From f5e374be41ef3bde93e0faaa76208e3e0e15e9ea Mon Sep 17 00:00:00 2001 From: Howaner Date: Sat, 8 Mar 2014 10:25:46 +0100 Subject: [PATCH 1/4] Add TNT Save/Load and add Netbeans projects to .gitignore --- .gitignore | 1 + src/Entities/TNTEntity.cpp | 27 +++++++++++++++--------- src/Entities/TNTEntity.h | 23 +++++++++++++------- src/WorldStorage/NBTChunkSerializer.cpp | 15 ++++++++++++- src/WorldStorage/NBTChunkSerializer.h | 2 ++ src/WorldStorage/WSSAnvil.cpp | 28 +++++++++++++++++++++++++ src/WorldStorage/WSSAnvil.h | 1 + 7 files changed, 79 insertions(+), 18 deletions(-) diff --git a/.gitignore b/.gitignore index c8ad93a80..c544f394d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ build/ +nbproject/ ipch/ Win32/ MCServer/MCServer diff --git a/src/Entities/TNTEntity.cpp b/src/Entities/TNTEntity.cpp index 339107b2e..4f361403c 100644 --- a/src/Entities/TNTEntity.cpp +++ b/src/Entities/TNTEntity.cpp @@ -10,8 +10,7 @@ cTNTEntity::cTNTEntity(double a_X, double a_Y, double a_Z, double a_FuseTimeInSec) : super(etTNT, a_X, a_Y, a_Z, 0.98, 0.98), - m_Counter(0), - m_MaxFuseTime(a_FuseTimeInSec) + m_FuseTicks(a_FuseTimeInSec) { } @@ -21,8 +20,7 @@ cTNTEntity::cTNTEntity(double a_X, double a_Y, double a_Z, double a_FuseTimeInSe cTNTEntity::cTNTEntity(const Vector3d & a_Pos, double a_FuseTimeInSec) : 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_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) { 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 -= delta_time; + 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(); } } diff --git a/src/Entities/TNTEntity.h b/src/Entities/TNTEntity.h index d1fcae766..8f83f52d9 100644 --- a/src/Entities/TNTEntity.h +++ b/src/Entities/TNTEntity.h @@ -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, double a_FuseTimeInSec = 4); + cTNTEntity(const Vector3d & a_Pos, double a_FuseTimeInSec = 4); // 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 */ + double GetFuseTicks(void) const { return m_FuseTicks; } + + /** Set the fuse ticks until the tnt will explode */ + void SetFuseTicks(double 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 + double m_FuseTicks; ///< How much time in seconds is left, while the tnt will explode }; // tolua_export diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp index 6d0e29958..06b815333 100644 --- a/src/WorldStorage/NBTChunkSerializer.cpp +++ b/src/WorldStorage/NBTChunkSerializer.cpp @@ -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" @@ -583,6 +584,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()) * 10); + m_Writer.EndCompound(); +} + + + + + void cNBTChunkSerializer::AddMinecartChestContents(cMinecartWithChest * a_Minecart) { m_Writer.BeginList("Items", TAG_Compound); @@ -662,7 +675,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; diff --git a/src/WorldStorage/NBTChunkSerializer.h b/src/WorldStorage/NBTChunkSerializer.h index 8a9e18413..3b486d2bc 100644 --- a/src/WorldStorage/NBTChunkSerializer.h +++ b/src/WorldStorage/NBTChunkSerializer.h @@ -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); diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp index 680f2458f..fa0c4dbd9 100644 --- a/src/WorldStorage/WSSAnvil.cpp +++ b/src/WorldStorage/WSSAnvil.cpp @@ -36,6 +36,7 @@ #include "../Entities/Minecart.h" #include "../Entities/Pickup.h" #include "../Entities/ProjectileEntity.h" +#include "../Entities/TNTEntity.h" @@ -1231,6 +1232,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 } @@ -2167,6 +2172,29 @@ void cWSSAnvil::LoadPigZombieFromNBT(cEntityList & a_Entities, const cParsedNBT +void cWSSAnvil::LoadTNTFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) +{ + std::auto_ptr 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) + { + int MojangFuseTicks = (int) a_NBT.GetByte(FuseTicks); + TNT->SetFuseTicks((double) MojangFuseTicks / 10); + } + + a_Entities.push_back(TNT.release()); +} + + + + + bool cWSSAnvil::LoadEntityBaseFromNBT(cEntity & a_Entity, const cParsedNBT & a_NBT, int a_TagIdx) { double Pos[3]; diff --git a/src/WorldStorage/WSSAnvil.h b/src/WorldStorage/WSSAnvil.h index b26345b13..fe93d16c3 100644 --- a/src/WorldStorage/WSSAnvil.h +++ b/src/WorldStorage/WSSAnvil.h @@ -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); From baeff21a5b693a99057aa5a7dc218bf93630b35a Mon Sep 17 00:00:00 2001 From: Howaner Date: Sat, 8 Mar 2014 10:29:57 +0100 Subject: [PATCH 2/4] Add new tnt documentation --- MCServer/Plugins/APIDump/APIDesc.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua index 39f7cbcd7..5cea49cb1 100644 --- a/MCServer/Plugins/APIDump/APIDesc.lua +++ b/MCServer/Plugins/APIDump/APIDesc.lua @@ -2023,8 +2023,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 (in seconds) until the tnt will explode." }, + SetFuseTicks = { Return = "number", Notes = "Set the fuse ticks (in seconds) until the tnt will explode." }, }, Inherits = "cEntity", }, From b37966fd214fb048a415a33291a85ee8c263691c Mon Sep 17 00:00:00 2001 From: Howaner Date: Sat, 8 Mar 2014 12:24:33 +0100 Subject: [PATCH 3/4] Change TNT Fuse to ticks --- src/BlockEntities/DispenserEntity.cpp | 2 +- src/Entities/TNTEntity.cpp | 12 ++++++------ src/Entities/TNTEntity.h | 10 +++++----- src/Items/ItemLighter.h | 4 ++-- src/Simulator/IncrementalRedstoneSimulator.cpp | 2 +- src/World.cpp | 4 ++-- src/World.h | 2 +- src/WorldStorage/NBTChunkSerializer.cpp | 2 +- src/WorldStorage/WSSAnvil.cpp | 3 +-- 9 files changed, 20 insertions(+), 21 deletions(-) diff --git a/src/BlockEntities/DispenserEntity.cpp b/src/BlockEntities/DispenserEntity.cpp index 374f3d6e3..cbfbb1b6a 100644 --- a/src/BlockEntities/DispenserEntity.cpp +++ b/src/BlockEntities/DispenserEntity.cpp @@ -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; diff --git a/src/Entities/TNTEntity.cpp b/src/Entities/TNTEntity.cpp index 4f361403c..02f31f5bb 100644 --- a/src/Entities/TNTEntity.cpp +++ b/src/Entities/TNTEntity.cpp @@ -8,9 +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_FuseTicks(a_FuseTimeInSec) + m_FuseTicks(a_FuseTicks) { } @@ -18,9 +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_FuseTicks(a_FuseTimeInSec) + m_FuseTicks(a_FuseTicks) { } @@ -56,8 +56,8 @@ 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_FuseTicks -= delta_time; + + m_FuseTicks -= 1; if (m_FuseTicks <= 0) { Explode(); diff --git a/src/Entities/TNTEntity.h b/src/Entities/TNTEntity.h index 8f83f52d9..116f5a8cb 100644 --- a/src/Entities/TNTEntity.h +++ b/src/Entities/TNTEntity.h @@ -16,8 +16,8 @@ public: // tolua_end CLASS_PROTODEF(cTNTEntity); - cTNTEntity(double a_X, double a_Y, double a_Z, double a_FuseTimeInSec = 4); - cTNTEntity(const Vector3d & a_Pos, double a_FuseTimeInSec = 4); + 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; @@ -29,15 +29,15 @@ public: void Explode(void); /** Returns the fuse ticks until the tnt will explode */ - double GetFuseTicks(void) const { return m_FuseTicks; } + int GetFuseTicks(void) const { return m_FuseTicks; } /** Set the fuse ticks until the tnt will explode */ - void SetFuseTicks(double a_FuseTicks) { m_FuseTicks = a_FuseTicks; } + void SetFuseTicks(int a_FuseTicks) { m_FuseTicks = a_FuseTicks; } // tolua_end protected: - double m_FuseTicks; ///< How much time in seconds is left, while the tnt will explode + int m_FuseTicks; ///< How much ticks is left, while the tnt will explode }; // tolua_export diff --git a/src/Items/ItemLighter.h b/src/Items/ItemLighter.h index cc7daeb08..18873e911 100644 --- a/src/Items/ItemLighter.h +++ b/src/Items/ItemLighter.h @@ -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; } diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp index f377b0aa7..ca2ef4b1a 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.cpp +++ b/src/Simulator/IncrementalRedstoneSimulator.cpp @@ -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); } } diff --git a/src/World.cpp b/src/World.cpp index ecb278e85..ebc37f7b2 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -1725,10 +1725,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 } diff --git a/src/World.h b/src/World.h index e6c665785..517b6b4fa 100644 --- a/src/World.h +++ b/src/World.h @@ -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 diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp index 06b815333..17cf838c3 100644 --- a/src/WorldStorage/NBTChunkSerializer.cpp +++ b/src/WorldStorage/NBTChunkSerializer.cpp @@ -588,7 +588,7 @@ void cNBTChunkSerializer::AddTNTEntity(cTNTEntity * a_TNT) { m_Writer.BeginCompound(""); AddBasicEntity(a_TNT, "PrimedTnt"); - m_Writer.AddByte("Fuse", ((unsigned char)a_TNT->GetFuseTicks()) * 10); + m_Writer.AddByte("Fuse", (unsigned char)a_TNT->GetFuseTicks()); m_Writer.EndCompound(); } diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp index fa0c4dbd9..b52b74932 100644 --- a/src/WorldStorage/WSSAnvil.cpp +++ b/src/WorldStorage/WSSAnvil.cpp @@ -2184,8 +2184,7 @@ void cWSSAnvil::LoadTNTFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NB int FuseTicks = a_NBT.FindChildByName(a_TagIdx, "Fuse"); if (FuseTicks > 0) { - int MojangFuseTicks = (int) a_NBT.GetByte(FuseTicks); - TNT->SetFuseTicks((double) MojangFuseTicks / 10); + TNT->SetFuseTicks((int) a_NBT.GetByte(FuseTicks)); } a_Entities.push_back(TNT.release()); From 60091bcba3f5e533a5b2a749e40f52556297e867 Mon Sep 17 00:00:00 2001 From: Howaner Date: Sat, 8 Mar 2014 12:31:20 +0100 Subject: [PATCH 4/4] Change tnt documentation to ticks --- MCServer/Plugins/APIDump/APIDesc.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua index 6d8272a95..28dffc1b6 100644 --- a/MCServer/Plugins/APIDump/APIDesc.lua +++ b/MCServer/Plugins/APIDump/APIDesc.lua @@ -2026,8 +2026,8 @@ end Functions = { Explode = { Return = "", Notes = "Explode the tnt." }, - GetFuseTicks = { Return = "number", Notes = "Returns the fuse ticks (in seconds) until the tnt will explode." }, - SetFuseTicks = { Return = "number", Notes = "Set the fuse ticks (in seconds) until the tnt will explode." }, + 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", }, @@ -2262,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." },