summaryrefslogtreecommitdiffstats
path: root/src/Chunk.cpp
diff options
context:
space:
mode:
authorTiger Wang <ziwei.tiger@outlook.com>2021-03-28 15:40:57 +0200
committerGitHub <noreply@github.com>2021-03-28 15:40:57 +0200
commit748b121703fa28b10933f4432c09391e66179118 (patch)
tree58a39b6a75c3e9127507bf3c185a99e546147276 /src/Chunk.cpp
parentFix Windows XP to 7 compatibility (#5167) (diff)
downloadcuberite-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.cpp398
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;
}