1
0

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:
madmaxoft@gmail.com 2013-04-13 21:02:10 +00:00
parent 58fb05980d
commit a49c004278
49 changed files with 691 additions and 582 deletions

View File

@ -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);

View File

@ -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 */

View File

@ -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);
}

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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];

View File

@ -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;
}

View File

@ -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);

View File

@ -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();
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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 );

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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(),

View File

@ -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;
}

View File

@ -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
}

View File

@ -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; }

View File

@ -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();
}
}
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
} ;

View File

@ -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);

View File

@ -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;
} ;

View File

@ -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)
{

View File

@ -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;}

View File

@ -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();
}
}
}

View File

@ -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;

View File

@ -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
}

View File

@ -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;
} ;

View File

@ -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);
}

View File

@ -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);

View File

@ -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
}

View File

@ -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;
} ;

View File

@ -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
}

View File

@ -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;
} ;

View File

@ -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

View File

@ -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;

View File

@ -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();

View File

@ -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; }

View File

@ -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;

View File

@ -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(); }

View File

@ -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;

View File

@ -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();
}

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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;