From c7481e976f86e1f60f034ecf27e399f508ceb341 Mon Sep 17 00:00:00 2001 From: Nick Blakely Date: Wed, 26 Aug 2020 23:10:21 -0700 Subject: [PATCH] Update patcher and add SDK includes. --- GPatch/GPatch.nsi | 20 +++-- Sdk/Include/ComponentBase.h | 119 ++++++++++++++++++++++++++++++ Sdk/Include/GameServerEvents.h | 52 +++++++++++++ Sdk/Include/IComponent.h | 15 ++++ Sdk/Include/IComponentContainer.h | 57 ++++++++++++++ Sdk/Include/IGameServer.h | 41 ++++++++++ Sdk/Include/IGameServerConsole.h | 24 ++++++ Sdk/Include/ITextLookupService.h | 27 +++++++ Sdk/Include/NetCommon.h | 110 +++++++++++++++++++++++++++ 9 files changed, 457 insertions(+), 8 deletions(-) create mode 100644 Sdk/Include/ComponentBase.h create mode 100644 Sdk/Include/GameServerEvents.h create mode 100644 Sdk/Include/IComponent.h create mode 100644 Sdk/Include/IComponentContainer.h create mode 100644 Sdk/Include/IGameServer.h create mode 100644 Sdk/Include/IGameServerConsole.h create mode 100644 Sdk/Include/ITextLookupService.h create mode 100644 Sdk/Include/NetCommon.h diff --git a/GPatch/GPatch.nsi b/GPatch/GPatch.nsi index f0e8cc8..d5d4d1f 100644 --- a/GPatch/GPatch.nsi +++ b/GPatch/GPatch.nsi @@ -42,7 +42,7 @@ SetCompressor /SOLID lzma ; MUI end ------ Name "${PRODUCT_NAME} ${PRODUCT_VERSION}" -OutFile "Output\GPatch1_498_181_0.exe" +OutFile "Output\GPatch1_498_201_0.exe" InstallDir "$PROGRAMFILES\Giants\" InstallDirRegKey HKCU "SOFTWARE\PlanetMoon\Giants" "DestDir" ShowInstDetails hide @@ -61,18 +61,21 @@ Section ExecWait "$INSTDIR\Redist\dxsetup.exe /silent" $0 ${If} $0 != 0 - MessageBox MB_OK "Setup failed to update DirectX ($0). Please visit www.microsoft.com and download the latest version of the DirectX end user redistributable." - RMDir /r "$INSTDIR\Redist" ; Delete temporary files - ;return - ${Else} - RMDir /r "$INSTDIR\Redist" ; Delete temporary files + MessageBox MB_OK "Setup failed to update DirectX ($0). Please visit www.microsoft.com and download the latest version of the DirectX end user redistributable." ${EndIf} + ExecWait "$INSTDIR\Redist\VC_redist.x86.exe /install /passive /norestart" $0 + ${If} $0 != 0 + MessageBox MB_OK "Setup failed to install the Visual C++ Runtime. Please visit www.microsoft.com and download the latest version of the Visual C++ redistributable." + ${EndIf} + + RMDir /r "$INSTDIR\Redist" ; Delete temporary files + ; Delete old files Delete $INSTDIR\bin\Shaders\*.* Delete $INSTDIR\gg_dx7r.dll Delete $INSTDIR\gg_dx8r.dll - Delete $INSTDIR\gg_dx9r.dll + Delete $INSTDIR\gg_dx9r.dll Delete $INSTDIR\Giants.exe Delete $INSTDIR\GiantsMain.exe Delete $INSTDIR\*.vso @@ -88,7 +91,8 @@ Section Delete $INSTDIR\bin\worldlist5.bin Delete $INSTDIR\bin\mappack1.gzp Delete $INSTDIR\bin\A-GRM1.gzp - + Delete $INSTDIR\bin\GData.gbt + Delete $INSTDIR\bin\GData.h SectionEnd diff --git a/Sdk/Include/ComponentBase.h b/Sdk/Include/ComponentBase.h new file mode 100644 index 0000000..896fc0f --- /dev/null +++ b/Sdk/Include/ComponentBase.h @@ -0,0 +1,119 @@ +#pragma once + +#include +#include +#include +#include + +#include +#include + +#pragma warning (disable:26487) // Disable LIFETIMES_FUNCTION_POSTCONDITION_VIOLATION: not COM-aware + +template using NthTypeOf = +typename std::tuple_element>::type; + +/// +// Base class for game components, automatically implements IUnknown. +// On construction, registers self with the component container (which is guaranteed to exist +// for the lifetime of the game process, hence the naked pointer stored in this type). +// On final release, the component is removed from the container. +// +// Note: following C#'s example here, we don't allow multiple inheritance. +// The first interface is the "primary" interface that we inherit from. The additional interfaces +// expanded from the parameter pack are registered with the container, but not inherited. +/// +/// The interfaces that this component can be located by. +template +struct ComponentBase : public NthTypeOf<0, TInterfaces...> +{ + static constexpr std::array ImplementedIids = { { __uuidof(TInterfaces)... } }; + ComponentBase(IComponentContainer* container) + { + m_pContainer = container; + + AddInterfaces(); + } + + virtual ~ComponentBase() + { + RemoveInterfaces(); + } + + HRESULT STDMETHODCALLTYPE QueryInterface( + const GUID& riid, + _COM_Outptr_ void __RPC_FAR* __RPC_FAR* ppvObject) override + { + if (!ppvObject) + { + return E_INVALIDARG; + } + + *ppvObject = nullptr; + + if (riid == IID_IUnknown + || riid == IID_IComponent + || IsExplicitlyImplementedInterface(riid)) + { + *ppvObject = this; + return S_OK; + } + + return E_NOINTERFACE; + } + + unsigned long STDMETHODCALLTYPE AddRef() override + { + InterlockedIncrement(&m_refs); + return m_refs; + } + + unsigned long STDMETHODCALLTYPE Release() override + { + const unsigned long refCount = InterlockedDecrement(&m_refs); + assert(refCount >= 0); + if (refCount == 0) + { + delete this; + } + + return refCount; + } + +protected: + IComponentContainer* m_pContainer = nullptr; + +private: + void AddInterfaces() + { + for (const auto& implementedIid : ImplementedIids) + { + m_pContainer->Add(implementedIid, this); + } + } + + bool IsExplicitlyImplementedInterface(const GUID& iid) noexcept + { + for (const auto& implementedIid : ImplementedIids) + { + if (IsEqualGUID(implementedIid, iid)) + { + return true; + } + } + + return false; + } + + void RemoveInterfaces() noexcept + { + for (const auto& implementedIid : ImplementedIids) + { + m_pContainer->Remove(implementedIid); + } + } + + unsigned long m_refs = 0; +}; + +#pragma warning (default:26487) \ No newline at end of file diff --git a/Sdk/Include/GameServerEvents.h b/Sdk/Include/GameServerEvents.h new file mode 100644 index 0000000..6965173 --- /dev/null +++ b/Sdk/Include/GameServerEvents.h @@ -0,0 +1,52 @@ +#pragma once + +#include "NetCommon.h" + +/// +/// Event types for . +/// +enum class GameServerEventType +{ + None = 0, + + PlayerConnected = 1, + PlayerDisconnected = 2, + ChatMessage = 3, + WorldLoaded = 4, +}; + +struct GameServerEvent +{ +public: + virtual ~GameServerEvent() = default; + GameServerEvent(GameServerEventType type) noexcept { this->type = type; } + +private: + GameServerEventType type; +}; + +struct PlayerConnectedEvent : GameServerEvent +{ + PlayerConnectedEvent() noexcept : GameServerEvent(GameServerEventType::PlayerConnected) { } + + std::unique_ptr info; +}; + +struct PlayerDisconnectedEvent : GameServerEvent +{ + PlayerDisconnectedEvent() noexcept : GameServerEvent(GameServerEventType::PlayerDisconnected) { } + + std::unique_ptr info; +}; + +struct ChatMessageEvent : GameServerEvent +{ + ChatMessageEvent() noexcept : GameServerEvent(GameServerEventType::ChatMessage) { } + + std::string_view message; +}; + +struct WorldLoadedEvent : GameServerEvent +{ + WorldLoadedEvent() noexcept : GameServerEvent(GameServerEventType::WorldLoaded) { } +}; diff --git a/Sdk/Include/IComponent.h b/Sdk/Include/IComponent.h new file mode 100644 index 0000000..e1b9009 --- /dev/null +++ b/Sdk/Include/IComponent.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +// {779CF758-3E3F-4FEE-9513-60106522686A} +DEFINE_GUID(IID_IComponent, 0x779cf758, 0x3e3f, 0x4fee, 0x95, 0x13, 0x60, 0x10, 0x65, 0x22, 0x68, 0x6a); + +/// +/// Base interface for a game COM component. +/// +struct IComponent : public IUnknown +{ +}; + +struct DECLSPEC_UUID("{779CF758-3E3F-4FEE-9513-60106522686A}") IComponent; \ No newline at end of file diff --git a/Sdk/Include/IComponentContainer.h b/Sdk/Include/IComponentContainer.h new file mode 100644 index 0000000..480157e --- /dev/null +++ b/Sdk/Include/IComponentContainer.h @@ -0,0 +1,57 @@ +#pragma once + +#include +#include + +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); + +template +struct TypedGet +{ + template + ComPtr Get() + { + ComPtr temp; + ComPtr pComponent = ((T*)this)->Get(__uuidof(TGet)); + HRESULT hr = pComponent.As(&temp); + if (FAILED(hr)) + { + 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)); + } + + pComponent.Detach(); + return temp; + } +}; + +/// +/// Container for game components. +/// Facilitates resource acquisition across module boundaries, and interop with .NET code. +/// +struct IComponentContainer : public TypedGet +{ + virtual ~IComponentContainer() { } + + virtual void Add(const IID& iid, IComponent* component) = 0; + virtual ComPtr Get(const IID& iid) noexcept = 0; + virtual void Remove(const IID& iid) noexcept = 0; + virtual void ReleaseAll() = 0; + + template + ComPtr Get() + { + return TypedGet::Get(); + } +}; + +struct DECLSPEC_UUID("{C942AA9B-C576-4D3F-A54F-B135B500E611}") IComponentContainer; \ No newline at end of file diff --git a/Sdk/Include/IGameServer.h b/Sdk/Include/IGameServer.h new file mode 100644 index 0000000..6fed479 --- /dev/null +++ b/Sdk/Include/IGameServer.h @@ -0,0 +1,41 @@ +#pragma once + +#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); + +/// +/// Defines an API for communicating with the game server. +/// +struct IGameServer : IComponent +{ + virtual ~IGameServer() = default; + + virtual void STDMETHODCALLTYPE SendChatMessage(const std::string_view& message, ChatColor color, int flags, PlayerIndex indexTo) = 0; + + virtual void STDMETHODCALLTYPE BanPlayer(int index) = 0; + + virtual void STDMETHODCALLTYPE KickPlayer(int index, KickReason reason) = 0; + + virtual PlayerInfo STDMETHODCALLTYPE GetPlayer(int index) = 0; + + virtual std::vector STDMETHODCALLTYPE GetPlayers() = 0; + + 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 new file mode 100644 index 0000000..afe59c0 --- /dev/null +++ b/Sdk/Include/IGameServerConsole.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include +#include + +// {3B2D43AC-2557-4C28-991D-A456B59D76CB} +DEFINE_GUID(IID_IGameServerConsole, + 0x3b2d43ac, 0x2557, 0x4c28, 0x99, 0x1d, 0xa4, 0x56, 0xb5, 0x9d, 0x76, 0xcb); + +/// +/// Interface for dedicated server consoles. +/// +struct IGameServerConsole : IComponent +{ + ~IGameServerConsole() = default; + + virtual void STDMETHODCALLTYPE CloseDialog() = 0; + virtual void STDMETHODCALLTYPE ShowDialog() = 0; + + static const int ApiVersion = 1; +}; + +struct DECLSPEC_UUID("{3B2D43AC-2557-4C28-991D-A456B59D76CB}") IGameServerConsole; \ No newline at end of file diff --git a/Sdk/Include/ITextLookupService.h b/Sdk/Include/ITextLookupService.h new file mode 100644 index 0000000..5280460 --- /dev/null +++ b/Sdk/Include/ITextLookupService.h @@ -0,0 +1,27 @@ +#pragma once + +#include +#include + +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); + +/// +/// Service providing localization of text placeholders and friendly-name mappings of common enums. +/// +struct ITextLookupService : public IComponent +{ + virtual std::string STDMETHODCALLTYPE GetLocalized(std::string_view lookup) = 0; + + virtual std::string STDMETHODCALLTYPE GetNetPlayerStateName(enum class NetPlayerState state) = 0; + + virtual std::string STDMETHODCALLTYPE GetGameTeamName(GameTeam team) = 0; + + virtual std::string STDMETHODCALLTYPE GetPlayerTeamName(int teamIndex) = 0; +}; + +struct DECLSPEC_UUID("{770DEBD3-165D-4340-829D-5262F473FBE3}") ITextLookupService; diff --git a/Sdk/Include/NetCommon.h b/Sdk/Include/NetCommon.h new file mode 100644 index 0000000..6fa358d --- /dev/null +++ b/Sdk/Include/NetCommon.h @@ -0,0 +1,110 @@ +#pragma once + +#include + +typedef int PlayerIndex; +typedef int PlayerTeamIndex; + +enum class ChatColor : int +{ + None = 0, + + System = 1, + PlayerAll = 2, + PlayerTeam = 3, + Smartie = 4, + Disciple = 5, + Mission = 6 +}; + +enum class GameOption : unsigned char +{ + DamageTeammates, // Toggle damage teammates on/off + PhFF, // Toggle party house friendly fire on/off + PMarkers, // Toggle player marker size + EndGame, // End the game immediately + Detente, // Add time to detente + Smarties, // Change max. smarties + Vimps, // Toggle vimps on/off + TeamChanges, // Toggle team changes on/off + PlayerScoreLimit, // Change player score limit + TeamScoreLimit, // Change team score limit +}; + +enum class KickReason +{ + Removed, + LostConnection +}; + +enum class NetPlayerState +{ + None = 0, + + Setup = 1, + HostConfiguring = 2, + HostStartLoading = 3, + HostWorldLoading = 4, + HostPreloading = 5, + JoinWorldWaiting = 6, + JoinStartLoading = 7, + JoinWorldLoading = 8, + JoinPreloading = 9, + JoinObjectWaiting = 10, + JoinObjectLoading = 11, + Ready = 12, + Server = 13, + Active = 14, +}; + +enum class GameTeam +{ + None = -1, // -1 for backwards compatibility + + MvM = 0, + MvMvM, + RvR, + MvR, + MvRvK, + MvK, + RvK, +}; + +struct PlayerInfo +{ + PlayerIndex index = 0; + std::string name; + float score = 0; + float deaths = 0; + int ping = 0; + PlayerTeamIndex team = 0; + bool host = false; + NetPlayerState state = NetPlayerState::None; +}; + +struct NetGameSettings +{ + bool allowNewPlayers = false; + bool damageTeammates = false; + int pointsPerKill = 0; + int pointsPerCapture = 0; + int capturePreventCountInMinutes = 0; + float capturePreventCountTime = 0.0f; + int maxPlayers = 0; + bool lockTeams = false; + int smartieDifficulty = 0; + int vimpMeatDifficulty = 0; + bool vimpsDisabled = false; + bool weaponAvailabilityModified = false; + int worldId = 0; +}; + +struct NetGameDetails +{ + // User-adjustable settings for the current game. + NetGameSettings settings; + + std::string worldName; + std::string teamTypeName; + std::string gameTypeName; +}; \ No newline at end of file