From 607ae9a3e6a64c7ac1eb8c25b9cfab50b94f1d86 Mon Sep 17 00:00:00 2001
From: WolverinDEV <git@teaspeak.de>
Date: Wed, 8 Apr 2020 02:56:08 +0200
Subject: [PATCH] Updated the property system and added a packet loss
 calculator

---
 CMakeLists.txt                        |   7 +-
 src/Properties.cpp                    | 478 +-------------------------
 src/Properties.h                      | 384 ++++++++++++---------
 src/PropertyDefinition.h              | 360 +++++++++++++++++++
 src/PropertyDefinitions.cpp           |  84 +++++
 src/converters/converter.cpp          |   3 +-
 src/converters/converter.h            |   2 +
 src/protocol/AcknowledgeManager.cpp   |  49 +--
 src/protocol/AcknowledgeManager.h     |  48 ++-
 src/protocol/Packet.cpp               |  21 +-
 src/protocol/Packet.h                 |  75 +++-
 src/protocol/PacketLossCalculator.cpp | 105 ++++++
 src/protocol/PacketLossCalculator.h   | 103 ++++++
 src/query/Command.h                   |  19 +-
 test/PacketLossCalculateTest.cpp      | 222 ++++++++++++
 test/PropertyTest.cpp                 |   9 +-
 16 files changed, 1257 insertions(+), 712 deletions(-)
 create mode 100644 src/PropertyDefinition.h
 create mode 100644 src/PropertyDefinitions.cpp
 create mode 100644 src/protocol/PacketLossCalculator.cpp
 create mode 100644 src/protocol/PacketLossCalculator.h
 create mode 100644 test/PacketLossCalculateTest.cpp

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6e0660d..1d29498 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -128,12 +128,14 @@ set(SOURCE_FILES
         src/EventLoop.cpp
 
         src/License.cpp
+        src/PropertyDefinitions.cpp
 
         src/bbcode/bbcodes.cpp
 
         src/channel/TreeView.cpp
         src/protocol/ringbuffer.cpp
         src/protocol/AcknowledgeManager.cpp
+        src/protocol/PacketLossCalculator.cpp
 )
 
 set(HEADER_FILES
@@ -287,7 +289,7 @@ if(BUILD_TESTS)
         add_executable(CrashTest test/CrashTest.cpp ${SOURCE_FILES})
         target_link_libraries(CrashTest ${TEST_LIBRARIES})
 
-        add_executable(PorpertyTest test/PropertyTest.cpp ${SOURCE_FILES})
+        add_executable(PorpertyTest test/PropertyTest.cpp src/Properties.cpp src/PropertyDefinitions.cpp)
         target_link_libraries(PorpertyTest ${TEST_LIBRARIES})
 
         add_executable(BBTest test/BBTest.cpp ${SOURCE_FILES} src/query/command_unused.h)
@@ -304,5 +306,8 @@ if(BUILD_TESTS)
 
         add_executable(RW-Lock-Test test/rw_lock.cpp src/lock/rw_mutex.cpp)
         target_link_libraries(GenerationTest ${TEST_LIBRARIES})
+
+        add_executable(PacketLossTest src/protocol/PacketLossCalculator.cpp test/PacketLossCalculateTest.cpp)
+        target_link_libraries(PacketLossTest)
     endif()
 endif()
diff --git a/src/Properties.cpp b/src/Properties.cpp
index d30c1df..fe3f919 100644
--- a/src/Properties.cpp
+++ b/src/Properties.cpp
@@ -1,6 +1,7 @@
 #include <algorithm>
 #include <mutex>
 #include <array>
+#include <utility>
 #include "log/LogUtils.h"
 #include "misc/memtracker.h"
 #include "Properties.h"
@@ -21,8 +22,6 @@ bool Properties::has(property::PropertyType type, int index) {
         if(!*it) continue;
         if(it->get()->type != type) continue;
 
-        index -= (int) it->get()->offset;
-        if(index < 0) return false;
         return index < it->get()->length;
     }
     return false;
@@ -34,10 +33,6 @@ PropertyWrapper Properties::find(property::PropertyType type, int index) {
         if(bulk->type != type)
             continue;
 
-        index -= (int) bulk->offset;
-        if(index < 0)
-            break;
-
         if(index >= bulk->length)
             break;
 
@@ -72,7 +67,7 @@ std::vector<PropertyWrapper> Properties::all_properties() {
     return result;
 }
 
-PropertyWrapper::PropertyWrapper(ts::Properties* handle, ts::PropertyData *data, const std::shared_ptr<ts::PropertyBundle> &bundle_lock) : handle(handle), data_ptr(data), bundle_lock(bundle_lock) {
+PropertyWrapper::PropertyWrapper(ts::Properties* handle, ts::PropertyData *data, std::shared_ptr<ts::PropertyBundle> bundle_lock) : handle{handle}, data_ptr{data}, bundle_lock{std::move(bundle_lock)} {
 }
 
 void PropertyWrapper::trigger_update() {
@@ -84,7 +79,7 @@ void PropertyWrapper::trigger_update() {
     }
 }
 
-bool Properties::register_property_type(ts::property::PropertyType type, size_t length, size_t offset) {
+bool Properties::register_property_type(ts::property::PropertyType type, size_t length) {
     for(auto& bulk : this->properties)
         if(bulk->type == type)
             return false;
@@ -95,7 +90,6 @@ bool Properties::register_property_type(ts::property::PropertyType type, size_t
 
         for(int index = 0; index < bundle->length; index++) {
             auto& property = bundle->properties[index];
-            property.description.~shared_ptr<property::PropertyDescription>();
             property.value.~string();
             property.value_lock.~spin_lock();
             property.casted_value.~any();
@@ -104,7 +98,6 @@ bool Properties::register_property_type(ts::property::PropertyType type, size_t
     });
 
     ptr->type = type;
-    ptr->offset = offset;
     ptr->length = length;
 
     for(int index = 0; index < length; index++) {
@@ -113,7 +106,7 @@ bool Properties::register_property_type(ts::property::PropertyType type, size_t
         new (&property.casted_value) any();
         new (&property.value_lock) spin_lock();
         new (&property.value) string();
-        new (&property.description) shared_ptr<property::PropertyDescription>(property::impl::info(type, (int) (offset + index)));
+        property.description = &property::describe(type, index);
         property.flag_modified = false;
         property.flag_db_reference = false;
 
@@ -127,470 +120,7 @@ bool Properties::register_property_type(ts::property::PropertyType type, size_t
 
 namespace ts {
     namespace property {
-        PropertyDescription::PropertyDescription(int property_id, PropertyType property_type, const std::string &name, const std::string &default_value, property::ValueType type, property::flag_type flags) noexcept : name(name), default_value(default_value),
-                                                                                                                                                                                                              type_value(type), flags(flags), property_index(property_id),
-                                                                                                                                                                                                              type_property(property_type) {
-            std::transform(this->name.begin(), this->name.end(), this->name.begin(), ::tolower);
-        }
-
-#define FLAG_SS (FLAG_SNAPSHOT | FLAG_SAVE)
-#define FLAG_SERVER_VV (FLAG_SERVER_VARIABLE | FLAG_SERVER_VIEW)
-#define FLAG_SERVER_VVSS  (FLAG_SERVER_VV | FLAG_SS)
-
-#define FLAG_CLIENT_VV (FLAG_CLIENT_VARIABLE | FLAG_CLIENT_VIEW)
-#define FLAG_CLIENT_VVSS  (FLAG_CLIENT_VV | FLAG_SS)
-
-        array<shared_ptr<PropertyDescription>, VirtualServerProperties::VIRTUALSERVER_ENDMARKER> virtualserver_info = {
-                make_shared<PropertyDescription>(VIRTUALSERVER_UNDEFINED, "VIRTUALSERVER_UNDEFINED", "", TYPE_UNKNOWN, 0), //Must be at index 0!
-                make_shared<PropertyDescription>(VIRTUALSERVER_ID, "VIRTUALSERVER_ID", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VIEW),                                          //available when connected
-                make_shared<PropertyDescription>(VIRTUALSERVER_UNIQUE_IDENTIFIER, "VIRTUALSERVER_UNIQUE_IDENTIFIER", "", TYPE_STRING, FLAG_SERVER_VV | FLAG_SNAPSHOT),
-                make_shared<PropertyDescription>(VIRTUALSERVER_NAME, "VIRTUALSERVER_NAME", "Another TeaSpeak server software user", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE),
-                make_shared<PropertyDescription>(VIRTUALSERVER_WELCOMEMESSAGE, "VIRTUALSERVER_WELCOMEMESSAGE", "Welcome on another TeaSpeak server. (Download now and a license fee is not your cup of tea! [URL]www.teaspeak.de[/URL])", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE),
-                make_shared<PropertyDescription>(VIRTUALSERVER_PLATFORM, "VIRTUALSERVER_PLATFORM", "undefined", TYPE_STRING, FLAG_SERVER_VIEW),
-                make_shared<PropertyDescription>(VIRTUALSERVER_VERSION, "VIRTUALSERVER_VERSION", "undefined", TYPE_STRING, FLAG_SERVER_VIEW),
-                make_shared<PropertyDescription>(VIRTUALSERVER_MAXCLIENTS, "VIRTUALSERVER_MAXCLIENTS", "120", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE),
-                make_shared<PropertyDescription>(VIRTUALSERVER_PASSWORD, "VIRTUALSERVER_PASSWORD", "", TYPE_STRING, FLAG_SS | FLAG_USER_EDITABLE),
-                make_shared<PropertyDescription>(VIRTUALSERVER_CLIENTS_ONLINE, "virtualserver_clientsonline", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE),
-                make_shared<PropertyDescription>(VIRTUALSERVER_CHANNELS_ONLINE, "virtualserver_channelsonline", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE),                   //only available on request (=> requestServerVariables),
-                make_shared<PropertyDescription>(VIRTUALSERVER_QUERYCLIENTS_ONLINE, "virtualserver_queryclientsonline", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE),                         //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_CREATED, "VIRTUALSERVER_CREATED", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VIEW | FLAG_SS),                           //available when connected, stores the time when the server was created
-                make_shared<PropertyDescription>(VIRTUALSERVER_UPTIME, "VIRTUALSERVER_UPTIME", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE),                            //only available on request (=> requestServerVariables), the time since the server was started
-                make_shared<PropertyDescription>(VIRTUALSERVER_CODEC_ENCRYPTION_MODE, "VIRTUALSERVER_CODEC_ENCRYPTION_MODE", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE),             //available and always up-to-date when connected
-
-                // Rare properties
-                make_shared<PropertyDescription>(VIRTUALSERVER_KEYPAIR, "VIRTUALSERVER_KEYPAIR", "", TYPE_STRING, FLAG_SS),                                     //internal use
-                make_shared<PropertyDescription>(VIRTUALSERVER_HOSTMESSAGE, "VIRTUALSERVER_HOSTMESSAGE", "Welcome", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE),                                 //available when connected, not updated while connected
-                make_shared<PropertyDescription>(VIRTUALSERVER_HOSTMESSAGE_MODE, "VIRTUALSERVER_HOSTMESSAGE_MODE", "1", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE),                            //available when connected, not updated while connected
-                make_shared<PropertyDescription>(VIRTUALSERVER_DEFAULT_SERVER_GROUP, "VIRTUALSERVER_DEFAULT_SERVER_GROUP", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE),                        //the manager permissions server group that a new manager gets assigned
-                make_shared<PropertyDescription>(VIRTUALSERVER_DEFAULT_MUSIC_GROUP, "VIRTUALSERVER_DEFAULT_MUSIC_GROUP", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE),                        //the manager permissions server group that a new manager gets assigned
-                make_shared<PropertyDescription>(VIRTUALSERVER_DEFAULT_CHANNEL_GROUP, "VIRTUALSERVER_DEFAULT_CHANNEL_GROUP", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE),                       //the channel permissions group that a new manager gets assigned when joining a channel
-                make_shared<PropertyDescription>(VIRTUALSERVER_FLAG_PASSWORD, "VIRTUALSERVER_FLAG_PASSWORD", "0", TYPE_BOOL, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE),                               //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_DEFAULT_CHANNEL_ADMIN_GROUP, "VIRTUALSERVER_DEFAULT_CHANNEL_ADMIN_GROUP", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SERVER_VIEW | FLAG_SS | FLAG_USER_EDITABLE),                 //the channel permissions group that a manager gets assigned when creating a channel
-                make_shared<PropertyDescription>(VIRTUALSERVER_MAX_DOWNLOAD_TOTAL_BANDWIDTH, "VIRTUALSERVER_MAX_DOWNLOAD_TOTAL_BANDWIDTH", "-1", TYPE_SIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE),                //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_MAX_UPLOAD_TOTAL_BANDWIDTH, "VIRTUALSERVER_MAX_UPLOAD_TOTAL_BANDWIDTH", "-1", TYPE_SIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE),                  //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_HOSTBANNER_URL, "VIRTUALSERVER_HOSTBANNER_URL", "", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE),                              //available when connected, always up-to-date
-                make_shared<PropertyDescription>(VIRTUALSERVER_HOSTBANNER_GFX_URL, "VIRTUALSERVER_HOSTBANNER_GFX_URL", "", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE),                          //available when connected, always up-to-date
-                make_shared<PropertyDescription>(VIRTUALSERVER_HOSTBANNER_GFX_INTERVAL, "VIRTUALSERVER_HOSTBANNER_GFX_INTERVAL", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE),                     //available when connected, always up-to-date
-                make_shared<PropertyDescription>(VIRTUALSERVER_COMPLAIN_AUTOBAN_COUNT, "VIRTUALSERVER_COMPLAIN_AUTOBAN_COUNT", "5", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE),                      //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_COMPLAIN_AUTOBAN_TIME, "VIRTUALSERVER_COMPLAIN_AUTOBAN_TIME", "5", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE),                       //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_COMPLAIN_REMOVE_TIME, "VIRTUALSERVER_COMPLAIN_REMOVE_TIME", "5", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE),                        //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_MIN_CLIENTS_IN_CHANNEL_BEFORE_FORCED_SILENCE, "VIRTUALSERVER_MIN_CLIENTS_IN_CHANNEL_BEFORE_FORCED_SILENCE", "20", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE),//only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_PRIORITY_SPEAKER_DIMM_MODIFICATOR, "VIRTUALSERVER_PRIORITY_SPEAKER_DIMM_MODIFICATOR", "-18", TYPE_FLOAT, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE),           //available when connected, always up-to-date
-                make_shared<PropertyDescription>(VIRTUALSERVER_ANTIFLOOD_POINTS_TICK_REDUCE, "VIRTUALSERVER_ANTIFLOOD_POINTS_TICK_REDUCE", "25", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE),                //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_ANTIFLOOD_POINTS_NEEDED_COMMAND_BLOCK, "VIRTUALSERVER_ANTIFLOOD_POINTS_NEEDED_COMMAND_BLOCK", "150", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE),       //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_ANTIFLOOD_POINTS_NEEDED_IP_BLOCK, "VIRTUALSERVER_ANTIFLOOD_POINTS_NEEDED_IP_BLOCK", "300", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE),            //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_CLIENT_CONNECTIONS, "VIRTUALSERVER_CLIENT_CONNECTIONS", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS),                          //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_QUERY_CLIENT_CONNECTIONS, "VIRTUALSERVER_QUERY_CLIENT_CONNECTIONS", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS),                    //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_HOSTBUTTON_TOOLTIP, "VIRTUALSERVER_HOSTBUTTON_TOOLTIP", "", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE),                          //available when connected, always up-to-date
-                make_shared<PropertyDescription>(VIRTUALSERVER_HOSTBUTTON_URL, "VIRTUALSERVER_HOSTBUTTON_URL", "", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE),                              //available when connected, always up-to-date
-                make_shared<PropertyDescription>(VIRTUALSERVER_HOSTBUTTON_GFX_URL, "VIRTUALSERVER_HOSTBUTTON_GFX_URL", "", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE),                          //available when connected, always up-to-date
-                make_shared<PropertyDescription>(VIRTUALSERVER_HOSTBANNER_MODE, "VIRTUALSERVER_HOSTBANNER_MODE", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE),                             //available when connected, always up-to-date
-                make_shared<PropertyDescription>(VIRTUALSERVER_FILEBASE, "VIRTUALSERVER_FILEBASE", "", TYPE_STRING, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE),                                    //not available to clients, stores the folder used for file transfers
-                make_shared<PropertyDescription>(VIRTUALSERVER_DOWNLOAD_QUOTA, "VIRTUALSERVER_DOWNLOAD_QUOTA", "-1", TYPE_SIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SAVE | FLAG_USER_EDITABLE),                              //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_UPLOAD_QUOTA, "VIRTUALSERVER_UPLOAD_QUOTA", "-1", TYPE_SIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SAVE | FLAG_USER_EDITABLE),                                //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_MONTH_BYTES_DOWNLOADED, "VIRTUALSERVER_MONTH_BYTES_DOWNLOADED", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SAVE),                      //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_MONTH_BYTES_UPLOADED, "VIRTUALSERVER_MONTH_BYTES_UPLOADED", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SAVE),                        //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_TOTAL_BYTES_DOWNLOADED, "VIRTUALSERVER_TOTAL_BYTES_DOWNLOADED", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SAVE),                      //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_TOTAL_BYTES_UPLOADED, "VIRTUALSERVER_TOTAL_BYTES_UPLOADED", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SAVE),                        //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_PORT, "VIRTUALSERVER_PORT", "9987", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE),                                        //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_HOST, "VIRTUALSERVER_HOST", "0.0.0.0,::", TYPE_STRING, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE),                                          //internal use | contains comma separated ip list
-                make_shared<PropertyDescription>(VIRTUALSERVER_AUTOSTART, "VIRTUALSERVER_AUTOSTART", "1", TYPE_BOOL, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE),                                   //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_MACHINE_ID, "VIRTUALSERVER_MACHINE_ID", "", TYPE_STRING, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE),                                  //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_NEEDED_IDENTITY_SECURITY_LEVEL, "VIRTUALSERVER_NEEDED_IDENTITY_SECURITY_LEVEL", "8", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE),              //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_LOG_CLIENT, "VIRTUALSERVER_LOG_CLIENT", "1", TYPE_BOOL, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE),                                  //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_LOG_QUERY, "VIRTUALSERVER_LOG_QUERY", "1", TYPE_BOOL, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE),                                   //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_LOG_CHANNEL, "VIRTUALSERVER_LOG_CHANNEL", "1", TYPE_BOOL, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE),                                 //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_LOG_PERMISSIONS, "VIRTUALSERVER_LOG_PERMISSIONS", "1", TYPE_BOOL, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE),                             //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_LOG_SERVER, "VIRTUALSERVER_LOG_SERVER", "1", TYPE_BOOL, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE),                                  //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_LOG_FILETRANSFER, "VIRTUALSERVER_LOG_FILETRANSFER", "1", TYPE_BOOL, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE),                            //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_NAME_PHONETIC, "VIRTUALSERVER_NAME_PHONETIC", "", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE),                               //available when connected, always up-to-date
-                make_shared<PropertyDescription>(VIRTUALSERVER_ICON_ID, "VIRTUALSERVER_ICON_ID", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE),                                     //available when connected, always up-to-date
-                make_shared<PropertyDescription>(VIRTUALSERVER_RESERVED_SLOTS, "VIRTUALSERVER_RESERVED_SLOTS", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE),                              //available when connected, always up-to-date
-                make_shared<PropertyDescription>(VIRTUALSERVER_TOTAL_PACKETLOSS_SPEECH, "VIRTUALSERVER_TOTAL_PACKETLOSS_SPEECH", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE),                     //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_TOTAL_PACKETLOSS_KEEPALIVE, "VIRTUALSERVER_TOTAL_PACKETLOSS_KEEPALIVE", "0", TYPE_FLOAT, FLAG_SERVER_VARIABLE),                  //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_TOTAL_PACKETLOSS_CONTROL, "VIRTUALSERVER_TOTAL_PACKETLOSS_CONTROL", "0", TYPE_FLOAT, FLAG_SERVER_VARIABLE),                    //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_TOTAL_PACKETLOSS_TOTAL, "VIRTUALSERVER_TOTAL_PACKETLOSS_TOTAL", "0", TYPE_FLOAT, FLAG_SERVER_VARIABLE),                      //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_TOTAL_PING, "VIRTUALSERVER_TOTAL_PING", "0", TYPE_FLOAT, FLAG_SERVER_VARIABLE),                                  //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_WEBLIST_ENABLED, "VIRTUALSERVER_WEBLIST_ENABLED", "1", TYPE_BOOL, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE),                             //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_AUTOGENERATED_PRIVILEGEKEY, "VIRTUALSERVER_AUTOGENERATED_PRIVILEGEKEY", "", TYPE_STRING, FLAG_SAVE),                  //internal use
-                make_shared<PropertyDescription>(VIRTUALSERVER_ASK_FOR_PRIVILEGEKEY, "VIRTUALSERVER_ASK_FOR_PRIVILEGEKEY", "1",  TYPE_BOOL, FLAG_SERVER_VV | FLAG_SAVE | FLAG_USER_EDITABLE),                        //available when connected
-                make_shared<PropertyDescription>(VIRTUALSERVER_CHANNEL_TEMP_DELETE_DELAY_DEFAULT, "VIRTUALSERVER_CHANNEL_TEMP_DELETE_DELAY_DEFAULT", "60", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE),           //available when connected, always up-to-date
-                make_shared<PropertyDescription>(VIRTUALSERVER_MIN_CLIENT_VERSION, "VIRTUALSERVER_MIN_CLIENT_VERSION", "1445512488", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_USER_EDITABLE),                          //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_MIN_ANDROID_VERSION, "VIRTUALSERVER_MIN_ANDROID_VERSION", "1407159763", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_USER_EDITABLE),                         //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_MIN_IOS_VERSION, "VIRTUALSERVER_MIN_IOS_VERSION", "1407159763", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_USER_EDITABLE),                             //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_MIN_WINPHONE_VERSION, "VIRTUALSERVER_MIN_WINPHONE_VERSION", "1407159763", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_USER_EDITABLE),                           //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_MAX_CHANNELS, "VIRTUALSERVER_MAX_CHANNELS", "1000", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_USER_EDITABLE),                           //only available on request (=> requestServerVariables)
-
-                make_shared<PropertyDescription>(VIRTUALSERVER_LAST_CLIENT_CONNECT, "VIRTUALSERVER_LAST_CLIENT_CONNECT", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_NEW | FLAG_SS),                           //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_LAST_QUERY_CONNECT, "VIRTUALSERVER_LAST_QUERY_CONNECT", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_NEW | FLAG_SS),                           //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_LAST_CLIENT_DISCONNECT, "VIRTUALSERVER_LAST_CLIENT_DISCONNECT", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_NEW | FLAG_SS),                           //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_LAST_QUERY_DISCONNECT, "VIRTUALSERVER_LAST_QUERY_DISCONNECT", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_NEW | FLAG_SS),                           //only available on request (=> requestServerVariables)
-
-                make_shared<PropertyDescription>(VIRTUALSERVER_WEB_PORT, "VIRTUALSERVER_WEB_PORT", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_NEW | FLAG_SS | FLAG_USER_EDITABLE),                           //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_WEB_HOST, "VIRTUALSERVER_WEB_HOST", "0.0.0.0", TYPE_STRING, FLAG_SERVER_VARIABLE | FLAG_NEW | FLAG_SS | FLAG_USER_EDITABLE),                           //only available on request (=> requestServerVariables)
-
-                make_shared<PropertyDescription>(VIRTUALSERVER_DEFAULT_CLIENT_DESCRIPTION, "VIRTUALSERVER_DEFAULT_CLIENT_DESCRIPTION", "", TYPE_STRING, FLAG_SERVER_VARIABLE | FLAG_NEW | FLAG_SS | FLAG_USER_EDITABLE),                           //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_DEFAULT_CHANNEL_DESCRIPTION, "VIRTUALSERVER_DEFAULT_CHANNEL_DESCRIPTION", "", TYPE_STRING, FLAG_SERVER_VARIABLE | FLAG_NEW | FLAG_SS | FLAG_USER_EDITABLE),                           //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_DEFAULT_CHANNEL_TOPIC, "VIRTUALSERVER_DEFAULT_CHANNEL_TOPIC", "", TYPE_STRING, FLAG_SERVER_VARIABLE | FLAG_NEW | FLAG_SS | FLAG_USER_EDITABLE),                           //only available on request (=> requestServerVariables)
-
-                make_shared<PropertyDescription>(VIRTUALSERVER_MUSIC_BOT_LIMIT, "VIRTUALSERVER_MUSIC_BOT_LIMIT", "-1", TYPE_SIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_NEW | FLAG_SS | FLAG_USER_EDITABLE),                           //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_SPOKEN_TIME, "VIRTUALSERVER_SPOKEN_TIME", "0", TYPE_UNSIGNED_NUMBER, FLAG_INTERNAL | FLAG_NEW | FLAG_SAVE),                           //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_DISABLE_IP_SAVING, "VIRTUALSERVER_DISABLE_IP_SAVING", "0", TYPE_BOOL, FLAG_INTERNAL | FLAG_NEW | FLAG_SAVE | FLAG_USER_EDITABLE),                           //only available on request (=> requestServerVariables)
-                make_shared<PropertyDescription>(VIRTUALSERVER_COUNTRY_CODE, "VIRTUALSERVER_COUNTRY_CODE", "XX", TYPE_STRING, FLAG_SERVER_VV | FLAG_SAVE | FLAG_USER_EDITABLE)                           //available when connected
-        };
-
-        array<shared_ptr<PropertyDescription>, ChannelProperties::CHANNEL_ENDMARKER> channel_info = {
-                make_shared<PropertyDescription>(CHANNEL_UNDEFINED, "CHANNEL_UNDEFINED", "", TYPE_UNKNOWN, 0), //Must be at index 0!
-                make_shared<PropertyDescription>(CHANNEL_ID, "cid", "0", TYPE_UNSIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS),
-                make_shared<PropertyDescription>(CHANNEL_PID, "cpid", "0", TYPE_UNSIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS),
-                make_shared<PropertyDescription>(CHANNEL_NAME, "CHANNEL_NAME", "undefined", TYPE_STRING, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE),                       //Available for all channels that are "in view", always up-to-date
-                make_shared<PropertyDescription>(CHANNEL_TOPIC, "CHANNEL_TOPIC", "", TYPE_STRING, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE),                          //Available for all channels that are "in view", always up-to-date
-                make_shared<PropertyDescription>(CHANNEL_DESCRIPTION, "CHANNEL_DESCRIPTION", "", TYPE_STRING, FLAG_CHANNEL_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE),                    //Must be requested (=> requestChannelDescription)
-                make_shared<PropertyDescription>(CHANNEL_PASSWORD, "CHANNEL_PASSWORD", "0", TYPE_STRING, FLAG_SS | FLAG_USER_EDITABLE),                       //not available manager side
-                make_shared<PropertyDescription>(CHANNEL_CODEC, "CHANNEL_CODEC", "4", TYPE_UNSIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE),                          //Available for all channels that are "in view", always up-to-date
-                make_shared<PropertyDescription>(CHANNEL_CODEC_QUALITY, "CHANNEL_CODEC_QUALITY", "7", TYPE_UNSIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE),                  //Available for all channels that are "in view", always up-to-date
-                make_shared<PropertyDescription>(CHANNEL_MAXCLIENTS, "CHANNEL_MAXCLIENTS", "-1", TYPE_SIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE),                     //Available for all channels that are "in view", always up-to-date
-                make_shared<PropertyDescription>(CHANNEL_MAXFAMILYCLIENTS, "CHANNEL_MAXFAMILYCLIENTS", "-1", TYPE_SIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE),               //Available for all channels that are "in view", always up-to-date
-                make_shared<PropertyDescription>(CHANNEL_ORDER, "CHANNEL_ORDER", "0", TYPE_UNSIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE),                          //Available for all channels that are "in view", always up-to-date
-                make_shared<PropertyDescription>(CHANNEL_FLAG_PERMANENT, "CHANNEL_FLAG_PERMANENT", "1", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE),                 //Available for all channels that are "in view", always up-to-date
-                make_shared<PropertyDescription>(CHANNEL_FLAG_SEMI_PERMANENT, "CHANNEL_FLAG_SEMI_PERMANENT", "0", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE),            //Available for all channels that are "in view", always up-to-date
-                make_shared<PropertyDescription>(CHANNEL_FLAG_DEFAULT, "CHANNEL_FLAG_DEFAULT", "0", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE),                   //Available for all channels that are "in view", always up-to-date
-                make_shared<PropertyDescription>(CHANNEL_FLAG_PASSWORD, "CHANNEL_FLAG_PASSWORD", "0", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE),                  //Available for all channels that are "in view", always up-to-date
-                make_shared<PropertyDescription>(CHANNEL_CODEC_LATENCY_FACTOR, "CHANNEL_CODEC_LATENCY_FACTOR", "1", TYPE_UNSIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE),           //Available for all channels that are "in view", always up-to-date
-                make_shared<PropertyDescription>(CHANNEL_CODEC_IS_UNENCRYPTED, "CHANNEL_CODEC_IS_UNENCRYPTED", "1", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE),           //Available for all channels that are "in view", always up-to-date
-                make_shared<PropertyDescription>(CHANNEL_SECURITY_SALT, "CHANNEL_SECURITY_SALT", "", TYPE_STRING, FLAG_SS),                  //Not available manager side, not used in teamspeak, only SDK. Sets the options+salt for security hash.
-                make_shared<PropertyDescription>(CHANNEL_DELETE_DELAY, "CHANNEL_DELETE_DELAY", "0", TYPE_UNSIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE),                   //How many seconds to wait before deleting this channel
-                make_shared<PropertyDescription>(CHANNEL_FLAG_MAXCLIENTS_UNLIMITED, "CHANNEL_FLAG_MAXCLIENTS_UNLIMITED", "1", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE),      //Available for all channels that are "in view", always up-to-date
-                make_shared<PropertyDescription>(CHANNEL_FLAG_MAXFAMILYCLIENTS_UNLIMITED, "CHANNEL_FLAG_MAXFAMILYCLIENTS_UNLIMITED", "1", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE),//Available for all channels that are "in view", always up-to-date
-                make_shared<PropertyDescription>(CHANNEL_FLAG_MAXFAMILYCLIENTS_INHERITED, "CHANNEL_FLAG_MAXFAMILYCLIENTS_INHERITED", "0", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE),//Available for all channels that are "in view", always up-to-date
-                make_shared<PropertyDescription>(CHANNEL_FLAG_ARE_SUBSCRIBED, "CHANNEL_FLAG_ARE_SUBSCRIBED", "1", TYPE_BOOL, FLAG_INTERNAL),            //Only available manager side, stores whether we are subscribed to this channel
-                make_shared<PropertyDescription>(CHANNEL_FILEPATH, "CHANNEL_FILEPATH", "", TYPE_STRING, FLAG_SS),                       //not available manager side, the folder used for file-transfers for this channel
-                make_shared<PropertyDescription>(CHANNEL_NEEDED_TALK_POWER, "CHANNEL_NEEDED_TALK_POWER", "0", TYPE_UNSIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE),              //Available for all channels that are "in view", always up-to-date
-                make_shared<PropertyDescription>(CHANNEL_FORCED_SILENCE, "CHANNEL_FORCED_SILENCE", "0", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE),                 //Available for all channels that are "in view", always up-to-date
-                make_shared<PropertyDescription>(CHANNEL_NAME_PHONETIC, "CHANNEL_NAME_PHONETIC", "", TYPE_STRING, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE),                  //Available for all channels that are "in view", always up-to-date
-                make_shared<PropertyDescription>(CHANNEL_ICON_ID, "CHANNEL_ICON_ID", "0", TYPE_UNSIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE),                        //Available for all channels that are "in view", always up-to-date
-                make_shared<PropertyDescription>(CHANNEL_FLAG_PRIVATE, "CHANNEL_FLAG_PRIVATE", "0", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS),                   //Available for all channels that are "in view", always up-to-date
-                make_shared<PropertyDescription>(CHANNEL_LAST_LEFT, "CHANNEL_LAST_LEFT", "0", TYPE_UNSIGNED_NUMBER, FLAG_SAVE | FLAG_CHANNEL_VIEW | FLAG_CHANNEL_VARIABLE | FLAG_NEW),                   //Available for all channels that are "in view", always up-to-date
-                make_shared<PropertyDescription>(CHANNEL_CREATED_AT, "CHANNEL_CREATED_AT", "0", TYPE_UNSIGNED_NUMBER, FLAG_SS | FLAG_CHANNEL_VIEW | FLAG_CHANNEL_VARIABLE | FLAG_NEW),                   //Available for all channels that are "in view", always up-to-date
-                make_shared<PropertyDescription>(CHANNEL_CREATED_BY, "CHANNEL_CREATED_BY", "0", TYPE_UNSIGNED_NUMBER, FLAG_SS | FLAG_CHANNEL_VIEW | FLAG_CHANNEL_VARIABLE | FLAG_NEW),                   //Available for all channels that are "in view", always up-to-date
-                make_shared<PropertyDescription>(CHANNEL_CONVERSATION_HISTORY_LENGTH, "CHANNEL_CONVERSATION_HISTORY_LENGTH", "1500", TYPE_SIGNED_NUMBER, FLAG_SS | FLAG_CHANNEL_VIEW | FLAG_CHANNEL_VARIABLE | FLAG_NEW | FLAG_USER_EDITABLE),
-                make_shared<PropertyDescription>(CHANNEL_FLAG_CONVERSATION_PRIVATE, "CHANNEL_FLAG_CONVERSATION_PRIVATE", "0", TYPE_BOOL, FLAG_SS | FLAG_CHANNEL_VIEW | FLAG_CHANNEL_VARIABLE | FLAG_NEW | FLAG_USER_EDITABLE)
-        };
-
-        array<shared_ptr<PropertyDescription>, GroupProperties::GROUP_ENDMARKER> group_info = {
-                make_shared<PropertyDescription>(GROUP_UNDEFINED, "GROUP_UNDEFINED", "", TYPE_UNKNOWN, 0),
-                make_shared<PropertyDescription>(GROUP_ID, "gid", "0", TYPE_UNSIGNED_NUMBER, FLAG_INTERNAL),
-                make_shared<PropertyDescription>(GROUP_TYPE, "type", "0", TYPE_UNSIGNED_NUMBER, FLAG_GROUP_VIEW),
-                make_shared<PropertyDescription>(GROUP_NAME, "name", "Undefined group", TYPE_STRING, FLAG_GROUP_VIEW),
-                make_shared<PropertyDescription>(GROUP_SORTID, "sortid", "0", TYPE_UNSIGNED_NUMBER, FLAG_GROUP_VIEW),
-                make_shared<PropertyDescription>(GROUP_SAVEDB, "savedb", "0", TYPE_BOOL, FLAG_GROUP_VIEW),
-                make_shared<PropertyDescription>(GROUP_NAMEMODE, "namemode", "0", TYPE_UNSIGNED_NUMBER, FLAG_GROUP_VIEW),
-                make_shared<PropertyDescription>(GROUP_ICONID, "iconid", "0", TYPE_UNSIGNED_NUMBER, FLAG_GROUP_VIEW)
-        };
-
-        array<shared_ptr<PropertyDescription>, ClientProperties::CLIENT_ENDMARKER> client_info = {
-                make_shared<PropertyDescription>(CLIENT_UNDEFINED, "CLIENT_UNDEFINED", "undefined", TYPE_UNKNOWN, 0),
-                make_shared<PropertyDescription>(CLIENT_UNIQUE_IDENTIFIER, "CLIENT_UNIQUE_IDENTIFIER", "", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_SNAPSHOT | FLAG_GLOBAL),           //automatically up-to-date for any manager "in view", can be used to identify this particular manager installation
-                make_shared<PropertyDescription>(CLIENT_NICKNAME, "CLIENT_NICKNAME", "undefined", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_SAVE_MUSIC | FLAG_SNAPSHOT | FLAG_GLOBAL | FLAG_USER_EDITABLE),                        //automatically up-to-date for any manager "in view"
-                make_shared<PropertyDescription>(CLIENT_VERSION, "CLIENT_VERSION", "unknown", TYPE_STRING, FLAG_CLIENT_VVSS | FLAG_USER_EDITABLE | FLAG_GLOBAL | FLAG_SAVE_MUSIC),                         //for other clients than ourself, this needs to be requested (=> requestClientVariables)
-                make_shared<PropertyDescription>(CLIENT_PLATFORM, "CLIENT_PLATFORM", "unknown", TYPE_STRING, FLAG_CLIENT_VVSS | FLAG_USER_EDITABLE | FLAG_GLOBAL | FLAG_SAVE_MUSIC),                        //for other clients than ourself, this needs to be requested (=> requestClientVariables)
-                make_shared<PropertyDescription>(CLIENT_FLAG_TALKING, "CLIENT_FLAG_TALKING", "0", TYPE_BOOL, FLAG_INTERNAL),                    //automatically up-to-date for any manager that can be heard (in room / whisper)
-                make_shared<PropertyDescription>(CLIENT_INPUT_MUTED, "CLIENT_INPUT_MUTED", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE),                     //automatically up-to-date for any manager "in view", this clients microphone mute status
-                make_shared<PropertyDescription>(CLIENT_OUTPUT_MUTED, "CLIENT_OUTPUT_MUTED", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE),                    //automatically up-to-date for any manager "in view", this clients headphones/speakers/mic combined mute status
-                make_shared<PropertyDescription>(CLIENT_OUTPUTONLY_MUTED, "CLIENT_OUTPUTONLY_MUTED", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE),                //automatically up-to-date for any manager "in view", this clients headphones/speakers only mute status
-                make_shared<PropertyDescription>(CLIENT_INPUT_HARDWARE, "CLIENT_INPUT_HARDWARE", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE),                  //automatically up-to-date for any manager "in view", this clients microphone hardware status (is the capture device opened?)
-                make_shared<PropertyDescription>(CLIENT_OUTPUT_HARDWARE, "CLIENT_OUTPUT_HARDWARE", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE),                 //automatically up-to-date for any manager "in view", this clients headphone/speakers hardware status (is the playback device opened?)
-                make_shared<PropertyDescription>(CLIENT_DEFAULT_CHANNEL, "CLIENT_DEFAULT_CHANNEL", "", TYPE_STRING, FLAG_INTERNAL),                 //only usable for ourself, the default channel we used to connect on our last connection attempt
-                make_shared<PropertyDescription>(CLIENT_DEFAULT_CHANNEL_PASSWORD, "CLIENT_DEFAULT_CHANNEL_PASSWORD", "", TYPE_STRING, FLAG_INTERNAL),        //internal use
-                make_shared<PropertyDescription>(CLIENT_SERVER_PASSWORD, "CLIENT_SERVER_PASSWORD", "", TYPE_STRING, FLAG_INTERNAL),                 //internal use
-                make_shared<PropertyDescription>(CLIENT_META_DATA, "CLIENT_META_DATA", "", TYPE_STRING, FLAG_CLIENT_VIEW| FLAG_GLOBAL|FLAG_USER_EDITABLE),                       //automatically up-to-date for any manager "in view", not used by TeamSpeak, free storage for sdk users
-                make_shared<PropertyDescription>(CLIENT_IS_RECORDING, "CLIENT_IS_RECORDING", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE),                    //automatically up-to-date for any manager "in view"
-                make_shared<PropertyDescription>(CLIENT_VERSION_SIGN, "CLIENT_VERSION_SIGN", "", TYPE_STRING, FLAG_INTERNAL),                    //sign
-                make_shared<PropertyDescription>(CLIENT_SECURITY_HASH, "CLIENT_SECURITY_HASH", "", TYPE_STRING, FLAG_INTERNAL),                   //SDK use, not used by teamspeak. Hash is provided by an outside source. A channel will use the security salt + other manager data to calculate a hash, which must be the same as the one provided here.
-
-                //Rare properties
-                make_shared<PropertyDescription>(CLIENT_KEY_OFFSET, "CLIENT_KEY_OFFSET", "0", TYPE_UNSIGNED_NUMBER, FLAG_INTERNAL),                      //internal use
-                make_shared<PropertyDescription>(CLIENT_LOGIN_NAME, "CLIENT_LOGIN_NAME", "", TYPE_STRING, FLAG_CLIENT_VARIABLE| FLAG_GLOBAL),                      //used for serverquery clients, makes no sense on normal clients currently
-                make_shared<PropertyDescription>(CLIENT_LOGIN_PASSWORD, "CLIENT_LOGIN_PASSWORD", "", TYPE_STRING, FLAG_INTERNAL| FLAG_GLOBAL),                  //used for serverquery clients, makes no sense on normal clients currently
-                make_shared<PropertyDescription>(CLIENT_DATABASE_ID, "CLIENT_DATABASE_ID", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VIEW | FLAG_GLOBAL),                     //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, holds database manager id
-                make_shared<PropertyDescription>(CLIENT_ID, "clid", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VV),                     //clid!
-                make_shared<PropertyDescription>(CLIENT_HARDWARE_ID, "hwid", "", TYPE_STRING, FLAG_SAVE),                     //hwid!
-                make_shared<PropertyDescription>(CLIENT_CHANNEL_GROUP_ID, "CLIENT_CHANNEL_GROUP_ID", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VIEW),                //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, holds database manager id
-                make_shared<PropertyDescription>(CLIENT_SERVERGROUPS, "CLIENT_SERVERGROUPS", "0", TYPE_STRING, FLAG_CLIENT_VIEW),                    //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, holds all servergroups manager belongs too
-                make_shared<PropertyDescription>(CLIENT_CREATED, "CLIENT_CREATED", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VARIABLE | FLAG_SAVE_MUSIC | FLAG_SNAPSHOT | FLAG_GLOBAL),                         //this needs to be requested (=> requestClientVariables), first time this manager connected to this server
-                make_shared<PropertyDescription>(CLIENT_LASTCONNECTED, "CLIENT_LASTCONNECTED", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VARIABLE | FLAG_SNAPSHOT | FLAG_GLOBAL),                   //this needs to be requested (=> requestClientVariables), last time this manager connected to this server
-                make_shared<PropertyDescription>(CLIENT_TOTALCONNECTIONS, "CLIENT_TOTALCONNECTIONS", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VARIABLE | FLAG_CLIENT_VIEW | FLAG_SNAPSHOT | FLAG_GLOBAL),                //this needs to be requested (=> requestClientVariables), how many times this manager connected to this server
-                make_shared<PropertyDescription>(CLIENT_AWAY, "CLIENT_AWAY", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE),                            //automatically up-to-date for any manager "in view", this clients away status
-                make_shared<PropertyDescription>(CLIENT_AWAY_MESSAGE, "CLIENT_AWAY_MESSAGE", "", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE),                    //automatically up-to-date for any manager "in view", this clients away message
-                make_shared<PropertyDescription>(CLIENT_TYPE, "CLIENT_TYPE", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VIEW | FLAG_GLOBAL),                            //automatically up-to-date for any manager "in view", determines if this is a real manager or a server-query connection
-                make_shared<PropertyDescription>(CLIENT_TYPE_EXACT, "CLIENT_TYPE_EXACT", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VIEW | FLAG_NEW | FLAG_GLOBAL),                            //automatically up-to-date for any manager "in view", determines if this is a real manager or a server-query connection
-                make_shared<PropertyDescription>(CLIENT_FLAG_AVATAR, "CLIENT_FLAG_AVATAR", "", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_SAVE | FLAG_USER_EDITABLE),                     //automatically up-to-date for any manager "in view", this manager got an avatar
-                make_shared<PropertyDescription>(CLIENT_TALK_POWER, "CLIENT_TALK_POWER", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VIEW),                      //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, holds database manager id
-                make_shared<PropertyDescription>(CLIENT_TALK_REQUEST, "CLIENT_TALK_REQUEST", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE),                    //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, holds timestamp where manager requested to talk
-                make_shared<PropertyDescription>(CLIENT_TALK_REQUEST_MSG, "CLIENT_TALK_REQUEST_MSG", "", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE),                //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, holds matter for the request
-                make_shared<PropertyDescription>(CLIENT_DESCRIPTION, "CLIENT_DESCRIPTION", "", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_SS | FLAG_USER_EDITABLE),                     //automatically up-to-date for any manager "in view"
-                make_shared<PropertyDescription>(CLIENT_IS_TALKER, "CLIENT_IS_TALKER", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE),                       //automatically up-to-date for any manager "in view"
-                make_shared<PropertyDescription>(CLIENT_MONTH_BYTES_UPLOADED, "CLIENT_MONTH_BYTES_UPLOADED", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VARIABLE | FLAG_SAVE),            //this needs to be requested (=> requestClientVariables)
-                make_shared<PropertyDescription>(CLIENT_MONTH_BYTES_DOWNLOADED, "CLIENT_MONTH_BYTES_DOWNLOADED", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VARIABLE | FLAG_SAVE),          //this needs to be requested (=> requestClientVariables)
-                make_shared<PropertyDescription>(CLIENT_TOTAL_BYTES_UPLOADED, "CLIENT_TOTAL_BYTES_UPLOADED", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VARIABLE | FLAG_SAVE),            //this needs to be requested (=> requestClientVariables)
-                make_shared<PropertyDescription>(CLIENT_TOTAL_BYTES_DOWNLOADED, "CLIENT_TOTAL_BYTES_DOWNLOADED", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VARIABLE | FLAG_SAVE),          //this needs to be requested (=> requestClientVariables)
-                make_shared<PropertyDescription>(CLIENT_TOTAL_ONLINE_TIME, "CLIENT_TOTAL_ONLINE_TIME", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VARIABLE | FLAG_SAVE | FLAG_NEW),          //this needs to be requested (=> requestClientVariables)
-                make_shared<PropertyDescription>(CLIENT_MONTH_ONLINE_TIME, "CLIENT_MONTH_ONLINE_TIME", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VARIABLE | FLAG_SAVE | FLAG_NEW),          //this needs to be requested (=> requestClientVariables)
-                make_shared<PropertyDescription>(CLIENT_IS_PRIORITY_SPEAKER, "CLIENT_IS_PRIORITY_SPEAKER", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE),             //automatically up-to-date for any manager "in view"
-                make_shared<PropertyDescription>(CLIENT_UNREAD_MESSAGES, "CLIENT_UNREAD_MESSAGES", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VIEW),                 //automatically up-to-date for any manager "in view"
-                make_shared<PropertyDescription>(CLIENT_NICKNAME_PHONETIC, "CLIENT_NICKNAME_PHONETIC", "", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE),               //automatically up-to-date for any manager "in view"
-                make_shared<PropertyDescription>(CLIENT_NEEDED_SERVERQUERY_VIEW_POWER, "CLIENT_NEEDED_SERVERQUERY_VIEW_POWER", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VIEW),   //automatically up-to-date for any manager "in view"
-                make_shared<PropertyDescription>(CLIENT_DEFAULT_TOKEN, "CLIENT_DEFAULT_TOKEN", "", TYPE_STRING, FLAG_INTERNAL),                   //only usable for ourself, the default token we used to connect on our last connection attempt
-                make_shared<PropertyDescription>(CLIENT_ICON_ID, "CLIENT_ICON_ID", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VIEW | FLAG_CLIENT_VARIABLE),                         //automatically up-to-date for any manager "in view"
-                make_shared<PropertyDescription>(CLIENT_IS_CHANNEL_COMMANDER, "CLIENT_IS_CHANNEL_COMMANDER", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE | FLAG_SAVE_MUSIC),            //automatically up-to-date for any manager "in view"
-                make_shared<PropertyDescription>(CLIENT_COUNTRY, "CLIENT_COUNTRY", "TS", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_CLIENT_VARIABLE | FLAG_GLOBAL | FLAG_SAVE_MUSIC | FLAG_USER_EDITABLE),                         //automatically up-to-date for any manager "in view"
-                make_shared<PropertyDescription>(CLIENT_CHANNEL_GROUP_INHERITED_CHANNEL_ID, "CLIENT_CHANNEL_GROUP_INHERITED_CHANNEL_ID", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VIEW), //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, contains channel_id where the channel_group_id is set from
-                make_shared<PropertyDescription>(CLIENT_BADGES, "CLIENT_BADGES", "", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE),                          //automatically up-to-date for any manager "in view", stores icons for partner badges
-                make_shared<PropertyDescription>(CLIENT_MYTEAMSPEAK_ID, "CLIENT_MYTEAMSPEAK_ID", "", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_SS | FLAG_USER_EDITABLE),                          //automatically up-to-date for any manager "in view", stores icons for partner badges
-                make_shared<PropertyDescription>(CLIENT_INTEGRATIONS, "CLIENT_INTEGRATIONS", "", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE),                          //automatically up-to-date for any manager "in view", stores icons for partner badges
-                make_shared<PropertyDescription>(CLIENT_ACTIVE_INTEGRATIONS_INFO, "CLIENT_ACTIVE_INTEGRATIONS_INFO", "", TYPE_STRING, FLAG_INTERNAL | FLAG_USER_EDITABLE),
-
-                //Using FLAG_GLOBAL here,lse they will be overridden on clientinit
-                make_shared<PropertyDescription>(CLIENT_TEAFORO_ID, "CLIENT_TEAFORO_ID", "0", TYPE_UNSIGNED_NUMBER, FLAG_NEW | FLAG_CLIENT_VIEW | FLAG_GLOBAL),
-                make_shared<PropertyDescription>(CLIENT_TEAFORO_NAME, "CLIENT_TEAFORO_NAME", "", TYPE_STRING, FLAG_NEW | FLAG_CLIENT_VIEW | FLAG_GLOBAL),
-                make_shared<PropertyDescription>(CLIENT_TEAFORO_FLAGS, "CLIENT_TEAFORO_FLAGS", "0", TYPE_UNSIGNED_NUMBER, FLAG_NEW | FLAG_CLIENT_VIEW | FLAG_GLOBAL),
-
-                //Music bot stuff
-                make_shared<PropertyDescription>(CLIENT_OWNER, "CLIENT_OWNER", "0", TYPE_UNSIGNED_NUMBER, FLAG_NEW | FLAG_CLIENT_VIEW),
-                make_shared<PropertyDescription>(CLIENT_BOT_TYPE, "CLIENT_BOT_TYPE", "0", TYPE_UNSIGNED_NUMBER, FLAG_NEW | FLAG_SAVE_MUSIC | FLAG_USER_EDITABLE | FLAG_CLIENT_VIEW),
-                make_shared<PropertyDescription>(CLIENT_LAST_CHANNEL, "CLIENT_LAST_CHANNEL", "0", TYPE_UNSIGNED_NUMBER, FLAG_NEW | FLAG_INTERNAL | FLAG_SAVE_MUSIC),
-                make_shared<PropertyDescription>(CLIENT_PLAYER_STATE, "PLAYER_STATE", "0", TYPE_UNSIGNED_NUMBER, FLAG_NEW | FLAG_CLIENT_VIEW | FLAG_SAVE_MUSIC),
-                make_shared<PropertyDescription>(CLIENT_PLAYER_VOLUME, "PLAYER_VOLUME", "1", TYPE_FLOAT, FLAG_NEW | FLAG_SAVE_MUSIC | FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE),
-                make_shared<PropertyDescription>(CLIENT_PLAYLIST_ID, "CLIENT_PLAYLIST_ID", "0", TYPE_UNSIGNED_NUMBER, FLAG_NEW | FLAG_CLIENT_VARIABLE | FLAG_SAVE_MUSIC),
-                make_shared<PropertyDescription>(CLIENT_DISABLED, "CLIENT_DISABLED", "0", TYPE_BOOL, FLAG_NEW | FLAG_CLIENT_VARIABLE),
-                make_shared<PropertyDescription>(CLIENT_UPTIME_MODE, "CLIENT_UPTIME_MODE", "0", TYPE_UNSIGNED_NUMBER, FLAG_NEW | FLAG_CLIENT_VARIABLE | FLAG_USER_EDITABLE | FLAG_SAVE_MUSIC),
-                make_shared<PropertyDescription>(CLIENT_FLAG_NOTIFY_SONG_CHANGE, "CLIENT_FLAG_NOTIFY_SONG_CHANGE", "1", TYPE_BOOL, FLAG_NEW | FLAG_CLIENT_VARIABLE | FLAG_USER_EDITABLE | FLAG_SAVE_MUSIC)
-        };
-
-        #define str(s) #s
-        #define V(key, flags) key, str(key), "0", TYPE_UNSIGNED_NUMBER, flags
-        #define F(key, flags) key, str(key), "0", TYPE_FLOAT, flags
-
-        array<shared_ptr<PropertyDescription>, ConnectionProperties::CONNECTION_ENDMARKER> connection_info = {
-                make_shared<PropertyDescription>(CONNECTION_UNDEFINED, "CONNECTION_UNDEFINED", "undefined", TYPE_UNKNOWN, 0),
-                make_shared<PropertyDescription>(CONNECTION_PING, "CONNECTION_PING", "0", TYPE_UNSIGNED_NUMBER, 0),                                        //average latency for a round trip through and back this connection
-                make_shared<PropertyDescription>(CONNECTION_PING_DEVIATION, "CONNECTION_PING_DEVIATION", "0", TYPE_UNSIGNED_NUMBER, 0),                                  //standard deviation of the above average latency
-                make_shared<PropertyDescription>(CONNECTION_CONNECTED_TIME, "CONNECTION_CONNECTED_TIME", "0", TYPE_UNSIGNED_NUMBER, 0),                                  //how long the connection exists already
-                make_shared<PropertyDescription>(CONNECTION_IDLE_TIME, "CONNECTION_IDLE_TIME", "0", TYPE_UNSIGNED_NUMBER, 0),                                       //how long since the last action of this manager
-                make_shared<PropertyDescription>(CONNECTION_CLIENT_IP, "CONNECTION_CLIENT_IP", "", TYPE_STRING, FLAG_SAVE),                                      //NEED DB SAVE! //IP of this manager (as seen from the server side)
-                make_shared<PropertyDescription>(CONNECTION_CLIENT_PORT, "CONNECTION_CLIENT_PORT", "0", TYPE_UNSIGNED_NUMBER, 0),                                     //Port of this manager (as seen from the server side)
-                make_shared<PropertyDescription>(CONNECTION_SERVER_IP, "CONNECTION_SERVER_IP", "", TYPE_STRING, 0),                                       //IP of the server (seen from the manager side) - only available on yourself, not for remote clients, not available server side
-                make_shared<PropertyDescription>(CONNECTION_SERVER_PORT, "CONNECTION_SERVER_PORT", "0", TYPE_UNSIGNED_NUMBER, 0),                                     //Port of the server (seen from the manager side) - only available on yourself, not for remote clients, not available server side
-                make_shared<PropertyDescription>(V(CONNECTION_PACKETS_SENT_SPEECH, 0)),                             //how many Speech packets were sent through this connection
-                make_shared<PropertyDescription>(V(CONNECTION_PACKETS_SENT_KEEPALIVE, 0)),
-                make_shared<PropertyDescription>(V(CONNECTION_PACKETS_SENT_CONTROL,0)),
-                make_shared<PropertyDescription>(V(CONNECTION_PACKETS_SENT_TOTAL, FLAG_CLIENT_INFO)),                              //how many packets were sent totally (this is PACKETS_SENT_SPEECH + PACKETS_SENT_KEEPALIVE + PACKETS_SENT_CONTROL)
-                make_shared<PropertyDescription>(V(CONNECTION_BYTES_SENT_SPEECH, 0)),
-                make_shared<PropertyDescription>(V(CONNECTION_BYTES_SENT_KEEPALIVE, 0)),
-                make_shared<PropertyDescription>(V(CONNECTION_BYTES_SENT_CONTROL, 0)),
-                make_shared<PropertyDescription>(V(CONNECTION_BYTES_SENT_TOTAL, FLAG_CLIENT_INFO)),
-                make_shared<PropertyDescription>(V(CONNECTION_PACKETS_RECEIVED_SPEECH, 0)),
-                make_shared<PropertyDescription>(V(CONNECTION_PACKETS_RECEIVED_KEEPALIVE, 0)),
-                make_shared<PropertyDescription>(V(CONNECTION_PACKETS_RECEIVED_CONTROL, 0)),
-                make_shared<PropertyDescription>(V(CONNECTION_PACKETS_RECEIVED_TOTAL, FLAG_CLIENT_INFO)),
-                make_shared<PropertyDescription>(V(CONNECTION_BYTES_RECEIVED_SPEECH, 0)),
-                make_shared<PropertyDescription>(V(CONNECTION_BYTES_RECEIVED_KEEPALIVE, 0)),
-                make_shared<PropertyDescription>(V(CONNECTION_BYTES_RECEIVED_CONTROL, 0)),
-                make_shared<PropertyDescription>(V(CONNECTION_BYTES_RECEIVED_TOTAL, FLAG_CLIENT_INFO)),
-                make_shared<PropertyDescription>(F(CONNECTION_PACKETLOSS_SPEECH, 0)),
-                make_shared<PropertyDescription>(F(CONNECTION_PACKETLOSS_KEEPALIVE, 0)),
-                make_shared<PropertyDescription>(F(CONNECTION_PACKETLOSS_CONTROL, 0)),
-                make_shared<PropertyDescription>(F(CONNECTION_PACKETLOSS_TOTAL, FLAG_CLIENT_INFO)),                                //the probability with which a packet round trip failed because a packet was lost
-                make_shared<PropertyDescription>(F(CONNECTION_SERVER2CLIENT_PACKETLOSS_SPEECH, 0)),                 //the probability with which a speech packet failed from the server to the manager
-                make_shared<PropertyDescription>(F(CONNECTION_SERVER2CLIENT_PACKETLOSS_KEEPALIVE, 0)),
-                make_shared<PropertyDescription>(F(CONNECTION_SERVER2CLIENT_PACKETLOSS_CONTROL, 0)),
-                make_shared<PropertyDescription>(F(CONNECTION_SERVER2CLIENT_PACKETLOSS_TOTAL, FLAG_CLIENT_INFO)),
-                make_shared<PropertyDescription>(F(CONNECTION_CLIENT2SERVER_PACKETLOSS_SPEECH, 0)),
-                make_shared<PropertyDescription>(F(CONNECTION_CLIENT2SERVER_PACKETLOSS_KEEPALIVE, 0)),
-                make_shared<PropertyDescription>(F(CONNECTION_CLIENT2SERVER_PACKETLOSS_CONTROL, 0)),
-                make_shared<PropertyDescription>(F(CONNECTION_CLIENT2SERVER_PACKETLOSS_TOTAL, FLAG_CLIENT_INFO)),
-                make_shared<PropertyDescription>(V(CONNECTION_BANDWIDTH_SENT_LAST_SECOND_SPEECH, 0)),               //howmany bytes of speech packets we sent during the last second
-                make_shared<PropertyDescription>(V(CONNECTION_BANDWIDTH_SENT_LAST_SECOND_KEEPALIVE, 0)),
-                make_shared<PropertyDescription>(V(CONNECTION_BANDWIDTH_SENT_LAST_SECOND_CONTROL, 0)),
-                make_shared<PropertyDescription>(V(CONNECTION_BANDWIDTH_SENT_LAST_SECOND_TOTAL,FLAG_CLIENT_INFO)),
-                make_shared<PropertyDescription>(V(CONNECTION_BANDWIDTH_SENT_LAST_MINUTE_SPEECH,0)),               //howmany bytes/s of speech packets we sent in average during the last minute
-                make_shared<PropertyDescription>(V(CONNECTION_BANDWIDTH_SENT_LAST_MINUTE_KEEPALIVE,0)),
-                make_shared<PropertyDescription>(V(CONNECTION_BANDWIDTH_SENT_LAST_MINUTE_CONTROL,0)),
-                make_shared<PropertyDescription>(V(CONNECTION_BANDWIDTH_SENT_LAST_MINUTE_TOTAL,FLAG_CLIENT_INFO)),
-                make_shared<PropertyDescription>(V(CONNECTION_BANDWIDTH_RECEIVED_LAST_SECOND_SPEECH, 0)),
-                make_shared<PropertyDescription>(V(CONNECTION_BANDWIDTH_RECEIVED_LAST_SECOND_KEEPALIVE,0)),
-                make_shared<PropertyDescription>(V(CONNECTION_BANDWIDTH_RECEIVED_LAST_SECOND_CONTROL,0)),
-                make_shared<PropertyDescription>(V(CONNECTION_BANDWIDTH_RECEIVED_LAST_SECOND_TOTAL,FLAG_CLIENT_INFO)),
-                make_shared<PropertyDescription>(V(CONNECTION_BANDWIDTH_RECEIVED_LAST_MINUTE_SPEECH,0)),
-                make_shared<PropertyDescription>(V(CONNECTION_BANDWIDTH_RECEIVED_LAST_MINUTE_KEEPALIVE,0)),
-                make_shared<PropertyDescription>(V(CONNECTION_BANDWIDTH_RECEIVED_LAST_MINUTE_CONTROL,0)),
-                make_shared<PropertyDescription>(V(CONNECTION_BANDWIDTH_RECEIVED_LAST_MINUTE_TOTAL,FLAG_CLIENT_INFO)),
-
-                //Rare properties
-                make_shared<PropertyDescription>(V(CONNECTION_FILETRANSFER_BANDWIDTH_SENT, FLAG_CLIENT_INFO)),                     //how many bytes per second are currently being sent by file transfers
-                make_shared<PropertyDescription>(V(CONNECTION_FILETRANSFER_BANDWIDTH_RECEIVED, FLAG_CLIENT_INFO)),                 //how many bytes per second are currently being received by file transfers
-                make_shared<PropertyDescription>(V(CONNECTION_FILETRANSFER_BYTES_RECEIVED_TOTAL, FLAG_CLIENT_INFO)),               //how many bytes we received in total through file transfers
-                make_shared<PropertyDescription>(V(CONNECTION_FILETRANSFER_BYTES_SENT_TOTAL, FLAG_CLIENT_INFO))                   //how many bytes we sent in total through file transfers
-        };
-
-        array<shared_ptr<PropertyDescription>, InstanceProperties::SERVERINSTANCE_ENDMARKER> instance_info = {
-                make_shared<PropertyDescription>(SERVERINSTANCE_UNDEFINED, "SERVERINSTANCE_UNDEFINED", "undefined", TYPE_UNKNOWN, 0),
-                make_shared<PropertyDescription>(SERVERINSTANCE_DATABASE_VERSION, "SERVERINSTANCE_DATABASE_VERSION", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE),
-                make_shared<PropertyDescription>(SERVERINSTANCE_PERMISSIONS_VERSION, "SERVERINSTANCE_PERMISSIONS_VERSION", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE),
-                make_shared<PropertyDescription>(SERVERINSTANCE_FILETRANSFER_HOST, "SERVERINSTANCE_FILETRANSFER_HOST", "0.0.0.0,[::]", TYPE_STRING, FLAG_INSTANCE_VARIABLE | FLAG_SAVE),
-                make_shared<PropertyDescription>(SERVERINSTANCE_FILETRANSFER_PORT, "SERVERINSTANCE_FILETRANSFER_PORT", "30303", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE),
-                make_shared<PropertyDescription>(SERVERINSTANCE_FILETRANSFER_MAX_CONNECTIONS, "SERVERINSTANCE_FILETRANSFER_MAX_CONNECTIONS", "100", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE),
-                make_shared<PropertyDescription>(SERVERINSTANCE_FILETRANSFER_MAX_CONNECTIONS_PER_IP, "SERVERINSTANCE_FILETRANSFER_MAX_CONNECTIONS_PER_IP", "20", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE),
-                make_shared<PropertyDescription>(SERVERINSTANCE_QUERY_HOST, "SERVERINSTANCE_QUERY_HOST", "0.0.0.0,[::]", TYPE_STRING, FLAG_INSTANCE_VARIABLE | FLAG_SAVE),
-                make_shared<PropertyDescription>(SERVERINSTANCE_QUERY_PORT, "SERVERINSTANCE_QUERY_PORT", "10101", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE),
-                make_shared<PropertyDescription>(SERVERINSTANCE_QUERY_MAX_CONNECTIONS, "SERVERINSTANCE_QUERY_MAX_CONNECTIONS", "100", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE),
-                make_shared<PropertyDescription>(SERVERINSTANCE_QUERY_MAX_CONNECTIONS_PER_IP, "SERVERINSTANCE_QUERY_MAX_CONNECTIONS_PER_IP", "3", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE),
-                make_shared<PropertyDescription>(SERVERINSTANCE_MONTHLY_TIMESTAMP, "SERVERINSTANCE_MONTHLY_TIMESTAMP", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE),
-                make_shared<PropertyDescription>(SERVERINSTANCE_MAX_DOWNLOAD_TOTAL_BANDWIDTH, "SERVERINSTANCE_MAX_DOWNLOAD_TOTAL_BANDWIDTH", "-1", TYPE_SIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE),
-                make_shared<PropertyDescription>(SERVERINSTANCE_MAX_UPLOAD_TOTAL_BANDWIDTH, "SERVERINSTANCE_MAX_UPLOAD_TOTAL_BANDWIDTH", "-1", TYPE_SIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE),
-                make_shared<PropertyDescription>(SERVERINSTANCE_SERVERQUERY_FLOOD_COMMANDS, "SERVERINSTANCE_SERVERQUERY_FLOOD_COMMANDS", "3", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE),       //how many commands we can issue while in the SERVERINSTANCE_SERVERQUERY_FLOOD_TIME window
-                make_shared<PropertyDescription>(SERVERINSTANCE_SERVERQUERY_FLOOD_TIME, "SERVERINSTANCE_SERVERQUERY_FLOOD_TIME", "1", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE),           //time window in seconds for max command execution check
-                make_shared<PropertyDescription>(SERVERINSTANCE_SERVERQUERY_BAN_TIME, "SERVERINSTANCE_SERVERQUERY_BAN_TIME", "600", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE),             //how many seconds someone get banned if he floods
-                make_shared<PropertyDescription>(SERVERINSTANCE_TEMPLATE_SERVERADMIN_GROUP, "SERVERINSTANCE_TEMPLATE_SERVERADMIN_GROUP", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE),
-                make_shared<PropertyDescription>(SERVERINSTANCE_TEMPLATE_SERVERDEFAULT_GROUP, "SERVERINSTANCE_TEMPLATE_SERVERDEFAULT_GROUP", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE),
-                make_shared<PropertyDescription>(SERVERINSTANCE_TEMPLATE_CHANNELADMIN_GROUP, "SERVERINSTANCE_TEMPLATE_CHANNELADMIN_GROUP", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE),
-                make_shared<PropertyDescription>(SERVERINSTANCE_TEMPLATE_CHANNELDEFAULT_GROUP, "SERVERINSTANCE_TEMPLATE_CHANNELDEFAULT_GROUP", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE),
-                make_shared<PropertyDescription>(SERVERINSTANCE_TEMPLATE_MUSICDEFAULT_GROUP, "SERVERINSTANCE_TEMPLATE_MUSICDEFAULT_GROUP", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE),
-                make_shared<PropertyDescription>(SERVERINSTANCE_GUEST_SERVERQUERY_GROUP, "SERVERINSTANCE_GUEST_SERVERQUERY_GROUP", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE),
-                make_shared<PropertyDescription>(SERVERINSTANCE_ADMIN_SERVERQUERY_GROUP, "SERVERINSTANCE_ADMIN_SERVERQUERY_GROUP", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE),
-                make_shared<PropertyDescription>(SERVERINSTANCE_PENDING_CONNECTIONS_PER_IP, "SERVERINSTANCE_PENDING_CONNECTIONS_PER_IP", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE),
-                make_shared<PropertyDescription>(SERVERINSTANCE_SPOKEN_TIME_TOTAL, "SERVERINSTANCE_SPOKEN_TIME_TOTAL", "0", TYPE_UNSIGNED_NUMBER, FLAG_INTERNAL | FLAG_SAVE | FLAG_NEW),
-                make_shared<PropertyDescription>(SERVERINSTANCE_SPOKEN_TIME_DELETED, "SERVERINSTANCE_SPOKEN_TIME_DELETED", "0", TYPE_UNSIGNED_NUMBER, FLAG_INTERNAL | FLAG_SAVE | FLAG_NEW),
-                make_shared<PropertyDescription>(SERVERINSTANCE_SPOKEN_TIME_ALIVE, "SERVERINSTANCE_SPOKEN_TIME_ALIVE", "0", TYPE_UNSIGNED_NUMBER, FLAG_INTERNAL | FLAG_SAVE | FLAG_NEW),
-                make_shared<PropertyDescription>(SERVERINSTANCE_SPOKEN_TIME_VARIANZ, "SERVERINSTANCE_SPOKEN_TIME_VARIANZ", "0", TYPE_UNSIGNED_NUMBER, FLAG_INTERNAL | FLAG_SAVE | FLAG_NEW),
-                make_shared<PropertyDescription>(SERVERINSTANCE_VIRTUAL_SERVER_ID_INDEX, "SERVERINSTANCE_VIRTUAL_SERVER_ID_INDEX", "1", TYPE_UNSIGNED_NUMBER, FLAG_SAVE | FLAG_INSTANCE_VARIABLE | FLAG_NEW),
-                make_shared<PropertyDescription>(SERVERINSTANCE_UNIQUE_ID, "SERVERINSTANCE_UNIQUE_ID", "", TYPE_STRING, FLAG_INTERNAL | FLAG_SAVE | FLAG_NEW),
-        };
-
-
-        array<shared_ptr<PropertyDescription>, PlaylistProperties::PLAYLIST_ENDMARKER> playlist_info = {
-                make_shared<PropertyDescription>(PLAYLIST_UNDEFINED, "PLAYLIST_UNDEFINED", "undefined", TYPE_UNKNOWN, 0),
-                make_shared<PropertyDescription>(PLAYLIST_ID, "PLAYLIST_ID", "0", TYPE_UNSIGNED_NUMBER, FLAG_PLAYLIST_VARIABLE),
-                make_shared<PropertyDescription>(PLAYLIST_TYPE, "PLAYLIST_TYPE", "0", TYPE_UNSIGNED_NUMBER, FLAG_PLAYLIST_VARIABLE | FLAG_SAVE),
-                make_shared<PropertyDescription>(PLAYLIST_TITLE, "PLAYLIST_TITLE", "Yet another playlist", TYPE_STRING, FLAG_PLAYLIST_VARIABLE | FLAG_USER_EDITABLE | FLAG_SAVE),
-                make_shared<PropertyDescription>(PLAYLIST_DESCRIPTION, "PLAYLIST_DESCRIPTION", "", TYPE_STRING, FLAG_PLAYLIST_VARIABLE | FLAG_USER_EDITABLE | FLAG_SAVE),
-                make_shared<PropertyDescription>(PLAYLIST_OWNER_DBID, "PLAYLIST_OWNER_DBID", "0", TYPE_UNSIGNED_NUMBER, FLAG_PLAYLIST_VARIABLE | FLAG_SAVE),
-                make_shared<PropertyDescription>(PLAYLIST_OWNER_NAME, "PLAYLIST_OWNER_NAME", "0", TYPE_STRING, FLAG_PLAYLIST_VARIABLE | FLAG_SAVE),
-                make_shared<PropertyDescription>(PLAYLIST_FLAG_DELETE_PLAYED, "PLAYLIST_FLAG_DELETE_PLAYED", "1", TYPE_BOOL, FLAG_PLAYLIST_VARIABLE | FLAG_USER_EDITABLE | FLAG_SAVE),
-                make_shared<PropertyDescription>(PLAYLIST_REPLAY_MODE, "PLAYLIST_REPLAY_MODE", "0", TYPE_UNSIGNED_NUMBER, FLAG_PLAYLIST_VARIABLE | FLAG_USER_EDITABLE | FLAG_SAVE),
-                make_shared<PropertyDescription>(PLAYLIST_CURRENT_SONG_ID, "PLAYLIST_CURRENT_SONG_ID", "0", TYPE_UNSIGNED_NUMBER, FLAG_PLAYLIST_VARIABLE | FLAG_SAVE),
-                make_shared<PropertyDescription>(PLAYLIST_FLAG_FINISHED, "PLAYLIST_FLAG_FINISHED", "0", TYPE_BOOL, FLAG_PLAYLIST_VARIABLE | FLAG_USER_EDITABLE | FLAG_SAVE),
-                make_shared<PropertyDescription>(PLAYLIST_MAX_SONGS, "PLAYLIST_MAX_SONGS", "-1", TYPE_SIGNED_NUMBER, FLAG_PLAYLIST_VARIABLE | FLAG_USER_EDITABLE | FLAG_SAVE),
-        };
-
-        shared_ptr<PropertyDescription> PropertyDescription::unknown = make_shared<PropertyDescription>(UNKNOWN_UNDEFINED, "undefined", "", ValueType::TYPE_UNKNOWN, 0);
         namespace impl {
-            #define M(type, _info)                                                   \
-            template <>                                                             \
-            const std::shared_ptr<property::PropertyDescription>& info<type>(type type) {                      \
-                for(const auto& element : (_info))                                   \
-                    if(element->property_index == (type))                                  \
-                        return element;                                             \
-                return (_info)[0];                                                   \
-            }                                                                       \
-                                                                                    \
-            template <>                                                             \
-            const std::shared_ptr<property::PropertyDescription>& info<type>(const std::string& _type) {       \
-                for(const auto& element : (_info))                                   \
-                    if(element->name == _type)                                       \
-                        return element;                                             \
-                return (_info)[0];                                                   \
-            }                                                                       \
-                                                                                    \
-                                                                                    \
-            template <>                                                             \
-            std::deque<std::shared_ptr<property::PropertyDescription>> list<type>() {                             \
-                return {_info.begin(), _info.end()};                                  \
-            }
-
-            M(VirtualServerProperties, virtualserver_info);
-            M(ChannelProperties, channel_info);
-            M(GroupProperties, group_info);
-            M(ClientProperties, client_info);
-            M(ConnectionProperties, connection_info);
-            M(InstanceProperties, instance_info);
-            M(PlaylistProperties, playlist_info);
-
-
-            #define TP(info) \
-            { for(const auto& prop : (info)) \
-                if(prop->name == key) return prop; }
-
-            const std::shared_ptr<property::PropertyDescription>& info_key(const std::string& key) {
-                TP(virtualserver_info);
-                TP(channel_info);
-                TP(group_info);
-                TP(client_info);
-                TP(connection_info);
-                TP(instance_info);
-                TP(playlist_info);
-                return PropertyDescription::unknown;
-            }
-
-
-            const std::shared_ptr<property::PropertyDescription>& info_key(PropertyType type, const std::string& key) {
-                if(type == PropertyType::PROP_TYPE_SERVER)
-                    TP(virtualserver_info)
-                else if(type == PropertyType::PROP_TYPE_CHANNEL)
-                    TP(channel_info)
-                else if(type == PropertyType::PROP_TYPE_CLIENT)
-                    TP(client_info)
-                else if(type == PropertyType::PROP_TYPE_GROUP)
-                    TP(group_info)
-                else if(type == PropertyType::PROP_TYPE_CONNECTION)
-                    TP(connection_info)
-                else if(type == PropertyType::PROP_TYPE_INSTANCE)
-                    TP(instance_info)
-                else if(type == PropertyType::PROP_TYPE_PLAYLIST)
-                    TP(playlist_info);
-                return PropertyDescription::unknown;
-            }
-
-            const std::shared_ptr<property::PropertyDescription>& info(PropertyType type, int index) {
-                if(type == PropertyType::PROP_TYPE_SERVER)
-                    return impl::info<VirtualServerProperties>((VirtualServerProperties) index);
-                else if(type == PropertyType::PROP_TYPE_CHANNEL)
-                    return impl::info<ChannelProperties>((ChannelProperties) index);
-                else if(type == PropertyType::PROP_TYPE_CLIENT)
-                    return impl::info<ClientProperties>((ClientProperties) index);
-                else if(type == PropertyType::PROP_TYPE_GROUP)
-                    return impl::info<GroupProperties>((GroupProperties) index);
-                else if(type == PropertyType::PROP_TYPE_CONNECTION)
-                    return impl::info<ConnectionProperties>((ConnectionProperties) index);
-                else if(type == PropertyType::PROP_TYPE_INSTANCE)
-                    return impl::info<InstanceProperties>((InstanceProperties) index);
-                else if(type == PropertyType::PROP_TYPE_PLAYLIST)
-                    return impl::info<PlaylistProperties>((PlaylistProperties) index);
-                return PropertyDescription::unknown;
-            }
-
-            #define M1(info)                                                                        \
-            for(const auto& e : (info)){                                                            \
-                auto found = find(used.begin(), used.end(), e->name);                                \
-                if(found != used.end()) {                                                           \
-                    cerr << "[CRITICAL] Double registered property! (" << e->name << ")" << endl;    \
-                    return false;                                                                   \
-                }                                                                                   \
-                used.push_back(e->name);                                                             \
-            }
-
-            bool validateUnique() {
-                deque<string> used;
-                M1(virtualserver_info);
-                M1(channel_info);
-                M1(group_info);
-                M1(client_info);
-                M1(connection_info);
-                M1(instance_info);
-                M1(playlist_info);
-                return true;
-            }
-
             bool validateInput(const std::string& input, ValueType type) {
                 if(type == ValueType::TYPE_UNKNOWN) return true;
                 else if(type == ValueType::TYPE_UNSIGNED_NUMBER) {
diff --git a/src/Properties.h b/src/Properties.h
index 6744781..df34b45 100644
--- a/src/Properties.h
+++ b/src/Properties.h
@@ -17,9 +17,11 @@
 #include "misc/spin_lock.h"
 #include "converters/converter.h"
 
-#define PROPS_DEFINED
-namespace ts {
+#ifdef NDEBUG
+    #define EXTERNALIZE_PROPERTY_DEFINITIONS
+#endif
 
+namespace ts {
     namespace property {
         enum PropertyType {
             PROP_TYPE_SERVER = 0,
@@ -29,8 +31,10 @@ namespace ts {
             PROP_TYPE_INSTANCE = 4,
             PROP_TYPE_CONNECTION = 5,
             PROP_TYPE_PLAYLIST = 6,
-            PROP_TYPE_UNKNOWN = 7
+            PROP_TYPE_UNKNOWN = 7,
+            PROP_TYPE_MAX
         };
+
         static constexpr const char *PropertyType_Names[7] = {
                 "SERVER",
                 "CHANNEL",
@@ -134,12 +138,12 @@ namespace ts {
             VIRTUALSERVER_MAXCLIENTS,                        //only available on request (=> requestServerVariables), stores the maximum number of clients that may currently join the server
             VIRTUALSERVER_PASSWORD,                          //not available to clients, the server password
             VIRTUALSERVER_CLIENTS_ONLINE,                    //only available on request (=> requestServerVariables),
+            VIRTUALSERVER_QUERYCLIENTS_ONLINE,                         //only available on request (=> requestServerVariables)
             VIRTUALSERVER_CHANNELS_ONLINE,                   //only available on request (=> requestServerVariables),
             VIRTUALSERVER_CREATED,                           //available when connected, stores the time when the server was created
             VIRTUALSERVER_UPTIME,                            //only available on request (=> requestServerVariables), the time since the server was started
-            VIRTUALSERVER_CODEC_ENCRYPTION_MODE,             //available and always up-to-date when connected
 
-            //Rare properties
+            VIRTUALSERVER_CODEC_ENCRYPTION_MODE,             //available and always up-to-date when connected
             VIRTUALSERVER_KEYPAIR,                                     //internal use
             VIRTUALSERVER_HOSTMESSAGE,                                 //available when connected, not updated while connected
             VIRTUALSERVER_HOSTMESSAGE_MODE,                            //available when connected, not updated while connected
@@ -154,6 +158,7 @@ namespace ts {
             VIRTUALSERVER_HOSTBANNER_URL,                              //available when connected, always up-to-date
             VIRTUALSERVER_HOSTBANNER_GFX_URL,                          //available when connected, always up-to-date
             VIRTUALSERVER_HOSTBANNER_GFX_INTERVAL,                     //available when connected, always up-to-date
+            VIRTUALSERVER_HOSTBANNER_MODE,                             //available when connected, always up-to-date
             VIRTUALSERVER_COMPLAIN_AUTOBAN_COUNT,                      //only available on request (=> requestServerVariables)
             VIRTUALSERVER_COMPLAIN_AUTOBAN_TIME,                       //only available on request (=> requestServerVariables)
             VIRTUALSERVER_COMPLAIN_REMOVE_TIME,                        //only available on request (=> requestServerVariables)
@@ -168,7 +173,6 @@ namespace ts {
             VIRTUALSERVER_HOSTBUTTON_TOOLTIP,                          //available when connected, always up-to-date
             VIRTUALSERVER_HOSTBUTTON_URL,                              //available when connected, always up-to-date
             VIRTUALSERVER_HOSTBUTTON_GFX_URL,                          //available when connected, always up-to-date
-            VIRTUALSERVER_QUERYCLIENTS_ONLINE,                         //only available on request (=> requestServerVariables)
             VIRTUALSERVER_DOWNLOAD_QUOTA,                              //only available on request (=> requestServerVariables)
             VIRTUALSERVER_UPLOAD_QUOTA,                                //only available on request (=> requestServerVariables)
             VIRTUALSERVER_MONTH_BYTES_DOWNLOADED,                      //only available on request (=> requestServerVariables)
@@ -176,6 +180,7 @@ namespace ts {
             VIRTUALSERVER_TOTAL_BYTES_DOWNLOADED,                      //only available on request (=> requestServerVariables)
             VIRTUALSERVER_TOTAL_BYTES_UPLOADED,                        //only available on request (=> requestServerVariables)
             VIRTUALSERVER_PORT,                                        //only available on request (=> requestServerVariables)
+            VIRTUALSERVER_HOST,                                        //internal use | contains comma separated ip list
             VIRTUALSERVER_AUTOSTART,                                   //only available on request (=> requestServerVariables)
             VIRTUALSERVER_MACHINE_ID,                                  //only available on request (=> requestServerVariables)
             VIRTUALSERVER_NEEDED_IDENTITY_SECURITY_LEVEL,              //only available on request (=> requestServerVariables)
@@ -185,7 +190,6 @@ namespace ts {
             VIRTUALSERVER_LOG_PERMISSIONS,                             //only available on request (=> requestServerVariables)
             VIRTUALSERVER_LOG_SERVER,                                  //only available on request (=> requestServerVariables)
             VIRTUALSERVER_LOG_FILETRANSFER,                            //only available on request (=> requestServerVariables)
-            VIRTUALSERVER_MIN_CLIENT_VERSION,                          //only available on request (=> requestServerVariables)
             VIRTUALSERVER_NAME_PHONETIC,                               //available when connected, always up-to-date
             VIRTUALSERVER_ICON_ID,                                     //available when connected, always up-to-date
             VIRTUALSERVER_RESERVED_SLOTS,                              //available when connected, always up-to-date
@@ -194,12 +198,11 @@ namespace ts {
             VIRTUALSERVER_TOTAL_PACKETLOSS_CONTROL,                    //only available on request (=> requestServerVariables)
             VIRTUALSERVER_TOTAL_PACKETLOSS_TOTAL,                      //only available on request (=> requestServerVariables)
             VIRTUALSERVER_TOTAL_PING,                                  //only available on request (=> requestServerVariables)
-            VIRTUALSERVER_HOST,                                        //internal use | contains comma separated ip list
             VIRTUALSERVER_WEBLIST_ENABLED,                             //only available on request (=> requestServerVariables)
             VIRTUALSERVER_AUTOGENERATED_PRIVILEGEKEY,                  //internal use
             VIRTUALSERVER_ASK_FOR_PRIVILEGEKEY,                        //available when connected
-            VIRTUALSERVER_HOSTBANNER_MODE,                             //available when connected, always up-to-date
             VIRTUALSERVER_CHANNEL_TEMP_DELETE_DELAY_DEFAULT,           //available when connected, always up-to-date
+            VIRTUALSERVER_MIN_CLIENT_VERSION,                          //only available on request (=> requestServerVariables)
             VIRTUALSERVER_MIN_ANDROID_VERSION,                         //only available on request (=> requestServerVariables)
             VIRTUALSERVER_MIN_IOS_VERSION,                             //only available on request (=> requestServerVariables)
             VIRTUALSERVER_MIN_WINPHONE_VERSION,                        //only available on request (=> requestServerVariables)
@@ -223,7 +226,6 @@ namespace ts {
             VIRTUALSERVER_DISABLE_IP_SAVING,
 
             VIRTUALSERVER_COUNTRY_CODE,
-
             VIRTUALSERVER_ENDMARKER
         };
 
@@ -347,21 +349,21 @@ namespace ts {
             CLIENT_INTEGRATIONS,
             CLIENT_ACTIVE_INTEGRATIONS_INFO,
 
+            CLIENT_TEAFORO_ID,
+            CLIENT_TEAFORO_NAME,
+            CLIENT_TEAFORO_FLAGS,
+
             //Music bot stuff
-            CLIENT_BOT_TYPE,
             CLIENT_OWNER,
-            CLIENT_PLAYER_VOLUME,
+            CLIENT_BOT_TYPE,
             CLIENT_LAST_CHANNEL,
             CLIENT_PLAYER_STATE,
+            CLIENT_PLAYER_VOLUME,
             CLIENT_PLAYLIST_ID,
             CLIENT_DISABLED,
             CLIENT_UPTIME_MODE,
             CLIENT_FLAG_NOTIFY_SONG_CHANGE,
 
-            CLIENT_TEAFORO_ID,
-            CLIENT_TEAFORO_NAME,
-            CLIENT_TEAFORO_FLAGS,
-
             CLIENT_ENDMARKER
         };
 
@@ -462,146 +464,212 @@ namespace ts {
         };
          */
 
-        class PropertyDescription;
         namespace impl {
-            template<typename T>
-            extern std::deque<std::shared_ptr<property::PropertyDescription>> list();
-            extern std::deque<std::shared_ptr<property::PropertyDescription>> list_all();
-
-            template<typename T>
-            extern const std::shared_ptr<property::PropertyDescription> &info(T /* property */);
-
-            template<typename T>
-            extern const std::shared_ptr<property::PropertyDescription> &info(const std::string& /* key */);
-
-
-            extern const std::shared_ptr<property::PropertyDescription> &info_key(const std::string &);
-            extern const std::shared_ptr<property::PropertyDescription> &info_key(PropertyType, const std::string &);
-            extern const std::shared_ptr<property::PropertyDescription> &info(PropertyType, int);
-
-            template<typename V>
-            inline PropertyType type() {
-                std::cerr << "[CRITICAL] Invalid property type!" << std::endl;
-                return PropertyType::PROP_TYPE_UNKNOWN;
+            template <typename... Properties>
+            constexpr auto make_property_array(Properties&&... props) noexcept {
+                return std::array<std::common_type_t<Properties...>, sizeof...(Properties)>{std::forward<Properties>(props)...};
             }
 
-            template<>
-            constexpr inline PropertyType type<VirtualServerProperties>() { return PropertyType::PROP_TYPE_SERVER; }
-
-            template<>
-            constexpr inline PropertyType type<ChannelProperties>() { return PropertyType::PROP_TYPE_CHANNEL; }
-
-            template<>
-            constexpr inline PropertyType type<ClientProperties>() { return PropertyType::PROP_TYPE_CLIENT; }
-
-            template<>
-            constexpr inline PropertyType type<ConnectionProperties>() { return PropertyType::PROP_TYPE_CONNECTION; }
-
-            template<>
-            constexpr inline PropertyType type<GroupProperties>() { return PropertyType::PROP_TYPE_GROUP; }
-
-            template<>
-            constexpr inline PropertyType type<InstanceProperties>() { return PropertyType::PROP_TYPE_INSTANCE; }
-
-            template<>
-            constexpr inline PropertyType type<PlaylistProperties>() { return PropertyType::PROP_TYPE_PLAYLIST; }
-
-            template<>
-            constexpr inline PropertyType type<UnknownProperties>() { return PropertyType::PROP_TYPE_UNKNOWN; }
-
-            inline size_t length(PropertyType type) {
-                switch (type) {
-                    case PROP_TYPE_SERVER:
-                        return VIRTUALSERVER_ENDMARKER - VIRTUALSERVER_BEGINMARKER;
-                    case PROP_TYPE_CHANNEL:
-                        return CHANNEL_ENDMARKER - CHANNEL_BEGINMARKER;
-                    case PROP_TYPE_CLIENT:
-                        return CLIENT_ENDMARKER - CLIENT_BEGINMARKER;
-                    case PROP_TYPE_CONNECTION:
-                        return CONNECTION_ENDMARKER - CONNECTION_BEGINMARKER;
-                    case PROP_TYPE_GROUP:
-                        return GROUP_ENDMARKER - GROUP_BEGINMARKER;
-                    case PROP_TYPE_INSTANCE:
-                        return SERVERINSTANCE_ENDMARKER - SERVERINSTANCE_BEGINMARKER;
-                    case PROP_TYPE_PLAYLIST:
-                        return PLAYLIST_ENDMARKER - PLAYLIST_BEGINMARKER;
-                    case PROP_TYPE_UNKNOWN:
-                        return UNKNOWN_ENDMARKER - UNKNOWN_BEGINMARKER;
-                    default:
-                        return 0;
-                }
-            }
-
-            inline size_t offset(PropertyType type) {
-                switch (type) {
-                    case PROP_TYPE_SERVER:
-                        return VIRTUALSERVER_BEGINMARKER;
-                    case PROP_TYPE_CHANNEL:
-                        return CHANNEL_BEGINMARKER;
-                    case PROP_TYPE_CLIENT:
-                        return CLIENT_BEGINMARKER;
-                    case PROP_TYPE_CONNECTION:
-                        return CONNECTION_BEGINMARKER;
-                    case PROP_TYPE_GROUP:
-                        return GROUP_BEGINMARKER;
-                    case PROP_TYPE_INSTANCE:
-                        return SERVERINSTANCE_BEGINMARKER;
-                    case PROP_TYPE_PLAYLIST:
-                        return PLAYLIST_BEGINMARKER;
-                    case PROP_TYPE_UNKNOWN:
-                        return UNKNOWN_BEGINMARKER;
-                    default:
-                        return 0;
-                }
-            }
-
-            extern bool validateUnique();
-
-            extern bool validateInput(const std::string &, ValueType);
+            extern bool validateInput(const std::string& input, ValueType type);
         }
 
+        template<typename>
+        constexpr inline PropertyType type_from_enum();
 
-        template<typename T>
-        inline const std::shared_ptr<property::PropertyDescription> &info(T property) { return impl::info<T>(property); }
+        template<>
+        constexpr inline PropertyType type_from_enum<VirtualServerProperties>() { return PropertyType::PROP_TYPE_SERVER; }
 
-        template<typename T>
-        inline const std::shared_ptr<property::PropertyDescription> &info(const std::string& key) { return impl::info<T>(key); }
+        template<>
+        constexpr inline PropertyType type_from_enum<ChannelProperties>() { return PropertyType::PROP_TYPE_CHANNEL; }
 
-        class PropertyDescription {
-            public:
-                static std::shared_ptr<PropertyDescription> unknown;
+        template<>
+        constexpr inline PropertyType type_from_enum<ClientProperties>() { return PropertyType::PROP_TYPE_CLIENT; }
 
-                std::string name;
-                std::string default_value;
+        template<>
+        constexpr inline PropertyType type_from_enum<ConnectionProperties>() { return PropertyType::PROP_TYPE_CONNECTION; }
 
-                ValueType type_value = property::ValueType::TYPE_UNKNOWN;
-                PropertyType type_property = PropertyType::PROP_TYPE_UNKNOWN;
+        template<>
+        constexpr inline PropertyType type_from_enum<GroupProperties>() { return PropertyType::PROP_TYPE_GROUP; }
 
-                int property_index = 0;
-                flag_type flags = 0;
+        template<>
+        constexpr inline PropertyType type_from_enum<InstanceProperties>() { return PropertyType::PROP_TYPE_INSTANCE; }
 
-                PropertyDescription(int property_id, PropertyType property_type, const std::string &name, const std::string &default_value, property::ValueType type, flag_type flags) noexcept;
+        template<>
+        constexpr inline PropertyType type_from_enum<PlaylistProperties>() { return PropertyType::PROP_TYPE_PLAYLIST; }
 
-                template<typename T>
-                PropertyDescription(T property, const std::string &name, const std::string &default_value, property::ValueType type, flag_type flags) noexcept : PropertyDescription((int) property, impl::type<T>(), name, default_value, type, flags) {}
+        template<>
+        constexpr inline PropertyType type_from_enum<UnknownProperties>() { return PropertyType::PROP_TYPE_UNKNOWN; }
 
-                inline bool operator==(const PropertyDescription& other) const {
-                    return other.property_index == this->property_index && other.type_property == this->type_property;
-                }
+        struct PropertyDescription {
+            std::string_view name{};
+            std::string_view default_value{};
 
-                inline bool operator==(const std::shared_ptr<PropertyDescription>& other) const {
-                    return this->operator==(*other);
-                }
+            //TODO: Rename these sucky variables
+            ValueType type_value{property::ValueType::TYPE_UNKNOWN};
+            PropertyType type_property{PropertyType::PROP_TYPE_UNKNOWN};
 
-                template <typename T, typename std::enable_if<std::is_enum<T>::value, int>::type = 0>
-                inline bool operator==(const T& type) const {
-                    return this->property_index == type && impl::type<T>() == this->type_property;
-                }
+            int property_index{0};
+            flag_type flags{0};
 
-                inline bool validate_input(const std::string& input) {
-                    return impl::validateInput(input, this->type_value);
-                }
+            template <typename PropertyEnumType, typename std::enable_if<std::is_enum<PropertyEnumType>::value, int>::type = 0>
+            constexpr PropertyDescription(PropertyEnumType property, std::string_view name, std::string_view default_value, property::ValueType value_type, flag_type flags) noexcept
+                : name{name}, default_value{default_value}, type_value{value_type}, type_property{type_from_enum<PropertyEnumType>()},
+                  property_index{(int) property}, flags{flags} { }
+            PropertyDescription(const PropertyDescription&) = delete;
+            PropertyDescription(PropertyDescription&&) = default;
+
+            constexpr inline bool operator==(const PropertyDescription& other) const {
+                return this->property_index == other.property_index && this->type_property == other.type_property;
+            }
+
+            template <typename PropertyEnumType, typename std::enable_if<std::is_enum<PropertyEnumType>::value, int>::type = 0>
+            constexpr inline bool operator==(const PropertyEnumType& other) const {
+                return this->property_index == (int) other && this->type_property == type_from_enum<PropertyEnumType>();
+            }
+
+            inline bool validate_input(const std::string& value) const { return impl::validateInput(value, this->type_value); }
         };
+        constexpr static PropertyDescription undefined_property_description{UnknownProperties::UNKNOWN_UNDEFINED, "undefined", "", ValueType::TYPE_UNKNOWN, 0};
+
+        struct PropertyListInfo {
+            std::array<size_t, PropertyType::PROP_TYPE_MAX> begin_index{}; /* inclusive */
+            std::array<size_t, PropertyType::PROP_TYPE_MAX> end_index{}; /* exclusive */
+        };
+
+#ifdef EXTERNALIZE_PROPERTY_DEFINITIONS
+        constexpr inline auto property_count() {
+            size_t result{0};
+            result += VIRTUALSERVER_ENDMARKER;
+            result += CHANNEL_ENDMARKER;
+            result += CLIENT_ENDMARKER;
+            result += GROUP_ENDMARKER;
+            result += SERVERINSTANCE_ENDMARKER;
+            result += CONNECTION_ENDMARKER;
+            result += PLAYLIST_ENDMARKER;
+            result += UNKNOWN_ENDMARKER;
+            return result;
+        }
+        extern std::array<PropertyDescription, property_count()> property_list;
+#else
+        #include "./PropertyDefinition.h"
+
+        constexpr inline auto property_count() {
+            return property_list.size();
+        }
+#endif
+
+#ifdef EXTERNALIZE_PROPERTY_DEFINITIONS
+    #define const_modifier
+#else
+    #define const_modifier constexpr
+#endif
+        namespace impl {
+            const_modifier inline size_t property_type_begin(PropertyType type) {
+                size_t index{0};
+                for(; index < property_list.size(); index++)
+                    if(property_list[index].type_property == type)
+                        return index;
+                return property_list.size();
+            }
+
+            const_modifier inline size_t property_type_end(size_t begin, PropertyType type) {
+                size_t index{begin};
+                for(; index < property_list.size() - 1; index++)
+                    if(property_list[index + 1].type_property != type)
+                        return index;
+                return property_list.size();
+            }
+
+            const_modifier inline PropertyListInfo list_info() noexcept {
+                std::array<size_t, PropertyType::PROP_TYPE_MAX> begin_index{
+                    /* We're using numbers here so we don't mess up the order. This would be fatal */
+                    property_type_begin((PropertyType) 0),
+                    property_type_begin((PropertyType) 1),
+                    property_type_begin((PropertyType) 2),
+                    property_type_begin((PropertyType) 3),
+                    property_type_begin((PropertyType) 4),
+                    property_type_begin((PropertyType) 5),
+                    property_type_begin((PropertyType) 6),
+                    property_type_begin((PropertyType) 7)
+                };
+
+                return {
+                        begin_index,
+                        std::array<size_t, PropertyType::PROP_TYPE_MAX>{
+                            /* We're using numbers here so we don't mess up the order. This would be fatal */
+                            property_type_end(begin_index[0], (PropertyType) 0),
+                            property_type_end(begin_index[1], (PropertyType) 1),
+                            property_type_end(begin_index[2], (PropertyType) 2),
+                            property_type_end(begin_index[3], (PropertyType) 3),
+                            property_type_end(begin_index[4], (PropertyType) 4),
+                            property_type_end(begin_index[5], (PropertyType) 5),
+                            property_type_end(begin_index[6], (PropertyType) 6),
+                            property_type_end(begin_index[7], (PropertyType) 7)
+                        }
+                };
+            }
+        }
+#ifdef EXTERNALIZE_PROPERTY_DEFINITIONS
+        extern const PropertyListInfo property_list_info;
+#else
+        constexpr auto property_list_info = impl::list_info();
+#endif
+
+        template <typename PropertyEnumType, typename std::enable_if<std::is_enum<PropertyEnumType>::value, int>::type = 0>
+        const_modifier inline const auto& describe(PropertyEnumType type) {
+            static_assert(type_from_enum<PropertyEnumType>() < property_list_info.end_index.size());
+            const auto begin = property_list_info.begin_index[type_from_enum<PropertyEnumType>()];
+            const auto end = property_list_info.end_index[type_from_enum<PropertyEnumType>()];
+            const auto idx = begin + (size_t) type;
+            if(idx >= end) return undefined_property_description;
+            return property_list[idx];
+        }
+
+        inline const auto& describe(PropertyType type, size_t index) {
+            if(type >= property_list_info.end_index.size()) return undefined_property_description;
+            const auto begin = property_list_info.begin_index[type];
+            const auto end = property_list_info.end_index[type];
+            const auto idx = begin + index;
+            if(idx >= end) return undefined_property_description;
+            return property_list[idx];
+        }
+
+        inline const auto& find(PropertyType type, const std::string_view& name) {
+            if(type >= property_list_info.end_index.size()) return undefined_property_description;
+
+            constexpr static auto buffer_size{128}; /* no property is longer than 128 bytes */
+            if(name.size() >= buffer_size) return undefined_property_description;
+            char buffer[buffer_size];
+            for(size_t index{0}; index < name.size(); index++)
+                buffer[index] = (char) tolower(name[index]);
+
+            const std::string_view lower_name{buffer, name.size()};
+            const auto begin = property_list_info.begin_index[type];
+            const auto end = property_list_info.end_index[type];
+            for(size_t index{begin}; index < end; index++)
+                if(property_list[index].name == lower_name)
+                    return property_list[index];
+            return property_list[begin]; /* begin index MUST be the undefined */
+        }
+
+        template <typename PropertyEnumType, typename std::enable_if<std::is_enum<PropertyEnumType>::value, int>::type = 0>
+        inline const auto& find(const std::string_view& name) {
+            return find(type_from_enum<PropertyEnumType>(), name);
+        }
+
+        template <typename PropertyEnumType, typename std::enable_if<std::is_enum<PropertyEnumType>::value, int>::type = 0>
+        const_modifier inline const std::string_view& name(PropertyEnumType type) { /* defining the return type here to help out my IDE a bit ;) */
+            return describe<PropertyEnumType>(type).name;
+        }
+
+        template <typename PropertyEnumType, typename std::enable_if<std::is_enum<PropertyEnumType>::value, int>::type = 0>
+        const_modifier inline size_t property_count() {
+            const auto begin = property_list_info.begin_index[type_from_enum<PropertyEnumType>()];
+            const auto end = property_list_info.end_index[type_from_enum<PropertyEnumType>()];
+            return end - begin;
+        }
+
+#undef const_modifier
     }
     class Properties;
 
@@ -609,7 +677,7 @@ namespace ts {
         spin_lock value_lock;
         std::any casted_value;
         std::string value;
-        std::shared_ptr<property::PropertyDescription> description;
+        const property::PropertyDescription* description;
 
         bool flag_db_reference;
         bool flag_modified;
@@ -672,14 +740,14 @@ namespace ts {
             PropertyWrapper&operator+=(int64_t val){ return operator=(as<int64_t>() + val); }
             PropertyWrapper&operator+=(uint64_t val){ return operator=(as<uint64_t>() + val); }
 
-            bool hasDbReference() const { return this->data_ptr->flag_db_reference; }
+            [[nodiscard]] bool hasDbReference() const { return this->data_ptr->flag_db_reference; }
             void setDbReference(bool flag){ this->data_ptr->flag_db_reference = flag; }
 
-            bool isModified() const { return this->data_ptr->flag_modified; }
+            [[nodiscard]] bool isModified() const { return this->data_ptr->flag_modified; }
             void setModified(bool flag){ this->data_ptr->flag_modified = flag; }
 
             template <typename T>
-            T as() const {
+            [[nodiscard]] T as() const {
                 static_assert(ts::converter<T>::supported, "as<T> isn't supported for type");
 
                 return PropertyAccess<T>::get(this->data_ptr);
@@ -687,10 +755,10 @@ namespace ts {
 
 
             template <typename T>
-            operator T(){ return this->as<T>(); }
+            [[nodiscard]] operator T(){ return this->as<T>(); }
 
             template <typename T>
-            T as_save() const {
+            [[nodiscard]] T as_save() const {
                 try {
                     std::lock_guard lock(this->data_ptr->value_lock);
                     if(this->data_ptr->casted_value.type() == typeid(T))
@@ -703,8 +771,8 @@ namespace ts {
                 }
             }
 
-            const property::PropertyDescription& type() const { return *this->data_ptr->description; }
-            std::string value() const {
+            [[nodiscard]] const property::PropertyDescription& type() const { return *this->data_ptr->description; }
+            [[nodiscard]] std::string value() const {
                 std::lock_guard lock(this->data_ptr->value_lock);
                 return this->data_ptr->value;
             }
@@ -721,7 +789,7 @@ namespace ts {
                     this->trigger_update();
             }
 
-            std::string default_value() const {
+            [[nodiscard]] const std::string_view& default_value() const {
                 return this->type().default_value;
             }
 
@@ -762,9 +830,9 @@ namespace ts {
 
             void trigger_update();
 
-            PropertyWrapper(Properties* /* handle */, PropertyData* /* ptr */, const std::shared_ptr<PropertyBundle>& /* bundle */);
+            PropertyWrapper(Properties* /* handle */, PropertyData* /* ptr */, std::shared_ptr<PropertyBundle>  /* bundle */);
 
-            inline Properties* get_handle() { return this->handle; }
+            [[nodiscard]] inline Properties* get_handle() { return this->handle; }
         private:
             Properties* handle = nullptr;
             PropertyData* data_ptr = nullptr;
@@ -786,23 +854,23 @@ namespace ts {
 
             template <typename Type>
             bool register_property_type() {
-                constexpr auto type = property::impl::type<Type>();
-                return this->register_property_type(type, property::impl::length(type), property::impl::offset(type));
+                constexpr auto type = property::type_from_enum<Type>();
+                return this->register_property_type(type, property::property_count<Type>());
             }
 
             template <typename T>
-            bool hasProperty(T type) { return this->has(property::impl::type<T>(), type); }
+            bool hasProperty(T type) { return this->has(property::type_from_enum<T>(), type); }
 
             template <typename T, typename std::enable_if<std::is_enum<T>::value, int>::type = 0>
             PropertyWrapper operator[](T type) {
-                return this->find(property::impl::type<T>(), type);
+                return this->find(property::type_from_enum<T>(), type);
             }
 
             PropertyWrapper operator[](const property::PropertyDescription& type) {
                 return this->find(type.type_property, type.property_index);
             }
 
-            PropertyWrapper operator[](const std::shared_ptr<property::PropertyDescription>& type) {
+            PropertyWrapper operator[](const property::PropertyDescription* type) {
                 return this->find(type->type_property, type->property_index);
             }
 
@@ -825,14 +893,14 @@ namespace ts {
             bool has(property::PropertyType type, int index);
 
             template <typename T, typename std::enable_if<std::is_enum<T>::value, int>::type = 0>
-            bool has(T type) { return this->has(property::impl::type<T>(), type); }
+            bool has(T type) { return this->has(property::type_from_enum<T>(), (int) type); }
         private:
-            bool register_property_type(property::PropertyType /* type */, size_t /* length */, size_t /* offset */);
+            bool register_property_type(property::PropertyType /* type */, size_t /* length */);
 
-            bool save = true;
+            bool save{true};
             std::vector<std::function<void(PropertyWrapper&)>> notifyFunctions{};
 
-            size_t properties_count = 0;
+            size_t properties_count{0};
             std::vector<std::shared_ptr<PropertyBundle>> properties;
     };
 };
diff --git a/src/PropertyDefinition.h b/src/PropertyDefinition.h
new file mode 100644
index 0000000..dad31c6
--- /dev/null
+++ b/src/PropertyDefinition.h
@@ -0,0 +1,360 @@
+
+#define FLAG_SS (FLAG_SNAPSHOT | FLAG_SAVE)
+#define FLAG_SERVER_VV (FLAG_SERVER_VARIABLE | FLAG_SERVER_VIEW)
+#define FLAG_SERVER_VVSS  (FLAG_SERVER_VV | FLAG_SS)
+
+#define FLAG_CLIENT_VV (FLAG_CLIENT_VARIABLE | FLAG_CLIENT_VIEW)
+#define FLAG_CLIENT_VVSS  (FLAG_CLIENT_VV | FLAG_SS)
+
+#define V(key, lkey, flags) key, lkey, "0", TYPE_UNSIGNED_NUMBER, flags
+#define F(key, lkey, flags) key, lkey, "0", TYPE_FLOAT, flags
+
+#ifdef EXTERNALIZE_PROPERTY_DEFINITIONS
+decltype(property::property_list) property::
+#else
+constexpr auto
+#endif
+property_list = property::impl::make_property_array(
+    PropertyDescription{UNKNOWN_UNDEFINED, "undefined", "", TYPE_UNKNOWN, 0},
+
+    /* virtual server properties */
+    PropertyDescription{VIRTUALSERVER_UNDEFINED, "undefined", "", TYPE_UNKNOWN, 0}, //Must be at index 0!
+    PropertyDescription{VIRTUALSERVER_UNIQUE_IDENTIFIER, "virtualserver_unique_identifier", "", TYPE_STRING, FLAG_SERVER_VV | FLAG_SNAPSHOT},
+    PropertyDescription{VIRTUALSERVER_NAME, "virtualserver_name", "Another TeaSpeak server software user", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE},
+    PropertyDescription{VIRTUALSERVER_WELCOMEMESSAGE, "virtualserver_welcomemessage", "Welcome on another TeaSpeak server. (Download now and a license fee is not your cup of tea! [URL]www.teaspeak.de[/URL])", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE},
+    PropertyDescription{VIRTUALSERVER_PLATFORM, "virtualserver_platform", "undefined", TYPE_STRING, FLAG_SERVER_VIEW},
+    PropertyDescription{VIRTUALSERVER_VERSION, "virtualserver_version", "undefined", TYPE_STRING, FLAG_SERVER_VIEW},
+    PropertyDescription{VIRTUALSERVER_MAXCLIENTS, "virtualserver_maxclients", "120", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE},
+    PropertyDescription{VIRTUALSERVER_PASSWORD, "virtualserver_password", "", TYPE_STRING, FLAG_SS | FLAG_USER_EDITABLE},
+    PropertyDescription{VIRTUALSERVER_CLIENTS_ONLINE, "virtualserver_clientsonline", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE},
+    PropertyDescription{VIRTUALSERVER_QUERYCLIENTS_ONLINE, "virtualserver_queryclientsonline", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE},                         //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_CHANNELS_ONLINE, "virtualserver_channelsonline", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE},                   //only available on request (=> requestServerVariables),
+    PropertyDescription{VIRTUALSERVER_CREATED, "virtualserver_created", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VIEW | FLAG_SS},                           //available when connected, stores the time when the server was created
+    PropertyDescription{VIRTUALSERVER_UPTIME, "virtualserver_uptime", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE},                            //only available on request (=> requestServerVariables), the time since the server was started
+
+    PropertyDescription{VIRTUALSERVER_CODEC_ENCRYPTION_MODE, "virtualserver_codec_encryption_mode", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE},             //available and always up-to-date when connected
+    PropertyDescription{VIRTUALSERVER_KEYPAIR, "virtualserver_keypair", "", TYPE_STRING, FLAG_SS},                                     //internal use
+    PropertyDescription{VIRTUALSERVER_HOSTMESSAGE, "virtualserver_hostmessage", "Welcome", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE},                                 //available when connected, not updated while connected
+    PropertyDescription{VIRTUALSERVER_HOSTMESSAGE_MODE, "virtualserver_hostmessage_mode", "1", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE},                            //available when connected, not updated while connected
+    PropertyDescription{VIRTUALSERVER_FILEBASE, "virtualserver_filebase", "", TYPE_STRING, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE},                                    //not available to clients, stores the folder used for file transfers
+    PropertyDescription{VIRTUALSERVER_DEFAULT_SERVER_GROUP, "virtualserver_default_server_group", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE},                        //the manager permissions server group that a new manager gets assigned
+    PropertyDescription{VIRTUALSERVER_DEFAULT_MUSIC_GROUP, "virtualserver_default_music_group", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE},                        //the manager permissions server group that a new manager gets assigned
+    PropertyDescription{VIRTUALSERVER_DEFAULT_CHANNEL_GROUP, "virtualserver_default_channel_group", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE},                       //the channel permissions group that a new manager gets assigned when joining a channel
+    PropertyDescription{VIRTUALSERVER_FLAG_PASSWORD, "virtualserver_flag_password", "0", TYPE_BOOL, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE},                               //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_DEFAULT_CHANNEL_ADMIN_GROUP, "virtualserver_default_channel_admin_group", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SERVER_VIEW | FLAG_SS | FLAG_USER_EDITABLE},                 //the channel permissions group that a manager gets assigned when creating a channel
+    PropertyDescription{VIRTUALSERVER_MAX_DOWNLOAD_TOTAL_BANDWIDTH, "virtualserver_max_download_total_bandwidth", "-1", TYPE_SIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE},                //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_MAX_UPLOAD_TOTAL_BANDWIDTH, "virtualserver_max_upload_total_bandwidth", "-1", TYPE_SIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE},                  //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_HOSTBANNER_URL, "virtualserver_hostbanner_url", "", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE},                              //available when connected, always up-to-date
+    PropertyDescription{VIRTUALSERVER_HOSTBANNER_GFX_URL, "virtualserver_hostbanner_gfx_url", "", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE},                          //available when connected, always up-to-date
+    PropertyDescription{VIRTUALSERVER_HOSTBANNER_GFX_INTERVAL, "virtualserver_hostbanner_gfx_interval", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE},                     //available when connected, always up-to-date
+    PropertyDescription{VIRTUALSERVER_HOSTBANNER_MODE, "virtualserver_hostbanner_mode", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE},                             //available when connected, always up-to-date
+    PropertyDescription{VIRTUALSERVER_COMPLAIN_AUTOBAN_COUNT, "virtualserver_complain_autoban_count", "5", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE},                      //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_COMPLAIN_AUTOBAN_TIME, "virtualserver_complain_autoban_time", "5", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE},                       //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_COMPLAIN_REMOVE_TIME, "virtualserver_complain_remove_time", "5", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE},                        //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_MIN_CLIENTS_IN_CHANNEL_BEFORE_FORCED_SILENCE, "virtualserver_min_clients_in_channel_before_forced_silence", "20", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE},//only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_PRIORITY_SPEAKER_DIMM_MODIFICATOR, "virtualserver_priority_speaker_dimm_modificator", "-18", TYPE_FLOAT, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE},           //available when connected, always up-to-date
+    PropertyDescription{VIRTUALSERVER_ID, "virtualserver_id", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VIEW},                                          //available when connected
+    PropertyDescription{VIRTUALSERVER_ANTIFLOOD_POINTS_TICK_REDUCE, "virtualserver_antiflood_points_tick_reduce", "25", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE},                //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_ANTIFLOOD_POINTS_NEEDED_COMMAND_BLOCK, "virtualserver_antiflood_points_needed_command_block", "150", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE},       //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_ANTIFLOOD_POINTS_NEEDED_IP_BLOCK, "virtualserver_antiflood_points_needed_ip_block", "300", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE},            //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_CLIENT_CONNECTIONS, "virtualserver_client_connections", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS},                          //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_QUERY_CLIENT_CONNECTIONS, "virtualserver_query_client_connections", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS},                    //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_HOSTBUTTON_TOOLTIP, "virtualserver_hostbutton_tooltip", "", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE},                          //available when connected, always up-to-date
+    PropertyDescription{VIRTUALSERVER_HOSTBUTTON_URL, "virtualserver_hostbutton_url", "", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE},                              //available when connected, always up-to-date
+    PropertyDescription{VIRTUALSERVER_HOSTBUTTON_GFX_URL, "virtualserver_hostbutton_gfx_url", "", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE},                          //available when connected, always up-to-date
+    PropertyDescription{VIRTUALSERVER_DOWNLOAD_QUOTA, "virtualserver_download_quota", "-1", TYPE_SIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SAVE | FLAG_USER_EDITABLE},                              //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_UPLOAD_QUOTA, "virtualserver_upload_quota", "-1", TYPE_SIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SAVE | FLAG_USER_EDITABLE},                                //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_MONTH_BYTES_DOWNLOADED, "virtualserver_month_bytes_downloaded", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SAVE},                      //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_MONTH_BYTES_UPLOADED, "virtualserver_month_bytes_uploaded", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SAVE},                        //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_TOTAL_BYTES_DOWNLOADED, "virtualserver_total_bytes_downloaded", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SAVE},                      //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_TOTAL_BYTES_UPLOADED, "virtualserver_total_bytes_uploaded", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SAVE},                        //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_PORT, "virtualserver_port", "9987", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE},                                        //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_HOST, "virtualserver_host", "0.0.0.0,::", TYPE_STRING, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE},                                          //internal use | contains comma separated ip list
+    PropertyDescription{VIRTUALSERVER_AUTOSTART, "virtualserver_autostart", "1", TYPE_BOOL, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE},                                   //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_MACHINE_ID, "virtualserver_machine_id", "", TYPE_STRING, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE},                                  //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_NEEDED_IDENTITY_SECURITY_LEVEL, "virtualserver_needed_identity_security_level", "8", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE},              //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_LOG_CLIENT, "virtualserver_log_client", "1", TYPE_BOOL, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE},                                  //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_LOG_QUERY, "virtualserver_log_query", "1", TYPE_BOOL, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE},                                   //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_LOG_CHANNEL, "virtualserver_log_channel", "1", TYPE_BOOL, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE},                                 //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_LOG_PERMISSIONS, "virtualserver_log_permissions", "1", TYPE_BOOL, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE},                             //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_LOG_SERVER, "virtualserver_log_server", "1", TYPE_BOOL, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE},                                  //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_LOG_FILETRANSFER, "virtualserver_log_filetransfer", "1", TYPE_BOOL, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE},                            //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_NAME_PHONETIC, "virtualserver_name_phonetic", "", TYPE_STRING, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE},                               //available when connected, always up-to-date
+    PropertyDescription{VIRTUALSERVER_ICON_ID, "virtualserver_icon_id", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE},                                     //available when connected, always up-to-date
+    PropertyDescription{VIRTUALSERVER_RESERVED_SLOTS, "virtualserver_reserved_slots", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE},                              //available when connected, always up-to-date
+    PropertyDescription{VIRTUALSERVER_TOTAL_PACKETLOSS_SPEECH, "virtualserver_total_packetloss_speech", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE},                     //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_TOTAL_PACKETLOSS_KEEPALIVE, "virtualserver_total_packetloss_keepalive", "0", TYPE_FLOAT, FLAG_SERVER_VARIABLE},                  //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_TOTAL_PACKETLOSS_CONTROL, "virtualserver_total_packetloss_control", "0", TYPE_FLOAT, FLAG_SERVER_VARIABLE},                    //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_TOTAL_PACKETLOSS_TOTAL, "virtualserver_total_packetloss_total", "0", TYPE_FLOAT, FLAG_SERVER_VARIABLE},                      //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_TOTAL_PING, "virtualserver_total_ping", "0", TYPE_FLOAT, FLAG_SERVER_VARIABLE},                                  //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_WEBLIST_ENABLED, "virtualserver_weblist_enabled", "1", TYPE_BOOL, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE},                             //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_AUTOGENERATED_PRIVILEGEKEY, "virtualserver_autogenerated_privilegekey", "", TYPE_STRING, FLAG_SAVE},                  //internal use
+    PropertyDescription{VIRTUALSERVER_ASK_FOR_PRIVILEGEKEY, "virtualserver_ask_for_privilegekey", "1",  TYPE_BOOL, FLAG_SERVER_VV | FLAG_SAVE | FLAG_USER_EDITABLE},                        //available when connected
+    PropertyDescription{VIRTUALSERVER_CHANNEL_TEMP_DELETE_DELAY_DEFAULT, "virtualserver_channel_temp_delete_delay_default", "60", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VVSS | FLAG_USER_EDITABLE},           //available when connected, always up-to-date
+    PropertyDescription{VIRTUALSERVER_MIN_CLIENT_VERSION, "virtualserver_min_client_version", "1445512488", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_USER_EDITABLE},                          //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_MIN_ANDROID_VERSION, "virtualserver_min_android_version", "1407159763", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_USER_EDITABLE},                         //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_MIN_IOS_VERSION, "virtualserver_min_ios_version", "1407159763", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_USER_EDITABLE},                             //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_MIN_WINPHONE_VERSION, "virtualserver_min_winphone_version", "1407159763", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_USER_EDITABLE},                           //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_MAX_CHANNELS, "virtualserver_max_channels", "1000", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_USER_EDITABLE},                           //only available on request (=> requestServerVariables)
+
+    PropertyDescription{VIRTUALSERVER_LAST_CLIENT_CONNECT, "virtualserver_last_client_connect", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_NEW | FLAG_SS},                           //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_LAST_QUERY_CONNECT, "virtualserver_last_query_connect", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_NEW | FLAG_SS},                           //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_LAST_CLIENT_DISCONNECT, "virtualserver_last_client_disconnect", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_NEW | FLAG_SS},                           //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_LAST_QUERY_DISCONNECT, "virtualserver_last_query_disconnect", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_NEW | FLAG_SS},                           //only available on request (=> requestServerVariables)
+
+    PropertyDescription{VIRTUALSERVER_WEB_HOST, "virtualserver_web_host", "0.0.0.0", TYPE_STRING, FLAG_SERVER_VARIABLE | FLAG_NEW | FLAG_SS | FLAG_USER_EDITABLE},                           //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_WEB_PORT, "virtualserver_web_port", "0", TYPE_UNSIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_NEW | FLAG_SS | FLAG_USER_EDITABLE},                           //only available on request (=> requestServerVariables)
+
+    PropertyDescription{VIRTUALSERVER_DEFAULT_CLIENT_DESCRIPTION, "virtualserver_default_client_description", "", TYPE_STRING, FLAG_SERVER_VARIABLE | FLAG_NEW | FLAG_SS | FLAG_USER_EDITABLE},                           //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_DEFAULT_CHANNEL_DESCRIPTION, "virtualserver_default_channel_description", "", TYPE_STRING, FLAG_SERVER_VARIABLE | FLAG_NEW | FLAG_SS | FLAG_USER_EDITABLE},                           //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_DEFAULT_CHANNEL_TOPIC, "virtualserver_default_channel_topic", "", TYPE_STRING, FLAG_SERVER_VARIABLE | FLAG_NEW | FLAG_SS | FLAG_USER_EDITABLE},                           //only available on request (=> requestServerVariables)
+
+    PropertyDescription{VIRTUALSERVER_MUSIC_BOT_LIMIT, "virtualserver_music_bot_limit", "-1", TYPE_SIGNED_NUMBER, FLAG_SERVER_VARIABLE | FLAG_NEW | FLAG_SS | FLAG_USER_EDITABLE},                           //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_SPOKEN_TIME, "virtualserver_spoken_time", "0", TYPE_UNSIGNED_NUMBER, FLAG_INTERNAL | FLAG_NEW | FLAG_SAVE},                           //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_DISABLE_IP_SAVING, "virtualserver_disable_ip_saving", "0", TYPE_BOOL, FLAG_INTERNAL | FLAG_NEW | FLAG_SAVE | FLAG_USER_EDITABLE},                           //only available on request (=> requestServerVariables)
+    PropertyDescription{VIRTUALSERVER_COUNTRY_CODE, "virtualserver_country_code", "XX", TYPE_STRING, FLAG_SERVER_VV | FLAG_SAVE | FLAG_USER_EDITABLE},                           //available when connected
+
+    /* channel properties */
+    PropertyDescription{CHANNEL_UNDEFINED, "undefined", "", TYPE_UNKNOWN, 0}, //Must be at index 0!
+    PropertyDescription{CHANNEL_ID, "cid", "0", TYPE_UNSIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS},
+    PropertyDescription{CHANNEL_PID, "cpid", "0", TYPE_UNSIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS},
+    PropertyDescription{CHANNEL_NAME, "channel_name", "undefined", TYPE_STRING, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE},                       //Available for all channels that are "in view", always up-to-date
+    PropertyDescription{CHANNEL_TOPIC, "channel_topic", "", TYPE_STRING, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE},                          //Available for all channels that are "in view", always up-to-date
+    PropertyDescription{CHANNEL_DESCRIPTION, "channel_description", "", TYPE_STRING, FLAG_CHANNEL_VARIABLE | FLAG_SS | FLAG_USER_EDITABLE},                    //Must be requested (=> requestChannelDescription)
+    PropertyDescription{CHANNEL_PASSWORD, "channel_password", "0", TYPE_STRING, FLAG_SS | FLAG_USER_EDITABLE},                       //not available manager side
+    PropertyDescription{CHANNEL_CODEC, "channel_codec", "4", TYPE_UNSIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE},                          //Available for all channels that are "in view", always up-to-date
+    PropertyDescription{CHANNEL_CODEC_QUALITY, "channel_codec_quality", "7", TYPE_UNSIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE},                  //Available for all channels that are "in view", always up-to-date
+    PropertyDescription{CHANNEL_MAXCLIENTS, "channel_maxclients", "-1", TYPE_SIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE},                     //Available for all channels that are "in view", always up-to-date
+    PropertyDescription{CHANNEL_MAXFAMILYCLIENTS, "channel_maxfamilyclients", "-1", TYPE_SIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE},               //Available for all channels that are "in view", always up-to-date
+    PropertyDescription{CHANNEL_ORDER, "channel_order", "0", TYPE_UNSIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE},                          //Available for all channels that are "in view", always up-to-date
+    PropertyDescription{CHANNEL_FLAG_PERMANENT, "channel_flag_permanent", "1", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE},                 //Available for all channels that are "in view", always up-to-date
+    PropertyDescription{CHANNEL_FLAG_SEMI_PERMANENT, "channel_flag_semi_permanent", "0", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE},            //Available for all channels that are "in view", always up-to-date
+    PropertyDescription{CHANNEL_FLAG_DEFAULT, "channel_flag_default", "0", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE},                   //Available for all channels that are "in view", always up-to-date
+    PropertyDescription{CHANNEL_FLAG_PASSWORD, "channel_flag_password", "0", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE},                  //Available for all channels that are "in view", always up-to-date
+    PropertyDescription{CHANNEL_CODEC_LATENCY_FACTOR, "channel_codec_latency_factor", "1", TYPE_UNSIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE},           //Available for all channels that are "in view", always up-to-date
+    PropertyDescription{CHANNEL_CODEC_IS_UNENCRYPTED, "channel_codec_is_unencrypted", "1", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE},           //Available for all channels that are "in view", always up-to-date
+    PropertyDescription{CHANNEL_SECURITY_SALT, "channel_security_salt", "", TYPE_STRING, FLAG_SS},                  //Not available manager side, not used in teamspeak, only SDK. Sets the options+salt for security hash.
+    PropertyDescription{CHANNEL_DELETE_DELAY, "channel_delete_delay", "0", TYPE_UNSIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE},                   //How many seconds to wait before deleting this channel
+    PropertyDescription{CHANNEL_FLAG_MAXCLIENTS_UNLIMITED, "channel_flag_maxclients_unlimited", "1", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE},      //Available for all channels that are "in view", always up-to-date
+    PropertyDescription{CHANNEL_FLAG_MAXFAMILYCLIENTS_UNLIMITED, "channel_flag_maxfamilyclients_unlimited", "1", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE},//Available for all channels that are "in view", always up-to-date
+    PropertyDescription{CHANNEL_FLAG_MAXFAMILYCLIENTS_INHERITED, "channel_flag_maxfamilyclients_inherited", "0", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE},//Available for all channels that are "in view", always up-to-date
+    PropertyDescription{CHANNEL_FLAG_ARE_SUBSCRIBED, "channel_flag_are_subscribed", "1", TYPE_BOOL, FLAG_INTERNAL},            //Only available manager side, stores whether we are subscribed to this channel
+    PropertyDescription{CHANNEL_FILEPATH, "channel_filepath", "", TYPE_STRING, FLAG_SS},                       //not available manager side, the folder used for file-transfers for this channel
+    PropertyDescription{CHANNEL_NEEDED_TALK_POWER, "channel_needed_talk_power", "0", TYPE_UNSIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE},              //Available for all channels that are "in view", always up-to-date
+    PropertyDescription{CHANNEL_FORCED_SILENCE, "channel_forced_silence", "0", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE},                 //Available for all channels that are "in view", always up-to-date
+    PropertyDescription{CHANNEL_NAME_PHONETIC, "channel_name_phonetic", "", TYPE_STRING, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE},                  //Available for all channels that are "in view", always up-to-date
+    PropertyDescription{CHANNEL_ICON_ID, "channel_icon_id", "0", TYPE_UNSIGNED_NUMBER, FLAG_CHANNEL_VIEW | FLAG_SS | FLAG_USER_EDITABLE},                        //Available for all channels that are "in view", always up-to-date
+    PropertyDescription{CHANNEL_FLAG_PRIVATE, "channel_flag_private", "0", TYPE_BOOL, FLAG_CHANNEL_VIEW | FLAG_SS},                   //Available for all channels that are "in view", always up-to-date
+    PropertyDescription{CHANNEL_LAST_LEFT, "channel_last_left", "0", TYPE_UNSIGNED_NUMBER, FLAG_SAVE | FLAG_CHANNEL_VIEW | FLAG_CHANNEL_VARIABLE | FLAG_NEW},                   //Available for all channels that are "in view", always up-to-date
+    PropertyDescription{CHANNEL_CREATED_AT, "channel_created_at", "0", TYPE_UNSIGNED_NUMBER, FLAG_SS | FLAG_CHANNEL_VIEW | FLAG_CHANNEL_VARIABLE | FLAG_NEW},                   //Available for all channels that are "in view", always up-to-date
+    PropertyDescription{CHANNEL_CREATED_BY, "channel_created_by", "0", TYPE_UNSIGNED_NUMBER, FLAG_SS | FLAG_CHANNEL_VIEW | FLAG_CHANNEL_VARIABLE | FLAG_NEW},                   //Available for all channels that are "in view", always up-to-date
+    PropertyDescription{CHANNEL_CONVERSATION_HISTORY_LENGTH, "channel_conversation_history_length", "1500", TYPE_SIGNED_NUMBER, FLAG_SS | FLAG_CHANNEL_VIEW | FLAG_CHANNEL_VARIABLE | FLAG_NEW | FLAG_USER_EDITABLE},
+    PropertyDescription{CHANNEL_FLAG_CONVERSATION_PRIVATE, "channel_flag_conversation_private", "0", TYPE_BOOL, FLAG_SS | FLAG_CHANNEL_VIEW | FLAG_CHANNEL_VARIABLE | FLAG_NEW | FLAG_USER_EDITABLE},
+
+    /* group properties, this may gets removed */
+    PropertyDescription{GROUP_UNDEFINED, "undefined", "", TYPE_UNKNOWN, 0},
+    PropertyDescription{GROUP_ID, "gid", "0", TYPE_UNSIGNED_NUMBER, FLAG_INTERNAL},
+    PropertyDescription{GROUP_TYPE, "type", "0", TYPE_UNSIGNED_NUMBER, FLAG_GROUP_VIEW},
+    PropertyDescription{GROUP_NAME, "name", "Undefined group", TYPE_STRING, FLAG_GROUP_VIEW},
+    PropertyDescription{GROUP_SORTID, "sortid", "0", TYPE_UNSIGNED_NUMBER, FLAG_GROUP_VIEW},
+    PropertyDescription{GROUP_SAVEDB, "savedb", "0", TYPE_BOOL, FLAG_GROUP_VIEW},
+    PropertyDescription{GROUP_NAMEMODE, "namemode", "0", TYPE_UNSIGNED_NUMBER, FLAG_GROUP_VIEW},
+    PropertyDescription{GROUP_ICONID, "iconid", "0", TYPE_UNSIGNED_NUMBER, FLAG_GROUP_VIEW},
+
+    /* client properties */
+    PropertyDescription{CLIENT_UNDEFINED, "undefined", "undefined", TYPE_UNKNOWN, 0},
+    PropertyDescription{CLIENT_UNIQUE_IDENTIFIER, "client_unique_identifier", "", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_SNAPSHOT | FLAG_GLOBAL},           //automatically up-to-date for any manager "in view", can be used to identify this particular manager installation
+    PropertyDescription{CLIENT_NICKNAME, "client_nickname", "undefined", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_SAVE_MUSIC | FLAG_SNAPSHOT | FLAG_GLOBAL | FLAG_USER_EDITABLE},                        //automatically up-to-date for any manager "in view"
+    PropertyDescription{CLIENT_VERSION, "client_version", "unknown", TYPE_STRING, FLAG_CLIENT_VVSS | FLAG_USER_EDITABLE | FLAG_GLOBAL | FLAG_SAVE_MUSIC},                         //for other clients than ourself, this needs to be requested (=> requestClientVariables)
+    PropertyDescription{CLIENT_PLATFORM, "client_platform", "unknown", TYPE_STRING, FLAG_CLIENT_VVSS | FLAG_USER_EDITABLE | FLAG_GLOBAL | FLAG_SAVE_MUSIC},                        //for other clients than ourself, this needs to be requested (=> requestClientVariables)
+    PropertyDescription{CLIENT_FLAG_TALKING, "client_flag_talking", "0", TYPE_BOOL, FLAG_INTERNAL},                    //automatically up-to-date for any manager that can be heard (in room / whisper)
+    PropertyDescription{CLIENT_INPUT_MUTED, "client_input_muted", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE},                     //automatically up-to-date for any manager "in view", this clients microphone mute status
+    PropertyDescription{CLIENT_OUTPUT_MUTED, "client_output_muted", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE},                    //automatically up-to-date for any manager "in view", this clients headphones/speakers/mic combined mute status
+    PropertyDescription{CLIENT_OUTPUTONLY_MUTED, "client_outputonly_muted", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE},                //automatically up-to-date for any manager "in view", this clients headphones/speakers only mute status
+    PropertyDescription{CLIENT_INPUT_HARDWARE, "client_input_hardware", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE},                  //automatically up-to-date for any manager "in view", this clients microphone hardware status (is the capture device opened?)
+    PropertyDescription{CLIENT_OUTPUT_HARDWARE, "client_output_hardware", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE},                 //automatically up-to-date for any manager "in view", this clients headphone/speakers hardware status (is the playback device opened?)
+    PropertyDescription{CLIENT_DEFAULT_CHANNEL, "client_default_channel", "", TYPE_STRING, FLAG_INTERNAL},                 //only usable for ourself, the default channel we used to connect on our last connection attempt
+    PropertyDescription{CLIENT_DEFAULT_CHANNEL_PASSWORD, "client_default_channel_password", "", TYPE_STRING, FLAG_INTERNAL},        //internal use
+    PropertyDescription{CLIENT_SERVER_PASSWORD, "client_server_password", "", TYPE_STRING, FLAG_INTERNAL},                 //internal use
+    PropertyDescription{CLIENT_META_DATA, "client_meta_data", "", TYPE_STRING, FLAG_CLIENT_VIEW| FLAG_GLOBAL|FLAG_USER_EDITABLE},                       //automatically up-to-date for any manager "in view", not used by TeamSpeak, free storage for sdk users
+    PropertyDescription{CLIENT_IS_RECORDING, "client_is_recording", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE},                    //automatically up-to-date for any manager "in view"
+    PropertyDescription{CLIENT_VERSION_SIGN, "client_version_sign", "", TYPE_STRING, FLAG_INTERNAL},                    //sign
+    PropertyDescription{CLIENT_SECURITY_HASH, "client_security_hash", "", TYPE_STRING, FLAG_INTERNAL},                   //SDK use, not used by teamspeak. Hash is provided by an outside source. A channel will use the security salt + other manager data to calculate a hash, which must be the same as the one provided here.
+
+    //Rare properties
+    PropertyDescription{CLIENT_KEY_OFFSET, "client_key_offset", "0", TYPE_UNSIGNED_NUMBER, FLAG_INTERNAL},                      //internal use
+    PropertyDescription{CLIENT_LOGIN_NAME, "client_login_name", "", TYPE_STRING, FLAG_CLIENT_VARIABLE| FLAG_GLOBAL},                      //used for serverquery clients, makes no sense on normal clients currently
+    PropertyDescription{CLIENT_LOGIN_PASSWORD, "client_login_password", "", TYPE_STRING, FLAG_INTERNAL| FLAG_GLOBAL},                  //used for serverquery clients, makes no sense on normal clients currently
+    PropertyDescription{CLIENT_DATABASE_ID, "client_database_id", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VIEW | FLAG_GLOBAL},                     //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, holds database manager id
+    PropertyDescription{CLIENT_ID, "clid", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VV},                     //clid!
+    PropertyDescription{CLIENT_HARDWARE_ID, "hwid", "", TYPE_STRING, FLAG_SAVE},                     //hwid!
+    PropertyDescription{CLIENT_CHANNEL_GROUP_ID, "client_channel_group_id", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VIEW},                //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, holds database manager id
+    PropertyDescription{CLIENT_SERVERGROUPS, "client_servergroups", "0", TYPE_STRING, FLAG_CLIENT_VIEW},                    //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, holds all servergroups manager belongs too
+    PropertyDescription{CLIENT_CREATED, "client_created", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VARIABLE | FLAG_SAVE_MUSIC | FLAG_SNAPSHOT | FLAG_GLOBAL},                         //this needs to be requested (=> requestClientVariables), first time this manager connected to this server
+    PropertyDescription{CLIENT_LASTCONNECTED, "client_lastconnected", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VARIABLE | FLAG_SNAPSHOT | FLAG_GLOBAL},                   //this needs to be requested (=> requestClientVariables), last time this manager connected to this server
+    PropertyDescription{CLIENT_TOTALCONNECTIONS, "client_totalconnections", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VARIABLE | FLAG_CLIENT_VIEW | FLAG_SNAPSHOT | FLAG_GLOBAL},                //this needs to be requested (=> requestClientVariables), how many times this manager connected to this server
+    PropertyDescription{CLIENT_AWAY, "client_away", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE},                            //automatically up-to-date for any manager "in view", this clients away status
+    PropertyDescription{CLIENT_AWAY_MESSAGE, "client_away_message", "", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE},                    //automatically up-to-date for any manager "in view", this clients away message
+    PropertyDescription{CLIENT_TYPE, "client_type", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VIEW | FLAG_GLOBAL},                            //automatically up-to-date for any manager "in view", determines if this is a real manager or a server-query connection
+    PropertyDescription{CLIENT_TYPE_EXACT, "client_type_exact", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VIEW | FLAG_NEW | FLAG_GLOBAL},                            //automatically up-to-date for any manager "in view", determines if this is a real manager or a server-query connection
+    PropertyDescription{CLIENT_FLAG_AVATAR, "client_flag_avatar", "", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_SAVE | FLAG_USER_EDITABLE},                     //automatically up-to-date for any manager "in view", this manager got an avatar
+    PropertyDescription{CLIENT_TALK_POWER, "client_talk_power", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VIEW},                      //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, holds database manager id
+    PropertyDescription{CLIENT_TALK_REQUEST, "client_talk_request", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE},                    //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, holds timestamp where manager requested to talk
+    PropertyDescription{CLIENT_TALK_REQUEST_MSG, "client_talk_request_msg", "", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE},                //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, holds matter for the request
+    PropertyDescription{CLIENT_DESCRIPTION, "client_description", "", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_SS | FLAG_USER_EDITABLE},                     //automatically up-to-date for any manager "in view"
+    PropertyDescription{CLIENT_IS_TALKER, "client_is_talker", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE},                       //automatically up-to-date for any manager "in view"
+    PropertyDescription{CLIENT_MONTH_BYTES_UPLOADED, "client_month_bytes_uploaded", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VARIABLE | FLAG_SAVE},            //this needs to be requested (=> requestClientVariables)
+    PropertyDescription{CLIENT_MONTH_BYTES_DOWNLOADED, "client_month_bytes_downloaded", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VARIABLE | FLAG_SAVE},          //this needs to be requested (=> requestClientVariables)
+    PropertyDescription{CLIENT_TOTAL_BYTES_UPLOADED, "client_total_bytes_uploaded", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VARIABLE | FLAG_SAVE},            //this needs to be requested (=> requestClientVariables)
+    PropertyDescription{CLIENT_TOTAL_BYTES_DOWNLOADED, "client_total_bytes_downloaded", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VARIABLE | FLAG_SAVE},          //this needs to be requested (=> requestClientVariables)
+    PropertyDescription{CLIENT_TOTAL_ONLINE_TIME, "client_total_online_time", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VARIABLE | FLAG_SAVE | FLAG_NEW},          //this needs to be requested (=> requestClientVariables)
+    PropertyDescription{CLIENT_MONTH_ONLINE_TIME, "client_month_online_time", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VARIABLE | FLAG_SAVE | FLAG_NEW},          //this needs to be requested (=> requestClientVariables)
+    PropertyDescription{CLIENT_IS_PRIORITY_SPEAKER, "client_is_priority_speaker", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE},             //automatically up-to-date for any manager "in view"
+    PropertyDescription{CLIENT_UNREAD_MESSAGES, "client_unread_messages", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VIEW},                 //automatically up-to-date for any manager "in view"
+    PropertyDescription{CLIENT_NICKNAME_PHONETIC, "client_nickname_phonetic", "", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE},               //automatically up-to-date for any manager "in view"
+    PropertyDescription{CLIENT_NEEDED_SERVERQUERY_VIEW_POWER, "client_needed_serverquery_view_power", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VIEW},   //automatically up-to-date for any manager "in view"
+    PropertyDescription{CLIENT_DEFAULT_TOKEN, "client_default_token", "", TYPE_STRING, FLAG_INTERNAL},                   //only usable for ourself, the default token we used to connect on our last connection attempt
+    PropertyDescription{CLIENT_ICON_ID, "client_icon_id", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VIEW | FLAG_CLIENT_VARIABLE},                         //automatically up-to-date for any manager "in view"
+    PropertyDescription{CLIENT_IS_CHANNEL_COMMANDER, "client_is_channel_commander", "0", TYPE_BOOL, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE | FLAG_SAVE_MUSIC},            //automatically up-to-date for any manager "in view"
+    PropertyDescription{CLIENT_COUNTRY, "client_country", "TS", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_CLIENT_VARIABLE | FLAG_GLOBAL | FLAG_SAVE_MUSIC | FLAG_USER_EDITABLE},                         //automatically up-to-date for any manager "in view"
+    PropertyDescription{CLIENT_CHANNEL_GROUP_INHERITED_CHANNEL_ID, "client_channel_group_inherited_channel_id", "0", TYPE_UNSIGNED_NUMBER, FLAG_CLIENT_VIEW}, //automatically up-to-date for any manager "in view", only valid with PERMISSION feature, contains channel_id where the channel_group_id is set from
+    PropertyDescription{CLIENT_BADGES, "client_badges", "", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE},                          //automatically up-to-date for any manager "in view", stores icons for partner badges
+    PropertyDescription{CLIENT_MYTEAMSPEAK_ID, "client_myteamspeak_id", "", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_SS | FLAG_USER_EDITABLE},                          //automatically up-to-date for any manager "in view", stores icons for partner badges
+    PropertyDescription{CLIENT_INTEGRATIONS, "client_integrations", "", TYPE_STRING, FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE},                          //automatically up-to-date for any manager "in view", stores icons for partner badges
+    PropertyDescription{CLIENT_ACTIVE_INTEGRATIONS_INFO, "client_active_integrations_info", "", TYPE_STRING, FLAG_INTERNAL | FLAG_USER_EDITABLE},
+
+    //Using FLAG_GLOBAL here,lse they will be overridden on clientinit
+    PropertyDescription{CLIENT_TEAFORO_ID, "client_teaforo_id", "0", TYPE_UNSIGNED_NUMBER, FLAG_NEW | FLAG_CLIENT_VIEW | FLAG_GLOBAL},
+    PropertyDescription{CLIENT_TEAFORO_NAME, "client_teaforo_name", "", TYPE_STRING, FLAG_NEW | FLAG_CLIENT_VIEW | FLAG_GLOBAL},
+    PropertyDescription{CLIENT_TEAFORO_FLAGS, "client_teaforo_flags", "0", TYPE_UNSIGNED_NUMBER, FLAG_NEW | FLAG_CLIENT_VIEW | FLAG_GLOBAL},
+
+    //Music bot stuff
+    PropertyDescription{CLIENT_OWNER, "client_owner", "0", TYPE_UNSIGNED_NUMBER, FLAG_NEW | FLAG_CLIENT_VIEW},
+    PropertyDescription{CLIENT_BOT_TYPE, "client_bot_type", "0", TYPE_UNSIGNED_NUMBER, FLAG_NEW | FLAG_SAVE_MUSIC | FLAG_USER_EDITABLE | FLAG_CLIENT_VIEW},
+    PropertyDescription{CLIENT_LAST_CHANNEL, "client_last_channel", "0", TYPE_UNSIGNED_NUMBER, FLAG_NEW | FLAG_INTERNAL | FLAG_SAVE_MUSIC},
+    PropertyDescription{CLIENT_PLAYER_STATE, "player_state", "0", TYPE_UNSIGNED_NUMBER, FLAG_NEW | FLAG_CLIENT_VIEW | FLAG_SAVE_MUSIC},
+    PropertyDescription{CLIENT_PLAYER_VOLUME, "player_volume", "1", TYPE_FLOAT, FLAG_NEW | FLAG_SAVE_MUSIC | FLAG_CLIENT_VIEW | FLAG_USER_EDITABLE},
+    PropertyDescription{CLIENT_PLAYLIST_ID, "client_playlist_id", "0", TYPE_UNSIGNED_NUMBER, FLAG_NEW | FLAG_CLIENT_VARIABLE | FLAG_SAVE_MUSIC},
+    PropertyDescription{CLIENT_DISABLED, "client_disabled", "0", TYPE_BOOL, FLAG_NEW | FLAG_CLIENT_VARIABLE},
+    PropertyDescription{CLIENT_UPTIME_MODE, "client_uptime_mode", "0", TYPE_UNSIGNED_NUMBER, FLAG_NEW | FLAG_CLIENT_VARIABLE | FLAG_USER_EDITABLE | FLAG_SAVE_MUSIC},
+    PropertyDescription{CLIENT_FLAG_NOTIFY_SONG_CHANGE, "client_flag_notify_song_change", "1", TYPE_BOOL, FLAG_NEW | FLAG_CLIENT_VARIABLE | FLAG_USER_EDITABLE | FLAG_SAVE_MUSIC},
+
+    /* connection list properties */
+    PropertyDescription{CONNECTION_UNDEFINED, "undefined", "", TYPE_UNKNOWN, 0},
+    PropertyDescription{CONNECTION_PING, "connection_ping", "0", TYPE_UNSIGNED_NUMBER, 0},                                        //average latency for a round trip through and back this connection
+    PropertyDescription{CONNECTION_PING_DEVIATION, "connection_ping_deviation", "0", TYPE_UNSIGNED_NUMBER, 0},                                  //standard deviation of the above average latency
+    PropertyDescription{CONNECTION_CONNECTED_TIME, "connection_connected_time", "0", TYPE_UNSIGNED_NUMBER, 0},                                  //how long the connection exists already
+    PropertyDescription{CONNECTION_IDLE_TIME, "connection_idle_time", "0", TYPE_UNSIGNED_NUMBER, 0},                                       //how long since the last action of this manager
+    PropertyDescription{CONNECTION_CLIENT_IP, "connection_client_ip", "", TYPE_STRING, FLAG_SAVE},                                      //NEED DB SAVE! //IP of this manager (as seen from the server side)
+    PropertyDescription{CONNECTION_CLIENT_PORT, "connection_client_port", "0", TYPE_UNSIGNED_NUMBER, 0},                                     //Port of this manager (as seen from the server side)
+    PropertyDescription{CONNECTION_SERVER_IP, "connection_server_ip", "", TYPE_STRING, 0},                                       //IP of the server (seen from the manager side) - only available on yourself, not for remote clients, not available server side
+    PropertyDescription{CONNECTION_SERVER_PORT, "connection_server_port", "0", TYPE_UNSIGNED_NUMBER, 0},                                     //Port of the server (seen from the manager side) - only available on yourself, not for remote clients, not available server side
+
+    PropertyDescription{V(CONNECTION_PACKETS_SENT_SPEECH, "connection_packets_sent_speech", 0)},                             //how many Speech packets were sent through this connection
+    PropertyDescription{V(CONNECTION_PACKETS_SENT_KEEPALIVE, "connection_packets_sent_keepalive", 0)},
+    PropertyDescription{V(CONNECTION_PACKETS_SENT_CONTROL, "connection_packets_sent_control", 0)},
+    PropertyDescription{V(CONNECTION_PACKETS_SENT_TOTAL, "connection_packets_sent_total", FLAG_CLIENT_INFO)},                              //how many packets were sent totally (this is PACKETS_SENT_SPEECH + PACKETS_SENT_KEEPALIVE + PACKETS_SENT_CONTROL)
+    PropertyDescription{V(CONNECTION_BYTES_SENT_SPEECH, "connection_bytes_sent_speech", 0)},
+    PropertyDescription{V(CONNECTION_BYTES_SENT_KEEPALIVE, "connection_bytes_sent_keepalive", 0)},
+    PropertyDescription{V(CONNECTION_BYTES_SENT_CONTROL, "connection_bytes_sent_control", 0)},
+    PropertyDescription{V(CONNECTION_BYTES_SENT_TOTAL, "connection_bytes_sent_total", FLAG_CLIENT_INFO)},
+    PropertyDescription{V(CONNECTION_PACKETS_RECEIVED_SPEECH, "connection_packets_received_speech", 0)},
+    PropertyDescription{V(CONNECTION_PACKETS_RECEIVED_KEEPALIVE, "connection_packets_received_keepalive", 0)},
+    PropertyDescription{V(CONNECTION_PACKETS_RECEIVED_CONTROL, "connection_packets_received_control", 0)},
+    PropertyDescription{V(CONNECTION_PACKETS_RECEIVED_TOTAL, "connection_packets_received_total", FLAG_CLIENT_INFO)},
+    PropertyDescription{V(CONNECTION_BYTES_RECEIVED_SPEECH, "connection_bytes_received_speech", 0)},
+    PropertyDescription{V(CONNECTION_BYTES_RECEIVED_KEEPALIVE, "connection_bytes_received_keepalive", 0)},
+    PropertyDescription{V(CONNECTION_BYTES_RECEIVED_CONTROL, "connection_bytes_received_control", 0)},
+    PropertyDescription{V(CONNECTION_BYTES_RECEIVED_TOTAL, "connection_bytes_received_total", FLAG_CLIENT_INFO)},
+    PropertyDescription{F(CONNECTION_PACKETLOSS_SPEECH, "connection_packetloss_speech", 0)},
+    PropertyDescription{F(CONNECTION_PACKETLOSS_KEEPALIVE, "connection_packetloss_keepalive", 0)},
+    PropertyDescription{F(CONNECTION_PACKETLOSS_CONTROL, "connection_packetloss_control", 0)},
+    PropertyDescription{F(CONNECTION_PACKETLOSS_TOTAL, "connection_packetloss_total", FLAG_CLIENT_INFO)},                                //the probability with which a packet round trip failed because a packet was lost
+    PropertyDescription{F(CONNECTION_SERVER2CLIENT_PACKETLOSS_SPEECH, "connection_server2client_packetloss_speech", 0)},                 //the probability with which a speech packet failed from the server to the manager
+    PropertyDescription{F(CONNECTION_SERVER2CLIENT_PACKETLOSS_KEEPALIVE, "connection_server2client_packetloss_keepalive", 0)},
+    PropertyDescription{F(CONNECTION_SERVER2CLIENT_PACKETLOSS_CONTROL, "connection_server2client_packetloss_control", 0)},
+    PropertyDescription{F(CONNECTION_SERVER2CLIENT_PACKETLOSS_TOTAL, "connection_server2client_packetloss_total", FLAG_CLIENT_INFO)},
+    PropertyDescription{F(CONNECTION_CLIENT2SERVER_PACKETLOSS_SPEECH, "connection_client2server_packetloss_speech", 0)},
+    PropertyDescription{F(CONNECTION_CLIENT2SERVER_PACKETLOSS_KEEPALIVE, "connection_client2server_packetloss_keepalive", 0)},
+    PropertyDescription{F(CONNECTION_CLIENT2SERVER_PACKETLOSS_CONTROL, "connection_client2server_packetloss_control", 0)},
+    PropertyDescription{F(CONNECTION_CLIENT2SERVER_PACKETLOSS_TOTAL, "connection_client2server_packetloss_total", FLAG_CLIENT_INFO)},
+    PropertyDescription{V(CONNECTION_BANDWIDTH_SENT_LAST_SECOND_SPEECH, "connection_bandwidth_sent_last_second_speech", 0)},               //howmany bytes of speech packets we sent during the last second
+    PropertyDescription{V(CONNECTION_BANDWIDTH_SENT_LAST_SECOND_KEEPALIVE, "connection_bandwidth_sent_last_second_keepalive", 0)},
+    PropertyDescription{V(CONNECTION_BANDWIDTH_SENT_LAST_SECOND_CONTROL, "connection_bandwidth_sent_last_second_control", 0)},
+    PropertyDescription{V(CONNECTION_BANDWIDTH_SENT_LAST_SECOND_TOTAL, "connection_bandwidth_sent_last_second_total", FLAG_CLIENT_INFO)},
+    PropertyDescription{V(CONNECTION_BANDWIDTH_SENT_LAST_MINUTE_SPEECH, "connection_bandwidth_sent_last_minute_speech", 0)},               //howmany bytes/s of speech packets we sent in average during the last minute
+    PropertyDescription{V(CONNECTION_BANDWIDTH_SENT_LAST_MINUTE_KEEPALIVE, "connection_bandwidth_sent_last_minute_keepalive", 0)},
+    PropertyDescription{V(CONNECTION_BANDWIDTH_SENT_LAST_MINUTE_CONTROL, "connection_bandwidth_sent_last_minute_control", 0)},
+    PropertyDescription{V(CONNECTION_BANDWIDTH_SENT_LAST_MINUTE_TOTAL, "connection_bandwidth_sent_last_minute_total", FLAG_CLIENT_INFO)},
+    PropertyDescription{V(CONNECTION_BANDWIDTH_RECEIVED_LAST_SECOND_SPEECH, "connection_bandwidth_received_last_second_speech", 0)},
+    PropertyDescription{V(CONNECTION_BANDWIDTH_RECEIVED_LAST_SECOND_KEEPALIVE, "connection_bandwidth_received_last_second_keepalive", 0)},
+    PropertyDescription{V(CONNECTION_BANDWIDTH_RECEIVED_LAST_SECOND_CONTROL, "connection_bandwidth_received_last_second_control", 0)},
+    PropertyDescription{V(CONNECTION_BANDWIDTH_RECEIVED_LAST_SECOND_TOTAL, "connection_bandwidth_received_last_second_total", FLAG_CLIENT_INFO)},
+    PropertyDescription{V(CONNECTION_BANDWIDTH_RECEIVED_LAST_MINUTE_SPEECH, "connection_bandwidth_received_last_minute_speech", 0)},
+    PropertyDescription{V(CONNECTION_BANDWIDTH_RECEIVED_LAST_MINUTE_KEEPALIVE, "connection_bandwidth_received_last_minute_keepalive", 0)},
+    PropertyDescription{V(CONNECTION_BANDWIDTH_RECEIVED_LAST_MINUTE_CONTROL, "connection_bandwidth_received_last_minute_control", 0)},
+    PropertyDescription{V(CONNECTION_BANDWIDTH_RECEIVED_LAST_MINUTE_TOTAL, "connection_bandwidth_received_last_minute_total", FLAG_CLIENT_INFO)},
+
+    //Rare properties
+    PropertyDescription{V(CONNECTION_FILETRANSFER_BANDWIDTH_SENT, "connection_filetransfer_bandwidth_sent", FLAG_CLIENT_INFO)},                     //how many bytes per second are currently being sent by file transfers
+    PropertyDescription{V(CONNECTION_FILETRANSFER_BANDWIDTH_RECEIVED, "connection_filetransfer_bandwidth_received", FLAG_CLIENT_INFO)},                 //how many bytes per second are currently being received by file transfers
+    PropertyDescription{V(CONNECTION_FILETRANSFER_BYTES_RECEIVED_TOTAL, "connection_filetransfer_bytes_received_total", FLAG_CLIENT_INFO)},               //how many bytes we received in total through file transfers
+    PropertyDescription{V(CONNECTION_FILETRANSFER_BYTES_SENT_TOTAL, "connection_filetransfer_bytes_sent_total", FLAG_CLIENT_INFO)},                   //how many bytes we sent in total through file transfers
+
+    /* server instance properties */
+    PropertyDescription{SERVERINSTANCE_UNDEFINED, "undefined", "", TYPE_UNKNOWN, 0},
+    PropertyDescription{SERVERINSTANCE_DATABASE_VERSION, "serverinstance_database_version", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE},
+    PropertyDescription{SERVERINSTANCE_PERMISSIONS_VERSION, "serverinstance_permissions_version", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE},
+    PropertyDescription{SERVERINSTANCE_FILETRANSFER_HOST, "serverinstance_filetransfer_host", "0.0.0.0,[::]", TYPE_STRING, FLAG_INSTANCE_VARIABLE | FLAG_SAVE},
+    PropertyDescription{SERVERINSTANCE_FILETRANSFER_PORT, "serverinstance_filetransfer_port", "30303", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE},
+    PropertyDescription{SERVERINSTANCE_FILETRANSFER_MAX_CONNECTIONS, "serverinstance_filetransfer_max_connections", "100", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE},
+    PropertyDescription{SERVERINSTANCE_FILETRANSFER_MAX_CONNECTIONS_PER_IP, "serverinstance_filetransfer_max_connections_per_ip", "20", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE},
+    PropertyDescription{SERVERINSTANCE_QUERY_HOST, "serverinstance_query_host", "0.0.0.0,[::]", TYPE_STRING, FLAG_INSTANCE_VARIABLE | FLAG_SAVE},
+    PropertyDescription{SERVERINSTANCE_QUERY_PORT, "serverinstance_query_port", "10101", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE},
+    PropertyDescription{SERVERINSTANCE_QUERY_MAX_CONNECTIONS, "serverinstance_query_max_connections", "100", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE},
+    PropertyDescription{SERVERINSTANCE_QUERY_MAX_CONNECTIONS_PER_IP, "serverinstance_query_max_connections_per_ip", "3", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE},
+    PropertyDescription{SERVERINSTANCE_MONTHLY_TIMESTAMP, "serverinstance_monthly_timestamp", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE},
+    PropertyDescription{SERVERINSTANCE_MAX_DOWNLOAD_TOTAL_BANDWIDTH, "serverinstance_max_download_total_bandwidth", "-1", TYPE_SIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE},
+    PropertyDescription{SERVERINSTANCE_MAX_UPLOAD_TOTAL_BANDWIDTH, "serverinstance_max_upload_total_bandwidth", "-1", TYPE_SIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE},
+    PropertyDescription{SERVERINSTANCE_SERVERQUERY_FLOOD_COMMANDS, "serverinstance_serverquery_flood_commands", "3", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE},       //how many commands we can issue while in the SERVERINSTANCE_SERVERQUERY_FLOOD_TIME window
+    PropertyDescription{SERVERINSTANCE_SERVERQUERY_FLOOD_TIME, "serverinstance_serverquery_flood_time", "1", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE},           //time window in seconds for max command execution check
+    PropertyDescription{SERVERINSTANCE_SERVERQUERY_BAN_TIME, "serverinstance_serverquery_ban_time", "600", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE},             //how many seconds someone get banned if he floods
+    PropertyDescription{SERVERINSTANCE_TEMPLATE_SERVERADMIN_GROUP, "serverinstance_template_serveradmin_group", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE},
+    PropertyDescription{SERVERINSTANCE_TEMPLATE_SERVERDEFAULT_GROUP, "serverinstance_template_serverdefault_group", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE},
+    PropertyDescription{SERVERINSTANCE_TEMPLATE_CHANNELADMIN_GROUP, "serverinstance_template_channeladmin_group", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE},
+    PropertyDescription{SERVERINSTANCE_TEMPLATE_CHANNELDEFAULT_GROUP, "serverinstance_template_channeldefault_group", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE},
+    PropertyDescription{SERVERINSTANCE_TEMPLATE_MUSICDEFAULT_GROUP, "serverinstance_template_musicdefault_group", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE},
+    PropertyDescription{SERVERINSTANCE_GUEST_SERVERQUERY_GROUP, "serverinstance_guest_serverquery_group", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE},
+    PropertyDescription{SERVERINSTANCE_ADMIN_SERVERQUERY_GROUP, "serverinstance_admin_serverquery_group", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE},
+    PropertyDescription{SERVERINSTANCE_PENDING_CONNECTIONS_PER_IP, "serverinstance_pending_connections_per_ip", "0", TYPE_UNSIGNED_NUMBER, FLAG_INSTANCE_VARIABLE | FLAG_SAVE},
+    PropertyDescription{SERVERINSTANCE_SPOKEN_TIME_TOTAL, "serverinstance_spoken_time_total", "0", TYPE_UNSIGNED_NUMBER, FLAG_INTERNAL | FLAG_SAVE | FLAG_NEW},
+    PropertyDescription{SERVERINSTANCE_SPOKEN_TIME_DELETED, "serverinstance_spoken_time_deleted", "0", TYPE_UNSIGNED_NUMBER, FLAG_INTERNAL | FLAG_SAVE | FLAG_NEW},
+    PropertyDescription{SERVERINSTANCE_SPOKEN_TIME_ALIVE, "serverinstance_spoken_time_alive", "0", TYPE_UNSIGNED_NUMBER, FLAG_INTERNAL | FLAG_SAVE | FLAG_NEW},
+    PropertyDescription{SERVERINSTANCE_SPOKEN_TIME_VARIANZ, "serverinstance_spoken_time_varianz", "0", TYPE_UNSIGNED_NUMBER, FLAG_INTERNAL | FLAG_SAVE | FLAG_NEW},
+    PropertyDescription{SERVERINSTANCE_VIRTUAL_SERVER_ID_INDEX, "serverinstance_virtual_server_id_index", "1", TYPE_UNSIGNED_NUMBER, FLAG_SAVE | FLAG_INSTANCE_VARIABLE | FLAG_NEW},
+    PropertyDescription{SERVERINSTANCE_UNIQUE_ID, "serverinstance_unique_id", "", TYPE_STRING, FLAG_INTERNAL | FLAG_SAVE | FLAG_NEW},
+
+    /* playlist properties */
+    PropertyDescription{PLAYLIST_UNDEFINED, "undefined", "", TYPE_UNKNOWN, 0},
+    PropertyDescription{PLAYLIST_ID, "playlist_id", "0", TYPE_UNSIGNED_NUMBER, FLAG_PLAYLIST_VARIABLE},
+    PropertyDescription{PLAYLIST_TITLE, "playlist_title", "Yet another playlist", TYPE_STRING, FLAG_PLAYLIST_VARIABLE | FLAG_USER_EDITABLE | FLAG_SAVE},
+    PropertyDescription{PLAYLIST_DESCRIPTION, "playlist_description", "", TYPE_STRING, FLAG_PLAYLIST_VARIABLE | FLAG_USER_EDITABLE | FLAG_SAVE},
+    PropertyDescription{PLAYLIST_TYPE, "playlist_type", "0", TYPE_UNSIGNED_NUMBER, FLAG_PLAYLIST_VARIABLE | FLAG_SAVE},
+    PropertyDescription{PLAYLIST_OWNER_DBID, "playlist_owner_dbid", "0", TYPE_UNSIGNED_NUMBER, FLAG_PLAYLIST_VARIABLE | FLAG_SAVE},
+    PropertyDescription{PLAYLIST_OWNER_NAME, "playlist_owner_name", "0", TYPE_STRING, FLAG_PLAYLIST_VARIABLE | FLAG_SAVE},
+    PropertyDescription{PLAYLIST_MAX_SONGS, "playlist_max_songs", "-1", TYPE_SIGNED_NUMBER, FLAG_PLAYLIST_VARIABLE | FLAG_USER_EDITABLE | FLAG_SAVE},
+    PropertyDescription{PLAYLIST_FLAG_DELETE_PLAYED, "playlist_flag_delete_played", "1", TYPE_BOOL, FLAG_PLAYLIST_VARIABLE | FLAG_USER_EDITABLE | FLAG_SAVE},
+    PropertyDescription{PLAYLIST_FLAG_FINISHED, "playlist_flag_finished", "0", TYPE_BOOL, FLAG_PLAYLIST_VARIABLE | FLAG_USER_EDITABLE | FLAG_SAVE},
+    PropertyDescription{PLAYLIST_REPLAY_MODE, "playlist_replay_mode", "0", TYPE_UNSIGNED_NUMBER, FLAG_PLAYLIST_VARIABLE | FLAG_USER_EDITABLE | FLAG_SAVE},
+    PropertyDescription{PLAYLIST_CURRENT_SONG_ID, "playlist_current_song_id", "0", TYPE_UNSIGNED_NUMBER, FLAG_PLAYLIST_VARIABLE | FLAG_SAVE}
+);
+
+#undef str_
+#undef V
+#undef F
+
+#undef FLAG_SS
+#undef FLAG_SERVER_VV
+#undef FLAG_SERVER_VVSS
+#undef FLAG_CLIENT_VV
+#undef FLAG_CLIENT_VVSS
\ No newline at end of file
diff --git a/src/PropertyDefinitions.cpp b/src/PropertyDefinitions.cpp
new file mode 100644
index 0000000..393c93f
--- /dev/null
+++ b/src/PropertyDefinitions.cpp
@@ -0,0 +1,84 @@
+//
+// Created by WolverinDEV on 08/04/2020.
+//
+
+#include "./Properties.h"
+
+using namespace ts;
+
+#ifdef EXTERNALIZE_PROPERTY_DEFINITIONS
+using PropertyDescription = property::PropertyDescription;
+#include "./PropertyDefinition.h"
+const property::PropertyListInfo property::property_list_info = impl::list_info();
+#endif
+
+using PropertyType = property::PropertyType;
+using PropertyType = property::PropertyType;
+
+/* verifier methods */
+constexpr bool validate_property_list_contains_all_types() {
+    for(const auto& entry : property::property_list_info.begin_index)
+        if(entry >= property::property_list.size())
+            return false;
+    return true;
+}
+
+constexpr bool validate_all_names_valid() {
+    for(const auto& entry : property::property_list)
+        for(const auto& c : entry.name)
+            if(!((c >= 'a' && c <= 'z') || c == '_' || (c >= '0' && c <= '9')))
+                return false;
+    return true;
+}
+
+constexpr bool validate_first_property_undefined() {
+    for(const auto& index : property::property_list_info.begin_index)
+        if(index < property::property_list.size())
+            if(property::property_list[index].name != "undefined")
+                return false;
+    return true;
+}
+
+constexpr bool property_list_ordered() {
+    static_assert(!property::property_list.empty());
+
+    /* initial setup */
+    std::array<bool, PropertyType::PROP_TYPE_MAX> visited_types{};
+    PropertyType current_type{property::property_list[0].type_property};
+    visited_types[current_type] = true;
+    size_t last_id{(size_t) property::property_list[0].property_index};
+    if(last_id != 0) return false;
+
+    /* iterate */
+    for(auto index{1}; index < property::property_list.size(); index++) {
+        const auto& entry = property::property_list[index];
+        if(last_id + 1 != entry.property_index) {
+            if(current_type == entry.type_property)
+                return false;
+            if(visited_types[entry.type_property])
+                return false;
+            if(entry.property_index != 0) /* new type must start with 0 (undefined) */
+                return false;
+            visited_types[current_type = entry.type_property] = true;
+            last_id = 0;
+        } else if(current_type != entry.type_property)
+            return false;
+        else
+            last_id++;
+    }
+    return true;
+}
+
+#ifdef EXTERNALIZE_PROPERTY_DEFINITIONS
+__attribute__((constructor)) void validate_properties() {
+    assert(property_list_ordered());
+    assert(validate_first_property_undefined());
+    assert(validate_property_list_contains_all_types());
+    assert(validate_all_names_valid());
+}
+#else
+static_assert(property_list_ordered(), "Property list is unordered!");
+static_assert(validate_first_property_undefined(), "First property of each type must be the undefined property");
+static_assert(validate_property_list_contains_all_types(), "Missing property begin for a property type");
+static_assert(validate_all_names_valid(), "Property list contains name which does not match the expected names: [a-z_]+");
+#endif
\ No newline at end of file
diff --git a/src/converters/converter.cpp b/src/converters/converter.cpp
index 7ffb256..aebbc1d 100644
--- a/src/converters/converter.cpp
+++ b/src/converters/converter.cpp
@@ -37,4 +37,5 @@ CONVERTER_PRIMITIVE_ST(double, std::stod(std::string{str}));
 CONVERTER_PRIMITIVE_ST(long_double, std::stold(std::string{str}));
 
 CONVERTER_ST(std__string, return std::string{str};, return std::any_cast<std__string>(value););
-CONVERTER_ST(const_char__ , return str.data();, return std::string(std::any_cast<const_char__>(value)););
\ No newline at end of file
+CONVERTER_ST(std__string_view, return str;, return std::string{std::any_cast<std__string_view>(value)};);
+CONVERTER_ST(const_char__ , return str.data();, return std::string{std::any_cast<const_char__>(value)};);
\ No newline at end of file
diff --git a/src/converters/converter.h b/src/converters/converter.h
index 58330b7..c0c0394 100644
--- a/src/converters/converter.h
+++ b/src/converters/converter.h
@@ -54,8 +54,10 @@ namespace ts {
     CONVERTER_PRIMITIVE(uint64_t);
 
     typedef std::string std__string;
+    typedef std::string_view std__string_view;
     typedef const char* const_char__;
     CONVERTER_PRIMITIVE(std__string);
+    CONVERTER_PRIMITIVE(std__string_view);
     CONVERTER_PRIMITIVE(const_char__);
 
     /* const expr char literal */
diff --git a/src/protocol/AcknowledgeManager.cpp b/src/protocol/AcknowledgeManager.cpp
index 6d5484c..bbe0b41 100644
--- a/src/protocol/AcknowledgeManager.cpp
+++ b/src/protocol/AcknowledgeManager.cpp
@@ -41,12 +41,12 @@ void AcknowledgeManager::process_packet(ts::protocol::BasicPacket &packet) {
     entry->buffer = packet.buffer();
 
     entry->resend_count = 0;
-    entry->resend_period = milliseconds((int) ceil(this->average_response * 3/2));
     entry->first_send = system_clock::now();
-    entry->next_resend = entry->first_send + entry->resend_period;
+    entry->next_resend = entry->first_send + std::chrono::milliseconds{(int64_t) ceil(this->rto)};
 
     entry->packet_type = packet.type().type();
     entry->packet_id = packet.packetId();
+    entry->generation_id = packet.generationId();
 
     entry->acknowledged = false;
     entry->send_count = 1;
@@ -56,11 +56,8 @@ void AcknowledgeManager::process_packet(ts::protocol::BasicPacket &packet) {
     }
 }
 
-bool AcknowledgeManager::process_acknowledge(uint8_t packet_type, const pipes::buffer_view& payload, std::string& error) {
-    if(payload.length() < 2) return false;
-
+bool AcknowledgeManager::process_acknowledge(uint8_t packet_type, uint16_t target_id, std::string& error) {
     PacketType target_type{packet_type == protocol::ACK_LOW ? PacketType::COMMAND_LOW : PacketType::COMMAND};
-    uint16_t target_id{be2le16((char*) payload.data_ptr())};
 
     std::shared_ptr<Entry> entry;
     std::unique_ptr<threads::Future<bool>> ack_listener;
@@ -72,8 +69,13 @@ bool AcknowledgeManager::process_acknowledge(uint8_t packet_type, const pipes::b
                 ack_listener = std::move(entry->acknowledge_listener); /* move it out so nobody else could call it as well */
 
                 entry->send_count--;
-                if(entry->send_count == 0)
+                if(entry->send_count == 0) {
                     this->entries.erase(it);
+                    if(entry->resend_count == 0) {
+                        auto difference = std::chrono::system_clock::now() - entry->first_send;
+                        this->update_rto(std::chrono::duration_cast<std::chrono::milliseconds>(difference).count());
+                    }
+                }
                 break;
             }
         }
@@ -83,18 +85,12 @@ bool AcknowledgeManager::process_acknowledge(uint8_t packet_type, const pipes::b
         return false;
     }
 
-    auto time = system_clock::now() - entry->next_resend + entry->resend_period;
-    auto ms_time = duration_cast<milliseconds>(time).count();
-    if(ms_time > 5) {
-        this->average_response = this->average_response * .80 + ms_time * .2;
-    }
-
     entry->acknowledged = true;
     if(ack_listener) ack_listener->executionSucceed(true);
     return true;
 }
 
-ssize_t AcknowledgeManager::execute_resend(const system_clock::time_point& now , std::chrono::system_clock::time_point &next_resend,std::deque<pipes::buffer>& buffers, string& error) {
+ssize_t AcknowledgeManager::execute_resend(const system_clock::time_point& now , std::chrono::system_clock::time_point &next_resend,std::deque<std::shared_ptr<Entry>>& buffers, string& error) {
     size_t resend_count{0};
 
     vector<shared_ptr<Entry>> need_resend;
@@ -105,19 +101,13 @@ ssize_t AcknowledgeManager::execute_resend(const system_clock::time_point& now ,
 
         for (auto &entry : this->entries) {
             if(entry->acknowledged) {
-                if(entry->next_resend + entry->resend_period <= now) { // Some resends are lost. So we just drop it after time
+                if(entry->next_resend + std::chrono::milliseconds{(int64_t) ceil(this->rto * 4)} <= now) { // Some resends are lost. So we just drop it after time
                     entry.reset();
                     cleanup = true;
                 }
             } else {
                if(entry->next_resend <= now) {
-                   entry->resend_period = entry->resend_period + milliseconds{(int) ceil(this->average_response * 2)};
-                   if(entry->resend_period.count() > 1000)
-                       entry->resend_period = milliseconds(1000);
-                   else if(entry->resend_period.count() < 25)
-                       entry->resend_period = milliseconds(25);
-
-                   entry->next_resend = now + entry->resend_period;
+                   entry->next_resend = now + std::chrono::milliseconds{(int64_t) min(ceil(this->rto), 1500.f)};
                    need_resend.push_back(entry);
                }
                 if(next_resend > entry->next_resend)
@@ -140,8 +130,21 @@ ssize_t AcknowledgeManager::execute_resend(const system_clock::time_point& now ,
         resend_count++;
         packet->resend_count++;
         packet->send_count++;
-        buffers.push_back(packet->buffer);
+        buffers.push_back(packet);
     }
 
     return resend_count;
+}
+
+/* we're not taking the clock granularity into account because its nearly 1ms and it would only add more branches  */
+void AcknowledgeManager::update_rto(size_t r) {
+    if(srtt == -1) {
+        this->srtt = r;
+        this->rttvar = r / 2.f;
+        this->rto = srtt + 4 * this->rttvar;
+    } else {
+        this->rttvar = (1.f - alpha) * this->rttvar + beta * abs(this->srtt - r);
+        this->srtt = (1.f - alpha) * srtt + alpha * r;
+        this->rto = std::min(200.f, this->srtt + 4 * this->rttvar);
+    }
 }
\ No newline at end of file
diff --git a/src/protocol/AcknowledgeManager.h b/src/protocol/AcknowledgeManager.h
index e3d3352..81d6416 100644
--- a/src/protocol/AcknowledgeManager.h
+++ b/src/protocol/AcknowledgeManager.h
@@ -7,22 +7,23 @@
 namespace ts::connection {
     class VoiceClientConnection;
     class AcknowledgeManager {
-        struct Entry {
-            uint16_t packet_id = 0;
-            uint8_t packet_type = 0xFF;
-            uint8_t resend_count = 0;
-            bool acknowledged : 1;
-            uint8_t send_count : 7;
-
-
-            pipes::buffer buffer;
-            std::chrono::system_clock::time_point first_send;
-            std::chrono::system_clock::time_point next_resend;
-            std::chrono::milliseconds resend_period;
-
-            std::unique_ptr<threads::Future<bool>> acknowledge_listener;
-        };
         public:
+            struct Entry {
+                uint16_t packet_id{0};
+                uint16_t generation_id{0};
+
+                uint8_t packet_type{0xFF};
+                uint8_t resend_count{0};
+                bool acknowledged : 1;
+                uint8_t send_count : 7;
+
+
+                pipes::buffer buffer;
+                std::chrono::system_clock::time_point first_send;
+                std::chrono::system_clock::time_point next_resend;
+                std::unique_ptr<threads::Future<bool>> acknowledge_listener;
+            };
+
             AcknowledgeManager();
             virtual ~AcknowledgeManager();
 
@@ -30,20 +31,29 @@ namespace ts::connection {
             void reset();
 
             void process_packet(ts::protocol::BasicPacket& /* packet */);
-            bool process_acknowledge(uint8_t packet_type, const pipes::buffer_view& /* payload */, std::string& /* error */);
+            bool process_acknowledge(uint8_t packet_type, uint16_t /* packet id */, std::string& /* error */);
 
             ssize_t execute_resend(
                     const std::chrono::system_clock::time_point& /* now */,
                     std::chrono::system_clock::time_point& /* next resend */,
-                    std::deque<pipes::buffer>& /* buffers to resend */,
+                    std::deque<std::shared_ptr<Entry>>& /* buffers to resend */,
                     std::string& /* error */
             );
+
+            [[nodiscard]] inline auto current_rto() const { return this->rto; }
+            [[nodiscard]] inline auto current_srtt() const { return this->srtt; }
+            [[nodiscard]] inline auto current_rttvar() const { return this->rttvar; }
         private:
             std::mutex entry_lock;
             std::deque<std::shared_ptr<Entry>> entries;
 
-            std::chrono::milliseconds resend_delay{500};
+            float rto{1000};
+            float srtt{-1};
+            float rttvar{};
 
-            double average_response = 20;
+            constexpr static auto alpha{.125f};
+            constexpr static auto beta{.25f};
+
+            void update_rto(size_t /* response time */);
     };
 }
\ No newline at end of file
diff --git a/src/protocol/Packet.cpp b/src/protocol/Packet.cpp
index 7cb3b31..efeb9b9 100644
--- a/src/protocol/Packet.cpp
+++ b/src/protocol/Packet.cpp
@@ -216,27 +216,32 @@ namespace ts {
         }
 
 
-        uint16_t ClientPacketParser::packet_id() const { return be2le16(this->_buffer.data_ptr<uint8_t>(), ClientPacketParser::kHeaderOffset + 0); }
-        uint16_t ClientPacketParser::client_id() const { return be2le16(this->_buffer.data_ptr<uint8_t>(), ClientPacketParser::kHeaderOffset + 2); }
-        uint8_t ClientPacketParser::type() const { return (uint8_t) this->_buffer[ClientPacketParser::kHeaderOffset + 4] & 0xFU; }
-        uint8_t ClientPacketParser::flags() const { return (uint8_t) this->_buffer[ClientPacketParser::kHeaderOffset + 4] & 0xF0U; }
-
-        bool ClientPacketParser::is_encrypted() const {
+        /* New packet parser API */
+        bool PacketParser::is_encrypted() const {
             if(this->decrypted) return false;
 
             return (this->flags() & PacketFlag::Unencrypted) == 0;
         }
 
-        bool ClientPacketParser::is_compressed() const {
+        bool PacketParser::is_compressed() const {
             if(this->uncompressed) return false;
 
             return (this->flags() & PacketFlag::Compressed) > 0;
         }
 
-        bool ClientPacketParser::is_fragmented() const {
+        bool PacketParser::is_fragmented() const {
             if(this->defragmented) return false;
 
             return (this->flags() & PacketFlag::Fragmented) > 0;
         }
+
+        uint16_t ClientPacketParser::packet_id() const { return be2le16(this->_buffer.data_ptr<uint8_t>(), ClientPacketParser::kHeaderOffset + 0); }
+        uint16_t ClientPacketParser::client_id() const { return be2le16(this->_buffer.data_ptr<uint8_t>(), ClientPacketParser::kHeaderOffset + 2); }
+        uint8_t ClientPacketParser::type() const { return (uint8_t) this->_buffer[ClientPacketParser::kHeaderOffset + 4] & 0xFU; }
+        uint8_t ClientPacketParser::flags() const { return (uint8_t) this->_buffer[ClientPacketParser::kHeaderOffset + 4] & 0xF0U; }
+
+        uint16_t ServerPacketParser::packet_id() const { return be2le16(this->_buffer.data_ptr<uint8_t>(), ClientPacketParser::kHeaderOffset + 0); }
+        uint8_t ServerPacketParser::type() const { return (uint8_t) this->_buffer[ClientPacketParser::kHeaderOffset + 2] & 0xFU; }
+        uint8_t ServerPacketParser::flags() const { return (uint8_t) this->_buffer[ClientPacketParser::kHeaderOffset + 2] & 0xF0U; }
     }
 }
\ No newline at end of file
diff --git a/src/protocol/Packet.h b/src/protocol/Packet.h
index ce456bf..97beac5 100644
--- a/src/protocol/Packet.h
+++ b/src/protocol/Packet.h
@@ -286,32 +286,23 @@ namespace ts {
                 void setPacketId(uint16_t, uint16_t) override;
         };
 
-        class ClientPacketParser {
+        class PacketParser {
             public:
-                constexpr static auto kHeaderOffset = 8;
-                constexpr static auto kHeaderLength = CLIENT_HEADER_SIZE;
-
-                constexpr static auto kPayloadOffset = kHeaderOffset + CLIENT_HEADER_SIZE;
-                explicit ClientPacketParser(pipes::buffer_view buffer) : _buffer{std::move(buffer)} {}
-                ClientPacketParser(const ClientPacketParser&) = delete;
-
-                [[nodiscard]] inline bool valid() const {
-                    if(this->_buffer.length() < kPayloadOffset) return false;
-                    return this->type() <= 8;
-                }
+                PacketParser(const PacketParser&) = delete;
+                explicit PacketParser(pipes::buffer_view buffer) : _buffer{std::move(buffer)} {}
 
                 [[nodiscard]] inline const void* data_ptr() const { return this->_buffer.data_ptr(); }
                 [[nodiscard]] inline void* mutable_data_ptr() { return (void*) this->_buffer.data_ptr(); }
 
                 [[nodiscard]] inline pipes::buffer_view buffer() const { return this->_buffer; }
                 [[nodiscard]] inline pipes::buffer_view mac() const { return this->_buffer.view(0, 8); }
-                [[nodiscard]] inline pipes::buffer_view payload() const { return this->_buffer.view(kPayloadOffset); }
-                [[nodiscard]] inline size_t payload_length() const { return this->_buffer.length() - kPayloadOffset; }
+                [[nodiscard]] virtual pipes::buffer_view payload() const = 0;
+                [[nodiscard]] virtual size_t payload_length() const = 0;
 
-                [[nodiscard]] uint16_t client_id() const;
-                [[nodiscard]] uint16_t packet_id() const;
-                [[nodiscard]] uint8_t type() const;
-                [[nodiscard]] uint8_t flags() const;
+                [[nodiscard]] inline uint32_t full_packet_id() const { return this->packet_id() | (this->estimated_generation() << 16U); }
+                [[nodiscard]] virtual uint16_t packet_id() const = 0;
+                [[nodiscard]] virtual uint8_t type() const = 0;
+                [[nodiscard]] virtual uint8_t flags() const = 0;
 
                 [[nodiscard]] bool is_encrypted() const;
                 [[nodiscard]] bool is_compressed() const;
@@ -323,12 +314,36 @@ namespace ts {
                 inline void set_decrypted() { this->decrypted = true; }
                 inline void set_uncompressed() { this->uncompressed = true; }
                 inline void set_defragmented() { this->defragmented = true; }
-            private:
+
+            protected:
                 uint16_t generation{};
                 bool decrypted{false}, uncompressed{false}, defragmented{false};
                 pipes::buffer_view _buffer{};
         };
 
+        class ClientPacketParser : public PacketParser {
+            public:
+                constexpr static auto kHeaderOffset = 8;
+                constexpr static auto kHeaderLength = CLIENT_HEADER_SIZE;
+
+                constexpr static auto kPayloadOffset = kHeaderOffset + CLIENT_HEADER_SIZE;
+                explicit ClientPacketParser(pipes::buffer_view buffer) : PacketParser{std::move(buffer)} {}
+                ClientPacketParser(const ClientPacketParser&) = delete;
+
+                [[nodiscard]] inline bool valid() const {
+                    if(this->_buffer.length() < kPayloadOffset) return false;
+                    return this->type() <= 8;
+                }
+
+                [[nodiscard]] inline pipes::buffer_view payload() const override { return this->_buffer.view(kPayloadOffset); }
+                [[nodiscard]] inline size_t payload_length() const override { return this->_buffer.length() - kPayloadOffset; }
+
+                [[nodiscard]] uint16_t client_id() const;
+                [[nodiscard]] uint16_t packet_id() const override;
+                [[nodiscard]] uint8_t type() const override;
+                [[nodiscard]] uint8_t flags() const override;
+        };
+
         /**
          * Packet from the server
          */
@@ -367,5 +382,27 @@ namespace ts {
 
                 void setPacketId(uint16_t, uint16_t) override;
         };
+
+        class ServerPacketParser : public PacketParser {
+            public:
+                constexpr static auto kHeaderOffset = 8;
+                constexpr static auto kHeaderLength = SERVER_HEADER_SIZE;
+
+                constexpr static auto kPayloadOffset = kHeaderOffset + SERVER_HEADER_SIZE;
+                explicit ServerPacketParser(pipes::buffer_view buffer) : PacketParser{std::move(buffer)} {}
+                ServerPacketParser(const ServerPacketParser&) = delete;
+
+                [[nodiscard]] inline bool valid() const {
+                    if(this->_buffer.length() < kPayloadOffset) return false;
+                    return this->type() <= 8;
+                }
+
+                [[nodiscard]] inline pipes::buffer_view payload() const override { return this->_buffer.view(kPayloadOffset); }
+                [[nodiscard]] inline size_t payload_length() const override { return this->_buffer.length() - kPayloadOffset; }
+
+                [[nodiscard]] uint16_t packet_id() const override;
+                [[nodiscard]] uint8_t type() const override;
+                [[nodiscard]] uint8_t flags() const override;
+        };
     }
 }
\ No newline at end of file
diff --git a/src/protocol/PacketLossCalculator.cpp b/src/protocol/PacketLossCalculator.cpp
new file mode 100644
index 0000000..f0a5bc6
--- /dev/null
+++ b/src/protocol/PacketLossCalculator.cpp
@@ -0,0 +1,105 @@
+//
+// Created by WolverinDEV on 06/04/2020.
+//
+
+#include <cassert>
+#include <utility>
+#include "PacketLossCalculator.h"
+
+using namespace ts::protocol;
+
+void UnorderedPacketLossCalculator::packet_received(uint32_t packet_id) {
+    if(packet_id > this->packet_history_offset) {
+        const auto age = packet_id - this->packet_history_offset; /* best case should be 1 */
+
+        if(age < this->packet_history.max_bits()) {
+            const auto received = this->packet_history.shift_in_bounds(age).count();
+            this->received_packets_ += received;
+            this->received_packets_total_ += received;
+
+            this->lost_packets_ += age - received;
+            this->lost_packets_total_ += age - received;
+        } else {
+            const auto received = this->packet_history.clear().count();
+            this->received_packets_ += received;
+            this->received_packets_total_ += received;
+            this->lost_packets_ += this->packet_history.max_bits() - received;
+            this->lost_packets_total_ += this->packet_history.max_bits() - received;
+
+            if(age >= this->packet_history.max_bits() * 2) {
+                this->packet_history.set_unchecked(0);
+                this->lost_packets_ += age - this->packet_history.max_bits() * 2;
+                this->lost_packets_total_ += age - this->packet_history.max_bits() * 2;
+            } else {
+                this->packet_history.set_unchecked(age - this->packet_history.max_bits());
+            }
+        }
+        this->packet_history.set_unchecked(0);
+        this->packet_history_offset = packet_id;
+        if(packet_id < this->packet_history.max_bits()) {
+            this->received_packets_ = 0;
+            this->received_packets_total_ = 0;
+            this->lost_packets_ = 0;
+            this->lost_packets_total_ = 0;
+        }
+    } else {
+        /* unordered packet */
+        const auto age = this->packet_history_offset - packet_id;
+        if(age >= this->packet_history.max_bits())
+            return; /* well that packet is way too old */
+
+        this->packet_history.set_unchecked(age);
+    }
+}
+
+void UnorderedPacketLossCalculator::short_stats() {
+    constexpr auto target_interval = 32;
+
+    const auto packets_passed = this->packet_history_offset - this->last_history_offset;
+    if(packets_passed < target_interval) return;
+
+    const auto factor = .5;
+    this->received_packets_ *= factor;
+    this->lost_packets_ *= factor;
+    this->last_history_offset = this->packet_history_offset;
+}
+
+void CommandPacketLossCalculator::packet_send(uint32_t packet_id) {
+    if(packet_id > this->packet_history_offset) {
+        assert(packet_id - 1 == this->packet_history_offset); /* the method will only be called with an incrementing packet id */
+        /* newly send packet */
+        auto lost = std::exchange(this->packet_ack_counts[packet_id % CommandPacketLossCalculator::packet_ack_counts_length], 1);
+        this->lost_packets_ += lost;
+        this->lost_packets_total_ += lost;
+        if(lost > 0)
+            __asm__("nop");
+        this->packet_history_offset = packet_id;
+    } else {
+        /* We're not really interested if the packet id matches the resend packet. If not we may accidentally increase the loss count. */
+        this->packet_ack_counts[packet_id % CommandPacketLossCalculator::packet_ack_counts_length]++;
+    }
+    this->packets_send_unshorten++;
+}
+
+void CommandPacketLossCalculator::ack_received(uint32_t packet_id) {
+    auto& count = this->packet_ack_counts[packet_id % CommandPacketLossCalculator::packet_ack_counts_length];
+    if(count > 0) /* could happen if receive an acknowledge for an packet which is older than out buffer size or the client send the ack twice... */
+        count--;
+    else
+        __asm__("nop");
+
+    this->received_packets_++;
+    this->received_packets_total_++;
+}
+
+void CommandPacketLossCalculator::short_stats() {
+    constexpr auto target_interval = 64;
+
+    const auto packets_passed = this->packets_send_unshorten;
+    if(packets_passed < target_interval) return;
+    this->packets_send_unshorten = 0;
+
+    const auto factor = target_interval / packets_passed;
+    this->received_packets_ *= factor;
+    this->lost_packets_ *= factor;
+}
\ No newline at end of file
diff --git a/src/protocol/PacketLossCalculator.h b/src/protocol/PacketLossCalculator.h
new file mode 100644
index 0000000..b0c7e73
--- /dev/null
+++ b/src/protocol/PacketLossCalculator.h
@@ -0,0 +1,103 @@
+#pragma once
+
+#include <utility>
+#include <cassert>
+#include <cstddef>
+#include <bitset>
+
+namespace ts::protocol {
+    template <size_t N>
+    struct bit_set;
+
+    template <>
+    struct bit_set<32> {
+            constexpr static auto native_memory_bytes = sizeof(uint32_t);
+            constexpr static auto native_memory_bits = native_memory_bytes * 8;
+        public:
+            bit_set() : memory{0} {}
+            explicit bit_set(uint32_t mem) : memory{mem} {}
+
+            [[nodiscard]] inline auto max_bits() const { return native_memory_bits; }
+
+            inline auto shift_in_bounds(size_t offset) {
+                assert(offset <= this->native_memory_bits);
+
+                auto result = bit_set<native_memory_bits>{this->memory >> (native_memory_bits - offset)};
+                this->memory <<= offset;
+                return result;
+            }
+
+            inline void set_unchecked(size_t offset) {
+                this->memory |= 1U << offset;
+            }
+
+            [[nodiscard]] inline auto count() const {
+                /* std::bitset will get optimized away */
+                return std::bitset<32>(this->memory).count();
+            }
+
+            inline auto clear() { return bit_set<native_memory_bits>{std::exchange(this->memory, 0)}; }
+        private:
+            uint32_t memory;
+    };
+
+    /* will we ever have more than 2^32 packets? Hell no. That would be over (2^32 / (50 * 60 * 60 * 24) := 994.2 days continuous speaking */
+    class UnorderedPacketLossCalculator {
+        public:
+            UnorderedPacketLossCalculator() = default;
+
+            void packet_received(uint32_t /* packet id */);
+            void short_stats();
+
+            [[nodiscard]] inline auto last_packet_id() const { return this->packet_history_offset; }
+            [[nodiscard]] inline bool valid_data() const { return this->packet_history_offset >= 32; }
+
+            [[nodiscard]] inline uint32_t received_packets() const { return this->received_packets_; }
+            [[nodiscard]] inline uint32_t lost_packets() const { return this->lost_packets_; }
+
+            [[nodiscard]] inline uint32_t received_packets_total() const { return this->received_packets_total_; }
+            [[nodiscard]] inline uint32_t lost_packets_total() const { return this->lost_packets_total_; }
+
+            [[nodiscard]] inline uint32_t unconfirmed_received_packets() const { return this->packet_history.count(); };
+            [[nodiscard]] inline uint32_t unconfirmed_lost_packets() const { return this->packet_history.max_bits() - this->packet_history.count(); };
+
+            inline void reset() { this->received_packets_ = 0; this->lost_packets_ = 0; }
+        private:
+            uint32_t received_packets_{0}, received_packets_total_{0}, lost_packets_{0}, lost_packets_total_{0};
+
+            uint32_t packet_history_offset{0}, last_history_offset{0};
+            bit_set<32> packet_history{};
+    };
+
+    class CommandPacketLossCalculator {
+            constexpr static auto packet_ack_counts_length{32};
+        public:
+            CommandPacketLossCalculator() = default;
+
+            void packet_send(uint32_t /* packet id */);
+            void ack_received(uint32_t /* packet id */); //Attention: This is a full ID!
+
+            void short_stats();
+
+            [[nodiscard]] inline bool valid_data() const { return true;  }
+
+            [[nodiscard]] inline uint32_t received_packets() const { return this->received_packets_; }
+            [[nodiscard]] inline uint32_t lost_packets() const { return this->lost_packets_; }
+
+            [[nodiscard]] inline uint32_t received_packets_total() const { return this->received_packets_total_; }
+            [[nodiscard]] inline uint32_t lost_packets_total() const { return this->lost_packets_total_; }
+
+            [[nodiscard]] inline uint32_t unconfirmed_received_packets() const { return 0; };
+            [[nodiscard]] inline uint32_t unconfirmed_lost_packets() const {
+                uint32_t result{0};
+                for(auto& e : this->packet_ack_counts)
+                    result += e;
+                return result;
+            };
+        private:
+            uint32_t received_packets_{0}, received_packets_total_{0}, lost_packets_{0}, lost_packets_total_{0};
+
+            uint32_t packet_history_offset{0}, packets_send_unshorten{0};
+            uint8_t packet_ack_counts[packet_ack_counts_length]{0};
+    };
+}
\ No newline at end of file
diff --git a/src/query/Command.h b/src/query/Command.h
index 52f964b..e315615 100644
--- a/src/query/Command.h
+++ b/src/query/Command.h
@@ -141,7 +141,7 @@ operator type(){ \
 
             friend std::ostream& operator<<(std::ostream&, const ValueList&);
         private:
-            ValueList(std::string& key, std::deque<ParameterBulk>& bulkList) : key(key), bulkList(bulkList) {}
+            ValueList(std::string key, std::deque<ParameterBulk>& bulkList) : key{std::move(key)}, bulkList(bulkList) {}
             std::string key;
         public:
             std::deque<ParameterBulk>& bulkList;
@@ -171,9 +171,9 @@ operator type(){ \
             ~Command();
 
             inline std::string command() const { return getCommand(); }
-            std::string getCommand() const { return _command; }
+            [[nodiscard]] std::string getCommand() const { return _command; }
 
-            std::string build(bool escaped = true) const;
+            [[nodiscard]] std::string build(bool escaped = true) const;
 
 #ifdef HAVE_JSON
             Json::Value buildJson() const;
@@ -184,15 +184,24 @@ operator type(){ \
                 return bulks[index];
             }
 
-            ParameterBulk& operator[](size_t index){
+            template <typename T, std::enable_if_t<std::is_integral<T>::value, int> = 0>
+            ParameterBulk& operator[](T index){
                 while(bulks.size() <= index) bulks.push_back(ParameterBulk{});
                 return bulks[index];
             }
 
-            ValueList operator[](std::string key){
+            ValueList operator[](const std::string& key){
                 return ValueList(key, bulks);
             }
 
+            ValueList operator[](const std::string_view& key){
+                return ValueList(std::string{key}, bulks); //FIXME This should not be the normal case!
+            }
+
+            ValueList operator[](const char* key){
+                return ValueList(std::string{key}, bulks); //FIXME This should not be the normal case!
+            }
+
             size_t bulkCount() const { return bulks.size(); }
             void pop_bulk();
             void push_bulk_front();
diff --git a/test/PacketLossCalculateTest.cpp b/test/PacketLossCalculateTest.cpp
new file mode 100644
index 0000000..50e63bc
--- /dev/null
+++ b/test/PacketLossCalculateTest.cpp
@@ -0,0 +1,222 @@
+//
+// Created by WolverinDEV on 06/04/2020.
+//
+#include <iostream>
+#include <bitset>
+#include <src/protocol/PacketLossCalculator.h>
+#include <cassert>
+#include <vector>
+#include <cmath>
+
+using UnorderedPacketLossCalculator = ts::protocol::UnorderedPacketLossCalculator;
+
+inline void print_unordered_stats(UnorderedPacketLossCalculator& generator) {
+    std::cout << "Valid data: " << generator.valid_data() << ". (Received{local: " << generator.received_packets() << ", unconfirmed: " << generator.unconfirmed_received_packets() << ", total: " << generator.received_packets_total() << "}" <<
+                                           " Lost: {local: " << generator.lost_packets() << ", unconfirmed: " << generator.unconfirmed_lost_packets() << ", total: " << generator.lost_packets_total() << "} Current ID: " << generator.last_packet_id() << ")\n";
+}
+
+template <typename vector_t>
+vector_t swap_elements(vector_t vector, int per, int max_distance) {
+    for(size_t index = 0; index < vector.size() - max_distance; index++) {
+        if ((rand() % 100) < per) {
+            //lets switch
+            auto offset = rand() % max_distance;
+            std::swap(vector[index], vector[index + offset]);
+        }
+    }
+
+    return vector;
+}
+
+inline void generate_unordered(UnorderedPacketLossCalculator& generator, int loss, size_t count) {
+    size_t id{generator.last_packet_id()};
+    while(count--) {
+        if(rand() % 100 >= loss)
+            generator.packet_received(id);
+        id++;
+    }
+}
+
+void test_const_unordered_0() {
+    UnorderedPacketLossCalculator generator{};
+    for(size_t pid{0}; pid < 100; pid++)
+        generator.packet_received(pid);
+
+    assert(generator.received_packets_total() == 68);
+    assert(generator.unconfirmed_received_packets() == 32);
+    assert(generator.received_packets() == 68);
+
+    assert(generator.lost_packets_total() == 0);
+    assert(generator.lost_packets() == 0);
+    assert(generator.unconfirmed_lost_packets() == 0);
+
+    assert(generator.valid_data());
+}
+
+
+void test_const_unordered_1() {
+    UnorderedPacketLossCalculator generator{};
+    generator.packet_received(100); /* we lost the first 99 packets */
+
+    assert(generator.received_packets_total() == 0);
+    assert(generator.unconfirmed_received_packets() == 1);
+    assert(generator.received_packets() == 0);
+
+    assert(generator.lost_packets_total() == 68);
+    assert(generator.lost_packets() == 68);
+    assert(generator.unconfirmed_lost_packets() == 31);
+
+    assert(generator.valid_data());
+}
+
+void test_const_unordered_2() {
+    UnorderedPacketLossCalculator generator{};
+    for(size_t pid{0}; pid < 100; pid++)
+        if(pid % 2)
+            generator.packet_received(pid);
+
+    assert(generator.received_packets_total() == 34);
+    assert(generator.received_packets() == 34);
+    assert(generator.unconfirmed_received_packets() == 16);
+
+    assert(generator.lost_packets_total() == 34);
+    assert(generator.lost_packets() == 34);
+    assert(generator.unconfirmed_lost_packets() == 16);
+
+    assert(generator.valid_data());
+}
+
+
+void test_const_unordered_3() {
+    UnorderedPacketLossCalculator generator{};
+    for(size_t pid{0}; pid < 100; pid++)
+        if(pid % 3)
+            generator.packet_received(pid);
+
+    assert(generator.received_packets_total() == 44);
+    assert(generator.received_packets() == 44);
+    assert(generator.unconfirmed_received_packets() == 22);
+
+    assert(generator.lost_packets_total() == 23);
+    assert(generator.lost_packets() == 23);
+    assert(generator.unconfirmed_lost_packets() == 10);
+
+    assert(generator.valid_data());
+}
+
+void test_const_unordered_4() {
+    std::vector<uint32_t> received_packets{};
+    for(size_t pid{0}; pid < 100; pid++)
+        received_packets.push_back(pid);
+
+    received_packets = swap_elements(received_packets, 50, 7);
+
+    UnorderedPacketLossCalculator generator{};
+    for(const auto& packet : received_packets)
+        generator.packet_received(packet);
+
+    assert(generator.received_packets_total() == 68);
+    assert(generator.unconfirmed_received_packets() == 32);
+    assert(generator.received_packets() == 68);
+
+    assert(generator.lost_packets_total() == 0);
+    assert(generator.lost_packets() == 0);
+    assert(generator.unconfirmed_lost_packets() == 0);
+
+    assert(generator.valid_data());
+}
+
+void test_const_unordered_5() {
+    std::vector<uint32_t> received_packets{};
+    for(size_t pid{0}; pid < 100; pid++)
+        if(pid % 3)
+            received_packets.push_back(pid);
+
+    received_packets = swap_elements(received_packets, 30, 7);
+
+    UnorderedPacketLossCalculator generator{};
+    for(const auto& packet : received_packets)
+        generator.packet_received(packet);
+
+    assert(generator.received_packets_total() == 44);
+    assert(generator.received_packets() == 44);
+    assert(generator.unconfirmed_received_packets() == 22);
+
+    assert(generator.lost_packets_total() == 23);
+    assert(generator.lost_packets() == 23);
+    assert(generator.unconfirmed_lost_packets() == 10);
+
+    assert(generator.valid_data());
+}
+
+void test_unordered_6() {
+    UnorderedPacketLossCalculator generator{};
+    {
+        const auto pid_base = generator.last_packet_id();
+        for(size_t pid{0}; pid < 100; pid++)
+            generator.packet_received(pid_base + pid);
+    }
+
+    print_unordered_stats(generator);
+    generator.short_stats();
+
+    {
+        const auto pid_base = generator.last_packet_id();
+        generator.packet_received(pid_base + 100);
+    }
+    print_unordered_stats(generator);
+    generator.short_stats();
+
+    {
+        const auto pid_base = generator.last_packet_id();
+        generator.packet_received(pid_base + 100);
+    }
+    print_unordered_stats(generator);
+    generator.short_stats();
+    {
+        const auto pid_base = generator.last_packet_id();
+        for(size_t pid{0}; pid < 100; pid++)
+            generator.packet_received(pid_base + pid);
+    }
+    print_unordered_stats(generator);
+    generator.short_stats();
+    {
+        const auto pid_base = generator.last_packet_id();
+        for(size_t pid{0}; pid < 100; pid++)
+            generator.packet_received(pid_base + pid);
+    }
+    print_unordered_stats(generator);
+}
+
+int main() {
+#if 0
+    test_const_unordered_0();
+    test_const_unordered_1();
+    test_const_unordered_2();
+    test_const_unordered_3();
+    test_const_unordered_4();
+    test_const_unordered_5();
+    test_unordered_6();
+#endif
+    size_t value = 0;
+
+
+    std::vector<size_t> bandwidth_seconds{};
+    for(size_t iteration{0}; iteration < 600; iteration++) {
+        if(iteration >= 200 && iteration <= 270)
+            bandwidth_seconds.push_back(0);
+        else
+            bandwidth_seconds.push_back(500);
+    }
+
+    constexpr auto cofactor = 0.915;
+    //constexpr auto cofactor = 0.978;
+    for(size_t iteration{0}; iteration < bandwidth_seconds.size(); iteration++) {
+        const auto next_value = value * cofactor + bandwidth_seconds[iteration] * (1 - cofactor);
+        if(next_value > value)
+            value = ceil(next_value);
+        else
+            value = floor(next_value);
+        std::cout << iteration << ": " << value << "\n";
+    }
+}
diff --git a/test/PropertyTest.cpp b/test/PropertyTest.cpp
index 724ff18..589dc09 100644
--- a/test/PropertyTest.cpp
+++ b/test/PropertyTest.cpp
@@ -7,15 +7,14 @@ using namespace std;
 
 
 int main() {
-    assert(property::impl::validateUnique());
+    //assert(property::impl::validateUnique());
 
-    cout << property::impl::info(property::VIRTUALSERVER_HOST)->name << endl;
-    cout << property::impl::info<property::VirtualServerProperties>("virtualserver_host")->name<< endl;
+    cout << property::describe(property::VIRTUALSERVER_HOST).name << endl;
+    cout << property::find(property::PROP_TYPE_SERVER, "virtualserver_host").name<< endl;
 
     Properties props;
     props.register_property_type<property::InstanceProperties>();
 
-    cout << "X: " << property::impl::info(property::SERVERINSTANCE_QUERY_PORT)->default_value << endl;
     auto property = props[property::SERVERINSTANCE_QUERY_PORT];
 
     cout << "Port: " << props[property::SERVERINSTANCE_QUERY_PORT].as<string>() << endl;
@@ -26,6 +25,7 @@ int main() {
     cout << "Port: " << props[property::SERVERINSTANCE_QUERY_PORT].as<int32_t>() << endl;
 
 
+    /*
     {
         assert(property::impl::validateInput("022222", property::TYPE_UNSIGNED_NUMBER) == true);
         assert(property::impl::validateInput("000000", property::TYPE_UNSIGNED_NUMBER) == true);
@@ -54,6 +54,7 @@ int main() {
         assert(property::impl::validateInput("-.1-", property::TYPE_FLOAT) == false);
         assert(property::impl::validateInput("-2.22222.2", property::TYPE_FLOAT) == false);
     }
+     */
 
     {
         TIMING_START(timings);