From a2e709dcf24159924f161f5c0b132e72871cca35 Mon Sep 17 00:00:00 2001 From: Reinder Feenstra Date: Mon, 28 Jun 2021 23:31:58 +0200 Subject: [PATCH] added vector property support for non object types --- .../src/core/abstractobjectvectorproperty.hpp | 5 + server/src/core/abstractvectorproperty.hpp | 2 + server/src/core/attributes.hpp | 7 +- server/src/core/object.cpp | 6 +- server/src/core/session.cpp | 4 +- server/src/core/vectorproperty.hpp | 210 ++++++++++++++++++ 6 files changed, 230 insertions(+), 4 deletions(-) create mode 100644 server/src/core/vectorproperty.hpp diff --git a/server/src/core/abstractobjectvectorproperty.hpp b/server/src/core/abstractobjectvectorproperty.hpp index 8fa51160..1c3aa606 100644 --- a/server/src/core/abstractobjectvectorproperty.hpp +++ b/server/src/core/abstractobjectvectorproperty.hpp @@ -89,6 +89,11 @@ class AbstractObjectVectorProperty : public AbstractVectorProperty { throw conversion_error(); } + + void load(const nlohmann::json&) final + { + throw conversion_error(); + } }; #endif diff --git a/server/src/core/abstractvectorproperty.hpp b/server/src/core/abstractvectorproperty.hpp index 23001e51..9cbf8a3a 100644 --- a/server/src/core/abstractvectorproperty.hpp +++ b/server/src/core/abstractvectorproperty.hpp @@ -49,6 +49,8 @@ class AbstractVectorProperty : public BaseProperty virtual void setDouble(size_t index, double value) = 0; virtual void setString(size_t index, const std::string& value) = 0; virtual void setObject(size_t index, const ObjectPtr& value) = 0; + + virtual void load(const nlohmann::json& values) = 0; }; #endif diff --git a/server/src/core/attributes.hpp b/server/src/core/attributes.hpp index 4b0386bf..62f67aed 100644 --- a/server/src/core/attributes.hpp +++ b/server/src/core/attributes.hpp @@ -26,6 +26,7 @@ #include "interfaceitem.hpp" #include "abstractobjectproperty.hpp" #include "property.hpp" +#include "vectorproperty.hpp" struct Attributes { @@ -96,7 +97,11 @@ struct Attributes property.addAttribute(AttributeName::Values, values); } - + template + static inline void addValues(VectorProperty& property, const std::array& values) + { + property.addAttribute(AttributeName::Values, values); + } //inline InterfaceItem& addAttributeSubObject(bool value) { return addAttribute(AttributeName::SubObject, value); } /* template diff --git a/server/src/core/object.cpp b/server/src/core/object.cpp index eba7d13c..2edcd473 100644 --- a/server/src/core/object.cpp +++ b/server/src/core/object.cpp @@ -111,15 +111,19 @@ void Object::load(WorldLoader& loader, const nlohmann::json& data) } } else - assert(false);// vectorProperty->load(value); + vectorProperty->load(value); } } // state values (optional): nlohmann::json state = loader.getState(getObjectId()); for(auto& [name, value] : state.items()) + { if(AbstractProperty* property = getProperty(name)) property->load(value); + else if(AbstractVectorProperty* vectorProperty = getVectorProperty(name)) + vectorProperty->load(value); + } } void Object::save(WorldSaver& saver, nlohmann::json& data, nlohmann::json& state) const diff --git a/server/src/core/session.cpp b/server/src/core/session.cpp index 363c33a1..66d0bad7 100644 --- a/server/src/core/session.cpp +++ b/server/src/core/session.cpp @@ -596,9 +596,9 @@ void Session::writeObject(Message& message, const ObjectPtr& object) message.write(baseProperty->type()); if(baseProperty->type() == ValueType::Enum) - message.write(property->enumName()); + message.write(baseProperty->enumName()); else if(baseProperty->type() == ValueType::Set) - message.write(property->setName()); + message.write(baseProperty->setName()); if(property) { diff --git a/server/src/core/vectorproperty.hpp b/server/src/core/vectorproperty.hpp new file mode 100644 index 00000000..41d6adf3 --- /dev/null +++ b/server/src/core/vectorproperty.hpp @@ -0,0 +1,210 @@ +/** + * server/src/core/vectorproperty.hpp + * + * This file is part of the traintastic source code. + * + * Copyright (C) 2021 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_VECTORPROPERTY_HPP +#define TRAINTASTIC_SERVER_CORE_VECTORPROPERTY_HPP + +#include "abstractvectorproperty.hpp" +#include +#include "to.hpp" + +template +class VectorProperty : public AbstractVectorProperty +{ + private: + std::vector m_values; + + public: + using const_iterator = typename std::vector::const_iterator; + + VectorProperty(Object& object, const std::string& name, std::initializer_list values, PropertyFlags flags) : + AbstractVectorProperty(object, name, value_type::value, flags), + m_values{values} + { + } + + inline const_iterator begin() const { return m_values.begin(); } + inline const_iterator end() const { return m_values.end(); } + + const T& operator [](size_t index) const + { + return m_values[index]; + } + + const std::vector& operator *() const + { + return m_values; + } + + void setValue(size_t index, T value) + { + assert(isWriteable()); + assert(index < size()); + if(m_values[index] == value) + return; + else if(!isWriteable()) + throw not_writable_error(); + else + { + m_values[index] = value; + changed(); + } + } + + void setValuesInternal(std::vector values) + { + if(m_values != values) + { + m_values = std::move(values); + changed(); + } + } + + void setValueInternal(size_t index, T value) + { + assert(index < size()); + if(m_values[index] != value) + { + m_values[index] = value; + changed(); + } + } + + void appendInternal(T value) + { + m_values.emplace_back(std::move(value)); + changed(); + } + + void removeInternal(const T& value) + { + auto it = std::find(m_values.begin(), m_values.end(), value); + if(it != m_values.end()) + { + m_values.erase(it); + changed(); + } + } + + void eraseInternal(size_t index) + { + assert(index < size()); + m_values.erase(m_values.begin() + index); + changed(); + } + + std::string_view enumName() const final + { + if constexpr(std::is_enum_v && !is_set_v) + return EnumName::value; + + assert(false); + return ""; + } + + std::string_view setName() const final + { + if constexpr(is_set_v) + return set_name_v; + + assert(false); + return ""; + } + + inline size_t size() const final + { + return m_values.size(); + } + + bool getBool(size_t index) const final + { + assert(index < size()); + return to(m_values[index]); + } + + int64_t getInt64(size_t index) const final + { + return to(m_values[index]); + } + + double getDouble(size_t index) const final + { + return to(m_values[index]); + } + + std::string getString(size_t index) const final + { + return to(m_values[index]); + } + + ObjectPtr getObject(size_t index) const final + { + throw conversion_error(); + } + + nlohmann::json toJSON() const final + { + nlohmann::json values = nlohmann::json::array(); + for(const auto& value : m_values) + values.emplace_back(to(value)); + return values; + } + + void setBool(size_t index, bool value) final + { + setValue(index, to(value)); + } + + void setInt64(size_t index, int64_t value) final + { + setValue(index, to(value)); + } + + void setDouble(size_t index, double value) final + { + setValue(index, to(value)); + } + + void setString(size_t index, const std::string& value) final + { + setValue(index, to(value)); + } + + void setObject(size_t index, const ObjectPtr& value) final + { + throw conversion_error(); + } + + void load(const nlohmann::json& values) final + { + if(values.is_array()) + { + m_values.resize(values.size()); + for(size_t i = 0; i < values.size(); i++) + m_values[i] = to(values[i]); + } + else + throw conversion_error(); + } +}; + +#endif