summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source/ClientHandle.cpp159
-rw-r--r--source/ClientHandle.h9
2 files changed, 54 insertions, 114 deletions
diff --git a/source/ClientHandle.cpp b/source/ClientHandle.cpp
index 3d819ee18..966b46719 100644
--- a/source/ClientHandle.cpp
+++ b/source/ClientHandle.cpp
@@ -98,6 +98,7 @@ cClientHandle::cClientHandle(const cSocket * a_Socket, int a_ViewDistance)
, m_HasStartedDigging(false)
, m_CurrentExplosionTick(0)
, m_RunningSumExplosions(0)
+ , m_HasSentPlayerChunk(false)
{
m_Protocol = new cProtocolRecognizer(this);
@@ -489,8 +490,14 @@ void cClientHandle::HandleCreativeInventory(short a_SlotNum, const cItem & a_Hel
void cClientHandle::HandlePlayerPos(double a_PosX, double a_PosY, double a_PosZ, double a_Stance, bool a_IsOnGround)
{
+ if ((m_Player == NULL) || (m_State != csPlaying))
+ {
+ // The client hasn't been spawned yet and sends nonsense, we know better
+ return;
+ }
+
/*
- // TODO: Invalid stance check
+ // TODO: Invalid stance check
if ((a_PosY >= a_Stance) || (a_Stance > a_PosY + 1.65))
{
LOGD("Invalid stance");
@@ -499,7 +506,7 @@ void cClientHandle::HandlePlayerPos(double a_PosX, double a_PosY, double a_PosZ,
}
*/
- // LOGD("recv player pos: {%0.2f %0.2f %0.2f}, ground: %d", a_PosX, a_PosY, a_PosZ, a_IsOnGround ? 1 : 0);
+ // If the player has moved too far, "repair" them:
Vector3d Pos(a_PosX, a_PosY, a_PosZ);
if ((m_Player->GetPosition() - Pos).SqrLength() > 100 * 100)
{
@@ -513,7 +520,7 @@ void cClientHandle::HandlePlayerPos(double a_PosX, double a_PosY, double a_PosZ,
{
// we only add this exhaustion if the player is not swimming - otherwise we end up with both jump + swim exhaustion
- if(! m_Player->IsSwimming() )
+ if (!m_Player->IsSwimming())
{
m_Player->AddFoodExhaustion(m_Player->IsSprinting() ? 0.8 : 0.2);
}
@@ -997,11 +1004,15 @@ void cClientHandle::HandleChat(const AString & a_Message)
void cClientHandle::HandlePlayerLook(float a_Rotation, float a_Pitch, bool a_IsOnGround)
{
+ if ((m_Player == NULL) || (m_State != csPlaying))
+ {
+ return;
+ }
+
m_Player->SetRotation (a_Rotation);
m_Player->SetHeadYaw (a_Rotation);
m_Player->SetPitch (a_Pitch);
m_Player->SetTouchGround(a_IsOnGround);
- m_Player->WrapRotation();
}
@@ -1010,6 +1021,12 @@ void cClientHandle::HandlePlayerLook(float a_Rotation, float a_Pitch, bool a_IsO
void cClientHandle::HandlePlayerMoveLook(double a_PosX, double a_PosY, double a_PosZ, double a_Stance, float a_Rotation, float a_Pitch, bool a_IsOnGround)
{
+ if ((m_Player == NULL) || (m_State != csPlaying))
+ {
+ // The client hasn't been spawned yet and sends nonsense, we know better
+ return;
+ }
+
/*
// TODO: Invalid stance check
if ((a_PosY >= a_Stance) || (a_Stance > a_PosY + 1.65))
@@ -1019,46 +1036,13 @@ void cClientHandle::HandlePlayerMoveLook(double a_PosX, double a_PosY, double a_
return;
}
*/
- switch (m_State)
- {
- case csPlaying:
- {
- m_Player->MoveTo(Vector3d(a_PosX, a_PosY, a_PosZ));
- m_Player->SetStance (a_Stance);
- m_Player->SetTouchGround(a_IsOnGround);
- m_Player->SetHeadYaw (a_Rotation);
- m_Player->SetRotation (a_Rotation);
- m_Player->SetPitch (a_Pitch);
- m_Player->WrapRotation();
- break;
- }
-
- case csDownloadingWorld:
- {
- Vector3d ReceivedPosition = Vector3d(a_PosX, a_PosY, a_PosZ);
- // LOGD("Received MoveLook confirmation: {%0.2f %0.2f %0.2f}", a_PosX, a_PosY, a_PosZ);
-
- // Test the distance between points with a small/large enough value instead of comparing directly. Floating point inaccuracies might screw stuff up
- double Dist = (ReceivedPosition - m_ConfirmPosition).SqrLength();
- if (Dist < 1.0)
- {
- if (ReceivedPosition.Equals(m_ConfirmPosition))
- {
- LOGINFO("Exact position confirmed by client!");
- }
- m_State = csPlaying;
- }
- else
- {
- LOGWARNING("Player \"%s\" sent a weird position confirmation %.2f blocks away, retrying", m_Username.c_str(), sqrt(Dist));
- LOGD(" Expected pos: {%0.2f, %0.2f, %0.2f}", m_ConfirmPosition.x, m_ConfirmPosition.y, m_ConfirmPosition.z);
- LOGD(" Received pos: {%0.2f, %0.2f, %0.2f}", a_PosX, a_PosY, a_PosZ);
- m_ConfirmPosition = m_Player->GetPosition();
- SendPlayerMoveLook();
- }
- break;
- }
- }
+
+ m_Player->MoveTo(Vector3d(a_PosX, a_PosY, a_PosZ));
+ m_Player->SetStance (a_Stance);
+ m_Player->SetTouchGround(a_IsOnGround);
+ m_Player->SetHeadYaw (a_Rotation);
+ m_Player->SetRotation (a_Rotation);
+ m_Player->SetPitch (a_Pitch);
}
@@ -1208,7 +1192,7 @@ void cClientHandle::HandleUseEntity(int a_TargetEntityID, bool a_IsLeftClick)
void cClientHandle::HandleRespawn(void)
{
- if( m_Player == NULL )
+ if (m_Player == NULL)
{
Destroy();
return;
@@ -1422,6 +1406,7 @@ void cClientHandle::MoveToWorld(cWorld & a_World, bool a_SendRespawnPacket)
m_State = csAuthenticated;
m_LastStreamedChunkX = 0x7fffffff;
m_LastStreamedChunkZ = 0x7fffffff;
+ m_HasSentPlayerChunk = false;
}
@@ -1495,17 +1480,23 @@ void cClientHandle::Tick(float a_Dt)
Destroy();
}
- if ((m_State == csDownloadingWorld) && m_ShouldCheckDownloaded)
- {
- CheckIfWorldDownloaded();
- m_ShouldCheckDownloaded = false;
- }
-
if (m_Player == NULL)
{
return;
}
+ // If the chunk the player's in was just sent, spawn the player:
+ if (m_HasSentPlayerChunk && (m_State != csPlaying))
+ {
+ if (!cRoot::Get()->GetPluginManager()->CallHookPlayerJoined(*m_Player))
+ {
+ // Broadcast that this player has joined the game! Yay~
+ m_Player->GetWorld()->BroadcastChat(m_Username + " joined the game!", this);
+ }
+ m_Protocol->SendPlayerMoveLook();
+ m_State = csPlaying;
+ }
+
// Send a ping packet:
cTimer t1;
if ((m_LastPingTime + cClientHandle::PING_TIME_MS <= t1.GetNowTime()))
@@ -1601,14 +1592,6 @@ void cClientHandle::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializ
{
ASSERT(m_Player != NULL);
- if ((m_State == csAuthenticated) || (m_State == csDownloadingWorld))
- {
- if ((a_ChunkX == m_Player->GetChunkX()) && (a_ChunkZ == m_Player->GetChunkZ()))
- {
- m_Protocol->SendPlayerMoveLook();
- }
- }
-
// Check chunks being sent, erase them from m_ChunksToSend:
bool Found = false;
{
@@ -1618,11 +1601,6 @@ void cClientHandle::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializ
if ((itr->m_ChunkX == a_ChunkX) && (itr->m_ChunkZ == a_ChunkZ))
{
m_ChunksToSend.erase(itr);
-
- // Make the tick thread check if all the needed chunks have been downloaded
- // -- needed to offload this from here due to a deadlock possibility
- m_ShouldCheckDownloaded = true;
-
Found = true;
break;
}
@@ -1637,6 +1615,15 @@ void cClientHandle::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializ
}
m_Protocol->SendChunkData(a_ChunkX, a_ChunkZ, a_Serializer);
+
+ // If it is the chunk the player's in, make them spawn (in the tick thread):
+ if ((m_State == csAuthenticated) || (m_State == csDownloadingWorld))
+ {
+ if ((a_ChunkX == m_Player->GetChunkX()) && (a_ChunkZ == m_Player->GetChunkZ()))
+ {
+ m_HasSentPlayerChunk = true;
+ }
+ }
}
@@ -2078,50 +2065,6 @@ void cClientHandle::SendWindowProperty(const cWindow & a_Window, int a_Property,
-void cClientHandle::CheckIfWorldDownloaded(void)
-{
- if (m_State != csDownloadingWorld)
- {
- return;
- }
-
- bool ShouldSendConfirm = false;
- {
- cCSLock Lock(m_CSChunkLists);
- ShouldSendConfirm = m_ChunksToSend.empty();
- }
-
- if (ShouldSendConfirm)
- {
- SendConfirmPosition();
- }
-}
-
-
-
-
-
-void cClientHandle::SendConfirmPosition(void)
-{
- LOG("Spawning player \"%s\" at {%.2f, %.2f, %.2f}",
- m_Username.c_str(), m_Player->GetPosX(), m_Player->GetPosY(), m_Player->GetPosZ()
- );
-
- m_State = csConfirmingPos;
-
- if (!cRoot::Get()->GetPluginManager()->CallHookPlayerJoined(*m_Player))
- {
- // Broadcast that this player has joined the game! Yay~
- m_Player->GetWorld()->BroadcastChat(m_Username + " joined the game!", this);
- }
-
- SendPlayerMoveLook();
-}
-
-
-
-
-
const AString & cClientHandle::GetUsername(void) const
{
return m_Username;
diff --git a/source/ClientHandle.h b/source/ClientHandle.h
index 9a2092361..67ddcb0ba 100644
--- a/source/ClientHandle.h
+++ b/source/ClientHandle.h
@@ -299,17 +299,14 @@ private:
static int s_ClientCount;
int m_UniqueID;
+ /// Set to true when the chunk where the player is is sent to the client. Used for spawning the player
+ bool m_HasSentPlayerChunk;
+
/// Returns true if the rate block interactions is within a reasonable limit (bot protection)
bool CheckBlockInteractionsRate(void);
- /// Checks whether all loaded chunks have been sent to the client; if so, sends the position to confirm
- void CheckIfWorldDownloaded(void);
-
- /// Sends the PlayerMoveLook packet that the client needs to reply to for the game to start
- void SendConfirmPosition(void);
-
/// Adds a single chunk to be streamed to the client; used by StreamChunks()
void StreamChunk(int a_ChunkX, int a_ChunkZ);