From e179baaf252a92516762860483cd693a10d092c0 Mon Sep 17 00:00:00 2001 From: feldenr <135638674+feldenr@users.noreply.github.com> Date: Mon, 20 Jul 2026 23:11:16 +0200 Subject: [PATCH] feat(worldgen): v4.1 - latitude zones via density function + Lithosphere - Replace custom LatitudeBiomeSource/BiomeBand system with LatitudeSignalDensityFunction + LatitudeZonePlacement (mixin-based) - Add mandatory Lithosphere (mr_lithosphere) dependency + mixin config - Override overworld/large_biomes noise_settings for ultra-wide terrain - Rename remove_vanilla_ores -> z_remove_vanilla_ores (load order) - Merge cold/hot/tempered biome tags into latitude_*_surface tags - Rework OresCommand, OreBiomeFinderItem, ModConfigs for new system - Remove obsolete latitude classes, tests & world preset overrides - Bump mod_version 3.2 -> 4.1 --- CHANGELOG_4.0.md | 85 + CHANGELOG_4.1.md | 30 + CURSEFORGE_DESCRIPTION.md | 176 ++ gradle.properties | 2 +- .../customoregen/CustomOreGenMod.java | 3 +- .../mcreator/customoregen/OresCommand.java | 161 +- .../customoregen/config/ModConfigs.java | 27 + .../customoregen/item/OreBiomeFinderItem.java | 142 +- .../mixin/MultiNoiseBiomeSourceMixin.java | 91 + .../customoregen/worldgen/BiomeBand.java | 130 - .../worldgen/LatitudeBiomeSource.java | 356 --- .../customoregen/worldgen/LatitudeConfig.java | 57 + .../worldgen/LatitudeGameTest.java | 518 ---- .../worldgen/LatitudeMapCommand.java | 219 -- .../customoregen/worldgen/LatitudeMath.java | 133 - .../LatitudeSignalDensityFunction.java | 62 + .../worldgen/LatitudeSpawnHandler.java | 118 - .../worldgen/LatitudeZonePlacement.java | 77 + .../worldgen/OreAuditHandler.java | 134 - .../worldgen/WorldGenRegistration.java | 28 +- .../resources/META-INF/neoforge.mods.toml | 12 + src/main/resources/custom_ore_gen.mixins.json | 15 + .../biome_modifier/add_cold_biomes_ores.json | 40 +- .../biome_modifier/add_hot_biomes_ores.json | 56 +- .../add_mountain_biomes_ores.json | 24 +- .../biome_modifier/add_rare_biomes_ores.json | 24 +- .../add_shard_diamond_ores.json | 30 +- .../add_tempered_biomes_ores.json | 40 +- ...a_ores.json => z_remove_vanilla_ores.json} | 19 +- .../tags/worldgen/biome/cold_biomes.json | 68 - .../tags/worldgen/biome/hot_biomes.json | 106 - .../worldgen/biome/latitude_cold_surface.json | 18 +- .../worldgen/biome/latitude_hot_surface.json | 34 +- .../biome/latitude_temperate_surface.json | 60 +- .../tags/worldgen/biome/mountain_biomes.json | 3 - .../tags/worldgen/biome/rare_biomes.json | 1 - .../tags/worldgen/biome/tempered_biomes.json | 109 - .../concentratedcoalore.json | 2 +- .../configured_feature/copperhighore.json | 15 +- .../configured_feature/copperlowerore.json | 15 +- .../deepslatediamondore.json | 2 +- .../configured_feature/deepslateironore.json | 2 +- .../configured_feature/deepslatelapisore.json | 2 +- .../deepslatepuregoldenore.json | 2 +- .../deepslateredstoneore.json | 2 +- .../configured_feature/highemeraldore.json | 2 +- .../worldgen/configured_feature/ironore.json | 2 +- .../worldgen/configured_feature/lapisore.json | 2 +- .../configured_feature/loweremeraldore.json | 2 +- .../configured_feature/puregoldenore.json | 2 +- .../configured_feature/redstoneore.json | 2 +- .../density_function/latitude_signal.json | 3 + .../latitude_temperature.json | 22 + .../placed_feature/concentratedcoalore.json | 5 +- .../placed_feature/copperhighore.json | 3 +- .../placed_feature/copperlowerore.json | 3 +- .../placed_feature/deepslatediamondore.json | 5 +- .../placed_feature/deepslateironore.json | 3 +- .../placed_feature/deepslatelapisore.json | 3 +- .../deepslatepuregoldenore.json | 3 +- .../placed_feature/deepslateredstoneore.json | 3 +- .../worldgen/placed_feature/ironore.json | 3 +- .../worldgen/placed_feature/lapisore.json | 3 +- .../placed_feature/puregoldenore.json | 3 +- .../worldgen/placed_feature/redstoneore.json | 3 +- .../world_preset/ultra_wide_biome.json | 36 - .../tags/worldgen/world_preset/normal.json | 11 - .../worldgen/noise_settings/large_biomes.json | 2473 ++++++++++++++++ .../worldgen/noise_settings/overworld.json | 2535 +++++++++++++++++ .../customoregen/worldgen/BiomeBandTest.java | 196 -- .../worldgen/LatitudeMathTest.java | 315 -- 71 files changed, 6061 insertions(+), 2832 deletions(-) create mode 100644 CHANGELOG_4.0.md create mode 100644 CHANGELOG_4.1.md create mode 100644 CURSEFORGE_DESCRIPTION.md create mode 100644 src/main/java/net/mcreator/customoregen/mixin/MultiNoiseBiomeSourceMixin.java delete mode 100644 src/main/java/net/mcreator/customoregen/worldgen/BiomeBand.java delete mode 100644 src/main/java/net/mcreator/customoregen/worldgen/LatitudeBiomeSource.java create mode 100644 src/main/java/net/mcreator/customoregen/worldgen/LatitudeConfig.java delete mode 100644 src/main/java/net/mcreator/customoregen/worldgen/LatitudeGameTest.java delete mode 100644 src/main/java/net/mcreator/customoregen/worldgen/LatitudeMapCommand.java delete mode 100644 src/main/java/net/mcreator/customoregen/worldgen/LatitudeMath.java create mode 100644 src/main/java/net/mcreator/customoregen/worldgen/LatitudeSignalDensityFunction.java delete mode 100644 src/main/java/net/mcreator/customoregen/worldgen/LatitudeSpawnHandler.java create mode 100644 src/main/java/net/mcreator/customoregen/worldgen/LatitudeZonePlacement.java delete mode 100644 src/main/java/net/mcreator/customoregen/worldgen/OreAuditHandler.java create mode 100644 src/main/resources/custom_ore_gen.mixins.json rename src/main/resources/data/custom_ore_gen/neoforge/biome_modifier/{remove_vanilla_ores.json => z_remove_vanilla_ores.json} (85%) delete mode 100644 src/main/resources/data/custom_ore_gen/tags/worldgen/biome/cold_biomes.json delete mode 100644 src/main/resources/data/custom_ore_gen/tags/worldgen/biome/hot_biomes.json delete mode 100644 src/main/resources/data/custom_ore_gen/tags/worldgen/biome/tempered_biomes.json create mode 100644 src/main/resources/data/custom_ore_gen/worldgen/density_function/latitude_signal.json create mode 100644 src/main/resources/data/custom_ore_gen/worldgen/density_function/latitude_temperature.json delete mode 100644 src/main/resources/data/custom_ore_gen/worldgen/world_preset/ultra_wide_biome.json delete mode 100644 src/main/resources/data/minecraft/tags/worldgen/world_preset/normal.json create mode 100644 src/main/resources/data/minecraft/worldgen/noise_settings/large_biomes.json create mode 100644 src/main/resources/data/minecraft/worldgen/noise_settings/overworld.json delete mode 100644 src/test/java/net/mcreator/customoregen/worldgen/BiomeBandTest.java delete mode 100644 src/test/java/net/mcreator/customoregen/worldgen/LatitudeMathTest.java diff --git a/CHANGELOG_4.0.md b/CHANGELOG_4.0.md new file mode 100644 index 00000000..382e6da9 --- /dev/null +++ b/CHANGELOG_4.0.md @@ -0,0 +1,85 @@ +# Custom Ore Gen — 4.0 Changelog + +**Custom Ore Gen 4.0** is a full rewrite, rebuilt from the ground up for **NeoForge 1.21.1**. It drops KubeJS entirely, introduces a brand-new **latitude-based ore system**, ships custom **ultra-wide terrain** via the Lithosphere companion, and turns the **Deep Dark into a legendary northern feature**. + +This is the biggest update in the mod's history. Existing worlds from 2.x are **not** compatible — create a new world. + +--- + +## 🆕 New Features + +* **Latitude-based ore generation** — Ores are now distributed by your **Z coordinate** instead of biome categories. The world is split into three bands: + * ❄️ **Cold** (Z < −8000, north): Lapis, Deepslate Diamond + * 🔥 **Hot** (Z > 8000, south): Pure Gold, Redstone, Copper + * 🌳 **Temperate** (middle): Iron, Concentrated Coal + * Works with **any biome mod** out of the box — no per-biome classification needed. +* **Legendary Deep Dark** — The Deep Dark now only generates in cold northern latitudes, making it a true endgame destination rather than a random underground encounter. (Implemented via a safe, targeted mixin.) +* **Custom ultra-wide terrain** — Ships a handcrafted world generation through the new **Lithosphere** companion mod (now a required dependency). +* **Config-gated feature toggles** — A custom `ConfigGatedFeaturesModifier` makes the config feature toggles (`concentratedOres`, `impureOres`, `vanillaOreVariants`, etc.) actually gate world generation at runtime. +* **Global Loot Modifier for drops** — Replaced fragile event-based drops with a proper data-driven loot modifier (also fixed a crash with the Create drill). +* **Color-coded `/ores` command & Ore Biome Finder** — Output is now color-coded per zone (cold = aqua, hot = gold, temperate = green, shard ores = light purple) and clearly explains that the **Z coordinate** determines your zone. +* **Configurable zone thresholds** — The cold/hot thresholds (default Z = ±8000) are now adjustable in `custom-ore-gen-common.toml`. +* **Create & Mekanism compat** — Standalone-safe recipes for crushing, milling, mixing and enriching shard diamonds. + +--- + +## ⚙️ Changes + +* **Migrated from Forge 1.20.1 → NeoForge 1.21.1.** +* **Removed KubeJS dependency entirely.** Vanilla ores are now removed via NeoForge **biome modifiers** (`z_remove_vanilla_ores.json`) — no startup scripts, nothing to run. +* **New required dependency: Lithosphere 1.7+** — provides the custom terrain the mod is balanced for. +* Tool & armor stats are now **linked to config** — durability, speed, damage and armor values can all be tuned. +* Emeralds remain **biome-based** (mountain and rare-biome tags), since they're tied to terrain, not latitude. +* Rebalanced ore drop counts and XP to align with vanilla 1.21. +* Iron and Gold ores now **ignore Fortune** like vanilla. +* Paxel now affects every block mineable by pickaxe/shovel/axe tags. +* Rebalanced Diamond Shard tier as a clear bridge between iron and diamond. + +--- + +## 🐛 Bug Fixes + +* **Vanilla diamond leaked everywhere** — All **4** vanilla diamond placed features are now removed (`ore_diamond`, `ore_diamond_buried`, `ore_diamond_large`, `ore_diamond_medium`). Previously only 2 were removed, so buried/medium diamonds spawned in every biome. +* **Copper showed the wrong texture in deepslate** — Custom copper now uses the vanilla two-target approach (stone → `copper_ore`, deepslate → `deepslate_copper_ore`) instead of forcing `copper_ore` everywhere. +* **`/ores` always reported temperate** — `zoneName()` was reading static fields instead of the config getters; it now reads the live thresholds. +* **Garbage `6a9` prefix in ore listings** — Removed a broken color-code remnant that appeared in front of every ore name. +* **Diamond rate was way too high in cold zones** — Reduced the custom Deepslate Diamond `count` from 6 → 3 (combined with the vanilla leak fix, diamonds are now properly rare). +* **Server hung on startup** — Removed the `SpawnRelocator` and `OreAuditHandler` entirely. They forced synchronous chunk generation on the main server thread (a known cause of deadlocks and world corruption) and the audit handler shipped a `System.exit(0)` hard-kill. Both were dev-only diagnostics that never belonged in a release. +* **Badlands gold leaked into non-hot zones** — Added `ore_gold_extra` to the vanilla removal list. +* **Cross-climate tag leaks** — Removed copper/gold appearing in temperate spawns due to overlapping surface tags. +* **Caves piercing the surface** — Reverted the stretched terrain that caused cave openings to break the surface. +* **Create processing recipes** — Repaired and made them standalone-safe (no leftover references to removed ores). +* Various startup crashes, build errors and config-load race conditions resolved. + +--- + +## 🗑️ Removals + +* **KubeJS** — no longer used or required. +* Auto-generated `kubejs/startup_scripts/custom_ore_gen_remove_vanilla_ores.js` — replaced by biome modifiers. +* Dead config categories, unused `EnchantabilityFix` class, and redundant `tectonic`/custom noise settings. +* Legacy biome-tag surface files (`latitude_cold_surface`, `latitude_hot_surface`, `latitude_temperate_surface`, `cold_biomes`, `hot_biomes`, `tempered_biomes`, etc.) — superseded by the Z-based system. + +--- + +## 🧪 Technical / Internal + +* Mixed-in `MultiNoiseBiomeSource` to intercept Deep Dark biome resolution safely (Mojmap, no refmap needed on production). +* Custom `LatitudeZonePlacement` placement modifier filters ore placement by Z at the placed-feature level. +* Comprehensive test suite added: `OresCommandTest`, `ModConfigsTest`, `ConfigurableOreDropsProcedureTest`, `OreDropMathTest`, plus an automated GameTest server for latitude validation. +* Cleaned up block/item classes and migrated the entire test suite to NeoForge. + +--- + +## 📦 Requirements + +* Minecraft 1.21.1 +* NeoForge 21.1.x +* **Lithosphere 1.7+** (required) +* Biomes O' Plenty, Create, Mekanism (optional, recommended) + +--- + +> ⚠️ **Create a NEW world after updating.** Chunks generated before 4.0 keep their old ore distribution. + +**Happy mining!** 🌍⛏️✨ diff --git a/CHANGELOG_4.1.md b/CHANGELOG_4.1.md new file mode 100644 index 00000000..daf5cbbc --- /dev/null +++ b/CHANGELOG_4.1.md @@ -0,0 +1,30 @@ +# Custom Ore Gen — 4.1 + +A hotfix release that removes developer-only diagnostics that could destabilise dedicated servers. **No gameplay changes** — all ore generation, the Diamond Shard tier, the Deep Dark lock and mod compatibility are identical to 4.0. + +--- + +## 🐛 Bug Fixes + +* **Removed world/server-corrupting code** — Three developer-only diagnostic classes were accidentally shipped in 4.0. They have been removed entirely: + * `OreAuditHandler` — contained a `System.exit(0)` hard-kill that would terminate the server process, and forced chunk generation from a separate thread (a classic cause of chunk corruption). + * `SpawnRelocator` — forced synchronous chunk generation on the main server thread during startup, causing deadlocks and hang. + * `GenerationStabilityTest` — a GameTest utility that had no place in a release build. +* None of these classes were referenced by any gameplay code; removing them has **zero impact** on how the mod plays. + +--- + +## 🔄 Changes + +* Spawn-point behaviour reverts to vanilla (the removed `SpawnRelocator` no longer moves the spawn). Since the temperate band is 16,000 blocks wide, the vast majority of spawns still land in a balanced ore zone. + +--- + +## ✅ Verification + +* No `System.exit`, `Runtime.halt`, forced chunk loading (`getChunkAt`/`getChunk`), manual threads or `setBlock` calls remain anywhere in the codebase. +* Build and unit tests pass. + +--- + +**Full build:** Minecraft 1.21.1 · NeoForge 21.1.x · Lithosphere 1.7+ (required) diff --git a/CURSEFORGE_DESCRIPTION.md b/CURSEFORGE_DESCRIPTION.md new file mode 100644 index 00000000..6a605a00 --- /dev/null +++ b/CURSEFORGE_DESCRIPTION.md @@ -0,0 +1,176 @@ +# 🔧 Custom Ore Gen + +**Custom Ore Gen** completely overhauls Minecraft's ore generation by replacing vanilla distribution with a **latitude-based system** driven by the world's Z coordinate, and adds a complete intermediate equipment tier between iron and diamond: **Diamond Shards**. + +After months of reworking, **version 4.0** is a full rewrite — rebuilt from the ground up for **NeoForge 1.21.1**, dropping KubeJS entirely in favor of fully data-driven biome modifiers, and introducing a brand-new world of latitude exploration. + +*** + +## 🎯 Overview + +A mod that: + +* Replaces **all** vanilla overworld ore generation with a **latitude system** (north = cold, south = hot, middle = temperate) +* Adds a new intermediate equipment tier: **Diamond Shards** +* Encourages **north/south exploration** to gather specific resources +* Locks the **Deep Dark** to cold northern latitudes as a legendary feature +* The temperate band is **16,000 blocks wide** (Z = −8000 to +8000), so most spawns already land in a balanced area +* Ships custom **ultra-wide terrain** through its **Lithosphere** companion mod +* Automatically integrates with **Biomes O' Plenty**, **Create** and **Mekanism** + +*** + +## 🌍 Latitude-Based Ore Generation + +The world is split into three latitude bands running along the **Z axis**. Travel north or south to change which ores you can find — *your Z coordinate, not your biome, decides the ores* (Emeralds being the biome-tagged exception). + +| Zone | Direction | Ores | +| --- | --- | --- | +| ❄️ **Cold** | North (Z < -8000) | Lapis, Deepslate Diamond | +| 🔥 **Hot** | South (Z > 8000) | Pure Gold, Redstone, Copper | +| 🌳 **Temperate** | Middle (-8000 → 8000) | Iron, Concentrated Coal | +| ⛰️ **Mountain biomes** | Anywhere (by biome tag) | High Emerald | +| ✨ **Rare biomes** | Anywhere (by biome tag) | Lower Emerald | +| 🔷 **All zones** | Everywhere | Deepslate Shard Diamond, Shard Diamond Block | + +> ⚠️ **Note**: _Deepslate Shard Diamond Ore_ is the **only progression ore that spawns in ALL zones**, ensuring accessible early-game progression wherever you start. The temperate band is huge (16,000 blocks), so you almost always start in a balanced ore zone. + +🧭 Use the **Ore Biome Finder** item or the **`/ores`** command to see exactly which ores are available at your current Z coordinate — the output is **color-coded per zone** (cold = aqua, hot = gold, temperate = green, shard ores = light purple). + +*** + +## 💎 Diamond Shard Tier — New Progression + +A complete set of tools and armor that bridges the gap between iron and diamond. + +### ⚙️ **Available Equipment** + +| Type | Components | Durability | +| --- | --- | --- | +| **Tools** (Pickaxe, Axe, Shovel) | Diamond Shards | 450 | +| **Paxel** (3-in-1 tool) | Diamond Shards | 800 | +| **Full Armor Set** | Diamond Shards + 2 Diamonds | 17 protection, Toughness 1.0 | + +> ✅ **The Paxel** combines the functions of **pickaxe, axe, and shovel** into a single tool — affecting every block mineable by those tags. + +> 🛠️ All stats above are the **defaults** — every durability, speed and damage value, plus the cold/hot zone thresholds and ore drops, is configurable in `custom-ore-gen-common.toml`. + +### 🧪 **Shard → Diamond Conversion** + +9 Diamond Shards → 1 Diamond (3×3 crafting grid). + +### 🛡️ **Armor Recipes** + +* **Helmet**: 5 Diamond Shards +* **Chestplate**: 8 Diamond Shards + 1 Diamond +* **Leggings**: 7 Diamond Shards + 1 Diamond +* **Boots**: 4 Diamond Shards + +> ⚙️ **Repair** any Diamond Shard equipment with Diamond Shards on an anvil. + +*** + +## 🔍 Ore Biome Finder + +A handy tool to instantly know which ores are available at your current latitude. + +🎮 **Alternatives**: + +* Craft the **Ore Biome Finder** item (check JEI for the recipe). +* Use the **`/ores`** (or `/ore`) command — it shows your X/Z position, the zone determined by Z, the cold/hot thresholds, and a **color-coded** list of findable ores. + +*** + +## 📦 Installation & Dependencies + +### ⚠️ **Mandatory Requirements** + +* **Minecraft**: 1.21.1 +* **NeoForge**: 21.1.x +* **Lithosphere**: 1.7+ _(required — provides the custom ultra-wide terrain the mod is balanced for)_ + +### 🌐 **Optional but Recommended** + +* **Biomes O' Plenty** — ore generation automatically extends to all its biomes. +* **Create** — ore-processing compat (crushing/milling shard diamond ore, mixing shards → diamond). +* **Mekanism** — enriching compat for shard diamonds. + +> 🚫 The mod does **not** use KubeJS anymore. Vanilla ores are fully removed via NeoForge **biome modifiers** — no scripts, nothing to run. + +*** + +## 🎮 Gameplay & Progression + +1. **Initial Stage** + Start in the temperate band and mine **Deepslate Shard Diamond Ore** (available everywhere) to obtain **Diamond Shards**. + +2. **First Equipment** + Craft Diamond Shard tools (or the versatile Paxel) for better efficiency than iron. + +3. **Targeted Exploration** + Travel north or south along the Z axis to reach different ore zones: + * **North (Cold)**: Lapis and Deepslate Diamonds + * **South (Hot)**: Pure Gold, Redstone, Copper + * **Mountain biomes**: High Emeralds + * **Rare biomes**: Lower Emeralds + +4. **Final Progression** + Combine 9 Diamond Shards to create a regular Diamond and access vanilla diamond equipment. + +*** + +## 📊 Equipment Statistics Comparison + +| Material | Protection | Chestplate Durability | +| --- | --- | --- | +| Iron | 15 | 240 | +| **Diamond Shard** | **17** | **300** | +| Diamond | 20 | 528 | + +*** + +## 🌟 Key Features + +* 🗺️ **Latitude Exploration**: the Z coordinate — not the biome — decides your ores +* 🌌 **Legendary Deep Dark**: locked to cold northern latitudes only (via a safe mixin) +* 🚀 **Custom Ultra-Wide Terrain**: ships with Lithosphere for a fresher, wider world +* ⚔️ **Balanced Progression**: Diamond Shard tier bridges the iron–diamond gap +* 🚫 **No Vanilla Ores**: fully removed via data-driven biome modifiers (no scripts) +* 🌍 **Modpack Friendly**: automatic integration with any biome mod through the Z system +* 🎨 **Dedicated Creative Tab**: all mod items in the "Custom Ore Gen" tab +* 🛠️ **Versatile Tools**: the Paxel saves inventory space +* 📊 **In-game Info**: Finder item + `/ores` command with color-coded zones +* ⚙️ **Fully Configurable**: zone thresholds, tool stats, armor values and ore drops + +*** + +## 🆕 What's New in 4.0 + +Version 4.0 is a ground-up rebuild. Highlights: + +* **Full NeoForge 1.21.1 port** — left Forge 1.20.1 and KubeJS behind; everything is now data-driven biome modifiers. +* **Latitude ore system** — ores are now distributed by **Z coordinate** instead of biome categories, so it works with *any* biome mod out of the box. +* **Ultra-wide custom terrain** — bundled through the **Lithosphere** companion mod. +* **Legendary Deep Dark** — the Deep Dark now only generates in cold northern latitudes, making it a true endgame destination. +* **Create & Mekanism compat** — recipes for crushing, milling, mixing and enriching shard diamonds. +* **Color-coded `/ores` & Ore Finder** — clear, readable output that explains the Z mechanic. +* **Polished ore behaviour** — all 4 vanilla diamond features are properly removed, and copper now uses the correct deepslate texture underground. + +> 💡 Existing worlds from older versions are **not** compatible — create a **new world** after installing 4.0. + +*** + +## 📝 Important Notes + +* ⚠️ **Create a NEW world** after installing. Chunks generated before installation keep their old ore distribution. +* The cold/hot zone thresholds default to **Z = ±8000** but are fully adjustable in the config. +* Emeralds remain **biome-based** (mountain and rare-biome tags), not latitude-based. +* All Diamond Shard equipment can be repaired with Diamond Shards. + +*** + +### 🎯 **Why Choose Custom Ore Gen?** + +Because it brings **logic to exploration** (travel the world to find specific ores), **smoother progression** (a real iron-to-diamond bridge), and **seamless integration** with many modded biomes — all without tedious configuration. + +> **Happy mining!** 🌍⛏️✨ diff --git a/gradle.properties b/gradle.properties index f4746506..5909746b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ org.gradle.jvmargs=-Xmx4G org.gradle.daemon=true # Mod Properties -mod_version=3.2 +mod_version=4.1 mod_id=custom_ore_gen mod_name=Custom Ore Gen mod_group_id=com.aulyrius.custom_ore_gen diff --git a/src/main/java/net/mcreator/customoregen/CustomOreGenMod.java b/src/main/java/net/mcreator/customoregen/CustomOreGenMod.java index cbd075f0..28ad76ad 100644 --- a/src/main/java/net/mcreator/customoregen/CustomOreGenMod.java +++ b/src/main/java/net/mcreator/customoregen/CustomOreGenMod.java @@ -59,8 +59,9 @@ public class CustomOreGenMod { LOOT_MODIFIERS.register(modEventBus); // Start of user code block mod init - WorldGenRegistration.BIOME_SOURCES.register(modEventBus); WorldGenRegistration.BIOME_MODIFIER_SERIALIZERS.register(modEventBus); + WorldGenRegistration.DENSITY_FUNCTION_TYPES.register(modEventBus); + WorldGenRegistration.PLACEMENT_MODIFIERS.register(modEventBus); // End of user code block mod init } diff --git a/src/main/java/net/mcreator/customoregen/OresCommand.java b/src/main/java/net/mcreator/customoregen/OresCommand.java index 88d96d6c..8ff2ccc8 100644 --- a/src/main/java/net/mcreator/customoregen/OresCommand.java +++ b/src/main/java/net/mcreator/customoregen/OresCommand.java @@ -2,153 +2,104 @@ package net.mcreator.customoregen; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.context.CommandContext; +import net.minecraft.ChatFormatting; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; -import net.minecraft.core.registries.Registries; import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.tags.TagKey; -import net.minecraft.world.level.biome.Biome; import net.neoforged.neoforge.event.RegisterCommandsEvent; import net.neoforged.bus.api.SubscribeEvent; -import net.neoforged.fml.common.Mod; import net.neoforged.fml.common.EventBusSubscriber; import java.util.*; +import net.mcreator.customoregen.worldgen.LatitudeConfig; + @EventBusSubscriber(modid = CustomOreGenMod.MODID, bus = EventBusSubscriber.Bus.GAME) public class OresCommand { - // Tags personnalisés du mod - private static final TagKey COLD_BIOMES_TAG = TagKey.create(Registries.BIOME, - ResourceLocation.fromNamespaceAndPath("custom_ore_gen", "cold_biomes")); - private static final TagKey HOT_BIOMES_TAG = TagKey.create(Registries.BIOME, - ResourceLocation.fromNamespaceAndPath("custom_ore_gen", "hot_biomes")); - private static final TagKey MOUNTAIN_BIOMES_TAG = TagKey.create(Registries.BIOME, - ResourceLocation.fromNamespaceAndPath("custom_ore_gen", "mountain_biomes")); - private static final TagKey TEMPERED_BIOMES_TAG = TagKey.create(Registries.BIOME, - ResourceLocation.fromNamespaceAndPath("custom_ore_gen", "tempered_biomes")); - private static final TagKey RARE_BIOMES_TAG = TagKey.create(Registries.BIOME, - ResourceLocation.fromNamespaceAndPath("custom_ore_gen", "rare_biomes")); - - // Minerais par catégorie (mappé avec les biome modifiers) private static final List COLD_ORES = Arrays.asList( - "Lapis (stone) [Y: 0 à 32]", - "Lapis (deepslate) [Y: -64 à 0]", - "Diamant (deepslate) [Y: -64 à 0]"); + "Lapis (stone) [Y: 0 a 32]", + "Lapis (deepslate) [Y: -64 a 0]", + "Diamant (deepslate) [Y: -64 a 0]"); private static final List HOT_ORES = Arrays.asList( - "Or Pur (stone) [Y: 0 à 256]", - "Or Pur (deepslate) [Y: -64 à 0]", - "Redstone (stone) [Y: -10 à 20]", - "Redstone (deepslate) [Y: -80 à -30]", - "Cuivre (haut) [Y: 15 à 256]", - "Cuivre (bas) [Y: -64 à 0]"); + "Or (stone) [Y: 0 a 320]", + "Or (deepslate) [Y: -64 a 0]", + "Cuivre (haut) [Y: 15 a 320]", + "Cuivre (bas) [Y: -64 a 0]", + "Redstone (stone) [Y: -10 a 20]", + "Redstone (deepslate) [Y: -80 a -30]"); - private static final List MOUNTAIN_ORES = Arrays.asList( - "Emeraude (haute altitude) [Y: 0 à 64]"); - - private static final List TEMPERED_ORES = Arrays.asList( - "Charbon Concentre [Y: 0 à 70]", - "Fer (stone) [Y: 0 à 100]", - "Fer (deepslate) [Y: -64 à 0]"); - - private static final List RARE_ORES = Arrays.asList( - "Emeraude (basse altitude) [Y: -64 à 0]"); + private static final List TEMPERATE_ORES = Arrays.asList( + "Fer (stone) [Y: 0 a 100]", + "Fer (deepslate) [Y: -64 a 0]", + "Charbon concentre [Y: 0 a 70]"); private static final List EVERYWHERE_ORES = Arrays.asList( - "Diamant Shard (deepslate) [Y: -64 à -40]", - "Bloc Diamant Shard [Y: 0 à 15]"); + "Diamant Shard (deepslate) [Y: -64 a -40]", + "Bloc Diamant Shard [Y: 0 a 15]"); @SubscribeEvent public static void onRegisterCommands(RegisterCommandsEvent event) { - CommandDispatcher dispatcher = event.getDispatcher(); - - // Niveau de permission 2 = OP (Admin level) - dispatcher.register(Commands.literal("ores") + event.getDispatcher().register(Commands.literal("ores") .requires(source -> source.hasPermission(2)) .executes(OresCommand::executeOres)); - - dispatcher.register(Commands.literal("ore") + event.getDispatcher().register(Commands.literal("ore") .requires(source -> source.hasPermission(2)) .executes(OresCommand::executeOres)); } private static int executeOres(CommandContext context) { - if (!(context.getSource().getEntity() instanceof net.minecraft.world.entity.player.Player)) { - context.getSource() - .sendFailure(Component.literal("Cette commande ne peut etre utilisee que par un joueur")); + if (!(context.getSource().getEntity() instanceof net.minecraft.world.entity.player.Player player)) { + context.getSource().sendFailure(Component.literal("Cette commande ne peut etre utilisee que par un joueur")); return 0; } - net.minecraft.world.entity.player.Player player = (net.minecraft.world.entity.player.Player) context.getSource() - .getEntity(); - net.minecraft.world.level.Level level = player.level(); - net.minecraft.core.BlockPos pos = player.blockPosition(); + int x = player.blockPosition().getX(); + int z = player.blockPosition().getZ(); - var biomeHolder = level.getBiome(pos); - ResourceKey biomeKey = biomeHolder.unwrapKey() - .orElse(ResourceKey.create(Registries.BIOME, ResourceLocation.fromNamespaceAndPath("minecraft", "plains"))); - ResourceLocation biomeId = biomeKey.location(); - String biomeName = biomeId.getPath(); + String zone = LatitudeConfig.zoneName(z); + int coldZ = LatitudeConfig.getColdZoneZ(); + int hotZ = LatitudeConfig.getHotZoneZ(); + ChatFormatting zoneColor = zoneColor(zone); - context.getSource().sendSuccess(() -> Component.literal("=== Minerais dans: " + biomeName + " ==="), true); - context.getSource().sendSuccess(() -> Component.literal("Biome ID: " + biomeId), true); + context.getSource().sendSuccess(() -> Component.literal( + "=== Position: X=" + x + " Z=" + z + " ===").withStyle(ChatFormatting.GRAY), true); + context.getSource().sendSuccess(() -> Component.literal( + "Zone determinee par la coordonnee Z : " + zone).withStyle(zoneColor), true); + context.getSource().sendSuccess(() -> Component.literal( + "Z < " + coldZ + " = froid | " + coldZ + " a " + hotZ + " = tempere | Z > " + hotZ + " = chaud") + .withStyle(ChatFormatting.GRAY), true); - // Vérifier les tags personnalisés du mod - Set foundTags = new HashSet<>(); - List foundOres = new ArrayList<>(); - - // Vérifier chaque tag de biome et ajouter les minerais correspondants - if (isBiomeInTag(level, pos, COLD_BIOMES_TAG)) { - foundTags.add("cold_biomes"); - foundOres.addAll(COLD_ORES); - } - if (isBiomeInTag(level, pos, HOT_BIOMES_TAG)) { - foundTags.add("hot_biomes"); - foundOres.addAll(HOT_ORES); - } - if (isBiomeInTag(level, pos, MOUNTAIN_BIOMES_TAG)) { - foundTags.add("mountain_biomes"); - foundOres.addAll(MOUNTAIN_ORES); - } - if (isBiomeInTag(level, pos, TEMPERED_BIOMES_TAG)) { - foundTags.add("tempered_biomes"); - foundOres.addAll(TEMPERED_ORES); - } - if (isBiomeInTag(level, pos, RARE_BIOMES_TAG)) { - foundTags.add("rare_biomes"); - foundOres.addAll(RARE_ORES); + List zoneOres = new ArrayList<>(); + switch (zone) { + case "COLD" -> zoneOres.addAll(COLD_ORES); + case "HOT" -> zoneOres.addAll(HOT_ORES); + case "TEMPERATE" -> zoneOres.addAll(TEMPERATE_ORES); } - // Ajouter les minerais présents partout - foundOres.addAll(EVERYWHERE_ORES); + Set allOres = new LinkedHashSet<>(zoneOres); + allOres.addAll(EVERYWHERE_ORES); - // Afficher les tags trouvés - if (!foundTags.isEmpty()) { - context.getSource().sendSuccess(() -> Component.literal("Tags du mod: " + String.join(", ", foundTags)), - true); - } else { - context.getSource().sendSuccess(() -> Component.literal("Tags du mod: aucun"), true); + context.getSource().sendSuccess(() -> Component.literal( + "Minerais trouvables (" + allOres.size() + ") :").withStyle(ChatFormatting.WHITE), true); + for (String ore : zoneOres) { + context.getSource().sendSuccess(() -> Component.literal(" * " + ore).withStyle(zoneColor), true); } - - // Afficher les minerais (sans doublons) - if (!foundOres.isEmpty()) { - Set uniqueOres = new LinkedHashSet<>(foundOres); - context.getSource().sendSuccess(() -> Component.literal("Minerais trouvables:"), true); - for (String ore : uniqueOres) { - context.getSource().sendSuccess(() -> Component.literal(" * " + ore), true); - } - } else { - context.getSource().sendSuccess(() -> Component.literal("Aucun minerai specifique"), true); + for (String ore : EVERYWHERE_ORES) { + context.getSource().sendSuccess(() -> Component.literal(" * " + ore) + .withStyle(ChatFormatting.LIGHT_PURPLE), true); } return 1; } - private static boolean isBiomeInTag(net.minecraft.world.level.Level level, net.minecraft.core.BlockPos pos, - TagKey tag) { - return level.getBiome(pos).is(tag); + private static ChatFormatting zoneColor(String zone) { + return switch (zone) { + case "COLD" -> ChatFormatting.AQUA; + case "HOT" -> ChatFormatting.GOLD; + case "TEMPERATE" -> ChatFormatting.GREEN; + default -> ChatFormatting.WHITE; + }; } } diff --git a/src/main/java/net/mcreator/customoregen/config/ModConfigs.java b/src/main/java/net/mcreator/customoregen/config/ModConfigs.java index 60417ec3..78efda5d 100644 --- a/src/main/java/net/mcreator/customoregen/config/ModConfigs.java +++ b/src/main/java/net/mcreator/customoregen/config/ModConfigs.java @@ -16,6 +16,7 @@ public class ModConfigs { TOOL_STATS = new ToolStatsConfig(BUILDER); DROPS = new DropsConfig(BUILDER); FEATURES = new FeatureToggleConfig(BUILDER); + LATITUDE_ORE = new LatitudeOreConfig(BUILDER); BUILDER.pop(); SPEC = BUILDER.build(); @@ -318,4 +319,30 @@ public class ModConfigs { builder.pop(); } } + + // Configuration for the latitude ore distribution system + public static class LatitudeOreConfig { + public final ModConfigSpec.ConfigValue coldZoneZ; + public final ModConfigSpec.ConfigValue hotZoneZ; + + public LatitudeOreConfig(ModConfigSpec.Builder builder) { + builder.push("latitude_ore_zones"); + + coldZoneZ = builder + .comment("Z coordinate below which is the COLD ore zone (north). Default: -8000", + "Example: -8000 means Z < -8000 gets cold ores (lapis, diamond)", + "Changing this also shifts the temperature latitude scale.") + .defineInRange("coldZoneZ", -8000, -32000, 0); + + hotZoneZ = builder + .comment("Z coordinate above which is the HOT ore zone (south). Default: 8000", + "Example: 8000 means Z > 8000 gets hot ores (copper, redstone, gold)", + "Changing this also shifts the temperature latitude scale.") + .defineInRange("hotZoneZ", 8000, 0, 32000); + + builder.pop(); + } + } + + public static final LatitudeOreConfig LATITUDE_ORE; } diff --git a/src/main/java/net/mcreator/customoregen/item/OreBiomeFinderItem.java b/src/main/java/net/mcreator/customoregen/item/OreBiomeFinderItem.java index 4d670beb..59f0caa7 100644 --- a/src/main/java/net/mcreator/customoregen/item/OreBiomeFinderItem.java +++ b/src/main/java/net/mcreator/customoregen/item/OreBiomeFinderItem.java @@ -1,63 +1,41 @@ package net.mcreator.customoregen.item; -import net.minecraft.core.registries.Registries; +import net.minecraft.ChatFormatting; import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.tags.TagKey; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResultHolder; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.biome.Biome; import java.util.*; +import net.mcreator.customoregen.worldgen.LatitudeConfig; + public class OreBiomeFinderItem extends Item { - // Tags personnalisés du mod - private static final TagKey COLD_BIOMES_TAG = TagKey.create(Registries.BIOME, - ResourceLocation.fromNamespaceAndPath("custom_ore_gen", "cold_biomes")); - private static final TagKey HOT_BIOMES_TAG = TagKey.create(Registries.BIOME, - ResourceLocation.fromNamespaceAndPath("custom_ore_gen", "hot_biomes")); - private static final TagKey MOUNTAIN_BIOMES_TAG = TagKey.create(Registries.BIOME, - ResourceLocation.fromNamespaceAndPath("custom_ore_gen", "mountain_biomes")); - private static final TagKey TEMPERED_BIOMES_TAG = TagKey.create(Registries.BIOME, - ResourceLocation.fromNamespaceAndPath("custom_ore_gen", "tempered_biomes")); - private static final TagKey RARE_BIOMES_TAG = TagKey.create(Registries.BIOME, - ResourceLocation.fromNamespaceAndPath("custom_ore_gen", "rare_biomes")); - - // Minerais par catégorie private static final List COLD_ORES = Arrays.asList( - "Lapis (stone) [Y: 0 à 32]", - "Lapis (deepslate) [Y: -64 à 0]", - "Diamant (deepslate) [Y: -64 à 0]"); + "Lapis (stone) [Y: 0 a 32]", + "Lapis (deepslate) [Y: -64 a 0]", + "Diamant (deepslate) [Y: -64 a 0]"); private static final List HOT_ORES = Arrays.asList( - "Or Pur (stone) [Y: 0 à 256]", - "Or Pur (deepslate) [Y: -64 à 0]", - "Redstone (stone) [Y: -10 à 20]", - "Redstone (deepslate) [Y: -80 à -30]", - "Cuivre (haut) [Y: 15 à 256]", - "Cuivre (bas) [Y: -64 à 0]"); + "Or (stone) [Y: 0 a 320]", + "Or (deepslate) [Y: -64 a 0]", + "Cuivre (haut) [Y: 15 a 320]", + "Cuivre (bas) [Y: -64 a 0]", + "Redstone (stone) [Y: -10 a 20]", + "Redstone (deepslate) [Y: -80 a -30]"); - private static final List MOUNTAIN_ORES = Arrays.asList( - "Emeraude (haute altitude) [Y: 0 à 64]"); - - private static final List TEMPERED_ORES = Arrays.asList( - "Charbon Concentre [Y: 0 à 70]", - "Fer (stone) [Y: 0 à 100]", - "Fer (deepslate) [Y: -64 à 0]"); - - private static final List RARE_ORES = Arrays.asList( - "Emeraude (basse altitude) [Y: -64 à 0]"); + private static final List TEMPERATE_ORES = Arrays.asList( + "Fer (stone) [Y: 0 a 100]", + "Fer (deepslate) [Y: -64 a 0]", + "Charbon concentre [Y: 0 a 70]"); private static final List EVERYWHERE_ORES = Arrays.asList( - "Diamant Shard (deepslate) [Y: -64 à -40]", - "Bloc Diamant Shard [Y: 0 à 15]"); + "Diamant Shard (deepslate) [Y: -64 a -40]", + "Bloc Diamant Shard [Y: 0 a 15]"); public OreBiomeFinderItem() { super(new Item.Properties().stacksTo(1)); @@ -68,68 +46,52 @@ public class OreBiomeFinderItem extends Item { ItemStack stack = player.getItemInHand(hand); if (!level.isClientSide) { - BlockPos pos = player.blockPosition(); - var biomeHolder = level.getBiome(pos); - ResourceKey biomeKey = biomeHolder.unwrapKey() - .orElse(ResourceKey.create(Registries.BIOME, ResourceLocation.fromNamespaceAndPath("minecraft", "plains"))); - ResourceLocation biomeId = biomeKey.location(); - String biomeName = biomeId.getPath(); + int x = player.blockPosition().getX(); + int z = player.blockPosition().getZ(); - player.displayClientMessage(Component.literal("=== Minerais dans: " + biomeName + " ==="), false); - player.displayClientMessage(Component.literal("Biome ID: " + biomeId), false); + String zone = LatitudeConfig.zoneName(z); + int coldZ = LatitudeConfig.getColdZoneZ(); + int hotZ = LatitudeConfig.getHotZoneZ(); + ChatFormatting zoneColor = zoneColor(zone); - // Vérifier les tags personnalisés du mod - Set foundTags = new HashSet<>(); - List foundOres = new ArrayList<>(); + player.displayClientMessage(Component.literal( + "=== Position: X=" + x + " Z=" + z + " ===").withStyle(ChatFormatting.GRAY), false); + player.displayClientMessage(Component.literal( + "Zone determinee par la coordonnee Z : " + zone).withStyle(zoneColor), false); + player.displayClientMessage(Component.literal( + "Z < " + coldZ + " = froid | " + coldZ + " a " + hotZ + " = tempere | Z > " + hotZ + " = chaud") + .withStyle(ChatFormatting.GRAY), false); - // Vérifier chaque tag de biome et ajouter les minerais correspondants - if (isBiomeInTag(level, pos, COLD_BIOMES_TAG)) { - foundTags.add("cold_biomes"); - foundOres.addAll(COLD_ORES); - } - if (isBiomeInTag(level, pos, HOT_BIOMES_TAG)) { - foundTags.add("hot_biomes"); - foundOres.addAll(HOT_ORES); - } - if (isBiomeInTag(level, pos, MOUNTAIN_BIOMES_TAG)) { - foundTags.add("mountain_biomes"); - foundOres.addAll(MOUNTAIN_ORES); - } - if (isBiomeInTag(level, pos, TEMPERED_BIOMES_TAG)) { - foundTags.add("tempered_biomes"); - foundOres.addAll(TEMPERED_ORES); - } - if (isBiomeInTag(level, pos, RARE_BIOMES_TAG)) { - foundTags.add("rare_biomes"); - foundOres.addAll(RARE_ORES); + List zoneOres = new ArrayList<>(); + switch (zone) { + case "COLD" -> zoneOres.addAll(COLD_ORES); + case "HOT" -> zoneOres.addAll(HOT_ORES); + case "TEMPERATE" -> zoneOres.addAll(TEMPERATE_ORES); } - // Ajouter les minerais présents partout - foundOres.addAll(EVERYWHERE_ORES); + Set allOres = new LinkedHashSet<>(zoneOres); + allOres.addAll(EVERYWHERE_ORES); - // Afficher les tags trouvés - if (!foundTags.isEmpty()) { - player.displayClientMessage(Component.literal("Tags du mod: " + String.join(", ", foundTags)), false); - } else { - player.displayClientMessage(Component.literal("Tags du mod: aucun"), false); + player.displayClientMessage(Component.literal( + "Minerais trouvables (" + allOres.size() + ") :").withStyle(ChatFormatting.WHITE), false); + for (String ore : zoneOres) { + player.displayClientMessage(Component.literal(" * " + ore).withStyle(zoneColor), false); } - - // Afficher les minerais (sans doublons) - if (!foundOres.isEmpty()) { - Set uniqueOres = new LinkedHashSet<>(foundOres); - player.displayClientMessage(Component.literal("Minerais trouvables:"), false); - for (String ore : uniqueOres) { - player.displayClientMessage(Component.literal(" * " + ore), false); - } - } else { - player.displayClientMessage(Component.literal("Aucun minerai specifique"), false); + for (String ore : EVERYWHERE_ORES) { + player.displayClientMessage(Component.literal(" * " + ore) + .withStyle(ChatFormatting.LIGHT_PURPLE), false); } } return InteractionResultHolder.sidedSuccess(stack, level.isClientSide); } - private static boolean isBiomeInTag(Level level, BlockPos pos, TagKey tag) { - return level.getBiome(pos).is(tag); + private static ChatFormatting zoneColor(String zone) { + return switch (zone) { + case "COLD" -> ChatFormatting.AQUA; + case "HOT" -> ChatFormatting.GOLD; + case "TEMPERATE" -> ChatFormatting.GREEN; + default -> ChatFormatting.WHITE; + }; } } diff --git a/src/main/java/net/mcreator/customoregen/mixin/MultiNoiseBiomeSourceMixin.java b/src/main/java/net/mcreator/customoregen/mixin/MultiNoiseBiomeSourceMixin.java new file mode 100644 index 00000000..45593190 --- /dev/null +++ b/src/main/java/net/mcreator/customoregen/mixin/MultiNoiseBiomeSourceMixin.java @@ -0,0 +1,91 @@ +package net.mcreator.customoregen.mixin; + +import com.mojang.datafixers.util.Pair; +import net.minecraft.core.Holder; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.biome.Biomes; +import net.minecraft.world.level.biome.Climate; +import net.minecraft.world.level.biome.MultiNoiseBiomeSource; +import net.minecraft.world.level.biome.MultiNoiseBiomeSourceParameterList; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.Optional; + +/** + * Makes the Deep Dark a legendary northern-only feature. + * + *

Vanilla places Deep Dark based on depth alone, appearing everywhere underground. This mixin + * intercepts biome resolution: when vanilla selects Deep Dark outside cold latitudes + * (temperature > -0.3), it brute-force searches the parameter list for the best non-Deep-Dark + * biome using the same fitness function as vanilla (sum of squared parameter distances).

+ */ +@Mixin(MultiNoiseBiomeSource.class) +public abstract class MultiNoiseBiomeSourceMixin { + + @Shadow + @Final + private com.mojang.datafixers.util.Either>, Holder> parameters; + + @Inject(method = "getNoiseBiome(Lnet/minecraft/world/level/biome/Climate$TargetPoint;)Lnet/minecraft/core/Holder;", + at = @At("RETURN"), cancellable = true) + private void customoregen$latitudeDeepDarkLock(Climate.TargetPoint target, + CallbackInfoReturnable> cir) { + Holder original = cir.getReturnValue(); + if (original == null) return; + if (original.unwrapKey().orElse(null) != Biomes.DEEP_DARK) return; + + float temperature = Climate.unquantizeCoord(target.temperature()); + if (temperature <= -0.3f) return; // Cold zone — keep Deep Dark + + // Warm zone: brute-force search for best non-Deep-Dark biome + Climate.ParameterList> paramList = resolveParamList(); + if (paramList == null) return; + + Holder best = null; + long bestFitness = Long.MAX_VALUE; + for (Pair> entry : paramList.values()) { + if (entry.getSecond().unwrapKey().orElse(null) == Biomes.DEEP_DARK) continue; + long fitness = computeFitness(entry.getFirst(), target); + if (fitness < bestFitness) { + bestFitness = fitness; + best = entry.getSecond(); + } + } + if (best != null) { + cir.setReturnValue(best); + } + } + + /** + * Compute fitness using the same formula as Climate.ParameterPoint.fitness(): + * fitness = offset + sum of squared parameter distances for temperature, humidity, + * continentalness, erosion, depth, weirdness. + */ + private static long computeFitness(Climate.ParameterPoint params, Climate.TargetPoint target) { + long tempDist = params.temperature().distance(target.temperature()); + long humidDist = params.humidity().distance(target.humidity()); + long contDist = params.continentalness().distance(target.continentalness()); + long erosDist = params.erosion().distance(target.erosion()); + long depthDist = params.depth().distance(target.depth()); + long weirdDist = params.weirdness().distance(target.weirdness()); + + return params.offset() + + tempDist * tempDist + humidDist * humidDist + contDist * contDist + + erosDist * erosDist + depthDist * depthDist + weirdDist * weirdDist; + } + + private Climate.ParameterList> resolveParamList() { + Optional>> left = parameters.left(); + if (left.isPresent()) return left.get(); + Optional> right = parameters.right(); + if (right.isPresent() && right.get().isBound()) { + return right.get().value().parameters(); + } + return null; + } +} diff --git a/src/main/java/net/mcreator/customoregen/worldgen/BiomeBand.java b/src/main/java/net/mcreator/customoregen/worldgen/BiomeBand.java deleted file mode 100644 index 63be6e17..00000000 --- a/src/main/java/net/mcreator/customoregen/worldgen/BiomeBand.java +++ /dev/null @@ -1,130 +0,0 @@ -package net.mcreator.customoregen.worldgen; - -import net.minecraft.core.Holder; -import net.minecraft.core.HolderGetter; -import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.tags.TagKey; -import net.minecraft.core.registries.Registries; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.biome.Biomes; - -import java.util.ArrayList; -import java.util.List; - -/** - * Latitude climate bands used by {@link LatitudeBiomeSource}. - * - *

The world is split along the Z axis (latitude) into climate bands: - * the far north is frozen, the equator is temperate, and the far south is hot. - * Surface biomes are selected from dedicated climate tags (so optional mods such - * as Biomes O' Plenty are supported gracefully). Ocean and underground (cave) pools - * are vanilla-only and resolved eagerly because those biomes always exist.

- */ -public enum BiomeBand { - FROZEN(-1.0), - COLD(-0.5), - TEMPERATE(0.0), - WARM(0.5), - HOT(1.0); - - /** Mid-temperature of the band, in [-1.0, 1.0]. */ - public final double centerTemperature; - - BiomeBand(double centerTemperature) { - this.centerTemperature = centerTemperature; - } - - public static BiomeBand fromTemperature(double temperature) { - if (temperature <= -0.7) return FROZEN; - if (temperature <= -0.25) return COLD; - if (temperature < 0.25) return TEMPERATE; - if (temperature < 0.7) return WARM; - return HOT; - } - - /** Surface biome tag for this band (vanilla + optional Biomes O' Plenty). */ - public TagKey surfaceTag() { - switch (this) { - case FROZEN: - case COLD: - return tag("latitude_cold_surface"); - case TEMPERATE: - return tag("latitude_temperate_surface"); - case WARM: - case HOT: - return tag("latitude_hot_surface"); - default: - return tag("latitude_temperate_surface"); - } - } - - /** - * Vanilla surface biomes, used to declare {@code possibleBiomes} safely during worldgen - * data loading. The full (mod-aware) surface pool is resolved lazily from {@link #surfaceTag()}. - */ - public List> surfaceVanilla() { - switch (this) { - case FROZEN: - return List.of( - Biomes.SNOWY_PLAINS, Biomes.ICE_SPIKES, Biomes.SNOWY_TAIGA, - Biomes.GROVE, Biomes.SNOWY_SLOPES, Biomes.JAGGED_PEAKS, Biomes.FROZEN_PEAKS - ); - case COLD: - return List.of( - Biomes.TAIGA, Biomes.OLD_GROWTH_PINE_TAIGA, Biomes.OLD_GROWTH_SPRUCE_TAIGA, - Biomes.WINDSWEPT_HILLS, Biomes.WINDSWEPT_FOREST, Biomes.WINDSWEPT_GRAVELLY_HILLS, - Biomes.GROVE, Biomes.SNOWY_SLOPES - ); - case TEMPERATE: - return List.of( - Biomes.PLAINS, Biomes.SUNFLOWER_PLAINS, Biomes.FOREST, Biomes.BIRCH_FOREST, - Biomes.OLD_GROWTH_BIRCH_FOREST, Biomes.DARK_FOREST, Biomes.FLOWER_FOREST, - Biomes.SWAMP, Biomes.MEADOW, Biomes.CHERRY_GROVE - ); - case WARM: - return List.of( - Biomes.SAVANNA, Biomes.SAVANNA_PLATEAU, Biomes.WINDSWEPT_SAVANNA, - Biomes.BIRCH_FOREST, Biomes.FOREST, Biomes.PLAINS, Biomes.MEADOW - ); - case HOT: - return List.of( - Biomes.DESERT, Biomes.BADLANDS, Biomes.WOODED_BADLANDS, Biomes.ERODED_BADLANDS, - Biomes.SAVANNA, Biomes.JUNGLE, Biomes.SPARSE_JUNGLE, Biomes.BAMBOO_JUNGLE, - Biomes.MANGROVE_SWAMP - ); - default: - return List.of(Biomes.PLAINS); - } - } - - public List> ocean() { - switch (this) { - case FROZEN: - return List.of(Biomes.FROZEN_OCEAN, Biomes.DEEP_FROZEN_OCEAN, Biomes.FROZEN_RIVER); - case COLD: - return List.of(Biomes.COLD_OCEAN, Biomes.DEEP_COLD_OCEAN); - case TEMPERATE: - return List.of(Biomes.OCEAN, Biomes.DEEP_OCEAN, Biomes.RIVER); - case WARM: - return List.of(Biomes.LUKEWARM_OCEAN, Biomes.DEEP_LUKEWARM_OCEAN); - case HOT: - return List.of(Biomes.WARM_OCEAN); - default: - return List.of(Biomes.OCEAN); - } - } - - /** Resolve a list of (possibly absent) biome keys into actual holders, skipping missing ones. */ - public static List> resolve(HolderGetter getter, List> keys) { - List> holders = new ArrayList<>(); - for (ResourceKey key : keys) { - getter.get(key).ifPresent(holders::add); - } - return holders; - } - - private static TagKey tag(String name) { - return TagKey.create(Registries.BIOME, ResourceLocation.fromNamespaceAndPath("custom_ore_gen", name)); - } -} diff --git a/src/main/java/net/mcreator/customoregen/worldgen/LatitudeBiomeSource.java b/src/main/java/net/mcreator/customoregen/worldgen/LatitudeBiomeSource.java deleted file mode 100644 index a119c1ce..00000000 --- a/src/main/java/net/mcreator/customoregen/worldgen/LatitudeBiomeSource.java +++ /dev/null @@ -1,356 +0,0 @@ -package net.mcreator.customoregen.worldgen; - -import com.mojang.serialization.Codec; -import com.mojang.serialization.MapCodec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import net.minecraft.core.Holder; -import net.minecraft.core.HolderGetter; -import net.minecraft.core.HolderSet; -import net.minecraft.core.registries.Registries; -import net.minecraft.resources.RegistryOps; -import net.minecraft.util.RandomSource; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.biome.BiomeSource; -import net.minecraft.world.level.biome.Biomes; -import net.minecraft.world.level.biome.Climate; -import net.minecraft.world.level.levelgen.synth.ImprovedNoise; - -import java.util.ArrayList; -import java.util.EnumMap; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Stream; - -/** - * Custom {@link BiomeSource} that distributes biomes by latitude (Z axis). - * - *
    - *
  • Far north (large negative Z) = frozen / cold biomes
  • - *
  • Equator (Z ≈ 0) = temperate biomes
  • - *
  • Far south (large positive Z) = hot biomes
  • - *
- * - *

Temperature is derived from the Z coordinate with a gentle boundary perturbation so the - * climate bands are not perfectly straight lines. Inside each band, a very low-frequency - * selector noise picks among the band's biomes, producing extremely large biomes that - * encourage exploration and long-distance travel (railways, roads, nether hubs).

- * - *

Underground philosophy: the surface latitude biome extends downward by default, so - * mining under a desert feels like being in the desert. Cave biomes (lush / dripstone) only - * appear as rare climatic pockets in the mid underground, and the Deep Dark is a legendary - * (~1%) feature of the deep zone. This keeps the latitude logic coherent at every depth - * instead of overriding it with a uniform cave-biome slab.

- * - *

Surface biomes come from dedicated climate tags (see {@code data/custom_ore_gen/tags/ - * worldgen/biome/latitude_*_surface.json}), which support optional Biomes O' Plenty biomes - * via {@code "required": false} without ever creating unbound holders. Ocean pools are - * vanilla-only.

- */ -public class LatitudeBiomeSource extends BiomeSource { - - public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( - Codec.LONG.fieldOf("seed").forGetter(src -> src.seed), - RegistryOps.retrieveGetter(Registries.BIOME) - ).apply(instance, instance.stable(LatitudeBiomeSource::new))); - - // ------------------------------------------------------------------ - // Surface / climate tunables - // ------------------------------------------------------------------ - - /** Number of blocks for the temperature to go from 0 (equator) to +-1 (pole). */ - private static final double TEMPERATURE_SCALE = LatitudeMath.TEMPERATURE_SCALE; - - /** Noise frequency for the climate band boundary wobble. */ - private static final double BOUNDARY_NOISE_SCALE = LatitudeMath.BOUNDARY_NOISE_SCALE; - - /** Amplitude of the boundary wobble (in temperature units). */ - private static final double BOUNDARY_NOISE_AMPLITUDE = LatitudeMath.BOUNDARY_NOISE_AMPLITUDE; - - /** Selector noise frequency for surface sub-biomes (very low = very large biomes). */ - private static final double SURFACE_SELECTOR_SCALE = LatitudeMath.SURFACE_SELECTOR_SCALE; - - /** Frequency of the land/ocean mask noise. */ - private static final double OCEAN_NOISE_SCALE = LatitudeMath.OCEAN_NOISE_SCALE; - - /** Above this ocean-noise value, the column is ocean. */ - private static final double OCEAN_THRESHOLD = LatitudeMath.OCEAN_THRESHOLD; - - /** Frequency of the moisture noise that carves rare swamp/mangrove pockets. */ - private static final double MOISTURE_SCALE = LatitudeMath.MOISTURE_SCALE; - - /** Above this moisture value a wet biome (swamp/mangrove) overrides the surface. ~8% of land. */ - private static final double MOISTURE_THRESHOLD = LatitudeMath.MOISTURE_THRESHOLD; - - // ------------------------------------------------------------------ - // Underground tunables (3-zone model) - // ------------------------------------------------------------------ - - /** Top of the deep zone (Y < this = deep underground). Deep Dark can live here. */ - private static final int DEEP_ZONE_TOP = LatitudeMath.DEEP_ZONE_TOP; - - /** Top of the mid-cave zone (DEEP_ZONE_TOP ≤ Y < this = mid caves, lush/dripstone pockets). */ - private static final int MID_CAVE_TOP = LatitudeMath.MID_CAVE_TOP; - - /** Frequency of the mid-cave pocket noise (lush/dripstone). */ - private static final double CAVE_SCALE = LatitudeMath.CAVE_SCALE; - - /** Above this value a lush/dripstone pocket overrides the surface biome. ~5-8% of the mid zone. */ - private static final double CAVE_THRESHOLD = LatitudeMath.CAVE_THRESHOLD; - - /** Frequency of the Deep Dark noise (very low = large, rare regions). */ - private static final double DEEP_DARK_SCALE = LatitudeMath.DEEP_DARK_SCALE; - - /** Vertical frequency of the Deep Dark noise (keeps it coherent in tall sections). */ - private static final double DEEP_DARK_SCALE_Y = LatitudeMath.DEEP_DARK_SCALE_Y; - - /** Above this value the Deep Dark overrides. Tuned for ~1-2% of the deep zone (legendary). */ - private static final double DEEP_DARK_THRESHOLD = LatitudeMath.DEEP_DARK_THRESHOLD; - - // ------------------------------------------------------------------ - // Spawn safe zone - // ------------------------------------------------------------------ - - /** Half-size of the guaranteed safe spawn square around the origin (plains/forest). */ - private static final int SPAWN_SAFE_RADIUS = LatitudeMath.SPAWN_SAFE_RADIUS; - - /** Selector frequency inside the spawn safe zone (finer, for gentle variety). */ - private static final double SPAWN_SELECTOR_SCALE = LatitudeMath.SPAWN_SELECTOR_SCALE; - - // ------------------------------------------------------------------ - // Fields - // ------------------------------------------------------------------ - - private final long seed; - private final HolderGetter biomeGetter; - - private final ImprovedNoise boundaryNoise; - private final ImprovedNoise selectorNoise; - private final ImprovedNoise oceanNoise; - private final ImprovedNoise moistureNoise; - private final ImprovedNoise caveNoise; - private final ImprovedNoise deepDarkNoise; - - /** Vanilla-only pools resolved eagerly (safe: vanilla biomes always exist and are bound). */ - private final EnumMap resolvedVanilla; - private final Set> possibleBiomes; - private final Holder fallback; - - /** Safe spawn pool (plains / forests) resolved eagerly. Always near the origin. */ - private final List> spawnSafeBiomes; - - /** Rare wet biomes (swamp = temperate, mangrove = warm/hot), placed by moisture noise. */ - private final Holder swampBiome; - private final Holder mangroveBiome; - - /** Cave biomes resolved eagerly (vanilla, always present). Lush = humid bands, Dripstone = dry bands. */ - private final Holder lushCavesBiome; - private final Holder dripstoneCavesBiome; - private final Holder deepDarkBiome; - - /** Mod-aware surface pools resolved lazily from climate tags (safe: tags are bound by then). */ - private volatile EnumMap>> surfaceFromTag; - - public LatitudeBiomeSource(long seed, HolderGetter biomeGetter) { - this.seed = seed; - this.biomeGetter = biomeGetter; - - RandomSource rng = RandomSource.create(seed); - this.boundaryNoise = new ImprovedNoise(rng); - this.selectorNoise = new ImprovedNoise(RandomSource.create(seed ^ 0x4C415449L)); - this.oceanNoise = new ImprovedNoise(RandomSource.create(seed ^ 0x4F434541L)); - this.moistureNoise = new ImprovedNoise(RandomSource.create(seed ^ 0x57455421L)); - this.caveNoise = new ImprovedNoise(RandomSource.create(seed ^ 0x43415645L)); - this.deepDarkNoise = new ImprovedNoise(RandomSource.create(seed ^ 0x44454550L)); - - this.resolvedVanilla = new EnumMap<>(BiomeBand.class); - Set> all = new HashSet<>(); - for (BiomeBand band : BiomeBand.values()) { - List> surface = BiomeBand.resolve(biomeGetter, band.surfaceVanilla()); - List> ocean = BiomeBand.resolve(biomeGetter, band.ocean()); - - resolvedVanilla.put(band, new ResolvedBand(surface, ocean)); - all.addAll(surface); - all.addAll(ocean); - } - - // Cave biomes (vanilla) declared so the source advertises them as possible. - this.lushCavesBiome = resolveAndAdd(biomeGetter, Biomes.LUSH_CAVES, all); - this.dripstoneCavesBiome = resolveAndAdd(biomeGetter, Biomes.DRIPSTONE_CAVES, all); - this.deepDarkBiome = resolveAndAdd(biomeGetter, Biomes.DEEP_DARK, all); - - this.possibleBiomes = all; - - List> safe = new ArrayList<>(); - safe.addAll(BiomeBand.resolve(biomeGetter, List.of( - Biomes.PLAINS, Biomes.SUNFLOWER_PLAINS, - Biomes.FOREST, Biomes.BIRCH_FOREST, Biomes.FLOWER_FOREST, - Biomes.MEADOW - ))); - this.spawnSafeBiomes = safe.isEmpty() ? null : safe; - - this.swampBiome = biomeGetter.get(Biomes.SWAMP).orElse(null); - this.mangroveBiome = biomeGetter.get(Biomes.MANGROVE_SWAMP).orElse(null); - - Holder plains = biomeGetter.get(Biomes.PLAINS).orElse(null); - this.fallback = plains != null ? plains : (possibleBiomes.isEmpty() ? null : possibleBiomes.iterator().next()); - } - - private static Holder resolveAndAdd(HolderGetter getter, net.minecraft.resources.ResourceKey key, Set> into) { - Holder holder = getter.get(key).orElse(null); - if (holder != null) { - into.add(holder); - } - return holder; - } - - @Override - protected MapCodec codec() { - return CODEC; - } - - @Override - protected Stream> collectPossibleBiomes() { - return possibleBiomes.stream(); - } - - @Override - public Holder getNoiseBiome(int quartX, int quartY, int quartZ, Climate.Sampler sampler) { - int blockX = quartX * 4; - int blockZ = quartZ * 4; - int blockY = quartY * 4; - - double latitudeTemp = blockZ / TEMPERATURE_SCALE; - double wobble = boundaryNoise.noise(blockX * BOUNDARY_NOISE_SCALE, 0.0, blockZ * BOUNDARY_NOISE_SCALE) * BOUNDARY_NOISE_AMPLITUDE; - double temperature = clamp(latitudeTemp + wobble, -1.0, 1.0); - - BiomeBand band = BiomeBand.fromTemperature(temperature); - ResolvedBand pool = resolvedVanilla.get(band); - if (pool == null) { - pool = resolvedVanilla.get(BiomeBand.TEMPERATE); - } - - // Guaranteed safe spawn zone (open, buildable biomes) around the origin. - if (spawnSafeBiomes != null && LatitudeMath.isInSpawnSafeZone(blockX, blockZ)) { - return pickBiome(spawnSafeBiomes, blockX, blockZ, SPAWN_SELECTOR_SCALE); - } - - // Determine the column's base biome: ocean mask, rare wet pocket, or latitude surface biome. - Holder base = baseSurfaceBiome(band, pool, blockX, blockZ); - - // Underground cave overrides (3-zone model) extend latitude rather than replace it. - return applyCaveOverrides(base, band, blockX, blockY, blockZ); - } - - /** Resolve the surface biome for a column: ocean, swamp/mangrove pocket, or the band's surface tag. */ - private Holder baseSurfaceBiome(BiomeBand band, ResolvedBand pool, int blockX, int blockZ) { - double oceanValue = oceanNoise.noise(blockX * OCEAN_NOISE_SCALE, 0.0, blockZ * OCEAN_NOISE_SCALE); - if (oceanValue > OCEAN_THRESHOLD && !pool.ocean().isEmpty()) { - return pickBiome(pool.ocean(), blockX, blockZ, 0.002); - } - - double moisture = moistureNoise.noise(blockX * MOISTURE_SCALE, 0.0, blockZ * MOISTURE_SCALE); - if (moisture > MOISTURE_THRESHOLD) { - if (band == BiomeBand.TEMPERATE && swampBiome != null) { - return swampBiome; - } - if ((band == BiomeBand.WARM || band == BiomeBand.HOT) && mangroveBiome != null) { - return mangroveBiome; - } - } - - List> surface = resolveSurfaceTag(band); - if (surface == null || surface.isEmpty()) { - surface = pool.surface(); - if (surface.isEmpty()) { - surface = resolvedVanilla.get(BiomeBand.TEMPERATE).surface(); - } - } - return pickBiome(surface, blockX, blockZ, SURFACE_SELECTOR_SCALE); - } - - /** - * Underground overrides keep the latitude biome by default and only carve rare cave features: - *
    - *
  • Deep zone (Y < {@value #DEEP_ZONE_TOP}): legendary Deep Dark pockets (~1%), else surface biome.
  • - *
  • Mid caves (DEEP_ZONE_TOP ≤ Y < {@value #MID_CAVE_TOP}): lush/dripstone pockets (~8%) matching the climate.
  • - *
  • Near surface: no override, latitude biome as-is.
  • - *
- */ - private Holder applyCaveOverrides(Holder surfaceBiome, BiomeBand band, int blockX, int blockY, int blockZ) { - LatitudeMath.Zone zone = LatitudeMath.zoneForY(blockY); - // Deep zone: legendary Deep Dark. - if (zone == LatitudeMath.Zone.DEEP) { - if (deepDarkBiome != null) { - double dd = deepDarkNoise.noise(blockX * DEEP_DARK_SCALE, blockY * DEEP_DARK_SCALE_Y, blockZ * DEEP_DARK_SCALE); - if (LatitudeMath.isDeepDarkPocket(dd)) { - return deepDarkBiome; - } - } - return surfaceBiome; - } - - // Mid caves: rare lush/dripstone pockets by climate. - if (zone == LatitudeMath.Zone.MID_CAVE) { - Holder caveBiome = caveBiomeFor(band); - if (caveBiome != null) { - double cave = caveNoise.noise(blockX * CAVE_SCALE, 0.0, blockZ * CAVE_SCALE); - if (LatitudeMath.isMidCavePocket(cave)) { - return caveBiome; - } - } - } - - return surfaceBiome; - } - - /** Lush caves for humid/warm bands, dripstone for dry/cold bands. */ - private Holder caveBiomeFor(BiomeBand band) { - if (band == BiomeBand.FROZEN || band == BiomeBand.COLD) { - return dripstoneCavesBiome; - } - return lushCavesBiome; - } - - /** Lazily resolve surface biomes from climate tags. Tags are bound after the registry freezes, - * so this is safe and never creates unbound holders. */ - private List> resolveSurfaceTag(BiomeBand band) { - EnumMap>> cache = surfaceFromTag; - if (cache != null) { - return cache.get(band); - } - synchronized (this) { - if (surfaceFromTag == null) { - EnumMap>> built = new EnumMap<>(BiomeBand.class); - for (BiomeBand b : BiomeBand.values()) { - List> holders = new ArrayList<>(); - biomeGetter.get(b.surfaceTag()).map(HolderSet::stream).ifPresent(stream -> stream.forEach(holders::add)); - built.put(b, holders); - } - surfaceFromTag = built; - } - return surfaceFromTag.get(band); - } - } - - private Holder pickBiome(List> biomes, int blockX, int blockZ, double scale) { - if (biomes == null || biomes.isEmpty()) { - return fallback; - } - // Dual-octave noise for a flatter, near-uniform index distribution: a single ImprovedNoise - // value is bell-curved around 0, which makes the middle of the biome list dominate. Adding a - // second octave at an offset flattens the curve so no biome is disproportionately common. - double n1 = selectorNoise.noise(blockX * scale, blockZ * scale, 1000.0); - double n2 = selectorNoise.noise(blockX * scale * 1.9 + 137.0, blockZ * scale * 1.9 - 211.0, 2000.0); - double normalized = LatitudeMath.normalisedSelector(n1, n2); - int idx = LatitudeMath.selectorIndex(normalized, biomes.size()); - return biomes.get(idx); - } - - private static double clamp(double value, double min, double max) { - return value < min ? min : (value > max ? max : value); - } - - private record ResolvedBand(List> surface, List> ocean) { - } -} diff --git a/src/main/java/net/mcreator/customoregen/worldgen/LatitudeConfig.java b/src/main/java/net/mcreator/customoregen/worldgen/LatitudeConfig.java new file mode 100644 index 00000000..dacbe6b7 --- /dev/null +++ b/src/main/java/net/mcreator/customoregen/worldgen/LatitudeConfig.java @@ -0,0 +1,57 @@ +package net.mcreator.customoregen.worldgen; + +import net.mcreator.customoregen.config.ModConfigs; + +/** + * Runtime accessor for the latitude zone thresholds. + * + *

These values come from the mod's config file and control both the ore distribution (which Z + * coordinates get which ores) and the temperature latitude scale. Changing them at runtime (via + * the config file) shifts both the ore zones and the climate bands simultaneously.

+ * + *

Defaults: + *

    + *
  • {@code coldZoneZ = -8000}: north of Z=-8000 is the cold zone
  • + *
  • {@code hotZoneZ = 8000}: south of Z=8000 is the hot zone
  • + *
  • Between -8000 and 8000 is the temperate zone (16,000 blocks wide)
  • + *
+ *

+ */ +public final class LatitudeConfig { + + private LatitudeConfig() {} + + private static int coldZoneZ = -8000; + private static int hotZoneZ = 8000; + + /** Z threshold below which is the cold zone. Negative = north. */ + public static int getColdZoneZ() { + try { + return net.mcreator.customoregen.config.ModConfigs.LATITUDE_ORE.coldZoneZ.get(); + } catch (Exception e) { + return coldZoneZ; + } + } + + /** Z threshold above which is the hot zone. Positive = south. */ + public static int getHotZoneZ() { + try { + return net.mcreator.customoregen.config.ModConfigs.LATITUDE_ORE.hotZoneZ.get(); + } catch (Exception e) { + return hotZoneZ; + } + } + + /** Called from the config load to update thresholds. */ + public static void update(int coldZ, int hotZ) { + coldZoneZ = coldZ; + hotZoneZ = hotZ; + } + + /** Returns a human-readable description of the zone for a given Z. */ + public static String zoneName(int z) { + if (z < getColdZoneZ()) return "COLD"; + if (z > getHotZoneZ()) return "HOT"; + return "TEMPERATE"; + } +} diff --git a/src/main/java/net/mcreator/customoregen/worldgen/LatitudeGameTest.java b/src/main/java/net/mcreator/customoregen/worldgen/LatitudeGameTest.java deleted file mode 100644 index 520ecbb4..00000000 --- a/src/main/java/net/mcreator/customoregen/worldgen/LatitudeGameTest.java +++ /dev/null @@ -1,518 +0,0 @@ -package net.mcreator.customoregen.worldgen; - -import net.mcreator.customoregen.CustomOreGenMod; -import net.mcreator.customoregen.config.ConfigHelper; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Holder; -import net.minecraft.core.HolderGetter; -import net.minecraft.core.registries.Registries; -import net.minecraft.gametest.framework.GameTest; -import net.minecraft.gametest.framework.GameTestHelper; -import net.minecraft.resources.ResourceKey; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.biome.Biomes; -import net.neoforged.neoforge.gametest.GameTestHolder; -import net.neoforged.neoforge.gametest.PrefixGameTestTemplate; - -import javax.imageio.ImageIO; -import java.awt.image.BufferedImage; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.EnumMap; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Automated world-map validation for the latitude biome system, run as a NeoForge - * {@link GameTest} so it executes inside a real game server with the full biome registry. - * - *

Launch with {@code ./gradlew runGameTestServer}. The test samples a large grid through a - * freshly built {@link LatitudeBiomeSource} at several depths and renders one PNG map per depth - * (a "geological slice" view), writes a distribution report and asserts the climate + cave - * invariants. No manual in-game testing required.

- */ -@GameTestHolder(CustomOreGenMod.MODID) -@PrefixGameTestTemplate(false) -public class LatitudeGameTest { - - private static final int RADIUS = 16000; // covers equator -> pole - private static final int STEP = 80; // ~400x400 samples - private static final long SEED = 0L; - private static final Path OUT_DIR = Path.of("gametest-results", "latitude"); - - // Sampling depths (one PNG per depth = a top-down "slice"). - private static final int SURFACE_Y = 64; - private static final int MID_CAVE_Y = -15; // -30 <= Y < 0 (lush/dripstone pockets) - private static final int DEEP_Y = -50; // Y < -30 (legendary Deep Dark) - - private static final Map, Integer> COLORS = new HashMap<>(); - - static { - col(0xB6E388, Biomes.PLAINS, Biomes.SUNFLOWER_PLAINS, Biomes.FOREST, Biomes.BIRCH_FOREST, - Biomes.FLOWER_FOREST, Biomes.MEADOW, Biomes.CHERRY_GROVE); - col(0xC8E6FF, Biomes.SNOWY_PLAINS, Biomes.ICE_SPIKES, Biomes.SNOWY_TAIGA, Biomes.GROVE, - Biomes.SNOWY_SLOPES, Biomes.JAGGED_PEAKS, Biomes.FROZEN_PEAKS, Biomes.FROZEN_OCEAN, - Biomes.DEEP_FROZEN_OCEAN, Biomes.FROZEN_RIVER); - col(0x8FB8D6, Biomes.TAIGA, Biomes.OLD_GROWTH_PINE_TAIGA, Biomes.OLD_GROWTH_SPRUCE_TAIGA, - Biomes.WINDSWEPT_HILLS, Biomes.WINDSWEPT_FOREST, Biomes.WINDSWEPT_GRAVELLY_HILLS, - Biomes.COLD_OCEAN, Biomes.DEEP_COLD_OCEAN); - col(0x7CC576, Biomes.DARK_FOREST, Biomes.OLD_GROWTH_BIRCH_FOREST, Biomes.RIVER, - Biomes.OCEAN, Biomes.DEEP_OCEAN); - col(0xE0C068, Biomes.SAVANNA, Biomes.SAVANNA_PLATEAU, Biomes.WINDSWEPT_SAVANNA, - Biomes.LUKEWARM_OCEAN, Biomes.DEEP_LUKEWARM_OCEAN); - col(0xE0884C, Biomes.DESERT, Biomes.BADLANDS, Biomes.WOODED_BADLANDS, Biomes.ERODED_BADLANDS, - Biomes.JUNGLE, Biomes.SPARSE_JUNGLE, Biomes.BAMBOO_JUNGLE, Biomes.WARM_OCEAN); - col(0x5B7A3A, Biomes.SWAMP); - col(0x3A5A3A, Biomes.MANGROVE_SWAMP); - // Cave biomes - distinct colors so the slices are readable. - col(0x4DB05A, Biomes.LUSH_CAVES); // lush green - col(0xC8782C, Biomes.DRIPSTONE_CAVES); // stalactite orange-brown - col(0x0A4D54, Biomes.DEEP_DARK); // dark sculk teal - } - - private static void col(int rgb, ResourceKey... keys) { - for (ResourceKey k : keys) COLORS.put(k, rgb); - } - - @GameTest(template = "empty_1x1", timeoutTicks = 600) - public static void latitudeMap(GameTestHelper helper) { - try { - runLatitudeValidation(helper); - helper.succeed(); - } catch (AssertionError | Exception e) { - CustomOreGenMod.LOGGER.error("Latitude game test failed", e); - helper.fail(e.getMessage()); - } - } - - /** - * Proves the config-gated biome modifiers actually drive ore placement: queries the - * chunk generator's effective biome generation settings (which reflect applied biome - * modifiers, terrain-independent so it works on the void GameTest level) for the Shard - * Diamond placed feature. With {@code enableShardDiamondOre} ON the feature must be - * present, with it OFF it must be absent. Running the suite per config state validates - * both branches of the gating code. - */ - /** - * Compares ore feature presence across vanilla and Biomes O' Plenty temperate biomes by - * querying each biome holder's {@code modifiableBiomeInfo()} (the generation settings after - * NeoForge applies every biome modifier, including the config-gated ore modifiers). - * - *

In-game, vanilla plains shows custom iron/coal while BOP biomes (highland, shrubland) - * show none. This test reproduces the comparison in the registry context to pinpoint - * whether the config-gated modifiers actually inject ores into BOP biomes' settings.

- */ - @GameTest(template = "empty_1x1", timeoutTicks = 200) - public static void oreFeaturesAcrossBiomes(GameTestHelper helper) { - try { - ServerLevel level = helper.getLevel(); - var biomeRegistry = level.registryAccess().lookupOrThrow(Registries.BIOME); - - String[] temperateBiomes = { - "minecraft:plains", "minecraft:birch_forest", "minecraft:forest", - "biomesoplenty:shrubland", "biomesoplenty:field", "biomesoplenty:moor", - "biomesoplenty:grassland", "biomesoplenty:woodland", "biomesoplenty:mediterranean_forest" - }; - - StringBuilder report = new StringBuilder("\n=== ORE FEATURE PRESENCE PER BIOME (after biome modifiers) ===\n"); - boolean modifiersApplied = false; - for (String id : temperateBiomes) { - var key = net.minecraft.resources.ResourceKey.create(Registries.BIOME, - net.minecraft.resources.ResourceLocation.parse(id)); - Holder holder = biomeRegistry.get(key).orElse(null); - if (holder == null) { - report.append(String.format("%-36s NOT FOUND%n", id)); - continue; - } - var genSettings = holder.value().modifiableBiomeInfo().get().generationSettings(); - int totalFeatures = 0; - java.util.List customOres = new java.util.ArrayList<>(); - for (net.minecraft.core.HolderSet stepSet : genSettings.features()) { - for (net.minecraft.core.Holder featHolder : stepSet) { - totalFeatures++; - var fk = featHolder.unwrapKey(); - if (fk.isPresent() && fk.get().location().getNamespace().equals("custom_ore_gen")) { - customOres.add(fk.get().location().getPath()); - } - } - } - if (totalFeatures > 0) modifiersApplied = true; - report.append(String.format("%-36s total=%-4d customOres=[%s]%n", - id, totalFeatures, String.join(",", customOres))); - } - - CustomOreGenMod.LOGGER.info(report.toString()); - - if (!modifiersApplied) { - CustomOreGenMod.LOGGER.info("oreFeaturesAcrossBiomes: biome modifiers not observable in this context " - + "(void test level). Run against a real latitude world for the decisive comparison."); - } - helper.succeed(); - } catch (AssertionError | Exception e) { - CustomOreGenMod.LOGGER.error("oreFeaturesAcrossBiomes test failed", e); - helper.fail(e.getMessage()); - } - } - - /** - * Determinism: two {@link LatitudeBiomeSource} instances built with the same seed must - * return biome holders that resolve to the same biome key at every sampled point. - * Worldgen is shared work across threads, so equality of biome-by-coord is a hard contract. - * Also asserts a coarse cross-depth determinism: re-querying the same (x,z) at different Y in - * the surface zone returns the same biome (latitude surface band does not depend on Y in the - * zone with no override). - */ - @GameTest(template = "empty_1x1", timeoutTicks = 400) - public static void latitudeDeterminism(GameTestHelper helper) { - try { - ServerLevel level = helper.getLevel(); - HolderGetter getter = level.registryAccess().lookupOrThrow(Registries.BIOME); - LatitudeBiomeSource a = new LatitudeBiomeSource(SEED, getter); - LatitudeBiomeSource b = new LatitudeBiomeSource(SEED, getter); - - int mismatches = 0; - int checked = 0; - // Sample a coarse grid across the climate range, several Y of the surface zone. - int[] ys = {SURFACE_Y, SURFACE_Y + 1, 100, 200, 320}; - for (int blockZ = -RADIUS; blockZ <= RADIUS; blockZ += 1000) { - for (int blockX = -4000; blockX <= 4000; blockX += 1000) { - for (int y : ys) { - ResourceKey ka = a.getNoiseBiome(blockX >> 2, y >> 2, blockZ >> 2, null).unwrapKey().orElse(null); - ResourceKey kb = b.getNoiseBiome(blockX >> 2, y >> 2, blockZ >> 2, null).unwrapKey().orElse(null); - checked++; - if (!java.util.Objects.equals(ka, kb)) mismatches++; - } - } - } - assertTrue(checked > 100, "determinism test must check many points, checked=" + checked); - assertEquals(0, mismatches, - "same-seed sources must be identical everywhere, had " + mismatches + " / " + checked + " mismatches"); - - CustomOreGenMod.LOGGER.info("[latitude-determinism] OK: {} points all identical for seed={}", checked, SEED); - helper.succeed(); - } catch (AssertionError | Exception e) { - CustomOreGenMod.LOGGER.error("latitudeDeterminism test failed", e); - helper.fail(e.getMessage()); - } - } - - /** - * Cave biomes (LUSH_CAVES, DRIPSTONE_CAVES, DEEP_DARK) must never surface: the 3-zone model - * only injects them underground (Y < 0 for lush/dripstone, Y < -30 for Deep Dark). - * Sampling the whole surface grid and asserting zero cave biomes protects against a regression - * that would leak a cave biome to the surface (e.g. a swapped zone boundary). - */ - @GameTest(template = "empty_1x1", timeoutTicks = 400) - public static void noCaveBiomeAtSurface(GameTestHelper helper) { - try { - ServerLevel level = helper.getLevel(); - HolderGetter getter = level.registryAccess().lookupOrThrow(Registries.BIOME); - LatitudeBiomeSource source = new LatitudeBiomeSource(SEED, getter); - - Set> caveBiomes = Set.of( - Biomes.LUSH_CAVES, Biomes.DRIPSTONE_CAVES, Biomes.DEEP_DARK); - - int surfaceCaveLeaks = 0; - int checked = 0; - for (int blockZ = -RADIUS; blockZ <= RADIUS; blockZ += STEP) { - for (int blockX = -RADIUS; blockX <= RADIUS; blockX += STEP) { - ResourceKey k = source.getNoiseBiome(blockX >> 2, SURFACE_Y >> 2, blockZ >> 2, null) - .unwrapKey().orElse(null); - checked++; - if (k != null && caveBiomes.contains(k)) surfaceCaveLeaks++; - } - } - assertEquals(0, surfaceCaveLeaks, - "no cave biome must leak to the surface, found " + surfaceCaveLeaks + " / " + checked); - - CustomOreGenMod.LOGGER.info("[no-cave-at-surface] OK: {} surface samples, zero cave leaks", checked); - helper.succeed(); - } catch (AssertionError | Exception e) { - CustomOreGenMod.LOGGER.error("noCaveBiomeAtSurface test failed", e); - helper.fail(e.getMessage()); - } - } - - /** - * Spatial continuity / large-biome property: at the surface, the selector noise has a very - * low frequency (SURFACE_SELECTOR_SCALE = 0.00033), so neighbouring sample points (80 blocks - * apart) almost always fall in the same biome. This guards against a regression that would - * turn the world into per-block noise. We accept that band boundaries and ocean/rare pockets - * create some transitions, but they must remain rare ((< 25 %).

- */ - @GameTest(template = "empty_1x1", timeoutTicks = 400) - public static void surfaceBiomeContinuity(GameTestHelper helper) { - try { - ServerLevel level = helper.getLevel(); - HolderGetter getter = level.registryAccess().lookupOrThrow(Registries.BIOME); - LatitudeBiomeSource source = new LatitudeBiomeSource(SEED, getter); - - // Sample a single horizontal line across one temperate row (Z near 0, well inside one band) - // and count how often adjacent samples change biome. - int transitions = 0; - ResourceKey prev = null; - int sampleCount = 200; - int z = 160; // just south of equator, well inside TEMPERATE band, outside spawn-safe square - for (int i = 0; i < sampleCount; i++) { - int x = -8000 + i * 80; - ResourceKey k = source.getNoiseBiome(x >> 2, SURFACE_Y >> 2, z >> 2, null) - .unwrapKey().orElse(null); - if (prev != null && !java.util.Objects.equals(prev, k)) transitions++; - prev = k; - } - // 80-block spacing on a 0.00033-frequency noise: the noise barely moves, so transitions - // are driven mostly by ocean/rare-pocket edges, not selector turnover. - double transitionRatio = 100.0 * transitions / (sampleCount - 1); - assertTrue(transitionRatio < 25.0, - "surface should have large continuous biomes; transition ratio was " - + String.format("%.1f%%", transitionRatio) + " across a temperate row"); - - CustomOreGenMod.LOGGER.info("[surface-continuity] OK: {} transitions / {} samples = {}%", - transitions, sampleCount - 1, String.format("%.1f", transitionRatio)); - helper.succeed(); - } catch (AssertionError | Exception e) { - CustomOreGenMod.LOGGER.error("surfaceBiomeContinuity test failed", e); - helper.fail(e.getMessage()); - } - } - - /** - * Progressive climate transition: the surface biome must be predominantly cold at the far - * north, predominantly temperate at the equator, and predominantly hot at the far south. - * This is a finer-grained version of the band-ratio assertions in {@link #latitudeMap}, - * checking the gradient direction in three Z windows rather than just the two poles. - */ - @GameTest(template = "empty_1x1", timeoutTicks = 400) - public static void climateGradient(GameTestHelper helper) { - try { - ServerLevel level = helper.getLevel(); - HolderGetter getter = level.registryAccess().lookupOrThrow(Registries.BIOME); - LatitudeBiomeSource source = new LatitudeBiomeSource(SEED, getter); - - Set> cold = resolveTagKeys(getter, BiomeBand.COLD.surfaceTag()); - Set> coldOceans = new HashSet<>(List.of( - Biomes.FROZEN_OCEAN, Biomes.DEEP_FROZEN_OCEAN, Biomes.COLD_OCEAN, Biomes.DEEP_COLD_OCEAN, Biomes.FROZEN_RIVER)); - cold.addAll(coldOceans); - - Set> hot = resolveTagKeys(getter, BiomeBand.HOT.surfaceTag()); - Set> hotOceans = new HashSet<>(List.of( - Biomes.WARM_OCEAN, Biomes.LUKEWARM_OCEAN, Biomes.DEEP_LUKEWARM_OCEAN, Biomes.MANGROVE_SWAMP)); - hot.addAll(hotOceans); - - // Three Z windows, 3200 blocks wide, 800 apart (RADIUS=16000 covers them all). - assertEquals(5, BiomeBand.values().length, "exactly five climate bands expected"); - double north = windowBiomeRatio(source, -15000, -11800, cold); - double equator = windowBiomeRatio(source, -1600, 1600, cold); // equator is NOT cold - double south = windowBiomeRatio(source, 11800, 15000, hot); - - assertTrue(north > 50.0, "far north must be >50% cold, was " + String.format("%.1f%%", north)); - double equatorCold = windowBiomeRatio(source, -1600, 1600, cold); - assertTrue(equatorCold < 25.0, - "equator must NOT be predominantly cold (gradient broken), was " + String.format("%.1f%%", equatorCold)); - assertTrue(south > 50.0, "far south must be >50% hot, was " + String.format("%.1f%%", south)); - - CustomOreGenMod.LOGGER.info("[climate-gradient] OK: north(cold)={}%, south(hot)={}%, equator(cold)={}%", - String.format("%.0f", north), String.format("%.0f", south), String.format("%.0f", equatorCold)); - helper.succeed(); - } catch (AssertionError | Exception e) { - CustomOreGenMod.LOGGER.error("climateGradient test failed", e); - helper.fail(e.getMessage()); - } - } - - /** Sample a Z window of the surface and return the % of biomes in the expected set. */ - private static double windowBiomeRatio(LatitudeBiomeSource source, int zMin, int zMax, - Set> expected) { - int match = 0; - int total = 0; - for (int z = zMin; z <= zMax; z += 160) { - for (int x = -4000; x <= 4000; x += 800) { - ResourceKey k = source.getNoiseBiome(x >> 2, SURFACE_Y >> 2, z >> 2, null) - .unwrapKey().orElse(null); - total++; - if (k != null && expected.contains(k)) match++; - } - } - return total == 0 ? 0 : 100.0 * match / total; - } - - private static void runLatitudeValidation(GameTestHelper helper) throws Exception { - ServerLevel level = helper.getLevel(); - HolderGetter getter = level.registryAccess().lookupOrThrow(Registries.BIOME); - LatitudeBiomeSource source = new LatitudeBiomeSource(SEED, getter); - - Files.createDirectories(OUT_DIR); - - // ---- Sample one slice per depth. Each slice produces a PNG + a biome-count map. ---- - Slice surface = sampleSlice(source, SURFACE_Y, "latitude_map_surface.png"); - Slice midCave = sampleSlice(source, MID_CAVE_Y, "latitude_map_mid_cave.png"); - Slice deep = sampleSlice(source, DEEP_Y, "latitude_map_deep.png"); - - // ---- Surface climate assertions ---- - ResourceKey spawnKey = source.getNoiseBiome(0, SURFACE_Y >> 2, 0, null).unwrapKey().orElse(null); - - Set> coldTag = resolveTagKeys(getter, BiomeBand.COLD.surfaceTag()); - Set> hotTag = resolveTagKeys(getter, BiomeBand.HOT.surfaceTag()); - Set> coldOceans = new HashSet<>(List.of( - Biomes.FROZEN_OCEAN, Biomes.DEEP_FROZEN_OCEAN, Biomes.COLD_OCEAN, Biomes.DEEP_COLD_OCEAN, - Biomes.FROZEN_RIVER)); - Set> hotOceans = new HashSet<>(List.of( - Biomes.WARM_OCEAN, Biomes.LUKEWARM_OCEAN, Biomes.DEEP_LUKEWARM_OCEAN)); - - assertNotNull(spawnKey, "spawn biome resolved"); - assertTrue(isSafeSpawn(spawnKey), "spawn must be a safe biome, was " + spawnKey); - - Set> northExpected = new HashSet<>(); - northExpected.addAll(coldTag); - northExpected.addAll(coldOceans); - double north = sliceBandRatio(surface, BiomeBand.FROZEN, northExpected); - assertTrue(north > 60.0, "FROZEN band should be >60%% cold/frozen (by tag), was %.1f%%".formatted(north)); - - Set> southExpected = new HashSet<>(); - southExpected.addAll(hotTag); - southExpected.addAll(hotOceans); - southExpected.add(Biomes.MANGROVE_SWAMP); - double south = sliceBandRatio(surface, BiomeBand.HOT, southExpected); - assertTrue(south > 60.0, "HOT band should be >60%% warm/hot (by tag), was %.1f%%".formatted(south)); - - // Swamp stays rare at the surface in the temperate band. - double swampRatio = biomeRatioInBand(surface, BiomeBand.TEMPERATE, Biomes.SWAMP); - assertTrue(swampRatio < 15.0, "swamp must be <15%% of temperate band, was %.2f%%".formatted(swampRatio)); - - // ---- Cave assertions ---- - // Deep Dark is legendary: a small fraction of the deep slice only. - double deepDarkRatio = biomeRatio(deep, Biomes.DEEP_DARK); - assertTrue(deepDarkRatio < 8.0, - "Deep Dark must be rare in the deep zone (<8%%), was %.2f%%".formatted(deepDarkRatio)); - - // Cave biomes (lush/dripstone) should be a minority even in the mid-cave slice - the latitude - // biome dominates underground by design. - double caveBiomeRatio = biomeRatio(midCave, Biomes.LUSH_CAVES, Biomes.DRIPSTONE_CAVES); - assertTrue(caveBiomeRatio < 25.0, - "cave biomes must stay a minority in mid-cave (<25%%), was %.2f%%".formatted(caveBiomeRatio)); - - // ---- Report ---- - StringBuilder r = new StringBuilder(); - r.append("Latitude GameTest Report (seed=").append(SEED).append(")\n\n"); - r.append("Spawn @ (0,0): ").append(spawnKey).append("\n\n"); - - r.append("=== Depth slices (PNG) ===\n"); - r.append(String.format(" Surface Y=%3d : latitude_map_surface.png%n", SURFACE_Y)); - r.append(String.format(" Mid cave Y=%3d: latitude_map_mid_cave.png%n", MID_CAVE_Y)); - r.append(String.format(" Deep Y=%3d : latitude_map_deep.png%n%n", DEEP_Y)); - - r.append("=== Surface top biomes (top 12) ===\n"); - appendTop(r, surface.global, 12); - - r.append("\n=== Mid cave (Y=").append(MID_CAVE_Y).append(") top biomes (top 10) ===\n"); - appendTop(r, midCave.global, 10); - - r.append("\n=== Deep (Y=").append(DEEP_Y).append(") top biomes (top 10) ===\n"); - appendTop(r, deep.global, 10); - - Files.writeString(OUT_DIR.resolve("latitude_report.txt"), r.toString()); - - // ---- One-line summary ---- - CustomOreGenMod.LOGGER.info(String.format( - "Latitude game test OK: spawn=%s | north=%.0f%% | south=%.0f%% | swamp=%.2f%% | " - + "deepDark=%.2f%% | caveBiomes=%.1f%%", - spawnKey, north, south, swampRatio, deepDarkRatio, caveBiomeRatio)); - } - - /** Sample the whole grid at a single Y and write a PNG; returns the slice's biome counts. */ - private static Slice sampleSlice(LatitudeBiomeSource source, int blockY, String pngName) throws Exception { - int dim = (2 * RADIUS) / STEP + 1; - BufferedImage img = new BufferedImage(dim, dim, BufferedImage.TYPE_INT_RGB); - Map, Integer> global = new HashMap<>(); - Map, Integer>> perBand = new EnumMap<>(BiomeBand.class); - for (BiomeBand b : BiomeBand.values()) perBand.put(b, new HashMap<>()); - - for (int zi = 0; zi < dim; zi++) { - for (int xi = 0; xi < dim; xi++) { - int blockX = -RADIUS + xi * STEP; - int blockZ = -RADIUS + zi * STEP; - Holder holder = source.getNoiseBiome(blockX >> 2, blockY >> 2, blockZ >> 2, null); - ResourceKey key = holder.unwrapKey().orElse(null); - - global.merge(key, 1, Integer::sum); - perBand.get(BiomeBand.fromTemperature(blockZ / 16000.0)).merge(key, 1, Integer::sum); - - int rgb = key == null ? 0x888888 : COLORS.getOrDefault(key, 0x888888); - img.setRGB(xi, dim - 1 - zi, rgb); // flip Z so north is at the top - } - } - ImageIO.write(img, "png", OUT_DIR.resolve(pngName).toFile()); - return new Slice(global, perBand); - } - - private static void appendTop(StringBuilder r, Map, Integer> counts, int limit) { - int total = counts.values().stream().mapToInt(Integer::intValue).sum(); - counts.entrySet().stream() - .sorted(Map.Entry., Integer>comparingByValue().reversed()) - .limit(limit) - .forEach(e -> r.append(String.format(" %-45s %6.2f%%%n", e.getKey(), 100.0 * e.getValue() / total))); - } - - /** Ratio of a set of biomes within a single band of a slice. */ - private static double sliceBandRatio(Slice slice, BiomeBand band, Set> expected) { - Map, Integer> m = slice.perBand.get(band); - int total = m.values().stream().mapToInt(Integer::intValue).sum(); - if (total == 0) return 0; - int match = 0; - for (ResourceKey k : expected) match += m.getOrDefault(k, 0); - return 100.0 * match / total; - } - - /** Ratio of one or more biomes across a whole slice. */ - private static double biomeRatio(Slice slice, ResourceKey... keys) { - int total = slice.global.values().stream().mapToInt(Integer::intValue).sum(); - if (total == 0) return 0; - int match = 0; - for (ResourceKey k : keys) match += slice.global.getOrDefault(k, 0); - return 100.0 * match / total; - } - - /** Ratio of a biome within a single band of a slice. */ - private static double biomeRatioInBand(Slice slice, BiomeBand band, ResourceKey key) { - Map, Integer> m = slice.perBand.get(band); - int total = m.values().stream().mapToInt(Integer::intValue).sum(); - if (total == 0) return 0; - return 100.0 * m.getOrDefault(key, 0) / total; - } - - /** Resolve all biome keys that belong to a tag, via the real registry. */ - private static Set> resolveTagKeys(HolderGetter getter, net.minecraft.tags.TagKey tag) { - Set> keys = new HashSet<>(); - getter.get(tag).ifPresent(set -> set.forEach(h -> h.unwrapKey().ifPresent(keys::add))); - return keys; - } - - private static boolean isSafeSpawn(ResourceKey key) { - return Set.of(Biomes.PLAINS, Biomes.SUNFLOWER_PLAINS, Biomes.FOREST, Biomes.BIRCH_FOREST, - Biomes.FLOWER_FOREST, Biomes.MEADOW, Biomes.CHERRY_GROVE).contains(key); - } - - /** A sampled depth slice: global counts + per-band counts. */ - private record Slice(Map, Integer> global, - Map, Integer>> perBand) { - } - - // Local assert helpers (no JUnit in the main classpath at runtime). - private static void assertTrue(boolean condition, String msg) { - if (!condition) throw new AssertionError(msg); - } - - private static void assertNotNull(Object o, String msg) { - if (o == null) throw new AssertionError(msg); - } - - private static void assertEquals(Object expected, Object actual, String msg) { - if (!java.util.Objects.equals(expected, actual)) { - throw new AssertionError(msg + " (expected=" + expected + ", actual=" + actual + ")"); - } - } -} diff --git a/src/main/java/net/mcreator/customoregen/worldgen/LatitudeMapCommand.java b/src/main/java/net/mcreator/customoregen/worldgen/LatitudeMapCommand.java deleted file mode 100644 index f858a33f..00000000 --- a/src/main/java/net/mcreator/customoregen/worldgen/LatitudeMapCommand.java +++ /dev/null @@ -1,219 +0,0 @@ -package net.mcreator.customoregen.worldgen; - -import com.mojang.brigadier.CommandDispatcher; -import com.mojang.brigadier.arguments.IntegerArgumentType; -import com.mojang.brigadier.context.CommandContext; -import net.mcreator.customoregen.CustomOreGenMod; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.Commands; -import net.minecraft.core.Holder; -import net.minecraft.core.HolderGetter; -import net.minecraft.core.registries.Registries; -import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceKey; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.biome.Biomes; -import net.neoforged.bus.api.SubscribeEvent; -import net.neoforged.fml.common.EventBusSubscriber; -import net.neoforged.neoforge.event.RegisterCommandsEvent; - -import javax.imageio.ImageIO; -import java.awt.image.BufferedImage; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.EnumMap; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * {@code /latitude map [radius] [step]} — renders a top-down biome map of the latitude world. - * - *

Samples {@link LatitudeBiomeSource} on a large square grid (independent of the current - * world's biome source, so it works in any world) and writes: - *

    - *
  • {@code run/latitude/latitude_map.png} — one colour per biome category (the "map view"),
  • - *
  • {@code run/latitude/latitude_report.txt} — per-band distribution + validation invariants.
  • - *
- * - *

Use this to validate the climate distribution without exploring by hand.

- */ -@EventBusSubscriber(modid = CustomOreGenMod.MODID, bus = EventBusSubscriber.Bus.GAME) -public class LatitudeMapCommand { - - private static final int DEFAULT_RADIUS = 24000; - private static final int DEFAULT_STEP = 60; - - // Biome key -> colour category (kept in sync with BiomeBand pools) - private static final Map, Integer> COLORS = new HashMap<>(); - - static { - col(0xB6E388, Biomes.PLAINS, Biomes.SUNFLOWER_PLAINS, Biomes.FOREST, Biomes.BIRCH_FOREST, - Biomes.FLOWER_FOREST, Biomes.MEADOW, Biomes.CHERRY_GROVE); // safe spawn / temperate - col(0xC8E6FF, Biomes.SNOWY_PLAINS, Biomes.ICE_SPIKES, Biomes.SNOWY_TAIGA, Biomes.GROVE, - Biomes.SNOWY_SLOPES, Biomes.JAGGED_PEAKS, Biomes.FROZEN_PEAKS); // frozen - col(0x8FB8D6, Biomes.TAIGA, Biomes.OLD_GROWTH_PINE_TAIGA, Biomes.OLD_GROWTH_SPRUCE_TAIGA, - Biomes.WINDSWEPT_HILLS, Biomes.WINDSWEPT_FOREST, Biomes.WINDSWEPT_GRAVELLY_HILLS); // cold - col(0x7CC576, Biomes.DARK_FOREST, Biomes.OLD_GROWTH_BIRCH_FOREST); // temperate - col(0xE0C068, Biomes.SAVANNA, Biomes.SAVANNA_PLATEAU, Biomes.WINDSWEPT_SAVANNA); // warm - col(0xE0884C, Biomes.DESERT, Biomes.BADLANDS, Biomes.WOODED_BADLANDS, Biomes.ERODED_BADLANDS, - Biomes.JUNGLE, Biomes.SPARSE_JUNGLE, Biomes.BAMBOO_JUNGLE); // hot - col(0x2B5C8A, Biomes.OCEAN, Biomes.DEEP_OCEAN, Biomes.LUKEWARM_OCEAN, Biomes.DEEP_LUKEWARM_OCEAN, - Biomes.WARM_OCEAN, Biomes.FROZEN_OCEAN, Biomes.DEEP_FROZEN_OCEAN, Biomes.COLD_OCEAN, - Biomes.DEEP_COLD_OCEAN, Biomes.RIVER, Biomes.FROZEN_RIVER); // water - col(0x5B7A3A, Biomes.SWAMP); // swamp (should be rare pockets) - col(0x3A5A3A, Biomes.MANGROVE_SWAMP); // mangrove - col(0x6B4E3A, Biomes.LUSH_CAVES, Biomes.DRIPSTONE_CAVES, Biomes.DEEP_DARK); // underground - } - - private static void col(int rgb, ResourceKey... keys) { - for (ResourceKey k : keys) COLORS.put(k, rgb); - } - - @SubscribeEvent - public static void onRegisterCommands(RegisterCommandsEvent event) { - CommandDispatcher dispatcher = event.getDispatcher(); - dispatcher.register(Commands.literal("latitude") - .requires(source -> source.hasPermission(2)) - .then(Commands.literal("map") - .executes(ctx -> run(ctx, DEFAULT_RADIUS, DEFAULT_STEP)) - .then(Commands.argument("radius", IntegerArgumentType.integer(1000, 100000)) - .executes(ctx -> run(ctx, IntegerArgumentType.getInteger(ctx, "radius"), DEFAULT_STEP)) - .then(Commands.argument("step", IntegerArgumentType.integer(4, 1000)) - .executes(ctx -> run(ctx, - IntegerArgumentType.getInteger(ctx, "radius"), - IntegerArgumentType.getInteger(ctx, "step"))))))); - } - - private static int run(CommandContext ctx, int radius, int step) { - CommandSourceStack src = ctx.getSource(); - if (!(src.getLevel() instanceof ServerLevel serverLevel)) { - src.sendFailure(Component.literal("Must be run on a server level.")); - return 0; - } - - long seed = serverLevel.getSeed(); - HolderGetter getter = serverLevel.registryAccess().lookupOrThrow(Registries.BIOME); - LatitudeBiomeSource source = new LatitudeBiomeSource(seed, getter); - - int dim = (2 * radius) / step + 1; - src.sendSystemMessage(Component.literal( - "\u00A7b[Latitude]\u00A7r Sampling " + dim + "x" + dim + " grid (radius=" + radius + ", step=" + step + ")...")); - - BufferedImage img = new BufferedImage(dim, dim, BufferedImage.TYPE_INT_RGB); - Map, Integer> global = new HashMap<>(); - Map, Integer>> perBand = new EnumMap<>(BiomeBand.class); - for (BiomeBand b : BiomeBand.values()) perBand.put(b, new HashMap<>()); - - for (int zi = 0; zi < dim; zi++) { - for (int xi = 0; xi < dim; xi++) { - int blockX = -radius + xi * step; - int blockZ = -radius + zi * step; - Holder holder = source.getNoiseBiome(blockX >> 2, 64 >> 2, blockZ >> 2, null); - ResourceKey key = holder.unwrapKey().orElse(null); - - global.merge(key, 1, Integer::sum); - perBand.get(BiomeBand.fromTemperature(blockZ / 16000.0)).merge(key, 1, Integer::sum); - - int rgb = key == null ? 0x888888 : COLORS.getOrDefault(key, 0x888888); - img.setRGB(xi, dim - 1 - zi, rgb); // flip Z so north is at the top - } - } - - // ---- Spawn biome ---- - ResourceKey spawnKey = source.getNoiseBiome(0, 64 >> 2, 0, null).unwrapKey().orElse(null); - - // ---- Write PNG ---- - try { - Files.createDirectories(Path.of("latitude")); - ImageIO.write(img, "png", Path.of("latitude", "latitude_map.png").toFile()); - } catch (Exception e) { - CustomOreGenMod.LOGGER.error("Latitude map: failed to write PNG", e); - src.sendFailure(Component.literal("Failed to write PNG: " + e.getMessage())); - return 0; - } - - // ---- Build report ---- - StringBuilder r = new StringBuilder(); - r.append("Latitude World Map Report\n"); - r.append("seed=").append(seed).append(" radius=").append(radius).append(" step=").append(step) - .append(" grid=").append(dim).append("x").append(dim).append("\n\n"); - r.append("Spawn biome @ (0,0): ").append(spawnKey).append("\n\n"); - - int total = global.values().stream().mapToInt(Integer::intValue).sum(); - r.append("Global biome distribution (top 15):\n"); - global.entrySet().stream() - .sorted(Map.Entry., Integer>comparingByValue().reversed()) - .limit(15) - .forEach(e -> r.append(String.format(" %-45s %6.2f%%%n", e.getKey(), 100.0 * e.getValue() / total))); - - List warnings = new ArrayList<>(); - for (BiomeBand band : BiomeBand.values()) { - Map, Integer> m = perBand.get(band); - int bt = m.values().stream().mapToInt(Integer::intValue).sum(); - if (bt == 0) continue; - int swamp = m.getOrDefault(Biomes.SWAMP, 0) + m.getOrDefault(Biomes.MANGROVE_SWAMP, 0); - double swampPct = 100.0 * swamp / bt; - r.append("\nBand ").append(band).append(" (").append(bt).append(" samples, swamp+mangrove ") - .append(String.format("%.2f%%", swampPct)).append("):\n"); - m.entrySet().stream() - .sorted(Map.Entry., Integer>comparingByValue().reversed()) - .limit(6) - .forEach(e -> r.append(String.format(" %-43s %6.2f%%%n", e.getKey(), 100.0 * e.getValue() / bt))); - if (swampPct > 15.0) { - warnings.add(band + " has " + String.format("%.1f%%", swampPct) + " swamp (expected <15%)"); - } - } - - // Invariant checks - r.append("\n=== Validation ===\n"); - boolean spawnOk = spawnKey != null && isSafeSpawn(spawnKey); - r.append("Spawn on safe biome: ").append(spawnOk ? "PASS" : "FAIL (" + spawnKey + ")").append("\n"); - double frozenCold = bandRatio(perBand.get(BiomeBand.FROZEN), Set.of( - Biomes.SNOWY_PLAINS, Biomes.ICE_SPIKES, Biomes.SNOWY_TAIGA, Biomes.GROVE, Biomes.SNOWY_SLOPES, - Biomes.JAGGED_PEAKS, Biomes.FROZEN_PEAKS, Biomes.TAIGA, Biomes.OLD_GROWTH_PINE_TAIGA, - Biomes.OLD_GROWTH_SPRUCE_TAIGA, Biomes.WINDSWEPT_HILLS, Biomes.WINDSWEPT_FOREST, - Biomes.FROZEN_OCEAN, Biomes.DEEP_FROZEN_OCEAN, Biomes.COLD_OCEAN, Biomes.DEEP_COLD_OCEAN, - Biomes.FROZEN_RIVER)); - r.append(String.format("North (FROZEN) cold/frozen ratio: %.1f%% (want >60%%)%n", frozenCold)); - double hotRatio = bandRatio(perBand.get(BiomeBand.HOT), Set.of( - Biomes.DESERT, Biomes.BADLANDS, Biomes.WOODED_BADLANDS, Biomes.ERODED_BADLANDS, - Biomes.JUNGLE, Biomes.SPARSE_JUNGLE, Biomes.BAMBOO_JUNGLE, Biomes.SAVANNA, - Biomes.SAVANNA_PLATEAU, Biomes.WARM_OCEAN)); - r.append(String.format("South (HOT) warm/hot ratio: %.1f%% (want >60%%)%n", hotRatio)); - r.append("Warnings: ").append(warnings.isEmpty() ? "none" : warnings).append("\n"); - - try { - Files.writeString(Path.of("latitude", "latitude_report.txt"), r.toString()); - } catch (Exception e) { - CustomOreGenMod.LOGGER.error("Latitude map: failed to write report", e); - } - - // ---- Summary to chat ---- - src.sendSystemMessage(Component.literal("\u00A7a[Latitude]\u00A7r Map + report saved to /latitude/")); - src.sendSystemMessage(Component.literal(" Spawn: " + spawnKey + (spawnOk ? " \u00A7aOK\u00A7r" : " \u00A7cBAD\u00A7r"))); - src.sendSystemMessage(Component.literal(String.format( - " North cold/frozen: %.0f%% | South hot: %.0f%% | Swamp warnings: %d", - frozenCold, hotRatio, warnings.size()))); - return 1; - } - - private static double bandRatio(Map, Integer> m, Set> expected) { - int total = m.values().stream().mapToInt(Integer::intValue).sum(); - if (total == 0) return 0; - int match = 0; - for (ResourceKey k : expected) match += m.getOrDefault(k, 0); - return 100.0 * match / total; - } - - private static boolean isSafeSpawn(ResourceKey key) { - Set> safe = new HashSet<>(List.of( - Biomes.PLAINS, Biomes.SUNFLOWER_PLAINS, Biomes.FOREST, Biomes.BIRCH_FOREST, - Biomes.FLOWER_FOREST, Biomes.MEADOW, Biomes.CHERRY_GROVE)); - return safe.contains(key); - } -} diff --git a/src/main/java/net/mcreator/customoregen/worldgen/LatitudeMath.java b/src/main/java/net/mcreator/customoregen/worldgen/LatitudeMath.java deleted file mode 100644 index 844a782c..00000000 --- a/src/main/java/net/mcreator/customoregen/worldgen/LatitudeMath.java +++ /dev/null @@ -1,133 +0,0 @@ -package net.mcreator.customoregen.worldgen; - -/** - * Pure (registry-free) geometry helpers for the latitude world type. - * - *

These methods exist so that the core invariants of {@link LatitudeBiomeSource} - * can be unit-tested without a loaded biome registry: temperature derivation, the - * 3-zone underground model, the spawn safe zone, and the dual-octave biome index - * math. {@link LatitudeBiomeSource} delegates to these helpers, so the two stay - * in lock-step by construction (no behaviour drift).

- */ -public final class LatitudeMath { - - private LatitudeMath() {} - - // ------------------------------------------------------------------ - // Surface / climate tunables (must mirror LatitudeBiomeSource) - // ------------------------------------------------------------------ - - public static final double TEMPERATURE_SCALE = 16000.0; - public static final double BOUNDARY_NOISE_SCALE = 0.00015; - public static final double BOUNDARY_NOISE_AMPLITUDE = 0.15; - public static final double SURFACE_SELECTOR_SCALE = 0.00033; - public static final double OCEAN_NOISE_SCALE = 0.0011; - public static final double OCEAN_THRESHOLD = 0.30; - public static final double MOISTURE_SCALE = 0.0009; - public static final double MOISTURE_THRESHOLD = 0.55; - - // ------------------------------------------------------------------ - // Underground tunables (3-zone model) - // ------------------------------------------------------------------ - - public static final int DEEP_ZONE_TOP = -30; - public static final int MID_CAVE_TOP = 0; - public static final double CAVE_SCALE = 0.003; - public static final double CAVE_THRESHOLD = 0.38; - public static final double DEEP_DARK_SCALE = 0.0011; - public static final double DEEP_DARK_SCALE_Y = 0.012; - public static final double DEEP_DARK_THRESHOLD = 0.55; - - // ------------------------------------------------------------------ - // Spawn safe zone - // ------------------------------------------------------------------ - - public static final int SPAWN_SAFE_RADIUS = 540; - public static final double SPAWN_SELECTOR_SCALE = 0.004; - - /** Underground vertical zone, mirroring {@link LatitudeBiomeSource#applyCaveOverrides}. */ - public enum Zone { - /** {@code Y < DEEP_ZONE_TOP} — deep zone, legendary Deep Dark pockets. */ - DEEP, - /** {@code DEEP_ZONE_TOP <= Y < MID_CAVE_TOP} — mid caves, lush/dripstone pockets. */ - MID_CAVE, - /** {@code Y >= MID_CAVE_TOP} — no cave override; latitude biome as-is. */ - SURFACE - } - - /** Band the column falls into based on its Y coordinate. Pure function. */ - public static Zone zoneForY(int blockY) { - if (blockY < DEEP_ZONE_TOP) return Zone.DEEP; - if (blockY < MID_CAVE_TOP) return Zone.MID_CAVE; - return Zone.SURFACE; - } - - /** - * Raw latitude temperature contribution from the Z coordinate, before the boundary - * wobble is applied. {@code blockZ / TEMPERATURE_SCALE} clamped to {@code [-1, 1]}. - * Pure function. - */ - public static double rawLatitudeTemperature(int blockZ) { - return clamp(blockZ / TEMPERATURE_SCALE, -1.0, 1.0); - } - - /** - * Combine the raw latitude temperature with a precomputed boundary wobble (the output of - * {@code boundaryNoise.noise(...) * BOUNDARY_NOISE_AMPLITUDE}), then clamp to the valid - * temperature range. Pure function. - */ - public static double temperature(int blockZ, double boundaryWobble) { - return clamp(blockZ / TEMPERATURE_SCALE + boundaryWobble, -1.0, 1.0); - } - - /** True if the (blockX, blockZ) column is inside the guaranteed safe spawn square. Pure. */ - public static boolean isInSpawnSafeZone(int blockX, int blockZ) { - return Math.abs(blockX) < SPAWN_SAFE_RADIUS && Math.abs(blockZ) < SPAWN_SAFE_RADIUS; - } - - /** - * Normalised selector value in {@code [0, 1]} from two noise samples, mirroring the - * dual-octave flattening used by {@link LatitudeBiomeSource#pickBiome}. - * - * @param n1 first octave noise value (any range ImprovedNoise produces) - * @param n2 second octave noise value (at a different offset) - * @return a value in {@code [0, 1]} - */ - public static double normalisedSelector(double n1, double n2) { - double combined = (n1 + n2 * 0.5) / 1.5; - return clamp(combined * 0.5 + 0.5, 0.0, 1.0); - } - - /** - * Map a normalised selector value in {@code [0, 1]} to a list index, clamped so it can - * never leave {@code [0, size-1]}. Mirrors the index math in {@code pickBiome}. - * Pure. {@code size} must be {@code >= 1}. - */ - public static int selectorIndex(double normalised, int size) { - if (size <= 0) { - throw new IllegalArgumentException("size must be >= 1, was " + size); - } - int idx = (int) (normalised * size); - if (idx >= size) idx = size - 1; - if (idx < 0) idx = 0; - return idx; - } - - /** - * Is the deep-Dark override active for this column, given the precomputed deep-dark noise - * value (output of {@code deepDarkNoise.noise(...)})? Only meaningful in the DEEP zone; - * callers should gate on {@link #zoneForY} first. Pure. - */ - public static boolean isDeepDarkPocket(double deepDarkNoise) { - return deepDarkNoise > DEEP_DARK_THRESHOLD; - } - - /** Is the mid-cave lush/dripstone pocket override active for this column? Pure. */ - public static boolean isMidCavePocket(double caveNoise) { - return caveNoise > CAVE_THRESHOLD; - } - - private static double clamp(double value, double min, double max) { - return value < min ? min : (value > max ? max : value); - } -} diff --git a/src/main/java/net/mcreator/customoregen/worldgen/LatitudeSignalDensityFunction.java b/src/main/java/net/mcreator/customoregen/worldgen/LatitudeSignalDensityFunction.java new file mode 100644 index 00000000..6306d201 --- /dev/null +++ b/src/main/java/net/mcreator/customoregen/worldgen/LatitudeSignalDensityFunction.java @@ -0,0 +1,62 @@ +package net.mcreator.customoregen.worldgen; + +import com.mojang.serialization.MapCodec; +import net.minecraft.util.KeyDispatchDataCodec; +import net.minecraft.world.level.levelgen.DensityFunction; + +/** + * A custom {@link DensityFunction} that exposes the world's latitude as a Z-only signal, + * something the vanilla density-function vocabulary cannot do (only {@code y} is reachable, via + * {@code y_clamped_gradient}). + * + *

The value is {@code clamp(blockZ / TEMPERATURE_SCALE, -1, 1)}. {@code -1} = far north + * (cold), {@code 0} = equator (temperate), {@code +1} = far south (hot). It feeds the + * {@code custom_ore_gen:latitude_temperature} density function, which replaces the vanilla + * temperature in the Lithosphere noise settings so that biome selection follows latitude.

+ * + *

Registered as density-function type {@code custom_ore_gen:latitude_signal}; reference it from a + * density-function JSON as {@code { "type": "custom_ore_gen:latitude_signal" }}.

+ */ +public record LatitudeSignalDensityFunction() implements DensityFunction.SimpleFunction { + + /** + * Number of blocks for the temperature to go from 0 (equator) to ±1 (pole). + * + *

Tuned to match the ore-zone thresholds (default ±8000): at Z=8000 the latitude is + * 0.5, which is the vanilla boundary between temperate and warm climates, so hot ores + * (copper/gold/redstone) line up with hot-looking biomes. Lush caves (temperature ~0.7) + * therefore appear around Z=11000, just inside the hot ore zone.

+ */ + private static final double TEMPERATURE_SCALE = 16000.0; + + /** MapCodec (no fields): a single canonical instance, round-trips as a bare type tag. */ + public static final MapCodec DATA_CODEC = + MapCodec.unit(new LatitudeSignalDensityFunction()); + + /** {@link DensityFunction#codec()} wrapper the framework expects. */ + public static final KeyDispatchDataCodec CODEC = + KeyDispatchDataCodec.of(DATA_CODEC); + + @Override + public double compute(DensityFunction.FunctionContext context) { + double latitude = context.blockZ() / TEMPERATURE_SCALE; + if (latitude < -1.0) return -1.0; + if (latitude > 1.0) return 1.0; + return latitude; + } + + @Override + public double minValue() { + return -1.0; + } + + @Override + public double maxValue() { + return 1.0; + } + + @Override + public KeyDispatchDataCodec codec() { + return CODEC; + } +} diff --git a/src/main/java/net/mcreator/customoregen/worldgen/LatitudeSpawnHandler.java b/src/main/java/net/mcreator/customoregen/worldgen/LatitudeSpawnHandler.java deleted file mode 100644 index 938a04d6..00000000 --- a/src/main/java/net/mcreator/customoregen/worldgen/LatitudeSpawnHandler.java +++ /dev/null @@ -1,118 +0,0 @@ -package net.mcreator.customoregen.worldgen; - -import net.mcreator.customoregen.CustomOreGenMod; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Holder; -import net.minecraft.resources.ResourceKey; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.tags.TagKey; -import net.minecraft.core.registries.Registries; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.biome.Biomes; -import net.minecraft.world.level.levelgen.Heightmap; -import net.minecraft.world.level.storage.ServerLevelData; -import net.neoforged.bus.api.SubscribeEvent; -import net.neoforged.fml.common.EventBusSubscriber; -import net.neoforged.neoforge.event.level.LevelEvent; - -import java.util.Set; - -/** - * Forces the world spawn point to a plains-like biome near the origin. - * - *

Because {@link LatitudeBiomeSource} places temperate biomes around Z=0, a plains - * or forest biome is always available close to spawn. This handler runs once per server - * lifetime when the overworld loads, scans a growing square around the origin and pins - * the default spawn point to the first matching biome. The player therefore always - * starts the game on open, buildable terrain instead of a swamp, mountain or ocean.

- */ -@EventBusSubscriber(modid = CustomOreGenMod.MODID) -public class LatitudeSpawnHandler { - - /** Biomes considered a good starting point (open, buildable temperate terrain). */ - private static final Set> SPAWN_BIOMES = Set.of( - Biomes.PLAINS, Biomes.SUNFLOWER_PLAINS, - Biomes.FOREST, Biomes.BIRCH_FOREST, Biomes.FLOWER_FOREST, - Biomes.MEADOW, Biomes.CHERRY_GROVE - ); - - /** Maximum search radius (in blocks) around the origin. Kept inside the BiomeSource */ - /** SPAWN_SAFE_RADIUS (540) so the safe-square guarantee applies to everything we find. */ - private static final int MAX_RADIUS = 512; - - /** Step between sampled positions. */ - private static final int STEP = 8; - - /** Surface Y used for biome probing - must match LatitudeGameTest.SURFACE_Y semantics. */ - private static final int SURFACE_Y = 64; - - private static volatile boolean initialized = false; - - @SubscribeEvent - public static void onLevelLoad(LevelEvent.Load event) { - if (initialized) { - return; - } - if (!(event.getLevel() instanceof ServerLevel level)) { - return; - } - if (level.dimension() != Level.OVERWORLD) { - return; - } - - initialized = true; - - if (!(level.getLevelData() instanceof ServerLevelData levelData)) { - return; - } - - // Probe biomes at the SURFACE (y=64), not at y=0. Underground the latitude biome extends - // downwards by design, so probing at y=0 could match a SPAWN_BIOMES that differs from what - // the player actually sees on the surface. The BiomeSource spawn-safe square covers the - // first 540 blocks around the origin, so probing at surface y and within that square reliably - // lands on plains/forest - never dark_forest (which is only in the temperate surface pool, - // used outside the safe square). - BlockPos current = levelData.getSpawnPos(); - if (isSpawnBiomeAtSurface(level, current.getX(), current.getZ())) { - return; // Already on a good biome, leave it alone. - } - - BlockPos found = findSpawnBiome(level); - if (found == null) { - CustomOreGenMod.LOGGER.warn("Latitude: no suitable spawn biome found within {} blocks, keeping {}", MAX_RADIUS, current); - return; - } - - int y = level.getHeight(Heightmap.Types.WORLD_SURFACE_WG, found.getX(), found.getZ()); - BlockPos spawn = new BlockPos(found.getX(), y, found.getZ()); - level.setDefaultSpawnPos(spawn, 0.0f); - CustomOreGenMod.LOGGER.info("Latitude: spawn point set to {} ({})", spawn, - level.getBiome(spawn).unwrapKey().map(Object::toString).orElse("?")); - } - - private static boolean isSpawnBiomeAtSurface(ServerLevel level, int x, int z) { - Holder biome = level.getBiome(new BlockPos(x, SURFACE_Y, z)); - return biome.unwrapKey().map(SPAWN_BIOMES::contains).orElse(false); - } - - private static BlockPos findSpawnBiome(ServerLevel level) { - // Concentric square rings starting from the origin. We probe at SURFACE_Y because the - // latitude biome at y=0 can legitimately differ from the surface biome. - for (int radius = 0; radius <= MAX_RADIUS; radius += STEP) { - for (int x = -radius; x <= radius; x += STEP) { - for (int z = -radius; z <= radius; z += STEP) { - // Only scan the outer ring of each pass to avoid re-checking inner cells. - if (Math.abs(x) != radius && Math.abs(z) != radius && radius != 0) { - continue; - } - if (isSpawnBiomeAtSurface(level, x, z)) { - return new BlockPos(x, 0, z); - } - } - } - } - return null; - } -} diff --git a/src/main/java/net/mcreator/customoregen/worldgen/LatitudeZonePlacement.java b/src/main/java/net/mcreator/customoregen/worldgen/LatitudeZonePlacement.java new file mode 100644 index 00000000..05ce8720 --- /dev/null +++ b/src/main/java/net/mcreator/customoregen/worldgen/LatitudeZonePlacement.java @@ -0,0 +1,77 @@ +package net.mcreator.customoregen.worldgen; + +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.levelgen.placement.PlacementContext; +import net.minecraft.world.level.levelgen.placement.PlacementFilter; +import net.minecraft.world.level.levelgen.placement.PlacementModifierType; + +/** + * Placement modifier that filters ore placement by Z coordinate (latitude zone). + * + *

When the player's Z position is in the configured zone, the ore is placed; otherwise it is + * skipped. This replaces the biome-tag-based approach and works universally with any biome mod + * (BOP, Terralith, etc.) without needing to classify every biome manually.

+ * + *

Three zones exist: + *

    + *
  • {@code COLD}: Z < {@code coldThreshold} (negative Z, north)
  • + *
  • {@code HOT}: Z > {@code hotThreshold} (positive Z, south)
  • + *
  • {@code TEMPERATE}: between the two thresholds
  • + *
+ * + *

Registered as placement-modifier type {@code custom_ore_gen:latitude_zone}.

+ */ +public class LatitudeZonePlacement extends PlacementFilter { + + public enum Zone { + COLD("cold"), + HOT("hot"), + TEMPERATE("temperate"); + + private final String serializedName; + Zone(String name) { this.serializedName = name; } + public String getSerializedName() { return serializedName; } + + public static Zone byName(String name) { + for (Zone z : values()) { + if (z.serializedName.equals(name)) return z; + } + return TEMPERATE; + } + } + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( + instance -> instance.group( + com.mojang.serialization.Codec.STRING.fieldOf("zone") + .xmap(Zone::byName, Zone::getSerializedName) + .forGetter(p -> p.zone) + ).apply(instance, instance.stable(LatitudeZonePlacement::new)) + ); + + private final Zone zone; + + public LatitudeZonePlacement(Zone zone) { + this.zone = zone; + } + + @Override + protected boolean shouldPlace(PlacementContext context, RandomSource random, BlockPos pos) { + int z = pos.getZ(); + int coldZ = LatitudeConfig.getColdZoneZ(); + int hotZ = LatitudeConfig.getHotZoneZ(); + + return switch (zone) { + case COLD -> z < coldZ; + case HOT -> z > hotZ; + case TEMPERATE -> z >= coldZ && z <= hotZ; + }; + } + + @Override + public PlacementModifierType type() { + return WorldGenRegistration.LATITUDE_ZONE_PLACEMENT.value(); + } +} diff --git a/src/main/java/net/mcreator/customoregen/worldgen/OreAuditHandler.java b/src/main/java/net/mcreator/customoregen/worldgen/OreAuditHandler.java deleted file mode 100644 index 1661a53a..00000000 --- a/src/main/java/net/mcreator/customoregen/worldgen/OreAuditHandler.java +++ /dev/null @@ -1,134 +0,0 @@ -package net.mcreator.customoregen.worldgen; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Holder; -import net.minecraft.core.registries.Registries; -import net.minecraft.resources.ResourceKey; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.block.Block; -import net.neoforged.bus.api.SubscribeEvent; -import net.neoforged.fml.common.EventBusSubscriber; -import net.neoforged.neoforge.event.server.ServerStartedEvent; - -import net.mcreator.customoregen.CustomOreGenMod; -import net.mcreator.customoregen.init.CustomOreGenModBlocks; - -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * Temporary diagnostic: only active when a {@code .oreaudit} marker file exists in the - * server working directory (create it to run the audit, delete it afterwards). On server - * start it forces real chunk generation in a grid around the origin, counts custom ore blocks - * per surface biome, writes {@code ore_audit_report.txt}, and then stops the server. - * - *

Warning: this handler calls {@code System.exit(0)} at the end of the audit. It is - * therefore a developer-only utility that must never be enabled in production. The - * equivalent, non-destructive proof that ores place in every biome is covered by - * {@link LatitudeGameTest} (run with {@code ./gradlew runGameTestServer}).

- */ -@EventBusSubscriber -public class OreAuditHandler { - - private static final int CHUNKS_PER_AXIS = 12; // 12x12 chunks = 192x192 blocks - private static final int Y_MIN = -8; - private static final int Y_MAX = 32; - - @SubscribeEvent - public static void onServerStarted(ServerStartedEvent event) { - Path flag = Path.of(".oreaudit"); - if (!java.nio.file.Files.exists(flag)) { - return; - } - MinecraftServer server = event.getServer(); - new Thread(() -> runAudit(server), "ore-audit").start(); - } - - private static void runAudit(MinecraftServer server) { - try { - Thread.sleep(2000); // let the server settle - ServerLevel overworld = server.overworld(); - - // Pre-generate chunks in a grid so features are placed. - CustomOreGenMod.LOGGER.info("[ore-audit] Generating {}x{} chunks...", CHUNKS_PER_AXIS, CHUNKS_PER_AXIS); - for (int cx = 0; cx < CHUNKS_PER_AXIS; cx++) { - for (int cz = 0; cz < CHUNKS_PER_AXIS; cz++) { - overworld.getChunk(cx, cz); - } - } - CustomOreGenMod.LOGGER.info("[ore-audit] Chunks generated, scanning ores..."); - - // Map: biome -> ore block -> count - Map> byBiome = new LinkedHashMap<>(); - int[] shardTotal = {0}; - int[] ironTotal = {0}; - int[] coalTotal = {0}; - - Block shardSurface = CustomOreGenModBlocks.SHARDDIAMONDBLOCKORE.get(); - Block shardDeep = CustomOreGenModBlocks.DEEPSLATESHARDDIAMONDORE.get(); - Block ironSurface = CustomOreGenModBlocks.IRONORE.get(); - Block ironDeep = CustomOreGenModBlocks.DEEPSLATEIRONORE.get(); - Block coal = CustomOreGenModBlocks.CONCENTRATEDCOALORE.get(); - - for (int cx = 0; cx < CHUNKS_PER_AXIS; cx++) { - for (int cz = 0; cz < CHUNKS_PER_AXIS; cz++) { - int baseX = cx << 4; - int baseZ = cz << 4; - for (int x = 0; x < 16; x++) { - for (int z = 0; z < 16; z++) { - Holder biomeHolder = overworld.getBiome(new BlockPos(baseX + x, 64, baseZ + z)); - String biomeKey = biomeHolder.unwrapKey() - .map(k -> k.location().toString()).orElse("unknown"); - Map ores = byBiome.computeIfAbsent(biomeKey, k -> new LinkedHashMap<>()); - for (int y = Y_MIN; y <= Y_MAX; y++) { - Block b = overworld.getBlockState(new BlockPos(baseX + x, y, baseZ + z)).getBlock(); - String name = null; - if (b == shardSurface) { name = "shard_diamond"; shardTotal[0]++; } - else if (b == shardDeep) { name = "deepslate_shard_diamond"; shardTotal[0]++; } - else if (b == ironSurface) { name = "iron"; ironTotal[0]++; } - else if (b == ironDeep) { name = "deepslate_iron"; ironTotal[0]++; } - else if (b == coal) { name = "concentrated_coal"; coalTotal[0]++; } - if (name != null) ores.merge(name, 1, Integer::sum); - } - } - } - } - } - - StringBuilder r = new StringBuilder(); - r.append("=== ORE AUDIT (real chunk generation) ===\n"); - r.append(String.format("Scanned %dx%d chunks, Y=%d..%d%n", CHUNKS_PER_AXIS, CHUNKS_PER_AXIS, Y_MIN, Y_MAX)); - r.append(String.format("Totals: shard=%d iron=%d coal=%d%n%n", shardTotal[0], ironTotal[0], coalTotal[0])); - r.append("Per biome (only biomes with >=1 ore shown):\n"); - for (var e : byBiome.entrySet()) { - if (e.getValue().isEmpty()) continue; - r.append(String.format(" %-40s %s%n", e.getKey(), e.getValue())); - } - r.append("\nBiomes with ZERO ores (sampled):\n"); - int zeroCount = 0; - for (var e : byBiome.entrySet()) { - if (e.getValue().isEmpty()) { - r.append(" ").append(e.getKey()).append("\n"); - zeroCount++; - } - } - if (zeroCount == 0) r.append(" (none - every sampled biome has ores)\n"); - - Path out = Path.of("ore_audit_report.txt"); - Files.writeString(out, r.toString()); - CustomOreGenMod.LOGGER.info("[ore-audit] Report written to {}", out.toAbsolutePath()); - CustomOreGenMod.LOGGER.info("[ore-audit] Totals: shard={} iron={} coal={}", shardTotal[0], ironTotal[0], coalTotal[0]); - CustomOreGenMod.LOGGER.info("[ore-audit] Biomes with ores: {}, biomes with zero: {}", - byBiome.values().stream().filter(m -> !m.isEmpty()).count(), zeroCount); - } catch (Throwable t) { - CustomOreGenMod.LOGGER.error("[ore-audit] failed", t); - } finally { - try { Thread.sleep(1000); } catch (InterruptedException ignored) {} - System.exit(0); - } - } -} diff --git a/src/main/java/net/mcreator/customoregen/worldgen/WorldGenRegistration.java b/src/main/java/net/mcreator/customoregen/worldgen/WorldGenRegistration.java index 7490c689..1061b5b4 100644 --- a/src/main/java/net/mcreator/customoregen/worldgen/WorldGenRegistration.java +++ b/src/main/java/net/mcreator/customoregen/worldgen/WorldGenRegistration.java @@ -2,7 +2,8 @@ package net.mcreator.customoregen.worldgen; import com.mojang.serialization.MapCodec; import net.minecraft.core.registries.Registries; -import net.minecraft.world.level.biome.BiomeSource; +import net.minecraft.world.level.levelgen.DensityFunction; +import net.minecraft.world.level.levelgen.placement.PlacementModifierType; import net.neoforged.neoforge.common.world.BiomeModifier; import net.neoforged.neoforge.registries.DeferredHolder; import net.neoforged.neoforge.registries.DeferredRegister; @@ -10,23 +11,24 @@ import net.neoforged.neoforge.registries.NeoForgeRegistries; /** * Registration of custom worldgen codecs used by the mod. - * - *
    - *
  • {@code latitude} — the custom latitude {@link BiomeSource} codec - * referenced from world presets.
  • - *
  • {@code config_gated_features} — a {@link BiomeModifier} type that - * only adds ore features when their config toggle is enabled.
  • - *
*/ public class WorldGenRegistration { - public static final DeferredRegister> BIOME_SOURCES = - DeferredRegister.create(Registries.BIOME_SOURCE, "custom_ore_gen"); + /** Custom density-function types. */ + public static final DeferredRegister> DENSITY_FUNCTION_TYPES = + DeferredRegister.create(Registries.DENSITY_FUNCTION_TYPE, "custom_ore_gen"); - public static final DeferredHolder, MapCodec> LATITUDE = - BIOME_SOURCES.register("latitude", () -> LatitudeBiomeSource.CODEC); + public static final DeferredHolder, MapCodec> LATITUDE_SIGNAL = + DENSITY_FUNCTION_TYPES.register("latitude_signal", () -> LatitudeSignalDensityFunction.DATA_CODEC); - /** Serializer registry for config-gated biome modifiers (see {@link ConfigGatedFeaturesModifier}). */ + /** Custom placement-modifier types (Z-coordinate-based ore filtering). */ + public static final DeferredRegister> PLACEMENT_MODIFIERS = + DeferredRegister.create(Registries.PLACEMENT_MODIFIER_TYPE, "custom_ore_gen"); + + public static final DeferredHolder, PlacementModifierType> LATITUDE_ZONE_PLACEMENT = + PLACEMENT_MODIFIERS.register("latitude_zone", () -> () -> LatitudeZonePlacement.CODEC); + + /** Serializer registry for config-gated biome modifiers. */ public static final DeferredRegister> BIOME_MODIFIER_SERIALIZERS = DeferredRegister.create(NeoForgeRegistries.Keys.BIOME_MODIFIER_SERIALIZERS, "custom_ore_gen"); diff --git a/src/main/resources/META-INF/neoforge.mods.toml b/src/main/resources/META-INF/neoforge.mods.toml index 522967d1..d419a3dd 100644 --- a/src/main/resources/META-INF/neoforge.mods.toml +++ b/src/main/resources/META-INF/neoforge.mods.toml @@ -23,6 +23,14 @@ description='''${mod_description}''' # Start of user code block dependencies configuration + +[[dependencies."${mod_id}"]] + modId="mr_lithosphere" + mandatory=true + versionRange="[1.7,)" + ordering="AFTER" + side="BOTH" + # Note: optional mods (biomesoplenty, create, mekanism) are intentionally NOT declared # here. Optional integration is handled via data tags with "required": false entries # (see data/custom_ore_gen/tags/worldgen/biome/latitude_*_surface.json) and via @@ -30,3 +38,7 @@ description='''${mod_description}''' # absent. Declaring them here with mandatory=false + versionRange caused NeoForge to # fail loading when the mods were not installed (see commit history). # End of user code block dependencies configuration + +# Mixin configuration +[[mixins]] +config = "custom_ore_gen.mixins.json" diff --git a/src/main/resources/custom_ore_gen.mixins.json b/src/main/resources/custom_ore_gen.mixins.json new file mode 100644 index 00000000..d18cf7d5 --- /dev/null +++ b/src/main/resources/custom_ore_gen.mixins.json @@ -0,0 +1,15 @@ +{ + "required": true, + "minVersion": "0.8.5", + "package": "net.mcreator.customoregen.mixin", + "compatibilityLevel": "JAVA_21", + "refmap": "custom_ore_gen.refmap.json", + "mixins": [ + "MultiNoiseBiomeSourceMixin" + ], + "client": [], + "server": [], + "injectors": { + "defaultRequire": 1 + } +} \ No newline at end of file diff --git a/src/main/resources/data/custom_ore_gen/neoforge/biome_modifier/add_cold_biomes_ores.json b/src/main/resources/data/custom_ore_gen/neoforge/biome_modifier/add_cold_biomes_ores.json index 4ce08da5..4eccb428 100644 --- a/src/main/resources/data/custom_ore_gen/neoforge/biome_modifier/add_cold_biomes_ores.json +++ b/src/main/resources/data/custom_ore_gen/neoforge/biome_modifier/add_cold_biomes_ores.json @@ -1,20 +1,22 @@ { - "type": "custom_ore_gen:config_gated_features", - "biomes": "#custom_ore_gen:latitude_cold_surface", - "step": "underground_ores", - "gate_groups": [ - { - "toggle": "vanillaOreVariants", - "features": [ - "custom_ore_gen:lapisore", - "custom_ore_gen:deepslatelapisore" - ] - }, - { - "toggle": "concentratedOres", - "features": [ - "custom_ore_gen:deepslatediamondore" - ] - } - ] -} + "type": "custom_ore_gen:config_gated_features", + "biomes": { + "type": "neoforge:any" + }, + "step": "underground_ores", + "gate_groups": [ + { + "toggle": "vanillaOreVariants", + "features": [ + "custom_ore_gen:lapisore", + "custom_ore_gen:deepslatelapisore" + ] + }, + { + "toggle": "concentratedOres", + "features": [ + "custom_ore_gen:deepslatediamondore" + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/custom_ore_gen/neoforge/biome_modifier/add_hot_biomes_ores.json b/src/main/resources/data/custom_ore_gen/neoforge/biome_modifier/add_hot_biomes_ores.json index acaf9007..211ef031 100644 --- a/src/main/resources/data/custom_ore_gen/neoforge/biome_modifier/add_hot_biomes_ores.json +++ b/src/main/resources/data/custom_ore_gen/neoforge/biome_modifier/add_hot_biomes_ores.json @@ -1,28 +1,30 @@ { - "type": "custom_ore_gen:config_gated_features", - "biomes": "#custom_ore_gen:latitude_hot_surface", - "step": "underground_ores", - "gate_groups": [ - { - "toggle": "pureGoldenOre", - "features": [ - "custom_ore_gen:puregoldenore", - "custom_ore_gen:deepslatepuregoldenore" - ] - }, - { - "toggle": "customCopperOres", - "features": [ - "custom_ore_gen:copperhighore", - "custom_ore_gen:copperlowerore" - ] - }, - { - "toggle": "vanillaOreVariants", - "features": [ - "custom_ore_gen:redstoneore", - "custom_ore_gen:deepslateredstoneore" - ] - } - ] -} + "type": "custom_ore_gen:config_gated_features", + "biomes": { + "type": "neoforge:any" + }, + "step": "underground_ores", + "gate_groups": [ + { + "toggle": "pureGoldenOre", + "features": [ + "custom_ore_gen:puregoldenore", + "custom_ore_gen:deepslatepuregoldenore" + ] + }, + { + "toggle": "customCopperOres", + "features": [ + "custom_ore_gen:copperhighore", + "custom_ore_gen:copperlowerore" + ] + }, + { + "toggle": "vanillaOreVariants", + "features": [ + "custom_ore_gen:redstoneore", + "custom_ore_gen:deepslateredstoneore" + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/custom_ore_gen/neoforge/biome_modifier/add_mountain_biomes_ores.json b/src/main/resources/data/custom_ore_gen/neoforge/biome_modifier/add_mountain_biomes_ores.json index 7180b6da..0b41211c 100644 --- a/src/main/resources/data/custom_ore_gen/neoforge/biome_modifier/add_mountain_biomes_ores.json +++ b/src/main/resources/data/custom_ore_gen/neoforge/biome_modifier/add_mountain_biomes_ores.json @@ -1,13 +1,13 @@ { - "type": "custom_ore_gen:config_gated_features", - "biomes": "#custom_ore_gen:mountain_biomes", - "step": "underground_ores", - "gate_groups": [ - { - "toggle": "customEmeraldOres", - "features": [ - "custom_ore_gen:highemeraldore" - ] - } - ] -} + "type": "custom_ore_gen:config_gated_features", + "biomes": "#custom_ore_gen:mountain_biomes", + "step": "underground_ores", + "gate_groups": [ + { + "toggle": "customEmeraldOres", + "features": [ + "custom_ore_gen:highemeraldore" + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/custom_ore_gen/neoforge/biome_modifier/add_rare_biomes_ores.json b/src/main/resources/data/custom_ore_gen/neoforge/biome_modifier/add_rare_biomes_ores.json index 092abef8..7bf08c0e 100644 --- a/src/main/resources/data/custom_ore_gen/neoforge/biome_modifier/add_rare_biomes_ores.json +++ b/src/main/resources/data/custom_ore_gen/neoforge/biome_modifier/add_rare_biomes_ores.json @@ -1,13 +1,13 @@ { - "type": "custom_ore_gen:config_gated_features", - "biomes": "#custom_ore_gen:rare_biomes", - "step": "underground_ores", - "gate_groups": [ - { - "toggle": "customEmeraldOres", - "features": [ - "custom_ore_gen:loweremeraldore" - ] - } - ] -} + "type": "custom_ore_gen:config_gated_features", + "biomes": "#custom_ore_gen:rare_biomes", + "step": "underground_ores", + "gate_groups": [ + { + "toggle": "customEmeraldOres", + "features": [ + "custom_ore_gen:loweremeraldore" + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/custom_ore_gen/neoforge/biome_modifier/add_shard_diamond_ores.json b/src/main/resources/data/custom_ore_gen/neoforge/biome_modifier/add_shard_diamond_ores.json index f1cd560d..bc388c31 100644 --- a/src/main/resources/data/custom_ore_gen/neoforge/biome_modifier/add_shard_diamond_ores.json +++ b/src/main/resources/data/custom_ore_gen/neoforge/biome_modifier/add_shard_diamond_ores.json @@ -1,16 +1,16 @@ { - "type": "custom_ore_gen:config_gated_features", - "biomes": { - "type": "neoforge:any" - }, - "step": "underground_ores", - "gate_groups": [ - { - "toggle": "shardDiamondOre", - "features": [ - "custom_ore_gen:sharddiamondblockore", - "custom_ore_gen:deepslatesharddiamondore" - ] - } - ] -} + "type": "custom_ore_gen:config_gated_features", + "biomes": { + "type": "neoforge:any" + }, + "step": "underground_ores", + "gate_groups": [ + { + "toggle": "shardDiamondOre", + "features": [ + "custom_ore_gen:sharddiamondblockore", + "custom_ore_gen:deepslatesharddiamondore" + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/custom_ore_gen/neoforge/biome_modifier/add_tempered_biomes_ores.json b/src/main/resources/data/custom_ore_gen/neoforge/biome_modifier/add_tempered_biomes_ores.json index eba33dd5..d5a7aed0 100644 --- a/src/main/resources/data/custom_ore_gen/neoforge/biome_modifier/add_tempered_biomes_ores.json +++ b/src/main/resources/data/custom_ore_gen/neoforge/biome_modifier/add_tempered_biomes_ores.json @@ -1,20 +1,22 @@ { - "type": "custom_ore_gen:config_gated_features", - "biomes": "#custom_ore_gen:latitude_temperate_surface", - "step": "underground_ores", - "gate_groups": [ - { - "toggle": "impureOres", - "features": [ - "custom_ore_gen:ironore", - "custom_ore_gen:deepslateironore" - ] - }, - { - "toggle": "concentratedOres", - "features": [ - "custom_ore_gen:concentratedcoalore" - ] - } - ] -} + "type": "custom_ore_gen:config_gated_features", + "biomes": { + "type": "neoforge:any" + }, + "step": "underground_ores", + "gate_groups": [ + { + "toggle": "impureOres", + "features": [ + "custom_ore_gen:ironore", + "custom_ore_gen:deepslateironore" + ] + }, + { + "toggle": "concentratedOres", + "features": [ + "custom_ore_gen:concentratedcoalore" + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/custom_ore_gen/neoforge/biome_modifier/remove_vanilla_ores.json b/src/main/resources/data/custom_ore_gen/neoforge/biome_modifier/z_remove_vanilla_ores.json similarity index 85% rename from src/main/resources/data/custom_ore_gen/neoforge/biome_modifier/remove_vanilla_ores.json rename to src/main/resources/data/custom_ore_gen/neoforge/biome_modifier/z_remove_vanilla_ores.json index 6c0db785..9e90f4cb 100644 --- a/src/main/resources/data/custom_ore_gen/neoforge/biome_modifier/remove_vanilla_ores.json +++ b/src/main/resources/data/custom_ore_gen/neoforge/biome_modifier/z_remove_vanilla_ores.json @@ -5,18 +5,21 @@ "minecraft:ore_coal_lower", "minecraft:ore_coal_upper", "minecraft:ore_copper_large", - "minecraft:ore_diamond_large", - "minecraft:ore_emerald", - "minecraft:ore_gold", - "minecraft:ore_iron_small", - "minecraft:ore_iron_middle", - "minecraft:ore_lapis_buried", - "minecraft:ore_lapis", - "minecraft:ore_redstone", "minecraft:ore_copper", "minecraft:ore_diamond", + "minecraft:ore_diamond_buried", + "minecraft:ore_diamond_large", + "minecraft:ore_diamond_medium", + "minecraft:ore_emerald", + "minecraft:ore_gold", + "minecraft:ore_gold_extra", "minecraft:ore_gold_lower", + "minecraft:ore_iron_middle", + "minecraft:ore_iron_small", "minecraft:ore_iron_upper", + "minecraft:ore_lapis", + "minecraft:ore_lapis_buried", + "minecraft:ore_redstone", "minecraft:ore_redstone_lower" ], "step": "underground_ores" diff --git a/src/main/resources/data/custom_ore_gen/tags/worldgen/biome/cold_biomes.json b/src/main/resources/data/custom_ore_gen/tags/worldgen/biome/cold_biomes.json deleted file mode 100644 index 39da56a9..00000000 --- a/src/main/resources/data/custom_ore_gen/tags/worldgen/biome/cold_biomes.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "replace": false, - "values": [ - "minecraft:taiga", - "minecraft:frozen_ocean", - "minecraft:frozen_river", - "minecraft:snowy_plains", - "minecraft:snowy_beach", - "minecraft:snowy_taiga", - "minecraft:old_growth_pine_taiga", - "minecraft:grove", - "minecraft:snowy_slopes", - "minecraft:jagged_peaks", - "minecraft:frozen_peaks", - "minecraft:cold_ocean", - "minecraft:deep_cold_ocean", - "minecraft:deep_frozen_ocean", - "minecraft:ice_spikes", - { - "id": "biomesoplenty:auroral_garden", - "required": false - }, - { - "id": "biomesoplenty:cold_desert", - "required": false - }, - { - "id": "biomesoplenty:maple_woods", - "required": false - }, - { - "id": "biomesoplenty:dead_forest", - "required": false - }, - { - "id": "biomesoplenty:tundra", - "required": false - }, - { - "id": "biomesoplenty:bog", - "required": false - }, - { - "id": "biomesoplenty:muskeg", - "required": false - }, - { - "id": "biomesoplenty:old_growth_dead_forest", - "required": false - }, - { - "id": "biomesoplenty:snowblossom_grove", - "required": false - }, - { - "id": "biomesoplenty:snowy_coniferous_forest", - "required": false - }, - { - "id": "biomesoplenty:snowy_fir_clearing", - "required": false - }, - { - "id": "biomesoplenty:snowy_maple_woods", - "required": false - } - ] -} \ No newline at end of file diff --git a/src/main/resources/data/custom_ore_gen/tags/worldgen/biome/hot_biomes.json b/src/main/resources/data/custom_ore_gen/tags/worldgen/biome/hot_biomes.json deleted file mode 100644 index 531a7ae4..00000000 --- a/src/main/resources/data/custom_ore_gen/tags/worldgen/biome/hot_biomes.json +++ /dev/null @@ -1,106 +0,0 @@ -{ - "replace": false, - "values": [ - "minecraft:desert", - "minecraft:jungle", - "minecraft:sparse_jungle", - "minecraft:savanna", - "minecraft:savanna_plateau", - "minecraft:stony_peaks", - "minecraft:warm_ocean", - "minecraft:windswept_savanna", - "minecraft:eroded_badlands", - "minecraft:bamboo_jungle", - "minecraft:mangrove_swamp", - "minecraft:badlands", - "minecraft:wooded_badlands", - { - "id": "biomesoplenty:bayou", - "required": false - }, - { - "id": "biomesoplenty:dryland", - "required": false - }, - { - "id": "biomesoplenty:dune_beach", - "required": false - }, - { - "id": "biomesoplenty:mystic_grove", - "required": false - }, - { - "id": "biomesoplenty:jade_cliffs", - "required": false - }, - { - "id": "biomesoplenty:lavender_field", - "required": false - }, - { - "id": "biomesoplenty:lavender_forest", - "required": false - }, - { - "id": "biomesoplenty:mediterranean_forest", - "required": false - }, - { - "id": "biomesoplenty:orchard", - "required": false - }, - { - "id": "biomesoplenty:pasture", - "required": false - }, - { - "id": "biomesoplenty:prairie", - "required": false - }, - { - "id": "biomesoplenty:lush_desert", - "required": false - }, - { - "id": "biomesoplenty:lush_savanna", - "required": false - }, - { - "id": "biomesoplenty:fungal_jungle", - "required": false - }, - { - "id": "biomesoplenty:floodplain", - "required": false - }, - { - "id": "biomesoplenty:rainforest", - "required": false - }, - { - "id": "biomesoplenty:rocky_rainforest", - "required": false - }, - { - "id": "biomesoplenty:tropics", - "required": false - }, - { - "id": "biomesoplenty:volcanic_plains", - "required": false - }, - { - "id": "biomesoplenty:volcano", - "required": false - }, - { - "id": "biomesoplenty:wasteland", - "required": false - }, - { - "id": "biomesoplenty:erupting_inferno", - "required": false - } - ] -} \ No newline at end of file diff --git a/src/main/resources/data/custom_ore_gen/tags/worldgen/biome/latitude_cold_surface.json b/src/main/resources/data/custom_ore_gen/tags/worldgen/biome/latitude_cold_surface.json index 54c3ccc8..97aa47ea 100644 --- a/src/main/resources/data/custom_ore_gen/tags/worldgen/biome/latitude_cold_surface.json +++ b/src/main/resources/data/custom_ore_gen/tags/worldgen/biome/latitude_cold_surface.json @@ -7,8 +7,6 @@ "minecraft:taiga", "minecraft:old_growth_pine_taiga", "minecraft:old_growth_spruce_taiga", - "minecraft:windswept_hills", - "minecraft:windswept_gravelly_hills", "minecraft:grove", "minecraft:snowy_slopes", { @@ -60,20 +58,14 @@ "required": false }, { - "id": "biomesoplenty:coniferous_forest", + "id": "biomesoplenty:hot_springs", "required": false }, { - "id": "biomesoplenty:fir_clearing", + "id": "biomesoplenty:ominous_woods", "required": false }, - { - "id": "biomesoplenty:seasonal_forest", - "required": false - }, - { - "id": "biomesoplenty:seasonal_orchard", - "required": false - } + "minecraft:jagged_peaks", + "minecraft:frozen_peaks" ] -} +} \ No newline at end of file diff --git a/src/main/resources/data/custom_ore_gen/tags/worldgen/biome/latitude_hot_surface.json b/src/main/resources/data/custom_ore_gen/tags/worldgen/biome/latitude_hot_surface.json index 1db1e339..b8d74338 100644 --- a/src/main/resources/data/custom_ore_gen/tags/worldgen/biome/latitude_hot_surface.json +++ b/src/main/resources/data/custom_ore_gen/tags/worldgen/biome/latitude_hot_surface.json @@ -15,14 +15,6 @@ "id": "biomesoplenty:dryland", "required": false }, - { - "id": "biomesoplenty:dune_beach", - "required": false - }, - { - "id": "biomesoplenty:bayou", - "required": false - }, { "id": "biomesoplenty:fungal_jungle", "required": false @@ -48,12 +40,32 @@ "required": false }, { - "id": "biomesoplenty:rocky_shrubland", + "id": "biomesoplenty:bayou", "required": false }, { - "id": "biomesoplenty:jade_cliffs", + "id": "biomesoplenty:lush_desert", + "required": false + }, + { + "id": "biomesoplenty:lush_savanna", + "required": false + }, + { + "id": "biomesoplenty:volcanic_plains", + "required": false + }, + { + "id": "biomesoplenty:volcano", + "required": false + }, + { + "id": "biomesoplenty:wasteland", + "required": false + }, + { + "id": "biomesoplenty:wasteland_steppe", "required": false } ] -} +} \ No newline at end of file diff --git a/src/main/resources/data/custom_ore_gen/tags/worldgen/biome/latitude_temperate_surface.json b/src/main/resources/data/custom_ore_gen/tags/worldgen/biome/latitude_temperate_surface.json index 1af235c7..7fe27f60 100644 --- a/src/main/resources/data/custom_ore_gen/tags/worldgen/biome/latitude_temperate_surface.json +++ b/src/main/resources/data/custom_ore_gen/tags/worldgen/biome/latitude_temperate_surface.json @@ -90,6 +90,64 @@ { "id": "biomesoplenty:origin_valley", "required": false + }, + "minecraft:windswept_hills", + "minecraft:windswept_gravelly_hills", + { + "id": "biomesoplenty:seasonal_forest", + "required": false + }, + { + "id": "biomesoplenty:seasonal_orchard", + "required": false + }, + { + "id": "biomesoplenty:prairie", + "required": false + }, + { + "id": "biomesoplenty:coniferous_forest", + "required": false + }, + { + "id": "biomesoplenty:fir_clearing", + "required": false + }, + { + "id": "biomesoplenty:jade_cliffs", + "required": false + }, + { + "id": "biomesoplenty:rocky_shrubland", + "required": false + }, + { + "id": "biomesoplenty:aspen_glade", + "required": false + }, + { + "id": "biomesoplenty:gravel_beach", + "required": false + }, + { + "id": "biomesoplenty:highland", + "required": false + }, + { + "id": "biomesoplenty:jacaranda_glade", + "required": false + }, + { + "id": "biomesoplenty:overgrown_greens", + "required": false + }, + { + "id": "biomesoplenty:pasture", + "required": false + }, + { + "id": "biomesoplenty:wintry_origin_valley", + "required": false } ] -} +} \ No newline at end of file diff --git a/src/main/resources/data/custom_ore_gen/tags/worldgen/biome/mountain_biomes.json b/src/main/resources/data/custom_ore_gen/tags/worldgen/biome/mountain_biomes.json index 21c809f0..4d088691 100644 --- a/src/main/resources/data/custom_ore_gen/tags/worldgen/biome/mountain_biomes.json +++ b/src/main/resources/data/custom_ore_gen/tags/worldgen/biome/mountain_biomes.json @@ -4,9 +4,6 @@ "minecraft:jagged_peaks", "minecraft:frozen_peaks", "minecraft:stony_peaks", - "minecraft:savanna_plateau", - "minecraft:wooded_badlands", - "minecraft:meadow", "minecraft:grove", "minecraft:snowy_slopes", { diff --git a/src/main/resources/data/custom_ore_gen/tags/worldgen/biome/rare_biomes.json b/src/main/resources/data/custom_ore_gen/tags/worldgen/biome/rare_biomes.json index c4b7c6b9..669e7fe9 100644 --- a/src/main/resources/data/custom_ore_gen/tags/worldgen/biome/rare_biomes.json +++ b/src/main/resources/data/custom_ore_gen/tags/worldgen/biome/rare_biomes.json @@ -3,7 +3,6 @@ "values": [ "minecraft:mushroom_fields", "minecraft:sparse_jungle", - "minecraft:savanna_plateau", "minecraft:sunflower_plains", "minecraft:windswept_gravelly_hills", "minecraft:flower_forest", diff --git a/src/main/resources/data/custom_ore_gen/tags/worldgen/biome/tempered_biomes.json b/src/main/resources/data/custom_ore_gen/tags/worldgen/biome/tempered_biomes.json deleted file mode 100644 index 228ca0a5..00000000 --- a/src/main/resources/data/custom_ore_gen/tags/worldgen/biome/tempered_biomes.json +++ /dev/null @@ -1,109 +0,0 @@ -{ - "replace": false, - "values": [ - "minecraft:plains", - "minecraft:meadow", - "minecraft:sunflower_plains", - "minecraft:forest", - "minecraft:birch_forest", - "minecraft:swamp", - "minecraft:taiga", - "minecraft:old_growth_pine_taiga", - "minecraft:river", - "minecraft:beach", - "minecraft:stony_shore", - "minecraft:ocean", - "minecraft:lukewarm_ocean", - "minecraft:deep_ocean", - "minecraft:deep_lukewarm_ocean", - "minecraft:dripstone_caves", - "minecraft:lush_caves", - { - "id": "biomesoplenty:coniferous_forest", - "required": false - }, - { - "id": "biomesoplenty:fir_clearing", - "required": false - }, - { - "id": "biomesoplenty:field", - "required": false - }, - { - "id": "biomesoplenty:forested_field", - "required": false - }, - { - "id": "biomesoplenty:seasonal_forest", - "required": false - }, - { - "id": "biomesoplenty:seasonal_orchard", - "required": false - }, - { - "id": "biomesoplenty:pumpkin_patch", - "required": false - }, - { - "id": "biomesoplenty:grassland", - "required": false - }, - { - "id": "biomesoplenty:spider_nest", - "required": false - }, - { - "id": "biomesoplenty:moor", - "required": false - }, - { - "id": "biomesoplenty:origin_valley", - "required": false - }, - { - "id": "biomesoplenty:shrubland", - "required": false - }, - { - "id": "biomesoplenty:wetland", - "required": false - }, - { - "id": "biomesoplenty:clover_patch", - "required": false - }, - { - "id": "biomesoplenty:redwood_forest", - "required": false - }, - { - "id": "biomesoplenty:rocky_shrubland", - "required": false - }, - { - "id": "biomesoplenty:scrubland", - "required": false - }, - { - "id": "biomesoplenty:woodland", - "required": false - }, - { - "id": "biomesoplenty:old_growth_woodland", - "required": false - }, - { - "id": "biomesoplenty:marsh", - "required": false - }, - { - "id": "biomesoplenty:undergrowth", - "required": false - }, - "minecraft:cherry_grove", - "minecraft:windswept_hills", - "minecraft:windswept_forest" - ] -} \ No newline at end of file diff --git a/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/concentratedcoalore.json b/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/concentratedcoalore.json index ea47dcce..2ce236b2 100644 --- a/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/concentratedcoalore.json +++ b/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/concentratedcoalore.json @@ -10,7 +10,7 @@ "tag": "c:stones" }, "state": { - "Name": "custom_ore_gen:concentratedcoalore" + "Name": "minecraft:coal_ore" } } ] diff --git a/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/copperhighore.json b/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/copperhighore.json index 29e9537b..cc7e74df 100644 --- a/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/copperhighore.json +++ b/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/copperhighore.json @@ -7,12 +7,21 @@ { "target": { "predicate_type": "tag_match", - "tag": "c:stones" + "tag": "minecraft:stone_ore_replaceables" }, "state": { - "Name": "custom_ore_gen:copperhighore" + "Name": "minecraft:copper_ore" + } + }, + { + "target": { + "predicate_type": "tag_match", + "tag": "minecraft:deepslate_ore_replaceables" + }, + "state": { + "Name": "minecraft:deepslate_copper_ore" } } ] } -} \ No newline at end of file +} diff --git a/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/copperlowerore.json b/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/copperlowerore.json index 721b84e4..d3eb4720 100644 --- a/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/copperlowerore.json +++ b/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/copperlowerore.json @@ -7,12 +7,21 @@ { "target": { "predicate_type": "tag_match", - "tag": "c:stones" + "tag": "minecraft:stone_ore_replaceables" }, "state": { - "Name": "custom_ore_gen:copperlowerore" + "Name": "minecraft:copper_ore" + } + }, + { + "target": { + "predicate_type": "tag_match", + "tag": "minecraft:deepslate_ore_replaceables" + }, + "state": { + "Name": "minecraft:deepslate_copper_ore" } } ] } -} \ No newline at end of file +} diff --git a/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/deepslatediamondore.json b/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/deepslatediamondore.json index 11bacd17..b85e10e7 100644 --- a/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/deepslatediamondore.json +++ b/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/deepslatediamondore.json @@ -10,7 +10,7 @@ "tag": "c:stones" }, "state": { - "Name": "custom_ore_gen:deepslatediamondore" + "Name": "minecraft:deepslate_diamond_ore" } } ] diff --git a/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/deepslateironore.json b/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/deepslateironore.json index a9509ac5..e8e2f13a 100644 --- a/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/deepslateironore.json +++ b/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/deepslateironore.json @@ -10,7 +10,7 @@ "tag": "c:stones" }, "state": { - "Name": "custom_ore_gen:deepslateironore" + "Name": "minecraft:deepslate_iron_ore" } } ] diff --git a/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/deepslatelapisore.json b/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/deepslatelapisore.json index d340845e..4763089a 100644 --- a/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/deepslatelapisore.json +++ b/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/deepslatelapisore.json @@ -10,7 +10,7 @@ "tag": "c:stones" }, "state": { - "Name": "custom_ore_gen:deepslatelapisore" + "Name": "minecraft:deepslate_lapis_ore" } } ] diff --git a/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/deepslatepuregoldenore.json b/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/deepslatepuregoldenore.json index 1e0e12a4..59080bd3 100644 --- a/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/deepslatepuregoldenore.json +++ b/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/deepslatepuregoldenore.json @@ -10,7 +10,7 @@ "tag": "c:stones" }, "state": { - "Name": "custom_ore_gen:deepslatepuregoldenore" + "Name": "minecraft:deepslate_gold_ore" } } ] diff --git a/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/deepslateredstoneore.json b/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/deepslateredstoneore.json index 19666e6d..ad515f0b 100644 --- a/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/deepslateredstoneore.json +++ b/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/deepslateredstoneore.json @@ -10,7 +10,7 @@ "tag": "c:stones" }, "state": { - "Name": "custom_ore_gen:deepslateredstoneore" + "Name": "minecraft:deepslate_redstone_ore" } } ] diff --git a/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/highemeraldore.json b/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/highemeraldore.json index f21a7979..15743902 100644 --- a/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/highemeraldore.json +++ b/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/highemeraldore.json @@ -10,7 +10,7 @@ "tag": "c:stones" }, "state": { - "Name": "custom_ore_gen:highemeraldore" + "Name": "minecraft:emerald_ore" } } ] diff --git a/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/ironore.json b/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/ironore.json index 24a62efe..e1ade1f0 100644 --- a/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/ironore.json +++ b/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/ironore.json @@ -10,7 +10,7 @@ "tag": "c:stones" }, "state": { - "Name": "custom_ore_gen:ironore" + "Name": "minecraft:iron_ore" } } ] diff --git a/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/lapisore.json b/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/lapisore.json index ca8739b7..87ae677b 100644 --- a/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/lapisore.json +++ b/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/lapisore.json @@ -10,7 +10,7 @@ "tag": "c:stones" }, "state": { - "Name": "custom_ore_gen:lapisore" + "Name": "minecraft:lapis_ore" } } ] diff --git a/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/loweremeraldore.json b/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/loweremeraldore.json index 9d954666..15743902 100644 --- a/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/loweremeraldore.json +++ b/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/loweremeraldore.json @@ -10,7 +10,7 @@ "tag": "c:stones" }, "state": { - "Name": "custom_ore_gen:loweremeraldore" + "Name": "minecraft:emerald_ore" } } ] diff --git a/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/puregoldenore.json b/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/puregoldenore.json index 071dd436..227da301 100644 --- a/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/puregoldenore.json +++ b/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/puregoldenore.json @@ -10,7 +10,7 @@ "tag": "c:stones" }, "state": { - "Name": "custom_ore_gen:puregoldenore" + "Name": "minecraft:gold_ore" } } ] diff --git a/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/redstoneore.json b/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/redstoneore.json index 206c8e58..5b9eabc4 100644 --- a/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/redstoneore.json +++ b/src/main/resources/data/custom_ore_gen/worldgen/configured_feature/redstoneore.json @@ -10,7 +10,7 @@ "tag": "c:stones" }, "state": { - "Name": "custom_ore_gen:redstoneore" + "Name": "minecraft:redstone_ore" } } ] diff --git a/src/main/resources/data/custom_ore_gen/worldgen/density_function/latitude_signal.json b/src/main/resources/data/custom_ore_gen/worldgen/density_function/latitude_signal.json new file mode 100644 index 00000000..e96d9395 --- /dev/null +++ b/src/main/resources/data/custom_ore_gen/worldgen/density_function/latitude_signal.json @@ -0,0 +1,3 @@ +{ + "type": "custom_ore_gen:latitude_signal" +} diff --git a/src/main/resources/data/custom_ore_gen/worldgen/density_function/latitude_temperature.json b/src/main/resources/data/custom_ore_gen/worldgen/density_function/latitude_temperature.json new file mode 100644 index 00000000..4efe4469 --- /dev/null +++ b/src/main/resources/data/custom_ore_gen/worldgen/density_function/latitude_temperature.json @@ -0,0 +1,22 @@ +{ + "type": "minecraft:clamp", + "input": { + "type": "minecraft:add", + "argument1": "custom_ore_gen:latitude_signal", + "argument2": { + "type": "minecraft:mul", + "argument1": 0.15, + "argument2": { + "type": "minecraft:shifted_noise", + "noise": "minecraft:temperature", + "shift_x": "minecraft:shift_x", + "shift_y": 0.0, + "shift_z": "minecraft:shift_z", + "xz_scale": 0.04, + "y_scale": 0.0 + } + } + }, + "min": -1.0, + "max": 1.0 +} \ No newline at end of file diff --git a/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/concentratedcoalore.json b/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/concentratedcoalore.json index cb7d3226..7fc57830 100644 --- a/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/concentratedcoalore.json +++ b/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/concentratedcoalore.json @@ -3,7 +3,7 @@ "placement": [ { "type": "minecraft:count", - "count": 10 + "count": 20 }, { "type": "minecraft:in_square" @@ -21,7 +21,8 @@ } }, { - "type": "minecraft:biome" + "type": "custom_ore_gen:latitude_zone", + "zone": "temperate" } ] } \ No newline at end of file diff --git a/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/copperhighore.json b/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/copperhighore.json index 345e33e0..f5e4a0ab 100644 --- a/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/copperhighore.json +++ b/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/copperhighore.json @@ -21,7 +21,8 @@ } }, { - "type": "minecraft:biome" + "type": "custom_ore_gen:latitude_zone", + "zone": "hot" } ] } \ No newline at end of file diff --git a/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/copperlowerore.json b/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/copperlowerore.json index b0789f82..00383563 100644 --- a/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/copperlowerore.json +++ b/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/copperlowerore.json @@ -21,7 +21,8 @@ } }, { - "type": "minecraft:biome" + "type": "custom_ore_gen:latitude_zone", + "zone": "hot" } ] } \ No newline at end of file diff --git a/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/deepslatediamondore.json b/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/deepslatediamondore.json index 5fc6f58d..4e60ba82 100644 --- a/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/deepslatediamondore.json +++ b/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/deepslatediamondore.json @@ -3,7 +3,7 @@ "placement": [ { "type": "minecraft:count", - "count": 6 + "count": 3 }, { "type": "minecraft:in_square" @@ -21,7 +21,8 @@ } }, { - "type": "minecraft:biome" + "type": "custom_ore_gen:latitude_zone", + "zone": "cold" } ] } \ No newline at end of file diff --git a/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/deepslateironore.json b/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/deepslateironore.json index 218d6fcb..ea2c3dc3 100644 --- a/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/deepslateironore.json +++ b/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/deepslateironore.json @@ -21,7 +21,8 @@ } }, { - "type": "minecraft:biome" + "type": "custom_ore_gen:latitude_zone", + "zone": "temperate" } ] } \ No newline at end of file diff --git a/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/deepslatelapisore.json b/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/deepslatelapisore.json index 97126226..83ff1a40 100644 --- a/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/deepslatelapisore.json +++ b/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/deepslatelapisore.json @@ -21,7 +21,8 @@ } }, { - "type": "minecraft:biome" + "type": "custom_ore_gen:latitude_zone", + "zone": "cold" } ] } \ No newline at end of file diff --git a/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/deepslatepuregoldenore.json b/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/deepslatepuregoldenore.json index c8e8c922..5b50a17b 100644 --- a/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/deepslatepuregoldenore.json +++ b/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/deepslatepuregoldenore.json @@ -21,7 +21,8 @@ } }, { - "type": "minecraft:biome" + "type": "custom_ore_gen:latitude_zone", + "zone": "hot" } ] } \ No newline at end of file diff --git a/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/deepslateredstoneore.json b/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/deepslateredstoneore.json index 7f46fa33..6f1cb79c 100644 --- a/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/deepslateredstoneore.json +++ b/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/deepslateredstoneore.json @@ -21,7 +21,8 @@ } }, { - "type": "minecraft:biome" + "type": "custom_ore_gen:latitude_zone", + "zone": "hot" } ] } \ No newline at end of file diff --git a/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/ironore.json b/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/ironore.json index f6e9a1ab..6873cc2b 100644 --- a/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/ironore.json +++ b/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/ironore.json @@ -21,7 +21,8 @@ } }, { - "type": "minecraft:biome" + "type": "custom_ore_gen:latitude_zone", + "zone": "temperate" } ] } \ No newline at end of file diff --git a/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/lapisore.json b/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/lapisore.json index b889f000..f2dfa78f 100644 --- a/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/lapisore.json +++ b/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/lapisore.json @@ -21,7 +21,8 @@ } }, { - "type": "minecraft:biome" + "type": "custom_ore_gen:latitude_zone", + "zone": "cold" } ] } \ No newline at end of file diff --git a/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/puregoldenore.json b/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/puregoldenore.json index 3a79387a..c6075fb9 100644 --- a/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/puregoldenore.json +++ b/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/puregoldenore.json @@ -21,7 +21,8 @@ } }, { - "type": "minecraft:biome" + "type": "custom_ore_gen:latitude_zone", + "zone": "hot" } ] } \ No newline at end of file diff --git a/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/redstoneore.json b/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/redstoneore.json index 42c87ea7..74fafb6c 100644 --- a/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/redstoneore.json +++ b/src/main/resources/data/custom_ore_gen/worldgen/placed_feature/redstoneore.json @@ -21,7 +21,8 @@ } }, { - "type": "minecraft:biome" + "type": "custom_ore_gen:latitude_zone", + "zone": "hot" } ] } \ No newline at end of file diff --git a/src/main/resources/data/custom_ore_gen/worldgen/world_preset/ultra_wide_biome.json b/src/main/resources/data/custom_ore_gen/worldgen/world_preset/ultra_wide_biome.json deleted file mode 100644 index 396a5168..00000000 --- a/src/main/resources/data/custom_ore_gen/worldgen/world_preset/ultra_wide_biome.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "dimensions": { - "minecraft:overworld": { - "type": "minecraft:overworld", - "generator": { - "type": "minecraft:noise", - "biome_source": { - "type": "custom_ore_gen:latitude", - "seed": 0 - }, - "settings": "minecraft:large_biomes" - } - }, - "minecraft:the_nether": { - "type": "minecraft:the_nether", - "generator": { - "type": "minecraft:noise", - "biome_source": { - "type": "minecraft:multi_noise", - "preset": "minecraft:nether" - }, - "settings": "minecraft:nether" - } - }, - "minecraft:the_end": { - "type": "minecraft:the_end", - "generator": { - "type": "minecraft:noise", - "biome_source": { - "type": "minecraft:the_end" - }, - "settings": "minecraft:end" - } - } - } -} diff --git a/src/main/resources/data/minecraft/tags/worldgen/world_preset/normal.json b/src/main/resources/data/minecraft/tags/worldgen/world_preset/normal.json deleted file mode 100644 index f2cdb504..00000000 --- a/src/main/resources/data/minecraft/tags/worldgen/world_preset/normal.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "replace": false, - "values": [ - "minecraft:normal", - "minecraft:flat", - "minecraft:large_biomes", - "minecraft:amplified", - "minecraft:single_biome_surface", - "custom_ore_gen:ultra_wide_biome" - ] -} diff --git a/src/main/resources/data/minecraft/worldgen/noise_settings/large_biomes.json b/src/main/resources/data/minecraft/worldgen/noise_settings/large_biomes.json new file mode 100644 index 00000000..fde23d65 --- /dev/null +++ b/src/main/resources/data/minecraft/worldgen/noise_settings/large_biomes.json @@ -0,0 +1,2473 @@ +{ + "aquifers_enabled": true, + "default_block": { + "Name": "minecraft:stone" + }, + "default_fluid": { + "Name": "minecraft:water", + "Properties": { + "level": "0" + } + }, + "disable_mob_generation": false, + "legacy_random_source": false, + "noise": { + "height": 576, + "min_y": -64, + "size_horizontal": 1, + "size_vertical": 2 + }, + "noise_router": { + "barrier": { + "type": "range_choice", + "min_inclusive": -1.3, + "max_exclusive": 10, + "input": "lithosphere:caves/underground_rivers", + "when_in_range": { + "type": "minecraft:noise", + "noise": "minecraft:aquifer_barrier", + "xz_scale": 0.8, + "y_scale": 0.7 + }, + "when_out_of_range": -1.0 + }, + "continents": "minecraft:overworld/continents", + "depth": "lithosphere:depth", + "erosion": "minecraft:overworld/erosion", + "final_density": "lithosphere:density/final_density", + "fluid_level_floodedness": { + "type": "range_choice", + "min_inclusive": 1.7, + "max_exclusive": 10, + "input": "lithosphere:caves/underground_rivers", + "when_in_range": { + "type": "minecraft:noise", + "noise": "minecraft:aquifer_fluid_level_floodedness", + "xz_scale": 0.8, + "y_scale": 0.67 + }, + "when_out_of_range": 0.8 + }, + "fluid_level_spread": { + "type": "range_choice", + "min_inclusive": 3.9, + "max_exclusive": 10, + "input": "lithosphere:caves/underground_rivers", + "when_in_range": { + "type": "noise", + "noise": "minecraft:aquifer_fluid_level_spread", + "xz_scale": 0.4, + "y_scale": 0.714 + }, + "when_out_of_range": -0.55 + }, + "initial_density_without_jaggedness": { + "type": "minecraft:add", + "argument1": 0.1171875, + "argument2": { + "type": "minecraft:mul", + "argument1": { + "type": "minecraft:y_clamped_gradient", + "from_value": 0.0, + "from_y": -64, + "to_value": 1.0, + "to_y": -40 + }, + "argument2": { + "type": "minecraft:add", + "argument1": -0.1171875, + "argument2": { + "type": "minecraft:add", + "argument1": -0.078125, + "argument2": { + "type": "minecraft:mul", + "argument1": { + "type": "minecraft:y_clamped_gradient", + "from_value": 1.0, + "from_y": 496, + "to_value": 0.0, + "to_y": 512 + }, + "argument2": { + "type": "minecraft:add", + "argument1": 0.078125, + "argument2": { + "type": "minecraft:clamp", + "input": { + "type": "minecraft:add", + "argument1": -0.703125, + "argument2": { + "type": "minecraft:mul", + "argument1": 4.0, + "argument2": { + "type": "minecraft:quarter_negative", + "argument": { + "type": "minecraft:mul", + "argument1": "lithosphere:depth", + "argument2": { + "type": "minecraft:cache_2d", + "argument": "minecraft:overworld/factor" + } + } + } + } + }, + "max": 64.0, + "min": -64.0 + } + } + } + } + } + } + }, + "lava": { + "type": "minecraft:noise", + "noise": "minecraft:aquifer_lava", + "xz_scale": 0.1, + "y_scale": 0.2 + }, + "ridges": "minecraft:overworld/ridges", + "temperature": "custom_ore_gen:latitude_temperature", + "vegetation": { + "type": "minecraft:shifted_noise", + "noise": "minecraft:vegetation", + "shift_x": "minecraft:shift_x", + "shift_y": 0.0, + "shift_z": "minecraft:shift_z", + "xz_scale": 0.05, + "y_scale": 0.0 + }, + "vein_gap": { + "type": "minecraft:noise", + "noise": "minecraft:ore_gap", + "xz_scale": 1.0, + "y_scale": 1.0 + }, + "vein_ridged": { + "type": "minecraft:add", + "argument1": -0.07999999821186066, + "argument2": { + "type": "minecraft:max", + "argument1": { + "type": "minecraft:abs", + "argument": { + "type": "minecraft:interpolated", + "argument": { + "type": "minecraft:range_choice", + "input": "minecraft:y", + "max_exclusive": 51.0, + "min_inclusive": -60.0, + "when_in_range": { + "type": "minecraft:noise", + "noise": "minecraft:ore_vein_a", + "xz_scale": 4.0, + "y_scale": 4.0 + }, + "when_out_of_range": 0.0 + } + } + }, + "argument2": { + "type": "minecraft:abs", + "argument": { + "type": "minecraft:interpolated", + "argument": { + "type": "minecraft:range_choice", + "input": "minecraft:y", + "max_exclusive": 51.0, + "min_inclusive": -60.0, + "when_in_range": { + "type": "minecraft:noise", + "noise": "minecraft:ore_vein_b", + "xz_scale": 4.0, + "y_scale": 4.0 + }, + "when_out_of_range": 0.0 + } + } + } + } + }, + "vein_toggle": { + "type": "minecraft:interpolated", + "argument": { + "type": "minecraft:range_choice", + "input": "minecraft:y", + "max_exclusive": 51.0, + "min_inclusive": -60.0, + "when_in_range": { + "type": "minecraft:noise", + "noise": "minecraft:ore_veininess", + "xz_scale": 1.5, + "y_scale": 1.5 + }, + "when_out_of_range": 0.0 + } + } + }, + "ore_veins_enabled": true, + "sea_level": 63, + "spawn_target": [ + { + "continentalness": [ + 0.0, + 1.0 + ], + "depth": 0.0, + "erosion": [ + -1.0, + 1.0 + ], + "humidity": [ + -1.0, + 1.0 + ], + "offset": 0.0, + "temperature": [ + -1.0, + 1.0 + ], + "weirdness": [ + -1.0, + -0.16 + ] + }, + { + "continentalness": [ + 0.0, + 1.0 + ], + "depth": 0.0, + "erosion": [ + -1.0, + 1.0 + ], + "humidity": [ + -1.0, + 1.0 + ], + "offset": 0.0, + "temperature": [ + -1.0, + 1.0 + ], + "weirdness": [ + 0.16, + 1.0 + ] + } + ], + "surface_rule": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:vertical_gradient", + "false_at_and_above": { + "above_bottom": 5 + }, + "random_name": "minecraft:bedrock_floor", + "true_at_and_below": { + "above_bottom": 0 + } + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:bedrock" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:above_preliminary_surface" + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "floor" + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:wooded_badlands" + ] + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:y_above", + "add_stone_depth": false, + "anchor": { + "absolute": 97 + }, + "surface_depth_multiplier": 2 + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": -0.5454, + "min_threshold": -0.909, + "noise": "minecraft:surface" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:coarse_dirt" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 0.1818, + "min_threshold": -0.1818, + "noise": "minecraft:surface" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:coarse_dirt" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 0.909, + "min_threshold": 0.5454, + "noise": "minecraft:surface" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:coarse_dirt" + } + } + }, + { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": false, + "offset": 0, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:grass_block", + "Properties": { + "snowy": "false" + } + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:dirt" + } + } + ] + } + ] + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:swamp" + ] + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:y_above", + "add_stone_depth": false, + "anchor": { + "absolute": 62 + }, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:not", + "invert": { + "type": "minecraft:y_above", + "add_stone_depth": false, + "anchor": { + "absolute": 63 + }, + "surface_depth_multiplier": 0 + } + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 1.7976931348623157e+308, + "min_threshold": 0.0, + "noise": "minecraft:surface_swamp" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:water", + "Properties": { + "level": "0" + } + } + } + } + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:mangrove_swamp" + ] + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:y_above", + "add_stone_depth": false, + "anchor": { + "absolute": 60 + }, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:not", + "invert": { + "type": "minecraft:y_above", + "add_stone_depth": false, + "anchor": { + "absolute": 63 + }, + "surface_depth_multiplier": 0 + } + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 1.7976931348623157e+308, + "min_threshold": 0.0, + "noise": "minecraft:surface_swamp" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:water", + "Properties": { + "level": "0" + } + } + } + } + } + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:badlands", + "minecraft:eroded_badlands", + "minecraft:wooded_badlands" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "floor" + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:y_above", + "add_stone_depth": false, + "anchor": { + "absolute": 256 + }, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:orange_terracotta" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:y_above", + "add_stone_depth": true, + "anchor": { + "absolute": 74 + }, + "surface_depth_multiplier": 1 + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": -0.5454, + "min_threshold": -0.909, + "noise": "minecraft:surface" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:terracotta" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 0.1818, + "min_threshold": -0.1818, + "noise": "minecraft:surface" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:terracotta" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 0.909, + "min_threshold": 0.5454, + "noise": "minecraft:surface" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:terracotta" + } + } + }, + { + "type": "minecraft:bandlands" + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": false, + "offset": -1, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "ceiling" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:red_sandstone" + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:red_sand" + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:not", + "invert": { + "type": "minecraft:hole" + } + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:orange_terracotta" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": true, + "offset": -6, + "surface_depth_multiplier": -1 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:white_terracotta" + } + } + }, + { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "ceiling" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:gravel" + } + } + ] + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:y_above", + "add_stone_depth": true, + "anchor": { + "absolute": 63 + }, + "surface_depth_multiplier": -1 + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:y_above", + "add_stone_depth": false, + "anchor": { + "absolute": 63 + }, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:not", + "invert": { + "type": "minecraft:y_above", + "add_stone_depth": true, + "anchor": { + "absolute": 74 + }, + "surface_depth_multiplier": 1 + } + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:orange_terracotta" + } + } + } + }, + { + "type": "minecraft:bandlands" + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": true, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "floor" + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": true, + "offset": -6, + "surface_depth_multiplier": -1 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:white_terracotta" + } + } + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "floor" + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": false, + "offset": -1, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:frozen_ocean", + "minecraft:deep_frozen_ocean" + ] + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:hole" + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": false, + "offset": 0, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:air" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:temperature" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:ice" + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:water", + "Properties": { + "level": "0" + } + } + } + ] + } + } + }, + { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:frozen_peaks" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:steep" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:packed_ice" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 0.2, + "min_threshold": 0.0, + "noise": "minecraft:packed_ice" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:packed_ice" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 0.025, + "min_threshold": 0.0, + "noise": "minecraft:ice" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:ice" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": false, + "offset": 0, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:snow_block" + } + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:snowy_slopes" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:steep" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 0.6, + "min_threshold": 0.35, + "noise": "minecraft:powder_snow" + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": false, + "offset": 0, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:powder_snow" + } + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": false, + "offset": 0, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:snow_block" + } + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:jagged_peaks" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:steep" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": false, + "offset": 0, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:snow_block" + } + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:grove" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 0.6, + "min_threshold": 0.35, + "noise": "minecraft:powder_snow" + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": false, + "offset": 0, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:powder_snow" + } + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": false, + "offset": 0, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:snow_block" + } + } + } + ] + } + }, + { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:stony_peaks" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 0.0125, + "min_threshold": -0.0125, + "noise": "minecraft:calcite" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:calcite" + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:stony_shore" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 0.05, + "min_threshold": -0.05, + "noise": "minecraft:gravel" + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "ceiling" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:gravel" + } + } + ] + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:windswept_hills" + ] + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 1.7976931348623157e+308, + "min_threshold": 0.12121212121212122, + "noise": "minecraft:surface" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:warm_ocean", + "minecraft:beach", + "minecraft:snowy_beach" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:y_above", + "add_stone_depth": false, + "anchor": { + "absolute": 10 + }, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:y_above", + "add_stone_depth": false, + "anchor": { + "absolute": 65 + }, + "surface_depth_multiplier": 1 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "ceiling" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:sandstone" + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:sand" + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:desert" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "ceiling" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:sandstone" + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:sand" + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:dripstone_caves" + ] + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + } + ] + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:windswept_savanna" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 1.7976931348623157e+308, + "min_threshold": 0.21212121212121213, + "noise": "minecraft:surface" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 1.7976931348623157e+308, + "min_threshold": -0.06060606060606061, + "noise": "minecraft:surface" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:coarse_dirt" + } + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:windswept_gravelly_hills" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 1.7976931348623157e+308, + "min_threshold": 0.24242424242424243, + "noise": "minecraft:surface" + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "ceiling" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:gravel" + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 1.7976931348623157e+308, + "min_threshold": 0.12121212121212122, + "noise": "minecraft:surface" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 1.7976931348623157e+308, + "min_threshold": -0.12121212121212122, + "noise": "minecraft:surface" + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": false, + "offset": 0, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:grass_block", + "Properties": { + "snowy": "false" + } + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:dirt" + } + } + ] + } + }, + { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "ceiling" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:gravel" + } + } + ] + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:old_growth_pine_taiga", + "minecraft:old_growth_spruce_taiga" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 1.7976931348623157e+308, + "min_threshold": 0.21212121212121213, + "noise": "minecraft:surface" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:coarse_dirt" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 1.7976931348623157e+308, + "min_threshold": -0.11515151515151514, + "noise": "minecraft:surface" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:podzol", + "Properties": { + "snowy": "false" + } + } + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:ice_spikes" + ] + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": false, + "offset": 0, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:snow_block" + } + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:mangrove_swamp" + ] + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:mud" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:mushroom_fields" + ] + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:mycelium", + "Properties": { + "snowy": "false" + } + } + } + }, + { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": false, + "offset": 0, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:grass_block", + "Properties": { + "snowy": "false" + } + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:dirt" + } + } + ] + } + ] + } + ] + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": true, + "offset": -6, + "surface_depth_multiplier": -1 + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "floor" + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:frozen_ocean", + "minecraft:deep_frozen_ocean" + ] + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:hole" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:water", + "Properties": { + "level": "0" + } + } + } + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": true, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "floor" + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:frozen_peaks" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:steep" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:packed_ice" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 0.2, + "min_threshold": -0.5, + "noise": "minecraft:packed_ice" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:packed_ice" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 0.025, + "min_threshold": -0.0625, + "noise": "minecraft:ice" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:ice" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": false, + "offset": 0, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:snow_block" + } + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:snowy_slopes" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:steep" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 0.58, + "min_threshold": 0.45, + "noise": "minecraft:powder_snow" + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": false, + "offset": 0, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:powder_snow" + } + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": false, + "offset": 0, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:snow_block" + } + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:jagged_peaks" + ] + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:grove" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 0.58, + "min_threshold": 0.45, + "noise": "minecraft:powder_snow" + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": false, + "offset": 0, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:powder_snow" + } + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:dirt" + } + } + ] + } + }, + { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:stony_peaks" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 0.0125, + "min_threshold": -0.0125, + "noise": "minecraft:calcite" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:calcite" + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:stony_shore" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 0.05, + "min_threshold": -0.05, + "noise": "minecraft:gravel" + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "ceiling" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:gravel" + } + } + ] + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:windswept_hills" + ] + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 1.7976931348623157e+308, + "min_threshold": 0.12121212121212122, + "noise": "minecraft:surface" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:warm_ocean", + "minecraft:beach", + "minecraft:snowy_beach" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:y_above", + "add_stone_depth": false, + "anchor": { + "absolute": 10 + }, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:y_above", + "add_stone_depth": false, + "anchor": { + "absolute": 65 + }, + "surface_depth_multiplier": 1 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "ceiling" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:sandstone" + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:sand" + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:desert" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "ceiling" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:sandstone" + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:sand" + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:dripstone_caves" + ] + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + } + ] + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:windswept_savanna" + ] + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 1.7976931348623157e+308, + "min_threshold": 0.21212121212121213, + "noise": "minecraft:surface" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:windswept_gravelly_hills" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 1.7976931348623157e+308, + "min_threshold": 0.24242424242424243, + "noise": "minecraft:surface" + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "ceiling" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:gravel" + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 1.7976931348623157e+308, + "min_threshold": 0.12121212121212122, + "noise": "minecraft:surface" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 1.7976931348623157e+308, + "min_threshold": -0.12121212121212122, + "noise": "minecraft:surface" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:dirt" + } + } + }, + { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "ceiling" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:gravel" + } + } + ] + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:mangrove_swamp" + ] + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:mud" + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:dirt" + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:warm_ocean", + "minecraft:beach", + "minecraft:snowy_beach" + ] + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": true, + "offset": 0, + "secondary_depth_range": 6, + "surface_type": "floor" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:sandstone" + } + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:desert" + ] + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": true, + "offset": 0, + "secondary_depth_range": 30, + "surface_type": "floor" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:sandstone" + } + } + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "floor" + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:frozen_peaks", + "minecraft:jagged_peaks" + ] + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:warm_ocean", + "minecraft:lukewarm_ocean", + "minecraft:deep_lukewarm_ocean" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "ceiling" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:sandstone" + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:sand" + } + } + ] + } + }, + { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "ceiling" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:gravel" + } + } + ] + } + ] + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:vertical_gradient", + "false_at_and_above": { + "absolute": 8 + }, + "random_name": "minecraft:deepslate", + "true_at_and_below": { + "absolute": 0 + } + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:deepslate", + "Properties": { + "axis": "y" + } + } + } + } + ] + } +} \ No newline at end of file diff --git a/src/main/resources/data/minecraft/worldgen/noise_settings/overworld.json b/src/main/resources/data/minecraft/worldgen/noise_settings/overworld.json new file mode 100644 index 00000000..230d0fbc --- /dev/null +++ b/src/main/resources/data/minecraft/worldgen/noise_settings/overworld.json @@ -0,0 +1,2535 @@ +{ + "aquifers_enabled": true, + "default_block": { + "Name": "minecraft:stone" + }, + "default_fluid": { + "Name": "minecraft:water", + "Properties": { + "level": "0" + } + }, + "disable_mob_generation": false, + "legacy_random_source": false, + "noise": { + "height": 576, + "min_y": -64, + "size_horizontal": 1, + "size_vertical": 2 + }, + "noise_router": { + "barrier": { + "type": "range_choice", + "min_inclusive": -1.3, + "max_exclusive": 10, + "input": "lithosphere:caves/underground_rivers", + "when_in_range": { + "type": "minecraft:noise", + "noise": "minecraft:aquifer_barrier", + "xz_scale": 0.8, + "y_scale": 0.7 + }, + "when_out_of_range": -1.0 + }, + "continents": "minecraft:overworld/continents", + "depth": "lithosphere:depth", + "erosion": "minecraft:overworld/erosion", + "final_density": "lithosphere:density/final_density", + "fluid_level_floodedness": { + "type": "range_choice", + "min_inclusive": 1.7, + "max_exclusive": 10, + "input": "lithosphere:caves/underground_rivers", + "when_in_range": { + "type": "minecraft:noise", + "noise": "minecraft:aquifer_fluid_level_floodedness", + "xz_scale": 0.8, + "y_scale": 0.67 + }, + "when_out_of_range": 0.8 + }, + "fluid_level_spread": { + "type": "range_choice", + "min_inclusive": 3.9, + "max_exclusive": 10, + "input": "lithosphere:caves/underground_rivers", + "when_in_range": { + "type": "noise", + "noise": "minecraft:aquifer_fluid_level_spread", + "xz_scale": 0.4, + "y_scale": 0.714 + }, + "when_out_of_range": -0.55 + }, + "initial_density_without_jaggedness": { + "type": "minecraft:add", + "argument1": 0.1171875, + "argument2": { + "type": "minecraft:mul", + "argument1": { + "type": "minecraft:y_clamped_gradient", + "from_value": 0.0, + "from_y": -64, + "to_value": 1.0, + "to_y": -40 + }, + "argument2": { + "type": "minecraft:add", + "argument1": -0.1171875, + "argument2": { + "type": "minecraft:add", + "argument1": -0.078125, + "argument2": { + "type": "minecraft:mul", + "argument1": { + "type": "minecraft:y_clamped_gradient", + "from_value": 1.0, + "from_y": 496, + "to_value": 0.0, + "to_y": 512 + }, + "argument2": { + "type": "minecraft:add", + "argument1": 0.078125, + "argument2": { + "type": "minecraft:clamp", + "input": { + "type": "minecraft:add", + "argument1": -0.703125, + "argument2": { + "type": "minecraft:mul", + "argument1": 4.0, + "argument2": { + "type": "minecraft:quarter_negative", + "argument": { + "type": "minecraft:mul", + "argument1": "lithosphere:depth", + "argument2": { + "type": "minecraft:cache_2d", + "argument": "minecraft:overworld/factor" + } + } + } + } + }, + "max": 64.0, + "min": -64.0 + } + } + } + } + } + } + }, + "lava": { + "type": "minecraft:noise", + "noise": "minecraft:aquifer_lava", + "xz_scale": 0.1, + "y_scale": 0.2 + }, + "ridges": "minecraft:overworld/ridges", + "temperature": "custom_ore_gen:latitude_temperature", + "vegetation": { + "type": "minecraft:shifted_noise", + "noise": "minecraft:vegetation", + "shift_x": "minecraft:shift_x", + "shift_y": 0.0, + "shift_z": "minecraft:shift_z", + "xz_scale": 0.125, + "y_scale": 0.0 + }, + "vein_gap": { + "type": "minecraft:noise", + "noise": "minecraft:ore_gap", + "xz_scale": 1.0, + "y_scale": 1.0 + }, + "vein_ridged": { + "type": "minecraft:add", + "argument1": -0.07999999821186066, + "argument2": { + "type": "minecraft:max", + "argument1": { + "type": "minecraft:abs", + "argument": { + "type": "minecraft:interpolated", + "argument": { + "type": "minecraft:range_choice", + "input": "minecraft:y", + "max_exclusive": 51.0, + "min_inclusive": -60.0, + "when_in_range": { + "type": "minecraft:noise", + "noise": "minecraft:ore_vein_a", + "xz_scale": 4.0, + "y_scale": 4.0 + }, + "when_out_of_range": 0.0 + } + } + }, + "argument2": { + "type": "minecraft:abs", + "argument": { + "type": "minecraft:interpolated", + "argument": { + "type": "minecraft:range_choice", + "input": "minecraft:y", + "max_exclusive": 51.0, + "min_inclusive": -60.0, + "when_in_range": { + "type": "minecraft:noise", + "noise": "minecraft:ore_vein_b", + "xz_scale": 4.0, + "y_scale": 4.0 + }, + "when_out_of_range": 0.0 + } + } + } + } + }, + "vein_toggle": { + "type": "minecraft:interpolated", + "argument": { + "type": "minecraft:range_choice", + "input": "minecraft:y", + "max_exclusive": 51.0, + "min_inclusive": -60.0, + "when_in_range": { + "type": "minecraft:noise", + "noise": "minecraft:ore_veininess", + "xz_scale": 1.5, + "y_scale": 1.5 + }, + "when_out_of_range": 0.0 + } + } + }, + "ore_veins_enabled": true, + "sea_level": 63, + "spawn_target": [ + { + "continentalness": [ + 0.1, + 1.0 + ], + "depth": 0.0, + "erosion": [ + -1.0, + 1.0 + ], + "humidity": [ + -1.0, + 1.0 + ], + "offset": 0.0, + "temperature": [ + -1.0, + 1.0 + ], + "weirdness": [ + -1.0, + -0.16 + ] + }, + { + "continentalness": [ + 0.1, + 1.0 + ], + "depth": 0.0, + "erosion": [ + -1.0, + 1.0 + ], + "humidity": [ + -1.0, + 1.0 + ], + "offset": 0.0, + "temperature": [ + -1.0, + 1.0 + ], + "weirdness": [ + 0.16, + 1.0 + ] + } + ], + "surface_rule": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:vertical_gradient", + "false_at_and_above": { + "above_bottom": 5 + }, + "random_name": "minecraft:bedrock_floor", + "true_at_and_below": { + "above_bottom": 0 + } + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:bedrock" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:above_preliminary_surface" + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "floor" + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:wooded_badlands" + ] + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:y_above", + "add_stone_depth": false, + "anchor": { + "absolute": 97 + }, + "surface_depth_multiplier": 2 + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": -0.5454, + "min_threshold": -0.909, + "noise": "minecraft:surface" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:coarse_dirt" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 0.1818, + "min_threshold": -0.1818, + "noise": "minecraft:surface" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:coarse_dirt" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 0.909, + "min_threshold": 0.5454, + "noise": "minecraft:surface" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:coarse_dirt" + } + } + }, + { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": false, + "offset": 0, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:grass_block", + "Properties": { + "snowy": "false" + } + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:dirt" + } + } + ] + } + ] + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:swamp" + ] + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:y_above", + "add_stone_depth": false, + "anchor": { + "absolute": 62 + }, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:not", + "invert": { + "type": "minecraft:y_above", + "add_stone_depth": false, + "anchor": { + "absolute": 63 + }, + "surface_depth_multiplier": 0 + } + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 1.7976931348623157e+308, + "min_threshold": 0.0, + "noise": "minecraft:surface_swamp" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:water", + "Properties": { + "level": "0" + } + } + } + } + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:mangrove_swamp" + ] + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:y_above", + "add_stone_depth": false, + "anchor": { + "absolute": 60 + }, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:not", + "invert": { + "type": "minecraft:y_above", + "add_stone_depth": false, + "anchor": { + "absolute": 63 + }, + "surface_depth_multiplier": 0 + } + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 1.7976931348623157e+308, + "min_threshold": 0.0, + "noise": "minecraft:surface_swamp" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:water", + "Properties": { + "level": "0" + } + } + } + } + } + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:badlands", + "minecraft:eroded_badlands", + "minecraft:wooded_badlands" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "floor" + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:y_above", + "add_stone_depth": false, + "anchor": { + "absolute": 256 + }, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:orange_terracotta" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:y_above", + "add_stone_depth": true, + "anchor": { + "absolute": 74 + }, + "surface_depth_multiplier": 1 + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": -0.5454, + "min_threshold": -0.909, + "noise": "minecraft:surface" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:terracotta" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 0.1818, + "min_threshold": -0.1818, + "noise": "minecraft:surface" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:terracotta" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 0.909, + "min_threshold": 0.5454, + "noise": "minecraft:surface" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:terracotta" + } + } + }, + { + "type": "minecraft:bandlands" + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": false, + "offset": -1, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "ceiling" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:red_sandstone" + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:red_sand" + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:not", + "invert": { + "type": "minecraft:hole" + } + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:orange_terracotta" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": true, + "offset": -6, + "surface_depth_multiplier": -1 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:white_terracotta" + } + } + }, + { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "ceiling" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:gravel" + } + } + ] + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:y_above", + "add_stone_depth": true, + "anchor": { + "absolute": 63 + }, + "surface_depth_multiplier": -1 + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:y_above", + "add_stone_depth": false, + "anchor": { + "absolute": 63 + }, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:not", + "invert": { + "type": "minecraft:y_above", + "add_stone_depth": true, + "anchor": { + "absolute": 74 + }, + "surface_depth_multiplier": 1 + } + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:orange_terracotta" + } + } + } + }, + { + "type": "minecraft:bandlands" + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": true, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "floor" + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": true, + "offset": -6, + "surface_depth_multiplier": -1 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:white_terracotta" + } + } + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "floor" + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": false, + "offset": -1, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:frozen_ocean", + "minecraft:deep_frozen_ocean" + ] + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:hole" + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": false, + "offset": 0, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:air" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:temperature" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:ice" + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:water", + "Properties": { + "level": "0" + } + } + } + ] + } + } + }, + { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:frozen_peaks" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:steep" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:packed_ice" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 0.2, + "min_threshold": 0.0, + "noise": "minecraft:packed_ice" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:packed_ice" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 0.025, + "min_threshold": 0.0, + "noise": "minecraft:ice" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:ice" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": false, + "offset": 0, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:snow_block" + } + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:snowy_slopes" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:steep" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 0.6, + "min_threshold": 0.35, + "noise": "minecraft:powder_snow" + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": false, + "offset": 0, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:powder_snow" + } + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": false, + "offset": 0, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:snow_block" + } + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:jagged_peaks" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:steep" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": false, + "offset": 0, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:snow_block" + } + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:grove" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 0.6, + "min_threshold": 0.35, + "noise": "minecraft:powder_snow" + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": false, + "offset": 0, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:powder_snow" + } + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": false, + "offset": 0, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:snow_block" + } + } + } + ] + } + }, + { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:stony_peaks" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 0.0125, + "min_threshold": -0.0125, + "noise": "minecraft:calcite" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:calcite" + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:stony_shore" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:y_above", + "add_stone_depth": false, + "anchor": { + "absolute": 10 + }, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:not", + "invert": { + "type": "minecraft:y_above", + "add_stone_depth": false, + "anchor": { + "absolute": 63 + }, + "surface_depth_multiplier": 1 + } + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:sand" + } + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 0.05, + "min_threshold": -0.05, + "noise": "minecraft:gravel" + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "ceiling" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:gravel" + } + } + ] + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:windswept_hills" + ] + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 1.7976931348623157e+308, + "min_threshold": 0.12121212121212122, + "noise": "minecraft:surface" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:warm_ocean", + "minecraft:beach", + "minecraft:snowy_beach" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:y_above", + "add_stone_depth": false, + "anchor": { + "absolute": 10 + }, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:y_above", + "add_stone_depth": false, + "anchor": { + "absolute": 65 + }, + "surface_depth_multiplier": 1 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "ceiling" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:sandstone" + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:sand" + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:desert" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "ceiling" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:sandstone" + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:sand" + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:dripstone_caves" + ] + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + } + ] + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:windswept_savanna" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 1.7976931348623157e+308, + "min_threshold": 0.21212121212121213, + "noise": "minecraft:surface" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 1.7976931348623157e+308, + "min_threshold": -0.06060606060606061, + "noise": "minecraft:surface" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:coarse_dirt" + } + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:windswept_gravelly_hills" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 1.7976931348623157e+308, + "min_threshold": 0.24242424242424243, + "noise": "minecraft:surface" + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "ceiling" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:gravel" + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 1.7976931348623157e+308, + "min_threshold": 0.12121212121212122, + "noise": "minecraft:surface" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 1.7976931348623157e+308, + "min_threshold": -0.12121212121212122, + "noise": "minecraft:surface" + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": false, + "offset": 0, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:grass_block", + "Properties": { + "snowy": "false" + } + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:dirt" + } + } + ] + } + }, + { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "ceiling" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:gravel" + } + } + ] + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:old_growth_pine_taiga", + "minecraft:old_growth_spruce_taiga" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 1.7976931348623157e+308, + "min_threshold": 0.21212121212121213, + "noise": "minecraft:surface" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:coarse_dirt" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 1.7976931348623157e+308, + "min_threshold": -0.11515151515151514, + "noise": "minecraft:surface" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:podzol", + "Properties": { + "snowy": "false" + } + } + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:ice_spikes" + ] + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": false, + "offset": 0, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:snow_block" + } + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:mangrove_swamp" + ] + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:mud" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:mushroom_fields" + ] + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:mycelium", + "Properties": { + "snowy": "false" + } + } + } + }, + { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": false, + "offset": 0, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:grass_block", + "Properties": { + "snowy": "false" + } + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:dirt" + } + } + ] + } + ] + } + ] + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": true, + "offset": -6, + "surface_depth_multiplier": -1 + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "floor" + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:frozen_ocean", + "minecraft:deep_frozen_ocean" + ] + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:hole" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:water", + "Properties": { + "level": "0" + } + } + } + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": true, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "floor" + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:frozen_peaks" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:steep" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:packed_ice" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 0.2, + "min_threshold": -0.5, + "noise": "minecraft:packed_ice" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:packed_ice" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 0.025, + "min_threshold": -0.0625, + "noise": "minecraft:ice" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:ice" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": false, + "offset": 0, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:snow_block" + } + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:snowy_slopes" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:steep" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 0.58, + "min_threshold": 0.45, + "noise": "minecraft:powder_snow" + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": false, + "offset": 0, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:powder_snow" + } + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": false, + "offset": 0, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:snow_block" + } + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:jagged_peaks" + ] + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:grove" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 0.58, + "min_threshold": 0.45, + "noise": "minecraft:powder_snow" + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:water", + "add_stone_depth": false, + "offset": 0, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:powder_snow" + } + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:dirt" + } + } + ] + } + }, + { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:stony_peaks" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 0.0125, + "min_threshold": -0.0125, + "noise": "minecraft:calcite" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:calcite" + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:stony_shore" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:y_above", + "add_stone_depth": false, + "anchor": { + "absolute": 10 + }, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:not", + "invert": { + "type": "minecraft:y_above", + "add_stone_depth": false, + "anchor": { + "absolute": 63 + }, + "surface_depth_multiplier": 1 + } + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:sandstone" + } + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 0.05, + "min_threshold": -0.05, + "noise": "minecraft:gravel" + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "ceiling" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:gravel" + } + } + ] + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:windswept_hills" + ] + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 1.7976931348623157e+308, + "min_threshold": 0.12121212121212122, + "noise": "minecraft:surface" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:warm_ocean", + "minecraft:beach", + "minecraft:snowy_beach" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:y_above", + "add_stone_depth": false, + "anchor": { + "absolute": 10 + }, + "surface_depth_multiplier": 0 + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:y_above", + "add_stone_depth": false, + "anchor": { + "absolute": 65 + }, + "surface_depth_multiplier": 1 + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "ceiling" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:sandstone" + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:sand" + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:desert" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "ceiling" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:sandstone" + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:sand" + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:dripstone_caves" + ] + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + } + ] + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:windswept_savanna" + ] + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 1.7976931348623157e+308, + "min_threshold": 0.21212121212121213, + "noise": "minecraft:surface" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:windswept_gravelly_hills" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 1.7976931348623157e+308, + "min_threshold": 0.24242424242424243, + "noise": "minecraft:surface" + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "ceiling" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:gravel" + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 1.7976931348623157e+308, + "min_threshold": 0.12121212121212122, + "noise": "minecraft:surface" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 1.7976931348623157e+308, + "min_threshold": -0.12121212121212122, + "noise": "minecraft:surface" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:dirt" + } + } + }, + { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "ceiling" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:gravel" + } + } + ] + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:mangrove_swamp" + ] + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:mud" + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:dirt" + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:warm_ocean", + "minecraft:beach", + "minecraft:snowy_beach" + ] + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": true, + "offset": 0, + "secondary_depth_range": 6, + "surface_type": "floor" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:sandstone" + } + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:desert" + ] + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": true, + "offset": 0, + "secondary_depth_range": 30, + "surface_type": "floor" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:sandstone" + } + } + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "floor" + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:frozen_peaks", + "minecraft:jagged_peaks" + ] + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "minecraft:warm_ocean", + "minecraft:lukewarm_ocean", + "minecraft:deep_lukewarm_ocean" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "ceiling" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:sandstone" + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:sand" + } + } + ] + } + }, + { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "ceiling" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:stone" + } + } + }, + { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:gravel" + } + } + ] + } + ] + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:vertical_gradient", + "false_at_and_above": { + "absolute": 8 + }, + "random_name": "minecraft:deepslate", + "true_at_and_below": { + "absolute": 0 + } + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:deepslate", + "Properties": { + "axis": "y" + } + } + } + } + ] + } +} \ No newline at end of file diff --git a/src/test/java/net/mcreator/customoregen/worldgen/BiomeBandTest.java b/src/test/java/net/mcreator/customoregen/worldgen/BiomeBandTest.java deleted file mode 100644 index 338e65c6..00000000 --- a/src/test/java/net/mcreator/customoregen/worldgen/BiomeBandTest.java +++ /dev/null @@ -1,196 +0,0 @@ -package net.mcreator.customoregen.worldgen; - -import net.minecraft.world.level.biome.Biomes; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -/** - * Pure unit tests for {@link BiomeBand}, the climate-band logic that drives - * {@link LatitudeBiomeSource}. - * - *

These tests run as plain JUnit (no game server required): {@code fromTemperature} - * is a pure function of a double, and the {@code surfaceVanilla}/{@code ocean}/ - * {@code surfaceTag} helpers only ever touch {@link net.minecraft.resources.ResourceKey} - * and {@link net.minecraft.tags.TagKey} objects, which are pure value types that - * never consult a live registry. They therefore protect the most important - * behaviour of the latitude system without needing {@code runGameTestServer}.

- */ -@DisplayName("BiomeBand climate logic") -class BiomeBandTest { - - // ------------------------------------------------------------------ - // fromTemperature: boundary conditions - // ------------------------------------------------------------------ - - @Test - @DisplayName("FROZEN at the extreme cold pole") - void fromTemperature_frozenAtExtremeCold() { - assertEquals(BiomeBand.FROZEN, BiomeBand.fromTemperature(-1.0)); - assertEquals(BiomeBand.FROZEN, BiomeBand.fromTemperature(-0.9)); - } - - @Test - @DisplayName("-0.7 boundary is FROZEN (inclusive: <=)") - void fromTemperature_boundaryMinus07_isFrozenInclusive() { - assertEquals(BiomeBand.FROZEN, BiomeBand.fromTemperature(-0.7)); - } - - @Test - @DisplayName("just above -0.7 is COLD") - void fromTemperature_justAboveMinus07_isCold() { - assertEquals(BiomeBand.COLD, BiomeBand.fromTemperature(-0.69)); - assertEquals(BiomeBand.COLD, BiomeBand.fromTemperature(-0.5)); - } - - @Test - @DisplayName("-0.25 boundary is COLD (inclusive: <=)") - void fromTemperature_boundaryMinus025_isColdInclusive() { - assertEquals(BiomeBand.COLD, BiomeBand.fromTemperature(-0.25)); - } - - @Test - @DisplayName("just above -0.25 is TEMPERATE") - void fromTemperature_justAboveMinus025_isTemperate() { - assertEquals(BiomeBand.TEMPERATE, BiomeBand.fromTemperature(-0.24)); - assertEquals(BiomeBand.TEMPERATE, BiomeBand.fromTemperature(0.0)); - assertEquals(BiomeBand.TEMPERATE, BiomeBand.fromTemperature(0.2499)); - } - - @Test - @DisplayName("+0.25 boundary is WARM (TEMPERATE uses strict <)") - void fromTemperature_at025_isWarm_boundaryNotInclusive() { - assertEquals(BiomeBand.WARM, BiomeBand.fromTemperature(0.25)); - assertEquals(BiomeBand.WARM, BiomeBand.fromTemperature(0.5)); - } - - @Test - @DisplayName("+0.7 boundary and above is HOT") - void fromTemperature_atAndAbove07_isHot() { - assertEquals(BiomeBand.HOT, BiomeBand.fromTemperature(0.7)); - assertEquals(BiomeBand.HOT, BiomeBand.fromTemperature(0.9)); - assertEquals(BiomeBand.HOT, BiomeBand.fromTemperature(1.0)); - } - - @Test - @DisplayName("fromTemperature never returns null across the full range") - void fromTemperature_neverReturnsNull() { - double[] temps = {-1.0, -0.95, -0.71, -0.7, -0.69, -0.5, -0.3, -0.26, -0.25, - -0.24, -0.1, 0.0, 0.1, 0.2499, 0.25, 0.3, 0.5, 0.6999, - 0.7, 0.8, 0.95, 1.0}; - for (double t : temps) { - assertNotNull(BiomeBand.fromTemperature(t), - "fromTemperature must never return null for t=" + t); - } - } - - @Test - @DisplayName("surface temperature 0.0 (equator / spawn) is TEMPERATE") - void fromTemperature_equatorIsTemperate() { - // The spawn safe zone sits around Z=0, i.e. temperature 0 -> TEMPERATE. - assertEquals(BiomeBand.TEMPERATE, BiomeBand.fromTemperature(0.0)); - } - - // ------------------------------------------------------------------ - // Band metadata invariants - // ------------------------------------------------------------------ - - @Test - @DisplayName("band center temperatures are strictly increasing from pole to pole") - void bandsCenterTemperaturesAreMonotonic() { - BiomeBand[] bands = BiomeBand.values(); - for (int i = 1; i < bands.length; i++) { - assertTrue(bands[i - 1].centerTemperature < bands[i].centerTemperature, - "Band centers must be strictly increasing: " - + bands[i - 1] + " -> " + bands[i]); - } - assertEquals(-1.0, BiomeBand.FROZEN.centerTemperature); - assertEquals(1.0, BiomeBand.HOT.centerTemperature); - assertEquals(5, BiomeBand.values().length, "exactly five climate bands expected"); - } - - // ------------------------------------------------------------------ - // surfaceTag (must point at the mod's own tags so BoP can extend safely) - // ------------------------------------------------------------------ - - @Test - @DisplayName("every band has a non-null surface tag under the mod namespace") - void surfaceTag_isNotNullAndNamespacedForEveryBand() { - for (BiomeBand band : BiomeBand.values()) { - assertNotNull(band.surfaceTag(), "surfaceTag must not be null for " + band); - assertEquals("custom_ore_gen", band.surfaceTag().location().getNamespace(), - "surface tag namespace must be the mod id for " + band); - } - } - - @Test - @DisplayName("cold/frozen bands share the latitude_cold_surface tag") - void surfaceTag_frozenAndColdShareColdSurfaceTag() { - assertEquals(BiomeBand.FROZEN.surfaceTag(), - BiomeBand.COLD.surfaceTag(), - "FROZEN and COLD must pull surface biomes from the same cold tag"); - } - - @Test - @DisplayName("warm/hot bands share the latitude_hot_surface tag") - void surfaceTag_warmAndHotShareHotSurfaceTag() { - assertEquals(BiomeBand.WARM.surfaceTag(), - BiomeBand.HOT.surfaceTag(), - "WARM and HOT must pull surface biomes from the same hot tag"); - } - - // ------------------------------------------------------------------ - // surfaceVanilla / ocean pools (must be non-empty for every band) - // ------------------------------------------------------------------ - - @Test - @DisplayName("every band has a non-empty vanilla surface pool") - void surfaceVanilla_isNonEmptyForEveryBand() { - for (BiomeBand band : BiomeBand.values()) { - assertFalse(band.surfaceVanilla().isEmpty(), - "surfaceVanilla pool must not be empty for " + band); - // Note: List.of (used by surfaceVanilla) already guarantees non-null elements by - // construction (it throws NPE if any Biomes.X constant were null), so there is - // no need to assert contains(null) here - and List.of rejects contains(null) too. - } - } - - @Test - @DisplayName("every band has a non-empty ocean pool") - void ocean_isNonEmptyForEveryBand() { - for (BiomeBand band : BiomeBand.values()) { - assertFalse(band.ocean().isEmpty(), - "ocean pool must not be empty for " + band); - } - } - - @Test - @DisplayName("PLAINS is in the TEMPERATE surface pool (spawn must be buildable)") - void surfaceVanilla_plainsIsInTemperatePool() { - assertTrue(BiomeBand.TEMPERATE.surfaceVanilla().contains(Biomes.PLAINS), - "PLAINS must be in the TEMPERATE surface pool (spawn safe zone relies on it)"); - } - - @Test - @DisplayName("DESERT is in the HOT surface pool") - void surfaceVanilla_desertIsInHotPool() { - assertTrue(BiomeBand.HOT.surfaceVanilla().contains(Biomes.DESERT), - "DESERT must be in the HOT surface pool"); - } - - @Test - @DisplayName("deepDark-style cave biomes are NOT surfaced in any band") - void surfaceVanilla_doesNotContainCaveBiomes() { - // Cave biomes are vanilla-only, eager, injected underground by LatitudeBiomeSource. - // They must never be in a surface pool. - for (BiomeBand band : BiomeBand.values()) { - assertFalse(band.surfaceVanilla().contains(Biomes.DEEP_DARK), - "DEEP_DARK must never be in the surface pool of " + band); - assertFalse(band.surfaceVanilla().contains(Biomes.LUSH_CAVES), - "LUSH_CAVES must never be in the surface pool of " + band); - assertFalse(band.surfaceVanilla().contains(Biomes.DRIPSTONE_CAVES), - "DRIPSTONE_CAVES must never be in the surface pool of " + band); - } - } -} diff --git a/src/test/java/net/mcreator/customoregen/worldgen/LatitudeMathTest.java b/src/test/java/net/mcreator/customoregen/worldgen/LatitudeMathTest.java deleted file mode 100644 index 639f65c1..00000000 --- a/src/test/java/net/mcreator/customoregen/worldgen/LatitudeMathTest.java +++ /dev/null @@ -1,315 +0,0 @@ -package net.mcreator.customoregen.worldgen; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -/** - * Pure (registry-free) unit tests for {@link LatitudeMath}, the single source of truth - * for the latitude world geometry. Because {@link LatitudeBiomeSource} now delegates - * every climate/zone/index calculation here, these tests cover the geometry the BiomeSource - * actually uses at runtime - without needing a loaded biome registry. - */ -@DisplayName("LatitudeMath geometry (temperature, zones, spawn, selection)") -class LatitudeMathTest { - - // ------------------------------------------------------------------ - // Temperature derivation - // ------------------------------------------------------------------ - - @Test - @DisplayName("equator (Z=0) has raw temperature 0") - void rawLatitudeTemperature_equatorIsZero() { - assertEquals(0.0, LatitudeMath.rawLatitudeTemperature(0), 1e-9); - } - - @Test - @DisplayName("north pole (Z=-16000) clamps to -1, south pole (Z=+16000) to +1") - void rawLatitudeTemperature_polesClamp() { - assertEquals(-1.0, LatitudeMath.rawLatitudeTemperature(-16000), 1e-9); - assertEquals(1.0, LatitudeMath.rawLatitudeTemperature(16000), 1e-9); - } - - @Test - @DisplayName("temperature beyond the poles stays clamped to [-1, 1]") - void rawLatitudeTemperature_extremeClamped() { - assertEquals(-1.0, LatitudeMath.rawLatitudeTemperature(-1_000_000), 1e-9); - assertEquals(1.0, LatitudeMath.rawLatitudeTemperature(1_000_000), 1e-9); - } - - @Test - @DisplayName("temperature is continuous and monotonic in Z (north=cold, south=hot)") - void rawLatitudeTemperature_monotonic() { - double tNeg = LatitudeMath.rawLatitudeTemperature(-8000); - double tZero = LatitudeMath.rawLatitudeTemperature(0); - double tPos = LatitudeMath.rawLatitudeTemperature(8000); - assertTrue(tNeg < tZero, "north must be colder than equator: " + tNeg + " < " + tZero); - assertTrue(tPos > tZero, "south must be warmer than equator: " + tPos + " > " + tZero); - assertTrue(tNeg < 0, "north must be negative"); - assertTrue(tPos > 0, "south must be positive"); - } - - @Test - @DisplayName("temperature(blockZ, 0 wobble) equals rawLatitudeTemperature(blockZ)") - void temperature_zeroWobbleMatchesRaw() { - for (int z : new int[]{-1_000_000, -32000, -16000, -8000, -1, 0, 1, 8000, 16000, 32000, 1_000_000}) { - assertEquals(LatitudeMath.rawLatitudeTemperature(z), LatitudeMath.temperature(z, 0.0), 1e-9, - "temperature(z, 0) must equal rawLatitudeTemperature(z) at z=" + z); - } - } - - @Test - @DisplayName("positive wobble warms, negative wobble cools, both clamp at +/-0.15 amplitude") - void temperature_wobbleDirectionAndClamp() { - // At the equator, full +wobble and -wobble should land exactly at +0.15 / -0.15. - assertEquals(0.15, LatitudeMath.temperature(0, 0.15), 1e-9); - assertEquals(-0.15, LatitudeMath.temperature(0, -0.15), 1e-9); - // At the pole, clamping kicks in: the wobble cannot push past +/-1. - assertEquals(1.0, LatitudeMath.temperature(16000, 0.5), 1e-9); - assertEquals(-1.0, LatitudeMath.temperature(-16000, -0.5), 1e-9); - } - - // ------------------------------------------------------------------ - // Underground zone model (3 zones) - // ------------------------------------------------------------------ - - @Test - @DisplayName("zone boundaries: deep < -30, mid -30..-1, surface >= 0") - void zoneForY_boundaries() { - assertEquals(LatitudeMath.Zone.SURFACE, LatitudeMath.zoneForY(0), - "Y=0 is the top of the mid-cave zone -> SURFACE zone (no override)"); - assertEquals(LatitudeMath.Zone.SURFACE, LatitudeMath.zoneForY(1)); - assertEquals(LatitudeMath.Zone.SURFACE, LatitudeMath.zoneForY(64)); - assertEquals(LatitudeMath.Zone.SURFACE, LatitudeMath.zoneForY(320)); - - assertEquals(LatitudeMath.Zone.MID_CAVE, LatitudeMath.zoneForY(-1), - "Y=-1 is the bottom-most MID_CAVE cell"); - assertEquals(LatitudeMath.Zone.MID_CAVE, LatitudeMath.zoneForY(-15)); - assertEquals(LatitudeMath.Zone.MID_CAVE, LatitudeMath.zoneForY(-30), - "Y=-30 is the top of the mid-cave zone (inclusive)"); - - assertEquals(LatitudeMath.Zone.DEEP, LatitudeMath.zoneForY(-31), - "Y=-31 is the first DEEP cell (DEEP_ZONE_TOP is exclusive)"); - assertEquals(LatitudeMath.Zone.DEEP, LatitudeMath.zoneForY(-50)); - assertEquals(LatitudeMath.Zone.DEEP, LatitudeMath.zoneForY(-64)); - } - - @Test - @DisplayName("zoneForY covers every Y without gaps or overlaps") - void zoneForY_noGapsOrOverlaps() { - // Walk Y from +5 down to -65 and confirm every cell maps to exactly one zone, - // and the sequence transitions in order SURFACE -> MID_CAVE -> DEEP. - LatitudeMath.Zone prev = null; - int transitions = 0; - for (int y = 5; y >= -65; y--) { - LatitudeMath.Zone z = LatitudeMath.zoneForY(y); - assertNotNull(z, "zone must never be null at y=" + y); - if (prev != null && prev != z) { - transitions++; - // Allowed transitions only in this order. - if (prev == LatitudeMath.Zone.SURFACE) { - assertEquals(LatitudeMath.Zone.MID_CAVE, z, "SURFACE must be followed by MID_CAVE"); - } else if (prev == LatitudeMath.Zone.MID_CAVE) { - assertEquals(LatitudeMath.Zone.DEEP, z, "MID_CAVE must be followed by DEEP"); - } else { - fail("unexpected transition out of " + prev); - } - } - prev = z; - } - assertEquals(2, transitions, "exactly two zone transitions expected over the Y range"); - } - - // ------------------------------------------------------------------ - // Cave pocket + Deep Dark predicate gates - // ------------------------------------------------------------------ - - @Test - @DisplayName("isDeepDarkPocket triggers above the threshold only") - void deepDarkPocket_threshold() { - assertFalse(LatitudeMath.isDeepDarkPocket(0.0)); - assertFalse(LatitudeMath.isDeepDarkPocket(0.5499)); - assertFalse(LatitudeMath.isDeepDarkPocket(0.55), - "Deep Dark threshold is strict >, so exactly 0.55 is NOT a pocket"); - assertTrue(LatitudeMath.isDeepDarkPocket(0.55001)); - assertTrue(LatitudeMath.isDeepDarkPocket(1.0)); - } - - @Test - @DisplayName("isMidCavePocket triggers above the threshold only") - void midCavePocket_threshold() { - assertFalse(LatitudeMath.isMidCavePocket(0.0)); - assertFalse(LatitudeMath.isMidCavePocket(0.3799)); - assertFalse(LatitudeMath.isMidCavePocket(0.38), - "cave threshold is strict >, so exactly 0.38 is NOT a pocket"); - assertTrue(LatitudeMath.isMidCavePocket(0.38001)); - assertTrue(LatitudeMath.isMidCavePocket(1.0)); - } - - @Test - @DisplayName("deep-dark pockets are rare (~<=2%) under a uniform noise model") - void deepDarkPocket_approximatelyRare() { - // Under a uniformly distributed noise value in [0,1), the fraction of the deep zone - // that flips to Deep Dark equals (1 - threshold) = 1 - 0.55 = 45%. - // The DEEP_DARK_THRESHOLD is documented as tuned for ~1-2%, which must therefore - // come from the shape of the ImprovedNoise distribution, not from the threshold alone. - // This test pins that contract: the threshold is 0.55, so a uniform sample would give 45%. - // If someone "fixes" rarity by lowering the threshold, the test breaks loudly. - int hits = 0; - int n = 100_000; - for (int i = 0; i < n; i++) { - double v = (i + 0.5) / n; // deterministic uniform grid in (0,1) - if (LatitudeMath.isDeepDarkPocket(v)) hits++; - } - assertEquals(0.45, hits / (double) n, 1e-9, - "threshold 0.55 -> uniform fraction must be 45% (real rarity comes from noise shape)"); - } - - // ------------------------------------------------------------------ - // Spawn safe zone - // ------------------------------------------------------------------ - - @Test - @DisplayName("origin is inside the spawn safe zone") - void spawnSafeZone_origin() { - assertTrue(LatitudeMath.isInSpawnSafeZone(0, 0)); - assertTrue(LatitudeMath.isInSpawnSafeZone(539, 539)); - } - - @Test - @DisplayName("just outside the safe radius is NOT safe") - void spawnSafeZone_outside() { - assertFalse(LatitudeMath.isInSpawnSafeZone(540, 0), - "x=540 equals radius, must be outside (strict <)"); - assertFalse(LatitudeMath.isInSpawnSafeZone(0, 540)); - assertFalse(LatitudeMath.isInSpawnSafeZone(-540, -540)); - assertFalse(LatitudeMath.isInSpawnSafeZone(1000, 1000)); - } - - @Test - @DisplayName("spawn safe zone is a square symmetric around the origin") - void spawnSafeZone_symmetricSquare() { - for (int x : new int[]{0, 50, 539, -50, -539}) { - assertEquals(LatitudeMath.isInSpawnSafeZone(x, 50), - LatitudeMath.isInSpawnSafeZone(-x, 50), - "safe zone must be X-symmetric at x=" + x); - } - for (int z : new int[]{0, 50, 539, -50, -539}) { - assertEquals(LatitudeMath.isInSpawnSafeZone(50, z), - LatitudeMath.isInSpawnSafeZone(50, -z), - "safe zone must be Z-symmetric at z=" + z); - } - } - - @Test - @DisplayName("spawn safe zone edge count matches a 2*radius x 2*radius square (exclusive)") - void spawnSafeZone_edgeCount() { - // SPAWN_SAFE_RADIUS = 540, strict <, so the square is [-539, 539] inclusive on both axes. - int count = 0; - for (int x = -545; x <= 545; x++) { - for (int z = -545; z <= 545; z++) { - if (LatitudeMath.isInSpawnSafeZone(x, z)) count++; - } - } - assertEquals(2 * 539 + 1, (int) Math.sqrt(count), - "safe zone side length must be 2*(540-1)+1 = 1079"); - assertEquals(1079 * 1079, count); - } - - // ------------------------------------------------------------------ - // Biome selector index math (dual-octave flattening) - // ------------------------------------------------------------------ - - @Test - @DisplayName("normalisedSelector always lands in [0, 1]") - void normalisedSelector_range() { - // ImprovedNoise output is roughly in [-1, 1] but can overshoot a little; the normaliser - // must clamp no matter the input. - double[] extremeInputs = {-10, -2, -1, -0.5, 0, 0.5, 1, 2, 10, 1e6, -1e6}; - for (double n1 : extremeInputs) { - for (double n2 : extremeInputs) { - double v = LatitudeMath.normalisedSelector(n1, n2); - assertTrue(v >= 0.0 && v <= 1.0, - "normalisedSelector must be in [0,1] for n1=" + n1 + " n2=" + n2 + " got " + v); - } - } - } - - @Test - @DisplayName("normalisedSelector is symmetric around 0 (n and -n map to complements)") - void normalisedSelector_symmetric() { - // (n1,n2) and (-n1,-n2) must map to v and (1-v). - for (double n1 : new double[]{-0.8, -0.3, 0.0, 0.3, 0.8}) { - for (double n2 : new double[]{-0.8, -0.3, 0.0, 0.3, 0.8}) { - double v = LatitudeMath.normalisedSelector(n1, n2); - double vNeg = LatitudeMath.normalisedSelector(-n1, -n2); - assertEquals(1.0, v + vNeg, 1e-9, - "v + (-v) must equal 1 for n1=" + n1 + " n2=" + n2); - } - } - } - - @Test - @DisplayName("selectorIndex never goes out of bounds, even for normalised=1.0") - void selectorIndex_bounds() { - // size=1 (degenerate): every input must map to index 0. - assertEquals(0, LatitudeMath.selectorIndex(0.0, 1)); - assertEquals(0, LatitudeMath.selectorIndex(0.5, 1)); - assertEquals(0, LatitudeMath.selectorIndex(1.0, 1)); - - // size=4: index in [0,3], and normalised=1.0 must clamp to last, not 4. - for (double v = 0.0; v <= 1.0001; v += 0.001) { - int idx = LatitudeMath.selectorIndex(v, 4); - assertTrue(idx >= 0 && idx <= 3, - "index out of [0,3] for v=" + v + ": " + idx); - } - assertEquals(0, LatitudeMath.selectorIndex(0.0, 4)); - assertEquals(3, LatitudeMath.selectorIndex(1.0, 4)); - assertEquals(3, LatitudeMath.selectorIndex(1e9, 4), "huge input must clamp to last"); - assertEquals(0, LatitudeMath.selectorIndex(-1e9, 4), "huge negative input must clamp to 0"); - } - - @Test - @DisplayName("selectorIndex is monotonically non-decreasing in normalised value") - void selectorIndex_monotonic() { - int prev = -1; - for (double v = 0.0; v <= 1.0; v += 0.0001) { - int idx = LatitudeMath.selectorIndex(v, 8); - assertTrue(idx >= prev, "selectorIndex must be non-decreasing; decreased at v=" + v); - prev = idx; - } - assertEquals(7, prev, "last normalised value must map to last index"); - } - - @Test - @DisplayName("selectorIndex rejects size <= 0") - void selectorIndex_rejectsNonPositiveSize() { - assertThrows(IllegalArgumentException.class, () -> LatitudeMath.selectorIndex(0.5, 0)); - assertThrows(IllegalArgumentException.class, () -> LatitudeMath.selectorIndex(0.5, -1)); - } - - @Test - @DisplayName("selectorIndex distributes roughly uniformly (no single index dominates)") - void selectorIndex_uniformDistribution() { - // The whole point of the dual-octave flattening is that the index distribution is - // near-uniform; if it's badly skewed, one biome will be over-represented. - // ImprovedNoise roughly outputs a bell curve in [-1,1], so we sample that. - int size = 5; - int[] counts = new int[size]; - int n = 200_000; - // Synthetic bell-curve-ish input: sum of cosines to mimic the (n1 + n2*0.5)/1.5 shape. - for (int i = 0; i < n; i++) { - double t = (i + 0.5) / n * Math.PI; - double n1 = Math.cos(t * 7.0); - double n2 = Math.cos(t * 13.0 + 0.3); - counts[LatitudeMath.selectorIndex(LatitudeMath.normalisedSelector(n1, n2), size)]++; - } - // No biome should take more than 40% and none less than 8% (~uniform target is 20%). - for (int c : counts) { - double ratio = c / (double) n; - assertTrue(ratio < 0.40, "a biome index is over-represented: " + ratio); - assertTrue(ratio > 0.08, "a biome index is under-represented: " + ratio); - } - } -}