From aa61f55b743a8ecf3cd8e1f99e1d9a0308f6d014 Mon Sep 17 00:00:00 2001 From: andrew Date: Tue, 21 Jan 2014 15:58:17 +0200 Subject: Scoreboard protocol support --- src/ClientHandle.cpp | 30 +++++++++++++++ src/ClientHandle.h | 4 ++ src/Entities/Player.cpp | 17 ++++++--- src/Protocol/Protocol.h | 4 ++ src/Protocol/Protocol125.h | 7 +++- src/Protocol/Protocol15x.cpp | 54 ++++++++++++++++++++++++++- src/Protocol/Protocol15x.h | 3 ++ src/Protocol/Protocol17x.cpp | 40 ++++++++++++++++++++ src/Protocol/Protocol17x.h | 3 ++ src/Protocol/ProtocolRecognizer.cpp | 32 +++++++++++++++- src/Protocol/ProtocolRecognizer.h | 3 ++ src/Scoreboard.cpp | 66 +++++++++++++++++++++++++++++---- src/Scoreboard.h | 13 ++++++- src/Server.cpp | 2 +- src/World.cpp | 57 +++++++++++++++++++++++++++- src/World.h | 5 ++- src/WorldStorage/ScoreboardSerializer.h | 4 ++ 17 files changed, 321 insertions(+), 23 deletions(-) diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index faf583fbb..30d1bdaa4 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -267,6 +267,9 @@ void cClientHandle::Authenticate(void) m_Player->Initialize(World); m_State = csAuthenticated; + // Query player team + m_Player->UpdateTeam(); + cRoot::Get()->GetPluginManager()->CallHookPlayerSpawned(*m_Player); } @@ -2105,6 +2108,33 @@ void cClientHandle::SendExperienceOrb(const cExpOrb & a_ExpOrb) +void cClientHandle::SendScoreboardObjective(const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) +{ + m_Protocol->SendScoreboardObjective(a_Name, a_DisplayName, a_Mode); +} + + + + + +void cClientHandle::SendScoreUpdate(const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) +{ + m_Protocol->SendScoreUpdate(a_Objective, a_Player, a_Score, a_Mode); +} + + + + + +void cClientHandle::SendDisplayObjective(const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) +{ + m_Protocol->SendDisplayObjective(a_Objective, a_Display); +} + + + + + void cClientHandle::SendSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) { m_Protocol->SendSoundEffect(a_SoundName, a_SrcX, a_SrcY, a_SrcZ, a_Volume, a_Pitch); diff --git a/src/ClientHandle.h b/src/ClientHandle.h index 373ca9e2e..636934f6f 100644 --- a/src/ClientHandle.h +++ b/src/ClientHandle.h @@ -16,6 +16,7 @@ #include "OSSupport/SocketThreads.h" #include "ChunkDef.h" #include "ByteBuffer.h" +#include "Scoreboard.h" @@ -125,6 +126,9 @@ public: void SendRespawn (void); void SendExperience (void); void SendExperienceOrb (const cExpOrb & a_ExpOrb); + void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode); + void SendScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode); + void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display); void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch); // a_Src coords are Block * 8 void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data); void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock); diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 285aefd25..c6b24a465 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -111,8 +111,6 @@ cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName) m_LastJumpHeight = (float)(GetPosY()); m_LastGroundHeight = (float)(GetPosY()); m_Stance = GetPosY() + 1.62; - - // UpdateTeam(); cRoot::Get()->GetServer()->PlayerCreated(this); } @@ -867,10 +865,10 @@ void cPlayer::KilledBy(cEntity * a_Killer) } } IncrementCounter (GetName()); - cScoreboard* Scoreboard = m_World->GetScoreBoard(); + cScoreboard & Scoreboard = m_World->GetScoreBoard(); // Update scoreboard objectives - Scoreboard->ForEachObjectiveWith(cObjective::E_TYPE_DEATH_COUNT, IncrementCounter); + Scoreboard.ForEachObjectiveWith(cObjective::E_TYPE_DEATH_COUNT, IncrementCounter); } @@ -977,9 +975,16 @@ void cPlayer::SetTeam(cTeam * a_Team) cTeam * cPlayer::UpdateTeam(void) { - cScoreboard * Scoreboard = m_World->GetScoreBoard(); + if (m_World == NULL) + { + SetTeam(NULL); + } + else + { + cScoreboard & Scoreboard = m_World->GetScoreBoard(); - m_Team = Scoreboard->QueryPlayerTeam(GetName()); + SetTeam(Scoreboard.QueryPlayerTeam(GetName())); + } return m_Team; } diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h index 3293da32c..0a213f476 100644 --- a/src/Protocol/Protocol.h +++ b/src/Protocol/Protocol.h @@ -12,6 +12,7 @@ #include "../Defines.h" #include "../Endianness.h" +#include "../Scoreboard.h" @@ -92,6 +93,9 @@ public: virtual void SendRespawn (void) = 0; virtual void SendExperience (void) = 0; virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) = 0; + virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) = 0; + virtual void SendScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) = 0; + virtual void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) = 0; virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) = 0; // a_Src coords are Block * 8 virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) = 0; virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) = 0; diff --git a/src/Protocol/Protocol125.h b/src/Protocol/Protocol125.h index d0e5c9428..fb08fb120 100644 --- a/src/Protocol/Protocol125.h +++ b/src/Protocol/Protocol125.h @@ -68,6 +68,9 @@ public: virtual void SendRespawn (void) override; virtual void SendExperience (void) override; virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override; + virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override {} // This protocol doesn't support such message + virtual void SendScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) override {} // This protocol doesn't support such message + virtual void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) override {} // This protocol doesn't support such message virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) override; // a_Src coords are Block * 8 virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override; virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) override; @@ -82,8 +85,8 @@ public: virtual void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) override; virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ ) override; virtual void SendWeather (eWeather a_Weather) override; - virtual void SendWholeInventory (const cWindow & a_Window) override; - virtual void SendWindowClose (const cWindow & a_Window) override; + virtual void SendWholeInventory (const cWindow & a_Window) override; + virtual void SendWindowClose (const cWindow & a_Window) override; virtual void SendWindowOpen (const cWindow & a_Window) override; virtual void SendWindowProperty (const cWindow & a_Window, short a_Property, short a_Value) override; diff --git a/src/Protocol/Protocol15x.cpp b/src/Protocol/Protocol15x.cpp index 0f1e59f10..c33aec7d5 100644 --- a/src/Protocol/Protocol15x.cpp +++ b/src/Protocol/Protocol15x.cpp @@ -35,8 +35,11 @@ Implements the 1.5.x protocol classes: enum { - PACKET_WINDOW_OPEN = 0x64, - PACKET_PARTICLE_EFFECT = 0x3F, + PACKET_WINDOW_OPEN = 0x64, + PACKET_PARTICLE_EFFECT = 0x3F, + PACKET_SCOREBOARD_OBJECTIVE = 0x3B, + PACKET_SCORE_UPDATE = 0x3C, + PACKET_DISPLAY_OBJECTIVE = 0x3D } ; @@ -97,6 +100,53 @@ void cProtocol150::SendParticleEffect(const AString & a_ParticleName, float a_Sr +void cProtocol150::SendScoreboardObjective(const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) +{ + cCSLock Lock(m_CSPacket); + WriteByte(PACKET_SCOREBOARD_OBJECTIVE); + WriteString(a_Name); + WriteString(a_DisplayName); + WriteByte(a_Mode); + Flush(); +} + + + + + +void cProtocol150::SendScoreUpdate(const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) +{ + cCSLock Lock(m_CSPacket); + WriteByte(PACKET_SCORE_UPDATE); + WriteString(a_Player); + WriteByte(a_Mode); + + if (a_Mode != 1) + { + WriteString(a_Objective); + WriteInt((int) a_Score); + } + + Flush(); +} + + + + + +void cProtocol150::SendDisplayObjective(const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) +{ + cCSLock Lock(m_CSPacket); + WriteByte(PACKET_DISPLAY_OBJECTIVE); + WriteByte((int) a_Display); + WriteString(a_Objective); + Flush(); +} + + + + + int cProtocol150::ParseWindowClick(void) { HANDLE_PACKET_READ(ReadChar, char, WindowID); diff --git a/src/Protocol/Protocol15x.h b/src/Protocol/Protocol15x.h index 0074b3a83..0d171a67c 100644 --- a/src/Protocol/Protocol15x.h +++ b/src/Protocol/Protocol15x.h @@ -30,6 +30,9 @@ public: virtual void SendWindowOpen (const cWindow & a_Window) override; virtual void SendParticleEffect (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_ParticleAmmount) override; + virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override; + virtual void SendScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) override; + virtual void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) override; virtual int ParseWindowClick(void); } ; diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index 5b3a79555..d5ed1a0aa 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -705,6 +705,46 @@ void cProtocol172::SendExperienceOrb(const cExpOrb & a_ExpOrb) +void cProtocol172::SendScoreboardObjective(const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) +{ + cPacketizer Pkt(*this, 0x3b); + Pkt.WriteString(a_Name); + Pkt.WriteString(a_DisplayName); + Pkt.WriteByte(a_Mode); +} + + + + + +void cProtocol172::SendScoreUpdate(const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) +{ + cPacketizer Pkt(*this, 0x3c); + Pkt.WriteString(a_Player); + Pkt.WriteByte(a_Mode); + + if (a_Mode != 1) + { + Pkt.WriteString(a_Objective); + Pkt.WriteInt((int) a_Score); + } +} + + + + + +void cProtocol172::SendDisplayObjective(const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) +{ + cPacketizer Pkt(*this, 0x3d); + Pkt.WriteByte((int) a_Display); + Pkt.WriteString(a_Objective); +} + + + + + void cProtocol172::SendSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) // a_Src coords are Block * 8 { cPacketizer Pkt(*this, 0x29); // Sound Effect packet diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h index 07dba834b..bbbf820a6 100644 --- a/src/Protocol/Protocol17x.h +++ b/src/Protocol/Protocol17x.h @@ -92,6 +92,9 @@ public: virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) override; // a_Src coords are Block * 8 virtual void SendExperience (void) override; virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override; + virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override; + virtual void SendScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) override; + virtual void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) override; virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override; virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) override; virtual void SendSpawnMob (const cMonster & a_Mob) override; diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp index a21f4f042..04db2a995 100644 --- a/src/Protocol/ProtocolRecognizer.cpp +++ b/src/Protocol/ProtocolRecognizer.cpp @@ -526,6 +526,36 @@ void cProtocolRecognizer::SendExperienceOrb(const cExpOrb & a_ExpOrb) +void cProtocolRecognizer::SendScoreboardObjective(const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) +{ + ASSERT(m_Protocol != NULL); + m_Protocol->SendScoreboardObjective(a_Name, a_DisplayName, a_Mode); +} + + + + + +void cProtocolRecognizer::SendScoreUpdate(const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) +{ + ASSERT(m_Protocol != NULL); + m_Protocol->SendScoreUpdate(a_Objective, a_Player, a_Score, a_Mode); +} + + + + + +void cProtocolRecognizer::SendDisplayObjective(const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) +{ + ASSERT(m_Protocol != NULL); + m_Protocol->SendDisplayObjective(a_Objective, a_Display); +} + + + + + void cProtocolRecognizer::SendSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) { ASSERT(m_Protocol != NULL); @@ -797,7 +827,7 @@ bool cProtocolRecognizer::TryRecognizeLengthlessProtocol(void) } switch (ch) { - case PROTO_VERSION_1_3_2: + case PROTO_VERSION_1_3_2: { m_Protocol = new cProtocol132(m_Client); return true; diff --git a/src/Protocol/ProtocolRecognizer.h b/src/Protocol/ProtocolRecognizer.h index e94f4cde8..0b811f4c6 100644 --- a/src/Protocol/ProtocolRecognizer.h +++ b/src/Protocol/ProtocolRecognizer.h @@ -103,6 +103,9 @@ public: virtual void SendRespawn (void) override; virtual void SendExperience (void) override; virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override; + virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override; + virtual void SendScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) override; + virtual void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) override; virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) override; virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override; virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) override; diff --git a/src/Scoreboard.cpp b/src/Scoreboard.cpp index 3ddf146a6..7fa1eab99 100644 --- a/src/Scoreboard.cpp +++ b/src/Scoreboard.cpp @@ -6,6 +6,7 @@ #include "Globals.h" #include "Scoreboard.h" +#include "World.h" @@ -72,11 +73,13 @@ cObjective::eType cObjective::StringToType(const AString & a_Name) -cObjective::cObjective(const AString & a_Name, const AString & a_DisplayName, cObjective::eType a_Type) +cObjective::cObjective(const AString & a_Name, const AString & a_DisplayName, cObjective::eType a_Type, cWorld * a_World) : m_DisplayName(a_DisplayName) , m_Name(a_Name) , m_Type(a_Type) -{} + , m_World(a_World) +{ +} @@ -84,6 +87,11 @@ cObjective::cObjective(const AString & a_Name, const AString & a_DisplayName, cO void cObjective::Reset(void) { + for (cScoreMap::iterator it = m_Scores.begin(); it != m_Scores.end(); ++it) + { + m_World->BroadcastScoreUpdate(m_Name, it->first, 0, 1); + } + m_Scores.clear(); } @@ -112,6 +120,8 @@ cObjective::Score cObjective::GetScore(const AString & a_Name) const void cObjective::SetScore(const AString & a_Name, cObjective::Score a_Score) { m_Scores[a_Name] = a_Score; + + m_World->BroadcastScoreUpdate(m_Name, a_Name, a_Score, 0); } @@ -121,6 +131,8 @@ void cObjective::SetScore(const AString & a_Name, cObjective::Score a_Score) void cObjective::ResetScore(const AString & a_Name) { m_Scores.erase(a_Name); + + m_World->BroadcastScoreUpdate(m_Name, a_Name, 0, 1); } @@ -132,7 +144,7 @@ cObjective::Score cObjective::AddScore(const AString & a_Name, cObjective::Score // TODO 2014-01-19 xdot: Potential optimization - Reuse iterator Score NewScore = m_Scores[a_Name] + a_Delta; - m_Scores[a_Name] = NewScore; + SetScore(a_Name, NewScore); return NewScore; } @@ -146,7 +158,7 @@ cObjective::Score cObjective::SubScore(const AString & a_Name, cObjective::Score // TODO 2014-01-19 xdot: Potential optimization - Reuse iterator Score NewScore = m_Scores[a_Name] - a_Delta; - m_Scores[a_Name] = NewScore; + SetScore(a_Name, NewScore); return NewScore; } @@ -155,6 +167,17 @@ cObjective::Score cObjective::SubScore(const AString & a_Name, cObjective::Score +void cObjective::SetDisplayName(const AString & a_Name) +{ + m_DisplayName = a_Name; + + m_World->BroadcastScoreboardObjective(m_Name, m_DisplayName, 2); +} + + + + + cTeam::cTeam(const AString & a_Name, const AString & a_DisplayName, const AString & a_Prefix, const AString & a_Suffix) : m_AllowsFriendlyFire(true) @@ -215,7 +238,7 @@ unsigned int cTeam::GetNumPlayers(void) const -cScoreboard::cScoreboard() +cScoreboard::cScoreboard(cWorld * a_World) : m_World(a_World) { for (int i = 0; i < (int) E_DISPLAY_SLOT_COUNT; ++i) { @@ -229,11 +252,21 @@ cScoreboard::cScoreboard() cObjective* cScoreboard::RegisterObjective(const AString & a_Name, const AString & a_DisplayName, cObjective::eType a_Type) { - cObjective Objective(a_Name, a_DisplayName, a_Type); + cObjective Objective(a_Name, a_DisplayName, a_Type, m_World); std::pair Status = m_Objectives.insert(cNamedObjective(a_Name, Objective)); - return Status.second ? &Status.first->second : NULL; + if (Status.second) + { + ASSERT(m_World != NULL); + m_World->BroadcastScoreboardObjective(a_Name, a_DisplayName, 0); + + return &Status.first->second; + } + else + { + return NULL; + } } @@ -242,6 +275,8 @@ cObjective* cScoreboard::RegisterObjective(const AString & a_Name, const AString bool cScoreboard::RemoveObjective(const AString & a_Name) { + cCSLock Lock(m_CSObjectives); + cObjectiveMap::iterator it = m_Objectives.find(a_Name); if (it == m_Objectives.end()) @@ -251,6 +286,9 @@ bool cScoreboard::RemoveObjective(const AString & a_Name) m_Objectives.erase(it); + ASSERT(m_World != NULL); + m_World->BroadcastScoreboardObjective(it->second.GetName(), it->second.GetDisplayName(), 1); + return true; } @@ -260,6 +298,8 @@ bool cScoreboard::RemoveObjective(const AString & a_Name) cObjective * cScoreboard::GetObjective(const AString & a_Name) { + cCSLock Lock(m_CSObjectives); + cObjectiveMap::iterator it = m_Objectives.find(a_Name); if (it == m_Objectives.end()) @@ -294,6 +334,8 @@ cTeam * cScoreboard::RegisterTeam( bool cScoreboard::RemoveTeam(const AString & a_Name) { + cCSLock Lock(m_CSTeams); + cTeamMap::iterator it = m_Teams.find(a_Name); if (it == m_Teams.end()) @@ -312,6 +354,8 @@ bool cScoreboard::RemoveTeam(const AString & a_Name) cTeam * cScoreboard::GetTeam(const AString & a_Name) { + cCSLock Lock(m_CSTeams); + cTeamMap::iterator it = m_Teams.find(a_Name); if (it == m_Teams.end()) @@ -330,6 +374,8 @@ cTeam * cScoreboard::GetTeam(const AString & a_Name) cTeam * cScoreboard::QueryPlayerTeam(const AString & a_Name) { + cCSLock Lock(m_CSTeams); + for (cTeamMap::iterator it = m_Teams.begin(); it != m_Teams.end(); ++it) { if (it->second.HasPlayer(a_Name)) @@ -352,6 +398,10 @@ void cScoreboard::SetDisplay(const AString & a_Objective, eDisplaySlot a_Slot) cObjective * Objective = GetObjective(a_Objective); m_Display[a_Slot] = Objective; + + ASSERT(m_World != NULL); + m_World->BroadcastDisplayObjective(Objective ? a_Objective : "", a_Slot); + } @@ -371,6 +421,8 @@ cObjective * cScoreboard::GetObjectiveIn(eDisplaySlot a_Slot) void cScoreboard::ForEachObjectiveWith(cObjective::eType a_Type, cObjectiveCallback& a_Callback) { + cCSLock Lock(m_CSObjectives); + for (cObjectiveMap::iterator it = m_Objectives.begin(); it != m_Objectives.end(); ++it) { if (it->second.GetType() == a_Type) diff --git a/src/Scoreboard.h b/src/Scoreboard.h index 2ce614de7..b92642a9a 100644 --- a/src/Scoreboard.h +++ b/src/Scoreboard.h @@ -14,6 +14,7 @@ class cObjective; +class cWorld; typedef cItemCallback cObjectiveCallback; @@ -54,7 +55,7 @@ public: public: - cObjective(const AString & a_Name, const AString & a_DisplayName, eType a_Type); + cObjective(const AString & a_Name, const AString & a_DisplayName, eType a_Type, cWorld * a_World); eType GetType(void) const { return m_Type; } @@ -79,6 +80,8 @@ public: /// Subtracts a_Delta and returns the new score Score SubScore(const AString & a_Name, Score a_Delta); + void SetDisplayName(const AString & a_Name); + private: typedef std::pair cTrackedPlayer; @@ -92,6 +95,8 @@ private: eType m_Type; + cWorld * m_World; + friend class cScoreboardSerializer; }; @@ -180,7 +185,7 @@ public: public: - cScoreboard(); + cScoreboard(cWorld * a_World); /// Registers a new scoreboard objective, returns the cObjective instance, NULL on name collision cObjective * RegisterObjective(const AString & a_Name, const AString & a_DisplayName, cObjective::eType a_Type); @@ -223,10 +228,14 @@ private: typedef std::map cTeamMap; // TODO 2014-01-19 xdot: Potential optimization - Sort objectives based on type + cCriticalSection m_CSObjectives; cObjectiveMap m_Objectives; + cCriticalSection m_CSTeams; cTeamMap m_Teams; + cWorld * m_World; + cObjective* m_Display[E_DISPLAY_SLOT_COUNT]; friend class cScoreboardSerializer; diff --git a/src/Server.cpp b/src/Server.cpp index 5280270b9..eb76fcaeb 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -501,7 +501,7 @@ void cServer::ExecuteConsoleCommand(const AString & a_Cmd, cCommandOutputCallbac } } #endif - + if (cPluginManager::Get()->ExecuteConsoleCommand(split, a_Output)) { a_Output.Finished(); diff --git a/src/World.cpp b/src/World.cpp index 8e7b6171c..fb20e2242 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -242,7 +242,8 @@ cWorld::cWorld(const AString & a_WorldName) : m_Weather(eWeather_Sunny), m_WeatherInterval(24000), // Guaranteed 1 day of sunshine at server start :) m_GeneratorCallbacks(*this), - m_TickThread(*this) + m_TickThread(*this), + m_Scoreboard(this) { LOGD("cWorld::cWorld(\"%s\")", a_WorldName.c_str()); @@ -1982,6 +1983,60 @@ void cWorld::BroadcastRemoveEntityEffect(const cEntity & a_Entity, int a_EffectI +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 == NULL) || !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 == NULL) || !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 == NULL) || !ch->IsLoggedIn() || ch->IsDestroyed()) + { + continue; + } + ch->SendDisplayObjective(a_Objective, a_Display); + } +} + + + + + void cWorld::BroadcastSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude) { m_ChunkMap->BroadcastSoundEffect(a_SoundName, a_SrcX, a_SrcY, a_SrcZ, a_Volume, a_Pitch, a_Exclude); diff --git a/src/World.h b/src/World.h index 1dcbac8e4..51c3af8cb 100644 --- a/src/World.h +++ b/src/World.h @@ -179,6 +179,9 @@ public: 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_ParticleAmmount, cClientHandle * a_Exclude = NULL); void BroadcastPlayerListItem (const cPlayer & a_Player, bool a_IsOnline, const cClientHandle * a_Exclude = NULL); void BroadcastRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude = NULL); + 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, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude = NULL); // tolua_export a_Src coords are Block * 8 void BroadcastSoundParticleEffect(int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data, const cClientHandle * a_Exclude = NULL); // tolua_export void BroadcastSpawnEntity (cEntity & a_Entity, const cClientHandle * a_Exclude = NULL); @@ -516,7 +519,7 @@ public: const AString & GetIniFileName(void) const {return m_IniFileName; } /// Returns the associated scoreboard instance - cScoreboard* GetScoreBoard(void) { return &m_Scoreboard; } + cScoreboard & GetScoreBoard(void) { return m_Scoreboard; } // tolua_end diff --git a/src/WorldStorage/ScoreboardSerializer.h b/src/WorldStorage/ScoreboardSerializer.h index 2a4e0767e..048fa3ab4 100644 --- a/src/WorldStorage/ScoreboardSerializer.h +++ b/src/WorldStorage/ScoreboardSerializer.h @@ -24,6 +24,7 @@ class cScoreboard; class cScoreboardSerializer { public: + cScoreboardSerializer(const AString & a_WorldName, cScoreboard* a_ScoreBoard); /// Try to load the scoreboard @@ -32,6 +33,7 @@ public: /// Try to save the scoreboard bool Save(void); + private: void SaveScoreboardToNBT(cFastNBTWriter & a_Writer); @@ -41,6 +43,8 @@ private: cScoreboard* m_ScoreBoard; AString m_Path; + + } ; -- cgit v1.2.3