Skip to content

Commit

Permalink
add basic support for block states
Browse files Browse the repository at this point in the history
+ 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)
  • Loading branch information
EtlamGit committed Dec 28, 2018
1 parent e4b662b commit 872dca6
Show file tree
Hide file tree
Showing 11 changed files with 120 additions and 106 deletions.
81 changes: 33 additions & 48 deletions blockidentifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
}

Expand Down Expand Up @@ -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<BlockInfo*> &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<BlockInfo*> &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();
Expand Down Expand Up @@ -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();
Expand All @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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<JSONArray *>(b->at("variants"));
int vlen = variants->length();
for (int j = 0; j < vlen; j++)
parseDefinition(dynamic_cast<JSONObject *>(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
Expand Down
43 changes: 23 additions & 20 deletions blockidentifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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;
Expand All @@ -75,16 +77,17 @@ 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();
BlockIdentifier(const BlockIdentifier &);
BlockIdentifier &operator=(const BlockIdentifier &);

void parseDefinition(JSONObject *block, BlockInfo *parent, int pack);
QMap<uint, BlockInfo*> blocks;
QMap<uint, BlockInfo*> blocks;
QList<QList<BlockInfo*> > packs;
};

Expand Down
28 changes: 23 additions & 5 deletions chunk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand All @@ -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]];
}
Expand Down
8 changes: 4 additions & 4 deletions chunk.h
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down
1 change: 1 addition & 0 deletions dimensionidentifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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++)
Expand Down
2 changes: 1 addition & 1 deletion flatteningconverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ FlatteningConverter& FlatteningConverter::Instance() {
}

//const BlockData * FlatteningConverter::getPalette() {
BlockData * FlatteningConverter::getPalette() {
PaletteEntry * FlatteningConverter::getPalette() {
return palette;
}

Expand Down
6 changes: 3 additions & 3 deletions flatteningconverter.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#ifndef FLATTENINGCONVERTER_H_
#define FLATTENINGCONVERTER_H_

#include "./blockdata.h"
#include "./paletteentry.h"

class JSONArray;
class JSONObject;
Expand All @@ -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
Expand All @@ -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<QList<BlockInfo*> > packs;
};

Expand Down
Loading

0 comments on commit 872dca6

Please sign in to comment.