diff options
| author | daoge_cmd <3523206925@qq.com> | 2026-03-01 12:16:08 +0800 |
|---|---|---|
| committer | daoge_cmd <3523206925@qq.com> | 2026-03-01 12:16:08 +0800 |
| commit | b691c43c44ff180d10e7d4a9afc83b98551ff586 (patch) | |
| tree | 3e9849222cbc6ba49f2f1fc6e5fe7179632c7390 /Minecraft.World/StrongholdFeature.cpp | |
| parent | def8cb415354ac390b7e89052a50605285f1aca9 (diff) | |
Initial commit
Diffstat (limited to 'Minecraft.World/StrongholdFeature.cpp')
| -rw-r--r-- | Minecraft.World/StrongholdFeature.cpp | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/Minecraft.World/StrongholdFeature.cpp b/Minecraft.World/StrongholdFeature.cpp new file mode 100644 index 00000000..5372f4f9 --- /dev/null +++ b/Minecraft.World/StrongholdFeature.cpp @@ -0,0 +1,224 @@ +#include "stdafx.h" +#include "StrongholdFeature.h" +#include "StrongholdPieces.h" +#include "net.minecraft.world.level.h" +#include "net.minecraft.world.level.biome.h" +#include "net.minecraft.world.level.dimension.h" +#include "FileHeader.h" +#include "JavaMath.h" + +vector<Biome *> StrongholdFeature::allowedBiomes; + +void StrongholdFeature::staticCtor() +{ + allowedBiomes.push_back(Biome::desert); + allowedBiomes.push_back(Biome::forest); + allowedBiomes.push_back(Biome::extremeHills); + allowedBiomes.push_back(Biome::swampland); + allowedBiomes.push_back(Biome::taiga); + allowedBiomes.push_back(Biome::iceFlats); + allowedBiomes.push_back(Biome::iceMountains); + allowedBiomes.push_back(Biome::desertHills); + allowedBiomes.push_back(Biome::forestHills); + allowedBiomes.push_back(Biome::smallerExtremeHills); + allowedBiomes.push_back(Biome::taigaHills); + allowedBiomes.push_back(Biome::jungle); + allowedBiomes.push_back(Biome::jungleHills); +}; + + +StrongholdFeature::StrongholdFeature() : StructureFeature() +{ + // 4J added initialisers + for (int i = 0; i < strongholdPos_length; i++) + { + strongholdPos[i] = NULL; + } + isSpotSelected = false; +} + +StrongholdFeature::~StrongholdFeature() +{ + for (int i = 0; i < strongholdPos_length; i++) + { + delete strongholdPos[i]; + } +} + +bool StrongholdFeature::isFeatureChunk(int x, int z,bool bIsSuperflat) +{ + if (!isSpotSelected) + { + Random random; + + random.setSeed(level->getSeed()); + double angle = random.nextDouble() * PI * 2.0; + + // 4J Stu - Changed so that we keep trying more until we have found somewhere in the world to place a stronghold + bool hasFoundValidPos = false; + int findAttempts = 0; + do + { + for (int i = 0; i < strongholdPos_length; i++) + { + double dist = 0.0; +#ifdef _LARGE_WORLDS + if(level->dimension->getXZSize() < (2.25f * 32.0f) ) + { + // Xbox360/PS3 distances + dist = (1.25 + random.nextDouble()) * (3 + random.nextInt(4)); + } + else + { + // Original Java + dist = (1.25 + random.nextDouble()) * 32.0; + } +#else + // 4J Stu - Design change: Original spawns at *32 chunks rather than *10 chunks from (0,0) but that is outside our world + // double dist = (1.25 + random->nextDouble()) * 32.0; + // The max of the first part is 2.25, and we have 27 chunks in each direction + // Therefore 27/2.25 = 12, which should be the max of the second part + // The constant part and random part can be tuned to move the strongholds further from the spawn + // 4J Stu - The original (pre-TU9) calculation for selecting a start point could put the stronghold very close to the edge + // of the world, causing some parts to fail to generate. If the save is a newer save then we bring that generation in + if(level->getOriginalSaveVersion() >= SAVE_FILE_VERSION_MOVED_STRONGHOLD) + { + // Post TU9 + // The stronghold cannot extend more than 7 chunks in any direction from the start position + // Therefore as long as the the start x/z are less than 20 it will be fully contained + dist = (1.25 + random.nextDouble()) * (3 + random.nextInt(4)); + } + else + { + // Pre TU9 + dist = (1.25 + random.nextDouble()) * (5.0 + random.nextInt(7)); + } +#endif + + int selectedX = (int) (Math::round(cos(angle) * dist)); + int selectedZ = (int) (Math::round(sin(angle) * dist)); + + TilePos *position = level->getBiomeSource()->findBiome((selectedX << 4) + 8, (selectedZ << 4) + 8, 7 << 4, allowedBiomes, &random); + if (position != NULL) + { + selectedX = position->x >> 4; + selectedZ = position->z >> 4; + +#ifndef _CONTENT_PACKAGE + if(position->x > 2560 || position->x < -2560 || position->z > 2560 || position->z < -2560) + { + __debugbreak(); + } +#endif + + app.DebugPrintf("Placed stronghold in valid biome at (%d, %d), (%d, %d)\n", selectedX, selectedZ, position->x, position->z); + // 4J added + app.AddTerrainFeaturePosition(eTerrainFeature_Stronghold,selectedX,selectedZ); + + // 4J Added + hasFoundValidPos = true; + delete position; + } + else + { + app.DebugPrintf("Placed stronghold in INVALID biome at (%d, %d)\n", selectedX, selectedZ); + } + + delete strongholdPos[i]; + strongholdPos[i] = new ChunkPos(selectedX, selectedZ); + + angle += PI * 2.0 / (double) strongholdPos_length; + } + + // 4J Stu - We want to make sure that we have at least one stronghold in this world + ++findAttempts; + + // 4J Stu - Randomise the angles for retries as well +#ifdef _LARGE_WORLDS + angle = random.nextDouble() * PI * 2.0; +#endif + } + while(!hasFoundValidPos && findAttempts < MAX_STRONGHOLD_ATTEMPTS); + + if(!hasFoundValidPos) + { + // Even if it's not a valid position we are still creating the last one we tried, so store it in the save so Eye of Ender works + // Fix for #81933 - GAMEPLAY: The Eye of Ender occasionally does not appear when used to try and locate the End Portal. + app.AddTerrainFeaturePosition(eTerrainFeature_Stronghold,strongholdPos[0]->x,strongholdPos[0]->z); + } + + isSpotSelected = true; + } + + for (int i = 0; i < strongholdPos_length; i++) + { + bool forcePlacement = false; + LevelGenerationOptions *levelGenOptions = app.getLevelGenerationOptions(); + if( levelGenOptions != NULL ) + { + forcePlacement = levelGenOptions->isFeatureChunk(x,z,eFeature_Stronghold); + } + + ChunkPos *pos = strongholdPos[i]; + if (forcePlacement || (pos && x == pos->x && z == pos->z) ) + { + return true; + } + } + return false; +} + +vector<TilePos> *StrongholdFeature::getGuesstimatedFeaturePositions() +{ + vector<TilePos> *positions = new vector<TilePos>(); + for( int i = 0; i < strongholdPos_length; i++ ) + { + ChunkPos *chunkPos = strongholdPos[i]; + if (chunkPos != NULL) + { + positions->push_back(chunkPos->getMiddleBlockPosition(64)); + } + } + return positions; +} + +StructureStart *StrongholdFeature::createStructureStart(int x, int z) +{ + + StrongholdStart *start = new StrongholdStart(level, random, x, z); + + // 4J - front() was get(0) + while (start->getPieces()->empty() || ((StrongholdPieces::StartPiece *) start->getPieces()->front())->portalRoomPiece == NULL) + { + delete start; + // regenerate stronghold without changing seed + start = new StrongholdStart(level, random, x, z); + } + + return start; + + // System.out.println("Creating stronghold at (" + x + ", " + z + ")"); + // return new StrongholdStart(level, random, x, z); +} + +StrongholdFeature::StrongholdStart::StrongholdStart(Level *level, Random *random, int chunkX, int chunkZ) : StructureStart() +{ + StrongholdPieces::resetPieces(); + + StrongholdPieces::StartPiece *startRoom = new StrongholdPieces::StartPiece(0, random, (chunkX << 4) + 2, (chunkZ << 4) + 2, level); + pieces.push_back(startRoom); + startRoom->addChildren(startRoom, &pieces, random); + + vector<StructurePiece *> *pendingChildren = &startRoom->pendingChildren; + while (!pendingChildren->empty()) + { + int pos = random->nextInt((int)pendingChildren->size()); + AUTO_VAR(it, pendingChildren->begin() + pos); + StructurePiece *structurePiece = *it; + pendingChildren->erase(it); + structurePiece->addChildren(startRoom, &pieces, random); + } + + calculateBoundingBox(); + moveBelowSeaLevel(level, random, 10); +}
\ No newline at end of file |
