iw5-mod/src/game/demonware/i_service.hpp
2018-12-27 17:02:06 +01:00

80 lines
1.9 KiB
C++

#pragma once
#include "i_server.hpp"
namespace demonware
{
class i_service
{
public:
virtual ~i_service() = default;
i_service() = default;
// Copying or moving a service object won't work
// as the callbacks are bound to the initial object pointer
// Therefore, you should never declare copy/move
// constructors when inheriting from IService!
i_service(i_service&&) = delete;
i_service(const i_service&) = delete;
i_service& operator=(const i_service&) = delete;
typedef std::function<void(i_server*, byte_buffer*)> callback;
virtual uint16_t getType() = 0;
virtual void call_service(i_server* server, const std::string& data)
{
std::lock_guard _(this->mutex_);
byte_buffer buffer(data);
buffer.read_byte(&this->sub_type_);
printf("DW: Handling subservice of type %d\n", this->sub_type_);
const auto callback = this->callbacks.find(this->sub_type_);
if (callback != this->callbacks.end())
{
callback->second(server, &buffer);
}
else
{
printf("DW: Missing subservice %d for type %d\n", this->sub_type_, this->getType());
}
}
protected:
std::map<uint8_t, callback> callbacks{};
template<typename Class, typename T, typename... Args>
void register_service(const uint8_t type, T(Class::*callback)(Args ...) const)
{
this->callbacks[type] = [this, callback](Args... args) -> T
{
return (reinterpret_cast<Class*>(this)->*callback)(args...);
};
}
template<typename Class, typename T, typename... Args>
void register_service(const uint8_t type, T(Class::*callback)(Args ...))
{
this->callbacks[type] = [this, callback](Args... args) -> T
{
return (reinterpret_cast<Class*>(this)->*callback)(args...);
};
}
uint8_t get_sub_type() const { return this->sub_type_; }
private:
std::mutex mutex_;
uint8_t sub_type_{};
};
template<uint16_t Type>
class i_generic_service : public i_service
{
public:
uint16_t getType() override { return Type; }
};
}