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();
|
m_pState->m_BlockEntities.clear();
|
||||||
|
|
||||||
LockEntities();
|
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();
|
UnlockEntities();
|
||||||
|
|
||||||
if( m_EntitiesCriticalSection )
|
if( m_EntitiesCriticalSection )
|
||||||
@ -1027,14 +1032,17 @@ void cChunk::RemoveClient( cClientHandle* a_Client )
|
|||||||
{
|
{
|
||||||
m_pState->m_LoadedByClient.remove( a_Client );
|
m_pState->m_LoadedByClient.remove( a_Client );
|
||||||
|
|
||||||
LockEntities();
|
if( !a_Client->IsDestroyed() )
|
||||||
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() );
|
LockEntities();
|
||||||
cPacket_DestroyEntity DestroyEntity( *itr );
|
for( EntityList::iterator itr = m_pState->m_Entities.begin(); itr != m_pState->m_Entities.end(); ++itr )
|
||||||
a_Client->Send( DestroyEntity );
|
{
|
||||||
|
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 )
|
void cChunk::AddEntity( cEntity & a_Entity )
|
||||||
|
@ -432,7 +432,9 @@ void cClientHandle::HandlePacket( cPacket* a_Packet )
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Now initialize player (adds to entity list etc.)
|
// 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 )
|
// Broadcasts to all but this ( this is actually handled in cChunk.cpp, after entity is added to the chunk )
|
||||||
//m_Player->SpawnOn( 0 );
|
//m_Player->SpawnOn( 0 );
|
||||||
@ -937,13 +939,15 @@ void cClientHandle::Tick(float a_Dt)
|
|||||||
{
|
{
|
||||||
m_bSendLoginResponse = false;
|
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)
|
// Spawn player (only serversided, so data is loaded)
|
||||||
m_Player = new cPlayer( this, GetUsername() ); // !!DO NOT INITIALIZE!! <- is done after receiving MoveLook Packet
|
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.
|
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
|
// Return a server login packet
|
||||||
cPacket_Login LoginResponse;
|
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_bDestroyed( false )
|
||||||
, m_EntityType( E_ENTITY )
|
, m_EntityType( E_ENTITY )
|
||||||
, m_World( 0 )
|
, m_World( 0 )
|
||||||
|
, m_bRemovedFromChunk( false )
|
||||||
{
|
{
|
||||||
m_EntityCount++;
|
m_EntityCount++;
|
||||||
m_UniqueID = 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()
|
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_Referencers;
|
||||||
delete m_References;
|
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_Pos;
|
||||||
delete m_Rot;
|
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 );
|
CLASS_DEF_GETCLASS( cEntity );
|
||||||
bool cEntity::IsA( const char* a_EntityType )
|
bool cEntity::IsA( const char* a_EntityType )
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
CLASS_DEF_ISA( classname, superclass ) \
|
CLASS_DEF_ISA( classname, superclass ) \
|
||||||
CLASS_DEF_GETCLASS( classname )
|
CLASS_DEF_GETCLASS( classname )
|
||||||
|
|
||||||
|
class cChunk;
|
||||||
class cWorld;
|
class cWorld;
|
||||||
class cReferenceManager;
|
class cReferenceManager;
|
||||||
class Vector3d;
|
class Vector3d;
|
||||||
@ -76,7 +77,8 @@ public: //tolua_export
|
|||||||
inline int GetUniqueID() { return m_UniqueID; } //tolua_export
|
inline int GetUniqueID() { return m_UniqueID; } //tolua_export
|
||||||
inline bool IsDestroyed() { return m_bDestroyed; } //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
|
virtual void Tick(float a_Dt) = 0; //tolua_export
|
||||||
|
|
||||||
@ -105,6 +107,7 @@ protected:
|
|||||||
bool m_bDirtyOrientation;
|
bool m_bDirtyOrientation;
|
||||||
|
|
||||||
bool m_bDestroyed;
|
bool m_bDestroyed;
|
||||||
|
bool m_bRemovedFromChunk;
|
||||||
|
|
||||||
ENUM_ENTITY_TYPE m_EntityType;
|
ENUM_ENTITY_TYPE m_EntityType;
|
||||||
private:
|
private:
|
||||||
|
@ -55,6 +55,7 @@ struct cPlayer::sPlayerState
|
|||||||
cPlayer::GroupList Groups;
|
cPlayer::GroupList Groups;
|
||||||
|
|
||||||
std::string PlayerName;
|
std::string PlayerName;
|
||||||
|
std::string LoadedWorldName;
|
||||||
};
|
};
|
||||||
|
|
||||||
cPlayer::cPlayer(cClientHandle* a_Client, const char* a_PlayerName)
|
cPlayer::cPlayer(cClientHandle* a_Client, const char* a_PlayerName)
|
||||||
@ -110,7 +111,7 @@ cPlayer::~cPlayer(void)
|
|||||||
m_Inventory = 0;
|
m_Inventory = 0;
|
||||||
}
|
}
|
||||||
delete m_pState;
|
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_Health = (short)root.get("health", 0 ).asInt();
|
||||||
m_Inventory->LoadFromJson(root["inventory"]);
|
m_Inventory->LoadFromJson(root["inventory"]);
|
||||||
|
|
||||||
|
m_pState->LoadedWorldName = root.get("world", "world").asString();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -731,6 +734,7 @@ bool cPlayer::SaveToDisk()
|
|||||||
root["rotation"] = JSON_PlayerRotation;
|
root["rotation"] = JSON_PlayerRotation;
|
||||||
root["inventory"] = JSON_Inventory;
|
root["inventory"] = JSON_Inventory;
|
||||||
root["health"] = m_Health;
|
root["health"] = m_Health;
|
||||||
|
root["world"] = GetWorld()->GetName();
|
||||||
|
|
||||||
Json::StyledWriter writer;
|
Json::StyledWriter writer;
|
||||||
std::string JsonData = writer.write( root );
|
std::string JsonData = writer.write( root );
|
||||||
@ -769,3 +773,8 @@ const cPlayer::GroupList & cPlayer::GetGroups()
|
|||||||
{
|
{
|
||||||
return m_pState->Groups;
|
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 CanUseCommand( const char* a_Command ); //tolua_export
|
||||||
bool HasPermission( const char* a_Permission ); //tolua_export
|
bool HasPermission( const char* a_Permission ); //tolua_export
|
||||||
const GroupList & GetGroups(); // >> EXPORTED IN MANUALBINDINGS <<
|
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
|
std::string GetColor(); //tolua_export
|
||||||
|
|
||||||
@ -73,6 +73,8 @@ public:
|
|||||||
bool SaveToDisk();
|
bool SaveToDisk();
|
||||||
bool LoadFromDisk();
|
bool LoadFromDisk();
|
||||||
|
|
||||||
|
const char* GetLoadedWorldName();
|
||||||
|
|
||||||
//Burning logic
|
//Burning logic
|
||||||
bool m_bBurnable;
|
bool m_bBurnable;
|
||||||
enum PMetaState{NORMAL,BURNING,CROUCHED,RIDING} e_EPMetaState;
|
enum PMetaState{NORMAL,BURNING,CROUCHED,RIDING} e_EPMetaState;
|
||||||
|
@ -88,6 +88,7 @@ cWorld::~cWorld()
|
|||||||
{
|
{
|
||||||
cEntity* Entity = *m_pState->m_AllEntities.begin();
|
cEntity* Entity = *m_pState->m_AllEntities.begin();
|
||||||
m_pState->m_AllEntities.remove( Entity );
|
m_pState->m_AllEntities.remove( Entity );
|
||||||
|
if( !Entity->IsDestroyed() ) Entity->Destroy();
|
||||||
RemoveEntity( Entity );
|
RemoveEntity( Entity );
|
||||||
}
|
}
|
||||||
UnlockEntities();
|
UnlockEntities();
|
||||||
|
@ -56,7 +56,6 @@ public:
|
|||||||
cPlayer* GetPlayer( const char* a_PlayerName ); //tolua_export
|
cPlayer* GetPlayer( const char* a_PlayerName ); //tolua_export
|
||||||
|
|
||||||
void AddEntity( cEntity* a_Entity );
|
void AddEntity( cEntity* a_Entity );
|
||||||
void AddToRemoveEntityQueue( cEntity & a_Entity );
|
|
||||||
bool RemoveEntityFromChunk( cEntity & a_Entity, cChunk* a_CalledFrom = 0 );
|
bool RemoveEntityFromChunk( cEntity & a_Entity, cChunk* a_CalledFrom = 0 );
|
||||||
EntityList & GetEntities();
|
EntityList & GetEntities();
|
||||||
|
|
||||||
@ -129,6 +128,7 @@ private:
|
|||||||
struct sWorldState;
|
struct sWorldState;
|
||||||
sWorldState* m_pState;
|
sWorldState* m_pState;
|
||||||
|
|
||||||
|
void AddToRemoveEntityQueue( cEntity & a_Entity );
|
||||||
void RemoveEntity( cEntity* a_Entity );
|
void RemoveEntity( cEntity* a_Entity );
|
||||||
void UnloadUnusedChunks();
|
void UnloadUnusedChunks();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user