forked from Kolyah35/minecraft-pe-0.6.1
the whole game
This commit is contained in:
239
src/world/level/tile/entity/ChestTileEntity.cpp
Executable file
239
src/world/level/tile/entity/ChestTileEntity.cpp
Executable file
@@ -0,0 +1,239 @@
|
||||
#include "ChestTileEntity.h"
|
||||
#include "../ChestTile.h"
|
||||
#include "../../Level.h"
|
||||
#include "../../../entity/player/Player.h"
|
||||
#include "../../../../nbt/NbtIo.h"
|
||||
|
||||
ChestTileEntity::ChestTileEntity()
|
||||
: super(TileEntityType::Chest),
|
||||
FillingContainer(ItemsSize, 0, ContainerType::CONTAINER, false),
|
||||
tickInterval(0),
|
||||
openCount(0),
|
||||
openness(0), oOpenness(0),
|
||||
hasCheckedNeighbors(false),
|
||||
n(NULL), s(NULL), w(NULL), e(NULL)
|
||||
{
|
||||
//rendererId = TR_CHEST_RENDERER;
|
||||
}
|
||||
|
||||
int ChestTileEntity::getContainerSize() const
|
||||
{
|
||||
return ItemsSize;
|
||||
}
|
||||
|
||||
ItemInstance* ChestTileEntity::getItem( int slot )
|
||||
{
|
||||
return items[slot];
|
||||
}
|
||||
|
||||
/*
|
||||
ItemInstance ChestTileEntity::removeItem( int slot, int count )
|
||||
{
|
||||
if (!items[slot].isNull()) {
|
||||
if (items[slot].count <= count) {
|
||||
ItemInstance item = items[slot];
|
||||
items[slot].setNull();
|
||||
this->setChanged();
|
||||
return item;
|
||||
} else {
|
||||
ItemInstance i = items[slot].remove(count);
|
||||
if (items[slot].count == 0) items[slot].setNull();
|
||||
this->setChanged();
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return ItemInstance();
|
||||
}
|
||||
|
||||
ItemInstance ChestTileEntity::removeItemNoUpdate( int slot )
|
||||
{
|
||||
if (!items[slot].isNull()) {
|
||||
ItemInstance item = items[slot];
|
||||
items[slot].setNull();
|
||||
return item;
|
||||
}
|
||||
return ItemInstance();
|
||||
}
|
||||
|
||||
void ChestTileEntity::setItem( int slot, ItemInstance* item )
|
||||
{
|
||||
items[slot] = item? *item : ItemInstance();
|
||||
if (item != NULL && item->count > getMaxStackSize()) item->count = getMaxStackSize();
|
||||
this->setChanged();
|
||||
}
|
||||
*/
|
||||
|
||||
std::string ChestTileEntity::getName() const
|
||||
{
|
||||
return "container.chest";
|
||||
}
|
||||
|
||||
bool ChestTileEntity::shouldSave() {
|
||||
for (int i = 0; i < ItemsSize; ++i)
|
||||
if (items[i] && !items[i]->isNull()) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void ChestTileEntity::load( CompoundTag* base )
|
||||
{
|
||||
super::load(base);
|
||||
|
||||
if (!base->contains("Items"))//, Tag::TAG_List)
|
||||
return;
|
||||
|
||||
ListTag* inventoryList = base->getList("Items");
|
||||
for (int i = 0; i < inventoryList->size(); i++) {
|
||||
Tag* ttag = inventoryList->get(i);
|
||||
if (ttag->getId() != Tag::TAG_Compound)
|
||||
continue;
|
||||
|
||||
CompoundTag* tag = (CompoundTag*) ttag;
|
||||
int slot = tag->getByte("Slot") & 0xff;
|
||||
if (slot >= 0 && slot < ItemsSize) {
|
||||
if (!items[slot]) items[slot] = new ItemInstance(); //@chestodo
|
||||
items[slot]->load(tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ChestTileEntity::save( CompoundTag* base )
|
||||
{
|
||||
if (!super::save(base))
|
||||
return false;
|
||||
|
||||
ListTag* listTag = new ListTag();
|
||||
|
||||
for (int i = 0; i < ItemsSize; i++) {
|
||||
if (items[i] && !items[i]->isNull()) {
|
||||
CompoundTag* tag = new CompoundTag();
|
||||
tag->putByte("Slot", (char) i);
|
||||
items[i]->save(tag);
|
||||
listTag->add(tag);
|
||||
}
|
||||
}
|
||||
base->put("Items", listTag);
|
||||
return true;
|
||||
}
|
||||
|
||||
int ChestTileEntity::getMaxStackSize() const
|
||||
{
|
||||
return Container::LARGE_MAX_STACK_SIZE;
|
||||
}
|
||||
|
||||
bool ChestTileEntity::stillValid( Player* player )
|
||||
{
|
||||
if (level->getTileEntity(x, y, z) != this) return false;
|
||||
if (player->distanceToSqr(x + 0.5f, y + 0.5f, z + 0.5f) > 8 * 8) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ChestTileEntity::clearCache()
|
||||
{
|
||||
super::clearCache();
|
||||
hasCheckedNeighbors = false;
|
||||
}
|
||||
|
||||
void ChestTileEntity::checkNeighbors()
|
||||
{
|
||||
if (hasCheckedNeighbors)
|
||||
return;
|
||||
|
||||
hasCheckedNeighbors = true;
|
||||
n = NULL;
|
||||
e = NULL;
|
||||
w = NULL;
|
||||
s = NULL;
|
||||
|
||||
// if (getTile() != NULL) {
|
||||
if (level->getTile(x - 1, y, z) == Tile::chest->id) {
|
||||
w = (ChestTileEntity*) level->getTileEntity(x - 1, y, z);
|
||||
}
|
||||
if (level->getTile(x + 1, y, z) == Tile::chest->id) {
|
||||
e = (ChestTileEntity*) level->getTileEntity(x + 1, y, z);
|
||||
}
|
||||
if (level->getTile(x, y, z - 1) == Tile::chest->id) {
|
||||
n = (ChestTileEntity*) level->getTileEntity(x, y, z - 1);
|
||||
}
|
||||
if (level->getTile(x, y, z + 1) == Tile::chest->id) {
|
||||
s = (ChestTileEntity*) level->getTileEntity(x, y, z + 1);
|
||||
}
|
||||
|
||||
if (n != NULL) n->clearCache();
|
||||
if (s != NULL) s->clearCache();
|
||||
if (e != NULL) e->clearCache();
|
||||
if (w != NULL) w->clearCache();
|
||||
// }
|
||||
}
|
||||
|
||||
void ChestTileEntity::tick()
|
||||
{
|
||||
super::tick();
|
||||
checkNeighbors();
|
||||
|
||||
if (++tickInterval >= 4 * SharedConstants::TicksPerSecond) {
|
||||
level->tileEvent(x, y, z, ChestTile::EVENT_SET_OPEN_COUNT, openCount);
|
||||
tickInterval = 0;
|
||||
}
|
||||
|
||||
oOpenness = openness;
|
||||
|
||||
float speed = 0.10f;
|
||||
if (openCount > 0 && openness == 0) {
|
||||
if (n == NULL && w == NULL) {
|
||||
float xc = x + 0.5f;
|
||||
float zc = z + 0.5f;
|
||||
if (s != NULL) zc += 0.5f;
|
||||
if (e != NULL) xc += 0.5f;
|
||||
|
||||
level->playSound(xc, y + 0.5f, zc, "random.chestopen", 0.5f, level->random.nextFloat() * 0.1f + 0.9f);
|
||||
}
|
||||
}
|
||||
if ((openCount == 0 && openness > 0) || (openCount > 0 && openness < 1)) {
|
||||
float oldOpen = openness;
|
||||
if (openCount > 0) openness += speed;
|
||||
else openness -= speed;
|
||||
if (openness > 1) {
|
||||
openness = 1;
|
||||
}
|
||||
float lim = 0.5f;
|
||||
if (openness < lim && oldOpen >= lim) {
|
||||
if (n == NULL && w == NULL) {
|
||||
float xc = x + 0.5f;
|
||||
float zc = z + 0.5f;
|
||||
if (s != NULL) zc += 0.5f;
|
||||
if (e != NULL) xc += 0.5f;
|
||||
|
||||
level->playSound(xc, y + 0.5f, zc, "random.chestclosed", 0.5f, level->random.nextFloat() * 0.1f + 0.9f);
|
||||
}
|
||||
}
|
||||
if (openness < 0) {
|
||||
openness = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ChestTileEntity::triggerEvent( int b0, int b1 )
|
||||
{
|
||||
if (b0 == ChestTile::EVENT_SET_OPEN_COUNT) {
|
||||
openCount = b1;
|
||||
}
|
||||
}
|
||||
|
||||
void ChestTileEntity::startOpen()
|
||||
{
|
||||
openCount++;
|
||||
level->tileEvent(x, y, z, ChestTile::EVENT_SET_OPEN_COUNT, openCount);
|
||||
}
|
||||
|
||||
void ChestTileEntity::stopOpen()
|
||||
{
|
||||
openCount--;
|
||||
level->tileEvent(x, y, z, ChestTile::EVENT_SET_OPEN_COUNT, openCount);
|
||||
}
|
||||
|
||||
void ChestTileEntity::setRemoved()
|
||||
{
|
||||
clearCache();
|
||||
checkNeighbors();
|
||||
super::setRemoved();
|
||||
}
|
||||
66
src/world/level/tile/entity/ChestTileEntity.h
Executable file
66
src/world/level/tile/entity/ChestTileEntity.h
Executable file
@@ -0,0 +1,66 @@
|
||||
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE_ENTITY__ChestTileEntity_H__
|
||||
#define NET_MINECRAFT_WORLD_LEVEL_TILE_ENTITY__ChestTileEntity_H__
|
||||
|
||||
//package net.minecraft.world.level->tile.entity;
|
||||
|
||||
#include "TileEntity.h"
|
||||
#include "../../../inventory/FillingContainer.h"
|
||||
#include "../../../item/ItemInstance.h"
|
||||
#include <string>
|
||||
|
||||
class CompoundTag;
|
||||
class Player;
|
||||
|
||||
/* import com.mojang.nbt.* */
|
||||
|
||||
class ChestTileEntity: public TileEntity,
|
||||
public FillingContainer
|
||||
{
|
||||
typedef TileEntity super;
|
||||
public:
|
||||
ChestTileEntity();
|
||||
|
||||
int getContainerSize() const;
|
||||
int getMaxStackSize() const;
|
||||
std::string getName() const;
|
||||
|
||||
ItemInstance* getItem(int slot);
|
||||
//void setItem(int slot, ItemInstance* item);
|
||||
//ItemInstance removeItem(int slot, int count);
|
||||
//ItemInstance removeItemNoUpdate(int slot);
|
||||
|
||||
bool shouldSave();
|
||||
void load(CompoundTag* base);
|
||||
bool save(CompoundTag* base);
|
||||
|
||||
bool stillValid(Player* player);
|
||||
|
||||
void clearCache();
|
||||
void checkNeighbors();
|
||||
|
||||
/*@Override*/
|
||||
void tick();
|
||||
|
||||
void triggerEvent(int b0, int b1);
|
||||
|
||||
void startOpen();
|
||||
void stopOpen();
|
||||
|
||||
/*@Override*/
|
||||
void setRemoved();
|
||||
|
||||
bool hasCheckedNeighbors;
|
||||
ChestTileEntity* n;
|
||||
ChestTileEntity* e;
|
||||
ChestTileEntity* w;
|
||||
ChestTileEntity* s;
|
||||
|
||||
float openness, oOpenness;
|
||||
int openCount;
|
||||
|
||||
private:
|
||||
static const int ItemsSize = 9*3;
|
||||
int tickInterval;
|
||||
};
|
||||
|
||||
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE_ENTITY__ChestTileEntity_H__*/
|
||||
251
src/world/level/tile/entity/FurnaceTileEntity.cpp
Executable file
251
src/world/level/tile/entity/FurnaceTileEntity.cpp
Executable file
@@ -0,0 +1,251 @@
|
||||
#include "FurnaceTileEntity.h"
|
||||
|
||||
#include "../FurnaceTile.h"
|
||||
#include "../../Level.h"
|
||||
#include "../../material/Material.h"
|
||||
#include "../../../Container.h"
|
||||
#include "../../../entity/player/Player.h"
|
||||
//#include "../../../item/crafting/FurnaceRecipes.h"
|
||||
#include "../../../item/ItemInstance.h"
|
||||
#include "../../../../nbt/ListTag.h"
|
||||
#include "../../../item/crafting/FurnaceRecipes.h"
|
||||
|
||||
FurnaceTileEntity::FurnaceTileEntity()
|
||||
: super(TileEntityType::Furnace),
|
||||
Container(ContainerType::FURNACE),
|
||||
litTime(0),
|
||||
litDuration(0),
|
||||
tickCount(0),
|
||||
finished(false),
|
||||
_canBeFinished(false)
|
||||
{
|
||||
//LOGI("CREATING FurnaceTileEntity! %p\n", this);
|
||||
}
|
||||
|
||||
FurnaceTileEntity::~FurnaceTileEntity() {
|
||||
//LOGI("DELETING FurnaceTileEntity! %p @ %d, %d, %d\n", this, x, y, z);
|
||||
}
|
||||
|
||||
ItemInstance* FurnaceTileEntity::getItem(int slot) {// @todo @container @fix
|
||||
return &items[slot];
|
||||
}
|
||||
|
||||
ItemInstance FurnaceTileEntity::removeItem(int slot, int count) {
|
||||
if (!items[slot].isNull()) {
|
||||
if (items[slot].count <= count) {
|
||||
ItemInstance item = items[slot];
|
||||
items[slot].setNull();
|
||||
return item;
|
||||
} else {
|
||||
ItemInstance i = items[slot].remove(count);
|
||||
if (items[slot].count == 0) items[slot].setNull();
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return ItemInstance();
|
||||
}
|
||||
|
||||
void FurnaceTileEntity::setItem(int slot, ItemInstance* item) {
|
||||
items[slot] = *item;
|
||||
if (item != NULL && item->count > getMaxStackSize())
|
||||
items[slot].count = getMaxStackSize();
|
||||
//LOGI("Furnace: Setting slot %d : %s\n", slot, item->getDescriptionId().c_str());
|
||||
}
|
||||
|
||||
std::string FurnaceTileEntity::getName() const {
|
||||
return "Furnace";
|
||||
}
|
||||
|
||||
bool FurnaceTileEntity::shouldSave() {
|
||||
if (litTime > 0) return true;
|
||||
for (int i = 0; i < NumItems; ++i)
|
||||
if (!items[i].isNull()) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void FurnaceTileEntity::load(CompoundTag* base) {
|
||||
super::load(base);
|
||||
ListTag* inventoryList = base->getList("Items");
|
||||
for (int i = 0; i < 3; ++i)
|
||||
items[i].setNull();
|
||||
for (int i = 0; i < inventoryList->size(); i++) {
|
||||
Tag* tt = inventoryList->get(i);
|
||||
if (tt->getId() == Tag::TAG_Compound) {
|
||||
CompoundTag* tag = (CompoundTag*)tt;
|
||||
int slot = tag->getByte("Slot");
|
||||
if (slot >= 0 && slot < NumItems) {
|
||||
ItemInstance* loaded = ItemInstance::fromTag(tag);
|
||||
if (loaded) {
|
||||
items[slot] = *loaded;
|
||||
delete loaded;
|
||||
} else
|
||||
items[slot].setNull();
|
||||
}
|
||||
} else {
|
||||
LOGE("load @ FurnaceTileEntity failed. item's not a compoundTag!\n");
|
||||
}
|
||||
}
|
||||
|
||||
litTime = base->getShort("BurnTime");
|
||||
tickCount = base->getShort("CookTime");
|
||||
litDuration = getBurnDuration(items[SLOT_FUEL]);
|
||||
}
|
||||
|
||||
bool FurnaceTileEntity::save(CompoundTag* base) {
|
||||
if (!super::save(base))
|
||||
return false;
|
||||
|
||||
base->putShort("BurnTime", (short) (litTime));
|
||||
base->putShort("CookTime", (short) (tickCount));
|
||||
ListTag* listTag = new ListTag();
|
||||
|
||||
for (int i = 0; i < NumItems; i++) {
|
||||
if (!items[i].isNull()) {
|
||||
CompoundTag* tag = new CompoundTag();
|
||||
tag->putByte("Slot", (char) i);
|
||||
items[i].save(tag);
|
||||
listTag->add(tag);
|
||||
}
|
||||
}
|
||||
base->put("Items", listTag);
|
||||
return true;
|
||||
}
|
||||
|
||||
int FurnaceTileEntity::getMaxStackSize() const {
|
||||
return Container::LARGE_MAX_STACK_SIZE;
|
||||
}
|
||||
|
||||
int FurnaceTileEntity::getContainerSize() const {
|
||||
return NumItems;
|
||||
}
|
||||
|
||||
int FurnaceTileEntity::getBurnProgress(int max) {
|
||||
return tickCount * max / BURN_INTERVAL;
|
||||
}
|
||||
|
||||
int FurnaceTileEntity::getLitProgress(int max) {
|
||||
if (litDuration == 0) litDuration = BURN_INTERVAL;
|
||||
return litTime * max / litDuration;
|
||||
}
|
||||
|
||||
bool FurnaceTileEntity::isLit() {
|
||||
return litTime > 0;
|
||||
}
|
||||
|
||||
void FurnaceTileEntity::tick()
|
||||
{
|
||||
//LOGI("lit|time, tick, dur: %d, %d, %d\n", litTime, tickCount, litDuration);
|
||||
|
||||
bool wasLit = litTime > 0;
|
||||
bool changed = false;
|
||||
if (litTime > 0) {
|
||||
--litTime;
|
||||
}
|
||||
|
||||
//LOGI("Ticking FurnaceTileEntity: %d\n", litTime);
|
||||
|
||||
if (!level->isClientSide) {
|
||||
if (litTime == 0 && canBurn()) {
|
||||
litDuration = litTime = getBurnDuration(items[SLOT_FUEL]);
|
||||
if (litTime > 0) {
|
||||
changed = true;
|
||||
if (!items[SLOT_FUEL].isNull()) {
|
||||
if (--items[SLOT_FUEL].count == 0) items[SLOT_FUEL].setNull();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isLit() && canBurn()) {
|
||||
if (++tickCount == BURN_INTERVAL) {
|
||||
tickCount = 0;
|
||||
burn();
|
||||
changed = true;
|
||||
}
|
||||
} else {
|
||||
tickCount = 0;
|
||||
}
|
||||
|
||||
if (wasLit != (litTime > 0)) {
|
||||
changed = true;
|
||||
FurnaceTile::setLit(litTime > 0, level, x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) setChanged();
|
||||
else {
|
||||
if (!wasLit) {
|
||||
finished = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool FurnaceTileEntity::isFinished()
|
||||
{
|
||||
return _canBeFinished && finished;
|
||||
}
|
||||
|
||||
|
||||
void FurnaceTileEntity::burn() {
|
||||
if (!canBurn()) return;
|
||||
|
||||
ItemInstance result = FurnaceRecipes::getInstance()->getResult(items[0].getItem()->id);
|
||||
if (items[2].isNull()) items[2] = result;
|
||||
else if (items[2].id == result.id) items[2].count++;
|
||||
|
||||
if (--items[0].count <= 0) items[0].setNull();
|
||||
}
|
||||
|
||||
bool FurnaceTileEntity::stillValid(Player* player) {
|
||||
if (level->getTileEntity(x, y, z) != this) return false;
|
||||
if (player->distanceToSqr(x + 0.5f, y + 0.5f, z + 0.5f) > 8 * 8) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void FurnaceTileEntity::startOpen() {
|
||||
//_canBeFinished = false;
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
void FurnaceTileEntity::stopOpen() {
|
||||
//_canBeFinished = true;
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
bool FurnaceTileEntity::canBurn() {
|
||||
if (items[SLOT_INGREDIENT].isNull()) return false;
|
||||
ItemInstance burnResult = FurnaceRecipes::getInstance()->getResult(items[SLOT_INGREDIENT].getItem()->id);
|
||||
if (burnResult.isNull()) return false;
|
||||
if (items[SLOT_RESULT].isNull()) return true;
|
||||
if (!items[SLOT_RESULT].sameItem(&burnResult)) return false;
|
||||
if (items[SLOT_RESULT].count < getMaxStackSize() && items[SLOT_RESULT].count < items[SLOT_RESULT].getMaxStackSize()) return true;
|
||||
if (items[SLOT_RESULT].count < burnResult.getMaxStackSize()) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*static*/
|
||||
int FurnaceTileEntity::getBurnDuration(const ItemInstance& itemInstance) {
|
||||
//if (itemInstance == NULL) return 0;
|
||||
if (itemInstance.isNull()) return 0;
|
||||
int id = itemInstance.getItem()->id;
|
||||
|
||||
if (id < 256 && Tile::tiles[id]->material == Material::wood)
|
||||
return BURN_INTERVAL * 3 / 2;
|
||||
|
||||
if (id == Item::stick->id) return BURN_INTERVAL / 2;
|
||||
if (id == Item::coal->id) return BURN_INTERVAL * 8;
|
||||
//case Item::bucket_lava->id: return BURN_INTERVAL * 100;
|
||||
//case Tile::sapling->id: return BURN_INTERVAL / 2;
|
||||
//case Item::blazeRod->id: return BURN_INTERVAL * 12;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool FurnaceTileEntity::isFuel( const ItemInstance& itemInstance )
|
||||
{
|
||||
return getBurnDuration(itemInstance) > 0;
|
||||
}
|
||||
|
||||
bool FurnaceTileEntity::isSlotEmpty( int slot )
|
||||
{
|
||||
return items[slot].isNull();
|
||||
}
|
||||
74
src/world/level/tile/entity/FurnaceTileEntity.h
Executable file
74
src/world/level/tile/entity/FurnaceTileEntity.h
Executable file
@@ -0,0 +1,74 @@
|
||||
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE_ENTITY__FurnaceTileEntity_H__
|
||||
#define NET_MINECRAFT_WORLD_LEVEL_TILE_ENTITY__FurnaceTileEntity_H__
|
||||
|
||||
//package net.minecraft.world.level->tile.entity;
|
||||
|
||||
#include "TileEntity.h"
|
||||
#include "../../../Container.h"
|
||||
#include "../../../item/ItemInstance.h"
|
||||
|
||||
class CompoundTag;
|
||||
class Player;
|
||||
|
||||
class FurnaceTileEntity: public TileEntity,
|
||||
public Container
|
||||
{
|
||||
typedef TileEntity super;
|
||||
static const int BURN_INTERVAL = 10 * 20;
|
||||
static const int NumItems = 3;
|
||||
public:
|
||||
FurnaceTileEntity();
|
||||
~FurnaceTileEntity();
|
||||
|
||||
// Container
|
||||
ItemInstance* getItem(int slot);
|
||||
void setItem(int slot, ItemInstance* item);
|
||||
ItemInstance removeItem(int slot, int count);
|
||||
|
||||
std::string getName() const;
|
||||
int getMaxStackSize() const;
|
||||
int getContainerSize() const;
|
||||
|
||||
bool stillValid(Player* player);
|
||||
|
||||
void startOpen();
|
||||
void stopOpen();
|
||||
|
||||
void setContainerChanged();
|
||||
|
||||
// Furnace
|
||||
void load(CompoundTag* base);
|
||||
bool save(CompoundTag* base);
|
||||
bool shouldSave();
|
||||
|
||||
int getBurnProgress(int max);
|
||||
int getLitProgress(int max);
|
||||
|
||||
bool isLit();
|
||||
bool isFinished();
|
||||
bool isSlotEmpty( int slot );
|
||||
|
||||
void tick();
|
||||
|
||||
void burn();
|
||||
|
||||
static bool isFuel(const ItemInstance& itemInstance);
|
||||
static int getBurnDuration(const ItemInstance& itemInstance);
|
||||
private:
|
||||
bool canBurn();
|
||||
|
||||
public:
|
||||
int litTime;
|
||||
int litDuration;
|
||||
int tickCount;
|
||||
ItemInstance items[NumItems];
|
||||
|
||||
static const int SLOT_INGREDIENT = 0;
|
||||
static const int SLOT_FUEL = 1;
|
||||
static const int SLOT_RESULT = 2;
|
||||
private:
|
||||
bool _canBeFinished;
|
||||
bool finished;
|
||||
};
|
||||
|
||||
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE_ENTITY__FurnaceTileEntity_H__*/
|
||||
402
src/world/level/tile/entity/NetherReactorTileEntity.cpp
Executable file
402
src/world/level/tile/entity/NetherReactorTileEntity.cpp
Executable file
@@ -0,0 +1,402 @@
|
||||
#include "NetherReactorTileEntity.h"
|
||||
#include "../../../../nbt/CompoundTag.h"
|
||||
#include "../../../../SharedConstants.h"
|
||||
#include "../../../phys/Vec3.h"
|
||||
#include "../../../level/Level.h"
|
||||
#include "../../../level/MobSpawner.h"
|
||||
#include "../../../entity/MobFactory.h"
|
||||
#include "../NetherReactor.h"
|
||||
#include "../../../entity/Entity.h"
|
||||
#include "../../../Difficulty.h"
|
||||
#include "../../../phys/AABB.h"
|
||||
#include "../NetherReactorPattern.h"
|
||||
NetherReactorTileEntity::NetherReactorTileEntity()
|
||||
: super(TileEntityType::NetherReactor)
|
||||
, isInitialized(false)
|
||||
, progress(0)
|
||||
, curLevel(0)
|
||||
, hasFinished(false)
|
||||
{ }
|
||||
|
||||
bool NetherReactorTileEntity::shouldSave() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetherReactorTileEntity::lightItUp( int x, int y, int z ) {
|
||||
//if(!isInitilized && !hasFinished) {
|
||||
curLevel = 0;
|
||||
NetherReactor::setPhase(level, x, y, z, 1);
|
||||
isInitialized = true;
|
||||
//clearDomeSpace(x, y, z);
|
||||
buildDome(x, y, z);
|
||||
|
||||
level->setNightMode(true);
|
||||
//}
|
||||
}
|
||||
|
||||
void NetherReactorTileEntity::tick() {
|
||||
if(level->isClientSide)
|
||||
return;
|
||||
if(progress < 0) {
|
||||
remove = true;
|
||||
}
|
||||
if(isInitialized && !hasFinished) {
|
||||
progress++;
|
||||
if(progress % SharedConstants::TicksPerSecond == 0) {
|
||||
int currentTime = progress / SharedConstants::TicksPerSecond;
|
||||
if(currentTime < 10) {
|
||||
tickGlowingRedstoneTransformation(currentTime);
|
||||
}
|
||||
if(currentTime > 42 && currentTime <= 45) {
|
||||
// start with the top layer and move down
|
||||
int currentLayer = 45 - currentTime;
|
||||
turnGlowingObsidianLayerToObsidian(currentLayer);
|
||||
}
|
||||
if(checkLevelChange(progress / SharedConstants::TicksPerSecond)) {
|
||||
curLevel++;
|
||||
spawnItems(getNumItemsPerLevel(curLevel));
|
||||
trySpawnPigZombies(NUM_PIG_ZOMBIE_SLOTS, getNumEnemiesPerLevel(curLevel));
|
||||
}
|
||||
}
|
||||
if(progress > SharedConstants::TicksPerSecond * 46) {
|
||||
finishReactorRun();
|
||||
}
|
||||
} else if(hasFinished) {
|
||||
if(progress % SharedConstants::TicksPerSecond * 60 == 0) {
|
||||
if(playersAreCloseBy()) {
|
||||
trySpawnPigZombies(2, 3);
|
||||
} else {
|
||||
killPigZombies();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NetherReactorTileEntity::load( CompoundTag* tag ) {
|
||||
super::load(tag);
|
||||
isInitialized = tag->getBoolean("IsInitialized");
|
||||
if(isInitialized) {
|
||||
progress = tag->getShort("Progress");
|
||||
hasFinished = tag->getBoolean("HasFinished");
|
||||
}
|
||||
}
|
||||
|
||||
bool NetherReactorTileEntity::save( CompoundTag* tag ) {
|
||||
super::save(tag);
|
||||
tag->putBoolean("IsInitialized", isInitialized);
|
||||
tag->putShort("Progress", progress);
|
||||
tag->putBoolean("HasFinished", hasFinished);
|
||||
if(isInitialized && !hasFinished)
|
||||
level->setNightMode(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string NetherReactorTileEntity::getName() const {
|
||||
return "NetherReactor";
|
||||
}
|
||||
|
||||
int NetherReactorTileEntity::getNumEnemiesPerLevel( int curLevel ) {
|
||||
if(curLevel == 0)
|
||||
return 3;
|
||||
else if(curLevel < 4)
|
||||
return 2;
|
||||
else if(curLevel < 6)
|
||||
return Mth::Max(0, level->random.nextInt(2));
|
||||
else
|
||||
return Mth::Max(0, level->random.nextInt(1));
|
||||
}
|
||||
|
||||
int NetherReactorTileEntity::getNumItemsPerLevel( int curLevel ) {
|
||||
if(curLevel == 0)
|
||||
return 3 * 3;
|
||||
else if(curLevel < 4)
|
||||
return 5 * 3;
|
||||
else if(curLevel < 8)
|
||||
return Mth::Max(0, level->random.nextInt(14 * 3) - 4);
|
||||
else
|
||||
return Mth::Max(0, level->random.nextInt(9 * 3) - 2);
|
||||
}
|
||||
|
||||
void NetherReactorTileEntity::spawnItems( int numItems ) {
|
||||
for (int ii = 0; ii < numItems ; ii++) {
|
||||
spawnItem();
|
||||
}
|
||||
}
|
||||
Vec3 NetherReactorTileEntity::getSpawnPosition( float minDistance, float varibleDistance, float offset ) {
|
||||
float distance = minDistance + level->random.nextFloat() * varibleDistance;
|
||||
float rad = level->random.nextFloat() * Mth::TWO_PI;
|
||||
return Vec3(sin(rad) * distance + x, offset + y, cos(rad) * distance + z);
|
||||
}
|
||||
void NetherReactorTileEntity::spawnEnemy() {
|
||||
Mob* mob = MobFactory::CreateMob(MobTypes::PigZombie, level);
|
||||
Vec3 enemyPosition = getSpawnPosition(3, 4, -1);
|
||||
while(enemyPosition.x < 0 || enemyPosition.z < 0 || enemyPosition.x >= LEVEL_WIDTH || enemyPosition.z >= LEVEL_DEPTH) {
|
||||
enemyPosition = getSpawnPosition(3, 4, -1);
|
||||
}
|
||||
MobSpawner::addMob(level, mob, enemyPosition.x, enemyPosition.y, enemyPosition.z, 0, 0, true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void NetherReactorTileEntity::spawnItem() {
|
||||
Vec3 itemPosition= getSpawnPosition(3, 4, -1);
|
||||
while(itemPosition.x < 0 || itemPosition.z < 0 || itemPosition.x >= LEVEL_WIDTH || itemPosition.z >= LEVEL_DEPTH) {
|
||||
itemPosition = getSpawnPosition(3, 4, -1);
|
||||
}
|
||||
ItemEntity* item = new ItemEntity(level, itemPosition.x, itemPosition.y, itemPosition.z, getSpawnItem());
|
||||
|
||||
item->throwTime = 10;
|
||||
item->age = item->getLifeTime() - SharedConstants::TicksPerSecond * 30;
|
||||
level->addEntity(item);
|
||||
}
|
||||
|
||||
ItemInstance NetherReactorTileEntity::getSpawnItem() {
|
||||
int itemType = level->random.nextInt(8);
|
||||
switch(itemType) {
|
||||
case 0: return ItemInstance(Item::yellowDust, 3);
|
||||
case 1: return ItemInstance(Item::seeds_melon);
|
||||
case 2: return ItemInstance(Tile::mushroom1);
|
||||
case 3: return ItemInstance(Tile::mushroom2);
|
||||
case 4: return ItemInstance(Item::reeds);
|
||||
case 5: return ItemInstance(Tile::cactus);
|
||||
case 6: return ItemInstance(Item::netherQuartz, 4);
|
||||
default: return GetLowOddsSpawnItem();
|
||||
}
|
||||
}
|
||||
|
||||
ItemInstance NetherReactorTileEntity::GetLowOddsSpawnItem() {
|
||||
if(level->random.nextInt(10) <= 9 ) {
|
||||
static Item* items[] = {
|
||||
Item::arrow,
|
||||
Item::bed,
|
||||
Item::bone,
|
||||
Item::book,
|
||||
Item::bow,
|
||||
Item::bowl,
|
||||
Item::feather,
|
||||
Item::painting,
|
||||
Item::door_wood
|
||||
};
|
||||
int itemIndex = level->random.nextInt(sizeof(items) / 4);
|
||||
Item* itemToSpawn = items[itemIndex];
|
||||
return ItemInstance(itemToSpawn);
|
||||
} else {
|
||||
static Tile* tiles[] = {
|
||||
Tile::bookshelf
|
||||
};
|
||||
int tileIndex = level->random.nextInt(sizeof(tiles) / 4);
|
||||
Tile* tileToSpawn = tiles[tileIndex];
|
||||
return ItemInstance(tileToSpawn);
|
||||
}
|
||||
}
|
||||
|
||||
bool NetherReactorTileEntity::checkLevelChange( int progress ) {
|
||||
static const int levelChangeTime[] = {10, 13, 20, 22, 25, 30, 34, 36, 38, 40};
|
||||
const int count = sizeof(levelChangeTime) / 4;
|
||||
for(int a = 0; a < count; ++a) {
|
||||
if(levelChangeTime[a] == progress)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void NetherReactorTileEntity::clearDomeSpace( int x, int y, int z ) {
|
||||
for(int curX = -12; curX <= 12; ++curX) {
|
||||
for(int curY = -3; curY < 40; ++curY) {
|
||||
for(int curZ = -12; curZ <= 12; ++curZ) {
|
||||
if(curY > 2 || curX < -1 || curX > 1 || curZ < -1 || curZ > 1)
|
||||
level->setTile(curX + x, curY + y, curZ + z, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NetherReactorTileEntity::finishReactorRun() {
|
||||
NetherReactor::setPhase(level, x, y, z, 2);
|
||||
level->setNightMode(false);
|
||||
hasFinished = true;
|
||||
deterioateDome(x, y, z);
|
||||
for(int curX = x - 1; curX <= x + 1; ++curX) {
|
||||
for(int curY = y - 1; curY <= y + 1; ++curY) {
|
||||
for(int curZ = z - 1; curZ <= z + 1; ++curZ) {
|
||||
if(curX != x || curY != y || curZ != z)
|
||||
level->setTile(curX, curY, curZ, Tile::obsidian->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int NetherReactorTileEntity::numOfFreeEnemySlots() {
|
||||
int numPigZombiesFound = 0;
|
||||
AABB bb((float)x, (float)y, (float)z, x + 1.0f, y + 1.0f, z + 1.0f);
|
||||
EntityList nearby = level->getEntities(NULL, bb.grow(7, 7, 7));
|
||||
for(EntityList::iterator it = nearby.begin(); it != nearby.end(); ++it) {
|
||||
if((*it)->isEntityType(MobTypes::PigZombie) && (*it)->isAlive()) {
|
||||
numPigZombiesFound++;
|
||||
}
|
||||
}
|
||||
return NUM_PIG_ZOMBIE_SLOTS - numPigZombiesFound;
|
||||
}
|
||||
|
||||
void NetherReactorTileEntity::trySpawnPigZombies( int maxNumOfEnemies, int maxToSpawn ) {
|
||||
if(level->difficulty == Difficulty::PEACEFUL)
|
||||
return;
|
||||
int currentNumOfPigZombies = NUM_PIG_ZOMBIE_SLOTS - numOfFreeEnemySlots();
|
||||
if(currentNumOfPigZombies < maxNumOfEnemies) {
|
||||
for(int a = 0; a < maxToSpawn && currentNumOfPigZombies < maxNumOfEnemies; ++a) {
|
||||
spawnEnemy();
|
||||
currentNumOfPigZombies++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NetherReactorTileEntity::tickGlowingRedstoneTransformation( int currentTime ) {
|
||||
switch(currentTime) {
|
||||
case 2: return turnLayerToGlowingObsidian(0, Tile::stoneBrick->id);
|
||||
case 3: return turnLayerToGlowingObsidian(1, Tile::stoneBrick->id);
|
||||
case 4: return turnLayerToGlowingObsidian(2, Tile::stoneBrick->id);
|
||||
case 7: return turnLayerToGlowingObsidian(0, Tile::goldBlock->id);
|
||||
case 8: return turnLayerToGlowingObsidian(1, Tile::goldBlock->id);
|
||||
case 9: return turnLayerToGlowingObsidian(2, Tile::goldBlock->id);
|
||||
}
|
||||
}
|
||||
|
||||
void NetherReactorTileEntity::turnLayerToGlowingObsidian( int layer, const int type ) {
|
||||
NetherReactorPattern pattern;
|
||||
for(int checkX = -1; checkX <= 1; ++checkX) {
|
||||
for(int checkZ = -1; checkZ <= 1; ++checkZ) {
|
||||
if(pattern.getTileAt(layer, checkX + 1, checkZ + 1) == type) {
|
||||
level->setTile(x + checkX, y - 1 + layer, z + checkZ, Tile::glowingObsidian->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NetherReactorTileEntity::turnGlowingObsidianLayerToObsidian( int layer ) {
|
||||
NetherReactorPattern pattern;
|
||||
for(int checkX = -1; checkX <= 1; ++checkX) {
|
||||
for(int checkZ = -1; checkZ <= 1; ++checkZ) {
|
||||
if(level->getTile(x + checkX, y - 1 + layer, z + checkZ) != Tile::netherReactor->id) {
|
||||
level->setTile(x + checkX, y - 1 + layer, z + checkZ, Tile::obsidian->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NetherReactorTileEntity::buildDome( int x, int y, int z ) {
|
||||
buildFloorVolume(x, y - 3, z, 8, 2, Tile::netherrack->id);
|
||||
buildHollowedVolume(x, y - 1, z, 8, 4, Tile::netherrack->id, 0);
|
||||
buildFloorVolume(x, y - 1 + 4, z, 8, 1, Tile::netherrack->id);
|
||||
buildCrockedRoofVolume(false, x, y - 1 + 5, z, 8, 1, Tile::netherrack->id);
|
||||
buildCrockedRoofVolume(true, x, y - 1 + 6, z, 5, 8, Tile::netherrack->id);
|
||||
buildCrockedRoofVolume(false, x, y + -1 + 12, z, 3, 14, Tile::netherrack->id);
|
||||
}
|
||||
|
||||
void NetherReactorTileEntity::buildHollowedVolume( int x, int y, int z, int expandWidth, int height, const int wallTileId, const int clearTileId ) {
|
||||
for(int curY = 0; curY < height; ++curY) {
|
||||
for(int curX = -expandWidth; curX <= expandWidth; ++curX) {
|
||||
for(int curZ = -expandWidth; curZ <= expandWidth; ++curZ) {
|
||||
if((curX == -expandWidth || curX == expandWidth)
|
||||
|| (curZ == -expandWidth || curZ == expandWidth)) {
|
||||
level->setTile(curX + x, curY + y, curZ + z, wallTileId);
|
||||
} else if(curY > 2 || curX < -1 || curX > 1 || curZ < -1 || curZ > 1) {
|
||||
level->setTile(curX + x, curY + y, curZ + z, clearTileId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NetherReactorTileEntity::buildFloorVolume( int x, int y, int z, int expandWidth, int height, const int tileId ) {
|
||||
for(int curY = 0; curY < height; ++curY) {
|
||||
for(int curX = -expandWidth; curX <= expandWidth; ++curX) {
|
||||
for(int curZ = -expandWidth; curZ <= expandWidth; ++curZ) {
|
||||
level->setTile(curX + x, curY + y, curZ + z, tileId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NetherReactorTileEntity::buildCrockedRoofVolume( bool inverted, int x, int y, int z, int expandWidth, int height, const int tileId ) {
|
||||
int fullHeight = height + expandWidth;
|
||||
for(int curX = -expandWidth; curX <= expandWidth; ++curX) {
|
||||
for(int curZ = -expandWidth; curZ <= expandWidth; ++curZ) {
|
||||
int offset = inverted ? ((-curX - curZ) / 2) : ((curX + curZ) / 2);
|
||||
int acceptHeight = fullHeight + offset;
|
||||
for(int curY = 0; curY < fullHeight + expandWidth; ++curY) {
|
||||
if(acceptHeight >= curY
|
||||
&& (isEdge(curX, expandWidth, curZ)
|
||||
|| acceptHeight == curY )) {
|
||||
level->setTile(curX + x, curY + y, curZ + z, tileId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool NetherReactorTileEntity::isEdge( int curX, int expandWidth, int curZ ) {
|
||||
return (curX == -expandWidth || curX == expandWidth)
|
||||
|| (curZ == -expandWidth || curZ == expandWidth);
|
||||
}
|
||||
|
||||
void NetherReactorTileEntity::deterioateDome( int x, int y, int z ) {
|
||||
deterioateHollowedVolume(x, y - 1, z, 8, 5, 0);
|
||||
deterioateCrockedRoofVolume(false, x, y - 1 + 5, z, 8, 1, 0);
|
||||
deterioateCrockedRoofVolume(true, x, y - 1 + 6, z, 5, 8, 0);
|
||||
deterioateCrockedRoofVolume(false, x, y + -1 + 12, z, 3, 14, 0);
|
||||
}
|
||||
|
||||
void NetherReactorTileEntity::deterioateCrockedRoofVolume( bool inverted, int x, int y, int z, int expandWidth, int height, int tileId ) {
|
||||
int fullHeight = height + expandWidth;
|
||||
for(int curX = -expandWidth; curX <= expandWidth; ++curX) {
|
||||
for(int curZ = -expandWidth; curZ <= expandWidth; ++curZ) {
|
||||
int offset = inverted ? ((-curX - curZ) / 2) : ((curX + curZ) / 2);
|
||||
int acceptHeight = fullHeight + offset;
|
||||
for(int curY = 0; curY < fullHeight + expandWidth; ++curY) {
|
||||
if(acceptHeight >= curY
|
||||
&& (isEdge(curX, expandWidth, curZ))) {
|
||||
if(level->random.nextInt(4) == 0) {
|
||||
level->setTile(curX + x, curY + y, curZ + z, tileId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NetherReactorTileEntity::deterioateHollowedVolume( int x, int y, int z, int expandWidth, int height, int tileId ) {
|
||||
for(int curY = 0; curY < height; ++curY) {
|
||||
for(int curX = -expandWidth; curX <= expandWidth; ++curX) {
|
||||
for(int curZ = -expandWidth; curZ <= expandWidth; ++curZ) {
|
||||
if((curX == -expandWidth || curX == expandWidth)
|
||||
|| (curZ == -expandWidth || curZ == expandWidth)) {
|
||||
if(level->random.nextInt(3) == 0)
|
||||
level->setTile(curX + x, curY + y, curZ + z, tileId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool NetherReactorTileEntity::playersAreCloseBy() {
|
||||
int numPlayers = 0;
|
||||
AABB bb((float)x, (float)y, (float)z, x + 1.0f, y + 1.0f, z + 1.0f);
|
||||
EntityList nearby = level->getEntities(NULL, bb.grow(40, 40, 40));
|
||||
for(EntityList::iterator it = nearby.begin(); it != nearby.end(); ++it) {
|
||||
if((*it)->isPlayer() && (*it)->isAlive() ) {
|
||||
if((*it)->distanceTo((float)x, (float)y, (float)z) < 40)
|
||||
numPlayers++;
|
||||
}
|
||||
}
|
||||
return numPlayers != 0;
|
||||
}
|
||||
|
||||
void NetherReactorTileEntity::killPigZombies() {
|
||||
AABB bb((float)x, (float)y, (float)z, x + 1.0f, y + 1.0f, z + 1.0f);
|
||||
EntityList nearby = level->getEntities(NULL, bb.grow(40, 40, 40));
|
||||
for(EntityList::iterator it = nearby.begin(); it != nearby.end(); ++it) {
|
||||
if((*it)->isEntityType(MobTypes::PigZombie)) {
|
||||
(*it)->remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
55
src/world/level/tile/entity/NetherReactorTileEntity.h
Executable file
55
src/world/level/tile/entity/NetherReactorTileEntity.h
Executable file
@@ -0,0 +1,55 @@
|
||||
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE_ENTITY__NetherReactorTileEntity_H__
|
||||
#define NET_MINECRAFT_WORLD_LEVEL_TILE_ENTITY__NetherReactorTileEntity_H__
|
||||
#include "../../../Pos.h"
|
||||
#include "TileEntity.h"
|
||||
class NetherReactorTileEntity : public TileEntity {
|
||||
typedef TileEntity super;
|
||||
static const int NUM_PIG_ZOMBIE_SLOTS = 3;
|
||||
public:
|
||||
NetherReactorTileEntity();
|
||||
bool shouldSave();
|
||||
void lightItUp(int x, int y, int z);
|
||||
|
||||
void buildDome(int x, int y, int z);
|
||||
void clearDomeSpace( int x, int y, int z );
|
||||
|
||||
void tick();
|
||||
|
||||
void finishReactorRun();
|
||||
|
||||
bool save(CompoundTag* tag);
|
||||
void load(CompoundTag* tag);
|
||||
int getNumEnemiesPerLevel(int curLevel);
|
||||
int getNumItemsPerLevel(int curLevel);
|
||||
void spawnItems(int numItems);
|
||||
std::string getName() const;
|
||||
void spawnEnemy();
|
||||
void spawnItem();
|
||||
ItemInstance getSpawnItem();
|
||||
|
||||
ItemInstance GetLowOddsSpawnItem();
|
||||
bool checkLevelChange( int progress );
|
||||
int numOfFreeEnemySlots();
|
||||
void trySpawnPigZombies( int maxNumOfEnemies, int maxToSpawn );
|
||||
void tickGlowingRedstoneTransformation( int currentTime );
|
||||
void turnLayerToGlowingObsidian( int layer, const int type );
|
||||
void turnGlowingObsidianLayerToObsidian( int layer );
|
||||
Vec3 getSpawnPosition( float minDistance, float varibleDistance, float offset );
|
||||
void buildHollowedVolume( int x, int y, int z, int expandWidth, int height, const int wallTileId, const int clearTileId );
|
||||
void buildFloorVolume( int x, int y, int z, int expandWidth, int heightm, const int tileId );
|
||||
void buildCrockedRoofVolume( bool inverted, int x, int y, int z, int expandWidth, int height, const int tileId );
|
||||
|
||||
bool isEdge( int curX, int expandWidth, int curZ );
|
||||
void deterioateDome( int x, int y, int z );
|
||||
void deterioateCrockedRoofVolume( bool inverted, int x, int y, int z, int expandWidth, int height, int tileId );
|
||||
void deterioateHollowedVolume( int x, int y, int z, int expandWidth, int height, int tileId );
|
||||
bool playersAreCloseBy();
|
||||
void killPigZombies();
|
||||
private:
|
||||
bool isInitialized;
|
||||
bool hasFinished;
|
||||
int curLevel;
|
||||
short progress;
|
||||
};
|
||||
|
||||
#endif /* NET_MINECRAFT_WORLD_LEVEL_TILE_ENTITY__NetherReactorTileEntity_H__ */
|
||||
58
src/world/level/tile/entity/SignTileEntity.cpp
Executable file
58
src/world/level/tile/entity/SignTileEntity.cpp
Executable file
@@ -0,0 +1,58 @@
|
||||
#include "SignTileEntity.h"
|
||||
#include "../../../../network/packet/SignUpdatePacket.h"
|
||||
#include "../../Level.h"
|
||||
SignTileEntity::SignTileEntity()
|
||||
: super(TileEntityType::Sign),
|
||||
selectedLine(-1),
|
||||
editable(true)
|
||||
{
|
||||
rendererId = TR_SIGN_RENDERER;
|
||||
}
|
||||
|
||||
bool SignTileEntity::save( CompoundTag* tag ) {
|
||||
if (!super::save(tag))
|
||||
return false;
|
||||
|
||||
tag->putString("Text1", messages[0]);
|
||||
tag->putString("Text2", messages[1]);
|
||||
tag->putString("Text3", messages[2]);
|
||||
tag->putString("Text4", messages[3]);
|
||||
return true;
|
||||
}
|
||||
|
||||
void SignTileEntity::load( CompoundTag* tag ) {
|
||||
editable = false;
|
||||
super::load(tag);
|
||||
|
||||
messages[0] = tag->getString("Text1");
|
||||
messages[1] = tag->getString("Text2");
|
||||
messages[2] = tag->getString("Text3");
|
||||
messages[3] = tag->getString("Text4");
|
||||
|
||||
for (int i = 0; i < NUM_LINES; i++)
|
||||
if (messages[i].length() > MAX_LINE_LENGTH)
|
||||
messages[i].resize(MAX_LINE_LENGTH);
|
||||
}
|
||||
|
||||
bool SignTileEntity::shouldSave() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SignTileEntity::isEditable() {
|
||||
return editable;
|
||||
}
|
||||
|
||||
void SignTileEntity::setEditable( bool isEditable ) {
|
||||
this->editable = isEditable;
|
||||
}
|
||||
|
||||
Packet* SignTileEntity::getUpdatePacket() {
|
||||
return new SignUpdatePacket(x, y, z, messages);
|
||||
}
|
||||
|
||||
void SignTileEntity::setLevelAndPos( Level* level, int x, int y, int z ) {
|
||||
super::setLevelAndPos(level, x, y, z);
|
||||
if(level->getTile(x, y, z) != Tile::sign->id) {
|
||||
remove = true;
|
||||
}
|
||||
}
|
||||
39
src/world/level/tile/entity/SignTileEntity.h
Executable file
39
src/world/level/tile/entity/SignTileEntity.h
Executable file
@@ -0,0 +1,39 @@
|
||||
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE_ENTITY__SignTileEntity_H__
|
||||
#define NET_MINECRAFT_WORLD_LEVEL_TILE_ENTITY__SignTileEntity_H__
|
||||
|
||||
//package net.minecraft.world.level.tile.entity;
|
||||
|
||||
/* import net.minecraft.network.packet.* */
|
||||
|
||||
#include "../../../../nbt/CompoundTag.h"
|
||||
|
||||
#include "TileEntity.h"
|
||||
|
||||
class SignTileEntity: public TileEntity
|
||||
{
|
||||
typedef TileEntity super;
|
||||
public:
|
||||
static const int MAX_LINE_LENGTH = 15;
|
||||
static const int NUM_LINES = 4;
|
||||
|
||||
SignTileEntity();
|
||||
|
||||
/*@Override*/
|
||||
bool save(CompoundTag* tag);
|
||||
/*@Override*/
|
||||
void load(CompoundTag* tag);
|
||||
bool shouldSave();
|
||||
|
||||
bool isEditable();
|
||||
void setEditable(bool isEditable);
|
||||
void setLevelAndPos(Level* level, int x, int y, int z);
|
||||
|
||||
Packet* getUpdatePacket();
|
||||
|
||||
std::string messages[NUM_LINES];
|
||||
int selectedLine;
|
||||
private:
|
||||
bool editable;
|
||||
};
|
||||
|
||||
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE_ENTITY__SignTileEntity_H__*/
|
||||
221
src/world/level/tile/entity/TileEntity.cpp
Executable file
221
src/world/level/tile/entity/TileEntity.cpp
Executable file
@@ -0,0 +1,221 @@
|
||||
#include "TileEntity.h"
|
||||
|
||||
TileEntity::MapIdType TileEntity::idClassMap;
|
||||
TileEntity::MapTypeId TileEntity::classIdMap;
|
||||
|
||||
#include "FurnaceTileEntity.h"
|
||||
#include "ChestTileEntity.h"
|
||||
#include "NetherReactorTileEntity.h"
|
||||
#include "../../Level.h"
|
||||
#include "../../../../nbt/CompoundTag.h"
|
||||
#include "SignTileEntity.h"
|
||||
|
||||
int TileEntity::_runningId = 0;
|
||||
|
||||
//
|
||||
// TileEntityFactory
|
||||
//
|
||||
TileEntity* TileEntityFactory::createTileEntity( int type )
|
||||
{
|
||||
switch(type) {
|
||||
case TileEntityType::Furnace: return new FurnaceTileEntity();
|
||||
case TileEntityType::Chest: return new ChestTileEntity();
|
||||
case TileEntityType::Sign: return new SignTileEntity();
|
||||
case TileEntityType::NetherReactor: return new NetherReactorTileEntity();
|
||||
default:
|
||||
LOGE("Can't find TileEntity of type: %d\n", type);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// TileEntity
|
||||
//
|
||||
|
||||
void TileEntity::initTileEntities()
|
||||
{
|
||||
setId(TileEntityType::Furnace, "Furnace");
|
||||
setId(TileEntityType::Chest, "Chest");
|
||||
setId(TileEntityType::NetherReactor, "NetherReactor");
|
||||
// setId(ChestTileEntity.class, "Chest");
|
||||
// setId(RecordPlayerTile.Entity.class, "RecordPlayer");
|
||||
// setId(DispenserTileEntity.class, "Trap");
|
||||
setId(TileEntityType::Sign, "Sign");
|
||||
// setId(MobSpawnerTileEntity.class, "MobSpawner");
|
||||
// setId(MusicTileEntity.class, "Music");
|
||||
// setId(PistonPieceEntity.class, "Piston");
|
||||
// setId(BrewingStandTileEntity.class, "Cauldron");
|
||||
// setId(EnchantmentTableEntity.class, "EnchantTable");
|
||||
// setId(TheEndPortalTileEntity.class, "Airportal");
|
||||
}
|
||||
|
||||
void TileEntity::teardownTileEntities()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
TileEntity::TileEntity( int tileEntityType )
|
||||
: data(-1),
|
||||
type(tileEntityType),
|
||||
remove(false),
|
||||
level(NULL),
|
||||
tile(NULL),
|
||||
clientSideOnly(false),
|
||||
rendererId(TR_DEFAULT_RENDERER),
|
||||
runningId(++_runningId)
|
||||
{
|
||||
}
|
||||
|
||||
void TileEntity::load( CompoundTag* tag )
|
||||
{
|
||||
x = tag->getInt("x");
|
||||
y = tag->getInt("y");
|
||||
z = tag->getInt("z");
|
||||
LOGI("Loaded tile entity @ %d, %d, %d\n", x, y, z);
|
||||
}
|
||||
|
||||
bool TileEntity::save( CompoundTag* tag )
|
||||
{
|
||||
MapTypeId::const_iterator it = classIdMap.find(type);
|
||||
if (it == classIdMap.end()) {
|
||||
LOGE("TileEntityType %d is missing a mapping! This is a bug!\n", type);
|
||||
return false;
|
||||
}
|
||||
tag->putString("id", it->second);
|
||||
tag->putInt("x", x);
|
||||
tag->putInt("y", y);
|
||||
tag->putInt("z", z);
|
||||
return true;
|
||||
}
|
||||
|
||||
TileEntity* TileEntity::loadStatic( CompoundTag* tag )
|
||||
{
|
||||
TileEntity* entity = NULL;
|
||||
|
||||
std::string id = tag->getString("id");
|
||||
MapIdType::const_iterator cit = idClassMap.find(id);
|
||||
if (cit != idClassMap.end()) {
|
||||
//LOGI("Loading Tile Entity @ %d,%d,%d\n", ));
|
||||
entity = TileEntityFactory::createTileEntity(cit->second);
|
||||
if (entity) {
|
||||
//LOGI("Loading TileEntity: %d\n", entity->type);
|
||||
entity->load(tag);
|
||||
}
|
||||
else
|
||||
LOGE("Couldn't create TileEntity of type: '%d'\n", cit->second);
|
||||
} else {
|
||||
LOGE("Couldn't find TileEntity type: '%s'\n", id.c_str());
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
int TileEntity::getData()
|
||||
{
|
||||
if (data == -1) data = level->getData(x, y, z);
|
||||
return data;
|
||||
}
|
||||
|
||||
void TileEntity::setData( int data )
|
||||
{
|
||||
this->data = data;
|
||||
level->setData(x, y, z, data);
|
||||
}
|
||||
|
||||
void TileEntity::setChanged()
|
||||
{
|
||||
if (level != NULL) {
|
||||
data = level->getData(x, y, z);
|
||||
level->tileEntityChanged(x, y, z, this);
|
||||
}
|
||||
}
|
||||
|
||||
float TileEntity::distanceToSqr( float xPlayer, float yPlayer, float zPlayer )
|
||||
{
|
||||
float xd = (x + 0.5f) - xPlayer;
|
||||
float yd = (y + 0.5f) - yPlayer;
|
||||
float zd = (z + 0.5f) - zPlayer;
|
||||
return xd * xd + yd * yd + zd * zd;
|
||||
}
|
||||
|
||||
Tile* TileEntity::getTile() {
|
||||
if (tile == NULL) tile = Tile::tiles[level->getTile(x, y, z)];
|
||||
return tile;
|
||||
}
|
||||
|
||||
bool TileEntity::isRemoved() const
|
||||
{
|
||||
return remove;
|
||||
}
|
||||
|
||||
void TileEntity::setRemoved()
|
||||
{
|
||||
remove = true;
|
||||
}
|
||||
|
||||
void TileEntity::clearRemoved()
|
||||
{
|
||||
remove = false;
|
||||
}
|
||||
|
||||
void TileEntity::triggerEvent( int b0, int b1 )
|
||||
{
|
||||
}
|
||||
|
||||
void TileEntity::clearCache()
|
||||
{
|
||||
tile = NULL;
|
||||
data = -1;
|
||||
}
|
||||
|
||||
void TileEntity::setId( int type, const std::string& id )
|
||||
{
|
||||
MapIdType::const_iterator cit = idClassMap.find(id);
|
||||
if (cit != idClassMap.end()) {
|
||||
LOGE("Duplicate id: %s\n", id.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
idClassMap.insert(std::make_pair(id, type));
|
||||
classIdMap.insert(std::make_pair(type, id));
|
||||
}
|
||||
|
||||
void TileEntity::setLevelAndPos( Level* level, int x, int y, int z ) {
|
||||
this->level = level;
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
this->z = z;
|
||||
|
||||
if (level) {
|
||||
this->tile = Tile::tiles[level->getTile(x, y, z)];
|
||||
}
|
||||
}
|
||||
|
||||
bool TileEntity::isFinished() {
|
||||
return false;
|
||||
}
|
||||
|
||||
Packet* TileEntity::getUpdatePacket() {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool TileEntity::isType( int Type ) {
|
||||
return type == Type;
|
||||
}
|
||||
|
||||
bool TileEntity::isType( TileEntity* te, int Type ) {
|
||||
return te != NULL && te->isType(Type);
|
||||
}
|
||||
|
||||
|
||||
int partitionTileEntities( const std::vector<TileEntity*>& in, std::vector<TileEntity*>& keep, std::vector<TileEntity*>& dontKeep ) {
|
||||
std::map<TilePos, TileEntity*> m;
|
||||
for (unsigned int i = 0; i < in.size(); ++i) {
|
||||
TileEntity* e = in[i];
|
||||
TilePos p(e->x, e->y, e->z);
|
||||
if (m.find(p) == m.end() && e->shouldSave()) {
|
||||
m.insert(std::make_pair(p, e));
|
||||
keep.push_back(e);
|
||||
} else dontKeep.push_back(e);
|
||||
}
|
||||
return (int)keep.size();
|
||||
}
|
||||
98
src/world/level/tile/entity/TileEntity.h
Executable file
98
src/world/level/tile/entity/TileEntity.h
Executable file
@@ -0,0 +1,98 @@
|
||||
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE_ENTITY__TileEntity_H__
|
||||
#define NET_MINECRAFT_WORLD_LEVEL_TILE_ENTITY__TileEntity_H__
|
||||
|
||||
//package net.minecraft.world.level->tile.entity;
|
||||
|
||||
#include "../Tile.h"
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include "TileEntityRendererId.h"
|
||||
|
||||
class Level;
|
||||
class TileEntity;
|
||||
class CompoundTag;
|
||||
class Packet;
|
||||
|
||||
class TileEntityType {
|
||||
public:
|
||||
static const int Undefined = 0;
|
||||
static const int Furnace = 1;
|
||||
static const int Chest = 2;
|
||||
static const int NetherReactor = 3;
|
||||
static const int Sign = 4;
|
||||
};
|
||||
|
||||
class TileEntityFactory {
|
||||
public:
|
||||
static TileEntity* createTileEntity(int type);
|
||||
};
|
||||
|
||||
class TileEntity
|
||||
{
|
||||
typedef std::map<std::string, int> MapIdType;
|
||||
typedef std::map<int, std::string> MapTypeId;
|
||||
|
||||
static int _runningId;
|
||||
public:
|
||||
static void initTileEntities();
|
||||
static void teardownTileEntities();
|
||||
|
||||
TileEntity(int tileEntityType);
|
||||
virtual ~TileEntity() {}
|
||||
|
||||
virtual bool shouldSave() = 0;
|
||||
virtual void load(CompoundTag* tag);
|
||||
virtual bool save(CompoundTag* tag);
|
||||
|
||||
virtual void tick() {}
|
||||
virtual bool isFinished();
|
||||
|
||||
static TileEntity* loadStatic(CompoundTag* tag);
|
||||
|
||||
virtual void setLevelAndPos(Level* level, int x, int y, int z);
|
||||
|
||||
int getData();
|
||||
void setData(int data);
|
||||
|
||||
void setChanged();
|
||||
|
||||
float distanceToSqr(float xPlayer, float yPlayer, float zPlayer);
|
||||
|
||||
Tile* getTile();
|
||||
|
||||
virtual Packet* getUpdatePacket();
|
||||
|
||||
bool isRemoved() const;
|
||||
void setRemoved();
|
||||
void clearRemoved();
|
||||
|
||||
virtual void triggerEvent(int b0, int b1);
|
||||
virtual void clearCache();
|
||||
|
||||
bool isType(int Type);
|
||||
static bool isType(TileEntity* te, int Type);
|
||||
public:
|
||||
Level* level;
|
||||
int x, y, z;
|
||||
|
||||
int data;
|
||||
int type;
|
||||
int runningId;
|
||||
|
||||
bool clientSideOnly;
|
||||
|
||||
TileEntityRendererId rendererId;
|
||||
|
||||
protected:
|
||||
Tile* tile;
|
||||
bool remove;
|
||||
|
||||
private:
|
||||
static MapIdType idClassMap;
|
||||
static MapTypeId classIdMap;
|
||||
static void setId(int type, const std::string& id);
|
||||
};
|
||||
|
||||
int partitionTileEntities(const std::vector<TileEntity*>& in, std::vector<TileEntity*>& keep, std::vector<TileEntity*>& dontKeep);
|
||||
|
||||
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE_ENTITY__TileEntity_H__*/
|
||||
10
src/world/level/tile/entity/TileEntityRendererId.h
Executable file
10
src/world/level/tile/entity/TileEntityRendererId.h
Executable file
@@ -0,0 +1,10 @@
|
||||
#ifndef NET_MINECRAFT_WORLD_ENTITY__TileEntityRendererId_H__
|
||||
#define NET_MINECRAFT_WORLD_ENTITY__TileEntityRendererId_H__
|
||||
|
||||
enum TileEntityRendererId {
|
||||
TR_DEFAULT_RENDERER,
|
||||
TR_CHEST_RENDERER,
|
||||
TR_SIGN_RENDERER
|
||||
};
|
||||
|
||||
#endif /*NET_MINECRAFT_WORLD_ENTITY__TileEntityRendererId_H__*/
|
||||
Reference in New Issue
Block a user