Editor/sandmod.libraryplus/LibrarySystemPlus.cs
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Threading;
using Editor;
using Sandbox;
using Sandbox.Diagnostics;
namespace LibraryPlus;
public static class LibrarySystemPlus
{
internal static readonly Logger Log = new("LibraryPlus");
private static readonly LibraryProject Self = LibrarySystem.All.First( library =>
library.Project.Package.IsLibraryPlus() );
internal static readonly DirectoryInfo Root = Self.Project.RootDirectory;
private static readonly HashSet<PlusLibrary> PlusCache = [];
private static readonly HashSet<ProjectLibrary> ProjectCache = [];
static LibrarySystemPlus()
{
foreach ( var library in LibrarySystem.All )
{
ProjectCache.Add( new ProjectLibrary( library ) );
}
var settingsPath = Path.Combine( Root.FullName, "Settings" );
if ( Directory.Exists( settingsPath ) )
{
foreach ( var filePath in Directory.EnumerateFiles( settingsPath, "*.sbproj",
SearchOption.AllDirectories ) )
{
var configString = File.ReadAllText( filePath );
var config = JsonSerializer.Deserialize<LibraryConfig>( configString );
var package = GetPackage( config );
PlusCache.Add( new PlusLibrary( package ) );
}
}
}
public static IEnumerable<Library> All
{
get
{
var uncachedHash = LibrarySystem.All.GetHashCode();
var cachedHash = ProjectCache.Select( project => project.Project ).GetHashCode();
if ( uncachedHash != cachedHash )
{
ProjectCache.RemoveWhere( cached => LibrarySystem.All.All( uncached => uncached != cached.Project ) );
foreach ( var library in LibrarySystem.All.Where( uncached =>
ProjectCache.All( cached => cached.Project != uncached ) ) )
{
ProjectCache.Add( new ProjectLibrary( library ) );
}
}
return PlusCache.Cast<Library>().Concat( ProjectCache );
}
}
public static IEnumerable<PlusLibrary> AllPlus =>
All.Where( l => l is PlusLibrary ).Cast<PlusLibrary>();
public static IEnumerable<ProjectLibrary> AllProject =>
All.Where( l => l is ProjectLibrary ).Cast<ProjectLibrary>();
public static void Install( string ident, long versionId )
{
LibrarySystem.Install( ident, versionId );
}
public static void Remove( Library library )
{
if ( library is ProjectLibrary projectLibrary )
{
projectLibrary.Project.RemoveAndDelete();
ProjectCache.Remove( projectLibrary );
}
else if ( library is PlusLibrary plusLibrary )
{
PlusCache.Remove( plusLibrary );
}
library.FileSystem.Delete();
}
public static void AddReference( Library library, Reference reference )
{
library.Config.LibraryReferences.Add( reference.Ident, reference );
library.SaveConfig();
}
public static void RemoveReference( Library library, string reference )
{
library.Config.LibraryReferences.Remove( reference );
library.SaveConfig();
}
internal static void Convert( ProjectLibrary library )
{
if ( library.IsLibraryPlus() )
{
Log.Warning(
$"{library.Package.ReferenceIdent()} can't be converted to plus library as this would break the library" );
return;
}
// Move to temp library first to update reference files
// This is done to prevent compiler errors while updating the files
var tempFileSystem = new TempFileSystem( library.Package.ReferenceIdent() );
library.FileSystem.Move( tempFileSystem );
new TempLibrary( library.Package, true ).UpdateReferenceFiles();
var targetFileSystem = new PlusFileSystem( library.Package.ReferenceIdent() );
tempFileSystem.Move( targetFileSystem );
library.Project.RemoveAndDelete();
PlusCache.Add( new PlusLibrary( library.Package ) );
ProjectCache.Remove( library );
UpdatePreprocessors();
}
internal static void Convert( PlusLibrary library )
{
// Move to temp library first to update reference files
// This is done to prevent compiler errors while updating the files
var tempFileSystem = new TempFileSystem( library.Package.ReferenceIdent() );
library.FileSystem.Move( tempFileSystem );
new TempLibrary( library.Package, false ).UpdateReferenceFiles();
var targetFileSystem = new ProjectFileSystem( library.Package.ReferenceIdent() );
tempFileSystem.Move( targetFileSystem );
LibrarySystem.Add( library.Package.ReferenceIdent(), new CancellationToken( false ) ).Wait();
var projectLibrary =
LibrarySystem.All.First( l => l.Project.Package.ReferenceIdent() == library.Package.ReferenceIdent() );
ProjectCache.Add( new ProjectLibrary( projectLibrary ) );
PlusCache.Remove( library );
UpdatePreprocessors();
}
[Event( "hotloaded", Priority = -1 )]
private static void UpdatePreprocessors()
{
foreach ( var library in All )
{
library.UpdateReferenceFiles();
}
}
internal static void WriteFileIfNeeded( string path, string contents )
{
if ( File.Exists( path ) && File.ReadAllText( path ) == contents )
{
return;
}
File.WriteAllText( path, contents );
}
private static Package GetPackage( LibraryConfig config )
{
/*var fetchedPackage = Package.FetchAsync( Package.FormatIdent( config.Org, config.Ident ), true, true ).Result;
if ( fetchedPackage != null )
{
return fetchedPackage;
}*/
return new Package
{
TypeName = config.Type,
Ident = config.Ident,
Org = new Package.Organization
{
Ident = config.Org, Title = config.Org, Thumb = "/ui/mainmenu/missing_package.png"
},
Title = config.Title,
Thumb = "/ui/mainmenu/missing_package.png",
PackageReferences = config.PackageReferences?.ToArray() ?? [],
EditorReferences = config.EditorReferences?.ToArray() ?? []
};
}
}