1
0

Merge pull request #1013 from mc-server/achievementtranslate

Proper achievement informing
This commit is contained in:
Mattes D 2014-05-25 10:42:30 +02:00
commit 0849e66d03
6 changed files with 109 additions and 32 deletions

View File

@ -80,9 +80,9 @@ public:
static AString GenerateOfflineUUID(const AString & a_Username); // tolua_export static AString GenerateOfflineUUID(const AString & a_Username); // tolua_export
/** Formats the type of message with the proper color and prefix for sending to the client. **/ /** Formats the type of message with the proper color and prefix for sending to the client. **/
AString FormatMessageType(bool ShouldAppendChatPrefixes, eMessageType a_ChatPrefix, const AString & a_AdditionalData); static AString FormatMessageType(bool ShouldAppendChatPrefixes, eMessageType a_ChatPrefix, const AString & a_AdditionalData);
AString FormatChatPrefix(bool ShouldAppendChatPrefixes, AString a_ChatPrefixS, AString m_Color1, AString m_Color2); static AString FormatChatPrefix(bool ShouldAppendChatPrefixes, AString a_ChatPrefixS, AString m_Color1, AString m_Color2);
void Kick(const AString & a_Reason); // tolua_export void Kick(const AString & a_Reason); // tolua_export
void Authenticate(const AString & a_Name, const AString & a_UUID); // Called by cAuthenticator when the user passes authentication void Authenticate(const AString & a_Name, const AString & a_UUID); // Called by cAuthenticator when the user passes authentication

View File

@ -189,6 +189,15 @@ void cCompositeChat::AddSuggestCommandPart(const AString & a_Text, const AString
void cCompositeChat::AddShowAchievementPart(const AString & a_PlayerName, const AString & a_Achievement, const AString & a_Style)
{
m_Parts.push_back(new cShowAchievementPart(a_PlayerName, a_Achievement, a_Style));
}
void cCompositeChat::ParseText(const AString & a_ParseText) void cCompositeChat::ParseText(const AString & a_ParseText)
{ {
size_t len = a_ParseText.length(); size_t len = a_ParseText.length();
@ -290,9 +299,10 @@ void cCompositeChat::ParseText(const AString & a_ParseText)
void cCompositeChat::SetMessageType(eMessageType a_MessageType) void cCompositeChat::SetMessageType(eMessageType a_MessageType, const AString & a_AdditionalMessageTypeData)
{ {
m_MessageType = a_MessageType; m_MessageType = a_MessageType;
m_AdditionalMessageTypeData = a_AdditionalMessageTypeData;
} }
@ -476,3 +486,16 @@ cCompositeChat::cSuggestCommandPart::cSuggestCommandPart(const AString & a_Text,
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cCompositeChat::cShowAchievementPart:
cCompositeChat::cShowAchievementPart::cShowAchievementPart(const AString & a_PlayerName, const AString & a_Achievement, const AString & a_Style) :
super(ptShowAchievement, a_Achievement, a_Style),
m_PlayerName(a_PlayerName)
{
}

View File

@ -38,6 +38,7 @@ public:
ptUrl, ptUrl,
ptRunCommand, ptRunCommand,
ptSuggestCommand, ptSuggestCommand,
ptShowAchievement,
} ; } ;
class cBasePart class cBasePart
@ -46,6 +47,7 @@ public:
ePartType m_PartType; ePartType m_PartType;
AString m_Text; AString m_Text;
AString m_Style; AString m_Style;
AString m_AdditionalStyleData;
cBasePart(ePartType a_PartType, const AString & a_Text, const AString & a_Style = ""); cBasePart(ePartType a_PartType, const AString & a_Text, const AString & a_Style = "");
@ -106,6 +108,15 @@ public:
public: public:
cSuggestCommandPart(const AString & a_Text, const AString & a_Command, const AString & a_Style = ""); cSuggestCommandPart(const AString & a_Text, const AString & a_Command, const AString & a_Style = "");
} ; } ;
class cShowAchievementPart :
public cBasePart
{
typedef cBasePart super;
public:
AString m_PlayerName;
cShowAchievementPart(const AString & a_PlayerName, const AString & a_Achievement, const AString & a_Style = "");
} ;
typedef std::vector<cBasePart *> cParts; typedef std::vector<cBasePart *> cParts;
@ -148,13 +159,20 @@ public:
/** Adds a part that suggests a command (enters it into the chat message area, but doesn't send) when clicked. /** Adds a part that suggests a command (enters it into the chat message area, but doesn't send) when clicked.
The default style is underlined yellow text. */ The default style is underlined yellow text. */
void AddSuggestCommandPart(const AString & a_Text, const AString & a_SuggestedCommand, const AString & a_Style = "u@b"); void AddSuggestCommandPart(const AString & a_Text, const AString & a_SuggestedCommand, const AString & a_Style = "u@b");
/** Adds a part that fully formats a specified achievement using client translatable strings
Takes achievement name and player awarded to. Displays as {player} has earned the achievement {achievement_name}.
*/
void AddShowAchievementPart(const AString & a_PlayerName, const AString & a_Achievement, const AString & a_Style = "");
/** Parses text into various parts, adds those. /** Parses text into various parts, adds those.
Recognizes "http:" and "https:" URLs and @color-codes. */ Recognizes "http:" and "https:" URLs and @color-codes. */
void ParseText(const AString & a_ParseText); void ParseText(const AString & a_ParseText);
/** Sets the message type, which is indicated by prefixes added to the message when serializing. */ /** Sets the message type, which is indicated by prefixes added to the message when serializing
void SetMessageType(eMessageType a_MessageType); Takes optional AdditionalMessageTypeData to set m_AdditionalMessageTypeData. See said variable for more documentation.
*/
void SetMessageType(eMessageType a_MessageType, const AString & a_AdditionalMessageTypeData = "");
/** Adds the "underline" style to each part that is an URL. */ /** Adds the "underline" style to each part that is an URL. */
void UnderlineUrls(void); void UnderlineUrls(void);
@ -163,6 +181,9 @@ public:
/** Returns the message type set previously by SetMessageType(). */ /** Returns the message type set previously by SetMessageType(). */
eMessageType GetMessageType(void) const { return m_MessageType; } eMessageType GetMessageType(void) const { return m_MessageType; }
/** Returns additional data pertaining to message type, for example, the name of a mtPrivateMsg sender */
AString GetAdditionalMessageTypeData(void) const { return m_AdditionalMessageTypeData; }
/** Returns the text from the parts that comprises the human-readable data. /** Returns the text from the parts that comprises the human-readable data.
Used for older protocols that don't support composite chat Used for older protocols that don't support composite chat
@ -184,6 +205,9 @@ protected:
/** The message type, as indicated by prefixes. */ /** The message type, as indicated by prefixes. */
eMessageType m_MessageType; eMessageType m_MessageType;
/** Additional data pertaining to message type, for example, the name of a mtPrivateMsg sender */
AString m_AdditionalMessageTypeData;
/** Adds a_AddStyle to a_Style; overwrites the existing style if appropriate. /** Adds a_AddStyle to a_Style; overwrites the existing style if appropriate.
If the style already contains something that a_AddStyle overrides, it is erased first. */ If the style already contains something that a_AddStyle overrides, it is erased first. */

View File

@ -1023,11 +1023,12 @@ void cEntity::DetectCacti(void)
int X = POSX_TOINT, Y = POSY_TOINT, Z = POSZ_TOINT; int X = POSX_TOINT, Y = POSY_TOINT, Z = POSZ_TOINT;
double w = m_Width / 2; double w = m_Width / 2;
if ( if (
(((X + 1) - GetPosX() < w) && (GetWorld()->GetBlock(X + 1, Y, Z) == E_BLOCK_CACTUS)) || ((Y > 0) && (Y < cChunkDef::Height)) &&
(((GetPosX() - (X - 1)) - 1 < w) && (GetWorld()->GetBlock(X - 1, Y, Z) == E_BLOCK_CACTUS)) || ((((X + 1) - GetPosX() < w) && (GetWorld()->GetBlock(X + 1, Y, Z) == E_BLOCK_CACTUS)) ||
((GetPosX() - X < w) && (GetWorld()->GetBlock(X - 1, Y, Z) == E_BLOCK_CACTUS)) ||
(((Z + 1) - GetPosZ() < w) && (GetWorld()->GetBlock(X, Y, Z + 1) == E_BLOCK_CACTUS)) || (((Z + 1) - GetPosZ() < w) && (GetWorld()->GetBlock(X, Y, Z + 1) == E_BLOCK_CACTUS)) ||
(((GetPosZ() - (Z - 1)) - 1 < w) && (GetWorld()->GetBlock(X, Y, Z - 1) == E_BLOCK_CACTUS)) || ((GetPosZ() - Z < w) && (GetWorld()->GetBlock(X, Y, Z - 1) == E_BLOCK_CACTUS)) ||
(((Y > 0) && (Y < cChunkDef::Height)) && ((GetPosY() - Y < 1) && (GetWorld()->GetBlock(X, Y, Z) == E_BLOCK_CACTUS))) (((GetPosY() - Y < 1) && (GetWorld()->GetBlock(X, Y, Z) == E_BLOCK_CACTUS))))
) )
{ {
TakeDamage(dtCactusContact, NULL, 1, 0); TakeDamage(dtCactusContact, NULL, 1, 0);

View File

@ -377,7 +377,7 @@ short cPlayer::DeltaExperience(short a_Xp_delta)
} }
LOGD("Player \"%s\" gained/lost %d experience, total is now: %d", LOGD("Player \"%s\" gained/lost %d experience, total is now: %d",
m_PlayerName.c_str(), a_Xp_delta, m_CurrentXp); GetName().c_str(), a_Xp_delta, m_CurrentXp);
// Set experience to be updated // Set experience to be updated
m_bDirtyExperience = true; m_bDirtyExperience = true;
@ -391,7 +391,7 @@ short cPlayer::DeltaExperience(short a_Xp_delta)
void cPlayer::StartChargingBow(void) void cPlayer::StartChargingBow(void)
{ {
LOGD("Player \"%s\" started charging their bow", m_PlayerName.c_str()); LOGD("Player \"%s\" started charging their bow", GetName().c_str());
m_IsChargingBow = true; m_IsChargingBow = true;
m_BowCharge = 0; m_BowCharge = 0;
} }
@ -402,7 +402,7 @@ void cPlayer::StartChargingBow(void)
int cPlayer::FinishChargingBow(void) int cPlayer::FinishChargingBow(void)
{ {
LOGD("Player \"%s\" finished charging their bow at a charge of %d", m_PlayerName.c_str(), m_BowCharge); LOGD("Player \"%s\" finished charging their bow at a charge of %d", GetName().c_str(), m_BowCharge);
int res = m_BowCharge; int res = m_BowCharge;
m_IsChargingBow = false; m_IsChargingBow = false;
m_BowCharge = 0; m_BowCharge = 0;
@ -415,7 +415,7 @@ int cPlayer::FinishChargingBow(void)
void cPlayer::CancelChargingBow(void) void cPlayer::CancelChargingBow(void)
{ {
LOGD("Player \"%s\" cancelled charging their bow at a charge of %d", m_PlayerName.c_str(), m_BowCharge); LOGD("Player \"%s\" cancelled charging their bow at a charge of %d", GetName().c_str(), m_BowCharge);
m_IsChargingBow = false; m_IsChargingBow = false;
m_BowCharge = 0; m_BowCharge = 0;
} }
@ -1179,8 +1179,8 @@ unsigned int cPlayer::AwardAchievement(const eStatistic a_Ach)
{ {
// First time, announce it // First time, announce it
cCompositeChat Msg; cCompositeChat Msg;
Msg.AddTextPart(m_PlayerName + " has just earned the achievement "); Msg.SetMessageType(mtSuccess);
Msg.AddTextPart(cStatInfo::GetName(a_Ach)); // TODO 2014-05-12 xdot: Use the proper cCompositeChat part (cAchievement) Msg.AddShowAchievementPart(GetName(), cStatInfo::GetName(a_Ach));
m_World->BroadcastChat(Msg); m_World->BroadcastChat(Msg);
// Increment the statistic // Increment the statistic
@ -1315,7 +1315,7 @@ void cPlayer::AddToGroup( const AString & a_GroupName )
{ {
cGroup* Group = cRoot::Get()->GetGroupManager()->GetGroup( a_GroupName ); cGroup* Group = cRoot::Get()->GetGroupManager()->GetGroup( a_GroupName );
m_Groups.push_back( Group ); m_Groups.push_back( Group );
LOGD("Added %s to group %s", m_PlayerName.c_str(), a_GroupName.c_str() ); LOGD("Added %s to group %s", GetName().c_str(), a_GroupName.c_str() );
ResolveGroups(); ResolveGroups();
ResolvePermissions(); ResolvePermissions();
} }
@ -1339,13 +1339,13 @@ void cPlayer::RemoveFromGroup( const AString & a_GroupName )
if( bRemoved ) if( bRemoved )
{ {
LOGD("Removed %s from group %s", m_PlayerName.c_str(), a_GroupName.c_str() ); LOGD("Removed %s from group %s", GetName().c_str(), a_GroupName.c_str() );
ResolveGroups(); ResolveGroups();
ResolvePermissions(); ResolvePermissions();
} }
else else
{ {
LOGWARN("Tried to remove %s from group %s but was not in that group", m_PlayerName.c_str(), a_GroupName.c_str() ); LOGWARN("Tried to remove %s from group %s but was not in that group", GetName().c_str(), a_GroupName.c_str() );
} }
} }
@ -1451,7 +1451,7 @@ void cPlayer::ResolveGroups()
if( AllGroups.find( CurrentGroup ) != AllGroups.end() ) if( AllGroups.find( CurrentGroup ) != AllGroups.end() )
{ {
LOGWARNING("ERROR: Player \"%s\" is in the group multiple times (\"%s\"). Please fix your settings in users.ini!", LOGWARNING("ERROR: Player \"%s\" is in the group multiple times (\"%s\"). Please fix your settings in users.ini!",
m_PlayerName.c_str(), CurrentGroup->GetName().c_str() GetName().c_str(), CurrentGroup->GetName().c_str()
); );
} }
else else
@ -1463,7 +1463,7 @@ void cPlayer::ResolveGroups()
{ {
if( AllGroups.find( *itr ) != AllGroups.end() ) if( AllGroups.find( *itr ) != AllGroups.end() )
{ {
LOGERROR("ERROR: Player %s is in the same group multiple times due to inheritance (%s). FIX IT!", m_PlayerName.c_str(), (*itr)->GetName().c_str() ); 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; continue;
} }
ToIterate.push_back( *itr ); ToIterate.push_back( *itr );
@ -1615,19 +1615,19 @@ void cPlayer::LoadPermissionsFromDisk()
cIniFile IniFile; cIniFile IniFile;
if (IniFile.ReadFile("users.ini")) if (IniFile.ReadFile("users.ini"))
{ {
AString Groups = IniFile.GetValueSet(m_PlayerName, "Groups", "Default"); AString Groups = IniFile.GetValueSet(GetName(), "Groups", "Default");
AStringVector Split = StringSplitAndTrim(Groups, ","); AStringVector Split = StringSplitAndTrim(Groups, ",");
for (AStringVector::const_iterator itr = Split.begin(), end = Split.end(); itr != end; ++itr) for (AStringVector::const_iterator itr = Split.begin(), end = Split.end(); itr != end; ++itr)
{ {
if (!cRoot::Get()->GetGroupManager()->ExistsGroup(*itr)) if (!cRoot::Get()->GetGroupManager()->ExistsGroup(*itr))
{ {
LOGWARNING("The group %s for player %s was not found!", itr->c_str(), m_PlayerName.c_str()); LOGWARNING("The group %s for player %s was not found!", itr->c_str(), GetName().c_str());
} }
AddToGroup(*itr); AddToGroup(*itr);
} }
AString Color = IniFile.GetValue(m_PlayerName, "Color", "-"); AString Color = IniFile.GetValue(GetName(), "Color", "-");
if (!Color.empty()) if (!Color.empty())
{ {
m_Color = Color[0]; m_Color = Color[0];
@ -1636,7 +1636,7 @@ void cPlayer::LoadPermissionsFromDisk()
else else
{ {
cGroupManager::GenerateDefaultUsersIni(IniFile); cGroupManager::GenerateDefaultUsersIni(IniFile);
IniFile.AddValue("Groups", m_PlayerName, "Default"); IniFile.AddValue("Groups", GetName(), "Default");
AddToGroup("Default"); AddToGroup("Default");
} }
IniFile.WriteFile("users.ini"); IniFile.WriteFile("users.ini");
@ -1651,14 +1651,14 @@ bool cPlayer::LoadFromDisk()
LoadPermissionsFromDisk(); LoadPermissionsFromDisk();
// Log player permissions, cause it's what the cool kids do // Log player permissions, cause it's what the cool kids do
LOGINFO("Player %s has permissions:", m_PlayerName.c_str() ); LOGINFO("Player %s has permissions:", GetName().c_str() );
for( PermissionMap::iterator itr = m_ResolvedPermissions.begin(); itr != m_ResolvedPermissions.end(); ++itr ) for( PermissionMap::iterator itr = m_ResolvedPermissions.begin(); itr != m_ResolvedPermissions.end(); ++itr )
{ {
if( itr->second ) LOG(" - %s", itr->first.c_str() ); if( itr->second ) LOG(" - %s", itr->first.c_str() );
} }
AString SourceFile; AString SourceFile;
Printf(SourceFile, "players/%s.json", m_PlayerName.c_str() ); Printf(SourceFile, "players/%s.json", GetName().c_str() );
cFile f; cFile f;
if (!f.Open(SourceFile, cFile::fmRead)) if (!f.Open(SourceFile, cFile::fmRead))
@ -1726,7 +1726,7 @@ bool cPlayer::LoadFromDisk()
StatSerializer.Load(); StatSerializer.Load();
LOGD("Player \"%s\" was read from file, spawning at {%.2f, %.2f, %.2f} in world \"%s\"", LOGD("Player \"%s\" was read from file, spawning at {%.2f, %.2f, %.2f} in world \"%s\"",
m_PlayerName.c_str(), GetPosX(), GetPosY(), GetPosZ(), m_LoadedWorldName.c_str() GetName().c_str(), GetPosX(), GetPosY(), GetPosZ(), m_LoadedWorldName.c_str()
); );
return true; return true;
@ -1782,12 +1782,12 @@ bool cPlayer::SaveToDisk()
std::string JsonData = writer.write(root); std::string JsonData = writer.write(root);
AString SourceFile; AString SourceFile;
Printf(SourceFile, "players/%s.json", m_PlayerName.c_str() ); Printf(SourceFile, "players/%s.json", GetName().c_str() );
cFile f; cFile f;
if (!f.Open(SourceFile, cFile::fmWrite)) if (!f.Open(SourceFile, cFile::fmWrite))
{ {
LOGERROR("ERROR WRITING PLAYER \"%s\" TO FILE \"%s\" - cannot open file", m_PlayerName.c_str(), SourceFile.c_str()); LOGERROR("ERROR WRITING PLAYER \"%s\" TO FILE \"%s\" - cannot open file", GetName().c_str(), SourceFile.c_str());
return false; return false;
} }
if (f.Write(JsonData.c_str(), JsonData.size()) != (int)JsonData.size()) if (f.Write(JsonData.c_str(), JsonData.size()) != (int)JsonData.size())
@ -1798,10 +1798,10 @@ bool cPlayer::SaveToDisk()
// Save the player stats. // Save the player stats.
// We use the default world name (like bukkit) because stats are shared between dimensions/worlds. // We use the default world name (like bukkit) because stats are shared between dimensions/worlds.
cStatSerializer StatSerializer(cRoot::Get()->GetDefaultWorld()->GetName(), m_PlayerName, &m_Stats); cStatSerializer StatSerializer(cRoot::Get()->GetDefaultWorld()->GetName(), GetName(), &m_Stats);
if (!StatSerializer.Save()) if (!StatSerializer.Save())
{ {
LOGERROR("Could not save stats for player %s", m_PlayerName.c_str()); LOGERROR("Could not save stats for player %s", GetName().c_str());
return false; return false;
} }

View File

@ -234,7 +234,7 @@ void cProtocol172::SendChat(const cCompositeChat & a_Message)
// Compose the complete Json string to send: // Compose the complete Json string to send:
Json::Value msg; Json::Value msg;
msg["text"] = ""; // The client crashes without this msg["text"] = cClientHandle::FormatMessageType(m_Client->GetPlayer()->GetWorld()->ShouldUseChatPrefixes(), a_Message.GetMessageType(), a_Message.GetAdditionalMessageTypeData()); // The client crashes without this field being present
const cCompositeChat::cParts & Parts = a_Message.GetParts(); const cCompositeChat::cParts & Parts = a_Message.GetParts();
for (cCompositeChat::cParts::const_iterator itr = Parts.begin(), end = Parts.end(); itr != end; ++itr) for (cCompositeChat::cParts::const_iterator itr = Parts.begin(), end = Parts.end(); itr != end; ++itr)
{ {
@ -289,6 +289,35 @@ void cProtocol172::SendChat(const cCompositeChat & a_Message)
AddChatPartStyle(Part, p.m_Style); AddChatPartStyle(Part, p.m_Style);
break; break;
} }
case cCompositeChat::ptShowAchievement:
{
const cCompositeChat::cShowAchievementPart & p = (const cCompositeChat::cShowAchievementPart &)**itr;
Part["translate"] = "chat.type.achievement";
Json::Value Ach;
Ach["action"] = "show_achievement";
Ach["value"] = p.m_Text;
Json::Value AchColourAndName;
AchColourAndName["color"] = "green";
AchColourAndName["translate"] = p.m_Text;
AchColourAndName["hoverEvent"] = Ach;
Json::Value Extra;
Extra.append(AchColourAndName);
Json::Value Name;
Name["text"] = p.m_PlayerName;
Json::Value With;
With.append(Name);
With.append(Extra);
Part["with"] = With;
AddChatPartStyle(Part, p.m_Style);
break;
}
} }
msg["extra"].append(Part); msg["extra"].append(Part);
} // for itr - Parts[] } // for itr - Parts[]