summaryrefslogtreecommitdiffstats
path: root/src/Entities
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/Entities/EnderCrystal.cpp56
-rw-r--r--src/Entities/EnderCrystal.h33
-rw-r--r--src/Entities/Entity.cpp381
-rw-r--r--src/Entities/Entity.h25
-rw-r--r--src/Entities/ExpOrb.cpp26
-rw-r--r--src/Entities/ExpOrb.h23
-rw-r--r--src/Entities/FallingBlock.cpp19
-rw-r--r--src/Entities/HangingEntity.cpp53
-rw-r--r--src/Entities/HangingEntity.h49
-rw-r--r--src/Entities/ItemFrame.cpp39
-rw-r--r--src/Entities/ItemFrame.h22
-rw-r--r--src/Entities/Pickup.cpp2
-rw-r--r--src/Entities/Pickup.h23
-rw-r--r--src/Entities/Player.cpp38
-rw-r--r--src/Entities/Player.h181
-rw-r--r--src/Entities/ProjectileEntity.cpp12
16 files changed, 627 insertions, 355 deletions
diff --git a/src/Entities/EnderCrystal.cpp b/src/Entities/EnderCrystal.cpp
new file mode 100644
index 000000000..a640b236c
--- /dev/null
+++ b/src/Entities/EnderCrystal.cpp
@@ -0,0 +1,56 @@
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "EnderCrystal.h"
+#include "ClientHandle.h"
+#include "Player.h"
+#include "../Chunk.h"
+
+
+
+
+
+cEnderCrystal::cEnderCrystal(double a_X, double a_Y, double a_Z)
+ : cEntity(etEnderCrystal, a_X, a_Y, a_Z, 1.0, 1.0)
+{
+ SetMaxHealth(5);
+}
+
+
+
+
+
+void cEnderCrystal::SpawnOn(cClientHandle & a_ClientHandle)
+{
+ a_ClientHandle.SendSpawnObject(*this, 51, 0, (Byte)GetYaw(), (Byte)GetPitch());
+}
+
+
+
+
+
+void cEnderCrystal::Tick(float a_Dt, cChunk & a_Chunk)
+{
+ UNUSED(a_Dt);
+
+ a_Chunk.SetBlock(POSX_TOINT, POSY_TOINT, POSZ_TOINT, E_BLOCK_FIRE, 0);
+
+ // No further processing (physics e.t.c.) is needed
+}
+
+
+
+
+
+void cEnderCrystal::KilledBy(cEntity * a_Killer)
+{
+ super::KilledBy(a_Killer);
+
+ m_World->DoExplosionAt(6.0, GetPosX(), GetPosY(), GetPosZ(), true, esEnderCrystal, this);
+
+ Destroy();
+}
+
+
+
+
diff --git a/src/Entities/EnderCrystal.h b/src/Entities/EnderCrystal.h
new file mode 100644
index 000000000..5b86df987
--- /dev/null
+++ b/src/Entities/EnderCrystal.h
@@ -0,0 +1,33 @@
+
+#pragma once
+
+#include "Entity.h"
+
+
+
+
+
+// tolua_begin
+class cEnderCrystal :
+ public cEntity
+{
+ // tolua_end
+ typedef cEntity super;
+
+public:
+ CLASS_PROTODEF(cEnderCrystal);
+
+ cEnderCrystal(double a_X, double a_Y, double a_Z);
+
+private:
+
+ // cEntity overrides:
+ virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
+ virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
+ virtual void KilledBy(cEntity * a_Killer) override;
+
+}; // tolua_export
+
+
+
+
diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp
index 0750ae05e..221cbbea7 100644
--- a/src/Entities/Entity.cpp
+++ b/src/Entities/Entity.cpp
@@ -521,27 +521,35 @@ void cEntity::Tick(float a_Dt, cChunk & a_Chunk)
{
if (a_Chunk.IsValid())
{
- HandlePhysics(a_Dt, a_Chunk);
- }
- }
- if (a_Chunk.IsValid())
- {
- TickBurning(a_Chunk);
- }
- if ((a_Chunk.IsValid()) && (GetPosY() < -46))
- {
- TickInVoid(a_Chunk);
- }
- else
- m_TicksSinceLastVoidDamage = 0;
+ cChunk * NextChunk = a_Chunk.GetNeighborChunk(POSX_TOINT, POSZ_TOINT);
- if (IsMob() || IsPlayer())
- {
- // Set swimming state
- SetSwimState(a_Chunk);
+ if ((NextChunk == NULL) || !NextChunk->IsValid())
+ {
+ return;
+ }
+
+ TickBurning(*NextChunk);
+
+ if (GetPosY() < VOID_BOUNDARY)
+ {
+ TickInVoid(*NextChunk);
+ }
+ else
+ {
+ m_TicksSinceLastVoidDamage = 0;
+ }
+
+ if (IsMob() || IsPlayer())
+ {
+ // Set swimming state
+ SetSwimState(*NextChunk);
- // Handle drowning
- HandleAir();
+ // Handle drowning
+ HandleAir();
+ }
+
+ HandlePhysics(a_Dt, *NextChunk);
+ }
}
}
@@ -562,7 +570,7 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
if ((BlockY >= cChunkDef::Height) || (BlockY < 0))
{
// Outside of the world
-
+
cChunk * NextChunk = a_Chunk.GetNeighborChunk(BlockX, BlockZ);
// See if we can commit our changes. If not, we will discard them.
if (NextChunk != NULL)
@@ -571,210 +579,205 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
NextPos += (NextSpeed * a_Dt);
SetPosition(NextPos);
}
+
return;
}
- // Make sure we got the correct chunk and a valid one. No one ever knows...
- cChunk * NextChunk = a_Chunk.GetNeighborChunk(BlockX, BlockZ);
- if (NextChunk != NULL)
+ int RelBlockX = BlockX - (a_Chunk.GetPosX() * cChunkDef::Width);
+ int RelBlockZ = BlockZ - (a_Chunk.GetPosZ() * cChunkDef::Width);
+ BLOCKTYPE BlockIn = a_Chunk.GetBlock( RelBlockX, BlockY, RelBlockZ );
+ BLOCKTYPE BlockBelow = (BlockY > 0) ? a_Chunk.GetBlock(RelBlockX, BlockY - 1, RelBlockZ) : E_BLOCK_AIR;
+ if (!cBlockInfo::IsSolid(BlockIn)) // Making sure we are not inside a solid block
{
- int RelBlockX = BlockX - (NextChunk->GetPosX() * cChunkDef::Width);
- int RelBlockZ = BlockZ - (NextChunk->GetPosZ() * cChunkDef::Width);
- BLOCKTYPE BlockIn = NextChunk->GetBlock( RelBlockX, BlockY, RelBlockZ );
- BLOCKTYPE BlockBelow = (BlockY > 0) ? NextChunk->GetBlock(RelBlockX, BlockY - 1, RelBlockZ) : E_BLOCK_AIR;
- if (!cBlockInfo::IsSolid(BlockIn)) // Making sure we are not inside a solid block
+ if (m_bOnGround) // check if it's still on the ground
{
- if (m_bOnGround) // check if it's still on the ground
+ if (!cBlockInfo::IsSolid(BlockBelow)) // Check if block below is air or water.
{
- if (!cBlockInfo::IsSolid(BlockBelow)) // Check if block below is air or water.
- {
- m_bOnGround = false;
- }
+ m_bOnGround = false;
}
}
- else
- {
- // Push out entity.
- BLOCKTYPE GotBlock;
+ }
+ else
+ {
+ // Push out entity.
+ BLOCKTYPE GotBlock;
- static const struct
- {
- int x, y, z;
- } gCrossCoords[] =
- {
- { 1, 0, 0},
- {-1, 0, 0},
- { 0, 0, 1},
- { 0, 0, -1},
- } ;
-
- bool IsNoAirSurrounding = true;
- for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++)
+ static const struct
+ {
+ int x, y, z;
+ } gCrossCoords[] =
+ {
+ { 1, 0, 0},
+ {-1, 0, 0},
+ { 0, 0, 1},
+ { 0, 0, -1},
+ } ;
+
+ bool IsNoAirSurrounding = true;
+ for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++)
+ {
+ if (!a_Chunk.UnboundedRelGetBlockType(RelBlockX + gCrossCoords[i].x, BlockY, RelBlockZ + gCrossCoords[i].z, GotBlock))
{
- if (!NextChunk->UnboundedRelGetBlockType(RelBlockX + gCrossCoords[i].x, BlockY, RelBlockZ + gCrossCoords[i].z, GotBlock))
- {
- // The pickup is too close to an unloaded chunk, bail out of any physics handling
- return;
- }
- if (!cBlockInfo::IsSolid(GotBlock))
- {
- NextPos.x += gCrossCoords[i].x;
- NextPos.z += gCrossCoords[i].z;
- IsNoAirSurrounding = false;
- break;
- }
- } // for i - gCrossCoords[]
-
- if (IsNoAirSurrounding)
+ // The pickup is too close to an unloaded chunk, bail out of any physics handling
+ return;
+ }
+ if (!cBlockInfo::IsSolid(GotBlock))
{
- NextPos.y += 0.5;
+ NextPos.x += gCrossCoords[i].x;
+ NextPos.z += gCrossCoords[i].z;
+ IsNoAirSurrounding = false;
+ break;
}
+ } // for i - gCrossCoords[]
+
+ if (IsNoAirSurrounding)
+ {
+ NextPos.y += 0.5;
+ }
- m_bOnGround = true;
+ m_bOnGround = true;
- /*
- // DEBUG:
- LOGD("Entity #%d (%s) is inside a block at {%d, %d, %d}",
- m_UniqueID, GetClass(), BlockX, BlockY, BlockZ
- );
- */
- }
+ /*
+ // DEBUG:
+ LOGD("Entity #%d (%s) is inside a block at {%d, %d, %d}",
+ m_UniqueID, GetClass(), BlockX, BlockY, BlockZ
+ );
+ */
+ }
- if (!m_bOnGround)
+ if (!m_bOnGround)
+ {
+ float fallspeed;
+ if (IsBlockWater(BlockIn))
{
- float fallspeed;
- if (IsBlockWater(BlockIn))
- {
- fallspeed = m_Gravity * a_Dt / 3; // Fall 3x slower in water.
- }
- else if (BlockIn == E_BLOCK_COBWEB)
- {
- NextSpeed.y *= 0.05; // Reduce overall falling speed
- fallspeed = 0; // No falling.
- }
- else
- {
- // Normal gravity
- fallspeed = m_Gravity * a_Dt;
- }
- NextSpeed.y += fallspeed;
+ fallspeed = m_Gravity * a_Dt / 3; // Fall 3x slower in water.
+ }
+ else if (BlockIn == E_BLOCK_COBWEB)
+ {
+ NextSpeed.y *= 0.05; // Reduce overall falling speed
+ fallspeed = 0; // No falling.
}
else
{
- // Friction
- if (NextSpeed.SqrLength() > 0.0004f)
+ // Normal gravity
+ fallspeed = m_Gravity * a_Dt;
+ }
+ NextSpeed.y += fallspeed;
+ }
+ else
+ {
+ // Friction
+ if (NextSpeed.SqrLength() > 0.0004f)
+ {
+ NextSpeed.x *= 0.7f / (1 + a_Dt);
+ if (fabs(NextSpeed.x) < 0.05)
{
- NextSpeed.x *= 0.7f / (1 + a_Dt);
- if (fabs(NextSpeed.x) < 0.05)
- {
- NextSpeed.x = 0;
- }
- NextSpeed.z *= 0.7f / (1 + a_Dt);
- if (fabs(NextSpeed.z) < 0.05)
- {
- NextSpeed.z = 0;
- }
+ NextSpeed.x = 0;
+ }
+ NextSpeed.z *= 0.7f / (1 + a_Dt);
+ if (fabs(NextSpeed.z) < 0.05)
+ {
+ NextSpeed.z = 0;
}
}
+ }
- // Adjust X and Z speed for COBWEB temporary. This speed modification should be handled inside block handlers since we
- // might have different speed modifiers according to terrain.
- if (BlockIn == E_BLOCK_COBWEB)
- {
- NextSpeed.x *= 0.25;
- NextSpeed.z *= 0.25;
- }
+ // Adjust X and Z speed for COBWEB temporary. This speed modification should be handled inside block handlers since we
+ // might have different speed modifiers according to terrain.
+ if (BlockIn == E_BLOCK_COBWEB)
+ {
+ NextSpeed.x *= 0.25;
+ NextSpeed.z *= 0.25;
+ }
- //Get water direction
- Direction WaterDir = m_World->GetWaterSimulator()->GetFlowingDirection(BlockX, BlockY, BlockZ);
+ //Get water direction
+ Direction WaterDir = m_World->GetWaterSimulator()->GetFlowingDirection(BlockX, BlockY, BlockZ);
- m_WaterSpeed *= 0.9f; //Reduce speed each tick
+ m_WaterSpeed *= 0.9f; //Reduce speed each tick
- switch(WaterDir)
- {
- case X_PLUS:
- m_WaterSpeed.x = 0.2f;
- m_bOnGround = false;
- break;
- case X_MINUS:
- m_WaterSpeed.x = -0.2f;
- m_bOnGround = false;
- break;
- case Z_PLUS:
- m_WaterSpeed.z = 0.2f;
- m_bOnGround = false;
- break;
- case Z_MINUS:
- m_WaterSpeed.z = -0.2f;
- m_bOnGround = false;
- break;
-
- default:
+ switch(WaterDir)
+ {
+ case X_PLUS:
+ m_WaterSpeed.x = 0.2f;
+ m_bOnGround = false;
break;
- }
+ case X_MINUS:
+ m_WaterSpeed.x = -0.2f;
+ m_bOnGround = false;
+ break;
+ case Z_PLUS:
+ m_WaterSpeed.z = 0.2f;
+ m_bOnGround = false;
+ break;
+ case Z_MINUS:
+ m_WaterSpeed.z = -0.2f;
+ m_bOnGround = false;
+ break;
+
+ default:
+ break;
+ }
- if (fabs(m_WaterSpeed.x) < 0.05)
- {
- m_WaterSpeed.x = 0;
- }
+ if (fabs(m_WaterSpeed.x) < 0.05)
+ {
+ m_WaterSpeed.x = 0;
+ }
- if (fabs(m_WaterSpeed.z) < 0.05)
- {
- m_WaterSpeed.z = 0;
- }
+ if (fabs(m_WaterSpeed.z) < 0.05)
+ {
+ m_WaterSpeed.z = 0;
+ }
- NextSpeed += m_WaterSpeed;
+ NextSpeed += m_WaterSpeed;
- if( NextSpeed.SqrLength() > 0.f )
+ if( NextSpeed.SqrLength() > 0.f )
+ {
+ cTracer Tracer( GetWorld() );
+ bool HasHit = Tracer.Trace( NextPos, NextSpeed, 2 );
+ if (HasHit) // Oh noez! we hit something
{
- cTracer Tracer( GetWorld() );
- int Ret = Tracer.Trace( NextPos, NextSpeed, 2 );
- if( Ret ) // Oh noez! we hit something
+ // Set to hit position
+ if ((Tracer.RealHit - NextPos).SqrLength() <= (NextSpeed * a_Dt).SqrLength())
{
- // Set to hit position
- if( (Tracer.RealHit - NextPos).SqrLength() <= ( NextSpeed * a_Dt ).SqrLength() )
- {
- if( Ret == 1 )
- {
- if( Tracer.HitNormal.x != 0.f ) NextSpeed.x = 0.f;
- if( Tracer.HitNormal.y != 0.f ) NextSpeed.y = 0.f;
- if( Tracer.HitNormal.z != 0.f ) NextSpeed.z = 0.f;
-
- if( Tracer.HitNormal.y > 0 ) // means on ground
- {
- m_bOnGround = true;
- }
- }
- NextPos.Set(Tracer.RealHit.x,Tracer.RealHit.y,Tracer.RealHit.z);
- NextPos.x += Tracer.HitNormal.x * 0.3f;
- NextPos.y += Tracer.HitNormal.y * 0.05f; // Any larger produces entity vibration-upon-the-spot
- NextPos.z += Tracer.HitNormal.z * 0.3f;
- }
- else
+ if (Tracer.HitNormal.x != 0.f) NextSpeed.x = 0.f;
+ if (Tracer.HitNormal.y != 0.f) NextSpeed.y = 0.f;
+ if (Tracer.HitNormal.z != 0.f) NextSpeed.z = 0.f;
+
+ if (Tracer.HitNormal.y > 0) // means on ground
{
- NextPos += (NextSpeed * a_Dt);
+ m_bOnGround = true;
}
+ NextPos.Set(Tracer.RealHit.x,Tracer.RealHit.y,Tracer.RealHit.z);
+ NextPos.x += Tracer.HitNormal.x * 0.3f;
+ NextPos.y += Tracer.HitNormal.y * 0.05f; // Any larger produces entity vibration-upon-the-spot
+ NextPos.z += Tracer.HitNormal.z * 0.3f;
}
else
{
- // We didn't hit anything, so move =]
NextPos += (NextSpeed * a_Dt);
}
}
- BlockX = (int) floor(NextPos.x);
- BlockZ = (int) floor(NextPos.z);
- NextChunk = NextChunk->GetNeighborChunk(BlockX,BlockZ);
- // See if we can commit our changes. If not, we will discard them.
- if (NextChunk != NULL)
+ else
{
- if (NextPos.x != GetPosX()) SetPosX(NextPos.x);
- if (NextPos.y != GetPosY()) SetPosY(NextPos.y);
- if (NextPos.z != GetPosZ()) SetPosZ(NextPos.z);
- if (NextSpeed.x != GetSpeedX()) SetSpeedX(NextSpeed.x);
- if (NextSpeed.y != GetSpeedY()) SetSpeedY(NextSpeed.y);
- if (NextSpeed.z != GetSpeedZ()) SetSpeedZ(NextSpeed.z);
+ // We didn't hit anything, so move =]
+ NextPos += (NextSpeed * a_Dt);
}
}
+
+ BlockX = (int) floor(NextPos.x);
+ BlockZ = (int) floor(NextPos.z);
+
+ cChunk * NextChunk = a_Chunk.GetNeighborChunk(BlockX, BlockZ);
+ // See if we can commit our changes. If not, we will discard them.
+ if (NextChunk != NULL)
+ {
+ if (NextPos.x != GetPosX()) SetPosX(NextPos.x);
+ if (NextPos.y != GetPosY()) SetPosY(NextPos.y);
+ if (NextPos.z != GetPosZ()) SetPosZ(NextPos.z);
+ if (NextSpeed.x != GetSpeedX()) SetSpeedX(NextSpeed.x);
+ if (NextSpeed.y != GetSpeedY()) SetSpeedY(NextSpeed.y);
+ if (NextSpeed.z != GetSpeedZ()) SetSpeedZ(NextSpeed.z);
+ }
}
@@ -815,14 +818,13 @@ void cEntity::TickBurning(cChunk & a_Chunk)
{
int RelX = x;
int RelZ = z;
- cChunk * CurChunk = a_Chunk.GetRelNeighborChunkAdjustCoords(RelX, RelZ);
- if (CurChunk == NULL)
- {
- continue;
- }
+
for (int y = MinY; y <= MaxY; y++)
{
- switch (CurChunk->GetBlock(RelX, y, RelZ))
+ BLOCKTYPE Block;
+ a_Chunk.UnboundedRelGetBlockType(RelX, y, RelZ, Block);
+
+ switch (Block)
{
case E_BLOCK_FIRE:
{
@@ -922,7 +924,7 @@ void cEntity::TickInVoid(cChunk & a_Chunk)
void cEntity::SetSwimState(cChunk & a_Chunk)
{
- int RelY = (int)floor(m_LastPosY + 0.1);
+ int RelY = (int)floor(GetPosY() + 0.1);
if ((RelY < 0) || (RelY >= cChunkDef::Height - 1))
{
m_IsSwimming = false;
@@ -931,11 +933,10 @@ void cEntity::SetSwimState(cChunk & a_Chunk)
}
BLOCKTYPE BlockIn;
- int RelX = (int)floor(m_LastPosX) - a_Chunk.GetPosX() * cChunkDef::Width;
- int RelZ = (int)floor(m_LastPosZ) - a_Chunk.GetPosZ() * cChunkDef::Width;
+ int RelX = POSX_TOINT - a_Chunk.GetPosX() * cChunkDef::Width;
+ int RelZ = POSZ_TOINT - a_Chunk.GetPosZ() * cChunkDef::Width;
// Check if the player is swimming:
- // Use Unbounded, because we're being called *after* processing super::Tick(), which could have changed our chunk
if (!a_Chunk.UnboundedRelGetBlockType(RelX, RelY, RelZ, BlockIn))
{
// This sometimes happens on Linux machines
diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h
index a73565de7..e41f74b09 100644
--- a/src/Entities/Entity.h
+++ b/src/Entities/Entity.h
@@ -69,6 +69,7 @@ public:
enum eEntityType
{
etEntity, // For all other types
+ etEnderCrystal,
etPlayer,
etPickup,
etMonster,
@@ -117,6 +118,7 @@ public:
BURN_TICKS = 200, ///< How long to keep an entity burning after it has stood in lava / fire
MAX_AIR_LEVEL = 300, ///< Maximum air an entity can have
DROWNING_TICKS = 20, ///< Number of ticks per heart of damage
+ VOID_BOUNDARY = -46 ///< At what position Y to begin applying void damage
} ;
cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, double a_Width, double a_Height);
@@ -129,18 +131,19 @@ public:
eEntityType GetEntityType(void) const { return m_EntityType; }
- bool IsPlayer (void) const { return (m_EntityType == etPlayer); }
- bool IsPickup (void) const { return (m_EntityType == etPickup); }
- bool IsMob (void) const { return (m_EntityType == etMonster); }
+ bool IsEnderCrystal(void) const { return (m_EntityType == etEnderCrystal); }
+ bool IsPlayer (void) const { return (m_EntityType == etPlayer); }
+ bool IsPickup (void) const { return (m_EntityType == etPickup); }
+ bool IsMob (void) const { return (m_EntityType == etMonster); }
bool IsFallingBlock(void) const { return (m_EntityType == etFallingBlock); }
- bool IsMinecart (void) const { return (m_EntityType == etMinecart); }
- bool IsBoat (void) const { return (m_EntityType == etBoat); }
- bool IsTNT (void) const { return (m_EntityType == etTNT); }
- bool IsProjectile (void) const { return (m_EntityType == etProjectile); }
- bool IsExpOrb (void) const { return (m_EntityType == etExpOrb); }
- bool IsFloater (void) const { return (m_EntityType == etFloater); }
- bool IsItemFrame (void) const { return (m_EntityType == etItemFrame); }
- bool IsPainting (void) const { return (m_EntityType == etPainting); }
+ bool IsMinecart (void) const { return (m_EntityType == etMinecart); }
+ bool IsBoat (void) const { return (m_EntityType == etBoat); }
+ bool IsTNT (void) const { return (m_EntityType == etTNT); }
+ bool IsProjectile (void) const { return (m_EntityType == etProjectile); }
+ bool IsExpOrb (void) const { return (m_EntityType == etExpOrb); }
+ bool IsFloater (void) const { return (m_EntityType == etFloater); }
+ bool IsItemFrame (void) const { return (m_EntityType == etItemFrame); }
+ bool IsPainting (void) const { return (m_EntityType == etPainting); }
/// Returns true if the entity is of the specified class or a subclass (cPawn's IsA("cEntity") returns true)
virtual bool IsA(const char * a_ClassName) const;
diff --git a/src/Entities/ExpOrb.cpp b/src/Entities/ExpOrb.cpp
index 3398f1c7b..3623c869a 100644
--- a/src/Entities/ExpOrb.cpp
+++ b/src/Entities/ExpOrb.cpp
@@ -5,20 +5,26 @@
#include "../ClientHandle.h"
-cExpOrb::cExpOrb(double a_X, double a_Y, double a_Z, int a_Reward) :
- cEntity(etExpOrb, a_X, a_Y, a_Z, 0.98, 0.98),
- m_Reward(a_Reward)
+cExpOrb::cExpOrb(double a_X, double a_Y, double a_Z, int a_Reward)
+ : cEntity(etExpOrb, a_X, a_Y, a_Z, 0.98, 0.98)
+ , m_Reward(a_Reward)
+ , m_Timer(0.f)
{
+ SetMaxHealth(5);
+ SetHealth(5);
}
-cExpOrb::cExpOrb(const Vector3d & a_Pos, int a_Reward) :
- cEntity(etExpOrb, a_Pos.x, a_Pos.y, a_Pos.z, 0.98, 0.98),
- m_Reward(a_Reward)
+cExpOrb::cExpOrb(const Vector3d & a_Pos, int a_Reward)
+ : cEntity(etExpOrb, a_Pos.x, a_Pos.y, a_Pos.z, 0.98, 0.98)
+ , m_Reward(a_Reward)
+ , m_Timer(0.f)
{
+ SetMaxHealth(5);
+ SetHealth(5);
}
@@ -52,7 +58,7 @@ void cExpOrb::Tick(float a_Dt, cChunk & a_Chunk)
LOGD("Player %s picked up an ExpOrb. His reward is %i", a_ClosestPlayer->GetName().c_str(), m_Reward);
a_ClosestPlayer->DeltaExperience(m_Reward);
- m_World->BroadcastSoundEffect("random.orb", (int)GetPosX() * 8, (int)GetPosY() * 8, (int)GetPosZ() * 8, 0.5f, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64));
+ m_World->BroadcastSoundEffect("random.orb", (int)(GetPosX() * 8), (int)(GetPosY() * 8), (int)(GetPosZ() * 8), 0.5f, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64));
Destroy();
}
@@ -64,4 +70,10 @@ void cExpOrb::Tick(float a_Dt, cChunk & a_Chunk)
BroadcastMovementUpdate();
}
HandlePhysics(a_Dt, a_Chunk);
+
+ m_Timer += a_Dt;
+ if (m_Timer >= 1000 * 60 * 5) // 5 minutes
+ {
+ Destroy(true);
+ }
}
diff --git a/src/Entities/ExpOrb.h b/src/Entities/ExpOrb.h
index 47d86922c..c1150bd03 100644
--- a/src/Entities/ExpOrb.h
+++ b/src/Entities/ExpOrb.h
@@ -7,14 +7,17 @@
+// tolua_begin
class cExpOrb :
public cEntity
{
typedef cExpOrb super;
public:
+ // tolua_end
+
CLASS_PROTODEF(cExpOrb);
-
+
cExpOrb(double a_X, double a_Y, double a_Z, int a_Reward);
cExpOrb(const Vector3d & a_Pos, int a_Reward);
@@ -22,9 +25,21 @@ public:
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
virtual void SpawnOn(cClientHandle & a_Client) override;
- // cExpOrb functions
- int GetReward(void) const { return m_Reward; }
+ /** Returns the number of ticks that this entity has existed */
+ int GetAge(void) const { return (int)(m_Timer / 50); } // tolua_export
+
+ /** Set the number of ticks that this entity has existed */
+ void SetAge(int a_Age) { m_Timer = (float)(a_Age * 50); } // tolua_export
+
+ /** Get the exp amount */
+ int GetReward(void) const { return m_Reward; } // tolua_export
+
+ /** Set the exp amount */
+ void SetReward(int a_Reward) { m_Reward = a_Reward; } // tolua_export
protected:
int m_Reward;
-} ; \ No newline at end of file
+
+ /** The number of ticks that the entity has existed / timer between collect and destroy; in msec */
+ float m_Timer;
+} ; // tolua_export \ No newline at end of file
diff --git a/src/Entities/FallingBlock.cpp b/src/Entities/FallingBlock.cpp
index 9fcd9ac80..a66c7e4ae 100644
--- a/src/Entities/FallingBlock.cpp
+++ b/src/Entities/FallingBlock.cpp
@@ -33,20 +33,16 @@ void cFallingBlock::SpawnOn(cClientHandle & a_ClientHandle)
void cFallingBlock::Tick(float a_Dt, cChunk & a_Chunk)
{
- float MilliDt = a_Dt * 0.001f;
- AddSpeedY(MilliDt * -9.8f);
- AddPosY(GetSpeedY() * MilliDt);
-
// GetWorld()->BroadcastTeleportEntity(*this); // Test position
- int BlockX = m_OriginalPosition.x;
+ int BlockX = POSX_TOINT;
int BlockY = (int)(GetPosY() - 0.5);
- int BlockZ = m_OriginalPosition.z;
+ int BlockZ = POSZ_TOINT;
if (BlockY < 0)
{
// Fallen out of this world, just continue falling until out of sight, then destroy:
- if (BlockY < 100)
+ if (BlockY < VOID_BOUNDARY)
{
Destroy(true);
}
@@ -86,6 +82,15 @@ void cFallingBlock::Tick(float a_Dt, cChunk & a_Chunk)
Destroy(true);
return;
}
+
+ float MilliDt = a_Dt * 0.001f;
+ AddSpeedY(MilliDt * -9.8f);
+ AddPosition(GetSpeed() * MilliDt);
+
+ if ((GetSpeedX() != 0) || (GetSpeedZ() != 0))
+ {
+ BroadcastMovementUpdate();
+ }
}
diff --git a/src/Entities/HangingEntity.cpp b/src/Entities/HangingEntity.cpp
new file mode 100644
index 000000000..41ac86268
--- /dev/null
+++ b/src/Entities/HangingEntity.cpp
@@ -0,0 +1,53 @@
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "HangingEntity.h"
+#include "ClientHandle.h"
+#include "Player.h"
+
+
+
+
+
+cHangingEntity::cHangingEntity(eEntityType a_EntityType, eBlockFace a_BlockFace, double a_X, double a_Y, double a_Z)
+ : cEntity(a_EntityType, a_X, a_Y, a_Z, 0.8, 0.8)
+ , m_BlockFace(a_BlockFace)
+{
+ SetMaxHealth(1);
+ SetHealth(1);
+}
+
+
+
+
+
+void cHangingEntity::SpawnOn(cClientHandle & a_ClientHandle)
+{
+ int Dir = 0;
+
+ // The client uses different values for item frame directions and block faces. Our constants are for the block faces, so we convert them here to item frame faces
+ switch (m_BlockFace)
+ {
+ case BLOCK_FACE_ZP: break; // Initialised to zero
+ case BLOCK_FACE_ZM: Dir = 2; break;
+ case BLOCK_FACE_XM: Dir = 1; break;
+ case BLOCK_FACE_XP: Dir = 3; break;
+ default: ASSERT(!"Unhandled block face when trying to spawn item frame!"); return;
+ }
+
+ if ((Dir == 0) || (Dir == 2)) // Probably a client bug, but two directions are flipped and contrary to the norm, so we do -180
+ {
+ SetYaw((Dir * 90) - 180);
+ }
+ else
+ {
+ SetYaw(Dir * 90);
+ }
+
+ a_ClientHandle.SendSpawnObject(*this, 71, Dir, (Byte)GetYaw(), (Byte)GetPitch());
+ a_ClientHandle.SendEntityMetadata(*this);
+}
+
+
+
+
diff --git a/src/Entities/HangingEntity.h b/src/Entities/HangingEntity.h
new file mode 100644
index 000000000..6498e4b5b
--- /dev/null
+++ b/src/Entities/HangingEntity.h
@@ -0,0 +1,49 @@
+
+#pragma once
+
+#include "Entity.h"
+
+
+
+
+
+// tolua_begin
+class cHangingEntity :
+ public cEntity
+{
+ // tolua_end
+ typedef cEntity super;
+
+public:
+
+ CLASS_PROTODEF(cHangingEntity);
+
+ cHangingEntity(eEntityType a_EntityType, eBlockFace a_BlockFace, double a_X, double a_Y, double a_Z);
+
+ /** Returns the orientation from the hanging entity */
+ eBlockFace GetDirection() const { return m_BlockFace; } // tolua_export
+
+ /** Set the orientation from the hanging entity */
+ void SetDirection(eBlockFace a_BlockFace) { m_BlockFace = a_BlockFace; } // tolua_export
+
+ /** Returns the X coord. */
+ int GetTileX() const { return POSX_TOINT; } // tolua_export
+
+ /** Returns the Y coord. */
+ int GetTileY() const { return POSY_TOINT; } // tolua_export
+
+ /** Returns the Z coord. */
+ int GetTileZ() const { return POSZ_TOINT; } // tolua_export
+
+private:
+
+ virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
+ virtual void Tick(float a_Dt, cChunk & a_Chunk) override {};
+
+ eBlockFace m_BlockFace;
+
+}; // tolua_export
+
+
+
+
diff --git a/src/Entities/ItemFrame.cpp b/src/Entities/ItemFrame.cpp
index 8cfa5e18d..9dd909880 100644
--- a/src/Entities/ItemFrame.cpp
+++ b/src/Entities/ItemFrame.cpp
@@ -10,43 +10,10 @@
cItemFrame::cItemFrame(eBlockFace a_BlockFace, double a_X, double a_Y, double a_Z)
- : cEntity(etItemFrame, a_X, a_Y, a_Z, 0.8, 0.8),
- m_BlockFace(a_BlockFace),
- m_Item(E_BLOCK_AIR),
- m_Rotation(0)
+ : cHangingEntity(etItemFrame, a_BlockFace, a_X, a_Y, a_Z)
+ , m_Item(E_BLOCK_AIR)
+ , m_Rotation(0)
{
- SetMaxHealth(1);
- SetHealth(1);
-}
-
-
-
-
-
-void cItemFrame::SpawnOn(cClientHandle & a_ClientHandle)
-{
- int Dir = 0;
-
- // The client uses different values for item frame directions and block faces. Our constants are for the block faces, so we convert them here to item frame faces
- switch (m_BlockFace)
- {
- case BLOCK_FACE_ZP: break; // Initialised to zero
- case BLOCK_FACE_ZM: Dir = 2; break;
- case BLOCK_FACE_XM: Dir = 1; break;
- case BLOCK_FACE_XP: Dir = 3; break;
- default: ASSERT(!"Unhandled block face when trying to spawn item frame!"); return;
- }
-
- if ((Dir == 0) || (Dir == 2)) // Probably a client bug, but two directions are flipped and contrary to the norm, so we do -180
- {
- SetYaw((Dir * 90) - 180);
- }
- else
- {
- SetYaw(Dir * 90);
- }
-
- a_ClientHandle.SendSpawnObject(*this, 71, Dir, (Byte)GetYaw(), (Byte)GetPitch());
}
diff --git a/src/Entities/ItemFrame.h b/src/Entities/ItemFrame.h
index 43915e3f9..6577e7d94 100644
--- a/src/Entities/ItemFrame.h
+++ b/src/Entities/ItemFrame.h
@@ -1,7 +1,7 @@
#pragma once
-#include "Entity.h"
+#include "HangingEntity.h"
@@ -9,10 +9,10 @@
// tolua_begin
class cItemFrame :
- public cEntity
+ public cHangingEntity
{
// tolua_end
- typedef cEntity super;
+ typedef cHangingEntity super;
public:
@@ -20,18 +20,24 @@ public:
cItemFrame(eBlockFace a_BlockFace, double a_X, double a_Y, double a_Z);
- const cItem & GetItem(void) { return m_Item; }
- Byte GetRotation(void) const { return m_Rotation; }
+ /** Returns the item in the frame */
+ const cItem & GetItem(void) { return m_Item; } // tolua_export
+
+ /** Set the item in the frame */
+ void SetItem(cItem & a_Item) { m_Item = a_Item; }; // tolua_export
+
+ /** Returns the rotation from the item in the frame */
+ Byte GetRotation(void) const { return m_Rotation; } // tolua_export
+
+ /** Set the rotation from the item in the frame */
+ void SetRotation(Byte a_Rotation) { m_Rotation = a_Rotation; } // tolua_export
private:
- virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
virtual void OnRightClicked(cPlayer & a_Player) override;
- virtual void Tick(float a_Dt, cChunk & a_Chunk) override {};
virtual void KilledBy(cEntity * a_Killer) override;
virtual void GetDrops(cItems & a_Items, cEntity * a_Killer) override;
- eBlockFace m_BlockFace;
cItem m_Item;
Byte m_Rotation;
diff --git a/src/Entities/Pickup.cpp b/src/Entities/Pickup.cpp
index c5503c16a..7fc89b62b 100644
--- a/src/Entities/Pickup.cpp
+++ b/src/Entities/Pickup.cpp
@@ -82,7 +82,7 @@ cPickup::cPickup(double a_PosX, double a_PosY, double a_PosZ, const cItem & a_It
void cPickup::SpawnOn(cClientHandle & a_Client)
{
- a_Client.SendPickupSpawn(*this);
+ a_Client.SendPickupSpawn(*this);
}
diff --git a/src/Entities/Pickup.h b/src/Entities/Pickup.h
index c273567d1..74b917bce 100644
--- a/src/Entities/Pickup.h
+++ b/src/Entities/Pickup.h
@@ -26,31 +26,34 @@ public:
CLASS_PROTODEF(cPickup);
cPickup(double a_PosX, double a_PosY, double a_PosZ, const cItem & a_Item, bool IsPlayerCreated, float a_SpeedX = 0.f, float a_SpeedY = 0.f, float a_SpeedZ = 0.f);
-
+
cItem & GetItem(void) {return m_Item; } // tolua_export
const cItem & GetItem(void) const {return m_Item; }
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
-
+
bool CollectedBy(cPlayer * a_Dest); // tolua_export
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
-
- /// Returns the number of ticks that this entity has existed
- int GetAge(void) const { return (int)(m_Timer / 50); } // tolua_export
-
- /// Returns true if the pickup has already been collected
+
+ /** Returns the number of ticks that this entity has existed */
+ int GetAge(void) const { return (int)(m_Timer / 50); } // tolua_export
+
+ /** Set the number of ticks that this entity has existed */
+ void SetAge(int a_Age) { m_Timer = (float)(a_Age * 50); } // tolua_export
+
+ /** Returns true if the pickup has already been collected */
bool IsCollected(void) const { return m_bCollected; } // tolua_export
- /// Returns true if created by player (i.e. vomiting), used for determining picking-up delay time
+ /** Returns true if created by player (i.e. vomiting), used for determining picking-up delay time */
bool IsPlayerCreated(void) const { return m_bIsPlayerCreated; } // tolua_export
-
+
private:
Vector3d m_ResultingSpeed; //Can be used to modify the resulting speed for the current tick ;)
Vector3d m_WaterSpeed;
- /// The number of ticks that the entity has existed / timer between collect and destroy; in msec
+ /** The number of ticks that the entity has existed / timer between collect and destroy; in msec */
float m_Timer;
cItem m_Item;
diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp
index 440d30595..646aad50f 100644
--- a/src/Entities/Player.cpp
+++ b/src/Entities/Player.cpp
@@ -43,8 +43,9 @@ cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName)
, m_GameMode(eGameMode_NotSet)
, m_IP("")
, m_ClientHandle(a_Client)
- , m_NormalMaxSpeed(0.1)
- , m_SprintingMaxSpeed(0.13)
+ , m_NormalMaxSpeed(1.0)
+ , m_SprintingMaxSpeed(1.3)
+ , m_FlyingMaxSpeed(1.0)
, m_IsCrouched(false)
, m_IsSprinting(false)
, m_IsFlying(false)
@@ -684,7 +685,21 @@ const cSlotNums & cPlayer::GetInventoryPaintSlots(void) const
double cPlayer::GetMaxSpeed(void) const
{
- return m_IsSprinting ? m_SprintingMaxSpeed : m_NormalMaxSpeed;
+ if (m_IsFlying)
+ {
+ return m_FlyingMaxSpeed;
+ }
+ else
+ {
+ if (m_IsSprinting)
+ {
+ return m_SprintingMaxSpeed;
+ }
+ else
+ {
+ return m_NormalMaxSpeed;
+ }
+ }
}
@@ -694,7 +709,7 @@ double cPlayer::GetMaxSpeed(void) const
void cPlayer::SetNormalMaxSpeed(double a_Speed)
{
m_NormalMaxSpeed = a_Speed;
- if (!m_IsSprinting)
+ if (!m_IsSprinting && !m_IsFlying)
{
m_ClientHandle->SendPlayerMaxSpeed();
}
@@ -707,7 +722,7 @@ void cPlayer::SetNormalMaxSpeed(double a_Speed)
void cPlayer::SetSprintingMaxSpeed(double a_Speed)
{
m_SprintingMaxSpeed = a_Speed;
- if (m_IsSprinting)
+ if (m_IsSprinting && !m_IsFlying)
{
m_ClientHandle->SendPlayerMaxSpeed();
}
@@ -717,6 +732,18 @@ void cPlayer::SetSprintingMaxSpeed(double a_Speed)
+void cPlayer::SetFlyingMaxSpeed(double a_Speed)
+{
+ m_FlyingMaxSpeed = a_Speed;
+
+ // Update the flying speed, always:
+ m_ClientHandle->SendPlayerAbilities();
+}
+
+
+
+
+
void cPlayer::SetCrouch(bool a_IsCrouched)
{
// Set the crouch status, broadcast to all visible players
@@ -1462,6 +1489,7 @@ bool cPlayer::MoveToWorld(const char * a_WorldName)
// Add player to all the necessary parts of the new world
SetWorld(World);
+ m_ClientHandle->StreamChunks();
World->AddEntity(this);
World->AddPlayer(this);
diff --git a/src/Entities/Player.h b/src/Entities/Player.h
index f9404dfaf..ea32dbfb9 100644
--- a/src/Entities/Player.h
+++ b/src/Entities/Player.h
@@ -47,19 +47,19 @@ public:
virtual void HandlePhysics(float a_Dt, cChunk &) override { UNUSED(a_Dt); };
- /// Returns the curently equipped weapon; empty item if none
+ /** Returns the curently equipped weapon; empty item if none */
virtual cItem GetEquippedWeapon(void) const override { return m_Inventory.GetEquippedItem(); }
- /// Returns the currently equipped helmet; empty item if none
+ /** Returns the currently equipped helmet; empty item if none */
virtual cItem GetEquippedHelmet(void) const override { return m_Inventory.GetEquippedHelmet(); }
- /// Returns the currently equipped chestplate; empty item if none
+ /** Returns the currently equipped chestplate; empty item if none */
virtual cItem GetEquippedChestplate(void) const override { return m_Inventory.GetEquippedChestplate(); }
- /// Returns the currently equipped leggings; empty item if none
+ /** Returns the currently equipped leggings; empty item if none */
virtual cItem GetEquippedLeggings(void) const override { return m_Inventory.GetEquippedLeggings(); }
- /// Returns the currently equipped boots; empty item if none
+ /** Returns the currently equipped boots; empty item if none */
virtual cItem GetEquippedBoots(void) const override { return m_Inventory.GetEquippedBoots(); }
@@ -77,36 +77,41 @@ public:
*/
short DeltaExperience(short a_Xp_delta);
- /// Gets the experience total - XpTotal for score on death
+ /** Gets the experience total - XpTotal for score on death */
inline short GetXpLifetimeTotal(void) { return m_LifetimeTotalXp; }
- /// Gets the currrent experience
+ /** Gets the currrent experience */
inline short GetCurrentXp(void) { return m_CurrentXp; }
- /// Gets the current level - XpLevel
+ /** Gets the current level - XpLevel */
short GetXpLevel(void);
- /// Gets the experience bar percentage - XpP
+ /** Gets the experience bar percentage - XpP */
float GetXpPercentage(void);
- /// Caculates the amount of XP needed for a given level, ref: http://minecraft.gamepedia.com/XP
+ /** Caculates the amount of XP needed for a given level
+ Ref: http://minecraft.gamepedia.com/XP
+ */
static short XpForLevel(short int a_Level);
- /// inverse of XpForLevel, ref: http://minecraft.gamepedia.com/XP values are as per this with pre-calculations
+ /** Inverse of XpForLevel
+ Ref: http://minecraft.gamepedia.com/XP
+ values are as per this with pre-calculations
+ */
static short CalcLevelFromXp(short int a_CurrentXp);
// tolua_end
- /// Starts charging the equipped bow
+ /** Starts charging the equipped bow */
void StartChargingBow(void);
- /// Finishes charging the current bow. Returns the number of ticks for which the bow has been charged
+ /** Finishes charging the current bow. Returns the number of ticks for which the bow has been charged */
int FinishChargingBow(void);
- /// Cancels the current bow charging
+ /** Cancels the current bow charging */
void CancelChargingBow(void);
- /// Returns true if the player is currently charging the bow
+ /** Returns true if the player is currently charging the bow */
bool IsChargingBow(void) const { return m_IsChargingBow; }
void SetTouchGround( bool a_bTouchGround );
@@ -124,16 +129,16 @@ public:
// tolua_begin
- /// Returns the position where projectiles thrown by this player should start, player eye position + adjustment
+ /** Returns the position where projectiles thrown by this player should start, player eye position + adjustment */
Vector3d GetThrowStartPos(void) const;
- /// Returns the initial speed vector of a throw, with a 3D length of a_SpeedCoeff.
+ /** Returns the initial speed vector of a throw, with a 3D length of a_SpeedCoeff. */
Vector3d GetThrowSpeed(double a_SpeedCoeff) const;
- /// Returns the current gamemode. Partly OBSOLETE, you should use IsGameModeXXX() functions wherever applicable
+ /** Returns the current gamemode. Partly OBSOLETE, you should use IsGameModeXXX() functions wherever applicable */
eGameMode GetGameMode(void) const { return m_GameMode; }
- /// Returns the current effective gamemode (inherited gamemode is resolved before returning)
+ /** Returns the current effective gamemode (inherited gamemode is resolved before returning) */
eGameMode GetEffectiveGameMode(void) const { return (m_GameMode == gmNotSet) ? m_World->GetGameMode() : m_GameMode; }
/** Sets the gamemode for the player.
@@ -142,24 +147,24 @@ public:
*/
void SetGameMode(eGameMode a_GameMode);
- /// Returns true if the player is in Creative mode, either explicitly, or by inheriting from current world
+ /** Returns true if the player is in Creative mode, either explicitly, or by inheriting from current world */
bool IsGameModeCreative(void) const;
- /// Returns true if the player is in Survival mode, either explicitly, or by inheriting from current world
+ /** Returns true if the player is in Survival mode, either explicitly, or by inheriting from current world */
bool IsGameModeSurvival(void) const;
- /// Returns true if the player is in Adventure mode, either explicitly, or by inheriting from current world
+ /** Returns true if the player is in Adventure mode, either explicitly, or by inheriting from current world */
bool IsGameModeAdventure(void) const;
AString GetIP(void) const { return m_IP; } // tolua_export
- /// Returns the associated team, NULL if none
+ /** Returns the associated team, NULL if none */
cTeam * GetTeam(void) { return m_Team; } // tolua_export
- /// Sets the player team, NULL if none
+ /** Sets the player team, NULL if none */
void SetTeam(cTeam * a_Team);
- /// Forces the player to query the scoreboard for his team
+ /** Forces the player to query the scoreboard for his team */
cTeam * UpdateTeam(void);
// tolua_end
@@ -169,24 +174,24 @@ public:
// Sets the current gamemode, doesn't check validity, doesn't send update packets to client
void LoginSetGameMode(eGameMode a_GameMode);
- /// Forces the player to move in the given direction.
+ /** Forces the player to move in the given direction. */
void ForceSetSpeed(Vector3d a_Direction); // tolua_export
- /// Tries to move to a new position, with attachment-related checks (y == -999)
+ /** Tries to move to a new position, with attachment-related checks (y == -999) */
void MoveTo(const Vector3d & a_NewPos); // tolua_export
cWindow * GetWindow(void) { return m_CurrentWindow; } // tolua_export
const cWindow * GetWindow(void) const { return m_CurrentWindow; }
- /// Opens the specified window; closes the current one first using CloseWindow()
+ /** Opens the specified window; closes the current one first using CloseWindow() */
void OpenWindow(cWindow * a_Window); // Exported in ManualBindings.cpp
// tolua_begin
- /// Closes the current window, resets current window to m_InventoryWindow. A plugin may refuse the closing if a_CanRefuse is true
+ /** Closes the current window, resets current window to m_InventoryWindow. A plugin may refuse the closing if a_CanRefuse is true */
void CloseWindow(bool a_CanRefuse = true);
- /// Closes the current window if it matches the specified ID, resets current window to m_InventoryWindow
+ /** Closes the current window if it matches the specified ID, resets current window to m_InventoryWindow */
void CloseWindowIfID(char a_WindowID, bool a_CanRefuse = true);
cClientHandle * GetClientHandle(void) const { return m_ClientHandle; }
@@ -208,10 +213,10 @@ public:
typedef std::list< cGroup* > GroupList;
typedef std::list< std::string > StringList;
- /// Adds a player to existing group or creates a new group when it doesn't exist
+ /** Adds a player to existing group or creates a new group when it doesn't exist */
void AddToGroup( const AString & a_GroupName ); // tolua_export
- /// Removes a player from the group, resolves permissions and group inheritance (case sensitive)
+ /** Removes a player from the group, resolves permissions and group inheritance (case sensitive) */
void RemoveFromGroup( const AString & a_GroupName ); // tolua_export
bool HasPermission( const AString & a_Permission ); // tolua_export
@@ -234,7 +239,7 @@ public:
/** tosses a pickup newly created from a_Item */
void TossPickup(const cItem & a_Item);
- /// Heals the player by the specified amount of HPs (positive only); sends health update
+ /** Heals the player by the specified amount of HPs (positive only); sends health update */
void Heal(int a_Health);
int GetFoodLevel (void) const { return m_FoodLevel; }
@@ -243,7 +248,7 @@ public:
double GetFoodExhaustionLevel (void) const { return m_FoodExhaustionLevel; }
int GetFoodPoisonedTicksRemaining(void) const { return m_FoodPoisonedTicksRemaining; }
- /// Returns true if the player is satiated, i. e. their foodlevel is at the max and they cannot eat anymore
+ /** Returns true if the player is satiated, i. e. their foodlevel is at the max and they cannot eat anymore */
bool IsSatiated(void) const { return (m_FoodLevel >= MAX_FOOD_LEVEL); }
void SetFoodLevel (int a_FoodLevel);
@@ -252,25 +257,28 @@ public:
void SetFoodExhaustionLevel (double a_FoodExhaustionLevel);
void SetFoodPoisonedTicksRemaining(int a_FoodPoisonedTicksRemaining);
- /// Adds to FoodLevel and FoodSaturationLevel, returns true if any food has been consumed, false if player "full"
+ /** Adds to FoodLevel and FoodSaturationLevel, returns true if any food has been consumed, false if player "full" */
bool Feed(int a_Food, double a_Saturation);
- /// Adds the specified exhaustion to m_FoodExhaustion. Expects only positive values.
+ /** Adds the specified exhaustion to m_FoodExhaustion. Expects only positive values. */
void AddFoodExhaustion(double a_Exhaustion)
{
m_FoodExhaustionLevel += a_Exhaustion;
}
- /// Starts the food poisoning for the specified amount of ticks; if already foodpoisoned, sets FoodPoisonedTicksRemaining to the larger of the two
+ /** Starts the food poisoning for the specified amount of ticks; if already foodpoisoned, sets FoodPoisonedTicksRemaining to the larger of the two */
void FoodPoison(int a_NumTicks);
- /// Returns true if the player is currently in the process of eating the currently equipped item
+ /** Returns true if the player is currently in the process of eating the currently equipped item */
bool IsEating(void) const { return (m_EatingFinishTick >= 0); }
- /// Returns true if the player is currently flying.
+ /** Returns true if the player is currently flying. */
bool IsFlying(void) const { return m_IsFlying; }
- /// returns true if the player has thrown out a floater.
+ /** Returns if a player is sleeping in a bed */
+ bool IsInBed(void) const { return m_bIsInBed; }
+
+ /** returns true if the player has thrown out a floater. */
bool IsFishing(void) const { return m_IsFishing; }
void SetIsFishing(bool a_IsFishing, int a_FloaterID = -1) { m_IsFishing = a_IsFishing; m_FloaterID = a_FloaterID; }
@@ -278,14 +286,17 @@ public:
int GetFloaterID(void) const { return m_FloaterID; }
// tolua_end
+
+ /** Sets a player's in-bed state; we can't be sure plugins will keep this value updated, so no exporting */
+ void SetIsInBed(bool a_Flag) { m_bIsInBed = a_Flag; }
- /// Starts eating the currently equipped item. Resets the eating timer and sends the proper animation packet
+ /** Starts eating the currently equipped item. Resets the eating timer and sends the proper animation packet */
void StartEating(void);
- /// Finishes eating the currently equipped item. Consumes the item, updates health and broadcasts the packets
+ /** Finishes eating the currently equipped item. Consumes the item, updates health and broadcasts the packets */
void FinishEating(void);
- /// Aborts the current eating operation
+ /** Aborts the current eating operation */
void AbortEating(void);
virtual void KilledBy(cEntity * a_Killer) override;
@@ -314,45 +325,51 @@ public:
cItem & GetDraggingItem(void) {return m_DraggingItem; }
// In UI windows, when inventory-painting:
- /// Clears the list of slots that are being inventory-painted. To be used by cWindow only
+ /** Clears the list of slots that are being inventory-painted. To be used by cWindow only */
void ClearInventoryPaintSlots(void);
- /// Adds a slot to the list for inventory painting. To be used by cWindow only
+ /** Adds a slot to the list for inventory painting. To be used by cWindow only */
void AddInventoryPaintSlot(int a_SlotNum);
- /// Returns the list of slots currently stored for inventory painting. To be used by cWindow only
+ /** Returns the list of slots currently stored for inventory painting. To be used by cWindow only */
const cSlotNums & GetInventoryPaintSlots(void) const;
// tolua_begin
- /// Returns the current maximum speed, as reported in the 1.6.1+ protocol (takes current sprinting state into account)
+ /** Returns the current relative maximum speed (takes current sprinting / flying state into account) */
double GetMaxSpeed(void) const;
- /// Gets the normal maximum speed, as reported in the 1.6.1+ protocol, in the protocol units
+ /** Gets the normal relative maximum speed */
double GetNormalMaxSpeed(void) const { return m_NormalMaxSpeed; }
- /// Gets the sprinting maximum speed, as reported in the 1.6.1+ protocol, in the protocol units
+ /** Gets the sprinting relative maximum speed */
double GetSprintingMaxSpeed(void) const { return m_SprintingMaxSpeed; }
- /// Sets the normal maximum speed, as reported in the 1.6.1+ protocol. Sends the update to player, if needed.
+ /** Gets the flying relative maximum speed */
+ double GetFlyingMaxSpeed(void) const { return m_FlyingMaxSpeed; }
+
+ /** Sets the normal relative maximum speed. Sends the update to player, if needed. */
void SetNormalMaxSpeed(double a_Speed);
- /// Sets the sprinting maximum speed, as reported in the 1.6.1+ protocol. Sends the update to player, if needed.
+ /** Sets the sprinting relative maximum speed. Sends the update to player, if needed. */
void SetSprintingMaxSpeed(double a_Speed);
- /// Sets the crouch status, broadcasts to all visible players
+ /** Sets the flying relative maximum speed. Sends the update to player, if needed. */
+ void SetFlyingMaxSpeed(double a_Speed);
+
+ /** Sets the crouch status, broadcasts to all visible players */
void SetCrouch(bool a_IsCrouched);
- /// Starts or stops sprinting, sends the max speed update to the client, if needed
+ /** Starts or stops sprinting, sends the max speed update to the client, if needed */
void SetSprint(bool a_IsSprinting);
- /// Flags the player as flying
+ /** Flags the player as flying */
void SetFlying(bool a_IsFlying);
- /// If true the player can fly even when he's not in creative.
+ /** If true the player can fly even when he's not in creative. */
void SetCanFly(bool a_CanFly);
- /// Returns wheter the player can fly or not.
+ /** Returns wheter the player can fly or not. */
virtual bool CanFly(void) const { return m_CanFly; }
// tolua_end
@@ -371,10 +388,10 @@ protected:
GroupList m_ResolvedGroups;
GroupList m_Groups;
- std::string m_PlayerName;
- std::string m_LoadedWorldName;
+ AString m_PlayerName;
+ AString m_LoadedWorldName;
- /// Xp Level stuff
+ /** Xp Level stuff */
enum
{
XP_TO_LEVEL15 = 255,
@@ -385,22 +402,22 @@ protected:
bool m_bVisible;
// Food-related variables:
- /// Represents the food bar, one point equals half a "drumstick"
+ /** Represents the food bar, one point equals half a "drumstick" */
int m_FoodLevel;
- /// "Overcharge" for the m_FoodLevel; is depleted before m_FoodLevel
+ /** "Overcharge" for the m_FoodLevel; is depleted before m_FoodLevel */
double m_FoodSaturationLevel;
- /// Count-up to the healing or damaging action, based on m_FoodLevel
+ /** Count-up to the healing or damaging action, based on m_FoodLevel */
int m_FoodTickTimer;
- /// A "buffer" which adds up hunger before it is substracted from m_FoodSaturationLevel or m_FoodLevel. Each action adds a little
+ /** A "buffer" which adds up hunger before it is substracted from m_FoodSaturationLevel or m_FoodLevel. Each action adds a little */
double m_FoodExhaustionLevel;
- /// Number of ticks remaining for the foodpoisoning effect; zero if not foodpoisoned
+ /** Number of ticks remaining for the foodpoisoning effect; zero if not foodpoisoned */
int m_FoodPoisonedTicksRemaining;
- /// Last position that has been recorded for food-related processing:
+ /** Last position that has been recorded for food-related processing: */
Vector3d m_LastFoodPos;
float m_LastJumpHeight;
@@ -416,7 +433,7 @@ protected:
eGameMode m_GameMode;
AString m_IP;
- /// The item being dragged by the cursor while in a UI window
+ /** The item being dragged by the cursor while in a UI window */
cItem m_DraggingItem;
long long m_LastPlayerListTime;
@@ -426,12 +443,21 @@ protected:
cSlotNums m_InventoryPaintSlots;
- /// Max speed, in ENTITY_PROPERTIES packet's units, when the player is walking. 0.1 by default
+ /** Max speed, relative to the game default.
+ 1 means regular speed, 2 means twice as fast, 0.5 means half-speed.
+ Default value is 1. */
double m_NormalMaxSpeed;
- /// Max speed, in ENTITY_PROPERTIES packet's units, when the player is sprinting. 0.13 by default
+ /** Max speed, relative to the game default max speed, when sprinting.
+ 1 means regular speed, 2 means twice as fast, 0.5 means half-speed.
+ Default value is 1.3. */
double m_SprintingMaxSpeed;
+ /** Max speed, relative to the game default flying max speed, when flying.
+ 1 means regular speed, 2 means twice as fast, 0.5 means half-speed.
+ Default value is 1. */
+ double m_FlyingMaxSpeed;
+
bool m_IsCrouched;
bool m_IsSprinting;
bool m_IsFlying;
@@ -441,10 +467,10 @@ protected:
bool m_CanFly; // If this is true the player can fly. Even if he is not in creative.
- /// The world tick in which eating will be finished. -1 if not eating
+ /** The world tick in which eating will be finished. -1 if not eating */
Int64 m_EatingFinishTick;
- /// Player Xp level
+ /** Player Xp level */
short int m_LifetimeTotalXp;
short int m_CurrentXp;
@@ -456,7 +482,7 @@ protected:
int m_FloaterID;
- cTeam* m_Team;
+ cTeam * m_Team;
@@ -465,20 +491,25 @@ protected:
virtual void Destroyed(void);
- /// Filters out damage for creative mode/friendly fire
+ /** Filters out damage for creative mode/friendly fire */
virtual void DoTakeDamage(TakeDamageInfo & TDI) override;
/** Stops players from burning in creative mode */
virtual void TickBurning(cChunk & a_Chunk) override;
- /// Called in each tick to handle food-related processing
+ /** Called in each tick to handle food-related processing */
void HandleFood(void);
- /// Called in each tick if the player is fishing to make sure the floater dissapears when the player doesn't have a fishing rod as equipped item.
+ /** Called in each tick if the player is fishing to make sure the floater dissapears when the player doesn't have a fishing rod as equipped item. */
void HandleFloater(void);
- /// Adds food exhaustion based on the difference between Pos and LastPos, sprinting status and swimming (in water block)
+ /** Adds food exhaustion based on the difference between Pos and LastPos, sprinting status and swimming (in water block) */
void ApplyFoodExhaustionFromMovement();
+
+ /** Flag representing whether the player is currently in a bed
+ Set by a right click on unoccupied bed, unset by a time fast forward or teleport */
+ bool m_bIsInBed;
+
} ; // tolua_export
diff --git a/src/Entities/ProjectileEntity.cpp b/src/Entities/ProjectileEntity.cpp
index f4ab825f2..a9735a53c 100644
--- a/src/Entities/ProjectileEntity.cpp
+++ b/src/Entities/ProjectileEntity.cpp
@@ -4,6 +4,7 @@
// Implements the cProjectileEntity class representing the common base class for projectiles, as well as individual projectile types
#include "Globals.h"
+#include "../Bindings/PluginManager.h"
#include "ProjectileEntity.h"
#include "../ClientHandle.h"
#include "Player.h"
@@ -66,6 +67,11 @@ protected:
eBlockFace Face;
if (bb.CalcLineIntersection(Line1, Line2, LineCoeff, Face))
{
+ if (cPluginManager::Get()->CallHookProjectileHitBlock(*m_Projectile))
+ {
+ return false;
+ }
+
Vector3d Intersection = Line1 + m_Projectile->GetSpeed() * LineCoeff;
m_Projectile->OnHitSolidBlock(Intersection, Face);
return true;
@@ -147,7 +153,11 @@ public:
}
// TODO: Some entities don't interact with the projectiles (pickups, falling blocks)
- // TODO: Allow plugins to interfere about which entities can be hit
+ if (cPluginManager::Get()->CallHookProjectileHitEntity(*m_Projectile, *a_Entity))
+ {
+ // A plugin disagreed.
+ return false;
+ }
if (LineCoeff < m_MinCoeff)
{