2020-05-15 00:27:12 +02:00

129 lines
4.1 KiB
C++

/*
* =====================================================================================
*
* OpenMiner
*
* Copyright (C) 2018-2020 Unarelith, Quentin Bazin <openminer@unarelith.net>
* Copyright (C) 2019-2020 the OpenMiner contributors (see CONTRIBUTORS.md)
*
* This file is part of OpenMiner.
*
* OpenMiner is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* OpenMiner is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with OpenMiner; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* =====================================================================================
*/
#ifndef CHUNK_HPP_
#define CHUNK_HPP_
#include <atomic>
#include <memory>
#include <unordered_map>
#include <vector>
#include <gk/core/Vector3.hpp>
#include <gk/gl/VertexBuffer.hpp>
#include <gk/utils/NonCopyable.hpp>
#include "Block.hpp"
#include "BlockData.hpp"
#include "ChunkLightmap.hpp"
class World;
class Chunk : public gk::NonCopyable {
public:
enum {
West, // cx - 1
East, // cx + 1
South, // cy - 1
North, // cy + 1
Bottom, // cz - 1
Top // cz + 1
};
public:
Chunk(s32 x, s32 y, s32 z, World &world);
virtual ~Chunk() = default;
u16 getBlock(int x, int y, int z) const;
u16 getData(int x, int y, int z) const;
void setBlock(int x, int y, int z, u16 type);
void setData(int x, int y, int z, u16 data);
void setBlockRaw(int x, int y, int z, u16 block);
virtual void onBlockPlaced(int, int, int, const Block &) const {}
virtual void onBlockDestroyed(int, int, int, const Block &) const {}
BlockData *getBlockData(int x, int y, int z) const;
BlockData *addBlockData(int x, int y, int z, int inventoryWidth = 0, int inventoryHeight = 0);
s32 x() const { return m_x; }
s32 y() const { return m_y; }
s32 z() const { return m_z; }
Chunk *getSurroundingChunk(u8 i) { return (i > 5) ? nullptr : m_surroundingChunks[i]; }
const Chunk *getSurroundingChunk(u8 i) const { return (i > 5) ? nullptr : m_surroundingChunks[i]; }
void setSurroundingChunk(u8 i, Chunk *chunk) { if (i < 6) m_surroundingChunks[i] = chunk; }
bool areAllNeighboursLoaded() const;
bool areAllNeighboursInitialized() const;
bool hasChanged() const { return m_hasChanged; }
void setChanged(bool hasChanged) { m_hasChanged = hasChanged; }
bool hasLightChanged() const { return m_hasLightChanged; }
void setLightChanged(bool hasLightChanged) { m_hasLightChanged = hasLightChanged; }
bool isInitialized() const { return m_isInitialized; }
void setInitialized(bool isInitialized) { m_isInitialized = isInitialized; }
ChunkLightmap &lightmap() { return m_lightmap; }
const ChunkLightmap &lightmap() const { return m_lightmap; }
static constexpr u8 width = CHUNK_WIDTH;
static constexpr u8 depth = CHUNK_DEPTH;
static constexpr u8 height = CHUNK_HEIGHT;
// Placing horizontal slices together may help with cache locality and compressibility
using DataArray = u32[Chunk::height][Chunk::depth][Chunk::width];
const DataArray &data() const { return m_data; }
u32 data(int x, int y, int z) const { return m_data[z][y][x]; }
protected:
s32 m_x;
s32 m_y;
s32 m_z;
World &m_world;
DataArray m_data;
ChunkLightmap m_lightmap{this};
Chunk *m_surroundingChunks[6]{nullptr, nullptr, nullptr, nullptr, nullptr, nullptr};
std::atomic_bool m_hasChanged{false};
std::atomic_bool m_hasLightChanged{false};
std::atomic_bool m_isInitialized{false};
std::unordered_map<std::size_t, const Block&> m_tickingBlocks;
std::unordered_map<gk::Vector3i, std::unique_ptr<BlockData>> m_blockData;
};
#endif // CHUNK_HPP_