Rewritten entities so that they are owned by individual chunks and ticked within their chunk's Tick()
git-svn-id: http://mc-server.googlecode.com/svn/trunk@1385 0a769ca7-a7f5-676a-18bf-c427514a06d6
This commit is contained in:
parent
58fb05980d
commit
a49c004278
@ -1,6 +1,6 @@
|
||||
/*
|
||||
** Lua binding: AllToLua
|
||||
** Generated automatically by tolua++-1.0.92 on 04/11/13 11:57:58.
|
||||
** Generated automatically by tolua++-1.0.92 on 04/13/13 22:59:55.
|
||||
*/
|
||||
|
||||
#ifndef __cplusplus
|
||||
@ -4717,38 +4717,6 @@ static int tolua_AllToLua_cEntity_GetChunkX00(lua_State* tolua_S)
|
||||
}
|
||||
#endif //#ifndef TOLUA_DISABLE
|
||||
|
||||
/* method: GetChunkY of class cEntity */
|
||||
#ifndef TOLUA_DISABLE_tolua_AllToLua_cEntity_GetChunkY00
|
||||
static int tolua_AllToLua_cEntity_GetChunkY00(lua_State* tolua_S)
|
||||
{
|
||||
#ifndef TOLUA_RELEASE
|
||||
tolua_Error tolua_err;
|
||||
if (
|
||||
!tolua_isusertype(tolua_S,1,"const cEntity",0,&tolua_err) ||
|
||||
!tolua_isnoobj(tolua_S,2,&tolua_err)
|
||||
)
|
||||
goto tolua_lerror;
|
||||
else
|
||||
#endif
|
||||
{
|
||||
const cEntity* self = (const cEntity*) tolua_tousertype(tolua_S,1,0);
|
||||
#ifndef TOLUA_RELEASE
|
||||
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetChunkY'", NULL);
|
||||
#endif
|
||||
{
|
||||
int tolua_ret = (int) self->GetChunkY();
|
||||
tolua_pushnumber(tolua_S,(lua_Number)tolua_ret);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
#ifndef TOLUA_RELEASE
|
||||
tolua_lerror:
|
||||
tolua_error(tolua_S,"#ferror in function 'GetChunkY'.",&tolua_err);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
#endif //#ifndef TOLUA_DISABLE
|
||||
|
||||
/* method: GetChunkZ of class cEntity */
|
||||
#ifndef TOLUA_DISABLE_tolua_AllToLua_cEntity_GetChunkZ00
|
||||
static int tolua_AllToLua_cEntity_GetChunkZ00(lua_State* tolua_S)
|
||||
@ -24470,7 +24438,6 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
|
||||
tolua_function(tolua_S,"GetSpeedY",tolua_AllToLua_cEntity_GetSpeedY00);
|
||||
tolua_function(tolua_S,"GetSpeedZ",tolua_AllToLua_cEntity_GetSpeedZ00);
|
||||
tolua_function(tolua_S,"GetChunkX",tolua_AllToLua_cEntity_GetChunkX00);
|
||||
tolua_function(tolua_S,"GetChunkY",tolua_AllToLua_cEntity_GetChunkY00);
|
||||
tolua_function(tolua_S,"GetChunkZ",tolua_AllToLua_cEntity_GetChunkZ00);
|
||||
tolua_function(tolua_S,"SetHeadYaw",tolua_AllToLua_cEntity_SetHeadYaw00);
|
||||
tolua_function(tolua_S,"SetPosX",tolua_AllToLua_cEntity_SetPosX00);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
** Lua binding: AllToLua
|
||||
** Generated automatically by tolua++-1.0.92 on 04/11/13 11:57:59.
|
||||
** Generated automatically by tolua++-1.0.92 on 04/13/13 22:59:55.
|
||||
*/
|
||||
|
||||
/* Exported function */
|
||||
|
@ -144,9 +144,9 @@ void cChestEntity::UsedBy(cPlayer * a_Player)
|
||||
// Instead of marking the chunk as dirty upon chest contents change, we mark it dirty now
|
||||
// We cannot properly detect contents change, but such a change doesn't happen without a player opening the chest first.
|
||||
// The few false positives aren't much to worry about
|
||||
int ChunkX, ChunkY = 0, ChunkZ;
|
||||
int ChunkX, ChunkZ;
|
||||
cChunkDef::BlockToChunk(m_PosX, m_PosY, m_PosZ, ChunkX, ChunkZ);
|
||||
m_World->MarkChunkDirty(ChunkX, ChunkY, ChunkZ);
|
||||
m_World->MarkChunkDirty(ChunkX, ChunkZ);
|
||||
}
|
||||
|
||||
|
||||
|
142
source/Chunk.cpp
142
source/Chunk.cpp
@ -118,19 +118,15 @@ cChunk::~cChunk()
|
||||
|
||||
// Remove and destroy all entities that are not players:
|
||||
cEntityList Entities;
|
||||
for (cEntityList::const_iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr)
|
||||
std::swap(Entities, m_Entities); // Need another list because cEntity destructors check if they've been removed from chunk
|
||||
for (cEntityList::const_iterator itr = Entities.begin(); itr != Entities.end(); ++itr)
|
||||
{
|
||||
if (!(*itr)->IsPlayer())
|
||||
{
|
||||
Entities.push_back(*itr);
|
||||
(*itr)->Destroy();
|
||||
delete *itr;
|
||||
}
|
||||
}
|
||||
for (cEntityList::iterator itr = Entities.begin(); itr != Entities.end(); ++itr)
|
||||
{
|
||||
(*itr)->RemoveFromChunk();
|
||||
(*itr)->Destroy();
|
||||
}
|
||||
m_Entities.clear();
|
||||
|
||||
if (m_NeighborXM != NULL)
|
||||
{
|
||||
@ -267,7 +263,6 @@ void cChunk::SetAllData(
|
||||
const NIBBLETYPE * a_BlockSkyLight,
|
||||
const HeightMap * a_HeightMap,
|
||||
const BiomeMap & a_BiomeMap,
|
||||
cEntityList & a_Entities,
|
||||
cBlockEntityList & a_BlockEntities
|
||||
)
|
||||
{
|
||||
@ -296,9 +291,6 @@ void cChunk::SetAllData(
|
||||
CalculateHeightmap();
|
||||
}
|
||||
|
||||
// Append entities to current entity list:
|
||||
m_Entities.insert(m_Entities.end(), a_Entities.begin(), a_Entities.end());
|
||||
|
||||
// Clear the block entities present - either the loader / saver has better, or we'll create empty ones:
|
||||
for (cBlockEntityList::iterator itr = m_BlockEntities.begin(); itr != m_BlockEntities.end(); ++itr)
|
||||
{
|
||||
@ -438,7 +430,7 @@ void cChunk::Stay(bool a_Stay)
|
||||
|
||||
|
||||
|
||||
void cChunk::Tick(float a_Dt, MTRand & a_TickRandom)
|
||||
void cChunk::Tick(float a_Dt)
|
||||
{
|
||||
BroadcastPendingBlockChanges();
|
||||
|
||||
@ -454,7 +446,7 @@ void cChunk::Tick(float a_Dt, MTRand & a_TickRandom)
|
||||
// Tick simulators:
|
||||
m_World->GetSimulatorManager()->SimulateChunk(a_Dt, m_PosX, m_PosZ, this);
|
||||
|
||||
TickBlocks(a_TickRandom);
|
||||
TickBlocks();
|
||||
|
||||
// Tick all block entities in this chunk:
|
||||
for (cBlockEntityList::iterator itr = m_BlockEntities.begin(); itr != m_BlockEntities.end(); ++itr)
|
||||
@ -462,6 +454,43 @@ void cChunk::Tick(float a_Dt, MTRand & a_TickRandom)
|
||||
m_IsDirty = (*itr)->Tick(a_Dt) | m_IsDirty;
|
||||
}
|
||||
|
||||
// Tick all entities in this chunk:
|
||||
for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr)
|
||||
{
|
||||
(*itr)->Tick(a_Dt, *this);
|
||||
} // for itr - m_Entitites[]
|
||||
|
||||
// Remove all entities that were scheduled for removal:
|
||||
for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end();)
|
||||
{
|
||||
if ((*itr)->IsDestroyed())
|
||||
{
|
||||
LOGD("Destroying entity #%i (%s)", (*itr)->GetUniqueID(), (*itr)->GetClass());
|
||||
cEntity * ToDelete = *itr;
|
||||
itr = m_Entities.erase(itr);
|
||||
delete ToDelete;
|
||||
continue;
|
||||
}
|
||||
itr++;
|
||||
} // for itr - m_Entitites[]
|
||||
|
||||
// If any entity moved out of the chunk, move it to the neighbor:
|
||||
for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end();)
|
||||
{
|
||||
if (
|
||||
((*itr)->GetChunkX() != m_PosX) ||
|
||||
((*itr)->GetChunkZ() != m_PosZ)
|
||||
)
|
||||
{
|
||||
MoveEntityToNewChunk(*itr);
|
||||
itr = m_Entities.erase(itr);
|
||||
}
|
||||
else
|
||||
{
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
|
||||
ApplyWeatherToTop();
|
||||
}
|
||||
|
||||
@ -469,6 +498,46 @@ void cChunk::Tick(float a_Dt, MTRand & a_TickRandom)
|
||||
|
||||
|
||||
|
||||
void cChunk::MoveEntityToNewChunk(cEntity * a_Entity)
|
||||
{
|
||||
cChunk * Neighbor = GetNeighborChunk((int)a_Entity->GetPosX(), (int)a_Entity->GetPosZ());
|
||||
if (Neighbor == NULL)
|
||||
{
|
||||
// TODO: What to do with this?
|
||||
LOGWARNING("%s: Failed to move entity, destination chunk unreachable. Entity lost", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
Neighbor->AddEntity(a_Entity);
|
||||
|
||||
class cMover :
|
||||
public cClientDiffCallback
|
||||
{
|
||||
virtual void Removed(cClientHandle * a_Client) override
|
||||
{
|
||||
a_Client->SendDestroyEntity(*m_Entity);
|
||||
}
|
||||
|
||||
virtual void Added(cClientHandle * a_Client) override
|
||||
{
|
||||
m_Entity->SpawnOn(*a_Client);
|
||||
}
|
||||
|
||||
cEntity * m_Entity;
|
||||
|
||||
public:
|
||||
cMover(cEntity * a_Entity) :
|
||||
m_Entity(a_Entity)
|
||||
{}
|
||||
} Mover(a_Entity);
|
||||
|
||||
m_ChunkMap->CompareChunkClients(this, Neighbor, Mover);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cChunk::BroadcastPendingBlockChanges(void)
|
||||
{
|
||||
sSetBlockVector Changes;
|
||||
@ -516,13 +585,13 @@ void cChunk::CheckBlocks(void)
|
||||
|
||||
|
||||
|
||||
void cChunk::TickBlocks(MTRand & a_TickRandom)
|
||||
void cChunk::TickBlocks(void)
|
||||
{
|
||||
// Tick dem blocks
|
||||
// _X: We must limit the random number or else we get a nasty int overflow bug ( http://forum.mc-server.org/showthread.php?tid=457 )
|
||||
int RandomX = a_TickRandom.randInt(0x00ffffff);
|
||||
int RandomY = a_TickRandom.randInt(0x00ffffff);
|
||||
int RandomZ = a_TickRandom.randInt(0x00ffffff);
|
||||
int RandomX = m_World->GetTickRandomNumber(0x00ffffff);
|
||||
int RandomY = m_World->GetTickRandomNumber(0x00ffffff);
|
||||
int RandomZ = m_World->GetTickRandomNumber(0x00ffffff);
|
||||
int TickX = m_BlockTickX;
|
||||
int TickY = m_BlockTickY;
|
||||
int TickZ = m_BlockTickZ;
|
||||
@ -1609,6 +1678,9 @@ void cChunk::AddEntity(cEntity * a_Entity)
|
||||
{
|
||||
MarkDirty();
|
||||
}
|
||||
|
||||
ASSERT(std::find(m_Entities.begin(), m_Entities.end(), a_Entity) == m_Entities.end()); // Not there already
|
||||
|
||||
m_Entities.push_back(a_Entity);
|
||||
}
|
||||
|
||||
@ -1636,6 +1708,22 @@ void cChunk::RemoveEntity(cEntity * a_Entity)
|
||||
|
||||
|
||||
|
||||
bool cChunk::HasEntity(int a_EntityID)
|
||||
{
|
||||
for (cEntityList::const_iterator itr = m_Entities.begin(), end = m_Entities.end(); itr != end; ++itr)
|
||||
{
|
||||
if ((*itr)->GetUniqueID() == a_EntityID)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
} // for itr - m_Entities[]
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunk::ForEachEntity(cEntityCallback & a_Callback)
|
||||
{
|
||||
// The entity list is locked by the parent chunkmap's CS
|
||||
@ -1654,6 +1742,24 @@ bool cChunk::ForEachEntity(cEntityCallback & a_Callback)
|
||||
|
||||
|
||||
|
||||
bool cChunk::DoWithEntityByID(int a_EntityID, cEntityCallback & a_Callback, bool & a_CallbackResult)
|
||||
{
|
||||
// The entity list is locked by the parent chunkmap's CS
|
||||
for (cEntityList::iterator itr = m_Entities.begin(), end = m_Entities.end(); itr != end; ++itr)
|
||||
{
|
||||
if ((*itr)->GetUniqueID() == a_EntityID)
|
||||
{
|
||||
a_CallbackResult = a_Callback.Item(*itr);
|
||||
return true;
|
||||
}
|
||||
} // for itr - m_Entitites[]
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunk::ForEachChest(cChestCallback & a_Callback)
|
||||
{
|
||||
// The blockentity list is locked by the parent chunkmap's CS
|
||||
|
@ -104,7 +104,6 @@ public:
|
||||
const NIBBLETYPE * a_BlockSkyLight,
|
||||
const cChunkDef::HeightMap * a_HeightMap,
|
||||
const cChunkDef::BiomeMap & a_BiomeMap,
|
||||
cEntityList & a_Entities,
|
||||
cBlockEntityList & a_BlockEntities
|
||||
);
|
||||
|
||||
@ -125,7 +124,7 @@ public:
|
||||
/// Sets or resets the internal flag that prevents chunk from being unloaded
|
||||
void Stay(bool a_Stay = true);
|
||||
|
||||
void Tick(float a_Dt, MTRand & a_TickRandom);
|
||||
void Tick(float a_Dt);
|
||||
|
||||
int GetPosX(void) const { return m_PosX; }
|
||||
int GetPosY(void) const { return m_PosY; }
|
||||
@ -176,12 +175,16 @@ public:
|
||||
bool HasClient (cClientHandle* a_Client );
|
||||
bool HasAnyClients(void); // Returns true if theres any client in the chunk; false otherwise
|
||||
|
||||
void AddEntity( cEntity * a_Entity);
|
||||
void RemoveEntity( cEntity * a_Entity);
|
||||
void AddEntity(cEntity * a_Entity);
|
||||
void RemoveEntity(cEntity * a_Entity);
|
||||
bool HasEntity(int a_EntityID);
|
||||
|
||||
/// Calls the callback for each entity; returns true if all entities processed, false if the callback aborted by returning true
|
||||
bool ForEachEntity(cEntityCallback & a_Callback); // Lua-accessible
|
||||
|
||||
/// Calls the callback if the entity with the specified ID is found, with the entity object as the callback param. Returns true if entity found.
|
||||
bool DoWithEntityByID(int a_EntityID, cEntityCallback & a_Callback, bool & a_CallbackResult); // Lua-accessible
|
||||
|
||||
/// Calls the callback for each chest; returns true if all chests processed, false if the callback aborted by returning true
|
||||
bool ForEachChest(cChestCallback & a_Callback); // Lua-accessible
|
||||
|
||||
@ -352,7 +355,8 @@ private:
|
||||
/// Checks the block scheduled for checking in m_ToTickBlocks[]
|
||||
void CheckBlocks(void);
|
||||
|
||||
void TickBlocks (MTRand & a_TickRandom);
|
||||
/// Ticks several random blocks in the chunk
|
||||
void TickBlocks(void);
|
||||
|
||||
/// Adds snow to the top of snowy biomes and hydrates farmland / fills cauldrons in rainy biomes
|
||||
void ApplyWeatherToTop(void);
|
||||
@ -368,6 +372,9 @@ private:
|
||||
|
||||
/// Checks if a leaves block at the specified coords has a log up to 4 blocks away connected by other leaves blocks (false if no log)
|
||||
bool HasNearLog(cBlockArea & a_Area, int a_BlockX, int a_BlockY, int a_BlockZ);
|
||||
|
||||
/// Called by Tick() when an entity moves out of this chunk into a neighbor; moves the entity and sends spawn / despawn packet to clients
|
||||
void MoveEntityToNewChunk(cEntity * a_Entity);
|
||||
};
|
||||
|
||||
typedef cChunk * cChunkPtr;
|
||||
|
@ -277,7 +277,7 @@ cChunk * cChunkMap::FindChunk(int a_ChunkX, int a_ChunkZ)
|
||||
void cChunkMap::BroadcastAttachEntity(const cEntity & a_Entity, const cEntity * a_Vehicle)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkY(), a_Entity.GetChunkZ());
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), ZERO_CHUNK_Y, a_Entity.GetChunkZ());
|
||||
if (Chunk == NULL)
|
||||
{
|
||||
return;
|
||||
@ -292,7 +292,7 @@ void cChunkMap::BroadcastAttachEntity(const cEntity & a_Entity, const cEntity *
|
||||
void cChunkMap::BroadcastPlayerAnimation(const cPlayer & a_Player, char a_Animation, const cClientHandle * a_Exclude)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_Player.GetChunkX(), a_Player.GetChunkY(), a_Player.GetChunkZ());
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_Player.GetChunkX(), ZERO_CHUNK_Y, a_Player.GetChunkZ());
|
||||
if (Chunk == NULL)
|
||||
{
|
||||
return;
|
||||
@ -308,7 +308,7 @@ void cChunkMap::BroadcastPlayerAnimation(const cPlayer & a_Player, char a_Animat
|
||||
void cChunkMap::BroadcastEntityEquipment(const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item, const cClientHandle * a_Exclude)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkY(), a_Entity.GetChunkZ());
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), ZERO_CHUNK_Y, a_Entity.GetChunkZ());
|
||||
if (Chunk == NULL)
|
||||
{
|
||||
return;
|
||||
@ -325,7 +325,7 @@ void cChunkMap::BroadcastEntityEquipment(const cEntity & a_Entity, short a_SlotN
|
||||
void cChunkMap::BroadcastEntVelocity(const cEntity & a_Entity, const cClientHandle * a_Exclude)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkY(), a_Entity.GetChunkZ());
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), ZERO_CHUNK_Y, a_Entity.GetChunkZ());
|
||||
if (Chunk == NULL)
|
||||
{
|
||||
return;
|
||||
@ -341,7 +341,7 @@ void cChunkMap::BroadcastEntVelocity(const cEntity & a_Entity, const cClientHand
|
||||
void cChunkMap::BroadcastEntRelMoveLook(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ, const cClientHandle * a_Exclude)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkY(), a_Entity.GetChunkZ());
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), ZERO_CHUNK_Y, a_Entity.GetChunkZ());
|
||||
if (Chunk == NULL)
|
||||
{
|
||||
return;
|
||||
@ -358,7 +358,7 @@ void cChunkMap::BroadcastEntRelMoveLook(const cEntity & a_Entity, char a_RelX, c
|
||||
void cChunkMap::BroadcastEntRelMove(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ, const cClientHandle * a_Exclude)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkY(), a_Entity.GetChunkZ());
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), ZERO_CHUNK_Y, a_Entity.GetChunkZ());
|
||||
if (Chunk == NULL)
|
||||
{
|
||||
return;
|
||||
@ -375,7 +375,7 @@ void cChunkMap::BroadcastEntRelMove(const cEntity & a_Entity, char a_RelX, char
|
||||
void cChunkMap::BroadcastEntLook(const cEntity & a_Entity, const cClientHandle * a_Exclude)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkY(), a_Entity.GetChunkZ());
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), ZERO_CHUNK_Y, a_Entity.GetChunkZ());
|
||||
if (Chunk == NULL)
|
||||
{
|
||||
return;
|
||||
@ -392,7 +392,7 @@ void cChunkMap::BroadcastEntLook(const cEntity & a_Entity, const cClientHandle *
|
||||
void cChunkMap::BroadcastEntHeadLook(const cEntity & a_Entity, const cClientHandle * a_Exclude)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkY(), a_Entity.GetChunkZ());
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), ZERO_CHUNK_Y, a_Entity.GetChunkZ());
|
||||
if (Chunk == NULL)
|
||||
{
|
||||
return;
|
||||
@ -431,7 +431,7 @@ void cChunkMap::BroadcastBlockAction(int a_BlockX, int a_BlockY, int a_BlockZ, c
|
||||
void cChunkMap::BroadcastDestroyEntity(const cEntity & a_Entity, const cClientHandle * a_Exclude)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkY(), a_Entity.GetChunkZ());
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), ZERO_CHUNK_Y, a_Entity.GetChunkZ());
|
||||
if (Chunk == NULL)
|
||||
{
|
||||
return;
|
||||
@ -448,7 +448,7 @@ void cChunkMap::BroadcastDestroyEntity(const cEntity & a_Entity, const cClientHa
|
||||
void cChunkMap::BroadcastEntityStatus(const cEntity & a_Entity, char a_Status, const cClientHandle * a_Exclude)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkY(), a_Entity.GetChunkZ());
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), ZERO_CHUNK_Y, a_Entity.GetChunkZ());
|
||||
if (Chunk == NULL)
|
||||
{
|
||||
return;
|
||||
@ -465,7 +465,7 @@ void cChunkMap::BroadcastEntityStatus(const cEntity & a_Entity, char a_Status, c
|
||||
void cChunkMap::BroadcastMetadata(const cPawn & a_Pawn, const cClientHandle * a_Exclude)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_Pawn.GetChunkX(), a_Pawn.GetChunkY(), a_Pawn.GetChunkZ());
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_Pawn.GetChunkX(), ZERO_CHUNK_Y, a_Pawn.GetChunkZ());
|
||||
if (Chunk == NULL)
|
||||
{
|
||||
return;
|
||||
@ -481,7 +481,7 @@ void cChunkMap::BroadcastMetadata(const cPawn & a_Pawn, const cClientHandle * a_
|
||||
void cChunkMap::BroadcastSpawn(cEntity & a_Entity, const cClientHandle * a_Exclude)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkY(), a_Entity.GetChunkZ());
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), ZERO_CHUNK_Y, a_Entity.GetChunkZ());
|
||||
if (Chunk == NULL)
|
||||
{
|
||||
return;
|
||||
@ -497,7 +497,7 @@ void cChunkMap::BroadcastSpawn(cEntity & a_Entity, const cClientHandle * a_Exclu
|
||||
void cChunkMap::BroadcastCollectPickup(const cPickup & a_Pickup, const cPlayer & a_Player, const cClientHandle * a_Exclude)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_Pickup.GetChunkX(), a_Pickup.GetChunkY(), a_Pickup.GetChunkZ());
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_Pickup.GetChunkX(), ZERO_CHUNK_Y, a_Pickup.GetChunkZ());
|
||||
if (Chunk == NULL)
|
||||
{
|
||||
return;
|
||||
@ -689,10 +689,10 @@ void cChunkMap::WakeUpSimulators(int a_BlockX, int a_BlockY, int a_BlockZ)
|
||||
|
||||
|
||||
|
||||
void cChunkMap::MarkChunkDirty (int a_ChunkX, int a_ChunkY, int a_ChunkZ)
|
||||
void cChunkMap::MarkChunkDirty (int a_ChunkX, int a_ChunkZ)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkY, a_ChunkZ);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
|
||||
if ((Chunk == NULL) || !Chunk->IsValid())
|
||||
{
|
||||
return;
|
||||
@ -704,10 +704,10 @@ void cChunkMap::MarkChunkDirty (int a_ChunkX, int a_ChunkY, int a_ChunkZ)
|
||||
|
||||
|
||||
|
||||
void cChunkMap::MarkChunkSaving(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
|
||||
void cChunkMap::MarkChunkSaving(int a_ChunkX, int a_ChunkZ)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkY, a_ChunkZ);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
|
||||
if ((Chunk == NULL) || !Chunk->IsValid())
|
||||
{
|
||||
return;
|
||||
@ -719,10 +719,10 @@ void cChunkMap::MarkChunkSaving(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
|
||||
|
||||
|
||||
|
||||
void cChunkMap::MarkChunkSaved (int a_ChunkX, int a_ChunkY, int a_ChunkZ)
|
||||
void cChunkMap::MarkChunkSaved (int a_ChunkX, int a_ChunkZ)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkY, a_ChunkZ);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
|
||||
if ((Chunk == NULL) || !Chunk->IsValid())
|
||||
{
|
||||
return;
|
||||
@ -735,25 +735,24 @@ void cChunkMap::MarkChunkSaved (int a_ChunkX, int a_ChunkY, int a_ChunkZ)
|
||||
|
||||
|
||||
void cChunkMap::SetChunkData(
|
||||
int a_ChunkX, int a_ChunkY, int a_ChunkZ,
|
||||
int a_ChunkX, int a_ChunkZ,
|
||||
const BLOCKTYPE * a_BlockTypes,
|
||||
const NIBBLETYPE * a_BlockMeta,
|
||||
const NIBBLETYPE * a_BlockLight,
|
||||
const NIBBLETYPE * a_BlockSkyLight,
|
||||
const cChunkDef::HeightMap * a_HeightMap,
|
||||
const cChunkDef::BiomeMap & a_BiomeMap,
|
||||
cEntityList & a_Entities,
|
||||
cBlockEntityList & a_BlockEntities,
|
||||
bool a_MarkDirty
|
||||
)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, a_ChunkY, a_ChunkZ);
|
||||
cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
|
||||
if (Chunk == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Chunk->SetAllData(a_BlockTypes, a_BlockMeta, a_BlockLight, a_BlockSkyLight, a_HeightMap, a_BiomeMap, a_Entities, a_BlockEntities);
|
||||
Chunk->SetAllData(a_BlockTypes, a_BlockMeta, a_BlockLight, a_BlockSkyLight, a_HeightMap, a_BiomeMap, a_BlockEntities);
|
||||
|
||||
if (a_MarkDirty)
|
||||
{
|
||||
@ -788,10 +787,10 @@ void cChunkMap::ChunkLighted(
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::GetChunkData(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cChunkDataCallback & a_Callback)
|
||||
bool cChunkMap::GetChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataCallback & a_Callback)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkY, a_ChunkZ);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
|
||||
if ((Chunk == NULL) || !Chunk->IsValid())
|
||||
{
|
||||
return false;
|
||||
@ -804,10 +803,10 @@ bool cChunkMap::GetChunkData(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cChunkDat
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::GetChunkBlockTypes(int a_ChunkX, int a_ChunkY, int a_ChunkZ, BLOCKTYPE * a_BlockTypes)
|
||||
bool cChunkMap::GetChunkBlockTypes(int a_ChunkX, int a_ChunkZ, BLOCKTYPE * a_BlockTypes)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkY, a_ChunkZ);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
|
||||
if ((Chunk == NULL) || !Chunk->IsValid())
|
||||
{
|
||||
return false;
|
||||
@ -820,10 +819,10 @@ bool cChunkMap::GetChunkBlockTypes(int a_ChunkX, int a_ChunkY, int a_ChunkZ, BLO
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::IsChunkValid(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
|
||||
bool cChunkMap::IsChunkValid(int a_ChunkX, int a_ChunkZ)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, a_ChunkY, a_ChunkZ);
|
||||
cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
|
||||
return (Chunk != NULL) && Chunk->IsValid();
|
||||
}
|
||||
|
||||
@ -831,10 +830,10 @@ bool cChunkMap::IsChunkValid(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::HasChunkAnyClients(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
|
||||
bool cChunkMap::HasChunkAnyClients(int a_ChunkX, int a_ChunkZ)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkY, a_ChunkZ);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
|
||||
return (Chunk != NULL) && Chunk->HasAnyClients();
|
||||
}
|
||||
|
||||
@ -844,24 +843,45 @@ bool cChunkMap::HasChunkAnyClients(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
|
||||
|
||||
int cChunkMap::GetHeight(int a_BlockX, int a_BlockZ)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
int ChunkX, ChunkZ, BlockY = 0;
|
||||
cChunkDef::AbsoluteToRelative(a_BlockX, BlockY, a_BlockZ, ChunkX, ChunkZ);
|
||||
cChunkPtr Chunk = GetChunk(ChunkX, ZERO_CHUNK_Y, ChunkZ);
|
||||
if (Chunk == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (Chunk->IsValid())
|
||||
{
|
||||
return Chunk->GetHeight(a_BlockX, a_BlockZ);
|
||||
}
|
||||
|
||||
// The chunk is not valid, wait for it to become valid:
|
||||
cCSUnlock Unlock(Lock);
|
||||
m_evtChunkValid.Wait();
|
||||
} // while (true)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::TryGetHeight(int a_BlockX, int a_BlockZ, int & a_Height)
|
||||
{
|
||||
// Returns false if chunk not loaded / generated
|
||||
cCSLock Lock(m_CSLayers);
|
||||
int ChunkX, ChunkZ, BlockY = 0;
|
||||
cChunkDef::AbsoluteToRelative(a_BlockX, BlockY, a_BlockZ, ChunkX, ChunkZ);
|
||||
cChunkPtr Chunk = GetChunk(ChunkX, ZERO_CHUNK_Y, ChunkZ);
|
||||
if (Chunk == NULL)
|
||||
cChunkPtr Chunk = GetChunkNoLoad(ChunkX, ZERO_CHUNK_Y, ChunkZ);
|
||||
if ((Chunk == NULL) || !Chunk->IsValid())
|
||||
{
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Wait for the chunk to become valid:
|
||||
while (!Chunk->IsValid())
|
||||
{
|
||||
GetChunk(ChunkX, ZERO_CHUNK_Y, ChunkZ); // Re-queue (in case it managed to get unloaded before we caught it
|
||||
cCSUnlock Unlock(Lock);
|
||||
m_evtChunkValid.Wait();
|
||||
}
|
||||
|
||||
return Chunk->GetHeight(a_BlockX, a_BlockZ);
|
||||
a_Height = Chunk->GetHeight(a_BlockX, a_BlockZ);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -1239,22 +1259,31 @@ void cChunkMap::SendBlockTo(int a_X, int a_Y, int a_Z, cPlayer * a_Player)
|
||||
|
||||
|
||||
|
||||
void cChunkMap::CompareChunkClients(int a_ChunkX1, int a_ChunkY1, int a_ChunkZ1, int a_ChunkX2, int a_ChunkY2, int a_ChunkZ2, cClientDiffCallback & a_Callback)
|
||||
void cChunkMap::CompareChunkClients(int a_ChunkX1, int a_ChunkZ1, int a_ChunkX2, int a_ChunkZ2, cClientDiffCallback & a_Callback)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr Chunk1 = GetChunkNoGen(a_ChunkX1, a_ChunkY1, a_ChunkZ1);
|
||||
cChunkPtr Chunk1 = GetChunkNoGen(a_ChunkX1, ZERO_CHUNK_Y, a_ChunkZ1);
|
||||
if (Chunk1 == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
cChunkPtr Chunk2 = GetChunkNoGen(a_ChunkX2, a_ChunkY2, a_ChunkZ2);
|
||||
cChunkPtr Chunk2 = GetChunkNoGen(a_ChunkX2, ZERO_CHUNK_Y, a_ChunkZ2);
|
||||
if (Chunk2 == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CompareChunkClients(Chunk1, Chunk2, a_Callback);
|
||||
}
|
||||
|
||||
cClientHandleList Clients1(Chunk1->GetAllClients());
|
||||
cClientHandleList Clients2(Chunk2->GetAllClients());
|
||||
|
||||
|
||||
|
||||
|
||||
void cChunkMap::CompareChunkClients(cChunk * a_Chunk1, cChunk * a_Chunk2, cClientDiffCallback & a_Callback)
|
||||
{
|
||||
cClientHandleList Clients1(a_Chunk1->GetAllClients());
|
||||
cClientHandleList Clients2(a_Chunk2->GetAllClients());
|
||||
|
||||
// Find "removed" clients:
|
||||
for (cClientHandleList::iterator itr1 = Clients1.begin(); itr1 != Clients1.end(); ++itr1)
|
||||
@ -1297,10 +1326,10 @@ void cChunkMap::CompareChunkClients(int a_ChunkX1, int a_ChunkY1, int a_ChunkZ1,
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::AddChunkClient(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client)
|
||||
bool cChunkMap::AddChunkClient(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr Chunk = GetChunk(a_ChunkX, a_ChunkY, a_ChunkZ);
|
||||
cChunkPtr Chunk = GetChunk(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
|
||||
if (Chunk == NULL)
|
||||
{
|
||||
return false;
|
||||
@ -1312,10 +1341,10 @@ bool cChunkMap::AddChunkClient(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClient
|
||||
|
||||
|
||||
|
||||
void cChunkMap::RemoveChunkClient(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client)
|
||||
void cChunkMap::RemoveChunkClient(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkY, a_ChunkZ);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
|
||||
if (Chunk == NULL)
|
||||
{
|
||||
return;
|
||||
@ -1341,15 +1370,16 @@ void cChunkMap::RemoveClientFromChunks(cClientHandle * a_Client)
|
||||
|
||||
|
||||
|
||||
void cChunkMap::MoveEntityToChunk(cEntity * a_Entity, int a_ChunkX, int a_ChunkY, int a_ChunkZ)
|
||||
// TODO: This function should not be needed, remove?
|
||||
void cChunkMap::MoveEntityToChunk(cEntity * a_Entity, int a_ChunkX, int a_ChunkZ)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr OldChunk = GetChunkNoGen(a_Entity->GetChunkX(), a_Entity->GetChunkY(), a_Entity->GetChunkZ());
|
||||
cChunkPtr OldChunk = GetChunkNoGen(a_Entity->GetChunkX(), ZERO_CHUNK_Y, a_Entity->GetChunkZ());
|
||||
if (OldChunk != NULL)
|
||||
{
|
||||
OldChunk->RemoveEntity(a_Entity);
|
||||
}
|
||||
cChunkPtr NewChunk = GetChunkNoGen(a_ChunkX, a_ChunkY, a_ChunkZ);
|
||||
cChunkPtr NewChunk = GetChunkNoGen(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
|
||||
if (NewChunk != NULL)
|
||||
{
|
||||
NewChunk->AddEntity(a_Entity);
|
||||
@ -1360,10 +1390,10 @@ void cChunkMap::MoveEntityToChunk(cEntity * a_Entity, int a_ChunkX, int a_ChunkY
|
||||
|
||||
|
||||
|
||||
void cChunkMap::RemoveEntityFromChunk(cEntity * a_Entity, int a_ChunkX, int a_ChunkY, int a_ChunkZ)
|
||||
void cChunkMap::RemoveEntityFromChunk(cEntity * a_Entity, int a_ChunkX, int a_ChunkZ)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkY, a_ChunkZ);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
|
||||
if ((Chunk == NULL) && !Chunk->IsValid())
|
||||
{
|
||||
return;
|
||||
@ -1375,6 +1405,55 @@ void cChunkMap::RemoveEntityFromChunk(cEntity * a_Entity, int a_ChunkX, int a_Ch
|
||||
|
||||
|
||||
|
||||
void cChunkMap::AddEntity(cEntity * a_Entity)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr Chunk = GetChunkNoGen(a_Entity->GetChunkX(), ZERO_CHUNK_Y, a_Entity->GetChunkZ());
|
||||
if ((Chunk == NULL) && !Chunk->IsValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
Chunk->AddEntity(a_Entity);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::HasEntity(int a_UniqueID)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
for (cChunkLayerList::const_iterator itr = m_Layers.begin(); itr != m_Layers.end(); ++itr)
|
||||
{
|
||||
if ((*itr)->HasEntity(a_UniqueID))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::ForEachEntity(cEntityCallback & a_Callback)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
for (cChunkLayerList::const_iterator itr = m_Layers.begin(); itr != m_Layers.end(); ++itr)
|
||||
{
|
||||
if ((*itr)->ForEachEntity(a_Callback))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback & a_Callback)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
@ -1390,6 +1469,24 @@ bool cChunkMap::ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::DoWithEntityByID(int a_UniqueID, cEntityCallback & a_Callback)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
bool res = false;
|
||||
for (cChunkLayerList::const_iterator itr = m_Layers.begin(); itr != m_Layers.end(); ++itr)
|
||||
{
|
||||
if ((*itr)->DoWithEntityByID(a_UniqueID, a_Callback, res))
|
||||
{
|
||||
return res;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::ForEachChestInChunk(int a_ChunkX, int a_ChunkZ, cChestCallback & a_Callback)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
@ -1794,12 +1891,12 @@ void cChunkMap::SetNextBlockTick(int a_BlockX, int a_BlockY, int a_BlockZ)
|
||||
|
||||
|
||||
|
||||
void cChunkMap::Tick( float a_Dt, MTRand & a_TickRandom )
|
||||
void cChunkMap::Tick(float a_Dt)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
for (cChunkLayerList::iterator itr = m_Layers.begin(); itr != m_Layers.end(); ++itr)
|
||||
{
|
||||
(*itr)->Tick(a_Dt, a_TickRandom);
|
||||
(*itr)->Tick(a_Dt);
|
||||
} // for itr - m_Layers
|
||||
}
|
||||
|
||||
@ -1951,14 +2048,14 @@ cChunk * cChunkMap::cChunkLayer::FindChunk(int a_ChunkX, int a_ChunkZ)
|
||||
|
||||
|
||||
|
||||
void cChunkMap::cChunkLayer::Tick(float a_Dt, MTRand & a_TickRand)
|
||||
void cChunkMap::cChunkLayer::Tick(float a_Dt)
|
||||
{
|
||||
for (int i = 0; i < ARRAYCOUNT(m_Chunks); i++)
|
||||
{
|
||||
// Only tick chunks that are valid and have clients:
|
||||
if ((m_Chunks[i] != NULL) && m_Chunks[i]->IsValid() && m_Chunks[i]->HasAnyClients())
|
||||
{
|
||||
m_Chunks[i]->Tick(a_Dt, a_TickRand);
|
||||
m_Chunks[i]->Tick(a_Dt);
|
||||
}
|
||||
} // for i - m_Chunks[]
|
||||
}
|
||||
@ -1982,6 +2079,65 @@ void cChunkMap::cChunkLayer::RemoveClient(cClientHandle * a_Client)
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::cChunkLayer::ForEachEntity(cEntityCallback & a_Callback)
|
||||
{
|
||||
// Calls the callback for each entity in the entire world; returns true if all entities processed, false if the callback aborted by returning true
|
||||
for (int i = 0; i < ARRAYCOUNT(m_Chunks); i++)
|
||||
{
|
||||
if ((m_Chunks[i] != NULL) && m_Chunks[i]->IsValid())
|
||||
{
|
||||
if (!m_Chunks[i]->ForEachEntity(a_Callback))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::cChunkLayer::DoWithEntityByID(int a_EntityID, cEntityCallback & a_Callback, bool & a_CallbackReturn)
|
||||
{
|
||||
// Calls the callback if the entity with the specified ID is found, with the entity object as the callback param. Returns true if entity found.
|
||||
for (int i = 0; i < ARRAYCOUNT(m_Chunks); i++)
|
||||
{
|
||||
if ((m_Chunks[i] != NULL) && m_Chunks[i]->IsValid())
|
||||
{
|
||||
if (m_Chunks[i]->DoWithEntityByID(a_EntityID, a_Callback, a_CallbackReturn))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunkMap::cChunkLayer::HasEntity(int a_EntityID)
|
||||
{
|
||||
for (int i = 0; i < ARRAYCOUNT(m_Chunks); i++)
|
||||
{
|
||||
if ((m_Chunks[i] != NULL) && m_Chunks[i]->IsValid())
|
||||
{
|
||||
if (m_Chunks[i]->HasEntity(a_EntityID))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int cChunkMap::cChunkLayer::GetNumChunksLoaded(void) const
|
||||
{
|
||||
int NumChunks = 0;
|
||||
|
@ -105,9 +105,9 @@ public:
|
||||
/// Wakes up simulators for the specified block
|
||||
void WakeUpSimulators(int a_BlockX, int a_BlockY, int a_BlockZ);
|
||||
|
||||
void MarkChunkDirty (int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
||||
void MarkChunkSaving (int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
||||
void MarkChunkSaved (int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
||||
void MarkChunkDirty (int a_ChunkX, int a_ChunkZ);
|
||||
void MarkChunkSaving (int a_ChunkX, int a_ChunkZ);
|
||||
void MarkChunkSaved (int a_ChunkX, int a_ChunkZ);
|
||||
|
||||
/** Sets the chunk data as either loaded from the storage or generated.
|
||||
a_BlockLight and a_BlockSkyLight are optional, if not present, chunk will be marked as unlighted.
|
||||
@ -116,14 +116,13 @@ public:
|
||||
If a_MarkDirty is set, the chunk is set as dirty (used after generating)
|
||||
*/
|
||||
void SetChunkData(
|
||||
int a_ChunkX, int a_ChunkY, int a_ChunkZ,
|
||||
int a_ChunkX, int a_ChunkZ,
|
||||
const BLOCKTYPE * a_BlockTypes,
|
||||
const NIBBLETYPE * a_BlockMeta,
|
||||
const NIBBLETYPE * a_BlockLight,
|
||||
const NIBBLETYPE * a_BlockSkyLight,
|
||||
const cChunkDef::HeightMap * a_HeightMap,
|
||||
const cChunkDef::BiomeMap & a_BiomeMap,
|
||||
cEntityList & a_Entities,
|
||||
cBlockEntityList & a_BlockEntities,
|
||||
bool a_MarkDirty
|
||||
);
|
||||
@ -134,14 +133,15 @@ public:
|
||||
const cChunkDef::BlockNibbles & a_SkyLight
|
||||
);
|
||||
|
||||
bool GetChunkData (int a_ChunkX, int a_ChunkY, int a_ChunkZ, cChunkDataCallback & a_Callback);
|
||||
bool GetChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataCallback & a_Callback);
|
||||
|
||||
/// Copies the chunk's blocktypes into a_Blocks; returns true if successful
|
||||
bool GetChunkBlockTypes (int a_ChunkX, int a_ChunkY, int a_ChunkZ, BLOCKTYPE * a_Blocks);
|
||||
bool GetChunkBlockTypes (int a_ChunkX, int a_ChunkZ, BLOCKTYPE * a_Blocks);
|
||||
|
||||
bool IsChunkValid (int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
||||
bool HasChunkAnyClients (int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
||||
int GetHeight (int a_BlockX, int a_BlockZ);
|
||||
bool IsChunkValid (int a_ChunkX, int a_ChunkZ);
|
||||
bool HasChunkAnyClients (int a_ChunkX, int a_ChunkZ);
|
||||
int GetHeight (int a_BlockX, int a_BlockZ); // Waits for the chunk to get loaded / generated
|
||||
bool TryGetHeight (int a_BlockX, int a_BlockZ, int & a_Height); // Returns false if chunk not loaded / generated
|
||||
void FastSetBlocks (sSetBlockList & a_BlockList);
|
||||
void CollectPickupsByPlayer(cPlayer * a_Player);
|
||||
|
||||
@ -169,25 +169,40 @@ public:
|
||||
void SendBlockTo(int a_X, int a_Y, int a_Z, cPlayer * a_Player);
|
||||
|
||||
/// Compares clients of two chunks, calls the callback accordingly
|
||||
void CompareChunkClients(int a_ChunkX1, int a_ChunkY1, int a_ChunkZ1, int a_ChunkX2, int a_ChunkY2, int a_ChunkZ2, cClientDiffCallback & a_Callback);
|
||||
void CompareChunkClients(int a_ChunkX1, int a_ChunkZ1, int a_ChunkX2, int a_ChunkZ2, cClientDiffCallback & a_Callback);
|
||||
|
||||
/// Compares clients of two chunks, calls the callback accordingly
|
||||
void CompareChunkClients(cChunk * a_Chunk1, cChunk * a_Chunk2, cClientDiffCallback & a_Callback);
|
||||
|
||||
/// Adds client to a chunk, if not already present; returns true if added, false if present
|
||||
bool AddChunkClient(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client);
|
||||
bool AddChunkClient(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client);
|
||||
|
||||
/// Removes the client from the chunk
|
||||
void RemoveChunkClient(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client);
|
||||
void RemoveChunkClient(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client);
|
||||
|
||||
/// Removes the client from all chunks it is present in
|
||||
void RemoveClientFromChunks(cClientHandle * a_Client);
|
||||
|
||||
/// Moves the entity from its current chunk to the new chunk specified
|
||||
void MoveEntityToChunk(cEntity * a_Entity, int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
||||
void MoveEntityToChunk(cEntity * a_Entity, int a_ChunkX, int a_ChunkZ);
|
||||
|
||||
/// Removes the entity from the chunk specified
|
||||
void RemoveEntityFromChunk(cEntity * a_Entity, int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
||||
void RemoveEntityFromChunk(cEntity * a_Entity, int a_ChunkX, int a_ChunkZ);
|
||||
|
||||
/// Adds the entity to its appropriate chunk, takes ownership of the entity pointer
|
||||
void AddEntity(cEntity * a_Entity);
|
||||
|
||||
/// Returns true if the entity with specified ID is present in the chunks
|
||||
bool HasEntity(int a_EntityID);
|
||||
|
||||
/// Calls the callback for each entity in the entire world; returns true if all entities processed, false if the callback aborted by returning true
|
||||
bool ForEachEntity(cEntityCallback & a_Callback); // Lua-accessible
|
||||
|
||||
/// Calls the callback for each entity in the specified chunk; returns true if all entities processed, false if the callback aborted by returning true
|
||||
bool ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback & a_Callback); // Lua-accessible
|
||||
|
||||
/// Calls the callback if the entity with the specified ID is found, with the entity object as the callback param. Returns true if entity found and callback returned false.
|
||||
bool DoWithEntityByID(int a_UniqueID, cEntityCallback & a_Callback); // Lua-accessible
|
||||
|
||||
/// Calls the callback for each chest in the specified chunk; returns true if all chests processed, false if the callback aborted by returning true
|
||||
bool ForEachChestInChunk (int a_ChunkX, int a_ChunkZ, cChestCallback & a_Callback); // Lua-accessible
|
||||
@ -253,12 +268,12 @@ public:
|
||||
/// Sets the blockticking to start at the specified block. Only one blocktick per chunk may be set, second call overwrites the first call
|
||||
void SetNextBlockTick(int a_BlockX, int a_BlockY, int a_BlockZ);
|
||||
|
||||
void Tick( float a_Dt, MTRand & a_TickRand );
|
||||
void Tick(float a_Dt);
|
||||
|
||||
void UnloadUnusedChunks();
|
||||
void SaveAllChunks();
|
||||
void UnloadUnusedChunks(void);
|
||||
void SaveAllChunks(void);
|
||||
|
||||
cWorld * GetWorld() { return m_World; }
|
||||
cWorld * GetWorld(void) { return m_World; }
|
||||
|
||||
int GetNumChunks(void);
|
||||
|
||||
@ -293,10 +308,19 @@ private:
|
||||
void Save(void);
|
||||
void UnloadUnusedChunks(void);
|
||||
|
||||
void Tick( float a_Dt, MTRand & a_TickRand );
|
||||
void Tick(float a_Dt);
|
||||
|
||||
void RemoveClient(cClientHandle * a_Client);
|
||||
|
||||
/// Calls the callback for each entity in the entire world; returns true if all entities processed, false if the callback aborted by returning true
|
||||
bool ForEachEntity(cEntityCallback & a_Callback); // Lua-accessible
|
||||
|
||||
/// Calls the callback if the entity with the specified ID is found, with the entity object as the callback param. Returns true if entity found.
|
||||
bool DoWithEntityByID(int a_EntityID, cEntityCallback & a_Callback, bool & a_CallbackReturn); // Lua-accessible
|
||||
|
||||
/// Returns true if there is an entity with the specified ID within this layer's chunks
|
||||
bool HasEntity(int a_EntityID);
|
||||
|
||||
protected:
|
||||
|
||||
cChunkPtr m_Chunks[LAYER_SIZE * LAYER_SIZE];
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
void cNotifyChunkSender::Call(int a_ChunkX, int a_ChunkZ)
|
||||
{
|
||||
m_ChunkSender->ChunkReady(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
|
||||
m_ChunkSender->ChunkReady(a_ChunkX, a_ChunkZ);
|
||||
}
|
||||
|
||||
|
||||
@ -76,12 +76,12 @@ void cChunkSender::Stop(void)
|
||||
|
||||
|
||||
|
||||
void cChunkSender::ChunkReady(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
|
||||
void cChunkSender::ChunkReady(int a_ChunkX, int a_ChunkZ)
|
||||
{
|
||||
// This is probably never gonna be called twice for the same chunk, and if it is, we don't mind, so we don't check
|
||||
{
|
||||
cCSLock Lock(m_CS);
|
||||
m_ChunksReady.push_back(cChunkCoords(a_ChunkX, a_ChunkY, a_ChunkZ));
|
||||
m_ChunksReady.push_back(cChunkCoords(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ));
|
||||
}
|
||||
m_evtQueue.Set();
|
||||
}
|
||||
@ -90,17 +90,17 @@ void cChunkSender::ChunkReady(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
|
||||
|
||||
|
||||
|
||||
void cChunkSender::QueueSendChunkTo(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client)
|
||||
void cChunkSender::QueueSendChunkTo(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client)
|
||||
{
|
||||
ASSERT(a_Client != NULL);
|
||||
{
|
||||
cCSLock Lock(m_CS);
|
||||
if (std::find(m_SendChunks.begin(), m_SendChunks.end(), sSendChunk(a_ChunkX, a_ChunkY, a_ChunkZ, a_Client)) != m_SendChunks.end())
|
||||
if (std::find(m_SendChunks.begin(), m_SendChunks.end(), sSendChunk(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ, a_Client)) != m_SendChunks.end())
|
||||
{
|
||||
// Already queued, bail out
|
||||
return;
|
||||
}
|
||||
m_SendChunks.push_back(sSendChunk(a_ChunkX, a_ChunkY, a_ChunkZ, a_Client));
|
||||
m_SendChunks.push_back(sSendChunk(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ, a_Client));
|
||||
}
|
||||
m_evtQueue.Set();
|
||||
}
|
||||
@ -200,13 +200,13 @@ void cChunkSender::SendChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHa
|
||||
}
|
||||
|
||||
// If the chunk has no clients, no need to packetize it:
|
||||
if (!m_World->HasChunkAnyClients(a_ChunkX, a_ChunkY, a_ChunkZ))
|
||||
if (!m_World->HasChunkAnyClients(a_ChunkX, a_ChunkZ))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// If the chunk is not valid, do nothing - whoever needs it has queued it for loading / generating
|
||||
if (!m_World->IsChunkValid(a_ChunkX, a_ChunkY, a_ChunkZ))
|
||||
if (!m_World->IsChunkValid(a_ChunkX, a_ChunkZ))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -219,7 +219,7 @@ void cChunkSender::SendChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHa
|
||||
}
|
||||
|
||||
// Query and prepare chunk data:
|
||||
if( !m_World->GetChunkData(a_ChunkX, a_ChunkY, a_ChunkZ, *this) )
|
||||
if (!m_World->GetChunkData(a_ChunkX, a_ChunkZ, *this))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -80,10 +80,10 @@ public:
|
||||
void Stop(void);
|
||||
|
||||
/// Notifies that a chunk has become ready and it should be sent to all its clients
|
||||
void ChunkReady(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
||||
void ChunkReady(int a_ChunkX, int a_ChunkZ);
|
||||
|
||||
/// Queues a chunk to be sent to a specific client
|
||||
void QueueSendChunkTo(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client);
|
||||
void QueueSendChunkTo(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client);
|
||||
|
||||
/// Removes the a_Client from all waiting chunk send operations
|
||||
void RemoveClient(cClientHandle * a_Client);
|
||||
|
@ -137,7 +137,10 @@ cClientHandle::~cClientHandle()
|
||||
if (World != NULL)
|
||||
{
|
||||
World->RemovePlayer(m_Player);
|
||||
m_Player->Destroy();
|
||||
}
|
||||
delete m_Player;
|
||||
m_Player = NULL;
|
||||
}
|
||||
|
||||
if (!m_HasSentDC)
|
||||
@ -145,12 +148,6 @@ cClientHandle::~cClientHandle()
|
||||
SendDisconnect("Server shut down? Kthnxbai");
|
||||
}
|
||||
|
||||
if (m_Player != NULL)
|
||||
{
|
||||
m_Player->Destroy();
|
||||
m_Player = NULL;
|
||||
}
|
||||
|
||||
// Queue all remaining outgoing packets to cSocketThreads:
|
||||
{
|
||||
cCSLock Lock(m_CSOutgoingData);
|
||||
@ -325,7 +322,7 @@ void cClientHandle::StreamChunks(void)
|
||||
}
|
||||
for (cChunkCoordsList::iterator itr = RemoveChunks.begin(); itr != RemoveChunks.end(); ++itr)
|
||||
{
|
||||
World->RemoveChunkClient(itr->m_ChunkX, itr->m_ChunkY, itr->m_ChunkZ, this);
|
||||
World->RemoveChunkClient(itr->m_ChunkX, itr->m_ChunkZ, this);
|
||||
m_Protocol->SendUnloadChunk(itr->m_ChunkX, itr->m_ChunkZ);
|
||||
} // for itr - RemoveChunks[]
|
||||
|
||||
@ -336,13 +333,13 @@ void cClientHandle::StreamChunks(void)
|
||||
// For each distance add chunks in a hollow square centered around current position:
|
||||
for (int i = -d; i <= d; ++i)
|
||||
{
|
||||
StreamChunk(ChunkPosX + d, ZERO_CHUNK_Y, ChunkPosZ + i);
|
||||
StreamChunk(ChunkPosX - d, ZERO_CHUNK_Y, ChunkPosZ + i);
|
||||
StreamChunk(ChunkPosX + d, ChunkPosZ + i);
|
||||
StreamChunk(ChunkPosX - d, ChunkPosZ + i);
|
||||
} // for i
|
||||
for (int i = -d + 1; i < d; ++i)
|
||||
{
|
||||
StreamChunk(ChunkPosX + i, ZERO_CHUNK_Y, ChunkPosZ + d);
|
||||
StreamChunk(ChunkPosX + i, ZERO_CHUNK_Y, ChunkPosZ - d);
|
||||
StreamChunk(ChunkPosX + i, ChunkPosZ + d);
|
||||
StreamChunk(ChunkPosX + i, ChunkPosZ - d);
|
||||
} // for i
|
||||
} // for d
|
||||
|
||||
@ -366,7 +363,7 @@ void cClientHandle::StreamChunks(void)
|
||||
|
||||
|
||||
|
||||
void cClientHandle::StreamChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
|
||||
void cClientHandle::StreamChunk(int a_ChunkX, int a_ChunkZ)
|
||||
{
|
||||
if (m_State >= csDestroying)
|
||||
{
|
||||
@ -377,14 +374,14 @@ void cClientHandle::StreamChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
|
||||
cWorld * World = m_Player->GetWorld();
|
||||
ASSERT(World != NULL);
|
||||
|
||||
if (World->AddChunkClient(a_ChunkX, a_ChunkY, a_ChunkZ, this))
|
||||
if (World->AddChunkClient(a_ChunkX, a_ChunkZ, this))
|
||||
{
|
||||
{
|
||||
cCSLock Lock(m_CSChunkLists);
|
||||
m_LoadedChunks.push_back(cChunkCoords(a_ChunkX, a_ChunkY, a_ChunkZ));
|
||||
m_ChunksToSend.push_back(cChunkCoords(a_ChunkX, a_ChunkY, a_ChunkZ));
|
||||
m_LoadedChunks.push_back(cChunkCoords(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ));
|
||||
m_ChunksToSend.push_back(cChunkCoords(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ));
|
||||
}
|
||||
World->SendChunkTo(a_ChunkX, a_ChunkY, a_ChunkZ, this);
|
||||
World->SendChunkTo(a_ChunkX, a_ChunkZ, this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1128,6 +1125,7 @@ void cClientHandle::HandleDisconnect(const AString & a_Reason)
|
||||
Printf(DisconnectMessage, "%s disconnected: %s", m_Username.c_str(), a_Reason.c_str());
|
||||
m_Player->GetWorld()->BroadcastChat(DisconnectMessage, this);
|
||||
}
|
||||
m_HasSentDC = true;
|
||||
Destroy();
|
||||
}
|
||||
|
||||
|
@ -209,7 +209,7 @@ private:
|
||||
|
||||
cPlayer * m_Player;
|
||||
|
||||
bool m_HasSentDC;
|
||||
bool m_HasSentDC; ///< True if a D/C packet has been sent in either direction
|
||||
|
||||
// Chunk position when the last StreamChunks() was called; used to avoid re-streaming while in the same chunk
|
||||
int m_LastStreamedChunkX;
|
||||
@ -267,7 +267,7 @@ private:
|
||||
void SendConfirmPosition(void);
|
||||
|
||||
/// Adds a single chunk to be streamed to the client; used by StreamChunks()
|
||||
void StreamChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
||||
void StreamChunk(int a_ChunkX, int a_ChunkZ);
|
||||
|
||||
/// Handles the DIG_STARTED dig packet:
|
||||
void HandleBlockDigStarted (int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_OldBlock, NIBBLETYPE a_OldMeta);
|
||||
|
@ -27,16 +27,13 @@ cEntity::cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z)
|
||||
, m_Attachee(NULL)
|
||||
, m_Referencers(new cReferenceManager(cReferenceManager::RFMNGR_REFERENCERS))
|
||||
, m_References(new cReferenceManager(cReferenceManager::RFMNGR_REFERENCES))
|
||||
, m_ChunkX(0)
|
||||
, m_ChunkY(0)
|
||||
, m_ChunkZ(0)
|
||||
, m_HeadYaw( 0.0 )
|
||||
, m_Pos(a_X, a_Y, a_Z)
|
||||
, m_bDirtyHead(true)
|
||||
, m_bDirtyOrientation(true)
|
||||
, m_bDirtyPosition(true)
|
||||
, m_bDirtySpeed(true)
|
||||
, m_bDestroyed(true)
|
||||
, m_IsInitialized(false)
|
||||
, m_LastPosX( 0.0 )
|
||||
, m_LastPosY( 0.0 )
|
||||
, m_LastPosZ( 0.0 )
|
||||
@ -45,7 +42,6 @@ cEntity::cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z)
|
||||
, m_TimeLastSpeedPacket(0)
|
||||
, m_EntityType(a_EntityType)
|
||||
, m_World(NULL)
|
||||
, m_bRemovedFromChunk(true)
|
||||
, m_FireDamageInterval(0.f)
|
||||
, m_BurnPeriod(0.f)
|
||||
{
|
||||
@ -60,6 +56,8 @@ cEntity::cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z)
|
||||
|
||||
cEntity::~cEntity()
|
||||
{
|
||||
ASSERT(!m_World->HasEntity(m_UniqueID)); // Before deleting, the entity needs to have been removed from the world
|
||||
|
||||
LOGD("Deleting entity %d at pos {%.2f, %.2f, %.2f} ~ [%d, %d]; ptr %p",
|
||||
m_UniqueID,
|
||||
m_Pos.x, m_Pos.y, m_Pos.z,
|
||||
@ -76,9 +74,9 @@ cEntity::~cEntity()
|
||||
m_Attachee->Detach();
|
||||
}
|
||||
|
||||
if (!m_bDestroyed || !m_bRemovedFromChunk)
|
||||
if (m_IsInitialized)
|
||||
{
|
||||
LOGERROR("ERROR: Entity deallocated without being destroyed %i or unlinked %i", m_bDestroyed, m_bRemovedFromChunk);
|
||||
LOGWARNING("ERROR: Entity deallocated without being destroyed");
|
||||
ASSERT(!"Entity deallocated without being destroyed or unlinked");
|
||||
}
|
||||
delete m_Referencers;
|
||||
@ -118,41 +116,43 @@ const char * cEntity::GetParentClass(void) const
|
||||
|
||||
void cEntity::Initialize(cWorld * a_World)
|
||||
{
|
||||
m_bDestroyed = false;
|
||||
m_bRemovedFromChunk = false;
|
||||
|
||||
LOGD("Initializing entity #%d (%s) at {%.02f, %.02f, %.02f}",
|
||||
m_UniqueID, GetClass(), m_Pos.x, m_Pos.y, m_Pos.z
|
||||
);
|
||||
m_IsInitialized = true;
|
||||
m_World = a_World;
|
||||
m_World->AddEntity(this);
|
||||
|
||||
MoveToCorrectChunk(true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cEntity::WrapHeadYaw()
|
||||
void cEntity::WrapHeadYaw(void)
|
||||
{
|
||||
while (m_HeadYaw > 180.f) m_HeadYaw -=360.f; // Wrap it
|
||||
while (m_HeadYaw < -180.f) m_HeadYaw +=360.f;
|
||||
while (m_HeadYaw > 180.f) m_HeadYaw -= 360.f; // Wrap it
|
||||
while (m_HeadYaw < -180.f) m_HeadYaw += 360.f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cEntity::WrapRotation()
|
||||
void cEntity::WrapRotation(void)
|
||||
{
|
||||
while (m_Rot.x > 180.f) m_Rot.x-=360.f; // Wrap it
|
||||
while (m_Rot.x < -180.f) m_Rot.x+=360.f;
|
||||
while (m_Rot.y > 180.f) m_Rot.y-=360.f;
|
||||
while (m_Rot.y < -180.f) m_Rot.y+=360.f;
|
||||
while (m_Rot.x > 180.f) m_Rot.x -= 360.f; // Wrap it
|
||||
while (m_Rot.x < -180.f) m_Rot.x += 360.f;
|
||||
while (m_Rot.y > 180.f) m_Rot.y -= 360.f;
|
||||
while (m_Rot.y < -180.f) m_Rot.y += 360.f;
|
||||
}
|
||||
|
||||
void cEntity::WrapSpeed()
|
||||
|
||||
|
||||
|
||||
void cEntity::WrapSpeed(void)
|
||||
{
|
||||
//There shoudn't be a need for flipping the flag on because this function is called
|
||||
//after any update, so the flag is already turned on
|
||||
// There shoudn't be a need for flipping the flag on because this function is called
|
||||
// after any update, so the flag is already turned on
|
||||
if (m_Speed.x > 20.0f) m_Speed.x = 20.0f;
|
||||
else if (m_Speed.x < -20.0f) m_Speed.x = -20.0f;
|
||||
if (m_Speed.y > 20.0f) m_Speed.y = 20.0f;
|
||||
@ -165,74 +165,15 @@ void cEntity::WrapSpeed()
|
||||
|
||||
|
||||
|
||||
void cEntity::MoveToCorrectChunk(bool a_bIgnoreOldChunk)
|
||||
void cEntity::Destroy(void)
|
||||
{
|
||||
if (!m_World)
|
||||
{
|
||||
// This is normal for entities being currently loaded
|
||||
return;
|
||||
}
|
||||
|
||||
int ChunkX = 0, ChunkY = 0, ChunkZ = 0;
|
||||
cWorld::BlockToChunk((int)m_Pos.x, (int)m_Pos.y, (int)m_Pos.z, ChunkX, ChunkY, ChunkZ);
|
||||
if (!a_bIgnoreOldChunk && (m_ChunkX == ChunkX) && (m_ChunkY == ChunkY) && (m_ChunkZ == ChunkZ))
|
||||
if (!m_IsInitialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
class cMover :
|
||||
public cClientDiffCallback
|
||||
{
|
||||
virtual void Removed(cClientHandle * a_Client) override
|
||||
{
|
||||
if (m_IgnoreOldChunk)
|
||||
{
|
||||
return;
|
||||
}
|
||||
a_Client->SendDestroyEntity(*m_Entity);
|
||||
}
|
||||
|
||||
virtual void Added(cClientHandle * a_Client) override
|
||||
{
|
||||
m_Entity->SpawnOn(*a_Client);
|
||||
}
|
||||
|
||||
bool m_IgnoreOldChunk;
|
||||
cEntity * m_Entity;
|
||||
|
||||
public:
|
||||
cMover(cEntity * a_Entity, bool a_IgnoreOldChunk) :
|
||||
m_IgnoreOldChunk(a_IgnoreOldChunk),
|
||||
m_Entity(a_Entity)
|
||||
{}
|
||||
} Mover(this, a_bIgnoreOldChunk);
|
||||
|
||||
m_World->CompareChunkClients(m_ChunkX, m_ChunkY, m_ChunkZ, ChunkX, ChunkY, ChunkZ, Mover);
|
||||
m_World->MoveEntityToChunk(this, ChunkX, ChunkY, ChunkZ);
|
||||
|
||||
m_ChunkX = ChunkX;
|
||||
m_ChunkY = ChunkY;
|
||||
m_ChunkZ = ChunkZ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cEntity::Destroy()
|
||||
{
|
||||
if (m_bDestroyed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!m_bRemovedFromChunk)
|
||||
{
|
||||
RemoveFromChunk();
|
||||
}
|
||||
|
||||
m_World->BroadcastDestroyEntity(*this);
|
||||
|
||||
m_bDestroyed = true;
|
||||
m_IsInitialized = false;
|
||||
|
||||
Destroyed();
|
||||
}
|
||||
@ -241,25 +182,8 @@ void cEntity::Destroy()
|
||||
|
||||
|
||||
|
||||
void cEntity::RemoveFromChunk(void)
|
||||
void cEntity::Tick(float a_Dt, cChunk & a_Chunk)
|
||||
{
|
||||
if (m_World == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_World->RemoveEntityFromChunk(this, m_ChunkX, m_ChunkY, m_ChunkZ);
|
||||
m_bRemovedFromChunk = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cEntity::Tick(float a_Dt, MTRand & a_TickRandom)
|
||||
{
|
||||
UNUSED(a_TickRandom);
|
||||
|
||||
if (m_AttachedTo != NULL)
|
||||
{
|
||||
if ((m_Pos - m_AttachedTo->GetPosition()).Length() > 0.5)
|
||||
@ -269,7 +193,7 @@ void cEntity::Tick(float a_Dt, MTRand & a_TickRandom)
|
||||
}
|
||||
else
|
||||
{
|
||||
HandlePhysics(a_Dt);
|
||||
HandlePhysics(a_Dt, a_Chunk);
|
||||
}
|
||||
}
|
||||
|
||||
@ -496,7 +420,6 @@ void cEntity::SetSpeedZ(double a_SpeedZ)
|
||||
void cEntity::AddPosX(double a_AddPosX)
|
||||
{
|
||||
m_Pos.x += a_AddPosX;
|
||||
MoveToCorrectChunk();
|
||||
m_bDirtyPosition = true;
|
||||
}
|
||||
|
||||
@ -506,7 +429,6 @@ void cEntity::AddPosX(double a_AddPosX)
|
||||
void cEntity::AddPosY(double a_AddPosY)
|
||||
{
|
||||
m_Pos.y += a_AddPosY;
|
||||
MoveToCorrectChunk();
|
||||
m_bDirtyPosition = true;
|
||||
}
|
||||
|
||||
@ -516,7 +438,6 @@ void cEntity::AddPosY(double a_AddPosY)
|
||||
void cEntity::AddPosZ(double a_AddPosZ)
|
||||
{
|
||||
m_Pos.z += a_AddPosZ;
|
||||
MoveToCorrectChunk();
|
||||
m_bDirtyPosition = true;
|
||||
}
|
||||
|
||||
@ -528,7 +449,6 @@ void cEntity::AddPosition(double a_AddPosX, double a_AddPosY, double a_AddPosZ)
|
||||
m_Pos.x += a_AddPosX;
|
||||
m_Pos.y += a_AddPosY;
|
||||
m_Pos.z += a_AddPosZ;
|
||||
MoveToCorrectChunk();
|
||||
m_bDirtyPosition = true;
|
||||
}
|
||||
|
||||
@ -600,7 +520,6 @@ Vector3d cEntity::GetLookVector(void) const
|
||||
void cEntity::SetPosition(double a_PosX, double a_PosY, double a_PosZ)
|
||||
{
|
||||
m_Pos.Set(a_PosX, a_PosY, a_PosZ);
|
||||
MoveToCorrectChunk();
|
||||
m_bDirtyPosition = true;
|
||||
}
|
||||
|
||||
@ -611,7 +530,6 @@ void cEntity::SetPosition(double a_PosX, double a_PosY, double a_PosZ)
|
||||
void cEntity::SetPosX(double a_PosX)
|
||||
{
|
||||
m_Pos.x = a_PosX;
|
||||
MoveToCorrectChunk();
|
||||
m_bDirtyPosition = true;
|
||||
}
|
||||
|
||||
@ -622,7 +540,6 @@ void cEntity::SetPosX(double a_PosX)
|
||||
void cEntity::SetPosY(double a_PosY)
|
||||
{
|
||||
m_Pos.y = a_PosY;
|
||||
MoveToCorrectChunk();
|
||||
m_bDirtyPosition = true;
|
||||
}
|
||||
|
||||
@ -633,7 +550,6 @@ void cEntity::SetPosY(double a_PosY)
|
||||
void cEntity::SetPosZ(double a_PosZ)
|
||||
{
|
||||
m_Pos.z = a_PosZ;
|
||||
MoveToCorrectChunk();
|
||||
m_bDirtyPosition = true;
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,7 @@ class cWorld;
|
||||
class cReferenceManager;
|
||||
class cClientHandle;
|
||||
class cPlayer;
|
||||
class MTRand;
|
||||
class cChunk;
|
||||
|
||||
|
||||
|
||||
@ -120,9 +120,8 @@ public:
|
||||
double GetSpeedY (void) const { return m_Speed.y; }
|
||||
double GetSpeedZ (void) const { return m_Speed.z; }
|
||||
|
||||
int GetChunkX(void) const {return m_ChunkX; }
|
||||
int GetChunkY(void) const {return m_ChunkY; }
|
||||
int GetChunkZ(void) const {return m_ChunkZ; }
|
||||
int GetChunkX(void) const {return FAST_FLOOR_DIV(((int)m_Pos.x), cChunkDef::Width); }
|
||||
int GetChunkZ(void) const {return FAST_FLOOR_DIV(((int)m_Pos.z), cChunkDef::Width); }
|
||||
|
||||
void SetHeadYaw (double a_HeadYaw);
|
||||
void SetPosX (double a_PosX);
|
||||
@ -135,7 +134,7 @@ public:
|
||||
void SetPitch (double a_Pitch);
|
||||
void SetRoll (double a_Roll);
|
||||
void SetSpeed (double a_SpeedX, double a_SpeedY, double a_SpeedZ);
|
||||
void SetSpeed (const Vector3d & a_Speed) { SetSpeed(a_Speed.x,a_Speed.y,a_Speed.z); }
|
||||
void SetSpeed (const Vector3d & a_Speed) { SetSpeed(a_Speed.x, a_Speed.y, a_Speed.z); }
|
||||
void SetSpeedX (double a_SpeedX);
|
||||
void SetSpeedY (double a_SpeedY);
|
||||
void SetSpeedZ (double a_SpeedZ);
|
||||
@ -151,16 +150,15 @@ public:
|
||||
void AddSpeedY (double a_AddSpeedY);
|
||||
void AddSpeedZ (double a_AddSpeedZ);
|
||||
|
||||
inline int GetUniqueID(void) const { return m_UniqueID; }
|
||||
inline bool IsDestroyed(void) const { return !m_IsInitialized; }
|
||||
|
||||
void Destroy(void);
|
||||
|
||||
// tolua_end
|
||||
|
||||
inline int GetUniqueID(void) const { return m_UniqueID; } // tolua_export
|
||||
inline bool IsDestroyed(void) const { return m_bDestroyed; } // tolua_export
|
||||
|
||||
void Destroy(); // tolua_export
|
||||
void RemoveFromChunk(void); // for internal use in cChunk
|
||||
|
||||
virtual void Tick(float a_Dt, MTRand & a_TickRandom);
|
||||
virtual void HandlePhysics(float a_Dt) {}
|
||||
virtual void Tick(float a_Dt, cChunk & a_Chunk);
|
||||
virtual void HandlePhysics(float a_Dt, cChunk & a_Chunk) {}
|
||||
|
||||
/** Descendants override this function to send a command to the specified client to spawn the entity on the client.
|
||||
To spawn on all eligible clients, use cChunkMap::BroadcastSpawnEntity()
|
||||
@ -215,22 +213,19 @@ protected:
|
||||
cReferenceManager* m_Referencers;
|
||||
cReferenceManager* m_References;
|
||||
|
||||
int m_ChunkX, m_ChunkY, m_ChunkZ;
|
||||
|
||||
//Flags that signal that we haven't updated the clients with the latest.
|
||||
// Flags that signal that we haven't updated the clients with the latest.
|
||||
bool m_bDirtyHead;
|
||||
bool m_bDirtyOrientation;
|
||||
bool m_bDirtyPosition;
|
||||
bool m_bDirtySpeed;
|
||||
|
||||
//Last Position.
|
||||
// Last Position.
|
||||
double m_LastPosX, m_LastPosY, m_LastPosZ;
|
||||
|
||||
//This variables keep track of the last time a packet was sent
|
||||
// This variables keep track of the last time a packet was sent
|
||||
Int64 m_TimeLastTeleportPacket,m_TimeLastMoveReltPacket,m_TimeLastSpeedPacket; // In ticks
|
||||
|
||||
bool m_bDestroyed;
|
||||
bool m_bRemovedFromChunk;
|
||||
bool m_IsInitialized; // Is set to true when it's initialized, until it's destroyed (Initialize() till Destroy() )
|
||||
|
||||
eEntityType m_EntityType;
|
||||
|
||||
@ -242,8 +237,7 @@ protected:
|
||||
virtual void Destroyed(void) {} // Called after the entity has been destroyed
|
||||
|
||||
void SetWorld(cWorld * a_World) { m_World = a_World; }
|
||||
void MoveToCorrectChunk(bool a_bIgnoreOldChunk = false);
|
||||
|
||||
|
||||
friend class cReferenceManager;
|
||||
void AddReference( cEntity*& a_EntityPtr );
|
||||
void ReferencedBy( cEntity*& a_EntityPtr );
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "World.h"
|
||||
#include "ClientHandle.h"
|
||||
#include "Simulator/SandSimulator.h"
|
||||
#include "Chunk.h"
|
||||
|
||||
|
||||
|
||||
@ -40,7 +41,7 @@ void cFallingBlock::SpawnOn(cClientHandle & a_ClientHandle)
|
||||
|
||||
|
||||
|
||||
void cFallingBlock::Tick(float a_Dt, MTRand & a_TickRandom)
|
||||
void cFallingBlock::Tick(float a_Dt, cChunk & a_Chunk)
|
||||
{
|
||||
float MilliDt = a_Dt * 0.001f;
|
||||
AddSpeedY(MilliDt * -9.8f);
|
||||
@ -62,26 +63,29 @@ void cFallingBlock::Tick(float a_Dt, MTRand & a_TickRandom)
|
||||
return;
|
||||
}
|
||||
|
||||
if (BlockY < cChunkDef::Height - 1)
|
||||
if (BlockY >= cChunkDef::Height)
|
||||
{
|
||||
BLOCKTYPE BlockBelow;
|
||||
NIBBLETYPE BelowMeta;
|
||||
GetWorld()->GetBlockTypeMeta(BlockX, BlockY, BlockZ, BlockBelow, BelowMeta);
|
||||
if (cSandSimulator::DoesBreakFallingThrough(BlockBelow, BelowMeta))
|
||||
{
|
||||
// Fallen onto a block that breaks this into pickups (e. g. half-slab)
|
||||
// Must finish the fall with coords one below the block:
|
||||
cSandSimulator::FinishFalling(m_World, BlockX, BlockY, BlockZ, m_BlockType, m_BlockMeta);
|
||||
Destroy();
|
||||
return;
|
||||
}
|
||||
else if (!cSandSimulator::CanContinueFallThrough(BlockBelow))
|
||||
{
|
||||
// Fallen onto a solid block
|
||||
cSandSimulator::FinishFalling(m_World, BlockX, BlockY + 1, BlockZ, m_BlockType, m_BlockMeta);
|
||||
Destroy();
|
||||
return;
|
||||
}
|
||||
// Above the world, just wait for it to fall back down
|
||||
return;
|
||||
}
|
||||
|
||||
int idx = a_Chunk.MakeIndexNoCheck(BlockX - a_Chunk.GetPosX() * cChunkDef::Width, BlockY, BlockZ - a_Chunk.GetPosZ() * cChunkDef::Width);
|
||||
BLOCKTYPE BlockBelow = a_Chunk.GetBlock(idx);
|
||||
NIBBLETYPE BelowMeta = a_Chunk.GetMeta(idx);
|
||||
if (cSandSimulator::DoesBreakFallingThrough(BlockBelow, BelowMeta))
|
||||
{
|
||||
// Fallen onto a block that breaks this into pickups (e. g. half-slab)
|
||||
// Must finish the fall with coords one below the block:
|
||||
cSandSimulator::FinishFalling(m_World, BlockX, BlockY, BlockZ, m_BlockType, m_BlockMeta);
|
||||
Destroy();
|
||||
return;
|
||||
}
|
||||
else if (!cSandSimulator::CanContinueFallThrough(BlockBelow))
|
||||
{
|
||||
// Fallen onto a solid block
|
||||
cSandSimulator::FinishFalling(m_World, BlockX, BlockY + 1, BlockZ, m_BlockType, m_BlockMeta);
|
||||
Destroy();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ public:
|
||||
// cEntity overrides:
|
||||
virtual void Initialize(cWorld * a_World) override;
|
||||
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
|
||||
virtual void Tick(float a_Dt, MTRand & a_TickRandom) override;
|
||||
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
|
||||
|
||||
private:
|
||||
BLOCKTYPE m_BlockType;
|
||||
|
@ -238,16 +238,16 @@ void cChunkGenerator::Execute(void)
|
||||
}
|
||||
|
||||
// Hack for regenerating chunks: if Y != 0, the chunk is considered invalid, even if it has its data set
|
||||
if ((coords.m_ChunkY == 0) && m_World->IsChunkValid(coords.m_ChunkX, coords.m_ChunkY, coords.m_ChunkZ))
|
||||
if ((coords.m_ChunkY == 0) && m_World->IsChunkValid(coords.m_ChunkX, coords.m_ChunkZ))
|
||||
{
|
||||
LOGD("Chunk [%d, %d] already generated, skipping generation", coords.m_ChunkX, coords.m_ChunkZ);
|
||||
// Already generated, ignore request
|
||||
continue;
|
||||
}
|
||||
|
||||
if (SkipEnabled && !m_World->HasChunkAnyClients(coords.m_ChunkX, coords.m_ChunkY, coords.m_ChunkZ))
|
||||
if (SkipEnabled && !m_World->HasChunkAnyClients(coords.m_ChunkX, coords.m_ChunkZ))
|
||||
{
|
||||
LOGWARNING("Chunk generator overloaded, skipping chunk [%d, %d, %d]", coords.m_ChunkX, coords.m_ChunkY, coords.m_ChunkZ);
|
||||
LOGWARNING("Chunk generator overloaded, skipping chunk [%d, %d]", coords.m_ChunkX, coords.m_ChunkZ);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -275,7 +275,7 @@ void cChunkGenerator::DoGenerate(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
|
||||
ChunkDesc.CompressBlockMetas(BlockMetas);
|
||||
|
||||
m_World->SetChunkData(
|
||||
a_ChunkX, a_ChunkY, a_ChunkZ,
|
||||
a_ChunkX, a_ChunkZ,
|
||||
ChunkDesc.GetBlockTypes(), BlockMetas,
|
||||
NULL, NULL, // We don't have lighting, chunk will be lighted when needed
|
||||
&ChunkDesc.GetHeightMap(), &ChunkDesc.GetBiomeMap(),
|
||||
|
@ -338,7 +338,7 @@ bool cLightingThread::ReadChunks(int a_ChunkX, int a_ChunkZ)
|
||||
for (int x = 0; x < 3; x++)
|
||||
{
|
||||
Reader.m_ReadingChunkX = x;
|
||||
if (!m_World->GetChunkData(a_ChunkX + x - 1, ZERO_CHUNK_Y, a_ChunkZ + z - 1, Reader))
|
||||
if (!m_World->GetChunkData(a_ChunkX + x - 1, a_ChunkZ + z - 1, Reader))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ void cMinecart::SpawnOn(cClientHandle & a_ClientHandle)
|
||||
|
||||
|
||||
|
||||
void cMinecart::Tick(float a_Dt, MTRand & a_TickRandom)
|
||||
void cMinecart::Tick(float a_Dt, cChunk & a_Chunk)
|
||||
{
|
||||
// TODO: the physics
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ public:
|
||||
// cEntity overrides:
|
||||
virtual void Initialize(cWorld * a_World) override;
|
||||
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
|
||||
virtual void Tick(float a_Dt, MTRand & a_TickRandom) override;
|
||||
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
|
||||
|
||||
ePayload GetPayload(void) const { return m_Payload; }
|
||||
|
||||
|
@ -23,9 +23,9 @@ cAggressiveMonster::cAggressiveMonster(const AString & a_ConfigName, char a_Prot
|
||||
|
||||
|
||||
// What to do if in Chasing State
|
||||
void cAggressiveMonster::InStateChasing(float a_Dt, MTRand & a_TickRandom)
|
||||
void cAggressiveMonster::InStateChasing(float a_Dt)
|
||||
{
|
||||
super::InStateChasing(a_Dt, a_TickRandom);
|
||||
super::InStateChasing(a_Dt);
|
||||
m_ChaseTime += a_Dt;
|
||||
if (m_Target != NULL)
|
||||
{
|
||||
@ -58,9 +58,9 @@ void cAggressiveMonster::InStateChasing(float a_Dt, MTRand & a_TickRandom)
|
||||
|
||||
|
||||
|
||||
void cAggressiveMonster::EventSeePlayer(cEntity * a_Entity, MTRand & a_TickRandom)
|
||||
void cAggressiveMonster::EventSeePlayer(cEntity * a_Entity)
|
||||
{
|
||||
super::EventSeePlayer(a_Entity, a_TickRandom);
|
||||
super::EventSeePlayer(a_Entity);
|
||||
m_EMState = CHASING;
|
||||
}
|
||||
|
||||
@ -68,26 +68,26 @@ void cAggressiveMonster::EventSeePlayer(cEntity * a_Entity, MTRand & a_TickRando
|
||||
|
||||
|
||||
|
||||
void cAggressiveMonster::Tick(float a_Dt, MTRand & a_TickRandom)
|
||||
void cAggressiveMonster::Tick(float a_Dt, cChunk & a_Chunk)
|
||||
{
|
||||
super::Tick(a_Dt, a_TickRandom);
|
||||
super::Tick(a_Dt, a_Chunk);
|
||||
|
||||
m_SeePlayerInterval += a_Dt;
|
||||
|
||||
if (m_SeePlayerInterval > 1)
|
||||
{
|
||||
int rem = a_TickRandom.randInt() % 3 + 1; // Check most of the time but miss occasionally
|
||||
int rem = m_World->GetTickRandomNumber(3) + 1; // Check most of the time but miss occasionally
|
||||
|
||||
m_SeePlayerInterval = 0.0;
|
||||
if (rem >= 2)
|
||||
{
|
||||
if (m_EMState == CHASING)
|
||||
{
|
||||
CheckEventLostPlayer(a_TickRandom);
|
||||
CheckEventLostPlayer();
|
||||
}
|
||||
else
|
||||
{
|
||||
CheckEventSeePlayer(a_TickRandom);
|
||||
CheckEventSeePlayer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,10 +15,10 @@ class cAggressiveMonster :
|
||||
public:
|
||||
cAggressiveMonster(const AString & a_ConfigName, char a_ProtocolMobType, const AString & a_SoundHurt, const AString & a_SoundDeath);
|
||||
|
||||
virtual void Tick (float a_Dt, MTRand & a_TickRandom) override;
|
||||
virtual void InStateChasing(float a_Dt, MTRand & a_TickRandom) override;
|
||||
virtual void Tick (float a_Dt, cChunk & a_Chunk) override;
|
||||
virtual void InStateChasing(float a_Dt) override;
|
||||
|
||||
virtual void EventSeePlayer(cEntity *, MTRand & a_TickRandom) override;
|
||||
virtual void EventSeePlayer(cEntity *) override;
|
||||
|
||||
protected:
|
||||
float m_ChaseTime;
|
||||
|
@ -16,11 +16,11 @@ cCavespider::cCavespider(void) :
|
||||
|
||||
|
||||
|
||||
void cCavespider::Tick(float a_Dt, MTRand & a_TickRandom)
|
||||
void cCavespider::Tick(float a_Dt, cChunk & a_Chunk)
|
||||
{
|
||||
super::Tick(a_Dt, a_TickRandom);
|
||||
super::Tick(a_Dt, a_Chunk);
|
||||
|
||||
// TODO: Check vanilla if cavespiders really get passive during the day
|
||||
// TODO: Check vanilla if cavespiders really get passive during the day / in daylight
|
||||
m_EMPersonality = (GetWorld()->GetTimeOfDay() < (12000 + 1000)) ? PASSIVE : AGGRESSIVE;
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ public:
|
||||
|
||||
CLASS_PROTODEF(cCaveSpider);
|
||||
|
||||
virtual void Tick(float a_Dt, MTRand & a_TickRandom) override;
|
||||
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
|
||||
virtual void GetDrops(cItems & a_Drops, cPawn * a_Killer = NULL) override;
|
||||
} ;
|
||||
|
||||
|
@ -16,21 +16,6 @@ cEnderman::cEnderman(void) :
|
||||
|
||||
|
||||
|
||||
void cEnderman::Tick(float a_Dt, MTRand & a_TickRandom)
|
||||
{
|
||||
cMonster::Tick(a_Dt, a_TickRandom);
|
||||
|
||||
// TODO Same as stated in cSkeleton
|
||||
if ((GetWorld()->GetTimeOfDay() < (12000 + 1000)) && (GetMetaData() != BURNING))
|
||||
{
|
||||
SetMetaData(BURNING); // BURN, BABY, BURN! >:D
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cEnderman::GetDrops(cItems & a_Drops, cPawn * a_Killer)
|
||||
{
|
||||
AddRandomDropItem(a_Drops, 0, 1, E_ITEM_ENDER_PEARL);
|
||||
|
@ -17,7 +17,6 @@ public:
|
||||
|
||||
CLASS_PROTODEF(cEnderman);
|
||||
|
||||
virtual void Tick(float a_Dt, MTRand & a_TickRandom) override;
|
||||
virtual void GetDrops(cItems & a_Drops, cPawn * a_Killer = NULL) override;
|
||||
} ;
|
||||
|
||||
|
@ -87,9 +87,9 @@ bool cMonster::ReachedDestination()
|
||||
|
||||
|
||||
|
||||
void cMonster::Tick(float a_Dt, MTRand & a_TickRandom)
|
||||
void cMonster::Tick(float a_Dt, cChunk & a_Chunk)
|
||||
{
|
||||
super::Tick(a_Dt, a_TickRandom);
|
||||
super::Tick(a_Dt, a_Chunk);
|
||||
|
||||
if (m_Health <= 0)
|
||||
{
|
||||
@ -145,7 +145,6 @@ void cMonster::Tick(float a_Dt, MTRand & a_TickRandom)
|
||||
|
||||
HandlePhysics(a_Dt);
|
||||
BroadcastMovementUpdate();
|
||||
MoveToCorrectChunk();
|
||||
|
||||
Vector3d Distance = m_Destination - GetPosition();
|
||||
if (Distance.SqrLength() > 0.1f)
|
||||
@ -163,20 +162,20 @@ void cMonster::Tick(float a_Dt, MTRand & a_TickRandom)
|
||||
case IDLE:
|
||||
{
|
||||
// If enemy passive we ignore checks for player visibility
|
||||
InStateIdle(a_Dt, a_TickRandom);
|
||||
InStateIdle(a_Dt);
|
||||
break;
|
||||
}
|
||||
|
||||
case CHASING:
|
||||
{
|
||||
// If we do not see a player anymore skip chasing action
|
||||
InStateChasing(a_Dt, a_TickRandom);
|
||||
InStateChasing(a_Dt);
|
||||
break;
|
||||
}
|
||||
|
||||
case ESCAPING:
|
||||
{
|
||||
InStateEscaping(a_Dt, a_TickRandom);
|
||||
InStateEscaping(a_Dt);
|
||||
break;
|
||||
}
|
||||
} // switch (m_EMState)
|
||||
@ -227,8 +226,6 @@ void cMonster::ReplicateMovement()
|
||||
m_LastPosZ = GetPosZ();
|
||||
m_bDirtyPosition = false;
|
||||
}
|
||||
|
||||
MoveToCorrectChunk();
|
||||
}
|
||||
|
||||
|
||||
@ -374,14 +371,14 @@ void cMonster::SetState(const AString & a_State)
|
||||
|
||||
//Checks to see if EventSeePlayer should be fired
|
||||
//monster sez: Do I see the player
|
||||
void cMonster::CheckEventSeePlayer(MTRand & a_TickRandom)
|
||||
void cMonster::CheckEventSeePlayer(void)
|
||||
{
|
||||
// TODO: Rewrite this to use cWorld's DoWithPlayers()
|
||||
cPlayer * Closest = FindClosestPlayer();
|
||||
|
||||
if (Closest != NULL)
|
||||
{
|
||||
EventSeePlayer(Closest, a_TickRandom);
|
||||
EventSeePlayer(Closest);
|
||||
}
|
||||
}
|
||||
|
||||
@ -389,10 +386,8 @@ void cMonster::CheckEventSeePlayer(MTRand & a_TickRandom)
|
||||
|
||||
|
||||
|
||||
void cMonster::CheckEventLostPlayer(MTRand & a_TickRandom)
|
||||
void cMonster::CheckEventLostPlayer(void)
|
||||
{
|
||||
UNUSED(a_TickRandom);
|
||||
|
||||
Vector3f pos;
|
||||
cTracer LineOfSight(GetWorld());
|
||||
|
||||
@ -416,12 +411,10 @@ void cMonster::CheckEventLostPlayer(MTRand & a_TickRandom)
|
||||
|
||||
// What to do if player is seen
|
||||
// default to change state to chasing
|
||||
void cMonster::EventSeePlayer(cEntity * a_SeenPlayer, MTRand & a_TickRandom)
|
||||
void cMonster::EventSeePlayer(cEntity * a_SeenPlayer)
|
||||
{
|
||||
UNUSED(a_TickRandom);
|
||||
|
||||
m_Target = a_SeenPlayer;
|
||||
AddReference( m_Target );
|
||||
AddReference(m_Target);
|
||||
}
|
||||
|
||||
|
||||
@ -431,7 +424,7 @@ void cMonster::EventSeePlayer(cEntity * a_SeenPlayer, MTRand & a_TickRandom)
|
||||
void cMonster::EventLosePlayer(void)
|
||||
{
|
||||
Dereference(m_Target);
|
||||
m_Target = 0;
|
||||
m_Target = NULL;
|
||||
m_EMState = IDLE;
|
||||
}
|
||||
|
||||
@ -440,24 +433,28 @@ void cMonster::EventLosePlayer(void)
|
||||
|
||||
|
||||
// What to do if in Idle State
|
||||
void cMonster::InStateIdle(float a_Dt, MTRand & a_TickRandom)
|
||||
void cMonster::InStateIdle(float a_Dt)
|
||||
{
|
||||
idle_interval += a_Dt;
|
||||
if (idle_interval > 1)
|
||||
{
|
||||
// at this interval the results are predictable
|
||||
int rem = (a_TickRandom.randInt() % 6) + 1;
|
||||
int rem = m_World->GetTickRandomNumber(6) + 1;
|
||||
// LOGD("Moving: int: %3.3f rem: %i",idle_interval,rem);
|
||||
idle_interval -= 1; // So nothing gets dropped when the server hangs for a few seconds
|
||||
Vector3f Dist;
|
||||
Dist.x = (float)((a_TickRandom.randInt() % 11) - 5);
|
||||
Dist.z = (float)((a_TickRandom.randInt() % 11) - 5);
|
||||
Dist.x = (float)(m_World->GetTickRandomNumber(10) - 5);
|
||||
Dist.z = (float)(m_World->GetTickRandomNumber(10) - 5);
|
||||
if ((Dist.SqrLength() > 2) && (rem >= 3))
|
||||
{
|
||||
m_Destination.x = (float)(GetPosX() + Dist.x);
|
||||
m_Destination.z = (float)(GetPosZ() + Dist.z);
|
||||
m_Destination.y = (float)GetWorld()->GetHeight((int)m_Destination.x, (int)m_Destination.z) + 1.2f;
|
||||
MoveToPosition(m_Destination);
|
||||
int PosY;
|
||||
if (m_World->TryGetHeight((int)m_Destination.x, (int)m_Destination.z, PosY))
|
||||
{
|
||||
m_Destination.y = (float)PosY + 1.2f;
|
||||
MoveToPosition(m_Destination);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -468,10 +465,9 @@ void cMonster::InStateIdle(float a_Dt, MTRand & a_TickRandom)
|
||||
|
||||
// What to do if in Chasing State
|
||||
// This state should always be defined in each child class
|
||||
void cMonster::InStateChasing(float a_Dt, MTRand & a_TickRandom)
|
||||
void cMonster::InStateChasing(float a_Dt)
|
||||
{
|
||||
UNUSED(a_Dt);
|
||||
UNUSED(a_TickRandom);
|
||||
}
|
||||
|
||||
|
||||
@ -479,10 +475,9 @@ void cMonster::InStateChasing(float a_Dt, MTRand & a_TickRandom)
|
||||
|
||||
|
||||
// What to do if in Escaping State
|
||||
void cMonster::InStateEscaping(float a_Dt, MTRand & a_TickRandom)
|
||||
void cMonster::InStateEscaping(float a_Dt)
|
||||
{
|
||||
UNUSED(a_Dt);
|
||||
UNUSED(a_TickRandom);
|
||||
|
||||
if (m_Target != NULL)
|
||||
{
|
||||
|
@ -24,6 +24,7 @@ class cMonster :
|
||||
typedef cPawn super;
|
||||
public:
|
||||
// tolua_end
|
||||
float m_SightDistance;
|
||||
|
||||
/** Creates the mob object.
|
||||
* If a_ConfigName is not empty, the configuration is loaded using GetMonsterConfig()
|
||||
@ -36,7 +37,7 @@ public:
|
||||
|
||||
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
|
||||
|
||||
virtual void Tick(float a_Dt, MTRand & a_TickRandom) override;
|
||||
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
|
||||
|
||||
virtual void HandlePhysics(float a_Dt);
|
||||
virtual void ReplicateMovement(void);
|
||||
@ -53,20 +54,19 @@ public:
|
||||
const char * GetState();
|
||||
void SetState(const AString & str);
|
||||
|
||||
virtual void CheckEventSeePlayer(MTRand & a_TickRandom);
|
||||
virtual void EventSeePlayer(cEntity *, MTRand & a_TickRandom);
|
||||
float m_SightDistance;
|
||||
virtual void CheckEventSeePlayer(void);
|
||||
virtual void EventSeePlayer(cEntity * a_Player);
|
||||
virtual cPlayer * FindClosestPlayer(); // non static is easier. also virtual so other mobs can implement their own searching algo
|
||||
|
||||
/// Reads the monster configuration for the specified monster name and assigns it to this object.
|
||||
void GetMonsterConfig(const AString & a_Name);
|
||||
|
||||
virtual void EventLosePlayer(void);
|
||||
virtual void CheckEventLostPlayer(MTRand & a_TickRandom);
|
||||
virtual void CheckEventLostPlayer(void);
|
||||
|
||||
virtual void InStateIdle (float a_Dt, MTRand & a_TickRandom);
|
||||
virtual void InStateChasing (float a_Dt, MTRand & a_TickRandom);
|
||||
virtual void InStateEscaping(float a_Dt, MTRand & a_TickRandom);
|
||||
virtual void InStateIdle (float a_Dt);
|
||||
virtual void InStateChasing (float a_Dt);
|
||||
virtual void InStateEscaping(float a_Dt);
|
||||
|
||||
virtual void Attack(float a_Dt);
|
||||
int GetMobType() {return m_MobType;}
|
||||
|
@ -31,22 +31,22 @@ void cPassiveMonster::DoTakeDamage(TakeDamageInfo & a_TDI)
|
||||
|
||||
|
||||
|
||||
void cPassiveMonster::Tick(float a_Dt, MTRand & a_TickRandom)
|
||||
void cPassiveMonster::Tick(float a_Dt, cChunk & a_Chunk)
|
||||
{
|
||||
super::Tick(a_Dt, a_TickRandom);
|
||||
super::Tick(a_Dt, a_Chunk);
|
||||
|
||||
m_SeePlayerInterval += a_Dt;
|
||||
|
||||
if (m_SeePlayerInterval > 1) // Check every second
|
||||
{
|
||||
int rem = a_TickRandom.randInt() % 3 + 1; // Check most of the time but miss occasionally
|
||||
int rem = m_World->GetTickRandomNumber(3) + 1; // Check most of the time but miss occasionally
|
||||
|
||||
m_SeePlayerInterval = 0.0;
|
||||
if (rem >= 2)
|
||||
{
|
||||
if (m_EMState == ESCAPING)
|
||||
{
|
||||
CheckEventLostPlayer(a_TickRandom);
|
||||
CheckEventLostPlayer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ class cPassiveMonster :
|
||||
public:
|
||||
cPassiveMonster(const AString & a_ConfigName, char a_ProtocolMobType, const AString & a_SoundHurt, const AString & a_SoundDeath);
|
||||
|
||||
virtual void Tick(float a_Dt, MTRand & a_TickRandom) override;
|
||||
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
|
||||
|
||||
/// When hit by someone, run away
|
||||
virtual void DoTakeDamage(TakeDamageInfo & a_TDI) override;
|
||||
|
@ -16,13 +16,13 @@ cSkeleton::cSkeleton(void) :
|
||||
|
||||
|
||||
|
||||
void cSkeleton::Tick(float a_Dt, MTRand & a_TickRandom)
|
||||
void cSkeleton::Tick(float a_Dt, cChunk & a_Chunk)
|
||||
{
|
||||
cMonster::Tick(a_Dt, a_TickRandom);
|
||||
cMonster::Tick(a_Dt, a_Chunk);
|
||||
|
||||
// TODO Outsource
|
||||
// TODO should do SkyLight check, mobs in the dark don´t burn
|
||||
if ((GetWorld()->GetTimeOfDay() < (12000 + 1000)) && (GetMetaData() != BURNING))
|
||||
if ((GetWorld()->GetTimeOfDay() < (12000 + 1000)) && !IsBurning())
|
||||
{
|
||||
SetMetaData(BURNING); // BURN, BABY, BURN! >:D
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ public:
|
||||
|
||||
CLASS_PROTODEF(cSkeleton);
|
||||
|
||||
virtual void Tick(float a_Dt, MTRand & a_TickRandom) override;
|
||||
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
|
||||
virtual void GetDrops(cItems & a_Drops, cPawn * a_Killer = NULL) override;
|
||||
} ;
|
||||
|
||||
|
@ -27,14 +27,15 @@ void cSquid::GetDrops(cItems & a_Drops, cPawn * a_Killer)
|
||||
|
||||
|
||||
|
||||
void cSquid::Tick(float a_Dt, MTRand & a_TickRandom)
|
||||
void cSquid::Tick(float a_Dt, cChunk & a_Chunk)
|
||||
{
|
||||
super::Tick(a_Dt, a_TickRandom);
|
||||
// TODO: Rewrite this function to use a_Chunk instead of m_World
|
||||
super::Tick(a_Dt, a_Chunk);
|
||||
|
||||
Vector3d Pos = GetPosition();
|
||||
|
||||
// TODO: Not a real behavior, but cool :D
|
||||
if (!IsBlockWater(GetWorld()->GetBlock((int) Pos.x, (int) Pos.y, (int) Pos.z)) && GetMetaData() != BURNING)
|
||||
if (!IsBlockWater(GetWorld()->GetBlock((int) Pos.x, (int) Pos.y, (int) Pos.z)) && !IsBurning())
|
||||
{
|
||||
SetMetaData(BURNING);
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ class cSquid :
|
||||
public:
|
||||
cSquid();
|
||||
|
||||
virtual void Tick(float a_Dt, MTRand & a_TickRandom) override;
|
||||
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
|
||||
|
||||
CLASS_PROTODEF(cSquid);
|
||||
|
||||
|
@ -16,12 +16,12 @@ cZombie::cZombie(void) :
|
||||
|
||||
|
||||
|
||||
void cZombie::Tick(float a_Dt, MTRand & a_TickRandom)
|
||||
void cZombie::Tick(float a_Dt, cChunk & a_Chunk)
|
||||
{
|
||||
super::Tick(a_Dt, a_TickRandom);
|
||||
super::Tick(a_Dt, a_Chunk);
|
||||
|
||||
// TODO Same as in cSkeleton :D
|
||||
if ((GetWorld()->GetTimeOfDay() < (12000 + 1000)) && (GetMetaData() != BURNING))
|
||||
if ((GetWorld()->GetTimeOfDay() < (12000 + 1000)) && !IsBurning())
|
||||
{
|
||||
SetMetaData(BURNING); // BURN, BABY, BURN! >:D
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ public:
|
||||
|
||||
CLASS_PROTODEF(cZombie);
|
||||
|
||||
virtual void Tick(float a_Dt, MTRand & a_TickRandom) override;
|
||||
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
|
||||
virtual void GetDrops(cItems & a_Drops, cPawn * a_Killer = NULL) override;
|
||||
} ;
|
||||
|
||||
|
@ -16,12 +16,12 @@ cZombiepigman::cZombiepigman(void) :
|
||||
|
||||
|
||||
|
||||
void cZombiepigman::Tick(float a_Dt, MTRand & a_TickRandom)
|
||||
void cZombiepigman::Tick(float a_Dt, cChunk & a_Chunk)
|
||||
{
|
||||
super::Tick(a_Dt, a_TickRandom);
|
||||
super::Tick(a_Dt, a_Chunk);
|
||||
|
||||
// TODO Same as noticed in cSkeleton AND Do they really burn by sun?? :D In the neather is no sun :D
|
||||
if ((GetWorld()->GetTimeOfDay() < (12000 + 1000)) && (GetMetaData() != BURNING))
|
||||
if ((GetWorld()->GetTimeOfDay() < (12000 + 1000)) && !IsBurning())
|
||||
{
|
||||
SetMetaData(BURNING); // BURN, BABY, BURN! >:D
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ public:
|
||||
|
||||
CLASS_PROTODEF(cZombiepigman);
|
||||
|
||||
virtual void Tick(float a_Dt, MTRand & a_TickRandom) override;
|
||||
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
|
||||
virtual void GetDrops(cItems & a_Drops, cPawn * a_Killer = NULL) override;
|
||||
virtual void KilledBy(cPawn * a_Killer) override;
|
||||
} ;
|
||||
|
@ -288,11 +288,11 @@ void cPawn::TeleportTo(double a_PosX, double a_PosY, double a_PosZ)
|
||||
|
||||
|
||||
|
||||
void cPawn::Tick(float a_Dt, MTRand & a_TickRandom)
|
||||
void cPawn::Tick(float a_Dt, cChunk & a_Chunk)
|
||||
{
|
||||
CheckMetaDataBurn(); // Check to see if pawn should burn based on block they are on
|
||||
CheckMetaDataBurn(a_Chunk); // Check to see if pawn should burn based on block they are on
|
||||
|
||||
if (GetMetaData() == BURNING)
|
||||
if (IsBurning())
|
||||
{
|
||||
InStateBurning(a_Dt);
|
||||
}
|
||||
@ -315,8 +315,10 @@ void cPawn::SetMetaData(MetaData a_MetaData)
|
||||
|
||||
|
||||
//----Change Entity MetaData
|
||||
void cPawn::CheckMetaDataBurn(void)
|
||||
void cPawn::CheckMetaDataBurn(cChunk & a_Chunk)
|
||||
{
|
||||
// TODO: Rewrite this function to use a_Chunk instead of m_World
|
||||
|
||||
if ((GetPosY() < 1) || (GetPosY() >= 254))
|
||||
{
|
||||
// Y coord out of range
|
||||
|
@ -83,7 +83,7 @@ public:
|
||||
|
||||
cPawn(eEntityType a_EntityType);
|
||||
|
||||
virtual void Tick(float a_Dt, MTRand & a_TickRandom) override;
|
||||
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
|
||||
|
||||
// tolua_begin
|
||||
|
||||
@ -150,10 +150,12 @@ public:
|
||||
|
||||
virtual void InStateBurning(float a_Dt);
|
||||
|
||||
virtual void CheckMetaDataBurn(void);
|
||||
virtual void CheckMetaDataBurn(cChunk & a_Chunk);
|
||||
|
||||
virtual void SetMaxHealth(short a_MaxHealth);
|
||||
virtual short GetMaxHealth() { return m_MaxHealth; }
|
||||
|
||||
bool IsBurning(void) const { return (m_MetaData == BURNING); }
|
||||
|
||||
protected:
|
||||
short m_Health;
|
||||
|
@ -59,9 +59,9 @@ void cPickup::SpawnOn(cClientHandle & a_Client)
|
||||
|
||||
|
||||
|
||||
void cPickup::Tick(float a_Dt, MTRand & a_TickRandom)
|
||||
void cPickup::Tick(float a_Dt, cChunk & a_Chunk)
|
||||
{
|
||||
super::Tick(a_Dt, a_TickRandom);
|
||||
super::Tick(a_Dt, a_Chunk);
|
||||
|
||||
m_Timer += a_Dt;
|
||||
a_Dt = a_Dt / 1000.f;
|
||||
@ -88,7 +88,6 @@ void cPickup::Tick(float a_Dt, MTRand & a_TickRandom)
|
||||
|
||||
if (!m_bReplicated || m_bDirtyPosition)
|
||||
{
|
||||
MoveToCorrectChunk();
|
||||
m_bReplicated = true;
|
||||
m_bDirtyPosition = false;
|
||||
GetWorld()->BroadcastTeleportEntity(*this);
|
||||
@ -99,8 +98,10 @@ void cPickup::Tick(float a_Dt, MTRand & a_TickRandom)
|
||||
|
||||
|
||||
|
||||
void cPickup::HandlePhysics(float a_Dt)
|
||||
void cPickup::HandlePhysics(float a_Dt, cChunk & a_Chunk)
|
||||
{
|
||||
// TODO: Rewrite this function to use a_Chunk instead of m_World
|
||||
|
||||
m_ResultingSpeed.Set(0.f, 0.f, 0.f);
|
||||
cWorld * World = GetWorld();
|
||||
|
||||
|
@ -35,8 +35,8 @@ public:
|
||||
|
||||
virtual bool CollectedBy(cPlayer * a_Dest); // tolua_export
|
||||
|
||||
virtual void Tick(float a_Dt, MTRand & a_TickRandom) override;
|
||||
virtual void HandlePhysics(float a_Dt) override;
|
||||
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
|
||||
virtual void HandlePhysics(float a_Dt, cChunk & a_Chunk) override;
|
||||
|
||||
short GetHealth(void) const { return m_Health; }
|
||||
|
||||
|
@ -99,7 +99,7 @@ cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName)
|
||||
|
||||
cPlayer::~cPlayer(void)
|
||||
{
|
||||
LOG("Deleting cPlayer \"%s\" at %p, ID %d; inv win %p", m_PlayerName.c_str(), this, GetUniqueID(), m_InventoryWindow);
|
||||
LOG("Deleting cPlayer \"%s\" at %p, ID %d", m_PlayerName.c_str(), this, GetUniqueID());
|
||||
|
||||
SaveToDisk();
|
||||
|
||||
@ -109,7 +109,7 @@ cPlayer::~cPlayer(void)
|
||||
|
||||
delete m_InventoryWindow;
|
||||
|
||||
LOG("Player %p deleted", this);
|
||||
LOGD("Player %p deleted", this);
|
||||
}
|
||||
|
||||
|
||||
@ -119,7 +119,7 @@ cPlayer::~cPlayer(void)
|
||||
void cPlayer::Initialize( cWorld* a_World )
|
||||
{
|
||||
cPawn::Initialize( a_World );
|
||||
GetWorld()->AddPlayer( this );
|
||||
GetWorld()->AddPlayer(this);
|
||||
}
|
||||
|
||||
|
||||
@ -156,7 +156,7 @@ void cPlayer::SpawnOn(cClientHandle & a_Client)
|
||||
|
||||
|
||||
|
||||
void cPlayer::Tick(float a_Dt, MTRand & a_TickRandom)
|
||||
void cPlayer::Tick(float a_Dt, cChunk & a_Chunk)
|
||||
{
|
||||
if (!m_ClientHandle->IsPlaying())
|
||||
{
|
||||
@ -164,7 +164,7 @@ void cPlayer::Tick(float a_Dt, MTRand & a_TickRandom)
|
||||
return;
|
||||
}
|
||||
|
||||
super::Tick(a_Dt, a_TickRandom);
|
||||
super::Tick(a_Dt, a_Chunk);
|
||||
//TODO: Change this to use the BroadcastMovementUpdate function
|
||||
if (m_bDirtyOrientation && !m_bDirtyPosition)
|
||||
{
|
||||
@ -853,12 +853,11 @@ bool cPlayer::MoveToWorld( const char* a_WorldName )
|
||||
/* Remove all links to the old world */
|
||||
m_World->RemovePlayer( this );
|
||||
m_ClientHandle->RemoveFromAllChunks();
|
||||
m_World->RemoveEntityFromChunk(this, m_ChunkX, m_ChunkY, m_ChunkZ);
|
||||
m_World->RemoveEntityFromChunk(this, GetChunkX(), GetChunkZ());
|
||||
|
||||
/* Add player to all the necessary parts of the new world */
|
||||
SetWorld( World );
|
||||
GetWorld()->AddPlayer( this );
|
||||
MoveToCorrectChunk(true);
|
||||
GetWorld()->AddPlayer(this);
|
||||
GetClientHandle()->StreamChunks();
|
||||
|
||||
return true;
|
||||
|
@ -35,11 +35,11 @@ public:
|
||||
cPlayer(cClientHandle * a_Client, const AString & a_PlayerName);
|
||||
virtual ~cPlayer();
|
||||
|
||||
virtual void Initialize( cWorld* a_World ); // tolua_export
|
||||
virtual void Initialize(cWorld * a_World); // tolua_export
|
||||
|
||||
virtual void SpawnOn(cClientHandle & a_Client) override;
|
||||
|
||||
virtual void Tick(float a_Dt, MTRand & a_TickRandom) override;
|
||||
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
|
||||
|
||||
/// Returns the curently equipped weapon; empty item if none
|
||||
virtual cItem GetEquippedWeapon(void) const override { return m_Inventory.GetEquippedItem(); }
|
||||
|
@ -38,10 +38,10 @@ protected:
|
||||
unsigned m_BurnStepTimeNonfuel;
|
||||
|
||||
/// Chance [0..100000] of an adjacent fuel to catch fire on each tick
|
||||
unsigned m_Flammability;
|
||||
int m_Flammability;
|
||||
|
||||
/// Chance [0..100000] of a fuel burning out being replaced by a new fire block instead of an air block
|
||||
unsigned m_ReplaceFuelChance;
|
||||
int m_ReplaceFuelChance;
|
||||
|
||||
|
||||
virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override;
|
||||
|
157
source/World.cpp
157
source/World.cpp
@ -294,20 +294,6 @@ cWorld::cWorld(const AString & a_WorldName) :
|
||||
|
||||
cWorld::~cWorld()
|
||||
{
|
||||
{
|
||||
cCSLock Lock(m_CSEntities);
|
||||
while (m_AllEntities.begin() != m_AllEntities.end())
|
||||
{
|
||||
cEntity* Entity = *m_AllEntities.begin();
|
||||
m_AllEntities.remove(Entity);
|
||||
if (!Entity->IsDestroyed())
|
||||
{
|
||||
Entity->Destroy();
|
||||
}
|
||||
delete Entity;
|
||||
}
|
||||
}
|
||||
|
||||
delete m_SimulatorManager;
|
||||
delete m_SandSimulator;
|
||||
delete m_WaterSimulator;
|
||||
@ -480,25 +466,7 @@ void cWorld::Tick(float a_Dt)
|
||||
m_LastTimeUpdate = m_WorldAge;
|
||||
}
|
||||
|
||||
// Remove entities scheduled for removal:
|
||||
{
|
||||
cCSLock Lock(m_CSEntities);
|
||||
for (cEntityList::iterator itr = m_AllEntities.begin(); itr != m_AllEntities.end();)
|
||||
{
|
||||
if ((*itr)->IsDestroyed())
|
||||
{
|
||||
LOGD("Destroying entity #%i", (*itr)->GetUniqueID());
|
||||
cEntity * RemoveMe = *itr;
|
||||
itr = m_AllEntities.erase(itr);
|
||||
m_RemoveEntityQueue.push_back(RemoveMe);
|
||||
continue;
|
||||
}
|
||||
(*itr)->Tick(a_Dt, m_TickRand);
|
||||
itr++;
|
||||
}
|
||||
}
|
||||
|
||||
m_ChunkMap->Tick(a_Dt, m_TickRand);
|
||||
m_ChunkMap->Tick(a_Dt);
|
||||
|
||||
TickQueuedBlocks(a_Dt);
|
||||
|
||||
@ -530,13 +498,6 @@ void cWorld::Tick(float a_Dt)
|
||||
UnloadUnusedChunks();
|
||||
}
|
||||
|
||||
// Delete entities queued for removal:
|
||||
for (cEntityList::iterator itr = m_RemoveEntityQueue.begin(); itr != m_RemoveEntityQueue.end(); ++itr)
|
||||
{
|
||||
delete *itr;
|
||||
}
|
||||
m_RemoveEntityQueue.clear();
|
||||
|
||||
TickSpawnMobs(a_Dt);
|
||||
|
||||
std::vector<int> m_RSList_copy(m_RSList);
|
||||
@ -1290,6 +1251,15 @@ int cWorld::GetHeight(int a_X, int a_Z)
|
||||
|
||||
|
||||
|
||||
bool cWorld::TryGetHeight(int a_BlockX, int a_BlockZ, int & a_Height)
|
||||
{
|
||||
return m_ChunkMap->TryGetHeight(a_BlockX, a_BlockZ, a_Height);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cWorld::BroadcastAttachEntity(const cEntity & a_Entity, const cEntity * a_Vehicle)
|
||||
{
|
||||
return m_ChunkMap->BroadcastAttachEntity(a_Entity, a_Vehicle);
|
||||
@ -1577,27 +1547,27 @@ void cWorld::SendBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cClientHa
|
||||
|
||||
|
||||
|
||||
void cWorld::MarkChunkDirty (int a_ChunkX, int a_ChunkY, int a_ChunkZ)
|
||||
void cWorld::MarkChunkDirty (int a_ChunkX, int a_ChunkZ)
|
||||
{
|
||||
m_ChunkMap->MarkChunkDirty (a_ChunkX, a_ChunkY, a_ChunkZ);
|
||||
m_ChunkMap->MarkChunkDirty (a_ChunkX, a_ChunkZ);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cWorld::MarkChunkSaving(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
|
||||
void cWorld::MarkChunkSaving(int a_ChunkX, int a_ChunkZ)
|
||||
{
|
||||
m_ChunkMap->MarkChunkSaving(a_ChunkX, a_ChunkY, a_ChunkZ);
|
||||
m_ChunkMap->MarkChunkSaving(a_ChunkX, a_ChunkZ);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cWorld::MarkChunkSaved (int a_ChunkX, int a_ChunkY, int a_ChunkZ)
|
||||
void cWorld::MarkChunkSaved (int a_ChunkX, int a_ChunkZ)
|
||||
{
|
||||
m_ChunkMap->MarkChunkSaved (a_ChunkX, a_ChunkY, a_ChunkZ);
|
||||
m_ChunkMap->MarkChunkSaved (a_ChunkX, a_ChunkZ);
|
||||
}
|
||||
|
||||
|
||||
@ -1605,7 +1575,7 @@ void cWorld::MarkChunkSaved (int a_ChunkX, int a_ChunkY, int a_ChunkZ)
|
||||
|
||||
|
||||
void cWorld::SetChunkData(
|
||||
int a_ChunkX, int a_ChunkY, int a_ChunkZ,
|
||||
int a_ChunkX, int a_ChunkZ,
|
||||
const BLOCKTYPE * a_BlockTypes,
|
||||
const NIBBLETYPE * a_BlockMeta,
|
||||
const NIBBLETYPE * a_BlockLight,
|
||||
@ -1628,10 +1598,10 @@ void cWorld::SetChunkData(
|
||||
}
|
||||
|
||||
m_ChunkMap->SetChunkData(
|
||||
a_ChunkX, a_ChunkY, a_ChunkZ,
|
||||
a_ChunkX, a_ChunkZ,
|
||||
a_BlockTypes, a_BlockMeta, a_BlockLight, a_BlockSkyLight,
|
||||
a_HeightMap, *Biomes,
|
||||
a_Entities, a_BlockEntities,
|
||||
a_BlockEntities,
|
||||
a_MarkDirty
|
||||
);
|
||||
|
||||
@ -1642,9 +1612,9 @@ void cWorld::SetChunkData(
|
||||
}
|
||||
|
||||
// If a client is requesting this chunk, send it to them:
|
||||
if (m_ChunkMap->HasChunkAnyClients(a_ChunkX, a_ChunkY, a_ChunkZ))
|
||||
if (m_ChunkMap->HasChunkAnyClients(a_ChunkX, a_ChunkZ))
|
||||
{
|
||||
m_ChunkSender.ChunkReady(a_ChunkX, a_ChunkY, a_ChunkZ);
|
||||
m_ChunkSender.ChunkReady(a_ChunkX, a_ChunkZ);
|
||||
}
|
||||
|
||||
// Notify the lighting thread that the chunk has become valid (in case it is a neighbor of a postponed chunk):
|
||||
@ -1668,36 +1638,36 @@ void cWorld::ChunkLighted(
|
||||
|
||||
|
||||
|
||||
bool cWorld::GetChunkData(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cChunkDataCallback & a_Callback)
|
||||
bool cWorld::GetChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataCallback & a_Callback)
|
||||
{
|
||||
return m_ChunkMap->GetChunkData(a_ChunkX, a_ChunkY, a_ChunkZ, a_Callback);
|
||||
return m_ChunkMap->GetChunkData(a_ChunkX, a_ChunkZ, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cWorld::GetChunkBlockTypes(int a_ChunkX, int a_ChunkY, int a_ChunkZ, BLOCKTYPE * a_BlockTypes)
|
||||
bool cWorld::GetChunkBlockTypes(int a_ChunkX, int a_ChunkZ, BLOCKTYPE * a_BlockTypes)
|
||||
{
|
||||
return m_ChunkMap->GetChunkBlockTypes(a_ChunkX, a_ChunkY, a_ChunkZ, a_BlockTypes);
|
||||
return m_ChunkMap->GetChunkBlockTypes(a_ChunkX, a_ChunkZ, a_BlockTypes);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cWorld::IsChunkValid(int a_ChunkX, int a_ChunkY, int a_ChunkZ) const
|
||||
bool cWorld::IsChunkValid(int a_ChunkX, int a_ChunkZ) const
|
||||
{
|
||||
return m_ChunkMap->IsChunkValid(a_ChunkX, a_ChunkY, a_ChunkZ);
|
||||
return m_ChunkMap->IsChunkValid(a_ChunkX, a_ChunkZ);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cWorld::HasChunkAnyClients(int a_ChunkX, int a_ChunkY, int a_ChunkZ) const
|
||||
bool cWorld::HasChunkAnyClients(int a_ChunkX, int a_ChunkZ) const
|
||||
{
|
||||
return m_ChunkMap->HasChunkAnyClients(a_ChunkX, a_ChunkY, a_ChunkZ);
|
||||
return m_ChunkMap->HasChunkAnyClients(a_ChunkX, a_ChunkZ);
|
||||
}
|
||||
|
||||
|
||||
@ -1736,7 +1706,7 @@ void cWorld::SetMaxPlayers(int iMax)
|
||||
|
||||
|
||||
|
||||
void cWorld::AddPlayer(cPlayer* a_Player)
|
||||
void cWorld::AddPlayer(cPlayer * a_Player)
|
||||
{
|
||||
cCSLock Lock(m_CSPlayers);
|
||||
|
||||
@ -1750,8 +1720,9 @@ void cWorld::AddPlayer(cPlayer* a_Player)
|
||||
|
||||
|
||||
|
||||
void cWorld::RemovePlayer(cPlayer* a_Player)
|
||||
void cWorld::RemovePlayer(cPlayer * a_Player)
|
||||
{
|
||||
m_ChunkMap->RemoveEntityFromChunk(a_Player, a_Player->GetChunkX(), a_Player->GetChunkZ());
|
||||
cCSLock Lock(m_CSPlayers);
|
||||
m_Players.remove(a_Player);
|
||||
}
|
||||
@ -1882,18 +1853,9 @@ void cWorld::SendPlayerList(cPlayer * a_DestPlayer)
|
||||
|
||||
|
||||
|
||||
void cWorld::RemoveEntityFromChunk(cEntity * a_Entity, int a_ChunkX, int a_ChunkY, int a_ChunkZ)
|
||||
void cWorld::RemoveEntityFromChunk(cEntity * a_Entity, int a_ChunkX, int a_ChunkZ)
|
||||
{
|
||||
m_ChunkMap->RemoveEntityFromChunk(a_Entity, a_ChunkX, a_ChunkY, a_ChunkZ);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cWorld::MoveEntityToChunk(cEntity * a_Entity, int a_ChunkX, int a_ChunkY, int a_ChunkZ)
|
||||
{
|
||||
m_ChunkMap->MoveEntityToChunk(a_Entity, a_ChunkX, a_ChunkY, a_ChunkZ);
|
||||
m_ChunkMap->RemoveEntityFromChunk(a_Entity, a_ChunkX, a_ChunkZ);
|
||||
}
|
||||
|
||||
|
||||
@ -1902,16 +1864,7 @@ void cWorld::MoveEntityToChunk(cEntity * a_Entity, int a_ChunkX, int a_ChunkY, i
|
||||
|
||||
bool cWorld::ForEachEntity(cEntityCallback & a_Callback)
|
||||
{
|
||||
cCSLock Lock(m_CSEntities);
|
||||
for (cEntityList::iterator itr = m_AllEntities.begin(), itr2 = itr; itr != m_AllEntities.end(); itr = itr2)
|
||||
{
|
||||
++itr2;
|
||||
if (a_Callback.Item(*itr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
} // for itr - m_AllEntities[]
|
||||
return false;
|
||||
return m_ChunkMap->ForEachEntity(a_Callback);
|
||||
}
|
||||
|
||||
|
||||
@ -1929,42 +1882,34 @@ bool cWorld::ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback &
|
||||
|
||||
bool cWorld::DoWithEntityByID(int a_UniqueID, cEntityCallback & a_Callback)
|
||||
{
|
||||
cCSLock Lock(m_CSEntities);
|
||||
for (cEntityList::iterator itr = m_AllEntities.begin(), end = m_AllEntities.end(); itr != end; ++itr)
|
||||
{
|
||||
if ((*itr)->GetUniqueID() == a_UniqueID)
|
||||
{
|
||||
return a_Callback.Item(*itr);
|
||||
}
|
||||
} // for itr - m_AllEntities[]
|
||||
return false;
|
||||
return m_ChunkMap->DoWithEntityByID(a_UniqueID, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cWorld::CompareChunkClients(int a_ChunkX1, int a_ChunkY1, int a_ChunkZ1, int a_ChunkX2, int a_ChunkY2, int a_ChunkZ2, cClientDiffCallback & a_Callback)
|
||||
void cWorld::CompareChunkClients(int a_ChunkX1, int a_ChunkZ1, int a_ChunkX2, int a_ChunkZ2, cClientDiffCallback & a_Callback)
|
||||
{
|
||||
m_ChunkMap->CompareChunkClients(a_ChunkX1, a_ChunkY1, a_ChunkZ1, a_ChunkX2, a_ChunkY2, a_ChunkZ2, a_Callback);
|
||||
m_ChunkMap->CompareChunkClients(a_ChunkX1, a_ChunkZ1, a_ChunkX2, a_ChunkZ2, a_Callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cWorld::AddChunkClient(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client)
|
||||
bool cWorld::AddChunkClient(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client)
|
||||
{
|
||||
return m_ChunkMap->AddChunkClient(a_ChunkX, a_ChunkY, a_ChunkZ, a_Client);
|
||||
return m_ChunkMap->AddChunkClient(a_ChunkX, a_ChunkZ, a_Client);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cWorld::RemoveChunkClient(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client)
|
||||
void cWorld::RemoveChunkClient(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client)
|
||||
{
|
||||
m_ChunkMap->RemoveChunkClient(a_ChunkX, a_ChunkY, a_ChunkZ, a_Client);
|
||||
m_ChunkMap->RemoveChunkClient(a_ChunkX, a_ChunkZ, a_Client);
|
||||
}
|
||||
|
||||
|
||||
@ -1980,9 +1925,9 @@ void cWorld::RemoveClientFromChunks(cClientHandle * a_Client)
|
||||
|
||||
|
||||
|
||||
void cWorld::SendChunkTo(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client)
|
||||
void cWorld::SendChunkTo(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client)
|
||||
{
|
||||
m_ChunkSender.QueueSendChunkTo(a_ChunkX, a_ChunkY, a_ChunkZ, a_Client);
|
||||
m_ChunkSender.QueueSendChunkTo(a_ChunkX, a_ChunkZ, a_Client);
|
||||
}
|
||||
|
||||
|
||||
@ -2123,8 +2068,16 @@ void cWorld::SaveAllChunks(void)
|
||||
|
||||
void cWorld::AddEntity(cEntity * a_Entity)
|
||||
{
|
||||
cCSLock Lock(m_CSEntities);
|
||||
m_AllEntities.push_back(a_Entity);
|
||||
m_ChunkMap->AddEntity(a_Entity);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cWorld::HasEntity(int a_UniqueID)
|
||||
{
|
||||
return m_ChunkMap->HasEntity(a_UniqueID);
|
||||
}
|
||||
|
||||
|
||||
@ -2254,8 +2207,8 @@ int cWorld::SpawnMob(double a_PosX, double a_PosY, double a_PosZ, int a_EntityTy
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
Monster->SetPosition(a_PosX, a_PosY, a_PosZ);
|
||||
Monster->Initialize(this);
|
||||
Monster->TeleportTo(a_PosX, a_PosY, a_PosZ);
|
||||
BroadcastSpawn(*Monster);
|
||||
return Monster->GetUniqueID();
|
||||
}
|
||||
|
@ -100,10 +100,14 @@ public:
|
||||
|
||||
eDimension GetDimension(void) const { return m_Dimension; }
|
||||
|
||||
/// Returns the world height at the specified coords; waits for the chunk to get loaded / generated
|
||||
int GetHeight(int a_BlockX, int a_BlockZ);
|
||||
|
||||
// tolua_end
|
||||
|
||||
/// Retrieves the world height at the specified coords; returns false if chunk not loaded / generated
|
||||
bool TryGetHeight(int a_BlockX, int a_BlockZ, int & a_Height); // TODO: Export in ManualBindings.cpp
|
||||
|
||||
void BroadcastAttachEntity (const cEntity & a_Entity, const cEntity * a_Vehicle);
|
||||
void BroadcastChat (const AString & a_Message, const cClientHandle * a_Exclude = NULL);
|
||||
void BroadcastPlayerAnimation (const cPlayer & a_Player, char a_Animation, const cClientHandle * a_Exclude = NULL);
|
||||
@ -136,9 +140,9 @@ public:
|
||||
/// If there is a block entity at the specified coords, sends it to the client specified
|
||||
void SendBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cClientHandle & a_Client);
|
||||
|
||||
void MarkChunkDirty (int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
||||
void MarkChunkSaving(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
||||
void MarkChunkSaved (int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
||||
void MarkChunkDirty (int a_ChunkX, int a_ChunkZ);
|
||||
void MarkChunkSaving(int a_ChunkX, int a_ChunkZ);
|
||||
void MarkChunkSaved (int a_ChunkX, int a_ChunkZ);
|
||||
|
||||
/** Sets the chunk data as either loaded from the storage or generated.
|
||||
a_BlockLight and a_BlockSkyLight are optional, if not present, chunk will be marked as unlighted.
|
||||
@ -147,7 +151,7 @@ public:
|
||||
If a_MarkDirty is set, the chunk is set as dirty (used after generating)
|
||||
*/
|
||||
void SetChunkData(
|
||||
int a_ChunkX, int a_ChunkY, int a_ChunkZ,
|
||||
int a_ChunkX, int a_ChunkZ,
|
||||
const BLOCKTYPE * a_BlockTypes,
|
||||
const NIBBLETYPE * a_BlockMeta,
|
||||
const NIBBLETYPE * a_BlockLight,
|
||||
@ -165,13 +169,13 @@ public:
|
||||
const cChunkDef::BlockNibbles & a_SkyLight
|
||||
);
|
||||
|
||||
bool GetChunkData (int a_ChunkX, int a_ChunkY, int a_ChunkZ, cChunkDataCallback & a_Callback);
|
||||
bool GetChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataCallback & a_Callback);
|
||||
|
||||
/// Gets the chunk's blocks, only the block types
|
||||
bool GetChunkBlockTypes(int a_ChunkX, int a_ChunkY, int a_ChunkZ, BLOCKTYPE * a_BlockTypes);
|
||||
bool GetChunkBlockTypes(int a_ChunkX, int a_ChunkZ, BLOCKTYPE * a_BlockTypes);
|
||||
|
||||
bool IsChunkValid (int a_ChunkX, int a_ChunkY, int a_ChunkZ) const;
|
||||
bool HasChunkAnyClients(int a_ChunkX, int a_ChunkY, int a_ChunkZ) const;
|
||||
bool IsChunkValid (int a_ChunkX, int a_ChunkZ) const;
|
||||
bool HasChunkAnyClients(int a_ChunkX, int a_ChunkZ) const;
|
||||
|
||||
void UnloadUnusedChunks(void); // tolua_export
|
||||
|
||||
@ -203,13 +207,12 @@ public:
|
||||
|
||||
void SendPlayerList(cPlayer * a_DestPlayer); // Sends playerlist to the player
|
||||
|
||||
void AddEntity( cEntity* a_Entity );
|
||||
void AddEntity(cEntity * a_Entity);
|
||||
|
||||
bool HasEntity(int a_UniqueID);
|
||||
|
||||
/// Removes the entity from the chunk specified
|
||||
void RemoveEntityFromChunk(cEntity * a_Entity, int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
||||
|
||||
/// Moves the entity from its current chunk to the new chunk specified
|
||||
void MoveEntityToChunk(cEntity * a_Entity, int a_ChunkX, int a_ChunkY, int a_ChunkZ);
|
||||
void RemoveEntityFromChunk(cEntity * a_Entity, int a_ChunkX, int a_ChunkZ);
|
||||
|
||||
/// Calls the callback for each entity in the entire world; returns true if all entities processed, false if the callback aborted by returning true
|
||||
bool ForEachEntity(cEntityCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
@ -217,23 +220,23 @@ public:
|
||||
/// Calls the callback for each entity in the specified chunk; returns true if all entities processed, false if the callback aborted by returning true
|
||||
bool ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback & a_Callback); // Exported in ManualBindings.cpp
|
||||
|
||||
/// Calls the callback if the entity with the specified ID is found, with the entity object as the callback param
|
||||
/// Calls the callback if the entity with the specified ID is found, with the entity object as the callback param. Returns true if entity found and callback returned false.
|
||||
bool DoWithEntityByID(int a_UniqueID, cEntityCallback & a_Callback); // TODO: Exported in ManualBindings.cpp
|
||||
|
||||
/// Compares clients of two chunks, calls the callback accordingly
|
||||
void CompareChunkClients(int a_ChunkX1, int a_ChunkY1, int a_ChunkZ1, int a_ChunkX2, int a_ChunkY2, int a_ChunkZ2, cClientDiffCallback & a_Callback);
|
||||
void CompareChunkClients(int a_ChunkX1, int a_ChunkZ1, int a_ChunkX2, int a_ChunkZ2, cClientDiffCallback & a_Callback);
|
||||
|
||||
/// Adds client to a chunk, if not already present; returns true if added, false if present
|
||||
bool AddChunkClient(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client);
|
||||
bool AddChunkClient(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client);
|
||||
|
||||
/// Removes client from the chunk specified
|
||||
void RemoveChunkClient(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client);
|
||||
void RemoveChunkClient(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client);
|
||||
|
||||
/// Removes the client from all chunks it is present in
|
||||
void RemoveClientFromChunks(cClientHandle * a_Client);
|
||||
|
||||
/// Sends the chunk to the client specified, if the chunk is valid. If not valid, the request is postponed (ChunkSender will send that chunk when it becomes valid+lighted)
|
||||
void SendChunkTo(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client);
|
||||
void SendChunkTo(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client);
|
||||
|
||||
/// Removes client from ChunkSender's queue of chunks to be sent
|
||||
void RemoveClientFromChunkSender(cClientHandle * a_Client);
|
||||
@ -461,7 +464,7 @@ public:
|
||||
int SpawnMob(double a_PosX, double a_PosY, double a_PosZ, int a_EntityType); // tolua_export
|
||||
|
||||
/// Returns a random number from the m_TickRand in range [0 .. a_Range]. To be used only in the tick thread!
|
||||
unsigned GetTickRandomNumber(unsigned a_Range) { return m_TickRand.randInt(a_Range); }
|
||||
int GetTickRandomNumber(unsigned a_Range) { return (int)(m_TickRand.randInt(a_Range)); }
|
||||
|
||||
private:
|
||||
|
||||
@ -505,7 +508,6 @@ private:
|
||||
cRedstoneSimulator * m_RedstoneSimulator;
|
||||
|
||||
cCriticalSection m_CSClients;
|
||||
cCriticalSection m_CSEntities;
|
||||
cCriticalSection m_CSPlayers;
|
||||
|
||||
cWorldStorage m_Storage;
|
||||
@ -536,8 +538,6 @@ private:
|
||||
bool m_IsSaplingBonemealable;
|
||||
bool m_IsSugarcaneBonemealable;
|
||||
|
||||
cEntityList m_RemoveEntityQueue;
|
||||
cEntityList m_AllEntities;
|
||||
cClientHandleList m_Clients;
|
||||
cPlayerList m_Players;
|
||||
|
||||
|
@ -113,10 +113,12 @@ bool cWSSAnvil::SaveChunk(const cChunkCoords & a_Chunk)
|
||||
AString ChunkData;
|
||||
if (!SaveChunkToData(a_Chunk, ChunkData))
|
||||
{
|
||||
LOGWARNING("Cannot serialize chunk [%d, %d] into data", a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
|
||||
return false;
|
||||
}
|
||||
if (!SetChunkData(a_Chunk, ChunkData))
|
||||
{
|
||||
LOGWARNING("Cannot store chunk [%d, %d] data", a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -252,6 +254,7 @@ bool cWSSAnvil::SaveChunkToData(const cChunkCoords & a_Chunk, AString & a_Data)
|
||||
cFastNBTWriter Writer;
|
||||
if (!SaveChunkToNBT(a_Chunk, Writer))
|
||||
{
|
||||
LOGWARNING("Cannot save chunk [%d, %d] to NBT", a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
|
||||
return false;
|
||||
}
|
||||
Writer.Finish();
|
||||
@ -360,7 +363,7 @@ bool cWSSAnvil::LoadChunkFromNBT(const cChunkCoords & a_Chunk, const cParsedNBT
|
||||
//*/
|
||||
|
||||
m_World->SetChunkData(
|
||||
a_Chunk.m_ChunkX, a_Chunk.m_ChunkY, a_Chunk.m_ChunkZ,
|
||||
a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ,
|
||||
BlockTypes, MetaData,
|
||||
IsLightValid ? BlockLight : NULL,
|
||||
IsLightValid ? SkyLight : NULL,
|
||||
@ -393,8 +396,9 @@ bool cWSSAnvil::SaveChunkToNBT(const cChunkCoords & a_Chunk, cFastNBTWriter & a_
|
||||
a_Writer.AddInt("xPos", a_Chunk.m_ChunkX);
|
||||
a_Writer.AddInt("zPos", a_Chunk.m_ChunkZ);
|
||||
cNBTChunkSerializer Serializer(a_Writer);
|
||||
if (!m_World->GetChunkData(a_Chunk.m_ChunkX, a_Chunk.m_ChunkY, a_Chunk.m_ChunkZ, Serializer))
|
||||
if (!m_World->GetChunkData(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, Serializer))
|
||||
{
|
||||
LOGWARNING("Cannot get chunk [%d, %d] data for NBT saving", a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
|
||||
return false;
|
||||
}
|
||||
Serializer.Finish(); // Close NBT tags
|
||||
|
@ -875,7 +875,7 @@ bool cWSSCompact::LoadChunkFromData(const cChunkCoords & a_Chunk, int & a_Uncomp
|
||||
NIBBLETYPE * SkyLight = (NIBBLETYPE *)(BlockData + cChunkDef::SkyLightOffset);
|
||||
|
||||
a_World->SetChunkData(
|
||||
a_Chunk.m_ChunkX, a_Chunk.m_ChunkY, a_Chunk.m_ChunkZ,
|
||||
a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ,
|
||||
BlockData, MetaData,
|
||||
IsLightValid ? BlockLight : NULL,
|
||||
IsLightValid ? SkyLight : NULL,
|
||||
@ -919,7 +919,7 @@ bool cWSSCompact::cPAKFile::SaveChunkToData(const cChunkCoords & a_Chunk, cWorld
|
||||
{
|
||||
// Serialize the chunk:
|
||||
cJsonChunkSerializer Serializer;
|
||||
if (!a_World->GetChunkData(a_Chunk.m_ChunkX, a_Chunk.m_ChunkY, a_Chunk.m_ChunkZ, Serializer))
|
||||
if (!a_World->GetChunkData(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, Serializer))
|
||||
{
|
||||
// Chunk not valid
|
||||
LOG("cWSSCompact: Trying to save chunk [%d, %d, %d] that has no data, ignoring request.", a_Chunk.m_ChunkX, a_Chunk.m_ChunkY, a_Chunk.m_ChunkZ);
|
||||
|
@ -349,16 +349,12 @@ bool cWorldStorage::SaveOneChunk(void)
|
||||
LOGINFO("Saved all chunks in world %s", m_World->GetName().c_str());
|
||||
return HasMore;
|
||||
}
|
||||
if (ShouldSave && m_World->IsChunkValid(Save.m_ChunkX, Save.m_ChunkY, Save.m_ChunkZ))
|
||||
if (ShouldSave && m_World->IsChunkValid(Save.m_ChunkX, Save.m_ChunkZ))
|
||||
{
|
||||
m_World->MarkChunkSaving(Save.m_ChunkX, Save.m_ChunkY, Save.m_ChunkZ);
|
||||
m_World->MarkChunkSaving(Save.m_ChunkX, Save.m_ChunkZ);
|
||||
if (m_SaveSchema->SaveChunk(Save))
|
||||
{
|
||||
m_World->MarkChunkSaved(Save.m_ChunkX, Save.m_ChunkY, Save.m_ChunkZ);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGWARNING("Cannot save chunk [%d, %d, %d]", Save.m_ChunkX, Save.m_ChunkY, Save.m_ChunkZ);
|
||||
m_World->MarkChunkSaved(Save.m_ChunkX, Save.m_ChunkZ);
|
||||
}
|
||||
}
|
||||
return HasMore;
|
||||
@ -370,7 +366,7 @@ bool cWorldStorage::SaveOneChunk(void)
|
||||
|
||||
bool cWorldStorage::LoadChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
|
||||
{
|
||||
if (m_World->IsChunkValid(a_ChunkX, a_ChunkY, a_ChunkZ))
|
||||
if (m_World->IsChunkValid(a_ChunkX, a_ChunkZ))
|
||||
{
|
||||
// Already loaded (can happen, since the queue is async)
|
||||
return true;
|
||||
|
Loading…
Reference in New Issue
Block a user