1
0

Merge pull request #1485 from mc-server/PluginMessages

Rewritten plugin messages, vanilla's are being parsed directly.
This commit is contained in:
Mattes D 2014-09-30 20:48:40 +02:00
commit 5de27e7edf
6 changed files with 242 additions and 118 deletions

View File

@ -551,6 +551,16 @@ void cClientHandle::RemoveFromAllChunks()
void cClientHandle::HandleNPCTrade(int a_SlotNum)
{
// TODO
LOGWARNING("%s: Not implemented yet", __FUNCTION__);
}
void cClientHandle::HandlePing(void)
{
// Somebody tries to retrieve information about the server
@ -573,7 +583,6 @@ void cClientHandle::HandlePing(void)
bool cClientHandle::HandleLogin(int a_ProtocolVersion, const AString & a_Username)
{
LOGD("LOGIN %s", a_Username.c_str());
m_Username = a_Username;
if (cRoot::Get()->GetPluginManager()->CallHookLogin(this, a_ProtocolVersion, a_Username))
@ -676,25 +685,7 @@ void cClientHandle::HandlePlayerPos(double a_PosX, double a_PosY, double a_PosZ,
void cClientHandle::HandlePluginMessage(const AString & a_Channel, const AString & a_Message)
{
if (a_Channel == "MC|AdvCdm")
{
// Command block, set text, Client -> Server
HandleCommandBlockMessage(a_Message.c_str(), a_Message.size());
}
else if (a_Channel == "MC|Brand")
{
// Client <-> Server branding exchange
SendPluginMessage("MC|Brand", "MCServer");
}
else if (a_Channel == "MC|Beacon")
{
HandleBeaconSelection(a_Message.c_str(), a_Message.size());
}
else if (a_Channel == "MC|ItemName")
{
HandleAnvilItemName(a_Message.c_str(), a_Message.size());
}
else if (a_Channel == "REGISTER")
if (a_Channel == "REGISTER")
{
if (HasPluginChannel(a_Channel))
{
@ -777,15 +768,8 @@ void cClientHandle::UnregisterPluginChannels(const AStringVector & a_ChannelList
void cClientHandle::HandleBeaconSelection(const char * a_Data, size_t a_Length)
void cClientHandle::HandleBeaconSelection(int a_PrimaryEffect, int a_SecondaryEffect)
{
if (a_Length < 14)
{
SendChat("Failure setting beacon selection; bad request", mtFailure);
LOGD("Malformed MC|Beacon packet.");
return;
}
cWindow * Window = m_Player->GetWindow();
if ((Window == NULL) || (Window->GetWindowType() != cWindow::wtBeacon))
{
@ -798,23 +782,15 @@ void cClientHandle::HandleBeaconSelection(const char * a_Data, size_t a_Length)
return;
}
cByteBuffer Buffer(a_Length);
Buffer.Write(a_Data, a_Length);
int PrimaryEffectID, SecondaryEffectID;
Buffer.ReadBEInt(PrimaryEffectID);
Buffer.ReadBEInt(SecondaryEffectID);
cEntityEffect::eType PrimaryEffect = cEntityEffect::effNoEffect;
if ((PrimaryEffectID >= 0) && (PrimaryEffectID <= (int)cEntityEffect::effSaturation))
if ((a_PrimaryEffect >= 0) && (a_PrimaryEffect <= (int)cEntityEffect::effSaturation))
{
PrimaryEffect = (cEntityEffect::eType)PrimaryEffectID;
PrimaryEffect = (cEntityEffect::eType)a_PrimaryEffect;
}
cEntityEffect::eType SecondaryEffect = cEntityEffect::effNoEffect;
if ((SecondaryEffectID >= 0) && (SecondaryEffectID <= (int)cEntityEffect::effSaturation))
if ((a_SecondaryEffect >= 0) && (a_SecondaryEffect <= (int)cEntityEffect::effSaturation))
{
SecondaryEffect = (cEntityEffect::eType)SecondaryEffectID;
SecondaryEffect = (cEntityEffect::eType)a_SecondaryEffect;
}
Window->SetSlot(*m_Player, 0, cItem());
@ -841,52 +817,12 @@ void cClientHandle::HandleBeaconSelection(const char * a_Data, size_t a_Length)
void cClientHandle::HandleCommandBlockMessage(const char * a_Data, size_t a_Length)
void cClientHandle::HandleCommandBlockBlockChange(int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_NewCommand)
{
if (a_Length < 14)
{
SendChat("Failure setting command block command; bad request", mtFailure);
LOGD("Malformed MC|AdvCdm packet.");
return;
}
cByteBuffer Buffer(a_Length);
Buffer.Write(a_Data, a_Length);
int BlockX, BlockY, BlockZ;
AString Command;
char Mode;
Buffer.ReadChar(Mode);
switch (Mode)
{
case 0x00:
{
Buffer.ReadBEInt(BlockX);
Buffer.ReadBEInt(BlockY);
Buffer.ReadBEInt(BlockZ);
Buffer.ReadVarUTF8String(Command);
break;
}
default:
{
SendChat("Failure setting command block command; unhandled mode", mtFailure);
LOGD("Unhandled MC|AdvCdm packet mode.");
return;
}
}
cWorld * World = m_Player->GetWorld();
if (World->AreCommandBlocksEnabled())
{
World->SetCommandBlockCommand(BlockX, BlockY, BlockZ, Command);
World->SetCommandBlockCommand(a_BlockX, a_BlockY, a_BlockZ, a_NewCommand);
SendChat("Successfully set command block command", mtSuccess);
}
else
@ -899,22 +835,26 @@ void cClientHandle::HandleCommandBlockMessage(const char * a_Data, size_t a_Leng
void cClientHandle::HandleAnvilItemName(const char * a_Data, size_t a_Length)
void cClientHandle::HandleCommandBlockEntityChange(int a_EntityID, const AString & a_NewCommand)
{
if (a_Length < 1)
{
return;
}
// TODO
LOGWARNING("%s: Not implemented yet", __FUNCTION__);
}
void cClientHandle::HandleAnvilItemName(const AString & a_ItemName)
{
if ((m_Player->GetWindow() == NULL) || (m_Player->GetWindow()->GetWindowType() != cWindow::wtAnvil))
{
return;
}
AString Name(a_Data, a_Length);
if (Name.length() <= 30)
if (a_ItemName.length() <= 30)
{
((cAnvilWindow *)m_Player->GetWindow())->SetRepairedItemName(Name, m_Player);
((cAnvilWindow *)m_Player->GetWindow())->SetRepairedItemName(a_ItemName, m_Player);
}
}

View File

@ -222,6 +222,13 @@ public:
bool HasPluginChannel(const AString & a_PluginChannel);
/** Called by the protocol when it receives the MC|Brand plugin message. Also callable by plugins.
Simply stores the string value. */
void SetClientBrand(const AString & a_ClientBrand) { m_ClientBrand = a_ClientBrand; }
/** Returns the client brand received in the MC|Brand plugin message or set by a plugin. */
const AString & GetClientBrand(void) const { return m_ClientBrand; }
// tolua_end
/** Returns true if the client wants the chunk specified to be sent (in m_ChunksToSend) */
@ -236,12 +243,31 @@ public:
void PacketError(unsigned char a_PacketType);
// Calls that cProtocol descendants use for handling packets:
void HandleAnimation (char a_Animation);
void HandleChat (const AString & a_Message);
void HandleCreativeInventory(short a_SlotNum, const cItem & a_HeldItem);
void HandleEntityCrouch (int a_EntityID, bool a_IsCrouching);
void HandleEntityLeaveBed (int a_EntityID);
void HandleEntitySprinting (int a_EntityID, bool a_IsSprinting);
void HandleAnimation(char a_Animation);
/** Called when the protocol receives a MC|ItemName plugin message, indicating that the player named
an item in the anvil UI. */
void HandleAnvilItemName(const AString & a_ItemName);
/** Called when the protocol receives a MC|Beacon plugin message, indicating that the player set an effect
in the beacon UI. */
void HandleBeaconSelection(int a_PrimaryEffect, int a_SecondaryEffect);
/** Called when the protocol detects a chat packet. */
void HandleChat(const AString & a_Message);
/** Called when the protocol receives a MC|AdvCdm plugin message, indicating that the player set a new
command in the command block UI, for a block-based commandblock. */
void HandleCommandBlockBlockChange(int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_NewCommand);
/** Called when the protocol receives a MC|AdvCdm plugin message, indicating that the player set a new
command in the command block UI, for an entity-based commandblock (minecart?). */
void HandleCommandBlockEntityChange(int a_EntityID, const AString & a_NewCommand);
void HandleCreativeInventory (short a_SlotNum, const cItem & a_HeldItem);
void HandleEntityCrouch (int a_EntityID, bool a_IsCrouching);
void HandleEntityLeaveBed (int a_EntityID);
void HandleEntitySprinting (int a_EntityID, bool a_IsSprinting);
/** Called when the protocol handshake has been received (for protocol versions that support it;
otherwise the first instant when a username is received).
@ -251,6 +277,11 @@ public:
void HandleKeepAlive (int a_KeepAliveID);
void HandleLeftClick (int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, char a_Status);
/** Called when the protocol receives a MC|TrSel packet, indicating that the player used a trade in
the NPC UI. */
void HandleNPCTrade(int a_SlotNum);
void HandlePing (void);
void HandlePlayerAbilities (bool a_CanFly, bool a_IsFlying, float FlyingSpeed, float WalkingSpeed);
void HandlePlayerLook (float a_Rotation, float a_Pitch, bool a_IsOnGround);
@ -392,6 +423,9 @@ private:
/** The plugin channels that the client has registered. */
cChannels m_PluginChannels;
/** The brand identification of the client, as received in the MC|Brand plugin message or set from a plugin. */
AString m_ClientBrand;
/** Handles the block placing packet when it is a real block placement (not block-using, item-using or eating) */
@ -421,15 +455,6 @@ private:
/** Removes all of the channels from the list of current plugin channels. Ignores channels that are not found. */
void UnregisterPluginChannels(const AStringVector & a_ChannelList);
/** Handles the "MC|Beacon" plugin message */
void HandleBeaconSelection(const char * a_Data, size_t a_Length);
/** Handles the "MC|AdvCdm" plugin message */
void HandleCommandBlockMessage(const char * a_Data, size_t a_Length);
/** Handles the "MC|ItemName" plugin message */
void HandleAnvilItemName(const char * a_Data, size_t a_Length);
// cSocketThreads::cCallback overrides:
virtual bool DataReceived (const char * a_Data, size_t a_Size) override; // Data is received from the client
virtual void GetOutgoingData(AString & a_Data) override; // Data can be sent to client

View File

@ -2064,6 +2064,22 @@ void cProtocol172::HandlePacketPluginMessage(cByteBuffer & a_ByteBuffer)
{
HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Channel);
HANDLE_READ(a_ByteBuffer, ReadBEShort, short, Length);
if (Length + 1 != (int)a_ByteBuffer.GetReadableSpace())
{
LOGD("Invalid plugin message packet, payload length doesn't match packet length (exp %d, got %d)",
(int)a_ByteBuffer.GetReadableSpace() - 1, Length
);
return;
}
// If the plugin channel is recognized vanilla, handle it directly:
if (Channel.substr(0, 3) == "MC|")
{
HandleVanillaPluginMessage(a_ByteBuffer, Channel, Length);
return;
}
// Read the plugin message and relay to clienthandle:
AString Data;
if (!a_ByteBuffer.ReadString(Data, Length))
{
@ -2217,6 +2233,82 @@ void cProtocol172::HandlePacketWindowClose(cByteBuffer & a_ByteBuffer)
void cProtocol172::HandleVanillaPluginMessage(cByteBuffer & a_ByteBuffer, const AString & a_Channel, short a_PayloadLength)
{
if (a_Channel == "MC|AdvCdm")
{
HANDLE_READ(a_ByteBuffer, ReadByte, Byte, Mode);
switch (Mode)
{
case 0x00:
{
// Block-based commandblock update:
HANDLE_READ(a_ByteBuffer, ReadBEInt, int, BlockX);
HANDLE_READ(a_ByteBuffer, ReadBEInt, int, BlockY);
HANDLE_READ(a_ByteBuffer, ReadBEInt, int, BlockZ);
HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Command);
m_Client->HandleCommandBlockBlockChange(BlockX, BlockY, BlockZ, Command);
break;
}
// TODO: Entity-based commandblock update
default:
{
m_Client->SendChat(Printf("Failure setting command block command; unhandled mode %d", Mode), mtFailure);
LOG("Unhandled MC|AdvCdm packet mode.");
return;
}
} // switch (Mode)
return;
}
else if (a_Channel == "MC|Brand")
{
// Read the client's brand:
AString Brand;
if (a_ByteBuffer.ReadString(Brand, a_PayloadLength))
{
m_Client->SetClientBrand(Brand);
}
// Send back our brand:
SendPluginMessage("MC|Brand", "MCServer");
return;
}
else if (a_Channel == "MC|Beacon")
{
HANDLE_READ(a_ByteBuffer, ReadBEInt, int, Effect1);
HANDLE_READ(a_ByteBuffer, ReadBEInt, int, Effect2);
m_Client->HandleBeaconSelection(Effect1, Effect2);
return;
}
else if (a_Channel == "MC|ItemName")
{
AString ItemName;
if (a_ByteBuffer.ReadString(ItemName, a_PayloadLength))
{
m_Client->HandleAnvilItemName(ItemName);
}
return;
}
else if (a_Channel == "MC|TrSel")
{
HANDLE_READ(a_ByteBuffer, ReadBEInt, int, SlotNum);
m_Client->HandleNPCTrade(SlotNum);
return;
}
LOG("Unhandled vanilla plugin channel: \"%s\".", a_Channel.c_str());
// Read the payload and send it through to the clienthandle:
AString Message;
VERIFY(a_ByteBuffer.ReadString(Message, a_PayloadLength));
m_Client->HandlePluginMessage(a_Channel, Message);
}
void cProtocol172::SendData(const char * a_Data, size_t a_Size)
{
if (m_IsEncrypted)

View File

@ -295,6 +295,9 @@ protected:
void HandlePacketWindowClick (cByteBuffer & a_ByteBuffer);
void HandlePacketWindowClose (cByteBuffer & a_ByteBuffer);
/** Parses Vanilla plugin messages into specific ClientHandle calls.
The message payload is still in the bytebuffer, to be read by this function. */
void HandleVanillaPluginMessage(cByteBuffer & a_ByteBuffer, const AString & a_Channel, short a_PayloadLength);
/** Sends the data to the client, encrypting them if needed. */
virtual void SendData(const char * a_Data, size_t a_Size) override;

View File

@ -989,10 +989,6 @@ void cProtocol180::SendPluginMessage(const AString & a_Channel, const AString &
cPacketizer Pkt(*this, 0x3f);
Pkt.WriteString(a_Channel);
if (a_Channel.substr(0, 3) == "MC|")
{
Pkt.WriteVarInt((UInt32)a_Message.size());
}
Pkt.WriteBuf(a_Message.data(), a_Message.size());
}
@ -2324,18 +2320,17 @@ void cProtocol180::HandlePacketPlayerPosLook(cByteBuffer & a_ByteBuffer)
void cProtocol180::HandlePacketPluginMessage(cByteBuffer & a_ByteBuffer)
{
HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Channel);
AString Data;
// If the plugin channel is recognized vanilla, handle it directly:
if (Channel.substr(0, 3) == "MC|")
{
// Vanilla sends the payload length within the payload itself, so skip it:
HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, DataLen);
if (DataLen != a_ByteBuffer.GetReadableSpace() - 1)
{
ASSERT(!"Bad plugin message payload length");
return;
}
HandleVanillaPluginMessage(a_ByteBuffer, Channel);
return;
}
a_ByteBuffer.ReadString(Data, a_ByteBuffer.GetReadableSpace() - 1); // Always succeeds
// Read the plugin message and relay to clienthandle:
AString Data;
VERIFY(a_ByteBuffer.ReadString(Data, a_ByteBuffer.GetReadableSpace() - 1)); // Always succeeds
m_Client->HandlePluginMessage(Channel, Data);
}
@ -2524,6 +2519,71 @@ void cProtocol180::HandlePacketWindowClose(cByteBuffer & a_ByteBuffer)
void cProtocol180::HandleVanillaPluginMessage(cByteBuffer & a_ByteBuffer, const AString & a_Channel)
{
if (a_Channel == "MC|AdvCdm")
{
HANDLE_READ(a_ByteBuffer, ReadByte, Byte, Mode)
switch (Mode)
{
case 0x00:
{
HANDLE_READ(a_ByteBuffer, ReadBEInt, int, BlockX);
HANDLE_READ(a_ByteBuffer, ReadBEInt, int, BlockY);
HANDLE_READ(a_ByteBuffer, ReadBEInt, int, BlockZ);
HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Command);
m_Client->HandleCommandBlockBlockChange(BlockX, BlockY, BlockZ, Command);
break;
}
default:
{
m_Client->SendChat(Printf("Failure setting command block command; unhandled mode %d", Mode), mtFailure);
LOG("Unhandled MC|AdvCdm packet mode.");
return;
}
} // switch (Mode)
return;
}
else if (a_Channel == "MC|Brand")
{
HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Brand);
m_Client->SetClientBrand(Brand);
// Send back our brand, including the length:
SendPluginMessage("MC|Brand", "\x08MCServer");
return;
}
else if (a_Channel == "MC|Beacon")
{
HANDLE_READ(a_ByteBuffer, ReadBEInt, int, Effect1);
HANDLE_READ(a_ByteBuffer, ReadBEInt, int, Effect2);
m_Client->HandleBeaconSelection(Effect1, Effect2);
return;
}
else if (a_Channel == "MC|ItemName")
{
HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, ItemName);
m_Client->HandleAnvilItemName(ItemName);
return;
}
else if (a_Channel == "MC|TrSel")
{
HANDLE_READ(a_ByteBuffer, ReadBEInt, int, SlotNum);
m_Client->HandleNPCTrade(SlotNum);
return;
}
LOG("Unhandled vanilla plugin channel: \"%s\".", a_Channel.c_str());
// Read the payload and send it through to the clienthandle:
AString Message;
VERIFY(a_ByteBuffer.ReadString(Message, a_ByteBuffer.GetReadableSpace() - 1));
m_Client->HandlePluginMessage(a_Channel, Message);
}
void cProtocol180::SendData(const char * a_Data, size_t a_Size)
{
if (m_IsEncrypted)

View File

@ -312,6 +312,10 @@ protected:
void HandlePacketWindowClick (cByteBuffer & a_ByteBuffer);
void HandlePacketWindowClose (cByteBuffer & a_ByteBuffer);
/** Parses Vanilla plugin messages into specific ClientHandle calls.
The message payload is still in the bytebuffer, the handler reads it specifically for each handled channel */
void HandleVanillaPluginMessage(cByteBuffer & a_ByteBuffer, const AString & a_Channel);
/** Sends the data to the client, encrypting them if needed. */
virtual void SendData(const char * a_Data, size_t a_Size) override;