diff options
Diffstat (limited to '')
-rw-r--r-- | src/Entities/EnderCrystal.cpp | 56 | ||||
-rw-r--r-- | src/Entities/EnderCrystal.h | 33 | ||||
-rw-r--r-- | src/Entities/Entity.cpp | 381 | ||||
-rw-r--r-- | src/Entities/Entity.h | 25 | ||||
-rw-r--r-- | src/Entities/ExpOrb.cpp | 26 | ||||
-rw-r--r-- | src/Entities/ExpOrb.h | 23 | ||||
-rw-r--r-- | src/Entities/FallingBlock.cpp | 19 | ||||
-rw-r--r-- | src/Entities/HangingEntity.cpp | 53 | ||||
-rw-r--r-- | src/Entities/HangingEntity.h | 49 | ||||
-rw-r--r-- | src/Entities/ItemFrame.cpp | 39 | ||||
-rw-r--r-- | src/Entities/ItemFrame.h | 22 | ||||
-rw-r--r-- | src/Entities/Pickup.cpp | 2 | ||||
-rw-r--r-- | src/Entities/Pickup.h | 23 | ||||
-rw-r--r-- | src/Entities/Player.cpp | 38 | ||||
-rw-r--r-- | src/Entities/Player.h | 181 | ||||
-rw-r--r-- | src/Entities/ProjectileEntity.cpp | 12 |
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) { |