Welcome to the Oculus Developer Forums!

Your participation on the forum is subject to the Oculus Code of Conduct.

In general, please be respectful and kind. If you violate the Oculus Code of Conduct, your access to the developer forums may be revoked at the discretion of Oculus staff.

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

eXifreXieXifreXi Posts: 12
NerveGear
edited April 2018 in Unreal Development
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

Comments

  • eXifreXieXifreXi Posts: 12
    NerveGear
    @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
  • eXifreXieXifreXi Posts: 12
    NerveGear
    edited April 2018
    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
Sign In or Register to comment.