diff --git a/openrct2.vcxproj b/openrct2.vcxproj index 9615badaff..5952fcceda 100644 --- a/openrct2.vcxproj +++ b/openrct2.vcxproj @@ -314,6 +314,7 @@ + diff --git a/src/core/Nullable.hpp b/src/core/Nullable.hpp new file mode 100644 index 0000000000..37e3393cfe --- /dev/null +++ b/src/core/Nullable.hpp @@ -0,0 +1,55 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#pragma once + +#include "../common.h" + +template +struct Nullable +{ +public: + Nullable() + { + _value = T(); + _hasValue = false; + } + + Nullable(const T &value) + { + _value = value; + _hasValue = true; + } + + bool HasValue() const + { + return _hasValue; + } + + T GetValue() const + { + return _value; + } + + T GetValueOrDefault(T defaultValue) const + { + return _hasValue ? _value : defaultValue; + } + +private: + T _value; + bool _hasValue; +}; diff --git a/src/network/network.cpp b/src/network/network.cpp index d7b2f839d3..e77556cada 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -1318,7 +1318,8 @@ uint8 Network::GetGroupIDByHash(const std::string &keyhash) { auto it = key_group_map.find(keyhash); if (it != key_group_map.end()) { - return it->second.GroupId; + auto groupId = it->second.GroupId; + return groupId.GetValueOrDefault(GetDefaultGroup()); } else { return GetDefaultGroup(); } @@ -1429,7 +1430,15 @@ void Network::SaveKeyMappings() for (auto it = key_group_map.cbegin(); it != key_group_map.cend(); it++) { json_t *keyMapping = json_object(); json_object_set_new(keyMapping, "hash", json_string(it->first.c_str())); - json_object_set_new(keyMapping, "groupId", json_integer(it->second.GroupId)); + + json_t *jsonGroupId; + if (it->second.GroupId.HasValue()) { + jsonGroupId = json_integer(it->second.GroupId.GetValue()); + } else { + jsonGroupId = json_null(); + } + json_object_set_new(keyMapping, "groupId", jsonGroupId); + json_array_append_new(jsonKeyMappings, keyMapping); } bool result; @@ -1466,11 +1475,14 @@ void Network::LoadKeyMappings() const char *hash = json_string_value(json_object_get(jsonKeyMapping, "hash")); const char *name = json_string_value(json_object_get(jsonKeyMapping, "name")); + const json_t *jsonGroupId = json_object_get(jsonKeyMapping, "groupId"); if (hash != nullptr && name != nullptr) { KeyMapping keyMapping; keyMapping.Hash = std::string(hash); keyMapping.Name = std::string(name); - keyMapping.GroupId = (uint8)json_integer_value(json_object_get(jsonKeyMapping, "groupId")); + if (!json_is_null(jsonGroupId)) { + keyMapping.GroupId = (uint8)json_integer_value(jsonGroupId); + } key_group_map[keyMapping.Hash] = keyMapping; } } @@ -1507,7 +1519,14 @@ void Network::UpdateKeyMappings() std::string hash(json_string_value(json_object_get(jsonKeyMapping, "hash"))); decltype(local_key_map.begin()) it; if ((it = local_key_map.find(hash)) != local_key_map.end()) { - json_object_set_new(jsonKeyMapping, "groupId", json_integer(it->second.GroupId)); + json_t *jsonGroupId; + if (it->second.GroupId.HasValue()) { + jsonGroupId = json_integer(it->second.GroupId.GetValue()); + } else { + jsonGroupId = json_null(); + } + json_object_set_new(jsonKeyMapping, "groupId", jsonGroupId); + // remove item once it was found and set local_key_map.erase(it); } @@ -1521,7 +1540,15 @@ void Network::UpdateKeyMappings() json_t *keyMapping = json_object(); json_object_set(keyMapping, "hash", json_string(it->first.c_str())); json_object_set(keyMapping, "name", json_string(it->second.Name.c_str())); - json_object_set(keyMapping, "groupId", json_integer(it->second.GroupId)); + + json_t *jsonGroupId; + if (it->second.GroupId.HasValue()) { + jsonGroupId = json_integer(it->second.GroupId.GetValue()); + } else { + jsonGroupId = json_null(); + } + json_object_set(keyMapping, "groupId", jsonGroupId); + json_array_append(jsonKeyMappings, keyMapping); } @@ -1946,7 +1973,7 @@ NetworkPlayer* Network::AddPlayer(const utf8 *name, const std::string &keyhash) player->SetName(MakePlayerNameUnique(std::string(name))); } } else { - player->group = keyMapping->GroupId; + player->group = keyMapping->GroupId.GetValueOrDefault(GetDefaultGroup()); player->SetName(keyMapping->Name); } diff --git a/src/network/network.h b/src/network/network.h index 7bf71b183f..b19c27553d 100644 --- a/src/network/network.h +++ b/src/network/network.h @@ -121,6 +121,7 @@ extern "C" { #include #include #include "../core/Json.hpp" +#include "../core/Nullable.hpp" #include "NetworkKey.h" template @@ -340,9 +341,9 @@ private: }; struct KeyMapping { - std::string Hash; - std::string Name; - uint8 GroupId; + std::string Hash; + std::string Name; + Nullable GroupId; }; class Network