Player data loading cleanup
* Kick player if data were corrupt to avoid making it worse
This commit is contained in:
parent
222d9957a1
commit
8a30a4a7b8
@ -140,15 +140,6 @@ void cClientHandle::Destroy(void)
|
||||
|
||||
|
||||
|
||||
void cClientHandle::GenerateOfflineUUID(void)
|
||||
{
|
||||
m_UUID = GenerateOfflineUUID(m_Username);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
AString cClientHandle::FormatChatPrefix(
|
||||
bool ShouldAppendChatPrefixes, const AString & a_ChatPrefixS,
|
||||
const AString & m_Color1, const AString & m_Color2
|
||||
@ -318,7 +309,19 @@ void cClientHandle::Authenticate(const AString & a_Name, const cUUID & a_UUID, c
|
||||
void cClientHandle::FinishAuthenticate(const AString & a_Name, const cUUID & a_UUID, const Json::Value & a_Properties)
|
||||
{
|
||||
// Serverside spawned player (so data are loaded).
|
||||
auto Player = std::make_unique<cPlayer>(shared_from_this());
|
||||
std::unique_ptr<cPlayer> Player;
|
||||
|
||||
try
|
||||
{
|
||||
Player = std::make_unique<cPlayer>(shared_from_this());
|
||||
}
|
||||
catch (const std::exception & Oops)
|
||||
{
|
||||
LOGWARNING("Error reading player \"%s\": %s", GetUsername().c_str(), Oops.what());
|
||||
Kick("Contact an operator.\n\nYour player's save files could not be parsed.\nTo avoid data loss you are prevented from joining.");
|
||||
return;
|
||||
}
|
||||
|
||||
m_Player = Player.get();
|
||||
|
||||
/*
|
||||
@ -1461,9 +1464,7 @@ void cClientHandle::HandleChat(const AString & a_Message)
|
||||
{
|
||||
if ((a_Message.size()) > MAX_CHAT_MSG_LENGTH)
|
||||
{
|
||||
this->Kick(std::string("Please don't exceed the maximum message length of ")
|
||||
+ std::to_string(MAX_CHAT_MSG_LENGTH)
|
||||
);
|
||||
Kick("Please don't exceed the maximum message length of " + std::to_string(MAX_CHAT_MSG_LENGTH));
|
||||
return;
|
||||
}
|
||||
// We no longer need to postpone message processing, because the messages already arrive in the Tick thread
|
||||
|
@ -90,12 +90,6 @@ public: // tolua_export
|
||||
and the results are passed to MCS running in offline mode. */
|
||||
void SetProperties(const Json::Value & a_Properties) { m_Properties = a_Properties; }
|
||||
|
||||
/** Generates an UUID based on the username stored for this client, and stores it in the m_UUID member.
|
||||
This is used for the offline (non-auth) mode, when there's no UUID source.
|
||||
Each username generates a unique and constant UUID, so that when the player reconnects with the same name, their UUID is the same.
|
||||
Internally calls the GenerateOfflineUUID static function. */
|
||||
void GenerateOfflineUUID(void);
|
||||
|
||||
/** Generates an UUID based on the player name provided.
|
||||
This is used for the offline (non-auth) mode, when there's no UUID source.
|
||||
Each username generates a unique and constant UUID, so that when the player reconnects with the same name, their UUID is the same. */
|
||||
|
@ -37,23 +37,6 @@
|
||||
namespace
|
||||
{
|
||||
|
||||
/** Returns the old Offline UUID generated before becoming vanilla compliant. */
|
||||
cUUID GetOldStyleOfflineUUID(const AString & a_PlayerName)
|
||||
{
|
||||
// Use lowercase username
|
||||
auto BaseUUID = cUUID::GenerateVersion3(StrToLower(a_PlayerName)).ToRaw();
|
||||
// Clobber a full nibble around the variant bits
|
||||
BaseUUID[8] = (BaseUUID[8] & 0x0f) | 0x80;
|
||||
|
||||
cUUID Ret;
|
||||
Ret.FromRaw(BaseUUID);
|
||||
return Ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** Returns the folder for the player data based on the UUID given.
|
||||
This can be used both for online and offline UUIDs. */
|
||||
AString GetUUIDFolderName(const cUUID & a_Uuid)
|
||||
@ -115,7 +98,6 @@ cPlayer::cPlayer(const std::shared_ptr<cClientHandle> & a_Client) :
|
||||
m_bIsInBed(false),
|
||||
m_TicksUntilNextSave(PLAYER_INVENTORY_SAVE_INTERVAL),
|
||||
m_bIsTeleporting(false),
|
||||
m_UUID((a_Client != nullptr) ? a_Client->GetUUID() : cUUID{}),
|
||||
m_SkinParts(0),
|
||||
m_MainHand(mhRight)
|
||||
{
|
||||
@ -129,22 +111,7 @@ cPlayer::cPlayer(const std::shared_ptr<cClientHandle> & a_Client) :
|
||||
m_Health = MAX_HEALTH;
|
||||
|
||||
cWorld * World = nullptr;
|
||||
if (!LoadFromDisk(World))
|
||||
{
|
||||
m_Inventory.Clear();
|
||||
SetPosX(World->GetSpawnX());
|
||||
SetPosY(World->GetSpawnY());
|
||||
SetPosZ(World->GetSpawnZ());
|
||||
|
||||
// This is a new player. Set the player spawn point to the spawn point of the default world
|
||||
SetBedPos(Vector3i(static_cast<int>(World->GetSpawnX()), static_cast<int>(World->GetSpawnY()), static_cast<int>(World->GetSpawnZ())), World);
|
||||
|
||||
m_EnchantmentSeed = GetRandomProvider().RandInt<unsigned int>(); // Use a random number to seed the enchantment generator
|
||||
|
||||
FLOGD("Player \"{0}\" is connecting for the first time, spawning at default world spawn {1:.2f}",
|
||||
GetName(), GetPosition()
|
||||
);
|
||||
}
|
||||
LoadFromDisk(World);
|
||||
|
||||
m_LastGroundHeight = static_cast<float>(GetPosY());
|
||||
m_Stance = GetPosY() + 1.62;
|
||||
@ -1734,70 +1701,30 @@ void cPlayer::TossPickup(const cItem & a_Item)
|
||||
|
||||
|
||||
|
||||
bool cPlayer::LoadFromDisk(cWorldPtr & a_World)
|
||||
void cPlayer::LoadFromDisk(cWorldPtr & a_World)
|
||||
{
|
||||
LoadRank();
|
||||
|
||||
const auto & UUID = GetUUID();
|
||||
|
||||
// Load from the UUID file:
|
||||
if (LoadFromFile(GetUUIDFileName(m_UUID), a_World))
|
||||
if (LoadFromFile(GetUUIDFileName(UUID), a_World))
|
||||
{
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for old offline UUID filename, if it exists migrate to new filename
|
||||
cUUID OfflineUUID = cClientHandle::GenerateOfflineUUID(GetName());
|
||||
auto OldFilename = GetUUIDFileName(GetOldStyleOfflineUUID(GetName()));
|
||||
auto NewFilename = GetUUIDFileName(m_UUID);
|
||||
// Only move if there isn't already a new file
|
||||
if (!cFile::IsFile(NewFilename) && cFile::IsFile(OldFilename))
|
||||
{
|
||||
cFile::CreateFolderRecursive(GetUUIDFolderName(m_UUID)); // Ensure folder exists to move to
|
||||
if (
|
||||
cFile::Rename(OldFilename, NewFilename) &&
|
||||
(m_UUID == OfflineUUID) &&
|
||||
LoadFromFile(NewFilename, a_World)
|
||||
)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Player not found:
|
||||
a_World = cRoot::Get()->GetDefaultWorld();
|
||||
LOG("Player \"%s\" (%s) data not found, resetting to defaults", GetName().c_str(), UUID.ToShortString().c_str());
|
||||
|
||||
// Load from the offline UUID file, if allowed:
|
||||
const char * OfflineUsage = " (unused)";
|
||||
if (cRoot::Get()->GetServer()->ShouldLoadOfflinePlayerData())
|
||||
{
|
||||
OfflineUsage = "";
|
||||
if (LoadFromFile(GetUUIDFileName(OfflineUUID), a_World))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
const Vector3i WorldSpawn(static_cast<int>(a_World->GetSpawnX()), static_cast<int>(a_World->GetSpawnY()), static_cast<int>(a_World->GetSpawnZ()));
|
||||
SetPosition(WorldSpawn);
|
||||
SetBedPos(WorldSpawn, a_World);
|
||||
|
||||
// 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, a_World))
|
||||
{
|
||||
// Save in new format and remove the old file
|
||||
if (SaveToDisk())
|
||||
{
|
||||
cFile::Delete(OldStyleFileName);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
m_Inventory.Clear();
|
||||
m_EnchantmentSeed = GetRandomProvider().RandInt<unsigned int>(); // Use a random number to seed the enchantment generator
|
||||
|
||||
// None of the files loaded successfully
|
||||
LOG("Player data file not found for %s (%s, offline %s%s), will be reset to defaults.",
|
||||
GetName().c_str(), m_UUID.ToShortString().c_str(), OfflineUUID.ToShortString().c_str(), OfflineUsage
|
||||
);
|
||||
|
||||
if (a_World == nullptr)
|
||||
{
|
||||
a_World = cRoot::Get()->GetDefaultWorld();
|
||||
}
|
||||
return false;
|
||||
FLOGD("Player \"{0}\" is connecting for the first time, spawning at default world spawn {1:.2f}", GetName(), GetPosition());
|
||||
}
|
||||
|
||||
|
||||
@ -1806,35 +1733,31 @@ bool cPlayer::LoadFromDisk(cWorldPtr & a_World)
|
||||
|
||||
bool cPlayer::LoadFromFile(const AString & a_FileName, cWorldPtr & a_World)
|
||||
{
|
||||
// Load the data from the file:
|
||||
cFile f;
|
||||
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\"", a_FileName.c_str());
|
||||
return false;
|
||||
}
|
||||
f.Close();
|
||||
Json::Value Root;
|
||||
|
||||
// Parse the JSON format:
|
||||
Json::Value root;
|
||||
AString ParseError;
|
||||
if (!JsonUtils::ParseString(buffer, root, &ParseError))
|
||||
try
|
||||
{
|
||||
FLOGWARNING(
|
||||
"Cannot parse player data in file \"{0}\":\n {1}",
|
||||
a_FileName, ParseError
|
||||
);
|
||||
return false;
|
||||
// Load the data from the file and parse:
|
||||
InputFileStream(a_FileName) >> Root;
|
||||
}
|
||||
catch (const Json::Exception & Oops)
|
||||
{
|
||||
// Parse failure:
|
||||
throw std::runtime_error(Oops.what());
|
||||
}
|
||||
catch (const InputFileStream::failure &)
|
||||
{
|
||||
if (errno == ENOENT)
|
||||
{
|
||||
// This is a new player whom we haven't seen yet, bail out, let them have the defaults:
|
||||
return false;
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
// Load the player data:
|
||||
Json::Value & JSON_PlayerPosition = root["position"];
|
||||
Json::Value & JSON_PlayerPosition = Root["position"];
|
||||
if (JSON_PlayerPosition.size() == 3)
|
||||
{
|
||||
SetPosX(JSON_PlayerPosition[0].asDouble());
|
||||
@ -1843,7 +1766,7 @@ bool cPlayer::LoadFromFile(const AString & a_FileName, cWorldPtr & a_World)
|
||||
m_LastPosition = GetPosition();
|
||||
}
|
||||
|
||||
Json::Value & JSON_PlayerRotation = root["rotation"];
|
||||
Json::Value & JSON_PlayerRotation = Root["rotation"];
|
||||
if (JSON_PlayerRotation.size() == 3)
|
||||
{
|
||||
SetYaw (static_cast<float>(JSON_PlayerRotation[0].asDouble()));
|
||||
@ -1851,18 +1774,18 @@ bool cPlayer::LoadFromFile(const AString & a_FileName, cWorldPtr & a_World)
|
||||
SetRoll (static_cast<float>(JSON_PlayerRotation[2].asDouble()));
|
||||
}
|
||||
|
||||
m_Health = root.get("health", 0).asFloat();
|
||||
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();
|
||||
m_FoodTickTimer = root.get("foodTickTimer", 0).asInt();
|
||||
m_FoodExhaustionLevel = root.get("foodExhaustion", 0).asDouble();
|
||||
m_LifetimeTotalXp = root.get("xpTotal", 0).asInt();
|
||||
m_CurrentXp = root.get("xpCurrent", 0).asInt();
|
||||
m_IsFlying = root.get("isflying", 0).asBool();
|
||||
m_EnchantmentSeed = root.get("enchantmentSeed", GetRandomProvider().RandInt<unsigned int>()).asUInt();
|
||||
m_Health = Root.get("health", 0).asFloat();
|
||||
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();
|
||||
m_FoodTickTimer = Root.get("foodTickTimer", 0).asInt();
|
||||
m_FoodExhaustionLevel = Root.get("foodExhaustion", 0).asDouble();
|
||||
m_LifetimeTotalXp = Root.get("xpTotal", 0).asInt();
|
||||
m_CurrentXp = Root.get("xpCurrent", 0).asInt();
|
||||
m_IsFlying = Root.get("isflying", 0).asBool();
|
||||
m_EnchantmentSeed = Root.get("enchantmentSeed", GetRandomProvider().RandInt<unsigned int>()).asUInt();
|
||||
|
||||
Json::Value & JSON_KnownItems = root["knownItems"];
|
||||
Json::Value & JSON_KnownItems = Root["knownItems"];
|
||||
for (UInt32 i = 0; i < JSON_KnownItems.size(); i++)
|
||||
{
|
||||
cItem Item;
|
||||
@ -1872,7 +1795,7 @@ bool cPlayer::LoadFromFile(const AString & a_FileName, cWorldPtr & a_World)
|
||||
|
||||
const auto & RecipeNameMap = cRoot::Get()->GetCraftingRecipes()->GetRecipeNameMap();
|
||||
|
||||
Json::Value & JSON_KnownRecipes = root["knownRecipes"];
|
||||
Json::Value & JSON_KnownRecipes = Root["knownRecipes"];
|
||||
for (UInt32 i = 0; i < JSON_KnownRecipes.size(); i++)
|
||||
{
|
||||
auto RecipeId = RecipeNameMap.find(JSON_KnownRecipes[i].asString());
|
||||
@ -1882,21 +1805,21 @@ bool cPlayer::LoadFromFile(const AString & a_FileName, cWorldPtr & a_World)
|
||||
}
|
||||
}
|
||||
|
||||
m_GameMode = static_cast<eGameMode>(root.get("gamemode", eGameMode_NotSet).asInt());
|
||||
m_GameMode = static_cast<eGameMode>(Root.get("gamemode", eGameMode_NotSet).asInt());
|
||||
|
||||
if (m_GameMode == eGameMode_Creative)
|
||||
{
|
||||
m_CanFly = true;
|
||||
}
|
||||
|
||||
m_Inventory.LoadFromJson(root["inventory"]);
|
||||
m_Inventory.LoadFromJson(Root["inventory"]);
|
||||
|
||||
int equippedSlotNum = root.get("equippedItemSlot", 0).asInt();
|
||||
int equippedSlotNum = Root.get("equippedItemSlot", 0).asInt();
|
||||
m_Inventory.SetEquippedSlotNum(equippedSlotNum);
|
||||
|
||||
cEnderChestEntity::LoadFromJson(root["enderchestinventory"], m_EnderChestContents);
|
||||
cEnderChestEntity::LoadFromJson(Root["enderchestinventory"], m_EnderChestContents);
|
||||
|
||||
m_CurrentWorldName = root.get("world", "world").asString();
|
||||
m_CurrentWorldName = Root.get("world", "world").asString();
|
||||
a_World = cRoot::Get()->GetWorld(GetLoadedWorldName());
|
||||
if (a_World == nullptr)
|
||||
{
|
||||
@ -1904,10 +1827,10 @@ bool cPlayer::LoadFromFile(const AString & a_FileName, cWorldPtr & a_World)
|
||||
}
|
||||
|
||||
|
||||
m_LastBedPos.x = root.get("SpawnX", a_World->GetSpawnX()).asInt();
|
||||
m_LastBedPos.y = root.get("SpawnY", a_World->GetSpawnY()).asInt();
|
||||
m_LastBedPos.z = root.get("SpawnZ", a_World->GetSpawnZ()).asInt();
|
||||
m_SpawnWorldName = root.get("SpawnWorld", cRoot::Get()->GetDefaultWorld()->GetName()).asString();
|
||||
m_LastBedPos.x = Root.get("SpawnX", a_World->GetSpawnX()).asInt();
|
||||
m_LastBedPos.y = Root.get("SpawnY", a_World->GetSpawnY()).asInt();
|
||||
m_LastBedPos.z = Root.get("SpawnZ", a_World->GetSpawnZ()).asInt();
|
||||
m_SpawnWorldName = Root.get("SpawnWorld", cRoot::Get()->GetDefaultWorld()->GetName()).asString();
|
||||
|
||||
try
|
||||
{
|
||||
@ -1960,9 +1883,10 @@ void cPlayer::OpenHorseInventory()
|
||||
|
||||
|
||||
|
||||
bool cPlayer::SaveToDisk()
|
||||
void cPlayer::SaveToDisk()
|
||||
{
|
||||
cFile::CreateFolderRecursive(GetUUIDFolderName(m_UUID));
|
||||
const auto & UUID = GetUUID();
|
||||
cFile::CreateFolderRecursive(GetUUIDFolderName(UUID));
|
||||
|
||||
// create the JSON data
|
||||
Json::Value JSON_PlayerPosition;
|
||||
@ -2023,22 +1947,22 @@ bool cPlayer::SaveToDisk()
|
||||
root["gamemode"] = static_cast<int>(m_GameMode);
|
||||
|
||||
auto JsonData = JsonUtils::WriteStyledString(root);
|
||||
AString SourceFile = GetUUIDFileName(m_UUID);
|
||||
AString SourceFile = GetUUIDFileName(UUID);
|
||||
|
||||
cFile f;
|
||||
if (!f.Open(SourceFile, cFile::fmWrite))
|
||||
{
|
||||
LOGWARNING("Error writing player \"%s\" to file \"%s\" - cannot open file. Player will lose their progress.",
|
||||
LOGWARNING("Error writing player \"%s\" to file \"%s\": cannot open file. Player will lose their progress",
|
||||
GetName().c_str(), SourceFile.c_str()
|
||||
);
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
if (f.Write(JsonData.c_str(), JsonData.size()) != static_cast<int>(JsonData.size()))
|
||||
{
|
||||
LOGWARNING("Error writing player \"%s\" to file \"%s\" - cannot save data. Player will lose their progress. ",
|
||||
LOGWARNING("Error writing player \"%s\" to file \"%s\": cannot save data. Player will lose their progress",
|
||||
GetName().c_str(), SourceFile.c_str()
|
||||
);
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
@ -2050,11 +1974,8 @@ bool cPlayer::SaveToDisk()
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOGWARNING("Could not save stats for player %s", GetName().c_str());
|
||||
return false;
|
||||
LOGWARNING("Error writing player \"%s\" statistics to file", GetName().c_str());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -2316,9 +2237,11 @@ void cPlayer::UpdateMovementStats(const Vector3d & a_DeltaPos, bool a_PreviousIs
|
||||
|
||||
void cPlayer::LoadRank(void)
|
||||
{
|
||||
// Load the values from cRankManager:
|
||||
const auto & UUID = GetUUID();
|
||||
cRankManager * RankMgr = cRoot::Get()->GetRankManager();
|
||||
m_Rank = RankMgr->GetPlayerRankName(m_UUID);
|
||||
|
||||
// Load the values from cRankManager:
|
||||
m_Rank = RankMgr->GetPlayerRankName(UUID);
|
||||
if (m_Rank.empty())
|
||||
{
|
||||
m_Rank = RankMgr->GetDefaultRank();
|
||||
@ -2326,10 +2249,10 @@ void cPlayer::LoadRank(void)
|
||||
else
|
||||
{
|
||||
// Update the name:
|
||||
RankMgr->UpdatePlayerName(m_UUID, GetName());
|
||||
RankMgr->UpdatePlayerName(UUID, GetName());
|
||||
}
|
||||
m_Permissions = RankMgr->GetPlayerPermissions(m_UUID);
|
||||
m_Restrictions = RankMgr->GetPlayerRestrictions(m_UUID);
|
||||
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:
|
||||
@ -2469,6 +2392,15 @@ bool cPlayer::DoesPlacingBlocksIntersectEntity(const sSetBlockVector & a_Blocks)
|
||||
|
||||
|
||||
|
||||
const cUUID & cPlayer::GetUUID(void) const
|
||||
{
|
||||
return m_ClientHandle->GetUUID();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cPlayer::PlaceBlocks(const sSetBlockVector & a_Blocks)
|
||||
{
|
||||
if (DoesPlacingBlocksIntersectEntity(a_Blocks))
|
||||
|
@ -379,21 +379,18 @@ public:
|
||||
void SetVisible( bool a_bVisible); // tolua_export
|
||||
bool IsVisible(void) const { return m_bVisible; } // tolua_export
|
||||
|
||||
/** Saves all player data, such as inventory, to JSON */
|
||||
bool SaveToDisk(void);
|
||||
/** Saves all player data, such as inventory, to JSON. */
|
||||
void SaveToDisk(void);
|
||||
|
||||
typedef cWorld * cWorldPtr;
|
||||
|
||||
/** Loads the player data from the disk file
|
||||
Sets a_World to the world where the player will spawn, based on the stored world name or the default world by calling LoadFromFile()
|
||||
Returns true on success, false on failure
|
||||
*/
|
||||
bool LoadFromDisk(cWorldPtr & a_World);
|
||||
/** Loads the player data from the disk file.
|
||||
Sets a_World to the world where the player will spawn, based on the stored world name or the default world by calling LoadFromFile(). */
|
||||
void LoadFromDisk(cWorldPtr & a_World);
|
||||
|
||||
/** Loads the player data from the specified file
|
||||
Sets a_World to the world where the player will spawn, based on the stored world name or the default world
|
||||
Returns true on success, false on failure
|
||||
*/
|
||||
/** Loads the player data from the specified file.
|
||||
Sets a_World to the world where the player will spawn, based on the stored world name or the default world.
|
||||
Returns true on success, false if the player wasn't found, and excepts with base std::runtime_error if the data couldn't be read or parsed. */
|
||||
bool LoadFromFile(const AString & a_FileName, cWorldPtr & a_World);
|
||||
|
||||
const AString & GetLoadedWorldName() const { return m_CurrentWorldName; }
|
||||
@ -499,7 +496,7 @@ public:
|
||||
bool DoesPlacingBlocksIntersectEntity(const sSetBlockVector & a_Blocks);
|
||||
|
||||
/** Returns the UUID that has been read from the client, or nil if not available. */
|
||||
const cUUID & GetUUID(void) const { return m_UUID; } // Exported in ManualBindings.cpp
|
||||
const cUUID & GetUUID(void) const; // Exported in ManualBindings.cpp
|
||||
|
||||
// tolua_begin
|
||||
|
||||
@ -507,7 +504,6 @@ public:
|
||||
virtual bool CanFly(void) const { return m_CanFly; }
|
||||
|
||||
/** (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);
|
||||
|
||||
@ -718,10 +714,6 @@ private:
|
||||
*/
|
||||
bool m_bIsTeleporting;
|
||||
|
||||
/** The UUID of the player, as read from the ClientHandle.
|
||||
If no ClientHandle is given, the UUID is nil. */
|
||||
cUUID m_UUID;
|
||||
|
||||
AString m_CustomName;
|
||||
|
||||
/** Displayed skin part bit mask */
|
||||
|
@ -117,9 +117,7 @@ cServer::cServer(void) :
|
||||
m_MaxPlayers(0),
|
||||
m_bIsHardcore(false),
|
||||
m_TickThread(*this),
|
||||
m_ShouldAuthenticate(false),
|
||||
m_ShouldLoadOfflinePlayerData(false),
|
||||
m_ShouldLoadNamedPlayerData(true)
|
||||
m_ShouldAuthenticate(false)
|
||||
{
|
||||
// Initialize the LuaStateTracker singleton before the app goes multithreaded:
|
||||
cLuaStateTracker::GetStats();
|
||||
@ -206,8 +204,6 @@ bool cServer::InitServer(cSettingsRepositoryInterface & a_Settings, bool a_Shoul
|
||||
|
||||
m_ShouldAllowMultiWorldTabCompletion = a_Settings.GetValueSetB("Server", "AllowMultiWorldTabCompletion", true);
|
||||
m_ShouldLimitPlayerBlockChanges = a_Settings.GetValueSetB("AntiCheat", "LimitPlayerBlockChanges", true);
|
||||
m_ShouldLoadOfflinePlayerData = a_Settings.GetValueSetB("PlayerData", "LoadOfflinePlayerData", false);
|
||||
m_ShouldLoadNamedPlayerData = a_Settings.GetValueSetB("PlayerData", "LoadNamedPlayerData", true);
|
||||
|
||||
const auto ClientViewDistance = a_Settings.GetValueSetI("Server", "DefaultViewDistance", cClientHandle::DEFAULT_VIEW_DISTANCE);
|
||||
if (ClientViewDistance < cClientHandle::MIN_VIEW_DISTANCE)
|
||||
|
19
src/Server.h
19
src/Server.h
@ -141,15 +141,6 @@ public:
|
||||
/** Returns true if limit for number of block changes per tick by a player has been turned on in server settings. */
|
||||
bool ShouldLimitPlayerBlockChanges(void) const { return m_ShouldLimitPlayerBlockChanges; }
|
||||
|
||||
/** Returns true if offline UUIDs should be used to load data for players whose normal UUIDs cannot be found.
|
||||
Loaded from the settings.ini [PlayerData].LoadOfflinePlayerData setting. */
|
||||
bool ShouldLoadOfflinePlayerData(void) const { return m_ShouldLoadOfflinePlayerData; }
|
||||
|
||||
/** Returns true if old-style playernames should be used to load data for players whose regular datafiles cannot be found.
|
||||
This allows a seamless transition from name-based to UUID-based player storage.
|
||||
Loaded from the settings.ini [PlayerData].LoadNamedPlayerData setting. */
|
||||
bool ShouldLoadNamedPlayerData(void) const { return m_ShouldLoadNamedPlayerData; }
|
||||
|
||||
/** Returns true if BungeeCord logins (that specify the player's UUID) are allowed.
|
||||
Read from settings, admins should set this to true only when they chain to BungeeCord,
|
||||
it makes the server vulnerable to identity theft through direct connections. */
|
||||
@ -243,16 +234,6 @@ private:
|
||||
/** True if limit for number of block changes per tick by a player should be enabled. */
|
||||
bool m_ShouldLimitPlayerBlockChanges;
|
||||
|
||||
/** True if offline UUIDs should be used to load data for players whose normal UUIDs cannot be found.
|
||||
This allows transitions from an offline (no-auth) server to an online one.
|
||||
Loaded from the settings.ini [PlayerData].LoadOfflinePlayerData setting. */
|
||||
bool m_ShouldLoadOfflinePlayerData;
|
||||
|
||||
/** True if old-style playernames should be used to load data for players whose regular datafiles cannot be found.
|
||||
This allows a seamless transition from name-based to UUID-based player storage.
|
||||
Loaded from the settings.ini [PlayerData].LoadNamedPlayerData setting. */
|
||||
bool m_ShouldLoadNamedPlayerData;
|
||||
|
||||
/** True if BungeeCord handshake packets (with player UUID) should be accepted. */
|
||||
bool m_ShouldAllowBungeeCord;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user