- tweak: Change content hold think
This commit is contained in:
@@ -75,5 +75,5 @@ public sealed class FileApi : IReadWriteFileApi
|
||||
return File.Exists(fullPath);
|
||||
}
|
||||
|
||||
public IEnumerable<string> AllFiles => Directory.EnumerateFiles(RootPath, "*.*", SearchOption.AllDirectories);
|
||||
public IEnumerable<string> AllFiles => Directory.EnumerateFiles(RootPath, "*.*", SearchOption.AllDirectories).Select(p=>p.Replace(RootPath,"").Substring(1));
|
||||
}
|
||||
@@ -1,4 +1,7 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Collections.Frozen;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Nebula.Shared.FileApis.Interfaces;
|
||||
using Nebula.Shared.Models;
|
||||
using Robust.LoaderApi;
|
||||
|
||||
@@ -6,26 +9,59 @@ namespace Nebula.Shared.FileApis;
|
||||
|
||||
public class HashApi : IFileApi
|
||||
{
|
||||
private readonly IFileApi _fileApi;
|
||||
public Dictionary<string, RobustManifestItem> Manifest;
|
||||
private readonly IReadWriteFileApi _fileApi;
|
||||
private readonly Dictionary<string, RobustManifestItem> _manifest;
|
||||
public IReadOnlyDictionary<string, RobustManifestItem> Manifest => _manifest;
|
||||
|
||||
public HashApi(List<RobustManifestItem> manifest, IFileApi fileApi)
|
||||
public HashApi(List<RobustManifestItem> manifest, IReadWriteFileApi fileApi)
|
||||
{
|
||||
_fileApi = fileApi;
|
||||
Manifest = new Dictionary<string, RobustManifestItem>();
|
||||
foreach (var item in manifest) Manifest.TryAdd(item.Path, item);
|
||||
_manifest = new Dictionary<string, RobustManifestItem>();
|
||||
foreach (var item in manifest) _manifest.TryAdd(item.Path, item);
|
||||
}
|
||||
|
||||
public bool TryOpen(string path,[NotNullWhen(true)] out Stream? stream)
|
||||
{
|
||||
if (path[0] == '/') path = path.Substring(1);
|
||||
|
||||
if (Manifest.TryGetValue(path, out var a) && _fileApi.TryOpen(a.Hash, out stream))
|
||||
if (_manifest.TryGetValue(path, out var a) && _fileApi.TryOpen(GetManifestPath(a), out stream))
|
||||
return true;
|
||||
|
||||
stream = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public IEnumerable<string> AllFiles => Manifest.Keys;
|
||||
public bool TryOpen(RobustManifestItem item ,[NotNullWhen(true)] out Stream? stream){
|
||||
if(_fileApi.TryOpen(GetManifestPath(item), out stream))
|
||||
return true;
|
||||
|
||||
stream = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool TryOpenByHash(string hash ,[NotNullWhen(true)] out Stream? stream){
|
||||
if(_fileApi.TryOpen(GetManifestPath(hash), out stream))
|
||||
return true;
|
||||
|
||||
stream = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool Save(RobustManifestItem item, Stream stream){
|
||||
return _fileApi.Save(GetManifestPath(item), stream);
|
||||
}
|
||||
|
||||
public bool Has(RobustManifestItem item){
|
||||
return _fileApi.Has(GetManifestPath(item));
|
||||
}
|
||||
|
||||
private string GetManifestPath(RobustManifestItem item){
|
||||
return GetManifestPath(item.Hash);
|
||||
}
|
||||
|
||||
public static string GetManifestPath(string hash){
|
||||
return hash[0].ToString() + hash[1].ToString() + '/' + hash;
|
||||
}
|
||||
|
||||
public IEnumerable<string> AllFiles => _manifest.Keys;
|
||||
}
|
||||
@@ -4,7 +4,7 @@ public class LoginInfo
|
||||
{
|
||||
public Guid UserId { get; set; }
|
||||
public string Username { get; set; } = default!;
|
||||
public LoginToken Token { get; set; }
|
||||
public LoginToken Token { get; set; } = default!;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@ namespace Nebula.Shared.Models;
|
||||
|
||||
public class RobustBuildInfo
|
||||
{
|
||||
public ServerInfo BuildInfo;
|
||||
public ServerInfo BuildInfo = default!;
|
||||
public RobustManifestInfo RobustManifestInfo;
|
||||
public RobustUrl Url;
|
||||
public RobustUrl Url = default!;
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Globalization;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Numerics;
|
||||
using Nebula.Shared.FileApis;
|
||||
using Nebula.Shared.FileApis.Interfaces;
|
||||
using Nebula.Shared.Models;
|
||||
using Nebula.Shared.Utils;
|
||||
@@ -15,7 +16,7 @@ public partial class ContentService
|
||||
return fileService.ContentFileApi.Has(item.Hash);
|
||||
}
|
||||
|
||||
public async Task<List<RobustManifestItem>> EnsureItems(ManifestReader manifestReader, Uri downloadUri,
|
||||
public async Task<HashApi> EnsureItems(ManifestReader manifestReader, Uri downloadUri,
|
||||
ILoadingHandler loadingHandler,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
@@ -25,26 +26,22 @@ public partial class ContentService
|
||||
while (manifestReader.TryReadItem(out var item))
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
debugService.Log("ensuring is cancelled!");
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!CheckManifestExist(item.Value))
|
||||
items.Add(item.Value);
|
||||
throw new TaskCanceledException();
|
||||
|
||||
allItems.Add(item.Value);
|
||||
}
|
||||
|
||||
var hashApi = new HashApi(allItems, fileService.ContentFileApi);
|
||||
|
||||
items = allItems.Where(a=> !hashApi.Has(a)).ToList();
|
||||
|
||||
debugService.Log("Download Count:" + items.Count);
|
||||
await Download(downloadUri, items, hashApi, loadingHandler, cancellationToken);
|
||||
|
||||
await Download(downloadUri, items, loadingHandler, cancellationToken);
|
||||
|
||||
fileService.ManifestItems = allItems;
|
||||
|
||||
return allItems;
|
||||
return hashApi;
|
||||
}
|
||||
|
||||
public async Task<List<RobustManifestItem>> EnsureItems(RobustManifestInfo info, ILoadingHandler loadingHandler,
|
||||
public async Task<HashApi> EnsureItems(RobustManifestInfo info, ILoadingHandler loadingHandler,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
debugService.Log("Getting manifest: " + info.Hash);
|
||||
@@ -71,11 +68,12 @@ public partial class ContentService
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
debugService.Log("Unpack manifest files");
|
||||
var items = await EnsureItems(info, loadingHandler, cancellationToken);
|
||||
var hashApi = await EnsureItems(info, loadingHandler, cancellationToken);
|
||||
var items = hashApi.Manifest.Values.ToList();
|
||||
loadingHandler.AppendJob(items.Count);
|
||||
foreach (var item in items)
|
||||
{
|
||||
if (fileService.ContentFileApi.TryOpen(item.Hash, out var stream))
|
||||
if (hashApi.TryOpen(item, out var stream))
|
||||
{
|
||||
debugService.Log($"Unpack {item.Hash} to: {item.Path}");
|
||||
otherApi.Save(item.Path, stream);
|
||||
@@ -90,7 +88,7 @@ public partial class ContentService
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Download(Uri contentCdn, List<RobustManifestItem> toDownload, ILoadingHandler loadingHandler,
|
||||
public async Task Download(Uri contentCdn, List<RobustManifestItem> toDownload, HashApi hashApi, ILoadingHandler loadingHandler,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
if (toDownload.Count == 0 || cancellationToken.IsCancellationRequested)
|
||||
@@ -189,10 +187,6 @@ public partial class ContentService
|
||||
EnsureBuffer(ref readBuffer, length);
|
||||
var data = readBuffer.AsMemory(0, length);
|
||||
|
||||
// Data to write to database.
|
||||
var compression = ContentCompressionScheme.None;
|
||||
var writeData = data;
|
||||
|
||||
if (preCompressed)
|
||||
{
|
||||
// Compressed length from extended header.
|
||||
@@ -210,10 +204,6 @@ public partial class ContentService
|
||||
|
||||
if (decompressedLength != data.Length)
|
||||
throw new Exception($"Compressed blob {i} had incorrect decompressed size!");
|
||||
|
||||
// Set variables so that the database write down below uses them.
|
||||
compression = ContentCompressionScheme.ZStd;
|
||||
writeData = compressedData;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -225,25 +215,8 @@ public partial class ContentService
|
||||
await stream.ReadExactAsync(data, null);
|
||||
}
|
||||
|
||||
if (!preCompressed)
|
||||
{
|
||||
// File wasn't pre-compressed. We should try to manually compress it to save space in DB.
|
||||
|
||||
|
||||
EnsureBuffer(ref compressBuffer, ZStd.CompressBound(data.Length));
|
||||
var compressLength = compressContext!.Compress(compressBuffer, data.Span);
|
||||
|
||||
// Don't bother saving compressed data if it didn't save enough space.
|
||||
if (compressLength + 10 < length)
|
||||
{
|
||||
// Set variables so that the database write down below uses them.
|
||||
compression = ContentCompressionScheme.ZStd;
|
||||
writeData = compressBuffer.AsMemory(0, compressLength);
|
||||
}
|
||||
}
|
||||
|
||||
using var fileStream = new MemoryStream(data.ToArray());
|
||||
fileService.ContentFileApi.Save(item.Hash, fileStream);
|
||||
hashApi.Save(item, fileStream);
|
||||
|
||||
debugService.Log("file saved:" + item.Path);
|
||||
loadingHandler.AppendResolvedJob();
|
||||
|
||||
@@ -14,14 +14,11 @@ public class FileService
|
||||
Environment.SpecialFolder.ApplicationData), "Datum");
|
||||
|
||||
private readonly DebugService _debugService;
|
||||
public readonly IReadWriteFileApi ConfigurationApi;
|
||||
|
||||
public readonly IReadWriteFileApi ConfigurationApi;
|
||||
public readonly IReadWriteFileApi ContentFileApi;
|
||||
public readonly IReadWriteFileApi EngineFileApi;
|
||||
public readonly IReadWriteFileApi ManifestFileApi;
|
||||
|
||||
private HashApi? _hashApi;
|
||||
|
||||
public FileService(DebugService debugService)
|
||||
{
|
||||
_debugService = debugService;
|
||||
@@ -29,21 +26,15 @@ public class FileService
|
||||
EngineFileApi = CreateFileApi("engine");
|
||||
ManifestFileApi = CreateFileApi("manifest");
|
||||
ConfigurationApi = CreateFileApi("config");
|
||||
}
|
||||
|
||||
public List<RobustManifestItem> ManifestItems
|
||||
{
|
||||
set => _hashApi = new HashApi(value, ContentFileApi);
|
||||
}
|
||||
|
||||
public HashApi HashApi
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_hashApi is null) throw new Exception("Hash API is not initialized!");
|
||||
return _hashApi;
|
||||
// Some migrating think
|
||||
foreach(var file in ContentFileApi.AllFiles){
|
||||
if(file.Contains("\\") || !ContentFileApi.TryOpen(file, out var stream)) continue;
|
||||
|
||||
ContentFileApi.Save(HashApi.GetManifestPath(file), stream);
|
||||
stream.Dispose();
|
||||
ContentFileApi.Remove(file);
|
||||
}
|
||||
set => _hashApi = value;
|
||||
}
|
||||
|
||||
public IReadWriteFileApi CreateFileApi(string path)
|
||||
|
||||
@@ -8,7 +8,6 @@ public sealed class RunnerService(
|
||||
ContentService contentService,
|
||||
DebugService debugService,
|
||||
ConfigurationService varService,
|
||||
FileService fileService,
|
||||
EngineService engineService,
|
||||
AssemblyService assemblyService)
|
||||
{
|
||||
@@ -20,7 +19,7 @@ public sealed class RunnerService(
|
||||
var engine = await engineService.EnsureEngine(buildInfo.BuildInfo.Build.EngineVersion);
|
||||
|
||||
if (engine is null)
|
||||
throw new Exception("Engine version is not usable: " + buildInfo.BuildInfo.Build.EngineVersion);
|
||||
throw new Exception("Engine version not found: " + buildInfo.BuildInfo.Build.EngineVersion);
|
||||
|
||||
await contentService.EnsureItems(buildInfo.RobustManifestInfo, loadingHandler, cancellationToken);
|
||||
await engineService.EnsureEngineModules("Robust.Client.WebView", buildInfo.BuildInfo.Build.EngineVersion);
|
||||
@@ -35,13 +34,13 @@ public sealed class RunnerService(
|
||||
var engine = await engineService.EnsureEngine(buildInfo.BuildInfo.Build.EngineVersion);
|
||||
|
||||
if (engine is null)
|
||||
throw new Exception("Engine version is not usable: " + buildInfo.BuildInfo.Build.EngineVersion);
|
||||
throw new Exception("Engine version not found: " + buildInfo.BuildInfo.Build.EngineVersion);
|
||||
|
||||
await contentService.EnsureItems(buildInfo.RobustManifestInfo, loadingHandler, cancellationToken);
|
||||
var hashApi = await contentService.EnsureItems(buildInfo.RobustManifestInfo, loadingHandler, cancellationToken);
|
||||
|
||||
var extraMounts = new List<ApiMount>
|
||||
{
|
||||
new(fileService.HashApi, "/")
|
||||
new(hashApi, "/")
|
||||
};
|
||||
|
||||
var module =
|
||||
|
||||
Reference in New Issue
Block a user