Moved ProtocolBlockTypePalette functionality into BlockTypePalette.
This commit is contained in:
parent
2de6b7537d
commit
7453a9fbe1
@ -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[]
|
||||
}
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
}
|
@ -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;
|
||||
};
|
@ -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<UInt32, bool>(0, true)));
|
||||
TEST_EQUAL(palette.maybeIndex("b", BlockState({{"foo", "baz"}})), (std::make_pair<UInt32, bool>(0, false)));
|
||||
TEST_EQUAL(palette.maybeIndex("a", BlockState({{"foo", "bar"}})), (std::make_pair<UInt32, bool>(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<UInt32, bool>(0, true)));
|
||||
TEST_EQUAL(palette.maybeIndex("b", {{"foo", "baz"}, {"moo", "bar"}}), (std::make_pair<UInt32, bool>(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<UInt32, bool>(0, true)));
|
||||
TEST_EQUAL(palette.maybeIndex("b", BlockState()), (std::make_pair<UInt32, bool>(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<UInt32, bool>(0, true)));
|
||||
TEST_EQUAL(palette.maybeIndex("minecraft:stone", BlockState()), (std::make_pair<UInt32, bool>(1, true)));
|
||||
TEST_EQUAL(
|
||||
palette.maybeIndex(
|
||||
"minecraft:dark_oak_leaves",
|
||||
BlockState({{"persistent", "false"}, {"distance", "6"}})
|
||||
),
|
||||
(std::make_pair<UInt32, bool>(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<UInt32, bool>(0, true)));
|
||||
TEST_EQUAL(palette.maybeIndex("minecraft:stone", BlockState()), (std::make_pair<UInt32, bool>(1, true)));
|
||||
TEST_EQUAL(palette.maybeIndex("minecraft:dirt", BlockState()), (std::make_pair<UInt32, bool>(10, true)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
IMPLEMENT_TEST_MAIN("BlockTypePalette",
|
||||
testBasic();
|
||||
testTransformAddMissing();
|
||||
testTransformWithFallback();
|
||||
testLoadSimpleSuccess();
|
||||
testLoadErrors();
|
||||
testLoadComplex1();
|
||||
testLoadComplex2();
|
||||
testLoadFromFile1();
|
||||
testLoadFromFile2();
|
||||
)
|
||||
|
||||
|
||||
|
@ -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 ./
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
@ -19,4 +19,3 @@ add_subdirectory(Network)
|
||||
add_subdirectory(OSSupport)
|
||||
add_subdirectory(SchematicFileSerializer)
|
||||
add_subdirectory(UUID)
|
||||
add_subdirectory(ProtocolBlockTypePalette)
|
||||
|
@ -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
|
||||
)
|
@ -1,168 +0,0 @@
|
||||
// ProtocolBlockTypePaletteTest.cpp
|
||||
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <streambuf>
|
||||
#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();
|
||||
)
|
Loading…
Reference in New Issue
Block a user