forked from Kolyah35/minecraft-pe-0.6.1
235 lines
5.7 KiB
C++
Executable File
235 lines
5.7 KiB
C++
Executable File
#include "HangingEntity.h"
|
|
#include "../Direction.h"
|
|
#include "../level/Level.h"
|
|
#include "../level/material/Material.h"
|
|
HangingEntity::HangingEntity( Level* level )
|
|
: super(level) {
|
|
init();
|
|
}
|
|
|
|
HangingEntity::HangingEntity( Level* level, int xTile, int yTile, int zTile, int dir )
|
|
: super(level), xTile(xTile), yTile(yTile), zTile(zTile) {
|
|
init();
|
|
}
|
|
void HangingEntity::setPosition( int x, int y, int z ) {
|
|
xTile = x;
|
|
yTile = y;
|
|
zTile = z;
|
|
}
|
|
void HangingEntity::init() {
|
|
heightOffset = 0;
|
|
setSize(0.5f, 0.5f);
|
|
dir = 0;
|
|
checkInterval = 0;
|
|
}
|
|
|
|
void HangingEntity::setDir( int dir ) {
|
|
//printf("HangingEntity dir: %d\n", dir);
|
|
this->dir = dir;
|
|
yRotO = yRot = float(dir * 90);
|
|
|
|
float w = float(getWidth());
|
|
float h = float(getHeight());
|
|
float d = float(getWidth());
|
|
|
|
if (dir == Direction::NORTH || dir == Direction::SOUTH) {
|
|
d = 2.0f;
|
|
yRot = yRotO = float(Direction::DIRECTION_OPPOSITE[dir] * 90);
|
|
} else {
|
|
w = 2.0f;
|
|
}
|
|
|
|
w /= 32.0f;
|
|
h /= 32.0f;
|
|
d /= 32.0f;
|
|
|
|
float x = xTile + 0.5f;
|
|
float y = yTile + 0.5f;
|
|
float z = zTile + 0.5f;
|
|
|
|
float offset = 0.5f + 1.0f / 16.0f;
|
|
|
|
if (dir == Direction::NORTH) z -= offset;
|
|
if (dir == Direction::WEST) x -= offset;
|
|
if (dir == Direction::SOUTH) z += offset;
|
|
if (dir == Direction::EAST) x += offset;
|
|
|
|
if (dir == Direction::NORTH) x -= offs(getWidth());
|
|
if (dir == Direction::WEST) z += offs(getWidth());
|
|
if (dir == Direction::SOUTH) x += offs(getWidth());
|
|
if (dir == Direction::EAST) z -= offs(getWidth());
|
|
y += offs(getHeight());
|
|
|
|
setPos(x, y, z);
|
|
|
|
float ss = -(0.5f / 16.0f);
|
|
bb.set(x - w - ss, y - h - ss, z - d - ss, x + w + ss, y + h + ss, z + d + ss);
|
|
}
|
|
float HangingEntity::offs( int w ) {
|
|
if(w == 32) return 0.5f;
|
|
if(w == 64) return 0.5f;
|
|
return 0;
|
|
}
|
|
|
|
void HangingEntity::tick() {
|
|
if(checkInterval++ == 20 * 5 && !level->isClientSide) {
|
|
checkInterval = 0;
|
|
if(!removed && !survives()) {
|
|
remove();
|
|
dropItem();
|
|
}
|
|
}
|
|
}
|
|
|
|
bool HangingEntity::survives() {
|
|
if (!level->getCubes(this, bb).empty()) {
|
|
return false;
|
|
} else {
|
|
int ws = Mth::Max(1, getWidth() / 16);
|
|
int hs = Mth::Max(1, getHeight() / 16);
|
|
|
|
int xt = xTile;
|
|
int yt = yTile;
|
|
int zt = zTile;
|
|
if (dir == Direction::NORTH) xt = Mth::floor(x - getWidth() / 32.0f);
|
|
if (dir == Direction::WEST) zt = Mth::floor(z - getWidth() / 32.0f);
|
|
if (dir == Direction::SOUTH) xt = Mth::floor(x - getWidth() / 32.0f);
|
|
if (dir == Direction::EAST) zt = Mth::floor(z - getWidth() / 32.0f);
|
|
yt = Mth::floor(y - getHeight() / 32.0f);
|
|
|
|
for (int ss = 0; ss < ws; ++ss) {
|
|
for (int yy = 0; yy < hs; ++yy) {
|
|
const Material* m;
|
|
if (dir == Direction::NORTH || dir == Direction::SOUTH) {
|
|
m = level->getMaterial(xt + ss, yt + yy, zTile);
|
|
} else {
|
|
m = level->getMaterial(xTile, yt + yy, zt + ss);
|
|
}
|
|
if (!m->isSolid())
|
|
return false;
|
|
}
|
|
EntityList entities = level->getEntities(this, bb);
|
|
for(EntityList::iterator ei = entities.begin(); ei != entities.end(); ++ei) {
|
|
Entity* entity = *(ei);
|
|
if(entity->isHangingEntity())
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool HangingEntity::isHangingEntity() {
|
|
return true;
|
|
}
|
|
|
|
bool HangingEntity::isPickable() {
|
|
return true;
|
|
}
|
|
|
|
bool HangingEntity::interact(Player* player) {
|
|
if(!removed && !level->isClientSide) {
|
|
if(player != NULL
|
|
&& player->inventory != NULL
|
|
&& player->inventory->getSelected() != NULL
|
|
&& player->inventory->getSelected()->id == Item::bow->id)
|
|
return false;
|
|
remove();
|
|
markHurt();
|
|
if(player != NULL && !player->abilities.instabuild)
|
|
dropItem();
|
|
return true;
|
|
} else {
|
|
return !removed;
|
|
}
|
|
}
|
|
|
|
void HangingEntity::move( float xa, float ya, float za ) {
|
|
if(!level->isClientSide && !removed && (xa * xa + ya * ya + za * za) > 0) {
|
|
dropItem();
|
|
remove();
|
|
}
|
|
}
|
|
|
|
void HangingEntity::push( float xa, float ya, float za ) {
|
|
if (!level->isClientSide && !removed && (xa * xa + ya * ya + za * za) > 0) {
|
|
dropItem();
|
|
remove();
|
|
}
|
|
}
|
|
|
|
void HangingEntity::addAdditonalSaveData( CompoundTag* tag ) {
|
|
tag->putByte("Direction", (char) dir);
|
|
tag->putInt("TileX", xTile);
|
|
tag->putInt("TileY", yTile);
|
|
tag->putInt("TileZ", zTile);
|
|
|
|
// Back compat
|
|
switch (dir) {
|
|
case Direction::NORTH:
|
|
tag->putByte("Dir", char(0));
|
|
break;
|
|
case Direction::WEST:
|
|
tag->putByte("Dir", char(1));
|
|
break;
|
|
case Direction::SOUTH:
|
|
tag->putByte("Dir", char(2));
|
|
break;
|
|
case Direction::EAST:
|
|
tag->putByte("Dir", char(3));
|
|
break;
|
|
}
|
|
}
|
|
|
|
void HangingEntity::readAdditionalSaveData( CompoundTag* tag ) {
|
|
if (tag->contains("Direction")) {
|
|
dir = tag->getByte("Direction");
|
|
} else {
|
|
switch (tag->getByte("Dir")) {
|
|
case 0:
|
|
dir = Direction::NORTH;
|
|
break;
|
|
case 1:
|
|
dir = Direction::WEST;
|
|
break;
|
|
case 2:
|
|
dir = Direction::SOUTH;
|
|
break;
|
|
case 3:
|
|
dir = Direction::EAST;
|
|
break;
|
|
}
|
|
}
|
|
xTile = tag->getInt("TileX");
|
|
yTile = tag->getInt("TileY");
|
|
zTile = tag->getInt("TileZ");
|
|
setDir(dir);
|
|
}
|
|
|
|
float HangingEntity::getBrightness( float a ) {
|
|
int xTile = Mth::floor(x);
|
|
int zTile = Mth::floor(z);
|
|
//if (dir == Direction::NORTH) xTile--;
|
|
//if (dir == Direction::WEST) zTile++;
|
|
//if (dir == Direction::SOUTH) xTile++;
|
|
//if (dir == Direction::EAST) zTile--;
|
|
if (level->hasChunkAt(xTile, 0, zTile)) {
|
|
int yTile = Mth::floor(y);
|
|
return level->getBrightness(xTile, yTile, zTile);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
bool HangingEntity::hurt( Entity* source, int damage ) {
|
|
if(!removed && !level->isClientSide) {
|
|
remove();
|
|
markHurt();
|
|
Player* player = Player::asPlayer(source);
|
|
if(player != NULL && player->abilities.instabuild) {
|
|
return true;
|
|
}
|
|
dropItem();
|
|
}
|
|
return true;
|
|
}
|