summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMattes D <github@xoft.cz>2019-12-02 16:45:55 +0100
committerMattes D <github@xoft.cz>2019-12-28 22:43:35 +0100
commit7453a9fbe120f345625a24bbea18c35cd3c26a6a (patch)
treee97cc9c90fedcad6e44f4011f0fdc4d2f6a284bf /src
parentBlockTypePalette: Refactored for usage in both directions. (diff)
downloadcuberite-7453a9fbe120f345625a24bbea18c35cd3c26a6a.tar
cuberite-7453a9fbe120f345625a24bbea18c35cd3c26a6a.tar.gz
cuberite-7453a9fbe120f345625a24bbea18c35cd3c26a6a.tar.bz2
cuberite-7453a9fbe120f345625a24bbea18c35cd3c26a6a.tar.lz
cuberite-7453a9fbe120f345625a24bbea18c35cd3c26a6a.tar.xz
cuberite-7453a9fbe120f345625a24bbea18c35cd3c26a6a.tar.zst
cuberite-7453a9fbe120f345625a24bbea18c35cd3c26a6a.zip
Diffstat (limited to 'src')
-rw-r--r--src/BlockTypePalette.cpp82
-rw-r--r--src/BlockTypePalette.h28
-rw-r--r--src/Protocol/CMakeLists.txt2
-rw-r--r--src/Protocol/ProtocolBlockTypePalette.cpp144
-rw-r--r--src/Protocol/ProtocolBlockTypePalette.h40
5 files changed, 110 insertions, 186 deletions
diff --git a/src/BlockTypePalette.cpp b/src/BlockTypePalette.cpp
index f0f54b7c1..92269db9d 100644
--- a/src/BlockTypePalette.cpp
+++ b/src/BlockTypePalette.cpp
@@ -1,5 +1,8 @@
#include "Globals.h"
#include "BlockTypePalette.h"
+#include "json/value.h"
+#include "json/reader.h"
+
@@ -113,3 +116,82 @@ std::map<UInt32, UInt32> BlockTypePalette::createTransformMapWithFallback(const
}
return res;
}
+
+
+
+
+
+void BlockTypePalette::loadFromString(const AString & aString)
+{
+ // TODO: Detect format (Json vs Lua)
+ return loadFromJsonString(aString);
+}
+
+
+
+
+
+void BlockTypePalette::loadFromJsonString(const AString & aJsonPalette)
+{
+ // Parse the string into JSON object:
+ Json::Value root;
+ Json::CharReaderBuilder builder;
+ std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
+ std::string errs;
+ if (!reader->parse(aJsonPalette.data(), aJsonPalette.data() + aJsonPalette.size(), &root, &errs))
+ {
+ throw LoadFailedException(errs);
+ }
+
+ // Check the JSON's metadata + version:
+ if (!root.isObject() ||
+ !root.isMember("Metadata") ||
+ !root["Metadata"].isMember("ProtocolBlockTypePaletteVersion") ||
+ !root.isMember("Palette") ||
+ !root["Palette"].isArray())
+ {
+ throw LoadFailedException("Incorrect palette format, wrong or missing metadata.");
+ }
+ auto version = root["Metadata"]["ProtocolBlockTypePaletteVersion"].asUInt();
+ if (version != 1)
+ {
+ throw(Printf("Palette format version %d not supported.", version));
+ }
+
+ // Load the palette:
+ auto len = root["Palette"].size();
+ for (decltype(len) i = 0; i < len; ++i)
+ {
+ const auto & record = root["Palette"][i];
+ if (!record.isObject())
+ {
+ throw LoadFailedException(Printf("Palette record #%u is not a JSON object.", i));
+ }
+
+ auto blockTypeName = record["name"].asString();
+ auto id = static_cast<UInt32>(std::stoul(record["id"].asString()));
+ std::map<AString, AString> state;
+
+ if (record.isMember("props"))
+ {
+ const auto & props = record["props"];
+ if (!props.isObject())
+ {
+ throw LoadFailedException(Printf("Palette record #%u: \"props\" value is not a JSON object.", i));
+ }
+ for (const auto & key: props.getMemberNames())
+ {
+ state[key] = props[key].asString();
+ }
+ }
+ BlockState blockState(state);
+
+ // Insert / update in the maps:
+ mNumberToBlock[id] = {blockTypeName, blockState};
+ mBlockToNumber[blockTypeName][blockState] = id;
+ if (id > mMaxIndex)
+ {
+ mMaxIndex = id;
+ }
+ } // for i - Palette[]
+}
diff --git a/src/BlockTypePalette.h b/src/BlockTypePalette.h
index adb156ff1..2d0985f08 100644
--- a/src/BlockTypePalette.h
+++ b/src/BlockTypePalette.h
@@ -34,6 +34,20 @@ public:
};
+ /** Exception that is thrown when loading the palette fails hard (bad format). */
+ class LoadFailedException:
+ public std::runtime_error
+ {
+ using Super = std::runtime_error;
+
+ public:
+ LoadFailedException(const AString & aReason):
+ Super(aReason)
+ {
+ }
+ };
+
+
/** Create a new empty instance. */
BlockTypePalette();
@@ -63,6 +77,13 @@ public:
Used for protocol block type mapping. */
std::map<UInt32, UInt32> createTransformMapWithFallback(const BlockTypePalette & aFrom, UInt32 aFallbackIndex) const;
+ /** Loads the palette from the string representation.
+ Throws a LoadFailedException if the loading fails hard (bad string format).
+ If the string specifies duplicate entries (either to already existing entries, or to itself),
+ the duplicates replace the current values silently (this allows us to chain multiple files as "overrides".
+ Currently handles only JSON representation, expected to handle also Lua representation in the future. */
+ void loadFromString(const AString & aString);
+
protected:
@@ -77,4 +98,11 @@ protected:
/** The maximum index ever used in the maps.
Used when adding new entries through the index() call. */
UInt32 mMaxIndex;
+
+
+ /** Loads the palette from the JSON representation.
+ Throws a LoadFailedException if the loading fails hard (bad string format).
+ If the string specifies duplicate entries (either to already existing entries, or to itself),
+ the duplicates replace the current values silently (this allows us to chain multiple files as "overrides". */
+ void loadFromJsonString(const AString & aJsonPalette);
};
diff --git a/src/Protocol/CMakeLists.txt b/src/Protocol/CMakeLists.txt
index d2170fb95..3e8d65b94 100644
--- a/src/Protocol/CMakeLists.txt
+++ b/src/Protocol/CMakeLists.txt
@@ -13,7 +13,6 @@ SET (SRCS
Protocol_1_12.cpp
Protocol_1_13.cpp
ProtocolRecognizer.cpp
- ProtocolBlockTypePalette.cpp
)
SET (HDRS
@@ -30,7 +29,6 @@ SET (HDRS
Protocol_1_12.h
Protocol_1_13.h
ProtocolRecognizer.h
- ProtocolBlockTypePalette.h
)
if (NOT MSVC)
diff --git a/src/Protocol/ProtocolBlockTypePalette.cpp b/src/Protocol/ProtocolBlockTypePalette.cpp
deleted file mode 100644
index 86d05623b..000000000
--- a/src/Protocol/ProtocolBlockTypePalette.cpp
+++ /dev/null
@@ -1,144 +0,0 @@
-#include "Globals.h"
-#include "ProtocolBlockTypePalette.h"
-#include <cstdint>
-#include <sstream>
-#include "json/value.h"
-#include "json/reader.h"
-
-
-
-
-
-ProtocolBlockTypePalette::ProtocolBlockTypePalette()
-{
- // empty
-}
-
-
-
-
-
-bool ProtocolBlockTypePalette::loadFromString(const AString & aMapping)
-{
- std::stringstream stream;
- stream << aMapping;
-
- return loadFromStream(stream);
-}
-
-
-
-
-
-bool ProtocolBlockTypePalette::loadFromStream(std::istream & aInputStream)
-{
- Json::Value root;
-
- try
- {
- aInputStream >> root;
- }
- #if defined _DEBUG
- catch (const std::exception & e)
- {
- LOGD(e.what());
- return false;
- }
- #else
- catch (const std::exception &)
- {
- return false;
- }
- #endif
-
- if (!root.isObject() ||
- !root.isMember("Metadata") ||
- !root["Metadata"].isMember("ProtocolBlockTypePaletteVersion") ||
- !root.isMember("Palette") ||
- !root["Palette"].isArray())
- {
- LOGD("Incorrect palette format.");
- return false;
- }
-
- if (root["Metadata"]["ProtocolBlockTypePaletteVersion"].asUInt() != 1)
- {
- LOGD("Palette format version not supported.");
- return false;
- }
-
- auto len = root["Palette"].size();
- for (decltype(len) i = 0; i < len; ++i)
- {
- const auto & record = root["Palette"][i];
- if (!record.isObject())
- {
- LOGD("Record #%u must be a JSON object.", i);
- return false;
- }
-
- auto blocktype = record["name"].asString();
- auto id = std::stoul(record["id"].asString());
- std::map<AString, AString> state;
-
- if (id >= NOT_FOUND)
- {
- LOGD("`id` must be less than ProtocolBlockTypePalette::NOT_FOUND, but is %lu", id);
- return false;
- }
-
- if (record.isMember("props"))
- {
- const auto & props = record["props"];
- if (!props.isObject())
- {
- LOGD("`props` key must be a JSON object.");
- return false;
- }
- for (const auto & key: props.getMemberNames())
- {
- state[key] = props[key].asString();
- }
- }
-
- // Block type map entry already exists?
- if (mIndex.count(blocktype) == 0)
- {
- mIndex.insert({blocktype, std::map<BlockState, UInt32>()});
- }
-
- const auto & result = mIndex[blocktype].insert({BlockState(state), id});
- if (result.second == false)
- {
- LOGINFO("Duplicate block state encountered (Current ID: %lu, other: %lu)", result.first->second, id);
- }
- }
- return true;
-}
-
-
-
-
-
-UInt32 ProtocolBlockTypePalette::index(const AString & aBlockTypeName, const BlockState & aBlockState) const
-{
- auto a = mIndex.find(aBlockTypeName);
- if (a != mIndex.end())
- {
- auto b = a->second.find(aBlockState);
- if (b != a->second.end())
- {
- return b->second;
- }
- }
- return NOT_FOUND;
-}
-
-
-
-
-
-void ProtocolBlockTypePalette::clear()
-{
- return mIndex.clear();
-}
diff --git a/src/Protocol/ProtocolBlockTypePalette.h b/src/Protocol/ProtocolBlockTypePalette.h
deleted file mode 100644
index fb156cfd5..000000000
--- a/src/Protocol/ProtocolBlockTypePalette.h
+++ /dev/null
@@ -1,40 +0,0 @@
-#pragma once
-#include <unordered_map>
-#include "../BlockState.h"
-
-
-/** Parses and holds a collection of block types and their possible states
-together with their corresponding Id within the Minecraft network protocol. */
-class ProtocolBlockTypePalette
-{
-public:
- static const UInt32 NOT_FOUND = UINT32_MAX;
-
- /** Create a new empty instance. */
- ProtocolBlockTypePalette();
-
- /** Loads the palette from a string.
- See loadFromStream() for further details. */
- bool loadFromString(const AString & aMapping);
-
- /** Loads the palette from an input stream.
- Returns `true` on success, `false` otherwise. Sucessive calls to this method
- will _add_ data to the palette. If duplicate keys are encountered, they will
- be ignored and an info message logged. */
- bool loadFromStream(std::istream & aInputStream);
-
- /** Returns the defined index corresponding of the given aBlockTypeName and
- aBlockState.
- Returns ProtocolBlockTypePalette::NOT_FOUND if the tuple is not found. */
- UInt32 index(const AString & aBlockTypeName, const BlockState & aBlockState) const;
-
- /** Clears the palette. */
- void clear();
-
-
-protected:
-
- /** The palette index. Each item in the map represents a single block state
- palette entry. The value is the block state ID. */
- std::unordered_map<AString, std::map<BlockState, UInt32>> mIndex;
-};