diff options
author | Tiger Wang <ziwei.tiger@outlook.com> | 2021-03-28 15:40:57 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-03-28 15:40:57 +0200 |
commit | 748b121703fa28b10933f4432c09391e66179118 (patch) | |
tree | 58a39b6a75c3e9127507bf3c185a99e546147276 /src/Chunk.cpp | |
parent | Fix Windows XP to 7 compatibility (#5167) (diff) | |
download | cuberite-748b121703fa28b10933f4432c09391e66179118.tar cuberite-748b121703fa28b10933f4432c09391e66179118.tar.gz cuberite-748b121703fa28b10933f4432c09391e66179118.tar.bz2 cuberite-748b121703fa28b10933f4432c09391e66179118.tar.lz cuberite-748b121703fa28b10933f4432c09391e66179118.tar.xz cuberite-748b121703fa28b10933f4432c09391e66179118.tar.zst cuberite-748b121703fa28b10933f4432c09391e66179118.zip |
Diffstat (limited to '')
-rw-r--r-- | src/Chunk.cpp | 398 |
1 files changed, 48 insertions, 350 deletions
diff --git a/src/Chunk.cpp b/src/Chunk.cpp index 161a42512..09b0f0f99 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -12,21 +12,6 @@ #include "ClientHandle.h" #include "Server.h" #include "Defines.h" -#include "BlockEntities/BeaconEntity.h" -#include "BlockEntities/BedEntity.h" -#include "BlockEntities/BrewingstandEntity.h" -#include "BlockEntities/ChestEntity.h" -#include "BlockEntities/CommandBlockEntity.h" -#include "BlockEntities/DispenserEntity.h" -#include "BlockEntities/DropperEntity.h" -#include "BlockEntities/FlowerPotEntity.h" -#include "BlockEntities/FurnaceEntity.h" -#include "BlockEntities/HopperEntity.h" -#include "BlockEntities/JukeboxEntity.h" -#include "BlockEntities/MobHeadEntity.h" -#include "BlockEntities/MobSpawnerEntity.h" -#include "BlockEntities/NoteEntity.h" -#include "BlockEntities/SignEntity.h" #include "Entities/Pickup.h" #include "Item.h" #include "Noise/Noise.h" @@ -468,7 +453,6 @@ void cChunk::WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlock auto clone = be->Clone({posX, posY, posZ}); clone->SetWorld(m_World); AddBlockEntity(std::move(clone)); - m_World->BroadcastBlockEntity({posX, posY, posZ}); } } } @@ -789,28 +773,34 @@ void cChunk::MoveEntityToNewChunk(OwnedEntity a_Entity) void cChunk::BroadcastPendingBlockChanges(void) { - if (m_PendingSendBlocks.empty()) + if (const auto PendingBlocksCount = m_PendingSendBlocks.size(); PendingBlocksCount >= 10240) { - return; - } - - if (m_PendingSendBlocks.size() >= 10240) - { - // Resend the full chunk - for (auto ClientHandle : m_LoadedByClient) + // Resend the full chunk: + for (const auto ClientHandle : m_LoadedByClient) { m_World->ForceSendChunkTo(m_PosX, m_PosZ, cChunkSender::Priority::Medium, ClientHandle); } } - else + else if (PendingBlocksCount != 0) { - // Only send block changes - for (auto ClientHandle : m_LoadedByClient) + // Send block changes: + for (const auto ClientHandle : m_LoadedByClient) { ClientHandle->SendBlockChanges(m_PosX, m_PosZ, m_PendingSendBlocks); } } + + // Send block entity changes: + for (const auto Entity : m_PendingSendBlockEntities) + { + for (const auto ClientHandle : m_LoadedByClient) + { + Entity->SendTo(*ClientHandle); + } + } + m_PendingSendBlocks.clear(); + m_PendingSendBlockEntities.clear(); } @@ -823,12 +813,12 @@ void cChunk::CheckBlocks() cBlockInServerPluginInterface PluginInterface(*m_World); // Process a limited number of blocks since cBlockHandler::Check may queue more to tick - auto Count = m_ToTickBlocks.size(); + auto Count = m_BlocksToCheck.size(); while (Count != 0) { - const auto Pos = m_ToTickBlocks.front(); - m_ToTickBlocks.pop(); + const auto Pos = m_BlocksToCheck.front(); + m_BlocksToCheck.pop(); Count--; cBlockHandler::For(GetBlock(Pos)).Check(ChunkInterface, PluginInterface, Pos, *this); @@ -1265,8 +1255,8 @@ void cChunk::SetBlock(Vector3i a_RelPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_Blo { FastSetBlock(a_RelPos, a_BlockType, a_BlockMeta); - // Tick this block's neighbors via cBlockHandler::Check: - m_ToTickBlocks.push(a_RelPos); + // Queue a check of this block's neighbors: + m_BlocksToCheck.push(a_RelPos); // Wake up the simulators for this block: GetWorld()->GetSimulatorManager()->WakeUp(*this, a_RelPos); @@ -1370,22 +1360,26 @@ void cChunk::FastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockT void cChunk::SendBlockTo(int a_RelX, int a_RelY, int a_RelZ, cClientHandle * a_Client) { + const auto BlockEntity = GetBlockEntityRel({ a_RelX, a_RelY, a_RelZ }); if (a_Client == nullptr) { - // Queue the block for all clients in the chunk (will be sent in Tick()) + // Queue the block (entity) for all clients in the chunk (will be sent in BroadcastPendingBlockChanges()): m_PendingSendBlocks.emplace_back(m_PosX, m_PosZ, a_RelX, a_RelY, a_RelZ, GetBlock(a_RelX, a_RelY, a_RelZ), GetMeta(a_RelX, a_RelY, a_RelZ)); + if (BlockEntity != nullptr) + { + m_PendingSendBlockEntities.push_back(BlockEntity); + } return; } - Vector3i wp = PositionToWorldPosition(a_RelX, a_RelY, a_RelZ); - a_Client->SendBlockChange(wp.x, wp.y, wp.z, GetBlock(a_RelX, a_RelY, a_RelZ), GetMeta(a_RelX, a_RelY, a_RelZ)); + const auto Position = PositionToWorldPosition(a_RelX, a_RelY, a_RelZ); + a_Client->SendBlockChange(Position.x, Position.y, Position.z, GetBlock(a_RelX, a_RelY, a_RelZ), GetMeta(a_RelX, a_RelY, a_RelZ)); // FS #268 - if a BlockEntity digging is cancelled by a plugin, the entire block entity must be re-sent to the client: - cBlockEntity * Block = GetBlockEntity(wp.x, wp.y, wp.z); - if (Block != nullptr) + if (BlockEntity != nullptr) { - Block->SendTo(*a_Client); + BlockEntity->SendTo(*a_Client); } } @@ -1508,39 +1502,12 @@ void cChunk::SetAreaBiome(int a_MinRelX, int a_MaxRelX, int a_MinRelZ, int a_Max -bool cChunk::SetSignLines(int a_PosX, int a_PosY, int a_PosZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) -{ - // Also sends update packets to all clients in the chunk - auto Entity = GetBlockEntity(a_PosX, a_PosY, a_PosZ); - if (Entity == nullptr) - { - return false; // Not a block entity - } - if ( - (Entity->GetBlockType() != E_BLOCK_WALLSIGN) && - (Entity->GetBlockType() != E_BLOCK_SIGN_POST) - ) - { - return false; // Not a sign - } - - MarkDirty(); - auto Sign = static_cast<cSignEntity *>(Entity); - Sign->SetLines(a_Line1, a_Line2, a_Line3, a_Line4); - m_World->BroadcastBlockEntity({a_PosX, a_PosY, a_PosZ}); - return true; -} - - - - - void cChunk::RemoveBlockEntity(cBlockEntity * a_BlockEntity) { MarkDirty(); ASSERT(a_BlockEntity != nullptr); - auto idx = static_cast<size_t>(cChunkDef::MakeIndex(a_BlockEntity->GetRelX(), a_BlockEntity->GetPosY(), a_BlockEntity->GetRelZ())); - m_BlockEntities.erase(idx); + m_BlockEntities.erase(static_cast<size_t>(cChunkDef::MakeIndex(a_BlockEntity->GetRelX(), a_BlockEntity->GetPosY(), a_BlockEntity->GetRelZ()))); + m_PendingSendBlockEntities.erase(std::remove(m_PendingSendBlockEntities.begin(), m_PendingSendBlockEntities.end(), a_BlockEntity), m_PendingSendBlockEntities.end()); } @@ -1745,308 +1712,39 @@ bool cChunk::DoWithEntityByID(UInt32 a_EntityID, cEntityCallback a_Callback, boo -template <class tyEntity, BLOCKTYPE... tBlocktype> -bool cChunk::GenericForEachBlockEntity(cFunctionRef<bool(tyEntity &)> a_Callback) +bool cChunk::ForEachBlockEntity(cBlockEntityCallback a_Callback) { // The blockentity list is locked by the parent chunkmap's CS + for (auto & KeyPair : m_BlockEntities) { - cBlockEntity * Block = KeyPair.second.get(); - if ( - (sizeof...(tBlocktype) == 0) || // Let empty list mean all block entities - (IsOneOf<tBlocktype...>(Block->GetBlockType())) - ) + if (a_Callback(*KeyPair.second)) { - if (a_Callback(*static_cast<tyEntity *>(Block))) - { - return false; - } + return false; } - } // for KeyPair - m_BlockEntitites[] - return true; -} - - - - - -bool cChunk::ForEachBlockEntity(cBlockEntityCallback a_Callback) -{ - return GenericForEachBlockEntity<cBlockEntity>(a_Callback); -} - - - - - -bool cChunk::ForEachBrewingstand(cBrewingstandCallback a_Callback) -{ - return GenericForEachBlockEntity<cBrewingstandEntity, - E_BLOCK_BREWING_STAND - >(a_Callback); -} - - - - - -bool cChunk::ForEachChest(cChestCallback a_Callback) -{ - return GenericForEachBlockEntity<cChestEntity, - E_BLOCK_CHEST - >(a_Callback); -} - - - - - -bool cChunk::ForEachDispenser(cDispenserCallback a_Callback) -{ - return GenericForEachBlockEntity<cDispenserEntity, - E_BLOCK_DISPENSER - >(a_Callback); -} - - - - - -bool cChunk::ForEachDropper(cDropperCallback a_Callback) -{ - return GenericForEachBlockEntity<cDropperEntity, - E_BLOCK_DROPPER - >(a_Callback); -} - - - - - -bool cChunk::ForEachDropSpenser(cDropSpenserCallback a_Callback) -{ - return GenericForEachBlockEntity<cDropSpenserEntity, - E_BLOCK_DISPENSER, - E_BLOCK_DROPPER - >(a_Callback); -} - - - - - -bool cChunk::ForEachFurnace(cFurnaceCallback a_Callback) -{ - return GenericForEachBlockEntity<cFurnaceEntity, - E_BLOCK_FURNACE, - E_BLOCK_LIT_FURNACE - >(a_Callback); -} - - - - - -template <class tyEntity, BLOCKTYPE... tBlocktype> -bool cChunk::GenericDoWithBlockEntityAt(Vector3i a_Position, cFunctionRef<bool(tyEntity &)> a_Callback) -{ - // The blockentity list is locked by the parent chunkmap's CS - cBlockEntity * Block = GetBlockEntityRel(a_Position); - if (Block == nullptr) - { - return false; // No block entity here } - if ( - (sizeof...(tBlocktype) != 0) && // Let empty list mean all block entities - (!IsOneOf<tBlocktype...>(Block->GetBlockType())) - ) - { - return false; // Not any of the given tBlocktypes - } - return !a_Callback(*static_cast<tyEntity *>(Block)); -} - - - - -bool cChunk::DoWithBlockEntityAt(Vector3i a_Position, cBlockEntityCallback a_Callback) -{ - return GenericDoWithBlockEntityAt<cBlockEntity>(a_Position, a_Callback); -} - - - - - -bool cChunk::DoWithBeaconAt(Vector3i a_Position, cBeaconCallback a_Callback) -{ - return GenericDoWithBlockEntityAt<cBeaconEntity, - E_BLOCK_BEACON - >(a_Position, a_Callback); -} - - - - - -bool cChunk::DoWithBedAt(Vector3i a_Position, cBedCallback a_Callback) -{ - return GenericDoWithBlockEntityAt<cBedEntity, - E_BLOCK_BED - >(a_Position, a_Callback); -} - - - - - -bool cChunk::DoWithBrewingstandAt(Vector3i a_Position, cBrewingstandCallback a_Callback) -{ - return GenericDoWithBlockEntityAt<cBrewingstandEntity, - E_BLOCK_BREWING_STAND - >(a_Position, a_Callback); -} - - - - - -bool cChunk::DoWithChestAt(Vector3i a_Position, cChestCallback a_Callback) -{ - return GenericDoWithBlockEntityAt<cChestEntity, - E_BLOCK_CHEST, - E_BLOCK_TRAPPED_CHEST - >(a_Position, a_Callback); -} - - - - - -bool cChunk::DoWithDispenserAt(Vector3i a_Position, cDispenserCallback a_Callback) -{ - return GenericDoWithBlockEntityAt<cDispenserEntity, - E_BLOCK_DISPENSER - >(a_Position, a_Callback); -} - - - - - -bool cChunk::DoWithDropperAt(Vector3i a_Position, cDropperCallback a_Callback) -{ - return GenericDoWithBlockEntityAt<cDropperEntity, - E_BLOCK_DROPPER - >(a_Position, a_Callback); -} - - - - - -bool cChunk::DoWithDropSpenserAt(Vector3i a_Position, cDropSpenserCallback a_Callback) -{ - return GenericDoWithBlockEntityAt<cDropSpenserEntity, - E_BLOCK_DISPENSER, - E_BLOCK_DROPPER - >(a_Position, a_Callback); -} - - - - - -bool cChunk::DoWithFurnaceAt(Vector3i a_Position, cFurnaceCallback a_Callback) -{ - return GenericDoWithBlockEntityAt<cFurnaceEntity, - E_BLOCK_FURNACE, - E_BLOCK_LIT_FURNACE - >(a_Position, a_Callback); -} - - - - - -bool cChunk::DoWithHopperAt(Vector3i a_Position, cHopperCallback a_Callback) -{ - return GenericDoWithBlockEntityAt<cHopperEntity, - E_BLOCK_HOPPER - >(a_Position, a_Callback); -} - - - - - -bool cChunk::DoWithNoteBlockAt(Vector3i a_Position, cNoteBlockCallback a_Callback) -{ - return GenericDoWithBlockEntityAt<cNoteEntity, - E_BLOCK_NOTE_BLOCK - >(a_Position, a_Callback); -} - - - - - -bool cChunk::DoWithCommandBlockAt(Vector3i a_Position, cCommandBlockCallback a_Callback) -{ - return GenericDoWithBlockEntityAt<cCommandBlockEntity, - E_BLOCK_COMMAND_BLOCK - >(a_Position, a_Callback); -} - - - - - -bool cChunk::DoWithMobHeadAt(Vector3i a_Position, cMobHeadCallback a_Callback) -{ - return GenericDoWithBlockEntityAt<cMobHeadEntity, - E_BLOCK_HEAD - >(a_Position, a_Callback); -} - - - - - -bool cChunk::DoWithFlowerPotAt(Vector3i a_Position, cFlowerPotCallback a_Callback) -{ - return GenericDoWithBlockEntityAt<cFlowerPotEntity, - E_BLOCK_FLOWER_POT - >(a_Position, a_Callback); + return true; } -bool cChunk::GetSignLines(Vector3i a_Position, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4) +bool cChunk::DoWithBlockEntityAt(Vector3i a_Position, cBlockEntityCallback a_Callback) { // The blockentity list is locked by the parent chunkmap's CS - auto Entity = GetBlockEntity(a_Position); - if (Entity == nullptr) - { - return false; // Not a block entity - } - if ( - (Entity->GetBlockType() != E_BLOCK_WALLSIGN) && - (Entity->GetBlockType() != E_BLOCK_SIGN_POST) - ) + + const auto BlockEntity = GetBlockEntityRel(a_Position); + if (BlockEntity == nullptr) { - return false; // Not a sign + return false; // No block entity here } - auto Sign = static_cast<cSignEntity *>(Entity); - a_Line1 = Sign->GetLine(0); - a_Line2 = Sign->GetLine(1); - a_Line3 = Sign->GetLine(2); - a_Line4 = Sign->GetLine(3); - return true; + const bool Result = a_Callback(*BlockEntity); + m_PendingSendBlockEntities.push_back(BlockEntity); + MarkDirty(); + return Result; } |