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/ build/
nbproject/
ipch/ ipch/
Win32/ Win32/
MCServer/MCServer MCServer/MCServer

View File

@ -2025,8 +2025,9 @@ end
Desc = "This class manages a TNT entity.", Desc = "This class manages a TNT entity.",
Functions = Functions =
{ {
GetCounterTime = { Return = "number", Notes = "Returns the time until the entity explodes." }, Explode = { Return = "", Notes = "Explode the tnt." },
GetMaxFuseTime = { Return = "number", Notes = "Returns how long the fuse was." }, 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", 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. " }, 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" }, 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" }, 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." }, 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()" }, 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." }, 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 TNTX = 0.5 + (DispX + DispChunk->GetPosX() * cChunkDef::Width);
double TNTZ = 0.5 + (DispZ + DispChunk->GetPosZ() * 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); m_Contents.ChangeSlotCount(a_SlotNum, -1);
} }
break; 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), super(etTNT, a_X, a_Y, a_Z, 0.98, 0.98),
m_Counter(0), m_FuseTicks(a_FuseTicks)
m_MaxFuseTime(a_FuseTimeInSec)
{ {
} }
@ -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), super(etTNT, a_Pos.x, a_Pos.y, a_Pos.z, 0.98, 0.98),
m_Counter(0), m_FuseTicks(a_FuseTicks)
m_MaxFuseTime(a_FuseTimeInSec)
{ {
} }
@ -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) void cTNTEntity::Tick(float a_Dt, cChunk & a_Chunk)
{ {
super::Tick(a_Dt, a_Chunk); super::Tick(a_Dt, a_Chunk);
BroadcastMovementUpdate(); BroadcastMovementUpdate();
float delta_time = a_Dt / 1000; // Convert miliseconds to seconds
m_Counter += delta_time; m_FuseTicks -= 1;
if (m_Counter > m_MaxFuseTime) // Check if we go KABOOOM if (m_FuseTicks <= 0)
{ {
Destroy(true); Explode();
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;
} }
} }

View File

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

View File

@ -33,8 +33,8 @@ public:
case E_BLOCK_TNT: case E_BLOCK_TNT:
{ {
// Activate the 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->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, 4); // 4 seconds to boom 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); a_World->SetBlock(a_BlockX,a_BlockY,a_BlockZ, E_BLOCK_AIR, 0);
break; 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)) 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.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); 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); 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); TNT->Initialize(this);
// TODO: Add a bit of speed in horiz and vert axes, based on the a_InitialVelocityCoeff // 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); 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 */ /** 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 // tolua_end

View File

@ -28,6 +28,7 @@
#include "../Entities/Minecart.h" #include "../Entities/Minecart.h"
#include "../Entities/Pickup.h" #include "../Entities/Pickup.h"
#include "../Entities/ProjectileEntity.h" #include "../Entities/ProjectileEntity.h"
#include "../Entities/TNTEntity.h"
#include "../Mobs/Monster.h" #include "../Mobs/Monster.h"
#include "../Mobs/Bat.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) void cNBTChunkSerializer::AddMinecartChestContents(cMinecartWithChest * a_Minecart)
{ {
m_Writer.BeginList("Items", TAG_Compound); 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::etMonster: AddMonsterEntity ((cMonster *) a_Entity); break;
case cEntity::etPickup: AddPickupEntity ((cPickup *) a_Entity); break; case cEntity::etPickup: AddPickupEntity ((cPickup *) a_Entity); break;
case cEntity::etProjectile: AddProjectileEntity ((cProjectileEntity *)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::etExpOrb: /* TODO */ break;
case cEntity::etItemFrame: /* TODO */ break; case cEntity::etItemFrame: /* TODO */ break;
case cEntity::etPainting: /* TODO */ break; case cEntity::etPainting: /* TODO */ break;

View File

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

View File

@ -36,6 +36,7 @@
#include "../Entities/Minecart.h" #include "../Entities/Minecart.h"
#include "../Entities/Pickup.h" #include "../Entities/Pickup.h"
#include "../Entities/ProjectileEntity.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); 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 // 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) bool cWSSAnvil::LoadEntityBaseFromNBT(cEntity & a_Entity, const cParsedNBT & a_NBT, int a_TagIdx)
{ {
double Pos[3]; double Pos[3];

View File

@ -192,6 +192,7 @@ protected:
void LoadWolfFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); 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 LoadZombieFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
void LoadPigZombieFromNBT (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 /// Loads entity common data from the NBT compound; returns true if successful
bool LoadEntityBaseFromNBT(cEntity & a_Entity, const cParsedNBT & a_NBT, int a_TagIdx); bool LoadEntityBaseFromNBT(cEntity & a_Entity, const cParsedNBT & a_NBT, int a_TagIdx);