Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[GameKit] Implement Xcode 16.0 beta 1-6 changes. #20880

Merged
merged 11 commits into from
Aug 26, 2024
59 changes: 59 additions & 0 deletions src/GameKit/GKGameCenterViewController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#if !WATCH
using System;

using Foundation;
using ObjCRuntime;

namespace GameKit {
/// <summary>This enum is used to select how to initialize a new instance of a <see cref="GKGameCenterViewController" />.</summary>
public enum GKGameCenterViewControllerInitializationOption {
/// <summary>The <c>id</c> parameter passed to the constructor is an achievement ID.</summary>
Achievement,
/// <summary>The <c>id</c> parameter passed to the constructor is a leaderboard set ID.</summary>
LeaderboardSet,
}

public partial class GKGameCenterViewController {
/// <summary>Create a new GKGameCenterViewController instance that presents an achievement.</summary>
/// <param name="id">The ID of the achievement to show.</param>
#if NET
[SupportedOSPlatform ("ios14.0")]
[SupportedOSPlatform ("maccatalyst14.0")]
[SupportedOSPlatform ("macos11.0")]
[SupportedOSPlatform ("tvos14.0")]
#else
[TV (14, 0), Mac (11, 0), iOS (14, 0), MacCatalyst (14, 0)]
#endif
public GKGameCenterViewController (string id)
: this (id, GKGameCenterViewControllerInitializationOption.Achievement)
{
}

/// <summary>Create a new GKGameCenterViewController instance that presents an achievement or a leaderboard set.</summary>
/// <param name="id">The ID of the achievement or the leaderboard set to show.</param>
/// <param name="option">Use this option to specify whether the GKGameCenterViewController shows an achievement or a leader board set.</param>
#if NET
[SupportedOSPlatform ("ios18.0")]
[SupportedOSPlatform ("maccatalyst18.0")]
[SupportedOSPlatform ("macos15.0")]
[SupportedOSPlatform ("tvos18.0")]
#else
[TV (18, 0), Mac (15, 0), iOS (18, 0), MacCatalyst (18, 0)]
#endif
public GKGameCenterViewController (string id, GKGameCenterViewControllerInitializationOption option)
: base (NSObjectFlag.Empty)
{
switch (option) {
case GKGameCenterViewControllerInitializationOption.Achievement:
InitializeHandle (_InitWithAchievementId (id));
break;
case GKGameCenterViewControllerInitializationOption.LeaderboardSet:
InitializeHandle (_InitWithLeaderboardSetId (id));
break;
default:
throw new ArgumentOutOfRangeException (nameof (option), option, "Invalid enum value.");
}
}
}
}
#endif // !WATCH
4 changes: 4 additions & 0 deletions src/GameKit/GameKit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,10 @@ public enum GKPlayerConnectionState : long {
}

// NSInteger -> GKVoiceChat.h
[Deprecated (PlatformName.iOS, 18, 0, message: "No longer supported.")]
[Deprecated (PlatformName.MacCatalyst, 18, 0, message: "No longer supported.")]
[Deprecated (PlatformName.TvOS, 18, 0, message: "No longer supported.")]
[Deprecated (PlatformName.MacOSX, 15, 0, message: "No longer supported.")]
[Native]
public enum GKVoiceChatPlayerState : long {
Connected,
Expand Down
1 change: 1 addition & 0 deletions src/frameworks.sources
Original file line number Diff line number Diff line change
Expand Up @@ -943,6 +943,7 @@ GAMEKIT_API_SOURCES = \
GameKit/GameKit.cs \

GAMEKIT_SOURCES = \
GameKit/GKGameCenterViewController.cs \
GameKit/GKLocalPlayerListener.cs \
GameKit/GameKit2.cs \
GameKit/GKCompat.cs \
Expand Down
55 changes: 41 additions & 14 deletions src/gamekit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -535,10 +535,8 @@ interface GKLeaderboardSet : NSCoding, NSSecureCoding {
[Async]
void LoadLeaderboardsWithCompletionHandler (GKLeaderboardsHandler handler);

[NoMac]
[NoTV]
[NoWatch]
[NoMacCatalyst]
[Export ("loadImageWithCompletionHandler:")]
[Async]
void LoadImage ([NullAllowed] GKImageLoadedHandler completionHandler);
Expand Down Expand Up @@ -917,8 +915,7 @@ interface GKLocalPlayer
Action<NSViewController, NSError> AuthenticateHandler { get; set; }
#endif

[NoWatch, NoTV, Mac (12, 0), iOS (15, 0)]
[NoMacCatalyst]
[NoWatch, NoTV, Mac (12, 0), iOS (15, 0), MacCatalyst (15, 0)]
[Export ("isPresentingFriendRequestViewController")]
bool IsPresentingFriendRequestViewController { get; }

Expand Down Expand Up @@ -1160,6 +1157,10 @@ interface GKMatch {
[Export ("disconnect")]
void Disconnect ();

[Deprecated (PlatformName.iOS, 18, 0, message: "No longer supported.")]
[Deprecated (PlatformName.MacCatalyst, 18, 0, message: "No longer supported.")]
[Deprecated (PlatformName.TvOS, 18, 0, message: "No longer supported.")]
[Deprecated (PlatformName.MacOSX, 15, 0, message: "No longer supported.")]
[Export ("voiceChatWithName:")]
[return: NullAllowed]
GKVoiceChat VoiceChatWithName (string name);
Expand Down Expand Up @@ -1254,6 +1255,10 @@ interface GKMatchDelegate {
void DataReceivedForRecipient (GKMatch match, NSData data, GKPlayer recipient, GKPlayer player);
}

[Deprecated (PlatformName.iOS, 18, 0, message: "No longer supported.")]
[Deprecated (PlatformName.MacCatalyst, 18, 0, message: "No longer supported.")]
[Deprecated (PlatformName.TvOS, 18, 0, message: "No longer supported.")]
[Deprecated (PlatformName.MacOSX, 15, 0, message: "No longer supported.")]
[NoWatch]
[MacCatalyst (13, 1)]
[BaseType (typeof (NSObject))]
Expand Down Expand Up @@ -1520,7 +1525,7 @@ interface GKMatchmaker {
[TV (17, 2), Mac (14, 2), iOS (17, 2), MacCatalyst (17, 2)]
[Async]
[Export ("findMatchedPlayers:withCompletionHandler:")]
void FindMatchedPlayers (GKMatchRequest request, [NullAllowed] Action<GKMatchedPlayers, NSError> completionHandler);
void FindMatchedPlayers (GKMatchRequest request, Action<GKMatchedPlayers, NSError> completionHandler);

// Not truly an [Async] method since the handler can be called multiple times, for each player found
[MacCatalyst (13, 1)]
Expand Down Expand Up @@ -2525,26 +2530,36 @@ interface GKGameCenterViewController
[Export ("initWithNibName:bundle:")]
NativeHandle Constructor ([NullAllowed] string nibNameOrNull, [NullAllowed] NSBundle nibBundleOrNull);

[TV (14, 0), NoWatch, Mac (11, 0), iOS (14, 0)]
[TV (14, 0), Mac (11, 0), iOS (14, 0)]
[MacCatalyst (14, 0)]
[Export ("initWithLeaderboardID:playerScope:timeScope:")]
NativeHandle Constructor (string leaderboardId, GKLeaderboardPlayerScope playerScope, GKLeaderboardTimeScope timeScope);

[TV (14, 0), NoWatch, Mac (11, 0), iOS (14, 0)]
[TV (14, 0), Mac (11, 0), iOS (14, 0)]
[MacCatalyst (14, 0)]
[Export ("initWithLeaderboard:playerScope:")]
NativeHandle Constructor (GKLeaderboard leaderboard, GKLeaderboardPlayerScope playerScope);

[TV (14, 0), NoWatch, Mac (11, 0), iOS (14, 0)]
[TV (14, 0), Mac (11, 0), iOS (14, 0)]
[MacCatalyst (14, 0)]
[Export ("initWithAchievementID:")]
NativeHandle Constructor (string achievementId);
[Internal]
NativeHandle _InitWithAchievementId (string achievementId);

[TV (14, 0), NoWatch, Mac (11, 0), iOS (14, 0)]
[TV (14, 0), Mac (11, 0), iOS (14, 0)]
[MacCatalyst (14, 0)]
[Export ("initWithState:")]
NativeHandle Constructor (GKGameCenterViewControllerState state);

[TV (18, 0), Mac (15, 0), iOS (18, 0), MacCatalyst (18, 0)]
[Export ("initWithLeaderboardSetID:")]
[Internal]
NativeHandle _InitWithLeaderboardSetId (string leaderboardSetId);

[TV (18, 0), Mac (15, 0), iOS (18, 0), MacCatalyst (18, 0)]
[Export ("initWithPlayer:")]
NativeHandle Constructor (GKPlayer player);

[Export ("gameCenterDelegate", ArgumentSemantic.Weak), NullAllowed]
NSObject WeakDelegate { get; set; }

Expand Down Expand Up @@ -3110,6 +3125,22 @@ interface GKAccessPoint {

[Export ("triggerAccessPointWithState:handler:")]
void TriggerAccessPoint (GKGameCenterViewControllerState state, Action handler);

[Watch (11, 0), TV (18, 0), Mac (15, 0), iOS (18, 0), MacCatalyst (18, 0)]
[Export ("triggerAccessPointWithAchievementID:handler:")]
void TriggerAccessPointWithAchievementId (string achievementId, [NullAllowed] Action handler);

[Watch (11, 0), TV (18, 0), Mac (15, 0), iOS (18, 0), MacCatalyst (18, 0)]
[Export ("triggerAccessPointWithLeaderboardSetID:handler:")]
void TriggerAccessPointWithLeaderboardSetId (string leaderboardSetId, [NullAllowed] Action handler);

[Watch (11, 0), TV (18, 0), Mac (15, 0), iOS (18, 0), MacCatalyst (18, 0)]
[Export ("triggerAccessPointWithLeaderboardID:playerScope:timeScope:handler:")]
void TriggerAccessPoint (string leaderboardId, GKLeaderboardPlayerScope playerScope, GKLeaderboardTimeScope timeScope, [NullAllowed] Action handler);

[Watch (11, 0), TV (18, 0), Mac (15, 0), iOS (18, 0), MacCatalyst (18, 0)]
[Export ("triggerAccessPointWithPlayer:handler:")]
void TriggerAccessPoint (GKPlayer player, [NullAllowed] Action handler);
}

[Watch (7, 0), TV (14, 0), Mac (11, 0), iOS (14, 0)]
Expand All @@ -3120,9 +3151,6 @@ interface GKLeaderboardEntry {
[Export ("player", ArgumentSemantic.Strong)]
GKPlayer Player { get; }

#if false
// Some APIs missing on iOS, tvOS, watchOS as of Xcode 12 beta 3 - https://github.com/xamarin/maccore/issues/2269
// disabled since the selectors don't respond on macOS 11.0
[Export ("rank")]
nint Rank { get; }

Expand All @@ -3137,7 +3165,6 @@ interface GKLeaderboardEntry {

[Export ("date", ArgumentSemantic.Strong)]
NSDate Date { get; }
#endif

[NoWatch] // header lists watch as supported, but UIViewController is not available on Watch!
[MacCatalyst (13, 1)]
Expand Down
32 changes: 32 additions & 0 deletions tests/introspection/ApiSelectorTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1021,6 +1021,35 @@ protected virtual bool Skip (Type type, string selectorName)
return !TestRuntime.CheckXcodeVersion (16, 0);
}
break;
case "GKLeaderboardEntry":
// It's not possible to create an instance of GKLeaderboardEntry, so I believe that whenever Apple
// returns an instance they return something that responds to these selectors, thus we have to
// provide bindings for them.
switch (selectorName) {
case "context":
case "date":
case "formattedScore":
case "rank":
case "score":
return true;
}
break;
#if __MACCATALYST__
case "GKLeaderboardSet":
switch (selectorName) {
case "loadImageWithCompletionHandler:":
// This exists in both iOS and macOS, so not existing in Mac Catalyst is weird - so just provide the binding.
return true;
}
break;
case "GKLocalPlayer":
switch (selectorName) {
case "isPresentingFriendRequestViewController":
// This exists in both iOS and macOS, so not existing in Mac Catalyst is weird - so just provide the binding.
return true;
}
break;
#endif // __MACCATALYST__
}

// old binding mistake
Expand Down Expand Up @@ -1277,6 +1306,9 @@ protected virtual bool SkipInit (string selector, MethodBase m)
// DDDevicePickerViewController
case "initWithBrowseDescriptor:parameters:":
return true;
// GKGameCenterViewController
case "initWithAchievementID:":
return true;
default:
return false;
}
Expand Down
50 changes: 50 additions & 0 deletions tests/monotouch-test/GameKit/GKGameCenterViewControllerTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//
// Unit tests for GKGameCenterViewControllerTest
//

#if !__WATCHOS__

using System;
using Foundation;
using ObjCRuntime;
#if MONOMAC
using AppKit;
#else
using UIKit;
#endif
using GameKit;
using NUnit.Framework;
using Xamarin.Utils;

namespace MonoTouchFixtures.GameKit {

[TestFixture]
[Preserve (AllMembers = true)]
public class GKGameCenterViewControllerTest {
[Test]
public void StringCtor ()
{
TestRuntime.AssertXcodeVersion (12, 0);
using var controller = new GKGameCenterViewController ("achievementId");
Assert.AreEqual (controller.ViewState, GKGameCenterViewControllerState.Achievements, "ViewState");
}

[Test]
public void StringOptionCtor_AchievementId ()
{
TestRuntime.AssertXcodeVersion (12, 0);
using var controller = new GKGameCenterViewController ("achievementId", GKGameCenterViewControllerInitializationOption.Achievement);
Assert.AreEqual (controller.ViewState, GKGameCenterViewControllerState.Achievements, "ViewState");
}

[Test]
public void StringOptionCtor_LeaderboardSetId ()
{
TestRuntime.AssertXcodeVersion (16, 0);
using var controller = new GKGameCenterViewController ("achievementId", GKGameCenterViewControllerInitializationOption.LeaderboardSet);
Assert.AreEqual (controller.ViewState, GKGameCenterViewControllerState.Leaderboards, "ViewState");
}
}
}

#endif // !__WATCHOS__

This file was deleted.

This file was deleted.

11 changes: 0 additions & 11 deletions tests/xtro-sharpie/api-annotations-dotnet/common-GameKit.ignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,3 @@

## enum size declared after the enum, e.g. `typedef NSInteger GKInviteeResponse;`, so we miss the metadata
!unknown-native-enum! GKInviteeResponse bound

# Xcode 12 beta 3 - these API are missing
# https://github.com/xamarin/maccore/issues/2269
!missing-selector! GKLeaderboardEntry::context not bound
!missing-selector! GKLeaderboardEntry::date not bound
!missing-selector! GKLeaderboardEntry::formattedScore not bound
!missing-selector! GKLeaderboardEntry::rank not bound
!missing-selector! GKLeaderboardEntry::score not bound

## unsorted

2 changes: 0 additions & 2 deletions tests/xtro-sharpie/api-annotations-dotnet/iOS-GameKit.ignore

This file was deleted.

8 changes: 0 additions & 8 deletions tests/xtro-sharpie/api-annotations-dotnet/iOS-GameKit.todo

This file was deleted.

12 changes: 0 additions & 12 deletions tests/xtro-sharpie/api-annotations-dotnet/macOS-GameKit.ignore
Original file line number Diff line number Diff line change
@@ -1,19 +1,7 @@
# The parent enum GKVoiceChatService is not available in macOS
# so to be honest it does not make much sense to expose this constant on macOS
# nor the below protocols

# This selector does not exist in macOS, confirmed by intro.

# Deprecated
!missing-protocol-member! GKInviteEventListener::player:didRequestMatchWithPlayers: not found
!missing-protocol-member! GKTurnBasedEventListener::player:didRequestMatchWithPlayers: not found

# We have bound GKVoiceChatServiceError as GKVoiceChatServiceError which has no support for macOS
!missing-field! GKVoiceChatServiceErrorDomain not bound
# https://developer.apple.com/documentation/gamekit/gkvoicechatserviceerror?language=objc

# This selector does not exist (respond?) in macOS either
!missing-selector! GKLeaderboardSet::loadImageWithCompletionHandler: not bound

# NullAllowed makes sense
!extra-null-allowed! 'System.Void GameKit.GKMatchmaker::FindMatchedPlayers(GameKit.GKMatchRequest,System.Action`2<GameKit.GKMatchedPlayers,Foundation.NSError>)' has a extraneous [NullAllowed] on parameter #1
8 changes: 0 additions & 8 deletions tests/xtro-sharpie/api-annotations-dotnet/macOS-GameKit.todo

This file was deleted.

2 changes: 0 additions & 2 deletions tests/xtro-sharpie/api-annotations-dotnet/tvOS-GameKit.ignore

This file was deleted.

8 changes: 0 additions & 8 deletions tests/xtro-sharpie/api-annotations-dotnet/tvOS-GameKit.todo

This file was deleted.

Loading