summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--source/cChunk.cpp28
-rw-r--r--source/cClientHandle.cpp12
-rw-r--r--source/cEntity.cpp39
-rw-r--r--source/cEntity.h5
-rw-r--r--source/cPlayer.cpp11
-rw-r--r--source/cPlayer.h4
-rw-r--r--source/cWorld.cpp1
-rw-r--r--source/cWorld.h2
8 files changed, 74 insertions, 28 deletions
diff --git a/source/cChunk.cpp b/source/cChunk.cpp
index 430fa6fc8..420ba078f 100644
--- a/source/cChunk.cpp
+++ b/source/cChunk.cpp
@@ -70,14 +70,19 @@ cChunk::~cChunk()
m_pState->m_BlockEntities.clear();
LockEntities();
- for( EntityList::iterator itr = m_pState->m_Entities.begin(); itr != m_pState->m_Entities.end(); ++itr)
+ if( m_pState->m_Entities.size() > 0 )
{
- if( (*itr)->GetEntityType() != cEntity::E_PLAYER )
+ EntityList Entities = m_pState->m_Entities; // Copy list to a temporary list
+ for( EntityList::iterator itr = Entities.begin(); itr != Entities.end(); ++itr)
{
- m_World->AddToRemoveEntityQueue( **itr ); // World also destroys the entity
+ if( (*itr)->GetEntityType() != cEntity::E_PLAYER )
+ {
+ (*itr)->RemoveFromChunk( this );
+ (*itr)->Destroy();
+ }
}
+ m_pState->m_Entities.clear();
}
- m_pState->m_Entities.clear();
UnlockEntities();
if( m_EntitiesCriticalSection )
@@ -1027,14 +1032,17 @@ void cChunk::RemoveClient( cClientHandle* a_Client )
{
m_pState->m_LoadedByClient.remove( a_Client );
- LockEntities();
- for( EntityList::iterator itr = m_pState->m_Entities.begin(); itr != m_pState->m_Entities.end(); ++itr )
+ if( !a_Client->IsDestroyed() )
{
- LOG("%i %i %i Destroying on %s", m_PosX, m_PosY, m_PosZ, a_Client->GetUsername() );
- cPacket_DestroyEntity DestroyEntity( *itr );
- a_Client->Send( DestroyEntity );
+ LockEntities();
+ for( EntityList::iterator itr = m_pState->m_Entities.begin(); itr != m_pState->m_Entities.end(); ++itr )
+ {
+ LOG("%i %i %i Destroying on %s", m_PosX, m_PosY, m_PosZ, a_Client->GetUsername() );
+ cPacket_DestroyEntity DestroyEntity( *itr );
+ a_Client->Send( DestroyEntity );
+ }
+ UnlockEntities();
}
- UnlockEntities();
}
void cChunk::AddEntity( cEntity & a_Entity )
diff --git a/source/cClientHandle.cpp b/source/cClientHandle.cpp
index a694ea97e..621e8a19e 100644
--- a/source/cClientHandle.cpp
+++ b/source/cClientHandle.cpp
@@ -432,7 +432,9 @@ void cClientHandle::HandlePacket( cPacket* a_Packet )
}
// Now initialize player (adds to entity list etc.)
- m_Player->Initialize( cRoot::Get()->GetDefaultWorld() ); // TODO - Get correct world for player
+ cWorld* PlayerWorld = cRoot::Get()->GetWorld( m_Player->GetLoadedWorldName() );
+ if( !PlayerWorld ) PlayerWorld = cRoot::Get()->GetDefaultWorld();
+ m_Player->Initialize( PlayerWorld ); // TODO - Get correct world for player
// Broadcasts to all but this ( this is actually handled in cChunk.cpp, after entity is added to the chunk )
//m_Player->SpawnOn( 0 );
@@ -937,13 +939,15 @@ void cClientHandle::Tick(float a_Dt)
{
m_bSendLoginResponse = false;
- cWorld* World = cRoot::Get()->GetDefaultWorld(); // TODO - Get the correct world or better yet, move this to the main thread so we don't have to lock anything
- World->LockEntities();
// Spawn player (only serversided, so data is loaded)
m_Player = new cPlayer( this, GetUsername() ); // !!DO NOT INITIALIZE!! <- is done after receiving MoveLook Packet
+
+ cWorld* World = cRoot::Get()->GetWorld( m_Player->GetLoadedWorldName() ); // TODO - Get the correct world or better yet, move this to the main thread so we don't have to lock anything
+ if( !World ) World = cRoot::Get()->GetDefaultWorld();
+ World->LockEntities();
m_Player->SetGameMode ( World->GetGameMode() ); //set player's gamemode to server's gamemode at login.
- cRoot::Get()->GetPluginManager()->CallHook( cPluginManager::E_PLUGIN_PLAYER_SPAWN, 1, m_Player ); // TODO - this function is called from a seperate thread, which might be dangerous
+ cRoot::Get()->GetPluginManager()->CallHook( cPluginManager::E_PLUGIN_PLAYER_SPAWN, 1, m_Player );
// Return a server login packet
cPacket_Login LoginResponse;
diff --git a/source/cEntity.cpp b/source/cEntity.cpp
index c22be3def..b9cbbd9f6 100644
--- a/source/cEntity.cpp
+++ b/source/cEntity.cpp
@@ -28,6 +28,7 @@ cEntity::cEntity(const double & a_X, const double & a_Y, const double & a_Z)
, m_bDestroyed( false )
, m_EntityType( E_ENTITY )
, m_World( 0 )
+ , m_bRemovedFromChunk( false )
{
m_EntityCount++;
m_UniqueID = m_EntityCount;
@@ -35,18 +36,12 @@ cEntity::cEntity(const double & a_X, const double & a_Y, const double & a_Z)
cEntity::~cEntity()
{
- delete m_Referencers;
- delete m_References;
- if( m_World )
+ if( !m_bDestroyed || !m_bRemovedFromChunk )
{
- cChunk* Chunk = m_World->GetChunkUnreliable( m_ChunkX, m_ChunkY, m_ChunkZ );
- if( Chunk )
- {
- cPacket_DestroyEntity DestroyEntity( this );
- Chunk->Broadcast( DestroyEntity );
- Chunk->RemoveEntity( *this );
- }
+ LOGERROR("ERROR: Entity deallocated without being destroyed %i or unlinked %i", m_bDestroyed, m_bRemovedFromChunk );
}
+ delete m_Referencers;
+ delete m_References;
delete m_Pos;
delete m_Rot;
}
@@ -143,6 +138,30 @@ void cEntity::MoveToCorrectChunk()
}
}
+void cEntity::Destroy()
+{
+ if( !m_bDestroyed )
+ {
+ m_bDestroyed = true;
+ if( !m_bRemovedFromChunk )
+ RemoveFromChunk(0);
+ }
+}
+
+void cEntity::RemoveFromChunk( cChunk* a_Chunk )
+{
+ if( m_World )
+ {
+ cChunk* Chunk = ( a_Chunk ? a_Chunk : m_World->GetChunkUnreliable( m_ChunkX, m_ChunkY, m_ChunkZ ) );
+ if( Chunk )
+ {
+ cPacket_DestroyEntity DestroyEntity( this );
+ Chunk->Broadcast( DestroyEntity );
+ Chunk->RemoveEntity( *this );
+ m_bRemovedFromChunk = true;
+ }
+ }
+}
CLASS_DEF_GETCLASS( cEntity );
bool cEntity::IsA( const char* a_EntityType )
diff --git a/source/cEntity.h b/source/cEntity.h
index 509a5c1d5..c25c3e293 100644
--- a/source/cEntity.h
+++ b/source/cEntity.h
@@ -27,6 +27,7 @@
CLASS_DEF_ISA( classname, superclass ) \
CLASS_DEF_GETCLASS( classname )
+class cChunk;
class cWorld;
class cReferenceManager;
class Vector3d;
@@ -76,7 +77,8 @@ public: //tolua_export
inline int GetUniqueID() { return m_UniqueID; } //tolua_export
inline bool IsDestroyed() { return m_bDestroyed; } //tolua_export
- void Destroy() { m_bDestroyed = true; } //tolua_export
+ void Destroy(); //tolua_export
+ void RemoveFromChunk( cChunk* a_Chunk ); // for internal use in cChunk
virtual void Tick(float a_Dt) = 0; //tolua_export
@@ -105,6 +107,7 @@ protected:
bool m_bDirtyOrientation;
bool m_bDestroyed;
+ bool m_bRemovedFromChunk;
ENUM_ENTITY_TYPE m_EntityType;
private:
diff --git a/source/cPlayer.cpp b/source/cPlayer.cpp
index 69e163629..85eec3e2d 100644
--- a/source/cPlayer.cpp
+++ b/source/cPlayer.cpp
@@ -55,6 +55,7 @@ struct cPlayer::sPlayerState
cPlayer::GroupList Groups;
std::string PlayerName;
+ std::string LoadedWorldName;
};
cPlayer::cPlayer(cClientHandle* a_Client, const char* a_PlayerName)
@@ -110,7 +111,7 @@ cPlayer::~cPlayer(void)
m_Inventory = 0;
}
delete m_pState;
- cRoot::Get()->GetWorld()->RemovePlayer( this ); // TODO - Remove from correct world? Or get rid of this?
+ GetWorld()->RemovePlayer( this ); // TODO - Remove from correct world? Or get rid of this?
}
@@ -702,6 +703,8 @@ bool cPlayer::LoadFromDisk() // TODO - This should also get/set/whatever the cor
m_Health = (short)root.get("health", 0 ).asInt();
m_Inventory->LoadFromJson(root["inventory"]);
+
+ m_pState->LoadedWorldName = root.get("world", "world").asString();
return true;
}
@@ -731,6 +734,7 @@ bool cPlayer::SaveToDisk()
root["rotation"] = JSON_PlayerRotation;
root["inventory"] = JSON_Inventory;
root["health"] = m_Health;
+ root["world"] = GetWorld()->GetName();
Json::StyledWriter writer;
std::string JsonData = writer.write( root );
@@ -769,3 +773,8 @@ const cPlayer::GroupList & cPlayer::GetGroups()
{
return m_pState->Groups;
}
+
+const char* cPlayer::GetLoadedWorldName()
+{
+ return m_pState->LoadedWorldName.c_str();
+} \ No newline at end of file
diff --git a/source/cPlayer.h b/source/cPlayer.h
index 4dedde727..fc546bd8d 100644
--- a/source/cPlayer.h
+++ b/source/cPlayer.h
@@ -56,7 +56,7 @@ public:
bool CanUseCommand( const char* a_Command ); //tolua_export
bool HasPermission( const char* a_Permission ); //tolua_export
const GroupList & GetGroups(); // >> EXPORTED IN MANUALBINDINGS <<
- bool IsInGroup( const char* a_Group ); //tolua_export
+ bool IsInGroup( const char* a_Group ); //tolua_export
std::string GetColor(); //tolua_export
@@ -73,6 +73,8 @@ public:
bool SaveToDisk();
bool LoadFromDisk();
+ const char* GetLoadedWorldName();
+
//Burning logic
bool m_bBurnable;
enum PMetaState{NORMAL,BURNING,CROUCHED,RIDING} e_EPMetaState;
diff --git a/source/cWorld.cpp b/source/cWorld.cpp
index a5f4bf1c3..c67998064 100644
--- a/source/cWorld.cpp
+++ b/source/cWorld.cpp
@@ -88,6 +88,7 @@ cWorld::~cWorld()
{
cEntity* Entity = *m_pState->m_AllEntities.begin();
m_pState->m_AllEntities.remove( Entity );
+ if( !Entity->IsDestroyed() ) Entity->Destroy();
RemoveEntity( Entity );
}
UnlockEntities();
diff --git a/source/cWorld.h b/source/cWorld.h
index 383ffaec3..10f73fae3 100644
--- a/source/cWorld.h
+++ b/source/cWorld.h
@@ -56,7 +56,6 @@ public:
cPlayer* GetPlayer( const char* a_PlayerName ); //tolua_export
void AddEntity( cEntity* a_Entity );
- void AddToRemoveEntityQueue( cEntity & a_Entity );
bool RemoveEntityFromChunk( cEntity & a_Entity, cChunk* a_CalledFrom = 0 );
EntityList & GetEntities();
@@ -129,6 +128,7 @@ private:
struct sWorldState;
sWorldState* m_pState;
+ void AddToRemoveEntityQueue( cEntity & a_Entity );
void RemoveEntity( cEntity* a_Entity );
void UnloadUnusedChunks();