diff --git a/GiantsTools.sln b/GiantsTools.sln index 4b3166b..91ea984 100644 --- a/GiantsTools.sln +++ b/GiantsTools.sln @@ -25,6 +25,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Plugins", "Plugins", "{0801 EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "imp_gbs", "Plugins\imp_gbs\imp_gbs.vcxproj", "{448F061E-AE05-4E06-84A1-C95660FD048C}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Giants.Services.Tests", "Giants.Services.Tests\Giants.Services.Tests.csproj", "{2AFB71CA-8313-472E-B242-0517343764B4}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ServerConsole", "ServerConsoleExample\ServerConsole.vcxproj", "{8AEE9CFF-0E24-498F-B60A-627A7F4A727D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -277,6 +281,52 @@ Global {448F061E-AE05-4E06-84A1-C95660FD048C}.ReleaseBeta|x64.Build.0 = Release|x64 {448F061E-AE05-4E06-84A1-C95660FD048C}.ReleaseBeta|x86.ActiveCfg = Release|Win32 {448F061E-AE05-4E06-84A1-C95660FD048C}.ReleaseBeta|x86.Build.0 = Release|Win32 + {2AFB71CA-8313-472E-B242-0517343764B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2AFB71CA-8313-472E-B242-0517343764B4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2AFB71CA-8313-472E-B242-0517343764B4}.Debug|x64.ActiveCfg = Debug|Any CPU + {2AFB71CA-8313-472E-B242-0517343764B4}.Debug|x64.Build.0 = Debug|Any CPU + {2AFB71CA-8313-472E-B242-0517343764B4}.Debug|x86.ActiveCfg = Debug|Any CPU + {2AFB71CA-8313-472E-B242-0517343764B4}.Debug|x86.Build.0 = Debug|Any CPU + {2AFB71CA-8313-472E-B242-0517343764B4}.DebugBeta|Any CPU.ActiveCfg = Debug|Any CPU + {2AFB71CA-8313-472E-B242-0517343764B4}.DebugBeta|Any CPU.Build.0 = Debug|Any CPU + {2AFB71CA-8313-472E-B242-0517343764B4}.DebugBeta|x64.ActiveCfg = Debug|Any CPU + {2AFB71CA-8313-472E-B242-0517343764B4}.DebugBeta|x64.Build.0 = Debug|Any CPU + {2AFB71CA-8313-472E-B242-0517343764B4}.DebugBeta|x86.ActiveCfg = Debug|Any CPU + {2AFB71CA-8313-472E-B242-0517343764B4}.DebugBeta|x86.Build.0 = Debug|Any CPU + {2AFB71CA-8313-472E-B242-0517343764B4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2AFB71CA-8313-472E-B242-0517343764B4}.Release|Any CPU.Build.0 = Release|Any CPU + {2AFB71CA-8313-472E-B242-0517343764B4}.Release|x64.ActiveCfg = Release|Any CPU + {2AFB71CA-8313-472E-B242-0517343764B4}.Release|x64.Build.0 = Release|Any CPU + {2AFB71CA-8313-472E-B242-0517343764B4}.Release|x86.ActiveCfg = Release|Any CPU + {2AFB71CA-8313-472E-B242-0517343764B4}.Release|x86.Build.0 = Release|Any CPU + {2AFB71CA-8313-472E-B242-0517343764B4}.ReleaseBeta|Any CPU.ActiveCfg = Release|Any CPU + {2AFB71CA-8313-472E-B242-0517343764B4}.ReleaseBeta|Any CPU.Build.0 = Release|Any CPU + {2AFB71CA-8313-472E-B242-0517343764B4}.ReleaseBeta|x64.ActiveCfg = Release|Any CPU + {2AFB71CA-8313-472E-B242-0517343764B4}.ReleaseBeta|x64.Build.0 = Release|Any CPU + {2AFB71CA-8313-472E-B242-0517343764B4}.ReleaseBeta|x86.ActiveCfg = Release|Any CPU + {2AFB71CA-8313-472E-B242-0517343764B4}.ReleaseBeta|x86.Build.0 = Release|Any CPU + {8AEE9CFF-0E24-498F-B60A-627A7F4A727D}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {8AEE9CFF-0E24-498F-B60A-627A7F4A727D}.Debug|x64.ActiveCfg = Debug|x64 + {8AEE9CFF-0E24-498F-B60A-627A7F4A727D}.Debug|x64.Build.0 = Debug|x64 + {8AEE9CFF-0E24-498F-B60A-627A7F4A727D}.Debug|x86.ActiveCfg = Debug|Win32 + {8AEE9CFF-0E24-498F-B60A-627A7F4A727D}.Debug|x86.Build.0 = Debug|Win32 + {8AEE9CFF-0E24-498F-B60A-627A7F4A727D}.DebugBeta|Any CPU.ActiveCfg = Debug|Win32 + {8AEE9CFF-0E24-498F-B60A-627A7F4A727D}.DebugBeta|Any CPU.Build.0 = Debug|Win32 + {8AEE9CFF-0E24-498F-B60A-627A7F4A727D}.DebugBeta|x64.ActiveCfg = Debug|x64 + {8AEE9CFF-0E24-498F-B60A-627A7F4A727D}.DebugBeta|x64.Build.0 = Debug|x64 + {8AEE9CFF-0E24-498F-B60A-627A7F4A727D}.DebugBeta|x86.ActiveCfg = Debug|Win32 + {8AEE9CFF-0E24-498F-B60A-627A7F4A727D}.DebugBeta|x86.Build.0 = Debug|Win32 + {8AEE9CFF-0E24-498F-B60A-627A7F4A727D}.Release|Any CPU.ActiveCfg = Release|Win32 + {8AEE9CFF-0E24-498F-B60A-627A7F4A727D}.Release|x64.ActiveCfg = Release|x64 + {8AEE9CFF-0E24-498F-B60A-627A7F4A727D}.Release|x64.Build.0 = Release|x64 + {8AEE9CFF-0E24-498F-B60A-627A7F4A727D}.Release|x86.ActiveCfg = Release|Win32 + {8AEE9CFF-0E24-498F-B60A-627A7F4A727D}.Release|x86.Build.0 = Release|Win32 + {8AEE9CFF-0E24-498F-B60A-627A7F4A727D}.ReleaseBeta|Any CPU.ActiveCfg = Debug|Win32 + {8AEE9CFF-0E24-498F-B60A-627A7F4A727D}.ReleaseBeta|Any CPU.Build.0 = Debug|Win32 + {8AEE9CFF-0E24-498F-B60A-627A7F4A727D}.ReleaseBeta|x64.ActiveCfg = Release|x64 + {8AEE9CFF-0E24-498F-B60A-627A7F4A727D}.ReleaseBeta|x64.Build.0 = Release|x64 + {8AEE9CFF-0E24-498F-B60A-627A7F4A727D}.ReleaseBeta|x86.ActiveCfg = Release|Win32 + {8AEE9CFF-0E24-498F-B60A-627A7F4A727D}.ReleaseBeta|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Sdk/Include/DataTypes.h b/Sdk/Include/DataTypes.h new file mode 100644 index 0000000..638b576 --- /dev/null +++ b/Sdk/Include/DataTypes.h @@ -0,0 +1,165 @@ +#pragma once + +#include +#include +#include +#include +#include + +////////////////////////////////////////////////////////////////////////////////////// +// Basic game data types and macros + +typedef unsigned int uint; +typedef unsigned char UBYTE; +typedef signed char SBYTE; +typedef unsigned short UWORD; +typedef int BOOL; +typedef unsigned long ULONG; +typedef unsigned long DWORD; +typedef std::int64_t int64; +typedef std::uint64_t uint64; +#ifdef UNICODE +typedef std::wstring tstring; +typedef std::wstring_view tstring_view; +#else +typedef std::string tstring; +typedef std::string_view tstring_view; +#endif + +#define countof(array) (sizeof((array)) / sizeof((array)[0])) + +#define FlagSet(b, f) ((b) |= (f)) +#define FlagClear(b, f) ((b) &= ~(f)) +#define FlagIsClear(b, f) (!FlagIsSet(b, f)) +#define FlagFlip(b, f) ((b) ^= (f)) +#define FlagIsSet(b, f) (((b) & (f)) != 0) + +////////////////////////////////////////////////////////////////////////////////////// +// Vectors + +struct P3D +{ + float x; + float y; + float z; + + inline const P3D& operator -= (const P3D& rhs) + { + x -= rhs.x; + y -= rhs.y; + z -= rhs.z; + + return *this; + } + + inline const P3D& operator += (const P3D& rhs) + { + x += rhs.x; + y += rhs.y; + z += rhs.z; + + return *this; + } + + inline P3D operator - (const P3D& rhs) + { + P3D result; + + result.x = x - rhs.x; + result.y = y - rhs.y; + result.z = z - rhs.z; + + return result; + } + + inline P3D Cross(const P3D& v2) + { + P3D result; + + result.x = y * v2.z - z * v2.y; + result.y = z * v2.x - x * v2.z; + result.z = x * v2.y - y * v2.x; + + return result; + } + + inline float Dot(const P3D& v2) + { + return x * v2.x + y * v2.y + z * v2.z; + } + + inline float Length() + { + return (float)(sqrt(x * x + y * y + z * z)); + } + + inline P3D Scale(float scale) + { + x *= scale; + y *= scale; + z *= scale; + + return *this; + } + + inline P3D Normalize() + { + const float length = Length(); + P3D normalized = *this; + + float factor = 0.0f; + if (length) + { + factor = 1 / length; + } + else + { + factor = 1.0f; + } + + normalized.x *= factor; + normalized.y *= factor; + normalized.z *= factor; + + return normalized; + } + + bool IsNaN() const + { + return (_isnan(x) || _isnan(y) || _isnan(z)); + } + + bool Finite() const + { + return (_finite(x) && _finite(y) && _finite(z)); + } +}; + +#pragma pack (push, 1) +// Optimized 3D vector for network packets. +struct NetP3D +{ + short x, y, z; +}; +#pragma pack (pop) + +////////////////////////////////////////////////////////////////////////////////////// + +struct RGBFloat +{ + float r{}; + float g{}; + float b{}; +}; + +struct VertRGB +{ + unsigned char r; + unsigned char g; + unsigned char b; +}; + +struct UV +{ + float u, v; +}; \ No newline at end of file diff --git a/Sdk/Include/GameServerEvents.h b/Sdk/Include/GameServerEvents.h index 6965173..44e2c2a 100644 --- a/Sdk/Include/GameServerEvents.h +++ b/Sdk/Include/GameServerEvents.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "NetCommon.h" /// @@ -29,21 +31,22 @@ struct PlayerConnectedEvent : GameServerEvent { PlayerConnectedEvent() noexcept : GameServerEvent(GameServerEventType::PlayerConnected) { } - std::unique_ptr info; + std::shared_ptr info; }; struct PlayerDisconnectedEvent : GameServerEvent { PlayerDisconnectedEvent() noexcept : GameServerEvent(GameServerEventType::PlayerDisconnected) { } - std::unique_ptr info; + std::shared_ptr info; }; struct ChatMessageEvent : GameServerEvent { ChatMessageEvent() noexcept : GameServerEvent(GameServerEventType::ChatMessage) { } - std::string_view message; + tstring_view message{}; + PlayerIndex senderIndex{}; }; struct WorldLoadedEvent : GameServerEvent diff --git a/Sdk/Include/IGameServer.h b/Sdk/Include/IGameServer.h index 2514417..33c8792 100644 --- a/Sdk/Include/IGameServer.h +++ b/Sdk/Include/IGameServer.h @@ -3,6 +3,8 @@ #include #include #include + +#include #include #include @@ -19,19 +21,60 @@ struct IGameServer : IComponent, IEventSource + /// Sends a chat message to all players or to a specified player. + /// + /// The chat message. + /// Text color. + /// Flags for the message. + /// The index to send the message to. If 0, it will be sent to all players. + virtual void STDMETHODCALLTYPE SendChatMessage(const tstring_view& message, ChatColor color, int flags, PlayerIndex indexTo) = 0; + /// + /// Bans the player at the specified index. + /// + /// The player index. + /// virtual void STDMETHODCALLTYPE BanPlayer(int index) = 0; + /// + /// Kicks the player at the specified index. + /// + /// The player index. + /// The reason for kicking the player. + /// virtual void STDMETHODCALLTYPE KickPlayer(int index, KickReason reason) = 0; - virtual PlayerInfo STDMETHODCALLTYPE GetPlayer(int index) = 0; + /// + /// Gets player data for the specified index. + /// + /// The zero-based player index. + /// std::out_of_range + virtual const std::shared_ptr STDMETHODCALLTYPE GetPlayer(int index) const = 0; - virtual std::vector STDMETHODCALLTYPE GetPlayers() = 0; + /// + /// Gets data for all players in the current game. + /// + virtual std::vector> STDMETHODCALLTYPE GetPlayers() const = 0; + /// + /// Toggles or increments the specified game option. + /// Note: the behavior of this method is the same as changing an option from the F1 in-game menu. + /// + /// + /// virtual void STDMETHODCALLTYPE ChangeGameOption(GameOption option) = 0; - virtual NetGameDetails STDMETHODCALLTYPE GetGameDetails() = 0; + /// + /// Gets details for the current game. + /// + virtual const std::shared_ptr STDMETHODCALLTYPE GetGameDetails() const = 0; + + /// + /// Modifies the settings for the current game. + /// + /// The game details. + virtual void STDMETHODCALLTYPE ChangeGameDetails(const NetGameDetails& gameDetails) = 0; }; struct DECLSPEC_UUID("{B2D67EE7-8063-488F-B3B9-E7DA675CB752}") IGameServer; \ No newline at end of file diff --git a/Sdk/Include/ITextLookupService.h b/Sdk/Include/ITextLookupService.h index 97416e2..12f05a4 100644 --- a/Sdk/Include/ITextLookupService.h +++ b/Sdk/Include/ITextLookupService.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -14,7 +15,7 @@ inline const GUID IID_ITextLookupService = { 0x770debd3, 0x165d, 0x4340, 0x82, 0 /// struct ITextLookupService : public IComponent { - virtual std::string STDMETHODCALLTYPE GetLocalized(std::string_view lookup) = 0; + virtual std::string STDMETHODCALLTYPE GetLocalized(tstring_view lookup) = 0; virtual std::string STDMETHODCALLTYPE GetNetPlayerStateName(enum class NetPlayerState state) = 0; diff --git a/ServerConsoleExample/ServerConsole.vcxproj b/ServerConsoleExample/ServerConsole.vcxproj index dc0c63e..ac9dcf4 100644 --- a/ServerConsoleExample/ServerConsole.vcxproj +++ b/ServerConsoleExample/ServerConsole.vcxproj @@ -93,6 +93,9 @@ + + true + Use @@ -100,7 +103,7 @@ true WIN32;_WINDOWS;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;_DEBUG;_USRDLL;%(PreprocessorDefinitions) pch.h - ..\..\Sdk\Include + ..\Sdk\Include true stdcpplatest MultiThreadedDebugDLL @@ -154,7 +157,7 @@ true WIN32;_WINDOWS;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;NDEBUG;_USRDLL;%(PreprocessorDefinitions) pch.h - ..\..\Sdk\Include + ..\Sdk\Include true stdcpplatest MultiThreadedDLL diff --git a/ServerConsoleExample/ServerDialog.cpp b/ServerConsoleExample/ServerDialog.cpp index c6a78d0..2305716 100644 --- a/ServerConsoleExample/ServerDialog.cpp +++ b/ServerConsoleExample/ServerDialog.cpp @@ -132,7 +132,7 @@ void ServerDialog::RefreshPlayers() const auto& pGameServer = m_pContainer->Get(); for (const auto& player : pGameServer->GetPlayers()) { - if (player.host) + if (player->host) { continue; // Skip host player } @@ -140,14 +140,14 @@ void ServerDialog::RefreshPlayers() LVITEM item{}; item.cColumns = NumColumns; item.mask = LVIF_COLUMNS | LVIF_PARAM; - item.lParam = player.index; + item.lParam = player->index; const int index = PlayersListCtrl.InsertItem(&item); - PlayersListCtrl.SetItemText(index, 0, player.name.c_str()); - PlayersListCtrl.SetItemText(index, 1, pTextLookupService->GetNetPlayerStateName(player.state).c_str()); - PlayersListCtrl.SetItemText(index, 2, fmt::format(_T("{0}"), player.ping).c_str()); - PlayersListCtrl.SetItemText(index, 3, fmt::format(_T("{0}"), player.score).c_str()); - PlayersListCtrl.SetItemText(index, 4, pTextLookupService->GetPlayerTeamName(player.team).c_str()); + PlayersListCtrl.SetItemText(index, 0, player->name.c_str()); + PlayersListCtrl.SetItemText(index, 1, pTextLookupService->GetNetPlayerStateName(player->state).c_str()); + PlayersListCtrl.SetItemText(index, 2, fmt::format(_T("{0}"), player->ping).c_str()); + PlayersListCtrl.SetItemText(index, 3, fmt::format(_T("{0}"), player->score).c_str()); + PlayersListCtrl.SetItemText(index, 4, pTextLookupService->GetPlayerTeamName(player->team).c_str()); } PlayersListCtrl.SetSelectionMark(savedSelection); @@ -181,7 +181,7 @@ void ServerDialog::HandleWorldLoaded(const GameServerEvent& event) const auto& pGameServer = m_pContainer->Get(); - NetGameDetails details = pGameServer->GetGameDetails(); + auto details = pGameServer->GetGameDetails(); // TODO: Connect to world state controls }