summaryrefslogtreecommitdiffstats
path: root/source/cClientHandle.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/cClientHandle.cpp')
-rw-r--r--source/cClientHandle.cpp335
1 files changed, 286 insertions, 49 deletions
diff --git a/source/cClientHandle.cpp b/source/cClientHandle.cpp
index 62c1a6ea5..a73e1f447 100644
--- a/source/cClientHandle.cpp
+++ b/source/cClientHandle.cpp
@@ -39,40 +39,45 @@
#include "cAuthenticator.h"
#include "MersenneTwister.h"
-#include "packets/cPacket_KeepAlive.h"
-#include "packets/cPacket_Respawn.h"
-#include "packets/cPacket_UpdateHealth.h"
-#include "packets/cPacket_RelativeEntityMoveLook.h"
-#include "packets/cPacket_Chat.h"
-#include "packets/cPacket_Login.h"
-#include "packets/cPacket_TimeUpdate.h"
-#include "packets/cPacket_BlockDig.h"
-#include "packets/cPacket_Handshake.h"
+#include "packets/cPacket_13.h"
#include "packets/cPacket_ArmAnim.h"
+#include "packets/cPacket_BlockChange.h"
+#include "packets/cPacket_BlockDig.h"
#include "packets/cPacket_BlockPlace.h"
-#include "packets/cPacket_Flying.h"
+#include "packets/cPacket_Chat.h"
+#include "packets/cPacket_CreativeInventoryAction.h"
+#include "packets/cPacket_DestroyEntity.h"
#include "packets/cPacket_Disconnect.h"
-#include "packets/cPacket_PickupSpawn.h"
-#include "packets/cPacket_ItemSwitch.h"
#include "packets/cPacket_EntityEquipment.h"
-#include "packets/cPacket_CreativeInventoryAction.h"
+#include "packets/cPacket_EntityLook.h"
+#include "packets/cPacket_Flying.h"
+#include "packets/cPacket_Handshake.h"
+#include "packets/cPacket_InventorySlot.h"
+#include "packets/cPacket_ItemSwitch.h"
+#include "packets/cPacket_KeepAlive.h"
+#include "packets/cPacket_Login.h"
+#include "packets/cPacket_MapChunk.h"
+#include "packets/cPacket_Metadata.h"
+#include "packets/cPacket_MultiBlock.h"
+#include "packets/cPacket_NamedEntitySpawn.h"
#include "packets/cPacket_NewInvalidState.h"
+#include "packets/cPacket_PickupSpawn.h"
+#include "packets/cPacket_Ping.h"
+#include "packets/cPacket_Player.h"
+#include "packets/cPacket_PreChunk.h"
+#include "packets/cPacket_RelativeEntityMove.h"
+#include "packets/cPacket_RelativeEntityMoveLook.h"
+#include "packets/cPacket_Respawn.h"
+#include "packets/cPacket_SpawnMob.h"
+#include "packets/cPacket_TeleportEntity.h"
+#include "packets/cPacket_TimeUpdate.h"
+#include "packets/cPacket_UpdateHealth.h"
+#include "packets/cPacket_UpdateSign.h"
#include "packets/cPacket_UseEntity.h"
+#include "packets/cPacket_WholeInventory.h"
#include "packets/cPacket_WindowClick.h"
#include "packets/cPacket_WindowClose.h"
#include "packets/cPacket_WindowOpen.h"
-#include "packets/cPacket_WholeInventory.h"
-#include "packets/cPacket_13.h"
-#include "packets/cPacket_UpdateSign.h"
-#include "packets/cPacket_Ping.h"
-#include "packets/cPacket_NamedEntitySpawn.h"
-#include "packets/cPacket_MapChunk.h"
-#include "packets/cPacket_PreChunk.h"
-#include "packets/cPacket_InventorySlot.h"
-
-// DEBUG:
-#include "packets/cPacket_BlockChange.h"
-#include "packets/cPacket_MultiBlock.h"
@@ -500,6 +505,8 @@ void cClientHandle::HandlePacket(cPacket * a_Packet)
// Therefore I keep this function huge and untidy for the time being
// ( http://forum.mc-server.org/showthread.php?tid=524 )
+ // LOGD("Recv packet %02x", a_Packet->m_PacketID);
+
m_TimeLastPacket = cWorld::GetTime();
// LOG("Recv packet 0x%02x from client \"%s\" (\"%s\")", a_Packet->m_PacketID, m_Socket.GetIPString().c_str(), m_Username.c_str());
@@ -678,11 +685,35 @@ void cClientHandle::HandlePacket(cPacket * a_Packet)
HandleWindowClick(wc->m_WindowID, wc->m_SlotNum, wc->m_IsRightClick, wc->m_IsShiftPressed, wc->m_HeldItem);
break;
}
- case E_UPDATE_SIGN: HandleUpdateSign (reinterpret_cast<cPacket_UpdateSign *> (a_Packet)); break;
- case E_USE_ENTITY: HandleUseEntity (reinterpret_cast<cPacket_UseEntity *> (a_Packet)); break;
- case E_RESPAWN: HandleRespawn(); break;
- case E_DISCONNECT: HandleDisconnect (reinterpret_cast<cPacket_Disconnect *> (a_Packet)); break;
- case E_KEEP_ALIVE: HandleKeepAlive (reinterpret_cast<cPacket_KeepAlive *> (a_Packet)); break;
+ case E_UPDATE_SIGN:
+ {
+ cPacket_UpdateSign * us = reinterpret_cast<cPacket_UpdateSign *>(a_Packet);
+ HandleUpdateSign(us->m_BlockX, us->m_BlockY, us->m_BlockZ, us->m_Line1, us->m_Line2, us->m_Line3, us->m_Line4);
+ break;
+ }
+ case E_USE_ENTITY:
+ {
+ cPacket_UseEntity * ue = reinterpret_cast<cPacket_UseEntity *>(a_Packet);
+ HandleUseEntity(ue->m_TargetEntityID, ue->m_IsLeftClick);
+ break;
+ }
+ case E_RESPAWN:
+ {
+ HandleRespawn();
+ break;
+ }
+ case E_DISCONNECT:
+ {
+ cPacket_Disconnect * dc = reinterpret_cast<cPacket_Disconnect *>(a_Packet);
+ HandleDisconnect(dc->m_Reason);
+ break;
+ }
+ case E_KEEP_ALIVE:
+ {
+ cPacket_KeepAlive * ka = reinterpret_cast<cPacket_KeepAlive *>(a_Packet);
+ HandleKeepAlive(ka->m_KeepAliveID);
+ break;
+ }
} // switch (Packet type)
break;
} // case csPlaying
@@ -797,7 +828,8 @@ void cClientHandle::HandleUnexpectedPacket(int a_PacketType)
void cClientHandle::HandleMoveLookConfirm(double a_PosX, double a_PosY, double a_PosZ)
{
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)
@@ -813,7 +845,7 @@ void cClientHandle::HandleMoveLookConfirm(double a_PosX, double a_PosY, double a
{
LOGWARNING("Player \"%s\" sent a weird position confirmation %.2f blocks away, retrying", m_Username.c_str(), Dist);
m_ConfirmPosition = m_Player->GetPosition();
- Send(cPacket_PlayerMoveLook(m_Player));
+ SendPlayerMoveLook();
}
}
@@ -840,8 +872,25 @@ 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)
{
- // LOG("recv player pos: %0.2f %0.2f %0.2f", PacketData->m_PosX, PacketData->m_PosY, PacketData->m_PosZ);
- m_Player->MoveTo(Vector3d(a_PosX, a_PosY, a_PosZ));
+ /*
+ // TODO: Invalid stance check
+ if ((a_PosY >= a_Stance) || (a_Stance > a_PosY + 1.65))
+ {
+ LOGD("Invalid stance");
+ SendPlayerMoveLook();
+ return;
+ }
+ */
+
+ // LOGD("recv player pos: {%0.2f %0.2f %0.2f}, ground: %d", a_PosX, a_PosY, a_PosZ, a_IsOnGround ? 1 : 0);
+ Vector3d Pos(a_PosX, a_PosY, a_PosZ);
+ if ((m_Player->GetPosition() - Pos).SqrLength() > 100 * 100)
+ {
+ LOGD("Too far away (%0.2f), \"repairing\" the client", (m_Player->GetPosition() - Pos).Length());
+ SendPlayerMoveLook();
+ return;
+ }
+ m_Player->MoveTo(Pos);
m_Player->SetStance(a_Stance);
m_Player->SetTouchGround(a_IsOnGround);
}
@@ -1086,6 +1135,16 @@ 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)
{
+ /*
+ // TODO: Invalid stance check
+ if ((a_PosY >= a_Stance) || (a_Stance > a_PosY + 1.65))
+ {
+ LOGD("Invalid stance");
+ SendPlayerMoveLook();
+ return;
+ }
+ */
+
m_Player->MoveTo(Vector3d(a_PosX, a_PosY, a_PosZ));
m_Player->SetStance (a_Stance);
m_Player->SetTouchGround(a_IsOnGround);
@@ -1148,20 +1207,25 @@ void cClientHandle::HandleWindowClick(char a_WindowID, short a_SlotNum, bool a_I
-void cClientHandle::HandleUpdateSign(cPacket_UpdateSign * a_Packet)
+void cClientHandle::HandleUpdateSign(
+ int a_BlockX, int a_BlockY, int a_BlockZ,
+ const AString & a_Line1, const AString & a_Line2,
+ const AString & a_Line3, const AString & a_Line4
+)
{
cWorld * World = m_Player->GetWorld();
- World->UpdateSign(a_Packet->m_PosX, a_Packet->m_PosY, a_Packet->m_PosZ, a_Packet->m_Line1, a_Packet->m_Line2, a_Packet->m_Line3, a_Packet->m_Line4);
+ World->UpdateSign(a_BlockX, a_BlockY, a_BlockZ, a_Line1, a_Line2, a_Line3, a_Line4);
}
-void cClientHandle::HandleUseEntity(cPacket_UseEntity * a_Packet)
+void cClientHandle::HandleUseEntity(int a_TargetEntityID, bool a_IsLeftClick)
{
- if (!a_Packet->m_bLeftClick)
+ if (!a_IsLeftClick)
{
+ // TODO: we don't handle right-clicking yet
return;
}
@@ -1169,9 +1233,9 @@ void cClientHandle::HandleUseEntity(cPacket_UseEntity * a_Packet)
{
virtual bool Item(cEntity * a_Entity) override
{
- if( a_Entity->IsA("cPawn") )
+ if (a_Entity->IsA("cPawn"))
{
- reinterpret_cast< cPawn* >( a_Entity )->TakeDamage(Damage, Instigator );
+ reinterpret_cast<cPawn *>(a_Entity)->TakeDamage(Damage, Instigator);
}
return true;
}
@@ -1184,7 +1248,7 @@ void cClientHandle::HandleUseEntity(cPacket_UseEntity * a_Packet)
Callback.Instigator = m_Player;
cWorld * World = m_Player->GetWorld();
- World->DoWithEntityByID(a_Packet->m_TargetID, Callback);
+ World->DoWithEntityByID(a_TargetEntityID, Callback);
}
@@ -1200,13 +1264,14 @@ void cClientHandle::HandleRespawn(void)
-void cClientHandle::HandleDisconnect(cPacket_Disconnect * a_Packet)
+void cClientHandle::HandleDisconnect(const AString & a_Reason)
{
- LOG("Received d/c packet from \"%s\"", m_Username.c_str());
- if (!cRoot::Get()->GetPluginManager()->CallHook(cPluginManager::HOOK_DISCONNECT, 2, a_Packet->m_Reason.c_str(), m_Player))
+ LOGD("Received d/c packet from \"%s\" with reason \"%s\"", m_Username.c_str(), a_Reason.c_str());
+ if (!cRoot::Get()->GetPluginManager()->CallHookDisconnect(m_Player, a_Reason))
{
- cPacket_Chat DisconnectMessage(m_Username + " disconnected: " + a_Packet->m_Reason);
- cRoot::Get()->GetServer()->Broadcast(DisconnectMessage);
+ AString DisconnectMessage;
+ Printf(DisconnectMessage, "%s disconnected: %s", m_Username.c_str(), a_Reason.c_str());
+ m_Player->GetWorld()->BroadcastChat(DisconnectMessage, this);
}
Destroy();
}
@@ -1215,9 +1280,9 @@ void cClientHandle::HandleDisconnect(cPacket_Disconnect * a_Packet)
-void cClientHandle::HandleKeepAlive(cPacket_KeepAlive * a_Packet)
+void cClientHandle::HandleKeepAlive(int a_KeepAliveID)
{
- if (a_Packet->m_KeepAliveID == m_PingID)
+ if (a_KeepAliveID == m_PingID)
{
cTimer t1;
m_Ping = (short)((t1.GetNowTime() - m_PingStartTime) / 2);
@@ -1225,6 +1290,9 @@ void cClientHandle::HandleKeepAlive(cPacket_KeepAlive * a_Packet)
}
+
+
+
bool cClientHandle::CheckBlockInteractionsRate(void)
{
ASSERT(m_Player != NULL);
@@ -1543,6 +1611,174 @@ void cClientHandle::SendWholeInventory(const cWindow & a_Window)
+void cClientHandle::SendTeleportEntity(const cEntity & a_Entity)
+{
+ cPacket_TeleportEntity te(a_Entity);
+ Send(te);
+}
+
+
+
+
+
+void cClientHandle::SendPlayerListItem(const cPlayer & a_Player)
+{
+ cPacket_PlayerListItem pli(a_Player.GetColor() + a_Player.GetName(), true, a_Player.GetClientHandle()->GetPing());
+ Send(pli);
+}
+
+
+
+
+
+void cClientHandle::SendPlayerPosition(void)
+{
+ cPacket_PlayerPosition pp(m_Player);
+ Send(pp);
+}
+
+
+
+
+
+void cClientHandle::SendRelEntMoveLook(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ)
+{
+ ASSERT(a_Entity.GetUniqueID() != m_Player->GetUniqueID()); // Must not send for self
+
+ cPacket_RelativeEntityMoveLook reml;
+ reml.m_UniqueID = a_Entity.GetUniqueID();
+ reml.m_MoveX = a_RelX;
+ reml.m_MoveY = a_RelY;
+ reml.m_MoveZ = a_RelZ;
+ reml.m_Yaw = (char)((a_Entity.GetRotation() / 360.f) * 256);
+ reml.m_Pitch = (char)((a_Entity.GetPitch() / 360.f) * 256);
+ Send(reml);
+}
+
+
+
+
+
+void cClientHandle::SendRelEntMove(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ)
+{
+ ASSERT(a_Entity.GetUniqueID() != m_Player->GetUniqueID()); // Must not send for self
+
+ cPacket_RelativeEntityMove rem;
+ rem.m_UniqueID = a_Entity.GetUniqueID();
+ rem.m_MoveX = a_RelX;
+ rem.m_MoveY = a_RelY;
+ rem.m_MoveZ = a_RelZ;
+ Send(rem);
+}
+
+
+
+
+
+void cClientHandle::SendEntLook(const cEntity & a_Entity)
+{
+ ASSERT(a_Entity.GetUniqueID() != m_Player->GetUniqueID()); // Must not send for self
+
+ cPacket_EntityLook el;
+ el.m_UniqueID = a_Entity.GetUniqueID();
+ el.m_Rotation = (char)((a_Entity.GetRotation() / 360.f) * 256);
+ el.m_Pitch = (char)((a_Entity.GetPitch() / 360.f) * 256);
+ Send(el);
+}
+
+
+
+
+
+void cClientHandle::SendEntHeadLook(const cEntity & a_Entity)
+{
+ ASSERT(a_Entity.GetUniqueID() != m_Player->GetUniqueID()); // Must not send for self
+
+ cPacket_EntityHeadLook ehl(a_Entity);
+ Send(ehl);
+}
+
+
+
+
+
+void cClientHandle::SendBlockAction(int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2)
+{
+ cPacket_BlockAction ba;
+ ba.m_BlockX = a_BlockX;
+ ba.m_BlockY = (short)a_BlockY;
+ ba.m_BlockZ = a_BlockZ;
+ ba.m_Byte1 = a_Byte1;
+ ba.m_Byte2 = a_Byte2;
+ Send(ba);
+}
+
+
+
+
+
+void cClientHandle::SendHealth(void)
+{
+ cPacket_UpdateHealth Health;
+ Health.m_Health = m_Player->GetHealth();
+ Health.m_Food = m_Player->GetFoodLevel();
+ Health.m_Saturation = m_Player->GetFoodSaturationLevel();
+ Send(Health);
+}
+
+
+
+
+
+void cClientHandle::SendRespawn(void)
+{
+ cPacket_Respawn Packet;
+ Packet.m_CreativeMode = (char)m_Player->GetGameMode(); // Set GameMode packet based on Player's GameMode;
+ Send(Packet);
+}
+
+
+
+
+
+void cClientHandle::SendGameMode(char a_GameMode)
+{
+ cPacket_NewInvalidState nis;
+ nis.m_Reason = 3;
+ nis.m_GameMode = a_GameMode;
+ Send(nis);
+}
+
+
+
+
+
+void cClientHandle::SendDestroyEntity(const cEntity & a_Entity)
+{
+ cPacket_DestroyEntity de;
+ de.m_UniqueID = a_Entity.GetUniqueID();
+ Send(de);
+}
+
+
+
+
+
+void cClientHandle::SendPlayerMoveLook(void)
+{
+ cPacket_PlayerMoveLook pml(*m_Player);
+ /*
+ LOGD("Sending PlayerMoveLook: {%0.2f, %0.2f, %0.2f}, stance %0.2f, OnGround: %d",
+ m_Player->GetPosX(), m_Player->GetPosY(), m_Player->GetPosZ(), m_Player->GetStance(), m_Player->IsOnGround() ? 1 : 0
+ );
+ */
+ Send(pml);
+}
+
+
+
+
+
void cClientHandle::CheckIfWorldDownloaded(void)
{
if (m_State != csDownloadingWorld)
@@ -1576,7 +1812,7 @@ void cClientHandle::SendConfirmPosition(void)
}
m_ConfirmPosition = m_Player->GetPosition();
- Send(cPacket_PlayerMoveLook(m_Player));
+ SendPlayerMoveLook();
}
@@ -1808,6 +2044,7 @@ void cClientHandle::GetOutgoingData(AString & a_Data)
while (!m_PendingNrmSendPackets.empty() && (Data.size() < 1000))
{
m_PendingNrmSendPackets.front()->Serialize(Data);
+ // LOGD("Sending packet 0x%02x", m_PendingNrmSendPackets.front()->m_PacketID);
delete m_PendingNrmSendPackets.front();
m_PendingNrmSendPackets.erase(m_PendingNrmSendPackets.begin());
}