diff --git a/Config/DefaultEngine.ini b/Config/DefaultEngine.ini index 76f3a35..2c17f62 100644 --- a/Config/DefaultEngine.ini +++ b/Config/DefaultEngine.ini @@ -4,15 +4,17 @@ +EditProfiles=(Name="Trigger",CustomResponses=((Channel=Projectile, Response=ECR_Ignore))) [/Script/EngineSettings.GameMapsSettings] -EditorStartupMap=/Game/FirstPerson/Maps/FirstPersonMap.FirstPersonMap +EditorStartupMap=/Game/MainMenu/MAP_MainMenu.MAP_MainMenu LocalMapOptions= -TransitionMap= +TransitionMap=None bUseSplitscreen=True TwoPlayerSplitscreenLayout=Horizontal ThreePlayerSplitscreenLayout=FavorTop -GameInstanceClass=/Script/Engine.GameInstance -GameDefaultMap=/Game/FirstPerson/Maps/FirstPersonMap.FirstPersonMap -ServerDefaultMap=/Engine/Maps/Entry +FourPlayerSplitscreenLayout=Grid +bOffsetPlayerGamepadIds=False +GameInstanceClass=/Game/Blueprints/GI_Monolith.GI_Monolith_C +GameDefaultMap=/Game/MainMenu/MAP_MainMenu.MAP_MainMenu +ServerDefaultMap=/Engine/Maps/Entry.Entry GlobalDefaultGameMode=/Game/FirstPerson/Blueprints/BP_FirstPersonGameMode.BP_FirstPersonGameMode_C GlobalDefaultServerGameMode=None @@ -93,3 +95,22 @@ ConnectionType=USBOnly bUseManualIPAddress=False ManualIPAddress= +[/Script/Engine.GameEngine] ++NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="OnlineSubsystemSteam.SteamNetDriver",DriverClassNameFallback="OnlineSubsystemUtils.IpNetDriver") + +[OnlineSubsystem] +DefaultPlatformService=Steam + +[OnlineSubsystemSteam] +bEnabled=true +SteamDevAppId=480 + +; If using Sessions +bInitServerOnClient=true + +[/Script/OnlineSubsystemSteam.SteamNetDriver] +NetConnectionClassName="OnlineSubsystemSteam.SteamNetConnection" + +[/Script/Engine.UserInterfaceSettings] +UIScaleCurve=(EditorCurveData=(Keys=((Time=480.000000,Value=0.444000),(Time=720.000000,Value=0.666000),(Time=1080.000000,Value=1.000000),(Time=8640.000000,Value=2.500000)),DefaultValue=340282346638528859811704183484516925440.000000,PreInfinityExtrap=RCCE_Constant,PostInfinityExtrap=RCCE_Constant),ExternalCurve=None) + diff --git a/Config/DefaultInput.ini b/Config/DefaultInput.ini index 0d0b0e5..77b17e8 100644 --- a/Config/DefaultInput.ini +++ b/Config/DefaultInput.ini @@ -92,7 +92,9 @@ bCaptureMouseOnLaunch=True bEnableLegacyInputScales=True bEnableMotionControls=True bFilterInputByPlatformUser=False +bEnableInputDeviceSubsystem=True bShouldFlushPressedKeysOnViewportFocusLost=True +bEnableDynamicComponentInputBinding=True bAlwaysShowTouchInterface=False bShowConsoleOnFourFingerTap=True bEnableGestureRecognizer=False @@ -101,6 +103,18 @@ DefaultViewportMouseCaptureMode=CapturePermanently_IncludingInitialMouseDown DefaultViewportMouseLockMode=LockOnCapture FOVScale=0.011110 DoubleClickTime=0.200000 ++ActionMappings=(ActionName="Jump",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=SpaceBar) ++ActionMappings=(ActionName="Crouch",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=LeftControl) ++ActionMappings=(ActionName="Sprint",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=LeftShift) ++ActionMappings=(ActionName="Use Left Weapon",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=LeftMouseButton) ++ActionMappings=(ActionName="Use Right Weapon",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=RightMouseButton) ++ActionMappings=(ActionName="Ability1",bShift=False,bCtrl=False,bAlt=True,bCmd=False,Key=One) ++AxisMappings=(AxisName="MoveForward",Scale=1.000000,Key=W) ++AxisMappings=(AxisName="MoveForward",Scale=-1.000000,Key=S) ++AxisMappings=(AxisName="MoveRight",Scale=1.000000,Key=D) ++AxisMappings=(AxisName="MoveRight",Scale=-1.000000,Key=A) ++AxisMappings=(AxisName="Turn",Scale=1.000000,Key=MouseX) ++AxisMappings=(AxisName="LookUp",Scale=-1.000000,Key=MouseY) DefaultPlayerInputClass=/Script/EnhancedInput.EnhancedPlayerInput DefaultInputComponentClass=/Script/EnhancedInput.EnhancedInputComponent DefaultTouchInterface=/Game/FirstPerson/Input/MobileControls.MobileControls diff --git a/Content/Assets/BlockoutAssets/HouseBlockout/LargeBuilding.uasset b/Content/Assets/BlockoutAssets/HouseBlockout/LargeBuilding.uasset new file mode 100644 index 0000000..731832d --- /dev/null +++ b/Content/Assets/BlockoutAssets/HouseBlockout/LargeBuilding.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:485e63deeb6e1d5209a4f6072426afefc06d23f7396f93fd3ad3b0e7bae0b716 +size 195803 diff --git a/Content/Assets/BlockoutAssets/HouseBlockout/MediumBuilding.uasset b/Content/Assets/BlockoutAssets/HouseBlockout/MediumBuilding.uasset new file mode 100644 index 0000000..74ab769 --- /dev/null +++ b/Content/Assets/BlockoutAssets/HouseBlockout/MediumBuilding.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:27efe1f99ac17372457d48181c6d60ef81d4bdd65d88c72b80c371a21f84c9eb +size 135087 diff --git a/Content/Assets/BlockoutAssets/HouseBlockout/SmallBuilding.uasset b/Content/Assets/BlockoutAssets/HouseBlockout/SmallBuilding.uasset new file mode 100644 index 0000000..2203876 --- /dev/null +++ b/Content/Assets/BlockoutAssets/HouseBlockout/SmallBuilding.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b8f7e1aec114813bf58203cb03c1866839edf009d99e01ff869319bf769d10ad +size 89891 diff --git a/Content/Assets/BlockoutAssets/IonaBaseBlockout/BlockOutMaterial.uasset b/Content/Assets/BlockoutAssets/IonaBaseBlockout/BlockOutMaterial.uasset index 0eee826..e19d74d 100644 --- a/Content/Assets/BlockoutAssets/IonaBaseBlockout/BlockOutMaterial.uasset +++ b/Content/Assets/BlockoutAssets/IonaBaseBlockout/BlockOutMaterial.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:59ae293d79e0ff314c09040a4d7404e987eb0bfbd99a493032a5df6b6158cc4f -size 12476 +oid sha256:6ff54ec0b6a53b83973249283da0fbc62b5cb490e5bcc96b6c00d54faa9c2a1e +size 12583 diff --git a/Content/Assets/BlockoutAssets/MonolithBlockout/Monolith_blockout_M_ArmLeft.uasset b/Content/Assets/BlockoutAssets/MonolithBlockout/Monolith_blockout_M_ArmLeft.uasset new file mode 100644 index 0000000..8eb14f2 --- /dev/null +++ b/Content/Assets/BlockoutAssets/MonolithBlockout/Monolith_blockout_M_ArmLeft.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c443f199fad0d552998d33b53a477929e8566ed2ea89f3dbd283ff8825402b65 +size 29679 diff --git a/Content/Assets/BlockoutAssets/MonolithBlockout/Monolith_blockout_M_ArmRight.uasset b/Content/Assets/BlockoutAssets/MonolithBlockout/Monolith_blockout_M_ArmRight.uasset new file mode 100644 index 0000000..68a4ae5 --- /dev/null +++ b/Content/Assets/BlockoutAssets/MonolithBlockout/Monolith_blockout_M_ArmRight.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:730d57660d154180861c3ce264bff68815045a39818b30bad904b94fc7ab1c71 +size 29611 diff --git a/Content/Assets/BlockoutAssets/MonolithBlockout/Monolith_blockout_M_BackBattery.uasset b/Content/Assets/BlockoutAssets/MonolithBlockout/Monolith_blockout_M_BackBattery.uasset new file mode 100644 index 0000000..2863580 --- /dev/null +++ b/Content/Assets/BlockoutAssets/MonolithBlockout/Monolith_blockout_M_BackBattery.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ff31eb8f77a1fac9dae625cf41daaa2b4e2f5f1be83a2c3bd3675f6e09f95e73 +size 18817 diff --git a/Content/Assets/BlockoutAssets/MonolithBlockout/Monolith_blockout_M_Head.uasset b/Content/Assets/BlockoutAssets/MonolithBlockout/Monolith_blockout_M_Head.uasset new file mode 100644 index 0000000..29645f9 --- /dev/null +++ b/Content/Assets/BlockoutAssets/MonolithBlockout/Monolith_blockout_M_Head.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eda172835a9b8def22b7f042660d16541901f610bf42d9687f54c715dc206896 +size 26979 diff --git a/Content/Assets/BlockoutAssets/MonolithBlockout/Monolith_blockout_M_LegLeft.uasset b/Content/Assets/BlockoutAssets/MonolithBlockout/Monolith_blockout_M_LegLeft.uasset new file mode 100644 index 0000000..7e6b95d --- /dev/null +++ b/Content/Assets/BlockoutAssets/MonolithBlockout/Monolith_blockout_M_LegLeft.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0f651bdc26e0824627c78a08489c93b9162fc2dd8dae1883b07d15ab4041f923 +size 29834 diff --git a/Content/Assets/BlockoutAssets/MonolithBlockout/Monolith_blockout_M_LegRight.uasset b/Content/Assets/BlockoutAssets/MonolithBlockout/Monolith_blockout_M_LegRight.uasset new file mode 100644 index 0000000..ab7fffc --- /dev/null +++ b/Content/Assets/BlockoutAssets/MonolithBlockout/Monolith_blockout_M_LegRight.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fdb67f2259218384d5925b99c0f8ea4a436198e31867bd8af47ff7a1e60267a8 +size 29881 diff --git a/Content/Assets/BlockoutAssets/MonolithBlockout/Monolith_blockout_M_ShoulderLeft.uasset b/Content/Assets/BlockoutAssets/MonolithBlockout/Monolith_blockout_M_ShoulderLeft.uasset new file mode 100644 index 0000000..54960ae --- /dev/null +++ b/Content/Assets/BlockoutAssets/MonolithBlockout/Monolith_blockout_M_ShoulderLeft.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5be535d8437a8d32ca20c201cda2206fc9a9dd907edf3cae3ba393bd1c58729c +size 23424 diff --git a/Content/Assets/BlockoutAssets/MonolithBlockout/Monolith_blockout_M_ShoulderRight.uasset b/Content/Assets/BlockoutAssets/MonolithBlockout/Monolith_blockout_M_ShoulderRight.uasset new file mode 100644 index 0000000..f71510f --- /dev/null +++ b/Content/Assets/BlockoutAssets/MonolithBlockout/Monolith_blockout_M_ShoulderRight.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cbd1397c0b5de77cc4455515d3f5b3fbb7906c0175a9e1d6442f7383474f6191 +size 23300 diff --git a/Content/Assets/BlockoutAssets/MonolithBlockout/Monolith_blockout_M_Torso.uasset b/Content/Assets/BlockoutAssets/MonolithBlockout/Monolith_blockout_M_Torso.uasset new file mode 100644 index 0000000..52f1347 --- /dev/null +++ b/Content/Assets/BlockoutAssets/MonolithBlockout/Monolith_blockout_M_Torso.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c82bb20a6f3512cc0c6cabb0578dd9d74144d5c87faae051acb62819b7f6b93a +size 27570 diff --git a/Content/Assets/BlockoutAssets/MonolithBlockout/Monolith_blockout_Rig.uasset b/Content/Assets/BlockoutAssets/MonolithBlockout/Monolith_blockout_Rig.uasset new file mode 100644 index 0000000..ffc689f --- /dev/null +++ b/Content/Assets/BlockoutAssets/MonolithBlockout/Monolith_blockout_Rig.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:07275b4d6e8dd6d77390a34a78d26381b1c6afcc600b70d989638c1d3e2e0b39 +size 590315 diff --git a/Content/Assets/BlockoutAssets/MonolithBlockout/Monolith_blockout_Rig_PhysicsAsset.uasset b/Content/Assets/BlockoutAssets/MonolithBlockout/Monolith_blockout_Rig_PhysicsAsset.uasset new file mode 100644 index 0000000..fca5055 --- /dev/null +++ b/Content/Assets/BlockoutAssets/MonolithBlockout/Monolith_blockout_Rig_PhysicsAsset.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:14875b8d3bab2b9b62baba4905f5132b6c00bb09ed31755f114498b0a4df1a26 +size 9241 diff --git a/Content/Assets/BlockoutAssets/MonolithBlockout/Monolith_blockout_Rig_Skeleton.uasset b/Content/Assets/BlockoutAssets/MonolithBlockout/Monolith_blockout_Rig_Skeleton.uasset new file mode 100644 index 0000000..eac14ee --- /dev/null +++ b/Content/Assets/BlockoutAssets/MonolithBlockout/Monolith_blockout_Rig_Skeleton.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:13c89f25dbe2673220a77a288074c3f015b849f069a5b3d3eddb818a445c9ad7 +size 74842 diff --git a/Content/Assets/BlockoutAssets/TreeBlockouts/DeadTreeBlockout.uasset b/Content/Assets/BlockoutAssets/TreeBlockouts/DeadTreeBlockout.uasset new file mode 100644 index 0000000..528f1e2 --- /dev/null +++ b/Content/Assets/BlockoutAssets/TreeBlockouts/DeadTreeBlockout.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d670401b315ca961a1d1700eece2e0c8b4206af39642f7edd7f2efab5d341ffe +size 18870 diff --git a/Content/Assets/BlockoutAssets/TreeBlockouts/LargeTreeBlockout.uasset b/Content/Assets/BlockoutAssets/TreeBlockouts/LargeTreeBlockout.uasset new file mode 100644 index 0000000..b5748ca --- /dev/null +++ b/Content/Assets/BlockoutAssets/TreeBlockouts/LargeTreeBlockout.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2781a5eca4e6035d1487e58693bad95c794a39024bd095c2294d51e91e30ac0b +size 26834 diff --git a/Content/Assets/BlockoutAssets/TreeBlockouts/SmallTreeBlockout.uasset b/Content/Assets/BlockoutAssets/TreeBlockouts/SmallTreeBlockout.uasset new file mode 100644 index 0000000..40faea5 --- /dev/null +++ b/Content/Assets/BlockoutAssets/TreeBlockouts/SmallTreeBlockout.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d171f6c916653026386282c268e7d8843922f4e1a79fd91294eb180e627be9c7 +size 22230 diff --git a/Content/Blueprints/BPI_MonolithInteriorExit.uasset b/Content/Blueprints/BPI_MonolithInteriorExit.uasset new file mode 100644 index 0000000..be031b4 --- /dev/null +++ b/Content/Blueprints/BPI_MonolithInteriorExit.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a81043802b63d2e32f261bb20317073e6b499fc200284e1835116e3d221e52be +size 26520 diff --git a/Content/Blueprints/GI_Monolith.uasset b/Content/Blueprints/GI_Monolith.uasset new file mode 100644 index 0000000..f514c78 --- /dev/null +++ b/Content/Blueprints/GI_Monolith.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f8d095afc364c3c805708077307794acf660972fbcf82c05c18083de2fa5a5ef +size 101204 diff --git a/Content/FirstPerson/Blueprints/BP_FirstPersonCharacter.uasset b/Content/FirstPerson/Blueprints/BP_FirstPersonCharacter.uasset index 0e541cc..b09c6e4 100644 --- a/Content/FirstPerson/Blueprints/BP_FirstPersonCharacter.uasset +++ b/Content/FirstPerson/Blueprints/BP_FirstPersonCharacter.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d633171bc248bf40c6c0c41ae2021744318a13363cb70ae35ab5b7c22e74d3e0 -size 51739 +oid sha256:47e65c9d7b5b817dc0bfba7dc268522e1d5643251556405985804b70adc9a272 +size 167021 diff --git a/Content/FirstPerson/Blueprints/BP_FirstPersonGameMode.uasset b/Content/FirstPerson/Blueprints/BP_FirstPersonGameMode.uasset index 59f66ce..cc7ed08 100644 --- a/Content/FirstPerson/Blueprints/BP_FirstPersonGameMode.uasset +++ b/Content/FirstPerson/Blueprints/BP_FirstPersonGameMode.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ca412af21b2bfe57534ca779a6f4279809c703746930687785a5af0a14e85525 -size 20527 +oid sha256:66423870f064bc93ae298cb6fda080959850efbf4485a72b6e01e257fc30aafb +size 21242 diff --git a/Content/FirstPerson/HUD/WBP_DashesRemaining.uasset b/Content/FirstPerson/HUD/WBP_DashesRemaining.uasset index 2be9372..95a8cc6 100644 --- a/Content/FirstPerson/HUD/WBP_DashesRemaining.uasset +++ b/Content/FirstPerson/HUD/WBP_DashesRemaining.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:573b8d01b4f498fd9134b0f3349203a101786474ad726e22bde97fb6d0ccbec4 -size 84134 +oid sha256:195060fd33031b016acdf6baf6a636e555bc3094a311019758962f5bde765d9f +size 85122 diff --git a/Content/Levels/PrototypeLevel.umap b/Content/Levels/PrototypeLevel.umap index 6a47326..58f54dc 100644 --- a/Content/Levels/PrototypeLevel.umap +++ b/Content/Levels/PrototypeLevel.umap @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b9e1b170f06777df41b6cb5d50ac0acf71c533a68d0c136e21886a8b01a118e6 -size 1612353 +oid sha256:26baf451b85524b7d1c631674270949328e89f322dfa2ee3e5aa8dec83ab32dc +size 8963314 diff --git a/Content/MainMenu/GM_MainMenu.uasset b/Content/MainMenu/GM_MainMenu.uasset new file mode 100644 index 0000000..f19ea1b --- /dev/null +++ b/Content/MainMenu/GM_MainMenu.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:75ce396492876d0352722960fed7461975c99937db1e4ff4483a3f849301b02f +size 20713 diff --git a/Content/MainMenu/MAP_MainMenu.umap b/Content/MainMenu/MAP_MainMenu.umap new file mode 100644 index 0000000..9d5a9ca --- /dev/null +++ b/Content/MainMenu/MAP_MainMenu.umap @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b2329d9d672450e8e1893115e66000ad701d7de898154236aac2f3e6b2dbfb3f +size 9081 diff --git a/Content/MainMenu/MainMenu.umap b/Content/MainMenu/MainMenu.umap new file mode 100644 index 0000000..86a9e4d --- /dev/null +++ b/Content/MainMenu/MainMenu.umap @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:42c25e45a4bbf8063447a3e9b734697fd4a38d18a725b00448e11c71c4e2d16c +size 1462 diff --git a/Content/MainMenu/PC_MainMenu.uasset b/Content/MainMenu/PC_MainMenu.uasset new file mode 100644 index 0000000..918b599 --- /dev/null +++ b/Content/MainMenu/PC_MainMenu.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cda3f70aeb8e6331e9e7f9960de0eac7d5a57b776d1710824e669cb23ad5ffe5 +size 58815 diff --git a/Content/MainMenu/WBP_CreateLobby.uasset b/Content/MainMenu/WBP_CreateLobby.uasset new file mode 100644 index 0000000..51f5169 --- /dev/null +++ b/Content/MainMenu/WBP_CreateLobby.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6c773b9a06772e83bb442b914a4ec4c50a8a0c4e3878c48503d1a989b28ddc72 +size 95699 diff --git a/Content/MainMenu/WBP_LobbyCard.uasset b/Content/MainMenu/WBP_LobbyCard.uasset new file mode 100644 index 0000000..cac565a --- /dev/null +++ b/Content/MainMenu/WBP_LobbyCard.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:87c668edb6f1bc430960611924e45a1347e237261d6ddb0567f44665860ef2e7 +size 112774 diff --git a/Content/MainMenu/WBP_LobbyList.uasset b/Content/MainMenu/WBP_LobbyList.uasset new file mode 100644 index 0000000..23d3381 --- /dev/null +++ b/Content/MainMenu/WBP_LobbyList.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:20416df494204150644f410970ce27cb443c6f3698178fab449856466318b264 +size 125535 diff --git a/Content/MainMenu/WBP_MainMenu.uasset b/Content/MainMenu/WBP_MainMenu.uasset new file mode 100644 index 0000000..0973b51 --- /dev/null +++ b/Content/MainMenu/WBP_MainMenu.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:807df0415ca2d52d57306d5fa89281f606145c93f23c8f77110ebf3ae5bebfc3 +size 90098 diff --git a/Content/Monolith/BPI_AOverheat.uasset b/Content/Monolith/BPI_AOverheat.uasset new file mode 100644 index 0000000..59400e5 --- /dev/null +++ b/Content/Monolith/BPI_AOverheat.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2ce069207eb27f77e2ff24383695ae65cd719bcabbebd497fc3d4ae7f7a5eafb +size 30065 diff --git a/Content/Monolith/BPI_Bullet.uasset b/Content/Monolith/BPI_Bullet.uasset new file mode 100644 index 0000000..b9bd1dc --- /dev/null +++ b/Content/Monolith/BPI_Bullet.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:515c51e1d6d2d222622b2cfa9772b6cc4e94722c3d5ed51543055fa66c0024b3 +size 30581 diff --git a/Content/Monolith/BPI_MeeleWeapon.uasset b/Content/Monolith/BPI_MeeleWeapon.uasset new file mode 100644 index 0000000..9577994 --- /dev/null +++ b/Content/Monolith/BPI_MeeleWeapon.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:119ede114e954ffdb164837884d34704a41ce958ac022aa65ce754444dad8013 +size 30542 diff --git a/Content/Monolith/BPI_Monolith.uasset b/Content/Monolith/BPI_Monolith.uasset new file mode 100644 index 0000000..2615d11 --- /dev/null +++ b/Content/Monolith/BPI_Monolith.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:df16c01e2bfbccec35a247e2c7d17d3edc4737401fbdf2ebd6e18edee7dfa309 +size 291876 diff --git a/Content/Monolith/Monolith.uasset b/Content/Monolith/Monolith.uasset new file mode 100644 index 0000000..c044839 --- /dev/null +++ b/Content/Monolith/Monolith.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7a2ada25ef17ee3fd3ed841f2eca35f495f0347e759eda8b696c7596d4ae4109 +size 2423 diff --git a/Content/Monolith/UI/WB_AbilityCircle.uasset b/Content/Monolith/UI/WB_AbilityCircle.uasset new file mode 100644 index 0000000..b0014b4 --- /dev/null +++ b/Content/Monolith/UI/WB_AbilityCircle.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ffc64311a867c5be59c974a60226140f5e5c87c6ba8c5b25ac816fd8156fd398 +size 26567 diff --git a/Content/Monolith/UI/WB_BatteryLife.uasset b/Content/Monolith/UI/WB_BatteryLife.uasset new file mode 100644 index 0000000..c80df1d --- /dev/null +++ b/Content/Monolith/UI/WB_BatteryLife.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:16815ee608b75b8c2f4c32235936db64804fc6592e78839e57936dfa3db8a398 +size 46539 diff --git a/Content/__ExternalActors__/FirstPerson/Maps/FirstPersonMap/0/X3/UXU1NDBLBOT2YE07NLBLYL.uasset b/Content/__ExternalActors__/FirstPerson/Maps/FirstPersonMap/0/X3/UXU1NDBLBOT2YE07NLBLYL.uasset new file mode 100644 index 0000000..e795224 --- /dev/null +++ b/Content/__ExternalActors__/FirstPerson/Maps/FirstPersonMap/0/X3/UXU1NDBLBOT2YE07NLBLYL.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b2ed44e89be94fb0b64bb5ec5e3d78ae9a1c2bc7d034a16aac7bb46440ac5dad +size 4733 diff --git a/Content/__ExternalActors__/FirstPerson/Maps/FirstPersonMap/2/BF/XS8GJDVBH2J1EJZHIBZ0IO.uasset b/Content/__ExternalActors__/FirstPerson/Maps/FirstPersonMap/2/BF/XS8GJDVBH2J1EJZHIBZ0IO.uasset new file mode 100644 index 0000000..d087904 --- /dev/null +++ b/Content/__ExternalActors__/FirstPerson/Maps/FirstPersonMap/2/BF/XS8GJDVBH2J1EJZHIBZ0IO.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7fad2f60e965125b94a312aca94374674430424b031408401b2486eeaca31f87 +size 4733 diff --git a/Content/__ExternalActors__/FirstPerson/Maps/FirstPersonMap/7/A5/6857LWX2ZHFBGGBBBXCG1B.uasset b/Content/__ExternalActors__/FirstPerson/Maps/FirstPersonMap/7/A5/6857LWX2ZHFBGGBBBXCG1B.uasset new file mode 100644 index 0000000..f977a83 --- /dev/null +++ b/Content/__ExternalActors__/FirstPerson/Maps/FirstPersonMap/7/A5/6857LWX2ZHFBGGBBBXCG1B.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3c8beb89cba4c86667399e78e20f3a3336bd8d7e5d045b8d38e7c4527990f6fb +size 4733 diff --git a/Monolith.uproject b/Monolith.uproject index c45ff17..5dbac3b 100644 --- a/Monolith.uproject +++ b/Monolith.uproject @@ -20,6 +20,52 @@ "TargetAllowList": [ "Editor" ] + }, + { + "Name": "WorldPartitionHLODUtilities", + "Enabled": true + }, + { + "Name": "OnlineSubsystemSteam", + "Enabled": true + }, + { + "Name": "SteamSockets", + "Enabled": true + }, + { + "Name": "OnlineSubsystemGooglePlay", + "Enabled": false, + "SupportedTargetPlatforms": [ + "Android" + ] + }, + { + "Name": "OnlineSubsystemIOS", + "Enabled": false, + "SupportedTargetPlatforms": [ + "IOS", + "TVOS" + ] + }, + { + "Name": "OnlineSubsystemNull", + "Enabled": true + }, + { + "Name": "OnlineFramework", + "Enabled": true + }, + { + "Name": "OnlineServicesNull", + "Enabled": true + }, + { + "Name": "OnlineServicesOSSAdapter", + "Enabled": true } + ], + "TargetPlatforms": [ + "Windows" ] } \ No newline at end of file diff --git a/Plugins/AdvancedSessions/AdvancedSessions.uplugin b/Plugins/AdvancedSessions/AdvancedSessions.uplugin new file mode 100644 index 0000000..7dc2e3a --- /dev/null +++ b/Plugins/AdvancedSessions/AdvancedSessions.uplugin @@ -0,0 +1,34 @@ +{ + "FileVersion": 3, + "FriendlyName": "Advanced Sessions", + "Version": 5.4, + "VersionName": "5.4", + "Description": "Adds new blueprint functions to handle more advanced session operations.", + "Category": "Advanced Sessions Plugin", + "CreatedBy": "Joshua Statzer", + "CreatedByURL": "N/A", + "Modules": [ + { + "Name": "AdvancedSessions", + "Type": "Runtime", + "LoadingPhase": "PreDefault" + } + ], + "Plugins": [ + { + "Name": "OnlineSubsystem", + "Enabled": true + }, + { + "Name": "OnlineSubsystemUtils", + "Enabled": true + } + ], + "DocsURL": "", + "MarketplaceURL": "", + "SupportURL": "", + "CanContainContent": false, + "IsBetaVersion": false, + "IsExperimentalVersion": false, + "Installed": false +} \ No newline at end of file diff --git a/Plugins/AdvancedSessions/Config/FilterPlugin.ini b/Plugins/AdvancedSessions/Config/FilterPlugin.ini new file mode 100644 index 0000000..ccebca2 --- /dev/null +++ b/Plugins/AdvancedSessions/Config/FilterPlugin.ini @@ -0,0 +1,8 @@ +[FilterPlugin] +; This section lists additional files which will be packaged along with your plugin. Paths should be listed relative to the root plugin directory, and +; may include "...", "*", and "?" wildcards to match directories, files, and individual characters respectively. +; +; Examples: +; /README.txt +; /Extras/... +; /Binaries/ThirdParty/*.dll diff --git a/Plugins/AdvancedSessions/Resources/Icon128.png b/Plugins/AdvancedSessions/Resources/Icon128.png new file mode 100644 index 0000000..0649dbf Binary files /dev/null and b/Plugins/AdvancedSessions/Resources/Icon128.png differ diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/AdvancedSessions.Build.cs b/Plugins/AdvancedSessions/Source/AdvancedSessions/AdvancedSessions.Build.cs new file mode 100644 index 0000000..a305151 --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/AdvancedSessions.Build.cs @@ -0,0 +1,17 @@ +using UnrealBuildTool; +using System.IO; + +public class AdvancedSessions : ModuleRules +{ + public AdvancedSessions(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; + //bEnforceIWYU = true; + + PublicDefinitions.Add("WITH_ADVANCED_SESSIONS=1"); + + // PrivateIncludePaths.AddRange(new string[] { "AdvancedSessions/Private"/*, "OnlineSubsystemSteam/Private"*/ }); + // PublicIncludePaths.AddRange(new string[] { "AdvancedSessions/Public" }); + PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "OnlineSubsystem", "CoreUObject", "OnlineSubsystemUtils", "Networking", "Sockets"/*"Voice", "OnlineSubsystemSteam"*/ }); + } +} \ No newline at end of file diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/AdvancedExternalUILibrary.h b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/AdvancedExternalUILibrary.h new file mode 100644 index 0000000..6153ed3 --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/AdvancedExternalUILibrary.h @@ -0,0 +1,63 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once +#include "CoreMinimal.h" +#include "BlueprintDataDefinitions.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "Online.h" +#include "Engine/LocalPlayer.h" +#include "OnlineSubsystem.h" +#include "BlueprintDataDefinitions.h" +//#include "OnlineFriendsInterface.h" +//#include "OnlineUserInterface.h" +//#include "OnlineMessageInterface.h" +//#include "OnlinePresenceInterface.h" +//#include "Engine/GameInstance.h" +#include "Interfaces/OnlineSessionInterface.h" + +//#include "UObjectIterator.h" + +#include "AdvancedExternalUILibrary.generated.h" + + +//General Advanced Sessions Log +DECLARE_LOG_CATEGORY_EXTERN(AdvancedExternalUILog, Log, All); + +UCLASS() +class UAdvancedExternalUILibrary : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() +public: + + //********* External UI Functions *************// + + // Show the UI that handles the Friends list + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedExternalUI", meta = (ExpandEnumAsExecs = "Result", WorldContext = "WorldContextObject")) + static void ShowFriendsUI(UObject* WorldContextObject, APlayerController *PlayerController, EBlueprintResultSwitch &Result); + + // Show the UI that handles inviting people to your game + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedExternalUI", meta = (ExpandEnumAsExecs = "Result", WorldContext = "WorldContextObject")) + static void ShowInviteUI(UObject* WorldContextObject, APlayerController *PlayerController, EBlueprintResultSwitch &Result); + + // Show the UI that shows the leaderboard (doesn't work with steam) + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedExternalUI", meta = (ExpandEnumAsExecs = "Result", WorldContext = "WorldContextObject")) + static void ShowLeaderBoardUI(UObject* WorldContextObject, FString LeaderboardName, EBlueprintResultSwitch &Result); + + // Show the UI that shows a web URL + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedExternalUI", meta = (ExpandEnumAsExecs = "Result", AutoCreateRefTerm = "AllowedDomains", WorldContext = "WorldContextObject")) + static void ShowWebURLUI(UObject* WorldContextObject, FString URLToShow, EBlueprintResultSwitch &Result, TArray& AllowedDomains, bool bEmbedded = false , bool bShowBackground = false, bool bShowCloseButton = false, int32 OffsetX = 0, int32 OffsetY = 0, int32 SizeX = 0, int32 SizeY = 0); + + // Show the UI that shows a web URL + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedExternalUI", meta = (WorldContext = "WorldContextObject")) + static void CloseWebURLUI(UObject* WorldContextObject); + + + // Show the UI that shows the profile of a uniquenetid + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedExternalUI", meta = (ExpandEnumAsExecs = "Result", WorldContext = "WorldContextObject")) + static void ShowProfileUI(UObject* WorldContextObject, const FBPUniqueNetId PlayerViewingProfile, const FBPUniqueNetId PlayerToViewProfileOf, EBlueprintResultSwitch &Result); + + // Show the UI that shows the account upgrade UI (doesn't work with steam) + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedExternalUI", meta = (ExpandEnumAsExecs = "Result", WorldContext = "WorldContextObject")) + static void ShowAccountUpgradeUI(UObject* WorldContextObject, const FBPUniqueNetId PlayerRequestingAccountUpgradeUI, EBlueprintResultSwitch &Result); + +}; diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/AdvancedFriendsGameInstance.h b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/AdvancedFriendsGameInstance.h new file mode 100644 index 0000000..be1def9 --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/AdvancedFriendsGameInstance.h @@ -0,0 +1,145 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once +#include "CoreMinimal.h" +#include "Engine/Engine.h" +#include "BlueprintDataDefinitions.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "Online.h" +#include "OnlineSubsystem.h" +#include "Interfaces/OnlineFriendsInterface.h" +#include "Interfaces/OnlineUserInterface.h" +#include "Interfaces/OnlineMessageInterface.h" +#include "Interfaces/OnlinePresenceInterface.h" +#include "Engine/GameInstance.h" +#include "Engine/LocalPlayer.h" +#include "Interfaces/OnlineSessionInterface.h" +#include "OnlineSessionSettings.h" +#include "UObject/UObjectIterator.h" +#include "AdvancedFriendsInterface.h" + +#include "AdvancedFriendsGameInstance.generated.h" + + +//General Advanced Sessions Log +DECLARE_LOG_CATEGORY_EXTERN(AdvancedFriendsInterfaceLog, Log, All); + +UCLASS() +class ADVANCEDSESSIONS_API UAdvancedFriendsGameInstance : public UGameInstance +{ + GENERATED_BODY() +public: + + UAdvancedFriendsGameInstance(const FObjectInitializer& ObjectInitializer); + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = AdvancedFriendsInterface) + bool bCallFriendInterfaceEventsOnPlayerControllers; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = AdvancedFriendsInterface) + bool bCallIdentityInterfaceEventsOnPlayerControllers; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = AdvancedFriendsInterface) + bool bCallVoiceInterfaceEventsOnPlayerControllers; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = AdvancedVoiceInterface) + bool bEnableTalkingStatusDelegate; + + //virtual void PostLoad() override; + virtual void Shutdown() override; + virtual void Init() override; + + //*** Session invite received by local ***// + FOnSessionInviteReceivedDelegate SessionInviteReceivedDelegate; + FDelegateHandle SessionInviteReceivedDelegateHandle; + + //const FUniqueNetId& /*UserId*/, const FUniqueNetId& /*FromId*/, const FString& /*AppId*/, const FOnlineSessionSearchResult& /*InviteResult*/ + void OnSessionInviteReceivedMaster(const FUniqueNetId & PersonInvited, const FUniqueNetId & PersonInviting, const FString & AppId, const FOnlineSessionSearchResult& SessionToJoin); + + // After a session invite has been accepted by the local player this event is triggered, call JoinSession on the session result to join it + UFUNCTION(BlueprintImplementableEvent, Category = "AdvancedFriends") + void OnSessionInviteReceived(int32 LocalPlayerNum, FBPUniqueNetId PersonInviting, const FString& AppId, const FBlueprintSessionResult& SessionToJoin); + + //*** Session invite accepted by local ***// + FOnSessionUserInviteAcceptedDelegate SessionInviteAcceptedDelegate; + FDelegateHandle SessionInviteAcceptedDelegateHandle; + + void OnSessionInviteAcceptedMaster(const bool bWasSuccessful, int32 LocalPlayer, TSharedPtr PersonInviting, const FOnlineSessionSearchResult& SessionToJoin); + + // After a session invite has been accepted by the local player this event is triggered, call JoinSession on the session result to join it + // This function is currently not hooked up in any of Epics default subsystems, it is here for custom subsystems + UFUNCTION(BlueprintImplementableEvent, Category = "AdvancedFriends") + void OnSessionInviteAccepted(int32 LocalPlayerNum, FBPUniqueNetId PersonInvited, const FBlueprintSessionResult& SessionToJoin); + + + // After a voice status has changed this event is triggered if the bEnableTalkingStatusDelegate property is true + UFUNCTION(BlueprintImplementableEvent, Category = "AdvancedVoice") + void OnPlayerTalkingStateChanged(FBPUniqueNetId PlayerId, bool bIsTalking); + + void OnPlayerTalkingStateChangedMaster(TSharedRef PlayerId, bool bIsTalking); + + FOnPlayerTalkingStateChangedDelegate PlayerTalkingStateChangedDelegate; + FDelegateHandle PlayerTalkingStateChangedDelegateHandle; + + + // Called when the designated LocalUser has changed login state + UFUNCTION(BlueprintImplementableEvent , Category = "AdvancedIdentity", meta = (DisplayName = "OnPlayerLoginChanged")) + void OnPlayerLoginChanged(int32 PlayerNum); + + void OnPlayerLoginChangedMaster(int32 PlayerNum); + FOnLoginChangedDelegate PlayerLoginChangedDelegate; + FDelegateHandle PlayerLoginChangedDelegateHandle; + + // Called when the designated LocalUser has changed login status + UFUNCTION(BlueprintImplementableEvent, Category = "AdvancedIdentity", meta = (DisplayName = "OnPlayerLoginStatusChanged")) + void OnPlayerLoginStatusChanged(int32 PlayerNum, EBPLoginStatus PreviousStatus, EBPLoginStatus NewStatus, FBPUniqueNetId NewPlayerUniqueNetID); + + void OnPlayerLoginStatusChangedMaster(int32 PlayerNum, ELoginStatus::Type PreviousStatus, ELoginStatus::Type NewStatus, const FUniqueNetId & NewPlayerUniqueNetID); + FOnLoginStatusChangedDelegate PlayerLoginStatusChangedDelegate; + FDelegateHandle PlayerLoginStatusChangedDelegateHandle; + + + //*** Session Invite Received From Friend ***// + // REMOVED BECAUSE IT NEVER GETS CALLED + /*FOnSessionInviteReceivedDelegate SessionInviteReceivedDelegate; + FDelegateHandle SessionInviteReceivedDelegateHandle; + + void OnSessionInviteReceivedMaster(const FUniqueNetId &InvitedPlayer, const FUniqueNetId &FriendInviting, const FOnlineSessionSearchResult& Session); + + // After a session invite has been sent from a friend this event is triggered, call JoinSession on the session result to join it + UFUNCTION(BlueprintImplementableEvent, Category = "AdvancedFriends") + void OnSessionInviteReceived(const FBPUniqueNetId &InvitedPlayer, const FBPUniqueNetId &FriendInviting, const FBlueprintSessionResult &Session); + */ + + //*** Friend Invite Accepted ***// + /*FOnInviteAcceptedDelegate FriendInviteAcceptedDelegate; + FDelegateHandle FriendInviteAcceptedDelegateHandle; + + void OnFriendInviteAcceptedDelegateMaster(const FUniqueNetId& LocalPlayer, const FUniqueNetId &PlayerInvited); + + // After a session invite has been accepted by a friend this event is triggered + UFUNCTION(BlueprintImplementableEvent, Category = "AdvancedFriends") + void OnFriendInviteAccepted(const FBPUniqueNetId &InvitedPlayer, const FBPUniqueNetId &PlayerInvited); + */ + + //*** Friend Invite Rejected ***// + /*FOnInviteRejectedDelegate SessionInviteRejectedByFriendDelegate; + FDelegateHandle InviteRejectedByFriendDelegateHandle; + + void OnFriendInviteRejectedDelegateMaster(const FUniqueNetId& LocalPlayer, const FUniqueNetId &PlayerDeclined); + + // After a friend invite has been rejected this event is triggered + UFUNCTION(BlueprintImplementableEvent, Category = "AdvancedFriends") + void OnFriendInviteRejected(const FBPUniqueNetId &InvitedPlayer, const FBPUniqueNetId &PlayerDeclined); + */ + + //*** Removed By Friend ***// + /*FOnFriendRemovedDelegate RemovedByFriendDelegate; + FDelegateHandle RemovedByFriendDelegateHandle; + + void OnRemovedByFriendDelegateMaster(const FUniqueNetId& LocalPlayer, const FUniqueNetId &FriendRemoved); + + // After a friend removed the player this event is triggered + UFUNCTION(BlueprintImplementableEvent, Category = "AdvancedFriends") + void OnRemovedByFriend(const FBPUniqueNetId &InvitedPlayer, const FBPUniqueNetId &FriendRemoved);*/ +}; + diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/AdvancedFriendsInterface.h b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/AdvancedFriendsInterface.h new file mode 100644 index 0000000..44cfc0b --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/AdvancedFriendsInterface.h @@ -0,0 +1,56 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once +#include "CoreMinimal.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "Online.h" +#include "OnlineSubsystem.h" +#include "Interfaces/OnlineFriendsInterface.h" +#include "Interfaces/OnlineUserInterface.h" +#include "Interfaces/OnlineMessageInterface.h" +#include "Interfaces/OnlinePresenceInterface.h" +#include "Engine/GameInstance.h" +#include "Interfaces/OnlineSessionInterface.h" +#include "OnlineSessionSettings.h" +#include "UObject/UObjectIterator.h" +#include "BlueprintDataDefinitions.h" +#include "AdvancedFriendsInterface.generated.h" + + +UINTERFACE(MinimalAPI) +class UAdvancedFriendsInterface : public UInterface +{ + GENERATED_UINTERFACE_BODY() +}; + +class IAdvancedFriendsInterface +{ + GENERATED_IINTERFACE_BODY() +public: + + // Called when the designated LocalUser has accepted a session invite, use JoinSession on result to connect + UFUNCTION(BlueprintImplementableEvent, meta = (DisplayName = "OnSessionInviteReceived")) + void OnSessionInviteReceived(FBPUniqueNetId PersonInviting, const FBlueprintSessionResult& SearchResult); + + // Called when the designated LocalUser has accepted a session invite, use JoinSession on result to connect + UFUNCTION(BlueprintImplementableEvent, meta = (DisplayName = "OnSessionInviteAccepted")) + void OnSessionInviteAccepted(FBPUniqueNetId PersonInvited, const FBlueprintSessionResult& SearchResult); + + // Called when the designated LocalUser has accepted a session invite, use JoinSession on result to connect + UFUNCTION(BlueprintImplementableEvent, meta = (DisplayName = "OnPlayerVoiceStateChanged")) + void OnPlayerVoiceStateChanged(FBPUniqueNetId PlayerId, bool bIsTalking); + + // Called when the designated LocalUser has changed login state + UFUNCTION(BlueprintImplementableEvent, meta = (DisplayName = "OnPlayerLoginChanged")) + void OnPlayerLoginChanged(int32 PlayerNum); + + // Called when the designated LocalUser has changed login state + UFUNCTION(BlueprintImplementableEvent, meta = (DisplayName = "OnPlayerLoginStatusChanged")) + void OnPlayerLoginStatusChanged(EBPLoginStatus PreviousStatus, EBPLoginStatus NewStatus, FBPUniqueNetId PlayerUniqueNetID); + + // REMOVED BECAUSE IT WAS NEVER BEING CALLED + // Called when the designated LocalUser has received a session invite, use JoinSession on result to connect + //UFUNCTION(BlueprintImplementableEvent, meta = (FriendlyName = "OnSessionInviteReceived")) + //void OnSessionInviteReceived(const FBPUniqueNetId &FriendInviting, const FBlueprintSessionResult &Session); + +}; diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/AdvancedFriendsLibrary.h b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/AdvancedFriendsLibrary.h new file mode 100644 index 0000000..fedf2c1 --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/AdvancedFriendsLibrary.h @@ -0,0 +1,56 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once +#include "CoreMinimal.h" +#include "BlueprintDataDefinitions.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "Online.h" +#include "Engine/LocalPlayer.h" +#include "OnlineSubsystem.h" +#include "Interfaces/OnlineFriendsInterface.h" +#include "Interfaces/OnlineUserInterface.h" +#include "Interfaces/OnlineMessageInterface.h" +#include "Interfaces/OnlinePresenceInterface.h" +#include "Engine/GameInstance.h" +#include "Interfaces/OnlineSessionInterface.h" + +#include "UObject/UObjectIterator.h" + +#include "AdvancedFriendsLibrary.generated.h" + + +//General Advanced Sessions Log +DECLARE_LOG_CATEGORY_EXTERN(AdvancedFriendsLog, Log, All); + +UCLASS() +class UAdvancedFriendsLibrary : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() +public: + + //********* Friend List Functions *************// + + // Sends an Invite to the current online session to a list of friends + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedFriends|FriendsList", meta = (ExpandEnumAsExecs = "Result")) + static void SendSessionInviteToFriends(APlayerController *PlayerController, const TArray &Friends, EBlueprintResultSwitch &Result); + + // Sends an Invite to the current online session to a friend + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedFriends|FriendsList", meta = (ExpandEnumAsExecs = "Result")) + static void SendSessionInviteToFriend(APlayerController *PlayerController, const FBPUniqueNetId &FriendUniqueNetId, EBlueprintResultSwitch &Result); + + // Get a friend from the previously read/saved friends list (Must Call GetFriends first for this to return anything) + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedFriends|FriendsList") + static void GetFriend(APlayerController *PlayerController, const FBPUniqueNetId FriendUniqueNetId, FBPFriendInfo &Friend); + + // Get the previously read/saved friends list (Must Call GetFriends first for this to return anything) + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedFriends|FriendsList") + static void GetStoredFriendsList(APlayerController *PlayerController, TArray &FriendsList); + + // Get the previously read/saved recent players list (Must Call GetRecentPlayers first for this to return anything) + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedFriends|RecentPlayersList") + static void GetStoredRecentPlayersList(FBPUniqueNetId UniqueNetId, TArray &PlayersList); + + // Check if a UniqueNetId is a friend + UFUNCTION(BlueprintPure, Category = "Online|AdvancedFriends|FriendsList") + static void IsAFriend(APlayerController *PlayerController, const FBPUniqueNetId UniqueNetId, bool &IsFriend); +}; diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/AdvancedGameSession.h b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/AdvancedGameSession.h new file mode 100644 index 0000000..179d857 --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/AdvancedGameSession.h @@ -0,0 +1,71 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once +#include "CoreMinimal.h" +#include "Engine/Engine.h" +#include "Online.h" +#include "OnlineSubsystem.h" +#include "Engine/GameInstance.h" +#include "GameFramework/GameModeBase.h" +#include "GameFramework/GameSession.h" +#include "GameFramework/PlayerState.h" + +//#include "UObjectIterator.h" + +#include "AdvancedGameSession.generated.h" + + + + +/** + A quick wrapper around the game session to add a partial ban implementation. Just bans for the duration of the current session +*/ +UCLASS(config = Game, notplaceable) +class AAdvancedGameSession : public AGameSession +{ + GENERATED_UCLASS_BODY() + +public: + + UPROPERTY(Transient) + TMap BanList; + + virtual bool BanPlayer(class APlayerController* BannedPlayer, const FText& BanReason) + { + + if (APlayerState* PlayerState = (BannedPlayer != NULL) ? BannedPlayer->PlayerState : NULL) + { + FUniqueNetIdRepl UniqueNetID = PlayerState->GetUniqueId(); + bool bWasKicked = KickPlayer(BannedPlayer, BanReason); + + if (bWasKicked) + { + BanList.Add(UniqueNetID, BanReason); + } + + return bWasKicked; + } + + return false; + } + + // This should really be handled in the game mode asking game session, but I didn't want to force a custom game session AND game mode + // If done in the game mode, we could check prior to actually spooling up any player information in ApproveLogin + virtual void PostLogin(APlayerController* NewPlayer) override + { + if (APlayerState* PlayerState = (NewPlayer != NULL) ? NewPlayer->PlayerState : NULL) + { + FUniqueNetIdRepl UniqueNetID = PlayerState->GetUniqueId(); + + if (BanList.Contains(UniqueNetID)) + { + KickPlayer(NewPlayer, BanList[UniqueNetID]); + } + } + } +}; + +AAdvancedGameSession::AAdvancedGameSession(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ +} \ No newline at end of file diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/AdvancedIdentityLibrary.h b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/AdvancedIdentityLibrary.h new file mode 100644 index 0000000..5f0dc15 --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/AdvancedIdentityLibrary.h @@ -0,0 +1,81 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once +#include "CoreMinimal.h" +#include "BlueprintDataDefinitions.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "Online.h" +#include "OnlineSubsystem.h" +#include "Interfaces/OnlineIdentityInterface.h" +#include "Interfaces/OnlineUserInterface.h" +#include "Interfaces/OnlinePresenceInterface.h" +#include "Engine/GameInstance.h" +#include "Engine/LocalPlayer.h" + +#include "UObject/UObjectIterator.h" + +#include "AdvancedIdentityLibrary.generated.h" + + +//General Advanced Sessions Log +DECLARE_LOG_CATEGORY_EXTERN(AdvancedIdentityLog, Log, All); + +UCLASS() +class UAdvancedIdentityLibrary : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() +public: + //********* Identity Functions *************// + + // Get the login status of a local player + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedIdentity", meta = (ExpandEnumAsExecs = "Result", WorldContext = "WorldContextObject")) + static void GetLoginStatus(UObject* WorldContextObject, const FBPUniqueNetId & UniqueNetID, EBPLoginStatus & LoginStatus, EBlueprintResultSwitch &Result); + + // Get the auth token for a local player + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedIdentity", meta = (ExpandEnumAsExecs = "Result", WorldContext = "WorldContextObject")) + static void GetPlayerAuthToken(UObject* WorldContextObject, APlayerController * PlayerController, FString & AuthToken, EBlueprintResultSwitch &Result); + + // Get a players nickname + UFUNCTION(BlueprintPure, Category = "Online|AdvancedIdentity", meta = (WorldContext = "WorldContextObject")) + static void GetPlayerNickname(UObject* WorldContextObject, const FBPUniqueNetId & UniqueNetID, FString & PlayerNickname); + + //********* User Account Functions *************// + + // Get a users account + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedIdentity|UserAccount", meta = (ExpandEnumAsExecs = "Result", WorldContext = "WorldContextObject")) + static void GetUserAccount(UObject* WorldContextObject, const FBPUniqueNetId & UniqueNetId, FBPUserOnlineAccount & AccountInfo, EBlueprintResultSwitch &Result); + + // Get all known users accounts + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedIdentity|UserAccount", meta = (ExpandEnumAsExecs = "Result", WorldContext = "WorldContextObject")) + static void GetAllUserAccounts(UObject* WorldContextObject, TArray & AccountInfos, EBlueprintResultSwitch &Result); + + // Get a user account access token + UFUNCTION(BlueprintPure, Category = "Online|AdvancedIdentity|UserAccount") + static void GetUserAccountAccessToken(const FBPUserOnlineAccount & AccountInfo, FString & AccessToken); + + // Get a user account Auth attribute (depends on subsystem) + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedIdentity|UserAccount", meta = (ExpandEnumAsExecs = "Result")) + static void GetUserAccountAuthAttribute(const FBPUserOnlineAccount & AccountInfo, const FString & AttributeName, FString & AuthAttribute, EBlueprintResultSwitch &Result); + + // Set a user account attribute (depends on subsystem) + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedIdentity|UserAccount", meta = (ExpandEnumAsExecs = "Result")) + static void SetUserAccountAttribute(const FBPUserOnlineAccount & AccountInfo, const FString & AttributeName, const FString & NewAttributeValue, EBlueprintResultSwitch &Result); + + // Get user ID + UFUNCTION(BlueprintPure, Category = "Online|AdvancedIdentity|UserAccount") + static void GetUserID(const FBPUserOnlineAccount & AccountInfo, FBPUniqueNetId & UniqueNetID); + + // Get user accounts real name if possible + UFUNCTION(BlueprintPure, Category = "Online|AdvancedIdentity|UserAccount") + static void GetUserAccountRealName(const FBPUserOnlineAccount & AccountInfo, FString & UserName); + + // Get user account display name if possible + UFUNCTION(BlueprintPure, Category = "Online|AdvancedIdentity|UserAccount") + static void GetUserAccountDisplayName(const FBPUserOnlineAccount & AccountInfo, FString & DisplayName); + + // Get user account attribute (depends on subsystem) + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedIdentity|UserAccount", meta = (ExpandEnumAsExecs = "Result")) + static void GetUserAccountAttribute(const FBPUserOnlineAccount & AccountInfo, const FString & AttributeName, FString & AttributeValue, EBlueprintResultSwitch &Result); + + +}; diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/AdvancedSessions.h b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/AdvancedSessions.h new file mode 100644 index 0000000..6218cd0 --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/AdvancedSessions.h @@ -0,0 +1,11 @@ +#pragma once + +#include "Modules/ModuleManager.h" + +class AdvancedSessions : public IModuleInterface +{ +public: + /** IModuleInterface implementation */ + void StartupModule(); + void ShutdownModule(); +}; \ No newline at end of file diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/AdvancedSessionsLibrary.h b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/AdvancedSessionsLibrary.h new file mode 100644 index 0000000..457bcdd --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/AdvancedSessionsLibrary.h @@ -0,0 +1,213 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once +#include "CoreMinimal.h" +#include "Engine/Engine.h" +#include "BlueprintDataDefinitions.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "Online.h" +#include "OnlineSubsystem.h" +#include "Interfaces/OnlineFriendsInterface.h" +#include "Interfaces/OnlineUserInterface.h" +#include "Interfaces/OnlineMessageInterface.h" +#include "Interfaces/OnlinePresenceInterface.h" +#include "Engine/GameInstance.h" +#include "Interfaces/OnlineSessionInterface.h" + +#include "GameFramework/GameModeBase.h" +#include "GameFramework/GameSession.h" + +//#include "UObjectIterator.h" + +#include "AdvancedSessionsLibrary.generated.h" + + +//General Advanced Sessions Log +DECLARE_LOG_CATEGORY_EXTERN(AdvancedSessionsLog, Log, All); + + +UCLASS() +class UAdvancedSessionsLibrary : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() +public: + //********* Session Admin Functions *************// + + // Kick a player from the currently active game session, only available on the server + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedSessions", meta = (WorldContext = "WorldContextObject")) + static bool KickPlayer(UObject* WorldContextObject, APlayerController* PlayerToKick, FText KickReason); + + // Ban a player from the currently active game session, only available on the server + // Note that the default gamesession class does not implement an actual ban list and just kicks when this is called + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedSessions", meta = (WorldContext = "WorldContextObject")) + static bool BanPlayer(UObject* WorldContextObject, APlayerController* PlayerToBan, FText BanReason); + + //********* Session Search Functions *************// + + // Adds or modifies session settings in an existing array depending on if they exist already or not + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedSessions|SessionInfo") + static void AddOrModifyExtraSettings(UPARAM(ref) TArray & SettingsArray, UPARAM(ref) TArray & NewOrChangedSettings, TArray & ModifiedSettingsArray); + + // Get an array of the session settings from a session search result + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedSessions|SessionInfo") + static void GetExtraSettings(FBlueprintSessionResult SessionResult, TArray & ExtraSettings); + + // Get the current session state + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedSessions|SessionInfo", meta = (WorldContext = "WorldContextObject")) + static void GetSessionState(UObject* WorldContextObject, EBPOnlineSessionState &SessionState); + + // Get the current session settings + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedSessions|SessionInfo", meta = (ExpandEnumAsExecs = "Result", WorldContext = "WorldContextObject")) + static void GetSessionSettings(UObject* WorldContextObject, int32 &NumConnections, int32 &NumPrivateConnections, bool &bIsLAN, bool &bIsDedicated, bool &bAllowInvites, bool &bAllowJoinInProgress, bool &bIsAnticheatEnabled, int32 &BuildUniqueID, TArray &ExtraSettings, EBlueprintResultSwitch &Result); + + // Check if someone is in the current session + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedSessions|SessionInfo", meta = (WorldContext = "WorldContextObject")) + static void IsPlayerInSession(UObject* WorldContextObject, const FBPUniqueNetId &PlayerToCheck, bool &bIsInSession); + + // Make a literal session search parameter + UFUNCTION(BlueprintPure, Category = "Online|AdvancedSessions|SessionInfo|Literals") + static FSessionsSearchSetting MakeLiteralSessionSearchProperty(FSessionPropertyKeyPair SessionSearchProperty, EOnlineComparisonOpRedux ComparisonOp); + + + //********* Session Information Functions ***********// + + // Check if a session result is valid or not + UFUNCTION(BlueprintPure, Category = "Online|AdvancedSessions|SessionInfo") + static bool IsValidSession(const FBlueprintSessionResult & SessionResult); + + // Get a string copy of a session ID + UFUNCTION(BlueprintPure, Category = "Online|AdvancedSessions|SessionInfo") + static void GetSessionID_AsString(const FBlueprintSessionResult & SessionResult, FString& SessionID); + + // Get a string copy of the current session ID + UFUNCTION(BlueprintPure, Category = "Online|AdvancedSessions|SessionInfo", meta = (WorldContext = "WorldContextObject")) + static void GetCurrentSessionID_AsString(UObject* WorldContextObject, FString& SessionID); + + // Get the Unique Current Build ID + UFUNCTION(BlueprintPure, Category = "Online|AdvancedSessions|SessionInfo") + static void GetCurrentUniqueBuildID(int32 &UniqueBuildId); + + // Get the Unique Build ID from a session search result + UFUNCTION(BlueprintPure, Category = "Online|AdvancedSessions|SessionInfo") + static void GetUniqueBuildID(FBlueprintSessionResult SessionResult, int32 &UniqueBuildId); + + + // Thanks CriErr for submission + + + // Get session property Key Name value + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedSessions|SessionInfo") + static FName GetSessionPropertyKey(const FSessionPropertyKeyPair& SessionProperty); + + // Find session property by Name + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedSessions|SessionInfo", meta = (ExpandEnumAsExecs = "Result")) + static void FindSessionPropertyByName(const TArray& ExtraSettings, FName SettingsName, EBlueprintResultSwitch &Result, FSessionPropertyKeyPair& OutProperty); + + // Find session property index by Name + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedSessions|SessionInfo", meta = (ExpandEnumAsExecs = "Result")) + static void FindSessionPropertyIndexByName(const TArray& ExtraSettings, FName SettingName, EBlueprintResultSwitch &Result, int32& OutIndex); + + /// Removed the Index_None part of the last function, that isn't accessible in blueprint, better to return success/failure + // End Thanks CriErr :p + + // Get session custom information key/value as Byte (For Enums) + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedSessions|SessionInfo", meta = (ExpandEnumAsExecs = "SearchResult")) + static void GetSessionPropertyByte(const TArray & ExtraSettings, FName SettingName, ESessionSettingSearchResult &SearchResult, uint8 &SettingValue); + + // Get session custom information key/value as Bool + // Steam only currently supports Int,Float,String,BYTE values for search filtering!!! + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedSessions|SessionInfo", meta = (ExpandEnumAsExecs = "SearchResult")) + static void GetSessionPropertyBool(const TArray & ExtraSettings, FName SettingName, ESessionSettingSearchResult &SearchResult, bool &SettingValue); + + // Get session custom information key/value as String + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedSessions|SessionInfo", meta = (ExpandEnumAsExecs = "SearchResult")) + static void GetSessionPropertyString(const TArray & ExtraSettings, FName SettingName, ESessionSettingSearchResult &SearchResult, FString &SettingValue); + + // Get session custom information key/value as Int + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedSessions|SessionInfo", meta = (ExpandEnumAsExecs = "SearchResult")) + static void GetSessionPropertyInt(const TArray & ExtraSettings, FName SettingName, ESessionSettingSearchResult &SearchResult, int32 &SettingValue); + + // Get session custom information key/value as Float + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedSessions|SessionInfo", meta = (ExpandEnumAsExecs = "SearchResult")) + static void GetSessionPropertyFloat(const TArray & ExtraSettings, FName SettingName, ESessionSettingSearchResult &SearchResult, float &SettingValue); + + + // Make a literal session custom information key/value pair from Byte (For Enums) + UFUNCTION(BlueprintPure, Category = "Online|AdvancedSessions|SessionInfo|Literals") + static FSessionPropertyKeyPair MakeLiteralSessionPropertyByte(FName Key, uint8 Value); + + // Make a literal session custom information key/value pair from Bool + // Steam only currently supports Int,Float,String,BYTE values for search filtering! + UFUNCTION(BlueprintPure, Category = "Online|AdvancedSessions|SessionInfo|Literals") + static FSessionPropertyKeyPair MakeLiteralSessionPropertyBool(FName Key, bool Value); + + // Make a literal session custom information key/value pair from String + UFUNCTION(BlueprintPure, Category = "Online|AdvancedSessions|SessionInfo|Literals") + static FSessionPropertyKeyPair MakeLiteralSessionPropertyString(FName Key, FString Value); + + // Make a literal session custom information key/value pair from Int + UFUNCTION(BlueprintPure, Category = "Online|AdvancedSessions|SessionInfo|Literals") + static FSessionPropertyKeyPair MakeLiteralSessionPropertyInt(FName Key, int32 Value); + + // Make a literal session custom information key/value pair from Float + UFUNCTION(BlueprintPure, Category = "Online|AdvancedSessions|SessionInfo|Literals") + static FSessionPropertyKeyPair MakeLiteralSessionPropertyFloat(FName Key, float Value); + + + //******* Player ID functions *********// + + // Get the unique net id of a network player attached to the given controller + UFUNCTION(BlueprintPure, Category = "Online|AdvancedSessions|PlayerInfo|PlayerID") + static void GetUniqueNetID(APlayerController *PlayerController, FBPUniqueNetId &UniqueNetId); + + // Get the unique net id of a network player who is assigned the the given player state + UFUNCTION(BlueprintPure, Category = "Online|AdvancedSessions|PlayerInfo|PlayerID") + static void GetUniqueNetIDFromPlayerState(APlayerState *PlayerState, FBPUniqueNetId &UniqueNetId); + + // Return True if Unique Net ID is valid + UFUNCTION(BlueprintPure, Category = "Online|AdvancedSessions|PlayerInfo|PlayerID") + static bool IsValidUniqueNetID(const FBPUniqueNetId &UniqueNetId); + + /* Returns true if the values are equal (A == B) */ + UFUNCTION(BlueprintPure, meta = (DisplayName = "Equal Unique Net ID", CompactNodeTitle = "==", Keywords = "== equal"), Category = "Online|AdvancedSessions|PlayerInfo|PlayerID") + static bool EqualEqual_UNetIDUnetID(const FBPUniqueNetId &A, const FBPUniqueNetId &B); + + /** Converts a FBPUniqueNetID into a FUniqueNetID_Repl */ + UFUNCTION(BlueprintPure, meta = (DisplayName = "ToUniqueNetIDRepl (Unique Net ID)", CompactNodeTitle = "->", BlueprintAutocast), Category = "Online|AdvancedSessions|PlayerInfo|PlayerID") + static FUniqueNetIdRepl Conv_BPUniqueIDToUniqueNetIDRepl(const FBPUniqueNetId& InUniqueID); + + // Check if a UniqueNetId is a friend + UFUNCTION(BlueprintPure, Category = "Online|AdvancedSessions|UniqueNetId") + static void UniqueNetIdToString(const FBPUniqueNetId &UniqueNetId, FString &String); + + //******** Player Name Functions **********// + + // Get the player name of a network player attached to the given controller + UFUNCTION(BlueprintPure, Category = "Online|AdvancedSessions|PlayerInfo|PlayerName") + static void GetPlayerName(APlayerController *PlayerController, FString &PlayerName); + + // Set the player name of a network player attached to the given controller + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedSessions|PlayerInfo|PlayerName") + static void SetPlayerName(APlayerController *PlayerController, FString PlayerName); + + //********** Misc Player Info Functions *********// + + // Get the number of network players + UFUNCTION(BlueprintPure, Category = "Online|AdvancedSessions|PlayerInfo|Misc", meta = (bIgnoreSelf = "true", WorldContext = "WorldContextObject", DisplayName = "GetNumNetworkPlayers")) + static void GetNumberOfNetworkPlayers(UObject* WorldContextObject, int32 &NumNetPlayers); + + // Get the network player index of the given controller + UFUNCTION(BlueprintPure, Category = "Online|AdvancedSessions|PlayerInfo|Misc") + static void GetNetPlayerIndex(APlayerController *PlayerController, int32 &NetPlayerIndex); + + // Checks if the stated session subsystem is active + UFUNCTION(BlueprintPure, Category = "Online|AdvancedSessions|Misc") + static bool HasOnlineSubsystem(FName SubSystemName); + + //**** Seamless travel Functions ****// + + //Exposes Server travel to blueprint + UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category = "Online|AdvancedSessions|Seamless", meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject")) + static bool ServerTravel(UObject* WorldContextObject, const FString& InURL, bool bAbsolute, bool bShouldSkipGameNotify); + +}; diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/AdvancedVoiceLibrary.h b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/AdvancedVoiceLibrary.h new file mode 100644 index 0000000..da1128d --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/AdvancedVoiceLibrary.h @@ -0,0 +1,99 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once +#include "CoreMinimal.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "BlueprintDataDefinitions.h" +#include "Online.h" +#include "OnlineSubsystem.h" +#include "Interfaces/VoiceInterface.h" +//#include "OnlineFriendsInterface.h" +//#include "OnlineUserInterface.h" +//#include "OnlineMessageInterface.h" +//#include "OnlinePresenceInterface.h" +#include "Engine/GameInstance.h" +//#include "OnlineSessionInterface.h" + +#include "UObject/UObjectIterator.h" + +#include "AdvancedVoiceLibrary.generated.h" + + +//General Advanced Sessions Log +DECLARE_LOG_CATEGORY_EXTERN(AdvancedVoiceLog, Log, All); + + +UCLASS() +class UAdvancedVoiceLibrary : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() +public: + + //********* Voice Library Functions *************// + + // Get if a headset is present for the specified local user + UFUNCTION(BlueprintPure, Category = "Online|AdvancedVoice|VoiceInfo", meta = (WorldContext = "WorldContextObject")) + static void IsHeadsetPresent(UObject* WorldContextObject, bool & bHasHeadset, uint8 LocalPlayerNum = 0); + + // Starts networked voice, allows push to talk in coordination with StopNetworkedVoice + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedVoice", meta = (WorldContext = "WorldContextObject")) + static void StartNetworkedVoice(UObject* WorldContextObject, uint8 LocalPlayerNum = 0); + + // Stops networked voice, allows push to talk in coordination with StartNetworkedVoice + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedVoice", meta = (WorldContext = "WorldContextObject")) + static void StopNetworkedVoice(UObject* WorldContextObject, uint8 LocalPlayerNum = 0); + + // Registers a local player as someone interested in voice data + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedVoice", meta = (WorldContext = "WorldContextObject")) + static bool RegisterLocalTalker(UObject* WorldContextObject, uint8 LocalPlayerNum = 0); + + // Registers all signed in players as local talkers + // This is already done automatically, only do it manually if you unregistered someone + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedVoice", meta = (WorldContext = "WorldContextObject")) + static void RegisterAllLocalTalkers(UObject* WorldContextObject); + + // UnRegisters local player as a local talker + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedVoice", meta = (WorldContext = "WorldContextObject")) + static void UnRegisterLocalTalker(UObject* WorldContextObject, uint8 LocalPlayerNum = 0); + + // UnRegisters all signed in players as local talkers + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedVoice", meta = (WorldContext = "WorldContextObject")) + static void UnRegisterAllLocalTalkers(UObject* WorldContextObject); + + // Registers a remote player as a talker + // This is already done automatically, only do it manually if you unregistered someone + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedVoice", meta = (WorldContext = "WorldContextObject")) + static bool RegisterRemoteTalker(UObject* WorldContextObject, const FBPUniqueNetId& UniqueNetId); + + // UnRegisters a remote player as a talker + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedVoice", meta = (WorldContext = "WorldContextObject")) + static bool UnRegisterRemoteTalker(UObject* WorldContextObject, const FBPUniqueNetId& UniqueNetId); + + // UnRegisters all remote players as talkers + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedVoice", meta = (WorldContext = "WorldContextObject")) + static void RemoveAllRemoteTalkers(UObject* WorldContextObject); + + // Returns whether a local player is currently talking + UFUNCTION(BlueprintPure, Category = "Online|AdvancedVoice|VoiceInfo", meta = (WorldContext = "WorldContextObject")) + static bool IsLocalPlayerTalking(UObject* WorldContextObject, uint8 LocalPlayerNum); + + // Returns whether a remote player is currently talking + UFUNCTION(BlueprintPure, Category = "Online|AdvancedVoice|VoiceInfo", meta = (WorldContext = "WorldContextObject")) + static bool IsRemotePlayerTalking(UObject* WorldContextObject, const FBPUniqueNetId& UniqueNetId); + + // Returns whether a player is muted for the specified local player + UFUNCTION(BlueprintPure, Category = "Online|AdvancedVoice|VoiceInfo", meta = (WorldContext = "WorldContextObject")) + static bool IsPlayerMuted(UObject* WorldContextObject, uint8 LocalUserNumChecking, const FBPUniqueNetId& UniqueNetId); + + // Mutes the player associated with the uniquenetid for the specified local player, if IsSystemWide is true then it will attempt to mute globally for the player + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedVoice", meta = (WorldContext = "WorldContextObject")) + static bool MuteRemoteTalker(UObject* WorldContextObject, uint8 LocalUserNum, const FBPUniqueNetId& UniqueNetId, bool bIsSystemWide = false); + + // UnMutes the player associated with the uniquenetid for the specified local player, if IsSystemWide is true then it will attempt to unmute globally for the player + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedVoice", meta = (WorldContext = "WorldContextObject")) + static bool UnMuteRemoteTalker(UObject* WorldContextObject, uint8 LocalUserNum, const FBPUniqueNetId& UniqueNetId, bool bIsSystemWide = false); + + // Gets the number of local talkers for this system + UFUNCTION(BlueprintPure, Category = "Online|AdvancedVoice|VoiceInfo", meta = (WorldContext = "WorldContextObject")) + static void GetNumLocalTalkers(UObject* WorldContextObject, int32 & NumLocalTalkers); +}; diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/AutoLoginUserCallbackProxy.h b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/AutoLoginUserCallbackProxy.h new file mode 100644 index 0000000..d07a666 --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/AutoLoginUserCallbackProxy.h @@ -0,0 +1,55 @@ +// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. +#pragma once + +#include "CoreMinimal.h" +#include "BlueprintDataDefinitions.h" +#include "Interfaces/OnlineIdentityInterface.h" +#include "Engine/LocalPlayer.h" +#include "AutoLoginUserCallbackProxy.generated.h" + +UCLASS(MinimalAPI) +class UAutoLoginUserCallbackProxy : public UOnlineBlueprintCallProxyBase +{ + GENERATED_UCLASS_BODY() + + // Called when there is a successful destroy + UPROPERTY(BlueprintAssignable) + FEmptyOnlineDelegate OnSuccess; + + // Called when there is an unsuccessful destroy + UPROPERTY(BlueprintAssignable) + FEmptyOnlineDelegate OnFailure; + + /** + * Logs the player into the online service using parameters passed on the + * command line. Expects -AUTH_LOGIN= -AUTH_PASSWORD=. If either + * are missing, the function returns false and doesn't start the login + * process + * + * @param LocalUserNum the controller number of the associated user + * + */ + UFUNCTION(BlueprintCallable, meta=(BlueprintInternalUseOnly = "true", WorldContext="WorldContextObject"), Category = "Online|AdvancedIdentity") + static UAutoLoginUserCallbackProxy* AutoLoginUser(UObject* WorldContextObject, int32 LocalUserNum); + + // UOnlineBlueprintCallProxyBase interface + virtual void Activate() override; + // End of UOnlineBlueprintCallProxyBase interface + +private: + // Internal callback when the operation completes, calls out to the public success/failure callbacks + void OnCompleted(int32 LocalUserNum, bool bWasSuccessful, const FUniqueNetId& UserId, const FString& ErrorVal); + +private: + // The controller number of the associated user + int32 LocalUserNumber; + + // The delegate executed by the online subsystem + FOnLoginCompleteDelegate Delegate; + + // Handle to the registered OnDestroySessionComplete delegate + FDelegateHandle DelegateHandle; + + // The world context object in which this call is taking place + TWeakObjectPtr WorldContextObject; +}; diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/BlueprintDataDefinitions.h b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/BlueprintDataDefinitions.h new file mode 100644 index 0000000..b5dc438 --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/BlueprintDataDefinitions.h @@ -0,0 +1,435 @@ +#pragma once +#include "CoreMinimal.h" +//#include "EngineMinimal.h" +#include "Engine/Engine.h" +#include "GameFramework/PlayerState.h" +//#include "Core.h" +#include "Interfaces/OnlineSessionInterface.h" +#include "OnlineSessionSettings.h" +#include "OnlineDelegateMacros.h" +#include "OnlineSubsystem.h" +#include "OnlineSubsystemImpl.h" +#include "OnlineSubsystemUtils.h" +#include "OnlineSubsystemUtilsModule.h" +#include "GameFramework/PlayerController.h" +#include "Modules/ModuleManager.h" +#include "OnlineSubsystemUtilsClasses.h" +#include "BlueprintDataDefinitions.generated.h" + +UENUM(BlueprintType) +enum class EBPUserPrivileges : uint8 +{ + /** Whether the user can play at all, online or offline - may be age restricted */ + CanPlay, + /** Whether the user can play in online modes */ + CanPlayOnline, + /** Whether the user can use voice and text chat */ + CanCommunicateOnline, + /** Whether the user can use content generated by other users */ + CanUseUserGeneratedContent +}; + + +UENUM(BlueprintType) +enum class EBPLoginStatus : uint8 +{ + /** Player has not logged in or chosen a local profile */ + NotLoggedIn, + /** Player is using a local profile but is not logged in */ + UsingLocalProfile, + /** Player has been validated by the platform specific authentication service */ + LoggedIn +}; + + +USTRUCT(BlueprintType) +struct FBPUserOnlineAccount +{ + GENERATED_USTRUCT_BODY() + +public: + TSharedPtr UserAccountInfo; + + FBPUserOnlineAccount() + { + + } + + FBPUserOnlineAccount(TSharedPtr UserAccount) + { + UserAccountInfo = UserAccount; + } +}; + +UENUM() +enum class ESessionSettingSearchResult : uint8 +{ + // Found the setting + Found, + + // Did not find the setting + NotFound, + + // Was not the correct type + WrongType +}; + +// This makes a lot of the blueprint functions cleaner +UENUM() +enum class EBlueprintResultSwitch : uint8 +{ + // On Success + OnSuccess, + + // On Failure + OnFailure +}; + +// This makes a lot of the blueprint functions cleaner +UENUM() +enum class EBlueprintAsyncResultSwitch : uint8 +{ + // On Success + OnSuccess, + + // Still loading + AsyncLoading, + // On Failure + OnFailure +}; + +// This is to define server type searches +UENUM(BlueprintType) +enum class EBPServerPresenceSearchType : uint8 +{ + AllServers, + ClientServersOnly, + DedicatedServersOnly +}; + +// Wanted this to be switchable in the editor +UENUM(BlueprintType) +enum class EBPOnlinePresenceState : uint8 +{ + Online, + Offline, + Away, + ExtendedAway, + DoNotDisturb, + Chat +}; + +UENUM(BlueprintType) +enum class EBPOnlineSessionState : uint8 +{ + /** An online session has not been created yet */ + NoSession, + /** An online session is in the process of being created */ + Creating, + /** Session has been created but the session hasn't started (pre match lobby) */ + Pending, + /** Session has been asked to start (may take time due to communication with backend) */ + Starting, + /** The current session has started. Sessions with join in progress disabled are no longer joinable */ + InProgress, + /** The session is still valid, but the session is no longer being played (post match lobby) */ + Ending, + /** The session is closed and any stats committed */ + Ended, + /** The session is being destroyed */ + Destroying +}; + +// Boy oh boy is this a dirty hack, but I can't figure out a good way to do it otherwise at the moment +// The UniqueNetId is an abstract class so I can't exactly re-initialize it to make a shared pointer on some functions +// So I made the blueprintable UniqueNetID into a dual variable struct with access functions and I am converting the const var for the pointer +// I really need to re-think this later +USTRUCT(BlueprintType) +struct FBPUniqueNetId +{ + GENERATED_USTRUCT_BODY() + +private: + bool bUseDirectPointer; + + +public: + TSharedPtr UniqueNetId; + const FUniqueNetId * UniqueNetIdPtr; + + void SetUniqueNetId(const TSharedPtr &ID) + { + bUseDirectPointer = false; + UniqueNetIdPtr = nullptr; + UniqueNetId = ID; + } + + void SetUniqueNetId(const FUniqueNetId *ID) + { + bUseDirectPointer = true; + UniqueNetIdPtr = ID; + } + + bool IsValid() const + { + if (bUseDirectPointer && UniqueNetIdPtr != nullptr && UniqueNetIdPtr->IsValid()) + { + return true; + } + else if (UniqueNetId.IsValid()) + { + return true; + } + else + return false; + + } + + const FUniqueNetId* GetUniqueNetId() const + { + if (bUseDirectPointer && UniqueNetIdPtr != nullptr) + { + // No longer converting to non const as all functions now pass const UniqueNetIds + return /*const_cast*/(UniqueNetIdPtr); + } + else if (UniqueNetId.IsValid()) + { + return UniqueNetId.Get(); + } + else + return nullptr; + } + + // Adding in a compare operator so that std functions will work with this struct + FORCEINLINE bool operator==(const FBPUniqueNetId& Other) const + { + return (IsValid() && Other.IsValid() && (*GetUniqueNetId() == *Other.GetUniqueNetId())); + } + + FORCEINLINE bool operator!=(const FBPUniqueNetId& Other) const + { + return !(IsValid() && Other.IsValid() && (*GetUniqueNetId() == *Other.GetUniqueNetId())); + } + + FBPUniqueNetId() + { + bUseDirectPointer = false; + UniqueNetIdPtr = nullptr; + } +}; + +USTRUCT(BluePrintType) +struct FBPOnlineUser +{ + GENERATED_USTRUCT_BODY() + +public: + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Online|Friend") + FBPUniqueNetId UniqueNetId; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Online|Friend") + FString DisplayName; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Online|Friend") + FString RealName; +}; + +USTRUCT(BluePrintType) +struct FBPOnlineRecentPlayer : public FBPOnlineUser +{ + GENERATED_USTRUCT_BODY() + +public: + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Online|Friend") + FString LastSeen; +}; + + +USTRUCT(BlueprintType) +struct FBPFriendPresenceInfo +{ + GENERATED_USTRUCT_BODY() + +public: + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Online|Friend") + bool bIsOnline = false; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Online|Friend") + bool bIsPlaying = false; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Online|Friend") + bool bIsPlayingThisGame = false; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Online|Friend") + bool bIsJoinable = false; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Online|Friend") + bool bHasVoiceSupport = false; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Online|Friend") + EBPOnlinePresenceState PresenceState = EBPOnlinePresenceState::Offline; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Online|Friend") + FString StatusString; + + FBPFriendPresenceInfo() + { + bIsOnline = false; + bIsPlaying = false; + bIsPlayingThisGame = false; + bIsJoinable = false; + bHasVoiceSupport = false; + PresenceState = EBPOnlinePresenceState::Offline; + } +}; + +USTRUCT(BlueprintType) +struct FBPFriendInfo +{ + GENERATED_USTRUCT_BODY() + +public: + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Online|Friend") + FString DisplayName; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Online|Friend") + FString RealName; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Online|Friend") + EBPOnlinePresenceState OnlineState = EBPOnlinePresenceState::Offline; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Online|Friend") + FBPUniqueNetId UniqueNetId; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Online|Friend") + bool bIsPlayingSameGame = false; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Online|Friend") + FBPFriendPresenceInfo PresenceInfo; + + FBPFriendInfo() + { + OnlineState = EBPOnlinePresenceState::Offline; + bIsPlayingSameGame = false; + } +}; + + +/** The types of comparison operations for a given search query */ +// Used to compare session properties +UENUM(BlueprintType) +enum class EOnlineComparisonOpRedux : uint8 +{ + Equals, + NotEquals, + GreaterThan, + GreaterThanEquals, + LessThan, + LessThanEquals, +}; + + +// Used to store session properties before converting to FVariantData +USTRUCT(BlueprintType) +struct FSessionPropertyKeyPair +{ + GENERATED_USTRUCT_BODY() + + FName Key; + FVariantData Data; +}; + + +// Sent to the FindSessionsAdvanced to filter the end results +USTRUCT(BlueprintType) +struct FSessionsSearchSetting +{ + GENERATED_USTRUCT_BODY() + //UPROPERTY() + + + // Had to make a copy of this to account for the original not being exposed to blueprints + /** How is this session setting compared on the backend searches */ + EOnlineComparisonOpRedux ComparisonOp; + + // The key pair to search for + FSessionPropertyKeyPair PropertyKeyPair; +}; + +// Couldn't use the default one as it is not exposed to other modules, had to re-create it here +// Helper class for various methods to reduce the call hierarchy +struct FOnlineSubsystemBPCallHelperAdvanced +{ +public: + FOnlineSubsystemBPCallHelperAdvanced(const TCHAR* CallFunctionContext, UWorld* World, FName SystemName = NAME_None) + : OnlineSub(Online::GetSubsystem(World, SystemName)) + , FunctionContext(CallFunctionContext) + { + if (OnlineSub == nullptr) + { + FFrame::KismetExecutionMessage(*FString::Printf(TEXT("%s - Invalid or uninitialized OnlineSubsystem"), FunctionContext), ELogVerbosity::Warning); + } + } + + void QueryIDFromPlayerController(APlayerController* PlayerController) + { + UserID.Reset(); + //return const_cast(UniqueNetIdPtr); + if (APlayerState* PlayerState = (PlayerController != NULL) ? PlayerController->PlayerState : NULL) + { + UserID = PlayerState->GetUniqueId().GetUniqueNetId(); + if (!UserID.IsValid()) + { + FFrame::KismetExecutionMessage(*FString::Printf(TEXT("%s - Cannot map local player to unique net ID"), FunctionContext), ELogVerbosity::Warning); + } + } + else + { + FFrame::KismetExecutionMessage(*FString::Printf(TEXT("%s - Invalid player state"), FunctionContext), ELogVerbosity::Warning); + } + } + + + bool IsValid() const + { + return UserID.IsValid() && (OnlineSub != nullptr); + } + +public: + //TSharedPtr& GetUniqueNetId() + TSharedPtr UserID; + IOnlineSubsystem* const OnlineSub; + const TCHAR* FunctionContext; +}; +class FOnlineSearchSettingsEx : public FOnlineSearchSettings +{ + /** + * Sets a key value pair combination that defines a search parameter + * + * @param Key key for the setting + * @param Value value of the setting + * @param InType type of comparison + */ +public: + + void HardSet(FName Key, const FVariantData& Value, EOnlineComparisonOpRedux CompOp) + { + FOnlineSessionSearchParam* SearchParam = SearchParams.Find(Key); + + TEnumAsByte op; + + switch (CompOp) + { + case EOnlineComparisonOpRedux::Equals: op = EOnlineComparisonOp::Equals; break; + case EOnlineComparisonOpRedux::GreaterThan: op = EOnlineComparisonOp::GreaterThan; break; + case EOnlineComparisonOpRedux::GreaterThanEquals: op = EOnlineComparisonOp::GreaterThanEquals; break; + case EOnlineComparisonOpRedux::LessThan: op = EOnlineComparisonOp::LessThan; break; + case EOnlineComparisonOpRedux::LessThanEquals: op = EOnlineComparisonOp::LessThanEquals; break; + case EOnlineComparisonOpRedux::NotEquals: op = EOnlineComparisonOp::NotEquals; break; + default: op = EOnlineComparisonOp::Equals; break; + } + + if (SearchParam) + { + SearchParam->Data = Value; + SearchParam->ComparisonOp = op; + } + else + { + FOnlineSessionSearchParam searchSetting((int)0, op); + searchSetting.Data = Value; + SearchParams.Add(Key, searchSetting); + } + } +}; + +#define INVALID_INDEX -1 \ No newline at end of file diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/CancelFindSessionsCallbackProxy.h b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/CancelFindSessionsCallbackProxy.h new file mode 100644 index 0000000..58d2ea0 --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/CancelFindSessionsCallbackProxy.h @@ -0,0 +1,46 @@ +// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. +#pragma once +#include "CoreMinimal.h" +#include "Engine/Engine.h" +#include "Interfaces/OnlineSessionInterface.h" +#include "BlueprintDataDefinitions.h" +#include "CancelFindSessionsCallbackProxy.generated.h" + +UCLASS(MinimalAPI) +class UCancelFindSessionsCallbackProxy : public UOnlineBlueprintCallProxyBase +{ + GENERATED_UCLASS_BODY() + + // Called when there is a successful destroy + UPROPERTY(BlueprintAssignable) + FEmptyOnlineDelegate OnSuccess; + + // Called when there is an unsuccessful destroy + UPROPERTY(BlueprintAssignable) + FEmptyOnlineDelegate OnFailure; + + // Cancels finding sessions + UFUNCTION(BlueprintCallable, meta=(BlueprintInternalUseOnly = "true", WorldContext="WorldContextObject"), Category = "Online|AdvancedSessions") + static UCancelFindSessionsCallbackProxy* CancelFindSessions(UObject* WorldContextObject, class APlayerController* PlayerController); + + // UOnlineBlueprintCallProxyBase interface + virtual void Activate() override; + // End of UOnlineBlueprintCallProxyBase interface + +private: + // Internal callback when the operation completes, calls out to the public success/failure callbacks + void OnCompleted(bool bWasSuccessful); + +private: + // The player controller triggering things + TWeakObjectPtr PlayerControllerWeakPtr; + + // The delegate executed by the online subsystem + FOnCancelFindSessionsCompleteDelegate Delegate; + + // Handle to the registered OnDestroySessionComplete delegate + FDelegateHandle DelegateHandle; + + // The world context object in which this call is taking place + TWeakObjectPtr WorldContextObject; +}; diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/CreateSessionCallbackProxyAdvanced.h b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/CreateSessionCallbackProxyAdvanced.h new file mode 100644 index 0000000..04ae6d1 --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/CreateSessionCallbackProxyAdvanced.h @@ -0,0 +1,107 @@ +// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. +#pragma once + +#include "CoreMinimal.h" +#include "Engine/Engine.h" +#include "BlueprintDataDefinitions.h" +#include "CreateSessionCallbackProxyAdvanced.generated.h" + +UCLASS(MinimalAPI) +class UCreateSessionCallbackProxyAdvanced : public UOnlineBlueprintCallProxyBase +{ + GENERATED_UCLASS_BODY() + + // Called when the session was created successfully + UPROPERTY(BlueprintAssignable) + FEmptyOnlineDelegate OnSuccess; + + // Called when there was an error creating the session + UPROPERTY(BlueprintAssignable) + FEmptyOnlineDelegate OnFailure; + + /** + * Creates a session with the default online subsystem with advanced optional inputs, for dedicated servers leave UsePresence as false and set IsDedicatedServer to true. Dedicated servers don't use presence. + * @param PublicConnections When doing a 'listen' server, this must be >=2 (ListenServer itself counts as a connection) + * @param bUseLAN When you want to play LAN, the level to play on must be loaded with option 'bIsLanMatch' + * @param bUsePresence Must be true for a 'listen' server (Map must be loaded with option 'listen'), false for a 'dedicated' server. + * @param bUseLobbiesIfAvailable Used to flag the subsystem to use a lobby api instead of general hosting if the API supports it, generally true on steam for listen servers and false for dedicated + * @param bShouldAdvertise Set to true when the OnlineSubsystem should list your server when someone is searching for servers. Otherwise the server is hidden and only join via invite is possible. + * @param bUseLobbiesVoiceChatIfAvailable Set to true to setup voice chat lobbies if the API supports it + * @param bStartAfterCreate Set to true to start the session after it's created. If false you need to manually call StartSession when ready. + */ + UFUNCTION(BlueprintCallable, meta=(BlueprintInternalUseOnly = "true", WorldContext="WorldContextObject",AutoCreateRefTerm="ExtraSettings"), Category = "Online|AdvancedSessions") + static UCreateSessionCallbackProxyAdvanced* CreateAdvancedSession(UObject* WorldContextObject, const TArray& ExtraSettings, class APlayerController* PlayerController = NULL, int32 PublicConnections = 100, int32 PrivateConnections = 0, bool bUseLAN = false, bool bAllowInvites = true, bool bIsDedicatedServer = false, bool bUsePresence = true, bool bUseLobbiesIfAvailable = true, bool bAllowJoinViaPresence = true, bool bAllowJoinViaPresenceFriendsOnly = false, bool bAntiCheatProtected = false, bool bUsesStats = false, bool bShouldAdvertise = true, bool bUseLobbiesVoiceChatIfAvailable = false, bool bStartAfterCreate = true); + + // UOnlineBlueprintCallProxyBase interface + virtual void Activate() override; + // End of UOnlineBlueprintCallProxyBase interface + +private: + // Internal callback when session creation completes, optionally calls StartSession + void OnCreateCompleted(FName SessionName, bool bWasSuccessful); + + // Internal callback when session start completes + void OnStartCompleted(FName SessionName, bool bWasSuccessful); + + // The player controller triggering things + TWeakObjectPtr PlayerControllerWeakPtr; + + // The delegate executed by the online subsystem + FOnCreateSessionCompleteDelegate CreateCompleteDelegate; + + // The delegate executed by the online subsystem + FOnStartSessionCompleteDelegate StartCompleteDelegate; + + // Handles to the registered delegates above + FDelegateHandle CreateCompleteDelegateHandle; + FDelegateHandle StartCompleteDelegateHandle; + + // Number of public connections + int NumPublicConnections; + + // Number of private connections + int NumPrivateConnections; + + // Whether or not to search LAN + bool bUseLAN; + + // Whether or not to allow invites + bool bAllowInvites; + + // Whether this is a dedicated server or not + bool bDedicatedServer; + + // Whether to use the presence option + bool bUsePresence; + + // Whether to prefer the use of lobbies for hosting if the api supports them + bool bUseLobbiesIfAvailable; + + // Whether to allow joining via presence + bool bAllowJoinViaPresence; + + // Allow joining via presence for friends only + bool bAllowJoinViaPresenceFriendsOnly; + + // Delcare the server to be anti cheat protected + bool bAntiCheatProtected; + + // Record Stats + bool bUsesStats; + + // Should advertise server? + bool bShouldAdvertise; + + // Whether to prefer the use of voice chat lobbies if the api supports them + bool bUseLobbiesVoiceChatIfAvailable; + + // Whether to start the session automatically after it is created + bool bStartAfterCreate; + + // Store extra settings + TArray ExtraSettings; + + // The world context object in which this call is taking place + TWeakObjectPtr WorldContextObject; +}; + diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/EndSessionCallbackProxy.h b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/EndSessionCallbackProxy.h new file mode 100644 index 0000000..e527c58 --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/EndSessionCallbackProxy.h @@ -0,0 +1,49 @@ +// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. +#pragma once +#include "CoreMinimal.h" +#include "Engine/Engine.h" +#include "Interfaces/OnlineSessionInterface.h" +#include "BlueprintDataDefinitions.h" +#include "EndSessionCallbackProxy.generated.h" + +UCLASS(MinimalAPI) +class UEndSessionCallbackProxy : public UOnlineBlueprintCallProxyBase +{ + GENERATED_UCLASS_BODY() + + // Called when there is a successful destroy + UPROPERTY(BlueprintAssignable) + FEmptyOnlineDelegate OnSuccess; + + // Called when there is an unsuccessful destroy + UPROPERTY(BlueprintAssignable) + FEmptyOnlineDelegate OnFailure; + + /** + * Ends the current sessions, Generally for almost all uses you should be using the engines native Destroy Session node instead. + * This exists for people using StartSession and optionally hand managing the session state. + */ + UFUNCTION(BlueprintCallable, meta=(BlueprintInternalUseOnly = "true", WorldContext="WorldContextObject"), Category = "Online|AdvancedSessions") + static UEndSessionCallbackProxy* EndSession(UObject* WorldContextObject, class APlayerController* PlayerController); + + // UOnlineBlueprintCallProxyBase interface + virtual void Activate() override; + // End of UOnlineBlueprintCallProxyBase interface + +private: + // Internal callback when the operation completes, calls out to the public success/failure callbacks + void OnCompleted(FName SessionName, bool bWasSuccessful); + +private: + // The player controller triggering things + TWeakObjectPtr PlayerControllerWeakPtr; + + // The delegate executed by the online subsystem + FOnEndSessionCompleteDelegate Delegate; + + // Handle to the registered OnDestroySessionComplete delegate + FDelegateHandle DelegateHandle; + + // The world context object in which this call is taking place + TWeakObjectPtr WorldContextObject; +}; diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/FindFriendSessionCallbackProxy.h b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/FindFriendSessionCallbackProxy.h new file mode 100644 index 0000000..58ef8f5 --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/FindFriendSessionCallbackProxy.h @@ -0,0 +1,51 @@ +// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. +#pragma once + +#include "CoreMinimal.h" +#include "BlueprintDataDefinitions.h" +#include "Engine/LocalPlayer.h" +#include "FindFriendSessionCallbackProxy.generated.h" + +DECLARE_LOG_CATEGORY_EXTERN(AdvancedFindFriendSessionLog, Log, All); + +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FBlueprintFindFriendSessionDelegate, const TArray &, SessionInfo); + +UCLASS(MinimalAPI) +class UFindFriendSessionCallbackProxy : public UOnlineBlueprintCallProxyBase +{ + GENERATED_UCLASS_BODY() + + // Called when the friends list successfully was retrieved + UPROPERTY(BlueprintAssignable) + FBlueprintFindFriendSessionDelegate OnSuccess; + + // Called when there was an error retrieving the friends list + UPROPERTY(BlueprintAssignable) + FBlueprintFindFriendSessionDelegate OnFailure; + + // Attempts to get the current session that a friend is in + UFUNCTION(BlueprintCallable, meta=(BlueprintInternalUseOnly = "true", WorldContext="WorldContextObject"), Category = "Online|AdvancedFriends") + static UFindFriendSessionCallbackProxy* FindFriendSession(UObject* WorldContextObject, APlayerController *PlayerController, const FBPUniqueNetId &FriendUniqueNetId); + + virtual void Activate() override; + +private: + // Internal callback when the friends list is retrieved + void OnFindFriendSessionCompleted(int32 LocalPlayer, bool bWasSuccessful, const TArray& SessionInfo); + + // The player controller triggering things + TWeakObjectPtr PlayerControllerWeakPtr; + + // The UniqueNetID of the person to invite + FBPUniqueNetId cUniqueNetId; + + // The delegate to call on completion + FOnFindFriendSessionCompleteDelegate OnFindFriendSessionCompleteDelegate; + + // Handles to the registered delegates above + FDelegateHandle FindFriendSessionCompleteDelegateHandle; + + // The world context object in which this call is taking place + TWeakObjectPtr WorldContextObject; +}; + diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/FindSessionsCallbackProxyAdvanced.h b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/FindSessionsCallbackProxyAdvanced.h new file mode 100644 index 0000000..e610277 --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/FindSessionsCallbackProxyAdvanced.h @@ -0,0 +1,109 @@ +// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. +#pragma once +#include "CoreMinimal.h" +#include "Engine/Engine.h" +#include "Interfaces/OnlineSessionInterface.h" +#include "FindSessionsCallbackProxy.h" +#include "BlueprintDataDefinitions.h" +#include "FindSessionsCallbackProxyAdvanced.generated.h" + + +FORCEINLINE bool operator==(const FBlueprintSessionResult& A, const FBlueprintSessionResult& B) +{ + return (A.OnlineResult.IsValid() == B.OnlineResult.IsValid() && (A.OnlineResult.GetSessionIdStr() == B.OnlineResult.GetSessionIdStr())); +} + +UCLASS(MinimalAPI) +class UFindSessionsCallbackProxyAdvanced : public UOnlineBlueprintCallProxyBase +{ + GENERATED_UCLASS_BODY() + + // Called when there is a successful query + UPROPERTY(BlueprintAssignable) + FBlueprintFindSessionsResultDelegate OnSuccess; + + // Called when there is an unsuccessful query + UPROPERTY(BlueprintAssignable) + FBlueprintFindSessionsResultDelegate OnFailure; + + // Searches for advertised sessions with the default online subsystem and includes an array of filters + UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", WorldContext = "WorldContextObject", AutoCreateRefTerm="Filters"), Category = "Online|AdvancedSessions") + static UFindSessionsCallbackProxyAdvanced* FindSessionsAdvanced(UObject* WorldContextObject, class APlayerController* PlayerController, int32 MaxResults, bool bUseLAN, EBPServerPresenceSearchType ServerTypeToSearch, const TArray &Filters, bool bEmptyServersOnly = false, bool bNonEmptyServersOnly = false, bool bSecureServersOnly = false, bool bSearchLobbies = true, int MinSlotsAvailable = 0); + + static bool CompareVariants(const FVariantData &A, const FVariantData &B, EOnlineComparisonOpRedux Comparator); + + // Filters an array of session results by the given search parameters, returns a new array with the filtered results + UFUNCTION(BluePrintCallable, meta = (Category = "Online|AdvancedSessions")) + static void FilterSessionResults(const TArray &SessionResults, const TArray &Filters, TArray &FilteredResults); + + // Removed, the default built in versions work fine in the normal FindSessionsCallbackProxy + /*UFUNCTION(BlueprintPure, Category = "Online|Session") + static int32 GetPingInMs(const FBlueprintSessionResult& Result); + + UFUNCTION(BlueprintPure, Category = "Online|Session") + static FString GetServerName(const FBlueprintSessionResult& Result); + + UFUNCTION(BlueprintPure, Category = "Online|Session") + static int32 GetCurrentPlayers(const FBlueprintSessionResult& Result); + + UFUNCTION(BlueprintPure, Category = "Online|Session") + static int32 GetMaxPlayers(const FBlueprintSessionResult& Result);*/ + + + // UOnlineBlueprintCallProxyBase interface + virtual void Activate() override; + // End of UOnlineBlueprintCallProxyBase interface + +private: + // Internal callback when the session search completes, calls out to the public success/failure callbacks + void OnCompleted(bool bSuccess); + + bool bRunSecondSearch; + bool bIsOnSecondSearch; + + TArray SessionSearchResults; + +private: + // The player controller triggering things + TWeakObjectPtr PlayerControllerWeakPtr; + + // The delegate executed by the online subsystem + FOnFindSessionsCompleteDelegate Delegate; + + // Handle to the registered OnFindSessionsComplete delegate + FDelegateHandle DelegateHandle; + + // Object to track search results + TSharedPtr SearchObject; + TSharedPtr SearchObjectDedicated; + + // Whether or not to search LAN + bool bUseLAN; + + // Whether or not to search for dedicated servers + EBPServerPresenceSearchType ServerSearchType; + + // Maximum number of results to return + int MaxResults; + + // Store extra settings + TArray SearchSettings; + + // Search for empty servers only + bool bEmptyServersOnly; + + // Search for non empty servers only + bool bNonEmptyServersOnly; + + // Search for secure servers only + bool bSecureServersOnly; + + // Search through lobbies + bool bSearchLobbies; + + // Min slots requires to search + int MinSlotsAvailable; + + // The world context object in which this call is taking place + TWeakObjectPtr WorldContextObject; +}; diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/GetFriendsCallbackProxy.h b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/GetFriendsCallbackProxy.h new file mode 100644 index 0000000..844bef6 --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/GetFriendsCallbackProxy.h @@ -0,0 +1,49 @@ +// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. +#pragma once + +#include "CoreMinimal.h" +#include "BlueprintDataDefinitions.h" +#include "Engine/LocalPlayer.h" +#include "GetFriendsCallbackProxy.generated.h" + +DECLARE_LOG_CATEGORY_EXTERN(AdvancedGetFriendsLog, Log, All); + +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FBlueprintGetFriendsListDelegate, const TArray&, Results); + +UCLASS(MinimalAPI) +class UGetFriendsCallbackProxy : public UOnlineBlueprintCallProxyBase +{ + GENERATED_UCLASS_BODY() + + // Called when the friends list successfully was retrieved + UPROPERTY(BlueprintAssignable) + FBlueprintGetFriendsListDelegate OnSuccess; + + // Called when there was an error retrieving the friends list + UPROPERTY(BlueprintAssignable) + FBlueprintGetFriendsListDelegate OnFailure; + + // Gets the players list of friends from the OnlineSubsystem and returns it, can be retrieved later with GetStoredFriendsList + UFUNCTION(BlueprintCallable, meta=(BlueprintInternalUseOnly = "true", WorldContext="WorldContextObject"), Category = "Online|AdvancedFriends") + static UGetFriendsCallbackProxy* GetAndStoreFriendsList(UObject* WorldContextObject, class APlayerController* PlayerController); + + virtual void Activate() override; + +private: + // Internal callback when the friends list is retrieved + void OnReadFriendsListCompleted(int32 LocalUserNum, bool bWasSuccessful, const FString& ListName, const FString& ErrorString); + + // The player controller triggering things + TWeakObjectPtr PlayerControllerWeakPtr; + + // The delegate executed + FOnReadFriendsListComplete FriendListReadCompleteDelegate; + + // The Type of friends list to get + // Removed because all but the facebook interfaces don't even currently support anything but the default friends list. + //EBPFriendsLists FriendListToGet; + + // The world context object in which this call is taking place + TWeakObjectPtr WorldContextObject; +}; + diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/GetRecentPlayersCallbackProxy.h b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/GetRecentPlayersCallbackProxy.h new file mode 100644 index 0000000..2b12c9f --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/GetRecentPlayersCallbackProxy.h @@ -0,0 +1,49 @@ +// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. +#pragma once + +#include "CoreMinimal.h" +#include "BlueprintDataDefinitions.h" +#include "GetRecentPlayersCallbackProxy.generated.h" + +DECLARE_LOG_CATEGORY_EXTERN(AdvancedGetRecentPlayersLog, Log, All); + +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FBlueprintGetRecentPlayersDelegate, const TArray&, Results); + +UCLASS(MinimalAPI) +class UGetRecentPlayersCallbackProxy : public UOnlineBlueprintCallProxyBase +{ + GENERATED_UCLASS_BODY() + + // Called when the friends list successfully was retrieved + UPROPERTY(BlueprintAssignable) + FBlueprintGetRecentPlayersDelegate OnSuccess; + + // Called when there was an error retrieving the friends list + UPROPERTY(BlueprintAssignable) + FBlueprintGetRecentPlayersDelegate OnFailure; + + // Gets the list of recent players from the OnlineSubsystem and returns it, can be retrieved later with GetStoredRecentPlayersList, can fail if no recent players are found + UFUNCTION(BlueprintCallable, meta=(BlueprintInternalUseOnly = "true", WorldContext="WorldContextObject"), Category = "Online|AdvancedFriends") + static UGetRecentPlayersCallbackProxy* GetAndStoreRecentPlayersList(UObject* WorldContextObject, const FBPUniqueNetId &UniqueNetId); + + virtual void Activate() override; + +private: + // Internal callback when the friends list is retrieved + void OnQueryRecentPlayersCompleted(const FUniqueNetId &UserID, const FString &Namespace, bool bWasSuccessful, const FString& ErrorString); + // Handle to the registered OnFindSessionsComplete delegate + FDelegateHandle DelegateHandle; + + // The player controller triggering things + //TWeakObjectPtr PlayerControllerWeakPtr; + + // The UniqueNetID of the person to get recent players for + FBPUniqueNetId cUniqueNetId; + + // The delegate executed + FOnQueryRecentPlayersCompleteDelegate QueryRecentPlayersCompleteDelegate; + + // The world context object in which this call is taking place + TWeakObjectPtr WorldContextObject; +}; + diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/GetUserPrivilegeCallbackProxy.h b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/GetUserPrivilegeCallbackProxy.h new file mode 100644 index 0000000..f47d2a5 --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/GetUserPrivilegeCallbackProxy.h @@ -0,0 +1,45 @@ +// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. +#pragma once + +#include "CoreMinimal.h" +#include "BlueprintDataDefinitions.h" +#include "Interfaces/OnlineIdentityInterface.h" +#include "GetUserPrivilegeCallbackProxy.generated.h" + +DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FBlueprintGetUserPrivilegeDelegate,/* const &FBPUniqueNetId, PlayerID,*/ EBPUserPrivileges, QueriedPrivilege, bool, HadPrivilege); + +UCLASS(MinimalAPI) +class UGetUserPrivilegeCallbackProxy : public UOnlineBlueprintCallProxyBase +{ + GENERATED_UCLASS_BODY() + + // Called when there is a successful destroy + UPROPERTY(BlueprintAssignable) + FBlueprintGetUserPrivilegeDelegate OnSuccess; + + // Called when there is an unsuccessful destroy + UPROPERTY(BlueprintAssignable) + FEmptyOnlineDelegate OnFailure; + + // Gets the privilage of the user + UFUNCTION(BlueprintCallable, meta=(BlueprintInternalUseOnly = "true", WorldContext="WorldContextObject"), Category = "Online|AdvancedIdentity") + static UGetUserPrivilegeCallbackProxy* GetUserPrivilege(UObject* WorldContextObject, const EBPUserPrivileges & PrivilegeToCheck, const FBPUniqueNetId & PlayerUniqueNetID); + + // UOnlineBlueprintCallProxyBase interface + virtual void Activate() override; + // End of UOnlineBlueprintCallProxyBase interface + +private: + // Internal callback when the operation completes, calls out to the public success/failure callbacks + void OnCompleted(const FUniqueNetId& PlayerID, EUserPrivileges::Type Privilege, uint32 Result); + +private: + // The player controller triggering things + FBPUniqueNetId PlayerUniqueNetID; + + // Privilege to check + EBPUserPrivileges UserPrivilege; + + // The world context object in which this call is taking place + TWeakObjectPtr WorldContextObject; +}; diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/LoginUserCallbackProxy.h b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/LoginUserCallbackProxy.h new file mode 100644 index 0000000..ba65b68 --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/LoginUserCallbackProxy.h @@ -0,0 +1,55 @@ +// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. +#pragma once + +#include "CoreMinimal.h" +#include "BlueprintDataDefinitions.h" +#include "Interfaces/OnlineIdentityInterface.h" +#include "Engine/LocalPlayer.h" +#include "LoginUserCallbackProxy.generated.h" + +UCLASS(MinimalAPI) +class ULoginUserCallbackProxy : public UOnlineBlueprintCallProxyBase +{ + GENERATED_UCLASS_BODY() + + // Called when there is a successful destroy + UPROPERTY(BlueprintAssignable) + FEmptyOnlineDelegate OnSuccess; + + // Called when there is an unsuccessful destroy + UPROPERTY(BlueprintAssignable) + FEmptyOnlineDelegate OnFailure; + + // Logs into the identity interface + UFUNCTION(BlueprintCallable, meta=(BlueprintInternalUseOnly = "true", WorldContext="WorldContextObject", AdvancedDisplay = "AuthType"), Category = "Online|AdvancedIdentity") + static ULoginUserCallbackProxy* LoginUser(UObject* WorldContextObject, class APlayerController* PlayerController, FString UserID, FString UserToken, FString AuthType); + + // UOnlineBlueprintCallProxyBase interface + virtual void Activate() override; + // End of UOnlineBlueprintCallProxyBase interface + +private: + // Internal callback when the operation completes, calls out to the public success/failure callbacks + void OnCompleted(int32 LocalUserNum, bool bWasSuccessful, const FUniqueNetId& UserId, const FString& ErrorVal); + +private: + // The player controller triggering things + TWeakObjectPtr PlayerControllerWeakPtr; + + // The user ID + FString UserID; + + // The user pass / token + FString UserToken; + + FString AuthType; + + // The delegate executed by the online subsystem + FOnLoginCompleteDelegate Delegate; + + // Handle to the registered OnDestroySessionComplete delegate + FDelegateHandle DelegateHandle; + + // The world context object in which this call is taking place + TWeakObjectPtr WorldContextObject; +}; diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/LogoutUserCallbackProxy.h b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/LogoutUserCallbackProxy.h new file mode 100644 index 0000000..5f85b0a --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/LogoutUserCallbackProxy.h @@ -0,0 +1,47 @@ +// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. +#pragma once + +#include "CoreMinimal.h" +#include "BlueprintDataDefinitions.h" +#include "Interfaces/OnlineIdentityInterface.h" +#include "Engine/LocalPlayer.h" +#include "LogoutUserCallbackProxy.generated.h" + +UCLASS(MinimalAPI) +class ULogoutUserCallbackProxy : public UOnlineBlueprintCallProxyBase +{ + GENERATED_UCLASS_BODY() + + // Called when there is a successful destroy + UPROPERTY(BlueprintAssignable) + FEmptyOnlineDelegate OnSuccess; + + // Called when there is an unsuccessful destroy + UPROPERTY(BlueprintAssignable) + FEmptyOnlineDelegate OnFailure; + + // Logs out of the identity interface + UFUNCTION(BlueprintCallable, meta=(BlueprintInternalUseOnly = "true", WorldContext="WorldContextObject"), Category = "Online|AdvancedIdentity") + static ULogoutUserCallbackProxy* LogoutUser(UObject* WorldContextObject, class APlayerController* PlayerController); + + // UOnlineBlueprintCallProxyBase interface + virtual void Activate() override; + // End of UOnlineBlueprintCallProxyBase interface + +private: + // Internal callback when the operation completes, calls out to the public success/failure callbacks + void OnCompleted(int LocalUserNum, bool bWasSuccessful); + +private: + // The player controller triggering things + TWeakObjectPtr PlayerControllerWeakPtr; + + // The delegate executed by the online subsystem + FOnLogoutCompleteDelegate Delegate; + + // Handle to the registered OnDestroySessionComplete delegate + FDelegateHandle DelegateHandle; + + // The world context object in which this call is taking place + TWeakObjectPtr WorldContextObject; +}; diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/OnlineSubSystemHeader.h b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/OnlineSubSystemHeader.h new file mode 100644 index 0000000..ad4b18f --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/OnlineSubSystemHeader.h @@ -0,0 +1,27 @@ +#pragma once + +//#include "EngineMinimal.h" +//#include "Core.h" +//#include "OnlineSessionInterface.h" +//#include "OnlineSessionSettings.h" +//#include "OnlineDelegateMacros.h" +//#include "OnlineSubsystem.h" +//#include "OnlineSubsystemImpl.h" +//#include "OnlineSubsystemUtils.h" +//#include "OnlineSubsystemUtilsModule.h" +//#include "ModuleManager.h" +//#include "OnlineSubsystemUtilsClasses.h" +//#include "BlueprintDataDefinitions.h" + + +/*#include "VoiceEngineImpl.h" +#include "VoiceInterfaceImpl.h" +#include "Voice.h"" +*/ + +// Found this in the steam controller, seems like a nice thought since steam is throwing errors +// Disable crazy warnings that claim that standard C library is "deprecated". +//#ifdef _MSC_VER +//#pragma warning(push) +//#pragma warning(disable:4996) +//#endif diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/SendFriendInviteCallbackProxy.h b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/SendFriendInviteCallbackProxy.h new file mode 100644 index 0000000..e878f51 --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/SendFriendInviteCallbackProxy.h @@ -0,0 +1,49 @@ +// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. +#pragma once + +#include "CoreMinimal.h" +#include "BlueprintDataDefinitions.h" +#include "Engine/LocalPlayer.h" +#include "SendFriendInviteCallbackProxy.generated.h" + +DECLARE_LOG_CATEGORY_EXTERN(AdvancedSendFriendInviteLog, Log, All); + +DECLARE_DYNAMIC_MULTICAST_DELEGATE(FBlueprintSendFriendInviteDelegate); + +UCLASS(MinimalAPI) +class USendFriendInviteCallbackProxy : public UOnlineBlueprintCallProxyBase +{ + GENERATED_UCLASS_BODY() + + // Called when the friends list successfully was retrieved + UPROPERTY(BlueprintAssignable) + FBlueprintSendFriendInviteDelegate OnSuccess; + + // Called when there was an error retrieving the friends list + UPROPERTY(BlueprintAssignable) + FBlueprintSendFriendInviteDelegate OnFailure; + + // Adds a friend who is using the defined UniqueNetId, some interfaces do now allow this function to be called (INCLUDING STEAM) + UFUNCTION(BlueprintCallable, meta=(BlueprintInternalUseOnly = "true", WorldContext="WorldContextObject"), Category = "Online|AdvancedFriends") + static USendFriendInviteCallbackProxy* SendFriendInvite(UObject* WorldContextObject, APlayerController *PlayerController, const FBPUniqueNetId &UniqueNetIDInvited); + + virtual void Activate() override; + +private: + // Internal callback when the friends list is retrieved + void OnSendInviteComplete(int32 LocalPlayerNum, bool bWasSuccessful, const FUniqueNetId &InvitedPlayer, const FString &ListName, const FString &ErrorString); + + + // The player controller triggering things + TWeakObjectPtr PlayerControllerWeakPtr; + + // The UniqueNetID of the person to invite + FBPUniqueNetId cUniqueNetId; + + // The delegate to call on completion + FOnSendInviteComplete OnSendInviteCompleteDelegate; + + // The world context object in which this call is taking place + TWeakObjectPtr WorldContextObject; +}; + diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/StartSessionCallbackProxyAdvanced.h b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/StartSessionCallbackProxyAdvanced.h new file mode 100644 index 0000000..e82cce8 --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/StartSessionCallbackProxyAdvanced.h @@ -0,0 +1,46 @@ +#pragma once + +#include "CoreMinimal.h" +#include "BlueprintDataDefinitions.h" +#include "StartSessionCallbackProxyAdvanced.generated.h" + +UCLASS(MinimalAPI) +class UStartSessionCallbackProxyAdvanced : public UOnlineBlueprintCallProxyBase +{ + GENERATED_UCLASS_BODY() + // Called when the session starts successfully + UPROPERTY(BlueprintAssignable) + FEmptyOnlineDelegate OnSuccess; + + // Called when there is an error starting the session + UPROPERTY(BlueprintAssignable) + FEmptyOnlineDelegate OnFailure; + + /** + * Starts a session with the default online subsystem. The session needs to be previously created by calling the "CreateAdvancedSession" node. + * @param WorldContextObject + */ + UFUNCTION( + BlueprintCallable + , meta=(BlueprintInternalUseOnly = "true", WorldContext="WorldContextObject") + , Category = "Online|AdvancedSessions" + ) + static UStartSessionCallbackProxyAdvanced* StartAdvancedSession(UObject* WorldContextObject); + + // UOnlineBlueprintCallProxyBase interface + virtual void Activate() override; + // End of UOnlineBlueprintCallProxyBase interface + +private: + // Internal callback when session start completes + void OnStartCompleted(FName SessionName, bool bWasSuccessful); + + // The delegate executed by the online subsystem + FOnStartSessionCompleteDelegate StartCompleteDelegate; + + // Handles to the registered delegates above + FDelegateHandle StartCompleteDelegateHandle; + + // The world context object in which this call is taking place + TWeakObjectPtr WorldContextObject; +}; \ No newline at end of file diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/UpdateSessionCallbackProxyAdvanced.h b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/UpdateSessionCallbackProxyAdvanced.h new file mode 100644 index 0000000..afdc181 --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Classes/UpdateSessionCallbackProxyAdvanced.h @@ -0,0 +1,69 @@ +// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. +#pragma once + +#include "CoreMinimal.h" +#include "Engine/Engine.h" +#include "BlueprintDataDefinitions.h" +#include "UpdateSessionCallbackProxyAdvanced.generated.h" + +UCLASS(MinimalAPI) +class UUpdateSessionCallbackProxyAdvanced : public UOnlineBlueprintCallProxyBase +{ + GENERATED_UCLASS_BODY() + + // Called when the session was updated successfully + UPROPERTY(BlueprintAssignable) + FEmptyOnlineDelegate OnSuccess; + + // Called when there was an error updating the session + UPROPERTY(BlueprintAssignable) + FEmptyOnlineDelegate OnFailure; + + // Creates a session with the default online subsystem with advanced optional inputs, you MUST fill in all categories or it will pass in values that you didn't want as default values + UFUNCTION(BlueprintCallable, meta=(BlueprintInternalUseOnly = "true", WorldContext="WorldContextObject",AutoCreateRefTerm="ExtraSettings"), Category = "Online|AdvancedSessions") + static UUpdateSessionCallbackProxyAdvanced* UpdateSession(UObject* WorldContextObject, const TArray &ExtraSettings, int32 PublicConnections = 100, int32 PrivateConnections = 0, bool bUseLAN = false, bool bAllowInvites = false, bool bAllowJoinInProgress = false, bool bRefreshOnlineData = true, bool bIsDedicatedServer = false, bool bShouldAdvertise = true); + + // UOnlineBlueprintCallProxyBase interface + virtual void Activate() override; + // End of UOnlineBlueprintCallProxyBase interface + +private: + // Internal callback when session creation completes, calls StartSession + void OnUpdateCompleted(FName SessionName, bool bWasSuccessful); + + // The delegate executed by the online subsystem + FOnUpdateSessionCompleteDelegate OnUpdateSessionCompleteDelegate; + + // Handles to the registered delegates above + FDelegateHandle OnUpdateSessionCompleteDelegateHandle; + + // Number of public connections + int NumPublicConnections = 100; + + // Number of private connections + int NumPrivateConnections = 0; + + // Whether or not to search LAN + bool bUseLAN = false; + + // Whether or not to allow invites + bool bAllowInvites = true; + + // Store extra settings + TArray ExtraSettings; + + // Whether to update the online data + bool bRefreshOnlineData = true; + + // Allow joining in progress + bool bAllowJoinInProgress = true; + + // Update whether this is a dedicated server or not + bool bDedicatedServer = false; + + bool bShouldAdvertise = true; + + // The world context object in which this call is taking place + TWeakObjectPtr WorldContextObject; +}; + diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/AdvancedExternalUILibrary.cpp b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/AdvancedExternalUILibrary.cpp new file mode 100644 index 0000000..a1792a1 --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/AdvancedExternalUILibrary.cpp @@ -0,0 +1,209 @@ +// Fill out your copyright notice in the Description page of Project Settings. +#include "AdvancedExternalUILibrary.h" +#include "Engine/LocalPlayer.h" + + +//General Log +DEFINE_LOG_CATEGORY(AdvancedExternalUILog); + +void UAdvancedExternalUILibrary::ShowAccountUpgradeUI(UObject* WorldContextObject, const FBPUniqueNetId PlayerRequestingAccountUpgradeUI, EBlueprintResultSwitch &Result) +{ + + UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull); + if (!IsValid(World)) + { + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + IOnlineExternalUIPtr ExternalUIInterface = Online::GetExternalUIInterface(World); + + if (!ExternalUIInterface.IsValid()) + { + UE_LOG(AdvancedExternalUILog, Warning, TEXT("ShowAccountUpgradeUI Failed to get External UI interface!")); + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + ExternalUIInterface->ShowAccountUpgradeUI(*PlayerRequestingAccountUpgradeUI.GetUniqueNetId()); + Result = EBlueprintResultSwitch::OnSuccess; +} + +void UAdvancedExternalUILibrary::ShowProfileUI(UObject* WorldContextObject, const FBPUniqueNetId PlayerViewingProfile, const FBPUniqueNetId PlayerToViewProfileOf, EBlueprintResultSwitch &Result) +{ + + UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull); + if (!IsValid(World)) + { + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + IOnlineExternalUIPtr ExternalUIInterface = Online::GetExternalUIInterface(World); + + if (!ExternalUIInterface.IsValid()) + { + UE_LOG(AdvancedExternalUILog, Warning, TEXT("ShowProfileUI Failed to get External UI interface!")); + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + ExternalUIInterface->ShowProfileUI(*PlayerViewingProfile.GetUniqueNetId(), *PlayerToViewProfileOf.GetUniqueNetId(), NULL); + Result = EBlueprintResultSwitch::OnSuccess; +} + + + +void UAdvancedExternalUILibrary::ShowWebURLUI(UObject* WorldContextObject, FString URLToShow, EBlueprintResultSwitch &Result, TArray& AllowedDomains, bool bEmbedded, bool bShowBackground, bool bShowCloseButton, int32 OffsetX, int32 OffsetY, int32 SizeX, int32 SizeY) +{ + UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull); + if (!IsValid(World)) + { + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + IOnlineExternalUIPtr ExternalUIInterface = Online::GetExternalUIInterface(World); + + if (!ExternalUIInterface.IsValid()) + { + UE_LOG(AdvancedExternalUILog, Warning, TEXT("ShowWebURLUI Failed to get External UI interface!")); + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + URLToShow = URLToShow.Replace(TEXT("http://"), TEXT("")); + URLToShow = URLToShow.Replace(TEXT("https://"), TEXT("")); + + FShowWebUrlParams Params; + Params.AllowedDomains = AllowedDomains; + Params.bEmbedded = bEmbedded; + Params.bShowBackground = bShowBackground; + Params.bShowCloseButton = bShowCloseButton; + Params.OffsetX = OffsetX; + Params.OffsetY = OffsetY; + Params.SizeX = SizeX; + Params.SizeY = SizeY; + + ExternalUIInterface->ShowWebURL(URLToShow, Params); + Result = EBlueprintResultSwitch::OnSuccess; +} + +void UAdvancedExternalUILibrary::CloseWebURLUI(UObject* WorldContextObject) +{ + UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull); + if (!IsValid(World)) + { + return; + } + + IOnlineExternalUIPtr ExternalUIInterface = Online::GetExternalUIInterface(World); + + if (!ExternalUIInterface.IsValid()) + { + UE_LOG(AdvancedExternalUILog, Warning, TEXT("CloseWebURLUI Failed to get External UI interface!")); + return; + } + + ExternalUIInterface->CloseWebURL(); +} + +void UAdvancedExternalUILibrary::ShowLeaderBoardUI(UObject* WorldContextObject, FString LeaderboardName, EBlueprintResultSwitch &Result) +{ + UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull); + if (!IsValid(World)) + { + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + IOnlineExternalUIPtr ExternalUIInterface = Online::GetExternalUIInterface(World); + + if (!ExternalUIInterface.IsValid()) + { + UE_LOG(AdvancedExternalUILog, Warning, TEXT("ShowLeaderboardsUI Failed to get External UI interface!")); + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + ExternalUIInterface->ShowLeaderboardUI(LeaderboardName); + Result = EBlueprintResultSwitch::OnSuccess; + +} + + +void UAdvancedExternalUILibrary::ShowInviteUI(UObject* WorldContextObject, APlayerController *PlayerController, EBlueprintResultSwitch &Result) +{ + if (!PlayerController) + { + UE_LOG(AdvancedExternalUILog, Warning, TEXT("ShowInviteUI Had a bad Player Controller!")); + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull); + if (!IsValid(World)) + { + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + IOnlineExternalUIPtr ExternalUIInterface = Online::GetExternalUIInterface(World); + + if (!ExternalUIInterface.IsValid()) + { + UE_LOG(AdvancedExternalUILog, Warning, TEXT("ShowInviteUI Failed to get External UI interface!")); + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + ULocalPlayer* Player = Cast(PlayerController->Player); + + if (!Player) + { + UE_LOG(AdvancedExternalUILog, Warning, TEXT("ShowInviteUI Failed to get ULocalPlayer for the given PlayerController!")); + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + ExternalUIInterface->ShowInviteUI(Player->GetControllerId(), NAME_GameSession); + Result = EBlueprintResultSwitch::OnSuccess; +} + +void UAdvancedExternalUILibrary::ShowFriendsUI(UObject* WorldContextObject, APlayerController *PlayerController, EBlueprintResultSwitch &Result) +{ + if (!PlayerController) + { + UE_LOG(AdvancedExternalUILog, Warning, TEXT("ShowFriendsUI Had a bad Player Controller!")); + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull); + if (!IsValid(World)) + { + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + IOnlineExternalUIPtr ExternalUIInterface = Online::GetExternalUIInterface(World); + + if (!ExternalUIInterface.IsValid()) + { + UE_LOG(AdvancedExternalUILog, Warning, TEXT("ShowFriendsUI Failed to get External UI interface!")); + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + ULocalPlayer* Player = Cast(PlayerController->Player); + + if (!Player) + { + UE_LOG(AdvancedExternalUILog, Warning, TEXT("ShowFriendsUI Failed to get ULocalPlayer for the given PlayerController!")); + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + ExternalUIInterface->ShowFriendsUI(Player->GetControllerId()); + Result = EBlueprintResultSwitch::OnSuccess; +} \ No newline at end of file diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/AdvancedFriendsGameInstance.cpp b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/AdvancedFriendsGameInstance.cpp new file mode 100644 index 0000000..47afb6a --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/AdvancedFriendsGameInstance.cpp @@ -0,0 +1,334 @@ +// Fill out your copyright notice in the Description page of Project Settings. +#include "AdvancedFriendsGameInstance.h" +#include "Kismet/GameplayStatics.h" +#include "GameFramework/PlayerController.h" + +//General Log +DEFINE_LOG_CATEGORY(AdvancedFriendsInterfaceLog); + +UAdvancedFriendsGameInstance::UAdvancedFriendsGameInstance(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) + , bCallFriendInterfaceEventsOnPlayerControllers(true) + , bCallIdentityInterfaceEventsOnPlayerControllers(true) + , bCallVoiceInterfaceEventsOnPlayerControllers(true) + , bEnableTalkingStatusDelegate(true) + , SessionInviteReceivedDelegate(FOnSessionInviteReceivedDelegate::CreateUObject(this, &ThisClass::OnSessionInviteReceivedMaster)) + , SessionInviteAcceptedDelegate(FOnSessionUserInviteAcceptedDelegate::CreateUObject(this, &ThisClass::OnSessionInviteAcceptedMaster)) + , PlayerTalkingStateChangedDelegate(FOnPlayerTalkingStateChangedDelegate::CreateUObject(this, &ThisClass::OnPlayerTalkingStateChangedMaster)) + , PlayerLoginChangedDelegate(FOnLoginChangedDelegate::CreateUObject(this, &ThisClass::OnPlayerLoginChangedMaster)) + , PlayerLoginStatusChangedDelegate(FOnLoginStatusChangedDelegate::CreateUObject(this, &ThisClass::OnPlayerLoginStatusChangedMaster)) +{ +} + +void UAdvancedFriendsGameInstance::Shutdown() +{ + IOnlineSessionPtr SessionInterface = Online::GetSessionInterface(GetWorld()); + + if (!SessionInterface.IsValid()) + { + UE_LOG(AdvancedFriendsInterfaceLog, Warning, TEXT("UAdvancedFriendsGameInstance Failed to get session system!")); + //return; + } + else + { + // Clear all of the delegate handles here + SessionInterface->ClearOnSessionUserInviteAcceptedDelegate_Handle(SessionInviteAcceptedDelegateHandle); + SessionInterface->ClearOnSessionInviteReceivedDelegate_Handle(SessionInviteReceivedDelegateHandle); + } + + + if (bEnableTalkingStatusDelegate) + { + IOnlineVoicePtr VoiceInterface = Online::GetVoiceInterface(GetWorld()); + + if (VoiceInterface.IsValid()) + { + VoiceInterface->ClearOnPlayerTalkingStateChangedDelegate_Handle(PlayerTalkingStateChangedDelegateHandle); + } + else + { + + UE_LOG(AdvancedFriendsInterfaceLog, Warning, TEXT("UAdvancedFriendsInstance Failed to get voice interface!")); + } + } + + IOnlineIdentityPtr IdentityInterface = Online::GetIdentityInterface(GetWorld()); + + if (IdentityInterface.IsValid()) + { + IdentityInterface->ClearOnLoginChangedDelegate_Handle(PlayerLoginChangedDelegateHandle); + + + // I am just defaulting to player 1 + IdentityInterface->ClearOnLoginStatusChangedDelegate_Handle(0, PlayerLoginStatusChangedDelegateHandle); + } + + + Super::Shutdown(); +} + +void UAdvancedFriendsGameInstance::Init() +{ + IOnlineSessionPtr SessionInterface = Online::GetSessionInterface(GetWorld());//OnlineSub->GetSessionInterface(); + + if (SessionInterface.IsValid()) + { + // Currently doesn't store a handle or assign a delegate to any local player beyond the first.....should handle? + // Thought about directly handling it but friends for multiple players probably isn't required + // Iterating through the local player TArray only works if it has had players assigned to it, most of the online interfaces don't support + // Multiple logins either (IE: Steam) + SessionInviteAcceptedDelegateHandle = SessionInterface->AddOnSessionUserInviteAcceptedDelegate_Handle(SessionInviteAcceptedDelegate); + + SessionInviteReceivedDelegateHandle = SessionInterface->AddOnSessionInviteReceivedDelegate_Handle(SessionInviteReceivedDelegate); + } + else + { + UE_LOG(AdvancedFriendsInterfaceLog, Warning, TEXT("UAdvancedFriendsInstance Failed to get session interface!")); + //return; + } + + // Beginning work on the voice interface + if (bEnableTalkingStatusDelegate) + { + IOnlineVoicePtr VoiceInterface = Online::GetVoiceInterface(GetWorld()); + + if (VoiceInterface.IsValid()) + { + PlayerTalkingStateChangedDelegateHandle = VoiceInterface->AddOnPlayerTalkingStateChangedDelegate_Handle(PlayerTalkingStateChangedDelegate); + } + else + { + + UE_LOG(AdvancedFriendsInterfaceLog, Warning, TEXT("UAdvancedFriendsInstance Failed to get voice interface!")); + } + } + + IOnlineIdentityPtr IdentityInterface = Online::GetIdentityInterface(GetWorld()); + + if (IdentityInterface.IsValid()) + { + PlayerLoginChangedDelegateHandle = IdentityInterface->AddOnLoginChangedDelegate_Handle(PlayerLoginChangedDelegate); + + // Just defaulting to player 1 + PlayerLoginStatusChangedDelegateHandle = IdentityInterface->AddOnLoginStatusChangedDelegate_Handle(0, PlayerLoginStatusChangedDelegate); + } + else + { + UE_LOG(AdvancedFriendsInterfaceLog, Warning, TEXT("UAdvancedFriendsInstance Failed to get identity interface!")); + } + + + Super::Init(); +} + +/*void UAdvancedFriendsGameInstance::PostLoad() +{ + Super::PostLoad(); +}*/ + + +// Removed because it never gets called by the online subsystems +/*void UAdvancedFriendsGameInstance::OnSessionInviteReceivedMaster(const FUniqueNetId &InvitedPlayer, const FUniqueNetId &FriendInviting, const FOnlineSessionSearchResult& Session) +{ + // Just call the blueprint event to let the user handle this + + FBPUniqueNetId IP, FI; + + IP.SetUniqueNetId(&InvitedPlayer); + + FI.SetUniqueNetId(&FriendInviting); + + FBlueprintSessionResult BPS; + BPS.OnlineResult = Session; + OnSessionInviteReceived(IP,FI,BPS); + + TArray& PlayerArray = GetWorld()->GetGameState()->PlayerArray; + const TArray&ControllerArray = this->GetLocalPlayers(); + + for (int i = 0; i < ControllerArray.Num(); i++) + { + if (*PlayerArray[ControllerArray[i]->PlayerController->NetPlayerIndex]->UniqueId.GetUniqueNetId().Get() == InvitedPlayer) + { + //Run the Event specific to the actor, if the actor has the interface, otherwise ignore + if (ControllerArray[i]->PlayerController->GetClass()->ImplementsInterface(UAdvancedFriendsInterface::StaticClass())) + { + IAdvancedFriendsInterface::Execute_OnSessionInviteReceived(ControllerArray[i]->PlayerController, FI, BPS); + } + break; + } + } +}*/ + +void UAdvancedFriendsGameInstance::OnPlayerLoginStatusChangedMaster(int32 PlayerNum, ELoginStatus::Type PreviousStatus, ELoginStatus::Type NewStatus, const FUniqueNetId & NewPlayerUniqueNetID) +{ + EBPLoginStatus OrigStatus = (EBPLoginStatus)PreviousStatus; + EBPLoginStatus CurrentStatus = (EBPLoginStatus)NewStatus; + FBPUniqueNetId PlayerID; + PlayerID.SetUniqueNetId(&NewPlayerUniqueNetID); + + OnPlayerLoginStatusChanged(PlayerNum, OrigStatus,CurrentStatus,PlayerID); + + + if (bCallIdentityInterfaceEventsOnPlayerControllers) + { + APlayerController* Player = UGameplayStatics::GetPlayerController(GetWorld(), PlayerNum); + + if (Player != NULL) + { + //Run the Event specific to the actor, if the actor has the interface, otherwise ignore + if (Player->GetClass()->ImplementsInterface(UAdvancedFriendsInterface::StaticClass())) + { + IAdvancedFriendsInterface::Execute_OnPlayerLoginStatusChanged(Player, OrigStatus, CurrentStatus, PlayerID); + } + } + else + { + UE_LOG(AdvancedFriendsInterfaceLog, Warning, TEXT("UAdvancedFriendsInstance Failed to get a controller with the specified index in OnPlayerLoginStatusChangedMaster!")); + } + } +} + +void UAdvancedFriendsGameInstance::OnPlayerLoginChangedMaster(int32 PlayerNum) +{ + OnPlayerLoginChanged(PlayerNum); + + if (bCallIdentityInterfaceEventsOnPlayerControllers) + { + APlayerController* Player = UGameplayStatics::GetPlayerController(GetWorld(), PlayerNum); + + if (Player != NULL) + { + //Run the Event specific to the actor, if the actor has the interface, otherwise ignore + if (Player->GetClass()->ImplementsInterface(UAdvancedFriendsInterface::StaticClass())) + { + IAdvancedFriendsInterface::Execute_OnPlayerLoginChanged(Player, PlayerNum); + } + } + else + { + UE_LOG(AdvancedFriendsInterfaceLog, Warning, TEXT("UAdvancedFriendsInstance Failed to get a controller with the specified index in OnPlayerLoginChanged!")); + } + } +} + +void UAdvancedFriendsGameInstance::OnPlayerTalkingStateChangedMaster(TSharedRef PlayerId, bool bIsTalking) +{ + FBPUniqueNetId PlayerTalking; + PlayerTalking.SetUniqueNetId(PlayerId); + OnPlayerTalkingStateChanged(PlayerTalking, bIsTalking); + + if (bCallVoiceInterfaceEventsOnPlayerControllers) + { + APlayerController* Player = NULL; + + for (const ULocalPlayer* LPlayer : LocalPlayers) + { + Player = UGameplayStatics::GetPlayerController(GetWorld(), LPlayer->GetControllerId()); + + if (Player != NULL) + { + //Run the Event specific to the actor, if the actor has the interface, otherwise ignore + if (Player->GetClass()->ImplementsInterface(UAdvancedFriendsInterface::StaticClass())) + { + IAdvancedFriendsInterface::Execute_OnPlayerVoiceStateChanged(Player, PlayerTalking, bIsTalking); + } + } + else + { + UE_LOG(AdvancedFriendsInterfaceLog, Warning, TEXT("UAdvancedFriendsInstance Failed to get a controller with the specified index in OnVoiceStateChanged!")); + } + } + } +} + +void UAdvancedFriendsGameInstance::OnSessionInviteReceivedMaster(const FUniqueNetId & PersonInvited, const FUniqueNetId & PersonInviting, const FString& AppId, const FOnlineSessionSearchResult& SessionToJoin) +{ + if (SessionToJoin.IsValid()) + { + FBlueprintSessionResult BluePrintResult; + BluePrintResult.OnlineResult = SessionToJoin; + + FBPUniqueNetId PInvited; + PInvited.SetUniqueNetId(&PersonInvited); + + FBPUniqueNetId PInviting; + PInviting.SetUniqueNetId(&PersonInviting); + + + TArray PlayerList; + GEngine->GetAllLocalPlayerControllers(PlayerList); + + APlayerController* Player = NULL; + + int32 LocalPlayer = 0; + for (int i = 0; i < PlayerList.Num(); i++) + { + if (*PlayerList[i]->PlayerState->GetUniqueId().GetUniqueNetId() == PersonInvited) + { + LocalPlayer = i; + Player = PlayerList[i]; + break; + } + } + + OnSessionInviteReceived(LocalPlayer, PInviting, AppId, BluePrintResult); + + //IAdvancedFriendsInterface* TheInterface = NULL; + + if (Player != NULL) + { + //Run the Event specific to the actor, if the actor has the interface, otherwise ignore + if (Player->GetClass()->ImplementsInterface(UAdvancedFriendsInterface::StaticClass())) + { + IAdvancedFriendsInterface::Execute_OnSessionInviteReceived(Player, PInviting, BluePrintResult); + } + } + else + { + UE_LOG(AdvancedFriendsInterfaceLog, Warning, TEXT("UAdvancedFriendsInstance Failed to get a controller with the specified index in OnSessionInviteReceived!")); + } + } + else + { + UE_LOG(AdvancedFriendsInterfaceLog, Warning, TEXT("UAdvancedFriendsInstance Return a bad search result in OnSessionInviteReceived!")); + } +} + +void UAdvancedFriendsGameInstance::OnSessionInviteAcceptedMaster(const bool bWasSuccessful, int32 LocalPlayer, TSharedPtr PersonInvited, const FOnlineSessionSearchResult& SessionToJoin) +{ + if (bWasSuccessful) + { + if (SessionToJoin.IsValid()) + { + + FBlueprintSessionResult BluePrintResult; + BluePrintResult.OnlineResult = SessionToJoin; + + FBPUniqueNetId PInvited; + PInvited.SetUniqueNetId(PersonInvited); + + OnSessionInviteAccepted(LocalPlayer,PInvited, BluePrintResult); + + APlayerController* Player = UGameplayStatics::GetPlayerController(GetWorld(), LocalPlayer); + + //IAdvancedFriendsInterface* TheInterface = NULL; + + if (Player != NULL) + { + //Run the Event specific to the actor, if the actor has the interface, otherwise ignore + if (Player->GetClass()->ImplementsInterface(UAdvancedFriendsInterface::StaticClass())) + { + IAdvancedFriendsInterface::Execute_OnSessionInviteAccepted(Player,PInvited, BluePrintResult); + } + } + else + { + UE_LOG(AdvancedFriendsInterfaceLog, Warning, TEXT("UAdvancedFriendsInstance Failed to get a controller with the specified index in OnSessionInviteAccepted!")); + } + } + else + { + UE_LOG(AdvancedFriendsInterfaceLog, Warning, TEXT("UAdvancedFriendsInstance Return a bad search result in OnSessionInviteAccepted!")); + } + } +} \ No newline at end of file diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/AdvancedFriendsInterface.cpp b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/AdvancedFriendsInterface.cpp new file mode 100644 index 0000000..92e5138 --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/AdvancedFriendsInterface.cpp @@ -0,0 +1,9 @@ +// Fill out your copyright notice in the Description page of Project Settings. +#include "AdvancedFriendsInterface.h" + + + +UAdvancedFriendsInterface::UAdvancedFriendsInterface(const class FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ +} diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/AdvancedFriendsLibrary.cpp b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/AdvancedFriendsLibrary.cpp new file mode 100644 index 0000000..5df1a94 --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/AdvancedFriendsLibrary.cpp @@ -0,0 +1,281 @@ +// Fill out your copyright notice in the Description page of Project Settings. +#include "AdvancedFriendsLibrary.h" + + + +// This is taken directly from UE4 - OnlineSubsystemSteamPrivatePCH.h as a fix for the array_count macro + +//General Log +DEFINE_LOG_CATEGORY(AdvancedFriendsLog); + +void UAdvancedFriendsLibrary::SendSessionInviteToFriends(APlayerController *PlayerController, const TArray &Friends, EBlueprintResultSwitch &Result) +{ + if (!PlayerController) + { + UE_LOG(AdvancedFriendsLog, Warning, TEXT("SendSessionInviteToFriend Had a bad Player Controller!")); + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + if (Friends.Num() < 1) + { + UE_LOG(AdvancedFriendsLog, Warning, TEXT("SendSessionInviteToFriend Had no friends in invitation array!")); + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + IOnlineSessionPtr SessionInterface = Online::GetSessionInterface(); + + if (!SessionInterface.IsValid()) + { + UE_LOG(AdvancedFriendsLog, Warning, TEXT("SendSessionInviteToFriend Failed to get session interface!")); + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + ULocalPlayer* Player = Cast(PlayerController->Player); + + if (!Player) + { + UE_LOG(AdvancedFriendsLog, Warning, TEXT("SendSessionInviteToFriend failed to get LocalPlayer!")); + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + TArray> List; + for (int i = 0; i < Friends.Num(); i++) + { + TSharedRef val(Friends[i].UniqueNetId.ToSharedRef()); + //TSharedRef val(Friends[i].GetUniqueNetId()); + List.Add(val); + } + + if (SessionInterface->SendSessionInviteToFriends(Player->GetControllerId(), NAME_GameSession, List)) + { + Result = EBlueprintResultSwitch::OnSuccess; + return; + } + + Result = EBlueprintResultSwitch::OnFailure; + return; +} + +void UAdvancedFriendsLibrary::SendSessionInviteToFriend(APlayerController *PlayerController, const FBPUniqueNetId &FriendUniqueNetId, EBlueprintResultSwitch &Result) +{ + if (!PlayerController) + { + UE_LOG(AdvancedFriendsLog, Warning, TEXT("SendSessionInviteToFriend Had a bad Player Controller!")); + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + if (!FriendUniqueNetId.IsValid()) + { + UE_LOG(AdvancedFriendsLog, Warning, TEXT("SendSessionInviteToFriend Had a bad UniqueNetId!")); + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + IOnlineSessionPtr SessionInterface = Online::GetSessionInterface(); + + if (!SessionInterface.IsValid()) + { + UE_LOG(AdvancedFriendsLog, Warning, TEXT("SendSessionInviteToFriend Failed to get session interface!")); + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + ULocalPlayer* Player = Cast(PlayerController->Player); + + if (!Player) + { + UE_LOG(AdvancedFriendsLog, Warning, TEXT("SendSessionInviteToFriend failed to get LocalPlayer!")); + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + if (SessionInterface->SendSessionInviteToFriend(Player->GetControllerId(), NAME_GameSession, *FriendUniqueNetId.GetUniqueNetId())) + { + Result = EBlueprintResultSwitch::OnSuccess; + return; + } + + Result = EBlueprintResultSwitch::OnFailure; + return; +} + +void UAdvancedFriendsLibrary::GetFriend(APlayerController *PlayerController, const FBPUniqueNetId FriendUniqueNetId, FBPFriendInfo &Friend) +{ + + if (!PlayerController) + { + UE_LOG(AdvancedFriendsLog, Warning, TEXT("GetFriend Had a bad Player Controller!")); + return; + } + + if (!FriendUniqueNetId.IsValid()) + { + UE_LOG(AdvancedFriendsLog, Warning, TEXT("GetFriend Had a bad UniqueNetId!")); + return; + } + + IOnlineFriendsPtr FriendsInterface = Online::GetFriendsInterface(); + + if (!FriendsInterface.IsValid()) + { + UE_LOG(AdvancedFriendsLog, Warning, TEXT("GetFriend Failed to get friends interface!")); + return; + } + + ULocalPlayer* Player = Cast(PlayerController->Player); + + if (!Player) + { + UE_LOG(AdvancedFriendsLog, Warning, TEXT("GetFriend failed to get LocalPlayer!")); + return; + } + + TSharedPtr fr = FriendsInterface->GetFriend(Player->GetControllerId(), *FriendUniqueNetId.GetUniqueNetId(), EFriendsLists::ToString(EFriendsLists::Default)); + if (fr.IsValid()) + { + const FOnlineUserPresence& pres = fr->GetPresence(); + Friend.DisplayName = fr->GetDisplayName(); + Friend.OnlineState = ((EBPOnlinePresenceState)((int32)pres.Status.State)); + Friend.RealName = fr->GetRealName(); + Friend.UniqueNetId.SetUniqueNetId(fr->GetUserId()); + Friend.bIsPlayingSameGame = pres.bIsPlayingThisGame; + + Friend.PresenceInfo.bHasVoiceSupport = pres.bHasVoiceSupport; + Friend.PresenceInfo.bIsJoinable = pres.bIsJoinable; + Friend.PresenceInfo.bIsOnline = pres.bIsOnline; + Friend.PresenceInfo.bIsPlaying = pres.bIsPlaying; + Friend.PresenceInfo.bIsPlayingThisGame = pres.bIsPlayingThisGame; + Friend.PresenceInfo.PresenceState = ((EBPOnlinePresenceState)((int32)pres.Status.State)); + // #TODO: Check back in on this in shipping, epic is missing the UTF8_TO_TCHAR call on converting this and its making an invalid string + //Friend.PresenceInfo.StatusString = pres.Status.StatusStr; + } +} + +void UAdvancedFriendsLibrary::IsAFriend(APlayerController *PlayerController, const FBPUniqueNetId UniqueNetId, bool &IsFriend) +{ + if (!PlayerController) + { + UE_LOG(AdvancedFriendsLog, Warning, TEXT("IsAFriend Had a bad Player Controller!")); + return; + } + + if (!UniqueNetId.IsValid()) + { + UE_LOG(AdvancedFriendsLog, Warning, TEXT("IsAFriend Had a bad UniqueNetId!")); + return; + } + + IOnlineFriendsPtr FriendsInterface = Online::GetFriendsInterface(); + + if (!FriendsInterface.IsValid()) + { + UE_LOG(AdvancedFriendsLog, Warning, TEXT("IsAFriend Failed to get friends interface!")); + return; + } + + ULocalPlayer* Player = Cast(PlayerController->Player); + + if (!Player) + { + UE_LOG(AdvancedFriendsLog, Warning, TEXT("IsAFriend Failed to get LocalPlayer!")); + return; + } + + IsFriend = FriendsInterface->IsFriend(Player->GetControllerId(), *UniqueNetId.GetUniqueNetId(), EFriendsLists::ToString(EFriendsLists::Default)); +} + +void UAdvancedFriendsLibrary::GetStoredRecentPlayersList(FBPUniqueNetId UniqueNetId, TArray &PlayersList) +{ + IOnlineFriendsPtr FriendsInterface = Online::GetFriendsInterface(); + + if (!FriendsInterface.IsValid()) + { + UE_LOG(AdvancedFriendsLog, Warning, TEXT("GetRecentPlayersList Failed to get friends interface!")); + return; + } + + if (!UniqueNetId.IsValid()) + { + UE_LOG(AdvancedFriendsLog, Warning, TEXT("GetRecentPlayersList Failed was given an invalid UniqueNetId!")); + return; + } + + TArray< TSharedRef > PlayerList; + + // For now getting all namespaces + FriendsInterface->GetRecentPlayers(*(UniqueNetId.GetUniqueNetId()),"", PlayerList); + + for (int32 i = 0; i < PlayerList.Num(); i++) + { + TSharedRef Player = PlayerList[i]; + FBPOnlineRecentPlayer BPF; + BPF.DisplayName = Player->GetDisplayName(); + BPF.RealName = Player->GetRealName(); + BPF.UniqueNetId.SetUniqueNetId(Player->GetUserId()); + PlayersList.Add(BPF); + } +} + +void UAdvancedFriendsLibrary::GetStoredFriendsList(APlayerController *PlayerController, TArray &FriendsList) +{ + + if (!PlayerController) + { + UE_LOG(AdvancedFriendsLog, Warning, TEXT("GetFriendsList Had a bad Player Controller!")); + return; + } + + IOnlineFriendsPtr FriendsInterface = Online::GetFriendsInterface(); + + if (!FriendsInterface.IsValid()) + { + UE_LOG(AdvancedFriendsLog, Warning, TEXT("GetFriendsList Failed to get friends interface!")); + return; + } + + ULocalPlayer* Player = Cast(PlayerController->Player); + + if (!Player) + { + UE_LOG(AdvancedFriendsLog, Warning, TEXT("GetFriendsList Failed to get LocalPlayer!")); + return; + } + + + TArray< TSharedRef > FriendList; + if (FriendsInterface->GetFriendsList(Player->GetControllerId(), EFriendsLists::ToString((EFriendsLists::Default)), FriendList)) + { + for (int32 i = 0; i < FriendList.Num(); i++) + { + FBPFriendInfo BPF; + const FOnlineUserPresence& pres = FriendList[i]->GetPresence(); + + BPF.OnlineState = ((EBPOnlinePresenceState)((int32)pres.Status.State)); + BPF.DisplayName = FriendList[i]->GetDisplayName(); + BPF.RealName = FriendList[i]->GetRealName(); + BPF.UniqueNetId.SetUniqueNetId(FriendList[i]->GetUserId()); + BPF.bIsPlayingSameGame = pres.bIsPlayingThisGame; + + BPF.PresenceInfo.bIsOnline = pres.bIsOnline; + BPF.PresenceInfo.bHasVoiceSupport = pres.bHasVoiceSupport; + BPF.PresenceInfo.bIsPlaying = pres.bIsPlaying; + BPF.PresenceInfo.PresenceState = ((EBPOnlinePresenceState)((int32)pres.Status.State)); + // #TODO: Check back in on this in shipping, epic is missing the UTF8_TO_TCHAR call on converting this and its making an invalid string + //BPF.PresenceInfo.StatusString = pres.Status.StatusStr; + BPF.PresenceInfo.bIsJoinable = pres.bIsJoinable; + BPF.PresenceInfo.bIsPlayingThisGame = pres.bIsPlayingThisGame; + + FriendsList.Add(BPF); + } + + return; + } + + UE_LOG(AdvancedFriendsLog, Warning, TEXT("GetFriendsList Failed to get any friends!")); + return; +} \ No newline at end of file diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/AdvancedIdentityLibrary.cpp b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/AdvancedIdentityLibrary.cpp new file mode 100644 index 0000000..47a554b --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/AdvancedIdentityLibrary.cpp @@ -0,0 +1,271 @@ +// Fill out your copyright notice in the Description page of Project Settings. +#include "AdvancedIdentityLibrary.h" + +//General Log +DEFINE_LOG_CATEGORY(AdvancedIdentityLog); + + +void UAdvancedIdentityLibrary::GetPlayerAuthToken(UObject* WorldContextObject, APlayerController * PlayerController, FString & AuthToken, EBlueprintResultSwitch &Result) +{ + if (!PlayerController) + { + UE_LOG(AdvancedIdentityLog, Warning, TEXT("GetPlayerAuthToken was passed a bad player controller!")); + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + ULocalPlayer* Player = Cast(PlayerController->Player); + + if (!Player) + { + UE_LOG(AdvancedIdentityLog, Warning, TEXT("GetPlayerAuthToken failed to get LocalPlayer!")); + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull); + if (!IsValid(World)) + { + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + IOnlineIdentityPtr IdentityInterface = Online::GetIdentityInterface(World); + + if (!IdentityInterface.IsValid()) + { + UE_LOG(AdvancedIdentityLog, Warning, TEXT("GetPlayerAuthToken Failed to get identity interface!")); + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + AuthToken = IdentityInterface->GetAuthToken(Player->GetControllerId()); + Result = EBlueprintResultSwitch::OnSuccess; +} + +void UAdvancedIdentityLibrary::GetPlayerNickname(UObject* WorldContextObject, const FBPUniqueNetId & UniqueNetID, FString & PlayerNickname) +{ + if (!UniqueNetID.IsValid()) + { + UE_LOG(AdvancedIdentityLog, Warning, TEXT("GetPlayerNickname was passed a bad player uniquenetid!")); + return; + } + + UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull); + if (!IsValid(World)) + { + return; + } + + IOnlineIdentityPtr IdentityInterface = Online::GetIdentityInterface(World); + + if (!IdentityInterface.IsValid()) + { + UE_LOG(AdvancedIdentityLog, Warning, TEXT("GetPlayerNickname Failed to get identity interface!")); + return; + } + PlayerNickname = IdentityInterface->GetPlayerNickname(*UniqueNetID.GetUniqueNetId()); +} + + +void UAdvancedIdentityLibrary::GetLoginStatus(UObject* WorldContextObject, const FBPUniqueNetId & UniqueNetID, EBPLoginStatus & LoginStatus, EBlueprintResultSwitch &Result) +{ + if (!UniqueNetID.IsValid()) + { + UE_LOG(AdvancedIdentityLog, Warning, TEXT("GetLoginStatus was passed a bad player uniquenetid!")); + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull); + if (!IsValid(World)) + { + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + IOnlineIdentityPtr IdentityInterface = Online::GetIdentityInterface(World); + + if (!IdentityInterface.IsValid()) + { + UE_LOG(AdvancedIdentityLog, Warning, TEXT("GetLoginStatus Failed to get identity interface!")); + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + LoginStatus = (EBPLoginStatus)IdentityInterface->GetLoginStatus(*UniqueNetID.GetUniqueNetId()); + Result = EBlueprintResultSwitch::OnSuccess; +} + + +void UAdvancedIdentityLibrary::GetAllUserAccounts(UObject* WorldContextObject, TArray & AccountInfos, EBlueprintResultSwitch &Result) +{ + + UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull); + if (!IsValid(World)) + { + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + IOnlineIdentityPtr IdentityInterface = Online::GetIdentityInterface(World); + + if (!IdentityInterface.IsValid()) + { + UE_LOG(AdvancedIdentityLog, Warning, TEXT("GetAllUserAccounts Failed to get identity interface!")); + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + TArray> accountInfos = IdentityInterface->GetAllUserAccounts(); + + for (int i = 0; i < accountInfos.Num(); ++i) + { + AccountInfos.Add(FBPUserOnlineAccount(accountInfos[i])); + } + + Result = EBlueprintResultSwitch::OnSuccess; +} + +void UAdvancedIdentityLibrary::GetUserAccount(UObject* WorldContextObject, const FBPUniqueNetId & UniqueNetId, FBPUserOnlineAccount & AccountInfo, EBlueprintResultSwitch &Result) +{ + + UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull); + if (!IsValid(World)) + { + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + IOnlineIdentityPtr IdentityInterface = Online::GetIdentityInterface(World); + + if(!UniqueNetId.IsValid()) + { + UE_LOG(AdvancedIdentityLog, Warning, TEXT("GetUserAccount was passed a bad unique net id!")); + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + if (!IdentityInterface.IsValid()) + { + UE_LOG(AdvancedIdentityLog, Warning, TEXT("GetUserAccount Failed to get identity interface!")); + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + TSharedPtr accountInfo = IdentityInterface->GetUserAccount(*UniqueNetId.GetUniqueNetId()); + + if (!accountInfo.IsValid()) + { + UE_LOG(AdvancedIdentityLog, Warning, TEXT("GetUserAccount Failed to get the account!")); + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + AccountInfo.UserAccountInfo = accountInfo; + Result = EBlueprintResultSwitch::OnSuccess; +} + +void UAdvancedIdentityLibrary::GetUserAccountAccessToken(const FBPUserOnlineAccount & AccountInfo, FString & AccessToken) +{ + if (!AccountInfo.UserAccountInfo.IsValid()) + { + UE_LOG(AdvancedIdentityLog, Warning, TEXT("GetUserAccountAccessToken was passed an invalid account!")); + return; + } + + AccessToken = AccountInfo.UserAccountInfo->GetAccessToken(); +} + +void UAdvancedIdentityLibrary::GetUserAccountAuthAttribute(const FBPUserOnlineAccount & AccountInfo, const FString & AttributeName, FString & AuthAttribute, EBlueprintResultSwitch &Result) +{ + if (!AccountInfo.UserAccountInfo.IsValid()) + { + UE_LOG(AdvancedIdentityLog, Warning, TEXT("GetUserAccountAuthAttribute was passed an invalid account!")); + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + if (!AccountInfo.UserAccountInfo->GetAuthAttribute(AttributeName, AuthAttribute)) + { + UE_LOG(AdvancedIdentityLog, Warning, TEXT("GetUserAccountAuthAttribute couldn't find the attribute!")); + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + Result = EBlueprintResultSwitch::OnSuccess; +} + +void UAdvancedIdentityLibrary::SetUserAccountAttribute(const FBPUserOnlineAccount & AccountInfo, const FString & AttributeName, const FString & NewAttributeValue, EBlueprintResultSwitch &Result) +{ + if (!AccountInfo.UserAccountInfo.IsValid()) + { + UE_LOG(AdvancedIdentityLog, Warning, TEXT("SetUserAccountAuthAttribute was passed an invalid account!")); + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + if (!AccountInfo.UserAccountInfo->SetUserAttribute(AttributeName, NewAttributeValue)) + { + UE_LOG(AdvancedIdentityLog, Warning, TEXT("SetUserAccountAuthAttribute was unable to set the attribute!")); + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + Result = EBlueprintResultSwitch::OnSuccess; +} + +void UAdvancedIdentityLibrary::GetUserID(const FBPUserOnlineAccount & AccountInfo, FBPUniqueNetId & UniqueNetID) +{ + if (!AccountInfo.UserAccountInfo.IsValid()) + { + UE_LOG(AdvancedIdentityLog, Warning, TEXT("GetUserID was passed an invalid account!")); + return; + } + + + UniqueNetID.SetUniqueNetId(AccountInfo.UserAccountInfo->GetUserId()); +} + +void UAdvancedIdentityLibrary::GetUserAccountRealName(const FBPUserOnlineAccount & AccountInfo, FString & UserName) +{ + if (!AccountInfo.UserAccountInfo.IsValid()) + { + UE_LOG(AdvancedIdentityLog, Warning, TEXT("GetUserAccountRealName was passed an invalid account!")); + return; + } + + + UserName = AccountInfo.UserAccountInfo->GetRealName(); +} + +void UAdvancedIdentityLibrary::GetUserAccountDisplayName(const FBPUserOnlineAccount & AccountInfo, FString & DisplayName) +{ + if (!AccountInfo.UserAccountInfo.IsValid()) + { + UE_LOG(AdvancedIdentityLog, Warning, TEXT("GetUserAccountDisplayName was passed an invalid account!")); + return; + } + + + DisplayName = AccountInfo.UserAccountInfo->GetDisplayName(); +} + +void UAdvancedIdentityLibrary::GetUserAccountAttribute(const FBPUserOnlineAccount & AccountInfo, const FString & AttributeName, FString & AttributeValue, EBlueprintResultSwitch &Result) +{ + if (!AccountInfo.UserAccountInfo.IsValid()) + { + UE_LOG(AdvancedIdentityLog, Warning, TEXT("GetUserAccountAttribute was passed an invalid account!")); + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + if (!AccountInfo.UserAccountInfo->GetUserAttribute(AttributeName, AttributeValue)) + { + UE_LOG(AdvancedIdentityLog, Warning, TEXT("GetUserAccountAttribute failed to get user attribute!")); + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + Result = EBlueprintResultSwitch::OnSuccess; +} \ No newline at end of file diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/AdvancedSessions.cpp b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/AdvancedSessions.cpp new file mode 100644 index 0000000..8a12271 --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/AdvancedSessions.cpp @@ -0,0 +1,12 @@ +//#include "StandAlonePrivatePCH.h" +#include "AdvancedSessions.h" + +void AdvancedSessions::StartupModule() +{ +} + +void AdvancedSessions::ShutdownModule() +{ +} + +IMPLEMENT_MODULE(AdvancedSessions, AdvancedSessions) \ No newline at end of file diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/AdvancedSessionsLibrary.cpp b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/AdvancedSessionsLibrary.cpp new file mode 100644 index 0000000..a5453d1 --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/AdvancedSessionsLibrary.cpp @@ -0,0 +1,552 @@ +// Fill out your copyright notice in the Description page of Project Settings. +#include "AdvancedSessionsLibrary.h" +#include "GameFramework/PlayerState.h" +#include "GameFramework/GameStateBase.h" + +//General Log +DEFINE_LOG_CATEGORY(AdvancedSessionsLog); + + +bool UAdvancedSessionsLibrary::KickPlayer(UObject* WorldContextObject, APlayerController* PlayerToKick, FText KickReason) +{ + UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull); + + if (World) + { + if (AGameModeBase* GameMode = World->GetAuthGameMode()) + { + if (GameMode->GameSession) + { + return GameMode->GameSession->KickPlayer(PlayerToKick, KickReason); + } + } + } + + return false; +} + +bool UAdvancedSessionsLibrary::BanPlayer(UObject* WorldContextObject, APlayerController* PlayerToBan, FText BanReason) +{ + UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull); + + if (World) + { + if (AGameModeBase* GameMode = World->GetAuthGameMode()) + { + if (GameMode->GameSession) + { + return GameMode->GameSession->BanPlayer(PlayerToBan, BanReason); + } + } + } + + return false; +} + +bool UAdvancedSessionsLibrary::IsValidSession(const FBlueprintSessionResult & SessionResult) +{ + return SessionResult.OnlineResult.IsValid(); +} + +void UAdvancedSessionsLibrary::GetSessionID_AsString(const FBlueprintSessionResult & SessionResult, FString& SessionID) +{ + const TSharedPtr SessionInfo = SessionResult.OnlineResult.Session.SessionInfo; + if (SessionInfo.IsValid() && SessionInfo->IsValid() && SessionInfo->GetSessionId().IsValid()) + { + SessionID = SessionInfo->GetSessionId().ToString(); + return; + } + + // Zero the string out if we didn't have a valid one, in case this is called in c++ + SessionID.Empty(); +} + +void UAdvancedSessionsLibrary::GetCurrentSessionID_AsString(UObject* WorldContextObject, FString& SessionID) +{ + UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull); + IOnlineSessionPtr SessionInterface = Online::GetSessionInterface(World); + + if (!SessionInterface.IsValid()) + { + UE_LOG(AdvancedSessionsLog, Warning, TEXT("GetCurrentSessionID_AsString couldn't get the session interface!")); + SessionID.Empty(); + return; + } + + const FNamedOnlineSession* Session = SessionInterface->GetNamedSession(NAME_GameSession); + if (Session != nullptr) + { + const TSharedPtr SessionInfo = Session->SessionInfo; + if (SessionInfo.IsValid() && SessionInfo->IsValid() && SessionInfo->GetSessionId().IsValid()) + { + SessionID = SessionInfo->GetSessionId().ToString(); + return; + } + } + + // Zero the string out if we didn't have a valid one, in case this is called in c++ + SessionID.Empty(); +} + +void UAdvancedSessionsLibrary::GetCurrentUniqueBuildID(int32 &UniqueBuildId) +{ + UniqueBuildId = GetBuildUniqueId(); +} + +void UAdvancedSessionsLibrary::GetUniqueBuildID(FBlueprintSessionResult SessionResult, int32 &UniqueBuildId) +{ + UniqueBuildId = SessionResult.OnlineResult.Session.SessionSettings.BuildUniqueId; +} + +FName UAdvancedSessionsLibrary::GetSessionPropertyKey(const FSessionPropertyKeyPair& SessionProperty) +{ + return SessionProperty.Key; +} + +void UAdvancedSessionsLibrary::FindSessionPropertyByName(const TArray& ExtraSettings, FName SettingName, EBlueprintResultSwitch &Result, FSessionPropertyKeyPair& OutProperty) +{ + const FSessionPropertyKeyPair* prop = ExtraSettings.FindByPredicate([&](const FSessionPropertyKeyPair& it) {return it.Key == SettingName; }); + if (prop) + { + Result = EBlueprintResultSwitch::OnSuccess; + OutProperty = *prop; + return; + } + + Result = EBlueprintResultSwitch::OnFailure; +} + +void UAdvancedSessionsLibrary::FindSessionPropertyIndexByName(const TArray& ExtraSettings, FName SettingName, EBlueprintResultSwitch &Result, int32& OutIndex) +{ + OutIndex = ExtraSettings.IndexOfByPredicate([&](const FSessionPropertyKeyPair& it) {return it.Key == SettingName; }); + + Result = OutIndex != INDEX_NONE ? EBlueprintResultSwitch::OnSuccess : EBlueprintResultSwitch::OnFailure; +} + +void UAdvancedSessionsLibrary::AddOrModifyExtraSettings(UPARAM(ref) TArray & SettingsArray, UPARAM(ref) TArray & NewOrChangedSettings, TArray & ModifiedSettingsArray) +{ + ModifiedSettingsArray = SettingsArray; + + bool bFoundSetting = false; + // For each new setting + for (const FSessionPropertyKeyPair& Setting : NewOrChangedSettings) + { + bFoundSetting = false; + + for (FSessionPropertyKeyPair & itr : ModifiedSettingsArray) + { + // Manually comparing the keys + if (itr.Key == Setting.Key) + { + bFoundSetting = true; + itr.Data = Setting.Data; + } + } + + // If it was not found, add to the array instead + if (!bFoundSetting) + { + ModifiedSettingsArray.Add(Setting); + } + } + +} + +void UAdvancedSessionsLibrary::GetExtraSettings(FBlueprintSessionResult SessionResult, TArray & ExtraSettings) +{ + FSessionPropertyKeyPair NewSetting; + for (auto& Elem : SessionResult.OnlineResult.Session.SessionSettings.Settings) + { + NewSetting.Key = Elem.Key; + NewSetting.Data = Elem.Value.Data; + ExtraSettings.Add(NewSetting); + } +} + +void UAdvancedSessionsLibrary::GetSessionState(UObject* WorldContextObject, EBPOnlineSessionState &SessionState) +{ + UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull); + IOnlineSessionPtr SessionInterface = Online::GetSessionInterface(World); + + if (!SessionInterface.IsValid()) + { + UE_LOG(AdvancedSessionsLog, Warning, TEXT("GetSessionState couldn't get the session interface!")); + return; + } + + SessionState = ((EBPOnlineSessionState)SessionInterface->GetSessionState(NAME_GameSession)); +} + +void UAdvancedSessionsLibrary::GetSessionSettings(UObject* WorldContextObject, int32 &NumConnections, int32 &NumPrivateConnections, bool &bIsLAN, bool &bIsDedicated, bool &bAllowInvites, bool &bAllowJoinInProgress, bool &bIsAnticheatEnabled, int32 &BuildUniqueID, TArray &ExtraSettings, EBlueprintResultSwitch &Result) +{ + UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull); + IOnlineSessionPtr SessionInterface = Online::GetSessionInterface(World); + + if (!SessionInterface.IsValid()) + { + UE_LOG(AdvancedSessionsLog, Warning, TEXT("GetSessionSettings couldn't get the session interface!")); + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + FOnlineSessionSettings* settings = SessionInterface->GetSessionSettings(NAME_GameSession); + if (!settings) + { + UE_LOG(AdvancedSessionsLog, Warning, TEXT("GetSessionSettings couldn't get the session settings!")); + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + BuildUniqueID = settings->BuildUniqueId; + NumConnections = settings->NumPublicConnections; + NumPrivateConnections = settings->NumPrivateConnections; + bIsLAN = settings->bIsLANMatch; + bIsDedicated = settings->bIsDedicated; + bIsAnticheatEnabled = settings->bAntiCheatProtected; + bAllowInvites = settings->bAllowInvites; + bAllowJoinInProgress = settings->bAllowJoinInProgress; + + FSessionPropertyKeyPair NewSetting; + + for (auto& Elem : settings->Settings) + { + NewSetting.Key = Elem.Key; + NewSetting.Data = Elem.Value.Data; + ExtraSettings.Add(NewSetting); + } + + Result = EBlueprintResultSwitch::OnSuccess; +} + +void UAdvancedSessionsLibrary::IsPlayerInSession(UObject* WorldContextObject, const FBPUniqueNetId &PlayerToCheck, bool &bIsInSession) +{ + UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull); + IOnlineSessionPtr SessionInterface = Online::GetSessionInterface(World); + + if (!SessionInterface.IsValid()) + { + UE_LOG(AdvancedSessionsLog, Warning, TEXT("IsPlayerInSession couldn't get the session interface!")); + bIsInSession = false; + return; + } + + bIsInSession = SessionInterface->IsPlayerInSession(NAME_GameSession, *PlayerToCheck.GetUniqueNetId()); +} + +FSessionsSearchSetting UAdvancedSessionsLibrary::MakeLiteralSessionSearchProperty(FSessionPropertyKeyPair SessionSearchProperty, EOnlineComparisonOpRedux ComparisonOp) +{ + FSessionsSearchSetting setting; + setting.PropertyKeyPair = SessionSearchProperty; + setting.ComparisonOp = ComparisonOp; + + return setting; +} + +FSessionPropertyKeyPair UAdvancedSessionsLibrary::MakeLiteralSessionPropertyByte(FName Key, uint8 Value) +{ + FSessionPropertyKeyPair Prop; + Prop.Key = Key; + Prop.Data.SetValue((int32)Value); + return Prop; +} + +FSessionPropertyKeyPair UAdvancedSessionsLibrary::MakeLiteralSessionPropertyBool(FName Key, bool Value) +{ + FSessionPropertyKeyPair Prop; + Prop.Key = Key; + Prop.Data.SetValue(Value); + return Prop; +} + +FSessionPropertyKeyPair UAdvancedSessionsLibrary::MakeLiteralSessionPropertyString(FName Key, FString Value) +{ + FSessionPropertyKeyPair Prop; + Prop.Key = Key; + Prop.Data.SetValue(Value); + return Prop; +} + +FSessionPropertyKeyPair UAdvancedSessionsLibrary::MakeLiteralSessionPropertyInt(FName Key, int32 Value) +{ + FSessionPropertyKeyPair Prop; + Prop.Key = Key; + Prop.Data.SetValue(Value); + return Prop; +} + +FSessionPropertyKeyPair UAdvancedSessionsLibrary::MakeLiteralSessionPropertyFloat(FName Key, float Value) +{ + FSessionPropertyKeyPair Prop; + Prop.Key = Key; + Prop.Data.SetValue(Value); + return Prop; +} + +void UAdvancedSessionsLibrary::GetSessionPropertyByte(const TArray & ExtraSettings, FName SettingName, ESessionSettingSearchResult &SearchResult, uint8 &SettingValue) +{ + for (FSessionPropertyKeyPair itr : ExtraSettings) + { + if (itr.Key == SettingName) + { + if (itr.Data.GetType() == EOnlineKeyValuePairDataType::Int32) + { + int32 Val; + itr.Data.GetValue(Val); + SettingValue = (uint8)(Val); + SearchResult = ESessionSettingSearchResult::Found; + } + else + { + SearchResult = ESessionSettingSearchResult::WrongType; + } + return; + } + } + + SearchResult = ESessionSettingSearchResult::NotFound; + return; +} + +void UAdvancedSessionsLibrary::GetSessionPropertyBool(const TArray & ExtraSettings, FName SettingName, ESessionSettingSearchResult &SearchResult, bool &SettingValue) +{ + for (FSessionPropertyKeyPair itr : ExtraSettings) + { + if (itr.Key == SettingName) + { + if (itr.Data.GetType() == EOnlineKeyValuePairDataType::Bool) + { + itr.Data.GetValue(SettingValue); + SearchResult = ESessionSettingSearchResult::Found; + } + else + { + SearchResult = ESessionSettingSearchResult::WrongType; + } + return; + } + } + + SearchResult = ESessionSettingSearchResult::NotFound; + return; +} + +void UAdvancedSessionsLibrary::GetSessionPropertyString(const TArray & ExtraSettings, FName SettingName, ESessionSettingSearchResult &SearchResult, FString &SettingValue) +{ + for (FSessionPropertyKeyPair itr : ExtraSettings) + { + if (itr.Key == SettingName) + { + if (itr.Data.GetType() == EOnlineKeyValuePairDataType::String) + { + itr.Data.GetValue(SettingValue); + SearchResult = ESessionSettingSearchResult::Found; + } + else + { + SearchResult = ESessionSettingSearchResult::WrongType; + } + return; + } + } + + SearchResult = ESessionSettingSearchResult::NotFound; + return; +} + +void UAdvancedSessionsLibrary::GetSessionPropertyInt(const TArray & ExtraSettings, FName SettingName, ESessionSettingSearchResult &SearchResult, int32 &SettingValue) +{ + for (FSessionPropertyKeyPair itr : ExtraSettings) + { + if (itr.Key == SettingName) + { + if (itr.Data.GetType() == EOnlineKeyValuePairDataType::Int32) + { + itr.Data.GetValue(SettingValue); + SearchResult = ESessionSettingSearchResult::Found; + } + else + { + SearchResult = ESessionSettingSearchResult::WrongType; + } + return; + } + } + + SearchResult = ESessionSettingSearchResult::NotFound; + return; +} + +void UAdvancedSessionsLibrary::GetSessionPropertyFloat(const TArray & ExtraSettings, FName SettingName, ESessionSettingSearchResult &SearchResult, float &SettingValue) +{ + for (FSessionPropertyKeyPair itr : ExtraSettings) + { + if (itr.Key == SettingName) + { + if (itr.Data.GetType() == EOnlineKeyValuePairDataType::Float) + { + itr.Data.GetValue(SettingValue); + SearchResult = ESessionSettingSearchResult::Found; + } + else + { + SearchResult = ESessionSettingSearchResult::WrongType; + } + return; + } + } + + SearchResult = ESessionSettingSearchResult::NotFound; + return; +} + + +bool UAdvancedSessionsLibrary::HasOnlineSubsystem(FName SubSystemName) +{ + return IOnlineSubsystem::DoesInstanceExist(SubSystemName); +} + +void UAdvancedSessionsLibrary::GetNetPlayerIndex(APlayerController *PlayerController, int32 &NetPlayerIndex) +{ + if (!PlayerController) + { + UE_LOG(AdvancedSessionsLog, Warning, TEXT("GetNetPlayerIndex received a bad PlayerController!")); + NetPlayerIndex = 0; + return; + } + + NetPlayerIndex = PlayerController->NetPlayerIndex; + return; +} + +void UAdvancedSessionsLibrary::UniqueNetIdToString(const FBPUniqueNetId& UniqueNetId, FString &String) +{ + const FUniqueNetId * ID = UniqueNetId.GetUniqueNetId(); + + if ( !ID ) + { + UE_LOG(AdvancedSessionsLog, Warning, TEXT("UniqueNetIdToString received a bad UniqueNetId!")); + String = "ERROR, BAD UNIQUE NET ID"; + } + else + String = ID->ToString(); +} + + +void UAdvancedSessionsLibrary::GetUniqueNetID(APlayerController *PlayerController, FBPUniqueNetId &UniqueNetId) +{ + if (!PlayerController) + { + UE_LOG(AdvancedSessionsLog, Warning, TEXT("GetUniqueNetIdFromController received a bad PlayerController!")); + return; + } + + if (APlayerState* PlayerState = (PlayerController != NULL) ? PlayerController->PlayerState : NULL) + { + UniqueNetId.SetUniqueNetId(PlayerState->GetUniqueId().GetUniqueNetId()); + if (!UniqueNetId.IsValid()) + { + UE_LOG(AdvancedSessionsLog, Warning, TEXT("GetUniqueNetIdFromController couldn't get the player uniquenetid!")); + } + return; + } +} + +void UAdvancedSessionsLibrary::GetUniqueNetIDFromPlayerState(APlayerState *PlayerState, FBPUniqueNetId &UniqueNetId) +{ + if (!PlayerState) + { + UE_LOG(AdvancedSessionsLog, Warning, TEXT("GetUniqueNetIdFromPlayerState received a bad PlayerState!")); + return; + } + + UniqueNetId.SetUniqueNetId(PlayerState->GetUniqueId().GetUniqueNetId()); + if (!UniqueNetId.IsValid()) + { + UE_LOG(AdvancedSessionsLog, Warning, TEXT("GetUniqueNetIdFromPlayerState couldn't get the player uniquenetid!")); + } + return; +} + +bool UAdvancedSessionsLibrary::IsValidUniqueNetID(const FBPUniqueNetId &UniqueNetId) +{ + return UniqueNetId.IsValid(); +} + +bool UAdvancedSessionsLibrary::EqualEqual_UNetIDUnetID(const FBPUniqueNetId &A, const FBPUniqueNetId &B) +{ + return ((A.IsValid() && B.IsValid()) && (*A.GetUniqueNetId() == *B.GetUniqueNetId())); +} + +FUniqueNetIdRepl UAdvancedSessionsLibrary::Conv_BPUniqueIDToUniqueNetIDRepl(const FBPUniqueNetId& InUniqueID) +{ + return FUniqueNetIdRepl(InUniqueID.GetUniqueNetId()->AsShared()); +} + +void UAdvancedSessionsLibrary::SetPlayerName(APlayerController *PlayerController, FString PlayerName) +{ + if (!PlayerController) + { + UE_LOG(AdvancedSessionsLog, Warning, TEXT("SetLocalPlayerNameFromController Bad Player Controller!")); + return; + } + + if (APlayerState* PlayerState = (PlayerController != NULL) ? PlayerController->PlayerState : NULL) + { + PlayerState->SetPlayerName(PlayerName); + return; + } + else + { + UE_LOG(AdvancedSessionsLog, Warning, TEXT("SetLocalPlayerNameFromController had a bad player state!")); + } +} + +void UAdvancedSessionsLibrary::GetPlayerName(APlayerController *PlayerController, FString &PlayerName) +{ + if (!PlayerController) + { + UE_LOG(AdvancedSessionsLog, Warning, TEXT("GetLocalPlayerNameFromController Bad Player Controller!")); + return; + } + + if (APlayerState* PlayerState = (PlayerController != NULL) ? PlayerController->PlayerState : NULL) + { + PlayerName = PlayerState->GetPlayerName(); + return; + } + else + { + UE_LOG(AdvancedSessionsLog, Warning, TEXT("GetLocalPlayerNameFromController had a bad player state!")); + } +} + +void UAdvancedSessionsLibrary::GetNumberOfNetworkPlayers(UObject* WorldContextObject, int32 &NumNetPlayers) +{ + //Get World + UWorld* TheWorld = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull); + + if (!TheWorld) + { + UE_LOG(AdvancedSessionsLog, Warning, TEXT("GetNumberOfNetworkPlayers Failed to get World()!")); + return; + } + + NumNetPlayers = TheWorld->GetGameState()->PlayerArray.Num(); +} + +bool UAdvancedSessionsLibrary::ServerTravel(UObject* WorldContextObject, const FString& FURL, bool bAbsolute, bool bShouldSkipGameNotify) +{ + if (!WorldContextObject) + { + return false; + } + + //using a context object to get the world + UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::ReturnNull); + if (World) + { + return World->ServerTravel(FURL, bAbsolute, bShouldSkipGameNotify); + } + + return false; +} \ No newline at end of file diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/AdvancedVoiceLibrary.cpp b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/AdvancedVoiceLibrary.cpp new file mode 100644 index 0000000..f6321c1 --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/AdvancedVoiceLibrary.cpp @@ -0,0 +1,359 @@ +// Fill out your copyright notice in the Description page of Project Settings. +#include "AdvancedVoiceLibrary.h" + + +//General Log +DEFINE_LOG_CATEGORY(AdvancedVoiceLog); + +void UAdvancedVoiceLibrary::IsHeadsetPresent(UObject* WorldContextObject, bool & bHasHeadset, uint8 LocalPlayerNum) +{ + + UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull); + if (!IsValid(World)) + { + return; + } + + IOnlineVoicePtr VoiceInterface = Online::GetVoiceInterface(World); + + if (!VoiceInterface.IsValid()) + { + bHasHeadset = false; + UE_LOG(AdvancedVoiceLog, Warning, TEXT("Check For Headset couldn't get the voice interface!")); + return; + } + + bHasHeadset = VoiceInterface->IsHeadsetPresent(LocalPlayerNum); +} + +void UAdvancedVoiceLibrary::StartNetworkedVoice(UObject* WorldContextObject, uint8 LocalPlayerNum) +{ + + UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull); + if (!IsValid(World)) + { + return; + } + + IOnlineVoicePtr VoiceInterface = Online::GetVoiceInterface(World); + + if (!VoiceInterface.IsValid()) + { + UE_LOG(AdvancedVoiceLog, Warning, TEXT("Start Networked Voice couldn't get the voice interface!")); + return; + } + + VoiceInterface->StartNetworkedVoice(LocalPlayerNum); +} + +void UAdvancedVoiceLibrary::StopNetworkedVoice(UObject* WorldContextObject, uint8 LocalPlayerNum) +{ + + UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull); + if (!IsValid(World)) + { + return; + } + + IOnlineVoicePtr VoiceInterface = Online::GetVoiceInterface(World); + + if (!VoiceInterface.IsValid()) + { + UE_LOG(AdvancedVoiceLog, Warning, TEXT("Start Networked Voice couldn't get the voice interface!")); + return; + } + + VoiceInterface->StopNetworkedVoice(LocalPlayerNum); +} + +bool UAdvancedVoiceLibrary::RegisterLocalTalker(UObject* WorldContextObject, uint8 LocalPlayerNum) +{ + UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull); + if (!IsValid(World)) + { + return false; + } + + IOnlineVoicePtr VoiceInterface = Online::GetVoiceInterface(World); + + if (!VoiceInterface.IsValid()) + { + UE_LOG(AdvancedVoiceLog, Warning, TEXT("Register Local Talker couldn't get the voice interface!")); + return false; + } + + return VoiceInterface->RegisterLocalTalker(LocalPlayerNum); +} + +void UAdvancedVoiceLibrary::RegisterAllLocalTalkers(UObject* WorldContextObject) +{ + + UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull); + if (!IsValid(World)) + { + return; + } + + IOnlineVoicePtr VoiceInterface = Online::GetVoiceInterface(World); + + if (!VoiceInterface.IsValid()) + { + UE_LOG(AdvancedVoiceLog, Warning, TEXT("Register Local Talkers couldn't get the voice interface!")); + return; + } + + VoiceInterface->RegisterLocalTalkers(); +} + + +void UAdvancedVoiceLibrary::UnRegisterLocalTalker(UObject* WorldContextObject, uint8 LocalPlayerNum) +{ + + UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull); + if (!IsValid(World)) + { + return; + } + + IOnlineVoicePtr VoiceInterface = Online::GetVoiceInterface(World); + + if (!VoiceInterface.IsValid()) + { + UE_LOG(AdvancedVoiceLog, Warning, TEXT("Unregister Local Talker couldn't get the voice interface!")); + return; + } + + VoiceInterface->UnregisterLocalTalker(LocalPlayerNum); +} + +void UAdvancedVoiceLibrary::UnRegisterAllLocalTalkers(UObject* WorldContextObject) +{ + + UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull); + if (!IsValid(World)) + { + return; + } + + IOnlineVoicePtr VoiceInterface = Online::GetVoiceInterface(World); + + if (!VoiceInterface.IsValid()) + { + UE_LOG(AdvancedVoiceLog, Warning, TEXT("UnRegister All Local Talkers couldn't get the voice interface!")); + return; + } + + VoiceInterface->UnregisterLocalTalkers(); +} + +bool UAdvancedVoiceLibrary::RegisterRemoteTalker(UObject* WorldContextObject, const FBPUniqueNetId& UniqueNetId) +{ + if (!UniqueNetId.IsValid()) + { + UE_LOG(AdvancedVoiceLog, Warning, TEXT("Register Remote Talker was passed an invalid unique net id!")); + return false; + } + + UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull); + if (!IsValid(World)) + { + return false; + } + + IOnlineVoicePtr VoiceInterface = Online::GetVoiceInterface(World); + + if (!VoiceInterface.IsValid()) + { + UE_LOG(AdvancedVoiceLog, Warning, TEXT("Register Remote Talker couldn't get the voice interface!")); + return false; + } + + return VoiceInterface->RegisterRemoteTalker(*UniqueNetId.GetUniqueNetId()); +} + +bool UAdvancedVoiceLibrary::UnRegisterRemoteTalker(UObject* WorldContextObject, const FBPUniqueNetId& UniqueNetId) +{ + if (!UniqueNetId.IsValid()) + { + UE_LOG(AdvancedVoiceLog, Warning, TEXT("UnRegister Remote Talker was passed an invalid unique net id!")); + return false; + } + + UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull); + if (!IsValid(World)) + { + return false; + } + + IOnlineVoicePtr VoiceInterface = Online::GetVoiceInterface(World); + + if (!VoiceInterface.IsValid()) + { + UE_LOG(AdvancedVoiceLog, Warning, TEXT("UnRegister Remote Talker couldn't get the voice interface!")); + return false; + } + + return VoiceInterface->UnregisterRemoteTalker(*UniqueNetId.GetUniqueNetId()); +} + +void UAdvancedVoiceLibrary::RemoveAllRemoteTalkers(UObject* WorldContextObject) +{ + + UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull); + if (!IsValid(World)) + { + return; + } + + IOnlineVoicePtr VoiceInterface = Online::GetVoiceInterface(World); + + if (!VoiceInterface.IsValid()) + { + UE_LOG(AdvancedVoiceLog, Warning, TEXT("Remove All Remote Talkers couldn't get the voice interface!")); + return; + } + + VoiceInterface->RemoveAllRemoteTalkers(); +} + +bool UAdvancedVoiceLibrary::IsLocalPlayerTalking(UObject* WorldContextObject, uint8 LocalPlayerNum) +{ + + UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull); + if (!IsValid(World)) + { + return false; + } + + IOnlineVoicePtr VoiceInterface = Online::GetVoiceInterface(World); + + if (!VoiceInterface.IsValid()) + { + UE_LOG(AdvancedVoiceLog, Warning, TEXT("Is Local Player Talking couldn't get the voice interface!")); + return false; + } + + return VoiceInterface->IsLocalPlayerTalking(LocalPlayerNum); +} + +bool UAdvancedVoiceLibrary::IsRemotePlayerTalking(UObject* WorldContextObject, const FBPUniqueNetId& UniqueNetId) +{ + if (!UniqueNetId.IsValid()) + { + UE_LOG(AdvancedVoiceLog, Warning, TEXT("Is Remote Player Talking was passed an invalid unique net id!")); + return false; + } + + UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull); + if (!IsValid(World)) + { + return false; + } + + IOnlineVoicePtr VoiceInterface = Online::GetVoiceInterface(World); + + if (!VoiceInterface.IsValid()) + { + UE_LOG(AdvancedVoiceLog, Warning, TEXT("Is Remote Player Talking couldn't get the voice interface!")); + return false; + } + + return VoiceInterface->IsRemotePlayerTalking(*UniqueNetId.GetUniqueNetId()); +} + +bool UAdvancedVoiceLibrary::IsPlayerMuted(UObject* WorldContextObject, uint8 LocalUserNumChecking, const FBPUniqueNetId& UniqueNetId) +{ + if (!UniqueNetId.IsValid()) + { + UE_LOG(AdvancedVoiceLog, Warning, TEXT("Is Player Muted was passed an invalid unique net id!")); + return false; + } + + UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull); + if (!IsValid(World)) + { + return false; + } + + IOnlineVoicePtr VoiceInterface = Online::GetVoiceInterface(World); + + if (!VoiceInterface.IsValid()) + { + UE_LOG(AdvancedVoiceLog, Warning, TEXT("Is Player Muted couldn't get the voice interface!")); + return false; + } + + return VoiceInterface->IsMuted(LocalUserNumChecking, *UniqueNetId.GetUniqueNetId()); +} + +bool UAdvancedVoiceLibrary::MuteRemoteTalker(UObject* WorldContextObject, uint8 LocalUserNum, const FBPUniqueNetId& UniqueNetId, bool bIsSystemWide) +{ + if (!UniqueNetId.IsValid()) + { + UE_LOG(AdvancedVoiceLog, Warning, TEXT("Mute Remote Talker was passed an invalid unique net id!")); + return false; + } + + UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull); + if (!IsValid(World)) + { + return false; + } + + IOnlineVoicePtr VoiceInterface = Online::GetVoiceInterface(World); + + if (!VoiceInterface.IsValid()) + { + UE_LOG(AdvancedVoiceLog, Warning, TEXT("Mute Remote Talker couldn't get the voice interface!")); + return false; + } + + return VoiceInterface->MuteRemoteTalker(LocalUserNum, *UniqueNetId.GetUniqueNetId(), bIsSystemWide); +} + +bool UAdvancedVoiceLibrary::UnMuteRemoteTalker(UObject* WorldContextObject, uint8 LocalUserNum, const FBPUniqueNetId& UniqueNetId, bool bIsSystemWide) +{ + if (!UniqueNetId.IsValid()) + { + UE_LOG(AdvancedVoiceLog, Warning, TEXT("Unmute Remote Talker was passed an invalid unique net id!")); + return false; + } + + UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull); + if (!IsValid(World)) + { + return false; + } + + IOnlineVoicePtr VoiceInterface = Online::GetVoiceInterface(World); + + if (!VoiceInterface.IsValid()) + { + UE_LOG(AdvancedVoiceLog, Warning, TEXT("Unmute Remote Talker couldn't get the voice interface!")); + return false; + } + + return VoiceInterface->UnmuteRemoteTalker(LocalUserNum, *UniqueNetId.GetUniqueNetId(), bIsSystemWide); +} + + +void UAdvancedVoiceLibrary::GetNumLocalTalkers(UObject* WorldContextObject, int32 & NumLocalTalkers) +{ + + UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull); + if (!IsValid(World)) + { + return; + } + + IOnlineVoicePtr VoiceInterface = Online::GetVoiceInterface(World); + + if (!VoiceInterface.IsValid()) + { + NumLocalTalkers = 0; + UE_LOG(AdvancedVoiceLog, Warning, TEXT("Unmute Remote Talker couldn't get the voice interface!")); + return; + } + + NumLocalTalkers = VoiceInterface->GetNumLocalTalkers(); +} \ No newline at end of file diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/AutoLoginUserCallbackProxy.cpp b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/AutoLoginUserCallbackProxy.cpp new file mode 100644 index 0000000..9046773 --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/AutoLoginUserCallbackProxy.cpp @@ -0,0 +1,89 @@ +// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. + +#include "AutoLoginUserCallbackProxy.h" +#include "Kismet/GameplayStatics.h" + +#include "Online.h" + +////////////////////////////////////////////////////////////////////////// +// ULoginUserCallbackProxy + +UAutoLoginUserCallbackProxy::UAutoLoginUserCallbackProxy(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) + , Delegate(FOnLoginCompleteDelegate::CreateUObject(this, &ThisClass::OnCompleted)) +{ +} + +UAutoLoginUserCallbackProxy* UAutoLoginUserCallbackProxy::AutoLoginUser(UObject* WorldContextObject, int32 LocalUserNum) +{ + UAutoLoginUserCallbackProxy* Proxy = NewObject(); + Proxy->LocalUserNumber = LocalUserNum; + Proxy->WorldContextObject = WorldContextObject; + return Proxy; +} + +void UAutoLoginUserCallbackProxy::Activate() +{ + + FOnlineSubsystemBPCallHelperAdvanced Helper(TEXT("AutoLoginUser"), GEngine->GetWorldFromContextObject(WorldContextObject.Get(), EGetWorldErrorMode::LogAndReturnNull)); + + if (Helper.OnlineSub != nullptr) + { + auto Identity = Helper.OnlineSub->GetIdentityInterface(); + + if (Identity.IsValid()) + { + DelegateHandle = Identity->AddOnLoginCompleteDelegate_Handle(LocalUserNumber, Delegate); + Identity->AutoLogin(LocalUserNumber); + return; + } + } + + // Fail immediately + OnFailure.Broadcast(); +} + +void UAutoLoginUserCallbackProxy::OnCompleted(int32 LocalUserNum, bool bWasSuccessful, const FUniqueNetId& UserId, const FString& ErrorVal) +{ + FOnlineSubsystemBPCallHelperAdvanced Helper(TEXT("AutoLoginUser"), GEngine->GetWorldFromContextObject(WorldContextObject.Get(), EGetWorldErrorMode::LogAndReturnNull)); + + if (Helper.OnlineSub != nullptr) + { + auto Identity = Helper.OnlineSub->GetIdentityInterface(); + + if (Identity.IsValid()) + { + Identity->ClearOnLoginCompleteDelegate_Handle(LocalUserNum, DelegateHandle); + } + + if (APlayerController* PController = UGameplayStatics::GetPlayerController(WorldContextObject->GetWorld(), LocalUserNum)) + { + ULocalPlayer* Player = Cast(PController->Player); + + FUniqueNetIdRepl uniqueId(UserId.AsShared()); + + if (Player) + { + Player->SetCachedUniqueNetId(uniqueId); + } + + if (APlayerState* State = PController->PlayerState) + { + // Update UniqueId. See also ShowLoginUICallbackProxy.cpp + State->SetUniqueId(uniqueId); + } + } + + + if (bWasSuccessful) + { + OnSuccess.Broadcast(); + } + else + { + OnFailure.Broadcast(); + } + } + + OnFailure.Broadcast(); +} diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/CancelFindSessionsCallbackProxy.cpp b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/CancelFindSessionsCallbackProxy.cpp new file mode 100644 index 0000000..600187e --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/CancelFindSessionsCallbackProxy.cpp @@ -0,0 +1,70 @@ +// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. +#include "CancelFindSessionsCallbackProxy.h" + + +////////////////////////////////////////////////////////////////////////// +// UCancelFindSessionsCallbackProxy + +UCancelFindSessionsCallbackProxy::UCancelFindSessionsCallbackProxy(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) + , Delegate(FOnCancelFindSessionsCompleteDelegate::CreateUObject(this, &ThisClass::OnCompleted)) +{ +} + +UCancelFindSessionsCallbackProxy* UCancelFindSessionsCallbackProxy::CancelFindSessions(UObject* WorldContextObject, class APlayerController* PlayerController) +{ + UCancelFindSessionsCallbackProxy* Proxy = NewObject(); + Proxy->PlayerControllerWeakPtr = PlayerController; + Proxy->WorldContextObject = WorldContextObject; + return Proxy; +} + +void UCancelFindSessionsCallbackProxy::Activate() +{ + FOnlineSubsystemBPCallHelperAdvanced Helper(TEXT("CancelFindSessions"), GEngine->GetWorldFromContextObject(WorldContextObject.Get(), EGetWorldErrorMode::LogAndReturnNull)); + Helper.QueryIDFromPlayerController(PlayerControllerWeakPtr.Get()); + + if (Helper.IsValid()) + { + auto Sessions = Helper.OnlineSub->GetSessionInterface(); + if (Sessions.IsValid()) + { + DelegateHandle = Sessions->AddOnCancelFindSessionsCompleteDelegate_Handle(Delegate); + Sessions->CancelFindSessions(); + + // OnCompleted will get called, nothing more to do now + return; + } + else + { + FFrame::KismetExecutionMessage(TEXT("Sessions not supported by Online Subsystem"), ELogVerbosity::Warning); + } + } + + // Fail immediately + OnFailure.Broadcast(); +} + +void UCancelFindSessionsCallbackProxy::OnCompleted(bool bWasSuccessful) +{ + FOnlineSubsystemBPCallHelperAdvanced Helper(TEXT("CancelFindSessionsCallback"), GEngine->GetWorldFromContextObject(WorldContextObject.Get(), EGetWorldErrorMode::LogAndReturnNull)); + Helper.QueryIDFromPlayerController(PlayerControllerWeakPtr.Get()); + + if (Helper.IsValid()) + { + auto Sessions = Helper.OnlineSub->GetSessionInterface(); + if (Sessions.IsValid()) + { + Sessions->ClearOnCancelFindSessionsCompleteDelegate_Handle(DelegateHandle); + } + } + + if (bWasSuccessful) + { + OnSuccess.Broadcast(); + } + else + { + OnFailure.Broadcast(); + } +} diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/CreateSessionCallbackProxyAdvanced.cpp b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/CreateSessionCallbackProxyAdvanced.cpp new file mode 100644 index 0000000..1ff10c1 --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/CreateSessionCallbackProxyAdvanced.cpp @@ -0,0 +1,182 @@ +// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. +#include "CreateSessionCallbackProxyAdvanced.h" + + +////////////////////////////////////////////////////////////////////////// +// UCreateSessionCallbackProxyAdvanced + +UCreateSessionCallbackProxyAdvanced::UCreateSessionCallbackProxyAdvanced(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) + , CreateCompleteDelegate(FOnCreateSessionCompleteDelegate::CreateUObject(this, &ThisClass::OnCreateCompleted)) + , StartCompleteDelegate(FOnStartSessionCompleteDelegate::CreateUObject(this, &ThisClass::OnStartCompleted)) + , NumPublicConnections(1) +{ +} + +UCreateSessionCallbackProxyAdvanced* UCreateSessionCallbackProxyAdvanced::CreateAdvancedSession(UObject* WorldContextObject, const TArray& ExtraSettings, class APlayerController* PlayerController, int32 PublicConnections, int32 PrivateConnections, bool bUseLAN, bool bAllowInvites, bool bIsDedicatedServer, bool bUsePresence, bool bUseLobbiesIfAvailable, bool bAllowJoinViaPresence, bool bAllowJoinViaPresenceFriendsOnly, bool bAntiCheatProtected, bool bUsesStats, bool bShouldAdvertise, bool bUseLobbiesVoiceChatIfAvailable, bool bStartAfterCreate) +{ + UCreateSessionCallbackProxyAdvanced* Proxy = NewObject(); + Proxy->PlayerControllerWeakPtr = PlayerController; + Proxy->NumPublicConnections = PublicConnections; + Proxy->NumPrivateConnections = PrivateConnections; + Proxy->bUseLAN = bUseLAN; + Proxy->WorldContextObject = WorldContextObject; + Proxy->bAllowInvites = bAllowInvites; + Proxy->ExtraSettings = ExtraSettings; + Proxy->bDedicatedServer = bIsDedicatedServer; + Proxy->bUsePresence = bUsePresence; + Proxy->bUseLobbiesIfAvailable = bUseLobbiesIfAvailable; + Proxy->bAllowJoinViaPresence = bAllowJoinViaPresence; + Proxy->bAllowJoinViaPresenceFriendsOnly = bAllowJoinViaPresenceFriendsOnly; + Proxy->bAntiCheatProtected = bAntiCheatProtected; + Proxy->bUsesStats = bUsesStats; + Proxy->bShouldAdvertise = bShouldAdvertise; + Proxy->bUseLobbiesVoiceChatIfAvailable = bUseLobbiesVoiceChatIfAvailable; + Proxy->bStartAfterCreate = bStartAfterCreate; + return Proxy; +} + +void UCreateSessionCallbackProxyAdvanced::Activate() +{ + FOnlineSubsystemBPCallHelperAdvanced Helper(TEXT("CreateSession"), GEngine->GetWorldFromContextObject(WorldContextObject.Get(), EGetWorldErrorMode::LogAndReturnNull)); + + if (PlayerControllerWeakPtr.IsValid() ) + Helper.QueryIDFromPlayerController(PlayerControllerWeakPtr.Get()); + + if (Helper.OnlineSub != nullptr) + { + auto Sessions = Helper.OnlineSub->GetSessionInterface(); + if (Sessions.IsValid()) + { + CreateCompleteDelegateHandle = Sessions->AddOnCreateSessionCompleteDelegate_Handle(CreateCompleteDelegate); + + FOnlineSessionSettings Settings; + Settings.NumPublicConnections = NumPublicConnections; + Settings.NumPrivateConnections = NumPrivateConnections; + Settings.bShouldAdvertise = bShouldAdvertise; + Settings.bAllowJoinInProgress = true; + Settings.bIsLANMatch = bUseLAN; + Settings.bAllowJoinViaPresence = bAllowJoinViaPresence; + Settings.bIsDedicated = bDedicatedServer; + + if (bDedicatedServer) + { + Settings.bUsesPresence = false; + Settings.bUseLobbiesIfAvailable = false; + } + else + { + Settings.bUsesPresence = bUsePresence; + Settings.bUseLobbiesIfAvailable = bUseLobbiesIfAvailable; + } + + Settings.bUseLobbiesVoiceChatIfAvailable = bUseLobbiesIfAvailable ? bUseLobbiesVoiceChatIfAvailable : false; + Settings.bAllowJoinViaPresenceFriendsOnly = bAllowJoinViaPresenceFriendsOnly; + Settings.bAntiCheatProtected = bAntiCheatProtected; + Settings.bUsesStats = bUsesStats; + + // These are about the only changes over the standard Create Sessions Node + Settings.bAllowInvites = bAllowInvites; + + FOnlineSessionSetting ExtraSetting; + for (int i = 0; i < ExtraSettings.Num(); i++) + { + ExtraSetting.Data = ExtraSettings[i].Data; + // ViaOnlineServiceAndPing + ExtraSetting.AdvertisementType = EOnlineDataAdvertisementType::ViaOnlineService; + Settings.Settings.Add(ExtraSettings[i].Key, ExtraSetting); + } + + + if (!bDedicatedServer ) + { + if (PlayerControllerWeakPtr.IsValid() && Helper.UserID.IsValid()) + { + Sessions->CreateSession(*Helper.UserID, NAME_GameSession, Settings); + } + else + { + FFrame::KismetExecutionMessage(TEXT("Invalid Player controller when attempting to start a session"), ELogVerbosity::Warning); + Sessions->ClearOnCreateSessionCompleteDelegate_Handle(CreateCompleteDelegateHandle); + + // Fail immediately + OnFailure.Broadcast(); + } + } + else + Sessions->CreateSession(0, NAME_GameSession, Settings); + + // OnCreateCompleted will get called, nothing more to do now + return; + } + else + { + FFrame::KismetExecutionMessage(TEXT("Sessions not supported by Online Subsystem"), ELogVerbosity::Warning); + } + } + + // Fail immediately + OnFailure.Broadcast(); +} + +void UCreateSessionCallbackProxyAdvanced::OnCreateCompleted(FName SessionName, bool bWasSuccessful) +{ + FOnlineSubsystemBPCallHelperAdvanced Helper(TEXT("CreateSessionCallback"), GEngine->GetWorldFromContextObject(WorldContextObject.Get(), EGetWorldErrorMode::LogAndReturnNull)); + //Helper.QueryIDFromPlayerController(PlayerControllerWeakPtr.Get()); + + if (Helper.OnlineSub != nullptr) + { + auto Sessions = Helper.OnlineSub->GetSessionInterface(); + if (Sessions.IsValid()) + { + Sessions->ClearOnCreateSessionCompleteDelegate_Handle(CreateCompleteDelegateHandle); + + if (bWasSuccessful) + { + if (this->bStartAfterCreate) + { + UE_LOG_ONLINE_SESSION(Display, TEXT("Session creation completed. Automatic start is turned on, starting session now.")); + StartCompleteDelegateHandle = Sessions->AddOnStartSessionCompleteDelegate_Handle(StartCompleteDelegate); + Sessions->StartSession(NAME_GameSession); // We'll call `OnSuccess.Broadcast()` when start succeeds. + } + else + { + UE_LOG_ONLINE_SESSION(Display, TEXT("Session creation completed. Automatic start is turned off, to start the session call 'StartSession'.")); + OnSuccess.Broadcast(); + } + + // OnStartCompleted will get called, nothing more to do now + return; + } + } + } + + if (!bWasSuccessful) + { + OnFailure.Broadcast(); + } +} + +void UCreateSessionCallbackProxyAdvanced::OnStartCompleted(FName SessionName, bool bWasSuccessful) +{ + FOnlineSubsystemBPCallHelperAdvanced Helper(TEXT("StartSessionCallback"), GEngine->GetWorldFromContextObject(WorldContextObject.Get(), EGetWorldErrorMode::LogAndReturnNull)); + //Helper.QueryIDFromPlayerController(PlayerControllerWeakPtr.Get()); + + if (Helper.OnlineSub != nullptr) + { + auto Sessions = Helper.OnlineSub->GetSessionInterface(); + if (Sessions.IsValid()) + { + Sessions->ClearOnStartSessionCompleteDelegate_Handle(StartCompleteDelegateHandle); + } + } + + if (bWasSuccessful) + { + OnSuccess.Broadcast(); + } + else + { + OnFailure.Broadcast(); + } +} diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/EndSessionCallbackProxy.cpp b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/EndSessionCallbackProxy.cpp new file mode 100644 index 0000000..ddb248c --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/EndSessionCallbackProxy.cpp @@ -0,0 +1,78 @@ +// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. +#include "EndSessionCallbackProxy.h" + + +////////////////////////////////////////////////////////////////////////// +// UEndSessionCallbackProxy + +UEndSessionCallbackProxy::UEndSessionCallbackProxy(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) + , Delegate(FOnEndSessionCompleteDelegate::CreateUObject(this, &ThisClass::OnCompleted)) +{ +} + +UEndSessionCallbackProxy* UEndSessionCallbackProxy::EndSession(UObject* WorldContextObject, class APlayerController* PlayerController) +{ + UEndSessionCallbackProxy* Proxy = NewObject(); + Proxy->PlayerControllerWeakPtr = PlayerController; + Proxy->WorldContextObject = WorldContextObject; + return Proxy; +} + +void UEndSessionCallbackProxy::Activate() +{ + FOnlineSubsystemBPCallHelperAdvanced Helper(TEXT("EndSession"), GEngine->GetWorldFromContextObject(WorldContextObject.Get(), EGetWorldErrorMode::LogAndReturnNull)); + Helper.QueryIDFromPlayerController(PlayerControllerWeakPtr.Get()); + + if (Helper.IsValid()) + { + auto Sessions = Helper.OnlineSub->GetSessionInterface(); + if (Sessions.IsValid()) + { + FNamedOnlineSession* Session = Sessions->GetNamedSession(NAME_GameSession); + if (Session && + Session->SessionState == EOnlineSessionState::InProgress) + { + DelegateHandle = Sessions->AddOnEndSessionCompleteDelegate_Handle(Delegate); + Sessions->EndSession(NAME_GameSession); + } + else + { + OnSuccess.Broadcast(); + } + // OnCompleted will get called, nothing more to do now + return; + } + else + { + FFrame::KismetExecutionMessage(TEXT("Sessions not supported by Online Subsystem"), ELogVerbosity::Warning); + } + } + + // Fail immediately + OnFailure.Broadcast(); +} + +void UEndSessionCallbackProxy::OnCompleted(FName SessionName, bool bWasSuccessful) +{ + FOnlineSubsystemBPCallHelperAdvanced Helper(TEXT("EndSessionCallback"), GEngine->GetWorldFromContextObject(WorldContextObject.Get(), EGetWorldErrorMode::LogAndReturnNull)); + Helper.QueryIDFromPlayerController(PlayerControllerWeakPtr.Get()); + + if (Helper.IsValid()) + { + auto Sessions = Helper.OnlineSub->GetSessionInterface(); + if (Sessions.IsValid()) + { + Sessions->ClearOnEndSessionCompleteDelegate_Handle(DelegateHandle); + } + } + + if (bWasSuccessful) + { + OnSuccess.Broadcast(); + } + else + { + OnFailure.Broadcast(); + } +} diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/FindFriendSessionCallbackProxy.cpp b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/FindFriendSessionCallbackProxy.cpp new file mode 100644 index 0000000..019255c --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/FindFriendSessionCallbackProxy.cpp @@ -0,0 +1,130 @@ +// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. +#include "FindFriendSessionCallbackProxy.h" + + +////////////////////////////////////////////////////////////////////////// +// UGetRecentPlayersCallbackProxy +DEFINE_LOG_CATEGORY(AdvancedFindFriendSessionLog); + +UFindFriendSessionCallbackProxy::UFindFriendSessionCallbackProxy(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) + , OnFindFriendSessionCompleteDelegate(FOnFindFriendSessionCompleteDelegate::CreateUObject(this, &ThisClass::OnFindFriendSessionCompleted)) +{ +} + +UFindFriendSessionCallbackProxy* UFindFriendSessionCallbackProxy::FindFriendSession(UObject* WorldContextObject, APlayerController *PlayerController, const FBPUniqueNetId &FriendUniqueNetId) +{ + UFindFriendSessionCallbackProxy* Proxy = NewObject(); + Proxy->PlayerControllerWeakPtr = PlayerController; + Proxy->cUniqueNetId = FriendUniqueNetId; + Proxy->WorldContextObject = WorldContextObject; + return Proxy; +} + +void UFindFriendSessionCallbackProxy::Activate() +{ + if (!cUniqueNetId.IsValid()) + { + // Fail immediately + UE_LOG(AdvancedFindFriendSessionLog, Warning, TEXT("FindFriendSession Failed received a bad UniqueNetId!")); + TArray EmptyResult; + OnFailure.Broadcast(EmptyResult); + return; + } + + if (!PlayerControllerWeakPtr.IsValid()) + { + // Fail immediately + UE_LOG(AdvancedFindFriendSessionLog, Warning, TEXT("FindFriendSession Failed received a bad playercontroller!")); + TArray EmptyResult; + OnFailure.Broadcast(EmptyResult); + return; + } + + FOnlineSubsystemBPCallHelperAdvanced Helper(TEXT("EndSessionCallback"), GEngine->GetWorldFromContextObject(WorldContextObject.Get(), EGetWorldErrorMode::LogAndReturnNull)); + Helper.QueryIDFromPlayerController(PlayerControllerWeakPtr.Get()); + + if (!Helper.IsValid()) + { + // Fail immediately + TArray EmptyResult; + OnFailure.Broadcast(EmptyResult); + return; + } + + IOnlineSessionPtr Sessions = Helper.OnlineSub->GetSessionInterface(); + + if (Sessions.IsValid()) + { + ULocalPlayer* Player = Cast(PlayerControllerWeakPtr->Player); + + if (!Player) + { + // Fail immediately + UE_LOG(AdvancedFindFriendSessionLog, Warning, TEXT("FindFriendSession Failed couldn't cast to ULocalPlayer!")); + TArray EmptyResult; + OnFailure.Broadcast(EmptyResult); + return; + } + + FindFriendSessionCompleteDelegateHandle = Sessions->AddOnFindFriendSessionCompleteDelegate_Handle(Player->GetControllerId(), OnFindFriendSessionCompleteDelegate); + + Sessions->FindFriendSession(Player->GetControllerId(), *cUniqueNetId.GetUniqueNetId()); + + return; + } + + // Fail immediately + TArray EmptyResult; + OnFailure.Broadcast(EmptyResult); +} + + +void UFindFriendSessionCallbackProxy::OnFindFriendSessionCompleted(int32 LocalPlayer, bool bWasSuccessful, const TArray& SessionInfo) +{ + FOnlineSubsystemBPCallHelperAdvanced Helper(TEXT("EndSessionCallback"), GEngine->GetWorldFromContextObject(WorldContextObject.Get(), EGetWorldErrorMode::LogAndReturnNull)); + Helper.QueryIDFromPlayerController(PlayerControllerWeakPtr.Get()); + + if (Helper.IsValid()) + { + IOnlineSessionPtr Sessions = Helper.OnlineSub->GetSessionInterface(); + + if (Sessions.IsValid()) + Sessions->ClearOnFindFriendSessionCompleteDelegate_Handle(LocalPlayer, FindFriendSessionCompleteDelegateHandle); + + if (bWasSuccessful) + { + TArray Result; + + for (auto& Sesh : SessionInfo) + { + if (Sesh.IsValid()) + { + FBlueprintSessionResult BSesh; + BSesh.OnlineResult = Sesh; + Result.Add(BSesh); + } + } + + if (Result.Num() > 0) + OnSuccess.Broadcast(Result); + else + { + UE_LOG(AdvancedFindFriendSessionLog, Warning, TEXT("FindFriendSession Failed, returned an invalid session.")); + OnFailure.Broadcast(Result); + } + } + else + { + UE_LOG(AdvancedFindFriendSessionLog, Warning, TEXT("FindFriendSession Failed")); + TArray EmptyResult; + OnFailure.Broadcast(EmptyResult); + } + } + else + { + UE_LOG(AdvancedFindFriendSessionLog, Warning, TEXT("FindFriendSession Failed")); + TArray EmptyResult; + OnFailure.Broadcast(EmptyResult); + } +} diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/FindSessionsCallbackProxyAdvanced.cpp b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/FindSessionsCallbackProxyAdvanced.cpp new file mode 100644 index 0000000..dc0dc4b --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/FindSessionsCallbackProxyAdvanced.cpp @@ -0,0 +1,444 @@ +// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. +#include "FindSessionsCallbackProxyAdvanced.h" + +#include "Online/OnlineSessionNames.h" + +////////////////////////////////////////////////////////////////////////// +// UFindSessionsCallbackProxyAdvanced + + +UFindSessionsCallbackProxyAdvanced::UFindSessionsCallbackProxyAdvanced(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) + , Delegate(FOnFindSessionsCompleteDelegate::CreateUObject(this, &ThisClass::OnCompleted)) + , bUseLAN(false) +{ + bRunSecondSearch = false; + bIsOnSecondSearch = false; +} + +UFindSessionsCallbackProxyAdvanced* UFindSessionsCallbackProxyAdvanced::FindSessionsAdvanced(UObject* WorldContextObject, class APlayerController* PlayerController, int MaxResults, bool bUseLAN, EBPServerPresenceSearchType ServerTypeToSearch, const TArray &Filters, bool bEmptyServersOnly, bool bNonEmptyServersOnly, bool bSecureServersOnly, bool bSearchLobbies, int MinSlotsAvailable) +{ + UFindSessionsCallbackProxyAdvanced* Proxy = NewObject(); + Proxy->PlayerControllerWeakPtr = PlayerController; + Proxy->bUseLAN = bUseLAN; + Proxy->MaxResults = MaxResults; + Proxy->WorldContextObject = WorldContextObject; + Proxy->SearchSettings = Filters; + Proxy->ServerSearchType = ServerTypeToSearch; + Proxy->bEmptyServersOnly = bEmptyServersOnly, + Proxy->bNonEmptyServersOnly = bNonEmptyServersOnly; + Proxy->bSecureServersOnly = bSecureServersOnly; + Proxy->bSearchLobbies = bSearchLobbies; + Proxy->MinSlotsAvailable = MinSlotsAvailable; + return Proxy; +} + +void UFindSessionsCallbackProxyAdvanced::Activate() +{ + FOnlineSubsystemBPCallHelperAdvanced Helper(TEXT("FindSessions"), GEngine->GetWorldFromContextObject(WorldContextObject.Get(), EGetWorldErrorMode::LogAndReturnNull)); + Helper.QueryIDFromPlayerController(PlayerControllerWeakPtr.Get()); + + if (Helper.IsValid()) + { + auto Sessions = Helper.OnlineSub->GetSessionInterface(); + if (Sessions.IsValid()) + { + // Re-initialize here, otherwise I think there might be issues with people re-calling search for some reason before it is destroyed + bRunSecondSearch = false; + bIsOnSecondSearch = false; + + DelegateHandle = Sessions->AddOnFindSessionsCompleteDelegate_Handle(Delegate); + + SearchObject = MakeShareable(new FOnlineSessionSearch); + SearchObject->MaxSearchResults = MaxResults; + SearchObject->bIsLanQuery = bUseLAN; + //SearchObject->QuerySettings.Set(SEARCH_PRESENCE, true, EOnlineComparisonOp::Equals); + + // Create temp filter variable, because I had to re-define a blueprint version of this, it is required. + FOnlineSearchSettingsEx tem; + + /* // Search only for dedicated servers (value is true/false) + #define SEARCH_DEDICATED_ONLY FName(TEXT("DEDICATEDONLY")) + // Search for empty servers only (value is true/false) + #define SEARCH_EMPTY_SERVERS_ONLY FName(TEXT("EMPTYONLY")) + // Search for non empty servers only (value is true/false) + #define SEARCH_NONEMPTY_SERVERS_ONLY FName(TEXT("NONEMPTYONLY")) + // Search for secure servers only (value is true/false) + #define SEARCH_SECURE_SERVERS_ONLY FName(TEXT("SECUREONLY")) + // Search for presence sessions only (value is true/false) + #define SEARCH_PRESENCE FName(TEXT("PRESENCESEARCH")) + // Search for a match with min player availability (value is int) + #define SEARCH_MINSLOTSAVAILABLE FName(TEXT("MINSLOTSAVAILABLE")) + // Exclude all matches where any unique ids in a given array are present (value is string of the form "uniqueid1;uniqueid2;uniqueid3") + #define SEARCH_EXCLUDE_UNIQUEIDS FName(TEXT("EXCLUDEUNIQUEIDS")) + // User ID to search for session of + #define SEARCH_USER FName(TEXT("SEARCHUSER")) + // Keywords to match in session search + #define SEARCH_KEYWORDS FName(TEXT("SEARCHKEYWORDS"))*/ + /** Keywords to match in session search */ + /** The matchmaking queue name to matchmake in, e.g. "TeamDeathmatch" (value is string) */ + /** #define SEARCH_MATCHMAKING_QUEUE FName(TEXT("MATCHMAKINGQUEUE"))*/ + /** If set, use the named Xbox Live hopper to find a session via matchmaking (value is a string) */ + /** #define SEARCH_XBOX_LIVE_HOPPER_NAME FName(TEXT("LIVEHOPPERNAME"))*/ + /** Which session template from the service configuration to use */ + /** #define SEARCH_XBOX_LIVE_SESSION_TEMPLATE_NAME FName(TEXT("LIVESESSIONTEMPLATE"))*/ + /** Selection method used to determine which match to join when multiple are returned (valid only on Switch) */ + /** #define SEARCH_SWITCH_SELECTION_METHOD FName(TEXT("SWITCHSELECTIONMETHOD"))*/ + /** Whether to use lobbies vs sessions */ + /** #define SEARCH_LOBBIES FName(TEXT("LOBBYSEARCH"))*/ + + if (bEmptyServersOnly) + tem.Set(SEARCH_EMPTY_SERVERS_ONLY, true, EOnlineComparisonOp::Equals); + + if (bNonEmptyServersOnly) + tem.Set(SEARCH_NONEMPTY_SERVERS_ONLY, true, EOnlineComparisonOp::Equals); + + if (bSecureServersOnly) + tem.Set(SEARCH_SECURE_SERVERS_ONLY, true, EOnlineComparisonOp::Equals); + + if (MinSlotsAvailable != 0) + tem.Set(SEARCH_MINSLOTSAVAILABLE, MinSlotsAvailable, EOnlineComparisonOp::GreaterThanEquals); + + // Filter results + if (SearchSettings.Num() > 0) + { + for (int i = 0; i < SearchSettings.Num(); i++) + { + // Function that was added to make directly adding a FVariant possible + tem.HardSet(SearchSettings[i].PropertyKeyPair.Key, SearchSettings[i].PropertyKeyPair.Data, SearchSettings[i].ComparisonOp); + } + } + + switch (ServerSearchType) + { + + case EBPServerPresenceSearchType::ClientServersOnly: + { + tem.Set(SEARCH_PRESENCE, true, EOnlineComparisonOp::Equals); + + if (bSearchLobbies && !IOnlineSubsystem::DoesInstanceExist("STEAM")) + tem.Set(SEARCH_LOBBIES, true, EOnlineComparisonOp::Equals); + } + break; + + case EBPServerPresenceSearchType::DedicatedServersOnly: + { + //tem.Set(SEARCH_DEDICATED_ONLY, true, EOnlineComparisonOp::Equals); + } + break; + + case EBPServerPresenceSearchType::AllServers: + default: + { + //if (IOnlineSubsystem::DoesInstanceExist("STEAM")) + //{ + bRunSecondSearch = true; + + SearchObjectDedicated = MakeShareable(new FOnlineSessionSearch); + SearchObjectDedicated->MaxSearchResults = MaxResults; + SearchObjectDedicated->bIsLanQuery = bUseLAN; + + FOnlineSearchSettingsEx DedicatedOnly = tem; + + tem.Set(SEARCH_PRESENCE, true, EOnlineComparisonOp::Equals); + + if (bSearchLobbies && !IOnlineSubsystem::DoesInstanceExist("STEAM")) + tem.Set(SEARCH_LOBBIES, true, EOnlineComparisonOp::Equals); + + //DedicatedOnly.Set(SEARCH_DEDICATED_ONLY, true, EOnlineComparisonOp::Equals); + SearchObjectDedicated->QuerySettings = DedicatedOnly; + //} + } + break; + } + + // Copy the derived temp variable over to it's base class + SearchObject->QuerySettings = tem; + + Sessions->FindSessions(*Helper.UserID, SearchObject.ToSharedRef()); + + // OnQueryCompleted will get called, nothing more to do now + return; + } + else + { + FFrame::KismetExecutionMessage(TEXT("Sessions not supported by Online Subsystem"), ELogVerbosity::Warning); + } + } + + // Fail immediately + OnFailure.Broadcast(SessionSearchResults); +} + +void UFindSessionsCallbackProxyAdvanced::OnCompleted(bool bSuccess) +{ + FOnlineSubsystemBPCallHelperAdvanced Helper(TEXT("FindSessionsCallback"), GEngine->GetWorldFromContextObject(WorldContextObject.Get(), EGetWorldErrorMode::LogAndReturnNull)); + Helper.QueryIDFromPlayerController(PlayerControllerWeakPtr.Get()); + + if (!Helper.IsValid()) + { + // Fail immediately + OnFailure.Broadcast(SessionSearchResults); + return; + } + + if (!bRunSecondSearch && Helper.IsValid()) + { + auto Sessions = Helper.OnlineSub->GetSessionInterface(); + if (Sessions.IsValid()) + { + Sessions->ClearOnFindSessionsCompleteDelegate_Handle(DelegateHandle); + } + } + + if (bSuccess) + { + if (bIsOnSecondSearch) + { + if (SearchObjectDedicated.IsValid()) + { + // Just log the results for now, will need to add a blueprint-compatible search result struct + for (auto& Result : SearchObjectDedicated->SearchResults) + { + FString ResultText = FString::Printf(TEXT("Found a session. Ping is %d"), Result.PingInMs); + + FFrame::KismetExecutionMessage(*ResultText, ELogVerbosity::Log); + + FBlueprintSessionResult BPResult; + BPResult.OnlineResult = Result; + SessionSearchResults.AddUnique(BPResult); + } + OnSuccess.Broadcast(SessionSearchResults); + return; + } + } + else + { + if (SearchObject.IsValid()) + { + // Just log the results for now, will need to add a blueprint-compatible search result struct + for (auto& Result : SearchObject->SearchResults) + { + FString ResultText = FString::Printf(TEXT("Found a session. Ping is %d"), Result.PingInMs); + + FFrame::KismetExecutionMessage(*ResultText, ELogVerbosity::Log); + + FBlueprintSessionResult BPResult; + BPResult.OnlineResult = Result; + SessionSearchResults.AddUnique(BPResult); + } + if (!bRunSecondSearch) + { + OnSuccess.Broadcast(SessionSearchResults); + return; + } + } + } + } + else + { + if (!bRunSecondSearch) + { + // Need to account for only one of the searches failing + if (SessionSearchResults.Num() > 0) + OnSuccess.Broadcast(SessionSearchResults); + else + OnFailure.Broadcast(SessionSearchResults); + return; + } + } + + if (Helper.IsValid() && bRunSecondSearch && ServerSearchType == EBPServerPresenceSearchType::AllServers) + { + bRunSecondSearch = false; + bIsOnSecondSearch = true; + auto Sessions = Helper.OnlineSub->GetSessionInterface(); + Sessions->FindSessions(*Helper.UserID, SearchObjectDedicated.ToSharedRef()); + } + else // We lost our player controller + { + if (bSuccess && SessionSearchResults.Num() > 0) + OnSuccess.Broadcast(SessionSearchResults); + else + OnFailure.Broadcast(SessionSearchResults); + } +} + + +void UFindSessionsCallbackProxyAdvanced::FilterSessionResults(const TArray &SessionResults, const TArray &Filters, TArray &FilteredResults) +{ + for (int j = 0; j < SessionResults.Num(); j++) + { + bool bAddResult = true; + + // Filter results + if (Filters.Num() > 0) + { + const FOnlineSessionSetting * setting; + for (int i = 0; i < Filters.Num(); i++) + { + setting = SessionResults[j].OnlineResult.Session.SessionSettings.Settings.Find(Filters[i].PropertyKeyPair.Key); + + // Couldn't find this key + if (!setting) + continue; + + if (!CompareVariants(setting->Data, Filters[i].PropertyKeyPair.Data, Filters[i].ComparisonOp)) + { + bAddResult = false; + break; + } + } + } + + if (bAddResult) + FilteredResults.Add(SessionResults[j]); + } + + return; +} + + +bool UFindSessionsCallbackProxyAdvanced::CompareVariants(const FVariantData &A, const FVariantData &B, EOnlineComparisonOpRedux Comparator) +{ + if (A.GetType() != B.GetType()) + return false; + + switch (A.GetType()) + { + case EOnlineKeyValuePairDataType::Bool: + { + bool bA, bB; + A.GetValue(bA); + B.GetValue(bB); + switch (Comparator) + { + case EOnlineComparisonOpRedux::Equals: + return bA == bB; break; + case EOnlineComparisonOpRedux::NotEquals: + return bA != bB; break; + default: + return false;break; + } + } + case EOnlineKeyValuePairDataType::Double: + { + double bA, bB; + A.GetValue(bA); + B.GetValue(bB); + switch (Comparator) + { + case EOnlineComparisonOpRedux::Equals: + return bA == bB; break; + case EOnlineComparisonOpRedux::NotEquals: + return bA != bB; break; + case EOnlineComparisonOpRedux::GreaterThanEquals: + return (bA == bB || bA > bB); break; + case EOnlineComparisonOpRedux::LessThanEquals: + return (bA == bB || bA < bB); break; + case EOnlineComparisonOpRedux::GreaterThan: + return bA > bB; break; + case EOnlineComparisonOpRedux::LessThan: + return bA < bB; break; + default: + return false; break; + } + } + case EOnlineKeyValuePairDataType::Float: + { + float tbA, tbB; + double bA, bB; + A.GetValue(tbA); + B.GetValue(tbB); + bA = (double)tbA; + bB = (double)tbB; + switch (Comparator) + { + case EOnlineComparisonOpRedux::Equals: + return bA == bB; break; + case EOnlineComparisonOpRedux::NotEquals: + return bA != bB; break; + case EOnlineComparisonOpRedux::GreaterThanEquals: + return (bA == bB || bA > bB); break; + case EOnlineComparisonOpRedux::LessThanEquals: + return (bA == bB || bA < bB); break; + case EOnlineComparisonOpRedux::GreaterThan: + return bA > bB; break; + case EOnlineComparisonOpRedux::LessThan: + return bA < bB; break; + default: + return false; break; + } + } + case EOnlineKeyValuePairDataType::Int32: + { + int32 bA, bB; + A.GetValue(bA); + B.GetValue(bB); + switch (Comparator) + { + case EOnlineComparisonOpRedux::Equals: + return bA == bB; break; + case EOnlineComparisonOpRedux::NotEquals: + return bA != bB; break; + case EOnlineComparisonOpRedux::GreaterThanEquals: + return (bA == bB || bA > bB); break; + case EOnlineComparisonOpRedux::LessThanEquals: + return (bA == bB || bA < bB); break; + case EOnlineComparisonOpRedux::GreaterThan: + return bA > bB; break; + case EOnlineComparisonOpRedux::LessThan: + return bA < bB; break; + default: + return false; break; + } + } + case EOnlineKeyValuePairDataType::Int64: + { + uint64 bA, bB; + A.GetValue(bA); + B.GetValue(bB); + switch (Comparator) + { + case EOnlineComparisonOpRedux::Equals: + return bA == bB; break; + case EOnlineComparisonOpRedux::NotEquals: + return bA != bB; break; + case EOnlineComparisonOpRedux::GreaterThanEquals: + return (bA == bB || bA > bB); break; + case EOnlineComparisonOpRedux::LessThanEquals: + return (bA == bB || bA < bB); break; + case EOnlineComparisonOpRedux::GreaterThan: + return bA > bB; break; + case EOnlineComparisonOpRedux::LessThan: + return bA < bB; break; + default: + return false; break; + } + } + + case EOnlineKeyValuePairDataType::String: + { + FString bA, bB; + A.GetValue(bA); + B.GetValue(bB); + switch (Comparator) + { + case EOnlineComparisonOpRedux::Equals: + return bA == bB; break; + case EOnlineComparisonOpRedux::NotEquals: + return bA != bB; break; + default: + return false; break; + } + } + + case EOnlineKeyValuePairDataType::Empty: + case EOnlineKeyValuePairDataType::Blob: + default: + return false; break; + } + + + +} \ No newline at end of file diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/GetFriendsCallbackProxy.cpp b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/GetFriendsCallbackProxy.cpp new file mode 100644 index 0000000..2d1d738 --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/GetFriendsCallbackProxy.cpp @@ -0,0 +1,114 @@ +// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. +#include "GetFriendsCallbackProxy.h" + +#include "Online.h" +#include "Interfaces/OnlineFriendsInterface.h" +#include "Interfaces/OnlinePresenceInterface.h" + +////////////////////////////////////////////////////////////////////////// +// UGetFriendsCallbackProxy +DEFINE_LOG_CATEGORY(AdvancedGetFriendsLog); + +UGetFriendsCallbackProxy::UGetFriendsCallbackProxy(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) + , FriendListReadCompleteDelegate(FOnReadFriendsListComplete::CreateUObject(this, &ThisClass::OnReadFriendsListCompleted)) +{ +} + +UGetFriendsCallbackProxy* UGetFriendsCallbackProxy::GetAndStoreFriendsList(UObject* WorldContextObject, class APlayerController* PlayerController) +{ + UGetFriendsCallbackProxy* Proxy = NewObject(); + Proxy->PlayerControllerWeakPtr = PlayerController; + Proxy->WorldContextObject = WorldContextObject; + return Proxy; +} + +void UGetFriendsCallbackProxy::Activate() +{ + if (!PlayerControllerWeakPtr.IsValid()) + { + // Fail immediately + UE_LOG(AdvancedGetFriendsLog, Warning, TEXT("GetFriends Failed received a bad player controller!")); + TArray EmptyArray; + OnFailure.Broadcast(EmptyArray); + return; + } + + FOnlineSubsystemBPCallHelperAdvanced Helper(TEXT("GetFriends"), GEngine->GetWorldFromContextObject(WorldContextObject.Get(), EGetWorldErrorMode::LogAndReturnNull)); + Helper.QueryIDFromPlayerController(PlayerControllerWeakPtr.Get()); + + if (Helper.IsValid()) + { + IOnlineFriendsPtr Friends = Helper.OnlineSub->GetFriendsInterface(); + if (Friends.IsValid()) + { + ULocalPlayer* Player = Cast(PlayerControllerWeakPtr->Player); + + Friends->ReadFriendsList(Player->GetControllerId(), EFriendsLists::ToString((EFriendsLists::Default)), FriendListReadCompleteDelegate); + return; + } + } + + // Fail immediately + TArray EmptyArray; + OnFailure.Broadcast(EmptyArray); +} + +void UGetFriendsCallbackProxy::OnReadFriendsListCompleted(int32 LocalUserNum, bool bWasSuccessful, const FString& ListName, const FString& ErrorString) +{ + if (bWasSuccessful) + { + FOnlineSubsystemBPCallHelperAdvanced Helper(TEXT("GetFriends"), GEngine->GetWorldFromContextObject(WorldContextObject.Get(), EGetWorldErrorMode::LogAndReturnNull)); + Helper.QueryIDFromPlayerController(PlayerControllerWeakPtr.Get()); + + if (!Helper.IsValid()) + { + TArray EmptyArray; + OnFailure.Broadcast(EmptyArray); + return; + } + + auto Friends = Helper.OnlineSub->GetFriendsInterface(); + if (Friends.IsValid()) + { + // Not actually needed anymore, plus was not being validated and causing a crash + //ULocalPlayer* Player = Cast(PlayerControllerWeakPtr->Player); + + TArray FriendsListOut; + TArray< TSharedRef > FriendList; + if (Friends->GetFriendsList(LocalUserNum, ListName, FriendList)) + { + for (int32 i = 0; i < FriendList.Num(); i++) + { + FBPFriendInfo BPF; + const FOnlineUserPresence& pres = FriendList[i]->GetPresence(); + BPF.OnlineState = ((EBPOnlinePresenceState)((int32)pres.Status.State)); + BPF.DisplayName = FriendList[i]->GetDisplayName(); + BPF.RealName = FriendList[i]->GetRealName(); + BPF.UniqueNetId.SetUniqueNetId(FriendList[i]->GetUserId()); + BPF.bIsPlayingSameGame = pres.bIsPlayingThisGame; + + BPF.PresenceInfo.bIsOnline = pres.bIsOnline; + BPF.PresenceInfo.bHasVoiceSupport = pres.bHasVoiceSupport; + BPF.PresenceInfo.bIsPlaying = pres.bIsPlaying; + BPF.PresenceInfo.PresenceState = ((EBPOnlinePresenceState)((int32)pres.Status.State)); + + // #TODO: Check back in on this in shipping, epic is missing the UTF8_TO_TCHAR call on converting this and its making an invalid string + //BPF.PresenceInfo.StatusString = pres.Status.StatusStr; + BPF.PresenceInfo.bIsJoinable = pres.bIsJoinable; + BPF.PresenceInfo.bIsPlayingThisGame = pres.bIsPlayingThisGame; + + + FriendsListOut.Add(BPF); + } + } + + OnSuccess.Broadcast(FriendsListOut); + } + } + else + { + TArray EmptyArray; + OnFailure.Broadcast(EmptyArray); + } +} diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/GetRecentPlayersCallbackProxy.cpp b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/GetRecentPlayersCallbackProxy.cpp new file mode 100644 index 0000000..84bdcec --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/GetRecentPlayersCallbackProxy.cpp @@ -0,0 +1,104 @@ +// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. +#include "GetRecentPlayersCallbackProxy.h" + +#include "Online.h" + +////////////////////////////////////////////////////////////////////////// +// UGetRecentPlayersCallbackProxy +DEFINE_LOG_CATEGORY(AdvancedGetRecentPlayersLog); + +UGetRecentPlayersCallbackProxy::UGetRecentPlayersCallbackProxy(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) + , QueryRecentPlayersCompleteDelegate(FOnQueryRecentPlayersCompleteDelegate::CreateUObject(this, &ThisClass::OnQueryRecentPlayersCompleted)) +{ +} + +UGetRecentPlayersCallbackProxy* UGetRecentPlayersCallbackProxy::GetAndStoreRecentPlayersList(UObject* WorldContextObject, const FBPUniqueNetId& UniqueNetId) +{ + UGetRecentPlayersCallbackProxy* Proxy = NewObject(); + Proxy->cUniqueNetId = UniqueNetId; + Proxy->WorldContextObject = WorldContextObject; + return Proxy; +} + +void UGetRecentPlayersCallbackProxy::Activate() +{ + if (!cUniqueNetId.IsValid()) + { + // Fail immediately + UE_LOG(AdvancedGetRecentPlayersLog, Warning, TEXT("GetRecentPlayers Failed received a bad UniqueNetId!")); + TArray EmptyArray; + OnFailure.Broadcast(EmptyArray); + return; + } + + FOnlineSubsystemBPCallHelperAdvanced Helper(TEXT("GetRecentPlayers"), GEngine->GetWorldFromContextObject(WorldContextObject.Get(), EGetWorldErrorMode::LogAndReturnNull)); + + if (!Helper.OnlineSub) + { + TArray EmptyArray; + OnFailure.Broadcast(EmptyArray); + return; + } + + IOnlineFriendsPtr Friends = Helper.OnlineSub->GetFriendsInterface(); + if (Friends.IsValid()) + { + DelegateHandle = Friends->AddOnQueryRecentPlayersCompleteDelegate_Handle(QueryRecentPlayersCompleteDelegate); + + // Testing with null namespace + Friends->QueryRecentPlayers(*(cUniqueNetId.GetUniqueNetId()), ""); + return; + } + // Fail immediately + TArray EmptyArray; + OnFailure.Broadcast(EmptyArray); +} + +void UGetRecentPlayersCallbackProxy::OnQueryRecentPlayersCompleted(const FUniqueNetId &UserID, const FString &Namespace, bool bWasSuccessful, const FString& ErrorString) +{ + + FOnlineSubsystemBPCallHelperAdvanced Helper(TEXT("GetRecentPlayers"), GEngine->GetWorldFromContextObject(WorldContextObject.Get(), EGetWorldErrorMode::LogAndReturnNull)); + + if (!Helper.OnlineSub) + { + TArray EmptyArray; + OnFailure.Broadcast(EmptyArray); + return; + } + + IOnlineFriendsPtr Friends = Helper.OnlineSub->GetFriendsInterface(); + if (Friends.IsValid()) + Friends->ClearOnQueryRecentPlayersCompleteDelegate_Handle(DelegateHandle); + + + if (bWasSuccessful) + { + // WHOOPS + //IOnlineFriendsPtr Friends = Online::GetFriendsInterface(); + if (Friends.IsValid()) + { + TArray PlayersListOut; + TArray< TSharedRef > PlayerList; + + Friends->GetRecentPlayers(*(cUniqueNetId.GetUniqueNetId()), "", PlayerList); + + for (int32 i = 0; i < PlayerList.Num(); i++) + { + TSharedRef Player = PlayerList[i]; + FBPOnlineRecentPlayer BPF; + BPF.DisplayName = Player->GetDisplayName(); + BPF.RealName = Player->GetRealName(); + BPF.UniqueNetId.SetUniqueNetId(Player->GetUserId()); + PlayersListOut.Add(BPF); + } + + OnSuccess.Broadcast(PlayersListOut); + } + } + else + { + TArray EmptyArray; + OnFailure.Broadcast(EmptyArray); + } +} diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/GetUserPrivilegeCallbackProxy.cpp b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/GetUserPrivilegeCallbackProxy.cpp new file mode 100644 index 0000000..7b1ef39 --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/GetUserPrivilegeCallbackProxy.cpp @@ -0,0 +1,48 @@ +// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. + +#include "GetUserPrivilegeCallbackProxy.h" + +#include "Online.h" + +////////////////////////////////////////////////////////////////////////// +// UGetUserPrivilegeCallbackProxy + +UGetUserPrivilegeCallbackProxy::UGetUserPrivilegeCallbackProxy(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ +} + +UGetUserPrivilegeCallbackProxy* UGetUserPrivilegeCallbackProxy::GetUserPrivilege(UObject* WorldContextObject, const EBPUserPrivileges & PrivilegeToCheck, const FBPUniqueNetId & PlayerUniqueNetID) +{ + UGetUserPrivilegeCallbackProxy* Proxy = NewObject(); + Proxy->PlayerUniqueNetID.SetUniqueNetId(PlayerUniqueNetID.GetUniqueNetId()); + Proxy->UserPrivilege = PrivilegeToCheck; + Proxy->WorldContextObject = WorldContextObject; + return Proxy; +} + +void UGetUserPrivilegeCallbackProxy::Activate() +{ + FOnlineSubsystemBPCallHelperAdvanced Helper(TEXT("GetUserPrivilege"), GEngine->GetWorldFromContextObject(WorldContextObject.Get(), EGetWorldErrorMode::LogAndReturnNull)); + + if (!Helper.OnlineSub) + { + OnFailure.Broadcast(); + return; + } + auto Identity = Helper.OnlineSub->GetIdentityInterface(); + + if (Identity.IsValid()) + { + Identity->GetUserPrivilege(*PlayerUniqueNetID.GetUniqueNetId(), (EUserPrivileges::Type)UserPrivilege, IOnlineIdentity::FOnGetUserPrivilegeCompleteDelegate::CreateUObject(this, &ThisClass::OnCompleted)); + return; + } + + // Fail immediately + OnFailure.Broadcast(); +} + +void UGetUserPrivilegeCallbackProxy::OnCompleted(const FUniqueNetId& PlayerID, EUserPrivileges::Type Privilege, uint32 PrivilegeResult) +{ + OnSuccess.Broadcast(/*PlayerID,*/ (EBPUserPrivileges)Privilege, PrivilegeResult == 0); +} diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/LoginUserCallbackProxy.cpp b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/LoginUserCallbackProxy.cpp new file mode 100644 index 0000000..584edc5 --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/LoginUserCallbackProxy.cpp @@ -0,0 +1,111 @@ +// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. + +#include "LoginUserCallbackProxy.h" + +#include "Online.h" + +////////////////////////////////////////////////////////////////////////// +// ULoginUserCallbackProxy + +ULoginUserCallbackProxy::ULoginUserCallbackProxy(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) + , Delegate(FOnLoginCompleteDelegate::CreateUObject(this, &ThisClass::OnCompleted)) +{ +} + +ULoginUserCallbackProxy* ULoginUserCallbackProxy::LoginUser(UObject* WorldContextObject, class APlayerController* PlayerController, FString UserID, FString UserToken, FString AuthType) +{ + ULoginUserCallbackProxy* Proxy = NewObject(); + Proxy->PlayerControllerWeakPtr = PlayerController; + Proxy->UserID = UserID; + Proxy->UserToken = UserToken; + Proxy->AuthType = AuthType; + Proxy->WorldContextObject = WorldContextObject; + return Proxy; +} + +void ULoginUserCallbackProxy::Activate() +{ + + if (!PlayerControllerWeakPtr.IsValid()) + { + OnFailure.Broadcast(); + return; + } + + ULocalPlayer* Player = Cast(PlayerControllerWeakPtr->Player); + + if (!Player) + { + OnFailure.Broadcast(); + return; + } + + FOnlineSubsystemBPCallHelperAdvanced Helper(TEXT("LoginUser"), GEngine->GetWorldFromContextObject(WorldContextObject.Get(), EGetWorldErrorMode::LogAndReturnNull)); + + if (!Helper.OnlineSub) + { + OnFailure.Broadcast(); + return; + } + + auto Identity = Helper.OnlineSub->GetIdentityInterface(); + if (Identity.IsValid()) + { + // Fallback to default AuthType if nothing is specified + if (AuthType.IsEmpty()) + { + AuthType = Identity->GetAuthType(); + } + DelegateHandle = Identity->AddOnLoginCompleteDelegate_Handle(Player->GetControllerId(), Delegate); + FOnlineAccountCredentials AccountCreds(AuthType, UserID, UserToken); + Identity->Login(Player->GetControllerId(), AccountCreds); + return; + } + + // Fail immediately + OnFailure.Broadcast(); +} + +void ULoginUserCallbackProxy::OnCompleted(int32 LocalUserNum, bool bWasSuccessful, const FUniqueNetId& UserId, const FString& ErrorVal) +{ + if (PlayerControllerWeakPtr.IsValid()) + { + ULocalPlayer* Player = Cast(PlayerControllerWeakPtr->Player); + + FUniqueNetIdRepl UniqueID(UserId.AsShared()); + + if (Player) + { + FOnlineSubsystemBPCallHelperAdvanced Helper(TEXT("GetUserPrivilege"), GEngine->GetWorldFromContextObject(WorldContextObject.Get(), EGetWorldErrorMode::LogAndReturnNull)); + + if (!Helper.OnlineSub) + { + OnFailure.Broadcast(); + return; + } + + auto Identity = Helper.OnlineSub->GetIdentityInterface(); + if (Identity.IsValid()) + { + Identity->ClearOnLoginCompleteDelegate_Handle(Player->GetControllerId(), DelegateHandle); + } + Player->SetCachedUniqueNetId(UniqueID); + } + + if (APlayerState* State = PlayerControllerWeakPtr->PlayerState) + { + // Update UniqueId. See also ShowLoginUICallbackProxy.cpp + State->SetUniqueId(UniqueID); + } + } + + if (bWasSuccessful) + { + OnSuccess.Broadcast(); + } + else + { + OnFailure.Broadcast(); + } +} diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/LogoutUserCallbackProxy.cpp b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/LogoutUserCallbackProxy.cpp new file mode 100644 index 0000000..07bc666 --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/LogoutUserCallbackProxy.cpp @@ -0,0 +1,94 @@ +// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. + +#include "LogoutUserCallbackProxy.h" + +#include "Online.h" + +////////////////////////////////////////////////////////////////////////// +// ULogoutUserCallbackProxy + +ULogoutUserCallbackProxy::ULogoutUserCallbackProxy(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) + , Delegate(FOnLogoutCompleteDelegate::CreateUObject(this, &ThisClass::OnCompleted)) +{ +} + +ULogoutUserCallbackProxy* ULogoutUserCallbackProxy::LogoutUser(UObject* WorldContextObject, class APlayerController* PlayerController) +{ + ULogoutUserCallbackProxy* Proxy = NewObject(); + Proxy->PlayerControllerWeakPtr = PlayerController; + Proxy->WorldContextObject = WorldContextObject; + return Proxy; +} + +void ULogoutUserCallbackProxy::Activate() +{ + + if (!PlayerControllerWeakPtr.IsValid()) + { + OnFailure.Broadcast(); + return; + } + + ULocalPlayer* Player = Cast(PlayerControllerWeakPtr->Player); + + if (!Player) + { + OnFailure.Broadcast(); + return; + } + + FOnlineSubsystemBPCallHelperAdvanced Helper(TEXT("LogoutUser"), GEngine->GetWorldFromContextObject(WorldContextObject.Get(), EGetWorldErrorMode::LogAndReturnNull)); + + if (!Helper.OnlineSub) + { + OnFailure.Broadcast(); + return; + } + auto Identity = Helper.OnlineSub->GetIdentityInterface(); + + if (Identity.IsValid()) + { + DelegateHandle = Identity->AddOnLogoutCompleteDelegate_Handle(Player->GetControllerId(), Delegate); + Identity->Logout(Player->GetControllerId()); + return; + } + + // Fail immediately + OnFailure.Broadcast(); +} + +void ULogoutUserCallbackProxy::OnCompleted(int LocalUserNum, bool bWasSuccessful) +{ + + if (PlayerControllerWeakPtr.IsValid()) + { + ULocalPlayer* Player = Cast(PlayerControllerWeakPtr->Player); + + if (Player) + { + FOnlineSubsystemBPCallHelperAdvanced Helper(TEXT("LogoutUser"), GEngine->GetWorldFromContextObject(WorldContextObject.Get(), EGetWorldErrorMode::LogAndReturnNull)); + + if (!Helper.OnlineSub) + { + OnFailure.Broadcast(); + return; + } + auto Identity = Helper.OnlineSub->GetIdentityInterface(); + + if (Identity.IsValid()) + { + Identity->ClearOnLogoutCompleteDelegate_Handle(Player->GetControllerId(), DelegateHandle); + } + } + } + + if (bWasSuccessful) + { + OnSuccess.Broadcast(); + } + else + { + OnFailure.Broadcast(); + } +} diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/SendFriendInviteCallbackProxy.cpp b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/SendFriendInviteCallbackProxy.cpp new file mode 100644 index 0000000..7c407c4 --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/SendFriendInviteCallbackProxy.cpp @@ -0,0 +1,82 @@ +// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. +#include "SendFriendInviteCallbackProxy.h" + +#include "Online.h" + +////////////////////////////////////////////////////////////////////////// +// UGetRecentPlayersCallbackProxy +DEFINE_LOG_CATEGORY(AdvancedSendFriendInviteLog); + +USendFriendInviteCallbackProxy::USendFriendInviteCallbackProxy(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) + , OnSendInviteCompleteDelegate(FOnSendInviteComplete::CreateUObject(this, &ThisClass::OnSendInviteComplete)) +{ +} + +USendFriendInviteCallbackProxy* USendFriendInviteCallbackProxy::SendFriendInvite(UObject* WorldContextObject, APlayerController *PlayerController, const FBPUniqueNetId &UniqueNetIDInvited) +{ + USendFriendInviteCallbackProxy* Proxy = NewObject(); + Proxy->PlayerControllerWeakPtr = PlayerController; + Proxy->cUniqueNetId = UniqueNetIDInvited; + Proxy->WorldContextObject = WorldContextObject; + return Proxy; +} + +void USendFriendInviteCallbackProxy::Activate() +{ + if (!cUniqueNetId.IsValid()) + { + // Fail immediately + UE_LOG(AdvancedSendFriendInviteLog, Warning, TEXT("SendFriendInvite Failed received a bad UniqueNetId!")); + OnFailure.Broadcast(); + return; + } + + if (!PlayerControllerWeakPtr.IsValid()) + { + // Fail immediately + UE_LOG(AdvancedSendFriendInviteLog, Warning, TEXT("SendFriendInvite Failed received a bad playercontroller!")); + OnFailure.Broadcast(); + return; + } + + FOnlineSubsystemBPCallHelperAdvanced Helper(TEXT("SendFriendInvite"), GEngine->GetWorldFromContextObject(WorldContextObject.Get(), EGetWorldErrorMode::LogAndReturnNull)); + + if (!Helper.OnlineSub) + { + OnFailure.Broadcast(); + return; + } + + auto Friends = Helper.OnlineSub->GetFriendsInterface(); + if (Friends.IsValid()) + { + ULocalPlayer* Player = Cast(PlayerControllerWeakPtr->Player); + + if (!Player) + { + // Fail immediately + UE_LOG(AdvancedSendFriendInviteLog, Warning, TEXT("SendFriendInvite Failed couldn't cast to ULocalPlayer!")); + OnFailure.Broadcast(); + return; + } + + Friends->SendInvite(Player->GetControllerId(), *cUniqueNetId.GetUniqueNetId(), EFriendsLists::ToString((EFriendsLists::Default)), OnSendInviteCompleteDelegate); + return; + } + // Fail immediately + OnFailure.Broadcast(); +} + +void USendFriendInviteCallbackProxy::OnSendInviteComplete(int32 LocalPlayerNum, bool bWasSuccessful, const FUniqueNetId &InvitedPlayer, const FString &ListName, const FString &ErrorString) +{ + if ( bWasSuccessful ) + { + OnSuccess.Broadcast(); + } + else + { + UE_LOG(AdvancedSendFriendInviteLog, Warning, TEXT("SendFriendInvite Failed with error: %s"), *ErrorString); + OnFailure.Broadcast(); + } +} diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/StartSessionCallbackProxyAdvanced.cpp b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/StartSessionCallbackProxyAdvanced.cpp new file mode 100644 index 0000000..d41e428 --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/StartSessionCallbackProxyAdvanced.cpp @@ -0,0 +1,58 @@ +#include "StartSessionCallbackProxyAdvanced.h" + +UStartSessionCallbackProxyAdvanced::UStartSessionCallbackProxyAdvanced(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) + , StartCompleteDelegate(FOnStartSessionCompleteDelegate::CreateUObject(this, &ThisClass::OnStartCompleted)) +{ +} + +UStartSessionCallbackProxyAdvanced* UStartSessionCallbackProxyAdvanced::StartAdvancedSession( + UObject* WorldContextObject) +{ + UStartSessionCallbackProxyAdvanced* Proxy = NewObject(); + Proxy->WorldContextObject = WorldContextObject; + return Proxy; +} + +void UStartSessionCallbackProxyAdvanced::Activate() +{ + const FOnlineSubsystemBPCallHelperAdvanced Helper(TEXT("StartSession"), GEngine->GetWorldFromContextObject(WorldContextObject.Get(), EGetWorldErrorMode::LogAndReturnNull)); + + if (Helper.OnlineSub != nullptr) + { + const auto Sessions = Helper.OnlineSub->GetSessionInterface(); + if (Sessions.IsValid()) + { + StartCompleteDelegateHandle = Sessions->AddOnStartSessionCompleteDelegate_Handle(StartCompleteDelegate); + Sessions->StartSession(NAME_GameSession); + return; + } + FFrame::KismetExecutionMessage(TEXT("Sessions not supported by Online Subsystem"), ELogVerbosity::Warning); + } + + // Fail immediately + OnFailure.Broadcast(); +} + +void UStartSessionCallbackProxyAdvanced::OnStartCompleted(FName SessionName, bool bWasSuccessful) +{ + FOnlineSubsystemBPCallHelperAdvanced Helper(TEXT("StartSessionCallback"), GEngine->GetWorldFromContextObject(WorldContextObject.Get(), EGetWorldErrorMode::LogAndReturnNull)); + + if (Helper.OnlineSub != nullptr) + { + auto Sessions = Helper.OnlineSub->GetSessionInterface(); + if (Sessions.IsValid()) + { + Sessions->ClearOnStartSessionCompleteDelegate_Handle(StartCompleteDelegateHandle); + } + } + + if (bWasSuccessful) + { + OnSuccess.Broadcast(); + } + else + { + OnFailure.Broadcast(); + } +} \ No newline at end of file diff --git a/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/UpdateSessionCallbackProxyAdvanced.cpp b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/UpdateSessionCallbackProxyAdvanced.cpp new file mode 100644 index 0000000..31aa9d9 --- /dev/null +++ b/Plugins/AdvancedSessions/Source/AdvancedSessions/Private/UpdateSessionCallbackProxyAdvanced.cpp @@ -0,0 +1,130 @@ +// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. +#include "UpdateSessionCallbackProxyAdvanced.h" + + +////////////////////////////////////////////////////////////////////////// +// UUpdateSessionCallbackProxyAdvanced + +UUpdateSessionCallbackProxyAdvanced::UUpdateSessionCallbackProxyAdvanced(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) + , OnUpdateSessionCompleteDelegate(FOnUpdateSessionCompleteDelegate::CreateUObject(this, &ThisClass::OnUpdateCompleted)) + , NumPublicConnections(1) +{ +} + +UUpdateSessionCallbackProxyAdvanced* UUpdateSessionCallbackProxyAdvanced::UpdateSession(UObject* WorldContextObject, const TArray &ExtraSettings, int32 PublicConnections, int32 PrivateConnections, bool bUseLAN, bool bAllowInvites, bool bAllowJoinInProgress, bool bRefreshOnlineData, bool bIsDedicatedServer, bool bShouldAdvertise) +{ + UUpdateSessionCallbackProxyAdvanced* Proxy = NewObject(); + Proxy->NumPublicConnections = PublicConnections; + Proxy->NumPrivateConnections = PrivateConnections; + Proxy->bUseLAN = bUseLAN; + Proxy->WorldContextObject = WorldContextObject; + Proxy->bAllowInvites = bAllowInvites; + Proxy->ExtraSettings = ExtraSettings; + Proxy->bRefreshOnlineData = bRefreshOnlineData; + Proxy->bAllowJoinInProgress = bAllowJoinInProgress; + Proxy->bDedicatedServer = bIsDedicatedServer; + Proxy->bShouldAdvertise = bShouldAdvertise; + return Proxy; +} + +void UUpdateSessionCallbackProxyAdvanced::Activate() +{ + const FOnlineSubsystemBPCallHelperAdvanced Helper(TEXT("UpdateSession"), GEngine->GetWorldFromContextObject(WorldContextObject.Get(), EGetWorldErrorMode::LogAndReturnNull)); + + if (Helper.OnlineSub != nullptr) + { + const auto Sessions = Helper.OnlineSub->GetSessionInterface(); + if (Sessions.IsValid()) + { + if (Sessions->GetNumSessions() < 1) + { + OnFailure.Broadcast(); + GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("NO REGISTERED SESSIONS!")); + return; + } + + // This gets the actual session itself + //FNamedOnlineSession * curSession = Sessions->GetNamedSession(NAME_GameSession); + FOnlineSessionSettings* Settings = Sessions->GetSessionSettings(NAME_GameSession); + + if (!Settings) + { + // Fail immediately + OnFailure.Broadcast(); + return; + } + + OnUpdateSessionCompleteDelegateHandle = Sessions->AddOnUpdateSessionCompleteDelegate_Handle(OnUpdateSessionCompleteDelegate); + + // FOnlineSessionSettings Settings; + //Settings->BuildUniqueId = GetBuildUniqueId(); + Settings->NumPublicConnections = NumPublicConnections; + Settings->NumPrivateConnections = NumPrivateConnections; + Settings->bShouldAdvertise = bShouldAdvertise; + Settings->bAllowJoinInProgress = bAllowJoinInProgress; + Settings->bIsLANMatch = bUseLAN; + //Settings->bUsesPresence = true; + //Settings->bAllowJoinViaPresence = true; + Settings->bAllowInvites = bAllowInvites; + Settings->bAllowJoinInProgress = bAllowJoinInProgress; + Settings->bIsDedicated = bDedicatedServer; + + FOnlineSessionSetting * fSetting = NULL; + FOnlineSessionSetting ExtraSetting; + for (int i = 0; i < ExtraSettings.Num(); i++) + { + fSetting = Settings->Settings.Find(ExtraSettings[i].Key); + + if (fSetting) + { + fSetting->Data = ExtraSettings[i].Data; + } + else + { + ExtraSetting.Data = ExtraSettings[i].Data; + ExtraSetting.AdvertisementType = EOnlineDataAdvertisementType::ViaOnlineService; + Settings->Settings.Add(ExtraSettings[i].Key, ExtraSetting); + } + } + + Sessions->UpdateSession(NAME_GameSession, *Settings, bRefreshOnlineData); + + // OnUpdateCompleted will get called, nothing more to do now + return; + } + else + { + FFrame::KismetExecutionMessage(TEXT("Sessions not supported by Online Subsystem"), ELogVerbosity::Warning); + } + } + // Fail immediately + OnFailure.Broadcast(); + GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("Sessions not supported")); +} + +void UUpdateSessionCallbackProxyAdvanced::OnUpdateCompleted(FName SessionName, bool bWasSuccessful) +{ + const FOnlineSubsystemBPCallHelperAdvanced Helper(TEXT("UpdateSessionCallback"), GEngine->GetWorldFromContextObject(WorldContextObject.Get(), EGetWorldErrorMode::LogAndReturnNull)); + + if (Helper.OnlineSub != nullptr) + { + const auto Sessions = Helper.OnlineSub->GetSessionInterface(); + if (Sessions.IsValid()) + { + Sessions->ClearOnUpdateSessionCompleteDelegate_Handle(OnUpdateSessionCompleteDelegateHandle); + + if (bWasSuccessful) + { + OnSuccess.Broadcast(); + return; + } + } + } + + if (!bWasSuccessful) + { + OnFailure.Broadcast(); + GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("WAS NOT SUCCESSFUL")); + } +} \ No newline at end of file diff --git a/Plugins/AdvancedSteamSessions/AdvancedSteamSessions.uplugin b/Plugins/AdvancedSteamSessions/AdvancedSteamSessions.uplugin new file mode 100644 index 0000000..307c51e --- /dev/null +++ b/Plugins/AdvancedSteamSessions/AdvancedSteamSessions.uplugin @@ -0,0 +1,42 @@ +{ + "FileVersion" : 3, + + "FriendlyName" : "Advanced Steam Sessions", + "Version" : 5.4, + "VersionName": "5.4", + "Description" : "Adds new blueprint functions to handle more advanced session operations in Steam. REQUIRES ADVANCED SESSIONS", + "Category" : "Advanced Sessions Plugin", + "CreatedBy" : "Joshua Statzer", + "CreatedByURL" : "N/A", + + "Modules" : + [ + { + "Name": "AdvancedSteamSessions", + "Type": "RunTime", + "LoadingPhase": "Default" + } + ], + "Plugins": [ + { + "Name": "AdvancedSessions", + "Enabled": true + }, + { + "Name": "OnlineSubsystem", + "Enabled": true + }, + { + "Name": "OnlineSubsystemSteam", + "Enabled": true + }, + { + "Name": "OnlineSubsystemUtils", + "Enabled": true + }, + { + "Name": "SteamShared", + "Enabled": true + } + ] +} \ No newline at end of file diff --git a/Plugins/AdvancedSteamSessions/Config/FilterPlugin.ini b/Plugins/AdvancedSteamSessions/Config/FilterPlugin.ini new file mode 100644 index 0000000..ccebca2 --- /dev/null +++ b/Plugins/AdvancedSteamSessions/Config/FilterPlugin.ini @@ -0,0 +1,8 @@ +[FilterPlugin] +; This section lists additional files which will be packaged along with your plugin. Paths should be listed relative to the root plugin directory, and +; may include "...", "*", and "?" wildcards to match directories, files, and individual characters respectively. +; +; Examples: +; /README.txt +; /Extras/... +; /Binaries/ThirdParty/*.dll diff --git a/Plugins/AdvancedSteamSessions/Resources/Icon128.png b/Plugins/AdvancedSteamSessions/Resources/Icon128.png new file mode 100644 index 0000000..c7bbea3 Binary files /dev/null and b/Plugins/AdvancedSteamSessions/Resources/Icon128.png differ diff --git a/Plugins/AdvancedSteamSessions/Source/AdvancedSteamSessions/AdvancedSteamSessions.Build.cs b/Plugins/AdvancedSteamSessions/Source/AdvancedSteamSessions/AdvancedSteamSessions.Build.cs new file mode 100644 index 0000000..6a4c768 --- /dev/null +++ b/Plugins/AdvancedSteamSessions/Source/AdvancedSteamSessions/AdvancedSteamSessions.Build.cs @@ -0,0 +1,22 @@ +using UnrealBuildTool; +using System.IO; + +public class AdvancedSteamSessions : ModuleRules +{ + public AdvancedSteamSessions(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; + //bEnforceIWYU = true; + + PublicDefinitions.Add("WITH_ADVANCED_STEAM_SESSIONS=1"); + + PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "OnlineSubsystem", "CoreUObject", "OnlineSubsystemUtils", "Networking", "Sockets", "AdvancedSessions"/*"Voice", "OnlineSubsystemSteam"*/ }); + PrivateDependencyModuleNames.AddRange(new string[] { "OnlineSubsystem", "Sockets", "Networking", "OnlineSubsystemUtils" /*"Voice", "Steamworks","OnlineSubsystemSteam"*/}); + + if ((Target.Platform == UnrealTargetPlatform.Win64) || (Target.Platform == UnrealTargetPlatform.Linux) || (Target.Platform == UnrealTargetPlatform.Mac)) + { + PublicDependencyModuleNames.AddRange(new string[] { "SteamShared", "Steamworks", "OnlineSubsystemSteam" }); + //PublicIncludePaths.AddRange(new string[] { "../Plugins/Online/OnlineSubsystemSteam/Source/Private" });// This is dumb but it isn't very open + } + } +} \ No newline at end of file diff --git a/Plugins/AdvancedSteamSessions/Source/AdvancedSteamSessions/Classes/AdvancedSteamFriendsLibrary.h b/Plugins/AdvancedSteamSessions/Source/AdvancedSteamSessions/Classes/AdvancedSteamFriendsLibrary.h new file mode 100644 index 0000000..83de461 --- /dev/null +++ b/Plugins/AdvancedSteamSessions/Source/AdvancedSteamSessions/Classes/AdvancedSteamFriendsLibrary.h @@ -0,0 +1,389 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once +#include "CoreMinimal.h" +#include "BlueprintDataDefinitions.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "Online.h" +#include "OnlineSubsystem.h" +#include "Interfaces/OnlineFriendsInterface.h" +#include "Interfaces/OnlineUserInterface.h" +#include "Interfaces/OnlineMessageInterface.h" +#include "Interfaces/OnlinePresenceInterface.h" +#include "Engine/GameInstance.h" +#include "Interfaces/OnlineSessionInterface.h" +#include "BlueprintDataDefinitions.h" +#include "UObject/UObjectIterator.h" + +// This is taken directly from UE4 - OnlineSubsystemSteamPrivatePCH.h as a fix for the array_count macro +// @todo Steam: Steam headers trigger secure-C-runtime warnings in Visual C++. Rather than mess with _CRT_SECURE_NO_WARNINGS, we'll just +// disable the warnings locally. Remove when this is fixed in the SDK +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4996) +// #TODO check back on this at some point +#pragma warning(disable:4265) // SteamAPI CCallback< specifically, this warning is off by default but 4.17 turned it on.... +#endif + +#if (PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX) && STEAM_SDK_INSTALLED + +#pragma push_macro("ARRAY_COUNT") +#undef ARRAY_COUNT + +#if USING_CODE_ANALYSIS +MSVC_PRAGMA(warning(push)) +MSVC_PRAGMA(warning(disable : ALL_CODE_ANALYSIS_WARNINGS)) +#endif // USING_CODE_ANALYSIS + +#include + +#if USING_CODE_ANALYSIS +MSVC_PRAGMA(warning(pop)) +#endif // USING_CODE_ANALYSIS + +#include +#include +//#include +#pragma pop_macro("ARRAY_COUNT") + +// @todo Steam: See above +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +// Making a copy of this here since the original is still in a private folder and is screwing with things +/** +* Steam specific implementation of the unique net id +*/ +class FUniqueNetIdSteam2 : + public FUniqueNetId +{ +PACKAGE_SCOPE: + /** Holds the net id for a player */ + uint64 UniqueNetId; + + /** Hidden on purpose */ + FUniqueNetIdSteam2() : + UniqueNetId(0) + { + } + + /** + * Copy Constructor + * + * @param Src the id to copy + */ + explicit FUniqueNetIdSteam2(const FUniqueNetIdSteam2& Src) : + UniqueNetId(Src.UniqueNetId) + { + } + +public: + /** + * Constructs this object with the specified net id + * + * @param InUniqueNetId the id to set ours to + */ + explicit FUniqueNetIdSteam2(uint64 InUniqueNetId) : + UniqueNetId(InUniqueNetId) + { + } + + /** + * Constructs this object with the steam id + * + * @param InUniqueNetId the id to set ours to + */ + explicit FUniqueNetIdSteam2(CSteamID InSteamId) : + UniqueNetId(InSteamId.ConvertToUint64()) + { + } + + /** + * Constructs this object with the specified net id + * + * @param String textual representation of an id + */ + explicit FUniqueNetIdSteam2(const FString& Str) : + UniqueNetId(FCString::Atoi64(*Str)) + { + } + + + /** + * Constructs this object with the specified net id + * + * @param InUniqueNetId the id to set ours to (assumed to be FUniqueNetIdSteam in fact) + */ + explicit FUniqueNetIdSteam2(const FUniqueNetId& InUniqueNetId) : + UniqueNetId(*(uint64*)InUniqueNetId.GetBytes()) + { + } + + virtual FName GetType() const override + { + return STEAM_SUBSYSTEM; + } + + /** + * Get the raw byte representation of this net id + * This data is platform dependent and shouldn't be manipulated directly + * + * @return byte array of size GetSize() + */ + virtual const uint8* GetBytes() const override + { + return (uint8*)&UniqueNetId; + } + + /** + * Get the size of the id + * + * @return size in bytes of the id representation + */ + virtual int32 GetSize() const override + { + return sizeof(uint64); + } + + /** + * Check the validity of the id + * + * @return true if this is a well formed ID, false otherwise + */ + virtual bool IsValid() const override + { + return UniqueNetId != 0 && CSteamID(UniqueNetId).IsValid(); + } + + /** + * Platform specific conversion to string representation of data + * + * @return data in string form + */ + virtual FString ToString() const override + { + return FString::Printf(TEXT("%llu"), UniqueNetId); + } + + /** + * Get a human readable representation of the net id + * Shouldn't be used for anything other than logging/debugging + * + * @return id in string form + */ + virtual FString ToDebugString() const override + { + CSteamID SteamID(UniqueNetId); + if (SteamID.IsLobby()) + { + return FString::Printf(TEXT("Lobby [0x%llX]"), UniqueNetId); + } + else if (SteamID.BAnonGameServerAccount()) + { + return FString::Printf(TEXT("Server [0x%llX]"), UniqueNetId); + } + else if (SteamID.IsValid()) + { + const FString NickName(SteamFriends() ? UTF8_TO_TCHAR(SteamFriends()->GetFriendPersonaName(UniqueNetId)) : TEXT("UNKNOWN")); + return FString::Printf(TEXT("%s [0x%llX]"), *NickName, UniqueNetId); + } + else + { + return FString::Printf(TEXT("INVALID [0x%llX]"), UniqueNetId); + } + } + + + virtual uint32 GetTypeHash() const override + { + return ::GetTypeHash(UniqueNetId); + } + + /** Convenience cast to CSteamID */ + operator CSteamID() + { + return UniqueNetId; + } + + /** Convenience cast to CSteamID */ + operator const CSteamID() const + { + return UniqueNetId; + } + + /** Convenience cast to CSteamID pointer */ + operator CSteamID*() + { + return (CSteamID*)&UniqueNetId; + } + + /** Convenience cast to CSteamID pointer */ + operator const CSteamID*() const + { + return (const CSteamID*)&UniqueNetId; + } + + friend FArchive& operator<<(FArchive& Ar, FUniqueNetIdSteam2& UserId) + { + return Ar << UserId.UniqueNetId; + } +}; + +#endif + +#include "AdvancedSteamFriendsLibrary.generated.h" + + +//General Advanced Sessions Log +DECLARE_LOG_CATEGORY_EXTERN(AdvancedSteamFriendsLog, Log, All); + +UENUM(Blueprintable) +enum class SteamAvatarSize : uint8 +{ + SteamAvatar_INVALID = 0, + SteamAvatar_Small = 1, + SteamAvatar_Medium = 2, + SteamAvatar_Large = 3 +}; + +UENUM(Blueprintable) +enum class ESteamUserOverlayType : uint8 +{ + /*Opens the overlay web browser to the specified user or groups profile.*/ + steamid, + /*Opens a chat window to the specified user, or joins the group chat.*/ + chat, + /*Opens a window to a Steam Trading session that was started with the ISteamEconomy / StartTrade Web API.*/ + jointrade, + /*Opens the overlay web browser to the specified user's stats.*/ + stats, + /*Opens the overlay web browser to the specified user's achievements.*/ + achievements, + /*Opens the overlay in minimal mode prompting the user to add the target user as a friend.*/ + friendadd, + /*Opens the overlay in minimal mode prompting the user to remove the target friend.*/ + friendremove, + /*Opens the overlay in minimal mode prompting the user to accept an incoming friend invite.*/ + friendrequestaccept, + /*Opens the overlay in minimal mode prompting the user to ignore an incoming friend invite.*/ + friendrequestignore, + /*Opens the invite overlay, invitations sent from this dialog will be for the provided lobby*/ + invitetolobby +}; + +static FString EnumToString(const FString& enumName, uint8 value) +{ + + const UEnum* EnumPtr = FindFirstObject(*enumName, EFindFirstObjectOptions::None, ELogVerbosity::Warning, TEXT("EumtoString")); + + if (!EnumPtr) + return FString(); + + FString EnumName = EnumPtr->GetNameStringByIndex(value); + return EnumName; +} + + +USTRUCT(BlueprintType, Category = "Online|SteamAPI|SteamGroups") +struct FBPSteamGroupInfo +{ + GENERATED_USTRUCT_BODY() + +public: + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|SteamAPI|SteamGroups") + FBPUniqueNetId GroupID; // Uint64 representation + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|SteamAPI|SteamGroups") + FString GroupName; + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|SteamAPI|SteamGroups") + FString GroupTag; + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|SteamAPI|SteamGroups") + int32 numOnline = 0; + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|SteamAPI|SteamGroups") + int32 numInGame = 0; + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|SteamAPI|SteamGroups") + int32 numChatting = 0; + +}; + +UENUM(Blueprintable) +enum class EBPTextFilteringContext : uint8 +{ + /*Unknown context.*/ + FContext_Unknown = 0, + /*Game content, only legally required filtering is performed.*/ + FContext_GameContent = 1, + /*Char from another player.*/ + FContext_Chat = 2, + /*Character or item name.*/ + FContext_Name = 3 +}; + +UCLASS() +class UAdvancedSteamFriendsLibrary : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() +public: + + //********* Friend List Functions *************// + + // Get a texture of a valid friends avatar, STEAM ONLY, Returns invalid texture if the subsystem hasn't loaded that size of avatar yet + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedFriends|SteamAPI", meta = (ExpandEnumAsExecs = "Result")) + static UTexture2D * GetSteamFriendAvatar(const FBPUniqueNetId UniqueNetId, EBlueprintAsyncResultSwitch &Result, SteamAvatarSize AvatarSize = SteamAvatarSize::SteamAvatar_Medium); + + // Preloads the avatar and name of a steam friend, return whether it is already available or not, STEAM ONLY, Takes time to actually load everything after this is called. + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedFriends|SteamAPI") + static bool RequestSteamFriendInfo(const FBPUniqueNetId UniqueNetId, bool bRequireNameOnly = false); + + // Opens the steam overlay to go to the specified user dialog + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedFriends|SteamAPI") + static bool OpenSteamUserOverlay(const FBPUniqueNetId UniqueNetId, ESteamUserOverlayType DialogType); + + // Returns if the steam overlay is currently active (this can return false during initial overlay hooking) + UFUNCTION(BlueprintPure, Category = "Online|AdvancedFriends|SteamAPI") + static bool IsOverlayEnabled(); + + // Gets the level of a friends steam account, STEAM ONLY, Returns -1 if the steam level is not known, might need RequestSteamFriendInfo called first. + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedFriends|SteamAPI") + static int32 GetFriendSteamLevel(const FBPUniqueNetId UniqueNetId); + + // Gets the persona name of a steam ID, STEAM ONLY, Returns empty if no result, might need RequestSteamFriendInfo called first. + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedFriends|SteamAPI") + static FString GetSteamPersonaName(const FBPUniqueNetId UniqueNetId); + + // Creates a unique steam id directly from a string holding a uint64 value, useful for testing + UFUNCTION(BlueprintPure, Category = "Online|AdvancedFriends|SteamAPI") + static FBPUniqueNetId CreateSteamIDFromString(const FString SteamID64); + + // Retreives the local steam ID from steam + UFUNCTION(BlueprintPure, Category = "Online|AdvancedFriends|SteamAPI") + static FBPUniqueNetId GetLocalSteamIDFromSteam(); + + /* Gets the current game played by a friend - AppID is int32 even though steam ids are uint32, can't be helped in blueprint currently + * can use the AppID with the WebAPI GetAppList request. + */ + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedFriends|SteamAPI", meta = (ExpandEnumAsExecs = "Result")) + static void GetSteamFriendGamePlayed(const FBPUniqueNetId UniqueNetId, EBlueprintResultSwitch &Result/*, FString & GameName*/, int32 & AppID); + + // Get a full list of steam groups + UFUNCTION(BlueprintCallable, Category = "Online|SteamAPI|SteamGroups") + static void GetSteamGroups(TArray & SteamGroups); + + // Initializes text filtering (pre-loading dictonaries) + // Returns if it succeeded, false if filtering is unavailable for the games language + UFUNCTION(BlueprintCallable, Category = "Online|SteamAPI|TextFiltering") + static bool InitTextFiltering(); + + // Attempts to filter a string with the given filtering context + // Returns true if the text has been filtered, false if it hasn't (no filtering required or operation failed) + // If false it will still output the original text + // Textsource is the steam id that is the source of the text (player name / chat) + // Requires that InitTextFiltering be called first!! + UFUNCTION(BlueprintCallable, Category = "Online|SteamAPI|TextFiltering") + static bool FilterText(FString TextToFilter, EBPTextFilteringContext Context, const FBPUniqueNetId TextSourceID, FString& FilteredText); + + // Returns if steam is running in big picture mode + UFUNCTION(BlueprintPure, Category = "Online|SteamAPI") + static bool IsSteamInBigPictureMode(); +}; diff --git a/Plugins/AdvancedSteamSessions/Source/AdvancedSteamSessions/Classes/AdvancedSteamSessions.h b/Plugins/AdvancedSteamSessions/Source/AdvancedSteamSessions/Classes/AdvancedSteamSessions.h new file mode 100644 index 0000000..4a49251 --- /dev/null +++ b/Plugins/AdvancedSteamSessions/Source/AdvancedSteamSessions/Classes/AdvancedSteamSessions.h @@ -0,0 +1,12 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Modules/ModuleManager.h" + +class AdvancedSteamSessions : public IModuleInterface +{ +public: + /** IModuleInterface implementation */ + void StartupModule(); + void ShutdownModule(); +}; \ No newline at end of file diff --git a/Plugins/AdvancedSteamSessions/Source/AdvancedSteamSessions/Classes/AdvancedSteamWorkshopLibrary.h b/Plugins/AdvancedSteamSessions/Source/AdvancedSteamSessions/Classes/AdvancedSteamWorkshopLibrary.h new file mode 100644 index 0000000..db56b35 --- /dev/null +++ b/Plugins/AdvancedSteamSessions/Source/AdvancedSteamSessions/Classes/AdvancedSteamWorkshopLibrary.h @@ -0,0 +1,351 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once +#include "CoreMinimal.h" +#include "BlueprintDataDefinitions.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "Online.h" +#include "OnlineSubsystem.h" +#if (PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX) && STEAM_SDK_INSTALLED +#include "steam/isteamugc.h" +#include "steam/isteamremotestorage.h" +#endif +#include "Interfaces/OnlineSessionInterface.h" + +// @todo Steam: Steam headers trigger secure-C-runtime warnings in Visual C++. Rather than mess with _CRT_SECURE_NO_WARNINGS, we'll just +// disable the warnings locally. Remove when this is fixed in the SDK +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4996) +// #TODO check back on this at some point +#pragma warning(disable:4265) // SteamAPI CCallback< specifically, this warning is off by default but 4.17 turned it on.... +#endif + +#if (PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX) && STEAM_SDK_INSTALLED + +#pragma push_macro("ARRAY_COUNT") +#undef ARRAY_COUNT + +#if USING_CODE_ANALYSIS +MSVC_PRAGMA(warning(push)) +MSVC_PRAGMA(warning(disable : ALL_CODE_ANALYSIS_WARNINGS)) +#endif // USING_CODE_ANALYSIS + +#include + +#if USING_CODE_ANALYSIS +MSVC_PRAGMA(warning(pop)) +#endif // USING_CODE_ANALYSIS + + +#pragma pop_macro("ARRAY_COUNT") + +#endif + +// @todo Steam: See above +#ifdef _MSC_VER +#pragma warning(pop) +#endif + + +#include "AdvancedSteamWorkshopLibrary.generated.h" + + +//General Advanced Sessions Log +DECLARE_LOG_CATEGORY_EXTERN(AdvancedSteamWorkshopLog, Log, All); + + +// Using a custom struct because uint32 isn't blueprint supported and I don't want to cast to int32 +// due to the size of the workshop it could end up overflowing? +USTRUCT(BlueprintType) +struct FBPSteamWorkshopID +{ + GENERATED_USTRUCT_BODY() + +public: + + uint64 SteamWorkshopID; + + FBPSteamWorkshopID() + { + + } + + FBPSteamWorkshopID(uint64 ID) + { + SteamWorkshopID = ID; + } +}; + + +// General result codes - Copying steams version over +// Check these to future proof +UENUM(BlueprintType) +enum class FBPSteamResult : uint8 +{ + K_EResultInvalid = 0, + k_EResultOK = 1, // success + k_EResultFail = 2, // generic failure + k_EResultNoConnection = 3, // no/failed network connection + // k_EResultNoConnectionRetry = 4, // OBSOLETE - removed + k_EResultInvalidPassword = 5, // password/ticket is invalid + k_EResultLoggedInElsewhere = 6, // same user logged in elsewhere + k_EResultInvalidProtocolVer = 7, // protocol version is incorrect + k_EResultInvalidParam = 8, // a parameter is incorrect + k_EResultFileNotFound = 9, // file was not found + k_EResultBusy = 10, // called method busy - action not taken + k_EResultInvalidState = 11, // called object was in an invalid state + k_EResultInvalidName = 12, // name is invalid + k_EResultInvalidEmail = 13, // email is invalid + k_EResultDuplicateName = 14, // name is not unique + k_EResultAccessDenied = 15, // access is denied + k_EResultTimeout = 16, // operation timed out + k_EResultBanned = 17, // VAC2 banned + k_EResultAccountNotFound = 18, // account not found + k_EResultInvalidSteamID = 19, // steamID is invalid + k_EResultServiceUnavailable = 20, // The requested service is currently unavailable + k_EResultNotLoggedOn = 21, // The user is not logged on + k_EResultPending = 22, // Request is pending (may be in process, or waiting on third party) + k_EResultEncryptionFailure = 23, // Encryption or Decryption failed + k_EResultInsufficientPrivilege = 24, // Insufficient privilege + k_EResultLimitExceeded = 25, // Too much of a good thing + k_EResultRevoked = 26, // Access has been revoked (used for revoked guest passes) + k_EResultExpired = 27, // License/Guest pass the user is trying to access is expired + k_EResultAlreadyRedeemed = 28, // Guest pass has already been redeemed by account, cannot be acked again + k_EResultDuplicateRequest = 29, // The request is a duplicate and the action has already occurred in the past, ignored this time + k_EResultAlreadyOwned = 30, // All the games in this guest pass redemption request are already owned by the user + k_EResultIPNotFound = 31, // IP address not found + k_EResultPersistFailed = 32, // failed to write change to the data store + k_EResultLockingFailed = 33, // failed to acquire access lock for this operation + k_EResultLogonSessionReplaced = 34, + k_EResultConnectFailed = 35, + k_EResultHandshakeFailed = 36, + k_EResultIOFailure = 37, + k_EResultRemoteDisconnect = 38, + k_EResultShoppingCartNotFound = 39, // failed to find the shopping cart requested + k_EResultBlocked = 40, // a user didn't allow it + k_EResultIgnored = 41, // target is ignoring sender + k_EResultNoMatch = 42, // nothing matching the request found + k_EResultAccountDisabled = 43, + k_EResultServiceReadOnly = 44, // this service is not accepting content changes right now + k_EResultAccountNotFeatured = 45, // account doesn't have value, so this feature isn't available + k_EResultAdministratorOK = 46, // allowed to take this action, but only because requester is admin + k_EResultContentVersion = 47, // A Version mismatch in content transmitted within the Steam protocol. + k_EResultTryAnotherCM = 48, // The current CM can't service the user making a request, user should try another. + k_EResultPasswordRequiredToKickSession = 49,// You are already logged in elsewhere, this cached credential login has failed. + k_EResultAlreadyLoggedInElsewhere = 50, // You are already logged in elsewhere, you must wait + k_EResultSuspended = 51, // Long running operation (content download) suspended/paused + k_EResultCancelled = 52, // Operation canceled (typically by user: content download) + k_EResultDataCorruption = 53, // Operation canceled because data is ill formed or unrecoverable + k_EResultDiskFull = 54, // Operation canceled - not enough disk space. + k_EResultRemoteCallFailed = 55, // an remote call or IPC call failed + k_EResultPasswordUnset = 56, // Password could not be verified as it's unset server side + k_EResultExternalAccountUnlinked = 57, // External account (PSN, Facebook...) is not linked to a Steam account + k_EResultPSNTicketInvalid = 58, // PSN ticket was invalid + k_EResultExternalAccountAlreadyLinked = 59, // External account (PSN, Facebook...) is already linked to some other account, must explicitly request to replace/delete the link first + k_EResultRemoteFileConflict = 60, // The sync cannot resume due to a conflict between the local and remote files + k_EResultIllegalPassword = 61, // The requested new password is not legal + k_EResultSameAsPreviousValue = 62, // new value is the same as the old one ( secret question and answer ) + k_EResultAccountLogonDenied = 63, // account login denied due to 2nd factor authentication failure + k_EResultCannotUseOldPassword = 64, // The requested new password is not legal + k_EResultInvalidLoginAuthCode = 65, // account login denied due to auth code invalid + k_EResultAccountLogonDeniedNoMail = 66, // account login denied due to 2nd factor auth failure - and no mail has been sent + k_EResultHardwareNotCapableOfIPT = 67, // + k_EResultIPTInitError = 68, // + k_EResultParentalControlRestricted = 69, // operation failed due to parental control restrictions for current user + k_EResultFacebookQueryError = 70, // Facebook query returned an error + k_EResultExpiredLoginAuthCode = 71, // account login denied due to auth code expired + k_EResultIPLoginRestrictionFailed = 72, + k_EResultAccountLockedDown = 73, + k_EResultAccountLogonDeniedVerifiedEmailRequired = 74, + k_EResultNoMatchingURL = 75, + k_EResultBadResponse = 76, // parse failure, missing field, etc. + k_EResultRequirePasswordReEntry = 77, // The user cannot complete the action until they re-enter their password + k_EResultValueOutOfRange = 78, // the value entered is outside the acceptable range + k_EResultUnexpectedError = 79, // something happened that we didn't expect to ever happen + k_EResultDisabled = 80, // The requested service has been configured to be unavailable + k_EResultInvalidCEGSubmission = 81, // The set of files submitted to the CEG server are not valid ! + k_EResultRestrictedDevice = 82, // The device being used is not allowed to perform this action + k_EResultRegionLocked = 83, // The action could not be complete because it is region restricted + k_EResultRateLimitExceeded = 84, // Temporary rate limit exceeded, try again later, different from k_EResultLimitExceeded which may be permanent + k_EResultAccountLoginDeniedNeedTwoFactor = 85, // Need two-factor code to login + k_EResultItemDeleted = 86, // The thing we're trying to access has been deleted + k_EResultAccountLoginDeniedThrottle = 87, // login attempt failed, try to throttle response to possible attacker + k_EResultTwoFactorCodeMismatch = 88, // two factor code mismatch + k_EResultTwoFactorActivationCodeMismatch = 89, // activation code for two-factor didn't match + k_EResultAccountAssociatedToMultiplePartners = 90, // account has been associated with multiple partners + k_EResultNotModified = 91, // data not modified +}; + +// Check these to future proof +UENUM(BlueprintType) +enum class FBPWorkshopFileType : uint8 +{ + k_EWorkshopFileTypeCommunity = 0, + k_EWorkshopFileTypeMicrotransaction = 1, + k_EWorkshopFileTypeCollection = 2, + k_EWorkshopFileTypeArt = 3, + k_EWorkshopFileTypeVideo = 4, + k_EWorkshopFileTypeScreenshot = 5, + k_EWorkshopFileTypeGame = 6, + k_EWorkshopFileTypeSoftware = 7, + k_EWorkshopFileTypeConcept = 8, + k_EWorkshopFileTypeWebGuide = 9, + k_EWorkshopFileTypeIntegratedGuide = 10, + k_EWorkshopFileTypeMerch = 11, + k_EWorkshopFileTypeControllerBinding = 12, + k_EWorkshopFileTypeSteamworksAccessInvite = 13, + k_EWorkshopFileTypeSteamVideo = 14, + + // Update k_EWorkshopFileTypeMax if you add values. + k_EWorkshopFileTypeMax = 15 +}; + +// WorkshopItemDetails Struct +USTRUCT(BlueprintType) +struct FBPSteamWorkshopItemDetails +{ + GENERATED_USTRUCT_BODY() + +public: + + FBPSteamWorkshopItemDetails() + { + ResultOfRequest = FBPSteamResult::k_EResultOK; + FileType = FBPWorkshopFileType::k_EWorkshopFileTypeMax; + CreatorAppID = 0; + ConsumerAppID = 0; + VotesUp = 0; + VotesDown = 0; + CalculatedScore = 0.f; + bBanned = false; + bAcceptedForUse = false; + bTagsTruncated = false; + } + +#if (PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX) && STEAM_SDK_INSTALLED + FBPSteamWorkshopItemDetails(SteamUGCDetails_t &hUGCDetails) + { + ResultOfRequest = (FBPSteamResult)hUGCDetails.m_eResult; + FileType = (FBPWorkshopFileType)hUGCDetails.m_eFileType; + CreatorAppID = (int32)hUGCDetails.m_nCreatorAppID; + ConsumerAppID = (int32)hUGCDetails.m_nConsumerAppID; + Title = FString(hUGCDetails.m_rgchTitle, k_cchPublishedDocumentTitleMax); + Description = FString(hUGCDetails.m_rgchDescription, k_cchPublishedDocumentDescriptionMax); + ItemUrl = FString(hUGCDetails.m_rgchURL, k_cchPublishedFileURLMax); + VotesUp = (int32)hUGCDetails.m_unVotesUp; + VotesDown = (int32)hUGCDetails.m_unVotesDown; + CalculatedScore = hUGCDetails.m_flScore; + bBanned = hUGCDetails.m_bBanned; + bAcceptedForUse = hUGCDetails.m_bAcceptedForUse; + bTagsTruncated = hUGCDetails.m_bTagsTruncated; + + CreatorSteamID = FString::Printf(TEXT("%llu"), hUGCDetails.m_ulSteamIDOwner); + } + + FBPSteamWorkshopItemDetails(const SteamUGCDetails_t &hUGCDetails) + { + ResultOfRequest = (FBPSteamResult)hUGCDetails.m_eResult; + FileType = (FBPWorkshopFileType)hUGCDetails.m_eFileType; + CreatorAppID = (int32)hUGCDetails.m_nCreatorAppID; + ConsumerAppID = (int32)hUGCDetails.m_nConsumerAppID; + Title = FString(hUGCDetails.m_rgchTitle, k_cchPublishedDocumentTitleMax); + Description = FString(hUGCDetails.m_rgchDescription, k_cchPublishedDocumentDescriptionMax); + ItemUrl = FString(hUGCDetails.m_rgchURL, k_cchPublishedFileURLMax); + VotesUp = (int32)hUGCDetails.m_unVotesUp; + VotesDown = (int32)hUGCDetails.m_unVotesDown; + CalculatedScore = hUGCDetails.m_flScore; + bBanned = hUGCDetails.m_bBanned; + bAcceptedForUse = hUGCDetails.m_bAcceptedForUse; + bTagsTruncated = hUGCDetails.m_bTagsTruncated; + + CreatorSteamID = FString::Printf(TEXT("%llu"), hUGCDetails.m_ulSteamIDOwner); + } +#endif + + // Result of obtaining the details + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|AdvancedSteamWorkshop") + FBPSteamResult ResultOfRequest; + + // Type of file + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|AdvancedSteamWorkshop") + FBPWorkshopFileType FileType; + + // These two are listed as baked to an int, but is stored as a uint, think its safe to keep int + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|AdvancedSteamWorkshop") + int32 CreatorAppID; + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|AdvancedSteamWorkshop") + int32 ConsumerAppID; + + // Title of item + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|AdvancedSteamWorkshop") + FString Title; + + // Description of item + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|AdvancedSteamWorkshop") + FString Description; + + //Url for a video of website + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|AdvancedSteamWorkshop") + FString ItemUrl; + + // Votes will be unlikely to go above signed limited + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|AdvancedSteamWorkshop") + int32 VotesUp; + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|AdvancedSteamWorkshop") + int32 VotesDown; + + // Calculated score + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|AdvancedSteamWorkshop") + float CalculatedScore; + + // whether the file was banned + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|AdvancedSteamWorkshop") + bool bBanned; + + // developer has specifically flagged this item as accepted in the Workshop + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|AdvancedSteamWorkshop") + bool bAcceptedForUse; + + // whether the list of tags was too long to be returned in the provided buffer + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|AdvancedSteamWorkshop") + bool bTagsTruncated; + + // Steam ID of the user who created this content. + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|AdvancedSteamWorkshop") + FString CreatorSteamID; + + /* + PublishedFileId_t m_nPublishedFileId; + uint32 m_rtimeCreated; // time when the published file was created + uint32 m_rtimeUpdated; // time when the published file was last updated + uint32 m_rtimeAddedToUserList; // time when the user added the published file to their list (not always applicable) + ERemoteStoragePublishedFileVisibility m_eVisibility; // visibility + char m_rgchTags[k_cchTagListMax]; // comma separated list of all tags associated with this file + // file/url information + UGCHandle_t m_hFile; // The handle of the primary file + UGCHandle_t m_hPreviewFile; // The handle of the preview file + char m_pchFileName[k_cchFilenameMax]; // The cloud filename of the primary file + int32 m_nFileSize; // Size of the primary file + int32 m_nPreviewFileSize; // Size of the preview file + uint32 m_unNumChildren; // if m_eFileType == k_EWorkshopFileTypeCollection, then this number will be the number of children contained within the collection + */ + +}; + +UCLASS() +class UAdvancedSteamWorkshopLibrary : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() +public: + + //********* Steam Functions *************// + + // Returns IDs for subscribed workshop items, TArray length dictates how many + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedSteamWorkshop") + static TArray GetSubscribedWorkshopItems(int32 & NumberOfItems); + + UFUNCTION(BlueprintCallable, Category = "Online|AdvancedSteamWorkshop") + static void GetNumSubscribedWorkshopItems(int32 & NumberOfItems); + +}; diff --git a/Plugins/AdvancedSteamSessions/Source/AdvancedSteamSessions/Classes/SteamNotificationsSubsystem.h b/Plugins/AdvancedSteamSessions/Source/AdvancedSteamSessions/Classes/SteamNotificationsSubsystem.h new file mode 100644 index 0000000..7b8641a --- /dev/null +++ b/Plugins/AdvancedSteamSessions/Source/AdvancedSteamSessions/Classes/SteamNotificationsSubsystem.h @@ -0,0 +1,87 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Subsystems/GameInstanceSubsystem.h" + +#if (PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX) && STEAM_SDK_INSTALLED + +#include + +#endif + +#include "SteamNotificationsSubsystem.generated.h" + +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnSteamOverlayActivated, bool, bOverlayState); + +UCLASS() +class ADVANCEDSTEAMSESSIONS_API USteamNotificationsSubsystem : public UGameInstanceSubsystem +{ + GENERATED_BODY() + +public: + + // Event thrown when the steam overlay switches states + UPROPERTY(BlueprintAssignable, Category = "SteamEvents") + FOnSteamOverlayActivated OnSteamOverlayActivated_Bind; + + USteamNotificationsSubsystem() : Super() + { + + } + + class cSteamEventsStore + { + public: + USteamNotificationsSubsystem* ParentSubsystem = nullptr; + void Initialize(USteamNotificationsSubsystem* MyParent) + { + ParentSubsystem = MyParent; + } + +#if (PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX) && STEAM_SDK_INSTALLED + cSteamEventsStore() : + OnExternalUITriggeredCallback(this, &cSteamEventsStore::OnExternalUITriggered) + { + + } +#else + //cSteamEventsStore() + //{ + + //} +#endif + + //~cSteamEventsStore(){} + + private: +#if (PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX) && STEAM_SDK_INSTALLED + STEAM_CALLBACK(cSteamEventsStore, OnExternalUITriggered, GameOverlayActivated_t, OnExternalUITriggeredCallback); +#endif + }; + + cSteamEventsStore MyEvents; + + /** Implement this for initialization of instances of the system */ + virtual void Initialize(FSubsystemCollectionBase& Collection) override + { + MyEvents.Initialize(this); + } + + /** Implement this for deinitialization of instances of the system */ + virtual void Deinitialize() override + { + + } +}; + +#if (PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX) && STEAM_SDK_INSTALLED +void USteamNotificationsSubsystem::cSteamEventsStore::OnExternalUITriggered(GameOverlayActivated_t* CallbackData) +{ + if (ParentSubsystem) + { + ParentSubsystem->OnSteamOverlayActivated_Bind.Broadcast((bool)CallbackData->m_bActive); + } +} +#endif \ No newline at end of file diff --git a/Plugins/AdvancedSteamSessions/Source/AdvancedSteamSessions/Classes/SteamRequestGroupOfficersCallbackProxy.h b/Plugins/AdvancedSteamSessions/Source/AdvancedSteamSessions/Classes/SteamRequestGroupOfficersCallbackProxy.h new file mode 100644 index 0000000..73955dd --- /dev/null +++ b/Plugins/AdvancedSteamSessions/Source/AdvancedSteamSessions/Classes/SteamRequestGroupOfficersCallbackProxy.h @@ -0,0 +1,100 @@ +// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. +#pragma once + +#include "CoreMinimal.h" +#include "BlueprintDataDefinitions.h" + +// This is taken directly from UE4 - OnlineSubsystemSteamPrivatePCH.h as a fix for the array_count macro + +// @todo Steam: Steam headers trigger secure-C-runtime warnings in Visual C++. Rather than mess with _CRT_SECURE_NO_WARNINGS, we'll just +// disable the warnings locally. Remove when this is fixed in the SDK +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4996) +// #TODO check back on this at some point +#pragma warning(disable:4265) // SteamAPI CCallback< specifically, this warning is off by default but 4.17 turned it on.... +#endif + +#if (PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX) && STEAM_SDK_INSTALLED + +//#include "OnlineSubsystemSteam.h" + +#pragma push_macro("ARRAY_COUNT") +#undef ARRAY_COUNT + +#if USING_CODE_ANALYSIS +MSVC_PRAGMA(warning(push)) +MSVC_PRAGMA(warning(disable : ALL_CODE_ANALYSIS_WARNINGS)) +#endif // USING_CODE_ANALYSIS + +#include + +#if USING_CODE_ANALYSIS +MSVC_PRAGMA(warning(pop)) +#endif // USING_CODE_ANALYSIS + + +#pragma pop_macro("ARRAY_COUNT") + +#endif + +// @todo Steam: See above +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#include "SteamRequestGroupOfficersCallbackProxy.generated.h" + +USTRUCT(BlueprintType, Category = "Online|SteamAPI|SteamGroups") +struct FBPSteamGroupOfficer +{ + GENERATED_USTRUCT_BODY() + +public: + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|SteamAPI|SteamGroups") + FBPUniqueNetId OfficerUniqueNetID; // Uint64 representation + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Online|SteamAPI|SteamGroups") + bool bIsOwner = false; + +}; + + +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FBlueprintGroupOfficerDetailsDelegate, const TArray &, OfficerList); + +UCLASS(MinimalAPI) +class USteamRequestGroupOfficersCallbackProxy : public UOnlineBlueprintCallProxyBase +{ + GENERATED_UCLASS_BODY() + + virtual ~USteamRequestGroupOfficersCallbackProxy(); + + // Called when there is a successful results return + UPROPERTY(BlueprintAssignable) + FBlueprintGroupOfficerDetailsDelegate OnSuccess; + + // Called when there is an unsuccessful results return + UPROPERTY(BlueprintAssignable) + FBlueprintGroupOfficerDetailsDelegate OnFailure; + + // Returns a list of steam group officers + UFUNCTION(BlueprintCallable, meta=(BlueprintInternalUseOnly = "true", WorldContext="WorldContextObject"), Category = "Online|SteamAPI|SteamGroups") + static USteamRequestGroupOfficersCallbackProxy* GetSteamGroupOfficerList(UObject* WorldContextObject, FBPUniqueNetId GroupUniqueNetID); + + // UOnlineBlueprintCallProxyBase interface + virtual void Activate() override; + // End of UOnlineBlueprintCallProxyBase interface + +private: + +#if (PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX) && STEAM_SDK_INSTALLED + void OnRequestGroupOfficerDetails( ClanOfficerListResponse_t *pResult, bool bIOFailure); + CCallResult m_callResultGroupOfficerRequestDetails; + +#endif + +private: + + FBPUniqueNetId GroupUniqueID; + UObject* WorldContextObject; +}; diff --git a/Plugins/AdvancedSteamSessions/Source/AdvancedSteamSessions/Classes/SteamWSRequestUGCDetailsCallbackProxy.h b/Plugins/AdvancedSteamSessions/Source/AdvancedSteamSessions/Classes/SteamWSRequestUGCDetailsCallbackProxy.h new file mode 100644 index 0000000..0adee7e --- /dev/null +++ b/Plugins/AdvancedSteamSessions/Source/AdvancedSteamSessions/Classes/SteamWSRequestUGCDetailsCallbackProxy.h @@ -0,0 +1,87 @@ +// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. +#pragma once + +#include "CoreMinimal.h" +#include "AdvancedSteamWorkshopLibrary.h" +#include "BlueprintDataDefinitions.h" + +// This is taken directly from UE4 - OnlineSubsystemSteamPrivatePCH.h as a fix for the array_count macro + +// @todo Steam: Steam headers trigger secure-C-runtime warnings in Visual C++. Rather than mess with _CRT_SECURE_NO_WARNINGS, we'll just +// disable the warnings locally. Remove when this is fixed in the SDK +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4996) +// #TODO check back on this at some point +#pragma warning(disable:4265) // SteamAPI CCallback< specifically, this warning is off by default but 4.17 turned it on.... +#endif + +#if (PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX) && STEAM_SDK_INSTALLED + +//#include "OnlineSubsystemSteam.h" + +#pragma push_macro("ARRAY_COUNT") +#undef ARRAY_COUNT + +#if USING_CODE_ANALYSIS +MSVC_PRAGMA(warning(push)) +MSVC_PRAGMA(warning(disable : ALL_CODE_ANALYSIS_WARNINGS)) +#endif // USING_CODE_ANALYSIS + +#include + +#if USING_CODE_ANALYSIS +MSVC_PRAGMA(warning(pop)) +#endif // USING_CODE_ANALYSIS + + +#pragma pop_macro("ARRAY_COUNT") + +#endif + +// @todo Steam: See above +#ifdef _MSC_VER +#pragma warning(pop) +#endif + + +#include "SteamWSRequestUGCDetailsCallbackProxy.generated.h" + +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FBlueprintWorkshopDetailsDelegate, const FBPSteamWorkshopItemDetails&, WorkShopDetails); + +UCLASS(MinimalAPI) +class USteamWSRequestUGCDetailsCallbackProxy : public UOnlineBlueprintCallProxyBase +{ + GENERATED_UCLASS_BODY() + + // Called when there is a successful results return + UPROPERTY(BlueprintAssignable) + FBlueprintWorkshopDetailsDelegate OnSuccess; + + // Called when there is an unsuccessful results return + UPROPERTY(BlueprintAssignable) + FBlueprintWorkshopDetailsDelegate OnFailure; + + // Ends the current session + UFUNCTION(BlueprintCallable, meta=(BlueprintInternalUseOnly = "true", WorldContext="WorldContextObject"), Category = "Online|AdvancedSteamWorkshop") + static USteamWSRequestUGCDetailsCallbackProxy* GetWorkshopItemDetails(UObject* WorldContextObject, FBPSteamWorkshopID WorkShopID); + + // UOnlineBlueprintCallProxyBase interface + virtual void Activate() override; + // End of UOnlineBlueprintCallProxyBase interface + +private: + +#if (PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX) && STEAM_SDK_INSTALLED + // Internal callback when the operation completes, calls out to the public success/failure callbacks + + void OnUGCRequestUGCDetails(SteamUGCQueryCompleted_t *pResult, bool bIOFailure); + CCallResult m_callResultUGCRequestDetails; + +#endif + +private: + + FBPSteamWorkshopID WorkShopID; + UObject* WorldContextObject; +}; diff --git a/Plugins/AdvancedSteamSessions/Source/AdvancedSteamSessions/Private/AdvancedSteamFriendsLibrary.cpp b/Plugins/AdvancedSteamSessions/Source/AdvancedSteamSessions/Private/AdvancedSteamFriendsLibrary.cpp new file mode 100644 index 0000000..85340e4 --- /dev/null +++ b/Plugins/AdvancedSteamSessions/Source/AdvancedSteamSessions/Private/AdvancedSteamFriendsLibrary.cpp @@ -0,0 +1,438 @@ +// Fill out your copyright notice in the Description page of Project Settings. +#include "AdvancedSteamFriendsLibrary.h" +#include "OnlineSubSystemHeader.h" + +//General Log +DEFINE_LOG_CATEGORY(AdvancedSteamFriendsLog); + + +// Clan functions, add in soon +/*int32 UAdvancedSteamFriendsLibrary::GetFriendSteamLevel(const FBPUniqueNetId UniqueNetId) +{ + +#if (PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX) && STEAM_SDK_INSTALLED + if (!UniqueNetId.IsValid() || !UniqueNetId.UniqueNetId->IsValid() || UniqueNetId.UniqueNetId->GetType() != STEAM_SUBSYSTEM) + { + UE_LOG(AdvancedSteamFriendsLog, Warning, TEXT("IsAFriend Had a bad UniqueNetId!")); + return 0; + } + + if (SteamAPI_Init()) + { + uint64 id = *((uint64*)UniqueNetId.UniqueNetId->GetBytes()); + + + // clan (group) iteration and access functions + //virtual int GetClanCount() = 0; + //virtual CSteamID GetClanByIndex(int iClan) = 0; + //virtual const char *GetClanName(CSteamID steamIDClan) = 0; + //virtual const char *GetClanTag(CSteamID steamIDClan) = 0; + // returns the most recent information we have about what's happening in a clan + //virtual bool GetClanActivityCounts(CSteamID steamIDClan, int *pnOnline, int *pnInGame, int *pnChatting) = 0; + // for clans a user is a member of, they will have reasonably up-to-date information, but for others you'll have to download the info to have the latest + //virtual SteamAPICall_t DownloadClanActivityCounts(ARRAY_COUNT(cClansToRequest) CSteamID *psteamIDClans, int cClansToRequest) = 0; + + // requests information about a clan officer list + // when complete, data is returned in ClanOfficerListResponse_t call result + // this makes available the calls below + // you can only ask about clans that a user is a member of + // note that this won't download avatars automatically; if you get an officer, + // and no avatar image is available, call RequestUserInformation( steamID, false ) to download the avatar + //virtual SteamAPICall_t RequestClanOfficerList(CSteamID steamIDClan) = 0; + + + // returns the steamID of the clan owner + //virtual CSteamID GetClanOwner(CSteamID steamIDClan) = 0; + // returns the number of officers in a clan (including the owner) + //virtual int GetClanOfficerCount(CSteamID steamIDClan) = 0; + // returns the steamID of a clan officer, by index, of range [0,GetClanOfficerCount) + //virtual CSteamID GetClanOfficerByIndex(CSteamID steamIDClan, int iOfficer) = 0; + + + return SteamFriends()->GetFriendSteamLevel(id); + } +#endif + + return 0; +}*/ + +void UAdvancedSteamFriendsLibrary::GetSteamGroups(TArray & SteamGroups) +{ + +#if (PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX) && STEAM_SDK_INSTALLED + + if (SteamAPI_Init()) + { + int numClans = SteamFriends()->GetClanCount(); + + for (int i = 0; i < numClans; i++) + { + CSteamID SteamGroupID = SteamFriends()->GetClanByIndex(i); + + if(!SteamGroupID.IsValid()) + continue; + + FBPSteamGroupInfo GroupInfo; + + TSharedPtr ValueID(new const FUniqueNetIdSteam2(SteamGroupID)); + GroupInfo.GroupID.SetUniqueNetId(ValueID); + SteamFriends()->GetClanActivityCounts(SteamGroupID, &GroupInfo.numOnline, &GroupInfo.numInGame, &GroupInfo.numChatting); + GroupInfo.GroupName = FString(UTF8_TO_TCHAR(SteamFriends()->GetClanName(SteamGroupID))); + GroupInfo.GroupTag = FString(UTF8_TO_TCHAR(SteamFriends()->GetClanTag(SteamGroupID))); + + SteamGroups.Add(GroupInfo); + } + } +#endif + +} + +void UAdvancedSteamFriendsLibrary::GetSteamFriendGamePlayed(const FBPUniqueNetId UniqueNetId, EBlueprintResultSwitch &Result/*, FString & GameName*/, int32 & AppID) +{ + +#if (PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX) && STEAM_SDK_INSTALLED + if (!UniqueNetId.IsValid() || !UniqueNetId.UniqueNetId->IsValid() || UniqueNetId.UniqueNetId->GetType() != STEAM_SUBSYSTEM) + { + UE_LOG(AdvancedSteamFriendsLog, Warning, TEXT("GetSteamFriendGamePlayed Had a bad UniqueNetId!")); + Result = EBlueprintResultSwitch::OnFailure; + return; + } + + if (SteamAPI_Init()) + { + uint64 id = *((uint64*)UniqueNetId.UniqueNetId->GetBytes()); + + FriendGameInfo_t GameInfo; + bool bIsInGame = SteamFriends()->GetFriendGamePlayed(id, &GameInfo); + + if (bIsInGame && GameInfo.m_gameID.IsValid()) + { + AppID = GameInfo.m_gameID.AppID(); + + // Forgot this test and left it in, it is incorrect, you would need restricted access + // And it would only find games in the local library anyway + /*char NameBuffer[512]; + int Len = SteamAppList()->GetAppName(GameInfo.m_gameID.AppID(), NameBuffer, 512); + + if (Len != -1) // Invalid + { + GameName = FString(UTF8_TO_TCHAR(NameBuffer)); + }*/ + + Result = EBlueprintResultSwitch::OnSuccess; + return; + } + + } +#endif + + Result = EBlueprintResultSwitch::OnFailure; +} + +int32 UAdvancedSteamFriendsLibrary::GetFriendSteamLevel(const FBPUniqueNetId UniqueNetId) +{ + +#if (PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX) && STEAM_SDK_INSTALLED + if (!UniqueNetId.IsValid() || !UniqueNetId.UniqueNetId->IsValid() || UniqueNetId.UniqueNetId->GetType() != STEAM_SUBSYSTEM) + { + UE_LOG(AdvancedSteamFriendsLog, Warning, TEXT("IsAFriend Had a bad UniqueNetId!")); + return 0; + } + + if (SteamAPI_Init()) + { + uint64 id = *((uint64*)UniqueNetId.UniqueNetId->GetBytes()); + + return SteamFriends()->GetFriendSteamLevel(id); + } +#endif + + return 0; +} + +FString UAdvancedSteamFriendsLibrary::GetSteamPersonaName(const FBPUniqueNetId UniqueNetId) +{ + +#if (PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX) && STEAM_SDK_INSTALLED + if (!UniqueNetId.IsValid() || !UniqueNetId.UniqueNetId->IsValid() || UniqueNetId.UniqueNetId->GetType() != STEAM_SUBSYSTEM) + { + UE_LOG(AdvancedSteamFriendsLog, Warning, TEXT("GetSteamPersonaName Had a bad UniqueNetId!")); + return FString(TEXT("")); + } + + if (SteamAPI_Init()) + { + uint64 id = *((uint64*)UniqueNetId.UniqueNetId->GetBytes()); + const char* PersonaName = SteamFriends()->GetFriendPersonaName(id); + return FString(UTF8_TO_TCHAR(PersonaName)); + } +#endif + + return FString(TEXT("")); +} + +FBPUniqueNetId UAdvancedSteamFriendsLibrary::CreateSteamIDFromString(const FString SteamID64) +{ + FBPUniqueNetId netId; + +#if (PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX) && STEAM_SDK_INSTALLED + if (!(SteamID64.Len() > 0)) + { + UE_LOG(AdvancedSteamFriendsLog, Warning, TEXT("CreateSteamIDFromString Had a bad UniqueNetId!")); + return netId; + } + + if (SteamAPI_Init()) + { + // Already does the conversion + TSharedPtr ValueID(new const FUniqueNetIdSteam2(SteamID64)); + //FCString::Atoi64(*SteamID64)); + + netId.SetUniqueNetId(ValueID); + return netId; + } +#endif + + return netId; +} + +FBPUniqueNetId UAdvancedSteamFriendsLibrary::GetLocalSteamIDFromSteam() +{ + FBPUniqueNetId netId; + +#if (PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX) && STEAM_SDK_INSTALLED + if (SteamAPI_Init()) + { + TSharedPtr SteamID(new const FUniqueNetIdSteam2(SteamUser()->GetSteamID())); + netId.SetUniqueNetId(SteamID); + } +#endif + + return netId; +} + +bool UAdvancedSteamFriendsLibrary::RequestSteamFriendInfo(const FBPUniqueNetId UniqueNetId, bool bRequireNameOnly) +{ +#if (PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX) && STEAM_SDK_INSTALLED + if (!UniqueNetId.IsValid() || !UniqueNetId.UniqueNetId->IsValid() || UniqueNetId.UniqueNetId->GetType() != STEAM_SUBSYSTEM) + { + UE_LOG(AdvancedSteamFriendsLog, Warning, TEXT("RequestSteamFriendInfo Had a bad UniqueNetId!")); + return false; + } + + if (SteamAPI_Init()) + { + uint64 id = *((uint64*)UniqueNetId.UniqueNetId->GetBytes()); + + return !SteamFriends()->RequestUserInformation(id, bRequireNameOnly); + } +#endif + + UE_LOG(AdvancedSteamFriendsLog, Warning, TEXT("RequestSteamFriendInfo Couldn't init steamAPI!")); + return false; +} + + +bool UAdvancedSteamFriendsLibrary::OpenSteamUserOverlay(const FBPUniqueNetId UniqueNetId, ESteamUserOverlayType DialogType) +{ +#if (PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX) && STEAM_SDK_INSTALLED + if (!UniqueNetId.IsValid() || !UniqueNetId.UniqueNetId->IsValid() || UniqueNetId.UniqueNetId->GetType() != STEAM_SUBSYSTEM) + { + UE_LOG(AdvancedSteamFriendsLog, Warning, TEXT("OpenSteamUserOverlay Had a bad UniqueNetId!")); + return false; + } + + if (SteamAPI_Init()) + { + uint64 id = *((uint64*)UniqueNetId.UniqueNetId->GetBytes()); + if (DialogType == ESteamUserOverlayType::invitetolobby) + { + SteamFriends()->ActivateGameOverlayInviteDialog(id); + } + else + { + FString DialogName = EnumToString("ESteamUserOverlayType", (uint8)DialogType); + SteamFriends()->ActivateGameOverlayToUser(TCHAR_TO_ANSI(*DialogName), id); + } + return true; + } +#endif + + UE_LOG(AdvancedSteamFriendsLog, Warning, TEXT("OpenSteamUserOverlay Couldn't init steamAPI!")); + return false; +} + +bool UAdvancedSteamFriendsLibrary::IsOverlayEnabled() +{ +#if (PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX) && STEAM_SDK_INSTALLED + if (SteamAPI_Init()) + { + return SteamUtils()->IsOverlayEnabled(); + } +#endif + + UE_LOG(AdvancedSteamFriendsLog, Warning, TEXT("OpenSteamUserOverlay Couldn't init steamAPI!")); + return false; +} + +UTexture2D * UAdvancedSteamFriendsLibrary::GetSteamFriendAvatar(const FBPUniqueNetId UniqueNetId, EBlueprintAsyncResultSwitch &Result, SteamAvatarSize AvatarSize) +{ +#if (PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX) && STEAM_SDK_INSTALLED + if (!UniqueNetId.IsValid() || !UniqueNetId.UniqueNetId->IsValid() || UniqueNetId.UniqueNetId->GetType() != STEAM_SUBSYSTEM) + { + UE_LOG(AdvancedSteamFriendsLog, Warning, TEXT("GetSteamFriendAvatar Had a bad UniqueNetId!")); + Result = EBlueprintAsyncResultSwitch::OnFailure; + return nullptr; + } + + uint32 Width = 0; + uint32 Height = 0; + + if (SteamAPI_Init()) + { + //Getting the PictureID from the SteamAPI and getting the Size with the ID + //virtual bool RequestUserInformation( CSteamID steamIDUser, bool bRequireNameOnly ) = 0; + + + uint64 id = *((uint64*)UniqueNetId.UniqueNetId->GetBytes()); + int Picture = 0; + + switch(AvatarSize) + { + case SteamAvatarSize::SteamAvatar_Small: Picture = SteamFriends()->GetSmallFriendAvatar(id); break; + case SteamAvatarSize::SteamAvatar_Medium: Picture = SteamFriends()->GetMediumFriendAvatar(id); break; + case SteamAvatarSize::SteamAvatar_Large: Picture = SteamFriends()->GetLargeFriendAvatar(id); break; + default: break; + } + + if (Picture == -1) + { + Result = EBlueprintAsyncResultSwitch::AsyncLoading; + return NULL; + } + + SteamUtils()->GetImageSize(Picture, &Width, &Height); + + // STOLEN FROM ANSWERHUB :p, then fixed because answerhub wasn't releasing the memory O.o + // Also fixed image pixel format and switched to a memcpy instead of manual iteration. + // At some point I should probably reply to that answerhub post with these fixes to prevent people killing their games..... + + if (Width > 0 && Height > 0) + { + //Creating the buffer "oAvatarRGBA" and then filling it with the RGBA Stream from the Steam Avatar + uint8 *oAvatarRGBA = new uint8[Width * Height * 4]; + + + //Filling the buffer with the RGBA Stream from the Steam Avatar and creating a UTextur2D to parse the RGBA Steam in + SteamUtils()->GetImageRGBA(Picture, (uint8*)oAvatarRGBA, 4 * Height * Width * sizeof(char)); + + + // Removed as I changed the image bit code to be RGB, I think the original author was unaware that there were different pixel formats + /* + //Swap R and B channels because for some reason the games whack + for (uint32 i = 0; i < (Width * Height * 4); i += 4) + { + uint8 Temp = oAvatarRGBA[i + 0]; + oAvatarRGBA[i + 0] = oAvatarRGBA[i + 2]; + oAvatarRGBA[i + 2] = Temp; + }*/ + + UTexture2D* Avatar = UTexture2D::CreateTransient(Width, Height, PF_R8G8B8A8); + // Switched to a Memcpy instead of byte by byte transer + + if (FTexturePlatformData* PlatformData = Avatar->GetPlatformData()) + { + uint8* MipData = (uint8*)PlatformData->Mips[0].BulkData.Lock(LOCK_READ_WRITE); + FMemory::Memcpy(MipData, (void*)oAvatarRGBA, Height * Width * 4); + PlatformData->Mips[0].BulkData.Unlock(); + + //Setting some Parameters for the Texture and finally returning it + PlatformData->SetNumSlices(1); + Avatar->NeverStream = true; + //Avatar->CompressionSettings = TC_EditorIcon; + } + + // Free RGBA buffer regardless of whether it was used or not + delete[] oAvatarRGBA; + + Avatar->UpdateResource(); + + Result = EBlueprintAsyncResultSwitch::OnSuccess; + return Avatar; + } + else + { + UE_LOG(AdvancedSteamFriendsLog, Warning, TEXT("Bad Height / Width with steam avatar!")); + } + + Result = EBlueprintAsyncResultSwitch::OnFailure; + return nullptr; + } +#endif + + UE_LOG(AdvancedSteamFriendsLog, Warning, TEXT("STEAM Couldn't be verified as initialized")); + Result = EBlueprintAsyncResultSwitch::OnFailure; + return nullptr; +} + +bool UAdvancedSteamFriendsLibrary::InitTextFiltering() +{ +#if (PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX) && STEAM_SDK_INSTALLED + + if (SteamAPI_Init()) + { + return SteamUtils()->InitFilterText(); + } + +#endif + + return false; +} + +bool UAdvancedSteamFriendsLibrary::FilterText(FString TextToFilter, EBPTextFilteringContext Context, const FBPUniqueNetId TextSourceID, FString& FilteredText) +{ +#if (PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX) && STEAM_SDK_INSTALLED + + if (SteamAPI_Init()) + { + uint32 BufferLen = TextToFilter.Len() + 10; // Docs say 1 byte excess min, going with 10 + char* OutText = new char[BufferLen]; + + uint64 id = 0; + + if (TextSourceID.IsValid()) + { + id = *((uint64*)TextSourceID.UniqueNetId->GetBytes()); + } + + int FilterCount = SteamUtils()->FilterText((ETextFilteringContext)Context, id, TCHAR_TO_ANSI(*TextToFilter), OutText, BufferLen); + + if (FilterCount > 0) + { + FilteredText = FString(UTF8_TO_TCHAR(OutText)); + delete[] OutText; + return true; + } + + delete[] OutText; + } + +#endif + + FilteredText = TextToFilter; + return false; +} + +bool UAdvancedSteamFriendsLibrary::IsSteamInBigPictureMode() +{ +#if (PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX) && STEAM_SDK_INSTALLED + + if (SteamAPI_Init()) + { + return SteamUtils()->IsSteamInBigPictureMode(); + } + +#endif + + return false; +} \ No newline at end of file diff --git a/Plugins/AdvancedSteamSessions/Source/AdvancedSteamSessions/Private/AdvancedSteamSessions.cpp b/Plugins/AdvancedSteamSessions/Source/AdvancedSteamSessions/Private/AdvancedSteamSessions.cpp new file mode 100644 index 0000000..34d9ff5 --- /dev/null +++ b/Plugins/AdvancedSteamSessions/Source/AdvancedSteamSessions/Private/AdvancedSteamSessions.cpp @@ -0,0 +1,12 @@ +//#include "StandAlonePrivatePCH.h" +#include "AdvancedSteamSessions.h" + +void AdvancedSteamSessions::StartupModule() +{ +} + +void AdvancedSteamSessions::ShutdownModule() +{ +} + +IMPLEMENT_MODULE(AdvancedSteamSessions, AdvancedSteamSessions) \ No newline at end of file diff --git a/Plugins/AdvancedSteamSessions/Source/AdvancedSteamSessions/Private/AdvancedSteamWorkshopLibrary.cpp b/Plugins/AdvancedSteamSessions/Source/AdvancedSteamSessions/Private/AdvancedSteamWorkshopLibrary.cpp new file mode 100644 index 0000000..03eb780 --- /dev/null +++ b/Plugins/AdvancedSteamSessions/Source/AdvancedSteamSessions/Private/AdvancedSteamWorkshopLibrary.cpp @@ -0,0 +1,69 @@ +// Fill out your copyright notice in the Description page of Project Settings. +#include "AdvancedSteamWorkshopLibrary.h" +#include "OnlineSubSystemHeader.h" +//General Log +DEFINE_LOG_CATEGORY(AdvancedSteamWorkshopLog); + + +void UAdvancedSteamWorkshopLibrary::GetNumSubscribedWorkshopItems(int32 & NumberOfItems) +{ + NumberOfItems = 0; +#if (PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX) && STEAM_SDK_INSTALLED + + if (SteamAPI_Init()) + { + NumberOfItems = SteamUGC()->GetNumSubscribedItems(); + return; + } + else + { + UE_LOG(AdvancedSteamWorkshopLog, Warning, TEXT("Error in GetNumSubscribedWorkshopItemCount : SteamAPI is not Inited!")); + return; + } +#else + UE_LOG(AdvancedSteamWorkshopLog, Warning, TEXT("Error in GetNumSubscribedWorkshopItemCount : Called on an incompatible platform")); + return; +#endif +} + +TArray UAdvancedSteamWorkshopLibrary::GetSubscribedWorkshopItems(int32 & NumberOfItems) +{ + TArray outArray; + NumberOfItems = 0; + +#if (PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX) && STEAM_SDK_INSTALLED + + if (SteamAPI_Init()) + { + uint32 NumItems = SteamUGC()->GetNumSubscribedItems(); + + if (NumItems == 0) + return outArray; + + // Not using the actual variable above in case someone somehow goes past int32 limits + // Don't want to go negative on the iteration. + NumberOfItems = NumItems; + + PublishedFileId_t *fileIds = new PublishedFileId_t[NumItems]; + + uint32 subItems = SteamUGC()->GetSubscribedItems(fileIds, NumItems); + + for (uint32 i = 0; i < subItems; ++i) + { + outArray.Add(FBPSteamWorkshopID(fileIds[i])); + } + + delete[] fileIds; + + return outArray; + } + else + { + UE_LOG(AdvancedSteamWorkshopLog, Warning, TEXT("Error in GetSubscribedWorkshopItemCount : SteamAPI is not Inited!")); + return outArray; + } +#else + UE_LOG(AdvancedSteamWorkshopLog, Warning, TEXT("Error in GetSubscribedWorkshopItemCount : Called on an incompatible platform")); + return outArray; +#endif +} diff --git a/Plugins/AdvancedSteamSessions/Source/AdvancedSteamSessions/Private/SteamRequestGroupOfficersCallbackProxy.cpp b/Plugins/AdvancedSteamSessions/Source/AdvancedSteamSessions/Private/SteamRequestGroupOfficersCallbackProxy.cpp new file mode 100644 index 0000000..44bcc75 --- /dev/null +++ b/Plugins/AdvancedSteamSessions/Source/AdvancedSteamSessions/Private/SteamRequestGroupOfficersCallbackProxy.cpp @@ -0,0 +1,121 @@ +// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. + +#include "SteamRequestGroupOfficersCallbackProxy.h" +#include "Online/CoreOnline.h" +#include "AdvancedSteamFriendsLibrary.h" +#include "OnlineSubSystemHeader.h" +#if (PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX) && STEAM_SDK_INSTALLED +#include "steam/isteamfriends.h" +#endif +//#include "OnlineSubsystemSteamTypes.h" + +////////////////////////////////////////////////////////////////////////// +// UEndSessionCallbackProxy + +USteamRequestGroupOfficersCallbackProxy::USteamRequestGroupOfficersCallbackProxy(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ +} + +USteamRequestGroupOfficersCallbackProxy::~USteamRequestGroupOfficersCallbackProxy() +{ +} + +USteamRequestGroupOfficersCallbackProxy* USteamRequestGroupOfficersCallbackProxy::GetSteamGroupOfficerList(UObject* WorldContextObject, FBPUniqueNetId GroupUniqueNetID) +{ + USteamRequestGroupOfficersCallbackProxy* Proxy = NewObject(); + + Proxy->GroupUniqueID = GroupUniqueNetID; + return Proxy; +} + +void USteamRequestGroupOfficersCallbackProxy::Activate() +{ +#if (PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX) && STEAM_SDK_INSTALLED + if (SteamAPI_Init()) + { + uint64 id = *((uint64*)GroupUniqueID.UniqueNetId->GetBytes()); + SteamAPICall_t hSteamAPICall = SteamFriends()->RequestClanOfficerList(id); + + m_callResultGroupOfficerRequestDetails.Set(hSteamAPICall, this, &USteamRequestGroupOfficersCallbackProxy::OnRequestGroupOfficerDetails); + return; + } +#endif + TArray EmptyArray; + OnFailure.Broadcast(EmptyArray); +} + +#if (PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX) && STEAM_SDK_INSTALLED +void USteamRequestGroupOfficersCallbackProxy::OnRequestGroupOfficerDetails(ClanOfficerListResponse_t *pResult, bool bIOFailure) +{ + TArray OfficerArray; + + //FOnlineSubsystemSteam* SteamSubsystem = (FOnlineSubsystemSteam*)(IOnlineSubsystem::Get(STEAM_SUBSYSTEM)); + + if (bIOFailure || !pResult || !pResult->m_bSuccess) + { + //if (SteamSubsystem != nullptr) + { + // SteamSubsystem->ExecuteNextTick([this]() + //{ + TArray FailureArray; + OnFailure.Broadcast(FailureArray); + //}); + } + //OnFailure.Broadcast(OfficerArray); + return; + } + + if (SteamAPI_Init()) + { + uint64 id = *((uint64*)GroupUniqueID.UniqueNetId->GetBytes()); + + FBPSteamGroupOfficer Officer; + CSteamID ClanOwner = SteamFriends()->GetClanOwner(id); + + Officer.bIsOwner = true; + + TSharedPtr ValueID(new const FUniqueNetIdSteam2(ClanOwner)); + Officer.OfficerUniqueNetID.SetUniqueNetId(ValueID); + OfficerArray.Add(Officer); + + for (int i = 0; i < pResult->m_cOfficers; i++) + { + CSteamID OfficerSteamID = SteamFriends()->GetClanOfficerByIndex(id, i); + + Officer.bIsOwner = false; + + TSharedPtr newValueID(new const FUniqueNetIdSteam2(OfficerSteamID)); + Officer.OfficerUniqueNetID.SetUniqueNetId(newValueID); + + OfficerArray.Add(Officer); + } + + //if (SteamSubsystem != nullptr) + //{ + //SteamSubsystem->ExecuteNextTick([OfficerArray, this]() + //{ + OnSuccess.Broadcast(OfficerArray); + //}); + //} + + //OnSuccess.Broadcast(OfficerArray); + return; + } + else + { + //if (SteamSubsystem != nullptr) + { + //SteamSubsystem->ExecuteNextTick([this]() + //{ + TArray FailureArray; + OnFailure.Broadcast(FailureArray); + //}); + } + } + + // Should never hit this anyway + //OnFailure.Broadcast(OfficerArray); +} +#endif + diff --git a/Plugins/AdvancedSteamSessions/Source/AdvancedSteamSessions/Private/SteamWSRequestUGCDetailsCallbackProxy.cpp b/Plugins/AdvancedSteamSessions/Source/AdvancedSteamSessions/Private/SteamWSRequestUGCDetailsCallbackProxy.cpp new file mode 100644 index 0000000..daf3b07 --- /dev/null +++ b/Plugins/AdvancedSteamSessions/Source/AdvancedSteamSessions/Private/SteamWSRequestUGCDetailsCallbackProxy.cpp @@ -0,0 +1,101 @@ +// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. + +#include "SteamWSRequestUGCDetailsCallbackProxy.h" +#include "OnlineSubSystemHeader.h" +#if (PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX) && STEAM_SDK_INSTALLED +#include "steam/isteamugc.h" +#endif + +////////////////////////////////////////////////////////////////////////// +// UEndSessionCallbackProxy + +USteamWSRequestUGCDetailsCallbackProxy::USteamWSRequestUGCDetailsCallbackProxy(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ +} + + +USteamWSRequestUGCDetailsCallbackProxy* USteamWSRequestUGCDetailsCallbackProxy::GetWorkshopItemDetails(UObject* WorldContextObject, FBPSteamWorkshopID WorkShopID/*, int32 NumSecondsBeforeTimeout*/) +{ + USteamWSRequestUGCDetailsCallbackProxy* Proxy = NewObject(); + + Proxy->WorkShopID = WorkShopID; + return Proxy; +} + +void USteamWSRequestUGCDetailsCallbackProxy::Activate() +{ +#if (PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX) && STEAM_SDK_INSTALLED + if (SteamAPI_Init()) + { + // #TODO: Support arrays instead in the future? + UGCQueryHandle_t hQueryHandle = SteamUGC()->CreateQueryUGCDetailsRequest((PublishedFileId_t *)&WorkShopID.SteamWorkshopID, 1); + // #TODO: add search settings here by calling into the handle? + SteamAPICall_t hSteamAPICall = SteamUGC()->SendQueryUGCRequest(hQueryHandle); + + // Need to release the query + SteamUGC()->ReleaseQueryUGCRequest(hQueryHandle); + + if (hSteamAPICall == k_uAPICallInvalid) + { + OnFailure.Broadcast(FBPSteamWorkshopItemDetails()); + return; + } + + m_callResultUGCRequestDetails.Set(hSteamAPICall, this, &USteamWSRequestUGCDetailsCallbackProxy::OnUGCRequestUGCDetails); + return; + } +#endif + OnFailure.Broadcast(FBPSteamWorkshopItemDetails()); +} + +#if (PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_LINUX) && STEAM_SDK_INSTALLED +void USteamWSRequestUGCDetailsCallbackProxy::OnUGCRequestUGCDetails(SteamUGCQueryCompleted_t *pResult, bool bIOFailure) +{ + //FOnlineSubsystemSteam* SteamSubsystem = (FOnlineSubsystemSteam*)(IOnlineSubsystem::Get(STEAM_SUBSYSTEM)); + + if (bIOFailure || !pResult || pResult->m_unNumResultsReturned <= 0) + { + //if (SteamSubsystem != nullptr) + { + // SteamSubsystem->ExecuteNextTick([this]() + //{ + OnFailure.Broadcast(FBPSteamWorkshopItemDetails()); + //}); + } + //OnFailure.Broadcast(FBPSteamWorkshopItemDetails()); + return; + } + if (SteamAPI_Init()) + { + SteamUGCDetails_t Details; + if (SteamUGC()->GetQueryUGCResult(pResult->m_handle, 0, &Details)) + { + //if (SteamSubsystem != nullptr) + { + //SteamSubsystem->ExecuteNextTick([Details, this]() + //{ + OnSuccess.Broadcast(FBPSteamWorkshopItemDetails(Details)); + //}); + } + + //OnSuccess.Broadcast(FBPSteamWorkshopItemDetails(Details)); + return; + } + } + else + { + //if (SteamSubsystem != nullptr) + { + //SteamSubsystem->ExecuteNextTick([this]() + //{ + OnFailure.Broadcast(FBPSteamWorkshopItemDetails()); + //}); + } + } + + // Not needed, should never hit here + //OnFailure.Broadcast(FBPSteamWorkshopItemDetails()); +} +#endif + diff --git a/Source/Monolith/Monolith.Build.cs b/Source/Monolith/Monolith.Build.cs index 92f3765..9b145fb 100644 --- a/Source/Monolith/Monolith.Build.cs +++ b/Source/Monolith/Monolith.Build.cs @@ -9,5 +9,9 @@ public class Monolith : ModuleRules PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "EnhancedInput" }); + + PrivateDependencyModuleNames.AddRange(new string[] { "OnlineSubsystem", "OnlineSubsystemUtils" }); + + DynamicallyLoadedModuleNames.Add("OnlineSubsystemSteam"); } -} +} \ No newline at end of file diff --git a/Source/Monolith/MonolithGameInstance.cpp b/Source/Monolith/MonolithGameInstance.cpp new file mode 100644 index 0000000..6dc5be4 --- /dev/null +++ b/Source/Monolith/MonolithGameInstance.cpp @@ -0,0 +1,4 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "MonolithGameInstance.h" diff --git a/Source/Monolith/MonolithGameInstance.h b/Source/Monolith/MonolithGameInstance.h new file mode 100644 index 0000000..c64865b --- /dev/null +++ b/Source/Monolith/MonolithGameInstance.h @@ -0,0 +1,16 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Engine/GameInstance.h" +#include "MonolithGameInstance.generated.h" + +/** + * + */ +UCLASS() +class MONOLITH_API UMonolithGameInstance : public UGameInstance +{ + GENERATED_BODY() +};