#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; }