Unreal Engine 4 is available for Win10 UWP app dev now

@ thank you for the advice. I disabled my SN-DBS service and now have an editor build. I can’t package the UWP configuration due to our FMOD plugin not having been built to be UWP compatible. I will have to get in touch with them to get that resolved I expect

I grabbed that project, and built both the ‘WindowDevicePortalWrapper’ and the ‘WindowDevicePortalWrapper.UniversalWindows’ projects in it (in both debug and release), but I’m still getting the error.
Any other ideas?

@ - It does appear that WindowsExports.TryGetVSInstallDir did fix my packaging problem. Thank you for that.

Secondly, as expected, I am able to instantiate the LeaderboardQuery and the call to StatisticsManager::GetLeaderboard does return with an StatisticEventType::GetLeaderboardComplete:



LeaderboardQuery^ Query = ref new LeaderboardQuery();
Query->SkipResultToMe = true;
Query->MaxItems = 100;
Query->Order = SortOrder::Descending;
mgr->GetLeaderboard(LiveContext->User, StatName, Query);


How do I go about getting the Leaderboard stats after GetLeaderboardComplete is returned?



void FOnlineLeaderboardsLive::Tick(float DeltaTime)
{
    StatisticManager^ mgr = Microsoft::Xbox::Services::Statistics::Manager::StatisticManager::SingletonInstance;
    if (mgr != nullptr)
    {
        auto EventList = mgr->DoWork();
        for (StatisticEvent^ Event : EventList)
        {
            if (Event->ErrorCode != 0)
            {
                UE_LOG_ONLINE(Warning, TEXT("DoWork error: %s"), Event->ErrorMessage->Data());
            }

            StatisticEventArgs^ args;

            switch (Event->EventType)
            {
                case StatisticEventType::LocalUserAdded:
                    UE_LOG_ONLINE(Warning, TEXT("DoWork LocalUserAdded: %s"), Event->User->Gamertag->ToString());
                    break;

                case StatisticEventType::LocalUserRemoved:
                    UE_LOG_ONLINE(Warning, TEXT("DoWork LocalUserRemoved: %s"), Event->User->Gamertag->ToString());
                    break;

                case StatisticEventType::GetLeaderboardComplete:
                    UE_LOG_ONLINE(Warning, TEXT("DoWork GetLeaderboardComplete: %s"), Event->User->Gamertag->ToString());
                    args = Event->EventArgs;

                    IVectorView<Platform::String^>^ stats = mgr->GetStatisticNames(Event->User);
                    for (Platform::String^ stat : stats)
                    {
                        UE_LOG_ONLINE(Warning, TEXT("DoWork Stat: %s"), stat->ToString());
                    }
                    break;

                case StatisticEventType::StatisticUpdateComplete:
                    UE_LOG_ONLINE(Warning, TEXT("DoWork StatisticUpdateComplete: %s"), Event->User->Gamertag->ToString());
                    args = Event->EventArgs;
                    break;
            }
        }
    }
}


Finally, is there a way to determine if a User has already been added to the StatisticManager::AddLocalUser(LiveContext->User)?



try
{
    mgr->AddLocalUser(LiveContext->User);
}


I realize my original advice was very poorly worded :frowning:

What I meant to say was that you should manually build the UWP.Automation.csproj within the Visual Studio solution for UE4. With default settings that will pull down the NuGet package for the device portal, which should resolve your error.

Alternatively, again within the Visual Studio UE4 solution, you can right-click the solution root and hit ‘Restore NuGet packages’.

The link to the device portal source was really just in case you were interested in what this thing we needed actually was. You shouldn’t ever need to clone it if you don’t want to.

The event you get back from DoWork carries the leaderboard data. So it should be something like



using namespace Microsoft::Xbox::Services::Statistic::Manager;
using namespace Microsoft::Xbox::Services::Leaderboard;

LeaderboardResultEventArgs^ LbResultEventArgs = safe_cast<LeaderboardResultEventArgs^>(Event->EventArgs);
LeaderboardResult^ LbResult = LbResultEventArgs->Result;

for (LeaderboardRow^ Row : LbResult->Rows)
{
	FString RowText = FString::Printf(TEXT("Leaderboard row: User %s, Stats "), Row->Gamertag->Data());
	for (int32 i = 0; i < Row->Values->Size; ++i)
	{
		RowText.Append(FString::Printf(TEXT("(%s : %s) "), LbResult->Columns->GetAt(i)->DisplayName->Data(), Row->Values->GetAt(i)->Data()));
	}

	UE_LOG_ONLINE(Warning, *RowText);
}


…though once again that’s code that has never been anywhere near a compiler.

Source for the types in the Microsoft::Xbox::Services::Leaderboard namespace is here.

Other than catching the exception for a double add, no. You should consider tracking this in your own code.

Well that helped quite a bit. . .and seems to show an update problem:

Is the Key (“HighScore”) missing then?

@ - I modified the above code some and discovered that the statName is NULL:



LeaderboardResultEventArgs^ LbResultEventArgs = safe_cast<LeaderboardResultEventArgs^>(Event->EventArgs);
LeaderboardResult^ LbResult = LbResultEventArgs->Result;

for (LeaderboardRow^ Row : LbResult->Rows)
{
    FString RowText = FString::Printf(TEXT("Leaderboard row: User %s, Stats "), Row->Gamertag->Data());
    for (unsigned int i = 0; i < Row->Values->Size; ++i)
   {
        LeaderboardColumn^ statCol = LbResult->Columns->GetAt(i);
        Platform::String^ statName = LbResult->Columns->GetAt(i)->DisplayName;

         RowText.Append(FString::Printf(TEXT("(%s : %s) "), LbResult->Columns->GetAt(i)->DisplayName->Data(), Row->Values->GetAt(i)->Data()));
    }
}


And yes, the score is correct: 932

@
Thanks for clearing it up. Unfortunately I get the same errors when attempting to build UWP.Automation within Visual Studio.
When I manage NuGet packages, I can see that ‘WindowsDevicePortalWrapper’ is installed. It was originally on the 0.9.4 (beta) version, so I updated to 0.9.5, but that didn’t seem to make a difference.

That’s odd. Can you see where WindowsDevicePortalWrapper.dll lands after the NuGet install? The project expects to be able to locate it in [Enlistment_Root]/Packages/WindowsDevicePortalWrapper.0.9.4.1-beta/lib/net452/ which should have been the default location for the 0.9.4 (beta) version.

@ - do you have any suggestions for the NULL stat name being returned in the LeaderboardRow?

I’m afraid anything at the moment is just guessing since I haven’t had a chance to play with this myself. Is the StatisticName property also null? Does the DisplayName property on the LeaderboardResult itself (not the LeaderboardColumn) contain a valid string that you recognize?

The .dll was present. I removed and reinstalled WindowsDevicePortalWrapper back to the 0.9.4 version, and now I can build. Progress!

Unfortunately when I try to install the package I get this error -



Deployment Add operation with target volume C: on Package Game_1.0.0.0_x64__a78hwt03br9rj from:  (Game.appx)  failed with error 0x80070070. See http://go.microsoft.com/fwlink/?LinkId=235160 for help diagnosing app deployment issues.


I checked out that link, but the specific error code raised isn’t detailed.

Since that HRESULT begins 8007 the low-order short is a traditional Win32 error code which you can find in winerror.h (or on MSDN, e.g. here). In this case, 0x70 is ERROR_DISK_FULL.

If you have another drive with more space you can change where new apps are installed in the Settings app (System->Storage->Change where new content is saved).

Thanks, that sorted it. Much appreciated!

Actually it was my mistake, I was confusing DisplayName with StatisticName :smiley:

DisplayName was returned as a null. Now, unfortunately, I am not getting any results back from the server so I can’t test my fix:



                case StatisticEventType::GetLeaderboardComplete:
                {
                    UE_LOG_ONLINE(Warning, TEXT("DoWork GetLeaderboardComplete: %s"), Event->User->Gamertag->ToString()->Data());

                    LeaderboardResultEventArgs^ LbResultEventArgs = safe_cast<LeaderboardResultEventArgs^>(Event->EventArgs);
                    LeaderboardResult^ LbResult = LbResultEventArgs->Result;

                    // how many columns are there? 1?
                    LeaderboardColumn^ lbCol = LbResult->Columns->GetAt(0);
                    Platform::String^ displayName = lbCol->DisplayName;
                    Platform::String^ statName = lbCol->StatisticName;

                    for (LeaderboardRow^ Row : LbResult->Rows)
                    {
                        FString RowText = FString::Printf(TEXT("Leaderboard row: User %s, Stats "), Row->Gamertag->Data());

                        for (unsigned int i = 0; i < Row->Values->Size; ++i)
                        {
                            Platform::String^ statValue = Row->Values->GetAt(i);

                            RowText.Append(FString::Printf(TEXT("(%s : %s) "), statName->Data(), statValue->Data()));
                        }

                        UE_LOG_ONLINE(Warning, *RowText);
                    }
                }
                break;


@ - Is there an easy way using existing API’s to add a player to the StatisticManager?



StatisticManager::AddLocalUser(LiveContext->User);


As you know before that line can be executed some setup is required:



if (!LiveSubsystem)
    return false;

const FOnlineIdentityLivePtr Identity = LiveSubsystem->GetIdentityLive();
if (!Identity.IsValid())
    return false;

const FUniqueNetIdLive UserLive(Player.Get());
Windows::Xbox::System::User^ XBoxUser = Identity->GetUserForUniqueNetId(UserLive);
if (!XBoxUser)
    return false;

XboxLiveContext^ LiveContext = LiveSubsystem->GetLiveContext(XBoxUser);
if (LiveContext == nullptr)
    return false;

StatisticManager^ mgr = StatisticManager::SingletonInstance;
if (mgr == nullptr)
    return false;

mgr->AddLocalUser(LiveContext->User);


What I would like to do, after the user logs in and a valid FUniqueNetId is returned, is add the PlayerId to the StatMgr.

Is there an easy way to go about this?

More thinking aloud: you could perhaps register a handler for the Windows::Xbox::System::User::SignInCompleted event. There’s a User property on the event args for that which you can convert to the type expected by AddLocalUser via the helper XSAPIUserFromSystemUser.

Informational Note: I’m trying to debug the XSAPI by following this link:
https:///Microsoft/xbox-live-api/blob/master/LINKTOSOURCE.md#how-to-link-against-the-xsapi-winrt-uwp-source

That does sound nice. For now, I have it in the FOnlineLeaderboardsLive constructor:



    Windows::Xbox::System::User::SignInCompleted += ref new
        Windows::Foundation::EventHandler<EraAdapter::Windows::Xbox::System::SignInCompletedEventArgs^>(
            =](Platform::Object^, EraAdapter::Windows::Xbox::System::SignInCompletedEventArgs^ args)
    {
        StatisticManager^ mgr = StatisticManager::SingletonInstance;
        if (mgr == nullptr) return;

        mgr->AddLocalUser(args->User->XSAPIUserFromShimUser(args->User));
    });


After updating to VS 15.2 I can no longer build my project. I’m getting the following error:



failed on 'C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcpackages\platform.winmd'
'The system cannot find the path specified.'


By chance do you know of a fix for this?