8 changed files with 181 additions and 9 deletions
@ -0,0 +1,19 @@
|
||||
#pragma once |
||||
|
||||
#include <string> |
||||
|
||||
namespace Feather |
||||
{ |
||||
// Represents a type of block and its behavior.
|
||||
class Block |
||||
{ |
||||
using string = std::string; |
||||
|
||||
const Identifier m_id; |
||||
|
||||
public: |
||||
Block(string&& name) : m_id(name) {} |
||||
|
||||
inline const Identifier& GetIdentifier() const { return m_id; } |
||||
}; |
||||
} |
@ -1,16 +1,23 @@
|
||||
#pragma once |
||||
|
||||
#include "IDMapper.h" |
||||
#include "RegistryMap.h" |
||||
#include "block/state/BlockState.h" |
||||
|
||||
|
||||
namespace Feather |
||||
{ |
||||
class Block; |
||||
|
||||
class Registry |
||||
{ |
||||
public: |
||||
// Maps block Identifier to Block
|
||||
static RegistryMap<Block> BLOCKS; |
||||
|
||||
// Maps numeric ID to BlockState
|
||||
static IDMapper<BlockState> BLOCK_STATES; |
||||
|
||||
static void Init(); |
||||
}; |
||||
} |
||||
} |
||||
|
@ -0,0 +1,42 @@
|
||||
#pragma once |
||||
|
||||
#include "resources/Identifier.h" |
||||
|
||||
#include <map> |
||||
|
||||
namespace Feather |
||||
{ |
||||
// Registry that maps Identifiers to objects
|
||||
// TODO: optimize ownership (move, forward, copying, etc). perhaps use pointers
|
||||
template <class T> |
||||
class RegistryMap |
||||
{ |
||||
std::map<Identifier, T> map; |
||||
|
||||
public: |
||||
inline void Register(const Identifier& id, T&& value) |
||||
{ |
||||
map.insert({ id, std::move(value) }); |
||||
} |
||||
|
||||
inline const T& Get(const Identifier& id) const { return map.at(id); } |
||||
|
||||
//inline Identifier& GetKey(T& value) const {}
|
||||
|
||||
inline size_t Size() const { return map.size(); } |
||||
}; |
||||
|
||||
template <class T> |
||||
class DefaultedRegistry : public RegistryMap<T> |
||||
{ |
||||
using string = std::string; |
||||
|
||||
const Identifier defaultKey; |
||||
T& defaultValue; |
||||
|
||||
public: |
||||
DefaultedRegistry(const string&& defaultKey) : defaultKey(Identifier(defaultKey)) {} |
||||
|
||||
|
||||
}; |
||||
} |
@ -0,0 +1,93 @@
|
||||
#pragma once |
||||
|
||||
#include "Common.h" |
||||
|
||||
#include <string> |
||||
#include <string_view> |
||||
#include <ostream> |
||||
#include <cctype> |
||||
#include <algorithm> |
||||
|
||||
namespace Feather |
||||
{ |
||||
// Namespaced ID, like "minecraft:lily_pad", also known as ResourceLocation
|
||||
class Identifier |
||||
{ |
||||
using string = std::string; |
||||
using string_view = std::string_view; |
||||
|
||||
protected: |
||||
const string m_namespace; |
||||
const string m_path; |
||||
|
||||
public: |
||||
inline static const string_view DEFAULT_NAMESPACE = "minecraft"; |
||||
inline static const char SEPARATOR = ':'; |
||||
|
||||
|
||||
Identifier(const string&& ns, const string&& path) : |
||||
m_namespace(ns.empty() ? DEFAULT_NAMESPACE : ns), |
||||
m_path(path) |
||||
{ |
||||
Assert(IsValidNamespace(m_namespace), "Identifier namespace contains non [a-z0-9_.-] character: {}", m_namespace); |
||||
Assert(IsValidPath(m_path), "Identifier path contains non [a-z0-9/._-] character: {}", m_path); |
||||
} |
||||
|
||||
Identifier(const string& id) : Identifier(id, id.find(SEPARATOR)) {} |
||||
|
||||
inline const string_view& GetNamespace() const { return m_namespace; } |
||||
inline const string_view& GetPath() const { return m_path; } |
||||
|
||||
|
||||
|
||||
// Operators
|
||||
|
||||
inline bool operator==(const Identifier& id) const { return this == &id || (m_namespace == id.m_namespace && m_path == id.m_path); } |
||||
|
||||
inline bool operator<(const Identifier& id) const { return this != &id && (m_path < id.m_path || m_namespace < id.m_namespace); } |
||||
|
||||
friend inline std::ostream& operator<<(std::ostream& st, const Identifier& id) |
||||
{ |
||||
return st << id.m_namespace.data() << ":" << id.m_path.data(); |
||||
} |
||||
protected: |
||||
|
||||
// Construct an Identifier having found the separator character, if any
|
||||
Identifier(const string& id, const size_t split) : Identifier( |
||||
split == string::npos ? "" : id.substr(0, split), |
||||
split == string::npos ? id : id.substr(split + 1)) |
||||
{} |
||||
|
||||
// Identifiers: 0-9 a-z _ : / . -
|
||||
inline static bool AllowedChar(char c) |
||||
{ |
||||
return ('0' <= c && c <= '9') || ('a' <= c && c <= 'z') || c == '_' || c == ':' || c == '/' || c == '.' || c == '-'; |
||||
} |
||||
|
||||
// Paths cannot contain :
|
||||
inline static bool IsValidPath(const string& ns) |
||||
{ |
||||
return std::all_of(ns.begin(), ns.end(), [](char c) { return AllowedChar(c) && c != ':'; }); |
||||
} |
||||
|
||||
// Namespaces cannot contain : or /
|
||||
inline static bool IsValidNamespace(const string& ns) |
||||
{ |
||||
return std::all_of(ns.begin(), ns.end(), [](char c) { return AllowedChar(c) && c != '/' && c != ':'; }); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
template <> |
||||
struct std::hash<Feather::Identifier> |
||||
{ |
||||
size_t operator()(const Feather::Identifier& id) const |
||||
{ |
||||
using std::hash; |
||||
using std::string_view; |
||||
|
||||
// based on Mojang's ResourceLocation.hashCode()
|
||||
return 31 * hash<string_view>{}(id.GetNamespace()) + hash<string_view>{}(id.GetPath()); |
||||
} |
||||
}; |
||||
|
Loading…
Reference in new issue