aboutsummaryrefslogtreecommitdiff
path: root/Minecraft.World/StrongholdPieces.cpp
diff options
context:
space:
mode:
authordaoge_cmd <3523206925@qq.com>2026-03-01 12:16:08 +0800
committerdaoge_cmd <3523206925@qq.com>2026-03-01 12:16:08 +0800
commitb691c43c44ff180d10e7d4a9afc83b98551ff586 (patch)
tree3e9849222cbc6ba49f2f1fc6e5fe7179632c7390 /Minecraft.World/StrongholdPieces.cpp
parentdef8cb415354ac390b7e89052a50605285f1aca9 (diff)
Initial commit
Diffstat (limited to 'Minecraft.World/StrongholdPieces.cpp')
-rw-r--r--Minecraft.World/StrongholdPieces.cpp1517
1 files changed, 1517 insertions, 0 deletions
diff --git a/Minecraft.World/StrongholdPieces.cpp b/Minecraft.World/StrongholdPieces.cpp
new file mode 100644
index 00000000..0168b2ba
--- /dev/null
+++ b/Minecraft.World/StrongholdPieces.cpp
@@ -0,0 +1,1517 @@
+#include "stdafx.h"
+#include "StrongholdPieces.h"
+#include "net.minecraft.world.level.h"
+#include "net.minecraft.world.level.tile.h"
+#include "net.minecraft.world.level.tile.entity.h"
+#include "net.minecraft.world.level.storage.h"
+#include "net.minecraft.world.level.levelgen.h"
+#include "net.minecraft.world.item.h"
+#include "WeighedTreasure.h"
+#include "FileHeader.h"
+#include "Facing.h"
+
+int StrongholdPieces::totalWeight = 0;
+list<StrongholdPieces::PieceWeight *> StrongholdPieces::currentPieces;
+StrongholdPieces::EPieceClass StrongholdPieces::imposedPiece;
+const bool StrongholdPieces::CHECK_AIR = true;
+
+StrongholdPieces::PieceWeight::PieceWeight(EPieceClass pieceClass, int weight, int maxPlaceCount) : weight(weight)
+{
+ this->placeCount = 0; // 4J added initialiser
+ this->pieceClass = pieceClass;
+ this->maxPlaceCount = maxPlaceCount;
+}
+
+bool StrongholdPieces::PieceWeight::doPlace(int depth)
+{
+ return maxPlaceCount == 0 || placeCount < maxPlaceCount;
+}
+
+bool StrongholdPieces::PieceWeight::isValid()
+{
+ return maxPlaceCount == 0 || placeCount < maxPlaceCount;
+}
+
+void StrongholdPieces::resetPieces()
+{
+ for( AUTO_VAR(it, currentPieces.begin()); it != currentPieces.end(); it++ )
+ {
+ delete (*it);
+ }
+ currentPieces.clear();
+
+ currentPieces.push_back( new PieceWeight(EPieceClass_Straight, 40, 0) );
+ currentPieces.push_back( new PieceWeight(EPieceClass_PrisonHall, 5, 5) );
+ currentPieces.push_back( new PieceWeight(EPieceClass_LeftTurn, 20, 0) );
+ currentPieces.push_back( new PieceWeight(EPieceClass_RightTurn, 20, 0) );
+ currentPieces.push_back( new PieceWeight(EPieceClass_RoomCrossing, 10, 6) );
+ currentPieces.push_back( new PieceWeight(EPieceClass_StraightStairsDown, 5, 5) );
+ currentPieces.push_back( new PieceWeight(EPieceClass_StairsDown, 5, 5) );
+ currentPieces.push_back( new PieceWeight(EPieceClass_FiveCrossing, 5, 4) );
+ currentPieces.push_back( new PieceWeight(EPieceClass_ChestCorridor, 5, 4) );
+ currentPieces.push_back( new PieceWeight_Library(EPieceClass_Library, 10, 2) );
+ currentPieces.push_back( new PieceWeight_PortalRoom(EPieceClass_PortalRoom, 20, 1) );
+
+ imposedPiece = EPieceClass_NULL;
+}
+
+bool StrongholdPieces::updatePieceWeight()
+{
+ bool hasAnyPieces = false;
+ totalWeight = 0;
+ for( AUTO_VAR(it, currentPieces.begin()); it != currentPieces.end(); it++ )
+ {
+ PieceWeight *piece = *it;
+ if (piece->maxPlaceCount > 0 && piece->placeCount < piece->maxPlaceCount)
+ {
+ hasAnyPieces = true;
+ }
+ totalWeight += piece->weight;
+ }
+ return hasAnyPieces;
+}
+
+StrongholdPieces::StrongholdPiece *StrongholdPieces::findAndCreatePieceFactory(EPieceClass pieceClass, list<StructurePiece*> *pieces, Random *random, int footX, int footY, int footZ, int direction, int depth)
+{
+ StrongholdPiece *strongholdPiece = NULL;
+
+ if (pieceClass == EPieceClass_Straight)
+ {
+ strongholdPiece = Straight::createPiece(pieces, random, footX, footY, footZ, direction, depth);
+ }
+ else if (pieceClass == EPieceClass_PrisonHall)
+ {
+ strongholdPiece = PrisonHall::createPiece(pieces, random, footX, footY, footZ, direction, depth);
+ }
+ else if (pieceClass == EPieceClass_LeftTurn)
+ {
+ strongholdPiece = LeftTurn::createPiece(pieces, random, footX, footY, footZ, direction, depth);
+ }
+ else if (pieceClass == EPieceClass_RightTurn)
+ {
+ strongholdPiece = RightTurn::createPiece(pieces, random, footX, footY, footZ, direction, depth);
+ }
+ else if (pieceClass == EPieceClass_RoomCrossing)
+ {
+ strongholdPiece = RoomCrossing::createPiece(pieces, random, footX, footY, footZ, direction, depth);
+ }
+ else if (pieceClass == EPieceClass_StraightStairsDown)
+ {
+ strongholdPiece = StraightStairsDown::createPiece(pieces, random, footX, footY, footZ, direction, depth);
+ }
+ else if (pieceClass == EPieceClass_StairsDown)
+ {
+ strongholdPiece = StairsDown::createPiece(pieces, random, footX, footY, footZ, direction, depth);
+ }
+ else if (pieceClass == EPieceClass_FiveCrossing)
+ {
+ strongholdPiece = FiveCrossing::createPiece(pieces, random, footX, footY, footZ, direction, depth);
+ }
+ else if (pieceClass == EPieceClass_ChestCorridor)
+ {
+ strongholdPiece = ChestCorridor::createPiece(pieces, random, footX, footY, footZ, direction, depth);
+ }
+ else if (pieceClass == EPieceClass_Library)
+ {
+ strongholdPiece = Library::createPiece(pieces, random, footX, footY, footZ, direction, depth);
+ }
+ else if (pieceClass == EPieceClass_PortalRoom)
+ {
+ strongholdPiece = PortalRoom::createPiece(pieces, random, footX, footY, footZ, direction, depth);
+ }
+
+
+ return strongholdPiece;
+}
+
+StrongholdPieces::StrongholdPiece *StrongholdPieces::generatePieceFromSmallDoor(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int depth)
+{
+ if (!updatePieceWeight())
+ {
+ return NULL;
+ }
+
+ if (imposedPiece != EPieceClass_NULL)
+ {
+ StrongholdPiece *strongholdPiece = findAndCreatePieceFactory(imposedPiece, pieces, random, footX, footY, footZ, direction, depth);
+ imposedPiece = EPieceClass_NULL;
+
+ if (strongholdPiece != NULL)
+ {
+ return strongholdPiece;
+ }
+ }
+
+ int numAttempts = 0;
+ while (numAttempts < 5)
+ {
+ numAttempts++;
+
+ int weightSelection = random->nextInt(totalWeight);
+ for( AUTO_VAR(it, currentPieces.begin()); it != currentPieces.end(); it++ )
+ {
+ PieceWeight *piece = *it;
+ weightSelection -= piece->weight;
+ if (weightSelection < 0)
+ {
+ if (!piece->doPlace(depth) || piece == startPiece->previousPiece)
+ {
+ break;
+ }
+
+ StrongholdPiece *strongholdPiece = findAndCreatePieceFactory(piece->pieceClass, pieces, random, footX, footY, footZ, direction, depth);
+ if (strongholdPiece != NULL)
+ {
+ piece->placeCount++;
+ startPiece->previousPiece = piece;
+
+ if (!piece->isValid())
+ {
+ currentPieces.remove(piece);
+ }
+ return strongholdPiece;
+ }
+ }
+ }
+ }
+ {
+ BoundingBox *box = FillerCorridor::findPieceBox(pieces, random, footX, footY, footZ, direction);
+ if (box != NULL && box->y0 > 1)
+ {
+ return new FillerCorridor(depth, random, box, direction);
+ }
+ if(box != NULL) delete box;
+ }
+
+ return NULL;
+}
+
+StructurePiece *StrongholdPieces::generateAndAddPiece(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int depth)
+{
+ if (depth > MAX_DEPTH)
+ {
+ return NULL;
+ }
+ if (abs(footX - startPiece->getBoundingBox()->x0) > 3 * 16 || abs(footZ - startPiece->getBoundingBox()->z0) > 3 * 16)
+ {
+ // Force attempt at spawning a portal room
+ if(startPiece->m_level->getOriginalSaveVersion() >= SAVE_FILE_VERSION_MOVED_STRONGHOLD && !startPiece->m_level->getLevelData()->getHasStrongholdEndPortal())
+ {
+ for( AUTO_VAR(it, currentPieces.begin()); it != currentPieces.end(); it++ )
+ {
+ PieceWeight *piece = *it;
+
+ if(piece->pieceClass != EPieceClass_PortalRoom) continue;
+
+#ifndef _CONTENT_PACKAGE
+ printf("Portal room forcing attempt\n");
+#endif
+ StrongholdPiece *strongholdPiece = PortalRoom::createPiece(pieces, random, footX, footY, footZ, direction, depth);
+ if (strongholdPiece != NULL)
+ {
+ piece->placeCount++;
+ startPiece->previousPiece = piece;
+
+ if (!piece->isValid())
+ {
+ currentPieces.remove(piece);
+ }
+#ifndef _CONTENT_PACKAGE
+ printf("Success\n");
+#endif
+ return strongholdPiece;
+ }
+ }
+ }
+ return NULL;
+ }
+
+ StructurePiece *newPiece = generatePieceFromSmallDoor(startPiece, pieces, random, footX, footY, footZ, direction, depth + 1);
+ if (newPiece != NULL)
+ {
+ pieces->push_back(newPiece);
+ startPiece->pendingChildren.push_back(newPiece);
+// newPiece.addChildren(startPiece, pieces, random, depth + 1);
+ }
+ return newPiece;
+}
+
+StrongholdPieces::StrongholdPiece::StrongholdPiece(int genDepth) : StructurePiece(genDepth)
+{
+}
+
+void StrongholdPieces::StrongholdPiece::generateSmallDoor(Level *level, Random *random, BoundingBox *chunkBB, StrongholdPieces::StrongholdPiece::SmallDoorType doorType, int footX, int footY, int footZ)
+{
+ switch (doorType)
+ {
+ default:
+ case OPENING:
+ generateBox(level, chunkBB, footX, footY, footZ, footX + SMALL_DOOR_WIDTH - 1, footY + SMALL_DOOR_HEIGHT - 1, footZ, 0, 0, false);
+ break;
+ case WOOD_DOOR:
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, footX, footY, footZ, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, footX, footY + 1, footZ, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, footX, footY + 2, footZ, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, footX + 1, footY + 2, footZ, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, footX + 2, footY + 2, footZ, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, footX + 2, footY + 1, footZ, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, footX + 2, footY, footZ, chunkBB);
+ placeBlock(level, Tile::door_wood_Id, 0, footX + 1, footY, footZ, chunkBB);
+ placeBlock(level, Tile::door_wood_Id, DoorTile::UPPER_BIT, footX + 1, footY + 1, footZ, chunkBB);
+ break;
+ case GRATES:
+ placeBlock(level, 0, 0, footX + 1, footY, footZ, chunkBB);
+ placeBlock(level, 0, 0, footX + 1, footY + 1, footZ, chunkBB);
+ placeBlock(level, Tile::ironFence_Id, 0, footX, footY, footZ, chunkBB);
+ placeBlock(level, Tile::ironFence_Id, 0, footX, footY + 1, footZ, chunkBB);
+ placeBlock(level, Tile::ironFence_Id, 0, footX, footY + 2, footZ, chunkBB);
+ placeBlock(level, Tile::ironFence_Id, 0, footX + 1, footY + 2, footZ, chunkBB);
+ placeBlock(level, Tile::ironFence_Id, 0, footX + 2, footY + 2, footZ, chunkBB);
+ placeBlock(level, Tile::ironFence_Id, 0, footX + 2, footY + 1, footZ, chunkBB);
+ placeBlock(level, Tile::ironFence_Id, 0, footX + 2, footY, footZ, chunkBB);
+ break;
+ case IRON_DOOR:
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, footX, footY, footZ, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, footX, footY + 1, footZ, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, footX, footY + 2, footZ, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, footX + 1, footY + 2, footZ, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, footX + 2, footY + 2, footZ, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, footX + 2, footY + 1, footZ, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, footX + 2, footY, footZ, chunkBB);
+ placeBlock(level, Tile::door_iron_Id, 0, footX + 1, footY, footZ, chunkBB);
+ placeBlock(level, Tile::door_iron_Id, DoorTile::UPPER_BIT, footX + 1, footY + 1, footZ, chunkBB);
+ placeBlock(level, Tile::button_stone_Id, getOrientationData(Tile::button_stone_Id, 4), footX + 2, footY + 1, footZ + 1, chunkBB);
+ placeBlock(level, Tile::button_stone_Id, getOrientationData(Tile::button_stone_Id, 3), footX + 2, footY + 1, footZ - 1, chunkBB);
+ break;
+ }
+
+}
+
+StrongholdPieces::StrongholdPiece::SmallDoorType StrongholdPieces::StrongholdPiece::randomSmallDoor(Random *random)
+{
+ int selection = random->nextInt(5);
+ switch (selection)
+ {
+ default:
+ case 0:
+ case 1:
+ return OPENING;
+ case 2:
+ return WOOD_DOOR;
+ case 3:
+ return GRATES;
+ case 4:
+ return IRON_DOOR;
+ }
+}
+
+StructurePiece *StrongholdPieces::StrongholdPiece::generateSmallDoorChildForward(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int xOff, int yOff)
+{
+ switch (orientation)
+ {
+ case Direction::NORTH:
+ return generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 + xOff, boundingBox->y0 + yOff, boundingBox->z0 - 1, orientation, getGenDepth());
+ case Direction::SOUTH:
+ return generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 + xOff, boundingBox->y0 + yOff, boundingBox->z1 + 1, orientation, getGenDepth());
+ case Direction::WEST:
+ return generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 - 1, boundingBox->y0 + yOff, boundingBox->z0 + xOff, orientation, getGenDepth());
+ case Direction::EAST:
+ return generateAndAddPiece(startPiece, pieces, random, boundingBox->x1 + 1, boundingBox->y0 + yOff, boundingBox->z0 + xOff, orientation, getGenDepth());
+ }
+ return NULL;
+}
+
+StructurePiece *StrongholdPieces::StrongholdPiece::generateSmallDoorChildLeft(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int yOff, int zOff)
+{
+ switch (orientation)
+ {
+ case Direction::NORTH:
+ return generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 - 1, boundingBox->y0 + yOff, boundingBox->z0 + zOff, Direction::WEST, getGenDepth());
+ case Direction::SOUTH:
+ return generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 - 1, boundingBox->y0 + yOff, boundingBox->z0 + zOff, Direction::WEST, getGenDepth());
+ case Direction::WEST:
+ return generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 + zOff, boundingBox->y0 + yOff, boundingBox->z0 - 1, Direction::NORTH, getGenDepth());
+ case Direction::EAST:
+ return generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 + zOff, boundingBox->y0 + yOff, boundingBox->z0 - 1, Direction::NORTH, getGenDepth());
+ }
+ return NULL;
+}
+
+StructurePiece *StrongholdPieces::StrongholdPiece::generateSmallDoorChildRight(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int yOff, int zOff)
+{
+ switch (orientation)
+ {
+ case Direction::NORTH:
+ return generateAndAddPiece(startPiece, pieces, random, boundingBox->x1 + 1, boundingBox->y0 + yOff, boundingBox->z0 + zOff, Direction::EAST, getGenDepth());
+ case Direction::SOUTH:
+ return generateAndAddPiece(startPiece, pieces, random, boundingBox->x1 + 1, boundingBox->y0 + yOff, boundingBox->z0 + zOff, Direction::EAST, getGenDepth());
+ case Direction::WEST:
+ return generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 + zOff, boundingBox->y0 + yOff, boundingBox->z1 + 1, Direction::SOUTH, getGenDepth());
+ case Direction::EAST:
+ return generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 + zOff, boundingBox->y0 + yOff, boundingBox->z1 + 1, Direction::SOUTH, getGenDepth());
+ }
+ return NULL;
+}
+
+bool StrongholdPieces::StrongholdPiece::isOkBox(BoundingBox *box, StartPiece *startRoom)
+{
+ //return box != NULL && box->y0 > LOWEST_Y_POSITION;
+
+ bool bIsOk = false;
+
+ if(box != NULL)
+ {
+ if( box->y0 > LOWEST_Y_POSITION ) bIsOk = true;
+
+ if( startRoom != NULL && startRoom->m_level->getOriginalSaveVersion() >= SAVE_FILE_VERSION_MOVED_STRONGHOLD )
+ {
+ int xzSize = startRoom->m_level->getLevelData()->getXZSize();
+ int blockMin = -( (xzSize << 4) / 2) + 1;
+ int blockMax = ( (xzSize << 4) / 2 ) - 1;
+
+ if(box->x0 <= blockMin) bIsOk = false;
+ if(box->z0 <= blockMin) bIsOk = false;
+ if(box->x1 >= blockMax) bIsOk = false;
+ if(box->z1 >= blockMax) bIsOk = false;
+ }
+ }
+
+ return bIsOk;
+}
+
+StrongholdPieces::FillerCorridor::FillerCorridor(int genDepth, Random *random, BoundingBox *corridorBox, int direction) : StrongholdPiece(genDepth),
+ steps((direction == Direction::NORTH || direction == Direction::SOUTH) ? corridorBox->getZSpan() : corridorBox->getXSpan())
+{
+ orientation = direction;
+ boundingBox = corridorBox;
+}
+
+BoundingBox *StrongholdPieces::FillerCorridor::findPieceBox(list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction)
+{
+ const int maxLength = 3;
+
+ BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, -1, -1, 0, 5, 5, maxLength + 1, direction);
+
+ StructurePiece *collisionPiece = StructurePiece::findCollisionPiece(pieces, box);
+
+ if (collisionPiece == NULL)
+ {
+ delete box;
+ // the filler must collide with something in order to be
+ // generated
+ return NULL;
+ }
+
+ if (collisionPiece->getBoundingBox()->y0 == box->y0)
+ {
+ delete box;
+ // attempt to make a smaller piece until it fits
+ for (int depth = maxLength; depth >= 1; depth--)
+ {
+ box = BoundingBox::orientBox(footX, footY, footZ, -1, -1, 0, 5, 5, depth - 1, direction);
+ if (!collisionPiece->getBoundingBox()->intersects(box))
+ {
+ delete box;
+ // the corridor has shrunk enough to fit, but make it
+ // one step too big to build an entrance into the other
+ // block
+ return BoundingBox::orientBox(footX, footY, footZ, -1, -1, 0, 5, 5, depth, direction);
+ }
+ delete box;
+ }
+ }
+
+ return NULL;
+}
+
+bool StrongholdPieces::FillerCorridor::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
+{
+ if (edgesLiquid(level, chunkBB))
+ {
+ return false;
+ }
+
+ // filler corridor
+ for (int i = 0; i < steps; i++)
+ {
+ // row 0
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, 0, 0, i, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, 1, 0, i, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, 2, 0, i, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, 3, 0, i, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, 4, 0, i, chunkBB);
+ // row 1-3
+ for (int y = 1; y <= 3; y++)
+ {
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, 0, y, i, chunkBB);
+ placeBlock(level, 0, 0, 1, y, i, chunkBB);
+ placeBlock(level, 0, 0, 2, y, i, chunkBB);
+ placeBlock(level, 0, 0, 3, y, i, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, 4, y, i, chunkBB);
+ }
+ // row 4
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, 0, 4, i, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, 1, 4, i, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, 2, 4, i, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, 3, 4, i, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, 4, 4, i, chunkBB);
+ }
+
+ return true;
+}
+
+StrongholdPieces::StairsDown::StairsDown(int genDepth, Random *random, int west, int north) : StrongholdPiece(genDepth), isSource(true), entryDoor(OPENING)
+{
+ orientation = random->nextInt(4);
+
+ switch (orientation)
+ {
+ case Direction::NORTH:
+ case Direction::SOUTH:
+ boundingBox = new BoundingBox(west, 64, north, west + width - 1, 64 + height - 1, north + depth - 1);
+ break;
+ default:
+ boundingBox = new BoundingBox(west, 64, north, west + depth - 1, 64 + height - 1, north + width - 1);
+ break;
+ }
+}
+
+StrongholdPieces::StairsDown::StairsDown(int genDepth, Random *random, BoundingBox *stairsBox, int direction) : StrongholdPiece(genDepth), isSource(false), entryDoor(randomSmallDoor(random))
+{
+ orientation = direction;
+ boundingBox = stairsBox;
+}
+
+void StrongholdPieces::StairsDown::addChildren(StructurePiece *startPiece, list<StructurePiece *> *pieces, Random *random)
+{
+ if( isSource )
+ {
+ imposedPiece = EPieceClass_FiveCrossing;
+ }
+ generateSmallDoorChildForward((StartPiece *) startPiece, pieces, random, 1, 1);
+}
+
+StrongholdPieces::StairsDown *StrongholdPieces::StairsDown::createPiece(list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth)
+{
+ BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, -1, 4 - height, 0, width, height, depth, direction);
+
+ StartPiece *startPiece = NULL;
+ if(pieces != NULL) startPiece = ((StrongholdPieces::StartPiece *) pieces->front());
+
+ if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL)
+ {
+ delete box;
+ return NULL;
+ }
+
+ return new StairsDown(genDepth, random, box, direction);
+}
+
+bool StrongholdPieces::StairsDown::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
+{
+ if (edgesLiquid(level, chunkBB))
+ {
+ return false;
+ }
+
+ // bounding walls
+ generateBox(level, chunkBB, 0, 0, 0, width - 1, height - 1, depth - 1, CHECK_AIR, random, (BlockSelector *)smoothStoneSelector);
+ // entry door
+ generateSmallDoor(level, random, chunkBB, entryDoor, 1, height - SMALL_DOOR_HEIGHT - 1, 0);
+ // exit door
+ generateSmallDoor(level, random, chunkBB, OPENING, 1, 1, depth - 1);
+
+ // stair steps
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, 2, 6, 1, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, 1, 5, 1, chunkBB);
+ placeBlock(level, Tile::stoneSlabHalf_Id, StoneSlabTile::STONE_SLAB, 1, 6, 1, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, 1, 5, 2, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, 1, 4, 3, chunkBB);
+ placeBlock(level, Tile::stoneSlabHalf_Id, StoneSlabTile::STONE_SLAB, 1, 5, 3, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, 2, 4, 3, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, 3, 3, 3, chunkBB);
+ placeBlock(level, Tile::stoneSlabHalf_Id, StoneSlabTile::STONE_SLAB, 3, 4, 3, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, 3, 3, 2, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, 3, 2, 1, chunkBB);
+ placeBlock(level, Tile::stoneSlabHalf_Id, StoneSlabTile::STONE_SLAB, 3, 3, 1, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, 2, 2, 1, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, 1, 1, 1, chunkBB);
+ placeBlock(level, Tile::stoneSlabHalf_Id, StoneSlabTile::STONE_SLAB, 1, 2, 1, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, 1, 1, 2, chunkBB);
+ placeBlock(level, Tile::stoneSlabHalf_Id, StoneSlabTile::STONE_SLAB, 1, 1, 3, chunkBB);
+
+ return true;
+}
+
+StrongholdPieces::StartPiece::StartPiece(int genDepth, Random *random, int west, int north, Level *level) : StairsDown(0, random, west, north)
+{
+ // 4J added initialisers
+ isLibraryAdded = false;
+ previousPiece = NULL;
+ portalRoomPiece = NULL;
+
+ m_level = level;
+}
+
+TilePos *StrongholdPieces::StartPiece::getLocatorPosition()
+{
+ if( portalRoomPiece != NULL )
+ {
+ return portalRoomPiece->getLocatorPosition();
+ }
+ return StairsDown::getLocatorPosition();
+}
+
+StrongholdPieces::Straight::Straight(int genDepth, Random *random, BoundingBox *stairsBox, int direction) : StrongholdPiece(genDepth),
+ entryDoor(randomSmallDoor(random)),
+ leftChild(random->nextInt(2) == 0),
+ rightChild(random->nextInt(2) == 0)
+{
+ orientation = direction;
+ boundingBox = stairsBox;
+}
+
+void StrongholdPieces::Straight::addChildren(StructurePiece *startPiece, list<StructurePiece *> *pieces, Random *random)
+{
+ generateSmallDoorChildForward((StartPiece *) startPiece, pieces, random, 1, 1);
+ if (leftChild) generateSmallDoorChildLeft((StartPiece *) startPiece, pieces, random, 1, 2);
+ if (rightChild) generateSmallDoorChildRight((StartPiece *) startPiece, pieces, random, 1, 2);
+}
+
+StrongholdPieces::Straight *StrongholdPieces::Straight::createPiece(list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth)
+{
+ BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, -1, -1, 0, width, height, depth, direction);
+
+ StartPiece *startPiece = NULL;
+ if(pieces != NULL) startPiece = ((StrongholdPieces::StartPiece *) pieces->front());
+
+ if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL)
+ {
+ delete box;
+ return NULL;
+ }
+
+ return new Straight(genDepth, random, box, direction);
+}
+
+bool StrongholdPieces::Straight::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
+{
+ if (edgesLiquid(level, chunkBB))
+ {
+ return false;
+ }
+
+ // bounding walls
+ generateBox(level, chunkBB, 0, 0, 0, width - 1, height - 1, depth - 1, CHECK_AIR, random, (BlockSelector *)smoothStoneSelector);
+ // entry door
+ generateSmallDoor(level, random, chunkBB, entryDoor, 1, height - SMALL_DOOR_HEIGHT - 1, 0);
+ // exit door
+ generateSmallDoor(level, random, chunkBB, OPENING, 1, 1, depth - 1);
+
+ maybeGenerateBlock(level, chunkBB, random, .1f, 1, 2, 1, Tile::torch_Id, 0);
+ maybeGenerateBlock(level, chunkBB, random, .1f, 3, 2, 1, Tile::torch_Id, 0);
+ maybeGenerateBlock(level, chunkBB, random, .1f, 1, 2, 5, Tile::torch_Id, 0);
+ maybeGenerateBlock(level, chunkBB, random, .1f, 3, 2, 5, Tile::torch_Id, 0);
+
+ if (leftChild)
+ {
+ generateBox(level, chunkBB, 0, 1, 2, 0, 3, 4, 0, 0, false);
+ }
+ if (rightChild)
+ {
+ generateBox(level, chunkBB, 4, 1, 2, 4, 3, 4, 0, 0, false);
+ }
+
+ return true;
+}
+
+WeighedTreasure *StrongholdPieces::ChestCorridor::treasureItems[TREASURE_ITEMS_COUNT] =
+{
+ new WeighedTreasure(Item::enderPearl_Id, 0, 1, 1, 10),
+ new WeighedTreasure(Item::diamond_Id, 0, 1, 3, 3),
+ new WeighedTreasure(Item::ironIngot_Id, 0, 1, 5, 10),
+ new WeighedTreasure(Item::goldIngot_Id, 0, 1, 3, 5),
+ new WeighedTreasure(Item::redStone_Id, 0, 4, 9, 5),
+ new WeighedTreasure(Item::bread_Id, 0, 1, 3, 15),
+ new WeighedTreasure(Item::apple_Id, 0, 1, 3, 15),
+ new WeighedTreasure(Item::pickAxe_iron_Id, 0, 1, 1, 5),
+ new WeighedTreasure(Item::sword_iron_Id, 0, 1, 1, 5),
+ new WeighedTreasure(Item::chestplate_iron_Id, 0, 1, 1, 5),
+ new WeighedTreasure(Item::helmet_iron_Id, 0, 1, 1, 5),
+ new WeighedTreasure(Item::leggings_iron_Id, 0, 1, 1, 5),
+ new WeighedTreasure(Item::boots_iron_Id, 0, 1, 1, 5),
+ new WeighedTreasure(Item::apple_gold_Id, 0, 1, 1, 1)
+};
+
+StrongholdPieces::ChestCorridor::ChestCorridor(int genDepth, Random *random, BoundingBox *stairsBox, int direction) : StrongholdPiece(genDepth), entryDoor(randomSmallDoor(random))
+{
+ orientation = direction;
+ boundingBox = stairsBox;
+}
+
+void StrongholdPieces::ChestCorridor::addChildren(StructurePiece *startPiece, list<StructurePiece *> *pieces, Random *random)
+{
+ generateSmallDoorChildForward((StartPiece *) startPiece, pieces, random, 1, 1);
+}
+
+StrongholdPieces::ChestCorridor *StrongholdPieces::ChestCorridor::createPiece(list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth)
+{
+ BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, -1, -1, 0, width, height, depth, direction);
+
+ StartPiece *startPiece = NULL;
+ if(pieces != NULL) startPiece = ((StrongholdPieces::StartPiece *) pieces->front());
+
+ if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL)
+ {
+ delete box;
+ return NULL;
+ }
+
+ return new ChestCorridor(genDepth, random, box, direction);
+}
+
+bool StrongholdPieces::ChestCorridor::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
+{
+ if (edgesLiquid(level, chunkBB))
+ {
+ return false;
+ }
+
+ // bounding walls
+ generateBox(level, chunkBB, 0, 0, 0, width - 1, height - 1, depth - 1, CHECK_AIR, random, (BlockSelector *)smoothStoneSelector);
+ // entry door
+ generateSmallDoor(level, random, chunkBB, entryDoor, 1, height - SMALL_DOOR_HEIGHT - 1, 0);
+ // exit door
+ generateSmallDoor(level, random, chunkBB, OPENING, 1, 1, depth - 1);
+
+ // chest placement
+ generateBox(level, chunkBB, 3, 1, 2, 3, 1, 4, Tile::stoneBrickSmooth_Id, Tile::stoneBrickSmooth_Id, false);
+ placeBlock(level, Tile::stoneSlabHalf_Id, StoneSlabTile::SMOOTHBRICK_SLAB, 3, 1, 1, chunkBB);
+ placeBlock(level, Tile::stoneSlabHalf_Id, StoneSlabTile::SMOOTHBRICK_SLAB, 3, 1, 5, chunkBB);
+ placeBlock(level, Tile::stoneSlabHalf_Id, StoneSlabTile::SMOOTHBRICK_SLAB, 3, 2, 2, chunkBB);
+ placeBlock(level, Tile::stoneSlabHalf_Id, StoneSlabTile::SMOOTHBRICK_SLAB, 3, 2, 4, chunkBB);
+ for (int z = 2; z <= 4; z++)
+ {
+ placeBlock(level, Tile::stoneSlabHalf_Id, StoneSlabTile::SMOOTHBRICK_SLAB, 2, 1, z, chunkBB);
+ }
+
+ if (!hasPlacedChest)
+ {
+ int y = getWorldY(2);
+ int x = getWorldX(3, 3), z = getWorldZ(3, 3);
+ if (chunkBB->isInside(x, y, z))
+ {
+ hasPlacedChest = true;
+ createChest(level, chunkBB, random, 3, 2, 3, WeighedTreasure::addToTreasure(WeighedTreasureArray(treasureItems,TREASURE_ITEMS_COUNT), Item::enchantedBook->createForRandomTreasure(random)), 2 + random->nextInt(2));
+ }
+ }
+
+ return true;
+}
+
+StrongholdPieces::StraightStairsDown::StraightStairsDown(int genDepth, Random *random, BoundingBox *stairsBox, int direction) : StrongholdPiece(genDepth), entryDoor(randomSmallDoor(random))
+{
+ orientation = direction;
+ boundingBox = stairsBox;
+}
+
+void StrongholdPieces::StraightStairsDown::addChildren(StructurePiece *startPiece, list<StructurePiece *> *pieces, Random *random)
+{
+ generateSmallDoorChildForward((StartPiece *) startPiece, pieces, random, 1, 1);
+}
+
+StrongholdPieces::StraightStairsDown *StrongholdPieces::StraightStairsDown::createPiece(list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth)
+{
+ BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, -1, 4 - height, 0, width, height, depth, direction);
+
+ StartPiece *startPiece = NULL;
+ if(pieces != NULL) startPiece = ((StrongholdPieces::StartPiece *) pieces->front());
+
+ if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL)
+ {
+ delete box;
+ return NULL;
+ }
+
+ return new StraightStairsDown(genDepth, random, box, direction);
+}
+
+bool StrongholdPieces::StraightStairsDown::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
+{
+ if (edgesLiquid(level, chunkBB))
+ {
+ return false;
+ }
+
+ // bounding walls
+ generateBox(level, chunkBB, 0, 0, 0, width - 1, height - 1, depth - 1, CHECK_AIR, random, (BlockSelector *)smoothStoneSelector);
+ // entry door
+ generateSmallDoor(level, random, chunkBB, entryDoor, 1, height - SMALL_DOOR_HEIGHT - 1, 0);
+ // exit door
+ generateSmallDoor(level, random, chunkBB, OPENING, 1, 1, depth - 1);
+
+ // stairs
+ int orientationData = getOrientationData(Tile::stairs_stone_Id, 2);
+ for (int i = 0; i < 6; i++)
+ {
+ placeBlock(level, Tile::stairs_stone_Id, orientationData, 1, height - 5 - i, 1 + i, chunkBB);
+ placeBlock(level, Tile::stairs_stone_Id, orientationData, 2, height - 5 - i, 1 + i, chunkBB);
+ placeBlock(level, Tile::stairs_stone_Id, orientationData, 3, height - 5 - i, 1 + i, chunkBB);
+ if (i < 5)
+ {
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, 1, height - 6 - i, 1 + i, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, 2, height - 6 - i, 1 + i, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, 3, height - 6 - i, 1 + i, chunkBB);
+ }
+ }
+
+ return true;
+}
+
+StrongholdPieces::LeftTurn::LeftTurn(int genDepth, Random *random, BoundingBox *stairsBox, int direction) : StrongholdPiece(genDepth), entryDoor(randomSmallDoor(random))
+{
+ orientation = direction;
+ boundingBox = stairsBox;
+}
+
+void StrongholdPieces::LeftTurn::addChildren(StructurePiece *startPiece, list<StructurePiece *> *pieces, Random *random)
+{
+ if (orientation == Direction::NORTH || orientation == Direction::EAST)
+ {
+ generateSmallDoorChildLeft((StartPiece *) startPiece, pieces, random, 1, 1);
+ }
+ else
+ {
+ generateSmallDoorChildRight((StartPiece *) startPiece, pieces, random, 1, 1);
+ }
+}
+
+StrongholdPieces::LeftTurn *StrongholdPieces::LeftTurn::createPiece(list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth)
+{
+ BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, -1, -1, 0, width, height, depth, direction);
+
+ StartPiece *startPiece = NULL;
+ if(pieces != NULL) startPiece = ((StrongholdPieces::StartPiece *) pieces->front());
+
+ if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL)
+ {
+ delete box;
+ return NULL;
+ }
+
+ return new LeftTurn(genDepth, random, box, direction);
+}
+
+bool StrongholdPieces::LeftTurn::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
+{
+ if (edgesLiquid(level, chunkBB))
+ {
+ return false;
+ }
+
+ // bounding walls
+ generateBox(level, chunkBB, 0, 0, 0, width - 1, height - 1, depth - 1, CHECK_AIR, random, (BlockSelector *)smoothStoneSelector);
+ // entry door
+ generateSmallDoor(level, random, chunkBB, entryDoor, 1, height - SMALL_DOOR_HEIGHT - 1, 0);
+ // exit opening
+ if (orientation == Direction::NORTH || orientation == Direction::EAST)
+ {
+ generateBox(level, chunkBB, 0, 1, 1, 0, 3, 3, 0, 0, false);
+ }
+ else
+ {
+ generateBox(level, chunkBB, 4, 1, 1, 4, 3, 3, 0, 0, false);
+ }
+
+ return true;
+}
+
+StrongholdPieces::RightTurn::RightTurn(int genDepth, Random *random, BoundingBox *stairsBox, int direction) : LeftTurn(genDepth, random, stairsBox, direction)
+{
+}
+
+void StrongholdPieces::RightTurn::addChildren(StructurePiece *startPiece, list<StructurePiece *> *pieces, Random *random)
+{
+ if (orientation == Direction::NORTH || orientation == Direction::EAST)
+ {
+ generateSmallDoorChildRight((StartPiece *) startPiece, pieces, random, 1, 1);
+ }
+ else
+ {
+ generateSmallDoorChildLeft((StartPiece *) startPiece, pieces, random, 1, 1);
+ }
+}
+
+bool StrongholdPieces::RightTurn::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
+{
+ if (edgesLiquid(level, chunkBB))
+ {
+ return false;
+ }
+
+ // bounding walls
+ generateBox(level, chunkBB, 0, 0, 0, width - 1, height - 1, depth - 1, CHECK_AIR, random, (BlockSelector *)smoothStoneSelector);
+ // entry door
+ generateSmallDoor(level, random, chunkBB, entryDoor, 1, height - SMALL_DOOR_HEIGHT - 1, 0);
+ // exit opening
+ if (orientation == Direction::NORTH || orientation == Direction::EAST)
+ {
+ generateBox(level, chunkBB, 4, 1, 1, 4, 3, 3, 0, 0, false);
+ }
+ else
+ {
+ generateBox(level, chunkBB, 0, 1, 1, 0, 3, 3, 0, 0, false);
+ }
+
+ return true;
+}
+
+
+StrongholdPieces::RoomCrossing::RoomCrossing(int genDepth, Random *random, BoundingBox *stairsBox, int direction) : StrongholdPiece(genDepth), entryDoor(randomSmallDoor(random)), type(random->nextInt(5))
+{
+ orientation = direction;
+ boundingBox = stairsBox;
+}
+
+void StrongholdPieces::RoomCrossing::addChildren(StructurePiece *startPiece, list<StructurePiece *> *pieces, Random *random)
+{
+ generateSmallDoorChildForward((StartPiece*) startPiece, pieces, random, 4, 1);
+ generateSmallDoorChildLeft((StartPiece*) startPiece, pieces, random, 1, 4);
+ generateSmallDoorChildRight((StartPiece*) startPiece, pieces, random, 1, 4);
+}
+
+StrongholdPieces::RoomCrossing *StrongholdPieces::RoomCrossing::createPiece(list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth)
+{
+ BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, -4, -1, 0, width, height, depth, direction);
+
+ StartPiece *startPiece = NULL;
+ if(pieces != NULL) startPiece = ((StrongholdPieces::StartPiece *) pieces->front());
+
+ if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL)
+ {
+ delete box;
+ return NULL;
+ }
+
+ return new RoomCrossing(genDepth, random, box, direction);
+}
+
+WeighedTreasure *StrongholdPieces::RoomCrossing::smallTreasureItems[SMALL_TREASURE_ITEMS_COUNT] =
+{
+ new WeighedTreasure(Item::ironIngot_Id, 0, 1, 5, 10),
+ new WeighedTreasure(Item::goldIngot_Id, 0, 1, 3, 5),
+ new WeighedTreasure(Item::redStone_Id, 0, 4, 9, 5),
+ new WeighedTreasure(Item::coal_Id, CoalItem::STONE_COAL, 3, 8, 10),
+ new WeighedTreasure(Item::bread_Id, 0, 1, 3, 15),
+ new WeighedTreasure(Item::apple_Id, 0, 1, 3, 15),
+ new WeighedTreasure(Item::pickAxe_iron_Id, 0, 1, 1, 1),
+};
+
+bool StrongholdPieces::RoomCrossing::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
+{
+ if (edgesLiquid(level, chunkBB))
+ {
+ return false;
+ }
+
+ // bounding walls
+ generateBox(level, chunkBB, 0, 0, 0, width - 1, height - 1, depth - 1, CHECK_AIR, random, (BlockSelector *)smoothStoneSelector);
+ // entry door
+ generateSmallDoor(level, random, chunkBB, entryDoor, 4, 1, 0);
+ // exit openings
+ generateBox(level, chunkBB, 4, 1, depth - 1, 6, 3, depth - 1, 0, 0, false);
+ generateBox(level, chunkBB, 0, 1, 4, 0, 3, 6, 0, 0, false);
+ generateBox(level, chunkBB, width - 1, 1, 4, width - 1, 3, 6, 0, 0, false);
+
+ switch (type)
+ {
+ default:
+ break;
+ case 0:
+ // middle torch pillar
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, 5, 1, 5, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, 5, 2, 5, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, 5, 3, 5, chunkBB);
+ placeBlock(level, Tile::torch_Id, 0, 4, 3, 5, chunkBB);
+ placeBlock(level, Tile::torch_Id, 0, 6, 3, 5, chunkBB);
+ placeBlock(level, Tile::torch_Id, 0, 5, 3, 4, chunkBB);
+ placeBlock(level, Tile::torch_Id, 0, 5, 3, 6, chunkBB);
+ placeBlock(level, Tile::stoneSlabHalf_Id, 0, 4, 1, 4, chunkBB);
+ placeBlock(level, Tile::stoneSlabHalf_Id, 0, 4, 1, 5, chunkBB);
+ placeBlock(level, Tile::stoneSlabHalf_Id, 0, 4, 1, 6, chunkBB);
+ placeBlock(level, Tile::stoneSlabHalf_Id, 0, 6, 1, 4, chunkBB);
+ placeBlock(level, Tile::stoneSlabHalf_Id, 0, 6, 1, 5, chunkBB);
+ placeBlock(level, Tile::stoneSlabHalf_Id, 0, 6, 1, 6, chunkBB);
+ placeBlock(level, Tile::stoneSlabHalf_Id, 0, 5, 1, 4, chunkBB);
+ placeBlock(level, Tile::stoneSlabHalf_Id, 0, 5, 1, 6, chunkBB);
+ break;
+ case 1:
+ {
+ for (int i = 0; i < 5; i++)
+ {
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, 3, 1, 3 + i, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, 7, 1, 3 + i, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, 3 + i, 1, 3, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, 3 + i, 1, 7, chunkBB);
+ }
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, 5, 1, 5, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, 5, 2, 5, chunkBB);
+ placeBlock(level, Tile::stoneBrickSmooth_Id, 0, 5, 3, 5, chunkBB);
+ placeBlock(level, Tile::water_Id, 0, 5, 4, 5, chunkBB);
+ }
+ break;
+ case 2:
+ {
+ for (int z = 1; z <= 9; z++)
+ {
+ placeBlock(level, Tile::stoneBrick_Id, 0, 1, 3, z, chunkBB);
+ placeBlock(level, Tile::stoneBrick_Id, 0, 9, 3, z, chunkBB);
+ }
+ for (int x = 1; x <= 9; x++)
+ {
+ placeBlock(level, Tile::stoneBrick_Id, 0, x, 3, 1, chunkBB);
+ placeBlock(level, Tile::stoneBrick_Id, 0, x, 3, 9, chunkBB);
+ }
+ placeBlock(level, Tile::stoneBrick_Id, 0, 5, 1, 4, chunkBB);
+ placeBlock(level, Tile::stoneBrick_Id, 0, 5, 1, 6, chunkBB);
+ placeBlock(level, Tile::stoneBrick_Id, 0, 5, 3, 4, chunkBB);
+ placeBlock(level, Tile::stoneBrick_Id, 0, 5, 3, 6, chunkBB);
+ placeBlock(level, Tile::stoneBrick_Id, 0, 4, 1, 5, chunkBB);
+ placeBlock(level, Tile::stoneBrick_Id, 0, 6, 1, 5, chunkBB);
+ placeBlock(level, Tile::stoneBrick_Id, 0, 4, 3, 5, chunkBB);
+ placeBlock(level, Tile::stoneBrick_Id, 0, 6, 3, 5, chunkBB);
+ for (int y = 1; y <= 3; y++)
+ {
+ placeBlock(level, Tile::stoneBrick_Id, 0, 4, y, 4, chunkBB);
+ placeBlock(level, Tile::stoneBrick_Id, 0, 6, y, 4, chunkBB);
+ placeBlock(level, Tile::stoneBrick_Id, 0, 4, y, 6, chunkBB);
+ placeBlock(level, Tile::stoneBrick_Id, 0, 6, y, 6, chunkBB);
+ }
+ placeBlock(level, Tile::torch_Id, 0, 5, 3, 5, chunkBB);
+ for (int z = 2; z <= 8; z++)
+ {
+ placeBlock(level, Tile::wood_Id, 0, 2, 3, z, chunkBB);
+ placeBlock(level, Tile::wood_Id, 0, 3, 3, z, chunkBB);
+ if (z <= 3 || z >= 7)
+ {
+ placeBlock(level, Tile::wood_Id, 0, 4, 3, z, chunkBB);
+ placeBlock(level, Tile::wood_Id, 0, 5, 3, z, chunkBB);
+ placeBlock(level, Tile::wood_Id, 0, 6, 3, z, chunkBB);
+ }
+ placeBlock(level, Tile::wood_Id, 0, 7, 3, z, chunkBB);
+ placeBlock(level, Tile::wood_Id, 0, 8, 3, z, chunkBB);
+ }
+ placeBlock(level, Tile::ladder_Id, getOrientationData(Tile::ladder_Id, Facing::WEST), 9, 1, 3, chunkBB);
+ placeBlock(level, Tile::ladder_Id, getOrientationData(Tile::ladder_Id, Facing::WEST), 9, 2, 3, chunkBB);
+ placeBlock(level, Tile::ladder_Id, getOrientationData(Tile::ladder_Id, Facing::WEST), 9, 3, 3, chunkBB);
+
+ createChest(level, chunkBB, random, 3, 4, 8, WeighedTreasure::addToTreasure(WeighedTreasureArray(smallTreasureItems,SMALL_TREASURE_ITEMS_COUNT), Item::enchantedBook->createForRandomTreasure(random)), 1 + random->nextInt(4));
+ // System.out.println("Created chest at " + getWorldX(3, 8) +
+ // "," + getWorldY(4) + "," + getWorldZ(3, 8));
+
+ }
+ break;
+ }
+ return true;
+}
+
+StrongholdPieces::PrisonHall::PrisonHall(int genDepth, Random *random, BoundingBox *stairsBox, int direction) : StrongholdPiece(genDepth), entryDoor(randomSmallDoor(random))
+{
+ orientation = direction;
+ boundingBox = stairsBox;
+}
+
+void StrongholdPieces::PrisonHall::addChildren(StructurePiece *startPiece, list<StructurePiece *> *pieces, Random *random)
+{
+ generateSmallDoorChildForward((StartPiece *) startPiece, pieces, random, 1, 1);
+}
+
+StrongholdPieces::PrisonHall *StrongholdPieces::PrisonHall::createPiece(list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth)
+{
+ BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, -1, -1, 0, width, height, depth, direction);
+
+ StartPiece *startPiece = NULL;
+ if(pieces != NULL) startPiece = ((StrongholdPieces::StartPiece *) pieces->front());
+
+ if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL)
+ {
+ delete box;
+ return NULL;
+ }
+
+ return new PrisonHall(genDepth, random, box, direction);
+}
+
+bool StrongholdPieces::PrisonHall::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
+{
+ if (edgesLiquid(level, chunkBB))
+ {
+ return false;
+ }
+
+ // bounding walls
+ generateBox(level, chunkBB, 0, 0, 0, width - 1, height - 1, depth - 1, CHECK_AIR, random, (BlockSelector *)smoothStoneSelector);
+ // entry door
+ generateSmallDoor(level, random, chunkBB, entryDoor, 1, 1, 0);
+ // exit openings
+ generateBox(level, chunkBB, 1, 1, depth - 1, 3, 3, depth - 1, 0, 0, false);
+
+ // door pillars
+ generateBox(level, chunkBB, 4, 1, 1, 4, 3, 1, false, random, (BlockSelector *)smoothStoneSelector);
+ generateBox(level, chunkBB, 4, 1, 3, 4, 3, 3, false, random, (BlockSelector *)smoothStoneSelector);
+ generateBox(level, chunkBB, 4, 1, 7, 4, 3, 7, false, random, (BlockSelector *)smoothStoneSelector);
+ generateBox(level, chunkBB, 4, 1, 9, 4, 3, 9, false, random, (BlockSelector *)smoothStoneSelector);
+
+ // grates
+ generateBox(level, chunkBB, 4, 1, 4, 4, 3, 6, Tile::ironFence_Id, Tile::ironFence_Id, false);
+ generateBox(level, chunkBB, 5, 1, 5, 7, 3, 5, Tile::ironFence_Id, Tile::ironFence_Id, false);
+
+ // doors
+ placeBlock(level, Tile::ironFence_Id, 0, 4, 3, 2, chunkBB);
+ placeBlock(level, Tile::ironFence_Id, 0, 4, 3, 8, chunkBB);
+ placeBlock(level, Tile::door_iron_Id, getOrientationData(Tile::door_iron_Id, 3), 4, 1, 2, chunkBB);
+ placeBlock(level, Tile::door_iron_Id, getOrientationData(Tile::door_iron_Id, 3) + DoorTile::UPPER_BIT, 4, 2, 2, chunkBB);
+ placeBlock(level, Tile::door_iron_Id, getOrientationData(Tile::door_iron_Id, 3), 4, 1, 8, chunkBB);
+ placeBlock(level, Tile::door_iron_Id, getOrientationData(Tile::door_iron_Id, 3) + DoorTile::UPPER_BIT, 4, 2, 8, chunkBB);
+
+ return true;
+
+}
+
+StrongholdPieces::Library::Library(int genDepth, Random *random, BoundingBox *roomBox, int direction) : StrongholdPiece(genDepth),
+ entryDoor(randomSmallDoor(random)),
+ isTall(roomBox->getYSpan() > height)
+{
+ orientation = direction;
+ boundingBox = roomBox;
+}
+
+StrongholdPieces::Library *StrongholdPieces::Library::createPiece(list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth)
+{
+ // attempt to make a tall library first
+ BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, -4, -1, 0, width, tallHeight, depth, direction);
+
+ StartPiece *startPiece = NULL;
+ if(pieces != NULL) startPiece = ((StrongholdPieces::StartPiece *) pieces->front());
+
+ if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL)
+ {
+ delete box;
+ // make a short library
+ box = BoundingBox::orientBox(footX, footY, footZ, -4, -1, 0, width, height, depth, direction);
+
+ if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL)
+ {
+ delete box;
+ return NULL;
+ }
+ }
+
+ return new Library(genDepth, random, box, direction);
+}
+
+WeighedTreasure *StrongholdPieces::Library::libraryTreasureItems[LIBRARY_TREASURE_ITEMS_COUNT] =
+{
+ new WeighedTreasure(Item::book_Id, 0, 1, 3, 20),
+ new WeighedTreasure(Item::paper_Id, 0, 2, 7, 20),
+ new WeighedTreasure(Item::map_Id, 0, 1, 1, 1),
+ new WeighedTreasure(Item::compass_Id, 0, 1, 1, 1),
+};
+
+bool StrongholdPieces::Library::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
+{
+ if (edgesLiquid(level, chunkBB))
+ {
+ return false;
+ }
+
+ int currentHeight = tallHeight;
+ if (!isTall)
+ {
+ currentHeight = height;
+ }
+
+ // bounding walls
+ generateBox(level, chunkBB, 0, 0, 0, width - 1, currentHeight - 1, depth - 1, CHECK_AIR, random, (BlockSelector *)smoothStoneSelector);
+ // entry door
+ generateSmallDoor(level, random, chunkBB, entryDoor, 4, 1, 0);
+
+ // place sparse cob webs
+ generateMaybeBox(level, chunkBB, random, .07f, 2, 1, 1, width - 1 - 2, height - 2, depth - 2, Tile::web_Id, Tile::web_Id, false);
+
+ const int bookLeft = 1;
+ const int bookRight = width - 2;
+
+ // place library walls
+ for (int d = 1; d <= depth - 2; d++) {
+ if (((d - 1) % 4) == 0) {
+ generateBox(level, chunkBB, bookLeft, 1, d, bookLeft, 4, d, Tile::wood_Id, Tile::wood_Id, false);
+ generateBox(level, chunkBB, bookRight, 1, d, bookRight, 4, d, Tile::wood_Id, Tile::wood_Id, false);
+
+ placeBlock(level, Tile::torch_Id, 0, 2, 3, d, chunkBB);
+ placeBlock(level, Tile::torch_Id, 0, width - 3, 3, d, chunkBB);
+
+ if (isTall)
+ {
+ generateBox(level, chunkBB, bookLeft, 6, d, bookLeft, 9, d, Tile::wood_Id, Tile::wood_Id, false);
+ generateBox(level, chunkBB, bookRight, 6, d, bookRight, 9, d, Tile::wood_Id, Tile::wood_Id, false);
+ }
+ }
+ else
+ {
+ generateBox(level, chunkBB, bookLeft, 1, d, bookLeft, 4, d, Tile::bookshelf_Id, Tile::bookshelf_Id, false);
+ generateBox(level, chunkBB, bookRight, 1, d, bookRight, 4, d, Tile::bookshelf_Id, Tile::bookshelf_Id, false);
+
+ if (isTall)
+ {
+ generateBox(level, chunkBB, bookLeft, 6, d, bookLeft, 9, d, Tile::bookshelf_Id, Tile::bookshelf_Id, false);
+ generateBox(level, chunkBB, bookRight, 6, d, bookRight, 9, d, Tile::bookshelf_Id, Tile::bookshelf_Id, false);
+ }
+ }
+ }
+
+ // place book shelves
+ for (int d = 3; d < depth - 3; d += 2)
+ {
+ generateBox(level, chunkBB, 3, 1, d, 4, 3, d, Tile::bookshelf_Id, Tile::bookshelf_Id, false);
+ generateBox(level, chunkBB, 6, 1, d, 7, 3, d, Tile::bookshelf_Id, Tile::bookshelf_Id, false);
+ generateBox(level, chunkBB, 9, 1, d, 10, 3, d, Tile::bookshelf_Id, Tile::bookshelf_Id, false);
+ }
+
+ if (isTall)
+ {
+ // create balcony
+ generateBox(level, chunkBB, 1, 5, 1, 3, 5, depth - 2, Tile::wood_Id, Tile::wood_Id, false);
+ generateBox(level, chunkBB, width - 4, 5, 1, width - 2, 5, depth - 2, Tile::wood_Id, Tile::wood_Id, false);
+ generateBox(level, chunkBB, 4, 5, 1, width - 5, 5, 2, Tile::wood_Id, Tile::wood_Id, false);
+ generateBox(level, chunkBB, 4, 5, depth - 3, width - 5, 5, depth - 2, Tile::wood_Id, Tile::wood_Id, false);
+
+ placeBlock(level, Tile::wood_Id, 0, width - 5, 5, depth - 4, chunkBB);
+ placeBlock(level, Tile::wood_Id, 0, width - 6, 5, depth - 4, chunkBB);
+ placeBlock(level, Tile::wood_Id, 0, width - 5, 5, depth - 5, chunkBB);
+
+ // balcony fences
+ generateBox(level, chunkBB, 3, 6, 2, 3, 6, depth - 3, Tile::fence_Id, Tile::fence_Id, false);
+ generateBox(level, chunkBB, width - 4, 6, 2, width - 4, 6, depth - 5, Tile::fence_Id, Tile::fence_Id, false);
+ generateBox(level, chunkBB, 4, 6, 2, width - 5, 6, 2, Tile::fence_Id, Tile::fence_Id, false);
+ generateBox(level, chunkBB, 4, 6, depth - 3, 8, 6, depth - 3, Tile::fence_Id, Tile::fence_Id, false);
+ placeBlock(level, Tile::fence_Id, 0, width - 5, 6, depth - 4, chunkBB);
+ placeBlock(level, Tile::fence_Id, 0, width - 6, 6, depth - 4, chunkBB);
+ placeBlock(level, Tile::fence_Id, 0, width - 5, 6, depth - 5, chunkBB);
+
+ // ladder
+ int orientationData = getOrientationData(Tile::ladder_Id, 3);
+ placeBlock(level, Tile::ladder_Id, orientationData, width - 4, 1, depth - 2, chunkBB);
+ placeBlock(level, Tile::ladder_Id, orientationData, width - 4, 2, depth - 2, chunkBB);
+ placeBlock(level, Tile::ladder_Id, orientationData, width - 4, 3, depth - 2, chunkBB);
+ placeBlock(level, Tile::ladder_Id, orientationData, width - 4, 4, depth - 2, chunkBB);
+ placeBlock(level, Tile::ladder_Id, orientationData, width - 4, 5, depth - 2, chunkBB);
+ placeBlock(level, Tile::ladder_Id, orientationData, width - 4, 6, depth - 2, chunkBB);
+ placeBlock(level, Tile::ladder_Id, orientationData, width - 4, 7, depth - 2, chunkBB);
+
+ // chandelier
+ int x = width / 2;
+ int z = depth / 2;
+ placeBlock(level, Tile::fence_Id, 0, x - 1, tallHeight - 2, z, chunkBB);
+ placeBlock(level, Tile::fence_Id, 0, x, tallHeight - 2, z, chunkBB);
+ placeBlock(level, Tile::fence_Id, 0, x - 1, tallHeight - 3, z, chunkBB);
+ placeBlock(level, Tile::fence_Id, 0, x, tallHeight - 3, z, chunkBB);
+ placeBlock(level, Tile::fence_Id, 0, x - 1, tallHeight - 4, z, chunkBB);
+ placeBlock(level, Tile::fence_Id, 0, x, tallHeight - 4, z, chunkBB);
+
+ placeBlock(level, Tile::fence_Id, 0, x - 2, tallHeight - 4, z, chunkBB);
+ placeBlock(level, Tile::fence_Id, 0, x + 1, tallHeight - 4, z, chunkBB);
+ placeBlock(level, Tile::fence_Id, 0, x - 1, tallHeight - 4, z - 1, chunkBB);
+ placeBlock(level, Tile::fence_Id, 0, x - 1, tallHeight - 4, z + 1, chunkBB);
+ placeBlock(level, Tile::fence_Id, 0, x, tallHeight - 4, z - 1, chunkBB);
+ placeBlock(level, Tile::fence_Id, 0, x, tallHeight - 4, z + 1, chunkBB);
+
+ placeBlock(level, Tile::torch_Id, 0, x - 2, tallHeight - 3, z, chunkBB);
+ placeBlock(level, Tile::torch_Id, 0, x + 1, tallHeight - 3, z, chunkBB);
+ placeBlock(level, Tile::torch_Id, 0, x - 1, tallHeight - 3, z - 1, chunkBB);
+ placeBlock(level, Tile::torch_Id, 0, x - 1, tallHeight - 3, z + 1, chunkBB);
+ placeBlock(level, Tile::torch_Id, 0, x, tallHeight - 3, z - 1, chunkBB);
+ placeBlock(level, Tile::torch_Id, 0, x, tallHeight - 3, z + 1, chunkBB);
+ }
+
+ // place chests
+ createChest(level, chunkBB, random, 3, 3, 5, WeighedTreasure::addToTreasure(WeighedTreasureArray(libraryTreasureItems,LIBRARY_TREASURE_ITEMS_COUNT), Item::enchantedBook->createForRandomTreasure(random, 1, 5, 2)), 1 + random->nextInt(4));
+ if (isTall)
+ {
+ placeBlock(level, 0, 0, width - 2, tallHeight - 2, 1, chunkBB);
+ createChest(level, chunkBB, random, width - 2, tallHeight - 3, 1, WeighedTreasure::addToTreasure(WeighedTreasureArray(libraryTreasureItems,LIBRARY_TREASURE_ITEMS_COUNT), Item::enchantedBook->createForRandomTreasure(random, 1, 5, 2)), 1 + random->nextInt(4));
+ }
+
+ return true;
+
+}
+
+StrongholdPieces::FiveCrossing::FiveCrossing(int genDepth, Random *random, BoundingBox *stairsBox, int direction) : StrongholdPiece(genDepth), entryDoor(randomSmallDoor(random))
+{
+ orientation = direction;
+ boundingBox = stairsBox;
+
+ leftLow = random->nextBoolean();
+ leftHigh = random->nextBoolean();
+ rightLow = random->nextBoolean();
+ rightHigh = random->nextInt(3) > 0;
+}
+
+void StrongholdPieces::FiveCrossing::addChildren(StructurePiece *startPiece, list<StructurePiece *> *pieces, Random *random)
+{
+ int zOffA = 3;
+ int zOffB = 5;
+ // compensate for weird negative-facing behaviour
+ if (orientation == Direction::WEST || orientation == Direction::NORTH)
+ {
+ zOffA = depth - 3 - zOffA;
+ zOffB = depth - 3 - zOffB;
+ }
+
+ generateSmallDoorChildForward((StartPiece *) startPiece, pieces, random, 5, 1);
+ if (leftLow) generateSmallDoorChildLeft((StartPiece *) startPiece, pieces, random, zOffA, 1);
+ if (leftHigh) generateSmallDoorChildLeft((StartPiece *) startPiece, pieces, random, zOffB, 7);
+ if (rightLow) generateSmallDoorChildRight((StartPiece *) startPiece, pieces, random, zOffA, 1);
+ if (rightHigh) generateSmallDoorChildRight((StartPiece *) startPiece, pieces, random, zOffB, 7);
+}
+
+StrongholdPieces::FiveCrossing *StrongholdPieces::FiveCrossing::createPiece(list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth)
+{
+ BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, -4, -3, 0, width, height, depth, direction);
+
+ StartPiece *startPiece = NULL;
+ if(pieces != NULL) startPiece = ((StrongholdPieces::StartPiece *) pieces->front());
+
+ if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL)
+ {
+ delete box;
+ return NULL;
+ }
+
+ return new FiveCrossing(genDepth, random, box, direction);
+}
+
+bool StrongholdPieces::FiveCrossing::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
+{
+ if (edgesLiquid(level, chunkBB))
+ {
+ return false;
+ }
+
+ // bounding walls
+ generateBox(level, chunkBB, 0, 0, 0, width - 1, height - 1, depth - 1, CHECK_AIR, random, (BlockSelector *)smoothStoneSelector);
+ // entry door
+ generateSmallDoor(level, random, chunkBB, entryDoor, 4, 3, 0);
+
+ // exit openings
+ if (leftLow) generateBox(level, chunkBB, 0, 3, 1, 0, 5, 3, 0, 0, false);
+ if (rightLow) generateBox(level, chunkBB, 9, 3, 1, 9, 5, 3, 0, 0, false);
+ if (leftHigh) generateBox(level, chunkBB, 0, 5, 7, 0, 7, 9, 0, 0, false);
+ if (rightHigh) generateBox(level, chunkBB, 9, 5, 7, 9, 7, 9, 0, 0, false);
+ generateBox(level, chunkBB, 5, 1, 10, 7, 3, 10, 0, 0, false);
+
+ // main floor
+ generateBox(level, chunkBB, 1, 2, 1, 8, 2, 6, false, random, (BlockSelector *)smoothStoneSelector);
+ // side walls
+ generateBox(level, chunkBB, 4, 1, 5, 4, 4, 9, false, random, (BlockSelector *)smoothStoneSelector);
+ generateBox(level, chunkBB, 8, 1, 5, 8, 4, 9, false, random, (BlockSelector *)smoothStoneSelector);
+ // upper floor
+ generateBox(level, chunkBB, 1, 4, 7, 3, 4, 9, false, random, (BlockSelector *)smoothStoneSelector);
+
+ // left stairs
+ generateBox(level, chunkBB, 1, 3, 5, 3, 3, 6, false, random, (BlockSelector *)smoothStoneSelector);
+ generateBox(level, chunkBB, 1, 3, 4, 3, 3, 4, Tile::stoneSlabHalf_Id, Tile::stoneSlabHalf_Id, false);
+ generateBox(level, chunkBB, 1, 4, 6, 3, 4, 6, Tile::stoneSlabHalf_Id, Tile::stoneSlabHalf_Id, false);
+
+ // lower stairs
+ generateBox(level, chunkBB, 5, 1, 7, 7, 1, 8, false, random, (BlockSelector *)smoothStoneSelector);
+ generateBox(level, chunkBB, 5, 1, 9, 7, 1, 9, Tile::stoneSlabHalf_Id, Tile::stoneSlabHalf_Id, false);
+ generateBox(level, chunkBB, 5, 2, 7, 7, 2, 7, Tile::stoneSlabHalf_Id, Tile::stoneSlabHalf_Id, false);
+
+ // bridge
+ generateBox(level, chunkBB, 4, 5, 7, 4, 5, 9, Tile::stoneSlabHalf_Id, Tile::stoneSlabHalf_Id, false);
+ generateBox(level, chunkBB, 8, 5, 7, 8, 5, 9, Tile::stoneSlabHalf_Id, Tile::stoneSlabHalf_Id, false);
+ generateBox(level, chunkBB, 5, 5, 7, 7, 5, 9, Tile::stoneSlab_Id, Tile::stoneSlab_Id, false);
+ placeBlock(level, Tile::torch_Id, 0, 6, 5, 6, chunkBB);
+
+ return true;
+
+}
+
+StrongholdPieces::PortalRoom::PortalRoom(int genDepth, Random *random, BoundingBox *box, int direction) : StrongholdPiece(genDepth)
+{
+ hasPlacedMobSpawner = false;
+ orientation = direction;
+ boundingBox = box;
+}
+
+void StrongholdPieces::PortalRoom::addChildren(StructurePiece *startPiece, list<StructurePiece *> *pieces, Random *random)
+{
+ if (startPiece != NULL)
+ {
+ ((StartPiece *) startPiece)->portalRoomPiece = this;
+ }
+}
+
+StrongholdPieces::PortalRoom *StrongholdPieces::PortalRoom::createPiece(list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth)
+{
+ BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, -4, -1, 0, width, height, depth, direction);
+
+ // 4J Added so that we can check that Portals stay within the bounds of the world (which they ALWAYS should anyway)
+ StartPiece *startPiece = NULL;
+ if(pieces != NULL) startPiece = ((StrongholdPieces::StartPiece *) pieces->front());
+
+ if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL)
+ {
+ delete box;
+ return NULL;
+ }
+
+ return new PortalRoom(genDepth, random, box, direction);
+}
+
+bool StrongholdPieces::PortalRoom::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
+{
+ // bounding walls
+ generateBox(level, chunkBB, 0, 0, 0, width - 1, height - 1, depth - 1, false, random, (BlockSelector *)smoothStoneSelector);
+ // entry door
+ generateSmallDoor(level, random, chunkBB, GRATES, 4, 1, 0);
+
+ // inner roof row
+ int y = height - 2;
+ generateBox(level, chunkBB, 1, y, 1, 1, y, depth - 2, false, random, (BlockSelector *)smoothStoneSelector);
+ generateBox(level, chunkBB, width - 2, y, 1, width - 2, y, depth - 2, false, random, (BlockSelector *)smoothStoneSelector);
+ generateBox(level, chunkBB, 2, y, 1, width - 3, y, 2, false, random, (BlockSelector *)smoothStoneSelector);
+ generateBox(level, chunkBB, 2, y, depth - 2, width - 3, y, depth - 2, false, random, (BlockSelector *)smoothStoneSelector);
+
+ // entrance lava pools
+ generateBox(level, chunkBB, 1, 1, 1, 2, 1, 4, false, random, (BlockSelector *)smoothStoneSelector);
+ generateBox(level, chunkBB, width - 3, 1, 1, width - 2, 1, 4, false, random, (BlockSelector *)smoothStoneSelector);
+ generateBox(level, chunkBB, 1, 1, 1, 1, 1, 3, Tile::lava_Id, Tile::lava_Id, false);
+ generateBox(level, chunkBB, width - 2, 1, 1, width - 2, 1, 3, Tile::lava_Id, Tile::lava_Id, false);
+
+ // portal lava pool
+ generateBox(level, chunkBB, 3, 1, 8, 7, 1, 12, false, random, (BlockSelector *)smoothStoneSelector);
+ generateBox(level, chunkBB, 4, 1, 9, 6, 1, 11, Tile::lava_Id, Tile::lava_Id, false);
+
+ // wall decorations
+ for (int z = 3; z < depth - 2; z += 2)
+ {
+ generateBox(level, chunkBB, 0, 3, z, 0, 4, z, Tile::ironFence_Id, Tile::ironFence_Id, false);
+ generateBox(level, chunkBB, width - 1, 3, z, width - 1, 4, z, Tile::ironFence_Id, Tile::ironFence_Id, false);
+ }
+ for (int x = 2; x < width - 2; x += 2)
+ {
+ generateBox(level, chunkBB, x, 3, depth - 1, x, 4, depth - 1, Tile::ironFence_Id, Tile::ironFence_Id, false);
+ }
+
+ // stair
+ int orientationData = getOrientationData(Tile::stairs_stoneBrickSmooth_Id, 3);
+ generateBox(level, chunkBB, 4, 1, 5, 6, 1, 7, false, random, (BlockSelector *)smoothStoneSelector);
+ generateBox(level, chunkBB, 4, 2, 6, 6, 2, 7, false, random, (BlockSelector *)smoothStoneSelector);
+ generateBox(level, chunkBB, 4, 3, 7, 6, 3, 7, false, random, (BlockSelector *)smoothStoneSelector);
+ for (int x = 4; x <= 6; x++)
+ {
+ placeBlock(level, Tile::stairs_stoneBrickSmooth_Id, orientationData, x, 1, 4, chunkBB);
+ placeBlock(level, Tile::stairs_stoneBrickSmooth_Id, orientationData, x, 2, 5, chunkBB);
+ placeBlock(level, Tile::stairs_stoneBrickSmooth_Id, orientationData, x, 3, 6, chunkBB);
+ }
+
+ int north = Direction::NORTH;
+ int south = Direction::SOUTH;
+ int east = Direction::EAST;
+ int west = Direction::WEST;
+
+ switch (orientation)
+ {
+ case Direction::SOUTH:
+ north = Direction::SOUTH;
+ south = Direction::NORTH;
+ break;
+ case Direction::EAST:
+ north = Direction::EAST;
+ south = Direction::WEST;
+ east = Direction::SOUTH;
+ west = Direction::NORTH;
+ break;
+ case Direction::WEST:
+ north = Direction::WEST;
+ south = Direction::EAST;
+ east = Direction::SOUTH;
+ west = Direction::NORTH;
+ break;
+ }
+
+ // 4J-PB - Removed for Christmas update since we don't have The End
+
+ // 4J-PB - not going to remove it, so that maps generated will have it in, but it can't be activated
+ placeBlock(level, Tile::endPortalFrameTile_Id, north + ((random->nextFloat() > 0.9f) ? TheEndPortalFrameTile::EYE_BIT : 0), 4, 3, 8, chunkBB);
+ placeBlock(level, Tile::endPortalFrameTile_Id, north + ((random->nextFloat() > 0.9f) ? TheEndPortalFrameTile::EYE_BIT : 0), 5, 3, 8, chunkBB);
+ placeBlock(level, Tile::endPortalFrameTile_Id, north + ((random->nextFloat() > 0.9f) ? TheEndPortalFrameTile::EYE_BIT : 0), 6, 3, 8, chunkBB);
+ placeBlock(level, Tile::endPortalFrameTile_Id, south + ((random->nextFloat() > 0.9f) ? TheEndPortalFrameTile::EYE_BIT : 0), 4, 3, 12, chunkBB);
+ placeBlock(level, Tile::endPortalFrameTile_Id, south + ((random->nextFloat() > 0.9f) ? TheEndPortalFrameTile::EYE_BIT : 0), 5, 3, 12, chunkBB);
+ placeBlock(level, Tile::endPortalFrameTile_Id, south + ((random->nextFloat() > 0.9f) ? TheEndPortalFrameTile::EYE_BIT : 0), 6, 3, 12, chunkBB);
+ placeBlock(level, Tile::endPortalFrameTile_Id, east + ((random->nextFloat() > 0.9f) ? TheEndPortalFrameTile::EYE_BIT : 0), 3, 3, 9, chunkBB);
+ placeBlock(level, Tile::endPortalFrameTile_Id, east + ((random->nextFloat() > 0.9f) ? TheEndPortalFrameTile::EYE_BIT : 0), 3, 3, 10, chunkBB);
+ placeBlock(level, Tile::endPortalFrameTile_Id, east + ((random->nextFloat() > 0.9f) ? TheEndPortalFrameTile::EYE_BIT : 0), 3, 3, 11, chunkBB);
+ placeBlock(level, Tile::endPortalFrameTile_Id, west + ((random->nextFloat() > 0.9f) ? TheEndPortalFrameTile::EYE_BIT : 0), 7, 3, 9, chunkBB);
+ placeBlock(level, Tile::endPortalFrameTile_Id, west + ((random->nextFloat() > 0.9f) ? TheEndPortalFrameTile::EYE_BIT : 0), 7, 3, 10, chunkBB);
+ placeBlock(level, Tile::endPortalFrameTile_Id, west + ((random->nextFloat() > 0.9f) ? TheEndPortalFrameTile::EYE_BIT : 0), 7, 3, 11, chunkBB);
+
+
+ if (!hasPlacedMobSpawner)
+ {
+ y = getWorldY(3);
+ int x = getWorldX(5, 6), z = getWorldZ(5, 6);
+ if (chunkBB->isInside(x, y, z))
+ {
+ // 4J Stu - The mob spawner location is close enough for the map icon display, and this ensures that we only need to set the position once
+ app.AddTerrainFeaturePosition(eTerrainFeature_StrongholdEndPortal,x,z);
+ level->getLevelData()->setXStrongholdEndPortal(x);
+ level->getLevelData()->setZStrongholdEndPortal(z);
+ level->getLevelData()->setHasStrongholdEndPortal();
+
+ hasPlacedMobSpawner = true;
+ level->setTile(x, y, z, Tile::mobSpawner_Id);
+ shared_ptr<MobSpawnerTileEntity> entity = dynamic_pointer_cast<MobSpawnerTileEntity>(level->getTileEntity(x, y, z));
+ if (entity != NULL) entity->setEntityId(L"Silverfish");
+ }
+ }
+
+ return true;
+
+}
+
+void StrongholdPieces::SmoothStoneSelector::next(Random *random, int worldX, int worldY, int worldZ, bool isEdge)
+{
+ if (isEdge)
+ {
+ nextId = Tile::stoneBrickSmooth_Id;
+
+ float selection = random->nextFloat();
+ if (selection < 0.2f)
+ {
+ nextData = SmoothStoneBrickTile::TYPE_CRACKED;
+ }
+ else if (selection < 0.5f)
+ {
+ nextData = SmoothStoneBrickTile::TYPE_MOSSY;
+ }
+ else if (selection < 0.55f)
+ {
+ nextId = Tile::monsterStoneEgg_Id;
+ nextData = StoneMonsterTile::HOST_STONEBRICK;
+ }
+ else
+ {
+ nextData = 0;
+ }
+ }
+ else
+ {
+ nextId = 0;
+ nextData = 0;
+ }
+}
+
+const StrongholdPieces::SmoothStoneSelector *StrongholdPieces::smoothStoneSelector = new SmoothStoneSelector();