Moved ProtocolBlockTypePalette functionality into BlockTypePalette.
This commit is contained in:
parent
2de6b7537d
commit
7453a9fbe1
@ -1,5 +1,8 @@
|
|||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "BlockTypePalette.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;
|
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. */
|
/** Create a new empty instance. */
|
||||||
BlockTypePalette();
|
BlockTypePalette();
|
||||||
@ -63,6 +77,13 @@ public:
|
|||||||
Used for protocol block type mapping. */
|
Used for protocol block type mapping. */
|
||||||
std::map<UInt32, UInt32> createTransformMapWithFallback(const BlockTypePalette & aFrom, UInt32 aFallbackIndex) const;
|
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:
|
protected:
|
||||||
|
|
||||||
@ -77,4 +98,11 @@ protected:
|
|||||||
/** The maximum index ever used in the maps.
|
/** The maximum index ever used in the maps.
|
||||||
Used when adding new entries through the index() call. */
|
Used when adding new entries through the index() call. */
|
||||||
UInt32 mMaxIndex;
|
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_12.cpp
|
||||||
Protocol_1_13.cpp
|
Protocol_1_13.cpp
|
||||||
ProtocolRecognizer.cpp
|
ProtocolRecognizer.cpp
|
||||||
ProtocolBlockTypePalette.cpp
|
|
||||||
)
|
)
|
||||||
|
|
||||||
SET (HDRS
|
SET (HDRS
|
||||||
@ -30,7 +29,6 @@ SET (HDRS
|
|||||||
Protocol_1_12.h
|
Protocol_1_12.h
|
||||||
Protocol_1_13.h
|
Protocol_1_13.h
|
||||||
ProtocolRecognizer.h
|
ProtocolRecognizer.h
|
||||||
ProtocolBlockTypePalette.h
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if (NOT MSVC)
|
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",
|
IMPLEMENT_TEST_MAIN("BlockTypePalette",
|
||||||
testBasic();
|
testBasic();
|
||||||
testTransformAddMissing();
|
testTransformAddMissing();
|
||||||
testTransformWithFallback();
|
testTransformWithFallback();
|
||||||
|
testLoadSimpleSuccess();
|
||||||
|
testLoadErrors();
|
||||||
|
testLoadComplex1();
|
||||||
|
testLoadComplex2();
|
||||||
|
testLoadFromFile1();
|
||||||
|
testLoadFromFile2();
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,8 +28,9 @@ add_executable(BlockTypePaletteTest
|
|||||||
${CMAKE_SOURCE_DIR}/src/BlockTypePalette.cpp
|
${CMAKE_SOURCE_DIR}/src/BlockTypePalette.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/StringUtils.cpp
|
${CMAKE_SOURCE_DIR}/src/StringUtils.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/OSSupport/CriticalSection.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:
|
# BlockTypeRegistryTest: Verify that the BlockTypeRegistry class works as intended:
|
||||||
add_executable(BlockTypeRegistryTest
|
add_executable(BlockTypeRegistryTest
|
||||||
@ -53,7 +54,14 @@ add_executable(PalettedBlockAreaTest
|
|||||||
${CMAKE_SOURCE_DIR}/src/StringUtils.cpp
|
${CMAKE_SOURCE_DIR}/src/StringUtils.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/OSSupport/CriticalSection.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(OSSupport)
|
||||||
add_subdirectory(SchematicFileSerializer)
|
add_subdirectory(SchematicFileSerializer)
|
||||||
add_subdirectory(UUID)
|
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