Removed cChunkPtrs from everywhere but internal cChunkMap usage. Now we should finally be threadsafe :)
Also fixed a threading issue when a player connecting might have gotten stuck in "Downloading world" forever git-svn-id: http://mc-server.googlecode.com/svn/trunk@304 0a769ca7-a7f5-676a-18bf-c427514a06d6
This commit is contained in:
parent
f0145ee9fa
commit
b653e6a012
@ -1,6 +1,6 @@
|
||||
/*
|
||||
** Lua binding: AllToLua
|
||||
** Generated automatically by tolua++-1.0.92 on 02/16/12 18:16:16.
|
||||
** Generated automatically by tolua++-1.0.92 on 02/21/12 17:01:49.
|
||||
*/
|
||||
|
||||
#ifndef __cplusplus
|
||||
@ -9508,7 +9508,7 @@ static int tolua_AllToLua_cWorld_GetHeight00(lua_State* tolua_S)
|
||||
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetHeight'", NULL);
|
||||
#endif
|
||||
{
|
||||
char tolua_ret = (char) self->GetHeight(a_X,a_Z);
|
||||
int tolua_ret = (int) self->GetHeight(a_X,a_Z);
|
||||
tolua_pushnumber(tolua_S,(lua_Number)tolua_ret);
|
||||
}
|
||||
}
|
||||
@ -9984,7 +9984,7 @@ static int tolua_AllToLua_cWorld_GetBlockEntity00(lua_State* tolua_S)
|
||||
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetBlockEntity'", NULL);
|
||||
#endif
|
||||
{
|
||||
cBlockEntity* tolua_ret = (cBlockEntity*) self->GetBlockEntity(a_X,a_Y,a_Z);
|
||||
OBSOLETE cBlockEntity* tolua_ret = (OBSOLETE cBlockEntity*) self->GetBlockEntity(a_X,a_Y,a_Z);
|
||||
tolua_pushusertype(tolua_S,(void*)tolua_ret,"cBlockEntity");
|
||||
}
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ sSetBlock::sSetBlock( int a_X, int a_Y, int a_Z, char a_BlockType, char a_BlockM
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// cChunk:
|
||||
|
||||
cChunk::cChunk(int a_X, int a_Y, int a_Z, cWorld * a_World)
|
||||
cChunk::cChunk(int a_X, int a_Y, int a_Z, cChunkMap * a_ChunkMap, cWorld * a_World)
|
||||
: m_bCalculateLighting( false )
|
||||
, m_bCalculateHeightmap( false )
|
||||
, m_PosX( a_X )
|
||||
@ -82,6 +82,7 @@ cChunk::cChunk(int a_X, int a_Y, int a_Z, cWorld * a_World)
|
||||
, m_BlockTickY( 0 )
|
||||
, m_BlockTickZ( 0 )
|
||||
, m_World( a_World )
|
||||
, m_ChunkMap(a_ChunkMap)
|
||||
, m_IsValid(false)
|
||||
, m_IsDirty(false)
|
||||
, m_IsSaving(false)
|
||||
@ -700,8 +701,8 @@ void cChunk::SpreadLight(char* a_LightBuffer)
|
||||
bCalcLeft = bCalcRight = bCalcFront = bCalcBack = false;
|
||||
|
||||
// Spread to neighbour chunks X-axis
|
||||
cChunkPtr LeftChunk = m_World->GetChunkNoGen( m_PosX - 1, m_PosY, m_PosZ );
|
||||
cChunkPtr RightChunk = m_World->GetChunkNoGen( m_PosX + 1, m_PosY, m_PosZ );
|
||||
cChunkPtr LeftChunk = m_ChunkMap->GetChunkNoGen( m_PosX - 1, m_PosY, m_PosZ );
|
||||
cChunkPtr RightChunk = m_ChunkMap->GetChunkNoGen( m_PosX + 1, m_PosY, m_PosZ );
|
||||
char * LeftSky = NULL, *RightSky = NULL;
|
||||
if (LeftChunk->IsValid())
|
||||
{
|
||||
@ -745,8 +746,8 @@ void cChunk::SpreadLight(char* a_LightBuffer)
|
||||
}
|
||||
|
||||
// Spread to neighbour chunks Z-axis
|
||||
cChunkPtr FrontChunk = m_World->GetChunkNoGen( m_PosX, m_PosY, m_PosZ - 1 );
|
||||
cChunkPtr BackChunk = m_World->GetChunkNoGen( m_PosX, m_PosY, m_PosZ + 1 );
|
||||
cChunkPtr FrontChunk = m_ChunkMap->GetChunkNoGen( m_PosX, m_PosY, m_PosZ - 1 );
|
||||
cChunkPtr BackChunk = m_ChunkMap->GetChunkNoGen( m_PosX, m_PosY, m_PosZ + 1 );
|
||||
char * FrontSky = NULL, * BackSky = NULL;
|
||||
if (FrontChunk->IsValid())
|
||||
{
|
||||
|
@ -46,10 +46,15 @@ class cClientHandle;
|
||||
class cServer;
|
||||
class MTRand;
|
||||
class cPlayer;
|
||||
class cChunkMap;
|
||||
|
||||
typedef std::list<cClientHandle *> cClientHandleList;
|
||||
typedef std::list<cBlockEntity *> cBlockEntityList;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** Interface class used for getting data out of a chunk using the GetAllData() function.
|
||||
Implementation must use the pointers immediately and NOT store any of them for later use
|
||||
*/
|
||||
@ -108,7 +113,7 @@ public:
|
||||
static const int c_NumBlocks = 16 * 128 * 16;
|
||||
static const int c_BlockDataSize = c_NumBlocks * 2 + (c_NumBlocks/2); // 2.5 * numblocks
|
||||
|
||||
cChunk(int a_X, int a_Y, int a_Z, cWorld* a_World);
|
||||
cChunk(int a_X, int a_Y, int a_Z, cChunkMap * a_ChunkMap, cWorld * a_World);
|
||||
~cChunk();
|
||||
|
||||
bool IsValid(void) const {return m_IsValid; } // Returns true if the chunk is valid (loaded / generated)
|
||||
@ -248,7 +253,8 @@ private:
|
||||
bool m_bCalculateHeightmap;
|
||||
|
||||
int m_PosX, m_PosY, m_PosZ;
|
||||
cWorld * m_World;
|
||||
cWorld * m_World;
|
||||
cChunkMap * m_ChunkMap;
|
||||
|
||||
char m_BlockData[c_BlockDataSize]; // Chunk data ready to be compressed and sent
|
||||
char *m_BlockType; // Pointers to an element in m_BlockData
|
||||
|
@ -2,11 +2,13 @@
|
||||
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
|
||||
|
||||
#include "cChunkMap.h"
|
||||
#include "cChunk.h"
|
||||
#include "cWorld.h"
|
||||
#include "cRoot.h"
|
||||
#include "cMakeDir.h"
|
||||
#include "cPlayer.h"
|
||||
#include "BlockID.h"
|
||||
#include "cItem.h"
|
||||
#include "cPickup.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <cstdlib> // abs
|
||||
@ -19,6 +21,17 @@
|
||||
|
||||
|
||||
|
||||
#define RECI_RAND_MAX (1.f/RAND_MAX)
|
||||
inline float fRadRand( float a_Radius )
|
||||
{
|
||||
MTRand r1;
|
||||
return ((float)r1.rand() * RECI_RAND_MAX)*a_Radius - a_Radius*0.5f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// cChunkMap:
|
||||
|
||||
@ -479,6 +492,88 @@ char cChunkMap::GetBlockMeta(int a_X, int a_Y, int a_Z)
|
||||
|
||||
|
||||
|
||||
void cChunkMap::SetBlockMeta(int a_X, int a_Y, int a_Z, char a_BlockMeta)
|
||||
{
|
||||
int ChunkX, ChunkZ;
|
||||
AbsoluteToRelative( a_X, a_Y, a_Z, ChunkX, ChunkZ );
|
||||
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr Chunk = GetChunk( ChunkX, ZERO_CHUNK_Y, ChunkZ );
|
||||
if ((Chunk != NULL) && Chunk->IsValid() )
|
||||
{
|
||||
// Although it is called SetLight(), it actually sets meta when passed the Meta field
|
||||
Chunk->SetLight( Chunk->pGetMeta(), a_X, a_Y, a_Z, a_BlockMeta );
|
||||
Chunk->SendBlockTo( a_X, a_Y, a_Z, NULL );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cChunkMap::SetBlock(int a_X, int a_Y, int a_Z, char a_BlockType, char a_BlockMeta)
|
||||
{
|
||||
int ChunkX, ChunkZ, X = a_X, Y = a_Y, Z = a_Z;
|
||||
AbsoluteToRelative( X, Y, Z, ChunkX, ChunkZ );
|
||||
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr Chunk = GetChunk( ChunkX, ZERO_CHUNK_Y, ChunkZ );
|
||||
if ((Chunk != NULL) && Chunk->IsValid())
|
||||
{
|
||||
Chunk->SetBlock(X, Y, Z, a_BlockType, a_BlockMeta );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::DigBlock(int a_X, int a_Y, int a_Z, cItem & a_PickupItem)
|
||||
{
|
||||
int PosX = a_X, PosY = a_Y, PosZ = a_Z, ChunkX, ChunkZ;
|
||||
|
||||
AbsoluteToRelative( PosX, PosY, PosZ, ChunkX, ChunkZ );
|
||||
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr DestChunk = GetChunk( ChunkX, ZERO_CHUNK_Y, ChunkZ );
|
||||
if ((DestChunk == NULL) || !DestChunk->IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DestChunk->SetBlock(PosX, PosY, PosZ, E_BLOCK_AIR, 0 );
|
||||
|
||||
m_World->GetSimulatorManager()->WakeUp(a_X, a_Y, a_Z);
|
||||
|
||||
if ( !a_PickupItem.IsEmpty() )
|
||||
{
|
||||
cPickup * Pickup = new cPickup( a_X * 32 + 16 + (int)fRadRand(16.f), a_Y * 32 + 16 + (int)fRadRand(16.f), a_Z * 32 + 16 + (int)fRadRand(16.f), a_PickupItem );
|
||||
Pickup->Initialize(m_World);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cChunkMap::SendBlockTo(int a_X, int a_Y, int a_Z, cPlayer * a_Player)
|
||||
{
|
||||
int ChunkX, ChunkZ;
|
||||
AbsoluteToRelative(a_X, a_Y, a_Z, ChunkX, ChunkZ);
|
||||
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr Chunk = GetChunk(ChunkX, ZERO_CHUNK_Y, ChunkZ);
|
||||
if (Chunk->IsValid())
|
||||
{
|
||||
Chunk->SendBlockTo(a_X, a_Y, a_Z, a_Player->GetClientHandle());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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);
|
||||
@ -552,6 +647,21 @@ bool cChunkMap::AddChunkClient(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClient
|
||||
|
||||
|
||||
|
||||
void cChunkMap::RemoveChunkClient(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkY, a_ChunkZ);
|
||||
if (Chunk == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Chunk->RemoveClient(a_Client);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cChunkMap::RemoveClientFromChunks(cClientHandle * a_Client, const cChunkCoordsList & a_Chunks)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
@ -569,7 +679,7 @@ void cChunkMap::RemoveClientFromChunks(cClientHandle * a_Client, const cChunkCoo
|
||||
bool cChunkMap::SendChunkTo(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkY, a_ChunkZ);
|
||||
cChunkPtr Chunk = GetChunk(a_ChunkX, a_ChunkY, a_ChunkZ);
|
||||
if ((Chunk == NULL) || !Chunk->IsValid())
|
||||
{
|
||||
return false;
|
||||
@ -616,6 +726,33 @@ void cChunkMap::RemoveEntityFromChunk(cEntity * a_Entity, int a_ChunkX, int a_Ch
|
||||
|
||||
|
||||
|
||||
void cChunkMap::TouchChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
GetChunk(a_ChunkX, a_ChunkY, a_ChunkZ);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cChunkMap::UpdateSign(int a_X, int a_Y, int a_Z, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
int ChunkX, ChunkZ;
|
||||
BlockToChunk(a_X, a_Y, a_Z, ChunkX, ChunkZ);
|
||||
cChunkPtr Chunk = GetChunkNoGen(ChunkX, ZERO_CHUNK_Y, ChunkZ);
|
||||
if ((Chunk == NULL) || !Chunk->IsValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
Chunk->UpdateSign(a_X, a_Y, a_Z, a_Line1, a_Line2, a_Line3, a_Line4);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cChunkMap::Tick( float a_Dt, MTRand & a_TickRandom )
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
@ -687,7 +824,7 @@ cChunkPtr cChunkMap::cChunkLayer::GetChunk( int a_ChunkX, int a_ChunkY, int a_Ch
|
||||
int Index = LocalX + LocalZ * LAYER_SIZE;
|
||||
if (m_Chunks[Index].get() == NULL)
|
||||
{
|
||||
m_Chunks[Index].reset(new cChunk(a_ChunkX, 0, a_ChunkZ, m_Parent->GetWorld()));
|
||||
m_Chunks[Index].reset(new cChunk(a_ChunkX, 0, a_ChunkZ, m_Parent, m_Parent->GetWorld()));
|
||||
}
|
||||
return m_Chunks[Index];
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
class cWorld;
|
||||
class cEntity;
|
||||
class cItem;
|
||||
class MTRand;
|
||||
|
||||
|
||||
@ -27,10 +28,6 @@ public:
|
||||
cChunkMap(cWorld* a_World );
|
||||
~cChunkMap();
|
||||
|
||||
// TODO: Get rid of these (put into Private section) in favor of the direct action methods:
|
||||
cChunkPtr GetChunk ( int a_ChunkX, int a_ChunkY, int a_ChunkZ ); // Also queues the chunk for loading / generating if not valid
|
||||
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);
|
||||
@ -56,6 +53,10 @@ public:
|
||||
void CollectPickupsByPlayer(cPlayer * a_Player);
|
||||
char GetBlock (int a_X, int a_Y, int a_Z);
|
||||
char GetBlockMeta (int a_X, int a_Y, int a_Z);
|
||||
void SetBlockMeta (int a_X, int a_Y, int a_Z, char a_BlockMeta);
|
||||
void SetBlock (int a_X, int a_Y, int a_Z, char a_BlockType, char a_BlockMeta);
|
||||
bool DigBlock (int a_X, int a_Y, int a_Z, cItem & a_PickupItem);
|
||||
void SendBlockTo (int a_X, int a_Y, int a_Z, 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);
|
||||
@ -63,6 +64,9 @@ public:
|
||||
/// Adds client to a chunk, if not already present; returns true if added, false if present
|
||||
bool AddChunkClient(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client);
|
||||
|
||||
/// Removes the client from the chunk
|
||||
void RemoveChunkClient(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client);
|
||||
|
||||
/// Removes the client from all chunks specified
|
||||
void RemoveClientFromChunks(cClientHandle * a_Client, const cChunkCoordsList & a_Chunks);
|
||||
|
||||
@ -75,6 +79,11 @@ public:
|
||||
/// Removes the entity from the chunk specified
|
||||
void RemoveEntityFromChunk(cEntity * a_Entity, int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
||||
|
||||
/// Touches the chunk, causing it to be loaded or generated
|
||||
void TouchChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
||||
|
||||
void UpdateSign(int a_X, int a_Y, int a_Z, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4);
|
||||
|
||||
void Tick( float a_Dt, MTRand & a_TickRand );
|
||||
|
||||
void UnloadUnusedChunks();
|
||||
@ -113,6 +122,8 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
friend class cChunk; // Temporary (until we have a separate Lighting thread), so that cChunk's lighting calc can ask for neighbor chunks
|
||||
|
||||
class cChunkLayer
|
||||
{
|
||||
public:
|
||||
@ -153,6 +164,9 @@ private:
|
||||
cEvent m_evtChunkValid; // Set whenever any chunk becomes valid, via ChunkValidated()
|
||||
|
||||
cWorld * m_World;
|
||||
|
||||
cChunkPtr GetChunk ( int a_ChunkX, int a_ChunkY, int a_ChunkZ ); // Also queues the chunk for loading / generating if not valid
|
||||
cChunkPtr GetChunkNoGen( int a_ChunkX, int a_ChunkY, int a_ChunkZ ); // Also queues the chunk for loading if not valid; doesn't generate
|
||||
};
|
||||
|
||||
|
||||
|
@ -343,7 +343,7 @@ void cClientHandle::StreamChunks(void)
|
||||
int RelZ = (*itr).m_ChunkZ - ChunkPosZ;
|
||||
if ((RelX > VIEWDISTANCE) || (RelX < -VIEWDISTANCE) || (RelZ > VIEWDISTANCE) || (RelZ < -VIEWDISTANCE))
|
||||
{
|
||||
World->GetChunk(itr->m_ChunkX, itr->m_ChunkY, itr->m_ChunkZ)->RemoveClient(this);
|
||||
World->RemoveChunkClient(itr->m_ChunkX, itr->m_ChunkY, itr->m_ChunkZ, this);
|
||||
itr = m_LoadedChunks.erase(itr);
|
||||
}
|
||||
else
|
||||
@ -389,13 +389,13 @@ void cClientHandle::StreamChunks(void)
|
||||
// For each distance touch chunks in a hollow square centered around current position:
|
||||
for (int i = -d; i <= d; ++i)
|
||||
{
|
||||
World->GetChunk(ChunkPosX + d, ZERO_CHUNK_Y, ChunkPosZ + i);
|
||||
World->GetChunk(ChunkPosX - d, ZERO_CHUNK_Y, ChunkPosZ + i);
|
||||
World->TouchChunk(ChunkPosX + d, ZERO_CHUNK_Y, ChunkPosZ + i);
|
||||
World->TouchChunk(ChunkPosX - d, ZERO_CHUNK_Y, ChunkPosZ + i);
|
||||
} // for i
|
||||
for (int i = -d + 1; i < d; ++i)
|
||||
{
|
||||
World->GetChunk(ChunkPosX + i, ZERO_CHUNK_Y, ChunkPosZ + d);
|
||||
World->GetChunk(ChunkPosX + i, ZERO_CHUNK_Y, ChunkPosZ - d);
|
||||
World->TouchChunk(ChunkPosX + i, ZERO_CHUNK_Y, ChunkPosZ + d);
|
||||
World->TouchChunk(ChunkPosX + i, ZERO_CHUNK_Y, ChunkPosZ - d);
|
||||
} // for i
|
||||
} // for d
|
||||
}
|
||||
@ -1510,12 +1510,7 @@ void cClientHandle::HandleWindowClick(cPacket_WindowClick * a_Packet)
|
||||
void cClientHandle::HandleUpdateSign(cPacket_UpdateSign * a_Packet)
|
||||
{
|
||||
cWorld * World = m_Player->GetWorld();
|
||||
cChunkPtr Chunk = World->GetChunkOfBlock(a_Packet->m_PosX, a_Packet->m_PosY, a_Packet->m_PosZ);
|
||||
if ((Chunk == NULL) || !Chunk->IsValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
Chunk->UpdateSign(a_Packet->m_PosX, a_Packet->m_PosY, a_Packet->m_PosZ, a_Packet->m_Line1, a_Packet->m_Line2, a_Packet->m_Line3, a_Packet->m_Line4);
|
||||
World->UpdateSign(a_Packet->m_PosX, a_Packet->m_PosY, a_Packet->m_PosZ, a_Packet->m_Line1, a_Packet->m_Line2, a_Packet->m_Line3, a_Packet->m_Line4);
|
||||
}
|
||||
|
||||
|
||||
@ -1664,8 +1659,10 @@ void cClientHandle::Tick(float a_Dt)
|
||||
// Only send up to 10 chunks per tick, otherwise we'd choke the tick thread
|
||||
break;
|
||||
}
|
||||
CheckIfWorldDownloaded();
|
||||
} // for itr - m_ChunksToSend[]
|
||||
|
||||
// Check even if we didn't send anything - a chunk may have sent a notification that we'd miss otherwise
|
||||
CheckIfWorldDownloaded();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -160,7 +160,7 @@ void cPickup::Tick(float a_Dt)
|
||||
m_bReplicated = true;
|
||||
m_bDirtyPosition = false;
|
||||
cPacket_TeleportEntity TeleportEntity( this );
|
||||
GetWorld()->GetChunk( m_ChunkX, m_ChunkY, m_ChunkZ )->Broadcast( &TeleportEntity );
|
||||
GetWorld()->BroadcastToChunk( m_ChunkX, m_ChunkY, m_ChunkZ, TeleportEntity );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -98,7 +98,7 @@ void cSignEntity::SendTo( cClientHandle* a_Client )
|
||||
}
|
||||
else // broadcast of a_Client == 0
|
||||
{
|
||||
m_World->GetChunkOfBlock(m_PosX, m_PosY, m_PosZ)->Broadcast( Sign );
|
||||
m_World->BroadcastToChunkOfBlock(m_PosX, m_PosY, m_PosZ, &Sign );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,17 +80,6 @@ bool g_BlockPistonBreakable[128];
|
||||
|
||||
|
||||
|
||||
#define RECI_RAND_MAX (1.f/RAND_MAX)
|
||||
inline float fRadRand( float a_Radius )
|
||||
{
|
||||
MTRand r1;
|
||||
return ((float)r1.rand() * RECI_RAND_MAX)*a_Radius - a_Radius*0.5f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// cWorldLoadProgress:
|
||||
|
||||
@ -443,7 +432,7 @@ void cWorld::InitializeSpawn()
|
||||
{
|
||||
for (int z = 0; z < ViewDist; z++)
|
||||
{
|
||||
GetChunk( x + ChunkX-(ViewDist - 1) / 2, 0, z + ChunkZ-(ViewDist - 1) / 2 ); // Queue the chunk in the generator / loader
|
||||
m_ChunkMap->TouchChunk( x + ChunkX-(ViewDist - 1) / 2, 0, z + ChunkZ-(ViewDist - 1) / 2 ); // Queue the chunk in the generator / loader
|
||||
}
|
||||
}
|
||||
|
||||
@ -812,29 +801,11 @@ void cWorld::GrowTree( int a_X, int a_Y, int a_Z )
|
||||
|
||||
|
||||
|
||||
cChunkPtr cWorld::GetChunkOfBlock( int a_X, int a_Y, int a_Z )
|
||||
{
|
||||
int ChunkX, ChunkY, ChunkZ;
|
||||
AbsoluteToRelative( a_X, a_Y, a_Z, ChunkX, ChunkY, ChunkZ );
|
||||
return GetChunk( ChunkX, ChunkY, ChunkZ );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cWorld::SetBlock( int a_X, int a_Y, int a_Z, char a_BlockType, char a_BlockMeta )
|
||||
{
|
||||
int ChunkX, ChunkY, ChunkZ, X = a_X, Y = a_Y, Z = a_Z;
|
||||
AbsoluteToRelative( X, Y, Z, ChunkX, ChunkY, ChunkZ );
|
||||
m_ChunkMap->SetBlock(a_X, a_Y, a_Z, a_BlockType, a_BlockMeta);
|
||||
|
||||
cChunkPtr Chunk = GetChunk( ChunkX, ChunkY, ChunkZ );
|
||||
if ( Chunk->IsValid() )
|
||||
{
|
||||
Chunk->SetBlock(X, Y, Z, a_BlockType, a_BlockMeta );
|
||||
this->GetSimulatorManager()->WakeUp(a_X, a_Y, a_Z);
|
||||
}
|
||||
// The chunk is not yet initialized, so it's probably far away from all players, no need to store this Meta change
|
||||
GetSimulatorManager()->WakeUp(a_X, a_Y, a_Z);
|
||||
}
|
||||
|
||||
|
||||
@ -899,17 +870,7 @@ char cWorld::GetBlockMeta( int a_X, int a_Y, int a_Z )
|
||||
|
||||
void cWorld::SetBlockMeta( int a_X, int a_Y, int a_Z, char a_MetaData )
|
||||
{
|
||||
int ChunkX, ChunkY, ChunkZ;
|
||||
|
||||
AbsoluteToRelative( a_X, a_Y, a_Z, ChunkX, ChunkY, ChunkZ );
|
||||
|
||||
cChunkPtr Chunk = GetChunk( ChunkX, ChunkY, ChunkZ );
|
||||
if ( Chunk->IsValid() )
|
||||
{
|
||||
Chunk->SetLight( Chunk->pGetMeta(), a_X, a_Y, a_Z, a_MetaData );
|
||||
Chunk->SendBlockTo( a_X, a_Y, a_Z, NULL );
|
||||
}
|
||||
// The chunk is not yet initialized, so it's probably far away from all players, no need to store this Meta change
|
||||
m_ChunkMap->SetBlockMeta(a_X, a_Y, a_Z, a_MetaData);
|
||||
}
|
||||
|
||||
|
||||
@ -918,24 +879,12 @@ void cWorld::SetBlockMeta( int a_X, int a_Y, int a_Z, char a_MetaData )
|
||||
|
||||
bool cWorld::DigBlock( int a_X, int a_Y, int a_Z, cItem & a_PickupItem )
|
||||
{
|
||||
int PosX = a_X, PosY = a_Y, PosZ = a_Z, ChunkX, ChunkY, ChunkZ;
|
||||
|
||||
AbsoluteToRelative( PosX, PosY, PosZ, ChunkX, ChunkY, ChunkZ );
|
||||
|
||||
cChunkPtr DestChunk = GetChunk( ChunkX, ChunkY, ChunkZ );
|
||||
if (DestChunk->IsValid())
|
||||
bool res = m_ChunkMap->DigBlock(a_X, a_Y, a_Z, a_PickupItem);
|
||||
if (res)
|
||||
{
|
||||
DestChunk->SetBlock(PosX, PosY, PosZ, E_BLOCK_AIR, 0 );
|
||||
|
||||
GetSimulatorManager()->WakeUp(a_X, a_Y, a_Z);
|
||||
|
||||
if ( !a_PickupItem.IsEmpty() )
|
||||
{
|
||||
cPickup * Pickup = new cPickup( a_X * 32 + 16 + (int)fRadRand(16.f), a_Y * 32 + 16 + (int)fRadRand(16.f), a_Z * 32 + 16 + (int)fRadRand(16.f), a_PickupItem );
|
||||
Pickup->Initialize( this );
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@ -944,13 +893,7 @@ bool cWorld::DigBlock( int a_X, int a_Y, int a_Z, cItem & a_PickupItem )
|
||||
|
||||
void cWorld::SendBlockTo( int a_X, int a_Y, int a_Z, cPlayer * a_Player )
|
||||
{
|
||||
int ChunkX, ChunkY, ChunkZ;
|
||||
AbsoluteToRelative( a_X, a_Y, a_Z, ChunkX, ChunkY, ChunkZ );
|
||||
cChunkPtr Chunk = GetChunk( ChunkX, ChunkY, ChunkZ );
|
||||
if (Chunk->IsValid())
|
||||
{
|
||||
Chunk->SendBlockTo( a_X, a_Y, a_Z, a_Player->GetClientHandle() );
|
||||
}
|
||||
m_ChunkMap->SendBlockTo(a_X, a_Y, a_Z, a_Player);
|
||||
}
|
||||
|
||||
|
||||
@ -960,15 +903,6 @@ void cWorld::SendBlockTo( int a_X, int a_Y, int a_Z, cPlayer * a_Player )
|
||||
// TODO: This interface is dangerous!
|
||||
cBlockEntity * cWorld::GetBlockEntity( int a_X, int a_Y, int a_Z )
|
||||
{
|
||||
int PosX = a_X, PosY = a_Y, PosZ = a_Z, ChunkX, ChunkY, ChunkZ;
|
||||
|
||||
AbsoluteToRelative( PosX, PosY, PosZ, ChunkX, ChunkY, ChunkZ );
|
||||
|
||||
cChunkPtr Chunk = GetChunk( ChunkX, ChunkY, ChunkZ );
|
||||
if (Chunk->IsValid())
|
||||
{
|
||||
// TODO: return Chunk->GetBlockEntity( a_X, a_Y, a_Z );
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -1340,6 +1274,15 @@ bool cWorld::AddChunkClient(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHan
|
||||
|
||||
|
||||
|
||||
void cWorld::RemoveChunkClient(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client)
|
||||
{
|
||||
m_ChunkMap->RemoveChunkClient(a_ChunkX, a_ChunkY, a_ChunkZ, a_Client);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cWorld::RemoveClientFromChunks(cClientHandle * a_Client, const cChunkCoordsList & a_Chunks)
|
||||
{
|
||||
m_ChunkMap->RemoveClientFromChunks(a_Client, a_Chunks);
|
||||
@ -1358,6 +1301,24 @@ bool cWorld::SendChunkTo(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle
|
||||
|
||||
|
||||
|
||||
void cWorld::TouchChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
|
||||
{
|
||||
m_ChunkMap->TouchChunk(a_ChunkX, a_ChunkY, a_ChunkZ);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cWorld::UpdateSign(int a_X, int a_Y, int a_Z, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4)
|
||||
{
|
||||
m_ChunkMap->UpdateSign(a_X, a_Y, a_Z, a_Line1, a_Line2, a_Line3, a_Line4);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cWorld::SaveAllChunks()
|
||||
{
|
||||
LOG("Saving all chunks...");
|
||||
|
@ -57,9 +57,6 @@ public:
|
||||
|
||||
void SetWorldTime(long long a_WorldTime) { m_WorldTime = a_WorldTime; } //tolua_export
|
||||
|
||||
cChunkPtr GetChunk ( int a_ChunkX, int a_ChunkY, int a_ChunkZ ) {return m_ChunkMap->GetChunk (a_ChunkX, a_ChunkY, a_ChunkZ); }
|
||||
cChunkPtr GetChunkNoGen ( int a_ChunkX, int a_ChunkY, int a_ChunkZ ) {return m_ChunkMap->GetChunkNoGen(a_ChunkX, a_ChunkY, a_ChunkZ); }
|
||||
cChunkPtr GetChunkOfBlock( int a_X, int a_Y, int a_Z );
|
||||
int GetHeight( int a_X, int a_Z ); //tolua_export
|
||||
|
||||
//void AddClient( cClientHandle* a_Client );
|
||||
@ -124,12 +121,20 @@ public:
|
||||
/// Adds client to a chunk, if not already present; returns true if added, false if present
|
||||
bool AddChunkClient(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client);
|
||||
|
||||
/// Removes client from the chunk specified
|
||||
void RemoveChunkClient(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client);
|
||||
|
||||
/// Removes the client from all chunks specified
|
||||
void RemoveClientFromChunks(cClientHandle * a_Client, const cChunkCoordsList & a_Chunks);
|
||||
|
||||
/// Sends a chunk to client, returns true if successful, false if not sent
|
||||
bool SendChunkTo(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client);
|
||||
|
||||
/// Touches the chunk, causing it to be loaded or generated
|
||||
void TouchChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
||||
|
||||
void UpdateSign(int a_X, int a_Y, int a_Z, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4);
|
||||
|
||||
// TODO: Export to Lua
|
||||
bool DoWithEntity( int a_UniqueID, cEntityCallback & a_Callback );
|
||||
|
||||
@ -150,7 +155,8 @@ public:
|
||||
inline cLavaSimulator *GetLavaSimulator() { return m_LavaSimulator; }
|
||||
|
||||
// TODO: This interface is dangerous! Export as a set of specific action functions for Lua: GetChestItem, GetFurnaceItem, SetFurnaceItem, SetSignLines etc.
|
||||
cBlockEntity * GetBlockEntity( int a_X, int a_Y, int a_Z ); //tolua_export
|
||||
// _X 2012_02_21: This function always returns NULL
|
||||
OBSOLETE cBlockEntity * GetBlockEntity( int a_X, int a_Y, int a_Z ); //tolua_export
|
||||
|
||||
/// a_Player is using block entity at [x, y, z], handle that:
|
||||
void UseBlockEntity(cPlayer * a_Player, int a_X, int a_Y, int a_Z) {m_ChunkMap->UseBlockEntity(a_Player, a_X, a_Y, a_Z); }
|
||||
|
Loading…
Reference in New Issue
Block a user