From b691c43c44ff180d10e7d4a9afc83b98551ff586 Mon Sep 17 00:00:00 2001 From: daoge_cmd <3523206925@qq.com> Date: Sun, 1 Mar 2026 12:16:08 +0800 Subject: Initial commit --- Minecraft.World/BedTile.cpp | 332 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 332 insertions(+) create mode 100644 Minecraft.World/BedTile.cpp (limited to 'Minecraft.World/BedTile.cpp') diff --git a/Minecraft.World/BedTile.cpp b/Minecraft.World/BedTile.cpp new file mode 100644 index 00000000..7d32c6d3 --- /dev/null +++ b/Minecraft.World/BedTile.cpp @@ -0,0 +1,332 @@ +#include "stdafx.h" +#include "Dimension.h" +#include "net.minecraft.h" +#include "net.minecraft.world.entity.player.h" +#include "net.minecraft.world.item.h" +#include "net.minecraft.world.level.h" +#include "net.minecraft.world.h" +#include "BedTile.h" + +int BedTile::HEAD_DIRECTION_OFFSETS[4][2] = +{ + { 0, 1 }, { -1, 0 }, { 0, -1 }, { 1, 0 } +}; + +BedTile::BedTile(int id) : DirectionalTile(id, Material::cloth, isSolidRender()) +{ + setShape(); + + iconEnd = NULL; + iconSide = NULL; + iconTop = NULL; +} + +// 4J Added override +void BedTile::updateDefaultShape() +{ + setShape(); +} + +// 4J-PB - Adding a TestUse for tooltip display +bool BedTile::TestUse(Level *level, int x, int y, int z, shared_ptr player) +{ + //if (level->isClientSide) return true; + + int data = level->getData(x, y, z); + + if (!BedTile::isHeadPiece(data)) + { + // fetch head piece instead + int direction = getDirection(data); + x += HEAD_DIRECTION_OFFSETS[direction][0]; + z += HEAD_DIRECTION_OFFSETS[direction][1]; + if (level->getTile(x, y, z) != id) + { + return true; + } + data = level->getData(x, y, z); + } + + if (!level->dimension->mayRespawn()) + { + return false; + } + if (BedTile::isOccupied(data)) + { + return false; + } + + Player::BedSleepingResult result = player->startSleepInBed(x, y, z, true); // true to just test the start sleep + if (result == Player::OK) + { + return true; + } + + return false; +} + +bool BedTile::use(Level *level, int x, int y, int z, shared_ptr player, int clickedFace, float clickX, float clickY, float clickZ, bool soundOnly/*=false*/) // 4J added soundOnly param +{ + if( soundOnly) return false; + if (level->isClientSide) return true; + + int data = level->getData(x, y, z); + + if (!BedTile::isHeadPiece(data)) + { + // fetch head piece instead + int direction = getDirection(data); + x += HEAD_DIRECTION_OFFSETS[direction][0]; + z += HEAD_DIRECTION_OFFSETS[direction][1]; + if (level->getTile(x, y, z) != id) + { + return true; + } + data = level->getData(x, y, z); + } + + if (!level->dimension->mayRespawn()) + { + double xc = x + 0.5; + double yc = y + 0.5; + double zc = z + 0.5; + level->setTile(x, y, z, 0); + int direction = getDirection(data); + x += HEAD_DIRECTION_OFFSETS[direction][0]; + z += HEAD_DIRECTION_OFFSETS[direction][1]; + if (level->getTile(x, y, z) == id) { + level->setTile(x, y, z, 0); + xc = (xc + x + 0.5) / 2; + yc = (yc + y + 0.5) / 2; + zc = (zc + z + 0.5) / 2; + } + level->explode(nullptr, x + 0.5f, y + 0.5f, z + 0.5f, 5, true, true); + return true; + } + + if (BedTile::isOccupied(data)) + { + shared_ptr sleepingPlayer = nullptr; + AUTO_VAR(itEnd, level->players.end()); + for (AUTO_VAR(it, level->players.begin()); it != itEnd; it++ ) + { + shared_ptr p = *it; + if (p->isSleeping()) + { + Pos pos = p->bedPosition; + if (pos.x == x && pos.y == y && pos.z == z) + { + sleepingPlayer = p; + } + } + } + + if (sleepingPlayer == NULL) + { + BedTile::setOccupied(level, x, y, z, false); + } + else + { + player->displayClientMessage(IDS_TILE_BED_OCCUPIED ); + + return true; + } + } + + Player::BedSleepingResult result = player->startSleepInBed(x, y, z); + if (result == Player::OK) + { + BedTile::setOccupied(level, x, y, z, true); + // 4J-PB added + // are there multiple players in the same world as us? + if(level->AllPlayersAreSleeping()==false) + { + player->displayClientMessage(IDS_TILE_BED_PLAYERSLEEP); + } + return true; + } + + if (result == Player::NOT_POSSIBLE_NOW) + { + player->displayClientMessage(IDS_TILE_BED_NO_SLEEP); + } + else if (result == Player::NOT_SAFE) + { + player->displayClientMessage(IDS_TILE_BED_NOTSAFE); + } + + return true; +} + +Icon *BedTile::getTexture(int face, int data) +{ + if (face == Facing::DOWN) + { + return Tile::wood->getTexture(face); + } + + int direction = getDirection(data); + int tileFacing = Direction::RELATIVE_DIRECTION_FACING[direction][face]; + + int part = isHeadPiece(data) ? PART_HEAD : PART_FOOT; + + if ((part == PART_HEAD && tileFacing == Facing::NORTH) || (part == PART_FOOT && tileFacing == Facing::SOUTH)) + { + return iconEnd[part]; + } + if (tileFacing == Facing::EAST || tileFacing == Facing::WEST) + { + return iconSide[part]; + } + return iconTop[part]; +} + +void BedTile::registerIcons(IconRegister *iconRegister) +{ + iconTop = new Icon *[2]; + iconTop[0] = iconRegister->registerIcon(L"bed_feet_top"); + iconTop[1] = iconRegister->registerIcon(L"bed_head_top"); + + iconEnd = new Icon *[2]; + iconEnd[0] = iconRegister->registerIcon(L"bed_feet_end"); + iconEnd[1] = iconRegister->registerIcon(L"bed_head_end"); + + iconSide = new Icon *[2]; + iconSide[0] = iconRegister->registerIcon(L"bed_feet_side"); + iconSide[1] = iconRegister->registerIcon(L"bed_head_side"); +} + +int BedTile::getRenderShape() +{ + return Tile::SHAPE_BED; +} + +bool BedTile::isCubeShaped() +{ + return false; +} + +bool BedTile::isSolidRender(bool isServerLevel) +{ + return false; +} + +void BedTile::updateShape(LevelSource *level, int x, int y, int z, int forceData, shared_ptr forceEntity) // 4J added forceData, forceEntity param +{ + setShape(); +} + +void BedTile::neighborChanged(Level *level, int x, int y, int z, int type) +{ + int data = level->getData(x, y, z); + int direction = getDirection(data); + + if (isHeadPiece(data)) + { + if (level->getTile(x - HEAD_DIRECTION_OFFSETS[direction][0], y, z - HEAD_DIRECTION_OFFSETS[direction][1]) != id) + { + level->setTile(x, y, z, 0); + } + } else + { + if (level->getTile(x + HEAD_DIRECTION_OFFSETS[direction][0], y, z + HEAD_DIRECTION_OFFSETS[direction][1]) != id) + { + level->setTile(x, y, z, 0); + if (!level->isClientSide) + { + Tile::spawnResources(level, x, y, z, data, 0); // 4J - had to add Tile:: here for C++ since this class doesn't have this overloaded method itself + } + } + } +} + +int BedTile::getResource(int data, Random *random, int playerBonusLevel) +{ + if (isHeadPiece(data)) + { + return 0; + } + return Item::bed->id; +} + +void BedTile::setShape() +{ + Tile::setShape(0, 0, 0, 1, 9 / 16.0f, 1); +} + +bool BedTile::isHeadPiece(int data) +{ + return (data & HEAD_PIECE_DATA) != 0; +} + +bool BedTile::isOccupied(int data) +{ + return (data & OCCUPIED_DATA) != 0; +} + +void BedTile::setOccupied(Level *level, int x, int y, int z, bool occupied) +{ + int data = level->getData(x, y, z); + if (occupied) + { + data = data | OCCUPIED_DATA; + } else + { + data = data & ~OCCUPIED_DATA; + } + level->setData(x, y, z, data); +} + +Pos *BedTile::findStandUpPosition(Level *level, int x, int y, int z, int skipCount) +{ + int data = level->getData(x, y, z); + int direction = DirectionalTile::getDirection(data); + + // try to find a clear location near the bed + for (int step = 0; step <= 1; step++) + { + int startX = x - BedTile::HEAD_DIRECTION_OFFSETS[direction][0] * step - 1; + int startZ = z - BedTile::HEAD_DIRECTION_OFFSETS[direction][1] * step - 1; + int endX = startX + 2; + int endZ = startZ + 2; + + for (int standX = startX; standX <= endX; standX++) + { + for (int standZ = startZ; standZ <= endZ; standZ++) + { + // 4J Stu - Changed to check isSolidBlockingTile rather than isEmpty for the blocks that we wish to place the player + // This allows the player to spawn in blocks with snow, grass etc + if (level->isTopSolidBlocking(standX, y - 1, standZ) && + !level->isSolidBlockingTile(standX, y, standZ) && + !level->isSolidBlockingTile(standX, y + 1, standZ)) + { + if (skipCount > 0) { + skipCount--; + continue; + } + return new Pos(standX, y, standZ); + } + } + } + } + + return NULL; +} + +void BedTile::spawnResources(Level *level, int x, int y, int z, int data, float odds, int playerBonus) +{ + if (!isHeadPiece(data)) + { + Tile::spawnResources(level, x, y, z, data, odds, 0); + } +} + +int BedTile::getPistonPushReaction() +{ + return Material::PUSH_DESTROY; +} + +int BedTile::cloneTileId(Level *level, int x, int y, int z) +{ + return Item::bed_Id; +} \ No newline at end of file -- cgit v1.2.3