2014-02-13 10:13:09 -05:00
|
|
|
|
|
|
|
// Map.cpp
|
|
|
|
|
|
|
|
#include "Globals.h"
|
|
|
|
|
2020-04-03 02:57:01 -04:00
|
|
|
#include "BlockInfo.h"
|
2020-09-20 09:50:52 -04:00
|
|
|
#include "Blocks/BlockHandler.h"
|
2014-02-14 09:21:16 -05:00
|
|
|
#include "Chunk.h"
|
2020-09-20 09:50:52 -04:00
|
|
|
#include "ClientHandle.h"
|
2014-02-15 13:06:47 -05:00
|
|
|
#include "Entities/Player.h"
|
2014-02-19 13:57:14 -05:00
|
|
|
#include "FastRandom.h"
|
2020-09-20 09:50:52 -04:00
|
|
|
#include "Map.h"
|
|
|
|
#include "World.h"
|
2014-02-18 13:50:08 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-11-18 14:00:04 -05:00
|
|
|
cMap::cMap(unsigned int a_ID, cWorld * a_World):
|
|
|
|
m_ID(a_ID),
|
|
|
|
m_Width(cChunkDef::Width * 8),
|
|
|
|
m_Height(cChunkDef::Width * 8),
|
|
|
|
m_Scale(3),
|
|
|
|
m_CenterX(0),
|
|
|
|
m_CenterZ(0),
|
|
|
|
m_World(a_World)
|
2014-02-13 14:36:24 -05:00
|
|
|
{
|
2014-02-22 05:50:30 -05:00
|
|
|
m_Data.assign(m_Width * m_Height, E_BASE_COLOR_TRANSPARENT);
|
2014-02-15 13:06:47 -05:00
|
|
|
|
|
|
|
Printf(m_Name, "map_%i", m_ID);
|
2014-02-13 14:36:24 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-02-13 10:13:09 -05:00
|
|
|
cMap::cMap(unsigned int a_ID, int a_CenterX, int a_CenterZ, cWorld * a_World, unsigned int a_Scale)
|
|
|
|
: m_ID(a_ID)
|
2014-02-14 10:38:22 -05:00
|
|
|
, m_Width(cChunkDef::Width * 8)
|
|
|
|
, m_Height(cChunkDef::Width * 8)
|
2014-02-13 10:13:09 -05:00
|
|
|
, m_Scale(a_Scale)
|
|
|
|
, m_CenterX(a_CenterX)
|
|
|
|
, m_CenterZ(a_CenterZ)
|
|
|
|
, m_World(a_World)
|
|
|
|
{
|
2014-02-22 05:50:30 -05:00
|
|
|
m_Data.assign(m_Width * m_Height, E_BASE_COLOR_TRANSPARENT);
|
2014-02-13 10:13:09 -05:00
|
|
|
|
2014-02-15 13:06:47 -05:00
|
|
|
Printf(m_Name, "map_%i", m_ID);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-06-30 10:50:15 -04:00
|
|
|
void cMap::Tick()
|
|
|
|
{
|
|
|
|
for (const auto & Client : m_ClientsInCurrentTick)
|
|
|
|
{
|
|
|
|
Client->SendMapData(*this, 0, 0);
|
|
|
|
}
|
|
|
|
m_ClientsInCurrentTick.clear();
|
|
|
|
m_Decorators.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-02-15 13:06:47 -05:00
|
|
|
void cMap::UpdateRadius(int a_PixelX, int a_PixelZ, unsigned int a_Radius)
|
|
|
|
{
|
2015-08-04 18:24:59 -04:00
|
|
|
int PixelRadius = static_cast<int>(a_Radius / GetPixelWidth());
|
2014-02-15 13:06:47 -05:00
|
|
|
|
2015-08-04 18:24:59 -04:00
|
|
|
unsigned int StartX = static_cast<unsigned int>(Clamp(a_PixelX - PixelRadius, 0, static_cast<int>(m_Width)));
|
|
|
|
unsigned int StartZ = static_cast<unsigned int>(Clamp(a_PixelZ - PixelRadius, 0, static_cast<int>(m_Height)));
|
2014-02-15 13:06:47 -05:00
|
|
|
|
2015-08-04 18:24:59 -04:00
|
|
|
unsigned int EndX = static_cast<unsigned int>(Clamp(a_PixelX + PixelRadius, 0, static_cast<int>(m_Width)));
|
|
|
|
unsigned int EndZ = static_cast<unsigned int>(Clamp(a_PixelZ + PixelRadius, 0, static_cast<int>(m_Height)));
|
2014-02-15 13:06:47 -05:00
|
|
|
|
|
|
|
for (unsigned int X = StartX; X < EndX; ++X)
|
2014-02-14 09:21:16 -05:00
|
|
|
{
|
2014-02-15 13:06:47 -05:00
|
|
|
for (unsigned int Z = StartZ; Z < EndZ; ++Z)
|
2014-02-14 09:21:16 -05:00
|
|
|
{
|
2015-08-04 18:24:59 -04:00
|
|
|
int dX = static_cast<int>(X) - a_PixelX;
|
|
|
|
int dZ = static_cast<int>(Z) - a_PixelZ;
|
2014-02-15 13:06:47 -05:00
|
|
|
|
|
|
|
if ((dX * dX) + (dZ * dZ) < (PixelRadius * PixelRadius))
|
|
|
|
{
|
|
|
|
UpdatePixel(X, Z);
|
|
|
|
}
|
2014-02-14 09:21:16 -05:00
|
|
|
}
|
|
|
|
}
|
2014-02-13 10:13:09 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-02-15 13:06:47 -05:00
|
|
|
void cMap::UpdateRadius(cPlayer & a_Player, unsigned int a_Radius)
|
|
|
|
{
|
2015-08-04 18:24:59 -04:00
|
|
|
int PixelWidth = static_cast<int>(GetPixelWidth());
|
2014-02-15 13:06:47 -05:00
|
|
|
|
2015-08-04 18:24:59 -04:00
|
|
|
int PixelX = static_cast<int>(a_Player.GetPosX() - m_CenterX) / PixelWidth + static_cast<int>(m_Width / 2);
|
|
|
|
int PixelZ = static_cast<int>(a_Player.GetPosZ() - m_CenterZ) / PixelWidth + static_cast<int>(m_Height / 2);
|
2014-02-15 13:06:47 -05:00
|
|
|
|
|
|
|
UpdateRadius(PixelX, PixelZ, a_Radius);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-02-17 09:27:12 -05:00
|
|
|
bool cMap::UpdatePixel(unsigned int a_X, unsigned int a_Z)
|
2014-02-13 10:13:09 -05:00
|
|
|
{
|
2015-08-04 18:24:59 -04:00
|
|
|
int BlockX = m_CenterX + static_cast<int>((a_X - m_Width / 2) * GetPixelWidth());
|
|
|
|
int BlockZ = m_CenterZ + static_cast<int>((a_Z - m_Height / 2) * GetPixelWidth());
|
2014-02-15 13:06:47 -05:00
|
|
|
|
2014-07-06 18:50:22 -04:00
|
|
|
int ChunkX, ChunkZ;
|
|
|
|
cChunkDef::BlockToChunk(BlockX, BlockZ, ChunkX, ChunkZ);
|
2014-02-13 10:13:09 -05:00
|
|
|
|
2014-02-15 13:06:47 -05:00
|
|
|
int RelX = BlockX - (ChunkX * cChunkDef::Width);
|
|
|
|
int RelZ = BlockZ - (ChunkZ * cChunkDef::Width);
|
|
|
|
|
2017-09-11 17:20:49 -04:00
|
|
|
ASSERT(m_World != nullptr);
|
2014-02-15 13:06:47 -05:00
|
|
|
|
2017-09-11 17:20:49 -04:00
|
|
|
ColorID PixelData;
|
|
|
|
m_World->DoWithChunk(ChunkX, ChunkZ, [&](cChunk & a_Chunk)
|
2014-02-15 13:06:47 -05:00
|
|
|
{
|
2017-09-11 17:20:49 -04:00
|
|
|
if (GetDimension() == dimNether)
|
2014-02-22 05:50:30 -05:00
|
|
|
{
|
|
|
|
// TODO 2014-02-22 xdot: Nether maps
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-06-30 10:50:15 -04:00
|
|
|
static const std::array<unsigned char, 4> BrightnessID = { { 3, 0, 1, 2 } }; // Darkest to lightest
|
|
|
|
BLOCKTYPE TargetBlock;
|
|
|
|
NIBBLETYPE TargetMeta;
|
|
|
|
|
2017-09-11 17:20:49 -04:00
|
|
|
auto Height = a_Chunk.GetHeight(RelX, RelZ);
|
2015-06-30 10:50:15 -04:00
|
|
|
auto ChunkHeight = cChunkDef::Height;
|
2017-09-11 17:20:49 -04:00
|
|
|
a_Chunk.GetBlockTypeMeta(RelX, Height, RelZ, TargetBlock, TargetMeta);
|
2020-09-20 09:50:52 -04:00
|
|
|
auto ColourID = cBlockHandler::For(TargetBlock).GetMapBaseColourID(TargetMeta);
|
2014-02-22 05:50:30 -05:00
|
|
|
|
2015-06-30 10:50:15 -04:00
|
|
|
if (IsBlockWater(TargetBlock))
|
2014-02-15 13:06:47 -05:00
|
|
|
{
|
2015-06-30 10:50:15 -04:00
|
|
|
ChunkHeight /= 4;
|
2017-09-11 17:20:49 -04:00
|
|
|
while (((--Height) != -1) && IsBlockWater(a_Chunk.GetBlock(RelX, Height, RelZ)))
|
2014-02-15 13:06:47 -05:00
|
|
|
{
|
2015-06-30 10:50:15 -04:00
|
|
|
continue;
|
2014-02-15 13:06:47 -05:00
|
|
|
}
|
|
|
|
}
|
2015-06-30 10:50:15 -04:00
|
|
|
else if (ColourID == 0)
|
2014-02-22 05:50:30 -05:00
|
|
|
{
|
2020-09-20 09:50:52 -04:00
|
|
|
while (((--Height) != -1) && ((ColourID = cBlockHandler::For(a_Chunk.GetBlock(RelX, Height, RelZ)).GetMapBaseColourID(a_Chunk.GetMeta(RelX, Height, RelZ))) == 0))
|
2014-02-22 05:50:30 -05:00
|
|
|
{
|
2015-06-30 10:50:15 -04:00
|
|
|
continue;
|
2014-02-22 05:50:30 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-30 10:50:15 -04:00
|
|
|
// Multiply base color ID by 4 and add brightness ID
|
2015-08-04 18:24:59 -04:00
|
|
|
const int BrightnessIDSize = static_cast<int>(BrightnessID.size());
|
2017-09-11 17:20:49 -04:00
|
|
|
PixelData = ColourID * 4 + BrightnessID[static_cast<size_t>(Clamp<int>((BrightnessIDSize * Height) / ChunkHeight, 0, BrightnessIDSize - 1))];
|
2014-02-15 13:06:47 -05:00
|
|
|
return false;
|
|
|
|
}
|
2017-09-11 17:20:49 -04:00
|
|
|
);
|
2014-02-15 13:06:47 -05:00
|
|
|
|
2017-09-11 17:20:49 -04:00
|
|
|
SetPixel(a_X, a_Z, PixelData);
|
2014-02-14 09:21:16 -05:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-02-21 08:26:33 -05:00
|
|
|
void cMap::UpdateClient(cPlayer * a_Player)
|
|
|
|
{
|
2014-10-20 16:55:07 -04:00
|
|
|
ASSERT(a_Player != nullptr);
|
2015-06-30 10:50:15 -04:00
|
|
|
m_Decorators.emplace_back(CreateDecorator(a_Player));
|
|
|
|
m_ClientsInCurrentTick.push_back(a_Player->GetClientHandle());
|
2014-02-13 10:13:09 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
eDimension cMap::GetDimension(void) const
|
|
|
|
{
|
2014-10-20 16:55:07 -04:00
|
|
|
ASSERT(m_World != nullptr);
|
2014-02-13 10:13:09 -05:00
|
|
|
return m_World->GetDimension();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void cMap::Resize(unsigned int a_Width, unsigned int a_Height)
|
|
|
|
{
|
|
|
|
if ((m_Width == a_Width) && (m_Height == a_Height))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_Width = a_Width;
|
|
|
|
m_Height = a_Height;
|
|
|
|
|
|
|
|
m_Data.assign(m_Width * m_Height, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void cMap::SetPosition(int a_CenterX, int a_CenterZ)
|
|
|
|
{
|
|
|
|
m_CenterX = a_CenterX;
|
|
|
|
m_CenterZ = a_CenterZ;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-02-22 06:59:49 -05:00
|
|
|
bool cMap::SetPixel(unsigned int a_X, unsigned int a_Z, cMap::ColorID a_Data)
|
|
|
|
{
|
|
|
|
if ((a_X < m_Width) && (a_Z < m_Height))
|
|
|
|
{
|
2015-06-30 10:50:15 -04:00
|
|
|
m_Data[a_Z * m_Width + a_X] = a_Data;
|
2014-02-22 06:59:49 -05:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cMap::ColorID cMap::GetPixel(unsigned int a_X, unsigned int a_Z)
|
|
|
|
{
|
|
|
|
if ((a_X < m_Width) && (a_Z < m_Height))
|
|
|
|
{
|
2015-06-30 10:50:15 -04:00
|
|
|
return m_Data[a_Z * m_Width + a_X];
|
2014-02-22 06:59:49 -05:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return E_BASE_COLOR_TRANSPARENT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-06-30 10:50:15 -04:00
|
|
|
unsigned int cMap::GetNumPixels(void) const
|
2014-02-13 10:13:09 -05:00
|
|
|
{
|
2015-06-30 10:50:15 -04:00
|
|
|
return m_Width * m_Height;
|
|
|
|
}
|
2014-02-13 10:13:09 -05:00
|
|
|
|
|
|
|
|
2014-02-18 13:50:08 -05:00
|
|
|
|
2014-02-13 10:13:09 -05:00
|
|
|
|
|
|
|
|
2015-06-30 10:50:15 -04:00
|
|
|
const cMapDecorator cMap::CreateDecorator(const cEntity * a_TrackedEntity)
|
|
|
|
{
|
|
|
|
int InsideWidth = (GetWidth() / 2) - 1;
|
|
|
|
int InsideHeight = (GetHeight() / 2) - 1;
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2015-06-30 10:50:15 -04:00
|
|
|
// Center of pixel
|
2015-08-04 18:24:59 -04:00
|
|
|
int PixelX = static_cast<int>(a_TrackedEntity->GetPosX() - GetCenterX()) / static_cast<int>(GetPixelWidth());
|
|
|
|
int PixelZ = static_cast<int>(a_TrackedEntity->GetPosZ() - GetCenterZ()) / static_cast<int>(GetPixelWidth());
|
2014-02-13 10:13:09 -05:00
|
|
|
|
2015-06-30 10:50:15 -04:00
|
|
|
cMapDecorator::eType Type;
|
|
|
|
int Rot;
|
2014-02-13 10:13:09 -05:00
|
|
|
|
2015-06-30 10:50:15 -04:00
|
|
|
if ((PixelX > -InsideWidth) && (PixelX <= InsideWidth) && (PixelZ > -InsideHeight) && (PixelZ <= InsideHeight))
|
|
|
|
{
|
|
|
|
double Yaw = a_TrackedEntity->GetYaw();
|
2014-02-13 10:13:09 -05:00
|
|
|
|
2015-06-30 10:50:15 -04:00
|
|
|
if (GetDimension() == dimNether)
|
|
|
|
{
|
|
|
|
// TODO 2014-02-19 xdot: Refine
|
2017-06-13 15:35:30 -04:00
|
|
|
Rot = GetRandomProvider().RandInt(15);
|
2015-06-30 10:50:15 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Rot = CeilC(((Yaw - 11.25) * 16) / 360);
|
|
|
|
}
|
2014-02-13 10:13:09 -05:00
|
|
|
|
2015-06-30 10:50:15 -04:00
|
|
|
Type = cMapDecorator::eType::E_TYPE_PLAYER;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Rot = 0;
|
|
|
|
Type = cMapDecorator::eType::E_TYPE_PLAYER_OUTSIDE;
|
2014-02-13 10:13:09 -05:00
|
|
|
|
2015-06-30 10:50:15 -04:00
|
|
|
// Move to border
|
|
|
|
if (PixelX <= -InsideWidth)
|
|
|
|
{
|
|
|
|
PixelX = -InsideWidth;
|
|
|
|
}
|
|
|
|
if (PixelZ <= -InsideHeight)
|
|
|
|
{
|
|
|
|
PixelZ = -InsideHeight;
|
|
|
|
}
|
|
|
|
if (PixelX > InsideWidth)
|
|
|
|
{
|
|
|
|
PixelX = InsideWidth;
|
|
|
|
}
|
|
|
|
if (PixelZ > InsideHeight)
|
|
|
|
{
|
|
|
|
PixelZ = InsideHeight;
|
|
|
|
}
|
|
|
|
}
|
2014-02-13 10:13:09 -05:00
|
|
|
|
2015-08-04 18:24:59 -04:00
|
|
|
return {Type, static_cast<unsigned>(2 * PixelX + 1), static_cast<unsigned>(2 * PixelZ + 1), Rot};
|
2014-02-22 06:59:49 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-07-26 17:24:36 -04:00
|
|
|
|
2014-02-15 13:06:47 -05:00
|
|
|
unsigned int cMap::GetPixelWidth(void) const
|
2014-02-13 10:13:09 -05:00
|
|
|
{
|
2015-08-04 18:24:59 -04:00
|
|
|
return static_cast<unsigned int>(pow(2.0, static_cast<double>(m_Scale)));
|
2014-02-13 10:13:09 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|