summaryrefslogtreecommitdiffstats
path: root/src/Entities
diff options
context:
space:
mode:
Diffstat (limited to 'src/Entities')
-rw-r--r--src/Entities/Entity.cpp48
-rw-r--r--src/Entities/Entity.h45
-rw-r--r--src/Entities/FallingBlock.cpp5
-rw-r--r--src/Entities/ItemFrame.cpp4
-rw-r--r--src/Entities/Player.cpp57
-rw-r--r--src/Entities/Player.h13
-rw-r--r--src/Entities/ProjectileEntity.cpp4
7 files changed, 111 insertions, 65 deletions
diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp
index 1226a2319..ee7ce06ac 100644
--- a/src/Entities/Entity.cpp
+++ b/src/Entities/Entity.cpp
@@ -129,9 +129,9 @@ const char * cEntity::GetParentClass(void) const
-bool cEntity::Initialize(cWorld * a_World)
+bool cEntity::Initialize(cWorld & a_World)
{
- if (cPluginManager::Get()->CallHookSpawningEntity(*a_World, *this))
+ if (cPluginManager::Get()->CallHookSpawningEntity(a_World, *this))
{
return false;
}
@@ -144,13 +144,13 @@ bool cEntity::Initialize(cWorld * a_World)
*/
m_IsInitialized = true;
- m_World = a_World;
+ m_World = &a_World;
m_World->AddEntity(this);
- cPluginManager::Get()->CallHookSpawnedEntity(*a_World, *this);
+ cPluginManager::Get()->CallHookSpawnedEntity(a_World, *this);
// Spawn the entity on the clients:
- a_World->BroadcastSpawnEntity(*this);
+ a_World.BroadcastSpawnEntity(*this);
return true;
}
@@ -179,14 +179,9 @@ void cEntity::WrapRotation(void)
void cEntity::WrapSpeed(void)
{
- // There shoudn't be a need for flipping the flag on because this function is called
- // after any update, so the flag is already turned on
- if (m_Speed.x > 78.0f) m_Speed.x = 78.0f;
- else if (m_Speed.x < -78.0f) m_Speed.x = -78.0f;
- if (m_Speed.y > 78.0f) m_Speed.y = 78.0f;
- else if (m_Speed.y < -78.0f) m_Speed.y = -78.0f;
- if (m_Speed.z > 78.0f) m_Speed.z = 78.0f;
- else if (m_Speed.z < -78.0f) m_Speed.z = -78.0f;
+ m_Speed.x = Clamp(m_Speed.x, -78.0, 78.0);
+ m_Speed.y = Clamp(m_Speed.y, -78.0, 78.0);
+ m_Speed.z = Clamp(m_Speed.z, -78.0, 78.0);
}
@@ -1076,6 +1071,17 @@ void cEntity::SetSwimState(cChunk & a_Chunk)
+void cEntity::DoSetSpeed(double a_SpeedX, double a_SpeedY, double a_SpeedZ)
+{
+ m_Speed.Set(a_SpeedX, a_SpeedY, a_SpeedZ);
+
+ WrapSpeed();
+}
+
+
+
+
+
void cEntity::HandleAir(void)
{
// Ref.: http://www.minecraftwiki.net/wiki/Chunk_format
@@ -1428,9 +1434,7 @@ void cEntity::SetRoll(double a_Roll)
void cEntity::SetSpeed(double a_SpeedX, double a_SpeedY, double a_SpeedZ)
{
- m_Speed.Set(a_SpeedX, a_SpeedY, a_SpeedZ);
-
- WrapSpeed();
+ DoSetSpeed(a_SpeedX, a_SpeedY, a_SpeedZ);
}
@@ -1438,9 +1442,7 @@ void cEntity::SetSpeed(double a_SpeedX, double a_SpeedY, double a_SpeedZ)
void cEntity::SetSpeedX(double a_SpeedX)
{
- m_Speed.x = a_SpeedX;
-
- WrapSpeed();
+ SetSpeed(a_SpeedX, m_Speed.y, m_Speed.z);
}
@@ -1448,9 +1450,7 @@ void cEntity::SetSpeedX(double a_SpeedX)
void cEntity::SetSpeedY(double a_SpeedY)
{
- m_Speed.y = a_SpeedY;
-
- WrapSpeed();
+ SetSpeed(m_Speed.x, a_SpeedY, m_Speed.z);
}
@@ -1458,9 +1458,7 @@ void cEntity::SetSpeedY(double a_SpeedY)
void cEntity::SetSpeedZ(double a_SpeedZ)
{
- m_Speed.z = a_SpeedZ;
-
- WrapSpeed();
+ SetSpeed(m_Speed.x, m_Speed.y, a_SpeedZ);
}
diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h
index 0c393c0f5..2df66e353 100644
--- a/src/Entities/Entity.h
+++ b/src/Entities/Entity.h
@@ -146,8 +146,9 @@ public:
cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, double a_Width, double a_Height);
virtual ~cEntity();
- /// Spawns the entity in the world; returns true if spawned, false if not (plugin disallowed)
- virtual bool Initialize(cWorld * a_World);
+ /** Spawns the entity in the world; returns true if spawned, false if not (plugin disallowed).
+ Adds the entity to the world. */
+ virtual bool Initialize(cWorld & a_World);
// tolua_begin
@@ -214,11 +215,22 @@ public:
void SetYaw (double a_Yaw); // In degrees, normalizes to [-180, +180)
void SetPitch (double a_Pitch); // In degrees, normalizes to [-180, +180)
void SetRoll (double a_Roll); // In degrees, normalizes to [-180, +180)
- void SetSpeed (double a_SpeedX, double a_SpeedY, double a_SpeedZ);
- void SetSpeed (const Vector3d & a_Speed) { SetSpeed(a_Speed.x, a_Speed.y, a_Speed.z); }
- void SetSpeedX (double a_SpeedX);
- void SetSpeedY (double a_SpeedY);
- void SetSpeedZ (double a_SpeedZ);
+
+ /** Sets the speed of the entity, measured in m / sec */
+ void SetSpeed(double a_SpeedX, double a_SpeedY, double a_SpeedZ);
+
+ /** Sets the speed of the entity, measured in m / sec */
+ void SetSpeed(const Vector3d & a_Speed) { SetSpeed(a_Speed.x, a_Speed.y, a_Speed.z); }
+
+ /** Sets the speed in the X axis, leaving the other speed components intact. Measured in m / sec. */
+ void SetSpeedX(double a_SpeedX);
+
+ /** Sets the speed in the Y axis, leaving the other speed components intact. Measured in m / sec. */
+ void SetSpeedY(double a_SpeedY);
+
+ /** Sets the speed in the Z axis, leaving the other speed components intact. Measured in m / sec. */
+ void SetSpeedZ(double a_SpeedZ);
+
void SetWidth (double a_Width);
void AddPosX (double a_AddPosX);
@@ -421,10 +433,16 @@ public:
UNUSED(a_Killer);
}
+ /** Sets the internal world pointer to a new cWorld, doesn't update anything else. */
+ void SetWorld(cWorld * a_World) { m_World = a_World; }
+
protected:
static cCriticalSection m_CSCount;
static int m_EntityCount;
+ /** Measured in meter/second (m/s) */
+ Vector3d m_Speed;
+
int m_UniqueID;
int m_Health;
@@ -482,13 +500,15 @@ protected:
/// Time, in ticks, since the last damage dealt by the void. Reset to zero when moving out of the void.
int m_TicksSinceLastVoidDamage;
-
+
+ /** Does the actual speed-setting. The default implementation just sets the member variable value;
+ overrides can provide further processing, such as forcing players to move at the given speed. */
+ virtual void DoSetSpeed(double a_SpeedX, double a_SpeedY, double a_SpeedZ);
+
virtual void Destroyed(void) {} // Called after the entity has been destroyed
- void SetWorld(cWorld * a_World) { m_World = a_World; }
-
/** Called in each tick to handle air-related processing i.e. drowning */
- virtual void HandleAir();
+ virtual void HandleAir(void);
/** Called once per tick to set IsSwimming and IsSubmerged */
virtual void SetSwimState(cChunk & a_Chunk);
@@ -504,9 +524,6 @@ private:
/** Measured in degrees, [-180, +180) */
double m_HeadYaw;
- /** Measured in meter/second (m/s) */
- Vector3d m_Speed;
-
/** Measured in degrees, [-180, +180) */
Vector3d m_Rot;
diff --git a/src/Entities/FallingBlock.cpp b/src/Entities/FallingBlock.cpp
index beb58f207..111c5fa84 100644
--- a/src/Entities/FallingBlock.cpp
+++ b/src/Entities/FallingBlock.cpp
@@ -55,9 +55,8 @@ void cFallingBlock::Tick(float a_Dt, cChunk & a_Chunk)
return;
}
- int idx = a_Chunk.MakeIndexNoCheck(BlockX - a_Chunk.GetPosX() * cChunkDef::Width, BlockY, BlockZ - a_Chunk.GetPosZ() * cChunkDef::Width);
- BLOCKTYPE BlockBelow = a_Chunk.GetBlock(idx);
- NIBBLETYPE BelowMeta = a_Chunk.GetMeta(idx);
+ BLOCKTYPE BlockBelow = a_Chunk.GetBlock(BlockX - a_Chunk.GetPosX() * cChunkDef::Width, BlockY, BlockZ - a_Chunk.GetPosZ() * cChunkDef::Width);
+ NIBBLETYPE BelowMeta = a_Chunk.GetMeta(BlockX - a_Chunk.GetPosX() * cChunkDef::Width, BlockY, BlockZ - a_Chunk.GetPosZ() * cChunkDef::Width);
if (cSandSimulator::DoesBreakFallingThrough(BlockBelow, BelowMeta))
{
// Fallen onto a block that breaks this into pickups (e. g. half-slab)
diff --git a/src/Entities/ItemFrame.cpp b/src/Entities/ItemFrame.cpp
index 9dd909880..7bc7bda8d 100644
--- a/src/Entities/ItemFrame.cpp
+++ b/src/Entities/ItemFrame.cpp
@@ -55,6 +55,7 @@ void cItemFrame::KilledBy(cEntity * a_Killer)
{
if (m_Item.IsEmpty())
{
+ SetHealth(0);
super::KilledBy(a_Killer);
Destroy();
return;
@@ -69,8 +70,9 @@ void cItemFrame::KilledBy(cEntity * a_Killer)
}
SetHealth(GetMaxHealth());
- m_Item.Clear();
+ m_Item.Empty();
m_Rotation = 0;
+ SetInvulnerableTicks(0);
GetWorld()->BroadcastEntityMetadata(*this);
}
diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp
index 0dfdcfd8b..fdc0bb390 100644
--- a/src/Entities/Player.cpp
+++ b/src/Entities/Player.cpp
@@ -22,6 +22,12 @@
#include "inifile/iniFile.h"
#include "json/json.h"
+// 6000 ticks or 5 minutes
+#define PLAYER_INVENTORY_SAVE_INTERVAL 6000
+
+// 1000 = once per second
+#define PLAYER_LIST_TIME_MS 1000
+
@@ -64,6 +70,7 @@ cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName)
, m_BowCharge(0)
, m_FloaterID(-1)
, m_Team(NULL)
+ , m_TicksUntilNextSave(PLAYER_INVENTORY_SAVE_INTERVAL)
{
LOGD("Created a player object for \"%s\" @ \"%s\" at %p, ID %d",
a_PlayerName.c_str(), a_Client->GetIPString().c_str(),
@@ -250,7 +257,7 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk)
// Send Player List (Once per m_LastPlayerListTime/1000 ms)
cTimer t1;
- if (m_LastPlayerListTime + cPlayer::PLAYER_LIST_TIME_MS <= t1.GetNowTime())
+ if (m_LastPlayerListTime + PLAYER_LIST_TIME_MS <= t1.GetNowTime())
{
m_World->SendPlayerList(this);
m_LastPlayerListTime = t1.GetNowTime();
@@ -260,6 +267,16 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk)
{
m_LastGroundHeight = (float)GetPosY();
}
+
+ if (m_TicksUntilNextSave == 0)
+ {
+ SaveToDisk();
+ m_TicksUntilNextSave = PLAYER_INVENTORY_SAVE_INTERVAL;
+ }
+ else
+ {
+ m_TicksUntilNextSave--;
+ }
}
@@ -940,6 +957,8 @@ void cPlayer::Killed(cEntity * a_Victim)
void cPlayer::Respawn(void)
{
+ ASSERT(m_World != NULL);
+
m_Health = GetMaxHealth();
SetInvulnerableTicks(20);
@@ -952,7 +971,7 @@ void cPlayer::Respawn(void)
m_LifetimeTotalXp = 0;
// ToDo: send score to client? How?
- m_ClientHandle->SendRespawn();
+ m_ClientHandle->SendRespawn(*m_World);
// Extinguish the fire:
StopBurning();
@@ -1255,6 +1274,17 @@ Vector3d cPlayer::GetThrowSpeed(double a_SpeedCoeff) const
void cPlayer::ForceSetSpeed(const Vector3d & a_Speed)
{
SetSpeed(a_Speed);
+}
+
+
+
+
+
+void cPlayer::DoSetSpeed(double a_SpeedX, double a_SpeedY, double a_SpeedZ)
+{
+ super::DoSetSpeed(a_SpeedX, a_SpeedY, a_SpeedZ);
+
+ // Send the speed to the client so he actualy moves
m_ClientHandle->SendEntityVelocity(*this);
}
@@ -1583,21 +1613,19 @@ bool cPlayer::MoveToWorld(const char * a_WorldName)
return false;
}
- eDimension OldDimension = m_World->GetDimension();
-
+ // Send the respawn packet:
+ if (m_ClientHandle != NULL)
+ {
+ m_ClientHandle->SendRespawn(*World);
+ }
+
// Remove all links to the old world
m_World->RemovePlayer(this);
- m_ClientHandle->RemoveFromAllChunks();
- m_World->RemoveEntity(this);
// If the dimension is different, we can send the respawn packet
// http://wiki.vg/Protocol#0x09 says "don't send if dimension is the same" as of 2013_07_02
- m_ClientHandle->MoveToWorld(*World, (OldDimension != World->GetDimension()));
- // Add player to all the necessary parts of the new world
- SetWorld(World);
- m_ClientHandle->StreamChunks();
- World->AddEntity(this);
+ // Queue adding player to the new world, including all the necessary adjustments to the object
World->AddPlayer(this);
return true;
@@ -1650,13 +1678,6 @@ bool cPlayer::LoadFromDisk()
{
LoadPermissionsFromDisk();
- // Log player permissions, cause it's what the cool kids do
- LOGINFO("Player %s has permissions:", GetName().c_str() );
- for( PermissionMap::iterator itr = m_ResolvedPermissions.begin(); itr != m_ResolvedPermissions.end(); ++itr )
- {
- if( itr->second ) LOG(" - %s", itr->first.c_str() );
- }
-
AString SourceFile;
Printf(SourceFile, "players/%s.json", GetName().c_str() );
diff --git a/src/Entities/Player.h b/src/Entities/Player.h
index b7cb27d6c..b2142a18b 100644
--- a/src/Entities/Player.h
+++ b/src/Entities/Player.h
@@ -194,7 +194,8 @@ 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.
+ @deprecated Use SetSpeed instead. */
void ForceSetSpeed(const Vector3d & a_Speed); // tolua_export
/** Tries to move to a new position, with attachment-related checks (y == -999) */
@@ -328,6 +329,8 @@ public:
void SetVisible( bool a_bVisible ); // tolua_export
bool IsVisible(void) const { return m_bVisible; } // tolua_export
+ /** Moves the player to the specified world.
+ Returns true if successful, false on failure (world not found). */
bool MoveToWorld(const char * a_WorldName); // tolua_export
bool SaveToDisk(void);
@@ -459,7 +462,6 @@ protected:
cItem m_DraggingItem;
long long m_LastPlayerListTime;
- static const unsigned short PLAYER_LIST_TIME_MS = 1000; // 1000 = once per second
cClientHandle * m_ClientHandle;
@@ -510,6 +512,9 @@ protected:
+ /** Sets the speed and sends it to the client, so that they are forced to move so. */
+ virtual void DoSetSpeed(double a_SpeedX, double a_SpeedY, double a_SpeedZ) override;
+
void ResolvePermissions(void);
void ResolveGroups(void);
@@ -537,6 +542,10 @@ protected:
Set by a right click on unoccupied bed, unset by a time fast forward or teleport */
bool m_bIsInBed;
+ /** How long till the player's inventory will be saved
+ Default save interval is #defined in PLAYER_INVENTORY_SAVE_INTERVAL */
+ unsigned int m_TicksUntilNextSave;
+
} ; // tolua_export
diff --git a/src/Entities/ProjectileEntity.cpp b/src/Entities/ProjectileEntity.cpp
index 3e48d310c..95c494569 100644
--- a/src/Entities/ProjectileEntity.cpp
+++ b/src/Entities/ProjectileEntity.cpp
@@ -76,12 +76,12 @@ protected:
eBlockFace Face;
if (bb.CalcLineIntersection(Line1, Line2, LineCoeff, Face))
{
- if (cPluginManager::Get()->CallHookProjectileHitBlock(*m_Projectile))
+ Vector3d Intersection = Line1 + m_Projectile->GetSpeed() * LineCoeff;
+ if (cPluginManager::Get()->CallHookProjectileHitBlock(*m_Projectile, a_BlockX, a_BlockY, a_BlockZ, Face, &Intersection))
{
return false;
}
- Vector3d Intersection = Line1 + m_Projectile->GetSpeed() * LineCoeff;
m_Projectile->OnHitSolidBlock(Intersection, Face);
return true;
}