From cea3a8e7e8cbf45f709ec63a096cf07b92c87073 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Thu, 29 May 2014 16:58:40 +0100 Subject: Cauldrons fill --- src/Blocks/BlockCauldron.h | 14 ++++++++++++++ src/Blocks/WorldInterface.h | 3 +++ src/Chunk.cpp | 1 - src/World.h | 4 ++-- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/Blocks/BlockCauldron.h b/src/Blocks/BlockCauldron.h index 41b79b6c3..8b5cd9ccb 100644 --- a/src/Blocks/BlockCauldron.h +++ b/src/Blocks/BlockCauldron.h @@ -58,6 +58,20 @@ public: { return true; } + + virtual void OnUpdate(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_PluginInterface, cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ) override + { + if (!a_WorldInterface.IsWeatherWet()) + { + return; + } + + NIBBLETYPE Meta = a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ); + if (Meta < 3) + { + a_Chunk.SetMeta(a_RelX, a_RelY, a_RelZ, Meta + 1); + } + } } ; diff --git a/src/Blocks/WorldInterface.h b/src/Blocks/WorldInterface.h index bfbb053d9..08600d502 100644 --- a/src/Blocks/WorldInterface.h +++ b/src/Blocks/WorldInterface.h @@ -37,4 +37,7 @@ public: virtual void SetTimeOfDay(Int64 a_TimeOfDay) = 0; + /** Returns true if the current weather has any precipitation - rain or storm */ + virtual bool IsWeatherWet(void) const = 0; + }; diff --git a/src/Chunk.cpp b/src/Chunk.cpp index ca536e89a..4506cfcc5 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -961,7 +961,6 @@ void cChunk::ApplyWeatherToTop() } break; } // case (snowy biomes) - // TODO: Rainy biomes should check for farmland and cauldrons default: { break; diff --git a/src/World.h b/src/World.h index 86cbb3e7e..067e18547 100644 --- a/src/World.h +++ b/src/World.h @@ -690,8 +690,8 @@ public: bool IsWeatherStorm(void) const { return (m_Weather == wStorm); } /** Returns true if the current weather has any precipitation - rain or storm */ - bool IsWeatherWet (void) const { return (m_Weather != wSunny); } - + virtual bool IsWeatherWet(void) const override { return (m_Weather != wSunny); } + // tolua_end cChunkGenerator & GetGenerator(void) { return m_Generator; } -- cgit v1.2.3 From 60a37c1370dc766c55a344090d8d26bc2e1c1c99 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Thu, 29 May 2014 16:58:55 +0100 Subject: Very minor code changes --- src/Blocks/BlockBed.cpp | 2 +- src/Blocks/BlockPortal.h | 2 +- src/Mobs/Monster.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Blocks/BlockBed.cpp b/src/Blocks/BlockBed.cpp index 6a3c6a55b..07ef997dd 100644 --- a/src/Blocks/BlockBed.cpp +++ b/src/Blocks/BlockBed.cpp @@ -108,7 +108,7 @@ void cBlockBedHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ); if (Meta & 0x4) { - a_Player->SendMessageFailure("This bed is occupied."); + a_Player->SendMessageFailure("This bed is occupied"); } else { diff --git a/src/Blocks/BlockPortal.h b/src/Blocks/BlockPortal.h index 3b8030028..e718d9a70 100644 --- a/src/Blocks/BlockPortal.h +++ b/src/Blocks/BlockPortal.h @@ -55,7 +55,7 @@ public: virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override { - if ((a_RelY - 1 < 0) || (a_RelY + 1 > cChunkDef::Height)) + if ((a_RelY == 0) || (a_RelY == cChunkDef::Height)) // Y can't be < 0 or > Height; (Fast)SetBlock won't allow it { return false; // In case someone places a portal with meta 1 or 2 at boundaries, and server tries to get invalid coords at Y - 1 or Y + 1 } diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp index a9ca7a2fa..839d21314 100644 --- a/src/Mobs/Monster.cpp +++ b/src/Mobs/Monster.cpp @@ -1024,7 +1024,7 @@ void cMonster::HandleDaylightBurning(cChunk & a_Chunk) (a_Chunk.GetBlock(RelX, RelY, RelZ) != E_BLOCK_SOULSAND) && // Not on soulsand (GetWorld()->GetTimeOfDay() < (12000 + 1000)) && // It is nighttime !IsOnFire() && // Not already burning - (GetWorld()->GetWeather() != eWeather_Rain) // Not raining + (GetWorld()->IsWeatherWet()) // Not raining ) { // Burn for 100 ticks, then decide again -- cgit v1.2.3 From 8bff3e5af220070ecc789ef551c0b8428b8953ef Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sat, 31 May 2014 22:28:51 +0100 Subject: Implemented end and nether portals --- src/Chunk.cpp | 74 +++++++++++---------- src/Chunk.h | 1 + src/ClientHandle.cpp | 7 +- src/ClientHandle.h | 2 +- src/Entities/Entity.cpp | 117 +++++++++++++++++++++++++++++++++ src/Entities/Entity.h | 6 ++ src/Entities/Player.cpp | 36 +++++++--- src/Entities/Player.h | 2 +- src/Generating/BioGen.cpp | 2 +- src/Generating/ComposableGenerator.cpp | 16 +---- src/Generating/EndGen.cpp | 2 +- src/Generating/EndGen.h | 3 +- src/Protocol/Protocol.h | 2 +- src/Protocol/Protocol125.cpp | 4 +- src/Protocol/Protocol125.h | 2 +- src/Protocol/Protocol16x.cpp | 4 +- src/Protocol/Protocol16x.h | 2 +- src/Protocol/Protocol17x.cpp | 4 +- src/Protocol/Protocol17x.h | 2 +- src/Protocol/ProtocolRecognizer.cpp | 4 +- src/Protocol/ProtocolRecognizer.h | 2 +- src/Root.cpp | 21 +++--- src/World.cpp | 31 +++++++++ 23 files changed, 254 insertions(+), 92 deletions(-) diff --git a/src/Chunk.cpp b/src/Chunk.cpp index 4506cfcc5..7131a26af 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -638,30 +638,22 @@ void cChunk::Tick(float a_Dt) 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) - 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); } } // for itr - m_Entitites[] - // Remove all entities that were scheduled for removal: for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end();) { - if ((*itr)->IsDestroyed()) - { - LOGD("Destroying entity #%i (%s)", (*itr)->GetUniqueID(), (*itr)->GetClass()); - cEntity * ToDelete = *itr; - itr = m_Entities.erase(itr); - delete ToDelete; - continue; - } - ++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 ( + auto itr2 = std::find(m_EntitiesToRemove.begin(), m_EntitiesToRemove.end(), (*itr)->GetUniqueID()); + if (itr2 != m_EntitiesToRemove.end()) + { + itr = m_Entities.erase(itr); + m_EntitiesToRemove.erase(itr2); + } + else if ( // If any entity moved out of the chunk, move it to the neighbor: ((*itr)->GetChunkX() != m_PosX) || ((*itr)->GetChunkZ() != m_PosZ) ) @@ -671,9 +663,19 @@ void cChunk::Tick(float a_Dt) } 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(); } @@ -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) { @@ -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) { @@ -1886,12 +1888,12 @@ void cChunk::RemoveClient( cClientHandle* a_Client ) { continue; } - + m_LoadedByClient.erase(itr); 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: @@ -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) { @@ -1942,9 +1944,9 @@ void cChunk::AddEntity(cEntity * a_Entity) { MarkDirty(); } - + ASSERT(std::find(m_Entities.begin(), m_Entities.end(), a_Entity) == m_Entities.end()); // Not there already - + m_Entities.push_back(a_Entity); } @@ -1954,17 +1956,12 @@ void cChunk::AddEntity(cEntity * a_Entity) void cChunk::RemoveEntity(cEntity * a_Entity) { - size_t SizeBefore = m_Entities.size(); - m_Entities.remove(a_Entity); - size_t SizeAfter = m_Entities.size(); - - if (SizeBefore != SizeAfter) + m_EntitiesToRemove.push_back(a_Entity->GetUniqueID()); + + // Mark as dirty if it was a server-generated entity: + if (!a_Entity->IsPlayer()) { - // Mark as dirty if it was a server-generated entity: - if (!a_Entity->IsPlayer()) - { - MarkDirty(); - } + MarkDirty(); } } @@ -1974,6 +1971,11 @@ void cChunk::RemoveEntity(cEntity * a_Entity) 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) { if ((*itr)->GetUniqueID() == a_EntityID) diff --git a/src/Chunk.h b/src/Chunk.h index 84ec35496..f61520e8f 100644 --- a/src/Chunk.h +++ b/src/Chunk.h @@ -411,6 +411,7 @@ private: // A critical section is not needed, because all chunk access is protected by its parent ChunkMap's csLayers cClientHandleList m_LoadedByClient; cEntityList m_Entities; + std::vector m_EntitiesToRemove; cBlockEntityList m_BlockEntities; /** Number of times the chunk has been requested to stay (by various cChunkStay objects); if zero, the chunk can be unloaded */ diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index 9b03bead9..8a5c81e70 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -125,7 +125,6 @@ cClientHandle::~cClientHandle() } if (World != NULL) { - World->RemovePlayer(m_Player); m_Player->Destroy(); } delete m_Player; @@ -1754,7 +1753,7 @@ void cClientHandle::MoveToWorld(cWorld & a_World, bool a_SendRespawnPacket) if (a_SendRespawnPacket) { - SendRespawn(); + SendRespawn(a_World); } 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); } diff --git a/src/ClientHandle.h b/src/ClientHandle.h index 659c67658..e86287735 100644 --- a/src/ClientHandle.h +++ b/src/ClientHandle.h @@ -149,7 +149,7 @@ public: void SendPlayerSpawn (const cPlayer & a_Player); void SendPluginMessage (const AString & a_Channel, const AString & a_Message); // Exported in ManualBindings.cpp void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID); - void SendRespawn (void); + void SendRespawn (const cWorld & a_World); void SendExperience (void); void SendExperienceOrb (const cExpOrb & a_ExpOrb); void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode); diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index 1226a2319..b5c272cf2 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -629,6 +629,7 @@ void cEntity::Tick(float a_Dt, cChunk & a_Chunk) // Handle drowning HandleAir(); } + DetectPortal(); // None of the above functions change position, we remain in the chunk of 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) { int RelY = (int)floor(GetPosY() + 0.1); diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h index 0c393c0f5..da8256606 100644 --- a/src/Entities/Entity.h +++ b/src/Entities/Entity.h @@ -323,6 +323,9 @@ public: /** Detects the time for application of cacti damage */ 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 virtual void TickInVoid(cChunk & a_Chunk); @@ -365,6 +368,9 @@ public: /// Teleports to the coordinates specified 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 diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 0dfdcfd8b..140b98d5d 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -134,7 +134,7 @@ cPlayer::~cPlayer(void) SaveToDisk(); - m_World->RemovePlayer( this ); + m_World->RemovePlayer(this); m_ClientHandle = NULL; @@ -150,8 +150,6 @@ cPlayer::~cPlayer(void) void cPlayer::Destroyed() { CloseWindow(false); - - m_ClientHandle = NULL; } @@ -952,7 +950,7 @@ void cPlayer::Respawn(void) m_LifetimeTotalXp = 0; // ToDo: send score to client? How? - m_ClientHandle->SendRespawn(); + m_ClientHandle->SendRespawn(*GetWorld()); // Extinguish the fire: 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); - if (World == NULL) + 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) { - LOG("%s: Couldn't find world \"%s\".", __FUNCTION__, a_WorldName); return false; } @@ -1588,11 +1599,11 @@ bool cPlayer::MoveToWorld(const char * a_WorldName) // Remove all links to the old world m_World->RemovePlayer(this); m_ClientHandle->RemoveFromAllChunks(); - m_World->RemoveEntity(this); // 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 - 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 SetWorld(World); @@ -1600,6 +1611,11 @@ bool cPlayer::MoveToWorld(const char * a_WorldName) World->AddEntity(this); World->AddPlayer(this); + if (SendRespawn) + { + GetClientHandle()->SendPlayerMoveLook(); + } + return true; } diff --git a/src/Entities/Player.h b/src/Entities/Player.h index b7cb27d6c..582f79b86 100644 --- a/src/Entities/Player.h +++ b/src/Entities/Player.h @@ -328,7 +328,7 @@ public: void SetVisible( bool a_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 LoadFromDisk(void); diff --git a/src/Generating/BioGen.cpp b/src/Generating/BioGen.cpp index 32a687201..e08e242e2 100644 --- a/src/Generating/BioGen.cpp +++ b/src/Generating/BioGen.cpp @@ -95,7 +95,7 @@ void cBioGenConstant::GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap 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); if (m_Biome == biInvalidBiome) { diff --git a/src/Generating/ComposableGenerator.cpp b/src/Generating/ComposableGenerator.cpp index 2e886336f..03ed0291f 100644 --- a/src/Generating/ComposableGenerator.cpp +++ b/src/Generating/ComposableGenerator.cpp @@ -39,7 +39,6 @@ cTerrainCompositionGen * cTerrainCompositionGen::CreateCompositionGen(cIniFile & { LOGWARN("[Generator] CompositionGen value not set in world.ini, using \"Biomal\"."); CompoGenName = "Biomal"; - a_IniFile.SetValue("Generator", "CompositionGen", CompoGenName); } cTerrainCompositionGen * res = NULL; @@ -93,7 +92,6 @@ cTerrainCompositionGen * cTerrainCompositionGen::CreateCompositionGen(cIniFile & else { LOGWARN("Unknown CompositionGen \"%s\", using \"Biomal\" instead.", CompoGenName.c_str()); - a_IniFile.DeleteValue("Generator", "CompositionGen"); a_IniFile.SetValue("Generator", "CompositionGen", "Biomal"); 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(); 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) - // 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"); + AString Finishers = a_IniFile.GetValueSet("Generator", "Finishers", ""); // Create all requested finishers: AStringVector Str = StringSplitAndTrim(Finishers, ","); diff --git a/src/Generating/EndGen.cpp b/src/Generating/EndGen.cpp index f466039b9..5be73bfbe 100644 --- a/src/Generating/EndGen.cpp +++ b/src/Generating/EndGen.cpp @@ -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_IslandSizeY = a_IniFile.GetValueSetI("Generator", "EndGenIslandSizeY", m_IslandSizeY); diff --git a/src/Generating/EndGen.h b/src/Generating/EndGen.h index 4904a0e3d..322061810 100644 --- a/src/Generating/EndGen.h +++ b/src/Generating/EndGen.h @@ -23,8 +23,6 @@ class cEndGen : public: cEndGen(int a_Seed); - void Initialize(cIniFile & a_IniFile); - protected: /// Seed for the noise @@ -66,4 +64,5 @@ protected: // cTerrainCompositionGen overrides: virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc) override; + virtual void InitializeCompoGen(cIniFile & a_IniFile) override; } ; diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h index a543c6361..c6e569919 100644 --- a/src/Protocol/Protocol.h +++ b/src/Protocol/Protocol.h @@ -100,7 +100,7 @@ public: virtual void SendPlayerSpawn (const cPlayer & a_Player) = 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 SendRespawn (void) = 0; + virtual void SendRespawn (const cWorld & a_World) = 0; virtual void SendExperience (void) = 0; virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) = 0; virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) = 0; diff --git a/src/Protocol/Protocol125.cpp b/src/Protocol/Protocol125.cpp index f3bdae3ac..873295f62 100644 --- a/src/Protocol/Protocol125.cpp +++ b/src/Protocol/Protocol125.cpp @@ -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); cPlayer * Player = m_Client->GetPlayer(); WriteByte (PACKET_RESPAWN); - WriteInt ((int)(Player->GetWorld()->GetDimension())); + WriteInt ((int)(a_World.GetDimension())); WriteByte (2); // TODO: Difficulty; 2 = Normal WriteChar ((char)Player->GetGameMode()); WriteShort (256); // Current world height diff --git a/src/Protocol/Protocol125.h b/src/Protocol/Protocol125.h index 18a626a2d..3f39c8965 100644 --- a/src/Protocol/Protocol125.h +++ b/src/Protocol/Protocol125.h @@ -72,7 +72,7 @@ public: virtual void SendPlayerSpawn (const cPlayer & a_Player) 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 SendRespawn (void) override; + virtual void SendRespawn (const cWorld & a_World) override; virtual void SendExperience (void) override; virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override; virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override; diff --git a/src/Protocol/Protocol16x.cpp b/src/Protocol/Protocol16x.cpp index 714bf5e46..9e0f3f852 100644 --- a/src/Protocol/Protocol16x.cpp +++ b/src/Protocol/Protocol16x.cpp @@ -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 - super::SendRespawn(); + super::SendRespawn(a_World); SendPlayerMaxSpeed(); } diff --git a/src/Protocol/Protocol16x.h b/src/Protocol/Protocol16x.h index 8eedce8d5..e91dc8a1c 100644 --- a/src/Protocol/Protocol16x.h +++ b/src/Protocol/Protocol16x.h @@ -42,7 +42,7 @@ protected: virtual void SendGameMode (eGameMode a_GameMode) override; virtual void SendHealth (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 int ParseEntityAction (void) override; diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index 7c526d103..96e1cbad9 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -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 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((Byte)Player->GetEffectiveGameMode()); Pkt.WriteString("default"); diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h index 3c6a8c085..cafdb50e4 100644 --- a/src/Protocol/Protocol17x.h +++ b/src/Protocol/Protocol17x.h @@ -104,7 +104,7 @@ public: virtual void SendPlayerSpawn (const cPlayer & a_Player) 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 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 SendExperience (void) override; virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override; diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp index b0cbb6def..35a331f43 100644 --- a/src/Protocol/ProtocolRecognizer.cpp +++ b/src/Protocol/ProtocolRecognizer.cpp @@ -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); - m_Protocol->SendRespawn(); + m_Protocol->SendRespawn(a_World); } diff --git a/src/Protocol/ProtocolRecognizer.h b/src/Protocol/ProtocolRecognizer.h index 3a291bf7a..5e178447c 100644 --- a/src/Protocol/ProtocolRecognizer.h +++ b/src/Protocol/ProtocolRecognizer.h @@ -107,7 +107,7 @@ public: virtual void SendPlayerSpawn (const cPlayer & a_Player) 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 SendRespawn (void) override; + virtual void SendRespawn (const cWorld & a_World) override; virtual void SendExperience (void) override; virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override; virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override; diff --git a/src/Root.cpp b/src/Root.cpp index c82b05a66..2a80baeb3 100644 --- a/src/Root.cpp +++ b/src/Root.cpp @@ -320,7 +320,7 @@ cWorld * cRoot::CreateAndInitializeWorld(const AString & a_WorldName) { return NULL; } - cWorld* NewWorld = new cWorld(a_WorldName.c_str()); + cWorld * NewWorld = new cWorld(a_WorldName.c_str()); m_WorldsByName[a_WorldName] = NewWorld; NewWorld->Start(); NewWorld->InitializeSpawn(); @@ -372,7 +372,7 @@ void cRoot::UnloadWorlds(void) -cWorld* cRoot::GetDefaultWorld() +cWorld * cRoot::GetDefaultWorld() { 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 ); - if( itr != m_WorldsByName.end() ) + WorldMap::iterator itr = m_WorldsByName.find(a_WorldName); + if (itr != m_WorldsByName.end()) + { 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) { ++itr2; - if (a_Callback.Item(itr->second)) + if (itr->second != NULL) { - return false; + if (a_Callback.Item(itr->second)) + { + return false; + } } } return true; diff --git a/src/World.cpp b/src/World.cpp index 807065bfa..9869e90fa 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -571,6 +571,37 @@ void cWorld::Start(void) m_GameMode = (eGameMode) Clamp(GameMode, (int)gmSurvival, (int)gmAdventure); 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: const char * DefaultMonsters = ""; switch (m_Dimension) -- cgit v1.2.3 From 576f89c1d5bdb067c0ca06237440f754d80bd13c Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 1 Jun 2014 18:46:59 +0100 Subject: Implemented bed homes + Implemented bed home positions * Fixed some inventory and health server/client mismatches after world change --- src/Blocks/BlockBed.cpp | 2 ++ src/Entities/Entity.cpp | 6 ++++++ src/Entities/Player.cpp | 35 ++++++++++++++++++++++------------- src/Entities/Player.h | 15 ++++++++++++--- 4 files changed, 42 insertions(+), 16 deletions(-) diff --git a/src/Blocks/BlockBed.cpp b/src/Blocks/BlockBed.cpp index 07ef997dd..5525f0d0c 100644 --- a/src/Blocks/BlockBed.cpp +++ b/src/Blocks/BlockBed.cpp @@ -133,6 +133,8 @@ void cBlockBedHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta | 0x4); // Where 0x4 = occupied bit a_Player->SetIsInBed(true); + a_Player->SetBedPos(Vector3i(a_BlockX, a_BlockY, a_BlockZ)); + a_Player->SendMessageSuccess("Home position set successfully"); cTimeFastForwardTester Tester; if (a_WorldInterface.ForEachPlayer(Tester)) diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index b5c272cf2..de6c628e9 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -1093,6 +1093,12 @@ void cEntity::DetectPortal() File.WriteFile(OverworldName + "/world.ini"); MoveToWorld(OverworldName, cRoot::Get()->CreateAndInitializeWorld(OverworldName)); + + if (IsPlayer()) + { + cPlayer * Player = (cPlayer *)this; + Player->TeleportToCoords(Player->GetLastBedPos().x, Player->GetLastBedPos().y, Player->GetLastBedPos().z); + } break; } case dimOverworld: diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 140b98d5d..3058d6e94 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -82,13 +82,13 @@ cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName) m_PlayerName = a_PlayerName; - if (!LoadFromDisk()) + cWorld * World; + if (!LoadFromDisk(World)) { m_Inventory.Clear(); - cWorld * DefaultWorld = cRoot::Get()->GetDefaultWorld(); - SetPosX(DefaultWorld->GetSpawnX()); - SetPosY(DefaultWorld->GetSpawnY()); - SetPosZ(DefaultWorld->GetSpawnZ()); + SetPosX(World->GetSpawnX()); + SetPosY(World->GetSpawnY()); + SetPosZ(World->GetSpawnZ()); LOGD("Player \"%s\" is connecting for the first time, spawning at default world spawn {%.2f, %.2f, %.2f}", a_PlayerName.c_str(), GetPosX(), GetPosY(), GetPosZ() @@ -101,11 +101,6 @@ cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName) if (m_GameMode == gmNotSet) { - cWorld * World = cRoot::Get()->GetWorld(GetLoadedWorldName()); - if (World == NULL) - { - World = cRoot::Get()->GetDefaultWorld(); - } if (World->IsGameModeCreative()) { m_CanFly = true; @@ -955,7 +950,7 @@ void cPlayer::Respawn(void) // Extinguish the fire: StopBurning(); - TeleportToCoords(GetWorld()->GetSpawnX(), GetWorld()->GetSpawnY(), GetWorld()->GetSpawnZ()); + TeleportToCoords(GetLastBedPos().x, GetLastBedPos().y, GetLastBedPos().z); SetVisible(true); } @@ -1614,6 +1609,8 @@ bool cPlayer::MoveToWorld(const AString & a_WorldName, cWorld * a_World) if (SendRespawn) { GetClientHandle()->SendPlayerMoveLook(); + GetClientHandle()->SendHealth(); + GetClientHandle()->SendWholeInventory((cWindow &)GetInventory()); } return true; @@ -1662,8 +1659,14 @@ void cPlayer::LoadPermissionsFromDisk() -bool cPlayer::LoadFromDisk() +bool cPlayer::LoadFromDisk(cWorld * a_World) { + a_World = cRoot::Get()->GetWorld(GetLoadedWorldName()); + if (a_World == NULL) + { + a_World = cRoot::Get()->GetDefaultWorld(); + } + LoadPermissionsFromDisk(); // Log player permissions, cause it's what the cool kids do @@ -1724,6 +1727,9 @@ bool cPlayer::LoadFromDisk() m_LifetimeTotalXp = (short) root.get("xpTotal", 0).asInt(); m_CurrentXp = (short) root.get("xpCurrent", 0).asInt(); m_IsFlying = root.get("isflying", 0).asBool(); + m_LastBedPos.x = root.get("SpawnX", a_World->GetSpawnX()).asInt(); + m_LastBedPos.y = root.get("SpawnY", a_World->GetSpawnY()).asInt(); + m_LastBedPos.z = root.get("SpawnZ", a_World->GetSpawnZ()).asInt(); m_GameMode = (eGameMode) root.get("gamemode", eGameMode_NotSet).asInt(); @@ -1742,7 +1748,7 @@ bool cPlayer::LoadFromDisk() StatSerializer.Load(); LOGD("Player \"%s\" was read from file, spawning at {%.2f, %.2f, %.2f} in world \"%s\"", - GetName().c_str(), GetPosX(), GetPosY(), GetPosZ(), m_LoadedWorldName.c_str() + GetName().c_str(), GetPosX(), GetPosY(), GetPosZ(), GetLoadedWorldName().c_str() ); return true; @@ -1784,6 +1790,9 @@ bool cPlayer::SaveToDisk() root["foodExhaustion"] = m_FoodExhaustionLevel; root["world"] = GetWorld()->GetName(); root["isflying"] = IsFlying(); + root["SpawnX"] = GetLastBedPos().x; + root["SpawnY"] = GetLastBedPos().y; + root["SpawnZ"] = GetLastBedPos().z; if (m_GameMode == GetWorld()->GetGameMode()) { diff --git a/src/Entities/Player.h b/src/Entities/Player.h index 582f79b86..5c0b61064 100644 --- a/src/Entities/Player.h +++ b/src/Entities/Player.h @@ -331,7 +331,7 @@ public: virtual bool MoveToWorld(const AString & a_WorldName, cWorld * a_World = NULL) override; // tolua_export bool SaveToDisk(void); - bool LoadFromDisk(void); + bool LoadFromDisk(cWorld * a_World); void LoadPermissionsFromDisk(void); // tolua_export const AString & GetLoadedWorldName() { return m_LoadedWorldName; } @@ -391,11 +391,19 @@ public: /** If true the player can fly even when he's not in creative. */ void SetCanFly(bool a_CanFly); + /** Gets the last position that the player slept in */ + Vector3i GetLastBedPos(void) const { return m_LastBedPos; } + + /** Sets the player's bed (home) position */ + void SetBedPos(const Vector3i & a_Pos) { m_LastBedPos = a_Pos; } + /** Update movement-related statistics. */ void UpdateMovementStats(const Vector3d & a_DeltaPos); /** Returns wheter the player can fly or not. */ virtual bool CanFly(void) const { return m_CanFly; } + + // tolua_end // cEntity overrides: @@ -450,6 +458,9 @@ protected: cWindow * m_CurrentWindow; cWindow * m_InventoryWindow; + /** The player's last saved bed position */ + Vector3i m_LastBedPos; + char m_Color; eGameMode m_GameMode; @@ -508,8 +519,6 @@ protected: cStatManager m_Stats; - - void ResolvePermissions(void); void ResolveGroups(void); -- cgit v1.2.3 From 01f38d883602045e84fdf98bf3395e97608d9aad Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Wed, 4 Jun 2014 13:22:50 +0100 Subject: Added checks for no downfall biomes --- src/Blocks/BlockCauldron.h | 2 +- src/Entities/Entity.cpp | 2 +- src/Mobs/Monster.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Blocks/BlockCauldron.h b/src/Blocks/BlockCauldron.h index 8b5cd9ccb..5ec776df6 100644 --- a/src/Blocks/BlockCauldron.h +++ b/src/Blocks/BlockCauldron.h @@ -61,7 +61,7 @@ public: virtual void OnUpdate(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_PluginInterface, cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ) override { - if (!a_WorldInterface.IsWeatherWet()) + if (IsBiomeNoDownfall(a_Chunk.GetBiomeAt(a_RelX, a_RelZ)) || !a_WorldInterface.IsWeatherWet()) { return; } diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index de6c628e9..16264a608 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -869,7 +869,7 @@ void cEntity::TickBurning(cChunk & a_Chunk) // Remember the current burning state: bool HasBeenBurning = (m_TicksLeftBurning > 0); - if (m_World->IsWeatherWet()) + if (IsBiomeNoDownfall(a_Chunk.GetBiomeAt(POSX_TOINT - a_Chunk.GetPosX() * cChunkDef::Width, POSZ_TOINT - a_Chunk.GetPosZ() * cChunkDef::Width)) || GetWorld()->IsWeatherWet()) { if (POSY_TOINT > m_World->GetHeight(POSX_TOINT, POSZ_TOINT)) { diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp index fa3969d5e..c25ee6b75 100644 --- a/src/Mobs/Monster.cpp +++ b/src/Mobs/Monster.cpp @@ -1034,7 +1034,7 @@ void cMonster::HandleDaylightBurning(cChunk & a_Chunk) (a_Chunk.GetBlock(RelX, RelY, RelZ) != E_BLOCK_SOULSAND) && // Not on soulsand (GetWorld()->GetTimeOfDay() < (12000 + 1000)) && // It is nighttime !IsOnFire() && // Not already burning - (GetWorld()->IsWeatherWet()) // Not raining + (IsBiomeNoDownfall(a_Chunk.GetBiomeAt(RelX, RelZ)) || GetWorld()->IsWeatherWet()) // Not raining ) { // Burn for 100 ticks, then decide again -- cgit v1.2.3 From 3278a403b5bc951818ed418c39c64934d55dbd65 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Wed, 4 Jun 2014 13:24:43 +0100 Subject: Removed use of auto --- src/Chunk.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Chunk.cpp b/src/Chunk.cpp index 59f4a8507..c6122852a 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -588,7 +588,7 @@ void cChunk::Tick(float a_Dt) for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end();) { - auto itr2 = std::find(m_EntitiesToRemove.begin(), m_EntitiesToRemove.end(), (*itr)->GetUniqueID()); + std::vector::const_iterator itr2 = std::find(m_EntitiesToRemove.begin(), m_EntitiesToRemove.end(), (*itr)->GetUniqueID()); if (itr2 != m_EntitiesToRemove.end()) { itr = m_Entities.erase(itr); -- cgit v1.2.3 From 74cd4f552152f73d0d46cf726bcef472841e2da5 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Wed, 4 Jun 2014 18:59:56 +0100 Subject: Suggestions --- src/Entities/Player.cpp | 2 +- src/Entities/Player.h | 12 ++++++++---- src/UI/Window.cpp | 2 +- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 02a55566c..8e4c89f68 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -1659,7 +1659,7 @@ void cPlayer::LoadPermissionsFromDisk() -bool cPlayer::LoadFromDisk(cWorld * a_World) +bool cPlayer::LoadFromDisk(cWorld *& a_World) { a_World = cRoot::Get()->GetWorld(GetLoadedWorldName()); if (a_World == NULL) diff --git a/src/Entities/Player.h b/src/Entities/Player.h index 5c0b61064..39031fbfb 100644 --- a/src/Entities/Player.h +++ b/src/Entities/Player.h @@ -127,7 +127,7 @@ public: inline const cItem & GetEquippedItem(void) const { return GetInventory().GetEquippedItem(); } // tolua_export - /** Returns whether the player is climbing (ladders, vines e.t.c). */ + /** Returns whether the player is climbing (ladders, vines etc.) */ bool IsClimbing(void) const; virtual void TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ) override; @@ -330,8 +330,13 @@ public: virtual bool MoveToWorld(const AString & a_WorldName, cWorld * a_World = NULL) override; // tolua_export + /** Saves all player data, such as inventory, to JSON */ bool SaveToDisk(void); - bool LoadFromDisk(cWorld * a_World); + + /** Loads player data from JSON to the object + Takes a (NULL) cWorld pointer which it will assign a value to based on either the loaded world or default world + */ + bool LoadFromDisk(cWorld *& a_World); void LoadPermissionsFromDisk(void); // tolua_export const AString & GetLoadedWorldName() { return m_LoadedWorldName; } @@ -342,8 +347,7 @@ public: void SendExperience(void); - // In UI windows, the item that the player is dragging: - bool IsDraggingItem(void) const { return !m_DraggingItem.IsEmpty(); } + /** In UI windows, the item that the player is dragging */ cItem & GetDraggingItem(void) {return m_DraggingItem; } // In UI windows, when inventory-painting: diff --git a/src/UI/Window.cpp b/src/UI/Window.cpp index 46885390b..c0e2cef64 100644 --- a/src/UI/Window.cpp +++ b/src/UI/Window.cpp @@ -283,7 +283,7 @@ void cWindow::OpenedByPlayer(cPlayer & a_Player) bool cWindow::ClosedByPlayer(cPlayer & a_Player, bool a_CanRefuse) { // Checks whether the player is still holding an item - if (a_Player.IsDraggingItem()) + if (!a_Player.GetDraggingItem().IsEmpty()) { LOGD("Player holds item! Dropping it..."); a_Player.TossHeldItem(a_Player.GetDraggingItem().m_ItemCount); -- cgit v1.2.3 From ccbf6cc446ad67fbba8163d4d4d61456c1ba0bc6 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Wed, 4 Jun 2014 20:00:55 +0100 Subject: Configurable portals --- src/Entities/Entity.cpp | 45 ++++++++++++++++++++++++++++++++------------- src/Entities/Player.cpp | 2 +- src/World.cpp | 26 ++++++++++++++++++++++++++ src/World.h | 24 ++++++++++++++++++++++++ 4 files changed, 83 insertions(+), 14 deletions(-) diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index 16264a608..7d9c10ec6 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -1042,6 +1042,11 @@ void cEntity::DetectCacti(void) void cEntity::DetectPortal() { + if (!GetWorld()->AreNetherPortalsEnabled() && !GetWorld()->AreEndPortalsEnabled()) + { + return; + } + int X = POSX_TOINT, Y = POSY_TOINT, Z = POSZ_TOINT; if ((Y > 0) && (Y < cChunkDef::Height)) { @@ -1049,11 +1054,18 @@ void cEntity::DetectPortal() { case E_BLOCK_NETHER_PORTAL: { + if (!GetWorld()->AreNetherPortalsEnabled()) + { + return; + } + switch (GetWorld()->GetDimension()) { case dimNether: { - AString OverworldName = GetWorld()->GetName().substr(0, GetWorld()->GetName().size() - 7); + cIniFile OwnIni; OwnIni.ReadFile(GetWorld()->GetIniFileName()); + AString OverworldName = OwnIni.GetValue("General", "OverworldName", cRoot::Get()->GetDefaultWorld()->GetName()); + cFile::CreateFolder(FILE_IO_PREFIX + OverworldName); cIniFile File; File.ReadFile(OverworldName + "/world.ini"); @@ -1065,14 +1077,14 @@ void cEntity::DetectPortal() } case dimOverworld: { - AString NetherWorldName = GetWorld()->GetName() + "_nether"; - cFile::CreateFolder(FILE_IO_PREFIX + NetherWorldName); + cFile::CreateFolder(FILE_IO_PREFIX + GetWorld()->GetNetherWorldName()); cIniFile File; - File.ReadFile(NetherWorldName + "/world.ini"); + File.ReadFile(GetWorld()->GetNetherWorldName() + "/world.ini"); File.SetValue("General", "Dimension", "Nether"); - File.WriteFile(NetherWorldName + "/world.ini"); + File.SetValue("General", "OverworldName", GetWorld()->GetName()); + File.WriteFile(GetWorld()->GetNetherWorldName() + "/world.ini"); - MoveToWorld(NetherWorldName, cRoot::Get()->CreateAndInitializeWorld(NetherWorldName)); + MoveToWorld(GetWorld()->GetNetherWorldName(), cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetNetherWorldName())); break; } default: break; @@ -1081,11 +1093,18 @@ void cEntity::DetectPortal() } case E_BLOCK_END_PORTAL: { + if (!GetWorld()->AreEndPortalsEnabled()) + { + return; + } + switch (GetWorld()->GetDimension()) { case dimEnd: { - AString OverworldName = GetWorld()->GetName().substr(0, GetWorld()->GetName().size() - 4); + cIniFile OwnIni; OwnIni.ReadFile(GetWorld()->GetIniFileName()); + AString OverworldName = OwnIni.GetValue("General", "OverworldName", cRoot::Get()->GetDefaultWorld()->GetName()); + cFile::CreateFolder(FILE_IO_PREFIX + OverworldName); cIniFile File; File.ReadFile(OverworldName + "/world.ini"); @@ -1103,14 +1122,14 @@ void cEntity::DetectPortal() } case dimOverworld: { - AString EndWorldName = GetWorld()->GetName() + "_end"; - cFile::CreateFolder(FILE_IO_PREFIX + EndWorldName); + cFile::CreateFolder(FILE_IO_PREFIX + GetWorld()->GetEndWorldName()); cIniFile File; - File.ReadFile(EndWorldName + "/world.ini"); + File.ReadFile(GetWorld()->GetEndWorldName() + "/world.ini"); File.SetValue("General", "Dimension", "End"); - File.WriteFile(EndWorldName + "/world.ini"); + File.SetValue("General", "OverworldName", GetWorld()->GetName()); + File.WriteFile(GetWorld()->GetEndWorldName() + "/world.ini"); - MoveToWorld(EndWorldName, cRoot::Get()->CreateAndInitializeWorld(EndWorldName)); + MoveToWorld(GetWorld()->GetEndWorldName(), cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetEndWorldName())); break; } default: break; @@ -1133,7 +1152,7 @@ bool cEntity::MoveToWorld(const AString & a_WorldName, cWorld * a_World) World = cRoot::Get()->GetWorld(a_WorldName); if (World == NULL) { - LOG("%s: Couldn't find world \"%s\".", __FUNCTION__, a_WorldName); + LOG("%s: Couldn't find world \"%s\".", __FUNCTION__, a_WorldName.c_str()); return false; } } diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 8e4c89f68..eebc9ecf9 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -1610,7 +1610,7 @@ bool cPlayer::MoveToWorld(const AString & a_WorldName, cWorld * a_World) { GetClientHandle()->SendPlayerMoveLook(); GetClientHandle()->SendHealth(); - GetClientHandle()->SendWholeInventory((cWindow &)GetInventory()); + GetClientHandle()->SendWholeInventory(*GetWindow()); } return true; diff --git a/src/World.cpp b/src/World.cpp index 66aca83ef..345c894eb 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -66,6 +66,9 @@ const int TIME_NIGHT_END = 22812; const int TIME_SUNRISE = 23999; const int TIME_SPAWN_DIVISOR = 148; +#define DEFAULT_NETHER_NAME GetName() + "_nether" +#define DEFAULT_END_NAME GetName() + "_end" + @@ -566,6 +569,14 @@ void cWorld::Start(void) m_bUseChatPrefixes = IniFile.GetValueSetB("Mechanics", "UseChatPrefixes", true); m_VillagersShouldHarvestCrops = IniFile.GetValueSetB("Monsters", "VillagersShouldHarvestCrops", true); int GameMode = IniFile.GetValueSetI("General", "Gamemode", (int)m_GameMode); + + if ((GetDimension() != dimNether) && (GetDimension() != dimEnd)) + { + m_bNetherPortalsEnabled = IniFile.GetValueSetB("General", "NetherPortalsEnabled", true); + m_NetherWorldName = IniFile.GetValueSet("General", "NetherWorldName", DEFAULT_NETHER_NAME); + m_bEndPortalsEnabled = IniFile.GetValueSetB("General", "EndPortalsEnabled", true); + m_EndWorldName = IniFile.GetValueSet("General", "EndWorldName", DEFAULT_END_NAME); + } // Adjust the enum-backed variables into their respective bounds: m_GameMode = (eGameMode) Clamp(GameMode, (int)gmSurvival, (int)gmAdventure); @@ -734,6 +745,21 @@ void cWorld::Stop(void) } // for itr - m_Clients[] m_Clients.clear(); } + + // Write settings to file; these are all plugin changeable values - keep updated! + cIniFile IniFile; + IniFile.ReadFile(m_IniFileName); + if ((GetDimension() != dimNether) && (GetDimension() != dimEnd)) + { + IniFile.SetValueB("General", "NetherPortalsEnabled", m_bNetherPortalsEnabled); + IniFile.SetValue("General", "NetherWorldName", m_NetherWorldName); + IniFile.SetValueB("General", "EndPortalsEnabled", m_bEndPortalsEnabled); + IniFile.SetValue("General", "EndWorldName", m_EndWorldName); + } + IniFile.SetValueI("Physics", "TNTShrapnelLevel", (int)m_TNTShrapnelLevel); + IniFile.SetValueB("Mechanics", "CommandBlocksEnabled", m_bCommandBlocksEnabled); + IniFile.SetValueB("Mechanics", "UseChatPrefixes", m_bUseChatPrefixes); + IniFile.WriteFile(m_IniFileName); m_TickThread.Stop(); m_Lighting.Stop(); diff --git a/src/World.h b/src/World.h index e72675194..7b87a76ac 100644 --- a/src/World.h +++ b/src/World.h @@ -624,6 +624,18 @@ public: bool ShouldUseChatPrefixes(void) const { return m_bUseChatPrefixes; } void SetShouldUseChatPrefixes(bool a_Flag) { m_bUseChatPrefixes = a_Flag; } + + bool AreNetherPortalsEnabled(void) const { return m_bNetherPortalsEnabled; } + void SetNetherPortalsEnabled(bool a_Flag) { m_bNetherPortalsEnabled = a_Flag; } + + bool AreEndPortalsEnabled(void) const { return m_bEndPortalsEnabled; } + void SetEndPortalsEnabled(bool a_Flag) { m_bEndPortalsEnabled = a_Flag; } + + AString GetNetherWorldName(void) const { return m_NetherWorldName; } + void SetNetherWorldName(const AString & a_Name) { m_NetherWorldName = a_Name; } + + AString GetEndWorldName(void) const { return m_EndWorldName; } + void SetEndWorldName(const AString & a_Name) { m_EndWorldName = a_Name; } // tolua_end @@ -886,6 +898,18 @@ private: See the eShrapnelLevel enumeration for details */ eShrapnelLevel m_TNTShrapnelLevel; + + /** Whether nether portals teleport entities */ + bool m_bNetherPortalsEnabled; + + /** Whether end portals teleport entities */ + bool m_bEndPortalsEnabled; + + /** Name of the nether world */ + AString m_NetherWorldName; + + /** Name of the end world */ + AString m_EndWorldName; cChunkGenerator m_Generator; -- cgit v1.2.3 From 7d3d9e92e89e726fc3e999ac343db06b694d95e7 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Wed, 4 Jun 2014 20:01:05 +0100 Subject: Fixed a NetherFinisher bug --- src/Generating/ChunkDesc.cpp | 21 --------------------- src/Generating/ChunkDesc.h | 3 --- src/Generating/FinishGen.cpp | 9 +++++++++ 3 files changed, 9 insertions(+), 24 deletions(-) diff --git a/src/Generating/ChunkDesc.cpp b/src/Generating/ChunkDesc.cpp index 7711723fc..759d57b83 100644 --- a/src/Generating/ChunkDesc.cpp +++ b/src/Generating/ChunkDesc.cpp @@ -20,7 +20,6 @@ cChunkDesc::cChunkDesc(int a_ChunkX, int a_ChunkZ) : m_bUseDefaultBiomes(true), m_bUseDefaultHeight(true), m_bUseDefaultComposition(true), - m_bUseDefaultStructures(true), m_bUseDefaultFinish(true) { m_BlockArea.Create(cChunkDef::Width, cChunkDef::Height, cChunkDef::Width); @@ -207,26 +206,6 @@ bool cChunkDesc::IsUsingDefaultComposition(void) const -void cChunkDesc::SetUseDefaultStructures(bool a_bUseDefaultStructures) -{ - LOGWARNING("%s: Structures are no longer accounted for, use Finishers instead", __FUNCTION__); - m_bUseDefaultStructures = a_bUseDefaultStructures; -} - - - - - -bool cChunkDesc::IsUsingDefaultStructures(void) const -{ - LOGWARNING("%s: Structures are no longer accounted for, use Finishers instead", __FUNCTION__); - return m_bUseDefaultStructures; -} - - - - - void cChunkDesc::SetUseDefaultFinish(bool a_bUseDefaultFinish) { m_bUseDefaultFinish = a_bUseDefaultFinish; diff --git a/src/Generating/ChunkDesc.h b/src/Generating/ChunkDesc.h index 8edc2800b..2680fe3fa 100644 --- a/src/Generating/ChunkDesc.h +++ b/src/Generating/ChunkDesc.h @@ -68,8 +68,6 @@ public: bool IsUsingDefaultHeight(void) const; void SetUseDefaultComposition(bool a_bUseDefaultComposition); bool IsUsingDefaultComposition(void) const; - void SetUseDefaultStructures(bool a_bUseDefaultStructures); - bool IsUsingDefaultStructures(void) const; void SetUseDefaultFinish(bool a_bUseDefaultFinish); bool IsUsingDefaultFinish(void) const; @@ -214,7 +212,6 @@ private: bool m_bUseDefaultBiomes; bool m_bUseDefaultHeight; bool m_bUseDefaultComposition; - bool m_bUseDefaultStructures; bool m_bUseDefaultFinish; } ; // tolua_export diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index f2d66af70..c77145bc6 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -125,6 +125,15 @@ void cFinishGenNetherClumpFoliage::TryPlaceClump(cChunkDesc & a_ChunkDesc, int a float zz = (float) a_ChunkDesc.GetChunkZ() * cChunkDef::Width + z; for (int y = a_RelY - 2; y < a_RelY + 2; y++) { + if ( + ((x < 0) || (x >= cChunkDef::Width)) || + ((y < 0) || (y >= cChunkDef::Height)) || + ((z < 0) || (z >= cChunkDef::Width)) + ) + { + continue; + } + if (a_ChunkDesc.GetBlockType(x, y, z) != E_BLOCK_AIR) // Don't replace non air blocks. { continue; -- cgit v1.2.3 From 9c7a6bc443605612c09be824c452b9287fa2bfdb Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Wed, 4 Jun 2014 20:09:02 +0100 Subject: Health of monsters is now saved --- src/WorldStorage/NBTChunkSerializer.cpp | 1 + src/WorldStorage/WSSAnvil.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp index a3b0d57be..70c07af50 100644 --- a/src/WorldStorage/NBTChunkSerializer.cpp +++ b/src/WorldStorage/NBTChunkSerializer.cpp @@ -484,6 +484,7 @@ void cNBTChunkSerializer::AddMonsterEntity(cMonster * a_Monster) m_Writer.AddFloat("", a_Monster->GetDropChanceBoots()); m_Writer.EndList(); m_Writer.AddByte("CanPickUpLoot", (char)a_Monster->CanPickUpLoot()); + m_Writer.AddShort("Health", (short)a_Monster->GetHealth()); switch (a_Monster->GetMobType()) { case cMonster::mtBat: diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp index 1891762fd..f58e876e0 100644 --- a/src/WorldStorage/WSSAnvil.cpp +++ b/src/WorldStorage/WSSAnvil.cpp @@ -2456,6 +2456,7 @@ bool cWSSAnvil::LoadMonsterBaseFromNBT(cMonster & a_Monster, const cParsedNBT & a_Monster.SetDropChanceBoots(DropChance[4]); bool CanPickUpLoot = (a_NBT.GetByte(a_NBT.FindChildByName(a_TagIdx, "CanPickUpLoot")) == 1); a_Monster.SetCanPickUpLoot(CanPickUpLoot); + a_Monster.SetHealth(a_NBT.GetShort(a_NBT.FindChildByName(a_TagIdx, "Health"))); return true; } -- cgit v1.2.3 From ea49abd113050eb36fb85ac792cdab0e901b77e6 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Wed, 4 Jun 2014 20:52:54 +0100 Subject: Time and weather is saved, part of #1058 Also fixed unreliability in Health and LootPickup loading. --- src/World.cpp | 12 ++++++++++++ src/WorldStorage/WSSAnvil.cpp | 13 ++++++++++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/World.cpp b/src/World.cpp index 345c894eb..739ae39d4 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -11,6 +11,7 @@ #include "ChunkMap.h" #include "Generating/ChunkDesc.h" #include "OSSupport/Timer.h" +#include // Serializers #include "WorldStorage/ScoreboardSerializer.h" @@ -569,6 +570,11 @@ void cWorld::Start(void) m_bUseChatPrefixes = IniFile.GetValueSetB("Mechanics", "UseChatPrefixes", true); m_VillagersShouldHarvestCrops = IniFile.GetValueSetB("Monsters", "VillagersShouldHarvestCrops", true); int GameMode = IniFile.GetValueSetI("General", "Gamemode", (int)m_GameMode); + int Weather = IniFile.GetValueSetI("General", "Weather", (int)m_Weather); + + std::stringstream ss; + ss << m_TimeOfDay; + Int64 TimeOfDay = _atoi64(IniFile.GetValueSet("General", "TimeInTicks", ss.str()).c_str()); if ((GetDimension() != dimNether) && (GetDimension() != dimEnd)) { @@ -581,6 +587,7 @@ void cWorld::Start(void) // Adjust the enum-backed variables into their respective bounds: m_GameMode = (eGameMode) Clamp(GameMode, (int)gmSurvival, (int)gmAdventure); m_TNTShrapnelLevel = (eShrapnelLevel)Clamp(TNTShrapnelLevel, (int)slNone, (int)slAll); + m_Weather = (eWeather) Clamp(Weather, (int)wSunny, (int)wStorm); switch (GetDimension()) { @@ -759,6 +766,11 @@ void cWorld::Stop(void) IniFile.SetValueI("Physics", "TNTShrapnelLevel", (int)m_TNTShrapnelLevel); IniFile.SetValueB("Mechanics", "CommandBlocksEnabled", m_bCommandBlocksEnabled); IniFile.SetValueB("Mechanics", "UseChatPrefixes", m_bUseChatPrefixes); + IniFile.SetValueI("General", "Weather", (int)m_Weather); + + std::stringstream ss; + ss << m_TimeOfDay; + IniFile.SetValue("General", "TimeInTicks", ss.str()); IniFile.WriteFile(m_IniFileName); m_TickThread.Stop(); diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp index f58e876e0..c84763ac2 100644 --- a/src/WorldStorage/WSSAnvil.cpp +++ b/src/WorldStorage/WSSAnvil.cpp @@ -2454,9 +2454,16 @@ bool cWSSAnvil::LoadMonsterBaseFromNBT(cMonster & a_Monster, const cParsedNBT & a_Monster.SetDropChanceChestplate(DropChance[2]); a_Monster.SetDropChanceLeggings(DropChance[3]); a_Monster.SetDropChanceBoots(DropChance[4]); - bool CanPickUpLoot = (a_NBT.GetByte(a_NBT.FindChildByName(a_TagIdx, "CanPickUpLoot")) == 1); - a_Monster.SetCanPickUpLoot(CanPickUpLoot); - a_Monster.SetHealth(a_NBT.GetShort(a_NBT.FindChildByName(a_TagIdx, "Health"))); + + int LootTag = a_NBT.FindChildByName(a_TagIdx, "CanPickUpLoot"); + if (LootTag > 0) + { + bool CanPickUpLoot = (a_NBT.GetByte(LootTag) == 1); + a_Monster.SetCanPickUpLoot(CanPickUpLoot); + } + + int HealthTag = a_NBT.FindChildByName(a_TagIdx, "Health"); + a_Monster.SetHealth(HealthTag > 0 ? a_NBT.GetShort(HealthTag) : a_Monster.GetMaxHealth()); return true; } -- cgit v1.2.3 From 873043c8e46dfd1ec764fbd5b673173ffe88271f Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Wed, 4 Jun 2014 21:51:19 +0100 Subject: Suggestions --- src/Entities/Entity.cpp | 6 ++++-- src/Entities/Player.cpp | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index 7d9c10ec6..2d8f385cb 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -1063,7 +1063,8 @@ void cEntity::DetectPortal() { case dimNether: { - cIniFile OwnIni; OwnIni.ReadFile(GetWorld()->GetIniFileName()); + cIniFile OwnIni; + OwnIni.ReadFile(GetWorld()->GetIniFileName()); AString OverworldName = OwnIni.GetValue("General", "OverworldName", cRoot::Get()->GetDefaultWorld()->GetName()); cFile::CreateFolder(FILE_IO_PREFIX + OverworldName); @@ -1102,7 +1103,8 @@ void cEntity::DetectPortal() { case dimEnd: { - cIniFile OwnIni; OwnIni.ReadFile(GetWorld()->GetIniFileName()); + cIniFile OwnIni; + OwnIni.ReadFile(GetWorld()->GetIniFileName()); AString OverworldName = OwnIni.GetValue("General", "OverworldName", cRoot::Get()->GetDefaultWorld()->GetName()); cFile::CreateFolder(FILE_IO_PREFIX + OverworldName); diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index eebc9ecf9..c2f384abf 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -89,6 +89,7 @@ cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName) SetPosX(World->GetSpawnX()); SetPosY(World->GetSpawnY()); SetPosZ(World->GetSpawnZ()); + SetBedPos(Vector3i(World->GetSpawnX(), World->GetSpawnY(), World->GetSpawnZ())); LOGD("Player \"%s\" is connecting for the first time, spawning at default world spawn {%.2f, %.2f, %.2f}", a_PlayerName.c_str(), GetPosX(), GetPosY(), GetPosZ() -- cgit v1.2.3 From f22a1b226ca1f5969ab9882c3f9c6f00c6c90aa2 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Thu, 5 Jun 2014 08:25:26 +0100 Subject: Fixed compilation --- src/Entities/Player.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index c2f384abf..af4299e4b 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -1576,7 +1576,7 @@ bool cPlayer::MoveToWorld(const AString & a_WorldName, cWorld * a_World) World = cRoot::Get()->GetWorld(a_WorldName); if (World == NULL) { - LOG("%s: Couldn't find world \"%s\".", __FUNCTION__, a_WorldName); + LOG("%s: Couldn't find world \"%s\".", __FUNCTION__, a_WorldName.c_str()); return false; } } -- cgit v1.2.3 From b73bf1a1e37a9455ff32cef37d23e0441d6ec555 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Thu, 5 Jun 2014 08:28:01 +0100 Subject: Fixed decision failure --- src/Mobs/Monster.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp index c25ee6b75..0f030da2d 100644 --- a/src/Mobs/Monster.cpp +++ b/src/Mobs/Monster.cpp @@ -1034,7 +1034,7 @@ void cMonster::HandleDaylightBurning(cChunk & a_Chunk) (a_Chunk.GetBlock(RelX, RelY, RelZ) != E_BLOCK_SOULSAND) && // Not on soulsand (GetWorld()->GetTimeOfDay() < (12000 + 1000)) && // It is nighttime !IsOnFire() && // Not already burning - (IsBiomeNoDownfall(a_Chunk.GetBiomeAt(RelX, RelZ)) || GetWorld()->IsWeatherWet()) // Not raining + (IsBiomeNoDownfall(a_Chunk.GetBiomeAt(RelX, RelZ)) || !GetWorld()->IsWeatherWet()) // Not raining ) { // Burn for 100 ticks, then decide again -- cgit v1.2.3 From 156c9851b8a099656fa86ea52d989e35e5b7ebf1 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Thu, 5 Jun 2014 17:58:29 +0100 Subject: Suggestions --- lib/inifile/iniFile.cpp | 20 ++++++++++++++++++++ lib/inifile/iniFile.h | 2 ++ src/Blocks/WorldInterface.h | 4 +++- src/Chunk.cpp | 7 +++++-- src/Generating/ChunkGenerator.cpp | 2 +- src/World.cpp | 11 ++--------- src/World.h | 4 +++- 7 files changed, 36 insertions(+), 14 deletions(-) diff --git a/lib/inifile/iniFile.cpp b/lib/inifile/iniFile.cpp index ea03f5d35..7515483df 100644 --- a/lib/inifile/iniFile.cpp +++ b/lib/inifile/iniFile.cpp @@ -447,6 +447,15 @@ bool cIniFile::SetValueI(const AString & a_KeyName, const AString & a_ValueName, +bool cIniFile::SetValueI(const AString & a_Keyname, const AString & a_ValueName, const Int64 a_Value, const bool a_CreateIfNotExists) +{ + return SetValue(a_Keyname, a_ValueName, Printf("lld", a_Value), a_CreateIfNotExists); +} + + + + + bool cIniFile::SetValueF(const AString & a_KeyName, const AString & a_ValueName, double const a_Value, const bool a_CreateIfNotExists) { return SetValue(a_KeyName, a_ValueName, Printf("%f", a_Value), a_CreateIfNotExists); @@ -571,6 +580,17 @@ int cIniFile::GetValueSetI(const AString & keyname, const AString & valuename, c +Int64 cIniFile::GetValueSetI(const AString & keyname, const AString & valuename, const Int64 defValue) +{ + AString Data; + Printf(Data, "%lld", defValue); + return std::stoll(GetValueSet(keyname, valuename, Data)); +} + + + + + bool cIniFile::DeleteValueByID(const int keyID, const int valueID) { if ((keyID < (int)keys.size()) && (valueID < (int)keys[keyID].names.size())) diff --git a/lib/inifile/iniFile.h b/lib/inifile/iniFile.h index 0bf1d917e..58fecd0cf 100644 --- a/lib/inifile/iniFile.h +++ b/lib/inifile/iniFile.h @@ -119,6 +119,7 @@ public: AString GetValueSet (const AString & keyname, const AString & valuename, const AString & defValue = ""); double GetValueSetF(const AString & keyname, const AString & valuename, const double defValue = 0.0); int GetValueSetI(const AString & keyname, const AString & valuename, const int defValue = 0); + Int64 GetValueSetI(const AString & keyname, const AString & valuename, const Int64 defValue = 0); bool GetValueSetB(const AString & keyname, const AString & valuename, const bool defValue = false) { return (GetValueSetI(keyname, valuename, defValue ? 1 : 0) != 0); @@ -141,6 +142,7 @@ public: bool SetValue (const int keyID, const int valueID, const AString & value); bool SetValue (const AString & a_KeyName, const AString & a_ValueName, const AString & a_Value, const bool a_CreateIfNotExists = true); bool SetValueI(const AString & a_KeyName, const AString & a_ValueName, const int a_Value, const bool a_CreateIfNotExists = true); + bool SetValueI(const AString & a_Keyname, const AString & a_ValueName, const Int64 a_Value, const bool a_CreateIfNotExists = true); bool SetValueB(const AString & a_KeyName, const AString & a_ValueName, const bool a_Value, const bool a_CreateIfNotExists = true) { return SetValueI(a_KeyName, a_ValueName, int(a_Value), a_CreateIfNotExists); diff --git a/src/Blocks/WorldInterface.h b/src/Blocks/WorldInterface.h index 08600d502..7df82197e 100644 --- a/src/Blocks/WorldInterface.h +++ b/src/Blocks/WorldInterface.h @@ -37,7 +37,9 @@ public: virtual void SetTimeOfDay(Int64 a_TimeOfDay) = 0; - /** Returns true if the current weather has any precipitation - rain or storm */ + /** Returns true if the current weather has any precipitation - rain or storm + Does not check if biome has no downfall, use cChunk::GetBiomeAt(RelX, RelZ) for that + */ virtual bool IsWeatherWet(void) const = 0; }; diff --git a/src/Chunk.cpp b/src/Chunk.cpp index c6122852a..2850dd93b 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -580,7 +580,10 @@ void cChunk::Tick(float a_Dt) { // Mobs are tickes inside MobTick (as we don't have to tick them if they are far away from players) // Don't tick things queued to be removed - if (!((*itr)->IsMob()) && (std::find(m_EntitiesToRemove.begin(), m_EntitiesToRemove.end(), (*itr)->GetUniqueID()) == m_EntitiesToRemove.end())) + if ( + !((*itr)->IsMob()) && + (std::find(m_EntitiesToRemove.begin(), m_EntitiesToRemove.end(), (*itr)->GetUniqueID()) == m_EntitiesToRemove.end()) + ) { (*itr)->Tick(a_Dt, *this); } @@ -588,7 +591,7 @@ void cChunk::Tick(float a_Dt) for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end();) { - std::vector::const_iterator itr2 = std::find(m_EntitiesToRemove.begin(), m_EntitiesToRemove.end(), (*itr)->GetUniqueID()); + std::vector::iterator itr2 = std::find(m_EntitiesToRemove.begin(), m_EntitiesToRemove.end(), (*itr)->GetUniqueID()); if (itr2 != m_EntitiesToRemove.end()) { itr = m_Entities.erase(itr); diff --git a/src/Generating/ChunkGenerator.cpp b/src/Generating/ChunkGenerator.cpp index 73f0223e8..1f2958901 100644 --- a/src/Generating/ChunkGenerator.cpp +++ b/src/Generating/ChunkGenerator.cpp @@ -52,7 +52,7 @@ bool cChunkGenerator::Start(cPluginInterface & a_PluginInterface, cChunkSink & a m_ChunkSink = &a_ChunkSink; MTRand rnd; - m_Seed = a_IniFile.GetValueSetI("Seed", "Seed", rnd.randInt()); + m_Seed = a_IniFile.GetValueSetI("Seed", "Seed", (int)rnd.randInt()); AString GeneratorName = a_IniFile.GetValueSet("Generator", "Generator", "Composable"); if (NoCaseCompare(GeneratorName, "Noise3D") == 0) diff --git a/src/World.cpp b/src/World.cpp index 739ae39d4..3e02caf8e 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -11,7 +11,6 @@ #include "ChunkMap.h" #include "Generating/ChunkDesc.h" #include "OSSupport/Timer.h" -#include // Serializers #include "WorldStorage/ScoreboardSerializer.h" @@ -571,10 +570,7 @@ void cWorld::Start(void) m_VillagersShouldHarvestCrops = IniFile.GetValueSetB("Monsters", "VillagersShouldHarvestCrops", true); int GameMode = IniFile.GetValueSetI("General", "Gamemode", (int)m_GameMode); int Weather = IniFile.GetValueSetI("General", "Weather", (int)m_Weather); - - std::stringstream ss; - ss << m_TimeOfDay; - Int64 TimeOfDay = _atoi64(IniFile.GetValueSet("General", "TimeInTicks", ss.str()).c_str()); + Int64 TimeOfDay = IniFile.GetValueSetI("General", "TimeInTicks", m_TimeOfDay); if ((GetDimension() != dimNether) && (GetDimension() != dimEnd)) { @@ -767,10 +763,7 @@ void cWorld::Stop(void) IniFile.SetValueB("Mechanics", "CommandBlocksEnabled", m_bCommandBlocksEnabled); IniFile.SetValueB("Mechanics", "UseChatPrefixes", m_bUseChatPrefixes); IniFile.SetValueI("General", "Weather", (int)m_Weather); - - std::stringstream ss; - ss << m_TimeOfDay; - IniFile.SetValue("General", "TimeInTicks", ss.str()); + IniFile.SetValueI("General", "TimeInTicks", m_TimeOfDay); IniFile.WriteFile(m_IniFileName); m_TickThread.Stop(); diff --git a/src/World.h b/src/World.h index 7b87a76ac..80f69f22f 100644 --- a/src/World.h +++ b/src/World.h @@ -715,7 +715,9 @@ public: bool IsWeatherRain (void) const { return (m_Weather == wRain); } bool IsWeatherStorm(void) const { return (m_Weather == wStorm); } - /** Returns true if the current weather has any precipitation - rain or storm */ + /** Returns true if the current weather has any precipitation - rain or storm + Does not check if biome has no downfall, use cChunk::GetBiomeAt(RelX, RelZ) for that + */ virtual bool IsWeatherWet(void) const override { return (m_Weather != wSunny); } // tolua_end -- cgit v1.2.3 From 43342540c80169c1d539751cfd48cae99d97e058 Mon Sep 17 00:00:00 2001 From: worktycho Date: Fri, 6 Jun 2014 23:54:24 +0100 Subject: Fixed Time of day --- src/World.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/World.cpp b/src/World.cpp index 3e02caf8e..1b5582b81 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -570,7 +570,7 @@ void cWorld::Start(void) m_VillagersShouldHarvestCrops = IniFile.GetValueSetB("Monsters", "VillagersShouldHarvestCrops", true); int GameMode = IniFile.GetValueSetI("General", "Gamemode", (int)m_GameMode); int Weather = IniFile.GetValueSetI("General", "Weather", (int)m_Weather); - Int64 TimeOfDay = IniFile.GetValueSetI("General", "TimeInTicks", m_TimeOfDay); + m_TimeOfDay = IniFile.GetValueSetI("General", "TimeInTicks", m_TimeOfDay); if ((GetDimension() != dimNether) && (GetDimension() != dimEnd)) { -- cgit v1.2.3 From 3275bbf01b79eefb77861cca1fa4fd79c6ae1403 Mon Sep 17 00:00:00 2001 From: worktycho Date: Sat, 7 Jun 2014 00:10:58 +0100 Subject: Fix reading 64 bit values --- lib/inifile/iniFile.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/inifile/iniFile.cpp b/lib/inifile/iniFile.cpp index 7515483df..0c208b953 100644 --- a/lib/inifile/iniFile.cpp +++ b/lib/inifile/iniFile.cpp @@ -449,7 +449,7 @@ bool cIniFile::SetValueI(const AString & a_KeyName, const AString & a_ValueName, bool cIniFile::SetValueI(const AString & a_Keyname, const AString & a_ValueName, const Int64 a_Value, const bool a_CreateIfNotExists) { - return SetValue(a_Keyname, a_ValueName, Printf("lld", a_Value), a_CreateIfNotExists); + return SetValue(a_Keyname, a_ValueName, Printf("%lld", a_Value), a_CreateIfNotExists); } @@ -584,7 +584,10 @@ Int64 cIniFile::GetValueSetI(const AString & keyname, const AString & valuename, { AString Data; Printf(Data, "%lld", defValue); - return std::stoll(GetValueSet(keyname, valuename, Data)); + Astring resultstring = GetValueSet(keyname, valuename, Data); + Int64 result; + sscanf(resultstring.c_str(), "%lld", &result); + return result; } -- cgit v1.2.3 From b925eb4ad4fb02141915aa5392d8a0852f291355 Mon Sep 17 00:00:00 2001 From: worktycho Date: Sat, 7 Jun 2014 00:18:58 +0100 Subject: Capitalising --- lib/inifile/iniFile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/inifile/iniFile.cpp b/lib/inifile/iniFile.cpp index 0c208b953..66410b901 100644 --- a/lib/inifile/iniFile.cpp +++ b/lib/inifile/iniFile.cpp @@ -584,7 +584,7 @@ Int64 cIniFile::GetValueSetI(const AString & keyname, const AString & valuename, { AString Data; Printf(Data, "%lld", defValue); - Astring resultstring = GetValueSet(keyname, valuename, Data); + AString resultstring = GetValueSet(keyname, valuename, Data); Int64 result; sscanf(resultstring.c_str(), "%lld", &result); return result; -- cgit v1.2.3 From 35b79e5d710862f957bc494638a8d8906992665d Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 10 Jun 2014 20:43:27 +0100 Subject: Portal improvements and suggestions --- lib/inifile/iniFile.cpp | 4 ++ src/BlockID.cpp | 35 +++++++++++++ src/BlockID.h | 7 ++- src/Chunk.cpp | 15 +++++- src/Entities/Entity.cpp | 130 +++++++++++++++++++++++++++++++++--------------- src/Entities/Entity.h | 3 ++ src/Root.cpp | 6 +-- src/Root.h | 2 +- src/World.cpp | 18 +++++-- src/World.h | 13 ++++- 10 files changed, 179 insertions(+), 54 deletions(-) diff --git a/lib/inifile/iniFile.cpp b/lib/inifile/iniFile.cpp index 66410b901..30f93e5a3 100644 --- a/lib/inifile/iniFile.cpp +++ b/lib/inifile/iniFile.cpp @@ -586,7 +586,11 @@ Int64 cIniFile::GetValueSetI(const AString & keyname, const AString & valuename, Printf(Data, "%lld", defValue); AString resultstring = GetValueSet(keyname, valuename, Data); Int64 result; +#ifdef _WIN32 + sscanf_s(resultstring.c_str(), "%lld", &result); +#else sscanf(resultstring.c_str(), "%lld", &result); +#endif return result; } diff --git a/src/BlockID.cpp b/src/BlockID.cpp index bfe826f40..641a6a225 100644 --- a/src/BlockID.cpp +++ b/src/BlockID.cpp @@ -345,6 +345,41 @@ eDimension StringToDimension(const AString & a_DimensionString) +AString DimensionToString(eDimension a_Dimension) +{ + // Decode using a built-in map: + static struct + { + eDimension m_Dimension; + const char * m_String; + } DimensionMap[] = + { + { dimOverworld, "Overworld" }, + { dimOverworld, "Normal" }, + { dimOverworld, "World" }, + { dimNether, "Nether" }, + { dimNether, "Hell" }, // Alternate name for Nether + { dimEnd, "End" }, + { dimEnd, "Sky" }, // Old name for End + }; + + for (size_t i = 0; i < ARRAYCOUNT(DimensionMap); i++) + { + if (DimensionMap[i].m_Dimension == a_Dimension) + { + return DimensionMap[i].m_String; + } + } // for i - DimensionMap[] + + // Not found + LOGWARNING("Unknown dimension: \"%i\". Setting to Overworld", (int)a_Dimension); + return "Overworld"; +} + + + + + /// Translates damage type constant to a string representation (built-in). AString DamageTypeToString(eDamageType a_DamageType) { diff --git a/src/BlockID.h b/src/BlockID.h index a227245aa..97c1aae86 100644 --- a/src/BlockID.h +++ b/src/BlockID.h @@ -916,9 +916,14 @@ extern AString ItemToFullString(const cItem & a_Item); /// Translates a mob string ("ocelot") to mobtype (E_ENTITY_TYPE_OCELOT) extern int StringToMobType(const AString & a_MobString); -/// Translates a dimension string to dimension enum. Takes either a number or a dimension alias (built-in). Returns -1000 on failure +/// Translates a dimension string to dimension enum. Takes either a number or a dimension alias (built-in). Returns dimOverworld on failure extern eDimension StringToDimension(const AString & a_DimensionString); +/** Translates a dimension enum to dimension string. +Takes a string and returns "Overworld" on failure +*/ +extern AString DimensionToString(eDimension a_Dimension); + /// Translates damage type constant to a string representation (built-in). extern AString DamageTypeToString(eDamageType a_DamageType); diff --git a/src/Chunk.cpp b/src/Chunk.cpp index 2850dd93b..02857ba5a 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -1859,7 +1859,20 @@ void cChunk::AddEntity(cEntity * a_Entity) MarkDirty(); } - ASSERT(std::find(m_Entities.begin(), m_Entities.end(), a_Entity) == m_Entities.end()); // Not there already + if (std::find(m_Entities.begin(), m_Entities.end(), a_Entity) != m_Entities.end()) + { + // Not there already + std::vector::iterator itr = std::find(m_EntitiesToRemove.begin(), m_EntitiesToRemove.end(), a_Entity->GetUniqueID()); + if (itr != m_EntitiesToRemove.end()) + { + m_EntitiesToRemove.erase(itr); + return; + } + else + { + ASSERT(!"Entity already present when AddEntity was called!"); + } + } m_Entities.push_back(a_Entity); } diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index 2d8f385cb..4b376a1fe 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -12,6 +12,7 @@ #include "../Bindings/PluginManager.h" #include "../Tracer.h" #include "Player.h" +#include "BlockArea.h" @@ -1047,6 +1048,28 @@ void cEntity::DetectPortal() return; } + class cPortalChunkLoader : public cChunkStay + { + public: + cPortalChunkLoader(cEntity * a_Entity, Vector3i & a_PortalPos) : + m_Entity(a_Entity), + m_PortalPos(a_PortalPos) + {} + + private: + virtual bool OnAllChunksAvailable(void) override + { + m_Entity->CreateExitPortal(m_PortalPos.x, m_PortalPos.y, m_PortalPos.z); + return true; + } + + virtual void OnChunkAvailable(int a_ChunkX, int a_ChunkZ) override {}; + virtual void OnDisabled(void) override {}; + + cEntity * m_Entity; + Vector3i m_PortalPos; + }; + int X = POSX_TOINT, Y = POSY_TOINT, Z = POSZ_TOINT; if ((Y > 0) && (Y < cChunkDef::Height)) { @@ -1061,31 +1084,31 @@ void cEntity::DetectPortal() switch (GetWorld()->GetDimension()) { - case dimNether: + case dimNether: MoveToWorld(GetWorld()->GetLinkedOverworldName(), cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedOverworldName())); break; + case dimOverworld: { - cIniFile OwnIni; - OwnIni.ReadFile(GetWorld()->GetIniFileName()); - AString OverworldName = OwnIni.GetValue("General", "OverworldName", cRoot::Get()->GetDefaultWorld()->GetName()); + if (IsPlayer()) + { + ((cPlayer *)this)->AwardAchievement(achEnterPortal); + } + MoveToWorld(GetWorld()->GetNetherWorldName(), cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetNetherWorldName(), dimNether, GetWorld()->GetName())); + + cChunkStay * Stay = new cPortalChunkLoader(this, Vector3i(X, Y, Z)); - cFile::CreateFolder(FILE_IO_PREFIX + OverworldName); - cIniFile File; - File.ReadFile(OverworldName + "/world.ini"); - File.SetValue("General", "Dimension", "Overworld"); - File.WriteFile(OverworldName + "/world.ini"); + int MinChunkX, MaxChunkX; + int MinChunkZ, MaxChunkZ; + cChunkDef::BlockToChunk(X - 128, Z - 128, MinChunkX, MinChunkZ); + cChunkDef::BlockToChunk(X + 128, Z + 128, MaxChunkX, MaxChunkZ); - MoveToWorld(OverworldName, cRoot::Get()->CreateAndInitializeWorld(OverworldName)); - break; - } - case dimOverworld: - { - cFile::CreateFolder(FILE_IO_PREFIX + GetWorld()->GetNetherWorldName()); - cIniFile File; - File.ReadFile(GetWorld()->GetNetherWorldName() + "/world.ini"); - File.SetValue("General", "Dimension", "Nether"); - File.SetValue("General", "OverworldName", GetWorld()->GetName()); - File.WriteFile(GetWorld()->GetNetherWorldName() + "/world.ini"); - - MoveToWorld(GetWorld()->GetNetherWorldName(), cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetNetherWorldName())); + for (int OtherMinChunkX = MinChunkX; OtherMinChunkX <= MaxChunkX; ++OtherMinChunkX) + { + for (int OtherMinChunkZ = MinChunkZ; OtherMinChunkZ <= MaxChunkZ; ++OtherMinChunkZ) + { + Stay->Add(OtherMinChunkX, OtherMinChunkZ); + } + } + + Stay->Enable(*GetWorld()->GetChunkMap()); break; } default: break; @@ -1103,17 +1126,7 @@ void cEntity::DetectPortal() { case dimEnd: { - cIniFile OwnIni; - OwnIni.ReadFile(GetWorld()->GetIniFileName()); - AString OverworldName = OwnIni.GetValue("General", "OverworldName", cRoot::Get()->GetDefaultWorld()->GetName()); - - 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)); + MoveToWorld(GetWorld()->GetLinkedOverworldName(), cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedOverworldName())); if (IsPlayer()) { @@ -1124,14 +1137,11 @@ void cEntity::DetectPortal() } case dimOverworld: { - cFile::CreateFolder(FILE_IO_PREFIX + GetWorld()->GetEndWorldName()); - cIniFile File; - File.ReadFile(GetWorld()->GetEndWorldName() + "/world.ini"); - File.SetValue("General", "Dimension", "End"); - File.SetValue("General", "OverworldName", GetWorld()->GetName()); - File.WriteFile(GetWorld()->GetEndWorldName() + "/world.ini"); - - MoveToWorld(GetWorld()->GetEndWorldName(), cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetEndWorldName())); + if (IsPlayer()) + { + ((cPlayer *)this)->AwardAchievement(achEnterTheEnd); + } + MoveToWorld(GetWorld()->GetEndWorldName(), cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetEndWorldName(), dimEnd, GetWorld()->GetName())); break; } default: break; @@ -1146,6 +1156,44 @@ void cEntity::DetectPortal() +void cEntity::CreateExitPortal(int a_BlockX, int a_BlockY, int a_BlockZ) +{ + cBlockArea Area; + Area.Read(GetWorld(), a_BlockX - 128, a_BlockX + 128, 0, 128, a_BlockZ - 128, a_BlockZ + 128); + for (int x = a_BlockX - 128; x <= a_BlockX + 128; ++x) for (int y = 0; y <= 128; ++y) for (int z = a_BlockZ - 128; z <= a_BlockZ + 128; ++z) + { + if ( + (Area.GetBlockType(x, y, z) == E_BLOCK_NETHER_PORTAL) && + ( + (Area.GetBlockType(x, (int)floor(y + GetHeight()), z) == E_BLOCK_NETHER_PORTAL) || + (Area.GetBlockType(x, (int)floor(y - GetHeight()), z) == E_BLOCK_NETHER_PORTAL) + ) + ) + { + TeleportToCoords(x, y, z); + return; + } + } + + int MinX = std::max(a_BlockX - (int)ceil(GetWidth()), a_BlockX - 2), MaxX = std::max(a_BlockX + (int)ceil(GetWidth()), a_BlockX + 1); + int MinY = std::max(a_BlockY - (int)ceil(GetHeight()), a_BlockY - 2), MaxY = std::max(a_BlockY + (int)ceil(GetHeight()), a_BlockY + 1); + + for (int y = MinY; y < MaxY + 1; y += MaxY - MinY) for (int x = MinX; x < MaxX + 1; ++x) + { + Area.SetBlockType(x, y, a_BlockZ, E_BLOCK_OBSIDIAN); + } + for (int y = MinY; y < MaxY + 1; ++y) for (int x = MinX; x < MaxX + 1; x += MaxX - MinX) + { + Area.SetBlockType(x, y, a_BlockZ, E_BLOCK_OBSIDIAN); + } + + Area.Write(GetWorld(), MinX, MinY, a_BlockZ); +} + + + + + bool cEntity::MoveToWorld(const AString & a_WorldName, cWorld * a_World) { cWorld * World; diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h index da8256606..b2317aaac 100644 --- a/src/Entities/Entity.h +++ b/src/Entities/Entity.h @@ -335,6 +335,9 @@ public: /// Called when the entity finishes burning virtual void OnFinishedBurning(void); + + /** Creates exit portal at given coordinates */ + void CreateExitPortal(int a_BlockX, int a_BlockY, int a_BlockZ); // tolua_begin diff --git a/src/Root.cpp b/src/Root.cpp index 2a80baeb3..572cbf1fc 100644 --- a/src/Root.cpp +++ b/src/Root.cpp @@ -314,15 +314,15 @@ void cRoot::LoadWorlds(cIniFile & IniFile) -cWorld * cRoot::CreateAndInitializeWorld(const AString & a_WorldName) +cWorld * cRoot::CreateAndInitializeWorld(const AString & a_WorldName, eDimension a_Dimension, const AString & a_OverworldName) { if (m_WorldsByName[a_WorldName] != NULL) { return NULL; } - cWorld * NewWorld = new cWorld(a_WorldName.c_str()); + cWorld * NewWorld = new cWorld(a_WorldName.c_str(), a_Dimension, a_OverworldName); m_WorldsByName[a_WorldName] = NewWorld; - NewWorld->Start(); + NewWorld->Start(!a_OverworldName.empty()); NewWorld->InitializeSpawn(); m_PluginManager->CallHookWorldStarted(*NewWorld); return NewWorld; diff --git a/src/Root.h b/src/Root.h index d2a4d1eed..1b56b4528 100644 --- a/src/Root.h +++ b/src/Root.h @@ -44,7 +44,7 @@ public: cServer * GetServer(void) { return m_Server; } // tolua_export cWorld * GetDefaultWorld(void); // tolua_export cWorld * GetWorld(const AString & a_WorldName); // tolua_export - cWorld * CreateAndInitializeWorld(const AString & a_WorldName); // tolua_export + cWorld * CreateAndInitializeWorld(const AString & a_WorldName, eDimension a_Dimension = dimOverworld, const AString & a_OverworldName = ""); // tolua_export /// Calls the callback for each world; returns true if the callback didn't abort (return true) bool ForEachWorld(cWorldListCallback & a_Callback); // >> Exported in ManualBindings << diff --git a/src/World.cpp b/src/World.cpp index 1b5582b81..1f4a88fa0 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -232,7 +232,7 @@ void cWorld::cTickThread::Execute(void) /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cWorld: -cWorld::cWorld(const AString & a_WorldName) : +cWorld::cWorld(const AString & a_WorldName, eDimension a_Dimension, const AString & a_OverworldName) : m_WorldName(a_WorldName), m_IniFileName(m_WorldName + "/world.ini"), m_StorageSchema("Default"), @@ -253,7 +253,9 @@ cWorld::cWorld(const AString & a_WorldName) : m_Scoreboard(this), m_MapManager(this), m_GeneratorCallbacks(*this), - m_TickThread(*this) + m_TickThread(*this), + m_Dimension(a_Dimension), + m_OverworldName(a_OverworldName) { LOGD("cWorld::cWorld(\"%s\")", a_WorldName.c_str()); @@ -511,7 +513,7 @@ void cWorld::InitializeSpawn(void) -void cWorld::Start(void) +void cWorld::Start(bool a_WasDimensionSet) { m_SpawnX = 0; m_SpawnY = cChunkDef::Height; @@ -523,8 +525,10 @@ void cWorld::Start(void) { LOGWARNING("Cannot read world settings from \"%s\", defaults will be used.", m_IniFileName.c_str()); } - AString Dimension = IniFile.GetValueSet("General", "Dimension", "Overworld"); + + AString Dimension = IniFile.GetValueSet("General", "Dimension", a_WasDimensionSet ? DimensionToString(GetDimension()) : "Overworld"); m_Dimension = StringToDimension(Dimension); + m_OverworldName = IniFile.GetValue("General", "OverworldName", a_WasDimensionSet ? m_OverworldName : ""); // Try to find the "SpawnPosition" key and coord values in the world configuration, set the flag if found int KeyNum = IniFile.FindKey("SpawnPosition"); @@ -570,7 +574,7 @@ void cWorld::Start(void) m_VillagersShouldHarvestCrops = IniFile.GetValueSetB("Monsters", "VillagersShouldHarvestCrops", true); int GameMode = IniFile.GetValueSetI("General", "Gamemode", (int)m_GameMode); int Weather = IniFile.GetValueSetI("General", "Weather", (int)m_Weather); - m_TimeOfDay = IniFile.GetValueSetI("General", "TimeInTicks", m_TimeOfDay); + m_TimeOfDay = IniFile.GetValueSetI("General", "TimeInTicks", m_TimeOfDay); if ((GetDimension() != dimNether) && (GetDimension() != dimEnd)) { @@ -759,6 +763,10 @@ void cWorld::Stop(void) IniFile.SetValueB("General", "EndPortalsEnabled", m_bEndPortalsEnabled); IniFile.SetValue("General", "EndWorldName", m_EndWorldName); } + else + { + IniFile.SetValue("General", "OverworldName", m_OverworldName); + } IniFile.SetValueI("Physics", "TNTShrapnelLevel", (int)m_TNTShrapnelLevel); IniFile.SetValueB("Mechanics", "CommandBlocksEnabled", m_bCommandBlocksEnabled); IniFile.SetValueB("Mechanics", "UseChatPrefixes", m_bUseChatPrefixes); diff --git a/src/World.h b/src/World.h index 80f69f22f..676c5d69a 100644 --- a/src/World.h +++ b/src/World.h @@ -636,6 +636,9 @@ public: AString GetEndWorldName(void) const { return m_EndWorldName; } void SetEndWorldName(const AString & a_Name) { m_EndWorldName = a_Name; } + + AString GetLinkedOverworldName(void) const { return m_OverworldName; } + void SetLinkedOverworldName(const AString & a_Name) { m_OverworldName = a_Name; } // tolua_end @@ -679,7 +682,7 @@ public: void InitializeSpawn(void); /** Starts threads that belong to this world */ - void Start(void); + void Start(bool a_WasDimensionSet = true); /** Stops threads that belong to this world (part of deinit) */ void Stop(void); @@ -816,6 +819,12 @@ private: AString m_WorldName; + + /** The name of the world that a portal in this world should link to + Only has effect if this world is a nether or end world, as it is used by entities to see which world to teleport to when in a portal + */ + AString m_OverworldName; + AString m_IniFileName; /** Name of the storage schema used to load and save chunks */ @@ -953,7 +962,7 @@ private: cClientHandleList m_ClientsToAdd; - cWorld(const AString & a_WorldName); + cWorld(const AString & a_WorldName, eDimension a_Dimension = dimOverworld, const AString & a_OverworldName = ""); virtual ~cWorld(); void Tick(float a_Dt, int a_LastTickDurationMSec); -- cgit v1.2.3 From 29567c56107c86b70da130f995564beb2eaf424c Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Thu, 12 Jun 2014 15:21:07 +0100 Subject: Portals animate and delay correctly --- MCServer/furnace.txt | 2 +- src/Chunk.cpp | 74 ++++++++++------------ src/Chunk.h | 2 +- src/ChunkMap.cpp | 1 + src/ClientHandle.cpp | 7 +-- src/ClientHandle.h | 2 +- src/Entities/Entity.cpp | 121 +++++++++++++++++++++++++++--------- src/Entities/Entity.h | 10 ++- src/Entities/Player.cpp | 21 ++----- src/Entities/Player.h | 10 +-- src/Protocol/Protocol.h | 2 +- src/Protocol/Protocol125.cpp | 8 +-- src/Protocol/Protocol125.h | 2 +- src/Protocol/Protocol16x.cpp | 4 +- src/Protocol/Protocol16x.h | 2 +- src/Protocol/Protocol17x.cpp | 8 +-- src/Protocol/Protocol17x.h | 2 +- src/Protocol/ProtocolRecognizer.cpp | 4 +- src/Protocol/ProtocolRecognizer.h | 2 +- src/World.cpp | 9 ++- 20 files changed, 175 insertions(+), 118 deletions(-) diff --git a/MCServer/furnace.txt b/MCServer/furnace.txt index 1e98583ba..229a939ff 100644 --- a/MCServer/furnace.txt +++ b/MCServer/furnace.txt @@ -87,4 +87,4 @@ ! 271:1 = 200 # 1 Wooden Axe -> 10 sec ! 269:1 = 200 # 1 Wooden Shovel -> 10 sec ! 290:1 = 200 # 1 Wooden Hoe -> 10 sec -! 268:1 = 200 # 1 Wooden Sword -> 10 sec +! 268:1 = 200 # 1 Wooden Sword -> 10 sec \ No newline at end of file diff --git a/src/Chunk.cpp b/src/Chunk.cpp index 399c8b9c7..c9e4f5411 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -85,7 +85,8 @@ cChunk::cChunk( m_NeighborZM(a_NeighborZM), m_NeighborZP(a_NeighborZP), m_WaterSimulatorData(a_World->GetWaterSimulator()->CreateChunkData()), - m_LavaSimulatorData (a_World->GetLavaSimulator ()->CreateChunkData()) + m_LavaSimulatorData (a_World->GetLavaSimulator ()->CreateChunkData()), + m_EntityTickIteratorData(std::make_pair(false, &m_Entities.end())) { if (a_NeighborXM != NULL) { @@ -576,26 +577,38 @@ void cChunk::Tick(float a_Dt) } // Tick all entities in this chunk (except mobs): - for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr) + m_EntityTickIteratorData.first = true; + for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end();) { - // Mobs are tickes inside MobTick (as we don't have to tick them if they are far away from players) + // Mobs are ticked inside cWorld::TickMobs() (as we don't have to tick them if they are far away from players) // Don't tick things queued to be removed - if ( - !((*itr)->IsMob()) && - (std::find(m_EntitiesToRemove.begin(), m_EntitiesToRemove.end(), (*itr)->GetUniqueID()) == m_EntitiesToRemove.end()) - ) + if (!((*itr)->IsMob())) { + m_EntityTickIteratorData.second = &itr; (*itr)->Tick(a_Dt, *this); + + if (itr != *m_EntityTickIteratorData.second) + { + itr = *m_EntityTickIteratorData.second; + } + else + { + ++itr; + } + continue; } + ++itr; } // for itr - m_Entitites[] + m_EntityTickIteratorData.first = false; for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end();) { - std::vector::iterator itr2 = std::find(m_EntitiesToRemove.begin(), m_EntitiesToRemove.end(), (*itr)->GetUniqueID()); - if (itr2 != m_EntitiesToRemove.end()) + 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); - m_EntitiesToRemove.erase(itr2); + delete ToDelete; } else if ( // If any entity moved out of the chunk, move it to the neighbor: ((*itr)->GetChunkX() != m_PosX) || @@ -607,17 +620,7 @@ void cChunk::Tick(float a_Dt) } else { - 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; - } + ++itr; } } // for itr - m_Entitites[] @@ -1860,20 +1863,7 @@ void cChunk::AddEntity(cEntity * a_Entity) MarkDirty(); } - if (std::find(m_Entities.begin(), m_Entities.end(), a_Entity) != m_Entities.end()) - { - // Not there already - std::vector::iterator itr = std::find(m_EntitiesToRemove.begin(), m_EntitiesToRemove.end(), a_Entity->GetUniqueID()); - if (itr != m_EntitiesToRemove.end()) - { - m_EntitiesToRemove.erase(itr); - return; - } - else - { - ASSERT(!"Entity already present when AddEntity was called!"); - } - } + ASSERT(std::find(m_Entities.begin(), m_Entities.end(), a_Entity) == m_Entities.end()); m_Entities.push_back(a_Entity); } @@ -1884,7 +1874,14 @@ void cChunk::AddEntity(cEntity * a_Entity) void cChunk::RemoveEntity(cEntity * a_Entity) { - m_EntitiesToRemove.push_back(a_Entity->GetUniqueID()); + if (m_EntityTickIteratorData.first) + { + *m_EntityTickIteratorData.second = m_Entities.erase(*m_EntityTickIteratorData.second); + } + else + { + m_Entities.remove(a_Entity); + } // Mark as dirty if it was a server-generated entity: if (!a_Entity->IsPlayer()) @@ -1899,11 +1896,6 @@ void cChunk::RemoveEntity(cEntity * a_Entity) 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) { if ((*itr)->GetUniqueID() == a_EntityID) diff --git a/src/Chunk.h b/src/Chunk.h index 8123ac062..3046b2efe 100644 --- a/src/Chunk.h +++ b/src/Chunk.h @@ -425,7 +425,7 @@ private: // A critical section is not needed, because all chunk access is protected by its parent ChunkMap's csLayers cClientHandleList m_LoadedByClient; cEntityList m_Entities; - std::vector m_EntitiesToRemove; + std::pair m_EntityTickIteratorData; cBlockEntityList m_BlockEntities; /** Number of times the chunk has been requested to stay (by various cChunkStay objects); if zero, the chunk can be unloaded */ diff --git a/src/ChunkMap.cpp b/src/ChunkMap.cpp index dba6f3f41..d06b67b67 100644 --- a/src/ChunkMap.cpp +++ b/src/ChunkMap.cpp @@ -2398,6 +2398,7 @@ bool cChunkMap::ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinCh { for (int x = a_MinChunkX; x <= a_MaxChunkX; x++) { + LOG("Request %i %i", x, z); cChunkPtr Chunk = GetChunkNoLoad(x, ZERO_CHUNK_Y, z); if ((Chunk == NULL) || (!Chunk->IsValid())) { diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index 256dad7da..84f096d67 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -1766,8 +1766,7 @@ void cClientHandle::RemoveFromWorld(void) m_Protocol->SendUnloadChunk(itr->m_ChunkX, itr->m_ChunkZ); } // for itr - Chunks[] - // StreamChunks() called in cPlayer::MoveToWorld() after new world has been set - // Meanwhile here, we set last streamed values to bogus ones so everything is resent + // Here, we set last streamed values to bogus ones so everything is resent m_LastStreamedChunkX = 0x7fffffff; m_LastStreamedChunkZ = 0x7fffffff; m_HasSentPlayerChunk = false; @@ -2367,9 +2366,9 @@ void cClientHandle::SendRemoveEntityEffect(const cEntity & a_Entity, int a_Effec -void cClientHandle::SendRespawn(const cWorld & a_World) +void cClientHandle::SendRespawn(eDimension a_Dimension) { - m_Protocol->SendRespawn(a_World); + m_Protocol->SendRespawn(a_Dimension); } diff --git a/src/ClientHandle.h b/src/ClientHandle.h index 0d883f3af..99d10c3aa 100644 --- a/src/ClientHandle.h +++ b/src/ClientHandle.h @@ -149,7 +149,7 @@ public: void SendPlayerSpawn (const cPlayer & a_Player); void SendPluginMessage (const AString & a_Channel, const AString & a_Message); // Exported in ManualBindings.cpp void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID); - void SendRespawn (const cWorld & a_World); + void SendRespawn (eDimension a_Dimension); void SendExperience (void); void SendExperienceOrb (const cExpOrb & a_ExpOrb); void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode); diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index 334cf5aa7..a7b6cca27 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -1051,15 +1051,16 @@ void cEntity::DetectPortal() class cPortalChunkLoader : public cChunkStay { public: - cPortalChunkLoader(cEntity * a_Entity, Vector3i & a_PortalPos) : + cPortalChunkLoader(cEntity * a_Entity, cWorld & a_World, Vector3i & a_PortalPos) : m_Entity(a_Entity), - m_PortalPos(a_PortalPos) + m_PortalPos(a_PortalPos), + m_World(a_World) {} private: virtual bool OnAllChunksAvailable(void) override { - m_Entity->CreateExitPortal(m_PortalPos.x, m_PortalPos.y, m_PortalPos.z); + cEntity::CreateExitPortal(m_PortalPos.x, m_PortalPos.y, m_PortalPos.z, m_Entity->GetWidth(), m_Entity->GetHeight(), m_World, m_Entity->GetUniqueID()); return true; } @@ -1068,6 +1069,7 @@ void cEntity::DetectPortal() cEntity * m_Entity; Vector3i m_PortalPos; + cWorld & m_World; }; int X = POSX_TOINT, Y = POSY_TOINT, Z = POSZ_TOINT; @@ -1077,106 +1079,167 @@ void cEntity::DetectPortal() { case E_BLOCK_NETHER_PORTAL: { - if (!GetWorld()->AreNetherPortalsEnabled()) + if (!GetWorld()->AreNetherPortalsEnabled() || m_PortalCooldownData.second) { return; } + if (m_PortalCooldownData.first != 80) + { + m_PortalCooldownData.first++; + return; + } + m_PortalCooldownData.first = 0; + switch (GetWorld()->GetDimension()) { - case dimNether: MoveToWorld(GetWorld()->GetLinkedOverworldName(), cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedOverworldName())); break; + case dimNether: + { + m_PortalCooldownData.second = true; // Stop portals from working on respawn + + if (IsPlayer()) + { + ((cPlayer *)this)->GetClientHandle()->SendRespawn(dimOverworld); + } + MoveToWorld(GetWorld()->GetLinkedOverworldName(), cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedOverworldName()), false); + + return; + } case dimOverworld: { + m_PortalCooldownData.second = true; // Stop portals from working on respawn + if (IsPlayer()) { ((cPlayer *)this)->AwardAchievement(achEnterPortal); + ((cPlayer *)this)->GetClientHandle()->SendRespawn(dimNether); } - MoveToWorld(GetWorld()->GetNetherWorldName(), cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetNetherWorldName(), dimNether, GetWorld()->GetName())); + MoveToWorld(GetWorld()->GetNetherWorldName(), cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetNetherWorldName(), dimNether, GetWorld()->GetName()), false); - cChunkStay * Stay = new cPortalChunkLoader(this, Vector3i(X, Y, Z)); + cChunkStay * Stay = new cPortalChunkLoader(this, *cRoot::Get()->GetWorld(GetWorld()->GetNetherWorldName()), Vector3i(X, Y, Z)); int MinChunkX, MaxChunkX; int MinChunkZ, MaxChunkZ; cChunkDef::BlockToChunk(X - 128, Z - 128, MinChunkX, MinChunkZ); cChunkDef::BlockToChunk(X + 128, Z + 128, MaxChunkX, MaxChunkZ); - for (int OtherMinChunkX = MinChunkX; OtherMinChunkX <= MaxChunkX; ++OtherMinChunkX) + for (int ChunkX = MinChunkX; ChunkX <= MaxChunkX; ++ChunkX) { - for (int OtherMinChunkZ = MinChunkZ; OtherMinChunkZ <= MaxChunkZ; ++OtherMinChunkZ) + for (int ChunkZ = MinChunkZ; ChunkZ <= MaxChunkZ; ++ChunkZ) { - Stay->Add(OtherMinChunkX, OtherMinChunkZ); + LOG("Queue %i %i", ChunkX, ChunkZ); + Stay->Add(ChunkX, ChunkZ); } } Stay->Enable(*GetWorld()->GetChunkMap()); - break; + return; } default: break; } - break; + return; } case E_BLOCK_END_PORTAL: { - if (!GetWorld()->AreEndPortalsEnabled()) + if (!GetWorld()->AreEndPortalsEnabled() || m_PortalCooldownData.second) + { + return; + } + + if (m_PortalCooldownData.first != 80) { + m_PortalCooldownData.first++; return; } + m_PortalCooldownData.first = 0; switch (GetWorld()->GetDimension()) { case dimEnd: { - MoveToWorld(GetWorld()->GetLinkedOverworldName(), cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedOverworldName())); + m_PortalCooldownData.second = true; // Stop portals from working on respawn if (IsPlayer()) { cPlayer * Player = (cPlayer *)this; Player->TeleportToCoords(Player->GetLastBedPos().x, Player->GetLastBedPos().y, Player->GetLastBedPos().z); + Player->GetClientHandle()->SendRespawn(dimOverworld); } - break; + MoveToWorld(GetWorld()->GetLinkedOverworldName(), cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedOverworldName()), false); + + return; } case dimOverworld: { + m_PortalCooldownData.second = true; // Stop portals from working on respawn + if (IsPlayer()) { ((cPlayer *)this)->AwardAchievement(achEnterTheEnd); + ((cPlayer *)this)->GetClientHandle()->SendRespawn(dimEnd); } - MoveToWorld(GetWorld()->GetEndWorldName(), cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetEndWorldName(), dimEnd, GetWorld()->GetName())); - break; + MoveToWorld(GetWorld()->GetEndWorldName(), cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetEndWorldName(), dimEnd, GetWorld()->GetName()), false); + + return; } default: break; } + return; } default: break; } } + + // Allow portals to work again + m_PortalCooldownData.second = false; + m_PortalCooldownData.first = 0; } -void cEntity::CreateExitPortal(int a_BlockX, int a_BlockY, int a_BlockZ) +void cEntity::CreateExitPortal(int a_BlockX, int a_BlockY, int a_BlockZ, double a_EntityWidth, double a_EntityHeight, cWorld & a_World, int a_UniqueIDToTeleport) { cBlockArea Area; - Area.Read(GetWorld(), a_BlockX - 128, a_BlockX + 128, 0, 128, a_BlockZ - 128, a_BlockZ + 128); + Area.Read(&a_World, a_BlockX - 128, a_BlockX + 128, 0, 128, a_BlockZ - 128, a_BlockZ + 128); for (int x = a_BlockX - 128; x <= a_BlockX + 128; ++x) for (int y = 0; y <= 128; ++y) for (int z = a_BlockZ - 128; z <= a_BlockZ + 128; ++z) { if ( (Area.GetBlockType(x, y, z) == E_BLOCK_NETHER_PORTAL) && ( - (Area.GetBlockType(x, (int)floor(y + GetHeight()), z) == E_BLOCK_NETHER_PORTAL) || - (Area.GetBlockType(x, (int)floor(y - GetHeight()), z) == E_BLOCK_NETHER_PORTAL) + (Area.GetBlockType(x, (int)floor(y + a_EntityHeight), z) == E_BLOCK_NETHER_PORTAL) || + (Area.GetBlockType(x, (int)floor(y - a_EntityHeight), z) == E_BLOCK_NETHER_PORTAL) ) ) { - TeleportToCoords(x, y, z); + class cTeleportEntityToPortalCallback : public cEntityCallback + { + public: + cTeleportEntityToPortalCallback(int a_X, int a_Y, int a_Z) : + m_X(a_X), + m_Y(a_Y), + m_Z(a_Z) + {} + + virtual bool Item(cEntity * a_Entity) override + { + a_Entity->TeleportToCoords(m_X, m_Y, m_Z); + return true; + } + + private: + int m_X, m_Y, m_Z; + }; + + cTeleportEntityToPortalCallback TETPC(x, y, z); + a_World.DoWithEntityByID(a_UniqueIDToTeleport, TETPC); return; } } - int MinX = std::max(a_BlockX - (int)ceil(GetWidth()), a_BlockX - 2), MaxX = std::max(a_BlockX + (int)ceil(GetWidth()), a_BlockX + 1); - int MinY = std::max(a_BlockY - (int)ceil(GetHeight()), a_BlockY - 2), MaxY = std::max(a_BlockY + (int)ceil(GetHeight()), a_BlockY + 1); + int MinX = std::max(a_BlockX - (int)ceil(a_EntityWidth), a_BlockX - 2), MaxX = std::max(a_BlockX + (int)ceil(a_EntityWidth), a_BlockX + 1); + int MinY = std::max(a_BlockY - (int)ceil(a_EntityHeight), a_BlockY - 2), MaxY = std::max(a_BlockY + (int)ceil(a_EntityHeight), a_BlockY + 1); for (int y = MinY; y < MaxY + 1; y += MaxY - MinY) for (int x = MinX; x < MaxX + 1; ++x) { @@ -1187,15 +1250,17 @@ void cEntity::CreateExitPortal(int a_BlockX, int a_BlockY, int a_BlockZ) Area.SetBlockType(x, y, a_BlockZ, E_BLOCK_OBSIDIAN); } - Area.Write(GetWorld(), MinX, MinY, a_BlockZ); + Area.Write(&a_World, MinX, MinY, a_BlockZ); } -bool cEntity::MoveToWorld(const AString & a_WorldName, cWorld * a_World) +bool cEntity::MoveToWorld(const AString & a_WorldName, cWorld * a_World, bool a_ShouldSendRespawn) { + UNUSED(a_ShouldSendRespawn); + cWorld * World; if (a_World == NULL) { @@ -1213,6 +1278,7 @@ bool cEntity::MoveToWorld(const AString & a_WorldName, cWorld * a_World) if (GetWorld() == World) { + // Don't move to same world return false; } @@ -1220,8 +1286,7 @@ bool cEntity::MoveToWorld(const AString & a_WorldName, cWorld * a_World) GetWorld()->RemoveEntity(this); GetWorld()->BroadcastDestroyEntity(*this); - // Add to all the necessary parts of the new world - SetWorld(World); + // Queue add to new world World->AddEntity(this); return true; diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h index 934e0302b..4d922aa11 100644 --- a/src/Entities/Entity.h +++ b/src/Entities/Entity.h @@ -338,7 +338,7 @@ public: virtual void OnFinishedBurning(void); /** Creates exit portal at given coordinates */ - void CreateExitPortal(int a_BlockX, int a_BlockY, int a_BlockZ); + static void CreateExitPortal(int a_BlockX, int a_BlockY, int a_BlockZ, double a_EntityWidth, double a_EntityHeight, cWorld & a_World, int a_UniqueIDToTeleport); // tolua_begin @@ -374,7 +374,7 @@ public: 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); + virtual bool MoveToWorld(const AString & a_WorldName, cWorld * a_World = NULL, bool a_ShouldSendRespawn = true); // tolua_end @@ -510,6 +510,12 @@ protected: /** Air level of a mobile */ int m_AirLevel; int m_AirTickTimer; + + /** Portal delay timer and cooldown boolean + First value is to delay sending the repsawn packet (which triggers the Entering the {Dimension} screen). + Second value is to prevent a teleportation loop by ensuring we do not reenter a portal that we came out of. + */ + std::pair m_PortalCooldownData; private: /** Measured in degrees, [-180, +180) */ diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 4d6688694..a346e68cf 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -948,7 +948,7 @@ void cPlayer::Respawn(void) m_LifetimeTotalXp = 0; // ToDo: send score to client? How? - m_ClientHandle->SendRespawn(*GetWorld()); + m_ClientHandle->SendRespawn(GetWorld()->GetDimension()); // Extinguish the fire: StopBurning(); @@ -1570,7 +1570,7 @@ void cPlayer::TossItems(const cItems & a_Items) -bool cPlayer::MoveToWorld(const AString & a_WorldName, cWorld * a_World) +bool cPlayer::MoveToWorld(const AString & a_WorldName, cWorld * a_World, bool a_ShouldSendRespawn) { cWorld * World; if (a_World == NULL) @@ -1589,31 +1589,22 @@ bool cPlayer::MoveToWorld(const AString & a_WorldName, cWorld * a_World) if (GetWorld() == World) { + // Don't move to same world return false; } // Send the respawn packet: - if (m_ClientHandle != NULL) + if (a_ShouldSendRespawn && (m_ClientHandle != NULL)) { - m_ClientHandle->SendRespawn(*World); + m_ClientHandle->SendRespawn(World->GetDimension()); } - // Remove all links to the old world + // Remove player from old world m_World->RemovePlayer(this); - // 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 - // Queue adding player to the new world, including all the necessary adjustments to the object World->AddPlayer(this); - if (GetWorld()->GetDimension() != World->GetDimension()) - { - GetClientHandle()->SendPlayerMoveLook(); - GetClientHandle()->SendHealth(); - GetClientHandle()->SendWholeInventory(*GetWindow()); - } - return true; } diff --git a/src/Entities/Player.h b/src/Entities/Player.h index 99a0e601c..8f319f1ae 100644 --- a/src/Entities/Player.h +++ b/src/Entities/Player.h @@ -323,14 +323,14 @@ public: virtual void Killed(cEntity * a_Victim) override; - void Respawn(void); // tolua_export + void Respawn(void); // tolua_export - void SetVisible( bool a_bVisible ); // tolua_export - bool IsVisible(void) const { return m_bVisible; } // tolua_export + void SetVisible(bool a_bVisible); // tolua_export + bool IsVisible(void) const { return m_bVisible; } // tolua_export /** Moves the player to the specified world. Returns true if successful, false on failure (world not found). */ - virtual bool MoveToWorld(const AString & a_WorldName, cWorld * a_World = NULL) override; // tolua_export + virtual bool MoveToWorld(const AString & a_WorldName, cWorld * a_World = NULL, bool a_ShouldSendRespawn = true) override; // tolua_export /** Saves all player data, such as inventory, to JSON */ bool SaveToDisk(void); @@ -339,7 +339,7 @@ public: Takes a (NULL) cWorld pointer which it will assign a value to based on either the loaded world or default world */ bool LoadFromDisk(cWorld *& a_World); - void LoadPermissionsFromDisk(void); // tolua_export + void LoadPermissionsFromDisk(void); // tolua_export const AString & GetLoadedWorldName() { return m_LoadedWorldName; } diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h index c6e569919..5b69d32a0 100644 --- a/src/Protocol/Protocol.h +++ b/src/Protocol/Protocol.h @@ -100,7 +100,7 @@ public: virtual void SendPlayerSpawn (const cPlayer & a_Player) = 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 SendRespawn (const cWorld & a_World) = 0; + virtual void SendRespawn (eDimension a_Dimension) = 0; virtual void SendExperience (void) = 0; virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) = 0; virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) = 0; diff --git a/src/Protocol/Protocol125.cpp b/src/Protocol/Protocol125.cpp index 5796ba271..f33965cb9 100644 --- a/src/Protocol/Protocol125.cpp +++ b/src/Protocol/Protocol125.cpp @@ -833,23 +833,23 @@ void cProtocol125::SendRemoveEntityEffect(const cEntity & a_Entity, int a_Effect -void cProtocol125::SendRespawn(const cWorld & a_World) +void cProtocol125::SendRespawn(eDimension a_Dimension) { cCSLock Lock(m_CSPacket); - if (m_LastSentDimension == a_World.GetDimension()) + if (m_LastSentDimension == a_Dimension) { // Must not send a respawn for the world with the same dimension, the client goes cuckoo if we do return; } cPlayer * Player = m_Client->GetPlayer(); WriteByte (PACKET_RESPAWN); - WriteInt ((int)(a_World.GetDimension())); + WriteInt ((int)(a_Dimension)); WriteByte (2); // TODO: Difficulty; 2 = Normal WriteChar ((char)Player->GetGameMode()); WriteShort (256); // Current world height WriteString("default"); Flush(); - m_LastSentDimension = a_World.GetDimension(); + m_LastSentDimension = a_Dimension; } diff --git a/src/Protocol/Protocol125.h b/src/Protocol/Protocol125.h index 85418f71f..dbf30a8e6 100644 --- a/src/Protocol/Protocol125.h +++ b/src/Protocol/Protocol125.h @@ -72,7 +72,7 @@ public: virtual void SendPlayerSpawn (const cPlayer & a_Player) 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 SendRespawn (const cWorld & a_World) override; + virtual void SendRespawn (eDimension a_Dimension) override; virtual void SendExperience (void) override; virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override; virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override; diff --git a/src/Protocol/Protocol16x.cpp b/src/Protocol/Protocol16x.cpp index 9e0f3f852..cc675c075 100644 --- a/src/Protocol/Protocol16x.cpp +++ b/src/Protocol/Protocol16x.cpp @@ -158,10 +158,10 @@ void cProtocol161::SendPlayerMaxSpeed(void) -void cProtocol161::SendRespawn(const cWorld & a_World) +void cProtocol161::SendRespawn(eDimension a_Dimension) { // Besides sending the respawn, we need to also send the player max speed, otherwise the client reverts to super-fast - super::SendRespawn(a_World); + super::SendRespawn(a_Dimension); SendPlayerMaxSpeed(); } diff --git a/src/Protocol/Protocol16x.h b/src/Protocol/Protocol16x.h index e91dc8a1c..2d50749ec 100644 --- a/src/Protocol/Protocol16x.h +++ b/src/Protocol/Protocol16x.h @@ -42,7 +42,7 @@ protected: virtual void SendGameMode (eGameMode a_GameMode) override; virtual void SendHealth (void) override; virtual void SendPlayerMaxSpeed(void) override; - virtual void SendRespawn (const cWorld & a_World) override; + virtual void SendRespawn (eDimension a_Dimension) override; virtual void SendWindowOpen (const cWindow & a_Window) override; virtual int ParseEntityAction (void) override; diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index f5b176e54..2460a4914 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -986,9 +986,9 @@ void cProtocol172::SendRemoveEntityEffect(const cEntity & a_Entity, int a_Effect -void cProtocol172::SendRespawn(const cWorld & a_World) +void cProtocol172::SendRespawn(eDimension a_Dimension) { - if (m_LastSentDimension == a_World.GetDimension()) + if (m_LastSentDimension == a_Dimension) { // Must not send a respawn for the world with the same dimension, the client goes cuckoo if we do return; @@ -996,11 +996,11 @@ void cProtocol172::SendRespawn(const cWorld & a_World) cPacketizer Pkt(*this, 0x07); // Respawn packet cPlayer * Player = m_Client->GetPlayer(); - Pkt.WriteInt((int)a_World.GetDimension()); + Pkt.WriteInt((int)a_Dimension); Pkt.WriteByte(2); // TODO: Difficulty (set to Normal) Pkt.WriteByte((Byte)Player->GetEffectiveGameMode()); Pkt.WriteString("default"); - m_LastSentDimension = a_World.GetDimension(); + m_LastSentDimension = a_Dimension; } diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h index 8be1d9211..5e3bf0e2a 100644 --- a/src/Protocol/Protocol17x.h +++ b/src/Protocol/Protocol17x.h @@ -104,7 +104,7 @@ public: virtual void SendPlayerSpawn (const cPlayer & a_Player) 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 SendRespawn (const cWorld & a_World) override; + virtual void SendRespawn (eDimension a_Dimension) 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 SendExperience (void) override; virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override; diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp index 35a331f43..4b9d2e97a 100644 --- a/src/Protocol/ProtocolRecognizer.cpp +++ b/src/Protocol/ProtocolRecognizer.cpp @@ -555,10 +555,10 @@ void cProtocolRecognizer::SendRemoveEntityEffect(const cEntity & a_Entity, int a -void cProtocolRecognizer::SendRespawn(const cWorld & a_World) +void cProtocolRecognizer::SendRespawn(eDimension a_Dimension) { ASSERT(m_Protocol != NULL); - m_Protocol->SendRespawn(a_World); + m_Protocol->SendRespawn(a_Dimension); } diff --git a/src/Protocol/ProtocolRecognizer.h b/src/Protocol/ProtocolRecognizer.h index 5e178447c..eb83fb0c0 100644 --- a/src/Protocol/ProtocolRecognizer.h +++ b/src/Protocol/ProtocolRecognizer.h @@ -107,7 +107,7 @@ public: virtual void SendPlayerSpawn (const cPlayer & a_Player) 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 SendRespawn (const cWorld & a_World) override; + virtual void SendRespawn (eDimension a_Dimension) override; virtual void SendExperience (void) override; virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override; virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override; diff --git a/src/World.cpp b/src/World.cpp index 6904000ea..c86827080 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -2416,7 +2416,6 @@ void cWorld::AddPlayer(cPlayer * a_Player) void cWorld::RemovePlayer(cPlayer * a_Player) { - m_ChunkMap->RemoveEntity(a_Player); { cCSLock Lock(m_CSPlayersToAdd); @@ -2424,7 +2423,7 @@ void cWorld::RemovePlayer(cPlayer * a_Player) } { cCSLock Lock(m_CSPlayers); - LOGD("Removing player \"%s\" from world \"%s\".", a_Player->GetName().c_str(), m_WorldName.c_str()); + LOGD("Removing player %s from world \"%s\".", a_Player->GetName().c_str(), m_WorldName.c_str()); m_Players.remove(a_Player); } @@ -3213,7 +3212,8 @@ void cWorld::AddQueuedPlayers(void) for (cPlayerList::iterator itr = PlayersToAdd.begin(), end = PlayersToAdd.end(); itr != end; ++itr) { ASSERT(std::find(m_Players.begin(), m_Players.end(), *itr) == m_Players.end()); // Is it already in the list? HOW? - + + LOGD("Adding player %s to world \"%s\".", (*itr)->GetName().c_str(), m_WorldName.c_str()); m_Players.push_back(*itr); (*itr)->SetWorld(this); @@ -3242,6 +3242,9 @@ void cWorld::AddQueuedPlayers(void) if (Client != NULL) { Client->StreamChunks(); + Client->SendPlayerMoveLook(); + Client->SendHealth(); + Client->SendWholeInventory(*(*itr)->GetWindow()); } } // for itr - PlayersToAdd[] } -- cgit v1.2.3 From e10940d57cf8500eb306e986d7cc2d79bca00467 Mon Sep 17 00:00:00 2001 From: worktycho Date: Thu, 12 Jun 2014 17:24:14 +0100 Subject: Fixed compile --- src/Entities/Entity.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index a7b6cca27..1c8818fe5 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -1051,7 +1051,7 @@ void cEntity::DetectPortal() class cPortalChunkLoader : public cChunkStay { public: - cPortalChunkLoader(cEntity * a_Entity, cWorld & a_World, Vector3i & a_PortalPos) : + cPortalChunkLoader(cEntity * a_Entity, cWorld & a_World, const Vector3i & a_PortalPos) : m_Entity(a_Entity), m_PortalPos(a_PortalPos), m_World(a_World) -- cgit v1.2.3 From 93d4a8aa92af58bb073f18c87167358d18632899 Mon Sep 17 00:00:00 2001 From: Tycho Date: Thu, 12 Jun 2014 18:51:33 +0100 Subject: Removed unnessicary indirection from Entity iterator list --- src/Chunk.cpp | 10 +++++----- src/Chunk.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Chunk.cpp b/src/Chunk.cpp index c9e4f5411..7ca0a4afd 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -86,7 +86,7 @@ cChunk::cChunk( m_NeighborZP(a_NeighborZP), m_WaterSimulatorData(a_World->GetWaterSimulator()->CreateChunkData()), m_LavaSimulatorData (a_World->GetLavaSimulator ()->CreateChunkData()), - m_EntityTickIteratorData(std::make_pair(false, &m_Entities.end())) + m_EntityTickIteratorData(std::make_pair(false, m_Entities.end())) { if (a_NeighborXM != NULL) { @@ -584,12 +584,12 @@ void cChunk::Tick(float a_Dt) // Don't tick things queued to be removed if (!((*itr)->IsMob())) { - m_EntityTickIteratorData.second = &itr; + m_EntityTickIteratorData.second = itr; (*itr)->Tick(a_Dt, *this); - if (itr != *m_EntityTickIteratorData.second) + if (itr != m_EntityTickIteratorData.second) { - itr = *m_EntityTickIteratorData.second; + itr = m_EntityTickIteratorData.second; } else { @@ -1876,7 +1876,7 @@ void cChunk::RemoveEntity(cEntity * a_Entity) { if (m_EntityTickIteratorData.first) { - *m_EntityTickIteratorData.second = m_Entities.erase(*m_EntityTickIteratorData.second); + m_EntityTickIteratorData.second = m_Entities.erase(m_EntityTickIteratorData.second); } else { diff --git a/src/Chunk.h b/src/Chunk.h index 3046b2efe..1619df333 100644 --- a/src/Chunk.h +++ b/src/Chunk.h @@ -425,7 +425,7 @@ private: // A critical section is not needed, because all chunk access is protected by its parent ChunkMap's csLayers cClientHandleList m_LoadedByClient; cEntityList m_Entities; - std::pair m_EntityTickIteratorData; + std::pair m_EntityTickIteratorData; cBlockEntityList m_BlockEntities; /** Number of times the chunk has been requested to stay (by various cChunkStay objects); if zero, the chunk can be unloaded */ -- cgit v1.2.3 From c82f4f6309f760186c43b4f32596c3e78a5725b7 Mon Sep 17 00:00:00 2001 From: Tycho Date: Thu, 12 Jun 2014 18:56:48 +0100 Subject: Fixed order of initalisation --- src/Chunk.cpp | 4 ++-- src/World.cpp | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Chunk.cpp b/src/Chunk.cpp index 7ca0a4afd..8255fdcaf 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -71,6 +71,7 @@ cChunk::cChunk( m_IsDirty(false), m_IsSaving(false), m_HasLoadFailed(false), + m_EntityTickIteratorData(std::make_pair(false, m_Entities.end())), m_StayCount(0), m_PosX(a_ChunkX), m_PosY(a_ChunkY), @@ -85,8 +86,7 @@ cChunk::cChunk( m_NeighborZM(a_NeighborZM), m_NeighborZP(a_NeighborZP), m_WaterSimulatorData(a_World->GetWaterSimulator()->CreateChunkData()), - m_LavaSimulatorData (a_World->GetLavaSimulator ()->CreateChunkData()), - m_EntityTickIteratorData(std::make_pair(false, m_Entities.end())) + m_LavaSimulatorData (a_World->GetLavaSimulator ()->CreateChunkData()) { if (a_NeighborXM != NULL) { diff --git a/src/World.cpp b/src/World.cpp index c86827080..3ed2f5f13 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -234,6 +234,7 @@ void cWorld::cTickThread::Execute(void) cWorld::cWorld(const AString & a_WorldName, eDimension a_Dimension, const AString & a_OverworldName) : m_WorldName(a_WorldName), + m_OverworldName(a_OverworldName), m_IniFileName(m_WorldName + "/world.ini"), m_StorageSchema("Default"), #ifdef __arm__ @@ -241,6 +242,7 @@ cWorld::cWorld(const AString & a_WorldName, eDimension a_Dimension, const AStrin #else m_StorageCompressionFactor(6), #endif + m_Dimension(a_Dimension), m_IsSpawnExplicitlySet(false), m_WorldAgeSecs(0), m_TimeOfDaySecs(0), @@ -253,9 +255,8 @@ cWorld::cWorld(const AString & a_WorldName, eDimension a_Dimension, const AStrin m_Scoreboard(this), m_MapManager(this), m_GeneratorCallbacks(*this), - m_TickThread(*this), - m_Dimension(a_Dimension), - m_OverworldName(a_OverworldName) + m_TickThread(*this) + { LOGD("cWorld::cWorld(\"%s\")", a_WorldName.c_str()); -- cgit v1.2.3 From a70b8298b6ada8abead9ef2b292531407225c2d1 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sat, 14 Jun 2014 10:14:04 +0100 Subject: Cauldrons check the heightmap --- src/Blocks/BlockCauldron.h | 6 +++++- src/Blocks/WorldInterface.h | 8 ++++---- src/World.h | 6 +++--- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/Blocks/BlockCauldron.h b/src/Blocks/BlockCauldron.h index 5ec776df6..e0f86f4cb 100644 --- a/src/Blocks/BlockCauldron.h +++ b/src/Blocks/BlockCauldron.h @@ -61,8 +61,12 @@ public: virtual void OnUpdate(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_PluginInterface, cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ) override { - if (IsBiomeNoDownfall(a_Chunk.GetBiomeAt(a_RelX, a_RelZ)) || !a_WorldInterface.IsWeatherWet()) + int BlockX = a_RelX + a_Chunk.GetPosX() * cChunkDef::Width; + int BlockZ = a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width; + if (!a_WorldInterface.IsWeatherWetAt(BlockX, BlockZ) || (a_RelY != a_WorldInterface.GetHeight(BlockX, BlockZ))) { + // It's not raining at our current location or we do not have a direct view of the sky + // We cannot eat the rain :( return; } diff --git a/src/Blocks/WorldInterface.h b/src/Blocks/WorldInterface.h index 7df82197e..e5638c16e 100644 --- a/src/Blocks/WorldInterface.h +++ b/src/Blocks/WorldInterface.h @@ -37,9 +37,9 @@ public: virtual void SetTimeOfDay(Int64 a_TimeOfDay) = 0; - /** Returns true if the current weather has any precipitation - rain or storm - Does not check if biome has no downfall, use cChunk::GetBiomeAt(RelX, RelZ) for that - */ - virtual bool IsWeatherWet(void) const = 0; + /** Returns true if it is raining, stormy or snowing at the specified location. This takes into account biomes. */ + virtual bool IsWeatherWetAt(int a_BlockX, int a_BlockZ) = 0; + /** Returns the world height at the specified coords; waits for the chunk to get loaded / generated */ + virtual int GetHeight(int a_BlockX, int a_BlockZ) = 0; }; diff --git a/src/World.h b/src/World.h index ab36e0a9b..0592c78fc 100644 --- a/src/World.h +++ b/src/World.h @@ -180,7 +180,7 @@ public: virtual eDimension GetDimension(void) const { return m_Dimension; } /** Returns the world height at the specified coords; waits for the chunk to get loaded / generated */ - int GetHeight(int a_BlockX, int a_BlockZ); + virtual int GetHeight(int a_BlockX, int a_BlockZ); // tolua_end @@ -749,10 +749,10 @@ public: } /** Returns true if the current weather has any precipitation - rain, storm or snow */ - virtual bool IsWeatherWet(void) const { return !IsWeatherSunny(); } + bool IsWeatherWet(void) const { return !IsWeatherSunny(); } /** Returns true if it is raining, stormy or snowing at the specified location. This takes into account biomes. */ - bool IsWeatherWetAt(int a_BlockX, int a_BlockZ) + virtual bool IsWeatherWetAt(int a_BlockX, int a_BlockZ) { return (IsWeatherWet() && !IsBiomeNoDownfall(GetBiomeAt(a_BlockX, a_BlockZ))); } -- cgit v1.2.3 From 8a80843ddf062b4a2df622d661628e4c77b9c399 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sat, 14 Jun 2014 10:18:16 +0100 Subject: Reverted portal creation code It wasn't really working and needs more development --- src/Entities/Entity.cpp | 100 ------------------------------------------------ src/Entities/Entity.h | 3 -- 2 files changed, 103 deletions(-) diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index 1c8818fe5..d42c49abe 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -12,7 +12,6 @@ #include "../Bindings/PluginManager.h" #include "../Tracer.h" #include "Player.h" -#include "BlockArea.h" @@ -1048,30 +1047,6 @@ void cEntity::DetectPortal() return; } - class cPortalChunkLoader : public cChunkStay - { - public: - cPortalChunkLoader(cEntity * a_Entity, cWorld & a_World, const Vector3i & a_PortalPos) : - m_Entity(a_Entity), - m_PortalPos(a_PortalPos), - m_World(a_World) - {} - - private: - virtual bool OnAllChunksAvailable(void) override - { - cEntity::CreateExitPortal(m_PortalPos.x, m_PortalPos.y, m_PortalPos.z, m_Entity->GetWidth(), m_Entity->GetHeight(), m_World, m_Entity->GetUniqueID()); - return true; - } - - virtual void OnChunkAvailable(int a_ChunkX, int a_ChunkZ) override {}; - virtual void OnDisabled(void) override {}; - - cEntity * m_Entity; - Vector3i m_PortalPos; - cWorld & m_World; - }; - int X = POSX_TOINT, Y = POSY_TOINT, Z = POSZ_TOINT; if ((Y > 0) && (Y < cChunkDef::Height)) { @@ -1115,24 +1090,7 @@ void cEntity::DetectPortal() ((cPlayer *)this)->GetClientHandle()->SendRespawn(dimNether); } MoveToWorld(GetWorld()->GetNetherWorldName(), cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetNetherWorldName(), dimNether, GetWorld()->GetName()), false); - - cChunkStay * Stay = new cPortalChunkLoader(this, *cRoot::Get()->GetWorld(GetWorld()->GetNetherWorldName()), Vector3i(X, Y, Z)); - - int MinChunkX, MaxChunkX; - int MinChunkZ, MaxChunkZ; - cChunkDef::BlockToChunk(X - 128, Z - 128, MinChunkX, MinChunkZ); - cChunkDef::BlockToChunk(X + 128, Z + 128, MaxChunkX, MaxChunkZ); - for (int ChunkX = MinChunkX; ChunkX <= MaxChunkX; ++ChunkX) - { - for (int ChunkZ = MinChunkZ; ChunkZ <= MaxChunkZ; ++ChunkZ) - { - LOG("Queue %i %i", ChunkX, ChunkZ); - Stay->Add(ChunkX, ChunkZ); - } - } - - Stay->Enable(*GetWorld()->GetChunkMap()); return; } default: break; @@ -1199,64 +1157,6 @@ void cEntity::DetectPortal() -void cEntity::CreateExitPortal(int a_BlockX, int a_BlockY, int a_BlockZ, double a_EntityWidth, double a_EntityHeight, cWorld & a_World, int a_UniqueIDToTeleport) -{ - cBlockArea Area; - Area.Read(&a_World, a_BlockX - 128, a_BlockX + 128, 0, 128, a_BlockZ - 128, a_BlockZ + 128); - for (int x = a_BlockX - 128; x <= a_BlockX + 128; ++x) for (int y = 0; y <= 128; ++y) for (int z = a_BlockZ - 128; z <= a_BlockZ + 128; ++z) - { - if ( - (Area.GetBlockType(x, y, z) == E_BLOCK_NETHER_PORTAL) && - ( - (Area.GetBlockType(x, (int)floor(y + a_EntityHeight), z) == E_BLOCK_NETHER_PORTAL) || - (Area.GetBlockType(x, (int)floor(y - a_EntityHeight), z) == E_BLOCK_NETHER_PORTAL) - ) - ) - { - class cTeleportEntityToPortalCallback : public cEntityCallback - { - public: - cTeleportEntityToPortalCallback(int a_X, int a_Y, int a_Z) : - m_X(a_X), - m_Y(a_Y), - m_Z(a_Z) - {} - - virtual bool Item(cEntity * a_Entity) override - { - a_Entity->TeleportToCoords(m_X, m_Y, m_Z); - return true; - } - - private: - int m_X, m_Y, m_Z; - }; - - cTeleportEntityToPortalCallback TETPC(x, y, z); - a_World.DoWithEntityByID(a_UniqueIDToTeleport, TETPC); - return; - } - } - - int MinX = std::max(a_BlockX - (int)ceil(a_EntityWidth), a_BlockX - 2), MaxX = std::max(a_BlockX + (int)ceil(a_EntityWidth), a_BlockX + 1); - int MinY = std::max(a_BlockY - (int)ceil(a_EntityHeight), a_BlockY - 2), MaxY = std::max(a_BlockY + (int)ceil(a_EntityHeight), a_BlockY + 1); - - for (int y = MinY; y < MaxY + 1; y += MaxY - MinY) for (int x = MinX; x < MaxX + 1; ++x) - { - Area.SetBlockType(x, y, a_BlockZ, E_BLOCK_OBSIDIAN); - } - for (int y = MinY; y < MaxY + 1; ++y) for (int x = MinX; x < MaxX + 1; x += MaxX - MinX) - { - Area.SetBlockType(x, y, a_BlockZ, E_BLOCK_OBSIDIAN); - } - - Area.Write(&a_World, MinX, MinY, a_BlockZ); -} - - - - - bool cEntity::MoveToWorld(const AString & a_WorldName, cWorld * a_World, bool a_ShouldSendRespawn) { UNUSED(a_ShouldSendRespawn); diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h index 4d922aa11..9f3b06c29 100644 --- a/src/Entities/Entity.h +++ b/src/Entities/Entity.h @@ -336,9 +336,6 @@ public: /// Called when the entity finishes burning virtual void OnFinishedBurning(void); - - /** Creates exit portal at given coordinates */ - static void CreateExitPortal(int a_BlockX, int a_BlockY, int a_BlockZ, double a_EntityWidth, double a_EntityHeight, cWorld & a_World, int a_UniqueIDToTeleport); // tolua_begin -- cgit v1.2.3 From b2fbcaf1bf43ca1f0e6df48de8584149cbe50222 Mon Sep 17 00:00:00 2001 From: archshift Date: Sun, 15 Jun 2014 20:27:27 -0700 Subject: Implemented PR suggestions Furnace.txt: newline BlockID: removed extraneous dimension mapping cEntity: fixed typo cPlayer: WorldPtr typedef --- MCServer/furnace.txt | 3 ++- src/BlockID.cpp | 4 ---- src/Entities/Entity.h | 2 +- src/Entities/Player.cpp | 2 +- src/Entities/Player.h | 3 ++- 5 files changed, 6 insertions(+), 8 deletions(-) diff --git a/MCServer/furnace.txt b/MCServer/furnace.txt index 229a939ff..d6177184b 100644 --- a/MCServer/furnace.txt +++ b/MCServer/furnace.txt @@ -87,4 +87,5 @@ ! 271:1 = 200 # 1 Wooden Axe -> 10 sec ! 269:1 = 200 # 1 Wooden Shovel -> 10 sec ! 290:1 = 200 # 1 Wooden Hoe -> 10 sec -! 268:1 = 200 # 1 Wooden Sword -> 10 sec \ No newline at end of file +! 268:1 = 200 # 1 Wooden Sword -> 10 sec + diff --git a/src/BlockID.cpp b/src/BlockID.cpp index 641a6a225..70cb801b6 100644 --- a/src/BlockID.cpp +++ b/src/BlockID.cpp @@ -355,12 +355,8 @@ AString DimensionToString(eDimension a_Dimension) } DimensionMap[] = { { dimOverworld, "Overworld" }, - { dimOverworld, "Normal" }, - { dimOverworld, "World" }, { dimNether, "Nether" }, - { dimNether, "Hell" }, // Alternate name for Nether { dimEnd, "End" }, - { dimEnd, "Sky" }, // Old name for End }; for (size_t i = 0; i < ARRAYCOUNT(DimensionMap); i++) diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h index 9f3b06c29..8975803a2 100644 --- a/src/Entities/Entity.h +++ b/src/Entities/Entity.h @@ -509,7 +509,7 @@ protected: int m_AirTickTimer; /** Portal delay timer and cooldown boolean - First value is to delay sending the repsawn packet (which triggers the Entering the {Dimension} screen). + First value is to delay sending the respawn packet (which triggers the Entering the {Dimension} screen). Second value is to prevent a teleportation loop by ensuring we do not reenter a portal that we came out of. */ std::pair m_PortalCooldownData; diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index a346e68cf..c26c18690 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -1651,7 +1651,7 @@ void cPlayer::LoadPermissionsFromDisk() -bool cPlayer::LoadFromDisk(cWorld *& a_World) +bool cPlayer::LoadFromDisk(cWorldPtr & a_World) { a_World = cRoot::Get()->GetWorld(GetLoadedWorldName()); if (a_World == NULL) diff --git a/src/Entities/Player.h b/src/Entities/Player.h index 8f319f1ae..b1fef1b68 100644 --- a/src/Entities/Player.h +++ b/src/Entities/Player.h @@ -335,10 +335,11 @@ public: /** Saves all player data, such as inventory, to JSON */ bool SaveToDisk(void); + typedef cWorld * cWorldPtr; /** Loads player data from JSON to the object Takes a (NULL) cWorld pointer which it will assign a value to based on either the loaded world or default world */ - bool LoadFromDisk(cWorld *& a_World); + bool LoadFromDisk(cWorldPtr & a_World); void LoadPermissionsFromDisk(void); // tolua_export const AString & GetLoadedWorldName() { return m_LoadedWorldName; } -- cgit v1.2.3 From 1296c5dce71f59f1d7b2bfd1791a22daa26f2cb3 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sat, 21 Jun 2014 20:42:10 +0100 Subject: More suggestions --- src/Entities/Entity.cpp | 2 +- src/Entities/Player.cpp | 2 +- src/Entities/Player.h | 6 ++++-- src/Mobs/Monster.cpp | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index d42c49abe..9110cd83b 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -869,7 +869,7 @@ void cEntity::TickBurning(cChunk & a_Chunk) // Remember the current burning state: bool HasBeenBurning = (m_TicksLeftBurning > 0); - if (IsBiomeNoDownfall(a_Chunk.GetBiomeAt(POSX_TOINT - a_Chunk.GetPosX() * cChunkDef::Width, POSZ_TOINT - a_Chunk.GetPosZ() * cChunkDef::Width)) || GetWorld()->IsWeatherWet()) + if (GetWorld()->IsWeatherWetAt(POSX_TOINT, POSZ_TOINT)) { if (POSY_TOINT > m_World->GetHeight(POSX_TOINT, POSZ_TOINT)) { diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index c26c18690..e975abdf5 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -1599,7 +1599,7 @@ bool cPlayer::MoveToWorld(const AString & a_WorldName, cWorld * a_World, bool a_ m_ClientHandle->SendRespawn(World->GetDimension()); } - // Remove player from old world + // Remove player from the old world m_World->RemovePlayer(this); // Queue adding player to the new world, including all the necessary adjustments to the object diff --git a/src/Entities/Player.h b/src/Entities/Player.h index b1fef1b68..c72d1eb8d 100644 --- a/src/Entities/Player.h +++ b/src/Entities/Player.h @@ -350,7 +350,7 @@ public: void SendExperience(void); - /** In UI windows, the item that the player is dragging */ + /** In UI windows, get the item that the player is dragging */ cItem & GetDraggingItem(void) {return m_DraggingItem; } // In UI windows, when inventory-painting: @@ -398,7 +398,9 @@ public: /** If true the player can fly even when he's not in creative. */ void SetCanFly(bool a_CanFly); - /** Gets the last position that the player slept in */ + /** Gets the last position that the player slept in + This is initialised to the world spawn point if the player has not slept in a bed as of yet + */ Vector3i GetLastBedPos(void) const { return m_LastBedPos; } /** Sets the player's bed (home) position */ diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp index 0f030da2d..89329dace 100644 --- a/src/Mobs/Monster.cpp +++ b/src/Mobs/Monster.cpp @@ -1034,7 +1034,7 @@ void cMonster::HandleDaylightBurning(cChunk & a_Chunk) (a_Chunk.GetBlock(RelX, RelY, RelZ) != E_BLOCK_SOULSAND) && // Not on soulsand (GetWorld()->GetTimeOfDay() < (12000 + 1000)) && // It is nighttime !IsOnFire() && // Not already burning - (IsBiomeNoDownfall(a_Chunk.GetBiomeAt(RelX, RelZ)) || !GetWorld()->IsWeatherWet()) // Not raining + GetWorld()->IsWeatherWetAt(POSX_TOINT, POSZ_TOINT) // Not raining ) { // Burn for 100 ticks, then decide again -- cgit v1.2.3 From 6e681269d9dfb33b5b73f4f01a61def247b3aee7 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sat, 21 Jun 2014 22:07:38 +0100 Subject: Fixed invalid iterators --- src/Chunk.cpp | 33 ++++++++++----------------------- src/Chunk.h | 1 - src/Entities/Entity.cpp | 3 ++- src/Entities/Entity.h | 10 +++++++++- src/Entities/Player.cpp | 1 + src/World.cpp | 14 ++++---------- src/World.h | 3 --- 7 files changed, 26 insertions(+), 39 deletions(-) diff --git a/src/Chunk.cpp b/src/Chunk.cpp index 8255fdcaf..727eb451d 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -71,7 +71,6 @@ cChunk::cChunk( m_IsDirty(false), m_IsSaving(false), m_HasLoadFailed(false), - m_EntityTickIteratorData(std::make_pair(false, m_Entities.end())), m_StayCount(0), m_PosX(a_ChunkX), m_PosY(a_ChunkY), @@ -577,44 +576,39 @@ void cChunk::Tick(float a_Dt) } // Tick all entities in this chunk (except mobs): - m_EntityTickIteratorData.first = true; - for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end();) + for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr) { // Mobs are ticked inside cWorld::TickMobs() (as we don't have to tick them if they are far away from players) // Don't tick things queued to be removed if (!((*itr)->IsMob())) { - m_EntityTickIteratorData.second = itr; (*itr)->Tick(a_Dt, *this); - - if (itr != m_EntityTickIteratorData.second) - { - itr = m_EntityTickIteratorData.second; - } - else - { - ++itr; - } continue; } - ++itr; } // for itr - m_Entitites[] - m_EntityTickIteratorData.first = false; for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end();) { if ((*itr)->IsDestroyed()) // Remove all entities that were scheduled for removal: { LOGD("Destroying entity #%i (%s)", (*itr)->GetUniqueID(), (*itr)->GetClass()); + MarkDirty(); cEntity * ToDelete = *itr; itr = m_Entities.erase(itr); delete ToDelete; } + else if ((*itr)->IsTravellingThroughPortal()) + { + MarkDirty(); + (*itr)->SetIsTravellingThroughPortal(false); + itr = m_Entities.erase(itr); + } else if ( // If any entity moved out of the chunk, move it to the neighbor: ((*itr)->GetChunkX() != m_PosX) || ((*itr)->GetChunkZ() != m_PosZ) ) { + MarkDirty(); MoveEntityToNewChunk(*itr); itr = m_Entities.erase(itr); } @@ -1874,14 +1868,7 @@ void cChunk::AddEntity(cEntity * a_Entity) void cChunk::RemoveEntity(cEntity * a_Entity) { - if (m_EntityTickIteratorData.first) - { - m_EntityTickIteratorData.second = m_Entities.erase(m_EntityTickIteratorData.second); - } - else - { - m_Entities.remove(a_Entity); - } + m_Entities.remove(a_Entity); // Mark as dirty if it was a server-generated entity: if (!a_Entity->IsPlayer()) diff --git a/src/Chunk.h b/src/Chunk.h index 1619df333..dfdabea04 100644 --- a/src/Chunk.h +++ b/src/Chunk.h @@ -425,7 +425,6 @@ private: // A critical section is not needed, because all chunk access is protected by its parent ChunkMap's csLayers cClientHandleList m_LoadedByClient; cEntityList m_Entities; - std::pair m_EntityTickIteratorData; cBlockEntityList m_BlockEntities; /** Number of times the chunk has been requested to stay (by various cChunkStay objects); if zero, the chunk can be unloaded */ diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index 9110cd83b..9a8c6586d 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -57,6 +57,7 @@ cEntity::cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, d , m_Width(a_Width) , m_Height(a_Height) , m_InvulnerableTicks(0) + , m_IsTravellingThroughPortal(false) { cCSLock Lock(m_CSCount); m_EntityCount++; @@ -1183,7 +1184,7 @@ bool cEntity::MoveToWorld(const AString & a_WorldName, cWorld * a_World, bool a_ } // Remove all links to the old world - GetWorld()->RemoveEntity(this); + SetIsTravellingThroughPortal(true); // cChunk handles entity removal GetWorld()->BroadcastDestroyEntity(*this); // Queue add to new world diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h index 8975803a2..0293968ab 100644 --- a/src/Entities/Entity.h +++ b/src/Entities/Entity.h @@ -374,6 +374,12 @@ public: virtual bool MoveToWorld(const AString & a_WorldName, cWorld * a_World = NULL, bool a_ShouldSendRespawn = true); // tolua_end + + /** Returns if the entity is travelling through a portal. Set to true by MoveToWorld and to false when the entity is removed by the old chunk */ + bool IsTravellingThroughPortal(void) const { return m_IsTravellingThroughPortal; } + + /** Sets if the entity has begun travelling through a portal or not */ + void SetIsTravellingThroughPortal(bool a_Flag) { m_IsTravellingThroughPortal = a_Flag; } /// Updates clients of changes in the entity. virtual void BroadcastMovementUpdate(const cClientHandle * a_Exclude = NULL); @@ -470,6 +476,9 @@ protected: /** True when entity is initialised (Initialize()) and false when destroyed pending deletion (Destroy()) */ bool m_IsInitialized; + /** True when entity is being moved across worlds, false anytime else */ + bool m_IsTravellingThroughPortal; + eEntityType m_EntityType; cWorld * m_World; @@ -492,7 +501,6 @@ protected: /// Time, in ticks, since the last damage dealt by the void. Reset to zero when moving out of the void. int m_TicksSinceLastVoidDamage; - virtual void Destroyed(void) {} // Called after the entity has been destroyed /** Called in each tick to handle air-related processing i.e. drowning */ diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index e975abdf5..b72f14f57 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -1600,6 +1600,7 @@ bool cPlayer::MoveToWorld(const AString & a_WorldName, cWorld * a_World, bool a_ } // Remove player from the old world + SetIsTravellingThroughPortal(true); // cChunk handles entity removal m_World->RemovePlayer(this); // Queue adding player to the new world, including all the necessary adjustments to the object diff --git a/src/World.cpp b/src/World.cpp index 3ed2f5f13..c9199b6ba 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -2417,7 +2417,10 @@ void cWorld::AddPlayer(cPlayer * a_Player) void cWorld::RemovePlayer(cPlayer * a_Player) { - m_ChunkMap->RemoveEntity(a_Player); + if (!a_Player->IsTravellingThroughPortal()) + { + m_ChunkMap->RemoveEntity(a_Player); + } { cCSLock Lock(m_CSPlayersToAdd); m_PlayersToAdd.remove(a_Player); @@ -2919,15 +2922,6 @@ bool cWorld::HasEntity(int a_UniqueID) -void cWorld::RemoveEntity(cEntity * a_Entity) -{ - m_ChunkMap->RemoveEntity(a_Entity); -} - - - - - /* unsigned int cWorld::GetNumPlayers(void) { diff --git a/src/World.h b/src/World.h index 0592c78fc..1d9026a5d 100644 --- a/src/World.h +++ b/src/World.h @@ -313,9 +313,6 @@ public: bool HasEntity(int a_UniqueID); - /** Removes the entity, the entity ptr ownership is assumed taken by the caller */ - void RemoveEntity(cEntity * a_Entity); - /** Calls the callback for each entity in the entire world; returns true if all entities processed, false if the callback aborted by returning true */ bool ForEachEntity(cEntityCallback & a_Callback); // Exported in ManualBindings.cpp -- cgit v1.2.3 From e709652257da1ba06a6642b4978365b14bc11a22 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 22 Jun 2014 00:21:39 +0100 Subject: Conforms to standards --- src/Entities/Entity.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index fadd12135..d4edc9144 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -37,6 +37,7 @@ cEntity::cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, d , m_Gravity(-9.81f) , m_LastPos(a_X, a_Y, a_Z) , m_IsInitialized(false) + , m_IsTravellingThroughPortal(false) , m_EntityType(a_EntityType) , m_World(NULL) , m_IsFireproof(false) @@ -57,7 +58,6 @@ cEntity::cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, d , m_Width(a_Width) , m_Height(a_Height) , m_InvulnerableTicks(0) - , m_IsTravellingThroughPortal(false) { cCSLock Lock(m_CSCount); m_EntityCount++; -- cgit v1.2.3 From 719551c31f5ed0d3cbad9797dd81a6bf1ae4e5a2 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Fri, 18 Jul 2014 20:12:27 +0100 Subject: Fix failed merge and other issues --- src/ClientHandle.cpp | 4 ++-- src/ClientHandle.h | 2 +- src/Entities/Entity.cpp | 6 +++--- src/Entities/Player.cpp | 40 ++++++++------------------------------- src/Entities/Player.h | 11 +---------- src/Protocol/Protocol.h | 2 +- src/Protocol/Protocol125.cpp | 2 +- src/Protocol/Protocol125.h | 2 +- src/Protocol/Protocol16x.h | 2 +- src/Protocol/Protocol17x.cpp | 2 +- src/Protocol/Protocol17x.h | 2 +- src/Protocol/ProtocolRecognizer.h | 2 +- src/World.cpp | 16 ++++++---------- src/World.h | 12 ------------ 14 files changed, 28 insertions(+), 77 deletions(-) diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index 1a18649c9..f90da94dd 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -2375,9 +2375,9 @@ void cClientHandle::SendRemoveEntityEffect(const cEntity & a_Entity, int a_Effec -void cClientHandle::SendRespawn(eDimension a_Dimension) +void cClientHandle::SendRespawn(eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks) { - m_Protocol->SendRespawn(a_Dimension); + m_Protocol->SendRespawn(a_Dimension, a_ShouldIgnoreDimensionChecks); } diff --git a/src/ClientHandle.h b/src/ClientHandle.h index cb0471421..e3c2b590f 100644 --- a/src/ClientHandle.h +++ b/src/ClientHandle.h @@ -161,7 +161,7 @@ public: void SendPlayerSpawn (const cPlayer & a_Player); void SendPluginMessage (const AString & a_Channel, const AString & a_Message); // Exported in ManualBindings.cpp void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID); - void SendRespawn (eDimension a_Dimension); + void SendRespawn (eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks = false); void SendExperience (void); void SendExperienceOrb (const cExpOrb & a_ExpOrb); void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode); diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index e5e4cf4cb..bd1839580 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -1028,7 +1028,7 @@ void cEntity::DetectCacti(void) void cEntity::DetectPortal() { - if (!GetWorld()->AreNetherPortalsEnabled() && !GetWorld()->AreEndPortalsEnabled()) + if (!GetWorld()->GetNetherWorldName().empty() && !GetWorld()->GetEndWorldName().empty()) { return; } @@ -1040,7 +1040,7 @@ void cEntity::DetectPortal() { case E_BLOCK_NETHER_PORTAL: { - if (!GetWorld()->AreNetherPortalsEnabled() || m_PortalCooldownData.second) + if (GetWorld()->GetNetherWorldName().empty() || m_PortalCooldownData.second) { return; } @@ -1085,7 +1085,7 @@ void cEntity::DetectPortal() } case E_BLOCK_END_PORTAL: { - if (!GetWorld()->AreEndPortalsEnabled() || m_PortalCooldownData.second) + if (GetWorld()->GetNetherWorldName().empty() || m_PortalCooldownData.second) { return; } diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 1acc8a962..2a91600e7 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -1695,12 +1695,7 @@ void cPlayer::LoadPermissionsFromDisk() -<<<<<<< HEAD bool cPlayer::LoadFromDisk(cWorldPtr & a_World) -======= - -bool cPlayer::LoadFromDisk(void) ->>>>>>> master { a_World = cRoot::Get()->GetWorld(GetLoadedWorldName()); if (a_World == NULL) @@ -1711,7 +1706,7 @@ bool cPlayer::LoadFromDisk(void) LoadPermissionsFromDisk(); // Load from the UUID file: - if (LoadFromFile(GetUUIDFileName(m_UUID))) + if (LoadFromFile(GetUUIDFileName(m_UUID), a_World)) { return true; } @@ -1720,7 +1715,7 @@ bool cPlayer::LoadFromDisk(void) AString OfflineUUID = cClientHandle::GenerateOfflineUUID(GetName()); if (cRoot::Get()->GetServer()->ShouldLoadOfflinePlayerData()) { - if (LoadFromFile(GetUUIDFileName(OfflineUUID))) + if (LoadFromFile(GetUUIDFileName(OfflineUUID), a_World)) { return true; } @@ -1730,7 +1725,7 @@ bool cPlayer::LoadFromDisk(void) if (cRoot::Get()->GetServer()->ShouldLoadNamedPlayerData()) { AString OldStyleFileName = Printf("players/%s.json", GetName().c_str()); - if (LoadFromFile(OldStyleFileName)) + if (LoadFromFile(OldStyleFileName, a_World)) { // Save in new format and remove the old file if (SaveToDisk()) @@ -1752,7 +1747,7 @@ bool cPlayer::LoadFromDisk(void) -bool cPlayer::LoadFromFile(const AString & a_FileName) +bool cPlayer::LoadFromFile(const AString & a_FileName, cWorld * a_World) { // Load the data from the file: cFile f; @@ -1860,28 +1855,6 @@ bool cPlayer::SaveToDisk() cEnderChestEntity::SaveToJson(JSON_EnderChestInventory, m_EnderChestContents); Json::Value root; -<<<<<<< HEAD - root["position"] = JSON_PlayerPosition; - root["rotation"] = JSON_PlayerRotation; - root["inventory"] = JSON_Inventory; - root["health"] = m_Health; - root["xpTotal"] = m_LifetimeTotalXp; - root["xpCurrent"] = m_CurrentXp; - root["air"] = m_AirLevel; - root["food"] = m_FoodLevel; - root["foodSaturation"] = m_FoodSaturationLevel; - root["foodTickTimer"] = m_FoodTickTimer; - root["foodExhaustion"] = m_FoodExhaustionLevel; - root["world"] = GetWorld()->GetName(); - root["isflying"] = IsFlying(); - root["SpawnX"] = GetLastBedPos().x; - root["SpawnY"] = GetLastBedPos().y; - root["SpawnZ"] = GetLastBedPos().z; - - if (m_GameMode == GetWorld()->GetGameMode()) - { - root["gamemode"] = (int) eGameMode_NotSet; -======= root["position"] = JSON_PlayerPosition; root["rotation"] = JSON_PlayerRotation; root["inventory"] = JSON_Inventory; @@ -1896,6 +1869,10 @@ bool cPlayer::SaveToDisk() root["foodExhaustion"] = m_FoodExhaustionLevel; root["isflying"] = IsFlying(); root["lastknownname"] = GetName(); + root["SpawnX"] = GetLastBedPos().x; + root["SpawnY"] = GetLastBedPos().y; + root["SpawnZ"] = GetLastBedPos().z; + if (m_World != NULL) { root["world"] = m_World->GetName(); @@ -1907,7 +1884,6 @@ bool cPlayer::SaveToDisk() { root["gamemode"] = (int) m_GameMode; } ->>>>>>> master } else { diff --git a/src/Entities/Player.h b/src/Entities/Player.h index f84cc5f55..ad434f036 100644 --- a/src/Entities/Player.h +++ b/src/Entities/Player.h @@ -326,11 +326,6 @@ public: virtual void Killed(cEntity * a_Victim) override; - void Respawn(void); // tolua_export - - void SetVisible(bool a_bVisible); // tolua_export - bool IsVisible(void) const { return m_bVisible; } // tolua_export - void Respawn(void); // tolua_export void SetVisible( bool a_bVisible ); // tolua_export @@ -352,7 +347,7 @@ Takes a (NULL) cWorld pointer which it will assign a value to based on either th /** Loads the player data from the specified file. Returns true on success, false on failure. */ - bool LoadFromFile(const AString & a_FileName); + bool LoadFromFile(const AString & a_FileName, cWorld * a_World); void LoadPermissionsFromDisk(void); // tolua_export @@ -544,8 +539,6 @@ protected: cStatManager m_Stats; -<<<<<<< HEAD -======= /** Flag representing whether the player is currently in a bed Set by a right click on unoccupied bed, unset by a time fast forward or teleport */ bool m_bIsInBed; @@ -563,8 +556,6 @@ protected: If no ClientHandle is given, the UUID is initialized to empty. */ AString m_UUID; - ->>>>>>> master /** Sets the speed and sends it to the client, so that they are forced to move so. */ virtual void DoSetSpeed(double a_SpeedX, double a_SpeedY, double a_SpeedZ) override; diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h index 7e9eed402..58dbfeff5 100644 --- a/src/Protocol/Protocol.h +++ b/src/Protocol/Protocol.h @@ -100,7 +100,7 @@ public: virtual void SendPlayerSpawn (const cPlayer & a_Player) = 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 SendRespawn (eDimension a_Dimension) = 0; + virtual void SendRespawn (eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks) = 0; virtual void SendExperience (void) = 0; virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) = 0; virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) = 0; diff --git a/src/Protocol/Protocol125.cpp b/src/Protocol/Protocol125.cpp index 8cb34c128..320c1212c 100644 --- a/src/Protocol/Protocol125.cpp +++ b/src/Protocol/Protocol125.cpp @@ -836,7 +836,7 @@ void cProtocol125::SendRemoveEntityEffect(const cEntity & a_Entity, int a_Effect void cProtocol125::SendRespawn(eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks) { cCSLock Lock(m_CSPacket); - if ((m_LastSentDimension == a_World.GetDimension()) && !a_ShouldIgnoreDimensionChecks) + if ((m_LastSentDimension == a_Dimension) && !a_ShouldIgnoreDimensionChecks) { // Must not send a respawn for the world with the same dimension, the client goes cuckoo if we do (unless we are respawning from death) return; diff --git a/src/Protocol/Protocol125.h b/src/Protocol/Protocol125.h index 955e3e741..d1ed00b54 100644 --- a/src/Protocol/Protocol125.h +++ b/src/Protocol/Protocol125.h @@ -72,7 +72,7 @@ public: virtual void SendPlayerSpawn (const cPlayer & a_Player) 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 SendRespawn (eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks = false) override; + virtual void SendRespawn (eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks) override; virtual void SendExperience (void) override; virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override; virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override; diff --git a/src/Protocol/Protocol16x.h b/src/Protocol/Protocol16x.h index 13866801a..add761d1e 100644 --- a/src/Protocol/Protocol16x.h +++ b/src/Protocol/Protocol16x.h @@ -42,7 +42,7 @@ protected: virtual void SendGameMode (eGameMode a_GameMode) override; virtual void SendHealth (void) override; virtual void SendPlayerMaxSpeed(void) override; - virtual void SendRespawn (eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks = false) override; + virtual void SendRespawn (eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks) override; virtual void SendWindowOpen (const cWindow & a_Window) override; virtual int ParseEntityAction (void) override; diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index a421e4da6..0ff0d0357 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -988,7 +988,7 @@ void cProtocol172::SendRemoveEntityEffect(const cEntity & a_Entity, int a_Effect void cProtocol172::SendRespawn(eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks) { - if ((m_LastSentDimension == a_World.GetDimension()) && !a_ShouldIgnoreDimensionChecks) + if ((m_LastSentDimension == a_Dimension) && !a_ShouldIgnoreDimensionChecks) { // Must not send a respawn for the world with the same dimension, the client goes cuckoo if we do (unless we are respawning from death) return; diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h index 2d4005f57..be41abd64 100644 --- a/src/Protocol/Protocol17x.h +++ b/src/Protocol/Protocol17x.h @@ -104,7 +104,7 @@ public: virtual void SendPlayerSpawn (const cPlayer & a_Player) 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 SendRespawn (eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks = false) override; + virtual void SendRespawn (eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks) override; virtual void SendSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch) override; virtual void SendExperience (void) override; virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override; diff --git a/src/Protocol/ProtocolRecognizer.h b/src/Protocol/ProtocolRecognizer.h index b78528e29..9c6c898ab 100644 --- a/src/Protocol/ProtocolRecognizer.h +++ b/src/Protocol/ProtocolRecognizer.h @@ -107,7 +107,7 @@ public: virtual void SendPlayerSpawn (const cPlayer & a_Player) 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 SendRespawn (eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks = false) override; + virtual void SendRespawn (eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks) override; virtual void SendExperience (void) override; virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override; virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override; diff --git a/src/World.cpp b/src/World.cpp index e32771353..924d5adbb 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -527,7 +527,7 @@ void cWorld::Start(bool a_WasDimensionSet) AString Dimension = IniFile.GetValueSet("General", "Dimension", a_WasDimensionSet ? DimensionToString(GetDimension()) : "Overworld"); m_Dimension = StringToDimension(Dimension); - m_OverworldName = IniFile.GetValue("General", "OverworldName", a_WasDimensionSet ? m_OverworldName : ""); + m_OverworldName = IniFile.GetValue("LinkedWorlds", "OverworldName", a_WasDimensionSet ? m_OverworldName : ""); // Try to find the "SpawnPosition" key and coord values in the world configuration, set the flag if found int KeyNum = IniFile.FindKey("SpawnPosition"); @@ -577,10 +577,8 @@ void cWorld::Start(bool a_WasDimensionSet) if ((GetDimension() != dimNether) && (GetDimension() != dimEnd)) { - m_bNetherPortalsEnabled = IniFile.GetValueSetB("General", "NetherPortalsEnabled", true); - m_NetherWorldName = IniFile.GetValueSet("General", "NetherWorldName", DEFAULT_NETHER_NAME); - m_bEndPortalsEnabled = IniFile.GetValueSetB("General", "EndPortalsEnabled", true); - m_EndWorldName = IniFile.GetValueSet("General", "EndWorldName", DEFAULT_END_NAME); + m_NetherWorldName = IniFile.GetValueSet("LinkedWorlds", "NetherWorldName", DEFAULT_NETHER_NAME); + m_EndWorldName = IniFile.GetValueSet("LinkedWorlds", "EndWorldName", DEFAULT_END_NAME); } // Adjust the enum-backed variables into their respective bounds: @@ -757,14 +755,12 @@ void cWorld::Stop(void) IniFile.ReadFile(m_IniFileName); if ((GetDimension() != dimNether) && (GetDimension() != dimEnd)) { - IniFile.SetValueB("General", "NetherPortalsEnabled", m_bNetherPortalsEnabled); - IniFile.SetValue("General", "NetherWorldName", m_NetherWorldName); - IniFile.SetValueB("General", "EndPortalsEnabled", m_bEndPortalsEnabled); - IniFile.SetValue("General", "EndWorldName", m_EndWorldName); + IniFile.SetValue("LinkedWorlds", "NetherWorldName", m_NetherWorldName); + IniFile.SetValue("LinkedWorlds", "EndWorldName", m_EndWorldName); } else { - IniFile.SetValue("General", "OverworldName", m_OverworldName); + IniFile.SetValue("LinkedWorlds", "OverworldName", m_OverworldName); } IniFile.SetValueI("Physics", "TNTShrapnelLevel", (int)m_TNTShrapnelLevel); IniFile.SetValueB("Mechanics", "CommandBlocksEnabled", m_bCommandBlocksEnabled); diff --git a/src/World.h b/src/World.h index 92376b4a0..73b8b81b0 100644 --- a/src/World.h +++ b/src/World.h @@ -630,12 +630,6 @@ public: bool ShouldUseChatPrefixes(void) const { return m_bUseChatPrefixes; } void SetShouldUseChatPrefixes(bool a_Flag) { m_bUseChatPrefixes = a_Flag; } - bool AreNetherPortalsEnabled(void) const { return m_bNetherPortalsEnabled; } - void SetNetherPortalsEnabled(bool a_Flag) { m_bNetherPortalsEnabled = a_Flag; } - - bool AreEndPortalsEnabled(void) const { return m_bEndPortalsEnabled; } - void SetEndPortalsEnabled(bool a_Flag) { m_bEndPortalsEnabled = a_Flag; } - AString GetNetherWorldName(void) const { return m_NetherWorldName; } void SetNetherWorldName(const AString & a_Name) { m_NetherWorldName = a_Name; } @@ -938,12 +932,6 @@ private: */ eShrapnelLevel m_TNTShrapnelLevel; - /** Whether nether portals teleport entities */ - bool m_bNetherPortalsEnabled; - - /** Whether end portals teleport entities */ - bool m_bEndPortalsEnabled; - /** Name of the nether world */ AString m_NetherWorldName; -- cgit v1.2.3 From 6ab9afd0fd808fad99cd8387c72ce461c37aef80 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 20 Jul 2014 10:46:45 +0100 Subject: Bug and crash fixes * Fixes end portals' solidity * Fixed crashes to do with multithreading and removing an entity from the wrong world * Fixed crashes due to bad merge * Fixed crashes due to an object being deleted twice * Simplified cWorld::Start() and added comments to configuration files --- src/BlockInfo.cpp | 1 + src/Chunk.cpp | 5 ++--- src/ClientHandle.cpp | 2 ++ src/Entities/Entity.cpp | 48 ++++++++++++++++++++++++++++++------------------ src/Entities/Entity.h | 15 +++++++++------ src/Entities/Player.cpp | 35 +++++++++++++++++------------------ src/Entities/Player.h | 15 +++++++++------ src/MobSpawner.cpp | 3 ++- src/Root.cpp | 9 +++++++-- src/Root.h | 13 +++++++++++-- src/World.cpp | 24 ++++++++++++++++-------- src/World.h | 2 +- 12 files changed, 107 insertions(+), 65 deletions(-) diff --git a/src/BlockInfo.cpp b/src/BlockInfo.cpp index 97e89359f..0882d2740 100644 --- a/src/BlockInfo.cpp +++ b/src/BlockInfo.cpp @@ -496,6 +496,7 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info) a_Info[E_BLOCK_CROPS ].m_IsSolid = false; a_Info[E_BLOCK_DANDELION ].m_IsSolid = false; a_Info[E_BLOCK_DETECTOR_RAIL ].m_IsSolid = false; + a_Info[E_BLOCK_END_PORTAL ].m_IsSolid = false; a_Info[E_BLOCK_FIRE ].m_IsSolid = false; a_Info[E_BLOCK_FLOWER ].m_IsSolid = false; a_Info[E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE].m_IsSolid = false; diff --git a/src/Chunk.cpp b/src/Chunk.cpp index 2f3bdff81..4588de9f3 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -591,7 +591,6 @@ void cChunk::Tick(float a_Dt) if (!((*itr)->IsMob())) { (*itr)->Tick(a_Dt, *this); - continue; } } // for itr - m_Entitites[] @@ -605,10 +604,10 @@ void cChunk::Tick(float a_Dt) itr = m_Entities.erase(itr); delete ToDelete; } - else if ((*itr)->IsTravellingThroughPortal()) // Remove all entities that are travelling to another world + else if ((*itr)->IsWorldTravellingFrom(m_World)) // Remove all entities that are travelling to another world { MarkDirty(); - (*itr)->SetIsTravellingThroughPortal(false); + (*itr)->SetWorldTravellingFrom(NULL); itr = m_Entities.erase(itr); } else if ( // If any entity moved out of the chunk, move it to the neighbor: diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index f90da94dd..8caaae917 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -120,6 +120,8 @@ cClientHandle::~cClientHandle() } if (World != NULL) { + m_Player->SetWorldTravellingFrom(NULL); // Make sure that the player entity is actually removed + World->RemovePlayer(m_Player); // Must be called before cPlayer::Destroy() as otherwise cChunk tries to delete the player, and then we do it again m_Player->Destroy(); } delete m_Player; diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index bd1839580..4768d38ae 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -37,7 +37,7 @@ cEntity::cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, d , m_Gravity(-9.81f) , m_LastPos(a_X, a_Y, a_Z) , m_IsInitialized(false) - , m_IsTravellingThroughPortal(false) + , m_WorldTravellingFrom(NULL) , m_EntityType(a_EntityType) , m_World(NULL) , m_IsFireproof(false) @@ -1028,10 +1028,11 @@ void cEntity::DetectCacti(void) void cEntity::DetectPortal() { - if (!GetWorld()->GetNetherWorldName().empty() && !GetWorld()->GetEndWorldName().empty()) + if (GetWorld()->GetDimension() == dimOverworld) { - return; + if (GetWorld()->GetNetherWorldName().empty() && GetWorld()->GetEndWorldName().empty()) { return; } } + else if (GetWorld()->GetLinkedOverworldName().empty()) { return; } int X = POSX_TOINT, Y = POSY_TOINT, Z = POSZ_TOINT; if ((Y > 0) && (Y < cChunkDef::Height)) @@ -1040,7 +1041,7 @@ void cEntity::DetectPortal() { case E_BLOCK_NETHER_PORTAL: { - if (GetWorld()->GetNetherWorldName().empty() || m_PortalCooldownData.second) + if (m_PortalCooldownData.second) { return; } @@ -1054,8 +1055,13 @@ void cEntity::DetectPortal() switch (GetWorld()->GetDimension()) { - case dimNether: + case dimNether: { + if (GetWorld()->GetLinkedOverworldName().empty()) + { + return; + } + m_PortalCooldownData.second = true; // Stop portals from working on respawn if (IsPlayer()) @@ -1068,6 +1074,11 @@ void cEntity::DetectPortal() } case dimOverworld: { + if (GetWorld()->GetNetherWorldName().empty()) + { + return; + } + m_PortalCooldownData.second = true; // Stop portals from working on respawn if (IsPlayer()) @@ -1079,28 +1090,25 @@ void cEntity::DetectPortal() return; } - default: break; + default: return; } - return; } case E_BLOCK_END_PORTAL: { - if (GetWorld()->GetNetherWorldName().empty() || m_PortalCooldownData.second) - { - return; - } - - if (m_PortalCooldownData.first != 80) + if (m_PortalCooldownData.second) { - m_PortalCooldownData.first++; return; } - m_PortalCooldownData.first = 0; switch (GetWorld()->GetDimension()) { case dimEnd: { + if (GetWorld()->GetLinkedOverworldName().empty()) + { + return; + } + m_PortalCooldownData.second = true; // Stop portals from working on respawn if (IsPlayer()) @@ -1115,6 +1123,11 @@ void cEntity::DetectPortal() } case dimOverworld: { + if (GetWorld()->GetEndWorldName().empty()) + { + return; + } + m_PortalCooldownData.second = true; // Stop portals from working on respawn if (IsPlayer()) @@ -1126,9 +1139,8 @@ void cEntity::DetectPortal() return; } - default: break; + default: return; } - return; } default: break; } @@ -1169,7 +1181,7 @@ bool cEntity::MoveToWorld(const AString & a_WorldName, cWorld * a_World, bool a_ } // Remove all links to the old world - SetIsTravellingThroughPortal(true); // cChunk handles entity removal + SetWorldTravellingFrom(GetWorld()); // cChunk handles entity removal GetWorld()->BroadcastDestroyEntity(*this); // Queue add to new world diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h index 8b6fc05f7..eea48a12f 100644 --- a/src/Entities/Entity.h +++ b/src/Entities/Entity.h @@ -387,11 +387,11 @@ public: // tolua_end - /** Returns if the entity is travelling through a portal. Set to true by MoveToWorld and to false when the entity is removed by the old chunk */ - bool IsTravellingThroughPortal(void) const { return m_IsTravellingThroughPortal; } + /** Returns if the entity is travelling away from a specified world */ + bool IsWorldTravellingFrom(cWorld * a_World) const { return (m_WorldTravellingFrom == a_World); } - /** Sets if the entity has begun travelling through a portal or not */ - void SetIsTravellingThroughPortal(bool a_Flag) { m_IsTravellingThroughPortal = a_Flag; } + /** Sets the world the entity will be leaving */ + void SetWorldTravellingFrom(cWorld * a_World) { (m_WorldTravellingFrom = a_World); } /// Updates clients of changes in the entity. virtual void BroadcastMovementUpdate(const cClientHandle * a_Exclude = NULL); @@ -491,8 +491,11 @@ protected: /** True when entity is initialised (Initialize()) and false when destroyed pending deletion (Destroy()) */ bool m_IsInitialized; - /** True when entity is being moved across worlds, false anytime else */ - bool m_IsTravellingThroughPortal; + /** World entity is travelling from + Set by MoveToWorld and back to NULL when the entity is removed by the old chunk + Can't be a simple boolean as context switches between worlds may leave the new chunk processing (and therefore immediately removing) the entity before the old chunk could remove it + */ + cWorld * m_WorldTravellingFrom; eEntityType m_EntityType; diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 2a91600e7..0b1b4ce5f 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -88,7 +88,7 @@ cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName) : m_PlayerName = a_PlayerName; - cWorld * World; + cWorld * World = NULL; if (!LoadFromDisk(World)) { m_Inventory.Clear(); @@ -136,8 +136,6 @@ cPlayer::~cPlayer(void) SaveToDisk(); - m_World->RemovePlayer(this); - m_ClientHandle = NULL; delete m_InventoryWindow; @@ -979,7 +977,7 @@ void cPlayer::Respawn(void) m_LifetimeTotalXp = 0; // ToDo: send score to client? How? - m_ClientHandle->SendRespawn(GetWorld()->GetDimension()); + m_ClientHandle->SendRespawn(GetWorld()->GetDimension(), true); // Extinguish the fire: StopBurning(); @@ -1643,11 +1641,12 @@ bool cPlayer::MoveToWorld(const AString & a_WorldName, cWorld * a_World, bool a_ } // Remove player from the old world - SetIsTravellingThroughPortal(true); // cChunk handles entity removal - m_World->RemovePlayer(this); + SetWorldTravellingFrom(GetWorld()); // cChunk handles entity removal + GetWorld()->RemovePlayer(this); // Queue adding player to the new world, including all the necessary adjustments to the object World->AddPlayer(this); + SetWorld(World); return true; } @@ -1697,12 +1696,6 @@ void cPlayer::LoadPermissionsFromDisk() bool cPlayer::LoadFromDisk(cWorldPtr & a_World) { - a_World = cRoot::Get()->GetWorld(GetLoadedWorldName()); - if (a_World == NULL) - { - a_World = cRoot::Get()->GetDefaultWorld(); - } - LoadPermissionsFromDisk(); // Load from the UUID file: @@ -1740,6 +1733,11 @@ bool cPlayer::LoadFromDisk(cWorldPtr & a_World) LOG("Player data file not found for %s (%s, offline %s), will be reset to defaults.", GetName().c_str(), m_UUID.c_str(), OfflineUUID.c_str() ); + + if (a_World == NULL) + { + a_World = cRoot::Get()->GetDefaultWorld(); + } return false; } @@ -1747,7 +1745,7 @@ bool cPlayer::LoadFromDisk(cWorldPtr & a_World) -bool cPlayer::LoadFromFile(const AString & a_FileName, cWorld * a_World) +bool cPlayer::LoadFromFile(const AString & a_FileName, cWorldPtr & a_World) { // Load the data from the file: cFile f; @@ -1800,9 +1798,6 @@ bool cPlayer::LoadFromFile(const AString & a_FileName, cWorld * a_World) m_LifetimeTotalXp = (short) root.get("xpTotal", 0).asInt(); m_CurrentXp = (short) root.get("xpCurrent", 0).asInt(); m_IsFlying = root.get("isflying", 0).asBool(); - m_LastBedPos.x = root.get("SpawnX", a_World->GetSpawnX()).asInt(); - m_LastBedPos.y = root.get("SpawnY", a_World->GetSpawnY()).asInt(); - m_LastBedPos.z = root.get("SpawnZ", a_World->GetSpawnZ()).asInt(); m_GameMode = (eGameMode) root.get("gamemode", eGameMode_NotSet).asInt(); @@ -1815,6 +1810,11 @@ bool cPlayer::LoadFromFile(const AString & a_FileName, cWorld * a_World) cEnderChestEntity::LoadFromJson(root["enderchestinventory"], m_EnderChestContents); m_LoadedWorldName = root.get("world", "world").asString(); + a_World = cRoot::Get()->GetWorld(GetLoadedWorldName(), true); + + m_LastBedPos.x = root.get("SpawnX", a_World->GetSpawnX()).asInt(); + m_LastBedPos.y = root.get("SpawnY", a_World->GetSpawnY()).asInt(); + m_LastBedPos.z = root.get("SpawnZ", a_World->GetSpawnZ()).asInt(); // Load the player stats. // We use the default world name (like bukkit) because stats are shared between dimensions/worlds. @@ -1822,7 +1822,7 @@ bool cPlayer::LoadFromFile(const AString & a_FileName, cWorld * a_World) StatSerializer.Load(); LOGD("Player %s was read from file \"%s\", spawning at {%.2f, %.2f, %.2f} in world \"%s\"", - GetName().c_str(), a_FileName.c_str(), GetPosX(), GetPosY(), GetPosZ(), m_LoadedWorldName.c_str() + GetName().c_str(), a_FileName.c_str(), GetPosX(), GetPosY(), GetPosZ(), a_World->GetName().c_str() ); return true; @@ -1834,7 +1834,6 @@ bool cPlayer::LoadFromFile(const AString & a_FileName, cWorld * a_World) bool cPlayer::SaveToDisk() { - cFile::CreateFolder(FILE_IO_PREFIX + AString("players")); cFile::CreateFolder(FILE_IO_PREFIX + AString("players/") + m_UUID.substr(0, 2)); // create the JSON data diff --git a/src/Entities/Player.h b/src/Entities/Player.h index ad434f036..226ec5e68 100644 --- a/src/Entities/Player.h +++ b/src/Entities/Player.h @@ -340,14 +340,17 @@ public: typedef cWorld * cWorldPtr; - /** Loads the player data from the disk file. -Takes a (NULL) cWorld pointer which it will assign a value to based on either the loaded world or default world - Returns true on success, false on failure. */ + /** Loads the player data from the disk file + Takes a (NULL) cWorld pointer which it will assign a value to based on either the loaded world or default world by calling LoadFromFile() + Returns true on success, false on failure + */ bool LoadFromDisk(cWorldPtr & a_World); - /** Loads the player data from the specified file. - Returns true on success, false on failure. */ - bool LoadFromFile(const AString & a_FileName, cWorld * a_World); + /** Loads the player data from the specified file + Takes a (NULL) cWorld pointer which it will assign a value to based on either the loaded world or default world + Returns true on success, false on failure + */ + bool LoadFromFile(const AString & a_FileName, cWorldPtr & a_World); void LoadPermissionsFromDisk(void); // tolua_export diff --git a/src/MobSpawner.cpp b/src/MobSpawner.cpp index da3e7c406..d09bbc943 100644 --- a/src/MobSpawner.cpp +++ b/src/MobSpawner.cpp @@ -241,7 +241,8 @@ bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_R (m_Random.NextInt(2, a_Biome) == 0) ); } - + + case cMonster::mtMagmaCube: case cMonster::mtSlime: { return ( diff --git a/src/Root.cpp b/src/Root.cpp index 822be92ff..e1eebb711 100644 --- a/src/Root.cpp +++ b/src/Root.cpp @@ -322,7 +322,7 @@ cWorld * cRoot::CreateAndInitializeWorld(const AString & a_WorldName, eDimension } cWorld * NewWorld = new cWorld(a_WorldName.c_str(), a_Dimension, a_OverworldName); m_WorldsByName[a_WorldName] = NewWorld; - NewWorld->Start(!a_OverworldName.empty()); + NewWorld->Start(); NewWorld->InitializeSpawn(); m_PluginManager->CallHookWorldStarted(*NewWorld); return NewWorld; @@ -381,13 +381,18 @@ cWorld * cRoot::GetDefaultWorld() -cWorld * cRoot::GetWorld(const AString & a_WorldName) +cWorld * cRoot::GetWorld(const AString & a_WorldName, bool a_SearchForFolder) { WorldMap::iterator itr = m_WorldsByName.find(a_WorldName); if (itr != m_WorldsByName.end()) { return itr->second; } + + if (a_SearchForFolder && cFile::IsFolder(FILE_IO_PREFIX + a_WorldName)) + { + return CreateAndInitializeWorld(a_WorldName); + } return NULL; } diff --git a/src/Root.h b/src/Root.h index c3aca37f9..4e3fcf080 100644 --- a/src/Root.h +++ b/src/Root.h @@ -51,8 +51,17 @@ public: // tolua_begin cServer * GetServer(void) { return m_Server; } cWorld * GetDefaultWorld(void); - cWorld * GetWorld(const AString & a_WorldName); - cWorld * CreateAndInitializeWorld(const AString & a_WorldName, eDimension a_Dimension = dimOverworld, const AString & a_OverworldName = ""); + + /** Returns a pointer to the world specified + If no world of that name was currently loaded and a_SearchForFolder was true, it will consult cFile::IsFolder() to see if a world folder of that name exists and if so, initialise a world based on that name + */ + cWorld * GetWorld(const AString & a_WorldName, bool a_SearchForFolder = false); + + /** Returns a pointer to a world of specified name - will search loaded worlds first, then create anew if not found + The dimension parameter is used to create a world with a specific dimension + a_OverworldName should be set for non-overworld dimensions if one wishes that world to link back to an overworld via portals + */ + cWorld * CreateAndInitializeWorld(const AString & a_WorldName, eDimension a_Dimension = dimOverworld, const AString & a_OverworldName = ""); // tolua_end /// Calls the callback for each world; returns true if the callback didn't abort (return true) diff --git a/src/World.cpp b/src/World.cpp index 924d5adbb..d27ad1eb4 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -512,7 +512,7 @@ void cWorld::InitializeSpawn(void) -void cWorld::Start(bool a_WasDimensionSet) +void cWorld::Start() { m_SpawnX = 0; m_SpawnY = cChunkDef::Height; @@ -523,11 +523,15 @@ void cWorld::Start(bool a_WasDimensionSet) if (!IniFile.ReadFile(m_IniFileName)) { LOGWARNING("Cannot read world settings from \"%s\", defaults will be used.", m_IniFileName.c_str()); + + // TODO: More descriptions for each key + IniFile.AddHeaderComment(" This is the per-world configuration file, managing settings such as generators, simulators, and spawn points"); + IniFile.AddKeyComment("LinkedWorlds", "This section governs portal world linkage; leave a value blank to disabled that associated method of teleportation"); } - AString Dimension = IniFile.GetValueSet("General", "Dimension", a_WasDimensionSet ? DimensionToString(GetDimension()) : "Overworld"); - m_Dimension = StringToDimension(Dimension); - m_OverworldName = IniFile.GetValue("LinkedWorlds", "OverworldName", a_WasDimensionSet ? m_OverworldName : ""); + // The presence of a configuration value overrides everything + // If no configuration value is found, GetDimension() is written to file and the variable is written to again to ensure that cosmic rays haven't sneakily changed its value + m_Dimension = StringToDimension(IniFile.GetValueSet("General", "Dimension", DimensionToString(GetDimension()))); // Try to find the "SpawnPosition" key and coord values in the world configuration, set the flag if found int KeyNum = IniFile.FindKey("SpawnPosition"); @@ -535,8 +539,8 @@ void cWorld::Start(bool a_WasDimensionSet) ( (KeyNum >= 0) && ( - (IniFile.FindValue(KeyNum, "X") >= 0) || - (IniFile.FindValue(KeyNum, "Y") >= 0) || + (IniFile.FindValue(KeyNum, "X") >= 0) && + (IniFile.FindValue(KeyNum, "Y") >= 0) && (IniFile.FindValue(KeyNum, "Z") >= 0) ) ); @@ -575,11 +579,15 @@ void cWorld::Start(bool a_WasDimensionSet) int Weather = IniFile.GetValueSetI("General", "Weather", (int)m_Weather); m_TimeOfDay = IniFile.GetValueSetI("General", "TimeInTicks", m_TimeOfDay); - if ((GetDimension() != dimNether) && (GetDimension() != dimEnd)) + if (GetDimension() == dimOverworld) { m_NetherWorldName = IniFile.GetValueSet("LinkedWorlds", "NetherWorldName", DEFAULT_NETHER_NAME); m_EndWorldName = IniFile.GetValueSet("LinkedWorlds", "EndWorldName", DEFAULT_END_NAME); } + else + { + m_OverworldName = IniFile.GetValueSet("LinkedWorlds", "OverworldName", GetLinkedOverworldName()); + } // Adjust the enum-backed variables into their respective bounds: m_GameMode = (eGameMode) Clamp(GameMode, (int)gmSurvival, (int)gmAdventure); @@ -2420,7 +2428,7 @@ void cWorld::AddPlayer(cPlayer * a_Player) void cWorld::RemovePlayer(cPlayer * a_Player) { - if (!a_Player->IsTravellingThroughPortal()) + if (!a_Player->IsWorldTravellingFrom(this)) { m_ChunkMap->RemoveEntity(a_Player); } diff --git a/src/World.h b/src/World.h index 73b8b81b0..09cbc6b48 100644 --- a/src/World.h +++ b/src/World.h @@ -669,7 +669,7 @@ public: void InitializeSpawn(void); /** Starts threads that belong to this world */ - void Start(bool a_WasDimensionSet = true); + void Start(); /** Stops threads that belong to this world (part of deinit) */ void Stop(void); -- cgit v1.2.3 From 8050a5b98a3003c2a4bed39b896b4a3a4c1068c0 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Mon, 21 Jul 2014 22:49:06 +0100 Subject: Suggestions --- lib/inifile/iniFile.cpp | 2 +- src/BlockID.h | 2 +- src/Chunk.cpp | 6 +-- src/ChunkMap.cpp | 1 - src/Entities/Entity.cpp | 78 +++++++++++++++------------- src/Entities/Entity.h | 30 +++++++---- src/Entities/Player.cpp | 25 ++------- src/Entities/Player.h | 2 +- src/World.cpp | 135 ++++++++++++++++++++++++++++-------------------- src/World.h | 7 +++ 10 files changed, 161 insertions(+), 127 deletions(-) diff --git a/lib/inifile/iniFile.cpp b/lib/inifile/iniFile.cpp index 30f93e5a3..2bf6c91ed 100644 --- a/lib/inifile/iniFile.cpp +++ b/lib/inifile/iniFile.cpp @@ -585,7 +585,7 @@ Int64 cIniFile::GetValueSetI(const AString & keyname, const AString & valuename, AString Data; Printf(Data, "%lld", defValue); AString resultstring = GetValueSet(keyname, valuename, Data); - Int64 result; + Int64 result = defValue; #ifdef _WIN32 sscanf_s(resultstring.c_str(), "%lld", &result); #else diff --git a/src/BlockID.h b/src/BlockID.h index 37eed8eda..08c576886 100644 --- a/src/BlockID.h +++ b/src/BlockID.h @@ -924,7 +924,7 @@ extern int StringToMobType(const AString & a_MobString); extern eDimension StringToDimension(const AString & a_DimensionString); /** Translates a dimension enum to dimension string. -Takes a string and returns "Overworld" on failure +Takes an eDimension enum value and returns "Overworld" on failure */ extern AString DimensionToString(eDimension a_Dimension); diff --git a/src/Chunk.cpp b/src/Chunk.cpp index 4588de9f3..7850b7e31 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -596,7 +596,7 @@ void cChunk::Tick(float a_Dt) for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end();) { - if ((*itr)->IsDestroyed()) // Remove all entities that were scheduled for removal: + if ((*itr)->IsDestroyed()) // Remove all entities that were scheduled for removal: { LOGD("Destroying entity #%i (%s)", (*itr)->GetUniqueID(), (*itr)->GetClass()); MarkDirty(); @@ -604,13 +604,13 @@ void cChunk::Tick(float a_Dt) itr = m_Entities.erase(itr); delete ToDelete; } - else if ((*itr)->IsWorldTravellingFrom(m_World)) // Remove all entities that are travelling to another world + else if ((*itr)->IsWorldTravellingFrom(m_World)) // Remove all entities that are travelling to another world { MarkDirty(); (*itr)->SetWorldTravellingFrom(NULL); itr = m_Entities.erase(itr); } - else if ( // If any entity moved out of the chunk, move it to the neighbor: + else if ( // If any entity moved out of the chunk, move it to the neighbor: ((*itr)->GetChunkX() != m_PosX) || ((*itr)->GetChunkZ() != m_PosZ) ) diff --git a/src/ChunkMap.cpp b/src/ChunkMap.cpp index 3cfa5c3f5..e91f77d27 100644 --- a/src/ChunkMap.cpp +++ b/src/ChunkMap.cpp @@ -2427,7 +2427,6 @@ bool cChunkMap::ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinCh { for (int x = a_MinChunkX; x <= a_MaxChunkX; x++) { - LOG("Request %i %i", x, z); cChunkPtr Chunk = GetChunkNoLoad(x, ZERO_CHUNK_Y, z); if ((Chunk == NULL) || (!Chunk->IsValid())) { diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index 4768d38ae..1254541ed 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -1030,9 +1030,15 @@ void cEntity::DetectPortal() { if (GetWorld()->GetDimension() == dimOverworld) { - if (GetWorld()->GetNetherWorldName().empty() && GetWorld()->GetEndWorldName().empty()) { return; } + if (GetWorld()->GetNetherWorldName().empty() && GetWorld()->GetEndWorldName().empty()) + { + return; + } + } + else if (GetWorld()->GetLinkedOverworldName().empty()) + { + return; } - else if (GetWorld()->GetLinkedOverworldName().empty()) { return; } int X = POSX_TOINT, Y = POSY_TOINT, Z = POSZ_TOINT; if ((Y > 0) && (Y < cChunkDef::Height)) @@ -1041,17 +1047,17 @@ void cEntity::DetectPortal() { case E_BLOCK_NETHER_PORTAL: { - if (m_PortalCooldownData.second) + if (m_PortalCooldownData.m_ShouldPreventTeleportation) { return; } - if (m_PortalCooldownData.first != 80) + if (IsPlayer() && !((cPlayer *)this)->IsGameModeCreative() && m_PortalCooldownData.m_TicksDelayed != 80) { - m_PortalCooldownData.first++; + m_PortalCooldownData.m_TicksDelayed++; return; } - m_PortalCooldownData.first = 0; + m_PortalCooldownData.m_TicksDelayed = 0; switch (GetWorld()->GetDimension()) { @@ -1062,13 +1068,13 @@ void cEntity::DetectPortal() return; } - m_PortalCooldownData.second = true; // Stop portals from working on respawn + m_PortalCooldownData.m_ShouldPreventTeleportation = true; // Stop portals from working on respawn if (IsPlayer()) { ((cPlayer *)this)->GetClientHandle()->SendRespawn(dimOverworld); } - MoveToWorld(GetWorld()->GetLinkedOverworldName(), cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedOverworldName()), false); + MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedOverworldName()), false); return; } @@ -1079,14 +1085,14 @@ void cEntity::DetectPortal() return; } - m_PortalCooldownData.second = true; // Stop portals from working on respawn + m_PortalCooldownData.m_ShouldPreventTeleportation = true; // Stop portals from working on respawn if (IsPlayer()) { ((cPlayer *)this)->AwardAchievement(achEnterPortal); ((cPlayer *)this)->GetClientHandle()->SendRespawn(dimNether); } - MoveToWorld(GetWorld()->GetNetherWorldName(), cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetNetherWorldName(), dimNether, GetWorld()->GetName()), false); + MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetNetherWorldName(), dimNether, GetWorld()->GetName()), false); return; } @@ -1095,7 +1101,7 @@ void cEntity::DetectPortal() } case E_BLOCK_END_PORTAL: { - if (m_PortalCooldownData.second) + if (m_PortalCooldownData.m_ShouldPreventTeleportation) { return; } @@ -1109,7 +1115,7 @@ void cEntity::DetectPortal() return; } - m_PortalCooldownData.second = true; // Stop portals from working on respawn + m_PortalCooldownData.m_ShouldPreventTeleportation = true; // Stop portals from working on respawn if (IsPlayer()) { @@ -1117,7 +1123,7 @@ void cEntity::DetectPortal() Player->TeleportToCoords(Player->GetLastBedPos().x, Player->GetLastBedPos().y, Player->GetLastBedPos().z); Player->GetClientHandle()->SendRespawn(dimOverworld); } - MoveToWorld(GetWorld()->GetLinkedOverworldName(), cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedOverworldName()), false); + MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedOverworldName()), false); return; } @@ -1128,14 +1134,14 @@ void cEntity::DetectPortal() return; } - m_PortalCooldownData.second = true; // Stop portals from working on respawn + m_PortalCooldownData.m_ShouldPreventTeleportation = true; // Stop portals from working on respawn if (IsPlayer()) { ((cPlayer *)this)->AwardAchievement(achEnterTheEnd); ((cPlayer *)this)->GetClientHandle()->SendRespawn(dimEnd); } - MoveToWorld(GetWorld()->GetEndWorldName(), cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetEndWorldName(), dimEnd, GetWorld()->GetName()), false); + MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetEndWorldName(), dimEnd, GetWorld()->GetName()), false); return; } @@ -1147,34 +1153,20 @@ void cEntity::DetectPortal() } // Allow portals to work again - m_PortalCooldownData.second = false; - m_PortalCooldownData.first = 0; + m_PortalCooldownData.m_ShouldPreventTeleportation = false; + m_PortalCooldownData.m_ShouldPreventTeleportation = 0; } -bool cEntity::MoveToWorld(const AString & a_WorldName, cWorld * a_World, bool a_ShouldSendRespawn) +bool cEntity::MoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn) { UNUSED(a_ShouldSendRespawn); + ASSERT(a_World == NULL); - 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.c_str()); - return false; - } - } - else - { - World = a_World; - } - - if (GetWorld() == World) + if (GetWorld() == a_World) { // Don't move to same world return false; @@ -1185,7 +1177,7 @@ bool cEntity::MoveToWorld(const AString & a_WorldName, cWorld * a_World, bool a_ GetWorld()->BroadcastDestroyEntity(*this); // Queue add to new world - World->AddEntity(this); + a_World->AddEntity(this); return true; } @@ -1194,6 +1186,22 @@ bool cEntity::MoveToWorld(const AString & a_WorldName, cWorld * a_World, bool a_ +bool cEntity::MoveToWorld(const AString & a_WorldName, bool a_ShouldSendRespawn) +{ + cWorld * World = cRoot::Get()->GetWorld(a_WorldName); + if (World == NULL) + { + LOG("%s: Couldn't find world \"%s\".", __FUNCTION__, a_WorldName.c_str()); + return false; + } + + return MoveToWorld(World, a_ShouldSendRespawn); +} + + + + + void cEntity::SetSwimState(cChunk & a_Chunk) { int RelY = (int)floor(GetPosY() + 0.1); diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h index eea48a12f..58254a493 100644 --- a/src/Entities/Entity.h +++ b/src/Entities/Entity.h @@ -382,16 +382,19 @@ public: /// Teleports to the coordinates specified 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, bool a_ShouldSendRespawn = true); + /** Moves entity to specified world, taking a world pointer */ + virtual bool MoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn = true); + + /** Moves entity to specified world, taking a world name */ + bool MoveToWorld(const AString & a_WorldName, bool a_ShouldSendRespawn = true); // tolua_end /** Returns if the entity is travelling away from a specified world */ - bool IsWorldTravellingFrom(cWorld * a_World) const { return (m_WorldTravellingFrom == a_World); } + bool IsWorldTravellingFrom(cWorld * a_World) const { return m_WorldTravellingFrom == a_World; } /** Sets the world the entity will be leaving */ - void SetWorldTravellingFrom(cWorld * a_World) { (m_WorldTravellingFrom = a_World); } + void SetWorldTravellingFrom(cWorld * a_World) { m_WorldTravellingFrom = a_World; } /// Updates clients of changes in the entity. virtual void BroadcastMovementUpdate(const cClientHandle * a_Exclude = NULL); @@ -538,11 +541,20 @@ protected: int m_AirLevel; int m_AirTickTimer; - /** Portal delay timer and cooldown boolean - First value is to delay sending the respawn packet (which triggers the Entering the {Dimension} screen). - Second value is to prevent a teleportation loop by ensuring we do not reenter a portal that we came out of. - */ - std::pair m_PortalCooldownData; + /** Structure storing the portal delay timer and cooldown boolean */ + struct sPortalCooldownData + { + /** Ticks since entry of portal, used to delay teleportation */ + unsigned short m_TicksDelayed; + + /** Whether the entity has just exited the portal, and should therefore not be teleported again + This prevents teleportation loops, and is reset when the entity has moved out of the portal + */ + bool m_ShouldPreventTeleportation; + }; + + /** Portal delay timer and cooldown boolean data */ + sPortalCooldownData m_PortalCooldownData; private: /** Measured in degrees, [-180, +180) */ diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 0b1b4ce5f..1159891cd 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -1611,24 +1611,9 @@ void cPlayer::TossItems(const cItems & a_Items) -bool cPlayer::MoveToWorld(const AString & a_WorldName, cWorld * a_World, bool a_ShouldSendRespawn) +bool cPlayer::MoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn) { - 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.c_str()); - return false; - } - } - else - { - World = a_World; - } - - if (GetWorld() == World) + if (GetWorld() == a_World) { // Don't move to same world return false; @@ -1637,7 +1622,7 @@ bool cPlayer::MoveToWorld(const AString & a_WorldName, cWorld * a_World, bool a_ // Send the respawn packet: if (a_ShouldSendRespawn && (m_ClientHandle != NULL)) { - m_ClientHandle->SendRespawn(World->GetDimension()); + m_ClientHandle->SendRespawn(a_World->GetDimension()); } // Remove player from the old world @@ -1645,8 +1630,8 @@ bool cPlayer::MoveToWorld(const AString & a_WorldName, cWorld * a_World, bool a_ GetWorld()->RemovePlayer(this); // Queue adding player to the new world, including all the necessary adjustments to the object - World->AddPlayer(this); - SetWorld(World); + a_World->AddPlayer(this); + SetWorld(a_World); // Chunks may be streamed before cWorld::AddPlayer() sets the world to the new value return true; } diff --git a/src/Entities/Player.h b/src/Entities/Player.h index 226ec5e68..f972063bb 100644 --- a/src/Entities/Player.h +++ b/src/Entities/Player.h @@ -333,7 +333,7 @@ public: /** Moves the player to the specified world. Returns true if successful, false on failure (world not found). */ - virtual bool MoveToWorld(const AString & a_WorldName, cWorld * a_World = NULL, bool a_ShouldSendRespawn = true) override; // tolua_export + virtual bool MoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn = true) override; // tolua_export /** Saves all player data, such as inventory, to JSON */ bool SaveToDisk(void); diff --git a/src/World.cpp b/src/World.cpp index d27ad1eb4..2af8fc59e 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -512,7 +512,7 @@ void cWorld::InitializeSpawn(void) -void cWorld::Start() +void cWorld::Start(void) { m_SpawnX = 0; m_SpawnY = cChunkDef::Height; @@ -594,61 +594,8 @@ void cWorld::Start() m_TNTShrapnelLevel = (eShrapnelLevel)Clamp(TNTShrapnelLevel, (int)slNone, (int)slAll); m_Weather = (eWeather) Clamp(Weather, (int)wSunny, (int)wStorm); - 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: - const char * DefaultMonsters = ""; - switch (m_Dimension) - { - case dimOverworld: DefaultMonsters = "bat, cavespider, chicken, cow, creeper, enderman, horse, mooshroom, ocelot, pig, sheep, silverfish, skeleton, slime, spider, squid, wolf, zombie"; break; - case dimNether: DefaultMonsters = "blaze, ghast, magmacube, skeleton, zombie, zombiepigman"; break; - case dimEnd: DefaultMonsters = "enderman"; break; - } - m_bAnimals = IniFile.GetValueSetB("Monsters", "AnimalsOn", true); - AString AllMonsters = IniFile.GetValueSet("Monsters", "Types", DefaultMonsters); - AStringVector SplitList = StringSplitAndTrim(AllMonsters, ","); - for (AStringVector::const_iterator itr = SplitList.begin(), end = SplitList.end(); itr != end; ++itr) - { - cMonster::eType ToAdd = cMonster::StringToMobType(*itr); - if (ToAdd != cMonster::mtInvalidType) - { - m_AllowedMobs.insert(ToAdd); - LOGD("Allowed mob: %s", itr->c_str()); - } - else - { - LOG("World \"%s\": Unknown mob type: %s", m_WorldName.c_str(), itr->c_str()); - } - } + InitialiseGeneratorDefaults(IniFile); + InitialiseAndLoadMobSpawningValues(IniFile); m_ChunkMap = new cChunkMap(this); @@ -745,6 +692,82 @@ eWeather cWorld::ChooseNewWeather() +void cWorld::InitialiseGeneratorDefaults(cIniFile & a_IniFile) +{ + switch (GetDimension()) + { + case dimEnd: + { + a_IniFile.GetValueSet("Generator", "BiomeGen", "Constant"); + a_IniFile.GetValueSet("Generator", "ConstantBiome", "End"); + a_IniFile.GetValueSet("Generator", "HeightGen", "Biomal"); + a_IniFile.GetValueSet("Generator", "CompositionGen", "End"); + break; + } + case dimOverworld: + { + a_IniFile.GetValueSet("Generator", "BiomeGen", "MultiStepMap"); + a_IniFile.GetValueSet("Generator", "HeightGen", "DistortedHeightmap"); + a_IniFile.GetValueSet("Generator", "CompositionGen", "DistortedHeightmap"); + a_IniFile.GetValueSet("Generator", "Finishers", "Ravines, WormNestCaves, WaterLakes, WaterSprings, LavaLakes, LavaSprings, OreNests, Mineshafts, Trees, SprinkleFoliage, Ice, Snow, Lilypads, BottomLava, DeadBushes, PreSimulator"); + break; + } + case dimNether: + { + a_IniFile.GetValueSet("Generator", "BiomeGen", "Constant"); + a_IniFile.GetValueSet("Generator", "ConstantBiome", "Nether"); + a_IniFile.GetValueSet("Generator", "HeightGen", "Flat"); + a_IniFile.GetValueSet("Generator", "FlatHeight", "128"); + a_IniFile.GetValueSet("Generator", "CompositionGen", "Nether"); + a_IniFile.GetValueSet("Generator", "Finishers", "WormNestCaves, BottomLava, LavaSprings, NetherClumpFoliage, NetherForts, PreSimulator"); + a_IniFile.GetValueSet("Generator", "BottomLavaHeight", "30"); + break; + } + } +} + + + + + +void cWorld::InitialiseAndLoadMobSpawningValues(cIniFile & a_IniFile) +{ + AString DefaultMonsters; + switch (m_Dimension) + { + case dimOverworld: DefaultMonsters = "bat, cavespider, chicken, cow, creeper, enderman, horse, mooshroom, ocelot, pig, sheep, silverfish, skeleton, slime, spider, squid, wolf, zombie"; break; + case dimNether: DefaultMonsters = "blaze, ghast, magmacube, skeleton, zombie, zombiepigman"; break; + case dimEnd: DefaultMonsters = "enderman"; break; + } + + m_bAnimals = a_IniFile.GetValueSetB("Monsters", "AnimalsOn", true); + AString AllMonsters = a_IniFile.GetValueSet("Monsters", "Types", DefaultMonsters); + + if (!m_bAnimals) + { + return; + } + + AStringVector SplitList = StringSplitAndTrim(AllMonsters, ","); + for (AStringVector::const_iterator itr = SplitList.begin(), end = SplitList.end(); itr != end; ++itr) + { + cMonster::eType ToAdd = cMonster::StringToMobType(*itr); + if (ToAdd != cMonster::mtInvalidType) + { + m_AllowedMobs.insert(ToAdd); + LOGD("Allowed mob: %s", itr->c_str()); + } + else + { + LOG("World \"%s\": Unknown mob type: %s", m_WorldName.c_str(), itr->c_str()); + } + } +} + + + + + void cWorld::Stop(void) { // Delete the clients that have been in this world: diff --git a/src/World.h b/src/World.h index 09cbc6b48..879da3cb9 100644 --- a/src/World.h +++ b/src/World.h @@ -1030,6 +1030,13 @@ private: /** Adds the players queued in the m_PlayersToAdd queue into the m_Players list. Assumes it is called from the Tick thread. */ void AddQueuedPlayers(void); + + /** Sets generator values to dimension specific defaults, if those values do not exist */ + void InitialiseGeneratorDefaults(cIniFile & a_IniFile); + + /** Sets mob spawning values if nonexistant to their dimension specific defaults */ + void InitialiseAndLoadMobSpawningValues(cIniFile & a_IniFile); + }; // tolua_export -- cgit v1.2.3 From 0a15e1f420402e797397ea447b1df96f6ea2106f Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 22 Jul 2014 10:33:16 +0100 Subject: Suggestion and failed merge fix --- src/Blocks/BlockPortal.h | 2 +- src/World.cpp | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Blocks/BlockPortal.h b/src/Blocks/BlockPortal.h index 6f41f96df..fc74e89d0 100644 --- a/src/Blocks/BlockPortal.h +++ b/src/Blocks/BlockPortal.h @@ -55,7 +55,7 @@ public: virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override { - if ((a_RelY == 0) || (a_RelY == cChunkDef::Height)) // Y can't be < 0 or > Height; (Fast)SetBlock won't allow it + if ((a_RelY - 1 < 0) || (a_RelY + 1 > cChunkDef::Height)) { return false; // In case someone places a portal with meta 1 or 2 at boundaries, and server tries to get invalid coords at Y - 1 or Y + 1 } diff --git a/src/World.cpp b/src/World.cpp index 9dc28afea..2736e77d3 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -579,6 +579,11 @@ void cWorld::Start(void) int Weather = IniFile.GetValueSetI("General", "Weather", (int)m_Weather); m_TimeOfDay = IniFile.GetValueSetI("General", "TimeInTicks", m_TimeOfDay); + if (GetDimension() == dimOverworld) + { + m_NetherWorldName = IniFile.GetValueSet("LinkedWorlds", "NetherWorldName", DEFAULT_NETHER_NAME); + m_EndWorldName = IniFile.GetValueSet("LinkedWorlds", "EndWorldName", DEFAULT_END_NAME); + } else { m_OverworldName = IniFile.GetValueSet("LinkedWorlds", "OverworldName", GetLinkedOverworldName()); -- cgit v1.2.3 From a28b0dc1201dca7c34d9a6c33232157e45a6d4f8 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 22 Jul 2014 17:26:48 +0100 Subject: Speed improvements, crash fixes, & self-suggestions --- src/Chunk.cpp | 19 ++++++---------- src/Entities/Entity.cpp | 59 ++++++++++++++++++++++++------------------------- src/Entities/Entity.h | 6 +++-- src/Entities/Player.cpp | 6 +++-- src/Entities/Player.h | 1 - src/Root.cpp | 6 +++-- src/World.cpp | 17 +++++--------- src/World.h | 2 +- 8 files changed, 55 insertions(+), 61 deletions(-) diff --git a/src/Chunk.cpp b/src/Chunk.cpp index 9b9646b0c..0be61f753 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -583,19 +583,14 @@ void cChunk::Tick(float a_Dt) m_IsDirty = (*itr)->Tick(a_Dt, *this) | m_IsDirty; } - // Tick all entities in this chunk (except mobs): - for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr) - { - // Mobs are ticked inside cWorld::TickMobs() (as we don't have to tick them if they are far away from players) - // Don't tick things queued to be removed - if (!((*itr)->IsMob())) + for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end();) + { + if (!((*itr)->IsMob())) // Mobs are ticked inside cWorld::TickMobs() (as we don't have to tick them if they are far away from players) { + // Tick all entities in this chunk (except mobs): (*itr)->Tick(a_Dt, *this); } - } // for itr - m_Entitites[] - - for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end();) - { + if ((*itr)->IsDestroyed()) // Remove all entities that were scheduled for removal: { LOGD("Destroying entity #%i (%s)", (*itr)->GetUniqueID(), (*itr)->GetClass()); @@ -604,7 +599,7 @@ void cChunk::Tick(float a_Dt) itr = m_Entities.erase(itr); delete ToDelete; } - else if ((*itr)->IsWorldTravellingFrom(m_World)) // Remove all entities that are travelling to another world + else if ((*itr)->IsWorldTravellingFrom(m_World)) // Remove all entities that are travelling to another world: { MarkDirty(); (*itr)->SetWorldTravellingFrom(NULL); @@ -1899,7 +1894,7 @@ void cChunk::AddEntity(cEntity * a_Entity) MarkDirty(); } - ASSERT(std::find(m_Entities.begin(), m_Entities.end(), a_Entity) == m_Entities.end()); + ASSERT(std::find(m_Entities.begin(), m_Entities.end(), a_Entity) == m_Entities.end()); // Not there already m_Entities.push_back(a_Entity); } diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index a7340a29c..68bfabb30 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -614,11 +614,13 @@ void cEntity::Tick(float a_Dt, cChunk & a_Chunk) // Handle drowning HandleAir(); + } + + if (!DetectPortal()) // Our chunk is invalid if we have moved to another world + { + // None of the above functions changed position, we remain in the chunk of NextChunk + HandlePhysics(a_Dt, *NextChunk); } - DetectPortal(); - - // None of the above functions change position, we remain in the chunk of NextChunk - HandlePhysics(a_Dt, *NextChunk); } } @@ -1026,18 +1028,18 @@ void cEntity::DetectCacti(void) -void cEntity::DetectPortal() +bool cEntity::DetectPortal() { if (GetWorld()->GetDimension() == dimOverworld) { if (GetWorld()->GetNetherWorldName().empty() && GetWorld()->GetEndWorldName().empty()) { - return; + return false; } } else if (GetWorld()->GetLinkedOverworldName().empty()) { - return; + return false; } int X = POSX_TOINT, Y = POSY_TOINT, Z = POSZ_TOINT; @@ -1049,13 +1051,13 @@ void cEntity::DetectPortal() { if (m_PortalCooldownData.m_ShouldPreventTeleportation) { - return; + return false; } if (IsPlayer() && !((cPlayer *)this)->IsGameModeCreative() && m_PortalCooldownData.m_TicksDelayed != 80) { m_PortalCooldownData.m_TicksDelayed++; - return; + return false; } m_PortalCooldownData.m_TicksDelayed = 0; @@ -1065,7 +1067,7 @@ void cEntity::DetectPortal() { if (GetWorld()->GetLinkedOverworldName().empty()) { - return; + return false; } m_PortalCooldownData.m_ShouldPreventTeleportation = true; // Stop portals from working on respawn @@ -1074,15 +1076,14 @@ void cEntity::DetectPortal() { ((cPlayer *)this)->GetClientHandle()->SendRespawn(dimOverworld); } - MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedOverworldName()), false); - - return; + + return MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedOverworldName()), false); } case dimOverworld: { if (GetWorld()->GetNetherWorldName().empty()) { - return; + return false; } m_PortalCooldownData.m_ShouldPreventTeleportation = true; // Stop portals from working on respawn @@ -1092,18 +1093,17 @@ void cEntity::DetectPortal() ((cPlayer *)this)->AwardAchievement(achEnterPortal); ((cPlayer *)this)->GetClientHandle()->SendRespawn(dimNether); } - MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetNetherWorldName(), dimNether, GetWorld()->GetName()), false); - - return; + + return MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetNetherWorldName(), dimNether, GetWorld()->GetName()), false); } - default: return; + default: return false; } } case E_BLOCK_END_PORTAL: { if (m_PortalCooldownData.m_ShouldPreventTeleportation) { - return; + return false; } switch (GetWorld()->GetDimension()) @@ -1112,7 +1112,7 @@ void cEntity::DetectPortal() { if (GetWorld()->GetLinkedOverworldName().empty()) { - return; + return false; } m_PortalCooldownData.m_ShouldPreventTeleportation = true; // Stop portals from working on respawn @@ -1122,16 +1122,15 @@ void cEntity::DetectPortal() cPlayer * Player = (cPlayer *)this; Player->TeleportToCoords(Player->GetLastBedPos().x, Player->GetLastBedPos().y, Player->GetLastBedPos().z); Player->GetClientHandle()->SendRespawn(dimOverworld); - } - MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedOverworldName()), false); + } - return; + return MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedOverworldName()), false); } case dimOverworld: { if (GetWorld()->GetEndWorldName().empty()) { - return; + return false; } m_PortalCooldownData.m_ShouldPreventTeleportation = true; // Stop portals from working on respawn @@ -1140,12 +1139,11 @@ void cEntity::DetectPortal() { ((cPlayer *)this)->AwardAchievement(achEnterTheEnd); ((cPlayer *)this)->GetClientHandle()->SendRespawn(dimEnd); - } - MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetEndWorldName(), dimEnd, GetWorld()->GetName()), false); + } - return; + return MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetEndWorldName(), dimEnd, GetWorld()->GetName()), false); } - default: return; + default: return false; } } default: break; @@ -1155,6 +1153,7 @@ void cEntity::DetectPortal() // Allow portals to work again m_PortalCooldownData.m_ShouldPreventTeleportation = false; m_PortalCooldownData.m_ShouldPreventTeleportation = 0; + return false; } @@ -1164,7 +1163,7 @@ void cEntity::DetectPortal() bool cEntity::MoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn) { UNUSED(a_ShouldSendRespawn); - ASSERT(a_World == NULL); + ASSERT(a_World != NULL); if (GetWorld() == a_World) { @@ -1173,7 +1172,7 @@ bool cEntity::MoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn) } // Remove all links to the old world - SetWorldTravellingFrom(GetWorld()); // cChunk handles entity removal + SetWorldTravellingFrom(GetWorld()); // cChunk handles entity removal GetWorld()->BroadcastDestroyEntity(*this); // Queue add to new world diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h index 1679b00d6..62a4097f3 100644 --- a/src/Entities/Entity.h +++ b/src/Entities/Entity.h @@ -337,8 +337,10 @@ public: /** Detects the time for application of cacti damage */ virtual void DetectCacti(void); - /** Detects whether we are in a portal block and begins teleportation procedures if so */ - virtual void DetectPortal(void); + /** Detects whether we are in a portal block and begins teleportation procedures if so + Returns true if MoveToWorld() was called, false if not + */ + virtual bool DetectPortal(void); /// Handles when the entity is in the void virtual void TickInVoid(cChunk & a_Chunk); diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index e54e10a08..087ac448f 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -95,7 +95,7 @@ cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName) : SetPosX(World->GetSpawnX()); SetPosY(World->GetSpawnY()); SetPosZ(World->GetSpawnZ()); - SetBedPos(Vector3i(World->GetSpawnX(), World->GetSpawnY(), World->GetSpawnZ())); + SetBedPos(Vector3i((int)World->GetSpawnX(), (int)World->GetSpawnY(), (int)World->GetSpawnZ())); LOGD("Player \"%s\" is connecting for the first time, spawning at default world spawn {%.2f, %.2f, %.2f}", a_PlayerName.c_str(), GetPosX(), GetPosY(), GetPosZ() @@ -1611,6 +1611,8 @@ void cPlayer::TossItems(const cItems & a_Items) bool cPlayer::MoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn) { + ASSERT(a_World != NULL); + if (GetWorld() == a_World) { // Don't move to same world @@ -1624,7 +1626,7 @@ bool cPlayer::MoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn) } // Remove player from the old world - SetWorldTravellingFrom(GetWorld()); // cChunk handles entity removal + SetWorldTravellingFrom(GetWorld()); // cChunk handles entity removal GetWorld()->RemovePlayer(this); // Queue adding player to the new world, including all the necessary adjustments to the object diff --git a/src/Entities/Player.h b/src/Entities/Player.h index 400377381..d1b3a0339 100644 --- a/src/Entities/Player.h +++ b/src/Entities/Player.h @@ -424,7 +424,6 @@ public: /** Returns wheter the player can fly or not. */ virtual bool CanFly(void) const { return m_CanFly; } - // tolua_end // cEntity overrides: diff --git a/src/Root.cpp b/src/Root.cpp index b793cb154..b65e9b067 100644 --- a/src/Root.cpp +++ b/src/Root.cpp @@ -314,10 +314,12 @@ void cRoot::LoadWorlds(cIniFile & IniFile) cWorld * cRoot::CreateAndInitializeWorld(const AString & a_WorldName, eDimension a_Dimension, const AString & a_OverworldName) { - if (m_WorldsByName[a_WorldName] != NULL) + cWorld * World = m_WorldsByName[a_WorldName]; + if (World != NULL) { - return NULL; + return World; } + cWorld * NewWorld = new cWorld(a_WorldName.c_str(), a_Dimension, a_OverworldName); m_WorldsByName[a_WorldName] = NewWorld; NewWorld->Start(); diff --git a/src/World.cpp b/src/World.cpp index 2736e77d3..9cbaf48fb 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -255,8 +255,7 @@ cWorld::cWorld(const AString & a_WorldName, eDimension a_Dimension, const AStrin m_Scoreboard(this), m_MapManager(this), m_GeneratorCallbacks(*this), - m_TickThread(*this) - + m_TickThread(*this) { LOGD("cWorld::cWorld(\"%s\")", a_WorldName.c_str()); @@ -526,7 +525,7 @@ void cWorld::Start(void) // TODO: More descriptions for each key IniFile.AddHeaderComment(" This is the per-world configuration file, managing settings such as generators, simulators, and spawn points"); - IniFile.AddKeyComment("LinkedWorlds", "This section governs portal world linkage; leave a value blank to disabled that associated method of teleportation"); + IniFile.AddKeyComment(" LinkedWorlds", "This section governs portal world linkage; leave a value blank to disabled that associated method of teleportation"); } // The presence of a configuration value overrides everything @@ -784,7 +783,7 @@ void cWorld::Stop(void) // Write settings to file; these are all plugin changeable values - keep updated! cIniFile IniFile; IniFile.ReadFile(m_IniFileName); - if ((GetDimension() != dimNether) && (GetDimension() != dimEnd)) + if (GetDimension() == dimOverworld) { IniFile.SetValue("LinkedWorlds", "NetherWorldName", m_NetherWorldName); IniFile.SetValue("LinkedWorlds", "EndWorldName", m_EndWorldName); @@ -1040,11 +1039,7 @@ void cWorld::TickClients(float a_Dt) // Add clients scheduled for adding: for (cClientHandleList::iterator itr = m_ClientsToAdd.begin(), end = m_ClientsToAdd.end(); itr != end; ++itr) { - if (std::find(m_Clients.begin(), m_Clients.end(), *itr) != m_Clients.end()) - { - ASSERT(!"Adding a client that is already in the clientlist"); - continue; - } + ASSERT(std::find(m_Clients.begin(), m_Clients.end(), *itr) == m_Clients.end()); m_Clients.push_back(*itr); } // for itr - m_ClientsToRemove[] m_ClientsToAdd.clear(); @@ -3253,9 +3248,9 @@ void cWorld::AddQueuedPlayers(void) cCSLock Lock(m_CSPlayers); for (cPlayerList::iterator itr = PlayersToAdd.begin(), end = PlayersToAdd.end(); itr != end; ++itr) { - ASSERT(std::find(m_Players.begin(), m_Players.end(), *itr) == m_Players.end()); // Is it already in the list? HOW? - + ASSERT(std::find(m_Players.begin(), m_Players.end(), *itr) == m_Players.end()); // Is it already in the list? HOW? LOGD("Adding player %s to world \"%s\".", (*itr)->GetName().c_str(), m_WorldName.c_str()); + m_Players.push_back(*itr); (*itr)->SetWorld(this); diff --git a/src/World.h b/src/World.h index 771cf51bf..f6c1437f1 100644 --- a/src/World.h +++ b/src/World.h @@ -669,7 +669,7 @@ public: void InitializeSpawn(void); /** Starts threads that belong to this world */ - void Start(); + void Start(void); /** Stops threads that belong to this world (part of deinit) */ void Stop(void); -- cgit v1.2.3 From 396739cc0faf01a099acbe669c5a9def98d3aaae Mon Sep 17 00:00:00 2001 From: Howaner Date: Wed, 23 Jul 2014 16:32:09 +0200 Subject: Fix item durability. Fixes #1181 --- src/BlockInfo.cpp | 1 + src/Blocks/BlockLeaves.h | 16 ---------------- src/Blocks/BlockTallGrass.h | 3 ++- src/Blocks/BlockVine.h | 7 +++++++ src/Entities/Entity.cpp | 13 ++++++++----- src/Entities/Player.cpp | 4 ++-- src/Entities/Player.h | 2 +- src/FastRandom.h | 3 +++ src/Inventory.cpp | 16 ++++++++++------ src/Item.cpp | 46 ++++++++++++++++++++++----------------------- src/Items/ItemHandler.cpp | 32 +++++++++++++++++++++++++++++-- src/Items/ItemHandler.h | 17 +++++++++++++++-- src/Items/ItemHoe.h | 10 +++++++--- src/Items/ItemShears.h | 25 +++++++++++++++++++++++- src/Items/ItemSword.h | 17 +++++++++++++++-- src/Mobs/Sheep.cpp | 6 +----- 16 files changed, 149 insertions(+), 69 deletions(-) diff --git a/src/BlockInfo.cpp b/src/BlockInfo.cpp index 97e89359f..c4510fe6d 100644 --- a/src/BlockInfo.cpp +++ b/src/BlockInfo.cpp @@ -454,6 +454,7 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info) a_Info[E_BLOCK_DOUBLE_STONE_SLAB ].m_RequiresSpecialTool = true; a_Info[E_BLOCK_EMERALD_ORE ].m_RequiresSpecialTool = true; a_Info[E_BLOCK_END_STONE ].m_RequiresSpecialTool = true; + a_Info[E_BLOCK_VINES ].m_RequiresSpecialTool = true; a_Info[E_BLOCK_GOLD_BLOCK ].m_RequiresSpecialTool = true; a_Info[E_BLOCK_GOLD_ORE ].m_RequiresSpecialTool = true; a_Info[E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE].m_RequiresSpecialTool = true; diff --git a/src/Blocks/BlockLeaves.h b/src/Blocks/BlockLeaves.h index 797824506..18f336225 100644 --- a/src/Blocks/BlockLeaves.h +++ b/src/Blocks/BlockLeaves.h @@ -55,22 +55,6 @@ public: } } } - - - void OnDestroyed(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ) override - { - cBlockHandler::OnDestroyed(a_ChunkInterface, a_WorldInterface, a_BlockX, a_BlockY, a_BlockZ); - - // 0.5% chance of dropping an apple, if the leaves' type is Apple Leaves: - NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ); - cFastRandom rand; - if (((Meta & 3) == E_META_LEAVES_APPLE) && (rand.NextInt(201) == 100)) - { - cItems Drops; - Drops.push_back(cItem(E_ITEM_RED_APPLE, 1, 0)); - a_WorldInterface.SpawnItemPickups(Drops, a_BlockX, a_BlockY, a_BlockZ); - } - } virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ) override diff --git a/src/Blocks/BlockTallGrass.h b/src/Blocks/BlockTallGrass.h index ba1f2e0f6..9c008f793 100644 --- a/src/Blocks/BlockTallGrass.h +++ b/src/Blocks/BlockTallGrass.h @@ -43,8 +43,9 @@ public: cItems Pickups; Pickups.Add(E_BLOCK_TALL_GRASS, 1, Meta); a_WorldInterface.SpawnItemPickups(Pickups, a_BlockX, a_BlockY, a_BlockZ); + + a_Player->UseEquippedItem(); } - a_Player->UseEquippedItem(); } diff --git a/src/Blocks/BlockVine.h b/src/Blocks/BlockVine.h index 61092af3e..1e1f6d8d2 100644 --- a/src/Blocks/BlockVine.h +++ b/src/Blocks/BlockVine.h @@ -44,6 +44,13 @@ public: } + virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override + { + // Reset meta to 0 + a_Pickups.push_back(cItem(E_BLOCK_VINES, 1, 0)); + } + + static NIBBLETYPE DirectionToMetaData(char a_BlockFace) { switch (a_BlockFace) diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index db0fd0fd6..6c3d7b40c 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -12,6 +12,7 @@ #include "../Bindings/PluginManager.h" #include "../Tracer.h" #include "Player.h" +#include "Items/ItemHandler.h" @@ -289,11 +290,6 @@ void cEntity::SetPitchFromSpeed(void) bool cEntity::DoTakeDamage(TakeDamageInfo & a_TDI) { - if (cRoot::Get()->GetPluginManager()->CallHookTakeDamage(*this, a_TDI)) - { - return false; - } - if (m_Health <= 0) { // Can't take damage if already dead @@ -306,10 +302,17 @@ bool cEntity::DoTakeDamage(TakeDamageInfo & a_TDI) return false; } + if (cRoot::Get()->GetPluginManager()->CallHookTakeDamage(*this, a_TDI)) + { + return false; + } + if ((a_TDI.Attacker != NULL) && (a_TDI.Attacker->IsPlayer())) { cPlayer * Player = (cPlayer *)a_TDI.Attacker; + Player->GetEquippedItem().GetHandler()->OnEntityAttack(Player, this); + // IsOnGround() only is false if the player is moving downwards // TODO: Better damage increase, and check for enchantments (and use magic critical instead of plain) if (!Player->IsOnGround()) diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index fcc8eb9a0..afe5965aa 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -1929,14 +1929,14 @@ cPlayer::StringList cPlayer::GetResolvedPermissions() -void cPlayer::UseEquippedItem(void) +void cPlayer::UseEquippedItem(int a_Amount) { if (IsGameModeCreative()) // No damage in creative { return; } - if (GetInventory().DamageEquippedItem()) + if (GetInventory().DamageEquippedItem(a_Amount)) { m_World->BroadcastSoundEffect("random.break", GetPosX(), GetPosY(), GetPosZ(), 0.5f, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64)); } diff --git a/src/Entities/Player.h b/src/Entities/Player.h index 26db2050b..e89d9f48f 100644 --- a/src/Entities/Player.h +++ b/src/Entities/Player.h @@ -349,7 +349,7 @@ public: const AString & GetLoadedWorldName() { return m_LoadedWorldName; } - void UseEquippedItem(void); + void UseEquippedItem(int a_Amount = 1); void SendHealth(void); diff --git a/src/FastRandom.h b/src/FastRandom.h index 567198a31..2061a3958 100644 --- a/src/FastRandom.h +++ b/src/FastRandom.h @@ -44,6 +44,9 @@ public: /// Returns a random float in the range [0 .. a_Range]; a_Range must be less than 1M; a_Salt is additional source of randomness float NextFloat(float a_Range, int a_Salt); + /** Returns a random float between 0 and 1. */ + float NextFloat(void) { return NextFloat(1); }; + /** Returns a random int in the range [a_Begin .. a_End] */ int GenerateRandomInteger(int a_Begin, int a_End); diff --git a/src/Inventory.cpp b/src/Inventory.cpp index 0f9716d89..a34d51993 100644 --- a/src/Inventory.cpp +++ b/src/Inventory.cpp @@ -222,12 +222,6 @@ void cInventory::SetSlot(int a_SlotNum, const cItem & a_Item) return; } Grid->SetSlot(GridSlotNum, a_Item); - - // Broadcast the Equipped Item, if the Slot is changed. - if ((Grid == &m_HotbarSlots) && (m_EquippedSlotNum == (a_SlotNum - invHotbarOffset))) - { - m_Owner.GetWorld()->BroadcastEntityEquipment(m_Owner, 0, a_Item, m_Owner.GetClientHandle()); - } } @@ -393,6 +387,10 @@ bool cInventory::DamageItem(int a_SlotNum, short a_Amount) LOGWARNING("%s: requesting an invalid slot index: %d out of %d", __FUNCTION__, a_SlotNum, invNumSlots - 1); return false; } + if (a_Amount <= 0) + { + return false; + } int GridSlotNum = 0; cItemGrid * Grid = GetGridForSlotNum(a_SlotNum, GridSlotNum); @@ -713,6 +711,12 @@ void cInventory::OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum) m_ArmorSlots.GetSlot(a_SlotNum), m_Owner.GetClientHandle() ); } + + // Broadcast the Equipped Item, if the Slot is changed. + if ((a_ItemGrid == &m_HotbarSlots) && (m_EquippedSlotNum == a_SlotNum)) + { + m_Owner.GetWorld()->BroadcastEntityEquipment(m_Owner, 0, GetEquippedItem(), m_Owner.GetClientHandle()); + } // Convert the grid-local a_SlotNum to our global SlotNum: int Base = 0; diff --git a/src/Item.cpp b/src/Item.cpp index b44472e38..2c5deaddf 100644 --- a/src/Item.cpp +++ b/src/Item.cpp @@ -41,33 +41,33 @@ short cItem::GetMaxDamage(void) const switch (m_ItemType) { case E_ITEM_BOW: return 384; - case E_ITEM_DIAMOND_AXE: return 1563; - case E_ITEM_DIAMOND_HOE: return 1563; - case E_ITEM_DIAMOND_PICKAXE: return 1563; - case E_ITEM_DIAMOND_SHOVEL: return 1563; - case E_ITEM_DIAMOND_SWORD: return 1563; - case E_ITEM_FLINT_AND_STEEL: return 65; + case E_ITEM_DIAMOND_AXE: return 1561; + case E_ITEM_DIAMOND_HOE: return 1561; + case E_ITEM_DIAMOND_PICKAXE: return 1561; + case E_ITEM_DIAMOND_SHOVEL: return 1561; + case E_ITEM_DIAMOND_SWORD: return 1561; + case E_ITEM_FLINT_AND_STEEL: return 64; case E_ITEM_GOLD_AXE: return 32; case E_ITEM_GOLD_HOE: return 32; case E_ITEM_GOLD_PICKAXE: return 32; case E_ITEM_GOLD_SHOVEL: return 32; case E_ITEM_GOLD_SWORD: return 32; - case E_ITEM_IRON_AXE: return 251; - case E_ITEM_IRON_HOE: return 251; - case E_ITEM_IRON_PICKAXE: return 251; - case E_ITEM_IRON_SHOVEL: return 251; - case E_ITEM_IRON_SWORD: return 251; - case E_ITEM_SHEARS: return 251; - case E_ITEM_STONE_AXE: return 132; - case E_ITEM_STONE_HOE: return 132; - case E_ITEM_STONE_PICKAXE: return 132; - case E_ITEM_STONE_SHOVEL: return 132; - case E_ITEM_STONE_SWORD: return 132; - case E_ITEM_WOODEN_AXE: return 60; - case E_ITEM_WOODEN_HOE: return 60; - case E_ITEM_WOODEN_PICKAXE: return 60; - case E_ITEM_WOODEN_SHOVEL: return 60; - case E_ITEM_WOODEN_SWORD: return 60; + case E_ITEM_IRON_AXE: return 250; + case E_ITEM_IRON_HOE: return 250; + case E_ITEM_IRON_PICKAXE: return 250; + case E_ITEM_IRON_SHOVEL: return 250; + case E_ITEM_IRON_SWORD: return 250; + case E_ITEM_SHEARS: return 250; + case E_ITEM_STONE_AXE: return 131; + case E_ITEM_STONE_HOE: return 131; + case E_ITEM_STONE_PICKAXE: return 131; + case E_ITEM_STONE_SHOVEL: return 131; + case E_ITEM_STONE_SWORD: return 131; + case E_ITEM_WOODEN_AXE: return 59; + case E_ITEM_WOODEN_HOE: return 59; + case E_ITEM_WOODEN_PICKAXE: return 59; + case E_ITEM_WOODEN_SHOVEL: return 59; + case E_ITEM_WOODEN_SWORD: return 59; } return 0; } @@ -86,7 +86,7 @@ bool cItem::DamageItem(short a_Amount) } m_ItemDamage += a_Amount; - return (m_ItemDamage >= MaxDamage); + return (m_ItemDamage > MaxDamage); } diff --git a/src/Items/ItemHandler.cpp b/src/Items/ItemHandler.cpp index bf1d4e4cb..f0a91214d 100644 --- a/src/Items/ItemHandler.cpp +++ b/src/Items/ItemHandler.cpp @@ -335,8 +335,21 @@ void cItemHandler::OnBlockDestroyed(cWorld * a_World, cPlayer * a_Player, const Handler->DropBlock(ChunkInterface, *a_World, PluginInterface, a_Player, a_BlockX, a_BlockY, a_BlockZ); } } - - a_Player->UseEquippedItem(); + + if (!cBlockInfo::IsOneHitDig(Block)) + { + a_Player->UseEquippedItem(GetDurabilityLostWithThatAction(dlaBreakBlock)); + } +} + + + + + +void cItemHandler::OnEntityAttack(cPlayer * a_Attacker, cEntity * a_AttackedEntity) +{ + UNUSED(a_AttackedEntity); + a_Attacker->UseEquippedItem(GetDurabilityLostWithThatAction(dlaAttackEntity)); } @@ -354,6 +367,20 @@ void cItemHandler::OnFoodEaten(cWorld * a_World, cPlayer * a_Player, cItem * a_I +short cItemHandler::GetDurabilityLostWithThatAction(eDurabilityLostAction a_Action) +{ + switch (a_Action) + { + case dlaAttackEntity: return 2; + case dlaBreakBlock: return 1; + } + return 0; +} + + + + + char cItemHandler::GetMaxStackSize(void) { if (m_ItemType < 256) @@ -505,6 +532,7 @@ bool cItemHandler::IsPlaceable(void) bool cItemHandler::CanRepairWithRawMaterial(short a_ItemType) { + UNUSED(a_ItemType); return false; } diff --git a/src/Items/ItemHandler.h b/src/Items/ItemHandler.h index c7362c5f4..28b1dd13b 100644 --- a/src/Items/ItemHandler.h +++ b/src/Items/ItemHandler.h @@ -19,6 +19,13 @@ class cPlayer; class cItemHandler { public: + + enum eDurabilityLostAction + { + dlaBreakBlock, + dlaAttackEntity, + }; + cItemHandler(int a_ItemType); /** Force virtual destructor */ @@ -48,11 +55,17 @@ public: virtual bool OnDiggingBlock(cWorld * a_World, cPlayer * a_Player, const cItem & a_HeldItem, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace); /** Called when the player destroys a block using this item. This also calls the drop function for the destroyed block */ - virtual void OnBlockDestroyed(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_X, int a_Y, int a_Z); + virtual void OnBlockDestroyed(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ); + + /** Called when a player attacks a other entity. */ + virtual void OnEntityAttack(cPlayer * a_Attacker, cEntity * a_AttackedEntity); /** Called after the player has eaten this item. */ virtual void OnFoodEaten(cWorld *a_World, cPlayer *a_Player, cItem *a_Item); - + + /** Get the durability lost which the item will get, when a specified action was performed. */ + virtual short GetDurabilityLostWithThatAction(eDurabilityLostAction a_Action); + /** Returns the maximum stack size for a given item */ virtual char GetMaxStackSize(void); diff --git a/src/Items/ItemHoe.h b/src/Items/ItemHoe.h index 29f7c83d5..6523b36d9 100644 --- a/src/Items/ItemHoe.h +++ b/src/Items/ItemHoe.h @@ -16,7 +16,6 @@ public: cItemHoeHandler(int a_ItemType) : cItemHandler(a_ItemType) { - } virtual bool OnItemUse(cWorld *a_World, cPlayer *a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir) override @@ -26,13 +25,18 @@ public: if ((Block == E_BLOCK_DIRT) || (Block == E_BLOCK_GRASS)) { a_World->FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_FARMLAND, 0); - a_Player->UseEquippedItem(); return true; - } + return false; } + + + virtual short GetDurabilityLostWithThatAction(eDurabilityLostAction a_Action) override + { + return 0; + } } ; diff --git a/src/Items/ItemShears.h b/src/Items/ItemShears.h index 39d2776fa..f1b6cafc3 100644 --- a/src/Items/ItemShears.h +++ b/src/Items/ItemShears.h @@ -12,6 +12,7 @@ class cItemShearsHandler : public cItemHandler { + typedef cItemHandler super; public: cItemShearsHandler(int a_ItemType) : cItemHandler(a_ItemType) @@ -30,8 +31,12 @@ public: BLOCKTYPE Block = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ); if ((Block == E_BLOCK_LEAVES) || (Block == E_BLOCK_NEW_LEAVES)) { + NIBBLETYPE Meta = a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ); + cBlockHandler * Handler = cBlockInfo::GetHandler(Block); + cItems Drops; - Drops.push_back(cItem(Block, 1, a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) & 0x03)); + Handler->ConvertToPickups(Drops, Meta); + Drops.push_back(cItem(Block, 1, Meta & 3)); a_World->SpawnItemPickups(Drops, a_BlockX, a_BlockY, a_BlockZ); a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0); @@ -56,6 +61,24 @@ public: } // switch (a_BlockType) return false; } + + + virtual short GetDurabilityLostWithThatAction(eDurabilityLostAction a_Action) override + { + return 0; + } + + + virtual void OnBlockDestroyed(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ) override + { + super::OnBlockDestroyed(a_World, a_Player, a_Item, a_BlockX, a_BlockY, a_BlockZ); + + BLOCKTYPE Block = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ); + if ((Block == E_BLOCK_TRIPWIRE) || (Block == E_BLOCK_VINES)) + { + a_Player->UseEquippedItem(); + } + } } ; diff --git a/src/Items/ItemSword.h b/src/Items/ItemSword.h index 44feb2d83..8fd70bd7b 100644 --- a/src/Items/ItemSword.h +++ b/src/Items/ItemSword.h @@ -12,18 +12,20 @@ class cItemSwordHandler : public cItemHandler { + typedef cItemHandler super; public: cItemSwordHandler(int a_ItemType) : cItemHandler(a_ItemType) { - } - + + virtual bool CanHarvestBlock(BLOCKTYPE a_BlockType) override { return (a_BlockType == E_BLOCK_COBWEB); } + virtual bool CanRepairWithRawMaterial(short a_ItemType) override { switch (m_ItemType) @@ -36,6 +38,17 @@ public: } return false; } + + + virtual short GetDurabilityLostWithThatAction(eDurabilityLostAction a_Action) override + { + switch (a_Action) + { + case dlaAttackEntity: return 1; + case dlaBreakBlock: return 2; + } + return 0; + } } ; diff --git a/src/Mobs/Sheep.cpp b/src/Mobs/Sheep.cpp index 7335848b7..9fb47201d 100644 --- a/src/Mobs/Sheep.cpp +++ b/src/Mobs/Sheep.cpp @@ -52,11 +52,7 @@ void cSheep::OnRightClicked(cPlayer & a_Player) { m_IsSheared = true; m_World->BroadcastEntityMetadata(*this); - - if (!a_Player.IsGameModeCreative()) - { - a_Player.UseEquippedItem(); - } + a_Player.UseEquippedItem(); cItems Drops; int NumDrops = m_World->GetTickRandomNumber(2) + 1; -- cgit v1.2.3 From 1156914dd60b4949116e57ec1480f81c39b6f292 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Wed, 23 Jul 2014 21:12:59 +0100 Subject: Suggestions --- src/ClientHandle.cpp | 4 ++-- src/Entities/Entity.cpp | 23 ++++++++++++++--------- src/Entities/Entity.h | 8 +++++--- src/Entities/Player.cpp | 2 +- src/Entities/Player.h | 6 +++--- src/World.cpp | 9 +++------ 6 files changed, 28 insertions(+), 24 deletions(-) diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index af53d3623..aaed483e2 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -120,8 +120,8 @@ cClientHandle::~cClientHandle() } if (World != NULL) { - m_Player->SetWorldTravellingFrom(NULL); // Make sure that the player entity is actually removed - World->RemovePlayer(m_Player); // Must be called before cPlayer::Destroy() as otherwise cChunk tries to delete the player, and then we do it again + m_Player->SetWorldTravellingFrom(NULL); // Make sure that the player entity is actually removed + World->RemovePlayer(m_Player); // Must be called before cPlayer::Destroy() as otherwise cChunk tries to delete the player, and then we do it again m_Player->Destroy(); } delete m_Player; diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index 68bfabb30..45c347aeb 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -1034,11 +1034,13 @@ bool cEntity::DetectPortal() { if (GetWorld()->GetNetherWorldName().empty() && GetWorld()->GetEndWorldName().empty()) { + // Teleportation to either dimension not enabled, don't bother proceeding return false; } } else if (GetWorld()->GetLinkedOverworldName().empty()) { + // Overworld teleportation disabled, abort return false; } @@ -1051,11 +1053,13 @@ bool cEntity::DetectPortal() { if (m_PortalCooldownData.m_ShouldPreventTeleportation) { + // Just exited a portal, don't teleport again return false; } if (IsPlayer() && !((cPlayer *)this)->IsGameModeCreative() && m_PortalCooldownData.m_TicksDelayed != 80) { + // Delay teleportation for four seconds if the entity is a non-creative player m_PortalCooldownData.m_TicksDelayed++; return false; } @@ -1070,11 +1074,11 @@ bool cEntity::DetectPortal() return false; } - m_PortalCooldownData.m_ShouldPreventTeleportation = true; // Stop portals from working on respawn + m_PortalCooldownData.m_ShouldPreventTeleportation = true; // Stop portals from working on respawn if (IsPlayer()) { - ((cPlayer *)this)->GetClientHandle()->SendRespawn(dimOverworld); + ((cPlayer *)this)->GetClientHandle()->SendRespawn(dimOverworld); // Send a respawn packet before world is loaded/generated so the client isn't left in limbo } return MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedOverworldName()), false); @@ -1086,7 +1090,7 @@ bool cEntity::DetectPortal() return false; } - m_PortalCooldownData.m_ShouldPreventTeleportation = true; // Stop portals from working on respawn + m_PortalCooldownData.m_ShouldPreventTeleportation = true; if (IsPlayer()) { @@ -1115,7 +1119,7 @@ bool cEntity::DetectPortal() return false; } - m_PortalCooldownData.m_ShouldPreventTeleportation = true; // Stop portals from working on respawn + m_PortalCooldownData.m_ShouldPreventTeleportation = true; if (IsPlayer()) { @@ -1133,7 +1137,7 @@ bool cEntity::DetectPortal() return false; } - m_PortalCooldownData.m_ShouldPreventTeleportation = true; // Stop portals from working on respawn + m_PortalCooldownData.m_ShouldPreventTeleportation = true; if (IsPlayer()) { @@ -1152,7 +1156,7 @@ bool cEntity::DetectPortal() // Allow portals to work again m_PortalCooldownData.m_ShouldPreventTeleportation = false; - m_PortalCooldownData.m_ShouldPreventTeleportation = 0; + m_PortalCooldownData.m_TicksDelayed = 0; return false; } @@ -1160,7 +1164,7 @@ bool cEntity::DetectPortal() -bool cEntity::MoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn) +bool cEntity::DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn) { UNUSED(a_ShouldSendRespawn); ASSERT(a_World != NULL); @@ -1172,11 +1176,12 @@ bool cEntity::MoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn) } // Remove all links to the old world - SetWorldTravellingFrom(GetWorld()); // cChunk handles entity removal + SetWorldTravellingFrom(GetWorld()); // cChunk::Tick() handles entity removal GetWorld()->BroadcastDestroyEntity(*this); // Queue add to new world a_World->AddEntity(this); + SetWorld(a_World); return true; } @@ -1194,7 +1199,7 @@ bool cEntity::MoveToWorld(const AString & a_WorldName, bool a_ShouldSendRespawn) return false; } - return MoveToWorld(World, a_ShouldSendRespawn); + return DoMoveToWorld(World, a_ShouldSendRespawn); } diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h index 62a4097f3..4b096b475 100644 --- a/src/Entities/Entity.h +++ b/src/Entities/Entity.h @@ -385,15 +385,17 @@ public: virtual void TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ); /** Moves entity to specified world, taking a world pointer */ - virtual bool MoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn = true); + bool MoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn = true) { return DoMoveToWorld(a_World, a_ShouldSendRespawn); } /** Moves entity to specified world, taking a world name */ bool MoveToWorld(const AString & a_WorldName, bool a_ShouldSendRespawn = true); // tolua_end + virtual bool DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn); + /** Returns if the entity is travelling away from a specified world */ - bool IsWorldTravellingFrom(cWorld * a_World) const { return m_WorldTravellingFrom == a_World; } + bool IsWorldTravellingFrom(cWorld * a_World) const { return (m_WorldTravellingFrom == a_World); } /** Sets the world the entity will be leaving */ void SetWorldTravellingFrom(cWorld * a_World) { m_WorldTravellingFrom = a_World; } @@ -500,7 +502,7 @@ protected: bool m_IsInitialized; /** World entity is travelling from - Set by MoveToWorld and back to NULL when the entity is removed by the old chunk + Set to a valid world pointer by MoveToWorld; reset to NULL when the entity is removed from the old world Can't be a simple boolean as context switches between worlds may leave the new chunk processing (and therefore immediately removing) the entity before the old chunk could remove it */ cWorld * m_WorldTravellingFrom; diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 087ac448f..406da8baa 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -1609,7 +1609,7 @@ void cPlayer::TossItems(const cItems & a_Items) -bool cPlayer::MoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn) +bool cPlayer::DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn) { ASSERT(a_World != NULL); diff --git a/src/Entities/Player.h b/src/Entities/Player.h index d1b3a0339..c28802eec 100644 --- a/src/Entities/Player.h +++ b/src/Entities/Player.h @@ -333,7 +333,7 @@ public: /** Moves the player to the specified world. Returns true if successful, false on failure (world not found). */ - virtual bool MoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn = true) override; // tolua_export + virtual bool DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn) override; /** Saves all player data, such as inventory, to JSON */ bool SaveToDisk(void); @@ -341,13 +341,13 @@ public: typedef cWorld * cWorldPtr; /** Loads the player data from the disk file - Takes a (NULL) cWorld pointer which it will assign a value to based on either the loaded world or default world by calling LoadFromFile() + Sets a_World to the world where the player will spawn, based on the stored world name or the default world by calling LoadFromFile() Returns true on success, false on failure */ bool LoadFromDisk(cWorldPtr & a_World); /** Loads the player data from the specified file - Takes a (NULL) cWorld pointer which it will assign a value to based on either the loaded world or default world + Sets a_World to the world where the player will spawn, based on the stored world name or the default world Returns true on success, false on failure */ bool LoadFromFile(const AString & a_FileName, cWorldPtr & a_World); diff --git a/src/World.cpp b/src/World.cpp index 9cbaf48fb..bcb2fa88d 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -66,9 +66,6 @@ const int TIME_NIGHT_END = 22812; const int TIME_SUNRISE = 23999; const int TIME_SPAWN_DIVISOR = 148; -#define DEFAULT_NETHER_NAME GetName() + "_nether" -#define DEFAULT_END_NAME GetName() + "_end" - @@ -255,7 +252,7 @@ cWorld::cWorld(const AString & a_WorldName, eDimension a_Dimension, const AStrin m_Scoreboard(this), m_MapManager(this), m_GeneratorCallbacks(*this), - m_TickThread(*this) + m_TickThread(*this) { LOGD("cWorld::cWorld(\"%s\")", a_WorldName.c_str()); @@ -580,8 +577,8 @@ void cWorld::Start(void) if (GetDimension() == dimOverworld) { - m_NetherWorldName = IniFile.GetValueSet("LinkedWorlds", "NetherWorldName", DEFAULT_NETHER_NAME); - m_EndWorldName = IniFile.GetValueSet("LinkedWorlds", "EndWorldName", DEFAULT_END_NAME); + m_NetherWorldName = IniFile.GetValueSet("LinkedWorlds", "NetherWorldName", GetName() + "_nether"); + m_EndWorldName = IniFile.GetValueSet("LinkedWorlds", "EndWorldName", GetName() + "_end"); } else { -- cgit v1.2.3 From 4de8f5ca2926068eb855ba19c35de2a63ddebf28 Mon Sep 17 00:00:00 2001 From: Howaner Date: Sat, 26 Jul 2014 13:26:14 +0200 Subject: Rename function. --- src/Items/ItemHandler.cpp | 6 +++--- src/Items/ItemHandler.h | 2 +- src/Items/ItemShears.h | 2 +- src/Items/ItemSword.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Items/ItemHandler.cpp b/src/Items/ItemHandler.cpp index e256fa232..ec86648b3 100644 --- a/src/Items/ItemHandler.cpp +++ b/src/Items/ItemHandler.cpp @@ -335,7 +335,7 @@ void cItemHandler::OnBlockDestroyed(cWorld * a_World, cPlayer * a_Player, const if (!cBlockInfo::IsOneHitDig(Block)) { - a_Player->UseEquippedItem(GetDurabilityLostWithThatAction(dlaBreakBlock)); + a_Player->UseEquippedItem(GetDurabilityLossByAction(dlaBreakBlock)); } } @@ -346,7 +346,7 @@ void cItemHandler::OnBlockDestroyed(cWorld * a_World, cPlayer * a_Player, const void cItemHandler::OnEntityAttack(cPlayer * a_Attacker, cEntity * a_AttackedEntity) { UNUSED(a_AttackedEntity); - a_Attacker->UseEquippedItem(GetDurabilityLostWithThatAction(dlaAttackEntity)); + a_Attacker->UseEquippedItem(GetDurabilityLossByAction(dlaAttackEntity)); } @@ -364,7 +364,7 @@ void cItemHandler::OnFoodEaten(cWorld * a_World, cPlayer * a_Player, cItem * a_I -short cItemHandler::GetDurabilityLostWithThatAction(eDurabilityLostAction a_Action) +short cItemHandler::GetDurabilityLossByAction(eDurabilityLostAction a_Action) { switch (a_Action) { diff --git a/src/Items/ItemHandler.h b/src/Items/ItemHandler.h index 28b1dd13b..1d5f59f3e 100644 --- a/src/Items/ItemHandler.h +++ b/src/Items/ItemHandler.h @@ -64,7 +64,7 @@ public: virtual void OnFoodEaten(cWorld *a_World, cPlayer *a_Player, cItem *a_Item); /** Get the durability lost which the item will get, when a specified action was performed. */ - virtual short GetDurabilityLostWithThatAction(eDurabilityLostAction a_Action); + virtual short GetDurabilityLossByAction(eDurabilityLostAction a_Action); /** Returns the maximum stack size for a given item */ virtual char GetMaxStackSize(void); diff --git a/src/Items/ItemShears.h b/src/Items/ItemShears.h index 8f5d5f385..fa2794df2 100644 --- a/src/Items/ItemShears.h +++ b/src/Items/ItemShears.h @@ -63,7 +63,7 @@ public: } - virtual short GetDurabilityLostWithThatAction(eDurabilityLostAction a_Action) override + virtual short GetDurabilityLossByAction(eDurabilityLostAction a_Action) override { return 0; } diff --git a/src/Items/ItemSword.h b/src/Items/ItemSword.h index 1a17023ef..b90965535 100644 --- a/src/Items/ItemSword.h +++ b/src/Items/ItemSword.h @@ -44,7 +44,7 @@ public: } - virtual short GetDurabilityLostWithThatAction(eDurabilityLostAction a_Action) override + virtual short GetDurabilityLossByAction(eDurabilityLostAction a_Action) override { switch (a_Action) { -- cgit v1.2.3 From c2a2aea9f8808b9742fedbfc8c8864cb9082afd5 Mon Sep 17 00:00:00 2001 From: Howaner Date: Sat, 26 Jul 2014 17:09:59 +0200 Subject: Derp. --- src/Items/ItemHoe.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Items/ItemHoe.h b/src/Items/ItemHoe.h index 6523b36d9..8d0b71478 100644 --- a/src/Items/ItemHoe.h +++ b/src/Items/ItemHoe.h @@ -33,7 +33,7 @@ public: } - virtual short GetDurabilityLostWithThatAction(eDurabilityLostAction a_Action) override + virtual short GetDurabilityLossByAction(eDurabilityLostAction a_Action) override { return 0; } -- cgit v1.2.3 From f79e68266426993af94f811afc8296e7b159462a Mon Sep 17 00:00:00 2001 From: Howaner Date: Sun, 27 Jul 2014 00:03:00 +0200 Subject: Fixed plugin count and fixed plugin loading, when settings.ini was regenerated. --- src/Bindings/PluginManager.cpp | 46 +++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/src/Bindings/PluginManager.cpp b/src/Bindings/PluginManager.cpp index 088b92a6d..1d97d1331 100644 --- a/src/Bindings/PluginManager.cpp +++ b/src/Bindings/PluginManager.cpp @@ -124,44 +124,58 @@ void cPluginManager::ReloadPluginsNow(cIniFile & a_SettingsIni) // Check if the Plugins section exists. int KeyNum = a_SettingsIni.FindKey("Plugins"); - // If it does, how many plugins are there? - int NumPlugins = ((KeyNum != -1) ? (a_SettingsIni.GetNumValues(KeyNum)) : 0); - if (KeyNum == -1) { InsertDefaultPlugins(a_SettingsIni); + KeyNum = a_SettingsIni.FindKey("Plugins"); } - else if (NumPlugins > 0) + + // How many plugins are there? + int NumPlugins = a_SettingsIni.GetNumValues(KeyNum); + + for (int i = 0; i < NumPlugins; i++) { - for (int i = 0; i < NumPlugins; i++) + AString ValueName = a_SettingsIni.GetValueName(KeyNum, i); + if (ValueName.compare("Plugin") == 0) { - AString ValueName = a_SettingsIni.GetValueName(KeyNum, i); - if (ValueName.compare("Plugin") == 0) + AString PluginFile = a_SettingsIni.GetValue(KeyNum, i); + if (!PluginFile.empty()) { - AString PluginFile = a_SettingsIni.GetValue(KeyNum, i); - if (!PluginFile.empty()) + if (m_Plugins.find(PluginFile) != m_Plugins.end()) { - if (m_Plugins.find(PluginFile) != m_Plugins.end()) - { - LoadPlugin(PluginFile); - } + LoadPlugin(PluginFile); } } } } + + // Remove invalid plugins from the PluginMap. + for (PluginMap::iterator itr = m_Plugins.begin(); itr != m_Plugins.end();) + { + if (itr->second == NULL) + { + PluginMap::iterator thiz = itr; + ++thiz; + m_Plugins.erase(itr); + itr = thiz; + continue; + } + ++itr; + } + size_t NumLoadedPlugins = GetNumPlugins(); if (NumLoadedPlugins == 0) { LOG("-- No Plugins Loaded --"); } - else if (NumLoadedPlugins > 1) + else if (NumLoadedPlugins == 1) { - LOG("-- Loaded %i Plugins --", (int)NumLoadedPlugins); + LOG("-- Loaded 1 Plugin --"); } else { - LOG("-- Loaded 1 Plugin --"); + LOG("-- Loaded %i Plugins --", (int)NumLoadedPlugins); } CallHookPluginsLoaded(); } -- cgit v1.2.3 From 77f4297c6ee4daca51220f60b626658a22a22ea2 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sun, 27 Jul 2014 00:03:26 +0200 Subject: RoughRavines: Initial generator implementation. This provides the basic shape of the ravines, with the basic settings based on GridStructGen, and good default values. --- src/Generating/CMakeLists.txt | 2 + src/Generating/ComposableGenerator.cpp | 14 ++- src/Generating/RoughRavines.cpp | 214 +++++++++++++++++++++++++++++++++ src/Generating/RoughRavines.h | 37 ++++++ 4 files changed, 264 insertions(+), 3 deletions(-) create mode 100644 src/Generating/RoughRavines.cpp create mode 100644 src/Generating/RoughRavines.h diff --git a/src/Generating/CMakeLists.txt b/src/Generating/CMakeLists.txt index 9063abd97..58df9d421 100644 --- a/src/Generating/CMakeLists.txt +++ b/src/Generating/CMakeLists.txt @@ -25,6 +25,7 @@ SET (SRCS PrefabPiecePool.cpp RainbowRoadsGen.cpp Ravines.cpp + RoughRavines.cpp StructGen.cpp TestRailsGen.cpp Trees.cpp @@ -52,6 +53,7 @@ SET (HDRS PrefabPiecePool.h RainbowRoadsGen.h Ravines.h + RoughRavines.h StructGen.h TestRailsGen.h Trees.h diff --git a/src/Generating/ComposableGenerator.cpp b/src/Generating/ComposableGenerator.cpp index ab6accee7..757f6ddb7 100644 --- a/src/Generating/ComposableGenerator.cpp +++ b/src/Generating/ComposableGenerator.cpp @@ -26,6 +26,7 @@ #include "POCPieceGenerator.h" #include "RainbowRoadsGen.h" #include "Ravines.h" +#include "RoughRavines.h" #include "TestRailsGen.h" #include "UnderwaterBaseGen.h" #include "VillageGen.h" @@ -397,16 +398,23 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile) } else if (NoCaseCompare(*itr, "RainbowRoads") == 0) { - int GridSize = a_IniFile.GetValueSetI("Generator", "RainbowRoadsGridSize", 512); + int GridSize = a_IniFile.GetValueSetI("Generator", "RainbowRoadsGridSize", 512); int MaxOffset = a_IniFile.GetValueSetI("Generator", "RainbowRoadsMaxOffset", 128); - int MaxDepth = a_IniFile.GetValueSetI("Generator", "RainbowRoadsMaxDepth", 30); - int MaxSize = a_IniFile.GetValueSetI("Generator", "RainbowRoadsMaxSize", 260); + int MaxDepth = a_IniFile.GetValueSetI("Generator", "RainbowRoadsMaxDepth", 30); + int MaxSize = a_IniFile.GetValueSetI("Generator", "RainbowRoadsMaxSize", 260); m_FinishGens.push_back(new cRainbowRoadsGen(Seed, GridSize, MaxOffset, MaxDepth, MaxSize)); } else if (NoCaseCompare(*itr, "Ravines") == 0) { m_FinishGens.push_back(new cStructGenRavines(Seed, 128)); } + else if (NoCaseCompare(*itr, "RoughRavines") == 0) + { + int GridSize = a_IniFile.GetValueSetI("Generator", "RoughRavinesGridSize", 256); + int MaxOffset = a_IniFile.GetValueSetI("Generator", "RoughRavinesMaxOffset", 128); + int MaxSize = a_IniFile.GetValueSetI("Generator", "RoughRavinesMaxSize", 64); + m_FinishGens.push_back(new cRoughRavines(Seed, MaxSize, GridSize, MaxOffset)); + } else if (NoCaseCompare(*itr, "Snow") == 0) { m_FinishGens.push_back(new cFinishGenSnow); diff --git a/src/Generating/RoughRavines.cpp b/src/Generating/RoughRavines.cpp new file mode 100644 index 000000000..1b1351a19 --- /dev/null +++ b/src/Generating/RoughRavines.cpp @@ -0,0 +1,214 @@ + +// RoughRavines.cpp + +// Implements the cRoughRavines class representing the rough ravine generator + +#include "Globals.h" + +#include "RoughRavines.h" + + + + + +//////////////////////////////////////////////////////////////////////////////// +// cRoughRavine: + +class cRoughRavine : + public cGridStructGen::cStructure +{ + typedef cGridStructGen::cStructure super; + +public: + cRoughRavine(int a_Seed, int a_MaxSize, int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) : + super(a_GridX, a_GridZ, a_OriginX, a_OriginZ), + m_Noise(a_Seed + 100), + m_MaxSize(a_MaxSize) + { + // Create the basic structure - 2 lines meeting at the centerpoint: + m_DefPoints.resize(a_MaxSize + 1); + int Half = a_MaxSize / 2; // m_DefPoints[Half] will be the centerpoint + int rnd = m_Noise.IntNoise2DInt(a_OriginX, a_OriginZ) / 7; + float Len = (float)(3 * a_MaxSize / 4 + rnd % (a_MaxSize / 4)); // Random number between 3 / 4 * a_MaxSize and a_MaxSize + rnd = rnd / a_MaxSize; + float Angle = (float)rnd; // Angle is in radians, will be wrapped in the "sin" and "cos" operations + float OfsX = sin(Angle) * Len; + float OfsZ = cos(Angle) * Len; + m_DefPoints[0].Set (a_OriginX - OfsX, a_OriginZ - OfsZ, 1, 42, 34); + m_DefPoints[Half].Set ((float)a_OriginX, (float)a_OriginZ, Len / 10, 62, 16); + m_DefPoints[a_MaxSize].Set(a_OriginX + OfsX, a_OriginZ + OfsZ, 1, 44, 32); + + // Calculate the points in between, recursively: + SubdivideLine(0, Half); + SubdivideLine(Half, a_MaxSize); + } + +protected: + struct sRavineDefPoint + { + float m_X; + float m_Z; + float m_Radius; + float m_Top; + float m_Bottom; + + void Set(float a_X, float a_Z, float a_Radius, float a_Top, float a_Bottom) + { + m_X = a_X; + m_Z = a_Z; + m_Radius = a_Radius; + m_Top = a_Top; + m_Bottom = a_Bottom; + } + }; + typedef std::vector sRavineDefPoints; + + cNoise m_Noise; + + int m_MaxSize; + + sRavineDefPoints m_DefPoints; + + + /** Recursively subdivides the line between the points of the specified index. + Sets the midpoint to the center of the line plus or minus a random offset, then calls itself for each half + of the new line. */ + void SubdivideLine(int a_Idx1, int a_Idx2) + { + // Calculate the midpoint: + const sRavineDefPoint & p1 = m_DefPoints[a_Idx1]; + const sRavineDefPoint & p2 = m_DefPoints[a_Idx2]; + float MidX = (p1.m_X + p2.m_X) / 2; + float MidZ = (p1.m_Z + p2.m_Z) / 2; + float MidR = (p1.m_Radius + p2.m_Radius) / 2 + 0.1f; + float MidT = (p1.m_Top + p2.m_Top) / 2; + float MidB = (p1.m_Bottom + p2.m_Bottom) / 2; + + // Adjust the midpoint by a small amount of perpendicular vector in a random one of its two directions: + float dx = p2.m_X - p1.m_X; + float dz = p2.m_Z - p1.m_Z; + if ((m_Noise.IntNoise2DInt((int)MidX, (int)MidZ) / 11) % 2 == 0) + { + MidX += dz / 10; + MidZ -= dx / 10; + } + else + { + MidX -= dz / 10; + MidZ += dx / 10; + } + int MidIdx = (a_Idx1 + a_Idx2) / 2; + m_DefPoints[MidIdx].Set(MidX, MidZ, MidR, MidT, MidB); + + // Recurse the two halves, if they are worth recursing: + if (MidIdx - a_Idx1 > 1) + { + SubdivideLine(a_Idx1, MidIdx); + } + if (a_Idx2 - MidIdx > 1) + { + SubdivideLine(MidIdx, a_Idx2); + } + } + + + virtual void DrawIntoChunk(cChunkDesc & a_ChunkDesc) override + { + int BlockStartX = a_ChunkDesc.GetChunkX() * cChunkDef::Width; + int BlockStartZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width; + int BlockEndX = BlockStartX + cChunkDef::Width; + int BlockEndZ = BlockStartZ + cChunkDef::Width; + for (sRavineDefPoints::const_iterator itr = m_DefPoints.begin(), end = m_DefPoints.end(); itr != end; ++itr) + { + if ( + (ceilf (itr->m_X + itr->m_Radius) < BlockStartX) || + (floorf(itr->m_X - itr->m_Radius) > BlockEndX) || + (ceilf (itr->m_Z + itr->m_Radius) < BlockStartZ) || + (floorf(itr->m_Z - itr->m_Radius) > BlockEndZ) + ) + { + // Cannot intersect, bail out early + continue; + } + + // Carve out a cylinder around the xz point, m_Radius in diameter, from Bottom to Top: + float RadiusSq = itr->m_Radius * itr->m_Radius; // instead of doing sqrt for each distance, we do sqr of the radius + float DifX = BlockStartX - itr->m_X; // substitution for faster calc + float DifZ = BlockStartZ - itr->m_Z; // substitution for faster calc + for (int x = 0; x < cChunkDef::Width; x++) for (int z = 0; z < cChunkDef::Width; z++) + { + #ifdef _DEBUG + // DEBUG: Make the roughravine shapepoints visible on a single layer (so that we can see with Minutor what's going on) + if ((DifX + x == 0) && (DifZ + z == 0)) + { + a_ChunkDesc.SetBlockType(x, 4, z, E_BLOCK_LAPIS_ORE); + } + #endif // _DEBUG + + float DistSq = (DifX + x) * (DifX + x) + (DifZ + z) * (DifZ + z); + if (DistSq <= RadiusSq) + { + int Top = std::min((int)ceilf(itr->m_Top), +cChunkDef::Height); + for (int y = std::max((int)floorf(itr->m_Bottom), 1); y <= Top; y++) + { + switch (a_ChunkDesc.GetBlockType(x, y, z)) + { + // Only carve out these specific block types + case E_BLOCK_DIRT: + case E_BLOCK_GRASS: + case E_BLOCK_STONE: + case E_BLOCK_COBBLESTONE: + case E_BLOCK_GRAVEL: + case E_BLOCK_SAND: + case E_BLOCK_SANDSTONE: + case E_BLOCK_NETHERRACK: + case E_BLOCK_COAL_ORE: + case E_BLOCK_IRON_ORE: + case E_BLOCK_GOLD_ORE: + case E_BLOCK_DIAMOND_ORE: + case E_BLOCK_REDSTONE_ORE: + case E_BLOCK_REDSTONE_ORE_GLOWING: + { + a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_AIR); + break; + } + default: break; + } + } + } + } // for x, z - a_BlockTypes + } // for itr - m_Points[] + } +}; + + + + + +//////////////////////////////////////////////////////////////////////////////// +// cRoughRavines: + +cRoughRavines::cRoughRavines(int a_Seed, int a_MaxSize, int a_GridSize, int a_MaxOffset) : + super(a_Seed, a_GridSize, a_GridSize, a_MaxOffset, a_MaxOffset, a_MaxSize, a_MaxSize, 64), + m_Seed(a_Seed), + m_MaxSize(a_MaxSize) +{ + if (m_MaxSize < 1) + { + m_MaxSize = 16; + LOGWARNING("RoughRavines: MaxSize too small, adjusting request from %d to %d", a_MaxSize, m_MaxSize); + } +} + + + + + +cGridStructGen::cStructurePtr cRoughRavines::CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) +{ + return cStructurePtr(new cRoughRavine(m_Seed, m_MaxSize, a_GridX, a_GridZ, a_OriginX, a_OriginZ)); +} + + + + diff --git a/src/Generating/RoughRavines.h b/src/Generating/RoughRavines.h new file mode 100644 index 000000000..68c628d84 --- /dev/null +++ b/src/Generating/RoughRavines.h @@ -0,0 +1,37 @@ + +// RoughRavines.h + +// Declares the cRoughRavines class representing the rough ravine generator + + + + +#pragma once + +#include "GridStructGen.h" + + + + + +class cRoughRavines : + public cGridStructGen +{ + typedef cGridStructGen super; + +public: + cRoughRavines(int a_Seed, int a_MaxSize, int a_GridSize, int a_MaxOffset); + +protected: + int m_Seed; + + /** Maximum size of the ravine, in each of the X / Z axis */ + int m_MaxSize; + + // cGridStructGen overrides: + virtual cStructurePtr CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) override; +}; + + + + -- cgit v1.2.3 From a5cca16abe524fdbd756908ac157a0c9881463f3 Mon Sep 17 00:00:00 2001 From: Howaner Date: Sun, 27 Jul 2014 00:39:39 +0200 Subject: Add "Broadcasting" settings to world.ini --- src/Entities/Player.cpp | 14 ++++++++------ src/Root.cpp | 4 ++-- src/Server.h | 4 ++-- src/World.cpp | 3 +++ src/World.h | 8 +++++++- 5 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index fcc8eb9a0..393afc3b6 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -890,7 +890,7 @@ void cPlayer::KilledBy(TakeDamageInfo & a_TDI) m_World->SpawnItemPickups(Pickups, GetPosX(), GetPosY(), GetPosZ(), 10); SaveToDisk(); // Save it, yeah the world is a tough place ! - if (a_TDI.Attacker == NULL) + if ((a_TDI.Attacker == NULL) && m_World->ShouldBroadcastDeathMessages()) { AString DamageText; switch (a_TDI.DamageType) @@ -1208,11 +1208,13 @@ unsigned int cPlayer::AwardAchievement(const eStatistic a_Ach) } else { - // First time, announce it - cCompositeChat Msg; - Msg.SetMessageType(mtSuccess); - Msg.AddShowAchievementPart(GetName(), cStatInfo::GetName(a_Ach)); - m_World->BroadcastChat(Msg); + if (m_World->ShouldBroadcastAchievementMessages()) + { + cCompositeChat Msg; + Msg.SetMessageType(mtSuccess); + Msg.AddShowAchievementPart(GetName(), cStatInfo::GetName(a_Ach)); + m_World->BroadcastChat(Msg); + } // Increment the statistic StatValue New = m_Stats.AddValue(a_Ach); diff --git a/src/Root.cpp b/src/Root.cpp index b03a13382..efa21b775 100644 --- a/src/Root.cpp +++ b/src/Root.cpp @@ -269,12 +269,12 @@ void cRoot::LoadWorlds(cIniFile & IniFile) { // First get the default world AString DefaultWorldName = IniFile.GetValueSet("Worlds", "DefaultWorld", "world"); - m_pDefaultWorld = new cWorld( DefaultWorldName.c_str()); + m_pDefaultWorld = new cWorld(DefaultWorldName.c_str()); m_WorldsByName[ DefaultWorldName ] = m_pDefaultWorld; // Then load the other worlds unsigned int KeyNum = IniFile.FindKey("Worlds"); - unsigned int NumWorlds = IniFile.GetNumValues( KeyNum); + unsigned int NumWorlds = IniFile.GetNumValues(KeyNum); if (NumWorlds <= 0) { return; diff --git a/src/Server.h b/src/Server.h index b03359f03..c1640b388 100644 --- a/src/Server.h +++ b/src/Server.h @@ -63,12 +63,12 @@ public: // tolua_export const AString & GetDescription(void) const {return m_Description; } // Player counts: - int GetMaxPlayers(void) const {return m_MaxPlayers; } + int GetMaxPlayers(void) const { return m_MaxPlayers; } int GetNumPlayers(void) const; void SetMaxPlayers(int a_MaxPlayers) { m_MaxPlayers = a_MaxPlayers; } // Hardcore mode or not: - bool IsHardcore(void) const {return m_bIsHardcore; } + bool IsHardcore(void) const { return m_bIsHardcore; } // tolua_end diff --git a/src/World.cpp b/src/World.cpp index 7ad350e24..ff393bc2b 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -522,6 +522,9 @@ void cWorld::Start(void) AString Dimension = IniFile.GetValueSet("General", "Dimension", "Overworld"); m_Dimension = StringToDimension(Dimension); + m_BroadcastDeathMessages = IniFile.GetValueSetB("Broadcasting", "BroadcastDeathMessages", true); + m_BroadcastAchievementMessages = IniFile.GetValueSetB("Broadcasting", "BroadcastAchievementMessages", true); + // Try to find the "SpawnPosition" key and coord values in the world configuration, set the flag if found int KeyNum = IniFile.FindKey("SpawnPosition"); m_IsSpawnExplicitlySet = diff --git a/src/World.h b/src/World.h index 9658178ae..cb77361f6 100644 --- a/src/World.h +++ b/src/World.h @@ -622,7 +622,10 @@ public: bool ShouldUseChatPrefixes(void) const { return m_bUseChatPrefixes; } void SetShouldUseChatPrefixes(bool a_Flag) { m_bUseChatPrefixes = a_Flag; } - + + bool ShouldBroadcastDeathMessages(void) const { return m_BroadcastDeathMessages; } + bool ShouldBroadcastAchievementMessages(void) const { return m_BroadcastAchievementMessages; } + // tolua_end /** Saves all chunks immediately. Dangerous interface, may deadlock, use QueueSaveAllChunks() instead */ @@ -842,6 +845,9 @@ private: double m_SpawnY; double m_SpawnZ; + bool m_BroadcastDeathMessages; + bool m_BroadcastAchievementMessages; + double m_WorldAgeSecs; // World age, in seconds. Is only incremented, cannot be set by plugins. double m_TimeOfDaySecs; // Time of day in seconds. Can be adjusted. Is wrapped to zero each day. Int64 m_WorldAge; // World age in ticks, calculated off of m_WorldAgeSecs -- cgit v1.2.3 From 7f9f46c9114837a6edaae53385b7b7970b91abbd Mon Sep 17 00:00:00 2001 From: Howaner Date: Sun, 27 Jul 2014 13:47:21 +0200 Subject: Fixed group color's. --- src/ClientHandle.cpp | 19 ++++--------------- src/GroupManager.cpp | 2 +- 2 files changed, 5 insertions(+), 16 deletions(-) diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index e4ad218a2..116ea459e 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -1973,28 +1973,17 @@ void cClientHandle::SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBlock void cClientHandle::SendChat(const AString & a_Message, eMessageType a_ChatPrefix, const AString & a_AdditionalData) { - bool ShouldAppendChatPrefixes = true; - - if (GetPlayer()->GetWorld() == NULL) + cWorld * World = GetPlayer()->GetWorld(); + if (World == NULL) { - cWorld * World = cRoot::Get()->GetWorld(GetPlayer()->GetLoadedWorldName()); + World = cRoot::Get()->GetWorld(GetPlayer()->GetLoadedWorldName()); if (World == NULL) { World = cRoot::Get()->GetDefaultWorld(); } - - if (!World->ShouldUseChatPrefixes()) - { - ShouldAppendChatPrefixes = false; - } - } - else if (!GetPlayer()->GetWorld()->ShouldUseChatPrefixes()) - { - ShouldAppendChatPrefixes = false; } - AString Message = FormatMessageType(ShouldAppendChatPrefixes, a_ChatPrefix, a_AdditionalData); - + AString Message = FormatMessageType(World->ShouldUseChatPrefixes(), a_ChatPrefix, a_AdditionalData); m_Protocol->SendChat(Message.append(a_Message)); } diff --git a/src/GroupManager.cpp b/src/GroupManager.cpp index 32c2f1c97..bc9bb67be 100644 --- a/src/GroupManager.cpp +++ b/src/GroupManager.cpp @@ -153,7 +153,7 @@ bool cGroupManager::LoadGroups() AString Color = IniFile.GetValue(KeyName, "Color", "-"); if ((Color != "-") && (Color.length() >= 1)) { - Group->SetColor(cChatColor::Delimiter + Color[0]); + Group->SetColor(cChatColor::Delimiter + Color); } else { -- cgit v1.2.3 From 472f70a6762369eb3375eb1ed874a95faaf2de71 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sun, 27 Jul 2014 13:54:27 +0200 Subject: RoughRavines: More settings - size, width, roughness --- src/Generating/ComposableGenerator.cpp | 18 +++++++--- src/Generating/RoughRavines.cpp | 66 ++++++++++++++++++++++++---------- src/Generating/RoughRavines.h | 23 +++++++++++- 3 files changed, 84 insertions(+), 23 deletions(-) diff --git a/src/Generating/ComposableGenerator.cpp b/src/Generating/ComposableGenerator.cpp index 757f6ddb7..3326dda36 100644 --- a/src/Generating/ComposableGenerator.cpp +++ b/src/Generating/ComposableGenerator.cpp @@ -410,10 +410,20 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile) } else if (NoCaseCompare(*itr, "RoughRavines") == 0) { - int GridSize = a_IniFile.GetValueSetI("Generator", "RoughRavinesGridSize", 256); - int MaxOffset = a_IniFile.GetValueSetI("Generator", "RoughRavinesMaxOffset", 128); - int MaxSize = a_IniFile.GetValueSetI("Generator", "RoughRavinesMaxSize", 64); - m_FinishGens.push_back(new cRoughRavines(Seed, MaxSize, GridSize, MaxOffset)); + int GridSize = a_IniFile.GetValueSetI("Generator", "RoughRavinesGridSize", 256); + int MaxOffset = a_IniFile.GetValueSetI("Generator", "RoughRavinesMaxOffset", 128); + int MaxSize = a_IniFile.GetValueSetI("Generator", "RoughRavinesMaxSize", 128); + int MinSize = a_IniFile.GetValueSetI("Generator", "RoughRavinesMinSize", 64); + double MaxCenterWidth = a_IniFile.GetValueSetF("Generator", "RoughRavinesMaxCenterWidth", 8); + double MinCenterWidth = a_IniFile.GetValueSetF("Generator", "RoughRavinesMinCenterWidth", 2); + double MaxRoughness = a_IniFile.GetValueSetF("Generator", "RoughRavinesMaxRoughness", 0.2); + double MinRoughness = a_IniFile.GetValueSetF("Generator", "RoughRavinesMinRoughness", 0.05); + m_FinishGens.push_back(new cRoughRavines( + Seed, MaxSize, MinSize, + (float)MaxCenterWidth, (float)MinCenterWidth, + (float)MaxRoughness, (float)MinRoughness, + GridSize, MaxOffset + )); } else if (NoCaseCompare(*itr, "Snow") == 0) { diff --git a/src/Generating/RoughRavines.cpp b/src/Generating/RoughRavines.cpp index 1b1351a19..ddc1a0351 100644 --- a/src/Generating/RoughRavines.cpp +++ b/src/Generating/RoughRavines.cpp @@ -20,27 +20,27 @@ class cRoughRavine : typedef cGridStructGen::cStructure super; public: - cRoughRavine(int a_Seed, int a_MaxSize, int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) : + cRoughRavine(int a_Seed, int a_Size, float a_CenterWidth, float a_Roughness, int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) : super(a_GridX, a_GridZ, a_OriginX, a_OriginZ), m_Noise(a_Seed + 100), - m_MaxSize(a_MaxSize) + m_Roughness(a_Roughness) { // Create the basic structure - 2 lines meeting at the centerpoint: - m_DefPoints.resize(a_MaxSize + 1); - int Half = a_MaxSize / 2; // m_DefPoints[Half] will be the centerpoint + int Max = 2 * a_Size; + int Half = a_Size; // m_DefPoints[Half] will be the centerpoint + m_DefPoints.resize(Max + 1); int rnd = m_Noise.IntNoise2DInt(a_OriginX, a_OriginZ) / 7; - float Len = (float)(3 * a_MaxSize / 4 + rnd % (a_MaxSize / 4)); // Random number between 3 / 4 * a_MaxSize and a_MaxSize - rnd = rnd / a_MaxSize; + float Len = (float)a_Size; float Angle = (float)rnd; // Angle is in radians, will be wrapped in the "sin" and "cos" operations float OfsX = sin(Angle) * Len; float OfsZ = cos(Angle) * Len; - m_DefPoints[0].Set (a_OriginX - OfsX, a_OriginZ - OfsZ, 1, 42, 34); - m_DefPoints[Half].Set ((float)a_OriginX, (float)a_OriginZ, Len / 10, 62, 16); - m_DefPoints[a_MaxSize].Set(a_OriginX + OfsX, a_OriginZ + OfsZ, 1, 44, 32); + m_DefPoints[0].Set (a_OriginX - OfsX, a_OriginZ - OfsZ, 1, 42, 34); + m_DefPoints[Half].Set((float)a_OriginX, (float)a_OriginZ, a_CenterWidth, 62, 16); + m_DefPoints[Max].Set (a_OriginX + OfsX, a_OriginZ + OfsZ, 1, 44, 32); // Calculate the points in between, recursively: SubdivideLine(0, Half); - SubdivideLine(Half, a_MaxSize); + SubdivideLine(Half, Max); } protected: @@ -69,6 +69,8 @@ protected: sRavineDefPoints m_DefPoints; + float m_Roughness; + /** Recursively subdivides the line between the points of the specified index. Sets the midpoint to the center of the line plus or minus a random offset, then calls itself for each half @@ -89,13 +91,13 @@ protected: float dz = p2.m_Z - p1.m_Z; if ((m_Noise.IntNoise2DInt((int)MidX, (int)MidZ) / 11) % 2 == 0) { - MidX += dz / 10; - MidZ -= dx / 10; + MidX += dz * m_Roughness; + MidZ -= dx * m_Roughness; } else { - MidX -= dz / 10; - MidZ += dx / 10; + MidX -= dz * m_Roughness; + MidZ += dx * m_Roughness; } int MidIdx = (a_Idx1 + a_Idx2) / 2; m_DefPoints[MidIdx].Set(MidX, MidZ, MidR, MidT, MidB); @@ -188,16 +190,41 @@ protected: //////////////////////////////////////////////////////////////////////////////// // cRoughRavines: -cRoughRavines::cRoughRavines(int a_Seed, int a_MaxSize, int a_GridSize, int a_MaxOffset) : +cRoughRavines::cRoughRavines( + int a_Seed, + int a_MaxSize, int a_MinSize, + float a_MaxCenterWidth, float a_MinCenterWidth, + float a_MaxRoughness, float a_MinRoughness, + int a_GridSize, int a_MaxOffset +) : super(a_Seed, a_GridSize, a_GridSize, a_MaxOffset, a_MaxOffset, a_MaxSize, a_MaxSize, 64), m_Seed(a_Seed), - m_MaxSize(a_MaxSize) + m_MaxSize(a_MaxSize), + m_MinSize(a_MinSize), + m_MaxCenterWidth(a_MaxCenterWidth), + m_MinCenterWidth(a_MinCenterWidth), + m_MaxRoughness(a_MaxRoughness), + m_MinRoughness(a_MinRoughness) { - if (m_MaxSize < 1) + if (m_MinSize > m_MaxSize) + { + std::swap(m_MinSize, m_MaxSize); + std::swap(a_MinSize, a_MaxSize); + } + if (m_MaxSize < 16) { m_MaxSize = 16; LOGWARNING("RoughRavines: MaxSize too small, adjusting request from %d to %d", a_MaxSize, m_MaxSize); } + if (m_MinSize < 16) + { + m_MinSize = 16; + LOGWARNING("RoughRavines: MinSize too small, adjusting request from %d to %d", a_MinSize, m_MinSize); + } + if (m_MinSize == m_MaxSize) + { + m_MaxSize = m_MinSize + 1; + } } @@ -206,7 +233,10 @@ cRoughRavines::cRoughRavines(int a_Seed, int a_MaxSize, int a_GridSize, int a_Ma cGridStructGen::cStructurePtr cRoughRavines::CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) { - return cStructurePtr(new cRoughRavine(m_Seed, m_MaxSize, a_GridX, a_GridZ, a_OriginX, a_OriginZ)); + int Size = m_MinSize + (m_Noise.IntNoise2DInt(a_GridX, a_GridZ) / 7) % (m_MaxSize - m_MinSize); // Random int from m_MinSize to m_MaxSize + float CenterWidth = m_MinCenterWidth + abs(m_Noise.IntNoise2D(a_GridX, a_GridZ + 10)) * (m_MaxCenterWidth - m_MinCenterWidth); // Random float from m_MinCenterWidth to m_MaxCenterWidth + float Roughness = m_MinRoughness + abs(m_Noise.IntNoise2D(a_GridX + 10, a_GridZ)) * (m_MaxRoughness - m_MinRoughness); // Random float from m_MinRoughness to m_MaxRoughness + return cStructurePtr(new cRoughRavine(m_Seed, Size, CenterWidth, Roughness, a_GridX, a_GridZ, a_OriginX, a_OriginZ)); } diff --git a/src/Generating/RoughRavines.h b/src/Generating/RoughRavines.h index 68c628d84..dce2f9ba7 100644 --- a/src/Generating/RoughRavines.h +++ b/src/Generating/RoughRavines.h @@ -20,13 +20,34 @@ class cRoughRavines : typedef cGridStructGen super; public: - cRoughRavines(int a_Seed, int a_MaxSize, int a_GridSize, int a_MaxOffset); + cRoughRavines( + int a_Seed, + int a_MaxSize, int a_MinSize, + float a_MaxCenterWidth, float a_MinCenterWidth, + float a_MaxRoughness, float a_MinRoughness, + int a_GridSize, int a_MaxOffset + ); protected: int m_Seed; /** Maximum size of the ravine, in each of the X / Z axis */ int m_MaxSize; + + /** Minimum size of the ravine */ + int m_MinSize; + + /** Maximum width of the ravine's center, in blocks */ + float m_MaxCenterWidth; + + /** Minimum width of the ravine's center, in blocks */ + float m_MinCenterWidth; + + /** Maximum roughness of the ravine */ + float m_MaxRoughness; + + /** Minimum roughness of the ravine */ + float m_MinRoughness; // cGridStructGen overrides: virtual cStructurePtr CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) override; -- cgit v1.2.3 From 960ab982b96d23485b6c42df1ed2b08a251a0c22 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sun, 27 Jul 2014 16:05:45 +0200 Subject: RoughRavines: Added per-height radius modifier. Ledges! --- src/Generating/RoughRavines.cpp | 105 ++++++++++++++++++++++++++++------------ 1 file changed, 73 insertions(+), 32 deletions(-) diff --git a/src/Generating/RoughRavines.cpp b/src/Generating/RoughRavines.cpp index ddc1a0351..8dec791c9 100644 --- a/src/Generating/RoughRavines.cpp +++ b/src/Generating/RoughRavines.cpp @@ -22,6 +22,7 @@ class cRoughRavine : public: cRoughRavine(int a_Seed, int a_Size, float a_CenterWidth, float a_Roughness, int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) : super(a_GridX, a_GridZ, a_OriginX, a_OriginZ), + m_Seed(a_Seed + 100), m_Noise(a_Seed + 100), m_Roughness(a_Roughness) { @@ -41,6 +42,9 @@ public: // Calculate the points in between, recursively: SubdivideLine(0, Half); SubdivideLine(Half, Max); + + // Initialize the per-height radius modifiers: + InitPerHeightRadius(a_GridX, a_GridZ); } protected: @@ -63,6 +67,8 @@ protected: }; typedef std::vector sRavineDefPoints; + int m_Seed; + cNoise m_Noise; int m_MaxSize; @@ -71,6 +77,9 @@ protected: float m_Roughness; + /** Number to add to the radius based on the height. This creates the "ledges" in the ravine walls. */ + float m_PerHeightRadius[cChunkDef::Height]; + /** Recursively subdivides the line between the points of the specified index. Sets the midpoint to the center of the line plus or minus a random offset, then calls itself for each half @@ -114,6 +123,29 @@ protected: } + void InitPerHeightRadius(int a_GridX, int a_GridZ) + { + int h = 0; + while (h < cChunkDef::Height) + { + m_Noise.SetSeed(m_Seed + h); + int rnd = m_Noise.IntNoise2DInt(a_GridX, a_GridZ) / 13; + int NumBlocks = (rnd % 3) + 2; + rnd = rnd / 4; + float Val = (float)(rnd % 256) / 128 - 1; // Random float in range [-1, +1] + if (h + NumBlocks > cChunkDef::Height) + { + NumBlocks = cChunkDef::Height - h; + } + for (int i = 0; i < NumBlocks; i++) + { + m_PerHeightRadius[h + i] = Val; + } + h += NumBlocks; + } + } + + virtual void DrawIntoChunk(cChunkDesc & a_ChunkDesc) override { int BlockStartX = a_ChunkDesc.GetChunkX() * cChunkDef::Width; @@ -123,18 +155,20 @@ protected: for (sRavineDefPoints::const_iterator itr = m_DefPoints.begin(), end = m_DefPoints.end(); itr != end; ++itr) { if ( - (ceilf (itr->m_X + itr->m_Radius) < BlockStartX) || - (floorf(itr->m_X - itr->m_Radius) > BlockEndX) || - (ceilf (itr->m_Z + itr->m_Radius) < BlockStartZ) || - (floorf(itr->m_Z - itr->m_Radius) > BlockEndZ) + (ceilf (itr->m_X + itr->m_Radius + 2) < BlockStartX) || + (floorf(itr->m_X - itr->m_Radius - 2) > BlockEndX) || + (ceilf (itr->m_Z + itr->m_Radius + 2) < BlockStartZ) || + (floorf(itr->m_Z - itr->m_Radius - 2) > BlockEndZ) ) { // Cannot intersect, bail out early continue; } - // Carve out a cylinder around the xz point, m_Radius in diameter, from Bottom to Top: - float RadiusSq = itr->m_Radius * itr->m_Radius; // instead of doing sqrt for each distance, we do sqr of the radius + // Carve out a cylinder around the xz point, up to (m_Radius + 2) in diameter, from Bottom to Top: + // On each height level, use m_PerHeightRadius[] to modify the actual radius used + // EnlargedRadiusSq is the square of the radius enlarged by the maximum m_PerHeightRadius offset - anything outside it will never be touched. + float RadiusSq = (itr->m_Radius + 2) * (itr->m_Radius + 2); float DifX = BlockStartX - itr->m_X; // substitution for faster calc float DifZ = BlockStartZ - itr->m_Z; // substitution for faster calc for (int x = 0; x < cChunkDef::Width; x++) for (int z = 0; z < cChunkDef::Width; z++) @@ -147,37 +181,44 @@ protected: } #endif // _DEBUG + // If the column is outside the enlarged radius, bail out completely float DistSq = (DifX + x) * (DifX + x) + (DifZ + z) * (DifZ + z); - if (DistSq <= RadiusSq) + if (DistSq > RadiusSq) + { + continue; + } + + int Top = std::min((int)ceilf(itr->m_Top), +cChunkDef::Height); + for (int y = std::max((int)floorf(itr->m_Bottom), 1); y <= Top; y++) { - int Top = std::min((int)ceilf(itr->m_Top), +cChunkDef::Height); - for (int y = std::max((int)floorf(itr->m_Bottom), 1); y <= Top; y++) + if ((itr->m_Radius + m_PerHeightRadius[y]) * (itr->m_Radius + m_PerHeightRadius[y]) < DistSq) + { + continue; + } + switch (a_ChunkDesc.GetBlockType(x, y, z)) { - switch (a_ChunkDesc.GetBlockType(x, y, z)) + // Only carve out these specific block types + case E_BLOCK_DIRT: + case E_BLOCK_GRASS: + case E_BLOCK_STONE: + case E_BLOCK_COBBLESTONE: + case E_BLOCK_GRAVEL: + case E_BLOCK_SAND: + case E_BLOCK_SANDSTONE: + case E_BLOCK_NETHERRACK: + case E_BLOCK_COAL_ORE: + case E_BLOCK_IRON_ORE: + case E_BLOCK_GOLD_ORE: + case E_BLOCK_DIAMOND_ORE: + case E_BLOCK_REDSTONE_ORE: + case E_BLOCK_REDSTONE_ORE_GLOWING: { - // Only carve out these specific block types - case E_BLOCK_DIRT: - case E_BLOCK_GRASS: - case E_BLOCK_STONE: - case E_BLOCK_COBBLESTONE: - case E_BLOCK_GRAVEL: - case E_BLOCK_SAND: - case E_BLOCK_SANDSTONE: - case E_BLOCK_NETHERRACK: - case E_BLOCK_COAL_ORE: - case E_BLOCK_IRON_ORE: - case E_BLOCK_GOLD_ORE: - case E_BLOCK_DIAMOND_ORE: - case E_BLOCK_REDSTONE_ORE: - case E_BLOCK_REDSTONE_ORE_GLOWING: - { - a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_AIR); - break; - } - default: break; + a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_AIR); + break; } - } - } + default: break; + } // switch (BlockType) + } // for y } // for x, z - a_BlockTypes } // for itr - m_Points[] } -- cgit v1.2.3 From 30893e7ee2f4dbaa3e4348b07cdc77aada168e1f Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sun, 27 Jul 2014 19:57:47 +0200 Subject: RoughRavines: Made floor and ceiling settings-adjustable. The world.ini has settings for the minimum and maximum height for each at the ravines' center and edges. --- src/Generating/ComposableGenerator.cpp | 32 ++++++++++++++------- src/Generating/RoughRavines.cpp | 51 ++++++++++++++++++++++++++++------ src/Generating/RoughRavines.h | 30 +++++++++++++++++++- src/Noise.h | 6 ++++ 4 files changed, 99 insertions(+), 20 deletions(-) diff --git a/src/Generating/ComposableGenerator.cpp b/src/Generating/ComposableGenerator.cpp index 3326dda36..0d9bedf45 100644 --- a/src/Generating/ComposableGenerator.cpp +++ b/src/Generating/ComposableGenerator.cpp @@ -410,18 +410,30 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile) } else if (NoCaseCompare(*itr, "RoughRavines") == 0) { - int GridSize = a_IniFile.GetValueSetI("Generator", "RoughRavinesGridSize", 256); - int MaxOffset = a_IniFile.GetValueSetI("Generator", "RoughRavinesMaxOffset", 128); - int MaxSize = a_IniFile.GetValueSetI("Generator", "RoughRavinesMaxSize", 128); - int MinSize = a_IniFile.GetValueSetI("Generator", "RoughRavinesMinSize", 64); - double MaxCenterWidth = a_IniFile.GetValueSetF("Generator", "RoughRavinesMaxCenterWidth", 8); - double MinCenterWidth = a_IniFile.GetValueSetF("Generator", "RoughRavinesMinCenterWidth", 2); - double MaxRoughness = a_IniFile.GetValueSetF("Generator", "RoughRavinesMaxRoughness", 0.2); - double MinRoughness = a_IniFile.GetValueSetF("Generator", "RoughRavinesMinRoughness", 0.05); + int GridSize = a_IniFile.GetValueSetI("Generator", "RoughRavinesGridSize", 256); + int MaxOffset = a_IniFile.GetValueSetI("Generator", "RoughRavinesMaxOffset", 128); + int MaxSize = a_IniFile.GetValueSetI("Generator", "RoughRavinesMaxSize", 128); + int MinSize = a_IniFile.GetValueSetI("Generator", "RoughRavinesMinSize", 64); + double MaxCenterWidth = a_IniFile.GetValueSetF("Generator", "RoughRavinesMaxCenterWidth", 8); + double MinCenterWidth = a_IniFile.GetValueSetF("Generator", "RoughRavinesMinCenterWidth", 2); + double MaxRoughness = a_IniFile.GetValueSetF("Generator", "RoughRavinesMaxRoughness", 0.2); + double MinRoughness = a_IniFile.GetValueSetF("Generator", "RoughRavinesMinRoughness", 0.05); + double MaxFloorHeightEdge = a_IniFile.GetValueSetF("Generator", "RoughRavinesMaxFloorHeightEdge", 8); + double MinFloorHeightEdge = a_IniFile.GetValueSetF("Generator", "RoughRavinesMinFloorHeightEdge", 30); + double MaxFloorHeightCenter = a_IniFile.GetValueSetF("Generator", "RoughRavinesMaxFloorHeightCenter", 20); + double MinFloorHeightCenter = a_IniFile.GetValueSetF("Generator", "RoughRavinesMinFloorHeightCenter", 6); + double MaxCeilingHeightEdge = a_IniFile.GetValueSetF("Generator", "RoughRavinesMaxCeilingHeightEdge", 56); + double MinCeilingHeightEdge = a_IniFile.GetValueSetF("Generator", "RoughRavinesMinCeilingHeightEdge", 38); + double MaxCeilingHeightCenter = a_IniFile.GetValueSetF("Generator", "RoughRavinesMaxCeilingHeightCenter", 58); + double MinCeilingHeightCenter = a_IniFile.GetValueSetF("Generator", "RoughRavinesMinCeilingHeightCenter", 36); m_FinishGens.push_back(new cRoughRavines( Seed, MaxSize, MinSize, - (float)MaxCenterWidth, (float)MinCenterWidth, - (float)MaxRoughness, (float)MinRoughness, + (float)MaxCenterWidth, (float)MinCenterWidth, + (float)MaxRoughness, (float)MinRoughness, + (float)MaxFloorHeightEdge, (float)MinFloorHeightEdge, + (float)MaxFloorHeightCenter, (float)MinFloorHeightCenter, + (float)MaxCeilingHeightEdge, (float)MinCeilingHeightEdge, + (float)MaxCeilingHeightCenter, (float)MinCeilingHeightCenter, GridSize, MaxOffset )); } diff --git a/src/Generating/RoughRavines.cpp b/src/Generating/RoughRavines.cpp index 8dec791c9..badc7768e 100644 --- a/src/Generating/RoughRavines.cpp +++ b/src/Generating/RoughRavines.cpp @@ -20,7 +20,13 @@ class cRoughRavine : typedef cGridStructGen::cStructure super; public: - cRoughRavine(int a_Seed, int a_Size, float a_CenterWidth, float a_Roughness, int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) : + cRoughRavine( + int a_Seed, int a_Size, + float a_CenterWidth, float a_Roughness, + float a_FloorHeightEdge1, float a_FloorHeightEdge2, float a_FloorHeightCenter, + float a_CeilingHeightEdge1, float a_CeilingHeightEdge2, float a_CeilingHeightCenter, + int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ + ) : super(a_GridX, a_GridZ, a_OriginX, a_OriginZ), m_Seed(a_Seed + 100), m_Noise(a_Seed + 100), @@ -35,9 +41,9 @@ public: float Angle = (float)rnd; // Angle is in radians, will be wrapped in the "sin" and "cos" operations float OfsX = sin(Angle) * Len; float OfsZ = cos(Angle) * Len; - m_DefPoints[0].Set (a_OriginX - OfsX, a_OriginZ - OfsZ, 1, 42, 34); - m_DefPoints[Half].Set((float)a_OriginX, (float)a_OriginZ, a_CenterWidth, 62, 16); - m_DefPoints[Max].Set (a_OriginX + OfsX, a_OriginZ + OfsZ, 1, 44, 32); + m_DefPoints[0].Set (a_OriginX - OfsX, a_OriginZ - OfsZ, 1, a_CeilingHeightEdge1, a_FloorHeightEdge1); + m_DefPoints[Half].Set((float)a_OriginX, (float)a_OriginZ, a_CenterWidth, a_CeilingHeightCenter, a_FloorHeightCenter); + m_DefPoints[Max].Set (a_OriginX + OfsX, a_OriginZ + OfsZ, 1, a_CeilingHeightEdge2, a_FloorHeightEdge2); // Calculate the points in between, recursively: SubdivideLine(0, Half); @@ -235,7 +241,11 @@ cRoughRavines::cRoughRavines( int a_Seed, int a_MaxSize, int a_MinSize, float a_MaxCenterWidth, float a_MinCenterWidth, - float a_MaxRoughness, float a_MinRoughness, + float a_MaxRoughness, float a_MinRoughness, + float a_MaxFloorHeightEdge, float a_MinFloorHeightEdge, + float a_MaxFloorHeightCenter, float a_MinFloorHeightCenter, + float a_MaxCeilingHeightEdge, float a_MinCeilingHeightEdge, + float a_MaxCeilingHeightCenter, float a_MinCeilingHeightCenter, int a_GridSize, int a_MaxOffset ) : super(a_Seed, a_GridSize, a_GridSize, a_MaxOffset, a_MaxOffset, a_MaxSize, a_MaxSize, 64), @@ -245,7 +255,15 @@ cRoughRavines::cRoughRavines( m_MaxCenterWidth(a_MaxCenterWidth), m_MinCenterWidth(a_MinCenterWidth), m_MaxRoughness(a_MaxRoughness), - m_MinRoughness(a_MinRoughness) + m_MinRoughness(a_MinRoughness), + m_MaxFloorHeightEdge(a_MaxFloorHeightEdge), + m_MinFloorHeightEdge(a_MinFloorHeightEdge), + m_MaxFloorHeightCenter(a_MaxFloorHeightCenter), + m_MinFloorHeightCenter(a_MinFloorHeightCenter), + m_MaxCeilingHeightEdge(a_MaxCeilingHeightEdge), + m_MinCeilingHeightEdge(a_MinCeilingHeightEdge), + m_MaxCeilingHeightCenter(a_MaxCeilingHeightCenter), + m_MinCeilingHeightCenter(a_MinCeilingHeightCenter) { if (m_MinSize > m_MaxSize) { @@ -274,10 +292,25 @@ cRoughRavines::cRoughRavines( cGridStructGen::cStructurePtr cRoughRavines::CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) { + // Pick a random value for each of the ravine's parameters: int Size = m_MinSize + (m_Noise.IntNoise2DInt(a_GridX, a_GridZ) / 7) % (m_MaxSize - m_MinSize); // Random int from m_MinSize to m_MaxSize - float CenterWidth = m_MinCenterWidth + abs(m_Noise.IntNoise2D(a_GridX, a_GridZ + 10)) * (m_MaxCenterWidth - m_MinCenterWidth); // Random float from m_MinCenterWidth to m_MaxCenterWidth - float Roughness = m_MinRoughness + abs(m_Noise.IntNoise2D(a_GridX + 10, a_GridZ)) * (m_MaxRoughness - m_MinRoughness); // Random float from m_MinRoughness to m_MaxRoughness - return cStructurePtr(new cRoughRavine(m_Seed, Size, CenterWidth, Roughness, a_GridX, a_GridZ, a_OriginX, a_OriginZ)); + float CenterWidth = m_Noise.IntNoise2DInRange(a_GridX + 10, a_GridZ, m_MinCenterWidth, m_MaxCenterWidth); + float Roughness = m_Noise.IntNoise2DInRange(a_GridX + 20, a_GridZ, m_MinRoughness, m_MaxRoughness); + float FloorHeightEdge1 = m_Noise.IntNoise2DInRange(a_GridX + 30, a_GridZ, m_MinFloorHeightEdge, m_MaxFloorHeightEdge); + float FloorHeightEdge2 = m_Noise.IntNoise2DInRange(a_GridX + 40, a_GridZ, m_MinFloorHeightEdge, m_MaxFloorHeightEdge); + float FloorHeightCenter = m_Noise.IntNoise2DInRange(a_GridX + 50, a_GridZ, m_MinFloorHeightCenter, m_MaxFloorHeightCenter); + float CeilingHeightEdge1 = m_Noise.IntNoise2DInRange(a_GridX + 60, a_GridZ, m_MinCeilingHeightEdge, m_MaxCeilingHeightEdge); + float CeilingHeightEdge2 = m_Noise.IntNoise2DInRange(a_GridX + 70, a_GridZ, m_MinCeilingHeightEdge, m_MaxCeilingHeightEdge); + float CeilingHeightCenter = m_Noise.IntNoise2DInRange(a_GridX + 80, a_GridZ, m_MinCeilingHeightCenter, m_MaxCeilingHeightCenter); + + // Create a ravine: + return cStructurePtr(new cRoughRavine( + m_Seed, + Size, CenterWidth, Roughness, + FloorHeightEdge1, FloorHeightEdge2, FloorHeightCenter, + CeilingHeightEdge1, CeilingHeightEdge2, CeilingHeightCenter, + a_GridX, a_GridZ, a_OriginX, a_OriginZ + )); } diff --git a/src/Generating/RoughRavines.h b/src/Generating/RoughRavines.h index dce2f9ba7..4c905b641 100644 --- a/src/Generating/RoughRavines.h +++ b/src/Generating/RoughRavines.h @@ -24,7 +24,11 @@ public: int a_Seed, int a_MaxSize, int a_MinSize, float a_MaxCenterWidth, float a_MinCenterWidth, - float a_MaxRoughness, float a_MinRoughness, + float a_MaxRoughness, float a_MinRoughness, + float a_MaxFloorHeightEdge, float a_MinFloorHeightEdge, + float a_MaxFloorHeightCenter, float a_MinFloorHeightCenter, + float a_MaxCeilingHeightEdge, float a_MinCeilingHeightEdge, + float a_MaxCeilingHeightCenter, float a_MinCeilingHeightCenter, int a_GridSize, int a_MaxOffset ); @@ -49,6 +53,30 @@ protected: /** Minimum roughness of the ravine */ float m_MinRoughness; + /** Maximum floor height at the ravine's edge */ + float m_MaxFloorHeightEdge; + + /** Minimum floor height at the ravine's edge */ + float m_MinFloorHeightEdge; + + /** Maximum floor height at the ravine's center */ + float m_MaxFloorHeightCenter; + + /** Minimum floor height at the ravine's center */ + float m_MinFloorHeightCenter; + + /** Maximum ceiling height at the ravine's edge */ + float m_MaxCeilingHeightEdge; + + /** Minimum ceiling height at the ravine's edge */ + float m_MinCeilingHeightEdge; + + /** Maximum ceiling height at the ravine's center */ + float m_MaxCeilingHeightCenter; + + /** Minimum ceiling height at the ravine's center */ + float m_MinCeilingHeightCenter; + // cGridStructGen overrides: virtual cStructurePtr CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) override; }; diff --git a/src/Noise.h b/src/Noise.h index 48a1c73f7..e69e5cdad 100644 --- a/src/Noise.h +++ b/src/Noise.h @@ -33,6 +33,12 @@ public: INLINE NOISE_DATATYPE IntNoise2D(int a_X, int a_Y) const; INLINE NOISE_DATATYPE IntNoise3D(int a_X, int a_Y, int a_Z) const; + // Return a float number in the specified range: + INLINE NOISE_DATATYPE IntNoise2DInRange(int a_X, int a_Y, float a_Min, float a_Max) const + { + return a_Min + std::abs(IntNoise2D(a_X, a_Y)) * (a_Max - a_Min); + } + // Note: These functions have a mod8-irregular chance - each of the mod8 remainders has different chance of occurrence. Divide by 8 to rectify. INLINE int IntNoise1DInt(int a_X) const; INLINE int IntNoise2DInt(int a_X, int a_Y) const; -- cgit v1.2.3 From 579b80fd3a3b633e59034c0924459a860d611b27 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sun, 27 Jul 2014 20:08:33 +0200 Subject: Added a missing include for abs(float). --- src/Noise.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Noise.h b/src/Noise.h index e69e5cdad..4cf8d4ad8 100644 --- a/src/Noise.h +++ b/src/Noise.h @@ -5,6 +5,12 @@ #pragma once +#include + + + + + // Some settings #define NOISE_DATATYPE float -- cgit v1.2.3 From 9be92fa71df5620421c5f64cfa21cb6448a7686c Mon Sep 17 00:00:00 2001 From: Howaner Date: Sun, 27 Jul 2014 20:44:00 +0200 Subject: Use Color[0]. --- src/GroupManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GroupManager.cpp b/src/GroupManager.cpp index bc9bb67be..e03f8bca3 100644 --- a/src/GroupManager.cpp +++ b/src/GroupManager.cpp @@ -153,7 +153,7 @@ bool cGroupManager::LoadGroups() AString Color = IniFile.GetValue(KeyName, "Color", "-"); if ((Color != "-") && (Color.length() >= 1)) { - Group->SetColor(cChatColor::Delimiter + Color); + Group->SetColor(cChatColor::Delimiter + AString(&Color[0])); } else { -- cgit v1.2.3 From d61f1d0f4a1565d4de7e8100d9bf766d6fd458d1 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Sun, 27 Jul 2014 20:48:39 +0200 Subject: NetherClumpGenerator: Fixed generating stuff on halfslabs and fences --- src/Generating/FinishGen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index 03137f616..9f0c8f3fa 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -141,7 +141,7 @@ void cFinishGenNetherClumpFoliage::TryPlaceClump(cChunkDesc & a_ChunkDesc, int a } BLOCKTYPE BlockBelow = a_ChunkDesc.GetBlockType(x, y - 1, z); - if (!cBlockInfo::IsSolid(BlockBelow)) // Only place on solid blocks + if (!cBlockInfo::FullyOccupiesVoxel(BlockBelow)) // Only place on solid blocks { continue; } -- cgit v1.2.3 From 3d730403278bca630856ce7d275aed920aa20235 Mon Sep 17 00:00:00 2001 From: Howaner Date: Sun, 27 Jul 2014 21:14:45 +0200 Subject: Use AString(1, Color[0]) --- src/GroupManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GroupManager.cpp b/src/GroupManager.cpp index e03f8bca3..f1f86dc0f 100644 --- a/src/GroupManager.cpp +++ b/src/GroupManager.cpp @@ -153,7 +153,7 @@ bool cGroupManager::LoadGroups() AString Color = IniFile.GetValue(KeyName, "Color", "-"); if ((Color != "-") && (Color.length() >= 1)) { - Group->SetColor(cChatColor::Delimiter + AString(&Color[0])); + Group->SetColor(cChatColor::Delimiter + AString(1, Color[0])); } else { -- cgit v1.2.3 From 2bdc2701f4208f5a705fafceec3685a9834714a1 Mon Sep 17 00:00:00 2001 From: Howaner Date: Sun, 27 Jul 2014 21:58:00 +0200 Subject: Change Group->SetColor() again. --- src/GroupManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GroupManager.cpp b/src/GroupManager.cpp index f1f86dc0f..4c3dfc6f0 100644 --- a/src/GroupManager.cpp +++ b/src/GroupManager.cpp @@ -153,7 +153,7 @@ bool cGroupManager::LoadGroups() AString Color = IniFile.GetValue(KeyName, "Color", "-"); if ((Color != "-") && (Color.length() >= 1)) { - Group->SetColor(cChatColor::Delimiter + AString(1, Color[0])); + Group->SetColor(AString(cChatColor::Delimiter) + Color[0]); } else { -- cgit v1.2.3 From fd4ee20b2a927649b4671be95dccc8644c96e5ab Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sun, 27 Jul 2014 23:15:51 +0200 Subject: Hotfixed compilation problems. --- src/Items/ItemHandler.cpp | 2 +- src/Items/ItemSword.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Items/ItemHandler.cpp b/src/Items/ItemHandler.cpp index ec86648b3..d36b5d663 100644 --- a/src/Items/ItemHandler.cpp +++ b/src/Items/ItemHandler.cpp @@ -366,7 +366,7 @@ void cItemHandler::OnFoodEaten(cWorld * a_World, cPlayer * a_Player, cItem * a_I short cItemHandler::GetDurabilityLossByAction(eDurabilityLostAction a_Action) { - switch (a_Action) + switch ((int)a_Action) { case dlaAttackEntity: return 2; case dlaBreakBlock: return 1; diff --git a/src/Items/ItemSword.h b/src/Items/ItemSword.h index b90965535..2b2dbfc0d 100644 --- a/src/Items/ItemSword.h +++ b/src/Items/ItemSword.h @@ -46,7 +46,7 @@ public: virtual short GetDurabilityLossByAction(eDurabilityLostAction a_Action) override { - switch (a_Action) + switch ((int)a_Action) { case dlaAttackEntity: return 1; case dlaBreakBlock: return 2; -- cgit v1.2.3 From 5b69b2ce4faf5a14e6ab5d5974b790d2bd751a95 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Mon, 28 Jul 2014 12:30:16 +0200 Subject: DistortedHeightmap: Now generates gravel in deep ocean. --- src/Generating/DistortedHeightmap.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Generating/DistortedHeightmap.cpp b/src/Generating/DistortedHeightmap.cpp index 1337896ab..c18c402da 100644 --- a/src/Generating/DistortedHeightmap.cpp +++ b/src/Generating/DistortedHeightmap.cpp @@ -809,7 +809,7 @@ void cDistortedHeightmap::FillColumnPattern(cChunkDesc & a_ChunkDesc, int a_RelX } // Select the ocean-floor pattern to use: - a_Pattern = ChooseOceanFloorPattern(a_RelX, a_RelZ); + a_Pattern = a_ChunkDesc.GetBiome(a_RelX, a_RelZ) == biDeepOcean ? patGravel.Get() : ChooseOceanFloorPattern(a_RelX, a_RelZ); HasHadWater = true; } // for y a_ChunkDesc.SetBlockType(a_RelX, 0, a_RelZ, E_BLOCK_BEDROCK); -- cgit v1.2.3 From bf1aa7993202c2f57de88b068d999d262f1874f6 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Mon, 28 Jul 2014 14:23:29 +0200 Subject: Renamed cFinishGenSingleBiomeSingleTopBlock to cFinishGenSingleTopBlock Now accepts a vector of biomes and a vector of allowed blocks. --- src/Generating/ComposableGenerator.cpp | 31 +++++++++++++++++++-- src/Generating/FinishGen.cpp | 21 ++++++++------ src/Generating/FinishGen.h | 50 +++++++++++++++++++++++++++------- 3 files changed, 82 insertions(+), 20 deletions(-) diff --git a/src/Generating/ComposableGenerator.cpp b/src/Generating/ComposableGenerator.cpp index ab6accee7..ed1e7f6c1 100644 --- a/src/Generating/ComposableGenerator.cpp +++ b/src/Generating/ComposableGenerator.cpp @@ -323,7 +323,24 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile) } else if (NoCaseCompare(*itr, "DeadBushes") == 0) { - m_FinishGens.push_back(new cFinishGenSingleBiomeSingleTopBlock(Seed, E_BLOCK_DEAD_BUSH, biDesert, 2, E_BLOCK_SAND, E_BLOCK_SAND)); + // A list with all the allowed biomes. + cFinishGenSingleTopBlock::BiomeList AllowedBiomes; + AllowedBiomes.push_back(biDesert); + AllowedBiomes.push_back(biDesertHills); + AllowedBiomes.push_back(biDesertM); + AllowedBiomes.push_back(biMesa); + AllowedBiomes.push_back(biMesaBryce); + AllowedBiomes.push_back(biMesaPlateauF); + AllowedBiomes.push_back(biMesaPlateauFM); + AllowedBiomes.push_back(biMesaPlateauM); + + // A list with all the allowed blocks that can be below the lilypad. + cFinishGenSingleTopBlock::BlockList AllowedBlocks; + AllowedBlocks.push_back(E_BLOCK_SAND); + AllowedBlocks.push_back(E_BLOCK_HARDENED_CLAY); + AllowedBlocks.push_back(E_BLOCK_STAINED_CLAY); + + m_FinishGens.push_back(new cFinishGenSingleTopBlock(Seed, E_BLOCK_DEAD_BUSH, AllowedBiomes, 2, AllowedBlocks)); } else if (NoCaseCompare(*itr, "DirectOverhangs") == 0) { @@ -370,7 +387,17 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile) } else if (NoCaseCompare(*itr, "Lilypads") == 0) { - m_FinishGens.push_back(new cFinishGenSingleBiomeSingleTopBlock(Seed, E_BLOCK_LILY_PAD, biSwampland, 4, E_BLOCK_WATER, E_BLOCK_STATIONARY_WATER)); + // A list with all the allowed biomes. + cFinishGenSingleTopBlock::BiomeList AllowedBiomes; + AllowedBiomes.push_back(biSwampland); + AllowedBiomes.push_back(biSwamplandM); + + // A list with all the allowed blocks that can be below the lilypad. + cFinishGenSingleTopBlock::BlockList AllowedBlocks; + AllowedBlocks.push_back(E_BLOCK_WATER); + AllowedBlocks.push_back(E_BLOCK_STATIONARY_WATER); + + m_FinishGens.push_back(new cFinishGenSingleTopBlock(Seed, E_BLOCK_LILY_PAD, AllowedBiomes, 4, AllowedBlocks)); } else if (NoCaseCompare(*itr, "NetherClumpFoliage") == 0) { diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index 9f0c8f3fa..4c99c7f86 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -456,12 +456,12 @@ void cFinishGenIce::GenFinish(cChunkDesc & a_ChunkDesc) //////////////////////////////////////////////////////////////////////////////// // cFinishGenLilypads: -int cFinishGenSingleBiomeSingleTopBlock::GetNumToGen(const cChunkDef::BiomeMap & a_BiomeMap) +int cFinishGenSingleTopBlock::GetNumToGen(const cChunkDef::BiomeMap & a_BiomeMap) { int res = 0; for (size_t i = 0; i < ARRAYCOUNT(a_BiomeMap); i++) { - if (a_BiomeMap[i] == m_Biome) + if (IsAllowedBiome(a_BiomeMap[i])) { res++; } @@ -473,7 +473,7 @@ int cFinishGenSingleBiomeSingleTopBlock::GetNumToGen(const cChunkDef::BiomeMap & -void cFinishGenSingleBiomeSingleTopBlock::GenFinish(cChunkDesc & a_ChunkDesc) +void cFinishGenSingleTopBlock::GenFinish(cChunkDesc & a_ChunkDesc) { // Add Lilypads on top of water surface in Swampland @@ -486,11 +486,13 @@ void cFinishGenSingleBiomeSingleTopBlock::GenFinish(cChunkDesc & a_ChunkDesc) int z = (m_Noise.IntNoise3DInt(ChunkX - ChunkZ, i, ChunkZ) / 11) % cChunkDef::Width; // Place the block at {x, z} if possible: - if (a_ChunkDesc.GetBiome(x, z) != m_Biome) + EMCSBiome Biome = a_ChunkDesc.GetBiome(x, z); + if (!IsAllowedBiome(Biome)) { // Incorrect biome continue; } + int Height = a_ChunkDesc.GetHeight(x, z); if (Height >= cChunkDef::Height) { @@ -502,13 +504,16 @@ void cFinishGenSingleBiomeSingleTopBlock::GenFinish(cChunkDesc & a_ChunkDesc) // Not an empty block continue; } + BLOCKTYPE BlockBelow = a_ChunkDesc.GetBlockType(x, Height, z); - if ((BlockBelow == m_AllowedBelow1) || (BlockBelow == m_AllowedBelow2)) + if (!IsAllowedBlockBelow(BlockBelow)) { - a_ChunkDesc.SetBlockType(x, Height + 1, z, m_BlockType); - a_ChunkDesc.SetHeight(x, z, Height + 1); + continue; } - } // for i + + a_ChunkDesc.SetBlockType(x, Height + 1, z, m_BlockType); + a_ChunkDesc.SetHeight(x, z, Height + 1); + } } diff --git a/src/Generating/FinishGen.h b/src/Generating/FinishGen.h index 810bb4a91..1b885df88 100644 --- a/src/Generating/FinishGen.h +++ b/src/Generating/FinishGen.h @@ -143,32 +143,62 @@ Used for: - Lilypads finisher - DeadBushes finisher */ -class cFinishGenSingleBiomeSingleTopBlock : +class cFinishGenSingleTopBlock : public cFinishGen { public: - cFinishGenSingleBiomeSingleTopBlock( - int a_Seed, BLOCKTYPE a_BlockType, EMCSBiome a_Biome, int a_Amount, - BLOCKTYPE a_AllowedBelow1, BLOCKTYPE a_AllowedBelow2 + + typedef std::vector BlockList; + typedef std::vector BiomeList; + + cFinishGenSingleTopBlock( + int a_Seed, BLOCKTYPE a_BlockType, BiomeList a_Biomes, int a_Amount, + BlockList a_AllowedBelow ) : m_Noise(a_Seed), m_BlockType(a_BlockType), - m_Biome(a_Biome), + m_Biomes(a_Biomes), m_Amount(a_Amount), - m_AllowedBelow1(a_AllowedBelow1), - m_AllowedBelow2(a_AllowedBelow2) + m_AllowedBelow(a_AllowedBelow) { } protected: cNoise m_Noise; BLOCKTYPE m_BlockType; - EMCSBiome m_Biome; int m_Amount; ///< Relative amount of blocks to try adding. 1 = one block per 256 biome columns. - BLOCKTYPE m_AllowedBelow1; ///< First of the two blocktypes that are allowed below m_BlockType - BLOCKTYPE m_AllowedBelow2; ///< Second of the two blocktypes that are allowed below m_BlockType + + BlockList m_AllowedBelow; + BiomeList m_Biomes; int GetNumToGen(const cChunkDef::BiomeMap & a_BiomeMap); + + // Returns true if the given biome is a biome that is allowed. + bool IsAllowedBiome(EMCSBiome a_Biome) + { + for (BiomeList::iterator itr = m_Biomes.begin(); itr != m_Biomes.end(); ++itr) + { + if (a_Biome == *itr) + { + return true; + } + } + return false; + } + + // Returns true if the given blocktype may be below m_BlockType + bool IsAllowedBlockBelow(BLOCKTYPE a_BlockBelow) + { + for (BlockList::iterator itr = m_AllowedBelow.begin(); itr != m_AllowedBelow.end(); ++itr) + { + if (*itr == a_BlockBelow) + { + return true; + } + } + return false; + } + // cFinishGen override: virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; -- cgit v1.2.3 From 579f850506a1cc72f8f205f9e8c686f434e63023 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Mon, 28 Jul 2014 14:28:16 +0200 Subject: Forgot Mesa Plateau biome. --- src/Generating/ComposableGenerator.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Generating/ComposableGenerator.cpp b/src/Generating/ComposableGenerator.cpp index ed1e7f6c1..a8c1a842f 100644 --- a/src/Generating/ComposableGenerator.cpp +++ b/src/Generating/ComposableGenerator.cpp @@ -330,6 +330,7 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile) AllowedBiomes.push_back(biDesertM); AllowedBiomes.push_back(biMesa); AllowedBiomes.push_back(biMesaBryce); + AllowedBiomes.push_back(biMesaPlateau); AllowedBiomes.push_back(biMesaPlateauF); AllowedBiomes.push_back(biMesaPlateauFM); AllowedBiomes.push_back(biMesaPlateauM); -- cgit v1.2.3 From e74984675cf74f3a74d2694dda10802b158f734c Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Mon, 28 Jul 2014 16:53:01 +0200 Subject: Using suggestions --- src/Generating/FinishGen.h | 45 ++++++++++++++++++++------------------------- 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/src/Generating/FinishGen.h b/src/Generating/FinishGen.h index 1b885df88..a856b2cda 100644 --- a/src/Generating/FinishGen.h +++ b/src/Generating/FinishGen.h @@ -147,9 +147,12 @@ class cFinishGenSingleTopBlock : public cFinishGen { public: - typedef std::vector BlockList; + bool m_IsAllowedBelow[256]; + typedef std::vector BiomeList; + bool m_IsBiomeAllowed[256]; + cFinishGenSingleTopBlock( int a_Seed, BLOCKTYPE a_BlockType, BiomeList a_Biomes, int a_Amount, @@ -157,46 +160,38 @@ public: ) : m_Noise(a_Seed), m_BlockType(a_BlockType), - m_Biomes(a_Biomes), - m_Amount(a_Amount), - m_AllowedBelow(a_AllowedBelow) + m_Amount(a_Amount) { + // Load the allowed blocks into m_IsAllowedBelow + for (BlockList::iterator itr = a_AllowedBelow.begin(); itr != a_AllowedBelow.end(); ++itr) + { + m_IsAllowedBelow[*itr] = true; + } + + // Load the allowed biomes into m_IsBiomeAllowed + for (BiomeList::iterator itr = a_Biomes.begin(); itr != a_Biomes.end(); ++itr) + { + m_IsBiomeAllowed[*itr] = true; + } } protected: cNoise m_Noise; BLOCKTYPE m_BlockType; int m_Amount; ///< Relative amount of blocks to try adding. 1 = one block per 256 biome columns. - - BlockList m_AllowedBelow; - BiomeList m_Biomes; int GetNumToGen(const cChunkDef::BiomeMap & a_BiomeMap); // Returns true if the given biome is a biome that is allowed. - bool IsAllowedBiome(EMCSBiome a_Biome) + inline bool IsAllowedBiome(EMCSBiome a_Biome) { - for (BiomeList::iterator itr = m_Biomes.begin(); itr != m_Biomes.end(); ++itr) - { - if (a_Biome == *itr) - { - return true; - } - } - return false; + return m_IsBiomeAllowed[a_Biome]; } // Returns true if the given blocktype may be below m_BlockType - bool IsAllowedBlockBelow(BLOCKTYPE a_BlockBelow) + inline bool IsAllowedBlockBelow(BLOCKTYPE a_BlockBelow) { - for (BlockList::iterator itr = m_AllowedBelow.begin(); itr != m_AllowedBelow.end(); ++itr) - { - if (*itr == a_BlockBelow) - { - return true; - } - } - return false; + return m_IsAllowedBelow[a_BlockBelow]; } -- cgit v1.2.3 From 57bb03148af3ad2adf2e613cf11ec8bc1852e00e Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Tue, 29 Jul 2014 13:13:23 +0200 Subject: SingleTopBlock: All blocktypes and biometypes get initialized properly --- src/Generating/FinishGen.h | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/Generating/FinishGen.h b/src/Generating/FinishGen.h index a856b2cda..2500ab344 100644 --- a/src/Generating/FinishGen.h +++ b/src/Generating/FinishGen.h @@ -161,13 +161,25 @@ public: m_Noise(a_Seed), m_BlockType(a_BlockType), m_Amount(a_Amount) - { + { + // Initialize all the block types. + for (int idx = 0; idx < ARRAYCOUNT(m_IsAllowedBelow); ++idx) + { + m_IsAllowedBelow[idx] = false; + } + // Load the allowed blocks into m_IsAllowedBelow for (BlockList::iterator itr = a_AllowedBelow.begin(); itr != a_AllowedBelow.end(); ++itr) { m_IsAllowedBelow[*itr] = true; } - + + // Initialize all the biome types. + for (int idx = 0; idx < ARRAYCOUNT(m_IsBiomeAllowed); ++idx) + { + m_IsBiomeAllowed[idx] = false; + } + // Load the allowed biomes into m_IsBiomeAllowed for (BiomeList::iterator itr = a_Biomes.begin(); itr != a_Biomes.end(); ++itr) { -- cgit v1.2.3 From c8c01b055d49496f1e0ed340b816dfc57f9edd68 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Tue, 29 Jul 2014 15:24:11 +0200 Subject: Fixed comment above cFinishGenSingleTopBlock --- src/Generating/FinishGen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index 4c99c7f86..842c9ccc5 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -454,7 +454,7 @@ void cFinishGenIce::GenFinish(cChunkDesc & a_ChunkDesc) //////////////////////////////////////////////////////////////////////////////// -// cFinishGenLilypads: +// cFinishGenSingleTopBlock: int cFinishGenSingleTopBlock::GetNumToGen(const cChunkDef::BiomeMap & a_BiomeMap) { -- cgit v1.2.3 From 4ccf14f3b3f7deb19a32afd4253c506d5a224c54 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Tue, 29 Jul 2014 17:01:15 +0200 Subject: Some finishing touches Removed whitespace fixed dead bush comment --- src/Generating/ComposableGenerator.cpp | 2 +- src/Generating/FinishGen.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Generating/ComposableGenerator.cpp b/src/Generating/ComposableGenerator.cpp index a8c1a842f..5231b499f 100644 --- a/src/Generating/ComposableGenerator.cpp +++ b/src/Generating/ComposableGenerator.cpp @@ -335,7 +335,7 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile) AllowedBiomes.push_back(biMesaPlateauFM); AllowedBiomes.push_back(biMesaPlateauM); - // A list with all the allowed blocks that can be below the lilypad. + // A list with all the allowed blocks that can be below the dead bush. cFinishGenSingleTopBlock::BlockList AllowedBlocks; AllowedBlocks.push_back(E_BLOCK_SAND); AllowedBlocks.push_back(E_BLOCK_HARDENED_CLAY); diff --git a/src/Generating/FinishGen.h b/src/Generating/FinishGen.h index 2500ab344..ed32768b3 100644 --- a/src/Generating/FinishGen.h +++ b/src/Generating/FinishGen.h @@ -161,7 +161,7 @@ public: m_Noise(a_Seed), m_BlockType(a_BlockType), m_Amount(a_Amount) - { + { // Initialize all the block types. for (int idx = 0; idx < ARRAYCOUNT(m_IsAllowedBelow); ++idx) { -- cgit v1.2.3 From cb77b39dc6ff19698c504525259aa2c3170aadae Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 29 Jul 2014 16:36:24 +0100 Subject: Detrailed whitespace --- src/Entities/Entity.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index 261afd89d..da578013d 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -617,7 +617,7 @@ void cEntity::Tick(float a_Dt, cChunk & a_Chunk) // Handle drowning HandleAir(); - } + } if (!DetectPortal()) // Our chunk is invalid if we have moved to another world { @@ -1129,7 +1129,7 @@ bool cEntity::DetectPortal() cPlayer * Player = (cPlayer *)this; Player->TeleportToCoords(Player->GetLastBedPos().x, Player->GetLastBedPos().y, Player->GetLastBedPos().z); Player->GetClientHandle()->SendRespawn(dimOverworld); - } + } return MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedOverworldName()), false); } @@ -1146,7 +1146,7 @@ bool cEntity::DetectPortal() { ((cPlayer *)this)->AwardAchievement(achEnterTheEnd); ((cPlayer *)this)->GetClientHandle()->SendRespawn(dimEnd); - } + } return MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetEndWorldName(), dimEnd, GetWorld()->GetName()), false); } -- cgit v1.2.3 From 4f5d73b7704e351365a987b421c35f1384afa240 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 29 Jul 2014 20:50:30 +0100 Subject: Slight cleanup after portals --- src/Bindings/PluginManager.cpp | 8 +++----- src/ClientHandle.cpp | 3 +-- src/Entities/Player.cpp | 2 +- src/Generating/CompoGen.cpp | 2 +- src/World.cpp | 6 ++++-- src/World.h | 5 +++-- src/WorldStorage/NBTChunkSerializer.cpp | 1 - src/WorldStorage/WSSAnvil.cpp | 7 +------ 8 files changed, 14 insertions(+), 20 deletions(-) diff --git a/src/Bindings/PluginManager.cpp b/src/Bindings/PluginManager.cpp index 088b92a6d..3560b8660 100644 --- a/src/Bindings/PluginManager.cpp +++ b/src/Bindings/PluginManager.cpp @@ -476,11 +476,9 @@ bool cPluginManager::CallHookDisconnect(cClientHandle & a_Client, const AString bool cPluginManager::CallHookEntityAddEffect(cEntity & a_Entity, int a_EffectType, int a_EffectDurationTicks, int a_EffectIntensity, double a_DistanceModifier) { - HookMap::iterator Plugins = m_Hooks.find(HOOK_ENTITY_ADD_EFFECT); - if (Plugins == m_Hooks.end()) - { - return false; - } + FIND_HOOK(HOOK_ENTITY_ADD_EFFECT); + VERIFY_HOOK; + for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr) { if ((*itr)->OnEntityAddEffect(a_Entity, a_EffectType, a_EffectDurationTicks, a_EffectIntensity, a_DistanceModifier)) diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index aaed483e2..b390bf2d6 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -120,8 +120,7 @@ cClientHandle::~cClientHandle() } if (World != NULL) { - m_Player->SetWorldTravellingFrom(NULL); // Make sure that the player entity is actually removed - World->RemovePlayer(m_Player); // Must be called before cPlayer::Destroy() as otherwise cChunk tries to delete the player, and then we do it again + World->RemovePlayer(m_Player, true); // Must be called before cPlayer::Destroy() as otherwise cChunk tries to delete the player, and then we do it again m_Player->Destroy(); } delete m_Player; diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index ffdcca2ec..cf3322968 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -1627,7 +1627,7 @@ bool cPlayer::DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn) // Remove player from the old world SetWorldTravellingFrom(GetWorld()); // cChunk handles entity removal - GetWorld()->RemovePlayer(this); + GetWorld()->RemovePlayer(this, false); // Queue adding player to the new world, including all the necessary adjustments to the object a_World->AddPlayer(this); diff --git a/src/Generating/CompoGen.cpp b/src/Generating/CompoGen.cpp index 912d74248..178673e32 100644 --- a/src/Generating/CompoGen.cpp +++ b/src/Generating/CompoGen.cpp @@ -638,7 +638,7 @@ void cCompoGenNether::ComposeTerrain(cChunkDesc & a_ChunkDesc) CeilingDisguise = -CeilingDisguise; } - int CeilingDisguiseHeight = Height - 2 - CeilingDisguise * 3; + int CeilingDisguiseHeight = Height - 2 - (int)CeilingDisguise * 3; for (int y = Height - 1; y > CeilingDisguiseHeight; y--) { diff --git a/src/World.cpp b/src/World.cpp index 0b0f7870b..84c0f2b93 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -2465,10 +2465,12 @@ void cWorld::AddPlayer(cPlayer * a_Player) -void cWorld::RemovePlayer(cPlayer * a_Player) +void cWorld::RemovePlayer(cPlayer * a_Player, bool a_RemoveFromChunk) { - if (!a_Player->IsWorldTravellingFrom(this)) + if (a_RemoveFromChunk) { + // To prevent iterator invalidations when an entity goes through a portal and calls this function whilst being ticked by cChunk + // we should not change cChunk's entity list if asked not to m_ChunkMap->RemoveEntity(a_Player); } { diff --git a/src/World.h b/src/World.h index 4bf5a9d64..6649c4163 100644 --- a/src/World.h +++ b/src/World.h @@ -281,8 +281,9 @@ public: /** Removes the player from the world. Removes the player from the addition queue, too, if appropriate. - If the player has a ClientHandle, the ClientHandle is removed from all chunks in the world and will not be ticked by this world anymore. */ - void RemovePlayer(cPlayer * a_Player); + If the player has a ClientHandle, the ClientHandle is removed from all chunks in the world and will not be ticked by this world anymore. + @param a_RemoveFromChunk determines if the entity should be removed from its chunk as well. Should be false when ticking from cChunk. */ + void RemovePlayer(cPlayer * a_Player, bool a_RemoveFromChunk); /** Calls the callback for each player in the list; returns true if all players processed, false if the callback aborted by returning true */ virtual bool ForEachPlayer(cPlayerListCallback & a_Callback) override; // >> EXPORTED IN MANUALBINDINGS << diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp index b7a3d40ce..4857da1b6 100644 --- a/src/WorldStorage/NBTChunkSerializer.cpp +++ b/src/WorldStorage/NBTChunkSerializer.cpp @@ -486,7 +486,6 @@ void cNBTChunkSerializer::AddMonsterEntity(cMonster * a_Monster) m_Writer.AddFloat("", a_Monster->GetDropChanceBoots()); m_Writer.EndList(); m_Writer.AddByte("CanPickUpLoot", (char)a_Monster->CanPickUpLoot()); - m_Writer.AddShort("Health", (short)a_Monster->GetHealth()); switch (a_Monster->GetMobType()) { case cMonster::mtBat: diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp index 6134e2c0a..71ff3ef99 100644 --- a/src/WorldStorage/WSSAnvil.cpp +++ b/src/WorldStorage/WSSAnvil.cpp @@ -2475,10 +2475,7 @@ bool cWSSAnvil::LoadEntityBaseFromNBT(cEntity & a_Entity, const cParsedNBT & a_N // Load health: int Health = a_NBT.FindChildByName(a_TagIdx, "Health"); - if (Health > 0) - { - a_Entity.SetHealth(a_NBT.GetShort(Health)); - } + a_Entity.SetHealth(Health > 0 ? a_NBT.GetShort(Health) : a_Entity.GetMaxHealth()); return true; } @@ -2507,8 +2504,6 @@ bool cWSSAnvil::LoadMonsterBaseFromNBT(cMonster & a_Monster, const cParsedNBT & a_Monster.SetCanPickUpLoot(CanPickUpLoot); } - int HealthTag = a_NBT.FindChildByName(a_TagIdx, "Health"); - a_Monster.SetHealth(HealthTag > 0 ? a_NBT.GetShort(HealthTag) : a_Monster.GetMaxHealth()); return true; } -- cgit v1.2.3 From adae2b70b1733a280fe342ca6d0dca7e37301f4f Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Tue, 29 Jul 2014 22:31:31 +0200 Subject: Added cBlockInfo::CanBeTerraformed and made finishers use it I might have forgotten some of them though --- src/BlockInfo.cpp | 21 +++++++++++++++++++++ src/BlockInfo.h | 4 ++++ src/Generating/Caves.cpp | 24 ++---------------------- src/Generating/RoughRavines.cpp | 26 ++++---------------------- 4 files changed, 31 insertions(+), 44 deletions(-) diff --git a/src/BlockInfo.cpp b/src/BlockInfo.cpp index 602deb26d..311a53c42 100644 --- a/src/BlockInfo.cpp +++ b/src/BlockInfo.cpp @@ -17,6 +17,7 @@ cBlockInfo::cBlockInfo() , m_IsSnowable(false) , m_IsSolid(true) , m_FullyOccupiesVoxel(false) + , m_CanBeTerraformed(false) , m_Handler(NULL) {} @@ -548,6 +549,26 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info) a_Info[E_BLOCK_STONE ].m_FullyOccupiesVoxel = true; a_Info[E_BLOCK_STONE_BRICKS ].m_FullyOccupiesVoxel = true; a_Info[E_BLOCK_WOOL ].m_FullyOccupiesVoxel = true; + + + // Blocks that can be terraformed + a_Info[E_BLOCK_COAL_ORE ].m_CanBeTerraformed = true; + a_Info[E_BLOCK_COBBLESTONE ].m_CanBeTerraformed = true; + a_Info[E_BLOCK_DIAMOND_ORE ].m_CanBeTerraformed = true; + a_Info[E_BLOCK_DIRT ].m_CanBeTerraformed = true; + a_Info[E_BLOCK_GOLD_ORE ].m_CanBeTerraformed = true; + a_Info[E_BLOCK_GRASS ].m_CanBeTerraformed = true; + a_Info[E_BLOCK_GRAVEL ].m_CanBeTerraformed = true; + a_Info[E_BLOCK_HARDENED_CLAY ].m_CanBeTerraformed = true; + a_Info[E_BLOCK_IRON_ORE ].m_CanBeTerraformed = true; + a_Info[E_BLOCK_MYCELIUM ].m_CanBeTerraformed = true; + a_Info[E_BLOCK_NETHERRACK ].m_CanBeTerraformed = true; + a_Info[E_BLOCK_REDSTONE_ORE ].m_CanBeTerraformed = true; + a_Info[E_BLOCK_REDSTONE_ORE_GLOWING].m_CanBeTerraformed = true; + a_Info[E_BLOCK_SAND ].m_CanBeTerraformed = true; + a_Info[E_BLOCK_SANDSTONE ].m_CanBeTerraformed = true; + a_Info[E_BLOCK_STAINED_CLAY ].m_CanBeTerraformed = true; + a_Info[E_BLOCK_STONE ].m_CanBeTerraformed = true; } diff --git a/src/BlockInfo.h b/src/BlockInfo.h index e6ce566c5..4c66c095a 100644 --- a/src/BlockInfo.h +++ b/src/BlockInfo.h @@ -45,6 +45,9 @@ public: /** Does this block fully occupy its voxel - is it a 'full' block? */ bool m_FullyOccupiesVoxel; + /** Can a finisher change it? */ + bool m_CanBeTerraformed; + // tolua_end /** Associated block handler. */ @@ -60,6 +63,7 @@ public: inline static bool IsSnowable (BLOCKTYPE a_Type) { return Get(a_Type).m_IsSnowable; } inline static bool IsSolid (BLOCKTYPE a_Type) { return Get(a_Type).m_IsSolid; } inline static bool FullyOccupiesVoxel (BLOCKTYPE a_Type) { return Get(a_Type).m_FullyOccupiesVoxel; } + inline static bool CanBeTerraformed (BLOCKTYPE a_Type) { return Get(a_Type).m_CanBeTerraformed; } // tolua_end diff --git a/src/Generating/Caves.cpp b/src/Generating/Caves.cpp index 3b71efb57..6fc371958 100644 --- a/src/Generating/Caves.cpp +++ b/src/Generating/Caves.cpp @@ -497,29 +497,9 @@ void cCaveTunnel::ProcessChunk( int SqDist = (DifX - x) * (DifX - x) + (DifY - y) * (DifY - y) + (DifZ - z) * (DifZ - z); if (4 * SqDist <= SqRad) { - switch (cChunkDef::GetBlock(a_BlockTypes, x, y, z)) + if (cBlockInfo::CanBeTerraformed(cChunkDef::GetBlock(a_BlockTypes, x, y, z))) { - // Only carve out these specific block types - case E_BLOCK_DIRT: - case E_BLOCK_GRASS: - case E_BLOCK_STONE: - case E_BLOCK_COBBLESTONE: - case E_BLOCK_GRAVEL: - case E_BLOCK_SAND: - case E_BLOCK_SANDSTONE: - case E_BLOCK_SOULSAND: - case E_BLOCK_NETHERRACK: - case E_BLOCK_COAL_ORE: - case E_BLOCK_IRON_ORE: - case E_BLOCK_GOLD_ORE: - case E_BLOCK_DIAMOND_ORE: - case E_BLOCK_REDSTONE_ORE: - case E_BLOCK_REDSTONE_ORE_GLOWING: - { - cChunkDef::SetBlock(a_BlockTypes, x, y, z, E_BLOCK_AIR); - break; - } - default: break; + cChunkDef::SetBlock(a_BlockTypes, x, y, z, E_BLOCK_AIR); } } } // for y diff --git a/src/Generating/RoughRavines.cpp b/src/Generating/RoughRavines.cpp index badc7768e..2ee3704b3 100644 --- a/src/Generating/RoughRavines.cpp +++ b/src/Generating/RoughRavines.cpp @@ -201,29 +201,11 @@ protected: { continue; } - switch (a_ChunkDesc.GetBlockType(x, y, z)) + + if (cBlockInfo::CanBeTerraformed(a_ChunkDesc.GetBlockType(x, y, z))) { - // Only carve out these specific block types - case E_BLOCK_DIRT: - case E_BLOCK_GRASS: - case E_BLOCK_STONE: - case E_BLOCK_COBBLESTONE: - case E_BLOCK_GRAVEL: - case E_BLOCK_SAND: - case E_BLOCK_SANDSTONE: - case E_BLOCK_NETHERRACK: - case E_BLOCK_COAL_ORE: - case E_BLOCK_IRON_ORE: - case E_BLOCK_GOLD_ORE: - case E_BLOCK_DIAMOND_ORE: - case E_BLOCK_REDSTONE_ORE: - case E_BLOCK_REDSTONE_ORE_GLOWING: - { - a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_AIR); - break; - } - default: break; - } // switch (BlockType) + a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_AIR); + } } // for y } // for x, z - a_BlockTypes } // for itr - m_Points[] -- cgit v1.2.3 From 931443ac67cefade2ebd0d29fd65a49d22293ea2 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Tue, 29 Jul 2014 22:40:40 +0200 Subject: Added soulsand to the terraformed list. --- src/BlockInfo.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/BlockInfo.cpp b/src/BlockInfo.cpp index 311a53c42..4bc3fbbdc 100644 --- a/src/BlockInfo.cpp +++ b/src/BlockInfo.cpp @@ -567,6 +567,7 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info) a_Info[E_BLOCK_REDSTONE_ORE_GLOWING].m_CanBeTerraformed = true; a_Info[E_BLOCK_SAND ].m_CanBeTerraformed = true; a_Info[E_BLOCK_SANDSTONE ].m_CanBeTerraformed = true; + a_Info[E_BLOCK_SOULSAND ].m_CanBeTerraformed = true; a_Info[E_BLOCK_STAINED_CLAY ].m_CanBeTerraformed = true; a_Info[E_BLOCK_STONE ].m_CanBeTerraformed = true; } -- cgit v1.2.3 From 9a4d80fc3b9dbaa09c8e6d9e8021762a486f280f Mon Sep 17 00:00:00 2001 From: Howaner Date: Wed, 30 Jul 2014 00:45:03 +0200 Subject: Fixed compile error with clang. --- src/Generating/FinishGen.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Generating/FinishGen.h b/src/Generating/FinishGen.h index ed32768b3..cf84a0336 100644 --- a/src/Generating/FinishGen.h +++ b/src/Generating/FinishGen.h @@ -163,7 +163,7 @@ public: m_Amount(a_Amount) { // Initialize all the block types. - for (int idx = 0; idx < ARRAYCOUNT(m_IsAllowedBelow); ++idx) + for (size_t idx = 0; idx < (size_t)ARRAYCOUNT(m_IsAllowedBelow); ++idx) { m_IsAllowedBelow[idx] = false; } @@ -175,7 +175,7 @@ public: } // Initialize all the biome types. - for (int idx = 0; idx < ARRAYCOUNT(m_IsBiomeAllowed); ++idx) + for (size_t idx = 0; idx < (size_t)ARRAYCOUNT(m_IsBiomeAllowed); ++idx) { m_IsBiomeAllowed[idx] = false; } -- cgit v1.2.3 From 438e4088d6a38f9904a36f2e1a358965d9fb4a26 Mon Sep 17 00:00:00 2001 From: Howaner Date: Wed, 30 Jul 2014 01:22:51 +0200 Subject: Changed size_t to 'unsigned long' --- src/Generating/FinishGen.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Generating/FinishGen.h b/src/Generating/FinishGen.h index cf84a0336..7171036e2 100644 --- a/src/Generating/FinishGen.h +++ b/src/Generating/FinishGen.h @@ -163,7 +163,7 @@ public: m_Amount(a_Amount) { // Initialize all the block types. - for (size_t idx = 0; idx < (size_t)ARRAYCOUNT(m_IsAllowedBelow); ++idx) + for (unsigned long idx = 0; idx < ARRAYCOUNT(m_IsAllowedBelow); ++idx) { m_IsAllowedBelow[idx] = false; } @@ -175,7 +175,7 @@ public: } // Initialize all the biome types. - for (size_t idx = 0; idx < (size_t)ARRAYCOUNT(m_IsBiomeAllowed); ++idx) + for (unsigned long idx = 0; idx < ARRAYCOUNT(m_IsBiomeAllowed); ++idx) { m_IsBiomeAllowed[idx] = false; } -- cgit v1.2.3 From 487c57242964ef4a86fc4f41c1c538d9df9ec892 Mon Sep 17 00:00:00 2001 From: archshift Date: Tue, 29 Jul 2014 19:14:56 -0700 Subject: Entity.h: Moved constants out of some unnamed enum --- src/Entities/Entity.h | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h index e66194ca2..b9c280b6b 100644 --- a/src/Entities/Entity.h +++ b/src/Entities/Entity.h @@ -128,20 +128,20 @@ public: esFireworkExploding = 17, } ; - enum - { - FIRE_TICKS_PER_DAMAGE = 10, ///< How many ticks to wait between damaging an entity when it stands in fire - FIRE_DAMAGE = 1, ///< How much damage to deal when standing in fire - LAVA_TICKS_PER_DAMAGE = 10, ///< How many ticks to wait between damaging an entity when it stands in lava - LAVA_DAMAGE = 5, ///< How much damage to deal when standing in lava - BURN_TICKS_PER_DAMAGE = 20, ///< How many ticks to wait between damaging an entity when it is burning - BURN_DAMAGE = 1, ///< How much damage to deal when the entity is burning - BURN_TICKS = 200, ///< How long to keep an entity burning after it has stood in lava / fire - MAX_AIR_LEVEL = 300, ///< Maximum air an entity can have - DROWNING_TICKS = 20, ///< Number of ticks per heart of damage - VOID_BOUNDARY = -46, ///< At what position Y to begin applying void damage - FALL_DAMAGE_HEIGHT = 4 ///< At what position Y fall damage is applied - } ; + static const int FIRE_TICKS_PER_DAMAGE = 10; ///< Ticks to wait between damaging an entity when it stands in fire + static const int FIRE_DAMAGE = 1; ///< Damage to deal when standing in fire + static const int LAVA_TICKS_PER_DAMAGE = 10; ///< Ticks to wait between damaging an entity when it stands in lava + static const int LAVA_DAMAGE = 5; ///< Damage to deal when standing in lava + static const int BURN_TICKS_PER_DAMAGE = 20; ///< Ticks to wait between damaging an entity when it is burning + static const int BURN_DAMAGE = 1; ///< Damage to deal when the entity is burning + + static const int BURN_TICKS = 200; ///< Ticks to keep an entity burning after it has stood in lava / fire + + static const int MAX_AIR_LEVEL = 300; ///< Maximum air an entity can have + static const int DROWNING_TICKS = 20; ///< Number of ticks per heart of damage + + static const int VOID_BOUNDARY = -46; ///< Y position to begin applying void damage + static const int FALL_DAMAGE_HEIGHT = 4; ///< Y difference after which fall damage is applied cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, double a_Width, double a_Height); virtual ~cEntity(); -- cgit v1.2.3 From 7022ae79886a9f90f30ff54387702d406b723837 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Wed, 30 Jul 2014 07:08:29 +0200 Subject: Fixed FinishGen.h types. --- src/Generating/FinishGen.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Generating/FinishGen.h b/src/Generating/FinishGen.h index 7171036e2..50a0fd2e7 100644 --- a/src/Generating/FinishGen.h +++ b/src/Generating/FinishGen.h @@ -163,7 +163,7 @@ public: m_Amount(a_Amount) { // Initialize all the block types. - for (unsigned long idx = 0; idx < ARRAYCOUNT(m_IsAllowedBelow); ++idx) + for (size_t idx = 0; idx < ARRAYCOUNT(m_IsAllowedBelow); ++idx) { m_IsAllowedBelow[idx] = false; } @@ -175,7 +175,7 @@ public: } // Initialize all the biome types. - for (unsigned long idx = 0; idx < ARRAYCOUNT(m_IsBiomeAllowed); ++idx) + for (size_t idx = 0; idx < ARRAYCOUNT(m_IsBiomeAllowed); ++idx) { m_IsBiomeAllowed[idx] = false; } -- cgit v1.2.3 From 1d684697186de4340c6a1cc5aea6a14ffd19c002 Mon Sep 17 00:00:00 2001 From: archshift Date: Tue, 29 Jul 2014 22:43:25 -0700 Subject: Fixed "Dependency" typos --- .gitignore | 2 +- src/Bindings/CMakeLists.txt | 4 ++-- src/CMakeLists.txt | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index 51987336c..a4cbef72f 100644 --- a/.gitignore +++ b/.gitignore @@ -64,7 +64,7 @@ install_mainfest.txt src/MCServer lib/tolua++/tolua src/Bindings/Bindings.* -src/Bindings/BindingDependecies.txt +src/Bindings/BindingDependencies.txt MCServer.dir/ src/AllFiles.lst diff --git a/src/Bindings/CMakeLists.txt b/src/Bindings/CMakeLists.txt index 2ea2fa8c0..48e7ce79c 100644 --- a/src/Bindings/CMakeLists.txt +++ b/src/Bindings/CMakeLists.txt @@ -125,8 +125,8 @@ if (NOT MSVC) DEPENDS ${BINDING_DEPENDENCIES} ) endif () -set_source_files_properties(Bindings/Bindings.cpp PROPERTIES GENERATED TRUE) -set_source_files_properties(Bindings/Bindings.h PROPERTIES GENERATED TRUE) +set_source_files_properties(${CMAKE_SOURCE_DIR}/src/Bindings/Bindings.cpp PROPERTIES GENERATED TRUE) +set_source_files_properties(${CMAKE_SOURCE_DIR}/src/Bindings/Bindings.h PROPERTIES GENERATED TRUE) if(NOT MSVC) add_library(Bindings ${SRCS} ${HDRS}) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 29337cb2e..87599c60d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -151,10 +151,10 @@ if (NOT MSVC) get_directory_property(BINDING_DEPENDENCIES DIRECTORY "Bindings" DEFINITION BINDING_DEPENDENCIES) #clear file - file(WRITE ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/BindingDependecies.txt) - foreach(dependecy ${BINDING_DEPENDECIES}) - #write each dependecy on a seperate line - file(APPEND ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/BindingDependecies.txt "${dependecy}\n") + file(WRITE ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/BindingDependencies.txt) + foreach(dependency ${BINDING_DEPENDENCIES}) + #write each dependency on a seperate line + file(APPEND ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/BindingDependencies.txt "${dependency}\n") endforeach() set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "Bindings.cpp Bindings.h") -- cgit v1.2.3 From 75b7c3775528ced647eb5d7db3437d2856e01e7e Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Wed, 30 Jul 2014 13:06:48 +0200 Subject: PreSimulator: Added configurations. You can now choose if it should pregenerate something or not --- src/Generating/ComposableGenerator.cpp | 7 ++++++- src/Generating/FinishGen.cpp | 22 ++++++++++++++++++---- src/Generating/FinishGen.h | 7 ++++++- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/Generating/ComposableGenerator.cpp b/src/Generating/ComposableGenerator.cpp index a7659149a..cedb9aeb7 100644 --- a/src/Generating/ComposableGenerator.cpp +++ b/src/Generating/ComposableGenerator.cpp @@ -408,7 +408,12 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile) } else if (NoCaseCompare(*itr, "PreSimulator") == 0) { - m_FinishGens.push_back(new cFinishGenPreSimulator); + // Load the settings + bool PreSimulateFallingBlocks = a_IniFile.GetValueSetB("Generator", "PreSimulatorFallingBlocks", true); + bool PreSimulateWater = a_IniFile.GetValueSetB("Generator", "PreSimulatorWater", true); + bool PreSimulateLava = a_IniFile.GetValueSetB("Generator", "PreSimulatorLava", true); + + m_FinishGens.push_back(new cFinishGenPreSimulator(PreSimulateFallingBlocks, PreSimulateWater, PreSimulateLava)); } else if (NoCaseCompare(*itr, "RainbowRoads") == 0) { diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index f53addb68..e8324095e 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -555,7 +555,10 @@ void cFinishGenBottomLava::GenFinish(cChunkDesc & a_ChunkDesc) //////////////////////////////////////////////////////////////////////////////// // cFinishGenPreSimulator: -cFinishGenPreSimulator::cFinishGenPreSimulator(void) +cFinishGenPreSimulator::cFinishGenPreSimulator(bool a_PreSimulateFallingBlocks, bool a_PreSimulateWater, bool a_PreSimulateLava) : + m_PreSimulateFallingBlocks(a_PreSimulateFallingBlocks), + m_PreSimulateWater(a_PreSimulateWater), + m_PreSimulateLava(a_PreSimulateLava) { // Nothing needed yet } @@ -566,9 +569,20 @@ cFinishGenPreSimulator::cFinishGenPreSimulator(void) void cFinishGenPreSimulator::GenFinish(cChunkDesc & a_ChunkDesc) { - CollapseSandGravel(a_ChunkDesc.GetBlockTypes(), a_ChunkDesc.GetHeightMap()); - StationarizeFluid(a_ChunkDesc.GetBlockTypes(), a_ChunkDesc.GetHeightMap(), E_BLOCK_WATER, E_BLOCK_STATIONARY_WATER); - StationarizeFluid(a_ChunkDesc.GetBlockTypes(), a_ChunkDesc.GetHeightMap(), E_BLOCK_LAVA, E_BLOCK_STATIONARY_LAVA); + if (m_PreSimulateFallingBlocks) + { + CollapseSandGravel(a_ChunkDesc.GetBlockTypes(), a_ChunkDesc.GetHeightMap()); + } + + if (m_PreSimulateWater) + { + StationarizeFluid(a_ChunkDesc.GetBlockTypes(), a_ChunkDesc.GetHeightMap(), E_BLOCK_WATER, E_BLOCK_STATIONARY_WATER); + } + + if (m_PreSimulateLava) + { + StationarizeFluid(a_ChunkDesc.GetBlockTypes(), a_ChunkDesc.GetHeightMap(), E_BLOCK_LAVA, E_BLOCK_STATIONARY_LAVA); + } // TODO: other operations } diff --git a/src/Generating/FinishGen.h b/src/Generating/FinishGen.h index 50a0fd2e7..4a08d70c8 100644 --- a/src/Generating/FinishGen.h +++ b/src/Generating/FinishGen.h @@ -240,9 +240,14 @@ class cFinishGenPreSimulator : public cFinishGen { public: - cFinishGenPreSimulator(void); + cFinishGenPreSimulator(bool a_PreSimulateFallingBlocks, bool a_PreSimulateWater, bool a_PreSimulateLava); protected: + + bool m_PreSimulateFallingBlocks; + bool m_PreSimulateWater; + bool m_PreSimulateLava; + // Drops hanging sand and gravel down to the ground, recalculates heightmap void CollapseSandGravel( cChunkDef::BlockTypes & a_BlockTypes, // Block types to read and change -- cgit v1.2.3 From 5249f574bd077158836455fa66218e5fea6dcafe Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Wed, 30 Jul 2014 15:55:50 +0200 Subject: Added RoofedForest trees. Could still be improved allot. --- src/Generating/Trees.cpp | 73 ++++++++++++++++++++++++++++++++++++++++++++++-- src/Generating/Trees.h | 2 ++ 2 files changed, 73 insertions(+), 2 deletions(-) diff --git a/src/Generating/Trees.cpp b/src/Generating/Trees.cpp index c40322630..87405608b 100644 --- a/src/Generating/Trees.cpp +++ b/src/Generating/Trees.cpp @@ -218,7 +218,6 @@ void GetTreeImageByBiome(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_No return; } - case biRoofedForest: case biColdTaiga: case biColdTaigaHills: case biMegaTaiga: @@ -238,7 +237,6 @@ void GetTreeImageByBiome(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_No case biIcePlainsSpikes: case biJungleM: case biJungleEdgeM: - case biRoofedForestM: case biColdTaigaM: case biMegaSpruceTaiga: case biMegaSpruceTaigaHills: @@ -253,6 +251,13 @@ void GetTreeImageByBiome(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_No GetBirchTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); return; } + + case biRoofedForest: + case biRoofedForestM: + { + GetRoofedForestTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); + return; + } case biDesert: case biDesertHills: @@ -807,3 +812,67 @@ void GetSmallJungleTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & + +void GetRoofedForestTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks) +{ + // Calculate a height + int Height = 5 + (a_Noise.IntNoise3DInt(a_BlockX + 32 * a_Seq, a_BlockY, a_BlockZ + 32 * a_Seq) / 11) % 4; + + // Creat the trunk + for (int i = 0; i < Height; i++) + { + a_LogBlocks.push_back(sSetBlock(a_BlockX, a_BlockY + i, a_BlockZ, E_BLOCK_NEW_LOG, E_META_NEW_LOG_DARK_OAK_WOOD)); + a_LogBlocks.push_back(sSetBlock(a_BlockX + 1, a_BlockY + i, a_BlockZ, E_BLOCK_NEW_LOG, E_META_NEW_LOG_DARK_OAK_WOOD)); + a_LogBlocks.push_back(sSetBlock(a_BlockX, a_BlockY + i, a_BlockZ + 1, E_BLOCK_NEW_LOG, E_META_NEW_LOG_DARK_OAK_WOOD)); + a_LogBlocks.push_back(sSetBlock(a_BlockX + 1, a_BlockY + i, a_BlockZ + 1, E_BLOCK_NEW_LOG, E_META_NEW_LOG_DARK_OAK_WOOD)); + } + + // Create branches + for (int i = 0; i < 3; i++) + { + //int x = (a_Noise.IntNoise3D(a_BlockX + 32 * a_Seq, a_BlockY * i, a_BlockZ + 32 * a_Seq) < 0 ? -1 : 2); + //int z = (a_Noise.IntNoise3D(a_BlockX - 32 * a_Seq, a_BlockY * i, a_BlockZ - 32 * a_Seq) < 0 ? -1 : 2); + int x = (a_Noise.IntNoise3DInt(a_BlockX + 32 * a_Seq, a_BlockY * i, a_BlockZ + 32 * a_Seq) % 3) - 1; + int z = (a_Noise.IntNoise3DInt(a_BlockX - 32 * a_Seq, a_BlockY * i, a_BlockZ - 32 * a_Seq) % 3) - 1; + + // The branches would end up in the trunk. + if ((x >= a_BlockX) && (x <= a_BlockX + 1) && (z >= a_BlockZ) && (z <= a_BlockZ + 1)) + { + NOISE_DATATYPE Val1 = a_Noise.IntNoise2D(x, z); + if (Val1 < 0) + { + x = a_BlockX + (Val1 < -0.5) ? -1 : 3; + } + else + { + z = a_BlockZ + (Val1 < 0.5) ? -1 : 3; + } + } + + int y = Height - (a_Noise.IntNoise3DInt(a_BlockX + x, a_BlockY * i, a_BlockZ - z) % (Height - (Height / 4))); + + for (int Y = y; Y < Height; Y++) + { + a_LogBlocks.push_back(sSetBlock(a_BlockX + x, a_BlockY + Y, a_BlockZ + z, E_BLOCK_NEW_LOG, E_META_NEW_LOG_DARK_OAK_WOOD)); + } + } + + int hei = a_BlockY + Height - 2; + + // The lower two leaves layers are BigO4 with log in the middle and possibly corners: + for (int i = 0; i < 2; i++) + { + PushCoordBlocks(a_BlockX, hei, a_BlockZ, a_OtherBlocks, BigO4, ARRAYCOUNT(BigO4), E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_DARK_OAK_WOOD); + PushCornerBlocks(a_BlockX, hei, a_BlockZ, a_Seq, a_Noise, 0x5fffffff, a_OtherBlocks, 3, E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_DARK_OAK_WOOD); + hei++; + } // for i - 2* + + // The top leaves layer is a BigO3 with leaves in the middle and possibly corners: + PushCoordBlocks(a_BlockX, hei, a_BlockZ, a_OtherBlocks, BigO3, ARRAYCOUNT(BigO3), E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_DARK_OAK_WOOD); + PushCornerBlocks(a_BlockX, hei, a_BlockZ, a_Seq, a_Noise, 0x5fffffff, a_OtherBlocks, 3, E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_DARK_OAK_WOOD); + a_OtherBlocks.push_back(sSetBlock(a_BlockX, hei, a_BlockZ, E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_DARK_OAK_WOOD)); +} + + + + diff --git a/src/Generating/Trees.h b/src/Generating/Trees.h index 1f6ac4dff..2b2e0acc3 100644 --- a/src/Generating/Trees.h +++ b/src/Generating/Trees.h @@ -96,6 +96,8 @@ void GetLargeJungleTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & /// Generates an image of a small jungle tree (1x1 trunk) void GetSmallJungleTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks); +/// Generates an image of a roofed tree forest tree +void GetRoofedForestTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks); -- cgit v1.2.3 From 17b679f355b8a63175815418983662c17ee13686 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Wed, 30 Jul 2014 17:09:00 +0200 Subject: Fixed compiling using Clang --- src/Generating/Trees.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Generating/Trees.cpp b/src/Generating/Trees.cpp index 87405608b..fb46a5e3b 100644 --- a/src/Generating/Trees.cpp +++ b/src/Generating/Trees.cpp @@ -830,8 +830,6 @@ void GetRoofedForestTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & // Create branches for (int i = 0; i < 3; i++) { - //int x = (a_Noise.IntNoise3D(a_BlockX + 32 * a_Seq, a_BlockY * i, a_BlockZ + 32 * a_Seq) < 0 ? -1 : 2); - //int z = (a_Noise.IntNoise3D(a_BlockX - 32 * a_Seq, a_BlockY * i, a_BlockZ - 32 * a_Seq) < 0 ? -1 : 2); int x = (a_Noise.IntNoise3DInt(a_BlockX + 32 * a_Seq, a_BlockY * i, a_BlockZ + 32 * a_Seq) % 3) - 1; int z = (a_Noise.IntNoise3DInt(a_BlockX - 32 * a_Seq, a_BlockY * i, a_BlockZ - 32 * a_Seq) % 3) - 1; @@ -841,11 +839,11 @@ void GetRoofedForestTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & NOISE_DATATYPE Val1 = a_Noise.IntNoise2D(x, z); if (Val1 < 0) { - x = a_BlockX + (Val1 < -0.5) ? -1 : 3; + x = a_BlockX + ((Val1 < -0.5) ? -1 : 3); } else { - z = a_BlockZ + (Val1 < 0.5) ? -1 : 3; + z = a_BlockZ + ((Val1 < 0.5) ? -1 : 3); } } -- cgit v1.2.3 From fd2d338a252a4c230e54e25a8695d7084a924bbe Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Wed, 30 Jul 2014 21:42:48 +0200 Subject: Fixed comment at the end of a for-loop --- src/Generating/Trees.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Generating/Trees.cpp b/src/Generating/Trees.cpp index fb46a5e3b..308947ad0 100644 --- a/src/Generating/Trees.cpp +++ b/src/Generating/Trees.cpp @@ -863,7 +863,7 @@ void GetRoofedForestTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & PushCoordBlocks(a_BlockX, hei, a_BlockZ, a_OtherBlocks, BigO4, ARRAYCOUNT(BigO4), E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_DARK_OAK_WOOD); PushCornerBlocks(a_BlockX, hei, a_BlockZ, a_Seq, a_Noise, 0x5fffffff, a_OtherBlocks, 3, E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_DARK_OAK_WOOD); hei++; - } // for i - 2* + } // for i < 2 // The top leaves layer is a BigO3 with leaves in the middle and possibly corners: PushCoordBlocks(a_BlockX, hei, a_BlockZ, a_OtherBlocks, BigO3, ARRAYCOUNT(BigO3), E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_DARK_OAK_WOOD); -- cgit v1.2.3 From f232ef5cd606d31068a758b3e784f33ca1860af0 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Wed, 30 Jul 2014 21:50:02 +0200 Subject: Fixed doxy comment --- src/Generating/Trees.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Generating/Trees.h b/src/Generating/Trees.h index 2b2e0acc3..2c54fce82 100644 --- a/src/Generating/Trees.h +++ b/src/Generating/Trees.h @@ -96,7 +96,7 @@ void GetLargeJungleTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & /// Generates an image of a small jungle tree (1x1 trunk) void GetSmallJungleTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks); -/// Generates an image of a roofed tree forest tree +/// Generates an image of a roofed forest tree void GetRoofedForestTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks); -- cgit v1.2.3 From 6e0a8d393bafd0b018f168c4ef7a651a2955c1e8 Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Wed, 30 Jul 2014 21:56:33 +0200 Subject: Moved GetRoofedForestTreeImage content to GetDarkoakTreeImage --- src/Generating/Trees.cpp | 119 ++++++++++++++++++++++------------------------- src/Generating/Trees.h | 2 - 2 files changed, 55 insertions(+), 66 deletions(-) diff --git a/src/Generating/Trees.cpp b/src/Generating/Trees.cpp index 308947ad0..4786cad5a 100644 --- a/src/Generating/Trees.cpp +++ b/src/Generating/Trees.cpp @@ -255,7 +255,7 @@ void GetTreeImageByBiome(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_No case biRoofedForest: case biRoofedForestM: { - GetRoofedForestTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); + GetDarkoakTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); return; } @@ -412,7 +412,60 @@ void GetAcaciaTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noi void GetDarkoakTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks) { - // TODO + // Calculate a height + int Height = 5 + (a_Noise.IntNoise3DInt(a_BlockX + 32 * a_Seq, a_BlockY, a_BlockZ + 32 * a_Seq) / 11) % 4; + + // Creat the trunk + for (int i = 0; i < Height; i++) + { + a_LogBlocks.push_back(sSetBlock(a_BlockX, a_BlockY + i, a_BlockZ, E_BLOCK_NEW_LOG, E_META_NEW_LOG_DARK_OAK_WOOD)); + a_LogBlocks.push_back(sSetBlock(a_BlockX + 1, a_BlockY + i, a_BlockZ, E_BLOCK_NEW_LOG, E_META_NEW_LOG_DARK_OAK_WOOD)); + a_LogBlocks.push_back(sSetBlock(a_BlockX, a_BlockY + i, a_BlockZ + 1, E_BLOCK_NEW_LOG, E_META_NEW_LOG_DARK_OAK_WOOD)); + a_LogBlocks.push_back(sSetBlock(a_BlockX + 1, a_BlockY + i, a_BlockZ + 1, E_BLOCK_NEW_LOG, E_META_NEW_LOG_DARK_OAK_WOOD)); + } + + // Create branches + for (int i = 0; i < 3; i++) + { + int x = (a_Noise.IntNoise3DInt(a_BlockX + 32 * a_Seq, a_BlockY * i, a_BlockZ + 32 * a_Seq) % 3) - 1; + int z = (a_Noise.IntNoise3DInt(a_BlockX - 32 * a_Seq, a_BlockY * i, a_BlockZ - 32 * a_Seq) % 3) - 1; + + // The branches would end up in the trunk. + if ((x >= a_BlockX) && (x <= a_BlockX + 1) && (z >= a_BlockZ) && (z <= a_BlockZ + 1)) + { + NOISE_DATATYPE Val1 = a_Noise.IntNoise2D(x, z); + if (Val1 < 0) + { + x = a_BlockX + ((Val1 < -0.5) ? -1 : 3); + } + else + { + z = a_BlockZ + ((Val1 < 0.5) ? -1 : 3); + } + } + + int y = Height - (a_Noise.IntNoise3DInt(a_BlockX + x, a_BlockY * i, a_BlockZ - z) % (Height - (Height / 4))); + + for (int Y = y; Y < Height; Y++) + { + a_LogBlocks.push_back(sSetBlock(a_BlockX + x, a_BlockY + Y, a_BlockZ + z, E_BLOCK_NEW_LOG, E_META_NEW_LOG_DARK_OAK_WOOD)); + } + } + + int hei = a_BlockY + Height - 2; + + // The lower two leaves layers are BigO4 with log in the middle and possibly corners: + for (int i = 0; i < 2; i++) + { + PushCoordBlocks(a_BlockX, hei, a_BlockZ, a_OtherBlocks, BigO4, ARRAYCOUNT(BigO4), E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_DARK_OAK_WOOD); + PushCornerBlocks(a_BlockX, hei, a_BlockZ, a_Seq, a_Noise, 0x5fffffff, a_OtherBlocks, 3, E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_DARK_OAK_WOOD); + hei++; + } // for i < 2 + + // The top leaves layer is a BigO3 with leaves in the middle and possibly corners: + PushCoordBlocks(a_BlockX, hei, a_BlockZ, a_OtherBlocks, BigO3, ARRAYCOUNT(BigO3), E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_DARK_OAK_WOOD); + PushCornerBlocks(a_BlockX, hei, a_BlockZ, a_Seq, a_Noise, 0x5fffffff, a_OtherBlocks, 3, E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_DARK_OAK_WOOD); + a_OtherBlocks.push_back(sSetBlock(a_BlockX, hei, a_BlockZ, E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_DARK_OAK_WOOD)); } @@ -812,65 +865,3 @@ void GetSmallJungleTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & - -void GetRoofedForestTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks) -{ - // Calculate a height - int Height = 5 + (a_Noise.IntNoise3DInt(a_BlockX + 32 * a_Seq, a_BlockY, a_BlockZ + 32 * a_Seq) / 11) % 4; - - // Creat the trunk - for (int i = 0; i < Height; i++) - { - a_LogBlocks.push_back(sSetBlock(a_BlockX, a_BlockY + i, a_BlockZ, E_BLOCK_NEW_LOG, E_META_NEW_LOG_DARK_OAK_WOOD)); - a_LogBlocks.push_back(sSetBlock(a_BlockX + 1, a_BlockY + i, a_BlockZ, E_BLOCK_NEW_LOG, E_META_NEW_LOG_DARK_OAK_WOOD)); - a_LogBlocks.push_back(sSetBlock(a_BlockX, a_BlockY + i, a_BlockZ + 1, E_BLOCK_NEW_LOG, E_META_NEW_LOG_DARK_OAK_WOOD)); - a_LogBlocks.push_back(sSetBlock(a_BlockX + 1, a_BlockY + i, a_BlockZ + 1, E_BLOCK_NEW_LOG, E_META_NEW_LOG_DARK_OAK_WOOD)); - } - - // Create branches - for (int i = 0; i < 3; i++) - { - int x = (a_Noise.IntNoise3DInt(a_BlockX + 32 * a_Seq, a_BlockY * i, a_BlockZ + 32 * a_Seq) % 3) - 1; - int z = (a_Noise.IntNoise3DInt(a_BlockX - 32 * a_Seq, a_BlockY * i, a_BlockZ - 32 * a_Seq) % 3) - 1; - - // The branches would end up in the trunk. - if ((x >= a_BlockX) && (x <= a_BlockX + 1) && (z >= a_BlockZ) && (z <= a_BlockZ + 1)) - { - NOISE_DATATYPE Val1 = a_Noise.IntNoise2D(x, z); - if (Val1 < 0) - { - x = a_BlockX + ((Val1 < -0.5) ? -1 : 3); - } - else - { - z = a_BlockZ + ((Val1 < 0.5) ? -1 : 3); - } - } - - int y = Height - (a_Noise.IntNoise3DInt(a_BlockX + x, a_BlockY * i, a_BlockZ - z) % (Height - (Height / 4))); - - for (int Y = y; Y < Height; Y++) - { - a_LogBlocks.push_back(sSetBlock(a_BlockX + x, a_BlockY + Y, a_BlockZ + z, E_BLOCK_NEW_LOG, E_META_NEW_LOG_DARK_OAK_WOOD)); - } - } - - int hei = a_BlockY + Height - 2; - - // The lower two leaves layers are BigO4 with log in the middle and possibly corners: - for (int i = 0; i < 2; i++) - { - PushCoordBlocks(a_BlockX, hei, a_BlockZ, a_OtherBlocks, BigO4, ARRAYCOUNT(BigO4), E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_DARK_OAK_WOOD); - PushCornerBlocks(a_BlockX, hei, a_BlockZ, a_Seq, a_Noise, 0x5fffffff, a_OtherBlocks, 3, E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_DARK_OAK_WOOD); - hei++; - } // for i < 2 - - // The top leaves layer is a BigO3 with leaves in the middle and possibly corners: - PushCoordBlocks(a_BlockX, hei, a_BlockZ, a_OtherBlocks, BigO3, ARRAYCOUNT(BigO3), E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_DARK_OAK_WOOD); - PushCornerBlocks(a_BlockX, hei, a_BlockZ, a_Seq, a_Noise, 0x5fffffff, a_OtherBlocks, 3, E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_DARK_OAK_WOOD); - a_OtherBlocks.push_back(sSetBlock(a_BlockX, hei, a_BlockZ, E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_DARK_OAK_WOOD)); -} - - - - diff --git a/src/Generating/Trees.h b/src/Generating/Trees.h index 2c54fce82..1f6ac4dff 100644 --- a/src/Generating/Trees.h +++ b/src/Generating/Trees.h @@ -96,8 +96,6 @@ void GetLargeJungleTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & /// Generates an image of a small jungle tree (1x1 trunk) void GetSmallJungleTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks); -/// Generates an image of a roofed forest tree -void GetRoofedForestTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks); -- cgit v1.2.3 From 7821326370385ddcfe2ac28034727d02abf104da Mon Sep 17 00:00:00 2001 From: STRWarrior Date: Wed, 30 Jul 2014 22:43:59 +0200 Subject: Suggestions --- src/Generating/Trees.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Generating/Trees.cpp b/src/Generating/Trees.cpp index 4786cad5a..32594d0b4 100644 --- a/src/Generating/Trees.cpp +++ b/src/Generating/Trees.cpp @@ -412,10 +412,10 @@ void GetAcaciaTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noi void GetDarkoakTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks) { - // Calculate a height + // Pick a height int Height = 5 + (a_Noise.IntNoise3DInt(a_BlockX + 32 * a_Seq, a_BlockY, a_BlockZ + 32 * a_Seq) / 11) % 4; - // Creat the trunk + // Create the trunk for (int i = 0; i < Height; i++) { a_LogBlocks.push_back(sSetBlock(a_BlockX, a_BlockY + i, a_BlockZ, E_BLOCK_NEW_LOG, E_META_NEW_LOG_DARK_OAK_WOOD)); -- cgit v1.2.3