Merge branch 'master' into EntityCustomName
Conflicts: src/ClientHandle.cpp src/ClientHandle.h src/Protocol/Protocol.h src/Protocol/Protocol125.cpp src/Protocol/Protocol125.h src/Protocol/Protocol17x.cpp src/Protocol/Protocol17x.h src/Protocol/ProtocolRecognizer.cpp src/Protocol/ProtocolRecognizer.h src/World.cpp src/World.h
This commit is contained in:
@@ -126,9 +126,12 @@ cClientHandle::~cClientHandle()
|
||||
cWorld * World = m_Player->GetWorld();
|
||||
if (World != NULL)
|
||||
{
|
||||
// Send the Offline PlayerList packet:
|
||||
World->BroadcastPlayerListItem(m_Player->GetTabListName(), false, 0, this);
|
||||
|
||||
if (!m_Username.empty())
|
||||
{
|
||||
// Send the Offline PlayerList packet:
|
||||
World->BroadcastPlayerListRemovePlayer(*m_Player, this);
|
||||
}
|
||||
|
||||
World->RemovePlayer(m_Player, true); // Must be called before cPlayer::Destroy() as otherwise cChunk tries to delete the player, and then we do it again
|
||||
m_Player->Destroy();
|
||||
}
|
||||
@@ -310,8 +313,16 @@ void cClientHandle::Authenticate(const AString & a_Name, const AString & a_UUID,
|
||||
ASSERT(m_Player == NULL);
|
||||
|
||||
m_Username = a_Name;
|
||||
m_UUID = a_UUID;
|
||||
m_Properties = a_Properties;
|
||||
|
||||
// Only assign UUID and properties if not already pre-assigned (BungeeCord sends those in the Handshake packet):
|
||||
if (m_UUID.empty())
|
||||
{
|
||||
m_UUID = a_UUID;
|
||||
}
|
||||
if (m_Properties.empty())
|
||||
{
|
||||
m_Properties = a_Properties;
|
||||
}
|
||||
|
||||
// Send login success (if the protocol supports it):
|
||||
m_Protocol->SendLoginSuccess();
|
||||
@@ -360,7 +371,12 @@ void cClientHandle::Authenticate(const AString & a_Name, const AString & a_UUID,
|
||||
|
||||
// Send experience
|
||||
m_Player->SendExperience();
|
||||
|
||||
|
||||
// Send player list items
|
||||
SendPlayerListAddPlayer(*m_Player);
|
||||
World->BroadcastPlayerListAddPlayer(*m_Player);
|
||||
World->SendPlayerList(m_Player);
|
||||
|
||||
m_Player->Initialize(*World);
|
||||
m_State = csAuthenticated;
|
||||
|
||||
@@ -470,13 +486,13 @@ void cClientHandle::StreamChunks(void)
|
||||
// For each distance touch chunks in a hollow square centered around current position:
|
||||
for (int i = -d; i <= d; ++i)
|
||||
{
|
||||
World->TouchChunk(ChunkPosX + d, ZERO_CHUNK_Y, ChunkPosZ + i);
|
||||
World->TouchChunk(ChunkPosX - d, ZERO_CHUNK_Y, ChunkPosZ + i);
|
||||
World->TouchChunk(ChunkPosX + d, ChunkPosZ + i);
|
||||
World->TouchChunk(ChunkPosX - d, ChunkPosZ + i);
|
||||
} // for i
|
||||
for (int i = -d + 1; i < d; ++i)
|
||||
{
|
||||
World->TouchChunk(ChunkPosX + i, ZERO_CHUNK_Y, ChunkPosZ + d);
|
||||
World->TouchChunk(ChunkPosX + i, ZERO_CHUNK_Y, ChunkPosZ - d);
|
||||
World->TouchChunk(ChunkPosX + i, ChunkPosZ + d);
|
||||
World->TouchChunk(ChunkPosX + i, ChunkPosZ - d);
|
||||
} // for i
|
||||
} // for d
|
||||
}
|
||||
@@ -499,8 +515,8 @@ void cClientHandle::StreamChunk(int a_ChunkX, int a_ChunkZ)
|
||||
{
|
||||
{
|
||||
cCSLock Lock(m_CSChunkLists);
|
||||
m_LoadedChunks.push_back(cChunkCoords(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ));
|
||||
m_ChunksToSend.push_back(cChunkCoords(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ));
|
||||
m_LoadedChunks.push_back(cChunkCoords(a_ChunkX, a_ChunkZ));
|
||||
m_ChunksToSend.push_back(cChunkCoords(a_ChunkX, a_ChunkZ));
|
||||
}
|
||||
World->SendChunkTo(a_ChunkX, a_ChunkZ, this);
|
||||
}
|
||||
@@ -1061,7 +1077,7 @@ void cClientHandle::HandleBlockDigStarted(int a_BlockX, int a_BlockY, int a_Bloc
|
||||
(m_Player->GetWorld()->GetBlock(a_BlockX, a_BlockY, a_BlockZ) != E_BLOCK_FIRE)
|
||||
)
|
||||
{
|
||||
// Players can't destroy blocks with a Sword in the hand.
|
||||
// Players can't destroy blocks with a sword in the hand.
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1132,6 +1148,12 @@ void cClientHandle::HandleBlockDigFinished(int a_BlockX, int a_BlockY, int a_Blo
|
||||
|
||||
FinishDigAnimation();
|
||||
|
||||
if (!m_Player->IsGameModeCreative() && (a_OldBlock == E_BLOCK_BEDROCK))
|
||||
{
|
||||
Kick("You can't break a bedrock!");
|
||||
return;
|
||||
}
|
||||
|
||||
cWorld * World = m_Player->GetWorld();
|
||||
cItemHandler * ItemHandler = cItemHandler::GetItemHandler(m_Player->GetEquippedItem());
|
||||
|
||||
@@ -1190,50 +1212,61 @@ void cClientHandle::FinishDigAnimation()
|
||||
|
||||
void cClientHandle::HandleRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, const cItem & a_HeldItem)
|
||||
{
|
||||
// TODO: Rewrite this function
|
||||
|
||||
LOGD("HandleRightClick: {%d, %d, %d}, face %d, HeldItem: %s",
|
||||
a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, ItemToFullString(a_HeldItem).c_str()
|
||||
);
|
||||
|
||||
cWorld * World = m_Player->GetWorld();
|
||||
bool AreRealCoords = (Vector3d(a_BlockX, a_BlockY, a_BlockZ) - m_Player->GetPosition()).Length() <= 5;
|
||||
|
||||
if (
|
||||
(a_BlockFace != BLOCK_FACE_NONE) && // The client is interacting with a specific block
|
||||
(
|
||||
(Diff(m_Player->GetPosX(), (double)a_BlockX) > 6) || // The block is too far away
|
||||
(Diff(m_Player->GetPosY(), (double)a_BlockY) > 6) ||
|
||||
(Diff(m_Player->GetPosZ(), (double)a_BlockZ) > 6)
|
||||
)
|
||||
IsValidBlock(a_HeldItem.m_ItemType) &&
|
||||
!AreRealCoords
|
||||
)
|
||||
{
|
||||
AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
|
||||
World->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player);
|
||||
if (a_BlockY < cChunkDef::Height - 1)
|
||||
if ((a_BlockX != -1) && (a_BlockY >= 0) && (a_BlockZ != -1))
|
||||
{
|
||||
World->SendBlockTo(a_BlockX, a_BlockY + 1, a_BlockZ, m_Player); // 2 block high things
|
||||
}
|
||||
if (a_BlockY > 0)
|
||||
{
|
||||
World->SendBlockTo(a_BlockX, a_BlockY - 1, a_BlockZ, m_Player); // 2 block high things
|
||||
World->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player);
|
||||
if (a_BlockY < cChunkDef::Height - 1)
|
||||
{
|
||||
World->SendBlockTo(a_BlockX, a_BlockY + 1, a_BlockZ, m_Player); // 2 block high things
|
||||
}
|
||||
if (a_BlockY > 0)
|
||||
{
|
||||
World->SendBlockTo(a_BlockX, a_BlockY - 1, a_BlockZ, m_Player); // 2 block high things
|
||||
}
|
||||
}
|
||||
m_Player->GetInventory().SendEquippedSlot();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!AreRealCoords)
|
||||
{
|
||||
a_BlockFace = BLOCK_FACE_NONE;
|
||||
}
|
||||
|
||||
cPluginManager * PlgMgr = cRoot::Get()->GetPluginManager();
|
||||
if (PlgMgr->CallHookPlayerRightClick(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ))
|
||||
{
|
||||
// A plugin doesn't agree with the action, replace the block on the client and quit:
|
||||
cChunkInterface ChunkInterface(World->GetChunkMap());
|
||||
BLOCKTYPE BlockType = World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
|
||||
cBlockHandler * BlockHandler = cBlockInfo::GetHandler(BlockType);
|
||||
BlockHandler->OnCancelRightClick(ChunkInterface, *World, m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
|
||||
|
||||
if (a_BlockFace != BLOCK_FACE_NONE)
|
||||
if (AreRealCoords)
|
||||
{
|
||||
AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
|
||||
World->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player);
|
||||
World->SendBlockTo(a_BlockX, a_BlockY + 1, a_BlockZ, m_Player); // 2 block high things
|
||||
m_Player->GetInventory().SendEquippedSlot();
|
||||
cChunkInterface ChunkInterface(World->GetChunkMap());
|
||||
BLOCKTYPE BlockType = World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
|
||||
cBlockHandler * BlockHandler = cBlockInfo::GetHandler(BlockType);
|
||||
BlockHandler->OnCancelRightClick(ChunkInterface, *World, m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
|
||||
|
||||
if (a_BlockFace != BLOCK_FACE_NONE)
|
||||
{
|
||||
AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
|
||||
World->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player);
|
||||
World->SendBlockTo(a_BlockX, a_BlockY + 1, a_BlockZ, m_Player); // 2 block high things
|
||||
m_Player->GetInventory().SendEquippedSlot();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -1266,22 +1299,25 @@ void cClientHandle::HandleRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, e
|
||||
return;
|
||||
}
|
||||
|
||||
BLOCKTYPE BlockType;
|
||||
NIBBLETYPE BlockMeta;
|
||||
World->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, BlockType, BlockMeta);
|
||||
cBlockHandler * BlockHandler = cBlockInfo::GetHandler(BlockType);
|
||||
|
||||
if (BlockHandler->IsUseable() && !m_Player->IsCrouched())
|
||||
if (AreRealCoords)
|
||||
{
|
||||
if (PlgMgr->CallHookPlayerUsingBlock(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta))
|
||||
BLOCKTYPE BlockType;
|
||||
NIBBLETYPE BlockMeta;
|
||||
World->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, BlockType, BlockMeta);
|
||||
cBlockHandler * BlockHandler = cBlockInfo::GetHandler(BlockType);
|
||||
|
||||
if (BlockHandler->IsUseable() && !m_Player->IsCrouched())
|
||||
{
|
||||
// A plugin doesn't agree with using the block, abort
|
||||
if (PlgMgr->CallHookPlayerUsingBlock(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta))
|
||||
{
|
||||
// A plugin doesn't agree with using the block, abort
|
||||
return;
|
||||
}
|
||||
cChunkInterface ChunkInterface(World->GetChunkMap());
|
||||
BlockHandler->OnUse(ChunkInterface, *World, m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ);
|
||||
PlgMgr->CallHookPlayerUsedBlock(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta);
|
||||
return;
|
||||
}
|
||||
cChunkInterface ChunkInterface(World->GetChunkMap());
|
||||
BlockHandler->OnUse(ChunkInterface, *World, m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ);
|
||||
PlgMgr->CallHookPlayerUsedBlock(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta);
|
||||
return;
|
||||
}
|
||||
|
||||
short EquippedDamage = Equipped.m_ItemDamage;
|
||||
@@ -1445,8 +1481,20 @@ void cClientHandle::HandlePlaceBlock(int a_BlockX, int a_BlockY, int a_BlockZ, e
|
||||
cChunkInterface ChunkInterface(World->GetChunkMap());
|
||||
NewBlock->OnPlacedByPlayer(ChunkInterface, *World, m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta);
|
||||
|
||||
// Step sound with 0.8f pitch is used as block placement sound
|
||||
World->BroadcastSoundEffect(NewBlock->GetStepSound(), (double)a_BlockX, (double)a_BlockY, (double)a_BlockZ, 1.0f, 0.8f);
|
||||
AString PlaceSound = cBlockInfo::GetPlaceSound(BlockType);
|
||||
float Volume = 1.0f, Pitch = 0.8f;
|
||||
if (PlaceSound == "dig.metal")
|
||||
{
|
||||
Pitch = 1.2f;
|
||||
PlaceSound = "dig.stone";
|
||||
}
|
||||
else if (PlaceSound == "random.anvil_land")
|
||||
{
|
||||
Volume = 0.65f;
|
||||
}
|
||||
|
||||
World->BroadcastSoundEffect(PlaceSound, a_BlockX + 0.5, a_BlockY + 0.5, a_BlockZ + 0.5, Volume, Pitch);
|
||||
|
||||
cRoot::Get()->GetPluginManager()->CallHookPlayerPlacedBlock(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta);
|
||||
}
|
||||
|
||||
@@ -2298,18 +2346,18 @@ void cClientHandle::SendInventorySlot(char a_WindowID, short a_SlotNum, const cI
|
||||
|
||||
|
||||
|
||||
void cClientHandle::SendMapColumn(int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length)
|
||||
void cClientHandle::SendMapColumn(int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length, unsigned int m_Scale)
|
||||
{
|
||||
m_Protocol->SendMapColumn(a_ID, a_X, a_Y, a_Colors, a_Length);
|
||||
m_Protocol->SendMapColumn(a_ID, a_X, a_Y, a_Colors, a_Length, m_Scale);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cClientHandle::SendMapDecorators(int a_ID, const cMapDecoratorList & a_Decorators)
|
||||
void cClientHandle::SendMapDecorators(int a_ID, const cMapDecoratorList & a_Decorators, unsigned int m_Scale)
|
||||
{
|
||||
m_Protocol->SendMapDecorators(a_ID, a_Decorators);
|
||||
m_Protocol->SendMapDecorators(a_ID, a_Decorators, m_Scale);
|
||||
}
|
||||
|
||||
|
||||
@@ -2325,9 +2373,9 @@ void cClientHandle::SendMapInfo(int a_ID, unsigned int a_Scale)
|
||||
|
||||
|
||||
|
||||
void cClientHandle::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)
|
||||
void cClientHandle::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_ParticleAmount)
|
||||
{
|
||||
m_Protocol->SendParticleEffect(a_ParticleName, a_SrcX, a_SrcY, a_SrcZ, a_OffsetX, a_OffsetY, a_OffsetZ, a_ParticleData, a_ParticleAmmount);
|
||||
m_Protocol->SendParticleEffect(a_ParticleName, a_SrcX, a_SrcY, a_SrcZ, a_OffsetX, a_OffsetY, a_OffsetZ, a_ParticleData, a_ParticleAmount);
|
||||
}
|
||||
|
||||
|
||||
@@ -2369,9 +2417,45 @@ void cClientHandle::SendPlayerAbilities()
|
||||
|
||||
|
||||
|
||||
void cClientHandle::SendPlayerListItem(const AString & a_PlayerName, bool a_IsOnline, short a_Ping)
|
||||
void cClientHandle::SendPlayerListAddPlayer(const cPlayer & a_Player)
|
||||
{
|
||||
m_Protocol->SendPlayerListItem(a_PlayerName, a_IsOnline, a_Ping);
|
||||
m_Protocol->SendPlayerListAddPlayer(a_Player);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cClientHandle::SendPlayerListRemovePlayer(const cPlayer & a_Player)
|
||||
{
|
||||
m_Protocol->SendPlayerListRemovePlayer(a_Player);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cClientHandle::SendPlayerListUpdateGameMode(const cPlayer & a_Player)
|
||||
{
|
||||
m_Protocol->SendPlayerListUpdateGameMode(a_Player);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cClientHandle::SendPlayerListUpdatePing(const cPlayer & a_Player)
|
||||
{
|
||||
m_Protocol->SendPlayerListUpdatePing(a_Player);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cClientHandle::SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_OldListName)
|
||||
{
|
||||
m_Protocol->SendPlayerListUpdateDisplayName(a_Player, a_OldListName);
|
||||
}
|
||||
|
||||
|
||||
@@ -2732,7 +2816,7 @@ bool cClientHandle::HasPluginChannel(const AString & a_PluginChannel)
|
||||
|
||||
|
||||
|
||||
bool cClientHandle::WantsSendChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
|
||||
bool cClientHandle::WantsSendChunk(int a_ChunkX, int a_ChunkZ)
|
||||
{
|
||||
if (m_State >= csDestroying)
|
||||
{
|
||||
@@ -2740,7 +2824,7 @@ bool cClientHandle::WantsSendChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
|
||||
}
|
||||
|
||||
cCSLock Lock(m_CSChunkLists);
|
||||
return (std::find(m_ChunksToSend.begin(), m_ChunksToSend.end(), cChunkCoords(a_ChunkX, a_ChunkY, a_ChunkZ)) != m_ChunksToSend.end());
|
||||
return (std::find(m_ChunksToSend.begin(), m_ChunksToSend.end(), cChunkCoords(a_ChunkX, a_ChunkZ)) != m_ChunksToSend.end());
|
||||
}
|
||||
|
||||
|
||||
@@ -2756,9 +2840,9 @@ void cClientHandle::AddWantedChunk(int a_ChunkX, int a_ChunkZ)
|
||||
|
||||
LOGD("Adding chunk [%d, %d] to wanted chunks for client %p", a_ChunkX, a_ChunkZ, this);
|
||||
cCSLock Lock(m_CSChunkLists);
|
||||
if (std::find(m_ChunksToSend.begin(), m_ChunksToSend.end(), cChunkCoords(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ)) == m_ChunksToSend.end())
|
||||
if (std::find(m_ChunksToSend.begin(), m_ChunksToSend.end(), cChunkCoords(a_ChunkX, a_ChunkZ)) == m_ChunksToSend.end())
|
||||
{
|
||||
m_ChunksToSend.push_back(cChunkCoords(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ));
|
||||
m_ChunksToSend.push_back(cChunkCoords(a_ChunkX, a_ChunkZ));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2856,11 +2940,27 @@ void cClientHandle::SocketClosed(void)
|
||||
|
||||
|
||||
|
||||
void cClientHandle::HandleEnchantItem(Byte & WindowID, Byte & Enchantment)
|
||||
void cClientHandle::HandleEnchantItem(Byte & a_WindowID, Byte & a_Enchantment)
|
||||
{
|
||||
cEnchantingWindow * Window = (cEnchantingWindow*)m_Player->GetWindow();
|
||||
if (a_Enchantment > 2)
|
||||
{
|
||||
LOGWARNING("%s attempt to crash the server with invalid enchanting selection!", GetUsername().c_str());
|
||||
Kick("Invalid enchanting!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
(m_Player->GetWindow() == NULL) ||
|
||||
(m_Player->GetWindow()->GetWindowID() != a_WindowID) ||
|
||||
(m_Player->GetWindow()->GetWindowType() != cWindow::wtEnchantment)
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
cEnchantingWindow * Window = (cEnchantingWindow*) m_Player->GetWindow();
|
||||
cItem Item = *Window->m_SlotArea->GetSlot(0, *m_Player);
|
||||
int BaseEnchantmentLevel = Window->GetPropertyValue(Enchantment);
|
||||
int BaseEnchantmentLevel = Window->GetPropertyValue(a_Enchantment);
|
||||
|
||||
if (Item.EnchantByXPLevels(BaseEnchantmentLevel))
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user