1
0
cuberite-2a/src/Map.cpp

365 lines
6.7 KiB
C++
Raw Normal View History

2014-02-13 10:13:09 -05:00
// Map.cpp
#include "Globals.h"
#include "Map.h"
#include "World.h"
2014-02-14 09:21:16 -05:00
#include "Chunk.h"
2014-02-15 13:06:47 -05:00
#include "Entities/Player.h"
#include "FastRandom.h"
2015-06-30 10:50:15 -04:00
#include "Blocks/BlockHandler.h"
2014-02-18 13:50:08 -05:00
2014-02-13 14:36:24 -05:00
cMap::cMap(unsigned int a_ID, cWorld * a_World)
: 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 14:36:24 -05:00
, m_Scale(3)
, m_CenterX(0)
, m_CenterZ(0)
, m_World(a_World)
{
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)
{
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)
{
int PixelRadius = a_Radius / GetPixelWidth();
2014-02-17 09:27:12 -05:00
unsigned int StartX = Clamp(a_PixelX - PixelRadius, 0, (int)m_Width);
unsigned int StartZ = Clamp(a_PixelZ - PixelRadius, 0, (int)m_Height);
2014-02-15 13:06:47 -05:00
2014-02-17 09:27:12 -05:00
unsigned int EndX = Clamp(a_PixelX + PixelRadius, 0, (int)m_Width);
unsigned int EndZ = Clamp(a_PixelZ + PixelRadius, 0, (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
{
2014-02-15 13:06:47 -05:00
int dX = X - a_PixelX;
int dZ = Z - a_PixelZ;
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)
{
unsigned int PixelWidth = GetPixelWidth();
int PixelX = (int) (a_Player.GetPosX() - m_CenterX) / PixelWidth + (m_Width / 2);
int PixelZ = (int) (a_Player.GetPosZ() - m_CenterZ) / PixelWidth + (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
{
2014-02-19 08:28:48 -05:00
unsigned int PixelWidth = GetPixelWidth();
2014-02-15 13:06:47 -05:00
int BlockX = m_CenterX + ((a_X - (m_Width / 2)) * PixelWidth);
int BlockZ = m_CenterZ + ((a_Z - (m_Height / 2)) * PixelWidth);
2014-02-15 13:06:47 -05: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);
class cCalculatePixelCb :
public cChunkCallback
2014-02-13 10:13:09 -05:00
{
2014-02-15 13:06:47 -05:00
cMap * m_Map;
int m_RelX, m_RelZ;
ColorID m_PixelData;
public:
cCalculatePixelCb(cMap * a_Map, int a_RelX, int a_RelZ)
: m_Map(a_Map), m_RelX(a_RelX), m_RelZ(a_RelZ), m_PixelData(E_BASE_COLOR_TRANSPARENT) {}
2014-02-15 13:06:47 -05:00
virtual bool Item(cChunk * a_Chunk) override
{
2015-06-30 10:50:15 -04:00
if (!a_Chunk->IsValid())
2014-02-15 13:06:47 -05:00
{
return false;
}
2014-02-14 09:21:16 -05:00
if (m_Map->GetDimension() == dimNether)
{
// 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;
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);
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;
while (((--Height) != -1) && IsBlockWater(a_Chunk->GetBlock(m_RelX, Height, m_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)
{
2015-06-30 10:50:15 -04:00
while (((--Height) != -1) && ((ColourID = BlockHandler(a_Chunk->GetBlock(m_RelX, Height, m_RelZ))->GetMapBaseColourID(a_Chunk->GetMeta(m_RelX, Height, m_RelZ))) == 0))
{
2015-06-30 10:50:15 -04:00
continue;
}
}
2015-06-30 10:50:15 -04:00
// 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)];
2014-02-15 13:06:47 -05:00
return false;
}
ColorID GetPixelData(void) const
{
return m_PixelData;
}
} CalculatePixelCb(this, RelX, RelZ);
2014-10-20 16:55:07 -04:00
ASSERT(m_World != nullptr);
2014-02-19 08:28:48 -05:00
m_World->DoWithChunk(ChunkX, ChunkZ, CalculatePixelCb);
2014-02-14 09:21:16 -05:00
2014-02-22 06:59:49 -05:00
SetPixel(a_X, a_Z, CalculatePixelCb.GetPixelData());
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;
// Center of pixel
int PixelX = (int)(a_TrackedEntity->GetPosX() - GetCenterX()) / GetPixelWidth();
int PixelZ = (int)(a_TrackedEntity->GetPosZ() - GetCenterZ()) / 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)
{
cFastRandom Random;
2014-02-13 10:13:09 -05:00
2015-06-30 10:50:15 -04:00
// TODO 2014-02-19 xdot: Refine
Rot = Random.NextInt(16);
}
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
{
if ((PixelX > 320.0) || (PixelZ > 320.0))
{
;
}
2014-02-13 10:13:09 -05:00
2015-06-30 10:50:15 -04:00
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-06-30 10:50:15 -04:00
return {Type, (unsigned)(2 * PixelX + 1), (unsigned)(2 * PixelZ + 1), Rot};
2014-02-22 06:59:49 -05:00
}
2014-02-15 13:06:47 -05:00
unsigned int cMap::GetPixelWidth(void) const
2014-02-13 10:13:09 -05:00
{
return (int) pow(2.0, (double) m_Scale);
2014-02-13 10:13:09 -05:00
}