#include "stdafx.h" #include "net.minecraft.world.level.levelgen.structure.h" #include "net.minecraft.world.level.h" #include "net.minecraft.world.level.tile.h" #include "net.minecraft.world.level.material.h" #include "net.minecraft.world.level.tile.entity.h" #include "net.minecraft.world.entity.h" #include "WeighedTreasure.h" #include "StructurePiece.h" #include "BoundingBox.h" #include "Direction.h" #include "JavaMath.h" #include "Facing.h" #include "DoorItem.h" /** * * A structure piece is a construction or room, located somewhere in the world * with a given orientatino (out of Direction.java). Structure pieces have a * bounding box that says where the piece is located and its bounds, and the * orientation is used to translate local coordinates into world coordinates. *
* The default orientation is Direction.UNDEFINED, in which case no translation * will occur. If the orientation is Direction::NORTH, coordinate (0, 0, 0) will * be at (boundingBox.x0, boundingBox.y0, boundingBox.z1). In other words, (1, * 1, 1) will be translated to (boundingBox.x0 + 1, boundingBox.y0 + 1, * boundingBox.z1 - 1). *
* When using Direction::SOUTH, the x coordinate will be the same, and the z * coordinate will be flipped. In other words, the bounding box is NOT rotated! * It is only flipped along the z axis. Also note that the bounding box is in * world coordinates, so the local drawing must never reach outside of this. *
* When using east and west coordinates, the local z coordinate will be swapped * with the local x coordinate. For example, (0, 0, 0) is (boundingBox.z1, * boundingBox.y0, boundingBox.z0), and (1, 1, 1) becomes (boundingBox.x1 - 1, * boundingBox.y0 + 1, boundingBox.z0 + 1) when using Direction::WEST. *
* When-ever a structure piece is placing blocks, it is VERY IMPORTANT to always
* make sure that all getTile and setTile calls are within the chunk's bounding
* box. Failing to check this will cause the level generator to create new
* chunks, leading to infinite loops and other errors.
*/
StructurePiece::StructurePiece()
{
boundingBox = NULL;
orientation = 0;
genDepth = 0;
// for reflection
}
StructurePiece::StructurePiece( int genDepth )
{
boundingBox = NULL;
this->genDepth = genDepth;
orientation = Direction::UNDEFINED;
}
StructurePiece::~StructurePiece()
{
if(boundingBox != NULL) delete boundingBox;
}
CompoundTag *StructurePiece::createTag()
{
CompoundTag *tag = new CompoundTag();
tag->putString(L"id", StructureFeatureIO::getEncodeId(this));
tag->put(L"BB", boundingBox->createTag(L"BB"));
tag->putInt(L"O", orientation);
tag->putInt(L"GD", genDepth);
addAdditonalSaveData(tag);
return tag;
}
void StructurePiece::load(Level *level, CompoundTag *tag)
{
if (tag->contains(L"BB"))
{
boundingBox = new BoundingBox(tag->getIntArray(L"BB"));
}
orientation = tag->getInt(L"O");
genDepth = tag->getInt(L"GD");
readAdditonalSaveData(tag);
}
void StructurePiece::addChildren( StructurePiece* startPiece, list< StructurePiece* > *pieces, Random* random )
{
}
BoundingBox* StructurePiece::getBoundingBox()
{
return boundingBox;
}
int StructurePiece::getGenDepth()
{
return genDepth;
}
bool StructurePiece::isInChunk( ChunkPos* pos )
{
int cx = ( pos->x << 4 );
int cz = ( pos->z << 4 );
return boundingBox->intersects( cx, cz, cx + 15, cz + 15 );
}
StructurePiece* StructurePiece::findCollisionPiece( list< StructurePiece* > *pieces, BoundingBox* box )
{
for ( AUTO_VAR(it, pieces->begin()); it != pieces->end(); it++ )
{
StructurePiece* piece = *it;
if ( piece->getBoundingBox() != NULL && piece->getBoundingBox()->intersects( box ) )
{
return piece;
}
}
return NULL;
}
// 4J-PB - Added from 1.2.3
TilePos *StructurePiece::getLocatorPosition()
{
return new TilePos(boundingBox->getXCenter(), boundingBox->getYCenter(), boundingBox->getZCenter());
}
bool StructurePiece::edgesLiquid( Level* level, BoundingBox* chunkBB )
{
int x0 = Math::_max( boundingBox->x0 - 1, chunkBB->x0 );
int y0 = Math::_max( boundingBox->y0 - 1, chunkBB->y0 );
int z0 = Math::_max( boundingBox->z0 - 1, chunkBB->z0 );
int x1 = Math::_min( boundingBox->x1 + 1, chunkBB->x1 );
int y1 = Math::_min( boundingBox->y1 + 1, chunkBB->y1 );
int z1 = Math::_min( boundingBox->z1 + 1, chunkBB->z1 );
// roof and floor
for ( int x = x0; x <= x1; x++ )
{
for ( int z = z0; z <= z1; z++ )
{
int tile = level->getTile( x, y0, z );
if ( tile > 0 && Tile::tiles[tile]->material->isLiquid() )
{
return true;
}
tile = level->getTile( x, y1, z );
if ( tile > 0 && Tile::tiles[tile]->material->isLiquid() )
{
return true;
}
}
}
// north and south
for ( int x = x0; x <= x1; x++ )
{
for ( int y = y0; y <= y1; y++ )
{
int tile = level->getTile( x, y, z0 );
if ( tile > 0 && Tile::tiles[tile]->material->isLiquid() )
{
return true;
}
tile = level->getTile( x, y, z1 );
if ( tile > 0 && Tile::tiles[tile]->material->isLiquid() )
{
return true;
}
}
}
// east and west
for ( int z = z0; z <= z1; z++ )
{
for ( int y = y0; y <= y1; y++ )
{
int tile = level->getTile( x0, y, z );
if ( tile > 0 && Tile::tiles[tile]->material->isLiquid() )
{
return true;
}
tile = level->getTile( x1, y, z );
if ( tile > 0 && Tile::tiles[tile]->material->isLiquid() )
{
return true;
}
}
}
return false;
}
int StructurePiece::getWorldX( int x, int z )
{
switch ( orientation )
{
case Direction::NORTH:
case Direction::SOUTH:
return boundingBox->x0 + x;
case Direction::WEST:
return boundingBox->x1 - z;
case Direction::EAST:
return boundingBox->x0 + z;
default:
return x;
}
}
int StructurePiece::getWorldY( int y )
{
if ( orientation == Direction::UNDEFINED )
{
return y;
}
return y + boundingBox->y0;
}
int StructurePiece::getWorldZ( int x, int z )
{
switch ( orientation )
{
case Direction::NORTH:
return boundingBox->z1 - z;
case Direction::SOUTH:
return boundingBox->z0 + z;
case Direction::WEST:
case Direction::EAST:
return boundingBox->z0 + x;
default:
return z;
}
}
int StructurePiece::getOrientationData( int tile, int data )
{
if ( tile == Tile::rail->id )
{
if ( orientation == Direction::WEST || orientation == Direction::EAST )
{
if ( data == BaseRailTile::DIR_FLAT_X )
{
return BaseRailTile::DIR_FLAT_Z;
}
else
{
return BaseRailTile::DIR_FLAT_X;
}
}
}
else if ( tile == Tile::door_wood_Id || tile == Tile::door_iron_Id )
{
if ( orientation == Direction::SOUTH )
{
if ( data == 0 )
{
return 2;
}
if ( data == 2 )
{
return 0;
}
}
else if ( orientation == Direction::WEST )
{
// 0 = 1
// 1 = 2
// 2 = 3
// 3 = 0
return ( data + 1 ) & 3;
}
else if ( orientation == Direction::EAST )
{
// 0 = 3
// 1 = 0
// 2 = 1
// 3 = 2
return ( data + 3 ) & 3;
}
}
else if ( tile == Tile::stairs_stone_Id || tile == Tile::stairs_wood_Id || tile == Tile::stairs_netherBricks_Id || tile == Tile::stairs_stoneBrick_Id || tile == Tile::stairs_sandstone_Id)
{
if ( orientation == Direction::SOUTH )
{
if ( data == 2 )
{
return 3;
}
if ( data == 3 )
{
return 2;
}
}
else if ( orientation == Direction::WEST )
{
if ( data == 0 )
{
return 2;
}
if ( data == 1 )
{
return 3;
}
if ( data == 2 )
{
return 0;
}
if ( data == 3 )
{
return 1;
}
}
else if ( orientation == Direction::EAST )
{
if ( data == 0 )
{
return 2;
}
if ( data == 1 )
{
return 3;
}
if ( data == 2 )
{
return 1;
}
if ( data == 3 )
{
return 0;
}
}
}
else if ( tile == Tile::ladder->id )
{
if ( orientation == Direction::SOUTH )
{
if ( data == Facing::NORTH )
{
return Facing::SOUTH;
}
if ( data == Facing::SOUTH )
{
return Facing::NORTH;
}
}
else if ( orientation == Direction::WEST )
{
if ( data == Facing::NORTH )
{
return Facing::WEST;
}
if ( data == Facing::SOUTH )
{
return Facing::EAST;
}
if ( data == Facing::WEST )
{
return Facing::NORTH;
}
if ( data == Facing::EAST )
{
return Facing::SOUTH;
}
}
else if ( orientation == Direction::EAST )
{
if ( data == Facing::NORTH )
{
return Facing::EAST;
}
if ( data == Facing::SOUTH )
{
return Facing::WEST;
}
if ( data == Facing::WEST )
{
return Facing::NORTH;
}
if ( data == Facing::EAST )
{
return Facing::SOUTH;
}
}
}
else if ( tile == Tile::button->id )
{
if ( orientation == Direction::SOUTH )
{
if ( data == 3 )
{
return 4;
}
if ( data == 4 )
{
return 3;
}
}
else if ( orientation == Direction::WEST )
{
if ( data == 3 )
{
return 1;
}
if ( data == 4 )
{
return 2;
}
if ( data == 2 )
{
return 3;
}
if ( data == 1 )
{
return 4;
}
}
else if ( orientation == Direction::EAST )
{
if ( data == 3 )
{
return 2;
}
if ( data == 4 )
{
return 1;
}
if ( data == 2 )
{
return 3;
}
if ( data == 1 )
{
return 4;
}
}
}
else if (tile == Tile::tripWireSource_Id || (Tile::tiles[tile] != NULL && dynamic_cast