Changed how the TryParse function works (and also did some general cleanup along the way)

This commit is contained in:
jadebenn 2024-02-02 17:50:30 -06:00
parent d78b50874c
commit 4f75479a4c
34 changed files with 506 additions and 535 deletions

View File

@ -82,11 +82,11 @@ int main(int argc, char** argv) {
Game::randomEngine = std::mt19937(time(0)); Game::randomEngine = std::mt19937(time(0));
//It's safe to pass 'localhost' here, as the IP is only used as the external IP. //It's safe to pass 'localhost' here, as the IP is only used as the external IP.
uint32_t maxClients = 999;
uint32_t ourPort = 1001; //LU client is hardcoded to use this for auth port, so I'm making it the default.
std::string ourIP = "localhost"; std::string ourIP = "localhost";
GeneralUtils::TryParse(Game::config->GetValue("max_clients"), maxClients); const uint32_t maxClients = GeneralUtils::TryParse<uint32_t>(Game::config->GetValue("max_clients")).value_or(999);
GeneralUtils::TryParse(Game::config->GetValue("auth_server_port"), ourPort);
//LU client is hardcoded to use this for auth port, so I'm making it the default.
const uint32_t ourPort = GeneralUtils::TryParse<uint32_t>(Game::config->GetValue("auth_server_port")).value_or(1001);
const auto externalIPString = Game::config->GetValue("external_ip"); const auto externalIPString = Game::config->GetValue("external_ip");
if (!externalIPString.empty()) ourIP = externalIPString; if (!externalIPString.empty()) ourIP = externalIPString;

View File

@ -99,18 +99,15 @@ int main(int argc, char** argv) {
masterPort = masterInfo->port; masterPort = masterInfo->port;
} }
//It's safe to pass 'localhost' here, as the IP is only used as the external IP. //It's safe to pass 'localhost' here, as the IP is only used as the external IP.
uint32_t maxClients = 999;
uint32_t ourPort = 1501;
std::string ourIP = "localhost"; std::string ourIP = "localhost";
GeneralUtils::TryParse(Game::config->GetValue("max_clients"), maxClients); const uint32_t maxClients = GeneralUtils::TryParse<uint32_t>(Game::config->GetValue("max_clients")).value_or(999);
GeneralUtils::TryParse(Game::config->GetValue("chat_server_port"), ourPort); const uint32_t ourPort = GeneralUtils::TryParse<uint32_t>(Game::config->GetValue("chat_server_port")).value_or(1501);
const auto externalIPString = Game::config->GetValue("external_ip"); const auto externalIPString = Game::config->GetValue("external_ip");
if (!externalIPString.empty()) ourIP = externalIPString; if (!externalIPString.empty()) ourIP = externalIPString;
Game::server = new dServer(ourIP, ourPort, 0, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::Chat, Game::config, &Game::lastSignal); Game::server = new dServer(ourIP, ourPort, 0, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::Chat, Game::config, &Game::lastSignal);
bool dontGenerateDCF = false; const bool dontGenerateDCF = GeneralUtils::TryParse<bool>(Game::config->GetValue("dont_generate_dcf")).value_or(false);
GeneralUtils::TryParse(Game::config->GetValue("dont_generate_dcf"), dontGenerateDCF);
Game::chatFilter = new dChatFilter(Game::assetManager->GetResPath().string() + "/chatplus_en_us", dontGenerateDCF); Game::chatFilter = new dChatFilter(Game::assetManager->GetResPath().string() + "/chatplus_en_us", dontGenerateDCF);
Game::randomEngine = std::mt19937(time(0)); Game::randomEngine = std::mt19937(time(0));

View File

@ -10,21 +10,14 @@
#include "Database.h" #include "Database.h"
#include "eConnectionType.h" #include "eConnectionType.h"
#include "eChatInternalMessageType.h" #include "eChatInternalMessageType.h"
#include "eGameMasterLevel.h"
#include "ChatPackets.h" #include "ChatPackets.h"
#include "dConfig.h" #include "dConfig.h"
void PlayerContainer::Initialize() { void PlayerContainer::Initialize() {
GeneralUtils::TryParse<uint32_t>(Game::config->GetValue("max_number_of_best_friends"), m_MaxNumberOfBestFriends); m_MaxNumberOfBestFriends =
GeneralUtils::TryParse<uint32_t>(Game::config->GetValue("max_number_of_friends"), m_MaxNumberOfFriends); GeneralUtils::TryParse<uint32_t>(Game::config->GetValue("max_number_of_best_friends")).value_or(m_MaxNumberOfBestFriends);
} m_MaxNumberOfFriends =
GeneralUtils::TryParse<uint32_t>(Game::config->GetValue("max_number_of_friends")).value_or(m_MaxNumberOfFriends);
PlayerContainer::~PlayerContainer() {
m_Players.clear();
}
PlayerData::PlayerData() {
gmLevel = eGameMasterLevel::CIVILIAN;
} }
TeamData::TeamData() { TeamData::TeamData() {

View File

@ -1,14 +1,13 @@
#pragma once #pragma once
#include <map> #include <map>
#include "dCommonVars.h" #include "dCommonVars.h"
#include "eGameMasterLevel.h"
#include "RakString.h" #include "RakString.h"
#include <vector> #include <vector>
#include "Game.h" #include "Game.h"
#include "dServer.h" #include "dServer.h"
#include <unordered_map> #include <unordered_map>
enum class eGameMasterLevel : uint8_t;
struct IgnoreData { struct IgnoreData {
IgnoreData(const std::string& name, const LWOOBJID& id) : playerName(name), playerId(id) {} IgnoreData(const std::string& name, const LWOOBJID& id) : playerName(name), playerId(id) {}
inline bool operator==(const std::string& other) const noexcept { inline bool operator==(const std::string& other) const noexcept {
@ -24,7 +23,6 @@ struct IgnoreData {
}; };
struct PlayerData { struct PlayerData {
PlayerData();
operator bool() const noexcept { operator bool() const noexcept {
return playerID != LWOOBJID_EMPTY; return playerID != LWOOBJID_EMPTY;
} }
@ -45,7 +43,7 @@ struct PlayerData {
std::string playerName; std::string playerName;
std::vector<FriendData> friends; std::vector<FriendData> friends;
std::vector<IgnoreData> ignoredPlayers; std::vector<IgnoreData> ignoredPlayers;
eGameMasterLevel gmLevel; eGameMasterLevel gmLevel = eGameMasterLevel::CIVILIAN;
bool isFTP = false; bool isFTP = false;
}; };
@ -61,8 +59,6 @@ struct TeamData {
class PlayerContainer { class PlayerContainer {
public: public:
~PlayerContainer();
void Initialize(); void Initialize();
void InsertPlayer(Packet* packet); void InsertPlayer(Packet* packet);
void RemovePlayer(Packet* packet); void RemovePlayer(Packet* packet);

View File

@ -319,7 +319,3 @@ std::vector<std::string> GeneralUtils::GetSqlFileNamesFromFolder(const std::stri
return sortedFiles; return sortedFiles;
} }
bool GeneralUtils::TryParse(const std::string& x, const std::string& y, const std::string& z, NiPoint3& dst) {
return TryParse<float>(x.c_str(), dst.x) && TryParse<float>(y.c_str(), dst.y) && TryParse<float>(z.c_str(), dst.z);
}

View File

@ -1,11 +1,13 @@
#pragma once #pragma once
// C++ // C++
#include <charconv>
#include <stdint.h> #include <stdint.h>
#include <random> #include <random>
#include <time.h> #include <time.h>
#include <string> #include <string>
#include <type_traits> #include <string_view>
#include <optional>
#include <functional> #include <functional>
#include <type_traits> #include <type_traits>
#include <stdexcept> #include <stdexcept>
@ -123,83 +125,105 @@ namespace GeneralUtils {
std::vector<std::string> GetSqlFileNamesFromFolder(const std::string& folder); std::vector<std::string> GetSqlFileNamesFromFolder(const std::string& folder);
// Concept constraining to enum types
template <typename T> template <typename T>
T Parse(const char* value); concept Enum = std::is_enum_v<T>;
template <> // Concept constraining to numeric types
inline bool Parse(const char* value) { template <typename T>
return std::stoi(value); concept Numeric = std::integral<T> || Enum<T> || std::floating_point<T>;
// Concept trickery to enable parsing underlying numeric types
template <Numeric T>
struct numeric_parse { using type = T; };
// If an enum, present an alias to its underlying type for parsing
template <Numeric T> requires Enum<T>
struct numeric_parse<T> { using type = std::underlying_type_t<T>; };
// If a boolean, present an alias to an integral type for parsing
template <Numeric T> requires std::same_as<T, bool>
struct numeric_parse<T> { using type = uint32_t; };
// Shorthand type alias
template <Numeric T>
using numeric_parse_t = numeric_parse<T>::type;
/**
* For numeric values: Parses a C-style char range (string) and returns an optional variable depending on the result
* @param str The pointer to the start of the char range (string)
* @param strEnd The pointer to the end of the char range (string), defaults to NULL
* @returns An std::optional containing the desired value if it exists in the string
*/
template <Numeric T>
[[nodiscard]] std::optional<T> TryParse(const char* const str, const char* const strEnd = NULL) {
numeric_parse_t<T> result;
const bool isParsed = std::from_chars(str, strEnd, result).ec == std::errc{};
return isParsed ? static_cast<T>(result) : std::optional<T>{};
} }
template <> /**
inline int32_t Parse(const char* value) { * For floating-point values: Parses a C-style char range (string) and returns an optional variable depending on the result
return std::stoi(value); * @param str The pointer to the start of the char range (string)
* @param strEnd The pointer to the end of the char range (string), defaults to NULL
* @returns An std::optional containing the desired value if it exists in the string
*/
/*template <std::floating_point T>
[[nodiscard]] std::optional<T> TryParse(const char* const str, const char* const strEnd = NULL) noexcept
try {
return std::make_optional<T>(std::stold(str));
} catch (...) {
return std::nullopt;
}*/
/**
* The TryParse overload for std::string
* @param str A constant reference to a std::string
* @returns An std::optional containing the desired value if it exists in the string
*/
template <typename T>
[[nodiscard]] std::optional<T> TryParse(const std::string& str) {
return TryParse<T>(str.data(), str.data() + str.size());
} }
template <> /**
inline int64_t Parse(const char* value) { * The TryParse overload for std::string_view
return std::stoll(value); * @param str A constant value std::string_view passed by copy
* @returns An std::optional containing the desired value if it exists in the string
*/
template <typename T>
[[nodiscard]] std::optional<T> TryParse(const std::string_view str) {
return TryParse<T>(str.data(), str.data() + str.size());
} }
template <> /**
inline float Parse(const char* value) { * The TryParse overload for handling NiPoint3 by passing 3 seperate string references
return std::stof(value); * @param strX The string representing the X coordinate
* @param strY The string representing the Y coordinate
* @param strZ The string representing the Z coordinate
* @returns An std::optional containing the desired NiPoint3 if it can be constructed from the string parameters
*/
template <typename T>
[[nodiscard]] std::optional<NiPoint3> TryParse(const std::string& strX, const std::string& strY, const std::string& strZ) {
const auto x = TryParse<float>(strX);
const auto y = TryParse<float>(strY);
const auto z = TryParse<float>(strZ);
return x && y && z ? std::make_optional<NiPoint3>(x.value(), y.value(), z.value()) : std::nullopt;
} }
template <> /**
inline double Parse(const char* value) { * The TryParse overload for handling NiPoint3 by passingn a reference to a vector of three strings
return std::stod(value); * @param str The string vector representing the X, Y, and Xcoordinates
} * @returns An std::optional containing the desired NiPoint3 if it can be constructed from the string parameters
*/
template <> template <typename T>
inline uint16_t Parse(const char* value) { [[nodiscard]] std::optional<NiPoint3> TryParse(const std::vector<std::string>& str) {
return std::stoul(value); return TryParse<NiPoint3>(str.at(0), str.at(1), str.at(2));
}
template <>
inline uint32_t Parse(const char* value) {
return std::stoul(value);
}
template <>
inline uint64_t Parse(const char* value) {
return std::stoull(value);
}
template <>
inline eInventoryType Parse(const char* value) {
return static_cast<eInventoryType>(std::stoul(value));
}
template <>
inline eReplicaComponentType Parse(const char* value) {
return static_cast<eReplicaComponentType>(std::stoul(value));
} }
template <typename T> template <typename T>
bool TryParse(const char* value, T& dst) {
try {
dst = Parse<T>(value);
return true;
} catch (...) {
return false;
}
}
template <typename T>
T Parse(const std::string& value) {
return Parse<T>(value.c_str());
}
template <typename T>
bool TryParse(const std::string& value, T& dst) {
return TryParse<T>(value.c_str(), dst);
}
bool TryParse(const std::string& x, const std::string& y, const std::string& z, NiPoint3& dst);
template<typename T>
std::u16string to_u16string(T value) { std::u16string to_u16string(T value) {
return GeneralUtils::ASCIIToUTF16(std::to_string(value)); return GeneralUtils::ASCIIToUTF16(std::to_string(value));
} }
@ -239,10 +263,8 @@ namespace GeneralUtils {
* @param entry Enum entry to cast * @param entry Enum entry to cast
* @returns The enum entry's value in its underlying type * @returns The enum entry's value in its underlying type
*/ */
template <typename eType> template <Enum eType>
inline constexpr typename std::underlying_type_t<eType> CastUnderlyingType(const eType entry) { constexpr typename std::underlying_type_t<eType> CastUnderlyingType(const eType entry) {
static_assert(std::is_enum_v<eType>, "Not an enum");
return static_cast<typename std::underlying_type_t<eType>>(entry); return static_cast<typename std::underlying_type_t<eType>>(entry);
} }

View File

@ -61,33 +61,33 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
} }
case LDF_TYPE_S32: { case LDF_TYPE_S32: {
int32_t data; const auto data = GeneralUtils::TryParse<int32_t>(ldfTypeAndValue.second);
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) { if (!data) {
LOG("Warning: Attempted to process invalid int32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data()); LOG("Warning: Attempted to process invalid int32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr; return nullptr;
} }
returnValue = new LDFData<int32_t>(key, data); returnValue = new LDFData<int32_t>(key, data.value());
break; break;
} }
case LDF_TYPE_FLOAT: { case LDF_TYPE_FLOAT: {
float data; const auto data = GeneralUtils::TryParse<float>(ldfTypeAndValue.second);
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) { if (!data) {
LOG("Warning: Attempted to process invalid float value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data()); LOG("Warning: Attempted to process invalid float value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr; return nullptr;
} }
returnValue = new LDFData<float>(key, data); returnValue = new LDFData<float>(key, data.value());
break; break;
} }
case LDF_TYPE_DOUBLE: { case LDF_TYPE_DOUBLE: {
double data; const auto data = GeneralUtils::TryParse<double>(ldfTypeAndValue.second);
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) { if (!data) {
LOG("Warning: Attempted to process invalid double value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data()); LOG("Warning: Attempted to process invalid double value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr; return nullptr;
} }
returnValue = new LDFData<double>(key, data); returnValue = new LDFData<double>(key, data.value());
break; break;
} }
@ -100,10 +100,12 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
} else if (ldfTypeAndValue.second == "false") { } else if (ldfTypeAndValue.second == "false") {
data = 0; data = 0;
} else { } else {
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) { const auto dataOptional = GeneralUtils::TryParse<uint32_t>(ldfTypeAndValue.second);
if (!dataOptional) {
LOG("Warning: Attempted to process invalid uint32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data()); LOG("Warning: Attempted to process invalid uint32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr; return nullptr;
} }
data = dataOptional.value();
} }
returnValue = new LDFData<uint32_t>(key, data); returnValue = new LDFData<uint32_t>(key, data);
@ -118,10 +120,12 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
} else if (ldfTypeAndValue.second == "false") { } else if (ldfTypeAndValue.second == "false") {
data = false; data = false;
} else { } else {
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) { const auto dataOptional = GeneralUtils::TryParse<bool>(ldfTypeAndValue.second);
if (!dataOptional) {
LOG("Warning: Attempted to process invalid bool value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data()); LOG("Warning: Attempted to process invalid bool value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr; return nullptr;
} }
data = dataOptional.value();
} }
returnValue = new LDFData<bool>(key, data); returnValue = new LDFData<bool>(key, data);
@ -129,22 +133,22 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
} }
case LDF_TYPE_U64: { case LDF_TYPE_U64: {
uint64_t data; const auto data = GeneralUtils::TryParse<uint64_t>(ldfTypeAndValue.second);
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) { if (!data) {
LOG("Warning: Attempted to process invalid uint64 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data()); LOG("Warning: Attempted to process invalid uint64 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr; return nullptr;
} }
returnValue = new LDFData<uint64_t>(key, data); returnValue = new LDFData<uint64_t>(key, data.value());
break; break;
} }
case LDF_TYPE_OBJID: { case LDF_TYPE_OBJID: {
LWOOBJID data; const auto data = GeneralUtils::TryParse<LWOOBJID>(ldfTypeAndValue.second);
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) { if (!data) {
LOG("Warning: Attempted to process invalid LWOOBJID value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data()); LOG("Warning: Attempted to process invalid LWOOBJID value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr; return nullptr;
} }
returnValue = new LDFData<LWOOBJID>(key, data); returnValue = new LDFData<LWOOBJID>(key, data.value());
break; break;
} }

View File

@ -162,7 +162,7 @@ public:
return new LDFData<T>(key, value); return new LDFData<T>(key, value);
} }
inline static T Default = {}; inline static const T Default = {};
}; };
// LDF Types // LDF Types

View File

@ -39,49 +39,49 @@ constexpr uint32_t lowFrameDelta = FRAMES_TO_MS(lowFramerate);
//=========== TYPEDEFS ========== //=========== TYPEDEFS ==========
typedef int32_t LOT; //!< A LOT using LOT = int32_t; //!< A LOT
typedef int64_t LWOOBJID; //!< An object ID (should be unsigned actually but ok) using LWOOBJID = int64_t; //!< An object ID (should be unsigned actually but ok)
typedef int32_t TSkillID; //!< A skill ID using TSkillID = int32_t; //!< A skill ID
typedef uint32_t LWOCLONEID; //!< Used for Clone IDs using LWOCLONEID = uint32_t; //!< Used for Clone IDs
typedef uint16_t LWOMAPID; //!< Used for Map IDs using LWOMAPID = uint16_t; //!< Used for Map IDs
typedef uint16_t LWOINSTANCEID; //!< Used for Instance IDs using LWOINSTANCEID = uint16_t; //!< Used for Instance IDs
typedef uint32_t PROPERTYCLONELIST; //!< Used for Property Clone IDs using PROPERTYCLONELIST = uint32_t; //!< Used for Property Clone IDs
typedef uint32_t StripId; using StripId = uint32_t;
const LWOOBJID LWOOBJID_EMPTY = 0; //!< An empty object ID constexpr LWOOBJID LWOOBJID_EMPTY = 0; //!< An empty object ID
const LOT LOT_NULL = -1; //!< A null LOT constexpr LOT LOT_NULL = -1; //!< A null LOT
const int32_t LOOTTYPE_NONE = 0; //!< No loot type available constexpr int32_t LOOTTYPE_NONE = 0; //!< No loot type available
const float SECONDARY_PRIORITY = 1.0f; //!< Secondary Priority constexpr float SECONDARY_PRIORITY = 1.0f; //!< Secondary Priority
const uint32_t INVENTORY_MAX = 9999999; //!< The Maximum Inventory Size constexpr uint32_t INVENTORY_MAX = 9999999; //!< The Maximum Inventory Size
const uint32_t LWOCLONEID_INVALID = -1; //!< Invalid LWOCLONEID constexpr LWOCLONEID LWOCLONEID_INVALID = -1; //!< Invalid LWOCLONEID
const uint16_t LWOINSTANCEID_INVALID = -1; //!< Invalid LWOINSTANCEID constexpr LWOINSTANCEID LWOINSTANCEID_INVALID = -1; //!< Invalid LWOINSTANCEID
const uint16_t LWOMAPID_INVALID = -1; //!< Invalid LWOMAPID constexpr LWOMAPID LWOMAPID_INVALID = -1; //!< Invalid LWOMAPID
const uint64_t LWOZONEID_INVALID = 0; //!< Invalid LWOZONEID constexpr uint64_t LWOZONEID_INVALID = 0; //!< Invalid LWOZONEID
const float PI = 3.14159f; constexpr float PI = 3.14159f;
//============ STRUCTS ============== //============ STRUCTS ==============
struct LWOSCENEID { struct LWOSCENEID {
public: public:
LWOSCENEID() { m_sceneID = -1; m_layerID = 0; } constexpr LWOSCENEID() noexcept { m_sceneID = -1; m_layerID = 0; }
LWOSCENEID(int sceneID) { m_sceneID = sceneID; m_layerID = 0; } constexpr LWOSCENEID(int sceneID) noexcept { m_sceneID = sceneID; m_layerID = 0; }
LWOSCENEID(int sceneID, unsigned int layerID) { m_sceneID = sceneID; m_layerID = layerID; } constexpr LWOSCENEID(int sceneID, unsigned int layerID) noexcept { m_sceneID = sceneID; m_layerID = layerID; }
LWOSCENEID& operator=(const LWOSCENEID& rhs) { m_sceneID = rhs.m_sceneID; m_layerID = rhs.m_layerID; return *this; } constexpr LWOSCENEID& operator=(const LWOSCENEID& rhs) noexcept { m_sceneID = rhs.m_sceneID; m_layerID = rhs.m_layerID; return *this; }
LWOSCENEID& operator=(const int rhs) { m_sceneID = rhs; m_layerID = 0; return *this; } constexpr LWOSCENEID& operator=(const int rhs) noexcept { m_sceneID = rhs; m_layerID = 0; return *this; }
bool operator<(const LWOSCENEID& rhs) const { return (m_sceneID < rhs.m_sceneID || (m_sceneID == rhs.m_sceneID && m_layerID < rhs.m_layerID)); } constexpr bool operator<(const LWOSCENEID& rhs) const noexcept { return (m_sceneID < rhs.m_sceneID || (m_sceneID == rhs.m_sceneID && m_layerID < rhs.m_layerID)); }
bool operator<(const int rhs) const { return m_sceneID < rhs; } constexpr bool operator<(const int rhs) const noexcept { return m_sceneID < rhs; }
bool operator==(const LWOSCENEID& rhs) const { return (m_sceneID == rhs.m_sceneID && m_layerID == rhs.m_layerID); } constexpr bool operator==(const LWOSCENEID& rhs) const noexcept { return (m_sceneID == rhs.m_sceneID && m_layerID == rhs.m_layerID); }
bool operator==(const int rhs) const { return m_sceneID == rhs; } constexpr bool operator==(const int rhs) const noexcept { return m_sceneID == rhs; }
const int GetSceneID() const { return m_sceneID; } constexpr int GetSceneID() const noexcept { return m_sceneID; }
const unsigned int GetLayerID() const { return m_layerID; } constexpr unsigned int GetLayerID() const noexcept { return m_layerID; }
void SetSceneID(const int sceneID) { m_sceneID = sceneID; } constexpr void SetSceneID(const int sceneID) noexcept { m_sceneID = sceneID; }
void SetLayerID(const unsigned int layerID) { m_layerID = layerID; } constexpr void SetLayerID(const unsigned int layerID) noexcept { m_layerID = layerID; }
private: private:
int m_sceneID; int m_sceneID;
@ -90,14 +90,14 @@ private:
struct LWOZONEID { struct LWOZONEID {
public: public:
const LWOMAPID& GetMapID() const { return m_MapID; } constexpr const LWOMAPID& GetMapID() const noexcept { return m_MapID; }
const LWOINSTANCEID& GetInstanceID() const { return m_InstanceID; } constexpr const LWOINSTANCEID& GetInstanceID() const noexcept { return m_InstanceID; }
const LWOCLONEID& GetCloneID() const { return m_CloneID; } constexpr const LWOCLONEID& GetCloneID() const noexcept { return m_CloneID; }
//In order: def constr, constr, assign op //In order: def constr, constr, assign op
LWOZONEID() { m_MapID = LWOMAPID_INVALID; m_InstanceID = LWOINSTANCEID_INVALID; m_CloneID = LWOCLONEID_INVALID; } constexpr LWOZONEID() noexcept { m_MapID = LWOMAPID_INVALID; m_InstanceID = LWOINSTANCEID_INVALID; m_CloneID = LWOCLONEID_INVALID; }
LWOZONEID(const LWOMAPID& mapID, const LWOINSTANCEID& instanceID, const LWOCLONEID& cloneID) { m_MapID = mapID; m_InstanceID = instanceID; m_CloneID = cloneID; } constexpr LWOZONEID(const LWOMAPID& mapID, const LWOINSTANCEID& instanceID, const LWOCLONEID& cloneID) noexcept { m_MapID = mapID; m_InstanceID = instanceID; m_CloneID = cloneID; }
LWOZONEID(const LWOZONEID& replacement) { *this = replacement; } constexpr LWOZONEID(const LWOZONEID& replacement) noexcept { *this = replacement; }
private: private:
LWOMAPID m_MapID; //1000 for VE, 1100 for AG, etc... LWOMAPID m_MapID; //1000 for VE, 1100 for AG, etc...
@ -105,20 +105,20 @@ private:
LWOCLONEID m_CloneID; //To differentiate between "your property" and "my property". Always 0 for non-prop worlds. LWOCLONEID m_CloneID; //To differentiate between "your property" and "my property". Always 0 for non-prop worlds.
}; };
const LWOSCENEID LWOSCENEID_INVALID = -1; constexpr LWOSCENEID LWOSCENEID_INVALID = -1;
struct LWONameValue { struct LWONameValue {
uint32_t length = 0; //!< The length of the name uint32_t length = 0; //!< The length of the name
std::u16string name; //!< The name std::u16string name; //!< The name
LWONameValue(void) {} LWONameValue() = default;
LWONameValue(const std::u16string& name) { LWONameValue(const std::u16string& name) {
this->name = name; this->name = name;
this->length = static_cast<uint32_t>(name.length()); this->length = static_cast<uint32_t>(name.length());
} }
~LWONameValue(void) {} ~LWONameValue() = default;
}; };
struct FriendData { struct FriendData {

View File

@ -419,10 +419,10 @@ void Entity::Initialize() {
if (!setFaction.empty()) { if (!setFaction.empty()) {
// TODO also split on space here however we do not have a general util for splitting on multiple characters yet. // TODO also split on space here however we do not have a general util for splitting on multiple characters yet.
std::vector<std::string> factionsToAdd = GeneralUtils::SplitString(setFaction, ';'); std::vector<std::string> factionsToAdd = GeneralUtils::SplitString(setFaction, ';');
int32_t factionToAdd;
for (const auto faction : factionsToAdd) { for (const auto faction : factionsToAdd) {
if (GeneralUtils::TryParse(faction, factionToAdd)) { const auto factionToAdd = GeneralUtils::TryParse<int32_t>(faction);
comp->AddFaction(factionToAdd, true); if (factionToAdd) {
comp->AddFaction(factionToAdd.value(), true);
} }
} }
} }

View File

@ -399,14 +399,8 @@ const T& Entity::GetVar(const std::u16string& name) const {
template<typename T> template<typename T>
T Entity::GetVarAs(const std::u16string& name) const { T Entity::GetVarAs(const std::u16string& name) const {
const auto data = GetVarAsString(name); const auto data = GetVarAsString(name);
T value; return GeneralUtils::TryParse<T>(data).value_or(LDFData<T>::Default);
if (!GeneralUtils::TryParse(data, value)) {
return LDFData<T>::Default;
}
return value;
} }
template<typename T> template<typename T>

View File

@ -84,7 +84,8 @@ void ActivityComponent::LoadActivityData(const int32_t activityId) {
if (m_ActivityInfo.instanceMapID == -1) { if (m_ActivityInfo.instanceMapID == -1) {
const auto& transferOverride = m_Parent->GetVarAsString(u"transferZoneID"); const auto& transferOverride = m_Parent->GetVarAsString(u"transferZoneID");
if (!transferOverride.empty()) { if (!transferOverride.empty()) {
GeneralUtils::TryParse(transferOverride, m_ActivityInfo.instanceMapID); m_ActivityInfo.instanceMapID =
GeneralUtils::TryParse<uint32_t>(transferOverride).value_or(m_ActivityInfo.instanceMapID);
} }
} }
} }

View File

@ -23,7 +23,7 @@
#include "CppScripts.h" #include "CppScripts.h"
QuickBuildComponent::QuickBuildComponent(Entity* entity) : Component(entity) { QuickBuildComponent::QuickBuildComponent(Entity* entity) : Component{ entity } {
std::u16string checkPreconditions = entity->GetVar<std::u16string>(u"CheckPrecondition"); std::u16string checkPreconditions = entity->GetVar<std::u16string>(u"CheckPrecondition");
if (!checkPreconditions.empty()) { if (!checkPreconditions.empty()) {
@ -33,10 +33,9 @@ QuickBuildComponent::QuickBuildComponent(Entity* entity) : Component(entity) {
// Should a setting that has the build activator position exist, fetch that setting here and parse it for position. // Should a setting that has the build activator position exist, fetch that setting here and parse it for position.
// It is assumed that the user who sets this setting uses the correct character delimiter (character 31 or in hex 0x1F) // It is assumed that the user who sets this setting uses the correct character delimiter (character 31 or in hex 0x1F)
auto positionAsVector = GeneralUtils::SplitString(m_Parent->GetVarAsString(u"rebuild_activators"), 0x1F); auto positionAsVector = GeneralUtils::SplitString(m_Parent->GetVarAsString(u"rebuild_activators"), 0x1F);
if (positionAsVector.size() == 3 && const auto activatorPositionValid = GeneralUtils::TryParse<NiPoint3>(positionAsVector);
GeneralUtils::TryParse(positionAsVector[0], m_ActivatorPosition.x) && if (positionAsVector.size() == 3 && activatorPositionValid) {
GeneralUtils::TryParse(positionAsVector[1], m_ActivatorPosition.y) && m_ActivatorPosition = activatorPositionValid.value();
GeneralUtils::TryParse(positionAsVector[2], m_ActivatorPosition.z)) {
} else { } else {
LOG("Failed to find activator position for lot %i. Defaulting to parents position.", m_Parent->GetLOT()); LOG("Failed to find activator position for lot %i. Defaulting to parents position.", m_Parent->GetLOT());
m_ActivatorPosition = m_Parent->GetPosition(); m_ActivatorPosition = m_Parent->GetPosition();
@ -284,51 +283,51 @@ void QuickBuildComponent::DespawnActivator() {
} }
} }
Entity* QuickBuildComponent::GetActivator() { Entity* QuickBuildComponent::GetActivator() const {
return Game::entityManager->GetEntity(m_ActivatorId); return Game::entityManager->GetEntity(m_ActivatorId);
} }
NiPoint3 QuickBuildComponent::GetActivatorPosition() { NiPoint3 QuickBuildComponent::GetActivatorPosition() const noexcept {
return m_ActivatorPosition; return m_ActivatorPosition;
} }
float QuickBuildComponent::GetResetTime() { float QuickBuildComponent::GetResetTime() const noexcept {
return m_ResetTime; return m_ResetTime;
} }
float QuickBuildComponent::GetCompleteTime() { float QuickBuildComponent::GetCompleteTime() const noexcept {
return m_CompleteTime; return m_CompleteTime;
} }
int QuickBuildComponent::GetTakeImagination() { int QuickBuildComponent::GetTakeImagination() const noexcept {
return m_TakeImagination; return m_TakeImagination;
} }
bool QuickBuildComponent::GetInterruptible() { bool QuickBuildComponent::GetInterruptible() const noexcept {
return m_Interruptible; return m_Interruptible;
} }
bool QuickBuildComponent::GetSelfActivator() { bool QuickBuildComponent::GetSelfActivator() const noexcept {
return m_SelfActivator; return m_SelfActivator;
} }
std::vector<int> QuickBuildComponent::GetCustomModules() { std::vector<int> QuickBuildComponent::GetCustomModules() const noexcept {
return m_CustomModules; return m_CustomModules;
} }
int QuickBuildComponent::GetActivityId() { int QuickBuildComponent::GetActivityId() const noexcept {
return m_ActivityId; return m_ActivityId;
} }
int QuickBuildComponent::GetPostImaginationCost() { int QuickBuildComponent::GetPostImaginationCost() const noexcept {
return m_PostImaginationCost; return m_PostImaginationCost;
} }
float QuickBuildComponent::GetTimeBeforeSmash() { float QuickBuildComponent::GetTimeBeforeSmash() const noexcept {
return m_TimeBeforeSmash; return m_TimeBeforeSmash;
} }
eQuickBuildState QuickBuildComponent::GetState() { eQuickBuildState QuickBuildComponent::GetState() const noexcept {
return m_State; return m_State;
} }
@ -338,19 +337,19 @@ Entity* QuickBuildComponent::GetBuilder() const {
return builder; return builder;
} }
bool QuickBuildComponent::GetRepositionPlayer() const { bool QuickBuildComponent::GetRepositionPlayer() const noexcept {
return m_RepositionPlayer; return m_RepositionPlayer;
} }
void QuickBuildComponent::SetActivatorPosition(NiPoint3 value) { void QuickBuildComponent::SetActivatorPosition(NiPoint3 value) noexcept {
m_ActivatorPosition = value; m_ActivatorPosition = value;
} }
void QuickBuildComponent::SetResetTime(float value) { void QuickBuildComponent::SetResetTime(float value) noexcept {
m_ResetTime = value; m_ResetTime = value;
} }
void QuickBuildComponent::SetCompleteTime(float value) { void QuickBuildComponent::SetCompleteTime(float value) noexcept {
if (value < 0) { if (value < 0) {
m_CompleteTime = 4.5f; m_CompleteTime = 4.5f;
} else { } else {
@ -358,31 +357,31 @@ void QuickBuildComponent::SetCompleteTime(float value) {
} }
} }
void QuickBuildComponent::SetTakeImagination(int value) { void QuickBuildComponent::SetTakeImagination(int value) noexcept {
m_TakeImagination = value; m_TakeImagination = value;
} }
void QuickBuildComponent::SetInterruptible(bool value) { void QuickBuildComponent::SetInterruptible(bool value) noexcept {
m_Interruptible = value; m_Interruptible = value;
} }
void QuickBuildComponent::SetSelfActivator(bool value) { void QuickBuildComponent::SetSelfActivator(bool value) noexcept {
m_SelfActivator = value; m_SelfActivator = value;
} }
void QuickBuildComponent::SetCustomModules(std::vector<int> value) { void QuickBuildComponent::SetCustomModules(std::vector<int> value) noexcept {
m_CustomModules = value; m_CustomModules = value;
} }
void QuickBuildComponent::SetActivityId(int value) { void QuickBuildComponent::SetActivityId(int value) noexcept {
m_ActivityId = value; m_ActivityId = value;
} }
void QuickBuildComponent::SetPostImaginationCost(int value) { void QuickBuildComponent::SetPostImaginationCost(int value) noexcept {
m_PostImaginationCost = value; m_PostImaginationCost = value;
} }
void QuickBuildComponent::SetTimeBeforeSmash(float value) { void QuickBuildComponent::SetTimeBeforeSmash(float value) noexcept {
if (value < 0) { if (value < 0) {
m_TimeBeforeSmash = 10.0f; m_TimeBeforeSmash = 10.0f;
} else { } else {
@ -390,7 +389,7 @@ void QuickBuildComponent::SetTimeBeforeSmash(float value) {
} }
} }
void QuickBuildComponent::SetRepositionPlayer(bool value) { void QuickBuildComponent::SetRepositionPlayer(bool value) noexcept {
m_RepositionPlayer = value; m_RepositionPlayer = value;
} }

View File

@ -50,148 +50,148 @@ public:
* Returns the entity that acts as the activator for this quickbuild * Returns the entity that acts as the activator for this quickbuild
* @return the entity that acts as the activator for this quickbuild * @return the entity that acts as the activator for this quickbuild
*/ */
Entity* GetActivator(); [[nodiscard]] Entity* GetActivator() const;
/** /**
* Returns the spawn position of the activator for this quickbuild, if any * Returns the spawn position of the activator for this quickbuild, if any
* @return the spawn position of the activator for this quickbuild, if any * @return the spawn position of the activator for this quickbuild, if any
*/ */
NiPoint3 GetActivatorPosition(); [[nodiscard]] NiPoint3 GetActivatorPosition() const noexcept;
/** /**
* Sets the spawn position for the activator of this quickbuild * Sets the spawn position for the activator of this quickbuild
* @param value the spawn position to set for the activator * @param value the spawn position to set for the activator
*/ */
void SetActivatorPosition(NiPoint3 value); void SetActivatorPosition(NiPoint3 value) noexcept;
/** /**
* Returns the time it takes for the quickbuild to reset after being built * Returns the time it takes for the quickbuild to reset after being built
* @return the time it takes for the quickbuild to reset after being built * @return the time it takes for the quickbuild to reset after being built
*/ */
float GetResetTime(); [[nodiscard]] float GetResetTime() const noexcept;
/** /**
* Sets the time it takes for the quickbuild to reset after being built * Sets the time it takes for the quickbuild to reset after being built
* @param value the reset time to set * @param value the reset time to set
*/ */
void SetResetTime(float value); void SetResetTime(float value) noexcept;
/** /**
* Returns the time it takes to complete the quickbuild * Returns the time it takes to complete the quickbuild
* @return the time it takes to complete the quickbuild * @return the time it takes to complete the quickbuild
*/ */
float GetCompleteTime(); [[nodiscard]] float GetCompleteTime() const noexcept;
/** /**
* Sets the time it takes to complete the quickbuild * Sets the time it takes to complete the quickbuild
* @param value the completion time to set * @param value the completion time to set
*/ */
void SetCompleteTime(float value); void SetCompleteTime(float value) noexcept;
/** /**
* Returns the imagination that's taken when completing the quickbuild * Returns the imagination that's taken when completing the quickbuild
* @return the imagination that's taken when completing the quickbuild * @return the imagination that's taken when completing the quickbuild
*/ */
int GetTakeImagination(); [[nodiscard]] int GetTakeImagination() const noexcept;
/** /**
* Sets the imagination that's taken when completing the quickbuild * Sets the imagination that's taken when completing the quickbuild
* @param value the imagination deduction to set * @param value the imagination deduction to set
*/ */
void SetTakeImagination(int value); void SetTakeImagination(int value) noexcept;
/** /**
* Returns if the quickbuild can be interrupted, currently unused * Returns if the quickbuild can be interrupted, currently unused
* @return if the quickbuild can be interrupted * @return if the quickbuild can be interrupted
*/ */
bool GetInterruptible(); [[nodiscard]] bool GetInterruptible() const noexcept;
/** /**
* Sets whether or not the quickbuild can be interrupted, currently unused * Sets whether or not the quickbuild can be interrupted, currently unused
* @param value true if the quickbuild may be interrupted, false otherwise * @param value true if the quickbuild may be interrupted, false otherwise
*/ */
void SetInterruptible(bool value); void SetInterruptible(bool value) noexcept;
/** /**
* Returns whether or not this entity contains a built-in activator * Returns whether or not this entity contains a built-in activator
* @return whether or not this entity contains a built-in activator * @return whether or not this entity contains a built-in activator
*/ */
bool GetSelfActivator(); [[nodiscard]] bool GetSelfActivator() const noexcept;
/** /**
* Sets whether or not this entity contains a built-in activator. If set to false this will spawn activators on * Sets whether or not this entity contains a built-in activator. If set to false this will spawn activators on
* each new quickbuild. * each new quickbuild.
* @param value whether or not this entity contains a built-in activator * @param value whether or not this entity contains a built-in activator
*/ */
void SetSelfActivator(bool value); void SetSelfActivator(bool value) noexcept;
/** /**
* Currently unused * Currently unused
*/ */
std::vector<int> GetCustomModules(); [[nodiscard]] std::vector<int> GetCustomModules() const noexcept;
/** /**
* Currently unused * Currently unused
*/ */
void SetCustomModules(std::vector<int> value); void SetCustomModules(std::vector<int> value) noexcept;
/** /**
* Returns the activity ID for participating in this quickbuild * Returns the activity ID for participating in this quickbuild
* @return the activity ID for participating in this quickbuild * @return the activity ID for participating in this quickbuild
*/ */
int GetActivityId(); [[nodiscard]] int GetActivityId() const noexcept;
/** /**
* Sets the activity ID for participating in this quickbuild * Sets the activity ID for participating in this quickbuild
* @param value the activity ID to set * @param value the activity ID to set
*/ */
void SetActivityId(int value); void SetActivityId(int value) noexcept;
/** /**
* Currently unused * Currently unused
*/ */
int GetPostImaginationCost(); [[nodiscard]] int GetPostImaginationCost() const noexcept;
/** /**
* Currently unused * Currently unused
*/ */
void SetPostImaginationCost(int value); void SetPostImaginationCost(int value) noexcept;
/** /**
* Returns the time it takes for an incomplete quickbuild to be smashed automatically * Returns the time it takes for an incomplete quickbuild to be smashed automatically
* @return the time it takes for an incomplete quickbuild to be smashed automatically * @return the time it takes for an incomplete quickbuild to be smashed automatically
*/ */
float GetTimeBeforeSmash(); [[nodiscard]] float GetTimeBeforeSmash() const noexcept;
/** /**
* Sets the time it takes for an incomplete quickbuild to be smashed automatically * Sets the time it takes for an incomplete quickbuild to be smashed automatically
* @param value the time to set * @param value the time to set
*/ */
void SetTimeBeforeSmash(float value); void SetTimeBeforeSmash(float value) noexcept;
/** /**
* Returns the current quickbuild state * Returns the current quickbuild state
* @return the current quickbuild state * @return the current quickbuild state
*/ */
eQuickBuildState GetState(); [[nodiscard]] eQuickBuildState GetState() const noexcept;
/** /**
* Returns the player that is currently building this quickbuild * Returns the player that is currently building this quickbuild
* @return the player that is currently building this quickbuild * @return the player that is currently building this quickbuild
*/ */
Entity* GetBuilder() const; [[nodiscard]] Entity* GetBuilder() const;
/** /**
* Returns whether or not the player is repositioned when initiating the quickbuild * Returns whether or not the player is repositioned when initiating the quickbuild
* @return whether or not the player is repositioned when initiating the quickbuild * @return whether or not the player is repositioned when initiating the quickbuild
*/ */
bool GetRepositionPlayer() const; [[nodiscard]] bool GetRepositionPlayer() const noexcept;
/** /**
* Sets whether or not the player is repositioned when initiating the quickbuild * Sets whether or not the player is repositioned when initiating the quickbuild
* @param value whether or not the player is repositioned when initiating the quickbuild * @param value whether or not the player is repositioned when initiating the quickbuild
*/ */
void SetRepositionPlayer(bool value); void SetRepositionPlayer(bool value) noexcept;
/** /**
* Adds a callback that is called when the quickbuild is completed * Adds a callback that is called when the quickbuild is completed

View File

@ -29,13 +29,15 @@ RenderComponent::RenderComponent(Entity* parent, int32_t componentId): Component
auto* animationsTable = CDClientManager::Instance().GetTable<CDAnimationsTable>(); auto* animationsTable = CDClientManager::Instance().GetTable<CDAnimationsTable>();
auto groupIdsSplit = GeneralUtils::SplitString(animationGroupIDs, ','); auto groupIdsSplit = GeneralUtils::SplitString(animationGroupIDs, ',');
for (auto& groupId : groupIdsSplit) { for (auto& groupId : groupIdsSplit) {
int32_t groupIdInt; const auto groupIdInt = GeneralUtils::TryParse<int32_t>(groupId);
if (!GeneralUtils::TryParse(groupId, groupIdInt)) {
if (!groupIdInt) {
LOG("bad animation group Id %s", groupId.c_str()); LOG("bad animation group Id %s", groupId.c_str());
continue; continue;
} }
m_animationGroupIds.push_back(groupIdInt);
animationsTable->CacheAnimationGroup(groupIdInt); m_animationGroupIds.push_back(groupIdInt.value());
animationsTable->CacheAnimationGroup(groupIdInt.value());
} }
} }
} }

View File

@ -22,10 +22,8 @@ TriggerComponent::TriggerComponent(Entity* parent, const std::string triggerInfo
std::vector<std::string> tokens = GeneralUtils::SplitString(triggerInfo, ':'); std::vector<std::string> tokens = GeneralUtils::SplitString(triggerInfo, ':');
uint32_t sceneID; const auto sceneID = GeneralUtils::TryParse<uint32_t>(tokens.at(0)).value();
GeneralUtils::TryParse<uint32_t>(tokens.at(0), sceneID); const auto triggerID = GeneralUtils::TryParse<uint32_t>(tokens.at(1)).value();
uint32_t triggerID;
GeneralUtils::TryParse<uint32_t>(tokens.at(1), triggerID);
m_Trigger = Game::zoneManager->GetZone()->GetTrigger(sceneID, triggerID); m_Trigger = Game::zoneManager->GetZone()->GetTrigger(sceneID, triggerID);
@ -191,9 +189,8 @@ void TriggerComponent::HandleFireEvent(Entity* targetEntity, std::string args) {
} }
void TriggerComponent::HandleDestroyObject(Entity* targetEntity, std::string args){ void TriggerComponent::HandleDestroyObject(Entity* targetEntity, std::string args){
uint32_t killType; const eKillType killType = GeneralUtils::TryParse<eKillType>(args).value_or(eKillType::SILENT);
GeneralUtils::TryParse<uint32_t>(args, killType); targetEntity->Smash(m_Parent->GetObjectID(), killType);
targetEntity->Smash(m_Parent->GetObjectID(), static_cast<eKillType>(killType));
} }
void TriggerComponent::HandleToggleTrigger(Entity* targetEntity, std::string args){ void TriggerComponent::HandleToggleTrigger(Entity* targetEntity, std::string args){
@ -217,9 +214,8 @@ void TriggerComponent::HandleResetRebuild(Entity* targetEntity, std::string args
void TriggerComponent::HandleMoveObject(Entity* targetEntity, std::vector<std::string> argArray){ void TriggerComponent::HandleMoveObject(Entity* targetEntity, std::vector<std::string> argArray){
if (argArray.size() <= 2) return; if (argArray.size() <= 2) return;
auto position = targetEntity->GetPosition(); NiPoint3 position = targetEntity->GetPosition();
NiPoint3 offset = NiPoint3Constant::ZERO; const NiPoint3 offset = GeneralUtils::TryParse<NiPoint3>(argArray).value_or(NiPoint3Constant::ZERO);
GeneralUtils::TryParse(argArray.at(0), argArray.at(1), argArray.at(2), offset);
position += offset; position += offset;
targetEntity->SetPosition(position); targetEntity->SetPosition(position);
@ -228,8 +224,7 @@ void TriggerComponent::HandleMoveObject(Entity* targetEntity, std::vector<std::s
void TriggerComponent::HandleRotateObject(Entity* targetEntity, std::vector<std::string> argArray){ void TriggerComponent::HandleRotateObject(Entity* targetEntity, std::vector<std::string> argArray){
if (argArray.size() <= 2) return; if (argArray.size() <= 2) return;
NiPoint3 vector = NiPoint3Constant::ZERO; const NiPoint3 vector = GeneralUtils::TryParse<NiPoint3>(argArray).value_or(NiPoint3Constant::ZERO);
GeneralUtils::TryParse(argArray.at(0), argArray.at(1), argArray.at(2), vector);
NiQuaternion rotation = NiQuaternion::FromEulerAngles(vector); NiQuaternion rotation = NiQuaternion::FromEulerAngles(vector);
targetEntity->SetRotation(rotation); targetEntity->SetRotation(rotation);
@ -246,8 +241,7 @@ void TriggerComponent::HandlePushObject(Entity* targetEntity, std::vector<std::s
phantomPhysicsComponent->SetPhysicsEffectActive(true); phantomPhysicsComponent->SetPhysicsEffectActive(true);
phantomPhysicsComponent->SetEffectType(ePhysicsEffectType::PUSH); phantomPhysicsComponent->SetEffectType(ePhysicsEffectType::PUSH);
phantomPhysicsComponent->SetDirectionalMultiplier(1); phantomPhysicsComponent->SetDirectionalMultiplier(1);
NiPoint3 direction = NiPoint3Constant::ZERO; const NiPoint3 direction = GeneralUtils::TryParse<NiPoint3>(argArray).value_or(NiPoint3Constant::ZERO);
GeneralUtils::TryParse(argArray.at(0), argArray.at(1), argArray.at(2), direction);
phantomPhysicsComponent->SetDirection(direction); phantomPhysicsComponent->SetDirection(direction);
Game::entityManager->SerializeEntity(m_Parent); Game::entityManager->SerializeEntity(m_Parent);
@ -260,8 +254,8 @@ void TriggerComponent::HandleRepelObject(Entity* targetEntity, std::string args)
LOG_DEBUG("Phantom Physics component not found!"); LOG_DEBUG("Phantom Physics component not found!");
return; return;
} }
float forceMultiplier; const float forceMultiplier = GeneralUtils::TryParse<float>(args).value();
GeneralUtils::TryParse<float>(args, forceMultiplier);
phantomPhysicsComponent->SetPhysicsEffectActive(true); phantomPhysicsComponent->SetPhysicsEffectActive(true);
phantomPhysicsComponent->SetEffectType(ePhysicsEffectType::REPULSE); phantomPhysicsComponent->SetEffectType(ePhysicsEffectType::REPULSE);
phantomPhysicsComponent->SetDirectionalMultiplier(forceMultiplier); phantomPhysicsComponent->SetDirectionalMultiplier(forceMultiplier);
@ -280,11 +274,10 @@ void TriggerComponent::HandleRepelObject(Entity* targetEntity, std::string args)
void TriggerComponent::HandleSetTimer(Entity* targetEntity, std::vector<std::string> argArray){ void TriggerComponent::HandleSetTimer(Entity* targetEntity, std::vector<std::string> argArray){
if (argArray.size() != 2) { if (argArray.size() != 2) {
LOG_DEBUG("Not ehought variables!"); LOG_DEBUG("Not enough variables!");
return; return;
} }
float time = 0.0; const float time = GeneralUtils::TryParse<float>(argArray.at(1)).value_or(0.0f);
GeneralUtils::TryParse<float>(argArray.at(1), time);
m_Parent->AddTimer(argArray.at(0), time); m_Parent->AddTimer(argArray.at(0), time);
} }
@ -300,7 +293,7 @@ void TriggerComponent::HandlePlayCinematic(Entity* targetEntity, std::vector<std
bool hidePlayer = false; bool hidePlayer = false;
if (argArray.size() >= 2) { if (argArray.size() >= 2) {
GeneralUtils::TryParse<float>(argArray.at(1), leadIn); leadIn = GeneralUtils::TryParse<float>(argArray.at(1)).value_or(leadIn);
if (argArray.size() >= 3 && argArray.at(2) == "wait") { if (argArray.size() >= 3 && argArray.at(2) == "wait") {
wait = eEndBehavior::WAIT; wait = eEndBehavior::WAIT;
if (argArray.size() >= 4 && argArray.at(3) == "unlock") { if (argArray.size() >= 4 && argArray.at(3) == "unlock") {
@ -345,12 +338,16 @@ void TriggerComponent::HandleUpdateMission(Entity* targetEntity, std::vector<std
void TriggerComponent::HandlePlayEffect(Entity* targetEntity, std::vector<std::string> argArray) { void TriggerComponent::HandlePlayEffect(Entity* targetEntity, std::vector<std::string> argArray) {
if (argArray.size() < 3) return; if (argArray.size() < 3) return;
int32_t effectID = 0; const auto effectID = GeneralUtils::TryParse<int32_t>(argArray.at(1));
if (!GeneralUtils::TryParse<int32_t>(argArray.at(1), effectID)) return; if (!effectID) return;
std::u16string effectType = GeneralUtils::UTF8ToUTF16(argArray.at(2)); std::u16string effectType = GeneralUtils::UTF8ToUTF16(argArray.at(2));
float priority = 1; float priority = 1;
if (argArray.size() == 4) GeneralUtils::TryParse<float>(argArray.at(3), priority); if (argArray.size() == 4) {
GameMessages::SendPlayFXEffect(targetEntity, effectID, effectType, argArray.at(0), LWOOBJID_EMPTY, priority); priority = GeneralUtils::TryParse<float>(argArray.at(3)).value_or(priority);
}
GameMessages::SendPlayFXEffect(targetEntity, effectID.value(), effectType, argArray.at(0), LWOOBJID_EMPTY, priority);
} }
void TriggerComponent::HandleCastSkill(Entity* targetEntity, std::string args){ void TriggerComponent::HandleCastSkill(Entity* targetEntity, std::string args){
@ -359,8 +356,7 @@ void TriggerComponent::HandleCastSkill(Entity* targetEntity, std::string args){
LOG_DEBUG("Skill component not found!"); LOG_DEBUG("Skill component not found!");
return; return;
} }
uint32_t skillId; const uint32_t skillId = GeneralUtils::TryParse<uint32_t>(args).value();
GeneralUtils::TryParse<uint32_t>(args, skillId);
skillComponent->CastSkill(skillId, targetEntity->GetObjectID()); skillComponent->CastSkill(skillId, targetEntity->GetObjectID());
} }
@ -382,17 +378,16 @@ void TriggerComponent::HandleSetPhysicsVolumeEffect(Entity* targetEntity, std::v
phantomPhysicsComponent->SetEffectType(effectType); phantomPhysicsComponent->SetEffectType(effectType);
phantomPhysicsComponent->SetDirectionalMultiplier(std::stof(argArray.at(1))); phantomPhysicsComponent->SetDirectionalMultiplier(std::stof(argArray.at(1)));
if (argArray.size() > 4) { if (argArray.size() > 4) {
NiPoint3 direction = NiPoint3Constant::ZERO; const NiPoint3 direction =
GeneralUtils::TryParse(argArray.at(2), argArray.at(3), argArray.at(4), direction); GeneralUtils::TryParse<NiPoint3>(argArray.at(2), argArray.at(3), argArray.at(4)).value_or(NiPoint3Constant::ZERO);
phantomPhysicsComponent->SetDirection(direction); phantomPhysicsComponent->SetDirection(direction);
} }
if (argArray.size() > 5) { if (argArray.size() > 5) {
uint32_t min; const uint32_t min = GeneralUtils::TryParse<uint32_t>(argArray.at(6)).value_or(0);
GeneralUtils::TryParse<uint32_t>(argArray.at(6), min);
phantomPhysicsComponent->SetMin(min); phantomPhysicsComponent->SetMin(min);
uint32_t max; const uint32_t max = GeneralUtils::TryParse<uint32_t>(argArray.at(7)).value_or(0);
GeneralUtils::TryParse<uint32_t>(argArray.at(7), max);
phantomPhysicsComponent->SetMax(max); phantomPhysicsComponent->SetMax(max);
} }

View File

@ -468,14 +468,14 @@ void Item::DisassembleModel(uint32_t numToDismantle) {
// First iteration gets the count // First iteration gets the count
std::map<int32_t, int32_t> parts; std::map<int32_t, int32_t> parts;
while (currentBrick) { while (currentBrick) {
auto* designID = currentBrick->Attribute("designID"); const char* const designID = currentBrick->Attribute("designID");
if (designID) { if (designID) {
uint32_t designId; const auto designId = GeneralUtils::TryParse<uint32_t>(designID);
if (!GeneralUtils::TryParse(designID, designId)) { if (!designId) {
LOG("Failed to parse designID %s", designID); LOG("Failed to parse designID %s", designID);
continue; continue;
} }
parts[designId]++; parts[designId.value()]++;
} }
currentBrick = currentBrick->NextSiblingElement(searchTerm.c_str()); currentBrick = currentBrick->NextSiblingElement(searchTerm.c_str());

View File

@ -87,10 +87,8 @@ ItemSet::ItemSet(const uint32_t id, InventoryComponent* inventoryComponent) {
m_Items = {}; m_Items = {};
while (std::getline(stream, token, ',')) { while (std::getline(stream, token, ',')) {
int32_t value; const auto validToken = GeneralUtils::TryParse<int32_t>(token);
if (GeneralUtils::TryParse(token, value)) { if (validToken) m_Items.push_back(validToken.value());
m_Items.push_back(value);
}
} }
m_Equipped = {}; m_Equipped = {};

View File

@ -27,19 +27,15 @@ MissionTask::MissionTask(Mission* mission, CDMissionTasks* info, uint32_t mask)
std::string token; std::string token;
while (std::getline(stream, token, ',')) { while (std::getline(stream, token, ',')) {
uint32_t parameter; const auto parameter = GeneralUtils::TryParse<uint32_t>(token);
if (GeneralUtils::TryParse(token, parameter)) { if (parameter) parameters.push_back(parameter.value());
parameters.push_back(parameter);
}
} }
stream = std::istringstream(info->targetGroup); stream = std::istringstream(info->targetGroup);
while (std::getline(stream, token, ',')) { while (std::getline(stream, token, ',')) {
uint32_t parameter; const auto parameter = GeneralUtils::TryParse<uint32_t>(token);
if (GeneralUtils::TryParse(token, parameter)) { if (parameter) targets.push_back(parameter.value());
targets.push_back(parameter);
}
} }
} }

View File

@ -5,7 +5,7 @@
#include "dCommonVars.h" #include "dCommonVars.h"
BehaviorMessageBase::BehaviorMessageBase(AMFArrayValue* arguments) { BehaviorMessageBase::BehaviorMessageBase(AMFArrayValue* arguments) {
behaviorId = GetBehaviorIdFromArgument(arguments); this->behaviorId = GetBehaviorIdFromArgument(arguments);
} }
int32_t BehaviorMessageBase::GetBehaviorIdFromArgument(AMFArrayValue* arguments) { int32_t BehaviorMessageBase::GetBehaviorIdFromArgument(AMFArrayValue* arguments) {
@ -13,12 +13,13 @@ int32_t BehaviorMessageBase::GetBehaviorIdFromArgument(AMFArrayValue* arguments)
auto* behaviorIDValue = arguments->Get<std::string>(key); auto* behaviorIDValue = arguments->Get<std::string>(key);
if (behaviorIDValue && behaviorIDValue->GetValueType() == eAmf::String) { if (behaviorIDValue && behaviorIDValue->GetValueType() == eAmf::String) {
GeneralUtils::TryParse(behaviorIDValue->GetValue(), behaviorId); this->behaviorId =
GeneralUtils::TryParse<int32_t>(behaviorIDValue->GetValue()).value_or(this->behaviorId);
} else if (arguments->Get(key) && arguments->Get(key)->GetValueType() != eAmf::Undefined) { } else if (arguments->Get(key) && arguments->Get(key)->GetValueType() != eAmf::Undefined) {
throw std::invalid_argument("Unable to find behavior ID"); throw std::invalid_argument("Unable to find behavior ID");
} }
return behaviorId; return this->behaviorId;
} }
int32_t BehaviorMessageBase::GetActionIndexFromArgument(AMFArrayValue* arguments, const std::string& keyName) { int32_t BehaviorMessageBase::GetActionIndexFromArgument(AMFArrayValue* arguments, const std::string& keyName) {

View File

@ -40,10 +40,8 @@ Precondition::Precondition(const uint32_t condition) {
std::string token; std::string token;
while (std::getline(stream, token, ',')) { while (std::getline(stream, token, ',')) {
uint32_t value; const auto validToken = GeneralUtils::TryParse<uint32_t>(token);
if (GeneralUtils::TryParse(token, value)) { if (validToken) this->values.push_back(validToken.value());
this->values.push_back(value);
}
} }
} }

View File

@ -114,13 +114,13 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
if ((chatCommand == "setgmlevel" || chatCommand == "makegm" || chatCommand == "gmlevel") && user->GetMaxGMLevel() > eGameMasterLevel::CIVILIAN) { if ((chatCommand == "setgmlevel" || chatCommand == "makegm" || chatCommand == "gmlevel") && user->GetMaxGMLevel() > eGameMasterLevel::CIVILIAN) {
if (args.size() != 1) return; if (args.size() != 1) return;
uint32_t level_intermed = 0; const auto level_intermed = GeneralUtils::TryParse<uint32_t>(args[0]);
if (!GeneralUtils::TryParse(args[0], level_intermed)) { if (!level_intermed) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid gm level."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid gm level.");
return; return;
} }
eGameMasterLevel level = static_cast<eGameMasterLevel>(level_intermed); eGameMasterLevel level = static_cast<eGameMasterLevel>(level_intermed.value());
#ifndef DEVELOPER_SERVER #ifndef DEVELOPER_SERVER
if (user->GetMaxGMLevel() == eGameMasterLevel::JUNIOR_DEVELOPER) { if (user->GetMaxGMLevel() == eGameMasterLevel::JUNIOR_DEVELOPER) {
@ -379,26 +379,27 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
} }
if (chatCommand == "resetmission" && args.size() >= 1 && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) { if (chatCommand == "resetmission" && args.size() >= 1 && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) {
uint32_t missionId; const auto missionId = GeneralUtils::TryParse<uint32_t>(args[0]);
if (!GeneralUtils::TryParse(args[0], missionId)) { if (!missionId) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid mission ID."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid mission ID.");
return; return;
} }
auto* missionComponent = entity->GetComponent<MissionComponent>(); auto* missionComponent = entity->GetComponent<MissionComponent>();
if (!missionComponent) return; if (!missionComponent) return;
missionComponent->ResetMission(missionId); missionComponent->ResetMission(missionId.value());
} }
// Log command to database // Log command to database
Database::Get()->InsertSlashCommandUsage(entity->GetObjectID(), chatCommand); Database::Get()->InsertSlashCommandUsage(entity->GetObjectID(), chatCommand);
if (chatCommand == "setminifig" && args.size() == 2 && entity->GetGMLevel() >= eGameMasterLevel::FORUM_MODERATOR) { // could break characters so only allow if GM > 0 if (chatCommand == "setminifig" && args.size() == 2 && entity->GetGMLevel() >= eGameMasterLevel::FORUM_MODERATOR) { // could break characters so only allow if GM > 0
int32_t minifigItemId; const auto minifigItemIdExists = GeneralUtils::TryParse<int32_t>(args[1]);
if (!GeneralUtils::TryParse(args[1], minifigItemId)) { if (!minifigItemIdExists) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid Minifig Item Id ID."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid Minifig Item Id ID.");
return; return;
} }
const int32_t minifigItemId = minifigItemIdExists.value();
Game::entityManager->DestructEntity(entity, sysAddr); Game::entityManager->DestructEntity(entity, sysAddr);
auto* charComp = entity->GetComponent<CharacterComponent>(); auto* charComp = entity->GetComponent<CharacterComponent>();
std::string lowerName = args[0]; std::string lowerName = args[0];
@ -458,14 +459,14 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
} }
if (chatCommand == "unlock-emote" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) { if (chatCommand == "unlock-emote" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) {
int32_t emoteID; const auto emoteID = GeneralUtils::TryParse<int32_t>(args.at(0));
if (!GeneralUtils::TryParse(args[0], emoteID)) { if (!emoteID) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid emote ID."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid emote ID.");
return; return;
} }
entity->GetCharacter()->UnlockEmote(emoteID); entity->GetCharacter()->UnlockEmote(emoteID.value());
} }
if (chatCommand == "force-save" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) { if (chatCommand == "force-save" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) {
@ -487,19 +488,19 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
} }
if (chatCommand == "speedboost" && args.size() == 1 && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) { if (chatCommand == "speedboost" && args.size() == 1 && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) {
float boost; const auto boostOptional = GeneralUtils::TryParse<float>(args[0]);
if (!boostOptional) {
if (!GeneralUtils::TryParse(args[0], boost)) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid boost."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid boost.");
return; return;
} }
const float boost = boostOptional.value();
auto* controllablePhysicsComponent = entity->GetComponent<ControllablePhysicsComponent>(); auto* controllablePhysicsComponent = entity->GetComponent<ControllablePhysicsComponent>();
if (!controllablePhysicsComponent) return; if (!controllablePhysicsComponent) return;
controllablePhysicsComponent->SetSpeedMultiplier(boost); controllablePhysicsComponent->SetSpeedMultiplier(boost);
// speedboost possesables // speedboost possessables
auto possessor = entity->GetComponent<PossessorComponent>(); auto possessor = entity->GetComponent<PossessorComponent>();
if (possessor) { if (possessor) {
auto possessedID = possessor->GetPossessable(); auto possessedID = possessor->GetPossessable();
@ -528,14 +529,14 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
} }
if (chatCommand == "setcontrolscheme" && args.size() == 1 && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) { if (chatCommand == "setcontrolscheme" && args.size() == 1 && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) {
uint32_t scheme; const auto scheme = GeneralUtils::TryParse<uint32_t>(args[0]);
if (!GeneralUtils::TryParse(args[0], scheme)) { if (!scheme) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid control scheme."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid control scheme.");
return; return;
} }
GameMessages::SendSetPlayerControlScheme(entity, static_cast<eControlScheme>(scheme)); GameMessages::SendSetPlayerControlScheme(entity, static_cast<eControlScheme>(scheme.value()));
ChatPackets::SendSystemMessage(sysAddr, u"Switched control scheme."); ChatPackets::SendSystemMessage(sysAddr, u"Switched control scheme.");
return; return;
@ -575,29 +576,28 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
} }
if ((chatCommand == "setinventorysize" || chatCommand == "setinvsize") && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() >= 1) { if ((chatCommand == "setinventorysize" || chatCommand == "setinvsize") && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() >= 1) {
uint32_t size; const auto sizeOptional = GeneralUtils::TryParse<uint32_t>(args[0]);
if (!sizeOptional) {
if (!GeneralUtils::TryParse(args.at(0), size)) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid size."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid size.");
return; return;
} }
const uint32_t size = sizeOptional.value();
eInventoryType selectedInventory = eInventoryType::ITEMS; eInventoryType selectedInventory = eInventoryType::ITEMS;
// a possible inventory was provided if we got more than 1 argument // a possible inventory was provided if we got more than 1 argument
if (args.size() >= 2) { if (args.size() >= 2) {
selectedInventory = eInventoryType::INVALID; selectedInventory = GeneralUtils::TryParse<eInventoryType>(args.at(1)).value_or(eInventoryType::INVALID);
if (!GeneralUtils::TryParse(args.at(1), selectedInventory)) { if (selectedInventory == eInventoryType::INVALID) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid inventory.");
return;
} else {
// In this case, we treat the input as a string and try to find it in the reflection list // In this case, we treat the input as a string and try to find it in the reflection list
std::transform(args.at(1).begin(), args.at(1).end(), args.at(1).begin(), ::toupper); std::transform(args.at(1).begin(), args.at(1).end(), args.at(1).begin(), ::toupper);
for (uint32_t index = 0; index < NUMBER_OF_INVENTORIES; index++) { for (uint32_t index = 0; index < NUMBER_OF_INVENTORIES; index++) {
if (std::string_view(args.at(1)) == std::string_view(InventoryType::InventoryTypeToString(static_cast<eInventoryType>(index)))) selectedInventory = static_cast<eInventoryType>(index); if (std::string_view(args.at(1)) == std::string_view(InventoryType::InventoryTypeToString(static_cast<eInventoryType>(index)))) selectedInventory = static_cast<eInventoryType>(index);
} }
} }
if (selectedInventory == eInventoryType::INVALID) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid inventory.");
return;
}
ChatPackets::SendSystemMessage(sysAddr, u"Setting inventory " + ChatPackets::SendSystemMessage(sysAddr, u"Setting inventory " +
GeneralUtils::ASCIIToUTF16(args.at(1)) + GeneralUtils::ASCIIToUTF16(args.at(1)) +
@ -644,48 +644,48 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
if (chatCommand == "addmission" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) { if (chatCommand == "addmission" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) {
if (args.size() == 0) return; if (args.size() == 0) return;
uint32_t missionID; const auto missionID = GeneralUtils::TryParse<uint32_t>(args.at(0));
if (!GeneralUtils::TryParse(args[0], missionID)) { if (!missionID) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid mission id."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid mission id.");
return; return;
} }
auto comp = static_cast<MissionComponent*>(entity->GetComponent(eReplicaComponentType::MISSION)); auto comp = static_cast<MissionComponent*>(entity->GetComponent(eReplicaComponentType::MISSION));
if (comp) comp->AcceptMission(missionID, true); if (comp) comp->AcceptMission(missionID.value(), true);
return; return;
} }
if (chatCommand == "completemission" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) { if (chatCommand == "completemission" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) {
if (args.size() == 0) return; if (args.size() == 0) return;
uint32_t missionID; const auto missionID = GeneralUtils::TryParse<uint32_t>(args.at(0));
if (!GeneralUtils::TryParse(args[0], missionID)) { if (!missionID) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid mission id."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid mission id.");
return; return;
} }
auto comp = static_cast<MissionComponent*>(entity->GetComponent(eReplicaComponentType::MISSION)); auto comp = static_cast<MissionComponent*>(entity->GetComponent(eReplicaComponentType::MISSION));
if (comp) comp->CompleteMission(missionID, true); if (comp) comp->CompleteMission(missionID.value(), true);
return; return;
} }
if (chatCommand == "setflag" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() == 1) { if (chatCommand == "setflag" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() == 1) {
int32_t flagId; const auto flagId = GeneralUtils::TryParse<int32_t>(args.at(0));
if (!GeneralUtils::TryParse(args[0], flagId)) { if (!flagId) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid flag id."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid flag id.");
return; return;
} }
entity->GetCharacter()->SetPlayerFlag(flagId, true); entity->GetCharacter()->SetPlayerFlag(flagId.value(), true);
} }
if (chatCommand == "setflag" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() == 2) { if (chatCommand == "setflag" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() == 2) {
int32_t flagId; const auto flagId = GeneralUtils::TryParse<int32_t>(args.at(1));
std::string onOffFlag = args[0]; std::string onOffFlag = args.at(0);
if (!GeneralUtils::TryParse(args[1], flagId)) { if (!flagId) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid flag id."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid flag id.");
return; return;
} }
@ -693,28 +693,26 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
ChatPackets::SendSystemMessage(sysAddr, u"Invalid flag type."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid flag type.");
return; return;
} }
entity->GetCharacter()->SetPlayerFlag(flagId, onOffFlag == "on"); entity->GetCharacter()->SetPlayerFlag(flagId.value(), onOffFlag == "on");
} }
if (chatCommand == "clearflag" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() == 1) { if (chatCommand == "clearflag" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() == 1) {
int32_t flagId; const auto flagId = GeneralUtils::TryParse<int32_t>(args.at(0));
if (!GeneralUtils::TryParse(args[0], flagId)) { if (!flagId) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid flag id."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid flag id.");
return; return;
} }
entity->GetCharacter()->SetPlayerFlag(flagId, false); entity->GetCharacter()->SetPlayerFlag(flagId.value(), false);
} }
if (chatCommand == "playeffect" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() >= 3) { if (chatCommand == "playeffect" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() >= 3) {
int32_t effectID = 0; const auto effectID = GeneralUtils::TryParse<int32_t>(args.at(0));
if (!GeneralUtils::TryParse(args[0], effectID)) { if (!effectID) return;
return;
}
// FIXME: use fallible ASCIIToUTF16 conversion, because non-ascii isn't valid anyway // FIXME: use fallible ASCIIToUTF16 conversion, because non-ascii isn't valid anyway
GameMessages::SendPlayFXEffect(entity->GetObjectID(), effectID, GeneralUtils::ASCIIToUTF16(args[1]), args[2]); GameMessages::SendPlayFXEffect(entity->GetObjectID(), effectID.value(), GeneralUtils::ASCIIToUTF16(args.at(1)), args.at(2));
} }
if (chatCommand == "stopeffect" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() >= 1) { if (chatCommand == "stopeffect" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() >= 1) {
@ -776,34 +774,34 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
if (chatCommand == "gmadditem" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) { if (chatCommand == "gmadditem" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) {
if (args.size() == 1) { if (args.size() == 1) {
uint32_t itemLOT; const auto itemLOT = GeneralUtils::TryParse<uint32_t>(args.at(0));
if (!GeneralUtils::TryParse(args[0], itemLOT)) { if (!itemLOT) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid item LOT."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid item LOT.");
return; return;
} }
InventoryComponent* inventory = static_cast<InventoryComponent*>(entity->GetComponent(eReplicaComponentType::INVENTORY)); InventoryComponent* inventory = static_cast<InventoryComponent*>(entity->GetComponent(eReplicaComponentType::INVENTORY));
inventory->AddItem(itemLOT, 1, eLootSourceType::MODERATION); inventory->AddItem(itemLOT.value(), 1, eLootSourceType::MODERATION);
} else if (args.size() == 2) { } else if (args.size() == 2) {
uint32_t itemLOT; const auto itemLOT = GeneralUtils::TryParse<uint32_t>(args.at(0));
if (!GeneralUtils::TryParse(args[0], itemLOT)) { if (!itemLOT) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid item LOT."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid item LOT.");
return; return;
} }
uint32_t count; const auto count = GeneralUtils::TryParse<uint32_t>(args.at(0));
if (!GeneralUtils::TryParse(args[1], count)) { if (!count) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid item count."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid item count.");
return; return;
} }
InventoryComponent* inventory = static_cast<InventoryComponent*>(entity->GetComponent(eReplicaComponentType::INVENTORY)); InventoryComponent* inventory = static_cast<InventoryComponent*>(entity->GetComponent(eReplicaComponentType::INVENTORY));
inventory->AddItem(itemLOT, count, eLootSourceType::MODERATION); inventory->AddItem(itemLOT.value(), count.value(), eLootSourceType::MODERATION);
} else { } else {
ChatPackets::SendSystemMessage(sysAddr, u"Correct usage: /gmadditem <lot>"); ChatPackets::SendSystemMessage(sysAddr, u"Correct usage: /gmadditem <lot>");
} }
@ -823,9 +821,9 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
receiverID = playerInfo->id; receiverID = playerInfo->id;
LOT lot; const auto lot = GeneralUtils::TryParse<LOT>(args.at(1));
if (!GeneralUtils::TryParse(args[1], lot)) { if (!lot) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid item lot."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid item lot.");
return; return;
} }
@ -838,7 +836,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
mailInsert.subject = "Lost item"; mailInsert.subject = "Lost item";
mailInsert.body = "This is a replacement item for one you lost."; mailInsert.body = "This is a replacement item for one you lost.";
mailInsert.itemID = LWOOBJID_EMPTY; mailInsert.itemID = LWOOBJID_EMPTY;
mailInsert.itemLOT = lot; mailInsert.itemLOT = lot.value();
mailInsert.itemSubkey = LWOOBJID_EMPTY; mailInsert.itemSubkey = LWOOBJID_EMPTY;
mailInsert.itemCount = 1; mailInsert.itemCount = 1;
Database::Get()->InsertNewMail(mailInsert); Database::Get()->InsertNewMail(mailInsert);
@ -872,46 +870,47 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
NiPoint3 pos{}; NiPoint3 pos{};
if (args.size() == 3) { if (args.size() == 3) {
float x, y, z; const auto x = GeneralUtils::TryParse<float>(args.at(0));
if (!x) {
if (!GeneralUtils::TryParse(args[0], x)) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid x."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid x.");
return; return;
} }
if (!GeneralUtils::TryParse(args[1], y)) { const auto y = GeneralUtils::TryParse<float>(args.at(1));
if (!y) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid y."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid y.");
return; return;
} }
if (!GeneralUtils::TryParse(args[2], z)) { const auto z = GeneralUtils::TryParse<float>(args.at(2));
if (!z) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid z."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid z.");
return; return;
} }
pos.SetX(x); pos.SetX(x.value());
pos.SetY(y); pos.SetY(y.value());
pos.SetZ(z); pos.SetZ(z.value());
LOG("Teleporting objectID: %llu to %f, %f, %f", entity->GetObjectID(), pos.x, pos.y, pos.z); LOG("Teleporting objectID: %llu to %f, %f, %f", entity->GetObjectID(), pos.x, pos.y, pos.z);
GameMessages::SendTeleport(entity->GetObjectID(), pos, NiQuaternion(), sysAddr); GameMessages::SendTeleport(entity->GetObjectID(), pos, NiQuaternion(), sysAddr);
} else if (args.size() == 2) { } else if (args.size() == 2) {
float x, z; const auto x = GeneralUtils::TryParse<float>(args.at(0));
if (!x) {
if (!GeneralUtils::TryParse(args[0], x)) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid x."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid x.");
return; return;
} }
if (!GeneralUtils::TryParse(args[1], z)) { const auto z = GeneralUtils::TryParse<float>(args.at(1));
if (!z) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid z."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid z.");
return; return;
} }
pos.SetX(x); pos.SetX(x.value());
pos.SetY(0.0f); pos.SetY(0.0f);
pos.SetZ(z); pos.SetZ(z.value());
LOG("Teleporting objectID: %llu to X: %f, Z: %f", entity->GetObjectID(), pos.x, pos.z); LOG("Teleporting objectID: %llu to X: %f, Z: %f", entity->GetObjectID(), pos.x, pos.z);
GameMessages::SendTeleport(entity->GetObjectID(), pos, NiQuaternion(), sysAddr); GameMessages::SendTeleport(entity->GetObjectID(), pos, NiQuaternion(), sysAddr);
@ -971,10 +970,10 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
float speedScale = 1.0f; float speedScale = 1.0f;
if (args.size() >= 1) { if (args.size() >= 1) {
float tempScaleStore; const auto tempScaleStore = GeneralUtils::TryParse<float>(args.at(0));
if (GeneralUtils::TryParse<float>(args[0], tempScaleStore)) { if (tempScaleStore) {
speedScale = tempScaleStore; speedScale = tempScaleStore.value();
} else { } else {
ChatPackets::SendSystemMessage(sysAddr, u"Failed to parse speed scale argument."); ChatPackets::SendSystemMessage(sysAddr, u"Failed to parse speed scale argument.");
} }
@ -1024,16 +1023,16 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
time_t expire = 1; // Default to indefinate mute time_t expire = 1; // Default to indefinate mute
if (args.size() >= 2) { if (args.size() >= 2) {
uint32_t days = 0; const auto days = GeneralUtils::TryParse<uint32_t>(args.at(1));
uint32_t hours = 0; const auto hours = GeneralUtils::TryParse<uint32_t>(args.at(2));
if (!GeneralUtils::TryParse(args[1], days)) { if (!days) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid days."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid days.");
return; return;
} }
if (args.size() >= 3) { if (args.size() >= 3) {
if (!GeneralUtils::TryParse(args[2], hours)) { if (!hours) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid hours."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid hours.");
return; return;
@ -1041,8 +1040,8 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
} }
expire = time(NULL); expire = time(NULL);
expire += 24 * 60 * 60 * days; expire += 24 * 60 * 60 * days.value_or(0);
expire += 60 * 60 * hours; expire += 60 * 60 * hours.value_or(0);
} }
Database::Get()->UpdateAccountUnmuteTime(accountId, expire); Database::Get()->UpdateAccountUnmuteTime(accountId, expire);
@ -1140,14 +1139,14 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
} }
if (chatCommand == "startcelebration" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() == 1) { if (chatCommand == "startcelebration" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() == 1) {
int32_t celebration; const auto celebration = GeneralUtils::TryParse<int32_t>(args.at(0));
if (!GeneralUtils::TryParse(args[0], celebration)) { if (!celebration) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid celebration."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid celebration.");
return; return;
} }
GameMessages::SendStartCelebrationEffect(entity, entity->GetSystemAddress(), celebration); GameMessages::SendStartCelebrationEffect(entity, entity->GetSystemAddress(), celebration.value());
} }
if (chatCommand == "buffmed" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) { if (chatCommand == "buffmed" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) {
@ -1201,15 +1200,15 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
ControllablePhysicsComponent* comp = static_cast<ControllablePhysicsComponent*>(entity->GetComponent(eReplicaComponentType::CONTROLLABLE_PHYSICS)); ControllablePhysicsComponent* comp = static_cast<ControllablePhysicsComponent*>(entity->GetComponent(eReplicaComponentType::CONTROLLABLE_PHYSICS));
if (!comp) return; if (!comp) return;
uint32_t lot; const auto lot = GeneralUtils::TryParse<uint32_t>(args[0]);
if (!GeneralUtils::TryParse(args[0], lot)) { if (!lot) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid lot."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid lot.");
return; return;
} }
EntityInfo info; EntityInfo info;
info.lot = lot; info.lot = lot.value();
info.pos = comp->GetPosition(); info.pos = comp->GetPosition();
info.rot = comp->GetRotation(); info.rot = comp->GetRotation();
info.spawner = nullptr; info.spawner = nullptr;
@ -1230,28 +1229,29 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
auto controllablePhysicsComponent = entity->GetComponent<ControllablePhysicsComponent>(); auto controllablePhysicsComponent = entity->GetComponent<ControllablePhysicsComponent>();
if (!controllablePhysicsComponent) return; if (!controllablePhysicsComponent) return;
LOT lot{}; const auto lot = GeneralUtils::TryParse<LOT>(args[0]);
uint32_t numberToSpawn{}; if (!lot) {
float radiusToSpawnWithin{};
if (!GeneralUtils::TryParse(args[0], lot)) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid lot."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid lot.");
return; return;
} }
if (!GeneralUtils::TryParse(args[1], numberToSpawn) && numberToSpawn > 0) { const auto numberToSpawnOptional = GeneralUtils::TryParse<uint32_t>(args[1]);
if (!numberToSpawnOptional && numberToSpawnOptional.value() > 0) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid number of enemies to spawn."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid number of enemies to spawn.");
return; return;
} }
uint32_t numberToSpawn = numberToSpawnOptional.value();
// Must spawn within a radius of at least 0.0f // Must spawn within a radius of at least 0.0f
if (!GeneralUtils::TryParse(args[2], radiusToSpawnWithin) && radiusToSpawnWithin < 0.0f) { const auto radiusToSpawnWithinOptional = GeneralUtils::TryParse<float>(args[2]);
if (!radiusToSpawnWithinOptional && radiusToSpawnWithinOptional.value() < 0.0f) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid radius to spawn within."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid radius to spawn within.");
return; return;
} }
const float radiusToSpawnWithin = radiusToSpawnWithinOptional.value();
EntityInfo info; EntityInfo info;
info.lot = lot; info.lot = lot.value();
info.spawner = nullptr; info.spawner = nullptr;
info.spawnerID = entity->GetObjectID(); info.spawnerID = entity->GetObjectID();
info.spawnerNodeID = 0; info.spawnerNodeID = 0;
@ -1278,12 +1278,12 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
} }
if ((chatCommand == "giveuscore") && args.size() >= 1 && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) { if ((chatCommand == "giveuscore") && args.size() >= 1 && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) {
int32_t uscore; const auto uscoreOptional = GeneralUtils::TryParse<int32_t>(args[0]);
if (!uscoreOptional) {
if (!GeneralUtils::TryParse(args[0], uscore)) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid uscore."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid uscore.");
return; return;
} }
const int32_t uscore = uscoreOptional.value();
CharacterComponent* character = entity->GetComponent<CharacterComponent>(); CharacterComponent* character = entity->GetComponent<CharacterComponent>();
if (character) character->SetUScore(character->GetUScore() + uscore); if (character) character->SetUScore(character->GetUScore() + uscore);
@ -1291,9 +1291,9 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
eLootSourceType lootType = eLootSourceType::MODERATION; eLootSourceType lootType = eLootSourceType::MODERATION;
int32_t type; const auto type = GeneralUtils::TryParse<eLootSourceType>(args[1]);
if (args.size() >= 2 && GeneralUtils::TryParse(args[1], type)) { if (args.size() >= 2 && type) {
lootType = static_cast<eLootSourceType>(type); lootType = type.value();
} }
GameMessages::SendModifyLEGOScore(entity, entity->GetSystemAddress(), uscore, lootType); GameMessages::SendModifyLEGOScore(entity, entity->GetSystemAddress(), uscore, lootType);
@ -1319,14 +1319,15 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
entity = requestedPlayer->GetOwner(); entity = requestedPlayer->GetOwner();
} }
uint32_t requestedLevel; const auto requestedLevelOptional = GeneralUtils::TryParse<uint32_t>(args[0]);
uint32_t oldLevel; uint32_t oldLevel;
// first check the level is valid
if (!GeneralUtils::TryParse(args[0], requestedLevel)) { // first check the level is valid
if (!requestedLevelOptional) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid level."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid level.");
return; return;
} }
uint32_t requestedLevel = requestedLevelOptional.value();
// query to set our uscore to the correct value for this level // query to set our uscore to the correct value for this level
auto characterComponent = entity->GetComponent<CharacterComponent>(); auto characterComponent = entity->GetComponent<CharacterComponent>();
@ -1399,27 +1400,27 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
} }
if ((chatCommand == "freemoney" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) && args.size() == 1) { if ((chatCommand == "freemoney" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) && args.size() == 1) {
int64_t money; const auto money = GeneralUtils::TryParse<int64_t>(args[0]);
if (!GeneralUtils::TryParse(args[0], money)) { if (!money) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid money."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid money.");
return; return;
} }
auto* ch = entity->GetCharacter(); auto* ch = entity->GetCharacter();
ch->SetCoins(ch->GetCoins() + money, eLootSourceType::MODERATION); ch->SetCoins(ch->GetCoins() + money.value(), eLootSourceType::MODERATION);
} }
if ((chatCommand == "setcurrency") && args.size() == 1 && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) { if ((chatCommand == "setcurrency") && args.size() == 1 && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) {
int32_t money; const auto money = GeneralUtils::TryParse<int64_t>(args[0]);
if (!GeneralUtils::TryParse(args[0], money)) { if (!money) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid money."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid money.");
return; return;
} }
auto* ch = entity->GetCharacter(); auto* ch = entity->GetCharacter();
ch->SetCoins(money, eLootSourceType::MODERATION); ch->SetCoins(money.value(), eLootSourceType::MODERATION);
} }
// Allow for this on even while not a GM, as it sometimes toggles incorrrectly. // Allow for this on even while not a GM, as it sometimes toggles incorrrectly.
@ -1432,17 +1433,14 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
if (chatCommand == "gmimmune" && args.size() >= 1 && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) { if (chatCommand == "gmimmune" && args.size() >= 1 && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) {
auto* destroyableComponent = entity->GetComponent<DestroyableComponent>(); auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
int32_t state = false; const auto state = GeneralUtils::TryParse<int32_t>(args[0]);
if (!GeneralUtils::TryParse(args[0], state)) { if (!state) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid state."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid state.");
return; return;
} }
if (destroyableComponent != nullptr) { if (destroyableComponent) destroyableComponent->SetIsGMImmune(state.value());
destroyableComponent->SetIsGMImmune(state);
}
return; return;
} }
@ -1450,53 +1448,48 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
if (chatCommand == "attackimmune" && args.size() >= 1 && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) { if (chatCommand == "attackimmune" && args.size() >= 1 && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) {
auto* destroyableComponent = entity->GetComponent<DestroyableComponent>(); auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
int32_t state = false; const auto state = GeneralUtils::TryParse<int32_t>(args[0]);
if (!GeneralUtils::TryParse(args[0], state)) { if (!state) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid state."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid state.");
return; return;
} }
if (destroyableComponent != nullptr) { if (destroyableComponent) destroyableComponent->SetIsImmune(state.value());
destroyableComponent->SetIsImmune(state);
}
return; return;
} }
if (chatCommand == "buff" && args.size() >= 2 && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) { if (chatCommand == "buff" && args.size() >= 2 && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) {
auto* buffComponent = entity->GetComponent<BuffComponent>(); auto* buffComponent = entity->GetComponent<BuffComponent>();
int32_t id = 0; const auto id = GeneralUtils::TryParse<int32_t>(args[0]);
int32_t duration = 0; const auto duration = GeneralUtils::TryParse<int32_t>(args[1]);
if (!GeneralUtils::TryParse(args[0], id)) { if (!id) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid buff id."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid buff id.");
return; return;
} }
if (!GeneralUtils::TryParse(args[1], duration)) { if (!duration) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid buff duration."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid buff duration.");
return; return;
} }
if (buffComponent != nullptr) { if (buffComponent) buffComponent->ApplyBuff(id.value(), duration.value(), entity->GetObjectID());
buffComponent->ApplyBuff(id, duration, entity->GetObjectID());
}
return; return;
} }
if ((chatCommand == "testmap" && args.size() >= 1) && entity->GetGMLevel() >= eGameMasterLevel::FORUM_MODERATOR) { if ((chatCommand == "testmap" && args.size() >= 1) && entity->GetGMLevel() >= eGameMasterLevel::FORUM_MODERATOR) {
ChatPackets::SendSystemMessage(sysAddr, u"Requesting map change..."); ChatPackets::SendSystemMessage(sysAddr, u"Requesting map change...");
uint32_t reqZone;
LWOCLONEID cloneId = 0; LWOCLONEID cloneId = 0;
bool force = false; bool force = false;
if (!GeneralUtils::TryParse(args[0], reqZone)) { const auto reqZoneOptional = GeneralUtils::TryParse<LWOMAPID>(args[0]);
if (!reqZoneOptional) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid zone."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid zone.");
return; return;
} }
const LWOMAPID reqZone = reqZoneOptional.value();
if (args.size() > 1) { if (args.size() > 1) {
auto index = 1; auto index = 1;
@ -1507,10 +1500,12 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
force = true; force = true;
} }
if (args.size() > index && !GeneralUtils::TryParse(args[index], cloneId)) { const auto cloneIdOptional = GeneralUtils::TryParse<LWOCLONEID>(args[index]);
if (args.size() > index && !cloneIdOptional) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid clone id."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid clone id.");
return; return;
} }
cloneId = cloneIdOptional.value();
} }
const auto objid = entity->GetObjectID(); const auto objid = entity->GetObjectID();
@ -1547,23 +1542,21 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
} }
if (chatCommand == "createprivate" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() >= 3) { if (chatCommand == "createprivate" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() >= 3) {
uint32_t zone; const auto zone = GeneralUtils::TryParse<uint32_t>(args[0]);
if (!zone) {
if (!GeneralUtils::TryParse(args[0], zone)) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid zone."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid zone.");
return; return;
} }
uint32_t clone; const auto clone = GeneralUtils::TryParse<uint32_t>(args[1]);
if (!clone) {
if (!GeneralUtils::TryParse(args[1], clone)) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid clone."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid clone.");
return; return;
} }
const auto& password = args[2]; const auto& password = args[2];
ZoneInstanceManager::Instance()->CreatePrivateZone(Game::server, zone, clone, password); ZoneInstanceManager::Instance()->CreatePrivateZone(Game::server, zone.value(), clone.value(), password);
ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::ASCIIToUTF16("Sent request for private zone with password: " + password)); ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::ASCIIToUTF16("Sent request for private zone with password: " + password));
@ -1590,14 +1583,14 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
} }
if (args.size() >= 1) { if (args.size() >= 1) {
float time; const auto time = GeneralUtils::TryParse<float>(args[0]);
if (!GeneralUtils::TryParse(args[0], time)) { if (!time) {
ChatPackets::SendSystemMessage(sysAddr, u"Invalid boost time."); ChatPackets::SendSystemMessage(sysAddr, u"Invalid boost time.");
return; return;
} else { } else {
GameMessages::SendVehicleAddPassiveBoostAction(vehicle->GetObjectID(), UNASSIGNED_SYSTEM_ADDRESS); GameMessages::SendVehicleAddPassiveBoostAction(vehicle->GetObjectID(), UNASSIGNED_SYSTEM_ADDRESS);
entity->AddCallbackTimer(time, [vehicle]() { entity->AddCallbackTimer(time.value(), [vehicle]() {
if (!vehicle) return; if (!vehicle) return;
GameMessages::SendVehicleRemovePassiveBoostAction(vehicle->GetObjectID(), UNASSIGNED_SYSTEM_ADDRESS); GameMessages::SendVehicleRemovePassiveBoostAction(vehicle->GetObjectID(), UNASSIGNED_SYSTEM_ADDRESS);
}); });
@ -1673,20 +1666,20 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
} }
if (chatCommand == "reforge" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() >= 2) { if (chatCommand == "reforge" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() >= 2) {
LOT baseItem; const auto baseItem = GeneralUtils::TryParse<LOT>(args[0]);
LOT reforgedItem; const auto reforgedItem = GeneralUtils::TryParse<LOT>(args[1]);
if (!GeneralUtils::TryParse(args[0], baseItem)) return; if (!baseItem) return;
if (!GeneralUtils::TryParse(args[1], reforgedItem)) return; if (!reforgedItem) return;
auto* inventoryComponent = entity->GetComponent<InventoryComponent>(); auto* inventoryComponent = entity->GetComponent<InventoryComponent>();
if (inventoryComponent == nullptr) return; if (inventoryComponent == nullptr) return;
std::vector<LDFBaseData*> data{}; std::vector<LDFBaseData*> data{};
data.push_back(new LDFData<int32_t>(u"reforgedLOT", reforgedItem)); data.push_back(new LDFData<int32_t>(u"reforgedLOT", reforgedItem.value()));
inventoryComponent->AddItem(baseItem, 1, eLootSourceType::MODERATION, eInventoryType::INVALID, data); inventoryComponent->AddItem(baseItem.value(), 1, eLootSourceType::MODERATION, eInventoryType::INVALID, data);
} }
if (chatCommand == "crash" && entity->GetGMLevel() >= eGameMasterLevel::OPERATOR) { if (chatCommand == "crash" && entity->GetGMLevel() >= eGameMasterLevel::OPERATOR) {
@ -1752,19 +1745,19 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
} }
if (chatCommand == "rollloot" && entity->GetGMLevel() >= eGameMasterLevel::OPERATOR && args.size() >= 3) { if (chatCommand == "rollloot" && entity->GetGMLevel() >= eGameMasterLevel::OPERATOR && args.size() >= 3) {
uint32_t lootMatrixIndex = 0; const auto lootMatrixIndex = GeneralUtils::TryParse<uint32_t>(args[0]);
uint32_t targetLot = 0; const auto targetLot = GeneralUtils::TryParse<uint32_t>(args[1]);
uint32_t loops = 1; const auto loops = GeneralUtils::TryParse<uint32_t>(args[2]);
if (!GeneralUtils::TryParse(args[0], lootMatrixIndex)) return; if (!lootMatrixIndex) return;
if (!GeneralUtils::TryParse(args[1], targetLot)) return; if (!targetLot) return;
if (!GeneralUtils::TryParse(args[2], loops)) return; if (!loops) return;
uint64_t totalRuns = 0; uint64_t totalRuns = 0;
for (uint32_t i = 0; i < loops; i++) { for (uint32_t i = 0; i < loops; i++) {
while (true) { while (true) {
auto lootRoll = Loot::RollLootMatrix(lootMatrixIndex); auto lootRoll = Loot::RollLootMatrix(lootMatrixIndex.value());
totalRuns += 1; totalRuns += 1;
bool doBreak = false; bool doBreak = false;
for (const auto& kv : lootRoll) { for (const auto& kv : lootRoll) {
@ -1777,26 +1770,30 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
} }
std::u16string message = u"Ran loot drops looking for " std::u16string message = u"Ran loot drops looking for "
+ GeneralUtils::to_u16string(targetLot) + GeneralUtils::to_u16string(targetLot.value())
+ u", " + u", "
+ GeneralUtils::to_u16string(loops) + GeneralUtils::to_u16string(loops.value())
+ u" times. It ran " + u" times. It ran "
+ GeneralUtils::to_u16string(totalRuns) + GeneralUtils::to_u16string(totalRuns)
+ u" times. Averaging out at " + u" times. Averaging out at "
+ GeneralUtils::to_u16string(static_cast<float>(totalRuns) / loops); + GeneralUtils::to_u16string(static_cast<float>(totalRuns) / loops.value());
ChatPackets::SendSystemMessage(sysAddr, message); ChatPackets::SendSystemMessage(sysAddr, message);
} }
if (chatCommand == "deleteinven" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() >= 1) { if (chatCommand == "deleteinven" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() >= 1) {
eInventoryType inventoryType = eInventoryType::INVALID; eInventoryType inventoryType = eInventoryType::INVALID;
if (!GeneralUtils::TryParse(args[0], inventoryType)) {
const auto inventoryTypeOptional = GeneralUtils::TryParse<eInventoryType>(args[0]);
if (!inventoryTypeOptional) {
// In this case, we treat the input as a string and try to find it in the reflection list // In this case, we treat the input as a string and try to find it in the reflection list
std::transform(args[0].begin(), args[0].end(), args[0].begin(), ::toupper); std::transform(args[0].begin(), args[0].end(), args[0].begin(), ::toupper);
LOG("looking for inventory %s", args[0].c_str()); LOG("looking for inventory %s", args[0].c_str());
for (uint32_t index = 0; index < NUMBER_OF_INVENTORIES; index++) { for (uint32_t index = 0; index < NUMBER_OF_INVENTORIES; index++) {
if (std::string_view(args[0]) == std::string_view(InventoryType::InventoryTypeToString(static_cast<eInventoryType>(index)))) inventoryType = static_cast<eInventoryType>(index); if (std::string_view(args[0]) == std::string_view(InventoryType::InventoryTypeToString(static_cast<eInventoryType>(index)))) inventoryType = static_cast<eInventoryType>(index);
} }
} else {
inventoryType = inventoryTypeOptional.value();
} }
if (inventoryType == eInventoryType::INVALID || inventoryType >= NUMBER_OF_INVENTORIES) { if (inventoryType == eInventoryType::INVALID || inventoryType >= NUMBER_OF_INVENTORIES) {
@ -1818,32 +1815,32 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
if (chatCommand == "castskill" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() >= 1) { if (chatCommand == "castskill" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() >= 1) {
auto* skillComponent = entity->GetComponent<SkillComponent>(); auto* skillComponent = entity->GetComponent<SkillComponent>();
if (skillComponent) { if (skillComponent) {
uint32_t skillId; const auto skillId = GeneralUtils::TryParse<uint32_t>(args[0]);
if (!GeneralUtils::TryParse(args[0], skillId)) { if (!skillId) {
ChatPackets::SendSystemMessage(sysAddr, u"Error getting skill ID."); ChatPackets::SendSystemMessage(sysAddr, u"Error getting skill ID.");
return; return;
} else { } else {
skillComponent->CastSkill(skillId, entity->GetObjectID(), entity->GetObjectID()); skillComponent->CastSkill(skillId.value(), entity->GetObjectID(), entity->GetObjectID());
ChatPackets::SendSystemMessage(sysAddr, u"Cast skill"); ChatPackets::SendSystemMessage(sysAddr, u"Cast skill");
} }
} }
} }
if (chatCommand == "setskillslot" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() >= 2) { if (chatCommand == "setskillslot" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() >= 2) {
uint32_t skillId; auto* const inventoryComponent = entity->GetComponent<InventoryComponent>();
int slot;
auto* inventoryComponent = entity->GetComponent<InventoryComponent>();
if (inventoryComponent) { if (inventoryComponent) {
if (!GeneralUtils::TryParse(args[0], slot)) { const auto slot = GeneralUtils::TryParse<BehaviorSlot>(args[0]);
if (!slot) {
ChatPackets::SendSystemMessage(sysAddr, u"Error getting slot."); ChatPackets::SendSystemMessage(sysAddr, u"Error getting slot.");
return; return;
} else { } else {
if (!GeneralUtils::TryParse(args[1], skillId)) { const auto skillId = GeneralUtils::TryParse<uint32_t>(args[1]);
if (!skillId) {
ChatPackets::SendSystemMessage(sysAddr, u"Error getting skill."); ChatPackets::SendSystemMessage(sysAddr, u"Error getting skill.");
return; return;
} else { } else {
if (inventoryComponent->SetSkill(slot, skillId)) ChatPackets::SendSystemMessage(sysAddr, u"Set skill to slot successfully"); if (inventoryComponent->SetSkill(slot.value(), skillId.value())) ChatPackets::SendSystemMessage(sysAddr, u"Set skill to slot successfully");
else ChatPackets::SendSystemMessage(sysAddr, u"Set skill to slot failed"); else ChatPackets::SendSystemMessage(sysAddr, u"Set skill to slot failed");
} }
} }
@ -1853,13 +1850,13 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
if (chatCommand == "setfaction" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() >= 1) { if (chatCommand == "setfaction" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() >= 1) {
auto* destroyableComponent = entity->GetComponent<DestroyableComponent>(); auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
if (destroyableComponent) { if (destroyableComponent) {
int32_t faction; const auto faction = GeneralUtils::TryParse<int32_t>(args[0]);
if (!GeneralUtils::TryParse(args[0], faction)) { if (!faction) {
ChatPackets::SendSystemMessage(sysAddr, u"Error getting faction."); ChatPackets::SendSystemMessage(sysAddr, u"Error getting faction.");
return; return;
} else { } else {
destroyableComponent->SetFaction(faction); destroyableComponent->SetFaction(faction.value());
ChatPackets::SendSystemMessage(sysAddr, u"Set faction and updated enemies list"); ChatPackets::SendSystemMessage(sysAddr, u"Set faction and updated enemies list");
} }
} }
@ -1868,13 +1865,13 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
if (chatCommand == "addfaction" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() >= 1) { if (chatCommand == "addfaction" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() >= 1) {
auto* destroyableComponent = entity->GetComponent<DestroyableComponent>(); auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
if (destroyableComponent) { if (destroyableComponent) {
int32_t faction; const auto faction = GeneralUtils::TryParse<int32_t>(args[0]);
if (!GeneralUtils::TryParse(args[0], faction)) { if (!faction) {
ChatPackets::SendSystemMessage(sysAddr, u"Error getting faction."); ChatPackets::SendSystemMessage(sysAddr, u"Error getting faction.");
return; return;
} else { } else {
destroyableComponent->AddFaction(faction); destroyableComponent->AddFaction(faction.value());
ChatPackets::SendSystemMessage(sysAddr, u"Added faction and updated enemies list"); ChatPackets::SendSystemMessage(sysAddr, u"Added faction and updated enemies list");
} }
} }
@ -1905,13 +1902,14 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
if (chatCommand == "inspect" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() >= 1) { if (chatCommand == "inspect" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() >= 1) {
Entity* closest = nullptr; Entity* closest = nullptr;
eReplicaComponentType component; //eReplicaComponentType component;
std::u16string ldf; std::u16string ldf;
bool isLDF = false; bool isLDF = false;
if (!GeneralUtils::TryParse(args[0], component)) { auto component = GeneralUtils::TryParse<eReplicaComponentType>(args[0]);
if (!component) {
component = eReplicaComponentType::INVALID; component = eReplicaComponentType::INVALID;
ldf = GeneralUtils::UTF8ToUTF16(args[0]); ldf = GeneralUtils::UTF8ToUTF16(args[0]);
@ -1923,7 +1921,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
auto closestDistance = 0.0f; auto closestDistance = 0.0f;
const auto candidates = Game::entityManager->GetEntitiesByComponent(component); const auto candidates = Game::entityManager->GetEntitiesByComponent(component.value());
for (auto* candidate : candidates) { for (auto* candidate : candidates) {
if (candidate->GetLOT() == 1 || candidate->GetLOT() == 8092) { if (candidate->GetLOT() == 1 || candidate->GetLOT() == 8092) {
@ -1934,7 +1932,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
continue; continue;
} }
if (closest == nullptr) { if (!closest) {
closest = candidate; closest = candidate;
closestDistance = NiPoint3::Distance(candidate->GetPosition(), reference); closestDistance = NiPoint3::Distance(candidate->GetPosition(), reference);
@ -1951,9 +1949,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
} }
} }
if (closest == nullptr) { if (!closest) return;
return;
}
Game::entityManager->SerializeEntity(closest); Game::entityManager->SerializeEntity(closest);
@ -1979,20 +1975,18 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
if (args.size() >= 2) { if (args.size() >= 2) {
if (args[1] == "-m" && args.size() >= 3) { if (args[1] == "-m" && args.size() >= 3) {
auto* movingPlatformComponent = closest->GetComponent<MovingPlatformComponent>(); auto* const movingPlatformComponent = closest->GetComponent<MovingPlatformComponent>();
int32_t value = 0; const auto mValue = GeneralUtils::TryParse<int32_t>(args[2]);
if (movingPlatformComponent == nullptr || !GeneralUtils::TryParse(args[2], value)) { if (!movingPlatformComponent || !mValue) return;
return;
}
movingPlatformComponent->SetSerialized(true); movingPlatformComponent->SetSerialized(true);
if (value == -1) { if (mValue == -1) {
movingPlatformComponent->StopPathing(); movingPlatformComponent->StopPathing();
} else { } else {
movingPlatformComponent->GotoWaypoint(value); movingPlatformComponent->GotoWaypoint(mValue.value());
} }
Game::entityManager->SerializeEntity(closest); Game::entityManager->SerializeEntity(closest);
@ -2033,13 +2027,11 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
} }
if (args.size() >= 3) { if (args.size() >= 3) {
int32_t faction; const auto faction = GeneralUtils::TryParse<int32_t>(args[2]);
if (!GeneralUtils::TryParse(args[2], faction)) { if (!faction) return;
return;
}
destuctable->SetFaction(-1); destuctable->SetFaction(-1);
destuctable->AddFaction(faction, true); destuctable->AddFaction(faction.value(), true);
} }
} else if (args[1] == "-cf") { } else if (args[1] == "-cf") {
auto* destuctable = entity->GetComponent<DestroyableComponent>(); auto* destuctable = entity->GetComponent<DestroyableComponent>();

View File

@ -17,7 +17,8 @@
InstanceManager::InstanceManager(Logger* logger, const std::string& externalIP) { InstanceManager::InstanceManager(Logger* logger, const std::string& externalIP) {
mLogger = logger; mLogger = logger;
mExternalIP = externalIP; mExternalIP = externalIP;
GeneralUtils::TryParse(Game::config->GetValue("world_port_start"), m_LastPort); m_LastPort =
GeneralUtils::TryParse<decltype(m_LastPort)>(Game::config->GetValue("world_port_start")).value_or(m_LastPort);
m_LastInstanceID = LWOINSTANCEID_INVALID; m_LastInstanceID = LWOINSTANCEID_INVALID;
} }

View File

@ -134,7 +134,7 @@ private:
Logger* mLogger; Logger* mLogger;
std::string mExternalIP; std::string mExternalIP;
std::vector<Instance*> m_Instances; std::vector<Instance*> m_Instances;
unsigned short m_LastPort = 3000; uint16_t m_LastPort = 3000;
LWOINSTANCEID m_LastInstanceID; LWOINSTANCEID m_LastInstanceID;
/** /**

View File

@ -89,9 +89,8 @@ int main(int argc, char** argv) {
if (!dConfig::Exists("worldconfig.ini")) LOG("Could not find worldconfig.ini, using default settings"); if (!dConfig::Exists("worldconfig.ini")) LOG("Could not find worldconfig.ini, using default settings");
uint32_t clientNetVersion = 171022;
const auto clientNetVersionString = Game::config->GetValue("client_net_version"); const auto clientNetVersionString = Game::config->GetValue("client_net_version");
if (!clientNetVersionString.empty()) GeneralUtils::TryParse(clientNetVersionString, clientNetVersion); const uint32_t clientNetVersion = GeneralUtils::TryParse<uint32_t>(clientNetVersionString).value_or(171022);
LOG("Using net version %i", clientNetVersion); LOG("Using net version %i", clientNetVersion);

View File

@ -39,10 +39,9 @@ void AuthPackets::LoadClaimCodes() {
auto rcstring = Game::config->GetValue("rewardcodes"); auto rcstring = Game::config->GetValue("rewardcodes");
auto codestrings = GeneralUtils::SplitString(rcstring, ','); auto codestrings = GeneralUtils::SplitString(rcstring, ',');
for(auto const &codestring: codestrings){ for(auto const &codestring: codestrings){
uint32_t code = -1; const auto code = GeneralUtils::TryParse<uint32_t>(codestring);
if(GeneralUtils::TryParse(codestring, code) && code != -1){
claimCodes.push_back(code); if (code) claimCodes.push_back(code.value());
}
} }
} }
@ -74,9 +73,8 @@ void AuthPackets::SendHandshake(dServer* server, const SystemAddress& sysAddr, c
RakNet::BitStream bitStream; RakNet::BitStream bitStream;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::SERVER, eServerMessageType::VERSION_CONFIRM); BitStreamUtils::WriteHeader(bitStream, eConnectionType::SERVER, eServerMessageType::VERSION_CONFIRM);
uint32_t clientNetVersion = 171022;
const auto clientNetVersionString = Game::config->GetValue("client_net_version"); const auto clientNetVersionString = Game::config->GetValue("client_net_version");
if (!clientNetVersionString.empty()) GeneralUtils::TryParse(clientNetVersionString, clientNetVersion); const uint32_t clientNetVersion = GeneralUtils::TryParse<uint32_t>(clientNetVersionString).value_or(171022);
bitStream.Write<uint32_t>(clientNetVersion); bitStream.Write<uint32_t>(clientNetVersion);
bitStream.Write<uint32_t>(861228100); bitStream.Write<uint32_t>(861228100);
@ -246,9 +244,9 @@ void AuthPackets::SendLoginResponse(dServer* server, const SystemAddress& sysAdd
uint16_t version_major = 1; uint16_t version_major = 1;
uint16_t version_current = 10; uint16_t version_current = 10;
uint16_t version_minor = 64; uint16_t version_minor = 64;
GeneralUtils::TryParse<uint16_t>(Game::config->GetValue("version_major"), version_major); version_major = GeneralUtils::TryParse<uint16_t>(Game::config->GetValue("version_major")).value_or(version_major);
GeneralUtils::TryParse<uint16_t>(Game::config->GetValue("version_current"), version_current); version_current = GeneralUtils::TryParse<uint16_t>(Game::config->GetValue("version_current")).value_or(version_current);
GeneralUtils::TryParse<uint16_t>(Game::config->GetValue("version_minor"), version_minor); version_minor = GeneralUtils::TryParse<uint16_t>(Game::config->GetValue("version_minor")).value_or(version_minor);
loginResponse.Write(version_major); loginResponse.Write(version_major);
loginResponse.Write(version_current); loginResponse.Write(version_current);

View File

@ -26,9 +26,15 @@ namespace {
void dpWorld::Initialize(unsigned int zoneID, bool generateNewNavMesh) { void dpWorld::Initialize(unsigned int zoneID, bool generateNewNavMesh) {
const auto physSpTilecount = Game::config->GetValue("phys_sp_tilecount"); const auto physSpTilecount = Game::config->GetValue("phys_sp_tilecount");
if (!physSpTilecount.empty()) GeneralUtils::TryParse(physSpTilecount, phys_sp_tilecount); if (!physSpTilecount.empty()) {
phys_sp_tilecount = GeneralUtils::TryParse<int32_t>(physSpTilecount).value_or(phys_sp_tilecount);
}
const auto physSpTilesize = Game::config->GetValue("phys_sp_tilesize"); const auto physSpTilesize = Game::config->GetValue("phys_sp_tilesize");
if (!physSpTilesize.empty()) GeneralUtils::TryParse(physSpTilesize, phys_sp_tilesize); if (!physSpTilesize.empty()) {
phys_sp_tilesize = GeneralUtils::TryParse<int32_t>(physSpTilesize).value_or(phys_sp_tilesize);
}
const auto physSpatialPartitioning = Game::config->GetValue("phys_spatial_partitioning"); const auto physSpatialPartitioning = Game::config->GetValue("phys_spatial_partitioning");
if (!physSpatialPartitioning.empty()) phys_spatial_partitioning = physSpatialPartitioning == "1"; if (!physSpatialPartitioning.empty()) phys_spatial_partitioning = physSpatialPartitioning == "1";

View File

@ -33,14 +33,12 @@ void AmDropshipComputer::OnUse(Entity* self, Entity* user) {
void AmDropshipComputer::OnDie(Entity* self, Entity* killer) { void AmDropshipComputer::OnDie(Entity* self, Entity* killer) {
const auto myGroup = GeneralUtils::UTF16ToWTF8(self->GetVar<std::u16string>(u"spawner_name")); const auto myGroup = GeneralUtils::UTF16ToWTF8(self->GetVar<std::u16string>(u"spawner_name"));
int32_t pipeNum = 0; const auto pipeNum = GeneralUtils::TryParse<int32_t>(myGroup.substr(10, 1));
if (!GeneralUtils::TryParse<int32_t>(myGroup.substr(10, 1), pipeNum)) { if (!pipeNum) return;
return;
}
const auto pipeGroup = myGroup.substr(0, 10); const auto pipeGroup = myGroup.substr(0, 10);
const auto nextPipeNum = pipeNum + 1; const auto nextPipeNum = pipeNum.value() + 1;
const auto samePipeSpawners = Game::zoneManager->GetSpawnersByName(myGroup); const auto samePipeSpawners = Game::zoneManager->GetSpawnersByName(myGroup);
@ -70,11 +68,9 @@ void AmDropshipComputer::OnDie(Entity* self, Entity* killer) {
} }
void AmDropshipComputer::OnTimerDone(Entity* self, std::string timerName) { void AmDropshipComputer::OnTimerDone(Entity* self, std::string timerName) {
auto* quickBuildComponent = self->GetComponent<QuickBuildComponent>(); const auto* const quickBuildComponent = self->GetComponent<QuickBuildComponent>();
if (quickBuildComponent == nullptr) { if (!quickBuildComponent) return;
return;
}
if (timerName == "reset" && quickBuildComponent->GetState() == eQuickBuildState::OPEN) { if (timerName == "reset" && quickBuildComponent->GetState() == eQuickBuildState::OPEN) {
self->Smash(self->GetObjectID(), eKillType::SILENT); self->Smash(self->GetObjectID(), eKillType::SILENT);

View File

@ -144,13 +144,10 @@ void AmSkullkinTower::OnChildRemoved(Entity* self, Entity* child) {
); );
for (const auto& mission : missions) { for (const auto& mission : missions) {
int32_t missionID = 0; const auto missionID = GeneralUtils::TryParse<LOT>(mission);
if (!missionID) continue;
if (!GeneralUtils::TryParse(mission, missionID)) { missionIDs.push_back(missionID.value());
continue;
}
missionIDs.push_back(missionID);
} }
} }

View File

@ -12,12 +12,9 @@ void AmTemplateSkillVolume::OnSkillEventFired(Entity* self, Entity* caster, cons
const auto missionIDs = GeneralUtils::SplitString(missionIDsVariable, '_'); const auto missionIDs = GeneralUtils::SplitString(missionIDsVariable, '_');
for (const auto& missionIDStr : missionIDs) { for (const auto& missionIDStr : missionIDs) {
int32_t missionID = 0; const auto missionID = GeneralUtils::TryParse<uint32_t>(missionIDStr);
if (!missionID) continue;
if (!GeneralUtils::TryParse(missionIDStr, missionID)) { missionComponent->ForceProgressTaskType(missionID.value(), 1, 1, false);
continue;
}
missionComponent->ForceProgressTaskType(missionID, 1, 1, false);
} }
} }

View File

@ -41,11 +41,9 @@ void ChooseYourDestinationNsToNt::SetDestination(Entity* self, Entity* player) {
void ChooseYourDestinationNsToNt::BaseChoiceBoxRespond(Entity* self, Entity* sender, int32_t button, const std::u16string& buttonIdentifier, const std::u16string& identifier) { void ChooseYourDestinationNsToNt::BaseChoiceBoxRespond(Entity* self, Entity* sender, int32_t button, const std::u16string& buttonIdentifier, const std::u16string& identifier) {
if (button != -1) { if (button != -1) {
const auto newMapStr = GeneralUtils::UTF16ToWTF8(buttonIdentifier).substr(7, -1); const auto newMapStr = GeneralUtils::UTF16ToWTF8(buttonIdentifier).substr(7, -1);
const auto newMap = GeneralUtils::TryParse<int32_t>(newMapStr);
int32_t newMap = 0;
if (!GeneralUtils::TryParse(newMapStr, newMap)) { if (!newMap) return;
return;
}
std::u16string strText = u""; std::u16string strText = u"";
@ -56,7 +54,7 @@ void ChooseYourDestinationNsToNt::BaseChoiceBoxRespond(Entity* self, Entity* sen
} }
self->SetVar(u"teleportString", strText); self->SetVar(u"teleportString", strText);
self->SetVar(u"transferZoneID", GeneralUtils::to_u16string(newMap)); self->SetVar(u"transferZoneID", GeneralUtils::to_u16string(newMap.value()));
GameMessages::SendDisplayMessageBox(sender->GetObjectID(), true, self->GetObjectID(), u"TransferBox", 0, strText, u"", sender->GetSystemAddress()); GameMessages::SendDisplayMessageBox(sender->GetObjectID(), true, self->GetObjectID(), u"TransferBox", 0, strText, u"", sender->GetSystemAddress());
} else { } else {

View File

@ -7,10 +7,8 @@
void FvBrickPuzzleServer::OnStartup(Entity* self) { void FvBrickPuzzleServer::OnStartup(Entity* self) {
const auto myGroup = GeneralUtils::UTF16ToWTF8(self->GetVar<std::u16string>(u"spawner_name")); const auto myGroup = GeneralUtils::UTF16ToWTF8(self->GetVar<std::u16string>(u"spawner_name"));
int32_t pipeNum = 0; const auto pipeNum = GeneralUtils::TryParse<int32_t>(myGroup.substr(10, 1));
if (!GeneralUtils::TryParse<int32_t>(myGroup.substr(10, 1), pipeNum)) { if (!pipeNum) return;
return;
}
if (pipeNum != 1) { if (pipeNum != 1) {
self->AddTimer("reset", 30); self->AddTimer("reset", 30);
@ -20,14 +18,12 @@ void FvBrickPuzzleServer::OnStartup(Entity* self) {
void FvBrickPuzzleServer::OnDie(Entity* self, Entity* killer) { void FvBrickPuzzleServer::OnDie(Entity* self, Entity* killer) {
const auto myGroup = GeneralUtils::UTF16ToWTF8(self->GetVar<std::u16string>(u"spawner_name")); const auto myGroup = GeneralUtils::UTF16ToWTF8(self->GetVar<std::u16string>(u"spawner_name"));
int32_t pipeNum = 0; const auto pipeNum = GeneralUtils::TryParse<int32_t>(myGroup.substr(10, 1));
if (!GeneralUtils::TryParse<int32_t>(myGroup.substr(10, 1), pipeNum)) { if (!pipeNum) return;
return;
}
const auto pipeGroup = myGroup.substr(0, 10); const auto pipeGroup = myGroup.substr(0, 10);
const auto nextPipeNum = pipeNum + 1; const auto nextPipeNum = pipeNum.value() + 1;
const auto samePipeSpawners = Game::zoneManager->GetSpawnersByName(myGroup); const auto samePipeSpawners = Game::zoneManager->GetSpawnersByName(myGroup);
@ -37,7 +33,7 @@ void FvBrickPuzzleServer::OnDie(Entity* self, Entity* killer) {
samePipeSpawners[0]->Deactivate(); samePipeSpawners[0]->Deactivate();
} }
if (killer != nullptr && killer->IsPlayer()) { if (killer && killer->IsPlayer()) {
const auto nextPipe = pipeGroup + std::to_string(nextPipeNum); const auto nextPipe = pipeGroup + std::to_string(nextPipeNum);
const auto nextPipeSpawners = Game::zoneManager->GetSpawnersByName(nextPipe); const auto nextPipeSpawners = Game::zoneManager->GetSpawnersByName(nextPipe);

View File

@ -209,8 +209,7 @@ int main(int argc, char** argv) {
UserManager::Instance()->Initialize(); UserManager::Instance()->Initialize();
bool dontGenerateDCF = false; const bool dontGenerateDCF = GeneralUtils::TryParse<bool>(Game::config->GetValue("dont_generate_dcf")).value_or(false);
GeneralUtils::TryParse(Game::config->GetValue("dont_generate_dcf"), dontGenerateDCF);
Game::chatFilter = new dChatFilter(Game::assetManager->GetResPath().string() + "/chatplus_en_us", dontGenerateDCF); Game::chatFilter = new dChatFilter(Game::assetManager->GetResPath().string() + "/chatplus_en_us", dontGenerateDCF);
Game::server = new dServer(masterIP, ourPort, instanceID, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::World, Game::config, &Game::lastSignal, zoneID); Game::server = new dServer(masterIP, ourPort, instanceID, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::World, Game::config, &Game::lastSignal, zoneID);

View File

@ -214,9 +214,9 @@ void Level::ReadSceneObjectDataChunk(std::istream& file, Header& header) {
gating.major = 1; gating.major = 1;
gating.current = 10; gating.current = 10;
gating.minor = 64; gating.minor = 64;
GeneralUtils::TryParse<int32_t>(Game::config->GetValue("version_major"), gating.major); gating.major = GeneralUtils::TryParse<int32_t>(Game::config->GetValue("version_major")).value_or(gating.major);
GeneralUtils::TryParse<int32_t>(Game::config->GetValue("version_current"), gating.current); gating.current = GeneralUtils::TryParse<int32_t>(Game::config->GetValue("version_current")).value_or(gating.current);
GeneralUtils::TryParse<int32_t>(Game::config->GetValue("version_minor"), gating.minor); gating.minor = GeneralUtils::TryParse<int32_t>(Game::config->GetValue("version_minor")).value_or(gating.minor);
const auto zoneControlObject = Game::zoneManager->GetZoneControlObject(); const auto zoneControlObject = Game::zoneManager->GetZoneControlObject();
DluAssert(zoneControlObject != nullptr); DluAssert(zoneControlObject != nullptr);