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 "net.minecraft.world.entity.item.h"
3#include "net.minecraft.world.level.levelgen.structure.h"
4#include "net.minecraft.world.level.h"
5#include "net.minecraft.world.level.tile.h"
6#include "net.minecraft.world.level.tile.entity.h"
7#include "net.minecraft.world.item.h"
8#include "JavaMath.h"
9#include "WeighedTreasure.h"
10#include "MineShaftPieces.h"
11
12WeighedTreasureArray MineShaftPieces::smallTreasureItems;;
13
14void MineShaftPieces::staticCtor()
15{
16 smallTreasureItems = WeighedTreasureArray(13);
17 smallTreasureItems[0] = new WeighedTreasure(Item::ironIngot_Id, 0, 1, 5, 10);
18 smallTreasureItems[1] = new WeighedTreasure(Item::goldIngot_Id, 0, 1, 3, 5);
19 smallTreasureItems[2] = new WeighedTreasure(Item::redStone_Id, 0, 4, 9, 5);
20 smallTreasureItems[3] = new WeighedTreasure(Item::dye_powder_Id, DyePowderItem::BLUE, 4, 9, 5);
21 smallTreasureItems[4] = new WeighedTreasure(Item::diamond_Id, 0, 1, 2, 3);
22 smallTreasureItems[5] = new WeighedTreasure(Item::coal_Id, CoalItem::STONE_COAL, 3, 8, 10);
23 smallTreasureItems[6] = new WeighedTreasure(Item::bread_Id, 0, 1, 3, 15);
24 smallTreasureItems[7] = new WeighedTreasure(Item::pickAxe_iron_Id, 0, 1, 1, 1);
25 smallTreasureItems[8] = new WeighedTreasure(Tile::rail_Id, 0, 4, 8, 1);
26 smallTreasureItems[9] = new WeighedTreasure(Item::seeds_melon_Id, 0, 2, 4, 10);
27 smallTreasureItems[10] = new WeighedTreasure(Item::seeds_pumpkin_Id, 0, 2, 4, 10);
28 // very rare for shafts ...
29 smallTreasureItems[11] = new WeighedTreasure(Item::saddle_Id, 0, 1, 1, 3);
30 smallTreasureItems[12] = new WeighedTreasure(Item::horseArmorMetal_Id, 0, 1, 1, 1);
31}
32
33void MineShaftPieces::loadStatic()
34{
35 StructureFeatureIO::setPieceId( eStructurePiece_MineShaftCorridor, MineShaftCorridor::Create, L"MSCorridor");
36 StructureFeatureIO::setPieceId( eStructurePiece_MineShaftCrossing, MineShaftCrossing::Create, L"MSCrossing");
37 StructureFeatureIO::setPieceId( eStructurePiece_MineShaftRoom, MineShaftRoom::Create, L"MSRoom");
38 StructureFeatureIO::setPieceId( eStructurePiece_MineShaftStairs, MineShaftStairs::Create, L"MSStairs");
39}
40
41StructurePiece *MineShaftPieces::createRandomShaftPiece(list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth)
42{
43 int randomSelection = random->nextInt(100);
44 if (randomSelection >= 80)
45 {
46 BoundingBox *crossingBox = MineShaftCrossing::findCrossing(pieces, random, footX, footY, footZ, direction);
47 if (crossingBox != NULL)
48 {
49 return new MineShaftCrossing(genDepth, random, crossingBox, direction);
50 }
51 }
52 else if (randomSelection >= 70)
53 {
54 BoundingBox *stairsBox = MineShaftStairs::findStairs(pieces, random, footX, footY, footZ, direction);
55 if (stairsBox != NULL)
56 {
57 return new MineShaftPieces::MineShaftStairs(genDepth, random, stairsBox, direction);
58 }
59 }
60 else
61 {
62 BoundingBox *corridorBox = MineShaftCorridor::findCorridorSize(pieces, random, footX, footY, footZ, direction);
63 if (corridorBox != NULL)
64 {
65 return new MineShaftCorridor(genDepth, random, corridorBox, direction);
66 }
67 }
68
69 return NULL;
70}
71
72StructurePiece *MineShaftPieces::generateAndAddPiece(StructurePiece *startPiece, list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int depth)
73{
74 if (depth > MAX_DEPTH)
75 {
76 return NULL;
77 }
78 if (abs(footX - startPiece->getBoundingBox()->x0) > 5 * 16 || abs(footZ - startPiece->getBoundingBox()->z0) > 5 * 16)
79 {
80 return NULL;
81 }
82
83 StructurePiece *newPiece = createRandomShaftPiece(pieces, random, footX, footY, footZ, direction, depth + 1);
84 if (newPiece != NULL)
85 {
86 MemSect(50);
87 pieces->push_back(newPiece);
88 MemSect(0);
89 newPiece->addChildren(startPiece, pieces, random);
90 }
91 return newPiece;
92}
93
94MineShaftPieces::MineShaftRoom::MineShaftRoom()
95{
96 // for reflection
97}
98
99MineShaftPieces::MineShaftRoom::MineShaftRoom(int genDepth, Random *random, int west, int north) : StructurePiece(genDepth)
100{
101 boundingBox = new BoundingBox(west, 50, north, west + 7 + random->nextInt(6), 54 + random->nextInt(6), north + 7 + random->nextInt(6));
102}
103
104MineShaftPieces::MineShaftRoom::~MineShaftRoom()
105{
106 for(AUTO_VAR(it, childEntranceBoxes.begin()); it != childEntranceBoxes.end(); ++it)
107 {
108 delete (*it);
109 }
110}
111
112void MineShaftPieces::MineShaftRoom::addChildren(StructurePiece *startPiece, list<StructurePiece *> *pieces, Random *random)
113{
114
115 int depth = getGenDepth();
116
117 int pos;
118
119 int heightSpace = boundingBox->getYSpan() - DEFAULT_SHAFT_HEIGHT - 1;
120 if (heightSpace <= 0)
121 {
122 heightSpace = 1;
123 }
124
125 // northern exits
126 pos = 0;
127 while (pos < boundingBox->getXSpan())
128 {
129 pos += random->nextInt(boundingBox->getXSpan());
130 if ((pos + DEFAULT_SHAFT_WIDTH) > boundingBox->getXSpan())
131 {
132 break;
133 }
134 StructurePiece *child = generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 + pos, boundingBox->y0 + random->nextInt(heightSpace) + 1, boundingBox->z0 - 1, Direction::NORTH, depth);
135 if (child != NULL)
136 {
137 BoundingBox *childBox = child->getBoundingBox();
138 childEntranceBoxes.push_back(new BoundingBox(childBox->x0, childBox->y0, boundingBox->z0, childBox->x1, childBox->y1, boundingBox->z0 + 1));
139 }
140 pos += DEFAULT_SHAFT_WIDTH + 1;
141 }
142 // southern exits
143 pos = 0;
144 while (pos < boundingBox->getXSpan())
145 {
146 pos += random->nextInt(boundingBox->getXSpan());
147 if ((pos + DEFAULT_SHAFT_WIDTH) > boundingBox->getXSpan())
148 {
149 break;
150 }
151 StructurePiece *child = generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 + pos, boundingBox->y0 + random->nextInt(heightSpace) + 1, boundingBox->z1 + 1, Direction::SOUTH, depth);
152 if (child != NULL)
153 {
154 BoundingBox *childBox = child->getBoundingBox();
155 childEntranceBoxes.push_back(new BoundingBox(childBox->x0, childBox->y0, boundingBox->z1 - 1, childBox->x1, childBox->y1, boundingBox->z1));
156 }
157 pos += DEFAULT_SHAFT_WIDTH + 1;
158 }
159 // western exits
160 pos = 0;
161 while (pos < boundingBox->getZSpan())
162 {
163 pos += random->nextInt(boundingBox->getZSpan());
164 if ((pos + DEFAULT_SHAFT_WIDTH) > boundingBox->getZSpan())
165 {
166 break;
167 }
168 StructurePiece *child = generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 - 1, boundingBox->y0 + random->nextInt(heightSpace) + 1, boundingBox->z0 + pos, Direction::WEST, depth);
169 if (child != NULL)
170 {
171 BoundingBox *childBox = child->getBoundingBox();
172 childEntranceBoxes.push_back(new BoundingBox(boundingBox->x0, childBox->y0, childBox->z0, boundingBox->x0 + 1, childBox->y1, childBox->z1));
173 }
174 pos += DEFAULT_SHAFT_WIDTH + 1;
175 }
176 // eastern exits
177 pos = 0;
178 while (pos < boundingBox->getZSpan())
179 {
180 pos += random->nextInt(boundingBox->getZSpan());
181 if ((pos + DEFAULT_SHAFT_WIDTH) > boundingBox->getZSpan())
182 {
183 break;
184 }
185 StructurePiece *child = generateAndAddPiece(startPiece, pieces, random, boundingBox->x1 + 1, boundingBox->y0 + random->nextInt(heightSpace) + 1, boundingBox->z0 + pos, Direction::EAST, depth);
186 if (child != NULL)
187 {
188 BoundingBox *childBox = child->getBoundingBox();
189 childEntranceBoxes.push_back(new BoundingBox(boundingBox->x1 - 1, childBox->y0, childBox->z0, boundingBox->x1, childBox->y1, childBox->z1));
190 }
191 pos += DEFAULT_SHAFT_WIDTH + 1;
192 }
193}
194
195bool MineShaftPieces::MineShaftRoom::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
196{
197 if (edgesLiquid(level, chunkBB))
198 {
199 return false;
200 }
201
202 // floor
203 generateBox(level, chunkBB, boundingBox->x0, boundingBox->y0, boundingBox->z0, boundingBox->x1, boundingBox->y0, boundingBox->z1, Tile::dirt_Id, 0, true);
204
205 // room air
206 generateBox(level, chunkBB, boundingBox->x0, boundingBox->y0 + 1, boundingBox->z0, boundingBox->x1, min(boundingBox->y0 + 3, boundingBox->y1), boundingBox->z1, 0, 0, false);
207 for(AUTO_VAR(it, childEntranceBoxes.begin()); it != childEntranceBoxes.end(); ++it)
208 {
209 BoundingBox *entranceBox = *it;
210 generateBox(level, chunkBB, entranceBox->x0, entranceBox->y1 - (DEFAULT_SHAFT_HEIGHT - 1), entranceBox->z0, entranceBox->x1, entranceBox->y1, entranceBox->z1, 0, 0, false);
211 }
212 generateUpperHalfSphere(level, chunkBB, boundingBox->x0, boundingBox->y0 + 4, boundingBox->z0, boundingBox->x1, boundingBox->y1, boundingBox->z1, 0, false);
213
214 return true;
215}
216
217void MineShaftPieces::MineShaftRoom::addAdditonalSaveData(CompoundTag *tag)
218{
219 ListTag<IntArrayTag> *entrances = new ListTag<IntArrayTag>(L"Entrances");
220 for (AUTO_VAR(it,childEntranceBoxes.begin()); it != childEntranceBoxes.end(); ++it)
221 {
222 BoundingBox *bb =*it;
223 entrances->add(bb->createTag(L""));
224 }
225 tag->put(L"Entrances", entrances);
226}
227
228void MineShaftPieces::MineShaftRoom::readAdditonalSaveData(CompoundTag *tag)
229{
230 ListTag<IntArrayTag> *entrances = (ListTag<IntArrayTag> *) tag->getList(L"Entrances");
231 for (int i = 0; i < entrances->size(); i++)
232 {
233 childEntranceBoxes.push_back(new BoundingBox(entrances->get(i)->data));
234 }
235}
236
237MineShaftPieces::MineShaftCorridor::MineShaftCorridor()
238{
239 // for reflection
240}
241
242void MineShaftPieces::MineShaftCorridor::addAdditonalSaveData(CompoundTag *tag)
243{
244 tag->putBoolean(L"hr", hasRails);
245 tag->putBoolean(L"sc", spiderCorridor);
246 tag->putBoolean(L"hps", hasPlacedSpider);
247 tag->putInt(L"Num", numSections);
248}
249
250void MineShaftPieces::MineShaftCorridor::readAdditonalSaveData(CompoundTag *tag)
251{
252 hasRails = tag->getBoolean(L"hr");
253 spiderCorridor = tag->getBoolean(L"sc");
254 hasPlacedSpider = tag->getBoolean(L"hps");
255 numSections = tag->getInt(L"Num");
256}
257
258MineShaftPieces::MineShaftCorridor::MineShaftCorridor(int genDepth, Random *random, BoundingBox *corridorBox, int direction)
259 : StructurePiece(genDepth)
260{
261 orientation = direction;
262 boundingBox = corridorBox;
263 hasRails = random->nextInt(3) == 0;
264 hasPlacedSpider=false;
265 spiderCorridor = !hasRails && random->nextInt(23) == 0;
266 //debug
267 //spiderCorridor = !hasRails ;//&& random->nextInt(23) == 0;
268
269 if (orientation == Direction::NORTH || orientation == Direction::SOUTH)
270 {
271 numSections = corridorBox->getZSpan() / DEFAULT_SHAFT_LENGTH;
272 }
273 else
274 {
275 numSections = corridorBox->getXSpan() / DEFAULT_SHAFT_LENGTH;
276 }
277}
278
279BoundingBox *MineShaftPieces::MineShaftCorridor::findCorridorSize(list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction)
280{
281
282 BoundingBox *box = new BoundingBox(footX, footY, footZ, footX, footY + (DEFAULT_SHAFT_HEIGHT - 1), footZ);
283
284 int corridorLength = random->nextInt(3) + 2;
285 while (corridorLength > 0)
286 {
287 int blockLength = corridorLength * DEFAULT_SHAFT_LENGTH;
288
289 switch (direction)
290 {
291 case Direction::NORTH:
292 box->x1 = footX + (DEFAULT_SHAFT_WIDTH - 1);
293 box->z0 = footZ - (blockLength - 1);
294 break;
295 case Direction::SOUTH:
296 box->x1 = footX + (DEFAULT_SHAFT_WIDTH - 1);
297 box->z1 = footZ + (blockLength - 1);
298 break;
299 case Direction::WEST:
300 box->x0 = footX - (blockLength - 1);
301 box->z1 = footZ + (DEFAULT_SHAFT_WIDTH - 1);
302 break;
303 case Direction::EAST:
304 box->x1 = footX + (blockLength - 1);
305 box->z1 = footZ + (DEFAULT_SHAFT_WIDTH - 1);
306 break;
307 }
308
309 if (StructurePiece::findCollisionPiece(pieces, box) != NULL)
310 {
311 corridorLength--;
312 }
313 else
314 {
315 break;
316 }
317 }
318
319 if (corridorLength > 0)
320 {
321 return box;
322 }
323 delete box;
324 // unable to place corridor here
325 return NULL;
326}
327
328void MineShaftPieces::MineShaftCorridor::addChildren(StructurePiece *startPiece, list<StructurePiece *> *pieces, Random *random)
329{
330 int depth = getGenDepth();
331 int endSelection = random->nextInt(4);
332 switch (orientation)
333 {
334 case Direction::NORTH:
335 if (endSelection <= 1)
336 {
337 generateAndAddPiece(startPiece, pieces, random, boundingBox->x0, boundingBox->y0 - 1 + random->nextInt(3), boundingBox->z0 - 1, orientation, depth);
338 }
339 else if (endSelection == 2)
340 {
341 generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 - 1, boundingBox->y0 - 1 + random->nextInt(3), boundingBox->z0, Direction::WEST, depth);
342 }
343 else
344 {
345 generateAndAddPiece(startPiece, pieces, random, boundingBox->x1 + 1, boundingBox->y0 - 1 + random->nextInt(3), boundingBox->z0, Direction::EAST, depth);
346 }
347 break;
348 case Direction::SOUTH:
349 if (endSelection <= 1)
350 {
351 generateAndAddPiece(startPiece, pieces, random, boundingBox->x0, boundingBox->y0 - 1 + random->nextInt(3), boundingBox->z1 + 1, orientation, depth);
352 }
353 else if (endSelection == 2)
354 {
355 generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 - 1, boundingBox->y0 - 1 + random->nextInt(3), boundingBox->z1 - DEFAULT_SHAFT_WIDTH, Direction::WEST, depth);
356 }
357 else
358 {
359 generateAndAddPiece(startPiece, pieces, random, boundingBox->x1 + 1, boundingBox->y0 - 1 + random->nextInt(3), boundingBox->z1 - DEFAULT_SHAFT_WIDTH, Direction::EAST, depth);
360 }
361 break;
362 case Direction::WEST:
363 if (endSelection <= 1)
364 {
365 generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 - 1, boundingBox->y0 - 1 + random->nextInt(3), boundingBox->z0, orientation, depth);
366 }
367 else if (endSelection == 2)
368 {
369 generateAndAddPiece(startPiece, pieces, random, boundingBox->x0, boundingBox->y0 - 1 + random->nextInt(3), boundingBox->z0 - 1, Direction::NORTH, depth);
370 }
371 else
372 {
373 generateAndAddPiece(startPiece, pieces, random, boundingBox->x0, boundingBox->y0 - 1 + random->nextInt(3), boundingBox->z1 + 1, Direction::SOUTH, depth);
374 }
375 break;
376 case Direction::EAST:
377 if (endSelection <= 1)
378 {
379 generateAndAddPiece(startPiece, pieces, random, boundingBox->x1 + 1, boundingBox->y0 - 1 + random->nextInt(3), boundingBox->z0, orientation, depth);
380 }
381 else if (endSelection == 2)
382 {
383 generateAndAddPiece(startPiece, pieces, random, boundingBox->x1 - DEFAULT_SHAFT_WIDTH, boundingBox->y0 - 1 + random->nextInt(3), boundingBox->z0 - 1, Direction::NORTH, depth);
384 }
385 else
386 {
387 generateAndAddPiece(startPiece, pieces, random, boundingBox->x1 - DEFAULT_SHAFT_WIDTH, boundingBox->y0 - 1 + random->nextInt(3), boundingBox->z1 + 1, Direction::SOUTH, depth);
388 }
389 break;
390 }
391
392 // generate cross sections using higher depth
393 if (depth < MAX_DEPTH)
394 {
395 if (orientation == Direction::NORTH || orientation == Direction::SOUTH)
396 {
397 for (int z = boundingBox->z0 + 3; (z + DEFAULT_SHAFT_WIDTH) <= boundingBox->z1; z += DEFAULT_SHAFT_LENGTH)
398 {
399 int selection = random->nextInt(5);
400 if (selection == 0)
401 {
402 generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 - 1, boundingBox->y0, z, Direction::WEST, depth + 1);
403 }
404 else if (selection == 1)
405 {
406 generateAndAddPiece(startPiece, pieces, random, boundingBox->x1 + 1, boundingBox->y0, z, Direction::EAST, depth + 1);
407 }
408 }
409 }
410 else
411 {
412 for (int x = boundingBox->x0 + 3; (x + DEFAULT_SHAFT_WIDTH) <= boundingBox->x1; x += DEFAULT_SHAFT_LENGTH)
413 {
414 int selection = random->nextInt(5);
415 if (selection == 0)
416 {
417 generateAndAddPiece(startPiece, pieces, random, x, boundingBox->y0, boundingBox->z0 - 1, Direction::NORTH, depth + 1);
418 }
419 else if (selection == 1)
420 {
421 generateAndAddPiece(startPiece, pieces, random, x, boundingBox->y0, boundingBox->z1 + 1, Direction::SOUTH, depth + 1);
422 }
423 }
424 }
425 }
426}
427
428bool MineShaftPieces::MineShaftCorridor::createChest(Level *level, BoundingBox *chunkBB, Random *random, int x, int y, int z, WeighedTreasureArray treasure, int numRolls)
429{
430 int worldX = getWorldX(x, z);
431 int worldY = getWorldY(y);
432 int worldZ = getWorldZ(x, z);
433
434 if (chunkBB->isInside(worldX, worldY, worldZ))
435 {
436 if (level->getTile(worldX, worldY, worldZ) == 0)
437 {
438 level->setTileAndData(worldX, worldY, worldZ, Tile::rail_Id, getOrientationData(Tile::rail_Id, random->nextBoolean() ? RailTile::DIR_FLAT_X : RailTile::DIR_FLAT_Z), Tile::UPDATE_CLIENTS);
439 shared_ptr<MinecartChest> chest = shared_ptr<MinecartChest>( new MinecartChest(level, worldX + 0.5f, worldY + 0.5f, worldZ + 0.5f) );
440 WeighedTreasure::addChestItems(random, treasure, chest, numRolls);
441 level->addEntity(chest);
442 return true;
443 }
444 }
445
446 return false;
447}
448
449bool MineShaftPieces::MineShaftCorridor::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
450{
451 if (edgesLiquid(level, chunkBB))
452 {
453 return false;
454 }
455
456 const int x0 = 0;
457 const int x1 = DEFAULT_SHAFT_WIDTH - 1;
458 const int y0 = 0;
459 const int y1 = DEFAULT_SHAFT_HEIGHT - 1;
460 const int length = (numSections * DEFAULT_SHAFT_LENGTH) - 1;
461
462 // corridor air
463 generateBox(level, chunkBB, x0, 0, y0, x1, y1 - 1, length, 0, 0, false);
464 generateMaybeBox(level, chunkBB, random, .8f, x0, y1, y0, x1, y1, length, 0, 0, false);
465
466 if (spiderCorridor)
467 {
468 generateMaybeBox(level, chunkBB, random, .6f, x0, 0, y0, x1, y1 - 1, length, Tile::web_Id, 0, false);
469 }
470
471 // place a support in every section
472 for (int section = 0; section < numSections; section++)
473 {
474
475 int z = 2 + section * DEFAULT_SHAFT_LENGTH;
476
477 // 4J-PB - Bringing forward the changes in 1.2.3
478 generateBox(level, chunkBB, x0, y0, z, x0, y1 - 1, z, Tile::fence_Id, 0, false);
479 generateBox(level, chunkBB, x1, y0, z, x1, y1 - 1, z, Tile::fence_Id, 0, false);
480 if (random->nextInt(4) == 0)
481 {
482 generateBox(level, chunkBB, x0, y1, z, x0, y1, z, Tile::wood_Id, 0, false);
483 generateBox(level, chunkBB, x1, y1, z, x1, y1, z, Tile::wood_Id, 0, false);
484 }
485 else
486 {
487 generateBox(level, chunkBB, x0, y1, z, x1, y1, z, Tile::wood_Id, 0, false);
488 }
489 maybeGenerateBlock(level, chunkBB, random, .1f, x0, y1, z - 1, Tile::web_Id, 0);
490 maybeGenerateBlock(level, chunkBB, random, .1f, x1, y1, z - 1, Tile::web_Id, 0);
491 maybeGenerateBlock(level, chunkBB, random, .1f, x0, y1, z + 1, Tile::web_Id, 0);
492 maybeGenerateBlock(level, chunkBB, random, .1f, x1, y1, z + 1, Tile::web_Id, 0);
493 maybeGenerateBlock(level, chunkBB, random, .05f, x0, y1, z - 2, Tile::web_Id, 0);
494 maybeGenerateBlock(level, chunkBB, random, .05f, x1, y1, z - 2, Tile::web_Id, 0);
495 maybeGenerateBlock(level, chunkBB, random, .05f, x0, y1, z + 2, Tile::web_Id, 0);
496 maybeGenerateBlock(level, chunkBB, random, .05f, x1, y1, z + 2, Tile::web_Id, 0);
497
498 maybeGenerateBlock(level, chunkBB, random, .05f, x0 + 1, y1, z - 1, Tile::torch_Id, 0);
499 maybeGenerateBlock(level, chunkBB, random, .05f, x0 + 1, y1, z + 1, Tile::torch_Id, 0);
500
501 if (random->nextInt(100) == 0)
502 {
503 createChest(level, chunkBB, random, x1, y0, z - 1, WeighedTreasure::addToTreasure(smallTreasureItems, Item::enchantedBook->createForRandomTreasure(random)), 3 + random->nextInt(4));
504 }
505 if (random->nextInt(100) == 0)
506 {
507 createChest(level, chunkBB, random, x0, y0, z + 1, WeighedTreasure::addToTreasure(smallTreasureItems, Item::enchantedBook->createForRandomTreasure(random)), 3 + random->nextInt(4));
508 }
509
510 if (spiderCorridor && !hasPlacedSpider)
511 {
512 int y = getWorldY(y0), newZ = z - 1 + random->nextInt(3);
513 int x = getWorldX(x0 + 1, newZ);
514 newZ = getWorldZ(x0 + 1, newZ);
515 if (chunkBB->isInside(x, y, newZ))
516 {
517 hasPlacedSpider = true;
518 level->setTileAndData(x, y, newZ, Tile::mobSpawner_Id, 0, Tile::UPDATE_CLIENTS);
519 shared_ptr<MobSpawnerTileEntity> entity = dynamic_pointer_cast<MobSpawnerTileEntity>( level->getTileEntity(x, y, newZ) );
520 if (entity != NULL) entity->getSpawner()->setEntityId(L"CaveSpider");
521 }
522 }
523 }
524
525 // prevent air floating
526 for (int x = x0; x <= x1; x++)
527 {
528 for (int z = 0; z <= length; z++)
529 {
530 int block = getBlock(level, x, -1, z, chunkBB);
531 if (block == 0)
532 {
533 placeBlock(level, Tile::wood_Id, 0, x, -1, z, chunkBB);
534 }
535 }
536 }
537
538 if (hasRails)
539 {
540 for (int z = 0; z <= length; z++)
541 {
542 int floor = getBlock(level, x0 + 1, y0 - 1, z, chunkBB);
543 if (floor > 0 && Tile::solid[floor])
544 {
545 maybeGenerateBlock(level, chunkBB, random, .7f, x0 + 1, y0, z, Tile::rail_Id, getOrientationData(Tile::rail_Id, BaseRailTile::DIR_FLAT_Z));
546 }
547 }
548 }
549
550 return true;
551}
552
553MineShaftPieces::MineShaftCrossing::MineShaftCrossing()
554{
555 // for reflection
556}
557
558void MineShaftPieces::MineShaftCrossing::addAdditonalSaveData(CompoundTag *tag)
559{
560 tag->putBoolean(L"tf", isTwoFloored);
561 tag->putInt(L"D", direction);
562}
563
564void MineShaftPieces::MineShaftCrossing::readAdditonalSaveData(CompoundTag *tag)
565{
566 isTwoFloored = tag->getBoolean(L"tf");
567 direction = tag->getInt(L"D");
568}
569
570MineShaftPieces::MineShaftCrossing::MineShaftCrossing(int genDepth, Random *random, BoundingBox *crossingBox, int direction)
571 : StructurePiece(genDepth), direction(direction), isTwoFloored( crossingBox->getYSpan() > DEFAULT_SHAFT_HEIGHT )
572{
573 boundingBox = crossingBox;
574}
575
576BoundingBox *MineShaftPieces::MineShaftCrossing::findCrossing(list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction)
577{
578
579 BoundingBox *box = new BoundingBox(footX, footY, footZ, footX, footY + (DEFAULT_SHAFT_HEIGHT - 1), footZ);
580
581 if (random->nextInt(4) == 0)
582 {
583 box->y1 += DEFAULT_SHAFT_HEIGHT + 1; // two-floored
584 }
585
586 switch (direction)
587 {
588 case Direction::NORTH:
589 box->x0 = footX - 1;
590 box->x1 = footX + DEFAULT_SHAFT_WIDTH;
591 box->z0 = footZ - (DEFAULT_SHAFT_WIDTH + 1);
592 break;
593 case Direction::SOUTH:
594 box->x0 = footX - 1;
595 box->x1 = footX + DEFAULT_SHAFT_WIDTH;
596 box->z1 = footZ + (DEFAULT_SHAFT_WIDTH + 1);
597 break;
598 case Direction::WEST:
599 box->x0 = footX - (DEFAULT_SHAFT_WIDTH + 1);
600 box->z0 = footZ - 1;
601 box->z1 = footZ + DEFAULT_SHAFT_WIDTH;
602 break;
603 case Direction::EAST:
604 box->x1 = footX + (DEFAULT_SHAFT_WIDTH + 1);
605 box->z0 = footZ - 1;
606 box->z1 = footZ + DEFAULT_SHAFT_WIDTH;
607 break;
608 }
609
610 if (StructurePiece::findCollisionPiece(pieces, box) != NULL)
611 {
612 delete box;
613 return NULL;
614 }
615
616 return box;
617}
618
619void MineShaftPieces::MineShaftCrossing::addChildren(StructurePiece *startPiece, list<StructurePiece *> *pieces, Random *random)
620{
621
622 int depth = getGenDepth();
623 // crossings are coming from a direction and will generate children
624 // in the
625 // remaining three directions
626 switch (direction)
627 {
628 case Direction::NORTH:
629 generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 + 1, boundingBox->y0, boundingBox->z0 - 1, Direction::NORTH, depth);
630 generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 - 1, boundingBox->y0, boundingBox->z0 + 1, Direction::WEST, depth);
631 generateAndAddPiece(startPiece, pieces, random, boundingBox->x1 + 1, boundingBox->y0, boundingBox->z0 + 1, Direction::EAST, depth);
632 break;
633 case Direction::SOUTH:
634 generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 + 1, boundingBox->y0, boundingBox->z1 + 1, Direction::SOUTH, depth);
635 generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 - 1, boundingBox->y0, boundingBox->z0 + 1, Direction::WEST, depth);
636 generateAndAddPiece(startPiece, pieces, random, boundingBox->x1 + 1, boundingBox->y0, boundingBox->z0 + 1, Direction::EAST, depth);
637 break;
638 case Direction::WEST:
639 generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 + 1, boundingBox->y0, boundingBox->z0 - 1, Direction::NORTH, depth);
640 generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 + 1, boundingBox->y0, boundingBox->z1 + 1, Direction::SOUTH, depth);
641 generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 - 1, boundingBox->y0, boundingBox->z0 + 1, Direction::WEST, depth);
642 break;
643 case Direction::EAST:
644 generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 + 1, boundingBox->y0, boundingBox->z0 - 1, Direction::NORTH, depth);
645 generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 + 1, boundingBox->y0, boundingBox->z1 + 1, Direction::SOUTH, depth);
646 generateAndAddPiece(startPiece, pieces, random, boundingBox->x1 + 1, boundingBox->y0, boundingBox->z0 + 1, Direction::EAST, depth);
647 break;
648 }
649
650 if (isTwoFloored)
651 {
652 if (random->nextBoolean()) generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 + 1, boundingBox->y0 + DEFAULT_SHAFT_HEIGHT + 1, boundingBox->z0 - 1, Direction::NORTH, depth);
653 if (random->nextBoolean()) generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 - 1, boundingBox->y0 + DEFAULT_SHAFT_HEIGHT + 1, boundingBox->z0 + 1, Direction::WEST, depth);
654 if (random->nextBoolean()) generateAndAddPiece(startPiece, pieces, random, boundingBox->x1 + 1, boundingBox->y0 + DEFAULT_SHAFT_HEIGHT + 1, boundingBox->z0 + 1, Direction::EAST, depth);
655 if (random->nextBoolean()) generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 + 1, boundingBox->y0 + DEFAULT_SHAFT_HEIGHT + 1, boundingBox->z1 + 1, Direction::SOUTH, depth);
656 }
657}
658
659bool MineShaftPieces::MineShaftCrossing::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
660{
661 if (edgesLiquid(level, chunkBB))
662 {
663 return false;
664 }
665
666 // corridor air
667 if (isTwoFloored)
668 {
669 generateBox(level, chunkBB, boundingBox->x0 + 1, boundingBox->y0, boundingBox->z0, boundingBox->x1 - 1, boundingBox->y0 + DEFAULT_SHAFT_HEIGHT - 1, boundingBox->z1, 0, 0, false);
670 generateBox(level, chunkBB, boundingBox->x0, boundingBox->y0, boundingBox->z0 + 1, boundingBox->x1, boundingBox->y0 + DEFAULT_SHAFT_HEIGHT - 1, boundingBox->z1 - 1, 0, 0, false);
671 generateBox(level, chunkBB, boundingBox->x0 + 1, boundingBox->y1 - (DEFAULT_SHAFT_HEIGHT - 1), boundingBox->z0, boundingBox->x1 - 1, boundingBox->y1, boundingBox->z1, 0, 0, false);
672 generateBox(level, chunkBB, boundingBox->x0, boundingBox->y1 - (DEFAULT_SHAFT_HEIGHT - 1), boundingBox->z0 + 1, boundingBox->x1, boundingBox->y1, boundingBox->z1 - 1, 0, 0, false);
673 generateBox(level, chunkBB, boundingBox->x0 + 1, boundingBox->y0 + DEFAULT_SHAFT_HEIGHT, boundingBox->z0 + 1, boundingBox->x1 - 1, boundingBox->y0 + DEFAULT_SHAFT_HEIGHT, boundingBox->z1 - 1, 0, 0, false);
674 }
675 else
676 {
677 generateBox(level, chunkBB, boundingBox->x0 + 1, boundingBox->y0, boundingBox->z0, boundingBox->x1 - 1, boundingBox->y1, boundingBox->z1, 0, 0, false);
678 generateBox(level, chunkBB, boundingBox->x0, boundingBox->y0, boundingBox->z0 + 1, boundingBox->x1, boundingBox->y1, boundingBox->z1 - 1, 0, 0, false);
679 }
680
681 // support pillars
682 generateBox(level, chunkBB, boundingBox->x0 + 1, boundingBox->y0, boundingBox->z0 + 1, boundingBox->x0 + 1, boundingBox->y1, boundingBox->z0 + 1, Tile::wood_Id, 0, false);
683 generateBox(level, chunkBB, boundingBox->x0 + 1, boundingBox->y0, boundingBox->z1 - 1, boundingBox->x0 + 1, boundingBox->y1, boundingBox->z1 - 1, Tile::wood_Id, 0, false);
684 generateBox(level, chunkBB, boundingBox->x1 - 1, boundingBox->y0, boundingBox->z0 + 1, boundingBox->x1 - 1, boundingBox->y1, boundingBox->z0 + 1, Tile::wood_Id, 0, false);
685 generateBox(level, chunkBB, boundingBox->x1 - 1, boundingBox->y0, boundingBox->z1 - 1, boundingBox->x1 - 1, boundingBox->y1, boundingBox->z1 - 1, Tile::wood_Id, 0, false);
686
687 // prevent air floating
688 // note: use world coordinates because the corridor hasn't defined
689 // orientation
690 for (int x = boundingBox->x0; x <= boundingBox->x1; x++)
691 {
692 for (int z = boundingBox->z0; z <= boundingBox->z1; z++)
693 {
694 int block = getBlock(level, x, boundingBox->y0 - 1, z, chunkBB);
695 if (block == 0)
696 {
697 placeBlock(level, Tile::wood_Id, 0, x, boundingBox->y0 - 1, z, chunkBB);
698 }
699 }
700 }
701
702 return true;
703}
704
705MineShaftPieces::MineShaftStairs::MineShaftStairs()
706{
707 // for reflection
708}
709
710MineShaftPieces::MineShaftStairs::MineShaftStairs(int genDepth, Random *random, BoundingBox *stairsBox, int direction) : StructurePiece(genDepth)
711{
712 this->orientation = direction;
713 boundingBox = stairsBox;
714}
715
716
717void MineShaftPieces::MineShaftStairs::addAdditonalSaveData(CompoundTag *tag)
718{
719}
720
721void MineShaftPieces::MineShaftStairs::readAdditonalSaveData(CompoundTag *tag)
722{
723}
724
725BoundingBox *MineShaftPieces::MineShaftStairs::findStairs(list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction)
726{
727 // stairs are two steps in, 5x5 steps down, two steps out
728
729 BoundingBox *box = new BoundingBox(footX, footY - 5, footZ, footX, footY + (DEFAULT_SHAFT_HEIGHT - 1), footZ);
730
731 switch (direction)
732 {
733 case Direction::NORTH:
734 box->x1 = footX + (DEFAULT_SHAFT_WIDTH - 1);
735 box->z0 = footZ - 8;
736 break;
737 case Direction::SOUTH:
738 box->x1 = footX + (DEFAULT_SHAFT_WIDTH - 1);
739 box->z1 = footZ + 8;
740 break;
741 case Direction::WEST:
742 box->x0 = footX - 8;
743 box->z1 = footZ + (DEFAULT_SHAFT_WIDTH - 1);
744 break;
745 case Direction::EAST:
746 box->x1 = footX + 8;
747 box->z1 = footZ + (DEFAULT_SHAFT_WIDTH - 1);
748 break;
749 }
750
751 if (StructurePiece::findCollisionPiece(pieces, box) != NULL)
752 {
753 delete box;
754 return NULL;
755 }
756
757 return box;
758}
759
760void MineShaftPieces::MineShaftStairs::addChildren(StructurePiece *startPiece, list<StructurePiece *> *pieces, Random *random)
761{
762 int depth = getGenDepth();
763 // crossings are coming from a direction and will generate children
764 // in the
765 // remaining three directions
766 switch (orientation)
767 {
768 case Direction::NORTH:
769 generateAndAddPiece(startPiece, pieces, random, boundingBox->x0, boundingBox->y0, boundingBox->z0 - 1, Direction::NORTH, depth);
770 break;
771 case Direction::SOUTH:
772 generateAndAddPiece(startPiece, pieces, random, boundingBox->x0, boundingBox->y0, boundingBox->z1 + 1, Direction::SOUTH, depth);
773 break;
774 case Direction::WEST:
775 generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 - 1, boundingBox->y0, boundingBox->z0, Direction::WEST, depth);
776 break;
777 case Direction::EAST:
778 generateAndAddPiece(startPiece, pieces, random, boundingBox->x1 + 1, boundingBox->y0, boundingBox->z0, Direction::EAST, depth);
779 break;
780 }
781
782}
783
784bool MineShaftPieces::MineShaftStairs::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
785{
786
787 if (edgesLiquid(level, chunkBB))
788 {
789 return false;
790 }
791
792 // upper floor
793 generateBox(level, chunkBB, 0, 5, 0, (DEFAULT_SHAFT_WIDTH - 1), 5 + (DEFAULT_SHAFT_HEIGHT - 1), 1, 0, 0, false);
794 // lower floor
795 generateBox(level, chunkBB, 0, 0, 7, (DEFAULT_SHAFT_WIDTH - 1), (DEFAULT_SHAFT_HEIGHT - 1), 8, 0, 0, false);
796 // stairs
797 for (int i = 0; i < 5; i++)
798 {
799 generateBox(level, chunkBB, 0, 5 - i - ((i < 4) ? 1 : 0), 2 + i, (DEFAULT_SHAFT_WIDTH - 1), 5 + (DEFAULT_SHAFT_HEIGHT - 1) - i, 2 + i, 0, 0, false);
800 }
801
802 return true;
803}