From f4cc413f61747de28f32c1af7df13721deb8d2cc Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 9 Mar 2024 03:36:08 +0300 Subject: [PATCH] block materials loading --- res/content/base/block_materials/grass.json | 3 + res/content/base/block_materials/stone.json | 3 + res/content/base/block_materials/wood.json | 3 + src/assets/AssetsLoader.cpp | 20 +++++-- src/assets/AssetsLoader.h | 2 + src/content/Content.cpp | 27 ++++++++- src/content/Content.h | 12 +++- src/content/ContentLoader.cpp | 18 ++++++ src/content/ContentLoader.h | 12 ++-- src/frontend/LevelFrontend.cpp | 20 ++++--- src/voxels/Block.h | 64 +++++++++++++++------ 11 files changed, 144 insertions(+), 40 deletions(-) create mode 100644 res/content/base/block_materials/grass.json create mode 100644 res/content/base/block_materials/stone.json create mode 100644 res/content/base/block_materials/wood.json diff --git a/res/content/base/block_materials/grass.json b/res/content/base/block_materials/grass.json new file mode 100644 index 00000000..ed16063e --- /dev/null +++ b/res/content/base/block_materials/grass.json @@ -0,0 +1,3 @@ +{ + "steps-sound": "steps/grass" +} diff --git a/res/content/base/block_materials/stone.json b/res/content/base/block_materials/stone.json new file mode 100644 index 00000000..2d9d5a91 --- /dev/null +++ b/res/content/base/block_materials/stone.json @@ -0,0 +1,3 @@ +{ + "steps-sound": "steps/stone" +} diff --git a/res/content/base/block_materials/wood.json b/res/content/base/block_materials/wood.json new file mode 100644 index 00000000..9c6839e2 --- /dev/null +++ b/res/content/base/block_materials/wood.json @@ -0,0 +1,3 @@ +{ + "steps-sound": "steps/wood" +} diff --git a/src/assets/AssetsLoader.cpp b/src/assets/AssetsLoader.cpp index 74b3d41d..615df567 100644 --- a/src/assets/AssetsLoader.cpp +++ b/src/assets/AssetsLoader.cpp @@ -61,6 +61,14 @@ void addLayouts(int env, const std::string& prefix, const fs::path& folder, Asse } } +void AssetsLoader::tryAddSound(std::string name) { + if (name.empty()) { + return; + } + fs::path file = SOUNDS_FOLDER"/"+name+".ogg"; + add(ASSET_SOUND, file, name); +} + void AssetsLoader::addDefaults(AssetsLoader& loader, const Content* content) { loader.add(ASSET_FONT, FONTS_FOLDER"/font", "normal"); loader.add(ASSET_SHADER, SHADERS_FOLDER"/ui", "ui"); @@ -81,12 +89,12 @@ void AssetsLoader::addDefaults(AssetsLoader& loader, const Content* content) { loader.add(ASSET_TEXTURE, TEXTURES_FOLDER"/misc/sun.png", "misc/sun"); loader.add(ASSET_TEXTURE, TEXTURES_FOLDER"/gui/crosshair.png", "gui/crosshair"); - // (test code) - // TODO: remove - loader.add(ASSET_SOUND, SOUNDS_FOLDER"/steps/grass.ogg", "steps/grass"); - loader.add(ASSET_SOUND, SOUNDS_FOLDER"/steps/stone.ogg", "steps/stone"); - loader.add(ASSET_SOUND, SOUNDS_FOLDER"/steps/wood.ogg", "steps/wood"); - loader.add(ASSET_SOUND, SOUNDS_FOLDER"/steps/ground.ogg", "steps/ground"); + for (auto& entry : content->getBlockMaterials()) { + auto& material = entry.second; + loader.tryAddSound(material.stepsSound); + loader.tryAddSound(material.placeSound); + loader.tryAddSound(material.breakSound); + } addLayouts(0, "core", loader.getPaths()->getMainRoot()/fs::path("layouts"), loader); for (auto& entry : content->getPacks()) { diff --git a/src/assets/AssetsLoader.h b/src/assets/AssetsLoader.h index 736216ff..2c277418 100644 --- a/src/assets/AssetsLoader.h +++ b/src/assets/AssetsLoader.h @@ -49,6 +49,8 @@ class AssetsLoader { std::map loaders; std::queue entries; const ResPaths* paths; + + void tryAddSound(std::string name); public: AssetsLoader(Assets* assets, const ResPaths* paths); void addLoader(int tag, aloader_func func); diff --git a/src/content/Content.cpp b/src/content/Content.cpp index 7c6ecac1..2652a4a5 100644 --- a/src/content/Content.cpp +++ b/src/content/Content.cpp @@ -28,6 +28,10 @@ void ContentBuilder::add(ContentPackRuntime* pack) { packs.emplace(pack->getId(), pack); } +void ContentBuilder::add(BlockMaterial material) { + blockMaterials.emplace(material.name, material); +} + Block& ContentBuilder::createBlock(std::string id) { auto found = blockDefs.find(id); if (found != blockDefs.end()) { @@ -109,7 +113,12 @@ Content* ContentBuilder::build() { auto indices = new ContentIndices(blockDefsIndices, itemDefsIndices); auto content = std::make_unique( - indices, std::move(groups), blockDefs, itemDefs, std::move(packs) + indices, + std::move(groups), + blockDefs, + itemDefs, + std::move(packs), + std::move(blockMaterials) ); // Now, it's time to resolve foreign keys @@ -136,11 +145,13 @@ Content::Content( std::unique_ptr drawGroups, std::unordered_map blockDefs, std::unordered_map itemDefs, - std::unordered_map> packs + std::unordered_map> packs, + std::unordered_map blockMaterials ) : blockDefs(blockDefs), itemDefs(itemDefs), indices(indices), packs(std::move(packs)), + blockMaterials(std::move(blockMaterials)), drawGroups(std::move(drawGroups)) {} @@ -178,6 +189,14 @@ ItemDef& Content::requireItem(std::string id) const { return *found->second; } +const BlockMaterial* Content::findBlockMaterial(std::string id) const { + auto found = blockMaterials.find(id); + if (found == blockMaterials.end()) { + return nullptr; + } + return &found->second; +} + const ContentPackRuntime* Content::getPackRuntime(std::string id) const { auto found = packs.find(id); if (found == packs.end()) { @@ -186,6 +205,10 @@ const ContentPackRuntime* Content::getPackRuntime(std::string id) const { return found->second.get(); } +const std::unordered_map& Content::getBlockMaterials() const { + return blockMaterials; +} + const std::unordered_map>& Content::getPacks() const { return packs; } diff --git a/src/content/Content.h b/src/content/Content.h index 9f201fa9..1f921010 100644 --- a/src/content/Content.h +++ b/src/content/Content.h @@ -8,10 +8,10 @@ #include #include #include "../typedefs.h" +#include "../voxels/Block.h" using DrawGroups = std::set; -class Block; class ItemDef; class Content; class ContentPackRuntime; @@ -48,6 +48,8 @@ class ContentBuilder { std::unordered_map itemDefs; std::vector itemIds; + std::unordered_map blockMaterials; + std::unordered_map> packs; public: ~ContentBuilder(); @@ -55,6 +57,7 @@ public: void add(Block* def); void add(ItemDef* def); void add(ContentPackRuntime* pack); + void add(BlockMaterial material); Block& createBlock(std::string id); ItemDef& createItem(std::string id); @@ -111,6 +114,7 @@ class Content { std::unordered_map itemDefs; std::unique_ptr indices; std::unordered_map> packs; + std::unordered_map blockMaterials; public: std::unique_ptr const drawGroups; @@ -119,7 +123,8 @@ public: std::unique_ptr drawGroups, std::unordered_map blockDefs, std::unordered_map itemDefs, - std::unordered_map> packs + std::unordered_map> packs, + std::unordered_map blockMaterials ); ~Content(); @@ -133,8 +138,11 @@ public: ItemDef* findItem(std::string id) const; ItemDef& requireItem(std::string id) const; + const BlockMaterial* findBlockMaterial(std::string id) const; + const ContentPackRuntime* getPackRuntime(std::string id) const; + const std::unordered_map& getBlockMaterials() const; const std::unordered_map>& getPacks() const; }; diff --git a/src/content/ContentLoader.cpp b/src/content/ContentLoader.cpp index eccedf16..146cb695 100644 --- a/src/content/ContentLoader.cpp +++ b/src/content/ContentLoader.cpp @@ -303,6 +303,15 @@ void ContentLoader::loadItem(ItemDef& def, std::string full, std::string name) { } } +BlockMaterial ContentLoader::loadBlockMaterial(fs::path file, std::string full) { + auto root = files::read_json(file); + BlockMaterial material {full}; + root->str("steps-sound", material.stepsSound); + root->str("place-sound", material.placeSound); + root->str("break-sound", material.breakSound); + return material; +} + void ContentLoader::load(ContentBuilder& builder) { std::cout << "-- loading pack [" << pack->id << "]" << std::endl; @@ -363,4 +372,13 @@ void ContentLoader::load(ContentBuilder& builder) { stats.totalItems++; } } + + fs::path materialsDir = folder / fs::u8path("block_materials"); + if (fs::is_directory(materialsDir)) { + for (auto entry : fs::directory_iterator(materialsDir)) { + fs::path file = entry.path(); + std::string name = pack->id+":"+file.stem().u8string(); + builder.add(loadBlockMaterial(file, name)); + } + } } diff --git a/src/content/ContentLoader.h b/src/content/ContentLoader.h index 2606e71d..b176b861 100644 --- a/src/content/ContentLoader.h +++ b/src/content/ContentLoader.h @@ -1,12 +1,13 @@ #ifndef CONTENT_CONTENT_LOADER_H_ #define CONTENT_CONTENT_LOADER_H_ +#include "../voxels/Block.h" + #include #include namespace fs = std::filesystem; -class Block; class ItemDef; struct ContentPack; class ContentBuilder; @@ -22,12 +23,15 @@ class ContentLoader { void loadBlock(Block& def, std::string full, std::string name); void loadCustomBlockModel(Block& def, dynamic::Map* primitives); void loadItem(ItemDef& def, std::string full, std::string name); + BlockMaterial loadBlockMaterial(fs::path file, std::string full); public: ContentLoader(ContentPack* pack); - bool fixPackIndices(std::filesystem::path folder, - dynamic::Map* indicesRoot, - std::string contentSection); + bool fixPackIndices( + fs::path folder, + dynamic::Map* indicesRoot, + std::string contentSection + ); void fixPackIndices(); void loadBlock(Block& def, std::string name, fs::path file); void loadItem(ItemDef& def, std::string name, fs::path file); diff --git a/src/frontend/LevelFrontend.cpp b/src/frontend/LevelFrontend.cpp index c406ebce..707699a3 100644 --- a/src/frontend/LevelFrontend.cpp +++ b/src/frontend/LevelFrontend.cpp @@ -8,16 +8,17 @@ #include "../voxels/Block.h" #include "../assets/Assets.h" #include "../graphics/Atlas.h" +#include "../content/Content.h" #include "../logic/LevelController.h" #include "../logic/PlayerController.h" LevelFrontend::LevelFrontend(Level* level, Assets* assets) -: level(level), - assets(assets), - contentCache(std::make_unique(level->content, assets)), - blocksAtlas(BlocksPreview::build(contentCache.get(), assets, level->content)) { -} + : level(level), + assets(assets), + contentCache(std::make_unique(level->content, assets)), + blocksAtlas(BlocksPreview::build(contentCache.get(), assets, level->content)) +{} void LevelFrontend::observe(LevelController* controller) { controller->getPlayerController()->listenBlockInteraction( @@ -25,9 +26,12 @@ void LevelFrontend::observe(LevelController* controller) { if (type != BlockInteraction::step) { return; } - // (test code) - // TODO: replace with BlockMaterial properties access - auto sound = assets->getSound("steps/"+def->material.substr(def->material.find(':')+1)); + auto material = level->content->findBlockMaterial(def->material); + if (material == nullptr) { + return; + } + + auto sound = assets->getSound(material->stepsSound); audio::play( sound, glm::vec3(), diff --git a/src/voxels/Block.h b/src/voxels/Block.h index 698d29d9..a3ee44d3 100644 --- a/src/voxels/Block.h +++ b/src/voxels/Block.h @@ -18,6 +18,8 @@ inline constexpr uint FACE_PY = 3; inline constexpr uint FACE_MZ = 4; inline constexpr uint FACE_PZ = 5; +/// @brief Grid size used for physics solver collision checking with +/// complex hitboxes inline constexpr uint BLOCK_AABB_GRID = 16; inline std::string DEFAULT_MATERIAL = "base:stone"; @@ -37,7 +39,7 @@ struct CoordSystem { glm::ivec3 axisY; glm::ivec3 axisZ; - // Grid 3d position fix offset (for negative vectors) + /// @brief Grid 3d position fix offset (for negative vectors) glm::ivec3 fix; CoordSystem() = default; @@ -57,6 +59,7 @@ struct BlockRotProfile { /// @brief Wood logs, pillars, pipes static const BlockRotProfile PIPE; + /// @brief Doors, signs and other panes static const BlockRotProfile PANE; }; @@ -80,9 +83,9 @@ using BoxModel = AABB; /// @brief Common kit of block properties applied to groups of blocks struct BlockMaterial { std::string name; - std::string stepsSound; - std::string placeSound; - std::string breakSound; + std::string stepsSound {""}; + std::string placeSound {""}; + std::string breakSound {""}; }; /// @brief Block properties definition @@ -90,7 +93,8 @@ class Block { public: /// @brief Block string id (with prefix included) std::string const name; - /// @brief Textures set applied to block sides + + /// @brief Textures set applied to block sides std::string textureFaces[6]; // -x,x, -y,y, -z,z std::vector modelTextures = {}; @@ -98,57 +102,81 @@ public: std::vector modelExtraPoints = {}; //initially made for tetragons std::vector modelUVs = {}; // boxes' tex-UVs also there + /// @brief id of used BlockMaterial, may specify non-existing material std::string material = DEFAULT_MATERIAL; /// @brief Light emission R, G, B, S (sky lights: sun, moon, radioactive clouds) uint8_t emission[4] {0, 0, 0, 0}; + /// @brief Influences visible block sides for transparent blocks uint8_t drawGroup = 0; - /// @brief Block model type + + /// @brief Block model type BlockModel model = BlockModel::block; - /// @brief Does the block passing lights into itself + + /// @brief Does the block passing lights into itself bool lightPassing = false; - /// @brief Does the block passing top-down sky lights into itself + + /// @brief Does the block passing top-down sky lights into itself bool skyLightPassing = false; - /// @brief Is the block a physical obstacle + + /// @brief Is the block a physical obstacle bool obstacle = true; - /// @brief Can the block be selected + + /// @brief Can the block be selected bool selectable = true; - /// @brief Can the block be replaced with other. + + /// @brief Can the block be replaced with other. /// Examples of replaceable blocks: air, flower, water bool replaceable = false; - /// @brief Can player destroy the block + + /// @brief Can player destroy the block bool breakable = true; - /// @brief Can the block be oriented different ways + + /// @brief Can the block be oriented different ways bool rotatable = false; + /// @brief Can the block exist without physical support be a solid block below bool grounded = false; + /// @brief Turns off block item generation bool hidden = false; + /// @brief Set of block physical hitboxes std::vector hitboxes; - /// @brief Set of available block rotations (coord-systems) + + /// @brief Set of available block rotations (coord-systems) BlockRotProfile rotations; + /// @brief Item will be picked on MMB click on the block std::string pickingItem = name+BLOCK_ITEM_SUFFIX; + /// @brief Block script name in blocks/ without extension std::string scriptName = name.substr(name.find(':')+1); - /// @brief Default block layout will be used by hud.open_block(...) + + /// @brief Default block layout will be used by hud.open_block(...) std::string uiLayout = name; + /// @brief Block inventory size. 0 - no inventory uint inventorySize = 0; + /// @brief Runtime indices (content indexing results) struct { /// @brief block runtime integer id blockid_t id; - /// @brief is the block completely opaque for render and raycast + + /// @brief is the block completely opaque for render and raycast bool solid = true; - /// @brief does the block emit any lights + + /// @brief does the block emit any lights bool emissive = false; + /// @brief set of hitboxes sets with all coord-systems precalculated std::vector hitboxes[BlockRotProfile::MAX_COUNT]; - /// @brief set of block callbacks flags + + /// @brief set of block callbacks flags block_funcs_set funcsset {}; + /// @brief picking item integer id itemid_t pickingItem = 0; } rt;