1
0

Fix gamemode not changing properly.

Should fix #604
This commit is contained in:
Alexander Harkness 2015-05-23 19:31:33 +01:00
parent 7e0dc0f9bc
commit febc8529b1
2 changed files with 154 additions and 148 deletions

View File

@ -94,7 +94,7 @@ cPlayer::cPlayer(cClientHandlePtr a_Client, const AString & a_PlayerName) :
SetMaxHealth(MAX_HEALTH); SetMaxHealth(MAX_HEALTH);
m_Health = MAX_HEALTH; m_Health = MAX_HEALTH;
m_LastPlayerListTime = std::chrono::steady_clock::now(); m_LastPlayerListTime = std::chrono::steady_clock::now();
m_PlayerName = a_PlayerName; m_PlayerName = a_PlayerName;
@ -106,7 +106,7 @@ cPlayer::cPlayer(cClientHandlePtr a_Client, const AString & a_PlayerName) :
SetPosY(World->GetSpawnY()); SetPosY(World->GetSpawnY());
SetPosZ(World->GetSpawnZ()); SetPosZ(World->GetSpawnZ());
SetBedPos(Vector3i(static_cast<int>(World->GetSpawnX()), static_cast<int>(World->GetSpawnY()), static_cast<int>(World->GetSpawnZ()))); SetBedPos(Vector3i(static_cast<int>(World->GetSpawnX()), static_cast<int>(World->GetSpawnY()), static_cast<int>(World->GetSpawnZ())));
LOGD("Player \"%s\" is connecting for the first time, spawning at default world spawn {%.2f, %.2f, %.2f}", LOGD("Player \"%s\" is connecting for the first time, spawning at default world spawn {%.2f, %.2f, %.2f}",
a_PlayerName.c_str(), GetPosX(), GetPosY(), GetPosZ() a_PlayerName.c_str(), GetPosX(), GetPosY(), GetPosZ()
); );
@ -135,7 +135,7 @@ cPlayer::cPlayer(cClientHandlePtr a_Client, const AString & a_PlayerName) :
m_IsFlying = true; m_IsFlying = true;
m_bVisible = false; m_bVisible = false;
} }
cRoot::Get()->GetServer()->PlayerCreated(this); cRoot::Get()->GetServer()->PlayerCreated(this);
} }
@ -152,17 +152,17 @@ cPlayer::~cPlayer(void)
} }
LOGD("Deleting cPlayer \"%s\" at %p, ID %d", GetName().c_str(), this, GetUniqueID()); LOGD("Deleting cPlayer \"%s\" at %p, ID %d", GetName().c_str(), this, GetUniqueID());
// Notify the server that the player is being destroyed // Notify the server that the player is being destroyed
cRoot::Get()->GetServer()->PlayerDestroying(this); cRoot::Get()->GetServer()->PlayerDestroying(this);
SaveToDisk(); SaveToDisk();
m_ClientHandle = nullptr; m_ClientHandle = nullptr;
delete m_InventoryWindow; delete m_InventoryWindow;
m_InventoryWindow = nullptr; m_InventoryWindow = nullptr;
LOGD("Player %p deleted", this); LOGD("Player %p deleted", this);
} }
@ -208,7 +208,7 @@ void cPlayer::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
m_ClientHandle = nullptr; m_ClientHandle = nullptr;
return; return;
} }
if (!m_ClientHandle->IsPlaying()) if (!m_ClientHandle->IsPlaying())
{ {
// We're not yet in the game, ignore everything // We're not yet in the game, ignore everything
@ -217,21 +217,21 @@ void cPlayer::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
} }
m_Stats.AddValue(statMinutesPlayed, 1); m_Stats.AddValue(statMinutesPlayed, 1);
if (!a_Chunk.IsValid()) if (!a_Chunk.IsValid())
{ {
// This may happen if the cPlayer is created before the chunks have the chance of being loaded / generated (#83) // This may happen if the cPlayer is created before the chunks have the chance of being loaded / generated (#83)
return; return;
} }
super::Tick(a_Dt, a_Chunk); super::Tick(a_Dt, a_Chunk);
// Handle charging the bow: // Handle charging the bow:
if (m_IsChargingBow) if (m_IsChargingBow)
{ {
m_BowCharge += 1; m_BowCharge += 1;
} }
// Handle updating experience // Handle updating experience
if (m_bDirtyExperience) if (m_bDirtyExperience)
{ {
@ -243,7 +243,7 @@ void cPlayer::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{ {
// Apply food exhaustion from movement: // Apply food exhaustion from movement:
ApplyFoodExhaustionFromMovement(); ApplyFoodExhaustionFromMovement();
if (cRoot::Get()->GetPluginManager()->CallHookPlayerMoving(*this, m_LastPos, GetPosition())) if (cRoot::Get()->GetPluginManager()->CallHookPlayerMoving(*this, m_LastPos, GetPosition()))
{ {
CanMove = false; CanMove = false;
@ -264,10 +264,10 @@ void cPlayer::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{ {
FinishEating(); FinishEating();
} }
HandleFood(); HandleFood();
} }
if (m_IsFishing) if (m_IsFishing)
{ {
HandleFloater(); HandleFloater();
@ -467,7 +467,7 @@ void cPlayer::SetTouchGround(bool a_bTouchGround)
{ {
return; return;
} }
m_bTouchGround = a_bTouchGround; m_bTouchGround = a_bTouchGround;
if (!m_bTouchGround) if (!m_bTouchGround)
@ -516,7 +516,7 @@ void cPlayer::SetTouchGround(bool a_bTouchGround)
{ {
// cPlayer makes sure damage isn't applied in creative, no need to check here // cPlayer makes sure damage isn't applied in creative, no need to check here
TakeDamage(dtFalling, nullptr, Damage, Damage, 0); TakeDamage(dtFalling, nullptr, Damage, Damage, 0);
// Fall particles // Fall particles
GetWorld()->BroadcastSoundParticleEffect(2006, POSX_TOINT, static_cast<int>(GetPosY()) - 1, POSZ_TOINT, Damage /* Used as particle effect speed modifier */); GetWorld()->BroadcastSoundParticleEffect(2006, POSX_TOINT, static_cast<int>(GetPosY()) - 1, POSZ_TOINT, Damage /* Used as particle effect speed modifier */);
} }
@ -548,7 +548,7 @@ void cPlayer::SetFoodLevel(int a_FoodLevel)
m_FoodSaturationLevel = 5.0; m_FoodSaturationLevel = 5.0;
return; return;
} }
m_FoodLevel = FoodLevel; m_FoodLevel = FoodLevel;
SendHealth(); SendHealth();
} }
@ -616,7 +616,7 @@ void cPlayer::StartEating(void)
{ {
// Set the timer: // Set the timer:
m_EatingFinishTick = m_World->GetWorldAge() + EATING_TICKS; m_EatingFinishTick = m_World->GetWorldAge() + EATING_TICKS;
// Send the packets: // Send the packets:
m_World->BroadcastEntityAnimation(*this, 3); m_World->BroadcastEntityAnimation(*this, 3);
m_World->BroadcastEntityMetadata(*this); m_World->BroadcastEntityMetadata(*this);
@ -630,7 +630,7 @@ void cPlayer::FinishEating(void)
{ {
// Reset the timer: // Reset the timer:
m_EatingFinishTick = -1; m_EatingFinishTick = -1;
// Send the packets: // Send the packets:
m_ClientHandle->SendEntityStatus(*this, esPlayerEatingAccepted); m_ClientHandle->SendEntityStatus(*this, esPlayerEatingAccepted);
m_World->BroadcastEntityMetadata(*this); m_World->BroadcastEntityMetadata(*this);
@ -764,7 +764,7 @@ void cPlayer::SetSprintingMaxSpeed(double a_Speed)
void cPlayer::SetFlyingMaxSpeed(double a_Speed) void cPlayer::SetFlyingMaxSpeed(double a_Speed)
{ {
m_FlyingMaxSpeed = a_Speed; m_FlyingMaxSpeed = a_Speed;
// Update the flying speed, always: // Update the flying speed, always:
m_ClientHandle->SendPlayerAbilities(); m_ClientHandle->SendPlayerAbilities();
} }
@ -776,7 +776,7 @@ void cPlayer::SetFlyingMaxSpeed(double a_Speed)
void cPlayer::SetCrouch(bool a_IsCrouched) void cPlayer::SetCrouch(bool a_IsCrouched)
{ {
// Set the crouch status, broadcast to all visible players // Set the crouch status, broadcast to all visible players
if (a_IsCrouched == m_IsCrouched) if (a_IsCrouched == m_IsCrouched)
{ {
// No change // No change
@ -797,7 +797,7 @@ void cPlayer::SetSprint(bool a_IsSprinting)
// No change // No change
return; return;
} }
m_IsSprinting = a_IsSprinting; m_IsSprinting = a_IsSprinting;
m_ClientHandle->SendPlayerMaxSpeed(); m_ClientHandle->SendPlayerMaxSpeed();
} }
@ -883,7 +883,7 @@ bool cPlayer::DoTakeDamage(TakeDamageInfo & a_TDI)
} }
} }
} }
if (super::DoTakeDamage(a_TDI)) if (super::DoTakeDamage(a_TDI))
{ {
// Any kind of damage adds food exhaustion // Any kind of damage adds food exhaustion
@ -1012,7 +1012,7 @@ void cPlayer::Respawn(void)
m_Health = GetMaxHealth(); m_Health = GetMaxHealth();
SetInvulnerableTicks(20); SetInvulnerableTicks(20);
// Reset food level: // Reset food level:
m_FoodLevel = MAX_FOOD_LEVEL; m_FoodLevel = MAX_FOOD_LEVEL;
m_FoodSaturationLevel = 5.0; m_FoodSaturationLevel = 5.0;
@ -1024,7 +1024,7 @@ void cPlayer::Respawn(void)
// ToDo: send score to client? How? // ToDo: send score to client? How?
m_ClientHandle->SendRespawn(GetWorld()->GetDimension(), true); m_ClientHandle->SendRespawn(GetWorld()->GetDimension(), true);
// Extinguish the fire: // Extinguish the fire:
StopBurning(); StopBurning();
@ -1158,7 +1158,7 @@ void cPlayer::CloseWindow(bool a_CanRefuse)
m_CurrentWindow = m_InventoryWindow; m_CurrentWindow = m_InventoryWindow;
return; return;
} }
if (m_CurrentWindow->ClosedByPlayer(*this, a_CanRefuse) || !a_CanRefuse) if (m_CurrentWindow->ClosedByPlayer(*this, a_CanRefuse) || !a_CanRefuse)
{ {
// Close accepted, go back to inventory window (the default): // Close accepted, go back to inventory window (the default):
@ -1196,30 +1196,17 @@ void cPlayer::SetGameMode(eGameMode a_GameMode)
LOGWARNING("%s: Setting invalid gamemode: %d", GetName().c_str(), a_GameMode); LOGWARNING("%s: Setting invalid gamemode: %d", GetName().c_str(), a_GameMode);
return; return;
} }
if (m_GameMode == a_GameMode) if (m_GameMode == a_GameMode)
{ {
// Gamemode already set // Gamemode already set
return; return;
} }
m_GameMode = a_GameMode; m_GameMode = a_GameMode;
m_ClientHandle->SendGameMode(a_GameMode); m_ClientHandle->SendGameMode(a_GameMode);
if (!(IsGameModeCreative() || IsGameModeSpectator())) SetCapabilities();
{
SetFlying(false);
SetCanFly(false);
}
if (IsGameModeSpectator() && IsVisible())
{
SetVisible(false);
}
else if (!IsVisible())
{
SetVisible(true);
}
m_World->BroadcastPlayerListUpdateGameMode(*this); m_World->BroadcastPlayerListUpdateGameMode(*this);
} }
@ -1231,6 +1218,30 @@ void cPlayer::SetGameMode(eGameMode a_GameMode)
void cPlayer::LoginSetGameMode( eGameMode a_GameMode) void cPlayer::LoginSetGameMode( eGameMode a_GameMode)
{ {
m_GameMode = a_GameMode; m_GameMode = a_GameMode;
SetCapabilities();
}
void cPlayer::SetCapabilities()
{
if (!IsGameModeCreative() || IsGameModeSpectator())
{
SetFlying(false);
SetCanFly(false);
}
if (IsGameModeSpectator())
{
SetVisible(false);
}
else
{
SetVisible(true);
}
} }
@ -1322,12 +1333,12 @@ void cPlayer::SendRotation(double a_YawDegrees, double a_PitchDegrees)
Vector3d cPlayer::GetThrowStartPos(void) const Vector3d cPlayer::GetThrowStartPos(void) const
{ {
Vector3d res = GetEyePosition(); Vector3d res = GetEyePosition();
// Adjust the position to be just outside the player's bounding box: // Adjust the position to be just outside the player's bounding box:
res.x += 0.16 * cos(GetPitch()); res.x += 0.16 * cos(GetPitch());
res.y += -0.1; res.y += -0.1;
res.z += 0.16 * sin(GetPitch()); res.z += 0.16 * sin(GetPitch());
return res; return res;
} }
@ -1339,9 +1350,9 @@ Vector3d cPlayer::GetThrowSpeed(double a_SpeedCoeff) const
{ {
Vector3d res = GetLookVector(); Vector3d res = GetLookVector();
res.Normalize(); res.Normalize();
// TODO: Add a slight random change (+-0.0075 in each direction) // TODO: Add a slight random change (+-0.0075 in each direction)
return res * a_SpeedCoeff; return res * a_SpeedCoeff;
} }
@ -1386,13 +1397,13 @@ void cPlayer::MoveTo( const Vector3d & a_NewPos)
} }
return; return;
} }
// TODO: should do some checks to see if player is not moving through terrain // TODO: should do some checks to see if player is not moving through terrain
// TODO: Official server refuses position packets too far away from each other, kicking "hacked" clients; we should, too // TODO: Official server refuses position packets too far away from each other, kicking "hacked" clients; we should, too
Vector3d DeltaPos = a_NewPos - GetPosition(); Vector3d DeltaPos = a_NewPos - GetPosition();
UpdateMovementStats(DeltaPos); UpdateMovementStats(DeltaPos);
SetPosition( a_NewPos); SetPosition( a_NewPos);
SetStance(a_NewPos.y + 1.62); SetStance(a_NewPos.y + 1.62);
} }
@ -1427,7 +1438,7 @@ bool cPlayer::HasPermission(const AString & a_Permission)
// Empty permission request is always granted // Empty permission request is always granted
return true; return true;
} }
AStringVector Split = StringSplit(a_Permission, "."); AStringVector Split = StringSplit(a_Permission, ".");
// Iterate over all restrictions; if any matches, then return failure: // Iterate over all restrictions; if any matches, then return failure:
@ -1599,7 +1610,7 @@ void cPlayer::TossItems(const cItems & a_Items)
{ {
return; return;
} }
m_Stats.AddValue(statItemsDropped, (StatValue)a_Items.Size()); m_Stats.AddValue(statItemsDropped, (StatValue)a_Items.Size());
double vX = 0, vY = 0, vZ = 0; double vX = 0, vY = 0, vZ = 0;
@ -1621,7 +1632,7 @@ bool cPlayer::DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn)
// Don't move to same world // Don't move to same world
return false; return false;
} }
// Ask the plugins if the player is allowed to changing the world // Ask the plugins if the player is allowed to changing the world
if (cRoot::Get()->GetPluginManager()->CallHookEntityChangingWorld(*this, *a_World)) if (cRoot::Get()->GetPluginManager()->CallHookEntityChangingWorld(*this, *a_World))
{ {
@ -1658,7 +1669,7 @@ bool cPlayer::DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn)
// Broadcast the player into the new world. // Broadcast the player into the new world.
a_World->BroadcastSpawnEntity(*this); a_World->BroadcastSpawnEntity(*this);
// Player changed the world, call the hook // Player changed the world, call the hook
cRoot::Get()->GetPluginManager()->CallHookEntityChangedWorld(*this, *OldWorld); cRoot::Get()->GetPluginManager()->CallHookEntityChangedWorld(*this, *OldWorld);
@ -1678,7 +1689,7 @@ bool cPlayer::LoadFromDisk(cWorldPtr & a_World)
{ {
return true; return true;
} }
// Load from the offline UUID file, if allowed: // Load from the offline UUID file, if allowed:
AString OfflineUUID = cClientHandle::GenerateOfflineUUID(GetName()); AString OfflineUUID = cClientHandle::GenerateOfflineUUID(GetName());
const char * OfflineUsage = " (unused)"; const char * OfflineUsage = " (unused)";
@ -1690,7 +1701,7 @@ bool cPlayer::LoadFromDisk(cWorldPtr & a_World)
return true; return true;
} }
} }
// Load from the old-style name-based file, if allowed: // Load from the old-style name-based file, if allowed:
if (cRoot::Get()->GetServer()->ShouldLoadNamedPlayerData()) if (cRoot::Get()->GetServer()->ShouldLoadNamedPlayerData())
{ {
@ -1705,7 +1716,7 @@ bool cPlayer::LoadFromDisk(cWorldPtr & a_World)
return true; return true;
} }
} }
// None of the files loaded successfully // None of the files loaded successfully
LOG("Player data file not found for %s (%s, offline %s%s), will be reset to defaults.", LOG("Player data file not found for %s (%s, offline %s%s), will be reset to defaults.",
GetName().c_str(), m_UUID.c_str(), OfflineUUID.c_str(), OfflineUsage GetName().c_str(), m_UUID.c_str(), OfflineUUID.c_str(), OfflineUsage
@ -1782,7 +1793,7 @@ bool cPlayer::LoadFromFile(const AString & a_FileName, cWorldPtr & a_World)
{ {
m_CanFly = true; m_CanFly = true;
} }
m_Inventory.LoadFromJson(root["inventory"]); m_Inventory.LoadFromJson(root["inventory"]);
cEnderChestEntity::LoadFromJson(root["enderchestinventory"], m_EnderChestContents); cEnderChestEntity::LoadFromJson(root["enderchestinventory"], m_EnderChestContents);
@ -1801,11 +1812,11 @@ bool cPlayer::LoadFromFile(const AString & a_FileName, cWorldPtr & a_World)
// 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(), GetName(), &m_Stats); cStatSerializer StatSerializer(cRoot::Get()->GetDefaultWorld()->GetName(), GetName(), &m_Stats);
StatSerializer.Load(); StatSerializer.Load();
LOGD("Player %s was read from file \"%s\", spawning at {%.2f, %.2f, %.2f} in world \"%s\"", 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(), a_World->GetName().c_str() GetName().c_str(), a_FileName.c_str(), GetPosX(), GetPosY(), GetPosZ(), a_World->GetName().c_str()
); );
return true; return true;
} }
@ -2161,7 +2172,7 @@ void cPlayer::ApplyFoodExhaustionFromMovement()
{ {
return; return;
} }
// Calculate the distance travelled, update the last pos: // Calculate the distance travelled, update the last pos:
Vector3d Movement(GetPosition() - m_LastPos); Vector3d Movement(GetPosition() - m_LastPos);
Movement.y = 0; // Only take XZ movement into account Movement.y = 0; // Only take XZ movement into account
@ -2364,7 +2375,7 @@ AString cPlayer::GetUUIDFileName(const AString & a_UUID)
{ {
AString UUID = cMojangAPI::MakeUUIDDashed(a_UUID); AString UUID = cMojangAPI::MakeUUIDDashed(a_UUID);
ASSERT(UUID.length() == 36); ASSERT(UUID.length() == 36);
AString res("players/"); AString res("players/");
res.append(UUID, 0, 2); res.append(UUID, 0, 2);
res.push_back('/'); res.push_back('/');
@ -2372,7 +2383,3 @@ AString cPlayer::GetUUIDFileName(const AString & a_UUID)
res.append(".json"); res.append(".json");
return res; return res;
} }

View File

@ -26,42 +26,42 @@ class cPlayer :
public cPawn public cPawn
{ {
typedef cPawn super; typedef cPawn super;
public: public:
static const int MAX_HEALTH; static const int MAX_HEALTH;
static const int MAX_FOOD_LEVEL; static const int MAX_FOOD_LEVEL;
/** Number of ticks it takes to eat an item */ /** Number of ticks it takes to eat an item */
static const int EATING_TICKS; static const int EATING_TICKS;
// tolua_end // tolua_end
CLASS_PROTODEF(cPlayer) CLASS_PROTODEF(cPlayer)
cPlayer(cClientHandlePtr a_Client, const AString & a_PlayerName); cPlayer(cClientHandlePtr a_Client, const AString & a_PlayerName);
virtual ~cPlayer(); virtual ~cPlayer();
virtual void SpawnOn(cClientHandle & a_Client) override; virtual void SpawnOn(cClientHandle & a_Client) override;
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
virtual void HandlePhysics(std::chrono::milliseconds a_Dt, cChunk &) override { UNUSED(a_Dt); } virtual void HandlePhysics(std::chrono::milliseconds a_Dt, cChunk &) override { UNUSED(a_Dt); }
/** Returns the curently equipped weapon; empty item if none */ /** Returns the curently equipped weapon; empty item if none */
virtual cItem GetEquippedWeapon(void) const override { return m_Inventory.GetEquippedItem(); } virtual cItem GetEquippedWeapon(void) const override { return m_Inventory.GetEquippedItem(); }
/** Returns the currently equipped helmet; empty item if none */ /** Returns the currently equipped helmet; empty item if none */
virtual cItem GetEquippedHelmet(void) const override { return m_Inventory.GetEquippedHelmet(); } virtual cItem GetEquippedHelmet(void) const override { return m_Inventory.GetEquippedHelmet(); }
/** Returns the currently equipped chestplate; empty item if none */ /** Returns the currently equipped chestplate; empty item if none */
virtual cItem GetEquippedChestplate(void) const override { return m_Inventory.GetEquippedChestplate(); } virtual cItem GetEquippedChestplate(void) const override { return m_Inventory.GetEquippedChestplate(); }
/** Returns the currently equipped leggings; empty item if none */ /** Returns the currently equipped leggings; empty item if none */
virtual cItem GetEquippedLeggings(void) const override { return m_Inventory.GetEquippedLeggings(); } virtual cItem GetEquippedLeggings(void) const override { return m_Inventory.GetEquippedLeggings(); }
/** Returns the currently equipped boots; empty item if none */ /** Returns the currently equipped boots; empty item if none */
virtual cItem GetEquippedBoots(void) const override { return m_Inventory.GetEquippedBoots(); } virtual cItem GetEquippedBoots(void) const override { return m_Inventory.GetEquippedBoots(); }
@ -104,16 +104,16 @@ public:
static int CalcLevelFromXp(int a_CurrentXp); static int CalcLevelFromXp(int a_CurrentXp);
// tolua_end // tolua_end
/** Starts charging the equipped bow */ /** Starts charging the equipped bow */
void StartChargingBow(void); void StartChargingBow(void);
/** Finishes charging the current bow. Returns the number of ticks for which the bow has been charged */ /** Finishes charging the current bow. Returns the number of ticks for which the bow has been charged */
int FinishChargingBow(void); int FinishChargingBow(void);
/** Cancels the current bow charging */ /** Cancels the current bow charging */
void CancelChargingBow(void); void CancelChargingBow(void);
/** Returns true if the player is currently charging the bow */ /** Returns true if the player is currently charging the bow */
bool IsChargingBow(void) const { return m_IsChargingBow; } bool IsChargingBow(void) const { return m_IsChargingBow; }
@ -128,7 +128,7 @@ public:
/** Gets the contents of the player's associated enderchest */ /** Gets the contents of the player's associated enderchest */
cItemGrid & GetEnderChestContents(void) { return m_EnderChestContents; } cItemGrid & GetEnderChestContents(void) { return m_EnderChestContents; }
inline const cItem & GetEquippedItem(void) const { return GetInventory().GetEquippedItem(); } // tolua_export inline const cItem & GetEquippedItem(void) const { return GetInventory().GetEquippedItem(); } // tolua_export
/** Returns whether the player is climbing (ladders, vines etc.) */ /** Returns whether the player is climbing (ladders, vines etc.) */
@ -137,43 +137,49 @@ public:
virtual void TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ) override; virtual void TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ) override;
// tolua_begin // tolua_begin
/** Sends the "look" packet to the player, forcing them to set their rotation to the specified values. /** Sends the "look" packet to the player, forcing them to set their rotation to the specified values.
a_YawDegrees is clipped to range [-180, +180), a_YawDegrees is clipped to range [-180, +180),
a_PitchDegrees is clipped to range [-180, +180) but the client only uses [-90, +90] a_PitchDegrees is clipped to range [-180, +180) but the client only uses [-90, +90]
*/ */
void SendRotation(double a_YawDegrees, double a_PitchDegrees); void SendRotation(double a_YawDegrees, double a_PitchDegrees);
/** Returns the position where projectiles thrown by this player should start, player eye position + adjustment */ /** Returns the position where projectiles thrown by this player should start, player eye position + adjustment */
Vector3d GetThrowStartPos(void) const; Vector3d GetThrowStartPos(void) const;
/** Returns the initial speed vector of a throw, with a 3D length of a_SpeedCoeff. */ /** Returns the initial speed vector of a throw, with a 3D length of a_SpeedCoeff. */
Vector3d GetThrowSpeed(double a_SpeedCoeff) const; Vector3d GetThrowSpeed(double a_SpeedCoeff) const;
/** Returns the current gamemode. Partly OBSOLETE, you should use IsGameModeXXX() functions wherever applicable */ /** Returns the current gamemode. Partly OBSOLETE, you should use IsGameModeXXX() functions wherever applicable */
eGameMode GetGameMode(void) const { return m_GameMode; } eGameMode GetGameMode(void) const { return m_GameMode; }
/** Returns the current effective gamemode (inherited gamemode is resolved before returning) */ /** Returns the current effective gamemode (inherited gamemode is resolved before returning) */
eGameMode GetEffectiveGameMode(void) const { return (m_GameMode == gmNotSet) ? m_World->GetGameMode() : m_GameMode; } eGameMode GetEffectiveGameMode(void) const { return (m_GameMode == gmNotSet) ? m_World->GetGameMode() : m_GameMode; }
/** Sets the gamemode for the player. /** Sets the gamemode for the player.
The gamemode may be gmNotSet, in that case the player inherits the world's gamemode. The gamemode may be gmNotSet, in that case the player inherits the world's gamemode.
Updates the gamemode on the client (sends the packet) Updates the gamemode on the client (sends the packet)
*/ */
void SetGameMode(eGameMode a_GameMode); void SetGameMode(eGameMode a_GameMode);
// Sets the current gamemode, doesn't check validity, doesn't send update packets to client
void LoginSetGameMode(eGameMode a_GameMode);
// Updates player's capabilities - flying, visibility, etc. from their gamemode.
void SetCapabilities();
/** Returns true if the player is in Creative mode, either explicitly, or by inheriting from current world */ /** Returns true if the player is in Creative mode, either explicitly, or by inheriting from current world */
bool IsGameModeCreative(void) const; bool IsGameModeCreative(void) const;
/** Returns true if the player is in Survival mode, either explicitly, or by inheriting from current world */ /** Returns true if the player is in Survival mode, either explicitly, or by inheriting from current world */
bool IsGameModeSurvival(void) const; bool IsGameModeSurvival(void) const;
/** Returns true if the player is in Adventure mode, either explicitly, or by inheriting from current world */ /** Returns true if the player is in Adventure mode, either explicitly, or by inheriting from current world */
bool IsGameModeAdventure(void) const; bool IsGameModeAdventure(void) const;
/** Returns true if the player is in Spectator mode, either explicitly, or by inheriting from current world */ /** Returns true if the player is in Spectator mode, either explicitly, or by inheriting from current world */
bool IsGameModeSpectator(void) const; bool IsGameModeSpectator(void) const;
AString GetIP(void) const { return m_IP; } // tolua_export AString GetIP(void) const { return m_IP; } // tolua_export
/** Returns the associated team, nullptr if none */ /** Returns the associated team, nullptr if none */
@ -195,11 +201,8 @@ public:
If the achievement has been already awarded to the player, this method will just increment the stat counter. If the achievement has been already awarded to the player, this method will just increment the stat counter.
Returns the _new_ stat value. (0 = Could not award achievement) */ Returns the _new_ stat value. (0 = Could not award achievement) */
unsigned int AwardAchievement(const eStatistic a_Ach); unsigned int AwardAchievement(const eStatistic a_Ach);
void SetIP(const AString & a_IP); void SetIP(const AString & a_IP);
// Sets the current gamemode, doesn't check validity, doesn't send update packets to client
void LoginSetGameMode(eGameMode a_GameMode);
/** Forces the player to move in the given direction. /** Forces the player to move in the given direction.
@deprecated Use SetSpeed instead. */ @deprecated Use SetSpeed instead. */
@ -210,15 +213,15 @@ public:
cWindow * GetWindow(void) { return m_CurrentWindow; } // tolua_export cWindow * GetWindow(void) { return m_CurrentWindow; } // tolua_export
const cWindow * GetWindow(void) const { return m_CurrentWindow; } const cWindow * GetWindow(void) const { return m_CurrentWindow; }
/** Opens the specified window; closes the current one first using CloseWindow() */ /** Opens the specified window; closes the current one first using CloseWindow() */
void OpenWindow(cWindow * a_Window); // Exported in ManualBindings.cpp void OpenWindow(cWindow * a_Window); // Exported in ManualBindings.cpp
// tolua_begin // tolua_begin
/** Closes the current window, resets current window to m_InventoryWindow. A plugin may refuse the closing if a_CanRefuse is true */ /** Closes the current window, resets current window to m_InventoryWindow. A plugin may refuse the closing if a_CanRefuse is true */
void CloseWindow(bool a_CanRefuse = true); void CloseWindow(bool a_CanRefuse = true);
/** Closes the current window if it matches the specified ID, resets current window to m_InventoryWindow */ /** Closes the current window if it matches the specified ID, resets current window to m_InventoryWindow */
void CloseWindowIfID(char a_WindowID, bool a_CanRefuse = true); void CloseWindowIfID(char a_WindowID, bool a_CanRefuse = true);
@ -243,7 +246,7 @@ public:
const AString & GetName(void) const { return m_PlayerName; } const AString & GetName(void) const { return m_PlayerName; }
void SetName(const AString & a_Name) { m_PlayerName = a_Name; } void SetName(const AString & a_Name) { m_PlayerName = a_Name; }
// tolua_end // tolua_end
bool HasPermission(const AString & a_Permission); // tolua_export bool HasPermission(const AString & a_Permission); // tolua_export
@ -260,7 +263,7 @@ public:
const AStringVector & GetRestrictions(void) const { return m_Restrictions; } // Exported in ManualBindings.cpp const AStringVector & GetRestrictions(void) const { return m_Restrictions; } // Exported in ManualBindings.cpp
// tolua_begin // tolua_begin
/** Returns the full color code to use for this player, based on their rank. /** 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. */ The returned value either is empty, or includes the cChatColor::Delimiter. */
AString GetColor(void) const; AString GetColor(void) const;
@ -279,15 +282,15 @@ public:
/** Heals the player by the specified amount of HPs (positive only); sends health update */ /** Heals the player by the specified amount of HPs (positive only); sends health update */
virtual void Heal(int a_Health) override; virtual void Heal(int a_Health) override;
int GetFoodLevel (void) const { return m_FoodLevel; } int GetFoodLevel (void) const { return m_FoodLevel; }
double GetFoodSaturationLevel (void) const { return m_FoodSaturationLevel; } double GetFoodSaturationLevel (void) const { return m_FoodSaturationLevel; }
int GetFoodTickTimer (void) const { return m_FoodTickTimer; } int GetFoodTickTimer (void) const { return m_FoodTickTimer; }
double GetFoodExhaustionLevel (void) const { return m_FoodExhaustionLevel; } double GetFoodExhaustionLevel (void) const { return m_FoodExhaustionLevel; }
/** Returns true if the player is satiated, i. e. their foodlevel is at the max and they cannot eat anymore */ /** Returns true if the player is satiated, i. e. their foodlevel is at the max and they cannot eat anymore */
bool IsSatiated(void) const { return (m_FoodLevel >= MAX_FOOD_LEVEL); } bool IsSatiated(void) const { return (m_FoodLevel >= MAX_FOOD_LEVEL); }
void SetFoodLevel (int a_FoodLevel); void SetFoodLevel (int a_FoodLevel);
void SetFoodSaturationLevel (double a_FoodSaturationLevel); void SetFoodSaturationLevel (double a_FoodSaturationLevel);
void SetFoodTickTimer (int a_FoodTickTimer); void SetFoodTickTimer (int a_FoodTickTimer);
@ -298,10 +301,10 @@ public:
/** Adds the specified exhaustion to m_FoodExhaustion. Expects only positive values. */ /** Adds the specified exhaustion to m_FoodExhaustion. Expects only positive values. */
void AddFoodExhaustion(double a_Exhaustion); void AddFoodExhaustion(double a_Exhaustion);
/** Returns true if the player is currently in the process of eating the currently equipped item */ /** Returns true if the player is currently in the process of eating the currently equipped item */
bool IsEating(void) const { return (m_EatingFinishTick >= 0); } bool IsEating(void) const { return (m_EatingFinishTick >= 0); }
/** Returns true if the player is currently flying. */ /** Returns true if the player is currently flying. */
bool IsFlying(void) const { return m_IsFlying; } bool IsFlying(void) const { return m_IsFlying; }
@ -329,16 +332,16 @@ public:
GetWorld()->BroadcastEntityAnimation(*this, 2); GetWorld()->BroadcastEntityAnimation(*this, 2);
} }
} }
/** Starts eating the currently equipped item. Resets the eating timer and sends the proper animation packet */ /** Starts eating the currently equipped item. Resets the eating timer and sends the proper animation packet */
void StartEating(void); void StartEating(void);
/** Finishes eating the currently equipped item. Consumes the item, updates health and broadcasts the packets */ /** Finishes eating the currently equipped item. Consumes the item, updates health and broadcasts the packets */
void FinishEating(void); void FinishEating(void);
/** Aborts the current eating operation */ /** Aborts the current eating operation */
void AbortEating(void); void AbortEating(void);
virtual void KilledBy(TakeDamageInfo & a_TDI) override; virtual void KilledBy(TakeDamageInfo & a_TDI) override;
virtual void Killed(cEntity * a_Victim) override; virtual void Killed(cEntity * a_Victim) override;
@ -356,69 +359,69 @@ public:
bool SaveToDisk(void); bool SaveToDisk(void);
typedef cWorld * cWorldPtr; typedef cWorld * cWorldPtr;
/** Loads the player data from the disk file /** 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() 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 Returns true on success, false on failure
*/ */
bool LoadFromDisk(cWorldPtr & a_World); bool LoadFromDisk(cWorldPtr & a_World);
/** Loads the player data from the specified file /** 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 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 Returns true on success, false on failure
*/ */
bool LoadFromFile(const AString & a_FileName, cWorldPtr & a_World); bool LoadFromFile(const AString & a_FileName, cWorldPtr & a_World);
const AString & GetLoadedWorldName() { return m_LoadedWorldName; } const AString & GetLoadedWorldName() { return m_LoadedWorldName; }
void UseEquippedItem(int a_Amount = 1); void UseEquippedItem(int a_Amount = 1);
void SendHealth(void); void SendHealth(void);
void SendExperience(void); void SendExperience(void);
/** In UI windows, get the item that the player is dragging */ /** In UI windows, get the item that the player is dragging */
cItem & GetDraggingItem(void) {return m_DraggingItem; } cItem & GetDraggingItem(void) {return m_DraggingItem; }
// In UI windows, when inventory-painting: // In UI windows, when inventory-painting:
/** Clears the list of slots that are being inventory-painted. To be used by cWindow only */ /** Clears the list of slots that are being inventory-painted. To be used by cWindow only */
void ClearInventoryPaintSlots(void); void ClearInventoryPaintSlots(void);
/** Adds a slot to the list for inventory painting. To be used by cWindow only */ /** Adds a slot to the list for inventory painting. To be used by cWindow only */
void AddInventoryPaintSlot(int a_SlotNum); void AddInventoryPaintSlot(int a_SlotNum);
/** Returns the list of slots currently stored for inventory painting. To be used by cWindow only */ /** Returns the list of slots currently stored for inventory painting. To be used by cWindow only */
const cSlotNums & GetInventoryPaintSlots(void) const; const cSlotNums & GetInventoryPaintSlots(void) const;
// tolua_begin // tolua_begin
/** Returns the current relative maximum speed (takes current sprinting / flying state into account) */ /** Returns the current relative maximum speed (takes current sprinting / flying state into account) */
double GetMaxSpeed(void) const; double GetMaxSpeed(void) const;
/** Gets the normal relative maximum speed */ /** Gets the normal relative maximum speed */
double GetNormalMaxSpeed(void) const { return m_NormalMaxSpeed; } double GetNormalMaxSpeed(void) const { return m_NormalMaxSpeed; }
/** Gets the sprinting relative maximum speed */ /** Gets the sprinting relative maximum speed */
double GetSprintingMaxSpeed(void) const { return m_SprintingMaxSpeed; } double GetSprintingMaxSpeed(void) const { return m_SprintingMaxSpeed; }
/** Gets the flying relative maximum speed */ /** Gets the flying relative maximum speed */
double GetFlyingMaxSpeed(void) const { return m_FlyingMaxSpeed; } double GetFlyingMaxSpeed(void) const { return m_FlyingMaxSpeed; }
/** Sets the normal relative maximum speed. Sends the update to player, if needed. */ /** Sets the normal relative maximum speed. Sends the update to player, if needed. */
void SetNormalMaxSpeed(double a_Speed); void SetNormalMaxSpeed(double a_Speed);
/** Sets the sprinting relative maximum speed. Sends the update to player, if needed. */ /** Sets the sprinting relative maximum speed. Sends the update to player, if needed. */
void SetSprintingMaxSpeed(double a_Speed); void SetSprintingMaxSpeed(double a_Speed);
/** Sets the flying relative maximum speed. Sends the update to player, if needed. */ /** Sets the flying relative maximum speed. Sends the update to player, if needed. */
void SetFlyingMaxSpeed(double a_Speed); void SetFlyingMaxSpeed(double a_Speed);
/** Sets the crouch status, broadcasts to all visible players */ /** Sets the crouch status, broadcasts to all visible players */
void SetCrouch(bool a_IsCrouched); void SetCrouch(bool a_IsCrouched);
/** Starts or stops sprinting, sends the max speed update to the client, if needed */ /** Starts or stops sprinting, sends the max speed update to the client, if needed */
void SetSprint(bool a_IsSprinting); void SetSprint(bool a_IsSprinting);
/** Flags the player as flying */ /** Flags the player as flying */
void SetFlying(bool a_IsFlying); void SetFlying(bool a_IsFlying);
@ -442,17 +445,17 @@ public:
/** Sets the player's bed (home) position */ /** Sets the player's bed (home) position */
void SetBedPos(const Vector3i & a_Pos) { m_LastBedPos = a_Pos; } void SetBedPos(const Vector3i & a_Pos) { m_LastBedPos = a_Pos; }
// tolua_end // tolua_end
/** Update movement-related statistics. */ /** Update movement-related statistics. */
void UpdateMovementStats(const Vector3d & a_DeltaPos); void UpdateMovementStats(const Vector3d & a_DeltaPos);
// tolua_begin // tolua_begin
/** Returns wheter the player can fly or not. */ /** Returns wheter the player can fly or not. */
virtual bool CanFly(void) const { return m_CanFly; } virtual bool CanFly(void) const { return m_CanFly; }
/** Returns the UUID (short format) that has been read from the client, or empty string if not available. */ /** 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; } const AString & GetUUID(void) const { return m_UUID; }
@ -492,7 +495,7 @@ public:
/** Called by cClientHandle when the client is being destroyed. /** Called by cClientHandle when the client is being destroyed.
The player removes its m_ClientHandle ownership so that the ClientHandle gets deleted. */ The player removes its m_ClientHandle ownership so that the ClientHandle gets deleted. */
void RemoveClientHandle(void); void RemoveClientHandle(void);
protected: protected:
typedef std::vector<std::vector<AString> > AStringVectorVector; typedef std::vector<std::vector<AString> > AStringVectorVector;
@ -535,16 +538,16 @@ protected:
// Food-related variables: // Food-related variables:
/** Represents the food bar, one point equals half a "drumstick" */ /** Represents the food bar, one point equals half a "drumstick" */
int m_FoodLevel; int m_FoodLevel;
/** "Overcharge" for the m_FoodLevel; is depleted before m_FoodLevel */ /** "Overcharge" for the m_FoodLevel; is depleted before m_FoodLevel */
double m_FoodSaturationLevel; double m_FoodSaturationLevel;
/** Count-up to the healing or damaging action, based on m_FoodLevel */ /** Count-up to the healing or damaging action, based on m_FoodLevel */
int m_FoodTickTimer; int m_FoodTickTimer;
/** A "buffer" which adds up hunger before it is substracted from m_FoodSaturationLevel or m_FoodLevel. Each action adds a little */ /** A "buffer" which adds up hunger before it is substracted from m_FoodSaturationLevel or m_FoodLevel. Each action adds a little */
double m_FoodExhaustionLevel; double m_FoodExhaustionLevel;
float m_LastJumpHeight; float m_LastJumpHeight;
float m_LastGroundHeight; float m_LastGroundHeight;
bool m_bTouchGround; bool m_bTouchGround;
@ -564,31 +567,31 @@ protected:
eGameMode m_GameMode; eGameMode m_GameMode;
AString m_IP; AString m_IP;
/** The item being dragged by the cursor while in a UI window */ /** The item being dragged by the cursor while in a UI window */
cItem m_DraggingItem; cItem m_DraggingItem;
std::chrono::steady_clock::time_point m_LastPlayerListTime; std::chrono::steady_clock::time_point m_LastPlayerListTime;
cClientHandlePtr m_ClientHandle; cClientHandlePtr m_ClientHandle;
cSlotNums m_InventoryPaintSlots; cSlotNums m_InventoryPaintSlots;
/** Max speed, relative to the game default. /** Max speed, relative to the game default.
1 means regular speed, 2 means twice as fast, 0.5 means half-speed. 1 means regular speed, 2 means twice as fast, 0.5 means half-speed.
Default value is 1. */ Default value is 1. */
double m_NormalMaxSpeed; double m_NormalMaxSpeed;
/** Max speed, relative to the game default max speed, when sprinting. /** Max speed, relative to the game default max speed, when sprinting.
1 means regular speed, 2 means twice as fast, 0.5 means half-speed. 1 means regular speed, 2 means twice as fast, 0.5 means half-speed.
Default value is 1.3. */ Default value is 1.3. */
double m_SprintingMaxSpeed; double m_SprintingMaxSpeed;
/** Max speed, relative to the game default flying max speed, when flying. /** Max speed, relative to the game default flying max speed, when flying.
1 means regular speed, 2 means twice as fast, 0.5 means half-speed. 1 means regular speed, 2 means twice as fast, 0.5 means half-speed.
Default value is 1. */ Default value is 1. */
double m_FlyingMaxSpeed; double m_FlyingMaxSpeed;
bool m_IsCrouched; bool m_IsCrouched;
bool m_IsSprinting; bool m_IsSprinting;
bool m_IsFlying; bool m_IsFlying;
@ -629,7 +632,7 @@ protected:
Will not apply food penalties if found to be true; will set to false after processing Will not apply food penalties if found to be true; will set to false after processing
*/ */
bool m_bIsTeleporting; bool m_bIsTeleporting;
/** The short UUID (no dashes) of the player, as read from the ClientHandle. /** The short UUID (no dashes) of the player, as read from the ClientHandle.
If no ClientHandle is given, the UUID is initialized to empty. */ If no ClientHandle is given, the UUID is initialized to empty. */
AString m_UUID; AString m_UUID;
@ -649,7 +652,7 @@ protected:
/** Stops players from burning in creative mode */ /** Stops players from burning in creative mode */
virtual void TickBurning(cChunk & a_Chunk) override; virtual void TickBurning(cChunk & a_Chunk) override;
/** Called in each tick to handle food-related processing */ /** Called in each tick to handle food-related processing */
void HandleFood(void); void HandleFood(void);
@ -666,7 +669,3 @@ protected:
This can be used both for online and offline UUIDs. */ This can be used both for online and offline UUIDs. */
AString GetUUIDFileName(const AString & a_UUID); AString GetUUIDFileName(const AString & a_UUID);
} ; // tolua_export } ; // tolua_export