164 lines
6.2 KiB
C++
164 lines
6.2 KiB
C++
/*
|
|
* =====================================================================================
|
|
*
|
|
* Filename: Chunk.cpp
|
|
*
|
|
* Description:
|
|
*
|
|
* Created: 15/12/2014 17:31:32
|
|
*
|
|
* Author: Quentin Bazin, <quent42340@gmail.com>
|
|
*
|
|
* =====================================================================================
|
|
*/
|
|
#include "Chunk.hpp"
|
|
#include "GameClock.hpp"
|
|
#include "Registry.hpp"
|
|
|
|
Chunk::Chunk(s32 x, s32 y, s32 z, Texture &texture) : m_texture(texture) {
|
|
m_x = x;
|
|
m_y = y;
|
|
m_z = z;
|
|
|
|
std::memset(m_data, 0, sizeof(m_data));
|
|
}
|
|
|
|
void Chunk::update(Player &player, World &world) {
|
|
if (!m_isChanged) return;
|
|
|
|
m_isChanged = false;
|
|
|
|
m_lightmap.updateLights();
|
|
|
|
m_verticesCount = m_builder.buildChunk(*this, m_vbo);
|
|
|
|
if (m_lastTick < GameClock::getTicks() / 50) {
|
|
m_lastTick = GameClock::getTicks() / 50;
|
|
|
|
for (auto &it : m_tickingBlocks) {
|
|
int z = it.first / (width * height);
|
|
int y = (it.first - z * width * height) / width;
|
|
int x = (it.first - z * width * height) % width;
|
|
it.second.onTick(glm::ivec3{x + m_x * width, y + m_y * height, z + m_z * depth}, player, *this, world);
|
|
}
|
|
}
|
|
}
|
|
|
|
u32 Chunk::getBlock(int x, int y, int z) const {
|
|
if(x < 0) return m_surroundingChunks[0] ? m_surroundingChunks[0]->getBlock(x + Chunk::width, y, z) : 0;
|
|
if(x >= Chunk::width) return m_surroundingChunks[1] ? m_surroundingChunks[1]->getBlock(x - Chunk::width, y, z) : 0;
|
|
if(y < 0) return m_surroundingChunks[4] ? m_surroundingChunks[4]->getBlock(x, y + Chunk::height, z) : 0;
|
|
if(y >= Chunk::height) return m_surroundingChunks[5] ? m_surroundingChunks[5]->getBlock(x, y - Chunk::height, z) : 0;
|
|
if(z < 0) return m_surroundingChunks[2] ? m_surroundingChunks[2]->getBlock(x, y, z + Chunk::depth) : 0;
|
|
if(z >= Chunk::depth) return m_surroundingChunks[3] ? m_surroundingChunks[3]->getBlock(x, y, z - Chunk::depth) : 0;
|
|
return m_data[x][y][z];
|
|
}
|
|
|
|
// #include "Debug.hpp"
|
|
|
|
void Chunk::setBlock(int x, int y, int z, u32 type) {
|
|
if(x < 0) { if(m_surroundingChunks[0]) m_surroundingChunks[0]->setBlock(x + Chunk::width, y, z, type); return; }
|
|
if(x >= Chunk::width) { if(m_surroundingChunks[1]) m_surroundingChunks[1]->setBlock(x - Chunk::width, y, z, type); return; }
|
|
if(y < 0) { if(m_surroundingChunks[4]) m_surroundingChunks[4]->setBlock(x, y + Chunk::height, z, type); return; }
|
|
if(y >= Chunk::height) { if(m_surroundingChunks[5]) m_surroundingChunks[5]->setBlock(x, y - Chunk::height, z, type); return; }
|
|
if(z < 0) { if(m_surroundingChunks[2]) m_surroundingChunks[2]->setBlock(x, y, z + Chunk::depth, type); return; }
|
|
if(z >= Chunk::depth) { if(m_surroundingChunks[3]) m_surroundingChunks[3]->setBlock(x, y, z - Chunk::depth, type); return; }
|
|
|
|
const Block &block = Registry::getInstance().getBlock(type);
|
|
// if (type == 8)
|
|
// DEBUG("at (", m_x, m_y, m_z, ")", "(", x, y, z, ")", type, "is", block.canUpdate());
|
|
if (block.canUpdate()) {
|
|
m_tickingBlocks.emplace(x + y * width + z * width * height, block);
|
|
}
|
|
else {
|
|
auto it = m_tickingBlocks.find(x + y * width + z * width * height);
|
|
if (it != m_tickingBlocks.end())
|
|
m_tickingBlocks.erase(it);
|
|
}
|
|
|
|
if (type == BlockType::Glowstone)
|
|
m_lightmap.addLight(x, y, z, 14);
|
|
else
|
|
m_lightmap.removeLight(x, y, z);
|
|
|
|
if (type == BlockType::Workbench)
|
|
m_blockData.emplace(Vector3i{x, y, z}, BlockData{3, 3});
|
|
else if (type == BlockType::Furnace)
|
|
m_blockData.emplace(Vector3i{x, y, z}, BlockData{1, 3});
|
|
|
|
if (m_data[x][y][z] == BlockType::Workbench || m_data[x][y][z] == BlockType::Furnace) {
|
|
auto it = m_blockData.find(Vector3i{x, y, z});
|
|
if (it != m_blockData.end())
|
|
m_blockData.erase(it);
|
|
}
|
|
|
|
m_data[x][y][z] = type;
|
|
|
|
m_isChanged = true;
|
|
|
|
updateNeighbours(x, y, z);
|
|
|
|
if(x == 0 && m_surroundingChunks[Left]) { m_surroundingChunks[Left]->m_isChanged = true; }
|
|
if(x == width - 1 && m_surroundingChunks[Right]) { m_surroundingChunks[Right]->m_isChanged = true; }
|
|
if(y == 0 && m_surroundingChunks[Bottom]) { m_surroundingChunks[Bottom]->m_isChanged = true; }
|
|
if(y == height - 1 && m_surroundingChunks[Top]) { m_surroundingChunks[Top]->m_isChanged = true; }
|
|
if(z == 0 && m_surroundingChunks[Front]) { m_surroundingChunks[Front]->m_isChanged = true; }
|
|
if(z == depth - 1 && m_surroundingChunks[Back]) { m_surroundingChunks[Back]->m_isChanged = true; }
|
|
}
|
|
|
|
BlockData *Chunk::getBlockData(int x, int y, int z) {
|
|
if(x < 0) return m_surroundingChunks[0] ? m_surroundingChunks[0]->getBlockData(x + Chunk::width, y, z) : 0;
|
|
if(x >= Chunk::width) return m_surroundingChunks[1] ? m_surroundingChunks[1]->getBlockData(x - Chunk::width, y, z) : 0;
|
|
if(y < 0) return m_surroundingChunks[4] ? m_surroundingChunks[4]->getBlockData(x, y + Chunk::height, z) : 0;
|
|
if(y >= Chunk::height) return m_surroundingChunks[5] ? m_surroundingChunks[5]->getBlockData(x, y - Chunk::height, z) : 0;
|
|
if(z < 0) return m_surroundingChunks[2] ? m_surroundingChunks[2]->getBlockData(x, y, z + Chunk::depth) : 0;
|
|
if(z >= Chunk::depth) return m_surroundingChunks[3] ? m_surroundingChunks[3]->getBlockData(x, y, z - Chunk::depth) : 0;
|
|
|
|
auto it = m_blockData.find(Vector3i{x, y, z});
|
|
if (it == m_blockData.end())
|
|
return nullptr;
|
|
|
|
return &it->second;
|
|
}
|
|
|
|
void Chunk::updateNeighbours(int x, int y, int z) {
|
|
int neighbours[7][3] = {
|
|
{x, y, z},
|
|
{x - 1, y, z},
|
|
{x + 1, y, z},
|
|
{x, y - 1, z},
|
|
{x, y + 1, z},
|
|
{x, y, z - 1},
|
|
{x, y, z + 1},
|
|
};
|
|
|
|
for (u32 i = 0 ; i < 7 ; ++i) {
|
|
u32 blockID = getBlock(neighbours[i][0], neighbours[i][1], neighbours[i][2]);
|
|
if (blockID) {
|
|
const Block &block = Registry::getInstance().getBlock(blockID);
|
|
block.onNeighbourUpdate(glm::vec3{x, y, z},
|
|
glm::vec3{neighbours[i][0], neighbours[i][1], neighbours[i][2]},
|
|
*this);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Chunk::draw(RenderTarget &target, RenderStates states) const {
|
|
if(m_verticesCount == 0) return;
|
|
|
|
states.texture = &m_texture;
|
|
|
|
target.draw(m_vbo, GL_QUADS, 0, m_verticesCount, states);
|
|
|
|
// drawOutlines(target, states);
|
|
}
|
|
|
|
void Chunk::drawOutlines(RenderTarget &target, RenderStates states) const {
|
|
states.texture = nullptr;
|
|
|
|
for(u32 i = 0 ; i < m_verticesCount ; i += 4) {
|
|
target.draw(m_vbo, GL_LINE_LOOP, i, 4, states);
|
|
}
|
|
}
|
|
|