From 5f71ac96ffa8902396e0c06672a04c2550513a12 Mon Sep 17 00:00:00 2001 From: Lord_Cambion Date: Wed, 8 Apr 2026 15:49:51 +0200 Subject: [PATCH] fix: ore spawning nether --- Minecraft.World/OreFeature.cpp | 186 +++++++++++++++++---------------- 1 file changed, 97 insertions(+), 89 deletions(-) diff --git a/Minecraft.World/OreFeature.cpp b/Minecraft.World/OreFeature.cpp index 01ddb993..d5a1eaef 100644 --- a/Minecraft.World/OreFeature.cpp +++ b/Minecraft.World/OreFeature.cpp @@ -3,6 +3,9 @@ #include "net.minecraft.world.level.tile.h" #include "OreFeature.h" +static thread_local bool s_oreFeaturePlacing = false; + + void OreFeature::_init(int tile, int data, int count, int targetTile) { this->tile = tile; @@ -28,128 +31,133 @@ OreFeature::OreFeature(int tile, int data, int count, int targetTile) bool OreFeature::place(Level *level, Random *random, int x, int y, int z) { - PIXBeginNamedEvent(0,"Place Ore Feature"); - float dir = random->nextFloat() * PI; + + if (s_oreFeaturePlacing) + { + return false; + } + + s_oreFeaturePlacing = true; + + PIXBeginNamedEvent(0,"Place Ore Feature"); + float dir = random->nextFloat() * PI; - double x0 = x + 8 + Mth::sin(dir) * count / 8; - double x1 = x + 8 - Mth::sin(dir) * count / 8; - double z0 = z + 8 + Mth::cos(dir) * count / 8; - double z1 = z + 8 - Mth::cos(dir) * count / 8; + double x0 = x + 8 + Mth::sin(dir) * count / 8; + double x1 = x + 8 - Mth::sin(dir) * count / 8; + double z0 = z + 8 + Mth::cos(dir) * count / 8; + double z1 = z + 8 - Mth::cos(dir) * count / 8; - double y0 = y + random->nextInt(3) - 2; - double y1 = y + random->nextInt(3) - 2; + double y0 = y + random->nextInt(3) - 2; + double y1 = y + random->nextInt(3) - 2; - bool collisionsExpected = false; + bool collisionsExpected = false; - LevelGenerationOptions *levelGenOptions = nullptr; - if( app.getLevelGenerationOptions() != nullptr ) - { - levelGenOptions = app.getLevelGenerationOptions(); + LevelGenerationOptions *levelGenOptions = nullptr; + if( app.getLevelGenerationOptions() != nullptr ) + { + levelGenOptions = app.getLevelGenerationOptions(); - // 4J Stu - Optimise schematic intersection checks by first checking the max possible bounding box of this place call - int minX = x0 - 1; - int minY = y0 - 1; - int minZ = z0 - 1; + int minX = x0 - 1; + int minY = y0 - 1; + int minZ = z0 - 1; - double maxss = count / 16; - double maxr = (Mth::sin(PI) + 1) * maxss + 1; - double maxhr = (Mth::sin(PI) + 1) * maxss + 1; - int maxX = Mth::floor(x1 + maxr / 2); - int maxY = Mth::floor(y1 + maxhr / 2); - int maxZ = Mth::floor(z1 + maxr / 2); + double maxss = count / 16; + double maxr = (Mth::sin(PI) + 1) * maxss + 1; + double maxhr = (Mth::sin(PI) + 1) * maxss + 1; + int maxX = Mth::floor(x1 + maxr / 2); + int maxY = Mth::floor(y1 + maxhr / 2); + int maxZ = Mth::floor(z1 + maxr / 2); - collisionsExpected = levelGenOptions->checkIntersects(minX, minY, minZ, maxX, maxY, maxZ); - } + collisionsExpected = levelGenOptions->checkIntersects(minX, minY, minZ, maxX, maxY, maxZ); + } - bool doEarlyRejectTest = false; - if( y0 > level->getSeaLevel() ) - { - doEarlyRejectTest = true; - } + bool doEarlyRejectTest = false; + if( y0 > level->getSeaLevel() ) + { + doEarlyRejectTest = true; + } - for (int d = 0; d <= count; d++) - { - double xx = x0 + (x1 - x0) * d / count; - double yy = y0 + (y1 - y0) * d / count; - double zz = z0 + (z1 - z0) * d / count; + for (int d = 0; d <= count; d++) + { + double xx = x0 + (x1 - x0) * d / count; + double yy = y0 + (y1 - y0) * d / count; + double zz = z0 + (z1 - z0) * d / count; double ss = random->nextDouble() * count / 16; double r = (Mth::sin(d * PI / count) + 1) * ss + 1; - double hr = r; //(Mth::sin(d * PI / count) + 1) * ss + 1; + double hr = r; - double halfR = r/2; - double halfHR = halfR; //hr/2; + double halfR = r/2; + double halfHR = halfR; - int xt0 = Mth::floor(xx - halfR); - int yt0 = Mth::floor(yy - halfHR); - int zt0 = Mth::floor(zz - halfR); + int xt0 = Mth::floor(xx - halfR); + int yt0 = Mth::floor(yy - halfHR); + int zt0 = Mth::floor(zz - halfR); - int xt1 = Mth::floor(xx + halfR); - int yt1 = Mth::floor(yy + halfHR); - int zt1 = Mth::floor(zz + halfR); + int xt1 = Mth::floor(xx + halfR); + int yt1 = Mth::floor(yy + halfHR); + int zt1 = Mth::floor(zz + halfR); - // 4J Stu Added to stop ore features generating areas previously place by game rule generation - if(collisionsExpected && levelGenOptions != nullptr) - { - bool intersects = levelGenOptions->checkIntersects(xt0, yt0, zt0, xt1, yt1, zt1); - if(intersects) - { - //app.DebugPrintf("Skipping ore feature generation as it overlaps a game rule structure\n"); - continue; - } - } + if(collisionsExpected && levelGenOptions != nullptr) + { + bool intersects = levelGenOptions->checkIntersects(xt0, yt0, zt0, xt1, yt1, zt1); + if(intersects) + { + continue; + } + } - // A large % of ore placement is entirely into the air. Attempt to identify some of these early, by check the corners - // of the area we are placing in to see if we are going to (very probably) be entirely above the height stored in the heightmap + if( doEarlyRejectTest ) + { + bool earlyReject = true; + if ( level->getHeightmap(xt0, zt0) >= yt0 ) earlyReject = false; + else if( level->getHeightmap(xt1, zt0) >= yt0 ) earlyReject = false; + else if( level->getHeightmap(xt0, zt1) >= yt0 ) earlyReject = false; + else if( level->getHeightmap(xt1, zt1) >= yt0 ) earlyReject = false; - if( doEarlyRejectTest ) - { - bool earlyReject = true; - if ( level->getHeightmap(xt0, zt0) >= yt0 ) earlyReject = false; - else if( level->getHeightmap(xt1, zt0) >= yt0 ) earlyReject = false; - else if( level->getHeightmap(xt0, zt1) >= yt0 ) earlyReject = false; - else if( level->getHeightmap(xt1, zt1) >= yt0 ) earlyReject = false; + if( earlyReject ) continue; + } - if( earlyReject ) continue; - } + double xdxd,ydyd; - double xdxd,ydyd; + double xd0 = ((xt0 + 0.5) - xx); + double yd0 = ((yt0 + 0.5) - yy); + double zd0 = ((zt0 + 0.5) - zz); - double xd0 = ((xt0 + 0.5) - xx); - double yd0 = ((yt0 + 0.5) - yy); - double zd0 = ((zt0 + 0.5) - zz); + double halfRSq = halfR * halfR; - double halfRSq = halfR * halfR; - - double xd = xd0; + double xd = xd0; for (int x2 = xt0; x2 <= xt1; x2++, xd++) - { - xdxd = xd * xd; + { + xdxd = xd * xd; if (xdxd < halfRSq) - { - double yd = yd0; + { + double yd = yd0; for (int y2 = yt0; y2 <= yt1; y2++, yd++) - { - ydyd = yd * yd; + { + ydyd = yd * yd; if (xdxd + ydyd < halfRSq) - { - double zd = zd0; + { + double zd = zd0; for (int z2 = zt0; z2 <= zt1; z2++, zd++) - { - if (xdxd + ydyd + zd * zd < halfRSq) - { - if ( level->getTile(x2, y2, z2) == targetTile) - { - level->setTileAndData(x2, y2, z2, tile, data, Tile::UPDATE_INVISIBLE_NO_LIGHT); - } + { + if (xdxd + ydyd + zd * zd < halfRSq) + { + + if ( level->hasChunkAt(x2, y2, z2) && level->getTile(x2, y2, z2) == targetTile) + { + level->setTileAndData(x2, y2, z2, tile, data, Tile::UPDATE_INVISIBLE_NO_LIGHT); + } } } - } + } } } } } - PIXEndNamedEvent(); + PIXEndNamedEvent(); + + s_oreFeaturePlacing = false; return true; } \ No newline at end of file