From 7453a9fbe120f345625a24bbea18c35cd3c26a6a Mon Sep 17 00:00:00 2001 From: Mattes D Date: Mon, 2 Dec 2019 16:45:55 +0100 Subject: Moved ProtocolBlockTypePalette functionality into BlockTypePalette. --- src/BlockTypePalette.cpp | 82 ++++++++++ src/BlockTypePalette.h | 28 ++++ src/Protocol/CMakeLists.txt | 2 - src/Protocol/ProtocolBlockTypePalette.cpp | 144 ------------------ src/Protocol/ProtocolBlockTypePalette.h | 40 ----- tests/BlockTypeRegistry/BlockTypePaletteTest.cpp | 148 ++++++++++++++++++ tests/BlockTypeRegistry/CMakeLists.txt | 12 +- tests/BlockTypeRegistry/test.btp.json | 146 ++++++++++++++++++ tests/CMakeLists.txt | 1 - tests/ProtocolBlockTypePalette/CMakeLists.txt | 47 ------ .../ProtocolBlockTypePaletteTest.cpp | 168 --------------------- tests/ProtocolBlockTypePalette/test.btp.json | 146 ------------------ 12 files changed, 414 insertions(+), 550 deletions(-) delete mode 100644 src/Protocol/ProtocolBlockTypePalette.cpp delete mode 100644 src/Protocol/ProtocolBlockTypePalette.h create mode 100644 tests/BlockTypeRegistry/test.btp.json delete mode 100644 tests/ProtocolBlockTypePalette/CMakeLists.txt delete mode 100644 tests/ProtocolBlockTypePalette/ProtocolBlockTypePaletteTest.cpp delete mode 100644 tests/ProtocolBlockTypePalette/test.btp.json 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 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 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(std::stoul(record["id"].asString())); + std::map 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 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 -#include -#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 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()}); - } - - 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 -#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> mIndex; -}; diff --git a/tests/BlockTypeRegistry/BlockTypePaletteTest.cpp b/tests/BlockTypeRegistry/BlockTypePaletteTest.cpp index 1337c7dc3..dddf80348 100644 --- a/tests/BlockTypeRegistry/BlockTypePaletteTest.cpp +++ b/tests/BlockTypeRegistry/BlockTypePaletteTest.cpp @@ -123,10 +123,158 @@ static void testTransformWithFallback() +/** Tests that loading a simple JSON palette succeeds. */ +static void testLoadSimpleSuccess(void) +{ + LOG("Testing loading a simple JSON palette"); + + BlockTypePalette palette; + + auto example = "{\"Metadata\":{\"ProtocolBlockTypePaletteVersion\":1}, \"Palette\":[{\ + \"props\": {\ + \"foo\": \"bar\"\ + }, \ + \"name\": \"b\", \ + \"id\": \"0\"\ + }]}"; + + palette.loadFromString(example); + TEST_EQUAL(palette.maybeIndex("b", BlockState({{"foo", "bar"}})), (std::make_pair(0, true))); + TEST_EQUAL(palette.maybeIndex("b", BlockState({{"foo", "baz"}})), (std::make_pair(0, false))); + TEST_EQUAL(palette.maybeIndex("a", BlockState({{"foo", "bar"}})), (std::make_pair(0, false))); +} + + + + + +static void testLoadErrors(void) +{ + LOG("Testing palette load error reporting."); + + BlockTypePalette palette; + TEST_THROWS(palette.loadFromString(""), BlockTypePalette::LoadFailedException); + TEST_THROWS(palette.loadFromString("[]"), BlockTypePalette::LoadFailedException); + TEST_THROWS(palette.loadFromString("a = {}"), BlockTypePalette::LoadFailedException); + TEST_THROWS(palette.loadFromString("{x = 1}"), BlockTypePalette::LoadFailedException); // Lua style + TEST_THROWS(palette.loadFromString("$#^%&"), BlockTypePalette::LoadFailedException); +} + + + + + +static void testLoadComplex1(void) +{ + LOG("Testing loading a complex palette (1)"); + BlockTypePalette palette; + auto str = "{\"Metadata\":{\"ProtocolBlockTypePaletteVersion\":1}, \"Palette\":[{\ + \"props\": {\ + \"foo\": \"bar\", \ + \"moo\": \"baz\"\ + }, \ + \"id\": \"0\", \ + \"name\": \"b\"\ + }, {\ + \"props\": {\ + \"foo\": \"baz\", \ + \"moo\": \"bar\"\ + }, \ + \"id\": \"1\", \ + \"name\": \"b\"\ + }, {\ + \"props\": {\ + \"foo\": \"baz\", \ + \"moo\": \"bar\"\ + }, \ + \"id\": \"1001\", \ + \"name\": \"b\"\ + }]}"; + // Note: The palette has a duplicate entry with differrent IDs, the latter ID wins + palette.loadFromString(str); + TEST_EQUAL(palette.maybeIndex("b", {{"foo", "bar"}}).second, false); + TEST_EQUAL(palette.maybeIndex("b", {{"foo", "bar"}, {"moo", "baz"}}), (std::make_pair(0, true))); + TEST_EQUAL(palette.maybeIndex("b", {{"foo", "baz"}, {"moo", "bar"}}), (std::make_pair(1001, true))); + TEST_EQUAL(palette.maybeIndex("c", {{"foo", "baz"}, {"moo", "bar"}}).second, false); +} + + + + + +static void testLoadComplex2(void) +{ + LOG("Testing loading a complex palette (2)"); + BlockTypePalette palette; + auto str = "{\"Metadata\":{\"ProtocolBlockTypePaletteVersion\":1}, \"Palette\":[{\ + \"id\": \"0\", \ + \"name\": \"a\"\ + }, {\ + \"id\": \"1\", \ + \"name\": \"b\"\ + }]}"; + palette.loadFromString(str); + TEST_EQUAL(palette.maybeIndex("a", BlockState()), (std::make_pair(0, true))); + TEST_EQUAL(palette.maybeIndex("b", BlockState()), (std::make_pair(1, true))); +} + + + + + +static void testLoadFromFile1(void) +{ + LOG("Testing loading a palette from file \"test.btp.json\""); + BlockTypePalette palette; + palette.loadFromString(cFile::ReadWholeFile("test.btp.json")); + + TEST_EQUAL(palette.maybeIndex("minecraft:air", BlockState()), (std::make_pair(0, true))); + TEST_EQUAL(palette.maybeIndex("minecraft:stone", BlockState()), (std::make_pair(1, true))); + TEST_EQUAL( + palette.maybeIndex( + "minecraft:dark_oak_leaves", + BlockState({{"persistent", "false"}, {"distance", "6"}}) + ), + (std::make_pair(225, true)) + ); + TEST_EQUAL( + palette.maybeIndex( + "minecraft:dark_oak_leaves", + BlockState({{"persistent", "false"}}) + ).second, + false + ); +} + + + + + +static void testLoadFromFile2(void) +{ + LOG("Testing loading a palette from file \"base.btp.json\" (version 1.13)"); + BlockTypePalette palette; + palette.loadFromString(cFile::ReadWholeFile("base.btp.json")); + + TEST_EQUAL(palette.maybeIndex("minecraft:air", BlockState()), (std::make_pair(0, true))); + TEST_EQUAL(palette.maybeIndex("minecraft:stone", BlockState()), (std::make_pair(1, true))); + TEST_EQUAL(palette.maybeIndex("minecraft:dirt", BlockState()), (std::make_pair(10, true))); +} + + + + + IMPLEMENT_TEST_MAIN("BlockTypePalette", testBasic(); testTransformAddMissing(); testTransformWithFallback(); + testLoadSimpleSuccess(); + testLoadErrors(); + testLoadComplex1(); + testLoadComplex2(); + testLoadFromFile1(); + testLoadFromFile2(); ) diff --git a/tests/BlockTypeRegistry/CMakeLists.txt b/tests/BlockTypeRegistry/CMakeLists.txt index 379158d5c..beadc8af3 100644 --- a/tests/BlockTypeRegistry/CMakeLists.txt +++ b/tests/BlockTypeRegistry/CMakeLists.txt @@ -28,8 +28,9 @@ add_executable(BlockTypePaletteTest ${CMAKE_SOURCE_DIR}/src/BlockTypePalette.cpp ${CMAKE_SOURCE_DIR}/src/StringUtils.cpp ${CMAKE_SOURCE_DIR}/src/OSSupport/CriticalSection.cpp + ${CMAKE_SOURCE_DIR}/src/OSSupport/File.cpp ) -target_link_libraries(BlockTypePaletteTest fmt::fmt) +target_link_libraries(BlockTypePaletteTest fmt::fmt jsoncpp_lib_static) # BlockTypeRegistryTest: Verify that the BlockTypeRegistry class works as intended: add_executable(BlockTypeRegistryTest @@ -53,7 +54,14 @@ add_executable(PalettedBlockAreaTest ${CMAKE_SOURCE_DIR}/src/StringUtils.cpp ${CMAKE_SOURCE_DIR}/src/OSSupport/CriticalSection.cpp ) -target_link_libraries(PalettedBlockAreaTest fmt::fmt) +target_link_libraries(PalettedBlockAreaTest fmt::fmt jsoncpp_lib_static) + +# Extra files for BlockTypePalette test: +file (COPY + test.btp.json + ../../Server/Protocol/1.13/base.btp.json + DESTINATION ./ +) diff --git a/tests/BlockTypeRegistry/test.btp.json b/tests/BlockTypeRegistry/test.btp.json new file mode 100644 index 000000000..264e56185 --- /dev/null +++ b/tests/BlockTypeRegistry/test.btp.json @@ -0,0 +1,146 @@ +{ + "Metadata": { + "ProtocolBlockTypePaletteVersion": 1 + }, + "Palette": [{ + "id": 0, + "name": "minecraft:air" + }, { + "id": 1, + "name": "minecraft:stone" + }, { + "id": 221, + "name": "minecraft:dark_oak_leaves", + "props": { + "persistent": "false", + "distance": "4" + } + }, { + "id": 222, + "name": "minecraft:dark_oak_leaves", + "props": { + "persistent": "true", + "distance": "5" + } + }, { + "id": 223, + "name": "minecraft:dark_oak_leaves", + "props": { + "persistent": "false", + "distance": "5" + } + }, { + "id": 224, + "name": "minecraft:dark_oak_leaves", + "props": { + "persistent": "true", + "distance": "6" + } + }, { + "id": 225, + "name": "minecraft:dark_oak_leaves", + "props": { + "persistent": "false", + "distance": "6" + } + }, { + "id": 226, + "name": "minecraft:dark_oak_leaves", + "props": { + "persistent": "true", + "distance": "7" + } + }, { + "id": 227, + "name": "minecraft:dark_oak_leaves", + "props": { + "persistent": "false", + "distance": "7" + } + }, { + "id": 9988, + "name": "minecraft:powered_rail", + "props": { + "powered": "true", + "shape": "north_south" + } + }, { + "id": 9989, + "name": "minecraft:powered_rail", + "props": { + "powered": "true", + "shape": "east_west" + } + }, { + "id": 9990, + "name": "minecraft:powered_rail", + "props": { + "powered": "true", + "shape": "ascending_east" + } + }, { + "id": 9991, + "name": "minecraft:powered_rail", + "props": { + "powered": "true", + "shape": "ascending_west" + } + }, { + "id": 9992, + "name": "minecraft:powered_rail", + "props": { + "powered": "true", + "shape": "ascending_north" + } + }, { + "id": 9993, + "name": "minecraft:powered_rail", + "props": { + "powered": "true", + "shape": "ascending_south" + } + }, { + "id": 9994, + "name": "minecraft:powered_rail", + "props": { + "powered": "false", + "shape": "north_south" + } + }, { + "id": 9995, + "name": "minecraft:powered_rail", + "props": { + "powered": "false", + "shape": "east_west" + } + }, { + "id": 9996, + "name": "minecraft:powered_rail", + "props": { + "powered": "false", + "shape": "ascending_east" + } + }, { + "id": 9997, + "name": "minecraft:powered_rail", + "props": { + "powered": "false", + "shape": "ascending_west" + } + }, { + "id": 9998, + "name": "minecraft:powered_rail", + "props": { + "powered": "false", + "shape": "ascending_north" + } + }, { + "id": 9999, + "name": "minecraft:powered_rail", + "props": { + "powered": "false", + "shape": "ascending_south" + } + } + ] +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 2ea55af25..74e4323ec 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -19,4 +19,3 @@ add_subdirectory(Network) add_subdirectory(OSSupport) add_subdirectory(SchematicFileSerializer) add_subdirectory(UUID) -add_subdirectory(ProtocolBlockTypePalette) diff --git a/tests/ProtocolBlockTypePalette/CMakeLists.txt b/tests/ProtocolBlockTypePalette/CMakeLists.txt deleted file mode 100644 index 43c2df676..000000000 --- a/tests/ProtocolBlockTypePalette/CMakeLists.txt +++ /dev/null @@ -1,47 +0,0 @@ -cmake_minimum_required(VERSION 3.0.2) -enable_testing() -add_definitions(-DTEST_GLOBALS=1) - -include_directories(SYSTEM "../../lib/jsoncpp/include") -include_directories(${CMAKE_SOURCE_DIR}/src/) - - -add_definitions(-DTEST_GLOBALS=1) - -set (SHARED_SRCS - ${CMAKE_SOURCE_DIR}/src/Protocol/ProtocolBlockTypePalette.cpp - ${CMAKE_SOURCE_DIR}/src/BlockState.cpp - ${CMAKE_SOURCE_DIR}/src/StringUtils.cpp -) - -set (SHARED_HDRS - ../TestHelpers.h - ${CMAKE_SOURCE_DIR}/src/Protocol/ProtocolBlockTypePalette.h - ${CMAKE_SOURCE_DIR}/src/BlockState.h - ${CMAKE_SOURCE_DIR}/src/StringUtils.h -) - -set (SRCS - ProtocolBlockTypePaletteTest.cpp -) - -file (COPY - test.btp.json - ../../Server/Protocol/1.13/base.btp.json - DESTINATION ./) - -source_group("Shared" FILES ${SHARED_SRCS} ${SHARED_HDRS}) -source_group("Sources" FILES ${SRCS}) -add_executable(ProtocolBlockTypePaletteTest-exe ${SRCS} ${SHARED_SRCS} ${SHARED_HDRS}) -target_link_libraries(ProtocolBlockTypePaletteTest-exe fmt::fmt jsoncpp_lib_static) -add_test(NAME ProtocolBlockTypePaletteTest-test COMMAND ProtocolBlockTypePaletteTest-exe) - - - - - -# Put the projects into solution folders (MSVC): -set_target_properties( - ProtocolBlockTypePaletteTest-exe - PROPERTIES FOLDER Tests -) diff --git a/tests/ProtocolBlockTypePalette/ProtocolBlockTypePaletteTest.cpp b/tests/ProtocolBlockTypePalette/ProtocolBlockTypePaletteTest.cpp deleted file mode 100644 index 948fd2219..000000000 --- a/tests/ProtocolBlockTypePalette/ProtocolBlockTypePaletteTest.cpp +++ /dev/null @@ -1,168 +0,0 @@ -// ProtocolBlockTypePaletteTest.cpp - -#include -#include -#include -#include "Globals.h" - -#include "Protocol/ProtocolBlockTypePalette.h" - -#include "../TestHelpers.h" - - - - - -static void TestSuccess(void) -{ - LOG("Test TestSuccess"); - ProtocolBlockTypePalette palette; - - auto example = "{\"Metadata\":{\"ProtocolBlockTypePaletteVersion\":1}, \"Palette\":[{\ - \"props\": {\ - \"foo\": \"bar\"\ - }, \ - \"name\": \"b\", \ - \"id\": \"0\"\ - }]}"; - - palette.clear(); - TEST_TRUE(palette.loadFromString(example)); - TEST_EQUAL(palette.index("b", BlockState({{"foo", "bar"}})), 0); - TEST_EQUAL(palette.index("b", BlockState({{"foo", "baz"}})), ProtocolBlockTypePalette::NOT_FOUND); - TEST_EQUAL(palette.index("a", BlockState({{"foo", "bar"}})), ProtocolBlockTypePalette::NOT_FOUND); -} - - - - - -static void TestErrors(void) -{ - LOG("Test TestErrors"); - ProtocolBlockTypePalette palette; - TEST_FALSE(palette.loadFromString("")); - - palette.clear(); - TEST_FALSE(palette.loadFromString("[]")); - - palette.clear(); - TEST_FALSE(palette.loadFromString("a = {}")); - - palette.clear(); - TEST_FALSE(palette.loadFromString("{x = 1}")); // Lua style - - palette.clear(); - TEST_FALSE(palette.loadFromString("$#^%&")); -} - - - - - -static void TestComplex1(void) -{ - LOG("Test TestComplex1"); - ProtocolBlockTypePalette palette; - auto str = "{\"Metadata\":{\"ProtocolBlockTypePaletteVersion\":1}, \"Palette\":[{\ - \"props\": {\ - \"foo\": \"bar\", \ - \"moo\": \"baz\"\ - }, \ - \"id\": \"0\", \ - \"name\": \"b\"\ - }, {\ - \"props\": {\ - \"foo\": \"baz\", \ - \"moo\": \"bar\"\ - }, \ - \"id\": \"1\", \ - \"name\": \"b\"\ - }, {\ - \"props\": {\ - \"foo\": \"baz\", \ - \"moo\": \"bar\"\ - }, \ - \"id\": \"1001\", \ - \"name\": \"b\"\ - }]}"; - TEST_TRUE(palette.loadFromString(str)); // This should print info message about duplicate ID - TEST_EQUAL(palette.index("b", BlockState({{"foo","bar"}})), ProtocolBlockTypePalette::NOT_FOUND); - TEST_EQUAL(palette.index("b", BlockState({{"foo","bar"}, {"moo","baz"}})), 0); - TEST_EQUAL(palette.index("b", BlockState({{"foo","baz"}, {"moo","bar"}})), 1); - TEST_EQUAL(palette.index("c", BlockState({{"foo","baz"}, {"moo","bar"}})), ProtocolBlockTypePalette::NOT_FOUND); -} - - - - - -static void TestComplex2(void) -{ - LOG("Test TestComplex2"); - ProtocolBlockTypePalette palette; - auto str = "{\"Metadata\":{\"ProtocolBlockTypePaletteVersion\":1}, \"Palette\":[{\ - \"id\": \"0\", \ - \"name\": \"a\"\ - }, {\ - \"id\": \"1\", \ - \"name\": \"b\"\ - }]}"; - TEST_TRUE(palette.loadFromString(str)); - TEST_EQUAL(palette.index("a", BlockState()), 0); - TEST_EQUAL(palette.index("b", BlockState({})), 1); -} - - - - - -static void TestFile(void) -{ - LOG("Test TestFile"); - std::ifstream f("base.btp.json"); - ProtocolBlockTypePalette palette; - TEST_TRUE(palette.loadFromStream(f)); - - // This is a bit problematic - the only permanently fixed block Id is air... - TEST_EQUAL(palette.index("minecraft:air", BlockState()), 0); - TEST_NOTEQUAL(palette.index("minecraft:stone", BlockState()), ProtocolBlockTypePalette::NOT_FOUND); - TEST_NOTEQUAL(palette.index("minecraft:dirt", BlockState()), ProtocolBlockTypePalette::NOT_FOUND); -} - - - - - -static void TestFile2(void) -{ - LOG("Test TestFile2"); - std::ifstream f("test.btp.json"); - ProtocolBlockTypePalette palette; - TEST_TRUE(palette.loadFromStream(f)); - - TEST_EQUAL(palette.index("minecraft:air", BlockState({})), 0); - TEST_EQUAL(palette.index("minecraft:stone", BlockState()), 1); - TEST_EQUAL(palette.index("minecraft:stone", BlockState()), 1); - TEST_EQUAL(palette.index( - "minecraft:dark_oak_leaves", - BlockState({{"persistent", "false"}, {"distance", "6"}}) - ), 225); - TEST_EQUAL(palette.index( - "minecraft:dark_oak_leaves", - BlockState({{"persistent", "false"}}) - ), ProtocolBlockTypePalette::NOT_FOUND); -} - - - - - -IMPLEMENT_TEST_MAIN("ProtocolBlockTypePaletteTest", - TestSuccess(); - TestErrors(); - TestComplex1(); - TestComplex2(); - TestFile(); - TestFile2(); -) diff --git a/tests/ProtocolBlockTypePalette/test.btp.json b/tests/ProtocolBlockTypePalette/test.btp.json deleted file mode 100644 index 264e56185..000000000 --- a/tests/ProtocolBlockTypePalette/test.btp.json +++ /dev/null @@ -1,146 +0,0 @@ -{ - "Metadata": { - "ProtocolBlockTypePaletteVersion": 1 - }, - "Palette": [{ - "id": 0, - "name": "minecraft:air" - }, { - "id": 1, - "name": "minecraft:stone" - }, { - "id": 221, - "name": "minecraft:dark_oak_leaves", - "props": { - "persistent": "false", - "distance": "4" - } - }, { - "id": 222, - "name": "minecraft:dark_oak_leaves", - "props": { - "persistent": "true", - "distance": "5" - } - }, { - "id": 223, - "name": "minecraft:dark_oak_leaves", - "props": { - "persistent": "false", - "distance": "5" - } - }, { - "id": 224, - "name": "minecraft:dark_oak_leaves", - "props": { - "persistent": "true", - "distance": "6" - } - }, { - "id": 225, - "name": "minecraft:dark_oak_leaves", - "props": { - "persistent": "false", - "distance": "6" - } - }, { - "id": 226, - "name": "minecraft:dark_oak_leaves", - "props": { - "persistent": "true", - "distance": "7" - } - }, { - "id": 227, - "name": "minecraft:dark_oak_leaves", - "props": { - "persistent": "false", - "distance": "7" - } - }, { - "id": 9988, - "name": "minecraft:powered_rail", - "props": { - "powered": "true", - "shape": "north_south" - } - }, { - "id": 9989, - "name": "minecraft:powered_rail", - "props": { - "powered": "true", - "shape": "east_west" - } - }, { - "id": 9990, - "name": "minecraft:powered_rail", - "props": { - "powered": "true", - "shape": "ascending_east" - } - }, { - "id": 9991, - "name": "minecraft:powered_rail", - "props": { - "powered": "true", - "shape": "ascending_west" - } - }, { - "id": 9992, - "name": "minecraft:powered_rail", - "props": { - "powered": "true", - "shape": "ascending_north" - } - }, { - "id": 9993, - "name": "minecraft:powered_rail", - "props": { - "powered": "true", - "shape": "ascending_south" - } - }, { - "id": 9994, - "name": "minecraft:powered_rail", - "props": { - "powered": "false", - "shape": "north_south" - } - }, { - "id": 9995, - "name": "minecraft:powered_rail", - "props": { - "powered": "false", - "shape": "east_west" - } - }, { - "id": 9996, - "name": "minecraft:powered_rail", - "props": { - "powered": "false", - "shape": "ascending_east" - } - }, { - "id": 9997, - "name": "minecraft:powered_rail", - "props": { - "powered": "false", - "shape": "ascending_west" - } - }, { - "id": 9998, - "name": "minecraft:powered_rail", - "props": { - "powered": "false", - "shape": "ascending_north" - } - }, { - "id": 9999, - "name": "minecraft:powered_rail", - "props": { - "powered": "false", - "shape": "ascending_south" - } - } - ] -} -- cgit v1.2.3