diff options
Diffstat (limited to 'src/Entities')
-rw-r--r-- | src/Entities/Minecart.cpp | 94 | ||||
-rw-r--r-- | src/Entities/Player.cpp | 262 | ||||
-rw-r--r-- | src/Entities/Player.h | 54 |
3 files changed, 181 insertions, 229 deletions
diff --git a/src/Entities/Minecart.cpp b/src/Entities/Minecart.cpp index d4eadc5d5..21c58fdba 100644 --- a/src/Entities/Minecart.cpp +++ b/src/Entities/Minecart.cpp @@ -871,11 +871,101 @@ bool cMinecart::TestEntityCollision(NIBBLETYPE a_RailMeta) return true; } case E_META_RAIL_CURVED_ZM_XM: + case E_META_RAIL_CURVED_ZP_XP: + { + Vector3d Distance = MinecartCollisionCallback.GetCollidedEntityPosition() - Vector3d(GetPosX(), 0, GetPosZ()); + + // Prevent division by small numbers + if (abs(Distance.z) < 0.001) + { + Distance.z = 0.001; + } + + /* Check to which side the minecart is to be pushed. + Let's consider a z-x-coordinate system where the minecart is the center (0/0). + The minecart moves along the line x = -z, the perpendicular line to this is x = z. + In order to decide to which side the minecart is to be pushed, it must be checked on what side of the perpendicular line the pushing entity is located. */ + if ( + ((Distance.z > 0) && ((Distance.x / Distance.z) >= 1)) || + ((Distance.z < 0) && ((Distance.x / Distance.z) <= 1)) + ) + { + // Moving -X +Z + if ((-GetSpeedX() * 0.4 / sqrt(2)) < 0.01) + { + // ~ SpeedX >= 0 Immobile or not moving in the "right" direction. Give it a bump! + AddSpeedX(-4 / sqrt(2)); + AddSpeedZ(4 / sqrt(2)); + } + else + { + // ~ SpeedX < 0 Moving in the "right" direction. Only accelerate it a bit. + SetSpeedX(GetSpeedX() * 0.4 / sqrt(2)); + SetSpeedZ(GetSpeedZ() * 0.4 / sqrt(2)); + } + } + else if ((GetSpeedX() * 0.4 / sqrt(2)) < 0.01) + { + // Moving +X -Z + // ~ SpeedX <= 0 Immobile or not moving in the "right" direction + AddSpeedX(4 / sqrt(2)); + AddSpeedZ(-4 / sqrt(2)); + } + else + { + // ~ SpeedX > 0 Moving in the "right" direction + SetSpeedX(GetSpeedX() * 0.4 / sqrt(2)); + SetSpeedZ(GetSpeedZ() * 0.4 / sqrt(2)); + } + break; + } case E_META_RAIL_CURVED_ZM_XP: case E_META_RAIL_CURVED_ZP_XM: - case E_META_RAIL_CURVED_ZP_XP: { - // TODO - simply can't be bothered right now + Vector3d Distance = MinecartCollisionCallback.GetCollidedEntityPosition() - Vector3d(GetPosX(), 0, GetPosZ()); + + // Prevent division by small numbers + if (abs(Distance.z) < 0.001) + { + Distance.z = 0.001; + } + + /* Check to which side the minecart is to be pushed. + Let's consider a z-x-coordinate system where the minecart is the center (0/0). + The minecart moves along the line x = z, the perpendicular line to this is x = -z. + In order to decide to which side the minecart is to be pushed, it must be checked on what side of the perpendicular line the pushing entity is located. */ + if ( + ((Distance.z > 0) && ((Distance.x / Distance.z) <= -1)) || + ((Distance.z < 0) && ((Distance.x / Distance.z) >= -1)) + ) + { + // Moving +X +Z + if ((GetSpeedX() * 0.4) < 0.01) + { + // ~ SpeedX <= 0 Immobile or not moving in the "right" direction + AddSpeedX(4 / sqrt(2)); + AddSpeedZ(4 / sqrt(2)); + } + else + { + // ~ SpeedX > 0 Moving in the "right" direction + SetSpeedX(GetSpeedX() * 0.4 / sqrt(2)); + SetSpeedZ(GetSpeedZ() * 0.4 / sqrt(2)); + } + } + else if ((-GetSpeedX() * 0.4) < 0.01) + { + // Moving -X -Z + // ~ SpeedX >= 0 Immobile or not moving in the "right" direction + AddSpeedX(-4 / sqrt(2)); + AddSpeedZ(-4 / sqrt(2)); + } + else + { + // ~ SpeedX < 0 Moving in the "right" direction + SetSpeedX(GetSpeedX() * 0.4 / sqrt(2)); + SetSpeedZ(GetSpeedZ() * 0.4 / sqrt(2)); + } break; } default: break; diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 32290885d..b0dd40615 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -10,8 +10,6 @@ #include "../Bindings/PluginManager.h" #include "../BlockEntities/BlockEntity.h" #include "../BlockEntities/EnderChestEntity.h" -#include "../GroupManager.h" -#include "../Group.h" #include "../Root.h" #include "../OSSupport/Timer.h" #include "../Chunk.h" @@ -59,7 +57,6 @@ cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName) : m_EnderChestContents(9, 3), m_CurrentWindow(NULL), m_InventoryWindow(NULL), - m_Color('-'), m_GameMode(eGameMode_NotSet), m_IP(""), m_ClientHandle(a_Client), @@ -1367,48 +1364,6 @@ void cPlayer::SetVisible(bool a_bVisible) -void cPlayer::AddToGroup( const AString & a_GroupName) -{ - cGroup* Group = cRoot::Get()->GetGroupManager()->GetGroup( a_GroupName); - m_Groups.push_back( Group); - LOGD("Added %s to group %s", GetName().c_str(), a_GroupName.c_str()); - ResolveGroups(); - ResolvePermissions(); -} - - - - - -void cPlayer::RemoveFromGroup( const AString & a_GroupName) -{ - bool bRemoved = false; - for (GroupList::iterator itr = m_Groups.begin(); itr != m_Groups.end(); ++itr) - { - if ((*itr)->GetName().compare(a_GroupName) == 0) - { - m_Groups.erase( itr); - bRemoved = true; - break; - } - } - - if (bRemoved) - { - LOGD("Removed %s from group %s", GetName().c_str(), a_GroupName.c_str()); - ResolveGroups(); - ResolvePermissions(); - } - else - { - LOGWARN("Tried to remove %s from group %s but was not in that group", GetName().c_str(), a_GroupName.c_str()); - } -} - - - - - bool cPlayer::HasPermission(const AString & a_Permission) { if (a_Permission.empty()) @@ -1417,33 +1372,18 @@ bool cPlayer::HasPermission(const AString & a_Permission) return true; } - AStringVector Split = StringSplit( a_Permission, "."); - PermissionMap Possibilities = m_ResolvedPermissions; - // Now search the namespaces - while (Possibilities.begin() != Possibilities.end()) + AStringVector Split = StringSplit(a_Permission, "."); + + // Iterate over all granted permissions; if any matches, then return success: + for (AStringVectorVector::const_iterator itr = m_SplitPermissions.begin(), end = m_SplitPermissions.end(); itr != end; ++itr) { - PermissionMap::iterator itr = Possibilities.begin(); - if (itr->second) + if (PermissionMatches(Split, *itr)) { - AStringVector OtherSplit = StringSplit( itr->first, "."); - if (OtherSplit.size() <= Split.size()) - { - unsigned int i; - for (i = 0; i < OtherSplit.size(); ++i) - { - if (OtherSplit[i].compare( Split[i]) != 0) - { - if (OtherSplit[i].compare("*") == 0) return true; // WildCard man!! WildCard! - break; - } - } - if (i == Split.size()) return true; - } + return true; } - Possibilities.erase( itr); - } + } // for itr - m_SplitPermissions[] - // Nothing that matched :( + // No granted permission matches return false; } @@ -1451,82 +1391,35 @@ bool cPlayer::HasPermission(const AString & a_Permission) -bool cPlayer::IsInGroup( const AString & a_Group) +bool cPlayer::PermissionMatches(const AStringVector & a_Permission, const AStringVector & a_Template) { - for (GroupList::iterator itr = m_ResolvedGroups.begin(); itr != m_ResolvedGroups.end(); ++itr) + // Check the sub-items if they are the same or there's a wildcard: + size_t lenP = a_Permission.size(); + size_t lenT = a_Template.size(); + size_t minLen = std::min(lenP, lenT); + for (size_t i = 0; i < minLen; i++) { - if (a_Group.compare( (*itr)->GetName().c_str()) == 0) + if (a_Template[i] == "*") + { + // Has matched so far and now there's a wildcard in the template, so the permission matches: return true; - } - return false; -} - - - - - -void cPlayer::ResolvePermissions() -{ - m_ResolvedPermissions.clear(); // Start with an empty map - - // Copy all player specific permissions into the resolved permissions map - for (PermissionMap::iterator itr = m_Permissions.begin(); itr != m_Permissions.end(); ++itr) - { - m_ResolvedPermissions[ itr->first ] = itr->second; - } - - for (GroupList::iterator GroupItr = m_ResolvedGroups.begin(); GroupItr != m_ResolvedGroups.end(); ++GroupItr) - { - const cGroup::PermissionMap & Permissions = (*GroupItr)->GetPermissions(); - for (cGroup::PermissionMap::const_iterator itr = Permissions.begin(); itr != Permissions.end(); ++itr) + } + if (a_Permission[i] != a_Template[i]) { - m_ResolvedPermissions[ itr->first ] = itr->second; + // Found a mismatch + return false; } } -} - - - - -void cPlayer::ResolveGroups() -{ - // Clear resolved groups first - m_ResolvedGroups.clear(); - - // Get a complete resolved list of all groups the player is in - std::map< cGroup*, bool > AllGroups; // Use a map, because it's faster than iterating through a list to find duplicates - GroupList ToIterate; - for (GroupList::iterator GroupItr = m_Groups.begin(); GroupItr != m_Groups.end(); ++GroupItr) + // So far all the sub-items have matched + // If the sub-item count is the same, then the permission matches: + if (lenP == lenT) { - ToIterate.push_back( *GroupItr); - } - while (ToIterate.begin() != ToIterate.end()) - { - cGroup* CurrentGroup = *ToIterate.begin(); - if (AllGroups.find( CurrentGroup) != AllGroups.end()) - { - LOGWARNING("ERROR: Player \"%s\" is in the group multiple times (\"%s\"). Please fix your settings in users.ini!", - GetName().c_str(), CurrentGroup->GetName().c_str() - ); - } - else - { - AllGroups[ CurrentGroup ] = true; - m_ResolvedGroups.push_back( CurrentGroup); // Add group to resolved list - const cGroup::GroupList & Inherits = CurrentGroup->GetInherits(); - for (cGroup::GroupList::const_iterator itr = Inherits.begin(); itr != Inherits.end(); ++itr) - { - if (AllGroups.find( *itr) != AllGroups.end()) - { - LOGERROR("ERROR: Player %s is in the same group multiple times due to inheritance (%s). FIX IT!", GetName().c_str(), (*itr)->GetName().c_str()); - continue; - } - ToIterate.push_back( *itr); - } - } - ToIterate.erase( ToIterate.begin()); + return true; } + + // There are more sub-items in either the permission or the template, not a match: + return false; } @@ -1535,17 +1428,14 @@ void cPlayer::ResolveGroups() AString cPlayer::GetColor(void) const { - if (m_Color != '-') + if (m_MsgNameColorCode.empty() || (m_MsgNameColorCode == "-")) { - return cChatColor::Delimiter + m_Color; + // Color has not been assigned, return an empty string: + return AString(); } - if (m_Groups.size() < 1) - { - return cChatColor::White; - } - - return (*m_Groups.begin())->GetColor(); + // Return the color, including the delimiter: + return cChatColor::Delimiter + m_MsgNameColorCode; } @@ -1661,48 +1551,9 @@ bool cPlayer::DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn) -void cPlayer::LoadPermissionsFromDisk() -{ - m_Groups.clear(); - m_Permissions.clear(); - - cIniFile IniFile; - if (IniFile.ReadFile("users.ini")) - { - AString Groups = IniFile.GetValueSet(GetName(), "Groups", "Default"); - AStringVector Split = StringSplitAndTrim(Groups, ","); - - for (AStringVector::const_iterator itr = Split.begin(), end = Split.end(); itr != end; ++itr) - { - if (!cRoot::Get()->GetGroupManager()->ExistsGroup(*itr)) - { - LOGWARNING("The group %s for player %s was not found!", itr->c_str(), GetName().c_str()); - } - AddToGroup(*itr); - } - - AString Color = IniFile.GetValue(GetName(), "Color", "-"); - if (!Color.empty()) - { - m_Color = Color[0]; - } - } - else - { - cGroupManager::GenerateDefaultUsersIni(IniFile); - IniFile.AddValue("Groups", GetName(), "Default"); - AddToGroup("Default"); - } - IniFile.WriteFile("users.ini"); - ResolvePermissions(); -} - - - - bool cPlayer::LoadFromDisk(cWorldPtr & a_World) { - LoadPermissionsFromDisk(); + LoadRank(); // Load from the UUID file: if (LoadFromFile(GetUUIDFileName(m_UUID), a_World)) @@ -1937,26 +1788,6 @@ bool cPlayer::SaveToDisk() -cPlayer::StringList cPlayer::GetResolvedPermissions() -{ - StringList Permissions; - - const PermissionMap& ResolvedPermissions = m_ResolvedPermissions; - for (PermissionMap::const_iterator itr = ResolvedPermissions.begin(); itr != ResolvedPermissions.end(); ++itr) - { - if (itr->second) - { - Permissions.push_back( itr->first); - } - } - - return Permissions; -} - - - - - void cPlayer::UseEquippedItem(int a_Amount) { if (IsGameModeCreative()) // No damage in creative @@ -2215,6 +2046,31 @@ void cPlayer::ApplyFoodExhaustionFromMovement() +void cPlayer::LoadRank(void) +{ + // Load the values from cRankManager: + cRankManager & RankMgr = cRoot::Get()->GetRankManager(); + m_Rank = RankMgr.GetPlayerRankName(m_UUID); + if (m_Rank.empty()) + { + m_Rank = RankMgr.GetDefaultRank(); + } + m_Permissions = RankMgr.GetPlayerPermissions(m_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 (AStringVector::const_iterator itr = m_Permissions.begin(), end = m_Permissions.end(); itr != end; ++itr) + { + m_SplitPermissions.push_back(StringSplit(*itr, ".")); + } // for itr - m_Permissions[] +} + + + + + void cPlayer::Detach() { super::Detach(); diff --git a/src/Entities/Player.h b/src/Entities/Player.h index d3ed1ef9d..9821cc6d9 100644 --- a/src/Entities/Player.h +++ b/src/Entities/Player.h @@ -13,7 +13,6 @@ -class cGroup; class cWindow; class cClientHandle; class cTeam; @@ -236,24 +235,20 @@ public: // tolua_end - typedef std::list< cGroup* > GroupList; - typedef std::list< std::string > StringList; + bool HasPermission(const AString & a_Permission); // tolua_export - /** Adds a player to existing group or creates a new group when it doesn't exist */ - void AddToGroup( const AString & a_GroupName); // tolua_export - - /** Removes a player from the group, resolves permissions and group inheritance (case sensitive) */ - void RemoveFromGroup( const AString & a_GroupName); // tolua_export - - bool HasPermission( const AString & a_Permission); // tolua_export - const GroupList & GetGroups() { return m_Groups; } // >> EXPORTED IN MANUALBINDINGS << - StringList GetResolvedPermissions(); // >> EXPORTED IN MANUALBINDINGS << - bool IsInGroup( const AString & a_Group); // 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. + Ie. {"a", "b", "c"} matches {"a", "b", "*"} but doesn't match {"a", "b"} */ + static bool PermissionMatches(const AStringVector & a_Permission, const AStringVector & a_Template); // Exported in ManualBindings with AString params + + /** Returns all the permissions that the player has assigned to them. */ + const AStringVector & GetPermissions(void) { return m_Permissions; } // Exported in ManualBindings.cpp // tolua_begin - /** Returns the full color code to use for this player, based on their primary group or set in m_Color. - The returned value includes the cChatColor::Delimiter. */ + /** Returns the full color code to use for this player, based on their rank. + The returned value either is empty, or includes the cChatColor::Delimiter. */ AString GetColor(void) const; /** tosses the item in the selected hotbar slot */ @@ -347,8 +342,6 @@ public: */ bool LoadFromFile(const AString & a_FileName, cWorldPtr & a_World); - void LoadPermissionsFromDisk(void); // tolua_export - const AString & GetLoadedWorldName() { return m_LoadedWorldName; } void UseEquippedItem(int a_Amount = 1); @@ -422,6 +415,11 @@ public: /** Returns the UUID (short format) that has been read from the client, or empty string if not available. */ const AString & GetUUID(void) const { return m_UUID; } + /** (Re)loads the rank and permissions from the cRankManager. + Expects the m_UUID member to be valid. + Loads the m_Rank, m_Permissions, m_MsgPrefix, m_MsgSuffix and m_MsgNameColorCode members. */ + void LoadRank(void); + // tolua_end // cEntity overrides: @@ -432,12 +430,22 @@ public: virtual void Detach(void); protected: - typedef std::map< std::string, bool > PermissionMap; - PermissionMap m_ResolvedPermissions; - PermissionMap m_Permissions; - GroupList m_ResolvedGroups; - GroupList m_Groups; + typedef std::vector<std::vector<AString> > AStringVectorVector; + + /** The name of the rank assigned to this player. */ + AString m_Rank; + + /** All the permissions that this player has, based on their rank. */ + AStringVector m_Permissions; + + /** All the permissions that this player has, based on their rank, split into individual dot-delimited parts. + This is used mainly by the HasPermission() function to optimize the lookup. */ + AStringVectorVector m_SplitPermissions; + + // Message visuals: + AString m_MsgPrefix, m_MsgSuffix; + AString m_MsgNameColorCode; AString m_PlayerName; AString m_LoadedWorldName; @@ -482,8 +490,6 @@ protected: /** The player's last saved bed position */ Vector3i m_LastBedPos; - char m_Color; - eGameMode m_GameMode; AString m_IP; |