mirror of
https://github.com/Facepunch/sbox-public.git
synced 2026-01-27 15:50:36 -05:00
Adds a universal way to get thumbnail images. - `thumb:entities/sents/npc/scientist.sent` - resources/assets - `thumb:mount://ns2/ns2/models/effects/exosuit_part1.model.vmdl` -mount files - `thumb:facepunch.snowman` - packages This greatly simplifies UI like the spawnmenu that needs to show thumbnails for these things. We also add `AssetTypeFlags.IncludeThumbnails`. If this is set then when the package is published, any asset types with this flag will include a "[path].c.png" thumbnail image of it. Also does Api++ protocol increase.
226 lines
5.5 KiB
C#
226 lines
5.5 KiB
C#
using Sandbox.Engine;
|
|
using System.Reflection;
|
|
|
|
namespace Sandbox.Mounting;
|
|
|
|
public static class Directory
|
|
{
|
|
static MountHost _system;
|
|
|
|
/// <summary>
|
|
/// Load the assemblies and collect sources. That's all.
|
|
/// </summary>
|
|
internal static void LoadAssemblies()
|
|
{
|
|
// Create system first.
|
|
var config = new Configuration();
|
|
config.SteamIntegration = new SteamIntegration();
|
|
_system = new MountHost( config );
|
|
|
|
//
|
|
// Loop each folder in mount/, look for /mount/x/x.dll and load it.
|
|
//
|
|
foreach ( var file in System.IO.Directory.EnumerateDirectories( "mount/" ) )
|
|
{
|
|
var folderName = System.IO.Path.GetFileName( file );
|
|
var assemblyName = System.IO.Path.Combine( file, folderName + ".dll" );
|
|
|
|
if ( !System.IO.File.Exists( assemblyName ) )
|
|
{
|
|
Log.Warning( $"Couldn't find {assemblyName} - skipping." );
|
|
continue;
|
|
}
|
|
|
|
assemblyName = System.IO.Path.GetFullPath( assemblyName );
|
|
|
|
try
|
|
{
|
|
var assembly = Assembly.LoadFile( assemblyName );
|
|
AddAssembly( assembly );
|
|
}
|
|
catch ( System.Exception e )
|
|
{
|
|
Log.Warning( e, $"Exception when loading {assemblyName}" );
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get information about all the current mounts
|
|
/// </summary>
|
|
public static MountInfo[] GetAll()
|
|
{
|
|
return _system.All.Select( e => new MountInfo( e ) ).ToArray();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get a specific mount by name
|
|
/// </summary>
|
|
public static BaseGameMount Get( string name )
|
|
{
|
|
return _system.GetSource( name );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Mount this game if we can. Returns null if it can't be mounted, or the mount object if it can.
|
|
/// If we're already mounted, will just return the mount straight away.
|
|
/// </summary>
|
|
public static async Task<BaseGameMount> Mount( string name )
|
|
{
|
|
var source = _system.GetSource( name );
|
|
if ( source is null ) return null;
|
|
if ( source.IsMounted ) return source;
|
|
if ( source.IsInstalled == false ) return source;
|
|
|
|
await SetMountState( name, true );
|
|
|
|
if ( !source.IsMounted ) return null;
|
|
|
|
return source;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set mounted or not mounted. Called by user via editor.
|
|
/// </summary>
|
|
internal static async Task SetMountState( string name, bool state )
|
|
{
|
|
var source = _system.GetSource( name );
|
|
if ( source is null ) return;
|
|
if ( state == source.IsMounted ) return;
|
|
if ( source.IsInstalled == false ) return;
|
|
|
|
if ( !state )
|
|
{
|
|
_system.Unmount( name );
|
|
}
|
|
else
|
|
{
|
|
TryMountFilesystem( name );
|
|
await _system.Mount( name );
|
|
}
|
|
|
|
if ( source.IsMounted )
|
|
{
|
|
IToolsDll.Current?.RunEvent<IMountEvents>( x => x.OnMountEnabled( Get( name ) ) );
|
|
}
|
|
else
|
|
{
|
|
IToolsDll.Current?.RunEvent<IMountEvents>( x => x.OnMountDisabled( Get( name ) ) );
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// If /mount/{x}/assets exists, add it to our filesystem
|
|
/// </summary>
|
|
static void TryMountFilesystem( string name )
|
|
{
|
|
var path = EngineFileSystem.Root.GetFullPath( $"/mount/{name}/assets" );
|
|
if ( string.IsNullOrWhiteSpace( path ) ) return;
|
|
if ( !System.IO.Directory.Exists( path ) ) return;
|
|
|
|
EngineFileSystem.AddAssetPath( $"mnt_{name}", path );
|
|
}
|
|
|
|
internal static bool TryLoad( string filename, ResourceType type, out object resource )
|
|
{
|
|
resource = default;
|
|
|
|
if ( !filename.StartsWith( "mount://" ) ) return false;
|
|
|
|
var sourceName = filename.Substring( 8 );
|
|
|
|
var i = sourceName.IndexOf( '/' );
|
|
sourceName = sourceName.Substring( 0, i );
|
|
|
|
var source = Get( sourceName );
|
|
if ( source is null )
|
|
{
|
|
Log.Warning( $"Couldn't find source \"{source}\"" );
|
|
return false;
|
|
}
|
|
|
|
var entry = source.Resources.FirstOrDefault( x => string.Equals( x.Path, filename, StringComparison.OrdinalIgnoreCase ) );
|
|
if ( entry is null )
|
|
{
|
|
Log.Warning( $"Couldn't find file \"{filename}\" in {source.Ident}" );
|
|
return false;
|
|
}
|
|
|
|
resource = SyncContext.RunBlocking( entry.GetOrCreate() );
|
|
|
|
if ( resource is null )
|
|
{
|
|
Log.Warning( $"Loading \"{filename}\" returned null!" );
|
|
return false;
|
|
}
|
|
|
|
return resource is not null;
|
|
}
|
|
|
|
internal static async Task<object> TryLoadAsync( string filename, ResourceType type )
|
|
{
|
|
if ( !filename.StartsWith( "mount://" ) ) return null;
|
|
|
|
var sourceName = filename.Substring( 8 );
|
|
|
|
var i = sourceName.IndexOf( '/' );
|
|
sourceName = sourceName.Substring( 0, i );
|
|
|
|
var source = Get( sourceName );
|
|
if ( source is null )
|
|
{
|
|
Log.Warning( $"Couldn't find source \"{source}\"" );
|
|
return null;
|
|
}
|
|
|
|
var entry = source.Resources.FirstOrDefault( x => string.Equals( x.Path, filename, StringComparison.OrdinalIgnoreCase ) );
|
|
if ( entry is null )
|
|
{
|
|
Log.Warning( $"Couldn't find file \"{filename}\" in {source.Ident}" );
|
|
return null;
|
|
}
|
|
|
|
var resource = await entry.GetOrCreate();
|
|
|
|
if ( resource is null )
|
|
{
|
|
Log.Warning( $"Loading \"{filename}\" returned null!" );
|
|
return null;
|
|
}
|
|
|
|
return resource;
|
|
}
|
|
|
|
internal static void AddAssembly( Assembly assembly )
|
|
{
|
|
_system.RegisterTypes( assembly );
|
|
}
|
|
|
|
internal static void RemoveAssembly( Assembly assembly )
|
|
{
|
|
_system.UnregisterTypes( assembly );
|
|
}
|
|
}
|
|
|
|
|
|
class SteamIntegration : ISteamIntegration
|
|
{
|
|
public string GetAppDirectory( long appid )
|
|
{
|
|
if ( !NativeEngine.Steam.SteamApps().IsValid ) return string.Empty;
|
|
return NativeEngine.Steam.SteamApps().GetAppInstallDir( (int)appid );
|
|
}
|
|
|
|
public bool IsAppInstalled( long appid )
|
|
{
|
|
if ( !NativeEngine.Steam.SteamApps().IsValid ) return false;
|
|
return NativeEngine.Steam.SteamApps().BIsAppInstalled( (int)appid );
|
|
}
|
|
|
|
public bool IsDlcInstalled( long appid )
|
|
{
|
|
if ( !NativeEngine.Steam.SteamApps().IsValid ) return false;
|
|
return NativeEngine.Steam.SteamApps().BIsDlcInstalled( (int)appid );
|
|
}
|
|
}
|