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.h"
3#include "net.minecraft.world.level.h"
4#include "net.minecraft.world.level.storage.h"
5#include "net.minecraft.world.level.tile.h"
6#include "net.minecraft.world.level.levelgen.h"
7#include "net.minecraft.world.level.levelgen.structure.h"
8#include "net.minecraft.world.item.h"
9#include "net.minecraft.world.level.dimension.h"
10#include "net.minecraft.world.entity.npc.h"
11#include "WeighedTreasure.h"
12#include "VillagePieces.h"
13#include "VillageFeature.h"
14#include "Direction.h"
15#include "JavaMath.h"
16#include "BiomeSource.h"
17
18WeighedTreasureArray VillagePieces::Smithy::treasureItems;
19
20void VillagePieces::loadStatic()
21{
22 StructureFeatureIO::setPieceId(eStructurePiece_BookHouse, BookHouse::Create, L"ViBH");
23 StructureFeatureIO::setPieceId(eStructurePiece_DoubleFarmland, DoubleFarmland::Create, L"ViDF");
24 StructureFeatureIO::setPieceId(eStructurePiece_Farmland, Farmland::Create, L"ViF");
25 StructureFeatureIO::setPieceId(eStructurePiece_LightPost, LightPost::Create, L"ViL");
26 StructureFeatureIO::setPieceId(eStructurePiece_PigHouse, PigHouse::Create, L"ViPH");
27 StructureFeatureIO::setPieceId(eStructurePiece_SimpleHouse, SimpleHouse::Create, L"ViSH");
28 StructureFeatureIO::setPieceId(eStructurePiece_SmallHut, SmallHut::Create, L"ViSmH");
29 StructureFeatureIO::setPieceId(eStructurePiece_SmallTemple, SmallTemple::Create, L"ViST");
30 StructureFeatureIO::setPieceId(eStructurePiece_Smithy, Smithy::Create, L"ViS");
31 StructureFeatureIO::setPieceId(eStructurePiece_VillageStartPiece, StartPiece::Create, L"ViStart");
32 StructureFeatureIO::setPieceId(eStructurePiece_StraightRoad, StraightRoad::Create, L"ViSR");
33 StructureFeatureIO::setPieceId(eStructurePiece_TwoRoomHouse, TwoRoomHouse::Create, L"ViTRH");
34 StructureFeatureIO::setPieceId(eStructurePiece_Well, Well::Create, L"ViW");
35}
36
37VillagePieces::PieceWeight::PieceWeight(VillagePieces::EPieceClass pieceClass, int weight, int maxPlaceCount) : weight(weight)
38{
39 this->placeCount = 0; // 4J added initialiser
40 this->pieceClass = pieceClass;
41 this->maxPlaceCount = maxPlaceCount;
42}
43
44bool VillagePieces::PieceWeight::doPlace(int depth)
45{
46 return maxPlaceCount == 0 || placeCount < maxPlaceCount;
47}
48
49bool VillagePieces::PieceWeight::isValid()
50{
51 return maxPlaceCount == 0 || placeCount < maxPlaceCount;
52}
53
54list<VillagePieces::PieceWeight *> *VillagePieces::createPieceSet(Random *random, int villageSize)
55{
56 list<PieceWeight *> *newPieces = new list<PieceWeight *>;
57
58 newPieces->push_back(new PieceWeight(VillagePieces::EPieceClass_SimpleHouse, 4, Mth::nextInt(random, 2 + villageSize, 4 + villageSize * 2)));
59 newPieces->push_back(new PieceWeight(VillagePieces::EPieceClass_SmallTemple, 20, Mth::nextInt(random, 0 + villageSize, 1 + villageSize)));
60 newPieces->push_back(new PieceWeight(VillagePieces::EPieceClass_BookHouse, 20, Mth::nextInt(random, 0 + villageSize, 2 + villageSize)));
61 newPieces->push_back(new PieceWeight(VillagePieces::EPieceClass_SmallHut, 3, Mth::nextInt(random, 2 + villageSize, 5 + villageSize * 3)));
62 newPieces->push_back(new PieceWeight(VillagePieces::EPieceClass_PigHouse, 15, Mth::nextInt(random, 0 + villageSize, 2 + villageSize)));
63 newPieces->push_back(new PieceWeight(VillagePieces::EPieceClass_DoubleFarmland, 3, Mth::nextInt(random, 1 + villageSize, 4 + villageSize)));
64 newPieces->push_back(new PieceWeight(VillagePieces::EPieceClass_Farmland, 3, Mth::nextInt(random, 2 + villageSize, 4 + villageSize * 2)));
65 newPieces->push_back(new PieceWeight(VillagePieces::EPieceClass_Smithy, 15, Mth::nextInt(random, 0, 1 + villageSize)));
66 newPieces->push_back(new PieceWeight(VillagePieces::EPieceClass_TwoRoomHouse, 8, Mth::nextInt(random, 0 + villageSize, 3 + villageSize * 2)));
67
68 // silly way of filtering "infinite" buildings
69 AUTO_VAR(it, newPieces->begin());
70 while( it != newPieces->end() )
71 {
72 if( (*it)->maxPlaceCount == 0 )
73 {
74 delete (*it);
75 it = newPieces->erase(it);
76 }
77 else
78 {
79 it++;
80 }
81 }
82
83 return newPieces;
84}
85
86int VillagePieces::updatePieceWeight(list<PieceWeight *> *currentPieces)
87{
88 bool hasAnyPieces = false;
89 int totalWeight = 0;
90 for( AUTO_VAR(it, currentPieces->begin()); it != currentPieces->end(); it++ )
91 {
92 PieceWeight *piece = *it;
93 if (piece->maxPlaceCount > 0 && piece->placeCount < piece->maxPlaceCount)
94 {
95 hasAnyPieces = true;
96 }
97 totalWeight += piece->weight;
98 }
99 return (hasAnyPieces ? totalWeight : -1);
100}
101
102VillagePieces::VillagePiece *VillagePieces::findAndCreatePieceFactory(StartPiece *startPiece, VillagePieces::PieceWeight *piece, list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int depth)
103{
104 VillagePieces::EPieceClass pieceClass = piece->pieceClass;
105 VillagePiece *villagePiece = NULL;
106
107 if (pieceClass == VillagePieces::EPieceClass_SimpleHouse)
108 {
109 villagePiece = SimpleHouse::createPiece(startPiece, pieces, random, footX, footY, footZ, direction, depth);
110 }
111 else if (pieceClass == VillagePieces::EPieceClass_SmallTemple)
112 {
113 villagePiece = SmallTemple::createPiece(startPiece, pieces, random, footX, footY, footZ, direction, depth);
114 }
115 else if (pieceClass == VillagePieces::EPieceClass_BookHouse)
116 {
117 villagePiece = BookHouse::createPiece(startPiece, pieces, random, footX, footY, footZ, direction, depth);
118 }
119 else if (pieceClass == VillagePieces::EPieceClass_SmallHut)
120 {
121 villagePiece = SmallHut::createPiece(startPiece, pieces, random, footX, footY, footZ, direction, depth);
122 }
123 else if (pieceClass == VillagePieces::EPieceClass_PigHouse)
124 {
125 villagePiece = PigHouse::createPiece(startPiece, pieces, random, footX, footY, footZ, direction, depth);
126 }
127 else if (pieceClass == VillagePieces::EPieceClass_DoubleFarmland)
128 {
129 villagePiece = DoubleFarmland::createPiece(startPiece, pieces, random, footX, footY, footZ, direction, depth);
130 }
131 else if (pieceClass == VillagePieces::EPieceClass_Farmland)
132 {
133 villagePiece = Farmland::createPiece(startPiece, pieces, random, footX, footY, footZ, direction, depth);
134 }
135 else if (pieceClass == VillagePieces::EPieceClass_Smithy)
136 {
137 villagePiece = Smithy::createPiece(startPiece, pieces, random, footX, footY, footZ, direction, depth);
138 }
139 else if (pieceClass == VillagePieces::EPieceClass_TwoRoomHouse)
140 {
141 villagePiece = TwoRoomHouse::createPiece(startPiece, pieces, random, footX, footY, footZ, direction, depth);
142 }
143
144 return villagePiece;
145}
146
147VillagePieces::VillagePiece *VillagePieces::generatePieceFromSmallDoor(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int depth)
148{
149 int totalWeight = updatePieceWeight(startPiece->pieceSet);
150 if (totalWeight <= 0)
151 {
152 return NULL;
153 }
154
155 int numAttempts = 0;
156 while (numAttempts < 5)
157 {
158 numAttempts++;
159
160 int weightSelection = random->nextInt(totalWeight);
161 for( AUTO_VAR(it, startPiece->pieceSet->begin()); it != startPiece->pieceSet->end(); it++ )
162 {
163 PieceWeight *piece = *it;
164 weightSelection -= piece->weight;
165 if (weightSelection < 0)
166 {
167
168 if (!piece->doPlace(depth) || (piece == startPiece->previousPiece && startPiece->pieceSet->size() > 1))
169 {
170 break;
171 }
172
173 VillagePiece *villagePiece = findAndCreatePieceFactory(startPiece, piece, pieces, random, footX, footY, footZ, direction, depth);
174 if (villagePiece != NULL)
175 {
176 piece->placeCount++;
177 startPiece->previousPiece = piece;
178
179 if (!piece->isValid())
180 {
181 startPiece->pieceSet->remove(piece);
182 }
183 return villagePiece;
184 }
185 }
186 }
187 }
188
189 // attempt to place a light post instead
190 {
191 BoundingBox *box = LightPost::findPieceBox(startPiece, pieces, random, footX, footY, footZ, direction);
192 if (box != NULL)
193 {
194 return new LightPost(startPiece, depth, random, box, direction);
195 }
196 delete box;
197 }
198
199 return NULL;
200}
201
202StructurePiece *VillagePieces::generateAndAddPiece(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int depth)
203{
204 if (depth > MAX_DEPTH)
205 {
206 return NULL;
207 }
208 if (abs(footX - startPiece->getBoundingBox()->x0) > 7 * 16 || abs(footZ - startPiece->getBoundingBox()->z0) > 7 * 16)
209 {
210 return NULL;
211 }
212
213 StructurePiece *newPiece = generatePieceFromSmallDoor(startPiece, pieces, random, footX, footY, footZ, direction, depth + 1);
214 if (newPiece != NULL)
215 {
216 int x = (newPiece->boundingBox->x0 + newPiece->boundingBox->x1) / 2;
217 int z = (newPiece->boundingBox->z0 + newPiece->boundingBox->z1) / 2;
218 int xs = newPiece->boundingBox->x1 - newPiece->boundingBox->x0;
219 int zs = newPiece->boundingBox->z1 - newPiece->boundingBox->z0;
220 int r = xs > zs ? xs : zs;
221 if (startPiece->getBiomeSource()->containsOnly(x, z, r / 2 + 4, VillageFeature::allowedBiomes))
222 {
223 pieces->push_back(newPiece);
224 startPiece->pendingHouses.push_back(newPiece);
225 return newPiece;
226 }
227 delete newPiece;
228 }
229 return NULL;
230}
231
232StructurePiece *VillagePieces::generateAndAddRoadPiece(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int depth)
233{
234 if (depth > BASE_ROAD_DEPTH + startPiece->villageSize)
235 {
236 return NULL;
237 }
238 if (abs(footX - startPiece->getBoundingBox()->x0) > 7 * 16 || abs(footZ - startPiece->getBoundingBox()->z0) > 7 * 16)
239 {
240 return NULL;
241 }
242
243 BoundingBox *box = StraightRoad::findPieceBox(startPiece, pieces, random, footX, footY, footZ, direction);
244 if (box != NULL && box->y0 > LOWEST_Y_POSITION)
245 {
246 StructurePiece *newPiece = new StraightRoad(startPiece, depth, random, box, direction);
247 int x = (newPiece->boundingBox->x0 + newPiece->boundingBox->x1) / 2;
248 int z = (newPiece->boundingBox->z0 + newPiece->boundingBox->z1) / 2;
249 int xs = newPiece->boundingBox->x1 - newPiece->boundingBox->x0;
250 int zs = newPiece->boundingBox->z1 - newPiece->boundingBox->z0;
251 int r = xs > zs ? xs : zs;
252 if (startPiece->getBiomeSource()->containsOnly(x, z, r / 2 + 4, VillageFeature::allowedBiomes))
253 {
254 pieces->push_back(newPiece);
255 startPiece->pendingRoads.push_back(newPiece);
256 return newPiece;
257 }
258 // 4J Stu - The dtor for newPiece will destroy box
259 delete newPiece;
260 }
261 else if(box != NULL)
262 {
263 delete box;
264 }
265
266 return NULL;
267}
268
269VillagePieces::VillagePiece::VillagePiece()
270{
271 heightPosition = -1;
272 spawnedVillagerCount = 0;
273 isDesertVillage = false;
274 startPiece = NULL;
275 // for reflection
276}
277
278VillagePieces::VillagePiece::VillagePiece(StartPiece *startPiece, int genDepth) : StructurePiece(genDepth)
279{
280 heightPosition = -1;
281 isDesertVillage = false;
282 spawnedVillagerCount = 0;
283 this->startPiece = startPiece;
284 if (startPiece != NULL)
285 {
286 this->isDesertVillage = startPiece->isDesertVillage;
287 }
288}
289
290void VillagePieces::VillagePiece::addAdditonalSaveData(CompoundTag *tag)
291{
292 tag->putInt(L"HPos", heightPosition);
293 tag->putInt(L"VCount", spawnedVillagerCount);
294 tag->putBoolean(L"Desert", isDesertVillage);
295}
296
297void VillagePieces::VillagePiece::readAdditonalSaveData(CompoundTag *tag)
298{
299 heightPosition = tag->getInt(L"HPos");
300 spawnedVillagerCount = tag->getInt(L"VCount");
301 isDesertVillage = tag->getBoolean(L"Desert");
302}
303
304StructurePiece *VillagePieces::VillagePiece::generateHouseNorthernLeft(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int yOff, int zOff)
305{
306 switch (orientation)
307 {
308 case Direction::NORTH:
309 return generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 - 1, boundingBox->y0 + yOff, boundingBox->z0 + zOff, Direction::WEST, getGenDepth());
310 case Direction::SOUTH:
311 return generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 - 1, boundingBox->y0 + yOff, boundingBox->z0 + zOff, Direction::WEST, getGenDepth());
312 case Direction::WEST:
313 return generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 + zOff, boundingBox->y0 + yOff, boundingBox->z0 - 1, Direction::NORTH, getGenDepth());
314 case Direction::EAST:
315 return generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 + zOff, boundingBox->y0 + yOff, boundingBox->z0 - 1, Direction::NORTH, getGenDepth());
316 }
317 return NULL;
318}
319
320StructurePiece *VillagePieces::VillagePiece::generateHouseNorthernRight(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int yOff, int zOff)
321{
322 switch (orientation)
323 {
324 case Direction::NORTH:
325 return generateAndAddPiece(startPiece, pieces, random, boundingBox->x1 + 1, boundingBox->y0 + yOff, boundingBox->z0 + zOff, Direction::EAST, getGenDepth());
326 case Direction::SOUTH:
327 return generateAndAddPiece(startPiece, pieces, random, boundingBox->x1 + 1, boundingBox->y0 + yOff, boundingBox->z0 + zOff, Direction::EAST, getGenDepth());
328 case Direction::WEST:
329 return generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 + zOff, boundingBox->y0 + yOff, boundingBox->z1 + 1, Direction::SOUTH, getGenDepth());
330 case Direction::EAST:
331 return generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 + zOff, boundingBox->y0 + yOff, boundingBox->z1 + 1, Direction::SOUTH, getGenDepth());
332 }
333 return NULL;
334}
335
336int VillagePieces::VillagePiece::getAverageGroundHeight(Level *level, BoundingBox *chunkBB)
337{
338 int total = 0;
339 int count = 0;
340 for (int z = boundingBox->z0; z <= boundingBox->z1; z++)
341 {
342 for (int x = boundingBox->x0; x <= boundingBox->x1; x++)
343 {
344 if (chunkBB->isInside(x, 64, z))
345 {
346 total += Math::_max(level->getTopSolidBlock(x, z), level->dimension->getSpawnYPosition());
347 count++;
348 }
349 }
350 }
351
352 if (count == 0)
353 {
354 return -1;
355 }
356 return total / count;
357}
358
359bool VillagePieces::VillagePiece::isOkBox(BoundingBox *box, StartPiece *startRoom)
360{
361 bool bIsOk = false;
362
363 if(box != NULL)
364 {
365 if( box->y0 > LOWEST_Y_POSITION ) bIsOk = true;
366
367 int xzSize = startRoom->m_level->getLevelData()->getXZSize();
368 int blockMin = -( (xzSize << 4) / 2) + 1;
369 int blockMax = ( (xzSize << 4) / 2 ) - 1;
370
371 if(box->x0 <= blockMin) bIsOk = false;
372 if(box->z0 <= blockMin) bIsOk = false;
373 if(box->x1 >= blockMax) bIsOk = false;
374 if(box->z1 >= blockMax) bIsOk = false;
375 }
376
377 return bIsOk;
378}
379
380void VillagePieces::VillagePiece::spawnVillagers(Level *level, BoundingBox *chunkBB, int x, int y, int z, int count)
381{
382 if (spawnedVillagerCount >= count)
383 {
384 return;
385 }
386
387 for (int i = spawnedVillagerCount; i < count; i++)
388 {
389 int worldX = getWorldX(x + i, z);
390 int worldY = getWorldY(y);
391 int worldZ = getWorldZ(x + i, z);
392
393 if (chunkBB->isInside(worldX, worldY, worldZ))
394 {
395 spawnedVillagerCount++;
396
397 shared_ptr<Villager> villager = shared_ptr<Villager>(new Villager(level, getVillagerProfession(i)));
398 villager->moveTo(worldX + 0.5, worldY, worldZ + 0.5, 0, 0);
399 level->addEntity(villager);
400 }
401 else
402 {
403 // try again later
404 break;
405 }
406 }
407}
408
409int VillagePieces::VillagePiece::getVillagerProfession(int villagerNumber)
410{
411 return Villager::PROFESSION_FARMER;
412}
413
414int VillagePieces::VillagePiece::biomeBlock(int tile, int data)
415{
416 if (isDesertVillage)
417 {
418 if (tile == Tile::treeTrunk_Id)
419 {
420 return Tile::sandStone_Id;
421 }
422 else if (tile == Tile::cobblestone_Id)
423 {
424 return Tile::sandStone_Id;
425 }
426 else if (tile == Tile::wood_Id)
427 {
428 return Tile::sandStone_Id;
429 }
430 else if (tile == Tile::stairs_wood_Id)
431 {
432 return Tile::stairs_sandstone_Id;
433 }
434 else if (tile == Tile::stairs_stone_Id)
435 {
436 return Tile::stairs_sandstone_Id;
437 }
438 else if (tile == Tile::gravel_Id)
439 {
440 return Tile::sandStone_Id;
441 }
442 }
443 return tile;
444}
445
446int VillagePieces::VillagePiece::biomeData(int tile, int data)
447{
448 if (isDesertVillage)
449 {
450 if (tile == Tile::treeTrunk_Id)
451 {
452 return 0;
453 }
454 else if (tile == Tile::cobblestone_Id)
455 {
456 return SandStoneTile::TYPE_DEFAULT;
457 }
458 else if (tile == Tile::wood_Id)
459 {
460 return SandStoneTile::TYPE_SMOOTHSIDE;
461 }
462 }
463 return data;
464}
465
466void VillagePieces::VillagePiece::placeBlock(Level *level, int block, int data, int x, int y, int z, BoundingBox *chunkBB)
467{
468 int bblock = biomeBlock(block, data);
469 int bdata = biomeData(block, data);
470 StructurePiece::placeBlock(level, bblock, bdata, x, y, z, chunkBB);
471}
472
473void VillagePieces::VillagePiece::generateBox(Level *level, BoundingBox *chunkBB, int x0, int y0, int z0, int x1, int y1, int z1, int edgeTile, int fillTile, bool skipAir)
474{
475 int bEdge = biomeBlock(edgeTile, 0);
476 int bEdgeData = biomeData(edgeTile, 0);
477 int bFill = biomeBlock(fillTile, 0);
478 int bFillData = biomeData(fillTile, 0);
479 StructurePiece::generateBox(level, chunkBB, x0, y0, z0, x1, y1, z1, bEdge, bEdgeData, bFill, bFillData, skipAir);
480}
481
482void VillagePieces::VillagePiece::fillColumnDown(Level *level, int block, int data, int x, int startY, int z, BoundingBox *chunkBB)
483{
484 int bblock = biomeBlock(block, data);
485 int bdata = biomeData(block, data);
486 StructurePiece::fillColumnDown(level, bblock, bdata, x, startY, z, chunkBB);
487}
488
489VillagePieces::Well::Well()
490{
491 // for reflection
492}
493
494VillagePieces::Well::Well(StartPiece *startPiece, int genDepth, Random *random, int west, int north) : VillagePiece(startPiece, genDepth)
495{
496 orientation = random->nextInt(4);
497
498 switch (orientation)
499 {
500 case Direction::NORTH:
501 case Direction::SOUTH:
502 boundingBox = new BoundingBox(west, 64, north, west + width - 1, 64 + height - 1, north + depth - 1);
503 break;
504 default:
505 boundingBox = new BoundingBox(west, 64, north, west + depth - 1, 64 + height - 1, north + width - 1);
506 break;
507 }
508}
509
510VillagePieces::Well::Well(StartPiece *startPiece, int genDepth, Random *random, BoundingBox *stairsBox, int direction) : VillagePiece(startPiece, genDepth)
511{
512 orientation = direction;
513 boundingBox = stairsBox;
514}
515
516void VillagePieces::Well::addChildren(StructurePiece *startPiece, list<StructurePiece *> *pieces, Random *random)
517{
518 generateAndAddRoadPiece((StartPiece *) startPiece, pieces, random, boundingBox->x0 - 1, boundingBox->y1 - 4, boundingBox->z0 + 1, Direction::WEST, getGenDepth());
519 generateAndAddRoadPiece((StartPiece *) startPiece, pieces, random, boundingBox->x1 + 1, boundingBox->y1 - 4, boundingBox->z0 + 1, Direction::EAST, getGenDepth());
520 generateAndAddRoadPiece((StartPiece *) startPiece, pieces, random, boundingBox->x0 + 1, boundingBox->y1 - 4, boundingBox->z0 - 1, Direction::NORTH, getGenDepth());
521 generateAndAddRoadPiece((StartPiece *) startPiece, pieces, random, boundingBox->x0 + 1, boundingBox->y1 - 4, boundingBox->z1 + 1, Direction::SOUTH, getGenDepth());
522}
523
524bool VillagePieces::Well::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
525{
526 if (heightPosition < 0)
527 {
528 heightPosition = getAverageGroundHeight(level, chunkBB);
529 if (heightPosition < 0)
530 {
531 return true;
532 }
533 boundingBox->move(0, heightPosition - boundingBox->y1 + 3, 0);
534 }
535
536 generateBox(level, chunkBB, 1, 0, 1, 4, height - 3, 4, Tile::cobblestone_Id, Tile::water_Id, false);
537 placeBlock(level, 0, 0, 2, height - 3, 2, chunkBB);
538 placeBlock(level, 0, 0, 3, height - 3, 2, chunkBB);
539 placeBlock(level, 0, 0, 2, height - 3, 3, chunkBB);
540 placeBlock(level, 0, 0, 3, height - 3, 3, chunkBB);
541
542 placeBlock(level, Tile::fence_Id, 0, 1, height - 2, 1, chunkBB);
543 placeBlock(level, Tile::fence_Id, 0, 1, height - 1, 1, chunkBB);
544 placeBlock(level, Tile::fence_Id, 0, 4, height - 2, 1, chunkBB);
545 placeBlock(level, Tile::fence_Id, 0, 4, height - 1, 1, chunkBB);
546 placeBlock(level, Tile::fence_Id, 0, 1, height - 2, 4, chunkBB);
547 placeBlock(level, Tile::fence_Id, 0, 1, height - 1, 4, chunkBB);
548 placeBlock(level, Tile::fence_Id, 0, 4, height - 2, 4, chunkBB);
549 placeBlock(level, Tile::fence_Id, 0, 4, height - 1, 4, chunkBB);
550 generateBox(level, chunkBB, 1, height, 1, 4, height, 4, Tile::cobblestone_Id, Tile::cobblestone_Id, false);
551
552 for (int z = 0; z <= 5; z++)
553 {
554 for (int x = 0; x <= 5; x++)
555 {
556 // only do the frame
557 if (x != 0 && x != 5 && z != 0 && z != 5)
558 {
559 continue;
560 }
561 placeBlock(level, Tile::gravel_Id, 0, x, height - 4, z, chunkBB);
562 generateAirColumnUp(level, x, height - 3, z, chunkBB);
563 }
564 }
565
566 return true;
567
568}
569
570VillagePieces::StartPiece::StartPiece()
571{
572 // for reflection
573}
574
575VillagePieces::StartPiece::StartPiece(BiomeSource *biomeSource, int genDepth, Random *random, int west, int north, list<PieceWeight *> *pieceSet, int villageSize, Level *level) : Well(NULL, 0, random, west, north)
576{
577 isLibraryAdded = false; // 4J - added initialiser
578 previousPiece = NULL; // 4J - added initialiser
579 this->biomeSource = biomeSource;
580 this->pieceSet = pieceSet;
581 this->villageSize = villageSize;
582 m_level = level;
583
584 Biome *biome = biomeSource->getBiome(west, north);
585 isDesertVillage = biome == Biome::desert || biome == Biome::desertHills;
586}
587
588VillagePieces::StartPiece::~StartPiece()
589{
590 for(AUTO_VAR(it, pieceSet->begin()); it != pieceSet->end(); it++ )
591 {
592 delete (*it);
593 }
594 delete pieceSet;
595}
596
597BiomeSource *VillagePieces::StartPiece::getBiomeSource()
598{
599 return biomeSource;
600}
601
602VillagePieces::StraightRoad::StraightRoad()
603{
604 // for reflection
605}
606
607VillagePieces::StraightRoad::StraightRoad(StartPiece *startPiece, int genDepth, Random *random, BoundingBox *stairsBox, int direction) : VillageRoadPiece(startPiece, genDepth)
608{
609 orientation = direction;
610 boundingBox = stairsBox;
611 length = Math::_max(stairsBox->getXSpan(), stairsBox->getZSpan());
612}
613
614void VillagePieces::StraightRoad::addAdditonalSaveData(CompoundTag *tag)
615{
616 VillageRoadPiece::addAdditonalSaveData(tag);
617 tag->putInt(L"Length", length);
618}
619
620void VillagePieces::StraightRoad::readAdditonalSaveData(CompoundTag *tag)
621{
622 VillageRoadPiece::readAdditonalSaveData(tag);
623 length = tag->getInt(L"Length");
624}
625
626void VillagePieces::StraightRoad::addChildren(StructurePiece *startPiece, list<StructurePiece *> *pieces, Random *random)
627{
628 bool hasHouses = false;
629
630 // place left houses
631 int depth = random->nextInt(5);
632 while (depth < length - 8)
633 {
634 StructurePiece *piece = generateHouseNorthernLeft((StartPiece *) startPiece, pieces, random, 0, depth);
635 if (piece != NULL)
636 {
637 depth += Math::_max(piece->boundingBox->getXSpan(), piece->boundingBox->getZSpan());
638 hasHouses = true;
639 }
640 depth += 2 + random->nextInt(5);
641 }
642
643 // place right houses
644 depth = random->nextInt(5);
645 while (depth < length - 8)
646 {
647 StructurePiece *piece = generateHouseNorthernRight((StartPiece *) startPiece, pieces, random, 0, depth);
648 if (piece != NULL)
649 {
650 depth += Math::_max(piece->boundingBox->getXSpan(), piece->boundingBox->getZSpan());
651 hasHouses = true;
652 }
653 depth += 2 + random->nextInt(5);
654 }
655
656 if (hasHouses && random->nextInt(3) > 0)
657 {
658 switch (orientation)
659 {
660 case Direction::NORTH:
661 generateAndAddRoadPiece((StartPiece *) startPiece, pieces, random, boundingBox->x0 - 1, boundingBox->y0, boundingBox->z0, Direction::WEST, getGenDepth());
662 break;
663 case Direction::SOUTH:
664 generateAndAddRoadPiece((StartPiece *) startPiece, pieces, random, boundingBox->x0 - 1, boundingBox->y0, boundingBox->z1 - 2, Direction::WEST, getGenDepth());
665 break;
666 case Direction::EAST:
667 generateAndAddRoadPiece((StartPiece *) startPiece, pieces, random, boundingBox->x1 - 2, boundingBox->y0, boundingBox->z0 - 1, Direction::NORTH, getGenDepth());
668 break;
669 case Direction::WEST:
670 generateAndAddRoadPiece((StartPiece *) startPiece, pieces, random, boundingBox->x0, boundingBox->y0, boundingBox->z0 - 1, Direction::NORTH, getGenDepth());
671 break;
672 }
673 }
674 if (hasHouses && random->nextInt(3) > 0)
675 {
676 switch (orientation)
677 {
678 case Direction::NORTH:
679 generateAndAddRoadPiece((StartPiece *) startPiece, pieces, random, boundingBox->x1 + 1, boundingBox->y0, boundingBox->z0, Direction::EAST, getGenDepth());
680 break;
681 case Direction::SOUTH:
682 generateAndAddRoadPiece((StartPiece *) startPiece, pieces, random, boundingBox->x1 + 1, boundingBox->y0, boundingBox->z1 - 2, Direction::EAST, getGenDepth());
683 break;
684 case Direction::EAST:
685 generateAndAddRoadPiece((StartPiece *) startPiece, pieces, random, boundingBox->x1 - 2, boundingBox->y0, boundingBox->z1 + 1, Direction::SOUTH, getGenDepth());
686 break;
687 case Direction::WEST:
688 generateAndAddRoadPiece((StartPiece *) startPiece, pieces, random, boundingBox->x0, boundingBox->y0, boundingBox->z1 + 1, Direction::SOUTH, getGenDepth());
689 break;
690 }
691 }
692}
693
694BoundingBox *VillagePieces::StraightRoad::findPieceBox(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction)
695{
696 int length = 7 * (Mth::nextInt(random, 3, 5));
697
698 while (length >= 7)
699 {
700 BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, 0, 0, 0, width, 3, length, direction);
701
702 if (isOkBox(box, startPiece) && StructurePiece::findCollisionPiece(pieces, box) == NULL)
703 {
704 return box;
705 }
706 delete box;
707 length -= 7;
708 }
709
710 return NULL;
711}
712
713bool VillagePieces::StraightRoad::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
714{
715 int tile = biomeBlock(Tile::gravel_Id, 0);
716 for (int x = boundingBox->x0; x <= boundingBox->x1; x++)
717 {
718 for (int z = boundingBox->z0; z <= boundingBox->z1; z++)
719 {
720 if (chunkBB->isInside(x, 64, z))
721 {
722 int y = level->getTopSolidBlock(x, z) - 1;
723 level->setTileAndData(x, y, z,tile, 0, Tile::UPDATE_CLIENTS);
724 }
725 }
726 }
727
728 return true;
729}
730
731VillagePieces::SimpleHouse::SimpleHouse()
732{
733 hasTerrace = false;
734 // for reflection
735}
736
737VillagePieces::SimpleHouse::SimpleHouse(StartPiece *startPiece, int genDepth, Random *random, BoundingBox *stairsBox, int direction) : VillagePiece(startPiece, genDepth), hasTerrace(random->nextBoolean())
738{
739 orientation = direction;
740 boundingBox = stairsBox;
741}
742
743void VillagePieces::SimpleHouse::addAdditonalSaveData(CompoundTag *tag)
744{
745 VillagePiece::addAdditonalSaveData(tag);
746 tag->putBoolean(L"Terrace", hasTerrace);
747}
748
749void VillagePieces::SimpleHouse::readAdditonalSaveData(CompoundTag *tag)
750{
751 VillagePiece::readAdditonalSaveData(tag);
752 hasTerrace = tag->getBoolean(L"Terrace");
753}
754
755VillagePieces::SimpleHouse *VillagePieces::SimpleHouse::createPiece(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth)
756{
757 BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, 0, 0, 0, width, height, depth, direction);
758
759 if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL)
760 {
761 delete box;
762 return NULL;
763 }
764
765 return new SimpleHouse(startPiece, genDepth, random, box, direction);
766}
767
768bool VillagePieces::SimpleHouse::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
769{
770 if (heightPosition < 0)
771 {
772 heightPosition = getAverageGroundHeight(level, chunkBB);
773 if (heightPosition < 0)
774 {
775 return true;
776 }
777 boundingBox->move(0, heightPosition - boundingBox->y1 + height - 1, 0);
778 }
779
780 // floor
781 generateBox(level, chunkBB, 0, 0, 0, 4, 0, 4, Tile::cobblestone_Id, Tile::cobblestone_Id, false);
782 // roof
783 generateBox(level, chunkBB, 0, 4, 0, 4, 4, 4, Tile::treeTrunk_Id, Tile::treeTrunk_Id, false);
784 generateBox(level, chunkBB, 1, 4, 1, 3, 4, 3, Tile::wood_Id, Tile::wood_Id, false);
785
786 // window walls
787 placeBlock(level, Tile::cobblestone_Id, 0, 0, 1, 0, chunkBB);
788 placeBlock(level, Tile::cobblestone_Id, 0, 0, 2, 0, chunkBB);
789 placeBlock(level, Tile::cobblestone_Id, 0, 0, 3, 0, chunkBB);
790 placeBlock(level, Tile::cobblestone_Id, 0, 4, 1, 0, chunkBB);
791 placeBlock(level, Tile::cobblestone_Id, 0, 4, 2, 0, chunkBB);
792 placeBlock(level, Tile::cobblestone_Id, 0, 4, 3, 0, chunkBB);
793 placeBlock(level, Tile::cobblestone_Id, 0, 0, 1, 4, chunkBB);
794 placeBlock(level, Tile::cobblestone_Id, 0, 0, 2, 4, chunkBB);
795 placeBlock(level, Tile::cobblestone_Id, 0, 0, 3, 4, chunkBB);
796 placeBlock(level, Tile::cobblestone_Id, 0, 4, 1, 4, chunkBB);
797 placeBlock(level, Tile::cobblestone_Id, 0, 4, 2, 4, chunkBB);
798 placeBlock(level, Tile::cobblestone_Id, 0, 4, 3, 4, chunkBB);
799 generateBox(level, chunkBB, 0, 1, 1, 0, 3, 3, Tile::wood_Id, Tile::wood_Id, false);
800 generateBox(level, chunkBB, 4, 1, 1, 4, 3, 3, Tile::wood_Id, Tile::wood_Id, false);
801 generateBox(level, chunkBB, 1, 1, 4, 3, 3, 4, Tile::wood_Id, Tile::wood_Id, false);
802 placeBlock(level, Tile::thinGlass_Id, 0, 0, 2, 2, chunkBB);
803 placeBlock(level, Tile::thinGlass_Id, 0, 2, 2, 4, chunkBB);
804 placeBlock(level, Tile::thinGlass_Id, 0, 4, 2, 2, chunkBB);
805
806 // door wall
807 placeBlock(level, Tile::wood_Id, 0, 1, 1, 0, chunkBB);
808 placeBlock(level, Tile::wood_Id, 0, 1, 2, 0, chunkBB);
809 placeBlock(level, Tile::wood_Id, 0, 1, 3, 0, chunkBB);
810 placeBlock(level, Tile::wood_Id, 0, 2, 3, 0, chunkBB);
811 placeBlock(level, Tile::wood_Id, 0, 3, 3, 0, chunkBB);
812 placeBlock(level, Tile::wood_Id, 0, 3, 2, 0, chunkBB);
813 placeBlock(level, Tile::wood_Id, 0, 3, 1, 0, chunkBB);
814 if (getBlock(level, 2, 0, -1, chunkBB) == 0 && getBlock(level, 2, -1, -1, chunkBB) != 0)
815 {
816 placeBlock(level, Tile::stairs_stone_Id, getOrientationData(Tile::stairs_stone_Id, 3), 2, 0, -1, chunkBB);
817 }
818
819 // fill room with air
820 generateBox(level, chunkBB, 1, 1, 1, 3, 3, 3, 0, 0, false);
821
822 // roof fence
823 if (hasTerrace) {
824 placeBlock(level, Tile::fence_Id, 0, 0, 5, 0, chunkBB);
825 placeBlock(level, Tile::fence_Id, 0, 1, 5, 0, chunkBB);
826 placeBlock(level, Tile::fence_Id, 0, 2, 5, 0, chunkBB);
827 placeBlock(level, Tile::fence_Id, 0, 3, 5, 0, chunkBB);
828 placeBlock(level, Tile::fence_Id, 0, 4, 5, 0, chunkBB);
829 placeBlock(level, Tile::fence_Id, 0, 0, 5, 4, chunkBB);
830 placeBlock(level, Tile::fence_Id, 0, 1, 5, 4, chunkBB);
831 placeBlock(level, Tile::fence_Id, 0, 2, 5, 4, chunkBB);
832 placeBlock(level, Tile::fence_Id, 0, 3, 5, 4, chunkBB);
833 placeBlock(level, Tile::fence_Id, 0, 4, 5, 4, chunkBB);
834 placeBlock(level, Tile::fence_Id, 0, 4, 5, 1, chunkBB);
835 placeBlock(level, Tile::fence_Id, 0, 4, 5, 2, chunkBB);
836 placeBlock(level, Tile::fence_Id, 0, 4, 5, 3, chunkBB);
837 placeBlock(level, Tile::fence_Id, 0, 0, 5, 1, chunkBB);
838 placeBlock(level, Tile::fence_Id, 0, 0, 5, 2, chunkBB);
839 placeBlock(level, Tile::fence_Id, 0, 0, 5, 3, chunkBB);
840 }
841
842 // ladder
843 if (hasTerrace)
844 {
845 int orientationData = getOrientationData(Tile::ladder_Id, 3);
846 placeBlock(level, Tile::ladder_Id, orientationData, 3, 1, 3, chunkBB);
847 placeBlock(level, Tile::ladder_Id, orientationData, 3, 2, 3, chunkBB);
848 placeBlock(level, Tile::ladder_Id, orientationData, 3, 3, 3, chunkBB);
849 placeBlock(level, Tile::ladder_Id, orientationData, 3, 4, 3, chunkBB);
850 }
851
852 // torch
853 placeBlock(level, Tile::torch_Id, 0, 2, 3, 1, chunkBB);
854
855 for (int z = 0; z < depth; z++)
856 {
857 for (int x = 0; x < width; x++)
858 {
859 generateAirColumnUp(level, x, height, z, chunkBB);
860 fillColumnDown(level, Tile::cobblestone_Id, 0, x, -1, z, chunkBB);
861 }
862 }
863
864 spawnVillagers(level, chunkBB, 1, 1, 2, 1);
865
866 return true;
867
868}
869
870VillagePieces::SmallTemple::SmallTemple()
871{
872 // for reflection
873}
874
875VillagePieces::SmallTemple::SmallTemple(StartPiece *startPiece, int genDepth, Random *random, BoundingBox *stairsBox, int direction) : VillagePiece(startPiece, genDepth)
876{
877 heightPosition = -1; // 4J added initialiser
878 orientation = direction;
879 boundingBox = stairsBox;
880}
881
882VillagePieces::SmallTemple *VillagePieces::SmallTemple::createPiece(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth)
883{
884 BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, 0, 0, 0, width, height, depth, direction);
885
886 if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL)
887 {
888 delete box;
889 return NULL;
890 }
891
892 return new SmallTemple(startPiece, genDepth, random, box, direction);
893}
894
895bool VillagePieces::SmallTemple::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
896{
897 if (heightPosition < 0)
898 {
899 heightPosition = getAverageGroundHeight(level, chunkBB);
900 if (heightPosition < 0)
901 {
902 return true;
903 }
904 boundingBox->move(0, heightPosition - boundingBox->y1 + height - 1, 0);
905 }
906
907 // fill inside with air
908 generateBox(level, chunkBB, 1, 1, 1, 3, 3, 7, 0, 0, false);
909 generateBox(level, chunkBB, 1, 5, 1, 3, 9, 3, 0, 0, false);
910
911 // floor
912 generateBox(level, chunkBB, 1, 0, 0, 3, 0, 8, Tile::cobblestone_Id, Tile::cobblestone_Id, false);
913
914 // front wall
915 generateBox(level, chunkBB, 1, 1, 0, 3, 10, 0, Tile::cobblestone_Id, Tile::cobblestone_Id, false);
916 // left tall wall
917 generateBox(level, chunkBB, 0, 1, 1, 0, 10, 3, Tile::cobblestone_Id, Tile::cobblestone_Id, false);
918 // right tall wall
919 generateBox(level, chunkBB, 4, 1, 1, 4, 10, 3, Tile::cobblestone_Id, Tile::cobblestone_Id, false);
920 // left low wall
921 generateBox(level, chunkBB, 0, 0, 4, 0, 4, 7, Tile::cobblestone_Id, Tile::cobblestone_Id, false);
922 // right low wall
923 generateBox(level, chunkBB, 4, 0, 4, 4, 4, 7, Tile::cobblestone_Id, Tile::cobblestone_Id, false);
924 // far low wall
925 generateBox(level, chunkBB, 1, 1, 8, 3, 4, 8, Tile::cobblestone_Id, Tile::cobblestone_Id, false);
926 // far upper wall
927 generateBox(level, chunkBB, 1, 5, 4, 3, 10, 4, Tile::cobblestone_Id, Tile::cobblestone_Id, false);
928
929 // low roof
930 generateBox(level, chunkBB, 1, 5, 5, 3, 5, 7, Tile::cobblestone_Id, Tile::cobblestone_Id, false);
931 // high roof
932 generateBox(level, chunkBB, 0, 9, 0, 4, 9, 4, Tile::cobblestone_Id, Tile::cobblestone_Id, false);
933 // middle floor / roof
934 generateBox(level, chunkBB, 0, 4, 0, 4, 4, 4, Tile::cobblestone_Id, Tile::cobblestone_Id, false);
935 placeBlock(level, Tile::cobblestone_Id, 0, 0, 11, 2, chunkBB);
936 placeBlock(level, Tile::cobblestone_Id, 0, 4, 11, 2, chunkBB);
937 placeBlock(level, Tile::cobblestone_Id, 0, 2, 11, 0, chunkBB);
938 placeBlock(level, Tile::cobblestone_Id, 0, 2, 11, 4, chunkBB);
939
940 // altar pieces
941 placeBlock(level, Tile::cobblestone_Id, 0, 1, 1, 6, chunkBB);
942 placeBlock(level, Tile::cobblestone_Id, 0, 1, 1, 7, chunkBB);
943 placeBlock(level, Tile::cobblestone_Id, 0, 2, 1, 7, chunkBB);
944 placeBlock(level, Tile::cobblestone_Id, 0, 3, 1, 6, chunkBB);
945 placeBlock(level, Tile::cobblestone_Id, 0, 3, 1, 7, chunkBB);
946 placeBlock(level, Tile::stairs_stone_Id, getOrientationData(Tile::stairs_stone_Id, 3), 1, 1, 5, chunkBB);
947 placeBlock(level, Tile::stairs_stone_Id, getOrientationData(Tile::stairs_stone_Id, 3), 2, 1, 6, chunkBB);
948 placeBlock(level, Tile::stairs_stone_Id, getOrientationData(Tile::stairs_stone_Id, 3), 3, 1, 5, chunkBB);
949 placeBlock(level, Tile::stairs_stone_Id, getOrientationData(Tile::stairs_stone_Id, 1), 1, 2, 7, chunkBB);
950 placeBlock(level, Tile::stairs_stone_Id, getOrientationData(Tile::stairs_stone_Id, 0), 3, 2, 7, chunkBB);
951
952 // windows
953 placeBlock(level, Tile::thinGlass_Id, 0, 0, 2, 2, chunkBB);
954 placeBlock(level, Tile::thinGlass_Id, 0, 0, 3, 2, chunkBB);
955 placeBlock(level, Tile::thinGlass_Id, 0, 4, 2, 2, chunkBB);
956 placeBlock(level, Tile::thinGlass_Id, 0, 4, 3, 2, chunkBB);
957 placeBlock(level, Tile::thinGlass_Id, 0, 0, 6, 2, chunkBB);
958 placeBlock(level, Tile::thinGlass_Id, 0, 0, 7, 2, chunkBB);
959 placeBlock(level, Tile::thinGlass_Id, 0, 4, 6, 2, chunkBB);
960 placeBlock(level, Tile::thinGlass_Id, 0, 4, 7, 2, chunkBB);
961 placeBlock(level, Tile::thinGlass_Id, 0, 2, 6, 0, chunkBB);
962 placeBlock(level, Tile::thinGlass_Id, 0, 2, 7, 0, chunkBB);
963 placeBlock(level, Tile::thinGlass_Id, 0, 2, 6, 4, chunkBB);
964 placeBlock(level, Tile::thinGlass_Id, 0, 2, 7, 4, chunkBB);
965 placeBlock(level, Tile::thinGlass_Id, 0, 0, 3, 6, chunkBB);
966 placeBlock(level, Tile::thinGlass_Id, 0, 4, 3, 6, chunkBB);
967 placeBlock(level, Tile::thinGlass_Id, 0, 2, 3, 8, chunkBB);
968
969 // torches
970 placeBlock(level, Tile::torch_Id, 0, 2, 4, 7, chunkBB);
971 placeBlock(level, Tile::torch_Id, 0, 1, 4, 6, chunkBB);
972 placeBlock(level, Tile::torch_Id, 0, 3, 4, 6, chunkBB);
973 placeBlock(level, Tile::torch_Id, 0, 2, 4, 5, chunkBB);
974
975 // ladder
976 int orientationData = getOrientationData(Tile::ladder_Id, 4);
977 for (int y = 1; y <= 9; y++)
978 {
979 placeBlock(level, Tile::ladder_Id, orientationData, 3, y, 3, chunkBB);
980 }
981
982 // entrance
983 placeBlock(level, 0, 0, 2, 1, 0, chunkBB);
984 placeBlock(level, 0, 0, 2, 2, 0, chunkBB);
985 createDoor(level, chunkBB, random, 2, 1, 0, getOrientationData(Tile::door_wood_Id, 1));
986 if (getBlock(level, 2, 0, -1, chunkBB) == 0 && getBlock(level, 2, -1, -1, chunkBB) != 0)
987 {
988 placeBlock(level, Tile::stairs_stone_Id, getOrientationData(Tile::stairs_stone_Id, 3), 2, 0, -1, chunkBB);
989 }
990
991
992 for (int z = 0; z < depth; z++)
993 {
994 for (int x = 0; x < width; x++)
995 {
996 generateAirColumnUp(level, x, height, z, chunkBB);
997 fillColumnDown(level, Tile::cobblestone_Id, 0, x, -1, z, chunkBB);
998 }
999 }
1000
1001 spawnVillagers(level, chunkBB, 2, 1, 2, 1);
1002
1003 return true;
1004
1005}
1006
1007int VillagePieces::SmallTemple::getVillagerProfession(int villagerNumber)
1008{
1009 return Villager::PROFESSION_PRIEST;
1010}
1011
1012VillagePieces::BookHouse::BookHouse()
1013{
1014 // for reflection
1015}
1016
1017VillagePieces::BookHouse::BookHouse(StartPiece *startPiece, int genDepth, Random *random, BoundingBox *stairsBox, int direction) : VillagePiece(startPiece, genDepth)
1018{
1019 heightPosition = -1; // 4J added initialiser
1020 orientation = direction;
1021 boundingBox = stairsBox;
1022}
1023
1024VillagePieces::BookHouse *VillagePieces::BookHouse::createPiece(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth)
1025{
1026 BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, 0, 0, 0, width, height, depth, direction);
1027
1028 if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL)
1029 {
1030 delete box;
1031 return NULL;
1032 }
1033
1034 return new BookHouse(startPiece, genDepth, random, box, direction);
1035}
1036
1037bool VillagePieces::BookHouse::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
1038{
1039 if (heightPosition < 0)
1040 {
1041 heightPosition = getAverageGroundHeight(level, chunkBB);
1042 if (heightPosition < 0)
1043 {
1044 return true;
1045 }
1046 boundingBox->move(0, heightPosition - boundingBox->y1 + height - 1, 0);
1047 }
1048
1049 // fill inside with air
1050 generateBox(level, chunkBB, 1, 1, 1, 7, 5, 4, 0, 0, false);
1051
1052 // floor
1053 generateBox(level, chunkBB, 0, 0, 0, 8, 0, 5, Tile::cobblestone_Id, Tile::cobblestone_Id, false);
1054 // roof
1055 generateBox(level, chunkBB, 0, 5, 0, 8, 5, 5, Tile::cobblestone_Id, Tile::cobblestone_Id, false);
1056 generateBox(level, chunkBB, 0, 6, 1, 8, 6, 4, Tile::cobblestone_Id, Tile::cobblestone_Id, false);
1057 generateBox(level, chunkBB, 0, 7, 2, 8, 7, 3, Tile::cobblestone_Id, Tile::cobblestone_Id, false);
1058 int southStairs = getOrientationData(Tile::stairs_wood_Id, 3);
1059 int northStairs = getOrientationData(Tile::stairs_wood_Id, 2);
1060 for (int d = -1; d <= 2; d++) {
1061 for (int w = 0; w <= 8; w++) {
1062 placeBlock(level, Tile::stairs_wood_Id, southStairs, w, 6 + d, d, chunkBB);
1063 placeBlock(level, Tile::stairs_wood_Id, northStairs, w, 6 + d, 5 - d, chunkBB);
1064 }
1065 }
1066
1067 // rock supports
1068 generateBox(level, chunkBB, 0, 1, 0, 0, 1, 5, Tile::cobblestone_Id, Tile::cobblestone_Id, false);
1069 generateBox(level, chunkBB, 1, 1, 5, 8, 1, 5, Tile::cobblestone_Id, Tile::cobblestone_Id, false);
1070 generateBox(level, chunkBB, 8, 1, 0, 8, 1, 4, Tile::cobblestone_Id, Tile::cobblestone_Id, false);
1071 generateBox(level, chunkBB, 2, 1, 0, 7, 1, 0, Tile::cobblestone_Id, Tile::cobblestone_Id, false);
1072 generateBox(level, chunkBB, 0, 2, 0, 0, 4, 0, Tile::cobblestone_Id, Tile::cobblestone_Id, false);
1073 generateBox(level, chunkBB, 0, 2, 5, 0, 4, 5, Tile::cobblestone_Id, Tile::cobblestone_Id, false);
1074 generateBox(level, chunkBB, 8, 2, 5, 8, 4, 5, Tile::cobblestone_Id, Tile::cobblestone_Id, false);
1075 generateBox(level, chunkBB, 8, 2, 0, 8, 4, 0, Tile::cobblestone_Id, Tile::cobblestone_Id, false);
1076
1077 // wooden walls
1078 generateBox(level, chunkBB, 0, 2, 1, 0, 4, 4, Tile::wood_Id, Tile::wood_Id, false);
1079 generateBox(level, chunkBB, 1, 2, 5, 7, 4, 5, Tile::wood_Id, Tile::wood_Id, false);
1080 generateBox(level, chunkBB, 8, 2, 1, 8, 4, 4, Tile::wood_Id, Tile::wood_Id, false);
1081 generateBox(level, chunkBB, 1, 2, 0, 7, 4, 0, Tile::wood_Id, Tile::wood_Id, false);
1082
1083 // windows
1084 placeBlock(level, Tile::thinGlass_Id, 0, 4, 2, 0, chunkBB);
1085 placeBlock(level, Tile::thinGlass_Id, 0, 5, 2, 0, chunkBB);
1086 placeBlock(level, Tile::thinGlass_Id, 0, 6, 2, 0, chunkBB);
1087 placeBlock(level, Tile::thinGlass_Id, 0, 4, 3, 0, chunkBB);
1088 placeBlock(level, Tile::thinGlass_Id, 0, 5, 3, 0, chunkBB);
1089 placeBlock(level, Tile::thinGlass_Id, 0, 6, 3, 0, chunkBB);
1090 placeBlock(level, Tile::thinGlass_Id, 0, 0, 2, 2, chunkBB);
1091 placeBlock(level, Tile::thinGlass_Id, 0, 0, 2, 3, chunkBB);
1092 placeBlock(level, Tile::thinGlass_Id, 0, 0, 3, 2, chunkBB);
1093 placeBlock(level, Tile::thinGlass_Id, 0, 0, 3, 3, chunkBB);
1094 placeBlock(level, Tile::thinGlass_Id, 0, 8, 2, 2, chunkBB);
1095 placeBlock(level, Tile::thinGlass_Id, 0, 8, 2, 3, chunkBB);
1096 placeBlock(level, Tile::thinGlass_Id, 0, 8, 3, 2, chunkBB);
1097 placeBlock(level, Tile::thinGlass_Id, 0, 8, 3, 3, chunkBB);
1098 placeBlock(level, Tile::thinGlass_Id, 0, 2, 2, 5, chunkBB);
1099 placeBlock(level, Tile::thinGlass_Id, 0, 3, 2, 5, chunkBB);
1100 placeBlock(level, Tile::thinGlass_Id, 0, 5, 2, 5, chunkBB);
1101 placeBlock(level, Tile::thinGlass_Id, 0, 6, 2, 5, chunkBB);
1102
1103 // roof inside and bookshelf
1104 generateBox(level, chunkBB, 1, 4, 1, 7, 4, 1, Tile::wood_Id, Tile::wood_Id, false);
1105 generateBox(level, chunkBB, 1, 4, 4, 7, 4, 4, Tile::wood_Id, Tile::wood_Id, false);
1106 generateBox(level, chunkBB, 1, 3, 4, 7, 3, 4, Tile::bookshelf_Id, Tile::bookshelf_Id, false);
1107
1108 // couch
1109 placeBlock(level, Tile::wood_Id, 0, 7, 1, 4, chunkBB);
1110 placeBlock(level, Tile::stairs_wood_Id, getOrientationData(Tile::stairs_wood_Id, 0), 7, 1, 3, chunkBB);
1111 int orientationData = getOrientationData(Tile::stairs_wood_Id, 3);
1112 placeBlock(level, Tile::stairs_wood_Id, orientationData, 6, 1, 4, chunkBB);
1113 placeBlock(level, Tile::stairs_wood_Id, orientationData, 5, 1, 4, chunkBB);
1114 placeBlock(level, Tile::stairs_wood_Id, orientationData, 4, 1, 4, chunkBB);
1115 placeBlock(level, Tile::stairs_wood_Id, orientationData, 3, 1, 4, chunkBB);
1116
1117 // tables
1118 placeBlock(level, Tile::fence_Id, 0, 6, 1, 3, chunkBB);
1119 placeBlock(level, Tile::pressurePlate_wood_Id, 0, 6, 2, 3, chunkBB);
1120 placeBlock(level, Tile::fence_Id, 0, 4, 1, 3, chunkBB);
1121 placeBlock(level, Tile::pressurePlate_wood_Id, 0, 4, 2, 3, chunkBB);
1122 placeBlock(level, Tile::workBench_Id, 0, 7, 1, 1, chunkBB);
1123
1124 // entrance
1125 placeBlock(level, 0, 0, 1, 1, 0, chunkBB);
1126 placeBlock(level, 0, 0, 1, 2, 0, chunkBB);
1127 createDoor(level, chunkBB, random, 1, 1, 0, getOrientationData(Tile::door_wood_Id, 1));
1128 if (getBlock(level, 1, 0, -1, chunkBB) == 0 && getBlock(level, 1, -1, -1, chunkBB) != 0)
1129 {
1130 placeBlock(level, Tile::stairs_stone_Id, getOrientationData(Tile::stairs_stone_Id, 3), 1, 0, -1, chunkBB);
1131 }
1132
1133 for (int z = 0; z < depth; z++)
1134 {
1135 for (int x = 0; x < width; x++)
1136 {
1137 generateAirColumnUp(level, x, height, z, chunkBB);
1138 fillColumnDown(level, Tile::cobblestone_Id, 0, x, -1, z, chunkBB);
1139 }
1140 }
1141
1142 spawnVillagers(level, chunkBB, 2, 1, 2, 1);
1143
1144 return true;
1145
1146}
1147
1148int VillagePieces::BookHouse::getVillagerProfession(int villagerNumber)
1149{
1150 return Villager::PROFESSION_LIBRARIAN;
1151}
1152
1153VillagePieces::SmallHut::SmallHut()
1154{
1155 // for reflection
1156}
1157
1158VillagePieces::SmallHut::SmallHut(StartPiece *startPiece, int genDepth, Random *random, BoundingBox *stairsBox, int direction) : VillagePiece(startPiece, genDepth), lowCeiling(random->nextBoolean()), tablePlacement(random->nextInt(3))
1159{
1160 heightPosition = -1; // 4J added initialiser
1161
1162 orientation = direction;
1163 boundingBox = stairsBox;
1164}
1165
1166void VillagePieces::SmallHut::addAdditonalSaveData(CompoundTag *tag)
1167{
1168 VillagePiece::addAdditonalSaveData(tag);
1169 tag->putInt(L"T", tablePlacement);
1170 tag->putBoolean(L"C", lowCeiling);
1171}
1172
1173void VillagePieces::SmallHut::readAdditonalSaveData(CompoundTag *tag)
1174{
1175 VillagePiece::readAdditonalSaveData(tag);
1176 tablePlacement = tag->getInt(L"T");
1177 lowCeiling = tag->getBoolean(L"C");
1178}
1179
1180VillagePieces::SmallHut *VillagePieces::SmallHut::createPiece(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth)
1181{
1182 BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, 0, 0, 0, width, height, depth, direction);
1183
1184 if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL)
1185 {
1186 delete box;
1187 return NULL;
1188 }
1189
1190 return new SmallHut(startPiece, genDepth, random, box, direction);
1191}
1192
1193bool VillagePieces::SmallHut::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
1194{
1195 if (heightPosition < 0)
1196 {
1197 heightPosition = getAverageGroundHeight(level, chunkBB);
1198 if (heightPosition < 0)
1199 {
1200 return true;
1201 }
1202 boundingBox->move(0, heightPosition - boundingBox->y1 + height - 1, 0);
1203 }
1204
1205 // fill inside with air
1206 generateBox(level, chunkBB, 1, 1, 1, 3, 5, 4, 0, 0, false);
1207
1208 // floor
1209 generateBox(level, chunkBB, 0, 0, 0, 3, 0, 4, Tile::cobblestone_Id, Tile::cobblestone_Id, false);
1210 generateBox(level, chunkBB, 1, 0, 1, 2, 0, 3, Tile::dirt_Id, Tile::dirt_Id, false);
1211 // roof
1212 if (lowCeiling) {
1213 generateBox(level, chunkBB, 1, 4, 1, 2, 4, 3, Tile::treeTrunk_Id, Tile::treeTrunk_Id, false);
1214 } else {
1215 generateBox(level, chunkBB, 1, 5, 1, 2, 5, 3, Tile::treeTrunk_Id, Tile::treeTrunk_Id, false);
1216 }
1217 placeBlock(level, Tile::treeTrunk_Id, 0, 1, 4, 0, chunkBB);
1218 placeBlock(level, Tile::treeTrunk_Id, 0, 2, 4, 0, chunkBB);
1219 placeBlock(level, Tile::treeTrunk_Id, 0, 1, 4, 4, chunkBB);
1220 placeBlock(level, Tile::treeTrunk_Id, 0, 2, 4, 4, chunkBB);
1221 placeBlock(level, Tile::treeTrunk_Id, 0, 0, 4, 1, chunkBB);
1222 placeBlock(level, Tile::treeTrunk_Id, 0, 0, 4, 2, chunkBB);
1223 placeBlock(level, Tile::treeTrunk_Id, 0, 0, 4, 3, chunkBB);
1224 placeBlock(level, Tile::treeTrunk_Id, 0, 3, 4, 1, chunkBB);
1225 placeBlock(level, Tile::treeTrunk_Id, 0, 3, 4, 2, chunkBB);
1226 placeBlock(level, Tile::treeTrunk_Id, 0, 3, 4, 3, chunkBB);
1227
1228 // corners
1229 generateBox(level, chunkBB, 0, 1, 0, 0, 3, 0, Tile::treeTrunk_Id, Tile::treeTrunk_Id, false);
1230 generateBox(level, chunkBB, 3, 1, 0, 3, 3, 0, Tile::treeTrunk_Id, Tile::treeTrunk_Id, false);
1231 generateBox(level, chunkBB, 0, 1, 4, 0, 3, 4, Tile::treeTrunk_Id, Tile::treeTrunk_Id, false);
1232 generateBox(level, chunkBB, 3, 1, 4, 3, 3, 4, Tile::treeTrunk_Id, Tile::treeTrunk_Id, false);
1233
1234 // wooden walls
1235 generateBox(level, chunkBB, 0, 1, 1, 0, 3, 3, Tile::wood_Id, Tile::wood_Id, false);
1236 generateBox(level, chunkBB, 3, 1, 1, 3, 3, 3, Tile::wood_Id, Tile::wood_Id, false);
1237 generateBox(level, chunkBB, 1, 1, 0, 2, 3, 0, Tile::wood_Id, Tile::wood_Id, false);
1238 generateBox(level, chunkBB, 1, 1, 4, 2, 3, 4, Tile::wood_Id, Tile::wood_Id, false);
1239
1240 // windows
1241 placeBlock(level, Tile::thinGlass_Id, 0, 0, 2, 2, chunkBB);
1242 placeBlock(level, Tile::thinGlass_Id, 0, 3, 2, 2, chunkBB);
1243
1244 // table
1245 if (tablePlacement > 0) {
1246 placeBlock(level, Tile::fence_Id, 0, tablePlacement, 1, 3, chunkBB);
1247 placeBlock(level, Tile::pressurePlate_wood_Id, 0, tablePlacement, 2, 3, chunkBB);
1248 }
1249
1250 // entrance
1251 placeBlock(level, 0, 0, 1, 1, 0, chunkBB);
1252 placeBlock(level, 0, 0, 1, 2, 0, chunkBB);
1253 createDoor(level, chunkBB, random, 1, 1, 0, getOrientationData(Tile::door_wood_Id, 1));
1254 if (getBlock(level, 1, 0, -1, chunkBB) == 0 && getBlock(level, 1, -1, -1, chunkBB) != 0)
1255 {
1256 placeBlock(level, Tile::stairs_stone_Id, getOrientationData(Tile::stairs_stone_Id, 3), 1, 0, -1, chunkBB);
1257 }
1258
1259 for (int z = 0; z < depth; z++)
1260 {
1261 for (int x = 0; x < width; x++)
1262 {
1263 generateAirColumnUp(level, x, height, z, chunkBB);
1264 fillColumnDown(level, Tile::cobblestone_Id, 0, x, -1, z, chunkBB);
1265 }
1266 }
1267
1268 spawnVillagers(level, chunkBB, 1, 1, 2, 1);
1269
1270 return true;
1271
1272}
1273
1274VillagePieces::PigHouse::PigHouse()
1275{
1276 // for reflection
1277}
1278
1279VillagePieces::PigHouse::PigHouse(StartPiece *startPiece, int genDepth, Random *random, BoundingBox *stairsBox, int direction) : VillagePiece(startPiece, genDepth)
1280{
1281 orientation = direction;
1282 boundingBox = stairsBox;
1283}
1284
1285VillagePieces::PigHouse *VillagePieces::PigHouse::createPiece(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth)
1286{
1287
1288 BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, 0, 0, 0, width, height, depth, direction);
1289
1290 if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL)
1291 {
1292 delete box;
1293 return NULL;
1294 }
1295
1296 return new PigHouse(startPiece, genDepth, random, box, direction);
1297}
1298
1299bool VillagePieces::PigHouse::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
1300{
1301 if (heightPosition < 0)
1302 {
1303 heightPosition = getAverageGroundHeight(level, chunkBB);
1304 if (heightPosition < 0)
1305 {
1306 return true;
1307 }
1308 boundingBox->move(0, heightPosition - boundingBox->y1 + height - 1, 0);
1309 }
1310
1311 // fill inside with air
1312 generateBox(level, chunkBB, 1, 1, 1, 7, 4, 4, 0, 0, false);
1313 generateBox(level, chunkBB, 2, 1, 6, 8, 4, 10, 0, 0, false);
1314
1315 // pig floor
1316 generateBox(level, chunkBB, 2, 0, 6, 8, 0, 10, Tile::dirt_Id, Tile::dirt_Id, false);
1317 placeBlock(level, Tile::cobblestone_Id, 0, 6, 0, 6, chunkBB);
1318 // pig fence
1319 generateBox(level, chunkBB, 2, 1, 6, 2, 1, 10, Tile::fence_Id, Tile::fence_Id, false);
1320 generateBox(level, chunkBB, 8, 1, 6, 8, 1, 10, Tile::fence_Id, Tile::fence_Id, false);
1321 generateBox(level, chunkBB, 3, 1, 10, 7, 1, 10, Tile::fence_Id, Tile::fence_Id, false);
1322
1323 // floor
1324 generateBox(level, chunkBB, 1, 0, 1, 7, 0, 4, Tile::wood_Id, Tile::wood_Id, false);
1325 generateBox(level, chunkBB, 0, 0, 0, 0, 3, 5, Tile::cobblestone_Id, Tile::cobblestone_Id, false);
1326 generateBox(level, chunkBB, 8, 0, 0, 8, 3, 5, Tile::cobblestone_Id, Tile::cobblestone_Id, false);
1327 generateBox(level, chunkBB, 1, 0, 0, 7, 1, 0, Tile::cobblestone_Id, Tile::cobblestone_Id, false);
1328 generateBox(level, chunkBB, 1, 0, 5, 7, 1, 5, Tile::cobblestone_Id, Tile::cobblestone_Id, false);
1329
1330 // roof
1331 generateBox(level, chunkBB, 1, 2, 0, 7, 3, 0, Tile::wood_Id, Tile::wood_Id, false);
1332 generateBox(level, chunkBB, 1, 2, 5, 7, 3, 5, Tile::wood_Id, Tile::wood_Id, false);
1333 generateBox(level, chunkBB, 0, 4, 1, 8, 4, 1, Tile::wood_Id, Tile::wood_Id, false);
1334 generateBox(level, chunkBB, 0, 4, 4, 8, 4, 4, Tile::wood_Id, Tile::wood_Id, false);
1335 generateBox(level, chunkBB, 0, 5, 2, 8, 5, 3, Tile::wood_Id, Tile::wood_Id, false);
1336 placeBlock(level, Tile::wood_Id, 0, 0, 4, 2, chunkBB);
1337 placeBlock(level, Tile::wood_Id, 0, 0, 4, 3, chunkBB);
1338 placeBlock(level, Tile::wood_Id, 0, 8, 4, 2, chunkBB);
1339 placeBlock(level, Tile::wood_Id, 0, 8, 4, 3, chunkBB);
1340
1341 int southStairs = getOrientationData(Tile::stairs_wood_Id, 3);
1342 int northStairs = getOrientationData(Tile::stairs_wood_Id, 2);
1343 for (int d = -1; d <= 2; d++)
1344 {
1345 for (int w = 0; w <= 8; w++)
1346 {
1347 placeBlock(level, Tile::stairs_wood_Id, southStairs, w, 4 + d, d, chunkBB);
1348 placeBlock(level, Tile::stairs_wood_Id, northStairs, w, 4 + d, 5 - d, chunkBB);
1349 }
1350 }
1351
1352 // windows etc
1353 placeBlock(level, Tile::treeTrunk_Id, 0, 0, 2, 1, chunkBB);
1354 placeBlock(level, Tile::treeTrunk_Id, 0, 0, 2, 4, chunkBB);
1355 placeBlock(level, Tile::treeTrunk_Id, 0, 8, 2, 1, chunkBB);
1356 placeBlock(level, Tile::treeTrunk_Id, 0, 8, 2, 4, chunkBB);
1357 placeBlock(level, Tile::thinGlass_Id, 0, 0, 2, 2, chunkBB);
1358 placeBlock(level, Tile::thinGlass_Id, 0, 0, 2, 3, chunkBB);
1359 placeBlock(level, Tile::thinGlass_Id, 0, 8, 2, 2, chunkBB);
1360 placeBlock(level, Tile::thinGlass_Id, 0, 8, 2, 3, chunkBB);
1361 placeBlock(level, Tile::thinGlass_Id, 0, 2, 2, 5, chunkBB);
1362 placeBlock(level, Tile::thinGlass_Id, 0, 3, 2, 5, chunkBB);
1363 placeBlock(level, Tile::thinGlass_Id, 0, 5, 2, 0, chunkBB);
1364 placeBlock(level, Tile::thinGlass_Id, 0, 6, 2, 5, chunkBB);
1365
1366 // table
1367 placeBlock(level, Tile::fence_Id, 0, 2, 1, 3, chunkBB);
1368 placeBlock(level, Tile::pressurePlate_wood_Id, 0, 2, 2, 3, chunkBB);
1369 placeBlock(level, Tile::wood_Id, 0, 1, 1, 4, chunkBB);
1370 placeBlock(level, Tile::stairs_wood_Id, getOrientationData(Tile::stairs_wood_Id, 3), 2, 1, 4, chunkBB);
1371 placeBlock(level, Tile::stairs_wood_Id, getOrientationData(Tile::stairs_wood_Id, 1), 1, 1, 3, chunkBB);
1372
1373 // butcher table
1374 generateBox(level, chunkBB, 5, 0, 1, 7, 0, 3, Tile::stoneSlab_Id, Tile::stoneSlab_Id, false);
1375 placeBlock(level, Tile::stoneSlab_Id, 0, 6, 1, 1, chunkBB);
1376 placeBlock(level, Tile::stoneSlab_Id, 0, 6, 1, 2, chunkBB);
1377
1378 // entrance
1379 placeBlock(level, 0, 0, 2, 1, 0, chunkBB);
1380 placeBlock(level, 0, 0, 2, 2, 0, chunkBB);
1381 placeBlock(level, Tile::torch_Id, 0, 2, 3, 1, chunkBB);
1382 createDoor(level, chunkBB, random, 2, 1, 0, getOrientationData(Tile::door_wood_Id, 1));
1383 if (getBlock(level, 2, 0, -1, chunkBB) == 0 && getBlock(level, 2, -1, -1, chunkBB) != 0)
1384 {
1385 placeBlock(level, Tile::stairs_stone_Id, getOrientationData(Tile::stairs_stone_Id, 3), 2, 0, -1, chunkBB);
1386 }
1387
1388 // pig entrance
1389 placeBlock(level, 0, 0, 6, 1, 5, chunkBB);
1390 placeBlock(level, 0, 0, 6, 2, 5, chunkBB);
1391 placeBlock(level, Tile::torch_Id, 0, 6, 3, 4, chunkBB);
1392 createDoor(level, chunkBB, random, 6, 1, 5, getOrientationData(Tile::door_wood_Id, 1));
1393
1394 for (int z = 0; z < 5; z++)
1395 {
1396 for (int x = 0; x < width; x++)
1397 {
1398 generateAirColumnUp(level, x, height, z, chunkBB);
1399 fillColumnDown(level, Tile::cobblestone_Id, 0, x, -1, z, chunkBB);
1400 }
1401 }
1402
1403 spawnVillagers(level, chunkBB, 4, 1, 2, 2);
1404
1405 return true;
1406
1407}
1408
1409int VillagePieces::PigHouse::getVillagerProfession(int villagerNumber)
1410{
1411 if (villagerNumber == 0)
1412 {
1413 return Villager::PROFESSION_BUTCHER;
1414 }
1415 return Villager::PROFESSION_FARMER;
1416}
1417
1418VillagePieces::TwoRoomHouse::TwoRoomHouse()
1419{
1420 // for reflection
1421}
1422
1423VillagePieces::TwoRoomHouse::TwoRoomHouse(StartPiece *startPiece, int genDepth, Random *random, BoundingBox *stairsBox, int direction) : VillagePiece(startPiece, genDepth)
1424{
1425 heightPosition = -1; // 4J added initialiser
1426
1427 orientation = direction;
1428 boundingBox = stairsBox;
1429}
1430
1431VillagePieces::TwoRoomHouse *VillagePieces::TwoRoomHouse::createPiece(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth)
1432{
1433 BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, 0, 0, 0, width, height, depth, direction);
1434
1435 if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL)
1436 {
1437 delete box;
1438 return NULL;
1439 }
1440
1441 return new TwoRoomHouse(startPiece, genDepth, random, box, direction);
1442}
1443
1444bool VillagePieces::TwoRoomHouse::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
1445{
1446 if (heightPosition < 0)
1447 {
1448 heightPosition = getAverageGroundHeight(level, chunkBB);
1449 if (heightPosition < 0)
1450 {
1451 return true;
1452 }
1453 boundingBox->move(0, heightPosition - boundingBox->y1 + height - 1, 0);
1454 }
1455
1456 // fill inside with air
1457 generateBox(level, chunkBB, 1, 1, 1, 7, 4, 4, 0, 0, false);
1458 generateBox(level, chunkBB, 2, 1, 6, 8, 4, 10, 0, 0, false);
1459
1460 // floor
1461 generateBox(level, chunkBB, 2, 0, 5, 8, 0, 10, Tile::wood_Id, Tile::wood_Id, false);
1462 generateBox(level, chunkBB, 1, 0, 1, 7, 0, 4, Tile::wood_Id, Tile::wood_Id, false);
1463 generateBox(level, chunkBB, 0, 0, 0, 0, 3, 5, Tile::cobblestone_Id, Tile::cobblestone_Id, false);
1464 generateBox(level, chunkBB, 8, 0, 0, 8, 3, 10, Tile::cobblestone_Id, Tile::cobblestone_Id, false);
1465 generateBox(level, chunkBB, 1, 0, 0, 7, 2, 0, Tile::cobblestone_Id, Tile::cobblestone_Id, false);
1466 generateBox(level, chunkBB, 1, 0, 5, 2, 1, 5, Tile::cobblestone_Id, Tile::cobblestone_Id, false);
1467 generateBox(level, chunkBB, 2, 0, 6, 2, 3, 10, Tile::cobblestone_Id, Tile::cobblestone_Id, false);
1468 generateBox(level, chunkBB, 3, 0, 10, 7, 3, 10, Tile::cobblestone_Id, Tile::cobblestone_Id, false);
1469
1470 // room 1 roof
1471 generateBox(level, chunkBB, 1, 2, 0, 7, 3, 0, Tile::wood_Id, Tile::wood_Id, false);
1472 generateBox(level, chunkBB, 1, 2, 5, 2, 3, 5, Tile::wood_Id, Tile::wood_Id, false);
1473 generateBox(level, chunkBB, 0, 4, 1, 8, 4, 1, Tile::wood_Id, Tile::wood_Id, false);
1474 generateBox(level, chunkBB, 0, 4, 4, 3, 4, 4, Tile::wood_Id, Tile::wood_Id, false);
1475 generateBox(level, chunkBB, 0, 5, 2, 8, 5, 3, Tile::wood_Id, Tile::wood_Id, false);
1476 placeBlock(level, Tile::wood_Id, 0, 0, 4, 2, chunkBB);
1477 placeBlock(level, Tile::wood_Id, 0, 0, 4, 3, chunkBB);
1478 placeBlock(level, Tile::wood_Id, 0, 8, 4, 2, chunkBB);
1479 placeBlock(level, Tile::wood_Id, 0, 8, 4, 3, chunkBB);
1480 placeBlock(level, Tile::wood_Id, 0, 8, 4, 4, chunkBB);
1481
1482 int southStairs = getOrientationData(Tile::stairs_wood_Id, 3);
1483 int northStairs = getOrientationData(Tile::stairs_wood_Id, 2);
1484 for (int d = -1; d <= 2; d++)
1485 {
1486 for (int w = 0; w <= 8; w++)
1487 {
1488 placeBlock(level, Tile::stairs_wood_Id, southStairs, w, 4 + d, d, chunkBB);
1489 if ((d > -1 || w <= 1) && (d > 0 || w <= 3) && (d > 1 || w <= 4 || w >= 6)) {
1490 placeBlock(level, Tile::stairs_wood_Id, northStairs, w, 4 + d, 5 - d, chunkBB);
1491 }
1492 }
1493 }
1494
1495 // room 2 roof
1496 generateBox(level, chunkBB, 3, 4, 5, 3, 4, 10, Tile::wood_Id, Tile::wood_Id, false);
1497 generateBox(level, chunkBB, 7, 4, 2, 7, 4, 10, Tile::wood_Id, Tile::wood_Id, false);
1498 generateBox(level, chunkBB, 4, 5, 4, 4, 5, 10, Tile::wood_Id, Tile::wood_Id, false);
1499 generateBox(level, chunkBB, 6, 5, 4, 6, 5, 10, Tile::wood_Id, Tile::wood_Id, false);
1500 generateBox(level, chunkBB, 5, 6, 3, 5, 6, 10, Tile::wood_Id, Tile::wood_Id, false);
1501 int westStairs = getOrientationData(Tile::stairs_wood_Id, 0);
1502 for (int w = 4; w >= 1; w--)
1503 {
1504 placeBlock(level, Tile::wood_Id, 0, w, 2 + w, 7 - w, chunkBB);
1505 for (int d = 8 - w; d <= 10; d++)
1506 {
1507 placeBlock(level, Tile::stairs_wood_Id, westStairs, w, 2 + w, d, chunkBB);
1508 }
1509 }
1510 int eastStairs = getOrientationData(Tile::stairs_wood_Id, 1);
1511 placeBlock(level, Tile::wood_Id, 0, 6, 6, 3, chunkBB);
1512 placeBlock(level, Tile::wood_Id, 0, 7, 5, 4, chunkBB);
1513 placeBlock(level, Tile::stairs_wood_Id, eastStairs, 6, 6, 4, chunkBB);
1514 for (int w = 6; w <= 8; w++)
1515 {
1516 for (int d = 5; d <= 10; d++)
1517 {
1518 placeBlock(level, Tile::stairs_wood_Id, eastStairs, w, 12 - w, d, chunkBB);
1519 }
1520 }
1521
1522 // windows etc
1523 placeBlock(level, Tile::treeTrunk_Id, 0, 0, 2, 1, chunkBB);
1524 placeBlock(level, Tile::treeTrunk_Id, 0, 0, 2, 4, chunkBB);
1525 placeBlock(level, Tile::thinGlass_Id, 0, 0, 2, 2, chunkBB);
1526 placeBlock(level, Tile::thinGlass_Id, 0, 0, 2, 3, chunkBB);
1527
1528 placeBlock(level, Tile::treeTrunk_Id, 0, 4, 2, 0, chunkBB);
1529 placeBlock(level, Tile::thinGlass_Id, 0, 5, 2, 0, chunkBB);
1530 placeBlock(level, Tile::treeTrunk_Id, 0, 6, 2, 0, chunkBB);
1531
1532 placeBlock(level, Tile::treeTrunk_Id, 0, 8, 2, 1, chunkBB);
1533 placeBlock(level, Tile::thinGlass_Id, 0, 8, 2, 2, chunkBB);
1534 placeBlock(level, Tile::thinGlass_Id, 0, 8, 2, 3, chunkBB);
1535 placeBlock(level, Tile::treeTrunk_Id, 0, 8, 2, 4, chunkBB);
1536 placeBlock(level, Tile::wood_Id, 0, 8, 2, 5, chunkBB);
1537 placeBlock(level, Tile::treeTrunk_Id, 0, 8, 2, 6, chunkBB);
1538 placeBlock(level, Tile::thinGlass_Id, 0, 8, 2, 7, chunkBB);
1539 placeBlock(level, Tile::thinGlass_Id, 0, 8, 2, 8, chunkBB);
1540 placeBlock(level, Tile::treeTrunk_Id, 0, 8, 2, 9, chunkBB);
1541 placeBlock(level, Tile::treeTrunk_Id, 0, 2, 2, 6, chunkBB);
1542 placeBlock(level, Tile::thinGlass_Id, 0, 2, 2, 7, chunkBB);
1543 placeBlock(level, Tile::thinGlass_Id, 0, 2, 2, 8, chunkBB);
1544 placeBlock(level, Tile::treeTrunk_Id, 0, 2, 2, 9, chunkBB);
1545
1546 placeBlock(level, Tile::treeTrunk_Id, 0, 4, 4, 10, chunkBB);
1547 placeBlock(level, Tile::thinGlass_Id, 0, 5, 4, 10, chunkBB);
1548 placeBlock(level, Tile::treeTrunk_Id, 0, 6, 4, 10, chunkBB);
1549 placeBlock(level, Tile::wood_Id, 0, 5, 5, 10, chunkBB);
1550
1551 // entrance
1552 placeBlock(level, 0, 0, 2, 1, 0, chunkBB);
1553 placeBlock(level, 0, 0, 2, 2, 0, chunkBB);
1554 placeBlock(level, Tile::torch_Id, 0, 2, 3, 1, chunkBB);
1555 createDoor(level, chunkBB, random, 2, 1, 0, getOrientationData(Tile::door_wood_Id, 1));
1556 generateBox(level, chunkBB, 1, 0, -1, 3, 2, -1, 0, 0, false);
1557 if (getBlock(level, 2, 0, -1, chunkBB) == 0 && getBlock(level, 2, -1, -1, chunkBB) != 0) {
1558 placeBlock(level, Tile::stairs_stone_Id, getOrientationData(Tile::stairs_stone_Id, 3), 2, 0, -1, chunkBB);
1559 }
1560
1561 for (int z = 0; z < 5; z++)
1562 {
1563 for (int x = 0; x < width; x++)
1564 {
1565 generateAirColumnUp(level, x, height, z, chunkBB);
1566 fillColumnDown(level, Tile::cobblestone_Id, 0, x, -1, z, chunkBB);
1567 }
1568 }
1569 for (int z = 5; z < depth - 1; z++)
1570 {
1571 for (int x = 2; x < width; x++)
1572 {
1573 generateAirColumnUp(level, x, height, z, chunkBB);
1574 fillColumnDown(level, Tile::cobblestone_Id, 0, x, -1, z, chunkBB);
1575 }
1576 }
1577
1578 spawnVillagers(level, chunkBB, 4, 1, 2, 2);
1579
1580 return true;
1581
1582}
1583
1584void VillagePieces::Smithy::staticCtor()
1585{
1586 treasureItems = WeighedTreasureArray(17);
1587 treasureItems[0] = new WeighedTreasure(Item::diamond_Id, 0, 1, 3, 3);
1588 treasureItems[1] = new WeighedTreasure(Item::ironIngot_Id, 0, 1, 5, 10);
1589 treasureItems[2] = new WeighedTreasure(Item::goldIngot_Id, 0, 1, 3, 5);
1590 treasureItems[3] = new WeighedTreasure(Item::bread_Id, 0, 1, 3, 15);
1591 treasureItems[4] = new WeighedTreasure(Item::apple_Id, 0, 1, 3, 15);
1592 treasureItems[5] = new WeighedTreasure(Item::pickAxe_iron_Id, 0, 1, 1, 5);
1593 treasureItems[6] = new WeighedTreasure(Item::sword_iron_Id, 0, 1, 1, 5);
1594 treasureItems[7] = new WeighedTreasure(Item::chestplate_iron_Id, 0, 1, 1, 5);
1595 treasureItems[8] = new WeighedTreasure(Item::helmet_iron_Id, 0, 1, 1, 5);
1596 treasureItems[9] = new WeighedTreasure(Item::leggings_iron_Id, 0, 1, 1, 5);
1597 treasureItems[10] = new WeighedTreasure(Item::boots_iron_Id, 0, 1, 1, 5);
1598 treasureItems[11] = new WeighedTreasure(Tile::obsidian_Id, 0, 3, 7, 5);
1599 treasureItems[12] = new WeighedTreasure(Tile::sapling_Id, 0, 3, 7, 5);
1600 // very rare for villages ...
1601 treasureItems[13] = new WeighedTreasure(Item::saddle_Id, 0, 1, 1, 3);
1602 treasureItems[14] = new WeighedTreasure(Item::horseArmorMetal_Id, 0, 1, 1, 1);
1603 treasureItems[15] = new WeighedTreasure(Item::horseArmorGold_Id, 0, 1, 1, 1);
1604 treasureItems[16] = new WeighedTreasure(Item::horseArmorDiamond_Id, 0, 1, 1, 1);
1605 // ...
1606}
1607
1608VillagePieces::Smithy::Smithy()
1609{
1610 // for reflection
1611}
1612
1613VillagePieces::Smithy::Smithy(StartPiece *startPiece, int genDepth, Random *random, BoundingBox *stairsBox, int direction) : VillagePiece(startPiece, genDepth)
1614{
1615 hasPlacedChest = false;
1616
1617 orientation = direction;
1618 boundingBox = stairsBox;
1619}
1620
1621VillagePieces::Smithy *VillagePieces::Smithy::createPiece(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth)
1622{
1623 BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, 0, 0, 0, width, height, depth, direction);
1624
1625 if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL)
1626 {
1627 delete box;
1628 return NULL;
1629 }
1630
1631 return new Smithy(startPiece, genDepth, random, box, direction);
1632}
1633
1634void VillagePieces::Smithy::addAdditonalSaveData(CompoundTag *tag)
1635{
1636 VillagePiece::addAdditonalSaveData(tag);
1637 tag->putBoolean(L"Chest", hasPlacedChest);
1638}
1639
1640void VillagePieces::Smithy::readAdditonalSaveData(CompoundTag *tag)
1641{
1642 VillagePiece::readAdditonalSaveData(tag);
1643 hasPlacedChest = tag->getBoolean(L"Chest");
1644}
1645
1646bool VillagePieces::Smithy::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
1647{
1648 if (heightPosition < 0)
1649 {
1650 heightPosition = getAverageGroundHeight(level, chunkBB);
1651 if (heightPosition < 0)
1652 {
1653 return true;
1654 }
1655 boundingBox->move(0, heightPosition - boundingBox->y1 + height - 1, 0);
1656 }
1657
1658 // fill inside with air
1659 generateBox(level, chunkBB, 0, 1, 0, 9, 4, 6, 0, 0, false);
1660
1661 // floor
1662 generateBox(level, chunkBB, 0, 0, 0, 9, 0, 6, Tile::cobblestone_Id, Tile::cobblestone_Id, false);
1663
1664 // roof
1665 generateBox(level, chunkBB, 0, 4, 0, 9, 4, 6, Tile::cobblestone_Id, Tile::cobblestone_Id, false);
1666 generateBox(level, chunkBB, 0, 5, 0, 9, 5, 6, Tile::stoneSlabHalf_Id, Tile::stoneSlabHalf_Id, false);
1667 generateBox(level, chunkBB, 1, 5, 1, 8, 5, 5, 0, 0, false);
1668
1669 // room walls
1670 generateBox(level, chunkBB, 1, 1, 0, 2, 3, 0, Tile::wood_Id, Tile::wood_Id, false);
1671 generateBox(level, chunkBB, 0, 1, 0, 0, 4, 0, Tile::treeTrunk_Id, Tile::treeTrunk_Id, false);
1672 generateBox(level, chunkBB, 3, 1, 0, 3, 4, 0, Tile::treeTrunk_Id, Tile::treeTrunk_Id, false);
1673 generateBox(level, chunkBB, 0, 1, 6, 0, 4, 6, Tile::treeTrunk_Id, Tile::treeTrunk_Id, false);
1674 placeBlock(level, Tile::wood_Id, 0, 3, 3, 1, chunkBB);
1675 generateBox(level, chunkBB, 3, 1, 2, 3, 3, 2, Tile::wood_Id, Tile::wood_Id, false);
1676 generateBox(level, chunkBB, 4, 1, 3, 5, 3, 3, Tile::wood_Id, Tile::wood_Id, false);
1677 generateBox(level, chunkBB, 0, 1, 1, 0, 3, 5, Tile::wood_Id, Tile::wood_Id, false);
1678 generateBox(level, chunkBB, 1, 1, 6, 5, 3, 6, Tile::wood_Id, Tile::wood_Id, false);
1679
1680 // pillars
1681 generateBox(level, chunkBB, 5, 1, 0, 5, 3, 0, Tile::fence_Id, Tile::fence_Id, false);
1682 generateBox(level, chunkBB, 9, 1, 0, 9, 3, 0, Tile::fence_Id, Tile::fence_Id, false);
1683
1684 // furnace
1685 generateBox(level, chunkBB, 6, 1, 4, 9, 4, 6, Tile::cobblestone_Id, Tile::cobblestone_Id, false);
1686 placeBlock(level, Tile::lava_Id, 0, 7, 1, 5, chunkBB);
1687 placeBlock(level, Tile::lava_Id, 0, 8, 1, 5, chunkBB);
1688 placeBlock(level, Tile::ironFence_Id, 0, 9, 2, 5, chunkBB);
1689 placeBlock(level, Tile::ironFence_Id, 0, 9, 2, 4, chunkBB);
1690 generateBox(level, chunkBB, 7, 2, 4, 8, 2, 5, 0, 0, false);
1691 placeBlock(level, Tile::cobblestone_Id, 0, 6, 1, 3, chunkBB);
1692 placeBlock(level, Tile::furnace_Id, 0, 6, 2, 3, chunkBB);
1693 placeBlock(level, Tile::furnace_Id, 0, 6, 3, 3, chunkBB);
1694 placeBlock(level, Tile::stoneSlab_Id, 0, 8, 1, 1, chunkBB);
1695
1696 // windows etc
1697 placeBlock(level, Tile::thinGlass_Id, 0, 0, 2, 2, chunkBB);
1698 placeBlock(level, Tile::thinGlass_Id, 0, 0, 2, 4, chunkBB);
1699 placeBlock(level, Tile::thinGlass_Id, 0, 2, 2, 6, chunkBB);
1700 placeBlock(level, Tile::thinGlass_Id, 0, 4, 2, 6, chunkBB);
1701
1702 // table
1703 placeBlock(level, Tile::fence_Id, 0, 2, 1, 4, chunkBB);
1704 placeBlock(level, Tile::pressurePlate_wood_Id, 0, 2, 2, 4, chunkBB);
1705 placeBlock(level, Tile::wood_Id, 0, 1, 1, 5, chunkBB);
1706 placeBlock(level, Tile::stairs_wood_Id, getOrientationData(Tile::stairs_wood_Id, 3), 2, 1, 5, chunkBB);
1707 placeBlock(level, Tile::stairs_wood_Id, getOrientationData(Tile::stairs_wood_Id, 1), 1, 1, 4, chunkBB);
1708
1709 if (!hasPlacedChest)
1710 {
1711 int y = getWorldY(1);
1712 int x = getWorldX(5, 5), z = getWorldZ(5, 5);
1713 if (chunkBB->isInside(x, y, z))
1714 {
1715 hasPlacedChest = true;
1716 createChest(level, chunkBB, random, 5, 1, 5, treasureItems, 3 + random->nextInt(6));
1717 }
1718 }
1719
1720 // entrance
1721 for (int x = 6; x <= 8; x++)
1722 {
1723 if (getBlock(level, x, 0, -1, chunkBB) == 0 && getBlock(level, x, -1, -1, chunkBB) != 0 )
1724 {
1725 placeBlock(level, Tile::stairs_stone_Id, getOrientationData(Tile::stairs_stone_Id, 3), x, 0, -1, chunkBB);
1726 }
1727 }
1728
1729 for (int z = 0; z < depth; z++)
1730 {
1731 for (int x = 0; x < width; x++)
1732 {
1733 generateAirColumnUp(level, x, height, z, chunkBB);
1734 fillColumnDown(level, Tile::cobblestone_Id, 0, x, -1, z, chunkBB);
1735 }
1736 }
1737
1738 spawnVillagers(level, chunkBB, 7, 1, 1, 1);
1739
1740 return true;
1741
1742}
1743
1744int VillagePieces::Smithy::getVillagerProfession(int villagerNumber)
1745{
1746 return Villager::PROFESSION_SMITH;
1747}
1748
1749VillagePieces::Farmland::Farmland()
1750{
1751 cropsA = 0;
1752 cropsB = 0;
1753 // for reflection
1754}
1755
1756VillagePieces::Farmland::Farmland(StartPiece *startPiece, int genDepth, Random *random, BoundingBox *stairsBox, int direction) : VillagePiece(startPiece, genDepth)
1757{
1758 orientation = direction;
1759 boundingBox = stairsBox;
1760
1761 cropsA = selectCrops(random);
1762 cropsB = selectCrops(random);
1763}
1764
1765int VillagePieces::Farmland::selectCrops(Random *random)
1766{
1767 switch (random->nextInt(5))
1768 {
1769 default:
1770 return Tile::wheat_Id;
1771 case 0:
1772 return Tile::carrots_Id;
1773 case 1:
1774 return Tile::potatoes_Id;
1775 }
1776}
1777
1778void VillagePieces::Farmland::addAdditonalSaveData(CompoundTag *tag)
1779{
1780 VillagePiece::addAdditonalSaveData(tag);
1781 tag->putInt(L"CA", cropsA);
1782 tag->putInt(L"CB", cropsB);
1783}
1784
1785void VillagePieces::Farmland::readAdditonalSaveData(CompoundTag *tag)
1786{
1787 VillagePiece::readAdditonalSaveData(tag);
1788 cropsA = tag->getInt(L"CA");
1789 cropsB = tag->getInt(L"CB");
1790}
1791
1792VillagePieces::Farmland *VillagePieces::Farmland::createPiece(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth)
1793{
1794 BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, 0, 0, 0, width, height, depth, direction);
1795
1796 if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL)
1797 {
1798 delete box;
1799 return NULL;
1800 }
1801
1802 return new Farmland(startPiece, genDepth, random, box, direction);
1803}
1804
1805bool VillagePieces::Farmland::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
1806{
1807 if (heightPosition < 0)
1808 {
1809 heightPosition = getAverageGroundHeight(level, chunkBB);
1810 if (heightPosition < 0)
1811 {
1812 return true;
1813 }
1814 boundingBox->move(0, heightPosition - boundingBox->y1 + height - 1, 0);
1815 }
1816
1817 // fill inside with air
1818 generateBox(level, chunkBB, 0, 1, 0, 6, 4, 8, 0, 0, false);
1819
1820 // farmlands
1821 generateBox(level, chunkBB, 1, 0, 1, 2, 0, 7, Tile::farmland_Id, Tile::farmland_Id, false);
1822 generateBox(level, chunkBB, 4, 0, 1, 5, 0, 7, Tile::farmland_Id, Tile::farmland_Id, false);
1823 // walkpaths
1824 generateBox(level, chunkBB, 0, 0, 0, 0, 0, 8, Tile::treeTrunk_Id, Tile::treeTrunk_Id, false);
1825 generateBox(level, chunkBB, 6, 0, 0, 6, 0, 8, Tile::treeTrunk_Id, Tile::treeTrunk_Id, false);
1826 generateBox(level, chunkBB, 1, 0, 0, 5, 0, 0, Tile::treeTrunk_Id, Tile::treeTrunk_Id, false);
1827 generateBox(level, chunkBB, 1, 0, 8, 5, 0, 8, Tile::treeTrunk_Id, Tile::treeTrunk_Id, false);
1828 // water
1829 generateBox(level, chunkBB, 3, 0, 1, 3, 0, 7, Tile::water_Id, Tile::water_Id, false);
1830 // crops
1831 for (int d = 1; d <= 7; d++)
1832 {
1833 placeBlock(level, cropsA, Mth::nextInt(random, 2, 7), 1, 1, d, chunkBB);
1834 placeBlock(level, cropsA, Mth::nextInt(random, 2, 7), 2, 1, d, chunkBB);
1835 placeBlock(level, cropsB, Mth::nextInt(random, 2, 7), 4, 1, d, chunkBB);
1836 placeBlock(level, cropsB, Mth::nextInt(random, 2, 7), 5, 1, d, chunkBB);
1837 }
1838
1839 for (int z = 0; z < depth; z++)
1840 {
1841 for (int x = 0; x < width; x++)
1842 {
1843 generateAirColumnUp(level, x, height, z, chunkBB);
1844 fillColumnDown(level, Tile::dirt_Id, 0, x, -1, z, chunkBB);
1845 }
1846 }
1847
1848 return true;
1849
1850}
1851
1852VillagePieces::DoubleFarmland::DoubleFarmland()
1853{
1854 cropsA = 0;
1855 cropsB = 0;
1856 cropsC = 0;
1857 cropsD = 0;
1858 // for reflection
1859}
1860
1861VillagePieces::DoubleFarmland::DoubleFarmland(StartPiece *startPiece, int genDepth, Random *random, BoundingBox *stairsBox, int direction) : VillagePiece(startPiece, genDepth)
1862{
1863 heightPosition = -1; // 4J added initialiser
1864 orientation = direction;
1865 boundingBox = stairsBox;
1866
1867 cropsA = selectCrops(random);
1868 cropsB = selectCrops(random);
1869 cropsC = selectCrops(random);
1870 cropsD = selectCrops(random);
1871}
1872
1873void VillagePieces::DoubleFarmland::addAdditonalSaveData(CompoundTag *tag)
1874{
1875 VillagePiece::addAdditonalSaveData(tag);
1876 tag->putInt(L"CA", cropsA);
1877 tag->putInt(L"CB", cropsB);
1878 tag->putInt(L"CC", cropsC);
1879 tag->putInt(L"CD", cropsD);
1880}
1881
1882void VillagePieces::DoubleFarmland::readAdditonalSaveData(CompoundTag *tag)
1883{
1884 VillagePiece::readAdditonalSaveData(tag);
1885 cropsA = tag->getInt(L"CA");
1886 cropsB = tag->getInt(L"CB");
1887 cropsC = tag->getInt(L"CC");
1888 cropsD = tag->getInt(L"CD");
1889}
1890
1891int VillagePieces::DoubleFarmland::selectCrops(Random *random)
1892{
1893 switch (random->nextInt(5))
1894 {
1895 default:
1896 return Tile::wheat_Id;
1897 case 0:
1898 return Tile::carrots_Id;
1899 case 1:
1900 return Tile::potatoes_Id;
1901 }
1902}
1903
1904VillagePieces::DoubleFarmland *VillagePieces::DoubleFarmland::createPiece(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth)
1905{
1906 BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, 0, 0, 0, width, height, depth, direction);
1907
1908 if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL)
1909 {
1910 delete box;
1911 return NULL;
1912 }
1913
1914 return new DoubleFarmland(startPiece, genDepth, random, box, direction);
1915}
1916
1917bool VillagePieces::DoubleFarmland::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
1918{
1919 if (heightPosition < 0)
1920 {
1921 heightPosition = getAverageGroundHeight(level, chunkBB);
1922 if (heightPosition < 0)
1923 {
1924 return true;
1925 }
1926 boundingBox->move(0, heightPosition - boundingBox->y1 + height - 1, 0);
1927 }
1928
1929 // fill inside with air
1930 generateBox(level, chunkBB, 0, 1, 0, 12, 4, 8, 0, 0, false);
1931
1932 // farmlands
1933 generateBox(level, chunkBB, 1, 0, 1, 2, 0, 7, Tile::farmland_Id, Tile::farmland_Id, false);
1934 generateBox(level, chunkBB, 4, 0, 1, 5, 0, 7, Tile::farmland_Id, Tile::farmland_Id, false);
1935 generateBox(level, chunkBB, 7, 0, 1, 8, 0, 7, Tile::farmland_Id, Tile::farmland_Id, false);
1936 generateBox(level, chunkBB, 10, 0, 1, 11, 0, 7, Tile::farmland_Id, Tile::farmland_Id, false);
1937 // walkpaths
1938 generateBox(level, chunkBB, 0, 0, 0, 0, 0, 8, Tile::treeTrunk_Id, Tile::treeTrunk_Id, false);
1939 generateBox(level, chunkBB, 6, 0, 0, 6, 0, 8, Tile::treeTrunk_Id, Tile::treeTrunk_Id, false);
1940 generateBox(level, chunkBB, 12, 0, 0, 12, 0, 8, Tile::treeTrunk_Id, Tile::treeTrunk_Id, false);
1941 generateBox(level, chunkBB, 1, 0, 0, 11, 0, 0, Tile::treeTrunk_Id, Tile::treeTrunk_Id, false);
1942 generateBox(level, chunkBB, 1, 0, 8, 11, 0, 8, Tile::treeTrunk_Id, Tile::treeTrunk_Id, false);
1943 // water
1944 generateBox(level, chunkBB, 3, 0, 1, 3, 0, 7, Tile::water_Id, Tile::water_Id, false);
1945 generateBox(level, chunkBB, 9, 0, 1, 9, 0, 7, Tile::water_Id, Tile::water_Id, false);
1946 // crops
1947 for (int d = 1; d <= 7; d++)
1948 {
1949 placeBlock(level, cropsA, Mth::nextInt(random, 2, 7), 1, 1, d, chunkBB);
1950 placeBlock(level, cropsA, Mth::nextInt(random, 2, 7), 2, 1, d, chunkBB);
1951 placeBlock(level, cropsB, Mth::nextInt(random, 2, 7), 4, 1, d, chunkBB);
1952 placeBlock(level, cropsB, Mth::nextInt(random, 2, 7), 5, 1, d, chunkBB);
1953 placeBlock(level, cropsC, Mth::nextInt(random, 2, 7), 7, 1, d, chunkBB);
1954 placeBlock(level, cropsC, Mth::nextInt(random, 2, 7), 8, 1, d, chunkBB);
1955 placeBlock(level, cropsD, Mth::nextInt(random, 2, 7), 10, 1, d, chunkBB);
1956 placeBlock(level, cropsD, Mth::nextInt(random, 2, 7), 11, 1, d, chunkBB);
1957 }
1958
1959 for (int z = 0; z < depth; z++)
1960 {
1961 for (int x = 0; x < width; x++)
1962 {
1963 generateAirColumnUp(level, x, height, z, chunkBB);
1964 fillColumnDown(level, Tile::dirt_Id, 0, x, -1, z, chunkBB);
1965 }
1966 }
1967
1968
1969 return true;
1970
1971}
1972
1973VillagePieces::LightPost::LightPost()
1974{
1975 // for reflection
1976}
1977
1978VillagePieces::LightPost::LightPost(StartPiece *startPiece, int genDepth, Random *random, BoundingBox *box, int direction) : VillagePiece(startPiece, genDepth)
1979{
1980 heightPosition = -1; // 4J - added initialiser
1981 orientation = direction;
1982 boundingBox = box;
1983}
1984
1985BoundingBox *VillagePieces::LightPost::findPieceBox(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction)
1986{
1987 BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, 0, 0, 0, width, height, depth, direction);
1988
1989 if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL)
1990 {
1991 delete box;
1992 return NULL;
1993 }
1994
1995 return box;
1996}
1997
1998bool VillagePieces::LightPost::postProcess(Level *level, Random *random, BoundingBox *chunkBB)
1999{
2000 if (heightPosition < 0)
2001 {
2002 heightPosition = getAverageGroundHeight(level, chunkBB);
2003 if (heightPosition < 0)
2004 {
2005 return true;
2006 }
2007 boundingBox->move(0, heightPosition - boundingBox->y1 + height - 1, 0);
2008 }
2009
2010 // fill with air
2011 generateBox(level, chunkBB, 0, 0, 0, 2, 3, 1, 0, 0, false);
2012
2013 // pillar
2014 placeBlock(level, Tile::fence_Id, 0, 1, 0, 0, chunkBB);
2015 placeBlock(level, Tile::fence_Id, 0, 1, 1, 0, chunkBB);
2016 placeBlock(level, Tile::fence_Id, 0, 1, 2, 0, chunkBB);
2017
2018 // head
2019 placeBlock(level, Tile::wool_Id, DyePowderItem::WHITE, 1, 3, 0, chunkBB);
2020
2021 // torches
2022 placeBlock(level, Tile::torch_Id, 0, 0, 3, 0, chunkBB);
2023 placeBlock(level, Tile::torch_Id, 0, 1, 3, 1, chunkBB);
2024 placeBlock(level, Tile::torch_Id, 0, 2, 3, 0, chunkBB);
2025 placeBlock(level, Tile::torch_Id, 0, 1, 3, -1, chunkBB);
2026
2027 return true;
2028}