1
0

Implemented end and nether portals

This commit is contained in:
Tiger Wang 2014-05-31 22:28:51 +01:00
parent 60a37c1370
commit 8bff3e5af2
23 changed files with 254 additions and 92 deletions

View File

@ -638,30 +638,22 @@ void cChunk::Tick(float a_Dt)
for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr) for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr)
{ {
// Mobs are tickes inside MobTick (as we don't have to tick them if they are far away from players) // Mobs are tickes inside MobTick (as we don't have to tick them if they are far away from players)
if (!((*itr)->IsMob())) // Don't tick things queued to be removed
if (!((*itr)->IsMob()) && (std::find(m_EntitiesToRemove.begin(), m_EntitiesToRemove.end(), (*itr)->GetUniqueID()) == m_EntitiesToRemove.end()))
{ {
(*itr)->Tick(a_Dt, *this); (*itr)->Tick(a_Dt, *this);
} }
} // for itr - m_Entitites[] } // for itr - m_Entitites[]
// Remove all entities that were scheduled for removal:
for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end();) for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end();)
{ {
if ((*itr)->IsDestroyed()) auto itr2 = std::find(m_EntitiesToRemove.begin(), m_EntitiesToRemove.end(), (*itr)->GetUniqueID());
{ if (itr2 != m_EntitiesToRemove.end())
LOGD("Destroying entity #%i (%s)", (*itr)->GetUniqueID(), (*itr)->GetClass()); {
cEntity * ToDelete = *itr; itr = m_Entities.erase(itr);
itr = m_Entities.erase(itr); m_EntitiesToRemove.erase(itr2);
delete ToDelete; }
continue; else if ( // If any entity moved out of the chunk, move it to the neighbor:
}
++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)->GetChunkX() != m_PosX) ||
((*itr)->GetChunkZ() != m_PosZ) ((*itr)->GetChunkZ() != m_PosZ)
) )
@ -671,9 +663,19 @@ void cChunk::Tick(float a_Dt)
} }
else else
{ {
++itr; if ((*itr)->IsDestroyed()) // Remove all entities that were scheduled for removal:
{
LOGD("Destroying entity #%i (%s)", (*itr)->GetUniqueID(), (*itr)->GetClass());
cEntity * ToDelete = *itr;
itr = m_Entities.erase(itr);
delete ToDelete;
}
else
{
++itr;
}
} }
} } // for itr - m_Entitites[]
ApplyWeatherToTop(); ApplyWeatherToTop();
} }
@ -1847,7 +1849,7 @@ void cChunk::RemoveBlockEntity( cBlockEntity* a_BlockEntity )
bool cChunk::AddClient(cClientHandle* a_Client) bool cChunk::AddClient(cClientHandle * a_Client)
{ {
for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr) for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{ {
@ -1878,7 +1880,7 @@ bool cChunk::AddClient(cClientHandle* a_Client)
void cChunk::RemoveClient( cClientHandle* a_Client ) void cChunk::RemoveClient(cClientHandle * a_Client)
{ {
for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr) for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{ {
@ -1886,12 +1888,12 @@ void cChunk::RemoveClient( cClientHandle* a_Client )
{ {
continue; continue;
} }
m_LoadedByClient.erase(itr); m_LoadedByClient.erase(itr);
if (!a_Client->IsDestroyed()) if (!a_Client->IsDestroyed())
{ {
for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr ) for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr)
{ {
/* /*
// DEBUG: // DEBUG:
@ -1911,7 +1913,7 @@ void cChunk::RemoveClient( cClientHandle* a_Client )
bool cChunk::HasClient( cClientHandle* a_Client ) bool cChunk::HasClient(cClientHandle* a_Client)
{ {
for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr) for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{ {
@ -1942,9 +1944,9 @@ void cChunk::AddEntity(cEntity * a_Entity)
{ {
MarkDirty(); MarkDirty();
} }
ASSERT(std::find(m_Entities.begin(), m_Entities.end(), a_Entity) == m_Entities.end()); // Not there already ASSERT(std::find(m_Entities.begin(), m_Entities.end(), a_Entity) == m_Entities.end()); // Not there already
m_Entities.push_back(a_Entity); m_Entities.push_back(a_Entity);
} }
@ -1954,17 +1956,12 @@ void cChunk::AddEntity(cEntity * a_Entity)
void cChunk::RemoveEntity(cEntity * a_Entity) void cChunk::RemoveEntity(cEntity * a_Entity)
{ {
size_t SizeBefore = m_Entities.size(); m_EntitiesToRemove.push_back(a_Entity->GetUniqueID());
m_Entities.remove(a_Entity);
size_t SizeAfter = m_Entities.size(); // Mark as dirty if it was a server-generated entity:
if (!a_Entity->IsPlayer())
if (SizeBefore != SizeAfter)
{ {
// Mark as dirty if it was a server-generated entity: MarkDirty();
if (!a_Entity->IsPlayer())
{
MarkDirty();
}
} }
} }
@ -1974,6 +1971,11 @@ void cChunk::RemoveEntity(cEntity * a_Entity)
bool cChunk::HasEntity(int a_EntityID) bool cChunk::HasEntity(int a_EntityID)
{ {
if (std::find(m_EntitiesToRemove.begin(), m_EntitiesToRemove.end(), a_EntityID) != m_EntitiesToRemove.end())
{
return false; // If EntitiesToRemove contains our ID, this chunk doesn't have it, as it should be removed soon
}
for (cEntityList::const_iterator itr = m_Entities.begin(), end = m_Entities.end(); itr != end; ++itr) for (cEntityList::const_iterator itr = m_Entities.begin(), end = m_Entities.end(); itr != end; ++itr)
{ {
if ((*itr)->GetUniqueID() == a_EntityID) if ((*itr)->GetUniqueID() == a_EntityID)

View File

@ -411,6 +411,7 @@ private:
// A critical section is not needed, because all chunk access is protected by its parent ChunkMap's csLayers // A critical section is not needed, because all chunk access is protected by its parent ChunkMap's csLayers
cClientHandleList m_LoadedByClient; cClientHandleList m_LoadedByClient;
cEntityList m_Entities; cEntityList m_Entities;
std::vector<int> m_EntitiesToRemove;
cBlockEntityList m_BlockEntities; cBlockEntityList m_BlockEntities;
/** Number of times the chunk has been requested to stay (by various cChunkStay objects); if zero, the chunk can be unloaded */ /** Number of times the chunk has been requested to stay (by various cChunkStay objects); if zero, the chunk can be unloaded */

View File

@ -125,7 +125,6 @@ cClientHandle::~cClientHandle()
} }
if (World != NULL) if (World != NULL)
{ {
World->RemovePlayer(m_Player);
m_Player->Destroy(); m_Player->Destroy();
} }
delete m_Player; delete m_Player;
@ -1754,7 +1753,7 @@ void cClientHandle::MoveToWorld(cWorld & a_World, bool a_SendRespawnPacket)
if (a_SendRespawnPacket) if (a_SendRespawnPacket)
{ {
SendRespawn(); SendRespawn(a_World);
} }
cWorld * World = m_Player->GetWorld(); cWorld * World = m_Player->GetWorld();
@ -2373,9 +2372,9 @@ void cClientHandle::SendRemoveEntityEffect(const cEntity & a_Entity, int a_Effec
void cClientHandle::SendRespawn(void) void cClientHandle::SendRespawn(const cWorld & a_World)
{ {
m_Protocol->SendRespawn(); m_Protocol->SendRespawn(a_World);
} }

View File

@ -149,7 +149,7 @@ public:
void SendPlayerSpawn (const cPlayer & a_Player); void SendPlayerSpawn (const cPlayer & a_Player);
void SendPluginMessage (const AString & a_Channel, const AString & a_Message); // Exported in ManualBindings.cpp void SendPluginMessage (const AString & a_Channel, const AString & a_Message); // Exported in ManualBindings.cpp
void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID); void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID);
void SendRespawn (void); void SendRespawn (const cWorld & a_World);
void SendExperience (void); void SendExperience (void);
void SendExperienceOrb (const cExpOrb & a_ExpOrb); void SendExperienceOrb (const cExpOrb & a_ExpOrb);
void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode); void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode);

View File

@ -629,6 +629,7 @@ void cEntity::Tick(float a_Dt, cChunk & a_Chunk)
// Handle drowning // Handle drowning
HandleAir(); HandleAir();
} }
DetectPortal();
// None of the above functions change position, we remain in the chunk of NextChunk // None of the above functions change position, we remain in the chunk of NextChunk
HandlePhysics(a_Dt, *NextChunk); HandlePhysics(a_Dt, *NextChunk);
@ -1039,6 +1040,122 @@ void cEntity::DetectCacti(void)
void cEntity::DetectPortal()
{
int X = POSX_TOINT, Y = POSY_TOINT, Z = POSZ_TOINT;
if ((Y > 0) && (Y < cChunkDef::Height))
{
switch (GetWorld()->GetBlock(X, Y, Z))
{
case E_BLOCK_NETHER_PORTAL:
{
switch (GetWorld()->GetDimension())
{
case dimNether:
{
AString OverworldName = GetWorld()->GetName().substr(0, GetWorld()->GetName().size() - 7);
cFile::CreateFolder(FILE_IO_PREFIX + OverworldName);
cIniFile File;
File.ReadFile(OverworldName + "/world.ini");
File.SetValue("General", "Dimension", "Overworld");
File.WriteFile(OverworldName + "/world.ini");
MoveToWorld(OverworldName, cRoot::Get()->CreateAndInitializeWorld(OverworldName));
break;
}
case dimOverworld:
{
AString NetherWorldName = GetWorld()->GetName() + "_nether";
cFile::CreateFolder(FILE_IO_PREFIX + NetherWorldName);
cIniFile File;
File.ReadFile(NetherWorldName + "/world.ini");
File.SetValue("General", "Dimension", "Nether");
File.WriteFile(NetherWorldName + "/world.ini");
MoveToWorld(NetherWorldName, cRoot::Get()->CreateAndInitializeWorld(NetherWorldName));
break;
}
default: break;
}
break;
}
case E_BLOCK_END_PORTAL:
{
switch (GetWorld()->GetDimension())
{
case dimEnd:
{
AString OverworldName = GetWorld()->GetName().substr(0, GetWorld()->GetName().size() - 4);
cFile::CreateFolder(FILE_IO_PREFIX + OverworldName);
cIniFile File;
File.ReadFile(OverworldName + "/world.ini");
File.SetValue("General", "Dimension", "Overworld");
File.WriteFile(OverworldName + "/world.ini");
MoveToWorld(OverworldName, cRoot::Get()->CreateAndInitializeWorld(OverworldName));
break;
}
case dimOverworld:
{
AString EndWorldName = GetWorld()->GetName() + "_end";
cFile::CreateFolder(FILE_IO_PREFIX + EndWorldName);
cIniFile File;
File.ReadFile(EndWorldName + "/world.ini");
File.SetValue("General", "Dimension", "End");
File.WriteFile(EndWorldName + "/world.ini");
MoveToWorld(EndWorldName, cRoot::Get()->CreateAndInitializeWorld(EndWorldName));
break;
}
default: break;
}
}
default: break;
}
}
}
bool cEntity::MoveToWorld(const AString & a_WorldName, cWorld * a_World)
{
cWorld * World;
if (a_World == NULL)
{
World = cRoot::Get()->GetWorld(a_WorldName);
if (World == NULL)
{
LOG("%s: Couldn't find world \"%s\".", __FUNCTION__, a_WorldName);
return false;
}
}
else
{
World = a_World;
}
if (GetWorld() == World)
{
return false;
}
// Remove all links to the old world
GetWorld()->RemoveEntity(this);
GetWorld()->BroadcastDestroyEntity(*this);
// Add to all the necessary parts of the new world
SetWorld(World);
World->AddEntity(this);
return true;
}
void cEntity::SetSwimState(cChunk & a_Chunk) void cEntity::SetSwimState(cChunk & a_Chunk)
{ {
int RelY = (int)floor(GetPosY() + 0.1); int RelY = (int)floor(GetPosY() + 0.1);

View File

@ -323,6 +323,9 @@ public:
/** Detects the time for application of cacti damage */ /** Detects the time for application of cacti damage */
virtual void DetectCacti(void); virtual void DetectCacti(void);
/** Detects whether we are in a portal block and begins teleportation procedures if so */
virtual void DetectPortal(void);
/// Handles when the entity is in the void /// Handles when the entity is in the void
virtual void TickInVoid(cChunk & a_Chunk); virtual void TickInVoid(cChunk & a_Chunk);
@ -365,6 +368,9 @@ public:
/// Teleports to the coordinates specified /// Teleports to the coordinates specified
virtual void TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ); virtual void TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ);
/** Moves entity to specified world */
virtual bool MoveToWorld(const AString & a_WorldName, cWorld * a_World = NULL);
// tolua_end // tolua_end

View File

@ -134,7 +134,7 @@ cPlayer::~cPlayer(void)
SaveToDisk(); SaveToDisk();
m_World->RemovePlayer( this ); m_World->RemovePlayer(this);
m_ClientHandle = NULL; m_ClientHandle = NULL;
@ -150,8 +150,6 @@ cPlayer::~cPlayer(void)
void cPlayer::Destroyed() void cPlayer::Destroyed()
{ {
CloseWindow(false); CloseWindow(false);
m_ClientHandle = NULL;
} }
@ -952,7 +950,7 @@ void cPlayer::Respawn(void)
m_LifetimeTotalXp = 0; m_LifetimeTotalXp = 0;
// ToDo: send score to client? How? // ToDo: send score to client? How?
m_ClientHandle->SendRespawn(); m_ClientHandle->SendRespawn(*GetWorld());
// Extinguish the fire: // Extinguish the fire:
StopBurning(); StopBurning();
@ -1574,12 +1572,25 @@ void cPlayer::TossItems(const cItems & a_Items)
bool cPlayer::MoveToWorld(const char * a_WorldName) bool cPlayer::MoveToWorld(const AString & a_WorldName, cWorld * a_World)
{ {
cWorld * World = cRoot::Get()->GetWorld(a_WorldName); cWorld * World;
if (World == NULL) if (a_World == NULL)
{
World = cRoot::Get()->GetWorld(a_WorldName);
if (World == NULL)
{
LOG("%s: Couldn't find world \"%s\".", __FUNCTION__, a_WorldName);
return false;
}
}
else
{
World = a_World;
}
if (GetWorld() == World)
{ {
LOG("%s: Couldn't find world \"%s\".", __FUNCTION__, a_WorldName);
return false; return false;
} }
@ -1588,11 +1599,11 @@ bool cPlayer::MoveToWorld(const char * a_WorldName)
// Remove all links to the old world // Remove all links to the old world
m_World->RemovePlayer(this); m_World->RemovePlayer(this);
m_ClientHandle->RemoveFromAllChunks(); m_ClientHandle->RemoveFromAllChunks();
m_World->RemoveEntity(this);
// If the dimension is different, we can send the respawn packet // If the dimension is different, we can send the respawn packet
// http://wiki.vg/Protocol#0x09 says "don't send if dimension is the same" as of 2013_07_02 // http://wiki.vg/Protocol#0x09 says "don't send if dimension is the same" as of 2013_07_02
m_ClientHandle->MoveToWorld(*World, (OldDimension != World->GetDimension())); bool SendRespawn = OldDimension != World->GetDimension();
m_ClientHandle->MoveToWorld(*World, SendRespawn);
// Add player to all the necessary parts of the new world // Add player to all the necessary parts of the new world
SetWorld(World); SetWorld(World);
@ -1600,6 +1611,11 @@ bool cPlayer::MoveToWorld(const char * a_WorldName)
World->AddEntity(this); World->AddEntity(this);
World->AddPlayer(this); World->AddPlayer(this);
if (SendRespawn)
{
GetClientHandle()->SendPlayerMoveLook();
}
return true; return true;
} }

View File

@ -328,7 +328,7 @@ public:
void SetVisible( bool a_bVisible ); // tolua_export void SetVisible( bool a_bVisible ); // tolua_export
bool IsVisible(void) const { return m_bVisible; } // tolua_export bool IsVisible(void) const { return m_bVisible; } // tolua_export
bool MoveToWorld(const char * a_WorldName); // tolua_export virtual bool MoveToWorld(const AString & a_WorldName, cWorld * a_World = NULL) override; // tolua_export
bool SaveToDisk(void); bool SaveToDisk(void);
bool LoadFromDisk(void); bool LoadFromDisk(void);

View File

@ -95,7 +95,7 @@ void cBioGenConstant::GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap
void cBioGenConstant::InitializeBiomeGen(cIniFile & a_IniFile) void cBioGenConstant::InitializeBiomeGen(cIniFile & a_IniFile)
{ {
AString Biome = a_IniFile.GetValueSet("Generator", "ConstantBiome", "Plains"); AString Biome = a_IniFile.GetValueSet("Generator", "ConstantBiome", "");
m_Biome = StringToBiome(Biome); m_Biome = StringToBiome(Biome);
if (m_Biome == biInvalidBiome) if (m_Biome == biInvalidBiome)
{ {

View File

@ -39,7 +39,6 @@ cTerrainCompositionGen * cTerrainCompositionGen::CreateCompositionGen(cIniFile &
{ {
LOGWARN("[Generator] CompositionGen value not set in world.ini, using \"Biomal\"."); LOGWARN("[Generator] CompositionGen value not set in world.ini, using \"Biomal\".");
CompoGenName = "Biomal"; CompoGenName = "Biomal";
a_IniFile.SetValue("Generator", "CompositionGen", CompoGenName);
} }
cTerrainCompositionGen * res = NULL; cTerrainCompositionGen * res = NULL;
@ -93,7 +92,6 @@ cTerrainCompositionGen * cTerrainCompositionGen::CreateCompositionGen(cIniFile &
else else
{ {
LOGWARN("Unknown CompositionGen \"%s\", using \"Biomal\" instead.", CompoGenName.c_str()); LOGWARN("Unknown CompositionGen \"%s\", using \"Biomal\" instead.", CompoGenName.c_str());
a_IniFile.DeleteValue("Generator", "CompositionGen");
a_IniFile.SetValue("Generator", "CompositionGen", "Biomal"); a_IniFile.SetValue("Generator", "CompositionGen", "Biomal");
return CreateCompositionGen(a_IniFile, a_BiomeGen, a_HeightGen, a_Seed); return CreateCompositionGen(a_IniFile, a_BiomeGen, a_HeightGen, a_Seed);
} }
@ -291,19 +289,7 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
int Seed = m_ChunkGenerator.GetSeed(); int Seed = m_ChunkGenerator.GetSeed();
eDimension Dimension = StringToDimension(a_IniFile.GetValue("General", "Dimension", "Overworld")); eDimension Dimension = StringToDimension(a_IniFile.GetValue("General", "Dimension", "Overworld"));
// Older configuration used "Structures" in addition to "Finishers"; we don't distinguish between the two anymore (#398) AString Finishers = a_IniFile.GetValueSet("Generator", "Finishers", "");
// Therefore, we load Structures from the ini file for compatibility, but move its contents over to Finishers:
AString Structures = a_IniFile.GetValue("Generator", "Structures", "");
AString Finishers = a_IniFile.GetValueSet("Generator", "Finishers", "Ravines, WormNestCaves, WaterLakes, LavaLakes, OreNests, Trees, SprinkleFoliage, Ice, Snow, Lilypads, BottomLava, DeadBushes, PreSimulator");
if (!Structures.empty())
{
LOGINFO("[Generator].Structures is deprecated, moving the contents to [Generator].Finishers.");
// Structures used to generate before Finishers, so place them first:
Structures.append(", ");
Finishers = Structures + Finishers;
a_IniFile.SetValue("Generator", "Finishers", Finishers);
}
a_IniFile.DeleteValue("Generator", "Structures");
// Create all requested finishers: // Create all requested finishers:
AStringVector Str = StringSplitAndTrim(Finishers, ","); AStringVector Str = StringSplitAndTrim(Finishers, ",");

View File

@ -50,7 +50,7 @@ cEndGen::cEndGen(int a_Seed) :
void cEndGen::Initialize(cIniFile & a_IniFile) void cEndGen::InitializeCompoGen(cIniFile & a_IniFile)
{ {
m_IslandSizeX = a_IniFile.GetValueSetI("Generator", "EndGenIslandSizeX", m_IslandSizeX); m_IslandSizeX = a_IniFile.GetValueSetI("Generator", "EndGenIslandSizeX", m_IslandSizeX);
m_IslandSizeY = a_IniFile.GetValueSetI("Generator", "EndGenIslandSizeY", m_IslandSizeY); m_IslandSizeY = a_IniFile.GetValueSetI("Generator", "EndGenIslandSizeY", m_IslandSizeY);

View File

@ -23,8 +23,6 @@ class cEndGen :
public: public:
cEndGen(int a_Seed); cEndGen(int a_Seed);
void Initialize(cIniFile & a_IniFile);
protected: protected:
/// Seed for the noise /// Seed for the noise
@ -66,4 +64,5 @@ protected:
// cTerrainCompositionGen overrides: // cTerrainCompositionGen overrides:
virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc) override; virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc) override;
virtual void InitializeCompoGen(cIniFile & a_IniFile) override;
} ; } ;

View File

@ -100,7 +100,7 @@ public:
virtual void SendPlayerSpawn (const cPlayer & a_Player) = 0; virtual void SendPlayerSpawn (const cPlayer & a_Player) = 0;
virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) = 0; virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) = 0;
virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) = 0; virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) = 0;
virtual void SendRespawn (void) = 0; virtual void SendRespawn (const cWorld & a_World) = 0;
virtual void SendExperience (void) = 0; virtual void SendExperience (void) = 0;
virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) = 0; virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) = 0;
virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) = 0; virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) = 0;

View File

@ -831,12 +831,12 @@ void cProtocol125::SendRemoveEntityEffect(const cEntity & a_Entity, int a_Effect
void cProtocol125::SendRespawn(void) void cProtocol125::SendRespawn(const cWorld & a_World)
{ {
cCSLock Lock(m_CSPacket); cCSLock Lock(m_CSPacket);
cPlayer * Player = m_Client->GetPlayer(); cPlayer * Player = m_Client->GetPlayer();
WriteByte (PACKET_RESPAWN); WriteByte (PACKET_RESPAWN);
WriteInt ((int)(Player->GetWorld()->GetDimension())); WriteInt ((int)(a_World.GetDimension()));
WriteByte (2); // TODO: Difficulty; 2 = Normal WriteByte (2); // TODO: Difficulty; 2 = Normal
WriteChar ((char)Player->GetGameMode()); WriteChar ((char)Player->GetGameMode());
WriteShort (256); // Current world height WriteShort (256); // Current world height

View File

@ -72,7 +72,7 @@ public:
virtual void SendPlayerSpawn (const cPlayer & a_Player) override; virtual void SendPlayerSpawn (const cPlayer & a_Player) override;
virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) override; virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) override;
virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override; virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override;
virtual void SendRespawn (void) override; virtual void SendRespawn (const cWorld & a_World) override;
virtual void SendExperience (void) override; virtual void SendExperience (void) override;
virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override; virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override;
virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override; virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override;

View File

@ -158,10 +158,10 @@ void cProtocol161::SendPlayerMaxSpeed(void)
void cProtocol161::SendRespawn(void) void cProtocol161::SendRespawn(const cWorld & a_World)
{ {
// Besides sending the respawn, we need to also send the player max speed, otherwise the client reverts to super-fast // Besides sending the respawn, we need to also send the player max speed, otherwise the client reverts to super-fast
super::SendRespawn(); super::SendRespawn(a_World);
SendPlayerMaxSpeed(); SendPlayerMaxSpeed();
} }

View File

@ -42,7 +42,7 @@ protected:
virtual void SendGameMode (eGameMode a_GameMode) override; virtual void SendGameMode (eGameMode a_GameMode) override;
virtual void SendHealth (void) override; virtual void SendHealth (void) override;
virtual void SendPlayerMaxSpeed(void) override; virtual void SendPlayerMaxSpeed(void) override;
virtual void SendRespawn (void) override; virtual void SendRespawn (const cWorld & a_World) override;
virtual void SendWindowOpen (const cWindow & a_Window) override; virtual void SendWindowOpen (const cWindow & a_Window) override;
virtual int ParseEntityAction (void) override; virtual int ParseEntityAction (void) override;

View File

@ -983,11 +983,11 @@ void cProtocol172::SendRemoveEntityEffect(const cEntity & a_Entity, int a_Effect
void cProtocol172::SendRespawn(void) void cProtocol172::SendRespawn(const cWorld & a_World)
{ {
cPacketizer Pkt(*this, 0x07); // Respawn packet cPacketizer Pkt(*this, 0x07); // Respawn packet
cPlayer * Player = m_Client->GetPlayer(); cPlayer * Player = m_Client->GetPlayer();
Pkt.WriteInt(Player->GetWorld()->GetDimension()); Pkt.WriteInt((int)a_World.GetDimension());
Pkt.WriteByte(2); // TODO: Difficulty (set to Normal) Pkt.WriteByte(2); // TODO: Difficulty (set to Normal)
Pkt.WriteByte((Byte)Player->GetEffectiveGameMode()); Pkt.WriteByte((Byte)Player->GetEffectiveGameMode());
Pkt.WriteString("default"); Pkt.WriteString("default");

View File

@ -104,7 +104,7 @@ public:
virtual void SendPlayerSpawn (const cPlayer & a_Player) override; virtual void SendPlayerSpawn (const cPlayer & a_Player) override;
virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) override; virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) override;
virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override; virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override;
virtual void SendRespawn (void) override; virtual void SendRespawn (const cWorld & a_World) override;
virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) override; // a_Src coords are Block * 8 virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) override; // a_Src coords are Block * 8
virtual void SendExperience (void) override; virtual void SendExperience (void) override;
virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override; virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override;

View File

@ -555,10 +555,10 @@ void cProtocolRecognizer::SendRemoveEntityEffect(const cEntity & a_Entity, int a
void cProtocolRecognizer::SendRespawn(void) void cProtocolRecognizer::SendRespawn(const cWorld & a_World)
{ {
ASSERT(m_Protocol != NULL); ASSERT(m_Protocol != NULL);
m_Protocol->SendRespawn(); m_Protocol->SendRespawn(a_World);
} }

View File

@ -107,7 +107,7 @@ public:
virtual void SendPlayerSpawn (const cPlayer & a_Player) override; virtual void SendPlayerSpawn (const cPlayer & a_Player) override;
virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) override; virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) override;
virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override; virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override;
virtual void SendRespawn (void) override; virtual void SendRespawn (const cWorld & a_World) override;
virtual void SendExperience (void) override; virtual void SendExperience (void) override;
virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override; virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override;
virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override; virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override;

View File

@ -320,7 +320,7 @@ cWorld * cRoot::CreateAndInitializeWorld(const AString & a_WorldName)
{ {
return NULL; return NULL;
} }
cWorld* NewWorld = new cWorld(a_WorldName.c_str()); cWorld * NewWorld = new cWorld(a_WorldName.c_str());
m_WorldsByName[a_WorldName] = NewWorld; m_WorldsByName[a_WorldName] = NewWorld;
NewWorld->Start(); NewWorld->Start();
NewWorld->InitializeSpawn(); NewWorld->InitializeSpawn();
@ -372,7 +372,7 @@ void cRoot::UnloadWorlds(void)
cWorld* cRoot::GetDefaultWorld() cWorld * cRoot::GetDefaultWorld()
{ {
return m_pDefaultWorld; return m_pDefaultWorld;
} }
@ -381,12 +381,14 @@ cWorld* cRoot::GetDefaultWorld()
cWorld* cRoot::GetWorld( const AString & a_WorldName ) cWorld * cRoot::GetWorld(const AString & a_WorldName)
{ {
WorldMap::iterator itr = m_WorldsByName.find( a_WorldName ); WorldMap::iterator itr = m_WorldsByName.find(a_WorldName);
if( itr != m_WorldsByName.end() ) if (itr != m_WorldsByName.end())
{
return itr->second; return itr->second;
return 0; }
return NULL;
} }
@ -398,9 +400,12 @@ bool cRoot::ForEachWorld(cWorldListCallback & a_Callback)
for (WorldMap::iterator itr = m_WorldsByName.begin(), itr2 = itr; itr != m_WorldsByName.end(); itr = itr2) for (WorldMap::iterator itr = m_WorldsByName.begin(), itr2 = itr; itr != m_WorldsByName.end(); itr = itr2)
{ {
++itr2; ++itr2;
if (a_Callback.Item(itr->second)) if (itr->second != NULL)
{ {
return false; if (a_Callback.Item(itr->second))
{
return false;
}
} }
} }
return true; return true;

View File

@ -571,6 +571,37 @@ void cWorld::Start(void)
m_GameMode = (eGameMode) Clamp(GameMode, (int)gmSurvival, (int)gmAdventure); m_GameMode = (eGameMode) Clamp(GameMode, (int)gmSurvival, (int)gmAdventure);
m_TNTShrapnelLevel = (eShrapnelLevel)Clamp(TNTShrapnelLevel, (int)slNone, (int)slAll); m_TNTShrapnelLevel = (eShrapnelLevel)Clamp(TNTShrapnelLevel, (int)slNone, (int)slAll);
switch (GetDimension())
{
case dimEnd:
{
IniFile.GetValueSet("Generator", "BiomeGen", "Constant");
IniFile.GetValueSet("Generator", "ConstantBiome", "End");
IniFile.GetValueSet("Generator", "HeightGen", "Biomal");
IniFile.GetValueSet("Generator", "CompositionGen", "End");
break;
}
case dimOverworld:
{
IniFile.GetValueSet("Generator", "BiomeGen", "MultiStepMap");
IniFile.GetValueSet("Generator", "HeightGen", "DistortedHeightmap");
IniFile.GetValueSet("Generator", "CompositionGen", "DistortedHeightmap");
IniFile.GetValueSet("Generator", "Finishers", "Ravines, WormNestCaves, WaterLakes, WaterSprings, LavaLakes, LavaSprings, OreNests, Mineshafts, Trees, SprinkleFoliage, Ice, Snow, Lilypads, BottomLava, DeadBushes, PreSimulator");
break;
}
case dimNether:
{
IniFile.GetValueSet("Generator", "BiomeGen", "Constant");
IniFile.GetValueSet("Generator", "ConstantBiome", "Nether");
IniFile.GetValueSet("Generator", "HeightGen", "Flat");
IniFile.GetValueSet("Generator", "FlatHeight", "128");
IniFile.GetValueSet("Generator", "CompositionGen", "Nether");
IniFile.GetValueSet("Generator", "Finishers", "WormNestCaves, BottomLava, LavaSprings, NetherClumpFoliage, NetherForts, PreSimulator");
IniFile.GetValueSet("Generator", "BottomLavaHeight", "30");
break;
}
}
// Load allowed mobs: // Load allowed mobs:
const char * DefaultMonsters = ""; const char * DefaultMonsters = "";
switch (m_Dimension) switch (m_Dimension)