Merge remote-tracking branch 'origin/master' into potions
This commit is contained in:
@@ -34,51 +34,47 @@
|
||||
|
||||
|
||||
|
||||
cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName)
|
||||
: super(etPlayer, 0.6, 1.8)
|
||||
, m_bVisible(true)
|
||||
, m_FoodLevel(MAX_FOOD_LEVEL)
|
||||
, m_FoodSaturationLevel(5.0)
|
||||
, m_FoodTickTimer(0)
|
||||
, m_FoodExhaustionLevel(0.0)
|
||||
, m_LastJumpHeight(0)
|
||||
, m_LastGroundHeight(0)
|
||||
, m_bTouchGround(false)
|
||||
, m_Stance(0.0)
|
||||
, m_Inventory(*this)
|
||||
, m_EnderChestContents(9, 3)
|
||||
, m_CurrentWindow(NULL)
|
||||
, m_InventoryWindow(NULL)
|
||||
, m_Color('-')
|
||||
, m_GameMode(eGameMode_NotSet)
|
||||
, m_IP("")
|
||||
, m_ClientHandle(a_Client)
|
||||
, m_NormalMaxSpeed(1.0)
|
||||
, m_SprintingMaxSpeed(1.3)
|
||||
, m_FlyingMaxSpeed(1.0)
|
||||
, m_IsCrouched(false)
|
||||
, m_IsSprinting(false)
|
||||
, m_IsFlying(false)
|
||||
, m_IsSwimming(false)
|
||||
, m_IsSubmerged(false)
|
||||
, m_IsFishing(false)
|
||||
, m_CanFly(false)
|
||||
, m_EatingFinishTick(-1)
|
||||
, m_LifetimeTotalXp(0)
|
||||
, m_CurrentXp(0)
|
||||
, m_bDirtyExperience(false)
|
||||
, m_IsChargingBow(false)
|
||||
, m_BowCharge(0)
|
||||
, m_FloaterID(-1)
|
||||
, m_Team(NULL)
|
||||
, m_TicksUntilNextSave(PLAYER_INVENTORY_SAVE_INTERVAL)
|
||||
, m_bIsTeleporting(false)
|
||||
cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName) :
|
||||
super(etPlayer, 0.6, 1.8),
|
||||
m_bVisible(true),
|
||||
m_FoodLevel(MAX_FOOD_LEVEL),
|
||||
m_FoodSaturationLevel(5.0),
|
||||
m_FoodTickTimer(0),
|
||||
m_FoodExhaustionLevel(0.0),
|
||||
m_LastJumpHeight(0),
|
||||
m_LastGroundHeight(0),
|
||||
m_bTouchGround(false),
|
||||
m_Stance(0.0),
|
||||
m_Inventory(*this),
|
||||
m_EnderChestContents(9, 3),
|
||||
m_CurrentWindow(NULL),
|
||||
m_InventoryWindow(NULL),
|
||||
m_Color('-'),
|
||||
m_GameMode(eGameMode_NotSet),
|
||||
m_IP(""),
|
||||
m_ClientHandle(a_Client),
|
||||
m_NormalMaxSpeed(1.0),
|
||||
m_SprintingMaxSpeed(1.3),
|
||||
m_FlyingMaxSpeed(1.0),
|
||||
m_IsCrouched(false),
|
||||
m_IsSprinting(false),
|
||||
m_IsFlying(false),
|
||||
m_IsSwimming(false),
|
||||
m_IsSubmerged(false),
|
||||
m_IsFishing(false),
|
||||
m_CanFly(false),
|
||||
m_EatingFinishTick(-1),
|
||||
m_LifetimeTotalXp(0),
|
||||
m_CurrentXp(0),
|
||||
m_bDirtyExperience(false),
|
||||
m_IsChargingBow(false),
|
||||
m_BowCharge(0),
|
||||
m_FloaterID(-1),
|
||||
m_Team(NULL),
|
||||
m_TicksUntilNextSave(PLAYER_INVENTORY_SAVE_INTERVAL),
|
||||
m_bIsTeleporting(false),
|
||||
m_UUID((a_Client != NULL) ? a_Client->GetUUID() : "")
|
||||
{
|
||||
LOGD("Created a player object for \"%s\" @ \"%s\" at %p, ID %d",
|
||||
a_PlayerName.c_str(), a_Client->GetIPString().c_str(),
|
||||
this, GetUniqueID()
|
||||
);
|
||||
|
||||
m_InventoryWindow = new cInventoryWindow(*this);
|
||||
m_CurrentWindow = m_InventoryWindow;
|
||||
m_InventoryWindow->OpenedByPlayer(*this);
|
||||
@@ -1670,53 +1666,98 @@ void cPlayer::LoadPermissionsFromDisk()
|
||||
|
||||
|
||||
|
||||
bool cPlayer::LoadFromDisk()
|
||||
|
||||
bool cPlayer::LoadFromDisk(void)
|
||||
{
|
||||
LoadPermissionsFromDisk();
|
||||
|
||||
AString SourceFile;
|
||||
Printf(SourceFile, "players/%s.json", GetName().c_str() );
|
||||
// Load from the UUID file:
|
||||
if (LoadFromFile(GetUUIDFileName(m_UUID)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Load from the offline UUID file, if allowed:
|
||||
AString OfflineUUID = cClientHandle::GenerateOfflineUUID(GetName());
|
||||
if (cRoot::Get()->GetServer()->ShouldLoadOfflinePlayerData())
|
||||
{
|
||||
if (LoadFromFile(GetUUIDFileName(OfflineUUID)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Load from the old-style name-based file, if allowed:
|
||||
if (cRoot::Get()->GetServer()->ShouldLoadNamedPlayerData())
|
||||
{
|
||||
AString OldStyleFileName = Printf("players/%s.json", GetName().c_str());
|
||||
if (LoadFromFile(OldStyleFileName))
|
||||
{
|
||||
// Save in new format and remove the old file
|
||||
if (SaveToDisk())
|
||||
{
|
||||
cFile::Delete(OldStyleFileName);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// None of the files loaded successfully
|
||||
LOG("Player data file not found for %s (%s, offline %s), will be reset to defaults.",
|
||||
GetName().c_str(), m_UUID.c_str(), OfflineUUID.c_str()
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cPlayer::LoadFromFile(const AString & a_FileName)
|
||||
{
|
||||
// Load the data from the file:
|
||||
cFile f;
|
||||
if (!f.Open(SourceFile, cFile::fmRead))
|
||||
if (!f.Open(a_FileName, cFile::fmRead))
|
||||
{
|
||||
// This is a new player whom we haven't seen yet, bail out, let them have the defaults
|
||||
return false;
|
||||
}
|
||||
|
||||
AString buffer;
|
||||
if (f.ReadRestOfFile(buffer) != f.GetSize())
|
||||
{
|
||||
LOGWARNING("Cannot read player data from file \"%s\"", SourceFile.c_str());
|
||||
LOGWARNING("Cannot read player data from file \"%s\"", a_FileName.c_str());
|
||||
return false;
|
||||
}
|
||||
f.Close(); //cool kids play nice
|
||||
f.Close();
|
||||
|
||||
// Parse the JSON format:
|
||||
Json::Value root;
|
||||
Json::Reader reader;
|
||||
if (!reader.parse(buffer, root, false))
|
||||
{
|
||||
LOGWARNING("Cannot parse player data in file \"%s\", player will be reset", SourceFile.c_str());
|
||||
LOGWARNING("Cannot parse player data in file \"%s\"", a_FileName.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load the player data:
|
||||
Json::Value & JSON_PlayerPosition = root["position"];
|
||||
if (JSON_PlayerPosition.size() == 3)
|
||||
{
|
||||
SetPosX(JSON_PlayerPosition[(unsigned int)0].asDouble());
|
||||
SetPosY(JSON_PlayerPosition[(unsigned int)1].asDouble());
|
||||
SetPosZ(JSON_PlayerPosition[(unsigned int)2].asDouble());
|
||||
SetPosX(JSON_PlayerPosition[(unsigned)0].asDouble());
|
||||
SetPosY(JSON_PlayerPosition[(unsigned)1].asDouble());
|
||||
SetPosZ(JSON_PlayerPosition[(unsigned)2].asDouble());
|
||||
m_LastPos = GetPosition();
|
||||
}
|
||||
|
||||
Json::Value & JSON_PlayerRotation = root["rotation"];
|
||||
if (JSON_PlayerRotation.size() == 3)
|
||||
{
|
||||
SetYaw ((float)JSON_PlayerRotation[(unsigned int)0].asDouble());
|
||||
SetPitch ((float)JSON_PlayerRotation[(unsigned int)1].asDouble());
|
||||
SetRoll ((float)JSON_PlayerRotation[(unsigned int)2].asDouble());
|
||||
SetYaw ((float)JSON_PlayerRotation[(unsigned)0].asDouble());
|
||||
SetPitch ((float)JSON_PlayerRotation[(unsigned)1].asDouble());
|
||||
SetRoll ((float)JSON_PlayerRotation[(unsigned)2].asDouble());
|
||||
}
|
||||
|
||||
m_Health = root.get("health", 0).asInt();
|
||||
m_Health = root.get("health", 0).asInt();
|
||||
m_AirLevel = root.get("air", MAX_AIR_LEVEL).asInt();
|
||||
m_FoodLevel = root.get("food", MAX_FOOD_LEVEL).asInt();
|
||||
m_FoodSaturationLevel = root.get("foodSaturation", MAX_FOOD_LEVEL).asDouble();
|
||||
@@ -1743,8 +1784,8 @@ bool cPlayer::LoadFromDisk()
|
||||
cStatSerializer StatSerializer(cRoot::Get()->GetDefaultWorld()->GetName(), GetName(), &m_Stats);
|
||||
StatSerializer.Load();
|
||||
|
||||
LOGD("Player \"%s\" was read from file, spawning at {%.2f, %.2f, %.2f} in world \"%s\"",
|
||||
GetName().c_str(), GetPosX(), GetPosY(), GetPosZ(), m_LoadedWorldName.c_str()
|
||||
LOGD("Player \"%s\" was read from file \"%s\", spawning at {%.2f, %.2f, %.2f} in world \"%s\"",
|
||||
GetName().c_str(), a_FileName.c_str(), GetPosX(), GetPosY(), GetPosZ(), m_LoadedWorldName.c_str()
|
||||
);
|
||||
|
||||
return true;
|
||||
@@ -1757,6 +1798,7 @@ bool cPlayer::LoadFromDisk()
|
||||
bool cPlayer::SaveToDisk()
|
||||
{
|
||||
cFile::CreateFolder(FILE_IO_PREFIX + AString("players"));
|
||||
cFile::CreateFolder(FILE_IO_PREFIX + AString("players/") + m_UUID.substr(0, 2));
|
||||
|
||||
// create the JSON data
|
||||
Json::Value JSON_PlayerPosition;
|
||||
@@ -1788,33 +1830,45 @@ bool cPlayer::SaveToDisk()
|
||||
root["foodSaturation"] = m_FoodSaturationLevel;
|
||||
root["foodTickTimer"] = m_FoodTickTimer;
|
||||
root["foodExhaustion"] = m_FoodExhaustionLevel;
|
||||
root["world"] = GetWorld()->GetName();
|
||||
root["isflying"] = IsFlying();
|
||||
|
||||
if (m_GameMode == GetWorld()->GetGameMode())
|
||||
root["lastknownname"] = GetName();
|
||||
if (m_World != NULL)
|
||||
{
|
||||
root["gamemode"] = (int) eGameMode_NotSet;
|
||||
root["world"] = m_World->GetName();
|
||||
if (m_GameMode == m_World->GetGameMode())
|
||||
{
|
||||
root["gamemode"] = (int) eGameMode_NotSet;
|
||||
}
|
||||
else
|
||||
{
|
||||
root["gamemode"] = (int) m_GameMode;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
root["gamemode"] = (int) m_GameMode;
|
||||
// This happens if the player is saved to new format after loading from the old format
|
||||
root["world"] = m_LoadedWorldName;
|
||||
root["gamemode"] = (int) eGameMode_NotSet;
|
||||
}
|
||||
|
||||
Json::StyledWriter writer;
|
||||
std::string JsonData = writer.write(root);
|
||||
|
||||
AString SourceFile;
|
||||
Printf(SourceFile, "players/%s.json", GetName().c_str() );
|
||||
AString SourceFile = GetUUIDFileName(m_UUID);
|
||||
|
||||
cFile f;
|
||||
if (!f.Open(SourceFile, cFile::fmWrite))
|
||||
{
|
||||
LOGERROR("ERROR WRITING PLAYER \"%s\" TO FILE \"%s\" - cannot open file", GetName().c_str(), SourceFile.c_str());
|
||||
LOGWARNING("Error writing player \"%s\" to file \"%s\" - cannot open file. Player will lose their progress.",
|
||||
GetName().c_str(), SourceFile.c_str()
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (f.Write(JsonData.c_str(), JsonData.size()) != (int)JsonData.size())
|
||||
{
|
||||
LOGERROR("ERROR WRITING PLAYER JSON TO FILE \"%s\"", SourceFile.c_str());
|
||||
LOGWARNING("Error writing player \"%s\" to file \"%s\" - cannot save data. Player will lose their progress. ",
|
||||
GetName().c_str(), SourceFile.c_str()
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1823,7 +1877,7 @@ bool cPlayer::SaveToDisk()
|
||||
cStatSerializer StatSerializer(cRoot::Get()->GetDefaultWorld()->GetName(), GetName(), &m_Stats);
|
||||
if (!StatSerializer.Save())
|
||||
{
|
||||
LOGERROR("Could not save stats for player %s", GetName().c_str());
|
||||
LOGWARNING("Could not save stats for player %s", GetName().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2125,3 +2179,19 @@ void cPlayer::Detach()
|
||||
|
||||
|
||||
|
||||
|
||||
AString cPlayer::GetUUIDFileName(const AString & a_UUID)
|
||||
{
|
||||
ASSERT(a_UUID.size() == 36);
|
||||
|
||||
AString res("players/");
|
||||
res.append(a_UUID, 0, 2);
|
||||
res.push_back('/');
|
||||
res.append(a_UUID, 2, AString::npos);
|
||||
res.append(".json");
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user