the whole game

This commit is contained in:
2026-03-02 22:04:18 +03:00
parent 816e9060b4
commit f0617a5d22
2069 changed files with 581500 additions and 0 deletions

213
src/world/level/tile/BedTile.cpp Executable file
View File

@@ -0,0 +1,213 @@
#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;
}

40
src/world/level/tile/BedTile.h Executable file
View File

@@ -0,0 +1,40 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__BedTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__BedTile_H__
#include "DirectionalTile.h"
#include "../material/Material.h"
class Pos;
class BedTile : public DirectionalTile
{
typedef DirectionalTile super;
public:
static const int HEAD_PIECE_DATA = 0x8;
static const int OCCUPIED_DATA = 0x4;
static const int HEAD_DIRECTION_OFFSETS[4][2];
BedTile(int id);
bool use(Level* level, int x, int y, int z, Player* player);
int getTexture(int face, int data);
int getRenderShape();
int getRenderLayer();
bool isCubeShaped();
bool isSolidRender();
void updateShape(LevelSource* level, int x, int y, int z);
void setShape();
void neighborChanged(Level* level, int x, int y, int z, int type);
int getResource(int data, Random* random);
void spawnResources(Level* level, int x, int y, int z, int data, float odds);
static bool isHeadPiece( int data );
static bool isOccupied(int data);
static void setOccupied( Level* level, int x, int y, int z, bool occupied );
static bool findStandUpPosition( Level* level, int x, int y, int z, int skipCount, Pos& position);
};
#endif /* NET_MINECRAFT_WORLD_LEVEL_TILE__BedTile_H__ */

View File

@@ -0,0 +1,33 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__BookshelfTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__BookshelfTile_H__
//package net.minecraft.world.level.tile;
#include "../../item/Item.h"
#include "../material/Material.h"
class BookshelfTile: public Tile
{
typedef Tile super;
public:
BookshelfTile(int id, int tex)
: super(id, tex, Material::wood)
{
}
int getTexture(int face) {
if (face <= 1) return 4;
return tex;
}
int getResourceCount(Random* random) {
return 3;
}
//@Override
int getResource(int data, Random* random/*, int playerBonusLevel*/) {
return Item::book->id;
}
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__BookshelfTile_H__*/

82
src/world/level/tile/Bush.h Executable file
View File

@@ -0,0 +1,82 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__Bush_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__Bush_H__
//package net.minecraft.world.level.tile;
#include "../Level.h"
#include "Tile.h"
#include "../material/Material.h"
class Bush: public Tile
{
public:
Bush(int id, int tex)
: Tile(id, Material::plant)
{
this->tex = tex;
setTicking(true);
float ss = 0.2f;
this->setShape(0.5f - ss, 0, 0.5f - ss, 0.5f + ss, ss * 3, 0.5f + ss);
}
Bush(int id, int tex, const Material* material) : Tile(id, material) {
this->tex = tex;
setTicking(true);
float ss = 0.2f;
this->setShape(0.5f - ss, 0, 0.5f - ss, 0.5f + ss, ss * 3, 0.5f + ss);
}
bool mayPlace(Level* level, int x, int y, int z, unsigned char face) {
return mayPlaceOn(level->getTile(x, y - 1, z));
}
void neighborChanged(Level* level, int x, int y, int z, int type) {
Tile::neighborChanged(level, x, y, z, type);
checkAlive(level, x, y, z);
}
void tick(Level* level, int x, int y, int z, Random* random) {
checkAlive(level, x, y, z);
}
bool canSurvive(Level* level, int x, int y, int z) {
return (level->getRawBrightness(x, y, z)>=8 || level->canSeeSky(x, y, z)) && mayPlaceOn(level->getTile(x, y - 1, z));
}
AABB* getAABB(Level* level, int x, int y, int z) {
return NULL;
}
bool blocksLight() {
return false;
}
bool isSolidRender() {
return false;
}
bool isCubeShaped() {
return false;
}
int getRenderShape() {
return Tile::SHAPE_CROSS_TEXTURE;
}
int getRenderLayer() {
return Tile::RENDERLAYER_ALPHATEST;
}
protected:
virtual bool mayPlaceOn(int tile) {
return tile == ((Tile*)Tile::grass)->id || tile == Tile::dirt->id || tile == Tile::farmland->id;
}
const void checkAlive(Level* level, int x, int y, int z) {
if (!canSurvive(level, x, y, z)) {
this->spawnResources(level, x, y, z, level->getData(x, y, z));
level->setTile(x, y, z, 0);
//printf("died! @ %d,%d,%d\n", x, y, z);
}
}
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__Bush_H__*/

111
src/world/level/tile/CactusTile.h Executable file
View File

@@ -0,0 +1,111 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__CactusTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__CactusTile_H__
//package net.minecraft.world.level->tile;
//#include "world/damagesource/DamageSource.h"
#include "Tile.h"
#include "../Level.h"
#include "../material/Material.h"
#include "../../entity/Entity.h"
#include "../../phys/AABB.h"
class Random;
class CactusTile: public Tile
{
typedef Tile super;
public:
CactusTile(int id, int tex)
: super(id, tex, Material::cactus)
{
setTicking(true);
}
void tick(Level* level, int x, int y, int z, Random* random) {
if (level->isEmptyTile(x, y + 1, z)) {
int height = 1;
while (level->getTile(x, y - height, z) == id) {
height++;
}
if (height < 3) {
int age = level->getData(x, y, z);
// It takes way to long on pocket edition becuase of fewer ticks
if (age >= /*15*/10) {
level->setTile(x, y + 1, z, id);
level->setData(x, y, z, 0);
} else {
level->setData(x, y, z, age + 1);
}
}
}
}
AABB* getAABB(Level* level, int x, int y, int z) {
float r = 1 / 16.0f;
tmpBB.x0 = x + r;
tmpBB.y0 = (float)y;
tmpBB.z0 = z + r;
tmpBB.x1 = x + 1 - r;
tmpBB.y1 = y + 1 - r;
tmpBB.z1 = z + 1 - r;
return &tmpBB;
}
AABB getTileAABB(Level* level, int x, int y, int z) {
float r = 1 / 16.0f;
return AABB((float)x + r, (float)y, (float)z + r, (float)x + 1 - r, (float)y + 1, (float)z + 1 - r);
}
int getTexture(int face) {
if (face == 1) return tex - 1;
if (face == 0) return tex + 1;
else return tex;
}
bool isCubeShaped() {
return false;
}
bool isSolidRender() {
return false;
}
int getRenderShape() {
return Tile::SHAPE_CACTUS;
}
int getRenderLayer() {
return Tile::RENDERLAYER_ALPHATEST;
}
bool mayPlace(Level* level, int x, int y, int z) {
if (!super::mayPlace(level, x, y, z)) return false;
return canSurvive(level, x, y, z);
}
void neighborChanged(Level* level, int x, int y, int z, int type) {
if (!canSurvive(level, x, y, z)) {
// Should always spawn a cactus when this happens
this->spawnResources(level, x, y, z, level->getData(x, y, z), 1);
level->setTile(x, y, z, 0);
}
}
bool canSurvive(Level* level, int x, int y, int z) {
if (level->getMaterial(x - 1, y, z)->isSolid()) return false;
if (level->getMaterial(x + 1, y, z)->isSolid()) return false;
if (level->getMaterial(x, y, z - 1)->isSolid()) return false;
if (level->getMaterial(x, y, z + 1)->isSolid()) return false;
int below = level->getTile(x, y - 1, z);
return below == Tile::cactus->id || below == Tile::sand->id;
}
void entityInside(Level* level, int x, int y, int z, Entity* entity) {
entity->hurt(NULL/*DamageSource.cactus*/, 1);
}
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__CactusTile_H__*/

View File

@@ -0,0 +1,40 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__CarriedTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__CarriedTile_H__
//package net.minecraft.world.level.tile;
#include "../../../util/Random.h"
#include "../material/Material.h"
#include "Tile.h"
class CarriedTile: public Tile
{
typedef Tile super;
public:
CarriedTile(int id, int texDefault, int texTop = -1)
: super(id, tex, Material::dirt),
texDefault(texDefault),
texTop(texTop >= 0? texTop : texDefault)
{
}
int getTexture(int face, int data) {
if (face == 1) return texTop;
return texDefault;
}
int getResource(int data, Random* random) {
return 0;
}
int getResourceCount(Random* random) {
return 0;
}
private:
int texDefault;
int texTop;
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__CarriedTile_H__*/

View File

@@ -0,0 +1,321 @@
#include "ChestTile.h"
#include "entity/ChestTileEntity.h"
#include "../Level.h"
#include "../material/Material.h"
#include "../../Facing.h"
#include "../../entity/item/ItemEntity.h"
ChestTile::ChestTile( int id )
: super(id, Material::wood)
{
tex = 10 + 16;
const float m = 0.025f;
setShape(m, 0, m, 1-m, 1-m-m, 1-m);
}
bool ChestTile::isSolidRender()
{
return false;
}
bool ChestTile::isCubeShaped()
{
return false;
}
int ChestTile::getRenderShape()
{
return super::getRenderShape();
//return Tile::SHAPE_ENTITYTILE_ANIMATED;
}
void ChestTile::onPlace( Level* level, int x, int y, int z )
{
super::onPlace(level, x, y, z);
recalcLockDir(level, x, y, z);
//@fullchest
//int n = level->getTile(x, y, z - 1); // face = 2
//int s = level->getTile(x, y, z + 1); // face = 3
//int w = level->getTile(x - 1, y, z); // face = 4
//int e = level->getTile(x + 1, y, z); // face = 5
//if (n == id) recalcLockDir(level, x, y, z - 1);
//if (s == id) recalcLockDir(level, x, y, z + 1);
//if (w == id) recalcLockDir(level, x - 1, y, z);
//if (e == id) recalcLockDir(level, x + 1, y, z);
}
void ChestTile::setPlacedBy( Level* level, int x, int y, int z, Mob* by )
{
int n = level->getTile(x, y, z - 1); // face = 2
int s = level->getTile(x, y, z + 1); // face = 3
int w = level->getTile(x - 1, y, z); // face = 4
int e = level->getTile(x + 1, y, z); // face = 5
int facing = 0;
int dir = (Mth::floor(by->yRot * 4 / (360) + 0.5f)) & 3;
if (dir == 0) facing = Facing::NORTH;
if (dir == 1) facing = Facing::EAST;
if (dir == 2) facing = Facing::SOUTH;
if (dir == 3) facing = Facing::WEST;
if (n != id && s != id && w != id && e != id) {
level->setData(x, y, z, facing);
} else {
if ((n == id || s == id) && (facing == Facing::WEST || facing == Facing::EAST)) {
if (n == id) level->setData(x, y, z - 1, facing);
else level->setData(x, y, z + 1, facing);
level->setData(x, y, z, facing);
}
if ((w == id || e == id) && (facing == Facing::NORTH || facing == Facing::SOUTH)) {
if (w == id) level->setData(x - 1, y, z, facing);
else level->setData(x + 1, y, z, facing);
level->setData(x, y, z, facing);
}
}
}
void ChestTile::recalcLockDir( Level* level, int x, int y, int z )
{
if (level->isClientSide)
return;
int n = level->getTile(x, y, z - 1); // face = 2
int s = level->getTile(x, y, z + 1); // face = 3
int w = level->getTile(x - 1, y, z); // face = 4
int e = level->getTile(x + 1, y, z); // face = 5
// Long!
//@fullchest
int lockDir = 4;
/*
if (n == id || s == id) {
int w2 = level->getTile(x - 1, y, n == id ? z - 1 : z + 1);
int e2 = level->getTile(x + 1, y, n == id ? z - 1 : z + 1);
lockDir = 5;
int otherDir = -1;
if (n == id) otherDir = level->getData(x, y, z - 1);
else otherDir = level->getData(x, y, z + 1);
if (otherDir == 4) lockDir = 4;
if ((Tile::solid[w] || Tile::solid[w2]) && !Tile::solid[e] && !Tile::solid[e2]) lockDir = 5;
if ((Tile::solid[e] || Tile::solid[e2]) && !Tile::solid[w] && !Tile::solid[w2]) lockDir = 4;
} else if (w == id || e == id) {
int n2 = level->getTile(w == id ? x - 1 : x + 1, y, z - 1);
int s2 = level->getTile(w == id ? x - 1 : x + 1, y, z + 1);
lockDir = 3;
int otherDir = -1;
if (w == id) otherDir = level->getData(x - 1, y, z);
else otherDir = level->getData(x + 1, y, z);
if (otherDir == 2) lockDir = 2;
if ((Tile::solid[n] || Tile::solid[n2]) && !Tile::solid[s] && !Tile::solid[s2]) lockDir = 3;
if ((Tile::solid[s] || Tile::solid[s2]) && !Tile::solid[n] && !Tile::solid[n2]) lockDir = 2;
} else */ {
lockDir = level->getData(x, y, z);
if ((lockDir == Facing::NORTH && Tile::solid[n])
|| (lockDir == Facing::SOUTH && Tile::solid[s])
|| (lockDir == Facing::WEST && Tile::solid[w])
|| (lockDir == Facing::EAST && Tile::solid[e])) {
if (Tile::solid[n] && !Tile::solid[s]) lockDir = Facing::SOUTH;
if (Tile::solid[s] && !Tile::solid[n]) lockDir = Facing::NORTH;
if (Tile::solid[w] && !Tile::solid[e]) lockDir = Facing::EAST;
if (Tile::solid[e] && !Tile::solid[w]) lockDir = Facing::WEST;
}
}
level->setData(x, y, z, lockDir);
}
int ChestTile::getTexture( LevelSource* level, int x, int y, int z, int face )
{
if (face == 1) return tex - 1;
if (face == 0) return tex - 1;
/*
int n = level->getTile(x, y, z - 1); // face = 2
int s = level->getTile(x, y, z + 1); // face = 3
int w = level->getTile(x - 1, y, z); // face = 4
int e = level->getTile(x + 1, y, z); // face = 5
*/
// Long!
//@fullchest
/*
if (n == id || s == id) {
if (face == 2 || face == 3) return tex;
int offs = 0;
if (n == id) {
offs = -1;
}
int w2 = level->getTile(x - 1, y, n == id ? z - 1 : z + 1);
int e2 = level->getTile(x + 1, y, n == id ? z - 1 : z + 1);
if (face == 4) offs = -1 - offs;
int lockDir = 5;
if ((Tile::solid[w] || Tile::solid[w2]) && !Tile::solid[e] && !Tile::solid[e2]) lockDir = 5;
if ((Tile::solid[e] || Tile::solid[e2]) && !Tile::solid[w] && !Tile::solid[w2]) lockDir = 4;
return (face == lockDir ? tex + 16 : tex + 32) + offs;
} else if (w == id || e == id) {
if (face == 4 || face == 5) return tex;
int offs = 0;
if (w == id) {
offs = -1;
}
int n2 = level->getTile(w == id ? x - 1 : x + 1, y, z - 1);
int s2 = level->getTile(w == id ? x - 1 : x + 1, y, z + 1);
if (face == 3) offs = -1 - offs;
int lockDir = 3;
if ((Tile::solid[n] || Tile::solid[n2]) && !Tile::solid[s] && !Tile::solid[s2]) lockDir = 3;
if ((Tile::solid[s] || Tile::solid[s2]) && !Tile::solid[n] && !Tile::solid[n2]) lockDir = 2;
return (face == lockDir ? tex + 16 : tex + 32) + offs;
} else { */
//int lockDir = 3;
int lockDir = level->getData(x, y, z);
/*
if ((lockDir == Facing::NORTH && Tile::solid[n])
|| (lockDir == Facing::SOUTH && Tile::solid[s])
|| (lockDir == Facing::WEST && Tile::solid[w])
|| (lockDir == Facing::EAST && Tile::solid[e])) {
if (Tile::solid[n] && !Tile::solid[s]) lockDir = 3;
if (Tile::solid[s] && !Tile::solid[n]) lockDir = 2;
if (Tile::solid[w] && !Tile::solid[e]) lockDir = 5;
if (Tile::solid[e] && !Tile::solid[w]) lockDir = 4;
}
*/
/*
if (Tile::solid[n] && !Tile::solid[s]) lockDir = 3;
if (Tile::solid[s] && !Tile::solid[n]) lockDir = 2;
if (Tile::solid[w] && !Tile::solid[e]) lockDir = 5;
if (Tile::solid[e] && !Tile::solid[w]) lockDir = 4;
*/
return (face == lockDir)? tex + 1 : tex;
}
int ChestTile::getTexture( int face )
{
if (face == 1) return tex - 1;
if (face == 0) return tex - 1;
if (face == 3) return tex + 1;
return tex;
}
bool ChestTile::mayPlace( Level* level, int x, int y, int z, unsigned char face )
{
int chestCount = 0;
if (level->getTile(x - 1, y, z) == id) chestCount++;
if (level->getTile(x + 1, y, z) == id) chestCount++;
if (level->getTile(x, y, z - 1) == id) chestCount++;
if (level->getTile(x, y, z + 1) == id) chestCount++;
//@fullchest
if (chestCount > 0) return false;
//if (isFullChest(level, x - 1, y, z)) return false;
//if (isFullChest(level, x + 1, y, z)) return false;
//if (isFullChest(level, x, y, z - 1)) return false;
//if (isFullChest(level, x, y, z + 1)) return false;
return true;
}
void ChestTile::neighborChanged( Level* level, int x, int y, int z, int type )
{
super::neighborChanged(level, x, y, z, type);
recalcLockDir(level, x, y, z);
TileEntity* te = level->getTileEntity(x, y, z);
if (te != NULL) te->clearCache();
}
void ChestTile::onRemove( Level* level, int x, int y, int z )
{
if (!level->isClientSide) {
TileEntity* te = level->getTileEntity(x, y, z);
if (te != NULL && te->type == TileEntityType::Chest) {
Container* container = (ChestTileEntity*) te;
for (int i = 0; i < container->getContainerSize(); i++) {
ItemInstance* item = container->getItem(i);
if (item != NULL) {
float xo = random.nextFloat() * 0.8f + 0.1f;
float yo = random.nextFloat() * 0.8f + 0.1f;
float zo = random.nextFloat() * 0.8f + 0.1f;
while (item->count > 0) {
int count = random.nextInt(21) + 10;
if (count > item->count) count = item->count;
item->count -= count;
ItemEntity* itemEntity = new ItemEntity(level, x + xo, y + yo, z + zo, ItemInstance(item->id, count, item->getAuxValue()));
float pow = 0.05f;
itemEntity->xd = (float) random.nextGaussian() * pow;
itemEntity->yd = (float) random.nextGaussian() * pow + 0.2f;
itemEntity->zd = (float) random.nextGaussian() * pow;
//if (item->hasTag()) {
// itemEntity->item->setTag((CompoundTag*) item->getTag()->copy());
//}
level->addEntity(itemEntity);
}
}
}
}
}
super::onRemove(level, x, y, z);
}
bool ChestTile::use( Level* level, int x, int y, int z, Player* player )
{
TileEntity* te = level->getTileEntity(x, y, z);
if (!TileEntity::isType(te, TileEntityType::Chest))
return true;
ChestTileEntity* chest = (ChestTileEntity*) te;
if (level->isSolidBlockingTile(x, y + 1, z)) return true;
// @fullchest
//if (level->getTile(x - 1, y, z) == id && (level->isSolidBlockingTile(x - 1, y + 1, z))) return true;
//if (level->getTile(x + 1, y, z) == id && (level->isSolidBlockingTile(x + 1, y + 1, z))) return true;
//if (level->getTile(x, y, z - 1) == id && (level->isSolidBlockingTile(x, y + 1, z - 1))) return true;
//if (level->getTile(x, y, z + 1) == id && (level->isSolidBlockingTile(x, y + 1, z + 1))) return true;
//if (level->getTile(x - 1, y, z) == id) container = /*new*/ CompoundContainer("Large chest", (ChestTileEntity) level->getTileEntity(x - 1, y, z), container);
//if (level->getTile(x + 1, y, z) == id) container = /*new*/ CompoundContainer("Large chest", container, (ChestTileEntity) level->getTileEntity(x + 1, y, z));
//if (level->getTile(x, y, z - 1) == id) container = /*new*/ CompoundContainer("Large chest", (ChestTileEntity) level->getTileEntity(x, y, z - 1), container);
//if (level->getTile(x, y, z + 1) == id) container = /*new*/ CompoundContainer("Large chest", container, (ChestTileEntity) level->getTileEntity(x, y, z + 1));
if (level->isClientSide) {
return true;
}
player->openContainer(chest);
return true;
}
TileEntity* ChestTile::newTileEntity()
{
return TileEntityFactory::createTileEntity(TileEntityType::Chest);
}
bool ChestTile::isFullChest( Level* level, int x, int y, int z )
{
return false; //@fullchest
/*
if (level->getTile(x, y, z) != id) return false;
if (level->getTile(x - 1, y, z) == id) return true;
if (level->getTile(x + 1, y, z) == id) return true;
if (level->getTile(x, y, z - 1) == id) return true;
if (level->getTile(x, y, z + 1) == id) return true;
return false;
*/
}

View File

@@ -0,0 +1,51 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__ChestTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__ChestTile_H__
#include "EntityTile.h"
class Level;
class LevelSource;
class Mob;
#include "../../../util/Random.h"
//package net.minecraft.world.level->tile;
class ChestTile: public EntityTile
{
typedef EntityTile super;
public:
static const int EVENT_SET_OPEN_COUNT = 1;
ChestTile(int id);
bool isSolidRender();
/*@Override*/
bool isCubeShaped();
int getRenderShape();
bool mayPlace(Level* level, int x, int y, int z, unsigned char face);
void setPlacedBy(Level* level, int x, int y, int z, Mob* by);
void onPlace(Level* level, int x, int y, int z);
void onRemove(Level* level, int x, int y, int z);
void recalcLockDir(Level* level, int x, int y, int z);
int getTexture(LevelSource* level, int x, int y, int z, int face);
int getTexture(int face);
void neighborChanged(Level* level, int x, int y, int z, int type);
bool use(Level* level, int x, int y, int z, Player* player);
TileEntity* newTileEntity();
private:
bool isFullChest(Level* level, int x, int y, int z);
Random random;
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__ChestTile_H__*/

26
src/world/level/tile/ClayTile.h Executable file
View File

@@ -0,0 +1,26 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__ClayTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__ClayTile_H__
//package net.minecraft.world.level.tile;
#include "../../../util/Random.h"
#include "../material/Material.h"
#include "Tile.h"
class ClayTile: public Tile {
public:
ClayTile(int id, int tex)
: Tile(id, tex, Material::clay)
{}
int getResource(int data, Random* random) {
return Item::clay->id;
}
int getResourceCount(Random* random) {
return 4;
}
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__ClayTile_H__*/

View File

@@ -0,0 +1,45 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__ClothTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__ClothTile_H__
//package net.minecraft.world.level.tile;
#include "../material/Material.h"
class ClothTile: public Tile
{
typedef Tile super;
static const int COLOR_TEX_POS = 7 * 16 + 1;
public:
ClothTile(int id)
: super(id, 4 * 16, Material::cloth)
{
}
ClothTile(int id, int data)
: super(id, 4 * 16, Material::cloth)
{
}
int getTexture(int face, int data) {
if (data == 0) {
// un-colored cloth
return tex;
}
// invert bits (so 1111 becomes black)
data = ~(data & 0xf);
return COLOR_TEX_POS + ((data & 8) >> 3) + ((data & 7) * 16);
}
static int getTileDataForItemAuxValue(int auxValue) {
return (~auxValue & 0xf);
}
protected:
int getSpawnResourcesAuxValue(int data) {
return data;
}
static int getItemAuxValueForTileData(int data) {
return (~data & 0xf);
}
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__ClothTile_H__*/

113
src/world/level/tile/CropTile.cpp Executable file
View File

@@ -0,0 +1,113 @@
#include "CropTile.h"
#include "Tile.h"
#include "../../entity/item/ItemEntity.h"
CropTile::CropTile( int id, int tex ) : super(id, tex) {
this->tex = tex;
setTicking(true);
float ss = 0.5f;
setShape(0.5f - ss, 0, 0.5f - ss, 0.5f + ss, 0.25f, 0.5f + ss);
}
void CropTile::tick( Level* level, int x, int y, int z, Random* random ) {
super::tick(level, x, y, z, random);
if(level->getRawBrightness(x, y, z) >= Level::MAX_BRIGHTNESS - 6) {
int age = level->getData(x, y, z);
if(age < 7) {
float growthSpeed = getGrowthSpeed(level, x, y, z);
if(random->nextInt(int(25 / growthSpeed)) == 0) {
age++;
level->setData(x, y, z, age);
}
}
}
}
void CropTile::growCropsToMax( Level* level, int x, int y, int z ) {
level->setData(x, y, z, 7);
}
float CropTile::getGrowthSpeed( Level* level, int x, int y, int z ) {
float speed = 1;
int n = level->getTile(x, y, z - 1);
int s = level->getTile(x, y, z + 1);
int w = level->getTile(x - 1, y, z);
int e = level->getTile(x + 1, y, z);
int d0 = level->getTile(x - 1, y, z - 1);
int d1 = level->getTile(x + 1, y, z - 1);
int d2 = level->getTile(x + 1, y, z + 1);
int d3 = level->getTile(x - 1, y, z + 1);
bool horizontal = w == this->id || e == this->id;
bool vertical = n == this->id || s == this->id;
bool diagonal = d0 == this->id || d1 == this->id || d2 == this->id || d3 == this->id;
for (int xx = x - 1; xx <= x + 1; xx++) {
for (int zz = z - 1; zz <= z + 1; zz++) {
int t = level->getTile(xx, y - 1, zz);
float tileSpeed = 0;
if (t == Tile::farmland->id) {
tileSpeed = 1;
if (level->getData(xx, y - 1, zz) > 0) tileSpeed = 3;
}
if (xx != x || zz != z) tileSpeed /= 4;
speed += tileSpeed;
}
}
if (diagonal || (horizontal && vertical)) speed /= 2;
return speed;
}
int CropTile::getTexture( LevelSource* level, int x, int y, int z, int face ) {
int data = level->getData(x, y, z);
if (data < 0) data = 7;
return tex + data;
}
int CropTile::getTexture( int face, int data ) {
if (data < 0) data = 7;
return tex + data;
}
int CropTile::getRenderShape() {
return Tile::SHAPE_ROWS;
}
void CropTile::spawnResources( Level* level, int x, int y, int z, int data, float odds ) {
super::spawnResources(level, x, y, z, data, odds);
if (level->isClientSide) {
return;
}
int count = 3;
for (int i = 0; i < count; i++) {
if (level->random.nextInt(5 * 3) > data) continue;
float s = 0.7f;
float xo = level->random.nextFloat() * s + (1 - s) * 0.5f;
float yo = level->random.nextFloat() * s + (1 - s) * 0.5f;
float zo = level->random.nextFloat() * s + (1 - s) * 0.5f;
ItemEntity* item = new ItemEntity(level, float(x) + xo, float(y) + yo, float(z) + zo, ItemInstance(Item::seeds_wheat));
item->throwTime = 10;
level->addEntity(item);
}
}
int CropTile::getResource( int data, Random* random ) {
if (data == 7) {
return Item::wheat->id;
}
return -1;
}
int CropTile::getResourceCount( Random* random ) {
return 1;
}
bool CropTile::mayPlaceOn( int tile ) {
return tile == Tile::farmland->id;
}

29
src/world/level/tile/CropTile.h Executable file
View File

@@ -0,0 +1,29 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__CropTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__CropTile_H__
#include "Bush.h"
class CropTile : public Bush
{
typedef Bush super;
public:
CropTile(int id, int tex);
bool mayPlaceOn(int tile);
void tick(Level* level, int x, int y, int z, Random* random);
int getTexture(LevelSource* level, int x, int y, int z, int face);
int getTexture( int face, int data );
int getRenderShape();
void spawnResources(Level* level, int x, int y, int z, int data, float odds);
int getResource(int data, Random* random);
int getResourceCount(Random* random);
void growCropsToMax(Level* level, int x, int y, int z);
private:
float getGrowthSpeed(Level* level, int x, int y, int z);
};
#endif /* NET_MINECRAFT_WORLD_LEVEL_TILE__CropTile_H__ */

View File

@@ -0,0 +1,17 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__DirectionalTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__DirectionalTile_H__
#include "Tile.h"
class Material;
class DirectionalTile : public Tile {
public:
static const int DIRECTION_MASK = 0x3;
static const int DIRECTION_INV_MASK = 0xc;
static int getDirection(int data) {
return data & DIRECTION_MASK;
}
protected:
DirectionalTile(int id, int tex, const Material* material) : Tile(id, tex, material) {}
DirectionalTile(int id, const Material* material) : Tile(id, material) {}
};
#endif /* NET_MINECRAFT_WORLD_LEVEL_TILE__DirectionalTile_H__ */

20
src/world/level/tile/DirtTile.h Executable file
View File

@@ -0,0 +1,20 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__DirtTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__DirtTile_H__
//package net.minecraft.world.level.tile;
#include "../material/Material.h"
#include "Tile.h"
class DirtTile: public Tile
{
public:
/*protected*/
DirtTile(int id, int tex)
: Tile(id, tex, Material::dirt)
{
}
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__DirtTile_H__*/

230
src/world/level/tile/DoorTile.cpp Executable file
View File

@@ -0,0 +1,230 @@
#include "DoorTile.h"
#include "LevelEvent.h"
#include "../Level.h"
#include "../../item/Item.h"
#include "../../entity/player/Player.h"
DoorTile::DoorTile(int id, const Material* material)
: super(id, material)
{
tex = 1 + 6 * 16;
if (material == Material::metal) tex++;
float r = 0.5f;
float h = 1.0f;
super::setShape(0.5f - r, 0, 0.5f - r, 0.5f + r, h, 0.5f + r);
}
int DoorTile::getTexture(LevelSource* level, int x, int y, int z, int face) {
if (face == 0 || face == 1) return tex;
int compositeData = getCompositeData(level, x, y, z);
int texture = tex;
if ((compositeData & C_IS_UPPER_MASK) != 0) texture -= 16;
int dir = compositeData & C_DIR_MASK;
bool isOpen = (compositeData & C_OPEN_MASK) != 0;
if (isOpen) {
if (dir == 0 && face == 2) texture = -texture;
else if (dir == 1 && face == 5) texture = -texture;
else if (dir == 2 && face == 3) texture = -texture;
else if (dir == 3 && face == 4) texture = -texture;
} else {
if (dir == 0 && face == 5) texture = -texture;
else if (dir == 1 && face == 3) texture = -texture;
else if (dir == 2 && face == 4) texture = -texture;
else if (dir == 3 && face == 2) texture = -texture;
if ((compositeData & C_RIGHT_HINGE_MASK) != 0) texture = -texture;
}
return texture;
}
bool DoorTile::blocksLight() {
return false;
}
bool DoorTile::isSolidRender() {
return false;
}
bool DoorTile::isCubeShaped() {
return false;
}
int DoorTile::getRenderShape() {
return Tile::SHAPE_DOOR;
}
int DoorTile::getRenderLayer() {
return Tile::RENDERLAYER_ALPHATEST;
}
AABB DoorTile::getTileAABB(Level* level, int x, int y, int z) {
updateShape(level, x, y, z);
return super::getTileAABB(level, x, y, z);
}
AABB* DoorTile::getAABB(Level* level, int x, int y, int z) {
updateShape(level, x, y, z);
return super::getAABB(level, x, y, z);
}
void DoorTile::updateShape(LevelSource* level, int x, int y, int z) {
setShape(getCompositeData(level, x, y, z));
}
void DoorTile::setShape(int compositeData) {
float r = 3 / 16.0f;
super::setShape(0, 0, 0, 1, 2, 1);
int dir = compositeData & C_DIR_MASK;
bool open = (compositeData & C_OPEN_MASK) != 0;
bool hasRightHinge = (compositeData & C_RIGHT_HINGE_MASK) != 0;
if (dir == 0) {
if (open) {
if (!hasRightHinge) super::setShape(0, 0, 0, 1, 1, r);
else super::setShape(0, 0, 1 - r, 1, 1, 1);
} else super::setShape(0, 0, 0, r, 1, 1);
} else if (dir == 1) {
if (open) {
if (!hasRightHinge) super::setShape(1 - r, 0, 0, 1, 1, 1);
else super::setShape(0, 0, 0, r, 1, 1);
} else super::setShape(0, 0, 0, 1, 1, r);
} else if (dir == 2) {
if (open) {
if (!hasRightHinge) super::setShape(0, 0, 1 - r, 1, 1, 1);
else super::setShape(0, 0, 0, 1, 1, r);
} else super::setShape(1 - r, 0, 0, 1, 1, 1);
} else if (dir == 3) {
if (open) {
if (!hasRightHinge) super::setShape(0, 0, 0, r, 1, 1);
else super::setShape(1 - r, 0, 0, 1, 1, 1);
} else super::setShape(0, 0, 1 - r, 1, 1, 1);
}
}
void DoorTile::attack(Level* level, int x, int y, int z, Player* player) {
use(level, x, y, z, player);
}
bool DoorTile::use(Level* level, int x, int y, int z, Player* player) {
if (material == Material::metal) return true;
int compositeData = getCompositeData(level, x, y, z);
int lowerData = compositeData & C_LOWER_DATA_MASK;
lowerData ^= 4;
if ((compositeData & C_IS_UPPER_MASK) == 0) {
level->setData(x, y, z, lowerData);
level->setTilesDirty(x, y, z, x, y, z);
} else {
level->setData(x, y - 1, z, lowerData);
level->setTilesDirty(x, y - 1, z, x, y, z);
}
level->levelEvent(player, LevelEvent::SOUND_OPEN_DOOR, x, y, z, 0);
return true;
}
bool DoorTile::isOpen( LevelSource* level, int x, int y, int z )
{
return (getCompositeData(level, x, y, z) & C_OPEN_MASK) != 0;
}
void DoorTile::setOpen(Level* level, int x, int y, int z, bool shouldOpen) {
int compositeData = getCompositeData(level, x, y, z);
bool isOpen = (compositeData & C_OPEN_MASK) != 0;
if (isOpen == shouldOpen) return;
int lowerData = compositeData & C_LOWER_DATA_MASK;
lowerData ^= 4;
if ((compositeData & C_IS_UPPER_MASK) == 0) {
level->setData(x, y, z, lowerData);
level->setTilesDirty(x, y, z, x, y, z);
} else {
level->setData(x, y - 1, z, lowerData);
level->setTilesDirty(x, y - 1, z, x, y, z);
}
level->levelEvent(NULL, LevelEvent::SOUND_OPEN_DOOR, x, y, z, 0);
}
void DoorTile::neighborChanged(Level* level, int x, int y, int z, int type) {
int data = level->getData(x, y, z);
if ((data & UPPER_BIT) == 0) {
bool spawn = false;
if (level->getTile(x, y + 1, z) != id) {
level->setTile(x, y, z, 0);
spawn = true;
}
if (!level->isSolidBlockingTile(x, y - 1, z)) {
level->setTile(x, y, z, 0);
spawn = true;
if (level->getTile(x, y + 1, z) == id) {
level->setTile(x, y + 1, z, 0);
}
}
if (spawn) {
if (!level->isClientSide) {
spawnResources(level, x, y, z, data, 0);
}
} else {
bool signal = level->hasNeighborSignal(x, y, z) || level->hasNeighborSignal(x, y + 1, z);
if ((signal || ((type > 0 && Tile::tiles[type]->isSignalSource()) || type == 0)) && type != id) {
setOpen(level, x, y, z, signal);
}
}
} else {
if (level->getTile(x, y - 1, z) != id) {
level->setTile(x, y, z, 0);
if(material == Material::metal) {
popResource(level, x, y, z, ItemInstance(Item::door_iron));
} else {
popResource(level, x, y, z, ItemInstance(Item::door_wood));
}
}
if (type > 0 && type != id) {
neighborChanged(level, x, y - 1, z, type);
}
}
}
int DoorTile::getResource(int data, Random* random) {
if ((data & 8) != 0) return 0;
if (material == Material::metal) return Item::door_iron->id;
return Item::door_wood->id;
}
HitResult DoorTile::clip(Level* level, int xt, int yt, int zt, const Vec3& a, const Vec3& b) {
updateShape(level, xt, yt, zt);
return super::clip(level, xt, yt, zt, a, b);
}
int DoorTile::getDir(LevelSource* level, int x, int y, int z) {
return getCompositeData(level, x, y, z) & C_DIR_MASK;
}
bool DoorTile::mayPlace(Level* level, int x, int y, int z, unsigned char face) {
if (y >= Level::DEPTH - 1) return false;
return (level->isSolidBlockingTile(x, y - 1, z)
&& super::mayPlace(level, x, y, z)
&& super::mayPlace(level, x, y + 1, z));
}
int DoorTile::getCompositeData( LevelSource* level, int x, int y, int z ) {
int data = level->getData(x, y, z);
bool isUpper = (data & UPPER_BIT) != 0;
int lowerData;
int upperData;
if (isUpper) {
lowerData = level->getData(x, y - 1, z);
upperData = data;
} else {
lowerData = data;
upperData = level->getData(x, y + 1, z);
}
// bits: dir, dir, open/closed, isUpper, isRightHinge
bool isRightHinge = (upperData & 1) != 0;
return lowerData & C_LOWER_DATA_MASK | (isUpper ? 8 : 0) | (isRightHinge ? 16 : 0);
}

61
src/world/level/tile/DoorTile.h Executable file
View File

@@ -0,0 +1,61 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__DoorTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__DoorTile_H__
//package net.minecraft.world.level->tile;
#include "Tile.h"
#include "../material/Material.h"
#include "../../../util/Random.h"
class Item;
class Level;
class LevelSource;
class Player;
class DoorTile: public Tile
{
typedef Tile super;
public:
static const int UPPER_BIT = 8;
static const int C_DIR_MASK = 3;
static const int C_OPEN_MASK = 4;
static const int C_LOWER_DATA_MASK = 7;
static const int C_IS_UPPER_MASK = 8;
static const int C_RIGHT_HINGE_MASK = 16;
DoorTile(int id, const Material* material);
int getTexture(LevelSource* level, int x, int y, int z, int face);
bool blocksLight();
bool isSolidRender();
bool isCubeShaped();
int getRenderShape();
int getRenderLayer();
AABB getTileAABB(Level* level, int x, int y, int z);
AABB* getAABB(Level* level, int x, int y, int z);
void updateShape(LevelSource* level, int x, int y, int z);
void setShape(int compositeData);
void attack(Level* level, int x, int y, int z, Player* player);
bool use(Level* level, int x, int y, int z, Player* player);
void setOpen(Level* level, int x, int y, int z, bool shouldOpen);
static bool isOpen(LevelSource* level, int x, int y, int z);
void neighborChanged(Level* level, int x, int y, int z, int type);
int getResource(int data, Random* random);
HitResult clip(Level* level, int xt, int yt, int zt, const Vec3& a, const Vec3& b);
int getDir(LevelSource* level, int x, int y, int z);
bool mayPlace(Level* level, int x, int y, int z, unsigned char face);
static int getCompositeData(LevelSource* level, int x, int y, int z);
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__DoorTile_H__*/

View File

@@ -0,0 +1,38 @@
#include "EntityTile.h"
#include "entity/TileEntity.h"
#include "../Level.h"
#include "../material/Material.h"
void EntityTile::onPlace( Level* level, int x, int y, int z )
{
super::onPlace(level, x, y, z);
level->setTileEntity(x, y, z, newTileEntity());
}
void EntityTile::onRemove( Level* level, int x, int y, int z )
{
super::onRemove(level, x, y, z);
level->removeTileEntity(x, y, z);
}
void EntityTile::triggerEvent( Level* level, int x, int y, int z, int b0, int b1 )
{
super::triggerEvent(level, x, y, z, b0, b1);
TileEntity* te = level->getTileEntity(x, y, z);
if (te != NULL) {
te->triggerEvent(b0, b1);
}
}
EntityTile::EntityTile( int id, const Material* material )
: super(id, material)
{
isEntityTile[this->id] = true;
}
EntityTile::EntityTile( int id, int tex, const Material* material )
: super(id, tex, material)
{
isEntityTile[this->id] = true;
}

View File

@@ -0,0 +1,28 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__EntityTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__EntityTile_H__
//package net.minecraft.world.level->tile;
#include "Tile.h"
class Level;
class TileEntity;
class Material;
/*abstract*/
class EntityTile: public Tile
{
typedef Tile super;
public:
virtual TileEntity* newTileEntity() = 0;
void onPlace(Level* level, int x, int y, int z);
void onRemove(Level* level, int x, int y, int z);
void triggerEvent(Level* level, int x, int y, int z, int b0, int b1);
protected:
EntityTile(int id, const Material* material);
EntityTile(int id, int tex, const Material* material);
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__EntityTile_H__*/

110
src/world/level/tile/FarmTile.h Executable file
View File

@@ -0,0 +1,110 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__FarmTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__FarmTile_H__
//package net.minecraft.world.level.tile;
#include "../../../util/Random.h"
#include "../material/Material.h"
#include "../Level.h"
#include "Tile.h"
class FarmTile: public Tile {
public:
FarmTile(int id)
: Tile(id, Material::dirt)
{
tex = 7 + 5 * 16;
setTicking(true);
setShape(0, 0, 0, 1, 15 / 16.0f, 1);
setLightBlock(255);
}
AABB* getAABB(Level* level, int x, int y, int z) {
tmpBB.x0 = (float)x;
tmpBB.y0 = (float)y;
tmpBB.z0 = (float)z;
tmpBB.x1 = (float)(x + 1);
tmpBB.y1 = (float)(y + 1);
tmpBB.z1 = (float)(z + 1);
return &tmpBB;
}
bool isSolidRender() {
return false;
}
bool isCubeShaped() {
return false;
}
int getTexture(int face, int data) {
if (face == 1 && data > 0) return tex - 1;
if (face == 1) return tex;
return 2;
}
void tick(Level* level, int x, int y, int z, Random* random) {
if (isNearWater(level, x, y, z)) {
level->setData(x, y, z, 7);
} else {
int moisture = level->getData(x, y, z);
if (moisture > 0) {
level->setData(x, y, z, moisture - 1);
} else {
if (!isUnderCrops(level, x, y, z)) {
level->setTile(x, y, z, Tile::dirt->id);
}
}
}
}
void fallOn(Level* level, int x, int y, int z, Entity* entity, float fallDistance) {
if (!level->isClientSide && level->random.nextFloat() < (fallDistance - .5f)) {
level->setTile(x, y, z, Tile::dirt->id);
}
}
void neighborChanged(Level* level, int x, int y, int z, int type) {
Tile::neighborChanged(level, x, y, z, type);
const Material* above = level->getMaterial(x, y + 1, z);
if (above->isSolid()) {
level->setTile(x, y, z, Tile::dirt->id);
}
}
bool blocksLight() {
return true;
}
int getResource(int data, Random* random) {
return Tile::dirt->getResource(0, random);
}
private:
bool isUnderCrops(Level* level, int x, int y, int z) {
int r = 0;
for (int xx = x - r; xx <= x + r; xx++)
for (int zz = z - r; zz <= z + r; zz++) {
if (level->getTile(xx, y + 1, zz) == Tile::crops->id) {
return true;
}
}
return false;
}
bool isNearWater(Level* level, int x, int y, int z) {
for (int xx = x - 4; xx <= x + 4; xx++) {
for (int yy = y; yy <= y + 1; yy++) {
for (int zz = z - 4; zz <= z + 4; zz++) {
if (level->getMaterial(xx, yy, zz) == Material::water) {
return true;
}
}
}
}
return false;
}
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__FarmTile_H__*/

View File

@@ -0,0 +1,98 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__FenceGateTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__FenceGateTile_H__
#include "Tile.h"
#include "LevelEvent.h"
#include "../Level.h"
#include "../material/Material.h"
#include "../../Direction.h"
#include "../../entity/Mob.h"
#include "../../entity/player/Player.h"
#include "../../phys/AABB.h"
#include "../../../util/Mth.h"
class FenceGateTile: public Tile
{
typedef Tile super;
static const int DIRECTION_MASK = 3;
static const int OPEN_BIT = 4;
public:
FenceGateTile(int id, int tex)
: super(id, tex, Material::wood)
{
}
bool mayPlace(Level* level, int x, int y, int z) {
if (!level->getMaterial(x, y - 1, z)->isSolid()) return false;
return super::mayPlace(level, x, y, z);
}
/*@Override*/
AABB* getAABB(Level* level, int x, int y, int z) {
int data = level->getData(x, y, z);
if (isOpen(data)) {
return NULL;
}
const float xx = (float)x;
const float yy = (float)y;
const float zz = (float)z;
if (data == Direction::NORTH || data == Direction::SOUTH) {
tmpBB.set(xx, yy, zz + 6.0f / 16.0f, xx + 1, yy + 1.5f, zz + 10.0f / 16.0f);
} else {
tmpBB.set(xx + 6.0f / 16.0f, yy, zz, xx + 10.0f / 16.0f, yy + 1.5f, zz + 1);
}
return &tmpBB;
}
bool blocksLight() {
return false;
}
bool isSolidRender() {
return false;
}
bool isCubeShaped() {
return false;
}
int getRenderShape() {
return Tile::SHAPE_FENCE_GATE;
}
/*@Override*/
void setPlacedBy(Level* level, int x, int y, int z, Mob* by) {
int dir = (((Mth::floor(by->yRot * 4 / (360) + 0.5f)) & 3)) % 4;
level->setData(x, y, z, dir);
}
/*@Override*/
bool use(Level* level, int x, int y, int z, Player* player) {
int data = level->getData(x, y, z);
if (isOpen(data)) {
level->setData(x, y, z, data & ~OPEN_BIT);
} else {
// open the door from the player
int dir = (((Mth::floor(player->yRot * 4 / (360) + 0.5f)) & 3)) % 4;
int current = getDirection(data);
if (current == ((dir + 2) % 4)) {
data = dir;
}
level->setData(x, y, z, data | OPEN_BIT);
}
level->levelEvent(player, LevelEvent::SOUND_OPEN_DOOR, x, y, z, 0);
return true;
}
static bool isOpen(int data) {
return (data & OPEN_BIT) != 0;
}
static int getDirection(int data) {
return (data & DIRECTION_MASK);
}
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__FenceGateTile_H__*/

117
src/world/level/tile/FenceTile.h Executable file
View File

@@ -0,0 +1,117 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__FenceTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__FenceTile_H__
//package net.minecraft.world.level->tile;
#include "Tile.h"
/* import net.minecraft.world.level->* */
#include "../material/Material.h"
#include "../../phys/AABB.h"
class FenceTile: public Tile
{
typedef Tile super;
public:
FenceTile(int id, int tex)
: super(id, tex, Material::wood)
{
}
FenceTile(int id, int tex, const Material* material)
: super(id, tex, material)
{
}
bool mayPlace(Level* level, int x, int y, int z) {
return super::mayPlace(level, x, y, z);
}
/*@Override*/
AABB* getAABB(Level* level, int x, int y, int z) {
bool n = connectsTo(level, x, y, z - 1);
bool s = connectsTo(level, x, y, z + 1);
bool w = connectsTo(level, x - 1, y, z);
bool e = connectsTo(level, x + 1, y, z);
float west = 6.0f / 16.0f;
float east = 10.0f / 16.0f;
float north = 6.0f / 16.0f;
float south = 10.0f / 16.0f;
if (n) {
north = 0;
}
if (s) {
south = 1;
}
if (w) {
west = 0;
}
if (e) {
east = 1;
}
tmpBB.set((float)x + west, (float)y, (float)z + north, (float)x + east, (float)y + 1.5f, (float)z + south);
return &tmpBB;
}
/*@Override*/
void updateShape(LevelSource* level, int x, int y, int z) {
bool n = connectsTo(level, x, y, z - 1);
bool s = connectsTo(level, x, y, z + 1);
bool w = connectsTo(level, x - 1, y, z);
bool e = connectsTo(level, x + 1, y, z);
float west = 6.0f / 16.0f;
float east = 10.0f / 16.0f;
float north = 6.0f / 16.0f;
float south = 10.0f / 16.0f;
if (n) {
north = 0;
}
if (s) {
south = 1;
}
if (w) {
west = 0;
}
if (e) {
east = 1;
}
setShape(west, 0, north, east, 1.0f, south);
}
bool blocksLight() {
return false;
}
bool isSolidRender() {
return false;
}
bool isCubeShaped() {
return false;
}
int getRenderShape() {
return Tile::SHAPE_FENCE;
}
bool connectsTo(LevelSource* level, int x, int y, int z) {
int tile = level->getTile(x, y, z);
if (tile == id || tile == Tile::fenceGate->id) {
return true;
}
Tile* tileInstance = Tile::tiles[tile];
if (tileInstance != NULL) {
if (tileInstance->material->isSolidBlocking() && tileInstance->isCubeShaped()) {
return tileInstance->material != Material::vegetable;
}
}
return false;
}
};
#endif /*NET_MINECRAFT_WORLD_LEVEL->TILE__FenceTile_H__*/

309
src/world/level/tile/FireTile.h Executable file
View File

@@ -0,0 +1,309 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__FireTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__FireTile_H__
//package net.minecraft.world.level.tile;
#include "../../../util/Random.h"
#include "../material/Material.h"
#include "../Level.h"
#include "Tile.h"
class FireTile: public Tile
{
int flameOdds[256];
int burnOdds[256];
public:
static const int FLAME_INSTANT = 60;
static const int FLAME_EASY = 30;
static const int FLAME_MEDIUM = 15;
static const int FLAME_HARD = 5;
static const int BURN_INSTANT = 100;
static const int BURN_EASY = 60;
static const int BURN_MEDIUM = 20;
static const int BURN_HARD = 5;
static const int BURN_NEVER = 0;
FireTile(int id, int tex)
: Tile(id, tex, Material::fire)
{
for (int i = 0; i < 256; ++i)
flameOdds[i] = burnOdds[i] = 0;
setFlammable(Tile::wood->id, FLAME_HARD, BURN_MEDIUM);
setFlammable(Tile::treeTrunk->id, FLAME_HARD, BURN_HARD);
setFlammable(((Tile*)Tile::leaves)->id, FLAME_EASY, BURN_EASY);
setFlammable(Tile::bookshelf->id, FLAME_EASY, BURN_MEDIUM);
setFlammable(Tile::tnt->id, FLAME_MEDIUM, BURN_INSTANT);
setFlammable(Tile::cloth->id, FLAME_EASY, BURN_EASY);
//setTicking(true); //@fire
}
AABB* getAABB(Level* level, int x, int y, int z) {
return NULL;
}
bool blocksLight() {
return false;
}
bool isSolidRender() {
return false;
}
bool isCubeShaped() {
return false;
}
int getRenderShape() {
return Tile::SHAPE_FIRE;
}
int getResourceCount(Random* random) {
return 0;
}
int getTickDelay() {
return 10;
}
void tick(Level* level, int x, int y, int z, Random* random) {
return; //@fire
bool infiniBurn = false;//level->getTile(x, y - 1, z) == Tile::hellRock->id;
int age = level->getData(x, y, z);
if (age < 15) {
level->setData(x, y, z, age + 1);
level->addToTickNextTick(x, y, z, id, getTickDelay());
}
if (!infiniBurn && !isValidFireLocation(level, x, y, z)) {
if (!level->isSolidBlockingTile(x, y - 1, z) || age > 3) level->setTile(x, y, z, 0);
return;
}
if (!infiniBurn && !canBurn(level, x, y - 1, z)) {
if (age == 15 && random->nextInt(4) == 0) {
level->setTile(x, y, z, 0);
return;
}
}
if (age % 2 == 0 && age > 2) {
checkBurn(level, x + 1, y, z, 300, random);
checkBurn(level, x - 1, y, z, 300, random);
checkBurn(level, x, y - 1, z, 250, random);
checkBurn(level, x, y + 1, z, 250, random);
checkBurn(level, x, y, z - 1, 300, random);
checkBurn(level, x, y, z + 1, 300, random);
for (int xx = x - 1; xx <= x + 1; xx++) {
for (int zz = z - 1; zz <= z + 1; zz++) {
for (int yy = y - 1; yy <= y + 4; yy++) {
if (xx == x && yy == y && zz == z) continue;
int rate = 100;
if (yy > y + 1) {
rate += ((yy - (y + 1)) * 100);
}
int odds = getFireOdds(level, xx, yy, zz);
if (odds > 0 && random->nextInt(rate) <= odds) {
level->setTile(xx, yy, zz, this->id);
}
}
}
}
}
if (age == 15) {
checkBurn(level, x + 1, y, z, 1, random);
checkBurn(level, x - 1, y, z, 1, random);
checkBurn(level, x, y - 1, z, 1, random);
checkBurn(level, x, y + 1, z, 1, random);
checkBurn(level, x, y, z - 1, 1, random);
checkBurn(level, x, y, z + 1, 1, random);
}
}
bool mayPick() {
return false;
}
bool canBurn(LevelSource* level, int x, int y, int z) {
return flameOdds[level->getTile(x, y, z)] > 0;
}
int getFlammability(Level* level, int x, int y, int z, int odds) {
int f = flameOdds[level->getTile(x, y, z)];
if (f > odds) return f;
return odds;
}
bool mayPlace(Level* level, int x, int y, int z, unsigned char face) {
return level->isSolidBlockingTile(x, y - 1, z) || isValidFireLocation(level, x, y, z);
}
void neighborChanged(Level* level, int x, int y, int z, int type) {
return; //@fire
if (!level->isSolidBlockingTile(x, y - 1, z) && !isValidFireLocation(level, x, y, z)) {
level->setTile(x, y, z, 0);
return;
}
}
void onPlace(Level* level, int x, int y, int z) {
return; //@fire
if (!level->isSolidBlockingTile(x, y - 1, z) && !isValidFireLocation(level, x, y, z)) {
level->setTile(x, y, z, 0);
return;
}
level->addToTickNextTick(x, y, z, id, getTickDelay());
}
bool isFlammable(int tile) {
return flameOdds[tile] > 0;
}
void ignite(Level* level, int x, int y, int z) {
return; //@fire
bool lit = false;
if (!lit) lit = tryIgnite(level, x, y + 1, z);
if (!lit) lit = tryIgnite(level, x - 1, y, z);
if (!lit) lit = tryIgnite(level, x + 1, y, z);
if (!lit) lit = tryIgnite(level, x, y, z - 1);
if (!lit) lit = tryIgnite(level, x, y, z + 1);
if (!lit) lit = tryIgnite(level, x, y - 1, z);
if (!lit) {
level->setTile(x, y, z, Tile::fire->id);
}
}
void animateTick(Level* level, int x, int y, int z, Random* random) {
return; //@fire
//if (random.nextInt(24) == 0) {
// level->playSound(x + 0.5f, y + 0.5f, z + 0.5f, "fire.fire", 1 + random.nextFloat(), random.nextFloat() * 0.7f + 0.3f);
//}
if (level->isSolidBlockingTile(x, y - 1, z) || Tile::fire->canBurn(level, x, y - 1, z)) {
for (int i = 0; i < 3; i++) {
float xx = x + random->nextFloat();
float yy = y + random->nextFloat() * 0.5f + 0.5f;
float zz = z + random->nextFloat();
level->addParticle(PARTICLETYPE(largesmoke), xx, yy, zz, 0, 0, 0);
}
} else {
if (Tile::fire->canBurn(level, x - 1, y, z)) {
for (int i = 0; i < 2; i++) {
float xx = x + random->nextFloat() * 0.1f;
float yy = y + random->nextFloat();
float zz = z + random->nextFloat();
level->addParticle(PARTICLETYPE(largesmoke), xx, yy, zz, 0, 0, 0);
}
}
if (Tile::fire->canBurn(level, x + 1, y, z)) {
for (int i = 0; i < 2; i++) {
float xx = x + 1 - random->nextFloat() * 0.1f;
float yy = y + random->nextFloat();
float zz = z + random->nextFloat();
level->addParticle(PARTICLETYPE(largesmoke), xx, yy, zz, 0, 0, 0);
}
}
if (Tile::fire->canBurn(level, x, y, z - 1)) {
for (int i = 0; i < 2; i++) {
float xx = x + random->nextFloat();
float yy = y + random->nextFloat();
float zz = z + random->nextFloat() * 0.1f;
level->addParticle(PARTICLETYPE(largesmoke), xx, yy, zz, 0, 0, 0);
}
}
if (Tile::fire->canBurn(level, x, y, z + 1)) {
for (int i = 0; i < 2; i++) {
float xx = x + random->nextFloat();
float yy = y + random->nextFloat();
float zz = z + 1 - random->nextFloat() * 0.1f;
level->addParticle(PARTICLETYPE(largesmoke), xx, yy, zz, 0, 0, 0);
}
}
if (Tile::fire->canBurn(level, x, y + 1, z)) {
for (int i = 0; i < 2; i++) {
float xx = x + random->nextFloat();
float yy = y + 1 - random->nextFloat() * 0.1f;
float zz = z + random->nextFloat();
level->addParticle(PARTICLETYPE(largesmoke), xx, yy, zz, 0, 0, 0);
}
}
}
}
private:
void setFlammable(int id, int flame, int burn) {
flameOdds[id] = flame;
burnOdds[id] = burn;
}
void checkBurn(Level* level, int x, int y, int z, int chance, Random* random) {
return; //@fire
int odds = burnOdds[level->getTile(x, y, z)];
if (random->nextInt(chance) < odds) {
bool wasTnt = level->getTile(x, y, z) == Tile::tnt->id;
if (random->nextInt(2) == 0) {
level->setTile(x, y, z, this->id);
} else {
level->setTile(x, y, z, 0);
}
if (wasTnt) {
Tile::tnt->destroy(level, x, y, z, 0);
}
}
}
bool isValidFireLocation(Level* level, int x, int y, int z) {
return false; //@fire
if (canBurn(level, x + 1, y, z)) return true;
if (canBurn(level, x - 1, y, z)) return true;
if (canBurn(level, x, y - 1, z)) return true;
if (canBurn(level, x, y + 1, z)) return true;
if (canBurn(level, x, y, z - 1)) return true;
if (canBurn(level, x, y, z + 1)) return true;
return false;
}
int getFireOdds(Level* level, int x, int y, int z) {
return 0; //@fire
int odds = 0;
if (!level->isEmptyTile(x, y, z)) return 0;
odds = getFlammability(level, x + 1, y, z, odds);
odds = getFlammability(level, x - 1, y, z, odds);
odds = getFlammability(level, x, y - 1, z, odds);
odds = getFlammability(level, x, y + 1, z, odds);
odds = getFlammability(level, x, y, z - 1, odds);
odds = getFlammability(level, x, y, z + 1, odds);
return odds;
}
bool tryIgnite(Level* level, int x, int y, int z) {
return false; //@fire
int t = level->getTile(x, y, z);
if (t == Tile::fire->id) return true;
if (t == 0) {
level->setTile(x, y, z, Tile::fire->id);
return true;
}
return false;
}
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__FireTile_H__*/

View File

@@ -0,0 +1,175 @@
#include "FurnaceTile.h"
#include "entity/FurnaceTileEntity.h"
#include "../material/Material.h"
#include "../../Facing.h"
#include "../../entity/Mob.h"
#include "../../entity/item/ItemEntity.h"
#include "../../entity/player/Player.h"
#include "../../item/ItemInstance.h"
#include "../../../util/Mth.h"
#include "../LevelSource.h"
#include "../Level.h"
bool FurnaceTile::noDrop = false;
FurnaceTile::FurnaceTile( int id, bool lit )
: super(id, Material::stone),
lit(lit)
{
tex = 13 + 16 * 2;
}
int FurnaceTile::getResource( int data, Random* random/*, int playerBonusLevel*/ )
{
return Tile::furnace->id;
}
void FurnaceTile::onPlace( Level* level, int x, int y, int z )
{
super::onPlace(level, x, y, z);
recalcLockDir(level, x, y, z);
}
int FurnaceTile::getTexture( LevelSource* level, int x, int y, int z, int face )
{
if (face == 1) return tex + 17;
if (face == 0) return tex + 17;
int lockDir = level->getData(x, y, z);
if (face != lockDir) return tex;
if (lit) return tex + 16;
else return tex - 1;
}
int FurnaceTile::getTexture( int face )
{
if (face == 1) return tex + 17;
if (face == 0) return tex + 17;
if (face == 3) return tex - 1;
return tex;
}
void FurnaceTile::animateTick( Level* level, int xt, int yt, int zt, Random* random )
{
if (!lit) return;
int dir = level->getData(xt, yt, zt);
float x = xt + 0.5f;
float y = yt + 0.0f + random->nextFloat() * 6 / 16.0f;
float z = zt + 0.5f;
float r = 0.52f;
float ss = random->nextFloat() * 0.6f - 0.3f;
if (dir == 4) {
level->addParticle(PARTICLETYPE(smoke), x - r, y, z + ss, 0, 0, 0);
level->addParticle(PARTICLETYPE(flame), x - r, y, z + ss, 0, 0, 0);
} else if (dir == 5) {
level->addParticle(PARTICLETYPE(smoke), x + r, y, z + ss, 0, 0, 0);
level->addParticle(PARTICLETYPE(flame), x + r, y, z + ss, 0, 0, 0);
} else if (dir == 2) {
level->addParticle(PARTICLETYPE(smoke), x + ss, y, z - r, 0, 0, 0);
level->addParticle(PARTICLETYPE(flame), x + ss, y, z - r, 0, 0, 0);
} else if (dir == 3) {
level->addParticle(PARTICLETYPE(smoke), x + ss, y, z + r, 0, 0, 0);
level->addParticle(PARTICLETYPE(flame), x + ss, y, z + r, 0, 0, 0);
}
}
bool FurnaceTile::use( Level* level, int x, int y, int z, Player* player )
{
if (level->isClientSide)
return true;
FurnaceTileEntity* furnace = static_cast<FurnaceTileEntity*>(level->getTileEntity(x, y, z));
if (furnace != NULL) player->openFurnace(furnace);
return true;
}
/*static*/
void FurnaceTile::setLit( bool lit, Level* level, int x, int y, int z )
{
int data = level->getData(x, y, z);
TileEntity* te = level->getTileEntity(x, y, z);
noDrop = true;
if (lit) level->setTile(x, y, z, Tile::furnace_lit->id);
else level->setTile(x, y, z, Tile::furnace->id);
noDrop = false;
level->setData(x, y, z, data);
LOGI("lit? %d @ %d, %d, %d\n", lit, x, y, z);
if (te != NULL) {
te->clearRemoved();
level->setTileEntity(x, y, z, te);
}
}
TileEntity* FurnaceTile::newTileEntity()
{
return TileEntityFactory::createTileEntity(TileEntityType::Furnace);
}
void FurnaceTile::setPlacedBy( Level* level, int x, int y, int z, Mob* by )
{
int dir = (Mth::floor(by->yRot * 4 / (360) + 0.5f)) & 3;
if (dir == 0) level->setData(x, y, z, Facing::NORTH);
if (dir == 1) level->setData(x, y, z, Facing::EAST);
if (dir == 2) level->setData(x, y, z, Facing::SOUTH);
if (dir == 3) level->setData(x, y, z, Facing::WEST);
}
void FurnaceTile::onRemove( Level* level, int x, int y, int z )
{
if (!noDrop && !level->isClientSide) {
FurnaceTileEntity* container = (FurnaceTileEntity*) level->getTileEntity(x, y, z);
if (container != NULL) {
for (int i = 0; i < container->getContainerSize(); i++) {
ItemInstance* item = container->getItem(i);
if (item) {
float xo = random.nextFloat() * 0.8f + 0.1f;
float yo = random.nextFloat() * 0.8f + 0.1f;
float zo = random.nextFloat() * 0.8f + 0.1f;
while (item->count > 0) {
int count = random.nextInt(21) + 10;
if (count > item->count) count = item->count;
item->count -= count;
ItemEntity* itemEntity = new ItemEntity(level, x + xo, y + yo, z + zo, ItemInstance(item->id, count, item->getAuxValue()));
float pow = 0.05f;
itemEntity->xd = random.nextGaussian() * pow;
itemEntity->yd = random.nextGaussian() * pow + 0.2f;
itemEntity->zd = random.nextGaussian() * pow;
level->addEntity(itemEntity);
}
}
}
}
}
super::onRemove(level, x, y, z);
}
void FurnaceTile::recalcLockDir( Level* level, int x, int y, int z )
{
if (level->isClientSide) {
return;
}
int n = level->getTile(x, y, z - 1); // face = 2
int s = level->getTile(x, y, z + 1); // face = 3
int w = level->getTile(x - 1, y, z); // face = 4
int e = level->getTile(x + 1, y, z); // face = 5
int lockDir = 3;
if (Tile::solid[e] && !Tile::solid[w]) lockDir = 4;
else if (Tile::solid[w] && !Tile::solid[e]) lockDir = 5;
else if (Tile::solid[s] && !Tile::solid[n]) lockDir = 2;
else if (Tile::solid[n] && !Tile::solid[s]) lockDir = 3;
level->setData(x, y, z, lockDir);
}

View File

@@ -0,0 +1,44 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__FurnaceTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__FurnaceTile_H__
//package net.minecraft.world.level->tile;
#include "EntityTile.h"
#include "../../../util/Random.h"
class Level;
class Mob;
class Player;
class LevelSource;
class FurnaceTile: public EntityTile
{
typedef EntityTile super;
public:
FurnaceTile(int id, bool lit);
int getTexture(int face);
int getTexture(LevelSource* level, int x, int y, int z, int face);
void animateTick(Level* level, int xt, int yt, int zt, Random* random);
bool use(Level* level, int x, int y, int z, Player* player);
int getResource(int data, Random* random/*, int playerBonusLevel*/);
static void setLit(bool lit, Level* level, int x, int y, int z);
TileEntity* newTileEntity();
void setPlacedBy(Level* level, int x, int y, int z, Mob* by);
void onPlace(Level* level, int x, int y, int z);
void onRemove(Level* level, int x, int y, int z);
private:
void recalcLockDir(Level* level, int x, int y, int z);
Random random;
const bool lit;
static bool noDrop;
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__FurnaceTile_H__*/

View File

@@ -0,0 +1,27 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__GlassTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__GlassTile_H__
//package net.minecraft.world.level.tile;
#include "HalfTransparentTile.h"
#include "../material/Material.h"
#include "../../../util/Random.h"
class GlassTile: public HalfTransparentTile
{
typedef HalfTransparentTile super;
public:
GlassTile(int id, int tex, const Material* material, bool allowSame)
: super(id, tex, material, allowSame)
{}
int getResourceCount(Random* random) {
return 0;
}
int getRenderLayer() {
return Tile::RENDERLAYER_ALPHATEST;
}
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__GlassTile_H__*/

View File

@@ -0,0 +1,54 @@
#include "GrassTile.h"
#include "../material/Material.h"
#include "../../entity/item/ItemEntity.h"
GrassTile::GrassTile(int id)
: super(id, Material::dirt)
{
tex = 3;
setTicking(true);
}
int GrassTile::getTexture( LevelSource* level, int x, int y, int z, int face ) {
if (face == 1) return 0;
if (face == 0) return 2;
const Material* above = level->getMaterial(x, y + 1, z);
if (above == Material::topSnow || above == Material::snow) return 4 * 16 + 4;
else return 3;
}
int GrassTile::getTexture( int face, int data ) {
if (face == 1) return 0;
if (face == 0) return 2;
return 3;
}
int GrassTile::getColor( LevelSource* level, int x, int y, int z ) {
//level.getBiomeSource().getBiomeBlock(x, z, 1, 1);
//float temp = level.getBiomeSource().temperatures[0];
//float rain = level.getBiomeSource().downfalls[0];
return 0x339933;//GrassColor.get(temp, rain);
}
void GrassTile::tick( Level* level, int x, int y, int z, Random* random ) {
if (level->isClientSide) return;
if (level->getRawBrightness(x, y + 1, z) < MIN_BRIGHTNESS && level->getMaterial(x, y + 1, z)->blocksLight()) {
if (random->nextInt(4) != 0) return;
level->setTile(x, y, z, Tile::dirt->id);
} else {
if (level->getRawBrightness(x, y + 1, z) >= level->MAX_BRIGHTNESS - 6) {
int xt = x + random->nextInt(3) - 1;
int yt = y + random->nextInt(5) - 3;
int zt = z + random->nextInt(3) - 1;
if (level->getTile(xt, yt, zt) == Tile::dirt->id && level->getRawBrightness(xt, yt + 1, zt) >= MIN_BRIGHTNESS && !level->getMaterial(xt, yt + 1, zt)->blocksLight()) {
level->setTile(xt, yt, zt, Tile::grass->id);
}
}
}
}
int GrassTile::getResource( int data, Random* random ) {
return Tile::dirt->getResource(0, random);
}

View File

@@ -0,0 +1,29 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__GrassTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__GrassTile_H__
//package net.minecraft.world.level.tile;
#include "../../../util/Random.h"
#include "../material/Material.h"
#include "../Level.h"
#include "../LevelSource.h"
#include "Tile.h"
class GrassTile: public Tile
{
typedef Tile super;
public:
static const int MIN_BRIGHTNESS = 4;
GrassTile(int id);
int getTexture(LevelSource* level, int x, int y, int z, int face);
int getTexture(int face, int data);
int getColor(LevelSource* level, int x, int y, int z);
void tick(Level* level, int x, int y, int z, Random* random);
int getResource(int data, Random* random);
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__GrassTile_H__*/

View File

@@ -0,0 +1,26 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__GravelTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__GravelTile_H__
//package net.minecraft.world.level.tile;
#include "../../../util/Random.h"
#include "../material/Material.h"
#include "HeavyTile.h"
class GravelTile: public HeavyTile
{
typedef HeavyTile super;
public:
GravelTile(int type, int tex)
: super(type, tex)
{
}
int getResource(int data, Random* random) {
if (random->nextInt(10) == 0) return Item::flint->id;
return id;
}
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__GravelTile_H__*/

View File

@@ -0,0 +1,39 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__HalfTransparentTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__HalfTransparentTile_H__
//package net.minecraft.world.level.tile;
#include "../LevelSource.h"
#include "../material/Material.h"
class HalfTransparentTile: public Tile {
bool allowSame;
public:
/*protected*/
HalfTransparentTile(int id, int tex, const Material* material, bool allowSame)
: Tile(id, tex, material)
{
this->allowSame = allowSame;
}
int getRenderLayer() {
return Tile::RENDERLAYER_BLEND;
}
bool isSolidRender() {
return false;
}
bool shouldRenderFace(LevelSource* level, int x, int y, int z, int face) {
int id = level->getTile(x, y, z);
if (!allowSame && id == this->id) return false;
return Tile::shouldRenderFace(level, x, y, z, face);
}
bool blocksLight() {
return false;
}
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__HalfTransparentTile_H__*/

View File

@@ -0,0 +1,72 @@
#include "HeavyTile.h"
#include "../Level.h"
#include "../material/Material.h"
#include "../../entity/item/FallingTile.h"
bool HeavyTile::instaFall = false;
HeavyTile::HeavyTile( int id, int tex )
: super(id, tex, Material::sand)
{
}
HeavyTile::HeavyTile( int id, int tex, const Material* material )
: super(id, tex, material)
{
}
void HeavyTile::onPlace( Level* level, int x, int y, int z ) {
level->addToTickNextTick(x, y, z, id, getTickDelay(level));
}
void HeavyTile::neighborChanged( Level* level, int x, int y, int z, int type ) {
level->addToTickNextTick(x, y, z, id, getTickDelay(level));
}
void HeavyTile::tick( Level* level, int x, int y, int z, Random* random ) {
if (!level->isClientSide) {
checkSlide(level, x, y, z);
}
}
int HeavyTile::getTickDelay( Level* level ) {
return 2;
}
bool HeavyTile::isFree( Level* level, int x, int y, int z ) {
int t = level->getTile(x, y, z);
if (t == 0) return true;
if (t == ((Tile*)Tile::fire)->id) return true;
const Material* material = Tile::tiles[t]->material;
if (material == Material::water) return true;
if (material == Material::lava) return true;
return false;
}
void HeavyTile::checkSlide( Level* level, int x, int y, int z ) {
int x2 = x;
int y2 = y;
int z2 = z;
if (isFree(level, x2, y2 - 1, z2) && y2 >= 0) {
int r = 32;
if (instaFall || !level->hasChunksAt(x - r, y - r, z - r, x + r, y + r, z + r)) {
level->setTile(x, y, z, 0);
while (isFree(level, x, y - 1, z) && y > 0)
y--;
if (y > 0) {
level->setTile(x, y, z, id);
//level->setTileAndUpdate(x, y, z, id);
}
} else if (!level->isClientSide) {
FallingTile* e = new FallingTile(level, x + 0.5f, y + 0.5f, z + 0.5f, id, level->getData(x, y, z));
falling(e);
level->addEntity(e);
}
}
}
void HeavyTile::falling( FallingTile* entity ) {
}
void HeavyTile::onLand( Level* level, int xt, int yt, int zt, int data ) {
}

View File

@@ -0,0 +1,32 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__HeavyTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__HeavyTile_H__
//package net.minecraft.world.level.tile;
#include "Tile.h"
class FallingTile;
class HeavyTile: public Tile {
typedef Tile super;
public:
static bool instaFall;
HeavyTile(int id, int tex);
HeavyTile(int id, int tex, const Material* material);
void onPlace(Level* level, int x, int y, int z);
void neighborChanged(Level* level, int x, int y, int z, int type);
void tick(Level* level, int x, int y, int z, Random* random);
int getTickDelay(Level* level);
static bool isFree(Level* level, int x, int y, int z);
virtual void falling(FallingTile* entity);
virtual void onLand(Level* level, int xt, int yt, int zt, int data);
private:
void checkSlide(Level* level, int x, int y, int z);
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__HeavyTile_H__*/

41
src/world/level/tile/IceTile.h Executable file
View File

@@ -0,0 +1,41 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__IceTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__IceTile_H__
//package net.minecraft.world.level.tile;
#include "Tile.h"
#include "../material/Material.h"
#include "../LightLayer.h"
#include "../../../util/Random.h"
class IceTile: public Tile
{
typedef Tile super;
public:
IceTile(int id, int tex)
: super(id, tex, Material::ice)
{
friction = 0.98f;
setTicking(true);
}
void playerDestroy(Level* level, Player* player, int x, int y, int z, int data) {
const Material* below = level->getMaterial(x, y - 1, z);
if (below->blocksMotion() || below->isLiquid()) {
level->setTile(x, y, z, Tile::water->id);
}
}
int getResourceCount(Random* random) {
return 0;
}
void tick(Level* level, int x, int y, int z, Random* random) {
if (level->getBrightness(LightLayer::Block, x, y, z) > 11 - Tile::lightBlock[id]) {
this->spawnResources(level, x, y, z, level->getData(x, y, z));
level->setTile(x, y, z, Tile::calmWater->id);
}
}
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__IceTile_H__*/

View File

@@ -0,0 +1,21 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__InvisibleTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__InvisibleTile_H__
#include "Tile.h"
class InvisibleTile : public Tile
{
typedef Tile super;
public:
InvisibleTile(int id, int tex, const Material* material)
: super(id, tex, material)
{
}
virtual int getRenderShape()
{
return SHAPE_INVISIBLE;
}
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__InvisibleTile_H__*/

112
src/world/level/tile/LadderTile.h Executable file
View File

@@ -0,0 +1,112 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__LadderTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__LadderTile_H__
//package net.minecraft.world.level->tile;
#include "../../../util/Random.h"
#include "../material/Material.h"
#include "../Level.h"
#include "Tile.h"
class LadderTile: public Tile
{
typedef Tile super;
public:
LadderTile(int id, int tex)
: super(id, tex, Material::decoration)
{
}
AABB* getAABB(Level* level, int x, int y, int z) {
int dir = level->getData(x, y, z);
float r = 2 / 16.0f;
if (dir == 2) this->setShape(0, 0, 1 - r, 1, 1, 1);
if (dir == 3) this->setShape(0, 0, 0, 1, 1, r);
if (dir == 4) this->setShape(1 - r, 0, 0, 1, 1, 1);
if (dir == 5) this->setShape(0, 0, 0, r, 1, 1);
return super::getAABB(level, x, y, z);
}
AABB getTileAABB(Level* level, int x, int y, int z) {
int dir = level->getData(x, y, z);
float r = 2 / 16.0f;
if (dir == 2) this->setShape(0, 0, 1 - r, 1, 1, 1);
if (dir == 3) this->setShape(0, 0, 0, 1, 1, r);
if (dir == 4) this->setShape(1 - r, 0, 0, 1, 1, 1);
if (dir == 5) this->setShape(0, 0, 0, r, 1, 1);
return super::getTileAABB(level, x, y, z);
}
bool blocksLight() {
return false;
}
bool isSolidRender() {
return false;
}
bool isCubeShaped() {
return false;
}
int getRenderShape() {
return Tile::SHAPE_LADDER;
}
int getRenderLayer() {
return Tile::RENDERLAYER_ALPHATEST;
}
bool mayPlace(Level* level, int x, int y, int z, unsigned char face) {
if (level->isSolidBlockingTile(x - 1, y, z)) {
return true;
} else if (level->isSolidBlockingTile(x + 1, y, z)) {
return true;
} else if (level->isSolidBlockingTile(x, y, z - 1)) {
return true;
} else if (level->isSolidBlockingTile(x, y, z + 1)) {
return true;
}
return false;
}
int getPlacedOnFaceDataValue(Level* level, int x, int y, int z, int face, float clickX, float clickY, float clickZ, int itemValue)
{
int dir = itemValue;
if ((dir == 0 || face == 2) && level->isSolidBlockingTile(x, y, z + 1)) dir = 2;
if ((dir == 0 || face == 3) && level->isSolidBlockingTile(x, y, z - 1)) dir = 3;
if ((dir == 0 || face == 4) && level->isSolidBlockingTile(x + 1, y, z)) dir = 4;
if ((dir == 0 || face == 5) && level->isSolidBlockingTile(x - 1, y, z)) dir = 5;
return dir;
}
void neighborChanged(Level* level, int x, int y, int z, int type) {
int face = level->getData(x, y, z);
bool ok = false;
if (face == 2 && level->isSolidBlockingTile(x, y, z + 1)) ok = true;
if (face == 3 && level->isSolidBlockingTile(x, y, z - 1)) ok = true;
if (face == 4 && level->isSolidBlockingTile(x + 1, y, z)) ok = true;
if (face == 5 && level->isSolidBlockingTile(x - 1, y, z)) ok = true;
if (!ok) {
//spawnResources(level, x, y, z, face); //@crafting
popResource(level, x, y, z, ItemInstance(Tile::ladder));
level->setTile(x, y, z, 0);
}
super::neighborChanged(level, x, y, z, type);
}
int getResourceCount(Random* random) {
return 1;
}
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__LadderTile_H__*/

208
src/world/level/tile/LeafTile.h Executable file
View File

@@ -0,0 +1,208 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__LeafTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__LeafTile_H__
//package net.minecraft.world.level.tile;
#include "TransparentTile.h"
#include "../Level.h"
#include "../material/Material.h"
#include "../../item/Item.h"
#include "../../item/ItemInstance.h"
#include "../FoliageColor.h"
class Entity;
class LeafTile: public TransparentTile
{
typedef TransparentTile super;
public:
static const int LEAF_TYPE_MASK = 3;
static const int REQUIRED_WOOD_RANGE = 4;
//@attn @note: PERSISTENT_LEAF_BIT and UPDATE_LEAF_BIT are reversed
// here, compared to desktop version
static const int PERSISTENT_LEAF_BIT = 8; // player-placed
static const int UPDATE_LEAF_BIT = 4;
static const int NORMAL_LEAF = 0;
static const int EVERGREEN_LEAF = 1;
static const int BIRCH_LEAF = 2;
LeafTile(int id, int tex)
: super(id, tex, Material::leaves, false),
oTex(tex),
checkBuffer(NULL)
{
setTicking(true);
}
~LeafTile() {
if (checkBuffer != NULL)
delete[] checkBuffer;
}
int getRenderLayer() {
return isSolidRender()? Tile::RENDERLAYER_OPAQUE : Tile::RENDERLAYER_ALPHATEST;
}
int getColor(LevelSource* level, int x, int y, int z) {
int data = (level->getData(x, y, z) & LEAF_TYPE_MASK);
if (data == EVERGREEN_LEAF) {
return FoliageColor::getEvergreenColor();
}
if (data == BIRCH_LEAF) {
return FoliageColor::getBirchColor();
}
return FoliageColor::getDefaultColor();
}
void onRemove(Level* level, int x, int y, int z) {
int r = 1;
int r2 = r + 1;
if (level->hasChunksAt(x - r2, y - r2, z - r2, x + r2, y + r2, z + r2)) {
for (int xo = -r; xo <= r; xo++)
for (int yo = -r; yo <= r; yo++)
for (int zo = -r; zo <= r; zo++) {
int t = level->getTile(x + xo, y + yo, z + zo);
if (t == Tile::leaves->id) {
int currentData = level->getData(x + xo, y + yo, z + zo);
level->setDataNoUpdate(x + xo, y + yo, z + zo, currentData | UPDATE_LEAF_BIT);
}
}
}
}
int* checkBuffer; //@todo Rewrite this?
void tick(Level* level, int x, int y, int z, Random* random) {
if (level->isClientSide) return;
int currentData = level->getData(x, y, z);
if ((currentData & UPDATE_LEAF_BIT) != 0 && (currentData & PERSISTENT_LEAF_BIT) == 0) {
const int r = LeafTile::REQUIRED_WOOD_RANGE;
int r2 = r + 1;
const int W = 32;
const int WW = W * W;
const int WO = W / 2;
if (!checkBuffer) {
checkBuffer = new int[W * W * W];
}
if (level->hasChunksAt(x - r2, y - r2, z - r2, x + r2, y + r2, z + r2)) {
for (int xo = -r; xo <= r; xo++)
for (int yo = -r; yo <= r; yo++)
for (int zo = -r; zo <= r; zo++) {
int t = level->getTile(x + xo, y + yo, z + zo);
if (t == Tile::treeTrunk->id) {
checkBuffer[(xo + WO) * WW + (yo + WO) * W + (zo + WO)] = 0;
} else if (t == Tile::leaves->id) {
checkBuffer[(xo + WO) * WW + (yo + WO) * W + (zo + WO)] = -2;
} else {
checkBuffer[(xo + WO) * WW + (yo + WO) * W + (zo + WO)] = -1;
}
}
for (int i = 1; i <= LeafTile::REQUIRED_WOOD_RANGE; i++) {
for (int xo = -r; xo <= r; xo++)
for (int yo = -r; yo <= r; yo++)
for (int zo = -r; zo <= r; zo++) {
if (checkBuffer[(xo + WO) * WW + (yo + WO) * W + (zo + WO)] == i - 1) {
if (checkBuffer[(xo + WO - 1) * WW + (yo + WO) * W + (zo + WO)] == -2) {
checkBuffer[(xo + WO - 1) * WW + (yo + WO) * W + (zo + WO)] = i;
}
if (checkBuffer[(xo + WO + 1) * WW + (yo + WO) * W + (zo + WO)] == -2) {
checkBuffer[(xo + WO + 1) * WW + (yo + WO) * W + (zo + WO)] = i;
}
if (checkBuffer[(xo + WO) * WW + (yo + WO - 1) * W + (zo + WO)] == -2) {
checkBuffer[(xo + WO) * WW + (yo + WO - 1) * W + (zo + WO)] = i;
}
if (checkBuffer[(xo + WO) * WW + (yo + WO + 1) * W + (zo + WO)] == -2) {
checkBuffer[(xo + WO) * WW + (yo + WO + 1) * W + (zo + WO)] = i;
}
if (checkBuffer[(xo + WO) * WW + (yo + WO) * W + (zo + WO - 1)] == -2) {
checkBuffer[(xo + WO) * WW + (yo + WO) * W + (zo + WO - 1)] = i;
}
if (checkBuffer[(xo + WO) * WW + (yo + WO) * W + (zo + WO + 1)] == -2) {
checkBuffer[(xo + WO) * WW + (yo + WO) * W + (zo + WO + 1)] = i;
}
}
}
}
}
int mid = checkBuffer[(WO) * WW + (WO) * W + (WO)];
if (mid >= 0) {
level->setDataNoUpdate(x, y, z, currentData & ~UPDATE_LEAF_BIT);
} else {
die(level, x, y, z);
}
}
}
void playerDestroy(Level* level, Player* player, int x, int y, int z, int data) {
if (!level->isClientSide) {
ItemInstance* item = player->inventory->getSelected();
if (item && item->id == ((Item*)Item::shears)->id) {
// drop leaf block instead of sapling
popResource(level, x, y, z, ItemInstance(Tile::leaves->id, 1, data & LEAF_TYPE_MASK));
return;
}
}
super::playerDestroy(level, player, x, y, z, data);
}
int getResourceCount(Random* random) {
return random->nextInt(20) == 0 ? 1 : 0;
}
int getResource(int data, Random* random) {
return Tile::sapling->id;
}
void spawnResources(Level* level, int x, int y, int z, int data, float odds) {
if (!level->isClientSide) {
int chance = 20;
if (level->random.nextInt(chance) == 0) {
int type = getResource(data, &level->random);
popResource(level, x, y, z, ItemInstance(type, 1, getSpawnResourcesAuxValue(data)));
}
if ((data & LEAF_TYPE_MASK) == NORMAL_LEAF && level->random.nextInt(200) == 0) {
popResource(level, x, y, z, ItemInstance(Item::apple, 1, 0));
}
}
}
bool isSolidRender() {
return !allowSame;
}
int getTexture(int face, int data) {
if ((data & LEAF_TYPE_MASK) == EVERGREEN_LEAF) {
return (this == Tile::leaves)? tex + 5 * 16
: tex - 16;
}
return tex;
}
void setFancy(bool fancyGraphics) {
allowSame = fancyGraphics;
tex = oTex + (fancyGraphics ? 0 : 1);
}
protected:
int getSpawnResourcesAuxValue(int data) {
return data & LEAF_TYPE_MASK;
}
private:
void die(Level* level, int x, int y, int z) {
spawnResources(level, x, y, z, level->getData(x, y, z) & LEAF_TYPE_MASK, 0);
level->setTile(x, y, z, 0);
}
int oTex;
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__LeafTile_H__*/

View File

@@ -0,0 +1,27 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__LevelEvent_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__LevelEvent_H__
class LevelEvent
{
public:
static const int SOUND_CLICK = 1000;
static const int SOUND_CLICK_FAIL = 1001;
static const int SOUND_LAUNCH = 1002;
static const int SOUND_OPEN_DOOR = 1003;
static const int SOUND_FIZZ = 1004;
static const int SOUND_PLAY_RECORDING = 1005;
static const int SOUND_GHAST_WARNING = 1007;
static const int SOUND_GHAST_FIREBALL = 1008;
static const int SOUND_BLAZE_FIREBALL = 1009;
static const int PARTICLES_SHOOT = 2000;
static const int PARTICLES_DESTROY_BLOCK = 2001;
static const int PARTICLES_POTION_SPLASH = 2002;
static const int PARTICLES_EYE_OF_ENDER_DEATH = 2003;
static const int PARTICLES_MOBTILE_SPAWN = 2004;
static const int ALL_PLAYERS_SLEEPING = 9800;
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__LevelEvent_H__*/

View File

@@ -0,0 +1,15 @@
#include "LightGemTile.h"
#include "../../../util/Random.h"
#include "../../item/Item.h"
LightGemTile::LightGemTile( int id, int tex, const Material* material )
: super(id, tex, material)
{ }
int LightGemTile::getResourceCount( Random* random ) {
return 2 + random->nextInt(3);
}
int LightGemTile::getResource( int data, Random* random ) {
return Item::yellowDust->id;
}

View File

@@ -0,0 +1,12 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__LightGemTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__LightGemTile_H__
#include "Tile.h"
class LightGemTile : public Tile {
typedef Tile super;
public:
LightGemTile(int id, int tex, const Material* material);
int getResourceCount(Random* random);
int getResource(int data, Random* random);
};
#endif /* NET_MINECRAFT_WORLD_LEVEL_TILE__LightGemTile_H__ */

232
src/world/level/tile/LiquidTile.h Executable file
View File

@@ -0,0 +1,232 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__LiquidTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__LiquidTile_H__
//package net.minecraft.world.level.tile;
#include "../../../util/Random.h"
#include "../material/Material.h"
#include "../Level.h"
#include "Tile.h"
/*abstract*/
class LiquidTile: public Tile
{
public:
static float getHeight(int d) {
// if (d == 0) d++; // NM
if (d >= 8) d = 0;
float h = (d + 1) / 9.0f;
return h;
}
int getTexture(int face) {
if (face == 0 || face == 1) {
return tex;
} else {
return tex + 1;
}
}
bool isCubeShaped() {
return false;
}
bool isSolidRender() {
return false;
}
bool mayPick(int data, bool liquid) {
return liquid && data == 0;
}
bool shouldRenderFace(LevelSource* level, int x, int y, int z, int face) {
const Material* m = level->getMaterial(x, y, z);
if (m == this->material) return false;
if (m == Material::ice) return false;
if (face == 1) return true;
return Tile::shouldRenderFace(level, x, y, z, face);
}
AABB* getAABB(Level* level, int x, int y, int z) {
return NULL;
}
int getRenderShape() {
return Tile::SHAPE_WATER;
}
int getResource(int data, Random* random) {
return 0;
}
int getResourceCount(Random* random) {
return 0;
}
int getColor(LevelSource* level, int x, int y, int z) {
return 0x999999ff;
}
void handleEntityInside(Level* level, int x, int y, int z, Entity* e, Vec3& current) {
Vec3 flow = getFlow(level, x, y, z);
current.x += flow.x * .5f;
current.y += flow.y * .5f;
current.z += flow.z * .5f;
}
int getTickDelay() {
if (material == Material::water) return 5;
if (material == Material::lava) return 30;
return 0;
}
float getBrightness(LevelSource* level, int x, int y, int z) {
float a = level->getBrightness(x, y, z);
float b = level->getBrightness(x, y + 1, z);
return a > b ? a : b;
}
virtual void tick(Level* level, int x, int y, int z, Random* random) {
Tile::tick(level, x, y, z, random);
}
int getRenderLayer() {
return (material == Material::water)? Tile::RENDERLAYER_BLEND : Tile::RENDERLAYER_OPAQUE;
}
void animateTick(Level* level, int x, int y, int z, Random* random) {
if (material == Material::water && random->nextInt(64) == 0) {
int d = level->getData(x, y, z);
if (d > 0 && d < 8) {
//level->playSound(x + 0.5f, y + 0.5f, z + 0.5f, "liquid.water", random.nextFloat() * 0.25f + 0.75f, random.nextFloat() * 1.0f + 0.5f);
}
}
if (material == Material::lava) {
if (level->getMaterial(x, y + 1, z) == Material::air && !level->isSolidRenderTile(x, y + 1, z)) {
if (random->nextInt(100) == 0) {
float xx = x + random->nextFloat();
float yy = y + yy1;
float zz = z + random->nextFloat();
level->addParticle(PARTICLETYPE(lava), xx, yy, zz, 0, 0, 0);
}
}
}
}
static float getSlopeAngle(LevelSource* level, int x, int y, int z, const Material* m) {
Vec3 flow;
if (m == Material::water) flow = ((LiquidTile*) Tile::water)->getFlow(level, x, y, z);
if (m == Material::lava) flow = ((LiquidTile*) Tile::lava)->getFlow(level, x, y, z);
if (flow.x == 0 && flow.z == 0) return -1000;
return atan2(flow.z, flow.x) - Mth::PI * 0.5f;
}
virtual void onPlace(Level* level, int x, int y, int z) {
updateLiquid(level, x, y, z);
}
virtual void neighborChanged(Level* level, int x, int y, int z, int type) {
updateLiquid(level, x, y, z);
}
protected:
LiquidTile(int id, const Material* material)
: Tile(id, (material == Material::lava ? 14 : 12) * 16 + 13, material)
{
float yo = 0;
float e = 0;
setShape(0 + e, 0 + yo, 0 + e, 1 + e, 1 + yo, 1 + e);
setTicking(true);
}
void fizz(Level* level, int x, int y, int z) {
//level->playSound(x + 0.5f, y + 0.5f, z + 0.5f, "random.fizz", 0.5f, 2.6f + (level->random.nextFloat() - level->random.nextFloat()) * 0.8f);
for (int i = 0; i < 8; i++) {
level->addParticle(PARTICLETYPE(largesmoke), (float)x + Mth::random(), (float)y + 1.2f, (float)z + Mth::random(), 0, 0, 0);
}
}
int getDepth(Level* level, int x, int y, int z) {
if (level->getMaterial(x, y, z) != material) return -1;
else return level->getData(x, y, z);
}
int getRenderedDepth(LevelSource* level, int x, int y, int z) {
if (level->getMaterial(x, y, z) != material) return -1;
int d = level->getData(x, y, z);
if (d >= 8) d = 0;
return d;
}
private:
void updateLiquid(Level* level, int x, int y, int z) {
if (level->getTile(x, y, z) != id) return;
if (material == Material::lava) {
bool water = false;
if (water || level->getMaterial(x, y, z - 1) == Material::water) water = true;
if (water || level->getMaterial(x, y, z + 1) == Material::water) water = true;
if (water || level->getMaterial(x - 1, y, z) == Material::water) water = true;
if (water || level->getMaterial(x + 1, y, z) == Material::water) water = true;
// if (water || level->getMaterial(x, y - 1, z) == Material::water) water = true; // NM
if (water || level->getMaterial(x, y + 1, z) == Material::water) water = true;
if (water) {
int data = level->getData(x, y, z);
if (data == 0) {
level->setTile(x, y, z, Tile::obsidian->id);
} else if (data <= 4) {
level->setTile(x, y, z, Tile::stoneBrick->id);
}
fizz(level, x, y, z);
}
}
}
Vec3 getFlow(LevelSource* level, int x, int y, int z) {
Vec3 flow(0,0,0);
int mid = getRenderedDepth(level, x, y, z);
for (int d = 0; d < 4; d++) {
int xt = x;
int yt = y;
int zt = z;
if (d == 0) xt--;
if (d == 1) zt--;
if (d == 2) xt++;
if (d == 3) zt++;
int t = getRenderedDepth(level, xt, yt, zt);
if (t < 0) {
if (!level->getMaterial(xt, yt, zt)->blocksMotion()) {
t = getRenderedDepth(level, xt, yt - 1, zt);
if (t >= 0) {
int dir = t - (mid - 8);
flow = flow.add((float)((xt - x) * dir), (float)((yt - y) * dir), (float)((zt - z) * dir));
}
}
} else {
if (t >= 0) {
int dir = t - mid;
flow = flow.add((float)((xt - x) * dir), (float)((yt - y) * dir), (float)((zt - z) * dir));
}
}
}
if (level->getData(x, y, z) >= 8) {
bool ok = false;
if (ok || shouldRenderFace(level, x, y, z - 1, 2)) ok = true;
if (ok || shouldRenderFace(level, x, y, z + 1, 3)) ok = true;
if (ok || shouldRenderFace(level, x - 1, y, z, 4)) ok = true;
if (ok || shouldRenderFace(level, x + 1, y, z, 5)) ok = true;
if (ok || shouldRenderFace(level, x, y + 1, z - 1, 2)) ok = true;
if (ok || shouldRenderFace(level, x, y + 1, z + 1, 3)) ok = true;
if (ok || shouldRenderFace(level, x - 1, y + 1, z, 4)) ok = true;
if (ok || shouldRenderFace(level, x + 1, y + 1, z, 5)) ok = true;
if (ok) flow = flow.normalized().add(0, -6, 0);
}
flow = flow.normalized();
return flow;
}
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__LiquidTile_H__*/

View File

@@ -0,0 +1,230 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__LiquidTileDynamic_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__LiquidTileDynamic_H__
//package net.minecraft.world.level.tile;
#include "LiquidTile.h"
#include "../Level.h"
class LiquidTileDynamic: public LiquidTile
{
typedef LiquidTile super;
public:
LiquidTileDynamic(int id, const Material* material)
: super(id, material),
maxCount(0)
{}
void tick(Level* level, int x, int y, int z, Random* random) {
//printf("liquid-tick\n");
int depth = getDepth(level, x, y, z);
int dropOff = 1;
if (material == Material::lava && !level->dimension->ultraWarm) dropOff = 2;
bool becomeStatic = true;
if (depth > 0) {
int highest = -100;
maxCount = 0;
highest = getHighest(level, x - 1, y, z, highest);
highest = getHighest(level, x + 1, y, z, highest);
highest = getHighest(level, x, y, z - 1, highest);
highest = getHighest(level, x, y, z + 1, highest);
int newDepth = highest + dropOff;
if (newDepth >= 8 || highest < 0) {
newDepth = -1;
}
if (getDepth(level, x, y + 1, z) >= 0) {
int above = getDepth(level, x, y + 1, z);
if (above >= 8) newDepth = above;
else newDepth = above + 8;
}
if (maxCount >= 2 && material == Material::water) {
// Only spread spring if it's on top of an existing spring, or on top of solid ground.
if (level->isSolidBlockingTile(x, y - 1, z)) {
newDepth = 0;
} else if (level->getMaterial(x, y - 1, z) == material && level->getData(x, y, z) == 0) {
newDepth = 0;
}
}
if (material == Material::lava) {
if (depth < 8 && newDepth < 8) {
if (newDepth > depth) {
if (random->nextInt(4) != 0) {
newDepth = depth;
becomeStatic = false;
}
}
}
}
if (newDepth != depth) {
depth = newDepth;
if (depth < 0) {
level->setTile(x, y, z, 0);
} else {
level->setData(x, y, z, depth);
level->addToTickNextTick(x, y, z, id, getTickDelay());
level->updateNeighborsAt(x, y, z, id);
}
} else {
if (becomeStatic) setStatic(level, x, y, z);
}
} else {
setStatic(level, x, y, z);
}
if (canSpreadTo(level, x, y - 1, z)) {
if (depth >= 8) level->setTileAndData(x, y - 1, z, id, depth);
else level->setTileAndData(x, y - 1, z, id, depth + 8);
} else if (depth >= 0 && (depth == 0 || isWaterBlocking(level, x, y - 1, z))) {
bool* spreads = getSpread(level, x, y, z);
int neighbor = depth + dropOff;
if (depth >= 8) {
neighbor = 1;
}
if (neighbor >= 8) return;
if (spreads[0]) trySpreadTo(level, x - 1, y, z, neighbor);
if (spreads[1]) trySpreadTo(level, x + 1, y, z, neighbor);
if (spreads[2]) trySpreadTo(level, x, y, z - 1, neighbor);
if (spreads[3]) trySpreadTo(level, x, y, z + 1, neighbor);
}
}
/*protected*/
int getHighest(Level* level, int x, int y, int z, int current) {
int d = getDepth(level, x, y, z);
if (d < 0) return current;
if (d == 0) maxCount++;
if (d >= 8) {
d = 0;
}
return current < 0 || d < current ? d : current;
}
void onPlace(Level* level, int x, int y, int z) {
super::onPlace(level, x, y, z);
if (level->getTile(x, y, z) == id) {
level->addToTickNextTick(x, y, z, id, getTickDelay());
}
}
private:
void setStatic(Level* level, int x, int y, int z) {
int d = level->getData(x, y, z);
level->setTileAndDataNoUpdate(x, y, z, id + 1, d);
level->setTilesDirty(x, y, z, x, y, z);
level->sendTileUpdated(x, y, z);
}
bool canSpreadTo(Level* level, int x, int y, int z) {
const Material* target = level->getMaterial(x, y, z);
if (target == material) return false;
if (target == Material::lava) return false;
return !isWaterBlocking(level, x, y, z);
}
bool isWaterBlocking(Level* level, int x, int y, int z) {
int t = level->getTile(x, y, z);
if (t == 0) return false;
if (t == Tile::door_wood->id /*|| t == Tile::door_iron->id */ || t == Tile::sign->id || t == Tile::ladder->id || t == Tile::reeds->id) {
return true;
}
const Material* m = Tile::tiles[t]->material;
if (m->blocksMotion()) return true;
if (m->isSolid()) return true;
return false;
}
bool* getSpread(Level* level, int x, int y, int z) {
for (int d = 0; d < 4; d++) {
dist[d] = 1000;
int xx = x;
int yy = y;
int zz = z;
if (d == 0) xx--;
if (d == 1) xx++;
if (d == 2) zz--;
if (d == 3) zz++;
if (isWaterBlocking(level, xx, yy, zz)) {
continue;
} else if (level->getMaterial(xx, yy, zz) == material && level->getData(xx, yy, zz) == 0) {
continue;
} else {
if (!isWaterBlocking(level, xx, yy - 1, zz)) {
dist[d] = 0;
} else {
dist[d] = getSlopeDistance(level, xx, yy, zz, 1, d);
}
}
}
int lowest = dist[0];
for (int d = 1; d < 4; d++) {
if (dist[d] < lowest) lowest = dist[d];
}
for (int d = 0; d < 4; d++) {
result[d] = dist[d] == lowest;
}
return result;
}
void trySpreadTo(Level* level, int x, int y, int z, int neighbor) {
if (canSpreadTo(level, x, y, z)) {
int old = level->getTile(x, y, z);
if (old > 0) {
if (material == Material::lava) {
fizz(level, x, y, z);
} else {
Tile::tiles[old]->spawnResources(level, x, y, z, level->getData(x, y, z));
}
}
level->setTileAndData(x, y, z, id, neighbor);
}
}
int getSlopeDistance(Level* level, int x, int y, int z, int pass, int from) {
int lowest = 1000;
for (int d = 0; d < 4; d++) {
if (d == 0 && from == 1) continue;
if (d == 1 && from == 0) continue;
if (d == 2 && from == 3) continue;
if (d == 3 && from == 2) continue;
int xx = x;
int yy = y;
int zz = z;
if (d == 0) xx--;
if (d == 1) xx++;
if (d == 2) zz--;
if (d == 3) zz++;
if (isWaterBlocking(level, xx, yy, zz)) {
continue;
} else if (level->getMaterial(xx, yy, zz) == material && level->getData(xx, yy, zz) == 0) {
continue;
} else {
if (!isWaterBlocking(level, xx, yy - 1, zz)) {
return pass;
} else {
if (pass < 4) {
int v = getSlopeDistance(level, xx, yy, zz, pass + 1, d);
if (v < lowest) lowest = v;
}
}
}
}
return lowest;
}
int maxCount;
static const int NumDirections = 4;
bool result[NumDirections];
int dist[NumDirections];
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__LiquidTileDynamic_H__*/

View File

@@ -0,0 +1,66 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__LiquidTileStatic_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__LiquidTileStatic_H__
//package net.minecraft.world.level.tile;
#include "LiquidTile.h"
#include "../Level.h"
#include "FireTile.h"
class LiquidTileStatic: public LiquidTile
{
typedef LiquidTile super;
public:
LiquidTileStatic(int id, const Material* material)
: super(id, material)
{
setTicking(false);
if (material == Material::lava) setTicking(true);
}
void neighborChanged(Level* level, int x, int y, int z, int type) {
super::neighborChanged(level, x, y, z, type);
if (level->getTile(x, y, z) == id) {
setDynamic(level, x, y, z);
}
}
void tick(Level* level, int x, int y, int z, Random* random) {
//@fire
return;
if (material == Material::lava) {
int h = random->nextInt(3);
for (int i = 0; i < h; i++) {
x += random->nextInt(3) - 1;
y++;
z += random->nextInt(3) - 1;
int t = level->getTile(x, y, z);
if (t == 0) {
if (isFlammable(level, x - 1, y, z) || isFlammable(level, x + 1, y, z) || isFlammable(level, x, y, z - 1) || isFlammable(level, x, y, z + 1) || isFlammable(level, x, y - 1, z) || isFlammable(level, x, y + 1, z)) {
level->setTile(x, y, z, Tile::fire->id);
return;
}
} else if (Tile::tiles[t]->material->blocksMotion()) {
return;
}
}
}
}
private:
bool isFlammable(Level* level, int x, int y, int z) {
return level->getMaterial(x, y, z)->isFlammable();
}
void setDynamic(Level* level, int x, int y, int z) {
int d = level->getData(x, y, z);
level->noNeighborUpdate = true;
level->setTileAndDataNoUpdate(x, y, z, id - 1, d);
level->setTilesDirty(x, y, z, x, y, z);
level->addToTickNextTick(x, y, z, id - 1, getTickDelay());
level->noNeighborUpdate = false;
}
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__LiquidTileStatic_H__*/

View File

@@ -0,0 +1,27 @@
#include "MelonTile.h"
#include "../material/Material.h"
#include "../../../util/Random.h"
#include "../../Facing.h"
#include "../../item/Item.h"
MelonTile::MelonTile( int id )
:super(id, Material::vegetable){
tex = TEX;
}
int MelonTile::getTexture( LevelSource* level, int x, int y, int z, int face ) {
return getTexture(face);
}
int MelonTile::getTexture( int face ) {
if(face == Facing::UP || face == Facing::DOWN) return TEX_TOP;
return TEX;
}
int MelonTile::getResource( int data, Random* random ) {
return Item::melon->id;
}
int MelonTile::getResourceCount( Random* random ) {
return 3 + random->nextInt(5);
}

View File

@@ -0,0 +1,17 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__MelonTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__MelonTile_H__
#include "Tile.h"
class MelonTile : public Tile {
typedef Tile super;
public:
MelonTile(int id);
int getTexture(LevelSource* level, int x, int y, int z, int face);
int getTexture(int face);
int getResource(int data, Random* random);
int getResourceCount(Random* random);
private:
static const int TEX = 8 + 8 * 16;
static const int TEX_TOP = 9 + 8 * 16;
};
#endif /* NET_MINECRAFT_WORLD_LEVEL_TILE__MelonTile_H__ */

View File

@@ -0,0 +1,23 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__MetalTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__MetalTile_H__
//package net.minecraft.world.level.tile;
#include "Tile.h"
#include "../material/Material.h"
class MetalTile: public Tile
{
public:
MetalTile(int id, int tex)
: Tile(id, Material::metal)
{
this->tex = tex;
}
int getTexture(int face) {
return tex;
}
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__MetalTile_H__*/

View File

@@ -0,0 +1,42 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__MultiTextureTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__MultiTextureTile_H__
//package net.minecraft.world.level.tile;
#include "../material/Material.h"
class MultiTextureTile: public Tile
{
typedef Tile super;
public:
MultiTextureTile(int id, const int* textures, int texCount, const Material* material)
: super(id, textures[0], material),
_textures(textures),
_textureCount(texCount)
{
}
virtual int getTexture(int face, int data) {
if (data >= 0 && data < _textureCount)
{
return _textures[data];
}
return tex;
}
static int getTileDataForItemAuxValue(int auxValue) {
return (auxValue & 0xf);
}
protected:
int getSpawnResourcesAuxValue(int data) {
return data;
}
static int getItemAuxValueForTileData(int data) {
return data;
}
const int* _textures;
int _textureCount;
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__ClothTile_H__*/

View File

@@ -0,0 +1,56 @@
#include "Mushroom.h"
Mushroom::Mushroom(int id, int tex)
: super(id, tex)
{
float ss = 0.2f;
this->setShape(0.5f - ss, 0, 0.5f - ss, 0.5f + ss, ss * 2, 0.5f + ss);
this->setTicking(true);
}
void Mushroom::tick( Level* level, int x, int y, int z, Random* random ) {
if(random->nextInt(25) == 0) {
int r = 4;
int max = 5;
for (int xx = x - r; xx <= x + r; xx++)
for (int zz = z - r; zz <= z + r; zz++)
for (int yy = y - 1; yy <= y + 1; yy++) {
if (level->getTile(xx, yy, zz) == id && --max <= 0) return;
}
int x2 = x + random->nextInt(3) - 1;
int y2 = y + random->nextInt(2) - random->nextInt(2);
int z2 = z + random->nextInt(3) - 1;
for (int i = 0; i < 4; i++) {
if (level->isEmptyTile(x2, y2, z2) && canSurvive(level, x2, y2, z2)) {
x = x2;
y = y2;
z = z2;
}
x2 = x + random->nextInt(3) - 1;
y2 = y + random->nextInt(2) - random->nextInt(2);
z2 = z + random->nextInt(3) - 1;
}
if (level->isEmptyTile(x2, y2, z2) && canSurvive(level, x2, y2, z2)) {
level->setTile(x2, y2, z2, id);
}
}
}
bool Mushroom::mayPlace( Level* level, int x, int y, int z, unsigned char face ) {
return super::mayPlace(level, x, y, z, face) && canSurvive(level, x, y, z);
}
bool Mushroom::mayPlaceOn( int tile ) {
return Tile::solid[tile];
}
bool Mushroom::canSurvive( Level* level, int x, int y, int z ) {
if (y < 0 || y >= LEVEL_HEIGHT/*Level::maxBuildHeight*/)
return false;
int below = level->getTile(x, y - 1, z);
return (level->getRawBrightness(x, y, z) < 13 && mayPlaceOn(below));
}

20
src/world/level/tile/Mushroom.h Executable file
View File

@@ -0,0 +1,20 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__Mushroom_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__Mushroom_H__
#include "Bush.h"
class Mushroom : public Bush
{
typedef Bush super;
public:
Mushroom(int id, int tex);
void tick(Level* level, int x, int y, int z, Random* random);
bool mayPlace(Level* level, int x, int y, int z, unsigned char face);
bool mayPlaceOn(int tile);
bool canSurvive(Level* level, int x, int y, int z);
};
#endif /* NET_MINECRAFT_WORLD_LEVEL_TILE__Mushroom_H__ */

View File

@@ -0,0 +1,74 @@
#include "NetherReactor.h"
#include "../../entity/player/Player.h"
#include "../Level.h"
#include "entity/NetherReactorTileEntity.h"
#include "NetherReactorPattern.h"
NetherReactor::NetherReactor( int id, int tex, const Material* material ) : super(id, tex, material) { }
bool NetherReactor::use( Level* level, int x, int y, int z, Player* player ) {
if(level->getLevelData()->getGameType() != GameType::Survival)
return false;
// Level, X, Z
NetherReactorPattern pattern;
for(int checkLevel = 0; checkLevel <= 2; ++checkLevel) {
for(int checkX = -1; checkX <= 1; ++checkX) {
for(int checkZ = -1; checkZ <= 1; ++checkZ) {
if(level->getTile(x + checkX, y + checkLevel - 1, z + checkZ) != pattern.getTileAt(checkLevel, checkX + 1, checkZ + 1)) {
player->displayClientMessage("Not the correct pattern!");
return false;
}
}
}
}
if(!canSpawnStartNetherReactor(level, x, y, z, player)) return false;
player->displayClientMessage("Active!");
NetherReactorTileEntity* reactor = static_cast<NetherReactorTileEntity*>(level->getTileEntity(x, y, z));
if (reactor != NULL) {
reactor->lightItUp(x, y, z);
}
return true;
}
TileEntity* NetherReactor::newTileEntity() {
return TileEntityFactory::createTileEntity(TileEntityType::NetherReactor);
}
void NetherReactor::setPhase(Level* level, int x, int y, int z, int phase) {
int curPhase = level->getData(x, y, z);
if(curPhase != phase) {
level->setData(x, y, z, phase);
}
}
int NetherReactor::getTexture( int face, int data ) {
switch(data) {
case 1: return tex-1;
case 2: return tex-2;
default: return tex;
}
}
bool NetherReactor::canSpawnStartNetherReactor( Level* level, int x, int y, int z, Player* player ) {
if(!allPlayersCloseToReactor(level, x, y, z)) {
player->displayClientMessage("All players need to be close to the reactor.");
return false;
} else if(y > LEVEL_HEIGHT - 28) {
player->displayClientMessage("The nether reactor needs to be built lower down.");
return false;
} else if(y < 2) {
player->displayClientMessage("The nether reactor needs to be built higher up.");
return false;
}
return true;
}
bool NetherReactor::allPlayersCloseToReactor( Level* level, int x, int y, int z ) {
for(PlayerList::const_iterator i = level->players.begin(); i != level->players.end(); ++i) {
Player* currentPlayer = (*i);
if(!(currentPlayer->x >= x - 5 && currentPlayer->x <= x + 5)) return false;
if(!(currentPlayer->y - currentPlayer->heightOffset >= y -1 && currentPlayer->y - currentPlayer->heightOffset <= y + 1)) return false;
if(!(currentPlayer->z >= z - 5 && currentPlayer->z <= z + 5)) return false;
}
return true;
}

View File

@@ -0,0 +1,19 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__NetherReactor_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__NetherReactor_H__
#include "EntityTile.h"
class Material;
class NetherReactor : public EntityTile {
typedef EntityTile super;
public:
int getTexture(int face, int data);
NetherReactor(int id, int tex, const Material* material);
bool use(Level* level, int x, int y, int z, Player* player);
static void setPhase(Level* level, int x, int y, int z, int phase);
TileEntity* newTileEntity();
bool canSpawnStartNetherReactor( Level* level, int x, int y, int z, Player* player );
bool allPlayersCloseToReactor( Level* level, int x, int y, int z );
};
#endif /* NET_MINECRAFT_WORLD_LEVEL_TILE__NetherReactor_H__ */

View File

@@ -0,0 +1,43 @@
#include "NetherReactorPattern.h"
#include "Tile.h"
NetherReactorPattern::NetherReactorPattern( ) {
const int goldId = Tile::goldBlock->id;
const int stoneId = Tile::stoneBrick->id;
const int netherCoreId = Tile::netherReactor->id;
const unsigned int types[3][3][3] =
{
// Level 0
{
{goldId, stoneId, goldId},
{stoneId, stoneId, stoneId},
{goldId, stoneId, goldId}
},
// Level 1
{
{stoneId, 0, stoneId},
{0, netherCoreId, 0},
{stoneId, 0, stoneId}
},
// Level 2
{
{0, stoneId, 0},
{stoneId, stoneId, stoneId},
{0, stoneId, 0}
}
};
for(int setLevel = 0; setLevel <= 2; ++setLevel) {
for(int setX = 0; setX <= 2; ++setX) {
for(int setZ = 0; setZ <= 2; ++setZ) {
setTileAt(setLevel, setX, setZ, types[setLevel][setX][setZ]);
}
}
}
}
void NetherReactorPattern::setTileAt( int level, int x, int z, int tile) {
pattern[level][x][z] = tile;
}
unsigned int NetherReactorPattern::getTileAt( int level, int x, int z ) {
return pattern[level][x][z];
}

View File

@@ -0,0 +1,14 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__NetherReactorPattern_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__NetherReactorPattern_H__
class NetherReactorPattern {
public:
NetherReactorPattern();
unsigned int getTileAt(int level, int x, int z);
private:
void setTileAt(int level, int x, int z, int tile);
private:
unsigned int pattern[3][3][3];
};
#endif /* NET_MINECRAFT_WORLD_LEVEL_TILE__NetherReactorPattern_H__ */

View File

@@ -0,0 +1,60 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__ObsidianTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__ObsidianTile_H__
//package net.minecraft.world.level.tile;
#include "../../../util/Random.h"
#include "StoneTile.h"
class
ObsidianTile: public StoneTile
{
public:
ObsidianTile(int id, int tex, bool isGlowing)
: StoneTile(id, tex), isGlowing(isGlowing)
{
}
int getResourceCount(Random* random) {
return 1;
}
int getResource(int data, Random* random) {
return Tile::obsidian->id;
}
void animateTick(Level* level, int x, int y, int z, Random* random) {
if(isGlowing) {
poofParticles(level, x, y, z);
}
}
void poofParticles(Level* level, int x, int y, int z) {
Random& random = level->random;
float r = 1 / 16.0f;
for (int i = 0; i < 6; i++) {
float xx = x + random.nextFloat();
float yy = y + random.nextFloat();
float zz = z + random.nextFloat();
if (i == 0 && !level->isSolidBlockingTile(x, y + 1, z)) yy = y + 1 + r;
if (i == 1 && !level->isSolidBlockingTile(x, y - 1, z)) yy = y + 0 - r;
if (i == 2 && !level->isSolidBlockingTile(x, y, z + 1)) zz = z + 1 + r;
if (i == 3 && !level->isSolidBlockingTile(x, y, z - 1)) zz = z + 0 - r;
if (i == 4 && !level->isSolidBlockingTile(x + 1, y, z)) xx = x + 1 + r;
if (i == 5 && !level->isSolidBlockingTile(x - 1, y, z)) xx = x + 0 - r;
if (xx < x || xx > x + 1 || yy < 0 || yy > y + 1 || zz < z || zz > z + 1) {
level->addParticle(PARTICLETYPE(reddust), xx, yy, zz, 0, 0, 0);
}
}
}
private:
bool isGlowing;
/* void wasExploded(Level* level, int x, int y, int z) {
float s = 0.7f;
float xo = level->random.nextFloat() * s + (1 - s) * 0.5;
float yo = level->random.nextFloat() * s + (1 - s) * 0.5;
float zo = level->random.nextFloat() * s + (1 - s) * 0.5;
ItemEntity* item = new ItemEntity(level, x + xo, y + yo, z + zo, new ItemInstance(id));
item->throwTime = 10;
level->addEntity(item);
}*/
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__ObsidianTile_H__*/

41
src/world/level/tile/OreTile.h Executable file
View File

@@ -0,0 +1,41 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__OreTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__OreTile_H__
//package net.minecraft.world.level.tile;
#include "../../../util/Random.h"
#include "../material/Material.h"
#include "Tile.h"
#include "../../item/DyePowderItem.h"
class OreTile: public Tile
{
public:
OreTile(int id, int tex)
: Tile(id, tex, Material::stone)
{
}
int getResource(int data, Random* random) {
if (id == Tile::coalOre->id) return Item::coal->id;
if (id == Tile::emeraldOre->id) return Item::emerald->id;
if (id == Tile::lapisOre->id) return Item::dye_powder->id;
return id;
}
int getResourceCount(Random* random) {
if (id == Tile::lapisOre->id) return 4 + random->nextInt(5);
return 1;
}
protected:
//@Override
int getSpawnResourcesAuxValue(int data) {
// lapis spawns blue dye
if (id == Tile::lapisOre->id) return DyePowderItem::BLUE;
return 0;
}
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__OreTile_H__*/

View File

@@ -0,0 +1,64 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__QuartzBlockTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__QuartzBlockTile_H__
//package net.minecraft.world.level.tile;
#include "../../../util/Random.h"
#include "../../Facing.h"
#include "../material/Material.h"
#include "../Level.h"
#include "Tile.h"
class QuartzBlockTile: public Tile
{
typedef Tile super;
public:
static const int TYPE_DEFAULT = 0;
static const int TYPE_CHISELED = 1;
static const int TYPE_LINES = 2;
QuartzBlockTile(int id)
: super(id, 4 + 13 * 16, Material::stone)
{}
int getTexture(int face, int data) {
if (face == Facing::UP || face == Facing::DOWN) {
if (data == TYPE_CHISELED)
{
return 6 + 12 * 16;
}
if (data == TYPE_LINES)
{
return 5 + 12 * 16;
}
if (face == Facing::DOWN) {
return 3 + 13 * 16;
}
return 4 + 12 * 16;
}
if (data == TYPE_CHISELED)
{
return 6 + 13 * 16;
}
if (data == TYPE_LINES)
{
return 5 + 13 * 16;
}
return tex;
}
static int getTileDataForItemAuxValue(int auxValue) {
return (auxValue & 0xf);
}
protected:
int getSpawnResourcesAuxValue(int data) {
return data;
}
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__QuartzBlockTile_H__*/

View File

@@ -0,0 +1,93 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__RedStoneOreTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__RedStoneOreTile_H__
//package net.minecraft.world.level.tile;
#include "../../../util/Random.h"
#include "../material/Material.h"
#include "../Level.h"
class Player;
class RedStoneOreTile: public Tile
{
bool lit;
public:
RedStoneOreTile(int id, int tex, bool lit)
: Tile(id, tex, Material::stone)
{
if (lit) {
this->setTicking(true);
}
this->lit = lit;
}
int getTickDelay() {
return 30;
}
void attack(Level* level, int x, int y, int z, Player* player) {
interact(level, x, y, z);
Tile::attack(level, x, y, z, player);
}
void stepOn(Level* level, int x, int y, int z, Entity* entity) {
interact(level, x, y, z);
Tile::stepOn(level, x, y, z, entity);
}
bool use(Level* level, int x, int y, int z, Player* player) {
interact(level, x, y, z);
return Tile::use(level, x, y, z, player);
}
/*private*/ void interact(Level* level, int x, int y, int z) {
poofParticles(level, x, y, z);
if (id == Tile::redStoneOre->id) {
level->setTile(x, y, z, Tile::redStoneOre_lit->id);
}
}
void tick(Level* level, int x, int y, int z, Random* random) {
if (id == Tile::redStoneOre_lit->id) {
level->setTile(x, y, z, Tile::redStoneOre->id);
}
}
int getResource(int data, Random* random) {
//return Item.redStone.id;
return 0;
}
int getResourceCount(Random* random) {
return 4 + random->nextInt(2);
}
void animateTick(Level* level, int x, int y, int z, Random* random) {
if (lit) {
poofParticles(level, x, y, z);
}
}
private:
void poofParticles(Level* level, int x, int y, int z) {
Random& random = level->random;
float r = 1 / 16.0f;
for (int i = 0; i < 6; i++) {
float xx = x + random.nextFloat();
float yy = y + random.nextFloat();
float zz = z + random.nextFloat();
if (i == 0 && !level->isSolidBlockingTile(x, y + 1, z)) yy = y + 1 + r;
if (i == 1 && !level->isSolidBlockingTile(x, y - 1, z)) yy = y + 0 - r;
if (i == 2 && !level->isSolidBlockingTile(x, y, z + 1)) zz = z + 1 + r;
if (i == 3 && !level->isSolidBlockingTile(x, y, z - 1)) zz = z + 0 - r;
if (i == 4 && !level->isSolidBlockingTile(x + 1, y, z)) xx = x + 1 + r;
if (i == 5 && !level->isSolidBlockingTile(x - 1, y, z)) xx = x + 0 - r;
if (xx < x || xx > x + 1 || yy < 0 || yy > y + 1 || zz < z || zz > z + 1) {
level->addParticle(PARTICLETYPE(reddust), xx, yy, zz, 0, 0, 0);
}
}
}
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__RedStoneOreTile_H__*/

98
src/world/level/tile/ReedTile.h Executable file
View File

@@ -0,0 +1,98 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__ReedTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__ReedTile_H__
//package net.minecraft.world.level.tile;
#include "../../../util/Random.h"
#include "../material/Material.h"
#include "../Level.h"
#include "Tile.h"
class ReedTile: public Tile
{
public:
ReedTile(int id, int tex)
: Tile(id, Material::plant)
{
this->tex = tex;
float ss = 6 / 16.0f;
this->setShape(0.5f - ss, 0, 0.5f - ss, 0.5f + ss, 1, 0.5f + ss);
this->setTicking(true);
}
void tick(Level* level, int x, int y, int z, Random* random) {
if (level->isEmptyTile(x, y + 1, z)) {
int height = 1;
while (level->getTile(x, y - height, z) == id) {
height++;
}
if (height < 3) {
int age = level->getData(x, y, z);
if (age == 15) {
level->setTile(x, y + 1, z, id);
level->setData(x, y, z, 0);
} else {
level->setData(x, y, z, age + 1);
}
}
}
}
bool mayPlace(Level* level, int x, int y, int z) {
int below = level->getTile(x, y - 1, z);
if (below == id) return true;
if (below != ((Tile*)Tile::grass)->id && below != Tile::dirt->id && below != Tile::sand->id) return false;
if (level->getMaterial(x - 1, y - 1, z) == Material::water) return true;
if (level->getMaterial(x + 1, y - 1, z) == Material::water) return true;
if (level->getMaterial(x, y - 1, z - 1) == Material::water) return true;
if (level->getMaterial(x, y - 1, z + 1) == Material::water) return true;
return false;
}
void neighborChanged(Level* level, int x, int y, int z, int type) {
checkAlive(level, x, y, z);
}
bool canSurvive(Level* level, int x, int y, int z) {
return mayPlace(level, x, y, z);
}
AABB* getAABB(Level* level, int x, int y, int z) {
return NULL;
}
int getResource(int data, Random* random) {
return Item::reeds->id;
}
bool blocksLight() {
return false;
}
bool isSolidRender() {
return false;
}
bool isCubeShaped() {
return false;
}
int getRenderShape() {
return Tile::SHAPE_CROSS_TEXTURE;
}
int getRenderLayer() {
return Tile::RENDERLAYER_ALPHATEST;
}
protected:
const void checkAlive(Level* level, int x, int y, int z) {
if (!canSurvive(level, x, y, z)) {
popResource(level, x, y, z, ItemInstance(Item::reeds));
level->setTile(x, y, z, 0);
}
}
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__ReedTile_H__*/

View File

@@ -0,0 +1,37 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__SandStoneTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__SandStoneTile_H__
//package net.minecraft.world.level.tile;
#include "../../../util/Random.h"
#include "../../Facing.h"
#include "../material/Material.h"
#include "../Level.h"
#include "Tile.h"
#include "MultiTextureTile.h"
class SandStoneTile: public MultiTextureTile
{
typedef MultiTextureTile super;
public:
SandStoneTile(int id, const int* textures, int texCount)
: super(id, textures, texCount, Material::stone)
{}
int getTexture(int face, int data) {
if (face == Facing::UP || (face == Facing::DOWN && data > 0)) {
return 11 * 16;//tex - 16;
}
if (face == Facing::DOWN) {
return 13 * 16;//tex + 16;
}
return super::getTexture(face, data);
}
static const int TYPE_DEFAULT = 0;
static const int TYPE_HEIROGLYPHS = 1;
static const int TYPE_SMOOTHSIDE = 2;
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__SandStoneTile_H__*/

View File

@@ -0,0 +1,26 @@
#include "SandTile.h"
#include "../../entity/item/FallingTile.h"
bool SandTile::instaFall = false;
/*private*/
void SandTile::checkSlide(Level* level, int x, int y, int z)
{
int x2 = x;
int y2 = y;
int z2 = z;
if (isFree(level, x2, y2 - 1, z2) && y2 >= 0) {
int r = 32;
if (instaFall || !level->hasChunksAt(x - r, y - r, z - r, x + r, y + r, z + r)) {
level->setTile(x, y, z, 0);
while (isFree(level, x, y - 1, z) && y > 0)
y--;
if (y > 0) {
level->setTile(x, y, z, id);
}
} else {
FallingTile* e = new FallingTile(level, x + 0.5f, y + 0.5f, z + 0.5f, id);
level->addEntity(e);
}
}
}

57
src/world/level/tile/SandTile.h Executable file
View File

@@ -0,0 +1,57 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__SandTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__SandTile_H__
//package net.minecraft.world.level.tile;
#include "../../../util/Random.h"
#include "../material/Material.h"
#include "../Level.h"
#include "Tile.h"
class Level;
class SandTile: public Tile
{
public:
static bool instaFall;
SandTile(int type, int tex)
: Tile(type, tex, Material::sand)
{
}
// id == 0 -> not possible to create via serialization (yet)
int getEntityTypeId() const { return 0; } // @todo
void onPlace(Level* level, int x, int y, int z) {
//level->addToTickNextTick(x, y, z, id, getTickDelay());
}
void neighborChanged(Level* level, int x, int y, int z, int type) {
//level->addToTickNextTick(x, y, z, id, getTickDelay());
}
void tick(Level* level, int x, int y, int z, Random* random) {
checkSlide(level, x, y, z);
}
int getTickDelay() {
return 3;
}
static bool isFree(Level* level, int x, int y, int z) {
int t = level->getTile(x, y, z);
if (t == 0) return true;
if (t == ((Tile*)Tile::fire)->id) return true;
const Material* material = Tile::tiles[t]->material;
if (material == Material::water) return true;
if (material == Material::lava) return true;
return false;
}
private:
void checkSlide(Level* level, int x, int y, int z);
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__SandTile_H__*/

132
src/world/level/tile/Sapling.h Executable file
View File

@@ -0,0 +1,132 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__Sapling_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__Sapling_H__
//package net.minecraft.world.level->tile;
#include "Bush.h"
#include "../Level.h"
#include "../levelgen/feature/SpruceFeature.h"
#include "../levelgen/feature/BirchFeature.h"
#include "../levelgen/feature/TreeFeature.h"
class Sapling: public Bush
{
typedef Bush super;
static const int TYPE_MASK = 3;
static const int AGE_BIT = 8;
public:
Sapling(int id, int tex)
: super(id, tex)
{
float ss = 0.4f;
setShape(0.5f - ss, 0, 0.5f - ss, 0.5f + ss, ss * 2, 0.5f + ss);
}
void tick(Level* level, int x, int y, int z, Random* random) {
if (level->isClientSide) return;
super::tick(level, x, y, z, random);
if (level->getRawBrightness(x, y + 1, z) >= Level::MAX_BRIGHTNESS - 6) {
if (random->nextInt(7) == 0) {
int data = level->getData(x, y, z);
if ((data & AGE_BIT) == 0) {
//@attn @fix : was setData, but it only works if using sendTileUpdate
level->setDataNoUpdate(x, y, z, data | AGE_BIT);
} else {
growTree(level, x, y, z, random);
}
}
}
}
/*@Override*/
int getTexture(int face, int data) {
data = data & LeafTile::LEAF_TYPE_MASK;
if (data == LeafTile::EVERGREEN_LEAF) {
return 15 + 16 * 3;
} else if (data == LeafTile::BIRCH_LEAF) {
return 15 + 16 * 4;
//} else if (data == TYPE_JUNGLE) {
// return 14 + 16;
} else {
return super::getTexture(face, data);
}
}
void growTree(Level* level, int x, int y, int z, Random* random) {
int data = level->getData(x, y, z) & TYPE_MASK;
Feature* f = NULL;
int ox = 0, oz = 0;
bool multiblock = false;
if (data == LeafTile::EVERGREEN_LEAF) {
f = new SpruceFeature(true);
} else if (data == LeafTile::BIRCH_LEAF) {
f = new BirchFeature(true);
// } else if (data == TYPE_JUNGLE) {
//
// // check for mega tree
// for (ox = 0; ox >= -1; ox--) {
// for (oz = 0; oz >= -1; oz--) {
// if (isSapling(level, x + ox, y, z + oz, TYPE_JUNGLE) &&
// isSapling(level, x + ox + 1, y, z + oz, TYPE_JUNGLE) &&
// isSapling(level, x + ox, y, z + oz + 1, TYPE_JUNGLE) &&
// isSapling(level, x + ox + 1, y, z + oz + 1, TYPE_JUNGLE)) {
// f = /*new*/ MegaTreeFeature(true, 10 + random.nextInt(20), TreeTile::JUNGLE_TRUNK, LeafTile::JUNGLE_LEAF);
// multiblock = true;
// break;
// }
// }
// if (f) {
// break;
// }
// }
// if (!f) {
// ox = oz = 0;
// f = new TreeFeature(true, 4 + random.nextInt(7), TreeTile::JUNGLE_TRUNK, LeafTile::JUNGLE_LEAF, false);
// }
} else {
//if (random->nextInt(10) == 0) {
// f = new BasicTree(true);
//} else
f = new TreeFeature(true);
}
if (multiblock) {
level->setTileNoUpdate(x + ox, y, z + oz, 0);
level->setTileNoUpdate(x + ox + 1, y, z + oz, 0);
level->setTileNoUpdate(x + ox, y, z + oz + 1, 0);
level->setTileNoUpdate(x + ox + 1, y, z + oz + 1, 0);
} else {
level->setTileNoUpdate(x, y, z, 0);
}
if (!f->place(level, random, x + ox, y, z + oz)) {
if (multiblock) {
level->setTileAndDataNoUpdate(x + ox, y, z + oz, this->id, data);
level->setTileAndDataNoUpdate(x + ox + 1, y, z + oz, this->id, data);
level->setTileAndDataNoUpdate(x + ox, y, z + oz + 1, this->id, data);
level->setTileAndDataNoUpdate(x + ox + 1, y, z + oz + 1, this->id, data);
} else {
level->setTileAndDataNoUpdate(x, y, z, this->id, data);
}
}
if (f) delete f;
}
bool isSapling(Level* level, int x, int y, int z, int type) {
return (level->getTile(x, y, z) == id) && ((level->getData(x, y, z) & TYPE_MASK) == type);
}
protected:
int getSpawnResourcesAuxValue(int data) {
return data & TYPE_MASK;
}
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__Sapling_H__*/

113
src/world/level/tile/SignTile.h Executable file
View File

@@ -0,0 +1,113 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__SignTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__SignTile_H__
//package net.minecraft.world.level.tile;
#include "EntityTile.h"
#include "../../item/Item.h"
#include "../material/Material.h"
#include "entity/TileEntity.h"
#include "../../phys/AABB.h"
class SignTile: public EntityTile
{
typedef EntityTile super;
public:
SignTile(int id, int tileEntityClassId, bool onGround)
: super(id, Material::wood),
tileEntityClassId(tileEntityClassId),
onGround(onGround)
{
tex = 4;
float r = 4 / 16.0f;
float h = 16 / 16.0f;
this->setShape(0.5f - r, 0, 0.5f - r, 0.5f + r, h, 0.5f + r);
}
/*@Override*/
AABB* getAABB(Level* level, int x, int y, int z) {
return NULL;
}
/*@Override*/
AABB getTileAABB(Level* level, int x, int y, int z) {
updateShape(level, x, y, z);
return super::getTileAABB(level, x, y, z);
}
/*@Override*/
void updateShape(LevelSource* level, int x, int y, int z) {
if (onGround) return;
int face = level->getData(x, y, z);
float h0 = (4 + 0.5f) / 16.0f;
float h1 = (12 + 0.5f) / 16.0f;
float w0 = 0 / 16.0f;
float w1 = 16 / 16.0f;
float d0 = 2 / 16.0f;
setShape(0, 0, 0, 1, 1, 1);
if (face == 2) setShape(w0, h0, 1 - d0, w1, h1, 1);
if (face == 3) setShape(w0, h0, 0, w1, h1, d0);
if (face == 4) setShape(1 - d0, h0, w0, 1, h1, w1);
if (face == 5) setShape(0, h0, w0, d0, h1, w1);
}
/*@Override*/
int getRenderShape() {
return Tile::SHAPE_INVISIBLE;
}
/*@Override*/
bool isCubeShaped() {
return false;
}
/*@Override*/
bool isPathfindable(LevelSource* level, int x, int y, int z) {
return true;
}
/*@Override*/
bool isSolidRender() {
return false;
}
/*@Override*/
TileEntity* newTileEntity() {
return TileEntityFactory::createTileEntity(tileEntityClassId);
}
/*@Override*/
int getResource(int data, Random* random/*, int playerBonusLevel*/) {
return Item::sign->id;
}
/*@Override*/
void neighborChanged(Level* level, int x, int y, int z, int type) {
bool remove = false;
if (onGround) {
if (!level->getMaterial(x, y - 1, z)->isSolid()) remove = true;
} else {
int face = level->getData(x, y, z);
remove = true;
if (face == 2 && level->getMaterial(x, y, z + 1)->isSolid()) remove = false;
if (face == 3 && level->getMaterial(x, y, z - 1)->isSolid()) remove = false;
if (face == 4 && level->getMaterial(x + 1, y, z)->isSolid()) remove = false;
if (face == 5 && level->getMaterial(x - 1, y, z)->isSolid()) remove = false;
}
if (remove) {
spawnResources(level, x, y, z, level->getData(x, y, z), 0);
level->setTile(x, y, z, 0);
}
super::neighborChanged(level, x, y, z, type);
}
private:
bool onGround;
int tileEntityClassId;
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__SignTile_H__*/

38
src/world/level/tile/SnowTile.h Executable file
View File

@@ -0,0 +1,38 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__SnowTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__SnowTile_H__
//package net.minecraft.world.level->tile;
#include "Tile.h"
#include "../material/Material.h"
#include "../../item/Item.h"
#include "../../../util/Random.h"
class SnowTile: public Tile
{
typedef Tile super;
public:
SnowTile(int id, int tex)
: super(id, tex, Material::snow)
{
setTicking(true);
}
int getResource(int data, Random* random) {
return Item::snowBall->id;
}
int getResourceCount(Random* random) {
return 4;
}
void tick(Level* level, int x, int y, int z, Random* random) {
if (level->getBrightness(LightLayer::Block, x, y, z) > 11) {
this->spawnResources(level, x, y, z, level->getData(x, y, z), 0);
level->setTile(x, y, z, 0);
}
}
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__SnowTile_H__*/

View File

@@ -0,0 +1,237 @@
#include "../Level.h"
#include "../../phys/HitResult.h"
#include "../../phys/Vec3.h"
#include "../../Facing.h"
#include "StairTile.h"
const int StairTile::DEAD_SPACES[8][2] = {
{2, 6}, {3, 7}, {2, 3}, {6, 7},
{0, 4}, {1, 5}, {0, 1}, {4, 5}
};
int StairTile::getPlacedOnFaceDataValue(Level* level, int x, int y, int z, int face, float clickX, float clickY, float clickZ, int itemValue) {
if (face == Facing::DOWN || (face != Facing::UP && clickY > 0.5)) {
return itemValue | UPSIDEDOWN_BIT;
}
return itemValue;
}
bool StairTile::setStepShape(LevelSource* level, int x, int y, int z) {
int data = level->getData(x, y, z);
int dir = data & 0x3;
float bottom = 0.5f;
float top = 1.0f;
if ((data & UPSIDEDOWN_BIT) != 0) {
bottom = 0;
top = .5f;
}
float west = 0;
float east = 1;
float north = 0;
float south = .5f;
bool checkInnerPiece = true;
if (dir == DIR_EAST) {
west = .5f;
south = 1;
int backTile = level->getTile(x + 1, y, z);
int backData = level->getData(x + 1, y, z);
if (isStairs(backTile) && ((data & UPSIDEDOWN_BIT) == (backData & UPSIDEDOWN_BIT))) {
int backDir = backData & 0x3;
if (backDir == DIR_NORTH && !isLockAttached(level, x, y, z + 1, data)) {
south = .5f;
checkInnerPiece = false;
} else if (backDir == DIR_SOUTH && !isLockAttached(level, x, y, z - 1, data)) {
north = .5f;
checkInnerPiece = false;
}
}
} else if (dir == DIR_WEST) {
east = .5f;
south = 1;
int backTile = level->getTile(x - 1, y, z);
int backData = level->getData(x - 1, y, z);
if (isStairs(backTile) && ((data & UPSIDEDOWN_BIT) == (backData & UPSIDEDOWN_BIT))) {
int backDir = backData & 0x3;
if (backDir == DIR_NORTH && !isLockAttached(level, x, y, z + 1, data)) {
south = .5f;
checkInnerPiece = false;
} else if (backDir == DIR_SOUTH && !isLockAttached(level, x, y, z - 1, data)) {
north = .5f;
checkInnerPiece = false;
}
}
} else if (dir == DIR_SOUTH) {
north = .5f;
south = 1;
int backTile = level->getTile(x, y, z + 1);
int backData = level->getData(x, y, z + 1);
if (isStairs(backTile) && ((data & UPSIDEDOWN_BIT) == (backData & UPSIDEDOWN_BIT))) {
int backDir = backData & 0x3;
if (backDir == DIR_WEST && !isLockAttached(level, x + 1, y, z, data)) {
east = .5f;
checkInnerPiece = false;
} else if (backDir == DIR_EAST && !isLockAttached(level, x - 1, y, z, data)) {
west = .5f;
checkInnerPiece = false;
}
}
} else if (dir == DIR_NORTH) {
int backTile = level->getTile(x, y, z - 1);
int backData = level->getData(x, y, z - 1);
if (isStairs(backTile) && ((data & UPSIDEDOWN_BIT) == (backData & UPSIDEDOWN_BIT))) {
int backDir = backData & 0x3;
if (backDir == DIR_WEST && !isLockAttached(level, x + 1, y, z, data)) {
east = .5f;
checkInnerPiece = false;
} else if (backDir == DIR_EAST && !isLockAttached(level, x - 1, y, z, data)) {
west = .5f;
checkInnerPiece = false;
}
}
}
setShape(west, bottom, north, east, top, south);
return checkInnerPiece;
}
/*
* This method adds an extra 1/8 block if the stairs can attach as an
* "inner corner."
*/
bool StairTile::setInnerPieceShape(LevelSource* level, int x, int y, int z) {
int data = level->getData(x, y, z);
int dir = data & 0x3;
float bottom = 0.5f;
float top = 1.0f;
if ((data & UPSIDEDOWN_BIT) != 0) {
bottom = 0;
top = .5f;
}
float west = 0;
float east = .5f;
float north = .5f;
float south = 1.0f;
bool hasInnerPiece = false;
if (dir == DIR_EAST) {
int frontTile = level->getTile(x - 1, y, z);
int frontData = level->getData(x - 1, y, z);
if (isStairs(frontTile) && ((data & UPSIDEDOWN_BIT) == (frontData & UPSIDEDOWN_BIT))) {
int frontDir = frontData & 0x3;
if (frontDir == DIR_NORTH && !isLockAttached(level, x, y, z - 1, data)) {
north = 0;
south = .5f;
hasInnerPiece = true;
} else if (frontDir == DIR_SOUTH && !isLockAttached(level, x, y, z + 1, data)) {
north = .5f;
south = 1;
hasInnerPiece = true;
}
}
} else if (dir == DIR_WEST) {
int frontTile = level->getTile(x + 1, y, z);
int frontData = level->getData(x + 1, y, z);
if (isStairs(frontTile) && ((data & UPSIDEDOWN_BIT) == (frontData & UPSIDEDOWN_BIT))) {
west = .5f;
east = 1.0f;
int frontDir = frontData & 0x3;
if (frontDir == DIR_NORTH && !isLockAttached(level, x, y, z - 1, data)) {
north = 0;
south = .5f;
hasInnerPiece = true;
} else if (frontDir == DIR_SOUTH && !isLockAttached(level, x, y, z + 1, data)) {
north = .5f;
south = 1;
hasInnerPiece = true;
}
}
} else if (dir == DIR_SOUTH) {
int frontTile = level->getTile(x, y, z - 1);
int frontData = level->getData(x, y, z - 1);
if (isStairs(frontTile) && ((data & UPSIDEDOWN_BIT) == (frontData & UPSIDEDOWN_BIT))) {
north = 0;
south = .5f;
int frontDir = frontData & 0x3;
if (frontDir == DIR_WEST && !isLockAttached(level, x - 1, y, z, data)) {
hasInnerPiece = true;
} else if (frontDir == DIR_EAST && !isLockAttached(level, x + 1, y, z, data)) {
west = .5f;
east = 1.0f;
hasInnerPiece = true;
}
}
} else if (dir == DIR_NORTH) {
int frontTile = level->getTile(x, y, z + 1);
int frontData = level->getData(x, y, z + 1);
if (isStairs(frontTile) && ((data & UPSIDEDOWN_BIT) == (frontData & UPSIDEDOWN_BIT))) {
int frontDir = frontData & 0x3;
if (frontDir == DIR_WEST && !isLockAttached(level, x - 1, y, z, data)) {
hasInnerPiece = true;
} else if (frontDir == DIR_EAST && !isLockAttached(level, x + 1, y, z, data)) {
west = .5f;
east = 1.0f;
hasInnerPiece = true;
}
}
}
if (hasInnerPiece) {
setShape(west, bottom, north, east, top, south);
}
return hasInnerPiece;
}
HitResult StairTile::clip(Level* level, int xt, int yt, int zt, const Vec3& a, const Vec3& b)
{
HitResult results[8];
int data = level->getData(xt, yt, zt);
int dir = data & 0x3;
bool upsideDown = (data & UPSIDEDOWN_BIT) == UPSIDEDOWN_BIT;
const int* deadSpaces = (const int*)&DEAD_SPACES[dir + (upsideDown ? 4 : 0)];
isClipping = true;
for (int i = 0; i < 8; i++) {
clipStep = i;
results[i] = super::clip(level, xt, yt, zt, a, b);
}
isClipping = false;
results[deadSpaces[0]] = HitResult();
results[deadSpaces[1]] = HitResult();
HitResult* closest = NULL;
double closestDist = 0;
for (int r = 0; r < 8; r++) {
HitResult& result = results[r];
if (result.isHit()) {
double dist = result.pos.distanceToSqr(b);
if (dist > closestDist) {
closest = &result;
closestDist = dist;
}
}
}
if (closest == NULL)
{
return HitResult();
}
return *closest;
}

243
src/world/level/tile/StairTile.h Executable file
View File

@@ -0,0 +1,243 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__StairTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__StairTile_H__
//package net.minecraft.world.level.tile;
#include <vector>
#include "Tile.h"
#include "../../../util/Mth.h"
#include "../../../util/Random.h"
#include "../../entity/Mob.h"
class StairTile: public Tile
{
typedef Tile super;
Tile* base;
bool isClipping;
int clipStep;
int baseData;
public:
static const int UPSIDEDOWN_BIT = 4;
// the direction is the way going up (for normal non-upsidedown stairs)
static const int DIR_EAST = 0;
static const int DIR_WEST = 1;
static const int DIR_SOUTH = 2;
static const int DIR_NORTH = 3;
static const int DEAD_SPACES[8][2];
StairTile(int id, Tile* base)
: super(id, base->tex, base->material),
base(base),
isClipping(false),
clipStep(0),
baseData(0) // when needed in the future, set this to necessary texture data
{
setDestroyTime(base->destroySpeed);
setExplodeable(base->explosionResistance / 3);
setSoundType(*base->soundType);
setLightBlock(255);
}
HitResult clip(Level* level, int xt, int yt, int zt, const Vec3& a, const Vec3& b);
void updateShape(LevelSource* level, int x, int y, int z) {
if (isClipping) {
setShape(0.5f * (clipStep % 2), 0.5f * (clipStep / 2 % 2), 0.5f * (clipStep / 4 % 2), 0.5f + 0.5f * (clipStep % 2), 0.5f + 0.5f * (clipStep / 2 % 2), 0.5f + 0.5f * (clipStep / 4 % 2));
} else {
setShape(0, 0, 0, 1, 1, 1);
}
}
void setBaseShape(LevelSource* level, int x, int y, int z) {
int data = level->getData(x, y, z);
if ((data & UPSIDEDOWN_BIT) != 0) {
setShape(0, .5f, 0, 1, 1, 1);
} else {
setShape(0, 0, 0, 1, .5f, 1);
}
}
static bool isStairs(int id) {
return id > 0 && Tile::tiles[id]->getRenderShape() == Tile::SHAPE_STAIRS;
}
bool isLockAttached(LevelSource* level, int x, int y, int z, int data) {
int lockTile = level->getTile(x, y, z);
if (isStairs(lockTile) && level->getData(x, y, z) == data) {
return true;
}
return false;
}
bool setStepShape(LevelSource* level, int x, int y, int z);
bool setInnerPieceShape(LevelSource* level, int x, int y, int z);
// AABB* getAABB(Level* level, int x, int y, int z) {
// return super::getAABB(level, x, y, z);
//// return AABB.newTemp(x, y, z, x + 1, y + 1, z + 1);
// }
bool isSolidRender() {
return false;
}
bool isCubeShaped() {
return false;
}
int getRenderShape() {
return Tile::SHAPE_STAIRS;
}
//bool shouldRenderFace(LevelSource* level, int x, int y, int z, int face) {
// return super::shouldRenderFace(level, x, y, z, face);
//}
void addAABBs(Level* level, int x, int y, int z, const AABB* box, std::vector<AABB>& boxes) {
setBaseShape(level, x, y, z);
super::addAABBs(level, x, y, z, box, boxes);
bool checkInnerPiece = setStepShape(level, x, y, z);
super::addAABBs(level, x, y, z, box, boxes);
if (checkInnerPiece) {
if (setInnerPieceShape(level, x, y, z)) {
super::addAABBs(level, x, y, z, box, boxes);
}
}
setShape(0, 0, 0, 1, 1, 1);
}
/*
* void neighborChanged(Level level, int x, int y, int z, int type) {
* if (level.isOnline) return; if (level.getMaterial(x, y + 1, z).isSolid())
* { level.setTile(x, y, z, base.id); } else { checkStairs(level, x, y, z);
* checkStairs(level, x + 1, y - 1, z); checkStairs(level, x - 1, y - 1, z);
* checkStairs(level, x, y - 1, z - 1); checkStairs(level, x, y - 1, z + 1);
* checkStairs(level, x + 1, y + 1, z); checkStairs(level, x - 1, y + 1, z);
* checkStairs(level, x, y + 1, z - 1); checkStairs(level, x, y + 1, z + 1);
* } base.neighborChanged(level, x, y, z, type); }
*/
/** DELEGATES: **/
void addLights(Level* level, int x, int y, int z) {
base->addLights(level, x, y, z);
}
void animateTick(Level* level, int x, int y, int z, Random* random) {
base->animateTick(level, x, y, z, random);
}
void attack(Level* level, int x, int y, int z, Player* player) {
base->attack(level, x, y, z, player);
}
void destroy(Level* level, int x, int y, int z, int data) {
base->destroy(level, x, y, z, data);
}
float getBrightness(LevelSource* level, int x, int y, int z) {
return base->getBrightness(level, x, y, z);
}
float getExplosionResistance(Entity* source) {
return base->getExplosionResistance(source);
}
int getRenderLayer() {
return base->getRenderLayer();
}
int getResourceCount(Random* random) {
return base->getResourceCount(random);
}
int getTexture(int face, int data) {
return base->getTexture(face, baseData);
}
int getTexture(int face) {
return base->getTexture(face, baseData);
}
int getTexture(LevelSource* level, int x, int y, int z, int face) {
return base->getTexture(face, baseData);
}
int getTickDelay() {
return base->getTickDelay();
}
AABB getTileAABB(Level* level, int x, int y, int z) {
return base->getTileAABB(level, x, y, z);
}
void handleEntityInside(Level* level, int x, int y, int z, Entity* e, Vec3& current) {
base->handleEntityInside(level, x, y, z, e, current);
}
bool mayPick() {
return base->mayPick();
}
bool mayPick(int data, bool liquid) {
return base->mayPick(data, liquid);
}
bool mayPlace(Level* level, int x, int y, int z, unsigned char face) {
return base->mayPlace(level, x, y, z);
}
void onPlace(Level* level, int x, int y, int z) {
neighborChanged(level, x, y, z, 0);
base->onPlace(level, x, y, z);
}
void onRemove(Level* level, int x, int y, int z) {
base->onRemove(level, x, y, z);
}
void prepareRender(Level* level, int x, int y, int z) {
base->prepareRender(level, x, y, z);
}
void stepOn(Level* level, int x, int y, int z, Entity* entity) {
base->stepOn(level, x, y, z, entity);
}
void tick(Level* level, int x, int y, int z, Random* random) {
base->tick(level, x, y, z, random);
}
bool use(Level* level, int x, int y, int z, Player* player) {
return base->use(level, x, y, z, player);
}
void wasExploded(Level* level, int x, int y, int z) {
base->wasExploded(level, x, y, z);
}
void setPlacedBy(Level* level, int x, int y, int z, Mob* by) {
int dir = (Mth::floor(by->yRot * 4 / (360) + 0.5f)) & 3;
int usd = level->getData(x, y, z) & UPSIDEDOWN_BIT;
if (dir == 0) level->setData(x, y, z, 2 | usd);
if (dir == 1) level->setData(x, y, z, 1 | usd);
if (dir == 2) level->setData(x, y, z, 3 | usd);
if (dir == 3) level->setData(x, y, z, 0 | usd);
}
int getPlacedOnFaceDataValue(Level* level, int x, int y, int z, int face, float clickX, float clickY, float clickZ, int itemValue);
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__StairTile_H__*/

153
src/world/level/tile/StemTile.cpp Executable file
View File

@@ -0,0 +1,153 @@
#include "StemTile.h"
StemTile::StemTile( int id, Tile* fruit )
: super(id, 15 + 6 * 16),
fruit(fruit) {
setTicking(true);
float ss = 0.125f;
this->setShape(0.5f - ss, 0, 0.5f - ss, 0.5f + ss, 0.25f, 0.5f + ss);
}
bool StemTile::mayPlaceOn( int tile ) {
return tile == Tile::farmland->id;
}
void StemTile::tick( Level* level, int x, int y, int z, Random* random ) {
super::tick(level, x, y, z, random);
if (level->getRawBrightness(x, y + 1, z) >= Level::MAX_BRIGHTNESS - 6) {
float growthSpeed = getGrowthSpeed(level, x, y, z);
if (random->nextInt((int) (25 / growthSpeed) + 1) == 0) {
int age = level->getData(x, y, z);
if (age < 7) {
age++;
level->setData(x, y, z, age);
} else {
if (level->getTile(x - 1, y, z) == fruit->id) return;
if (level->getTile(x + 1, y, z) == fruit->id) return;
if (level->getTile(x, y, z - 1) == fruit->id) return;
if (level->getTile(x, y, z + 1) == fruit->id) return;
for(int a = 0; a < 4; ++a) {
int dir = a; //random->nextInt(4);
int xx = x;
int zz = z;
if (dir == 0) xx--;
if (dir == 1) xx++;
if (dir == 2) zz--;
if (dir == 3) zz++;
int below = level->getTile(xx, y - 1, zz);
if (level->getTile(xx, y, zz) == 0 && (below == Tile::farmland->id || below == Tile::dirt->id || below == Tile::grass->id)) {
level->setTile(xx, y, zz, fruit->id);
break;
}
}
}
}
}
}
void StemTile::growCropsToMax( Level* level, int x, int y, int z ) {
level->setData(x, y, z, 7);
}
float StemTile::getGrowthSpeed( Level* level, int x, int y, int z ) {
float speed = 1;
int n = level->getTile(x, y, z - 1);
int s = level->getTile(x, y, z + 1);
int w = level->getTile(x - 1, y, z);
int e = level->getTile(x + 1, y, z);
int d0 = level->getTile(x - 1, y, z - 1);
int d1 = level->getTile(x + 1, y, z - 1);
int d2 = level->getTile(x + 1, y, z + 1);
int d3 = level->getTile(x - 1, y, z + 1);
bool horizontal = w == this->id || e == this->id;
bool vertical = n == this->id || s == this->id;
bool diagonal = d0 == this->id || d1 == this->id || d2 == this->id || d3 == this->id;
for (int xx = x - 1; xx <= x + 1; xx++)
for (int zz = z - 1; zz <= z + 1; zz++) {
int t = level->getTile(xx, y - 1, zz);
float tileSpeed = 0;
if (t == Tile::farmland->id) {
tileSpeed = 1;
if (level->getData(xx, y - 1, zz) > 0) tileSpeed = 3;
}
if (xx != x || zz != z) tileSpeed /= 4;
speed += tileSpeed;
}
if (diagonal || (horizontal && vertical)) speed /= 2;
return speed;
}
int StemTile::getColor( int data ) {
int r = data * 32;
int g = 255 - data * 8;
int b = data * 4;
return r << 16 | g << 8 | b;
}
int StemTile::getColor( LevelSource* level, int x, int y, int z ) {
return getColor(level->getData(x, y, z));
}
int StemTile::getTexture( int face, int data ) {
return tex;
}
void StemTile::updateDefaultShape() {
float ss = 0.125f;
this->setShape(0.5f - ss, 0, 0.5f - ss, 0.5f + ss, 0.25f, 0.5f + ss);
}
void StemTile::updateShape( LevelSource* level, int x, int y, int z ) {
yy1 = (level->getData(x, y, z) * 2 + 2) / 16.0f;
float ss = 0.125f;
this->setShape(0.5f - ss, 0, 0.5f - ss, 0.5f + ss, (float) yy1, 0.5f + ss);
}
int StemTile::getRenderShape() {
return Tile::SHAPE_STEM;
}
int StemTile::getConnectDir( LevelSource* level, int x, int y, int z ) {
int d = level->getData(x, y, z);
if (d < 7) return -1;
if (level->getTile(x - 1, y, z) == fruit->id) return 0;
if (level->getTile(x + 1, y, z) == fruit->id) return 1;
if (level->getTile(x, y, z - 1) == fruit->id) return 2;
if (level->getTile(x, y, z + 1) == fruit->id) return 3;
return -1;
}
void StemTile::spawnResources( Level* level, int x, int y, int z, int data, float odds ) {
super::spawnResources(level, x, y, z, data, odds);
if (level->isClientSide) {
return;
}
Item* seed = NULL;
//if (fruit == Tile::pumpkin) seed = Item::seeds_pumpkin;
if (fruit == Tile::melon) seed = Item::seeds_melon;
for (int i = 0; i < 3; i++) {
if (level->random.nextInt(5 * 3) > data) continue;
popResource(level, x, y, z, ItemInstance(seed));
}
}
int StemTile::getResource( int data, Random* random ) {
return -1;
}
int StemTile::getResourceCount( Random* random ) {
return 1;
}

28
src/world/level/tile/StemTile.h Executable file
View File

@@ -0,0 +1,28 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__StemTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__StemTile_H__
#include "Bush.h"
class StemTile : public Bush {
typedef Bush super;
public:
StemTile(int id, Tile* fruit);
bool mayPlaceOn(int tile);
void tick(Level* level, int x, int y, int z, Random* random);
void growCropsToMax(Level* level, int x, int y, int z);
int getColor(int data);
int getColor(LevelSource* level, int x, int y, int z);
int getTexture(int face, int data);
void updateDefaultShape();
void updateShape(LevelSource* level, int x, int y, int z);
int getRenderShape();
int getConnectDir(LevelSource* level, int x, int y, int z);
void spawnResources(Level* level, int x, int y, int z, int data, float odds);
int getResource(int data, Random* random);
int getResourceCount(Random* random);
private:
float getGrowthSpeed(Level* level, int x, int y, int z);
private:
Tile* fruit;
};
#endif /* NET_MINECRAFT_WORLD_LEVEL_TILE__StemTile_H__ */

View File

@@ -0,0 +1,155 @@
#include "StoneSlabTile.h"
#include "../../../util/Random.h"
#include "../material/Material.h"
#include "../Level.h"
#include "../../Facing.h"
const std::string StoneSlabTile::SLAB_NAMES[] = {
"stone", "sand", "wood", "cobble", "brick", "smoothStoneBrick"
};
const int StoneSlabTile::SLAB_NAMES_COUNT = sizeof(SLAB_NAMES) / sizeof(std::string);
StoneSlabTile::StoneSlabTile(int id, bool fullSize)
: Tile(id, 6, Material::stone)
{
this->fullSize = fullSize;
if (!fullSize) {
setShape(0, 0, 0, 1, 0.5f, 1);
}
setLightBlock(255);
}
void StoneSlabTile::updateShape(LevelSource* level, int x, int y, int z)
{
if (fullSize) {
setShape(0, 0, 0, 1, 1, 1);
} else {
bool upper = (level->getData(x, y, z) & TOP_SLOT_BIT) != 0;
if (upper) {
setShape(0, 0.5f, 0, 1, 1, 1);
} else {
setShape(0, 0, 0, 1, 0.5f, 1);
}
}
}
void StoneSlabTile::updateDefaultShape()
{
if (fullSize) {
setShape(0, 0, 0, 1, 1, 1);
} else {
setShape(0, 0, 0, 1, 0.5f, 1);
}
}
int StoneSlabTile::getTexture(int face, int data) {
data = data & TYPE_MASK;
if (data == STONE_SLAB) {
if (face <= 1) return 6;
return 5;
} else if (data == SAND_SLAB) {
if (face == Facing::DOWN) return 13 * 16;
if (face == Facing::UP) return 11 * 16;
return 12 * 16;
} else if (data == WOOD_SLAB) {
return 4;
} else if (data == COBBLESTONE_SLAB) {
return 16;
} else if (data == BRICK_SLAB) {
return Tile::redBrick->tex;
} else if (data == SMOOTHBRICK_SLAB) {
return Tile::stoneBrickSmooth->tex;
}
return 6;
}
int StoneSlabTile::getTexture(int face) {
return getTexture(face, 0);
}
bool StoneSlabTile::isSolidRender() {
return fullSize;
}
int StoneSlabTile::getPlacedOnFaceDataValue(Level* level, int x, int y, int z, int face, float clickX, float clickY, float clickZ, int itemValue)
{
if (fullSize) return itemValue;
if (face == Facing::DOWN || (face != Facing::UP && clickY > 0.5)) {
return itemValue | TOP_SLOT_BIT;
}
return itemValue;
}
/*
void StoneSlabTile::onPlace(Level* level, int x, int y, int z) {
if (this != Tile::stoneSlabHalf) Tile::onPlace(level, x, y, z);
int below = level->getTile(x, y - 1, z);
int myData = level->getData(x, y, z);
int belowData = level->getData(x, y - 1, z);
if (myData != belowData) {
return;
}
if (below == Tile::stoneSlabHalf->id) {
level->setTile(x, y, z, 0);
level->setTileAndData(x, y - 1, z, Tile::stoneSlab->id, myData);
}
}
*/
int StoneSlabTile::getResource(int data, Random* random) {
return Tile::stoneSlabHalf->id;
}
int StoneSlabTile::getResourceCount(Random* random) {
if (fullSize) {
return 2;
}
return 1;
}
bool StoneSlabTile::isCubeShaped() {
return fullSize;
}
void StoneSlabTile::addAABBs( Level* level, int x, int y, int z, const AABB* box, std::vector<AABB>& boxes ) {
updateShape(level, x, y, z);
super::addAABBs(level, x, y, z, box, boxes);
}
static bool isHalfSlab(int tileId) {
return tileId == Tile::stoneSlabHalf->id;// || tileId == Tile::woodSlabHalf->id;
}
bool StoneSlabTile::shouldRenderFace(LevelSource* level, int x, int y, int z, int face) {
if (fullSize) return super::shouldRenderFace(level, x, y, z, face);
if (face != Facing::UP && face != Facing::DOWN && !super::shouldRenderFace(level, x, y, z, face)) {
return false;
}
int ox = x, oy = y, oz = z;
ox += Facing::STEP_X[Facing::OPPOSITE_FACING[face]];
oy += Facing::STEP_Y[Facing::OPPOSITE_FACING[face]];
oz += Facing::STEP_Z[Facing::OPPOSITE_FACING[face]];
bool isUpper = (level->getData(ox, oy, oz) & TOP_SLOT_BIT) != 0;
if (isUpper) {
if (face == Facing::DOWN) return true;
if (face == Facing::UP && super::shouldRenderFace(level, x, y, z, face)) return true;
return !(isHalfSlab(level->getTile(x, y, z)) && (level->getData(x, y, z) & TOP_SLOT_BIT) != 0);
} else {
if (face == Facing::UP) return true;
if (face == Facing::DOWN && super::shouldRenderFace(level, x, y, z, face)) return true;
return !(isHalfSlab(level->getTile(x, y, z)) && (level->getData(x, y, z) & TOP_SLOT_BIT) == 0);
}
}
int StoneSlabTile::getSpawnResourcesAuxValue(int data) {
return data & TYPE_MASK;
}

View File

@@ -0,0 +1,56 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__StoneSlabTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__StoneSlabTile_H__
//package net.minecraft.world.level.tile;
#include "Tile.h"
class Level;
class LevelSource;
class StoneSlabTile: public Tile
{
typedef Tile super;
public:
static const int STONE_SLAB = 0;
static const int SAND_SLAB = 1;
static const int WOOD_SLAB = 2;
static const int COBBLESTONE_SLAB = 3;
static const int BRICK_SLAB = 4;
static const int SMOOTHBRICK_SLAB = 5;
static const int TYPE_MASK = 7;
static const int TOP_SLOT_BIT = 8;
static const std::string SLAB_NAMES[];
static const int SLAB_NAMES_COUNT;
StoneSlabTile(int id, bool fullSize);
int getTexture(int face, int data);
int getTexture(int face);
bool isSolidRender();
bool isCubeShaped();
void updateShape(LevelSource* level, int x, int y, int z);
void updateDefaultShape();
void addAABBs( Level* level, int x, int y, int z, const AABB* box, std::vector<AABB>& boxes );
//void onPlace(Level* level, int x, int y, int z);
int getPlacedOnFaceDataValue(Level* level, int x, int y, int z, int face, float clickX, float clickY, float clickZ, int itemValue);
int getResource(int data, Random* random);
int getResourceCount(Random* random);
bool shouldRenderFace(LevelSource* level, int x, int y, int z, int face);
protected:
int getSpawnResourcesAuxValue(int data);
private:
bool fullSize;
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__StoneSlabTile_H__*/

View File

@@ -0,0 +1,24 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__StoneTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__StoneTile_H__
//package net.minecraft.world.level.tile;
#include "../../../util/Random.h"
#include "../material/Material.h"
#include "Tile.h"
class StoneTile: public Tile
{
public:
StoneTile(int id, int tex)
: Tile(id, tex, Material::stone)
{
}
int getResource(int data, Random* random) {
return Tile::stoneBrick->id;
}
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__StoneTile_H__*/

View File

@@ -0,0 +1,32 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__StonecutterTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__StonecutterTile_H__
#include "Tile.h"
#include "../Level.h"
#include "../material/Material.h"
#include "../../entity/player/Player.h"
class StonecutterTile: public Tile
{
typedef Tile super;
public:
StonecutterTile(int id)
: super(id, Material::stone)
{
tex = 13 + 16 * 2;
}
int getTexture(int face) {
if (face == Facing::UP) return 9 + 10 * 16;
if (face == Facing::DOWN) return 14 + 3 * 16;
if (face == Facing::NORTH || face == Facing::SOUTH) return 8 + 10 * 16;
return tex;
}
bool use(Level* level, int x, int y, int z, Player* player) {
player->startStonecutting(x, y, z);
return true;
}
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__StonecutterTile_H__*/

View File

@@ -0,0 +1,55 @@
#include "TallGrass.h"
#include "../FoliageColor.h"
#include "../../entity/player/Player.h"
#include "../../item/Item.h"
#include "../../item/ShearsItem.h"
TallGrass::TallGrass( int id, int tex ) : super(id, tex, Material::replaceable_plant) {
float ss = 0.4f;
setShape(0.5f - ss, 0, 0.5f - ss, 0.5f + ss, 0.8f, 0.5f + ss);
}
int TallGrass::getTexture( int face, int data ) {
if(data == TALL_GRASS) return tex;
if(data == FERN) return tex + 16 + 1;
if(data == DEAD_SHRUB) return tex + 16;
return tex;
}
int TallGrass::getColor() {
/*double temp = 0.5;
double rain = 1.0;
return GrassColor.get(temp, rain);*/
return 0x339933;
}
int TallGrass::getColor( int auxData ) {
if(auxData == DEAD_SHRUB) return 0xffffffff;
return FoliageColor::getDefaultColor();
}
int TallGrass::getColor( LevelSource* level, int x, int y, int z ) {
int d = level->getData(x, y, z);
if (d == DEAD_SHRUB) return 0xffffff;
return 0x339933;//level->getBiome(x, z)->getGrassColor();
}
int TallGrass::getResource( int data, Random* random ) {
if (random->nextInt(8) == 0) {
return Item::seeds_wheat->id;
}
return -1;
}
void TallGrass::playerDestroy( Level* level, Player* player, int x, int y, int z, int data ) {
if (!level->isClientSide && player->getSelectedItem() != NULL && player->getSelectedItem()->id == Item::shears->id) {
//player->awardStat(Stats.blockMined[id], 1);
// drop leaf block instead of sapling
ItemInstance itemInstance(Tile::tallgrass, 1, data);
popResource(level, x, y, z, itemInstance);
} else {
super::playerDestroy(level, player, x, y, z, data);
}
}

View File

@@ -0,0 +1,24 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__TallGrass_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__TallGrass_H__
#include "Bush.h"
class Pos;
class TallGrass : public Bush {
public:
typedef Bush super;
public:
static const int DEAD_SHRUB = 0;
static const int TALL_GRASS = 1;
static const int FERN = 3;
TallGrass(int id, int tex);
int getTexture(int face, int data);
int getColor();
int getColor(int auxData);
int getColor(LevelSource* level, int x, int y, int z);
int getResource(int data, Random* random);
void playerDestroy(Level* level, Player* player, int x, int y, int z, int data);
};
#endif /* NET_MINECRAFT_WORLD_LEVEL_TILE__TallGrass_H__ */

View File

@@ -0,0 +1,133 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__ThinFenceTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__ThinFenceTile_H__
//package net.minecraft.world.level.tile;
#include "Tile.h"
#include "../material/Material.h"
#include "../../phys/AABB.h"
class ThinFenceTile: public Tile
{
typedef Tile super;
public:
ThinFenceTile(int id, int tex, int edgeTex, const Material* material, bool dropsResources)
: super(id, tex, material),
edgeTexture(edgeTex),
dropsResources(dropsResources)
{
}
/*@Override*/
int getResource(int data, Random* random/*, int playerBonusLevel*/) {
if (!dropsResources) {
return 0;
}
return super::getResource(data, random/*, playerBonusLevel*/);
}
/*@Override*/
bool isSolidRender() {
return false;
}
/*@Override*/
bool isCubeShaped() {
return false;
}
int getRenderLayer() {
return Tile::RENDERLAYER_ALPHATEST;
}
/*@Override*/
int getRenderShape() {
return Tile::SHAPE_IRON_FENCE;
}
/*@Override*/
bool shouldRenderFace(LevelSource* level, int x, int y, int z, int face) {
int id = level->getTile(x, y, z);
if (id == this->id) return false;
return super::shouldRenderFace(level, x, y, z, face);
}
/*@Override*/
void addAABBs(Level* level, int x, int y, int z, const AABB* box, std::vector<AABB>& boxes ) {
bool n = attachsTo(level->getTile(x, y, z - 1));
bool s = attachsTo(level->getTile(x, y, z + 1));
bool w = attachsTo(level->getTile(x - 1, y, z));
bool e = attachsTo(level->getTile(x + 1, y, z));
if ((w && e) || (!w && !e && !n && !s)) {
setShape(0, 0, 7.0f / 16.0f, 1, 1, 9.0f / 16.0f);
super::addAABBs(level, x, y, z, box, boxes);
} else if (w && !e) {
setShape(0, 0, 7.0f / 16.0f, .5f, 1, 9.0f / 16.0f);
super::addAABBs(level, x, y, z, box, boxes);
} else if (!w && e) {
setShape(.5f, 0, 7.0f / 16.0f, 1, 1, 9.0f / 16.0f);
super::addAABBs(level, x, y, z, box, boxes);
}
if ((n && s) || (!w && !e && !n && !s)) {
setShape(7.0f / 16.0f, 0, 0, 9.0f / 16.0f, 1, 1);
super::addAABBs(level, x, y, z, box, boxes);
} else if (n && !s) {
setShape(7.0f / 16.0f, 0, 0, 9.0f / 16.0f, 1, .5f);
super::addAABBs(level, x, y, z, box, boxes);
} else if (!n && s) {
setShape(7.0f / 16.0f, 0, .5f, 9.0f / 16.0f, 1, 1);
super::addAABBs(level, x, y, z, box, boxes);
}
}
/*@Override*/
void updateDefaultShape() {
setShape(0, 0, 0, 1, 1, 1);
}
/*@Override*/
void updateShape(LevelSource* level, int x, int y, int z) {
float minX = 7.0f / 16.0f;
float maxX = 9.0f / 16.0f;
float minZ = 7.0f / 16.0f;
float maxZ = 9.0f / 16.0f;
bool n = attachsTo(level->getTile(x, y, z - 1));
bool s = attachsTo(level->getTile(x, y, z + 1));
bool w = attachsTo(level->getTile(x - 1, y, z));
bool e = attachsTo(level->getTile(x + 1, y, z));
if ((w && e) || (!w && !e && !n && !s)) {
minX = 0;
maxX = 1;
} else if (w && !e) {
minX = 0;
} else if (!w && e) {
maxX = 1;
}
if ((n && s) || (!w && !e && !n && !s)) {
minZ = 0;
maxZ = 1;
} else if (n && !s) {
minZ = 0;
} else if (!n && s) {
maxZ = 1;
}
setShape(minX, 0, minZ, maxX, 1, maxZ);
}
int getEdgeTexture() {
return edgeTexture;
}
const bool attachsTo(int tile) {
return Tile::solid[tile] || tile == id || tile == Tile::glass->id;
}
private:
int edgeTexture;
const bool dropsResources;
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__ThinFenceTile_H__*/

747
src/world/level/tile/Tile.cpp Executable file
View File

@@ -0,0 +1,747 @@
#include "TileInclude.h"
#include "../Level.h"
#include "../../entity/player/Player.h"
#include "../../entity/item/ItemEntity.h"
#include "../../item/Item.h"
#include "../../item/TileItem.h"
#include "../../../util/Random.h"
//#include "locale/Descriptive.h"
//#include "stats/Stats.h"
#include "../../entity/Entity.h"
#include "../LevelSource.h"
#include "../material/Material.h"
#include "../../phys/AABB.h"
#include "../../phys/HitResult.h"
#include "../../phys/Vec3.h"
#include "../../../locale/I18n.h"
#include "../../item/ClothTileItem.h"
#include "../../item/AuxDataTileItem.h"
#include "../../item/LeafTileItem.h"
#include "../../item/StoneSlabTileItem.h"
#include "../../item/SaplingTileItem.h"
#include "../../item/ItemCategory.h"
const int Tile::RENDERLAYER_OPAQUE = 0;
const int Tile::RENDERLAYER_ALPHATEST = 1;
const int Tile::RENDERLAYER_BLEND = 2;
const std::string Tile::TILE_DESCRIPTION_PREFIX("tile.");
const Tile::SoundType Tile::SOUND_NORMAL("stone", 1, 1);
const Tile::SoundType Tile::SOUND_WOOD("wood", 1, 1);
const Tile::SoundType Tile::SOUND_GRAVEL("gravel", 1, 1);
const Tile::SoundType Tile::SOUND_GRASS("grass", 0.5f, 1);
const Tile::SoundType Tile::SOUND_STONE("stone", 1, 1);
const Tile::SoundType Tile::SOUND_METAL("stone", 1, 1.5f);
const Tile::SoundType Tile::SOUND_GLASS("stone", "random.glass", 1, 1);
const Tile::SoundType Tile::SOUND_CLOTH("cloth", 1, 1);
#ifdef PRE_ANDROID23
const Tile::SoundType Tile::SOUND_SAND("sand", 0.45f, 1);
#else
const Tile::SoundType Tile::SOUND_SAND("sand", "step.gravel", 1, 1);
#endif
const Tile::SoundType Tile::SOUND_SILENT("", 0, 0);
Tile* Tile::tiles[] = {NULL};
int Tile::lightBlock[] = {0};
int Tile::lightEmission[] = {0};
bool Tile::solid[] = {false};
bool Tile::isEntityTile[] = {false};
bool Tile::translucent[] = {true, false}; // @trans: translucent, @trans "asbMax", some more like "*conditon"
bool Tile::shouldTick[] = {false};
bool Tile::sendTileData[] = {false};
Tile* Tile::sand = NULL;
Tile* Tile::sandStone = NULL;
const int SANDSTONE_TEXTURES[] = { 0 + 16 * 12, 5 + 16 * 14, 6 + 16 * 14 };
const int SANDSTONE_TEXTURE_COUNT = 3;
Tile* Tile::stoneBrick = NULL;
Tile* Tile::redBrick = NULL;
Tile* Tile::wood = NULL;
Tile* Tile::sapling = NULL;
Tile* Tile::glass = NULL;
Tile* Tile::web = NULL;
Tile* Tile::thinGlass = NULL;
Tile* Tile::calmWater = NULL;
Tile* Tile::calmLava = NULL;
Tile* Tile::gravel = NULL;
Tile* Tile::rock = NULL;
Tile* Tile::unbreakable = NULL;
Tile* Tile::dirt = NULL;
Tile* Tile::grass = NULL;
Tile* Tile::ice = NULL;
Tile* Tile::clay = NULL;
Tile* Tile::farmland = NULL;
Tile* Tile::stoneSlab = NULL;
Tile* Tile::stoneSlabHalf=NULL;
Tile* Tile::cloth = NULL;
Tile* Tile::flower = NULL;
Tile* Tile::rose = NULL;
Tile* Tile::mushroom1 = NULL;
Tile* Tile::mushroom2 = NULL;
Tile* Tile::topSnow = NULL;
Tile* Tile::treeTrunk = NULL;
Tile* Tile::snow = NULL;
LeafTile* Tile::leaves = NULL;
Tile* Tile::emeraldOre = NULL;
Tile* Tile::redStoneOre = NULL;
Tile* Tile::redStoneOre_lit = NULL;
Tile* Tile::goldOre = NULL;
Tile* Tile::ironOre = NULL;
Tile* Tile::coalOre = NULL;
Tile* Tile::lapisOre = NULL;
Tile* Tile::lapisBlock = NULL;
Tile* Tile::reeds = NULL;
Tile* Tile::ladder = NULL;
Tile* Tile::obsidian = NULL;
Tile* Tile::tnt = NULL;
Tile* Tile::bookshelf = NULL;
Tile* Tile::sign = NULL;
Tile* Tile::wallSign = NULL;
Tile* Tile::mossStone = NULL;
Tile* Tile::torch = NULL;
Tile* Tile::water = NULL;
Tile* Tile::lava = NULL;
FireTile* Tile::fire = NULL;
Tile* Tile::invisible_bedrock = NULL;
Tile* Tile::goldBlock = NULL;
Tile* Tile::ironBlock = NULL;
Tile* Tile::emeraldBlock= NULL;
Tile* Tile::workBench = NULL;
Tile* Tile::stonecutterBench = NULL;
Tile* Tile::crops = NULL;
Tile* Tile::furnace = NULL;
Tile* Tile::furnace_lit = NULL;
Tile* Tile::chest = NULL;
Tile* Tile::lightGem = NULL;
Tile* Tile::stairs_wood = NULL;
Tile* Tile::stairs_stone= NULL;
Tile* Tile::stairs_brick= NULL;
Tile* Tile::door_wood = NULL;
Tile* Tile::door_iron = NULL;
Tile* Tile::cactus = NULL;
Tile* Tile::melon = NULL;
Tile* Tile::melonStem = NULL;
Tile* Tile::bed = NULL;
Tile* Tile::tallgrass = NULL;
Tile* Tile::trapdoor = NULL;
Tile* Tile::stoneBrickSmooth = NULL;
const int STONE_BRICK_TEXTURES[] = { 6 + 16 * 3, 4 + 16 * 6, 5 + 16 * 6 };
const int STONE_BRICK_TEXTURE_COUNT = 3;
Tile* Tile::fence = NULL;
Tile* Tile::fenceGate = NULL;
Tile* Tile::info_updateGame1 = NULL;
Tile* Tile::info_updateGame2 = NULL;
Tile* Tile::info_reserved6 = NULL;
Tile* Tile::grass_carried = NULL;
LeafTile* Tile::leaves_carried = NULL;
Tile* Tile::netherReactor = NULL;
Tile* Tile::glowingObsidian = NULL;
Tile* Tile::stairs_stoneBrickSmooth = NULL;
Tile* Tile::netherBrick = NULL;
Tile* Tile::netherrack = NULL;
Tile* Tile::stairs_netherBricks = NULL;
Tile* Tile::stairs_sandStone = NULL;
Tile* Tile::quartzBlock = NULL;
Tile* Tile::stairs_quartz = NULL;
/*static*/
void Tile::initTiles() {
rock = (new StoneTile(1, 1))->init()->setDestroyTime(1.5f)->setExplodeable(10)->setSoundType(SOUND_STONE)->setCategory(ItemCategory::Structures)->setDescriptionId("stone");
grass = (GrassTile*) (new GrassTile(2))->init()->setDestroyTime(0.6f)->setSoundType(SOUND_GRASS)->setCategory(ItemCategory::Structures)->setDescriptionId("grass");
dirt = (new DirtTile(3, 2))->init()->setDestroyTime(0.5f)->setSoundType(SOUND_GRAVEL)->setCategory(ItemCategory::Structures)->setDescriptionId("dirt");
stoneBrick = (new Tile(4, 16, Material::stone))->init()->setDestroyTime(2.0f)->setExplodeable(10)->setSoundType(SOUND_STONE)->setCategory(ItemCategory::Structures)->setDescriptionId("stonebrick");
wood = (new Tile(5, 4, Material::wood))->init()->setDestroyTime(2.0f)->setExplodeable(5)->setSoundType(SOUND_WOOD)->setCategory(ItemCategory::Structures)->setDescriptionId("wood");
sapling = (new Sapling(6, 15))->init()->setDestroyTime(0.0f)->setSoundType(SOUND_GRASS)->setCategory(ItemCategory::Structures)->setDescriptionId("sapling");//->sendTileData();
unbreakable = (new Tile(7, 17, Material::stone))->init()->setDestroyTime(-1)->setExplodeable(6000000)->setSoundType(SOUND_STONE)->setCategory(ItemCategory::Structures)->setDescriptionId("bedrock");
water = (new LiquidTileDynamic(8, Material::water))->init()->setDestroyTime(100.0f)->setLightBlock(3)->setCategory(ItemCategory::Structures)->setDescriptionId("water");
calmWater = (new LiquidTileStatic(9, Material::water))->init()->setDestroyTime(100.0f)->setLightBlock(3)->setCategory(ItemCategory::Structures)->setDescriptionId("water");
lava = (new LiquidTileDynamic(10, Material::lava))->init()->setDestroyTime(00.0f)->setLightEmission(1.0f)->setLightBlock(255)->setCategory(ItemCategory::Structures)->setDescriptionId("lava"); // 00.0?
calmLava = (new LiquidTileStatic(11, Material::lava))->init()->setDestroyTime(100.0f)->setLightEmission(1.0f)->setLightBlock(255)->setCategory(ItemCategory::Structures)->setDescriptionId("lava");
sand = (new HeavyTile(12, 18))->init()->setDestroyTime(0.5f)->setSoundType(SOUND_SAND)->setCategory(ItemCategory::Structures)->setDescriptionId("sand");
gravel = (new GravelTile(13, 19))->init()->setDestroyTime(0.6f)->setSoundType(SOUND_GRAVEL)->setCategory(ItemCategory::Structures)->setDescriptionId("gravel");
goldOre = (new OreTile(14, 32))->init()->setDestroyTime(3.0f)->setExplodeable(5)->setSoundType(SOUND_STONE)->setCategory(ItemCategory::Decorations)->setDescriptionId("oreGold");
ironOre = (new OreTile(15, 33))->init()->setDestroyTime(3.0f)->setExplodeable(5)->setSoundType(SOUND_STONE)->setCategory(ItemCategory::Decorations)->setDescriptionId("oreIron");
coalOre = (new OreTile(16, 34))->init()->setDestroyTime(3.0f)->setExplodeable(5)->setSoundType(SOUND_STONE)->setCategory(ItemCategory::Structures)->setDescriptionId("oreCoal");
treeTrunk = (new TreeTile(17))->init()->setDestroyTime(2.0f)->setSoundType(SOUND_WOOD)->setCategory(ItemCategory::Structures)->setDescriptionId("log");
leaves = (LeafTile*) (new LeafTile(18, 4 + 3 * 16))->init()->setDestroyTime(0.2f)->setLightBlock(1)->setSoundType(SOUND_GRASS)->setCategory(ItemCategory::Structures)->setDescriptionId("leaves");
glass = (new GlassTile(20, 49, Material::glass, false))->init()->setDestroyTime(0.3f)->setSoundType(SOUND_GLASS)->setCategory(ItemCategory::Structures)->setDescriptionId("glass");
lapisOre = (new OreTile(21, 10 * 16))->init()->setDestroyTime(3.0f)->setExplodeable(5)->setSoundType(SOUND_STONE)->setCategory(ItemCategory::Structures)->setDescriptionId("oreLapis");
lapisBlock = (new Tile(22, 9 * 16, Material::stone))->init()->setDestroyTime(3.0f)->setExplodeable(5)->setSoundType(SOUND_STONE)->setCategory(ItemCategory::Decorations)->setDescriptionId("blockLapis");
sandStone = (new SandStoneTile(24, (const int*)&SANDSTONE_TEXTURES, SANDSTONE_TEXTURE_COUNT))->init()->setSoundType(SOUND_STONE)->setDestroyTime(0.8f)->setCategory(ItemCategory::Structures)->setDescriptionId("sandStone");
bed = (new BedTile(26))->init()->setDestroyTime(0.2f)->setCategory(ItemCategory::Structures)->setDescriptionId("bed");
web = (new WebTile(30, 11))->init()->setLightBlock(1)->setDestroyTime(4.0f)->setCategory(ItemCategory::Decorations)->setDescriptionId("web");
tallgrass = (new TallGrass(31, 2 * 16 + 7))->init()->setDestroyTime(0.0f)->setSoundType(SOUND_GRASS)->setCategory(ItemCategory::Decorations)->setDescriptionId("tallgrass");
cloth = (new ClothTile(35))->init()->setDestroyTime(0.8f)->setSoundType(SOUND_CLOTH)->setCategory(ItemCategory::Structures)->setDescriptionId("cloth");
flower = (new Bush(37, 13))->init()->setDestroyTime(0.0f)->setSoundType(SOUND_GRASS)->setCategory(ItemCategory::Decorations)->setDescriptionId("flower");
rose = (new Bush(38, 12))->init()->setDestroyTime(0.0f)->setSoundType(SOUND_GRASS)->setCategory(ItemCategory::Decorations)->setDescriptionId("rose");
mushroom1 = (new Mushroom(39, 13 + 16))->init()->setDestroyTime(0.0f)->setSoundType(SOUND_GRASS)->setLightEmission(2 / 16.0f)->setCategory(ItemCategory::Decorations)->setDescriptionId("mushroom");
mushroom2 = (new Mushroom(40, 12 + 16))->init()->setDestroyTime(0.0f)->setSoundType(SOUND_GRASS)->setCategory(ItemCategory::Decorations)->setDescriptionId("mushroom");
goldBlock = (new MetalTile(41, 39 - 16))->init()->setDestroyTime(3.0f)->setExplodeable(10)->setSoundType(SOUND_METAL)->setCategory(ItemCategory::Decorations)->setDescriptionId("blockGold");
ironBlock = (new MetalTile(42, 38 - 16))->init()->setDestroyTime(5.0f)->setExplodeable(10)->setSoundType(SOUND_METAL)->setCategory(ItemCategory::Decorations)->setDescriptionId("blockIron");
stoneSlab = (new StoneSlabTile(43, true))->init()->setDestroyTime(2.0f)->setExplodeable(10)->setSoundType(SOUND_STONE)->setCategory(ItemCategory::Structures)->setDescriptionId("stoneSlab");
stoneSlabHalf=(new StoneSlabTile(44, false))->init()->setDestroyTime(2.0f)->setExplodeable(10)->setSoundType(SOUND_STONE)->setCategory(ItemCategory::Structures)->setDescriptionId("stoneSlab");
redBrick = (new Tile(45, 7, Material::stone))->init()->setDestroyTime(2.0f)->setExplodeable(10)->setSoundType(SOUND_STONE)->setCategory(ItemCategory::Structures)->setDescriptionId("brick");
tnt = (new TntTile(46, 8))->init()->setDestroyTime(0.0f)->setSoundType(SOUND_GRASS)->setCategory(ItemCategory::Tools)->setDescriptionId("tnt");
bookshelf = (new BookshelfTile(47, 35))->init()->setDestroyTime(1.5f)->setSoundType(SOUND_WOOD)->setCategory(ItemCategory::Decorations)->setDescriptionId("bookshelf");
mossStone = (new Tile(48, 36, Material::stone))->init()->setDestroyTime(2.0f)->setExplodeable(10)->setSoundType(SOUND_STONE)->setCategory(ItemCategory::Structures)->setDescriptionId("stoneMoss");
obsidian = (new ObsidianTile(49, 37, false))->init()->setDestroyTime(10.0f)->setExplodeable(2000)->setSoundType(SOUND_STONE)->setCategory(ItemCategory::Structures)->setDescriptionId("obsidian");
torch = (new TorchTile(50, 5 * 16))->init()->setDestroyTime(0.0f)->setLightEmission(15 / 16.0f)->setSoundType(SOUND_WOOD)->setCategory(ItemCategory::Tools)->setDescriptionId("torch");
stairs_wood = (new StairTile(53, wood))->init()->setCategory(ItemCategory::Structures)->setDescriptionId("stairsWood");
chest = (new ChestTile(54))->init()->setCategory(ItemCategory::Structures)->setDestroyTime(2.5f)->setSoundType(SOUND_WOOD)->setDescriptionId("chest");//->sendTileData();
emeraldOre = (new OreTile(56, 16 * 3 + 2))->init()->setDestroyTime(3.0f)->setExplodeable(5)->setSoundType(SOUND_STONE)->setCategory(ItemCategory::Decorations)->setDescriptionId("oreDiamond");
emeraldBlock= (new MetalTile(57, 40 - 16))->init()->setDestroyTime(5.0f)->setExplodeable(10)->setSoundType(SOUND_METAL)->setCategory(ItemCategory::Decorations)->setDescriptionId("blockDiamond");
workBench = (new WorkbenchTile(58))->init()->setDestroyTime(2.5f)->setSoundType(SOUND_WOOD)->setCategory(ItemCategory::Structures)->setDescriptionId("workbench");
crops = (new CropTile(59, 8 + 5 * 16))->init()->setDestroyTime(0.0f)->setSoundType(SOUND_GRASS)->setCategory(ItemCategory::Structures)->setDescriptionId("crops");//->sendTileData();
farmland = (new FarmTile(60))->init()->setDestroyTime(0.6f)->setSoundType(SOUND_GRAVEL)->setCategory(ItemCategory::Structures)->setDescriptionId("farmland");
furnace = (new FurnaceTile(61, false))->init()->setDestroyTime(3.5f)->setSoundType(SOUND_STONE)->setCategory(ItemCategory::Structures)->setDescriptionId("furnace");//.sendTileData();
furnace_lit = (new FurnaceTile(62, true))->init()->setDestroyTime(3.5f)->setSoundType(SOUND_STONE)->setLightEmission(14 / 16.0f)->setCategory(ItemCategory::Structures)->setDescriptionId("furnace");//.sendTileData();
sign = (new SignTile(63, TileEntityType::Sign, true))->init()->setDestroyTime(1.0f)->setSoundType(SOUND_WOOD)->setCategory(ItemCategory::Decorations)->setDescriptionId("sign");//->sendTileData();
door_wood = (new DoorTile(64, Material::wood))->init()->setDestroyTime(3.0f)->setSoundType(SOUND_WOOD)->setCategory(ItemCategory::Structures)->setDescriptionId("doorWood");
ladder = (new LadderTile(65, 3 + 5 * 16))->init()->setDestroyTime(0.4f)->setSoundType(SOUND_WOOD)->setCategory(ItemCategory::Structures)->setDescriptionId("ladder");
stairs_stone= (new StairTile(67, stoneBrick))->init()->setCategory(ItemCategory::Structures)->setDescriptionId("stairsStone");
wallSign = (new SignTile(68, TileEntityType::Sign, false))->init()->setDestroyTime(1.0f)->setSoundType(SOUND_WOOD)->setCategory(ItemCategory::Decorations)->setDescriptionId("sign");//->sendTileData();
door_iron = (new DoorTile(71, Material::metal))->init()->setDestroyTime(5.0f)->setSoundType(SOUND_METAL)->setCategory(ItemCategory::Structures)->setDescriptionId("doorIron");
redStoneOre = (new RedStoneOreTile(73, 16 * 3 + 3, false))->init()->setDestroyTime(3.0f)->setExplodeable(5)->setSoundType(SOUND_STONE)->setCategory(ItemCategory::Mechanisms)->setDescriptionId("oreRedstone");
redStoneOre_lit = (new RedStoneOreTile(74, 16 * 3 + 3, true))->init()->setDestroyTime(3.0f)->setLightEmission(10 / 16.0f)->setExplodeable(5)->setSoundType(SOUND_STONE)->setCategory(ItemCategory::Mechanisms)->setDescriptionId("oreRedstone");
topSnow = (new TopSnowTile(78, 16 * 4 + 2))->init()->setDestroyTime(0.1f)->setSoundType(SOUND_CLOTH)->setCategory(ItemCategory::Structures)->setDescriptionId("snow");
ice = (new IceTile(79, 16 * 4 + 3))->init()->setDestroyTime(0.5f)->setLightBlock(3)->setSoundType(SOUND_GLASS)->setCategory(ItemCategory::Structures)->setDescriptionId("ice");
snow = (new SnowTile(80, 16 * 4 + 2))->init()->setDestroyTime(0.2f)->setSoundType(SOUND_CLOTH)->setCategory(ItemCategory::Structures)->setDescriptionId("snow");
cactus = (new CactusTile(81, 16 * 4 + 6))->init()->setDestroyTime(0.4f)->setSoundType(SOUND_CLOTH)->setCategory(ItemCategory::Structures)->setDescriptionId("cactus");
clay = (new ClayTile(82, 16 * 4 + 8))->init()->setDestroyTime(0.6f)->setSoundType(SOUND_GRAVEL)->setCategory(ItemCategory::Structures)->setDescriptionId("clay");
reeds = (new ReedTile(83, 16 * 4 + 9))->init()->setDestroyTime(0.0f)->setSoundType(SOUND_GRASS)->setCategory(ItemCategory::Structures)->setDescriptionId("reeds");
fence = (new FenceTile(85, 4))->init()->setDestroyTime(2.0f)->setExplodeable(5)->setSoundType(SOUND_WOOD)->setCategory(ItemCategory::Structures)->setDescriptionId("fence");
netherrack = (new Tile(87, 7 + 6 * 16, Material::stone))->init()->setDestroyTime(0.4f)->setSoundType(SOUND_STONE)->setDescriptionId("hellrock");
//hellSand = (new HellSandTile(88, 8 + 6 * 16, Material::sand))->init()->setDestroyTime(0.5f)->setSoundType(SOUND_SAND)->setDescriptionId("hellsand");
lightGem = (new LightGemTile(89, 9 + 16 * 6, Material::glass))->init()->setDestroyTime(0.3f)->setCategory(ItemCategory::Structures)->setSoundType(SOUND_GLASS)->setLightEmission(1.0f)->setDescriptionId("lightgem");
invisible_bedrock = (new InvisibleTile(95, 0, Material::stone))->init()->setDestroyTime(-1)->setExplodeable(6000000);//->setSoundType(SOUND_SILENT);
trapdoor = (new TrapDoorTile(96, Material::wood))->init()->setDestroyTime(3.0f)->setSoundType(SOUND_WOOD)->setCategory(ItemCategory::Structures)->setDescriptionId("trapdoor");//->sendTileData();
stoneBrickSmooth = (new MultiTextureTile(98, (const int*)&STONE_BRICK_TEXTURES, STONE_BRICK_TEXTURE_COUNT, Material::stone))->init()->setDestroyTime(1.5f)->setExplodeable(10)->setSoundType(SOUND_STONE)->setCategory(ItemCategory::Structures)->setDescriptionId("stonebricksmooth");
thinGlass = (new ThinFenceTile(102, 1 + 3 * 16, 4 + 9 * 16, Material::glass, false))->init()->setDestroyTime(0.3f)->setSoundType(SOUND_GLASS)->setCategory(ItemCategory::Structures)->setDescriptionId("thinGlass");
melon = (new MelonTile(103))->init()->setDestroyTime(1.0f)->setSoundType(SOUND_WOOD)->setCategory(ItemCategory::FoodArmor)->setDescriptionId("melon");
melonStem = (new StemTile(105, Tile::melon))->init()->setDestroyTime(0.0f)->setSoundType(SOUND_WOOD)->setCategory(ItemCategory::FoodArmor)->setDescriptionId("pumpkinStem");//->sendTileData();
fenceGate = (new FenceGateTile(107, 4))->init()->setDestroyTime(2.0f)->setExplodeable(5)->setSoundType(SOUND_WOOD)->setCategory(ItemCategory::Structures)->setDescriptionId("fenceGate");//->sendTileData();
stairs_brick = (new StairTile(108, Tile::redBrick))->init()->setCategory(ItemCategory::Structures)->setDescriptionId("stairsBrick");//->sendTileData();
stairs_stoneBrickSmooth = (new StairTile(109, Tile::stoneBrickSmooth))->init()->setCategory(ItemCategory::Structures)->setDescriptionId("stairsStoneBrickSmooth");//->sendTileData();
netherBrick = (new Tile(112, 0 + 14 * 16, Material::stone))->init()->setDestroyTime(2.0f)->setExplodeable(10)->setSoundType(SOUND_STONE)->setCategory(ItemCategory::Structures)->setDescriptionId("netherBrick");
stairs_netherBricks = (new StairTile(114, Tile::netherBrick))->init()->setCategory(ItemCategory::Structures)->setDescriptionId("stairsNetherBrick");//->sendTileData();
stairs_sandStone = (new StairTile(128, Tile::sandStone))->init()->setCategory(ItemCategory::Structures)->setDescriptionId("stairsSandStone");//->sendTileData();
quartzBlock = (new QuartzBlockTile(155))->init()->setSoundType(SOUND_STONE)->setDestroyTime(0.8f)->setCategory(ItemCategory::Structures)->setDescriptionId("quartzBlock");
stairs_quartz = (new StairTile(156, Tile::quartzBlock))->init()->setCategory(ItemCategory::Structures)->setDescriptionId("stairsQuartz");//->sendTileData();
//
// Special tiles for Pocket Edition is placed at high IDs
//
stonecutterBench= (new StonecutterTile(245))->init()->setDestroyTime(2.5f)->setSoundType(SOUND_STONE)->setCategory(ItemCategory::Structures)->setDescriptionId("stonecutter");
glowingObsidian = (new ObsidianTile(246, 10 + 16 * 13, true))->init()->setDestroyTime(10.0f)->setLightEmission(14 / 16.0f)->setExplodeable(2000)->setSoundType(SOUND_STONE)->setCategory(ItemCategory::Structures)->setDescriptionId("glowingobsidian");
netherReactor = (new NetherReactor(247, 10 + 14 * 16, Material::metal))->init()->setDestroyTime(3.0f)->setSoundType(SOUND_METAL)->setCategory(ItemCategory::Structures)->setDescriptionId("netherreactor");
info_updateGame1= (new Tile(248, 252, Material::dirt))->init()->setDestroyTime(1.0f)->setSoundType(SOUND_GRAVEL)->setCategory(ItemCategory::Structures)->setDescriptionId("info_update");
info_updateGame2= (new Tile(249, 253, Material::dirt))->init()->setDestroyTime(1.0f)->setSoundType(SOUND_GRAVEL)->setCategory(ItemCategory::Structures)->setDescriptionId("info_update");
grass_carried = (new CarriedTile(253, 3, 12*16 + 12))->init()->setDescriptionId("grass");
leaves_carried = (LeafTile*) (new LeafTile(254, 11 + 14 * 16))->init()->setDestroyTime(0.2f)->setLightBlock(1)->setSoundType(SOUND_GRASS)->setCategory(ItemCategory::Structures)->setDescriptionId("leaves");
info_reserved6 = (new Tile(255, Material::dirt))->init();
//
// Stuff that need to be inited in a specific order (i.e. after the other tiles have been created)
//
fire = (FireTile*) (new FireTile(51, 1 * 16 + 15))->init()->setDestroyTime(0.0f)->setLightEmission(1.0f)->setSoundType(SOUND_WOOD)->setCategory(ItemCategory::Structures)->setDescriptionId("fire");
//
// Special case for certain items since they can have different icons
// @note: Make sure those different items are handled in ItemInHandRenderer::renderItem
//
Item::items[cloth->id] = (new ClothTileItem(cloth->id - 256))->setCategory(ItemCategory::Structures)->setDescriptionId("cloth");
Item::items[treeTrunk->id] = (new AuxDataTileItem(treeTrunk->id - 256, treeTrunk))->setCategory(ItemCategory::Structures)->setDescriptionId("log");
Item::items[stoneBrickSmooth->id] = (new AuxDataTileItem(stoneBrickSmooth->id - 256, stoneBrickSmooth))->setCategory(ItemCategory::Structures)->setDescriptionId("stonebricksmooth");
Item::items[stoneSlabHalf->id] = (new StoneSlabTileItem(stoneSlabHalf->id - 256))->setCategory(ItemCategory::Structures)->setDescriptionId("stoneSlab");
Item::items[sapling->id] = (new SaplingTileItem(sapling->id - 256))->setCategory(ItemCategory::Structures)->setDescriptionId("sapling");
Item::items[leaves->id] = (new LeafTileItem(leaves->id - 256))->setCategory(ItemCategory::Decorations)->setDescriptionId("leaves");
Item::items[sandStone->id] = (new AuxDataTileItem(sandStone->id - 256, sandStone))->setCategory(ItemCategory::Structures)->setDescriptionId("sandStone");
Item::items[quartzBlock->id] = (new AuxDataTileItem(quartzBlock->id - 256, quartzBlock))->setCategory(ItemCategory::Structures)->setDescriptionId("quartzBlock");
for (int i = 0; i < 256; i++) {
if (Tile::tiles[i] != NULL) {
if (Item::items[i] == NULL) {
Item::items[i] = new TileItem(i - 256);
Item::items[i]->category = Tile::tiles[i]->category;
}
// Check for missing category
if (Item::items[i]->category == -1)
LOGE("Error: Missing category for tile %d: %s\n", tiles[i]->id, tiles[i]->getDescriptionId().c_str());
}
}
}
/*static*/
void Tile::teardownTiles() {
for (int i = 0; i < 256; ++i)
if (Tile::tiles[i]) {
delete Tile::tiles[i];
Tile::tiles[i] = NULL;
}
}
int Tile::transformToValidBlockId( int blockId ) {
return transformToValidBlockId(blockId, 0, 0, 0);
}
int Tile::transformToValidBlockId( int blockId, int x, int y, int z ) {
if (blockId != 0 && Tile::tiles[blockId] == NULL)
return (((x + y + z)&1) == 1)? Tile::info_updateGame1->id : Tile::info_updateGame2->id;
return blockId;
}
Tile::Tile(int id, const Material* material)
: id(id),
material(material),
tex(1),
category(-1),
gravity(1.0f),
friction(0.6f),
soundType(&Tile::SOUND_NORMAL),
tmpBB(0,0,0,1,1,1),
xx0(0),yy0(0),zz0(0),
xx1(1),yy1(1),zz1(1)
{
if (Tile::tiles[id]) {
printf("Slot %d is already occupied by %p when adding %p\n", id, &Tile::tiles[id], this);
}
}
Tile::Tile( int id, int tex, const Material* material )
: id(id),
tex(tex),
material(material),
category(-1),
gravity(1.0f),
friction(0.6f),
soundType(&Tile::SOUND_NORMAL),
tmpBB(0,0,0,1,1,1),
xx0(0),yy0(0),zz0(0),
xx1(1),yy1(1),zz1(1)
{
if (Tile::tiles[id]) {
printf("Slot %d is already occupied by %p when adding %p\n", id, &Tile::tiles[id], this);
}
}
//Tile* sendTileData() {
// Tile::sendTileData[id] = true;
// return this;
//}
/*protected*/
Tile* Tile::setLightEmission(float f) {
Tile::lightEmission[id] = (int) (Level::MAX_BRIGHTNESS * f);
return this;
}
/*public static*/
bool Tile::isFaceVisible(Level* level, int x, int y, int z, int f) {
switch (f) {
case Facing::DOWN : y--; break;
case Facing::UP : y++; break;
case Facing::NORTH: z--; break;
case Facing::SOUTH: z++; break;
case Facing::WEST : x--; break;
case Facing::EAST : x++; break;
}
return !level->isSolidRenderTile(x, y, z);
}
/* private */
Tile* Tile::init() {
Tile::tiles[id] = this;
setShape(xx0, yy0, zz0, xx1, yy1, zz1); // @attn
solid[id] = isSolidRender();
lightBlock[id] = isSolidRender() ? 255 : 0;
translucent[id] = !material->blocksLight();
return this;
}
/*public virtual*/
float Tile::getDestroyProgress(Player* player) {
if (destroySpeed < 0) return 0;
if (!player->canDestroy(this)) return 1 / destroySpeed / 100.0f;
return (player->getDestroySpeed(this) / destroySpeed) / 30.0f;
}
/*public virtual*/
HitResult Tile::clip(Level* level, int xt, int yt, int zt, const Vec3& A, const Vec3& B) {
updateShape(level, xt, yt, zt);
//Stopwatch sw;
//sw.start();
Vec3 sub((float)xt, (float)yt, (float)zt);
Vec3 a = A - sub;//a.add((float)-xt, (float)-yt, (float)-zt);
Vec3 b = B - sub;//b.add((float)-xt, (float)-yt, (float)-zt);
Vec3 xh0, xh1, yh0, yh1, zh0, zh1;
bool bxh0 = a.clipX(b, xx0, xh0);
bool bxh1 = a.clipX(b, xx1, xh1);
bool byh0 = a.clipY(b, yy0, yh0);
bool byh1 = a.clipY(b, yy1, yh1);
bool bzh0 = a.clipZ(b, zz0, zh0);
bool bzh1 = a.clipZ(b, zz1, zh1);
//if (!containsX(xh0)) xh0 = NULL;
if (!bxh0 || !containsX(xh0)) bxh0 = false;
if (!bxh1 || !containsX(xh1)) bxh1 = false;
if (!byh0 || !containsY(yh0)) byh0 = false;
if (!byh1 || !containsY(yh1)) byh1 = false;
if (!bzh0 || !containsZ(zh0)) bzh0 = false;
if (!bzh1 || !containsZ(zh1)) bzh1 = false;
Vec3* closest = NULL;
//if (xh0 != NULL && (closest == NULL || a.distanceToSqr(xh0) < a.distanceToSqr(closest))) closest = xh0;
if (bxh0 && (closest == NULL || a.distanceToSqr(xh0) < a.distanceToSqr(*closest))) closest = &xh0;
if (bxh1 && (closest == NULL || a.distanceToSqr(xh1) < a.distanceToSqr(*closest))) closest = &xh1;
if (byh0 && (closest == NULL || a.distanceToSqr(yh0) < a.distanceToSqr(*closest))) closest = &yh0;
if (byh1 && (closest == NULL || a.distanceToSqr(yh1) < a.distanceToSqr(*closest))) closest = &yh1;
if (bzh0 && (closest == NULL || a.distanceToSqr(zh0) < a.distanceToSqr(*closest))) closest = &zh0;
if (bzh1 && (closest == NULL || a.distanceToSqr(zh1) < a.distanceToSqr(*closest))) closest = &zh1;
if (closest == NULL)
return HitResult();
int face = -1;
if (closest == &xh0) face = 4;
if (closest == &xh1) face = 5;
if (closest == &yh0) face = 0;
if (closest == &yh1) face = 1;
if (closest == &zh0) face = 2;
if (closest == &zh1) face = 3;
//sw.stop();
//sw.printEvery(5, ">>> ");
return HitResult(xt, yt, zt, face, closest->add((float)xt, (float)yt, (float)zt));
}
/*virtual*/
void Tile::spawnResources(Level* level, int x, int y, int z, int data, float odds) {
if (level->isClientSide) return;
int count = getResourceCount(&level->random);
for (int i = 0; i < count; i++) {
if (level->random.nextFloat() > odds) continue;
int type = getResource(data, &level->random);
if (type <= 0) continue;
const float s = 0.7f;
float xo = level->random.nextFloat() * s + (1 - s) * 0.5f;
float yo = level->random.nextFloat() * s + (1 - s) * 0.5f;
float zo = level->random.nextFloat() * s + (1 - s) * 0.5f;
ItemEntity* item = new ItemEntity(level, x + xo, y + yo, z + zo, ItemInstance(type, 1, getSpawnResourcesAuxValue(data)));
item->throwTime = 10;
level->addEntity(item);
}
}
void Tile::spawnResources( Level* level, int x, int y, int z, int data )
{
spawnResources(level, x, y, z, data, 1);
}
void Tile::popResource(Level* level, int x, int y, int z, const ItemInstance& itemInstance) {
if (level->isClientSide || level->getLevelData()->getGameType() == GameType::Creative) return;
float s = 0.7f;
float xo = level->random.nextFloat() * s + (1 - s) * 0.5f;
float yo = level->random.nextFloat() * s + (1 - s) * 0.5f;
float zo = level->random.nextFloat() * s + (1 - s) * 0.5f;
ItemEntity* item = new ItemEntity(level, x + xo, y + yo, z + zo, itemInstance);
item->throwTime = 10;
level->addEntity(item);
}
void Tile::destroy( Level* level, int x, int y, int z, int data )
{
}
bool Tile::isCubeShaped()
{
return true;
}
int Tile::getRenderShape()
{
return SHAPE_BLOCK;
}
float Tile::getBrightness( LevelSource* level, int x, int y, int z )
{
return level->getBrightness(x, y, z);
}
bool Tile::shouldRenderFace( LevelSource* level, int x, int y, int z, int face )
{
if (face == 0 && y == -1) return false;
// For fixed size worlds //@todo: external constants rather than magic numbers
if (face == 2 && z == -1) return false;
if (face == 3 && z == 256) return false;
if (face == 4 && x == -1) return false;
if (face == 5 && x == 256) return false;
// Common
if (face == 0 && yy0 > 0) return true;
if (face == 1 && yy1 < 1) return true;
if (face == 2 && zz0 > 0) return true;
if (face == 3 && zz1 < 1) return true;
if (face == 4 && xx0 > 0) return true;
if (face == 5 && xx1 < 1) return true;
Tile* t = Tile::tiles[level->getTile(x, y, z)];
if (!t) return true;
if (face == 1 && t->id == topSnow->id) return false;
return !t->isSolidRender();
//return (!level->isSolidRenderTile(x, y, z));
}
int Tile::getTexture( LevelSource* level, int x, int y, int z, int face )
{
return getTexture(face, level->getData(x, y, z));
}
int Tile::getTexture( int face, int data )
{
return getTexture(face);
}
int Tile::getTexture( int face )
{
return tex;
}
void Tile::addAABBs( Level* level, int x, int y, int z, const AABB* box, std::vector<AABB>& boxes )
{
AABB* aabb = getAABB(level, x, y, z);
if (aabb != NULL && box->intersects(*aabb)) {
boxes.push_back(*aabb);
}
}
AABB* Tile::getAABB( Level* level, int x, int y, int z )
{
tmpBB.x0 = x + xx0;
tmpBB.y0 = y + yy0;
tmpBB.z0 = z + zz0;
tmpBB.x1 = x + xx1;
tmpBB.y1 = y + yy1;
tmpBB.z1 = z + zz1;
return &tmpBB;
}
bool Tile::isSolidRender()
{
return true;
}
bool Tile::mayPick( int data, bool liquid )
{
return mayPick();
}
bool Tile::mayPick()
{
return true;
}
int Tile::getTickDelay()
{
return 10;
}
int Tile::getResourceCount( Random* random )
{
return 1;
}
int Tile::getResource( int data, Random* random )
{
return id;
}
float Tile::getExplosionResistance( Entity* source )
{
return explosionResistance / 5.0f;
}
int Tile::getRenderLayer()
{
return Tile::RENDERLAYER_OPAQUE;
}
bool Tile::use( Level* level, int x, int y, int z, Player* player )
{
return false;
}
bool Tile::spawnBurnResources( Level* level, float x, float y, float z )
{
return false;
}
int Tile::getColor( LevelSource* level, int x, int y, int z )
{
return 0xffffff;
}
bool Tile::getSignal( LevelSource* level, int x, int y, int z )
{
return false;
}
bool Tile::getSignal( LevelSource* level, int x, int y, int z, int dir )
{
return false;
}
bool Tile::isSignalSource()
{
return false;
}
bool Tile::getDirectSignal( Level* level, int x, int y, int z, int dir )
{
return false;
}
void Tile::playerDestroy( Level* level, Player* player, int x, int y, int z, int data )
{
//player.awardStat(Stats.blockMined[id], 1);
spawnResources(level, x, y, z, data);
}
bool Tile::canSurvive( Level* level, int x, int y, int z )
{
return true;
}
Tile* Tile::setDescriptionId( const std::string& id )
{
descriptionId = TILE_DESCRIPTION_PREFIX + id;
return this;
}
std::string Tile::getName() const
{
return I18n::get(getDescriptionId() + ".name");
}
std::string Tile::getDescriptionId() const
{
return descriptionId;
}
Tile* Tile::setSoundType( const SoundType& soundType )
{
this->soundType = &soundType;
return this;
}
Tile* Tile::setLightBlock( int i )
{
lightBlock[id] = i;
return this;
}
Tile* Tile::setExplodeable( float explosionResistance )
{
this->explosionResistance = explosionResistance * 3;
return this;
}
Tile* Tile::setDestroyTime( float destroySpeed )
{
this->destroySpeed = destroySpeed;
if (explosionResistance < destroySpeed * 5) explosionResistance = destroySpeed * 5;
return this;
}
void Tile::setTicking( bool tick )
{
shouldTick[id] = tick;
}
int Tile::getSpawnResourcesAuxValue( int data )
{
return 0;
}
bool Tile::containsX( const Vec3& v )
{
return v.y >= yy0 && v.y <= yy1 && v.z >= zz0 && v.z <= zz1;
}
bool Tile::containsY( const Vec3& v )
{
return v.x >= xx0 && v.x <= xx1 && v.z >= zz0 && v.z <= zz1;
}
bool Tile::containsZ( const Vec3& v )
{
return v.x >= xx0 && v.x <= xx1 && v.y >= yy0 && v.y <= yy1;
}
/*public*/
AABB Tile::getTileAABB(Level* level, int x, int y, int z) {
return AABB(x + xx0, y + yy0, z + zz0, x + xx1, y + yy1, z + zz1);
}
/*public*/
void Tile::setShape(float x0, float y0, float z0, float x1, float y1, float z1) {
this->xx0 = x0;
this->yy0 = y0;
this->zz0 = z0;
this->xx1 = x1;
this->yy1 = y1;
this->zz1 = z1;
}
/*public*/
bool Tile::mayPlace(Level* level, int x, int y, int z, unsigned char face) {
return mayPlace(level, x, y, z);
}
bool Tile::mayPlace( Level* level, int x, int y, int z ) {
int t = level->getTile(x, y, z);
return t == 0 || Tile::tiles[t]->material->isReplaceable();
}
Tile* Tile::setCategory(int category) {
this->category = category;
return this;
}

389
src/world/level/tile/Tile.h Executable file
View File

@@ -0,0 +1,389 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__Tile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__Tile_H__
//package net.minecraft.world.level.tile;
#include <string>
#include "../../phys/AABB.h"
class Entity;
class Mob;
class Player;
class Level;
class LevelSource;
class Material;
class Random;
class ItemInstance;
class Bush;
class GrassTile;
class LeafTile;
class FireTile;
// @Note: Got a memory leak in initTiles? You probably didn't call
// Tile::init after constructing the tile!
class Tile
{
static const std::string TILE_DESCRIPTION_PREFIX;
public:
class SoundType
{
public:
//const std::string name;
const float volume;
const float pitch;
const std::string breakSound;
const std::string stepSound;
SoundType(const std::string& name, float volume, float pitch)
: volume(volume),
pitch(pitch),
breakSound("step." + name),
stepSound("step." + name)
{}
SoundType(const std::string& name, const std::string& breakSound, float volume, float pitch)
: volume(volume),
pitch(pitch),
stepSound("step." + name),
breakSound(breakSound)
{}
float getVolume() const {
return volume;
}
float getPitch() const {
return pitch;
}
const std::string& getBreakSound() const {
return breakSound;
}
const std::string& getStepSound() const {
return stepSound;
}
};
static const SoundType SOUND_NORMAL;
static const SoundType SOUND_WOOD;
static const SoundType SOUND_GRAVEL;
static const SoundType SOUND_GRASS;
static const SoundType SOUND_STONE;
static const SoundType SOUND_METAL;
static const SoundType SOUND_GLASS;
static const SoundType SOUND_CLOTH;
static const SoundType SOUND_SAND;
static const SoundType SOUND_SILENT;
static const int SHAPE_INVISIBLE = -1;
static const int SHAPE_BLOCK = 0;
static const int SHAPE_CROSS_TEXTURE = 1;
static const int SHAPE_TORCH = 2;
static const int SHAPE_FIRE = 3;
static const int SHAPE_WATER = 4;
static const int SHAPE_RED_DUST = 5;
static const int SHAPE_ROWS = 6;
static const int SHAPE_DOOR = 7;
static const int SHAPE_LADDER = 8;
static const int SHAPE_RAIL = 9;
static const int SHAPE_STAIRS = 10;
static const int SHAPE_FENCE = 11;
static const int SHAPE_LEVER = 12;
static const int SHAPE_CACTUS = 13;
static const int SHAPE_BED = 14;
static const int SHAPE_DIODE = 15;
static const int SHAPE_IRON_FENCE = 18;
static const int SHAPE_STEM = 19;
static const int SHAPE_FENCE_GATE = 21;
static const int SHAPE_ENTITYTILE_ANIMATED = 22;
static const int NUM_BLOCK_TYPES = 256;
static Tile* tiles[NUM_BLOCK_TYPES];
static bool sendTileData[NUM_BLOCK_TYPES];
static bool shouldTick[NUM_BLOCK_TYPES];
static bool solid[NUM_BLOCK_TYPES];
static bool isEntityTile[NUM_BLOCK_TYPES];
static int lightBlock[NUM_BLOCK_TYPES];
static bool translucent[NUM_BLOCK_TYPES];
static int lightEmission[NUM_BLOCK_TYPES];
static Tile* rock;
static Tile* grass;
static Tile* dirt;
static Tile* stoneBrick;
static Tile* wood;
static Tile* sapling;
static Tile* unbreakable;
static Tile* water;
static Tile* calmWater;
static Tile* lava;
static Tile* calmLava;
static Tile* sand;
static Tile* gravel;
static Tile* goldOre;
static Tile* ironOre;
static Tile* coalOre;
static Tile* treeTrunk;
static LeafTile* leaves;
static Tile* sponge;
static Tile* web;
static Tile* glass;
static Tile* thinGlass;
static Tile* lapisOre;
static Tile* lapisBlock;
static Tile* dispenser;
static Tile* sandStone;
static Tile* musicBlock;
static Tile* bed;
static Tile* unused_27;
static Tile* unused_28;
static Tile* unused_29;
static Tile* unused_30;
static Tile* tallgrass;
static Tile* unused_32;
static Tile* unused_33;
static Tile* unused_34;
static Tile* unused_36;
static Tile* cloth;
static Tile* flower;
static Tile* rose;
static Tile* mushroom1;
static Tile* mushroom2;
static Tile* goldBlock;
static Tile* ironBlock;
static Tile* stoneSlab;
static Tile* stoneSlabHalf;
static Tile* redBrick;
static Tile* tnt;
static Tile* bookshelf;
static Tile* mossStone;
static Tile* obsidian;
static Tile* torch;
static FireTile* fire;
static Tile* mobSpawner;
static Tile* stairs_wood;
static Tile* chest;
static Tile* redStoneDust;
static Tile* emeraldOre;
static Tile* emeraldBlock;
static Tile* workBench;
static Tile* stonecutterBench;
static Tile* crops;
static Tile* farmland;
static Tile* furnace;
static Tile* furnace_lit;
static Tile* sign;
static Tile* door_wood;
static Tile* ladder;
static Tile* rail;
static Tile* stairs_stone;
static Tile* wallSign;
static Tile* lever;
static Tile* pressurePlate_stone;
static Tile* door_iron;
static Tile* pressurePlate_wood;
static Tile* redStoneOre;
static Tile* redStoneOre_lit;
static Tile* notGate_off;
static Tile* notGate_on;
static Tile* button;
static Tile* topSnow;
static Tile* ice;
static Tile* snow;
static Tile* cactus;
static Tile* clay;
static Tile* reeds;
static Tile* recordPlayer;
static Tile* fence;
static Tile* stairs_brick;
static Tile* fenceGate;
static Tile* pumpkin;
static Tile* hellRock;
static Tile* hellSand;
static Tile* lightGem;
static Tile* portalTile;
static Tile* litPumpkin;
static Tile* cake;
static Tile* diode_off;
static Tile* diode_on;
static Tile* trapdoor;
static Tile* stoneBrickSmooth;
static Tile* grass_carried;
static LeafTile* leaves_carried;
static Tile* melon;
static Tile* melonStem;
static Tile* netherReactor;
static Tile* glowingObsidian;
static Tile* stairs_stoneBrickSmooth;
static Tile* netherBrick;
static Tile* netherrack;
static Tile* stairs_netherBricks;
static Tile* stairs_sandStone;
static Tile* quartzBlock;
static Tile* stairs_quartz;
// invisible bedrock is used to block off empty chunks (i.e. prevent player movement)
static Tile* invisible_bedrock;
static Tile* info_updateGame1;
static Tile* info_updateGame2;
static Tile* info_reserved6;
static void initTiles();
static void teardownTiles();
static int transformToValidBlockId(int blockId);
static int transformToValidBlockId(int blockId, int x, int y, int z);
Tile(int id, const Material* material);
Tile(int id, int tex, const Material* material);
virtual ~Tile() {}
virtual bool isCubeShaped();
virtual int getRenderShape();
virtual void setShape(float x0, float y0, float z0, float x1, float y1, float z1);
virtual void updateShape(LevelSource* level, int x, int y, int z) {}
virtual void updateDefaultShape() {}
virtual void addLights(Level* level, int x, int y, int z) {}
virtual float getBrightness(LevelSource* level, int x, int y, int z);
static bool isFaceVisible(Level* level, int x, int y, int z, int f);
virtual bool shouldRenderFace(LevelSource* level, int x, int y, int z, int face);
virtual int getTexture(int face);
virtual int getTexture(int face, int data);
virtual int getTexture(LevelSource* level, int x, int y, int z, int face);
// @attn Not threadsafe (ADDON: nor safe to _save_ this returned AABB*.
// Make a copy if you need to save this AABB (rather then using as a temp)
virtual AABB* getAABB(Level* level, int x, int y, int z);
virtual void addAABBs(Level* level, int x, int y, int z, const AABB* box, std::vector<AABB>& boxes);
virtual AABB getTileAABB(Level* level, int x, int y, int z);
virtual bool isSolidRender();
virtual bool mayPick();
virtual bool mayPick(int data, bool liquid);
virtual bool mayPlace(Level* level, int x, int y, int z, unsigned char face);
virtual bool mayPlace(Level* level, int x, int y, int z);
virtual int getTickDelay();
virtual void tick(Level* level, int x, int y, int z, Random* random) {}
virtual void animateTick(Level* level, int x, int y, int z, Random* random) {}
virtual void destroy(Level* level, int x, int y, int z, int data);
virtual void neighborChanged(Level* level, int x, int y, int z, int type) {}
virtual void onPlace(Level* level, int x, int y, int z) {}
virtual void onRemove(Level* level, int x, int y, int z) {}
virtual int getResource(int data, Random* random);
virtual int getResourceCount(Random* random);
virtual float getDestroyProgress(Player* player);
virtual void spawnResources(Level* level, int x, int y, int z, int data);
virtual void spawnResources(Level* level, int x, int y, int z, int data, float odds);
virtual bool spawnBurnResources(Level* level, float x, float y, float z);
void popResource(Level* level, int x, int y, int z, const ItemInstance& itemInstance);
virtual float getExplosionResistance(Entity* source);
virtual HitResult clip(Level* level, int xt, int yt, int zt, const Vec3& a, const Vec3& b);
virtual void wasExploded(Level* level, int x, int y, int z) {}
virtual int getRenderLayer();
virtual bool use(Level* level, int x, int y, int z, Player* player);
virtual void stepOn(Level* level, int x, int y, int z, Entity* entity) {}
virtual void fallOn( Level* level, int x, int y, int z, Entity* entity, float fallDistance ) {}
virtual int getPlacedOnFaceDataValue(Level* level, int x, int y, int z, int face, float clickX, float clickY, float clickZ, int itemValue) { return itemValue; }
virtual void setPlacedBy(Level* level, int x, int y, int z, Mob* by) {}
virtual void prepareRender(Level* level, int x, int y, int z) {}
virtual void attack(Level* level, int x, int y, int z, Player* player) {}
virtual void handleEntityInside(Level* level, int x, int y, int z, Entity* e, Vec3& current) {}
virtual int getColor(LevelSource* level, int x, int y, int z);
virtual bool isSignalSource();
virtual bool getSignal(LevelSource* level, int x, int y, int z);
virtual bool getSignal(LevelSource* level, int x, int y, int z, int dir);
virtual bool getDirectSignal(Level* level, int x, int y, int z, int dir);
virtual void entityInside(Level* level, int x, int y, int z, Entity* entity) {}
virtual void playerDestroy(Level* level, Player* player, int x, int y, int z, int data);
virtual bool canSurvive(Level* level, int x, int y, int z);
virtual std::string getName() const;
virtual std::string getDescriptionId() const;
virtual Tile* setDescriptionId(const std::string& id);
virtual void triggerEvent(Level* level, int x, int y, int z, int b0, int b1) {}
protected:
virtual Tile* setSoundType(const SoundType& soundType);
virtual Tile* setLightBlock(int i);
virtual Tile* setLightEmission(float f);
virtual Tile* setExplodeable(float explosionResistance);
virtual Tile* setDestroyTime(float destroySpeed);
virtual void setTicking(bool tick);
/*** Returns the item instance's auxValue when a TileItem is spawned from this Tile. */
virtual int getSpawnResourcesAuxValue(int data);
private:
Tile* init();
Tile* setCategory(int category);
bool containsX(const Vec3& v);
bool containsY(const Vec3& v);
bool containsZ(const Vec3& v);
public:
int tex;
const int id;
float xx0, yy0, zz0, xx1, yy1, zz1;
const SoundType* soundType;
float gravity;
const Material* const material;
float friction;
//protected:
float destroySpeed;
float explosionResistance;
int category;
protected:
AABB tmpBB;
static const int RENDERLAYER_OPAQUE;
static const int RENDERLAYER_ALPHATEST;
static const int RENDERLAYER_BLEND;
private:
std::string descriptionId;
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__Tile_H__*/

View File

@@ -0,0 +1,62 @@
#ifndef TILE_INCLUDE_H__
#define TILE_INCLUDE_H__
#include "Tile.h"
#include "BedTile.h"
#include "BookshelfTile.h"
#include "Bush.h"
#include "CactusTile.h"
#include "CarriedTile.h"
#include "ClayTile.h"
#include "ChestTile.h"
#include "ClothTile.h"
#include "CropTile.h"
#include "DirtTile.h"
#include "DoorTile.h"
#include "FarmTile.h"
#include "FenceTile.h"
#include "FenceGateTile.h"
#include "FireTile.h"
#include "FurnaceTile.h"
#include "GlassTile.h"
#include "GrassTile.h"
#include "GravelTile.h"
#include "HeavyTile.h"
#include "IceTile.h"
#include "InvisibleTile.h"
#include "LadderTile.h"
#include "LeafTile.h"
#include "LightGemTile.h"
#include "LiquidTileDynamic.h"
#include "LiquidTileStatic.h"
#include "MelonTile.h"
#include "MultiTextureTile.h"
#include "Mushroom.h"
#include "ObsidianTile.h"
#include "OreTile.h"
#include "MetalTile.h"
#include "NetherReactor.h"
#include "QuartzBlockTile.h"
#include "RedStoneOreTile.h"
#include "ReedTile.h"
#include "SandStoneTile.h"
#include "Sapling.h"
#include "SignTile.h"
#include "SnowTile.h"
#include "StairTile.h"
#include "StemTile.h"
#include "StonecutterTile.h"
#include "StoneTile.h"
#include "StoneSlabTile.h"
#include "TallGrass.h"
#include "ThinFenceTile.h"
#include "TopSnowTile.h"
#include "TorchTile.h"
#include "TrapDoorTile.h"
#include "TreeTile.h"
#include "TntTile.h"
#include "WebTile.h"
#include "WorkbenchTile.h"
#endif /* TILE_INCLUDE_H__ */

69
src/world/level/tile/TntTile.h Executable file
View File

@@ -0,0 +1,69 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__TntTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__TntTile_H__
//package net.minecraft.world.level.tile;
#include "../../../util/Random.h"
#include "../../entity/item/PrimedTnt.h"
#include "../Level.h"
#include "../material/Material.h"
class TntTile: public Tile
{
typedef Tile super;
static const int EXPLODE_BIT = 1;
public:
TntTile(int id, int tex)
: super(id, tex, Material::explosive)
{
}
int getTexture(int face) {
if (face == 0) return tex + 2;
if (face == 1) return tex + 1;
return tex;
}
void neighborChanged(Level* level, int x, int y, int z, int type) {
if (type > 0 && Tile::tiles[type]->isSignalSource()) {
if (level->hasNeighborSignal(x, y, z)) {
destroy(level, x, y, z, EXPLODE_BIT);
level->setTile(x, y, z, 0);
}
}
}
int getResourceCount(Random* random) {
return 1;
}
void wasExploded(Level* level, int x, int y, int z) {
PrimedTnt* primed = new PrimedTnt(level, x + 0.5f, y + 0.5f, z + 0.5f);
primed->life = level->random.nextInt(primed->life / 4) + primed->life / 8;
level->addEntity(primed);
}
void destroy(Level* level, int x, int y, int z, int data) {
if (level->isClientSide) return;
if ((data & EXPLODE_BIT) == 1) {
PrimedTnt* tnt = new PrimedTnt(level, x + 0.5f, y + 0.5f, z + 0.5f);
level->addEntity(tnt);
level->playSound(tnt, "random.fuse", 1, 1.0f);
}
}
bool use(Level* level, int x, int y, int z, Player* player) {
ItemInstance* carried = player->getSelectedItem();
if (carried && carried->id == Item::flintAndSteel->id) {
carried->hurt(1);
destroy(level, x, y, z, EXPLODE_BIT);
level->setTile(x, y, z, 0);
return true;
}
return super::use(level, x, y, z, player);
}
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__TntTile_H__*/

View File

@@ -0,0 +1,97 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__TopSnowTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__TopSnowTile_H__
//package net.minecraft.world.level->tile;
#include "Tile.h"
#include "../Level.h"
#include "../material/Material.h"
#include "../../entity/item/ItemEntity.h"
#include "../../item/ItemInstance.h"
#include "../../../util/Random.h"
class TopSnowTile: public Tile
{
public:
TopSnowTile(int id, int tex)
: Tile(id, tex, Material::topSnow)
{
setShape(0, 0, 0, 1, 1 / 8.0f, 1);
setTicking(true);
}
AABB* getAABB(Level* level, int x, int y, int z) {
return NULL;
}
bool blocksLight() {
return false;
}
bool isSolidRender() {
return false;
}
bool isCubeShaped() {
return false;
}
bool mayPlace(Level* level, int x, int y, int z) {
int t = level->getTile(x, y - 1, z);
if (t == 0 || !Tile::tiles[t]->isSolidRender()) return false;
return level->getMaterial(x, y - 1, z)->blocksMotion();
}
void neighborChanged(Level* level, int x, int y, int z, int type) {
checkCanSurvive(level, x, y, z);
}
void playerDestroy(Level* level, Player* player, int x, int y, int z, int data) {
if (level->isClientSide)
return;
int type = Item::snowBall->id;
float s = 0.7f;
float xo = level->random.nextFloat() * s + (1 - s) * 0.5f;
float yo = level->random.nextFloat() * s + (1 - s) * 0.5f;
float zo = level->random.nextFloat() * s + (1 - s) * 0.5f;
ItemEntity* item = new ItemEntity(level, x + xo, y + yo, z + zo, ItemInstance(type, 1, 0));
item->throwTime = 10;
level->addEntity(item);
level->setTile(x, y, z, 0);
}
int getResource(int data, Random* random) {
return Item::snowBall->id;
}
int getResourceCount(Random* random) {
return 0;
}
void tick(Level* level, int x, int y, int z, Random* random) {
if (level->getBrightness(LightLayer::Block, x, y, z) > 11) {
this->spawnResources(level, x, y, z, level->getData(x, y, z));
level->setTile(x, y, z, 0);
}
}
bool shouldRenderFace(LevelSource* level, int x, int y, int z, int face) {
const Material* m = level->getMaterial(x, y, z);
if (face == 1) return true;
if (m == this->material) return false;
return Tile::shouldRenderFace(level, x, y, z, face);
}
private:
bool checkCanSurvive(Level* level, int x, int y, int z) {
if (!mayPlace(level, x, y, z)) {
this->spawnResources(level, x, y, z, level->getData(x, y, z));
level->setTile(x, y, z, 0);
return false;
}
return true;
}
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__TopSnowTile_H__*/

177
src/world/level/tile/TorchTile.h Executable file
View File

@@ -0,0 +1,177 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__TorchTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__TorchTile_H__
//package net.minecraft.world.level->tile;
#include "../../../util/Random.h"
#include "../material/Material.h"
#include "../Level.h"
#include "Tile.h"
class TorchTile: public Tile
{
typedef Tile super;
public:
TorchTile(int id, int tex)
: super(id, tex, Material::decoration)
{
this->setTicking(true);
}
AABB* getAABB(Level* level, int x, int y, int z) {
return NULL;
}
bool isSolidRender() {
return false;
}
bool isCubeShaped() {
return false;
}
int getRenderShape() {
return Tile::SHAPE_TORCH;
}
int getRenderLayer() {
return Tile::RENDERLAYER_ALPHATEST;
}
bool mayPlace(Level* level, int x, int y, int z) {
if (level->isSolidBlockingTile(x - 1, y, z)) {
return true;
} else if (level->isSolidBlockingTile(x + 1, y, z)) {
return true;
} else if (level->isSolidBlockingTile(x, y, z - 1)) {
return true;
} else if (level->isSolidBlockingTile(x, y, z + 1)) {
return true;
} else if (isConnection(level, x, y - 1, z)) {
return true;
}
return false;
}
int getPlacedOnFaceDataValue(Level* level, int x, int y, int z, int face, float clickX, float clickY, float clickZ, int itemValue)
{
int dir = itemValue;
if (face == 1 && isConnection(level, x, y - 1, z)) dir = 5;
if (face == 2 && level->isSolidBlockingTile(x, y, z + 1)) dir = 4;
if (face == 3 && level->isSolidBlockingTile(x, y, z - 1)) dir = 3;
if (face == 4 && level->isSolidBlockingTile(x + 1, y, z)) dir = 2;
if (face == 5 && level->isSolidBlockingTile(x - 1, y, z)) dir = 1;
return dir;
}
void tick(Level* level, int x, int y, int z, Random* random) {
super::tick(level, x, y, z, random);
if (level->getData(x, y, z) == 0) onPlace(level, x, y, z);
}
void onPlace(Level* level, int x, int y, int z) {
if (level->isSolidBlockingTile(x - 1, y, z)) {
level->setData(x, y, z, 1);
} else if (level->isSolidBlockingTile(x + 1, y, z)) {
level->setData(x, y, z, 2);
} else if (level->isSolidBlockingTile(x, y, z - 1)) {
level->setData(x, y, z, 3);
} else if (level->isSolidBlockingTile(x, y, z + 1)) {
level->setData(x, y, z, 4);
} else if (isConnection(level, x, y - 1, z)) {
level->setData(x, y, z, 5);
}
checkCanSurvive(level, x, y, z);
}
void neighborChanged(Level* level, int x, int y, int z, int type) {
if (checkCanSurvive(level, x, y, z)) {
int dir = level->getData(x, y, z);
bool replace = false;
if (!level->isSolidBlockingTile(x - 1, y, z) && dir == 1) replace = true;
if (!level->isSolidBlockingTile(x + 1, y, z) && dir == 2) replace = true;
if (!level->isSolidBlockingTile(x, y, z - 1) && dir == 3) replace = true;
if (!level->isSolidBlockingTile(x, y, z + 1) && dir == 4) replace = true;
if (!isConnection(level, x, y - 1, z) && dir == 5) replace = true;
if (replace) {
this->spawnResources(level, x, y, z, level->getData(x, y, z));
level->setTile(x, y, z, 0);
}
}
}
HitResult clip(Level* level, int x, int y, int z, const Vec3& a, const Vec3& b) {
int dir = level->getData(x, y, z) & 7;
float r = 0.15f;
if (dir == 1) {
setShape(0, 0.2f, 0.5f - r, r * 2, 0.8f, 0.5f + r);
} else if (dir == 2) {
setShape(1 - r * 2, 0.2f, 0.5f - r, 1, 0.8f, 0.5f + r);
} else if (dir == 3) {
setShape(0.5f - r, 0.2f, 0, 0.5f + r, 0.8f, r * 2);
} else if (dir == 4) {
setShape(0.5f - r, 0.2f, 1 - r * 2, 0.5f + r, 0.8f, 1);
} else {
r = 0.1f;
setShape(0.5f - r, 0.0f, 0.5f - r, 0.5f + r, 0.6f, 0.5f + r);
}
return super::clip(level, x, y, z, a, b);
}
void animateTick(Level* level, int xt, int yt, int zt, Random* random) {
int dir = level->getData(xt, yt, zt);
float x = xt + 0.5f;
float y = yt + 0.7f;
float z = zt + 0.5f;
float h = 0.22f;
float r = 0.27f;
if (dir == 1) {
level->addParticle(PARTICLETYPE(smoke), x - r, y + h, z, 0, 0, 0);
level->addParticle(PARTICLETYPE(flame), x - r, y + h, z, 0, 0, 0);
} else if (dir == 2) {
level->addParticle(PARTICLETYPE(smoke), x + r, y + h, z, 0, 0, 0);
level->addParticle(PARTICLETYPE(flame), x + r, y + h, z, 0, 0, 0);
} else if (dir == 3) {
level->addParticle(PARTICLETYPE(smoke), x, y + h, z - r, 0, 0, 0);
level->addParticle(PARTICLETYPE(flame), x, y + h, z - r, 0, 0, 0);
} else if (dir == 4) {
level->addParticle(PARTICLETYPE(smoke), x, y + h, z + r, 0, 0, 0);
level->addParticle(PARTICLETYPE(flame), x, y + h, z + r, 0, 0, 0);
} else {
level->addParticle(PARTICLETYPE(smoke), x, y, z, 0, 0, 0);
level->addParticle(PARTICLETYPE(flame), x, y, z, 0, 0, 0);
}
}
private:
bool isConnection(Level* level, int x, int y, int z) {
if (level->isSolidBlockingTile(x, y, z)) {
return true;
}
int tile = level->getTile(x, y, z);
if (tile == Tile::fence->id || tile == Tile::glass->id /*|| tile == Tile::cobbleWall->id*/) {
return true;
}
return false;
}
bool checkCanSurvive(Level* level, int x, int y, int z) {
if (!mayPlace(level, x, y, z)) {
if (level->getTile(x, y, z) == id) {
spawnResources(level, x, y, z, level->getData(x, y, z));
level->setTile(x, y, z, 0);
}
return false;
}
return true;
}
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__TorchTile_H__*/

View File

@@ -0,0 +1,40 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__TransparentTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__TransparentTile_H__
//package net.minecraft.world.level.tile;
#include "Tile.h"
#include "../LevelSource.h"
class Material;
class TransparentTile: public Tile
{
public:
/*protected*/
bool allowSame;
/*protected*/
TransparentTile(int id, int tex, const Material* material, bool allowSame)
: Tile(id, tex, material)
{
this->allowSame = allowSame;
}
bool isSolidRender()
{
return false;
}
bool shouldRenderFace(LevelSource* level, int x, int y, int z, int face)
{
int id = level->getTile(x, y, z);
if (!allowSame && id == this->id) return false;
return Tile::shouldRenderFace(level, x, y, z, face);
}
bool blocksLight() {
return false;
}
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__TransparentTile_H__*/

View File

@@ -0,0 +1,154 @@
#include "TrapDoorTile.h"
#include "../material/Material.h"
#include "../Level.h"
#include "LevelEvent.h"
TrapDoorTile::TrapDoorTile( int id, const Material* material ) : super(id, material) {
tex = 4 + 5 * 16;
if(material == Material::metal) tex++;
float r = 0.5f;
float h = 1.0f;
super::setShape(0.5f - r, 0, 0.5f - r, 0.5f + r, h, 0.5f + r);
}
bool TrapDoorTile::blocksLight() {
return false;
}
bool TrapDoorTile::isSolidRender() {
return false;
}
bool TrapDoorTile::isCubeShaped() {
return false;
}
int TrapDoorTile::getRenderShape() {
return Tile::SHAPE_BLOCK;
}
int TrapDoorTile::getRenderLayer() {
return Tile::RENDERLAYER_ALPHATEST;
}
AABB TrapDoorTile::getTileAABB( Level* level, int x, int y, int z ) {
updateShape(level, x, y, z);
return super::getTileAABB(level, x, y, z);
}
AABB* TrapDoorTile::getAABB( Level* level, int x, int y, int z ) {
updateShape(level, x, y, z);
return super::getAABB(level, x, y, z);
}
void TrapDoorTile::updateShape( LevelSource* level, int x, int y, int z ) {
setShape(level->getData(x, y, z));
}
void TrapDoorTile::updateDefaultShape() {
float r = 3 / 16.0f;
super::setShape(0, 0.5f - r / 2, 0, 1, 0.5f + r / 2, 1);
}
void TrapDoorTile::setShape( int data ) {
float r = 3 / 16.0f;
super::setShape(0, 0, 0, 1, r, 1);
if (isOpen(data)) {
if ((data & 3) == 0) super::setShape(0, 0, 1 - r, 1, 1, 1);
if ((data & 3) == 1) super::setShape(0, 0, 0, 1, 1, r);
if ((data & 3) == 2) super::setShape(1 - r, 0, 0, 1, 1, 1);
if ((data & 3) == 3) super::setShape(0, 0, 0, r, 1, 1);
}
}
void TrapDoorTile::attack( Level* level, int x, int y, int z, Player* player ) {
use(level, x, y, z, player);
}
bool TrapDoorTile::use( Level* level, int x, int y, int z, Player* player ) {
if (material == Material::metal) return true;
int dir = level->getData(x, y, z);
level->setData(x, y, z, dir ^ 4);
level->levelEvent(player, LevelEvent::SOUND_OPEN_DOOR, x, y, z, 0);
return true;
}
void TrapDoorTile::setOpen( Level* level, int x, int y, int z, bool shouldOpen ) {
int dir = level->getData(x, y, z);
bool wasOpen = (dir & 4) > 0;
if (wasOpen == shouldOpen) return;
level->setData(x, y, z, dir ^ 4);
level->levelEvent(NULL, LevelEvent::SOUND_OPEN_DOOR, x, y, z, 0);
}
void TrapDoorTile::neighborChanged( Level* level, int x, int y, int z, int type ) {
if (level->isClientSide) return;
int data = level->getData(x, y, z);
int xt = x;
int zt = z;
if ((data & 3) == 0) zt++;
if ((data & 3) == 1) zt--;
if ((data & 3) == 2) xt++;
if ((data & 3) == 3) xt--;
if (!attachesTo(level->getTile(xt, y, zt))) {
level->setTile(x, y, z, 0);
popResource(level, x, y, z, ItemInstance(Tile::trapdoor));
}
bool signal = level->hasNeighborSignal(x, y, z);
if (signal || ((type > 0 && Tile::tiles[type]->isSignalSource()) || type == 0)) {
setOpen(level, x, y, z, signal);
}
}
HitResult TrapDoorTile::clip( Level* level, int xt, int yt, int zt, const Vec3& a, const Vec3& b ) {
updateShape(level, xt, yt, zt);
return super::clip(level, xt, yt, zt, a, b);
}
int TrapDoorTile::getDir( int dir ) {
if ((dir & 4) == 0) {
return ((dir - 1) & 3);
} else {
return (dir & 3);
}
}
int TrapDoorTile::getPlacedOnFaceDataValue(Level* level, int x, int y, int z, int face, float clickX, float clickY, float clickZ, int itemValue) {
int dir = 0;
if (face == 2) dir = 0;
if (face == 3) dir = 1;
if (face == 4) dir = 2;
if (face == 5) dir = 3;
return dir;
}
bool TrapDoorTile::mayPlace( Level* level, int x, int y, int z, unsigned char face) {
if (face == 0) return false;
if (face == 1) return false;
if (face == 2) z++;
if (face == 3) z--;
if (face == 4) x++;
if (face == 5) x--;
return attachesTo(level->getTile(x, y, z));
}
bool TrapDoorTile::isOpen( int data ) {
return (data & 4) != 0;
}
bool TrapDoorTile::attachesTo( int id ) {
if (id <= 0) {
return false;
}
Tile* tile = Tile::tiles[id];
bool isStair = tile != NULL && tile->getRenderShape() == Tile::SHAPE_STAIRS;
return tile != NULL && (tile->material->isSolidBlocking() && tile->isCubeShaped()) || tile == Tile::lightGem || tile == Tile::stoneSlabHalf || isStair;
}

View File

@@ -0,0 +1,36 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__TrapDoorTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__TrapDoorTile_H__
#include "Tile.h"
class TrapDoorTile : public Tile {
typedef Tile super;
public:
TrapDoorTile(int id, const Material* material);
bool blocksLight();
bool isSolidRender();
bool isCubeShaped();
int getRenderLayer();
//@Override
// public boolean isPathfindable(LevelSource level, int x, int y, int z) {
// return !isOpen(level.getData(x, y, z));
//}
int getRenderShape();
AABB getTileAABB(Level* level, int x, int y, int z);
AABB* getAABB(Level* level, int x, int y, int z);
void updateShape(LevelSource* level, int x, int y, int z);
void updateDefaultShape();
void setShape(int data);
void attack(Level* level, int x, int y, int z, Player* player);
bool use(Level* level, int x, int y, int z, Player* player);
void setOpen(Level* level, int x, int y, int z, bool shouldOpen);
void neighborChanged(Level* level, int x, int y, int z, int type);
HitResult clip(Level* level, int xt, int yt, int zt, const Vec3& a, const Vec3& b);
int getDir(int dir);
int getPlacedOnFaceDataValue(Level* level, int x, int y, int z, int face, float clickX, float clickY, float clickZ, int itemValue);
bool mayPlace(Level* level, int x, int y, int z, unsigned char face);
static bool isOpen(int data);
static bool attachesTo(int id);
};
#endif /* NET_MINECRAFT_WORLD_LEVEL_TILE__TrapDoorTile_H__ */

67
src/world/level/tile/TreeTile.h Executable file
View File

@@ -0,0 +1,67 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__TreeTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__TreeTile_H__
//package net.minecraft.world.level.tile;
#include "../../../util/Random.h"
#include "../material/Material.h"
#include "../Level.h"
#include "Tile.h"
#include "LeafTile.h"
class TreeTile: public Tile
{
public:
static const int NORMAL_TRUNK = 0;
static const int DARK_TRUNK = 1;
static const int BIRCH_TRUNK = 2;
TreeTile(int id)
: Tile(id, Material::wood)
{
tex = 20;
}
int getResourceCount(Random* random) {
return 1;
}
int getResource(int data, Random* random) {
return Tile::treeTrunk->id;
}
void onRemove(Level* level, int x, int y, int z) {
int r = LeafTile::REQUIRED_WOOD_RANGE;
int r2 = r + 1;
if (level->hasChunksAt(x - r2, y - r2, z - r2, x + r2, y + r2, z + r2)) {
for (int xo = -r; xo <= r; xo++)
for (int yo = -r; yo <= r; yo++)
for (int zo = -r; zo <= r; zo++) {
int t = level->getTile(x + xo, y + yo, z + zo);
if (t == Tile::leaves->id) {
int currentData = level->getData(x + xo, y + yo, z + zo);
if ((currentData & LeafTile::UPDATE_LEAF_BIT) == 0) {
level->setDataNoUpdate(x + xo, y + yo, z + zo, currentData | LeafTile::UPDATE_LEAF_BIT);
}
}
}
}
}
int getTexture(int face, int data) {
if (face == 1) return 21;
if (face == 0) return 21;
if (data == DARK_TRUNK) return 4 + 7 * 16;
if (data == BIRCH_TRUNK) return 5 + 7 * 16;
return 20;
}
protected:
int getSpawnResourcesAuxValue(int data) {
return data;
}
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__TreeTile_H__*/

59
src/world/level/tile/WebTile.h Executable file
View File

@@ -0,0 +1,59 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__WebTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__WebTile_H__
//package net.minecraft.world.level.tile;
#include "../../entity/Entity.h"
#include "../../item/Item.h"
#include "../Level.h"
#include "../material/Material.h"
#include "../../phys/AABB.h"
class WebTile: public Tile
{
typedef Tile super;
public:
WebTile(int id, int tex)
: super(id, tex, Material::web)
{
}
int getRenderLayer(){
return RENDERLAYER_ALPHATEST;
}
/*@Override*/
void entityInside(Level* level, int x, int y, int z, Entity* entity) {
entity->makeStuckInWeb();
}
/*@Override*/
bool isSolidRender() {
return false;
}
/*@Override*/
AABB* getAABB(Level* level, int x, int y, int z) {
return NULL;
}
/*@Override*/
int getRenderShape() {
return Tile::SHAPE_CROSS_TEXTURE;
}
bool blocksLight() {
return false;
}
bool isCubeShaped() {
return false;
}
/*@Override*/
int getResource(int data, Random* random) {
return Item::string->id;
}
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__WebTile_H__*/

View File

@@ -0,0 +1,34 @@
#ifndef NET_MINECRAFT_WORLD_LEVEL_TILE__WorkbenchTile_H__
#define NET_MINECRAFT_WORLD_LEVEL_TILE__WorkbenchTile_H__
//package net.minecraft.world.level.tile;
#include "Tile.h"
#include "../Level.h"
#include "../material/Material.h"
#include "../../entity/player/Player.h"
class WorkbenchTile: public Tile
{
typedef Tile super;
public:
WorkbenchTile(int id)
: super(id, Material::wood)
{
tex = 11 + 16 * 3;
}
int getTexture(int face) {
if (face == 1) return tex - 16;
if (face == 0) return Tile::wood->getTexture(0);
if (face == 2 || face == 4) return tex + 1;
return tex;
}
bool use(Level* level, int x, int y, int z, Player* player) {
player->startCrafting(x, y, z, Recipe::SIZE_3X3);
return true;
}
};
#endif /*NET_MINECRAFT_WORLD_LEVEL_TILE__WorkbenchTile_H__*/

View 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();
}

View 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__*/

View 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();
}

View 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__*/

View 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();
}
}
}

View 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__ */

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

View 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__*/

View 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();
}

View 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__*/

View 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__*/