parent
89956ddf6a
commit
85b5b4e820
|
@ -19,12 +19,19 @@ configure_file(
|
||||||
executable(
|
executable(
|
||||||
'mornelune',
|
'mornelune',
|
||||||
sources: [
|
sources: [
|
||||||
|
# Core
|
||||||
'src/main.cpp',
|
'src/main.cpp',
|
||||||
|
|
||||||
'src/Game.cpp',
|
'src/Game.cpp',
|
||||||
|
'src/Services.cpp',
|
||||||
|
'src/Service.cpp',
|
||||||
|
|
||||||
|
# Logs
|
||||||
'src/logs/Logs.cpp',
|
'src/logs/Logs.cpp',
|
||||||
'src/logs/FileLogs.cpp',
|
'src/logs/FileLogs.cpp',
|
||||||
|
|
||||||
|
# Events
|
||||||
|
'src/events/Events.cpp',
|
||||||
|
'src/events/Event.cpp',
|
||||||
],
|
],
|
||||||
dependencies: [
|
dependencies: [
|
||||||
],
|
],
|
||||||
|
|
10
src/Game.cpp
10
src/Game.cpp
|
@ -1,9 +1,11 @@
|
||||||
#include "Game.hpp"
|
#include "Game.hpp"
|
||||||
|
#include "logs/FileLogs.hpp"
|
||||||
|
#include "src/events/Events.hpp"
|
||||||
|
#include "src/logs/Logs.hpp"
|
||||||
|
|
||||||
namespace ml
|
namespace ml
|
||||||
{
|
{
|
||||||
/*explicit*/ Game::Game(std::shared_ptr<Logs> logs)
|
/*explicit*/ Game::Game()
|
||||||
: m_logs { logs }
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,11 +15,11 @@ namespace ml
|
||||||
|
|
||||||
void Game::start()
|
void Game::start()
|
||||||
{
|
{
|
||||||
m_logs->log(LEVEL_DEBUG, "game started");
|
ML_SYS(FileLogs)->log(LEVEL_INFO, "game started");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::stop()
|
void Game::stop()
|
||||||
{
|
{
|
||||||
m_logs->log(LEVEL_DEBUG, "game stopped");
|
ML_SYS(FileLogs)->log(LEVEL_INFO, "game stopped");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,24 +2,23 @@
|
||||||
#define ml_GAME_HPP
|
#define ml_GAME_HPP
|
||||||
|
|
||||||
#include "commons.hpp"
|
#include "commons.hpp"
|
||||||
#include "logs/Logs.hpp"
|
#include "Services.hpp"
|
||||||
|
|
||||||
namespace ml
|
namespace ml
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Manage services and game state.
|
* Manage game state.
|
||||||
**/
|
**/
|
||||||
class Game
|
class Game
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit Game(std::shared_ptr<Logs> logs);
|
explicit Game();
|
||||||
virtual ~Game();
|
virtual ~Game();
|
||||||
|
|
||||||
void start();
|
void start();
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<Logs> m_logs;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
#include "Service.hpp"
|
||||||
|
|
||||||
|
namespace ml
|
||||||
|
{
|
||||||
|
/*explicit*/ Service::Service()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*virtual*/ Service::~Service()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef ml_SERVICE_HPP
|
||||||
|
#define ml_SERVICE_HPP
|
||||||
|
|
||||||
|
namespace ml
|
||||||
|
{
|
||||||
|
class Service
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Service();
|
||||||
|
virtual ~Service();
|
||||||
|
|
||||||
|
virtual void init() {};
|
||||||
|
virtual void free() {};
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,24 @@
|
||||||
|
#include "Services.hpp"
|
||||||
|
|
||||||
|
namespace ml
|
||||||
|
{
|
||||||
|
/*static*/ std::shared_ptr<Services> Services::instance = nullptr;
|
||||||
|
|
||||||
|
/*static*/ std::shared_ptr<Services> Services::get()
|
||||||
|
{
|
||||||
|
if (Services::instance == nullptr)
|
||||||
|
{
|
||||||
|
Services::instance = std::shared_ptr<Services>(new Services);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Services::instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*explicit*/ Services::Services()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*virtual*/ Services::~Services()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
#ifndef ml_SERVICES_HPP
|
||||||
|
#define ml_SERVICES_HPP
|
||||||
|
|
||||||
|
#include "commons.hpp"
|
||||||
|
#include "Service.hpp"
|
||||||
|
|
||||||
|
namespace ml
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Manage game services.
|
||||||
|
**/
|
||||||
|
class Services
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static std::shared_ptr<Services> get();
|
||||||
|
|
||||||
|
virtual ~Services();
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
size_t id();
|
||||||
|
|
||||||
|
template<typename T, typename... Args>
|
||||||
|
void add(Args... args);
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
std::shared_ptr<T> get();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static std::shared_ptr<Services> instance;
|
||||||
|
|
||||||
|
size_t m_id = 0;
|
||||||
|
std::unordered_map<size_t,
|
||||||
|
std::shared_ptr<Service>> m_services;
|
||||||
|
|
||||||
|
explicit Services();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
size_t Services::id()
|
||||||
|
{
|
||||||
|
static size_t i = m_id++;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename... Args>
|
||||||
|
void Services::add(Args... args)
|
||||||
|
{
|
||||||
|
auto service = std::make_shared<T>(args...);
|
||||||
|
size_t i = id<T>();
|
||||||
|
m_services[i] = service;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
std::shared_ptr<T> Services::get()
|
||||||
|
{
|
||||||
|
size_t i = id<T>();
|
||||||
|
return std::static_pointer_cast<T>(m_services[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,12 +1,19 @@
|
||||||
#ifndef ml_COMMONS_HPP
|
#ifndef ml_COMMONS_HPP
|
||||||
#define ml_COMMONS_HPP
|
#define ml_COMMONS_HPP
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
#define ML ml::Services::get()
|
||||||
|
#define ML_SYS(SYSTEM) ML->get<SYSTEM>()
|
||||||
|
|
||||||
#define ML_GEN_ENUM(X) X
|
#define ML_GEN_ENUM(X) X
|
||||||
#define ML_GEN_STRING(X) #X
|
#define ML_GEN_STRING(X) #X
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
#include "Event.hpp"
|
||||||
|
|
||||||
|
namespace ml
|
||||||
|
{
|
||||||
|
/*explicit*/ Event::Event(EventType type)
|
||||||
|
: m_type { type }
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*virtual*/ Event::~Event()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
#ifndef ml_EVENT_HPP
|
||||||
|
#define ml_EVENT_HPP
|
||||||
|
|
||||||
|
#include "../commons.hpp"
|
||||||
|
|
||||||
|
#define EVENT_TYPES(G) G(EVENT_QUIT)
|
||||||
|
|
||||||
|
namespace ml
|
||||||
|
{
|
||||||
|
ML_ENUM(EventType, EVENT_TYPES);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A generic event type.
|
||||||
|
* @see Events
|
||||||
|
**/
|
||||||
|
class Event
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Event(EventType type);
|
||||||
|
virtual ~Event();
|
||||||
|
|
||||||
|
EventType type() const { return m_type; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
EventType m_type;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,8 @@
|
||||||
|
#include "Events.hpp"
|
||||||
|
|
||||||
|
namespace ml
|
||||||
|
{
|
||||||
|
/*virtual*/ Events::~Events()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,119 @@
|
||||||
|
#ifndef ml_EVENTS_HPP
|
||||||
|
#define ml_EVENTS_HPP
|
||||||
|
|
||||||
|
#include "../commons.hpp"
|
||||||
|
#include "../Service.hpp"
|
||||||
|
#include "../Services.hpp"
|
||||||
|
#include "../logs/FileLogs.hpp"
|
||||||
|
|
||||||
|
#include "Event.hpp"
|
||||||
|
|
||||||
|
namespace ml
|
||||||
|
{
|
||||||
|
using listener_t = std::function<void(Event const&)>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controls event listeners lifetime.
|
||||||
|
* @see ListenerEntry
|
||||||
|
**/
|
||||||
|
struct EventToken {};
|
||||||
|
|
||||||
|
struct ListenerEntry {
|
||||||
|
listener_t listener;
|
||||||
|
std::optional<std::weak_ptr<EventToken>> token;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Publish events to subscribed listeners.
|
||||||
|
* @see Event
|
||||||
|
* @see Service
|
||||||
|
**/
|
||||||
|
class Events: public Service
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Events() = default;
|
||||||
|
virtual ~Events();
|
||||||
|
|
||||||
|
template <typename EventTy>
|
||||||
|
size_t get();
|
||||||
|
|
||||||
|
template <typename EventTy>
|
||||||
|
void subscribe(listener_t listener,
|
||||||
|
std::shared_ptr<EventToken> token=nullptr);
|
||||||
|
|
||||||
|
template <typename EventTy, typename ObjectTy>
|
||||||
|
void subscribe(ObjectTy* instance,
|
||||||
|
void (ObjectTy::*method)(Event const&),
|
||||||
|
std::shared_ptr<EventToken> token=nullptr);
|
||||||
|
|
||||||
|
template <typename EventTy>
|
||||||
|
void publish(EventTy const& event);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unordered_map<size_t,
|
||||||
|
std::vector<ListenerEntry>> m_listeners;
|
||||||
|
size_t m_id = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename EventTy>
|
||||||
|
size_t Events::get()
|
||||||
|
{
|
||||||
|
static size_t i = m_id++;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename EventTy>
|
||||||
|
void Events::subscribe(listener_t listener,
|
||||||
|
std::shared_ptr<EventToken> token)
|
||||||
|
{
|
||||||
|
size_t index = get<EventTy>();
|
||||||
|
|
||||||
|
ListenerEntry entry;
|
||||||
|
entry.listener = listener;
|
||||||
|
|
||||||
|
if (token)
|
||||||
|
{
|
||||||
|
entry.token = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto itr = m_listeners.find(index);
|
||||||
|
itr == std::end(m_listeners))
|
||||||
|
{
|
||||||
|
m_listeners.insert({index, {entry}});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
itr->second.push_back(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename EventTy, typename ObjectTy>
|
||||||
|
void Events::subscribe(ObjectTy* instance,
|
||||||
|
void (ObjectTy::*method)(Event const&),
|
||||||
|
std::shared_ptr<EventToken> token)
|
||||||
|
{
|
||||||
|
auto listener = std::bind(method, instance, std::placeholders::_1);
|
||||||
|
subscribe<EventTy>(listener, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename EventTy>
|
||||||
|
void Events::publish(EventTy const& event)
|
||||||
|
{
|
||||||
|
size_t index = get<EventTy>();
|
||||||
|
std::string name = (EventTypeStr[event.type()]
|
||||||
|
+ std::strlen("EVENT_"));
|
||||||
|
|
||||||
|
ML_SYS(FileLogs)->log(LEVEL_DEBUG, "event: " + name);
|
||||||
|
|
||||||
|
for (auto& listener: m_listeners.at(index))
|
||||||
|
{
|
||||||
|
if (listener.token == std::nullopt
|
||||||
|
|| listener.token->lock())
|
||||||
|
{
|
||||||
|
listener.listener(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -24,6 +24,7 @@ namespace ml
|
||||||
switch (level)
|
switch (level)
|
||||||
{
|
{
|
||||||
case LEVEL_DEBUG: color = "34"; break;
|
case LEVEL_DEBUG: color = "34"; break;
|
||||||
|
case LEVEL_INFO: color = "32"; break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw log_error {std::string("cannot find color for log level '")
|
throw log_error {std::string("cannot find color for log level '")
|
||||||
|
|
|
@ -2,8 +2,9 @@
|
||||||
#define ml_LOGS_HPP
|
#define ml_LOGS_HPP
|
||||||
|
|
||||||
#include "../commons.hpp"
|
#include "../commons.hpp"
|
||||||
|
#include "../Service.hpp"
|
||||||
|
|
||||||
#define LOG_LEVELS(G) G(LEVEL_DEBUG)
|
#define LOG_LEVELS(G) G(LEVEL_DEBUG), G(LEVEL_INFO)
|
||||||
|
|
||||||
namespace ml
|
namespace ml
|
||||||
{
|
{
|
||||||
|
@ -13,7 +14,7 @@ namespace ml
|
||||||
/**
|
/**
|
||||||
* Logs game activities into an output stream.
|
* Logs game activities into an output stream.
|
||||||
**/
|
**/
|
||||||
class Logs
|
class Logs: public Service
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit Logs(std::ostream& out);
|
explicit Logs(std::ostream& out);
|
||||||
|
|
|
@ -1,16 +1,21 @@
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "conf.hpp"
|
#include "conf.hpp"
|
||||||
|
#include "commons.hpp"
|
||||||
|
|
||||||
#include "logs/FileLogs.hpp"
|
#include "logs/FileLogs.hpp"
|
||||||
|
#include "events/Events.hpp"
|
||||||
|
#include "Services.hpp"
|
||||||
|
|
||||||
#include "Game.hpp"
|
#include "Game.hpp"
|
||||||
|
|
||||||
int main(int, char**)
|
int main(int, char**)
|
||||||
{
|
{
|
||||||
auto logs = std::make_shared<ml::FileLogs>
|
ML->add<ml::FileLogs>
|
||||||
(std::filesystem::temp_directory_path() / "mornelune.log");
|
(std::filesystem::temp_directory_path() / "mornelune.log");
|
||||||
|
ML->add<ml::Events>();
|
||||||
|
|
||||||
ml::Game game {logs};
|
ml::Game game;
|
||||||
|
|
||||||
game.start();
|
game.start();
|
||||||
game.stop();
|
game.stop();
|
||||||
|
|
Reference in New Issue