Files
minecraft-pe-0.6.1/src/world/level/tile/BedTile.cpp
2026-03-02 22:04:18 +03:00

214 lines
6.1 KiB
C++
Executable File

#include "BedTile.h"
#include "../Level.h"
#include "../dimension/Dimension.h"
#include "../../entity/player/Player.h"
#include "../../Facing.h"
#include "../../Direction.h"
const int BedTile::HEAD_DIRECTION_OFFSETS[4][2] = {
{ 0, 1 },
{ -1, 0 },
{ 0, -1 },
{ 1, 0 }
};
BedTile::BedTile( int id ) : super(id, 6 + 8 * 16, Material::cloth) {
setShape();
}
bool BedTile::use(Level* level, int x, int y, int z, Player* player) {
if(player->isSleeping()) {
int dimensionsMatch = player->bedPosition.x == x ? 1 : 0;
dimensionsMatch += player->bedPosition.y == y ? 1 : 0;
dimensionsMatch += player->bedPosition.z == z ? 1 : 0;
int maxDistance = Mth::abs(player->bedPosition.x - x);
maxDistance = Mth::Max(maxDistance, Mth::abs(player->bedPosition.y - y));
maxDistance = Mth::Max(maxDistance, Mth::abs(player->bedPosition.z - z));
if(dimensionsMatch >= 2 && maxDistance < 3) {
player->stopSleepInBed(false, true, true);
return true;
}
}
if(level->isClientSide) return true;
int data = level->getData(x, y, z);
if(!isHeadPiece(data)) {
int direction = DirectionalTile::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()) {
float xc = x + 0.5f;
float yc = y + 0.5f;
float zc = z + 0.5f;
level->setTile(x, y, z, 0);
int direction = DirectionalTile::getDirection(data);
x += HEAD_DIRECTION_OFFSETS[direction][0];
y += HEAD_DIRECTION_OFFSETS[direction][1];
if(level->getTile(x, y, z) == id) {
level->setTile(x, y, z, 0);
xc = (xc + x + 0.5f) / 2;
yc = (yc + y + 0.5f) / 2;
zc = (zc + z + 0.5f) / 2;
}
level->explode(NULL, x + 0.5f, y + 0.5f, z + 0.5f, 5, true);
return true;
}
if(isOccupied(data)) {
Player* sleepingPlayer = NULL;
for(PlayerList::iterator i = level->players.begin(); i != level->players.end(); ++i) {
if((*i)->isSleeping()) {
Pos pos = (*i)->bedPosition;
if(pos.x == x && pos.y == y && pos.z == z) {
sleepingPlayer = (*i);
break;
}
}
}
if(sleepingPlayer == NULL) {
BedTile::setOccupied(level, x, y, z, false);
}
else {
sleepingPlayer->displayClientMessage("This bed is occupied"/*"tile.bed.occupied"*/);
return true;
}
}
int result = player->startSleepInBed(x, y, z);
if(result == BedSleepingResult::OK) {
BedTile::setOccupied(level, x, y, z, true);
return true;
}
if(result == BedSleepingResult::NOT_POSSIBLE_NOW) {
player->displayClientMessage("You can only sleep at night" /*tile.bed.noSleep"*/);
} else if(result == BedSleepingResult::NOT_SAFE) {
player->displayClientMessage("You may not rest now, there are monsters nearby"/*"tile.bed.notSafe"*/);
}
return true;
}
void BedTile::setOccupied( Level* level, int x, int y, int z, bool occupied ) {
int data = level->getData(x, y, z);
if(occupied) {
data |= OCCUPIED_DATA;
} else {
data &= ~OCCUPIED_DATA;
}
level->setData(x, y, z, data);
}
int BedTile::getTexture( int face, int data ) {
if(face == Facing::DOWN) {
return Tile::wood->tex;
}
int direction = getDirection(data);
int tileFacing = Direction::RELATIVE_DIRECTION_FACING[direction][face];
if (isHeadPiece(data)) {
if (tileFacing == Facing::NORTH) {
return tex + 2 + 16;
}
if (tileFacing == Facing::EAST || tileFacing == Facing::WEST) {
return tex + 1 + 16;
}
return tex + 1;
} else {
if (tileFacing == Facing::SOUTH) {
return tex - 1 + 16;
}
if (tileFacing == Facing::EAST || tileFacing == Facing::WEST) {
return tex + 16;
}
return tex;
}
}
int BedTile::getRenderShape() {
return Tile::SHAPE_BED;
}
bool BedTile::isCubeShaped() {
return false;
}
bool BedTile::isSolidRender() {
return false;
}
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) {
//spawnResources(level, x, y, z, data, 1);
popResource(level, x, y, z, ItemInstance(Item::bed));
}
}
}
}
int BedTile::getResource( int data, Random* random ) {
if(isHeadPiece(data)) {
return 0;
}
return Item::bed->id;
}
bool BedTile::findStandUpPosition( Level* level, int x, int y, int z, int skipCount, Pos& position) {
int data = level->getData(x, y, z);
int direction = DirectionalTile::getDirection(data);
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) {
if (level->isSolidBlockingTile(standX, y - 1, standZ) && level->isEmptyTile(standX, y, standZ) && level->isEmptyTile(standX, y + 1, standZ)) {
if (skipCount > 0) {
skipCount--;
continue;
}
position = Pos(standX, y, standZ);
return true;
}
}
}
}
return false;
}
void BedTile::spawnResources( Level* level, int x, int y, int z, int data, float odds ) {
if(!isHeadPiece(data)) {
//super::spawnResources(level, x, y, z, data, odds);
popResource(level, x, y, z, ItemInstance(Item::bed));
}
}
void BedTile::updateShape( LevelSource* level, int x, int y, int z ) {
setShape();
}
int BedTile::getRenderLayer() {
return Tile::RENDERLAYER_ALPHATEST;
}
void BedTile::setShape() {
super::setShape(0, 0, 0, 1, 9.0f / 16.0f, 1);
}
bool BedTile::isHeadPiece( int data ) {
return (data & HEAD_PIECE_DATA) != 0;
}
bool BedTile::isOccupied( int data ) {
return (data & OCCUPIED_DATA) != 0;
}