1
0

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:
madmaxoft@gmail.com 2012-02-21 16:27:30 +00:00
parent f0145ee9fa
commit b653e6a012
10 changed files with 231 additions and 109 deletions

View File

@ -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");
}
}

View File

@ -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())
{

View File

@ -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

View File

@ -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];
}

View File

@ -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);
@ -74,6 +78,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 );
@ -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
};

View File

@ -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();
}
}

View File

@ -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 );
}
}

View File

@ -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 );
}
}

View File

@ -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...");

View File

@ -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,11 +121,19 @@ 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); }