From fd7a2374566fd7393ac0fe64ea01c3316159acbd Mon Sep 17 00:00:00 2001 From: Bonnie <73203899+Bonnie39@users.noreply.github.com> Date: Wed, 4 Mar 2026 16:29:35 -0600 Subject: [PATCH] generate aerclouds in the aether --- Minecraft.World/AerCloudFeature.cpp | 142 ++++++++++++++++++ Minecraft.World/AerCloudFeature.h | 28 ++++ Minecraft.World/AercloudTile.h | 1 + Minecraft.World/AetherBiomeDecorator.cpp | 57 +++++++ Minecraft.World/AetherBiomeDecorator.h | 8 + Minecraft.World/AetherDimension.cpp | 10 ++ Minecraft.World/AetherDimension.h | 2 + Minecraft.World/AetherLevelSource.cpp | 2 +- Minecraft.World/Dimension.h | 2 +- Minecraft.World/Minecraft.World.vcxproj | 2 + .../Minecraft.World.vcxproj.filters | 6 + ...t.minecraft.world.level.levelgen.feature.h | 1 + 12 files changed, 259 insertions(+), 2 deletions(-) create mode 100644 Minecraft.World/AerCloudFeature.cpp create mode 100644 Minecraft.World/AerCloudFeature.h diff --git a/Minecraft.World/AerCloudFeature.cpp b/Minecraft.World/AerCloudFeature.cpp new file mode 100644 index 00000000..2ec305a8 --- /dev/null +++ b/Minecraft.World/AerCloudFeature.cpp @@ -0,0 +1,142 @@ +#include "stdafx.h" +#include "AerCloudFeature.h" +#include "net.minecraft.world.level.h" +#include "net.minecraft.world.level.tile.h" + +AerCloudFeature::AerCloudFeature(int tileId, int minRadius, int maxRadius, int minHeight, int maxHeight, bool islandBottom) + : Feature(false) +{ + this->tileId = tileId; + this->minRadius = minRadius; + this->maxRadius = maxRadius; + this->minHeight = minHeight; + this->maxHeight = maxHeight; + this->islandBottom = islandBottom; +} + +int AerCloudFeature::findIslandBottom(Level *level, int x, int startY, int z) +{ + // Scan down from startY to find the lowest solid block in this column that's part of an island + for (int yy = startY; yy >= 1; yy--) + { + int tile = level->getTile(x, yy, z); + if (tile != 0) + { + // Found solid — now find the bottom of this solid section + for (int by = yy; by >= 1; by--) + { + int belowTile = level->getTile(x, by - 1, z); + if (belowTile == 0) + { + return by; // This is the bottom of the island + } + } + return 1; + } + } + return -1; // No solid block found +} + +void AerCloudFeature::generateCloudBlob(Level *level, Random *random, int cx, int cy, int cz, int rx, int rz, int ry) +{ + // Generate an ellipsoidal cloud using distance checks with randomization for organic shape + float rxSq = (float)(rx * rx); + float rySq = (float)(ry * ry); + float rzSq = (float)(rz * rz); + + for (int dx = -rx; dx <= rx; dx++) + { + for (int dz = -rz; dz <= rz; dz++) + { + for (int dy = -ry; dy <= ry; dy++) + { + float distSq = (dx * dx) / rxSq + (dy * dy) / rySq + (dz * dz) / rzSq; + + // Ellipsoid check with randomized edges for organic cloud shapes + if (distSq < 1.0f + (random->nextFloat() * 0.3f - 0.15f)) + { + int bx = cx + dx; + int by = cy + dy; + int bz = cz + dz; + + if (by < 1 || by >= Level::genDepth) continue; + + // Only place in air + if (level->getTile(bx, by, bz) == 0) + { + placeBlock(level, bx, by, bz, tileId); + } + } + } + } + } +} + +bool AerCloudFeature::place(Level *level, Random *random, int x, int y, int z) +{ + if (islandBottom) + { + // Large cloud formation at the underside of islands + // Find the bottom of the nearest island + int bottomY = findIslandBottom(level, x, y, z); + if (bottomY < 2) return false; + + // Verify there's actually an island above (at least a few solid blocks) + int solidCount = 0; + for (int cy = bottomY; cy <= bottomY + 5 && cy < Level::genDepth; cy++) + { + if (level->getTile(x, cy, z) != 0) solidCount++; + } + if (solidCount < 3) return false; + + // Verify there's open air below the island bottom + bool hasAirBelow = false; + for (int cy = bottomY - 1; cy >= bottomY - 4 && cy >= 0; cy--) + { + if (level->getTile(x, cy, z) == 0) + { + hasAirBelow = true; + break; + } + } + if (!hasAirBelow) return false; + + // Generate a large cloud clump beneath the island + int rx = minRadius + random->nextInt(maxRadius - minRadius + 1); + int rz = minRadius + random->nextInt(maxRadius - minRadius + 1); + int ry = minHeight + random->nextInt(maxHeight - minHeight + 1); + + int cloudY = bottomY - ry - 1; + if (cloudY < 1) return false; + + // Place multiple overlapping blobs for a more natural cloud appearance + int blobCount = 2 + random->nextInt(3); // 2-4 overlapping blobs + for (int i = 0; i < blobCount; i++) + { + int blobX = x + random->nextInt(rx) - rx / 2; + int blobZ = z + random->nextInt(rz) - rz / 2; + int blobY = cloudY + random->nextInt(ry > 1 ? ry : 1); + int blobRx = rx / 2 + random->nextInt(rx / 2 + 1); + int blobRz = rz / 2 + random->nextInt(rz / 2 + 1); + int blobRy = max(1, ry / 2 + random->nextInt(max(1, ry / 2))); + + generateCloudBlob(level, random, blobX, blobY, blobZ, blobRx, blobRz, blobRy); + } + + return true; + } + else + { + // Small floating cloud in the sky at the given position + // Only place in air — verify the position is actually open + if (level->getTile(x, y, z) != 0) return false; + + int rx = minRadius + random->nextInt(maxRadius - minRadius + 1); + int rz = minRadius + random->nextInt(maxRadius - minRadius + 1); + int ry = minHeight + random->nextInt(maxHeight - minHeight + 1); + + generateCloudBlob(level, random, x, y, z, rx, rz, ry); + + return true; + } +} diff --git a/Minecraft.World/AerCloudFeature.h b/Minecraft.World/AerCloudFeature.h new file mode 100644 index 00000000..260ddea5 --- /dev/null +++ b/Minecraft.World/AerCloudFeature.h @@ -0,0 +1,28 @@ +#pragma once +#include "Feature.h" + +class AerCloudFeature : public Feature +{ +public: + // tileId: which aercloud tile to place (aercloud, gold, blue) + // minRadius/maxRadius: horizontal radius range for the cloud blob + // minHeight/maxHeight: vertical thickness range + // islandBottom: if true, generates large clouds at island undersides; if false, generates floating sky clouds + AerCloudFeature(int tileId, int minRadius, int maxRadius, int minHeight, int maxHeight, bool islandBottom); + + virtual bool place(Level *level, Random *random, int x, int y, int z); + +private: + int tileId; + int minRadius; + int maxRadius; + int minHeight; + int maxHeight; + bool islandBottom; + + // Generate an ellipsoidal cloud blob centered at (cx, cy, cz) + void generateCloudBlob(Level *level, Random *random, int cx, int cy, int cz, int rx, int rz, int ry); + + // Find the bottom of an island by scanning down from y + int findIslandBottom(Level *level, int x, int startY, int z); +}; diff --git a/Minecraft.World/AercloudTile.h b/Minecraft.World/AercloudTile.h index b05f3506..50a9eff2 100644 --- a/Minecraft.World/AercloudTile.h +++ b/Minecraft.World/AercloudTile.h @@ -12,4 +12,5 @@ public: virtual void fallOn(Level *level, int x, int y, int z, shared_ptr entity, float fallDistance); virtual void entityInside(Level *level, int x, int y, int z, shared_ptr entity); virtual bool isSolidRender(bool isServerLevel = false); + virtual bool shouldRenderFace(LevelSource *level, int x, int y, int z, int face); }; diff --git a/Minecraft.World/AetherBiomeDecorator.cpp b/Minecraft.World/AetherBiomeDecorator.cpp index 55f8b7cd..2deb2478 100644 --- a/Minecraft.World/AetherBiomeDecorator.cpp +++ b/Minecraft.World/AetherBiomeDecorator.cpp @@ -5,6 +5,7 @@ #include "net.minecraft.world.level.levelgen.feature.h" #include "net.minecraft.world.level.biome.h" #include "QuicksoilShelfFeature.h" +#include "AerCloudFeature.h" AetherBiomeDecorator::AetherBiomeDecorator(Biome *biome) : BiomeDecorator(biome) { @@ -16,6 +17,16 @@ AetherBiomeDecorator::AetherBiomeDecorator(Biome *biome) : BiomeDecorator(biome) // Quicksoil shelves on island undersides quicksoilShelfFeature = new QuicksoilShelfFeature(); + // AerCloud features + // Large clouds at island bottoms: radius 6-10, height 2-4, island-bottom mode + largeAerCloudFeature = new AerCloudFeature(Tile::aercloud_Id, 6, 10, 2, 4, true); + // Small white sky clouds: radius 3-6, height 1-2, free-floating + smallAerCloudFeature = new AerCloudFeature(Tile::aercloud_Id, 3, 6, 1, 2, false); + // Small gold sky clouds: radius 2-4, height 1-2, free-floating + smallGoldAerCloudFeature = new AerCloudFeature(Tile::goldAercloud_Id, 2, 4, 1, 2, false); + // Small blue sky clouds: radius 2-4, height 1-2, free-floating + smallBlueAerCloudFeature = new AerCloudFeature(Tile::blueAercloud_Id, 2, 4, 1, 2, false); + // Aether decoration counts treeCount = 2; grassCount = 5; @@ -90,6 +101,52 @@ void AetherBiomeDecorator::decorate() } } PIXEndNamedEvent(); + + PIXBeginNamedEvent(0, "Decorate Aether clouds"); + + // Large aercloud formations at island undersides — gives players a safety net when falling (1 in 5 chunks) + if (random->nextInt(5) == 0) + { + int x = xo + random->nextInt(16) + 8; + int z = zo + random->nextInt(16) + 8; + int y = level->getHeightmap(x, z); + if (y > 0) + { + largeAerCloudFeature->place(level, random, x, y, z); + } + } + + // Sky clouds spawn at y=80 or higher + const int minCloudY = 80; + + // Small white aerclouds floating in the sky (1 in 10 chunks) + if (random->nextInt(10) == 0) + { + int x = xo + random->nextInt(16) + 8; + int z = zo + random->nextInt(16) + 8; + int y = minCloudY + random->nextInt(Level::genDepth - 10 - minCloudY); + smallAerCloudFeature->place(level, random, x, y, z); + } + + // Small gold aerclouds — rare (1 in 30 chunks) + if (random->nextInt(30) == 0) + { + int x = xo + random->nextInt(16) + 8; + int z = zo + random->nextInt(16) + 8; + int y = minCloudY + random->nextInt(Level::genDepth - 10 - minCloudY); + smallGoldAerCloudFeature->place(level, random, x, y, z); + } + + // Small blue aerclouds — rarest (1 in 60 chunks) + if (random->nextInt(60) == 0) + { + int x = xo + random->nextInt(16) + 8; + int z = zo + random->nextInt(16) + 8; + int y = minCloudY + random->nextInt(Level::genDepth - 10 - minCloudY); + smallBlueAerCloudFeature->place(level, random, x, y, z); + } + + PIXEndNamedEvent(); } void AetherBiomeDecorator::decorateAetherOres() diff --git a/Minecraft.World/AetherBiomeDecorator.h b/Minecraft.World/AetherBiomeDecorator.h index 008849c7..61af4fe0 100644 --- a/Minecraft.World/AetherBiomeDecorator.h +++ b/Minecraft.World/AetherBiomeDecorator.h @@ -1,6 +1,8 @@ #pragma once #include "BiomeDecorator.h" +class AerCloudFeature; + class AetherBiomeDecorator : public BiomeDecorator { public: @@ -15,6 +17,12 @@ protected: // Quicksoil shelf feature for island undersides Feature *quicksoilShelfFeature; + // AerCloud features + Feature *largeAerCloudFeature; // Big cloud clumps at island undersides + Feature *smallAerCloudFeature; // Small white clouds in the sky + Feature *smallGoldAerCloudFeature; // Small gold clouds (rare) + Feature *smallBlueAerCloudFeature; // Small blue clouds (rarest) + virtual void decorate(); void decorateAetherOres(); }; diff --git a/Minecraft.World/AetherDimension.cpp b/Minecraft.World/AetherDimension.cpp index 826dd5f5..6904ae1b 100644 --- a/Minecraft.World/AetherDimension.cpp +++ b/Minecraft.World/AetherDimension.cpp @@ -86,6 +86,16 @@ bool AetherDimension::isFoggyAt(int x, int z) return false; } +bool AetherDimension::hasBedrockFog() +{ + return false; +} + +double AetherDimension::getClearColorScale() +{ + return 1.0; +} + int AetherDimension::getSpawnYPosition() { return 64; diff --git a/Minecraft.World/AetherDimension.h b/Minecraft.World/AetherDimension.h index 132e2b76..20bfbd00 100644 --- a/Minecraft.World/AetherDimension.h +++ b/Minecraft.World/AetherDimension.h @@ -17,4 +17,6 @@ public: virtual Pos *getSpawnPos(); virtual int getSpawnYPosition(); virtual bool isFoggyAt(int x, int z); + virtual bool hasBedrockFog(); + virtual double getClearColorScale(); }; diff --git a/Minecraft.World/AetherLevelSource.cpp b/Minecraft.World/AetherLevelSource.cpp index bd8aa1a7..7caa7fd7 100644 --- a/Minecraft.World/AetherLevelSource.cpp +++ b/Minecraft.World/AetherLevelSource.cpp @@ -308,7 +308,7 @@ doubleArray AetherLevelSource::getHeights(doubleArray buffer, int x, int y, int val = val * (1 - slide) + -3000 * slide; } // Slide down at the bottom of the world - r = 8; + r = 10; if (yy < r) { double slide = (r - yy) / (r - 1.0f); diff --git a/Minecraft.World/Dimension.h b/Minecraft.World/Dimension.h index 36df385e..a04c0cb6 100644 --- a/Minecraft.World/Dimension.h +++ b/Minecraft.World/Dimension.h @@ -54,7 +54,7 @@ public: int getSpawnYPosition(); virtual bool hasBedrockFog(); - double getClearColorScale(); + virtual double getClearColorScale(); virtual bool isFoggyAt(int x, int z); // 4J Added diff --git a/Minecraft.World/Minecraft.World.vcxproj b/Minecraft.World/Minecraft.World.vcxproj index 804e0c6a..06e37b90 100644 --- a/Minecraft.World/Minecraft.World.vcxproj +++ b/Minecraft.World/Minecraft.World.vcxproj @@ -2514,6 +2514,7 @@ + @@ -3540,6 +3541,7 @@ + diff --git a/Minecraft.World/Minecraft.World.vcxproj.filters b/Minecraft.World/Minecraft.World.vcxproj.filters index 8defdcfe..bb6f05f1 100644 --- a/Minecraft.World/Minecraft.World.vcxproj.filters +++ b/Minecraft.World/Minecraft.World.vcxproj.filters @@ -466,6 +466,9 @@ net\minecraft\world\level\levelgen\feature + + net\minecraft\world\level\levelgen\feature + net\minecraft\world\level\levelgen\feature @@ -3006,6 +3009,9 @@ net\minecraft\world\level\levelgen\feature + + net\minecraft\world\level\levelgen\feature + net\minecraft\world\level\levelgen\feature diff --git a/Minecraft.World/net.minecraft.world.level.levelgen.feature.h b/Minecraft.World/net.minecraft.world.level.levelgen.feature.h index 05bd0249..3c022d9c 100644 --- a/Minecraft.World/net.minecraft.world.level.levelgen.feature.h +++ b/Minecraft.World/net.minecraft.world.level.levelgen.feature.h @@ -37,5 +37,6 @@ #include "SkyrootTreeFeature.h" #include "GoldenOakTreeFeature.h" +#include "AerCloudFeature.h" #include "VinesFeature.h" #include "GroundBushFeature.h" \ No newline at end of file