2013-07-29 07:13:03 -04:00
|
|
|
|
|
|
|
// Protocol16x.cpp
|
|
|
|
|
|
|
|
/*
|
|
|
|
Implements the 1.6.x protocol classes:
|
|
|
|
- cProtocol161
|
|
|
|
- release 1.6.1 protocol (#73)
|
|
|
|
- cProtocol162
|
|
|
|
- release 1.6.2 protocol (#74)
|
2013-09-19 14:49:09 -04:00
|
|
|
- release 1.6.3 protocol (#77) - no relevant changes
|
|
|
|
- release 1.6.4 protocol (#78) - no relevant changes
|
2013-07-29 07:13:03 -04:00
|
|
|
(others may be added later in the future for the 1.6 release series)
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "Globals.h"
|
|
|
|
#include "Protocol16x.h"
|
|
|
|
#include "../ClientHandle.h"
|
2013-08-19 05:39:13 -04:00
|
|
|
#include "../Entities/Entity.h"
|
|
|
|
#include "../Entities/Player.h"
|
2013-11-08 15:32:14 -05:00
|
|
|
#include "../UI/Window.h"
|
2014-04-06 16:28:41 -04:00
|
|
|
#include "../CompositeChat.h"
|
2013-07-29 07:13:03 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define HANDLE_PACKET_READ(Proc, Type, Var) \
|
|
|
|
Type Var; \
|
|
|
|
{ \
|
|
|
|
if (!m_ReceivedData.Proc(Var)) \
|
|
|
|
{ \
|
|
|
|
m_ReceivedData.CheckValid(); \
|
|
|
|
return PARSE_INCOMPLETE; \
|
|
|
|
} \
|
|
|
|
m_ReceivedData.CheckValid(); \
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
PACKET_CHAT = 0x03,
|
|
|
|
PACKET_UPDATE_HEALTH = 0x08,
|
|
|
|
PACKET_STEER_VEHICLE = 0x1b,
|
|
|
|
PACKET_ATTACH_ENTITY = 0x27,
|
|
|
|
PACKET_ENTITY_PROPERTIES = 0x2c,
|
|
|
|
PACKET_WINDOW_OPEN = 0x64,
|
2013-07-29 15:42:05 -04:00
|
|
|
PACKET_TILE_EDITOR_OPEN = 0x85,
|
2013-07-29 07:13:03 -04:00
|
|
|
PACKET_PLAYER_ABILITIES = 0xca,
|
|
|
|
} ;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-07-17 16:15:34 -04:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2013-07-29 07:13:03 -04:00
|
|
|
// cProtocol161:
|
|
|
|
|
|
|
|
cProtocol161::cProtocol161(cClientHandle * a_Client) :
|
|
|
|
super(a_Client)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void cProtocol161::SendAttachEntity(const cEntity & a_Entity, const cEntity * a_Vehicle)
|
|
|
|
{
|
|
|
|
cCSLock Lock(m_CSPacket);
|
|
|
|
WriteByte(PACKET_ATTACH_ENTITY);
|
|
|
|
WriteInt(a_Entity.GetUniqueID());
|
|
|
|
WriteInt((a_Vehicle == NULL) ? -1 : a_Vehicle->GetUniqueID());
|
|
|
|
WriteBool(false); // TODO: "Should use leash?" -> no
|
|
|
|
Flush();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void cProtocol161::SendChat(const AString & a_Message)
|
|
|
|
{
|
|
|
|
super::SendChat(Printf("{\"text\":\"%s\"}", EscapeString(a_Message).c_str()));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-07-29 15:42:05 -04:00
|
|
|
|
2014-04-06 16:28:41 -04:00
|
|
|
void cProtocol161::SendChat(const cCompositeChat & a_Message)
|
|
|
|
{
|
|
|
|
// This protocol version doesn't support composite messages to the full
|
|
|
|
// Just extract each part's text and use it:
|
|
|
|
|
|
|
|
super::SendChat(Printf("{\"text\":\"%s\"}", EscapeString(a_Message.ExtractText()).c_str()));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-07-29 15:42:05 -04:00
|
|
|
void cProtocol161::SendEditSign(int a_BlockX, int a_BlockY, int a_BlockZ)
|
|
|
|
{
|
|
|
|
cCSLock Lock(m_CSPacket);
|
|
|
|
WriteByte(PACKET_TILE_EDITOR_OPEN);
|
|
|
|
WriteByte(0);
|
|
|
|
WriteInt(a_BlockX);
|
|
|
|
WriteInt(a_BlockY);
|
|
|
|
WriteInt(a_BlockZ);
|
|
|
|
Flush();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-07-29 07:13:03 -04:00
|
|
|
void cProtocol161::SendGameMode(eGameMode a_GameMode)
|
|
|
|
{
|
|
|
|
super::SendGameMode(a_GameMode);
|
|
|
|
SendPlayerMaxSpeed();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void cProtocol161::SendHealth(void)
|
|
|
|
{
|
|
|
|
cCSLock Lock(m_CSPacket);
|
|
|
|
WriteByte (PACKET_UPDATE_HEALTH);
|
2014-04-18 15:09:44 -04:00
|
|
|
cPlayer * Player = m_Client->GetPlayer();
|
|
|
|
WriteFloat((float)Player->GetHealth());
|
|
|
|
WriteShort((short)Player->GetFoodLevel());
|
|
|
|
WriteFloat((float)Player->GetFoodSaturationLevel());
|
2013-07-29 07:13:03 -04:00
|
|
|
Flush();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void cProtocol161::SendPlayerMaxSpeed(void)
|
|
|
|
{
|
|
|
|
cCSLock Lock(m_CSPacket);
|
2014-04-18 15:09:44 -04:00
|
|
|
cPlayer * Player = m_Client->GetPlayer();
|
2013-07-29 07:13:03 -04:00
|
|
|
WriteByte(PACKET_ENTITY_PROPERTIES);
|
2014-04-18 15:09:44 -04:00
|
|
|
WriteInt(Player->GetUniqueID());
|
2013-07-29 07:13:03 -04:00
|
|
|
WriteInt(1);
|
|
|
|
WriteString("generic.movementSpeed");
|
2014-04-18 15:09:44 -04:00
|
|
|
WriteDouble(0.1 * Player->GetMaxSpeed());
|
2013-07-29 07:13:03 -04:00
|
|
|
Flush();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-06-29 17:44:01 -04:00
|
|
|
void cProtocol161::SendRespawn(const cWorld & a_World, bool a_ShouldIgnoreDimensionChecks)
|
2013-07-29 07:13:03 -04:00
|
|
|
{
|
|
|
|
// Besides sending the respawn, we need to also send the player max speed, otherwise the client reverts to super-fast
|
2014-06-29 17:44:01 -04:00
|
|
|
super::SendRespawn(a_World, a_ShouldIgnoreDimensionChecks);
|
2013-07-29 07:13:03 -04:00
|
|
|
SendPlayerMaxSpeed();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-11-08 15:32:14 -05:00
|
|
|
void cProtocol161::SendWindowOpen(const cWindow & a_Window)
|
2013-07-29 07:13:03 -04:00
|
|
|
{
|
2013-11-08 15:32:14 -05:00
|
|
|
if (a_Window.GetWindowType() < 0)
|
2013-07-29 07:13:03 -04:00
|
|
|
{
|
|
|
|
// Do not send for inventory windows
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
cCSLock Lock(m_CSPacket);
|
|
|
|
WriteByte (PACKET_WINDOW_OPEN);
|
2014-04-04 05:47:46 -04:00
|
|
|
WriteChar (a_Window.GetWindowID());
|
|
|
|
WriteByte ((Byte)a_Window.GetWindowType());
|
2013-11-08 15:32:14 -05:00
|
|
|
WriteString(a_Window.GetWindowTitle());
|
2014-04-04 05:47:46 -04:00
|
|
|
WriteByte ((Byte)a_Window.GetNumNonInventorySlots());
|
2013-07-29 07:13:03 -04:00
|
|
|
WriteByte (1); // Use title
|
2013-11-08 15:32:14 -05:00
|
|
|
if (a_Window.GetWindowType() == cWindow::wtAnimalChest)
|
2013-07-29 07:13:03 -04:00
|
|
|
{
|
2013-11-08 15:32:14 -05:00
|
|
|
WriteInt(0); // TODO: The animal's EntityID
|
2013-07-29 07:13:03 -04:00
|
|
|
}
|
|
|
|
Flush();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int cProtocol161::ParseEntityAction(void)
|
|
|
|
{
|
|
|
|
HANDLE_PACKET_READ(ReadBEInt, int, EntityID);
|
|
|
|
HANDLE_PACKET_READ(ReadChar, char, ActionID);
|
|
|
|
HANDLE_PACKET_READ(ReadBEInt, int, UnknownHorseVal);
|
2014-03-08 11:55:53 -05:00
|
|
|
|
2014-03-08 13:26:32 -05:00
|
|
|
switch (ActionID)
|
2014-03-08 11:55:53 -05:00
|
|
|
{
|
2014-07-17 16:15:34 -04:00
|
|
|
case 1: m_Client->HandleEntityCrouch(EntityID, true); break; // Crouch
|
|
|
|
case 2: m_Client->HandleEntityCrouch(EntityID, false); break; // Uncrouch
|
|
|
|
case 3: m_Client->HandleEntityLeaveBed(EntityID); break; // Leave Bed
|
|
|
|
case 4: m_Client->HandleEntitySprinting(EntityID, true); break; // Start sprinting
|
|
|
|
case 5: m_Client->HandleEntitySprinting(EntityID, false); break; // Stop sprinting
|
2014-03-08 11:55:53 -05:00
|
|
|
}
|
|
|
|
|
2013-07-29 07:13:03 -04:00
|
|
|
return PARSE_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-04-21 02:22:25 -04:00
|
|
|
int cProtocol161::ParseLogin(void)
|
|
|
|
{
|
|
|
|
// The login packet is sent by Forge clients only
|
|
|
|
// Only parse the packet, do no extra processing
|
|
|
|
// Note that the types and the names have been only guessed and are not verified at all!
|
|
|
|
HANDLE_PACKET_READ(ReadBEInt, int, Int1);
|
|
|
|
HANDLE_PACKET_READ(ReadBEUTF16String16, AString, String1);
|
|
|
|
HANDLE_PACKET_READ(ReadChar, char, Char1);
|
|
|
|
HANDLE_PACKET_READ(ReadChar, char, Char2);
|
|
|
|
HANDLE_PACKET_READ(ReadChar, char, Char3);
|
|
|
|
HANDLE_PACKET_READ(ReadByte, Byte, Byte1);
|
|
|
|
HANDLE_PACKET_READ(ReadByte, Byte, Byte2);
|
|
|
|
return PARSE_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-07-29 07:13:03 -04:00
|
|
|
int cProtocol161::ParsePlayerAbilities(void)
|
|
|
|
{
|
|
|
|
HANDLE_PACKET_READ(ReadByte, Byte, Flags);
|
|
|
|
HANDLE_PACKET_READ(ReadBEFloat, float, FlyingSpeed);
|
|
|
|
HANDLE_PACKET_READ(ReadBEFloat, float, WalkingSpeed);
|
|
|
|
// TODO: m_Client->HandlePlayerAbilities(...);
|
|
|
|
return PARSE_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int cProtocol161::ParseSteerVehicle(void)
|
|
|
|
{
|
|
|
|
HANDLE_PACKET_READ(ReadBEFloat, float, Sideways);
|
|
|
|
HANDLE_PACKET_READ(ReadBEFloat, float, Forward);
|
|
|
|
HANDLE_PACKET_READ(ReadBool, bool, Jump);
|
|
|
|
HANDLE_PACKET_READ(ReadBool, bool, Unmount);
|
|
|
|
if (Unmount)
|
|
|
|
{
|
|
|
|
m_Client->HandleUnmount();
|
|
|
|
}
|
2013-09-05 18:04:49 -04:00
|
|
|
else
|
|
|
|
{
|
|
|
|
m_Client->HandleSteerVehicle(Forward, Sideways);
|
|
|
|
}
|
2013-07-29 07:13:03 -04:00
|
|
|
return PARSE_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int cProtocol161::ParsePacket(unsigned char a_PacketType)
|
|
|
|
{
|
|
|
|
switch (a_PacketType)
|
|
|
|
{
|
|
|
|
case PACKET_STEER_VEHICLE: return ParseSteerVehicle();
|
|
|
|
default: return super::ParsePacket(a_PacketType);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-07-17 16:15:34 -04:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2013-07-29 07:13:03 -04:00
|
|
|
// cProtocol162:
|
|
|
|
|
|
|
|
cProtocol162::cProtocol162(cClientHandle * a_Client) :
|
|
|
|
super(a_Client)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void cProtocol162::SendPlayerMaxSpeed(void)
|
|
|
|
{
|
|
|
|
cCSLock Lock(m_CSPacket);
|
2014-04-18 15:09:44 -04:00
|
|
|
cPlayer * Player = m_Client->GetPlayer();
|
2013-07-29 07:13:03 -04:00
|
|
|
WriteByte(PACKET_ENTITY_PROPERTIES);
|
2014-04-18 15:09:44 -04:00
|
|
|
WriteInt(Player->GetUniqueID());
|
2013-07-29 07:13:03 -04:00
|
|
|
WriteInt(1);
|
|
|
|
WriteString("generic.movementSpeed");
|
2014-04-18 15:09:44 -04:00
|
|
|
WriteDouble(0.1 * Player->GetMaxSpeed());
|
2013-07-29 07:13:03 -04:00
|
|
|
WriteShort(0);
|
|
|
|
Flush();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|