// Protocol15x.cpp
/*
Implements the 1.5.x protocol classes:
- cProtocol150
- release 1.5 protocol (#60)
- release 1.5.2 protocol (#61, no relevant changes found)
*/
#include "Globals.h"
#include "Protocol15x.h"
#include "../ClientHandle.h"
#include "../Item.h"
#include "../UI/Window.h"
#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_WINDOW_OPEN = 0x64,
PACKET_PARTICLE_EFFECT = 0x3F,
PACKET_SCOREBOARD_OBJECTIVE = 0xCE,
PACKET_SCORE_UPDATE = 0xCF,
PACKET_DISPLAY_OBJECTIVE = 0xD0
} ;
////////////////////////////////////////////////////////////////////////////////
// cProtocol150:
cProtocol150::cProtocol150(cClientHandle * a_Client) :
super(a_Client)
{
}
void cProtocol150::SendWindowOpen(const cWindow & a_Window)
{
if (a_Window.GetWindowType() < 0)
{
// Do not send for inventory windows
return;
}
cCSLock Lock(m_CSPacket);
WriteByte (PACKET_WINDOW_OPEN);
WriteByte (a_Window.GetWindowID());
WriteByte (a_Window.GetWindowType());
WriteString(a_Window.GetWindowTitle());
WriteByte (a_Window.GetNumNonInventorySlots());
WriteByte (1); // Use title
Flush();
}
void cProtocol150::SendParticleEffect(const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount)
{
cCSLock Lock(m_CSPacket);
WriteByte(PACKET_PARTICLE_EFFECT);
WriteString(a_ParticleName);
WriteFloat(a_SrcX);
WriteFloat(a_SrcY);
WriteFloat(a_SrcZ);
WriteFloat(a_OffsetX);
WriteFloat(a_OffsetY);
WriteFloat(a_OffsetZ);
WriteFloat(a_ParticleData);
WriteInt(a_ParticleAmmount);
Flush();
}
void cProtocol150::SendScoreboardObjective(const AString & a_Name, const AString & a_DisplayName, Byte a_Mode)
{
cCSLock Lock(m_CSPacket);
WriteByte(PACKET_SCOREBOARD_OBJECTIVE);
WriteString(a_Name);
WriteString(a_DisplayName);
WriteByte(a_Mode);
Flush();
}
void cProtocol150::SendScoreUpdate(const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode)
{
cCSLock Lock(m_CSPacket);
WriteByte(PACKET_SCORE_UPDATE);
WriteString(a_Player);
WriteByte(a_Mode);
if (a_Mode != 1)
{
WriteString(a_Objective);
WriteInt((int) a_Score);
}
Flush();
}
void cProtocol150::SendDisplayObjective(const AString & a_Objective, cScoreboard::eDisplaySlot a_Display)
{
cCSLock Lock(m_CSPacket);
WriteByte(PACKET_DISPLAY_OBJECTIVE);
WriteByte((int) a_Display);
WriteString(a_Objective);
Flush();
}
int cProtocol150::ParseWindowClick(void)
{
HANDLE_PACKET_READ(ReadChar, char, WindowID);
HANDLE_PACKET_READ(ReadBEShort, short, SlotNum);
HANDLE_PACKET_READ(ReadByte, Byte, Button);
HANDLE_PACKET_READ(ReadBEShort, short, TransactionID);
HANDLE_PACKET_READ(ReadByte, Byte, Mode);
cItem HeldItem;
int res = ParseItem(HeldItem);
if (res < 0)
{
return res;
}
// Convert Button, Mode, SlotNum and HeldItem into eClickAction:
eClickAction Action = caUnknown;
switch ((Mode << 8) | Button)
{
case 0x0000: Action = (SlotNum != -999) ? caLeftClick : caLeftClickOutside; break;
case 0x0001: Action = (SlotNum != -999) ? caRightClick : caRightClickOutside; break;
case 0x0100: Action = caShiftLeftClick; break;
case 0x0101: Action = caShiftRightClick; break;
case 0x0200: Action = caNumber1; break;
case 0x0201: Action = caNumber2; break;
case 0x0202: Action = caNumber3; break;
case 0x0203: Action = caNumber4; break;
case 0x0204: Action = caNumber5; break;
case 0x0205: Action = caNumber6; break;
case 0x0206: Action = caNumber7; break;
case 0x0207: Action = caNumber8; break;
case 0x0208: Action = caNumber9; break;
case 0x0300: Action = caMiddleClick; break;
case 0x0400: Action = (SlotNum == -999) ? caLeftClickOutsideHoldNothing : caDropKey; break;
case 0x0401: Action = (SlotNum == -999) ? caRightClickOutsideHoldNothing : caCtrlDropKey; break;
case 0x0500: Action = (SlotNum == -999) ? caLeftPaintBegin : caUnknown; break;
case 0x0501: Action = (SlotNum != -999) ? caLeftPaintProgress : caUnknown; break;
case 0x0502: Action = (SlotNum == -999) ? caLeftPaintEnd : caUnknown; break;
case 0x0504: Action = (SlotNum == -999) ? caRightPaintBegin : caUnknown; break;
case 0x0505: Action = (SlotNum != -999) ? caRightPaintProgress : caUnknown; break;
case 0x0506: Action = (SlotNum == -999) ? caRightPaintEnd : caUnknown; break;
case 0x0600: Action = caDblClick; break;
}
if (Action == caUnknown)
{
LOGWARNING("Received an unknown click action combination: Mode = %d, Button = %d, Slot = %d, HeldItem = %s. Ignoring packet.",
Mode, Button, SlotNum, ItemToFullString(HeldItem).c_str()
);
ASSERT(!"Unknown click action");
return PARSE_OK;
}
m_Client->HandleWindowClick(WindowID, SlotNum, Action, HeldItem);
return PARSE_OK;
}