From f4c04299961a96e153bf50e2e1fb92c8f9db77f5 Mon Sep 17 00:00:00 2001 From: Simon Pribylski <66266021+Persson-dev@users.noreply.github.com> Date: Mon, 24 Jan 2022 21:24:55 +0100 Subject: Add player permission level (#5358) --- Server/Plugins/APIDump/APIDesc.lua | 6 +-- src/ClientHandle.cpp | 17 +++++++- src/ClientHandle.h | 1 + src/Defines.h | 5 --- src/Entities/Player.cpp | 81 ++++++++++++++++++++++---------------- src/Entities/Player.h | 10 +++-- src/Protocol/Protocol.h | 1 + src/Protocol/Protocol_1_8.cpp | 9 +++++ src/Protocol/Protocol_1_8.h | 1 + src/Protocol/Protocol_1_9.cpp | 36 +++++++++++++++++ src/Protocol/Protocol_1_9.h | 47 +++++++++++----------- 11 files changed, 143 insertions(+), 71 deletions(-) diff --git a/Server/Plugins/APIDump/APIDesc.lua b/Server/Plugins/APIDump/APIDesc.lua index a6b6a957d..531e11ac1 100644 --- a/Server/Plugins/APIDump/APIDesc.lua +++ b/Server/Plugins/APIDump/APIDesc.lua @@ -9774,7 +9774,7 @@ a_Player:OpenWindow(Window); Type = "Vector3i", }, }, - Notes = "Function to find suitable teleport destination in or below box. Returns true and places result in Destination if found, otherwise returns false. Details at: https://minecraft.fandom.com/wiki/Enderman#Teleportation.", + Notes = "Function to find suitable teleport destination in or below box. Returns true and places result in Destination if found, otherwise returns false. Details at: {{https://minecraft.fandom.com/wiki/Enderman#Teleportation}}.", }, { Params = @@ -9800,7 +9800,7 @@ a_Player:OpenWindow(Window); Type = "cBoundingBox", }, }, - Notes = "Function to find suitable teleport destination in or below box. Returns true and places result in Destination if found, otherwise returns false. Details at: https://minecraft.fandom.com/wiki/Enderman#Teleportation.", + Notes = "Function to find suitable teleport destination in or below box. Returns true and places result in Destination if found, otherwise returns false. Details at: {{https://minecraft.fandom.com/wiki/Enderman#Teleportation}}.", }, { Params = @@ -9826,7 +9826,7 @@ a_Player:OpenWindow(Window); Type = "number", }, }, - Notes = "Function to find suitable teleport destination in or below box. Returns true and places result in Destination if found, otherwise returns false. Details at: https://minecraft.fandom.com/wiki/Enderman#Teleportation.", + Notes = "Function to find suitable teleport destination in or below box. Returns true and places result in Destination if found, otherwise returns false. Details at: {{https://minecraft.fandom.com/wiki/Enderman#Teleportation}}.", }, }, HasEntityEffect = diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index c2135777b..cd7de10dc 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -459,6 +459,10 @@ void cClientHandle::FinishAuthenticate() // Return a server login packet: m_Protocol->SendLogin(*m_Player, *World); + // Send the player's permission level. + // The key effect is to allow 1.9+ clients to open the command block UI. + SendPlayerPermissionLevel(); + if (m_Player->GetKnownRecipes().empty()) { SendInitRecipes(0); @@ -1042,7 +1046,7 @@ void cClientHandle::HandleCommandBlockBlockChange(int a_BlockX, int a_BlockY, in return; } - if ((m_Player == nullptr) || !m_Player->HasPermission("comandblock.set")) + if ((m_Player == nullptr) || !m_Player->HasPermission("cuberite.commandblock.set")) { SendChat("You cannot edit command blocks on this server", mtFailure); return; @@ -1589,7 +1593,7 @@ void cClientHandle::HandleChat(const AString & a_Message) Msg.AddTextPart(m_Player->GetName(), Color); Msg.ParseText(m_Player->GetSuffix()); Msg.AddTextPart("> "); - if (m_Player->HasPermission("chat.format")) + if (m_Player->HasPermission("cuberite.chat.format")) { Msg.ParseText(Message); } @@ -2880,6 +2884,15 @@ void cClientHandle::SendPlayerMoveLook(void) +void cClientHandle::SendPlayerPermissionLevel() +{ + m_Protocol->SendPlayerPermissionLevel(); +} + + + + + void cClientHandle::SendPlayerPosition(void) { m_Protocol->SendPlayerPosition(); diff --git a/src/ClientHandle.h b/src/ClientHandle.h index cd07f502d..612883e46 100644 --- a/src/ClientHandle.h +++ b/src/ClientHandle.h @@ -205,6 +205,7 @@ public: // tolua_export void SendPlayerListUpdateGameMode (const cPlayer & a_Player); void SendPlayerListUpdatePing (); void SendPlayerMoveLook (void); + void SendPlayerPermissionLevel (void); void SendPlayerPosition (void); void SendPlayerSpawn (const cPlayer & a_Player); void SendPluginMessage (const AString & a_Channel, std::string_view a_Message); // Exported in ManualBindings.cpp diff --git a/src/Defines.h b/src/Defines.h index 899bc8c2d..82b85e3c4 100644 --- a/src/Defines.h +++ b/src/Defines.h @@ -503,11 +503,6 @@ enum class EntityAnimation PlayerMainHandSwings, // PlayerReducedDebugScreenDisables, // PlayerReducedDebugScreenEnables, - // PlayerSetsOperatorLevelFour, - // PlayerSetsOperatorLevelOne, - // PlayerSetsOperatorLevelThree, - // PlayerSetsOperatorLevelTwo, - // PlayerSetsOperatorLevelZero, PlayerOffHandSwings, RabbitJumps, RavagerAttacks, diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index de4acc806..30650a6d0 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -1567,7 +1567,7 @@ void cPlayer::PermuteEnchantmentSeed() -bool cPlayer::HasPermission(const AString & a_Permission) +bool cPlayer::HasPermission(const AString & a_Permission) const { if (a_Permission.empty()) { @@ -1786,7 +1786,7 @@ void cPlayer::TossPickup(const cItem & a_Item) void cPlayer::LoadFromDisk() { - LoadRank(); + RefreshRank(); Json::Value Root; const auto & UUID = GetUUID(); @@ -2295,39 +2295,11 @@ void cPlayer::UpdateMovementStats(const Vector3d & a_DeltaPos, bool a_PreviousIs void cPlayer::LoadRank(void) { - const auto & UUID = GetUUID(); - cRankManager * RankMgr = cRoot::Get()->GetRankManager(); - - // Load the values from cRankManager: - m_Rank = RankMgr->GetPlayerRankName(UUID); - if (m_Rank.empty()) - { - m_Rank = RankMgr->GetDefaultRank(); - } - else - { - // Update the name: - RankMgr->UpdatePlayerName(UUID, GetName()); - } - m_Permissions = RankMgr->GetPlayerPermissions(UUID); - m_Restrictions = RankMgr->GetPlayerRestrictions(UUID); - RankMgr->GetRankVisuals(m_Rank, m_MsgPrefix, m_MsgSuffix, m_MsgNameColorCode); + // Update our permissions: + RefreshRank(); - // Break up the individual permissions on each dot, into m_SplitPermissions: - m_SplitPermissions.clear(); - m_SplitPermissions.reserve(m_Permissions.size()); - for (auto & Permission: m_Permissions) - { - m_SplitPermissions.push_back(StringSplit(Permission, ".")); - } // for Permission - m_Permissions[] - - // Break up the individual restrictions on each dot, into m_SplitRestrictions: - m_SplitRestrictions.clear(); - m_SplitRestrictions.reserve(m_Restrictions.size()); - for (auto & Restriction: m_Restrictions) - { - m_SplitRestrictions.push_back(StringSplit(Restriction, ".")); - } // for itr - m_Restrictions[] + // Send a permission level update: + m_ClientHandle->SendPlayerPermissionLevel(); } @@ -2808,6 +2780,47 @@ void cPlayer::TickFreezeCode() +void cPlayer::RefreshRank() +{ + const auto & UUID = GetUUID(); + cRankManager * RankMgr = cRoot::Get()->GetRankManager(); + + // Load the values from cRankManager: + m_Rank = RankMgr->GetPlayerRankName(UUID); + if (m_Rank.empty()) + { + m_Rank = RankMgr->GetDefaultRank(); + } + else + { + // Update the name: + RankMgr->UpdatePlayerName(UUID, GetName()); + } + m_Permissions = RankMgr->GetPlayerPermissions(UUID); + m_Restrictions = RankMgr->GetPlayerRestrictions(UUID); + RankMgr->GetRankVisuals(m_Rank, m_MsgPrefix, m_MsgSuffix, m_MsgNameColorCode); + + // Break up the individual permissions on each dot, into m_SplitPermissions: + m_SplitPermissions.clear(); + m_SplitPermissions.reserve(m_Permissions.size()); + for (auto & Permission : m_Permissions) + { + m_SplitPermissions.push_back(StringSplit(Permission, ".")); + } + + // Break up the individual restrictions on each dot, into m_SplitRestrictions: + m_SplitRestrictions.clear(); + m_SplitRestrictions.reserve(m_Restrictions.size()); + for (auto & Restriction : m_Restrictions) + { + m_SplitRestrictions.push_back(StringSplit(Restriction, ".")); + } +} + + + + + void cPlayer::ApplyArmorDamage(int a_DamageBlocked) { short ArmorDamage = static_cast(std::max(a_DamageBlocked / 4, 1)); diff --git a/src/Entities/Player.h b/src/Entities/Player.h index 87eaad2fe..e0a88814d 100644 --- a/src/Entities/Player.h +++ b/src/Entities/Player.h @@ -301,7 +301,7 @@ public: // tolua_end - bool HasPermission(const AString & a_Permission); // tolua_export + bool HasPermission(const AString & a_Permission) const; // tolua_export /** Returns true iff a_Permission matches the a_Template. A match is defined by either being exactly the same, or each sub-item matches until there's a wildcard in a_Template. @@ -545,8 +545,7 @@ public: /** Returns wheter the player can fly or not. */ virtual bool CanFly(void) const { return m_IsFlightCapable; } - /** (Re)loads the rank and permissions from the cRankManager. - Loads the m_Rank, m_Permissions, m_MsgPrefix, m_MsgSuffix and m_MsgNameColorCode members. */ + /** (Re)loads the rank and permissions from the cRankManager and sends a permission level update to the client. */ void LoadRank(void); /** Sends the block in the specified range around the specified coord to the client @@ -626,7 +625,6 @@ private: This is used mainly by the HasPermission() function to optimize the lookup. */ AStringVectorVector m_SplitRestrictions; - // Message visuals: AString m_MsgPrefix, m_MsgSuffix; AString m_MsgNameColorCode; @@ -787,6 +785,10 @@ private: void TickFreezeCode(); + /** (Re)loads the rank and permissions from the cRankManager. + Loads the m_Rank, m_Permissions, m_MsgPrefix, m_MsgSuffix and m_MsgNameColorCode members. */ + void RefreshRank(); + // cEntity overrides: virtual void ApplyArmorDamage(int DamageBlocked) override; virtual void BroadcastMovementUpdate(const cClientHandle * a_Exclude = nullptr) override; diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h index f306abc1c..4acc0546a 100644 --- a/src/Protocol/Protocol.h +++ b/src/Protocol/Protocol.h @@ -408,6 +408,7 @@ public: virtual void SendPlayerListUpdatePing () = 0; virtual void SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName) = 0; virtual void SendPlayerMoveLook (void) = 0; + virtual void SendPlayerPermissionLevel (void) = 0; virtual void SendPlayerPosition (void) = 0; virtual void SendPlayerSpawn (const cPlayer & a_Player) = 0; virtual void SendPluginMessage (const AString & a_Channel, ContiguousByteBufferView a_Message) = 0; diff --git a/src/Protocol/Protocol_1_8.cpp b/src/Protocol/Protocol_1_8.cpp index 1308f1826..69fe40b9b 100644 --- a/src/Protocol/Protocol_1_8.cpp +++ b/src/Protocol/Protocol_1_8.cpp @@ -1184,6 +1184,15 @@ void cProtocol_1_8_0::SendPlayerMoveLook(void) +void cProtocol_1_8_0::SendPlayerPermissionLevel() +{ + // 1.8 has no concept of a permission level. +} + + + + + void cProtocol_1_8_0::SendPlayerPosition(void) { // There is no dedicated packet for this, send the whole thing: diff --git a/src/Protocol/Protocol_1_8.h b/src/Protocol/Protocol_1_8.h index 7365cd2db..6ee1fdcaf 100644 --- a/src/Protocol/Protocol_1_8.h +++ b/src/Protocol/Protocol_1_8.h @@ -94,6 +94,7 @@ public: virtual void SendPlayerListUpdateGameMode (const cPlayer & a_Player) override; virtual void SendPlayerListUpdatePing () override; virtual void SendPlayerMoveLook (void) override; + virtual void SendPlayerPermissionLevel (void) override; virtual void SendPlayerPosition (void) override; virtual void SendPlayerSpawn (const cPlayer & a_Player) override; virtual void SendPluginMessage (const AString & a_Channel, ContiguousByteBufferView a_Message) override; diff --git a/src/Protocol/Protocol_1_9.cpp b/src/Protocol/Protocol_1_9.cpp index 587b01f0d..ad304b4ac 100644 --- a/src/Protocol/Protocol_1_9.cpp +++ b/src/Protocol/Protocol_1_9.cpp @@ -501,6 +501,42 @@ void cProtocol_1_9_0::SendPlayerMoveLook(void) +void cProtocol_1_9_0::SendPlayerPermissionLevel() +{ + const cPlayer & Player = *m_Client->GetPlayer(); + + cPacketizer Pkt(*this, pktEntityStatus); + Pkt.WriteBEUInt32(Player.GetUniqueID()); + Pkt.WriteBEInt8([&Player]() -> signed char + { + if (Player.HasPermission("core.stop") || Player.HasPermission("core.reload") || Player.HasPermission("core.save-all")) + { + return 28; + } + + if (Player.HasPermission("core.ban") || Player.HasPermission("core.deop") || Player.HasPermission("core.kick") || Player.HasPermission("core.op")) + { + return 27; + } + + if (Player.HasPermission("cuberite.comandblock.set") || Player.HasPermission("core.clear") || Player.HasPermission("core.difficulty") || Player.HasPermission("core.effect") || Player.HasPermission("core.gamemode") || Player.HasPermission("core.tp") || Player.HasPermission("core.give")) + { + return 26; + } + + if (Player.HasPermission("core.spawnprotect.bypass")) + { + return 25; + } + + return 24; + }()); +} + + + + + void cProtocol_1_9_0::SendPlayerSpawn(const cPlayer & a_Player) { // Called to spawn another player for the client diff --git a/src/Protocol/Protocol_1_9.h b/src/Protocol/Protocol_1_9.h index 9766646e0..6dfa51811 100644 --- a/src/Protocol/Protocol_1_9.h +++ b/src/Protocol/Protocol_1_9.h @@ -35,29 +35,30 @@ public: cProtocol_1_9_0(cClientHandle * a_Client, const AString & a_ServerAddress, State a_State); - virtual void SendAttachEntity (const cEntity & a_Entity, const cEntity & a_Vehicle) override; - virtual void SendBossBarAdd (UInt32 a_UniqueID, const cCompositeChat & a_Title, float a_FractionFilled, BossBarColor a_Color, BossBarDivisionType a_DivisionType, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog) override; - virtual void SendBossBarRemove (UInt32 a_UniqueID) override; - virtual void SendBossBarUpdateFlags (UInt32 a_UniqueID, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog) override; - virtual void SendBossBarUpdateHealth(UInt32 a_UniqueID, float a_FractionFilled) override; - virtual void SendBossBarUpdateStyle (UInt32 a_UniqueID, BossBarColor a_Color, BossBarDivisionType a_DivisionType) override; - virtual void SendBossBarUpdateTitle (UInt32 a_UniqueID, const cCompositeChat & a_Title) override; - virtual void SendDetachEntity (const cEntity & a_Entity, const cEntity & a_PreviousVehicle) override; - virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override; - virtual void SendEntityMetadata (const cEntity & a_Entity) override; - virtual void SendEntityPosition (const cEntity & a_Entity) override; - virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override; - virtual void SendKeepAlive (UInt32 a_PingID) override; - virtual void SendLeashEntity (const cEntity & a_Entity, const cEntity & a_EntityLeashedTo) override; - virtual void SendMapData (const cMap & a_Map, int a_DataStartX, int a_DataStartY) override; - virtual void SendPaintingSpawn (const cPainting & a_Painting) override; - virtual void SendPlayerMoveLook (void) override; - virtual void SendPlayerSpawn (const cPlayer & a_Player) override; - virtual void SendSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch) override; - virtual void SendSpawnMob (const cMonster & a_Mob) override; - virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) override; - virtual void SendUnleashEntity (const cEntity & a_Entity) override; - virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) override; + virtual void SendAttachEntity (const cEntity & a_Entity, const cEntity & a_Vehicle) override; + virtual void SendBossBarAdd (UInt32 a_UniqueID, const cCompositeChat & a_Title, float a_FractionFilled, BossBarColor a_Color, BossBarDivisionType a_DivisionType, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog) override; + virtual void SendBossBarRemove (UInt32 a_UniqueID) override; + virtual void SendBossBarUpdateFlags (UInt32 a_UniqueID, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog) override; + virtual void SendBossBarUpdateHealth (UInt32 a_UniqueID, float a_FractionFilled) override; + virtual void SendBossBarUpdateStyle (UInt32 a_UniqueID, BossBarColor a_Color, BossBarDivisionType a_DivisionType) override; + virtual void SendBossBarUpdateTitle (UInt32 a_UniqueID, const cCompositeChat & a_Title) override; + virtual void SendDetachEntity (const cEntity & a_Entity, const cEntity & a_PreviousVehicle) override; + virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override; + virtual void SendEntityMetadata (const cEntity & a_Entity) override; + virtual void SendEntityPosition (const cEntity & a_Entity) override; + virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override; + virtual void SendKeepAlive (UInt32 a_PingID) override; + virtual void SendLeashEntity (const cEntity & a_Entity, const cEntity & a_EntityLeashedTo) override; + virtual void SendMapData (const cMap & a_Map, int a_DataStartX, int a_DataStartY) override; + virtual void SendPaintingSpawn (const cPainting & a_Painting) override; + virtual void SendPlayerMoveLook (void) override; + virtual void SendPlayerPermissionLevel() override; + virtual void SendPlayerSpawn (const cPlayer & a_Player) override; + virtual void SendSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch) override; + virtual void SendSpawnMob (const cMonster & a_Mob) override; + virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) override; + virtual void SendUnleashEntity (const cEntity & a_Entity) override; + virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) override; protected: -- cgit v1.2.3