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:
parent
40b5574144
commit
dada2bea27
@ -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 )
|
||||
|
@ -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;
|
||||
|
@ -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 )
|
||||
|
@ -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:
|
||||
|
@ -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();
|
||||
}
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user