Pickups are now being saved into Anvil.
Also changed cEntity rotation datatype to double git-svn-id: http://mc-server.googlecode.com/svn/trunk@1262 0a769ca7-a7f5-676a-18bf-c427514a06d6
This commit is contained in:
parent
ef65bd6f49
commit
7593707713
@ -1634,6 +1634,14 @@
|
||||
RelativePath="..\source\WorldStorage\FastNBT.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\source\WorldStorage\NBTChunkSerializer.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\source\WorldStorage\NBTChunkSerializer.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\source\WorldStorage\WorldStorage.cpp"
|
||||
>
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
** Lua binding: AllToLua
|
||||
** Generated automatically by tolua++-1.0.92 on 03/04/13 22:33:20.
|
||||
** Generated automatically by tolua++-1.0.92 on 03/09/13 15:33:58.
|
||||
*/
|
||||
|
||||
#ifndef __cplusplus
|
||||
@ -257,7 +257,7 @@ static int tolua_AllToLua_cStairs_RotationToMetaData00(lua_State* tolua_S)
|
||||
else
|
||||
#endif
|
||||
{
|
||||
float a_Rotation = ((float) tolua_tonumber(tolua_S,2,0));
|
||||
double a_Rotation = ((double) tolua_tonumber(tolua_S,2,0));
|
||||
{
|
||||
unsigned char tolua_ret = (unsigned char) cStairs::RotationToMetaData(a_Rotation);
|
||||
tolua_pushnumber(tolua_S,(lua_Number)tolua_ret);
|
||||
@ -4365,8 +4365,8 @@ static int tolua_AllToLua_cEntity_GetRot00(lua_State* tolua_S)
|
||||
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetRot'", NULL);
|
||||
#endif
|
||||
{
|
||||
const Vector3f& tolua_ret = (const Vector3f&) self->GetRot();
|
||||
tolua_pushusertype(tolua_S,(void*)&tolua_ret,"const Vector3f");
|
||||
const Vector3d& tolua_ret = (const Vector3d&) self->GetRot();
|
||||
tolua_pushusertype(tolua_S,(void*)&tolua_ret,"const Vector3d");
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
@ -4397,7 +4397,7 @@ static int tolua_AllToLua_cEntity_GetRotation00(lua_State* tolua_S)
|
||||
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetRotation'", NULL);
|
||||
#endif
|
||||
{
|
||||
float tolua_ret = (float) self->GetRotation();
|
||||
double tolua_ret = (double) self->GetRotation();
|
||||
tolua_pushnumber(tolua_S,(lua_Number)tolua_ret);
|
||||
}
|
||||
}
|
||||
@ -4429,7 +4429,7 @@ static int tolua_AllToLua_cEntity_GetPitch00(lua_State* tolua_S)
|
||||
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetPitch'", NULL);
|
||||
#endif
|
||||
{
|
||||
float tolua_ret = (float) self->GetPitch();
|
||||
double tolua_ret = (double) self->GetPitch();
|
||||
tolua_pushnumber(tolua_S,(lua_Number)tolua_ret);
|
||||
}
|
||||
}
|
||||
@ -4461,7 +4461,7 @@ static int tolua_AllToLua_cEntity_GetRoll00(lua_State* tolua_S)
|
||||
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetRoll'", NULL);
|
||||
#endif
|
||||
{
|
||||
float tolua_ret = (float) self->GetRoll();
|
||||
double tolua_ret = (double) self->GetRoll();
|
||||
tolua_pushnumber(tolua_S,(lua_Number)tolua_ret);
|
||||
}
|
||||
}
|
||||
@ -4493,15 +4493,15 @@ static int tolua_AllToLua_cEntity_GetLookVector00(lua_State* tolua_S)
|
||||
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetLookVector'", NULL);
|
||||
#endif
|
||||
{
|
||||
Vector3f tolua_ret = (Vector3f) self->GetLookVector();
|
||||
Vector3d tolua_ret = (Vector3d) self->GetLookVector();
|
||||
{
|
||||
#ifdef __cplusplus
|
||||
void* tolua_obj = Mtolua_new((Vector3f)(tolua_ret));
|
||||
tolua_pushusertype(tolua_S,tolua_obj,"Vector3f");
|
||||
void* tolua_obj = Mtolua_new((Vector3d)(tolua_ret));
|
||||
tolua_pushusertype(tolua_S,tolua_obj,"Vector3d");
|
||||
tolua_register_gc(tolua_S,lua_gettop(tolua_S));
|
||||
#else
|
||||
void* tolua_obj = tolua_copy(tolua_S,(void*)&tolua_ret,sizeof(Vector3f));
|
||||
tolua_pushusertype(tolua_S,tolua_obj,"Vector3f");
|
||||
void* tolua_obj = tolua_copy(tolua_S,(void*)&tolua_ret,sizeof(Vector3d));
|
||||
tolua_pushusertype(tolua_S,tolua_obj,"Vector3d");
|
||||
tolua_register_gc(tolua_S,lua_gettop(tolua_S));
|
||||
#endif
|
||||
}
|
||||
@ -4953,7 +4953,7 @@ static int tolua_AllToLua_cEntity_SetRotation00(lua_State* tolua_S)
|
||||
#endif
|
||||
{
|
||||
cEntity* self = (cEntity*) tolua_tousertype(tolua_S,1,0);
|
||||
float a_Rotation = ((float) tolua_tonumber(tolua_S,2,0));
|
||||
double a_Rotation = ((double) tolua_tonumber(tolua_S,2,0));
|
||||
#ifndef TOLUA_RELEASE
|
||||
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'SetRotation'", NULL);
|
||||
#endif
|
||||
@ -4986,7 +4986,7 @@ static int tolua_AllToLua_cEntity_SetPitch00(lua_State* tolua_S)
|
||||
#endif
|
||||
{
|
||||
cEntity* self = (cEntity*) tolua_tousertype(tolua_S,1,0);
|
||||
float a_Pitch = ((float) tolua_tonumber(tolua_S,2,0));
|
||||
double a_Pitch = ((double) tolua_tonumber(tolua_S,2,0));
|
||||
#ifndef TOLUA_RELEASE
|
||||
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'SetPitch'", NULL);
|
||||
#endif
|
||||
@ -5019,7 +5019,7 @@ static int tolua_AllToLua_cEntity_SetRoll00(lua_State* tolua_S)
|
||||
#endif
|
||||
{
|
||||
cEntity* self = (cEntity*) tolua_tousertype(tolua_S,1,0);
|
||||
float a_Roll = ((float) tolua_tonumber(tolua_S,2,0));
|
||||
double a_Roll = ((double) tolua_tonumber(tolua_S,2,0));
|
||||
#ifndef TOLUA_RELEASE
|
||||
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'SetRoll'", NULL);
|
||||
#endif
|
||||
@ -5036,6 +5036,71 @@ static int tolua_AllToLua_cEntity_SetRoll00(lua_State* tolua_S)
|
||||
}
|
||||
#endif //#ifndef TOLUA_DISABLE
|
||||
|
||||
/* method: SetSpeed of class cEntity */
|
||||
#ifndef TOLUA_DISABLE_tolua_AllToLua_cEntity_SetSpeed00
|
||||
static int tolua_AllToLua_cEntity_SetSpeed00(lua_State* tolua_S)
|
||||
{
|
||||
#ifndef TOLUA_RELEASE
|
||||
tolua_Error tolua_err;
|
||||
if (
|
||||
!tolua_isusertype(tolua_S,1,"cEntity",0,&tolua_err) ||
|
||||
!tolua_isnumber(tolua_S,2,0,&tolua_err) ||
|
||||
!tolua_isnumber(tolua_S,3,0,&tolua_err) ||
|
||||
!tolua_isnumber(tolua_S,4,0,&tolua_err) ||
|
||||
!tolua_isnoobj(tolua_S,5,&tolua_err)
|
||||
)
|
||||
goto tolua_lerror;
|
||||
else
|
||||
#endif
|
||||
{
|
||||
cEntity* self = (cEntity*) tolua_tousertype(tolua_S,1,0);
|
||||
double a_SpeedX = ((double) tolua_tonumber(tolua_S,2,0));
|
||||
double a_SpeedY = ((double) tolua_tonumber(tolua_S,3,0));
|
||||
double a_SpeedZ = ((double) tolua_tonumber(tolua_S,4,0));
|
||||
#ifndef TOLUA_RELEASE
|
||||
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'SetSpeed'", NULL);
|
||||
#endif
|
||||
{
|
||||
self->SetSpeed(a_SpeedX,a_SpeedY,a_SpeedZ);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
#ifndef TOLUA_RELEASE
|
||||
tolua_lerror:
|
||||
tolua_error(tolua_S,"#ferror in function 'SetSpeed'.",&tolua_err);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
#endif //#ifndef TOLUA_DISABLE
|
||||
|
||||
/* method: SetSpeed of class cEntity */
|
||||
#ifndef TOLUA_DISABLE_tolua_AllToLua_cEntity_SetSpeed01
|
||||
static int tolua_AllToLua_cEntity_SetSpeed01(lua_State* tolua_S)
|
||||
{
|
||||
tolua_Error tolua_err;
|
||||
if (
|
||||
!tolua_isusertype(tolua_S,1,"cEntity",0,&tolua_err) ||
|
||||
(tolua_isvaluenil(tolua_S,2,&tolua_err) || !tolua_isusertype(tolua_S,2,"const Vector3d",0,&tolua_err)) ||
|
||||
!tolua_isnoobj(tolua_S,3,&tolua_err)
|
||||
)
|
||||
goto tolua_lerror;
|
||||
else
|
||||
{
|
||||
cEntity* self = (cEntity*) tolua_tousertype(tolua_S,1,0);
|
||||
const Vector3d* a_Speed = ((const Vector3d*) tolua_tousertype(tolua_S,2,0));
|
||||
#ifndef TOLUA_RELEASE
|
||||
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'SetSpeed'", NULL);
|
||||
#endif
|
||||
{
|
||||
self->SetSpeed(*a_Speed);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
tolua_lerror:
|
||||
return tolua_AllToLua_cEntity_SetSpeed00(tolua_S);
|
||||
}
|
||||
#endif //#ifndef TOLUA_DISABLE
|
||||
|
||||
/* method: AddSpeed of class cEntity */
|
||||
#ifndef TOLUA_DISABLE_tolua_AllToLua_cEntity_AddSpeed00
|
||||
static int tolua_AllToLua_cEntity_AddSpeed00(lua_State* tolua_S)
|
||||
@ -21731,6 +21796,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
|
||||
tolua_constant(tolua_S,"etEntity",cEntity::etEntity);
|
||||
tolua_constant(tolua_S,"etPlayer",cEntity::etPlayer);
|
||||
tolua_constant(tolua_S,"etPickup",cEntity::etPickup);
|
||||
tolua_constant(tolua_S,"etMonster",cEntity::etMonster);
|
||||
tolua_constant(tolua_S,"etMob",cEntity::etMob);
|
||||
tolua_constant(tolua_S,"etFallingBlock",cEntity::etFallingBlock);
|
||||
tolua_constant(tolua_S,"etMinecart",cEntity::etMinecart);
|
||||
@ -21773,6 +21839,8 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
|
||||
tolua_function(tolua_S,"SetRotation",tolua_AllToLua_cEntity_SetRotation00);
|
||||
tolua_function(tolua_S,"SetPitch",tolua_AllToLua_cEntity_SetPitch00);
|
||||
tolua_function(tolua_S,"SetRoll",tolua_AllToLua_cEntity_SetRoll00);
|
||||
tolua_function(tolua_S,"SetSpeed",tolua_AllToLua_cEntity_SetSpeed00);
|
||||
tolua_function(tolua_S,"SetSpeed",tolua_AllToLua_cEntity_SetSpeed01);
|
||||
tolua_function(tolua_S,"AddSpeed",tolua_AllToLua_cEntity_AddSpeed00);
|
||||
tolua_function(tolua_S,"GetUniqueID",tolua_AllToLua_cEntity_GetUniqueID00);
|
||||
tolua_function(tolua_S,"IsDestroyed",tolua_AllToLua_cEntity_IsDestroyed00);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
** Lua binding: AllToLua
|
||||
** Generated automatically by tolua++-1.0.92 on 03/04/13 22:33:20.
|
||||
** Generated automatically by tolua++-1.0.92 on 03/09/13 15:33:59.
|
||||
*/
|
||||
|
||||
/* Exported function */
|
||||
|
@ -47,14 +47,14 @@ public:
|
||||
|
||||
|
||||
// Bed specific helper functions
|
||||
static NIBBLETYPE RotationToMetaData(float a_Rotation)
|
||||
static NIBBLETYPE RotationToMetaData(double a_Rotation)
|
||||
{
|
||||
a_Rotation += 180 + (180/4); // So its not aligned with axis
|
||||
if( a_Rotation > 360.f ) a_Rotation -= 360.f;
|
||||
if( a_Rotation > 360 ) a_Rotation -= 360;
|
||||
|
||||
a_Rotation = (a_Rotation/360) * 4;
|
||||
a_Rotation = (a_Rotation / 360) * 4;
|
||||
|
||||
return ((char)a_Rotation+2) % 4;
|
||||
return ((char)a_Rotation + 2) % 4;
|
||||
}
|
||||
|
||||
|
||||
|
@ -41,7 +41,7 @@ public:
|
||||
{
|
||||
return false;
|
||||
}
|
||||
float rot = a_Player->GetRotation();
|
||||
double rot = a_Player->GetRotation();
|
||||
if (
|
||||
(Area.GetRelBlockType(0, 0, 1) == E_BLOCK_CHEST) ||
|
||||
(Area.GetRelBlockType(2, 0, 1) == E_BLOCK_CHEST)
|
||||
@ -79,7 +79,7 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
float rot = a_Player->GetRotation();
|
||||
double rot = a_Player->GetRotation();
|
||||
// Choose meta from player rotation, choose only between 2 or 3
|
||||
NIBBLETYPE NewMeta = ((rot >= -90) && (rot < 90)) ? 2 : 3;
|
||||
if (
|
||||
@ -178,7 +178,7 @@ public:
|
||||
|
||||
|
||||
/// Translates player rotation when placing a chest into the chest block metadata. Valid for single chests only
|
||||
static NIBBLETYPE RotationToMetaData(float a_Rotation)
|
||||
static NIBBLETYPE RotationToMetaData(double a_Rotation)
|
||||
{
|
||||
a_Rotation += 90 + 45; // So its not aligned with axis
|
||||
|
||||
|
@ -28,6 +28,8 @@ public:
|
||||
) override
|
||||
{
|
||||
a_BlockType = m_BlockType;
|
||||
|
||||
// FIXME: Do not use cPiston class for dispenser placement!
|
||||
a_BlockMeta = cPiston::RotationPitchToMetaData(a_Player->GetRotation(), 0);
|
||||
return true;
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ public:
|
||||
{
|
||||
NIBBLETYPE OldMetaData = a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
|
||||
NIBBLETYPE NewMetaData = cDoors::RotationToMetaData(a_Player->GetRotation() + 270);
|
||||
OldMetaData ^= 4; //Toggle the gate
|
||||
OldMetaData ^= 4; // Toggle the gate
|
||||
if ((OldMetaData & 1) == (NewMetaData & 1))
|
||||
{
|
||||
// Standing in front of the gate - apply new direction
|
||||
|
@ -34,7 +34,10 @@ public:
|
||||
) override
|
||||
{
|
||||
a_BlockType = m_BlockType;
|
||||
|
||||
// FIXME: Do not use cPiston class for furnace placement!
|
||||
a_BlockMeta = cPiston::RotationPitchToMetaData(a_Player->GetRotation(), 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
} ;
|
||||
|
@ -296,6 +296,12 @@ void cChunk::SetAllData(
|
||||
CalculateHeightmap();
|
||||
}
|
||||
|
||||
// Initialize incoming entities:
|
||||
for (cEntityList::iterator itr = a_Entities.begin(), end = a_Entities.end(); itr != end; ++itr)
|
||||
{
|
||||
(*itr)->Initialize(m_World);
|
||||
} // for itr - a_Entities[]
|
||||
|
||||
// Append entities to current entity list:
|
||||
m_Entities.splice(m_Entities.end(), a_Entities);
|
||||
|
||||
|
@ -204,13 +204,13 @@ inline void AddFaceDirection(int & a_BlockX, unsigned char & a_BlockY, int & a_B
|
||||
#define PI 3.14159265358979323846264338327950288419716939937510582097494459072381640628620899862803482534211706798f
|
||||
#define MIN(a,b) (((a)>(b))?(b):(a))
|
||||
#define MAX(a,b) (((a)>(b))?(a):(b))
|
||||
inline void EulerToVector( float a_Pan, float a_Pitch, float & a_X, float & a_Y, float & a_Z )
|
||||
inline void EulerToVector(double a_Pan, double a_Pitch, double & a_X, double & a_Y, double & a_Z)
|
||||
{
|
||||
// a_X = sinf ( a_Pan / 180 * PI ) * cosf ( a_Pitch / 180 * PI );
|
||||
// a_Y = -sinf ( a_Pitch / 180 * PI );
|
||||
// a_Z = -cosf ( a_Pan / 180 * PI ) * cosf ( a_Pitch / 180 * PI );
|
||||
a_X = cos(a_Pan / 180 * PI)*cos(a_Pitch / 180 * PI);
|
||||
a_Y = sin(a_Pan / 180 * PI)*cos(a_Pitch / 180 * PI);
|
||||
a_X = cos(a_Pan / 180 * PI) * cos(a_Pitch / 180 * PI);
|
||||
a_Y = sin(a_Pan / 180 * PI) * cos(a_Pitch / 180 * PI);
|
||||
a_Z = sin(a_Pitch / 180 * PI);
|
||||
}
|
||||
|
||||
@ -218,22 +218,26 @@ inline void EulerToVector( float a_Pan, float a_Pitch, float & a_X, float & a_Y,
|
||||
|
||||
|
||||
|
||||
inline void VectorToEuler( float a_X, float a_Y, float a_Z, float & a_Pan, float & a_Pitch )
|
||||
inline void VectorToEuler(double a_X, double a_Y, double a_Z, double & a_Pan, double & a_Pitch)
|
||||
{
|
||||
if( a_X != 0 )
|
||||
a_Pan = atan2( a_Z, a_X ) * 180 / PI - 90;
|
||||
if (a_X != 0)
|
||||
{
|
||||
a_Pan = atan2(a_Z, a_X) * 180 / PI - 90;
|
||||
}
|
||||
else
|
||||
{
|
||||
a_Pan = 0;
|
||||
a_Pitch = atan2(a_Y, sqrtf((a_X * a_X) + (a_Z * a_Z))) * 180 / PI;
|
||||
}
|
||||
a_Pitch = atan2(a_Y, sqrt((a_X * a_X) + (a_Z * a_Z))) * 180 / PI;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
inline float GetSignf( float a_Val )
|
||||
inline float GetSignf(float a_Val)
|
||||
{
|
||||
return (a_Val < 0.f)?-1.f:1.f;
|
||||
return (a_Val < 0.f) ? -1.f : 1.f;
|
||||
}
|
||||
|
||||
|
||||
@ -242,7 +246,7 @@ inline float GetSignf( float a_Val )
|
||||
|
||||
inline float GetSpecialSignf( float a_Val )
|
||||
{
|
||||
return (a_Val <= 0.f)?-1.f:1.f;
|
||||
return (a_Val <= 0.f) ? -1.f : 1.f;
|
||||
}
|
||||
|
||||
|
||||
|
102
source/Doors.h
102
source/Doors.h
@ -1,61 +1,87 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
class cDoors // tolua_export
|
||||
{ // tolua_export
|
||||
public:
|
||||
static char RotationToMetaData( float a_Rotation ) // tolua_export
|
||||
{ // tolua_export
|
||||
a_Rotation += 90 + 45; // So its not aligned with axis
|
||||
if( a_Rotation > 360.f ) a_Rotation -= 360.f;
|
||||
if( a_Rotation >= 0.f && a_Rotation < 90.f )
|
||||
return 0x0;
|
||||
else if( a_Rotation >= 180 && a_Rotation < 270 )
|
||||
return 0x2;
|
||||
else if( a_Rotation >= 90 && a_Rotation < 180 )
|
||||
return 0x1;
|
||||
else
|
||||
return 0x3;
|
||||
} // tolua_export
|
||||
|
||||
static char ChangeStateMetaData( char a_MetaData ) // tolua_export
|
||||
{ // tolua_export
|
||||
|
||||
|
||||
// tolua_begin
|
||||
class cDoors
|
||||
{
|
||||
public:
|
||||
static char RotationToMetaData(double a_Rotation)
|
||||
{
|
||||
a_Rotation += 90 + 45; // So its not aligned with axis
|
||||
if (a_Rotation > 360)
|
||||
{
|
||||
a_Rotation -= 360;
|
||||
}
|
||||
if (a_Rotation >= 0.f && a_Rotation < 90)
|
||||
{
|
||||
return 0x0;
|
||||
}
|
||||
else if ((a_Rotation >= 180) && (a_Rotation < 270))
|
||||
{
|
||||
return 0x2;
|
||||
}
|
||||
else if ((a_Rotation >= 90) && (a_Rotation < 180))
|
||||
{
|
||||
return 0x1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0x3;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static NIBBLETYPE ChangeStateMetaData(NIBBLETYPE a_MetaData)
|
||||
{
|
||||
|
||||
a_MetaData ^= 4; //XOR bit 2 aka 3. bit (Door open state)
|
||||
|
||||
return a_MetaData;
|
||||
} // tolua_export
|
||||
}
|
||||
|
||||
|
||||
static void ChangeDoor(cWorld *a_World, int a_X, int a_Y, int a_Z) // tolua_export
|
||||
{ // tolua_export
|
||||
char OldMetaData = a_World->GetBlockMeta(a_X, a_Y, a_Z);
|
||||
static void ChangeDoor(cWorld * a_World, int a_X, int a_Y, int a_Z)
|
||||
{
|
||||
NIBBLETYPE OldMetaData = a_World->GetBlockMeta(a_X, a_Y, a_Z);
|
||||
|
||||
a_World->SetBlockMeta(a_X, a_Y, a_Z, ChangeStateMetaData ( OldMetaData ) );
|
||||
|
||||
a_World->SetBlockMeta(a_X, a_Y, a_Z, ChangeStateMetaData(OldMetaData));
|
||||
|
||||
if (OldMetaData & 8)
|
||||
{ //current block is top of the door
|
||||
char BottomBlock = a_World->GetBlock(a_X, a_Y - 1, a_Z);
|
||||
char BottomMeta = a_World->GetBlockMeta(a_X, a_Y - 1, a_Z);
|
||||
{
|
||||
// Current block is top of the door
|
||||
BLOCKTYPE BottomBlock = a_World->GetBlock(a_X, a_Y - 1, a_Z);
|
||||
NIBBLETYPE BottomMeta = a_World->GetBlockMeta(a_X, a_Y - 1, a_Z);
|
||||
|
||||
if (IsDoor(BottomBlock) && !(BottomMeta & 8))
|
||||
{
|
||||
a_World->SetBlockMeta(a_X, a_Y - 1, a_Z, ChangeStateMetaData ( BottomMeta ) );
|
||||
a_World->SetBlockMeta(a_X, a_Y - 1, a_Z, ChangeStateMetaData(BottomMeta));
|
||||
}
|
||||
} else { //current block is bottom of the door
|
||||
char TopBlock = a_World->GetBlock(a_X, a_Y + 1, a_Z);
|
||||
char TopMeta = a_World->GetBlockMeta(a_X, a_Y + 1, a_Z);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Current block is bottom of the door
|
||||
BLOCKTYPE TopBlock = a_World->GetBlock(a_X, a_Y + 1, a_Z);
|
||||
NIBBLETYPE TopMeta = a_World->GetBlockMeta(a_X, a_Y + 1, a_Z);
|
||||
|
||||
if (IsDoor(TopBlock) && (TopMeta & 8))
|
||||
{
|
||||
a_World->SetBlockMeta(a_X, a_Y + 1, a_Z, ChangeStateMetaData ( TopMeta ) );
|
||||
a_World->SetBlockMeta(a_X, a_Y + 1, a_Z, ChangeStateMetaData(TopMeta));
|
||||
}
|
||||
}
|
||||
} // tolua_export
|
||||
|
||||
inline static bool IsDoor(char a_Block)
|
||||
{
|
||||
return (a_Block == E_BLOCK_WOODEN_DOOR || a_Block == E_BLOCK_IRON_DOOR);
|
||||
}
|
||||
|
||||
|
||||
inline static bool IsDoor(BLOCKTYPE a_Block)
|
||||
{
|
||||
return (a_Block == E_BLOCK_WOODEN_DOOR) || (a_Block == E_BLOCK_IRON_DOOR);
|
||||
}
|
||||
} ;
|
||||
// tolua_end
|
||||
|
||||
|
||||
|
||||
|
||||
}; // tolua_export
|
||||
|
@ -6,7 +6,6 @@
|
||||
#include "Server.h"
|
||||
#include "Root.h"
|
||||
#include "Vector3d.h"
|
||||
#include "Vector3f.h"
|
||||
#include "Matrix4f.h"
|
||||
#include "ReferenceManager.h"
|
||||
#include "ClientHandle.h"
|
||||
@ -134,8 +133,11 @@ void cEntity::WrapRotation()
|
||||
|
||||
void cEntity::MoveToCorrectChunk(bool a_bIgnoreOldChunk)
|
||||
{
|
||||
ASSERT(m_World != NULL); // Entity needs a world to move to a chunk
|
||||
if (!m_World) return;
|
||||
if (!m_World)
|
||||
{
|
||||
// This is normal for entities being currently loaded
|
||||
return;
|
||||
}
|
||||
|
||||
int ChunkX = 0, ChunkY = 0, ChunkZ = 0;
|
||||
cWorld::BlockToChunk((int)m_Pos.x, (int)m_Pos.y, (int)m_Pos.z, ChunkX, ChunkY, ChunkZ);
|
||||
@ -299,7 +301,7 @@ void cEntity::SetRot(const Vector3f & a_Rot)
|
||||
|
||||
|
||||
|
||||
void cEntity::SetRotation(float a_Rotation)
|
||||
void cEntity::SetRotation(double a_Rotation)
|
||||
{
|
||||
m_Rot.x = a_Rotation;
|
||||
m_bDirtyOrientation = true;
|
||||
@ -309,7 +311,7 @@ void cEntity::SetRotation(float a_Rotation)
|
||||
|
||||
|
||||
|
||||
void cEntity::SetPitch(float a_Pitch)
|
||||
void cEntity::SetPitch(double a_Pitch)
|
||||
{
|
||||
m_Rot.y = a_Pitch;
|
||||
m_bDirtyOrientation = true;
|
||||
@ -319,7 +321,7 @@ void cEntity::SetPitch(float a_Pitch)
|
||||
|
||||
|
||||
|
||||
void cEntity::SetRoll(float a_Roll)
|
||||
void cEntity::SetRoll(double a_Roll)
|
||||
{
|
||||
m_Rot.z = a_Roll;
|
||||
m_bDirtyOrientation = true;
|
||||
@ -329,6 +331,15 @@ void cEntity::SetRoll(float a_Roll)
|
||||
|
||||
|
||||
|
||||
void cEntity::SetSpeed(double a_SpeedX, double a_SpeedY, double a_SpeedZ)
|
||||
{
|
||||
m_Speed.Set(a_SpeedX, a_SpeedY, a_SpeedZ);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cEntity::AddSpeed(const Vector3d & a_AddSpeed)
|
||||
{
|
||||
m_Speed += a_AddSpeed;
|
||||
@ -340,11 +351,11 @@ void cEntity::AddSpeed(const Vector3d & a_AddSpeed)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Get look vector (this is NOT a rotation!)
|
||||
Vector3f cEntity::GetLookVector(void) const
|
||||
Vector3d cEntity::GetLookVector(void) const
|
||||
{
|
||||
Matrix4f m;
|
||||
Matrix4d m;
|
||||
m.Init(Vector3f(), 0, m_Rot.x, -m_Rot.y);
|
||||
Vector3f Look = m.Transform(Vector3f(0, 0, 1));
|
||||
Vector3d Look = m.Transform(Vector3d(0, 0, 1));
|
||||
return Look;
|
||||
}
|
||||
|
||||
|
@ -63,11 +63,12 @@ public:
|
||||
etEntity, // For all other types
|
||||
etPlayer,
|
||||
etPickup,
|
||||
etMob,
|
||||
etMonster,
|
||||
etMob = etMonster, // DEPRECATED, use etMonster instead!
|
||||
etFallingBlock,
|
||||
etMinecart,
|
||||
|
||||
// Older constants, left over for compatibility reasons (plugins)
|
||||
// DEPRECATED older constants, left over for compatibility reasons (plugins)
|
||||
eEntityType_Entity = etEntity,
|
||||
eEntityType_Player = etPlayer,
|
||||
eEntityType_Pickup = etPickup,
|
||||
@ -108,11 +109,11 @@ public:
|
||||
double GetPosX (void) const {return m_Pos.x; }
|
||||
double GetPosY (void) const {return m_Pos.y; }
|
||||
double GetPosZ (void) const {return m_Pos.z; }
|
||||
const Vector3f & GetRot (void) const {return m_Rot; }
|
||||
float GetRotation (void) const {return m_Rot.x; }
|
||||
float GetPitch (void) const {return m_Rot.y; }
|
||||
float GetRoll (void) const {return m_Rot.z; }
|
||||
Vector3f GetLookVector(void) const;
|
||||
const Vector3d & GetRot (void) const {return m_Rot; }
|
||||
double GetRotation (void) const {return m_Rot.x; }
|
||||
double GetPitch (void) const {return m_Rot.y; }
|
||||
double GetRoll (void) const {return m_Rot.z; }
|
||||
Vector3d GetLookVector(void) const;
|
||||
const Vector3d & GetSpeed (void) const { return m_Speed; }
|
||||
double GetSpeedX (void) const { return m_Speed.x; }
|
||||
double GetSpeedY (void) const { return m_Speed.y; }
|
||||
@ -128,11 +129,14 @@ public:
|
||||
void SetPosition(double a_PosX, double a_PosY, double a_PosZ);
|
||||
void SetPosition(const Vector3d & a_Pos);
|
||||
void SetRot (const Vector3f & a_Rot);
|
||||
void SetRotation(float a_Rotation);
|
||||
void SetPitch (float a_Pitch);
|
||||
void SetRoll (float a_Roll);
|
||||
void SetRotation(double a_Rotation);
|
||||
void SetPitch (double a_Pitch);
|
||||
void SetRoll (double a_Roll);
|
||||
void SetSpeed (double a_SpeedX, double a_SpeedY, double a_SpeedZ);
|
||||
void SetSpeed (const Vector3d & a_Speed) { m_Speed = a_Speed; }
|
||||
|
||||
void AddSpeed(const Vector3d & a_AddSpeed);
|
||||
|
||||
// tolua_end
|
||||
|
||||
inline int GetUniqueID(void) const { return m_UniqueID; } // tolua_export
|
||||
@ -173,16 +177,6 @@ public:
|
||||
virtual void OnRightClicked(cPlayer & a_Player) {};
|
||||
|
||||
protected:
|
||||
virtual void Destroyed(void) {} // Called after the entity has been destroyed
|
||||
|
||||
void SetWorld(cWorld * a_World) { m_World = a_World; }
|
||||
void MoveToCorrectChunk(bool a_bIgnoreOldChunk = false);
|
||||
|
||||
friend class cReferenceManager;
|
||||
void AddReference( cEntity*& a_EntityPtr );
|
||||
void ReferencedBy( cEntity*& a_EntityPtr );
|
||||
void Dereference( cEntity*& a_EntityPtr );
|
||||
|
||||
static cCriticalSection m_CSCount;
|
||||
static int m_EntityCount;
|
||||
|
||||
@ -201,7 +195,7 @@ protected:
|
||||
Vector3d m_Pos;
|
||||
bool m_bDirtyPosition;
|
||||
|
||||
Vector3f m_Rot;
|
||||
Vector3d m_Rot;
|
||||
bool m_bDirtyOrientation;
|
||||
|
||||
Vector3d m_Speed;
|
||||
@ -211,11 +205,21 @@ protected:
|
||||
|
||||
eEntityType m_EntityType;
|
||||
|
||||
cWorld* m_World;
|
||||
cWorld * m_World;
|
||||
|
||||
float m_FireDamageInterval;
|
||||
float m_BurnPeriod;
|
||||
}; // tolua_export
|
||||
|
||||
virtual void Destroyed(void) {} // Called after the entity has been destroyed
|
||||
|
||||
void SetWorld(cWorld * a_World) { m_World = a_World; }
|
||||
void MoveToCorrectChunk(bool a_bIgnoreOldChunk = false);
|
||||
|
||||
friend class cReferenceManager;
|
||||
void AddReference( cEntity*& a_EntityPtr );
|
||||
void ReferencedBy( cEntity*& a_EntityPtr );
|
||||
void Dereference( cEntity*& a_EntityPtr );
|
||||
} ; // tolua_export
|
||||
|
||||
typedef std::list<cEntity *> cEntityList;
|
||||
|
||||
|
@ -109,3 +109,117 @@ public:
|
||||
}
|
||||
float cell[16];
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class Matrix4d
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
TX=3,
|
||||
TY=7,
|
||||
TZ=11,
|
||||
D0=0, D1=5, D2=10, D3=15,
|
||||
SX=D0, SY=D1, SZ=D2,
|
||||
W=D3
|
||||
};
|
||||
Matrix4d() { Identity(); }
|
||||
double& operator [] ( int a_N ) { return cell[a_N]; }
|
||||
void Identity()
|
||||
{
|
||||
cell[1] = cell[2] = cell[TX] = cell[4] = cell[6] = cell[TY] =
|
||||
cell[8] = cell[9] = cell[TZ] = cell[12] = cell[13] = cell[14] = 0;
|
||||
cell[D0] = cell[D1] = cell[D2] = cell[W] = 1;
|
||||
}
|
||||
void Init( Vector3f a_Pos, double a_RX, double a_RY, double a_RZ )
|
||||
{
|
||||
Matrix4d t;
|
||||
t.RotateX( a_RZ );
|
||||
RotateY( a_RY );
|
||||
Concatenate( t );
|
||||
t.RotateZ( a_RX );
|
||||
Concatenate( t );
|
||||
Translate( a_Pos );
|
||||
}
|
||||
void RotateX( double a_RX )
|
||||
{
|
||||
double sx = (double)sin( a_RX * M_PI / 180 );
|
||||
double cx = (double)cos( a_RX * M_PI / 180 );
|
||||
Identity();
|
||||
cell[5] = cx, cell[6] = sx, cell[9] = -sx, cell[10] = cx;
|
||||
}
|
||||
void RotateY( double a_RY )
|
||||
{
|
||||
double sy = (double)sin( a_RY * M_PI / 180 );
|
||||
double cy = (double)cos( a_RY * M_PI / 180 );
|
||||
Identity ();
|
||||
cell[0] = cy, cell[2] = -sy, cell[8] = sy, cell[10] = cy;
|
||||
}
|
||||
void RotateZ( double a_RZ )
|
||||
{
|
||||
double sz = (double)sin( a_RZ * M_PI / 180 );
|
||||
double cz = (double)cos( a_RZ * M_PI / 180 );
|
||||
Identity ();
|
||||
cell[0] = cz, cell[1] = sz, cell[4] = -sz, cell[5] = cz;
|
||||
}
|
||||
void Translate( Vector3d a_Pos ) { cell[TX] += a_Pos.x; cell[TY] += a_Pos.y; cell[TZ] += a_Pos.z; }
|
||||
void SetTranslation( Vector3d a_Pos ) { cell[TX] = a_Pos.x; cell[TY] = a_Pos.y; cell[TZ] = a_Pos.z; }
|
||||
void Concatenate( const Matrix4d & m2 )
|
||||
{
|
||||
Matrix4d res;
|
||||
int c;
|
||||
for ( c = 0; c < 4; c++ ) for ( int r = 0; r < 4; r++ )
|
||||
res.cell[r * 4 + c] = cell[r * 4] * m2.cell[c] +
|
||||
cell[r * 4 + 1] * m2.cell[c + 4] +
|
||||
cell[r * 4 + 2] * m2.cell[c + 8] +
|
||||
cell[r * 4 + 3] * m2.cell[c + 12];
|
||||
for ( c = 0; c < 16; c++ ) cell[c] = res.cell[c];
|
||||
}
|
||||
Vector3d Transform( const Vector3d & v ) const
|
||||
{
|
||||
double x = cell[0] * v.x + cell[1] * v.y + cell[2] * v.z + cell[3];
|
||||
double y = cell[4] * v.x + cell[5] * v.y + cell[6] * v.z + cell[7];
|
||||
double z = cell[8] * v.x + cell[9] * v.y + cell[10] * v.z + cell[11];
|
||||
return Vector3d( x, y, z );
|
||||
}
|
||||
void Invert()
|
||||
{
|
||||
Matrix4d t;
|
||||
int h, i;
|
||||
double tx = -cell[3], ty = -cell[7], tz = -cell[11];
|
||||
for ( h = 0; h < 3; h++ ) for ( int v = 0; v < 3; v++ ) t.cell[h + v * 4] = cell[v + h * 4];
|
||||
for ( i = 0; i < 11; i++ ) cell[i] = t.cell[i];
|
||||
cell[3] = tx * cell[0] + ty * cell[1] + tz * cell[2];
|
||||
cell[7] = tx * cell[4] + ty * cell[5] + tz * cell[6];
|
||||
cell[11] = tx * cell[8] + ty * cell[9] + tz * cell[10];
|
||||
}
|
||||
Vector3d GetXColumn() { return Vector3d( cell[0], cell[1], cell[2] ); }
|
||||
Vector3d GetYColumn() { return Vector3d( cell[4], cell[5], cell[6] ); }
|
||||
Vector3d GetZColumn() { return Vector3d( cell[8], cell[9], cell[10] ); }
|
||||
void SetXColumn( const Vector3d & a_X )
|
||||
{
|
||||
cell[0] = a_X.x;
|
||||
cell[1] = a_X.y;
|
||||
cell[2] = a_X.z;
|
||||
}
|
||||
void SetYColumn( const Vector3d & a_Y )
|
||||
{
|
||||
cell[4] = a_Y.x;
|
||||
cell[5] = a_Y.y;
|
||||
cell[6] = a_Y.z;
|
||||
}
|
||||
void SetZColumn( const Vector3d & a_Z )
|
||||
{
|
||||
cell[8] = a_Z.x;
|
||||
cell[9] = a_Z.y;
|
||||
cell[10] = a_Z.z;
|
||||
}
|
||||
double cell[16];
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -115,6 +115,17 @@ cMinecartWithChest::cMinecartWithChest(double a_X, double a_Y, double a_Z) :
|
||||
|
||||
|
||||
|
||||
void cMinecartWithChest::SetItem(int a_Idx, const cItem & a_Item)
|
||||
{
|
||||
ASSERT((a_Idx >= 0) && (a_Idx < ARRAYCOUNT(m_Items)));
|
||||
|
||||
m_Items[a_Idx] = a_Item;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cMinecartWithChest::OnRightClicked(cPlayer & a_Player)
|
||||
{
|
||||
// Show the chest UI window to the player
|
||||
|
@ -10,6 +10,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "Entity.h"
|
||||
#include "Item.h"
|
||||
|
||||
|
||||
|
||||
@ -74,8 +75,21 @@ class cMinecartWithChest :
|
||||
public:
|
||||
CLASS_PROTODEF(cMinecartWithChest);
|
||||
|
||||
/// Number of item slots in the chest
|
||||
static const int NumSlots = 9 * 3;
|
||||
|
||||
cMinecartWithChest(double a_X, double a_Y, double a_Z);
|
||||
|
||||
const cItem & GetItem(int a_Idx) const { return m_Items[a_Idx]; }
|
||||
cItem & GetItem(int a_Idx) { return m_Items[a_Idx]; }
|
||||
|
||||
void SetItem(int a_Idx, const cItem & a_Item);
|
||||
|
||||
protected:
|
||||
|
||||
/// The chest contents:
|
||||
cItem m_Items[NumSlots];
|
||||
|
||||
// cEntity overrides:
|
||||
virtual void OnRightClicked(cPlayer & a_Player) override;
|
||||
} ;
|
||||
|
@ -145,10 +145,10 @@ void cMonster::Tick(float a_Dt, MTRand & a_TickRandom)
|
||||
|
||||
ReplicateMovement();
|
||||
|
||||
Vector3f Distance = m_Destination - Vector3f( m_Pos );
|
||||
Vector3d Distance = m_Destination - Vector3f( m_Pos );
|
||||
if (Distance.SqrLength() > 0.1f)
|
||||
{
|
||||
float Rotation, Pitch;
|
||||
double Rotation, Pitch;
|
||||
Distance.Normalize();
|
||||
VectorToEuler( Distance.x, Distance.y, Distance.z, Rotation, Pitch );
|
||||
SetRotation( Rotation );
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
cPickup::cPickup(int a_MicroPosX, int a_MicroPosY, int a_MicroPosZ, const cItem & a_Item, float a_SpeedX /* = 0.f */, float a_SpeedY /* = 0.f */, float a_SpeedZ /* = 0.f */)
|
||||
: cEntity(etPickup, ((double)(a_MicroPosX)) / 32, ((double)(a_MicroPosY)) / 32, ((double)(a_MicroPosZ)) / 32)
|
||||
, m_Health(5)
|
||||
, m_bOnGround( false )
|
||||
, m_bReplicated( false )
|
||||
, m_Timer( 0.f )
|
||||
|
@ -38,7 +38,13 @@ public:
|
||||
virtual void Tick(float a_Dt, MTRand & a_TickRandom) override;
|
||||
virtual void HandlePhysics(float a_Dt) override;
|
||||
|
||||
short GetHealth(void) const { return m_Health; }
|
||||
|
||||
/// Returns the number of ticks that this entity has existed
|
||||
short GetAge(void) const { return (short)(m_Timer / 50); }
|
||||
|
||||
private:
|
||||
short m_Health;
|
||||
|
||||
Vector3d m_ResultingSpeed; //Can be used to modify the resulting speed for the current tick ;)
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
|
||||
|
||||
// fwd: "cWorld.h"
|
||||
// fwd: World.h
|
||||
class cWorld;
|
||||
|
||||
|
||||
@ -16,15 +16,15 @@ class cPiston
|
||||
{
|
||||
public:
|
||||
|
||||
cPiston( cWorld* a_World );
|
||||
cPiston(cWorld * a_World);
|
||||
|
||||
static NIBBLETYPE RotationPitchToMetaData(float a_Rotation, float a_Pitch)
|
||||
static NIBBLETYPE RotationPitchToMetaData(double a_Rotation, double a_Pitch)
|
||||
{
|
||||
if (a_Pitch >= 50.f)
|
||||
if (a_Pitch >= 50)
|
||||
{
|
||||
return 0x1;
|
||||
}
|
||||
else if (a_Pitch <= -50.f)
|
||||
else if (a_Pitch <= -50)
|
||||
{
|
||||
return 0x0;
|
||||
}
|
||||
@ -32,11 +32,11 @@ public:
|
||||
{
|
||||
a_Rotation += 90 + 45; // So its not aligned with axis
|
||||
|
||||
if (a_Rotation > 360.f)
|
||||
if (a_Rotation > 360)
|
||||
{
|
||||
a_Rotation -= 360.f;
|
||||
a_Rotation -= 360;
|
||||
}
|
||||
if ((a_Rotation >= 0.f) && (a_Rotation < 90.f))
|
||||
if ((a_Rotation >= 0) && (a_Rotation < 90))
|
||||
{
|
||||
return 0x4;
|
||||
}
|
||||
@ -58,13 +58,12 @@ public:
|
||||
void ExtendPiston( int, int, int );
|
||||
void RetractPiston( int, int, int );
|
||||
|
||||
cWorld* m_World;
|
||||
cWorld * m_World;
|
||||
|
||||
private:
|
||||
void ChainMove( int, int, int, char, unsigned short * );
|
||||
unsigned short FirstPassthroughBlock( int, int, int, char );
|
||||
|
||||
};
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
@ -843,7 +843,7 @@ void cPlayer::TossItem(
|
||||
}
|
||||
}
|
||||
}
|
||||
float vX = 0, vY = 0, vZ = 0;
|
||||
double vX = 0, vY = 0, vZ = 0;
|
||||
EulerToVector(-GetRotation(), GetPitch(), vZ, vX, vY);
|
||||
vY = -vY * 2 + 1.f;
|
||||
m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY() + 1.6f, GetPosZ(), vX * 2, vY * 2, vZ * 2);
|
||||
|
@ -556,8 +556,8 @@ void cProtocol125::SendPlayerMoveLook(void)
|
||||
WriteDouble(Player->GetStance() + 0.03); // Add a small amount so that the player doesn't start inside a block
|
||||
WriteDouble(Player->GetPosY() + 0.03); // Add a small amount so that the player doesn't start inside a block
|
||||
WriteDouble(Player->GetPosZ());
|
||||
WriteFloat (Player->GetRotation());
|
||||
WriteFloat (Player->GetPitch());
|
||||
WriteFloat ((float)(Player->GetRotation()));
|
||||
WriteFloat ((float)(Player->GetPitch()));
|
||||
WriteBool (Player->IsOnGround());
|
||||
Flush();
|
||||
}
|
||||
|
@ -1,32 +1,44 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
class cSign // tolua_export
|
||||
{ // tolua_export
|
||||
|
||||
|
||||
|
||||
|
||||
// tolua_begin
|
||||
class cSign
|
||||
{
|
||||
public:
|
||||
static char RotationToMetaData( float a_Rotation ) // tolua_export
|
||||
{ // tolua_export
|
||||
a_Rotation += 180 + (180/16); // So its not aligned with axis
|
||||
if( a_Rotation > 360.f ) a_Rotation -= 360.f;
|
||||
static char RotationToMetaData(double a_Rotation)
|
||||
{
|
||||
a_Rotation += 180 + (180 / 16); // So it's not aligned with axis
|
||||
if (a_Rotation > 360)
|
||||
{
|
||||
a_Rotation -= 360;
|
||||
}
|
||||
|
||||
a_Rotation = (a_Rotation/360) * 16;
|
||||
a_Rotation = (a_Rotation / 360) * 16;
|
||||
|
||||
return ((char)a_Rotation) % 16;
|
||||
} // tolua_export
|
||||
static char DirectionToMetaData( char a_Direction ) // tolua_export
|
||||
{ // tolua_export
|
||||
switch( a_Direction )
|
||||
}
|
||||
|
||||
|
||||
static char DirectionToMetaData(char a_Direction)
|
||||
{
|
||||
switch (a_Direction)
|
||||
{
|
||||
case 0x2:
|
||||
return 0x2;
|
||||
case 0x3:
|
||||
return 0x3;
|
||||
case 0x4:
|
||||
return 0x4;
|
||||
case 0x5:
|
||||
return 0x5;
|
||||
default:
|
||||
break;
|
||||
case 0x2: return 0x2;
|
||||
case 0x3: return 0x3;
|
||||
case 0x4: return 0x4;
|
||||
case 0x5: return 0x5;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
return 0x2;
|
||||
}
|
||||
}; // tolua_export
|
||||
} ;
|
||||
// tolua_end
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1015,15 +1015,15 @@ bool cRedstoneSimulator::IsRepeaterPointingAway(const Vector3i & a_RepeaterPos,
|
||||
|
||||
|
||||
|
||||
NIBBLETYPE cRedstoneSimulator::RepeaterRotationToMetaData(float a_Rotation)
|
||||
NIBBLETYPE cRedstoneSimulator::RepeaterRotationToMetaData(double a_Rotation)
|
||||
{
|
||||
a_Rotation += 90 + 45; // So its not aligned with axis
|
||||
if (a_Rotation > 360.f)
|
||||
if (a_Rotation > 360)
|
||||
{
|
||||
a_Rotation -= 360.f;
|
||||
a_Rotation -= 360;
|
||||
}
|
||||
|
||||
if ((a_Rotation >= 0.f) && (a_Rotation < 90.f))
|
||||
if ((a_Rotation >= 0) && (a_Rotation < 90))
|
||||
{
|
||||
return 0x1;
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ public:
|
||||
|
||||
static bool IsRepeaterPointingTo (const Vector3i & a_RepeaterPos, char a_MetaData, const Vector3i & a_BlockPos);
|
||||
static bool IsRepeaterPointingAway(const Vector3i & a_RepeaterPos, char a_MetaData, const Vector3i & a_BlockPos);
|
||||
static NIBBLETYPE RepeaterRotationToMetaData(float a_Rotation);
|
||||
static NIBBLETYPE RepeaterRotationToMetaData(double a_Rotation);
|
||||
static Vector3i GetRepeaterDirection(NIBBLETYPE a_MetaData);
|
||||
static NIBBLETYPE LeverDirectionToMetaData(char a_Dir);
|
||||
static bool IsLeverOn(cWorld * a_World, const Vector3i & a_BlockPos);
|
||||
|
@ -5,19 +5,21 @@
|
||||
|
||||
|
||||
|
||||
class cStairs // tolua_export
|
||||
{ // tolua_export
|
||||
// tolua_begin
|
||||
|
||||
class cStairs
|
||||
{
|
||||
public:
|
||||
/// Converts player rotation to stair rotation metadata. To get upside-down stairs, OR with 0x4
|
||||
static NIBBLETYPE RotationToMetaData(float a_Rotation) // tolua_export
|
||||
{ // tolua_export
|
||||
a_Rotation += 90 + 45; // So its not aligned with axis
|
||||
NIBBLETYPE result = 0x0;
|
||||
if (a_Rotation > 360.f)
|
||||
static NIBBLETYPE RotationToMetaData(double a_Rotation)
|
||||
{
|
||||
a_Rotation += 90 + 45; // So its not aligned with axis
|
||||
NIBBLETYPE result = 0x0;
|
||||
if (a_Rotation > 360)
|
||||
{
|
||||
a_Rotation -= 360.f;
|
||||
a_Rotation -= 360;
|
||||
}
|
||||
if ((a_Rotation >= 0.f) && (a_Rotation < 90.f))
|
||||
if ((a_Rotation >= 0) && (a_Rotation < 90))
|
||||
{
|
||||
return 0x0;
|
||||
}
|
||||
@ -33,9 +35,10 @@ public:
|
||||
{
|
||||
return 0x3;
|
||||
}
|
||||
} // tolua_export
|
||||
} ; // tolua_export
|
||||
|
||||
}
|
||||
} ;
|
||||
|
||||
// tolua_end
|
||||
|
||||
|
||||
|
||||
|
@ -764,7 +764,7 @@ void cSlotAreaTemporary::TossItems(cPlayer & a_Player, int a_Begin, int a_End)
|
||||
Item.Empty();
|
||||
} // for i - itr->second[]
|
||||
|
||||
float vX = 0, vY = 0, vZ = 0;
|
||||
double vX = 0, vY = 0, vZ = 0;
|
||||
EulerToVector(-a_Player.GetRotation(), a_Player.GetPitch(), vZ, vX, vY);
|
||||
vY = -vY * 2 + 1.f;
|
||||
a_Player.GetWorld()->SpawnItemPickups(Drops, a_Player.GetPosX(), a_Player.GetPosY() + 1.6f, a_Player.GetPosZ(), vX * 2, vY * 2, vZ * 2);
|
||||
|
@ -385,9 +385,10 @@ void cFastNBTWriter::BeginList(const AString & a_Name, eTagType a_ChildrenType)
|
||||
m_Result.append(4, (char)0);
|
||||
|
||||
++m_CurrentStack;
|
||||
m_Stack[m_CurrentStack].m_Type = TAG_List;
|
||||
m_Stack[m_CurrentStack].m_Pos = m_Result.size() - 4;
|
||||
m_Stack[m_CurrentStack].m_Count = 0;
|
||||
m_Stack[m_CurrentStack].m_Type = TAG_List;
|
||||
m_Stack[m_CurrentStack].m_Pos = m_Result.size() - 4;
|
||||
m_Stack[m_CurrentStack].m_Count = 0;
|
||||
m_Stack[m_CurrentStack].m_ItemType = a_ChildrenType;
|
||||
}
|
||||
|
||||
|
||||
|
@ -247,6 +247,7 @@ protected:
|
||||
int m_Type; // TAG_Compound or TAG_List
|
||||
int m_Pos; // for TAG_List, the position of the list count
|
||||
int m_Count; // for TAG_List, the element count
|
||||
eTagType m_ItemType; // for TAG_List, the element type
|
||||
} ;
|
||||
|
||||
static const int MAX_STACK = 50; // Highliy doubtful that an NBT would be constructed this many levels deep
|
||||
@ -263,6 +264,9 @@ protected:
|
||||
|
||||
inline void TagCommon(const AString & a_Name, eTagType a_Type)
|
||||
{
|
||||
// If we're directly inside a list, check that the list is of the correct type:
|
||||
ASSERT((m_Stack[m_CurrentStack].m_Type != TAG_List) || (m_Stack[m_CurrentStack].m_ItemType == a_Type));
|
||||
|
||||
if (IsStackTopCompound())
|
||||
{
|
||||
// Compound: add the type and name:
|
||||
|
417
source/WorldStorage/NBTChunkSerializer.cpp
Normal file
417
source/WorldStorage/NBTChunkSerializer.cpp
Normal file
@ -0,0 +1,417 @@
|
||||
|
||||
// NBTChunkSerializer.cpp
|
||||
|
||||
|
||||
#include "Globals.h"
|
||||
#include "NBTChunkSerializer.h"
|
||||
#include "../BlockID.h"
|
||||
#include "../ChestEntity.h"
|
||||
#include "../DispenserEntity.h"
|
||||
#include "../FurnaceEntity.h"
|
||||
#include "../SignEntity.h"
|
||||
#include "../NoteEntity.h"
|
||||
#include "../JukeboxEntity.h"
|
||||
#include "../Item.h"
|
||||
#include "../StringCompression.h"
|
||||
#include "../Entity.h"
|
||||
#include "../OSSupport/MakeDir.h"
|
||||
#include "FastNBT.h"
|
||||
#include "../FallingBlock.h"
|
||||
#include "../Minecart.h"
|
||||
#include "../Mobs/Monster.h"
|
||||
#include "../Pickup.h"
|
||||
|
||||
|
||||
|
||||
|
||||
cNBTChunkSerializer::cNBTChunkSerializer(cFastNBTWriter & a_Writer) :
|
||||
m_BiomesAreValid(false),
|
||||
m_Writer(a_Writer),
|
||||
m_IsTagOpen(false),
|
||||
m_HasHadEntity(false),
|
||||
m_HasHadBlockEntity(false),
|
||||
m_IsLightValid(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cNBTChunkSerializer::Finish(void)
|
||||
{
|
||||
if (m_IsTagOpen)
|
||||
{
|
||||
m_Writer.EndList();
|
||||
}
|
||||
|
||||
// If light not valid, reset it to all zeroes:
|
||||
if (!m_IsLightValid)
|
||||
{
|
||||
memset(m_BlockLight, 0, sizeof(m_BlockLight));
|
||||
memset(m_BlockSkyLight, 0, sizeof(m_BlockSkyLight));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cNBTChunkSerializer::AddItem(const cItem & a_Item, int a_Slot, const AString & a_CompoundName)
|
||||
{
|
||||
m_Writer.BeginCompound(a_CompoundName);
|
||||
m_Writer.AddShort("id", (short)(a_Item.m_ItemType));
|
||||
m_Writer.AddShort("Damage", a_Item.m_ItemDamage);
|
||||
m_Writer.AddByte ("Count", a_Item.m_ItemCount);
|
||||
if (a_Slot >= 0)
|
||||
{
|
||||
m_Writer.AddByte ("Slot", (unsigned char)a_Slot);
|
||||
}
|
||||
m_Writer.EndCompound();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cNBTChunkSerializer::AddBasicTileEntity(cBlockEntity * a_Entity, const char * a_EntityTypeID)
|
||||
{
|
||||
m_Writer.AddInt ("x", a_Entity->GetPosX());
|
||||
m_Writer.AddInt ("y", a_Entity->GetPosY());
|
||||
m_Writer.AddInt ("z", a_Entity->GetPosZ());
|
||||
m_Writer.AddString("id", a_EntityTypeID);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cNBTChunkSerializer::AddChestEntity(cChestEntity * a_Entity)
|
||||
{
|
||||
m_Writer.BeginCompound("");
|
||||
AddBasicTileEntity(a_Entity, "Chest");
|
||||
m_Writer.BeginList("Items", TAG_Compound);
|
||||
for (int i = 0; i < cChestEntity::c_ChestHeight * cChestEntity::c_ChestWidth; i++)
|
||||
{
|
||||
const cItem * Item = a_Entity->GetSlot(i);
|
||||
if ((Item == NULL) || Item->IsEmpty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
AddItem(*Item, i);
|
||||
} // for i - chest slots[]
|
||||
m_Writer.EndList();
|
||||
m_Writer.EndCompound();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cNBTChunkSerializer::AddDispenserEntity(cDispenserEntity * a_Entity)
|
||||
{
|
||||
m_Writer.BeginCompound("");
|
||||
AddBasicTileEntity(a_Entity, "Trap");
|
||||
m_Writer.BeginList("Items", TAG_Compound);
|
||||
for (int i = 0; i < 9; i++)
|
||||
{
|
||||
const cItem * Item = a_Entity->GetSlot(i);
|
||||
if ((Item == NULL) || Item->IsEmpty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
AddItem(*Item, i);
|
||||
} // for i - contents[]
|
||||
m_Writer.EndList();
|
||||
m_Writer.EndCompound();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cNBTChunkSerializer::AddFurnaceEntity(cFurnaceEntity * a_Furnace)
|
||||
{
|
||||
m_Writer.BeginCompound("");
|
||||
AddBasicTileEntity(a_Furnace, "Furnace");
|
||||
m_Writer.BeginList("Items", TAG_Compound);
|
||||
AddItem(*(a_Furnace->GetSlot(0)), 0);
|
||||
AddItem(*(a_Furnace->GetSlot(1)), 1);
|
||||
AddItem(*(a_Furnace->GetSlot(2)), 2);
|
||||
m_Writer.EndList();
|
||||
m_Writer.AddShort("BurnTime", (Int16)(a_Furnace->GetTimeToBurn() / 50.0));
|
||||
m_Writer.AddShort("CookTime", (Int16)(a_Furnace->GetTimeCooked() / 50.0));
|
||||
m_Writer.EndCompound();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cNBTChunkSerializer::AddSignEntity(cSignEntity * a_Sign)
|
||||
{
|
||||
m_Writer.BeginCompound("");
|
||||
AddBasicTileEntity(a_Sign, "Sign");
|
||||
m_Writer.AddString("Text1", a_Sign->GetLine(0));
|
||||
m_Writer.AddString("Text2", a_Sign->GetLine(1));
|
||||
m_Writer.AddString("Text3", a_Sign->GetLine(2));
|
||||
m_Writer.AddString("Text4", a_Sign->GetLine(3));
|
||||
m_Writer.EndCompound();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cNBTChunkSerializer::AddNoteEntity(cNoteEntity * a_Note)
|
||||
{
|
||||
m_Writer.BeginCompound("");
|
||||
AddBasicTileEntity(a_Note, "Music");
|
||||
m_Writer.AddByte("note", a_Note->GetPitch());
|
||||
m_Writer.EndCompound();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cNBTChunkSerializer::AddJukeboxEntity(cJukeboxEntity * a_Jukebox)
|
||||
{
|
||||
m_Writer.BeginCompound("");
|
||||
AddBasicTileEntity(a_Jukebox, "RecordPlayer");
|
||||
m_Writer.AddInt("Record", a_Jukebox->GetRecord());
|
||||
m_Writer.EndCompound();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cNBTChunkSerializer::AddBasicEntity(cEntity * a_Entity, const AString & a_ClassName)
|
||||
{
|
||||
m_Writer.AddString("id", a_ClassName);
|
||||
m_Writer.BeginList("Pos", TAG_Double);
|
||||
m_Writer.AddDouble("", a_Entity->GetPosX());
|
||||
m_Writer.AddDouble("", a_Entity->GetPosY());
|
||||
m_Writer.AddDouble("", a_Entity->GetPosZ());
|
||||
m_Writer.EndList();
|
||||
m_Writer.BeginList("Motion", TAG_Double);
|
||||
m_Writer.AddDouble("", a_Entity->GetSpeedX());
|
||||
m_Writer.AddDouble("", a_Entity->GetSpeedY());
|
||||
m_Writer.AddDouble("", a_Entity->GetSpeedZ());
|
||||
m_Writer.EndList();
|
||||
m_Writer.BeginList("Rotation", TAG_Double);
|
||||
m_Writer.AddDouble("", a_Entity->GetRotation());
|
||||
m_Writer.AddDouble("", a_Entity->GetPitch());
|
||||
m_Writer.EndList();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cNBTChunkSerializer::AddFallingBlockEntity(cFallingBlock * a_FallingBlock)
|
||||
{
|
||||
m_Writer.BeginCompound("");
|
||||
AddBasicEntity(a_FallingBlock, "FallingSand");
|
||||
m_Writer.AddInt("TileID", a_FallingBlock->GetBlockType());
|
||||
m_Writer.AddByte("Data", a_FallingBlock->GetBlockMeta());
|
||||
m_Writer.AddByte("Time", 1); // Unused in MCServer, Vanilla said to need nonzero
|
||||
m_Writer.AddByte("DropItem", 1);
|
||||
m_Writer.AddByte("HurtEntities", a_FallingBlock->GetBlockType() == E_BLOCK_ANVIL);
|
||||
m_Writer.EndCompound();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cNBTChunkSerializer::AddMinecartEntity(cMinecart * a_Minecart)
|
||||
{
|
||||
const char * EntityClass = NULL;
|
||||
switch (a_Minecart->GetPayload())
|
||||
{
|
||||
case cMinecart::mpNone: EntityClass = "MinecarRideable"; break;
|
||||
case cMinecart::mpChest: EntityClass = "MinecartChest"; break;
|
||||
case cMinecart::mpFurnace: EntityClass = "MinecartFurnace"; break;
|
||||
default:
|
||||
{
|
||||
ASSERT(!"Unhandled minecart payload type");
|
||||
return;
|
||||
}
|
||||
} // switch (payload)
|
||||
|
||||
m_Writer.BeginCompound("");
|
||||
AddBasicEntity(a_Minecart, EntityClass);
|
||||
switch (a_Minecart->GetPayload())
|
||||
{
|
||||
case cMinecart::mpChest:
|
||||
{
|
||||
// Add chest contents into the Items tag:
|
||||
AddMinecartChestContents((cMinecartWithChest *)a_Minecart);
|
||||
break;
|
||||
}
|
||||
|
||||
case cMinecart::mpFurnace:
|
||||
{
|
||||
// TODO: Add "Push" and "Fuel" tags
|
||||
break;
|
||||
}
|
||||
} // switch (Payload)
|
||||
m_Writer.EndCompound();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cNBTChunkSerializer::AddMonsterEntity(cMonster * a_Monster)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cNBTChunkSerializer::AddPickupEntity(cPickup * a_Pickup)
|
||||
{
|
||||
m_Writer.BeginCompound("");
|
||||
AddBasicEntity(a_Pickup, "Item");
|
||||
AddItem(a_Pickup->GetItem(), -1, "Item");
|
||||
m_Writer.AddShort("Health", a_Pickup->GetHealth());
|
||||
m_Writer.AddShort("Age", a_Pickup->GetAge());
|
||||
m_Writer.EndCompound();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cNBTChunkSerializer::AddMinecartChestContents(cMinecartWithChest * a_Minecart)
|
||||
{
|
||||
m_Writer.BeginList("Items", TAG_Compound);
|
||||
for (int i = 0; i < cMinecartWithChest::NumSlots; i++)
|
||||
{
|
||||
const cItem & Item = a_Minecart->GetItem(i);
|
||||
if (Item.IsEmpty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
AddItem(Item, i);
|
||||
}
|
||||
m_Writer.EndList();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cNBTChunkSerializer::LightIsValid(bool a_IsLightValid)
|
||||
{
|
||||
m_IsLightValid = a_IsLightValid;
|
||||
return a_IsLightValid; // We want lighting only if it's valid, otherwise don't bother
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cNBTChunkSerializer::BiomeData(const cChunkDef::BiomeMap * a_BiomeMap)
|
||||
{
|
||||
memcpy(m_Biomes, a_BiomeMap, sizeof(m_Biomes));
|
||||
for (int i = 0; i < ARRAYCOUNT(m_Biomes); i++)
|
||||
{
|
||||
if ((*a_BiomeMap)[i] < 255)
|
||||
{
|
||||
// Normal MC biome, copy as-is:
|
||||
m_VanillaBiomes[i] = (unsigned char)((*a_BiomeMap)[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: MCS-specific biome, need to map to some basic MC biome:
|
||||
ASSERT(!"Unimplemented MCS-specific biome");
|
||||
return;
|
||||
}
|
||||
} // for i - m_BiomeMap[]
|
||||
m_BiomesAreValid = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cNBTChunkSerializer::Entity(cEntity * a_Entity)
|
||||
{
|
||||
// Add entity into NBT:
|
||||
if (m_IsTagOpen)
|
||||
{
|
||||
if (!m_HasHadEntity)
|
||||
{
|
||||
m_Writer.EndList();
|
||||
m_Writer.BeginList("Entities", TAG_Compound);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Writer.BeginList("Entities", TAG_Compound);
|
||||
}
|
||||
m_IsTagOpen = true;
|
||||
m_HasHadEntity = true;
|
||||
|
||||
switch (a_Entity->GetEntityType())
|
||||
{
|
||||
case cEntity::etFallingBlock: AddFallingBlockEntity((cFallingBlock *)a_Entity); break;
|
||||
case cEntity::etMinecart: AddMinecartEntity ((cMinecart *) a_Entity); break;
|
||||
case cEntity::etMonster: AddMonsterEntity ((cMonster *) a_Entity); break;
|
||||
case cEntity::etPickup: AddPickupEntity ((cPickup *) a_Entity); break;
|
||||
case cEntity::etPlayer: return; // Players aren't saved into the world
|
||||
default:
|
||||
{
|
||||
ASSERT(!"Unhandled entity type is being saved");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cNBTChunkSerializer::BlockEntity(cBlockEntity * a_Entity)
|
||||
{
|
||||
if (m_IsTagOpen)
|
||||
{
|
||||
if (!m_HasHadBlockEntity)
|
||||
{
|
||||
m_Writer.EndList();
|
||||
m_Writer.BeginList("TileEntities", TAG_Compound);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Writer.BeginList("TileEntities", TAG_Compound);
|
||||
}
|
||||
m_IsTagOpen = true;
|
||||
|
||||
// Add tile-entity into NBT:
|
||||
switch (a_Entity->GetBlockType())
|
||||
{
|
||||
case E_BLOCK_CHEST: AddChestEntity ((cChestEntity *) a_Entity); break;
|
||||
case E_BLOCK_DISPENSER: AddDispenserEntity ((cDispenserEntity *) a_Entity); break;
|
||||
case E_BLOCK_FURNACE: AddFurnaceEntity ((cFurnaceEntity *) a_Entity); break;
|
||||
case E_BLOCK_SIGN_POST:
|
||||
case E_BLOCK_WALLSIGN: AddSignEntity ((cSignEntity *) a_Entity); break;
|
||||
case E_BLOCK_NOTE_BLOCK: AddNoteEntity ((cNoteEntity *) a_Entity); break;
|
||||
case E_BLOCK_JUKEBOX: AddJukeboxEntity ((cJukeboxEntity *) a_Entity); break;
|
||||
default:
|
||||
{
|
||||
ASSERT(!"Unhandled block entity saved into Anvil");
|
||||
}
|
||||
}
|
||||
m_HasHadBlockEntity = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
101
source/WorldStorage/NBTChunkSerializer.h
Normal file
101
source/WorldStorage/NBTChunkSerializer.h
Normal file
@ -0,0 +1,101 @@
|
||||
|
||||
// NBTChunkSerializer.h
|
||||
|
||||
// Declares the cNBTChunkSerializer class that is used for saving individual chunks into NBT format used by Anvil
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../ChunkDef.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// fwd:
|
||||
class cFastNBTWriter;
|
||||
class cEntity;
|
||||
class cBlockEntity;
|
||||
class cChestEntity;
|
||||
class cFurnaceEntity;
|
||||
class cDispenserEntity;
|
||||
class cSignEntity;
|
||||
class cNoteEntity;
|
||||
class cJukeboxEntity;
|
||||
class cFallingBlock;
|
||||
class cMinecart;
|
||||
class cMinecartWithChest;
|
||||
class cMinecartWithFurnace;
|
||||
class cMonster;
|
||||
class cPickup;
|
||||
|
||||
|
||||
|
||||
|
||||
class cNBTChunkSerializer :
|
||||
public cChunkDataSeparateCollector
|
||||
{
|
||||
public:
|
||||
cChunkDef::BiomeMap m_Biomes;
|
||||
unsigned char m_VanillaBiomes[cChunkDef::Width * cChunkDef::Width];
|
||||
bool m_BiomesAreValid;
|
||||
|
||||
|
||||
cNBTChunkSerializer(cFastNBTWriter & a_Writer);
|
||||
|
||||
/// Close NBT tags that we've opened
|
||||
void Finish(void);
|
||||
|
||||
bool IsLightValid(void) const {return m_IsLightValid; }
|
||||
|
||||
protected:
|
||||
|
||||
/* From cChunkDataSeparateCollector we inherit:
|
||||
- m_BlockTypes[]
|
||||
- m_BlockMetas[]
|
||||
- m_BlockLight[]
|
||||
- m_BlockSkyLight[]
|
||||
*/
|
||||
|
||||
cFastNBTWriter & m_Writer;
|
||||
|
||||
bool m_IsTagOpen; // True if a tag has been opened in the callbacks and not yet closed.
|
||||
bool m_HasHadEntity; // True if any Entity has already been received and processed
|
||||
bool m_HasHadBlockEntity; // True if any BlockEntity has already been received and processed
|
||||
bool m_IsLightValid; // True if the chunk lighting is valid
|
||||
|
||||
|
||||
/// Writes an item into the writer, if slot >= 0, adds the Slot tag. The compound is named as requested.
|
||||
void AddItem(const cItem & a_Item, int a_Slot, const AString & a_CompoundName = "");
|
||||
|
||||
// Block entities:
|
||||
void AddBasicTileEntity(cBlockEntity * a_Entity, const char * a_EntityTypeID);
|
||||
void AddChestEntity(cChestEntity * a_Entity);
|
||||
void AddDispenserEntity(cDispenserEntity * a_Entity);
|
||||
void AddFurnaceEntity(cFurnaceEntity * a_Furnace);
|
||||
void AddSignEntity(cSignEntity * a_Sign);
|
||||
void AddNoteEntity(cNoteEntity * a_Note);
|
||||
void AddJukeboxEntity(cJukeboxEntity * a_Jukebox);
|
||||
void AddBasicEntity(cEntity * a_Entity, const AString & a_ClassName);
|
||||
|
||||
// Entities:
|
||||
void AddFallingBlockEntity(cFallingBlock * a_FallingBlock);
|
||||
void AddMinecartEntity (cMinecart * a_Minecart);
|
||||
void AddMonsterEntity (cMonster * a_Monster);
|
||||
void AddPickupEntity (cPickup * a_Pickup);
|
||||
|
||||
void AddMinecartChestContents(cMinecartWithChest * a_Minecart);
|
||||
|
||||
// cChunkDataSeparateCollector overrides:
|
||||
virtual bool LightIsValid(bool a_IsLightValid) override;
|
||||
virtual void BiomeData(const cChunkDef::BiomeMap * a_BiomeMap) override;
|
||||
virtual void Entity(cEntity * a_Entity) override;
|
||||
virtual void BlockEntity(cBlockEntity * a_Entity) override;
|
||||
} ; // class cNBTChunkSerializer
|
||||
|
||||
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
#include "Globals.h"
|
||||
#include "WSSAnvil.h"
|
||||
#include "NBTChunkSerializer.h"
|
||||
#include "../World.h"
|
||||
#include "zlib.h"
|
||||
#include "../BlockID.h"
|
||||
@ -19,6 +20,10 @@
|
||||
#include "../Entity.h"
|
||||
#include "../OSSupport/MakeDir.h"
|
||||
#include "FastNBT.h"
|
||||
#include "../FallingBlock.h"
|
||||
#include "../Minecart.h"
|
||||
#include "../Mobs/Monster.h"
|
||||
#include "../Pickup.h"
|
||||
|
||||
|
||||
|
||||
@ -37,238 +42,6 @@ Since only the header is actually in the memory, this number can be high, but st
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// cNBTChunkSerializer
|
||||
|
||||
class cNBTChunkSerializer :
|
||||
public cChunkDataSeparateCollector
|
||||
{
|
||||
public:
|
||||
cChunkDef::BiomeMap m_Biomes;
|
||||
unsigned char m_VanillaBiomes[cChunkDef::Width * cChunkDef::Width];
|
||||
bool m_BiomesAreValid;
|
||||
|
||||
|
||||
cNBTChunkSerializer(cFastNBTWriter & a_Writer) :
|
||||
m_BiomesAreValid(false),
|
||||
m_Writer(a_Writer),
|
||||
m_IsTagOpen(false),
|
||||
m_HasHadEntity(false),
|
||||
m_HasHadBlockEntity(false),
|
||||
m_IsLightValid(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// Close NBT tags that we've opened
|
||||
void Finish(void)
|
||||
{
|
||||
if (m_IsTagOpen)
|
||||
{
|
||||
m_Writer.EndList();
|
||||
}
|
||||
|
||||
// If light not valid, reset it to all zeroes:
|
||||
if (!m_IsLightValid)
|
||||
{
|
||||
memset(m_BlockLight, 0, sizeof(m_BlockLight));
|
||||
memset(m_BlockSkyLight, 0, sizeof(m_BlockSkyLight));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool IsLightValid(void) const {return m_IsLightValid; }
|
||||
|
||||
protected:
|
||||
|
||||
/* From cChunkDataSeparateCollector we inherit:
|
||||
- m_BlockTypes[]
|
||||
- m_BlockMetas[]
|
||||
- m_BlockLight[]
|
||||
- m_BlockSkyLight[]
|
||||
*/
|
||||
|
||||
cFastNBTWriter & m_Writer;
|
||||
|
||||
bool m_IsTagOpen; // True if a tag has been opened in the callbacks and not yet closed.
|
||||
bool m_HasHadEntity; // True if any Entity has already been received and processed
|
||||
bool m_HasHadBlockEntity; // True if any BlockEntity has already been received and processed
|
||||
bool m_IsLightValid; // True if the chunk lighting is valid
|
||||
|
||||
|
||||
void AddBasicTileEntity(cBlockEntity * a_Entity, const char * a_EntityTypeID)
|
||||
{
|
||||
m_Writer.AddInt ("x", a_Entity->GetPosX());
|
||||
m_Writer.AddInt ("y", a_Entity->GetPosY());
|
||||
m_Writer.AddInt ("z", a_Entity->GetPosZ());
|
||||
m_Writer.AddString("id", a_EntityTypeID);
|
||||
}
|
||||
|
||||
|
||||
void AddItem(const cItem * a_Item, int a_Slot)
|
||||
{
|
||||
m_Writer.BeginCompound("");
|
||||
m_Writer.AddShort("id", (short)(a_Item->m_ItemType));
|
||||
m_Writer.AddShort("Damage", a_Item->m_ItemDamage);
|
||||
m_Writer.AddByte ("Count", a_Item->m_ItemCount);
|
||||
m_Writer.AddByte ("Slot", (unsigned char)a_Slot);
|
||||
m_Writer.EndCompound();
|
||||
}
|
||||
|
||||
|
||||
void AddChestEntity(cChestEntity * a_Entity)
|
||||
{
|
||||
m_Writer.BeginCompound("");
|
||||
AddBasicTileEntity(a_Entity, "Chest");
|
||||
m_Writer.BeginList("Items", TAG_Compound);
|
||||
for (int i = 0; i < cChestEntity::c_ChestHeight * cChestEntity::c_ChestWidth; i++)
|
||||
{
|
||||
const cItem * Item = a_Entity->GetSlot(i);
|
||||
if ((Item == NULL) || Item->IsEmpty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
AddItem(Item, i);
|
||||
}
|
||||
m_Writer.EndList();
|
||||
m_Writer.EndCompound();
|
||||
}
|
||||
|
||||
|
||||
void AddDispenserEntity(cDispenserEntity * a_Entity)
|
||||
{
|
||||
m_Writer.BeginCompound("");
|
||||
AddBasicTileEntity(a_Entity, "Trap");
|
||||
m_Writer.BeginList("Items", TAG_Compound);
|
||||
for (int i = 0; i < 9; i++)
|
||||
{
|
||||
const cItem * Item = a_Entity->GetSlot(i);
|
||||
if ((Item == NULL) || Item->IsEmpty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
AddItem(Item, i);
|
||||
}
|
||||
m_Writer.EndList();
|
||||
m_Writer.EndCompound();
|
||||
}
|
||||
|
||||
|
||||
void AddFurnaceEntity(cFurnaceEntity * a_Furnace)
|
||||
{
|
||||
m_Writer.BeginCompound("");
|
||||
AddBasicTileEntity(a_Furnace, "Furnace");
|
||||
m_Writer.BeginList("Items", TAG_Compound);
|
||||
AddItem(a_Furnace->GetSlot(0), 0);
|
||||
AddItem(a_Furnace->GetSlot(1), 1);
|
||||
AddItem(a_Furnace->GetSlot(2), 2);
|
||||
m_Writer.EndList();
|
||||
m_Writer.AddShort("BurnTime", (Int16)(a_Furnace->GetTimeToBurn() / 50.0));
|
||||
m_Writer.AddShort("CookTime", (Int16)(a_Furnace->GetTimeCooked() / 50.0));
|
||||
m_Writer.EndCompound();
|
||||
}
|
||||
|
||||
|
||||
void AddSignEntity(cSignEntity * a_Sign)
|
||||
{
|
||||
m_Writer.BeginCompound("");
|
||||
AddBasicTileEntity(a_Sign, "Sign");
|
||||
m_Writer.AddString("Text1", a_Sign->GetLine(0));
|
||||
m_Writer.AddString("Text2", a_Sign->GetLine(1));
|
||||
m_Writer.AddString("Text3", a_Sign->GetLine(2));
|
||||
m_Writer.AddString("Text4", a_Sign->GetLine(3));
|
||||
m_Writer.EndCompound();
|
||||
}
|
||||
|
||||
void AddNoteEntity(cNoteEntity * a_Note)
|
||||
{
|
||||
m_Writer.BeginCompound("");
|
||||
AddBasicTileEntity(a_Note, "Music");
|
||||
m_Writer.AddByte("note", a_Note->GetPitch());
|
||||
m_Writer.EndCompound();
|
||||
}
|
||||
|
||||
void AddJukeboxEntity(cJukeboxEntity * a_Jukebox)
|
||||
{
|
||||
m_Writer.BeginCompound("");
|
||||
AddBasicTileEntity(a_Jukebox, "RecordPlayer");
|
||||
m_Writer.AddInt("Record", a_Jukebox->GetRecord());
|
||||
m_Writer.EndCompound();
|
||||
}
|
||||
|
||||
virtual bool LightIsValid(bool a_IsLightValid) override
|
||||
{
|
||||
m_IsLightValid = a_IsLightValid;
|
||||
return a_IsLightValid; // We want lighting only if it's valid, otherwise don't bother
|
||||
}
|
||||
|
||||
|
||||
virtual void BiomeData(const cChunkDef::BiomeMap * a_BiomeMap) override
|
||||
{
|
||||
memcpy(m_Biomes, a_BiomeMap, sizeof(m_Biomes));
|
||||
for (int i = 0; i < ARRAYCOUNT(m_Biomes); i++)
|
||||
{
|
||||
if ((*a_BiomeMap)[i] < 255)
|
||||
{
|
||||
// Normal MC biome, copy as-is:
|
||||
m_VanillaBiomes[i] = (unsigned char)((*a_BiomeMap)[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: MCS-specific biome, need to map to some basic MC biome:
|
||||
ASSERT(!"Unimplemented MCS-specific biome");
|
||||
return;
|
||||
}
|
||||
} // for i - m_BiomeMap[]
|
||||
m_BiomesAreValid = true;
|
||||
}
|
||||
|
||||
|
||||
virtual void Entity(cEntity * a_Entity) override
|
||||
{
|
||||
// TODO: Add entity into NBT:
|
||||
}
|
||||
|
||||
|
||||
virtual void BlockEntity(cBlockEntity * a_Entity)
|
||||
{
|
||||
if (m_IsTagOpen)
|
||||
{
|
||||
if (!m_HasHadBlockEntity)
|
||||
{
|
||||
m_Writer.EndList();
|
||||
m_Writer.BeginList("TileEntities", TAG_Compound);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Writer.BeginList("TileEntities", TAG_Compound);
|
||||
}
|
||||
m_IsTagOpen = true;
|
||||
|
||||
// Add tile-entity into NBT:
|
||||
switch (a_Entity->GetBlockType())
|
||||
{
|
||||
case E_BLOCK_CHEST: AddChestEntity ((cChestEntity *) a_Entity); break;
|
||||
case E_BLOCK_DISPENSER: AddDispenserEntity ((cDispenserEntity *) a_Entity); break;
|
||||
case E_BLOCK_FURNACE: AddFurnaceEntity ((cFurnaceEntity *) a_Entity); break;
|
||||
case E_BLOCK_SIGN_POST:
|
||||
case E_BLOCK_WALLSIGN: AddSignEntity ((cSignEntity *) a_Entity); break;
|
||||
case E_BLOCK_NOTE_BLOCK: AddNoteEntity ((cNoteEntity *) a_Entity); break;
|
||||
case E_BLOCK_JUKEBOX: AddJukeboxEntity ((cJukeboxEntity *) a_Entity); break;
|
||||
default:
|
||||
{
|
||||
ASSERT(!"Unhandled block entity saved into Anvil");
|
||||
}
|
||||
}
|
||||
m_HasHadBlockEntity = true;
|
||||
}
|
||||
} ; // class cNBTChunkSerializer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// cWSSAnvil:
|
||||
|
||||
@ -378,6 +151,9 @@ bool cWSSAnvil::SetChunkData(const cChunkCoords & a_Chunk, const AString & a_Dat
|
||||
{
|
||||
return false;
|
||||
}
|
||||
LOGD("Saving chunk [%d, %d] into region file %s",
|
||||
a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, File->GetFileName().c_str()
|
||||
);
|
||||
return File->SetChunkData(a_Chunk, a_Data);
|
||||
}
|
||||
|
||||
@ -392,6 +168,10 @@ cWSSAnvil::cMCAFile * cWSSAnvil::LoadMCAFile(const cChunkCoords & a_Chunk)
|
||||
|
||||
const int RegionX = FAST_FLOOR_DIV(a_Chunk.m_ChunkX, 32);
|
||||
const int RegionZ = FAST_FLOOR_DIV(a_Chunk.m_ChunkZ, 32);
|
||||
ASSERT(a_Chunk.m_ChunkX - RegionX * 32 >= 0);
|
||||
ASSERT(a_Chunk.m_ChunkZ - RegionZ * 32 >= 0);
|
||||
ASSERT(a_Chunk.m_ChunkX - RegionX * 32 < 32);
|
||||
ASSERT(a_Chunk.m_ChunkZ - RegionZ * 32 < 32);
|
||||
|
||||
// Is it already cached?
|
||||
for (cMCAFiles::iterator itr = m_Files.begin(); itr != m_Files.end(); ++itr)
|
||||
@ -478,6 +258,7 @@ bool cWSSAnvil::SaveChunkToData(const cChunkCoords & a_Chunk, AString & a_Data)
|
||||
return false;
|
||||
}
|
||||
Writer.Finish();
|
||||
|
||||
CompressString(Writer.GetResult().data(), Writer.GetResult().size(), a_Data);
|
||||
return true;
|
||||
}
|
||||
@ -719,9 +500,26 @@ cChunkDef::BiomeMap * cWSSAnvil::LoadBiomeMapFromNBT(cChunkDef::BiomeMap * a_Bio
|
||||
|
||||
|
||||
|
||||
void cWSSAnvil::LoadEntitiesFromNBT(cEntityList & a_Entitites, const cParsedNBT & a_NBT, int a_TagIdx)
|
||||
void cWSSAnvil::LoadEntitiesFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
|
||||
{
|
||||
// TODO: Load the entities
|
||||
if ((a_TagIdx < 0) || (a_NBT.GetType(a_TagIdx) != TAG_List))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int Child = a_NBT.GetFirstChild(a_TagIdx); Child != -1; Child = a_NBT.GetNextSibling(Child))
|
||||
{
|
||||
if (a_NBT.GetType(Child) != TAG_Compound)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
int sID = a_NBT.FindChildByName(Child, "id");
|
||||
if (sID < 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
LoadEntityFromNBT(a_Entities, a_NBT, Child, a_NBT.GetData(sID), a_NBT.GetDataLength(sID));
|
||||
} // for Child - a_NBT[]
|
||||
}
|
||||
|
||||
|
||||
@ -778,6 +576,37 @@ void cWSSAnvil::LoadBlockEntitiesFromNBT(cBlockEntityList & a_BlockEntities, con
|
||||
|
||||
|
||||
|
||||
bool cWSSAnvil::LoadItemFromNBT(cItem & a_Item, const cParsedNBT & a_NBT, int a_TagIdx)
|
||||
{
|
||||
int ID = a_NBT.FindChildByName(a_TagIdx, "id");
|
||||
if ((ID < 0) || (a_NBT.GetType(ID) != TAG_Short))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
a_Item.m_ItemType = (ENUM_ITEM_ID)(a_NBT.GetShort(ID));
|
||||
|
||||
int Damage = a_NBT.FindChildByName(a_TagIdx, "Damage");
|
||||
if ((Damage < 0) || (a_NBT.GetType(Damage) != TAG_Short))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
a_Item.m_ItemDamage = a_NBT.GetShort(Damage);
|
||||
|
||||
int Count = a_NBT.FindChildByName(a_TagIdx, "Count");
|
||||
if ((Count < 0) || (a_NBT.GetType(Count) != TAG_Byte))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
a_Item.m_ItemCount = a_NBT.GetByte(Count);
|
||||
|
||||
// TODO: enchantments and other item properties
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cWSSAnvil::LoadChestFromNBT(cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx)
|
||||
{
|
||||
ASSERT(a_NBT.GetType(a_TagIdx) == TAG_Compound);
|
||||
@ -800,25 +629,10 @@ void cWSSAnvil::LoadChestFromNBT(cBlockEntityList & a_BlockEntities, const cPars
|
||||
continue;
|
||||
}
|
||||
cItem Item;
|
||||
int ID = a_NBT.FindChildByName(Child, "id");
|
||||
if ((ID < 0) || (a_NBT.GetType(ID) != TAG_Short))
|
||||
if (LoadItemFromNBT(Item, a_NBT, Child))
|
||||
{
|
||||
continue;
|
||||
Chest->SetSlot(a_NBT.GetByte(Slot), Item);
|
||||
}
|
||||
Item.m_ItemType = (ENUM_ITEM_ID)(a_NBT.GetShort(ID));
|
||||
int Damage = a_NBT.FindChildByName(Child, "Damage");
|
||||
if ((Damage < 0) || (a_NBT.GetType(Damage) != TAG_Short))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Item.m_ItemDamage = a_NBT.GetShort(Damage);
|
||||
int Count = a_NBT.FindChildByName(Child, "Count");
|
||||
if ((Count < 0) || (a_NBT.GetType(Count) != TAG_Byte))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Item.m_ItemCount = a_NBT.GetByte(Count);
|
||||
Chest->SetSlot(a_NBT.GetByte(Slot), Item);
|
||||
} // for itr - ItemDefs[]
|
||||
a_BlockEntities.push_back(Chest.release());
|
||||
}
|
||||
@ -849,25 +663,10 @@ void cWSSAnvil::LoadDispenserFromNBT(cBlockEntityList & a_BlockEntities, const c
|
||||
continue;
|
||||
}
|
||||
cItem Item;
|
||||
int ID = a_NBT.FindChildByName(Child, "id");
|
||||
if ((ID < 0) || (a_NBT.GetType(ID) != TAG_Short))
|
||||
if (LoadItemFromNBT(Item, a_NBT, Child))
|
||||
{
|
||||
continue;
|
||||
Dispenser->SetSlot(a_NBT.GetByte(Slot), Item);
|
||||
}
|
||||
Item.m_ItemType = (ENUM_ITEM_ID)(a_NBT.GetShort(ID));
|
||||
int Damage = a_NBT.FindChildByName(Child, "Damage");
|
||||
if ((Damage < 0) || (a_NBT.GetType(Damage) != TAG_Short))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Item.m_ItemDamage = a_NBT.GetShort(Damage);
|
||||
int Count = a_NBT.FindChildByName(Child, "Count");
|
||||
if ((Count < 0) || (a_NBT.GetType(Count) != TAG_Byte))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Item.m_ItemCount = a_NBT.GetByte(Count);
|
||||
Dispenser->SetSlot(a_NBT.GetByte(Slot), Item);
|
||||
} // for itr - ItemDefs[]
|
||||
a_BlockEntities.push_back(Dispenser.release());
|
||||
}
|
||||
@ -898,25 +697,10 @@ void cWSSAnvil::LoadFurnaceFromNBT(cBlockEntityList & a_BlockEntities, const cPa
|
||||
continue;
|
||||
}
|
||||
cItem Item;
|
||||
int ID = a_NBT.FindChildByName(Child, "id");
|
||||
if ((ID < 0) || (a_NBT.GetType(ID) != TAG_Short))
|
||||
if (LoadItemFromNBT(Item, a_NBT, Child))
|
||||
{
|
||||
continue;
|
||||
Furnace->SetSlot(a_NBT.GetByte(Slot), Item);
|
||||
}
|
||||
Item.m_ItemType = (ENUM_ITEM_ID)(a_NBT.GetShort(ID));
|
||||
int Damage = a_NBT.FindChildByName(Child, "Damage");
|
||||
if ((Damage < 0) || (a_NBT.GetType(Damage) != TAG_Short))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Item.m_ItemDamage = a_NBT.GetShort(Damage);
|
||||
int Count = a_NBT.FindChildByName(Child, "Count");
|
||||
if ((Count < 0) || (a_NBT.GetType(Count) != TAG_Byte))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Item.m_ItemCount = a_NBT.GetByte(Count);
|
||||
Furnace->SetSlot(a_NBT.GetByte(Slot), Item);
|
||||
} // for itr - ItemDefs[]
|
||||
int BurnTime = a_NBT.FindChildByName(a_TagIdx, "BurnTime");
|
||||
if (BurnTime >= 0)
|
||||
@ -1022,6 +806,159 @@ void cWSSAnvil::LoadJukeboxFromNBT(cBlockEntityList & a_BlockEntities, const cPa
|
||||
|
||||
|
||||
|
||||
void cWSSAnvil::LoadEntityFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_EntityTagIdx, const char * a_IDTag, int a_IDTagLength)
|
||||
{
|
||||
if (strncmp(a_IDTag, "FallingBlock", a_IDTagLength) == 0)
|
||||
{
|
||||
LoadFallingBlockFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
|
||||
}
|
||||
else if (strncmp(a_IDTag, "Minecart", a_IDTagLength) == 0)
|
||||
{
|
||||
// It is a minecart, old style, find out the type:
|
||||
int TypeTag = a_NBT.FindChildByName(a_EntityTagIdx, "Type");
|
||||
if ((TypeTag < 0) || (a_NBT.GetType(TypeTag) != TAG_Int))
|
||||
{
|
||||
return;
|
||||
}
|
||||
switch (a_NBT.GetInt(TypeTag))
|
||||
{
|
||||
case 0: LoadMinecartRFromNBT(a_Entities, a_NBT, a_EntityTagIdx); break; // Rideable minecart
|
||||
case 1: LoadMinecartCFromNBT(a_Entities, a_NBT, a_EntityTagIdx); break; // Minecart with chest
|
||||
case 2: LoadMinecartFFromNBT(a_Entities, a_NBT, a_EntityTagIdx); break; // Minecart with furnace
|
||||
}
|
||||
}
|
||||
else if (strncmp(a_IDTag, "MinecartRideable", a_IDTagLength) == 0)
|
||||
{
|
||||
LoadMinecartRFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
|
||||
}
|
||||
else if (strncmp(a_IDTag, "MinecartChest", a_IDTagLength) == 0)
|
||||
{
|
||||
LoadMinecartCFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
|
||||
}
|
||||
else if (strncmp(a_IDTag, "MinecartFurnace", a_IDTagLength) == 0)
|
||||
{
|
||||
LoadMinecartFFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
|
||||
}
|
||||
if (strncmp(a_IDTag, "Item", a_IDTagLength) == 0)
|
||||
{
|
||||
LoadPickupFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
|
||||
}
|
||||
// TODO: other entities
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cWSSAnvil::LoadFallingBlockFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cWSSAnvil::LoadMinecartRFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cWSSAnvil::LoadMinecartCFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cWSSAnvil::LoadMinecartFFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cWSSAnvil::LoadPickupFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
|
||||
{
|
||||
int ItemTag = a_NBT.FindChildByName(a_TagIdx, "Item");
|
||||
if ((ItemTag < 0) || (a_NBT.GetType(ItemTag) != TAG_Compound))
|
||||
{
|
||||
return;
|
||||
}
|
||||
cItem Item;
|
||||
if (!LoadItemFromNBT(Item, a_NBT, ItemTag))
|
||||
{
|
||||
return;
|
||||
}
|
||||
std::auto_ptr<cPickup> Pickup(new cPickup(0, 0, 0, Item));
|
||||
if (!LoadEntityBaseFromNBT(*Pickup.get(), a_NBT, a_TagIdx))
|
||||
{
|
||||
return;
|
||||
}
|
||||
a_Entities.push_back(Pickup.release());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cWSSAnvil::LoadEntityBaseFromNBT(cEntity & a_Entity, const cParsedNBT & a_NBT, int a_TagIdx)
|
||||
{
|
||||
double Pos[3];
|
||||
if (!LoadDoublesListFromNBT(Pos, 3, a_NBT, a_NBT.FindChildByName(a_TagIdx, "Pos")))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
a_Entity.SetPosition(Pos[0], Pos[1], Pos[2]);
|
||||
|
||||
double Speed[3];
|
||||
if (!LoadDoublesListFromNBT(Speed, 3, a_NBT, a_NBT.FindChildByName(a_TagIdx, "Motion")))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
a_Entity.SetSpeed(Speed[0], Speed[1], Speed[2]);
|
||||
|
||||
double Rotation[3];
|
||||
if (!LoadDoublesListFromNBT(Rotation, 2, a_NBT, a_NBT.FindChildByName(a_TagIdx, "Rotation")))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
a_Entity.SetRotation(Rotation[0]);
|
||||
a_Entity.SetRoll (Rotation[1]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cWSSAnvil::LoadDoublesListFromNBT(double * a_Doubles, int a_NumDoubles, const cParsedNBT & a_NBT, int a_TagIdx)
|
||||
{
|
||||
if ((a_TagIdx < 0) || (a_NBT.GetType(a_TagIdx) != TAG_List) || (a_NBT.GetChildrenType(a_TagIdx) != TAG_Double))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int idx = 0;
|
||||
for (int Tag = a_NBT.GetFirstChild(a_TagIdx); (Tag > 0) && (idx < a_NumDoubles); Tag = a_NBT.GetNextSibling(Tag), ++idx)
|
||||
{
|
||||
a_Doubles[idx] = a_NBT.GetDouble(Tag);
|
||||
} // for Tag - PosTag[]
|
||||
return (idx == a_NumDoubles); // Did we read enough doubles?
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cWSSAnvil::GetBlockEntityNBTPos(const cParsedNBT & a_NBT, int a_TagIdx, int & a_X, int & a_Y, int & a_Z)
|
||||
{
|
||||
int x = a_NBT.FindChildByName(a_TagIdx, "x");
|
||||
@ -1162,6 +1099,7 @@ bool cWSSAnvil::cMCAFile::SetChunkData(const cChunkCoords & a_Chunk, const AStri
|
||||
{
|
||||
if (!OpenFile(false))
|
||||
{
|
||||
LOGWARNING("Cannot save chunk [%d, %d], opening file \"%s\" failed", a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, GetFileName().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1183,15 +1121,18 @@ bool cWSSAnvil::cMCAFile::SetChunkData(const cChunkCoords & a_Chunk, const AStri
|
||||
unsigned ChunkSize = htonl(a_Data.size() + 1);
|
||||
if (m_File.Write(&ChunkSize, 4) != 4)
|
||||
{
|
||||
LOGWARNING("Cannot save chunk [%d, %d], writing(1) data to file \"%s\" failed", a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, GetFileName().c_str());
|
||||
return false;
|
||||
}
|
||||
char CompressionType = 2;
|
||||
if (m_File.Write(&CompressionType, 1) != 1)
|
||||
{
|
||||
LOGWARNING("Cannot save chunk [%d, %d], writing(2) data to file \"%s\" failed", a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, GetFileName().c_str());
|
||||
return false;
|
||||
}
|
||||
if (m_File.Write(a_Data.data(), a_Data.size()) != (int)(a_Data.size()))
|
||||
{
|
||||
LOGWARNING("Cannot save chunk [%d, %d], writing(3) data to file \"%s\" failed", a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, GetFileName().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1199,9 +1140,14 @@ bool cWSSAnvil::cMCAFile::SetChunkData(const cChunkCoords & a_Chunk, const AStri
|
||||
ChunkSize = (a_Data.size() + MCA_CHUNK_HEADER_LENGTH + 4095) / 4096; // Round data size *up* to nearest 4KB sector, make it a sector number
|
||||
ASSERT(ChunkSize < 256);
|
||||
m_Header[LocalX + 32 * LocalZ] = htonl((ChunkSector << 8) | ChunkSize);
|
||||
m_File.Seek(0);
|
||||
if (m_File.Seek(0) < 0)
|
||||
{
|
||||
LOGWARNING("Cannot save chunk [%d, %d], seeking in file \"%s\" failed", a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, GetFileName().c_str());
|
||||
return false;
|
||||
}
|
||||
if (m_File.Write(m_Header, sizeof(m_Header)) != sizeof(m_Header))
|
||||
{
|
||||
LOGWARNING("Cannot save chunk [%d, %d], writing header to file \"%s\" failed", a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, GetFileName().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -111,6 +111,9 @@ protected:
|
||||
/// Loads the chunk's BlockEntities from NBT data (a_Tag is the Level\\TileEntities list tag; may be -1)
|
||||
void LoadBlockEntitiesFromNBT(cBlockEntityList & a_BlockEntitites, const cParsedNBT & a_NBT, int a_Tag);
|
||||
|
||||
/// Loads a cItem contents from the specified NBT tag; returns true if successful. Doesn't load the Slot tag
|
||||
bool LoadItemFromNBT(cItem & a_Item, const cParsedNBT & a_NBT, int a_TagIdx);
|
||||
|
||||
void LoadChestFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx);
|
||||
void LoadDispenserFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx);
|
||||
void LoadFurnaceFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx);
|
||||
@ -118,6 +121,20 @@ protected:
|
||||
void LoadNoteFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx);
|
||||
void LoadJukeboxFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx);
|
||||
|
||||
void LoadEntityFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_EntityTagIdx, const char * a_IDTag, int a_IDTagLength);
|
||||
|
||||
void LoadFallingBlockFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
|
||||
void LoadMinecartRFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
|
||||
void LoadMinecartCFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
|
||||
void LoadMinecartFFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
|
||||
void LoadPickupFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
|
||||
|
||||
/// Loads entity common data from the NBT compound; returns true if successful
|
||||
bool LoadEntityBaseFromNBT(cEntity & a_Entity, const cParsedNBT & a_NBT, int a_TagIdx);
|
||||
|
||||
/// Loads an array of doubles of the specified length from the specified NBT list tag a_TagIdx; returns true if successful
|
||||
bool LoadDoublesListFromNBT(double * a_Doubles, int a_NumDoubles, const cParsedNBT & a_NBT, int a_TagIdx);
|
||||
|
||||
/// Helper function for extracting the X, Y, and Z int subtags of a NBT compound; returns true if successful
|
||||
bool GetBlockEntityNBTPos(const cParsedNBT & a_NBT, int a_TagIdx, int & a_X, int & a_Y, int & a_Z);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user