traintastic/server/src/core/object.hpp
Reinder Feenstra f828066cf2 WIP output system refactor (very big commit...), see #95 and #21
Summary of the changes:
- Output channel is now an enum
- Support for different output types: single/pair/aspect
- Outputs are no longer created on the interface and then assigned to a turnout/signal, instead a interface+channel+address is selected for a turnout/signal. Up to eight address can be used.
- Removed some network commands, can now be handled using the generic property/method system.
- Added support for DCCext (RCN-213) for LocoNet, DCC-EX and Z21.
TODO:
- Test/fix MarklinCAN/ECoS.
- Test/fix load old world files.
2024-02-12 23:34:16 +01:00

140 Zeilen
4.9 KiB
C++

/**
* server/src/core/object.hpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019-2024 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef TRAINTASTIC_SERVER_CORE_OBJECT_HPP
#define TRAINTASTIC_SERVER_CORE_OBJECT_HPP
#include "objectptr.hpp"
#include <boost/signals2/signal.hpp>
#include <nlohmann/json.hpp>
#include "interfaceitems.hpp"
#include "argument.hpp"
#include <traintastic/enum/worldevent.hpp>
#include <traintastic/set/worldstate.hpp>
#define CLASS_ID(id) \
public: \
static constexpr std::string_view classId = id; \
std::string_view getClassId() const override { return classId; }
template<class... Args> class Event;
class AbstractMethod;
class BaseProperty;
class AbstractProperty;
class AbstractObjectProperty;
class AbstractVectorProperty;
class AbstractAttribute;
class AbstractEvent;
class WorldLoader;
class WorldSaver;
class Object : public std::enable_shared_from_this<Object>
{
friend class World;
friend class WorldLoader;
friend class WorldSaver;
private:
static nlohmann::json toJSON(WorldSaver& saver, const BaseProperty& baseProperty);
static void loadJSON(WorldLoader& loader, BaseProperty& baseProperty, const nlohmann::json& value);
bool m_dying; // TODO: atomic??
protected:
InterfaceItems m_interfaceItems;
template<class... Args>
inline void fireEvent(Event<Args...>& event, Args... args)
{
event.fire(std::forward<Args>(args)...);
}
template<class T, class... Args>
inline void fireEvent(Event<const std::shared_ptr<T>&, Args...>& event, const std::shared_ptr<T>& object, Args... args)
{
event.fire(object, std::forward<Args>(args)...);
}
template<class T1, class T2, class... Args>
inline void fireEvent(Event<T1, const std::shared_ptr<T2>&, Args...>& event, T1 value1, const std::shared_ptr<T2>& object2, Args... args)
{
event.fire(value1, object2, std::forward<Args>(args)...);
}
template<class T1, class T2, class... Args>
inline void fireEvent(Event<const std::shared_ptr<T1>&, const std::shared_ptr<T2>&, Args...>& event, const std::shared_ptr<T1>& object1, const std::shared_ptr<T2>& object2, Args... args)
{
event.fire(object1, object2, std::forward<Args>(args)...);
}
virtual void destroying() {}
virtual void load(WorldLoader& loader, const nlohmann::json& data);
virtual void save(WorldSaver& saver, nlohmann::json& data, nlohmann::json& state) const;
virtual void loaded();
virtual void worldEvent(WorldState state, WorldEvent event);
public:
Object(const Object&) = delete;
Object& operator =(const Object&) = delete;
boost::signals2::signal<void (Object&)> onDestroying;
boost::signals2::signal<void (BaseProperty&)> propertyChanged;
boost::signals2::signal<void (AbstractAttribute&)> attributeChanged;
boost::signals2::signal<void (const AbstractEvent&, const Arguments&)> onEventFired;
Object();
virtual ~Object() = default;
inline bool dying() const noexcept { return m_dying; }
void destroy();
template <typename Derived>
inline std::shared_ptr<const Derived> shared_ptr_c() const
{
return std::static_pointer_cast<const Derived>(shared_from_this());
}
template <typename Derived>
std::shared_ptr<Derived> shared_ptr()
{
return std::static_pointer_cast<Derived>(shared_from_this());
}
virtual std::string_view getClassId() const = 0;
virtual std::string getObjectId() const = 0;
const InterfaceItems& interfaceItems() const { return m_interfaceItems; }
const InterfaceItem* getItem(std::string_view name) const;
InterfaceItem* getItem(std::string_view name);
const AbstractMethod* getMethod(std::string_view name) const;
AbstractMethod* getMethod(std::string_view name);
const AbstractProperty* getProperty(std::string_view name) const;
AbstractProperty* getProperty(std::string_view name);
const AbstractObjectProperty* getObjectProperty(std::string_view name) const;
AbstractObjectProperty* getObjectProperty(std::string_view name);
const AbstractVectorProperty* getVectorProperty(std::string_view name) const;
AbstractVectorProperty* getVectorProperty(std::string_view name);
};
#endif