#online,wegame

OnlineSubsystemTencent plugin for WeGame (RailSDK) functionality in UE4

[at]rob.cannaday, [at]josh.markiewicz, [at]billy.mccarroll

#ROBOMERGE-OWNER: ben.marsh
#ROBOMERGE-AUTHOR: sam.zamani
#ROBOMERGE-SOURCE: CL 6180210 via CL 6181045 via CL 6181140
#ROBOMERGE-BOT: BUILD (Main -> Dev-Build)

[CL 6212166 by sam zamani in Dev-Build branch]
This commit is contained in:
sam zamani
2019-05-01 18:21:45 -04:00
parent 1fd7d1be7c
commit d07cc785a3
115 changed files with 21247 additions and 0 deletions

View File

@@ -39472,6 +39472,11 @@
<File Name="Engine/Source/ThirdParty/Steamworks/Steamv139/sdk/redistributable_bin/win64/steam_api64.dll" Hash="fa732757f9aaa47e8de4ecfcabc07b5df4f0f1cf" />
<File Name="Engine/Source/ThirdParty/Steamworks/Steamv139/sdk/redistributable_bin/win64/steam_api64.lib" Hash="e0fd6b78e68ad49887496715222b279aae54c7f2" />
<File Name="Engine/Source/ThirdParty/Steamworks/Steamv139/steamworks_sdk_139.zip" Hash="c1543a29778aa0ae9038389f59ee385dab9adabe" />
<File Name="Engine/Source/ThirdParty/Tencent/WeGame/railSDK/rail/libs/win/Release_32/rail_api.dll" Hash="7999d060354ef49cd98f698795969a9a8246ea79" />
<File Name="Engine/Source/ThirdParty/Tencent/WeGame/railSDK/rail/libs/win/Release_32/rail_sdk_wegame_platform.dll" Hash="35be354b2a19c02b3d260b9f21e4133535e9d636" />
<File Name="Engine/Source/ThirdParty/Tencent/WeGame/railSDK/rail/libs/win/Release_64/rail_api64.dll" Hash="918ac1de97c20110c0b0426aa31483917a57848b" />
<File Name="Engine/Source/ThirdParty/Tencent/WeGame/railSDK/rail/libs/win/Release_64/rail_sdk_wegame_platform64.dll" Hash="11383665c7264ddf4b602df2089616fcd035c3d6" />
<File Name="Engine/Source/ThirdParty/Tencent/WeGame/railSDK/rail/sdk/base/BUILD" Hash="28dc6844c329f35642ee3b0602a43c79696892a4" />
<File Name="Engine/Source/ThirdParty/VHACD/build/Xcode/VHACD.xcodeproj/project.pbxproj" Hash="9700532a3ab5b5ce7fec0dfe6c2c83316df4e1ff" />
<File Name="Engine/Source/ThirdParty/VHACD/cl/vhacdKernels.cl" Hash="b3309dbd607a6238507b41562431a86177a5bf65" />
<File Name="Engine/Source/ThirdParty/VHACD/Lib/Linux/x86_64-unknown-linux-gnu/libVHACD.a" Hash="35157b8e1d062f3fbd796afbd05d9bbb5a1320d1" />
@@ -42986,6 +42991,7 @@
<Blob Hash="1136bba0636ae8a71f328374937722240aa00445" Size="93111" PackHash="67f9a57842391bca1072e56b907d2adde02d2d34" PackOffset="1225995" />
<Blob Hash="1137b229a45145daebe8274f6b5918b07f6100f5" Size="2952" PackHash="eda6e1c1edcf27f8270efff9c2cdc40a86fe34fd" PackOffset="2067455" />
<Blob Hash="11382d89547aaeeb486a94153c04cfa5df931339" Size="105837" PackHash="6413cc72c0494488f4a124a78b19a8b98687aa46" PackOffset="1676876" />
<Blob Hash="11383665c7264ddf4b602df2089616fcd035c3d6" Size="15622816" PackHash="e6d69ba3da7d3a04cf1656f22709b7bbdef05b8f" PackOffset="8" />
<Blob Hash="11392706b96f4976bef221574678da90b8535afe" Size="132" PackHash="bbd0d366aa5edcf7c89a18c6bcc1c936170ac171" PackOffset="1019579" />
<Blob Hash="1139b8f4efde61a6df0243ca4787d3666931b8ac" Size="1291" PackHash="3c04f2c7b48bbc9d09a45901b0c37ef486805cb6" PackOffset="55137" />
<Blob Hash="113b9af7b62321844946a0973ed80e9e55b2d189" Size="85928256" PackHash="bd0074eda451f9864389d34ed5720ad1086a8482" PackOffset="8" />
@@ -45461,6 +45467,7 @@
<Blob Hash="28d4b9d0263f58e5ac23b2f546b3333883631315" Size="5117" PackHash="cb73a430e097bac42d93ec902203b7888ed0b681" PackOffset="173760" />
<Blob Hash="28d729c89c82366c64aff943dbc0ecd161980014" Size="17321192" PackHash="5c0af455c4e717168c4a6c3d9ccbdc0ea950e3a9" PackOffset="8" />
<Blob Hash="28daf75604dace7c3a77a2d224ce713b1d9798a3" Size="7976" PackHash="76107ffad88e4bd4762670491ea2da0aa178b29f" PackOffset="2021929" />
<Blob Hash="28dc6844c329f35642ee3b0602a43c79696892a4" Size="350" PackHash="bdc38ac04c02594fea5422373ce7dbf8d2ec1a6d" PackOffset="1085608" />
<Blob Hash="28dcc0f9cb4f9485d08c87eb905f4e258ec71822" Size="24065" PackHash="77f03c66e7c43010c9ca62602372048fd94efaef" PackOffset="1013596" />
<Blob Hash="28e3982f010b09213e8f11425cbc85800607f274" Size="5145" PackHash="adecd2c644904747c3cdc204c4e4d0c59ab35970" PackOffset="2089261" />
<Blob Hash="28e3fede46363ca1cff054e052d644395f895e00" Size="15360" PackHash="fe6078495c852c69d53e6d83466c7cb7ba20a43b" PackOffset="1424760" />
@@ -46833,6 +46840,7 @@
<Blob Hash="35bbf0c1116d36a3756d432cdb80232bb3e37856" Size="3034" PackHash="b2f88f44baa14211312509c95df7f2a600873cef" PackOffset="1931872" />
<Blob Hash="35bbfc4b9acb5196521f41e08a96a0bcb89cdc9e" Size="3382" PackHash="d7cd467675e181dbeba3cf24443590ebb76f9515" PackOffset="290676" />
<Blob Hash="35bd6492ff0e447842326ae72bc205fc96b1f903" Size="149946" PackHash="5e7d96af5e5b1cafa670bd77ae918457a118f7a5" PackOffset="1869077" />
<Blob Hash="35be354b2a19c02b3d260b9f21e4133535e9d636" Size="12297888" PackHash="d501460c3c1d7254e3a665d82425fc3013d0f0a5" PackOffset="8" />
<Blob Hash="35c19d7fa17ab8f76cd03512d63858490d1edf37" Size="23869" PackHash="8859a255b2dc33282a9c8cdda2d065b762dde4eb" PackOffset="1940612" />
<Blob Hash="35c29119b4b9d8625254e40e1835451e0240def1" Size="36773" PackHash="4efac4b827a85de03a834184653eddda35a14e06" PackOffset="1135984" />
<Blob Hash="35c7219a416b2a2d5e7876f6f9973e2cf4460b28" Size="26598" PackHash="d420a69d00fddaac7b90d8fc4a90fedca43efb31" PackOffset="1414544" />
@@ -54206,6 +54214,7 @@
<Blob Hash="79870a0e68aa0a9b301414edc21889f83bb81e40" Size="286" PackHash="f25f5da5b49f7c1000f7e4195d4038bda16e5c38" PackOffset="1698594" />
<Blob Hash="7987b24e7bbc1054985c3a0e4a1e4af812452164" Size="9329320" PackHash="b3ba54dd3b4a9c7c235223aca9ad7d6007559484" PackOffset="8" />
<Blob Hash="7988de327dbcb77b864c3587f4cbbf80811558f1" Size="3008" PackHash="bbd0d366aa5edcf7c89a18c6bcc1c936170ac171" PackOffset="844758" />
<Blob Hash="7999d060354ef49cd98f698795969a9a8246ea79" Size="1085600" PackHash="bdc38ac04c02594fea5422373ce7dbf8d2ec1a6d" PackOffset="8" />
<Blob Hash="799e9fe238d3d3b62d34b3f21f2c5f0f275999da" Size="2802" PackHash="cb73a430e097bac42d93ec902203b7888ed0b681" PackOffset="806084" />
<Blob Hash="799ed7bfb9e2b6df2fe535b5b37cc4e922c2ed27" Size="5212" PackHash="9e3075eea5e5e885d9aa9e6b2952ebe61a8b60a1" PackOffset="2090349" />
<Blob Hash="799f72ca104615b9d9198d7e593407b8d97b24d3" Size="83554" PackHash="35b0e5ed5cbf20a0b47af4bb9ca6ffef4d3e5d8e" PackOffset="1425455" />
@@ -56803,6 +56812,7 @@
<Blob Hash="918094daa026d620a9c675021dac03e7da592d54" Size="1331" PackHash="70bc3cba2df02db94668c029275adba4d7f590cb" PackOffset="2095565" />
<Blob Hash="9185e1b0a207ad2335043819c6d0948b69d22057" Size="9520" PackHash="afc5cb40d4e6c77d1775d83fce7636691d3fa748" PackOffset="2070262" />
<Blob Hash="9186dec8b8459922e6e2212615f4cd37461b2204" Size="6782810" PackHash="e6b6eae991adb9b39c9dd688676859a2a37b6d39" PackOffset="8" />
<Blob Hash="918ac1de97c20110c0b0426aa31483917a57848b" Size="1309856" PackHash="5c3042995c3b61f80cf22b97d0266faeb1177e38" PackOffset="8" />
<Blob Hash="918b9914b249c73b3b3f1598da1f41ff6ecbf2e7" Size="305008" PackHash="5bdf3c096176f291f046364231143f6c20777eb7" PackOffset="568415" />
<Blob Hash="918c2c2fdeea16c5e228df334ee99f83280995ea" Size="338" PackHash="80c1ba699c3de9b0950a5521e587025e7f85f8bb" PackOffset="1159250" />
<Blob Hash="918c908e4c32ea5ef2684d16a2700f89c4702e7d" Size="130145" PackHash="50f9fc796963c692e13289ee270e9728c3446e24" PackOffset="1100910" />
@@ -69849,6 +69859,7 @@
<Pack Hash="5bebca5faa7b71ff2927f873eecb93cf54bdeeba" Size="362228" CompressedSize="343383" RemotePath="3352991-5446f868f9d3466fadfb74d5f834c560" />
<Pack Hash="5c01c6b5fed7cf25e36fa4c1a858552e163f10ec" Size="5131234" CompressedSize="1008793" RemotePath="UnrealEngine-3720923-5712cc719d4541ffbfdee6e387fdb8bb" />
<Pack Hash="5c0af455c4e717168c4a6c3d9ccbdc0ea950e3a9" Size="17321200" CompressedSize="6903824" RemotePath="UnrealEngine-5711864-7f363a77fda64610b5af3e3fa1cb3a67" />
<Pack Hash="5c3042995c3b61f80cf22b97d0266faeb1177e38" Size="1309864" CompressedSize="348925" RemotePath="UnrealEngine-6181140-1c7de385c391478e8e868f077889754c" />
<Pack Hash="5c3cb1bc324339ff637e39ac99e09c8a276fbf1d" Size="1646514" CompressedSize="461726" RemotePath="2647804-bc48e958b8224dc19d6eb2f094c9d70e" />
<Pack Hash="5c42920f6f44c053dcf7e87f29ccef27b326822c" Size="2097150" CompressedSize="745224" RemotePath="2369826-2acd3c361c9d4a858bd63938a2ab980e" />
<Pack Hash="5c517712601cff542ae326efa6bdc3a7734755c9" Size="2127960" CompressedSize="596413" RemotePath="2369826-2acd3c361c9d4a858bd63938a2ab980e" />
@@ -71036,6 +71047,7 @@
<Pack Hash="bd969e12b2d210ce0b8817860e18034a3a30c510" Size="6574676" CompressedSize="2411840" RemotePath="2369826-2acd3c361c9d4a858bd63938a2ab980e" />
<Pack Hash="bda6f07dbc0dd70ab1d6ba2cc79bcebb3c536f75" Size="105348" CompressedSize="99307" RemotePath="UnrealEngine-4290333-9bc7c3c4358949c3abc291bf0a3dbeb5" />
<Pack Hash="bdb795ab990273ac2325d4ad5f1a40ce4a107d12" Size="2976076" CompressedSize="955784" RemotePath="UnrealEngine-5711709-e859150dc06c4f60824a16d3ff8aa7a0" />
<Pack Hash="bdc38ac04c02594fea5422373ce7dbf8d2ec1a6d" Size="1085958" CompressedSize="256222" RemotePath="UnrealEngine-6181140-1c7de385c391478e8e868f077889754c" />
<Pack Hash="bde207f2cccc5c5dce89acc8f63625ae78e3d1e1" Size="979376" CompressedSize="131858" RemotePath="UnrealEngine-4924894-90bacaa8b4214d5a8b3b0f6186c26090" />
<Pack Hash="bde504e141af1b3d4487c18b5869aca6f206534e" Size="2096310" CompressedSize="723601" RemotePath="3386123-114c137db15c440eb0400947c008540e" />
<Pack Hash="bdf8cf915f1bb45fdf33feefb6137097f0ad9d96" Size="292627392" CompressedSize="96232837" RemotePath="UnrealEngine-5229842-94b15c1a9376404f9d5e80d1494cf546" />
@@ -71318,6 +71330,7 @@
<Pack Hash="d46df2e9f511a859db8a9551c3cfa8672f1e14b6" Size="2097075" CompressedSize="693226" RemotePath="UnrealEngine-4784913-527cfd96b8c0432389bb7e5cc58ba600" />
<Pack Hash="d4a41b654dcbbd51f64a81e9c879f5d156f13024" Size="38321" CompressedSize="8787" RemotePath="UnrealEngine-4646582-f38ebc3b3e8d42f4b13177ccab6764ba" />
<Pack Hash="d4b6bc525135e5f3997bc740127b9f8e5a064369" Size="2097068" CompressedSize="607465" RemotePath="UnrealEngine-4690078-25be7614c4f74274adc1c3cb1d6e032e" />
<Pack Hash="d501460c3c1d7254e3a665d82425fc3013d0f0a5" Size="12297896" CompressedSize="4650398" RemotePath="UnrealEngine-6181140-1c7de385c391478e8e868f077889754c" />
<Pack Hash="d504626ae1dc9e947a7a440673d602c39da5c96f" Size="1122267" CompressedSize="508290" RemotePath="UnrealEngine-4669551-a8deccc6c0e54c3bb11bf72482f1b9e0" />
<Pack Hash="d52390dbb691d4e6a77292998b1af87bbc636aaf" Size="1770393" CompressedSize="747528" RemotePath="UnrealEngine-4508974-a785f129cd624979915a561b5d4e8e7c" />
<Pack Hash="d5300790dac3cc619f89851b34f424d123202d88" Size="551589" CompressedSize="494005" RemotePath="UnrealEngine-3503486-1d5f9328de214edda653a39de04f2a9b" />
@@ -71513,6 +71526,7 @@
<Pack Hash="e6b83ec97fafafc6143681038daeef55640515f3" Size="764014" CompressedSize="452142" RemotePath="UnrealEngine-4101728-4654c82bbd394a2b8316dbe37d78529c" />
<Pack Hash="e6c3d3a7d041d8fecb9399548174729182d6f31b" Size="1863582" CompressedSize="1612606" RemotePath="UnrealEngine-4627797-c595844e3a2f4767b9211afc9460d9bd" />
<Pack Hash="e6d6170217e3ab596bcc10a49c297cbbac27c3e4" Size="2089789" CompressedSize="986727" RemotePath="3094220-59e13834c31f46ecbaebfd3e87eef600" />
<Pack Hash="e6d69ba3da7d3a04cf1656f22709b7bbdef05b8f" Size="15622824" CompressedSize="5595837" RemotePath="UnrealEngine-6181140-1c7de385c391478e8e868f077889754c" />
<Pack Hash="e6dd425a09187e0b4554a45bca1423b74e0e270e" Size="1698661" CompressedSize="330841" RemotePath="UnrealEngine-6113024-522060f115d244c886e6ae70f4badce9" />
<Pack Hash="e6f9ebf77b895562aef27a0eae3bf2eeba669d89" Size="2349859" CompressedSize="285011" RemotePath="UnrealEngine-5478274-0d5a02708fc74725a962de6de34be276" />
<Pack Hash="e70d1009f85ea849d752e08d4ec2c8aae59dce96" Size="2097125" CompressedSize="688124" RemotePath="UnrealEngine-5711265-921677eaa6dd449da72bb2cae5500deb" />

View File

@@ -0,0 +1,40 @@
{
"FileVersion" : 1,
"FriendlyName" : "Online Subsystem Tencent",
"Version" : 1,
"VersionName" : "1.0",
"Description" : "Access to Tencent platform",
"Category" : "Online Platform",
"CreatedBy" : "Epic Games, Inc.",
"CreatedByURL" : "http://epicgames.com",
"EnabledByDefault" : false,
"Modules": [
{
"Name": "OnlineSubsystemTencent",
"Type": "Runtime",
"LoadingPhase": "Default",
"WhitelistPlatforms":
[
"Linux",
"Win32",
"Win64"
]
}
],
"Plugins": [
{
"Name": "OnlineSubsystem",
"Enabled": true
},
{
"Name": "OnlineSubsystemUtils",
"Enabled": true
},
{
"Name": "OnlineFramework",
"Enabled": true
}
]
}

View File

@@ -0,0 +1,64 @@
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
using UnrealBuildTool;
using System.IO;
public class OnlineSubsystemTencent : ModuleRules
{
public OnlineSubsystemTencent(ReadOnlyTargetRules Target) : base(Target)
{
PrivateDefinitions.Add("ONLINESUBSYSTEM_TENCENT_PACKAGE=1");
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
PrivateIncludePaths.Add("Private");
PublicDependencyModuleNames.AddRange(
new string[] {
"Core",
"CoreUObject"
}
);
PrivateDependencyModuleNames.AddRange(
new string[] {
"Sockets",
"HTTP",
"Json",
"OnlineSubsystem",
"PacketHandler",
"PlayTimeLimit"
}
);
if (Target.bCompileAgainstEngine)
{
PrivateDependencyModuleNames.AddRange(
new string[] {
"Engine",
"OnlineSubsystemUtils"
}
);
}
if (System.IO.Directory.Exists(System.IO.Path.Combine(Target.UEThirdPartySourceDirectory, "Tencent", "WeGame")))
{
AddEngineThirdPartyPrivateDynamicDependencies(Target, "WeGame");
PublicIncludePathModuleNames.Add("WeGame");
PublicDefinitions.Add("WITH_TENCENTSDK=1");
}
else
{
PublicDefinitions.Add("WITH_TENCENTSDK=0");
}
if (System.IO.Directory.Exists(System.IO.Path.Combine(Target.UEThirdPartySourceDirectory, "NotForLicensees", "Tencent")))
{
AddEngineThirdPartyPrivateDynamicDependencies(Target, "Tencent");
PublicIncludePathModuleNames.Add("Tencent");
}
// Don't want to introduce Tencent dependency when building the base editor
PrecompileForTargets = PrecompileTargetsType.None;
}
}

View File

@@ -0,0 +1,340 @@
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
#include "OnlineAsyncTaskManagerTencent.h"
#include "OnlineSubsystemTencentPCH.h"
#include "OnlineAsyncTasksTencent.h"
#include "OnlinePresenceTencent.h"
#include "PlayTimeLimitImpl.h"
#if WITH_TENCENTSDK
#if WITH_TENCENT_RAIL_SDK
#include "RailSdkWrapper.h"
#endif
FOnlineAsyncTaskManagerTencent::FOnlineAsyncTaskManagerTencent()
: Subsystem(nullptr)
{
#if WITH_TENCENT_RAIL_SDK
RegisterRailEvents();
#endif
}
FOnlineAsyncTaskManagerTencent::FOnlineAsyncTaskManagerTencent(class FOnlineSubsystemTencent* InSubsystem)
: Subsystem(InSubsystem)
{
#if WITH_TENCENT_RAIL_SDK
RegisterRailEvents();
#endif
}
FOnlineAsyncTaskManagerTencent::~FOnlineAsyncTaskManagerTencent()
{
#if WITH_TENCENT_RAIL_SDK
UnregisterRailEvents();
#endif
}
void FOnlineAsyncTaskManagerTencent::OnlineTick()
{
check(Subsystem);
check(FPlatformTLS::GetCurrentThreadId() == OnlineThreadId || !FPlatformProcess::SupportsMultithreading());
#if WITH_TENCENT_RAIL_SDK
RailSdkWrapper& RailSDK = RailSdkWrapper::Get();
if (RailSDK.IsInitialized())
{
RailSDK.RailFireEvents();
}
#endif
}
#if WITH_TENCENT_RAIL_SDK
void FOnlineAsyncTaskManagerTencent::RegisterRailEvents()
{
RailSdkWrapper& RailSDK = RailSdkWrapper::Get();
if (RailSDK.IsInitialized())
{
/**
* System Events
*/
// Rail system state changed (for example launcher was closed) (RailSystemStateChanged)
RegisteredRailEvents.Add(rail::kRailEventSystemStateChanged);
/**
* Friends
*/
// Friend add request has completed (RailFriendsAddFriendResult)
RegisteredRailEvents.Add(rail::kRailEventFriendsAddFriendResult);
// Friends list has changed (RailFriendsListChanged)
RegisteredRailEvents.Add(rail::kRailEventFriendsFriendsListChanged);
// Friend's online status has changed (RailFriendsOnlineStateChanged)
RegisteredRailEvents.Add(rail::kRailEventFriendsOnlineStateChanged);
// Friends' key/value pairs metadata has changed (RailFriendsMetadataChanged)
RegisteredRailEvents.Add(rail::kRailEventFriendsMetadataChanged);
/**
* External UI
*/
// Floating window dialog has opened/closed (ShowFloatingWindowResult)
RegisteredRailEvents.Add(rail::kRailEventShowFloatingWindow);
// Floating notify window dialog should be displayed by application
RegisteredRailEvents.Add(rail::kRailEventShowFloatingNotifyWindow);
/**
* Invites
*/
// Invite has been sent to a remote user notification (RailUsersNotifyInviter)
RegisteredRailEvents.Add(rail::kRailEventUsersNotifyInviter);
// Invite has been sent to a remote user via AsyncInviteUsers (RailUsersInviteUsersResult)
RegisteredRailEvents.Add(rail::kRailEventUsersInviteUsersResult);
// Inviter receives a response regarding invitee handling invite (RailUsersInviteJoinGameResult)
RegisteredRailEvents.Add(rail::kRailEventUsersInviteJoinGameResult);
// Invitee has responded to inviter's invite (RailUsersRespondInvitation)
RegisteredRailEvents.Add(rail::kRailEventUsersRespondInvitation);
// Join via presence user trying to join a remote session (RailPlatformNotifyEventJoinGameByUser)
RegisteredRailEvents.Add(rail::kRailPlatformNotifyEventJoinGameByUser);
/**
* Assets
*/
// Assets in the user's inventory has changed (RailAssetsChanged)
RegisteredRailEvents.Add(rail::kRailEventAssetsAssetsChanged);
/**
* NYI
*/
// Querying a friends running game is complete (RailFriendsQueryFriendPlayedGamesResult)
RegisteredRailEvents.Add(rail::kRailEventFriendsGetFriendPlayedGamesResult);
// Querying a user's info is complete (RailUsersInfoData)
RegisteredRailEvents.Add(rail::kRailEventUsersGetUsersInfo);
// (RailUsersCancelInviteResult)
RegisteredRailEvents.Add(rail::kRailEventUsersCancelInviteResult);
RegisteredRailEvents.Add(rail::kRailEventFriendsDialogShow);
/**
* Implemented by Async Tasks
*/
RegisteredRailEvents.Add(rail::kRailEventFriendsSetMetadataResult);
RegisteredRailEvents.Add(rail::kRailEventFriendsGetInviteCommandLine);
for (auto EventId : RegisteredRailEvents)
{
RailSDK.RailRegisterEvent(EventId, this);
}
}
}
void FOnlineAsyncTaskManagerTencent::UnregisterRailEvents()
{
RailSdkWrapper& RailSDK = RailSdkWrapper::Get();
if (RailSDK.IsInitialized())
{
for (auto EventId : RegisteredRailEvents)
{
RailSDK.RailUnregisterEvent(EventId, this);
}
RegisteredRailEvents.Empty();
}
}
void FOnlineAsyncTaskManagerTencent::OnRailEvent(rail::RAIL_EVENT_ID event_id, rail::EventBase* param)
{
UE_LOG_ONLINE(Verbose, TEXT("FOnlineAsyncTaskManagerTencent::OnRailEvent EventId: %d Result: %d"), static_cast<uint32>(event_id), param ? param->get_result() : -1);
/** THIS IS ONLINE THREAD */
if ((OnlineThreadId != 0) && (FPlatformTLS::GetCurrentThreadId() != OnlineThreadId))
{
UE_LOG_ONLINE(Warning, TEXT("Task ran on thread other than online!"));
}
switch (event_id)
{
case rail::kRailEventSystemStateChanged:
OnRailSystemStateChanged(static_cast<rail::rail_event::RailSystemStateChanged*>(param));
break;
case rail::kRailEventShowFloatingWindow:
OnRailShowFloatingWindow(static_cast<rail::rail_event::ShowFloatingWindowResult*>(param));
break;
case rail::kRailEventShowFloatingNotifyWindow:
OnRailShowFloatingNotifyWindow(static_cast<rail::rail_event::ShowNotifyWindow*>(param));
break;
case rail::kRailEventFriendsDialogShow:
break;
case rail::kRailEventUsersNotifyInviter:
OnRailInviteSentNotification(static_cast<rail::rail_event::RailUsersNotifyInviter*>(param));
break;
case rail::kRailEventUsersInviteUsersResult:
OnRailInviteUsersResult(static_cast<rail::rail_event::RailUsersInviteUsersResult*>(param));
break;
case rail::kRailEventUsersInviteJoinGameResult:
OnRailInviteJoinGameResult(static_cast<rail::rail_event::RailUsersInviteJoinGameResult*>(param));
break;
case rail::kRailEventUsersRespondInvitation:
OnRailFriendsInviteRespondInvitation(static_cast<rail::rail_event::RailUsersRespondInvitation*>(param));
break;
case rail::kRailPlatformNotifyEventJoinGameByUser:
OnRailFriendsJoinGameByUser(static_cast<rail::rail_event::RailPlatformNotifyEventJoinGameByUser*>(param));
break;
case rail::kRailEventAssetsAssetsChanged:
OnRailAssetsChanged(static_cast<rail::rail_event::RailAssetsChanged*>(param));
break;
case rail::kRailEventUsersGetUsersInfo:
OnRailGetUsersInfo(static_cast<rail::rail_event::RailUsersInfoData*>(param));
break;
case rail::kRailEventFriendsGetFriendPlayedGamesResult:
OnRailGetFriendPlayedGamesResult(static_cast<rail::rail_event::RailFriendsQueryFriendPlayedGamesResult*>(param));
break;
case rail::kRailEventFriendsGetInviteCommandLine:
OnRailInviteCommandline(static_cast<rail::rail_event::RailFriendsGetInviteCommandLine*>(param));
break;
case rail::kRailEventUsersCancelInviteResult:
OnRailCancelInviteResult(static_cast<rail::rail_event::RailUsersCancelInviteResult*>(param));
break;
case rail::kRailEventFriendsSetMetadataResult:
OnRailFriendsSetMetadataResult(static_cast<rail::rail_event::RailFriendsSetMetadataResult*>(param));
break;
case rail::kRailEventFriendsAddFriendResult:
OnRailEventFriendsAddFriendResult(static_cast<rail::rail_event::RailFriendsAddFriendResult*>(param));
break;
case rail::kRailEventFriendsFriendsListChanged:
OnRailFriendsListChanged(static_cast<const rail::rail_event::RailFriendsListChanged*>(param));
break;
case rail::kRailEventFriendsOnlineStateChanged:
OnRailFriendsOnlineStateChanged(static_cast<const rail::rail_event::RailFriendsOnlineStateChanged*>(param));
break;
case rail::kRailEventFriendsMetadataChanged:
OnRailFriendsMetadataChanged(static_cast<const rail::rail_event::RailFriendsMetadataChanged*>(param));
break;
default:
UE_LOG_ONLINE(Log, TEXT("FOnlineAsyncTaskManagerTencent::OnRailEvent Unhandled Event"));
break;
}
}
void FOnlineAsyncTaskManagerTencent::OnRailSystemStateChanged(const rail::rail_event::RailSystemStateChanged* param)
{
FOnlineAsyncEventRailSystemStateChanged* NewEvent = new FOnlineAsyncEventRailSystemStateChanged(Subsystem, param);
UE_LOG_ONLINE(Verbose, TEXT("%s"), *NewEvent->ToString());
AddToOutQueue(NewEvent);
}
void FOnlineAsyncTaskManagerTencent::OnRailShowFloatingWindow(const rail::rail_event::ShowFloatingWindowResult* param)
{
FOnlineAsyncEventRailShowFloatingWindow* NewEvent = new FOnlineAsyncEventRailShowFloatingWindow(Subsystem, param);
UE_LOG_ONLINE(Verbose, TEXT("%s"), *NewEvent->ToString());
AddToOutQueue(NewEvent);
}
void FOnlineAsyncTaskManagerTencent::OnRailShowFloatingNotifyWindow(const rail::rail_event::ShowNotifyWindow* param)
{
if (IModularFeatures::Get().IsModularFeatureAvailable(IOnlinePlayTimeLimit::GetModularFeatureName()))
{
FOnlineAsyncEventRailShowFloatingNotifyWindow* NewEvent = new FOnlineAsyncEventRailShowFloatingNotifyWindow(Subsystem, param);
UE_LOG_ONLINE(Verbose, TEXT("%s"), *NewEvent->ToString());
AddToOutQueue(NewEvent);
}
}
void FOnlineAsyncTaskManagerTencent::OnRailInviteSentNotification(const rail::rail_event::RailUsersNotifyInviter* param)
{
FOnlineAsyncEventRailInviteSent* NewEvent = new FOnlineAsyncEventRailInviteSent(Subsystem, param);
UE_LOG_ONLINE(Verbose, TEXT("%s"), *NewEvent->ToString());
AddToOutQueue(NewEvent);
}
void FOnlineAsyncTaskManagerTencent::OnRailInviteUsersResult(const rail::rail_event::RailUsersInviteUsersResult* param)
{
FOnlineAsyncEventRailInviteSentEx* NewEvent = new FOnlineAsyncEventRailInviteSentEx(Subsystem, param);
UE_LOG_ONLINE(Verbose, TEXT("%s"), *NewEvent->ToString());
AddToOutQueue(NewEvent);
}
void FOnlineAsyncTaskManagerTencent::OnRailInviteJoinGameResult(const rail::rail_event::RailUsersInviteJoinGameResult* param)
{
FOnlineAsyncEventRailJoinGameResult* NewEvent = new FOnlineAsyncEventRailJoinGameResult(Subsystem, param);
UE_LOG_ONLINE(Verbose, TEXT("%s"), *NewEvent->ToString());
AddToOutQueue(NewEvent);
}
void FOnlineAsyncTaskManagerTencent::OnRailFriendsInviteRespondInvitation(const rail::rail_event::RailUsersRespondInvitation* param)
{
FOnlineAsyncEventRailInviteResponse* NewEvent = new FOnlineAsyncEventRailInviteResponse(Subsystem, param);
UE_LOG_ONLINE(Verbose, TEXT("%s"), *NewEvent->ToString());
AddToOutQueue(NewEvent);
}
void FOnlineAsyncTaskManagerTencent::OnRailFriendsJoinGameByUser(const rail::rail_event::RailPlatformNotifyEventJoinGameByUser* param)
{
FOnlineAsyncEventRailJoinGameByUser* NewEvent = new FOnlineAsyncEventRailJoinGameByUser(Subsystem, param);
UE_LOG_ONLINE(Verbose, TEXT("%s"), *NewEvent->ToString());
AddToOutQueue(NewEvent);
}
void FOnlineAsyncTaskManagerTencent::OnRailAssetsChanged(const rail::rail_event::RailAssetsChanged* param)
{
FOnlineAsyncEventRailAssetsChanged* NewEvent = new FOnlineAsyncEventRailAssetsChanged(Subsystem, param);
UE_LOG_ONLINE(Verbose, TEXT("%s"), *NewEvent->ToString());
AddToOutQueue(NewEvent);
}
void FOnlineAsyncTaskManagerTencent::OnRailGetUsersInfo(const rail::rail_event::RailUsersInfoData* param)
{
UE_LOG_ONLINE(VeryVerbose, TEXT("FOnlineAsyncTaskManagerTencent::OnRailGetUsersInfo NOOP %s"), *LexToString(param ? param->get_result() : rail::RailResult::kErrorUnknown));
}
void FOnlineAsyncTaskManagerTencent::OnRailGetFriendPlayedGamesResult(const rail::rail_event::RailFriendsQueryFriendPlayedGamesResult* param)
{
UE_LOG_ONLINE(VeryVerbose, TEXT("FOnlineAsyncTaskManagerTencent::OnRailGetFriendPlayedGamesResult NOOP %s"), *LexToString(param ? param->get_result() : rail::RailResult::kErrorUnknown));
}
void FOnlineAsyncTaskManagerTencent::OnRailInviteCommandline(const rail::rail_event::RailFriendsGetInviteCommandLine* param)
{
UE_LOG_ONLINE(VeryVerbose, TEXT("FOnlineAsyncTaskManagerTencent::OnRailInviteCommandline NOOP %s"), *LexToString(param ? param->get_result() : rail::RailResult::kErrorUnknown));
}
void FOnlineAsyncTaskManagerTencent::OnRailCancelInviteResult(const rail::rail_event::RailUsersCancelInviteResult* param)
{
UE_LOG_ONLINE(VeryVerbose, TEXT("FOnlineAsyncTaskManagerTencent::OnRailCancelInviteResult NOOP %s"), *LexToString(param ? param->get_result() : rail::RailResult::kErrorUnknown));
}
void FOnlineAsyncTaskManagerTencent::OnRailFriendsSetMetadataResult(const rail::rail_event::RailFriendsSetMetadataResult* param)
{
UE_LOG_ONLINE(VeryVerbose, TEXT("FOnlineAsyncTaskManagerTencent::OnRailFriendsSetMetadataResult NOOP %s"), *LexToString(param ? param->get_result() : rail::RailResult::kErrorUnknown));
}
void FOnlineAsyncTaskManagerTencent::OnRailEventFriendsAddFriendResult(const rail::rail_event::RailFriendsAddFriendResult* param)
{
UE_LOG_ONLINE(VeryVerbose, TEXT("FOnlineAsyncTaskManagerTencent::OnRailEventFriendsAddFriendResult NOOP %s"), *LexToString(param ? param->get_result() : rail::RailResult::kErrorUnknown));
}
void FOnlineAsyncTaskManagerTencent::OnRailFriendsListChanged(const rail::rail_event::RailFriendsListChanged* param)
{
FOnlineAsyncEventRailFriendsListChanged* NewEvent = new FOnlineAsyncEventRailFriendsListChanged(Subsystem, param);
UE_LOG_ONLINE(Verbose, TEXT("%s"), *NewEvent->ToString());
AddToOutQueue(NewEvent);
}
void FOnlineAsyncTaskManagerTencent::OnRailFriendsOnlineStateChanged(const rail::rail_event::RailFriendsOnlineStateChanged* param)
{
FOnlineAsyncEventRailFriendsOnlineStateChanged* NewEvent = new FOnlineAsyncEventRailFriendsOnlineStateChanged(Subsystem, param);
UE_LOG_ONLINE(Verbose, TEXT("%s"), *NewEvent->ToString());
AddToOutQueue(NewEvent);
}
void FOnlineAsyncTaskManagerTencent::OnRailFriendsMetadataChanged(const rail::rail_event::RailFriendsMetadataChanged* param)
{
FOnlineAsyncEventRailFriendsMetadataChanged* NewEvent = new FOnlineAsyncEventRailFriendsMetadataChanged(Subsystem, param);
UE_LOG_ONLINE(Verbose, TEXT("%s"), *NewEvent->ToString());
AddToOutQueue(NewEvent);
}
#endif // WITH_TENCENT_RAIL_SDK
#endif // WITH_TENCENTSDK

View File

@@ -0,0 +1,77 @@
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
#pragma once
#if WITH_TENCENTSDK
#include "RailSDK.h"
#include "OnlineAsyncTaskManager.h"
class FOnlineSubsystemTencent;
/**
* Tencent version of the async task manager to register the various callbacks with the engine
*/
#if WITH_TENCENT_RAIL_SDK
class FOnlineAsyncTaskManagerTencent : public FOnlineAsyncTaskManager, public rail::IRailEvent
#else
class FOnlineAsyncTaskManagerTencent : public FOnlineAsyncTaskManager
#endif
{
protected:
/** Cached reference to the main online subsystem */
FOnlineSubsystemTencent* Subsystem;
FOnlineAsyncTaskManagerTencent();
public:
FOnlineAsyncTaskManagerTencent(FOnlineSubsystemTencent* InSubsystem);
~FOnlineAsyncTaskManagerTencent();
// FOnlineAsyncTaskManager
/**
* ** CALL ONLY FROM ONLINE THREAD **
* Give the online service a chance to do work
*/
virtual void OnlineTick() override;
#if WITH_TENCENT_RAIL_SDK
void RegisterRailEvents();
void UnregisterRailEvents();
void OnRailSystemStateChanged(const rail::rail_event::RailSystemStateChanged* param);
/** Event notification that any of the floating windows have been opened or closed */
void OnRailShowFloatingWindow(const rail::rail_event::ShowFloatingWindowResult* param);
void OnRailShowFloatingNotifyWindow(const rail::rail_event::ShowNotifyWindow* param);
void OnRailInviteSentNotification(const rail::rail_event::RailUsersNotifyInviter* param);
void OnRailInviteUsersResult(const rail::rail_event::RailUsersInviteUsersResult* param);
void OnRailInviteJoinGameResult(const rail::rail_event::RailUsersInviteJoinGameResult* param);
void OnRailFriendsInviteRespondInvitation(const rail::rail_event::RailUsersRespondInvitation* param);
void OnRailFriendsJoinGameByUser(const rail::rail_event::RailPlatformNotifyEventJoinGameByUser* param);
void OnRailAssetsChanged(const rail::rail_event::RailAssetsChanged* param);
void OnRailGetUsersInfo(const rail::rail_event::RailUsersInfoData* param);
void OnRailGetFriendPlayedGamesResult(const rail::rail_event::RailFriendsQueryFriendPlayedGamesResult* param);
void OnRailInviteCommandline(const rail::rail_event::RailFriendsGetInviteCommandLine* param);
void OnRailCancelInviteResult(const rail::rail_event::RailUsersCancelInviteResult* param);
void OnRailFriendsSetMetadataResult(const rail::rail_event::RailFriendsSetMetadataResult* param);
void OnRailEventFriendsAddFriendResult(const rail::rail_event::RailFriendsAddFriendResult* param);
void OnRailFriendsListChanged(const rail::rail_event::RailFriendsListChanged* param);
/** Event notification that remote friend online state has changed */
void OnRailFriendsOnlineStateChanged(const rail::rail_event::RailFriendsOnlineStateChanged* param);
/** Event notification that remote friend metadata keys/values have changed */
void OnRailFriendsMetadataChanged(const rail::rail_event::RailFriendsMetadataChanged* param);
// Begin IRailEvent interface
virtual void OnRailEvent(rail::RAIL_EVENT_ID event_id, rail::EventBase* param) override;
// End IRailEvent interface
TSet<rail::RAIL_EVENT_ID> RegisteredRailEvents;
#endif
};
#endif // WITH_TENCENTSDK

View File

@@ -0,0 +1,73 @@
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
#include "OnlineExternalUITencent.h"
#if WITH_TENCENTSDK
#if WITH_TENCENT_RAIL_SDK
#include "OnlineSubsystemTencent.h"
#include "OnlineAsyncTasksTencent.h"
bool FOnlineExternalUITencent::ShowLoginUI(const int ControllerIndex, bool bShowOnlineOnly, bool bShowSkipButton, const FOnLoginUIClosedDelegate& Delegate)
{
return false;
}
bool FOnlineExternalUITencent::ShowFriendsUI(int32 LocalUserNum)
{
FOnlineAsyncTaskRailShowFloatingWindow* NewTask = new FOnlineAsyncTaskRailShowFloatingWindow(TencentSubsystem, rail::EnumRailWindowType::kRailWindowFriendList);
TencentSubsystem->QueueAsyncTask(NewTask);
return true;
}
bool FOnlineExternalUITencent::ShowInviteUI(int32 LocalUserNum, FName SessionName)
{
return false;
}
bool FOnlineExternalUITencent::ShowAchievementsUI(int32 LocalUserNum)
{
FOnlineAsyncTaskRailShowFloatingWindow* NewTask = new FOnlineAsyncTaskRailShowFloatingWindow(TencentSubsystem, rail::EnumRailWindowType::kRailWindowAchievement);
TencentSubsystem->QueueAsyncTask(NewTask);
return true;
}
bool FOnlineExternalUITencent::ShowLeaderboardUI(const FString& LeaderboardName)
{
FOnlineAsyncTaskRailShowFloatingWindow* NewTask = new FOnlineAsyncTaskRailShowFloatingWindow(TencentSubsystem, rail::EnumRailWindowType::kRailWindowLeaderboard);
TencentSubsystem->QueueAsyncTask(NewTask);
return true;
}
bool FOnlineExternalUITencent::ShowWebURL(const FString& Url, const FShowWebUrlParams& ShowParams, const FOnShowWebUrlClosedDelegate& Delegate)
{
return false;
}
bool FOnlineExternalUITencent::CloseWebURL()
{
return false;
}
bool FOnlineExternalUITencent::ShowProfileUI(const FUniqueNetId& Requestor, const FUniqueNetId& Requestee, const FOnProfileUIClosedDelegate& Delegate)
{
return false;
}
bool FOnlineExternalUITencent::ShowAccountUpgradeUI(const FUniqueNetId& UniqueId)
{
return false;
}
bool FOnlineExternalUITencent::ShowStoreUI(int32 LocalUserNum, const FShowStoreParams& ShowParams, const FOnShowStoreUIClosedDelegate& Delegate)
{
return false;
}
bool FOnlineExternalUITencent::ShowSendMessageUI(int32 LocalUserNum, const FShowSendMessageParams& ShowParams, const FOnShowSendMessageUIClosedDelegate& Delegate)
{
return false;
}
#endif // WITH_TENCENTSDK
#endif // WITH_TENCENT_RAIL_SDK

View File

@@ -0,0 +1,310 @@
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
#pragma once
#if WITH_TENCENTSDK
#if WITH_TENCENT_RAIL_SDK
#include "RailSDK.h"
#include "Interfaces/OnlineFriendsInterface.h"
#include "OnlineSubsystemTencentTypes.h"
#include "OnlineAsyncTasksTencent.h"
#include "OnlineSubsystemTencentPackage.h"
class FOnlineSubsystemTencent;
class FUniqueNetIdRail;
class FOnlineUserPresence;
struct FOnlineError;
/**
* Info associated with an online friend on the Tencent / Rail service
*/
class FOnlineFriendTencent : public FOnlineFriend
{
public:
// FOnlineUser
virtual TSharedRef<const FUniqueNetId> GetUserId() const override;
virtual FString GetRealName() const override;
virtual FString GetDisplayName(const FString& Platform = FString()) const override;
virtual bool GetUserAttribute(const FString& AttrName, FString& OutAttrValue) const override;
// FOnlineFriend
virtual EInviteStatus::Type GetInviteStatus() const override;
virtual const FOnlineUserPresence& GetPresence() const override;
/**
* Init constructor
*/
FOnlineFriendTencent(FOnlineSubsystemTencent* InTencentSubsystem, const TSharedRef<const FUniqueNetIdRail> InUserId);
/**
* Destructor
*/
virtual ~FOnlineFriendTencent()
{
}
/**
* Get account data attribute
*
* @param Key account data entry key
* @param OutVal [out] value that was found
*
* @return true if entry was found
*/
inline bool GetAccountData(const FString& Key, FString& OutVal) const
{
const FString* FoundVal = AccountData.Find(Key);
if (FoundVal != NULL)
{
OutVal = *FoundVal;
return true;
}
return false;
}
/** Used to access presence data for the friend entry */
FOnlineSubsystemTencent* TencentSubsystem;
/** User Id represented as a FUniqueNetId */
TSharedRef<const FUniqueNetIdRail> UserId;
/** Any addition account data associated with the friend */
TMap<FString, FString> AccountData;
};
/**
* Named list of friends
*/
class FOnlineFriendsListTencent
{
public:
/**
* Init/default constructor
*/
FOnlineFriendsListTencent(const FString& InListName = TEXT(""))
: ListName(InListName)
{
}
/** Can have multiple friends lists. Each with its own name */
FString ListName;
/** Array of friends populated by ReadFriendsList */
TArray<TSharedRef<FOnlineFriendTencent> > Friends;
};
/** Mapping from user id to array of friends lists */
typedef TRailIdMap<FOnlineFriendsListTencent> FOnlineFriendsListTencentMap;
/**
* Info associated with a recent player on the Tencent service
*/
class FOnlineRecentPlayerTencent :
public FOnlineRecentPlayer
{
public:
// FOnlineUser
virtual TSharedRef<const FUniqueNetId> GetUserId() const override;
virtual FString GetRealName() const override;
virtual FString GetDisplayName(const FString& Platform = FString()) const override;
virtual bool GetUserAttribute(const FString& AttrName, FString& OutAttrValue) const override;
// FOnlineRecentPlayer
virtual FDateTime GetLastSeen() const override;
/**
* Init/default constructor
*/
FOnlineRecentPlayerTencent(const FUniqueNetId& InUserId)
: UserId(InUserId.AsShared())
{
}
FOnlineRecentPlayerTencent(const TSharedRef<const FUniqueNetId>& InUserId)
: UserId(InUserId)
{
}
FOnlineRecentPlayerTencent(const FString& InUserId = TEXT(""))
: UserId(new FUniqueNetIdRail(InUserId))
{
}
/**
* Destructor
*/
virtual ~FOnlineRecentPlayerTencent()
{
}
/**
* Get account data attribute
*
* @param Key account data entry key
* @param OutVal [out] value that was found
*
* @return true if entry was found
*/
inline bool GetAccountData(const FString& Key, FString& OutVal) const
{
const FString* FoundVal = AccountData.Find(Key);
if (FoundVal != NULL)
{
OutVal = *FoundVal;
return true;
}
return false;
}
/** User Id represented as a FUniqueNetId */
TSharedRef<const FUniqueNetId> UserId;
/** last seen in online game */
FDateTime LastSeen;
/** Any addition account data associated with the recent player */
TMap<FString, FString> AccountData;
};
/** Mapping from user id to list of recent players */
typedef TUniqueNetIdMap<TArray<TSharedRef<FOnlineRecentPlayerTencent>>> FOnlineRecentPlayersTencentMap;
/**
* Tencent / Rail implementation of the online friends interface
*/
class FOnlineFriendsTencent :
public IOnlineFriends,
public TSharedFromThis<FOnlineFriendsTencent, ESPMode::ThreadSafe>
{
public:
//~ Begin IOnlineFriends Interface
virtual bool ReadFriendsList(int32 LocalUserNum, const FString& ListName, const FOnReadFriendsListComplete& Delegate = FOnReadFriendsListComplete()) override;
virtual bool DeleteFriendsList(int32 LocalUserNum, const FString& ListName, const FOnDeleteFriendsListComplete& Delegate = FOnDeleteFriendsListComplete()) override;
virtual bool SendInvite(int32 LocalUserNum, const FUniqueNetId& FriendId, const FString& ListName, const FOnSendInviteComplete& Delegate = FOnSendInviteComplete()) override;
virtual bool AcceptInvite(int32 LocalUserNum, const FUniqueNetId& FriendId, const FString& ListName, const FOnAcceptInviteComplete& Delegate = FOnAcceptInviteComplete()) override;
virtual bool RejectInvite(int32 LocalUserNum, const FUniqueNetId& FriendId, const FString& ListName) override;
virtual bool DeleteFriend(int32 LocalUserNum, const FUniqueNetId& FriendId, const FString& ListName) override;
virtual bool GetFriendsList(int32 LocalUserNum, const FString& ListName, TArray< TSharedRef<FOnlineFriend> >& OutFriends) override;
virtual TSharedPtr<FOnlineFriend> GetFriend(int32 LocalUserNum, const FUniqueNetId& FriendId, const FString& ListName) override;
virtual bool IsFriend(int32 LocalUserNum, const FUniqueNetId& FriendId, const FString& ListName) override;
virtual void AddRecentPlayers(const FUniqueNetId& UserId, const TArray<FReportPlayedWithUser>& InRecentPlayers, const FString& ListName, const FOnAddRecentPlayersComplete& InCompletionDelegate);
virtual bool QueryRecentPlayers(const FUniqueNetId& UserId, const FString& Namespace) override;
virtual bool GetRecentPlayers(const FUniqueNetId& UserId, const FString& Namespace, TArray< TSharedRef<FOnlineRecentPlayer> >& OutRecentPlayers) override;
virtual void DumpRecentPlayers() const override;
virtual bool BlockPlayer(int32 LocalUserNum, const FUniqueNetId& PlayerId) override;
virtual bool UnblockPlayer(int32 LocalUserNum, const FUniqueNetId& PlayerId) override;
virtual bool QueryBlockedPlayers(const FUniqueNetId& UserId) override;
virtual bool GetBlockedPlayers(const FUniqueNetId& UserId, TArray< TSharedRef<FOnlineBlockedPlayer> >& OutBlockedPlayers) override;
virtual void DumpBlockedPlayers() const override;
//~ End IOnlineFriends Interface
// FOnlineFriendsTencent
/**
* Constructor
*
* @param InSubsystem subsystem being used
*/
FOnlineFriendsTencent(FOnlineSubsystemTencent* InSubsystem);
/**
* Destructor
*/
virtual ~FOnlineFriendsTencent();
/**
* Initialize the interface
*
* @return true if successful, false otherwise
*/
bool Init();
/**
* Check to see if a single player is blocked. Used as an alternative to GetBlockedPlayers which involves array copying
*
* @param LocalUserId User whose block list we will be checking against
* @param PeerUserId User who we want to check if they are blocked
*
* @return true if the peer user is blocked, false if not
*/
bool IsPlayerBlocked(const FUniqueNetId& LocalUserId, const FUniqueNetId& PeerUserId) const;
/**
* Called when Rail informs us the friends list has changed
*/
void OnRailFriendsListChanged(const FUniqueNetIdRail& UserId);
private:
/**
* Delegate fired when query user info is complete for a list of Tencent friends
*
* @param LocalUserNum the controller number of the associated user that made the request
* @param bWasSuccessful true if the async action completed without error, false if there was an error
* @param UserIds list of user ids that were queried
* @param ErrorStr string representing the error condition
* @param ListName name of the friends list to use
*/
void OnQueryUsersForFriendsListComplete(int32 LocalUserNum, bool bWasSuccessful, const TArray<TSharedRef<const FUniqueNetId>>& UserIds, const FString& ErrorStr, FString ListName, TArray<TSharedRef<const FUniqueNetId>> ExpectedFriendIds);
/**
* Delegate fired when query presence is complete for a list of Tencent friends
*
* @param TaskResult result of the async action
* @param LocalUserNum the controller number of the associated user that made the request
* @param ListName name of the friends list to use
*/
void OnQueryFriendsPresenceComplete(const FQueryUserPresenceTaskResult& TaskResult, int32 LocalUserNum, FString ListName);
/**
* Notification that login status has changed for a user
*
* @param LocalUserNum id of local user whose login status has changed
*/
void OnLoginChanged(int32 LocalUserNum);
/**
* Find an existing friend entry that is cached
*
* @param LocalUserNum user with friends list to operate on
* @param FriendId id of friend to find
* @param bAddIfMissing add new entry to cache if true
*
* @return friend entry pointer if found or NULL if not found
*/
TSharedPtr<FOnlineFriendTencent> FindFriendEntry(int32 LocalUserNum, const FUniqueNetIdRail& FriendId, bool bAddIfMissing);
/** Called when the SendInvite async task has completed */
void SendInvite_Complete(const FOnlineError& Result, const int32 LocalUserNum, const TSharedRef<const FUniqueNetId> FriendId, const FString ListName, const FOnSendInviteComplete CompletionDelegate);
/**
* Should use the initialization constructor instead
*/
FOnlineFriendsTencent() = delete;
FOnlineSubsystemTencent* TencentSubsystem;
/** Cache of all friends lists for all local users */
FOnlineFriendsListTencentMap FriendsLists;
/** Handle to login change events for clearing friends lists */
FDelegateHandle OnLoginChangedHandle;
/** Handle when a query user info call for reading friends list is complete */
FDelegateHandle OnQueryUsersForFriendsListCompleteDelegate;
/** Cache of all recent players lists for all local users */
FOnlineRecentPlayersTencentMap RecentPlayersLists;
/** Array of delegates for ReadFriendList requests. All will be completed at the same time if there were calls to ReadFriendsList while it was in progress */
TArray<FOnReadFriendsListComplete> OnReadFriendsListCompleteDelegates;
};
typedef TSharedPtr<FOnlineFriendsTencent, ESPMode::ThreadSafe> FOnlineFriendsTencentPtr;
#endif // WITH_TENCENT_RAIL_SDK
#endif // WITH_TENCENTSDK

View File

@@ -0,0 +1,45 @@
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
#include "OnlineIdentityTencent.h"
#include "OnlineSubsystemTencentPCH.h"
#if WITH_TENCENT_RAIL_SDK || WITH_TENCENT_TCLS
bool FOnlineIdentityTencent::GetLocalUserIdx(const FUniqueNetId& UserId, int32& OutLocalIdx) const
{
for (TMap<int32, TSharedPtr<const FUniqueNetId> >::TConstIterator It(UserIds); It; ++It)
{
if (*It->Value == UserId)
{
OutLocalIdx = It->Key;
return true;
}
}
return false;
}
#endif
#if !WITH_TENCENT_RAIL_SDK && !WITH_TENCENT_TCLS
FOnlineIdentityTencent::FOnlineIdentityTencent(FOnlineSubsystemTencent* InSubsystem) {}
FOnlineIdentityTencent::~FOnlineIdentityTencent() {}
TSharedPtr<FUserOnlineAccountTencent> FOnlineIdentityTencent::GetUserAccountTencent(const FUniqueNetId& UserId) const { return nullptr; }
bool FOnlineIdentityTencent::Login(int32 LocalUserNum, const FOnlineAccountCredentials& AccountCredentials){ return false; }
bool FOnlineIdentityTencent::Logout(int32 LocalUserNum){ return false; }
bool FOnlineIdentityTencent::AutoLogin(int32 LocalUserNum){ return false; }
TSharedPtr<FUserOnlineAccount> FOnlineIdentityTencent::GetUserAccount(const FUniqueNetId& UserId) const{ return nullptr; }
TArray<TSharedPtr<FUserOnlineAccount> > FOnlineIdentityTencent::GetAllUserAccounts() const{ return TArray<TSharedPtr<FUserOnlineAccount> >(); }
TSharedPtr<const FUniqueNetId> FOnlineIdentityTencent::GetUniquePlayerId(int32 LocalUserNum) const { return nullptr; }
TSharedPtr<const FUniqueNetId> FOnlineIdentityTencent::CreateUniquePlayerId(uint8* Bytes, int32 Size){ return nullptr; }
TSharedPtr<const FUniqueNetId> FOnlineIdentityTencent::CreateUniquePlayerId(const FString& Str){ return nullptr; }
ELoginStatus::Type FOnlineIdentityTencent::GetLoginStatus(int32 LocalUserNum) const{ return ELoginStatus::NotLoggedIn; }
ELoginStatus::Type FOnlineIdentityTencent::GetLoginStatus(const FUniqueNetId& UserId) const{ return ELoginStatus::NotLoggedIn; }
FString FOnlineIdentityTencent::GetPlayerNickname(int32 LocalUserNum) const{ return FString(); }
FString FOnlineIdentityTencent::GetPlayerNickname(const FUniqueNetId& UserId) const{ return FString(); }
FString FOnlineIdentityTencent::GetAuthToken(int32 LocalUserNum) const{ return FString(); }
void FOnlineIdentityTencent::GetUserPrivilege(const FUniqueNetId& UserId, EUserPrivileges::Type Privilege, const FOnGetUserPrivilegeCompleteDelegate& Delegate){}
FPlatformUserId FOnlineIdentityTencent::GetPlatformUserIdFromUniqueNetId(const FUniqueNetId& UniqueNetId) const { return FPlatformUserId(); }
FString FOnlineIdentityTencent::GetAuthType() const{ return FString(); }
void FOnlineIdentityTencent::RevokeAuthToken(const FUniqueNetId& UserId, const FOnRevokeAuthTokenCompleteDelegate& Delegate){ }
bool FOnlineIdentityTencent::GetLocalUserIdx(const FUniqueNetId& UserId, int32& OutLocalIdx) const { return false; }
#endif // !WITH_TENCENT_RAIL_SDK && !WITH_TENCENT_TCLS

View File

@@ -0,0 +1,372 @@
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
#include "OnlineIdentityTencent.h"
#include "OnlineSubsystemTencentPCH.h"
#if WITH_TENCENTSDK
#if WITH_TENCENT_RAIL_SDK
#include "OnlineIdentityTencent.h"
#include "RailSdkWrapper.h"
#include "OnlineAsyncTasksTencent.h"
// FUserOnlineAccountTencent
// Per request from Tencent - when WeGame does not provide us with a display name, use 'Player One'
static const FString InvalidWeGameDisplayName(TEXT("Player One"));
TSharedRef<const FUniqueNetId> FUserOnlineAccountTencent::GetUserId() const
{
return UserId;
}
FString FUserOnlineAccountTencent::GetRealName() const
{
FString Result;
GetAccountData(TEXT("name"), Result);
return Result;
}
FString FUserOnlineAccountTencent::GetDisplayName(const FString& Platform) const
{
FString Result;
GetAccountData(USER_ATTR_DISPLAYNAME, Result);
return Result;
}
bool FUserOnlineAccountTencent::GetUserAttribute(const FString& AttrName, FString& OutAttrValue) const
{
if (AttrName.Equals(USER_ATTR_ID, ESearchCase::IgnoreCase))
{
OutAttrValue = UserId->ToString();
return true;
}
return GetAccountData(AttrName, OutAttrValue);
}
bool FUserOnlineAccountTencent::SetUserAttribute(const FString& AttrName, const FString& AttrValue)
{
return SetAccountData(AttrName, AttrValue);
}
FString FUserOnlineAccountTencent::GetAccessToken() const
{
return AuthToken;
}
bool FUserOnlineAccountTencent::GetAuthAttribute(const FString& AttrName, FString& OutAttrValue) const
{
return GetUserAttribute(AttrName, OutAttrValue);
}
TSharedPtr<FUserOnlineAccountTencent> FOnlineIdentityTencent::GetUserAccountTencent(const FUniqueNetId& UserId) const
{
TSharedPtr<FUserOnlineAccountTencent> Result;
if (UserAccount.IsValid() &&
*UserAccount->GetUserId() == UserId)
{
Result = UserAccount;
}
return Result;
}
TSharedPtr<FUserOnlineAccount> FOnlineIdentityTencent::GetUserAccount(const FUniqueNetId& UserId) const
{
return GetUserAccountTencent(UserId);
}
TArray<TSharedPtr<FUserOnlineAccount> > FOnlineIdentityTencent::GetAllUserAccounts() const
{
TArray<TSharedPtr<FUserOnlineAccount> > Result;
if (UserAccount.IsValid())
{
Result.Add(UserAccount);
}
return Result;
}
TSharedPtr<const FUniqueNetId> FOnlineIdentityTencent::GetUniquePlayerId(int32 LocalUserNum) const
{
if (LocalUserNum >= 0 && LocalUserNum < MAX_LOCAL_PLAYERS)
{
const TSharedPtr<const FUniqueNetId>* FoundId = UserIds.Find(LocalUserNum);
if (FoundId != nullptr)
{
return *FoundId;
}
}
return nullptr;
}
TSharedPtr<const FUniqueNetId> FOnlineIdentityTencent::CreateUniquePlayerId(uint8* Bytes, int32 Size)
{
if (Bytes != nullptr && Size == sizeof(rail::RailID))
{
return MakeShared<FUniqueNetIdRail>(*reinterpret_cast<const rail::RailID*>(Bytes));
}
return nullptr;
}
TSharedPtr<const FUniqueNetId> FOnlineIdentityTencent::CreateUniquePlayerId(const FString& Str)
{
return MakeShared<FUniqueNetIdRail>(Str);
}
bool FOnlineIdentityTencent::Login(int32 LocalUserNum, const FOnlineAccountCredentials& AccountCredentials)
{
FString ErrorStr;
UE_LOG_ONLINE_IDENTITY(Log, TEXT("Login starting for user %d"), LocalUserNum);
// valid local player index
if (LocalUserNum < 0 || LocalUserNum >= MAX_LOCAL_PLAYERS)
{
ErrorStr = FString::Printf(TEXT("Invalid LocalUserNum=%d"), LocalUserNum);
}
// Check RailSdk
rail::IRailPlayer* RailPlayer = nullptr;
if (ErrorStr.IsEmpty())
{
RailSdkWrapper& RailSDK = RailSdkWrapper::Get();
if (RailSDK.IsInitialized())
{
rail::IRailFactory* const RailFactory = RailSDK.RailFactory();
if (RailFactory)
{
RailPlayer = RailFactory->RailPlayer();
if (!RailPlayer)
{
ErrorStr = TEXT("Failed to get RailPlayer");
}
}
else
{
ErrorStr = TEXT("Failed to get RailFactory");
}
}
else
{
ErrorStr = TEXT("Failed to initialize Rail");
}
}
if (ErrorStr.IsEmpty())
{
const bool bIsNewAccount = !UserAccount.IsValid();
const rail::RailID RailId = RailPlayer->GetRailID();
if (bIsNewAccount)
{
TSharedRef<const FUniqueNetId> UserId = MakeShared<FUniqueNetIdRail>(RailId);
UserAccount = MakeShared<FUserOnlineAccountTencent>(UserId);
// Try to get the display name
rail::RailString RailPlayerName;
rail::RailResult RailPlayerNameResult = RailPlayer->GetPlayerName(&RailPlayerName);
if (RailPlayerNameResult == rail::RailResult::kSuccess)
{
FString PlayerName = LexToString(RailPlayerName);
UserAccount->AccountData.Emplace(USER_ATTR_DISPLAYNAME, MoveTemp(PlayerName));
}
else
{
UE_LOG_ONLINE_IDENTITY(Warning, TEXT("Failed to get RailPlayer PlayerName with result %s"), *LexToString(RailPlayerNameResult));
}
// keep track of user ids for local users
UserIds.Emplace(LocalUserNum, UserAccount->GetUserId());
}
FOnlineAsyncTaskRailAcquireSessionTicket::FCompletionDelegate CompletionDelegate;
CompletionDelegate.BindThreadSafeSP(this, &FOnlineIdentityTencent::OnRailAcquireSessionTicket, LocalUserNum, bIsNewAccount);
Subsystem->QueueAsyncTask(new FOnlineAsyncTaskRailAcquireSessionTicket(Subsystem, RailId, CompletionDelegate));
UE_LOG_ONLINE_IDENTITY(Log, TEXT("Logged in user %d with token=%s"), LocalUserNum, *UserAccount->AuthToken);
}
const bool bWasSuccessful = ErrorStr.IsEmpty();
if (!bWasSuccessful)
{
UE_LOG_ONLINE_IDENTITY(Warning, TEXT("Login request failed. %s"), *ErrorStr);
TriggerOnLoginCompleteDelegates(LocalUserNum, bWasSuccessful, *FUniqueNetIdRail::EmptyId(), ErrorStr);
}
return bWasSuccessful;
}
void FOnlineIdentityTencent::OnRailAcquireSessionTicket(const FOnlineError& OnlineError, const FString& SessionTicket, int32 LocalUserNum, const bool bIsNewUser)
{
if (OnlineError.WasSuccessful())
{
if (UserAccount.IsValid())
{
const FUniqueNetIdRail& UserId = static_cast<const FUniqueNetIdRail&>(*UserAccount->GetUserId());
UserAccount->AuthToken = FString::Printf(TEXT("%llu:%s:%s"), UserId.RailID.get_id(), *Subsystem->GetAppId(), *SessionTicket);
TriggerOnLoginCompleteDelegates(LocalUserNum, true, UserId, OnlineError.GetErrorCode());
if (bIsNewUser)
{
TriggerOnLoginStatusChangedDelegates(LocalUserNum, ELoginStatus::NotLoggedIn, ELoginStatus::LoggedIn, UserId);
TriggerOnLoginChangedDelegates(LocalUserNum);
}
}
else
{
UE_LOG_ONLINE_IDENTITY(Error, TEXT("FOnlineIdentityTencent::OnRailAcquireSessionTicket: Missing UserAccount! Did we call logout?"));
}
}
else
{
// Do not clear the user data, the user will change based on events from Rail
UE_LOG_ONLINE_IDENTITY(Warning, TEXT("Login request failed (delegate). %s"), *OnlineError.ToLogString());
TriggerOnLoginCompleteDelegates(LocalUserNum, false, *FUniqueNetIdRail::EmptyId(), OnlineError.GetErrorCode());
}
}
bool FOnlineIdentityTencent::Logout(int32 LocalUserNum)
{
UE_LOG_ONLINE_IDENTITY(Log, TEXT("Logout user %d"), LocalUserNum);
const ELoginStatus::Type LastLoginStatus = GetLoginStatus(LocalUserNum);
TSharedPtr<const FUniqueNetId> UserId = GetUniquePlayerId(LocalUserNum);
if (UserAccount.IsValid())
{
UserAccount.Reset();
UserIds.Remove(LocalUserNum);
TriggerOnLogoutCompleteDelegates(LocalUserNum, true);
}
else
{
UE_LOG_ONLINE_IDENTITY(Warning, TEXT("No logged in user found for LocalUserNum=%d."), LocalUserNum);
TriggerOnLogoutCompleteDelegates(LocalUserNum, false);
}
if (LastLoginStatus != ELoginStatus::NotLoggedIn && UserId.IsValid())
{
TriggerOnLoginStatusChangedDelegates(LocalUserNum, LastLoginStatus, ELoginStatus::NotLoggedIn, *UserId);
TriggerOnLoginChangedDelegates(LocalUserNum);
}
return true;
}
bool FOnlineIdentityTencent::AutoLogin(int32 LocalUserNum)
{
return Login(LocalUserNum, FOnlineAccountCredentials());
}
ELoginStatus::Type FOnlineIdentityTencent::GetLoginStatus(int32 LocalUserNum) const
{
TSharedPtr<const FUniqueNetId> UserId = GetUniquePlayerId(LocalUserNum);
if (UserId.IsValid())
{
return GetLoginStatus(*UserId);
}
return ELoginStatus::NotLoggedIn;
}
ELoginStatus::Type FOnlineIdentityTencent::GetLoginStatus(const FUniqueNetId& UserId) const
{
//@todo sz - also check WeGame status
if (UserAccount.IsValid() &&
*UserAccount->GetUserId() == UserId &&
!UserAccount->GetAccessToken().IsEmpty())
{
return ELoginStatus::LoggedIn;
}
return ELoginStatus::NotLoggedIn;
}
FString FOnlineIdentityTencent::GetPlayerNickname(int32 LocalUserNum) const
{
TSharedPtr<const FUniqueNetId> UserId = GetUniquePlayerId(LocalUserNum);
if (UserId.IsValid())
{
return GetPlayerNickname(*UserId);
}
return InvalidWeGameDisplayName;
}
FString FOnlineIdentityTencent::GetPlayerNickname(const FUniqueNetId& UserId) const
{
// display name will be cached for users that registered or logged in manually
TSharedPtr<FUserOnlineAccountTencent> FoundUserAccount = GetUserAccountTencent(UserId);
if (FoundUserAccount.IsValid())
{
FString DisplayName = FoundUserAccount->GetDisplayName();
if (!DisplayName.IsEmpty())
{
return DisplayName;
}
}
return InvalidWeGameDisplayName;
}
FString FOnlineIdentityTencent::GetAuthToken(int32 LocalUserNum) const
{
FString AuthToken;
TSharedPtr<const FUniqueNetId> UserId = GetUniquePlayerId(LocalUserNum);
if (UserId.IsValid())
{
TSharedPtr<FUserOnlineAccountTencent> FoundUserAccount = GetUserAccountTencent(*UserId);
if (FoundUserAccount.IsValid())
{
AuthToken = FoundUserAccount->GetAccessToken();
}
}
return AuthToken;
}
FOnlineIdentityTencent::FOnlineIdentityTencent(class FOnlineSubsystemTencent* InSubsystem)
: Subsystem(InSubsystem)
{
}
FOnlineIdentityTencent::~FOnlineIdentityTencent()
{
}
FPlatformUserId FOnlineIdentityTencent::GetPlatformUserIdFromUniqueNetId(const FUniqueNetId& UniqueNetId) const
{
for (int i = 0; i < MAX_LOCAL_PLAYERS; ++i)
{
auto CurrentUniqueId = GetUniquePlayerId(i);
if (CurrentUniqueId.IsValid() && (*CurrentUniqueId == UniqueNetId))
{
return i;
}
}
return PLATFORMUSERID_NONE;
}
void FOnlineIdentityTencent::GetUserPrivilege(const FUniqueNetId& UserId, EUserPrivileges::Type Privilege, const FOnGetUserPrivilegeCompleteDelegate& Delegate)
{
Delegate.ExecuteIfBound(UserId, Privilege, (uint32)EPrivilegeResults::NoFailures);
}
FString FOnlineIdentityTencent::GetAuthType() const
{
return TEXT("wegame");
}
void FOnlineIdentityTencent::RevokeAuthToken(const FUniqueNetId& UserId, const FOnRevokeAuthTokenCompleteDelegate& Delegate)
{
UE_LOG_ONLINE_IDENTITY(Display, TEXT("FOnlineIdentityTencent::RevokeAuthToken not implemented"));
TSharedRef<const FUniqueNetId> UserIdRef(UserId.AsShared());
Subsystem->ExecuteNextTick([UserIdRef, Delegate]()
{
Delegate.ExecuteIfBound(*UserIdRef, FOnlineError(FString(TEXT("RevokeAuthToken not implemented"))));
});
}
#endif // WITH_TENCENT_RAIL_SDK
#endif // WITH_TENCENTSDK

View File

@@ -0,0 +1,220 @@
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
#include "OnlineMessageSanitizerTencent.h"
#include "OnlineSubsystemTencent.h"
#include "OnlineIdentityTencent.h"
#include "RailSdkWrapper.h"
/* Returns a bool indicating whether or not any words were replaced in the InOut string. */
static bool FilterProfanity(FString& InOutString)
{
#if WITH_TENCENT_RAIL_SDK
// Check RailSdk
RailSdkWrapper& RailSDK = RailSdkWrapper::Get();
if (rail::IRailUtils* RailUtils = RailSdkWrapper::Get().RailUtils())
{
// Supposedly we can only send kRailUsersDirtyWordsOnceCheckLimit words under length kRailUsersDirtyWordMaxLength
// but neither of these constants seem to exist in the API.
rail::RailDirtyWordsCheckResult DirtyWordResult;
rail::RailString InRailString;
ToRailString(InOutString, InRailString);
rail::RailResult Result = RailUtils->DirtyWordsFilter(InRailString, true, &DirtyWordResult);
if (Result == rail::RailResult::kSuccess && DirtyWordResult.dirty_type != rail::kRailDirtyWordsTypeNormalAllowWords)
{
InOutString = LexToString(DirtyWordResult.replace_string);
return true;
}
}
#endif
return false;
}
void FSanitizeMessage::Filter()
{
FilterProfanity(RawMessage);
}
void FSanitizeMessage::TriggerDelegate(bool bSuccess)
{
CompletionDelegate.ExecuteIfBound(bSuccess, RawMessage);
}
void FSanitizeMessageArray::Filter()
{
for (FString& RawMessage : RawMessageArray)
{
FilterProfanity(RawMessage);
}
}
void FSanitizeMessageArray::TriggerDelegate(bool bSuccess)
{
CompletionDelegate.ExecuteIfBound(bSuccess, RawMessageArray);
}
void FMessageSanitizerTask::DoWork()
{
// Have the message object filter itself.
Data.Message->Filter();
Data.bSuccess = true;
// Queue up an event in the async task manager so that the delegate can safely trigger in the game thread.
FOnlineAsyncTaskManagerTencent* TaskManager = TencentSubsystem->GetAsyncTaskManager();
if (TaskManager)
{
FAsyncEventSanitizerTaskCompleted* NewEvent = new FAsyncEventSanitizerTaskCompleted(TencentSubsystem, Data);
TaskManager->AddToOutQueue(NewEvent);
}
}
void FAsyncEventSanitizerTaskCompleted::TriggerDelegates()
{
// this must be called from the main thread
check(IsInGameThread());
FOnlineAsyncEvent::TriggerDelegates();
Data.Message->TriggerDelegate(Data.bSuccess);
}
void FMessageSanitizerTencent::SanitizeDisplayName(const FString& DisplayName, const FOnMessageProcessed& CompletionDelegate)
{
const FString* FoundString = WordMap.Find(DisplayName);
if (FoundString)
{
CompletionDelegate.ExecuteIfBound(true, *FoundString);
}
else
{
FOnMessageProcessed MessageSanitizerCallback = FOnMessageProcessed::CreateThreadSafeSP(this, &FMessageSanitizerTencent::HandleMessageSanitized, CompletionDelegate, DisplayName);
TSharedRef<FSanitizeMessage, ESPMode::ThreadSafe> SanitizeMessage = MakeShared<FSanitizeMessage, ESPMode::ThreadSafe>(DisplayName, MessageSanitizerCallback);
ProcessList.Add(SanitizeMessage);
}
}
void FMessageSanitizerTencent::SanitizeDisplayNames(const TArray<FString>& DisplayNames, const FOnMessageArrayProcessed& CompletionDelegate)
{
TArray<FString> AlreadyProcessedMessages;
TArray<int32> AlreadyProcessedIndex;
TArray<FString> MessagesToProcess;
for (int32 iMessageIndex = 0; iMessageIndex < DisplayNames.Num(); iMessageIndex++)
{
const FString& DisplayName = DisplayNames[iMessageIndex];
const FString* FoundString = WordMap.Find(DisplayName);
if (!FoundString)
{
MessagesToProcess.Add(*DisplayName);
}
else
{
AlreadyProcessedMessages.Add(*FoundString);
AlreadyProcessedIndex.Add(iMessageIndex);
}
}
// If we have messages to process, pack them into a struct for processing.
if (MessagesToProcess.Num() != 0)
{
TSharedRef<FMultiPartMessage> MultiPartMessage = MakeShared<FMultiPartMessage>();
MultiPartMessage->MessagesToSanitize = MessagesToProcess;
MultiPartMessage->AlreadyProcessedMessages = MoveTemp(AlreadyProcessedMessages);
MultiPartMessage->AlreadyProcessedIndex = AlreadyProcessedIndex;
FOnMessageArrayProcessed MessageSanitizerCallback = FOnMessageArrayProcessed::CreateRaw(this, &FMessageSanitizerTencent::HandleMessageArraySanitized, CompletionDelegate, MultiPartMessage);
TSharedRef<FSanitizeMessageArray, ESPMode::ThreadSafe> SanitizeMessageArray = MakeShared<FSanitizeMessageArray, ESPMode::ThreadSafe>(MoveTemp(MessagesToProcess), MessageSanitizerCallback);
ProcessList.Add(SanitizeMessageArray);
}
// If we don't have anything to process, it's all been cached
else
{
CompletionDelegate.ExecuteIfBound(true, MoveTemp(AlreadyProcessedMessages));
}
}
void FMessageSanitizerTencent::QueryBlockedUser(int32 LocalUserNum, const FString& FromUserId, const FString& FromPlatform, const FOnQueryUserBlockedResponse& CompletionDelegate)
{
// Not supported, always return that user is not blocked.
FBlockedQueryResult Result;
Result.UserId = FromUserId;
Result.bIsBlocked = false;
CompletionDelegate.ExecuteIfBound(Result);
}
bool FMessageSanitizerTencent::HandleTicker(float DeltaTime)
{
QUICK_SCOPE_CYCLE_COUNTER(STAT_FMessageSanitizerTencent_HandleTicker);
if (ProcessList.Num())
{
FSanitizerTaskData Data(ProcessList[0]);
TSharedRef<MessageSanitizerTask> SanitizerTask = MakeShared<MessageSanitizerTask>(TencentSubsystem, Data);
SanitizerTask->StartBackgroundTask();
CurrentTasks.Add(SanitizerTask);
ProcessList.RemoveAt(0);
}
CleanTaskList();
return true;
}
void FMessageSanitizerTencent::CleanTaskList()
{
for (int i = CurrentTasks.Num() - 1; i >= 0; --i)
{
if (CurrentTasks[i]->IsDone())
{
CurrentTasks.RemoveAt(i);
}
}
}
void FMessageSanitizerTencent::HandleMessageSanitized(bool bSuccess, const FString& SanitizedMessage, FOnMessageProcessed CompletionDelegate, FString UnsanitizedMessage)
{
// Add response
if (!WordMap.Find(UnsanitizedMessage))
{
WordMap.Add(UnsanitizedMessage, SanitizedMessage);
}
CompletionDelegate.ExecuteIfBound(bSuccess, SanitizedMessage);
}
void FMessageSanitizerTencent::HandleMessageArraySanitized(bool bSuccess,
const TArray<FString>& SanitizedMessages,
FOnMessageArrayProcessed CompletionDelegate,
TSharedRef<FMultiPartMessage> MultiPartMessage)
{
TArray<FString> SanitizedStrings;
if (bSuccess == false)
{
CompletionDelegate.ExecuteIfBound(false, SanitizedStrings);
}
else
{
SanitizedStrings = SanitizedMessages;
TArray<FString>& UnsanitizedStrings = MultiPartMessage->MessagesToSanitize;
check(SanitizedStrings.Num() == UnsanitizedStrings.Num())
for (int32 iMessageIndex = 0; iMessageIndex < UnsanitizedStrings.Num(); iMessageIndex++)
{
if (!WordMap.Find(UnsanitizedStrings[iMessageIndex]))
{
WordMap.Add(UnsanitizedStrings[iMessageIndex], SanitizedStrings[iMessageIndex]);
}
}
for (int32 MessageIndex = 0; MessageIndex < MultiPartMessage->AlreadyProcessedMessages.Num(); MessageIndex++)
{
SanitizedStrings.Insert(MultiPartMessage->AlreadyProcessedMessages[MessageIndex], MultiPartMessage->AlreadyProcessedIndex[MessageIndex]);
}
CompletionDelegate.ExecuteIfBound(true, SanitizedStrings);
}
}
FMessageSanitizerTencent::~FMessageSanitizerTencent()
{
ProcessList.Empty();
FTicker::GetCoreTicker().RemoveTicker(TickDelegateHandle);
}

View File

@@ -0,0 +1,184 @@
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
#pragma once
#include "OnlineSubsystem.h"
#include "Interfaces/IMessageSanitizerInterface.h"
#include "OnlineSubsystemTencent.h"
#include "OnlineAsyncTaskManagerTencent.h"
#include "Async/AsyncWork.h"
#include "Containers/Ticker.h"
class FOnlineSubsystemTencent;
/* Interface for Message sanitization data */
struct ISanitizeMessage
{
virtual ~ISanitizeMessage() {}
virtual void Filter() = 0;
virtual void TriggerDelegate(bool bSuccess) = 0;
};
/* Sanitization data holding a single string to filter */
struct FSanitizeMessage : public ISanitizeMessage
{
FSanitizeMessage(const FString& InRawMessage, FOnMessageProcessed InProcessCompleteDelegate)
: CompletionDelegate(InProcessCompleteDelegate)
, RawMessage(InRawMessage)
{
}
virtual ~FSanitizeMessage(){}
virtual void Filter() override;
virtual void TriggerDelegate(bool bSuccess) override;
FOnMessageProcessed CompletionDelegate;
FString RawMessage;
};
/* Sanitization data holding an array of strings to filter */
struct FSanitizeMessageArray : public ISanitizeMessage
{
FSanitizeMessageArray(TArray<FString>&& InRawMessageArray, FOnMessageArrayProcessed InProcessCompleteDelegate)
: CompletionDelegate(InProcessCompleteDelegate)
, RawMessageArray(InRawMessageArray)
{
}
virtual ~FSanitizeMessageArray() {}
virtual void Filter() override;
virtual void TriggerDelegate(bool bSuccess) override;
FOnMessageArrayProcessed CompletionDelegate;
TArray<FString> RawMessageArray;
};
/* Structure used to tie the filtered words back to the original request*/
struct FMultiPartMessage
{
TArray<FString> AlreadyProcessedMessages;
TArray<int32> AlreadyProcessedIndex;
TArray<FString> MessagesToSanitize;
};
struct FSanitizerTaskData
{
FSanitizerTaskData(TSharedRef<ISanitizeMessage, ESPMode::ThreadSafe> InMessage)
: Message(InMessage)
, bSuccess(false)
{}
TSharedRef<ISanitizeMessage, ESPMode::ThreadSafe> Message;
bool bSuccess;
};
// worker task
class FMessageSanitizerTask : public FNonAbandonableTask
{
public:
/** Constructor */
FMessageSanitizerTask(FOnlineSubsystemTencent * InTencentSubsystem, const FSanitizerTaskData & InData)
: TencentSubsystem(InTencentSubsystem), Data(InData)
{
}
/** Performs work on thread */
void DoWork();
/** Returns the stat id for this task */
FORCEINLINE TStatId GetStatId() const
{
RETURN_QUICK_DECLARE_CYCLE_STAT(FMessageSanitizerTask, STATGROUP_ThreadPoolAsyncTasks);
}
private:
FOnlineSubsystemTencent* TencentSubsystem;
FSanitizerTaskData Data;
};
typedef FAsyncTask<FMessageSanitizerTask> MessageSanitizerTask;
class FAsyncEventSanitizerTaskCompleted : public FOnlineAsyncEvent<FOnlineSubsystemTencent>
{
private:
FSanitizerTaskData Data;
public:
/**
* Constructor.
*
* @param InTencentSubsystem The owner of the external UI interface that triggered this event.
* @param InData All the data relating to the task
*/
FAsyncEventSanitizerTaskCompleted(FOnlineSubsystemTencent* InTencentSubsystem, const FSanitizerTaskData & InData) :
FOnlineAsyncEvent(InTencentSubsystem),
Data(InData)
{
}
virtual FString ToString() const override
{
return TEXT("Sanitize string complete");
}
virtual void TriggerDelegates() override;
};
/**
* Implements the Tencent specific interface chat message sanitization
*/
class FMessageSanitizerTencent :
public IMessageSanitizer
{
public:
// IMessageSanitizer
virtual void SanitizeDisplayName(const FString& DisplayName, const FOnMessageProcessed& CompletionDelegate) override;
virtual void SanitizeDisplayNames(const TArray<FString>& DisplayNames, const FOnMessageArrayProcessed& CompletionDelegate) override;
virtual void QueryBlockedUser(int32 LocalUserNum, const FString& FromUserId, const FString& FromPlatform, const FOnQueryUserBlockedResponse& CompletionDelegate) override;
virtual void ResetBlockedUserCache() override {}
// FMessageSanitizerSwitch
explicit FMessageSanitizerTencent(FOnlineSubsystemTencent* InTencentSubsystem) :
TencentSubsystem(InTencentSubsystem)
{
check(TencentSubsystem);
FTickerDelegate TickDelegate = FTickerDelegate::CreateRaw(this, &FMessageSanitizerTencent::HandleTicker);
TickDelegateHandle = FTicker::GetCoreTicker().AddTicker(TickDelegate, 1.0f);
}
virtual ~FMessageSanitizerTencent();
private:
bool HandleTicker(float DeltaTime);
void CleanTaskList();
void HandleMessageSanitized(bool bSuccess, const FString& SanitizedMessage, FOnMessageProcessed CompletionDelegate, FString UnsanitizedMessage);
void HandleMessageArraySanitized(bool bSuccess, const TArray<FString>& SanitizedMessages,
FOnMessageArrayProcessed CompletionDelegate,
TSharedRef<FMultiPartMessage> MultiPartMessage);
private:
// Holds the list of messages being processed
TArray<TSharedRef<ISanitizeMessage, ESPMode::ThreadSafe>> ProcessList;
/** List of current tasks */
TArray<TSharedPtr<MessageSanitizerTask>> CurrentTasks;
// Holds a map of sanitized words
TMap<FString, FString> WordMap;
/** Handle to the registered TickDelegate. */
FDelegateHandle TickDelegateHandle;
/** Reference to the main Tencent subsystem */
FOnlineSubsystemTencent* TencentSubsystem;
};
typedef TSharedPtr<FMessageSanitizerTencent, ESPMode::ThreadSafe> FMessageSanitizerTencentPtr;

View File

@@ -0,0 +1,116 @@
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
#include "OnlinePlayTimeLimitTencent.h"
#include "OnlineSubsystemTencentPCH.h"
#if WITH_TENCENT_RAIL_SDK
#include "RailSdkWrapper.h"
FOnlinePlayTimeLimitUserTencentRail::~FOnlinePlayTimeLimitUserTencentRail()
{
if (IOnlineSubsystem::IsLoaded())
{
FOnlineSubsystemTencent* OSS = StaticCast<FOnlineSubsystemTencent*>(IOnlineSubsystem::Get(TENCENT_SUBSYSTEM));
if (OSS)
{
OSS->ClearOnAASDialogDelegate_Handle(AASDelegateHandle);
}
}
}
void FOnlinePlayTimeLimitUserTencentRail::Init()
{
FPlayTimeLimitUser::Init();
FOnlineSubsystemTencent* OSS = StaticCast<FOnlineSubsystemTencent*>(IOnlineSubsystem::Get(TENCENT_SUBSYSTEM));
if (OSS)
{
const FOnAASDialogDelegate& AASDelegate = FOnAASDialogDelegate::CreateThreadSafeSP(this, &FOnlinePlayTimeLimitUserTencentRail::HandleAASDialog);
AASDelegateHandle = OSS->AddOnAASDialogDelegate_Handle(AASDelegate);
}
}
bool FOnlinePlayTimeLimitUserTencentRail::HasTimeLimit() const
{
bool bHasTimeLimit = false;
rail::IRailPlayer* const RailPlayer = RailSdkWrapper::Get().RailPlayer();
if (RailPlayer)
{
bHasTimeLimit = RailPlayer->IsGameRevenueLimited();
}
else
{
UE_LOG_ONLINE(Warning, TEXT("HasTimeLimit: Missing RailPlayer"));
}
return bHasTimeLimit;
}
int32 FOnlinePlayTimeLimitUserTencentRail::GetPlayTimeMinutes() const
{
int32 PlayTimeMinutes = 0;
// Only track number of minutes played for users that have a limit
if (HasTimeLimit())
{
rail::IRailPlayer* const RailPlayer = RailSdkWrapper::Get().RailPlayer();
check(RailPlayer); // HasTimeLimit should only return true if everything is valid
// @todo use new API if it becomes available, for now guess based on reward rate
float RewardRate = RailPlayer->GetRateOfGameRevenue();
if (FMath::IsNearlyEqual(RewardRate, 1.0f, KINDA_SMALL_NUMBER))
{
// Full rewards up to 3 hours
PlayTimeMinutes = 0;
}
else if (FMath::IsNearlyEqual(RewardRate, 0.5f, KINDA_SMALL_NUMBER))
{
// Half rewards from 3 hours to 5 hours
PlayTimeMinutes = 60 * 3;
}
else if (FMath::IsNearlyZero(RewardRate, KINDA_SMALL_NUMBER))
{
// No rewards after 5 hours
PlayTimeMinutes = 60 * 5;
}
else
{
static bool bWarned = false;
if (!bWarned)
{
UE_LOG_ONLINE(Warning, TEXT("GetPlayTimeMinutes: Received RewardRate=%0.4f, unexpected"), RewardRate);
bWarned = true;
}
// Assume 5 hours then.
PlayTimeMinutes = 60 * 5;
}
}
return PlayTimeMinutes;
}
float FOnlinePlayTimeLimitUserTencentRail::GetRewardRate() const
{
float RewardRate = 1.0f;
if (HasTimeLimit())
{
rail::IRailPlayer* const RailPlayer = RailSdkWrapper::Get().RailPlayer();
check(RailPlayer); // HasTimeLimit should only return true if everything is valid
RewardRate = RailPlayer->GetRateOfGameRevenue();
}
return RewardRate;
}
void FOnlinePlayTimeLimitUserTencentRail::HandleAASDialog(const FString& DialogTitle, const FString& DialogText, const FString& ButtonText)
{
// RailSDK has told us that we should display an anti addiction message.
// Set time until next message to 0, and let the PlayTimeLimit system handle
// displaying the message.
double Now = FPlatformTime::Seconds();
OverrideDialogTitle = DialogTitle;
OverrideDialogText = DialogText;
OverrideButtonText = ButtonText;
NextNotificationTime = Now;
}
#endif // WITH_TENCENT_RAIL_SDK

View File

@@ -0,0 +1,36 @@
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
#pragma once
#if WITH_TENCENTSDK
#if WITH_TENCENT_RAIL_SDK
#include "PlayTimeLimitUser.h"
class ONLINESUBSYSTEMTENCENT_API FOnlinePlayTimeLimitUserTencentRail
: public FPlayTimeLimitUser
{
public:
explicit FOnlinePlayTimeLimitUserTencentRail(const TSharedRef<const FUniqueNetId>& InUserId)
: FPlayTimeLimitUser(InUserId)
{}
~FOnlinePlayTimeLimitUserTencentRail();
//~ Begin FPlayTimeLimitUser Interface
virtual bool HasTimeLimit() const override;
virtual int32 GetPlayTimeMinutes() const override;
virtual float GetRewardRate() const override;
virtual void Init() override;
// Tencent display times are controlled by Rail SDK events.
// just clear the existing time if an attempt is made.
virtual void SetNextNotificationTime(const TOptional<double>& InNextNotificationTime) override { NextNotificationTime = TOptional<double>(); }
//~ End FPlayTimeLimitUser Interface
void HandleAASDialog(const FString& DialogTitle, const FString& DialogText, const FString& ButtonText);
FDelegateHandle AASDelegateHandle;
};
#endif // WITH_TENCENT_RAIL_SDK
#endif // WITH_TENCENTSDK

View File

@@ -0,0 +1,343 @@
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
#include "OnlinePresenceTencent.h"
#include "OnlineSubsystemTencentPCH.h"
#if WITH_TENCENTSDK
#if WITH_TENCENT_RAIL_SDK
#include "OnlineSubsystemTencent.h"
#include "OnlineIdentityTencent.h"
#include "OnlineSessionTencent.h"
#include "MetadataKeysRail.h"
FOnlinePresenceTencent::FOnlinePresenceTencent(FOnlineSubsystemTencent* InSubsystem)
: TencentSubsystem(InSubsystem)
{
}
FOnlinePresenceTencent::~FOnlinePresenceTencent()
{
IOnlineIdentityPtr IdentityInt = TencentSubsystem->GetIdentityInterface();
if (IdentityInt.IsValid())
{
IdentityInt->ClearOnLoginChangedDelegate_Handle(OnLoginChangedHandle);
}
}
bool FOnlinePresenceTencent::Init()
{
IOnlineIdentityPtr IdentityInt = TencentSubsystem->GetIdentityInterface();
if (IdentityInt.IsValid())
{
OnLoginChangedHandle = IdentityInt->AddOnLoginChangedDelegate_Handle(FOnLoginChangedDelegate::CreateThreadSafeSP(this, &FOnlinePresenceTencent::OnLoginChanged));
FOnFriendMetadataChangedDelegate Delegate = FOnFriendMetadataChangedDelegate::CreateThreadSafeSP(this, &FOnlinePresenceTencent::OnFriendMetadataChangedEvent);
OnFriendMetadataChangedDelegateHandle = TencentSubsystem->AddOnFriendMetadataChangedDelegate_Handle(Delegate);
if (rail::IRailFriends* RailFriends = RailSdkWrapper::Get().RailFriends())
{
// Cache the initial online state of all friends
rail::RailArray<rail::RailFriendInfo> Friends;
rail::RailResult Result = RailFriends->GetFriendsList(&Friends);
if (Result == rail::kSuccess)
{
TArray<TSharedRef<const FUniqueNetId>> FriendIds;
for (uint32 RailIdx = 0; RailIdx < Friends.size(); ++RailIdx)
{
const rail::RailFriendInfo& RailFriendInfo(Friends[RailIdx]);
if (RailFriendInfo.friend_rail_id != rail::kInvalidRailId)
{
TSharedRef<const FUniqueNetId> FriendId(MakeShared<const FUniqueNetIdRail>(RailFriendInfo.friend_rail_id));
UE_LOG_ONLINE_PRESENCE(VeryVerbose, TEXT("Friend Id: %s State: %s"), *FriendId->ToDebugString(), *LexToString(RailFriendInfo.online_state.friend_online_state));
SetUserOnlineState(*FriendId, RailOnlineStateToOnlinePresence(RailFriendInfo.online_state.friend_online_state));
}
else
{
UE_LOG_ONLINE_PRESENCE(Warning, TEXT("Invalid friend in friends list"));
}
}
}
else
{
UE_LOG_ONLINE_PRESENCE(Warning, TEXT("Unable to read friends friends list"));
}
}
else
{
UE_LOG_ONLINE_PRESENCE(Warning, TEXT("Rail friends interface is null"));
}
return true;
}
return false;
}
void FOnlinePresenceTencent::Shutdown()
{
TencentSubsystem->ClearOnFriendMetadataChangedDelegate_Handle(OnFriendMetadataChangedDelegateHandle);
}
void FOnlinePresenceTencent::SetUserOnlineState(const FUniqueNetId& UserId, EOnlinePresenceState::Type NewState)
{
const TSharedRef<FOnlineUserPresenceTencent>* Found = CachedPresence.Find(UserId.AsShared());
if (Found != nullptr)
{
(*Found)->bIsOnline = (NewState != EOnlinePresenceState::Type::Offline);
(*Found)->Status.State = NewState;
}
EOnlinePresenceState::Type& OnlineState = UserOnlineStatus.FindOrAdd(UserId.AsShared());
OnlineState = NewState;
}
void FOnlinePresenceTencent::OnLoginChanged(int32 LocalUserNum)
{
IOnlineIdentityPtr IdentityInt = TencentSubsystem->GetIdentityInterface();
if (IdentityInt.IsValid())
{
TSharedPtr<const FUniqueNetIdRail> UserId = StaticCastSharedPtr<const FUniqueNetIdRail>(IdentityInt->GetUniquePlayerId(LocalUserNum));
if (UserId.IsValid())
{
ELoginStatus::Type LoginStatus = IdentityInt->GetLoginStatus(LocalUserNum);
if (LoginStatus == ELoginStatus::NotLoggedIn)
{
FOnlineAsyncTaskRailClearAllMetadata* NewTask = new FOnlineAsyncTaskRailClearAllMetadata(TencentSubsystem, *UserId);
TencentSubsystem->QueueAsyncTask(NewTask);
int32 NumRemoved = CachedPresence.Remove(UserId.ToSharedRef());
}
}
}
}
void FOnlinePresenceTencent::OnFriendMetadataChangedEvent(const FUniqueNetId& UserId, const FMetadataPropertiesRail& Metadata)
{
UE_LOG_ONLINE_PRESENCE(Verbose, TEXT("FOnlinePresenceTencent::OnFriendMetadataChangedEvent"));
}
bool IsPresenceEqual(const FOnlineUserPresenceStatus& A, const FOnlineUserPresenceStatus& B)
{
// Session and joinability details are updated internally and don't need comparison
const bool bEqual = (A.StatusStr == B.StatusStr) &&
(A.State == B.State) &&
(A.Properties.OrderIndependentCompareEqual(B.Properties));
return bEqual;
}
void FOnlinePresenceTencent::SetPresence(const FUniqueNetId& User, const FOnlineUserPresenceStatus& Status, const FOnPresenceTaskCompleteDelegate& Delegate)
{
bool bNeedsUpdate = true;
TSharedRef<const FUniqueNetId> UserPtr = User.AsShared();
TSharedRef<FOnlineUserPresenceTencent>* Cached = CachedPresence.Find(User.AsShared());
if (Cached != nullptr)
{
bNeedsUpdate = !IsPresenceEqual((*Cached)->Status, Status);
}
else
{
Cached = &CachedPresence.Add(User.AsShared(), MakeShared<FOnlineUserPresenceTencent>());
}
(*Cached)->Status = Status;
if (bNeedsUpdate)
{
FMetadataPropertiesRail Metadata;
Metadata.Add(RAIL_PRESENCE_STATUS_KEY, Status.StatusStr);
Metadata.Add(RAIL_PRESENCE_APPID_KEY, TencentSubsystem->GetAppId());
Metadata.Append(Status.Properties);
GetGameSessionPresenceData(Metadata);
FOnlineAsyncTaskRailSetUserMetadata* NewTask = new FOnlineAsyncTaskRailSetUserPresence(TencentSubsystem, Metadata, FOnOnlineAsyncTaskRailSetUserMetadataComplete::CreateLambda([Delegate, UserPtr](const FSetUserMetadataTaskResult& Result)
{
Delegate.ExecuteIfBound(*UserPtr, Result.Error.WasSuccessful());
}));
TencentSubsystem->QueueAsyncTask(NewTask);
}
else
{
UE_LOG_ONLINE_PRESENCE(Verbose, TEXT("SetPresence data already set."));
TencentSubsystem->ExecuteNextTick([UserPtr, Delegate]()
{
Delegate.ExecuteIfBound(*UserPtr, true);
});
}
}
void FOnlinePresenceTencent::GetGameSessionPresenceData(FMetadataPropertiesRail& InMetadata)
{
// Get the user's session, if any
FString UserSessionId;
bool bIsOnline = true;
bool bIsPlaying = false;
bool bIsJoinable = false;
bool bHasVoiceSupport = false;
FOnlineSessionTencentPtr SessionInt = StaticCastSharedPtr<FOnlineSessionTencent>(TencentSubsystem->GetSessionInterface());
if (SessionInt.IsValid())
{
bool bPublicJoinable = false;
bool bFriendJoinable = false;
bool bInviteOnly = false;
bool bAllowInvites = false;
FNamedOnlineSession* PresenceSession = SessionInt->GetPresenceSession();
if (PresenceSession != nullptr &&
PresenceSession->GetJoinability(bPublicJoinable, bFriendJoinable, bInviteOnly, bAllowInvites))
{
TSharedPtr<FOnlineSessionInfo> UserSessionInfo = PresenceSession->SessionInfo;
if (UserSessionInfo.IsValid())
{
bIsPlaying = true;
UserSessionId = UserSessionInfo->GetSessionId().ToString();
bIsJoinable = (bPublicJoinable || bFriendJoinable) && (!bInviteOnly && bAllowInvites);
}
}
}
int32 NumBits = 0;
uint32 PresenceBits = 0;
PresenceBits |= bIsOnline ? (1 << NumBits) : 0; NumBits++;
PresenceBits |= bIsPlaying ? (1 << NumBits) : 0; NumBits++;
PresenceBits |= bIsJoinable ? (1 << NumBits) : 0; NumBits++;
PresenceBits |= bHasVoiceSupport ? (1 << NumBits) : 0; NumBits++;
InMetadata.Add(RAIL_PRESENCE_PRESENCEBITS_KEY, FVariantData(PresenceBits));
InMetadata.Add(RAIL_PRESENCE_SESSION_ID_KEY, FVariantData(UserSessionId));
}
void FOnlinePresenceTencent::UpdatePresenceFromSessionData()
{
FMetadataPropertiesRail Metadata;
GetGameSessionPresenceData(Metadata);
FOnlineAsyncTaskRailSetUserMetadata* NewTask = new FOnlineAsyncTaskRailSetUserMetadata(TencentSubsystem, Metadata, FOnOnlineAsyncTaskRailSetUserMetadataComplete::CreateLambda([](const FSetUserMetadataTaskResult& Result)
{
UE_LOG_ONLINE_PRESENCE(Verbose, TEXT("UpdatePresenceFromSessionData %s"), *Result.Error.ToLogString());
}));
TencentSubsystem->QueueAsyncTask(NewTask);
}
void FOnlinePresenceTencent::QueryPresence(const FUniqueNetId& User, const FOnPresenceTaskCompleteDelegate& Delegate)
{
TSharedRef<const FUniqueNetId> UserPtr = User.AsShared();
TSharedRef<FOnlinePresenceTencent, ESPMode::ThreadSafe> StrongThis = AsShared();
FOnlineAsyncTaskRailGetUserPresence* NewTask = new FOnlineAsyncTaskRailGetUserPresence(TencentSubsystem, (const FUniqueNetIdRail&)User, FOnOnlineAsyncTaskRailGetUserMetadataComplete::CreateLambda([StrongThis, Delegate, UserPtr](const FGetUserMetadataTaskResult& InResult)
{
if (InResult.Error.WasSuccessful() && InResult.UserId.IsValid())
{
const TSharedRef<FOnlineUserPresenceTencent>* Cached = StrongThis->CachedPresence.Find(InResult.UserId.ToSharedRef());
if (Cached == nullptr)
{
Cached = &StrongThis->CachedPresence.Add(InResult.UserId.ToSharedRef(), MakeShared<FOnlineUserPresenceTencent>());
}
const FVariantData* PresenceBitsData = InResult.Metadata.Find(RAIL_PRESENCE_PRESENCEBITS_KEY);
if (PresenceBitsData && PresenceBitsData->GetType() == EOnlineKeyValuePairDataType::UInt32)
{
uint32 PresenceBits;
PresenceBitsData->GetValue(PresenceBits);
int32 NumBits = 0;
(*Cached)->bIsOnline = !!(PresenceBits & (1 << NumBits)); NumBits++;
(*Cached)->bIsPlaying = !!(PresenceBits & (1 << NumBits)); NumBits++;
(*Cached)->bIsJoinable = !!(PresenceBits & (1 << NumBits)); NumBits++;
(*Cached)->bHasVoiceSupport = !!(PresenceBits & (1 << NumBits)); NumBits++;
}
else
{
(*Cached)->bIsOnline = false;
(*Cached)->bIsPlaying = false;
(*Cached)->bIsJoinable = false;
(*Cached)->bHasVoiceSupport = false;
}
const FVariantData* PresenceSessionIdData = InResult.Metadata.Find(RAIL_PRESENCE_SESSION_ID_KEY);
if (PresenceSessionIdData && PresenceSessionIdData->GetType() == EOnlineKeyValuePairDataType::String)
{
FString SessionIdStr;
PresenceSessionIdData->GetValue(SessionIdStr);
if (!SessionIdStr.IsEmpty())
{
(*Cached)->SessionId = MakeShared<const FUniqueNetIdString>(SessionIdStr);
}
}
else
{
(*Cached)->SessionId = FUniqueNetIdRail::EmptyId();
}
const FVariantData* AppIdData = InResult.Metadata.Find(RAIL_PRESENCE_APPID_KEY);
if (AppIdData && AppIdData->GetType() == EOnlineKeyValuePairDataType::String)
{
(*Cached)->bIsPlayingThisGame = (StrongThis->TencentSubsystem->GetAppId() == AppIdData->ToString());
}
else
{
(*Cached)->bIsPlayingThisGame = false;
}
const FVariantData* StatusData = InResult.Metadata.Find(RAIL_PRESENCE_STATUS_KEY);
if (StatusData && StatusData->GetType() == EOnlineKeyValuePairDataType::String)
{
StatusData->GetValue((*Cached)->Status.StatusStr);
}
else
{
(*Cached)->Status.StatusStr.Empty();
}
EOnlinePresenceState::Type OnlineState = EOnlinePresenceState::Offline;
if (const EOnlinePresenceState::Type* UserOnlineState = StrongThis->UserOnlineStatus.Find(InResult.UserId.ToSharedRef()))
{
// Override the presence data with latest state from Rail status
OnlineState = *UserOnlineState;
(*Cached)->bIsOnline = (OnlineState != EOnlinePresenceState::Offline);
}
else if (PresenceBitsData)
{
// No cached data but presence key data
OnlineState = (*Cached)->bIsOnline ? EOnlinePresenceState::Online : EOnlinePresenceState::Offline;
}
else
{
// Neither pieces of information has to mean the user is offline
(*Cached)->bIsOnline = false;
}
(*Cached)->Status.State = OnlineState;
(*Cached)->Status.Properties = InResult.Metadata;
}
Delegate.ExecuteIfBound(*UserPtr, InResult.Error.WasSuccessful());
}));
TencentSubsystem->QueueAsyncTask(NewTask);
}
EOnlineCachedResult::Type FOnlinePresenceTencent::GetCachedPresence(const FUniqueNetId& User, TSharedPtr<FOnlineUserPresence>& OutPresence)
{
EOnlineCachedResult::Type Result = EOnlineCachedResult::NotFound;
const TSharedRef<FOnlineUserPresenceTencent>* Found = CachedPresence.Find(User.AsShared());
if (Found != nullptr)
{
Result = EOnlineCachedResult::Success;
OutPresence = *Found;
}
return Result;
}
EOnlineCachedResult::Type FOnlinePresenceTencent::GetCachedPresenceForApp(const FUniqueNetId& LocalUserId, const FUniqueNetId& User, const FString& AppId, TSharedPtr<FOnlineUserPresence>& OutPresence)
{
/** NYI */
return EOnlineCachedResult::Type::NotFound;
}
#endif // WITH_TENCENTSDK
#endif // WITH_TENCENT_RAIL_SDK

View File

@@ -0,0 +1,151 @@
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
#include "OnlinePurchaseTencent.h"
#if WITH_TENCENT_RAIL_SDK
#include "OnlineSubsystemTencent.h"
#include "OnlineError.h"
#include "OnlineAsyncTasksTencent.h"
#include "Interfaces/OnlineIdentityInterface.h"
FOnlinePurchaseTencent::FOnlinePurchaseTencent(FOnlineSubsystemTencent* const InSubsystem)
: Subsystem(InSubsystem)
{
check(Subsystem != nullptr);
}
bool FOnlinePurchaseTencent::IsAllowedToPurchase(const FUniqueNetId& UserId)
{
const bool bResult = true;
return bResult;
}
void FOnlinePurchaseTencent::Checkout(const FUniqueNetId& UserId, const FPurchaseCheckoutRequest& CheckoutRequest, const FOnPurchaseCheckoutComplete& Delegate)
{
FOnlineError Result(true);
// Validate user
{
const IOnlineIdentityPtr IdentityInt = Subsystem->GetIdentityInterface();
if (IdentityInt.IsValid())
{
ELoginStatus::Type LoginStatus = IdentityInt->GetLoginStatus(UserId);
if (LoginStatus != ELoginStatus::LoggedIn)
{
Result.SetFromErrorCode(TEXT("com.epicgames.purchase.invalid_user"));
}
}
else
{
Result.SetFromErrorCode(TEXT("com.epicgames.purchase.missing_identity"));
}
Result.bSucceeded = Result.ErrorCode.IsEmpty();
}
// Validate request
if (Result.WasSuccessful())
{
if (CheckoutRequest.PurchaseOffers.Num() <= 0)
{
Result.SetFromErrorCode(TEXT("com.epicgames.purchase.no_offers"));
}
Result.bSucceeded = Result.ErrorCode.IsEmpty();
}
// Only allow one request at a time
if (Result.WasSuccessful())
{
if (bCheckoutPending)
{
Result.SetFromErrorCode(TEXT("com.epicgames.purchase.already_in_checkout"));
}
Result.bSucceeded = Result.ErrorCode.IsEmpty();
}
if (Result.WasSuccessful())
{
bCheckoutPending = true;
FOnOnlineAsyncTaskRailPurchaseProductsComplete CompletionDelegate;
CompletionDelegate.BindThreadSafeSP(this, &FOnlinePurchaseTencent::Checkout_Complete, Delegate);
FOnlineAsyncTaskRailPurchaseProducts* AsyncTask = new FOnlineAsyncTaskRailPurchaseProducts(Subsystem, UserId.AsShared(), CheckoutRequest, CompletionDelegate);
Subsystem->QueueAsyncTask(AsyncTask);
}
if (!Result.WasSuccessful())
{
UE_LOG_ONLINE_PURCHASE(Log, TEXT("Checkout: Failed with Result=[%s]"), *Result.ToLogString());
Subsystem->ExecuteNextTick([Result = MoveTemp(Result), Delegate]()
{
static const TSharedRef<FPurchaseReceipt> BlankReceipt(MakeShared<FPurchaseReceipt>());
Delegate.ExecuteIfBound(Result, BlankReceipt);
});
}
}
void FOnlinePurchaseTencent::Checkout_Complete(const FPurchaseProductsTaskResult& Result, FOnPurchaseCheckoutComplete Delegate)
{
UE_LOG_ONLINE_PURCHASE(Log, TEXT("Checkout_Complete: [%s]"), *Result.Error.ToLogString());
bCheckoutPending = false;
static TSharedRef<FPurchaseReceipt> EmptyReceipt = MakeShared<FPurchaseReceipt>();
Delegate.ExecuteIfBound(Result.Error, Result.Error.WasSuccessful() ? Result.PurchaseReceipt.ToSharedRef() : EmptyReceipt);
}
void FOnlinePurchaseTencent::FinalizePurchase(const FUniqueNetId& UserId, const FString& ReceiptId)
{
// NYI
}
void FOnlinePurchaseTencent::RedeemCode(const FUniqueNetId& UserId, const FRedeemCodeRequest& RedeemCodeRequest, const FOnPurchaseRedeemCodeComplete& Delegate)
{
// NYI
Subsystem->ExecuteNextTick([Delegate]()
{
static const FOnlineError NotImplementedResult(TEXT("not implemented"));
static const TSharedRef<FPurchaseReceipt> BlankReceipt(MakeShared<FPurchaseReceipt>());
Delegate.ExecuteIfBound(NotImplementedResult, BlankReceipt);
});
}
void FOnlinePurchaseTencent::QueryReceipts(const FUniqueNetId& UserId, bool bRestoreReceipts, const FOnQueryReceiptsComplete& Delegate)
{
const TSharedRef<const FUniqueNetId> UserIdRef(UserId.AsShared());
FOnOnlineAsyncTaskRailRequestAllAssetsComplete CompletionDelegate;
CompletionDelegate.BindThreadSafeSP(this, &FOnlinePurchaseTencent::QueryReceipts_Complete, UserIdRef, Delegate);
FOnlineAsyncTaskRailRequestAllAssets* AsyncTask = new FOnlineAsyncTaskRailRequestAllAssets(Subsystem, UserIdRef, CompletionDelegate);
Subsystem->QueueAsyncTask(AsyncTask);
}
void FOnlinePurchaseTencent::QueryReceipts_Complete(const FRequestAllAssetsTaskResult& Result, const TSharedRef<const FUniqueNetId> UserId, const FOnQueryReceiptsComplete Delegate)
{
UE_LOG_ONLINE_PURCHASE(Verbose, TEXT("QueryReceipts Complete with result=[%s]"), *Result.Error.ToLogString());
PurchaseReceipts.Empty(1);
if (Result.Error.WasSuccessful())
{
PurchaseReceipts.Emplace(Result.PurchaseReceipt);
}
Delegate.ExecuteIfBound(Result.Error);
}
void FOnlinePurchaseTencent::GetReceipts(const FUniqueNetId& UserId, TArray<FPurchaseReceipt>& OutReceipts) const
{
OutReceipts = PurchaseReceipts;
}
void FOnlinePurchaseTencent::OnRailAssetsChanged(const FUniqueNetId& UserId)
{
// Broadcast that an unexpected purchase receipt was received
if (!bCheckoutPending)
{
TriggerOnUnexpectedPurchaseReceiptDelegates(UserId);
}
}
void FOnlinePurchaseTencent::FinalizeReceiptValidationInfo(const FUniqueNetId& UserId, FString& InReceiptValidationInfo, const FOnFinalizeReceiptValidationInfoComplete& Delegate)
{
FOnlineError DefaultSuccess(true);
Delegate.ExecuteIfBound(DefaultSuccess, InReceiptValidationInfo);
}
#endif // WITH_TENCENT_RAIL_SDK

View File

@@ -0,0 +1,69 @@
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
#pragma once
#if WITH_TENCENT_RAIL_SDK
#include "Interfaces/OnlinePurchaseInterface.h"
class FOnlineSubsystemTencent;
struct FRequestAllAssetsTaskResult;
struct FPurchaseProductsTaskResult;
/**
* Implementation of IOnlinePurchase using the Rail SDK
*/
class FOnlinePurchaseTencent
: public IOnlinePurchase
, public TSharedFromThis<FOnlinePurchaseTencent, ESPMode::ThreadSafe>
{
public:
/** Destructor */
virtual ~FOnlinePurchaseTencent() = default;
// Begin IOnlinePurchase
virtual bool IsAllowedToPurchase(const FUniqueNetId& UserId) override;
virtual void Checkout(const FUniqueNetId& UserId, const FPurchaseCheckoutRequest& CheckoutRequest, const FOnPurchaseCheckoutComplete& Delegate) override;
virtual void FinalizePurchase(const FUniqueNetId& UserId, const FString& ReceiptId) override;
virtual void RedeemCode(const FUniqueNetId& UserId, const FRedeemCodeRequest& RedeemCodeRequest, const FOnPurchaseRedeemCodeComplete& Delegate) override;
virtual void QueryReceipts(const FUniqueNetId& UserId, bool bRestoreReceipts, const FOnQueryReceiptsComplete& Delegate) override;
virtual void GetReceipts(const FUniqueNetId& UserId, TArray<FPurchaseReceipt>& OutReceipts) const override;
virtual void FinalizeReceiptValidationInfo(const FUniqueNetId& UserId, FString& InReceiptValidationInfo, const FOnFinalizeReceiptValidationInfoComplete& Delegate) override;
// End IOnlinePurchase
PACKAGE_SCOPE:
/**
* Constructor
* @param InSubsystem the owning subsystem
*/
FOnlinePurchaseTencent(FOnlineSubsystemTencent* const InSubsystem);
/**
* Called via an event emitted from the Rail SDK when a user's assets have changed
*/
void OnRailAssetsChanged(const FUniqueNetId& UserId);
private:
/** Called when the QueryReceipts async task completes */
void QueryReceipts_Complete(const FRequestAllAssetsTaskResult& Result, const TSharedRef<const FUniqueNetId> UserId, const FOnQueryReceiptsComplete Delegate);
/** Called when the Checkout async task completes */
void Checkout_Complete(const FPurchaseProductsTaskResult& Result, FOnPurchaseCheckoutComplete Delegate);
/** Default constructor disabled */
FOnlinePurchaseTencent() = delete;
/** Owning subsystem */
FOnlineSubsystemTencent* const Subsystem;
/** Purchase receipts */
TArray<FPurchaseReceipt> PurchaseReceipts;
/** Only allow one checkout at a time */
bool bCheckoutPending = false;
};
typedef TSharedPtr<FOnlinePurchaseTencent, ESPMode::ThreadSafe> FOnlinePurchaseTencentPtr;
#endif // WITH_TENCENT_RAIL_SDK

View File

@@ -0,0 +1,186 @@
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
#include "OnlineSessionTencent.h"
#include "OnlineSubsystemTencentPCH.h"
#include "OnlineSubsystemTencentTypes.h"
#include "OnlineIdentityTencent.h"
#include "Misc/ScopeLock.h"
#if WITH_TENCENTSDK
FOnlineSessionInfoTencent::FOnlineSessionInfoTencent()
: SessionId(nullptr)
{
}
FOnlineSessionInfoTencent::FOnlineSessionInfoTencent(const TSharedPtr<const FUniqueNetIdString>& InSessionId)
: SessionId(InSessionId)
{
}
void FOnlineSessionInfoTencent::Init()
{
FGuid NewGuid = FGuid::NewGuid();
SessionId = MakeShareable(new FUniqueNetIdString(NewGuid.ToString(), TENCENT_SUBSYSTEM));
}
TSharedPtr<const FUniqueNetId> FOnlineSessionTencent::CreateSessionIdFromString(const FString& SessionIdStr)
{
TSharedPtr<const FUniqueNetId> SessionId;
if (!SessionIdStr.IsEmpty())
{
SessionId = MakeShared<FUniqueNetIdString>(SessionIdStr, TENCENT_SUBSYSTEM);
}
return SessionId;
}
FNamedOnlineSession* FOnlineSessionTencent::AddNamedSession(FName SessionName, const FOnlineSessionSettings& SessionSettings)
{
FScopeLock ScopeLock(&SessionLock);
return new (Sessions) FNamedOnlineSessionTencent(SessionName, SessionSettings);
}
FNamedOnlineSession* FOnlineSessionTencent::AddNamedSession(FName SessionName, const FOnlineSession& Session)
{
FScopeLock ScopeLock(&SessionLock);
return new (Sessions)FNamedOnlineSessionTencent(SessionName, Session);
}
FNamedOnlineSession* FOnlineSessionTencent::GetNamedSession(FName SessionName)
{
FScopeLock ScopeLock(&SessionLock);
for (int32 SearchIndex = 0; SearchIndex < Sessions.Num(); SearchIndex++)
{
if (Sessions[SearchIndex].SessionName == SessionName)
{
return &Sessions[SearchIndex];
}
}
return nullptr;
}
void FOnlineSessionTencent::RemoveNamedSession(FName SessionName)
{
FScopeLock ScopeLock(&SessionLock);
for (int32 SearchIndex = 0; SearchIndex < Sessions.Num(); SearchIndex++)
{
if (Sessions[SearchIndex].SessionName == SessionName)
{
Sessions.RemoveAtSwap(SearchIndex);
return;
}
}
}
EOnlineSessionState::Type FOnlineSessionTencent::GetSessionState(FName SessionName) const
{
FScopeLock ScopeLock(&SessionLock);
for (int32 SearchIndex = 0; SearchIndex < Sessions.Num(); SearchIndex++)
{
if (Sessions[SearchIndex].SessionName == SessionName)
{
return Sessions[SearchIndex].SessionState;
}
}
return EOnlineSessionState::NoSession;
}
bool FOnlineSessionTencent::HasPresenceSession()
{
FScopeLock ScopeLock(&SessionLock);
for (int32 SearchIndex = 0; SearchIndex < Sessions.Num(); SearchIndex++)
{
if (Sessions[SearchIndex].SessionSettings.bUsesPresence)
{
return true;
}
}
return false;
}
bool FOnlineSessionTencent::IsPlayerInSession(FName SessionName, const FUniqueNetId& UniqueId)
{
return IsPlayerInSessionImpl(this, SessionName, UniqueId);
}
FOnlineSessionSettings* FOnlineSessionTencent::GetSessionSettings(FName SessionName)
{
FNamedOnlineSession* Session = GetNamedSession(SessionName);
if (Session)
{
return &Session->SessionSettings;
}
return nullptr;
}
int32 FOnlineSessionTencent::GetNumSessions()
{
FScopeLock ScopeLock(&SessionLock);
return Sessions.Num();
}
void FOnlineSessionTencent::DumpSessionState()
{
FScopeLock ScopeLock(&SessionLock);
for (int32 SessionIdx = 0; SessionIdx < Sessions.Num(); SessionIdx++)
{
DumpNamedSession(&Sessions[SessionIdx]);
}
}
FNamedOnlineSession* FOnlineSessionTencent::GetPresenceSession()
{
FScopeLock ScopeLock(&SessionLock);
for (int32 SearchIndex = 0; SearchIndex < Sessions.Num(); SearchIndex++)
{
FNamedOnlineSession& Session = Sessions[SearchIndex];
if (Session.SessionSettings.bUsesPresence)
{
return &Sessions[SearchIndex];
}
}
return nullptr;
}
bool FOnlineSessionTencent::StartMatchmaking(const TArray< TSharedRef<const FUniqueNetId> >& LocalPlayers, FName SessionName, const FOnlineSessionSettings& NewSessionSettings, TSharedRef<FOnlineSessionSearch>& SearchSettings) { return false; }
bool FOnlineSessionTencent::CancelMatchmaking(int32 SearchingPlayerNum, FName SessionName) { return false; }
bool FOnlineSessionTencent::CancelMatchmaking(const FUniqueNetId& SearchingPlayerId, FName SessionName) { return false; }
bool FOnlineSessionTencent::FindSessions(int32 SearchingPlayerNum, const TSharedRef<FOnlineSessionSearch>& SearchSettings) { return false; }
bool FOnlineSessionTencent::FindSessions(const FUniqueNetId& SearchingPlayerId, const TSharedRef<FOnlineSessionSearch>& SearchSettings) { return false; }
bool FOnlineSessionTencent::FindSessionById(const FUniqueNetId& SearchingUserId, const FUniqueNetId& SessionId, const FUniqueNetId& FriendId, const FOnSingleSessionResultCompleteDelegate& CompletionDelegate)
{
FOnlineSessionSearchResult EmptyResult;
const int32 LocalUserNum = TencentSubsystem->GetIdentityInterface()->GetPlatformUserIdFromUniqueNetId(SearchingUserId);
CompletionDelegate.ExecuteIfBound(LocalUserNum, false, EmptyResult);
return false;
}
bool FOnlineSessionTencent::CancelFindSessions() { return false; }
bool FOnlineSessionTencent::PingSearchResults(const FOnlineSessionSearchResult& SearchResult) { return false; }
bool FOnlineSessionTencent::FindFriendSession(int32 LocalUserNum, const FUniqueNetId& Friend) { return false; }
bool FOnlineSessionTencent::FindFriendSession(const FUniqueNetId& LocalUserId, const FUniqueNetId& Friend) { return false; }
bool FOnlineSessionTencent::FindFriendSession(const FUniqueNetId& LocalUserId, const TArray<TSharedRef<const FUniqueNetId>>& FriendList) { return false; }
bool FOnlineSessionTencent::SendSessionInviteToFriend(int32 LocalUserNum, FName SessionName, const FUniqueNetId& Friend) { return false; }
bool FOnlineSessionTencent::SendSessionInviteToFriend(const FUniqueNetId& LocalUserId, FName SessionName, const FUniqueNetId& Friend) { return false; }
bool FOnlineSessionTencent::SendSessionInviteToFriends(int32 LocalUserNum, FName SessionName, const TArray< TSharedRef<const FUniqueNetId> >& Friends) { return false; }
bool FOnlineSessionTencent::SendSessionInviteToFriends(const FUniqueNetId& LocalUserId, FName SessionName, const TArray< TSharedRef<const FUniqueNetId> >& Friends) { return false; }
bool FOnlineSessionTencent::GetResolvedConnectString(FName SessionName, FString& ConnectInfo, FName PortType) { return false; }
bool FOnlineSessionTencent::GetResolvedConnectString(const FOnlineSessionSearchResult& SearchResult, FName PortType, FString& ConnectInfo) { return false; }
int32 FOnlineSessionTencent::GetLocalUserIdx(const FUniqueNetId& UserId) const
{
FOnlineIdentityTencentPtr IdentityInt = StaticCastSharedPtr<FOnlineIdentityTencent>(TencentSubsystem->GetIdentityInterface());
if (IdentityInt)
{
int32 LocalUserNum = INDEX_NONE;
if (IdentityInt->GetLocalUserIdx(UserId, LocalUserNum))
{
return LocalUserNum;
}
}
return INDEX_NONE;
}
#endif // WITH_TENCENTSDK

Some files were not shown because too many files have changed in this diff Show More