From 55b5e60b189490c33b415e3c956800da21064e3b Mon Sep 17 00:00:00 2001 From: LaG1924 <12997935+LaG1924@users.noreply.github.com> Date: Wed, 8 Aug 2018 07:30:01 +0500 Subject: Basic BlockState support --- src/AssetManager.cpp | 113 ++++++++++++++++++++++++++++++++++++--------------- src/AssetManager.hpp | 22 ++++++++++ src/Block.cpp | 35 +++++++++++++++- src/Block.hpp | 6 ++- 4 files changed, 140 insertions(+), 36 deletions(-) diff --git a/src/AssetManager.cpp b/src/AssetManager.cpp index aaa71ed..9671491 100644 --- a/src/AssetManager.cpp +++ b/src/AssetManager.cpp @@ -20,6 +20,7 @@ std::map assetIds; std::map blockIdToBlockName; std::unique_ptr assetTree; std::unique_ptr atlas; +std::map blockIdToBlockModel; void LoadIds(); void LoadAssets(); @@ -29,6 +30,7 @@ void WalkDirEntry(const fs::directory_entry &dirEntry, AssetTreeNode *node); void ParseAsset(AssetTreeNode &node); void ParseAssetTexture(AssetTreeNode &node); void ParseAssetBlockModel(AssetTreeNode &node); +void ParseAssetBlockState(AssetTreeNode &node); void ParseBlockModels(); @@ -118,6 +120,11 @@ void ParseAsset(AssetTreeNode &node) { return; } + if (node.parent->name == "blockstates") { + ParseAssetBlockState(node); + return; + } + if (node.data[0] == 0x89 && node.data[1] == 'P' && node.data[2] == 'N' && node.data[3] == 'G') { ParseAssetTexture(node); return; @@ -181,7 +188,7 @@ void ParseAssetBlockModel(AssetTreeNode &node) { model.BlockName = node.name; - if (model.BlockName == "block") + if (model.BlockName == "block" || model.BlockName == "cube_mirrored") model.IsBlock = true; if (model.BlockName == "thin_block" || model.BlockName == "leaves") @@ -291,6 +298,55 @@ void ParseAssetBlockModel(AssetTreeNode &node) { node.data.swap(std::vector()); } +void ParseAssetBlockState(AssetTreeNode &node) { + nlohmann::json j = nlohmann::json::parse(node.data); + + BlockState blockState; + if (j.find("multipart") != j.end()) + return; + + j = j["variants"]; + for (auto variantIt = j.begin(); variantIt != j.end(); variantIt++) { + std::string variantName = variantIt.key(); + BlockStateVariant variant; + variant.variantName = variantName; + if (variantIt.value().is_array()) { + for (auto &it : variantIt.value()) { + BlockStateVariant::Model model; + model.modelName = it["model"].get(); + if (it.count("x")) + model.x = it["x"].get(); + if (it.count("y")) + model.y = it["y"].get(); + if (it.count("uvlock")) + model.uvLock = it["uvlock"].get(); + if (it.count("weight")) + model.weight = it["weight"].get(); + variant.models.push_back(model); + } + } else { + BlockStateVariant::Model model; + model.modelName = variantIt.value()["model"].get(); + if (variantIt.value().count("x")) + model.x = variantIt.value()["x"].get(); + if (variantIt.value().count("y")) + model.y = variantIt.value()["y"].get(); + if (variantIt.value().count("uvlock")) + model.uvLock = variantIt.value()["uvlock"].get(); + if (variantIt.value().count("weight")) + model.weight = variantIt.value()["weight"].get(); + variant.models.push_back(model); + } + blockState.variants[variant.variantName] = variant; + } + + node.asset = std::make_unique(); + AssetBlockState *asset = dynamic_cast(node.asset.get()); + asset->blockState = blockState; + + node.data.swap(std::vector()); +} + void ParseBlockModels() { std::string textureName; @@ -448,40 +504,31 @@ void ParseBlockModels() { } const BlockModel *AssetManager::GetBlockModelByBlockId(BlockId block) { - block.state = 0; - if (blockIdToBlockName.find(block) == blockIdToBlockName.end()) { - std::string blockName = ""; - for (const auto& it : assetIds) { - if (BlockId{ it.second.id,0 } == block) { - blockName = it.first; - break; - } - } - if (blockName == "grass") - blockName = "grass_normal"; - if (blockName == "torch") - blockName = "normal_torch"; - if (blockName == "leaves") - blockName = "oak_leaves"; - if (blockName == "tallgrass") - blockName = "tall_grass"; - if (blockName == "log") - blockName = "oak_bark"; - if (blockName == "snow_layer") - blockName = "snow_height2"; - - blockName = "block/" + blockName; - - if (blockName == "") - return nullptr; - - blockIdToBlockName[block] = blockName; - } + auto it = blockIdToBlockModel.find(block); + if (it != blockIdToBlockModel.end()) + return it->second; + + auto blockStateName = TransformBlockIdToBlockStateName(block); + AssetBlockState *asset = GetAsset("/minecraft/blockstates/" + blockStateName.first); + if (!asset) + return &GetAsset("/minecraft/models/block/error")->blockModel; + + BlockState &blockState = asset->blockState; + if (blockState.variants.find(blockStateName.second) == blockState.variants.end()) + return &GetAsset("/minecraft/models/block/error")->blockModel; + + BlockStateVariant &variant = blockState.variants[blockStateName.second]; + if (variant.models.empty()) + return &GetAsset("/minecraft/models/block/error")->blockModel; + + BlockStateVariant::Model &model = variant.models[0]; + AssetBlockModel *assetModel = GetAsset("/minecraft/models/block/" + model.modelName); + if (!assetModel) + return &GetAsset("/minecraft/models/block/error")->blockModel; - std::string blockName = blockIdToBlockName[block]; + blockIdToBlockModel.insert(std::make_pair(block, &assetModel->blockModel)); - AssetBlockModel *model = GetAsset("/minecraft/models/" + blockName); - return (model == nullptr) ? &GetAsset("/minecraft/models/block/error")->blockModel : &model->blockModel; + return &assetModel->blockModel; } std::string AssetManager::GetAssetNameByBlockId(BlockId block) { diff --git a/src/AssetManager.hpp b/src/AssetManager.hpp index 2940b5f..f3d0718 100644 --- a/src/AssetManager.hpp +++ b/src/AssetManager.hpp @@ -92,6 +92,24 @@ struct BlockModel { std::vector parsedFaces; }; +struct BlockStateVariant { + std::string variantName; + + struct Model { + std::string modelName; + int x = 0; + int y = 0; + bool uvLock = false; + int weight = 1; + }; + + std::vector models; +}; + +struct BlockState { + std::map variants; +}; + inline bool operator==(const BlockModel::ElementData::FaceData::Uv &lhs, const BlockModel::ElementData::FaceData::Uv &rhs) { return lhs.x1 == rhs.x1 && lhs.y1 == rhs.y1 && lhs.x2 == rhs.x2 && lhs.y2 == rhs.y2; @@ -113,6 +131,10 @@ struct AssetBlockModel : Asset { BlockModel blockModel; }; +struct AssetBlockState : Asset { + BlockState blockState; +}; + struct AssetTexture : Asset { std::vector textureData; unsigned int realWidth, realHeight; diff --git a/src/Block.cpp b/src/Block.cpp index 303909b..98f1b0a 100644 --- a/src/Block.cpp +++ b/src/Block.cpp @@ -1,5 +1,7 @@ #include "Block.hpp" +#include + Block::~Block() {} Block::Block(unsigned short id, unsigned char state, @@ -13,5 +15,34 @@ bool operator==(const BlockId& lhs, const BlockId &rhs) { } bool operator<(const BlockId& lhs, const BlockId &rhs) { - return (lhs.id < rhs.id); -} \ No newline at end of file + if (lhs.id < rhs.id) + return true; + return lhs.state < rhs.state; +} + +std::pair TransformBlockIdToBlockStateName(BlockId blockId) { + switch (blockId.id) { + case 1: { + if (blockId.state > 6) + break; + static const std::pair ids[] = { + std::pair("stone", "normal"), + std::pair("granite", "normal"), + std::pair("smooth_granite", "normal"), + std::pair("diorite", "normal"), + std::pair("smooth_diorite", "normal"), + std::pair("andesite", "normal"), + std::pair("smooth_andesite", "normal"), + }; + return ids[blockId.state]; + } + case 2: { + return std::make_pair("grass", "snowy=false"); + } + + default: + break; + } + + return std::make_pair("", ""); +} diff --git a/src/Block.hpp b/src/Block.hpp index cd01f9a..c922adf 100644 --- a/src/Block.hpp +++ b/src/Block.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include struct Block { Block(); @@ -42,4 +43,7 @@ namespace std { return (id & state << 1); } }; -} \ No newline at end of file +} + +//returns name of blockstate and name of variant +std::pair TransformBlockIdToBlockStateName(BlockId blockId); \ No newline at end of file -- cgit v1.2.3