Merge branch 'master' into portals
Conflicts: src/Blocks/WorldInterface.h src/ClientHandle.cpp src/ClientHandle.h src/Entities/Player.cpp src/Entities/Player.h src/Generating/FinishGen.cpp src/Protocol/Protocol.h src/Protocol/Protocol125.cpp src/Protocol/Protocol125.h src/Protocol/Protocol16x.cpp src/Protocol/Protocol16x.h src/Protocol/Protocol17x.cpp src/Protocol/Protocol17x.h src/Protocol/ProtocolRecognizer.cpp src/Protocol/ProtocolRecognizer.h src/Root.h src/World.cpp
This commit is contained in:
@@ -81,7 +81,7 @@ extern bool g_ShouldLogCommIn, g_ShouldLogCommOut;
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// cProtocol172:
|
||||
|
||||
cProtocol172::cProtocol172(cClientHandle * a_Client, const AString & a_ServerAddress, UInt16 a_ServerPort, UInt32 a_State) :
|
||||
@@ -351,12 +351,12 @@ void cProtocol172::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerialize
|
||||
|
||||
|
||||
|
||||
void cProtocol172::SendCollectPickup(const cPickup & a_Pickup, const cPlayer & a_Player)
|
||||
void cProtocol172::SendCollectEntity(const cEntity & a_Entity, const cPlayer & a_Player)
|
||||
{
|
||||
ASSERT(m_State == 3); // In game mode?
|
||||
|
||||
cPacketizer Pkt(*this, 0x0d); // Collect Item packet
|
||||
Pkt.WriteInt(a_Pickup.GetUniqueID());
|
||||
Pkt.WriteInt(a_Entity.GetUniqueID());
|
||||
Pkt.WriteInt(a_Player.GetUniqueID());
|
||||
}
|
||||
|
||||
@@ -651,7 +651,7 @@ void cProtocol172::SendLogin(const cPlayer & a_Player, const cWorld & a_World)
|
||||
cServer * Server = cRoot::Get()->GetServer();
|
||||
cPacketizer Pkt(*this, 0x01); // Join Game packet
|
||||
Pkt.WriteInt(a_Player.GetUniqueID());
|
||||
Pkt.WriteByte((Byte)a_Player.GetEffectiveGameMode() | (Server->IsHardcore() ? 0x08 : 0)); // Hardcore flag bit 4
|
||||
Pkt.WriteByte((Byte)a_Player.GetEffectiveGameMode() | (Server->IsHardcore() ? 0x08 : 0)); // Hardcore flag bit 4
|
||||
Pkt.WriteChar((char)a_World.GetDimension());
|
||||
Pkt.WriteByte(2); // TODO: Difficulty (set to Normal)
|
||||
Pkt.WriteByte(std::min(Server->GetMaxPlayers(), 60));
|
||||
@@ -807,7 +807,7 @@ void cProtocol172::SendPlayerAbilities(void)
|
||||
if (Player->IsGameModeCreative())
|
||||
{
|
||||
Flags |= 0x01;
|
||||
Flags |= 0x08; // Godmode, used for creative
|
||||
Flags |= 0x08; // Godmode, used for creative
|
||||
}
|
||||
if (Player->IsFlying())
|
||||
{
|
||||
@@ -986,11 +986,11 @@ void cProtocol172::SendRemoveEntityEffect(const cEntity & a_Entity, int a_Effect
|
||||
|
||||
|
||||
|
||||
void cProtocol172::SendRespawn(eDimension a_Dimension)
|
||||
void cProtocol172::SendRespawn(eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks)
|
||||
{
|
||||
if (m_LastSentDimension == a_Dimension)
|
||||
if ((m_LastSentDimension == a_World.GetDimension()) && !a_ShouldIgnoreDimensionChecks)
|
||||
{
|
||||
// Must not send a respawn for the world with the same dimension, the client goes cuckoo if we do
|
||||
// Must not send a respawn for the world with the same dimension, the client goes cuckoo if we do (unless we are respawning from death)
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1026,7 +1026,7 @@ void cProtocol172::SendExperienceOrb(const cExpOrb & a_ExpOrb)
|
||||
{
|
||||
ASSERT(m_State == 3); // In game mode?
|
||||
|
||||
cPacketizer Pkt(*this, 0x11);
|
||||
cPacketizer Pkt(*this, 0x11);
|
||||
Pkt.WriteVarInt(a_ExpOrb.GetUniqueID());
|
||||
Pkt.WriteInt((int) a_ExpOrb.GetPosX());
|
||||
Pkt.WriteInt((int) a_ExpOrb.GetPosY());
|
||||
@@ -1084,15 +1084,15 @@ void cProtocol172::SendDisplayObjective(const AString & a_Objective, cScoreboard
|
||||
|
||||
|
||||
|
||||
void cProtocol172::SendSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) // a_Src coords are Block * 8
|
||||
void cProtocol172::SendSoundEffect(const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch)
|
||||
{
|
||||
ASSERT(m_State == 3); // In game mode?
|
||||
|
||||
|
||||
cPacketizer Pkt(*this, 0x29); // Sound Effect packet
|
||||
Pkt.WriteString(a_SoundName);
|
||||
Pkt.WriteInt(a_SrcX);
|
||||
Pkt.WriteInt(a_SrcY);
|
||||
Pkt.WriteInt(a_SrcZ);
|
||||
Pkt.WriteInt((int)(a_X * 8.0));
|
||||
Pkt.WriteInt((int)(a_Y * 8.0));
|
||||
Pkt.WriteInt((int)(a_Z * 8.0));
|
||||
Pkt.WriteFloat(a_Volume);
|
||||
Pkt.WriteByte((Byte)(a_Pitch * 63));
|
||||
}
|
||||
@@ -1130,7 +1130,7 @@ void cProtocol172::SendSpawnFallingBlock(const cFallingBlock & a_FallingBlock)
|
||||
Pkt.WriteFPInt(a_FallingBlock.GetPosZ());
|
||||
Pkt.WriteByteAngle(a_FallingBlock.GetYaw());
|
||||
Pkt.WriteByteAngle(a_FallingBlock.GetPitch());
|
||||
Pkt.WriteInt(((int)a_FallingBlock.GetBlockType()) | (((int)a_FallingBlock.GetBlockMeta()) << 16)); // Or 0x10
|
||||
Pkt.WriteInt(((int)a_FallingBlock.GetBlockType()) | (((int)a_FallingBlock.GetBlockMeta()) << 16)); // Or 0x10
|
||||
Pkt.WriteShort((short)(a_FallingBlock.GetSpeedX() * 400));
|
||||
Pkt.WriteShort((short)(a_FallingBlock.GetSpeedY() * 400));
|
||||
Pkt.WriteShort((short)(a_FallingBlock.GetSpeedZ() * 400));
|
||||
@@ -1219,12 +1219,11 @@ void cProtocol172::SendStatistics(const cStatManager & a_Manager)
|
||||
ASSERT(m_State == 3); // In game mode?
|
||||
|
||||
cPacketizer Pkt(*this, 0x37);
|
||||
Pkt.WriteVarInt(statCount); // TODO 2014-05-11 xdot: Optimization: Send "dirty" statistics only
|
||||
Pkt.WriteVarInt(statCount); // TODO 2014-05-11 xdot: Optimization: Send "dirty" statistics only
|
||||
|
||||
for (unsigned int i = 0; i < (unsigned int)statCount; ++i)
|
||||
for (size_t i = 0; i < (size_t)statCount; ++i)
|
||||
{
|
||||
StatValue Value = a_Manager.GetValue((eStatistic) i);
|
||||
|
||||
const AString & StatName = cStatInfo::GetName((eStatistic) i);
|
||||
|
||||
Pkt.WriteString(StatName);
|
||||
@@ -1327,10 +1326,10 @@ void cProtocol172::SendUpdateBlockEntity(cBlockEntity & a_BlockEntity)
|
||||
Byte Action = 0;
|
||||
switch (a_BlockEntity.GetBlockType())
|
||||
{
|
||||
case E_BLOCK_MOB_SPAWNER: Action = 1; break; // Update mob spawner spinny mob thing
|
||||
case E_BLOCK_COMMAND_BLOCK: Action = 2; break; // Update command block text
|
||||
case E_BLOCK_HEAD: Action = 4; break; // Update Mobhead entity
|
||||
case E_BLOCK_FLOWER_POT: Action = 5; break; // Update flower pot
|
||||
case E_BLOCK_MOB_SPAWNER: Action = 1; break; // Update mob spawner spinny mob thing
|
||||
case E_BLOCK_COMMAND_BLOCK: Action = 2; break; // Update command block text
|
||||
case E_BLOCK_HEAD: Action = 4; break; // Update Mobhead entity
|
||||
case E_BLOCK_FLOWER_POT: Action = 5; break; // Update flower pot
|
||||
default: ASSERT(!"Unhandled or unimplemented BlockEntity update request!"); break;
|
||||
}
|
||||
Pkt.WriteByte(Action);
|
||||
@@ -1657,7 +1656,7 @@ bool cProtocol172::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType)
|
||||
case 0x0c: HandlePacketSteerVehicle (a_ByteBuffer); return true;
|
||||
case 0x0d: HandlePacketWindowClose (a_ByteBuffer); return true;
|
||||
case 0x0e: HandlePacketWindowClick (a_ByteBuffer); return true;
|
||||
case 0x0f: // Confirm transaction - not used in MCS
|
||||
case 0x0f: // Confirm transaction - not used in MCS
|
||||
case 0x10: HandlePacketCreativeInventoryAction(a_ByteBuffer); return true;
|
||||
case 0x11: HandlePacketEnchantItem (a_ByteBuffer); return true;
|
||||
case 0x12: HandlePacketUpdateSign (a_ByteBuffer); return true;
|
||||
@@ -1951,11 +1950,11 @@ void cProtocol172::HandlePacketEntityAction(cByteBuffer & a_ByteBuffer)
|
||||
|
||||
switch (Action)
|
||||
{
|
||||
case 1: m_Client->HandleEntityCrouch(PlayerID, true); break; // Crouch
|
||||
case 2: m_Client->HandleEntityCrouch(PlayerID, false); break; // Uncrouch
|
||||
case 3: m_Client->HandleEntityLeaveBed(PlayerID); break; // Leave Bed
|
||||
case 4: m_Client->HandleEntitySprinting(PlayerID, true); break; // Start sprinting
|
||||
case 5: m_Client->HandleEntitySprinting(PlayerID, false); break; // Stop sprinting
|
||||
case 1: m_Client->HandleEntityCrouch(PlayerID, true); break; // Crouch
|
||||
case 2: m_Client->HandleEntityCrouch(PlayerID, false); break; // Uncrouch
|
||||
case 3: m_Client->HandleEntityLeaveBed(PlayerID); break; // Leave Bed
|
||||
case 4: m_Client->HandleEntitySprinting(PlayerID, true); break; // Start sprinting
|
||||
case 5: m_Client->HandleEntitySprinting(PlayerID, false); break; // Stop sprinting
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2312,7 +2311,7 @@ void cProtocol172::ParseItemMetadata(cItem & a_Item, const AString & a_Metadata)
|
||||
{
|
||||
case TAG_List:
|
||||
{
|
||||
if ((TagName == "ench") || (TagName == "StoredEnchantments")) // Enchantments tags
|
||||
if ((TagName == "ench") || (TagName == "StoredEnchantments")) // Enchantments tags
|
||||
{
|
||||
EnchantmentSerializer::ParseFromNBT(a_Item.m_Enchantments, NBT, tag);
|
||||
}
|
||||
@@ -2320,21 +2319,21 @@ void cProtocol172::ParseItemMetadata(cItem & a_Item, const AString & a_Metadata)
|
||||
}
|
||||
case TAG_Compound:
|
||||
{
|
||||
if (TagName == "display") // Custom name and lore tag
|
||||
if (TagName == "display") // Custom name and lore tag
|
||||
{
|
||||
for (int displaytag = NBT.GetFirstChild(tag); displaytag >= 0; displaytag = NBT.GetNextSibling(displaytag))
|
||||
{
|
||||
if ((NBT.GetType(displaytag) == TAG_String) && (NBT.GetName(displaytag) == "Name")) // Custon name tag
|
||||
if ((NBT.GetType(displaytag) == TAG_String) && (NBT.GetName(displaytag) == "Name")) // Custon name tag
|
||||
{
|
||||
a_Item.m_CustomName = NBT.GetString(displaytag);
|
||||
}
|
||||
else if ((NBT.GetType(displaytag) == TAG_List) && (NBT.GetName(displaytag) == "Lore")) // Lore tag
|
||||
else if ((NBT.GetType(displaytag) == TAG_List) && (NBT.GetName(displaytag) == "Lore")) // Lore tag
|
||||
{
|
||||
AString Lore;
|
||||
|
||||
for (int loretag = NBT.GetFirstChild(displaytag); loretag >= 0; loretag = NBT.GetNextSibling(loretag)) // Loop through array of strings
|
||||
for (int loretag = NBT.GetFirstChild(displaytag); loretag >= 0; loretag = NBT.GetNextSibling(loretag)) // Loop through array of strings
|
||||
{
|
||||
AppendPrintf(Lore, "%s`", NBT.GetString(loretag).c_str()); // Append the lore with a newline, used internally by MCS to display a new line in the client; don't forget to c_str ;)
|
||||
AppendPrintf(Lore, "%s`", NBT.GetString(loretag).c_str()); // Append the lore with a grave accent/backtick, used internally by MCS to display a new line in the client; don't forget to c_str ;)
|
||||
}
|
||||
|
||||
a_Item.m_Lore = Lore;
|
||||
@@ -2464,7 +2463,7 @@ void cProtocol172::AddChatPartStyle(Json::Value & a_Value, const AString & a_Par
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// cProtocol172::cPacketizer:
|
||||
|
||||
cProtocol172::cPacketizer::~cPacketizer()
|
||||
@@ -2586,7 +2585,7 @@ void cProtocol172::cPacketizer::WriteBlockEntity(const cBlockEntity & a_BlockEnt
|
||||
{
|
||||
cCommandBlockEntity & CommandBlockEntity = (cCommandBlockEntity &)a_BlockEntity;
|
||||
|
||||
Writer.AddByte("TrackOutput", 1); // Neither I nor the MC wiki has any idea about this
|
||||
Writer.AddByte("TrackOutput", 1); // Neither I nor the MC wiki has any idea about this
|
||||
Writer.AddInt("SuccessCount", CommandBlockEntity.GetResult());
|
||||
Writer.AddInt("x", CommandBlockEntity.GetPosX());
|
||||
Writer.AddInt("y", CommandBlockEntity.GetPosY());
|
||||
@@ -2596,7 +2595,7 @@ void cProtocol172::cPacketizer::WriteBlockEntity(const cBlockEntity & a_BlockEnt
|
||||
// For a command block, this would be the 'name' prepended to anything it outputs into global chat
|
||||
// MCS doesn't have this, so just leave it @ '@'. (geddit?)
|
||||
Writer.AddString("CustomName", "@");
|
||||
Writer.AddString("id", "Control"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
|
||||
Writer.AddString("id", "Control"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
|
||||
|
||||
if (!CommandBlockEntity.GetLastOutput().empty())
|
||||
{
|
||||
@@ -2617,7 +2616,7 @@ void cProtocol172::cPacketizer::WriteBlockEntity(const cBlockEntity & a_BlockEnt
|
||||
Writer.AddByte("SkullType", MobHeadEntity.GetType() & 0xFF);
|
||||
Writer.AddByte("Rot", MobHeadEntity.GetRotation() & 0xFF);
|
||||
Writer.AddString("ExtraType", MobHeadEntity.GetOwner().c_str());
|
||||
Writer.AddString("id", "Skull"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
|
||||
Writer.AddString("id", "Skull"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
|
||||
break;
|
||||
}
|
||||
case E_BLOCK_FLOWER_POT:
|
||||
@@ -2629,7 +2628,7 @@ void cProtocol172::cPacketizer::WriteBlockEntity(const cBlockEntity & a_BlockEnt
|
||||
Writer.AddInt("z", FlowerPotEntity.GetPosZ());
|
||||
Writer.AddInt("Item", (Int32) FlowerPotEntity.GetItem().m_ItemType);
|
||||
Writer.AddInt("Data", (Int32) FlowerPotEntity.GetItem().m_ItemDamage);
|
||||
Writer.AddString("id", "FlowerPot"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
|
||||
Writer.AddString("id", "FlowerPot"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
@@ -2708,15 +2707,16 @@ void cProtocol172::cPacketizer::WriteEntityMetadata(const cEntity & a_Entity)
|
||||
|
||||
// The following expression makes Minecarts shake more with less health or higher damage taken
|
||||
// It gets half the maximum health, and takes it away from the current health minus the half health:
|
||||
/* Health: 5 | 3 - (5 - 3) = 1 (shake power)
|
||||
Health: 3 | 3 - (3 - 3) = 3
|
||||
Health: 1 | 3 - (1 - 3) = 5
|
||||
/*
|
||||
Health: 5 | 3 - (5 - 3) = 1 (shake power)
|
||||
Health: 3 | 3 - (3 - 3) = 3
|
||||
Health: 1 | 3 - (1 - 3) = 5
|
||||
*/
|
||||
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
|
||||
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
|
||||
WriteFloat((float)(((const cMinecart &)a_Entity).LastDamage() + 10)); // Damage taken / shake effect multiplyer
|
||||
|
||||
if (((cMinecart &)a_Entity).GetPayload() == cMinecart::mpNone)
|
||||
{
|
||||
@@ -2904,9 +2904,9 @@ void cProtocol172::cPacketizer::WriteMobMetadata(const cMonster & a_Mob)
|
||||
|
||||
case cMonster::mtWither:
|
||||
{
|
||||
WriteByte(0x54); // Int at index 20
|
||||
WriteByte(0x54); // Int at index 20
|
||||
WriteInt(((const cWither &)a_Mob).GetWitherInvulnerableTicks());
|
||||
WriteByte(0x66); // Float at index 6
|
||||
WriteByte(0x66); // Float at index 6
|
||||
WriteFloat((float)(a_Mob.GetHealth()));
|
||||
break;
|
||||
}
|
||||
@@ -2986,7 +2986,7 @@ void cProtocol172::cPacketizer::WriteEntityProperties(const cEntity & a_Entity)
|
||||
return;
|
||||
}
|
||||
|
||||
//const cMonster & Mob = (const cMonster &)a_Entity;
|
||||
// const cMonster & Mob = (const cMonster &)a_Entity;
|
||||
|
||||
// TODO: Send properties and modifiers based on the mob type
|
||||
|
||||
@@ -2997,7 +2997,7 @@ void cProtocol172::cPacketizer::WriteEntityProperties(const cEntity & a_Entity)
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// cProtocol176:
|
||||
|
||||
cProtocol176::cProtocol176(cClientHandle * a_Client, const AString &a_ServerAddress, UInt16 a_ServerPort, UInt32 a_State) :
|
||||
@@ -3016,7 +3016,18 @@ void cProtocol176::SendPlayerSpawn(const cPlayer & a_Player)
|
||||
Pkt.WriteVarInt(a_Player.GetUniqueID());
|
||||
Pkt.WriteString(a_Player.GetClientHandle()->GetUUID());
|
||||
Pkt.WriteString(a_Player.GetName());
|
||||
Pkt.WriteVarInt(0); // We have no data to send here
|
||||
|
||||
const Json::Value & Properties = m_Client->GetProperties();
|
||||
const Json::Value::const_iterator End = Properties.end();
|
||||
Pkt.WriteVarInt(Properties.size());
|
||||
|
||||
for (Json::Value::iterator itr = Properties.begin(); itr != End; ++itr)
|
||||
{
|
||||
Pkt.WriteString(((Json::Value)*itr).get("name", "").toStyledString());
|
||||
Pkt.WriteString(((Json::Value)*itr).get("value", "").toStyledString());
|
||||
Pkt.WriteString(((Json::Value)*itr).get("signature", "").toStyledString());
|
||||
}
|
||||
|
||||
Pkt.WriteFPInt(a_Player.GetPosX());
|
||||
Pkt.WriteFPInt(a_Player.GetPosY());
|
||||
Pkt.WriteFPInt(a_Player.GetPosZ());
|
||||
|
||||
Reference in New Issue
Block a user