Streamline player abilities handling
* Update player list gamemode on world change * Fix invisibility for spectators, use entity metadata * Populate m_World for cPlayers on load - Remove SendPlayerMaxSpeed, a duplicate of SendEntityProperties
This commit is contained in:
parent
0f9d424427
commit
1394fc8eb5
@ -10781,16 +10781,6 @@ a_Player:OpenWindow(Window);
|
||||
},
|
||||
Notes = "Returns true if the player is satiated (cannot eat).",
|
||||
},
|
||||
IsVisible =
|
||||
{
|
||||
Returns =
|
||||
{
|
||||
{
|
||||
Type = "boolean",
|
||||
},
|
||||
},
|
||||
Notes = "Returns true if the player is visible to other players",
|
||||
},
|
||||
LoadRank =
|
||||
{
|
||||
Notes = "Reloads the player's rank, message visuals and permissions from the {{cRankManager}}, based on the player's current rank.",
|
||||
|
@ -345,6 +345,19 @@ void cWorld::BroadcastEntityPosition(const cEntity & a_Entity, const cClientHand
|
||||
|
||||
|
||||
|
||||
void cWorld::BroadcastEntityProperties(const cEntity & a_Entity)
|
||||
{
|
||||
ForClientsWithEntity(a_Entity, *this, nullptr, [&](cClientHandle & a_Client)
|
||||
{
|
||||
a_Client.SendEntityProperties(a_Entity);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cWorld::BroadcastEntityStatus(const cEntity & a_Entity, Int8 a_Status, const cClientHandle * a_Exclude)
|
||||
{
|
||||
ForClientsWithEntity(a_Entity, *this, a_Exclude, [&](cClientHandle & a_Client)
|
||||
|
@ -2528,6 +2528,15 @@ void cClientHandle::SendEntityPosition(const cEntity & a_Entity)
|
||||
|
||||
|
||||
|
||||
void cClientHandle::SendEntityProperties(const cEntity & a_Entity)
|
||||
{
|
||||
m_Protocol->SendEntityProperties(a_Entity);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cClientHandle::SendEntityStatus(const cEntity & a_Entity, char a_Status)
|
||||
{
|
||||
m_Protocol->SendEntityStatus(a_Entity, a_Status);
|
||||
@ -2737,15 +2746,6 @@ void cClientHandle::SendPlayerListUpdatePing()
|
||||
|
||||
|
||||
|
||||
void cClientHandle::SendPlayerMaxSpeed(void)
|
||||
{
|
||||
m_Protocol->SendPlayerMaxSpeed();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cClientHandle::SendPlayerMoveLook(void)
|
||||
{
|
||||
/*
|
||||
|
@ -169,6 +169,7 @@ public: // tolua_export
|
||||
void SendEntityLook (const cEntity & a_Entity);
|
||||
void SendEntityMetadata (const cEntity & a_Entity);
|
||||
void SendEntityPosition (const cEntity & a_Entity);
|
||||
void SendEntityProperties (const cEntity & a_Entity);
|
||||
void SendEntityStatus (const cEntity & a_Entity, char a_Status);
|
||||
void SendEntityVelocity (const cEntity & a_Entity);
|
||||
void SendExperience (void);
|
||||
@ -191,7 +192,6 @@ public: // tolua_export
|
||||
void SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName);
|
||||
void SendPlayerListUpdateGameMode (const cPlayer & a_Player);
|
||||
void SendPlayerListUpdatePing ();
|
||||
void SendPlayerMaxSpeed (void); ///< Informs the client of the maximum player speed (1.6.1+)
|
||||
void SendPlayerMoveLook (void);
|
||||
void SendPlayerPosition (void);
|
||||
void SendPlayerSpawn (const cPlayer & a_Player);
|
||||
|
@ -122,7 +122,7 @@ bool cEntity::Initialize(OwnedEntity a_Self, cWorld & a_EntityWorld)
|
||||
*/
|
||||
|
||||
|
||||
ASSERT(m_World == nullptr);
|
||||
ASSERT(a_Self->IsPlayer() || (m_World == nullptr)); // Players' worlds are loaded from disk.
|
||||
ASSERT(GetParentChunk() == nullptr);
|
||||
SetWorld(&a_EntityWorld);
|
||||
a_EntityWorld.AddEntity(std::move(a_Self));
|
||||
|
@ -144,30 +144,10 @@ cPlayer::cPlayer(const std::shared_ptr<cClientHandle> & a_Client) :
|
||||
SetMaxHealth(MAX_HEALTH);
|
||||
m_Health = MAX_HEALTH;
|
||||
|
||||
cWorld * World = nullptr;
|
||||
LoadFromDisk(World);
|
||||
LoadFromDisk();
|
||||
UpdateCapabilities();
|
||||
|
||||
m_LastGroundHeight = static_cast<float>(GetPosY());
|
||||
|
||||
if (m_GameMode == gmNotSet)
|
||||
{
|
||||
if (World->IsGameModeCreative())
|
||||
{
|
||||
m_IsFlightCapable = true;
|
||||
}
|
||||
if (World->IsGameModeSpectator()) // Otherwise Player will fall out of the world on join
|
||||
{
|
||||
m_IsFlightCapable = true;
|
||||
m_IsFlying = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_GameMode == gmSpectator) // If player is reconnecting to the server in spectator mode
|
||||
{
|
||||
m_IsFlightCapable = true;
|
||||
m_IsFlying = true;
|
||||
m_IsVisible = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -614,10 +594,11 @@ double cPlayer::GetMaxSpeed(void) const
|
||||
void cPlayer::SetNormalMaxSpeed(double a_Speed)
|
||||
{
|
||||
m_NormalMaxSpeed = a_Speed;
|
||||
if (!IsSprinting() && !IsFlying() && !IsFrozen())
|
||||
|
||||
if (!m_IsFrozen)
|
||||
{
|
||||
// If we are frozen, we do not send this yet. We send when unfreeze() is called
|
||||
m_ClientHandle->SendPlayerMaxSpeed();
|
||||
m_World->BroadcastEntityProperties(*this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -628,10 +609,11 @@ void cPlayer::SetNormalMaxSpeed(double a_Speed)
|
||||
void cPlayer::SetSprintingMaxSpeed(double a_Speed)
|
||||
{
|
||||
m_SprintingMaxSpeed = a_Speed;
|
||||
if (IsSprinting() && !m_IsFlying && !m_IsFrozen)
|
||||
|
||||
if (!m_IsFrozen)
|
||||
{
|
||||
// If we are frozen, we do not send this yet. We send when unfreeze() is called
|
||||
m_ClientHandle->SendPlayerMaxSpeed();
|
||||
m_World->BroadcastEntityProperties(*this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -643,7 +625,6 @@ void cPlayer::SetFlyingMaxSpeed(double a_Speed)
|
||||
{
|
||||
m_FlyingMaxSpeed = a_Speed;
|
||||
|
||||
// Update the flying speed, always:
|
||||
if (!m_IsFrozen)
|
||||
{
|
||||
// If we are frozen, we do not send this yet. We send when unfreeze() is called
|
||||
@ -723,6 +704,7 @@ void cPlayer::SetSprint(const bool a_ShouldSprint)
|
||||
}
|
||||
|
||||
m_World->BroadcastEntityMetadata(*this);
|
||||
m_World->BroadcastEntityProperties(*this);
|
||||
}
|
||||
|
||||
|
||||
@ -1325,49 +1307,38 @@ void cPlayer::SetGameMode(eGameMode a_GameMode)
|
||||
}
|
||||
|
||||
m_GameMode = a_GameMode;
|
||||
UpdateCapabilities();
|
||||
|
||||
m_ClientHandle->SendGameMode(a_GameMode);
|
||||
|
||||
SetCapabilities();
|
||||
|
||||
m_ClientHandle->SendInventorySlot(-1, -1, m_DraggingItem);
|
||||
m_World->BroadcastPlayerListUpdateGameMode(*this);
|
||||
m_World->BroadcastEntityMetadata(*this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cPlayer::SetCapabilities()
|
||||
void cPlayer::UpdateCapabilities()
|
||||
{
|
||||
// Fly ability
|
||||
// Fly ability:
|
||||
if (IsGameModeCreative() || IsGameModeSpectator())
|
||||
{
|
||||
SetCanFly(true);
|
||||
m_IsFlightCapable = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
SetFlying(false);
|
||||
SetCanFly(false);
|
||||
m_IsFlying = false;
|
||||
m_IsFlightCapable = false;
|
||||
}
|
||||
|
||||
// Visible
|
||||
if (IsGameModeSpectator())
|
||||
{
|
||||
SetVisible(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetVisible(true);
|
||||
}
|
||||
// Visible:
|
||||
m_IsVisible = !IsGameModeSpectator();
|
||||
|
||||
// Set for spectator
|
||||
// Clear the current dragging item of spectators:
|
||||
if (IsGameModeSpectator())
|
||||
{
|
||||
// Clear the current dragging item of the player
|
||||
if (GetWindow() != nullptr)
|
||||
{
|
||||
m_DraggingItem.Empty();
|
||||
GetClientHandle()->SendInventorySlot(-1, -1, m_DraggingItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1449,8 +1420,8 @@ void cPlayer::Unfreeze()
|
||||
m_World->BroadcastEntityMetadata(*this);
|
||||
}
|
||||
|
||||
GetClientHandle()->SendPlayerAbilities();
|
||||
GetClientHandle()->SendPlayerMaxSpeed();
|
||||
m_ClientHandle->SendPlayerAbilities();
|
||||
m_World->BroadcastEntityProperties(*this);
|
||||
|
||||
m_IsFrozen = false;
|
||||
BroadcastMovementUpdate(m_ClientHandle.get());
|
||||
@ -1521,21 +1492,7 @@ Vector3d cPlayer::GetThrowSpeed(double a_SpeedCoeff) const
|
||||
|
||||
eGameMode cPlayer::GetEffectiveGameMode(void) const
|
||||
{
|
||||
// Since entities' m_World aren't set until Initialize, but cClientHandle sends the player's gamemode early
|
||||
// the below block deals with m_World being nullptr when called.
|
||||
|
||||
auto World = m_World;
|
||||
|
||||
if (World == nullptr)
|
||||
{
|
||||
World = cRoot::Get()->GetDefaultWorld();
|
||||
}
|
||||
else if (IsWorldChangeScheduled())
|
||||
{
|
||||
World = m_WorldChangeInfo.m_NewWorld;
|
||||
}
|
||||
|
||||
return (m_GameMode == gmNotSet) ? World->GetGameMode() : m_GameMode;
|
||||
return (m_GameMode == gmNotSet) ? m_World->GetGameMode() : m_GameMode;
|
||||
}
|
||||
|
||||
|
||||
@ -1553,17 +1510,16 @@ void cPlayer::ForceSetSpeed(const Vector3d & a_Speed)
|
||||
|
||||
void cPlayer::SetVisible(bool a_bVisible)
|
||||
{
|
||||
// Need to Check if the player or other players are in gamemode spectator, but will break compatibility
|
||||
if (a_bVisible && !m_IsVisible) // Make visible
|
||||
if (a_bVisible && !m_IsVisible)
|
||||
{
|
||||
m_IsVisible = true;
|
||||
m_World->BroadcastSpawnEntity(*this);
|
||||
}
|
||||
if (!a_bVisible && m_IsVisible)
|
||||
{
|
||||
m_IsVisible = false;
|
||||
m_World->BroadcastDestroyEntity(*this, m_ClientHandle.get()); // Destroy on all clients
|
||||
}
|
||||
|
||||
m_World->BroadcastEntityMetadata(*this);
|
||||
}
|
||||
|
||||
|
||||
@ -1806,25 +1762,25 @@ void cPlayer::TossPickup(const cItem & a_Item)
|
||||
|
||||
|
||||
|
||||
void cPlayer::LoadFromDisk(cWorldPtr & a_World)
|
||||
void cPlayer::LoadFromDisk()
|
||||
{
|
||||
LoadRank();
|
||||
|
||||
const auto & UUID = GetUUID();
|
||||
|
||||
// Load from the UUID file:
|
||||
if (LoadFromFile(GetUUIDFileName(UUID), a_World))
|
||||
if (LoadFromFile(GetUUIDFileName(UUID)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Player not found:
|
||||
a_World = cRoot::Get()->GetDefaultWorld();
|
||||
m_World = cRoot::Get()->GetDefaultWorld();
|
||||
LOG("Player \"%s\" (%s) data not found, resetting to defaults", GetName().c_str(), UUID.ToShortString().c_str());
|
||||
|
||||
const Vector3i WorldSpawn(static_cast<int>(a_World->GetSpawnX()), static_cast<int>(a_World->GetSpawnY()), static_cast<int>(a_World->GetSpawnZ()));
|
||||
const Vector3i WorldSpawn(static_cast<int>(m_World->GetSpawnX()), static_cast<int>(m_World->GetSpawnY()), static_cast<int>(m_World->GetSpawnZ()));
|
||||
SetPosition(WorldSpawn);
|
||||
SetBedPos(WorldSpawn, a_World);
|
||||
SetBedPos(WorldSpawn, m_World);
|
||||
|
||||
m_Inventory.Clear();
|
||||
m_EnchantmentSeed = GetRandomProvider().RandInt<unsigned int>(); // Use a random number to seed the enchantment generator
|
||||
@ -1836,7 +1792,7 @@ void cPlayer::LoadFromDisk(cWorldPtr & a_World)
|
||||
|
||||
|
||||
|
||||
bool cPlayer::LoadFromFile(const AString & a_FileName, cWorldPtr & a_World)
|
||||
bool cPlayer::LoadFromFile(const AString & a_FileName)
|
||||
{
|
||||
Json::Value Root;
|
||||
|
||||
@ -1925,16 +1881,15 @@ bool cPlayer::LoadFromFile(const AString & a_FileName, cWorldPtr & a_World)
|
||||
cEnderChestEntity::LoadFromJson(Root["enderchestinventory"], m_EnderChestContents);
|
||||
|
||||
m_CurrentWorldName = Root.get("world", "world").asString();
|
||||
a_World = cRoot::Get()->GetWorld(GetLoadedWorldName());
|
||||
if (a_World == nullptr)
|
||||
m_World = cRoot::Get()->GetWorld(m_CurrentWorldName);
|
||||
if (m_World == nullptr)
|
||||
{
|
||||
a_World = cRoot::Get()->GetDefaultWorld();
|
||||
m_World = cRoot::Get()->GetDefaultWorld();
|
||||
}
|
||||
|
||||
|
||||
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_LastBedPos.x = Root.get("SpawnX", m_World->GetSpawnX()).asInt();
|
||||
m_LastBedPos.y = Root.get("SpawnY", m_World->GetSpawnY()).asInt();
|
||||
m_LastBedPos.z = Root.get("SpawnZ", m_World->GetSpawnZ()).asInt();
|
||||
m_SpawnWorldName = Root.get("SpawnWorld", cRoot::Get()->GetDefaultWorld()->GetName()).asString();
|
||||
|
||||
try
|
||||
@ -1949,7 +1904,7 @@ bool cPlayer::LoadFromFile(const AString & a_FileName, cWorldPtr & a_World)
|
||||
}
|
||||
|
||||
FLOGD("Player {0} was read from file \"{1}\", spawning at {2:.2f} in world \"{3}\"",
|
||||
GetName(), a_FileName, GetPosition(), a_World->GetName()
|
||||
GetName(), a_FileName, GetPosition(), m_World->GetName()
|
||||
);
|
||||
|
||||
return true;
|
||||
@ -2689,10 +2644,10 @@ void cPlayer::FreezeInternal(const Vector3d & a_Location, bool a_ManuallyFrozen)
|
||||
m_IsFlying = true;
|
||||
|
||||
// Send the client its fake speed and max speed of 0
|
||||
GetClientHandle()->SendPlayerMoveLook();
|
||||
GetClientHandle()->SendPlayerAbilities();
|
||||
GetClientHandle()->SendPlayerMaxSpeed();
|
||||
GetClientHandle()->SendEntityVelocity(*this);
|
||||
m_ClientHandle->SendPlayerMoveLook();
|
||||
m_ClientHandle->SendPlayerAbilities();
|
||||
m_ClientHandle->SendEntityVelocity(*this);
|
||||
m_World->BroadcastEntityProperties(*this);
|
||||
|
||||
// Keep the server side speed variables as they were in the first place
|
||||
m_NormalMaxSpeed = NormalMaxSpeed;
|
||||
@ -3050,6 +3005,15 @@ float cPlayer::GetEnchantmentBlastKnockbackReduction()
|
||||
|
||||
|
||||
|
||||
bool cPlayer::IsInvisible() const
|
||||
{
|
||||
return !m_IsVisible || Super::IsInvisible();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cPlayer::IsCrouched(void) const
|
||||
{
|
||||
return std::holds_alternative<BodyStanceCrouching>(m_BodyStance);
|
||||
@ -3079,6 +3043,7 @@ bool cPlayer::IsSprinting(void) const
|
||||
|
||||
void cPlayer::OnAddToWorld(cWorld & a_World)
|
||||
{
|
||||
// Sends player spawn:
|
||||
Super::OnAddToWorld(a_World);
|
||||
|
||||
// Update world name tracking:
|
||||
@ -3087,8 +3052,10 @@ void cPlayer::OnAddToWorld(cWorld & a_World)
|
||||
// Fix to stop the player falling through the world, until we get serversided collision detection:
|
||||
FreezeInternal(GetPosition(), false);
|
||||
|
||||
// Set capabilities based on new world:
|
||||
SetCapabilities();
|
||||
// UpdateCapabilities was called in the constructor, and in OnRemoveFromWorld, possibly changing our visibility.
|
||||
// If world is in spectator mode, invisibility will need updating. If we just connected, we might be on fire from a previous game.
|
||||
// Hence, tell the client by sending metadata:
|
||||
m_ClientHandle->SendEntityMetadata(*this);
|
||||
|
||||
// Send contents of the inventory window:
|
||||
m_ClientHandle->SendWholeInventory(*m_CurrentWindow);
|
||||
@ -3168,8 +3135,13 @@ void cPlayer::OnRemoveFromWorld(cWorld & a_World)
|
||||
AwardAchievement(Statistic::AchPortal);
|
||||
}
|
||||
|
||||
// Set capabilities based on new world:
|
||||
UpdateCapabilities();
|
||||
|
||||
// Clientside warp start:
|
||||
m_ClientHandle->SendRespawn(DestinationDimension, false);
|
||||
m_ClientHandle->SendPlayerListUpdateGameMode(*this);
|
||||
m_World->BroadcastPlayerListUpdateGameMode(*this);
|
||||
|
||||
// Clear sent chunk lists from the clienthandle:
|
||||
m_ClientHandle->RemoveFromWorld();
|
||||
@ -3184,7 +3156,7 @@ void cPlayer::OnRemoveFromWorld(cWorld & a_World)
|
||||
|
||||
void cPlayer::SpawnOn(cClientHandle & a_Client)
|
||||
{
|
||||
if (!m_IsVisible || (m_ClientHandle.get() == (&a_Client)))
|
||||
if (m_ClientHandle.get() == &a_Client)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -163,8 +163,8 @@ public:
|
||||
|
||||
virtual void TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ) override;
|
||||
|
||||
// Updates player's capabilities - flying, visibility, etc. from their gamemode.
|
||||
void SetCapabilities();
|
||||
/** Updates player's capabilities - flying, visibility, etc. from their gamemode. */
|
||||
void UpdateCapabilities();
|
||||
|
||||
// tolua_begin
|
||||
|
||||
@ -412,21 +412,18 @@ public:
|
||||
void Respawn(void); // tolua_export
|
||||
|
||||
void SetVisible( bool a_bVisible); // tolua_export
|
||||
bool IsVisible(void) const { return m_IsVisible; } // tolua_export
|
||||
|
||||
/** 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(). */
|
||||
void LoadFromDisk(cWorldPtr & a_World);
|
||||
Sets m_World to the world where the player will spawn, based on the stored world name or the default world by calling LoadFromFile(). */
|
||||
void LoadFromDisk();
|
||||
|
||||
/** 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 m_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);
|
||||
bool LoadFromFile(const AString & a_FileName);
|
||||
|
||||
const AString & GetLoadedWorldName() const { return m_CurrentWorldName; }
|
||||
|
||||
@ -805,6 +802,7 @@ private:
|
||||
virtual bool DoTakeDamage(TakeDamageInfo & TDI) override;
|
||||
virtual float GetEnchantmentBlastKnockbackReduction() override;
|
||||
virtual void HandlePhysics(std::chrono::milliseconds a_Dt, cChunk &) override { UNUSED(a_Dt); }
|
||||
virtual bool IsInvisible() const override;
|
||||
virtual bool IsRclking(void) const override { return IsEating() || IsChargingBow(); }
|
||||
virtual void OnAddToWorld(cWorld & a_World) override;
|
||||
virtual void OnRemoveFromWorld(cWorld & a_World) override;
|
||||
|
@ -99,7 +99,6 @@ AString cPacketizer::PacketTypeToStr(cProtocol::ePacketType a_PacketType)
|
||||
case cProtocol::pktPlayerAbilities: return "pktPlayerAbilities";
|
||||
case cProtocol::pktPlayerList: return "pktPlayerList";
|
||||
case cProtocol::pktPlayerListHeaderFooter: return "pktPlayerListHeaderFooter";
|
||||
case cProtocol::pktPlayerMaxSpeed: return "pktPlayerMaxSpeed";
|
||||
case cProtocol::pktPlayerMoveLook: return "pktPlayerMoveLook";
|
||||
case cProtocol::pktPluginMessage: return "pktPluginMessage";
|
||||
case cProtocol::pktRemoveEntityEffect: return "pktRemoveEntityEffect";
|
||||
|
@ -105,7 +105,6 @@ public:
|
||||
pktPlayerAbilities,
|
||||
pktPlayerList,
|
||||
pktPlayerListHeaderFooter,
|
||||
pktPlayerMaxSpeed,
|
||||
pktPlayerMoveLook,
|
||||
pktPluginMessage,
|
||||
pktRemoveEntityEffect,
|
||||
@ -412,7 +411,6 @@ public:
|
||||
virtual void SendPlayerListUpdateGameMode (const cPlayer & a_Player) = 0;
|
||||
virtual void SendPlayerListUpdatePing () = 0;
|
||||
virtual void SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName) = 0;
|
||||
virtual void SendPlayerMaxSpeed (void) = 0; ///< Informs the client of the maximum player speed (1.6.1+)
|
||||
virtual void SendPlayerMoveLook (void) = 0;
|
||||
virtual void SendPlayerPosition (void) = 0;
|
||||
virtual void SendPlayerSpawn (const cPlayer & a_Player) = 0;
|
||||
|
@ -1003,7 +1003,6 @@ UInt32 cProtocol_1_12::GetPacketID(cProtocol::ePacketType a_Packet)
|
||||
case pktExperience: return 0x3f;
|
||||
case pktHeldItemChange: return 0x39;
|
||||
case pktLeashEntity: return 0x3c;
|
||||
case pktPlayerMaxSpeed: return 0x4d;
|
||||
case pktRemoveEntityEffect: return 0x32;
|
||||
case pktResourcePack: return 0x33;
|
||||
case pktRespawn: return 0x34;
|
||||
@ -1184,7 +1183,6 @@ UInt32 cProtocol_1_12_1::GetPacketID(ePacketType a_Packet)
|
||||
case pktPlayerList: return 0x2e;
|
||||
case pktPlayerListHeaderFooter: return 0x4a;
|
||||
case pktPlayerAbilities: return 0x2c;
|
||||
case pktPlayerMaxSpeed: return 0x4e;
|
||||
case pktPlayerMoveLook: return 0x2f;
|
||||
case pktRemoveEntityEffect: return 0x33;
|
||||
case pktResourcePack: return 0x34;
|
||||
|
@ -372,8 +372,7 @@ UInt32 cProtocol_1_13::GetPacketID(ePacketType a_PacketType)
|
||||
case pktParticleEffect: return 0x24;
|
||||
case pktPlayerAbilities: return 0x2e;
|
||||
case pktPlayerList: return 0x30;
|
||||
case pktPlayerListHeaderFooter: return 0x4E;
|
||||
case pktPlayerMaxSpeed: return 0x52;
|
||||
case pktPlayerListHeaderFooter: return 0x4e;
|
||||
case pktPlayerMoveLook: return 0x32;
|
||||
case pktPluginMessage: return 0x19;
|
||||
case pktRemoveEntityEffect: return 0x36;
|
||||
|
@ -832,9 +832,6 @@ void cProtocol_1_8_0::SendLogin(const cPlayer & a_Player, const cWorld & a_World
|
||||
cPacketizer Pkt(*this, pktDifficulty);
|
||||
Pkt.WriteBEInt8(1);
|
||||
}
|
||||
|
||||
// Send player abilities:
|
||||
SendPlayerAbilities();
|
||||
}
|
||||
|
||||
|
||||
@ -1132,35 +1129,6 @@ void cProtocol_1_8_0::SendPlayerListUpdatePing()
|
||||
|
||||
|
||||
|
||||
void cProtocol_1_8_0::SendPlayerMaxSpeed(void)
|
||||
{
|
||||
ASSERT(m_State == 3); // In game mode?
|
||||
|
||||
cPacketizer Pkt(*this, pktEntityProperties);
|
||||
cPlayer * Player = m_Client->GetPlayer();
|
||||
Pkt.WriteVarInt32(Player->GetUniqueID());
|
||||
Pkt.WriteBEInt32(1); // Count
|
||||
Pkt.WriteString("generic.movementSpeed");
|
||||
// The default game speed is 0.1, multiply that value by the relative speed:
|
||||
Pkt.WriteBEDouble(0.1 * Player->GetNormalMaxSpeed());
|
||||
if (Player->IsSprinting())
|
||||
{
|
||||
Pkt.WriteVarInt32(1); // Modifier count
|
||||
Pkt.WriteBEUInt64(0x662a6b8dda3e4c1c);
|
||||
Pkt.WriteBEUInt64(0x881396ea6097278d); // UUID of the modifier
|
||||
Pkt.WriteBEDouble(Player->GetSprintingMaxSpeed() - Player->GetNormalMaxSpeed());
|
||||
Pkt.WriteBEUInt8(2);
|
||||
}
|
||||
else
|
||||
{
|
||||
Pkt.WriteVarInt32(0); // Modifier count
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cProtocol_1_8_0::SendPlayerMoveLook(void)
|
||||
{
|
||||
ASSERT(m_State == 3); // In game mode?
|
||||
@ -1201,12 +1169,8 @@ void cProtocol_1_8_0::SendPlayerSpawn(const cPlayer & a_Player)
|
||||
Pkt.WriteFPInt(LastSentPos.z);
|
||||
Pkt.WriteByteAngle(a_Player.GetYaw());
|
||||
Pkt.WriteByteAngle(a_Player.GetPitch());
|
||||
short ItemType = a_Player.GetEquippedItem().IsEmpty() ? 0 : a_Player.GetEquippedItem().m_ItemType;
|
||||
Pkt.WriteBEInt16(ItemType);
|
||||
Pkt.WriteBEUInt8((3 << 5) | 6); // Metadata: float + index 6
|
||||
Pkt.WriteBEFloat(static_cast<float>(a_Player.GetHealth()));
|
||||
Pkt.WriteBEUInt8((4 << 5 | (2 & 0x1F)) & 0xFF);
|
||||
Pkt.WriteString(a_Player.GetName());
|
||||
Pkt.WriteBEInt16(a_Player.GetEquippedItem().IsEmpty() ? 0 : a_Player.GetEquippedItem().m_ItemType);
|
||||
WriteEntityMetadata(Pkt, a_Player);
|
||||
Pkt.WriteBEUInt8(0x7f); // Metadata: end
|
||||
}
|
||||
|
||||
@ -3377,11 +3341,15 @@ void cProtocol_1_8_0::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a
|
||||
{
|
||||
auto & Player = static_cast<const cPlayer &>(a_Entity);
|
||||
|
||||
// Player health (not handled since players aren't monsters)
|
||||
// Player name:
|
||||
a_Pkt.WriteBEUInt8(0x82);
|
||||
a_Pkt.WriteString(Player.GetName());
|
||||
|
||||
// Player health:
|
||||
a_Pkt.WriteBEUInt8(0x66);
|
||||
a_Pkt.WriteBEFloat(static_cast<float>(Player.GetHealth()));
|
||||
|
||||
// Skin flags
|
||||
// Skin flags:
|
||||
a_Pkt.WriteBEUInt8(0x0A);
|
||||
a_Pkt.WriteBEUInt8(static_cast<UInt8>(Player.GetSkinParts()));
|
||||
|
||||
@ -3815,18 +3783,38 @@ void cProtocol_1_8_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_M
|
||||
|
||||
void cProtocol_1_8_0::WriteEntityProperties(cPacketizer & a_Pkt, const cEntity & a_Entity)
|
||||
{
|
||||
if (!a_Entity.IsMob())
|
||||
if (a_Entity.IsPlayer())
|
||||
{
|
||||
// No properties for anything else than mobs
|
||||
a_Pkt.WriteBEInt32(0);
|
||||
return;
|
||||
}
|
||||
const auto & Player = static_cast<const cPlayer &>(a_Entity);
|
||||
|
||||
a_Pkt.WriteBEInt32(1); // Count.
|
||||
a_Pkt.WriteString("generic.movementSpeed");
|
||||
a_Pkt.WriteBEDouble(0.1 * Player.GetNormalMaxSpeed()); // The default game speed is 0.1, multiply that value by the relative speed.
|
||||
|
||||
// It seems the modifiers aren't conditionally activated; their effects are applied immediately!
|
||||
// We have to keep on re-sending this packet when the client notifies us of sprint start and end, and so on. Strange.
|
||||
|
||||
if (Player.IsSprinting())
|
||||
{
|
||||
a_Pkt.WriteVarInt32(1); // Modifier count.
|
||||
a_Pkt.WriteBEUInt64(0x662a6b8dda3e4c1c);
|
||||
a_Pkt.WriteBEUInt64(0x881396ea6097278d); // UUID of the modifier (sprinting speed boost).
|
||||
a_Pkt.WriteBEDouble(Player.GetSprintingMaxSpeed() - Player.GetNormalMaxSpeed());
|
||||
a_Pkt.WriteBEUInt8(2);
|
||||
}
|
||||
else
|
||||
{
|
||||
a_Pkt.WriteVarInt32(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// const cMonster & Mob = (const cMonster &)a_Entity;
|
||||
|
||||
// TODO: Send properties and modifiers based on the mob type
|
||||
|
||||
a_Pkt.WriteBEInt32(0); // NumProperties
|
||||
a_Pkt.WriteBEInt32(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -95,7 +95,6 @@ public:
|
||||
virtual void SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName) override;
|
||||
virtual void SendPlayerListUpdateGameMode (const cPlayer & a_Player) override;
|
||||
virtual void SendPlayerListUpdatePing () override;
|
||||
virtual void SendPlayerMaxSpeed (void) override;
|
||||
virtual void SendPlayerMoveLook (void) override;
|
||||
virtual void SendPlayerPosition (void) override;
|
||||
virtual void SendPlayerSpawn (const cPlayer & a_Player) override;
|
||||
|
@ -490,35 +490,6 @@ void cProtocol_1_9_0::SendMapData(const cMap & a_Map, int a_DataStartX, int a_Da
|
||||
|
||||
|
||||
|
||||
void cProtocol_1_9_0::SendPlayerMaxSpeed(void)
|
||||
{
|
||||
ASSERT(m_State == 3); // In game mode?
|
||||
|
||||
cPacketizer Pkt(*this, pktPlayerMaxSpeed);
|
||||
cPlayer * Player = m_Client->GetPlayer();
|
||||
Pkt.WriteVarInt32(Player->GetUniqueID());
|
||||
Pkt.WriteBEInt32(1); // Count
|
||||
Pkt.WriteString("generic.movementSpeed");
|
||||
// The default game speed is 0.1, multiply that value by the relative speed:
|
||||
Pkt.WriteBEDouble(0.1 * Player->GetNormalMaxSpeed());
|
||||
if (Player->IsSprinting())
|
||||
{
|
||||
Pkt.WriteVarInt32(1); // Modifier count
|
||||
Pkt.WriteBEUInt64(0x662a6b8dda3e4c1c);
|
||||
Pkt.WriteBEUInt64(0x881396ea6097278d); // UUID of the modifier
|
||||
Pkt.WriteBEDouble(Player->GetSprintingMaxSpeed() - Player->GetNormalMaxSpeed());
|
||||
Pkt.WriteBEUInt8(2);
|
||||
}
|
||||
else
|
||||
{
|
||||
Pkt.WriteVarInt32(0); // Modifier count
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cProtocol_1_9_0::SendPlayerMoveLook(void)
|
||||
{
|
||||
ASSERT(m_State == 3); // In game mode?
|
||||
@ -690,7 +661,6 @@ UInt32 cProtocol_1_9_0::GetPacketID(cProtocol::ePacketType a_Packet)
|
||||
case pktPlayerAbilities: return 0x2b;
|
||||
case pktPlayerList: return 0x2d;
|
||||
case pktPlayerListHeaderFooter: return 0x48;
|
||||
case pktPlayerMaxSpeed: return 0x4b;
|
||||
case pktPlayerMoveLook: return 0x2e;
|
||||
case pktPluginMessage: return 0x18;
|
||||
case pktRemoveEntityEffect: return 0x31;
|
||||
@ -2271,26 +2241,6 @@ void cProtocol_1_9_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_M
|
||||
|
||||
|
||||
|
||||
void cProtocol_1_9_0::WriteEntityProperties(cPacketizer & a_Pkt, const cEntity & a_Entity)
|
||||
{
|
||||
if (!a_Entity.IsMob())
|
||||
{
|
||||
// No properties for anything else than mobs
|
||||
a_Pkt.WriteBEInt32(0);
|
||||
return;
|
||||
}
|
||||
|
||||
// const cMonster & Mob = (const cMonster &)a_Entity;
|
||||
|
||||
// TODO: Send properties and modifiers based on the mob type
|
||||
|
||||
a_Pkt.WriteBEInt32(0); // NumProperties
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// cProtocol_1_9_1:
|
||||
|
||||
@ -2320,9 +2270,6 @@ void cProtocol_1_9_1::SendLogin(const cPlayer & a_Player, const cWorld & a_World
|
||||
cPacketizer Pkt(*this, pktDifficulty);
|
||||
Pkt.WriteBEInt8(1);
|
||||
}
|
||||
|
||||
// Send player abilities:
|
||||
SendPlayerAbilities();
|
||||
}
|
||||
|
||||
|
||||
@ -2405,7 +2352,6 @@ UInt32 cProtocol_1_9_4::GetPacketID(cProtocol::ePacketType a_Packet)
|
||||
case pktCollectEntity: return 0x48;
|
||||
case pktEntityEffect: return 0x4b;
|
||||
case pktEntityProperties: return 0x4a;
|
||||
case pktPlayerMaxSpeed: return 0x4a;
|
||||
case pktPlayerListHeaderFooter: return 0x47;
|
||||
case pktTeleportEntity: return 0x49;
|
||||
|
||||
|
@ -57,7 +57,6 @@ public:
|
||||
virtual void SendLeashEntity (const cEntity & a_Entity, const cEntity & a_EntityLeashedTo) override;
|
||||
virtual void SendMapData (const cMap & a_Map, int a_DataStartX, int a_DataStartY) override;
|
||||
virtual void SendPaintingSpawn (const cPainting & a_Painting) override;
|
||||
virtual void SendPlayerMaxSpeed (void) override;
|
||||
virtual void SendPlayerMoveLook (void) override;
|
||||
virtual void SendPlayerSpawn (const cPlayer & a_Player) override;
|
||||
virtual void SendSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch) override;
|
||||
@ -125,9 +124,6 @@ protected:
|
||||
/** Writes the mob-specific metadata for the specified mob */
|
||||
virtual void WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) override;
|
||||
|
||||
/** Writes the entity properties for the specified entity, including the Count field. */
|
||||
virtual void WriteEntityProperties(cPacketizer & a_Pkt, const cEntity & a_Entity) override;
|
||||
|
||||
/** Types used within metadata */
|
||||
enum eMetadataType
|
||||
{
|
||||
|
@ -184,6 +184,7 @@ public:
|
||||
virtual void BroadcastEntityLook (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) override;
|
||||
virtual void BroadcastEntityMetadata (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) override;
|
||||
virtual void BroadcastEntityPosition (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) override;
|
||||
void BroadcastEntityProperties (const cEntity & a_Entity);
|
||||
virtual void BroadcastEntityStatus (const cEntity & a_Entity, Int8 a_Status, const cClientHandle * a_Exclude = nullptr) override;
|
||||
virtual void BroadcastEntityVelocity (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) override;
|
||||
virtual void BroadcastEntityAnimation (const cEntity & a_Entity, Int8 a_Animation, const cClientHandle * a_Exclude = nullptr) override; // tolua_export
|
||||
|
Loading…
Reference in New Issue
Block a user