Skip to content

Commit b71df7c

Browse files
authored
refactor: replace string-based registry lookup with std::type_index (#360)
Use std::type_index(typeid(T)) to key registries instead of raw strings. Remove ENDSTONE_REGISTRY_TYPE macro and T::RegistryType from all types. Add type-erased virtuals to IRegistry (get0, forEach0, getTypeId) so Python bindings use a single opaque Registry class via IRegistry directly, extracting std::type_info from py::type to call Server::_getRegistry.
1 parent 7895176 commit b71df7c

11 files changed

Lines changed: 97 additions & 112 deletions

File tree

endstone/__init__.pyi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -797,3 +797,4 @@ class Registry(typing.Generic[_T]):
797797
def __getitem__(self, key: str) -> _T: ...
798798
def __iter__(self) -> list: ...
799799
def __contains__(self, key: str) -> bool: ...
800+
def __len__(self) -> int: ...

include/endstone/actor/actor_type.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,5 @@ class ActorType : public Registry<ActorType>::Type {
168168
static constexpr auto WitherSkullDangerous = ActorTypeId::minecraft("wither_skull_dangerous");
169169
static constexpr auto XpBottle = ActorTypeId::minecraft("xp_bottle");
170170
static constexpr auto XpOrb = ActorTypeId::minecraft("xp_orb");
171-
172-
ENDSTONE_REGISTRY_TYPE(ActorType)
173-
};
171+
``};
174172
} // namespace endstone

include/endstone/block/block_type.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@ class BlockType : public Registry<BlockType>::Type {
3131
public:
3232
static constexpr auto Air = BlockTypeId::minecraft("air");
3333

34-
ENDSTONE_REGISTRY_TYPE(BlockType)
35-
3634
/**
3735
* @brief Returns true if this BlockType has a corresponding ItemType.
3836
*

include/endstone/enchantments/enchantment.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ class ItemStack;
2121
using EnchantmentId = Identifier<class Enchantment>;
2222
class Enchantment : public Registry<Enchantment>::Type {
2323
public:
24-
ENDSTONE_REGISTRY_TYPE(Enchantment)
2524
/**
2625
* @brief Provides protection against environmental damage
2726
*/

include/endstone/inventory/item_type.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@ class ItemType : public Registry<ItemType>::Type {
2626
public:
2727
static constexpr auto Air = ItemTypeId::minecraft("air");
2828

29-
ENDSTONE_REGISTRY_TYPE(ItemType)
30-
3129
/**
3230
* @brief Get the translation key, suitable for use in a translation component.
3331
*

include/endstone/registry.h

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,20 @@
2626
#include "server.h"
2727

2828
namespace endstone {
29+
namespace python {
30+
class PyRegistry;
31+
}
32+
2933
class IRegistry {
3034
public:
3135
virtual ~IRegistry() = default;
36+
[[nodiscard]] virtual std::size_t size() const = 0;
37+
38+
protected:
39+
friend class python::PyRegistry;
40+
[[nodiscard]] virtual const void *get0(std::string_view id) const noexcept = 0;
41+
virtual void forEach0(std::function<bool(const void *)> func) const = 0;
42+
[[nodiscard]] virtual const std::type_info &getTypeId() const noexcept = 0;
3243
};
3344

3445
/**
@@ -147,16 +158,21 @@ class Registry : public IRegistry {
147158
*/
148159
virtual void forEach(std::function<bool(const T &)> func) const = 0;
149160

150-
/**
151-
* @brief Returns the number of entries in this registry.
152-
*
153-
* @return std::size_t The number of entries.
154-
*/
155-
[[nodiscard]] virtual std::size_t size() const = 0;
156-
};
161+
[[nodiscard]] std::size_t size() const override = 0;
157162

158-
#define ENDSTONE_REGISTRY_TYPE(type) static constexpr auto RegistryType = #type;
163+
private:
164+
[[nodiscard]] const void *get0(std::string_view id) const noexcept override
165+
{
166+
return get(Identifier<T>(id));
167+
}
159168

169+
void forEach0(std::function<bool(const void *)> func) const override
170+
{
171+
forEach([&func](const T &elem) { return func(&elem); });
172+
}
173+
174+
[[nodiscard]] const std::type_info &getTypeId() const noexcept override { return typeid(T); }
175+
};
160176
} // namespace endstone
161177

162178
template <typename T>

include/endstone/server.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <stdexcept>
2121
#include <string>
2222
#include <string_view>
23+
#include <typeinfo>
2324
#include <utility>
2425
#include <vector>
2526

@@ -406,12 +407,12 @@ class Server {
406407
*
407408
* @return the corresponding registry or null if not present
408409
*/
409-
[[nodiscard]] virtual IRegistry *_getRegistry(const std::string &type) const = 0;
410+
[[nodiscard]] virtual IRegistry *_getRegistry(const std::type_info &type) const = 0;
410411

411412
template <typename T>
412413
[[nodiscard]] const Registry<T> &getRegistry() const
413414
{
414-
return *static_cast<Registry<T> *>(_getRegistry(T::RegistryType));
415+
return *static_cast<Registry<T> *>(_getRegistry(typeid(T)));
415416
}
416417

417418
/**

src/endstone/core/server.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -191,10 +191,10 @@ void EndstoneServer::setLevel(::Level &level)
191191

192192
void EndstoneServer::initRegistries()
193193
{
194-
registries_["ActorType"] = EndstoneRegistry<ActorType, std::string>::create();
195-
registries_["BlockType"] = EndstoneRegistry<BlockType, ::BlockType>::create();
196-
registries_["Enchantment"] = EndstoneRegistry<Enchantment, ::Enchant>::create();
197-
registries_["ItemType"] = EndstoneRegistry<ItemType, ::Item>::create();
194+
registries_[typeid(ActorType)] = EndstoneRegistry<ActorType, std::string>::create();
195+
registries_[typeid(BlockType)] = EndstoneRegistry<BlockType, ::BlockType>::create();
196+
registries_[typeid(Enchantment)] = EndstoneRegistry<Enchantment, ::Enchant>::create();
197+
registries_[typeid(ItemType)] = EndstoneRegistry<ItemType, ::Item>::create();
198198
BlockStateRegistry::get().unregisterBlockStates();
199199
::BlockState::forEachState([](const auto &state) {
200200
BlockStateRegistry::get().registerBlockState(state);
@@ -639,9 +639,9 @@ ServiceManager &EndstoneServer::getServiceManager() const
639639
return *service_manager_;
640640
}
641641

642-
IRegistry *EndstoneServer::_getRegistry(const std::string &type) const
642+
IRegistry *EndstoneServer::_getRegistry(const std::type_info &type) const
643643
{
644-
const auto it = registries_.find(type);
644+
const auto it = registries_.find(std::type_index(type));
645645
if (registries_.end() == it) {
646646
return nullptr;
647647
}

src/endstone/core/server.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <chrono>
1818
#include <memory>
1919
#include <string>
20+
#include <typeindex>
2021

2122
#include "bedrock/resources/resource_pack_repository_interface.h"
2223
#include "bedrock/server/server_instance.h"
@@ -110,7 +111,7 @@ class EndstoneServer : public Server {
110111
[[nodiscard]] PlayerBanList &getBanList() const override;
111112
[[nodiscard]] IpBanList &getIpBanList() const override;
112113
[[nodiscard]] ServiceManager &getServiceManager() const override;
113-
[[nodiscard]] IRegistry *_getRegistry(const std::string &type) const override;
114+
[[nodiscard]] IRegistry *_getRegistry(const std::type_info &type) const override;
114115
[[nodiscard]] MapView *getMap(std::int64_t id) const override;
115116
[[nodiscard]] MapView &createMap(const Dimension &dimension) const override;
116117

@@ -152,7 +153,7 @@ class EndstoneServer : public Server {
152153
std::unique_ptr<EndstoneScheduler> scheduler_;
153154
std::unique_ptr<EndstoneCommandMap> command_map_;
154155
std::unique_ptr<EndstoneLevel> level_;
155-
std::unordered_map<std::string, std::unique_ptr<IRegistry>> registries_;
156+
std::unordered_map<std::type_index, std::unique_ptr<IRegistry>> registries_;
156157
std::shared_ptr<EndstoneScoreboard> scoreboard_;
157158
std::unique_ptr<EndstoneMetrics> metrics_;
158159
std::unordered_map<UUID, std::shared_ptr<EndstoneScoreboard>> player_boards_;

src/endstone/python/endstone_python.cpp

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,8 @@ PYBIND11_MODULE(_python, m) // NOLINT(*-use-anonymous-namespace)
133133
auto block = py::class_<Block>(m_block, "Block", "Represents a block.");
134134
auto command_sender = py_class<CommandSender>(m_command, "CommandSender", "Represents a command sender.");
135135
auto actor = py_class<Actor>(m_actor, "Actor", "Represents a base actor in the level.");
136-
auto mob = py_class<Mob>(m_actor, "Mob",
137-
"Represents a mobile entity (i.e. living entity), such as a monster or player.");
136+
auto mob =
137+
py_class<Mob>(m_actor, "Mob", "Represents a mobile entity (i.e. living entity), such as a monster or player.");
138138
py::class_<OfflinePlayer>(
139139
m, "OfflinePlayer",
140140
"Represents a reference to a player identity and the data belonging to a player that is stored on the disk and "
@@ -274,7 +274,14 @@ void init_logger(py::module &m)
274274

275275
void init_registry(py::module_ &m)
276276
{
277-
bind_registries(m, RegistryTypes{});
277+
py::class_<PyRegistry>(m, "Registry")
278+
.def("get", &PyRegistry::get, py::arg("id"), "Get the object by its identifier.")
279+
.def("get_or_throw", &PyRegistry::getOrThrow, py::arg("id"),
280+
"Get the object by its identifier or throw if missing.")
281+
.def("__getitem__", &PyRegistry::getOrThrow, py::arg("id"))
282+
.def("__iter__", &PyRegistry::iter)
283+
.def("__contains__", &PyRegistry::contains, py::arg("id"))
284+
.def("__len__", &PyRegistry::size);
278285
}
279286

280287
void init_server(py::class_<Server> &server)
@@ -303,8 +310,18 @@ void init_server(py::class_<Server> &server)
303310
"Gets the service manager.")
304311
.def(
305312
"get_registry",
306-
[](const Server &self, const py::type &t) -> py::object { return get_registry(self, t, RegistryTypes{}); },
307-
py::arg("type"), py::return_value_policy::reference, "Returns the registry for all the enchantments.")
313+
[](const Server &self, const py::type &t) -> py::object {
314+
auto *type_info = py::detail::get_type_info(reinterpret_cast<PyTypeObject *>(t.ptr()));
315+
if (!type_info) {
316+
return py::none();
317+
}
318+
auto *registry = self._getRegistry(*type_info->cpptype);
319+
if (!registry) {
320+
return py::none();
321+
}
322+
return py::cast(PyRegistry(*registry));
323+
},
324+
py::arg("type"), "Returns the registry for the given type.")
308325
.def_property_readonly("level", &Server::getLevel, py::return_value_policy::reference_internal,
309326
"Gets the server level.")
310327
.def_property_readonly("online_players", &Server::getOnlinePlayers, py::return_value_policy::reference_internal,

0 commit comments

Comments
 (0)