diff options
author | Alexander Harkness <bearbin@gmail.com> | 2013-11-24 15:19:41 +0100 |
---|---|---|
committer | Alexander Harkness <bearbin@gmail.com> | 2013-11-24 15:19:41 +0100 |
commit | 675b4aa878f16291ce33fced48a2bc7425f635ae (patch) | |
tree | 409914df27a98f65adf866da669429c4de141b6f /source/Protocol/Protocol125.cpp | |
parent | LineBlockTracer: Using the coord-based block faces. (diff) | |
download | cuberite-675b4aa878f16291ce33fced48a2bc7425f635ae.tar cuberite-675b4aa878f16291ce33fced48a2bc7425f635ae.tar.gz cuberite-675b4aa878f16291ce33fced48a2bc7425f635ae.tar.bz2 cuberite-675b4aa878f16291ce33fced48a2bc7425f635ae.tar.lz cuberite-675b4aa878f16291ce33fced48a2bc7425f635ae.tar.xz cuberite-675b4aa878f16291ce33fced48a2bc7425f635ae.tar.zst cuberite-675b4aa878f16291ce33fced48a2bc7425f635ae.zip |
Diffstat (limited to 'source/Protocol/Protocol125.cpp')
-rw-r--r-- | source/Protocol/Protocol125.cpp | 1869 |
1 files changed, 0 insertions, 1869 deletions
diff --git a/source/Protocol/Protocol125.cpp b/source/Protocol/Protocol125.cpp deleted file mode 100644 index 9f2770815..000000000 --- a/source/Protocol/Protocol125.cpp +++ /dev/null @@ -1,1869 +0,0 @@ - -// Protocol125.cpp - -// Implements the cProtocol125 class representing the release 1.2.5 protocol (#29) -/* -Documentation: - - protocol: http://wiki.vg/wiki/index.php?title=Protocol&oldid=2513 - - session handling: http://wiki.vg/wiki/index.php?title=Session&oldid=2262 - - slot format: http://wiki.vg/wiki/index.php?title=Slot_Data&oldid=2152 -*/ - -#include "Globals.h" - -#include "Protocol125.h" - -#include "../ClientHandle.h" -#include "../World.h" -#include "ChunkDataSerializer.h" -#include "../Entities/Entity.h" -#include "../Mobs/Monster.h" -#include "../Entities/Pickup.h" -#include "../Entities/Player.h" -#include "../ChatColor.h" -#include "../UI/Window.h" -#include "../Root.h" -#include "../Server.h" - -#include "../Entities/ProjectileEntity.h" -#include "../Entities/Minecart.h" -#include "../Entities/FallingBlock.h" - -#include "../Mobs/IncludeAllMonsters.h" - - - - - -enum -{ - PACKET_KEEP_ALIVE = 0x00, - PACKET_LOGIN = 0x01, - PACKET_HANDSHAKE = 0x02, - PACKET_CHAT = 0x03, - PACKET_UPDATE_TIME = 0x04, - PACKET_ENTITY_EQUIPMENT = 0x05, - PACKET_USE_ENTITY = 0x07, - PACKET_UPDATE_HEALTH = 0x08, - PACKET_RESPAWN = 0x09, - PACKET_PLAYER_ON_GROUND = 0x0a, - PACKET_PLAYER_POS = 0x0b, - PACKET_PLAYER_LOOK = 0x0c, - PACKET_PLAYER_MOVE_LOOK = 0x0d, - PACKET_BLOCK_DIG = 0x0e, - PACKET_BLOCK_PLACE = 0x0f, - PACKET_SLOT_SELECTED = 0x10, - PACKET_USE_BED = 0x11, - PACKET_ANIMATION = 0x12, - PACKET_PACKET_ENTITY_ACTION = 0x13, - PACKET_PLAYER_SPAWN = 0x14, - PACKET_PICKUP_SPAWN = 0x15, - PACKET_COLLECT_PICKUP = 0x16, - PACKET_SPAWN_OBJECT = 0x17, - PACKET_SPAWN_MOB = 0x18, - PACKET_ENTITY_VELOCITY = 0x1c, - PACKET_DESTROY_ENTITY = 0x1d, - PACKET_ENTITY = 0x1e, - PACKET_ENT_REL_MOVE = 0x1f, - PACKET_ENT_LOOK = 0x20, - PACKET_ENT_REL_MOVE_LOOK = 0x21, - PACKET_ENT_TELEPORT = 0x22, - PACKET_ENT_HEAD_LOOK = 0x23, - PACKET_ENT_STATUS = 0x26, - PACKET_ATTACH_ENTITY = 0x27, - PACKET_METADATA = 0x28, - PACKET_PRE_CHUNK = 0x32, - PACKET_MAP_CHUNK = 0x33, - PACKET_MULTI_BLOCK = 0x34, - PACKET_BLOCK_CHANGE = 0x35, - PACKET_BLOCK_ACTION = 0x36, - PACKET_EXPLOSION = 0x3C, - PACKET_SOUND_EFFECT = 0x3e, - PACKET_SOUND_PARTICLE_EFFECT = 0x3d, - PACKET_CHANGE_GAME_STATE = 0x46, - PACKET_THUNDERBOLT = 0x47, - PACKET_WINDOW_OPEN = 0x64, - PACKET_WINDOW_CLOSE = 0x65, - PACKET_WINDOW_CLICK = 0x66, - PACKET_INVENTORY_SLOT = 0x67, - PACKET_INVENTORY_WHOLE = 0x68, - PACKET_WINDOW_PROPERTY = 0x69, - PACKET_CREATIVE_INVENTORY_ACTION = 0x6B, - PACKET_UPDATE_SIGN = 0x82, - PACKET_PLAYER_LIST_ITEM = 0xC9, - PACKET_PLAYER_ABILITIES = 0xca, - PACKET_PLUGIN_MESSAGE = 0xfa, - PACKET_PING = 0xfe, - PACKET_DISCONNECT = 0xff -} ; - - - - - -#define HANDLE_PACKET_READ(Proc, Type, Var) \ - Type Var; \ - { \ - if (!m_ReceivedData.Proc(Var)) \ - { \ - m_ReceivedData.CheckValid(); \ - return PARSE_INCOMPLETE; \ - } \ - m_ReceivedData.CheckValid(); \ - } - - - - -typedef unsigned char Byte; - - - - - -cProtocol125::cProtocol125(cClientHandle * a_Client) : - super(a_Client), - m_ReceivedData(32 KiB) -{ -} - - - - - -void cProtocol125::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()); - Flush(); -} - - - - - -void cProtocol125::SendBlockAction(int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) -{ - UNUSED(a_BlockType); - - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_BLOCK_ACTION); - WriteInt (a_BlockX); - WriteShort((short)a_BlockY); - WriteInt (a_BlockZ); - WriteByte (a_Byte1); - WriteByte (a_Byte2); - Flush(); -} - - - - - -void cProtocol125::SendBlockBreakAnim(int a_entityID, int a_BlockX, int a_BlockY, int a_BlockZ, char stage) -{ - // Not supported in this protocol version -} - - - - - -void cProtocol125::SendBlockChange(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) -{ - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_BLOCK_CHANGE); - WriteInt (a_BlockX); - WriteByte((unsigned char)a_BlockY); - WriteInt (a_BlockZ); - WriteByte(a_BlockType); - WriteByte(a_BlockMeta); - Flush(); -} - - - - - -void cProtocol125::SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) -{ - cCSLock Lock(m_CSPacket); - if (a_Changes.size() == 1) - { - // Special packet for single-block changes - const sSetBlock & blk = a_Changes.front(); - SendBlockChange(a_ChunkX * cChunkDef::Width + blk.x, blk.y, a_ChunkZ * cChunkDef::Width + blk.z, blk.BlockType, blk.BlockMeta); - return; - } - - WriteByte (PACKET_MULTI_BLOCK); - WriteInt (a_ChunkX); - WriteInt (a_ChunkZ); - WriteShort((unsigned short)a_Changes.size()); - WriteUInt (sizeof(int) * a_Changes.size()); - for (sSetBlockVector::const_iterator itr = a_Changes.begin(), end = a_Changes.end(); itr != end; ++itr) - { - unsigned int Coords = itr->y | (itr->z << 8) | (itr->x << 12); - unsigned int Blocks = itr->BlockMeta | (itr->BlockType << 4); - WriteUInt(Coords << 16 | Blocks); - } - Flush(); -} - - - - - -void cProtocol125::SendChat(const AString & a_Message) -{ - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_CHAT); - WriteString(a_Message); - Flush(); -} - - - - - -void cProtocol125::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) -{ - cCSLock Lock(m_CSPacket); - - // Send the pre-chunk: - SendPreChunk(a_ChunkX, a_ChunkZ, true); - - // Send the chunk data: - AString Serialized = a_Serializer.Serialize(cChunkDataSerializer::RELEASE_1_2_5); - WriteByte(PACKET_MAP_CHUNK); - WriteInt (a_ChunkX); - WriteInt (a_ChunkZ); - SendData(Serialized.data(), Serialized.size()); - Flush(); -} - - - - - -void cProtocol125::SendCollectPickup(const cPickup & a_Pickup, const cPlayer & a_Player) -{ - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_COLLECT_PICKUP); - WriteInt (a_Pickup.GetUniqueID()); - WriteInt (a_Player.GetUniqueID()); - Flush(); -} - - - - - -void cProtocol125::SendDestroyEntity(const cEntity & a_Entity) -{ - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_DESTROY_ENTITY); - WriteInt (a_Entity.GetUniqueID()); - Flush(); -} - - - - - -void cProtocol125::SendDisconnect(const AString & a_Reason) -{ - cCSLock Lock(m_CSPacket); - WriteByte ((unsigned char)PACKET_DISCONNECT); - WriteString(a_Reason); - Flush(); -} - - - - - -void cProtocol125::SendEditSign(int a_BlockX, int a_BlockY, int a_BlockZ) -{ - // This protocol version doesn't support this packet, sign editor is invoked by the client automatically - UNUSED(a_BlockX); - UNUSED(a_BlockY); - UNUSED(a_BlockZ); -} - - - - - -void cProtocol125::SendEntityEquipment(const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) -{ - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_ENTITY_EQUIPMENT); - WriteInt (a_Entity.GetUniqueID()); - WriteShort(a_SlotNum); - WriteShort(a_Item.m_ItemType); - WriteShort(a_Item.m_ItemDamage); - Flush(); -} - - - - - -void cProtocol125::SendEntityHeadLook(const cEntity & a_Entity) -{ - ASSERT(a_Entity.GetUniqueID() != m_Client->GetPlayer()->GetUniqueID()); // Must not send for self - - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_ENT_HEAD_LOOK); - WriteInt (a_Entity.GetUniqueID()); - WriteByte((char)((a_Entity.GetHeadYaw() / 360.f) * 256)); - Flush(); -} - - - - - -void cProtocol125::SendEntityLook(const cEntity & a_Entity) -{ - ASSERT(a_Entity.GetUniqueID() != m_Client->GetPlayer()->GetUniqueID()); // Must not send for self - - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_ENT_LOOK); - WriteInt (a_Entity.GetUniqueID()); - WriteByte((char)((a_Entity.GetRotation() / 360.f) * 256)); - WriteByte((char)((a_Entity.GetPitch() / 360.f) * 256)); - Flush(); -} - - - - - -void cProtocol125::SendEntityMetadata(const cEntity & a_Entity) -{ - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_METADATA); - WriteInt (a_Entity.GetUniqueID()); - - WriteCommonMetadata(a_Entity); - if (a_Entity.IsMob()) - { - WriteMobMetadata(((const cMonster &)a_Entity)); - } - else - { - WriteEntityMetadata(a_Entity); - } - WriteByte(0x7f); - - Flush(); -} - - - - - -void cProtocol125::SendEntityProperties(const cEntity & a_Entity) -{ - // Not supported in this protocol version -} - - - - - -void cProtocol125::SendEntityRelMove(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) -{ - ASSERT(a_Entity.GetUniqueID() != m_Client->GetPlayer()->GetUniqueID()); // Must not send for self - - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_ENT_REL_MOVE); - WriteInt (a_Entity.GetUniqueID()); - WriteByte(a_RelX); - WriteByte(a_RelY); - WriteByte(a_RelZ); - Flush(); -} - - - - - -void cProtocol125::SendEntityRelMoveLook(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) -{ - ASSERT(a_Entity.GetUniqueID() != m_Client->GetPlayer()->GetUniqueID()); // Must not send for self - - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_ENT_REL_MOVE_LOOK); - WriteInt (a_Entity.GetUniqueID()); - WriteByte(a_RelX); - WriteByte(a_RelY); - WriteByte(a_RelZ); - WriteByte((char)((a_Entity.GetRotation() / 360.f) * 256)); - WriteByte((char)((a_Entity.GetPitch() / 360.f) * 256)); - Flush(); -} - - - - - -void cProtocol125::SendEntityStatus(const cEntity & a_Entity, char a_Status) -{ - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_ENT_STATUS); - WriteInt (a_Entity.GetUniqueID()); - WriteByte(a_Status); - Flush(); -} - - - - - -void cProtocol125::SendEntityVelocity(const cEntity & a_Entity) -{ - ASSERT(a_Entity.GetUniqueID() != m_Client->GetPlayer()->GetUniqueID()); // Must not send for self - - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_ENTITY_VELOCITY); - WriteInt (a_Entity.GetUniqueID()); - WriteShort((short) (a_Entity.GetSpeedX() * 400)); //400 = 8000 / 20 - WriteShort((short) (a_Entity.GetSpeedY() * 400)); - WriteShort((short) (a_Entity.GetSpeedZ() * 400)); - Flush(); -} - - - - - -void cProtocol125::SendExplosion(double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion) -{ - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_EXPLOSION); - WriteDouble (a_BlockX); - WriteDouble (a_BlockY); - WriteDouble (a_BlockZ); - WriteFloat (a_Radius); - WriteInt (a_BlocksAffected.size()); - int BlockX = (int)a_BlockX; - int BlockY = (int)a_BlockY; - int BlockZ = (int)a_BlockZ; - for (cVector3iArray::const_iterator itr = a_BlocksAffected.begin(); itr != a_BlocksAffected.end(); ++itr) - { - WriteByte((Byte)(itr->x - BlockX)); - WriteByte((Byte)(itr->y - BlockY)); - WriteByte((Byte)(itr->z - BlockZ)); - } - WriteFloat((float)a_PlayerMotion.x); - WriteFloat((float)a_PlayerMotion.y); - WriteFloat((float)a_PlayerMotion.z); - Flush(); -} - - - - - -void cProtocol125::SendGameMode(eGameMode a_GameMode) -{ - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_CHANGE_GAME_STATE); - WriteByte(3); - WriteByte((char)a_GameMode); - Flush(); -} - - - - - -void cProtocol125::SendHandshake(const AString & a_ConnectionHash) -{ - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_HANDSHAKE); - WriteString(a_ConnectionHash); - Flush(); -} - - - - - -void cProtocol125::SendHealth(void) -{ - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_UPDATE_HEALTH); - WriteShort((short)m_Client->GetPlayer()->GetHealth()); - WriteShort(m_Client->GetPlayer()->GetFoodLevel()); - WriteFloat((float)m_Client->GetPlayer()->GetFoodSaturationLevel()); - Flush(); -} - - - - - -void cProtocol125::SendInventorySlot(char a_WindowID, short a_SlotNum, const cItem & a_Item) -{ - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_INVENTORY_SLOT); - WriteByte (a_WindowID); - WriteShort(a_SlotNum); - WriteItem (a_Item); - Flush(); -} - - - - - -void cProtocol125::SendKeepAlive(int a_PingID) -{ - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_KEEP_ALIVE); - WriteInt (a_PingID); - Flush(); -} - - - - - -void cProtocol125::SendLogin(const cPlayer & a_Player, const cWorld & a_World) -{ - UNUSED(a_World); - cCSLock Lock(m_CSPacket); - - WriteByte (PACKET_LOGIN); - WriteInt (a_Player.GetUniqueID()); // EntityID of the player - WriteString(""); // Username, not used - WriteString("default"); // Level type - WriteInt ((int)a_Player.GetGameMode()); - WriteInt ((int)(a_World.GetDimension())); - WriteByte (2); // TODO: Difficulty - WriteByte (0); // Unused - WriteByte (60); // Client list width or something - Flush(); -} - - - - - -void cProtocol125::SendPickupSpawn(const cPickup & a_Pickup) -{ - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_PICKUP_SPAWN); - WriteInt (a_Pickup.GetUniqueID()); - WriteShort (a_Pickup.GetItem().m_ItemType); - WriteByte (a_Pickup.GetItem().m_ItemCount); - WriteShort (a_Pickup.GetItem().m_ItemDamage); - WriteVectorI((Vector3i)(a_Pickup.GetPosition() * 32)); - WriteByte ((char)(a_Pickup.GetSpeed().x * 8)); - WriteByte ((char)(a_Pickup.GetSpeed().y * 8)); - WriteByte ((char)(a_Pickup.GetSpeed().z * 8)); - Flush(); -} - - - - - -void cProtocol125::SendPlayerAnimation(const cPlayer & a_Player, char a_Animation) -{ - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_ANIMATION); - WriteInt (a_Player.GetUniqueID()); - WriteByte(a_Animation); - Flush(); -} - - - - - -void cProtocol125::SendPlayerListItem(const cPlayer & a_Player, bool a_IsOnline) -{ - cCSLock Lock(m_CSPacket); - AString PlayerName(a_Player.GetColor()); - PlayerName.append(a_Player.GetName()); - if (PlayerName.length() > 14) - { - PlayerName.erase(14); - } - PlayerName += cChatColor::White; - - WriteByte ((unsigned char)PACKET_PLAYER_LIST_ITEM); - WriteString(PlayerName); - WriteBool (a_IsOnline); - WriteShort (a_IsOnline ? a_Player.GetClientHandle()->GetPing() : 0); - Flush(); -} - - - - - -void cProtocol125::SendPlayerMaxSpeed(void) -{ - // Not supported by this protocol version -} - - - - - -void cProtocol125::SendPlayerMoveLook(void) -{ - cCSLock Lock(m_CSPacket); - - /* - 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 - ); - */ - - WriteByte (PACKET_PLAYER_MOVE_LOOK); - cPlayer * Player = m_Client->GetPlayer(); - WriteDouble(Player->GetPosX()); - WriteDouble(Player->GetStance() + 0.03); // Add a small amount so that the player doesn't start inside a block - WriteDouble(Player->GetPosY() + 0.03); // Add a small amount so that the player doesn't start inside a block - WriteDouble(Player->GetPosZ()); - WriteFloat ((float)(Player->GetRotation())); - WriteFloat ((float)(Player->GetPitch())); - WriteBool (Player->IsOnGround()); - Flush(); -} - - - - - -void cProtocol125::SendPlayerPosition(void) -{ - cCSLock Lock(m_CSPacket); - LOGD("Ignore send PlayerPos"); // PlayerPos is a C->S packet only now -} - - - - - -void cProtocol125::SendPlayerSpawn(const cPlayer & a_Player) -{ - const cItem & HeldItem = a_Player.GetEquippedItem(); - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_PLAYER_SPAWN); - WriteInt (a_Player.GetUniqueID()); - WriteString(a_Player.GetName()); - WriteInt ((int)(a_Player.GetPosX() * 32)); - WriteInt ((int)(a_Player.GetPosY() * 32)); - WriteInt ((int)(a_Player.GetPosZ() * 32)); - WriteByte ((char)((a_Player.GetRot().x / 360.f) * 256)); - WriteByte ((char)((a_Player.GetRot().y / 360.f) * 256)); - WriteShort (HeldItem.IsEmpty() ? 0 : HeldItem.m_ItemType); - Flush(); -} - - - - - -void cProtocol125::SendRespawn(void) -{ - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_RESPAWN); - WriteInt ((int)(m_Client->GetPlayer()->GetWorld()->GetDimension())); - WriteByte (2); // TODO: Difficulty; 2 = Normal - WriteByte ((char)m_Client->GetPlayer()->GetGameMode()); - WriteShort (256); // Current world height - WriteString("default"); -} - - - - - -void cProtocol125::SendSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) -{ - // Not needed in this protocol version -} - - - - - -void cProtocol125::SendSoundParticleEffect(int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) -{ - // Not implemented in this protocol version -} - - - - - -void cProtocol125::SendSpawnFallingBlock(const cFallingBlock & a_FallingBlock) -{ - // This protocol version implements falling blocks using the spawn object / vehicle packet: - SendSpawnObject(a_FallingBlock, 70, a_FallingBlock.GetBlockType(), 0, 0); -} - - - - - -void cProtocol125::SendSpawnMob(const cMonster & a_Mob) -{ - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_SPAWN_MOB); - WriteInt (a_Mob.GetUniqueID()); - WriteByte (a_Mob.GetMobType()); - WriteVectorI((Vector3i)(a_Mob.GetPosition() * 32)); - WriteByte (0); - WriteByte (0); - WriteByte (0); - - WriteCommonMetadata(a_Mob); - WriteMobMetadata(a_Mob); - WriteByte(0x7f); - - Flush(); -} - - - - - -void cProtocol125::SendSpawnObject(const cEntity & a_Entity, char a_ObjectType, int a_ObjectData, Byte a_Yaw, Byte a_Pitch) -{ - UNUSED(a_Yaw); - UNUSED(a_Pitch); - - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_SPAWN_OBJECT); - WriteInt (a_Entity.GetUniqueID()); - WriteByte(a_ObjectType); - WriteInt ((int)(a_Entity.GetPosX() * 32)); - WriteInt ((int)(a_Entity.GetPosY() * 32)); - WriteInt ((int)(a_Entity.GetPosZ() * 32)); - WriteByte(a_Pitch); - WriteByte(a_Yaw); - WriteInt (a_ObjectData); - if (a_ObjectData != 0) - { - WriteShort((short)(a_Entity.GetSpeedX() * 400)); - WriteShort((short)(a_Entity.GetSpeedY() * 400)); - WriteShort((short)(a_Entity.GetSpeedZ() * 400)); - } - Flush(); -} - - - - - -void cProtocol125::SendSpawnVehicle(const cEntity & a_Vehicle, char a_VehicleType, char a_VehicleSubType) -{ - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_SPAWN_OBJECT); - WriteInt (a_Vehicle.GetUniqueID()); - WriteByte (a_VehicleType); - WriteInt ((int)(a_Vehicle.GetPosX() * 32)); - WriteInt ((int)(a_Vehicle.GetPosY() * 32)); - WriteInt ((int)(a_Vehicle.GetPosZ() * 32)); - WriteByte ((Byte)((a_Vehicle.GetPitch() / 360.f) * 256)); - WriteByte ((Byte)((a_Vehicle.GetRotation() / 360.f) * 256)); - WriteInt (a_VehicleSubType); - if (a_VehicleSubType != 0) - { - WriteShort((short)(a_Vehicle.GetSpeedX() * 400)); - WriteShort((short)(a_Vehicle.GetSpeedY() * 400)); - WriteShort((short)(a_Vehicle.GetSpeedZ() * 400)); - } - Flush(); -} - - - - - -void cProtocol125::SendTabCompletionResults(const AStringVector & a_Results) -{ - // This protocol version doesn't support tab completion - UNUSED(a_Results); -} - - - - - -void cProtocol125::SendTeleportEntity(const cEntity & a_Entity) -{ - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_ENT_TELEPORT); - WriteInt (a_Entity.GetUniqueID()); - WriteInt ((int)(floor(a_Entity.GetPosX() * 32))); - WriteInt ((int)(floor(a_Entity.GetPosY() * 32))); - WriteInt ((int)(floor(a_Entity.GetPosZ() * 32))); - WriteByte ((char)((a_Entity.GetRotation() / 360.f) * 256)); - WriteByte ((char)((a_Entity.GetPitch() / 360.f) * 256)); - Flush(); -} - - - - - -void cProtocol125::SendThunderbolt(int a_BlockX, int a_BlockY, int a_BlockZ) -{ - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_THUNDERBOLT); - WriteInt (0x7fffffff); // Entity ID of the thunderbolt; we use a constant one - WriteBool(true); // Unknown bool - WriteInt (a_BlockX * 32); - WriteInt (a_BlockY * 32); - WriteInt (a_BlockZ * 32); - Flush(); -} - - - - - -void cProtocol125::SendTimeUpdate(Int64 a_WorldAge, Int64 a_TimeOfDay) -{ - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_UPDATE_TIME); - // Use a_WorldAge for daycount, and a_TimeOfDay for the proper time of day: - WriteInt64((24000 * (a_WorldAge / 24000)) + (a_TimeOfDay % 24000)); - Flush(); -} - - - - - -void cProtocol125::SendUnloadChunk(int a_ChunkX, int a_ChunkZ) -{ - cCSLock Lock(m_CSPacket); - SendPreChunk(a_ChunkX, a_ChunkZ, false); -} - - - - - -void cProtocol125::SendUpdateSign( - 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 -) -{ - cCSLock Lock(m_CSPacket); - WriteByte ((unsigned char)PACKET_UPDATE_SIGN); - WriteInt (a_BlockX); - WriteShort ((short)a_BlockY); - WriteInt (a_BlockZ); - WriteString(a_Line1); - WriteString(a_Line2); - WriteString(a_Line3); - WriteString(a_Line4); - Flush(); -} - - - - - -void cProtocol125::SendUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ ) -{ - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_USE_BED); - WriteInt (a_Entity.GetUniqueID()); - WriteByte(0); // Unknown byte only 0 has been observed - WriteInt (a_BlockX); - WriteByte(a_BlockY); - WriteInt (a_BlockZ); - Flush(); -} - - - - - -void cProtocol125::SendWeather(eWeather a_Weather) -{ - cCSLock Lock(m_CSPacket); - switch( a_Weather ) - { - case eWeather_Sunny: - { - WriteByte(PACKET_CHANGE_GAME_STATE); - WriteByte(2); // Stop rain - WriteByte(0); // Unused - Flush(); - break; - } - - case eWeather_Rain: - case eWeather_ThunderStorm: - { - WriteByte(PACKET_CHANGE_GAME_STATE); - WriteByte(1); // Begin rain - WriteByte(0); // Unused - Flush(); - break; - } - } -} - - - - - -void cProtocol125::SendWholeInventory(const cWindow & a_Window) -{ - cCSLock Lock(m_CSPacket); - cItems Slots; - a_Window.GetSlots(*(m_Client->GetPlayer()), Slots); - SendWindowSlots(a_Window.GetWindowID(), Slots.size(), &(Slots[0])); -} - - - - - -void cProtocol125::SendWindowClose(const cWindow & a_Window) -{ - if (a_Window.GetWindowType() == cWindow::wtInventory) - { - // Do not send inventory-window-close - return; - } - - cCSLock Lock(m_CSPacket); - WriteByte(PACKET_WINDOW_CLOSE); - WriteByte(a_Window.GetWindowID()); - Flush(); -} - - - - - -void cProtocol125::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()); - Flush(); -} - - - - - -void cProtocol125::SendWindowProperty(const cWindow & a_Window, short a_Property, short a_Value) -{ - cCSLock Lock(m_CSPacket); - WriteByte (PACKET_WINDOW_PROPERTY); - WriteByte (a_Window.GetWindowID()); - WriteShort(a_Property); - WriteShort(a_Value); - Flush(); -} - - - - - -AString cProtocol125::GetAuthServerID(void) -{ - // http://wiki.vg/wiki/index.php?title=Session&oldid=2262 - // The server generates a random hash and that is used for all clients, unmodified - return cRoot::Get()->GetServer()->GetServerID(); -} - - - - - -void cProtocol125::SendData(const char * a_Data, int a_Size) -{ - m_Client->SendData(a_Data, a_Size); -} - - - - - -void cProtocol125::DataReceived(const char * a_Data, int a_Size) -{ - if (!m_ReceivedData.Write(a_Data, a_Size)) - { - // Too much data in the incoming queue, report to caller: - m_Client->PacketBufferFull(); - return; - } - - // Parse and handle all complete packets in m_ReceivedData: - while (m_ReceivedData.CanReadBytes(1)) - { - unsigned char PacketType; - m_ReceivedData.ReadByte(PacketType); - switch (ParsePacket(PacketType)) - { - case PARSE_UNKNOWN: - { - // An unknown packet has been received, notify the client and abort: - m_Client->PacketUnknown(PacketType); - return; - } - case PARSE_ERROR: - { - // An error occurred while parsing a known packet, notify the client and abort: - m_Client->PacketError(PacketType); - return; - } - case PARSE_INCOMPLETE: - { - // Incomplete packet, bail out and process with the next batch of data - m_ReceivedData.ResetRead(); - return; - } - default: - { - // Packet successfully parsed, commit the read data and try again one more packet - m_ReceivedData.CommitRead(); - break; - } - } - } -} - - - - - -int cProtocol125::ParsePacket(unsigned char a_PacketType) -{ - switch (a_PacketType) - { - default: return PARSE_UNKNOWN; - case PACKET_ANIMATION: return ParseArmAnim(); - case PACKET_BLOCK_DIG: return ParseBlockDig(); - case PACKET_BLOCK_PLACE: return ParseBlockPlace(); - case PACKET_CHAT: return ParseChat(); - case PACKET_CREATIVE_INVENTORY_ACTION: return ParseCreativeInventoryAction(); - case PACKET_DISCONNECT: return ParseDisconnect(); - case PACKET_HANDSHAKE: return ParseHandshake(); - case PACKET_KEEP_ALIVE: return ParseKeepAlive(); - case PACKET_LOGIN: return ParseLogin(); - case PACKET_PACKET_ENTITY_ACTION: return ParseEntityAction(); - case PACKET_PING: return ParsePing(); - case PACKET_PLAYER_ABILITIES: return ParsePlayerAbilities(); - case PACKET_PLAYER_LOOK: return ParsePlayerLook(); - case PACKET_PLAYER_MOVE_LOOK: return ParsePlayerMoveLook(); - case PACKET_PLAYER_ON_GROUND: return ParsePlayerOnGround(); - case PACKET_PLAYER_POS: return ParsePlayerPosition(); - case PACKET_PLUGIN_MESSAGE: return ParsePluginMessage(); - case PACKET_RESPAWN: return ParseRespawn(); - case PACKET_SLOT_SELECTED: return ParseSlotSelected(); - case PACKET_UPDATE_SIGN: return ParseUpdateSign(); - case PACKET_USE_ENTITY: return ParseUseEntity(); - case PACKET_WINDOW_CLICK: return ParseWindowClick(); - case PACKET_WINDOW_CLOSE: return ParseWindowClose(); - } -} - - - - - -#define HANDLE_PACKET_PARSE(Packet) \ - { \ - int res = Packet.Parse(m_ReceivedData); \ - if (res < 0) \ - { \ - return res; \ - } \ - } - - - - - -int cProtocol125::ParseArmAnim(void) -{ - HANDLE_PACKET_READ(ReadBEInt, int, EntityID); - HANDLE_PACKET_READ(ReadChar, char, Animation); - m_Client->HandleAnimation(Animation); - return PARSE_OK; -} - - - - - -int cProtocol125::ParseBlockDig(void) -{ - HANDLE_PACKET_READ(ReadChar, char, Status); - HANDLE_PACKET_READ(ReadBEInt, int, PosX); - HANDLE_PACKET_READ(ReadByte, Byte, PosY); - HANDLE_PACKET_READ(ReadBEInt, int, PosZ); - HANDLE_PACKET_READ(ReadChar, char, BlockFace); - m_Client->HandleLeftClick(PosX, PosY, PosZ, BlockFace, Status); - return PARSE_OK; -} - - - - - -int cProtocol125::ParseBlockPlace(void) -{ - HANDLE_PACKET_READ(ReadBEInt, int, PosX); - HANDLE_PACKET_READ(ReadByte, Byte, PosY); - HANDLE_PACKET_READ(ReadBEInt, int, PosZ); - HANDLE_PACKET_READ(ReadChar, char, BlockFace); - - cItem HeldItem; - int res = ParseItem(HeldItem); - if (res < 0) - { - return res; - } - - // 1.2.5 didn't have any cursor position, so use 8, 8, 8, so that halfslabs and stairs work correctly and the special value is recognizable. - m_Client->HandleRightClick(PosX, PosY, PosZ, BlockFace, 8, 8, 8, HeldItem); - return PARSE_OK; -} - - - - - -int cProtocol125::ParseChat(void) -{ - HANDLE_PACKET_READ(ReadBEUTF16String16, AString, Message); - m_Client->HandleChat(Message); - return PARSE_OK; -} - - - - - -int cProtocol125::ParseCreativeInventoryAction(void) -{ - HANDLE_PACKET_READ(ReadBEShort, short, SlotNum); - cItem HeldItem; - int res = ParseItem(HeldItem); - if (res < 0) - { - return res; - } - m_Client->HandleCreativeInventory(SlotNum, HeldItem); - return PARSE_OK; -} - - - - - -int cProtocol125::ParseDisconnect(void) -{ - HANDLE_PACKET_READ(ReadBEUTF16String16, AString, Reason); - m_Client->HandleDisconnect(Reason); - return PARSE_OK; -} - - - - - -int cProtocol125::ParseEntityAction(void) -{ - HANDLE_PACKET_READ(ReadBEInt, int, EntityID); - HANDLE_PACKET_READ(ReadChar, char, ActionID); - m_Client->HandleEntityAction(EntityID, ActionID); - return PARSE_OK; -} - - - - - -int cProtocol125::ParseHandshake(void) -{ - HANDLE_PACKET_READ(ReadBEUTF16String16, AString, Username); - - AStringVector UserData = StringSplit(Username, ";"); // "FakeTruth;localhost:25565" - if (UserData.empty()) - { - m_Client->Kick("Did not receive username"); - return PARSE_OK; - } - m_Username = UserData[0]; - - LOGD("HANDSHAKE %s", Username.c_str()); - - if (!m_Client->HandleHandshake( m_Username )) - { - return PARSE_OK; // Player is not allowed into the server - } - - SendHandshake(cRoot::Get()->GetServer()->GetServerID()); - LOGD("User \"%s\" was sent a handshake response", m_Username.c_str()); - - return PARSE_OK; -} - - - - - -int cProtocol125::ParseKeepAlive(void) -{ - HANDLE_PACKET_READ(ReadBEInt, int, KeepAliveID); - m_Client->HandleKeepAlive(KeepAliveID); - return PARSE_OK; -} - - - - - -int cProtocol125::ParseLogin(void) -{ - HANDLE_PACKET_READ(ReadBEInt, int, ProtocolVersion); - HANDLE_PACKET_READ(ReadBEUTF16String16, AString, Username); - HANDLE_PACKET_READ(ReadBEUTF16String16, AString, LevelType); - HANDLE_PACKET_READ(ReadBEInt, int, ServerMode); - HANDLE_PACKET_READ(ReadBEInt, int, Dimension); - HANDLE_PACKET_READ(ReadChar, char, Difficulty); - HANDLE_PACKET_READ(ReadByte, Byte, WorldHeight); - HANDLE_PACKET_READ(ReadByte, Byte, MaxPlayers); - - if (ProtocolVersion < 29) - { - m_Client->Kick("Your client is outdated!"); - return PARSE_OK; - } - else if (ProtocolVersion > 29) - { - m_Client->Kick("Your client version is higher than the server!"); - return PARSE_OK; - } - - if (m_Username.compare(Username) != 0) - { - LOGWARNING("Login Username (\"%s\") does not match Handshake username (\"%s\") for client @ \"%s\", kicking", - Username.c_str(), - m_Username.c_str(), - m_Client->GetIPString().c_str() - ); - m_Client->Kick("Hacked client"); // Don't tell them why we don't want them - return PARSE_OK; - } - - m_Client->HandleLogin(ProtocolVersion, Username); - return PARSE_OK; -} - - - - - -int cProtocol125::ParsePing(void) -{ - // Packet has no more data - m_Client->HandlePing(); - return PARSE_OK; -} - - - - - - -int cProtocol125::ParsePlayerAbilities(void) -{ - HANDLE_PACKET_READ(ReadBool, bool, Invulnerable); - HANDLE_PACKET_READ(ReadBool, bool, IsFlying); - HANDLE_PACKET_READ(ReadBool, bool, CanFly); - HANDLE_PACKET_READ(ReadBool, bool, InstaMine); - // TODO: m_Client->HandlePlayerAbilities(...); - return PARSE_OK; -} - - - - - -int cProtocol125::ParsePlayerLook(void) -{ - HANDLE_PACKET_READ(ReadBEFloat, float, Rotation); - HANDLE_PACKET_READ(ReadBEFloat, float, Pitch); - HANDLE_PACKET_READ(ReadBool, bool, IsOnGround); - m_Client->HandlePlayerLook(Rotation, Pitch, IsOnGround); - return PARSE_OK; -} - - - - - -int cProtocol125::ParsePlayerMoveLook(void) -{ - HANDLE_PACKET_READ(ReadBEDouble, double, PosX); - HANDLE_PACKET_READ(ReadBEDouble, double, PosY); - HANDLE_PACKET_READ(ReadBEDouble, double, Stance); - HANDLE_PACKET_READ(ReadBEDouble, double, PosZ); - HANDLE_PACKET_READ(ReadBEFloat, float, Rotation); - HANDLE_PACKET_READ(ReadBEFloat, float, Pitch); - HANDLE_PACKET_READ(ReadBool, bool, IsOnGround); - // LOGD("Recv PML: {%0.2f, %0.2f, %0.2f}, Stance %0.2f, Gnd: %d", PosX, PosY, PosZ, Stance, IsOnGround ? 1 : 0); - m_Client->HandlePlayerMoveLook(PosX, PosY, PosZ, Stance, Rotation, Pitch, IsOnGround); - return PARSE_OK; -} - - - - - -int cProtocol125::ParsePlayerOnGround(void) -{ - HANDLE_PACKET_READ(ReadBool, bool, IsOnGround); - // TODO: m_Client->HandleFlying(IsOnGround); - return PARSE_OK; -} - - - - - -int cProtocol125::ParsePlayerPosition(void) -{ - HANDLE_PACKET_READ(ReadBEDouble, double, PosX); - HANDLE_PACKET_READ(ReadBEDouble, double, PosY); - HANDLE_PACKET_READ(ReadBEDouble, double, Stance); - HANDLE_PACKET_READ(ReadBEDouble, double, PosZ); - HANDLE_PACKET_READ(ReadBool, bool, IsOnGround); - m_Client->HandlePlayerPos(PosX, PosY, PosZ, Stance, IsOnGround); - return PARSE_OK; -} - - - - - -int cProtocol125::ParsePluginMessage(void) -{ - HANDLE_PACKET_READ(ReadBEUTF16String16, AString, ChannelName); - HANDLE_PACKET_READ(ReadBEShort, short, Length); - AString Data; - if (!m_ReceivedData.ReadString(Data, Length)) - { - m_ReceivedData.CheckValid(); - return PARSE_INCOMPLETE; - } - m_ReceivedData.CheckValid(); - - // TODO: Process the data - LOGD("Received %d bytes of plugin data on channel \"%s\".", Length, ChannelName.c_str()); - - return PARSE_OK; -} - - - - - -int cProtocol125::ParseRespawn(void) -{ - HANDLE_PACKET_READ(ReadBEInt, int, Dimension); - HANDLE_PACKET_READ(ReadChar, char, Difficulty); - HANDLE_PACKET_READ(ReadChar, char, CreativeMode); - HANDLE_PACKET_READ(ReadBEShort, short, WorldHeight); - HANDLE_PACKET_READ(ReadBEUTF16String16, AString, LevelType); - m_Client->HandleRespawn(); - return PARSE_OK; -} - - - - - -int cProtocol125::ParseSlotSelected(void) -{ - HANDLE_PACKET_READ(ReadBEShort, short, SlotNum); - m_Client->HandleSlotSelected(SlotNum); - return PARSE_OK; -} - - - - - -int cProtocol125::ParseUpdateSign(void) -{ - HANDLE_PACKET_READ(ReadBEInt, int, BlockX); - HANDLE_PACKET_READ(ReadBEShort, short, BlockY); - HANDLE_PACKET_READ(ReadBEInt, int, BlockZ); - HANDLE_PACKET_READ(ReadBEUTF16String16, AString, Line1); - HANDLE_PACKET_READ(ReadBEUTF16String16, AString, Line2); - HANDLE_PACKET_READ(ReadBEUTF16String16, AString, Line3); - HANDLE_PACKET_READ(ReadBEUTF16String16, AString, Line4); - m_Client->HandleUpdateSign(BlockX, BlockY, BlockZ, Line1, Line2, Line3, Line4); - return PARSE_OK; -} - - - - - -int cProtocol125::ParseUseEntity(void) -{ - HANDLE_PACKET_READ(ReadBEInt, int, SourceEntityID); - HANDLE_PACKET_READ(ReadBEInt, int, TargetEntityID); - HANDLE_PACKET_READ(ReadBool, bool, IsLeftClick); - m_Client->HandleUseEntity(TargetEntityID, IsLeftClick); - return PARSE_OK; -} - - - - - -int cProtocol125::ParseWindowClick(void) -{ - HANDLE_PACKET_READ(ReadChar, char, WindowID); - HANDLE_PACKET_READ(ReadBEShort, short, SlotNum); - HANDLE_PACKET_READ(ReadBool, bool, IsRightClick); - HANDLE_PACKET_READ(ReadBEShort, short, TransactionID); - HANDLE_PACKET_READ(ReadBool, bool, IsShiftPressed); - cItem HeldItem; - int res = ParseItem(HeldItem); - if (res < 0) - { - return res; - } - - // Convert IsShiftPressed, IsRightClick, SlotNum and HeldItem into eClickAction used in the newer protocols: - eClickAction Action; - if (IsRightClick) - { - if (IsShiftPressed) - { - Action = caShiftRightClick; - } - else - { - if (SlotNum == -999) - { - Action = (HeldItem.IsEmpty()) ? caRightClickOutsideHoldNothing : caRightClickOutside; - } - else - { - Action = caRightClick; - } - } - } - else - { - // IsLeftClick - if (IsShiftPressed) - { - Action = caShiftLeftClick; - } - else - { - if (SlotNum == -999) - { - Action = (HeldItem.IsEmpty()) ? caLeftClickOutsideHoldNothing : caRightClickOutside; - } - else - { - Action = caLeftClick; - } - } - } - m_Client->HandleWindowClick(WindowID, SlotNum, Action, HeldItem); - return PARSE_OK; -} - - - - - -int cProtocol125::ParseWindowClose(void) -{ - HANDLE_PACKET_READ(ReadChar, char, WindowID); - m_Client->HandleWindowClose(WindowID); - return PARSE_OK; -} - - - - - -void cProtocol125::SendPreChunk(int a_ChunkX, int a_ChunkZ, bool a_ShouldLoad) -{ - WriteByte(PACKET_PRE_CHUNK); - WriteInt (a_ChunkX); - WriteInt (a_ChunkZ); - WriteBool(a_ShouldLoad); - Flush(); -} - - - - - -void cProtocol125::SendWindowSlots(char a_WindowID, int a_NumItems, const cItem * a_Items) -{ - WriteByte (PACKET_INVENTORY_WHOLE); - WriteByte (a_WindowID); - WriteShort((short)a_NumItems); - - for (int j = 0; j < a_NumItems; j++) - { - WriteItem(a_Items[j]); - } - Flush(); -} - - - - - -void cProtocol125::WriteItem(const cItem & a_Item) -{ - short ItemType = a_Item.m_ItemType; - ASSERT(ItemType >= -1); // Check validity of packets in debug runtime - if (ItemType <= 0) - { - // Fix, to make sure no invalid values are sent. - ItemType = -1; - } - - WriteShort(ItemType); - if (a_Item.IsEmpty()) - { - return; - } - - WriteByte (a_Item.m_ItemCount); - WriteShort(a_Item.m_ItemDamage); - - if (cItem::IsEnchantable(a_Item.m_ItemType)) - { - // TODO: Implement enchantments - WriteShort(-1); - } -} - - - - - -int cProtocol125::ParseItem(cItem & a_Item) -{ - HANDLE_PACKET_READ(ReadBEShort, short, ItemType); - - if (ItemType <= -1) - { - a_Item.Empty(); - return PARSE_OK; - } - a_Item.m_ItemType = ItemType; - - HANDLE_PACKET_READ(ReadChar, char, ItemCount); - HANDLE_PACKET_READ(ReadBEShort, short, ItemDamage); - a_Item.m_ItemCount = ItemCount; - a_Item.m_ItemDamage = ItemDamage; - if (ItemCount <= 0) - { - a_Item.Empty(); - } - - if (!cItem::IsEnchantable(ItemType)) - { - return PARSE_OK; - } - - HANDLE_PACKET_READ(ReadBEShort, short, EnchantNumBytes); - - if (EnchantNumBytes <= 0) - { - return PARSE_OK; - } - - // TODO: Enchantment not implemented yet! - if (!m_ReceivedData.SkipRead(EnchantNumBytes)) - { - return PARSE_INCOMPLETE; - } - - return PARSE_OK; -} - - - - - -void cProtocol125::WriteCommonMetadata(const cEntity & a_Entity) -{ - Byte CommonMetadata = 0; - - if (a_Entity.IsOnFire()) - { - CommonMetadata |= 0x1; - } - if (a_Entity.IsCrouched()) - { - CommonMetadata |= 0x2; - } - if (a_Entity.IsRiding()) - { - CommonMetadata |= 0x4; - } - if (a_Entity.IsSprinting()) - { - CommonMetadata |= 0x8; - } - if (a_Entity.IsRclking()) - { - CommonMetadata |= 0x10; - } - if (a_Entity.IsInvisible()) - { - CommonMetadata |= 0x20; - } - - WriteByte(0x0); - WriteByte(CommonMetadata); -} - - - - - -void cProtocol125::WriteEntityMetadata(const cEntity & a_Entity) -{ - if (a_Entity.IsMinecart()) - { - WriteByte(0x51); - // No idea how Mojang makes their carts shakey shakey, so here is a complicated one-liner expression that does something similar - WriteInt( (((a_Entity.GetMaxHealth() / 2) - (a_Entity.GetHealth() - (a_Entity.GetMaxHealth() / 2))) * ((const cMinecart &)a_Entity).LastDamage()) * 4 ); - WriteByte(0x52); - WriteInt(1); // Shaking direction, doesn't seem to affect anything - WriteByte(0x73); - WriteFloat((float)(((const cMinecart &)a_Entity).LastDamage() + 10)); // Damage taken / shake effect multiplyer - - if (((cMinecart &)a_Entity).GetPayload() == cMinecart::mpFurnace) - { - WriteByte(0x10); - WriteByte(((const cMinecartWithFurnace &)a_Entity).IsFueled() ? 1 : 0); // Fueled? - } - } - else if ((a_Entity.IsProjectile() && ((cProjectileEntity &)a_Entity).GetProjectileKind() == cProjectileEntity::pkArrow)) - { - WriteByte(0x10); - WriteByte(((const cArrowEntity &)a_Entity).IsCritical() ? 1 : 0); // Critical hitting arrow? - } -} - - - - - -void cProtocol125::WriteMobMetadata(const cMonster & a_Mob) -{ - switch (a_Mob.GetMobType()) - { - case cMonster::mtCreeper: - { - WriteByte(0x10); - WriteByte(((const cCreeper &)a_Mob).IsBlowing() ? 1 : -1); // Blowing up? - WriteByte(0x11); - WriteByte(((const cCreeper &)a_Mob).IsCharged() ? 1 : 0); // Lightning-charged? - break; - } - case cMonster::mtBat: - { - WriteByte(0x10); - WriteByte(((const cBat &)a_Mob).IsHanging() ? 1 : 0); // Upside down? - break; - } - case cMonster::mtPig: - { - WriteByte(0x10); - WriteByte(((const cPig &)a_Mob).IsSaddled() ? 1 : 0); // Saddled? - break; - } - case cMonster::mtVillager: - { - WriteByte(0x50); - WriteInt(((const cVillager &)a_Mob).GetVilType()); // What sort of TESTIFICATE? - break; - } - case cMonster::mtZombie: - { - WriteByte(0xC); - WriteByte(((const cZombie &)a_Mob).IsBaby() ? 1 : 0); // Babby zombie? - WriteByte(0xD); - WriteByte(((const cZombie &)a_Mob).IsVillagerZombie() ? 1 : 0); // Converted zombie? - WriteByte(0xE); - WriteByte(((const cZombie &)a_Mob).IsConverting() ? 1 : 0); // Converted-but-converting-back zombllager? - break; - } - case cMonster::mtGhast: - { - WriteByte(0x10); - WriteByte(((const cGhast &)a_Mob).IsCharging()); // About to eject un flamé-bol? :P - break; - } - case cMonster::mtWolf: - { - Byte WolfStatus = 0; - if (((const cWolf &)a_Mob).IsSitting()) - { - WolfStatus |= 0x1; - } - if (((const cWolf &)a_Mob).IsAngry()) - { - WolfStatus |= 0x2; - } - if (((const cWolf &)a_Mob).IsTame()) - { - WolfStatus |= 0x4; - } - WriteByte(0x10); - WriteByte(WolfStatus); - - WriteByte(0x72); - WriteFloat((float)(a_Mob.GetHealth())); // Tail health-o-meter (only shown when tamed, by the way) - WriteByte(0x13); - WriteByte(((const cWolf &)a_Mob).IsBegging() ? 1 : 0); // Ultra cute mode? - break; - } - case cMonster::mtSheep: - { - // [1](1111) - // [] = Is sheared? () = Color, from 0 to 15 - - WriteByte(0x10); - Byte SheepMetadata = 0; - SheepMetadata = ((const cSheep &)a_Mob).GetFurColor(); // Fur colour - - if (((const cSheep &)a_Mob).IsSheared()) // Is sheared? - { - SheepMetadata |= 0x16; - } - WriteByte(SheepMetadata); - break; - } - case cMonster::mtEnderman: - { - WriteByte(0x10); - WriteByte((Byte)(((const cEnderman &)a_Mob).GetCarriedBlock())); // Block that he stole from your house - WriteByte(0x11); - WriteByte((Byte)(((const cEnderman &)a_Mob).GetCarriedMeta())); // Meta of block that he stole from your house - WriteByte(0x12); - WriteByte(((const cEnderman &)a_Mob).IsScreaming() ? 1 : 0); // Screaming at your face? - break; - } - case cMonster::mtSkeleton: - { - WriteByte(0xD); - WriteByte(((const cSkeleton &)a_Mob).IsWither() ? 1 : 0); // It's a skeleton, but it's not - break; - } - case cMonster::mtWitch: - { - WriteByte(0x15); - WriteByte(((const cWitch &)a_Mob).IsAngry() ? 1 : 0); // Aggravated? Doesn't seem to do anything - break; - } - case cMonster::mtSlime: - case cMonster::mtMagmaCube: - { - WriteByte(0x10); - if (a_Mob.GetMobType() == cMonster::mtSlime) - { - WriteByte(((const cSlime &)a_Mob).GetSize()); // Size of slime - HEWGE, meh, cute BABBY SLIME - } - else - { - WriteByte(((const cMagmaCube &)a_Mob).GetSize()); // Size of slime - HEWGE, meh, cute BABBY SLIME - } - break; - } - case cMonster::mtHorse: - { - int Flags = 0; - if (((const cHorse &)a_Mob).IsTame()) - { - Flags |= 0x2; - } - if (((const cHorse &)a_Mob).IsSaddled()) - { - Flags |= 0x4; - } - if (((const cHorse &)a_Mob).IsChested()) - { - Flags |= 0x8; - } - if (((const cHorse &)a_Mob).IsBaby()) - { - Flags |= 0x10; // IsBred flag, according to wiki.vg - don't think it does anything in multiplayer - } - if (((const cHorse &)a_Mob).IsEating()) - { - Flags |= 0x20; - } - if (((const cHorse &)a_Mob).IsRearing()) - { - Flags |= 0x40; - } - if (((const cHorse &)a_Mob).IsMthOpen()) - { - Flags |= 0x80; - } - WriteByte(0x50); - WriteInt(Flags); - - WriteByte(0x13); - WriteByte(((const cHorse &)a_Mob).GetHorseType()); // Type of horse (donkey, chestnut, etc.) - - WriteByte(0x54); - int Appearance = 0; - Appearance = ((const cHorse &)a_Mob).GetHorseColor(); // Mask FF - Appearance |= ((const cHorse &)a_Mob).GetHorseStyle() * 256; // Mask FF00, so multiply by 256 - WriteInt(Appearance); - - WriteByte(0x56); - WriteInt(((const cHorse &)a_Mob).GetHorseArmour()); // Horshey armour - break; - } - } -} - - - - |