summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/AssetManager.cpp113
-rw-r--r--src/AssetManager.hpp22
-rw-r--r--src/Block.cpp35
-rw-r--r--src/Block.hpp6
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<std::string, BlockId> assetIds;
std::map<BlockId, std::string> blockIdToBlockName;
std::unique_ptr<AssetTreeNode> assetTree;
std::unique_ptr<TextureAtlas> atlas;
+std::map<BlockId, const BlockModel *> 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<unsigned char>());
}
+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<std::string>();
+ if (it.count("x"))
+ model.x = it["x"].get<int>();
+ if (it.count("y"))
+ model.y = it["y"].get<int>();
+ if (it.count("uvlock"))
+ model.uvLock = it["uvlock"].get<int>();
+ if (it.count("weight"))
+ model.weight = it["weight"].get<int>();
+ variant.models.push_back(model);
+ }
+ } else {
+ BlockStateVariant::Model model;
+ model.modelName = variantIt.value()["model"].get<std::string>();
+ if (variantIt.value().count("x"))
+ model.x = variantIt.value()["x"].get<int>();
+ if (variantIt.value().count("y"))
+ model.y = variantIt.value()["y"].get<int>();
+ if (variantIt.value().count("uvlock"))
+ model.uvLock = variantIt.value()["uvlock"].get<int>();
+ if (variantIt.value().count("weight"))
+ model.weight = variantIt.value()["weight"].get<int>();
+ variant.models.push_back(model);
+ }
+ blockState.variants[variant.variantName] = variant;
+ }
+
+ node.asset = std::make_unique<AssetBlockState>();
+ AssetBlockState *asset = dynamic_cast<AssetBlockState*>(node.asset.get());
+ asset->blockState = blockState;
+
+ node.data.swap(std::vector<unsigned char>());
+}
+
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<AssetBlockState>("/minecraft/blockstates/" + blockStateName.first);
+ if (!asset)
+ return &GetAsset<AssetBlockModel>("/minecraft/models/block/error")->blockModel;
+
+ BlockState &blockState = asset->blockState;
+ if (blockState.variants.find(blockStateName.second) == blockState.variants.end())
+ return &GetAsset<AssetBlockModel>("/minecraft/models/block/error")->blockModel;
+
+ BlockStateVariant &variant = blockState.variants[blockStateName.second];
+ if (variant.models.empty())
+ return &GetAsset<AssetBlockModel>("/minecraft/models/block/error")->blockModel;
+
+ BlockStateVariant::Model &model = variant.models[0];
+ AssetBlockModel *assetModel = GetAsset<AssetBlockModel>("/minecraft/models/block/" + model.modelName);
+ if (!assetModel)
+ return &GetAsset<AssetBlockModel>("/minecraft/models/block/error")->blockModel;
- std::string blockName = blockIdToBlockName[block];
+ blockIdToBlockModel.insert(std::make_pair(block, &assetModel->blockModel));
- AssetBlockModel *model = GetAsset<AssetBlockModel>("/minecraft/models/" + blockName);
- return (model == nullptr) ? &GetAsset<AssetBlockModel>("/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<ParsedFace> 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<Model> models;
+};
+
+struct BlockState {
+ std::map<std::string, BlockStateVariant> 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<unsigned char> 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 <string>
+
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<std::string, std::string> TransformBlockIdToBlockStateName(BlockId blockId) {
+ switch (blockId.id) {
+ case 1: {
+ if (blockId.state > 6)
+ break;
+ static const std::pair<std::string, std::string> ids[] = {
+ std::pair<std::string,std::string>("stone", "normal"),
+ std::pair<std::string,std::string>("granite", "normal"),
+ std::pair<std::string,std::string>("smooth_granite", "normal"),
+ std::pair<std::string,std::string>("diorite", "normal"),
+ std::pair<std::string,std::string>("smooth_diorite", "normal"),
+ std::pair<std::string,std::string>("andesite", "normal"),
+ std::pair<std::string,std::string>("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 <functional>
+#include <utility>
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<std::string, std::string> TransformBlockIdToBlockStateName(BlockId blockId); \ No newline at end of file