/** * 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 #include #include "interfaceitems.hpp" #include "argument.hpp" #include #include #define CLASS_ID(id) \ public: \ static constexpr std::string_view classId = id; \ std::string_view getClassId() const override { return classId; } template 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 { 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 inline void fireEvent(Event& event, Args... args) { event.fire(std::forward(args)...); } template inline void fireEvent(Event&, Args...>& event, const std::shared_ptr& object, Args... args) { event.fire(object, std::forward(args)...); } template inline void fireEvent(Event&, Args...>& event, T1 value1, const std::shared_ptr& object2, Args... args) { event.fire(value1, object2, std::forward(args)...); } template inline void fireEvent(Event&, const std::shared_ptr&, Args...>& event, const std::shared_ptr& object1, const std::shared_ptr& object2, Args... args) { event.fire(object1, object2, std::forward(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 onDestroying; boost::signals2::signal propertyChanged; boost::signals2::signal attributeChanged; boost::signals2::signal onEventFired; Object(); virtual ~Object() = default; inline bool dying() const noexcept { return m_dying; } void destroy(); template inline std::shared_ptr shared_ptr_c() const { return std::static_pointer_cast(shared_from_this()); } template std::shared_ptr shared_ptr() { return std::static_pointer_cast(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