generate aerclouds in the aether

This commit is contained in:
Bonnie
2026-03-04 16:29:35 -06:00
parent f4a5572b52
commit fd7a237456
12 changed files with 259 additions and 2 deletions

View File

@@ -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;
}
}

View File

@@ -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);
};

View File

@@ -12,4 +12,5 @@ public:
virtual void fallOn(Level *level, int x, int y, int z, shared_ptr<Entity> entity, float fallDistance);
virtual void entityInside(Level *level, int x, int y, int z, shared_ptr<Entity> entity);
virtual bool isSolidRender(bool isServerLevel = false);
virtual bool shouldRenderFace(LevelSource *level, int x, int y, int z, int face);
};

View File

@@ -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()

View File

@@ -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();
};

View File

@@ -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;

View File

@@ -17,4 +17,6 @@ public:
virtual Pos *getSpawnPos();
virtual int getSpawnYPosition();
virtual bool isFoggyAt(int x, int z);
virtual bool hasBedrockFog();
virtual double getClearColorScale();
};

View File

@@ -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);

View File

@@ -54,7 +54,7 @@ public:
int getSpawnYPosition();
virtual bool hasBedrockFog();
double getClearColorScale();
virtual double getClearColorScale();
virtual bool isFoggyAt(int x, int z);
// 4J Added

View File

@@ -2514,6 +2514,7 @@
<ClInclude Include="OldChunkStorage.h" />
<ClInclude Include="OreFeature.h" />
<ClInclude Include="QuicksoilShelfFeature.h" />
<ClInclude Include="AerCloudFeature.h" />
<ClInclude Include="OreRecipies.h" />
<ClInclude Include="OreTile.h" />
<ClInclude Include="OutputStream.h" />
@@ -3540,6 +3541,7 @@
<ClCompile Include="OldChunkStorage.cpp" />
<ClCompile Include="OreFeature.cpp" />
<ClCompile Include="QuicksoilShelfFeature.cpp" />
<ClCompile Include="AerCloudFeature.cpp" />
<ClCompile Include="OreRecipies.cpp" />
<ClCompile Include="OreTile.cpp" />
<ClCompile Include="Packet.cpp" />

View File

@@ -466,6 +466,9 @@
<ClInclude Include="QuicksoilShelfFeature.h">
<Filter>net\minecraft\world\level\levelgen\feature</Filter>
</ClInclude>
<ClInclude Include="AerCloudFeature.h">
<Filter>net\minecraft\world\level\levelgen\feature</Filter>
</ClInclude>
<ClInclude Include="PumpkinFeature.h">
<Filter>net\minecraft\world\level\levelgen\feature</Filter>
</ClInclude>
@@ -3006,6 +3009,9 @@
<ClCompile Include="QuicksoilShelfFeature.cpp">
<Filter>net\minecraft\world\level\levelgen\feature</Filter>
</ClCompile>
<ClCompile Include="AerCloudFeature.cpp">
<Filter>net\minecraft\world\level\levelgen\feature</Filter>
</ClCompile>
<ClCompile Include="PumpkinFeature.cpp">
<Filter>net\minecraft\world\level\levelgen\feature</Filter>
</ClCompile>

View File

@@ -37,5 +37,6 @@
#include "SkyrootTreeFeature.h"
#include "GoldenOakTreeFeature.h"
#include "AerCloudFeature.h"
#include "VinesFeature.h"
#include "GroundBushFeature.h"