Files
minecraft-pe-0.6.1/src/world/entity/item/ItemEntity.cpp
2026-03-02 22:04:18 +03:00

212 lines
4.7 KiB
C++
Executable File

#include "ItemEntity.h"
#include "../../entity/player/Player.h"
#include "../../item/ItemInstance.h"
#include "../../level/Level.h"
#include "../../level/material/Material.h"
#include "../../level/tile/Tile.h"
#include "../../../util/Mth.h"
#include "../../../nbt/CompoundTag.h"
const int ItemEntity::LIFETIME = 5 * 60 * SharedConstants::TicksPerSecond; // Five minutes, changed in 0.3.3!
ItemEntity::ItemEntity( Level* level, float x, float y, float z, const ItemInstance& item )
: super(level),
item(item),
health(5),
age(0),
tickCount(0),
throwTime(0),
lifeTime(LIFETIME),
bobOffs((float) (Mth::random() * Mth::PI * 2))
{
entityRendererId = ER_ITEM_RENDERER;
setSize(0.25f, 0.25f);
heightOffset = bbHeight / 2.0f;
setPos(x, y, z);
yRot = (float) (Mth::random() * 360);
xd = (float) (Mth::random() * 0.2f - 0.1f);
yd = +0.2f;
zd = (float) (Mth::random() * 0.2f - 0.1f);
makeStepSound = false;
}
ItemEntity::ItemEntity( Level* level )
: super(level),
health(5),
age(0),
tickCount(0),
throwTime(0),
lifeTime(LIFETIME),
bobOffs((float) (Mth::random() * Mth::PI * 2))
{
entityRendererId = ER_ITEM_RENDERER;
setSize(0.25f, 0.25f);
heightOffset = bbHeight / 2.0f;
}
ItemEntity::~ItemEntity()
{
}
void ItemEntity::tick()
{
super::tick();
if (throwTime > 0) throwTime--;
xo = x;
yo = y;
zo = z;
yd -= 0.04f;
if (level->getMaterial(Mth::floor(x), Mth::floor(y), Mth::floor(z)) == Material::lava) {
yd = 0.2f;
xd = (sharedRandom.nextFloat() - sharedRandom.nextFloat()) * 0.2f;
zd = (sharedRandom.nextFloat() - sharedRandom.nextFloat()) * 0.2f;
level->playSound(this, "random.fizz", 0.4f, 2.0f + sharedRandom.nextFloat() * 0.4f);
}
checkInTile(x, y, z);
move(xd, yd, zd);
float friction = 0.98f;
if (onGround) {
friction = 0.6f * 0.98f;
int t = level->getTile(Mth::floor(x), Mth::floor(bb.y0) - 1, Mth::floor(z));
if (t > 0) {
friction = Tile::tiles[t]->friction * 0.98f;
}
}
xd *= friction;
yd *= 0.98f;
zd *= friction;
if (onGround) {
yd *= -0.5f;
}
tickCount++;
age++;
if (age >= lifeTime) {
remove();
}
}
bool ItemEntity::isInWater()
{
return level->checkAndHandleWater(bb, Material::water, this);
}
bool ItemEntity::hurt( Entity* source, int damage )
{
markHurt();
health -= damage;
if (health <= 0) {
remove();
}
return false;
}
void ItemEntity::playerTouch( Player* player )
{
if (level->isClientSide) return;
int orgCount = item.count;
if (throwTime == 0 && player->isAlive() && player->inventory->add(&item)) {
level->playSound(this, "random.pop", 0.3f, ((sharedRandom.nextFloat() - sharedRandom.nextFloat()) * 0.7f + 1.0f) * 2.f);
player->take(this, orgCount);
//if (item.count <= 0) remove(); //@todo
remove();
}
}
void ItemEntity::burn( int dmg )
{
hurt(NULL, dmg);
}
bool ItemEntity::checkInTile( float x, float y, float z )
{
int xTile = Mth::floor(x);
int yTile = Mth::floor(y);
int zTile = Mth::floor(z);
float xd = x - xTile;
float yd = y - yTile;
float zd = z - zTile;
if (Tile::solid[level->getTile(xTile, yTile, zTile)]) {
bool west = !Tile::solid[level->getTile(xTile - 1, yTile, zTile)];
bool east = !Tile::solid[level->getTile(xTile + 1, yTile, zTile)];
bool up = !Tile::solid[level->getTile(xTile, yTile - 1, zTile)];
bool down = !Tile::solid[level->getTile(xTile, yTile + 1, zTile)];
bool north = !Tile::solid[level->getTile(xTile, yTile, zTile - 1)];
bool south = !Tile::solid[level->getTile(xTile, yTile, zTile + 1)];
int dir = -1;
float closest = 9999;
if (west && xd < closest) {
closest = xd;
dir = 0;
}
if (east && 1 - xd < closest) {
closest = 1 - xd;
dir = 1;
}
if (up && yd < closest) {
closest = yd;
dir = 2;
}
if (down && 1 - yd < closest) {
closest = 1 - yd;
dir = 3;
}
if (north && zd < closest) {
closest = zd;
dir = 4;
}
if (south && 1 - zd < closest) {
// closest = 1 - zd; //@note: not read
dir = 5;
}
float speed = sharedRandom.nextFloat() * 0.2f + 0.1f;
if (dir == 0) this->xd = -speed;
if (dir == 1) this->xd = +speed;
if (dir == 2) this->yd = -speed;
if (dir == 3) this->yd = +speed;
if (dir == 4) this->zd = -speed;
if (dir == 5) this->zd = +speed;
}
return false;
}
void ItemEntity::addAdditonalSaveData(CompoundTag* entityTag) {
entityTag->putShort("Health", (char) health);
entityTag->putShort("Age", (short) age);
entityTag->putCompound("Item", item.save(new CompoundTag()));
}
void ItemEntity::readAdditionalSaveData(CompoundTag* tag) {
health = tag->getShort("Health") & 0xff;
age = tag->getShort("Age");
CompoundTag* itemTag = tag->getCompound("Item");
item.load(itemTag);
}
bool ItemEntity::isItemEntity() {
return true;
}
int ItemEntity::getEntityTypeId() const {
return EntityTypes::IdItemEntity;
}
int ItemEntity::getLifeTime() const {
return lifeTime;
}