the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
1#include "stdafx.h"
2#include "StrongholdPieces.h"
3#include "net.minecraft.world.level.h"
4#include "net.minecraft.world.level.tile.h"
5#include "net.minecraft.world.level.tile.entity.h"
6#include "net.minecraft.world.level.storage.h"
7#include "net.minecraft.world.level.levelgen.h"
8#include "net.minecraft.world.level.levelgen.structure.h"
9#include "net.minecraft.world.item.h"
10#include "WeighedTreasure.h"
11#include "FileHeader.h"
12#include "Facing.h"
13
14int StrongholdPieces::totalWeight = 0;
15list<StrongholdPieces::PieceWeight *> StrongholdPieces::currentPieces;
16StrongholdPieces::EPieceClass StrongholdPieces::imposedPiece;
17const bool StrongholdPieces::CHECK_AIR = true;
18
19void StrongholdPieces::loadStatic()
20{
21 StructureFeatureIO::setPieceId(eStructurePiece_ChestCorridor, ChestCorridor::Create, L"SHCC");
22 StructureFeatureIO::setPieceId(eStructurePiece_FillerCorridor, FillerCorridor::Create, L"SHFC");
23 StructureFeatureIO::setPieceId(eStructurePiece_FiveCrossing, FiveCrossing::Create, L"SH5C");
24 StructureFeatureIO::setPieceId(eStructurePiece_LeftTurn, LeftTurn::Create, L"SHLT");
25 StructureFeatureIO::setPieceId(eStructurePiece_Library, Library::Create, L"SHLi");
26 StructureFeatureIO::setPieceId(eStructurePiece_PortalRoom, PortalRoom::Create, L"SHPR");
27 StructureFeatureIO::setPieceId(eStructurePiece_PrisonHall, PrisonHall::Create, L"SHPH");
28 StructureFeatureIO::setPieceId(eStructurePiece_RightTurn, RightTurn::Create, L"SHRT");
29 StructureFeatureIO::setPieceId(eStructurePiece_StrongholdRoomCrossing, RoomCrossing::Create, L"SHRC");
30 StructureFeatureIO::setPieceId(eStructurePiece_StairsDown, StairsDown::Create, L"SHSD");
31 StructureFeatureIO::setPieceId(eStructurePiece_StrongholdStartPiece, StartPiece::Create, L"SHStart");
32 StructureFeatureIO::setPieceId(eStructurePiece_Straight, Straight::Create, L"SHS");
33 StructureFeatureIO::setPieceId(eStructurePiece_StraightStairsDown, StraightStairsDown::Create, L"SHSSD");
34}
35
36StrongholdPieces::PieceWeight::PieceWeight(EPieceClass pieceClass, int weight, int maxPlaceCount) : weight(weight)
37{
38 this->placeCount = 0; // 4J added initialiser
39 this->pieceClass = pieceClass;
40 this->maxPlaceCount = maxPlaceCount;
41}
42
43bool StrongholdPieces::PieceWeight::doPlace(int depth)
44{
45 return maxPlaceCount == 0 || placeCount < maxPlaceCount;
46}
47
48bool StrongholdPieces::PieceWeight::isValid()
49{
50 return maxPlaceCount == 0 || placeCount < maxPlaceCount;
51}
52
53void StrongholdPieces::resetPieces()
54{
55 for( AUTO_VAR(it, currentPieces.begin()); it != currentPieces.end(); it++ )
56 {
57 delete (*it);
58 }
59 currentPieces.clear();
60
61 currentPieces.push_back( new PieceWeight(EPieceClass_Straight, 40, 0) );
62 currentPieces.push_back( new PieceWeight(EPieceClass_PrisonHall, 5, 5) );
63 currentPieces.push_back( new PieceWeight(EPieceClass_LeftTurn, 20, 0) );
64 currentPieces.push_back( new PieceWeight(EPieceClass_RightTurn, 20, 0) );
65 currentPieces.push_back( new PieceWeight(EPieceClass_RoomCrossing, 10, 6) );
66 currentPieces.push_back( new PieceWeight(EPieceClass_StraightStairsDown, 5, 5) );
67 currentPieces.push_back( new PieceWeight(EPieceClass_StairsDown, 5, 5) );
68 currentPieces.push_back( new PieceWeight(EPieceClass_FiveCrossing, 5, 4) );
69 currentPieces.push_back( new PieceWeight(EPieceClass_ChestCorridor, 5, 4) );
70 currentPieces.push_back( new PieceWeight_Library(EPieceClass_Library, 10, 2) );
71 currentPieces.push_back( new PieceWeight_PortalRoom(EPieceClass_PortalRoom, 20, 1) );
72
73 imposedPiece = EPieceClass_NULL;
74}
75
76bool StrongholdPieces::updatePieceWeight()
77{
78 bool hasAnyPieces = false;
79 totalWeight = 0;
80 for( AUTO_VAR(it, currentPieces.begin()); it != currentPieces.end(); it++ )
81 {
82 PieceWeight *piece = *it;
83 if (piece->maxPlaceCount > 0 && piece->placeCount < piece->maxPlaceCount)
84 {
85 hasAnyPieces = true;
86 }
87 totalWeight += piece->weight;
88 }
89 return hasAnyPieces;
90}
91
92StrongholdPieces::StrongholdPiece *StrongholdPieces::findAndCreatePieceFactory(EPieceClass pieceClass, list<StructurePiece*> *pieces, Random *random, int footX, int footY, int footZ, int direction, int depth)
93{
94 StrongholdPiece *strongholdPiece = NULL;
95
96 if (pieceClass == EPieceClass_Straight)
97 {
98 strongholdPiece = Straight::createPiece(pieces, random, footX, footY, footZ, direction, depth);
99 }
100 else if (pieceClass == EPieceClass_PrisonHall)
101 {
102 strongholdPiece = PrisonHall::createPiece(pieces, random, footX, footY, footZ, direction, depth);
103 }
104 else if (pieceClass == EPieceClass_LeftTurn)
105 {
106 strongholdPiece = LeftTurn::createPiece(pieces, random, footX, footY, footZ, direction, depth);
107 }
108 else if (pieceClass == EPieceClass_RightTurn)
109 {
110 strongholdPiece = RightTurn::createPiece(pieces, random, footX, footY, footZ, direction, depth);
111 }
112 else if (pieceClass == EPieceClass_RoomCrossing)
113 {
114 strongholdPiece = RoomCrossing::createPiece(pieces, random, footX, footY, footZ, direction, depth);
115 }
116 else if (pieceClass == EPieceClass_StraightStairsDown)
117 {
118 strongholdPiece = StraightStairsDown::createPiece(pieces, random, footX, footY, footZ, direction, depth);
119 }
120 else if (pieceClass == EPieceClass_StairsDown)
121 {
122 strongholdPiece = StairsDown::createPiece(pieces, random, footX, footY, footZ, direction, depth);
123 }
124 else if (pieceClass == EPieceClass_FiveCrossing)
125 {
126 strongholdPiece = FiveCrossing::createPiece(pieces, random, footX, footY, footZ, direction, depth);
127 }
128 else if (pieceClass == EPieceClass_ChestCorridor)
129 {
130 strongholdPiece = ChestCorridor::createPiece(pieces, random, footX, footY, footZ, direction, depth);
131 }
132 else if (pieceClass == EPieceClass_Library)
133 {
134 strongholdPiece = Library::createPiece(pieces, random, footX, footY, footZ, direction, depth);
135 }
136 else if (pieceClass == EPieceClass_PortalRoom)
137 {
138 strongholdPiece = PortalRoom::createPiece(pieces, random, footX, footY, footZ, direction, depth);
139 }
140
141
142 return strongholdPiece;
143}
144
145StrongholdPieces::StrongholdPiece *StrongholdPieces::generatePieceFromSmallDoor(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int depth)
146{
147 if (!updatePieceWeight())
148 {
149 return NULL;
150 }
151
152 if (imposedPiece != EPieceClass_NULL)
153 {
154 StrongholdPiece *strongholdPiece = findAndCreatePieceFactory(imposedPiece, pieces, random, footX, footY, footZ, direction, depth);
155 imposedPiece = EPieceClass_NULL;
156
157 if (strongholdPiece != NULL)
158 {
159 return strongholdPiece;
160 }
161 }
162
163 int numAttempts = 0;
164 while (numAttempts < 5)
165 {
166 numAttempts++;
167
168 int weightSelection = random->nextInt(totalWeight);
169 for( AUTO_VAR(it, currentPieces.begin()); it != currentPieces.end(); it++ )
170 {
171 PieceWeight *piece = *it;
172 weightSelection -= piece->weight;
173 if (weightSelection < 0)
174 {
175 if (!piece->doPlace(depth) || piece == startPiece->previousPiece)
176 {
177 break;
178 }
179
180 StrongholdPiece *strongholdPiece = findAndCreatePieceFactory(piece->pieceClass, pieces, random, footX, footY, footZ, direction, depth);
181 if (strongholdPiece != NULL)
182 {
183 piece->placeCount++;
184 startPiece->previousPiece = piece;
185
186 if (!piece->isValid())
187 {
188 currentPieces.remove(piece);
189 }
190 return strongholdPiece;
191 }
192 }
193 }
194 }
195 {
196 BoundingBox *box = FillerCorridor::findPieceBox(pieces, random, footX, footY, footZ, direction);
197 if (box != NULL && box->y0 > 1)
198 {
199 return new FillerCorridor(depth, random, box, direction);
200 }
201 if(box != NULL) delete box;
202 }
203
204 return NULL;
205}
206
207StructurePiece *StrongholdPieces::generateAndAddPiece(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int depth)
208{
209 if (depth > MAX_DEPTH)
210 {
211 return NULL;
212 }
213 if (abs(footX - startPiece->getBoundingBox()->x0) > 3 * 16 || abs(footZ - startPiece->getBoundingBox()->z0) > 3 * 16)
214 {
215 // Force attempt at spawning a portal room
216 if(startPiece->m_level->getOriginalSaveVersion() >= SAVE_FILE_VERSION_MOVED_STRONGHOLD && !startPiece->m_level->getLevelData()->getHasStrongholdEndPortal())
217 {
218 for( AUTO_VAR(it, currentPieces.begin()); it != currentPieces.end(); it++ )
219 {
220 PieceWeight *piece = *it;
221
222 if(piece->pieceClass != EPieceClass_PortalRoom) continue;
223
224#ifndef _CONTENT_PACKAGE
225 printf("Portal room forcing attempt\n");
226#endif
227 StrongholdPiece *strongholdPiece = PortalRoom::createPiece(pieces, random, footX, footY, footZ, direction, depth);
228 if (strongholdPiece != NULL)
229 {
230 piece->placeCount++;
231 startPiece->previousPiece = piece;
232
233 if (!piece->isValid())
234 {
235 currentPieces.remove(piece);
236 }
237#ifndef _CONTENT_PACKAGE
238 printf("Success\n");
239#endif
240 return strongholdPiece;
241 }
242 }
243 }
244 return NULL;
245 }
246
247 StructurePiece *newPiece = generatePieceFromSmallDoor(startPiece, pieces, random, footX, footY, footZ, direction, depth + 1);
248 if (newPiece != NULL)
249 {
250 pieces->push_back(newPiece);
251 startPiece->pendingChildren.push_back(newPiece);
252 // newPiece.addChildren(startPiece, pieces, random, depth + 1);
253 }
254 return newPiece;
255}
256
257StrongholdPieces::StrongholdPiece::StrongholdPiece()
258{
259 entryDoor = OPENING;
260 // for reflection
261}
262
263StrongholdPieces::StrongholdPiece::StrongholdPiece(int genDepth) : StructurePiece(genDepth)
264{
265 entryDoor = OPENING;
266}
267
268void StrongholdPieces::StrongholdPiece::addAdditonalSaveData(CompoundTag *tag)
269{
270 tag->putString(L"EntryDoor", _toString<int>(entryDoor));
271}
272
273void StrongholdPieces::StrongholdPiece::readAdditonalSaveData(CompoundTag *tag)
274{
275 entryDoor = (SmallDoorType)_fromString<int>(tag->getString(L"EntryDoor"));
276}
277
278void StrongholdPieces::StrongholdPiece::generateSmallDoor(Level *level, Random *random, BoundingBox *chunkBB, StrongholdPieces::StrongholdPiece::SmallDoorType doorType, int footX, int footY, int footZ)
279{
280 switch (doorType)
281 {
282 default:
283 case OPENING:
284 generateBox(level, chunkBB, footX, footY, footZ, footX + SMALL_DOOR_WIDTH - 1, footY + SMALL_DOOR_HEIGHT - 1, footZ, 0, 0, false);
285 break;
286 case WOOD_DOOR:
287 placeBlock(level, Tile::stoneBrick_Id, 0, footX, footY, footZ, chunkBB);
288 placeBlock(level, Tile::stoneBrick_Id, 0, footX, footY + 1, footZ, chunkBB);
289 placeBlock(level, Tile::stoneBrick_Id, 0, footX, footY + 2, footZ, chunkBB);
290 placeBlock(level, Tile::stoneBrick_Id, 0, footX + 1, footY + 2, footZ, chunkBB);
291 placeBlock(level, Tile::stoneBrick_Id, 0, footX + 2, footY + 2, footZ, chunkBB);
292 placeBlock(level, Tile::stoneBrick_Id, 0, footX + 2, footY + 1, footZ, chunkBB);
293 placeBlock(level, Tile::stoneBrick_Id, 0, footX + 2, footY, footZ, chunkBB);
294 placeBlock(level, Tile::door_wood_Id, 0, footX + 1, footY, footZ, chunkBB);
295 placeBlock(level, Tile::door_wood_Id, DoorTile::UPPER_BIT, footX + 1, footY + 1, footZ, chunkBB);
296 break;
297 case GRATES:
298 placeBlock(level, 0, 0, footX + 1, footY, footZ, chunkBB);
299 placeBlock(level, 0, 0, footX + 1, footY + 1, footZ, chunkBB);
300 placeBlock(level, Tile::ironFence_Id, 0, footX, footY, footZ, chunkBB);
301 placeBlock(level, Tile::ironFence_Id, 0, footX, footY + 1, footZ, chunkBB);
302 placeBlock(level, Tile::ironFence_Id, 0, footX, footY + 2, footZ, chunkBB);
303 placeBlock(level, Tile::ironFence_Id, 0, footX + 1, footY + 2, footZ, chunkBB);
304 placeBlock(level, Tile::ironFence_Id, 0, footX + 2, footY + 2, footZ, chunkBB);
305 placeBlock(level, Tile::ironFence_Id, 0, footX + 2, footY + 1, footZ, chunkBB);
306 placeBlock(level, Tile::ironFence_Id, 0, footX + 2, footY, footZ, chunkBB);
307 break;
308 case IRON_DOOR:
309 placeBlock(level, Tile::stoneBrick_Id, 0, footX, footY, footZ, chunkBB);
310 placeBlock(level, Tile::stoneBrick_Id, 0, footX, footY + 1, footZ, chunkBB);
311 placeBlock(level, Tile::stoneBrick_Id, 0, footX, footY + 2, footZ, chunkBB);
312 placeBlock(level, Tile::stoneBrick_Id, 0, footX + 1, footY + 2, footZ, chunkBB);
313 placeBlock(level, Tile::stoneBrick_Id, 0, footX + 2, footY + 2, footZ, chunkBB);
314 placeBlock(level, Tile::stoneBrick_Id, 0, footX + 2, footY + 1, footZ, chunkBB);
315 placeBlock(level, Tile::stoneBrick_Id, 0, footX + 2, footY, footZ, chunkBB);
316 placeBlock(level, Tile::door_iron_Id, 0, footX + 1, footY, footZ, chunkBB);
317 placeBlock(level, Tile::door_iron_Id, DoorTile::UPPER_BIT, footX + 1, footY + 1, footZ, chunkBB);
318 placeBlock(level, Tile::button_stone_Id, getOrientationData(Tile::button_stone_Id, 4), footX + 2, footY + 1, footZ + 1, chunkBB);
319 placeBlock(level, Tile::button_stone_Id, getOrientationData(Tile::button_stone_Id, 3), footX + 2, footY + 1, footZ - 1, chunkBB);
320 break;
321 }
322
323}
324
325StrongholdPieces::StrongholdPiece::SmallDoorType StrongholdPieces::StrongholdPiece::randomSmallDoor(Random *random)
326{
327 int selection = random->nextInt(5);
328 switch (selection)
329 {
330 default:
331 case 0:
332 case 1:
333 return OPENING;
334 case 2:
335 return WOOD_DOOR;
336 case 3:
337 return GRATES;
338 case 4:
339 return IRON_DOOR;
340 }
341}
342
343StructurePiece *StrongholdPieces::StrongholdPiece::generateSmallDoorChildForward(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int xOff, int yOff)
344{
345 switch (orientation)
346 {
347 case Direction::NORTH:
348 return generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 + xOff, boundingBox->y0 + yOff, boundingBox->z0 - 1, orientation, getGenDepth());
349 case Direction::SOUTH:
350 return generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 + xOff, boundingBox->y0 + yOff, boundingBox->z1 + 1, orientation, getGenDepth());
351 case Direction::WEST:
352 return generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 - 1, boundingBox->y0 + yOff, boundingBox->z0 + xOff, orientation, getGenDepth());
353 case Direction::EAST:
354 return generateAndAddPiece(startPiece, pieces, random, boundingBox->x1 + 1, boundingBox->y0 + yOff, boundingBox->z0 + xOff, orientation, getGenDepth());
355 }
356 return NULL;
357}
358
359StructurePiece *StrongholdPieces::StrongholdPiece::generateSmallDoorChildLeft(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int yOff, int zOff)
360{
361 switch (orientation)
362 {
363 case Direction::NORTH:
364 return generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 - 1, boundingBox->y0 + yOff, boundingBox->z0 + zOff, Direction::WEST, getGenDepth());
365 case Direction::SOUTH:
366 return generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 - 1, boundingBox->y0 + yOff, boundingBox->z0 + zOff, Direction::WEST, getGenDepth());
367 case Direction::WEST:
368 return generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 + zOff, boundingBox->y0 + yOff, boundingBox->z0 - 1, Direction::NORTH, getGenDepth());
369 case Direction::EAST:
370 return generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 + zOff, boundingBox->y0 + yOff, boundingBox->z0 - 1, Direction::NORTH, getGenDepth());
371 }
372 return NULL;
373}
374
375StructurePiece *StrongholdPieces::StrongholdPiece::generateSmallDoorChildRight(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int yOff, int zOff)
376{
377 switch (orientation)
378 {
379 case Direction::NORTH:
380 return generateAndAddPiece(startPiece, pieces, random, boundingBox->x1 + 1, boundingBox->y0 + yOff, boundingBox->z0 + zOff, Direction::EAST, getGenDepth());
381 case Direction::SOUTH:
382 return generateAndAddPiece(startPiece, pieces, random, boundingBox->x1 + 1, boundingBox->y0 + yOff, boundingBox->z0 + zOff, Direction::EAST, getGenDepth());
383 case Direction::WEST:
384 return generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 + zOff, boundingBox->y0 + yOff, boundingBox->z1 + 1, Direction::SOUTH, getGenDepth());
385 case Direction::EAST:
386 return generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 + zOff, boundingBox->y0 + yOff, boundingBox->z1 + 1, Direction::SOUTH, getGenDepth());
387 }
388 return NULL;
389}
390
391bool StrongholdPieces::StrongholdPiece::isOkBox(BoundingBox *box, StartPiece *startRoom)
392{
393 //return box != NULL && box->y0 > LOWEST_Y_POSITION;
394
395 bool bIsOk = false;
396
397 if(box != NULL)
398 {
399 if( box->y0 > LOWEST_Y_POSITION ) bIsOk = true;
400
401 if( startRoom != NULL && startRoom->m_level->getOriginalSaveVersion() >= SAVE_FILE_VERSION_MOVED_STRONGHOLD )
402 {
403 int xzSize = startRoom->m_level->getLevelData()->getXZSize();
404 int blockMin = -( (xzSize << 4) / 2) + 1;
405 int blockMax = ( (xzSize << 4) / 2 ) - 1;
406
407 if(box->x0 <= blockMin) bIsOk = false;
408 if(box->z0 <= blockMin) bIsOk = false;
409 if(box->x1 >= blockMax) bIsOk = false;
410 if(box->z1 >= blockMax) bIsOk = false;
411 }
412 }
413
414 return bIsOk;
415}
416
417StrongholdPieces::FillerCorridor::FillerCorridor() : steps(0)
418{
419 // for reflection
420}
421
422StrongholdPieces::FillerCorridor::FillerCorridor(int genDepth, Random *random, BoundingBox *corridorBox, int direction) : StrongholdPiece(genDepth),
423 steps((direction == Direction::NORTH || direction == Direction::SOUTH) ? corridorBox->getZSpan() : corridorBox->getXSpan())
424{
425 orientation = direction;
426 boundingBox = corridorBox;
427}
428
429void StrongholdPieces::FillerCorridor::addAdditonalSaveData(CompoundTag *tag)
430{
431 StrongholdPiece::addAdditonalSaveData(tag);
432 tag->putInt(L"Steps", steps);
433}
434
435void StrongholdPieces::FillerCorridor::readAdditonalSaveData(CompoundTag *tag)
436{
437 StrongholdPiece::readAdditonalSaveData(tag);
438 steps = tag->getInt(L"Steps");
439}
440
441BoundingBox *StrongholdPieces::FillerCorridor::findPieceBox(list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction)
442{
443 const int maxLength = 3;
444
445 BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, -1, -1, 0, 5, 5, maxLength + 1, direction);
446
447 StructurePiece *collisionPiece = StructurePiece::findCollisionPiece(pieces, box);
448
449 if (collisionPiece == NULL)
450 {
451 delete box;
452 // the filler must collide with something in order to be
453 // generated
454 return NULL;
455 }
456
457 if (collisionPiece->getBoundingBox()->y0 == box->y0)
458 {
459 delete box;
460 // attempt to make a smaller piece until it fits
461 for (int depth = maxLength; depth >= 1; depth--)
462 {
463 box = BoundingBox::orientBox(footX, footY, footZ, -1, -1, 0, 5, 5, depth - 1, direction);
464 if (!collisionPiece->getBoundingBox()->intersects(box))
465 {
466 delete box;
467 // the corridor has shrunk enough to fit, but make it
468 // one step too big to build an entrance into the other block
469 return BoundingBox::orientBox(footX, footY, footZ, -1, -1, 0, 5, 5, depth, direction);
470 }
471 delete box;
472 }
473 }
474
475 return NULL;
476}
477
478bool StrongholdPieces::FillerCorridor::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
479{
480 if (edgesLiquid(level, chunkBB))
481 {
482 return false;
483 }
484
485 // filler corridor
486 for (int i = 0; i < steps; i++)
487 {
488 // row 0
489 placeBlock(level, Tile::stoneBrick_Id, 0, 0, 0, i, chunkBB);
490 placeBlock(level, Tile::stoneBrick_Id, 0, 1, 0, i, chunkBB);
491 placeBlock(level, Tile::stoneBrick_Id, 0, 2, 0, i, chunkBB);
492 placeBlock(level, Tile::stoneBrick_Id, 0, 3, 0, i, chunkBB);
493 placeBlock(level, Tile::stoneBrick_Id, 0, 4, 0, i, chunkBB);
494 // row 1-3
495 for (int y = 1; y <= 3; y++)
496 {
497 placeBlock(level, Tile::stoneBrick_Id, 0, 0, y, i, chunkBB);
498 placeBlock(level, 0, 0, 1, y, i, chunkBB);
499 placeBlock(level, 0, 0, 2, y, i, chunkBB);
500 placeBlock(level, 0, 0, 3, y, i, chunkBB);
501 placeBlock(level, Tile::stoneBrick_Id, 0, 4, y, i, chunkBB);
502 }
503 // row 4
504 placeBlock(level, Tile::stoneBrick_Id, 0, 0, 4, i, chunkBB);
505 placeBlock(level, Tile::stoneBrick_Id, 0, 1, 4, i, chunkBB);
506 placeBlock(level, Tile::stoneBrick_Id, 0, 2, 4, i, chunkBB);
507 placeBlock(level, Tile::stoneBrick_Id, 0, 3, 4, i, chunkBB);
508 placeBlock(level, Tile::stoneBrick_Id, 0, 4, 4, i, chunkBB);
509 }
510
511 return true;
512}
513
514StrongholdPieces::StairsDown::StairsDown()
515{
516 // for reflection
517}
518
519StrongholdPieces::StairsDown::StairsDown(int genDepth, Random *random, int west, int north) : StrongholdPiece(genDepth), isSource(true)
520{
521 orientation = random->nextInt(4);
522 entryDoor = OPENING;
523
524 switch (orientation)
525 {
526 case Direction::NORTH:
527 case Direction::SOUTH:
528 boundingBox = new BoundingBox(west, 64, north, west + width - 1, 64 + height - 1, north + depth - 1);
529 break;
530 default:
531 boundingBox = new BoundingBox(west, 64, north, west + depth - 1, 64 + height - 1, north + width - 1);
532 break;
533 }
534}
535
536StrongholdPieces::StairsDown::StairsDown(int genDepth, Random *random, BoundingBox *stairsBox, int direction) : StrongholdPiece(genDepth), isSource(false)
537{
538 entryDoor = randomSmallDoor(random);
539 orientation = direction;
540 boundingBox = stairsBox;
541}
542
543void StrongholdPieces::StairsDown::addAdditonalSaveData(CompoundTag *tag)
544{
545 StrongholdPiece::addAdditonalSaveData(tag);
546 tag->putBoolean(L"Source", isSource);
547}
548
549void StrongholdPieces::StairsDown::readAdditonalSaveData(CompoundTag *tag)
550{
551 StrongholdPiece::readAdditonalSaveData(tag);
552 isSource = tag->getBoolean(L"Source");
553}
554
555void StrongholdPieces::StairsDown::addChildren(StructurePiece *startPiece, list<StructurePiece *> *pieces, Random *random)
556{
557 if( isSource )
558 {
559 imposedPiece = EPieceClass_FiveCrossing;
560 }
561 generateSmallDoorChildForward((StartPiece *) startPiece, pieces, random, 1, 1);
562}
563
564StrongholdPieces::StairsDown *StrongholdPieces::StairsDown::createPiece(list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth)
565{
566 BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, -1, 4 - height, 0, width, height, depth, direction);
567
568 StartPiece *startPiece = NULL;
569 if(pieces != NULL) startPiece = ((StrongholdPieces::StartPiece *) pieces->front());
570
571 if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL)
572 {
573 delete box;
574 return NULL;
575 }
576
577 return new StairsDown(genDepth, random, box, direction);
578}
579
580bool StrongholdPieces::StairsDown::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
581{
582 if (edgesLiquid(level, chunkBB))
583 {
584 return false;
585 }
586
587 // bounding walls
588 generateBox(level, chunkBB, 0, 0, 0, width - 1, height - 1, depth - 1, CHECK_AIR, random, (BlockSelector *)smoothStoneSelector);
589 // entry door
590 generateSmallDoor(level, random, chunkBB, entryDoor, 1, height - SMALL_DOOR_HEIGHT - 1, 0);
591 // exit door
592 generateSmallDoor(level, random, chunkBB, OPENING, 1, 1, depth - 1);
593
594 // stair steps
595 placeBlock(level, Tile::stoneBrick_Id, 0, 2, 6, 1, chunkBB);
596 placeBlock(level, Tile::stoneBrick_Id, 0, 1, 5, 1, chunkBB);
597 placeBlock(level, Tile::stoneSlabHalf_Id, StoneSlabTile::STONE_SLAB, 1, 6, 1, chunkBB);
598 placeBlock(level, Tile::stoneBrick_Id, 0, 1, 5, 2, chunkBB);
599 placeBlock(level, Tile::stoneBrick_Id, 0, 1, 4, 3, chunkBB);
600 placeBlock(level, Tile::stoneSlabHalf_Id, StoneSlabTile::STONE_SLAB, 1, 5, 3, chunkBB);
601 placeBlock(level, Tile::stoneBrick_Id, 0, 2, 4, 3, chunkBB);
602 placeBlock(level, Tile::stoneBrick_Id, 0, 3, 3, 3, chunkBB);
603 placeBlock(level, Tile::stoneSlabHalf_Id, StoneSlabTile::STONE_SLAB, 3, 4, 3, chunkBB);
604 placeBlock(level, Tile::stoneBrick_Id, 0, 3, 3, 2, chunkBB);
605 placeBlock(level, Tile::stoneBrick_Id, 0, 3, 2, 1, chunkBB);
606 placeBlock(level, Tile::stoneSlabHalf_Id, StoneSlabTile::STONE_SLAB, 3, 3, 1, chunkBB);
607 placeBlock(level, Tile::stoneBrick_Id, 0, 2, 2, 1, chunkBB);
608 placeBlock(level, Tile::stoneBrick_Id, 0, 1, 1, 1, chunkBB);
609 placeBlock(level, Tile::stoneSlabHalf_Id, StoneSlabTile::STONE_SLAB, 1, 2, 1, chunkBB);
610 placeBlock(level, Tile::stoneBrick_Id, 0, 1, 1, 2, chunkBB);
611 placeBlock(level, Tile::stoneSlabHalf_Id, StoneSlabTile::STONE_SLAB, 1, 1, 3, chunkBB);
612
613 return true;
614}
615
616StrongholdPieces::StartPiece::StartPiece()
617{
618 // for reflection
619}
620
621StrongholdPieces::StartPiece::StartPiece(int genDepth, Random *random, int west, int north, Level *level) : StairsDown(0, random, west, north)
622{
623 // 4J added initialisers
624 isLibraryAdded = false;
625 previousPiece = NULL;
626 portalRoomPiece = NULL;
627
628 m_level = level;
629}
630
631TilePos *StrongholdPieces::StartPiece::getLocatorPosition()
632{
633 if( portalRoomPiece != NULL )
634 {
635 return portalRoomPiece->getLocatorPosition();
636 }
637 return StairsDown::getLocatorPosition();
638}
639
640StrongholdPieces::Straight::Straight()
641{
642 // for reflection
643}
644
645StrongholdPieces::Straight::Straight(int genDepth, Random *random, BoundingBox *stairsBox, int direction) : StrongholdPiece(genDepth),
646 leftChild(random->nextInt(2) == 0),
647 rightChild(random->nextInt(2) == 0)
648{
649 entryDoor = randomSmallDoor(random);
650 orientation = direction;
651 boundingBox = stairsBox;
652}
653
654void StrongholdPieces::Straight::addAdditonalSaveData(CompoundTag *tag)
655{
656 StrongholdPiece::addAdditonalSaveData(tag);
657 tag->putBoolean(L"Left", leftChild);
658 tag->putBoolean(L"Right", rightChild);
659}
660
661void StrongholdPieces::Straight::readAdditonalSaveData(CompoundTag *tag)
662{
663 StrongholdPiece::readAdditonalSaveData(tag);
664 leftChild = tag->getBoolean(L"Left");
665 rightChild = tag->getBoolean(L"Right");
666}
667
668void StrongholdPieces::Straight::addChildren(StructurePiece *startPiece, list<StructurePiece *> *pieces, Random *random)
669{
670 generateSmallDoorChildForward((StartPiece *) startPiece, pieces, random, 1, 1);
671 if (leftChild) generateSmallDoorChildLeft((StartPiece *) startPiece, pieces, random, 1, 2);
672 if (rightChild) generateSmallDoorChildRight((StartPiece *) startPiece, pieces, random, 1, 2);
673}
674
675StrongholdPieces::Straight *StrongholdPieces::Straight::createPiece(list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth)
676{
677 BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, -1, -1, 0, width, height, depth, direction);
678
679 StartPiece *startPiece = NULL;
680 if(pieces != NULL) startPiece = ((StrongholdPieces::StartPiece *) pieces->front());
681
682 if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL)
683 {
684 delete box;
685 return NULL;
686 }
687
688 return new Straight(genDepth, random, box, direction);
689}
690
691bool StrongholdPieces::Straight::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
692{
693 if (edgesLiquid(level, chunkBB))
694 {
695 return false;
696 }
697
698 // bounding walls
699 generateBox(level, chunkBB, 0, 0, 0, width - 1, height - 1, depth - 1, CHECK_AIR, random, (BlockSelector *)smoothStoneSelector);
700 // entry door
701 generateSmallDoor(level, random, chunkBB, entryDoor, 1, height - SMALL_DOOR_HEIGHT - 1, 0);
702 // exit door
703 generateSmallDoor(level, random, chunkBB, OPENING, 1, 1, depth - 1);
704
705 maybeGenerateBlock(level, chunkBB, random, .1f, 1, 2, 1, Tile::torch_Id, 0);
706 maybeGenerateBlock(level, chunkBB, random, .1f, 3, 2, 1, Tile::torch_Id, 0);
707 maybeGenerateBlock(level, chunkBB, random, .1f, 1, 2, 5, Tile::torch_Id, 0);
708 maybeGenerateBlock(level, chunkBB, random, .1f, 3, 2, 5, Tile::torch_Id, 0);
709
710 if (leftChild)
711 {
712 generateBox(level, chunkBB, 0, 1, 2, 0, 3, 4, 0, 0, false);
713 }
714 if (rightChild)
715 {
716 generateBox(level, chunkBB, 4, 1, 2, 4, 3, 4, 0, 0, false);
717 }
718
719 return true;
720}
721
722WeighedTreasure *StrongholdPieces::ChestCorridor::treasureItems[TREASURE_ITEMS_COUNT] =
723{
724 new WeighedTreasure(Item::enderPearl_Id, 0, 1, 1, 10),
725 new WeighedTreasure(Item::diamond_Id, 0, 1, 3, 3),
726 new WeighedTreasure(Item::ironIngot_Id, 0, 1, 5, 10),
727 new WeighedTreasure(Item::goldIngot_Id, 0, 1, 3, 5),
728 new WeighedTreasure(Item::redStone_Id, 0, 4, 9, 5),
729 new WeighedTreasure(Item::bread_Id, 0, 1, 3, 15),
730 new WeighedTreasure(Item::apple_Id, 0, 1, 3, 15),
731 new WeighedTreasure(Item::pickAxe_iron_Id, 0, 1, 1, 5),
732 new WeighedTreasure(Item::sword_iron_Id, 0, 1, 1, 5),
733 new WeighedTreasure(Item::chestplate_iron_Id, 0, 1, 1, 5),
734 new WeighedTreasure(Item::helmet_iron_Id, 0, 1, 1, 5),
735 new WeighedTreasure(Item::leggings_iron_Id, 0, 1, 1, 5),
736 new WeighedTreasure(Item::boots_iron_Id, 0, 1, 1, 5),
737 new WeighedTreasure(Item::apple_gold_Id, 0, 1, 1, 1),
738 // very rare for strongholds ...
739 new WeighedTreasure(Item::saddle_Id, 0, 1, 1, 1),
740 new WeighedTreasure(Item::horseArmorMetal_Id, 0, 1, 1, 1),
741 new WeighedTreasure(Item::horseArmorGold_Id, 0, 1, 1, 1),
742 new WeighedTreasure(Item::horseArmorDiamond_Id, 0, 1, 1, 1),
743 // ...
744};
745
746StrongholdPieces::ChestCorridor::ChestCorridor()
747{
748 // for reflection
749}
750
751StrongholdPieces::ChestCorridor::ChestCorridor(int genDepth, Random *random, BoundingBox *stairsBox, int direction) : StrongholdPiece(genDepth)
752{
753 entryDoor = randomSmallDoor(random);
754 orientation = direction;
755 boundingBox = stairsBox;
756}
757
758void StrongholdPieces::ChestCorridor::addAdditonalSaveData(CompoundTag *tag)
759{
760 StrongholdPiece::addAdditonalSaveData(tag);
761 tag->putBoolean(L"Chest", hasPlacedChest);
762}
763
764void StrongholdPieces::ChestCorridor::readAdditonalSaveData(CompoundTag *tag)
765{
766 StrongholdPiece::readAdditonalSaveData(tag);
767 hasPlacedChest = tag->getBoolean(L"Chest");
768}
769
770void StrongholdPieces::ChestCorridor::addChildren(StructurePiece *startPiece, list<StructurePiece *> *pieces, Random *random)
771{
772 generateSmallDoorChildForward((StartPiece *) startPiece, pieces, random, 1, 1);
773}
774
775StrongholdPieces::ChestCorridor *StrongholdPieces::ChestCorridor::createPiece(list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth)
776{
777 BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, -1, -1, 0, width, height, depth, direction);
778
779 StartPiece *startPiece = NULL;
780 if(pieces != NULL) startPiece = ((StrongholdPieces::StartPiece *) pieces->front());
781
782 if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL)
783 {
784 delete box;
785 return NULL;
786 }
787
788 return new ChestCorridor(genDepth, random, box, direction);
789}
790
791bool StrongholdPieces::ChestCorridor::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
792{
793 if (edgesLiquid(level, chunkBB))
794 {
795 return false;
796 }
797
798 // bounding walls
799 generateBox(level, chunkBB, 0, 0, 0, width - 1, height - 1, depth - 1, CHECK_AIR, random, (BlockSelector *)smoothStoneSelector);
800 // entry door
801 generateSmallDoor(level, random, chunkBB, entryDoor, 1, height - SMALL_DOOR_HEIGHT - 1, 0);
802 // exit door
803 generateSmallDoor(level, random, chunkBB, OPENING, 1, 1, depth - 1);
804
805 // chest placement
806 generateBox(level, chunkBB, 3, 1, 2, 3, 1, 4, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false);
807 placeBlock(level, Tile::stoneSlabHalf_Id, StoneSlabTile::SMOOTHBRICK_SLAB, 3, 1, 1, chunkBB);
808 placeBlock(level, Tile::stoneSlabHalf_Id, StoneSlabTile::SMOOTHBRICK_SLAB, 3, 1, 5, chunkBB);
809 placeBlock(level, Tile::stoneSlabHalf_Id, StoneSlabTile::SMOOTHBRICK_SLAB, 3, 2, 2, chunkBB);
810 placeBlock(level, Tile::stoneSlabHalf_Id, StoneSlabTile::SMOOTHBRICK_SLAB, 3, 2, 4, chunkBB);
811 for (int z = 2; z <= 4; z++)
812 {
813 placeBlock(level, Tile::stoneSlabHalf_Id, StoneSlabTile::SMOOTHBRICK_SLAB, 2, 1, z, chunkBB);
814 }
815
816 if (!hasPlacedChest)
817 {
818 int y = getWorldY(2);
819 int x = getWorldX(3, 3), z = getWorldZ(3, 3);
820 if (chunkBB->isInside(x, y, z))
821 {
822 hasPlacedChest = true;
823 createChest(level, chunkBB, random, 3, 2, 3, WeighedTreasure::addToTreasure(WeighedTreasureArray(treasureItems,TREASURE_ITEMS_COUNT), Item::enchantedBook->createForRandomTreasure(random)), 2 + random->nextInt(2));
824 }
825 }
826
827 return true;
828}
829
830StrongholdPieces::StraightStairsDown::StraightStairsDown()
831{
832 // for reflection
833}
834
835StrongholdPieces::StraightStairsDown::StraightStairsDown(int genDepth, Random *random, BoundingBox *stairsBox, int direction) : StrongholdPiece(genDepth)
836{
837 entryDoor = randomSmallDoor(random);
838 orientation = direction;
839 boundingBox = stairsBox;
840}
841
842void StrongholdPieces::StraightStairsDown::addChildren(StructurePiece *startPiece, list<StructurePiece *> *pieces, Random *random)
843{
844 generateSmallDoorChildForward((StartPiece *) startPiece, pieces, random, 1, 1);
845}
846
847StrongholdPieces::StraightStairsDown *StrongholdPieces::StraightStairsDown::createPiece(list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth)
848{
849 BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, -1, 4 - height, 0, width, height, depth, direction);
850
851 StartPiece *startPiece = NULL;
852 if(pieces != NULL) startPiece = ((StrongholdPieces::StartPiece *) pieces->front());
853
854 if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL)
855 {
856 delete box;
857 return NULL;
858 }
859
860 return new StraightStairsDown(genDepth, random, box, direction);
861}
862
863bool StrongholdPieces::StraightStairsDown::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
864{
865 if (edgesLiquid(level, chunkBB))
866 {
867 return false;
868 }
869
870 // bounding walls
871 generateBox(level, chunkBB, 0, 0, 0, width - 1, height - 1, depth - 1, CHECK_AIR, random, (BlockSelector *)smoothStoneSelector);
872 // entry door
873 generateSmallDoor(level, random, chunkBB, entryDoor, 1, height - SMALL_DOOR_HEIGHT - 1, 0);
874 // exit door
875 generateSmallDoor(level, random, chunkBB, OPENING, 1, 1, depth - 1);
876
877 // stairs
878 int orientationData = getOrientationData(Tile::stairs_stone_Id, 2);
879 for (int i = 0; i < 6; i++)
880 {
881 placeBlock(level, Tile::stairs_stone_Id, orientationData, 1, height - 5 - i, 1 + i, chunkBB);
882 placeBlock(level, Tile::stairs_stone_Id, orientationData, 2, height - 5 - i, 1 + i, chunkBB);
883 placeBlock(level, Tile::stairs_stone_Id, orientationData, 3, height - 5 - i, 1 + i, chunkBB);
884 if (i < 5)
885 {
886 placeBlock(level, Tile::stoneBrick_Id, 0, 1, height - 6 - i, 1 + i, chunkBB);
887 placeBlock(level, Tile::stoneBrick_Id, 0, 2, height - 6 - i, 1 + i, chunkBB);
888 placeBlock(level, Tile::stoneBrick_Id, 0, 3, height - 6 - i, 1 + i, chunkBB);
889 }
890 }
891
892 return true;
893}
894
895StrongholdPieces::LeftTurn::LeftTurn()
896{
897 // for reflection
898}
899
900StrongholdPieces::LeftTurn::LeftTurn(int genDepth, Random *random, BoundingBox *stairsBox, int direction) : StrongholdPiece(genDepth)
901{
902 entryDoor = randomSmallDoor(random);
903 orientation = direction;
904 boundingBox = stairsBox;
905}
906
907void StrongholdPieces::LeftTurn::addChildren(StructurePiece *startPiece, list<StructurePiece *> *pieces, Random *random)
908{
909 if (orientation == Direction::NORTH || orientation == Direction::EAST)
910 {
911 generateSmallDoorChildLeft((StartPiece *) startPiece, pieces, random, 1, 1);
912 }
913 else
914 {
915 generateSmallDoorChildRight((StartPiece *) startPiece, pieces, random, 1, 1);
916 }
917}
918
919StrongholdPieces::LeftTurn *StrongholdPieces::LeftTurn::createPiece(list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth)
920{
921 BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, -1, -1, 0, width, height, depth, direction);
922
923 StartPiece *startPiece = NULL;
924 if(pieces != NULL) startPiece = ((StrongholdPieces::StartPiece *) pieces->front());
925
926 if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL)
927 {
928 delete box;
929 return NULL;
930 }
931
932 return new LeftTurn(genDepth, random, box, direction);
933}
934
935bool StrongholdPieces::LeftTurn::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
936{
937 if (edgesLiquid(level, chunkBB))
938 {
939 return false;
940 }
941
942 // bounding walls
943 generateBox(level, chunkBB, 0, 0, 0, width - 1, height - 1, depth - 1, CHECK_AIR, random, (BlockSelector *)smoothStoneSelector);
944 // entry door
945 generateSmallDoor(level, random, chunkBB, entryDoor, 1, height - SMALL_DOOR_HEIGHT - 1, 0);
946 // exit opening
947 if (orientation == Direction::NORTH || orientation == Direction::EAST)
948 {
949 generateBox(level, chunkBB, 0, 1, 1, 0, 3, 3, 0, 0, false);
950 }
951 else
952 {
953 generateBox(level, chunkBB, 4, 1, 1, 4, 3, 3, 0, 0, false);
954 }
955
956 return true;
957}
958
959StrongholdPieces::RightTurn::RightTurn()
960{
961 // for reflection
962}
963
964StrongholdPieces::RightTurn::RightTurn(int genDepth, Random *random, BoundingBox *stairsBox, int direction) : LeftTurn(genDepth, random, stairsBox, direction)
965{
966}
967
968void StrongholdPieces::RightTurn::addChildren(StructurePiece *startPiece, list<StructurePiece *> *pieces, Random *random)
969{
970 if (orientation == Direction::NORTH || orientation == Direction::EAST)
971 {
972 generateSmallDoorChildRight((StartPiece *) startPiece, pieces, random, 1, 1);
973 }
974 else
975 {
976 generateSmallDoorChildLeft((StartPiece *) startPiece, pieces, random, 1, 1);
977 }
978}
979
980bool StrongholdPieces::RightTurn::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
981{
982 if (edgesLiquid(level, chunkBB))
983 {
984 return false;
985 }
986
987 // bounding walls
988 generateBox(level, chunkBB, 0, 0, 0, width - 1, height - 1, depth - 1, CHECK_AIR, random, (BlockSelector *)smoothStoneSelector);
989 // entry door
990 generateSmallDoor(level, random, chunkBB, entryDoor, 1, height - SMALL_DOOR_HEIGHT - 1, 0);
991 // exit opening
992 if (orientation == Direction::NORTH || orientation == Direction::EAST)
993 {
994 generateBox(level, chunkBB, 4, 1, 1, 4, 3, 3, 0, 0, false);
995 }
996 else
997 {
998 generateBox(level, chunkBB, 0, 1, 1, 0, 3, 3, 0, 0, false);
999 }
1000
1001 return true;
1002}
1003
1004StrongholdPieces::RoomCrossing::RoomCrossing()
1005{
1006 // for reflection
1007}
1008
1009StrongholdPieces::RoomCrossing::RoomCrossing(int genDepth, Random *random, BoundingBox *stairsBox, int direction) : StrongholdPiece(genDepth), type(random->nextInt(5))
1010{
1011 entryDoor = randomSmallDoor(random);
1012 orientation = direction;
1013 boundingBox = stairsBox;
1014}
1015
1016void StrongholdPieces::RoomCrossing::addAdditonalSaveData(CompoundTag *tag)
1017{
1018 StrongholdPiece::addAdditonalSaveData(tag);
1019 tag->putInt(L"Type", type);
1020}
1021
1022void StrongholdPieces::RoomCrossing::readAdditonalSaveData(CompoundTag *tag)
1023{
1024 StrongholdPiece::readAdditonalSaveData(tag);
1025 type = tag->getInt(L"Type");
1026}
1027
1028void StrongholdPieces::RoomCrossing::addChildren(StructurePiece *startPiece, list<StructurePiece *> *pieces, Random *random)
1029{
1030 generateSmallDoorChildForward((StartPiece*) startPiece, pieces, random, 4, 1);
1031 generateSmallDoorChildLeft((StartPiece*) startPiece, pieces, random, 1, 4);
1032 generateSmallDoorChildRight((StartPiece*) startPiece, pieces, random, 1, 4);
1033}
1034
1035StrongholdPieces::RoomCrossing *StrongholdPieces::RoomCrossing::createPiece(list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth)
1036{
1037 BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, -4, -1, 0, width, height, depth, direction);
1038
1039 StartPiece *startPiece = NULL;
1040 if(pieces != NULL) startPiece = ((StrongholdPieces::StartPiece *) pieces->front());
1041
1042 if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL)
1043 {
1044 delete box;
1045 return NULL;
1046 }
1047
1048 return new RoomCrossing(genDepth, random, box, direction);
1049}
1050
1051WeighedTreasure *StrongholdPieces::RoomCrossing::smallTreasureItems[SMALL_TREASURE_ITEMS_COUNT] =
1052{
1053 new WeighedTreasure(Item::ironIngot_Id, 0, 1, 5, 10),
1054 new WeighedTreasure(Item::goldIngot_Id, 0, 1, 3, 5),
1055 new WeighedTreasure(Item::redStone_Id, 0, 4, 9, 5),
1056 new WeighedTreasure(Item::coal_Id, CoalItem::STONE_COAL, 3, 8, 10),
1057 new WeighedTreasure(Item::bread_Id, 0, 1, 3, 15),
1058 new WeighedTreasure(Item::apple_Id, 0, 1, 3, 15),
1059 new WeighedTreasure(Item::pickAxe_iron_Id, 0, 1, 1, 1),
1060};
1061
1062bool StrongholdPieces::RoomCrossing::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
1063{
1064 if (edgesLiquid(level, chunkBB))
1065 {
1066 return false;
1067 }
1068
1069 // bounding walls
1070 generateBox(level, chunkBB, 0, 0, 0, width - 1, height - 1, depth - 1, CHECK_AIR, random, (BlockSelector *)smoothStoneSelector);
1071 // entry door
1072 generateSmallDoor(level, random, chunkBB, entryDoor, 4, 1, 0);
1073 // exit openings
1074 generateBox(level, chunkBB, 4, 1, depth - 1, 6, 3, depth - 1, 0, 0, false);
1075 generateBox(level, chunkBB, 0, 1, 4, 0, 3, 6, 0, 0, false);
1076 generateBox(level, chunkBB, width - 1, 1, 4, width - 1, 3, 6, 0, 0, false);
1077
1078 switch (type)
1079 {
1080 default:
1081 break;
1082 case 0:
1083 // middle torch pillar
1084 placeBlock(level, Tile::stoneBrick_Id, 0, 5, 1, 5, chunkBB);
1085 placeBlock(level, Tile::stoneBrick_Id, 0, 5, 2, 5, chunkBB);
1086 placeBlock(level, Tile::stoneBrick_Id, 0, 5, 3, 5, chunkBB);
1087 placeBlock(level, Tile::torch_Id, 0, 4, 3, 5, chunkBB);
1088 placeBlock(level, Tile::torch_Id, 0, 6, 3, 5, chunkBB);
1089 placeBlock(level, Tile::torch_Id, 0, 5, 3, 4, chunkBB);
1090 placeBlock(level, Tile::torch_Id, 0, 5, 3, 6, chunkBB);
1091 placeBlock(level, Tile::stoneSlabHalf_Id, 0, 4, 1, 4, chunkBB);
1092 placeBlock(level, Tile::stoneSlabHalf_Id, 0, 4, 1, 5, chunkBB);
1093 placeBlock(level, Tile::stoneSlabHalf_Id, 0, 4, 1, 6, chunkBB);
1094 placeBlock(level, Tile::stoneSlabHalf_Id, 0, 6, 1, 4, chunkBB);
1095 placeBlock(level, Tile::stoneSlabHalf_Id, 0, 6, 1, 5, chunkBB);
1096 placeBlock(level, Tile::stoneSlabHalf_Id, 0, 6, 1, 6, chunkBB);
1097 placeBlock(level, Tile::stoneSlabHalf_Id, 0, 5, 1, 4, chunkBB);
1098 placeBlock(level, Tile::stoneSlabHalf_Id, 0, 5, 1, 6, chunkBB);
1099 break;
1100 case 1:
1101 {
1102 for (int i = 0; i < 5; i++)
1103 {
1104 placeBlock(level, Tile::stoneBrick_Id, 0, 3, 1, 3 + i, chunkBB);
1105 placeBlock(level, Tile::stoneBrick_Id, 0, 7, 1, 3 + i, chunkBB);
1106 placeBlock(level, Tile::stoneBrick_Id, 0, 3 + i, 1, 3, chunkBB);
1107 placeBlock(level, Tile::stoneBrick_Id, 0, 3 + i, 1, 7, chunkBB);
1108 }
1109 placeBlock(level, Tile::stoneBrick_Id, 0, 5, 1, 5, chunkBB);
1110 placeBlock(level, Tile::stoneBrick_Id, 0, 5, 2, 5, chunkBB);
1111 placeBlock(level, Tile::stoneBrick_Id, 0, 5, 3, 5, chunkBB);
1112 placeBlock(level, Tile::water_Id, 0, 5, 4, 5, chunkBB);
1113 }
1114 break;
1115 case 2:
1116 {
1117 for (int z = 1; z <= 9; z++)
1118 {
1119 placeBlock(level, Tile::cobblestone_Id, 0, 1, 3, z, chunkBB);
1120 placeBlock(level, Tile::cobblestone_Id, 0, 9, 3, z, chunkBB);
1121 }
1122 for (int x = 1; x <= 9; x++)
1123 {
1124 placeBlock(level, Tile::cobblestone_Id, 0, x, 3, 1, chunkBB);
1125 placeBlock(level, Tile::cobblestone_Id, 0, x, 3, 9, chunkBB);
1126 }
1127 placeBlock(level, Tile::cobblestone_Id, 0, 5, 1, 4, chunkBB);
1128 placeBlock(level, Tile::cobblestone_Id, 0, 5, 1, 6, chunkBB);
1129 placeBlock(level, Tile::cobblestone_Id, 0, 5, 3, 4, chunkBB);
1130 placeBlock(level, Tile::cobblestone_Id, 0, 5, 3, 6, chunkBB);
1131 placeBlock(level, Tile::cobblestone_Id, 0, 4, 1, 5, chunkBB);
1132 placeBlock(level, Tile::cobblestone_Id, 0, 6, 1, 5, chunkBB);
1133 placeBlock(level, Tile::cobblestone_Id, 0, 4, 3, 5, chunkBB);
1134 placeBlock(level, Tile::cobblestone_Id, 0, 6, 3, 5, chunkBB);
1135 for (int y = 1; y <= 3; y++)
1136 {
1137 placeBlock(level, Tile::cobblestone_Id, 0, 4, y, 4, chunkBB);
1138 placeBlock(level, Tile::cobblestone_Id, 0, 6, y, 4, chunkBB);
1139 placeBlock(level, Tile::cobblestone_Id, 0, 4, y, 6, chunkBB);
1140 placeBlock(level, Tile::cobblestone_Id, 0, 6, y, 6, chunkBB);
1141 }
1142 placeBlock(level, Tile::torch_Id, 0, 5, 3, 5, chunkBB);
1143 for (int z = 2; z <= 8; z++)
1144 {
1145 placeBlock(level, Tile::wood_Id, 0, 2, 3, z, chunkBB);
1146 placeBlock(level, Tile::wood_Id, 0, 3, 3, z, chunkBB);
1147 if (z <= 3 || z >= 7)
1148 {
1149 placeBlock(level, Tile::wood_Id, 0, 4, 3, z, chunkBB);
1150 placeBlock(level, Tile::wood_Id, 0, 5, 3, z, chunkBB);
1151 placeBlock(level, Tile::wood_Id, 0, 6, 3, z, chunkBB);
1152 }
1153 placeBlock(level, Tile::wood_Id, 0, 7, 3, z, chunkBB);
1154 placeBlock(level, Tile::wood_Id, 0, 8, 3, z, chunkBB);
1155 }
1156 placeBlock(level, Tile::ladder_Id, getOrientationData(Tile::ladder_Id, Facing::WEST), 9, 1, 3, chunkBB);
1157 placeBlock(level, Tile::ladder_Id, getOrientationData(Tile::ladder_Id, Facing::WEST), 9, 2, 3, chunkBB);
1158 placeBlock(level, Tile::ladder_Id, getOrientationData(Tile::ladder_Id, Facing::WEST), 9, 3, 3, chunkBB);
1159
1160 createChest(level, chunkBB, random, 3, 4, 8, WeighedTreasure::addToTreasure(WeighedTreasureArray(smallTreasureItems,SMALL_TREASURE_ITEMS_COUNT), Item::enchantedBook->createForRandomTreasure(random)), 1 + random->nextInt(4));
1161 // System.out.println("Created chest at " + getWorldX(3, 8) +
1162 // "," + getWorldY(4) + "," + getWorldZ(3, 8));
1163
1164 }
1165 break;
1166 }
1167 return true;
1168}
1169
1170StrongholdPieces::PrisonHall::PrisonHall()
1171{
1172 // for reflection
1173}
1174
1175StrongholdPieces::PrisonHall::PrisonHall(int genDepth, Random *random, BoundingBox *stairsBox, int direction) : StrongholdPiece(genDepth)
1176{
1177 entryDoor = randomSmallDoor(random);
1178 orientation = direction;
1179 boundingBox = stairsBox;
1180}
1181
1182void StrongholdPieces::PrisonHall::addChildren(StructurePiece *startPiece, list<StructurePiece *> *pieces, Random *random)
1183{
1184 generateSmallDoorChildForward((StartPiece *) startPiece, pieces, random, 1, 1);
1185}
1186
1187StrongholdPieces::PrisonHall *StrongholdPieces::PrisonHall::createPiece(list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth)
1188{
1189 BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, -1, -1, 0, width, height, depth, direction);
1190
1191 StartPiece *startPiece = NULL;
1192 if(pieces != NULL) startPiece = ((StrongholdPieces::StartPiece *) pieces->front());
1193
1194 if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL)
1195 {
1196 delete box;
1197 return NULL;
1198 }
1199
1200 return new PrisonHall(genDepth, random, box, direction);
1201}
1202
1203bool StrongholdPieces::PrisonHall::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
1204{
1205 if (edgesLiquid(level, chunkBB))
1206 {
1207 return false;
1208 }
1209
1210 // bounding walls
1211 generateBox(level, chunkBB, 0, 0, 0, width - 1, height - 1, depth - 1, CHECK_AIR, random, (BlockSelector *)smoothStoneSelector);
1212 // entry door
1213 generateSmallDoor(level, random, chunkBB, entryDoor, 1, 1, 0);
1214 // exit openings
1215 generateBox(level, chunkBB, 1, 1, depth - 1, 3, 3, depth - 1, 0, 0, false);
1216
1217 // door pillars
1218 generateBox(level, chunkBB, 4, 1, 1, 4, 3, 1, false, random, (BlockSelector *)smoothStoneSelector);
1219 generateBox(level, chunkBB, 4, 1, 3, 4, 3, 3, false, random, (BlockSelector *)smoothStoneSelector);
1220 generateBox(level, chunkBB, 4, 1, 7, 4, 3, 7, false, random, (BlockSelector *)smoothStoneSelector);
1221 generateBox(level, chunkBB, 4, 1, 9, 4, 3, 9, false, random, (BlockSelector *)smoothStoneSelector);
1222
1223 // grates
1224 generateBox(level, chunkBB, 4, 1, 4, 4, 3, 6, Tile::ironFence_Id, Tile::ironFence_Id, false);
1225 generateBox(level, chunkBB, 5, 1, 5, 7, 3, 5, Tile::ironFence_Id, Tile::ironFence_Id, false);
1226
1227 // doors
1228 placeBlock(level, Tile::ironFence_Id, 0, 4, 3, 2, chunkBB);
1229 placeBlock(level, Tile::ironFence_Id, 0, 4, 3, 8, chunkBB);
1230 placeBlock(level, Tile::door_iron_Id, getOrientationData(Tile::door_iron_Id, 3), 4, 1, 2, chunkBB);
1231 placeBlock(level, Tile::door_iron_Id, getOrientationData(Tile::door_iron_Id, 3) + DoorTile::UPPER_BIT, 4, 2, 2, chunkBB);
1232 placeBlock(level, Tile::door_iron_Id, getOrientationData(Tile::door_iron_Id, 3), 4, 1, 8, chunkBB);
1233 placeBlock(level, Tile::door_iron_Id, getOrientationData(Tile::door_iron_Id, 3) + DoorTile::UPPER_BIT, 4, 2, 8, chunkBB);
1234
1235 return true;
1236
1237}
1238
1239StrongholdPieces::Library::Library()
1240{
1241 isTall = false;
1242 // for reflection
1243}
1244
1245StrongholdPieces::Library::Library(int genDepth, Random *random, BoundingBox *roomBox, int direction) : StrongholdPiece(genDepth),
1246 isTall(roomBox->getYSpan() > height)
1247{
1248 entryDoor = randomSmallDoor(random);
1249 orientation = direction;
1250 boundingBox = roomBox;
1251}
1252
1253void StrongholdPieces::Library::addAdditonalSaveData(CompoundTag *tag)
1254{
1255 StrongholdPiece::addAdditonalSaveData(tag);
1256 tag->putBoolean(L"Tall", isTall);
1257}
1258
1259void StrongholdPieces::Library::readAdditonalSaveData(CompoundTag *tag)
1260{
1261 StrongholdPiece::readAdditonalSaveData(tag);
1262 isTall = tag->getBoolean(L"Tall");
1263}
1264
1265StrongholdPieces::Library *StrongholdPieces::Library::createPiece(list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth)
1266{
1267 // attempt to make a tall library first
1268 BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, -4, -1, 0, width, tallHeight, depth, direction);
1269
1270 StartPiece *startPiece = NULL;
1271 if(pieces != NULL) startPiece = ((StrongholdPieces::StartPiece *) pieces->front());
1272
1273 if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL)
1274 {
1275 delete box;
1276 // make a short library
1277 box = BoundingBox::orientBox(footX, footY, footZ, -4, -1, 0, width, height, depth, direction);
1278
1279 if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL)
1280 {
1281 delete box;
1282 return NULL;
1283 }
1284 }
1285
1286 return new Library(genDepth, random, box, direction);
1287}
1288
1289WeighedTreasure *StrongholdPieces::Library::libraryTreasureItems[LIBRARY_TREASURE_ITEMS_COUNT] =
1290{
1291 new WeighedTreasure(Item::book_Id, 0, 1, 3, 20),
1292 new WeighedTreasure(Item::paper_Id, 0, 2, 7, 20),
1293 new WeighedTreasure(Item::map_Id, 0, 1, 1, 1),
1294 new WeighedTreasure(Item::compass_Id, 0, 1, 1, 1),
1295};
1296
1297bool StrongholdPieces::Library::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
1298{
1299 if (edgesLiquid(level, chunkBB))
1300 {
1301 return false;
1302 }
1303
1304 int currentHeight = tallHeight;
1305 if (!isTall)
1306 {
1307 currentHeight = height;
1308 }
1309
1310 // bounding walls
1311 generateBox(level, chunkBB, 0, 0, 0, width - 1, currentHeight - 1, depth - 1, CHECK_AIR, random, (BlockSelector *)smoothStoneSelector);
1312 // entry door
1313 generateSmallDoor(level, random, chunkBB, entryDoor, 4, 1, 0);
1314
1315 // place sparse cob webs
1316 generateMaybeBox(level, chunkBB, random, .07f, 2, 1, 1, width - 1 - 2, height - 2, depth - 2, Tile::web_Id, Tile::web_Id, false);
1317
1318 const int bookLeft = 1;
1319 const int bookRight = width - 2;
1320
1321 // place library walls
1322 for (int d = 1; d <= depth - 2; d++) {
1323 if (((d - 1) % 4) == 0) {
1324 generateBox(level, chunkBB, bookLeft, 1, d, bookLeft, 4, d, Tile::wood_Id, Tile::wood_Id, false);
1325 generateBox(level, chunkBB, bookRight, 1, d, bookRight, 4, d, Tile::wood_Id, Tile::wood_Id, false);
1326
1327 placeBlock(level, Tile::torch_Id, 0, 2, 3, d, chunkBB);
1328 placeBlock(level, Tile::torch_Id, 0, width - 3, 3, d, chunkBB);
1329
1330 if (isTall)
1331 {
1332 generateBox(level, chunkBB, bookLeft, 6, d, bookLeft, 9, d, Tile::wood_Id, Tile::wood_Id, false);
1333 generateBox(level, chunkBB, bookRight, 6, d, bookRight, 9, d, Tile::wood_Id, Tile::wood_Id, false);
1334 }
1335 }
1336 else
1337 {
1338 generateBox(level, chunkBB, bookLeft, 1, d, bookLeft, 4, d, Tile::bookshelf_Id, Tile::bookshelf_Id, false);
1339 generateBox(level, chunkBB, bookRight, 1, d, bookRight, 4, d, Tile::bookshelf_Id, Tile::bookshelf_Id, false);
1340
1341 if (isTall)
1342 {
1343 generateBox(level, chunkBB, bookLeft, 6, d, bookLeft, 9, d, Tile::bookshelf_Id, Tile::bookshelf_Id, false);
1344 generateBox(level, chunkBB, bookRight, 6, d, bookRight, 9, d, Tile::bookshelf_Id, Tile::bookshelf_Id, false);
1345 }
1346 }
1347 }
1348
1349 // place book shelves
1350 for (int d = 3; d < depth - 3; d += 2)
1351 {
1352 generateBox(level, chunkBB, 3, 1, d, 4, 3, d, Tile::bookshelf_Id, Tile::bookshelf_Id, false);
1353 generateBox(level, chunkBB, 6, 1, d, 7, 3, d, Tile::bookshelf_Id, Tile::bookshelf_Id, false);
1354 generateBox(level, chunkBB, 9, 1, d, 10, 3, d, Tile::bookshelf_Id, Tile::bookshelf_Id, false);
1355 }
1356
1357 if (isTall)
1358 {
1359 // create balcony
1360 generateBox(level, chunkBB, 1, 5, 1, 3, 5, depth - 2, Tile::wood_Id, Tile::wood_Id, false);
1361 generateBox(level, chunkBB, width - 4, 5, 1, width - 2, 5, depth - 2, Tile::wood_Id, Tile::wood_Id, false);
1362 generateBox(level, chunkBB, 4, 5, 1, width - 5, 5, 2, Tile::wood_Id, Tile::wood_Id, false);
1363 generateBox(level, chunkBB, 4, 5, depth - 3, width - 5, 5, depth - 2, Tile::wood_Id, Tile::wood_Id, false);
1364
1365 placeBlock(level, Tile::wood_Id, 0, width - 5, 5, depth - 4, chunkBB);
1366 placeBlock(level, Tile::wood_Id, 0, width - 6, 5, depth - 4, chunkBB);
1367 placeBlock(level, Tile::wood_Id, 0, width - 5, 5, depth - 5, chunkBB);
1368
1369 // balcony fences
1370 generateBox(level, chunkBB, 3, 6, 2, 3, 6, depth - 3, Tile::fence_Id, Tile::fence_Id, false);
1371 generateBox(level, chunkBB, width - 4, 6, 2, width - 4, 6, depth - 5, Tile::fence_Id, Tile::fence_Id, false);
1372 generateBox(level, chunkBB, 4, 6, 2, width - 5, 6, 2, Tile::fence_Id, Tile::fence_Id, false);
1373 generateBox(level, chunkBB, 4, 6, depth - 3, 8, 6, depth - 3, Tile::fence_Id, Tile::fence_Id, false);
1374 placeBlock(level, Tile::fence_Id, 0, width - 5, 6, depth - 4, chunkBB);
1375 placeBlock(level, Tile::fence_Id, 0, width - 6, 6, depth - 4, chunkBB);
1376 placeBlock(level, Tile::fence_Id, 0, width - 5, 6, depth - 5, chunkBB);
1377
1378 // ladder
1379 int orientationData = getOrientationData(Tile::ladder_Id, 3);
1380 placeBlock(level, Tile::ladder_Id, orientationData, width - 4, 1, depth - 2, chunkBB);
1381 placeBlock(level, Tile::ladder_Id, orientationData, width - 4, 2, depth - 2, chunkBB);
1382 placeBlock(level, Tile::ladder_Id, orientationData, width - 4, 3, depth - 2, chunkBB);
1383 placeBlock(level, Tile::ladder_Id, orientationData, width - 4, 4, depth - 2, chunkBB);
1384 placeBlock(level, Tile::ladder_Id, orientationData, width - 4, 5, depth - 2, chunkBB);
1385 placeBlock(level, Tile::ladder_Id, orientationData, width - 4, 6, depth - 2, chunkBB);
1386 placeBlock(level, Tile::ladder_Id, orientationData, width - 4, 7, depth - 2, chunkBB);
1387
1388 // chandelier
1389 int x = width / 2;
1390 int z = depth / 2;
1391 placeBlock(level, Tile::fence_Id, 0, x - 1, tallHeight - 2, z, chunkBB);
1392 placeBlock(level, Tile::fence_Id, 0, x, tallHeight - 2, z, chunkBB);
1393 placeBlock(level, Tile::fence_Id, 0, x - 1, tallHeight - 3, z, chunkBB);
1394 placeBlock(level, Tile::fence_Id, 0, x, tallHeight - 3, z, chunkBB);
1395 placeBlock(level, Tile::fence_Id, 0, x - 1, tallHeight - 4, z, chunkBB);
1396 placeBlock(level, Tile::fence_Id, 0, x, tallHeight - 4, z, chunkBB);
1397
1398 placeBlock(level, Tile::fence_Id, 0, x - 2, tallHeight - 4, z, chunkBB);
1399 placeBlock(level, Tile::fence_Id, 0, x + 1, tallHeight - 4, z, chunkBB);
1400 placeBlock(level, Tile::fence_Id, 0, x - 1, tallHeight - 4, z - 1, chunkBB);
1401 placeBlock(level, Tile::fence_Id, 0, x - 1, tallHeight - 4, z + 1, chunkBB);
1402 placeBlock(level, Tile::fence_Id, 0, x, tallHeight - 4, z - 1, chunkBB);
1403 placeBlock(level, Tile::fence_Id, 0, x, tallHeight - 4, z + 1, chunkBB);
1404
1405 placeBlock(level, Tile::torch_Id, 0, x - 2, tallHeight - 3, z, chunkBB);
1406 placeBlock(level, Tile::torch_Id, 0, x + 1, tallHeight - 3, z, chunkBB);
1407 placeBlock(level, Tile::torch_Id, 0, x - 1, tallHeight - 3, z - 1, chunkBB);
1408 placeBlock(level, Tile::torch_Id, 0, x - 1, tallHeight - 3, z + 1, chunkBB);
1409 placeBlock(level, Tile::torch_Id, 0, x, tallHeight - 3, z - 1, chunkBB);
1410 placeBlock(level, Tile::torch_Id, 0, x, tallHeight - 3, z + 1, chunkBB);
1411 }
1412
1413 // place chests
1414 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));
1415 if (isTall)
1416 {
1417 placeBlock(level, 0, 0, width - 2, tallHeight - 2, 1, chunkBB);
1418 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));
1419 }
1420
1421 return true;
1422
1423}
1424
1425StrongholdPieces::FiveCrossing::FiveCrossing()
1426{
1427 leftLow = leftHigh = rightLow = rightHigh = false;
1428 // for reflection
1429}
1430
1431StrongholdPieces::FiveCrossing::FiveCrossing(int genDepth, Random *random, BoundingBox *stairsBox, int direction) : StrongholdPiece(genDepth)
1432{
1433 entryDoor = randomSmallDoor(random);
1434 orientation = direction;
1435 boundingBox = stairsBox;
1436
1437 leftLow = random->nextBoolean();
1438 leftHigh = random->nextBoolean();
1439 rightLow = random->nextBoolean();
1440 rightHigh = random->nextInt(3) > 0;
1441}
1442
1443void StrongholdPieces::FiveCrossing::addAdditonalSaveData(CompoundTag *tag)
1444{
1445 StrongholdPiece::addAdditonalSaveData(tag);
1446 tag->putBoolean(L"leftLow", leftLow);
1447 tag->putBoolean(L"leftHigh", leftHigh);
1448 tag->putBoolean(L"rightLow", rightLow);
1449 tag->putBoolean(L"rightHigh", rightHigh);
1450}
1451
1452void StrongholdPieces::FiveCrossing::readAdditonalSaveData(CompoundTag *tag)
1453{
1454 StrongholdPiece::readAdditonalSaveData(tag);
1455 leftLow = tag->getBoolean(L"leftLow");
1456 leftHigh = tag->getBoolean(L"leftHigh");
1457 rightLow = tag->getBoolean(L"rightLow");
1458 rightHigh = tag->getBoolean(L"rightHigh");
1459}
1460
1461void StrongholdPieces::FiveCrossing::addChildren(StructurePiece *startPiece, list<StructurePiece *> *pieces, Random *random)
1462{
1463 int zOffA = 3;
1464 int zOffB = 5;
1465 // compensate for weird negative-facing behaviour
1466 if (orientation == Direction::WEST || orientation == Direction::NORTH)
1467 {
1468 zOffA = depth - 3 - zOffA;
1469 zOffB = depth - 3 - zOffB;
1470 }
1471
1472 generateSmallDoorChildForward((StartPiece *) startPiece, pieces, random, 5, 1);
1473 if (leftLow) generateSmallDoorChildLeft((StartPiece *) startPiece, pieces, random, zOffA, 1);
1474 if (leftHigh) generateSmallDoorChildLeft((StartPiece *) startPiece, pieces, random, zOffB, 7);
1475 if (rightLow) generateSmallDoorChildRight((StartPiece *) startPiece, pieces, random, zOffA, 1);
1476 if (rightHigh) generateSmallDoorChildRight((StartPiece *) startPiece, pieces, random, zOffB, 7);
1477}
1478
1479StrongholdPieces::FiveCrossing *StrongholdPieces::FiveCrossing::createPiece(list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth)
1480{
1481 BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, -4, -3, 0, width, height, depth, direction);
1482
1483 StartPiece *startPiece = NULL;
1484 if(pieces != NULL) startPiece = ((StrongholdPieces::StartPiece *) pieces->front());
1485
1486 if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL)
1487 {
1488 delete box;
1489 return NULL;
1490 }
1491
1492 return new FiveCrossing(genDepth, random, box, direction);
1493}
1494
1495bool StrongholdPieces::FiveCrossing::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
1496{
1497 if (edgesLiquid(level, chunkBB))
1498 {
1499 return false;
1500 }
1501
1502 // bounding walls
1503 generateBox(level, chunkBB, 0, 0, 0, width - 1, height - 1, depth - 1, CHECK_AIR, random, (BlockSelector *)smoothStoneSelector);
1504 // entry door
1505 generateSmallDoor(level, random, chunkBB, entryDoor, 4, 3, 0);
1506
1507 // exit openings
1508 if (leftLow) generateBox(level, chunkBB, 0, 3, 1, 0, 5, 3, 0, 0, false);
1509 if (rightLow) generateBox(level, chunkBB, 9, 3, 1, 9, 5, 3, 0, 0, false);
1510 if (leftHigh) generateBox(level, chunkBB, 0, 5, 7, 0, 7, 9, 0, 0, false);
1511 if (rightHigh) generateBox(level, chunkBB, 9, 5, 7, 9, 7, 9, 0, 0, false);
1512 generateBox(level, chunkBB, 5, 1, 10, 7, 3, 10, 0, 0, false);
1513
1514 // main floor
1515 generateBox(level, chunkBB, 1, 2, 1, 8, 2, 6, false, random, (BlockSelector *)smoothStoneSelector);
1516 // side walls
1517 generateBox(level, chunkBB, 4, 1, 5, 4, 4, 9, false, random, (BlockSelector *)smoothStoneSelector);
1518 generateBox(level, chunkBB, 8, 1, 5, 8, 4, 9, false, random, (BlockSelector *)smoothStoneSelector);
1519 // upper floor
1520 generateBox(level, chunkBB, 1, 4, 7, 3, 4, 9, false, random, (BlockSelector *)smoothStoneSelector);
1521
1522 // left stairs
1523 generateBox(level, chunkBB, 1, 3, 5, 3, 3, 6, false, random, (BlockSelector *)smoothStoneSelector);
1524 generateBox(level, chunkBB, 1, 3, 4, 3, 3, 4, Tile::stoneSlabHalf_Id, Tile::stoneSlabHalf_Id, false);
1525 generateBox(level, chunkBB, 1, 4, 6, 3, 4, 6, Tile::stoneSlabHalf_Id, Tile::stoneSlabHalf_Id, false);
1526
1527 // lower stairs
1528 generateBox(level, chunkBB, 5, 1, 7, 7, 1, 8, false, random, (BlockSelector *)smoothStoneSelector);
1529 generateBox(level, chunkBB, 5, 1, 9, 7, 1, 9, Tile::stoneSlabHalf_Id, Tile::stoneSlabHalf_Id, false);
1530 generateBox(level, chunkBB, 5, 2, 7, 7, 2, 7, Tile::stoneSlabHalf_Id, Tile::stoneSlabHalf_Id, false);
1531
1532 // bridge
1533 generateBox(level, chunkBB, 4, 5, 7, 4, 5, 9, Tile::stoneSlabHalf_Id, Tile::stoneSlabHalf_Id, false);
1534 generateBox(level, chunkBB, 8, 5, 7, 8, 5, 9, Tile::stoneSlabHalf_Id, Tile::stoneSlabHalf_Id, false);
1535 generateBox(level, chunkBB, 5, 5, 7, 7, 5, 9, Tile::stoneSlab_Id, Tile::stoneSlab_Id, false);
1536 placeBlock(level, Tile::torch_Id, 0, 6, 5, 6, chunkBB);
1537
1538 return true;
1539
1540}
1541
1542StrongholdPieces::PortalRoom::PortalRoom()
1543{
1544 // for reflection
1545}
1546
1547StrongholdPieces::PortalRoom::PortalRoom(int genDepth, Random *random, BoundingBox *box, int direction) : StrongholdPiece(genDepth)
1548{
1549 hasPlacedMobSpawner = false;
1550 orientation = direction;
1551 boundingBox = box;
1552}
1553
1554void StrongholdPieces::PortalRoom::addAdditonalSaveData(CompoundTag *tag)
1555{
1556 StrongholdPiece::addAdditonalSaveData(tag);
1557 tag->putBoolean(L"Mob", hasPlacedMobSpawner);
1558}
1559
1560void StrongholdPieces::PortalRoom::readAdditonalSaveData(CompoundTag *tag)
1561{
1562 StrongholdPiece::readAdditonalSaveData(tag);
1563 hasPlacedMobSpawner = tag->getBoolean(L"Mob");
1564}
1565
1566void StrongholdPieces::PortalRoom::addChildren(StructurePiece *startPiece, list<StructurePiece *> *pieces, Random *random)
1567{
1568 if (startPiece != NULL)
1569 {
1570 ((StartPiece *) startPiece)->portalRoomPiece = this;
1571 }
1572}
1573
1574StrongholdPieces::PortalRoom *StrongholdPieces::PortalRoom::createPiece(list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth)
1575{
1576 BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, -4, -1, 0, width, height, depth, direction);
1577
1578 // 4J Added so that we can check that Portals stay within the bounds of the world (which they ALWAYS should anyway)
1579 StartPiece *startPiece = NULL;
1580 if(pieces != NULL) startPiece = ((StrongholdPieces::StartPiece *) pieces->front());
1581
1582 if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL)
1583 {
1584 delete box;
1585 return NULL;
1586 }
1587
1588 return new PortalRoom(genDepth, random, box, direction);
1589}
1590
1591bool StrongholdPieces::PortalRoom::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
1592{
1593 // bounding walls
1594 generateBox(level, chunkBB, 0, 0, 0, width - 1, height - 1, depth - 1, false, random, (BlockSelector *)smoothStoneSelector);
1595 // entry door
1596 generateSmallDoor(level, random, chunkBB, GRATES, 4, 1, 0);
1597
1598 // inner roof row
1599 int y = height - 2;
1600 generateBox(level, chunkBB, 1, y, 1, 1, y, depth - 2, false, random, (BlockSelector *)smoothStoneSelector);
1601 generateBox(level, chunkBB, width - 2, y, 1, width - 2, y, depth - 2, false, random, (BlockSelector *)smoothStoneSelector);
1602 generateBox(level, chunkBB, 2, y, 1, width - 3, y, 2, false, random, (BlockSelector *)smoothStoneSelector);
1603 generateBox(level, chunkBB, 2, y, depth - 2, width - 3, y, depth - 2, false, random, (BlockSelector *)smoothStoneSelector);
1604
1605 // entrance lava pools
1606 generateBox(level, chunkBB, 1, 1, 1, 2, 1, 4, false, random, (BlockSelector *)smoothStoneSelector);
1607 generateBox(level, chunkBB, width - 3, 1, 1, width - 2, 1, 4, false, random, (BlockSelector *)smoothStoneSelector);
1608 generateBox(level, chunkBB, 1, 1, 1, 1, 1, 3, Tile::lava_Id, Tile::lava_Id, false);
1609 generateBox(level, chunkBB, width - 2, 1, 1, width - 2, 1, 3, Tile::lava_Id, Tile::lava_Id, false);
1610
1611 // portal lava pool
1612 generateBox(level, chunkBB, 3, 1, 8, 7, 1, 12, false, random, (BlockSelector *)smoothStoneSelector);
1613 generateBox(level, chunkBB, 4, 1, 9, 6, 1, 11, Tile::lava_Id, Tile::lava_Id, false);
1614
1615 // wall decorations
1616 for (int z = 3; z < depth - 2; z += 2)
1617 {
1618 generateBox(level, chunkBB, 0, 3, z, 0, 4, z, Tile::ironFence_Id, Tile::ironFence_Id, false);
1619 generateBox(level, chunkBB, width - 1, 3, z, width - 1, 4, z, Tile::ironFence_Id, Tile::ironFence_Id, false);
1620 }
1621 for (int x = 2; x < width - 2; x += 2)
1622 {
1623 generateBox(level, chunkBB, x, 3, depth - 1, x, 4, depth - 1, Tile::ironFence_Id, Tile::ironFence_Id, false);
1624 }
1625
1626 // stair
1627 int orientationData = getOrientationData(Tile::stairs_stoneBrick_Id, 3);
1628 generateBox(level, chunkBB, 4, 1, 5, 6, 1, 7, false, random, (BlockSelector *)smoothStoneSelector);
1629 generateBox(level, chunkBB, 4, 2, 6, 6, 2, 7, false, random, (BlockSelector *)smoothStoneSelector);
1630 generateBox(level, chunkBB, 4, 3, 7, 6, 3, 7, false, random, (BlockSelector *)smoothStoneSelector);
1631 for (int x = 4; x <= 6; x++)
1632 {
1633 placeBlock(level, Tile::stairs_stoneBrick_Id, orientationData, x, 1, 4, chunkBB);
1634 placeBlock(level, Tile::stairs_stoneBrick_Id, orientationData, x, 2, 5, chunkBB);
1635 placeBlock(level, Tile::stairs_stoneBrick_Id, orientationData, x, 3, 6, chunkBB);
1636 }
1637
1638 int north = Direction::NORTH;
1639 int south = Direction::SOUTH;
1640 int east = Direction::EAST;
1641 int west = Direction::WEST;
1642
1643 switch (orientation)
1644 {
1645 case Direction::SOUTH:
1646 north = Direction::SOUTH;
1647 south = Direction::NORTH;
1648 break;
1649 case Direction::EAST:
1650 north = Direction::EAST;
1651 south = Direction::WEST;
1652 east = Direction::SOUTH;
1653 west = Direction::NORTH;
1654 break;
1655 case Direction::WEST:
1656 north = Direction::WEST;
1657 south = Direction::EAST;
1658 east = Direction::SOUTH;
1659 west = Direction::NORTH;
1660 break;
1661 }
1662
1663 // 4J-PB - Removed for Christmas update since we don't have The End
1664
1665 // 4J-PB - not going to remove it, so that maps generated will have it in, but it can't be activated
1666 placeBlock(level, Tile::endPortalFrameTile_Id, north + ((random->nextFloat() > 0.9f) ? TheEndPortalFrameTile::EYE_BIT : 0), 4, 3, 8, chunkBB);
1667 placeBlock(level, Tile::endPortalFrameTile_Id, north + ((random->nextFloat() > 0.9f) ? TheEndPortalFrameTile::EYE_BIT : 0), 5, 3, 8, chunkBB);
1668 placeBlock(level, Tile::endPortalFrameTile_Id, north + ((random->nextFloat() > 0.9f) ? TheEndPortalFrameTile::EYE_BIT : 0), 6, 3, 8, chunkBB);
1669 placeBlock(level, Tile::endPortalFrameTile_Id, south + ((random->nextFloat() > 0.9f) ? TheEndPortalFrameTile::EYE_BIT : 0), 4, 3, 12, chunkBB);
1670 placeBlock(level, Tile::endPortalFrameTile_Id, south + ((random->nextFloat() > 0.9f) ? TheEndPortalFrameTile::EYE_BIT : 0), 5, 3, 12, chunkBB);
1671 placeBlock(level, Tile::endPortalFrameTile_Id, south + ((random->nextFloat() > 0.9f) ? TheEndPortalFrameTile::EYE_BIT : 0), 6, 3, 12, chunkBB);
1672 placeBlock(level, Tile::endPortalFrameTile_Id, east + ((random->nextFloat() > 0.9f) ? TheEndPortalFrameTile::EYE_BIT : 0), 3, 3, 9, chunkBB);
1673 placeBlock(level, Tile::endPortalFrameTile_Id, east + ((random->nextFloat() > 0.9f) ? TheEndPortalFrameTile::EYE_BIT : 0), 3, 3, 10, chunkBB);
1674 placeBlock(level, Tile::endPortalFrameTile_Id, east + ((random->nextFloat() > 0.9f) ? TheEndPortalFrameTile::EYE_BIT : 0), 3, 3, 11, chunkBB);
1675 placeBlock(level, Tile::endPortalFrameTile_Id, west + ((random->nextFloat() > 0.9f) ? TheEndPortalFrameTile::EYE_BIT : 0), 7, 3, 9, chunkBB);
1676 placeBlock(level, Tile::endPortalFrameTile_Id, west + ((random->nextFloat() > 0.9f) ? TheEndPortalFrameTile::EYE_BIT : 0), 7, 3, 10, chunkBB);
1677 placeBlock(level, Tile::endPortalFrameTile_Id, west + ((random->nextFloat() > 0.9f) ? TheEndPortalFrameTile::EYE_BIT : 0), 7, 3, 11, chunkBB);
1678
1679
1680 if (!hasPlacedMobSpawner)
1681 {
1682 y = getWorldY(3);
1683 int x = getWorldX(5, 6), z = getWorldZ(5, 6);
1684 if (chunkBB->isInside(x, y, z))
1685 {
1686 // 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
1687 app.AddTerrainFeaturePosition(eTerrainFeature_StrongholdEndPortal,x,z);
1688 level->getLevelData()->setXStrongholdEndPortal(x);
1689 level->getLevelData()->setZStrongholdEndPortal(z);
1690 level->getLevelData()->setHasStrongholdEndPortal();
1691
1692 hasPlacedMobSpawner = true;
1693 level->setTileAndData(x, y, z, Tile::mobSpawner_Id, 0, Tile::UPDATE_CLIENTS);
1694 shared_ptr<MobSpawnerTileEntity> entity = dynamic_pointer_cast<MobSpawnerTileEntity>(level->getTileEntity(x, y, z));
1695 if (entity != NULL) entity->getSpawner()->setEntityId(L"Silverfish");
1696 }
1697 }
1698
1699 return true;
1700
1701}
1702
1703void StrongholdPieces::SmoothStoneSelector::next(Random *random, int worldX, int worldY, int worldZ, bool isEdge)
1704{
1705 if (isEdge)
1706 {
1707 nextId = Tile::stoneBrick_Id;
1708
1709 float selection = random->nextFloat();
1710 if (selection < 0.2f)
1711 {
1712 nextData = SmoothStoneBrickTile::TYPE_CRACKED;
1713 }
1714 else if (selection < 0.5f)
1715 {
1716 nextData = SmoothStoneBrickTile::TYPE_MOSSY;
1717 }
1718 else if (selection < 0.55f)
1719 {
1720 nextId = Tile::monsterStoneEgg_Id;
1721 nextData = StoneMonsterTile::HOST_STONEBRICK;
1722 }
1723 else
1724 {
1725 nextData = 0;
1726 }
1727 }
1728 else
1729 {
1730 nextId = 0;
1731 nextData = 0;
1732 }
1733}
1734
1735const StrongholdPieces::SmoothStoneSelector *StrongholdPieces::smoothStoneSelector = new SmoothStoneSelector();