using Sandbox.Engine; using Sandbox.Engine.Settings; using Sandbox.Modals; using Sandbox.Services; using System; using System.Net; namespace Sandbox; [Hide] public static partial class MenuUtility { public static Action Tick { get; set; } public static void SetModalSystem( IModalSystem system ) { IModalSystem.Current = system; } public static void AddLogger( Action logger ) { Sandbox.Diagnostics.Logging.OnMessage += logger; } public static void RemoveLogger( Action logger ) { Sandbox.Diagnostics.Logging.OnMessage -= logger; } public static ConCmdAttribute.AutoCompleteResult[] AutoComplete( string text, int maxCount ) { return ConVarSystem.GetAutoComplete( text, maxCount ); } public static void SkipAllTransitions() { IMenuDll.Current?.RunEvent( "ui.skiptransitions" ); } /// /// If current game is active, return the package /// public static Package GamePackage => Application.GamePackage; /// /// Init a stream service /// public static async Task ConnectStream( StreamService service ) { return await Sandbox.Engine.Streamer.Init( service ); } /// /// Init a stream service /// public static void DisconnectStream() { Sandbox.Engine.Streamer.Shutdown(); } public static SceneWorld CreateSceneWorld() { return new SceneWorld { IsTransient = false }; } #nullable enable /// /// Open an 'open file' dialog /// public static string? OpenFileDialog() { var r = NativeEngine.WindowsGlue.FindFile(); if ( string.IsNullOrEmpty( r ) ) return null; return r; } #nullable disable /// /// Open a folder /// public static void OpenFolder( string path ) { System.Diagnostics.Process.Start( new System.Diagnostics.ProcessStartInfo() { FileName = path, UseShellExecute = true, Verb = "open" } ); } /// /// Open a url /// public static void OpenUrl( string path ) { System.Diagnostics.Process.Start( new System.Diagnostics.ProcessStartInfo() { FileName = path, UseShellExecute = true, Verb = "open" } ); } static List _friendList; /// /// Get all friends. /// public static IEnumerable Friends { get { // // querying this once should be enough, unless they add a new friend or something // if ( _friendList is null ) { _friendList = Steamworks.SteamFriends.GetFriends().Select( x => new Friend( x ) ).ToList(); } return _friendList; } } /// /// Number of seconds escape has been held down /// public static float EscapeTime => InputRouter.EscapeTime; /// /// Join the game a friend is in /// public static void JoinFriendGame( Friend friend ) { var connectString = friend.GetRichPresence( "connect" ); if ( string.IsNullOrWhiteSpace( connectString ) ) return; connectString = connectString.Replace( "+connect", "" ); connectString = connectString.Replace( " ", "" ); // Should be left with a Steam Id but otherwise try connecting by IP. if ( ulong.TryParse( connectString, out ulong lobbySteamId ) ) { ConsoleSystem.Run( $"connect {lobbySteamId}" ); } else { var ipAddress = IPEndPoint.Parse( connectString ); ConsoleSystem.Run( $"connect {ipAddress}" ); } } /// /// We might be running the game from sbox.game, so we want the menu system to open the game immediately /// public static string StartupGameIdent => Utility.CommandLine.GetSwitch( "-rungame", null ); /// /// This is called when the cancel button is pressed when loading. /// We should disconnect and leave the game. /// public static void CancelLoading() { // Close the game CloseGame(); // Close the loading screen LoadingScreen.IsVisible = false; } /// /// Set a console variable. Unlike ConsoleSystem.*, this is unprotected and allows any console variable to be changed. /// public static void SetConsoleVariable( string name, object value ) { ConVarSystem.SetValue( name, value?.ToString(), true ); } /// /// Access to the client's render settings /// public static RenderSettings RenderSettings => Sandbox.Engine.Settings.RenderSettings.Instance; /// /// Listen to the voice /// public static void SetVoiceListen( bool b ) { if ( b ) { PartyRoom.Current?.SetBroadcastVoice(); } } /// /// Close every open modal /// public static void CloseAllModals() { IModalSystem.Current?.CloseAll(); } /// /// Get the player's friend activity feed /// public static Task GetPlayerFeed( int take = 20 ) => Feed.GetFeed( take ); /// /// How many notifications does the player have? /// public static Task GetNotificationCount() => Notification.GetCount(); /// /// Mark the player's notifications as all read. Call when viewing notifications. /// public static Task MarkNotificationsRead() => Notification.MarkRead(); /// /// Get a list of notifications /// public static Task GetNotifications( int count ) => Notification.Get( count ); /// /// Get a list of recent achievement progress /// public static Task GetAchievementOverviews( int count ) => AchievementOverview.GetFeed( count ); /// /// Get a list of recent achievement progress /// public static Task SaveAvatar( ClothingContainer container, bool isActive, int slot ) => container.Store( isActive, slot ); /// /// Delete avatar in slot x /// public static Task DeleteAvatar( int slot ) { return Backend.Storage.Delete( (long)Utility.Steam.SteamId, "facepunch.avatar", "avatar", $"{slot}" ); } /// /// Delete all avatars, return to default /// public static async Task DeleteAvatars() { await Backend.Storage.Drop( (long)Utility.Steam.SteamId, "facepunch.avatar", "avatar" ); await Backend.Storage.Drop( (long)Utility.Steam.SteamId, "facepunch.avatar", "avatar.active" ); } /// /// Invite someone to the current party. If one exists /// public static void InviteToParty( SteamId steamid ) { PartyRoom.Current?.InviteFriend( steamid ); } /// /// Opens the invite overlay /// public static void InviteOverlayToParty() { PartyRoom.Current?.InviteFriend(); } /// /// Post a review for a package /// public static Task PostReview( string packageIdent, Sandbox.Services.Review.ReviewScore score, string content ) { return Sandbox.Services.Review.Post( packageIdent, score, content ); } /// /// Allows async tasks to wait to be executed in the menu context /// public static void RunTask( Func func ) { if ( Application.IsEditor ) func(); // Post the *whole* function into the target context MenuDll.AsyncContext.Post( async _ => { await func().ConfigureAwait( true ); }, null ); } } public class StoragePublish { Ugc.UgcPublisher item; public ulong ItemId => item?.ItemId ?? 0; public string Title { get; set; } public string Description { get; set; } public string Metadata { get; set; } public Storage.Visibility Visibility { get; set; } = Storage.Visibility.Public; public Dictionary KeyValues { get; set; } public HashSet Tags { get; set; } public Bitmap Thumbnail { get; set; } public BaseFileSystem FileSystem { get; set; } public async Task Submit() { item = await Sandbox.Services.Ugc.CreateCommunityItem(); string _imagePath = null; string _dataPath = null; item.SetTitle( Title ); item.SetDescription( Description ); item.SetMetaData( Metadata ); item.SetVisibility( Visibility ); if ( KeyValues != null ) { foreach ( var kv in KeyValues ) { item.SetKeyValue( kv.Key, kv.Value ); } } if ( Tags != null ) { foreach ( var tag in Tags ) { item.SetTag( tag ); } } // Save thumbnail to a temp file if ( Thumbnail != null ) { _imagePath = System.IO.Path.GetTempFileName() + ".png"; System.IO.File.WriteAllBytes( _imagePath, Thumbnail.ToPng() ); item.SetPreviewImage( _imagePath ); } // Copy files from virtual filesystem to a temp folder if ( FileSystem != null ) { _dataPath = System.IO.Path.GetTempPath() + "/" + System.Guid.NewGuid().ToString(); var files = FileSystem.FindFile( "/", "*", true ); foreach ( var file in files ) { var srcPath = System.IO.Path.Combine( "/", file ); var destPath = System.IO.Path.Combine( _dataPath, file ); System.IO.Directory.CreateDirectory( System.IO.Path.GetDirectoryName( destPath ) ); System.IO.File.WriteAllBytes( destPath, FileSystem.ReadAllBytes( srcPath ) ); } item.SetContentFile( _dataPath ); } item.SetKeyValue( "package", Game.Ident ); // TODO - walk the stack to determine what called it? item.SetKeyValue( "version", Application.Version ); await item.Submit(); if ( _imagePath != null ) System.IO.File.Delete( _imagePath ); if ( _dataPath != null ) System.IO.Directory.Delete( _dataPath, true ); } public float PercentComplete => item?.PercentComplete ?? 0f; public bool IsPublishing => item?.IsPublishing ?? false; public bool IsFinished => item?.IsFinished ?? false; }