[TilesDef] Alternative tiles added. [ISerializable] Improved.

This commit is contained in:
Quentin Bazin 2020-01-31 15:04:04 +09:00
parent 6d8d8ef623
commit e516b86d49
26 changed files with 180 additions and 117 deletions

View File

@ -149,8 +149,8 @@ inline void ChunkBuilder::addFace(u8 x, u8 y, u8 z, u8 i, const ClientChunk &chu
// Computing face normal (already normalized because vertexCoords are normalized)
normal = glm::cross(v1, v2);
// const glm::vec4 &blockTexCoords = block->getTexCoords(i, chunk.getData(x, y, z));
const gk::FloatRect &blockTexCoords = m_textureAtlas.getTexCoords(block->tiles().getTextureForFace(i));
const BlockData *blockData = chunk.getBlockData(x, y, z);
const gk::FloatRect &blockTexCoords = m_textureAtlas.getTexCoords(block->tiles().getTextureForFace(i, blockData ? blockData->useAltTiles : false));
float faceTexCoords[2 * 4] = {
blockTexCoords.x, blockTexCoords.y + blockTexCoords.height,
blockTexCoords.x + blockTexCoords.width, blockTexCoords.y + blockTexCoords.height,
@ -178,7 +178,6 @@ inline void ChunkBuilder::addFace(u8 x, u8 y, u8 z, u8 i, const ClientChunk &chu
vertices[j].texCoord[0] = faceTexCoords[j * 2];
vertices[j].texCoord[1] = faceTexCoords[j * 2 + 1];
// FIXME: Duplicated below
if (Config::isSunSmoothLightingEnabled)
vertices[j].lightValue[0] = getLightForVertex(Light::Sun, x, y, z, i, j, normal, chunk);
else
@ -186,7 +185,6 @@ inline void ChunkBuilder::addFace(u8 x, u8 y, u8 z, u8 i, const ClientChunk &chu
surroundingBlockPos[0], surroundingBlockPos[1], surroundingBlockPos[2]);
int torchlight = chunk.lightmap().getTorchlight(x, y, z);
if (Config::isTorchSmoothLightingEnabled && torchlight == 0)
vertices[j].lightValue[1] = getLightForVertex(Light::Torch, x, y, z, i, j, normal, chunk);
else
@ -230,7 +228,6 @@ inline void ChunkBuilder::addFace(u8 x, u8 y, u8 z, u8 i, const ClientChunk &chu
}
inline void ChunkBuilder::addCross(u8 x, u8 y, u8 z, const ClientChunk &chunk, const Block *block) {
// const glm::vec4 &blockTexCoords = block->getTexCoords(0, chunk.getData(x, y, z));
const gk::FloatRect &blockTexCoords = m_textureAtlas.getTexCoords(block->tiles().getTextureForFace(0));
float faceTexCoords[2 * 4] = {
blockTexCoords.x, blockTexCoords.y + blockTexCoords.height,
@ -261,20 +258,9 @@ inline void ChunkBuilder::addCross(u8 x, u8 y, u8 z, const ClientChunk &chunk, c
vertices[j].texCoord[0] = faceTexCoords[j * 2];
vertices[j].texCoord[1] = faceTexCoords[j * 2 + 1];
// FIXME: Duplicated above
// if (Config::isSunSmoothLightingEnabled)
// vertices[j].lightValue[0] = getLightForVertex(Light::Sun, x, y, z, i, j, normal, chunk);
// else
vertices[j].lightValue[0] = chunk.lightmap().getSunlight(x, y, z);
// if (Config::isTorchSmoothLightingEnabled)
// vertices[j].lightValue[1] = getLightForVertex(Light::Torch, x, y, z, i, j, normal, chunk);
// else
vertices[j].lightValue[1] = chunk.lightmap().getTorchlight(x, y, z);
// if (Config::isAmbientOcclusionEnabled)
// vertices[j].ambientOcclusion = getAmbientOcclusion(x, y, z, i, j, chunk);
// else
vertices[j].ambientOcclusion = 5;
vertices[j].blockType = block->id();

View File

@ -61,7 +61,7 @@ class Registry : public ISerializable {
const Recipe *getRecipe(const Inventory &inventory) const;
void serialize(sf::Packet &packet) override;
void serialize(sf::Packet &packet) const override;
void deserialize(sf::Packet &packet) override;
const std::vector<std::unique_ptr<Block>> &blocks() const { return m_blocks; }

View File

@ -21,6 +21,8 @@
#include <gk/core/IntTypes.hpp>
#include <sol.hpp>
#include "ISerializable.hpp"
enum BlockFace : u8 {
@ -35,15 +37,16 @@ enum BlockFace : u8 {
class TilesDef : public ISerializable {
public:
TilesDef() = default;
TilesDef(const std::vector<std::string> &textureFilenames_)
: textureFilenames(textureFilenames_) {}
const std::string &getTextureForFace(u8 face) const;
const std::string &getTextureForFace(u8 face, bool useAltTiles = false) const;
void serialize(sf::Packet &packet) override;
void serialize(sf::Packet &packet) const override;
void deserialize(sf::Packet &packet) override;
void loadFromLuaTable(const sol::table &table);
std::vector<std::string> textureFilenames;
std::vector<std::string> altTextureFilenames;
};
#endif // TILESDEF_HPP_

View File

@ -24,7 +24,7 @@ class CraftingRecipe : public Recipe {
CraftingRecipe() : Recipe("craft") {}
CraftingRecipe(const std::vector<std::string> &pattern, const std::map<char, std::vector<std::string>> &keys, const ItemStack &result, bool isShapeless = false);
void serialize(sf::Packet &packet) override;
void serialize(sf::Packet &packet) const override;
void deserialize(sf::Packet &packet) override;
bool isMatching(const Inventory &inventory) const override;

View File

@ -19,8 +19,9 @@
#include <gk/core/Vector3.hpp>
#include "ItemStack.hpp"
#include "ISerializable.hpp"
class Inventory {
class Inventory : public ISerializable {
public:
Inventory(u16 width, u16 height)
: m_width(width), m_height(height) { m_items.resize(width * height); }
@ -30,6 +31,9 @@ class Inventory {
void setStack(u16 x, u16 y, const std::string &name, u16 amount = 1);
void addStack(const std::string &name, u16 amount = 1);
void serialize(sf::Packet &packet) const override;
void deserialize(sf::Packet &packet) override;
u16 width() const { return m_width; }
u16 height() const { return m_height; }
@ -56,7 +60,4 @@ class Inventory {
bool m_hasChanged = false; // Used to send inventory update packets
};
sf::Packet &operator<<(sf::Packet &packet, Inventory &inventory);
sf::Packet &operator>>(sf::Packet &packet, Inventory &inventory);
#endif // INVENTORY_HPP_

View File

@ -27,7 +27,7 @@ class Item : public ISerializable {
Item() = default;
Item(u32 id, const TilesDef &tiles, const std::string &name, const std::string &label);
void serialize(sf::Packet &packet) override;
void serialize(sf::Packet &packet) const override;
void deserialize(sf::Packet &packet) override;
const std::string &name() const { return m_name; }

View File

@ -21,7 +21,7 @@ class SmeltingRecipe : public Recipe {
SmeltingRecipe() : Recipe("smelt") {}
SmeltingRecipe(const ItemStack &input, const ItemStack &output);
void serialize(sf::Packet &packet) override;
void serialize(sf::Packet &packet) const override;
void deserialize(sf::Packet &packet) override;
bool isMatching(const Inventory &inventory) const override;

View File

@ -20,8 +20,11 @@ class ISerializable {
public:
virtual ~ISerializable() = default;
virtual void serialize(sf::Packet &packet) = 0;
virtual void serialize(sf::Packet &packet) const = 0;
virtual void deserialize(sf::Packet &packet) = 0;
};
sf::Packet &operator<<(sf::Packet &packet, const ISerializable &s);
sf::Packet &operator>>(sf::Packet &packet, ISerializable &s);
#endif // ISERIALIZABLE_HPP_

View File

@ -0,0 +1,43 @@
/*
* =====================================================================================
*
* Filename: NetworkUtils.hpp
*
* Description:
*
* Created: 31/01/2020 14:41:18
*
* Author: Quentin Bazin, <quent42340@gmail.com>
*
* =====================================================================================
*/
#ifndef NETWORKUTILS_HPP_
#define NETWORKUTILS_HPP_
#include <vector>
#include <SFML/Network/Packet.hpp>
template<typename T>
sf::Packet &operator<<(sf::Packet &packet, const std::vector<T> &vec) {
packet << (unsigned int)vec.size();
for (auto &it : vec)
packet << it;
return packet;
}
template<typename T>
sf::Packet &operator>>(sf::Packet &packet, std::vector<T> &vec) {
unsigned int size;
packet >> size;
for (unsigned int i = 0 ; i < size ; ++i) {
T v;
packet >> v;
vec.emplace_back(v);
}
return packet;
}
#endif // NETWORKUTILS_HPP_

View File

@ -41,7 +41,7 @@ class Block : public ISerializable {
Block(u32 id, const TilesDef &tiles, const std::string &name, const std::string &label);
virtual ~Block() = default;
void serialize(sf::Packet &packet) override;
void serialize(sf::Packet &packet) const override;
void deserialize(sf::Packet &packet) override;
u16 id() const { return m_id & 0xffff; }

View File

@ -25,6 +25,8 @@ struct BlockData {
Inventory inventory;
u32 data = 0;
bool useAltTiles = false;
};
#endif // BLOCKDATA_HPP_

View File

@ -49,7 +49,7 @@ class Chunk : public gk::NonCopyable {
void setBlockRaw(int x, int y, int z, u16 block);
BlockData *getBlockData(int x, int y, int z);
BlockData *getBlockData(int x, int y, int z) const;
s32 x() const { return m_x; }
s32 y() const { return m_y; }
@ -96,7 +96,7 @@ class Chunk : public gk::NonCopyable {
std::unordered_map<std::size_t, const Block&> m_tickingBlocks;
std::unordered_map<gk::Vector3i, BlockData> m_blockData;
std::unordered_map<gk::Vector3i, std::unique_ptr<BlockData>> m_blockData;
};
#endif // CHUNK_HPP_

View File

@ -19,7 +19,7 @@
class Player : public ISerializable {
public:
void serialize(sf::Packet &packet) override;
void serialize(sf::Packet &packet) const override;
void deserialize(sf::Packet &packet) override;
s32 x() const { return m_x; }

View File

@ -60,20 +60,18 @@ const Recipe *Registry::getRecipe(const Inventory &inventory) const {
return nullptr;
}
void Registry::serialize(sf::Packet &packet) {
void Registry::serialize(sf::Packet &packet) const {
for (auto &it : m_items) {
packet << u8(DataType::Item);
it.serialize(packet);
packet << u8(DataType::Item) << it;
}
for (auto &it : m_blocks) {
packet << u8(DataType::Block);
it->serialize(packet);
packet << u8(DataType::Block) << *it;
}
for (auto &it : m_recipes) {
packet << u8((it->type() == "craft") ? DataType::CraftingRecipe : DataType::SmeltingRecipe);
it->serialize(packet);
packet << u8((it->type() == "craft") ? DataType::CraftingRecipe : DataType::SmeltingRecipe)
<< *it;
}
}

View File

@ -13,40 +13,58 @@
*/
#include <gk/core/Exception.hpp>
#include "NetworkUtils.hpp"
#include "TilesDef.hpp"
const std::string &TilesDef::getTextureForFace(u8 face) const {
u8 size = textureFilenames.size();
const std::string &TilesDef::getTextureForFace(u8 face, bool useAltTiles) const {
u8 size = (!useAltTiles) ? textureFilenames.size() : altTextureFilenames.size();
if (size == 0)
throw EXCEPTION("Trying to get texture from empty tiles definition");
u8 outFace = face;
if (size == 1)
face = BlockFace::Top;
outFace = BlockFace::Top;
else if (size == 2)
face = (face == BlockFace::Top || face == BlockFace::Bottom) ? 0 : 1;
outFace = (face == BlockFace::Top || face == BlockFace::Bottom) ? 0 : 1;
else if (size == 3 && face >= size)
face = BlockFace::Left;
outFace = BlockFace::Left;
else if (size == 4 && face >= size)
face = BlockFace::Right;
outFace = BlockFace::Right;
else if (size == 5 && face >= size)
face = BlockFace::Front;
outFace = BlockFace::Front;
return textureFilenames.at(face);
}
void TilesDef::serialize(sf::Packet &packet) {
packet << (u8)textureFilenames.size();
for (std::string &it : textureFilenames)
packet << it;
}
void TilesDef::deserialize(sf::Packet &packet) {
u8 textureFilenamesSize = 0;
packet >> textureFilenamesSize;
for (u8 i = 0 ; i < textureFilenamesSize ; ++i) {
std::string str;
packet >> str;
textureFilenames.emplace_back(str);
if (!useAltTiles)
return textureFilenames.at(outFace);
else {
const std::string &filename = altTextureFilenames.at(outFace);
return (!filename.empty()) ? filename : getTextureForFace(face, false);
}
}
void TilesDef::serialize(sf::Packet &packet) const {
packet << textureFilenames; // << altTextureFilenames;
}
void TilesDef::deserialize(sf::Packet &packet) {
packet >> textureFilenames; // >> altTextureFilenames;
}
void TilesDef::loadFromLuaTable(const sol::table &table) {
if (table["tiles"].get_type() == sol::type::table) {
sol::as_table_t<std::vector<std::string>> t = table["tiles"];
textureFilenames = t.source;
}
else
textureFilenames.emplace_back(table["tiles"].get<std::string>());
if (table["alt_tiles"].get_type() != sol::type::none) {
if (table["alt_tiles"].get_type() == sol::type::table) {
sol::as_table_t<std::vector<std::string>> t = table["alt_tiles"];
altTextureFilenames = t.source;
}
else
altTextureFilenames.emplace_back(table["alt_tiles"].get<std::string>());
}
}

View File

@ -29,15 +29,15 @@ CraftingRecipe::CraftingRecipe(const std::vector<std::string> &pattern, const st
m_isShapeless = isShapeless;
}
void CraftingRecipe::serialize(sf::Packet &packet) {
void CraftingRecipe::serialize(sf::Packet &packet) const {
packet << m_result << u8(m_pattern.size());
for (std::string &it : m_pattern)
for (const std::string &it : m_pattern)
packet << it;
packet << u8(m_keys.size());
for (auto &it : m_keys) {
packet << u8(it.first) << u8(it.second.size());
for (std::string &str : it.second) {
for (const std::string &str : it.second) {
packet << str;
}
}

View File

@ -34,33 +34,31 @@ void Inventory::addStack(const std::string &name, u16 amount) {
}
}
sf::Packet &operator<<(sf::Packet &packet, Inventory &inventory) {
packet << u8(inventory.inBlock())
<< s32(inventory.blockPos().x) << s32(inventory.blockPos().y) << s32(inventory.blockPos().z);
void Inventory::serialize(sf::Packet &packet) const {
packet << u8(m_inBlock)
<< s32(m_blockPos.x) << s32(m_blockPos.y) << s32(m_blockPos.z);
int i = 0;
for (auto &it : inventory.items()) {
for (auto &it : m_items) {
packet << it.item().name() << it.amount()
<< u8(i % inventory.width()) << u8(i / inventory.width());
<< u8(i % m_width) << u8(i / m_width);
++i;
}
return packet;
}
sf::Packet &operator>>(sf::Packet &packet, Inventory &inventory) {
void Inventory::deserialize(sf::Packet &packet) {
u8 inBlock;
s32 bx, by, bz;
packet >> inBlock >> bx >> by >> bz;
inventory.setInBlock(inBlock);
inventory.setBlockPos({bx, by, bz});
m_inBlock = inBlock;
m_blockPos = gk::Vector3i{bx, by, bz};
std::string name;
u16 amount;
u8 x, y;
while (!packet.endOfPacket()) {
packet >> name >> amount >> x >> y;
inventory.setStack(x, y, name, amount);
setStack(x, y, name, amount);
}
return packet;
}

View File

@ -23,17 +23,13 @@ Item::Item(u32 id, const TilesDef &tiles, const std::string &name, const std::st
m_label = label;
}
void Item::serialize(sf::Packet &packet) {
void Item::serialize(sf::Packet &packet) const {
packet << m_id << m_name << m_label << m_isBlock << m_isFuel
<< m_burnTime << m_miningSpeed << m_harvestCapability;
m_tiles.serialize(packet);
<< m_burnTime << m_miningSpeed << m_harvestCapability << m_tiles;
}
void Item::deserialize(sf::Packet &packet) {
packet >> m_id >> m_name >> m_label >> m_isBlock >> m_isFuel
>> m_burnTime >> m_miningSpeed >> m_harvestCapability;
m_tiles.deserialize(packet);
>> m_burnTime >> m_miningSpeed >> m_harvestCapability >> m_tiles;
}

View File

@ -17,7 +17,7 @@ SmeltingRecipe::SmeltingRecipe(const ItemStack &input, const ItemStack &output)
m_input = input;
}
void SmeltingRecipe::serialize(sf::Packet &packet) {
void SmeltingRecipe::serialize(sf::Packet &packet) const {
packet << m_result << m_input;
}

View File

@ -0,0 +1,25 @@
/*
* =====================================================================================
*
* Filename: ISerializable.cpp
*
* Description:
*
* Created: 31/01/2020 14:36:28
*
* Author: Quentin Bazin, <quent42340@gmail.com>
*
* =====================================================================================
*/
#include "ISerializable.hpp"
sf::Packet &operator<<(sf::Packet &packet, const ISerializable &s) {
s.serialize(packet);
return packet;
}
sf::Packet &operator>>(sf::Packet &packet, ISerializable &s) {
s.deserialize(packet);
return packet;
}

View File

@ -30,11 +30,9 @@ Block::Block(u32 id, const TilesDef &tiles, const std::string &name, const std::
m_itemDropAmount = 1;
}
void Block::serialize(sf::Packet &packet) {
void Block::serialize(sf::Packet &packet) const {
packet << u32(m_id) << m_name << m_label << u8(m_drawType)
<< m_hardness << m_harvestRequirements << m_itemDrop << m_itemDropAmount;
m_tiles.serialize(packet);
<< m_hardness << m_harvestRequirements << m_itemDrop << m_itemDropAmount << m_tiles;
}
void Block::deserialize(sf::Packet &packet) {
@ -42,9 +40,7 @@ void Block::deserialize(sf::Packet &packet) {
u8 drawType;
packet >> id >> m_name >> m_label >> drawType >> m_hardness
>> m_harvestRequirements >> m_itemDrop >> m_itemDropAmount;
m_tiles.deserialize(packet);
>> m_harvestRequirements >> m_itemDrop >> m_itemDropAmount >> m_tiles;
m_id = id;
m_drawType = BlockDrawType(drawType);

View File

@ -82,10 +82,10 @@ void Chunk::setBlock(int x, int y, int z, u16 type) {
gk::Vector3i pos{x, y, z};
gk::Vector3i absolutePos{x + m_x * CHUNK_WIDTH, y + m_y * CHUNK_HEIGHT, z + m_z * CHUNK_DEPTH};
if (type == BlockType::Workbench) {
m_blockData.emplace(pos, BlockData{absolutePos, 3, 3});
m_blockData.emplace(pos, new BlockData{absolutePos, 3, 3});
}
else if (type == BlockType::Furnace) {
m_blockData.emplace(pos, BlockData{absolutePos, 3, 1});
m_blockData.emplace(pos, new BlockData{absolutePos, 3, 1});
}
if (m_data[x][y][z] == BlockType::Workbench || m_data[x][y][z] == BlockType::Furnace) {
@ -136,10 +136,10 @@ void Chunk::setBlockRaw(int x, int y, int z, u16 type) {
gk::Vector3i pos{x, y, z};
gk::Vector3i absolutePos{x + m_x * CHUNK_WIDTH, y + m_y * CHUNK_HEIGHT, z + m_z * CHUNK_DEPTH};
if (type == BlockType::Workbench) {
m_blockData.emplace(pos, BlockData{absolutePos, 3, 3});
m_blockData.emplace(pos, new BlockData{absolutePos, 3, 3});
}
else if (type == BlockType::Furnace)
m_blockData.emplace(pos, BlockData{absolutePos, 3, 1});
m_blockData.emplace(pos, new BlockData{absolutePos, 3, 1});
if (m_data[x][y][z] == BlockType::Workbench || m_data[x][y][z] == BlockType::Furnace) {
auto it = m_blockData.find(pos);
@ -152,7 +152,7 @@ void Chunk::setBlockRaw(int x, int y, int z, u16 type) {
m_hasChanged = true;
}
BlockData *Chunk::getBlockData(int x, int y, int z) {
BlockData *Chunk::getBlockData(int x, int y, int z) const {
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;
@ -164,7 +164,7 @@ BlockData *Chunk::getBlockData(int x, int y, int z) {
if (it == m_blockData.end())
return nullptr;
return &it->second;
return it->second.get();
}
bool Chunk::areAllNeighboursLoaded() const {

View File

@ -14,7 +14,7 @@
#include "Network.hpp"
#include "Player.hpp"
void Player::serialize(sf::Packet &packet) {
void Player::serialize(sf::Packet &packet) const {
packet << m_x << m_y << m_z << m_inventory;
}

View File

@ -2,6 +2,7 @@ mod:block {
id = "furnace",
name = "Furnace",
tiles = {"furnace_top.png", "furnace_top.png", "furnace_front.png", "furnace_side.png"},
alt_tiles = {"", "", "furnace_front_on.png", ""},
on_block_activated = function(pos, player, world, client)
local gui = LuaGUI.new()
@ -44,7 +45,8 @@ mod:block {
data.inventory:set_stack(2, 0, fuel_stack:item():name(), fuel_stack:amount() - 1)
ticks_remaining = fuel_stack:item():burn_time()
current_burn_time = fuel_stack:item():burn_time()
world:set_data(pos.x, pos.y, pos.z, 1)
data.useAltTiles = true;
-- world:set_data(pos.x, pos.y, pos.z, 1)
elseif ticks_remaining > 0 then
ticks_remaining = ticks_remaining - 1
@ -56,7 +58,8 @@ mod:block {
end
elseif ticks_remaining == 0 then
current_burn_time = 0
world:set_data(pos.x, pos.y, pos.z, 0)
data.useAltTiles = false;
-- world:set_data(pos.x, pos.y, pos.z, 0)
end
if item_progress >= 200 and recipe then

View File

@ -21,12 +21,7 @@
void LuaMod::registerBlock(const sol::table &table) {
TilesDef tiles;
if (table["tiles"].get_type() == sol::type::table) {
sol::as_table_t<std::vector<std::string>> t = table["tiles"];
tiles.textureFilenames = t.source;
}
else
tiles.textureFilenames.emplace_back(table["tiles"].get<std::string>());
tiles.loadFromLuaTable(table);
std::string id = m_id + ":" + table["id"].get<std::string>();
std::string name = table["name"].get<std::string>();
@ -56,12 +51,7 @@ void LuaMod::registerBlock(const sol::table &table) {
void LuaMod::registerItem(const sol::table &table) {
TilesDef tiles;
if (table["tiles"].get_type() == sol::type::table) {
sol::as_table_t<std::vector<std::string>> t = table["tiles"];
tiles.textureFilenames = t.source;
}
else
tiles.textureFilenames.emplace_back(table["tiles"].get<std::string>());
tiles.loadFromLuaTable(table);
std::string id = table["id"].get<std::string>();
std::string name = table["name"].get<std::string>();

View File

@ -60,7 +60,8 @@ void ScriptEngine::initUsertypes() {
m_lua.new_usertype<BlockData>("BlockData",
"inventory", &BlockData::inventory,
"data", &BlockData::data
"data", &BlockData::data,
"useAltTiles", &BlockData::useAltTiles
);
m_lua.new_usertype<Player>("Player",