2019-01-24 08:43:03 +00:00
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
2018-04-13 09:19:50 +00:00
2022-06-17 07:37:17 +00:00
#nullable disable
2016-08-26 03:28:23 +00:00
using System ;
2016-10-14 18:10:01 +00:00
using System.IO ;
2022-03-02 08:54:33 +00:00
using System.Runtime.Versioning ;
2021-11-28 09:00:06 +00:00
using osu.Desktop.LegacyIpc ;
2017-09-18 13:32:49 +00:00
using osu.Framework ;
2018-08-17 04:28:35 +00:00
using osu.Framework.Development ;
2018-08-03 10:25:55 +00:00
using osu.Framework.Logging ;
2017-09-18 13:32:49 +00:00
using osu.Framework.Platform ;
2022-06-20 19:21:16 +00:00
using osu.Game ;
2016-10-21 09:25:22 +00:00
using osu.Game.IPC ;
2018-11-06 05:49:09 +00:00
using osu.Game.Tournament ;
2022-07-12 06:42:20 +00:00
using SDL2 ;
2022-03-02 08:54:33 +00:00
using Squirrel ;
2018-07-10 11:30:08 +00:00
2017-10-13 17:10:21 +00:00
namespace osu.Desktop
2016-08-26 03:28:23 +00:00
{
public static class Program
{
2021-07-21 06:02:15 +00:00
private const string base_game_name = @"osu" ;
2021-11-28 13:24:42 +00:00
private static LegacyTcpIpcProvider legacyIpc ;
2016-08-26 03:28:23 +00:00
[STAThread]
2021-11-28 05:03:21 +00:00
public static void Main ( string [ ] args )
2016-08-26 03:28:23 +00:00
{
2022-03-02 08:54:33 +00:00
// run Squirrel first, as the app may exit after these run
if ( OperatingSystem . IsWindows ( ) )
2022-07-12 06:42:20 +00:00
{
var windowsVersion = Environment . OSVersion . Version ;
2022-07-12 07:16:46 +00:00
// While .NET 6 still supports Windows 7 and above, we are limited by realm currently, as they choose to only support 8.1 and higher.
// See https://www.mongodb.com/docs/realm/sdk/dotnet/#supported-platforms
if ( windowsVersion . Major < 6 | | ( windowsVersion . Major = = 6 & & windowsVersion . Minor < = 2 ) )
2022-07-12 06:42:20 +00:00
{
SDL . SDL_ShowSimpleMessageBox ( SDL . SDL_MessageBoxFlags . SDL_MESSAGEBOX_ERROR ,
"Your operating system is too old to run osu!" ,
2022-07-12 15:29:17 +00:00
"This version of osu! requires at least Windows 8.1 to run.\nPlease upgrade your operating system or consider using an older version of osu!." , IntPtr . Zero ) ;
2022-07-12 06:42:20 +00:00
return ;
}
2022-03-02 08:54:33 +00:00
setupSquirrel ( ) ;
2022-07-12 06:42:20 +00:00
}
2022-03-02 08:54:33 +00:00
2017-01-30 14:35:59 +00:00
// Back up the cwd before DesktopGameHost changes it
2021-10-27 04:04:41 +00:00
string cwd = Environment . CurrentDirectory ;
2018-04-13 09:19:50 +00:00
2021-07-21 06:02:15 +00:00
string gameName = base_game_name ;
2021-07-21 04:53:24 +00:00
bool tournamentClient = false ;
2021-07-21 00:12:44 +00:00
2021-10-27 04:04:41 +00:00
foreach ( string arg in args )
2021-07-21 00:12:44 +00:00
{
2021-10-27 04:04:41 +00:00
string [ ] split = arg . Split ( '=' ) ;
2021-07-21 06:02:15 +00:00
2021-10-27 04:04:41 +00:00
string key = split [ 0 ] ;
string val = split . Length > 1 ? split [ 1 ] : string . Empty ;
2021-07-21 06:02:15 +00:00
switch ( key )
2021-07-21 04:53:24 +00:00
{
case "--tournament" :
tournamentClient = true ;
break ;
case "--debug-client-id" :
if ( ! DebugUtils . IsDebugBuild )
2021-07-21 06:02:15 +00:00
throw new InvalidOperationException ( "Cannot use this argument in a non-debug build." ) ;
if ( ! int . TryParse ( val , out int clientID ) )
throw new ArgumentException ( "Provided client ID must be an integer." ) ;
2021-07-21 04:53:24 +00:00
2021-07-21 06:02:15 +00:00
gameName = $"{base_game_name}-{clientID}" ;
2021-07-21 04:53:24 +00:00
break ;
}
2021-07-21 00:12:44 +00:00
}
2022-01-25 05:16:15 +00:00
using ( DesktopGameHost host = Host . GetSuitableDesktopHost ( gameName , new HostOptions { BindIPC = true } ) )
2016-10-21 09:25:22 +00:00
{
2016-11-08 00:04:31 +00:00
if ( ! host . IsPrimaryInstance )
{
2022-06-20 19:21:16 +00:00
if ( trySendIPCMessage ( host , cwd , args ) )
2021-11-28 05:03:21 +00:00
return ;
2019-07-23 04:38:05 +00:00
// we want to allow multiple instances to be started when in debug.
if ( ! DebugUtils . IsDebugBuild )
2021-09-21 09:00:54 +00:00
{
Logger . Log ( @"osu! does not support multiple running instances." , LoggingTarget . Runtime , LogLevel . Error ) ;
2021-11-28 05:03:21 +00:00
return ;
2021-09-21 09:00:54 +00:00
}
2016-11-08 00:04:31 +00:00
}
2019-07-23 04:38:05 +00:00
2021-11-28 12:15:29 +00:00
if ( host . IsPrimaryInstance )
{
2021-11-28 13:24:42 +00:00
try
{
Logger . Log ( "Starting legacy IPC provider..." ) ;
legacyIpc = new LegacyTcpIpcProvider ( ) ;
legacyIpc . Bind ( ) ;
}
catch ( Exception ex )
{
Logger . Error ( ex , "Failed to start legacy IPC provider" ) ;
}
2021-11-28 12:15:29 +00:00
}
2021-07-21 04:53:24 +00:00
if ( tournamentClient )
2021-07-21 00:12:44 +00:00
host . Run ( new TournamentGame ( ) ) ;
else
host . Run ( new OsuGameDesktop ( args ) ) ;
2016-11-08 00:04:31 +00:00
}
2016-08-26 03:28:23 +00:00
}
2018-08-03 10:25:55 +00:00
2022-06-20 19:21:16 +00:00
private static bool trySendIPCMessage ( IIpcHost host , string cwd , string [ ] args )
{
if ( args . Length = = 1 & & args [ 0 ] . StartsWith ( OsuGameBase . OSU_PROTOCOL , StringComparison . Ordinal ) )
{
var osuSchemeLinkHandler = new OsuSchemeLinkIPCChannel ( host ) ;
if ( ! osuSchemeLinkHandler . HandleLinkAsync ( args [ 0 ] ) . Wait ( 3000 ) )
throw new IPCTimeoutException ( osuSchemeLinkHandler . GetType ( ) ) ;
return true ;
}
if ( args . Length > 0 & & args [ 0 ] . Contains ( '.' ) ) // easy way to check for a file import in args
{
var importer = new ArchiveImportIPCChannel ( host ) ;
foreach ( string file in args )
{
Console . WriteLine ( @"Importing {0}" , file ) ;
if ( ! importer . ImportAsync ( Path . GetFullPath ( file , cwd ) ) . Wait ( 3000 ) )
throw new IPCTimeoutException ( importer . GetType ( ) ) ;
}
return true ;
}
return false ;
}
2022-03-02 08:54:33 +00:00
[SupportedOSPlatform("windows")]
private static void setupSquirrel ( )
{
2022-06-24 12:25:23 +00:00
SquirrelAwareApp . HandleEvents ( onInitialInstall : ( _ , tools ) = >
2022-03-02 08:54:33 +00:00
{
tools . CreateShortcutForThisExe ( ) ;
2022-03-02 18:54:39 +00:00
tools . CreateUninstallerRegistryEntry ( ) ;
2022-06-24 12:25:23 +00:00
} , onAppUpdate : ( _ , tools ) = >
2022-04-26 05:48:12 +00:00
{
tools . CreateUninstallerRegistryEntry ( ) ;
2022-06-24 12:25:23 +00:00
} , onAppUninstall : ( _ , tools ) = >
2022-03-02 08:54:33 +00:00
{
tools . RemoveShortcutForThisExe ( ) ;
tools . RemoveUninstallerRegistryEntry ( ) ;
2022-06-24 12:25:23 +00:00
} , onEveryRun : ( _ , _ , _ ) = >
2022-03-02 08:54:33 +00:00
{
2022-04-25 09:37:35 +00:00
// While setting the `ProcessAppUserModelId` fixes duplicate icons/shortcuts on the taskbar, it currently
// causes the right-click context menu to function incorrectly.
//
// This may turn out to be non-required after an alternative solution is implemented.
// see https://github.com/clowd/Clowd.Squirrel/issues/24
// tools.SetProcessAppUserModelId();
2022-03-02 08:54:33 +00:00
} ) ;
}
2021-11-28 05:03:21 +00:00
}
2016-08-26 03:28:23 +00:00
}