diff options
| author | daoge_cmd <3523206925@qq.com> | 2026-03-01 12:16:08 +0800 |
|---|---|---|
| committer | daoge_cmd <3523206925@qq.com> | 2026-03-01 12:16:08 +0800 |
| commit | b691c43c44ff180d10e7d4a9afc83b98551ff586 (patch) | |
| tree | 3e9849222cbc6ba49f2f1fc6e5fe7179632c7390 /Minecraft.World/VillagePieces.cpp | |
| parent | def8cb415354ac390b7e89052a50605285f1aca9 (diff) | |
Initial commit
Diffstat (limited to 'Minecraft.World/VillagePieces.cpp')
| -rw-r--r-- | Minecraft.World/VillagePieces.cpp | 1847 |
1 files changed, 1847 insertions, 0 deletions
diff --git a/Minecraft.World/VillagePieces.cpp b/Minecraft.World/VillagePieces.cpp new file mode 100644 index 00000000..27b21aa5 --- /dev/null +++ b/Minecraft.World/VillagePieces.cpp @@ -0,0 +1,1847 @@ +#include "stdafx.h" +#include "net.minecraft.h" +#include "net.minecraft.world.level.h" +#include "net.minecraft.world.level.storage.h" +#include "net.minecraft.world.level.tile.h" +#include "net.minecraft.world.level.levelgen.h" +#include "net.minecraft.world.item.h" +#include "net.minecraft.world.level.dimension.h" +#include "net.minecraft.world.entity.npc.h" +#include "WeighedTreasure.h" +#include "VillagePieces.h" +#include "VillageFeature.h" +#include "Direction.h" +#include "JavaMath.h" +#include "BiomeSource.h" + +WeighedTreasureArray VillagePieces::Smithy::treasureItems; + +VillagePieces::PieceWeight::PieceWeight(VillagePieces::EPieceClass pieceClass, int weight, int maxPlaceCount) : weight(weight) +{ + this->placeCount = 0; // 4J added initialiser + this->pieceClass = pieceClass; + this->maxPlaceCount = maxPlaceCount; +} + +bool VillagePieces::PieceWeight::doPlace(int depth) +{ + return maxPlaceCount == 0 || placeCount < maxPlaceCount; +} + +bool VillagePieces::PieceWeight::isValid() +{ + return maxPlaceCount == 0 || placeCount < maxPlaceCount; +} + +list<VillagePieces::PieceWeight *> *VillagePieces::createPieceSet(Random *random, int villageSize) +{ + list<PieceWeight *> *newPieces = new list<PieceWeight *>; + + newPieces->push_back(new PieceWeight(VillagePieces::EPieceClass_SimpleHouse, 4, Mth::nextInt(random, 2 + villageSize, 4 + villageSize * 2))); + newPieces->push_back(new PieceWeight(VillagePieces::EPieceClass_SmallTemple, 20, Mth::nextInt(random, 0 + villageSize, 1 + villageSize))); + newPieces->push_back(new PieceWeight(VillagePieces::EPieceClass_BookHouse, 20, Mth::nextInt(random, 0 + villageSize, 2 + villageSize))); + newPieces->push_back(new PieceWeight(VillagePieces::EPieceClass_SmallHut, 3, Mth::nextInt(random, 2 + villageSize, 5 + villageSize * 3))); + newPieces->push_back(new PieceWeight(VillagePieces::EPieceClass_PigHouse, 15, Mth::nextInt(random, 0 + villageSize, 2 + villageSize))); + newPieces->push_back(new PieceWeight(VillagePieces::EPieceClass_DoubleFarmland, 3, Mth::nextInt(random, 1 + villageSize, 4 + villageSize))); + newPieces->push_back(new PieceWeight(VillagePieces::EPieceClass_Farmland, 3, Mth::nextInt(random, 2 + villageSize, 4 + villageSize * 2))); + newPieces->push_back(new PieceWeight(VillagePieces::EPieceClass_Smithy, 15, Mth::nextInt(random, 0, 1 + villageSize))); + newPieces->push_back(new PieceWeight(VillagePieces::EPieceClass_TwoRoomHouse, 8, Mth::nextInt(random, 0 + villageSize, 3 + villageSize * 2))); + + // silly way of filtering "infinite" buildings + AUTO_VAR(it, newPieces->begin()); + while( it != newPieces->end() ) + { + if( (*it)->maxPlaceCount == 0 ) + { + delete (*it); + it = newPieces->erase(it); + } + else + { + it++; + } + } + + return newPieces; +} + +int VillagePieces::updatePieceWeight(list<PieceWeight *> *currentPieces) +{ + bool hasAnyPieces = false; + int totalWeight = 0; + for( AUTO_VAR(it, currentPieces->begin()); it != currentPieces->end(); it++ ) + { + PieceWeight *piece = *it; + if (piece->maxPlaceCount > 0 && piece->placeCount < piece->maxPlaceCount) + { + hasAnyPieces = true; + } + totalWeight += piece->weight; + } + return (hasAnyPieces ? totalWeight : -1); +} + +VillagePieces::VillagePiece *VillagePieces::findAndCreatePieceFactory(StartPiece *startPiece, VillagePieces::PieceWeight *piece, list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int depth) +{ + VillagePieces::EPieceClass pieceClass = piece->pieceClass; + VillagePiece *villagePiece = NULL; + + if (pieceClass == VillagePieces::EPieceClass_SimpleHouse) + { + villagePiece = SimpleHouse::createPiece(startPiece, pieces, random, footX, footY, footZ, direction, depth); + } + else if (pieceClass == VillagePieces::EPieceClass_SmallTemple) + { + villagePiece = SmallTemple::createPiece(startPiece, pieces, random, footX, footY, footZ, direction, depth); + } + else if (pieceClass == VillagePieces::EPieceClass_BookHouse) + { + villagePiece = BookHouse::createPiece(startPiece, pieces, random, footX, footY, footZ, direction, depth); + } + else if (pieceClass == VillagePieces::EPieceClass_SmallHut) + { + villagePiece = SmallHut::createPiece(startPiece, pieces, random, footX, footY, footZ, direction, depth); + } + else if (pieceClass == VillagePieces::EPieceClass_PigHouse) + { + villagePiece = PigHouse::createPiece(startPiece, pieces, random, footX, footY, footZ, direction, depth); + } + else if (pieceClass == VillagePieces::EPieceClass_DoubleFarmland) + { + villagePiece = DoubleFarmland::createPiece(startPiece, pieces, random, footX, footY, footZ, direction, depth); + } + else if (pieceClass == VillagePieces::EPieceClass_Farmland) + { + villagePiece = Farmland::createPiece(startPiece, pieces, random, footX, footY, footZ, direction, depth); + } + else if (pieceClass == VillagePieces::EPieceClass_Smithy) + { + villagePiece = Smithy::createPiece(startPiece, pieces, random, footX, footY, footZ, direction, depth); + } + else if (pieceClass == VillagePieces::EPieceClass_TwoRoomHouse) + { + villagePiece = TwoRoomHouse::createPiece(startPiece, pieces, random, footX, footY, footZ, direction, depth); + } + + return villagePiece; +} + +VillagePieces::VillagePiece *VillagePieces::generatePieceFromSmallDoor(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int depth) +{ + int totalWeight = updatePieceWeight(startPiece->pieceSet); + if (totalWeight <= 0) + { + return NULL; + } + + int numAttempts = 0; + while (numAttempts < 5) + { + numAttempts++; + + int weightSelection = random->nextInt(totalWeight); + for( AUTO_VAR(it, startPiece->pieceSet->begin()); it != startPiece->pieceSet->end(); it++ ) + { + PieceWeight *piece = *it; + weightSelection -= piece->weight; + if (weightSelection < 0) + { + + if (!piece->doPlace(depth) || (piece == startPiece->previousPiece && startPiece->pieceSet->size() > 1)) + { + break; + } + + VillagePiece *villagePiece = findAndCreatePieceFactory(startPiece, piece, pieces, random, footX, footY, footZ, direction, depth); + if (villagePiece != NULL) + { + piece->placeCount++; + startPiece->previousPiece = piece; + + if (!piece->isValid()) + { + startPiece->pieceSet->remove(piece); + } + return villagePiece; + } + } + } + } + + // attempt to place a light post instead + { + BoundingBox *box = LightPost::findPieceBox(startPiece, pieces, random, footX, footY, footZ, direction); + if (box != NULL) + { + return new LightPost(startPiece, depth, random, box, direction); + } + delete box; + } + + return NULL; +} + +StructurePiece *VillagePieces::generateAndAddPiece(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int depth) +{ + if (depth > MAX_DEPTH) + { + return NULL; + } + if (abs(footX - startPiece->getBoundingBox()->x0) > 7 * 16 || abs(footZ - startPiece->getBoundingBox()->z0) > 7 * 16) + { + return NULL; + } + + StructurePiece *newPiece = generatePieceFromSmallDoor(startPiece, pieces, random, footX, footY, footZ, direction, depth + 1); + if (newPiece != NULL) + { + int x = (newPiece->boundingBox->x0 + newPiece->boundingBox->x1) / 2; + int z = (newPiece->boundingBox->z0 + newPiece->boundingBox->z1) / 2; + int xs = newPiece->boundingBox->x1 - newPiece->boundingBox->x0; + int zs = newPiece->boundingBox->z1 - newPiece->boundingBox->z0; + int r = xs > zs ? xs : zs; + if (startPiece->getBiomeSource()->containsOnly(x, z, r / 2 + 4, VillageFeature::allowedBiomes)) + { + pieces->push_back(newPiece); + startPiece->pendingHouses.push_back(newPiece); + return newPiece; + } + delete newPiece; + } + return NULL; +} + +StructurePiece *VillagePieces::generateAndAddRoadPiece(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int depth) +{ + if (depth > BASE_ROAD_DEPTH + startPiece->villageSize) + { + return NULL; + } + if (abs(footX - startPiece->getBoundingBox()->x0) > 7 * 16 || abs(footZ - startPiece->getBoundingBox()->z0) > 7 * 16) + { + return NULL; + } + + BoundingBox *box = StraightRoad::findPieceBox(startPiece, pieces, random, footX, footY, footZ, direction); + if (box != NULL && box->y0 > LOWEST_Y_POSITION) + { + StructurePiece *newPiece = new StraightRoad(startPiece, depth, random, box, direction); + int x = (newPiece->boundingBox->x0 + newPiece->boundingBox->x1) / 2; + int z = (newPiece->boundingBox->z0 + newPiece->boundingBox->z1) / 2; + int xs = newPiece->boundingBox->x1 - newPiece->boundingBox->x0; + int zs = newPiece->boundingBox->z1 - newPiece->boundingBox->z0; + int r = xs > zs ? xs : zs; + if (startPiece->getBiomeSource()->containsOnly(x, z, r / 2 + 4, VillageFeature::allowedBiomes)) + { + pieces->push_back(newPiece); + startPiece->pendingRoads.push_back(newPiece); + return newPiece; + } + // 4J Stu - The dtor for newPiece will destroy box + delete newPiece; + } + else if(box != NULL) + { + delete box; + } + + return NULL; +} + +VillagePieces::VillagePiece::VillagePiece(StartPiece *startPiece, int genDepth) : StructurePiece(genDepth) +{ + spawnedVillagerCount = 0; + this->startPiece = startPiece; +} + +StructurePiece *VillagePieces::VillagePiece::generateHouseNorthernLeft(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int yOff, int zOff) +{ + switch (orientation) + { + case Direction::NORTH: + return generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 - 1, boundingBox->y0 + yOff, boundingBox->z0 + zOff, Direction::WEST, getGenDepth()); + case Direction::SOUTH: + return generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 - 1, boundingBox->y0 + yOff, boundingBox->z0 + zOff, Direction::WEST, getGenDepth()); + case Direction::WEST: + return generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 + zOff, boundingBox->y0 + yOff, boundingBox->z0 - 1, Direction::NORTH, getGenDepth()); + case Direction::EAST: + return generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 + zOff, boundingBox->y0 + yOff, boundingBox->z0 - 1, Direction::NORTH, getGenDepth()); + } + return NULL; +} + +StructurePiece *VillagePieces::VillagePiece::generateHouseNorthernRight(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int yOff, int zOff) +{ + switch (orientation) + { + case Direction::NORTH: + return generateAndAddPiece(startPiece, pieces, random, boundingBox->x1 + 1, boundingBox->y0 + yOff, boundingBox->z0 + zOff, Direction::EAST, getGenDepth()); + case Direction::SOUTH: + return generateAndAddPiece(startPiece, pieces, random, boundingBox->x1 + 1, boundingBox->y0 + yOff, boundingBox->z0 + zOff, Direction::EAST, getGenDepth()); + case Direction::WEST: + return generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 + zOff, boundingBox->y0 + yOff, boundingBox->z1 + 1, Direction::SOUTH, getGenDepth()); + case Direction::EAST: + return generateAndAddPiece(startPiece, pieces, random, boundingBox->x0 + zOff, boundingBox->y0 + yOff, boundingBox->z1 + 1, Direction::SOUTH, getGenDepth()); + } + return NULL; +} + +int VillagePieces::VillagePiece::getAverageGroundHeight(Level *level, BoundingBox *chunkBB) +{ + int total = 0; + int count = 0; + for (int z = boundingBox->z0; z <= boundingBox->z1; z++) + { + for (int x = boundingBox->x0; x <= boundingBox->x1; x++) + { + if (chunkBB->isInside(x, 64, z)) + { + total += Math::_max(level->getTopSolidBlock(x, z), level->dimension->getSpawnYPosition()); + count++; + } + } + } + + if (count == 0) + { + return -1; + } + return total / count; +} + +bool VillagePieces::VillagePiece::isOkBox(BoundingBox *box, StartPiece *startRoom) +{ + bool bIsOk = false; + + if(box != NULL) + { + if( box->y0 > LOWEST_Y_POSITION ) bIsOk = true; + + int xzSize = startRoom->m_level->getLevelData()->getXZSize(); + int blockMin = -( (xzSize << 4) / 2) + 1; + int blockMax = ( (xzSize << 4) / 2 ) - 1; + + if(box->x0 <= blockMin) bIsOk = false; + if(box->z0 <= blockMin) bIsOk = false; + if(box->x1 >= blockMax) bIsOk = false; + if(box->z1 >= blockMax) bIsOk = false; + } + + return bIsOk; +} + +void VillagePieces::VillagePiece::spawnVillagers(Level *level, BoundingBox *chunkBB, int x, int y, int z, int count) +{ + if (spawnedVillagerCount >= count) + { + return; + } + + for (int i = spawnedVillagerCount; i < count; i++) + { + int worldX = getWorldX(x + i, z); + int worldY = getWorldY(y); + int worldZ = getWorldZ(x + i, z); + + if (chunkBB->isInside(worldX, worldY, worldZ)) + { + spawnedVillagerCount++; + + shared_ptr<Villager> villager = shared_ptr<Villager>(new Villager(level, getVillagerProfession(i))); + villager->moveTo(worldX + 0.5, worldY, worldZ + 0.5, 0, 0); + level->addEntity(villager); + } + else + { + // try again later + break; + } + } +} + +int VillagePieces::VillagePiece::getVillagerProfession(int villagerNumber) +{ + return Villager::PROFESSION_FARMER; +} + +int VillagePieces::VillagePiece::biomeBlock(int tile, int data) +{ + if (startPiece->isDesertVillage) + { + if (tile == Tile::treeTrunk_Id) + { + return Tile::sandStone_Id; + } + else if (tile == Tile::stoneBrick_Id) + { + return Tile::sandStone_Id; + } + else if (tile == Tile::wood_Id) + { + return Tile::sandStone_Id; + } + else if (tile == Tile::stairs_wood_Id) + { + return Tile::stairs_sandstone_Id; + } + else if (tile == Tile::stairs_stone_Id) + { + return Tile::stairs_sandstone_Id; + } + else if (tile == Tile::gravel_Id) + { + return Tile::sandStone_Id; + } + } + return tile; +} + +int VillagePieces::VillagePiece::biomeData(int tile, int data) +{ + if (startPiece->isDesertVillage) + { + if (tile == Tile::treeTrunk_Id) + { + return 0; + } + else if (tile == Tile::stoneBrick_Id) + { + return SandStoneTile::TYPE_DEFAULT; + } + else if (tile == Tile::wood_Id) + { + return SandStoneTile::TYPE_SMOOTHSIDE; + } + } + return data; +} + +void VillagePieces::VillagePiece::placeBlock(Level *level, int block, int data, int x, int y, int z, BoundingBox *chunkBB) +{ + int bblock = biomeBlock(block, data); + int bdata = biomeData(block, data); + StructurePiece::placeBlock(level, bblock, bdata, x, y, z, chunkBB); +} + +void 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) +{ + int bEdge = biomeBlock(edgeTile, 0); + int bEdgeData = biomeData(edgeTile, 0); + int bFill = biomeBlock(fillTile, 0); + int bFillData = biomeData(fillTile, 0); + StructurePiece::generateBox(level, chunkBB, x0, y0, z0, x1, y1, z1, bEdge, bEdgeData, bFill, bFillData, skipAir); +} + +void VillagePieces::VillagePiece::fillColumnDown(Level *level, int block, int data, int x, int startY, int z, BoundingBox *chunkBB) +{ + int bblock = biomeBlock(block, data); + int bdata = biomeData(block, data); + StructurePiece::fillColumnDown(level, bblock, bdata, x, startY, z, chunkBB); +} + +VillagePieces::Well::Well(StartPiece *startPiece, int genDepth, Random *random, int west, int north) : VillagePiece(startPiece, genDepth), isSource(true) +{ + heightPosition = -1; // 4J added initialiser + orientation = random->nextInt(4); + + switch (orientation) + { + case Direction::NORTH: + case Direction::SOUTH: + boundingBox = new BoundingBox(west, 64, north, west + width - 1, 64 + height - 1, north + depth - 1); + break; + default: + boundingBox = new BoundingBox(west, 64, north, west + depth - 1, 64 + height - 1, north + width - 1); + break; + } +} + +VillagePieces::Well::Well(StartPiece *startPiece, int genDepth, Random *random, BoundingBox *stairsBox, int direction) : VillagePiece(startPiece, genDepth), isSource(false) +{ + heightPosition = -1; // 4J added initialiser + + orientation = direction; + boundingBox = stairsBox; +} + +void VillagePieces::Well::addChildren(StructurePiece *startPiece, list<StructurePiece *> *pieces, Random *random) +{ + generateAndAddRoadPiece((StartPiece *) startPiece, pieces, random, boundingBox->x0 - 1, boundingBox->y1 - 4, boundingBox->z0 + 1, Direction::WEST, getGenDepth()); + generateAndAddRoadPiece((StartPiece *) startPiece, pieces, random, boundingBox->x1 + 1, boundingBox->y1 - 4, boundingBox->z0 + 1, Direction::EAST, getGenDepth()); + generateAndAddRoadPiece((StartPiece *) startPiece, pieces, random, boundingBox->x0 + 1, boundingBox->y1 - 4, boundingBox->z0 - 1, Direction::NORTH, getGenDepth()); + generateAndAddRoadPiece((StartPiece *) startPiece, pieces, random, boundingBox->x0 + 1, boundingBox->y1 - 4, boundingBox->z1 + 1, Direction::SOUTH, getGenDepth()); +} + +//VillagePieces::Well *VillagePieces::Well::createPiece(list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth) +//{ +// BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, -1, 4 - height, 0, width, height, depth, direction); +// +// if (!isOkBox(box) || StructurePiece::findCollisionPiece(pieces, box) != NULL) +// { +// delete box; +// return NULL; +// } +// +// return new Well(genDepth, random, box, direction); +//} + +bool VillagePieces::Well::postProcess(Level *level, Random *random, BoundingBox *chunkBB) +{ + if (heightPosition < 0) + { + heightPosition = getAverageGroundHeight(level, chunkBB); + if (heightPosition < 0) + { + return true; + } + boundingBox->move(0, heightPosition - boundingBox->y1 + 3, 0); + } + + generateBox(level, chunkBB, 1, 0, 1, 4, height - 3, 4, Tile::stoneBrick_Id, Tile::water_Id, false); + placeBlock(level, 0, 0, 2, height - 3, 2, chunkBB); + placeBlock(level, 0, 0, 3, height - 3, 2, chunkBB); + placeBlock(level, 0, 0, 2, height - 3, 3, chunkBB); + placeBlock(level, 0, 0, 3, height - 3, 3, chunkBB); + + placeBlock(level, Tile::fence_Id, 0, 1, height - 2, 1, chunkBB); + placeBlock(level, Tile::fence_Id, 0, 1, height - 1, 1, chunkBB); + placeBlock(level, Tile::fence_Id, 0, 4, height - 2, 1, chunkBB); + placeBlock(level, Tile::fence_Id, 0, 4, height - 1, 1, chunkBB); + placeBlock(level, Tile::fence_Id, 0, 1, height - 2, 4, chunkBB); + placeBlock(level, Tile::fence_Id, 0, 1, height - 1, 4, chunkBB); + placeBlock(level, Tile::fence_Id, 0, 4, height - 2, 4, chunkBB); + placeBlock(level, Tile::fence_Id, 0, 4, height - 1, 4, chunkBB); + generateBox(level, chunkBB, 1, height, 1, 4, height, 4, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false); + + for (int z = 0; z <= 5; z++) + { + for (int x = 0; x <= 5; x++) + { + // only do the frame + if (x != 0 && x != 5 && z != 0 && z != 5) + { + continue; + } + placeBlock(level, Tile::gravel_Id, 0, x, height - 4, z, chunkBB); + generateAirColumnUp(level, x, height - 3, z, chunkBB); + } + } + + return true; + +} + +VillagePieces::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) +{ + isLibraryAdded = false; // 4J - added initialiser + previousPiece = NULL; // 4J - added initialiser + this->biomeSource = biomeSource; + this->pieceSet = pieceSet; + this->villageSize = villageSize; + m_level = level; + + Biome *biome = biomeSource->getBiome(west, north); + this->isDesertVillage = biome == Biome::desert || biome == Biome::desertHills; + this->startPiece = this; +} + +VillagePieces::StartPiece::~StartPiece() +{ + for(AUTO_VAR(it, pieceSet->begin()); it != pieceSet->end(); it++ ) + { + delete (*it); + } + delete pieceSet; +} + +BiomeSource *VillagePieces::StartPiece::getBiomeSource() +{ + return biomeSource; +} + +VillagePieces::StraightRoad::StraightRoad(StartPiece *startPiece, int genDepth, Random *random, BoundingBox *stairsBox, int direction) : VillageRoadPiece(startPiece, genDepth) +{ + orientation = direction; + boundingBox = stairsBox; + length = Math::_max(stairsBox->getXSpan(), stairsBox->getZSpan()); +} + +void VillagePieces::StraightRoad::addChildren(StructurePiece *startPiece, list<StructurePiece *> *pieces, Random *random) +{ + bool hasHouses = false; + + // place left houses + int depth = random->nextInt(5); + while (depth < length - 8) + { + StructurePiece *piece = generateHouseNorthernLeft((StartPiece *) startPiece, pieces, random, 0, depth); + if (piece != NULL) + { + depth += Math::_max(piece->boundingBox->getXSpan(), piece->boundingBox->getZSpan()); + hasHouses = true; + } + depth += 2 + random->nextInt(5); + } + + // place right houses + depth = random->nextInt(5); + while (depth < length - 8) + { + StructurePiece *piece = generateHouseNorthernRight((StartPiece *) startPiece, pieces, random, 0, depth); + if (piece != NULL) + { + depth += Math::_max(piece->boundingBox->getXSpan(), piece->boundingBox->getZSpan()); + hasHouses = true; + } + depth += 2 + random->nextInt(5); + } + + if (hasHouses && random->nextInt(3) > 0) + { + switch (orientation) + { + case Direction::NORTH: + generateAndAddRoadPiece((StartPiece *) startPiece, pieces, random, boundingBox->x0 - 1, boundingBox->y0, boundingBox->z0, Direction::WEST, getGenDepth()); + break; + case Direction::SOUTH: + generateAndAddRoadPiece((StartPiece *) startPiece, pieces, random, boundingBox->x0 - 1, boundingBox->y0, boundingBox->z1 - 2, Direction::WEST, getGenDepth()); + break; + case Direction::EAST: + generateAndAddRoadPiece((StartPiece *) startPiece, pieces, random, boundingBox->x1 - 2, boundingBox->y0, boundingBox->z0 - 1, Direction::NORTH, getGenDepth()); + break; + case Direction::WEST: + generateAndAddRoadPiece((StartPiece *) startPiece, pieces, random, boundingBox->x0, boundingBox->y0, boundingBox->z0 - 1, Direction::NORTH, getGenDepth()); + break; + } + } + if (hasHouses && random->nextInt(3) > 0) + { + switch (orientation) + { + case Direction::NORTH: + generateAndAddRoadPiece((StartPiece *) startPiece, pieces, random, boundingBox->x1 + 1, boundingBox->y0, boundingBox->z0, Direction::EAST, getGenDepth()); + break; + case Direction::SOUTH: + generateAndAddRoadPiece((StartPiece *) startPiece, pieces, random, boundingBox->x1 + 1, boundingBox->y0, boundingBox->z1 - 2, Direction::EAST, getGenDepth()); + break; + case Direction::EAST: + generateAndAddRoadPiece((StartPiece *) startPiece, pieces, random, boundingBox->x1 - 2, boundingBox->y0, boundingBox->z1 + 1, Direction::SOUTH, getGenDepth()); + break; + case Direction::WEST: + generateAndAddRoadPiece((StartPiece *) startPiece, pieces, random, boundingBox->x0, boundingBox->y0, boundingBox->z1 + 1, Direction::SOUTH, getGenDepth()); + break; + } + } +} + +BoundingBox *VillagePieces::StraightRoad::findPieceBox(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction) +{ + int length = 7 * (Mth::nextInt(random, 3, 5)); + + while (length >= 7) + { + BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, 0, 0, 0, width, 3, length, direction); + + if (isOkBox(box, startPiece) && StructurePiece::findCollisionPiece(pieces, box) == NULL) + { + return box; + } + delete box; + length -= 7; + } + + return NULL; +} + +bool VillagePieces::StraightRoad::postProcess(Level *level, Random *random, BoundingBox *chunkBB) +{ + int tile = biomeBlock(Tile::gravel_Id, 0); + for (int x = boundingBox->x0; x <= boundingBox->x1; x++) + { + for (int z = boundingBox->z0; z <= boundingBox->z1; z++) + { + if (chunkBB->isInside(x, 64, z)) + { + int y = level->getTopSolidBlock(x, z) - 1; + level->setTileNoUpdate(x, y, z,tile); + } + } + } + + return true; +} + +/* +int heightPosition; +const bool hasTerrace;*/ + +VillagePieces::SimpleHouse::SimpleHouse(StartPiece *startPiece, int genDepth, Random *random, BoundingBox *stairsBox, int direction) : VillagePiece(startPiece, genDepth), hasTerrace(random->nextBoolean()) +{ + heightPosition = -1; // 4J added initialiser + orientation = direction; + boundingBox = stairsBox; +} + +VillagePieces::SimpleHouse *VillagePieces::SimpleHouse::createPiece(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth) +{ + BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, 0, 0, 0, width, height, depth, direction); + + if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL) + { + delete box; + return NULL; + } + + return new SimpleHouse(startPiece, genDepth, random, box, direction); +} + +bool VillagePieces::SimpleHouse::postProcess(Level *level, Random *random, BoundingBox *chunkBB) +{ + if (heightPosition < 0) + { + heightPosition = getAverageGroundHeight(level, chunkBB); + if (heightPosition < 0) + { + return true; + } + boundingBox->move(0, heightPosition - boundingBox->y1 + height - 1, 0); + } + + // floor + generateBox(level, chunkBB, 0, 0, 0, 4, 0, 4, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false); + // roof + generateBox(level, chunkBB, 0, 4, 0, 4, 4, 4, Tile::treeTrunk_Id, Tile::treeTrunk_Id, false); + generateBox(level, chunkBB, 1, 4, 1, 3, 4, 3, Tile::wood_Id, Tile::wood_Id, false); + + // window walls + placeBlock(level, Tile::stoneBrick_Id, 0, 0, 1, 0, chunkBB); + placeBlock(level, Tile::stoneBrick_Id, 0, 0, 2, 0, chunkBB); + placeBlock(level, Tile::stoneBrick_Id, 0, 0, 3, 0, chunkBB); + placeBlock(level, Tile::stoneBrick_Id, 0, 4, 1, 0, chunkBB); + placeBlock(level, Tile::stoneBrick_Id, 0, 4, 2, 0, chunkBB); + placeBlock(level, Tile::stoneBrick_Id, 0, 4, 3, 0, chunkBB); + placeBlock(level, Tile::stoneBrick_Id, 0, 0, 1, 4, chunkBB); + placeBlock(level, Tile::stoneBrick_Id, 0, 0, 2, 4, chunkBB); + placeBlock(level, Tile::stoneBrick_Id, 0, 0, 3, 4, chunkBB); + placeBlock(level, Tile::stoneBrick_Id, 0, 4, 1, 4, chunkBB); + placeBlock(level, Tile::stoneBrick_Id, 0, 4, 2, 4, chunkBB); + placeBlock(level, Tile::stoneBrick_Id, 0, 4, 3, 4, chunkBB); + generateBox(level, chunkBB, 0, 1, 1, 0, 3, 3, Tile::wood_Id, Tile::wood_Id, false); + generateBox(level, chunkBB, 4, 1, 1, 4, 3, 3, Tile::wood_Id, Tile::wood_Id, false); + generateBox(level, chunkBB, 1, 1, 4, 3, 3, 4, Tile::wood_Id, Tile::wood_Id, false); + placeBlock(level, Tile::thinGlass_Id, 0, 0, 2, 2, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 2, 2, 4, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 4, 2, 2, chunkBB); + + // door wall + placeBlock(level, Tile::wood_Id, 0, 1, 1, 0, chunkBB); + placeBlock(level, Tile::wood_Id, 0, 1, 2, 0, chunkBB); + placeBlock(level, Tile::wood_Id, 0, 1, 3, 0, chunkBB); + placeBlock(level, Tile::wood_Id, 0, 2, 3, 0, chunkBB); + placeBlock(level, Tile::wood_Id, 0, 3, 3, 0, chunkBB); + placeBlock(level, Tile::wood_Id, 0, 3, 2, 0, chunkBB); + placeBlock(level, Tile::wood_Id, 0, 3, 1, 0, chunkBB); + if (getBlock(level, 2, 0, -1, chunkBB) == 0 && getBlock(level, 2, -1, -1, chunkBB) != 0) + { + placeBlock(level, Tile::stairs_stone_Id, getOrientationData(Tile::stairs_stone_Id, 3), 2, 0, -1, chunkBB); + } + + // fill room with air + generateBox(level, chunkBB, 1, 1, 1, 3, 3, 3, 0, 0, false); + + // roof fence + if (hasTerrace) { + placeBlock(level, Tile::fence_Id, 0, 0, 5, 0, chunkBB); + placeBlock(level, Tile::fence_Id, 0, 1, 5, 0, chunkBB); + placeBlock(level, Tile::fence_Id, 0, 2, 5, 0, chunkBB); + placeBlock(level, Tile::fence_Id, 0, 3, 5, 0, chunkBB); + placeBlock(level, Tile::fence_Id, 0, 4, 5, 0, chunkBB); + placeBlock(level, Tile::fence_Id, 0, 0, 5, 4, chunkBB); + placeBlock(level, Tile::fence_Id, 0, 1, 5, 4, chunkBB); + placeBlock(level, Tile::fence_Id, 0, 2, 5, 4, chunkBB); + placeBlock(level, Tile::fence_Id, 0, 3, 5, 4, chunkBB); + placeBlock(level, Tile::fence_Id, 0, 4, 5, 4, chunkBB); + placeBlock(level, Tile::fence_Id, 0, 4, 5, 1, chunkBB); + placeBlock(level, Tile::fence_Id, 0, 4, 5, 2, chunkBB); + placeBlock(level, Tile::fence_Id, 0, 4, 5, 3, chunkBB); + placeBlock(level, Tile::fence_Id, 0, 0, 5, 1, chunkBB); + placeBlock(level, Tile::fence_Id, 0, 0, 5, 2, chunkBB); + placeBlock(level, Tile::fence_Id, 0, 0, 5, 3, chunkBB); + } + + // ladder + if (hasTerrace) + { + int orientationData = getOrientationData(Tile::ladder_Id, 3); + placeBlock(level, Tile::ladder_Id, orientationData, 3, 1, 3, chunkBB); + placeBlock(level, Tile::ladder_Id, orientationData, 3, 2, 3, chunkBB); + placeBlock(level, Tile::ladder_Id, orientationData, 3, 3, 3, chunkBB); + placeBlock(level, Tile::ladder_Id, orientationData, 3, 4, 3, chunkBB); + } + + // torch + placeBlock(level, Tile::torch_Id, 0, 2, 3, 1, chunkBB); + + for (int z = 0; z < depth; z++) + { + for (int x = 0; x < width; x++) + { + generateAirColumnUp(level, x, height, z, chunkBB); + fillColumnDown(level, Tile::stoneBrick_Id, 0, x, -1, z, chunkBB); + } + } + + spawnVillagers(level, chunkBB, 1, 1, 2, 1); + + return true; + +} + +VillagePieces::SmallTemple::SmallTemple(StartPiece *startPiece, int genDepth, Random *random, BoundingBox *stairsBox, int direction) : VillagePiece(startPiece, genDepth) +{ + heightPosition = -1; // 4J added initialiser + orientation = direction; + boundingBox = stairsBox; +} + +VillagePieces::SmallTemple *VillagePieces::SmallTemple::createPiece(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth) +{ + BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, 0, 0, 0, width, height, depth, direction); + + if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL) + { + delete box; + return NULL; + } + + return new SmallTemple(startPiece, genDepth, random, box, direction); +} + +bool VillagePieces::SmallTemple::postProcess(Level *level, Random *random, BoundingBox *chunkBB) +{ + if (heightPosition < 0) + { + heightPosition = getAverageGroundHeight(level, chunkBB); + if (heightPosition < 0) + { + return true; + } + boundingBox->move(0, heightPosition - boundingBox->y1 + height - 1, 0); + } + + // fill inside with air + generateBox(level, chunkBB, 1, 1, 1, 3, 3, 7, 0, 0, false); + generateBox(level, chunkBB, 1, 5, 1, 3, 9, 3, 0, 0, false); + + // floor + generateBox(level, chunkBB, 1, 0, 0, 3, 0, 8, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false); + + // front wall + generateBox(level, chunkBB, 1, 1, 0, 3, 10, 0, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false); + // left tall wall + generateBox(level, chunkBB, 0, 1, 1, 0, 10, 3, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false); + // right tall wall + generateBox(level, chunkBB, 4, 1, 1, 4, 10, 3, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false); + // left low wall + generateBox(level, chunkBB, 0, 0, 4, 0, 4, 7, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false); + // right low wall + generateBox(level, chunkBB, 4, 0, 4, 4, 4, 7, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false); + // far low wall + generateBox(level, chunkBB, 1, 1, 8, 3, 4, 8, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false); + // far upper wall + generateBox(level, chunkBB, 1, 5, 4, 3, 10, 4, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false); + + // low roof + generateBox(level, chunkBB, 1, 5, 5, 3, 5, 7, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false); + // high roof + generateBox(level, chunkBB, 0, 9, 0, 4, 9, 4, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false); + // middle floor / roof + generateBox(level, chunkBB, 0, 4, 0, 4, 4, 4, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false); + placeBlock(level, Tile::stoneBrick_Id, 0, 0, 11, 2, chunkBB); + placeBlock(level, Tile::stoneBrick_Id, 0, 4, 11, 2, chunkBB); + placeBlock(level, Tile::stoneBrick_Id, 0, 2, 11, 0, chunkBB); + placeBlock(level, Tile::stoneBrick_Id, 0, 2, 11, 4, chunkBB); + + // altar pieces + placeBlock(level, Tile::stoneBrick_Id, 0, 1, 1, 6, chunkBB); + placeBlock(level, Tile::stoneBrick_Id, 0, 1, 1, 7, chunkBB); + placeBlock(level, Tile::stoneBrick_Id, 0, 2, 1, 7, chunkBB); + placeBlock(level, Tile::stoneBrick_Id, 0, 3, 1, 6, chunkBB); + placeBlock(level, Tile::stoneBrick_Id, 0, 3, 1, 7, chunkBB); + placeBlock(level, Tile::stairs_stone_Id, getOrientationData(Tile::stairs_stone_Id, 3), 1, 1, 5, chunkBB); + placeBlock(level, Tile::stairs_stone_Id, getOrientationData(Tile::stairs_stone_Id, 3), 2, 1, 6, chunkBB); + placeBlock(level, Tile::stairs_stone_Id, getOrientationData(Tile::stairs_stone_Id, 3), 3, 1, 5, chunkBB); + placeBlock(level, Tile::stairs_stone_Id, getOrientationData(Tile::stairs_stone_Id, 1), 1, 2, 7, chunkBB); + placeBlock(level, Tile::stairs_stone_Id, getOrientationData(Tile::stairs_stone_Id, 0), 3, 2, 7, chunkBB); + + // windows + placeBlock(level, Tile::thinGlass_Id, 0, 0, 2, 2, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 0, 3, 2, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 4, 2, 2, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 4, 3, 2, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 0, 6, 2, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 0, 7, 2, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 4, 6, 2, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 4, 7, 2, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 2, 6, 0, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 2, 7, 0, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 2, 6, 4, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 2, 7, 4, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 0, 3, 6, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 4, 3, 6, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 2, 3, 8, chunkBB); + + // torches + placeBlock(level, Tile::torch_Id, 0, 2, 4, 7, chunkBB); + placeBlock(level, Tile::torch_Id, 0, 1, 4, 6, chunkBB); + placeBlock(level, Tile::torch_Id, 0, 3, 4, 6, chunkBB); + placeBlock(level, Tile::torch_Id, 0, 2, 4, 5, chunkBB); + + // ladder + int orientationData = getOrientationData(Tile::ladder_Id, 4); + for (int y = 1; y <= 9; y++) + { + placeBlock(level, Tile::ladder_Id, orientationData, 3, y, 3, chunkBB); + } + + // entrance + placeBlock(level, 0, 0, 2, 1, 0, chunkBB); + placeBlock(level, 0, 0, 2, 2, 0, chunkBB); + createDoor(level, chunkBB, random, 2, 1, 0, getOrientationData(Tile::door_wood_Id, 1)); + if (getBlock(level, 2, 0, -1, chunkBB) == 0 && getBlock(level, 2, -1, -1, chunkBB) != 0) + { + placeBlock(level, Tile::stairs_stone_Id, getOrientationData(Tile::stairs_stone_Id, 3), 2, 0, -1, chunkBB); + } + + + for (int z = 0; z < depth; z++) + { + for (int x = 0; x < width; x++) + { + generateAirColumnUp(level, x, height, z, chunkBB); + fillColumnDown(level, Tile::stoneBrick_Id, 0, x, -1, z, chunkBB); + } + } + + spawnVillagers(level, chunkBB, 2, 1, 2, 1); + + return true; + +} + +int VillagePieces::SmallTemple::getVillagerProfession(int villagerNumber) +{ + return Villager::PROFESSION_PRIEST; +} + + +VillagePieces::BookHouse::BookHouse(StartPiece *startPiece, int genDepth, Random *random, BoundingBox *stairsBox, int direction) : VillagePiece(startPiece, genDepth) +{ + heightPosition = -1; // 4J added initialiser + orientation = direction; + boundingBox = stairsBox; +} + +VillagePieces::BookHouse *VillagePieces::BookHouse::createPiece(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth) +{ + BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, 0, 0, 0, width, height, depth, direction); + + if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL) + { + delete box; + return NULL; + } + + return new BookHouse(startPiece, genDepth, random, box, direction); +} + +bool VillagePieces::BookHouse::postProcess(Level *level, Random *random, BoundingBox *chunkBB) +{ + if (heightPosition < 0) + { + heightPosition = getAverageGroundHeight(level, chunkBB); + if (heightPosition < 0) + { + return true; + } + boundingBox->move(0, heightPosition - boundingBox->y1 + height - 1, 0); + } + + // fill inside with air + generateBox(level, chunkBB, 1, 1, 1, 7, 5, 4, 0, 0, false); + + // floor + generateBox(level, chunkBB, 0, 0, 0, 8, 0, 5, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false); + // roof + generateBox(level, chunkBB, 0, 5, 0, 8, 5, 5, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false); + generateBox(level, chunkBB, 0, 6, 1, 8, 6, 4, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false); + generateBox(level, chunkBB, 0, 7, 2, 8, 7, 3, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false); + int southStairs = getOrientationData(Tile::stairs_wood_Id, 3); + int northStairs = getOrientationData(Tile::stairs_wood_Id, 2); + for (int d = -1; d <= 2; d++) { + for (int w = 0; w <= 8; w++) { + placeBlock(level, Tile::stairs_wood_Id, southStairs, w, 6 + d, d, chunkBB); + placeBlock(level, Tile::stairs_wood_Id, northStairs, w, 6 + d, 5 - d, chunkBB); + } + } + + // rock supports + generateBox(level, chunkBB, 0, 1, 0, 0, 1, 5, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false); + generateBox(level, chunkBB, 1, 1, 5, 8, 1, 5, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false); + generateBox(level, chunkBB, 8, 1, 0, 8, 1, 4, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false); + generateBox(level, chunkBB, 2, 1, 0, 7, 1, 0, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false); + generateBox(level, chunkBB, 0, 2, 0, 0, 4, 0, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false); + generateBox(level, chunkBB, 0, 2, 5, 0, 4, 5, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false); + generateBox(level, chunkBB, 8, 2, 5, 8, 4, 5, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false); + generateBox(level, chunkBB, 8, 2, 0, 8, 4, 0, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false); + + // wooden walls + generateBox(level, chunkBB, 0, 2, 1, 0, 4, 4, Tile::wood_Id, Tile::wood_Id, false); + generateBox(level, chunkBB, 1, 2, 5, 7, 4, 5, Tile::wood_Id, Tile::wood_Id, false); + generateBox(level, chunkBB, 8, 2, 1, 8, 4, 4, Tile::wood_Id, Tile::wood_Id, false); + generateBox(level, chunkBB, 1, 2, 0, 7, 4, 0, Tile::wood_Id, Tile::wood_Id, false); + + // windows + placeBlock(level, Tile::thinGlass_Id, 0, 4, 2, 0, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 5, 2, 0, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 6, 2, 0, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 4, 3, 0, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 5, 3, 0, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 6, 3, 0, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 0, 2, 2, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 0, 2, 3, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 0, 3, 2, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 0, 3, 3, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 8, 2, 2, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 8, 2, 3, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 8, 3, 2, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 8, 3, 3, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 2, 2, 5, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 3, 2, 5, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 5, 2, 5, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 6, 2, 5, chunkBB); + + // roof inside and bookshelf + generateBox(level, chunkBB, 1, 4, 1, 7, 4, 1, Tile::wood_Id, Tile::wood_Id, false); + generateBox(level, chunkBB, 1, 4, 4, 7, 4, 4, Tile::wood_Id, Tile::wood_Id, false); + generateBox(level, chunkBB, 1, 3, 4, 7, 3, 4, Tile::bookshelf_Id, Tile::bookshelf_Id, false); + + // couch + placeBlock(level, Tile::wood_Id, 0, 7, 1, 4, chunkBB); + placeBlock(level, Tile::stairs_wood_Id, getOrientationData(Tile::stairs_wood_Id, 0), 7, 1, 3, chunkBB); + int orientationData = getOrientationData(Tile::stairs_wood_Id, 3); + placeBlock(level, Tile::stairs_wood_Id, orientationData, 6, 1, 4, chunkBB); + placeBlock(level, Tile::stairs_wood_Id, orientationData, 5, 1, 4, chunkBB); + placeBlock(level, Tile::stairs_wood_Id, orientationData, 4, 1, 4, chunkBB); + placeBlock(level, Tile::stairs_wood_Id, orientationData, 3, 1, 4, chunkBB); + + // tables + placeBlock(level, Tile::fence_Id, 0, 6, 1, 3, chunkBB); + placeBlock(level, Tile::pressurePlate_wood_Id, 0, 6, 2, 3, chunkBB); + placeBlock(level, Tile::fence_Id, 0, 4, 1, 3, chunkBB); + placeBlock(level, Tile::pressurePlate_wood_Id, 0, 4, 2, 3, chunkBB); + placeBlock(level, Tile::workBench_Id, 0, 7, 1, 1, chunkBB); + + // entrance + placeBlock(level, 0, 0, 1, 1, 0, chunkBB); + placeBlock(level, 0, 0, 1, 2, 0, chunkBB); + createDoor(level, chunkBB, random, 1, 1, 0, getOrientationData(Tile::door_wood_Id, 1)); + if (getBlock(level, 1, 0, -1, chunkBB) == 0 && getBlock(level, 1, -1, -1, chunkBB) != 0) + { + placeBlock(level, Tile::stairs_stone_Id, getOrientationData(Tile::stairs_stone_Id, 3), 1, 0, -1, chunkBB); + } + + for (int z = 0; z < depth; z++) + { + for (int x = 0; x < width; x++) + { + generateAirColumnUp(level, x, height, z, chunkBB); + fillColumnDown(level, Tile::stoneBrick_Id, 0, x, -1, z, chunkBB); + } + } + + spawnVillagers(level, chunkBB, 2, 1, 2, 1); + + return true; + +} + +int VillagePieces::BookHouse::getVillagerProfession(int villagerNumber) +{ + return Villager::PROFESSION_LIBRARIAN; +} + +VillagePieces::SmallHut::SmallHut(StartPiece *startPiece, int genDepth, Random *random, BoundingBox *stairsBox, int direction) : VillagePiece(startPiece, genDepth), lowCeiling(random->nextBoolean()), tablePlacement(random->nextInt(3)) +{ + heightPosition = -1; // 4J added initialiser + + orientation = direction; + boundingBox = stairsBox; +} + +VillagePieces::SmallHut *VillagePieces::SmallHut::createPiece(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth) +{ + BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, 0, 0, 0, width, height, depth, direction); + + if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL) + { + delete box; + return NULL; + } + + return new SmallHut(startPiece, genDepth, random, box, direction); +} + +bool VillagePieces::SmallHut::postProcess(Level *level, Random *random, BoundingBox *chunkBB) +{ + if (heightPosition < 0) + { + heightPosition = getAverageGroundHeight(level, chunkBB); + if (heightPosition < 0) + { + return true; + } + boundingBox->move(0, heightPosition - boundingBox->y1 + height - 1, 0); + } + + // fill inside with air + generateBox(level, chunkBB, 1, 1, 1, 3, 5, 4, 0, 0, false); + + // floor + generateBox(level, chunkBB, 0, 0, 0, 3, 0, 4, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false); + generateBox(level, chunkBB, 1, 0, 1, 2, 0, 3, Tile::dirt_Id, Tile::dirt_Id, false); + // roof + if (lowCeiling) { + generateBox(level, chunkBB, 1, 4, 1, 2, 4, 3, Tile::treeTrunk_Id, Tile::treeTrunk_Id, false); + } else { + generateBox(level, chunkBB, 1, 5, 1, 2, 5, 3, Tile::treeTrunk_Id, Tile::treeTrunk_Id, false); + } + placeBlock(level, Tile::treeTrunk_Id, 0, 1, 4, 0, chunkBB); + placeBlock(level, Tile::treeTrunk_Id, 0, 2, 4, 0, chunkBB); + placeBlock(level, Tile::treeTrunk_Id, 0, 1, 4, 4, chunkBB); + placeBlock(level, Tile::treeTrunk_Id, 0, 2, 4, 4, chunkBB); + placeBlock(level, Tile::treeTrunk_Id, 0, 0, 4, 1, chunkBB); + placeBlock(level, Tile::treeTrunk_Id, 0, 0, 4, 2, chunkBB); + placeBlock(level, Tile::treeTrunk_Id, 0, 0, 4, 3, chunkBB); + placeBlock(level, Tile::treeTrunk_Id, 0, 3, 4, 1, chunkBB); + placeBlock(level, Tile::treeTrunk_Id, 0, 3, 4, 2, chunkBB); + placeBlock(level, Tile::treeTrunk_Id, 0, 3, 4, 3, chunkBB); + + // corners + generateBox(level, chunkBB, 0, 1, 0, 0, 3, 0, Tile::treeTrunk_Id, Tile::treeTrunk_Id, false); + generateBox(level, chunkBB, 3, 1, 0, 3, 3, 0, Tile::treeTrunk_Id, Tile::treeTrunk_Id, false); + generateBox(level, chunkBB, 0, 1, 4, 0, 3, 4, Tile::treeTrunk_Id, Tile::treeTrunk_Id, false); + generateBox(level, chunkBB, 3, 1, 4, 3, 3, 4, Tile::treeTrunk_Id, Tile::treeTrunk_Id, false); + + // wooden walls + generateBox(level, chunkBB, 0, 1, 1, 0, 3, 3, Tile::wood_Id, Tile::wood_Id, false); + generateBox(level, chunkBB, 3, 1, 1, 3, 3, 3, Tile::wood_Id, Tile::wood_Id, false); + generateBox(level, chunkBB, 1, 1, 0, 2, 3, 0, Tile::wood_Id, Tile::wood_Id, false); + generateBox(level, chunkBB, 1, 1, 4, 2, 3, 4, Tile::wood_Id, Tile::wood_Id, false); + + // windows + placeBlock(level, Tile::thinGlass_Id, 0, 0, 2, 2, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 3, 2, 2, chunkBB); + + // table + if (tablePlacement > 0) { + placeBlock(level, Tile::fence_Id, 0, tablePlacement, 1, 3, chunkBB); + placeBlock(level, Tile::pressurePlate_wood_Id, 0, tablePlacement, 2, 3, chunkBB); + } + + // entrance + placeBlock(level, 0, 0, 1, 1, 0, chunkBB); + placeBlock(level, 0, 0, 1, 2, 0, chunkBB); + createDoor(level, chunkBB, random, 1, 1, 0, getOrientationData(Tile::door_wood_Id, 1)); + if (getBlock(level, 1, 0, -1, chunkBB) == 0 && getBlock(level, 1, -1, -1, chunkBB) != 0) + { + placeBlock(level, Tile::stairs_stone_Id, getOrientationData(Tile::stairs_stone_Id, 3), 1, 0, -1, chunkBB); + } + + for (int z = 0; z < depth; z++) + { + for (int x = 0; x < width; x++) + { + generateAirColumnUp(level, x, height, z, chunkBB); + fillColumnDown(level, Tile::stoneBrick_Id, 0, x, -1, z, chunkBB); + } + } + + spawnVillagers(level, chunkBB, 1, 1, 2, 1); + + return true; + +} + +VillagePieces::PigHouse::PigHouse(StartPiece *startPiece, int genDepth, Random *random, BoundingBox *stairsBox, int direction) : VillagePiece(startPiece, genDepth) +{ + heightPosition = -1; // 4J added initialiser + orientation = direction; + boundingBox = stairsBox; +} + +VillagePieces::PigHouse *VillagePieces::PigHouse::createPiece(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth) +{ + + BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, 0, 0, 0, width, height, depth, direction); + + if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL) + { + delete box; + return NULL; + } + + return new PigHouse(startPiece, genDepth, random, box, direction); +} + +bool VillagePieces::PigHouse::postProcess(Level *level, Random *random, BoundingBox *chunkBB) +{ + if (heightPosition < 0) + { + heightPosition = getAverageGroundHeight(level, chunkBB); + if (heightPosition < 0) + { + return true; + } + boundingBox->move(0, heightPosition - boundingBox->y1 + height - 1, 0); + } + + // fill inside with air + generateBox(level, chunkBB, 1, 1, 1, 7, 4, 4, 0, 0, false); + generateBox(level, chunkBB, 2, 1, 6, 8, 4, 10, 0, 0, false); + + // pig floor + generateBox(level, chunkBB, 2, 0, 6, 8, 0, 10, Tile::dirt_Id, Tile::dirt_Id, false); + placeBlock(level, Tile::stoneBrick_Id, 0, 6, 0, 6, chunkBB); + // pig fence + generateBox(level, chunkBB, 2, 1, 6, 2, 1, 10, Tile::fence_Id, Tile::fence_Id, false); + generateBox(level, chunkBB, 8, 1, 6, 8, 1, 10, Tile::fence_Id, Tile::fence_Id, false); + generateBox(level, chunkBB, 3, 1, 10, 7, 1, 10, Tile::fence_Id, Tile::fence_Id, false); + + // floor + generateBox(level, chunkBB, 1, 0, 1, 7, 0, 4, Tile::wood_Id, Tile::wood_Id, false); + generateBox(level, chunkBB, 0, 0, 0, 0, 3, 5, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false); + generateBox(level, chunkBB, 8, 0, 0, 8, 3, 5, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false); + generateBox(level, chunkBB, 1, 0, 0, 7, 1, 0, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false); + generateBox(level, chunkBB, 1, 0, 5, 7, 1, 5, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false); + + // roof + generateBox(level, chunkBB, 1, 2, 0, 7, 3, 0, Tile::wood_Id, Tile::wood_Id, false); + generateBox(level, chunkBB, 1, 2, 5, 7, 3, 5, Tile::wood_Id, Tile::wood_Id, false); + generateBox(level, chunkBB, 0, 4, 1, 8, 4, 1, Tile::wood_Id, Tile::wood_Id, false); + generateBox(level, chunkBB, 0, 4, 4, 8, 4, 4, Tile::wood_Id, Tile::wood_Id, false); + generateBox(level, chunkBB, 0, 5, 2, 8, 5, 3, Tile::wood_Id, Tile::wood_Id, false); + placeBlock(level, Tile::wood_Id, 0, 0, 4, 2, chunkBB); + placeBlock(level, Tile::wood_Id, 0, 0, 4, 3, chunkBB); + placeBlock(level, Tile::wood_Id, 0, 8, 4, 2, chunkBB); + placeBlock(level, Tile::wood_Id, 0, 8, 4, 3, chunkBB); + + int southStairs = getOrientationData(Tile::stairs_wood_Id, 3); + int northStairs = getOrientationData(Tile::stairs_wood_Id, 2); + for (int d = -1; d <= 2; d++) + { + for (int w = 0; w <= 8; w++) + { + placeBlock(level, Tile::stairs_wood_Id, southStairs, w, 4 + d, d, chunkBB); + placeBlock(level, Tile::stairs_wood_Id, northStairs, w, 4 + d, 5 - d, chunkBB); + } + } + + // windows etc + placeBlock(level, Tile::treeTrunk_Id, 0, 0, 2, 1, chunkBB); + placeBlock(level, Tile::treeTrunk_Id, 0, 0, 2, 4, chunkBB); + placeBlock(level, Tile::treeTrunk_Id, 0, 8, 2, 1, chunkBB); + placeBlock(level, Tile::treeTrunk_Id, 0, 8, 2, 4, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 0, 2, 2, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 0, 2, 3, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 8, 2, 2, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 8, 2, 3, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 2, 2, 5, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 3, 2, 5, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 5, 2, 0, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 6, 2, 5, chunkBB); + + // table + placeBlock(level, Tile::fence_Id, 0, 2, 1, 3, chunkBB); + placeBlock(level, Tile::pressurePlate_wood_Id, 0, 2, 2, 3, chunkBB); + placeBlock(level, Tile::wood_Id, 0, 1, 1, 4, chunkBB); + placeBlock(level, Tile::stairs_wood_Id, getOrientationData(Tile::stairs_wood_Id, 3), 2, 1, 4, chunkBB); + placeBlock(level, Tile::stairs_wood_Id, getOrientationData(Tile::stairs_wood_Id, 1), 1, 1, 3, chunkBB); + + // butcher table + generateBox(level, chunkBB, 5, 0, 1, 7, 0, 3, Tile::stoneSlab_Id, Tile::stoneSlab_Id, false); + placeBlock(level, Tile::stoneSlab_Id, 0, 6, 1, 1, chunkBB); + placeBlock(level, Tile::stoneSlab_Id, 0, 6, 1, 2, chunkBB); + + // entrance + placeBlock(level, 0, 0, 2, 1, 0, chunkBB); + placeBlock(level, 0, 0, 2, 2, 0, chunkBB); + placeBlock(level, Tile::torch_Id, 0, 2, 3, 1, chunkBB); + createDoor(level, chunkBB, random, 2, 1, 0, getOrientationData(Tile::door_wood_Id, 1)); + if (getBlock(level, 2, 0, -1, chunkBB) == 0 && getBlock(level, 2, -1, -1, chunkBB) != 0) + { + placeBlock(level, Tile::stairs_stone_Id, getOrientationData(Tile::stairs_stone_Id, 3), 2, 0, -1, chunkBB); + } + + // pig entrance + placeBlock(level, 0, 0, 6, 1, 5, chunkBB); + placeBlock(level, 0, 0, 6, 2, 5, chunkBB); + placeBlock(level, Tile::torch_Id, 0, 6, 3, 4, chunkBB); + createDoor(level, chunkBB, random, 6, 1, 5, getOrientationData(Tile::door_wood_Id, 1)); + + for (int z = 0; z < 5; z++) + { + for (int x = 0; x < width; x++) + { + generateAirColumnUp(level, x, height, z, chunkBB); + fillColumnDown(level, Tile::stoneBrick_Id, 0, x, -1, z, chunkBB); + } + } + + spawnVillagers(level, chunkBB, 4, 1, 2, 2); + + return true; + +} + +int VillagePieces::PigHouse::getVillagerProfession(int villagerNumber) +{ + if (villagerNumber == 0) + { + return Villager::PROFESSION_BUTCHER; + } + return Villager::PROFESSION_FARMER; +} + +VillagePieces::TwoRoomHouse::TwoRoomHouse(StartPiece *startPiece, int genDepth, Random *random, BoundingBox *stairsBox, int direction) : VillagePiece(startPiece, genDepth) +{ + heightPosition = -1; // 4J added initialiser + + orientation = direction; + boundingBox = stairsBox; +} + +VillagePieces::TwoRoomHouse *VillagePieces::TwoRoomHouse::createPiece(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth) +{ + BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, 0, 0, 0, width, height, depth, direction); + + if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL) + { + delete box; + return NULL; + } + + return new TwoRoomHouse(startPiece, genDepth, random, box, direction); +} + +bool VillagePieces::TwoRoomHouse::postProcess(Level *level, Random *random, BoundingBox *chunkBB) +{ + if (heightPosition < 0) + { + heightPosition = getAverageGroundHeight(level, chunkBB); + if (heightPosition < 0) + { + return true; + } + boundingBox->move(0, heightPosition - boundingBox->y1 + height - 1, 0); + } + + // fill inside with air + generateBox(level, chunkBB, 1, 1, 1, 7, 4, 4, 0, 0, false); + generateBox(level, chunkBB, 2, 1, 6, 8, 4, 10, 0, 0, false); + + // floor + generateBox(level, chunkBB, 2, 0, 5, 8, 0, 10, Tile::wood_Id, Tile::wood_Id, false); + generateBox(level, chunkBB, 1, 0, 1, 7, 0, 4, Tile::wood_Id, Tile::wood_Id, false); + generateBox(level, chunkBB, 0, 0, 0, 0, 3, 5, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false); + generateBox(level, chunkBB, 8, 0, 0, 8, 3, 10, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false); + generateBox(level, chunkBB, 1, 0, 0, 7, 2, 0, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false); + generateBox(level, chunkBB, 1, 0, 5, 2, 1, 5, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false); + generateBox(level, chunkBB, 2, 0, 6, 2, 3, 10, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false); + generateBox(level, chunkBB, 3, 0, 10, 7, 3, 10, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false); + + // room 1 roof + generateBox(level, chunkBB, 1, 2, 0, 7, 3, 0, Tile::wood_Id, Tile::wood_Id, false); + generateBox(level, chunkBB, 1, 2, 5, 2, 3, 5, Tile::wood_Id, Tile::wood_Id, false); + generateBox(level, chunkBB, 0, 4, 1, 8, 4, 1, Tile::wood_Id, Tile::wood_Id, false); + generateBox(level, chunkBB, 0, 4, 4, 3, 4, 4, Tile::wood_Id, Tile::wood_Id, false); + generateBox(level, chunkBB, 0, 5, 2, 8, 5, 3, Tile::wood_Id, Tile::wood_Id, false); + placeBlock(level, Tile::wood_Id, 0, 0, 4, 2, chunkBB); + placeBlock(level, Tile::wood_Id, 0, 0, 4, 3, chunkBB); + placeBlock(level, Tile::wood_Id, 0, 8, 4, 2, chunkBB); + placeBlock(level, Tile::wood_Id, 0, 8, 4, 3, chunkBB); + placeBlock(level, Tile::wood_Id, 0, 8, 4, 4, chunkBB); + + int southStairs = getOrientationData(Tile::stairs_wood_Id, 3); + int northStairs = getOrientationData(Tile::stairs_wood_Id, 2); + for (int d = -1; d <= 2; d++) + { + for (int w = 0; w <= 8; w++) + { + placeBlock(level, Tile::stairs_wood_Id, southStairs, w, 4 + d, d, chunkBB); + if ((d > -1 || w <= 1) && (d > 0 || w <= 3) && (d > 1 || w <= 4 || w >= 6)) { + placeBlock(level, Tile::stairs_wood_Id, northStairs, w, 4 + d, 5 - d, chunkBB); + } + } + } + + // room 2 roof + generateBox(level, chunkBB, 3, 4, 5, 3, 4, 10, Tile::wood_Id, Tile::wood_Id, false); + generateBox(level, chunkBB, 7, 4, 2, 7, 4, 10, Tile::wood_Id, Tile::wood_Id, false); + generateBox(level, chunkBB, 4, 5, 4, 4, 5, 10, Tile::wood_Id, Tile::wood_Id, false); + generateBox(level, chunkBB, 6, 5, 4, 6, 5, 10, Tile::wood_Id, Tile::wood_Id, false); + generateBox(level, chunkBB, 5, 6, 3, 5, 6, 10, Tile::wood_Id, Tile::wood_Id, false); + int westStairs = getOrientationData(Tile::stairs_wood_Id, 0); + for (int w = 4; w >= 1; w--) + { + placeBlock(level, Tile::wood_Id, 0, w, 2 + w, 7 - w, chunkBB); + for (int d = 8 - w; d <= 10; d++) + { + placeBlock(level, Tile::stairs_wood_Id, westStairs, w, 2 + w, d, chunkBB); + } + } + int eastStairs = getOrientationData(Tile::stairs_wood_Id, 1); + placeBlock(level, Tile::wood_Id, 0, 6, 6, 3, chunkBB); + placeBlock(level, Tile::wood_Id, 0, 7, 5, 4, chunkBB); + placeBlock(level, Tile::stairs_wood_Id, eastStairs, 6, 6, 4, chunkBB); + for (int w = 6; w <= 8; w++) + { + for (int d = 5; d <= 10; d++) + { + placeBlock(level, Tile::stairs_wood_Id, eastStairs, w, 12 - w, d, chunkBB); + } + } + + // windows etc + placeBlock(level, Tile::treeTrunk_Id, 0, 0, 2, 1, chunkBB); + placeBlock(level, Tile::treeTrunk_Id, 0, 0, 2, 4, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 0, 2, 2, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 0, 2, 3, chunkBB); + + placeBlock(level, Tile::treeTrunk_Id, 0, 4, 2, 0, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 5, 2, 0, chunkBB); + placeBlock(level, Tile::treeTrunk_Id, 0, 6, 2, 0, chunkBB); + + placeBlock(level, Tile::treeTrunk_Id, 0, 8, 2, 1, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 8, 2, 2, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 8, 2, 3, chunkBB); + placeBlock(level, Tile::treeTrunk_Id, 0, 8, 2, 4, chunkBB); + placeBlock(level, Tile::wood_Id, 0, 8, 2, 5, chunkBB); + placeBlock(level, Tile::treeTrunk_Id, 0, 8, 2, 6, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 8, 2, 7, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 8, 2, 8, chunkBB); + placeBlock(level, Tile::treeTrunk_Id, 0, 8, 2, 9, chunkBB); + placeBlock(level, Tile::treeTrunk_Id, 0, 2, 2, 6, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 2, 2, 7, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 2, 2, 8, chunkBB); + placeBlock(level, Tile::treeTrunk_Id, 0, 2, 2, 9, chunkBB); + + placeBlock(level, Tile::treeTrunk_Id, 0, 4, 4, 10, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 5, 4, 10, chunkBB); + placeBlock(level, Tile::treeTrunk_Id, 0, 6, 4, 10, chunkBB); + placeBlock(level, Tile::wood_Id, 0, 5, 5, 10, chunkBB); + + // entrance + placeBlock(level, 0, 0, 2, 1, 0, chunkBB); + placeBlock(level, 0, 0, 2, 2, 0, chunkBB); + placeBlock(level, Tile::torch_Id, 0, 2, 3, 1, chunkBB); + createDoor(level, chunkBB, random, 2, 1, 0, getOrientationData(Tile::door_wood_Id, 1)); + generateBox(level, chunkBB, 1, 0, -1, 3, 2, -1, 0, 0, false); + if (getBlock(level, 2, 0, -1, chunkBB) == 0 && getBlock(level, 2, -1, -1, chunkBB) != 0) { + placeBlock(level, Tile::stairs_stone_Id, getOrientationData(Tile::stairs_stone_Id, 3), 2, 0, -1, chunkBB); + } + + for (int z = 0; z < 5; z++) + { + for (int x = 0; x < width; x++) + { + generateAirColumnUp(level, x, height, z, chunkBB); + fillColumnDown(level, Tile::stoneBrick_Id, 0, x, -1, z, chunkBB); + } + } + for (int z = 5; z < depth - 1; z++) + { + for (int x = 2; x < width; x++) + { + generateAirColumnUp(level, x, height, z, chunkBB); + fillColumnDown(level, Tile::stoneBrick_Id, 0, x, -1, z, chunkBB); + } + } + + spawnVillagers(level, chunkBB, 4, 1, 2, 2); + + return true; + +} + +void VillagePieces::Smithy::staticCtor() +{ + treasureItems = WeighedTreasureArray(13); + treasureItems[0] = new WeighedTreasure(Item::diamond_Id, 0, 1, 3, 3); + treasureItems[1] = new WeighedTreasure(Item::ironIngot_Id, 0, 1, 5, 10); + treasureItems[2] = new WeighedTreasure(Item::goldIngot_Id, 0, 1, 3, 5); + treasureItems[3] = new WeighedTreasure(Item::bread_Id, 0, 1, 3, 15); + treasureItems[4] = new WeighedTreasure(Item::apple_Id, 0, 1, 3, 15); + treasureItems[5] = new WeighedTreasure(Item::pickAxe_iron_Id, 0, 1, 1, 5); + treasureItems[6] = new WeighedTreasure(Item::sword_iron_Id, 0, 1, 1, 5); + treasureItems[7] = new WeighedTreasure(Item::chestplate_iron_Id, 0, 1, 1, 5); + treasureItems[8] = new WeighedTreasure(Item::helmet_iron_Id, 0, 1, 1, 5); + treasureItems[9] = new WeighedTreasure(Item::leggings_iron_Id, 0, 1, 1, 5); + treasureItems[10] = new WeighedTreasure(Item::boots_iron_Id, 0, 1, 1, 5); + treasureItems[11] = new WeighedTreasure(Tile::obsidian_Id, 0, 3, 7, 5); + treasureItems[12] = new WeighedTreasure(Tile::sapling_Id, 0, 3, 7, 5); +} + +VillagePieces::Smithy::Smithy(StartPiece *startPiece, int genDepth, Random *random, BoundingBox *stairsBox, int direction) : VillagePiece(startPiece, genDepth) +{ + heightPosition = -1; // 4J added initialiser + hasPlacedChest = false; + + orientation = direction; + boundingBox = stairsBox; +} + +VillagePieces::Smithy *VillagePieces::Smithy::createPiece(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth) +{ + BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, 0, 0, 0, width, height, depth, direction); + + if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL) + { + delete box; + return NULL; + } + + return new Smithy(startPiece, genDepth, random, box, direction); +} + +bool VillagePieces::Smithy::postProcess(Level *level, Random *random, BoundingBox *chunkBB) +{ + if (heightPosition < 0) + { + heightPosition = getAverageGroundHeight(level, chunkBB); + if (heightPosition < 0) + { + return true; + } + boundingBox->move(0, heightPosition - boundingBox->y1 + height - 1, 0); + } + + // fill inside with air + generateBox(level, chunkBB, 0, 1, 0, 9, 4, 6, 0, 0, false); + + // floor + generateBox(level, chunkBB, 0, 0, 0, 9, 0, 6, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false); + + // roof + generateBox(level, chunkBB, 0, 4, 0, 9, 4, 6, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false); + generateBox(level, chunkBB, 0, 5, 0, 9, 5, 6, Tile::stoneSlabHalf_Id, Tile::stoneSlabHalf_Id, false); + generateBox(level, chunkBB, 1, 5, 1, 8, 5, 5, 0, 0, false); + + // room walls + generateBox(level, chunkBB, 1, 1, 0, 2, 3, 0, Tile::wood_Id, Tile::wood_Id, false); + generateBox(level, chunkBB, 0, 1, 0, 0, 4, 0, Tile::treeTrunk_Id, Tile::treeTrunk_Id, false); + generateBox(level, chunkBB, 3, 1, 0, 3, 4, 0, Tile::treeTrunk_Id, Tile::treeTrunk_Id, false); + generateBox(level, chunkBB, 0, 1, 6, 0, 4, 6, Tile::treeTrunk_Id, Tile::treeTrunk_Id, false); + placeBlock(level, Tile::wood_Id, 0, 3, 3, 1, chunkBB); + generateBox(level, chunkBB, 3, 1, 2, 3, 3, 2, Tile::wood_Id, Tile::wood_Id, false); + generateBox(level, chunkBB, 4, 1, 3, 5, 3, 3, Tile::wood_Id, Tile::wood_Id, false); + generateBox(level, chunkBB, 0, 1, 1, 0, 3, 5, Tile::wood_Id, Tile::wood_Id, false); + generateBox(level, chunkBB, 1, 1, 6, 5, 3, 6, Tile::wood_Id, Tile::wood_Id, false); + + // pillars + generateBox(level, chunkBB, 5, 1, 0, 5, 3, 0, Tile::fence_Id, Tile::fence_Id, false); + generateBox(level, chunkBB, 9, 1, 0, 9, 3, 0, Tile::fence_Id, Tile::fence_Id, false); + + // furnace + generateBox(level, chunkBB, 6, 1, 4, 9, 4, 6, Tile::stoneBrick_Id, Tile::stoneBrick_Id, false); + placeBlock(level, Tile::lava_Id, 0, 7, 1, 5, chunkBB); + placeBlock(level, Tile::lava_Id, 0, 8, 1, 5, chunkBB); + placeBlock(level, Tile::ironFence_Id, 0, 9, 2, 5, chunkBB); + placeBlock(level, Tile::ironFence_Id, 0, 9, 2, 4, chunkBB); + generateBox(level, chunkBB, 7, 2, 4, 8, 2, 5, 0, 0, false); + placeBlock(level, Tile::stoneBrick_Id, 0, 6, 1, 3, chunkBB); + placeBlock(level, Tile::furnace_Id, 0, 6, 2, 3, chunkBB); + placeBlock(level, Tile::furnace_Id, 0, 6, 3, 3, chunkBB); + placeBlock(level, Tile::stoneSlab_Id, 0, 8, 1, 1, chunkBB); + + // windows etc + placeBlock(level, Tile::thinGlass_Id, 0, 0, 2, 2, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 0, 2, 4, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 2, 2, 6, chunkBB); + placeBlock(level, Tile::thinGlass_Id, 0, 4, 2, 6, chunkBB); + + // table + placeBlock(level, Tile::fence_Id, 0, 2, 1, 4, chunkBB); + placeBlock(level, Tile::pressurePlate_wood_Id, 0, 2, 2, 4, chunkBB); + placeBlock(level, Tile::wood_Id, 0, 1, 1, 5, chunkBB); + placeBlock(level, Tile::stairs_wood_Id, getOrientationData(Tile::stairs_wood_Id, 3), 2, 1, 5, chunkBB); + placeBlock(level, Tile::stairs_wood_Id, getOrientationData(Tile::stairs_wood_Id, 1), 1, 1, 4, chunkBB); + + if (!hasPlacedChest) + { + int y = getWorldY(1); + int x = getWorldX(5, 5), z = getWorldZ(5, 5); + if (chunkBB->isInside(x, y, z)) + { + hasPlacedChest = true; + createChest(level, chunkBB, random, 5, 1, 5, treasureItems, 3 + random->nextInt(6)); + } + } + + // entrance + for (int x = 6; x <= 8; x++) + { + if (getBlock(level, x, 0, -1, chunkBB) == 0 && getBlock(level, x, -1, -1, chunkBB) != 0 ) + { + placeBlock(level, Tile::stairs_stone_Id, getOrientationData(Tile::stairs_stone_Id, 3), x, 0, -1, chunkBB); + } + } + + for (int z = 0; z < depth; z++) + { + for (int x = 0; x < width; x++) + { + generateAirColumnUp(level, x, height, z, chunkBB); + fillColumnDown(level, Tile::stoneBrick_Id, 0, x, -1, z, chunkBB); + } + } + + spawnVillagers(level, chunkBB, 7, 1, 1, 1); + + return true; + +} + +int VillagePieces::Smithy::getVillagerProfession(int villagerNumber) +{ + return Villager::PROFESSION_SMITH; +} + +VillagePieces::Farmland::Farmland(StartPiece *startPiece, int genDepth, Random *random, BoundingBox *stairsBox, int direction) : VillagePiece(startPiece, genDepth) +{ + heightPosition = -1; // 4J added initialiser + orientation = direction; + boundingBox = stairsBox; + + cropsA = selectCrops(random); + cropsB = selectCrops(random); +} + +int VillagePieces::Farmland::selectCrops(Random *random) +{ + switch (random->nextInt(5)) + { + default: + return Tile::crops_Id; + case 0: + return Tile::carrots_Id; + case 1: + return Tile::potatoes_Id; + } +} + +VillagePieces::Farmland *VillagePieces::Farmland::createPiece(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth) +{ + BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, 0, 0, 0, width, height, depth, direction); + + if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL) + { + delete box; + return NULL; + } + + return new Farmland(startPiece, genDepth, random, box, direction); +} + +bool VillagePieces::Farmland::postProcess(Level *level, Random *random, BoundingBox *chunkBB) +{ + if (heightPosition < 0) + { + heightPosition = getAverageGroundHeight(level, chunkBB); + if (heightPosition < 0) + { + return true; + } + boundingBox->move(0, heightPosition - boundingBox->y1 + height - 1, 0); + } + + // fill inside with air + generateBox(level, chunkBB, 0, 1, 0, 6, 4, 8, 0, 0, false); + + // farmlands + generateBox(level, chunkBB, 1, 0, 1, 2, 0, 7, Tile::farmland_Id, Tile::farmland_Id, false); + generateBox(level, chunkBB, 4, 0, 1, 5, 0, 7, Tile::farmland_Id, Tile::farmland_Id, false); + // walkpaths + generateBox(level, chunkBB, 0, 0, 0, 0, 0, 8, Tile::treeTrunk_Id, Tile::treeTrunk_Id, false); + generateBox(level, chunkBB, 6, 0, 0, 6, 0, 8, Tile::treeTrunk_Id, Tile::treeTrunk_Id, false); + generateBox(level, chunkBB, 1, 0, 0, 5, 0, 0, Tile::treeTrunk_Id, Tile::treeTrunk_Id, false); + generateBox(level, chunkBB, 1, 0, 8, 5, 0, 8, Tile::treeTrunk_Id, Tile::treeTrunk_Id, false); + // water + generateBox(level, chunkBB, 3, 0, 1, 3, 0, 7, Tile::water_Id, Tile::water_Id, false); + // crops + for (int d = 1; d <= 7; d++) + { + placeBlock(level, cropsA, Mth::nextInt(random, 2, 7), 1, 1, d, chunkBB); + placeBlock(level, cropsA, Mth::nextInt(random, 2, 7), 2, 1, d, chunkBB); + placeBlock(level, cropsB, Mth::nextInt(random, 2, 7), 4, 1, d, chunkBB); + placeBlock(level, cropsB, Mth::nextInt(random, 2, 7), 5, 1, d, chunkBB); + } + + for (int z = 0; z < depth; z++) + { + for (int x = 0; x < width; x++) + { + generateAirColumnUp(level, x, height, z, chunkBB); + fillColumnDown(level, Tile::dirt_Id, 0, x, -1, z, chunkBB); + } + } + + return true; + +} + +VillagePieces::DoubleFarmland::DoubleFarmland(StartPiece *startPiece, int genDepth, Random *random, BoundingBox *stairsBox, int direction) : VillagePiece(startPiece, genDepth) +{ + heightPosition = -1; // 4J added initialiser + orientation = direction; + boundingBox = stairsBox; + + cropsA = selectCrops(random); + cropsB = selectCrops(random); + cropsC = selectCrops(random); + cropsD = selectCrops(random); +} + +int VillagePieces::DoubleFarmland::selectCrops(Random *random) +{ + switch (random->nextInt(5)) + { + default: + return Tile::crops_Id; + case 0: + return Tile::carrots_Id; + case 1: + return Tile::potatoes_Id; + } +} + +VillagePieces::DoubleFarmland *VillagePieces::DoubleFarmland::createPiece(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction, int genDepth) +{ + BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, 0, 0, 0, width, height, depth, direction); + + if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL) + { + delete box; + return NULL; + } + + return new DoubleFarmland(startPiece, genDepth, random, box, direction); +} + +bool VillagePieces::DoubleFarmland::postProcess(Level *level, Random *random, BoundingBox *chunkBB) +{ + if (heightPosition < 0) + { + heightPosition = getAverageGroundHeight(level, chunkBB); + if (heightPosition < 0) + { + return true; + } + boundingBox->move(0, heightPosition - boundingBox->y1 + height - 1, 0); + } + + // fill inside with air + generateBox(level, chunkBB, 0, 1, 0, 12, 4, 8, 0, 0, false); + + // farmlands + generateBox(level, chunkBB, 1, 0, 1, 2, 0, 7, Tile::farmland_Id, Tile::farmland_Id, false); + generateBox(level, chunkBB, 4, 0, 1, 5, 0, 7, Tile::farmland_Id, Tile::farmland_Id, false); + generateBox(level, chunkBB, 7, 0, 1, 8, 0, 7, Tile::farmland_Id, Tile::farmland_Id, false); + generateBox(level, chunkBB, 10, 0, 1, 11, 0, 7, Tile::farmland_Id, Tile::farmland_Id, false); + // walkpaths + generateBox(level, chunkBB, 0, 0, 0, 0, 0, 8, Tile::treeTrunk_Id, Tile::treeTrunk_Id, false); + generateBox(level, chunkBB, 6, 0, 0, 6, 0, 8, Tile::treeTrunk_Id, Tile::treeTrunk_Id, false); + generateBox(level, chunkBB, 12, 0, 0, 12, 0, 8, Tile::treeTrunk_Id, Tile::treeTrunk_Id, false); + generateBox(level, chunkBB, 1, 0, 0, 11, 0, 0, Tile::treeTrunk_Id, Tile::treeTrunk_Id, false); + generateBox(level, chunkBB, 1, 0, 8, 11, 0, 8, Tile::treeTrunk_Id, Tile::treeTrunk_Id, false); + // water + generateBox(level, chunkBB, 3, 0, 1, 3, 0, 7, Tile::water_Id, Tile::water_Id, false); + generateBox(level, chunkBB, 9, 0, 1, 9, 0, 7, Tile::water_Id, Tile::water_Id, false); + // crops + for (int d = 1; d <= 7; d++) + { + placeBlock(level, cropsA, Mth::nextInt(random, 2, 7), 1, 1, d, chunkBB); + placeBlock(level, cropsA, Mth::nextInt(random, 2, 7), 2, 1, d, chunkBB); + placeBlock(level, cropsB, Mth::nextInt(random, 2, 7), 4, 1, d, chunkBB); + placeBlock(level, cropsB, Mth::nextInt(random, 2, 7), 5, 1, d, chunkBB); + placeBlock(level, cropsC, Mth::nextInt(random, 2, 7), 7, 1, d, chunkBB); + placeBlock(level, cropsC, Mth::nextInt(random, 2, 7), 8, 1, d, chunkBB); + placeBlock(level, cropsD, Mth::nextInt(random, 2, 7), 10, 1, d, chunkBB); + placeBlock(level, cropsD, Mth::nextInt(random, 2, 7), 11, 1, d, chunkBB); + } + + for (int z = 0; z < depth; z++) + { + for (int x = 0; x < width; x++) + { + generateAirColumnUp(level, x, height, z, chunkBB); + fillColumnDown(level, Tile::dirt_Id, 0, x, -1, z, chunkBB); + } + } + + + return true; + +} + +VillagePieces::LightPost::LightPost(StartPiece *startPiece, int genDepth, Random *random, BoundingBox *box, int direction) : VillagePiece(startPiece, genDepth) +{ + heightPosition = -1; // 4J - added initialiser + orientation = direction; + boundingBox = box; +} + +BoundingBox *VillagePieces::LightPost::findPieceBox(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int footX, int footY, int footZ, int direction) +{ + BoundingBox *box = BoundingBox::orientBox(footX, footY, footZ, 0, 0, 0, width, height, depth, direction); + + if (!isOkBox(box, startPiece) || StructurePiece::findCollisionPiece(pieces, box) != NULL) + { + delete box; + return NULL; + } + + return box; +} + +bool VillagePieces::LightPost::postProcess(Level *level, Random *random, BoundingBox *chunkBB) +{ + if (heightPosition < 0) + { + heightPosition = getAverageGroundHeight(level, chunkBB); + if (heightPosition < 0) + { + return true; + } + boundingBox->move(0, heightPosition - boundingBox->y1 + height - 1, 0); + } + + // fill with air + generateBox(level, chunkBB, 0, 0, 0, 2, 3, 1, 0, 0, false); + + // pillar + placeBlock(level, Tile::fence_Id, 0, 1, 0, 0, chunkBB); + placeBlock(level, Tile::fence_Id, 0, 1, 1, 0, chunkBB); + placeBlock(level, Tile::fence_Id, 0, 1, 2, 0, chunkBB); + + // head + placeBlock(level, Tile::cloth_Id, DyePowderItem::WHITE, 1, 3, 0, chunkBB); + + // torches + placeBlock(level, Tile::torch_Id, 0, 0, 3, 0, chunkBB); + placeBlock(level, Tile::torch_Id, 0, 1, 3, 1, chunkBB); + placeBlock(level, Tile::torch_Id, 0, 2, 3, 0, chunkBB); + placeBlock(level, Tile::torch_Id, 0, 1, 3, -1, chunkBB); + + return true; +} |
