From 872dca633f881852198cf4ba56d78dae29ef72d2 Mon Sep 17 00:00:00 2001 From: EtlamGit Date: Fri, 28 Dec 2018 18:55:10 +0100 Subject: [PATCH] add basic support for block states + refactoring of BlockInfo -> PaletteEntry (to reduce confusion reading the code) + add all available block states to ToolTip in bottom status bar + color of Blocks can now be different depending on single block state (e.g. jungle_log with axis:y) --- blockidentifier.cpp | 81 ++++++++++++++--------------------- blockidentifier.h | 43 ++++++++++--------- chunk.cpp | 28 +++++++++--- chunk.h | 8 ++-- dimensionidentifier.cpp | 1 + flatteningconverter.cpp | 2 +- flatteningconverter.h | 6 +-- mapview.cpp | 46 ++++++++++++-------- minutor.h | 1 - minutor.pro | 2 +- blockdata.h => paletteentry.h | 8 ++-- 11 files changed, 120 insertions(+), 106 deletions(-) rename blockdata.h => paletteentry.h (66%) diff --git a/blockidentifier.cpp b/blockidentifier.cpp index 067628fd..8bee8ce3 100644 --- a/blockidentifier.cpp +++ b/blockidentifier.cpp @@ -10,18 +10,29 @@ static BlockInfo unknownBlock; -BlockInfo::BlockInfo() : transparent(false), liquid(false), rendernormal(true), - providepower(false), spawninside(false), grass(false), foliage(false) {} +BlockInfo::BlockInfo() + : variants(false) + , transparent(false) + , liquid(false) + , rendernormal(true) + , providepower(false) + , spawninside(false) + , grass(false) + , foliage(false) {} + +bool BlockInfo::hasVariants() const { + return this->variants; +} -bool BlockInfo::isOpaque() { +bool BlockInfo::isOpaque() const { return !(this->transparent); } -bool BlockInfo::isLiquid() { +bool BlockInfo::isLiquid() const { return this->liquid; } -bool BlockInfo::doesBlockHaveSolidTopSurface(int data) { +bool BlockInfo::doesBlockHaveSolidTopSurface(int data) const { if (this->isOpaque() && this->renderAsNormalBlock()) return true; if (this->stairs && ((data & 4) == 4)) return true; if (this->halfslab && ((data & 8) == 8)) return true; @@ -30,22 +41,22 @@ bool BlockInfo::doesBlockHaveSolidTopSurface(int data) { return false; } -bool BlockInfo::doesBlockHaveSolidTopSurface() { +bool BlockInfo::doesBlockHaveSolidTopSurface() const { if (this->isOpaque() && this->renderAsNormalBlock()) return true; if (this->hopper) return true; return false; } -bool BlockInfo::isBlockNormalCube() { +bool BlockInfo::isBlockNormalCube() const { return this->isOpaque() && this->renderAsNormalBlock() && !this->canProvidePower(); } -bool BlockInfo::renderAsNormalBlock() { +bool BlockInfo::renderAsNormalBlock() const { return this->rendernormal; } -bool BlockInfo::canProvidePower() { +bool BlockInfo::canProvidePower() const { return this->providepower; } @@ -105,43 +116,17 @@ BlockIdentifier& BlockIdentifier::Instance() { } BlockInfo &BlockIdentifier::getBlockInfo(uint hid) { - // first apply the mask if (blocks.contains(hid)) { return *blocks[hid]; } - // data &= blocks[name].first()->mask; - // - // quint32 bid = id | (data << 12); - // // first check the cache - // if (cache[bid] != NULL) - // return *cache[bid]; - // - // // now find the variant - // if (blocks.contains(bid)) { - // QList &list = blocks[bid]; - // // run backwards for priority sorting - // for (int i = list.length() - 1; i >= 0; i--) { - // if (list[i]->enabled) { - // cache[bid] = list[i]; - // return *list[i]; - // } - // } - // } - // // no enabled variant found - // if (blocks.contains(id)) { - // QList &list = blocks[id]; - // for (int i = list.length() - 1; i >= 0; i--) { - // if (list[i]->enabled) { - // cache[bid] = list[i]; - // return *list[i]; - // } - // } - // } - // no blocks at all found.. dammit return unknownBlock; } +bool BlockIdentifier::hasBlockInfo(uint hid) { + return blocks.contains(hid); +} + void BlockIdentifier::enableDefinitions(int pack) { if (pack < 0) return; int len = packs[pack].length(); @@ -181,6 +166,7 @@ void BlockIdentifier::parseDefinition(JSONObject *b, BlockInfo *parent, // } // block->id = id; + // name of Block QString name; if (b->has("name")) name = b->at("name")->asString(); @@ -191,6 +177,10 @@ void BlockIdentifier::parseDefinition(JSONObject *b, BlockInfo *parent, block->setName(name); block->enabled = true; + // optional Block State + if (b->has("blockstate")) + block->blockstate = b->at("blockstate")->asString(); + if (b->has("transparent")) { block->transparent = b->at("transparent")->asBool(); block->rendernormal = false; // for most cases except the following @@ -209,6 +199,7 @@ void BlockIdentifier::parseDefinition(JSONObject *b, BlockInfo *parent, block->spawninside = false; } + // generic attributes if (b->has("liquid")) block->liquid = b->at("liquid")->asBool(); else if (parent != NULL) @@ -268,22 +259,16 @@ void BlockIdentifier::parseDefinition(JSONObject *b, BlockInfo *parent, if (b->has("biomeFoliage")) block->setBiomeFoliage( b->at("biomeFoliage")->asBool() ); - // variant reduction mask - if (b->has("mask")) - block->mask = b->at("mask")->asNumber(); - else if (b->has("variants")) - block->mask = 0x0f; - else - block->mask = 0x00; - + // variants due to block_state difference if (b->has("variants")) { + block->variants = true; JSONArray *variants = dynamic_cast(b->at("variants")); int vlen = variants->length(); for (int j = 0; j < vlen; j++) parseDefinition(dynamic_cast(variants->at(j)), block, pack); } - uint hid = qHash(name); + uint hid = qHash(name+block->blockstate); if (blocks.contains(hid)) { // this will only trigger during development of vanilla_blocks.json // and prevents generating a wrong definition file diff --git a/blockidentifier.h b/blockidentifier.h index bc5590e3..0ca3b6b8 100644 --- a/blockidentifier.h +++ b/blockidentifier.h @@ -16,14 +16,16 @@ class BlockInfo { public: BlockInfo(); + bool hasVariants() const; + // special block attribute used during mob spawning detection - bool isOpaque(); - bool isLiquid(); - bool doesBlockHaveSolidTopSurface(int data); - bool doesBlockHaveSolidTopSurface(); - bool isBlockNormalCube(); - bool renderAsNormalBlock(); - bool canProvidePower(); + bool isOpaque() const; + bool isLiquid() const; + bool doesBlockHaveSolidTopSurface(int data) const; + bool doesBlockHaveSolidTopSurface() const; + bool isBlockNormalCube() const; + bool renderAsNormalBlock() const; + bool canProvidePower() const; // special block type used during mob spawning detection bool isBedrock(); @@ -42,20 +44,20 @@ class BlockInfo { void setBiomeFoliage(bool value); const QString &getName(); -// int id; - double alpha; - quint8 mask; - bool enabled; - bool transparent; - bool liquid; - bool rendernormal; - bool providepower; - bool spawninside; - QColor colors[16]; + double alpha; + QString blockstate; + bool variants; // block_state dependant variants + bool enabled; + bool transparent; + bool liquid; + bool rendernormal; + bool providepower; + bool spawninside; + QColor colors[16]; private: QString name; - // cache special blocks used during mob spawning detection + // cache special block attributes used during mob spawning detection bool bedrock; bool hopper; bool stairs; @@ -75,8 +77,9 @@ class BlockIdentifier { void enableDefinitions(int id); void disableDefinitions(int id); BlockInfo &getBlockInfo(uint hid); + bool hasBlockInfo(uint hid); -private: + private: // singleton: prevent access to constructor and copyconstructor BlockIdentifier(); ~BlockIdentifier(); @@ -84,7 +87,7 @@ class BlockIdentifier { BlockIdentifier &operator=(const BlockIdentifier &); void parseDefinition(JSONObject *block, BlockInfo *parent, int pack); - QMap blocks; + QMap blocks; QList > packs; }; diff --git a/chunk.cpp b/chunk.cpp index c06d501a..e640b32e 100644 --- a/chunk.cpp +++ b/chunk.cpp @@ -4,6 +4,7 @@ #include "./chunk.h" #include "./flatteningconverter.h" +#include "./blockidentifier.h" quint16 getBits(const unsigned char *data, int pos, int n) { // quint16 result = 0; @@ -183,17 +184,34 @@ void Chunk::loadSection1343(ChunkSection *cs, const Tag *section) { cs->palette = FlatteningConverter::Instance().getPalette(); } -// Cunk format afer "The Flattening" version 1509 +// Chunk format after "The Flattening" version 1509 void Chunk::loadSection1519(ChunkSection *cs, const Tag *section) { + BlockIdentifier &bi = BlockIdentifier::Instance(); // decode Palette to be able to map BlockStates auto rawPalette = section->at("Palette"); cs->paletteLength = rawPalette->length(); - cs->palette = new BlockData[cs->paletteLength]; + cs->palette = new PaletteEntry[cs->paletteLength]; for (int j = 0; j < rawPalette->length(); j++) { + // get name and hash it to hid cs->palette[j].name = rawPalette->at(j)->at("Name")->toString(); - cs->palette[j].hid = qHash(cs->palette[j].name); + uint hid = qHash(cs->palette[j].name); + // copy all other properties if (rawPalette->at(j)->has("Properties")) cs->palette[j].properties = rawPalette->at(j)->at("Properties")->getData().toMap(); + + // check vor variants + BlockInfo const & block = bi.getBlockInfo(hid); + if (block.hasVariants()) { + // test all available properties + for (auto key : cs->palette[j].properties.keys()) { + QString vname = cs->palette[j].name + key + ":" + cs->palette[j].properties[key].toString(); + uint vhid = qHash(vname); + if (bi.hasBlockInfo(vhid)) + hid = vhid; // use this vaiant instead + } + } + // store hash of found variant + cs->palette[j].hid = hid; } // map BlockStates to BlockData @@ -215,14 +233,14 @@ void Chunk::loadSection1519(ChunkSection *cs, const Tag *section) { } -const BlockData & ChunkSection::getBlockData(int x, int y, int z) { +const PaletteEntry & ChunkSection::getPaletteEntry(int x, int y, int z) { int xoffset = x; int yoffset = (y & 0x0f) << 8; int zoffset = z << 4; return palette[blocks[xoffset + yoffset + zoffset]]; } -const BlockData & ChunkSection::getBlockData(int offset, int y) { +const PaletteEntry & ChunkSection::getPaletteEntry(int offset, int y) { int yoffset = (y & 0x0f) << 8; return palette[blocks[offset + yoffset]]; } diff --git a/chunk.h b/chunk.h index a6ad7c0e..1a0efaea 100644 --- a/chunk.h +++ b/chunk.h @@ -7,20 +7,20 @@ #include "./nbt.h" #include "./entity.h" -#include "./blockdata.h" +#include "./paletteentry.h" #include "./generatedstructure.h" class ChunkSection { public: - const BlockData & getBlockData(int x, int y, int z); - const BlockData & getBlockData(int offset, int y); + const PaletteEntry & getPaletteEntry(int x, int y, int z); + const PaletteEntry & getPaletteEntry(int offset, int y); quint8 getSkyLight(int x, int y, int z); quint8 getSkyLight(int offset, int y); quint8 getBlockLight(int x, int y, int z); quint8 getBlockLight(int offset, int y); - BlockData *palette; + PaletteEntry *palette; int paletteLength; quint16 blocks[16*16*16]; diff --git a/dimensionidentifier.cpp b/dimensionidentifier.cpp index 7c4f330f..722702d0 100644 --- a/dimensionidentifier.cpp +++ b/dimensionidentifier.cpp @@ -23,6 +23,7 @@ class DimensionDef { DimensionIdentifier::DimensionIdentifier() { group = NULL; } + DimensionIdentifier::~DimensionIdentifier() { for (int i = 0; i < packs.length(); i++) { for (int j = 0; j < packs[i].length(); j++) diff --git a/flatteningconverter.cpp b/flatteningconverter.cpp index 423ef9cc..d3e8ae31 100644 --- a/flatteningconverter.cpp +++ b/flatteningconverter.cpp @@ -19,7 +19,7 @@ FlatteningConverter& FlatteningConverter::Instance() { } //const BlockData * FlatteningConverter::getPalette() { -BlockData * FlatteningConverter::getPalette() { +PaletteEntry * FlatteningConverter::getPalette() { return palette; } diff --git a/flatteningconverter.h b/flatteningconverter.h index 203a1785..3d46bece 100644 --- a/flatteningconverter.h +++ b/flatteningconverter.h @@ -2,7 +2,7 @@ #ifndef FLATTENINGCONVERTER_H_ #define FLATTENINGCONVERTER_H_ -#include "./blockdata.h" +#include "./paletteentry.h" class JSONArray; class JSONObject; @@ -17,7 +17,7 @@ class FlatteningConverter { void enableDefinitions(int id); void disableDefinitions(int id); // const BlockData * getPalette(); - BlockData * getPalette(); + PaletteEntry * getPalette(); private: // singleton: prevent access to constructor and copyconstructor @@ -27,7 +27,7 @@ class FlatteningConverter { FlatteningConverter &operator=(const FlatteningConverter &); void parseDefinition(JSONObject *block, int *parentID, int pack); - BlockData palette[16*256]; // 4 bit data + 8 bit ID + PaletteEntry palette[16*256]; // 4 bit data + 8 bit ID // QList > packs; }; diff --git a/mapview.cpp b/mapview.cpp index 4413a306..74026ad4 100644 --- a/mapview.cpp +++ b/mapview.cpp @@ -451,7 +451,7 @@ void MapView::renderChunk(Chunk *chunk) { //int data = section->getData(offset, y); // get BlockInfo from block value - BlockInfo &block = BlockIdentifier::Instance().getBlockInfo(section->getBlockData(offset, y).hid); + BlockInfo &block = BlockIdentifier::Instance().getBlockInfo(section->getPaletteEntry(offset, y).hid); if (block.alpha == 0.0) continue; // get light value from one block above @@ -513,13 +513,13 @@ void MapView::renderChunk(Chunk *chunk) { if (y > 0) sectionB = chunk->sections[(y-1) >> 4]; if (section1) { - blid1 = section1->getBlockData(offset, y+1).hid; + blid1 = section1->getPaletteEntry(offset, y+1).hid; } if (section2) { - blid2 = section2->getBlockData(offset, y+2).hid; + blid2 = section2->getPaletteEntry(offset, y+2).hid; } if (sectionB) { - blidB = sectionB->getBlockData(offset, y-1).hid; + blidB = sectionB->getPaletteEntry(offset, y-1).hid; } BlockInfo &block2 = BlockIdentifier::Instance().getBlockInfo(blid2); BlockInfo &block1 = BlockIdentifier::Instance().getBlockInfo(blid1); @@ -586,7 +586,7 @@ void MapView::renderChunk(Chunk *chunk) { // get data value // int data = section->getData(offset, y); // get BlockInfo from block value - BlockInfo &block = BlockIdentifier::Instance().getBlockInfo(section->getBlockData(offset, y).hid); + BlockInfo &block = BlockIdentifier::Instance().getBlockInfo(section->getPaletteEntry(offset, y).hid); if (block.transparent) { cave_factor -= caveshade[cave_test]; } @@ -613,11 +613,11 @@ void MapView::getToolTip(int x, int z) { int cz = floor(z / 16.0); Chunk *chunk = cache.fetch(cx, cz); int offset = (x & 0xf) + (z & 0xf) * 16; - int id = 0, bd = 0; int y = 0; - QString name = "Unknown"; + QString name = "Unknown"; QString biome = "Unknown Biome"; + QString blockstate; QMap entityIds; if (chunk) { @@ -630,12 +630,20 @@ void MapView::getToolTip(int x, int z) { continue; } // get information about block - const BlockData & bdata = section->getBlockData(offset, y); - name = bdata.name; + const PaletteEntry & pdata = section->getPaletteEntry(offset, y); + name = pdata.name; // in case of fully transparent blocks (meaning air) // -> we continue downwards - auto & block = BlockIdentifier::Instance().getBlockInfo(bdata.hid); + auto & block = BlockIdentifier::Instance().getBlockInfo(pdata.hid); if (block.alpha == 0.0) continue; + // list all Block States + for (auto key : pdata.properties.keys()) { + blockstate += key; + blockstate += ":"; + blockstate += pdata.properties[key].toString(); + blockstate += " "; + } + blockstate.chop(1); break; } auto &bi = BiomeIdentifier::Instance().getBiome(chunk->biomes[(x & 0xf) + (z & 0xf) * 16]); @@ -661,15 +669,15 @@ void MapView::getToolTip(int x, int z) { entityStr = entities.join(", "); } - emit hoverTextChanged(tr("X:%1 Y:%2 Z:%3 - %4 - %5 (%6:%7) %8") - .arg(x) - .arg(y) - .arg(z) - .arg(biome) - .arg(name) - .arg(id) - .arg(bd) - .arg(entityStr)); + QString hovertext = QString("X:%1 Y:%2 Z:%3 - %4 - %5") + .arg(x).arg(y).arg(z) + .arg(biome) + .arg(name); + if (blockstate.length() > 0) + hovertext += " (" + blockstate + ")"; + if (entityStr.length() > 0) + hovertext += " - " + entityStr; + emit hoverTextChanged(hovertext); } void MapView::addStructureFromChunk(QSharedPointer structure) { diff --git a/minutor.h b/minutor.h index ae6b66a7..6a9fce5b 100644 --- a/minutor.h +++ b/minutor.h @@ -115,7 +115,6 @@ private slots: DefinitionManager *dm; Settings *settings; JumpTo *jumpTo; -// DimensionIdentifier *dimensions; QDir currentWorld; QSet overlayItemTypes; diff --git a/minutor.pro b/minutor.pro index 502b9403..6cd859de 100644 --- a/minutor.pro +++ b/minutor.pro @@ -45,7 +45,7 @@ HEADERS += \ jumpto.h \ pngexport.h \ flatteningconverter.h \ - blockdata.h + paletteentry.h SOURCES += \ labelledslider.cpp \ biomeidentifier.cpp \ diff --git a/blockdata.h b/paletteentry.h similarity index 66% rename from blockdata.h rename to paletteentry.h index 5bb81644..4c60e3c8 100644 --- a/blockdata.h +++ b/paletteentry.h @@ -1,15 +1,15 @@ /** Copyright (c) 2018, nnooney, EtlamGit */ -#ifndef BLOCKDATA_H_ -#define BLOCKDATA_H_ +#ifndef PALETTEENTRY_H_ +#define PALETTEENTRY_H_ #include #include -class BlockData { +class PaletteEntry { public: uint hid; // we use hashed name as ID QString name; QMap properties; }; -#endif // BLOCKDATA_H_ +#endif // PALETTEENTRY_H_