diff options
Diffstat (limited to '')
-rw-r--r-- | src/Bindings/ManualBindings_World.cpp | 3 | ||||
-rw-r--r-- | src/BlockEntities/MobSpawnerEntity.cpp | 6 | ||||
-rw-r--r-- | src/Blocks/BlockBed.cpp | 4 | ||||
-rw-r--r-- | src/Blocks/BlockTrapdoor.h | 2 | ||||
-rw-r--r-- | src/Blocks/BroadcastInterface.h | 62 | ||||
-rw-r--r-- | src/Broadcaster.cpp | 626 | ||||
-rw-r--r-- | src/Broadcaster.h | 18 | ||||
-rw-r--r-- | src/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/Chunk.cpp | 402 | ||||
-rw-r--r-- | src/Chunk.h | 34 | ||||
-rw-r--r-- | src/ChunkDef.h | 27 | ||||
-rw-r--r-- | src/ChunkMap.cpp | 469 | ||||
-rw-r--r-- | src/ChunkMap.h | 29 | ||||
-rw-r--r-- | src/ChunkSender.cpp | 2 | ||||
-rw-r--r-- | src/ChunkSender.h | 2 | ||||
-rw-r--r-- | src/Entities/Entity.cpp | 21 | ||||
-rw-r--r-- | src/Entities/Entity.h | 3 | ||||
-rw-r--r-- | src/Entities/EntityEffect.cpp | 6 | ||||
-rw-r--r-- | src/Entities/Floater.cpp | 5 | ||||
-rw-r--r-- | src/Entities/Pickup.cpp | 6 | ||||
-rw-r--r-- | src/Mobs/Horse.cpp | 3 | ||||
-rw-r--r-- | src/Mobs/Ocelot.cpp | 5 | ||||
-rw-r--r-- | src/Mobs/Wolf.cpp | 5 | ||||
-rw-r--r-- | src/OpaqueWorld.h | 25 | ||||
-rw-r--r-- | src/Simulator/FloodyFluidSimulator.cpp | 4 | ||||
-rw-r--r-- | src/Simulator/VaporizeFluidSimulator.cpp | 10 | ||||
-rw-r--r-- | src/World.cpp | 505 | ||||
-rw-r--r-- | src/World.h | 123 |
28 files changed, 845 insertions, 1564 deletions
diff --git a/src/Bindings/ManualBindings_World.cpp b/src/Bindings/ManualBindings_World.cpp index aada2ea47..e98e13c47 100644 --- a/src/Bindings/ManualBindings_World.cpp +++ b/src/Bindings/ManualBindings_World.cpp @@ -6,7 +6,6 @@ #include "Globals.h" #include "tolua++/include/tolua++.h" #include "../World.h" -#include "../Broadcaster.h" #include "../UUID.h" #include "ManualBindings.h" #include "LuaState.h" @@ -54,7 +53,7 @@ static int tolua_cWorld_BroadcastParticleEffect(lua_State * tolua_S) L.GetStackValue(11 + i, data[static_cast<size_t>(i)]); } - World->GetBroadcaster().BroadcastParticleEffect(Name, Vector3f(PosX, PosY, PosZ), Vector3f(OffX, OffY, OffZ), ParticleData, ParticleAmount, ExcludeClient); + World->BroadcastParticleEffect(Name, Vector3f(PosX, PosY, PosZ), Vector3f(OffX, OffY, OffZ), ParticleData, ParticleAmount, ExcludeClient); return 0; } diff --git a/src/BlockEntities/MobSpawnerEntity.cpp b/src/BlockEntities/MobSpawnerEntity.cpp index 772fa8d79..b92139025 100644 --- a/src/BlockEntities/MobSpawnerEntity.cpp +++ b/src/BlockEntities/MobSpawnerEntity.cpp @@ -178,11 +178,9 @@ void cMobSpawnerEntity::SpawnEntity(void) if (Chunk->GetWorld()->SpawnMobFinalize(std::move(Monster)) != cEntity::INVALID_ID) { HaveSpawnedEntity = true; - Chunk->BroadcastSoundParticleEffect( + m_World->BroadcastSoundParticleEffect( EffectID::PARTICLE_MOBSPAWN, - static_cast<int>(PosX * 8.0), - static_cast<int>(RelY * 8.0), - static_cast<int>(PosZ * 8.0), + Vector3d(PosX, RelY, PosZ).Floor(), 0 ); NearbyEntities++; diff --git a/src/Blocks/BlockBed.cpp b/src/Blocks/BlockBed.cpp index 901d7936a..aa816b046 100644 --- a/src/Blocks/BlockBed.cpp +++ b/src/Blocks/BlockBed.cpp @@ -91,7 +91,7 @@ bool cBlockBedHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface if ((Meta & 0x8) == 0x8) { // Is pillow - a_WorldInterface.GetBroadcastManager().BroadcastUseBed(a_Player, a_BlockX, a_BlockY, a_BlockZ); + a_WorldInterface.GetBroadcastManager().BroadcastUseBed(a_Player, { a_BlockX, a_BlockY, a_BlockZ }); } else { @@ -101,7 +101,7 @@ bool cBlockBedHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface PillowDirection = MetaDataToDirection(Meta & 0x3); if (a_ChunkInterface.GetBlock(Coords + PillowDirection) == E_BLOCK_BED) // Must always use pillow location for sleeping { - a_WorldInterface.GetBroadcastManager().BroadcastUseBed(a_Player, a_BlockX + PillowDirection.x, a_BlockY, a_BlockZ + PillowDirection.z); + a_WorldInterface.GetBroadcastManager().BroadcastUseBed(a_Player, Vector3i{ a_BlockX, a_BlockY, a_BlockZ } + PillowDirection); } } diff --git a/src/Blocks/BlockTrapdoor.h b/src/Blocks/BlockTrapdoor.h index f8e5df09a..8fdae6028 100644 --- a/src/Blocks/BlockTrapdoor.h +++ b/src/Blocks/BlockTrapdoor.h @@ -39,7 +39,7 @@ public: // Flip the ON bit on / off using the XOR bitwise operation NIBBLETYPE Meta = (a_ChunkInterface.GetBlockMeta({a_BlockX, a_BlockY, a_BlockZ}) ^ 0x04); a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta); - a_WorldInterface.GetBroadcastManager().BroadcastSoundParticleEffect(EffectID::SFX_RANDOM_FENCE_GATE_OPEN, a_BlockX, a_BlockY, a_BlockZ, 0, a_Player.GetClientHandle()); + a_WorldInterface.GetBroadcastManager().BroadcastSoundParticleEffect(EffectID::SFX_RANDOM_FENCE_GATE_OPEN, { a_BlockX, a_BlockY, a_BlockZ }, 0, a_Player.GetClientHandle()); return true; } diff --git a/src/Blocks/BroadcastInterface.h b/src/Blocks/BroadcastInterface.h index 6943d5030..9916687ee 100644 --- a/src/Blocks/BroadcastInterface.h +++ b/src/Blocks/BroadcastInterface.h @@ -1,9 +1,15 @@ #pragma once -#include "EffectID.h" - +#include "Defines.h" +#include "Scoreboard.h" +// fwd: +class cClientHandle; +class cCompositeChat; +class cPlayer; +class cWorld; +enum class EffectID : Int32; @@ -12,8 +18,52 @@ class cBroadcastInterface public: virtual ~cBroadcastInterface() {} - virtual void BroadcastUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) = 0; - virtual void BroadcastSoundEffect(const AString & a_SoundName, Vector3d a_Position, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude = nullptr) = 0; - virtual void BroadcastEntityAnimation(const cEntity & a_Entity, char a_Animation, const cClientHandle * a_Exclude = nullptr) = 0; - virtual void BroadcastSoundParticleEffect(const EffectID a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data, const cClientHandle * a_Exclude = nullptr) = 0; + // Broadcast respective packets to all clients of the chunk where the event is taking place + // (Please keep these alpha-sorted) + virtual void BroadcastAttachEntity (const cEntity & a_Entity, const cEntity & a_Vehicle) = 0; + virtual void BroadcastBlockAction (Vector3i a_BlockPos, Byte a_Byte1, Byte a_Byte2, BLOCKTYPE a_BlockType, const cClientHandle * a_Exclude = nullptr) = 0; + virtual void BroadcastBlockBreakAnimation (UInt32 a_EntityID, Vector3i a_BlockPos, Int8 a_Stage, const cClientHandle * a_Exclude = nullptr) = 0; + virtual void BroadcastBlockEntity (Vector3i a_BlockPos, const cClientHandle * a_Exclude = nullptr) = 0; + virtual void BroadcastChat (const AString & a_Message, const cClientHandle * a_Exclude = nullptr, eMessageType a_ChatPrefix = mtCustom) = 0; + virtual void BroadcastChatInfo (const AString & a_Message, const cClientHandle * a_Exclude = nullptr) = 0; + virtual void BroadcastChatFailure (const AString & a_Message, const cClientHandle * a_Exclude = nullptr) = 0; + virtual void BroadcastChatSuccess (const AString & a_Message, const cClientHandle * a_Exclude = nullptr) = 0; + virtual void BroadcastChatWarning (const AString & a_Message, const cClientHandle * a_Exclude = nullptr) = 0; + virtual void BroadcastChatFatal (const AString & a_Message, const cClientHandle * a_Exclude = nullptr) = 0; + virtual void BroadcastChatDeath (const AString & a_Message, const cClientHandle * a_Exclude = nullptr) = 0; + virtual void BroadcastChat (const cCompositeChat & a_Message, const cClientHandle * a_Exclude = nullptr) = 0; + virtual void BroadcastCollectEntity (const cEntity & a_Pickup, const cPlayer & a_Player, int a_Count, const cClientHandle * a_Exclude = nullptr) = 0; + virtual void BroadcastDestroyEntity (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) = 0; + virtual void BroadcastDetachEntity (const cEntity & a_Entity, const cEntity & a_PreviousVehicle) = 0; + virtual void BroadcastEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration, const cClientHandle * a_Exclude = nullptr) = 0; + virtual void BroadcastEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item, const cClientHandle * a_Exclude = nullptr) = 0; + virtual void BroadcastEntityHeadLook (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) = 0; + virtual void BroadcastEntityLook (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) = 0; + virtual void BroadcastEntityMetadata (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) = 0; + virtual void BroadcastEntityRelMove (const cEntity & a_Entity, Vector3<Int8> a_RelMove, const cClientHandle * a_Exclude = nullptr) = 0; + virtual void BroadcastEntityRelMoveLook (const cEntity & a_Entity, Vector3<Int8> a_RelMove, const cClientHandle * a_Exclude = nullptr) = 0; + virtual void BroadcastEntityStatus (const cEntity & a_Entity, Int8 a_Status, const cClientHandle * a_Exclude = nullptr) = 0; + virtual void BroadcastEntityVelocity (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) = 0; + virtual void BroadcastEntityAnimation (const cEntity & a_Entity, Int8 a_Animation, const cClientHandle * a_Exclude = nullptr) = 0; + virtual void BroadcastLeashEntity (const cEntity & a_Entity, const cEntity & a_EntityLeashedTo) = 0; + virtual void BroadcastParticleEffect (const AString & a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, const cClientHandle * a_Exclude = nullptr) = 0; + virtual void BroadcastParticleEffect (const AString & a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array<int, 2> a_Data, const cClientHandle * a_Exclude = nullptr) = 0; + virtual void BroadcastPlayerListAddPlayer (const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr) = 0; + virtual void BroadcastPlayerListRemovePlayer (const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr) = 0; + virtual void BroadcastPlayerListUpdateGameMode (const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr) = 0; + virtual void BroadcastPlayerListUpdatePing (const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr) = 0; + virtual void BroadcastPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName, const cClientHandle * a_Exclude = nullptr) = 0; + virtual void BroadcastRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude = nullptr) = 0; + virtual void BroadcastScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) = 0; + virtual void BroadcastScoreUpdate (const AString & a_Objective, const AString & a_PlayerName, cObjective::Score a_Score, Byte a_Mode) = 0; + virtual void BroadcastDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) = 0; + virtual void BroadcastSoundEffect (const AString & a_SoundName, Vector3d a_Position, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude = nullptr) = 0; + virtual void BroadcastSoundParticleEffect (const EffectID a_EffectID, Vector3i a_SrcPos, int a_Data, const cClientHandle * a_Exclude = nullptr) = 0; + virtual void BroadcastSpawnEntity (cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) = 0; + virtual void BroadcastTeleportEntity (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) = 0; + virtual void BroadcastThunderbolt (Vector3i a_BlockPos, const cClientHandle * a_Exclude = nullptr) = 0; + virtual void BroadcastTimeUpdate (const cClientHandle * a_Exclude = nullptr) = 0; + virtual void BroadcastUnleashEntity (const cEntity & a_Entity) = 0; + virtual void BroadcastUseBed (const cEntity & a_Entity, Vector3i a_BedPos) = 0; + virtual void BroadcastWeather (eWeather a_Weather, const cClientHandle * a_Exclude = nullptr) = 0; }; diff --git a/src/Broadcaster.cpp b/src/Broadcaster.cpp index d3d3de9f0..7ea3476b3 100644 --- a/src/Broadcaster.cpp +++ b/src/Broadcaster.cpp @@ -1,60 +1,636 @@ // Broadcaster.cpp -// Implements the broadcasting interface for cWorld +// Implements the broadcasting functions for cWorld #include "Globals.h" -#include "Broadcaster.h" #include "World.h" #include "Chunk.h" #include "ClientHandle.h" +#include "Entities/Entity.h" +#include "Entities/Player.h" +#include "BlockEntities/BlockEntity.h" -cBroadcaster::cBroadcaster(cWorld * a_World) : - m_World(a_World) +namespace { -} + /** Calls the function object a_Func for every active client in the world + \param a_World World the clients are in + \param a_Exclude Client for which a_Func should not be called + \param a_Func Function to be called with each non-excluded client */ + template <typename Func> + void ForClientsInWorld(cWorld & a_World, const cClientHandle * a_Exclude, Func a_Func) + { + a_World.ForEachPlayer([&](cPlayer & a_Player) + { + cClientHandle * Client = a_Player.GetClientHandle(); + if ((Client != a_Exclude) && (Client != nullptr) && Client->IsLoggedIn() && !Client->IsDestroyed()) + { + a_Func(*Client); + } + return false; + } + ); + } + /** Calls the function object a_Func for every client who has the specified chunk + \param a_ChunkCoords Coords of the chunk to query for clients + \param a_World World that the chunk is in + \param a_Exclude Client for which a_Func should not be called + \param a_Func Function to be called with each non-excluded client */ + template <typename Func> + void ForClientsWithChunk(const cChunkCoords a_ChunkCoords, cWorld & a_World, const cClientHandle * a_Exclude, Func a_Func) + { + a_World.DoWithChunk(a_ChunkCoords.m_ChunkX, a_ChunkCoords.m_ChunkZ, + [&](cChunk & a_Chunk) + { + for (auto * Client : a_Chunk.GetAllClients()) + { + if (Client != a_Exclude) + { + a_Func(*Client); + } + }; + return true; + } + ); + } -void cBroadcaster::BroadcastParticleEffect(const AString & a_ParticleName, const Vector3f a_Src, const Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, cClientHandle * a_Exclude) -{ - m_World->DoWithChunkAt(a_Src, - [=](cChunk & a_Chunk) -> bool + + /** Calls the function object a_Func for every client who has the chunk at the specified block position + \param a_WorldPos Coordinates of the block to query for clients + \param a_World World that the block is in + \param a_Exclude Client for which a_Func should not be called + \param a_Func Function to be called with each non-excluded client */ + template <typename Func> + void ForClientsWithChunkAtPos(const Vector3i a_WorldPos, cWorld & a_World, const cClientHandle * a_Exclude, Func a_Func) + { + ForClientsWithChunk(cChunkDef::BlockToChunk(a_WorldPos), a_World, a_Exclude, std::move(a_Func)); + } + + + + /** Calls the function object a_Func for every client who has the specified entity + \param a_Entity Entity to query for clients + \param a_World World that the block is in + \param a_Exclude Client for which a_Func should not be called + \param a_Func Function to be called with each non-excluded client */ + template <typename Func> + void ForClientsWithEntity(const cEntity & a_Entity, cWorld & a_World, const cClientHandle * a_Exclude, Func a_Func) + { + cWorld::cLock Lock(a_World); // Lock world before accessing a_Entity + auto Chunk = a_Entity.GetParentChunk(); + if (Chunk != nullptr) { - for (auto && client : a_Chunk.GetAllClients()) + for (auto * Client : Chunk->GetAllClients()) { - if (client == a_Exclude) + if (Client != a_Exclude) { - continue; + a_Func(*Client); } - client->SendParticleEffect(a_ParticleName, a_Src.x, a_Src.y, a_Src.z, a_Offset.x, a_Offset.y, a_Offset.z, a_ParticleData, a_ParticleAmount); - }; - return true; - }); + } + } + else // Some broadcasts happen before the entity's first tick sets its ParentChunk + { + ForClientsWithChunk({ a_Entity.GetChunkX(), a_Entity.GetChunkZ() }, a_World, a_Exclude, std::move(a_Func)); + } + } +} // namespace (anonymous) + + + + + +void cWorld::BroadcastAttachEntity(const cEntity & a_Entity, const cEntity & a_Vehicle) +{ + ForClientsWithEntity(a_Entity, *this, nullptr, [&](cClientHandle & a_Client) + { + a_Client.SendAttachEntity(a_Entity, a_Vehicle); + } + ); } -void cBroadcaster::BroadcastParticleEffect(const AString & a_ParticleName, const Vector3f a_Src, const Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array<int, 2> a_Data, cClientHandle * a_Exclude) +void cWorld::BroadcastBlockAction(Vector3i a_BlockPos, Byte a_Byte1, Byte a_Byte2, BLOCKTYPE a_BlockType, const cClientHandle * a_Exclude) { - m_World->DoWithChunkAt(a_Src, - [=](cChunk & a_Chunk) -> bool + ForClientsWithChunkAtPos(a_BlockPos, *this, a_Exclude, [&](cClientHandle & a_Client) { - for (auto && client : a_Chunk.GetAllClients()) + a_Client.SendBlockAction(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, static_cast<char>(a_Byte1), static_cast<char>(a_Byte2), a_BlockType); + } + ); +} + + + + + +void cWorld::BroadcastBlockBreakAnimation(UInt32 a_EntityID, Vector3i a_BlockPos, Int8 a_Stage, const cClientHandle * a_Exclude) +{ + ForClientsWithChunkAtPos(a_BlockPos, *this, a_Exclude, [&](cClientHandle & a_Client) + { + a_Client.SendBlockBreakAnim(a_EntityID, a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, a_Stage); + } + ); +} + + + + + +void cWorld::BroadcastBlockEntity(Vector3i a_BlockPos, const cClientHandle * a_Exclude) +{ + DoWithChunkAt(a_BlockPos, [&](cChunk & a_Chunk) + { + cBlockEntity * Entity = a_Chunk.GetBlockEntity(a_BlockPos); + if (Entity == nullptr) { - if (client == a_Exclude) + return false; + } + + for (auto * Client : a_Chunk.GetAllClients()) + { + if (Client != a_Exclude) { - continue; + Entity->SendTo(*Client); } - client->SendParticleEffect(a_ParticleName, a_Src, a_Offset, a_ParticleData, a_ParticleAmount, a_Data); - }; + } return true; - }); + } + ); +} + + + + + +void cWorld::BroadcastChat(const AString & a_Message, const cClientHandle * a_Exclude, eMessageType a_ChatPrefix) +{ + ForClientsInWorld(*this, a_Exclude, [&](cClientHandle & a_Client) + { + a_Client.SendChat(a_Message, a_ChatPrefix); + } + ); +} + + + + + +void cWorld::BroadcastChat(const cCompositeChat & a_Message, const cClientHandle * a_Exclude) +{ + ForClientsInWorld(*this, a_Exclude, [&](cClientHandle & a_Client) + { + a_Client.SendChat(a_Message); + } + ); +} + + + + + +void cWorld::BroadcastCollectEntity(const cEntity & a_Entity, const cPlayer & a_Player, int a_Count, const cClientHandle * a_Exclude) +{ + ForClientsWithEntity(a_Entity, *this, a_Exclude, [&](cClientHandle & a_Client) + { + a_Client.SendCollectEntity(a_Entity, a_Player, a_Count); + } + ); +} + + + + + +void cWorld::BroadcastDestroyEntity(const cEntity & a_Entity, const cClientHandle * a_Exclude) +{ + ForClientsWithEntity(a_Entity, *this, a_Exclude, [&](cClientHandle & a_Client) + { + a_Client.SendDestroyEntity(a_Entity); + } + ); +} + + + + + +void cWorld::BroadcastDetachEntity(const cEntity & a_Entity, const cEntity & a_PreviousVehicle) +{ + ForClientsWithEntity(a_Entity, *this, nullptr, [&](cClientHandle & a_Client) + { + a_Client.SendDetachEntity(a_Entity, a_PreviousVehicle); + } + ); +} + + + + + +void cWorld::BroadcastDisplayObjective(const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) +{ + ForClientsInWorld(*this, nullptr, [&](cClientHandle & a_Client) + { + a_Client.SendDisplayObjective(a_Objective, a_Display); + } + ); +} + + + + + +void cWorld::BroadcastEntityEffect(const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration, const cClientHandle * a_Exclude) +{ + ForClientsWithEntity(a_Entity, *this, a_Exclude, [&](cClientHandle & a_Client) + { + a_Client.SendEntityEffect(a_Entity, a_EffectID, a_Amplifier, a_Duration); + } + ); +} + + + + + +void cWorld::BroadcastEntityEquipment(const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item, const cClientHandle * a_Exclude) +{ + ForClientsWithEntity(a_Entity, *this, a_Exclude, [&](cClientHandle & a_Client) + { + a_Client.SendEntityEquipment(a_Entity, a_SlotNum, a_Item); + } + ); +} + + + + + +void cWorld::BroadcastEntityHeadLook(const cEntity & a_Entity, const cClientHandle * a_Exclude) +{ + ForClientsWithEntity(a_Entity, *this, a_Exclude, [&](cClientHandle & a_Client) + { + a_Client.SendEntityHeadLook(a_Entity); + } + ); +} + + + + + +void cWorld::BroadcastEntityLook(const cEntity & a_Entity, const cClientHandle * a_Exclude) +{ + ForClientsWithEntity(a_Entity, *this, a_Exclude, [&](cClientHandle & a_Client) + { + a_Client.SendEntityLook(a_Entity); + } + ); +} + + + + + +void cWorld::BroadcastEntityMetadata(const cEntity & a_Entity, const cClientHandle * a_Exclude) +{ + ForClientsWithEntity(a_Entity, *this, a_Exclude, [&](cClientHandle & a_Client) + { + a_Client.SendEntityMetadata(a_Entity); + } + ); +} + + + + + +void cWorld::BroadcastEntityRelMove(const cEntity & a_Entity, Vector3<Int8> a_RelMove, const cClientHandle * a_Exclude) +{ + ForClientsWithEntity(a_Entity, *this, a_Exclude, [&](cClientHandle & a_Client) + { + a_Client.SendEntityRelMove(a_Entity, a_RelMove.x, a_RelMove.y, a_RelMove.z); + } + ); +} + + + + + +void cWorld::BroadcastEntityRelMoveLook(const cEntity & a_Entity, Vector3<Int8> a_RelMove, const cClientHandle * a_Exclude) +{ + ForClientsWithEntity(a_Entity, *this, a_Exclude, [&](cClientHandle & a_Client) + { + a_Client.SendEntityRelMoveLook(a_Entity, a_RelMove.x, a_RelMove.y, a_RelMove.z); + } + ); +} + + + + + +void cWorld::BroadcastEntityStatus(const cEntity & a_Entity, Int8 a_Status, const cClientHandle * a_Exclude) +{ + ForClientsWithEntity(a_Entity, *this, a_Exclude, [&](cClientHandle & a_Client) + { + a_Client.SendEntityStatus(a_Entity, a_Status); + } + ); +} + + + + + +void cWorld::BroadcastEntityVelocity(const cEntity & a_Entity, const cClientHandle * a_Exclude) +{ + ForClientsWithEntity(a_Entity, *this, a_Exclude, [&](cClientHandle & a_Client) + { + a_Client.SendEntityVelocity(a_Entity); + } + ); +} + + + + +void cWorld::BroadcastEntityAnimation(const cEntity & a_Entity, Int8 a_Animation, const cClientHandle * a_Exclude) +{ + ForClientsWithEntity(a_Entity, *this, a_Exclude, [&](cClientHandle & a_Client) + { + a_Client.SendEntityAnimation(a_Entity, a_Animation); + } + ); +} + + + + + +void cWorld::BroadcastLeashEntity(const cEntity & a_Entity, const cEntity & a_EntityLeashedTo) +{ + ForClientsWithEntity(a_Entity, *this, nullptr, [&](cClientHandle & a_Client) + { + a_Client.SendLeashEntity(a_Entity, a_EntityLeashedTo); + } + ); +} + + + + + +void cWorld::BroadcastParticleEffect(const AString & a_ParticleName, const Vector3f a_Src, const Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, const cClientHandle * a_Exclude) +{ + ForClientsWithChunkAtPos(a_Src, *this, a_Exclude, [&](cClientHandle & a_Client) + { + a_Client.SendParticleEffect(a_ParticleName, a_Src.x, a_Src.y, a_Src.z, a_Offset.x, a_Offset.y, a_Offset.z, a_ParticleData, a_ParticleAmount); + } + ); +} + + + + + +void cWorld::BroadcastParticleEffect(const AString & a_ParticleName, const Vector3f a_Src, const Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array<int, 2> a_Data, const cClientHandle * a_Exclude) +{ + ForClientsWithChunkAtPos(a_Src, *this, a_Exclude, [&](cClientHandle & a_Client) + { + a_Client.SendParticleEffect(a_ParticleName, a_Src, a_Offset, a_ParticleData, a_ParticleAmount, a_Data); + } + ); +} + + + + + + +void cWorld::BroadcastPlayerListAddPlayer(const cPlayer & a_Player, const cClientHandle * a_Exclude) +{ + ForClientsInWorld(*this, a_Exclude, [&](cClientHandle & a_Client) + { + a_Client.SendPlayerListAddPlayer(a_Player); + } + ); +} + + + + + +void cWorld::BroadcastPlayerListRemovePlayer(const cPlayer & a_Player, const cClientHandle * a_Exclude) +{ + ForClientsInWorld(*this, a_Exclude, [&](cClientHandle & a_Client) + { + a_Client.SendPlayerListRemovePlayer(a_Player); + } + ); +} + + + + + +void cWorld::BroadcastPlayerListUpdateGameMode(const cPlayer & a_Player, const cClientHandle * a_Exclude) +{ + ForClientsInWorld(*this, a_Exclude, [&](cClientHandle & a_Client) + { + a_Client.SendPlayerListUpdateGameMode(a_Player); + } + ); +} + + + + + +void cWorld::BroadcastPlayerListUpdatePing(const cPlayer & a_Player, const cClientHandle * a_Exclude) +{ + ForClientsInWorld(*this, a_Exclude, [&](cClientHandle & a_Client) + { + a_Client.SendPlayerListUpdatePing(a_Player); + } + ); +} + + + + + +void cWorld::BroadcastPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName, const cClientHandle * a_Exclude) +{ + ForClientsInWorld(*this, a_Exclude, [&](cClientHandle & a_Client) + { + a_Client.SendPlayerListUpdateDisplayName(a_Player, a_CustomName); + } + ); +} + + + + + +void cWorld::BroadcastRemoveEntityEffect(const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude) +{ + ForClientsWithEntity(a_Entity, *this, a_Exclude, [&](cClientHandle & a_Client) + { + a_Client.SendRemoveEntityEffect(a_Entity, a_EffectID); + } + ); +} + + + + + +void cWorld::BroadcastScoreboardObjective(const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) +{ + ForClientsInWorld(*this, nullptr, [&](cClientHandle & a_Client) + { + a_Client.SendScoreboardObjective(a_Name, a_DisplayName, a_Mode); + } + ); +} + + + + + +void cWorld::BroadcastScoreUpdate(const AString & a_Objective, const AString & a_PlayerName, cObjective::Score a_Score, Byte a_Mode) +{ + ForClientsInWorld(*this, nullptr, [&](cClientHandle & a_Client) + { + a_Client.SendScoreUpdate(a_Objective, a_PlayerName, a_Score, a_Mode); + } + ); +} + + + + + +void cWorld::BroadcastSoundEffect(const AString & a_SoundName, Vector3d a_Position, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude) +{ + ForClientsWithChunkAtPos(a_Position, *this, a_Exclude, [&](cClientHandle & a_Client) + { + a_Client.SendSoundEffect(a_SoundName, a_Position, a_Volume, a_Pitch); + } + ); +} + + + + + +void cWorld::BroadcastSoundParticleEffect(const EffectID a_EffectID, Vector3i a_SrcPos, int a_Data, const cClientHandle * a_Exclude) +{ + ForClientsWithChunkAtPos(a_SrcPos, *this, a_Exclude, [&](cClientHandle & a_Client) + { + a_Client.SendSoundParticleEffect(a_EffectID, a_SrcPos.x, a_SrcPos.y, a_SrcPos.z, a_Data); + } + ); +} + + + + + +void cWorld::BroadcastSpawnEntity(cEntity & a_Entity, const cClientHandle * a_Exclude) +{ + ForClientsWithEntity(a_Entity, *this, a_Exclude, [&](cClientHandle & a_Client) + { + a_Entity.SpawnOn(a_Client); + } + ); +} + + + + + +void cWorld::BroadcastTeleportEntity(const cEntity & a_Entity, const cClientHandle * a_Exclude) +{ + ForClientsInWorld(*this, a_Exclude, [&](cClientHandle & a_Client) + { + a_Client.SendTeleportEntity(a_Entity); + } + ); +} + + + + + +void cWorld::BroadcastThunderbolt(Vector3i a_BlockPos, const cClientHandle * a_Exclude) +{ + ForClientsWithChunkAtPos(a_BlockPos, *this, a_Exclude, [&](cClientHandle & a_Client) + { + a_Client.SendThunderbolt(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z); + } + ); +} + + + + + +void cWorld::BroadcastTimeUpdate(const cClientHandle * a_Exclude) +{ + ForClientsInWorld(*this, a_Exclude, [&](cClientHandle & a_Client) + { + a_Client.SendTimeUpdate(GetWorldAge(), GetTimeOfDay(), IsDaylightCycleEnabled()); + } + ); +} + + + + + +void cWorld::BroadcastUnleashEntity(const cEntity & a_Entity) +{ + ForClientsWithEntity(a_Entity, *this, nullptr, [&](cClientHandle & a_Client) + { + a_Client.SendUnleashEntity(a_Entity); + } + ); +} + + + + + +void cWorld::BroadcastUseBed(const cEntity & a_Entity, Vector3i a_BedPos) +{ + ForClientsWithChunkAtPos(a_BedPos, *this, nullptr, [&](cClientHandle & a_Client) + { + a_Client.SendUseBed(a_Entity, a_BedPos.x, a_BedPos.y, a_BedPos.z); + } + ); +} + + + + + +void cWorld::BroadcastWeather(eWeather a_Weather, const cClientHandle * a_Exclude) +{ + ForClientsInWorld(*this, a_Exclude, [&](cClientHandle & a_Client) + { + a_Client.SendWeather(a_Weather); + } + ); } diff --git a/src/Broadcaster.h b/src/Broadcaster.h deleted file mode 100644 index bdd63aa41..000000000 --- a/src/Broadcaster.h +++ /dev/null @@ -1,18 +0,0 @@ - -class cWorld; - -class cBroadcaster -{ - -public: - - cBroadcaster(cWorld * a_World); - - void BroadcastParticleEffect(const AString & a_ParticleName, const Vector3f a_Src, const Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, cClientHandle * a_Exclude = nullptr); - - void BroadcastParticleEffect(const AString & a_ParticleName, const Vector3f a_Src, const Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array<int, 2> a_Data, cClientHandle * a_Exclude = nullptr); - -private: - cWorld * m_World; - -}; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f2732bf8f..642bc81a3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -85,7 +85,6 @@ SET (HDRS BlockInfo.h BlockTracer.h BrewingRecipes.h - Broadcaster.h BoundingBox.h BuildInfo.h BuildInfo.h.cmake @@ -136,6 +135,7 @@ SET (HDRS MobSpawner.h MonsterConfig.h NetherPortalScanner.h + OpaqueWorld.h OverridesSettingsRepository.h ProbabDistrib.h RankManager.h diff --git a/src/Chunk.cpp b/src/Chunk.cpp index 03415b348..b980ab3ed 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -484,7 +484,7 @@ void cChunk::WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlock auto clone = be->Clone(posX, posY, posZ); clone->SetWorld(m_World); AddBlockEntityClean(clone); - BroadcastBlockEntity({posX, posY, posZ}); + m_World->BroadcastBlockEntity({posX, posY, posZ}); } } } @@ -2636,406 +2636,6 @@ cChunk * cChunk::GetRelNeighborChunkAdjustCoords(int & a_RelX, int & a_RelZ) con -void cChunk::BroadcastAttachEntity(const cEntity & a_Entity, const cEntity & a_Vehicle) -{ - for (auto ClientHandle : m_LoadedByClient) - { - ClientHandle->SendAttachEntity(a_Entity, a_Vehicle); - } // for itr - LoadedByClient[] -} - - - - -void cChunk::BroadcastLeashEntity(const cEntity & a_Entity, const cEntity & a_EntityLeashedTo) -{ - for (auto ClientHandle : m_LoadedByClient) - { - ClientHandle->SendLeashEntity(a_Entity, a_EntityLeashedTo); - } -} - - - - -void cChunk::BroadcastUnleashEntity(const cEntity & a_Entity) -{ - for (auto ClientHandle : m_LoadedByClient) - { - ClientHandle->SendUnleashEntity(a_Entity); - } -} - - - - - -void cChunk::BroadcastBlockAction(Vector3i a_BlockPos, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType, const cClientHandle * a_Exclude) -{ - for (auto itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr) - { - if (*itr == a_Exclude) - { - continue; - } - (*itr)->SendBlockAction(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, a_Byte1, a_Byte2, a_BlockType); - } // for itr - LoadedByClient[] -} - - - - - -void cChunk::BroadcastBlockBreakAnimation(UInt32 a_EntityID, Vector3i a_BlockPos, char a_Stage, const cClientHandle * a_Exclude) -{ - for (auto itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr) - { - if (*itr == a_Exclude) - { - continue; - } - (*itr)->SendBlockBreakAnim(a_EntityID, a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, a_Stage); - } // for itr - LoadedByClient[] -} - - - - - -void cChunk::BroadcastBlockEntity(Vector3i a_BlockPos, const cClientHandle * a_Exclude) -{ - // We can operate on entity pointers, we're inside the ChunkMap's CS lock which guards the list - cBlockEntity * Entity = GetBlockEntity(a_BlockPos); - if (Entity == nullptr) - { - return; - } - for (auto itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr) - { - if (*itr == a_Exclude) - { - continue; - } - Entity->SendTo(*(*itr)); - } // for itr - LoadedByClient[] -} - - - - - -void cChunk::BroadcastCollectEntity(const cEntity & a_Entity, const cPlayer & a_Player, int a_Count, const cClientHandle * a_Exclude) -{ - for (auto itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr) - { - if (*itr == a_Exclude) - { - continue; - } - (*itr)->SendCollectEntity(a_Entity, a_Player, a_Count); - } // for itr - LoadedByClient[] -} - - - - - -void cChunk::BroadcastDestroyEntity(const cEntity & a_Entity, const cClientHandle * a_Exclude) -{ - for (auto itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr) - { - if (*itr == a_Exclude) - { - continue; - } - (*itr)->SendDestroyEntity(a_Entity); - } // for itr - LoadedByClient[] -} - - - - - -void cChunk::BroadcastDetachEntity(const cEntity & a_Entity, const cEntity & a_PreviousVehicle) -{ - for (auto ClientHandle : m_LoadedByClient) - { - ClientHandle->SendDetachEntity(a_Entity, a_PreviousVehicle); - } // for itr - LoadedByClient[] -} - - - - - -void cChunk::BroadcastEntityEffect(const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration, const cClientHandle * a_Exclude) -{ - for (auto itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr) - { - if (*itr == a_Exclude) - { - continue; - } - (*itr)->SendEntityEffect(a_Entity, a_EffectID, a_Amplifier, a_Duration); - } // for itr - LoadedByClient[] -} - - - - - -void cChunk::BroadcastEntityEquipment(const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item, const cClientHandle * a_Exclude) -{ - for (auto itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr) - { - if (*itr == a_Exclude) - { - continue; - } - (*itr)->SendEntityEquipment(a_Entity, a_SlotNum, a_Item); - } // for itr - LoadedByClient[] -} - - - - - -void cChunk::BroadcastEntityHeadLook(const cEntity & a_Entity, const cClientHandle * a_Exclude) -{ - for (auto itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr) - { - if (*itr == a_Exclude) - { - continue; - } - (*itr)->SendEntityHeadLook(a_Entity); - } // for itr - LoadedByClient[] -} - - - - - -void cChunk::BroadcastEntityLook(const cEntity & a_Entity, const cClientHandle * a_Exclude) -{ - for (auto itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr) - { - if (*itr == a_Exclude) - { - continue; - } - (*itr)->SendEntityLook(a_Entity); - } // for itr - LoadedByClient[] -} - - - - - -void cChunk::BroadcastEntityMetadata(const cEntity & a_Entity, const cClientHandle * a_Exclude) -{ - for (auto itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr) - { - if (*itr == a_Exclude) - { - continue; - } - (*itr)->SendEntityMetadata(a_Entity); - } // for itr - LoadedByClient[] -} - - - - - -void cChunk::BroadcastEntityRelMove(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ, const cClientHandle * a_Exclude) -{ - for (auto itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr) - { - if (*itr == a_Exclude) - { - continue; - } - (*itr)->SendEntityRelMove(a_Entity, a_RelX, a_RelY, a_RelZ); - } // for itr - LoadedByClient[] -} - - - - - -void cChunk::BroadcastEntityRelMoveLook(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ, const cClientHandle * a_Exclude) -{ - for (auto itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr) - { - if (*itr == a_Exclude) - { - continue; - } - (*itr)->SendEntityRelMoveLook(a_Entity, a_RelX, a_RelY, a_RelZ); - } // for itr - LoadedByClient[] -} - - - - - -void cChunk::BroadcastEntityStatus(const cEntity & a_Entity, char a_Status, const cClientHandle * a_Exclude) -{ - for (auto itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr) - { - if (*itr == a_Exclude) - { - continue; - } - (*itr)->SendEntityStatus(a_Entity, a_Status); - } // for itr - LoadedByClient[] -} - - - - - -void cChunk::BroadcastEntityVelocity(const cEntity & a_Entity, const cClientHandle * a_Exclude) -{ - for (auto itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr) - { - if (*itr == a_Exclude) - { - continue; - } - (*itr)->SendEntityVelocity(a_Entity); - } // for itr - LoadedByClient[] -} - - - - - -void cChunk::BroadcastEntityAnimation(const cEntity & a_Entity, char a_Animation, const cClientHandle * a_Exclude) -{ - for (auto itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr) - { - if (*itr == a_Exclude) - { - continue; - } - (*itr)->SendEntityAnimation(a_Entity, a_Animation); - } // for itr - LoadedByClient[] -} - - - - - -void cChunk::BroadcastParticleEffect(const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount, cClientHandle * a_Exclude) -{ - for (auto itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr) - { - if (*itr == a_Exclude) - { - continue; - } - (*itr)->SendParticleEffect(a_ParticleName, a_SrcX, a_SrcY, a_SrcZ, a_OffsetX, a_OffsetY, a_OffsetZ, a_ParticleData, a_ParticleAmount); - } // for itr - LoadedByClient[] -} - - - - - -void cChunk::BroadcastRemoveEntityEffect(const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude) -{ - for (auto itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr) - { - if (*itr == a_Exclude) - { - continue; - } - (*itr)->SendRemoveEntityEffect(a_Entity, a_EffectID); - } // for itr - LoadedByClient[] -} - - - - - -void cChunk::BroadcastSoundEffect(const AString & a_SoundName, Vector3d a_Position, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude) -{ - for (auto itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr) - { - if (*itr == a_Exclude) - { - continue; - } - (*itr)->SendSoundEffect(a_SoundName, a_Position, a_Volume, a_Pitch); - } // for itr - LoadedByClient[] -} - - - - - -void cChunk::BroadcastSoundParticleEffect(const EffectID a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data, const cClientHandle * a_Exclude) -{ - for (auto itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr) - { - if (*itr == a_Exclude) - { - continue; - } - (*itr)->SendSoundParticleEffect(a_EffectID, a_SrcX, a_SrcY, a_SrcZ, a_Data); - } // for itr - LoadedByClient[] -} - - - - - -void cChunk::BroadcastSpawnEntity(cEntity & a_Entity, const cClientHandle * a_Exclude) -{ - for (auto itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr) - { - if (*itr == a_Exclude) - { - continue; - } - a_Entity.SpawnOn(*(*itr)); - } // for itr - LoadedByClient[] -} - - - - - -void cChunk::BroadcastThunderbolt(Vector3i a_BlockPos, const cClientHandle * a_Exclude) -{ - for (auto itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr) - { - if (*itr == a_Exclude) - { - continue; - } - (*itr)->SendThunderbolt(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z); - } // for itr - LoadedByClient[] -} - - - - - -void cChunk::BroadcastUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) -{ - for (auto itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr) - { - (*itr)->SendUseBed(a_Entity, a_BlockX, a_BlockY, a_BlockZ); - } // for itr - LoadedByClient[] -} - - - - - void cChunk::SendBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cClientHandle & a_Client) { cBlockEntity * Entity = GetBlockEntity(a_BlockX, a_BlockY, a_BlockZ); diff --git a/src/Chunk.h b/src/Chunk.h index 2ca8a751a..8bec58c81 100644 --- a/src/Chunk.h +++ b/src/Chunk.h @@ -352,35 +352,6 @@ public: void CalculateHeightmap(const BLOCKTYPE * a_BlockTypes); - // Broadcast various packets to all clients of this chunk: - // (Please keep these alpha-sorted) - void BroadcastAttachEntity (const cEntity & a_Entity, const cEntity & a_Vehicle); - void BroadcastBlockAction (Vector3i a_BlockPos, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType, const cClientHandle * a_Exclude = nullptr); - void BroadcastBlockBreakAnimation(UInt32 a_EntityID, Vector3i a_BlockPos, char a_Stage, const cClientHandle * a_Exclude = nullptr); - void BroadcastBlockEntity (Vector3i a_BlockPos, const cClientHandle * a_Exclude = nullptr); - void BroadcastCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player, int a_Count, const cClientHandle * a_Exclude = nullptr); - void BroadcastDestroyEntity (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr); - void BroadcastDetachEntity (const cEntity & a_Entity, const cEntity & a_PreviousVehicle); - void BroadcastEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration, const cClientHandle * a_Exclude = nullptr); - void BroadcastEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item, const cClientHandle * a_Exclude = nullptr); - void BroadcastEntityHeadLook (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr); - void BroadcastEntityLook (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr); - void BroadcastEntityMetadata (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr); - void BroadcastEntityRelMove (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ, const cClientHandle * a_Exclude = nullptr); - void BroadcastEntityRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ, const cClientHandle * a_Exclude = nullptr); - void BroadcastEntityStatus (const cEntity & a_Entity, char a_Status, const cClientHandle * a_Exclude = nullptr); - void BroadcastEntityVelocity (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr); - void BroadcastEntityAnimation (const cEntity & a_Entity, char a_Animation, const cClientHandle * a_Exclude = nullptr); - void BroadcastLeashEntity (const cEntity & a_Entity, const cEntity & a_EntityLeashedTo); - void BroadcastParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount, cClientHandle * a_Exclude = nullptr); - void BroadcastRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude = nullptr); - void BroadcastSoundEffect (const AString & a_SoundName, Vector3d a_Position, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude = nullptr); - void BroadcastSoundParticleEffect(const EffectID a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data, const cClientHandle * a_Exclude = nullptr); - void BroadcastSpawnEntity (cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr); - void BroadcastThunderbolt (Vector3i a_BlockPos, const cClientHandle * a_Exclude = nullptr); - void BroadcastUnleashEntity (const cEntity & a_Entity); - void BroadcastUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ); - void SendBlockEntity (int a_BlockX, int a_BlockY, int a_BlockZ, cClientHandle & a_Client); Vector3i PositionToWorldPosition(Vector3i a_RelPos) @@ -503,10 +474,9 @@ public: as at least one requests is active the chunk will be ticked). */ void SetAlwaysTicked(bool a_AlwaysTicked); - // Makes a copy of the list - cClientHandleList GetAllClients(void) const + cChunkClientHandles GetAllClients(void) const { - return cClientHandleList(m_LoadedByClient.begin(), m_LoadedByClient.end()); + return cChunkClientHandles(m_LoadedByClient); } private: diff --git a/src/ChunkDef.h b/src/ChunkDef.h index 3807ae1aa..d73bd4198 100644 --- a/src/ChunkDef.h +++ b/src/ChunkDef.h @@ -71,6 +71,33 @@ public: +/** Non-owning view of a chunk's client handles. */ +class cChunkClientHandles +{ +public: + using const_iterator = std::vector<cClientHandle *>::const_iterator; + using iterator = const_iterator; + + explicit cChunkClientHandles(const std::vector<cClientHandle *> & a_Container): + m_Begin(a_Container.cbegin()), + m_End(a_Container.cend()) + { + } + + const_iterator begin() const { return m_Begin; } + const_iterator cbegin() const { return m_Begin; } + + const_iterator end() const { return m_End; } + const_iterator cend() const { return m_End; } + +private: + const_iterator m_Begin, m_End; +}; + + + + + /** Constants used throughout the code, useful typedefs and utility functions */ class cChunkDef { diff --git a/src/ChunkMap.cpp b/src/ChunkMap.cpp index 607fd0081..a8b1eff05 100644 --- a/src/ChunkMap.cpp +++ b/src/ChunkMap.cpp @@ -259,439 +259,6 @@ cChunk * cChunkMap::FindChunk(int a_ChunkX, int a_ChunkZ) -void cChunkMap::BroadcastAttachEntity(const cEntity & a_Entity, const cEntity & a_Vehicle) -{ - cCSLock Lock(m_CSChunks); - cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkZ()); - if (Chunk == nullptr) - { - return; - } - // It's perfectly legal to broadcast packets even to invalid chunks! - Chunk->BroadcastAttachEntity(a_Entity, a_Vehicle); -} - - - - -void cChunkMap::BroadcastLeashEntity(const cEntity & a_Entity, const cEntity & a_EntityLeashedTo) -{ - cCSLock Lock(m_CSChunks); - cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkZ()); - if (Chunk == nullptr) - { - return; - } - Chunk->BroadcastLeashEntity(a_Entity, a_EntityLeashedTo); -} - - - - - -void cChunkMap::BroadcastUnleashEntity(const cEntity & a_Entity) -{ - cCSLock Lock(m_CSChunks); - cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkZ()); - if (Chunk == nullptr) - { - return; - } - Chunk->BroadcastUnleashEntity(a_Entity); -} - - - - - -void cChunkMap::BroadcastBlockAction(Vector3i a_BlockPos, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType, const cClientHandle * a_Exclude) -{ - cCSLock Lock(m_CSChunks); - int x, z, ChunkX, ChunkZ; - x = a_BlockPos.x; - z = a_BlockPos.z; - cChunkDef::BlockToChunk(x, z, ChunkX, ChunkZ); - cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ); - if (Chunk == nullptr) - { - return; - } - // It's perfectly legal to broadcast packets even to invalid chunks! - Chunk->BroadcastBlockAction(a_BlockPos, a_Byte1, a_Byte2, a_BlockType, a_Exclude); -} - - - - - -void cChunkMap::BroadcastBlockBreakAnimation(UInt32 a_EntityID, Vector3i a_BlockPos, char a_Stage, const cClientHandle * a_Exclude) -{ - cCSLock Lock(m_CSChunks); - cChunkCoords ChunkPos = cChunkDef::BlockToChunk(a_BlockPos); - cChunkPtr Chunk = GetChunkNoGen(ChunkPos); - if (Chunk == nullptr) - { - return; - } - // It's perfectly legal to broadcast packets even to invalid chunks! - Chunk->BroadcastBlockBreakAnimation(a_EntityID, a_BlockPos, a_Stage, a_Exclude); -} - - - - - -void cChunkMap::BroadcastBlockEntity(Vector3i a_BlockPos, const cClientHandle * a_Exclude) -{ - cCSLock Lock(m_CSChunks); - cChunkCoords ChunkPos = cChunkDef::BlockToChunk(a_BlockPos); - cChunkPtr Chunk = GetChunkNoGen(ChunkPos); - if ((Chunk == nullptr) || !Chunk->IsValid()) - { - return; - } - Chunk->BroadcastBlockEntity(a_BlockPos, a_Exclude); -} - - - - - -void cChunkMap::BroadcastCollectEntity(const cEntity & a_Entity, const cPlayer & a_Player, int a_Count, const cClientHandle * a_Exclude) -{ - cCSLock Lock(m_CSChunks); - cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkZ()); - if (Chunk == nullptr) - { - return; - } - // It's perfectly legal to broadcast packets even to invalid chunks! - Chunk->BroadcastCollectEntity(a_Entity, a_Player, a_Count, a_Exclude); -} - - - - - -void cChunkMap::BroadcastDestroyEntity(const cEntity & a_Entity, const cClientHandle * a_Exclude) -{ - cCSLock Lock(m_CSChunks); - cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkZ()); - if (Chunk == nullptr) - { - return; - } - // It's perfectly legal to broadcast packets even to invalid chunks! - Chunk->BroadcastDestroyEntity(a_Entity, a_Exclude); -} - - - - - -void cChunkMap::BroadcastDetachEntity(const cEntity & a_Entity, const cEntity & a_PreviousVehicle) -{ - cCSLock Lock(m_CSChunks); - cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkZ()); - if (Chunk == nullptr) - { - return; - } - // It's perfectly legal to broadcast packets even to invalid chunks! - Chunk->BroadcastDetachEntity(a_Entity, a_PreviousVehicle); -} - - - - - -void cChunkMap::BroadcastEntityEffect(const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration, const cClientHandle * a_Exclude) -{ - cCSLock Lock(m_CSChunks); - cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkZ()); - if (Chunk == nullptr) - { - return; - } - // It's perfectly legal to broadcast packets even to invalid chunks! - Chunk->BroadcastEntityEffect(a_Entity, a_EffectID, a_Amplifier, a_Duration); -} - - - - - -void cChunkMap::BroadcastEntityEquipment(const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item, const cClientHandle * a_Exclude) -{ - cCSLock Lock(m_CSChunks); - cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkZ()); - if (Chunk == nullptr) - { - return; - } - // It's perfectly legal to broadcast packets even to invalid chunks! - Chunk->BroadcastEntityEquipment(a_Entity, a_SlotNum, a_Item, a_Exclude); -} - - - - - -void cChunkMap::BroadcastEntityHeadLook(const cEntity & a_Entity, const cClientHandle * a_Exclude) -{ - cCSLock Lock(m_CSChunks); - cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkZ()); - if (Chunk == nullptr) - { - return; - } - // It's perfectly legal to broadcast packets even to invalid chunks! - Chunk->BroadcastEntityHeadLook(a_Entity, a_Exclude); -} - - - - - -void cChunkMap::BroadcastEntityLook(const cEntity & a_Entity, const cClientHandle * a_Exclude) -{ - cCSLock Lock(m_CSChunks); - cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkZ()); - if (Chunk == nullptr) - { - return; - } - // It's perfectly legal to broadcast packets even to invalid chunks! - Chunk->BroadcastEntityLook(a_Entity, a_Exclude); -} - - - - - -void cChunkMap::BroadcastEntityMetadata(const cEntity & a_Entity, const cClientHandle * a_Exclude) -{ - cCSLock Lock(m_CSChunks); - cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkZ()); - if (Chunk == nullptr) - { - return; - } - // It's perfectly legal to broadcast packets even to invalid chunks! - Chunk->BroadcastEntityMetadata(a_Entity, a_Exclude); -} - - - - - -void cChunkMap::BroadcastEntityRelMove(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ, const cClientHandle * a_Exclude) -{ - cCSLock Lock(m_CSChunks); - cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkZ()); - if (Chunk == nullptr) - { - return; - } - // It's perfectly legal to broadcast packets even to invalid chunks! - Chunk->BroadcastEntityRelMove(a_Entity, a_RelX, a_RelY, a_RelZ, a_Exclude); -} - - - - - -void cChunkMap::BroadcastEntityRelMoveLook(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ, const cClientHandle * a_Exclude) -{ - cCSLock Lock(m_CSChunks); - cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkZ()); - if (Chunk == nullptr) - { - return; - } - // It's perfectly legal to broadcast packets even to invalid chunks! - Chunk->BroadcastEntityRelMoveLook(a_Entity, a_RelX, a_RelY, a_RelZ, a_Exclude); -} - - - - - -void cChunkMap::BroadcastEntityStatus(const cEntity & a_Entity, char a_Status, const cClientHandle * a_Exclude) -{ - cCSLock Lock(m_CSChunks); - cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkZ()); - if (Chunk == nullptr) - { - return; - } - // It's perfectly legal to broadcast packets even to invalid chunks! - Chunk->BroadcastEntityStatus(a_Entity, a_Status, a_Exclude); -} - - - - - -void cChunkMap::BroadcastEntityVelocity(const cEntity & a_Entity, const cClientHandle * a_Exclude) -{ - cCSLock Lock(m_CSChunks); - cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkZ()); - if (Chunk == nullptr) - { - return; - } - // It's perfectly legal to broadcast packets even to invalid chunks! - Chunk->BroadcastEntityVelocity(a_Entity, a_Exclude); -} - - - - - -void cChunkMap::BroadcastEntityAnimation(const cEntity & a_Entity, char a_Animation, const cClientHandle * a_Exclude) -{ - cCSLock Lock(m_CSChunks); - cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkZ()); - if (Chunk == nullptr) - { - return; - } - // It's perfectly legal to broadcast packets even to invalid chunks! - Chunk->BroadcastEntityAnimation(a_Entity, a_Animation, a_Exclude); -} - - - - - -void cChunkMap::BroadcastParticleEffect(const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount, cClientHandle * a_Exclude) -{ - cCSLock Lock(m_CSChunks); - int ChunkX, ChunkZ; - - cChunkDef::BlockToChunk(FloorC(a_SrcX), FloorC(a_SrcZ), ChunkX, ChunkZ); - cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ); - if (Chunk == nullptr) - { - return; - } - // It's perfectly legal to broadcast packets even to invalid chunks! - Chunk->BroadcastParticleEffect(a_ParticleName, a_SrcX, a_SrcY, a_SrcZ, a_OffsetX, a_OffsetY, a_OffsetZ, a_ParticleData, a_ParticleAmount, a_Exclude); -} - - - - - -void cChunkMap::BroadcastRemoveEntityEffect(const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude) -{ - cCSLock Lock(m_CSChunks); - - cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkZ()); - if (Chunk == nullptr) - { - return; - } - // It's perfectly legal to broadcast packets even to invalid chunks! - Chunk->BroadcastRemoveEntityEffect(a_Entity, a_EffectID, a_Exclude); -} - - - - - -void cChunkMap::BroadcastSoundEffect(const AString & a_SoundName, Vector3d a_Position, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude) -{ - cCSLock Lock(m_CSChunks); - int ChunkX, ChunkZ; - - cChunkDef::BlockToChunk(FloorC(std::floor(a_Position.x)), FloorC(std::floor(a_Position.z)), ChunkX, ChunkZ); - cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ); - if (Chunk == nullptr) - { - return; - } - // It's perfectly legal to broadcast packets even to invalid chunks! - Chunk->BroadcastSoundEffect(a_SoundName, a_Position, a_Volume, a_Pitch, a_Exclude); -} - - - - - -void cChunkMap::BroadcastSoundParticleEffect(const EffectID a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data, const cClientHandle * a_Exclude) -{ - cCSLock Lock(m_CSChunks); - int ChunkX, ChunkZ; - - cChunkDef::BlockToChunk(a_SrcX, a_SrcZ, ChunkX, ChunkZ); - cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ); - if (Chunk == nullptr) - { - return; - } - // It's perfectly legal to broadcast packets even to invalid chunks! - Chunk->BroadcastSoundParticleEffect(a_EffectID, a_SrcX, a_SrcY, a_SrcZ, a_Data, a_Exclude); -} - - - - - -void cChunkMap::BroadcastSpawnEntity(cEntity & a_Entity, const cClientHandle * a_Exclude) -{ - cCSLock Lock(m_CSChunks); - cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkZ()); - if (Chunk == nullptr) - { - return; - } - // It's perfectly legal to broadcast packets even to invalid chunks! - Chunk->BroadcastSpawnEntity(a_Entity, a_Exclude); -} - - - - - -void cChunkMap::BroadcastThunderbolt(Vector3i a_BlockPos, const cClientHandle * a_Exclude) -{ - cCSLock Lock(m_CSChunks); - int ChunkX, ChunkZ; - cChunkDef::BlockToChunk(a_BlockPos.x, a_BlockPos.z, ChunkX, ChunkZ); - cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ); - if (Chunk == nullptr) - { - return; - } - // It's perfectly legal to broadcast packets even to invalid chunks! - Chunk->BroadcastThunderbolt(a_BlockPos, a_Exclude); -} - - - - - -void cChunkMap::BroadcastUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) -{ - cCSLock Lock(m_CSChunks); - int ChunkX, ChunkZ; - - cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ); - cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ); - if (Chunk == nullptr) - { - return; - } - // It's perfectly legal to broadcast packets even to invalid chunks! - Chunk->BroadcastUseBed(a_Entity, a_BlockX, a_BlockY, a_BlockZ); -} - - - - - void cChunkMap::SendBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cClientHandle & a_Client) { cCSLock Lock(m_CSChunks); @@ -1418,44 +985,28 @@ void cChunkMap::CompareChunkClients(int a_ChunkX1, int a_ChunkZ1, int a_ChunkX2, void cChunkMap::CompareChunkClients(cChunk * a_Chunk1, cChunk * a_Chunk2, cClientDiffCallback & a_Callback) { - cClientHandleList Clients1(a_Chunk1->GetAllClients()); - cClientHandleList Clients2(a_Chunk2->GetAllClients()); + auto Clients1 = a_Chunk1->GetAllClients(); + auto Clients2 = a_Chunk2->GetAllClients(); // Find "removed" clients: - for (cClientHandleList::iterator itr1 = Clients1.begin(); itr1 != Clients1.end(); ++itr1) + for (auto * Client : Clients1) { - bool Found = false; - for (cClientHandleList::iterator itr2 = Clients2.begin(); itr2 != Clients2.end(); ++itr2) - { - if (*itr1 == *itr2) - { - Found = true; - break; - } - } // for itr2 - Clients2[] + bool Found = (std::find(Clients2.begin(), Clients2.end(), Client) != Clients2.end()); if (!Found) { - a_Callback.Removed(*itr1); + a_Callback.Removed(Client); } - } // for itr1 - Clients1[] + } // for Client - Clients1[] // Find "added" clients: - for (cClientHandleList::iterator itr2 = Clients2.begin(); itr2 != Clients2.end(); ++itr2) + for (auto * Client : Clients2) { - bool Found = false; - for (cClientHandleList::iterator itr1 = Clients1.begin(); itr1 != Clients1.end(); ++itr1) - { - if (*itr1 == *itr2) - { - Found = true; - break; - } - } // for itr1 - Clients1[] + bool Found = (std::find(Clients1.begin(), Clients1.end(), Client) != Clients1.end()); if (!Found) { - a_Callback.Added(*itr2); + a_Callback.Added(Client); } - } // for itr2 - Clients2[] + } // for Client - Clients2[] } diff --git a/src/ChunkMap.h b/src/ChunkMap.h index 2bd8e8302..8f0ac3a7c 100644 --- a/src/ChunkMap.h +++ b/src/ChunkMap.h @@ -68,35 +68,6 @@ public: cChunkMap(cWorld * a_World); ~cChunkMap(); - // Broadcast respective packets to all clients of the chunk where the event is taking place - // (Please keep these alpha-sorted) - void BroadcastAttachEntity(const cEntity & a_Entity, const cEntity & a_Vehicle); - void BroadcastBlockAction(Vector3i a_BlockPos, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType, const cClientHandle * a_Exclude = nullptr); - void BroadcastBlockBreakAnimation(UInt32 a_EntityID, Vector3i a_BlockPos, char a_Stage, const cClientHandle * a_Exclude = nullptr); - void BroadcastBlockEntity(Vector3i a_BlockPos, const cClientHandle * a_Exclude); - void BroadcastCollectEntity(const cEntity & a_Entity, const cPlayer & a_Player, int a_Count, const cClientHandle * a_Exclude = nullptr); - void BroadcastDestroyEntity(const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr); - void BroadcastDetachEntity(const cEntity & a_Entity, const cEntity & a_PreviousVehicle); - void BroadcastEntityEffect(const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration, const cClientHandle * a_Exclude = nullptr); - void BroadcastEntityEquipment(const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item, const cClientHandle * a_Exclude = nullptr); - void BroadcastEntityHeadLook(const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr); - void BroadcastEntityLook(const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr); - void BroadcastEntityMetadata(const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr); - void BroadcastEntityRelMove(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ, const cClientHandle * a_Exclude = nullptr); - void BroadcastEntityRelMoveLook(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ, const cClientHandle * a_Exclude = nullptr); - void BroadcastEntityStatus(const cEntity & a_Entity, char a_Status, const cClientHandle * a_Exclude = nullptr); - void BroadcastEntityVelocity(const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr); - void BroadcastEntityAnimation(const cEntity & a_Entity, char a_Animation, const cClientHandle * a_Exclude = nullptr); - void BroadcastLeashEntity(const cEntity & a_Entity, const cEntity & a_EntityLeashedTo); - void BroadcastParticleEffect(const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount, cClientHandle * a_Exclude = nullptr); - void BroadcastRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude = nullptr); - void BroadcastSoundEffect(const AString & a_SoundName, Vector3d a_Position, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude = nullptr); - void BroadcastSoundParticleEffect(const EffectID a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data, const cClientHandle * a_Exclude = nullptr); - void BroadcastSpawnEntity(cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr); - void BroadcastThunderbolt(Vector3i a_BlockPos, const cClientHandle * a_Exclude = nullptr); - void BroadcastUnleashEntity(const cEntity & a_Entity); - void BroadcastUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ); - /** Sends the block entity, if it is at the coords specified, to a_Client */ void SendBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cClientHandle & a_Client); diff --git a/src/ChunkSender.cpp b/src/ChunkSender.cpp index aa51ed4ed..d5aed1a48 100644 --- a/src/ChunkSender.cpp +++ b/src/ChunkSender.cpp @@ -123,7 +123,7 @@ void cChunkSender::QueueSendChunkTo(int a_ChunkX, int a_ChunkZ, eChunkPriority a -void cChunkSender::QueueSendChunkTo(int a_ChunkX, int a_ChunkZ, eChunkPriority a_Priority, std::list<cClientHandle *> a_Clients) +void cChunkSender::QueueSendChunkTo(int a_ChunkX, int a_ChunkZ, eChunkPriority a_Priority, cChunkClientHandles a_Clients) { { cChunkCoords Chunk{a_ChunkX, a_ChunkZ}; diff --git a/src/ChunkSender.h b/src/ChunkSender.h index c5702d7b3..018beb60e 100644 --- a/src/ChunkSender.h +++ b/src/ChunkSender.h @@ -71,7 +71,7 @@ public: /** Queues a chunk to be sent to a specific client */ void QueueSendChunkTo(int a_ChunkX, int a_ChunkZ, eChunkPriority a_Priority, cClientHandle * a_Client); - void QueueSendChunkTo(int a_ChunkX, int a_ChunkZ, eChunkPriority a_Priority, std::list<cClientHandle *> a_Client); + void QueueSendChunkTo(int a_ChunkX, int a_ChunkZ, eChunkPriority a_Priority, cChunkClientHandles a_Client); /** Removes the a_Client from all waiting chunk send operations */ void RemoveClient(cClientHandle * a_Client); diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index 4ecc5c4da..a71c68708 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -214,15 +214,6 @@ void cEntity::SetParentChunk(cChunk * a_Chunk) -cChunk * cEntity::GetParentChunk() -{ - return m_ParentChunk; -} - - - - - void cEntity::Destroy(bool a_ShouldBroadcast) { SetIsTicking(false); @@ -1923,23 +1914,21 @@ void cEntity::BroadcastMovementUpdate(const cClientHandle * a_Exclude) if (!m_bHasSentNoSpeed || IsPlayer()) { // TODO: Pickups move disgracefully if relative move packets are sent as opposed to just velocity. Have a system to send relmove only when SetPosXXX() is called with a large difference in position - int DiffX = FloorC(GetPosX() * 32.0) - FloorC(m_LastSentPosition.x * 32.0); - int DiffY = FloorC(GetPosY() * 32.0) - FloorC(m_LastSentPosition.y * 32.0); - int DiffZ = FloorC(GetPosZ() * 32.0) - FloorC(m_LastSentPosition.z * 32.0); + Vector3i Diff = (GetPosition() * 32.0).Floor() - (m_LastSentPosition * 32.0).Floor(); - if ((DiffX != 0) || (DiffY != 0) || (DiffZ != 0)) // Have we moved? + if (Diff.HasNonZeroLength()) // Have we moved? { - if ((abs(DiffX) <= 127) && (abs(DiffY) <= 127) && (abs(DiffZ) <= 127)) // Limitations of a Byte + if ((abs(Diff.x) <= 127) && (abs(Diff.y) <= 127) && (abs(Diff.z) <= 127)) // Limitations of a Byte { // Difference within Byte limitations, use a relative move packet if (m_bDirtyOrientation) { - m_World->BroadcastEntityRelMoveLook(*this, static_cast<char>(DiffX), static_cast<char>(DiffY), static_cast<char>(DiffZ), a_Exclude); + m_World->BroadcastEntityRelMoveLook(*this, Vector3<Int8>(Diff), a_Exclude); m_bDirtyOrientation = false; } else { - m_World->BroadcastEntityRelMove(*this, static_cast<char>(DiffX), static_cast<char>(DiffY), static_cast<char>(DiffZ), a_Exclude); + m_World->BroadcastEntityRelMove(*this, Vector3<Int8>(Diff), a_Exclude); } // Clients seem to store two positions, one for the velocity packet and one for the teleport / relmove packet // The latter is only changed with a relmove / teleport, and m_LastSentPosition stores this position diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h index 91ad524c7..bb6efcbbd 100644 --- a/src/Entities/Entity.h +++ b/src/Entities/Entity.h @@ -535,7 +535,8 @@ public: void SetParentChunk(cChunk * a_Chunk); /** Returns the chunk responsible for ticking this entity. */ - cChunk * GetParentChunk(); + cChunk * GetParentChunk() { return m_ParentChunk; } + const cChunk * GetParentChunk() const { return m_ParentChunk; } /** Set the entity's status to either ticking or not ticking. */ void SetIsTicking(bool a_IsTicking); diff --git a/src/Entities/EntityEffect.cpp b/src/Entities/EntityEffect.cpp index 45a98c0d2..040513a26 100644 --- a/src/Entities/EntityEffect.cpp +++ b/src/Entities/EntityEffect.cpp @@ -410,10 +410,10 @@ void cEntityEffectHunger::OnTick(cPawn & a_Target) void cEntityEffectInvisibility::BroadcastMetadata(cPawn & a_Target) { - auto ParentChunk = a_Target.GetParentChunk(); - if (ParentChunk != nullptr) + auto World = a_Target.GetWorld(); + if (World != nullptr) { - ParentChunk->BroadcastEntityMetadata(a_Target); + World->BroadcastEntityMetadata(a_Target); } } diff --git a/src/Entities/Floater.cpp b/src/Entities/Floater.cpp index 82213c668..d70cb4345 100644 --- a/src/Entities/Floater.cpp +++ b/src/Entities/Floater.cpp @@ -6,7 +6,6 @@ #include "Floater.h" #include "Player.h" #include "../ClientHandle.h" -#include "Broadcaster.h" @@ -123,12 +122,12 @@ void cFloater::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { LOGD("Started producing particles for floater %i", GetUniqueID()); m_ParticlePos.Set(GetPosX() + Random.RandInt(-4, 4), GetPosY(), GetPosZ() + Random.RandInt(-4, 4)); - m_World->GetBroadcaster().BroadcastParticleEffect("splash", static_cast<Vector3f>(m_ParticlePos), Vector3f{}, 0, 15); + m_World->BroadcastParticleEffect("splash", static_cast<Vector3f>(m_ParticlePos), Vector3f{}, 0, 15); } else if (m_CountDownTime < 20) { m_ParticlePos = (m_ParticlePos + (GetPosition() - m_ParticlePos) / 6); - m_World->GetBroadcaster().BroadcastParticleEffect("splash", static_cast<Vector3f>(m_ParticlePos), Vector3f{}, 0, 15); + m_World->BroadcastParticleEffect("splash", static_cast<Vector3f>(m_ParticlePos), Vector3f{}, 0, 15); } m_CountDownTime--; diff --git a/src/Entities/Pickup.cpp b/src/Entities/Pickup.cpp index 629f5d189..4b983588c 100644 --- a/src/Entities/Pickup.cpp +++ b/src/Entities/Pickup.cpp @@ -60,10 +60,8 @@ public: if (Item.m_ItemCount <= 0) { /* Experimental: show animation pickups getting together */ - int DiffX = FloorC(m_Pickup->GetPosX() * 32.0) - FloorC(EntityPos.x * 32.0); - int DiffY = FloorC(m_Pickup->GetPosY() * 32.0) - FloorC(EntityPos.y * 32.0); - int DiffZ = FloorC(m_Pickup->GetPosZ() * 32.0) - FloorC(EntityPos.z * 32.0); - a_Entity.GetWorld()->BroadcastEntityRelMove(a_Entity, static_cast<char>(DiffX), static_cast<char>(DiffY), static_cast<char>(DiffZ)); + auto Diff = (m_Pickup->GetPosition() * 32.0).Floor() - (EntityPos * 32.0).Floor(); + a_Entity.GetWorld()->BroadcastEntityRelMove(a_Entity, Vector3<char>(Diff)); /* End of experimental animation */ a_Entity.Destroy(); diff --git a/src/Mobs/Horse.cpp b/src/Mobs/Horse.cpp index 77edc0d27..af325ae67 100644 --- a/src/Mobs/Horse.cpp +++ b/src/Mobs/Horse.cpp @@ -4,7 +4,6 @@ #include "../World.h" #include "../EffectID.h" #include "../Entities/Player.h" -#include "Broadcaster.h" #include "UI/HorseWindow.h" @@ -90,7 +89,7 @@ void cHorse::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) } else { - m_World->GetBroadcaster().BroadcastParticleEffect("heart", static_cast<Vector3f>(GetPosition()), Vector3f{}, 0, 5); + m_World->BroadcastParticleEffect("heart", static_cast<Vector3f>(GetPosition()), Vector3f{}, 0, 5); m_bIsTame = true; } } diff --git a/src/Mobs/Ocelot.cpp b/src/Mobs/Ocelot.cpp index 5e94cacb9..7ebe37d20 100644 --- a/src/Mobs/Ocelot.cpp +++ b/src/Mobs/Ocelot.cpp @@ -5,7 +5,6 @@ #include "../World.h" #include "../Entities/Player.h" #include "../Items/ItemHandler.h" -#include "Broadcaster.h" #include "../BoundingBox.h" @@ -159,13 +158,13 @@ void cOcelot::OnRightClicked(cPlayer & a_Player) SetOwner(a_Player.GetName(), a_Player.GetUUID()); SetCatType(static_cast<eCatType>(Random.RandInt<int>(1, 3))); m_World->BroadcastEntityStatus(*this, esWolfTamed); - m_World->GetBroadcaster().BroadcastParticleEffect("heart", static_cast<Vector3f>(GetPosition()), Vector3f{}, 0, 5); + m_World->BroadcastParticleEffect("heart", static_cast<Vector3f>(GetPosition()), Vector3f{}, 0, 5); } else { // Taming failed m_World->BroadcastEntityStatus(*this, esWolfTaming); - m_World->GetBroadcaster().BroadcastParticleEffect("smoke", static_cast<Vector3f>(GetPosition()), Vector3f{}, 0, 5); + m_World->BroadcastParticleEffect("smoke", static_cast<Vector3f>(GetPosition()), Vector3f{}, 0, 5); } } } diff --git a/src/Mobs/Wolf.cpp b/src/Mobs/Wolf.cpp index 45df3dd05..ffeb8cf90 100644 --- a/src/Mobs/Wolf.cpp +++ b/src/Mobs/Wolf.cpp @@ -5,7 +5,6 @@ #include "../World.h" #include "../Entities/Player.h" #include "../Items/ItemHandler.h" -#include "Broadcaster.h" @@ -183,13 +182,13 @@ void cWolf::OnRightClicked(cPlayer & a_Player) SetIsTame(true); SetOwner(a_Player.GetName(), a_Player.GetUUID()); m_World->BroadcastEntityStatus(*this, esWolfTamed); - m_World->GetBroadcaster().BroadcastParticleEffect("heart", static_cast<Vector3f>(GetPosition()), Vector3f{}, 0, 5); + m_World->BroadcastParticleEffect("heart", static_cast<Vector3f>(GetPosition()), Vector3f{}, 0, 5); } else { // Taming failed m_World->BroadcastEntityStatus(*this, esWolfTaming); - m_World->GetBroadcaster().BroadcastParticleEffect("smoke", static_cast<Vector3f>(GetPosition()), Vector3f{}, 0, 5); + m_World->BroadcastParticleEffect("smoke", static_cast<Vector3f>(GetPosition()), Vector3f{}, 0, 5); } } } diff --git a/src/OpaqueWorld.h b/src/OpaqueWorld.h new file mode 100644 index 000000000..d0d4e7fd0 --- /dev/null +++ b/src/OpaqueWorld.h @@ -0,0 +1,25 @@ + +#pragma once + +// fwd: +class cBroadcastInterface; +class cChunkInterface; +class cForEachChunkProvider; +class cWorld; +class cWorldInterface; + +/** Utilities to allow casting a cWorld to one of its interfaces without including World.h. */ +namespace World +{ + // Defined in World.cpp + cBroadcastInterface * GetBroadcastInterface(cWorld * a_World); + cForEachChunkProvider * GetFECProvider (cWorld * a_World); + cWorldInterface * GetWorldInterface (cWorld * a_World); + + inline cBroadcastInterface & GetBroadcastInterface(cWorld & a_World) { return *GetBroadcastInterface(&a_World); } + inline cForEachChunkProvider & GetFECProvider (cWorld & a_World) { return *GetFECProvider(&a_World); } + inline cWorldInterface & GetWorldInterface (cWorld & a_World) { return *GetWorldInterface(&a_World); } + + // cChunkInterface is more like a pimpl for cChunkMap than an interface so it needs to be returned by value + cChunkInterface GetChunkInterface(cWorld & a_World); +} diff --git a/src/Simulator/FloodyFluidSimulator.cpp b/src/Simulator/FloodyFluidSimulator.cpp index b5ded0c3e..76f1502ff 100644 --- a/src/Simulator/FloodyFluidSimulator.cpp +++ b/src/Simulator/FloodyFluidSimulator.cpp @@ -258,7 +258,7 @@ void cFloodyFluidSimulator::SpreadToNeighbor(cChunk * a_NearChunk, int a_RelX, i ); a_NearChunk->SetBlock(a_RelX, a_RelY, a_RelZ, NewBlock, 0); - a_NearChunk->BroadcastSoundEffect( + m_World.BroadcastSoundEffect( "block.lava.extinguish", Vector3d(BlockX, a_RelY, BlockZ), 0.5f, @@ -278,7 +278,7 @@ void cFloodyFluidSimulator::SpreadToNeighbor(cChunk * a_NearChunk, int a_RelX, i ); a_NearChunk->SetBlock(a_RelX, a_RelY, a_RelZ, NewBlock, 0); - a_NearChunk->BroadcastSoundEffect( + m_World.BroadcastSoundEffect( "block.lava.extinguish", Vector3d(BlockX, a_RelY, BlockZ), 0.5f, diff --git a/src/Simulator/VaporizeFluidSimulator.cpp b/src/Simulator/VaporizeFluidSimulator.cpp index 873dbe177..32a55794d 100644 --- a/src/Simulator/VaporizeFluidSimulator.cpp +++ b/src/Simulator/VaporizeFluidSimulator.cpp @@ -5,7 +5,9 @@ #include "Globals.h" #include "VaporizeFluidSimulator.h" +#include "../OpaqueWorld.h" #include "../Chunk.h" +#include "../Blocks/BroadcastInterface.h" @@ -35,13 +37,9 @@ void cVaporizeFluidSimulator::AddBlock(Vector3i a_Block, cChunk * a_Chunk) ) { a_Chunk->SetBlock(RelX, a_Block.y, RelZ, E_BLOCK_AIR, 0); - a_Chunk->BroadcastSoundEffect( + World::GetBroadcastInterface(m_World).BroadcastSoundEffect( "block.fire.extinguish", - { - static_cast<double>(a_Block.x), - static_cast<double>(a_Block.y), - static_cast<double>(a_Block.z) - }, + Vector3d(a_Block), 1.0f, 0.6f ); diff --git a/src/World.cpp b/src/World.cpp index 97155c872..c88db0a7e 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -50,9 +50,9 @@ #include <stdlib.h> #endif -#include "Broadcaster.h" #include "SpawnPrepare.h" #include "FastRandom.h" +#include "OpaqueWorld.h" @@ -66,6 +66,23 @@ const int TIME_SPAWN_DIVISOR = 148; +namespace World +{ + // Implement conversion functions from OpaqueWorld.h + cBroadcastInterface * GetBroadcastInterface(cWorld * a_World) { return a_World; } + cForEachChunkProvider * GetFECProvider (cWorld * a_World) { return a_World; } + cWorldInterface * GetWorldInterface (cWorld * a_World) { return a_World; } + + cChunkInterface GetChunkInterface(cWorld & a_World) + { + return { a_World.GetChunkMap() }; + } +} + + + + + //////////////////////////////////////////////////////////////////////////////// // cWorld::cLock: @@ -2409,485 +2426,6 @@ bool cWorld::TryGetHeight(int a_BlockX, int a_BlockZ, int & a_Height) -void cWorld::BroadcastAttachEntity(const cEntity & a_Entity, const cEntity & a_Vehicle) -{ - m_ChunkMap->BroadcastAttachEntity(a_Entity, a_Vehicle); -} - - - - - -void cWorld::BroadcastBlockAction(Vector3i a_BlockPos, Byte a_Byte1, Byte a_Byte2, BLOCKTYPE a_BlockType, const cClientHandle * a_Exclude) -{ - m_ChunkMap->BroadcastBlockAction(a_BlockPos, static_cast<char>(a_Byte1), static_cast<char>(a_Byte2), a_BlockType, a_Exclude); -} - - - - - -void cWorld::BroadcastBlockAction(int a_BlockX, int a_BlockY, int a_BlockZ, Byte a_Byte1, Byte a_Byte2, BLOCKTYPE a_BlockType, const cClientHandle * a_Exclude) -{ - LOG("BroadcastBlockAction with integer position is deprecated, use vector-parametered version instead."); - m_ChunkMap->BroadcastBlockAction({a_BlockX, a_BlockY, a_BlockZ}, static_cast<char>(a_Byte1), static_cast<char>(a_Byte2), a_BlockType, a_Exclude); -} - - - - - -void cWorld::BroadcastBlockBreakAnimation(UInt32 a_EntityID, Vector3i a_BlockPos, char a_Stage, const cClientHandle * a_Exclude) -{ - m_ChunkMap->BroadcastBlockBreakAnimation(a_EntityID, a_BlockPos, a_Stage, a_Exclude); -} - - - - - -void cWorld::BroadcastBlockEntity(Vector3i a_BlockPos, const cClientHandle * a_Exclude) -{ - m_ChunkMap->BroadcastBlockEntity(a_BlockPos, a_Exclude); -} - - - - - -void cWorld::BroadcastChat(const AString & a_Message, const cClientHandle * a_Exclude, eMessageType a_ChatPrefix) -{ - cCSLock Lock(m_CSPlayers); - for (cPlayerList::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) - { - cClientHandle * ch = (*itr)->GetClientHandle(); - if ((ch == a_Exclude) || (ch == nullptr) || !ch->IsLoggedIn() || ch->IsDestroyed()) - { - continue; - } - ch->SendChat(a_Message, a_ChatPrefix); - } -} - - - - - -void cWorld::BroadcastChat(const cCompositeChat & a_Message, const cClientHandle * a_Exclude) -{ - cCSLock Lock(m_CSPlayers); - for (cPlayerList::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) - { - cClientHandle * ch = (*itr)->GetClientHandle(); - if ((ch == a_Exclude) || (ch == nullptr) || !ch->IsLoggedIn() || ch->IsDestroyed()) - { - continue; - } - ch->SendChat(a_Message); - } -} - - - - - -void cWorld::BroadcastCollectEntity(const cEntity & a_Entity, const cPlayer & a_Player, int a_Count, const cClientHandle * a_Exclude) -{ - m_ChunkMap->BroadcastCollectEntity(a_Entity, a_Player, a_Count, a_Exclude); -} - - - - - -void cWorld::BroadcastDestroyEntity(const cEntity & a_Entity, const cClientHandle * a_Exclude) -{ - m_ChunkMap->BroadcastDestroyEntity(a_Entity, a_Exclude); -} - - - - - -void cWorld::BroadcastDetachEntity(const cEntity & a_Entity, const cEntity & a_PreviousVehicle) -{ - m_ChunkMap->BroadcastDetachEntity(a_Entity, a_PreviousVehicle); -} - - - - - -void cWorld::BroadcastLeashEntity(const cEntity & a_Entity, const cEntity & a_EntityLeashedTo) -{ - m_ChunkMap->BroadcastLeashEntity(a_Entity, a_EntityLeashedTo); -} - - - - - -void cWorld::BroadcastUnleashEntity(const cEntity & a_Entity) -{ - m_ChunkMap->BroadcastUnleashEntity(a_Entity); -} - - - - - -void cWorld::BroadcastEntityEffect(const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration, const cClientHandle * a_Exclude) -{ - m_ChunkMap->BroadcastEntityEffect(a_Entity, a_EffectID, a_Amplifier, a_Duration, a_Exclude); -} - - - - - -void cWorld::BroadcastEntityEquipment(const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item, const cClientHandle * a_Exclude) -{ - m_ChunkMap->BroadcastEntityEquipment(a_Entity, a_SlotNum, a_Item, a_Exclude); -} - - - - - -void cWorld::BroadcastEntityHeadLook(const cEntity & a_Entity, const cClientHandle * a_Exclude) -{ - m_ChunkMap->BroadcastEntityHeadLook(a_Entity, a_Exclude); -} - - - - - -void cWorld::BroadcastEntityLook(const cEntity & a_Entity, const cClientHandle * a_Exclude) -{ - m_ChunkMap->BroadcastEntityLook(a_Entity, a_Exclude); -} - - - - - -void cWorld::BroadcastEntityMetadata(const cEntity & a_Entity, const cClientHandle * a_Exclude) -{ - m_ChunkMap->BroadcastEntityMetadata(a_Entity, a_Exclude); -} - - - - - -void cWorld::BroadcastEntityRelMove(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ, const cClientHandle * a_Exclude) -{ - m_ChunkMap->BroadcastEntityRelMove(a_Entity, a_RelX, a_RelY, a_RelZ, a_Exclude); -} - - - - - -void cWorld::BroadcastEntityRelMoveLook(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ, const cClientHandle * a_Exclude) -{ - m_ChunkMap->BroadcastEntityRelMoveLook(a_Entity, a_RelX, a_RelY, a_RelZ, a_Exclude); -} - - - - - -void cWorld::BroadcastEntityStatus(const cEntity & a_Entity, char a_Status, const cClientHandle * a_Exclude) -{ - m_ChunkMap->BroadcastEntityStatus(a_Entity, a_Status, a_Exclude); -} - - - - - -void cWorld::BroadcastEntityVelocity(const cEntity & a_Entity, const cClientHandle * a_Exclude) -{ - m_ChunkMap->BroadcastEntityVelocity(a_Entity, a_Exclude); -} - - - - -void cWorld::BroadcastEntityAnimation(const cEntity & a_Entity, char a_Animation, const cClientHandle * a_Exclude) -{ - m_ChunkMap->BroadcastEntityAnimation(a_Entity, a_Animation, a_Exclude); -} - - - - - - -void cWorld::BroadcastPlayerListAddPlayer(const cPlayer & a_Player, const cClientHandle * a_Exclude) -{ - cCSLock Lock(m_CSPlayers); - for (cPlayerList::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) - { - cClientHandle * ch = (*itr)->GetClientHandle(); - if ((ch == a_Exclude) || (ch == nullptr) || !ch->IsLoggedIn() || ch->IsDestroyed()) - { - continue; - } - ch->SendPlayerListAddPlayer(a_Player); - } -} - - - - - -void cWorld::BroadcastPlayerListRemovePlayer(const cPlayer & a_Player, const cClientHandle * a_Exclude) -{ - cCSLock Lock(m_CSPlayers); - for (cPlayerList::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) - { - cClientHandle * ch = (*itr)->GetClientHandle(); - if ((ch == a_Exclude) || (ch == nullptr) || !ch->IsLoggedIn()) - { - continue; - } - ch->SendPlayerListRemovePlayer(a_Player); - } -} - - - - - -void cWorld::BroadcastPlayerListUpdateGameMode(const cPlayer & a_Player, const cClientHandle * a_Exclude) -{ - cCSLock Lock(m_CSPlayers); - for (cPlayerList::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) - { - cClientHandle * ch = (*itr)->GetClientHandle(); - if ((ch == a_Exclude) || (ch == nullptr) || !ch->IsLoggedIn() || ch->IsDestroyed()) - { - continue; - } - ch->SendPlayerListUpdateGameMode(a_Player); - } -} - - - - - -void cWorld::BroadcastPlayerListUpdatePing(const cPlayer & a_Player, const cClientHandle * a_Exclude) -{ - cCSLock Lock(m_CSPlayers); - for (cPlayerList::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) - { - cClientHandle * ch = (*itr)->GetClientHandle(); - if ((ch == a_Exclude) || (ch == nullptr) || !ch->IsLoggedIn() || ch->IsDestroyed()) - { - continue; - } - ch->SendPlayerListUpdatePing(a_Player); - } -} - - - - - -void cWorld::BroadcastPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName, const cClientHandle * a_Exclude) -{ - cCSLock Lock(m_CSPlayers); - for (cPlayerList::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) - { - cClientHandle * ch = (*itr)->GetClientHandle(); - if ((ch == a_Exclude) || (ch == nullptr) || !ch->IsLoggedIn() || ch->IsDestroyed()) - { - continue; - } - ch->SendPlayerListUpdateDisplayName(a_Player, a_CustomName); - } -} - - - - - -void cWorld::BroadcastRemoveEntityEffect(const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude) -{ - m_ChunkMap->BroadcastRemoveEntityEffect(a_Entity, a_EffectID, a_Exclude); -} - - - - - -void cWorld::BroadcastScoreboardObjective(const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) -{ - cCSLock Lock(m_CSPlayers); - for (cPlayerList::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) - { - cClientHandle * ch = (*itr)->GetClientHandle(); - if ((ch == nullptr) || !ch->IsLoggedIn() || ch->IsDestroyed()) - { - continue; - } - ch->SendScoreboardObjective(a_Name, a_DisplayName, a_Mode); - } -} - - - - - -void cWorld::BroadcastScoreUpdate(const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) -{ - cCSLock Lock(m_CSPlayers); - for (cPlayerList::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) - { - cClientHandle * ch = (*itr)->GetClientHandle(); - if ((ch == nullptr) || !ch->IsLoggedIn() || ch->IsDestroyed()) - { - continue; - } - ch->SendScoreUpdate(a_Objective, a_Player, a_Score, a_Mode); - } -} - - - - - -void cWorld::BroadcastDisplayObjective(const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) -{ - cCSLock Lock(m_CSPlayers); - for (cPlayerList::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) - { - cClientHandle * ch = (*itr)->GetClientHandle(); - if ((ch == nullptr) || !ch->IsLoggedIn() || ch->IsDestroyed()) - { - continue; - } - ch->SendDisplayObjective(a_Objective, a_Display); - } -} - - - - - -void cWorld::BroadcastSoundEffect(const AString & a_SoundName, Vector3d a_Position, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude) -{ - m_ChunkMap->BroadcastSoundEffect(a_SoundName, a_Position, a_Volume, a_Pitch, a_Exclude); -} - - - - - -void cWorld::BroadcastSoundEffect(const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude) -{ - LOG("BroadcastSoundEffect with double position arguments is deprecated, use vector-parametered version instead."); - BroadcastSoundEffect(a_SoundName, {a_X, a_Y, a_Z}, a_Volume, a_Pitch, a_Exclude); -} - - - - - -void cWorld::BroadcastSoundParticleEffect(const EffectID a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data, const cClientHandle * a_Exclude) -{ - m_ChunkMap->BroadcastSoundParticleEffect(a_EffectID, a_SrcX, a_SrcY, a_SrcZ, a_Data, a_Exclude); -} - - - - - -void cWorld::BroadcastSpawnEntity(cEntity & a_Entity, const cClientHandle * a_Exclude) -{ - m_ChunkMap->BroadcastSpawnEntity(a_Entity, a_Exclude); -} - - - - - -void cWorld::BroadcastTeleportEntity(const cEntity & a_Entity, const cClientHandle * a_Exclude) -{ - cCSLock Lock(m_CSPlayers); - for (cPlayerList::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) - { - cClientHandle * ch = (*itr)->GetClientHandle(); - if ((ch == a_Exclude) || (ch == nullptr) || !ch->IsLoggedIn() || ch->IsDestroyed()) - { - continue; - } - ch->SendTeleportEntity(a_Entity); - } -} - - - - - -void cWorld::BroadcastThunderbolt(Vector3i a_BlockPos, const cClientHandle * a_Exclude) -{ - m_ChunkMap->BroadcastThunderbolt(a_BlockPos, a_Exclude); -} - - - - - -void cWorld::BroadcastTimeUpdate(const cClientHandle * a_Exclude) -{ - cCSLock Lock(m_CSPlayers); - for (cPlayerList::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) - { - cClientHandle * ch = (*itr)->GetClientHandle(); - if ((ch == a_Exclude) || (ch == nullptr) || !ch->IsLoggedIn() || ch->IsDestroyed()) - { - continue; - } - ch->SendTimeUpdate(std::chrono::duration_cast<cTickTimeLong>(m_WorldAge).count(), std::chrono::duration_cast<cTickTimeLong>(m_TimeOfDay).count(), m_IsDaylightCycleEnabled); - } -} - - - - - -void cWorld::BroadcastUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) -{ - m_ChunkMap->BroadcastUseBed(a_Entity, a_BlockX, a_BlockY, a_BlockZ); -} - - - - - -void cWorld::BroadcastWeather(eWeather a_Weather, const cClientHandle * a_Exclude) -{ - cCSLock Lock(m_CSPlayers); - for (cPlayerList::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) - { - cClientHandle * ch = (*itr)->GetClientHandle(); - if ((ch == a_Exclude) || (ch == nullptr) || !ch->IsLoggedIn() || ch->IsDestroyed()) - { - continue; - } - ch->SendWeather(a_Weather); - } -} - - - - - void cWorld::SendBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cClientHandle & a_Client) { m_ChunkMap->SendBlockEntity(a_BlockX, a_BlockY, a_BlockZ, a_Client); @@ -4228,10 +3766,3 @@ void cWorld::cChunkGeneratorCallbacks::CallHookChunkGenerated (cChunkDesc & a_Ch *m_World, a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ(), &a_ChunkDesc ); } - - - -cBroadcaster cWorld::GetBroadcaster() -{ - return cBroadcaster(this); -} diff --git a/src/World.h b/src/World.h index fda4ef045..595cdb807 100644 --- a/src/World.h +++ b/src/World.h @@ -49,7 +49,6 @@ class cNoteEntity; class cMobHeadEntity; class cCompositeChat; class cSetChunkData; -class cBroadcaster; class cDeadlockDetect; class cUUID; @@ -63,14 +62,14 @@ typedef std::vector<cSetChunkDataPtr> cSetChunkDataPtrs; -// tolua_begin -class cWorld : +class cWorld // tolua_export + final: public cForEachChunkProvider, public cWorldInterface, public cBroadcastInterface +// tolua_begin { public: - // tolua_end /** A simple RAII locker for the chunkmap - locks the chunkmap in its constructor, unlocks it in the destructor */ @@ -160,57 +159,79 @@ public: bool TryGetHeight(int a_BlockX, int a_BlockZ, int & a_Height); // Exported in ManualBindings.cpp // Broadcast respective packets to all clients of the chunk where the event is taking place + // Implemented in Broadcaster.cpp // (Please keep these alpha-sorted) - void BroadcastAttachEntity (const cEntity & a_Entity, const cEntity & a_Vehicle); - void BroadcastBlockAction (Vector3i a_BlockPos, Byte a_Byte1, Byte a_Byte2, BLOCKTYPE a_BlockType, const cClientHandle * a_Exclude = nullptr); // tolua_export - void BroadcastBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, Byte a_Byte1, Byte a_Byte2, BLOCKTYPE a_BlockType, const cClientHandle * a_Exclude = nullptr); // tolua_export - void BroadcastBlockBreakAnimation(UInt32 a_EntityID, Vector3i a_BlockPos, char a_Stage, const cClientHandle * a_Exclude = nullptr); - void BroadcastBlockEntity (Vector3i a_BlockPos, const cClientHandle * a_Exclude = nullptr); ///< If there is a block entity at the specified coods, sends it to all clients except a_Exclude + virtual void BroadcastAttachEntity (const cEntity & a_Entity, const cEntity & a_Vehicle) override; + virtual void BroadcastBlockAction (Vector3i a_BlockPos, Byte a_Byte1, Byte a_Byte2, BLOCKTYPE a_BlockType, const cClientHandle * a_Exclude = nullptr) override; // tolua_export + virtual void BroadcastBlockBreakAnimation(UInt32 a_EntityID, Vector3i a_BlockPos, Int8 a_Stage, const cClientHandle * a_Exclude = nullptr) override; + virtual void BroadcastBlockEntity (Vector3i a_BlockPos, const cClientHandle * a_Exclude = nullptr) override; ///< If there is a block entity at the specified coods, sends it to all clients except a_Exclude // tolua_begin - void BroadcastChat (const AString & a_Message, const cClientHandle * a_Exclude = nullptr, eMessageType a_ChatPrefix = mtCustom); - void BroadcastChatInfo (const AString & a_Message, const cClientHandle * a_Exclude = nullptr) { BroadcastChat(a_Message, a_Exclude, mtInformation); } - void BroadcastChatFailure(const AString & a_Message, const cClientHandle * a_Exclude = nullptr) { BroadcastChat(a_Message, a_Exclude, mtFailure); } - void BroadcastChatSuccess(const AString & a_Message, const cClientHandle * a_Exclude = nullptr) { BroadcastChat(a_Message, a_Exclude, mtSuccess); } - void BroadcastChatWarning(const AString & a_Message, const cClientHandle * a_Exclude = nullptr) { BroadcastChat(a_Message, a_Exclude, mtWarning); } - void BroadcastChatFatal (const AString & a_Message, const cClientHandle * a_Exclude = nullptr) { BroadcastChat(a_Message, a_Exclude, mtFailure); } - void BroadcastChatDeath (const AString & a_Message, const cClientHandle * a_Exclude = nullptr) { BroadcastChat(a_Message, a_Exclude, mtDeath); } - void BroadcastChat (const cCompositeChat & a_Message, const cClientHandle * a_Exclude = nullptr); + virtual void BroadcastChat (const AString & a_Message, const cClientHandle * a_Exclude = nullptr, eMessageType a_ChatPrefix = mtCustom) override; + virtual void BroadcastChatInfo (const AString & a_Message, const cClientHandle * a_Exclude = nullptr) override { BroadcastChat(a_Message, a_Exclude, mtInformation); } + virtual void BroadcastChatFailure(const AString & a_Message, const cClientHandle * a_Exclude = nullptr) override { BroadcastChat(a_Message, a_Exclude, mtFailure); } + virtual void BroadcastChatSuccess(const AString & a_Message, const cClientHandle * a_Exclude = nullptr) override { BroadcastChat(a_Message, a_Exclude, mtSuccess); } + virtual void BroadcastChatWarning(const AString & a_Message, const cClientHandle * a_Exclude = nullptr) override { BroadcastChat(a_Message, a_Exclude, mtWarning); } + virtual void BroadcastChatFatal (const AString & a_Message, const cClientHandle * a_Exclude = nullptr) override { BroadcastChat(a_Message, a_Exclude, mtFailure); } + virtual void BroadcastChatDeath (const AString & a_Message, const cClientHandle * a_Exclude = nullptr) override { BroadcastChat(a_Message, a_Exclude, mtDeath); } + virtual void BroadcastChat (const cCompositeChat & a_Message, const cClientHandle * a_Exclude = nullptr) override; // tolua_end - void BroadcastCollectEntity (const cEntity & a_Pickup, const cPlayer & a_Player, int a_Count, const cClientHandle * a_Exclude = nullptr); - void BroadcastDestroyEntity (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr); - void BroadcastDetachEntity (const cEntity & a_Entity, const cEntity & a_PreviousVehicle); - void BroadcastEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration, const cClientHandle * a_Exclude = nullptr); - void BroadcastEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item, const cClientHandle * a_Exclude = nullptr); - void BroadcastEntityHeadLook (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr); - void BroadcastEntityLook (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr); - void BroadcastEntityMetadata (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr); - void BroadcastEntityRelMove (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ, const cClientHandle * a_Exclude = nullptr); - void BroadcastEntityRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ, const cClientHandle * a_Exclude = nullptr); - void BroadcastEntityStatus (const cEntity & a_Entity, char a_Status, const cClientHandle * a_Exclude = nullptr); - void BroadcastEntityVelocity (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr); - virtual void BroadcastEntityAnimation (const cEntity & a_Entity, char a_Animation, const cClientHandle * a_Exclude = nullptr) override; // tolua_export - void BroadcastLeashEntity (const cEntity & a_Entity, const cEntity & a_EntityLeashedTo); - void BroadcastPlayerListAddPlayer (const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr); - void BroadcastPlayerListRemovePlayer (const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr); - void BroadcastPlayerListUpdateGameMode (const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr); - void BroadcastPlayerListUpdatePing (const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr); - void BroadcastPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName, const cClientHandle * a_Exclude = nullptr); - void BroadcastRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude = nullptr); - void BroadcastScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode); - void BroadcastScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode); - void BroadcastDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display); - void BroadcastSoundEffect (const AString & a_SoundName, Vector3d a_Position, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude = nullptr) override; // tolua_export - void BroadcastSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude = nullptr); // tolua_export - virtual void BroadcastSoundParticleEffect (const EffectID a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data, const cClientHandle * a_Exclude = nullptr) override; // tolua_export - void BroadcastSpawnEntity (cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr); - void BroadcastTeleportEntity (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr); - void BroadcastThunderbolt (Vector3i a_BlockPos, const cClientHandle * a_Exclude = nullptr); - void BroadcastTimeUpdate (const cClientHandle * a_Exclude = nullptr); - void BroadcastUnleashEntity (const cEntity & a_Entity); - virtual void BroadcastUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) override; - void BroadcastWeather (eWeather a_Weather, const cClientHandle * a_Exclude = nullptr); + virtual void BroadcastCollectEntity (const cEntity & a_Pickup, const cPlayer & a_Player, int a_Count, const cClientHandle * a_Exclude = nullptr) override; + virtual void BroadcastDestroyEntity (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) override; + virtual void BroadcastDetachEntity (const cEntity & a_Entity, const cEntity & a_PreviousVehicle) override; + virtual void BroadcastEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration, const cClientHandle * a_Exclude = nullptr) override; + virtual void BroadcastEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item, const cClientHandle * a_Exclude = nullptr) override; + virtual void BroadcastEntityHeadLook (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) override; + virtual void BroadcastEntityLook (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) override; + virtual void BroadcastEntityMetadata (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) override; + virtual void BroadcastEntityRelMove (const cEntity & a_Entity, Vector3<Int8> a_RelMove, const cClientHandle * a_Exclude = nullptr) override; + virtual void BroadcastEntityRelMoveLook (const cEntity & a_Entity, Vector3<Int8> a_RelMove, const cClientHandle * a_Exclude = nullptr) override; + virtual void BroadcastEntityStatus (const cEntity & a_Entity, Int8 a_Status, const cClientHandle * a_Exclude = nullptr) override; + virtual void BroadcastEntityVelocity (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) override; + virtual void BroadcastEntityAnimation (const cEntity & a_Entity, Int8 a_Animation, const cClientHandle * a_Exclude = nullptr) override; // tolua_export + virtual void BroadcastLeashEntity (const cEntity & a_Entity, const cEntity & a_EntityLeashedTo) override; + virtual void BroadcastParticleEffect (const AString & a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, const cClientHandle * a_Exclude = nullptr) override; + virtual void BroadcastParticleEffect (const AString & a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array<int, 2> a_Data, const cClientHandle * a_Exclude = nullptr) override; + virtual void BroadcastPlayerListAddPlayer (const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr) override; + virtual void BroadcastPlayerListRemovePlayer (const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr) override; + virtual void BroadcastPlayerListUpdateGameMode (const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr) override; + virtual void BroadcastPlayerListUpdatePing (const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr) override; + virtual void BroadcastPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName, const cClientHandle * a_Exclude = nullptr) override; + virtual void BroadcastRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude = nullptr) override; + virtual void BroadcastScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override; + virtual void BroadcastScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) override; + virtual void BroadcastDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) override; + virtual void BroadcastSoundEffect (const AString & a_SoundName, Vector3d a_Position, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude = nullptr) override; // tolua_export + virtual void BroadcastSoundParticleEffect (const EffectID a_EffectID, Vector3i a_SrcPos, int a_Data, const cClientHandle * a_Exclude = nullptr) override; + virtual void BroadcastSpawnEntity (cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) override; + virtual void BroadcastTeleportEntity (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) override; + virtual void BroadcastThunderbolt (Vector3i a_BlockPos, const cClientHandle * a_Exclude = nullptr) override; + virtual void BroadcastTimeUpdate (const cClientHandle * a_Exclude = nullptr) override; + virtual void BroadcastUnleashEntity (const cEntity & a_Entity) override; + virtual void BroadcastUseBed (const cEntity & a_Entity, Vector3i a_BlockPos) override; + virtual void BroadcastWeather (eWeather a_Weather, const cClientHandle * a_Exclude = nullptr) override; + + // Deprecated broadcasts maintained for lua compatibility + + // tolua_begin + void BroadcastBlockAction(int a_BlockX, int a_BlockY, int a_BlockZ, Byte a_Byte1, Byte a_Byte2, BLOCKTYPE a_BlockType, const cClientHandle * a_Exclude) + { + LOG("BroadcastBlockAction with integer position is deprecated, use vector-parametered version instead."); + BroadcastBlockAction({ a_BlockX, a_BlockY, a_BlockZ }, a_Byte1, a_Byte2, a_BlockType, a_Exclude); + } + + void BroadcastSoundEffect(const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude = nullptr) + { + LOG("BroadcastSoundEffect with double position arguments is deprecated, use vector-parametered version instead."); + BroadcastSoundEffect(a_SoundName, { a_X, a_Y, a_Z }, a_Volume, a_Pitch, a_Exclude); + } + + void BroadcastSoundParticleEffect(const EffectID a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data, const cClientHandle * a_Exclude = nullptr) + { + BroadcastSoundParticleEffect(a_EffectID, { a_SrcX, a_SrcY, a_SrcZ }, a_Data, a_Exclude); + } + // tolua_end virtual cBroadcastInterface & GetBroadcastManager(void) override { @@ -855,8 +876,6 @@ public: as at least one requests is active the chunk will be ticked). */ void SetChunkAlwaysTicked(int a_ChunkX, int a_ChunkZ, bool a_AlwaysTicked = true); // tolua_export - cBroadcaster GetBroadcaster(); - private: friend class cRoot; |