1
0

Merge branch 'master' into VillageGen

This commit is contained in:
madmaxoft 2014-05-27 22:09:30 +02:00
commit dff71823d4
14 changed files with 158 additions and 80 deletions

View File

@ -39,7 +39,8 @@ pre
body body
{ {
min-width: 800px; min-width: 400px;
max-width: 1200px;
width: 95%; width: 95%;
margin: 10px auto; margin: 10px auto;
background-color: white; background-color: white;

@ -1 +1 @@
Subproject commit 5c8557d4fdfa580c100510cde07a1a778ea2e244 Subproject commit 3790f78d3f7503ff33a423b8e73e81a275562783

View File

@ -1,38 +1,39 @@
MCServer MCServer [![Build Status](http://img.shields.io/travis/mc-server/MCServer.svg)](https://travis-ci.org/mc-server/MCServer) [![Support via Gittip](http://img.shields.io/gittip/mcs_team.svg)](https://www.gittip.com/mcs_team) [![tip for next commit](http://tip4commit.com/projects/74.svg)](http://tip4commit.com/projects/74)
======== ========
**Current Protocol Supported:** Minecraft v1.2 -> v1.7 MCServer is a Minecraft server that is written in C++ and designed to be efficient with memory and CPU, as well as having a flexible Lua Plugin API.
MCServer is a performant C++ Minecraft server designed for use in memory and cpu-limited places, or just to make regular server perform better.
MCServer can run on PCs, Macs, and *nix. This includes android phones and tablets as well as Raspberry Pis. MCServer can run on PCs, Macs, and *nix. This includes android phones and tablets as well as Raspberry Pis.
We currently support the protocol from Minecraft 1.2 all the way up to Minecraft 1.7.9.
Installation Installation
------------ ------------
To install MCServer, you can either download the repository and compile it, or download a pre-compiled version. Normally, you will want to download a pre-compiled version of MCServer from one of the buildservers:
If you've cloned the repository using Git, you need to pull down the submodules (core plugins, some dependencies). This can be achieved with `git submodule init` and then on a regular basis (to keep up to date) `git submodule update`. * [Linux and Raspberry Pi](http://ci.bearbin.net) (Bearbin's CI Server)
* [Windows](http://mc-server.xoft.cz) (xoft's nightly build service)
If you downloaded a ZIP file of the sources instead, you will need to download PolarSSL, too, from https://github.com/polarssl/polarssl , and unpack it into the `lib/polarssl` folder. You will also need to manually download all the plugins that you want included. You simply need to download and extract these files before you can use the server.
Compilation instructions are available in the COMPILING file. If you're a more advanced user, you may want to compile the server yourself for more performance. See the [COMPILING.md](https://github.com/mc-server/MCServer/blob/master/COMPILING.md) file for more details.
Linux builds can be downloaded from [Bearbin's CI Service](http://ci.bearbin.net) and Windows builds from xoft's [nightly build service](http://mc-server.xoft.cz).
After you've extracted the files, simply run the MCServer executable.
Contributing Contributing
------------ ------------
MCServer is licensed under the Apache license V2, and we welcome anybody to fork and submit a Pull Request back with their changes, and if you want to join as a permanent member we can add you to the team. MCServer is licensed under the Apache license V2, and we welcome anybody to fork and submit a Pull Request back with their changes, and if you want to join as a permanent member we can add you to the team.
Check out the [CONTRIBUTING.md](https://github.com/mc-server/MCServer/blob/master/CONTRIBUTING.md) file for more details.
Other Stuff Other Stuff
----------- -----------
For other stuff, including plugins and discussion, check the [forums](http://forum.mc-server.org) and [wiki](http://wiki.mc-server.org/). For other stuff, including plugins and discussion, check the [forums](http://forum.mc-server.org) and [Plugin API](http://mc-server.xoft.cz/LuaAPI/).
Earn bitcoins for commits or donate to reward the MCServer developers: [![tip for next commit](http://tip4commit.com/projects/74.svg)](http://tip4commit.com/projects/74) Earn bitcoins for commits or donate to reward the MCServer developers: [![tip for next commit](http://tip4commit.com/projects/74.svg)](http://tip4commit.com/projects/74)
Travis CI: [![Build Status](https://travis-ci.org/mc-server/MCServer.png?branch=master)](https://travis-ci.org/mc-server/MCServer) Support Us on Gittip: [![Support via Gittip](http://img.shields.io/gittip/mcs_team.svg)](https://www.gittip.com/mcs_team)
Travis CI: [![Build Status](http://img.shields.io/travis/mc-server/MCServer.svg)](https://travis-ci.org/mc-server/MCServer)

View File

@ -1391,28 +1391,8 @@ void cClientHandle::HandlePlayerLook(float a_Rotation, float a_Pitch, bool a_IsO
void cClientHandle::HandlePlayerMoveLook(double a_PosX, double a_PosY, double a_PosZ, double a_Stance, float a_Rotation, float a_Pitch, bool a_IsOnGround) void cClientHandle::HandlePlayerMoveLook(double a_PosX, double a_PosY, double a_PosZ, double a_Stance, float a_Rotation, float a_Pitch, bool a_IsOnGround)
{ {
if ((m_Player == NULL) || (m_State != csPlaying)) HandlePlayerLook(a_Rotation, a_Pitch, a_IsOnGround);
{ HandlePlayerPos(a_PosX, a_PosY, a_PosZ, a_Stance, a_IsOnGround);
// The client hasn't been spawned yet and sends nonsense, we know better
return;
}
/*
// TODO: Invalid stance check
if ((a_PosY >= a_Stance) || (a_Stance > a_PosY + 1.65))
{
LOGD("Invalid stance");
SendPlayerMoveLook();
return;
}
*/
m_Player->MoveTo(Vector3d(a_PosX, a_PosY, a_PosZ));
m_Player->SetStance (a_Stance);
m_Player->SetTouchGround(a_IsOnGround);
m_Player->SetHeadYaw (a_Rotation);
m_Player->SetYaw (a_Rotation);
m_Player->SetPitch (a_Pitch);
} }

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

@ -1018,16 +1018,17 @@ void cEntity::TickInVoid(cChunk & a_Chunk)
void cEntity::DetectCacti() void cEntity::DetectCacti(void)
{ {
int X = POSX_TOINT, Y = POSY_TOINT, Z = POSZ_TOINT; int X = POSX_TOINT, Y = POSY_TOINT, Z = POSZ_TOINT;
float 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

@ -50,6 +50,15 @@ cGridStructGen::cGridStructGen(
m_MaxStructureSizeZ(a_MaxStructureSizeZ), m_MaxStructureSizeZ(a_MaxStructureSizeZ),
m_MaxCacheSize(a_MaxCacheSize) m_MaxCacheSize(a_MaxCacheSize)
{ {
size_t NumStructuresPerQuery = (size_t)((m_MaxStructureSizeX / m_GridSizeX + 1) * (m_MaxStructureSizeZ / m_GridSizeZ + 1));
if (NumStructuresPerQuery > m_MaxCacheSize)
{
m_MaxCacheSize = NumStructuresPerQuery * 4;
LOGINFO(
"cGridStructGen: The cache size is too small (%u), increasing the cache size to %u to avoid inefficiency.",
(unsigned)a_MaxCacheSize, (unsigned)m_MaxCacheSize
);
}
} }

View File

@ -1283,7 +1283,7 @@ cStructGenMineShafts::cStructGenMineShafts(
int a_Seed, int a_GridSize, int a_MaxSystemSize, int a_Seed, int a_GridSize, int a_MaxSystemSize,
int a_ChanceCorridor, int a_ChanceCrossing, int a_ChanceStaircase int a_ChanceCorridor, int a_ChanceCrossing, int a_ChanceStaircase
) : ) :
super(a_Seed, a_GridSize, a_GridSize, 120 + a_MaxSystemSize * 10, 120 + a_MaxSystemSize * 10, 100), super(a_Seed, a_GridSize, a_GridSize, a_MaxSystemSize, a_MaxSystemSize, 100),
m_Noise(a_Seed), m_Noise(a_Seed),
m_GridSize(a_GridSize), m_GridSize(a_GridSize),
m_MaxSystemSize(a_MaxSystemSize), m_MaxSystemSize(a_MaxSystemSize),

View File

@ -45,8 +45,14 @@ cGroupManager::cGroupManager()
{ {
LOGD("-- Loading Groups --"); LOGD("-- Loading Groups --");
LoadGroups(); if (!LoadGroups())
CheckUsers(); {
LOGWARNING("ERROR: Groups could not load!");
}
if (!CheckUsers())
{
LOGWARNING("ERROR: User file could not be found!");
}
LOGD("-- Groups Successfully Loaded --"); LOGD("-- Groups Successfully Loaded --");
} }
@ -70,13 +76,13 @@ void cGroupManager::GenerateDefaultUsersIni(cIniFile & a_IniFile)
void cGroupManager::CheckUsers(void) bool cGroupManager::CheckUsers()
{ {
cIniFile IniFile; cIniFile IniFile;
if (!IniFile.ReadFile("users.ini")) if (!IniFile.ReadFile("users.ini"))
{ {
GenerateDefaultUsersIni(IniFile); GenerateDefaultUsersIni(IniFile);
return; return true;
} }
int NumKeys = IniFile.GetNumKeys(); int NumKeys = IniFile.GetNumKeys();
@ -97,13 +103,15 @@ void cGroupManager::CheckUsers(void)
} }
} // for itr - Split[] } // for itr - Split[]
} // for i - ini file keys } // for i - ini file keys
// Always return true for now, just but we can handle writefile fails later.
return true;
} }
void cGroupManager::LoadGroups() bool cGroupManager::LoadGroups()
{ {
cIniFile IniFile; cIniFile IniFile;
if (!IniFile.ReadFile("groups.ini")) if (!IniFile.ReadFile("groups.ini"))
@ -180,6 +188,8 @@ void cGroupManager::LoadGroups()
} }
} }
} }
// Always return true, we can handle writefile fails later.
return true;
} }

View File

@ -16,8 +16,8 @@ class cGroupManager
public: public:
bool ExistsGroup(const AString & a_Name); bool ExistsGroup(const AString & a_Name);
cGroup * GetGroup(const AString & a_Name); cGroup * GetGroup(const AString & a_Name);
void LoadGroups(void); bool LoadGroups();
void CheckUsers(void); bool CheckUsers();
/** Writes the default header to the specified ini file, and saves it as "users.ini". */ /** Writes the default header to the specified ini file, and saves it as "users.ini". */
static void GenerateDefaultUsersIni(cIniFile & a_IniFile); static void GenerateDefaultUsersIni(cIniFile & a_IniFile);

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[]