diff --git a/src/Chunk.cpp b/src/Chunk.cpp index 3028d24d0..0587beb9c 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -1652,6 +1652,38 @@ void cChunk::UseBlockEntity(cPlayer * a_Player, int a_X, int a_Y, int a_Z) +void cChunk::SetBiomeAt(int a_RelX, int a_RelZ, EMCSBiome a_Biome) +{ + cChunkDef::SetBiome(m_BiomeMap, a_RelX, a_RelZ, a_Biome); + MarkDirty(); +} + + + + + +void cChunk::SetAreaBiome(int a_MinRelX, int a_MaxRelX, int a_MinRelZ, int a_MaxRelZ, EMCSBiome a_Biome) +{ + for (int z = a_MinRelZ; z <= a_MaxRelZ; z++) + { + for (int x = a_MinRelX; x <= a_MaxRelX; x++) + { + cChunkDef::SetBiome(m_BiomeMap, x, z, a_Biome); + } + } + MarkDirty(); + + // Re-send the chunk to all clients: + for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr) + { + m_World->ForceSendChunkTo(m_PosX, m_PosZ, (*itr)); + } // for itr - m_LoadedByClient[] +} + + + + + void cChunk::CollectPickupsByPlayer(cPlayer * a_Player) { double PosX = a_Player->GetPosX(); diff --git a/src/Chunk.h b/src/Chunk.h index 696690068..682ec6170 100644 --- a/src/Chunk.h +++ b/src/Chunk.h @@ -175,6 +175,14 @@ public: EMCSBiome GetBiomeAt(int a_RelX, int a_RelZ) const {return cChunkDef::GetBiome(m_BiomeMap, a_RelX, a_RelZ); } + /** Sets the biome at the specified relative coords. + Doesn't resend the chunk to clients. */ + void SetBiomeAt(int a_RelX, int a_RelZ, EMCSBiome a_Biome); + + /** Sets the biome in the specified relative coords area. All the coords are inclusive. + Sends the chunk to all relevant clients. */ + void SetAreaBiome(int a_MinRelX, int a_MaxRelX, int a_MinRelZ, int a_MaxRelZ, EMCSBiome a_Biome); + void CollectPickupsByPlayer(cPlayer * a_Player); /** Sets the sign text. Returns true if successful. Also sends update packets to all clients in the chunk */ diff --git a/src/ChunkMap.cpp b/src/ChunkMap.cpp index 0c5a8d9b9..01195e8bc 100644 --- a/src/ChunkMap.cpp +++ b/src/ChunkMap.cpp @@ -1390,10 +1390,10 @@ void cChunkMap::ReplaceTreeBlocks(const sSetBlockVector & a_Blocks) EMCSBiome cChunkMap::GetBiomeAt (int a_BlockX, int a_BlockZ) { int ChunkX, ChunkZ, X = a_BlockX, Y = 0, Z = a_BlockZ; - cChunkDef::AbsoluteToRelative( X, Y, Z, ChunkX, ChunkZ ); + cChunkDef::AbsoluteToRelative(X, Y, Z, ChunkX, ChunkZ); cCSLock Lock(m_CSLayers); - cChunkPtr Chunk = GetChunk( ChunkX, ZERO_CHUNK_Y, ChunkZ ); + cChunkPtr Chunk = GetChunk(ChunkX, ZERO_CHUNK_Y, ChunkZ); if ((Chunk != NULL) && Chunk->IsValid()) { return Chunk->GetBiomeAt(X, Z); @@ -1408,6 +1408,63 @@ EMCSBiome cChunkMap::GetBiomeAt (int a_BlockX, int a_BlockZ) +bool cChunkMap::SetBiomeAt(int a_BlockX, int a_BlockZ, EMCSBiome a_Biome) +{ + int ChunkX, ChunkZ, X = a_BlockX, Y = 0, Z = a_BlockZ; + cChunkDef::AbsoluteToRelative(X, Y, Z, ChunkX, ChunkZ); + + cCSLock Lock(m_CSLayers); + cChunkPtr Chunk = GetChunk(ChunkX, ZERO_CHUNK_Y, ChunkZ); + if ((Chunk != NULL) && Chunk->IsValid()) + { + Chunk->SetBiomeAt(X, Z, a_Biome); + return true; + } + return false; +} + + + + + +bool cChunkMap::SetAreaBiome(int a_MinX, int a_MaxX, int a_MinZ, int a_MaxZ, EMCSBiome a_Biome) +{ + // Translate coords to relative: + int Y = 0; + int MinChunkX, MinChunkZ, MinX = a_MinX, MinZ = a_MinZ; + int MaxChunkX, MaxChunkZ, MaxX = a_MaxX, MaxZ = a_MaxZ; + cChunkDef::AbsoluteToRelative(MinX, Y, MinZ, MinChunkX, MinChunkZ); + cChunkDef::AbsoluteToRelative(MaxX, Y, MaxZ, MaxChunkX, MaxChunkZ); + + // Go through all chunks, set: + bool res = true; + cCSLock Lock(m_CSLayers); + for (int x = MinChunkX; x <= MaxChunkX; x++) + { + int MinRelX = (x == MinChunkX) ? MinX : 0; + int MaxRelX = (x == MaxChunkX) ? MaxX : cChunkDef::Width - 1; + for (int z = MinChunkZ; z <= MaxChunkZ; z++) + { + int MinRelZ = (z == MinChunkZ) ? MinZ : 0; + int MaxRelZ = (z == MaxChunkZ) ? MaxZ : cChunkDef::Width - 1; + cChunkPtr Chunk = GetChunkNoLoad(x, ZERO_CHUNK_Y, z); + if ((Chunk != NULL) && Chunk->IsValid()) + { + Chunk->SetAreaBiome(MinRelX, MaxRelX, MinRelZ, MaxRelZ, a_Biome); + } + else + { + res = false; + } + } // for z + } // for x + return res; +} + + + + + bool cChunkMap::GetBlocks(sSetBlockVector & a_Blocks, bool a_ContinueOnFailure) { bool res = true; diff --git a/src/ChunkMap.h b/src/ChunkMap.h index d713d0cf5..9f0dd087e 100644 --- a/src/ChunkMap.h +++ b/src/ChunkMap.h @@ -159,8 +159,17 @@ public: /** Special function used for growing trees, replaces only blocks that tree may overwrite */ void ReplaceTreeBlocks(const sSetBlockVector & a_Blocks); + /** Returns the biome at the specified coords. Reads the biome from the chunk, if loaded, otherwise uses the world generator to provide the biome value */ EMCSBiome GetBiomeAt (int a_BlockX, int a_BlockZ); + /** Sets the biome at the specified coords. Returns true if successful, false if not (chunk not loaded). + Doesn't resend the chunk to clients. */ + bool SetBiomeAt(int a_BlockX, int a_BlockZ, EMCSBiome a_Biome); + + /** Sets the biome at the area. Returns true if successful, false if any subarea failed (chunk not loaded). + (Re)sends the chunks to their relevant clients if successful. */ + bool SetAreaBiome(int a_MinX, int a_MaxX, int a_MinZ, int a_MaxZ, EMCSBiome a_Biome); + /** Retrieves block types of the specified blocks. If a chunk is not loaded, doesn't modify the block. Returns true if all blocks were read. */ bool GetBlocks(sSetBlockVector & a_Blocks, bool a_ContinueOnFailure); diff --git a/src/World.cpp b/src/World.cpp index d67ad36d1..c9d7f42be 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -1487,6 +1487,33 @@ EMCSBiome cWorld::GetBiomeAt (int a_BlockX, int a_BlockZ) +bool cWorld::SetBiomeAt(int a_BlockX, int a_BlockZ, EMCSBiome a_Biome) +{ + return m_ChunkMap->SetBiomeAt(a_BlockX, a_BlockZ, a_Biome); +} + + + + + +bool cWorld::SetAreaBiome(int a_MinX, int a_MaxX, int a_MinZ, int a_MaxZ, EMCSBiome a_Biome) +{ + return m_ChunkMap->SetAreaBiome(a_MinX, a_MaxX, a_MinZ, a_MaxZ, a_Biome); +} + + + + + +bool cWorld::SetAreaBiome(const cCuboid & a_Area, EMCSBiome a_Biome) +{ + return SetAreaBiome(a_Area.p1.x, a_Area.p2.x, a_Area.p1.z, a_Area.p2.z, a_Biome); +} + + + + + void cWorld::SetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { m_ChunkMap->SetBlock(*this, a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta); @@ -2490,6 +2517,16 @@ void cWorld::SendChunkTo(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client) +void cWorld::ForceSendChunkTo(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client) +{ + a_Client->AddWantedChunk(a_ChunkX, a_ChunkZ); + m_ChunkSender.QueueSendChunkTo(a_ChunkX, a_ChunkZ, a_Client); +} + + + + + void cWorld::RemoveClientFromChunkSender(cClientHandle * a_Client) { m_ChunkSender.RemoveClient(a_Client); diff --git a/src/World.h b/src/World.h index f885040ba..dc286598c 100644 --- a/src/World.h +++ b/src/World.h @@ -47,6 +47,7 @@ class cFurnaceEntity; class cNoteEntity; class cMobCensus; class cCompositeChat; +class cCuboid; typedef std::list< cPlayer * > cPlayerList; @@ -306,9 +307,14 @@ public: /** Removes the client from all chunks it is present in */ void RemoveClientFromChunks(cClientHandle * a_Client); - /** Sends the chunk to the client specified, if the chunk is valid. If not valid, the request is postponed (ChunkSender will send that chunk when it becomes valid+lighted) */ + /** Sends the chunk to the client specified, if the client doesn't have the chunk yet. + If chunk not valid, the request is postponed (ChunkSender will send that chunk when it becomes valid + lighted). */ void SendChunkTo(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client); + /** Sends the chunk to the client specified, even if the client already has the chunk. + If the chunk's not valid, the request is postponed (ChunkSender will send that chunk when it becomes valid + lighted). */ + void ForceSendChunkTo(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client); + /** Removes client from ChunkSender's queue of chunks to be sent */ void RemoveClientFromChunkSender(cClientHandle * a_Client); @@ -549,6 +555,18 @@ public: /** Returns the biome at the specified coords. Reads the biome from the chunk, if loaded, otherwise uses the world generator to provide the biome value */ EMCSBiome GetBiomeAt(int a_BlockX, int a_BlockZ); + + /** Sets the biome at the specified coords. Returns true if successful, false if not (chunk not loaded). + Doesn't resend the chunk to clients, use ForceSendChunkTo() for that. */ + bool SetBiomeAt(int a_BlockX, int a_BlockZ, EMCSBiome a_Biome); + + /** Sets the biome at the area. Returns true if successful, false if any subarea failed (chunk not loaded). + (Re)sends the chunks to their relevant clients if successful. */ + bool SetAreaBiome(int a_MinX, int a_MaxX, int a_MinZ, int a_MaxZ, EMCSBiome a_Biome); + + /** Sets the biome at the area. Returns true if successful, false if any subarea failed (chunk not loaded). + (Re)sends the chunks to their relevant clients if successful. */ + bool SetAreaBiome(const cCuboid & a_Area, EMCSBiome a_Biome); /** Returns the name of the world */ const AString & GetName(void) const { return m_WorldName; }