1
0
Fork 0

Fixed some "Entity was not found in any chunk!" warnings

Player's current world is saved in the player file. When a player joins the server, the player joins the last world he was in.
It seems MCServer can finally run multiple worlds! It just needs functionality to switch between them

git-svn-id: http://mc-server.googlecode.com/svn/trunk@46 0a769ca7-a7f5-676a-18bf-c427514a06d6
This commit is contained in:
faketruth 2011-11-02 20:19:57 +00:00
parent 40b5574144
commit dada2bea27
8 changed files with 74 additions and 28 deletions

View File

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

View File

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

View File

@ -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()
{
if( !m_bDestroyed || !m_bRemovedFromChunk )
{
LOGERROR("ERROR: Entity deallocated without being destroyed %i or unlinked %i", m_bDestroyed, m_bRemovedFromChunk );
}
delete m_Referencers;
delete m_References;
if( m_World )
{
cChunk* Chunk = m_World->GetChunkUnreliable( m_ChunkX, m_ChunkY, m_ChunkZ );
if( Chunk )
{
cPacket_DestroyEntity DestroyEntity( this );
Chunk->Broadcast( DestroyEntity );
Chunk->RemoveEntity( *this );
}
}
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 )

View File

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

View File

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

View File

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

View File

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

View File

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