فهرست منبع

Remove IAsyncResult pattern and replaced with modern equivalent.

Dominique Louis 3 هفته پیش
والد
کامیت
74e2ba0930

+ 3 - 3
NetworkStateManagement/.vscode/launch.json

@@ -16,7 +16,7 @@
       "type": "coreclr",
       "request": "launch",
       "preLaunchTask": "build-desktopgl",
-      "program": "${workspaceFolder}/Platforms/Desktop/bin/Debug/net8.0/NetworkStateManagement.exe",
+      "program": "${workspaceFolder}/Platforms/Desktop/bin/Debug/net8.0/NetworkStateManagement",
       "args": [],
       "cwd": "${workspaceFolder}/Platforms/Desktop",
       "stopAtEntry": false
@@ -26,7 +26,7 @@
       "type": "coreclr",
       "request": "launch",
       "preLaunchTask": "build-android",
-      "program": "${workspaceFolder}/Platforms/Android/bin/Debug/net8.0-android/NetworkStateManagement.Android.dll",
+      "program": "${workspaceFolder}/Platforms/Android/bin/Debug/net8.0-android/NetworkStateManagement.dll",
       "args": [],
       "cwd": "${workspaceFolder}/Platforms/Android",
       "stopAtEntry": false
@@ -36,7 +36,7 @@
       "type": "coreclr",
       "request": "launch",
       "preLaunchTask": "build-ios",
-      "program": "${workspaceFolder}/Platforms/iOS/bin/Debug/net8.0-ios/NetworkStateManagement.iOS.dll",
+      "program": "${workspaceFolder}/Platforms/iOS/bin/Debug/net8.0-ios/NetworkStateManagement.dll",
       "args": [],
       "cwd": "${workspaceFolder}/Platforms/iOS",
       "stopAtEntry": false

+ 1 - 1
NetworkStateManagement/Core/NetworkStateManagement.Core.csproj

@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
     <TargetFramework>net8.0</TargetFramework>
-    <RootNamespace>NetworkStateManagement.Core</RootNamespace>
+    <RootNamespace>NetworkStateManagement</RootNamespace>
     <AssemblyName>NetworkStateManagement.Core</AssemblyName>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
   </PropertyGroup>

+ 0 - 4
NetworkStateManagement/Core/NetworkStateManagementGame.cs

@@ -45,11 +45,7 @@ namespace NetworkStateManagement
 		/// <summary>
 		/// The main game constructor.
 		/// </summary>		
-#if ANDROID
-		public NetworkStateManagementGame  (Activity activity) : base (activity)
-#else
 		public NetworkStateManagementGame()
-#endif
 		{
 			Content.RootDirectory = "Content";
 

+ 3 - 4
NetworkStateManagement/Core/Networking/CreateOrFindSessionScreen.cs

@@ -90,7 +90,7 @@ namespace NetworkStateManagement
 
 				// Activate the network busy screen, which will display
 				// an animation until this operation has completed.
-				NetworkBusyScreen busyScreen = new NetworkBusyScreen(networkSession);
+				NetworkBusyScreen<NetworkSession> busyScreen = new NetworkBusyScreen<NetworkSession>(networkSession);
 
 				busyScreen.OperationCompleted += CreateSessionOperationCompleted;
 
@@ -158,7 +158,7 @@ namespace NetworkStateManagement
 
 				// Activate the network busy screen, which will display
 				// an animation until this operation has completed.
-				NetworkBusyScreen busyScreen = new NetworkBusyScreen(availableNetworkSessions);
+				NetworkBusyScreen<AvailableNetworkSessionCollection> busyScreen = new NetworkBusyScreen<AvailableNetworkSessionCollection>(availableNetworkSessions);
 
 				busyScreen.OperationCompleted += FindSessionsOperationCompleted;
 
@@ -177,8 +177,7 @@ namespace NetworkStateManagement
 		/// Event handler for when the asynchronous find network sessions
 		/// operation has completed.
 		/// </summary>
-		void FindSessionsOperationCompleted(object sender,
-					OperationCompletedEventArgs e)
+		void FindSessionsOperationCompleted(object sender, OperationCompletedEventArgs e)
 		{
 			GameScreen nextScreen;
 

+ 1 - 1
NetworkStateManagement/Core/Networking/JoinSessionScreen.cs

@@ -75,7 +75,7 @@ namespace NetworkStateManagement
 
 				// Activate the network busy screen, which will display
 				// an animation until this operation has completed.
-				NetworkBusyScreen busyScreen = new NetworkBusyScreen(networkSession);
+				NetworkBusyScreen<NetworkSession> busyScreen = new NetworkBusyScreen<NetworkSession>(networkSession);
 
 				busyScreen.OperationCompleted += JoinSessionOperationCompleted;
 

+ 74 - 32
NetworkStateManagement/Core/Networking/NetworkBusyScreen.cs

@@ -9,39 +9,45 @@ using System;
 using Microsoft.Xna.Framework;
 using Microsoft.Xna.Framework.Content;
 using Microsoft.Xna.Framework.Graphics;
+using System.Threading.Tasks;
+using Microsoft.Xna.Framework.Input;
 
 
 namespace NetworkStateManagement
 {
 	/// <summary>
 	/// When an asynchronous network operation (for instance searching for or joining a
-	/// session) is in progress, we want to display some sort of busy indicator to let
-	/// the user know the game hasn't just locked up. We also want to make sure they
-	/// can't pick some other menu option before the current operation has finished.
-	/// This screen takes care of both requirements in a single stroke. It monitors
-	/// the IAsyncResult returned by an asynchronous network call, displaying a busy
-	/// indicator for as long as the call is still in progress. When it notices the
-	/// IAsyncResult has completed, it raises an event to let the game know it should
-	/// proceed to the next step, after which the busy screen automatically goes away.
-	/// Because this screen is on top of all others for as long as the asynchronous
-	/// operation is in progress, it automatically takes over all user input,
-	/// preventing any other menu entries being selected until the operation completes.
+	/// session) is in progress, this screen displays a busy indicator and blocks input.
+	/// It monitors a Task&lt;T&gt; returned by the async call, showing the indicator while
+	/// the task is running. When the task completes, it raises an event with the
+	/// operation result (or null on failure), then automatically dismisses itself.
+	/// Because this screen sits on top while the async operation is in progress, it
+	/// captures all user input to prevent interaction with underlying screens until
+	/// the operation completes.
 	/// </summary>
-	class NetworkBusyScreen : GameScreen
+	class NetworkBusyScreen<T> : GameScreen
 	{
-
-		IAsyncResult asyncResult;
+		readonly Task<T> task;
+		readonly System.Threading.CancellationTokenSource cts;
+		bool completionRaised;
 		Texture2D gradientTexture;
 		Texture2D catTexture;
 
-		public event EventHandler<OperationCompletedEventArgs> OperationCompleted;
+		event EventHandler<OperationCompletedEventArgs> operationCompleted;
+		public event EventHandler<OperationCompletedEventArgs> OperationCompleted
+		{
+			add { operationCompleted += value; }
+			remove { operationCompleted -= value; }
+		}
 
 		/// <summary>
 		/// Constructs a network busy screen for the specified asynchronous operation.
+		/// Accepts a Task&lt;T&gt; representing the in-flight operation.
 		/// </summary>
-		public NetworkBusyScreen(IAsyncResult asyncResult)
+		public NetworkBusyScreen(Task<T> task)
 		{
-			this.asyncResult = asyncResult;
+			this.task = task;
+			this.cts = null;
 
 			IsPopup = true;
 
@@ -49,6 +55,19 @@ namespace NetworkStateManagement
 			TransitionOffTime = TimeSpan.FromSeconds(0.2);
 		}
 
+		/// <summary>
+		/// Overload that accepts a CancellationTokenSource to allow user cancellation.
+		/// </summary>
+		public NetworkBusyScreen(Task<T> task, System.Threading.CancellationTokenSource cts)
+		{
+			this.task = task;
+			this.cts = cts;
+
+			IsPopup = true;
+
+			TransitionOnTime = TimeSpan.FromSeconds(0.1);
+			TransitionOffTime = TimeSpan.FromSeconds(0.2);
+		}
 
 		/// <summary>
 		/// Loads graphics content for this screen. This uses the shared ContentManager
@@ -64,35 +83,60 @@ namespace NetworkStateManagement
 			catTexture = content.Load<Texture2D>("cat");
 		}
 
-
-
-
-
 		/// <summary>
-		/// Updates the NetworkBusyScreen.
+		/// Updates the NetworkBusyScreen, checking whether the underlying Task has
+		/// completed and raising OperationCompleted when it does.
 		/// </summary>
 		public override void Update(GameTime gameTime, bool otherScreenHasFocus,
 							bool coveredByOtherScreen)
 		{
 			base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);
 
+			// Optional: allow user to cancel (Esc or B)
+			if (!completionRaised && cts != null)
+			{
+				var kb = Keyboard.GetState();
+				if (kb.IsKeyDown(Keys.Escape))
+				{
+					cts.Cancel();
+				}
+				var gp = GamePad.GetState(PlayerIndex.One);
+				if (gp.IsConnected && gp.IsButtonDown(Buttons.B))
+				{
+					cts.Cancel();
+				}
+			}
+
 			// Has our asynchronous operation completed?
-			if ((asyncResult != null) && asyncResult.IsCompleted)
+			if (!completionRaised && task != null && task.IsCompleted)
 			{
-				// If so, raise the OperationCompleted event.
-				if (OperationCompleted != null)
+				object resultObject = default(T);
+				Exception error = null;
+				try
+				{
+					// Accessing Result will throw if the task faulted/canceled.
+					// We catch here and allow handlers to present error UI.
+					resultObject = task.Result;
+				}
+				catch (Exception ex)
 				{
-					OperationCompleted(this,
-					new OperationCompletedEventArgs(asyncResult));
+					// Leave result as default (usually null) to signal failure to handlers.
+					error = (task?.Exception?.GetBaseException()) ?? ex;
 				}
 
-				ExitScreen();
+				var handler = operationCompleted;
+				if (handler != null)
+				{
+					handler(this, new OperationCompletedEventArgs(resultObject, error));
+				}
 
-				asyncResult = null;
+				completionRaised = true;
+				// Clear handlers to avoid reentry if this screen lingers during transition off
+				operationCompleted = null;
+				ExitScreen();
 			}
 		}
 
-
 		/// <summary>
 		/// Draws the NetworkBusyScreen.
 		/// </summary>
@@ -148,7 +192,5 @@ namespace NetworkStateManagement
 
 			spriteBatch.End();
 		}
-
-
 	}
 }

+ 2 - 2
NetworkStateManagement/Core/Networking/NetworkSessionComponent.cs

@@ -244,7 +244,7 @@ namespace NetworkStateManagement
 				// delivered. When the loading screen finishes, it will activate the
 				// network busy screen, which displays an animation as it waits for
 				// the join operation to complete.
-				NetworkBusyScreen busyScreen = new NetworkBusyScreen(joinTask);
+				NetworkBusyScreen<NetworkSession> busyScreen = new NetworkBusyScreen<NetworkSession>(joinTask);
 
 				busyScreen.OperationCompleted += JoinInvitedOperationCompleted;
 
@@ -309,7 +309,7 @@ namespace NetworkStateManagement
 					return false;
 
 				case NetworkSessionType.PlayerMatch:
-					//case NetworkSessionType.Ranked:
+				case NetworkSessionType.Ranked:
 					return true;
 
 				default:

+ 14 - 2
NetworkStateManagement/Core/Networking/OperationCompletedEventArgs.cs

@@ -14,13 +14,16 @@ namespace NetworkStateManagement
     /// </summary>
     class OperationCompletedEventArgs : EventArgs
     {
-
-
         /// <summary>
         /// Gets or sets the result of the network operation that has just completed.
         /// </summary>
         public object Result { get; set; }
 
+        /// <summary>
+        /// Gets or sets the exception that caused the operation to fail, if any.
+        /// </summary>
+        public Exception Exception { get; set; }
+
         /// <summary>
         /// Constructs a new event arguments class.
         /// </summary>
@@ -28,5 +31,14 @@ namespace NetworkStateManagement
         {
             this.Result = result;
         }
+
+        /// <summary>
+        /// Constructs a new event arguments class with an optional exception.
+        /// </summary>
+        public OperationCompletedEventArgs(object result, Exception exception)
+        {
+            this.Result = result;
+            this.Exception = exception;
+        }
     }
 }

+ 1 - 1
NetworkStateManagement/Core/ScreenManager/InputState.cs

@@ -66,7 +66,7 @@ namespace NetworkStateManagement
                 LastKeyboardStates[i] = CurrentKeyboardStates[i];
                 LastGamePadStates[i] = CurrentGamePadStates[i];
 
-                CurrentKeyboardStates[i] = Keyboard.GetState((PlayerIndex)i);
+                CurrentKeyboardStates[i] = Keyboard.GetState();
                 CurrentGamePadStates[i] = GamePad.GetState((PlayerIndex)i);
 
                 // Keep track of whether a gamepad has ever been

+ 4 - 4
NetworkStateManagement/Core/Screens/MainMenuScreen.cs

@@ -26,20 +26,20 @@ namespace NetworkStateManagement
 		{
 			// Create our menu entries.
 			MenuEntry singlePlayerMenuEntry = new MenuEntry(Resources.SinglePlayer);
-			MenuEntry liveMenuEntry = new MenuEntry(Resources.PlayerMatch);
+			// TODO MenuEntry liveMenuEntry = new MenuEntry(Resources.PlayerMatch);
 			MenuEntry systemLinkMenuEntry = new MenuEntry(Resources.SystemLink);
 			MenuEntry exitMenuEntry = new MenuEntry(Resources.Exit);
 
 			// Hook up menu event handlers.
 			singlePlayerMenuEntry.Selected += SinglePlayerMenuEntrySelected;
-			liveMenuEntry.Selected += LiveMenuEntrySelected;
+			// TODO liveMenuEntry.Selected += LiveMenuEntrySelected;
 			systemLinkMenuEntry.Selected += SystemLinkMenuEntrySelected;
 			exitMenuEntry.Selected += OnCancel;
 
 			// Add entries to the menu.
-			MenuEntries.Add(singlePlayerMenuEntry);
-			MenuEntries.Add(liveMenuEntry);
+			// TODO MenuEntries.Add(liveMenuEntry);
 			MenuEntries.Add(systemLinkMenuEntry);
+			MenuEntries.Add(singlePlayerMenuEntry);
 			MenuEntries.Add(exitMenuEntry);
 		}
 

+ 2 - 2
NetworkStateManagement/Core/Screens/MenuEntry.cs

@@ -103,7 +103,7 @@ namespace NetworkStateManagement
         {
             // there is no such thing as a selected item on Windows Phone, so we always
             // force isSelected to be false
-#if WINDOWS_PHONE
+#if MOBILE
             isSelected = false;
 #endif
 
@@ -126,7 +126,7 @@ namespace NetworkStateManagement
         {
             // there is no such thing as a selected item on Windows Phone, so we always
             // force isSelected to be false
-#if WINDOWS_PHONE
+#if MOBILE
             isSelected = false;
 #endif
 

+ 2 - 2
NetworkStateManagement/Platforms/Android/NetworkStateManagement.Android.csproj

@@ -3,7 +3,7 @@
     <OutputType>Exe</OutputType>
     <TargetFramework>net8.0-android</TargetFramework>
     <RootNamespace>NetworkStateManagement</RootNamespace>
-    <AssemblyName>NetworkStateManagement.Android</AssemblyName>
+    <AssemblyName>NetworkStateManagement</AssemblyName>
     <GenerateAssemblyInfo>true</GenerateAssemblyInfo>
     <AssemblyTitle>NetworkStateManagement</AssemblyTitle>
     <AssemblyDescription></AssemblyDescription>
@@ -16,7 +16,7 @@
     <FileVersion>1.0.0.0</FileVersion>
   </PropertyGroup>
   <ItemGroup>
-    <PackageReference Include="MonoGame.Framework.Android" Version="3.8.*" />
+    <PackageReference Include="MonoGame.Framework.Android" Version="3.8.*"/>
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\..\Core\NetworkStateManagement.Core.csproj" />

+ 1 - 1
NetworkStateManagement/Platforms/Desktop/NetworkStateManagement.DesktopGL.csproj

@@ -3,7 +3,7 @@
     <OutputType>Exe</OutputType>
     <TargetFramework>net8.0</TargetFramework>
     <RootNamespace>NetworkStateManagement</RootNamespace>
-    <AssemblyName>NetworkStateManagement.DesktopGL</AssemblyName>
+    <AssemblyName>NetworkStateManagement</AssemblyName>
     <GenerateAssemblyInfo>true</GenerateAssemblyInfo>
     <AssemblyTitle>NetworkStateManagement</AssemblyTitle>
     <AssemblyDescription></AssemblyDescription>

+ 1 - 1
NetworkStateManagement/Platforms/iOS/NetworkStateManagement.iOS.csproj

@@ -3,7 +3,7 @@
     <OutputType>Exe</OutputType>
     <TargetFramework>net8.0-ios</TargetFramework>
     <RootNamespace>NetworkStateManagement</RootNamespace>
-    <AssemblyName>NetworkStateManagement.iOS</AssemblyName>
+    <AssemblyName>NetworkStateManagement</AssemblyName>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <AssemblyTitle>NetworkStateManagement</AssemblyTitle>
     <AssemblyDescription></AssemblyDescription>