From 382e014ebcd44a72788bea8cdcec7f64861b063f Mon Sep 17 00:00:00 2001 From: Howaner Date: Thu, 2 Oct 2014 23:50:41 +0200 Subject: Optimized chunk loader --- src/ChunkSender.cpp | 21 +++--- src/ClientHandle.cpp | 163 ++++++++++++++++++++----------------------- src/ClientHandle.h | 10 +-- src/Entities/Player.cpp | 1 - src/Protocol/Protocol17x.cpp | 1 + src/Protocol/Protocol18x.cpp | 1 + src/World.cpp | 1 - 7 files changed, 93 insertions(+), 105 deletions(-) diff --git a/src/ChunkSender.cpp b/src/ChunkSender.cpp index a3151eb3f..0bdc0cf75 100644 --- a/src/ChunkSender.cpp +++ b/src/ChunkSender.cpp @@ -192,40 +192,37 @@ void cChunkSender::SendChunk(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Clien ASSERT(m_World != NULL); // Ask the client if it still wants the chunk: - if (a_Client != NULL) + if ((a_Client != NULL) && !a_Client->WantsSendChunk(a_ChunkX, a_ChunkZ)) { - if (!a_Client->WantsSendChunk(a_ChunkX, a_ChunkZ)) - { - return; - } + return; } - + // If the chunk has no clients, no need to packetize it: if (!m_World->HasChunkAnyClients(a_ChunkX, a_ChunkZ)) { return; } - + // If the chunk is not valid, do nothing - whoever needs it has queued it for loading / generating if (!m_World->IsChunkValid(a_ChunkX, a_ChunkZ)) { return; } - + // If the chunk is not lighted, queue it for relighting and get notified when it's ready: if (!m_World->IsChunkLighted(a_ChunkX, a_ChunkZ)) { m_World->QueueLightChunk(a_ChunkX, a_ChunkZ, &m_Notify); return; } - + // Query and prepare chunk data: if (!m_World->GetChunkData(a_ChunkX, a_ChunkZ, *this)) { return; } cChunkDataSerializer Data(m_BlockTypes, m_BlockMetas, m_BlockLight, m_BlockSkyLight, m_BiomeMap); - + // Send: if (a_Client == NULL) { @@ -235,7 +232,7 @@ void cChunkSender::SendChunk(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Clien { a_Client->SendChunkData(a_ChunkX, a_ChunkZ, Data); } - + // Send block-entity packets: for (sBlockCoords::iterator itr = m_BlockEntities.begin(); itr != m_BlockEntities.end(); ++itr) { @@ -249,7 +246,7 @@ void cChunkSender::SendChunk(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Clien } } // for itr - m_Packets[] m_BlockEntities.clear(); - + // TODO: Send entity spawn packets } diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index a29bef0c0..27d41da1b 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -70,8 +70,6 @@ cClientHandle::cClientHandle(const cSocket * a_Socket, int a_ViewDistance) : m_OutgoingData(64 KiB), m_Player(NULL), m_HasSentDC(false), - m_LastStreamedChunkX(0x7fffffff), // bogus chunk coords to force streaming upon login - m_LastStreamedChunkZ(0x7fffffff), m_TimeSinceLastPacket(0), m_Ping(1000), m_PingID(1), @@ -401,53 +399,84 @@ void cClientHandle::Authenticate(const AString & a_Name, const AString & a_UUID, -void cClientHandle::StreamChunks(void) +void cClientHandle::StreamNextChunk(void) { if ((m_State < csAuthenticated) || (m_State >= csDestroying)) { return; } - ASSERT(m_Player != NULL); + Vector3d LookVector = m_Player->GetLookVector(); + LookVector.Normalize(); - int ChunkPosX = FAST_FLOOR_DIV((int)m_Player->GetPosX(), cChunkDef::Width); - int ChunkPosZ = FAST_FLOOR_DIV((int)m_Player->GetPosZ(), cChunkDef::Width); - if ((ChunkPosX == m_LastStreamedChunkX) && (ChunkPosZ == m_LastStreamedChunkZ)) + Vector3d Position = m_Player->GetEyePosition(); + for (size_t Range = 0; Range < (size_t)m_ViewDistance; Range++) { - // Already streamed for this position - return; + Vector3d Vector = Position + LookVector * cChunkDef::Width * Range; + + int RangeX, RangeZ = 0; + cChunkDef::BlockToChunk((int)std::floor(Vector.x), (int)std::floor(Vector.z), RangeX, RangeZ); + + for (size_t X = 0; X < 6; X++) + { + for (size_t Z = 0; Z < 6; Z++) + { + int ChunkX = RangeX + ((X >= 3) ? (2 - X) : X); + int ChunkZ = RangeZ + ((Z >= 3) ? (2 - Z) : Z); + cChunkCoords Coords(ChunkX, ChunkZ); + + // If the chunk already loading/loaded -> skip + { + cCSLock Lock(m_CSChunkLists); + if ( + (std::find(m_ChunksToSend.begin(), m_ChunksToSend.end(), Coords) != m_ChunksToSend.end()) || + (std::find(m_LoadedChunks.begin(), m_LoadedChunks.end(), Coords) != m_LoadedChunks.end()) + ) + { + continue; + } + } + + // Unloaded chunk found -> Send it to the client. + StreamChunk(ChunkX, ChunkZ); + return; + } + } } - m_LastStreamedChunkX = ChunkPosX; - m_LastStreamedChunkZ = ChunkPosZ; - - LOGD("Streaming chunks centered on [%d, %d], view distance %d", ChunkPosX, ChunkPosZ, m_ViewDistance); - - cWorld * World = m_Player->GetWorld(); - ASSERT(World != NULL); +} + + - // Remove all loaded chunks that are no longer in range; deferred to out-of-CS: - cChunkCoordsList RemoveChunks; + + +void cClientHandle::UnloadOutOfRangeChunks(void) +{ + int ChunkPosX = FAST_FLOOR_DIV((int)m_Player->GetPosX(), cChunkDef::Width); + int ChunkPosZ = FAST_FLOOR_DIV((int)m_Player->GetPosZ(), cChunkDef::Width); + + cChunkCoordsList ChunksToRemove; { cCSLock Lock(m_CSChunkLists); for (cChunkCoordsList::iterator itr = m_LoadedChunks.begin(); itr != m_LoadedChunks.end();) { - int RelX = (*itr).m_ChunkX - ChunkPosX; - int RelZ = (*itr).m_ChunkZ - ChunkPosZ; - if ((RelX > m_ViewDistance) || (RelX < -m_ViewDistance) || (RelZ > m_ViewDistance) || (RelZ < -m_ViewDistance)) + int DiffX = Diff((*itr).m_ChunkX, ChunkPosX); + int DiffZ = Diff((*itr).m_ChunkZ, ChunkPosZ); + if ((DiffX > m_ViewDistance) || (DiffZ > m_ViewDistance)) { - RemoveChunks.push_back(*itr); + ChunksToRemove.push_back(*itr); itr = m_LoadedChunks.erase(itr); } else { ++itr; } - } // for itr - m_LoadedChunks[] + } + for (cChunkCoordsList::iterator itr = m_ChunksToSend.begin(); itr != m_ChunksToSend.end();) { - int RelX = (*itr).m_ChunkX - ChunkPosX; - int RelZ = (*itr).m_ChunkZ - ChunkPosZ; - if ((RelX > m_ViewDistance) || (RelX < -m_ViewDistance) || (RelZ > m_ViewDistance) || (RelZ < -m_ViewDistance)) + int DiffX = Diff((*itr).m_ChunkX, ChunkPosX); + int DiffZ = Diff((*itr).m_ChunkZ, ChunkPosZ); + if ((DiffX > m_ViewDistance) || (DiffZ > m_ViewDistance)) { itr = m_ChunksToSend.erase(itr); } @@ -455,51 +484,20 @@ void cClientHandle::StreamChunks(void) { ++itr; } - } // for itr - m_ChunksToSend[] + } } - for (cChunkCoordsList::iterator itr = RemoveChunks.begin(); itr != RemoveChunks.end(); ++itr) + + for (cChunkCoordsList::iterator itr = ChunksToRemove.begin(); itr != ChunksToRemove.end(); ++itr) { - World->RemoveChunkClient(itr->m_ChunkX, itr->m_ChunkZ, this); + m_Player->GetWorld()->RemoveChunkClient(itr->m_ChunkX, itr->m_ChunkZ, this); m_Protocol->SendUnloadChunk(itr->m_ChunkX, itr->m_ChunkZ); - } // for itr - RemoveChunks[] - - // Add all chunks that are in range and not yet in m_LoadedChunks: - // Queue these smartly - from the center out to the edge - for (int d = 0; d <= m_ViewDistance; ++d) // cycle through (square) distance, from nearest to furthest - { - // For each distance add chunks in a hollow square centered around current position: - for (int i = -d; i <= d; ++i) - { - StreamChunk(ChunkPosX + d, ChunkPosZ + i); - StreamChunk(ChunkPosX - d, ChunkPosZ + i); - } // for i - for (int i = -d + 1; i < d; ++i) - { - StreamChunk(ChunkPosX + i, ChunkPosZ + d); - StreamChunk(ChunkPosX + i, ChunkPosZ - d); - } // for i - } // for d - - // Touch chunks GENERATEDISTANCE ahead to let them generate: - for (int d = m_ViewDistance + 1; d <= m_ViewDistance + GENERATEDISTANCE; ++d) // cycle through (square) distance, from nearest to furthest - { - // For each distance touch chunks in a hollow square centered around current position: - for (int i = -d; i <= d; ++i) - { - World->TouchChunk(ChunkPosX + d, ChunkPosZ + i); - World->TouchChunk(ChunkPosX - d, ChunkPosZ + i); - } // for i - for (int i = -d + 1; i < d; ++i) - { - World->TouchChunk(ChunkPosX + i, ChunkPosZ + d); - World->TouchChunk(ChunkPosX + i, ChunkPosZ - d); - } // for i - } // for d + } } + void cClientHandle::StreamChunk(int a_ChunkX, int a_ChunkZ) { if (m_State >= csDestroying) @@ -539,11 +537,6 @@ void cClientHandle::RemoveFromAllChunks() cCSLock Lock(m_CSChunkLists); m_LoadedChunks.clear(); m_ChunksToSend.clear(); - - // Also reset the LastStreamedChunk coords to bogus coords, - // so that all chunks are streamed in subsequent StreamChunks() call (FS #407) - m_LastStreamedChunkX = 0x7fffffff; - m_LastStreamedChunkZ = 0x7fffffff; } } @@ -1858,10 +1851,7 @@ void cClientHandle::RemoveFromWorld(void) { m_Protocol->SendUnloadChunk(itr->m_ChunkX, itr->m_ChunkZ); } // for itr - Chunks[] - - // Here, we set last streamed values to bogus ones so everything is resent - m_LastStreamedChunkX = 0x7fffffff; - m_LastStreamedChunkZ = 0x7fffffff; + m_HasSentPlayerChunk = false; } @@ -1907,7 +1897,7 @@ void cClientHandle::Tick(float a_Dt) { return; } - + // If the chunk the player's in was just sent, spawn the player: if (m_HasSentPlayerChunk && (m_State == csDownloadingWorld)) { @@ -1928,6 +1918,17 @@ void cClientHandle::Tick(float a_Dt) } } + if ((m_State >= csAuthenticated) && (m_State < csDestroying)) + { + StreamNextChunk(); // Streams the next chunk + + // Unload all chunks that are out of the view distance (all 2 seconds) + if ((m_Player->GetWorld()->GetWorldAge() % 40) == 0) + { + UnloadOutOfRangeChunks(); + } + } + // Handle block break animation: if (m_BlockDigAnimStage > -1) { @@ -1964,7 +1965,7 @@ void cClientHandle::ServerTick(float a_Dt) if (m_State == csAuthenticated) { - StreamChunks(); + StreamNextChunk(); // Remove the client handle from the server, it will be ticked from its cPlayer object from now on cRoot::Get()->GetServer()->ClientMovedToWorld(this); @@ -2723,18 +2724,8 @@ void cClientHandle::SetUsername( const AString & a_Username) void cClientHandle::SetViewDistance(int a_ViewDistance) { - if (a_ViewDistance < MIN_VIEW_DISTANCE) - { - a_ViewDistance = MIN_VIEW_DISTANCE; - } - if (a_ViewDistance > MAX_VIEW_DISTANCE) - { - a_ViewDistance = MAX_VIEW_DISTANCE; - } - m_ViewDistance = a_ViewDistance; - - // Need to re-stream chunks for the change to become apparent: - StreamChunks(); + m_ViewDistance = Clamp(a_ViewDistance, MIN_VIEW_DISTANCE, MAX_VIEW_DISTANCE); + LOGD("Setted %s's view distance to %i", GetUsername().c_str(), m_ViewDistance); } diff --git a/src/ClientHandle.h b/src/ClientHandle.h index 20592c190..897fb8705 100644 --- a/src/ClientHandle.h +++ b/src/ClientHandle.h @@ -113,7 +113,11 @@ public: /** Authenticates the specified user, called by cAuthenticator */ void Authenticate(const AString & a_Name, const AString & a_UUID, const Json::Value & a_Properties); - void StreamChunks(void); + /** This function sends a new unloaded chunk to the player. */ + void StreamNextChunk(void); + + /** Remove all loaded chunks that are no longer in range */ + void UnloadOutOfRangeChunks(void); // Removes the client from all chunks. Used when switching worlds or destroying the player void RemoveFromAllChunks(void); @@ -352,10 +356,6 @@ private: cPlayer * m_Player; bool m_HasSentDC; ///< True if a D/C packet has been sent in either direction - - // Chunk position when the last StreamChunks() was called; used to avoid re-streaming while in the same chunk - int m_LastStreamedChunkX; - int m_LastStreamedChunkZ; /** Seconds since the last packet data was received (updated in Tick(), reset in DataReceived()) */ float m_TimeSinceLastPacket; diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index f58a0a016..19273b0a9 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -235,7 +235,6 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk) CanMove = false; TeleportToCoords(m_LastPos.x, m_LastPos.y, m_LastPos.z); } - m_ClientHandle->StreamChunks(); } if (CanMove) diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index a7abd240f..494413f63 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -1901,6 +1901,7 @@ void cProtocol172::HandlePacketClientSettings(cByteBuffer & a_ByteBuffer) HANDLE_READ(a_ByteBuffer, ReadByte, Byte, ShowCape); m_Client->SetLocale(Locale); + m_Client->SetViewDistance(ViewDistance); // TODO: Do anything with the other values. } diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp index acdb48cf7..f37409744 100644 --- a/src/Protocol/Protocol18x.cpp +++ b/src/Protocol/Protocol18x.cpp @@ -2160,6 +2160,7 @@ void cProtocol180::HandlePacketClientSettings(cByteBuffer & a_ByteBuffer) HANDLE_READ(a_ByteBuffer, ReadChar, char, SkinFlags); m_Client->SetLocale(Locale); + m_Client->SetViewDistance(ViewDistance); // TODO: Handle other values } diff --git a/src/World.cpp b/src/World.cpp index a3c804b44..30c1a73b1 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -3491,7 +3491,6 @@ void cWorld::AddQueuedPlayers(void) cClientHandle * Client = (*itr)->GetClientHandle(); if (Client != NULL) { - Client->StreamChunks(); Client->SendPlayerMoveLook(); Client->SendHealth(); Client->SendWholeInventory(*(*itr)->GetWindow()); -- cgit v1.2.3 From 5a6b86180e0144a5671c747b838d14992c21afae Mon Sep 17 00:00:00 2001 From: Howaner Date: Mon, 6 Oct 2014 17:38:17 +0200 Subject: Better StreamNextChunk() method --- src/ClientHandle.cpp | 131 +++++++++++++++++++++++++++++++++++++++++++++------ src/ClientHandle.h | 4 ++ 2 files changed, 120 insertions(+), 15 deletions(-) diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index 27d41da1b..3c73296a4 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -70,6 +70,8 @@ cClientHandle::cClientHandle(const cSocket * a_Socket, int a_ViewDistance) : m_OutgoingData(64 KiB), m_Player(NULL), m_HasSentDC(false), + m_LastStreamedChunkX(0x7fffffff), // bogus chunk coords to force streaming upon login + m_LastStreamedChunkZ(0x7fffffff), m_TimeSinceLastPacket(0), m_Ping(1000), m_PingID(1), @@ -405,44 +407,133 @@ void cClientHandle::StreamNextChunk(void) { return; } + ASSERT(m_Player != NULL); + int ChunkPosX = m_Player->GetChunkX(); + int ChunkPosZ = m_Player->GetChunkZ(); + if ((m_LastStreamedChunkX == ChunkPosX) && (m_LastStreamedChunkZ == ChunkPosZ)) + { + // All chunks are already loaded. Abort loading. + return; + } + + // Get the look vector and normalize it. + Vector3d Position = m_Player->GetEyePosition(); Vector3d LookVector = m_Player->GetLookVector(); LookVector.Normalize(); - Vector3d Position = m_Player->GetEyePosition(); + // Lock the list + cCSLock Lock(m_CSChunkLists); + + // High priority: Load the chunks that are in the view-direction of the player (with a radius of 3) for (size_t Range = 0; Range < (size_t)m_ViewDistance; Range++) { Vector3d Vector = Position + LookVector * cChunkDef::Width * Range; + // Get the chunk from the x/z coords. int RangeX, RangeZ = 0; cChunkDef::BlockToChunk((int)std::floor(Vector.x), (int)std::floor(Vector.z), RangeX, RangeZ); - for (size_t X = 0; X < 6; X++) + for (size_t X = 0; X < 7; X++) { - for (size_t Z = 0; Z < 6; Z++) + for (size_t Z = 0; Z < 7; Z++) { - int ChunkX = RangeX + ((X >= 3) ? (2 - X) : X); - int ChunkZ = RangeZ + ((Z >= 3) ? (2 - Z) : Z); + int ChunkX = RangeX + ((X >= 4) ? (3 - X) : X); + int ChunkZ = RangeZ + ((Z >= 4) ? (3 - Z) : Z); cChunkCoords Coords(ChunkX, ChunkZ); // If the chunk already loading/loaded -> skip + if ( + (std::find(m_ChunksToSend.begin(), m_ChunksToSend.end(), Coords) != m_ChunksToSend.end()) || + (std::find(m_LoadedChunks.begin(), m_LoadedChunks.end(), Coords) != m_LoadedChunks.end()) + ) { - cCSLock Lock(m_CSChunkLists); - if ( - (std::find(m_ChunksToSend.begin(), m_ChunksToSend.end(), Coords) != m_ChunksToSend.end()) || - (std::find(m_LoadedChunks.begin(), m_LoadedChunks.end(), Coords) != m_LoadedChunks.end()) - ) - { - continue; - } + continue; } // Unloaded chunk found -> Send it to the client. + Lock.Unlock(); StreamChunk(ChunkX, ChunkZ); return; } } } + + // Medium priority: Load the chunks that are behind the player + LookVector = m_Player->GetLookVector() * -1; + for (size_t Range = 0; Range < 3; Range++) + { + Vector3d Vector = Position + LookVector * cChunkDef::Width * Range; + + // Get the chunk from the x/z coords. + int RangeX, RangeZ = 0; + cChunkDef::BlockToChunk((int)std::floor(Vector.x), (int)std::floor(Vector.z), RangeX, RangeZ); + + for (size_t X = 0; X < 7; X++) + { + for (size_t Z = 0; Z < 7; Z++) + { + int ChunkX = RangeX + ((X >= 4) ? (3 - X) : X); + int ChunkZ = RangeZ + ((Z >= 4) ? (3 - Z) : Z); + cChunkCoords Coords(ChunkX, ChunkZ); + + // If the chunk already loading/loaded -> skip + if ( + (std::find(m_ChunksToSend.begin(), m_ChunksToSend.end(), Coords) != m_ChunksToSend.end()) || + (std::find(m_LoadedChunks.begin(), m_LoadedChunks.end(), Coords) != m_LoadedChunks.end()) + ) + { + continue; + } + + // Unloaded chunk found -> Send it to the client. + Lock.Unlock(); + StreamChunk(ChunkX, ChunkZ); + return; + } + } + } + + // Low priority: Add all chunks that are in range. (From the center out to the edge) + for (int d = 0; d <= m_ViewDistance; ++d) // cycle through (square) distance, from nearest to furthest + { + // For each distance add chunks in a hollow square centered around current position: + cChunkCoordsList CurcleChunks; + for (int i = -d; i <= d; ++i) + { + CurcleChunks.push_back(cChunkCoords(ChunkPosX + d, ChunkPosZ + i)); + CurcleChunks.push_back(cChunkCoords(ChunkPosX - d, ChunkPosZ + i)); + } + for (int i = -d + 1; i < d; ++i) + { + CurcleChunks.push_back(cChunkCoords(ChunkPosX + i, ChunkPosZ + d)); + CurcleChunks.push_back(cChunkCoords(ChunkPosX + i, ChunkPosZ - d)); + } + + // For each the CurcleChunks list and send the first unloaded chunk: + for (cChunkCoordsList::iterator itr = CurcleChunks.begin(), end = CurcleChunks.end(); itr != end; ++itr) + { + cChunkCoords Coords = *itr; + + // If the chunk already loading/loaded -> skip + if ( + (std::find(m_ChunksToSend.begin(), m_ChunksToSend.end(), Coords) != m_ChunksToSend.end()) || + (std::find(m_LoadedChunks.begin(), m_LoadedChunks.end(), Coords) != m_LoadedChunks.end()) + ) + { + continue; + } + + // Unloaded chunk found -> Send it to the client. + Lock.Unlock(); + StreamChunk(Coords.m_ChunkX, Coords.m_ChunkZ); + return; + } + } + + // All chunks are loaded -> Sets the last loaded chunk coordinates to current coordinates + m_LastStreamedChunkX = ChunkPosX; + m_LastStreamedChunkZ = ChunkPosZ; } @@ -537,6 +628,11 @@ void cClientHandle::RemoveFromAllChunks() cCSLock Lock(m_CSChunkLists); m_LoadedChunks.clear(); m_ChunksToSend.clear(); + + // Also reset the LastStreamedChunk coords to bogus coords, + // so that all chunks are streamed in subsequent StreamChunks() call (FS #407) + m_LastStreamedChunkX = 0x7fffffff; + m_LastStreamedChunkZ = 0x7fffffff; } } @@ -1852,6 +1948,10 @@ void cClientHandle::RemoveFromWorld(void) m_Protocol->SendUnloadChunk(itr->m_ChunkX, itr->m_ChunkZ); } // for itr - Chunks[] + // Here, we set last streamed values to bogus ones so everything is resent + m_LastStreamedChunkX = 0x7fffffff; + m_LastStreamedChunkZ = 0x7fffffff; + m_HasSentPlayerChunk = false; } @@ -1920,10 +2020,11 @@ void cClientHandle::Tick(float a_Dt) if ((m_State >= csAuthenticated) && (m_State < csDestroying)) { + StreamNextChunk(); // Streams the next chunk - // Unload all chunks that are out of the view distance (all 2 seconds) - if ((m_Player->GetWorld()->GetWorldAge() % 40) == 0) + // Unload all chunks that are out of the view distance (all 5 seconds) + if ((m_Player->GetWorld()->GetWorldAge() % 100) == 0) { UnloadOutOfRangeChunks(); } diff --git a/src/ClientHandle.h b/src/ClientHandle.h index 897fb8705..018c537c6 100644 --- a/src/ClientHandle.h +++ b/src/ClientHandle.h @@ -357,6 +357,10 @@ private: bool m_HasSentDC; ///< True if a D/C packet has been sent in either direction + // Chunk position when the last StreamChunks() was called; used to avoid re-streaming while in the same chunk + int m_LastStreamedChunkX; + int m_LastStreamedChunkZ; + /** Seconds since the last packet data was received (updated in Tick(), reset in DataReceived()) */ float m_TimeSinceLastPacket; -- cgit v1.2.3 From b493beb3bbac05d0402a6e388a61bf446c6c00ff Mon Sep 17 00:00:00 2001 From: Howaner Date: Mon, 6 Oct 2014 21:27:53 +0200 Subject: Stream 4 chunks per tick. Added priority. --- src/Chunk.cpp | 2 +- src/ChunkSender.cpp | 13 +++++++++---- src/ChunkSender.h | 18 ++++++++++++++++-- src/ClientHandle.cpp | 35 ++++++++++++++++++++++------------- src/ClientHandle.h | 7 ++++--- src/World.cpp | 8 ++++---- src/World.h | 4 ++-- 7 files changed, 58 insertions(+), 29 deletions(-) diff --git a/src/Chunk.cpp b/src/Chunk.cpp index 96b8eda4e..e8a1de908 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -1742,7 +1742,7 @@ void cChunk::SetAreaBiome(int a_MinRelX, int a_MaxRelX, int a_MinRelZ, int a_Max // Re-send the chunk to all clients: for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr) { - m_World->ForceSendChunkTo(m_PosX, m_PosZ, (*itr)); + m_World->ForceSendChunkTo(m_PosX, m_PosZ, cChunkSender::E_CHUNK_PRIORITY_MEDIUM, (*itr)); } // for itr - m_LoadedByClient[] } diff --git a/src/ChunkSender.cpp b/src/ChunkSender.cpp index 0bdc0cf75..2a953db1f 100644 --- a/src/ChunkSender.cpp +++ b/src/ChunkSender.cpp @@ -91,17 +91,22 @@ void cChunkSender::ChunkReady(int a_ChunkX, int a_ChunkZ) -void cChunkSender::QueueSendChunkTo(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client) +void cChunkSender::QueueSendChunkTo(int a_ChunkX, int a_ChunkZ, eChunkPriority a_Priority, cClientHandle * a_Client) { ASSERT(a_Client != NULL); { + sSendChunk Chunk(a_ChunkX, a_ChunkZ, a_Priority, a_Client); + cCSLock Lock(m_CS); - if (std::find(m_SendChunks.begin(), m_SendChunks.end(), sSendChunk(a_ChunkX, a_ChunkZ, a_Client)) != m_SendChunks.end()) + if (std::find(m_SendChunks.begin(), m_SendChunks.end(), Chunk) != m_SendChunks.end()) { // Already queued, bail out return; } - m_SendChunks.push_back(sSendChunk(a_ChunkX, a_ChunkZ, a_Client)); + m_SendChunks.push_back(Chunk); + + // Sort the list: + m_SendChunks.sort(); } m_evtQueue.Set(); } @@ -169,7 +174,7 @@ void cChunkSender::Execute(void) sSendChunk Chunk(m_SendChunks.front()); m_SendChunks.pop_front(); Lock.Unlock(); - + SendChunk(Chunk.m_ChunkX, Chunk.m_ChunkZ, Chunk.m_Client); } Lock.Lock(); diff --git a/src/ChunkSender.h b/src/ChunkSender.h index a0e9087a9..3a1e1f5ea 100644 --- a/src/ChunkSender.h +++ b/src/ChunkSender.h @@ -75,6 +75,13 @@ class cChunkSender: public: cChunkSender(void); ~cChunkSender(); + + enum eChunkPriority + { + E_CHUNK_PRIORITY_HIGH = 0, + E_CHUNK_PRIORITY_MEDIUM = 1, + E_CHUNK_PRIORITY_LOW = 2, + }; bool Start(cWorld * a_World); @@ -84,7 +91,7 @@ public: void ChunkReady(int a_ChunkX, int a_ChunkZ); /// Queues a chunk to be sent to a specific client - void QueueSendChunkTo(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client); + void QueueSendChunkTo(int a_ChunkX, int a_ChunkZ, eChunkPriority a_Priority, cClientHandle * a_Client); /// Removes the a_Client from all waiting chunk send operations void RemoveClient(cClientHandle * a_Client); @@ -96,11 +103,13 @@ protected: { int m_ChunkX; int m_ChunkZ; + eChunkPriority m_Priority; cClientHandle * m_Client; - sSendChunk(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client) : + sSendChunk(int a_ChunkX, int a_ChunkZ, eChunkPriority a_Priority, cClientHandle * a_Client) : m_ChunkX(a_ChunkX), m_ChunkZ(a_ChunkZ), + m_Priority(a_Priority), m_Client(a_Client) { } @@ -113,6 +122,11 @@ protected: (a_Other.m_Client == m_Client) ); } + + bool operator < (const sSendChunk & a_Other) + { + return (m_Priority < a_Other.m_Priority); + } } ; typedef std::list sSendChunkList; diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index 535f9d386..588a1caba 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -402,11 +402,11 @@ void cClientHandle::Authenticate(const AString & a_Name, const AString & a_UUID, -void cClientHandle::StreamNextChunk(void) +bool cClientHandle::StreamNextChunk(void) { if ((m_State < csAuthenticated) || (m_State >= csDestroying)) { - return; + return true; } ASSERT(m_Player != NULL); @@ -415,7 +415,7 @@ void cClientHandle::StreamNextChunk(void) if ((m_LastStreamedChunkX == ChunkPosX) && (m_LastStreamedChunkZ == ChunkPosZ)) { // All chunks are already loaded. Abort loading. - return; + return true; } // Get the look vector and normalize it. @@ -454,8 +454,8 @@ void cClientHandle::StreamNextChunk(void) // Unloaded chunk found -> Send it to the client. Lock.Unlock(); - StreamChunk(ChunkX, ChunkZ); - return; + StreamChunk(ChunkX, ChunkZ, cChunkSender::E_CHUNK_PRIORITY_HIGH); + return false; } } } @@ -489,8 +489,8 @@ void cClientHandle::StreamNextChunk(void) // Unloaded chunk found -> Send it to the client. Lock.Unlock(); - StreamChunk(ChunkX, ChunkZ); - return; + StreamChunk(ChunkX, ChunkZ, cChunkSender::E_CHUNK_PRIORITY_MEDIUM); + return false; } } } @@ -527,14 +527,15 @@ void cClientHandle::StreamNextChunk(void) // Unloaded chunk found -> Send it to the client. Lock.Unlock(); - StreamChunk(Coords.m_ChunkX, Coords.m_ChunkZ); - return; + StreamChunk(Coords.m_ChunkX, Coords.m_ChunkZ, cChunkSender::E_CHUNK_PRIORITY_LOW); + return false; } } // All chunks are loaded -> Sets the last loaded chunk coordinates to current coordinates m_LastStreamedChunkX = ChunkPosX; m_LastStreamedChunkZ = ChunkPosZ; + return true; } @@ -590,7 +591,7 @@ void cClientHandle::UnloadOutOfRangeChunks(void) -void cClientHandle::StreamChunk(int a_ChunkX, int a_ChunkZ) +void cClientHandle::StreamChunk(int a_ChunkX, int a_ChunkZ, cChunkSender::eChunkPriority a_Priority) { if (m_State >= csDestroying) { @@ -608,7 +609,7 @@ void cClientHandle::StreamChunk(int a_ChunkX, int a_ChunkZ) m_LoadedChunks.push_back(cChunkCoords(a_ChunkX, a_ChunkZ)); m_ChunksToSend.push_back(cChunkCoords(a_ChunkX, a_ChunkZ)); } - World->SendChunkTo(a_ChunkX, a_ChunkZ, this); + World->SendChunkTo(a_ChunkX, a_ChunkZ, a_Priority, this); } } @@ -2028,8 +2029,16 @@ void cClientHandle::Tick(float a_Dt) if ((m_State >= csAuthenticated) && (m_State < csDestroying)) { - - StreamNextChunk(); // Streams the next chunk + // Stream 4 chunks per tick + for (int i = 0; i < 4; i++) + { + // Stream the next chunk + if (StreamNextChunk()) + { + // Streaming finished. All chunks are loaded. + break; + } + } // Unload all chunks that are out of the view distance (all 5 seconds) if ((m_Player->GetWorld()->GetWorldAge() % 100) == 0) diff --git a/src/ClientHandle.h b/src/ClientHandle.h index eb91b8487..c6444b1c2 100644 --- a/src/ClientHandle.h +++ b/src/ClientHandle.h @@ -21,6 +21,7 @@ #include "Enchantments.h" #include "UI/SlotArea.h" #include "json/json.h" +#include "ChunkSender.h" @@ -113,8 +114,8 @@ public: /** Authenticates the specified user, called by cAuthenticator */ void Authenticate(const AString & a_Name, const AString & a_UUID, const Json::Value & a_Properties); - /** This function sends a new unloaded chunk to the player. */ - void StreamNextChunk(void); + /** This function sends a new unloaded chunk to the player. Returns true if all chunks are loaded. */ + bool StreamNextChunk(); /** Remove all loaded chunks that are no longer in range */ void UnloadOutOfRangeChunks(void); @@ -448,7 +449,7 @@ private: bool CheckBlockInteractionsRate(void); /** Adds a single chunk to be streamed to the client; used by StreamChunks() */ - void StreamChunk(int a_ChunkX, int a_ChunkZ); + void StreamChunk(int a_ChunkX, int a_ChunkZ, cChunkSender::eChunkPriority a_Priority); /** Handles the DIG_STARTED dig packet: */ void HandleBlockDigStarted (int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, BLOCKTYPE a_OldBlock, NIBBLETYPE a_OldMeta); diff --git a/src/World.cpp b/src/World.cpp index 30c1a73b1..049dbc106 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -2850,19 +2850,19 @@ void cWorld::RemoveClientFromChunks(cClientHandle * a_Client) -void cWorld::SendChunkTo(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client) +void cWorld::SendChunkTo(int a_ChunkX, int a_ChunkZ, cChunkSender::eChunkPriority a_Priority, cClientHandle * a_Client) { - m_ChunkSender.QueueSendChunkTo(a_ChunkX, a_ChunkZ, a_Client); + m_ChunkSender.QueueSendChunkTo(a_ChunkX, a_ChunkZ, a_Priority, a_Client); } -void cWorld::ForceSendChunkTo(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client) +void cWorld::ForceSendChunkTo(int a_ChunkX, int a_ChunkZ, cChunkSender::eChunkPriority a_Priority, cClientHandle * a_Client) { a_Client->AddWantedChunk(a_ChunkX, a_ChunkZ); - m_ChunkSender.QueueSendChunkTo(a_ChunkX, a_ChunkZ, a_Client); + m_ChunkSender.QueueSendChunkTo(a_ChunkX, a_ChunkZ, a_Priority, a_Client); } diff --git a/src/World.h b/src/World.h index 90dada259..f940a98c4 100644 --- a/src/World.h +++ b/src/World.h @@ -359,11 +359,11 @@ public: /** Sends the chunk to the client specified, if the client doesn't have the chunk yet. If chunk not valid, the request is postponed (ChunkSender will send that chunk when it becomes valid + lighted). */ - void SendChunkTo(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client); + void SendChunkTo(int a_ChunkX, int a_ChunkZ, cChunkSender::eChunkPriority a_Priority, cClientHandle * a_Client); /** Sends the chunk to the client specified, even if the client already has the chunk. If the chunk's not valid, the request is postponed (ChunkSender will send that chunk when it becomes valid + lighted). */ - void ForceSendChunkTo(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client); + void ForceSendChunkTo(int a_ChunkX, int a_ChunkZ, cChunkSender::eChunkPriority a_Priority, cClientHandle * a_Client); /** Removes client from ChunkSender's queue of chunks to be sent */ void RemoveClientFromChunkSender(cClientHandle * a_Client); -- cgit v1.2.3 From 97623fc634263eeff99e25b7527fde318108ea0d Mon Sep 17 00:00:00 2001 From: Howaner Date: Tue, 7 Oct 2014 21:36:01 +0200 Subject: Added distance check. --- src/ClientHandle.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index 588a1caba..897ee9e9e 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -443,6 +443,12 @@ bool cClientHandle::StreamNextChunk(void) int ChunkZ = RangeZ + ((Z >= 4) ? (3 - Z) : Z); cChunkCoords Coords(ChunkX, ChunkZ); + // Checks if the chunk is in distance + if ((Diff(ChunkX, ChunkPosX) > m_ViewDistance) || (Diff(ChunkZ, ChunkPosZ) > m_ViewDistance)) + { + continue; + } + // If the chunk already loading/loaded -> skip if ( (std::find(m_ChunksToSend.begin(), m_ChunksToSend.end(), Coords) != m_ChunksToSend.end()) || @@ -478,6 +484,12 @@ bool cClientHandle::StreamNextChunk(void) int ChunkZ = RangeZ + ((Z >= 4) ? (3 - Z) : Z); cChunkCoords Coords(ChunkX, ChunkZ); + // Checks if the chunk is in distance + if ((Diff(ChunkX, ChunkPosX) > m_ViewDistance) || (Diff(ChunkZ, ChunkPosZ) > m_ViewDistance)) + { + continue; + } + // If the chunk already loading/loaded -> skip if ( (std::find(m_ChunksToSend.begin(), m_ChunksToSend.end(), Coords) != m_ChunksToSend.end()) || -- cgit v1.2.3 From a07456d7126d61d903eb7c14f88d436d20546474 Mon Sep 17 00:00:00 2001 From: Howaner Date: Tue, 21 Oct 2014 17:00:41 +0200 Subject: New c++11 stuff. --- src/ClientHandle.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index ec1bebe8d..28fcb0d37 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -430,13 +430,13 @@ bool cClientHandle::StreamNextChunk(void) cCSLock Lock(m_CSChunkLists); // High priority: Load the chunks that are in the view-direction of the player (with a radius of 3) - for (size_t Range = 0; Range < (size_t)m_ViewDistance; Range++) + for (int Range = 0; Range < m_ViewDistance; Range++) { Vector3d Vector = Position + LookVector * cChunkDef::Width * Range; // Get the chunk from the x/z coords. int RangeX, RangeZ = 0; - cChunkDef::BlockToChunk((int)std::floor(Vector.x), (int)std::floor(Vector.z), RangeX, RangeZ); + cChunkDef::BlockToChunk(FloorC(Vector.x), FloorC(Vector.z), RangeX, RangeZ); for (size_t X = 0; X < 7; X++) { @@ -471,13 +471,13 @@ bool cClientHandle::StreamNextChunk(void) // Medium priority: Load the chunks that are behind the player LookVector = m_Player->GetLookVector() * -1; - for (size_t Range = 0; Range < 3; Range++) + for (int Range = 0; Range < 3; Range++) { Vector3d Vector = Position + LookVector * cChunkDef::Width * Range; // Get the chunk from the x/z coords. int RangeX, RangeZ = 0; - cChunkDef::BlockToChunk((int)std::floor(Vector.x), (int)std::floor(Vector.z), RangeX, RangeZ); + cChunkDef::BlockToChunk(FloorC(Vector.x), FloorC(Vector.z), RangeX, RangeZ); for (size_t X = 0; X < 7; X++) { -- cgit v1.2.3 From b0988e65aadc1a9d33065cf6afefc05dbf768ef8 Mon Sep 17 00:00:00 2001 From: Howaner Date: Tue, 21 Oct 2014 17:35:23 +0200 Subject: Use two lists and 2 chunk send prioritys. --- src/Chunk.cpp | 2 +- src/ChunkSender.cpp | 48 +++++++++++++++++++++++++++++++++++------------- src/ChunkSender.h | 15 ++++----------- src/ClientHandle.cpp | 41 ----------------------------------------- 4 files changed, 40 insertions(+), 66 deletions(-) diff --git a/src/Chunk.cpp b/src/Chunk.cpp index e4fa9629f..bfa287f63 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -1742,7 +1742,7 @@ void cChunk::SetAreaBiome(int a_MinRelX, int a_MaxRelX, int a_MinRelZ, int a_Max // Re-send the chunk to all clients: for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr) { - m_World->ForceSendChunkTo(m_PosX, m_PosZ, cChunkSender::E_CHUNK_PRIORITY_MEDIUM, (*itr)); + m_World->ForceSendChunkTo(m_PosX, m_PosZ, cChunkSender::E_CHUNK_PRIORITY_HIGH, (*itr)); } // for itr - m_LoadedByClient[] } diff --git a/src/ChunkSender.cpp b/src/ChunkSender.cpp index 2a953db1f..680f34bce 100644 --- a/src/ChunkSender.cpp +++ b/src/ChunkSender.cpp @@ -95,18 +95,23 @@ void cChunkSender::QueueSendChunkTo(int a_ChunkX, int a_ChunkZ, eChunkPriority a { ASSERT(a_Client != NULL); { - sSendChunk Chunk(a_ChunkX, a_ChunkZ, a_Priority, a_Client); + sSendChunk Chunk(a_ChunkX, a_ChunkZ, a_Client); cCSLock Lock(m_CS); - if (std::find(m_SendChunks.begin(), m_SendChunks.end(), Chunk) != m_SendChunks.end()) + if ( + std::find(m_SendChunksLowPriority.begin(), m_SendChunksLowPriority.end(), Chunk) != m_SendChunksLowPriority.end() || + std::find(m_SendChunksHighPriority.begin(), m_SendChunksHighPriority.end(), Chunk) != m_SendChunksHighPriority.end() + ) { // Already queued, bail out return; } - m_SendChunks.push_back(Chunk); - // Sort the list: - m_SendChunks.sort(); + if (a_Priority == E_CHUNK_PRIORITY_LOW) { + m_SendChunksLowPriority.push_back(Chunk); + } else if (a_Priority == E_CHUNK_PRIORITY_HIGH) { + m_SendChunksHighPriority.push_back(Chunk); + } } m_evtQueue.Set(); } @@ -119,15 +124,23 @@ void cChunkSender::RemoveClient(cClientHandle * a_Client) { { cCSLock Lock(m_CS); - for (sSendChunkList::iterator itr = m_SendChunks.begin(); itr != m_SendChunks.end();) + for (sSendChunkList::iterator itr = m_SendChunksLowPriority.begin(); itr != m_SendChunksLowPriority.end();) { if (itr->m_Client == a_Client) { - itr = m_SendChunks.erase(itr); + itr = m_SendChunksLowPriority.erase(itr); + continue; + } + ++itr; + } // for itr - m_SendChunksLowPriority[] + for (sSendChunkList::iterator itr = m_SendChunksHighPriority.begin(); itr != m_SendChunksHighPriority.end();) + { + if (itr->m_Client == a_Client) { + itr = m_SendChunksHighPriority.erase(itr); continue; } ++itr; - } // for itr - m_SendChunks[] + } // for itr - m_SendChunksHighPriority[] m_RemoveCount++; } m_evtQueue.Set(); @@ -143,7 +156,7 @@ void cChunkSender::Execute(void) while (!m_ShouldTerminate) { cCSLock Lock(m_CS); - while (m_ChunksReady.empty() && m_SendChunks.empty()) + while (m_ChunksReady.empty() && m_SendChunksLowPriority.empty() && m_SendChunksHighPriority.empty()) { int RemoveCount = m_RemoveCount; m_RemoveCount = 0; @@ -158,8 +171,17 @@ void cChunkSender::Execute(void) return; } } // while (empty) - - if (!m_ChunksReady.empty()) + + if (!m_SendChunksHighPriority.empty()) + { + // Take one from the queue: + sSendChunk Chunk(m_SendChunksHighPriority.front()); + m_SendChunksHighPriority.pop_front(); + Lock.Unlock(); + + SendChunk(Chunk.m_ChunkX, Chunk.m_ChunkZ, Chunk.m_Client); + } + else if (!m_ChunksReady.empty()) { // Take one from the queue: cChunkCoords Coords(m_ChunksReady.front()); @@ -171,8 +193,8 @@ void cChunkSender::Execute(void) else { // Take one from the queue: - sSendChunk Chunk(m_SendChunks.front()); - m_SendChunks.pop_front(); + sSendChunk Chunk(m_SendChunksLowPriority.front()); + m_SendChunksLowPriority.pop_front(); Lock.Unlock(); SendChunk(Chunk.m_ChunkX, Chunk.m_ChunkZ, Chunk.m_Client); diff --git a/src/ChunkSender.h b/src/ChunkSender.h index 3a1e1f5ea..bd489e2c4 100644 --- a/src/ChunkSender.h +++ b/src/ChunkSender.h @@ -79,8 +79,7 @@ public: enum eChunkPriority { E_CHUNK_PRIORITY_HIGH = 0, - E_CHUNK_PRIORITY_MEDIUM = 1, - E_CHUNK_PRIORITY_LOW = 2, + E_CHUNK_PRIORITY_LOW = 1, }; bool Start(cWorld * a_World); @@ -103,13 +102,11 @@ protected: { int m_ChunkX; int m_ChunkZ; - eChunkPriority m_Priority; cClientHandle * m_Client; - sSendChunk(int a_ChunkX, int a_ChunkZ, eChunkPriority a_Priority, cClientHandle * a_Client) : + sSendChunk(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client) : m_ChunkX(a_ChunkX), m_ChunkZ(a_ChunkZ), - m_Priority(a_Priority), m_Client(a_Client) { } @@ -122,11 +119,6 @@ protected: (a_Other.m_Client == m_Client) ); } - - bool operator < (const sSendChunk & a_Other) - { - return (m_Priority < a_Other.m_Priority); - } } ; typedef std::list sSendChunkList; @@ -150,7 +142,8 @@ protected: cCriticalSection m_CS; cChunkCoordsList m_ChunksReady; - sSendChunkList m_SendChunks; + sSendChunkList m_SendChunksLowPriority; + sSendChunkList m_SendChunksHighPriority; cEvent m_evtQueue; // Set when anything is added to m_ChunksReady cEvent m_evtRemoved; // Set when removed clients are safe to be deleted int m_RemoveCount; // Number of threads waiting for a client removal (m_evtRemoved needs to be set this many times) diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index 28fcb0d37..ce5056f30 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -469,47 +469,6 @@ bool cClientHandle::StreamNextChunk(void) } } - // Medium priority: Load the chunks that are behind the player - LookVector = m_Player->GetLookVector() * -1; - for (int Range = 0; Range < 3; Range++) - { - Vector3d Vector = Position + LookVector * cChunkDef::Width * Range; - - // Get the chunk from the x/z coords. - int RangeX, RangeZ = 0; - cChunkDef::BlockToChunk(FloorC(Vector.x), FloorC(Vector.z), RangeX, RangeZ); - - for (size_t X = 0; X < 7; X++) - { - for (size_t Z = 0; Z < 7; Z++) - { - int ChunkX = RangeX + ((X >= 4) ? (3 - X) : X); - int ChunkZ = RangeZ + ((Z >= 4) ? (3 - Z) : Z); - cChunkCoords Coords(ChunkX, ChunkZ); - - // Checks if the chunk is in distance - if ((Diff(ChunkX, ChunkPosX) > m_ViewDistance) || (Diff(ChunkZ, ChunkPosZ) > m_ViewDistance)) - { - continue; - } - - // If the chunk already loading/loaded -> skip - if ( - (std::find(m_ChunksToSend.begin(), m_ChunksToSend.end(), Coords) != m_ChunksToSend.end()) || - (std::find(m_LoadedChunks.begin(), m_LoadedChunks.end(), Coords) != m_LoadedChunks.end()) - ) - { - continue; - } - - // Unloaded chunk found -> Send it to the client. - Lock.Unlock(); - StreamChunk(ChunkX, ChunkZ, cChunkSender::E_CHUNK_PRIORITY_MEDIUM); - return false; - } - } - } - // Low priority: Add all chunks that are in range. (From the center out to the edge) for (int d = 0; d <= m_ViewDistance; ++d) // cycle through (square) distance, from nearest to furthest { -- cgit v1.2.3 From 690e89001ef7211dfc71a457e6893b52baf34387 Mon Sep 17 00:00:00 2001 From: Howaner Date: Tue, 21 Oct 2014 18:13:14 +0200 Subject: Fixed submodule downgrades --- MCServer/Plugins/Core | 2 +- MCServer/Plugins/ProtectionAreas | 2 +- lib/polarssl | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/MCServer/Plugins/Core b/MCServer/Plugins/Core index 3a0e0597b..2dddf205d 160000 --- a/MCServer/Plugins/Core +++ b/MCServer/Plugins/Core @@ -1 +1 @@ -Subproject commit 3a0e0597b7a24c44bf87ec90beb9be48d0b99709 +Subproject commit 2dddf205dd5346363207b72ab289f2a2a60c2583 diff --git a/MCServer/Plugins/ProtectionAreas b/MCServer/Plugins/ProtectionAreas index 7765048fa..624580e5b 160000 --- a/MCServer/Plugins/ProtectionAreas +++ b/MCServer/Plugins/ProtectionAreas @@ -1 +1 @@ -Subproject commit 7765048fa740b8f119db72a4ccc546504f86b2ab +Subproject commit 624580e5b522ba2799dfe5b5902b4002b1a8da3e diff --git a/lib/polarssl b/lib/polarssl index 1ed82759c..d6a15321a 160000 --- a/lib/polarssl +++ b/lib/polarssl @@ -1 +1 @@ -Subproject commit 1ed82759c68f92c4acc7e3f33b850cf9f01c8aba +Subproject commit d6a15321ae51762098e49a976d26efa2493c94f6 -- cgit v1.2.3 From 5d3b6c212f4092398122e528061847ee347bf3fc Mon Sep 17 00:00:00 2001 From: Howaner Date: Tue, 21 Oct 2014 18:30:48 +0200 Subject: Reverted plugin remove --- MCServer/Plugins/ChatLog | 1 + MCServer/Plugins/ChunkWorx | 1 + MCServer/Plugins/Handy | 1 + MCServer/Plugins/MagicCarpet | 1 + 4 files changed, 4 insertions(+) create mode 160000 MCServer/Plugins/ChatLog create mode 160000 MCServer/Plugins/ChunkWorx create mode 160000 MCServer/Plugins/Handy create mode 160000 MCServer/Plugins/MagicCarpet diff --git a/MCServer/Plugins/ChatLog b/MCServer/Plugins/ChatLog new file mode 160000 index 000000000..983d23ca3 --- /dev/null +++ b/MCServer/Plugins/ChatLog @@ -0,0 +1 @@ +Subproject commit 983d23ca37baa89f7e4dc11d71502d9c059f6376 diff --git a/MCServer/Plugins/ChunkWorx b/MCServer/Plugins/ChunkWorx new file mode 160000 index 000000000..894c7e320 --- /dev/null +++ b/MCServer/Plugins/ChunkWorx @@ -0,0 +1 @@ +Subproject commit 894c7e32049e9d2a1e736f7d721aaacd1ae29e53 diff --git a/MCServer/Plugins/Handy b/MCServer/Plugins/Handy new file mode 160000 index 000000000..e64a04be3 --- /dev/null +++ b/MCServer/Plugins/Handy @@ -0,0 +1 @@ +Subproject commit e64a04be39ac7790abcb09de3d4c7d8fc2a2a1e2 diff --git a/MCServer/Plugins/MagicCarpet b/MCServer/Plugins/MagicCarpet new file mode 160000 index 000000000..493f2dfa6 --- /dev/null +++ b/MCServer/Plugins/MagicCarpet @@ -0,0 +1 @@ +Subproject commit 493f2dfa6d39f134e37c4c614cf8d6ffd10c825f -- cgit v1.2.3 From 2d639675516cb563e3f7bf018ee3619970ef1edc Mon Sep 17 00:00:00 2001 From: Howaner Date: Tue, 21 Oct 2014 18:32:02 +0200 Subject: style. --- src/ChunkSender.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ChunkSender.cpp b/src/ChunkSender.cpp index 680f34bce..fdcd485a9 100644 --- a/src/ChunkSender.cpp +++ b/src/ChunkSender.cpp @@ -135,7 +135,8 @@ void cChunkSender::RemoveClient(cClientHandle * a_Client) } // for itr - m_SendChunksLowPriority[] for (sSendChunkList::iterator itr = m_SendChunksHighPriority.begin(); itr != m_SendChunksHighPriority.end();) { - if (itr->m_Client == a_Client) { + if (itr->m_Client == a_Client) + { itr = m_SendChunksHighPriority.erase(itr); continue; } -- cgit v1.2.3 From 07bbfd58949d1155617e969651e89c8392a981c0 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Thu, 23 Oct 2014 12:51:59 +0200 Subject: Fixed a crash in redstone simulator. --- src/Simulator/IncrementalRedstoneSimulator.inc | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Simulator/IncrementalRedstoneSimulator.inc b/src/Simulator/IncrementalRedstoneSimulator.inc index 200fc0971..2d03584e2 100644 --- a/src/Simulator/IncrementalRedstoneSimulator.inc +++ b/src/Simulator/IncrementalRedstoneSimulator.inc @@ -2001,7 +2001,6 @@ bool cIncrementalRedstoneSimulatorUnboundedRelGetBlock(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, Block, OtherRepeaterDir) && (Block == E_BLOCK_REDSTONE_REPEATER_ON)) { - NIBBLETYPE OtherRepeaterDir = m_Chunk->GetMeta(a_RelBlockX -1, a_RelBlockY, a_RelBlockZ) & 0x3; if ((OtherRepeaterDir & 0x03) == 0x1) { return true; -- cgit v1.2.3 From 449d08cb3d1a8ef430430790fcea0ce36b713866 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Thu, 23 Oct 2014 15:15:10 +0200 Subject: Merged IniFile into main MCS sources. --- CMakeLists.txt | 1 - lib/inifile/CMakeLists.txt | 11 - lib/inifile/iniFile.cpp | 908 --------------------------------- lib/inifile/iniFile.h | 224 -------- src/Bindings/AllToLua.pkg | 2 +- src/Bindings/PluginManager.cpp | 2 +- src/BlockID.cpp | 2 +- src/CMakeLists.txt | 4 +- src/Entities/Player.cpp | 2 +- src/Generating/BioGen.cpp | 2 +- src/Generating/ChunkGenerator.cpp | 2 +- src/Generating/CompoGen.cpp | 2 +- src/Generating/ComposableGenerator.cpp | 2 +- src/Generating/DistortedHeightmap.cpp | 2 +- src/Generating/EndGen.cpp | 2 +- src/Generating/FinishGen.cpp | 2 +- src/Generating/HeiGen.cpp | 2 +- src/Generating/Noise3DGenerator.cpp | 2 +- src/HTTPServer/HTTPServer.h | 2 +- src/IniFile.cpp | 908 +++++++++++++++++++++++++++++++++ src/IniFile.h | 224 ++++++++ src/MonsterConfig.cpp | 2 +- src/Protocol/Authenticator.cpp | 2 +- src/Protocol/MojangAPI.cpp | 2 +- src/RCONServer.cpp | 2 +- src/RankManager.cpp | 2 +- src/Root.cpp | 5 +- src/Server.cpp | 2 +- src/Simulator/SandSimulator.cpp | 2 +- src/WebAdmin.h | 2 +- src/World.cpp | 2 +- 31 files changed, 1160 insertions(+), 1171 deletions(-) delete mode 100644 lib/inifile/CMakeLists.txt delete mode 100644 lib/inifile/iniFile.cpp delete mode 100644 lib/inifile/iniFile.h create mode 100644 src/IniFile.cpp create mode 100644 src/IniFile.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 188cf81e3..66281fe0c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,7 +81,6 @@ set(SQLITECPP_BUILD_TESTS OFF CACHE BOOL "Build and run tests." set(SQLITECPP_INTERNAL_SQLITE OFF CACHE BOOL "Add the internal SQLite3 source to the project." FORCE) # Include all the libraries: -add_subdirectory(lib/inifile/) add_subdirectory(lib/jsoncpp/) add_subdirectory(lib/zlib/) add_subdirectory(lib/lua/) diff --git a/lib/inifile/CMakeLists.txt b/lib/inifile/CMakeLists.txt deleted file mode 100644 index 321d501d7..000000000 --- a/lib/inifile/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -cmake_minimum_required (VERSION 2.6) -project (iniFile) - -include_directories ("${PROJECT_SOURCE_DIR}/../../src/") - -file(GLOB SOURCE - "*.h" - "*.cpp" -) - -add_library(iniFile ${SOURCE}) diff --git a/lib/inifile/iniFile.cpp b/lib/inifile/iniFile.cpp deleted file mode 100644 index 7cfe7661f..000000000 --- a/lib/inifile/iniFile.cpp +++ /dev/null @@ -1,908 +0,0 @@ -// IniFile.cpp: Implementation of the CIniFile class. -// Written by: Adam Clauss -// Email: cabadam@houston.rr.com -// You may use this class/code as you wish in your programs. Feel free to distribute it, and -// email suggested changes to me. -// -// Rewritten by: Shane Hill -// Date: 21/08/2001 -// Email: Shane.Hill@dsto.defence.gov.au -// Reason: Remove dependancy on MFC. Code should compile on any -// platform. -////////////////////////////////////////////////////////////////////// - -/* -!! MODIFIED BY FAKETRUTH and xoft !! -*/ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -// C++ Includes -#include - -// C Includes -#include - -// Local Includes -#include "iniFile.h" - -#if defined(WIN32) - #define iniEOL endl -#else - #define iniEOL '\r' << endl -#endif - -#ifndef _WIN32 - #define sscanf_s(buffer, stringbuffer, ...) (sscanf(buffer, stringbuffer, __VA_ARGS__)) -#endif - -using namespace std; - - - - - -cIniFile::cIniFile(void) : - m_IsCaseInsensitive(true) -{ -} - - - - - -bool cIniFile::ReadFile(const AString & a_FileName, bool a_AllowExampleRedirect) -{ - // Normally you would use ifstream, but the SGI CC compiler has - // a few bugs with ifstream. So ... fstream used. - fstream f; - AString line; - AString keyname, valuename, value; - AString::size_type pLeft, pRight; - bool IsFromExampleRedirect = false; - - f.open((FILE_IO_PREFIX + a_FileName).c_str(), ios::in); - if (f.fail()) - { - f.clear(); - if (a_AllowExampleRedirect) - { - // Retry with the .example.ini file instead of .ini: - AString ExPath(a_FileName.substr(0, a_FileName.length() - 4)); - ExPath.append(".example.ini"); - f.open((FILE_IO_PREFIX + ExPath).c_str(), ios::in); - if (f.fail()) - { - return false; - } - IsFromExampleRedirect = true; - } - else - { - return false; - } - } - - bool IsFirstLine = true; - - while (getline(f, line)) - { - // To be compatible with Win32, check for existence of '\r'. - // Win32 files have the '\r' and Unix files don't at the end of a line. - // Note that the '\r' will be written to INI files from - // Unix so that the created INI file can be read under Win32 - // without change. - - // Removes UTF-8 Byte Order Markers (BOM) if, present. - if (IsFirstLine) - { - RemoveBom(line); - IsFirstLine = false; - } - - size_t lineLength = line.length(); - if (lineLength == 0) - { - continue; - } - if (line[lineLength - 1] == '\r') - { - line = line.substr(0, lineLength - 1); - } - - if (line.length() == 0) - { - continue; - } - - // Check that the user hasn't opened a binary file by checking the first - // character of each line! - if (!isprint(line[0])) - { - printf("%s: Binary-check failed on char %d\n", __FUNCTION__, line[0]); - f.close(); - return false; - } - if ((pLeft = line.find_first_of(";#[=")) == AString::npos) - { - continue; - } - - switch (line[pLeft]) - { - case '[': - { - if ( - ((pRight = line.find_last_of("]")) != AString::npos) && - (pRight > pLeft) - ) - { - keyname = line.substr(pLeft + 1, pRight - pLeft - 1); - AddKeyName(keyname); - } - break; - } - - case '=': - { - valuename = line.substr(0, pLeft); - value = line.substr(pLeft + 1); - AddValue(keyname, valuename, value); - break; - } - - case ';': - case '#': - { - if (names.empty()) - { - AddHeaderComment(line.substr(pLeft + 1)); - } - else - { - AddKeyComment(keyname, line.substr(pLeft + 1)); - } - break; - } - } // switch (line[pLeft]) - } // while (getline()) - - f.close(); - if (keys.empty() && names.empty() && comments.empty()) - { - // File be empty or unreadable, equivalent to nonexistant - return false; - } - - if (IsFromExampleRedirect) - { - WriteFile(FILE_IO_PREFIX + a_FileName); - } - - return true; -} - - - - - -bool cIniFile::WriteFile(const AString & a_FileName) const -{ - // Normally you would use ofstream, but the SGI CC compiler has - // a few bugs with ofstream. So ... fstream used. - fstream f; - - f.open((FILE_IO_PREFIX + a_FileName).c_str(), ios::out); - if (f.fail()) - { - return false; - } - - // Write header comments. - size_t NumComments = comments.size(); - for (size_t commentID = 0; commentID < NumComments; ++commentID) - { - f << ';' << comments[commentID] << iniEOL; - } - if (NumComments > 0) - { - f << iniEOL; - } - - // Write keys and values. - for (size_t keyID = 0; keyID < keys.size(); ++keyID) - { - f << '[' << names[keyID] << ']' << iniEOL; - - // Comments. - for (size_t commentID = 0; commentID < keys[keyID].comments.size(); ++commentID) - { - f << ';' << keys[keyID].comments[commentID] << iniEOL; - } - - // Values. - for (size_t valueID = 0; valueID < keys[keyID].names.size(); ++valueID) - { - f << keys[keyID].names[valueID] << '=' << keys[keyID].values[valueID] << iniEOL; - } - f << iniEOL; - } - f.close(); - - return true; -} - - - - - -int cIniFile::FindKey(const AString & a_KeyName) const -{ - AString CaseKeyName = CheckCase(a_KeyName); - for (size_t keyID = 0; keyID < names.size(); ++keyID) - { - if (CheckCase(names[keyID]) == CaseKeyName) - { - return (int)keyID; - } - } - return noID; -} - - - - - -int cIniFile::FindValue(const int keyID, const AString & a_ValueName) const -{ - if (!keys.size() || (keyID >= (int)keys.size())) - { - return noID; - } - - AString CaseValueName = CheckCase(a_ValueName); - for (size_t valueID = 0; valueID < keys[keyID].names.size(); ++valueID) - { - if (CheckCase(keys[keyID].names[valueID]) == CaseValueName) - { - return int(valueID); - } - } - return noID; -} - - - - - -int cIniFile::AddKeyName(const AString & keyname) -{ - names.resize(names.size() + 1, keyname); - keys.resize(keys.size() + 1); - return (int)names.size() - 1; -} - - - - - -AString cIniFile::GetKeyName(const int keyID) const -{ - if (keyID < (int)names.size()) - { - return names[keyID]; - } - else - { - return ""; - } -} - - - - - -int cIniFile::GetNumValues(const int keyID) const -{ - if (keyID < (int)keys.size()) - { - return (int)keys[keyID].names.size(); - } - return 0; -} - - - - - -int cIniFile::GetNumValues(const AString & keyname) const -{ - int keyID = FindKey(keyname); - if (keyID == noID) - { - return 0; - } - return (int)keys[keyID].names.size(); -} - - - - - -AString cIniFile::GetValueName(const int keyID, const int valueID) const -{ - if ((keyID < (int)keys.size()) && (valueID < (int)keys[keyID].names.size())) - { - return keys[keyID].names[valueID]; - } - return ""; -} - - - - - -AString cIniFile::GetValueName(const AString & keyname, const int valueID) const -{ - int keyID = FindKey(keyname); - if (keyID == noID) - { - return ""; - } - return GetValueName(keyID, valueID); -} - - - - - -void cIniFile::AddValue(const AString & a_KeyName, const AString & a_ValueName, const AString & a_Value) -{ - int keyID = FindKey(a_KeyName); - if (keyID == noID) - { - keyID = int(AddKeyName(a_KeyName)); - } - - keys[keyID].names.push_back(a_ValueName); - keys[keyID].values.push_back(a_Value); -} - - - - - -void cIniFile::AddValueI(const AString & a_KeyName, const AString & a_ValueName, const int a_Value) -{ - AddValue(a_KeyName, a_ValueName, Printf("%d", a_Value)); -} - - - - - -void cIniFile::AddValueF(const AString & a_KeyName, const AString & a_ValueName, const double a_Value) -{ - AddValue(a_KeyName, a_ValueName, Printf("%f", a_Value)); -} - - - - - -bool cIniFile::SetValue(const int keyID, const int valueID, const AString & value) -{ - if (((size_t)keyID >= keys.size()) || ((size_t)valueID >= keys[keyID].names.size())) - { - return false; - } - keys[keyID].values[valueID] = value; - return true; -} - - - - - -bool cIniFile::SetValue(const AString & a_KeyName, const AString & a_ValueName, const AString & a_Value, const bool a_CreateIfNotExists) -{ - int keyID = FindKey(a_KeyName); - if (keyID == noID) - { - if (!a_CreateIfNotExists) - { - return false; - } - keyID = AddKeyName(a_KeyName); - } - - int valueID = FindValue(keyID, a_ValueName); - if (valueID == noID) - { - if (!a_CreateIfNotExists) - { - return false; - } - keys[keyID].names.push_back(a_ValueName); - keys[keyID].values.push_back(a_Value); - } - else - { - keys[keyID].values[valueID] = a_Value; - } - - return true; -} - - - - - -bool cIniFile::SetValueI(const AString & a_KeyName, const AString & a_ValueName, const int a_Value, const bool a_CreateIfNotExists) -{ - return SetValue(a_KeyName, a_ValueName, Printf("%d", a_Value), a_CreateIfNotExists); -} - - - - - -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); -} - - - - - -bool cIniFile::SetValueV(const AString & a_KeyName, const AString & a_ValueName, const char * a_Format, ...) -{ - va_list args; - va_start(args, a_Format); - AString Data; - AppendVPrintf(Data, a_Format, args); - va_end(args); - return SetValue(a_KeyName, a_ValueName, Data); -} - - - - - -AString cIniFile::GetValue(const int keyID, const int valueID, const AString & defValue) const -{ - if ((keyID < (int)keys.size()) && (valueID < (int)keys[keyID].names.size())) - { - return keys[keyID].values[valueID]; - } - return defValue; -} - - - - - -AString cIniFile::GetValue(const AString & keyname, const AString & valuename, const AString & defValue) const -{ - int keyID = FindKey(keyname); - if (keyID == noID) - { - return defValue; - } - - int valueID = FindValue(int(keyID), valuename); - if (valueID == noID) - { - return defValue; - } - - return keys[keyID].values[valueID]; -} - - - - - -int cIniFile::GetValueI(const AString & keyname, const AString & valuename, const int defValue) const -{ - AString Data; - Printf(Data, "%d", defValue); - return atoi(GetValue(keyname, valuename, Data).c_str()); -} - - - - - -double cIniFile::GetValueF(const AString & keyname, const AString & valuename, double const defValue) const -{ - AString Data; - Printf(Data, "%f", defValue); - return atof(GetValue(keyname, valuename, Data).c_str()); -} - - - - - -AString cIniFile::GetValueSet(const AString & keyname, const AString & valuename, const AString & defValue) -{ - int keyID = FindKey(keyname); - if (keyID == noID) - { - SetValue(keyname, valuename, defValue); - return defValue; - } - - int valueID = FindValue(int(keyID), valuename); - if (valueID == noID) - { - SetValue(keyname, valuename, defValue); - return defValue; - } - - return keys[keyID].values[valueID]; -} - - - - - -double cIniFile::GetValueSetF(const AString & keyname, const AString & valuename, const double defValue) -{ - AString Data; - Printf(Data, "%f", defValue); - return atof(GetValueSet(keyname, valuename, Data).c_str()); -} - - - - - -int cIniFile::GetValueSetI(const AString & keyname, const AString & valuename, const int defValue) -{ - AString Data; - Printf(Data, "%d", defValue); - return atoi(GetValueSet(keyname, valuename, Data).c_str()); -} - - - - - -Int64 cIniFile::GetValueSetI(const AString & keyname, const AString & valuename, const Int64 defValue) -{ - AString Data; - Printf(Data, "%lld", defValue); - AString resultstring = GetValueSet(keyname, valuename, Data); - Int64 result = defValue; -#ifdef _WIN32 - sscanf_s(resultstring.c_str(), "%lld", &result); -#else - sscanf(resultstring.c_str(), "%lld", &result); -#endif - return result; -} - - - - - -bool cIniFile::DeleteValueByID(const int keyID, const int valueID) -{ - if ((keyID < (int)keys.size()) && (valueID < (int)keys[keyID].names.size())) - { - // This looks strange, but is neccessary. - vector::iterator npos = keys[keyID].names.begin() + valueID; - vector::iterator vpos = keys[keyID].values.begin() + valueID; - keys[keyID].names.erase(npos, npos + 1); - keys[keyID].values.erase(vpos, vpos + 1); - return true; - } - return false; -} - - - - - -bool cIniFile::DeleteValue(const AString & keyname, const AString & valuename) -{ - int keyID = FindKey(keyname); - if (keyID == noID) - { - return false; - } - - int valueID = FindValue(int(keyID), valuename); - if (valueID == noID) - { - return false; - } - - return DeleteValueByID(keyID, valueID); -} - - - - - -bool cIniFile::DeleteKey(const AString & keyname) -{ - int keyID = FindKey(keyname); - if (keyID == noID) - { - return false; - } - - vector::iterator npos = names.begin() + keyID; - vector::iterator kpos = keys.begin() + keyID; - names.erase(npos, npos + 1); - keys.erase(kpos, kpos + 1); - - return true; -} - - - - - -void cIniFile::Clear(void) -{ - names.clear(); - keys.clear(); - comments.clear(); -} - - - - - -bool cIniFile::HasValue(const AString & a_KeyName, const AString & a_ValueName) -{ - // Find the key: - int keyID = FindKey(a_KeyName); - if (keyID == noID) - { - return false; - } - - // Find the value: - int valueID = FindValue(keyID, a_ValueName); - return (valueID != noID); -} - - - - - -void cIniFile::AddHeaderComment(const AString & comment) -{ - comments.push_back(comment); - // comments.resize(comments.size() + 1, comment); -} - - - - - -AString cIniFile::GetHeaderComment(const int commentID) const -{ - if (commentID < (int)comments.size()) - { - return comments[commentID]; - } - return ""; -} - - - - - -bool cIniFile::DeleteHeaderComment(int commentID) -{ - if (commentID < (int)comments.size()) - { - vector::iterator cpos = comments.begin() + commentID; - comments.erase(cpos, cpos + 1); - return true; - } - return false; -} - - - - - -int cIniFile::GetNumKeyComments(const int keyID) const -{ - if (keyID < (int)keys.size()) - { - return (int)keys[keyID].comments.size(); - } - return 0; -} - - - - - -int cIniFile::GetNumKeyComments(const AString & keyname) const -{ - int keyID = FindKey(keyname); - if (keyID == noID) - { - return 0; - } - return (int)keys[keyID].comments.size(); -} - - - - - -bool cIniFile::AddKeyComment(const int keyID, const AString & comment) -{ - if (keyID < (int)keys.size()) - { - keys[keyID].comments.resize(keys[keyID].comments.size() + 1, comment); - return true; - } - return false; -} - - - - - -bool cIniFile::AddKeyComment(const AString & keyname, const AString & comment) -{ - int keyID = FindKey(keyname); - if (keyID == noID) - { - return false; - } - return AddKeyComment(keyID, comment); -} - - - - - -AString cIniFile::GetKeyComment(const int keyID, const int commentID) const -{ - if ((keyID < (int)keys.size()) && (commentID < (int)keys[keyID].comments.size())) - { - return keys[keyID].comments[commentID]; - } - return ""; -} - - - - - -AString cIniFile::GetKeyComment(const AString & keyname, const int commentID) const -{ - int keyID = FindKey(keyname); - if (keyID == noID) - { - return ""; - } - return GetKeyComment(int(keyID), commentID); -} - - - - - -bool cIniFile::DeleteKeyComment(const int keyID, const int commentID) -{ - if ((keyID < (int)keys.size()) && (commentID < (int)keys[keyID].comments.size())) - { - vector::iterator cpos = keys[keyID].comments.begin() + commentID; - keys[keyID].comments.erase(cpos, cpos + 1); - return true; - } - return false; -} - - - - - -bool cIniFile::DeleteKeyComment(const AString & keyname, const int commentID) -{ - int keyID = FindKey(keyname); - if (keyID == noID) - { - return false; - } - return DeleteKeyComment(int(keyID), commentID); -} - - - - - -bool cIniFile::DeleteKeyComments(const int keyID) -{ - if (keyID < (int)keys.size()) - { - keys[keyID].comments.clear(); - return true; - } - return false; -} - - - - - -bool cIniFile::DeleteKeyComments(const AString & keyname) -{ - int keyID = FindKey(keyname); - if (keyID == noID) - { - return false; - } - return DeleteKeyComments(int(keyID)); -} - - - - - -AString cIniFile::CheckCase(const AString & s) const -{ - if (!m_IsCaseInsensitive) - { - return s; - } - AString res(s); - size_t len = res.length(); - for (size_t i = 0; i < len; i++) - { - res[i] = tolower(res[i]); - } - return res; -} - - - - - -void cIniFile::RemoveBom(AString & a_line) const -{ - // The BOM sequence for UTF-8 is 0xEF,0xBB,0xBF - static unsigned const char BOM[] = { 0xEF, 0xBB, 0xBF }; - - // The BOM sequence, if present, is always th e first three characters of the input. - const AString ref = a_line.substr(0, 3); - - // If any of the first three chars do not match, return and do nothing. - for (int i = 0; i < 3; ++i) - { - if (static_cast(ref[i]) != BOM[i]) - { - return; - } - } - - // First three characters match; erase them. - a_line.erase(0, 3); -} - - - - diff --git a/lib/inifile/iniFile.h b/lib/inifile/iniFile.h deleted file mode 100644 index 33229bff0..000000000 --- a/lib/inifile/iniFile.h +++ /dev/null @@ -1,224 +0,0 @@ -// IniFile.cpp: Implementation of the CIniFile class. -// Written by: Adam Clauss -// Email: cabadam@tamu.edu -// You may use this class/code as you wish in your programs. Feel free to distribute it, and -// email suggested changes to me. -// -// Rewritten by: Shane Hill -// Date: 21/08/2001 -// Email: Shane.Hill@dsto.defence.gov.au -// Reason: Remove dependancy on MFC. Code should compile on any -// platform. Tested on Windows/Linux/Irix -////////////////////////////////////////////////////////////////////// - -/* -!! MODIFIED BY FAKETRUTH and madmaxoft!! -*/ - -#ifndef CIniFile_H -#define CIniFile_H - - - - - -#define MAX_KEYNAME 128 -#define MAX_VALUENAME 128 -#define MAX_VALUEDATA 2048 - - - - - -// tolua_begin - -class cIniFile -{ -private: - bool m_IsCaseInsensitive; - - struct key - { - std::vector names; - std::vector values; - std::vector comments; - } ; - - std::vector keys; - std::vector names; - std::vector comments; - - /// If the object is case-insensitive, returns s as lowercase; otherwise returns s as-is - AString CheckCase(const AString & s) const; - - /// Removes the UTF-8 BOMs (Byte order makers), if present. - void RemoveBom(AString & a_line) const; - -public: - - enum errors - { - noID = -1, - }; - - /// Creates a new instance with no data - cIniFile(void); - - // Sets whether or not keynames and valuenames should be case sensitive. - // The default is case insensitive. - void CaseSensitive (void) { m_IsCaseInsensitive = false; } - void CaseInsensitive(void) { m_IsCaseInsensitive = true; } - - /** Reads the contents of the specified ini file - If the file doesn't exist and a_AllowExampleRedirect is true, tries to read .example.ini, and - writes its contents as .ini, if successful. - Returns true if successful, false otherwise. - */ - bool ReadFile(const AString & a_FileName, bool a_AllowExampleRedirect = true); - - /// Writes data stored in class to the specified ini file - bool WriteFile(const AString & a_FileName) const; - - /// Deletes all stored ini data (but doesn't touch the file) - void Clear(void); - - /** Returns true iff the specified value exists. */ - bool HasValue(const AString & a_KeyName, const AString & a_ValueName); - - /// Returns index of specified key, or noID if not found - int FindKey(const AString & keyname) const; - - /// Returns index of specified value, in the specified key, or noID if not found - int FindValue(const int keyID, const AString & valuename) const; - - /// Returns number of keys currently in the ini - int GetNumKeys(void) const { return (int)keys.size(); } - - /// Add a key name - int AddKeyName(const AString & keyname); - - // Returns key names by index. - AString GetKeyName(const int keyID) const; - - // Returns number of values stored for specified key. - int GetNumValues(const AString & keyname) const; - int GetNumValues(const int keyID) const; - - // Returns value name by index for a given keyname or keyID. - AString GetValueName(const AString & keyname, const int valueID) const; - AString GetValueName(const int keyID, const int valueID) const; - - // Gets value of [keyname] valuename =. - // Overloaded to return string, int, and double. - // Returns defValue if key/value not found. - AString GetValue (const AString & keyname, const AString & valuename, const AString & defValue = "") const; - AString GetValue (const int keyID, const int valueID, const AString & defValue = "") const; - double GetValueF(const AString & keyname, const AString & valuename, const double defValue = 0) const; - int GetValueI(const AString & keyname, const AString & valuename, const int defValue = 0) const; - bool GetValueB(const AString & keyname, const AString & valuename, const bool defValue = false) const - { - return (GetValueI(keyname, valuename, defValue ? 1 : 0) != 0); - } - - // Gets the value; if not found, write the default to the INI file - 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); - } - - // Adds a new value to the specified key. - // If a value of the same name already exists, creates another one (non-standard INI file) - void AddValue (const AString & a_KeyName, const AString & a_ValueName, const AString & a_Value); - void AddValueI(const AString & a_KeyName, const AString & a_ValueName, const int a_Value); - void AddValueB(const AString & a_KeyName, const AString & a_ValueName, const bool a_Value) - { - return AddValueI(a_KeyName, a_ValueName, a_Value ? 1 : 0); - } - void AddValueF(const AString & a_KeyName, const AString & a_ValueName, const double a_Value); - - // Overwrites the value of [keyname].valuename - // Specify the optional parameter as false (0) if you do not want the value created if it doesn't exist. - // Returns true if value set, false otherwise. - // Overloaded to accept string, int, and double. - 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); - } - bool SetValueF(const AString & a_KeyName, const AString & a_ValueName, const double a_Value, const bool a_CreateIfNotExists = true); - - // tolua_end - - bool SetValueV( const AString & a_KeyName, const AString & a_ValueName, const char * a_Format, ...); - - // tolua_begin - - // Deletes specified value. - // Returns true if value existed and deleted, false otherwise. - bool DeleteValueByID(const int keyID, const int valueID); - bool DeleteValue(const AString & keyname, const AString & valuename); - - // Deletes specified key and all values contained within. - // Returns true if key existed and deleted, false otherwise. - bool DeleteKey(const AString & keyname); - - // Header comment functions. - // Header comments are those comments before the first key. - - /// Returns the number of header comments - int GetNumHeaderComments(void) {return (int)comments.size();} - - /// Adds a header comment - void AddHeaderComment(const AString & comment); - - /// Returns a header comment, or empty string if out of range - AString GetHeaderComment(const int commentID) const; - - /// Deletes a header comment. Returns true if successful - bool DeleteHeaderComment(int commentID); - - /// Deletes all header comments - void DeleteHeaderComments(void) {comments.clear();} - - - // Key comment functions. - // Key comments are those comments within a key. Any comments - // defined within value names will be added to this list. Therefore, - // these comments will be moved to the top of the key definition when - // the CIniFile::WriteFile() is called. - - /// Get number of key comments - int GetNumKeyComments(const int keyID) const; - - /// Get number of key comments - int GetNumKeyComments(const AString & keyname) const; - - /// Add a key comment - bool AddKeyComment(const int keyID, const AString & comment); - - /// Add a key comment - bool AddKeyComment(const AString & keyname, const AString & comment); - - /// Return a key comment - AString GetKeyComment(const int keyID, const int commentID) const; - AString GetKeyComment(const AString & keyname, const int commentID) const; - - // Delete a key comment. - bool DeleteKeyComment(const int keyID, const int commentID); - bool DeleteKeyComment(const AString & keyname, const int commentID); - - // Delete all comments for a key. - bool DeleteKeyComments(const int keyID); - bool DeleteKeyComments(const AString & keyname); -}; - -// tolua_end - -#endif diff --git a/src/Bindings/AllToLua.pkg b/src/Bindings/AllToLua.pkg index 1bff26b0e..7b78578ee 100644 --- a/src/Bindings/AllToLua.pkg +++ b/src/Bindings/AllToLua.pkg @@ -15,7 +15,7 @@ $cfile "../Vector3.h" $cfile "../ChunkDef.h" $cfile "../BiomeDef.h" -$cfile "../../lib/inifile/iniFile.h" +$cfile "../IniFile.h" $cfile "../OSSupport/File.h" diff --git a/src/Bindings/PluginManager.cpp b/src/Bindings/PluginManager.cpp index e549aefa3..f63578885 100644 --- a/src/Bindings/PluginManager.cpp +++ b/src/Bindings/PluginManager.cpp @@ -9,7 +9,7 @@ #include "../Server.h" #include "../CommandOutput.h" -#include "inifile/iniFile.h" +#include "../IniFile.h" #include "../Entities/Player.h" #define FIND_HOOK(a_HookName) HookMap::iterator Plugins = m_Hooks.find(a_HookName); diff --git a/src/BlockID.cpp b/src/BlockID.cpp index 755c721db..c0f3193bb 100644 --- a/src/BlockID.cpp +++ b/src/BlockID.cpp @@ -4,7 +4,7 @@ #include "Globals.h" #include "BlockID.h" -#include "inifile/iniFile.h" +#include "IniFile.h" #include "Item.h" #include "Mobs/Monster.h" diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9d0e2cede..096fa824d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -34,6 +34,7 @@ SET (SRCS FastRandom.cpp FurnaceRecipe.cpp Globals.cpp + IniFile.cpp Inventory.cpp Item.cpp ItemGrid.cpp @@ -98,6 +99,7 @@ SET (HDRS ForEachChunkProvider.h FurnaceRecipe.h Globals.h + IniFile.h Inventory.h Item.h ItemGrid.h @@ -320,4 +322,4 @@ endif () if (WIN32) target_link_libraries(${EXECUTABLE} expat tolualib ws2_32.lib Psapi.lib) endif() -target_link_libraries(${EXECUTABLE} luaexpat iniFile jsoncpp polarssl zlib sqlite lua SQLiteCpp) +target_link_libraries(${EXECUTABLE} luaexpat jsoncpp polarssl zlib sqlite lua SQLiteCpp) diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 790147fd3..1f1627f8a 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -20,7 +20,7 @@ #include "../WorldStorage/StatSerializer.h" #include "../CompositeChat.h" -#include "inifile/iniFile.h" +#include "../IniFile.h" #include "json/json.h" // 6000 ticks or 5 minutes diff --git a/src/Generating/BioGen.cpp b/src/Generating/BioGen.cpp index d86d44bbc..203faff56 100644 --- a/src/Generating/BioGen.cpp +++ b/src/Generating/BioGen.cpp @@ -5,7 +5,7 @@ #include "Globals.h" #include "BioGen.h" -#include "inifile/iniFile.h" +#include "../IniFile.h" #include "../LinearUpscale.h" diff --git a/src/Generating/ChunkGenerator.cpp b/src/Generating/ChunkGenerator.cpp index 1eecd6e51..92e1bb31d 100644 --- a/src/Generating/ChunkGenerator.cpp +++ b/src/Generating/ChunkGenerator.cpp @@ -2,7 +2,7 @@ #include "Globals.h" #include "ChunkGenerator.h" -#include "inifile/iniFile.h" +#include "../IniFile.h" #include "ChunkDesc.h" #include "ComposableGenerator.h" #include "Noise3DGenerator.h" diff --git a/src/Generating/CompoGen.cpp b/src/Generating/CompoGen.cpp index 2c88f23f1..29b831dfd 100644 --- a/src/Generating/CompoGen.cpp +++ b/src/Generating/CompoGen.cpp @@ -12,7 +12,7 @@ #include "../BlockID.h" #include "../Item.h" #include "../LinearUpscale.h" -#include "inifile/iniFile.h" +#include "../IniFile.h" diff --git a/src/Generating/ComposableGenerator.cpp b/src/Generating/ComposableGenerator.cpp index 9a52588d5..169821050 100644 --- a/src/Generating/ComposableGenerator.cpp +++ b/src/Generating/ComposableGenerator.cpp @@ -7,7 +7,7 @@ #include "ComposableGenerator.h" #include "../World.h" -#include "inifile/iniFile.h" +#include "../IniFile.h" #include "../Root.h" // Individual composed algorithms: diff --git a/src/Generating/DistortedHeightmap.cpp b/src/Generating/DistortedHeightmap.cpp index e6849fadf..aac1d2bf3 100644 --- a/src/Generating/DistortedHeightmap.cpp +++ b/src/Generating/DistortedHeightmap.cpp @@ -7,7 +7,7 @@ #include "DistortedHeightmap.h" #include "../OSSupport/File.h" -#include "inifile/iniFile.h" +#include "../IniFile.h" #include "../LinearUpscale.h" diff --git a/src/Generating/EndGen.cpp b/src/Generating/EndGen.cpp index c94cd1eff..0111d2fa3 100644 --- a/src/Generating/EndGen.cpp +++ b/src/Generating/EndGen.cpp @@ -5,7 +5,7 @@ #include "Globals.h" #include "EndGen.h" -#include "inifile/iniFile.h" +#include "../IniFile.h" #include "../LinearUpscale.h" diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index 96e3dc26b..0564789dc 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -15,7 +15,7 @@ #include "../Simulator/FluidSimulator.h" // for cFluidSimulator::CanWashAway() #include "../Simulator/FireSimulator.h" #include "../World.h" -#include "inifile/iniFile.h" +#include "../IniFile.h" diff --git a/src/Generating/HeiGen.cpp b/src/Generating/HeiGen.cpp index acfefaefc..a0b8770f5 100644 --- a/src/Generating/HeiGen.cpp +++ b/src/Generating/HeiGen.cpp @@ -6,7 +6,7 @@ #include "Globals.h" #include "HeiGen.h" #include "../LinearUpscale.h" -#include "inifile/iniFile.h" +#include "../IniFile.h" #include "DistortedHeightmap.h" #include "EndGen.h" #include "Noise3DGenerator.h" diff --git a/src/Generating/Noise3DGenerator.cpp b/src/Generating/Noise3DGenerator.cpp index c3ca30384..5a4cb44cf 100644 --- a/src/Generating/Noise3DGenerator.cpp +++ b/src/Generating/Noise3DGenerator.cpp @@ -6,7 +6,7 @@ #include "Globals.h" #include "Noise3DGenerator.h" #include "../OSSupport/File.h" -#include "inifile/iniFile.h" +#include "../IniFile.h" #include "../LinearInterpolation.h" #include "../LinearUpscale.h" diff --git a/src/HTTPServer/HTTPServer.h b/src/HTTPServer/HTTPServer.h index 522b7da62..73d4cbdd0 100644 --- a/src/HTTPServer/HTTPServer.h +++ b/src/HTTPServer/HTTPServer.h @@ -11,7 +11,7 @@ #include "../OSSupport/ListenThread.h" #include "../OSSupport/SocketThreads.h" -#include "inifile/iniFile.h" +#include "../IniFile.h" #include "PolarSSL++/RsaPrivateKey.h" #include "PolarSSL++/CryptoKey.h" #include "PolarSSL++/X509Cert.h" diff --git a/src/IniFile.cpp b/src/IniFile.cpp new file mode 100644 index 000000000..517fd36af --- /dev/null +++ b/src/IniFile.cpp @@ -0,0 +1,908 @@ +// IniFile.cpp: Implementation of the CIniFile class. +// Written by: Adam Clauss +// Email: cabadam@houston.rr.com +// You may use this class/code as you wish in your programs. Feel free to distribute it, and +// email suggested changes to me. +// +// Rewritten by: Shane Hill +// Date: 21/08/2001 +// Email: Shane.Hill@dsto.defence.gov.au +// Reason: Remove dependancy on MFC. Code should compile on any +// platform. +////////////////////////////////////////////////////////////////////// + +/* +!! MODIFIED BY FAKETRUTH and xoft !! +*/ + +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +// C++ Includes +#include + +// C Includes +#include + +// Local Includes +#include "IniFile.h" + +#if defined(WIN32) + #define iniEOL endl +#else + #define iniEOL '\r' << endl +#endif + +#ifndef _WIN32 + #define sscanf_s(buffer, stringbuffer, ...) (sscanf(buffer, stringbuffer, __VA_ARGS__)) +#endif + +using namespace std; + + + + + +cIniFile::cIniFile(void) : + m_IsCaseInsensitive(true) +{ +} + + + + + +bool cIniFile::ReadFile(const AString & a_FileName, bool a_AllowExampleRedirect) +{ + // Normally you would use ifstream, but the SGI CC compiler has + // a few bugs with ifstream. So ... fstream used. + fstream f; + AString line; + AString keyname, valuename, value; + AString::size_type pLeft, pRight; + bool IsFromExampleRedirect = false; + + f.open((FILE_IO_PREFIX + a_FileName).c_str(), ios::in); + if (f.fail()) + { + f.clear(); + if (a_AllowExampleRedirect) + { + // Retry with the .example.ini file instead of .ini: + AString ExPath(a_FileName.substr(0, a_FileName.length() - 4)); + ExPath.append(".example.ini"); + f.open((FILE_IO_PREFIX + ExPath).c_str(), ios::in); + if (f.fail()) + { + return false; + } + IsFromExampleRedirect = true; + } + else + { + return false; + } + } + + bool IsFirstLine = true; + + while (getline(f, line)) + { + // To be compatible with Win32, check for existence of '\r'. + // Win32 files have the '\r' and Unix files don't at the end of a line. + // Note that the '\r' will be written to INI files from + // Unix so that the created INI file can be read under Win32 + // without change. + + // Removes UTF-8 Byte Order Markers (BOM) if, present. + if (IsFirstLine) + { + RemoveBom(line); + IsFirstLine = false; + } + + size_t lineLength = line.length(); + if (lineLength == 0) + { + continue; + } + if (line[lineLength - 1] == '\r') + { + line = line.substr(0, lineLength - 1); + } + + if (line.length() == 0) + { + continue; + } + + // Check that the user hasn't opened a binary file by checking the first + // character of each line! + if (!isprint(line[0])) + { + printf("%s: Binary-check failed on char %d\n", __FUNCTION__, line[0]); + f.close(); + return false; + } + if ((pLeft = line.find_first_of(";#[=")) == AString::npos) + { + continue; + } + + switch (line[pLeft]) + { + case '[': + { + if ( + ((pRight = line.find_last_of("]")) != AString::npos) && + (pRight > pLeft) + ) + { + keyname = line.substr(pLeft + 1, pRight - pLeft - 1); + AddKeyName(keyname); + } + break; + } + + case '=': + { + valuename = line.substr(0, pLeft); + value = line.substr(pLeft + 1); + AddValue(keyname, valuename, value); + break; + } + + case ';': + case '#': + { + if (names.empty()) + { + AddHeaderComment(line.substr(pLeft + 1)); + } + else + { + AddKeyComment(keyname, line.substr(pLeft + 1)); + } + break; + } + } // switch (line[pLeft]) + } // while (getline()) + + f.close(); + if (keys.empty() && names.empty() && comments.empty()) + { + // File be empty or unreadable, equivalent to nonexistant + return false; + } + + if (IsFromExampleRedirect) + { + WriteFile(FILE_IO_PREFIX + a_FileName); + } + + return true; +} + + + + + +bool cIniFile::WriteFile(const AString & a_FileName) const +{ + // Normally you would use ofstream, but the SGI CC compiler has + // a few bugs with ofstream. So ... fstream used. + fstream f; + + f.open((FILE_IO_PREFIX + a_FileName).c_str(), ios::out); + if (f.fail()) + { + return false; + } + + // Write header comments. + size_t NumComments = comments.size(); + for (size_t commentID = 0; commentID < NumComments; ++commentID) + { + f << ';' << comments[commentID] << iniEOL; + } + if (NumComments > 0) + { + f << iniEOL; + } + + // Write keys and values. + for (size_t keyID = 0; keyID < keys.size(); ++keyID) + { + f << '[' << names[keyID] << ']' << iniEOL; + + // Comments. + for (size_t commentID = 0; commentID < keys[keyID].comments.size(); ++commentID) + { + f << ';' << keys[keyID].comments[commentID] << iniEOL; + } + + // Values. + for (size_t valueID = 0; valueID < keys[keyID].names.size(); ++valueID) + { + f << keys[keyID].names[valueID] << '=' << keys[keyID].values[valueID] << iniEOL; + } + f << iniEOL; + } + f.close(); + + return true; +} + + + + + +int cIniFile::FindKey(const AString & a_KeyName) const +{ + AString CaseKeyName = CheckCase(a_KeyName); + for (size_t keyID = 0; keyID < names.size(); ++keyID) + { + if (CheckCase(names[keyID]) == CaseKeyName) + { + return (int)keyID; + } + } + return noID; +} + + + + + +int cIniFile::FindValue(const int keyID, const AString & a_ValueName) const +{ + if (!keys.size() || (keyID >= (int)keys.size())) + { + return noID; + } + + AString CaseValueName = CheckCase(a_ValueName); + for (size_t valueID = 0; valueID < keys[keyID].names.size(); ++valueID) + { + if (CheckCase(keys[keyID].names[valueID]) == CaseValueName) + { + return int(valueID); + } + } + return noID; +} + + + + + +int cIniFile::AddKeyName(const AString & keyname) +{ + names.resize(names.size() + 1, keyname); + keys.resize(keys.size() + 1); + return (int)names.size() - 1; +} + + + + + +AString cIniFile::GetKeyName(const int keyID) const +{ + if (keyID < (int)names.size()) + { + return names[keyID]; + } + else + { + return ""; + } +} + + + + + +int cIniFile::GetNumValues(const int keyID) const +{ + if (keyID < (int)keys.size()) + { + return (int)keys[keyID].names.size(); + } + return 0; +} + + + + + +int cIniFile::GetNumValues(const AString & keyname) const +{ + int keyID = FindKey(keyname); + if (keyID == noID) + { + return 0; + } + return (int)keys[keyID].names.size(); +} + + + + + +AString cIniFile::GetValueName(const int keyID, const int valueID) const +{ + if ((keyID < (int)keys.size()) && (valueID < (int)keys[keyID].names.size())) + { + return keys[keyID].names[valueID]; + } + return ""; +} + + + + + +AString cIniFile::GetValueName(const AString & keyname, const int valueID) const +{ + int keyID = FindKey(keyname); + if (keyID == noID) + { + return ""; + } + return GetValueName(keyID, valueID); +} + + + + + +void cIniFile::AddValue(const AString & a_KeyName, const AString & a_ValueName, const AString & a_Value) +{ + int keyID = FindKey(a_KeyName); + if (keyID == noID) + { + keyID = int(AddKeyName(a_KeyName)); + } + + keys[keyID].names.push_back(a_ValueName); + keys[keyID].values.push_back(a_Value); +} + + + + + +void cIniFile::AddValueI(const AString & a_KeyName, const AString & a_ValueName, const int a_Value) +{ + AddValue(a_KeyName, a_ValueName, Printf("%d", a_Value)); +} + + + + + +void cIniFile::AddValueF(const AString & a_KeyName, const AString & a_ValueName, const double a_Value) +{ + AddValue(a_KeyName, a_ValueName, Printf("%f", a_Value)); +} + + + + + +bool cIniFile::SetValue(const int keyID, const int valueID, const AString & value) +{ + if (((size_t)keyID >= keys.size()) || ((size_t)valueID >= keys[keyID].names.size())) + { + return false; + } + keys[keyID].values[valueID] = value; + return true; +} + + + + + +bool cIniFile::SetValue(const AString & a_KeyName, const AString & a_ValueName, const AString & a_Value, const bool a_CreateIfNotExists) +{ + int keyID = FindKey(a_KeyName); + if (keyID == noID) + { + if (!a_CreateIfNotExists) + { + return false; + } + keyID = AddKeyName(a_KeyName); + } + + int valueID = FindValue(keyID, a_ValueName); + if (valueID == noID) + { + if (!a_CreateIfNotExists) + { + return false; + } + keys[keyID].names.push_back(a_ValueName); + keys[keyID].values.push_back(a_Value); + } + else + { + keys[keyID].values[valueID] = a_Value; + } + + return true; +} + + + + + +bool cIniFile::SetValueI(const AString & a_KeyName, const AString & a_ValueName, const int a_Value, const bool a_CreateIfNotExists) +{ + return SetValue(a_KeyName, a_ValueName, Printf("%d", a_Value), a_CreateIfNotExists); +} + + + + + +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); +} + + + + + +bool cIniFile::SetValueV(const AString & a_KeyName, const AString & a_ValueName, const char * a_Format, ...) +{ + va_list args; + va_start(args, a_Format); + AString Data; + AppendVPrintf(Data, a_Format, args); + va_end(args); + return SetValue(a_KeyName, a_ValueName, Data); +} + + + + + +AString cIniFile::GetValue(const int keyID, const int valueID, const AString & defValue) const +{ + if ((keyID < (int)keys.size()) && (valueID < (int)keys[keyID].names.size())) + { + return keys[keyID].values[valueID]; + } + return defValue; +} + + + + + +AString cIniFile::GetValue(const AString & keyname, const AString & valuename, const AString & defValue) const +{ + int keyID = FindKey(keyname); + if (keyID == noID) + { + return defValue; + } + + int valueID = FindValue(int(keyID), valuename); + if (valueID == noID) + { + return defValue; + } + + return keys[keyID].values[valueID]; +} + + + + + +int cIniFile::GetValueI(const AString & keyname, const AString & valuename, const int defValue) const +{ + AString Data; + Printf(Data, "%d", defValue); + return atoi(GetValue(keyname, valuename, Data).c_str()); +} + + + + + +double cIniFile::GetValueF(const AString & keyname, const AString & valuename, double const defValue) const +{ + AString Data; + Printf(Data, "%f", defValue); + return atof(GetValue(keyname, valuename, Data).c_str()); +} + + + + + +AString cIniFile::GetValueSet(const AString & keyname, const AString & valuename, const AString & defValue) +{ + int keyID = FindKey(keyname); + if (keyID == noID) + { + SetValue(keyname, valuename, defValue); + return defValue; + } + + int valueID = FindValue(int(keyID), valuename); + if (valueID == noID) + { + SetValue(keyname, valuename, defValue); + return defValue; + } + + return keys[keyID].values[valueID]; +} + + + + + +double cIniFile::GetValueSetF(const AString & keyname, const AString & valuename, const double defValue) +{ + AString Data; + Printf(Data, "%f", defValue); + return atof(GetValueSet(keyname, valuename, Data).c_str()); +} + + + + + +int cIniFile::GetValueSetI(const AString & keyname, const AString & valuename, const int defValue) +{ + AString Data; + Printf(Data, "%d", defValue); + return atoi(GetValueSet(keyname, valuename, Data).c_str()); +} + + + + + +Int64 cIniFile::GetValueSetI(const AString & keyname, const AString & valuename, const Int64 defValue) +{ + AString Data; + Printf(Data, "%lld", defValue); + AString resultstring = GetValueSet(keyname, valuename, Data); + Int64 result = defValue; +#ifdef _WIN32 + sscanf_s(resultstring.c_str(), "%lld", &result); +#else + sscanf(resultstring.c_str(), "%lld", &result); +#endif + return result; +} + + + + + +bool cIniFile::DeleteValueByID(const int keyID, const int valueID) +{ + if ((keyID < (int)keys.size()) && (valueID < (int)keys[keyID].names.size())) + { + // This looks strange, but is neccessary. + vector::iterator npos = keys[keyID].names.begin() + valueID; + vector::iterator vpos = keys[keyID].values.begin() + valueID; + keys[keyID].names.erase(npos, npos + 1); + keys[keyID].values.erase(vpos, vpos + 1); + return true; + } + return false; +} + + + + + +bool cIniFile::DeleteValue(const AString & keyname, const AString & valuename) +{ + int keyID = FindKey(keyname); + if (keyID == noID) + { + return false; + } + + int valueID = FindValue(int(keyID), valuename); + if (valueID == noID) + { + return false; + } + + return DeleteValueByID(keyID, valueID); +} + + + + + +bool cIniFile::DeleteKey(const AString & keyname) +{ + int keyID = FindKey(keyname); + if (keyID == noID) + { + return false; + } + + vector::iterator npos = names.begin() + keyID; + vector::iterator kpos = keys.begin() + keyID; + names.erase(npos, npos + 1); + keys.erase(kpos, kpos + 1); + + return true; +} + + + + + +void cIniFile::Clear(void) +{ + names.clear(); + keys.clear(); + comments.clear(); +} + + + + + +bool cIniFile::HasValue(const AString & a_KeyName, const AString & a_ValueName) +{ + // Find the key: + int keyID = FindKey(a_KeyName); + if (keyID == noID) + { + return false; + } + + // Find the value: + int valueID = FindValue(keyID, a_ValueName); + return (valueID != noID); +} + + + + + +void cIniFile::AddHeaderComment(const AString & comment) +{ + comments.push_back(comment); + // comments.resize(comments.size() + 1, comment); +} + + + + + +AString cIniFile::GetHeaderComment(const int commentID) const +{ + if (commentID < (int)comments.size()) + { + return comments[commentID]; + } + return ""; +} + + + + + +bool cIniFile::DeleteHeaderComment(int commentID) +{ + if (commentID < (int)comments.size()) + { + vector::iterator cpos = comments.begin() + commentID; + comments.erase(cpos, cpos + 1); + return true; + } + return false; +} + + + + + +int cIniFile::GetNumKeyComments(const int keyID) const +{ + if (keyID < (int)keys.size()) + { + return (int)keys[keyID].comments.size(); + } + return 0; +} + + + + + +int cIniFile::GetNumKeyComments(const AString & keyname) const +{ + int keyID = FindKey(keyname); + if (keyID == noID) + { + return 0; + } + return (int)keys[keyID].comments.size(); +} + + + + + +bool cIniFile::AddKeyComment(const int keyID, const AString & comment) +{ + if (keyID < (int)keys.size()) + { + keys[keyID].comments.resize(keys[keyID].comments.size() + 1, comment); + return true; + } + return false; +} + + + + + +bool cIniFile::AddKeyComment(const AString & keyname, const AString & comment) +{ + int keyID = FindKey(keyname); + if (keyID == noID) + { + return false; + } + return AddKeyComment(keyID, comment); +} + + + + + +AString cIniFile::GetKeyComment(const int keyID, const int commentID) const +{ + if ((keyID < (int)keys.size()) && (commentID < (int)keys[keyID].comments.size())) + { + return keys[keyID].comments[commentID]; + } + return ""; +} + + + + + +AString cIniFile::GetKeyComment(const AString & keyname, const int commentID) const +{ + int keyID = FindKey(keyname); + if (keyID == noID) + { + return ""; + } + return GetKeyComment(int(keyID), commentID); +} + + + + + +bool cIniFile::DeleteKeyComment(const int keyID, const int commentID) +{ + if ((keyID < (int)keys.size()) && (commentID < (int)keys[keyID].comments.size())) + { + vector::iterator cpos = keys[keyID].comments.begin() + commentID; + keys[keyID].comments.erase(cpos, cpos + 1); + return true; + } + return false; +} + + + + + +bool cIniFile::DeleteKeyComment(const AString & keyname, const int commentID) +{ + int keyID = FindKey(keyname); + if (keyID == noID) + { + return false; + } + return DeleteKeyComment(int(keyID), commentID); +} + + + + + +bool cIniFile::DeleteKeyComments(const int keyID) +{ + if (keyID < (int)keys.size()) + { + keys[keyID].comments.clear(); + return true; + } + return false; +} + + + + + +bool cIniFile::DeleteKeyComments(const AString & keyname) +{ + int keyID = FindKey(keyname); + if (keyID == noID) + { + return false; + } + return DeleteKeyComments(int(keyID)); +} + + + + + +AString cIniFile::CheckCase(const AString & s) const +{ + if (!m_IsCaseInsensitive) + { + return s; + } + AString res(s); + size_t len = res.length(); + for (size_t i = 0; i < len; i++) + { + res[i] = tolower(res[i]); + } + return res; +} + + + + + +void cIniFile::RemoveBom(AString & a_line) const +{ + // The BOM sequence for UTF-8 is 0xEF,0xBB,0xBF + static unsigned const char BOM[] = { 0xEF, 0xBB, 0xBF }; + + // The BOM sequence, if present, is always th e first three characters of the input. + const AString ref = a_line.substr(0, 3); + + // If any of the first three chars do not match, return and do nothing. + for (int i = 0; i < 3; ++i) + { + if (static_cast(ref[i]) != BOM[i]) + { + return; + } + } + + // First three characters match; erase them. + a_line.erase(0, 3); +} + + + + diff --git a/src/IniFile.h b/src/IniFile.h new file mode 100644 index 000000000..33229bff0 --- /dev/null +++ b/src/IniFile.h @@ -0,0 +1,224 @@ +// IniFile.cpp: Implementation of the CIniFile class. +// Written by: Adam Clauss +// Email: cabadam@tamu.edu +// You may use this class/code as you wish in your programs. Feel free to distribute it, and +// email suggested changes to me. +// +// Rewritten by: Shane Hill +// Date: 21/08/2001 +// Email: Shane.Hill@dsto.defence.gov.au +// Reason: Remove dependancy on MFC. Code should compile on any +// platform. Tested on Windows/Linux/Irix +////////////////////////////////////////////////////////////////////// + +/* +!! MODIFIED BY FAKETRUTH and madmaxoft!! +*/ + +#ifndef CIniFile_H +#define CIniFile_H + + + + + +#define MAX_KEYNAME 128 +#define MAX_VALUENAME 128 +#define MAX_VALUEDATA 2048 + + + + + +// tolua_begin + +class cIniFile +{ +private: + bool m_IsCaseInsensitive; + + struct key + { + std::vector names; + std::vector values; + std::vector comments; + } ; + + std::vector keys; + std::vector names; + std::vector comments; + + /// If the object is case-insensitive, returns s as lowercase; otherwise returns s as-is + AString CheckCase(const AString & s) const; + + /// Removes the UTF-8 BOMs (Byte order makers), if present. + void RemoveBom(AString & a_line) const; + +public: + + enum errors + { + noID = -1, + }; + + /// Creates a new instance with no data + cIniFile(void); + + // Sets whether or not keynames and valuenames should be case sensitive. + // The default is case insensitive. + void CaseSensitive (void) { m_IsCaseInsensitive = false; } + void CaseInsensitive(void) { m_IsCaseInsensitive = true; } + + /** Reads the contents of the specified ini file + If the file doesn't exist and a_AllowExampleRedirect is true, tries to read .example.ini, and + writes its contents as .ini, if successful. + Returns true if successful, false otherwise. + */ + bool ReadFile(const AString & a_FileName, bool a_AllowExampleRedirect = true); + + /// Writes data stored in class to the specified ini file + bool WriteFile(const AString & a_FileName) const; + + /// Deletes all stored ini data (but doesn't touch the file) + void Clear(void); + + /** Returns true iff the specified value exists. */ + bool HasValue(const AString & a_KeyName, const AString & a_ValueName); + + /// Returns index of specified key, or noID if not found + int FindKey(const AString & keyname) const; + + /// Returns index of specified value, in the specified key, or noID if not found + int FindValue(const int keyID, const AString & valuename) const; + + /// Returns number of keys currently in the ini + int GetNumKeys(void) const { return (int)keys.size(); } + + /// Add a key name + int AddKeyName(const AString & keyname); + + // Returns key names by index. + AString GetKeyName(const int keyID) const; + + // Returns number of values stored for specified key. + int GetNumValues(const AString & keyname) const; + int GetNumValues(const int keyID) const; + + // Returns value name by index for a given keyname or keyID. + AString GetValueName(const AString & keyname, const int valueID) const; + AString GetValueName(const int keyID, const int valueID) const; + + // Gets value of [keyname] valuename =. + // Overloaded to return string, int, and double. + // Returns defValue if key/value not found. + AString GetValue (const AString & keyname, const AString & valuename, const AString & defValue = "") const; + AString GetValue (const int keyID, const int valueID, const AString & defValue = "") const; + double GetValueF(const AString & keyname, const AString & valuename, const double defValue = 0) const; + int GetValueI(const AString & keyname, const AString & valuename, const int defValue = 0) const; + bool GetValueB(const AString & keyname, const AString & valuename, const bool defValue = false) const + { + return (GetValueI(keyname, valuename, defValue ? 1 : 0) != 0); + } + + // Gets the value; if not found, write the default to the INI file + 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); + } + + // Adds a new value to the specified key. + // If a value of the same name already exists, creates another one (non-standard INI file) + void AddValue (const AString & a_KeyName, const AString & a_ValueName, const AString & a_Value); + void AddValueI(const AString & a_KeyName, const AString & a_ValueName, const int a_Value); + void AddValueB(const AString & a_KeyName, const AString & a_ValueName, const bool a_Value) + { + return AddValueI(a_KeyName, a_ValueName, a_Value ? 1 : 0); + } + void AddValueF(const AString & a_KeyName, const AString & a_ValueName, const double a_Value); + + // Overwrites the value of [keyname].valuename + // Specify the optional parameter as false (0) if you do not want the value created if it doesn't exist. + // Returns true if value set, false otherwise. + // Overloaded to accept string, int, and double. + 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); + } + bool SetValueF(const AString & a_KeyName, const AString & a_ValueName, const double a_Value, const bool a_CreateIfNotExists = true); + + // tolua_end + + bool SetValueV( const AString & a_KeyName, const AString & a_ValueName, const char * a_Format, ...); + + // tolua_begin + + // Deletes specified value. + // Returns true if value existed and deleted, false otherwise. + bool DeleteValueByID(const int keyID, const int valueID); + bool DeleteValue(const AString & keyname, const AString & valuename); + + // Deletes specified key and all values contained within. + // Returns true if key existed and deleted, false otherwise. + bool DeleteKey(const AString & keyname); + + // Header comment functions. + // Header comments are those comments before the first key. + + /// Returns the number of header comments + int GetNumHeaderComments(void) {return (int)comments.size();} + + /// Adds a header comment + void AddHeaderComment(const AString & comment); + + /// Returns a header comment, or empty string if out of range + AString GetHeaderComment(const int commentID) const; + + /// Deletes a header comment. Returns true if successful + bool DeleteHeaderComment(int commentID); + + /// Deletes all header comments + void DeleteHeaderComments(void) {comments.clear();} + + + // Key comment functions. + // Key comments are those comments within a key. Any comments + // defined within value names will be added to this list. Therefore, + // these comments will be moved to the top of the key definition when + // the CIniFile::WriteFile() is called. + + /// Get number of key comments + int GetNumKeyComments(const int keyID) const; + + /// Get number of key comments + int GetNumKeyComments(const AString & keyname) const; + + /// Add a key comment + bool AddKeyComment(const int keyID, const AString & comment); + + /// Add a key comment + bool AddKeyComment(const AString & keyname, const AString & comment); + + /// Return a key comment + AString GetKeyComment(const int keyID, const int commentID) const; + AString GetKeyComment(const AString & keyname, const int commentID) const; + + // Delete a key comment. + bool DeleteKeyComment(const int keyID, const int commentID); + bool DeleteKeyComment(const AString & keyname, const int commentID); + + // Delete all comments for a key. + bool DeleteKeyComments(const int keyID); + bool DeleteKeyComments(const AString & keyname); +}; + +// tolua_end + +#endif diff --git a/src/MonsterConfig.cpp b/src/MonsterConfig.cpp index a15e413ba..ae2cbbc6b 100644 --- a/src/MonsterConfig.cpp +++ b/src/MonsterConfig.cpp @@ -3,7 +3,7 @@ #include "MonsterConfig.h" #include "Mobs/Monster.h" -#include "inifile/iniFile.h" +#include "IniFile.h" diff --git a/src/Protocol/Authenticator.cpp b/src/Protocol/Authenticator.cpp index 984000795..c9e4296a2 100644 --- a/src/Protocol/Authenticator.cpp +++ b/src/Protocol/Authenticator.cpp @@ -7,7 +7,7 @@ #include "../Server.h" #include "../ClientHandle.h" -#include "inifile/iniFile.h" +#include "../IniFile.h" #include "json/json.h" #include "PolarSSL++/BlockingSslClientSocket.h" diff --git a/src/Protocol/MojangAPI.cpp b/src/Protocol/MojangAPI.cpp index dd0d62af5..67f513e44 100644 --- a/src/Protocol/MojangAPI.cpp +++ b/src/Protocol/MojangAPI.cpp @@ -7,7 +7,7 @@ #include "MojangAPI.h" #include "SQLiteCpp/Database.h" #include "SQLiteCpp/Statement.h" -#include "inifile/iniFile.h" +#include "../IniFile.h" #include "json/json.h" #include "PolarSSL++/BlockingSslClientSocket.h" #include "../RankManager.h" diff --git a/src/RCONServer.cpp b/src/RCONServer.cpp index df027c91f..49ca4fc61 100644 --- a/src/RCONServer.cpp +++ b/src/RCONServer.cpp @@ -4,7 +4,7 @@ // Implements the cRCONServer class representing the RCON server #include "Globals.h" -#include "inifile/iniFile.h" +#include "IniFile.h" #include "RCONServer.h" #include "Server.h" #include "Root.h" diff --git a/src/RankManager.cpp b/src/RankManager.cpp index 3778f5d64..451de88e7 100644 --- a/src/RankManager.cpp +++ b/src/RankManager.cpp @@ -5,7 +5,7 @@ #include "Globals.h" #include "RankManager.h" -#include "inifile/iniFile.h" +#include "IniFile.h" #include "Protocol/MojangAPI.h" #include "ClientHandle.h" diff --git a/src/Root.cpp b/src/Root.cpp index 6a91ec238..24c1a4cc8 100644 --- a/src/Root.cpp +++ b/src/Root.cpp @@ -19,11 +19,10 @@ #include "OSSupport/Timer.h" #include "LoggerListeners.h" #include "BuildInfo.h" - -#include "inifile/iniFile.h" +#include "IniFile.h" #ifdef _WIN32 - #include "conio.h" + #include #include #elif defined(__linux__) #include diff --git a/src/Server.cpp b/src/Server.cpp index 5085d4c94..bbb5ecff3 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -22,7 +22,7 @@ #include "MersenneTwister.h" -#include "inifile/iniFile.h" +#include "IniFile.h" #include "Vector3.h" #include diff --git a/src/Simulator/SandSimulator.cpp b/src/Simulator/SandSimulator.cpp index 073518b31..dfbd3e458 100644 --- a/src/Simulator/SandSimulator.cpp +++ b/src/Simulator/SandSimulator.cpp @@ -7,7 +7,7 @@ #include "../Defines.h" #include "../Entities/FallingBlock.h" #include "../Chunk.h" -#include "inifile/iniFile.h" +#include "../IniFile.h" diff --git a/src/WebAdmin.h b/src/WebAdmin.h index 94b95dbcf..a85fb1f0c 100644 --- a/src/WebAdmin.h +++ b/src/WebAdmin.h @@ -7,7 +7,7 @@ #include "OSSupport/Socket.h" #include "Bindings/LuaState.h" -#include "inifile/iniFile.h" +#include "IniFile.h" #include "HTTPServer/HTTPServer.h" #include "HTTPServer/HTTPFormParser.h" diff --git a/src/World.cpp b/src/World.cpp index ff333ad2a..b77b01c10 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -8,7 +8,7 @@ #include "Server.h" #include "Item.h" #include "Root.h" -#include "inifile/iniFile.h" +#include "IniFile.h" #include "ChunkMap.h" #include "Generating/ChunkDesc.h" #include "OSSupport/Timer.h" -- cgit v1.2.3 From 1235ccb1e20aa764682d766c18a32804963ecf0a Mon Sep 17 00:00:00 2001 From: Mattes D Date: Thu, 23 Oct 2014 15:26:43 +0200 Subject: Removed iniFile library from linux dependencies. --- src/Generating/CMakeLists.txt | 2 +- src/Generating/Prefabs/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Generating/CMakeLists.txt b/src/Generating/CMakeLists.txt index 33d622b42..cd3d5a9f3 100644 --- a/src/Generating/CMakeLists.txt +++ b/src/Generating/CMakeLists.txt @@ -65,5 +65,5 @@ SET (HDRS if(NOT MSVC) add_library(Generating ${SRCS} ${HDRS}) - target_link_libraries(Generating OSSupport iniFile Blocks) + target_link_libraries(Generating OSSupport Blocks) endif() diff --git a/src/Generating/Prefabs/CMakeLists.txt b/src/Generating/Prefabs/CMakeLists.txt index 2c62aa73d..68f6491c4 100644 --- a/src/Generating/Prefabs/CMakeLists.txt +++ b/src/Generating/Prefabs/CMakeLists.txt @@ -29,5 +29,5 @@ SET (HDRS if(NOT MSVC) add_library(Generating_Prefabs ${SRCS} ${HDRS}) - target_link_libraries(Generating_Prefabs OSSupport iniFile Blocks) + target_link_libraries(Generating_Prefabs OSSupport Blocks) endif() -- cgit v1.2.3 From 298be25413b9d2f48b1071385a52a55d37d86857 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Thu, 23 Oct 2014 15:29:02 +0200 Subject: QtBiomeVisualiser: Moved the IniFile lib. --- Tools/QtBiomeVisualiser/ChunkSource.cpp | 2 +- Tools/QtBiomeVisualiser/GeneratorSetup.cpp | 2 +- Tools/QtBiomeVisualiser/MainWindow.cpp | 2 +- Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Tools/QtBiomeVisualiser/ChunkSource.cpp b/Tools/QtBiomeVisualiser/ChunkSource.cpp index 3e5216458..c5cde1c3b 100644 --- a/Tools/QtBiomeVisualiser/ChunkSource.cpp +++ b/Tools/QtBiomeVisualiser/ChunkSource.cpp @@ -4,7 +4,7 @@ #include "src/Generating/BioGen.h" #include "src/StringCompression.h" #include "src/WorldStorage/FastNBT.h" -#include "inifile/iniFile.h" +#include "src/IniFile.h" diff --git a/Tools/QtBiomeVisualiser/GeneratorSetup.cpp b/Tools/QtBiomeVisualiser/GeneratorSetup.cpp index 7d94a1682..a6490d9fe 100644 --- a/Tools/QtBiomeVisualiser/GeneratorSetup.cpp +++ b/Tools/QtBiomeVisualiser/GeneratorSetup.cpp @@ -3,7 +3,7 @@ #include #include #include "src/Generating/BioGen.h" -#include "inifile/iniFile.h" +#include "src/IniFile.h" diff --git a/Tools/QtBiomeVisualiser/MainWindow.cpp b/Tools/QtBiomeVisualiser/MainWindow.cpp index 63d72f992..7853d768e 100644 --- a/Tools/QtBiomeVisualiser/MainWindow.cpp +++ b/Tools/QtBiomeVisualiser/MainWindow.cpp @@ -8,7 +8,7 @@ #include #include #include -#include "inifile/iniFile.h" +#include "src/IniFile.h" #include "ChunkSource.h" #include "src/Generating/BioGen.h" #include "src/StringCompression.h" diff --git a/Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro b/Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro index 9e5d1303c..f3a5255fb 100644 --- a/Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro +++ b/Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro @@ -21,7 +21,7 @@ SOURCES +=\ ../../src/StringUtils.cpp \ ../../src/LoggerListeners.cpp \ ../../src/Logger.cpp \ - ../../lib/inifile/iniFile.cpp \ + ../../src/IniFile.cpp \ ../../src/OSSupport/File.cpp \ ../../src/OSSupport/CriticalSection.cpp \ ../../src/OSSupport/IsThread.cpp \ @@ -59,7 +59,7 @@ HEADERS += MainWindow.h \ ../../src/StringUtils.h \ ../../src/LoggerListeners.h \ ../../src/Logger.h \ - ../../lib/inifile/iniFile.h \ + ../../src/IniFile.h \ ../../src/OSSupport/File.h \ ../../src/OSSupport/CriticalSection.h \ ../../src/OSSupport/IsThread.h \ -- cgit v1.2.3 From 32cab75e438dae9c545e51950f14bf36d39d5ef0 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Thu, 23 Oct 2014 16:07:43 +0200 Subject: IniFile: Removed an unused macro. --- src/IniFile.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/IniFile.cpp b/src/IniFile.cpp index 517fd36af..eff41de33 100644 --- a/src/IniFile.cpp +++ b/src/IniFile.cpp @@ -32,10 +32,6 @@ #define iniEOL '\r' << endl #endif -#ifndef _WIN32 - #define sscanf_s(buffer, stringbuffer, ...) (sscanf(buffer, stringbuffer, __VA_ARGS__)) -#endif - using namespace std; -- cgit v1.2.3 From 9af58a81d6467829b72801169c8e80a2bab01804 Mon Sep 17 00:00:00 2001 From: Howaner Date: Thu, 23 Oct 2014 21:19:43 +0200 Subject: Use 3 priorities. --- src/Chunk.cpp | 2 +- src/ChunkSender.cpp | 44 ++++++++++++++++++++++++++++++++++++++++---- src/ChunkSender.h | 4 +++- src/ClientHandle.cpp | 2 +- 4 files changed, 45 insertions(+), 7 deletions(-) diff --git a/src/Chunk.cpp b/src/Chunk.cpp index 35a16edec..a0224322a 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -1742,7 +1742,7 @@ void cChunk::SetAreaBiome(int a_MinRelX, int a_MaxRelX, int a_MinRelZ, int a_Max // Re-send the chunk to all clients: for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr) { - m_World->ForceSendChunkTo(m_PosX, m_PosZ, cChunkSender::E_CHUNK_PRIORITY_HIGH, (*itr)); + m_World->ForceSendChunkTo(m_PosX, m_PosZ, cChunkSender::E_CHUNK_PRIORITY_MEDIUM, (*itr)); } // for itr - m_LoadedByClient[] } diff --git a/src/ChunkSender.cpp b/src/ChunkSender.cpp index 7e2301eab..ef2be167b 100644 --- a/src/ChunkSender.cpp +++ b/src/ChunkSender.cpp @@ -100,6 +100,7 @@ void cChunkSender::QueueSendChunkTo(int a_ChunkX, int a_ChunkZ, eChunkPriority a cCSLock Lock(m_CS); if ( std::find(m_SendChunksLowPriority.begin(), m_SendChunksLowPriority.end(), Chunk) != m_SendChunksLowPriority.end() || + std::find(m_SendChunksMediumPriority.begin(), m_SendChunksMediumPriority.end(), Chunk) != m_SendChunksMediumPriority.end() || std::find(m_SendChunksHighPriority.begin(), m_SendChunksHighPriority.end(), Chunk) != m_SendChunksHighPriority.end() ) { @@ -107,10 +108,27 @@ void cChunkSender::QueueSendChunkTo(int a_ChunkX, int a_ChunkZ, eChunkPriority a return; } - if (a_Priority == E_CHUNK_PRIORITY_LOW) { - m_SendChunksLowPriority.push_back(Chunk); - } else if (a_Priority == E_CHUNK_PRIORITY_HIGH) { - m_SendChunksHighPriority.push_back(Chunk); + switch (a_Priority) + { + case E_CHUNK_PRIORITY_LOW: + { + m_SendChunksLowPriority.push_back(Chunk); + break; + } + case E_CHUNK_PRIORITY_MEDIUM: + { + m_SendChunksMediumPriority.push_back(Chunk); + break; + } + case E_CHUNK_PRIORITY_HIGH: + { + m_SendChunksHighPriority.push_back(Chunk); + break; + } + default: + { + ASSERT(!"Unknown chunk priority!"); + } } } m_evtQueue.Set(); @@ -133,6 +151,15 @@ void cChunkSender::RemoveClient(cClientHandle * a_Client) } ++itr; } // for itr - m_SendChunksLowPriority[] + for (sSendChunkList::iterator itr = m_SendChunksMediumPriority.begin(); itr != m_SendChunksMediumPriority.end();) + { + if (itr->m_Client == a_Client) + { + itr = m_SendChunksMediumPriority.erase(itr); + continue; + } + ++itr; + } // for itr - m_SendChunksMediumPriority[] for (sSendChunkList::iterator itr = m_SendChunksHighPriority.begin(); itr != m_SendChunksHighPriority.end();) { if (itr->m_Client == a_Client) @@ -191,6 +218,15 @@ void cChunkSender::Execute(void) SendChunk(Coords.m_ChunkX, Coords.m_ChunkZ, nullptr); } + else if (!m_SendChunksMediumPriority.empty()) + { + // Take one from the queue: + sSendChunk Chunk(m_SendChunksMediumPriority.front()); + m_SendChunksMediumPriority.pop_front(); + Lock.Unlock(); + + SendChunk(Chunk.m_ChunkX, Chunk.m_ChunkZ, Chunk.m_Client); + } else { // Take one from the queue: diff --git a/src/ChunkSender.h b/src/ChunkSender.h index 585d50914..7cd7ddd86 100644 --- a/src/ChunkSender.h +++ b/src/ChunkSender.h @@ -79,7 +79,8 @@ public: enum eChunkPriority { E_CHUNK_PRIORITY_HIGH = 0, - E_CHUNK_PRIORITY_LOW = 1, + E_CHUNK_PRIORITY_MEDIUM = 1, + E_CHUNK_PRIORITY_LOW = 2, }; bool Start(cWorld * a_World); @@ -143,6 +144,7 @@ protected: cCriticalSection m_CS; cChunkCoordsList m_ChunksReady; sSendChunkList m_SendChunksLowPriority; + sSendChunkList m_SendChunksMediumPriority; sSendChunkList m_SendChunksHighPriority; cEvent m_evtQueue; // Set when anything is added to m_ChunksReady cEvent m_evtRemoved; // Set when removed clients are safe to be deleted diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index dc360861e..faee05450 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -463,7 +463,7 @@ bool cClientHandle::StreamNextChunk(void) // Unloaded chunk found -> Send it to the client. Lock.Unlock(); - StreamChunk(ChunkX, ChunkZ, cChunkSender::E_CHUNK_PRIORITY_HIGH); + StreamChunk(ChunkX, ChunkZ, ((Range <= 2) ? cChunkSender::E_CHUNK_PRIORITY_HIGH : cChunkSender::E_CHUNK_PRIORITY_MEDIUM)); return false; } } -- cgit v1.2.3 From f6ddafabd67c721f30f4e560a0b51067e238ea0d Mon Sep 17 00:00:00 2001 From: Mattes D Date: Thu, 23 Oct 2014 22:50:42 +0200 Subject: Re-updated Core. --- MCServer/Plugins/Core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MCServer/Plugins/Core b/MCServer/Plugins/Core index 2dddf205d..470247194 160000 --- a/MCServer/Plugins/Core +++ b/MCServer/Plugins/Core @@ -1 +1 @@ -Subproject commit 2dddf205dd5346363207b72ab289f2a2a60c2583 +Subproject commit 4702471943511f641458c7e8e89b430a723f43ea -- cgit v1.2.3 From 6bcc2c187aff025bb8ab35e8454c0a3e1c62e97e Mon Sep 17 00:00:00 2001 From: archshift Date: Thu, 23 Oct 2014 14:58:42 -0700 Subject: Fix linking on OS X, which does not have librt. --- src/OSSupport/CMakeLists.txt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/OSSupport/CMakeLists.txt b/src/OSSupport/CMakeLists.txt index 429949c59..a2f46d656 100644 --- a/src/OSSupport/CMakeLists.txt +++ b/src/OSSupport/CMakeLists.txt @@ -38,7 +38,11 @@ SET (HDRS if(NOT MSVC) add_library(OSSupport ${SRCS} ${HDRS}) - if(UNIX) - target_link_libraries(OSSupport pthread rt) + if(NOT APPLE) + target_link_libraries(OSSupport rt) endif() + + if(UNIX) + target_link_libraries(OSSupport pthread) + endif() endif() -- cgit v1.2.3 From 8ccb729504a866b50907993a71d3e35ad19e96a4 Mon Sep 17 00:00:00 2001 From: archshift Date: Thu, 23 Oct 2014 15:03:54 -0700 Subject: Fixed potential linker errors with mingw, as it isn't MSVC and it isn't APPLE. --- src/OSSupport/CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/OSSupport/CMakeLists.txt b/src/OSSupport/CMakeLists.txt index a2f46d656..3c0a3f1a0 100644 --- a/src/OSSupport/CMakeLists.txt +++ b/src/OSSupport/CMakeLists.txt @@ -38,11 +38,11 @@ SET (HDRS if(NOT MSVC) add_library(OSSupport ${SRCS} ${HDRS}) - if(NOT APPLE) - target_link_libraries(OSSupport rt) - endif() - if(UNIX) + if(NOT APPLE) + target_link_libraries(OSSupport rt) + endif() + target_link_libraries(OSSupport pthread) endif() endif() -- cgit v1.2.3 From d5dfacae8790da4bfed71760c75528da89218596 Mon Sep 17 00:00:00 2001 From: worktycho Date: Thu, 23 Oct 2014 23:23:34 +0100 Subject: Fixed formatstring --- src/IniFile.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/IniFile.h b/src/IniFile.h index 33229bff0..44b3422d0 100644 --- a/src/IniFile.h +++ b/src/IniFile.h @@ -156,7 +156,7 @@ public: // tolua_end - bool SetValueV( const AString & a_KeyName, const AString & a_ValueName, const char * a_Format, ...); + bool SetValueV( const AString & a_KeyName, const AString & a_ValueName, const char * a_Format, ...) FORMATSTRING(3,4); // tolua_begin -- cgit v1.2.3 From dd86c1f4a33cc89cf4316105690f4d8d1cb24c4a Mon Sep 17 00:00:00 2001 From: archshift Date: Thu, 23 Oct 2014 23:49:20 -0700 Subject: OSSupport/CMakeLists.txt: fixed indentation --- src/OSSupport/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/OSSupport/CMakeLists.txt b/src/OSSupport/CMakeLists.txt index 3c0a3f1a0..c3eabeef6 100644 --- a/src/OSSupport/CMakeLists.txt +++ b/src/OSSupport/CMakeLists.txt @@ -38,11 +38,11 @@ SET (HDRS if(NOT MSVC) add_library(OSSupport ${SRCS} ${HDRS}) - if(UNIX) + if(UNIX) if(NOT APPLE) target_link_libraries(OSSupport rt) endif() - target_link_libraries(OSSupport pthread) - endif() + target_link_libraries(OSSupport pthread) + endif() endif() -- cgit v1.2.3 From e272637ff582f3e32794bc7b2a1a23564bba54c4 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Fri, 24 Oct 2014 08:49:36 +0200 Subject: IniFile: Removed the problematic printf-like Set function. It wasn't used in any client code anyway. --- src/IniFile.cpp | 14 -------------- src/IniFile.h | 6 ------ 2 files changed, 20 deletions(-) diff --git a/src/IniFile.cpp b/src/IniFile.cpp index eff41de33..a666a4ff8 100644 --- a/src/IniFile.cpp +++ b/src/IniFile.cpp @@ -461,20 +461,6 @@ bool cIniFile::SetValueF(const AString & a_KeyName, const AString & a_ValueName, -bool cIniFile::SetValueV(const AString & a_KeyName, const AString & a_ValueName, const char * a_Format, ...) -{ - va_list args; - va_start(args, a_Format); - AString Data; - AppendVPrintf(Data, a_Format, args); - va_end(args); - return SetValue(a_KeyName, a_ValueName, Data); -} - - - - - AString cIniFile::GetValue(const int keyID, const int valueID, const AString & defValue) const { if ((keyID < (int)keys.size()) && (valueID < (int)keys[keyID].names.size())) diff --git a/src/IniFile.h b/src/IniFile.h index 44b3422d0..3f704551f 100644 --- a/src/IniFile.h +++ b/src/IniFile.h @@ -154,12 +154,6 @@ public: } bool SetValueF(const AString & a_KeyName, const AString & a_ValueName, const double a_Value, const bool a_CreateIfNotExists = true); - // tolua_end - - bool SetValueV( const AString & a_KeyName, const AString & a_ValueName, const char * a_Format, ...) FORMATSTRING(3,4); - - // tolua_begin - // Deletes specified value. // Returns true if value existed and deleted, false otherwise. bool DeleteValueByID(const int keyID, const int valueID); -- cgit v1.2.3