[BlockData] Added. [BlockWorkbench] Now keeps items stored inside.

This commit is contained in:
Quentin Bazin 2018-06-29 07:16:51 +02:00
parent b7d8c47e52
commit 9c16bfd264
13 changed files with 178 additions and 11 deletions

84
include/core/Vector3.hpp Normal file
View File

@ -0,0 +1,84 @@
/*
* =====================================================================================
*
* Filename: Vector3.hpp
*
* Description:
*
* Created: 29/06/2018 06:57:12
*
* Author: Quentin Bazin, <quent42340@gmail.com>
*
* =====================================================================================
*/
#ifndef VECTOR3_HPP_
#define VECTOR3_HPP_
#include <stdexcept>
#include <utility>
#include "IntTypes.hpp"
template<typename T>
class Vector3 {
public:
Vector3() = default;
Vector3(T _x, T _y, T _z) : x(_x), y(_y), z(_z) {}
template<typename U>
Vector3(const Vector3<U> &vector3) : x(vector3.x), y(vector3.y), z(vector3.z) {}
Vector3 operator+(const Vector3<T> &vector3) const { return Vector3{x + vector3.x, y + vector3.y, z + vector3.z}; }
Vector3 operator-(const Vector3<T> &vector3) const { return Vector3{x - vector3.x, y - vector3.y, z - vector3.z}; }
Vector3 operator*(T n) const { return Vector3{x * n, y * n, z * n}; }
Vector3 operator/(T n) const {
if(n != 0) {
return Vector3{x / n, y / n, z / n};
} else {
throw std::overflow_error("Divide by zero exception");
}
}
Vector3& operator=(T n) { x = n; y = n; z = n; return *this; }
Vector3 &operator+=(const Vector3 &vector3) { *this = operator+(vector3); return *this; }
Vector3 &operator-=(const Vector3 &vector3) { *this = operator-(vector3); return *this; }
Vector3 &operator*=(T n) { *this = operator*(n); return *this; }
Vector3 &operator/=(T n) { *this = operator/(n); return *this; }
bool operator==(const Vector3<T> &vector3) const { return x == vector3.x && y == vector3.y && z == vector3.z; }
bool operator!=(const Vector3<T> &vector3) const { return !operator==(vector3); }
// Needed if Vector3 is used as a key in a std::map
bool operator<(const Vector3<T> &vector3) const { return x < vector3.x && y <= vector3.y && z <= vector3.z; }
bool operator>(const Vector3<T> &vector3) const { return x > vector3.x && y >= vector3.y && z >= vector3.z; }
T x;
T y;
T z;
};
template<typename T>
Vector3<T> operator*(T n, Vector3<T> &vector3) { return vector3.operator*(n); }
namespace std {
template<typename T>
struct hash<Vector3<T>> {
size_t operator()(const Vector3<T>& vector3) const {
std::hash<T> hash;
auto h1 = hash(vector3.x);
auto h2 = hash(vector3.y);
auto h3 = hash(vector3.z);
return std::hash<T>{}(h1 ^ (h2 << h3) ^ h3);
}
};
}
using Vector3i = Vector3<int>;
using Vector3u = Vector3<unsigned int>;
using Vector3f = Vector3<float>;
using Vector3d = Vector3<double>;
#endif // VECTOR3_HPP_

View File

@ -20,7 +20,7 @@ class CraftingRecipe;
class CraftingWidget : public Widget {
public:
CraftingWidget(u16 width, u16 height, Widget *parent = nullptr);
CraftingWidget(Inventory &craftingInventory, Widget *parent = nullptr);
void onMouseEvent(const SDL_Event &event, MouseItemWidget &mouseItemWidget);
@ -29,7 +29,7 @@ class CraftingWidget : public Widget {
const ItemWidget *currentItemWidget() const { return m_craftingResultInventoryWidget.currentItemWidget() ? m_craftingResultInventoryWidget.currentItemWidget() : m_craftingInventoryWidget.currentItemWidget(); }
protected:
Inventory m_craftingInventory;
Inventory &m_craftingInventory;
InventoryWidget m_craftingInventoryWidget{this};
Inventory m_craftingResultInventory{1, 1};

View File

@ -19,6 +19,9 @@
class SmallCraftingWidget : public CraftingWidget {
public:
SmallCraftingWidget(Widget *parent = nullptr);
private:
Inventory m_inventory{2, 2};
};
#endif // SMALLCRAFTINGWIDGET_HPP_

View File

@ -18,7 +18,7 @@
class WorkbenchWidget : public Widget {
public:
WorkbenchWidget(Inventory &playerInventory, Inventory &hotbarInventory, Widget *parent = nullptr);
WorkbenchWidget(Inventory &playerInventory, Inventory &hotbarInventory, Inventory &craftingInventory, Widget *parent = nullptr);
void onEvent(const SDL_Event &event) override;
@ -29,14 +29,14 @@ class WorkbenchWidget : public Widget {
Image m_background;
CraftingWidget m_craftingWidget{3, 3, this};
Inventory &m_playerInventory;
InventoryWidget m_playerInventoryWidget{this};
Inventory &m_hotbarInventory;
InventoryWidget m_hotbarInventoryWidget{this};
CraftingWidget m_craftingWidget;
MouseItemWidget m_mouseItemWidget{this};
};

View File

@ -0,0 +1,25 @@
/*
* =====================================================================================
*
* Filename: BlockData.hpp
*
* Description:
*
* Created: 29/06/2018 06:52:08
*
* Author: Quentin Bazin, <quent42340@gmail.com>
*
* =====================================================================================
*/
#ifndef BLOCKDATA_HPP_
#define BLOCKDATA_HPP_
#include "Inventory.hpp"
struct BlockData {
BlockData(int width, int height) : inventory(width, height) {}
Inventory inventory;
};
#endif // BLOCKDATA_HPP_

View File

@ -19,12 +19,14 @@
#include <vector>
#include "Block.hpp"
#include "BlockData.hpp"
#include "ChunkBuilder.hpp"
#include "ChunkLightmap.hpp"
#include "IDrawable.hpp"
#include "NonCopyable.hpp"
#include "Shader.hpp"
#include "Texture.hpp"
#include "Vector3.hpp"
#include "VertexBuffer.hpp"
class Chunk : public NonCopyable, public IDrawable {
@ -46,6 +48,8 @@ class Chunk : public NonCopyable, public IDrawable {
u32 getBlock(int x, int y, int z) const;
void setBlock(int x, int y, int z, u32 id);
BlockData *getBlockData(int x, int y, int z);
s32 x() const { return m_x; }
s32 y() const { return m_y; }
s32 z() const { return m_z; }
@ -97,6 +101,8 @@ class Chunk : public NonCopyable, public IDrawable {
u32 m_lastTick = 0;
std::unordered_map<std::size_t, const Block&> m_tickingBlocks;
std::unordered_map<Vector3i, BlockData> m_blockData;
};
#endif // CHUNK_HPP_

View File

@ -33,6 +33,8 @@ class World : public IDrawable {
u32 getBlock(int x, int y, int z) const;
void setBlock(int x, int y, int z, u32 id);
BlockData *getBlockData(int x, int y, int z);
// Render distance in chunks
static const u16 renderDistance = 8;

View File

@ -14,7 +14,7 @@
#include "CraftingWidget.hpp"
#include "Registry.hpp"
CraftingWidget::CraftingWidget(u16 width, u16 height, Widget *parent) : Widget(parent), m_craftingInventory{width, height} {
CraftingWidget::CraftingWidget(Inventory &craftingInventory, Widget *parent) : Widget(parent), m_craftingInventory{craftingInventory} {
m_craftingInventoryWidget.init(m_craftingInventory);
m_craftingInventoryWidget.setPosition(29, 16, 0);

View File

@ -13,7 +13,7 @@
*/
#include "SmallCraftingWidget.hpp"
SmallCraftingWidget::SmallCraftingWidget(Widget *parent) : CraftingWidget(2, 2, parent) {
SmallCraftingWidget::SmallCraftingWidget(Widget *parent) : CraftingWidget(m_inventory, parent) {
m_craftingInventoryWidget.setPosition(97, 17, 0);
m_craftingResultInventoryWidget.setPosition(153, 27, 0);
}

View File

@ -13,8 +13,8 @@
*/
#include "WorkbenchWidget.hpp"
WorkbenchWidget::WorkbenchWidget(Inventory &playerInventory, Inventory &hotbarInventory, Widget *parent)
: Widget(176, 166, parent), m_playerInventory(playerInventory), m_hotbarInventory(hotbarInventory)
WorkbenchWidget::WorkbenchWidget(Inventory &playerInventory, Inventory &hotbarInventory, Inventory &craftingInventory, Widget *parent)
: Widget(176, 166, parent), m_playerInventory(playerInventory), m_hotbarInventory(hotbarInventory), m_craftingWidget(craftingInventory, this)
{
m_background.load("texture-workbench");
m_background.setClipRect(0, 0, 176, 166);

View File

@ -13,16 +13,23 @@
*/
#include "ApplicationStateStack.hpp"
#include "BlockWorkbench.hpp"
#include "Exception.hpp"
#include "InventoryState.hpp"
#include "Player.hpp"
#include "WorkbenchWidget.hpp"
#include "World.hpp"
BlockWorkbench::BlockWorkbench() : Block(BlockType::Workbench, 77) {
}
bool BlockWorkbench::onBlockActivated(const glm::ivec3 &, Player &player, World &) const {
bool BlockWorkbench::onBlockActivated(const glm::ivec3 &position, Player &player, World &world) const {
BlockData *data = world.getBlockData(position.x, position.y, position.z);
if (!data)
throw EXCEPTION("BlockWorkbench at (", position.x, position.y, position.z, ") has no inventory");
auto &inventoryState = ApplicationStateStack::getInstance().push<InventoryState>(&ApplicationStateStack::getInstance().top());
inventoryState.setupWidget<WorkbenchWidget>(player.inventory(), player.hotbarInventory());
inventoryState.setupWidget<WorkbenchWidget>(player.inventory(), player.hotbarInventory(), data->inventory);
return true;
}

View File

@ -81,6 +81,17 @@ void Chunk::setBlock(int x, int y, int z, u32 type) {
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;
@ -95,6 +106,21 @@ void Chunk::setBlock(int x, int y, int z, u32 type) {
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},

View File

@ -168,3 +168,17 @@ void World::setBlock(int x, int y, int z, u32 id) {
chunk->setBlock(x & (Chunk::width - 1), y & (Chunk::height - 1), z & (Chunk::depth - 1), id);
}
BlockData *World::getBlockData(int x, int y, int z) {
int cx = (x + Chunk::width * (m_width / 2)) / Chunk::width;
int cy = (y + Chunk::height * (m_height / 2)) / Chunk::height;
int cz = (z + Chunk::depth * (m_depth / 2)) / Chunk::depth;
if (cx < 0 || cx >= m_width || cy < 0 || cy >= m_height || cz < 0 || cz >= m_depth)
return 0;
Chunk *chunk = m_chunks.at(cx + cy * m_width + cz * m_width * m_height).get();
if (chunk)
return chunk->getBlockData(x & (Chunk::width - 1), y & (Chunk::height - 1), z & (Chunk::depth - 1));
return 0;
}