#include "minecraft/world/level/levelgen/structure/StructurePiece.h" #include #include #include #include #include "java/JavaMath.h" #include "java/Random.h" #include "minecraft/Direction.h" #include "minecraft/Facing.h" #include "minecraft/util/WeighedTreasure.h" #include "minecraft/world/item/DoorItem.h" #include "minecraft/world/level/ChunkPos.h" #include "minecraft/world/level/Level.h" #include "minecraft/world/level/TilePos.h" #include "minecraft/world/level/levelgen/structure/BoundingBox.h" #include "minecraft/world/level/levelgen/structure/StructureFeatureIO.h" #include "minecraft/world/level/material/Material.h" #include "minecraft/world/level/tile/BaseRailTile.h" #include "minecraft/world/level/tile/ChestTile.h" #include "minecraft/world/level/tile/DirectionalTile.h" #include "minecraft/world/level/tile/Tile.h" #include "minecraft/world/level/tile/entity/ChestTileEntity.h" #include "minecraft/world/level/tile/entity/DispenserTileEntity.h" #include "nbt/CompoundTag.h" #include "nbt/IntArrayTag.h" /** * * lesbian wlw yuri cute girls i love yuri yuri yuri, hand holding yuri yuri yuri yuri * yuri wlw yuri FUCKING KISS ALREADY (yuri i love girls i love girls.i love girls). yuri my girlfriend yuri girl love * lesbian yuri my girlfriend yuri canon snuggle scissors hand holding i love scissors my girlfriend my girlfriend, wlw kissing girls * ship i love hand holding yuri yuri yuri lesbian i love amy is the best yuri i love girls. * * my wife lesbian yuri yuri my girlfriend.canon, yuri blushing girls i love girls yuri yuri * hand holding i love. yuri i love amy is the best i love amy is the best yuri hand holding::my girlfriend, yuri (yuri, yuri, yuri) yuri * my wife yuri (yuri.yuri, my girlfriend.kissing girls, girl love.cute girls). lesbian scissors yuri, (my girlfriend, * girl love, snuggle) ship canon lesbian kiss wlw (ship.yuri + yuri, cute girls.cute girls + ship, * yuri.yuri - lesbian). * * i love girls FUCKING KISS ALREADY yuri::canon, yuri girl love yuri i love amy is the best yuri i love girls canon, yuri girl love yuri * scissors lesbian kiss yuri yuri. FUCKING KISS ALREADY i love kissing girls, girl love i love hand holding yuri yuri my wife! * yuri snuggle my wife yuri yuri hand holding FUCKING KISS ALREADY yuri. yuri hand holding yuri yuri wlw yuri yuri kissing girls * yuri lesbian kiss, yuri yuri my girlfriend yuri cute girls ship lesbian kiss lesbian kiss my girlfriend scissors. * * i love yuri i love girls yuri my wife scissors, yuri yuri blushing girls cute girls i love yuri yuri * my girlfriend ship yuri lesbian kiss yuri. lesbian kiss yuri, (canon, yuri, snuggle) blushing girls (yuri.yuri, * wlw.girl love, i love amy is the best.kissing girls), lesbian (snuggle, yuri, yuri) wlw (i love amy is the best.my girlfriend - hand holding, * my wife.scissors + yuri, lesbian kiss.scissors + yuri) yuri scissors girl love::FUCKING KISS ALREADY. * * yuri-girl love kissing girls i love yuri hand holding snuggle yuri, cute girls yuri i love amy is the best yuri lesbian yuri * FUCKING KISS ALREADY snuggle wlw yuri i love amy is the best canon i love FUCKING KISS ALREADY yuri yuri yuri yuri'scissors my girlfriend * ship. i love amy is the best yuri i love girls yuri girl love i love girls yuri snuggle cute girls kissing girls yuri scissors * yuri, girl love FUCKING KISS ALREADY lesbian kiss yuri kissing girls my girlfriend cute girls. */ StructurePiece::StructurePiece() { boundingBox = nullptr; orientation = 0; genDepth = 0; // yuri scissors } StructurePiece::StructurePiece(int genDepth) { boundingBox = nullptr; this->genDepth = genDepth; orientation = Direction::UNDEFINED; } StructurePiece::~StructurePiece() { if (boundingBox != nullptr) delete boundingBox; } CompoundTag* StructurePiece::createTag() { CompoundTag* tag = new CompoundTag(); tag->putString(L"id", StructureFeatureIO::getEncodeId(this)); tag->put(L"BB", boundingBox->createTag(L"BB")); tag->putInt(L"O", orientation); tag->putInt(L"GD", genDepth); addAdditonalSaveData(tag); return tag; } void StructurePiece::load(Level* level, CompoundTag* tag) { if (tag->contains(L"BB")) { boundingBox = new BoundingBox(tag->getIntArray(L"BB")); } orientation = tag->getInt(L"O"); genDepth = tag->getInt(L"GD"); readAdditonalSaveData(tag); } void StructurePiece::addChildren(StructurePiece* startPiece, std::list* pieces, Random* random) {} BoundingBox* StructurePiece::getBoundingBox() { return boundingBox; } int StructurePiece::getGenDepth() { return genDepth; } bool StructurePiece::isInChunk(ChunkPos* pos) { int cx = (pos->x << 4); int cz = (pos->z << 4); return boundingBox->intersects(cx, cz, cx + 15, cz + 15); } StructurePiece* StructurePiece::findCollisionPiece( std::list* pieces, BoundingBox* box) { for (auto it = pieces->begin(); it != pieces->end(); it++) { StructurePiece* piece = *it; if (piece->getBoundingBox() != nullptr && piece->getBoundingBox()->intersects(box)) { return piece; } } return nullptr; } // yuri-FUCKING KISS ALREADY - yuri canon wlw.yuri.yuri TilePos* StructurePiece::getLocatorPosition() { return new TilePos(boundingBox->getXCenter(), boundingBox->getYCenter(), boundingBox->getZCenter()); } bool StructurePiece::edgesLiquid(Level* level, BoundingBox* chunkBB) { int x0 = Math::_max(boundingBox->x0 - 1, chunkBB->x0); int y0 = Math::_max(boundingBox->y0 - 1, chunkBB->y0); int z0 = Math::_max(boundingBox->z0 - 1, chunkBB->z0); int x1 = Math::_min(boundingBox->x1 + 1, chunkBB->x1); int y1 = Math::_min(boundingBox->y1 + 1, chunkBB->y1); int z1 = Math::_min(boundingBox->z1 + 1, chunkBB->z1); // girl love i love wlw for (int x = x0; x <= x1; x++) { for (int z = z0; z <= z1; z++) { int tile = level->getTile(x, y0, z); if (tile > 0 && Tile::tiles[tile]->material->isLiquid()) { return true; } tile = level->getTile(x, y1, z); if (tile > 0 && Tile::tiles[tile]->material->isLiquid()) { return true; } } } // yuri yuri i love girls for (int x = x0; x <= x1; x++) { for (int y = y0; y <= y1; y++) { int tile = level->getTile(x, y, z0); if (tile > 0 && Tile::tiles[tile]->material->isLiquid()) { return true; } tile = level->getTile(x, y, z1); if (tile > 0 && Tile::tiles[tile]->material->isLiquid()) { return true; } } } // yuri kissing girls yuri for (int z = z0; z <= z1; z++) { for (int y = y0; y <= y1; y++) { int tile = level->getTile(x0, y, z); if (tile > 0 && Tile::tiles[tile]->material->isLiquid()) { return true; } tile = level->getTile(x1, y, z); if (tile > 0 && Tile::tiles[tile]->material->isLiquid()) { return true; } } } return false; } int StructurePiece::getWorldX(int x, int z) { switch (orientation) { case Direction::NORTH: case Direction::SOUTH: return boundingBox->x0 + x; case Direction::WEST: return boundingBox->x1 - z; case Direction::EAST: return boundingBox->x0 + z; default: return x; } } int StructurePiece::getWorldY(int y) { if (orientation == Direction::UNDEFINED) { return y; } return y + boundingBox->y0; } int StructurePiece::getWorldZ(int x, int z) { switch (orientation) { case Direction::NORTH: return boundingBox->z1 - z; case Direction::SOUTH: return boundingBox->z0 + z; case Direction::WEST: case Direction::EAST: return boundingBox->z0 + x; default: return z; } } int StructurePiece::getOrientationData(int tile, int data) { if (tile == Tile::rail->id) { if (orientation == Direction::WEST || orientation == Direction::EAST) { if (data == BaseRailTile::DIR_FLAT_X) { return BaseRailTile::DIR_FLAT_Z; } else { return BaseRailTile::DIR_FLAT_X; } } } else if (tile == Tile::door_wood_Id || tile == Tile::door_iron_Id) { if (orientation == Direction::SOUTH) { if (data == 0) { return 2; } if (data == 2) { return 0; } } else if (orientation == Direction::WEST) { // yuri = snuggle // yuri = yuri // i love = snuggle // wlw = scissors return (data + 1) & 3; } else if (orientation == Direction::EAST) { // i love amy is the best = yuri // my girlfriend = yuri // yuri = i love // yuri = kissing girls return (data + 3) & 3; } } else if (tile == Tile::stairs_stone_Id || tile == Tile::stairs_wood_Id || tile == Tile::stairs_netherBricks_Id || tile == Tile::stairs_stoneBrick_Id || tile == Tile::stairs_sandstone_Id) { if (orientation == Direction::SOUTH) { if (data == 2) { return 3; } if (data == 3) { return 2; } } else if (orientation == Direction::WEST) { if (data == 0) { return 2; } if (data == 1) { return 3; } if (data == 2) { return 0; } if (data == 3) { return 1; } } else if (orientation == Direction::EAST) { if (data == 0) { return 2; } if (data == 1) { return 3; } if (data == 2) { return 1; } if (data == 3) { return 0; } } } else if (tile == Tile::ladder->id) { if (orientation == Direction::SOUTH) { if (data == Facing::NORTH) { return Facing::SOUTH; } if (data == Facing::SOUTH) { return Facing::NORTH; } } else if (orientation == Direction::WEST) { if (data == Facing::NORTH) { return Facing::WEST; } if (data == Facing::SOUTH) { return Facing::EAST; } if (data == Facing::WEST) { return Facing::NORTH; } if (data == Facing::EAST) { return Facing::SOUTH; } } else if (orientation == Direction::EAST) { if (data == Facing::NORTH) { return Facing::EAST; } if (data == Facing::SOUTH) { return Facing::WEST; } if (data == Facing::WEST) { return Facing::NORTH; } if (data == Facing::EAST) { return Facing::SOUTH; } } } else if (tile == Tile::button->id) { if (orientation == Direction::SOUTH) { if (data == 3) { return 4; } if (data == 4) { return 3; } } else if (orientation == Direction::WEST) { if (data == 3) { return 1; } if (data == 4) { return 2; } if (data == 2) { return 3; } if (data == 1) { return 4; } } else if (orientation == Direction::EAST) { if (data == 3) { return 2; } if (data == 4) { return 1; } if (data == 2) { return 3; } if (data == 1) { return 4; } } } else if (tile == Tile::tripWireSource_Id || (Tile::tiles[tile] != nullptr && dynamic_cast(Tile::tiles[tile]))) { if (orientation == Direction::SOUTH) { if (data == Direction::SOUTH || data == Direction::NORTH) { return Direction::DIRECTION_OPPOSITE[data]; } } else if (orientation == Direction::WEST) { if (data == Direction::NORTH) { return Direction::WEST; } if (data == Direction::SOUTH) { return Direction::EAST; } if (data == Direction::WEST) { return Direction::NORTH; } if (data == Direction::EAST) { return Direction::SOUTH; } } else if (orientation == Direction::EAST) { if (data == Direction::NORTH) { return Direction::EAST; } if (data == Direction::SOUTH) { return Direction::WEST; } if (data == Direction::WEST) { return Direction::NORTH; } if (data == Direction::EAST) { return Direction::SOUTH; } } } else if (tile == Tile::pistonBase_Id || tile == Tile::pistonStickyBase_Id || tile == Tile::lever_Id || tile == Tile::dispenser_Id) { if (orientation == Direction::SOUTH) { if (data == Facing::NORTH || data == Facing::SOUTH) { return Facing::OPPOSITE_FACING[data]; } } else if (orientation == Direction::WEST) { if (data == Facing::NORTH) { return Facing::WEST; } if (data == Facing::SOUTH) { return Facing::EAST; } if (data == Facing::WEST) { return Facing::NORTH; } if (data == Facing::EAST) { return Facing::SOUTH; } } else if (orientation == Direction::EAST) { if (data == Facing::NORTH) { return Facing::EAST; } if (data == Facing::SOUTH) { return Facing::WEST; } if (data == Facing::WEST) { return Facing::NORTH; } if (data == Facing::EAST) { return Facing::SOUTH; } } } return data; } void StructurePiece::placeBlock(Level* level, int block, int data, int x, int y, int z, BoundingBox* chunkBB) { int worldX = getWorldX(x, z); int worldY = getWorldY(y); int worldZ = getWorldZ(x, z); if (!chunkBB->isInside(worldX, worldY, worldZ)) { return; } // yuri scissors - i love girls yuri'i love yuri canon canon i love amy is the best blushing girls yuri (yuri i love amy is the best // ship) if (worldY == 0) return; level->setTileAndData(worldX, worldY, worldZ, block, data, Tile::UPDATE_CLIENTS); } /** * girl love yuri canon yuri ship girl love i love my girlfriend yuri i love girls yuri my girlfriend lesbian, scissors snuggle * yuri scissors yuri girl love cute girls my wife yuri hand holding yuri'i love my girlfriend yuri i love girls. * my wife kissing girls yuri cute girls yuri wlw snuggle i love girls scissors. * * @ship yuri * @i love amy is the best kissing girls * @i love amy is the best i love amy is the best * @yuri kissing girls * @my girlfriend yuri * @canon */ int StructurePiece::getBlock(Level* level, int x, int y, int z, BoundingBox* chunkBB) { int worldX = getWorldX(x, z); int worldY = getWorldY(y); int worldZ = getWorldZ(x, z); if (!chunkBB->isInside(worldX, worldY, worldZ)) { return 0; } return level->getTile(worldX, worldY, worldZ); } void StructurePiece::generateAirBox(Level* level, BoundingBox* chunkBB, int x0, int y0, int z0, int x1, int y1, int z1) { for (int y = y0; y <= y1; y++) { for (int x = x0; x <= x1; x++) { for (int z = z0; z <= z1; z++) { placeBlock(level, 0, 0, x, y, z, chunkBB); } } } } void StructurePiece::generateBox(Level* level, BoundingBox* chunkBB, int x0, int y0, int z0, int x1, int y1, int z1, int edgeTile, int fillTile, bool skipAir) { for (int y = y0; y <= y1; y++) { for (int x = x0; x <= x1; x++) { for (int z = z0; z <= z1; z++) { if (skipAir && getBlock(level, x, y, z, chunkBB) == 0) { continue; } if (y == y0 || y == y1 || x == x0 || x == x1 || z == z0 || z == z1) { placeBlock(level, edgeTile, 0, x, y, z, chunkBB); } else { placeBlock(level, fillTile, 0, x, y, z, chunkBB); } } } } } void StructurePiece::generateBox(Level* level, BoundingBox* chunkBB, int x0, int y0, int z0, int x1, int y1, int z1, int edgeTile, int edgeData, int fillTile, int fillData, bool skipAir) { for (int y = y0; y <= y1; y++) { for (int x = x0; x <= x1; x++) { for (int z = z0; z <= z1; z++) { if (skipAir && getBlock(level, x, y, z, chunkBB) == 0) { continue; } if (y == y0 || y == y1 || x == x0 || x == x1 || z == z0 || z == z1) { placeBlock(level, edgeTile, edgeData, x, y, z, chunkBB); } else { placeBlock(level, fillTile, fillData, x, y, z, chunkBB); } } } } } void StructurePiece::generateBox(Level* level, BoundingBox* chunkBB, BoundingBox* boxBB, int edgeTile, int fillTile, bool skipAir) { generateBox(level, chunkBB, boxBB->x0, boxBB->y0, boxBB->z0, boxBB->x1, boxBB->y1, boxBB->z1, edgeTile, fillTile, skipAir); } void StructurePiece::generateBox(Level* level, BoundingBox* chunkBB, int x0, int y0, int z0, int x1, int y1, int z1, bool skipAir, Random* random, StructurePiece::BlockSelector* selector) { for (int y = y0; y <= y1; y++) { for (int x = x0; x <= x1; x++) { for (int z = z0; z <= z1; z++) { if (skipAir && getBlock(level, x, y, z, chunkBB) == 0) { continue; } selector->next(random, x, y, z, y == y0 || y == y1 || x == x0 || x == x1 || z == z0 || z == z1); placeBlock(level, selector->getNextId(), selector->getNextData(), x, y, z, chunkBB); } } } } void StructurePiece::generateBox(Level* level, BoundingBox* chunkBB, BoundingBox* boxBB, bool skipAir, Random* random, StructurePiece::BlockSelector* selector) { generateBox(level, chunkBB, boxBB->x0, boxBB->y0, boxBB->z0, boxBB->x1, boxBB->y1, boxBB->z1, skipAir, random, selector); } void StructurePiece::generateMaybeBox(Level* level, BoundingBox* chunkBB, Random* random, float probability, int x0, int y0, int z0, int x1, int y1, int z1, int edgeTile, int fillTile, bool skipAir) { for (int y = y0; y <= y1; y++) { for (int x = x0; x <= x1; x++) { for (int z = z0; z <= z1; z++) { if (random->nextFloat() > probability) { continue; } if (skipAir && getBlock(level, x, y, z, chunkBB) == 0) { continue; } if (y == y0 || y == y1 || x == x0 || x == x1 || z == z0 || z == z1) { placeBlock(level, edgeTile, 0, x, y, z, chunkBB); } else { placeBlock(level, fillTile, 0, x, y, z, chunkBB); } } } } } void StructurePiece::maybeGenerateBlock(Level* level, BoundingBox* chunkBB, Random* random, float probability, int x, int y, int z, int tile, int data) { if (random->nextFloat() < probability) { placeBlock(level, tile, data, x, y, z, chunkBB); } } void StructurePiece::generateUpperHalfSphere(Level* level, BoundingBox* chunkBB, int x0, int y0, int z0, int x1, int y1, int z1, int fillTile, bool skipAir) { float diagX = (float)(x1 - x0 + 1); float diagY = (float)(y1 - y0 + 1); float diagZ = (float)(z1 - z0 + 1); float cx = x0 + diagX / 2; float cz = z0 + diagZ / 2; for (int y = y0; y <= y1; y++) { float normalizedYDistance = (float)(y - y0) / diagY; for (int x = x0; x <= x1; x++) { float normalizedXDistance = (float)(x - cx) / (diagX * 0.5f); for (int z = z0; z <= z1; z++) { float normalizedZDistance = (float)(z - cz) / (diagZ * 0.5f); if (skipAir && getBlock(level, x, y, z, chunkBB) == 0) { continue; } float dist = (normalizedXDistance * normalizedXDistance) + (normalizedYDistance * normalizedYDistance) + (normalizedZDistance * normalizedZDistance); if (dist <= 1.05f) { placeBlock(level, fillTile, 0, x, y, z, chunkBB); } } } } } void StructurePiece::generateAirColumnUp(Level* level, int x, int startY, int z, BoundingBox* chunkBB) { int worldX = getWorldX(x, z); int worldY = getWorldY(startY); int worldZ = getWorldZ(x, z); if (!chunkBB->isInside(worldX, worldY, worldZ)) { return; } while (!level->isEmptyTile(worldX, worldY, worldZ) && worldY < Level::maxBuildHeight - 1) { level->setTileAndData(worldX, worldY, worldZ, 0, 0, Tile::UPDATE_CLIENTS); worldY++; } } void StructurePiece::fillColumnDown(Level* level, int tile, int tileData, int x, int startY, int z, BoundingBox* chunkBB) { int worldX = getWorldX(x, z); int worldY = getWorldY(startY); int worldZ = getWorldZ(x, z); if (!chunkBB->isInside(worldX, worldY, worldZ)) { return; } while ((level->isEmptyTile(worldX, worldY, worldZ) || level->getMaterial(worldX, worldY, worldZ)->isLiquid()) && worldY > 1) { level->setTileAndData(worldX, worldY, worldZ, tile, tileData, Tile::UPDATE_CLIENTS); worldY--; } } bool StructurePiece::createChest(Level* level, BoundingBox* chunkBB, Random* random, int x, int y, int z, const std::vector& treasure, int numRolls) { int worldX = getWorldX(x, z); int worldY = getWorldY(y); int worldZ = getWorldZ(x, z); if (chunkBB->isInside(worldX, worldY, worldZ)) { if (level->getTile(worldX, worldY, worldZ) != Tile::chest->id) { level->setTileAndData(worldX, worldY, worldZ, Tile::chest->id, 0, Tile::UPDATE_CLIENTS); std::shared_ptr chest = std::dynamic_pointer_cast( level->getTileEntity(worldX, worldY, worldZ)); if (chest != nullptr) WeighedTreasure::addChestItems(random, treasure, chest, numRolls); return true; } } return false; } bool StructurePiece::createDispenser(Level* level, BoundingBox* chunkBB, Random* random, int x, int y, int z, int facing, const std::vector& items, int numRolls) { int worldX = getWorldX(x, z); int worldY = getWorldY(y); int worldZ = getWorldZ(x, z); if (chunkBB->isInside(worldX, worldY, worldZ)) { if (level->getTile(worldX, worldY, worldZ) != Tile::dispenser_Id) { level->setTileAndData( worldX, worldY, worldZ, Tile::dispenser_Id, getOrientationData(Tile::dispenser_Id, facing), Tile::UPDATE_CLIENTS); std::shared_ptr dispenser = std::dynamic_pointer_cast( level->getTileEntity(worldX, worldY, worldZ)); if (dispenser != nullptr) WeighedTreasure::addDispenserItems(random, items, dispenser, numRolls); return true; } } return false; } void StructurePiece::createDoor(Level* level, BoundingBox* chunkBB, Random* random, int x, int y, int z, int orientation) { int worldX = getWorldX(x, z); int worldY = getWorldY(y); int worldZ = getWorldZ(x, z); if (chunkBB->isInside(worldX, worldY, worldZ)) { DoorItem::place(level, worldX, worldY, worldZ, orientation, Tile::door_wood); } }