texture caching

This commit is contained in:
tresabhi committed 2026-06-10 20:12:18 -05:00
1 parent 6395dd3f3d
commit 3299ce069e
6 files changed
+79 -92

No files matched your search

+1 -1
View File
@@ -3,7 +3,7 @@
"isRoot": true, "isRoot": true,
"tools": { "tools": {
"csharpier": { "csharpier": {
"version": "1.2.6", "version": "1.3.0",
"commands": [ "commands": [
"csharpier" "csharpier"
], ],
+68 -60
View File
@@ -1,4 +1,5 @@
using System.Text.RegularExpressions; using System.Text.Json;
using System.Text.RegularExpressions;
using BlitzKit.Game.Models; using BlitzKit.Game.Models;
using CUE4Parse_Conversion; using CUE4Parse_Conversion;
using CUE4Parse_Conversion.Materials; using CUE4Parse_Conversion.Materials;
@@ -28,22 +29,31 @@ public partial class GameInterface
public GameInterface(string directory, string map, string temp) public GameInterface(string directory, string map, string temp)
{ {
Console.WriteLine("GameInterface constructor called");
provider = new(directory, map, temp); provider = new(directory, map, temp);
Console.WriteLine("Provider created");
files = [.. provider.Files.Keys]; files = [.. provider.Files.Keys];
Console.WriteLine("Files loaded");
} }
readonly Dictionary<string, string> texturePaths = new(); readonly Dictionary<string, string> texturePaths = new();
readonly string textureCache = "../../temp/textures.json";
public void DiscoverTextures(string[] tankTags) public void DiscoverTextures(string[] tankTags)
{ {
Console.WriteLine("Discovering textures..."); if (File.Exists(textureCache))
{
Console.WriteLine("Found textures cache");
var content = File.ReadAllText(textureCache);
var cached = JsonSerializer.Deserialize<Dictionary<string, string>>(content);
foreach (var (key, value) in cached)
{
texturePaths[key] = value;
}
return;
}
Console.WriteLine("Textures cache not found, building...");
var options = new ExporterOptions() { TextureFormat = ETextureFormat.Jpeg }; var options = new ExporterOptions() { TextureFormat = ETextureFormat.Jpeg };
@@ -109,6 +119,13 @@ public partial class GameInterface
} }
Console.WriteLine($"Discovered {texturePaths.Count} textures"); Console.WriteLine($"Discovered {texturePaths.Count} textures");
Directory.CreateDirectory(Path.GetDirectoryName(textureCache));
var json = JsonSerializer.Serialize(texturePaths);
File.WriteAllText(textureCache, json);
Console.WriteLine("Saved textures cache");
} }
public List<string> Textures => [.. texturePaths.Keys]; public List<string> Textures => [.. texturePaths.Keys];
@@ -200,62 +217,53 @@ public partial class GameInterface
public byte[] TankPart(string tag, string part) public byte[] TankPart(string tag, string part)
{ {
try var pda = provider.Discovered<UPrimaryDataAsset>(tag);
UDataTable? dataTable = null;
foreach (var (prefix, name) in tankPartPrefixes)
{ {
var pda = provider.Discovered<UPrimaryDataAsset>(tag); if (!part.StartsWith(prefix))
UDataTable? dataTable = null;
foreach (var (prefix, name) in tankPartPrefixes)
{ {
if (!part.StartsWith(prefix)) continue;
{
continue;
}
dataTable = pda.Get<UDataTable>(name);
break;
} }
if (dataTable == null) dataTable = pda.Get<UDataTable>(name);
{ break;
throw new ArgumentException($"Unknown tank part: {part}");
}
dataTable.TryGetDataTableRow(part, StringComparison.Ordinal, out var row);
if (row == null)
{
throw new ArgumentException($"Unknown tank part: {part}");
}
var visualData = row.Get<UObject>("VisualData");
var meshSettings = visualData.Get<FStructFallback>("MeshSettings");
var meshes = new List<UStaticMesh>();
foreach (var property in meshSettings.Properties)
{
var name = property.Name.Text;
if (name == "CollisionMesh")
{
continue;
}
if (meshSettings.TryGet<UStaticMesh>(name, out var mesh))
{
meshes.Add(mesh);
}
}
var gltf = new MonoGltf(meshes);
return gltf.Write($"{tag}/{part}");
}
catch (Exception e)
{
Console.WriteLine(e);
} }
return []; if (dataTable == null)
{
throw new ArgumentException($"Unknown tank part: {part}");
}
dataTable.TryGetDataTableRow(part, StringComparison.Ordinal, out var row);
if (row == null)
{
throw new ArgumentException($"Unknown tank part: {part}");
}
var visualData = row.Get<UObject>("VisualData");
var meshSettings = visualData.Get<FStructFallback>("MeshSettings");
var meshes = new List<UStaticMesh>();
foreach (var property in meshSettings.Properties)
{
var name = property.Name.Text;
if (name == "CollisionMesh")
{
continue;
}
if (meshSettings.TryGet<UStaticMesh>(name, out var mesh))
{
meshes.Add(mesh);
}
}
var gltf = new MonoGltf(meshes);
return gltf.Write($"{tag}/{part}");
} }
} }
+7 -19
View File
@@ -1,19 +1,19 @@
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using CUE4Parse_Conversion.Textures; using CUE4Parse_Conversion.Textures;
using CUE4Parse.Compression; using CUE4Parse.Compression;
using CUE4Parse.FileProvider; using CUE4Parse.FileProvider;
using CUE4Parse.MappingsProvider; using CUE4Parse.MappingsProvider;
using CUE4Parse.UE4.AssetRegistry;
using CUE4Parse.UE4.Assets.Exports;
using CUE4Parse.UE4.Assets.Exports.Texture; using CUE4Parse.UE4.Assets.Exports.Texture;
using CUE4Parse.UE4.Exceptions; using CUE4Parse.UE4.Exceptions;
using CUE4Parse.UE4.Objects.Engine; using CUE4Parse.UE4.Objects.Engine;
using CUE4Parse.UE4.Objects.UObject; using CUE4Parse.UE4.Objects.UObject;
using CUE4Parse.UE4.Readers;
using CUE4Parse.UE4.Versions; using CUE4Parse.UE4.Versions;
using CUE4Parse.Utils; using CUE4Parse.Utils;
using SkiaSharp; using SkiaSharp;
using CUE4Parse.UE4.Readers;
using CUE4Parse.UE4.AssetRegistry;
using System.Text.RegularExpressions;
using CUE4Parse.UE4.Assets.Exports;
namespace BlitzKit.Game.Models; namespace BlitzKit.Game.Models;
@@ -32,28 +32,15 @@ public partial class BlitzFileProvider : DefaultFileProvider
pathComparer: StringComparer.OrdinalIgnoreCase pathComparer: StringComparer.OrdinalIgnoreCase
) )
{ {
Console.WriteLine("BlitzFileProvider constructor called");
MappingsContainer = new FileUsmapTypeMappingsProvider(map); MappingsContainer = new FileUsmapTypeMappingsProvider(map);
Console.WriteLine("MappingsContainer initialized");
Initialize(); Initialize();
Console.WriteLine("Initialize called");
Mount(); Mount();
Console.WriteLine("Mount called"); // string oodlePath = $"{temp}/oodle.so";
string oodlePath = $"{temp}/oodle.so";
// OodleHelper.DownloadOodleDll(ref oodlePath!); // OodleHelper.DownloadOodleDll(ref oodlePath!);
// Console.WriteLine("DownloadOodleDll called");
OodleHelper.Initialize("../../stupid/oodle.so"); OodleHelper.Initialize("../../stupid/oodle.so");
Console.WriteLine("Initialize called");
if (TryGetGameFile("Blitz/AssetRegistry.bin", out var file)) if (TryGetGameFile("Blitz/AssetRegistry.bin", out var file))
{ {
var bytes = file.Read(); var bytes = file.Read();
@@ -78,7 +65,8 @@ public partial class BlitzFileProvider : DefaultFileProvider
} }
} }
public T Discovered<T>(string path) where T : UObject public T Discovered<T>(string path)
where T : UObject
{ {
return LoadPackageObject<T>(discovered[path]); return LoadPackageObject<T>(discovered[path]);
} }
@@ -175,8 +175,10 @@ function Consumables({ characteristics }: ConsumablesProps) {
{Object.entries(consumables.consumables).map( {Object.entries(consumables.consumables).map(
([id, { compatibility, consumable, purchase }]) => { ([id, { compatibility, consumable, purchase }]) => {
if (!isCompatible(compatibility!)) return null; if (!isCompatible(compatibility!)) return null;
return ( return (
<Consumable <Consumable
key={id}
id={id} id={id}
consumable={consumable!} consumable={consumable!}
purchase={purchase!} purchase={purchase!}
-10
View File
@@ -7,20 +7,14 @@ import { assertDiscoveryTag } from "./assertDiscoveryTag";
let _game: GameInterface | null = null; let _game: GameInterface | null = null;
if (!clientUnmounted && import.meta.env.SSR) { if (!clientUnmounted && import.meta.env.SSR) {
console.log("Pre-import");
const { GameInterface } = await import("@blitzkit/game"); const { GameInterface } = await import("@blitzkit/game");
console.log("Pre-creation");
_game = new GameInterface( _game = new GameInterface(
assertSecret(import.meta.env.PUBLIC_WOTB_CLIENT), assertSecret(import.meta.env.PUBLIC_WOTB_CLIENT),
assertSecret(import.meta.env.WOTB_USMAP), assertSecret(import.meta.env.WOTB_USMAP),
"../../temp", "../../temp",
); );
console.log("Pre-tags");
const tankTags: string[] = []; const tankTags: string[] = [];
for (const item of api.metadata.group("TankEntity")) { for (const item of api.metadata.group("TankEntity")) {
@@ -30,11 +24,7 @@ if (!clientUnmounted && import.meta.env.SSR) {
tankTags.push(tag); tankTags.push(tag);
} }
console.log("Pre-discovery");
_game.discoverTextures(tankTags); _game.discoverTextures(tankTags);
console.log("Post-discovery");
} }
export const game = _game; export const game = _game;
+1 -2
View File
@@ -1,3 +1,2 @@
cd packages/game cd packages/game
dotnet build -clp:ErrorsOnly dotnet build
find ./bin -type f | sort