Portals animate and delay correctly
This commit is contained in:
parent
bfa8aaf41b
commit
29567c5610
@ -87,4 +87,4 @@
|
|||||||
! 271:1 = 200 # 1 Wooden Axe -> 10 sec
|
! 271:1 = 200 # 1 Wooden Axe -> 10 sec
|
||||||
! 269:1 = 200 # 1 Wooden Shovel -> 10 sec
|
! 269:1 = 200 # 1 Wooden Shovel -> 10 sec
|
||||||
! 290:1 = 200 # 1 Wooden Hoe -> 10 sec
|
! 290:1 = 200 # 1 Wooden Hoe -> 10 sec
|
||||||
! 268:1 = 200 # 1 Wooden Sword -> 10 sec
|
! 268:1 = 200 # 1 Wooden Sword -> 10 sec
|
@ -85,7 +85,8 @@ cChunk::cChunk(
|
|||||||
m_NeighborZM(a_NeighborZM),
|
m_NeighborZM(a_NeighborZM),
|
||||||
m_NeighborZP(a_NeighborZP),
|
m_NeighborZP(a_NeighborZP),
|
||||||
m_WaterSimulatorData(a_World->GetWaterSimulator()->CreateChunkData()),
|
m_WaterSimulatorData(a_World->GetWaterSimulator()->CreateChunkData()),
|
||||||
m_LavaSimulatorData (a_World->GetLavaSimulator ()->CreateChunkData())
|
m_LavaSimulatorData (a_World->GetLavaSimulator ()->CreateChunkData()),
|
||||||
|
m_EntityTickIteratorData(std::make_pair(false, &m_Entities.end()))
|
||||||
{
|
{
|
||||||
if (a_NeighborXM != NULL)
|
if (a_NeighborXM != NULL)
|
||||||
{
|
{
|
||||||
@ -576,26 +577,38 @@ void cChunk::Tick(float a_Dt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Tick all entities in this chunk (except mobs):
|
// Tick all entities in this chunk (except mobs):
|
||||||
for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr)
|
m_EntityTickIteratorData.first = true;
|
||||||
|
for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end();)
|
||||||
{
|
{
|
||||||
// Mobs are tickes inside MobTick (as we don't have to tick them if they are far away from players)
|
// Mobs are ticked inside cWorld::TickMobs() (as we don't have to tick them if they are far away from players)
|
||||||
// Don't tick things queued to be removed
|
// Don't tick things queued to be removed
|
||||||
if (
|
if (!((*itr)->IsMob()))
|
||||||
!((*itr)->IsMob()) &&
|
|
||||||
(std::find(m_EntitiesToRemove.begin(), m_EntitiesToRemove.end(), (*itr)->GetUniqueID()) == m_EntitiesToRemove.end())
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
|
m_EntityTickIteratorData.second = &itr;
|
||||||
(*itr)->Tick(a_Dt, *this);
|
(*itr)->Tick(a_Dt, *this);
|
||||||
|
|
||||||
|
if (itr != *m_EntityTickIteratorData.second)
|
||||||
|
{
|
||||||
|
itr = *m_EntityTickIteratorData.second;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++itr;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
++itr;
|
||||||
} // for itr - m_Entitites[]
|
} // for itr - m_Entitites[]
|
||||||
|
m_EntityTickIteratorData.first = false;
|
||||||
|
|
||||||
for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end();)
|
for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end();)
|
||||||
{
|
{
|
||||||
std::vector<int>::iterator itr2 = std::find(m_EntitiesToRemove.begin(), m_EntitiesToRemove.end(), (*itr)->GetUniqueID());
|
if ((*itr)->IsDestroyed()) // Remove all entities that were scheduled for removal:
|
||||||
if (itr2 != m_EntitiesToRemove.end())
|
|
||||||
{
|
{
|
||||||
|
LOGD("Destroying entity #%i (%s)", (*itr)->GetUniqueID(), (*itr)->GetClass());
|
||||||
|
cEntity * ToDelete = *itr;
|
||||||
itr = m_Entities.erase(itr);
|
itr = m_Entities.erase(itr);
|
||||||
m_EntitiesToRemove.erase(itr2);
|
delete ToDelete;
|
||||||
}
|
}
|
||||||
else if ( // If any entity moved out of the chunk, move it to the neighbor:
|
else if ( // If any entity moved out of the chunk, move it to the neighbor:
|
||||||
((*itr)->GetChunkX() != m_PosX) ||
|
((*itr)->GetChunkX() != m_PosX) ||
|
||||||
@ -607,17 +620,7 @@ void cChunk::Tick(float a_Dt)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((*itr)->IsDestroyed()) // Remove all entities that were scheduled for removal:
|
++itr;
|
||||||
{
|
|
||||||
LOGD("Destroying entity #%i (%s)", (*itr)->GetUniqueID(), (*itr)->GetClass());
|
|
||||||
cEntity * ToDelete = *itr;
|
|
||||||
itr = m_Entities.erase(itr);
|
|
||||||
delete ToDelete;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
++itr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} // for itr - m_Entitites[]
|
} // for itr - m_Entitites[]
|
||||||
|
|
||||||
@ -1860,20 +1863,7 @@ void cChunk::AddEntity(cEntity * a_Entity)
|
|||||||
MarkDirty();
|
MarkDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::find(m_Entities.begin(), m_Entities.end(), a_Entity) != m_Entities.end())
|
ASSERT(std::find(m_Entities.begin(), m_Entities.end(), a_Entity) == m_Entities.end());
|
||||||
{
|
|
||||||
// Not there already
|
|
||||||
std::vector<int>::iterator itr = std::find(m_EntitiesToRemove.begin(), m_EntitiesToRemove.end(), a_Entity->GetUniqueID());
|
|
||||||
if (itr != m_EntitiesToRemove.end())
|
|
||||||
{
|
|
||||||
m_EntitiesToRemove.erase(itr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ASSERT(!"Entity already present when AddEntity was called!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_Entities.push_back(a_Entity);
|
m_Entities.push_back(a_Entity);
|
||||||
}
|
}
|
||||||
@ -1884,7 +1874,14 @@ void cChunk::AddEntity(cEntity * a_Entity)
|
|||||||
|
|
||||||
void cChunk::RemoveEntity(cEntity * a_Entity)
|
void cChunk::RemoveEntity(cEntity * a_Entity)
|
||||||
{
|
{
|
||||||
m_EntitiesToRemove.push_back(a_Entity->GetUniqueID());
|
if (m_EntityTickIteratorData.first)
|
||||||
|
{
|
||||||
|
*m_EntityTickIteratorData.second = m_Entities.erase(*m_EntityTickIteratorData.second);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_Entities.remove(a_Entity);
|
||||||
|
}
|
||||||
|
|
||||||
// Mark as dirty if it was a server-generated entity:
|
// Mark as dirty if it was a server-generated entity:
|
||||||
if (!a_Entity->IsPlayer())
|
if (!a_Entity->IsPlayer())
|
||||||
@ -1899,11 +1896,6 @@ void cChunk::RemoveEntity(cEntity * a_Entity)
|
|||||||
|
|
||||||
bool cChunk::HasEntity(int a_EntityID)
|
bool cChunk::HasEntity(int a_EntityID)
|
||||||
{
|
{
|
||||||
if (std::find(m_EntitiesToRemove.begin(), m_EntitiesToRemove.end(), a_EntityID) != m_EntitiesToRemove.end())
|
|
||||||
{
|
|
||||||
return false; // If EntitiesToRemove contains our ID, this chunk doesn't have it, as it should be removed soon
|
|
||||||
}
|
|
||||||
|
|
||||||
for (cEntityList::const_iterator itr = m_Entities.begin(), end = m_Entities.end(); itr != end; ++itr)
|
for (cEntityList::const_iterator itr = m_Entities.begin(), end = m_Entities.end(); itr != end; ++itr)
|
||||||
{
|
{
|
||||||
if ((*itr)->GetUniqueID() == a_EntityID)
|
if ((*itr)->GetUniqueID() == a_EntityID)
|
||||||
|
@ -425,7 +425,7 @@ private:
|
|||||||
// A critical section is not needed, because all chunk access is protected by its parent ChunkMap's csLayers
|
// A critical section is not needed, because all chunk access is protected by its parent ChunkMap's csLayers
|
||||||
cClientHandleList m_LoadedByClient;
|
cClientHandleList m_LoadedByClient;
|
||||||
cEntityList m_Entities;
|
cEntityList m_Entities;
|
||||||
std::vector<int> m_EntitiesToRemove;
|
std::pair<bool, cEntityList::iterator *> m_EntityTickIteratorData;
|
||||||
cBlockEntityList m_BlockEntities;
|
cBlockEntityList m_BlockEntities;
|
||||||
|
|
||||||
/** Number of times the chunk has been requested to stay (by various cChunkStay objects); if zero, the chunk can be unloaded */
|
/** Number of times the chunk has been requested to stay (by various cChunkStay objects); if zero, the chunk can be unloaded */
|
||||||
|
@ -2398,6 +2398,7 @@ bool cChunkMap::ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinCh
|
|||||||
{
|
{
|
||||||
for (int x = a_MinChunkX; x <= a_MaxChunkX; x++)
|
for (int x = a_MinChunkX; x <= a_MaxChunkX; x++)
|
||||||
{
|
{
|
||||||
|
LOG("Request %i %i", x, z);
|
||||||
cChunkPtr Chunk = GetChunkNoLoad(x, ZERO_CHUNK_Y, z);
|
cChunkPtr Chunk = GetChunkNoLoad(x, ZERO_CHUNK_Y, z);
|
||||||
if ((Chunk == NULL) || (!Chunk->IsValid()))
|
if ((Chunk == NULL) || (!Chunk->IsValid()))
|
||||||
{
|
{
|
||||||
|
@ -1766,8 +1766,7 @@ void cClientHandle::RemoveFromWorld(void)
|
|||||||
m_Protocol->SendUnloadChunk(itr->m_ChunkX, itr->m_ChunkZ);
|
m_Protocol->SendUnloadChunk(itr->m_ChunkX, itr->m_ChunkZ);
|
||||||
} // for itr - Chunks[]
|
} // for itr - Chunks[]
|
||||||
|
|
||||||
// StreamChunks() called in cPlayer::MoveToWorld() after new world has been set
|
// Here, we set last streamed values to bogus ones so everything is resent
|
||||||
// Meanwhile here, we set last streamed values to bogus ones so everything is resent
|
|
||||||
m_LastStreamedChunkX = 0x7fffffff;
|
m_LastStreamedChunkX = 0x7fffffff;
|
||||||
m_LastStreamedChunkZ = 0x7fffffff;
|
m_LastStreamedChunkZ = 0x7fffffff;
|
||||||
m_HasSentPlayerChunk = false;
|
m_HasSentPlayerChunk = false;
|
||||||
@ -2367,9 +2366,9 @@ void cClientHandle::SendRemoveEntityEffect(const cEntity & a_Entity, int a_Effec
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cClientHandle::SendRespawn(const cWorld & a_World)
|
void cClientHandle::SendRespawn(eDimension a_Dimension)
|
||||||
{
|
{
|
||||||
m_Protocol->SendRespawn(a_World);
|
m_Protocol->SendRespawn(a_Dimension);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -149,7 +149,7 @@ public:
|
|||||||
void SendPlayerSpawn (const cPlayer & a_Player);
|
void SendPlayerSpawn (const cPlayer & a_Player);
|
||||||
void SendPluginMessage (const AString & a_Channel, const AString & a_Message); // Exported in ManualBindings.cpp
|
void SendPluginMessage (const AString & a_Channel, const AString & a_Message); // Exported in ManualBindings.cpp
|
||||||
void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID);
|
void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID);
|
||||||
void SendRespawn (const cWorld & a_World);
|
void SendRespawn (eDimension a_Dimension);
|
||||||
void SendExperience (void);
|
void SendExperience (void);
|
||||||
void SendExperienceOrb (const cExpOrb & a_ExpOrb);
|
void SendExperienceOrb (const cExpOrb & a_ExpOrb);
|
||||||
void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode);
|
void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode);
|
||||||
|
@ -1051,15 +1051,16 @@ void cEntity::DetectPortal()
|
|||||||
class cPortalChunkLoader : public cChunkStay
|
class cPortalChunkLoader : public cChunkStay
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
cPortalChunkLoader(cEntity * a_Entity, Vector3i & a_PortalPos) :
|
cPortalChunkLoader(cEntity * a_Entity, cWorld & a_World, Vector3i & a_PortalPos) :
|
||||||
m_Entity(a_Entity),
|
m_Entity(a_Entity),
|
||||||
m_PortalPos(a_PortalPos)
|
m_PortalPos(a_PortalPos),
|
||||||
|
m_World(a_World)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool OnAllChunksAvailable(void) override
|
virtual bool OnAllChunksAvailable(void) override
|
||||||
{
|
{
|
||||||
m_Entity->CreateExitPortal(m_PortalPos.x, m_PortalPos.y, m_PortalPos.z);
|
cEntity::CreateExitPortal(m_PortalPos.x, m_PortalPos.y, m_PortalPos.z, m_Entity->GetWidth(), m_Entity->GetHeight(), m_World, m_Entity->GetUniqueID());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1068,6 +1069,7 @@ void cEntity::DetectPortal()
|
|||||||
|
|
||||||
cEntity * m_Entity;
|
cEntity * m_Entity;
|
||||||
Vector3i m_PortalPos;
|
Vector3i m_PortalPos;
|
||||||
|
cWorld & m_World;
|
||||||
};
|
};
|
||||||
|
|
||||||
int X = POSX_TOINT, Y = POSY_TOINT, Z = POSZ_TOINT;
|
int X = POSX_TOINT, Y = POSY_TOINT, Z = POSZ_TOINT;
|
||||||
@ -1077,106 +1079,167 @@ void cEntity::DetectPortal()
|
|||||||
{
|
{
|
||||||
case E_BLOCK_NETHER_PORTAL:
|
case E_BLOCK_NETHER_PORTAL:
|
||||||
{
|
{
|
||||||
if (!GetWorld()->AreNetherPortalsEnabled())
|
if (!GetWorld()->AreNetherPortalsEnabled() || m_PortalCooldownData.second)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_PortalCooldownData.first != 80)
|
||||||
|
{
|
||||||
|
m_PortalCooldownData.first++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_PortalCooldownData.first = 0;
|
||||||
|
|
||||||
switch (GetWorld()->GetDimension())
|
switch (GetWorld()->GetDimension())
|
||||||
{
|
{
|
||||||
case dimNether: MoveToWorld(GetWorld()->GetLinkedOverworldName(), cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedOverworldName())); break;
|
case dimNether:
|
||||||
|
{
|
||||||
|
m_PortalCooldownData.second = true; // Stop portals from working on respawn
|
||||||
|
|
||||||
|
if (IsPlayer())
|
||||||
|
{
|
||||||
|
((cPlayer *)this)->GetClientHandle()->SendRespawn(dimOverworld);
|
||||||
|
}
|
||||||
|
MoveToWorld(GetWorld()->GetLinkedOverworldName(), cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedOverworldName()), false);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
case dimOverworld:
|
case dimOverworld:
|
||||||
{
|
{
|
||||||
|
m_PortalCooldownData.second = true; // Stop portals from working on respawn
|
||||||
|
|
||||||
if (IsPlayer())
|
if (IsPlayer())
|
||||||
{
|
{
|
||||||
((cPlayer *)this)->AwardAchievement(achEnterPortal);
|
((cPlayer *)this)->AwardAchievement(achEnterPortal);
|
||||||
|
((cPlayer *)this)->GetClientHandle()->SendRespawn(dimNether);
|
||||||
}
|
}
|
||||||
MoveToWorld(GetWorld()->GetNetherWorldName(), cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetNetherWorldName(), dimNether, GetWorld()->GetName()));
|
MoveToWorld(GetWorld()->GetNetherWorldName(), cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetNetherWorldName(), dimNether, GetWorld()->GetName()), false);
|
||||||
|
|
||||||
cChunkStay * Stay = new cPortalChunkLoader(this, Vector3i(X, Y, Z));
|
cChunkStay * Stay = new cPortalChunkLoader(this, *cRoot::Get()->GetWorld(GetWorld()->GetNetherWorldName()), Vector3i(X, Y, Z));
|
||||||
|
|
||||||
int MinChunkX, MaxChunkX;
|
int MinChunkX, MaxChunkX;
|
||||||
int MinChunkZ, MaxChunkZ;
|
int MinChunkZ, MaxChunkZ;
|
||||||
cChunkDef::BlockToChunk(X - 128, Z - 128, MinChunkX, MinChunkZ);
|
cChunkDef::BlockToChunk(X - 128, Z - 128, MinChunkX, MinChunkZ);
|
||||||
cChunkDef::BlockToChunk(X + 128, Z + 128, MaxChunkX, MaxChunkZ);
|
cChunkDef::BlockToChunk(X + 128, Z + 128, MaxChunkX, MaxChunkZ);
|
||||||
|
|
||||||
for (int OtherMinChunkX = MinChunkX; OtherMinChunkX <= MaxChunkX; ++OtherMinChunkX)
|
for (int ChunkX = MinChunkX; ChunkX <= MaxChunkX; ++ChunkX)
|
||||||
{
|
{
|
||||||
for (int OtherMinChunkZ = MinChunkZ; OtherMinChunkZ <= MaxChunkZ; ++OtherMinChunkZ)
|
for (int ChunkZ = MinChunkZ; ChunkZ <= MaxChunkZ; ++ChunkZ)
|
||||||
{
|
{
|
||||||
Stay->Add(OtherMinChunkX, OtherMinChunkZ);
|
LOG("Queue %i %i", ChunkX, ChunkZ);
|
||||||
|
Stay->Add(ChunkX, ChunkZ);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Stay->Enable(*GetWorld()->GetChunkMap());
|
Stay->Enable(*GetWorld()->GetChunkMap());
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
case E_BLOCK_END_PORTAL:
|
case E_BLOCK_END_PORTAL:
|
||||||
{
|
{
|
||||||
if (!GetWorld()->AreEndPortalsEnabled())
|
if (!GetWorld()->AreEndPortalsEnabled() || m_PortalCooldownData.second)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_PortalCooldownData.first != 80)
|
||||||
|
{
|
||||||
|
m_PortalCooldownData.first++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_PortalCooldownData.first = 0;
|
||||||
|
|
||||||
switch (GetWorld()->GetDimension())
|
switch (GetWorld()->GetDimension())
|
||||||
{
|
{
|
||||||
case dimEnd:
|
case dimEnd:
|
||||||
{
|
{
|
||||||
MoveToWorld(GetWorld()->GetLinkedOverworldName(), cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedOverworldName()));
|
m_PortalCooldownData.second = true; // Stop portals from working on respawn
|
||||||
|
|
||||||
if (IsPlayer())
|
if (IsPlayer())
|
||||||
{
|
{
|
||||||
cPlayer * Player = (cPlayer *)this;
|
cPlayer * Player = (cPlayer *)this;
|
||||||
Player->TeleportToCoords(Player->GetLastBedPos().x, Player->GetLastBedPos().y, Player->GetLastBedPos().z);
|
Player->TeleportToCoords(Player->GetLastBedPos().x, Player->GetLastBedPos().y, Player->GetLastBedPos().z);
|
||||||
|
Player->GetClientHandle()->SendRespawn(dimOverworld);
|
||||||
}
|
}
|
||||||
break;
|
MoveToWorld(GetWorld()->GetLinkedOverworldName(), cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedOverworldName()), false);
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
case dimOverworld:
|
case dimOverworld:
|
||||||
{
|
{
|
||||||
|
m_PortalCooldownData.second = true; // Stop portals from working on respawn
|
||||||
|
|
||||||
if (IsPlayer())
|
if (IsPlayer())
|
||||||
{
|
{
|
||||||
((cPlayer *)this)->AwardAchievement(achEnterTheEnd);
|
((cPlayer *)this)->AwardAchievement(achEnterTheEnd);
|
||||||
|
((cPlayer *)this)->GetClientHandle()->SendRespawn(dimEnd);
|
||||||
}
|
}
|
||||||
MoveToWorld(GetWorld()->GetEndWorldName(), cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetEndWorldName(), dimEnd, GetWorld()->GetName()));
|
MoveToWorld(GetWorld()->GetEndWorldName(), cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetEndWorldName(), dimEnd, GetWorld()->GetName()), false);
|
||||||
break;
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Allow portals to work again
|
||||||
|
m_PortalCooldownData.second = false;
|
||||||
|
m_PortalCooldownData.first = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cEntity::CreateExitPortal(int a_BlockX, int a_BlockY, int a_BlockZ)
|
void cEntity::CreateExitPortal(int a_BlockX, int a_BlockY, int a_BlockZ, double a_EntityWidth, double a_EntityHeight, cWorld & a_World, int a_UniqueIDToTeleport)
|
||||||
{
|
{
|
||||||
cBlockArea Area;
|
cBlockArea Area;
|
||||||
Area.Read(GetWorld(), a_BlockX - 128, a_BlockX + 128, 0, 128, a_BlockZ - 128, a_BlockZ + 128);
|
Area.Read(&a_World, a_BlockX - 128, a_BlockX + 128, 0, 128, a_BlockZ - 128, a_BlockZ + 128);
|
||||||
for (int x = a_BlockX - 128; x <= a_BlockX + 128; ++x) for (int y = 0; y <= 128; ++y) for (int z = a_BlockZ - 128; z <= a_BlockZ + 128; ++z)
|
for (int x = a_BlockX - 128; x <= a_BlockX + 128; ++x) for (int y = 0; y <= 128; ++y) for (int z = a_BlockZ - 128; z <= a_BlockZ + 128; ++z)
|
||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
(Area.GetBlockType(x, y, z) == E_BLOCK_NETHER_PORTAL) &&
|
(Area.GetBlockType(x, y, z) == E_BLOCK_NETHER_PORTAL) &&
|
||||||
(
|
(
|
||||||
(Area.GetBlockType(x, (int)floor(y + GetHeight()), z) == E_BLOCK_NETHER_PORTAL) ||
|
(Area.GetBlockType(x, (int)floor(y + a_EntityHeight), z) == E_BLOCK_NETHER_PORTAL) ||
|
||||||
(Area.GetBlockType(x, (int)floor(y - GetHeight()), z) == E_BLOCK_NETHER_PORTAL)
|
(Area.GetBlockType(x, (int)floor(y - a_EntityHeight), z) == E_BLOCK_NETHER_PORTAL)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
TeleportToCoords(x, y, z);
|
class cTeleportEntityToPortalCallback : public cEntityCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
cTeleportEntityToPortalCallback(int a_X, int a_Y, int a_Z) :
|
||||||
|
m_X(a_X),
|
||||||
|
m_Y(a_Y),
|
||||||
|
m_Z(a_Z)
|
||||||
|
{}
|
||||||
|
|
||||||
|
virtual bool Item(cEntity * a_Entity) override
|
||||||
|
{
|
||||||
|
a_Entity->TeleportToCoords(m_X, m_Y, m_Z);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_X, m_Y, m_Z;
|
||||||
|
};
|
||||||
|
|
||||||
|
cTeleportEntityToPortalCallback TETPC(x, y, z);
|
||||||
|
a_World.DoWithEntityByID(a_UniqueIDToTeleport, TETPC);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int MinX = std::max(a_BlockX - (int)ceil(GetWidth()), a_BlockX - 2), MaxX = std::max(a_BlockX + (int)ceil(GetWidth()), a_BlockX + 1);
|
int MinX = std::max(a_BlockX - (int)ceil(a_EntityWidth), a_BlockX - 2), MaxX = std::max(a_BlockX + (int)ceil(a_EntityWidth), a_BlockX + 1);
|
||||||
int MinY = std::max(a_BlockY - (int)ceil(GetHeight()), a_BlockY - 2), MaxY = std::max(a_BlockY + (int)ceil(GetHeight()), a_BlockY + 1);
|
int MinY = std::max(a_BlockY - (int)ceil(a_EntityHeight), a_BlockY - 2), MaxY = std::max(a_BlockY + (int)ceil(a_EntityHeight), a_BlockY + 1);
|
||||||
|
|
||||||
for (int y = MinY; y < MaxY + 1; y += MaxY - MinY) for (int x = MinX; x < MaxX + 1; ++x)
|
for (int y = MinY; y < MaxY + 1; y += MaxY - MinY) for (int x = MinX; x < MaxX + 1; ++x)
|
||||||
{
|
{
|
||||||
@ -1187,15 +1250,17 @@ void cEntity::CreateExitPortal(int a_BlockX, int a_BlockY, int a_BlockZ)
|
|||||||
Area.SetBlockType(x, y, a_BlockZ, E_BLOCK_OBSIDIAN);
|
Area.SetBlockType(x, y, a_BlockZ, E_BLOCK_OBSIDIAN);
|
||||||
}
|
}
|
||||||
|
|
||||||
Area.Write(GetWorld(), MinX, MinY, a_BlockZ);
|
Area.Write(&a_World, MinX, MinY, a_BlockZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cEntity::MoveToWorld(const AString & a_WorldName, cWorld * a_World)
|
bool cEntity::MoveToWorld(const AString & a_WorldName, cWorld * a_World, bool a_ShouldSendRespawn)
|
||||||
{
|
{
|
||||||
|
UNUSED(a_ShouldSendRespawn);
|
||||||
|
|
||||||
cWorld * World;
|
cWorld * World;
|
||||||
if (a_World == NULL)
|
if (a_World == NULL)
|
||||||
{
|
{
|
||||||
@ -1213,6 +1278,7 @@ bool cEntity::MoveToWorld(const AString & a_WorldName, cWorld * a_World)
|
|||||||
|
|
||||||
if (GetWorld() == World)
|
if (GetWorld() == World)
|
||||||
{
|
{
|
||||||
|
// Don't move to same world
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1220,8 +1286,7 @@ bool cEntity::MoveToWorld(const AString & a_WorldName, cWorld * a_World)
|
|||||||
GetWorld()->RemoveEntity(this);
|
GetWorld()->RemoveEntity(this);
|
||||||
GetWorld()->BroadcastDestroyEntity(*this);
|
GetWorld()->BroadcastDestroyEntity(*this);
|
||||||
|
|
||||||
// Add to all the necessary parts of the new world
|
// Queue add to new world
|
||||||
SetWorld(World);
|
|
||||||
World->AddEntity(this);
|
World->AddEntity(this);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -338,7 +338,7 @@ public:
|
|||||||
virtual void OnFinishedBurning(void);
|
virtual void OnFinishedBurning(void);
|
||||||
|
|
||||||
/** Creates exit portal at given coordinates */
|
/** Creates exit portal at given coordinates */
|
||||||
void CreateExitPortal(int a_BlockX, int a_BlockY, int a_BlockZ);
|
static void CreateExitPortal(int a_BlockX, int a_BlockY, int a_BlockZ, double a_EntityWidth, double a_EntityHeight, cWorld & a_World, int a_UniqueIDToTeleport);
|
||||||
|
|
||||||
// tolua_begin
|
// tolua_begin
|
||||||
|
|
||||||
@ -374,7 +374,7 @@ public:
|
|||||||
virtual void TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ);
|
virtual void TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ);
|
||||||
|
|
||||||
/** Moves entity to specified world */
|
/** Moves entity to specified world */
|
||||||
virtual bool MoveToWorld(const AString & a_WorldName, cWorld * a_World = NULL);
|
virtual bool MoveToWorld(const AString & a_WorldName, cWorld * a_World = NULL, bool a_ShouldSendRespawn = true);
|
||||||
|
|
||||||
// tolua_end
|
// tolua_end
|
||||||
|
|
||||||
@ -510,6 +510,12 @@ protected:
|
|||||||
/** Air level of a mobile */
|
/** Air level of a mobile */
|
||||||
int m_AirLevel;
|
int m_AirLevel;
|
||||||
int m_AirTickTimer;
|
int m_AirTickTimer;
|
||||||
|
|
||||||
|
/** Portal delay timer and cooldown boolean
|
||||||
|
First value is to delay sending the repsawn packet (which triggers the Entering the {Dimension} screen).
|
||||||
|
Second value is to prevent a teleportation loop by ensuring we do not reenter a portal that we came out of.
|
||||||
|
*/
|
||||||
|
std::pair<unsigned short, bool> m_PortalCooldownData;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** Measured in degrees, [-180, +180) */
|
/** Measured in degrees, [-180, +180) */
|
||||||
|
@ -948,7 +948,7 @@ void cPlayer::Respawn(void)
|
|||||||
m_LifetimeTotalXp = 0;
|
m_LifetimeTotalXp = 0;
|
||||||
// ToDo: send score to client? How?
|
// ToDo: send score to client? How?
|
||||||
|
|
||||||
m_ClientHandle->SendRespawn(*GetWorld());
|
m_ClientHandle->SendRespawn(GetWorld()->GetDimension());
|
||||||
|
|
||||||
// Extinguish the fire:
|
// Extinguish the fire:
|
||||||
StopBurning();
|
StopBurning();
|
||||||
@ -1570,7 +1570,7 @@ void cPlayer::TossItems(const cItems & a_Items)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cPlayer::MoveToWorld(const AString & a_WorldName, cWorld * a_World)
|
bool cPlayer::MoveToWorld(const AString & a_WorldName, cWorld * a_World, bool a_ShouldSendRespawn)
|
||||||
{
|
{
|
||||||
cWorld * World;
|
cWorld * World;
|
||||||
if (a_World == NULL)
|
if (a_World == NULL)
|
||||||
@ -1589,31 +1589,22 @@ bool cPlayer::MoveToWorld(const AString & a_WorldName, cWorld * a_World)
|
|||||||
|
|
||||||
if (GetWorld() == World)
|
if (GetWorld() == World)
|
||||||
{
|
{
|
||||||
|
// Don't move to same world
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send the respawn packet:
|
// Send the respawn packet:
|
||||||
if (m_ClientHandle != NULL)
|
if (a_ShouldSendRespawn && (m_ClientHandle != NULL))
|
||||||
{
|
{
|
||||||
m_ClientHandle->SendRespawn(*World);
|
m_ClientHandle->SendRespawn(World->GetDimension());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove all links to the old world
|
// Remove player from old world
|
||||||
m_World->RemovePlayer(this);
|
m_World->RemovePlayer(this);
|
||||||
|
|
||||||
// If the dimension is different, we can send the respawn packet
|
|
||||||
// http://wiki.vg/Protocol#0x09 says "don't send if dimension is the same" as of 2013_07_02
|
|
||||||
|
|
||||||
// Queue adding player to the new world, including all the necessary adjustments to the object
|
// Queue adding player to the new world, including all the necessary adjustments to the object
|
||||||
World->AddPlayer(this);
|
World->AddPlayer(this);
|
||||||
|
|
||||||
if (GetWorld()->GetDimension() != World->GetDimension())
|
|
||||||
{
|
|
||||||
GetClientHandle()->SendPlayerMoveLook();
|
|
||||||
GetClientHandle()->SendHealth();
|
|
||||||
GetClientHandle()->SendWholeInventory(*GetWindow());
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,14 +323,14 @@ public:
|
|||||||
|
|
||||||
virtual void Killed(cEntity * a_Victim) override;
|
virtual void Killed(cEntity * a_Victim) override;
|
||||||
|
|
||||||
void Respawn(void); // tolua_export
|
void Respawn(void); // tolua_export
|
||||||
|
|
||||||
void SetVisible( bool a_bVisible ); // tolua_export
|
void SetVisible(bool a_bVisible); // tolua_export
|
||||||
bool IsVisible(void) const { return m_bVisible; } // tolua_export
|
bool IsVisible(void) const { return m_bVisible; } // tolua_export
|
||||||
|
|
||||||
/** Moves the player to the specified world.
|
/** Moves the player to the specified world.
|
||||||
Returns true if successful, false on failure (world not found). */
|
Returns true if successful, false on failure (world not found). */
|
||||||
virtual bool MoveToWorld(const AString & a_WorldName, cWorld * a_World = NULL) override; // tolua_export
|
virtual bool MoveToWorld(const AString & a_WorldName, cWorld * a_World = NULL, bool a_ShouldSendRespawn = true) override; // tolua_export
|
||||||
|
|
||||||
/** Saves all player data, such as inventory, to JSON */
|
/** Saves all player data, such as inventory, to JSON */
|
||||||
bool SaveToDisk(void);
|
bool SaveToDisk(void);
|
||||||
@ -339,7 +339,7 @@ public:
|
|||||||
Takes a (NULL) cWorld pointer which it will assign a value to based on either the loaded world or default world
|
Takes a (NULL) cWorld pointer which it will assign a value to based on either the loaded world or default world
|
||||||
*/
|
*/
|
||||||
bool LoadFromDisk(cWorld *& a_World);
|
bool LoadFromDisk(cWorld *& a_World);
|
||||||
void LoadPermissionsFromDisk(void); // tolua_export
|
void LoadPermissionsFromDisk(void); // tolua_export
|
||||||
|
|
||||||
const AString & GetLoadedWorldName() { return m_LoadedWorldName; }
|
const AString & GetLoadedWorldName() { return m_LoadedWorldName; }
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ public:
|
|||||||
virtual void SendPlayerSpawn (const cPlayer & a_Player) = 0;
|
virtual void SendPlayerSpawn (const cPlayer & a_Player) = 0;
|
||||||
virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) = 0;
|
virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) = 0;
|
||||||
virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) = 0;
|
virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) = 0;
|
||||||
virtual void SendRespawn (const cWorld & a_World) = 0;
|
virtual void SendRespawn (eDimension a_Dimension) = 0;
|
||||||
virtual void SendExperience (void) = 0;
|
virtual void SendExperience (void) = 0;
|
||||||
virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) = 0;
|
virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) = 0;
|
||||||
virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) = 0;
|
virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) = 0;
|
||||||
|
@ -833,23 +833,23 @@ void cProtocol125::SendRemoveEntityEffect(const cEntity & a_Entity, int a_Effect
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cProtocol125::SendRespawn(const cWorld & a_World)
|
void cProtocol125::SendRespawn(eDimension a_Dimension)
|
||||||
{
|
{
|
||||||
cCSLock Lock(m_CSPacket);
|
cCSLock Lock(m_CSPacket);
|
||||||
if (m_LastSentDimension == a_World.GetDimension())
|
if (m_LastSentDimension == a_Dimension)
|
||||||
{
|
{
|
||||||
// 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
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cPlayer * Player = m_Client->GetPlayer();
|
cPlayer * Player = m_Client->GetPlayer();
|
||||||
WriteByte (PACKET_RESPAWN);
|
WriteByte (PACKET_RESPAWN);
|
||||||
WriteInt ((int)(a_World.GetDimension()));
|
WriteInt ((int)(a_Dimension));
|
||||||
WriteByte (2); // TODO: Difficulty; 2 = Normal
|
WriteByte (2); // TODO: Difficulty; 2 = Normal
|
||||||
WriteChar ((char)Player->GetGameMode());
|
WriteChar ((char)Player->GetGameMode());
|
||||||
WriteShort (256); // Current world height
|
WriteShort (256); // Current world height
|
||||||
WriteString("default");
|
WriteString("default");
|
||||||
Flush();
|
Flush();
|
||||||
m_LastSentDimension = a_World.GetDimension();
|
m_LastSentDimension = a_Dimension;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ public:
|
|||||||
virtual void SendPlayerSpawn (const cPlayer & a_Player) override;
|
virtual void SendPlayerSpawn (const cPlayer & a_Player) override;
|
||||||
virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) override;
|
virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) override;
|
||||||
virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override;
|
virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override;
|
||||||
virtual void SendRespawn (const cWorld & a_World) override;
|
virtual void SendRespawn (eDimension a_Dimension) override;
|
||||||
virtual void SendExperience (void) override;
|
virtual void SendExperience (void) override;
|
||||||
virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override;
|
virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override;
|
||||||
virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override;
|
virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override;
|
||||||
|
@ -158,10 +158,10 @@ void cProtocol161::SendPlayerMaxSpeed(void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cProtocol161::SendRespawn(const cWorld & a_World)
|
void cProtocol161::SendRespawn(eDimension a_Dimension)
|
||||||
{
|
{
|
||||||
// Besides sending the respawn, we need to also send the player max speed, otherwise the client reverts to super-fast
|
// Besides sending the respawn, we need to also send the player max speed, otherwise the client reverts to super-fast
|
||||||
super::SendRespawn(a_World);
|
super::SendRespawn(a_Dimension);
|
||||||
SendPlayerMaxSpeed();
|
SendPlayerMaxSpeed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ protected:
|
|||||||
virtual void SendGameMode (eGameMode a_GameMode) override;
|
virtual void SendGameMode (eGameMode a_GameMode) override;
|
||||||
virtual void SendHealth (void) override;
|
virtual void SendHealth (void) override;
|
||||||
virtual void SendPlayerMaxSpeed(void) override;
|
virtual void SendPlayerMaxSpeed(void) override;
|
||||||
virtual void SendRespawn (const cWorld & a_World) override;
|
virtual void SendRespawn (eDimension a_Dimension) override;
|
||||||
virtual void SendWindowOpen (const cWindow & a_Window) override;
|
virtual void SendWindowOpen (const cWindow & a_Window) override;
|
||||||
|
|
||||||
virtual int ParseEntityAction (void) override;
|
virtual int ParseEntityAction (void) override;
|
||||||
|
@ -986,9 +986,9 @@ void cProtocol172::SendRemoveEntityEffect(const cEntity & a_Entity, int a_Effect
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cProtocol172::SendRespawn(const cWorld & a_World)
|
void cProtocol172::SendRespawn(eDimension a_Dimension)
|
||||||
{
|
{
|
||||||
if (m_LastSentDimension == a_World.GetDimension())
|
if (m_LastSentDimension == a_Dimension)
|
||||||
{
|
{
|
||||||
// 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
|
||||||
return;
|
return;
|
||||||
@ -996,11 +996,11 @@ void cProtocol172::SendRespawn(const cWorld & a_World)
|
|||||||
|
|
||||||
cPacketizer Pkt(*this, 0x07); // Respawn packet
|
cPacketizer Pkt(*this, 0x07); // Respawn packet
|
||||||
cPlayer * Player = m_Client->GetPlayer();
|
cPlayer * Player = m_Client->GetPlayer();
|
||||||
Pkt.WriteInt((int)a_World.GetDimension());
|
Pkt.WriteInt((int)a_Dimension);
|
||||||
Pkt.WriteByte(2); // TODO: Difficulty (set to Normal)
|
Pkt.WriteByte(2); // TODO: Difficulty (set to Normal)
|
||||||
Pkt.WriteByte((Byte)Player->GetEffectiveGameMode());
|
Pkt.WriteByte((Byte)Player->GetEffectiveGameMode());
|
||||||
Pkt.WriteString("default");
|
Pkt.WriteString("default");
|
||||||
m_LastSentDimension = a_World.GetDimension();
|
m_LastSentDimension = a_Dimension;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@ public:
|
|||||||
virtual void SendPlayerSpawn (const cPlayer & a_Player) override;
|
virtual void SendPlayerSpawn (const cPlayer & a_Player) override;
|
||||||
virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) override;
|
virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) override;
|
||||||
virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override;
|
virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override;
|
||||||
virtual void SendRespawn (const cWorld & a_World) override;
|
virtual void SendRespawn (eDimension a_Dimension) override;
|
||||||
virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) override; // a_Src coords are Block * 8
|
virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) override; // a_Src coords are Block * 8
|
||||||
virtual void SendExperience (void) override;
|
virtual void SendExperience (void) override;
|
||||||
virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override;
|
virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override;
|
||||||
|
@ -555,10 +555,10 @@ void cProtocolRecognizer::SendRemoveEntityEffect(const cEntity & a_Entity, int a
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cProtocolRecognizer::SendRespawn(const cWorld & a_World)
|
void cProtocolRecognizer::SendRespawn(eDimension a_Dimension)
|
||||||
{
|
{
|
||||||
ASSERT(m_Protocol != NULL);
|
ASSERT(m_Protocol != NULL);
|
||||||
m_Protocol->SendRespawn(a_World);
|
m_Protocol->SendRespawn(a_Dimension);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ public:
|
|||||||
virtual void SendPlayerSpawn (const cPlayer & a_Player) override;
|
virtual void SendPlayerSpawn (const cPlayer & a_Player) override;
|
||||||
virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) override;
|
virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) override;
|
||||||
virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override;
|
virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override;
|
||||||
virtual void SendRespawn (const cWorld & a_World) override;
|
virtual void SendRespawn (eDimension a_Dimension) override;
|
||||||
virtual void SendExperience (void) override;
|
virtual void SendExperience (void) override;
|
||||||
virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override;
|
virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override;
|
||||||
virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override;
|
virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override;
|
||||||
|
@ -2416,7 +2416,6 @@ void cWorld::AddPlayer(cPlayer * a_Player)
|
|||||||
|
|
||||||
void cWorld::RemovePlayer(cPlayer * a_Player)
|
void cWorld::RemovePlayer(cPlayer * a_Player)
|
||||||
{
|
{
|
||||||
|
|
||||||
m_ChunkMap->RemoveEntity(a_Player);
|
m_ChunkMap->RemoveEntity(a_Player);
|
||||||
{
|
{
|
||||||
cCSLock Lock(m_CSPlayersToAdd);
|
cCSLock Lock(m_CSPlayersToAdd);
|
||||||
@ -2424,7 +2423,7 @@ void cWorld::RemovePlayer(cPlayer * a_Player)
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
cCSLock Lock(m_CSPlayers);
|
cCSLock Lock(m_CSPlayers);
|
||||||
LOGD("Removing player \"%s\" from world \"%s\".", a_Player->GetName().c_str(), m_WorldName.c_str());
|
LOGD("Removing player %s from world \"%s\".", a_Player->GetName().c_str(), m_WorldName.c_str());
|
||||||
m_Players.remove(a_Player);
|
m_Players.remove(a_Player);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3213,7 +3212,8 @@ void cWorld::AddQueuedPlayers(void)
|
|||||||
for (cPlayerList::iterator itr = PlayersToAdd.begin(), end = PlayersToAdd.end(); itr != end; ++itr)
|
for (cPlayerList::iterator itr = PlayersToAdd.begin(), end = PlayersToAdd.end(); itr != end; ++itr)
|
||||||
{
|
{
|
||||||
ASSERT(std::find(m_Players.begin(), m_Players.end(), *itr) == m_Players.end()); // Is it already in the list? HOW?
|
ASSERT(std::find(m_Players.begin(), m_Players.end(), *itr) == m_Players.end()); // Is it already in the list? HOW?
|
||||||
|
|
||||||
|
LOGD("Adding player %s to world \"%s\".", (*itr)->GetName().c_str(), m_WorldName.c_str());
|
||||||
m_Players.push_back(*itr);
|
m_Players.push_back(*itr);
|
||||||
(*itr)->SetWorld(this);
|
(*itr)->SetWorld(this);
|
||||||
|
|
||||||
@ -3242,6 +3242,9 @@ void cWorld::AddQueuedPlayers(void)
|
|||||||
if (Client != NULL)
|
if (Client != NULL)
|
||||||
{
|
{
|
||||||
Client->StreamChunks();
|
Client->StreamChunks();
|
||||||
|
Client->SendPlayerMoveLook();
|
||||||
|
Client->SendHealth();
|
||||||
|
Client->SendWholeInventory(*(*itr)->GetWindow());
|
||||||
}
|
}
|
||||||
} // for itr - PlayersToAdd[]
|
} // for itr - PlayersToAdd[]
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user