cancel
Showing results for 
Search instead for 
Did you mean: 

How to react to an incoming Session Invite by a Friend?

eXifreXi
Explorer
Hello there,

I've looked into adding basic support for "Invite Friend to Session", "Accept Invite", "Reject Invite" and "React to Invite".
Now I did things like these with Steam already, but it seems like Oculus didn't implement all needed functions.

Here is how I would expect it to work:

- PlayerA invites PlayerB to an open game, either via InGame FriendList, using the UniqueNetId and the SessionInterface, or via Oculus own UI.
- PlayerB receives the invite, inside the Game and outside the Game in Oculus own UI.

Now either:

- PlayerB decides to reject the Invite either through InGame UI or Oculus own UI -> Notification closes, nothing else should happen.
OR
- PlayerB decides to accept the Invite either through InGame UI or Oculus own UI -> Notification closes, PlayerB joins PlayerA's session.

Now some of this works, other things aren't documented or no one really asked about that yet.
I found one post on this forum, but it was never answered by you.

What I know how to do is:

- Invite a Friend using the SessionInterface, as there is the "SendSessionInviteToFriend", which you seem to have implemented.
- Joining a Session through a simple "FindFriendSession" and then "JoinSession". That already works for other systems we implemented.

What I don't know how to do is:

- Display the incoming Invite inside the game.

Steam has a simple callback, which I can hook up with a function and then display UI.
How does Oculus handle this? Where can I hook into to get notified, ingame, that someone invites me?

In addition, can PlayerA be notified, if PlayerB accept or rejects the invite?

Cheres,
Cedric Neukirchen
5 REPLIES 5

eXifreXi
Explorer
@imperativity

Thanks for the answer! I have a slight problem with listening to the Invite Request.
You guys are popping your message queue in your TaskManager of your OnlineSubsystem Integration in its Tick.
So each Frame you iterate over all Messages (pop them) and trigger your Delegates, if they are currently bound.

Now if I call "popmessage" myself, it's empty, cause you already popped the message.
That's why I tried to get IOnlineSubsystem, cast it to "FOnlineSubsystemOculus" and add my own Delegate to your already working system. However Epic doesn't really allow casting from the Interface to the actual Subsystem, so the implementation uses a static_cast, which is quite dirty and seems to crash every now and then.
I can't check the pointer with a static_cast and see if it's null...

I mean, don't get me wrong, I can listen to the InviteReceived that way, but it's too unstable.
Is there a proper way to listen to your queue, which I haven't found yet?

Kind regards,
Cedric Neukirchen

eXifreXi
Explorer
Alright, think I got it to work. For anyone being interested, here are parts of my code for this:

GameInstance.cpp

void UMRGameInstance::Init()
{
Super::Init();

IOnlineSubsystem* OnlineSub = Online::GetSubsystem(GetWorld(), OCULUS_SUBSYSTEM);
if (OnlineSub)
{
// This is not safe, but even Epic advises us to do so.
// And sadly we need the OculusSubsystem, not just the Interface
OculusSubsystem = static_cast<FOnlineSubsystemOculus*>(OnlineSub);

// Listen to the RoomGet and RoomInviteReceived delegates.
// Oculus pops messages already on tick, so we have to register to their queue.
if (OculusSubsystem)
{
OnRoomReceivedDelegate_Handle = OculusSubsystem->GetNotifDelegate(ovrMessage_Room_Get).AddUObject(this, &UMRGameInstance::OnRoomReceived);
OnRoomInviteReceivedDelegate_Handle = OculusSubsystem->GetNotifDelegate(ovrMessage_Notification_Room_InviteReceived).AddUObject(this, &UMRGameInstance::OnRoomInviteReceived);
}
}
}

void UMRGameInstance::Shutdown()
{
// Make sure to clean these delegates up again!
if (OnRoomInviteReceivedDelegate_Handle.IsValid() && OculusSubsystem)
{
OculusSubsystem->RemoveNotifDelegate(ovrMessage_Notification_Room_InviteReceived, OnRoomInviteReceivedDelegate_Handle);
OnRoomInviteReceivedDelegate_Handle.Reset();
OculusSubsystem->RemoveNotifDelegate(ovrMessage_Room_Get, OnRoomReceivedDelegate_Handle);
OnRoomReceivedDelegate_Handle.Reset();
}

Super::Shutdown();
}

GameInstance.h

/** Pointer to the Oculus Subsystem. */
FOnlineSubsystemOculus* OculusSubsystem;

/** Delegate Handle. */
FDelegateHandle OnRoomInviteReceivedDelegate_Handle;
FDelegateHandle OnRoomReceivedDelegate_Handle;

/** Handles the Room Invite Message. */
void OnRoomInviteReceived(ovrMessageHandle Message, bool bIsError);
/** Handles receiving the room itself. */
void OnRoomReceived(ovrMessageHandle Message, bool bIsError);

virtual void Init() override;
virtual void Shutdown() override;

When receiving the Invite via "OnRoomInviteReceived", you can grab the RoomID like this:
// Retrieve RoomID
ovrRoomInviteNotificationHandle RoomInviteHandle = ovr_Message_GetRoomInviteNotification(Message);
ovrID RoomID = ovr_RoomInviteNotification_GetRoomID(RoomInviteHandle);

And then perform the GetRoom request, to get more information about the room, such as the Owner (so the one who probably send you the invite):
// This returns an "ovrRequest" which you can save in an array of pending request.
// When receiving the response in "OnRoomReceived" you could use "ovr_Message_GetRequestID(Message)" to receive an "ovrRequest" again and simple compare them. They are just "uint64_t" variables.
ovr_Room_Get(RoomID)

And finall in the "OnRoomReceived" function, you can grab the OwnerID and more like this:
// Retrieve OwnerID
ovrUserHandle Owner = ovr_Room_GetOwner(RoomHandle);
ovrID OwnerID = ovr_User_GetID(Owner);
// FUniqueNetIdOculus is a child of Epic UniqueNetId
// From here on I search for a FriendSession with this ID and then join that session via the normal JoinSession code
TSharedPtr<const FUniqueNetIdOculus> OculusOwnerID = MakeShareable(new FUniqueNetIdOculus(OwnerID));

Hope this helps other users who want to display Invites ingame.
You can probably also listen to the Accept Message of the Oculus Interface Invite.
That would probably just be binding to the default SessionInterface delegate "OnSessionUserInviteAccepted".
At least as far as I can tell. Haven't tested it yet.

Cheers

7777ivan
Protege

thanks for the detailed description. I figured out the same thing, luckily I saw you stuff before testing and added the delegate for ovrMessage_Room_Get, because on game startup this is the event I can grab in practice, when previously an invite has been accepted, to join the Room, and the game session afterwards. I have never got result from ovrMessage_Notification_Room_InviteReceived so far...
btw, is it possible to suppress Oculus menu in-game when you get an invite? currently we have to exit the game, accept the invite, that opens the game again... thanks.

7777ivan
Protege

sorry, ovrMessage_Notification_Room_InviteReceived works too, my debugging into log was wrong....
but I'm still struggling with turning off in-game notifications

VintageGreen
Adventurer

hello I've been trying for weeks to get two headsets to connect using blueprints and I stumble upon this post and realize that this might be why the join session never sees the right map is that correct? I need to make a custom cpp gameinstance ? is that where the map is pulled from as atm I'm using advancedsessiongameinstance

thank you