From b653e6a01271c05bdbd947ab7120d10d30ecee91 Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Tue, 21 Feb 2012 16:27:30 +0000 Subject: 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 --- source/cChunkMap.cpp | 143 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 140 insertions(+), 3 deletions(-) (limited to 'source/cChunkMap.cpp') diff --git a/source/cChunkMap.cpp b/source/cChunkMap.cpp index 2621e0793..21b99873f 100644 --- a/source/cChunkMap.cpp +++ b/source/cChunkMap.cpp @@ -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 // 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]; } -- cgit v1.2.3