Removed some more cChunkPtr usage
git-svn-id: http://mc-server.googlecode.com/svn/trunk@298 0a769ca7-a7f5-676a-18bf-c427514a06d6
This commit is contained in:
parent
0b616909e3
commit
d592882fe0
@ -1148,7 +1148,7 @@ bool cChunk::HasAnyClients(void)
|
||||
|
||||
|
||||
|
||||
void cChunk::AddEntity( cEntity * a_Entity )
|
||||
void cChunk::AddEntity( cEntity * a_Entity)
|
||||
{
|
||||
cCSLock Lock(m_CSEntities);
|
||||
if (a_Entity->GetEntityType() != cEntity::E_PLAYER)
|
||||
@ -1171,9 +1171,13 @@ void cChunk::RemoveEntity(cEntity * a_Entity)
|
||||
m_Entities.remove(a_Entity);
|
||||
SizeAfter = m_Entities.size();
|
||||
}
|
||||
if ((a_Entity->GetEntityType() != cEntity::E_PLAYER) && (SizeBefore != SizeAfter))
|
||||
if (SizeBefore != SizeAfter)
|
||||
{
|
||||
MarkDirty();
|
||||
// Mark as dirty if it was a server-generated entity:
|
||||
if (a_Entity->GetEntityType() != cEntity::E_PLAYER)
|
||||
{
|
||||
MarkDirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,6 +70,23 @@ public:
|
||||
|
||||
|
||||
|
||||
/** Interface class used for comparing clients of two chunks.
|
||||
Used primarily for entity moving while both chunks are locked.
|
||||
*/
|
||||
class cClientDiffCallback
|
||||
{
|
||||
public:
|
||||
/// Called for clients that are in Chunk1 and not in Chunk2,
|
||||
virtual void Removed(cClientHandle * a_Client) = 0;
|
||||
|
||||
/// Called for clients that are in Chunk2 and not in Chunk1.
|
||||
virtual void Added(cClientHandle * a_Client) = 0;
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
struct sSetBlock
|
||||
{
|
||||
int x, y, z;
|
||||
@ -121,7 +138,7 @@ public:
|
||||
|
||||
/// Returns true if there is a block entity at the coords specified
|
||||
bool HasBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ);
|
||||
|
||||
|
||||
void Tick(float a_Dt, MTRand & a_TickRandom);
|
||||
|
||||
int GetPosX() { return m_PosX; }
|
||||
@ -149,7 +166,7 @@ public:
|
||||
bool HasClient (cClientHandle* a_Client );
|
||||
bool HasAnyClients(void); // Returns true if theres any client in the chunk; false otherwise
|
||||
|
||||
void AddEntity( cEntity * a_Entity );
|
||||
void AddEntity( cEntity * a_Entity);
|
||||
void RemoveEntity( cEntity * a_Entity);
|
||||
|
||||
void UseBlockEntity(cPlayer * a_Player, int a_X, int a_Y, int a_Z); // [x, y, z] in world block coords
|
||||
@ -206,6 +223,8 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
friend class cChunkMap;
|
||||
|
||||
bool m_IsValid; // True if the chunk is loaded / generated
|
||||
bool m_IsDirty; // True if the chunk has changed since it was last saved
|
||||
bool m_IsSaving; // True if the chunk is being saved
|
||||
@ -251,6 +270,9 @@ private:
|
||||
void SpreadLightOfBlockZ(char* a_LightBuffer, int a_X, int a_Y, int a_Z);
|
||||
|
||||
void CreateBlockEntities(void);
|
||||
|
||||
// Makes a copy of the list
|
||||
cClientHandleList GetAllClients(void) const {return m_LoadedByClient; }
|
||||
};
|
||||
|
||||
typedef std::tr1::shared_ptr<cChunk> cChunkPtr;
|
||||
|
@ -6,7 +6,8 @@
|
||||
// The object takes requests for generating chunks and processes them in a separate thread one by one.
|
||||
// The requests are not added to the queue if there is already a request with the same coords
|
||||
// Before generating, the thread checks if the chunk hasn't been already generated.
|
||||
// It is theoretically possible to have multiple generator threads by having multiple instances of this object (if the cChunkPtr is thread-safe)
|
||||
// It is theoretically possible to have multiple generator threads by having multiple instances of this object
|
||||
// but then it MAY happen that the chunk is generated twice
|
||||
// If the generator queue is overloaded, the generator skips chunks with no clients in them
|
||||
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "cWorld.h"
|
||||
#include "cRoot.h"
|
||||
#include "cMakeDir.h"
|
||||
#include "cPlayer.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <cstdlib> // abs
|
||||
@ -15,9 +16,6 @@
|
||||
#include <json/json.h>
|
||||
|
||||
|
||||
#define USE_MEMCPY
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -136,6 +134,24 @@ cChunkPtr cChunkMap::GetChunkNoGen( int a_ChunkX, int a_ChunkY, int a_ChunkZ )
|
||||
|
||||
|
||||
|
||||
void cChunkMap::BroadcastToChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cPacket & a_Packet, cClientHandle * a_Exclude)
|
||||
{
|
||||
// Broadcasts a_Packet to all clients in the chunk where block [x, y, z] is, except to client a_Exclude
|
||||
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkY, a_ChunkZ);
|
||||
if (Chunk == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// It's perfectly legal to broadcast packets even to invalid chunks!
|
||||
Chunk->Broadcast(a_Packet, a_Exclude);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cChunkMap::BroadcastToChunkOfBlock(int a_X, int a_Y, int a_Z, cPacket * a_Packet, cClientHandle * a_Exclude)
|
||||
{
|
||||
// Broadcasts a_Packet to all clients in the chunk where block [x, y, z] is, except to client a_Exclude
|
||||
@ -143,13 +159,13 @@ void cChunkMap::BroadcastToChunkOfBlock(int a_X, int a_Y, int a_Z, cPacket * a_P
|
||||
cCSLock Lock(m_CSLayers);
|
||||
int ChunkX, ChunkZ;
|
||||
BlockToChunk(a_X, a_Y, a_Z, ChunkX, ChunkZ);
|
||||
cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ);
|
||||
cChunkPtr Chunk = GetChunkNoGen(ChunkX, ZERO_CHUNK_Y, ChunkZ);
|
||||
if (Chunk == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Packets can be broadcasted even to invalid chunks!
|
||||
Chunk->Broadcast(a_Packet);
|
||||
// It's perfectly legal to broadcast packets even to invalid chunks!
|
||||
Chunk->Broadcast(a_Packet, a_Exclude);
|
||||
}
|
||||
|
||||
|
||||
@ -402,6 +418,122 @@ void cChunkMap::FastSetBlocks(sSetBlockList & a_BlockList)
|
||||
|
||||
|
||||
|
||||
void cChunkMap::CollectPickupsByPlayer(cPlayer * a_Player)
|
||||
{
|
||||
int BlockX = (int)(a_Player->GetPosX()); // Truncating doesn't matter much; we're scanning entire chunks anyway
|
||||
int BlockY = (int)(a_Player->GetPosY());
|
||||
int BlockZ = (int)(a_Player->GetPosZ());
|
||||
int ChunkX, ChunkZ, ChunkY = ZERO_CHUNK_Y;
|
||||
AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
|
||||
int OtherChunkX = ChunkX + ((BlockX > 8) ? 1 : -1);
|
||||
int OtherChunkZ = ChunkZ + ((BlockZ > 8) ? 1 : -1);
|
||||
|
||||
cCSLock Lock(m_CSLayers);
|
||||
GetChunkNoGen(ChunkX, ChunkY, ChunkZ)->CollectPickupsByPlayer(a_Player);
|
||||
|
||||
// Check the neighboring chunks as well:
|
||||
GetChunkNoGen(OtherChunkX, ChunkY, ChunkZ )->CollectPickupsByPlayer(a_Player);
|
||||
GetChunkNoGen(OtherChunkX, ChunkY, OtherChunkZ)->CollectPickupsByPlayer(a_Player);
|
||||
GetChunkNoGen(ChunkX, ChunkY, ChunkZ )->CollectPickupsByPlayer(a_Player);
|
||||
GetChunkNoGen(ChunkX, ChunkY, OtherChunkZ)->CollectPickupsByPlayer(a_Player);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cChunkMap::CompareChunkClients(int a_ChunkX1, int a_ChunkY1, int a_ChunkZ1, int a_ChunkX2, int a_ChunkY2, int a_ChunkZ2, cClientDiffCallback & a_Callback)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr Chunk1 = GetChunkNoGen(a_ChunkX1, a_ChunkY1, a_ChunkZ1);
|
||||
if (Chunk1 == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
cChunkPtr Chunk2 = GetChunkNoGen(a_ChunkX2, a_ChunkY2, a_ChunkZ2);
|
||||
if (Chunk2 == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
cClientHandleList Clients1(Chunk1->GetAllClients());
|
||||
cClientHandleList Clients2(Chunk2->GetAllClients());
|
||||
|
||||
// Find "removed" clients:
|
||||
for (cClientHandleList::iterator itr1 = Clients1.begin(); itr1 != Clients1.end(); ++itr1)
|
||||
{
|
||||
bool Found = false;
|
||||
for (cClientHandleList::iterator itr2 = Clients2.begin(); itr2 != Clients2.end(); ++itr2)
|
||||
{
|
||||
if (*itr1 == *itr2)
|
||||
{
|
||||
Found = true;
|
||||
break;
|
||||
}
|
||||
} // for itr2 - Clients2[]
|
||||
if (!Found)
|
||||
{
|
||||
a_Callback.Removed(*itr1);
|
||||
}
|
||||
} // for itr1 - Clients1[]
|
||||
|
||||
// Find "added" clients:
|
||||
for (cClientHandleList::iterator itr2 = Clients2.begin(); itr2 != Clients2.end(); ++itr2)
|
||||
{
|
||||
bool Found = false;
|
||||
for (cClientHandleList::iterator itr1 = Clients1.begin(); itr1 != Clients1.end(); ++itr1)
|
||||
{
|
||||
if (*itr1 == *itr2)
|
||||
{
|
||||
Found = true;
|
||||
break;
|
||||
}
|
||||
} // for itr1 - Clients1[]
|
||||
if (!Found)
|
||||
{
|
||||
a_Callback.Added(*itr2);
|
||||
}
|
||||
} // for itr2 - Clients2[]
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cChunkMap::MoveEntityToChunk(cEntity * a_Entity, int a_ChunkX, int a_ChunkY, int a_ChunkZ)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr OldChunk = GetChunkNoGen(a_Entity->GetChunkX(), a_Entity->GetChunkY(), a_Entity->GetChunkZ());
|
||||
if (OldChunk != NULL)
|
||||
{
|
||||
OldChunk->RemoveEntity(a_Entity);
|
||||
}
|
||||
cChunkPtr NewChunk = GetChunkNoGen(a_ChunkX, a_ChunkY, a_ChunkZ);
|
||||
if (NewChunk != NULL)
|
||||
{
|
||||
NewChunk->AddEntity(a_Entity);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cChunkMap::RemoveEntityFromChunk(cEntity * a_Entity, int a_ChunkX, int a_ChunkY, int a_ChunkZ)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkY, a_ChunkZ);
|
||||
if ((Chunk == NULL) && !Chunk->IsValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
Chunk->RemoveEntity(a_Entity);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cChunkMap::Tick( float a_Dt, MTRand & a_TickRandom )
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
|
@ -32,9 +32,14 @@ public:
|
||||
cChunkPtr GetChunkNoGen( int a_ChunkX, int a_ChunkY, int a_ChunkZ ); // Also queues the chunk for loading if not valid; doesn't generate
|
||||
|
||||
// Direct action methods:
|
||||
/// Broadcast a_Packet to all clients in the chunk specified
|
||||
void BroadcastToChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cPacket & a_Packet, cClientHandle * a_Exclude = NULL);
|
||||
|
||||
/// Broadcasts a_Packet to all clients in the chunk where block [x, y, z] is, except to client a_Exclude
|
||||
void BroadcastToChunkOfBlock(int a_X, int a_Y, int a_Z, cPacket * a_Packet, cClientHandle * a_Exclude = NULL);
|
||||
void UseBlockEntity(cPlayer * a_Player, int a_X, int a_Y, int a_Z); // a_Player rclked block entity at the coords specified, handle it
|
||||
|
||||
/// a_Player rclked block entity at the coords specified, handle it
|
||||
void UseBlockEntity(cPlayer * a_Player, int a_X, int a_Y, int a_Z);
|
||||
|
||||
void MarkChunkDirty (int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
||||
void MarkChunkSaving (int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
||||
@ -48,6 +53,16 @@ public:
|
||||
void SpreadChunkLighting(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
||||
int GetHeight (int a_BlockX, int a_BlockZ);
|
||||
void FastSetBlocks (sSetBlockList & a_BlockList);
|
||||
void CollectPickupsByPlayer(cPlayer * a_Player);
|
||||
|
||||
/// Compares clients of two chunks, calls the callback accordingly
|
||||
void CompareChunkClients(int a_ChunkX1, int a_ChunkY1, int a_ChunkZ1, int a_ChunkX2, int a_ChunkY2, int a_ChunkZ2, cClientDiffCallback & a_Callback);
|
||||
|
||||
/// Moves the entity from its current chunk to the new chunk specified
|
||||
void MoveEntityToChunk(cEntity * a_Entity, int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
||||
|
||||
/// Removes the entity from the chunk specified
|
||||
void RemoveEntityFromChunk(cEntity * a_Entity, int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
||||
|
||||
void Tick( float a_Dt, MTRand & a_TickRand );
|
||||
|
||||
|
@ -66,6 +66,7 @@
|
||||
#include "packets/cPacket_Ping.h"
|
||||
#include "packets/cPacket_PlayerListItem.h"
|
||||
#include "packets/cPacket_NamedEntitySpawn.h"
|
||||
#include "packets/cPacket_MapChunk.h"
|
||||
|
||||
|
||||
|
||||
@ -1784,7 +1785,9 @@ void cClientHandle::CheckIfWorldDownloaded(void)
|
||||
|
||||
void cClientHandle::SendConfirmPosition(void)
|
||||
{
|
||||
LOG("Spawning player \"%s\"", m_Username.c_str());
|
||||
LOG("Spawning player \"%s\" at {%.2f, %.2f, %.2f}",
|
||||
m_Username.c_str(), m_Player->GetPosX(), m_Player->GetPosY(), m_Player->GetPosZ()
|
||||
);
|
||||
|
||||
m_State = csConfirmingPos;
|
||||
|
||||
|
@ -106,27 +106,60 @@ void cEntity::MoveToCorrectChunk(bool a_bIgnoreOldChunk)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!a_bIgnoreOldChunk)
|
||||
class cMover :
|
||||
public cClientDiffCallback
|
||||
{
|
||||
cChunkPtr OldChunk = m_World->GetChunk(m_ChunkX, m_ChunkY, m_ChunkZ);
|
||||
OldChunk->RemoveEntity(this);
|
||||
cPacket_DestroyEntity DestroyEntity( this );
|
||||
OldChunk->Broadcast(DestroyEntity);
|
||||
}
|
||||
virtual void Removed(cClientHandle * a_Client) override
|
||||
{
|
||||
if (m_IgnoreOldChunk)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (m_Destroy == NULL)
|
||||
{
|
||||
m_Destroy = new cPacket_DestroyEntity(m_Entity);
|
||||
}
|
||||
a_Client->Send(m_Destroy);
|
||||
}
|
||||
|
||||
virtual void Added(cClientHandle * a_Client) override
|
||||
{
|
||||
if (m_Spawn == NULL)
|
||||
{
|
||||
m_Spawn = m_Entity->GetSpawnPacket(); // Only create the packet when needed
|
||||
}
|
||||
if (m_Spawn != NULL)
|
||||
{
|
||||
a_Client->Send(m_Spawn);
|
||||
}
|
||||
}
|
||||
|
||||
cPacket * m_Destroy;
|
||||
cPacket * m_Spawn;
|
||||
bool m_IgnoreOldChunk;
|
||||
cEntity * m_Entity;
|
||||
|
||||
public:
|
||||
cMover(cEntity * a_Entity, bool a_IgnoreOldChunk) :
|
||||
m_Destroy(NULL),
|
||||
m_Spawn(NULL),
|
||||
m_IgnoreOldChunk(a_IgnoreOldChunk),
|
||||
m_Entity(a_Entity)
|
||||
{}
|
||||
|
||||
~cMover()
|
||||
{
|
||||
delete m_Spawn;
|
||||
delete m_Destroy;
|
||||
}
|
||||
} Mover(this, a_bIgnoreOldChunk);
|
||||
|
||||
m_World->CompareChunkClients(m_ChunkX, m_ChunkY, m_ChunkZ, ChunkX, ChunkY, ChunkZ, Mover);
|
||||
m_World->MoveEntityToChunk(this, ChunkX, ChunkY, ChunkZ);
|
||||
|
||||
m_ChunkX = ChunkX;
|
||||
m_ChunkY = ChunkY;
|
||||
m_ChunkZ = ChunkZ;
|
||||
cChunkPtr NewChunk = m_World->GetChunk( m_ChunkX, m_ChunkY, m_ChunkZ );
|
||||
if ( NewChunk != NULL )
|
||||
{
|
||||
NewChunk->AddEntity( this );
|
||||
std::auto_ptr<cPacket> SpawnPacket(GetSpawnPacket());
|
||||
if (SpawnPacket.get() != NULL)
|
||||
{
|
||||
NewChunk->Broadcast(SpawnPacket.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -151,19 +184,13 @@ void cEntity::Destroy()
|
||||
|
||||
void cEntity::RemoveFromChunk(void)
|
||||
{
|
||||
if ( m_World == NULL )
|
||||
if (m_World == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
cChunkPtr Chunk = m_World->GetChunk( m_ChunkX, m_ChunkY, m_ChunkZ );
|
||||
if ( Chunk != NULL )
|
||||
{
|
||||
cPacket_DestroyEntity DestroyEntity( this );
|
||||
Chunk->Broadcast( DestroyEntity );
|
||||
Chunk->RemoveEntity( this );
|
||||
m_bRemovedFromChunk = true;
|
||||
}
|
||||
m_World->RemoveEntityFromChunk(this, m_ChunkX, m_ChunkY, m_ChunkZ);
|
||||
m_bRemovedFromChunk = true;
|
||||
}
|
||||
|
||||
|
||||
@ -180,11 +207,7 @@ void cEntity::SpawnOn(cClientHandle * a_Client)
|
||||
|
||||
if (a_Client == NULL)
|
||||
{
|
||||
cChunkPtr Chunk = m_World->GetChunk( m_ChunkX, m_ChunkY, m_ChunkZ );
|
||||
if ( Chunk != NULL )
|
||||
{
|
||||
Chunk->Broadcast(SpawnPacket.get());
|
||||
}
|
||||
m_World->BroadcastToChunk(m_ChunkX, m_ChunkY, m_ChunkZ, *SpawnPacket.get(), NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -79,6 +79,10 @@ public: //tolua_export
|
||||
float GetPitch (void) const {return m_Rot.y; } //tolua_export
|
||||
float GetRoll (void) const {return m_Rot.z; } //tolua_export
|
||||
Vector3f GetLookVector(); //tolua_export
|
||||
|
||||
int GetChunkX(void) const {return m_ChunkX; }
|
||||
int GetChunkY(void) const {return m_ChunkY; }
|
||||
int GetChunkZ(void) const {return m_ChunkZ; }
|
||||
|
||||
void SetPosX( const double & a_PosX ); //tolua_export
|
||||
void SetPosY( const double & a_PosY ); //tolua_export
|
||||
|
@ -206,31 +206,27 @@ void cMonster::Tick(float a_Dt)
|
||||
|
||||
void cMonster::ReplicateMovement()
|
||||
{
|
||||
cChunkPtr InChunk = GetWorld()->GetChunk( m_ChunkX, m_ChunkY, m_ChunkZ );
|
||||
if ( !InChunk->IsValid() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(m_bDirtyOrientation && !m_bDirtyPosition)
|
||||
{
|
||||
cPacket_EntityLook EntityLook( this );
|
||||
InChunk->Broadcast( EntityLook );
|
||||
m_World->BroadcastToChunk(m_ChunkX, m_ChunkY, m_ChunkZ, EntityLook );
|
||||
m_bDirtyOrientation = false;
|
||||
}
|
||||
|
||||
if( m_bDirtyPosition )
|
||||
{
|
||||
|
||||
float DiffX = (float)(GetPosX() - m_LastPosX );
|
||||
float DiffY = (float)(GetPosY() - m_LastPosY );
|
||||
float DiffZ = (float)(GetPosZ() - m_LastPosZ );
|
||||
float SqrDist = DiffX*DiffX + DiffY*DiffY + DiffZ*DiffZ;
|
||||
if( SqrDist > 4*4 // 4 blocks is max Relative Move
|
||||
|| cWorld::GetTime() - m_TimeLastTeleportPacket > 2 ) // Send an absolute position every 2 seconds
|
||||
if (
|
||||
(SqrDist > 4 * 4) // 4 blocks is max Relative Move
|
||||
|| (cWorld::GetTime() - m_TimeLastTeleportPacket > 2 ) // Send an absolute position every 2 seconds
|
||||
)
|
||||
{
|
||||
//LOG("Teleported %f", sqrtf(SqrDist) );
|
||||
cPacket_TeleportEntity TeleportEntity( this );
|
||||
InChunk->Broadcast( TeleportEntity );
|
||||
m_World->BroadcastToChunk(m_ChunkX, m_ChunkY, m_ChunkZ, TeleportEntity);
|
||||
m_TimeLastTeleportPacket = cWorld::GetTime();
|
||||
}
|
||||
else
|
||||
@ -239,21 +235,21 @@ void cMonster::ReplicateMovement()
|
||||
{
|
||||
cPacket_RelativeEntityMoveLook RelativeEntityMoveLook;
|
||||
RelativeEntityMoveLook.m_UniqueID = GetUniqueID();
|
||||
RelativeEntityMoveLook.m_MoveX = (char)(DiffX*32);
|
||||
RelativeEntityMoveLook.m_MoveY = (char)(DiffY*32);
|
||||
RelativeEntityMoveLook.m_MoveZ = (char)(DiffZ*32);
|
||||
RelativeEntityMoveLook.m_Yaw = (char)((GetRotation()/360.f)*256);
|
||||
RelativeEntityMoveLook.m_MoveX = (char)(DiffX*32);
|
||||
RelativeEntityMoveLook.m_MoveY = (char)(DiffY*32);
|
||||
RelativeEntityMoveLook.m_MoveZ = (char)(DiffZ*32);
|
||||
RelativeEntityMoveLook.m_Yaw = (char)((GetRotation()/360.f)*256);
|
||||
RelativeEntityMoveLook.m_Pitch = (char)((GetPitch()/360.f)*256);
|
||||
InChunk->Broadcast( RelativeEntityMoveLook );
|
||||
m_World->BroadcastToChunk(m_ChunkX, m_ChunkY, m_ChunkZ, RelativeEntityMoveLook );
|
||||
}
|
||||
else
|
||||
{
|
||||
cPacket_RelativeEntityMove RelativeEntityMove;
|
||||
RelativeEntityMove.m_UniqueID = GetUniqueID();
|
||||
RelativeEntityMove.m_MoveX = (char)(DiffX*32);
|
||||
RelativeEntityMove.m_MoveY = (char)(DiffY*32);
|
||||
RelativeEntityMove.m_MoveZ = (char)(DiffZ*32);
|
||||
InChunk->Broadcast( RelativeEntityMove );
|
||||
RelativeEntityMove.m_MoveX = (char)(DiffX*32);
|
||||
RelativeEntityMove.m_MoveY = (char)(DiffY*32);
|
||||
RelativeEntityMove.m_MoveZ = (char)(DiffZ*32);
|
||||
m_World->BroadcastToChunk(m_ChunkX, m_ChunkY, m_ChunkZ, RelativeEntityMove );
|
||||
}
|
||||
}
|
||||
m_LastPosX = GetPosX();
|
||||
|
@ -80,8 +80,7 @@ void cPawn::TakeDamage( int a_Damage, cEntity* a_Instigator )
|
||||
cPacket_EntityStatus Status;
|
||||
Status.m_UniqueID = GetUniqueID();
|
||||
Status.m_Status = cPacket_EntityStatus::STATUS_TAKEDAMAGE;
|
||||
cChunkPtr Chunk = GetWorld()->GetChunk( m_ChunkX, m_ChunkY, m_ChunkZ );
|
||||
Chunk->Broadcast( Status );
|
||||
m_World->BroadcastToChunk(m_ChunkX, m_ChunkY, m_ChunkZ, Status);
|
||||
|
||||
if (m_Health <= 0)
|
||||
{
|
||||
@ -105,8 +104,7 @@ void cPawn::KilledBy( cEntity* a_Killer )
|
||||
cPacket_EntityStatus Status;
|
||||
Status.m_UniqueID = GetUniqueID();
|
||||
Status.m_Status = cPacket_EntityStatus::STATUS_DIE;
|
||||
cChunkPtr Chunk = GetWorld()->GetChunk( m_ChunkX, m_ChunkY, m_ChunkZ );
|
||||
Chunk->Broadcast( Status ); // Die
|
||||
m_World->BroadcastToChunk(m_ChunkX, m_ChunkY, m_ChunkZ, Status);
|
||||
}
|
||||
|
||||
|
||||
@ -152,12 +150,10 @@ void cPawn::Tick(float a_Dt)
|
||||
|
||||
void cPawn::SetMetaData(MetaData a_MetaData)
|
||||
{
|
||||
cChunkPtr InChunk = GetWorld()->GetChunk( m_ChunkX, m_ChunkY, m_ChunkZ );
|
||||
|
||||
//Broadcast new status to clients in the chunk
|
||||
m_MetaData = a_MetaData;
|
||||
cPacket_Metadata md(a_MetaData, GetUniqueID());
|
||||
InChunk->Broadcast(md);
|
||||
m_World->BroadcastToChunk(m_ChunkX, m_ChunkY, m_ChunkZ, md);
|
||||
}
|
||||
|
||||
|
||||
|
@ -101,15 +101,27 @@ cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName)
|
||||
m_Pos.x = cRoot::Get()->GetDefaultWorld()->GetSpawnX();
|
||||
m_Pos.y = cRoot::Get()->GetDefaultWorld()->GetSpawnY();
|
||||
m_Pos.z = cRoot::Get()->GetDefaultWorld()->GetSpawnZ();
|
||||
|
||||
LOGD("Player \"%s\" is connecting for the first time, spawning at default world spawn {%.2f, %.2f, %.2f}",
|
||||
a_PlayerName.c_str(), m_Pos.x, m_Pos.y, m_Pos.z
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cPlayer::Initialize( cWorld* a_World )
|
||||
{
|
||||
cPawn::Initialize( a_World );
|
||||
GetWorld()->AddPlayer( this );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cPlayer::~cPlayer(void)
|
||||
{
|
||||
SaveToDisk();
|
||||
@ -135,6 +147,10 @@ cPlayer::~cPlayer(void)
|
||||
|
||||
cPacket * cPlayer::GetSpawnPacket(void) const
|
||||
{
|
||||
LOGD("cPlayer::GetSpawnPacket for \"%s\" at pos {%.2f, %.2f, %.2f}",
|
||||
m_pState->PlayerName.c_str(), m_Pos.x, m_Pos.y, m_Pos.z
|
||||
);
|
||||
|
||||
if (!m_bVisible )
|
||||
{
|
||||
return NULL;
|
||||
@ -159,14 +175,12 @@ cPacket * cPlayer::GetSpawnPacket(void) const
|
||||
|
||||
void cPlayer::Tick(float a_Dt)
|
||||
{
|
||||
cChunkPtr InChunk = GetWorld()->GetChunk( m_ChunkX, m_ChunkY, m_ChunkZ );
|
||||
|
||||
cPawn::Tick(a_Dt);
|
||||
|
||||
if (m_bDirtyOrientation && !m_bDirtyPosition)
|
||||
{
|
||||
cPacket_EntityLook EntityLook( this );
|
||||
InChunk->Broadcast( EntityLook, m_ClientHandle );
|
||||
m_World->BroadcastToChunk(m_ChunkX, m_ChunkY, m_ChunkZ, EntityLook, m_ClientHandle );
|
||||
m_bDirtyOrientation = false;
|
||||
}
|
||||
else if (m_bDirtyPosition )
|
||||
@ -184,7 +198,7 @@ void cPlayer::Tick(float a_Dt)
|
||||
{
|
||||
//LOG("Teleported %f", sqrtf(SqrDist) );
|
||||
cPacket_TeleportEntity TeleportEntity( this );
|
||||
InChunk->Broadcast( TeleportEntity, m_ClientHandle );
|
||||
m_World->BroadcastToChunk(m_ChunkX, m_ChunkY, m_ChunkZ, TeleportEntity, m_ClientHandle);
|
||||
m_TimeLastTeleportPacket = cWorld::GetTime();
|
||||
}
|
||||
else
|
||||
@ -198,7 +212,7 @@ void cPlayer::Tick(float a_Dt)
|
||||
RelativeEntityMoveLook.m_MoveZ = (char)(DiffZ*32);
|
||||
RelativeEntityMoveLook.m_Yaw = (char)((GetRotation()/360.f)*256);
|
||||
RelativeEntityMoveLook.m_Pitch = (char)((GetPitch()/360.f)*256);
|
||||
InChunk->Broadcast( RelativeEntityMoveLook, m_ClientHandle );
|
||||
m_World->BroadcastToChunk(m_ChunkX, m_ChunkY, m_ChunkZ, RelativeEntityMoveLook, m_ClientHandle );
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -207,7 +221,7 @@ void cPlayer::Tick(float a_Dt)
|
||||
RelativeEntityMove.m_MoveX = (char)(DiffX*32);
|
||||
RelativeEntityMove.m_MoveY = (char)(DiffY*32);
|
||||
RelativeEntityMove.m_MoveZ = (char)(DiffZ*32);
|
||||
InChunk->Broadcast( RelativeEntityMove, m_ClientHandle );
|
||||
m_World->BroadcastToChunk(m_ChunkX, m_ChunkY, m_ChunkZ, RelativeEntityMove, m_ClientHandle );
|
||||
}
|
||||
}
|
||||
m_LastPosX = GetPosX();
|
||||
@ -217,10 +231,9 @@ void cPlayer::Tick(float a_Dt)
|
||||
m_ClientHandle->StreamChunks();
|
||||
}
|
||||
|
||||
if( m_Health > 0 ) // make sure player is alive
|
||||
if ( m_Health > 0 ) // make sure player is alive
|
||||
{
|
||||
// TODO: Don't only check in current chunks, but also close chunks (chunks within range)
|
||||
GetWorld()->GetChunk(m_ChunkX, m_ChunkY, m_ChunkZ)->CollectPickupsByPlayer(this);
|
||||
m_World->CollectPickupsByPlayer(this);
|
||||
}
|
||||
|
||||
cTimer t1;
|
||||
@ -521,6 +534,8 @@ void cPlayer::TeleportTo( const double & a_PosX, const double & a_PosY, const do
|
||||
void cPlayer::MoveTo( const Vector3d & a_NewPos )
|
||||
{
|
||||
// TODO: should do some checks to see if player is not moving through terrain
|
||||
// TODO: Official server refuses position packets too far away from each other, kicking "hacked" clients; we should, too
|
||||
|
||||
SetPosition( a_NewPos );
|
||||
}
|
||||
|
||||
@ -539,11 +554,7 @@ void cPlayer::SetVisible( bool a_bVisible )
|
||||
{
|
||||
m_bVisible = false;
|
||||
cPacket_DestroyEntity DestroyEntity( this );
|
||||
cChunkPtr Chunk = GetWorld()->GetChunk( m_ChunkX, m_ChunkY, m_ChunkZ );
|
||||
if ( Chunk != NULL )
|
||||
{
|
||||
Chunk->Broadcast( DestroyEntity ); // Destroy on all clients
|
||||
}
|
||||
m_World->BroadcastToChunk(m_ChunkX, m_ChunkY, m_ChunkZ, DestroyEntity ); // Destroy on all clients
|
||||
}
|
||||
}
|
||||
|
||||
@ -560,6 +571,10 @@ void cPlayer::AddToGroup( const char* a_GroupName )
|
||||
ResolvePermissions();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cPlayer::CanUseCommand( const char* a_Command )
|
||||
{
|
||||
for( GroupList::iterator itr = m_pState->Groups.begin(); itr != m_pState->Groups.end(); ++itr )
|
||||
@ -753,12 +768,7 @@ bool cPlayer::MoveToWorld( const char* a_WorldName )
|
||||
/* Remove all links to the old world */
|
||||
m_World->RemovePlayer( this );
|
||||
m_ClientHandle->RemoveFromAllChunks();
|
||||
cChunkPtr Chunk = m_World->GetChunk( m_ChunkX, m_ChunkY, m_ChunkZ );
|
||||
if ( Chunk != NULL )
|
||||
{
|
||||
Chunk->RemoveEntity( this );
|
||||
Chunk->Broadcast( cPacket_DestroyEntity( this ) ); // Remove player entity from all clients in old world
|
||||
}
|
||||
m_World->RemoveEntityFromChunk(this, m_ChunkX, m_ChunkY, m_ChunkZ);
|
||||
|
||||
/* Add player to all the necessary parts of the new world */
|
||||
SetWorld( World );
|
||||
@ -831,11 +841,8 @@ bool cPlayer::LoadFromDisk()
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get file size
|
||||
long FileSize = f.GetSize();
|
||||
|
||||
std::auto_ptr<char> buffer(new char[FileSize]);
|
||||
if (f.Read(buffer.get(), FileSize) != FileSize)
|
||||
AString buffer;
|
||||
if (f.ReadRestOfFile(buffer) != f.GetSize())
|
||||
{
|
||||
LOGERROR("ERROR READING FROM FILE \"%s\"", SourceFile.c_str());
|
||||
return false;
|
||||
@ -844,12 +851,10 @@ bool cPlayer::LoadFromDisk()
|
||||
|
||||
Json::Value root;
|
||||
Json::Reader reader;
|
||||
if (!reader.parse(buffer.get(), root, false))
|
||||
if (!reader.parse(buffer, root, false))
|
||||
{
|
||||
LOGERROR("ERROR WHILE PARSING JSON FROM FILE %s", SourceFile.c_str());
|
||||
}
|
||||
|
||||
buffer.reset();
|
||||
|
||||
Json::Value & JSON_PlayerPosition = root["position"];
|
||||
if( JSON_PlayerPosition.size() == 3 )
|
||||
@ -874,6 +879,10 @@ bool cPlayer::LoadFromDisk()
|
||||
|
||||
m_pState->LoadedWorldName = root.get("world", "world").asString();
|
||||
|
||||
LOGD("Player \"%s\" was read from file, spawning at {%.2f, %.2f, %.2f} in world \"%s\"",
|
||||
m_pState->PlayerName.c_str(), m_Pos.x, m_Pos.y, m_Pos.z, m_pState->LoadedWorldName.c_str()
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -431,7 +431,12 @@ void cWorld::InitializeSpawn()
|
||||
int ChunkX = 0, ChunkY = 0, ChunkZ = 0;
|
||||
BlockToChunk( (int)m_SpawnX, (int)m_SpawnY, (int)m_SpawnZ, ChunkX, ChunkY, ChunkZ );
|
||||
|
||||
// For the debugging builds, don't make the server build too much world upon start:
|
||||
#ifdef _DEBUG
|
||||
int ViewDist = 9;
|
||||
#else
|
||||
int ViewDist = 20; // Always prepare an area 20 chunks across, no matter what the actual cClientHandle::VIEWDISTANCE is
|
||||
#endif // _DEBUG
|
||||
|
||||
LOG("Preparing spawn area in world \"%s\"", m_WorldName.c_str());
|
||||
for (int x = 0; x < ViewDist; x++)
|
||||
@ -807,16 +812,6 @@ void cWorld::GrowTree( int a_X, int a_Y, int a_Z )
|
||||
|
||||
|
||||
|
||||
void cWorld::UnloadUnusedChunks()
|
||||
{
|
||||
m_LastUnload = m_Time;
|
||||
m_ChunkMap->UnloadUnusedChunks();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cChunkPtr cWorld::GetChunkOfBlock( int a_X, int a_Y, int a_Z )
|
||||
{
|
||||
int ChunkX, ChunkY, ChunkZ;
|
||||
@ -1005,6 +1000,15 @@ void cWorld::Broadcast( const cPacket & a_Packet, cClientHandle* a_Exclude)
|
||||
|
||||
|
||||
|
||||
void cWorld::BroadcastToChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cPacket & a_Packet, cClientHandle * a_Exclude)
|
||||
{
|
||||
m_ChunkMap->BroadcastToChunk(a_ChunkX, a_ChunkY, a_ChunkZ, a_Packet, a_Exclude);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cWorld::BroadcastToChunkOfBlock(int a_X, int a_Y, int a_Z, cPacket * a_Packet, cClientHandle * a_Exclude)
|
||||
{
|
||||
m_ChunkMap->BroadcastToChunkOfBlock(a_X, a_Y, a_Z, a_Packet, a_Exclude);
|
||||
@ -1095,6 +1099,25 @@ bool cWorld::HasChunkAnyClients(int a_ChunkX, int a_ChunkY, int a_ChunkZ) const
|
||||
|
||||
|
||||
|
||||
void cWorld::UnloadUnusedChunks(void )
|
||||
{
|
||||
m_LastUnload = m_Time;
|
||||
m_ChunkMap->UnloadUnusedChunks();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cWorld::CollectPickupsByPlayer(cPlayer * a_Player)
|
||||
{
|
||||
m_ChunkMap->CollectPickupsByPlayer(a_Player);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cWorld::SetMaxPlayers(int iMax)
|
||||
{
|
||||
m_MaxPlayers = MAX_PLAYERS;
|
||||
@ -1271,10 +1294,27 @@ bool cWorld::DoWithEntity( int a_UniqueID, cEntityCallback & a_Callback )
|
||||
|
||||
|
||||
|
||||
void cWorld::RemoveEntityFromChunk(cEntity * a_Entity)
|
||||
void cWorld::RemoveEntityFromChunk(cEntity * a_Entity, int a_ChunkX, int a_ChunkY, int a_ChunkZ)
|
||||
{
|
||||
cChunkPtr Chunk = GetChunkOfBlock((int)(a_Entity->GetPosX()), (int)(a_Entity->GetPosY()), (int)(a_Entity->GetPosZ()));
|
||||
Chunk->RemoveEntity(a_Entity);
|
||||
m_ChunkMap->RemoveEntityFromChunk(a_Entity, a_ChunkX, a_ChunkY, a_ChunkZ);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cWorld::MoveEntityToChunk(cEntity * a_Entity, int a_ChunkX, int a_ChunkY, int a_ChunkZ)
|
||||
{
|
||||
m_ChunkMap->MoveEntityToChunk(a_Entity, a_ChunkX, a_ChunkY, a_ChunkZ);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cWorld::CompareChunkClients(int a_ChunkX1, int a_ChunkY1, int a_ChunkZ1, int a_ChunkX2, int a_ChunkY2, int a_ChunkZ2, cClientDiffCallback & a_Callback)
|
||||
{
|
||||
m_ChunkMap->CompareChunkClients(a_ChunkX1, a_ChunkY1, a_ChunkZ1, a_ChunkX2, a_ChunkY2, a_ChunkZ2, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
@ -1286,7 +1326,6 @@ void cWorld::SaveAllChunks()
|
||||
LOG("Saving all chunks...");
|
||||
m_LastSave = m_Time;
|
||||
m_ChunkMap->SaveAllChunks();
|
||||
LOG("Done saving chunks");
|
||||
}
|
||||
|
||||
|
||||
|
@ -68,6 +68,8 @@ public:
|
||||
|
||||
void Broadcast( const cPacket & a_Packet, cClientHandle* a_Exclude = 0 );
|
||||
|
||||
void BroadcastToChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cPacket & a_Packet, cClientHandle * a_Exclude = NULL);
|
||||
|
||||
void BroadcastToChunkOfBlock(int a_X, int a_Y, int a_Z, cPacket * a_Packet, cClientHandle * a_Exclude = NULL);
|
||||
|
||||
void MarkChunkDirty (int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
||||
@ -80,6 +82,7 @@ public:
|
||||
bool IsChunkValid (int a_ChunkX, int a_ChunkY, int a_ChunkZ) const;
|
||||
bool HasChunkAnyClients(int a_ChunkX, int a_ChunkY, int a_ChunkZ) const;
|
||||
void UnloadUnusedChunks(void);
|
||||
void CollectPickupsByPlayer(cPlayer * a_Player);
|
||||
|
||||
// MOTD
|
||||
const AString & GetDescription(void) const {return m_Description; }
|
||||
@ -105,7 +108,18 @@ public:
|
||||
void SendPlayerList(cPlayer * a_DestPlayer); // Sends playerlist to the player
|
||||
|
||||
void AddEntity( cEntity* a_Entity );
|
||||
void RemoveEntityFromChunk( cEntity * a_Entity);
|
||||
|
||||
/// Add an entity to the chunk specified; broadcasts the a_SpawnPacket to all clients of that chunk
|
||||
void AddEntityToChunk(cEntity * a_Entity, int a_ChunkX, int a_ChunkY, int a_ChunkZ, cPacket * a_SpawnPacket);
|
||||
|
||||
/// Removes the entity from the chunk specified
|
||||
void RemoveEntityFromChunk(cEntity * a_Entity, int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
||||
|
||||
/// Moves the entity from its current chunk to the new chunk specified
|
||||
void MoveEntityToChunk(cEntity * a_Entity, int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
||||
|
||||
/// Compares clients of two chunks, calls the callback accordingly
|
||||
void CompareChunkClients(int a_ChunkX1, int a_ChunkY1, int a_ChunkZ1, int a_ChunkX2, int a_ChunkY2, int a_ChunkZ2, cClientDiffCallback & a_Callback);
|
||||
|
||||
// TODO: Export to Lua
|
||||
bool DoWithEntity( int a_UniqueID, cEntityCallback & a_Callback );
|
||||
|
Loading…
Reference in New Issue
Block a user