1
0

Merge pull request #768 from Howaner/BlockEntitys

Add TNT load/save
This commit is contained in:
Tiger Wang 2014-03-09 21:44:32 +00:00
commit 09c5542123
13 changed files with 92 additions and 31 deletions

1
.gitignore vendored
View File

@ -1,4 +1,5 @@
build/
nbproject/
ipch/
Win32/
MCServer/MCServer

View File

@ -2025,8 +2025,9 @@ end
Desc = "This class manages a TNT entity.",
Functions =
{
GetCounterTime = { Return = "number", Notes = "Returns the time until the entity explodes." },
GetMaxFuseTime = { Return = "number", Notes = "Returns how long the fuse was." },
Explode = { Return = "", Notes = "Explode the tnt." },
GetFuseTicks = { Return = "number", Notes = "Returns the fuse ticks until the tnt will explode." },
SetFuseTicks = { Return = "number", Notes = "Set the fuse ticks until the tnt will explode." },
},
Inherits = "cEntity",
},
@ -2261,7 +2262,7 @@ end
SpawnMob = { Params = "X, Y, Z, {{cMonster|MonsterType}}", Return = "EntityID", Notes = "Spawns the specified type of mob at the specified coords. Returns the EntityID of the creates entity, or -1 on failure. " },
SpawnFallingBlock = { Params = "X, Y, Z, BlockType, BlockMeta", Return = "EntityID", Notes = "Spawns an {{cFallingBlock|Falling Block}} entity at the specified coords with the given block type/meta" },
SpawnExperienceOrb = { Params = "X, Y, Z, Reward", Return = "EntityID", Notes = "Spawns an {{cExpOrb|experience orb}} at the specified coords, with the given reward" },
SpawnPrimedTNT = { Params = "X, Y, Z, FuseTimeSecs, InitialVelocityCoeff", Return = "", Notes = "Spawns a {{cTNTEntity|primed TNT entity}} at the specified coords, with the given fuse time. The entity gets a random speed multiplied by the InitialVelocityCoeff, 1 being the default value." },
SpawnPrimedTNT = { Params = "X, Y, Z, FuseTicks, InitialVelocityCoeff", Return = "", Notes = "Spawns a {{cTNTEntity|primed TNT entity}} at the specified coords, with the given fuse ticks. The entity gets a random speed multiplied by the InitialVelocityCoeff, 1 being the default value." },
TryGetHeight = { Params = "BlockX, BlockZ", Return = "IsValid, Height", Notes = "Returns true and height of the highest non-air block if the chunk is loaded, or false otherwise." },
UpdateSign = { Params = "X, Y, Z, Line1, Line2, Line3, Line4, [{{cPlayer|Player}}]", Return = "", Notes = "Sets the sign text at the specified coords. The sign-updating hooks are called for the change. The Player parameter is used to indicate the player from whom the change has come, it may be nil. Same as SetSignLiens()" },
UseBlockEntity = { Params = "{{cPlayer|Player}}, BlockX, BlockY, BlockZ", Return = "", Notes = "Makes the specified Player use the block entity at the specified coords (open chest UI, etc.) If the cords are in an unloaded chunk or there's no block entity, ignores the call." },

View File

@ -116,7 +116,7 @@ void cDispenserEntity::DropSpenseFromSlot(cChunk & a_Chunk, int a_SlotNum)
{
double TNTX = 0.5 + (DispX + DispChunk->GetPosX() * cChunkDef::Width);
double TNTZ = 0.5 + (DispZ + DispChunk->GetPosZ() * cChunkDef::Width);
m_World->SpawnPrimedTNT(TNTX, DispY + 0.5, TNTZ, 4, 0); // 4 seconds fuse, no initial velocity
m_World->SpawnPrimedTNT(TNTX, DispY + 0.5, TNTZ, 80, 0); // 80 ticks fuse, no initial velocity
m_Contents.ChangeSlotCount(a_SlotNum, -1);
}
break;

View File

@ -8,10 +8,9 @@
cTNTEntity::cTNTEntity(double a_X, double a_Y, double a_Z, double a_FuseTimeInSec) :
cTNTEntity::cTNTEntity(double a_X, double a_Y, double a_Z, int a_FuseTicks) :
super(etTNT, a_X, a_Y, a_Z, 0.98, 0.98),
m_Counter(0),
m_MaxFuseTime(a_FuseTimeInSec)
m_FuseTicks(a_FuseTicks)
{
}
@ -19,10 +18,9 @@ cTNTEntity::cTNTEntity(double a_X, double a_Y, double a_Z, double a_FuseTimeInSe
cTNTEntity::cTNTEntity(const Vector3d & a_Pos, double a_FuseTimeInSec) :
cTNTEntity::cTNTEntity(const Vector3d & a_Pos, int a_FuseTicks) :
super(etTNT, a_Pos.x, a_Pos.y, a_Pos.z, 0.98, 0.98),
m_Counter(0),
m_MaxFuseTime(a_FuseTimeInSec)
m_FuseTicks(a_FuseTicks)
{
}
@ -42,18 +40,27 @@ void cTNTEntity::SpawnOn(cClientHandle & a_ClientHandle)
void cTNTEntity::Explode(void)
{
m_FuseTicks = 0;
Destroy(true);
LOGD("BOOM at {%f,%f,%f}", GetPosX(), GetPosY(), GetPosZ());
m_World->DoExplosionAt(4.0, GetPosX() + 0.49, GetPosY() + 0.49, GetPosZ() + 0.49, true, esPrimedTNT, this);
}
void cTNTEntity::Tick(float a_Dt, cChunk & a_Chunk)
{
super::Tick(a_Dt, a_Chunk);
BroadcastMovementUpdate();
float delta_time = a_Dt / 1000; // Convert miliseconds to seconds
m_Counter += delta_time;
if (m_Counter > m_MaxFuseTime) // Check if we go KABOOOM
m_FuseTicks -= 1;
if (m_FuseTicks <= 0)
{
Destroy(true);
LOGD("BOOM at {%f,%f,%f}", GetPosX(), GetPosY(), GetPosZ());
m_World->DoExplosionAt(4.0, GetPosX() + 0.49, GetPosY() + 0.49, GetPosZ() + 0.49, true, esPrimedTNT, this);
return;
Explode();
}
}

View File

@ -16,19 +16,28 @@ public:
// tolua_end
CLASS_PROTODEF(cTNTEntity);
cTNTEntity(double a_X, double a_Y, double a_Z, double a_FuseTimeInSec);
cTNTEntity(const Vector3d & a_Pos, double a_FuseTimeInSec);
cTNTEntity(double a_X, double a_Y, double a_Z, int a_FuseTicks = 80);
cTNTEntity(const Vector3d & a_Pos, int a_FuseTicks = 80);
// cEntity overrides:
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
double GetCounterTime(void) const { return m_Counter; } // tolua_export
double GetMaxFuseTime(void) const { return m_MaxFuseTime; } // tolua_export
// tolua_begin
/** Explode the tnt */
void Explode(void);
/** Returns the fuse ticks until the tnt will explode */
int GetFuseTicks(void) const { return m_FuseTicks; }
/** Set the fuse ticks until the tnt will explode */
void SetFuseTicks(int a_FuseTicks) { m_FuseTicks = a_FuseTicks; }
// tolua_end
protected:
double m_Counter; ///< How much time has elapsed since the object was created, in seconds
double m_MaxFuseTime; ///< How long the fuse is, in seconds
int m_FuseTicks; ///< How much ticks is left, while the tnt will explode
}; // tolua_export

View File

@ -33,8 +33,8 @@ public:
case E_BLOCK_TNT:
{
// Activate the TNT:
a_World->BroadcastSoundEffect("game.tnt.primed", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 0.5f, 0.6f);
a_World->SpawnPrimedTNT(a_BlockX + 0.5, a_BlockY + 0.5, a_BlockZ + 0.5, 4); // 4 seconds to boom
a_World->BroadcastSoundEffect("game.tnt.primed", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 1.0f, 1.0f);
a_World->SpawnPrimedTNT(a_BlockX + 0.5, a_BlockY + 0.5, a_BlockZ + 0.5); // 80 ticks to boom
a_World->SetBlock(a_BlockX,a_BlockY,a_BlockZ, E_BLOCK_AIR, 0);
break;
}

View File

@ -838,7 +838,7 @@ void cIncrementalRedstoneSimulator::HandleTNT(int a_BlockX, int a_BlockY, int a_
if (AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ))
{
m_World.BroadcastSoundEffect("game.tnt.primed", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 0.5f, 0.6f);
m_World.SpawnPrimedTNT(a_BlockX + 0.5, a_BlockY + 0.5, a_BlockZ + 0.5, 4); // 4 seconds to boom
m_World.SpawnPrimedTNT(a_BlockX + 0.5, a_BlockY + 0.5, a_BlockZ + 0.5); // 80 ticks to boom
m_World.SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
}
}

View File

@ -1726,10 +1726,10 @@ int cWorld::SpawnMinecart(double a_X, double a_Y, double a_Z, int a_MinecartType
void cWorld::SpawnPrimedTNT(double a_X, double a_Y, double a_Z, double a_FuseTimeInSec, double a_InitialVelocityCoeff)
void cWorld::SpawnPrimedTNT(double a_X, double a_Y, double a_Z, int a_FuseTicks, double a_InitialVelocityCoeff)
{
UNUSED(a_InitialVelocityCoeff);
cTNTEntity * TNT = new cTNTEntity(a_X, a_Y, a_Z, a_FuseTimeInSec);
cTNTEntity * TNT = new cTNTEntity(a_X, a_Y, a_Z, a_FuseTicks);
TNT->Initialize(this);
// TODO: Add a bit of speed in horiz and vert axes, based on the a_InitialVelocityCoeff
}

View File

@ -445,7 +445,7 @@ public:
int SpawnExperienceOrb(double a_X, double a_Y, double a_Z, int a_Reward);
/** Spawns a new primed TNT entity at the specified block coords and specified fuse duration. Initial velocity is given based on the relative coefficient provided */
void SpawnPrimedTNT(double a_X, double a_Y, double a_Z, double a_FuseTimeInSec, double a_InitialVelocityCoeff = 1);
void SpawnPrimedTNT(double a_X, double a_Y, double a_Z, int a_FuseTimeInSec = 80, double a_InitialVelocityCoeff = 1);
// tolua_end

View File

@ -28,6 +28,7 @@
#include "../Entities/Minecart.h"
#include "../Entities/Pickup.h"
#include "../Entities/ProjectileEntity.h"
#include "../Entities/TNTEntity.h"
#include "../Mobs/Monster.h"
#include "../Mobs/Bat.h"
@ -591,6 +592,18 @@ void cNBTChunkSerializer::AddProjectileEntity(cProjectileEntity * a_Projectile)
void cNBTChunkSerializer::AddTNTEntity(cTNTEntity * a_TNT)
{
m_Writer.BeginCompound("");
AddBasicEntity(a_TNT, "PrimedTnt");
m_Writer.AddByte("Fuse", (unsigned char)a_TNT->GetFuseTicks());
m_Writer.EndCompound();
}
void cNBTChunkSerializer::AddMinecartChestContents(cMinecartWithChest * a_Minecart)
{
m_Writer.BeginList("Items", TAG_Compound);
@ -670,7 +683,7 @@ void cNBTChunkSerializer::Entity(cEntity * a_Entity)
case cEntity::etMonster: AddMonsterEntity ((cMonster *) a_Entity); break;
case cEntity::etPickup: AddPickupEntity ((cPickup *) a_Entity); break;
case cEntity::etProjectile: AddProjectileEntity ((cProjectileEntity *)a_Entity); break;
case cEntity::etTNT: /* TODO */ break;
case cEntity::etTNT: AddTNTEntity ((cTNTEntity *) a_Entity); break;
case cEntity::etExpOrb: /* TODO */ break;
case cEntity::etItemFrame: /* TODO */ break;
case cEntity::etPainting: /* TODO */ break;

View File

@ -41,6 +41,7 @@ class cMonster;
class cPickup;
class cItemGrid;
class cProjectileEntity;
class cTNTEntity;
@ -107,6 +108,7 @@ protected:
void AddMonsterEntity (cMonster * a_Monster);
void AddPickupEntity (cPickup * a_Pickup);
void AddProjectileEntity (cProjectileEntity * a_Projectile);
void AddTNTEntity (cTNTEntity * a_TNT);
void AddMinecartChestContents(cMinecartWithChest * a_Minecart);

View File

@ -36,6 +36,7 @@
#include "../Entities/Minecart.h"
#include "../Entities/Pickup.h"
#include "../Entities/ProjectileEntity.h"
#include "../Entities/TNTEntity.h"
@ -1237,6 +1238,10 @@ void cWSSAnvil::LoadEntityFromNBT(cEntityList & a_Entities, const cParsedNBT & a
{
LoadPigZombieFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
}
else if (strncmp(a_IDTag, "PrimedTnt", a_IDTagLength) == 0)
{
LoadTNTFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
}
// TODO: other entities
}
@ -2173,6 +2178,28 @@ void cWSSAnvil::LoadPigZombieFromNBT(cEntityList & a_Entities, const cParsedNBT
void cWSSAnvil::LoadTNTFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
{
std::auto_ptr<cTNTEntity> TNT(new cTNTEntity(0.0, 0.0, 0.0, 0));
if (!LoadEntityBaseFromNBT(*TNT.get(), a_NBT, a_TagIdx))
{
return;
}
// Load Fuse Ticks:
int FuseTicks = a_NBT.FindChildByName(a_TagIdx, "Fuse");
if (FuseTicks > 0)
{
TNT->SetFuseTicks((int) a_NBT.GetByte(FuseTicks));
}
a_Entities.push_back(TNT.release());
}
bool cWSSAnvil::LoadEntityBaseFromNBT(cEntity & a_Entity, const cParsedNBT & a_NBT, int a_TagIdx)
{
double Pos[3];

View File

@ -192,6 +192,7 @@ protected:
void LoadWolfFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
void LoadZombieFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
void LoadPigZombieFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
void LoadTNTFromNBT (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);