diff options
Diffstat (limited to 'src/Map.cpp')
-rw-r--r-- | src/Map.cpp | 451 |
1 files changed, 92 insertions, 359 deletions
diff --git a/src/Map.cpp b/src/Map.cpp index 48d7fb0ca..d55642a5a 100644 --- a/src/Map.cpp +++ b/src/Map.cpp @@ -5,108 +5,11 @@ #include "Map.h" -#include "ClientHandle.h" #include "World.h" #include "Chunk.h" #include "Entities/Player.h" #include "FastRandom.h" - - - - - -cMapDecorator::cMapDecorator(cMap * a_Map, eType a_Type, int a_X, int a_Z, int a_Rot) - : m_Map(a_Map) - , m_Type(a_Type) - , m_PixelX(a_X) - , m_PixelZ(a_Z) - , m_Rot(a_Rot) - , m_Player(nullptr) -{ -} - - - - - -cMapDecorator::cMapDecorator(cMap * a_Map, cPlayer * a_Player) - : m_Map(a_Map) - , m_Type(E_TYPE_PLAYER) - , m_Player(a_Player) -{ - Update(); -} - - - - - -void cMapDecorator::Update(void) -{ - if (m_Player != nullptr) - { - ASSERT(m_Map != nullptr); - unsigned int PixelWidth = m_Map->GetPixelWidth(); - - int InsideWidth = (m_Map->GetWidth() / 2) - 1; - int InsideHeight = (m_Map->GetHeight() / 2) - 1; - - int PixelX = (int) (m_Player->GetPosX() - m_Map->GetCenterX()) / PixelWidth; - int PixelZ = (int) (m_Player->GetPosZ() - m_Map->GetCenterZ()) / PixelWidth; - - // Center of pixel - m_PixelX = (2 * PixelX) + 1; - m_PixelZ = (2 * PixelZ) + 1; - - if ((PixelX > -InsideWidth) && (PixelX <= InsideWidth) && (PixelZ > -InsideHeight) && (PixelZ <= InsideHeight)) - { - double Yaw = m_Player->GetYaw(); - - if (m_Map->GetDimension() == dimNether) - { - cFastRandom Random; - - // TODO 2014-02-19 xdot: Refine - m_Rot = Random.NextInt(16); - } - else - { - m_Rot = (int) (Yaw * 16) / 360; - } - - m_Type = E_TYPE_PLAYER; - } - else - { - if ((abs(PixelX) > 320.0) || (abs(PixelZ) > 320.0)) - { - // TODO 2014-02-18 xdot: Remove decorator - } - - m_Rot = 0; - - m_Type = E_TYPE_PLAYER_OUTSIDE; - - // Move to border - if (PixelX <= -InsideWidth) - { - m_PixelX = (2 * -InsideWidth) + 1; - } - if (PixelZ <= -InsideHeight) - { - m_PixelZ = (2 * -InsideHeight) + 1; - } - if (PixelX > InsideWidth) - { - m_PixelX = (2 * InsideWidth) + 1; - } - if (PixelZ > InsideHeight) - { - m_PixelZ = (2 * InsideHeight) + 1; - } - } - } -} +#include "Blocks/BlockHandler.h" @@ -148,6 +51,20 @@ cMap::cMap(unsigned int a_ID, int a_CenterX, int a_CenterZ, cWorld * a_World, un +void cMap::Tick() +{ + for (const auto & Client : m_ClientsInCurrentTick) + { + Client->SendMapData(*this, 0, 0); + } + m_ClientsInCurrentTick.clear(); + m_Decorators.clear(); +} + + + + + void cMap::UpdateRadius(int a_PixelX, int a_PixelZ, unsigned int a_Radius) { int PixelRadius = a_Radius / GetPixelWidth(); @@ -219,13 +136,11 @@ bool cMap::UpdatePixel(unsigned int a_X, unsigned int a_Z) virtual bool Item(cChunk * a_Chunk) override { - if (a_Chunk == nullptr) + if (!a_Chunk->IsValid()) { return false; } - unsigned int CallbackPixelWidth = m_Map->GetPixelWidth(); - if (m_Map->GetDimension() == dimNether) { // TODO 2014-02-22 xdot: Nether maps @@ -233,84 +148,33 @@ bool cMap::UpdatePixel(unsigned int a_X, unsigned int a_Z) return false; } - typedef std::map<ColorID, unsigned int> ColorCountMap; - ColorCountMap ColorCounts; + static const std::array<unsigned char, 4> BrightnessID = { { 3, 0, 1, 2 } }; // Darkest to lightest + BLOCKTYPE TargetBlock; + NIBBLETYPE TargetMeta; + + auto Height = a_Chunk->GetHeight(m_RelX, m_RelZ); + auto ChunkHeight = cChunkDef::Height; + a_Chunk->GetBlockTypeMeta(m_RelX, Height, m_RelZ, TargetBlock, TargetMeta); + auto ColourID = BlockHandler(TargetBlock)->GetMapBaseColourID(TargetMeta); - // Count surface blocks - for (unsigned int X = m_RelX; X < m_RelX + CallbackPixelWidth; ++X) + if (IsBlockWater(TargetBlock)) { - for (unsigned int Z = m_RelZ; Z < m_RelZ + CallbackPixelWidth; ++Z) + ChunkHeight /= 4; + while (((--Height) != -1) && IsBlockWater(a_Chunk->GetBlock(m_RelX, Height, m_RelZ))) { - // unsigned int WaterDepth = 0; - - BLOCKTYPE TargetBlock = E_BLOCK_AIR; - NIBBLETYPE TargetMeta = 0; - - int Height = a_Chunk->GetHeight(X, Z); - - while (Height > 0) - { - a_Chunk->GetBlockTypeMeta(X, Height, Z, TargetBlock, TargetMeta); - - // TODO 2014-02-22 xdot: Check if block color is transparent - if (TargetBlock == E_BLOCK_AIR) - { - --Height; - continue; - } - // TODO 2014-02-22 xdot: Check if block is liquid - /* - else if (false) - { - --Height; - ++WaterDepth; - continue; - } - */ - - break; - } - - // TODO 2014-02-22 xdot: Query block color - ColorID Color = E_BASE_COLOR_BROWN; - - // Debug - Temporary - switch (TargetBlock) - { - case E_BLOCK_GRASS: - { - Color = E_BASE_COLOR_LIGHT_GREEN; break; - } - case E_BLOCK_STATIONARY_WATER: - case E_BLOCK_WATER: - { - Color = E_BASE_COLOR_BLUE; break; - } - } - - ++ColorCounts[Color]; + continue; } } - - // Find dominant color - ColorID PixelColor = E_BASE_COLOR_TRANSPARENT; - - unsigned int MaxCount = 0; - - for (ColorCountMap::iterator it = ColorCounts.begin(); it != ColorCounts.end(); ++it) + else if (ColourID == 0) { - if (it->second > MaxCount) + while (((--Height) != -1) && ((ColourID = BlockHandler(a_Chunk->GetBlock(m_RelX, Height, m_RelZ))->GetMapBaseColourID(a_Chunk->GetMeta(m_RelX, Height, m_RelZ))) == 0)) { - PixelColor = it->first; - MaxCount = it->second; + continue; } } - // TODO 2014-02-22 xdot: Adjust brightness - unsigned int dColor = 1; - - m_PixelData = PixelColor + dColor; - + // Multiply base color ID by 4 and add brightness ID + m_PixelData = ColourID * 4 + BrightnessID[Clamp<size_t>(static_cast<size_t>(Height / (ChunkHeight / BrightnessID.size())), 0, BrightnessID.size() - 1)]; return false; } @@ -332,162 +196,11 @@ bool cMap::UpdatePixel(unsigned int a_X, unsigned int a_Z) -void cMap::UpdateDecorators(void) -{ - for (cMapDecoratorList::iterator it = m_Decorators.begin(); it != m_Decorators.end(); ++it) - { - it->Update(); - } -} - - - - - -void cMap::AddPlayer(cPlayer * a_Player, Int64 a_WorldAge) -{ - cClientHandle * Handle = a_Player->GetClientHandle(); - if (Handle == nullptr) - { - return; - } - - cMapClient MapClient; - - MapClient.m_LastUpdate = a_WorldAge; - MapClient.m_SendInfo = true; - MapClient.m_Handle = Handle; - MapClient.m_DataUpdate = 0; - MapClient.m_NextDecoratorUpdate = 0; - - m_Clients.push_back(MapClient); - - cMapDecorator PlayerDecorator(this, a_Player); - - m_Decorators.push_back(PlayerDecorator); -} - - - - - -void cMap::RemoveInactiveClients(Int64 a_WorldAge) -{ - for (cMapClientList::iterator it = m_Clients.begin(); it != m_Clients.end();) - { - if (it->m_LastUpdate < a_WorldAge) - { - // Remove associated decorators - for (cMapDecoratorList::iterator it2 = m_Decorators.begin(); it2 != m_Decorators.end();) - { - if (it2->GetPlayer()->GetClientHandle() == it->m_Handle) - { - // Erase decorator - cMapDecoratorList::iterator temp = it2; - ++it2; - m_Decorators.erase(temp); - } - else - { - ++it2; - } - } - - // Erase client - cMapClientList::iterator temp = it; - ++it; - m_Clients.erase(temp); - } - else - { - ++it; - } - } -} - - - - - -void cMap::StreamNext(cMapClient & a_Client) -{ - cClientHandle * Handle = a_Client.m_Handle; - - if (a_Client.m_SendInfo) - { - Handle->SendMapInfo(m_ID, m_Scale); - - a_Client.m_SendInfo = false; - - return; - } - - ++a_Client.m_NextDecoratorUpdate; - - if (a_Client.m_NextDecoratorUpdate >= 4) - { - // TODO 2014-02-19 xdot - // This is dangerous as the player object may have been destroyed before the decorator is erased from the list - UpdateDecorators(); - - Handle->SendMapDecorators(m_ID, m_Decorators, m_Scale); - - a_Client.m_NextDecoratorUpdate = 0; - } - else - { - ++a_Client.m_DataUpdate; - - unsigned int Y = (a_Client.m_DataUpdate * 11) % m_Width; - - const Byte * Colors = &m_Data[Y * m_Height]; - - Handle->SendMapColumn(m_ID, Y, 0, Colors, m_Height, m_Scale); - } -} - - - - - void cMap::UpdateClient(cPlayer * a_Player) { ASSERT(a_Player != nullptr); - cClientHandle * Handle = a_Player->GetClientHandle(); - - if (Handle == nullptr) - { - return; - } - - Int64 WorldAge = a_Player->GetWorld()->GetWorldAge(); - - RemoveInactiveClients(WorldAge - 5); - - // Linear search for client state - for (cMapClientList::iterator it = m_Clients.begin(); it != m_Clients.end(); ++it) - { - if (it->m_Handle == Handle) - { - it->m_LastUpdate = WorldAge; - - StreamNext(*it); - - return; - } - } - - // New player, construct a new client state - AddPlayer(a_Player, WorldAge); -} - - - - - -void cMap::EraseData(void) -{ - m_Data.assign(m_Width * m_Height, 0); + m_Decorators.emplace_back(CreateDecorator(a_Player)); + m_ClientsInCurrentTick.push_back(a_Player->GetClientHandle()); } @@ -532,30 +245,11 @@ void cMap::SetPosition(int a_CenterX, int a_CenterZ) -void cMap::SetScale(unsigned int a_Scale) -{ - if (m_Scale == a_Scale) - { - return; - } - - m_Scale = a_Scale; - - for (cMapClientList::iterator it = m_Clients.begin(); it != m_Clients.end(); ++it) - { - it->m_SendInfo = true; - } -} - - - - - bool cMap::SetPixel(unsigned int a_X, unsigned int a_Z, cMap::ColorID a_Data) { if ((a_X < m_Width) && (a_Z < m_Height)) { - m_Data[a_Z + (a_X * m_Height)] = a_Data; + m_Data[a_Z * m_Width + a_X] = a_Data; return true; } @@ -573,7 +267,7 @@ cMap::ColorID cMap::GetPixel(unsigned int a_X, unsigned int a_Z) { if ((a_X < m_Width) && (a_Z < m_Height)) { - return m_Data[a_Z + (a_X * m_Height)]; + return m_Data[a_Z * m_Width + a_X]; } else { @@ -585,36 +279,75 @@ cMap::ColorID cMap::GetPixel(unsigned int a_X, unsigned int a_Z) -void cMap::SendTo(cClientHandle & a_Client) +unsigned int cMap::GetNumPixels(void) const { - a_Client.SendMapInfo(m_ID, m_Scale); + return m_Width * m_Height; +} - for (unsigned int i = 0; i < m_Width; ++i) - { - const Byte * Colors = &m_Data[i * m_Height]; - a_Client.SendMapColumn(m_ID, i, 0, Colors, m_Height, m_Scale); - } - a_Client.SendMapDecorators(m_ID, m_Decorators, m_Scale); -} +const cMapDecorator cMap::CreateDecorator(const cEntity * a_TrackedEntity) +{ + int InsideWidth = (GetWidth() / 2) - 1; + int InsideHeight = (GetHeight() / 2) - 1; + + // Center of pixel + int PixelX = (int)(a_TrackedEntity->GetPosX() - GetCenterX()) / GetPixelWidth(); + int PixelZ = (int)(a_TrackedEntity->GetPosZ() - GetCenterZ()) / GetPixelWidth(); + cMapDecorator::eType Type; + int Rot; + if ((PixelX > -InsideWidth) && (PixelX <= InsideWidth) && (PixelZ > -InsideHeight) && (PixelZ <= InsideHeight)) + { + double Yaw = a_TrackedEntity->GetYaw(); -unsigned int cMap::GetNumPixels(void) const -{ - return m_Width * m_Height; -} + if (GetDimension() == dimNether) + { + cFastRandom Random; + // TODO 2014-02-19 xdot: Refine + Rot = Random.NextInt(16); + } + else + { + Rot = CeilC(((Yaw - 11.25) * 16) / 360); + } + Type = cMapDecorator::eType::E_TYPE_PLAYER; + } + else + { + if ((PixelX > 320.0) || (PixelZ > 320.0)) + { + ; + } + Rot = 0; + Type = cMapDecorator::eType::E_TYPE_PLAYER_OUTSIDE; + // Move to border + if (PixelX <= -InsideWidth) + { + PixelX = -InsideWidth; + } + if (PixelZ <= -InsideHeight) + { + PixelZ = -InsideHeight; + } + if (PixelX > InsideWidth) + { + PixelX = InsideWidth; + } + if (PixelZ > InsideHeight) + { + PixelZ = InsideHeight; + } + } -size_t cMap::GetNumDecorators(void) const -{ - return m_Decorators.size(); + return {Type, (unsigned)(2 * PixelX + 1), (unsigned)(2 * PixelZ + 1), Rot}; } |