From 9689e7996f340650e2b6d2875b41d63c938b62cf Mon Sep 17 00:00:00 2001 From: DankParrot Date: Wed, 12 Aug 2020 20:10:44 -0700 Subject: [PATCH] Implement global palette loading --- src/DedicatedServer.cpp | 5 ++- src/data/IDMapper.h | 56 +++++++++++++++++++++++++++++ src/data/Registry.cpp | 67 +++++++++++++++++++++++++++++++++++ src/data/Registry.h | 16 +++++++++ src/meson.build | 2 ++ src/world/Palette.h | 35 ++++++++++++++++++ src/world/PalettedContainer.h | 13 +++++++ src/world/World.cpp | 6 ++++ src/world/World.h | 4 +++ 9 files changed, 203 insertions(+), 1 deletion(-) create mode 100644 src/data/IDMapper.h create mode 100644 src/data/Registry.cpp create mode 100644 src/data/Registry.h create mode 100644 src/world/Palette.h create mode 100644 src/world/PalettedContainer.h diff --git a/src/DedicatedServer.cpp b/src/DedicatedServer.cpp index 5730813..acb0c1d 100644 --- a/src/DedicatedServer.cpp +++ b/src/DedicatedServer.cpp @@ -1,5 +1,6 @@ #include "DedicatedServer.h" #include "config/ServerProperties.h" +#include "data/Registry.h" #include "PacketReader.h" @@ -15,7 +16,9 @@ namespace Feather { m_status.descriptionText = properties->motd.GetValue(); m_status.maxPlayers = properties->maxPlayers; - + + Registry::Init(); + m_worldManager.LoadWorld(m_properties->levelName); while (1) diff --git a/src/data/IDMapper.h b/src/data/IDMapper.h new file mode 100644 index 0000000..3103578 --- /dev/null +++ b/src/data/IDMapper.h @@ -0,0 +1,56 @@ +#pragma once + +#include +#include + +namespace Feather +{ + + template + class IDMapper + { + std::vector m_IDtoValue; + std::unordered_map m_ValueToID; + + int m_NextID = 0; + + public: + IDMapper(int size = 512) + { + m_IDtoValue.reserve(size); + m_ValueToID.reserve(size); + } + + inline void AddMapping(int id, T& value) + { + m_IDtoValue.insert(m_IDtoValue.begin() + id, value); + m_ValueToID.insert({ value, id }); + + if (m_NextID <= id) { + m_NextID = id + 1; + } + } + + inline void Add(T& value) + { + AddMapping(m_NextID, value); + } + + inline int GetID(T& value) const + { + return m_ValueToID.at(value); + } + + inline const T& ByID(int id) const + { + return m_IDtoValue.at(id); + } + + inline int Size() const + { + return m_IDtoValue.size(); + } + + + }; +} \ No newline at end of file diff --git a/src/data/Registry.cpp b/src/data/Registry.cpp new file mode 100644 index 0000000..9fcca9a --- /dev/null +++ b/src/data/Registry.cpp @@ -0,0 +1,67 @@ +#include "Common.h" +#include "Registry.h" + +#include "rapidjson/document.h" +#include "rapidjson/filereadstream.h" +#include "rapidjson/stringbuffer.h" +#include "rapidjson/writer.h" + +#include +#include +#include +#include + +namespace Feather +{ + IDMapper Registry::BLOCK_STATES; + + void Registry::Init() + { + static bool initialized = false; + if (initialized) return; + + Log::Info("Loading data/blocks.json..."); + { + using namespace rapidjson; + + std::string text; + FILE* fp = fopen("data/blocks.json", "rb"); + if (!fp) { + Log::Error("Failed to read data/blocks.json"); + return; + } + fseek(fp, 0, SEEK_END); + text.resize(ftell(fp)); + rewind(fp); + fread(&text[0], 1, text.size(), fp); + fclose(fp); + + Document doc; + doc.Parse(text.c_str()); + + + for (auto& block : doc.GetObject()) + { + //Log::Info("{}: {} states", m.name.GetString(), m.value["states"].Size()); + for (auto& stateData : block.value["states"].GetArray()) + { + std::string* name = new std::string(block.name.GetString()); + BlockState state(*name); + BLOCK_STATES.AddMapping(stateData["id"].GetInt(), state); + } + } + + Log::Info("Loaded {} block states.", BLOCK_STATES.Size()); + + //StringBuffer buf; + //Writer writer(buf); + //doc.Accept(writer); + + // FIXME: why does this crash + //Log::Info(text); + + + + } + } +} \ No newline at end of file diff --git a/src/data/Registry.h b/src/data/Registry.h new file mode 100644 index 0000000..d0c4215 --- /dev/null +++ b/src/data/Registry.h @@ -0,0 +1,16 @@ +#pragma once + +#include "IDMapper.h" +#include "block/state/BlockState.h" + + +namespace Feather +{ + class Registry + { + public: + static IDMapper BLOCK_STATES; + + static void Init(); + }; +} \ No newline at end of file diff --git a/src/meson.build b/src/meson.build index e590b28..df540a0 100644 --- a/src/meson.build +++ b/src/meson.build @@ -7,6 +7,8 @@ feather_src = [ 'nbt/NBT.cpp', + 'data/Registry.cpp', + 'network/NetworkManager.cpp', 'network/TCPListener.cpp', 'network/TCPClient.cpp', diff --git a/src/world/Palette.h b/src/world/Palette.h new file mode 100644 index 0000000..abbdee2 --- /dev/null +++ b/src/world/Palette.h @@ -0,0 +1,35 @@ +#pragma once + +#include "data/IDMapper.h" + +namespace Feather +{ + template + class Palette + { + protected: + const IDMapper& m_registry; + public: + Palette(const IDMapper& registry) : + m_registry(registry) + {} + + virtual int GetID(T& value) const = 0; + + virtual const T& ByID(int id) const = 0; + }; + + template + class GlobalPalette : public Palette + { + const T* m_defaultValue; + public: + GlobalPalette(const IDMapper& registry, const T* defaultValue) : + Palette(registry), + m_defaultValue(defaultValue) + {} + + inline virtual int GetID(T& value) const final { return m_registry.GetID(value); } + inline virtual const T& ByID(int id) const final { return m_registry.ByID(id); } + }; +} \ No newline at end of file diff --git a/src/world/PalettedContainer.h b/src/world/PalettedContainer.h new file mode 100644 index 0000000..16d0fc5 --- /dev/null +++ b/src/world/PalettedContainer.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Palette.h" + +namespace Feather +{ + // A container that maps values from a local palette to a + template + class PalettedContainer + { + const Palette& m_globalPalette; + }; +} \ No newline at end of file diff --git a/src/world/World.cpp b/src/world/World.cpp index 5079685..621ce56 100644 --- a/src/world/World.cpp +++ b/src/world/World.cpp @@ -3,6 +3,7 @@ #include "World.h" #include "nbt/NBT.h" #include "RegionFile.h" +#include "data/Registry.h" #include #include @@ -15,6 +16,11 @@ using std::stringstream; namespace Feather { + const GlobalPalette World::GLOBAL_PALETTE = GlobalPalette( + Registry::BLOCK_STATES, + new BlockState("minecraft:air") // temp + ); + static bool CheckPath(fs::path path, bool dir = false) { if (!fs::exists(path) || (dir && !fs::is_directory(path))) diff --git a/src/world/World.h b/src/world/World.h index 98d0281..e49fe91 100644 --- a/src/world/World.h +++ b/src/world/World.h @@ -1,6 +1,8 @@ #pragma once #include "Common.h" +#include "Palette.h" + #include #include @@ -9,6 +11,8 @@ namespace Feather class World { public: + // global palette of all block states + static const GlobalPalette GLOBAL_PALETTE; struct LevelData { int32_t spawnX, spawnY, spawnZ;