Skip to content

Commit eb4b163

Browse files
committed
Initial commit with v2.0.0 release
0 parents  commit eb4b163

20 files changed

+1207
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Binaries/
2+
Intermediate/

GameSwiftSdk.uplugin

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"FileVersion": 3,
3+
"VersionName": "2.0.0",
4+
"Version": 200,
5+
"FriendlyName": "GameSwiftUnrealSdk",
6+
"Description": "GameSwift Unreal SDK is Unity toolset created to integrate with GameSwift ID ecosystem.",
7+
"Category": "Other",
8+
"CreatedBy": "GameSwift",
9+
"CreatedByURL": "https://gameswift.io/",
10+
"DocsURL": "https://docs.gameswift.io/gameswift-products/sdk",
11+
"CanContainContent": true,
12+
"IsBetaVersion": false,
13+
"IsExperimentalVersion": false,
14+
"Installed": false,
15+
"Modules": [
16+
{
17+
"Name": "GameSwiftSdk",
18+
"Type": "Runtime",
19+
"LoadingPhase": "PreDefault",
20+
"WhitelistPlatforms": [
21+
"Win64",
22+
"Win32",
23+
"Mac",
24+
"IOS",
25+
"Android"
26+
]
27+
}
28+
]
29+
}

README.md

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
# Overview
2+
3+
GameSwift Unreal SDK is a toolset created to to help you seamlessly
4+
integrate [GameSwift ecosystem](https://platform.gameswift.io/) into your Unreal Engine projects. Key features of
5+
GameSwift Unreal SDK are:
6+
7+
* **Rapid integration**
8+
9+
Installation and integration process is streamlined and can be completed in under 30 minutes. This means you can focus
10+
more on building your game and less on complex API integration.
11+
12+
* **Safety**
13+
14+
Firstly, [GameSwift Launcher](https://launcher.gameswift.io/) is equipped with a robust DRM system that guarantees
15+
players launch your game without altering any game files.
16+
Secondly, [Multiple Logins Blocker](#multiple-logins-blocker) ensures that a user account is logged in from exactly
17+
one device at a time. Both of these features prevent various types of abuses and help you maintain a secure and fair
18+
gaming environment.
19+
20+
* **Blueprint support**
21+
22+
All SDK features can be accessed both in C++ code and in the Unreal Engine Blueprint system. This versatility
23+
ensures that not only programmers but also non-coding individuals can work on GameSwift ecosystem integration.
24+
25+
* **Multiplatform support**
26+
27+
The wrapper is designed to work seamlessly on multiple platforms, making it adaptable for a variety of game
28+
development projects. You can bring the best gaming experiences with GameSwift Unreal SDK for Windows, MacOS and
29+
mobile.
30+
31+
GameSwift Unreal SDK is compatible with Unreal Engine versions 4.24 and beyond. We are committed to keeping
32+
it up-to-date with newer Unreal Engine releases, including Unreal Engine 5 and upcoming versions.
33+
34+
# Installation
35+
36+
1. Add SDK to you project. This can be done in two ways:
37+
* Add SDK as [git submodule](https://git-scm.com/book/en/v2/Git-Tools-Submodules) to your repository by invoking the
38+
following command:
39+
```bash
40+
git submodule add https://github.com/GameSwift/gameswift-unreal-sdk YourMainProjectDir/Plugins/GameSwiftUnrealSdk
41+
```
42+
* Download this repository contents
43+
from [newest release](https://github.com/GameSwift/gameswift-unreal-sdk/releases/) and unpack the plugin to
44+
the `Plugins/GameSwiftUnrealSdk` folder. If you don't have a `Plugins` folder in your main project directory yet,
45+
create it.
46+
2. Open Project Settings in the editor and navigate to `Plugins > GameSwiftSdk`. Fill in following
47+
fields: `ClientId`, `ClientRedirectUri`, `ClientAuthenticationSecret`. These secrets
48+
are [distributed by GameSwift](#contact-us).
49+
50+
![Plugin secrets](https://github-production-user-asset-6210df.s3.amazonaws.com/109578061/275326695-cad47683-f07a-4d60-a9eb-338e454e6f12.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20231015%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20231015T155030Z&X-Amz-Expires=300&X-Amz-Signature=5f594705cef1e88f03b416a8397762fcc610522672ffb78ce0e0bed12208ef51&X-Amz-SignedHeaders=host&actor_id=109578061&key_id=0&repo_id=704859033)
51+
3. Add `GameSwiftSdk` to `PublicDependencyModuleNames` in your main `*.Build.cs` file.
52+
53+
# Integration
54+
55+
You can handle GameSwift login in 2 ways: [with launcher](#logging-in-from-launcher)
56+
or [without launcher](#logging-in-without-launcher). You can download GameSwift
57+
launcher [here](https://launcher.gameswift.io/). As long as your game targets Windows or MacOS, we strongly recommend to
58+
use data passed from our launcher. By doing so, you won't need to implement any login screen for your game as launcher
59+
already handles user credentials ina secure way.If you are building for mobile, you will need to create a login screen
60+
and implement connection with GameSwift backend [the other way](#logging-in-without-launcher).
61+
62+
No matter which approach you choose (C++ or Blueprints), be sure that `AuthorizeAndReadUserInfoFromLauncher`
63+
or `LoginAndAuthorize` is called at the application startup.This method wil succeed provided that:
64+
65+
1. User has internet connection.
66+
2. User did not attempt to login simultaneously from multiple devices (applicable only for
67+
applications with [Multiple Logins Blocker](#multiple-logins-blocker) enabled).
68+
3. User launched the game via launcher instead of your game executable file (provided that you
69+
used [with launcher](#logging-in-from-launcher) flow).
70+
71+
Otherwise, you should retry calling this method or close the application as it may not be launched the intended way.
72+
73+
## Launcher authentication - C++
74+
75+
Authorizing the user and getting his info can be done by
76+
calling `UGameSwiftAuthenticationManager::AuthorizeAndReadUserInfoFromLauncher`.
77+
78+
```cpp
79+
void ASampleCharacter::ReadUserInfoFromLauncher()
80+
{
81+
FGetUserInfoDelegate SuccessDelegate;
82+
SuccessDelegate.BindUFunction(this, "OnSuccess");
83+
FBaseSdkFailDelegate FailDelegate;
84+
FailDelegate.BindUFunction(this, "OnError");
85+
86+
UGameSwiftAuthenticationManager::AuthorizeAndReadUserInfoFromLauncher(SuccessDelegate, FailDelegate);
87+
}
88+
89+
void ASampleCharacter::OnSuccess(const FOAuthUserInfoResponse& Response)
90+
{
91+
// success - you can read user nickname and other data from Response
92+
}
93+
94+
void ASampleCharacter::OnError(const FBaseSdkFailResponse& Response)
95+
{
96+
// fail - close the application or retry authorization
97+
}
98+
```
99+
100+
## Launcher authentication - Blueprint
101+
102+
`AuthorizeAndReadUserInfoFromLauncher` node is responsible for authorizing the user, who accessed the game through
103+
GameSwift Launcher.
104+
105+
![Launcher login with Blueprints](https://github-production-user-asset-6210df.s3.amazonaws.com/109578061/275194063-dfb534d1-a6ea-45de-a892-1b60841a6952.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20231015%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20231015T155121Z&X-Amz-Expires=300&X-Amz-Signature=509ef88a05d06069d351a8e471035592768ba0e7475ad8517df11d1ef2ccc674&X-Amz-SignedHeaders=host&actor_id=109578061&key_id=0&repo_id=704859033)
106+
107+
## Non-launcher authentication - C++
108+
109+
With this approach you need to create a custom login widget, which will enable user to input the login data and
110+
authorize.
111+
112+
Authorizing the user and getting his info can be done by calling `UGameSwiftAuthenticationManager::LoginAndAuthorize`.
113+
114+
```cpp
115+
void ASampleCharacter::LoginAndAuthorize()
116+
{
117+
Fstring EmailOrNickname = "bob.smith@example.com";
118+
Fstring Password = "Password123";
119+
FGetUserInfoDelegate SuccessDelegate;
120+
SuccessDelegate.BindUFunction(this, "OnSuccess");
121+
FBaseSdkFailDelegate FailDelegate;
122+
FailDelegate.BindUFunction(this, "OnError");
123+
124+
UGameSwiftAuthenticationManager::LoginAndAuthorize(EmailOrNickname, Password,
125+
SuccessDelegate, FailDelegate);
126+
}
127+
128+
void ASampleCharacter::OnSuccess(const FOAuthUserInfoResponse& Response)
129+
{
130+
// success - you can read user nickname and other data from Response
131+
}
132+
133+
void ASampleCharacter::OnError(const FBaseSdkFailResponse& Response)
134+
{
135+
// fail - close the application or retry authorization
136+
}
137+
```
138+
139+
## Non-launcher authentication - Blueprint
140+
141+
`GetUserCredentials` node in the sample below is your implementation of retrieving login data from your custom login
142+
widget. Then, you can pass retrieved data to `LoginAndAuthorize` node.
143+
144+
![Non launcher login with Blueprints](https://github-production-user-asset-6210df.s3.amazonaws.com/109578061/275194061-6bd7b194-49c9-4898-bc49-1fd146baa9d9.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20231015%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20231015T155137Z&X-Amz-Expires=300&X-Amz-Signature=d5ed67496752a06bf27352d60840374e60342f77f816ffa71b04fd17bf8100d3&X-Amz-SignedHeaders=host&actor_id=109578061&key_id=0&repo_id=704859033)
145+
146+
## Multiple Logins Blocker
147+
148+
Multiple Logins Blocker is an optional, powerful feature of GameSwift Unreal SDK that ensures a user's account can
149+
only be logged in on one device at a time. This component's setup is done in Project Settings
150+
under `Plugins > GameSwiftSdk`.
151+
152+
If enabled, this component works in background of your game, sending periodic heartbeats to GameSwift server at time
153+
intervals specified by you. When server receives these heartbeats, it recognizes that the user is already logged in and
154+
will block any additional login attempts from this user for a configurable duration. If you want to configure the lock
155+
duration, feel free to [contact us](#contact-us).
156+
157+
# Contact Us
158+
159+
If you have any questions, concerns, or feedback, please don't hesitate to reach out to GameSwift team. We're here to
160+
assist you and can be contacted via email at [piotr.sobiecki@gameswift.io](mailto:piotr.sobiecki@gameswift.io).

Resources/Icon128.png

7.37 KB
Loading
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using System.IO;
2+
using UnrealBuildTool;
3+
4+
public class GameSwiftSdk : ModuleRules
5+
{
6+
public GameSwiftSdk(ReadOnlyTargetRules Target) : base(Target)
7+
{
8+
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
9+
10+
PublicIncludePaths.Add(Path.Combine(ModuleDirectory, "Public"));
11+
PrivateIncludePaths.Add(Path.Combine(ModuleDirectory, "Private"));
12+
13+
PublicDependencyModuleNames.AddRange(new[]
14+
{
15+
"Core",
16+
"CoreUObject",
17+
"HTTP",
18+
"Json",
19+
"JsonUtilities",
20+
"Engine"
21+
});
22+
}
23+
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
#include "BackendResponses.h"
2+
3+
bool FOAuthUserInfoResponse::Parse(const FJsonObject& JsonObject, FOAuthUserInfoResponse& ParsedResponse)
4+
{
5+
bool SuccessfulRead = true;
6+
SuccessfulRead &= JsonObject.TryGetStringField("userId", ParsedResponse.UserId);
7+
SuccessfulRead &= JsonObject.TryGetStringField("nickname", ParsedResponse.Nickname);
8+
SuccessfulRead &= JsonObject.TryGetStringField("avatarUrl", ParsedResponse.AvatarUrl);
9+
SuccessfulRead &= JsonObject.TryGetStringField("country", ParsedResponse.Country);
10+
return SuccessfulRead;
11+
}
12+
13+
bool FAuthorizeResponse::Parse(const FJsonObject& JsonObject, FAuthorizeResponse& ParsedResponse)
14+
{
15+
bool SuccessfulRead = true;
16+
SuccessfulRead &= JsonObject.TryGetStringField("code", ParsedResponse.Code);
17+
return SuccessfulRead;
18+
}
19+
20+
bool FTokenResponse::Parse(const FJsonObject& JsonObject, FTokenResponse& ParsedResponse)
21+
{
22+
bool SuccessfulRead = true;
23+
SuccessfulRead &= JsonObject.TryGetStringField("access_token", ParsedResponse.AccessToken);
24+
SuccessfulRead &= JsonObject.TryGetStringField("refresh_token", ParsedResponse.RefreshToken);
25+
return SuccessfulRead;
26+
}
27+
28+
bool FWalletsResponse::Parse(const TArray<FJsonObject> JsonObject, FWalletsResponse& ParsedResponse)
29+
{
30+
bool SuccessfulRead = true;
31+
32+
for (const auto WalletElement : JsonObject)
33+
{
34+
FWallet Wallet = FWallet();
35+
SuccessfulRead &= WalletElement.TryGetStringField("address", Wallet.Address);
36+
SuccessfulRead &= WalletElement.TryGetStringField("name", Wallet.Name);
37+
SuccessfulRead &= WalletElement.TryGetStringField("walletId", Wallet.WalletId);
38+
39+
TArray<FGame> Games;
40+
TArray<TSharedPtr<FJsonValue>> GamesArray = WalletElement.GetArrayField("games");
41+
for (const TSharedPtr<FJsonValue>& GameValue : GamesArray)
42+
{
43+
FGame Game = FGame();
44+
TSharedPtr<FJsonObject> GameObject = GameValue->AsObject();
45+
Game.GameId = GameObject->GetStringField("gameId");
46+
Games.Add(Game);
47+
}
48+
Wallet.Games = Games;
49+
50+
FChain Chain = FChain();
51+
TSharedPtr<FJsonObject> ChainObject = WalletElement.GetObjectField("chain");
52+
Chain.ChainId = ChainObject->GetStringField("chainId");
53+
Chain.ChainName = ChainObject->GetStringField("chainName");
54+
Wallet.Chain = Chain;
55+
56+
ParsedResponse.Wallets.Add(Wallet);
57+
}
58+
59+
return SuccessfulRead;
60+
}
61+
62+
bool FWalletBalanceResponse::Parse(const FJsonObject& JsonObject, FWalletBalanceResponse& ParsedResponse)
63+
{
64+
bool SuccessfulRead = true;
65+
66+
const TArray<TSharedPtr<FJsonValue>>* NftsArray;
67+
SuccessfulRead &= JsonObject.TryGetArrayField("nfts", NftsArray);
68+
for (const TSharedPtr<FJsonValue>& NftValue : *NftsArray)
69+
{
70+
FNft Nft = FNft();
71+
TSharedPtr<FJsonObject> GameObject = NftValue->AsObject();
72+
Nft.Address = GameObject->GetStringField("address");
73+
Nft.Balance = GameObject->GetNumberField("balance");
74+
Nft.Id = GameObject->GetStringField("id");
75+
ParsedResponse.Nfts.Add(Nft);
76+
}
77+
78+
const TArray<TSharedPtr<FJsonValue>>* TokensArray;
79+
SuccessfulRead &= JsonObject.TryGetArrayField("tokens", TokensArray);
80+
for (const TSharedPtr<FJsonValue>& TokenValue : *TokensArray)
81+
{
82+
FToken Token = FToken();
83+
TSharedPtr<FJsonObject> GameObject = TokenValue->AsObject();
84+
Token.Address = GameObject->GetStringField("address");
85+
Token.Balance = GameObject->GetNumberField("balance");
86+
ParsedResponse.Tokens.Add(Token);
87+
}
88+
89+
return SuccessfulRead;
90+
}
91+
92+
bool FLoginResponse::Parse(const FJsonObject& JsonObject, FLoginResponse& ParsedResponse)
93+
{
94+
bool SuccessfulRead = true;
95+
SuccessfulRead &= JsonObject.TryGetStringField("userId", ParsedResponse.UserId);
96+
SuccessfulRead &= JsonObject.TryGetStringField("email", ParsedResponse.Email);
97+
SuccessfulRead &= JsonObject.TryGetStringField("nickname", ParsedResponse.Nickname);
98+
SuccessfulRead &= JsonObject.TryGetStringField("accessToken", ParsedResponse.AccessToken);
99+
return SuccessfulRead;
100+
}

0 commit comments

Comments
 (0)