diff --git a/Sdk/Include/ConfigConstants.h b/Sdk/Include/ConfigConstants.h new file mode 100644 index 0000000..1176b61 --- /dev/null +++ b/Sdk/Include/ConfigConstants.h @@ -0,0 +1,13 @@ +#pragma once + +namespace ConfigSections +{ + const char* const Network = "network"; +}; + +namespace ConfigKeys +{ + // Network + const char* const MasterServerHostName = "masterServerHostName"; + const char* const BannedPlayers = "bannedPlayers"; +} \ No newline at end of file diff --git a/Sdk/Include/ConfigEvents.h b/Sdk/Include/ConfigEvents.h new file mode 100644 index 0000000..9aa23d6 --- /dev/null +++ b/Sdk/Include/ConfigEvents.h @@ -0,0 +1,44 @@ +#pragma once + +/// +/// Event types for . +/// +enum class ConfigEventType +{ + None = 0, + + ConfigLoaded, + ConfigSaving +}; + +struct ConfigEvent +{ +public: + virtual ~ConfigEvent() = default; + ConfigEvent(ConfigEventType type) noexcept { this->type = type; } + +private: + ConfigEventType type; +}; + +struct ConfigLoadedEvent : ConfigEvent +{ + ConfigLoadedEvent(struct IConfig& config) noexcept + : ConfigEvent(ConfigEventType::ConfigLoaded), + config(config) + { + } + + struct IConfig& config; +}; + +struct ConfigSavingEvent : ConfigEvent +{ + ConfigSavingEvent(struct IConfig& config) noexcept + : ConfigEvent(ConfigEventType::ConfigSaving), + config(config) + { + } + + struct IConfig& config; +}; diff --git a/Sdk/Include/IComponent.h b/Sdk/Include/IComponent.h index e1b9009..bde23d8 100644 --- a/Sdk/Include/IComponent.h +++ b/Sdk/Include/IComponent.h @@ -3,7 +3,7 @@ #include // {779CF758-3E3F-4FEE-9513-60106522686A} -DEFINE_GUID(IID_IComponent, 0x779cf758, 0x3e3f, 0x4fee, 0x95, 0x13, 0x60, 0x10, 0x65, 0x22, 0x68, 0x6a); +inline const GUID IID_IComponent = { 0x779cf758, 0x3e3f, 0x4fee, 0x95, 0x13, 0x60, 0x10, 0x65, 0x22, 0x68, 0x6a }; /// /// Base interface for a game COM component. diff --git a/Sdk/Include/IComponentContainer.h b/Sdk/Include/IComponentContainer.h index 480157e..7e616b0 100644 --- a/Sdk/Include/IComponentContainer.h +++ b/Sdk/Include/IComponentContainer.h @@ -7,8 +7,7 @@ template using ComPtr = Microsoft::WRL::ComPtr; // {C942AA9B-C576-4D3F-A54F-B135B500E611} -DEFINE_GUID(IID_IComponentContainer, - 0xc942aa9b, 0xc576, 0x4d3f, 0xa5, 0x4f, 0xb1, 0x35, 0xb5, 0x0, 0xe6, 0x11); +inline const GUID IID_IComponentContainer = { 0xc942aa9b, 0xc576, 0x4d3f, 0xa5, 0x4f, 0xb1, 0x35, 0xb5, 0x0, 0xe6, 0x11 }; template struct TypedGet @@ -18,19 +17,24 @@ struct TypedGet { ComPtr temp; ComPtr pComponent = ((T*)this)->Get(__uuidof(TGet)); - HRESULT hr = pComponent.As(&temp); - if (FAILED(hr)) + if (pComponent) { - if (hr == E_NOINTERFACE) + HRESULT hr = pComponent.As(&temp); + if (FAILED(hr)) { - throw std::invalid_argument("The interface is not supported."); + if (hr == E_NOINTERFACE) + { + throw std::invalid_argument("The interface is not supported."); + } + + throw std::invalid_argument(fmt::format("Unknown exception {0:x} querying interface.", hr)); } - throw std::invalid_argument(fmt::format("Unknown exception {0:x} querying interface.", hr)); + pComponent.Detach(); + return temp; } - pComponent.Detach(); - return temp; + return ComPtr(); // Null } }; diff --git a/Sdk/Include/IConfig.h b/Sdk/Include/IConfig.h new file mode 100644 index 0000000..e5d05e6 --- /dev/null +++ b/Sdk/Include/IConfig.h @@ -0,0 +1,44 @@ +#pragma once + +#include +#include +#include +#include + +// {599E6624-694C-41B6-B354-62EEA1132041} +inline const GUID IID_IConfig = { 0x599e6624, 0x694c, 0x41b6, 0xb3, 0x54, 0x62, 0xee, 0xa1, 0x13, 0x20, 0x41 }; + +struct IConfig : IComponent, IEventSource +{ + virtual ~IConfig() = default; + + virtual void STDMETHODCALLTYPE Read() = 0; + + virtual void STDMETHODCALLTYPE Save() = 0; + + virtual float STDMETHODCALLTYPE GetFloat(const tstring_view& section, const tstring_view& setting) const = 0; + + virtual std::vector STDMETHODCALLTYPE GetFloatArray(const tstring_view& section, const tstring_view& setting) const = 0; + + virtual int STDMETHODCALLTYPE GetInteger(const tstring_view& section, const tstring_view& setting) const = 0; + + virtual std::vector STDMETHODCALLTYPE GetIntegerArray(const tstring_view& section, const tstring_view& setting) const = 0; + + virtual tstring STDMETHODCALLTYPE GetString(const tstring_view& section, const tstring_view& setting) const = 0; + + virtual std::vector STDMETHODCALLTYPE GetStringArray(const tstring_view& section, const tstring_view& setting) const = 0; + + virtual void STDMETHODCALLTYPE SetFloat(const tstring_view& section, const tstring_view& setting, float value) = 0; + + virtual void STDMETHODCALLTYPE SetFloatArray(const tstring_view& section, const tstring_view& setting, std::vector&& values) = 0; + + virtual void STDMETHODCALLTYPE SetInteger(const tstring_view& section, const tstring_view& setting, int value) = 0; + + virtual void STDMETHODCALLTYPE SetIntegerArray(const tstring_view& section, const tstring_view& setting, std::vector&& values) = 0; + + virtual void STDMETHODCALLTYPE SetString(const tstring_view& section, const tstring_view& setting, tstring_view value) = 0; + + virtual void STDMETHODCALLTYPE SetStringArray(const tstring_view& section, const tstring_view& setting, std::vector&& values) = 0; +}; + +struct DECLSPEC_UUID("{599E6624-694C-41B6-B354-62EEA1132041}") IConfig; \ No newline at end of file diff --git a/Sdk/Include/IEventSource.h b/Sdk/Include/IEventSource.h new file mode 100644 index 0000000..5951663 --- /dev/null +++ b/Sdk/Include/IEventSource.h @@ -0,0 +1,10 @@ +#pragma once + +template +struct IEventSource +{ + virtual ~IEventSource() = default; + + virtual UUID STDMETHODCALLTYPE Listen(TEventType event, std::function function) noexcept = 0; + virtual void STDMETHODCALLTYPE Unlisten(TEventType event, UUID uuid) noexcept = 0; +}; \ No newline at end of file diff --git a/Sdk/Include/IExceptionHandler.h b/Sdk/Include/IExceptionHandler.h new file mode 100644 index 0000000..0d7de6e --- /dev/null +++ b/Sdk/Include/IExceptionHandler.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +// {9C4C8F9C-D4C1-4749-A073-D710548D3154} +inline const GUID IID_IExceptionHandler = { 0x9c4c8f9c, 0xd4c1, 0x4749, 0xa0, 0x73, 0xd7, 0x10, 0x54, 0x8d, 0x31, 0x54 }; +struct IExceptionHandler : IComponent +{ + virtual ~IExceptionHandler() = default; + + virtual void STDMETHODCALLTYPE AttachToCurrentThread() = 0; + virtual void STDMETHODCALLTYPE DetachFromCurrentThread() = 0; + virtual void STDMETHODCALLTYPE Initialize() = 0; + virtual void STDMETHODCALLTYPE PostLoad() = 0; + virtual void STDMETHODCALLTYPE Shutdown() = 0; +}; + +struct DECLSPEC_UUID("{9C4C8F9C-D4C1-4749-A073-D710548D3154}") IExceptionHandler; \ No newline at end of file diff --git a/Sdk/Include/IGameServer.h b/Sdk/Include/IGameServer.h index 6fed479..2514417 100644 --- a/Sdk/Include/IGameServer.h +++ b/Sdk/Include/IGameServer.h @@ -4,18 +4,18 @@ #include #include #include +#include #include "GameServerEvents.h" #include "NetCommon.h" // {B2D67EE7-8063-488F-B3B9-E7DA675CB752} -DEFINE_GUID(IID_IGameServer, - 0xb2d67ee7, 0x8063, 0x488f, 0xb3, 0xb9, 0xe7, 0xda, 0x67, 0x5c, 0xb7, 0x52); +inline const GUID IID_IGameServer = { 0xb2d67ee7, 0x8063, 0x488f, 0xb3, 0xb9, 0xe7, 0xda, 0x67, 0x5c, 0xb7, 0x52 }; /// /// Defines an API for communicating with the game server. /// -struct IGameServer : IComponent +struct IGameServer : IComponent, IEventSource { virtual ~IGameServer() = default; @@ -32,10 +32,6 @@ struct IGameServer : IComponent virtual void STDMETHODCALLTYPE ChangeGameOption(GameOption option) = 0; virtual NetGameDetails STDMETHODCALLTYPE GetGameDetails() = 0; - - virtual UUID STDMETHODCALLTYPE Listen(GameServerEventType event, std::function function) noexcept = 0; - - virtual void STDMETHODCALLTYPE Unlisten(GameServerEventType event, UUID uuid) noexcept = 0; }; struct DECLSPEC_UUID("{B2D67EE7-8063-488F-B3B9-E7DA675CB752}") IGameServer; \ No newline at end of file diff --git a/Sdk/Include/IGameServerConsole.h b/Sdk/Include/IGameServerConsole.h index afe59c0..be2f128 100644 --- a/Sdk/Include/IGameServerConsole.h +++ b/Sdk/Include/IGameServerConsole.h @@ -5,8 +5,7 @@ #include // {3B2D43AC-2557-4C28-991D-A456B59D76CB} -DEFINE_GUID(IID_IGameServerConsole, - 0x3b2d43ac, 0x2557, 0x4c28, 0x99, 0x1d, 0xa4, 0x56, 0xb5, 0x9d, 0x76, 0xcb); +inline const GUID IID_IGameServerConsole = { 0x3b2d43ac, 0x2557, 0x4c28, 0x99, 0x1d, 0xa4, 0x56, 0xb5, 0x9d, 0x76, 0xcb }; /// /// Interface for dedicated server consoles. diff --git a/Sdk/Include/ITextLookupService.h b/Sdk/Include/ITextLookupService.h index 5280460..97416e2 100644 --- a/Sdk/Include/ITextLookupService.h +++ b/Sdk/Include/ITextLookupService.h @@ -7,8 +7,7 @@ enum class NetPlayerState; enum class GameTeam; // {770DEBD3-165D-4340-829D-5262F473FBE3} -DEFINE_GUID(IID_ITextLookupService, - 0x770debd3, 0x165d, 0x4340, 0x82, 0x9d, 0x52, 0x62, 0xf4, 0x73, 0xfb, 0xe3); +inline const GUID IID_ITextLookupService = { 0x770debd3, 0x165d, 0x4340, 0x82, 0x9d, 0x52, 0x62, 0xf4, 0x73, 0xfb, 0xe3 }; /// /// Service providing localization of text placeholders and friendly-name mappings of common enums. diff --git a/Sdk/Include/MasterServer/IGiantsApiClient.h b/Sdk/Include/MasterServer/IGiantsApiClient.h new file mode 100644 index 0000000..071c5d3 --- /dev/null +++ b/Sdk/Include/MasterServer/IGiantsApiClient.h @@ -0,0 +1,24 @@ +#pragma once + +#include + +#include +#include + +using njson = nlohmann::json; + +typedef std::future> ServerInfoFuture; + +// {EE129A81-0A86-49C4-8D23-A771A7350952} +inline const GUID IID_IGiantsApiClient = { 0xee129a81, 0xa86, 0x49c4, 0x8d, 0x23, 0xa7, 0x71, 0xa7, 0x35, 0x9, 0x52 }; + +struct IGiantsApiClient : IComponent +{ + virtual ~IGiantsApiClient() = default; + + virtual void STDMETHODCALLTYPE DeleteServerInformationAsync() = 0; + virtual ServerInfoFuture STDMETHODCALLTYPE GetServerInformationAsync() = 0; + virtual void STDMETHODCALLTYPE PostServerInformationAsync(const njson& requestBody) = 0; +}; + +struct DECLSPEC_UUID("{EE129A81-0A86-49C4-8D23-A771A7350952}") IGiantsApiClient; \ No newline at end of file diff --git a/Sdk/Include/MasterServer/PlayerInfoResponse.h b/Sdk/Include/MasterServer/PlayerInfoResponse.h new file mode 100644 index 0000000..530f292 --- /dev/null +++ b/Sdk/Include/MasterServer/PlayerInfoResponse.h @@ -0,0 +1,21 @@ +#pragma once + +using njson = nlohmann::json; + +struct PlayerInfoResponse +{ + explicit PlayerInfoResponse(const njson& playerInfoResponse) + { + index = playerInfoResponse["index"]; + name = playerInfoResponse["name"]; + frags = playerInfoResponse["frags"]; + deaths = playerInfoResponse["deaths"]; + teamName = playerInfoResponse["teamName"]; + } + + int index; + std::string name; + int frags; + int deaths; + std::string teamName; +}; diff --git a/Sdk/Include/MasterServer/ServerInfoResponse.h b/Sdk/Include/MasterServer/ServerInfoResponse.h new file mode 100644 index 0000000..6ed9302 --- /dev/null +++ b/Sdk/Include/MasterServer/ServerInfoResponse.h @@ -0,0 +1,51 @@ +#pragma once + +#include + +using njson = nlohmann::json; + +struct ServerInfoResponse +{ + explicit ServerInfoResponse(const njson& serverInfoResponse) + { + hostIp = serverInfoResponse["hostIpAddress"]; + gameName = serverInfoResponse["gameName"]; + + njson versionJson = serverInfoResponse["version"]; + version.build = versionJson["build"]; + version.major = versionJson["major"]; + version.minor = versionJson["minor"]; + version.revision = versionJson["revision"]; + + sessionName = serverInfoResponse["sessionName"]; + port = serverInfoResponse["port"]; + mapName = serverInfoResponse["mapName"]; + gameType = serverInfoResponse["gameType"]; + numPlayers = serverInfoResponse["numPlayers"]; + gameState = serverInfoResponse["gameState"]; + timeLimit = serverInfoResponse["timeLimit"]; + fragLimit = serverInfoResponse["fragLimit"]; + teamFragLimit = serverInfoResponse["teamFragLimit"]; + firstBaseComplete = serverInfoResponse["firstBaseComplete"]; + + for (const auto& playerInfoResponse : serverInfoResponse["playerInfo"]) + { + playerInfo.emplace_back(PlayerInfoResponse(playerInfoResponse)); + } + } + + std::string hostIp; + std::string gameName; + Version version; + std::string sessionName; + int port = 0; + std::string mapName; + std::string gameType; + int numPlayers = 0; + std::string gameState; + int timeLimit = 0; + int fragLimit = 0; + int teamFragLimit = 0; + bool firstBaseComplete = false; + std::vector playerInfo; +}; diff --git a/Sdk/Include/Version.h b/Sdk/Include/Version.h new file mode 100644 index 0000000..cad8c6a --- /dev/null +++ b/Sdk/Include/Version.h @@ -0,0 +1,9 @@ +#pragma once + +struct Version +{ + int major; + int minor; + int build; + int revision; +};