diff --git a/src/Generating/ChunkGenerator.cpp b/src/Generating/ChunkGenerator.cpp index 27210f49d..ef38f1399 100644 --- a/src/Generating/ChunkGenerator.cpp +++ b/src/Generating/ChunkGenerator.cpp @@ -223,6 +223,8 @@ void cChunkGenerator::Execute(void) if (m_Queue.empty()) { + // Sometimes the queue remains empty + // If so, we can't do any front() operations on it! continue; } diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp index 1db16ab71..9ba18f4d1 100644 --- a/src/Mobs/Monster.cpp +++ b/src/Mobs/Monster.cpp @@ -259,6 +259,17 @@ void cMonster::Tick(float a_Dt, cChunk & a_Chunk) if (m_bMovingToDestination) { + if (m_bOnGround) + { + int NextHeight = FindFirstNonAirBlockPosition(m_Destination.x, m_Destination.z); + + if (DoesPosYRequireJump(NextHeight)) + { + m_bOnGround = false; + AddPosY(1.5); // Jump!! + } + } + Vector3f Distance = m_Destination - GetPosition(); if(!ReachedDestination() && !ReachedFinalDestination()) // If we haven't reached any sort of destination, move { @@ -285,17 +296,6 @@ void cMonster::Tick(float a_Dt, cChunk & a_Chunk) TickPathFinding(); // We have reached the next point in our path, calculate another point } } - - if(m_bOnGround) - { - int NextHeight = FindFirstNonAirBlockPosition(m_Destination.x, m_Destination.z); - - if (IsNextYPosReachable(NextHeight)) - { - m_bOnGround = false; - SetSpeedY(5.f); // Jump!! - } - } } if (ReachedFinalDestination()) @@ -373,6 +373,11 @@ int cMonster::FindFirstNonAirBlockPosition(double a_PosX, double a_PosZ) { int PosY = (int)floor(GetPosY()); + if (PosY < 0) + PosY = 0; + else if (PosY > cChunkDef::Height) + PosY = cChunkDef::Height; + if (!g_BlockIsSolid[m_World->GetBlock((int)floor(a_PosX), PosY, (int)floor(a_PosZ))]) { while (!g_BlockIsSolid[m_World->GetBlock((int)floor(a_PosX), PosY, (int)floor(a_PosZ))] && (PosY > 0)) @@ -494,7 +499,7 @@ void cMonster::KilledBy(cEntity * a_Killer) void cMonster::CheckEventSeePlayer(void) { // TODO: Rewrite this to use cWorld's DoWithPlayers() - cPlayer * Closest = m_World->FindClosestPlayer(GetPosition(), (float)m_SightDistance); + cPlayer * Closest = m_World->FindClosestPlayer(GetPosition(), (float)m_SightDistance, false); if (Closest != NULL) { @@ -548,6 +553,11 @@ void cMonster::EventLosePlayer(void) void cMonster::InStateIdle(float a_Dt) { + if (m_bMovingToDestination) + { + return; // Still getting there + } + m_IdleInterval += a_Dt; if (m_IdleInterval > 1) @@ -557,20 +567,19 @@ void cMonster::InStateIdle(float a_Dt) m_IdleInterval -= 1; // So nothing gets dropped when the server hangs for a few seconds Vector3d Dist; - Dist.x = (double)m_World->GetTickRandomNumber(m_SightDistance * 2) - m_SightDistance; - Dist.z = (double)m_World->GetTickRandomNumber(m_SightDistance * 2) - m_SightDistance; + Dist.x = (double)m_World->GetTickRandomNumber(10) - 5; + Dist.z = (double)m_World->GetTickRandomNumber(10) - 5; if ((Dist.SqrLength() > 2) && (rem >= 3)) { - m_Destination.x = GetPosX() + Dist.x; - m_Destination.z = GetPosZ() + Dist.z; + Vector3d Destination(GetPosX() + Dist.x, 0, GetPosZ() + Dist.z); - int NextHeight = FindFirstNonAirBlockPosition(m_Destination.x, m_Destination.z); + int NextHeight = FindFirstNonAirBlockPosition(Destination.x, Destination.z); - if (IsNextYPosReachable(NextHeight + 1)) + if (IsNextYPosReachable(NextHeight)) { - m_Destination.y = (double)NextHeight; - MoveToPosition(m_Destination); + Destination.y = NextHeight; + MoveToPosition(Destination); } } } diff --git a/src/Mobs/Monster.h b/src/Mobs/Monster.h index c8129e63d..d04cb8941 100644 --- a/src/Mobs/Monster.h +++ b/src/Mobs/Monster.h @@ -168,10 +168,18 @@ protected: If current Y is nonsolid, goes down to try to find a solid block, then returns that + 1 If current Y is solid, goes up to find first nonsolid block, and returns that */ int FindFirstNonAirBlockPosition(double a_PosX, double a_PosZ); - /** Returns if a monster can actually reach a given height by jumping */ + /** Returns if a monster can actually reach a given height by jumping or walking */ inline bool IsNextYPosReachable(int a_PosY) { - return (a_PosY > (int)floor(GetPosY())) && (a_PosY == (int)floor(GetPosY()) + 1); + return ( + (a_PosY <= (int)floor(GetPosY())) || + DoesPosYRequireJump(a_PosY) + ); + } + /** Returns if a monster can reach a given height by jumping */ + inline bool DoesPosYRequireJump(int a_PosY) + { + return ((a_PosY > (int)floor(GetPosY())) && (a_PosY == (int)floor(GetPosY()) + 1)); } /** A semi-temporary list to store the traversed coordinates during active pathfinding so we don't visit them again */ diff --git a/src/Server.cpp b/src/Server.cpp index 34ee066cb..2774c8b46 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -194,7 +194,7 @@ bool cServer::InitServer(cIniFile & a_SettingsIni) m_PlayerCount = 0; m_PlayerCountDiff = 0; - m_FaviconData = Base64Encode(cFile::ReadWholeFile("favicon.png")); // Will return empty string if file nonexistant; client doesn't mind + m_FaviconData = Base64Encode(cFile::ReadWholeFile(FILE_IO_PREFIX + AString("favicon.png"))); // Will return empty string if file nonexistant; client doesn't mind if (m_bIsConnected) { diff --git a/src/World.cpp b/src/World.cpp index 453a22c2d..514524991 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -234,7 +234,11 @@ cWorld::cWorld(const AString & a_WorldName) : m_WorldName(a_WorldName), m_IniFileName(m_WorldName + "/world.ini"), m_StorageSchema("Default"), +#ifdef _arm_ + m_StorageCompressionFactor(3), +#else m_StorageCompressionFactor(6), +#endif m_IsSpawnExplicitlySet(false), m_WorldAgeSecs(0), m_TimeOfDaySecs(0), @@ -2419,7 +2423,7 @@ bool cWorld::FindAndDoWithPlayer(const AString & a_PlayerNameHint, cPlayerListCa // TODO: This interface is dangerous! -cPlayer * cWorld::FindClosestPlayer(const Vector3f & a_Pos, float a_SightLimit) +cPlayer * cWorld::FindClosestPlayer(const Vector3f & a_Pos, float a_SightLimit, bool a_CheckLineOfSight) { cTracer LineOfSight(this); @@ -2434,7 +2438,12 @@ cPlayer * cWorld::FindClosestPlayer(const Vector3f & a_Pos, float a_SightLimit) if (Distance < ClosestDistance) { - if (!LineOfSight.Trace(a_Pos,(Pos - a_Pos),(int)(Pos - a_Pos).Length())) + if (a_CheckLineOfSight && !LineOfSight.Trace(a_Pos,(Pos - a_Pos),(int)(Pos - a_Pos).Length())) + { + ClosestDistance = Distance; + ClosestPlayer = *itr; + } + else { ClosestDistance = Distance; ClosestPlayer = *itr; diff --git a/src/World.h b/src/World.h index 61c7604df..933e3ba6f 100644 --- a/src/World.h +++ b/src/World.h @@ -239,7 +239,7 @@ public: bool FindAndDoWithPlayer(const AString & a_PlayerNameHint, cPlayerListCallback & a_Callback); // >> EXPORTED IN MANUALBINDINGS << // TODO: This interface is dangerous - rewrite to DoWithClosestPlayer(pos, sight, action) - cPlayer * FindClosestPlayer(const Vector3f & a_Pos, float a_SightLimit); + cPlayer * FindClosestPlayer(const Vector3f & a_Pos, float a_SightLimit, bool a_CheckLineOfSight = true); void SendPlayerList(cPlayer * a_DestPlayer); // Sends playerlist to the player