diff --git a/src/ll/api/command/CommandHandle.cpp b/src/ll/api/command/CommandHandle.cpp index d0773efa16..89edd0d9a2 100644 --- a/src/ll/api/command/CommandHandle.cpp +++ b/src/ll/api/command/CommandHandle.cpp @@ -14,9 +14,9 @@ struct CommandHandle::Impl { gsl::not_null registrar; gsl::not_null signature; bool owned; + std::recursive_mutex mutex; }; - CommandHandle::CommandHandle(CommandRegistrar& registrar, CommandRegistry::Signature* signature, bool owned) : impl(std::make_unique(®istrar, signature, owned)) {} @@ -26,8 +26,9 @@ CommandHandle::~CommandHandle() = default; CommandRegistrar& CommandHandle::getRegistrar() { return *impl->registrar; } void CommandHandle::registerOverload(OverloadData&& data) { - auto& overload = impl->signature->overloads.emplace_back(CommandVersion{}, data.getFactory()); - overload.params = data.moveParams(); + std::lock_guard lock{impl->mutex}; + auto& overload = impl->signature->overloads.emplace_back(CommandVersion{}, data.getFactory()); + overload.params = data.moveParams(); impl->registrar->getRegistry().registerOverloadInternal(*impl->signature, overload); } char const* CommandHandle::addText(std::string_view text) { return impl->registrar->addText(*this, text); } diff --git a/src/ll/api/command/CommandRegistrar.cpp b/src/ll/api/command/CommandRegistrar.cpp index 6cba79a649..ec1d7e4d47 100644 --- a/src/ll/api/command/CommandRegistrar.cpp +++ b/src/ll/api/command/CommandRegistrar.cpp @@ -21,6 +21,7 @@ namespace ll::command { struct CommandRegistrar::Impl { std::unordered_map commands; std::unordered_map textWithRef; + std::recursive_mutex mutex; }; CommandRegistrar::CommandRegistrar() : impl(std::make_unique()) {} @@ -38,11 +39,15 @@ CommandHandle& CommandRegistrar::getOrCreateCommand( CommandFlag flag, std::weak_ptr /*plugin*/ ) { - auto& registry = getRegistry(); - auto signature = registry.findCommand(name); + std::lock_guard lock{impl->mutex}; + auto& registry = getRegistry(); + auto signature = registry.findCommand(name); if (!signature) { registry.registerCommand(name, description.c_str(), requirement, flag); signature = registry.findCommand(name); + if (!signature) { + throw std::runtime_error{"failed to register command " + name}; + } return impl->commands.try_emplace(name, *this, signature, true).first->second; } else if (impl->commands.contains(signature->name)) { return impl->commands.at(signature->name); @@ -124,7 +129,8 @@ bool CommandRegistrar::setSoftEnumValues(std::string const& name, std::vectormutex}; + std::string storedName{"ll_text_enum_name_"}; storedName += text; if (impl->textWithRef.contains(storedName)) { impl->textWithRef.at(storedName)++; diff --git a/src/ll/api/command/OverloadData.cpp b/src/ll/api/command/OverloadData.cpp index 1e2c2b1e12..e620cc65c6 100644 --- a/src/ll/api/command/OverloadData.cpp +++ b/src/ll/api/command/OverloadData.cpp @@ -22,16 +22,24 @@ struct OverloadData::Impl { gsl::not_null handle; CommandRegistry::FactoryFn factory{}; std::vector params; + std::recursive_mutex mutex; }; OverloadData::OverloadData(CommandHandle& handle) : impl(std::make_unique(&handle)) {} OverloadData::~OverloadData() = default; -CommandRegistry::FactoryFn OverloadData::getFactory() { return impl->factory; } -std::vector OverloadData::moveParams() { return std::move(impl->params); } +CommandRegistry::FactoryFn OverloadData::getFactory() { + std::lock_guard lock{impl->mutex}; + return impl->factory; +} +std::vector OverloadData::moveParams() { + std::lock_guard lock{impl->mutex}; + return std::move(impl->params); +} CommandParameterData& OverloadData::back() { + std::lock_guard lock{impl->mutex}; if (!impl->params.empty()) { return impl->params.back(); } else { @@ -49,7 +57,8 @@ CommandParameterData& OverloadData::addParamImpl( int flagOffset, bool optional ) { - auto& param = + std::lock_guard lock{impl->mutex}; + auto& param = impl->params.emplace_back(id, parser, std::string{name}, type, enumNameOrPostfix, offset, optional, flagOffset); if (id == Bedrock::type_id() || id == Bedrock::type_id()) { @@ -61,6 +70,7 @@ CommandParameterData& OverloadData::addParamImpl( return param; } CommandParameterData& OverloadData::addTextImpl(std::string_view text, int offset) { + std::lock_guard lock{impl->mutex}; return addParamImpl( Bedrock::type_id(), &CommandRegistry::parse, @@ -74,6 +84,7 @@ CommandParameterData& OverloadData::addTextImpl(std::string_view text, int offse } void OverloadData::setFactory(CommandRegistry::FactoryFn fn) { + std::lock_guard lock{impl->mutex}; impl->factory = fn; impl->handle->registerOverload(std::move(*this)); } diff --git a/src/ll/core/dimension/CustomDimensionConfig.cpp b/src/ll/core/dimension/CustomDimensionConfig.cpp index a823245c65..ec92c48731 100644 --- a/src/ll/core/dimension/CustomDimensionConfig.cpp +++ b/src/ll/core/dimension/CustomDimensionConfig.cpp @@ -19,7 +19,7 @@ void setDimensionConfigPath() { if (!ll::service::getLevel()) { throw std::runtime_error("Level nullptr"); } - dimensionConfigPath /= string_utils::str2u8str(ll::service::getLevel()->getLevelName()); + dimensionConfigPath /= string_utils::str2u8str(ll::service::getLevel()->getLevelData().getLevelName()); dimensionConfigPath /= u8"dimension_config.json"; } diff --git a/src/mc/world/actor/Mob.cpp b/src/mc/world/actor/Mob.cpp new file mode 100644 index 0000000000..136b184b72 --- /dev/null +++ b/src/mc/world/actor/Mob.cpp @@ -0,0 +1,6 @@ +#include "mc/world/actor/Mob.h" + +void Mob::refreshInventory() { + sendInventory(true); + sendArmor(std::bitset<4>{"1111"}); +} diff --git a/src/mc/world/actor/Mob.h b/src/mc/world/actor/Mob.h index 82e4a823d8..1c23e6643c 100644 --- a/src/mc/world/actor/Mob.h +++ b/src/mc/world/actor/Mob.h @@ -34,10 +34,7 @@ class BodyControl; class Mob : public ::Actor { public: - inline void refreshInventory() { - sendInventory(true); - sendArmor(std::bitset<4>{"1111"}); - } + LLAPI void refreshInventory(); // prevent constructor by default Mob& operator=(Mob const&); diff --git a/src/mc/world/actor/player/Player.cpp b/src/mc/world/actor/player/Player.cpp index 3f32cf909a..5e90fd1398 100644 --- a/src/mc/world/actor/player/Player.cpp +++ b/src/mc/world/actor/player/Player.cpp @@ -39,6 +39,18 @@ optional_ref Player::getConnectionRequest() const { return ll::service::getServerNetworkHandler()->fetchConnectionRequest(getNetworkIdentifier()); } +NetworkIdentifier const& Player::getNetworkIdentifier() const { return getUserEntityIdentifier().mNetworkId; } + +optional_ref Player::getCertificate() const { return getUserEntityIdentifier().mCertificate.get(); } + +SubClientId const& Player::getClientSubId() const { return getUserEntityIdentifier().mClientSubId; } + +mce::UUID const& Player::getUuid() const { return getUserEntityIdentifier().mClientUUID; } + +std::string Player::getIPAndPort() const { return getNetworkIdentifier().getIPAndPort(); } + +bool Player::isOperator() const { return getPlayerPermissionLevel() == PlayerPermissionLevel::Operator; } + std::string Player::getLocaleName() const { if (auto request = getConnectionRequest()) { return request->mRawToken->mDataInfo["LanguageCode"].asString(""); diff --git a/src/mc/world/actor/player/Player.h b/src/mc/world/actor/player/Player.h index 41bd388ede..4d96bd59e3 100644 --- a/src/mc/world/actor/player/Player.h +++ b/src/mc/world/actor/player/Player.h @@ -102,32 +102,30 @@ class Player : public ::Mob { LLNDAPI optional_ref getConnectionRequest() const; - [[nodiscard]] NetworkIdentifier const& getNetworkIdentifier() const { return getUserEntityIdentifier().mNetworkId; } + LLNDAPI NetworkIdentifier const& getNetworkIdentifier() const; - [[nodiscard]] optional_ref getCertificate() const { - return getUserEntityIdentifier().mCertificate.get(); - } + LLNDAPI optional_ref getCertificate() const; - [[nodiscard]] SubClientId const& getClientSubId() const { return getUserEntityIdentifier().mClientSubId; } + LLNDAPI SubClientId const& getClientSubId() const; /** * @brief Get the player's uuid * @return Player's uuid */ - [[nodiscard]] mce::UUID const& getUuid() const { return getUserEntityIdentifier().mClientUUID; } + LLNDAPI mce::UUID const& getUuid() const; /** * @brief Get the player's IP and port * @return player's IP and port */ - [[nodiscard]] std::string getIPAndPort() const { return getNetworkIdentifier().getIPAndPort(); } + LLNDAPI std::string getIPAndPort() const; /** * @brief Determine if a player is an administrator of the server * @return Returns true if the player is an administrator of the server; otherwise returns false * @warning Custom permissions are not considered administrators */ - [[nodiscard]] bool isOperator() const { return getPlayerPermissionLevel() == PlayerPermissionLevel::Operator; } + LLNDAPI bool isOperator() const; /** * @brief Get the player's real in-game nickname diff --git a/src/mc/world/events/ServerInstanceEventCoordinator.h b/src/mc/world/events/ServerInstanceEventCoordinator.h index 6661e3936f..34c000b90d 100644 --- a/src/mc/world/events/ServerInstanceEventCoordinator.h +++ b/src/mc/world/events/ServerInstanceEventCoordinator.h @@ -7,6 +7,8 @@ #include "mc/events/ServerInstanceGameplayEvent.h" #include "mc/world/events/EventRef.h" +class ServerInstance; + class ServerInstanceEventCoordinator { public: // prevent constructor by default diff --git a/src/mc/world/level/Level.h b/src/mc/world/level/Level.h index 915f9024da..321cf06ce4 100644 --- a/src/mc/world/level/Level.h +++ b/src/mc/world/level/Level.h @@ -51,8 +51,6 @@ class ServerLevel; class Level : public ILevel, public BlockSourceListener, public IWorldRegistriesProvider { public: - [[nodiscard]] std::string const& getLevelName() const { return getLevelData().getLevelName(); } - [[nodiscard]] ServerLevel& asServer() { return *reinterpret_cast(this); } // prevent constructor by default