Skip to content

Commit bae88f9

Browse files
authored
Merge pull request #36 from ModdersLink/feature/bundle-dependency-resolving
[WIP] Custom bundle stuff
2 parents d91e8f9 + 4e72d74 commit bae88f9

16 files changed

Lines changed: 907 additions & 193 deletions

File tree

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System.IO;
2+
using RimeLib.Cmd.Attributes;
3+
using RimeLib.Cmd.Contexts;
4+
5+
namespace RimeLib.Cmd.Commands.BundleBuilding
6+
{
7+
[CommandDescription("Adds a bundle that definitely gets loaded before the bundle that gets built.")]
8+
internal class AddDependencyBundleCommand : Command
9+
{
10+
[CommandArgument(Description = "The name of the dependency bundle.")]
11+
public string? Name { get; set; }
12+
13+
public override bool Execute(ref ExecutionContext p_Context, TextWriter p_Writer)
14+
{
15+
if (string.IsNullOrWhiteSpace(Name))
16+
{
17+
p_Writer.WriteLine("The specified bundle name is invalid.");
18+
return false;
19+
}
20+
21+
var s_BundleContext = (BundleBuildingContext)p_Context;
22+
s_BundleContext.AddDependencyBundle(Name);
23+
24+
return true;
25+
}
26+
}
27+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System.IO;
2+
using RimeLib.Cmd.Attributes;
3+
using RimeLib.Cmd.Contexts;
4+
5+
namespace RimeLib.Cmd.Commands.BundleBuilding
6+
{
7+
[CommandDescription("Adds a superbundle whose chunks will be excluded from the bundle that gets built.")]
8+
internal class AddDependencySuperbundleCommand : Command
9+
{
10+
[CommandArgument(Description = "The name of the dependency superbundle.")]
11+
public string? Name { get; set; }
12+
13+
public override bool Execute(ref ExecutionContext p_Context, TextWriter p_Writer)
14+
{
15+
if (string.IsNullOrWhiteSpace(Name))
16+
{
17+
p_Writer.WriteLine("The specified superbundle name is invalid.");
18+
return false;
19+
}
20+
21+
var s_BundleContext = (BundleBuildingContext)p_Context;
22+
s_BundleContext.AddDependencySuperbundle(Name);
23+
24+
return true;
25+
}
26+
}
27+
}
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Linq;
5+
using RimeLib.Cmd.Attributes;
6+
using RimeLib.Cmd.Contexts;
7+
using RimeLib.Content.Mounting;
8+
9+
namespace RimeLib.Cmd.Commands.BundleBuilding
10+
{
11+
[CommandDescription("Removes all partitions, resources, and chunks that are already in any of the dependency bundles.")]
12+
public class RemoveDuplicateBundleItemsCommand : Command
13+
{
14+
public override bool Execute(ref ExecutionContext p_Context, TextWriter p_Writer)
15+
{
16+
var s_BundleContext = (BundleBuildingContext)p_Context;
17+
var s_SbBuildingContext = (SbBuildingContext)s_BundleContext.Parent!;
18+
var s_BaseContext = (BaseContext)s_SbBuildingContext.Parent!;
19+
20+
var s_Mounters = s_BaseContext.GetMounters();
21+
if (s_Mounters.Count == 0)
22+
{
23+
p_Writer.WriteLine("Error: No game mounter found.");
24+
return false;
25+
}
26+
var s_Mounter = s_Mounters.Values.First();
27+
28+
var s_DepBundles = s_BundleContext.GetDependencyBundles().ToList();
29+
var s_DepSuperbundles = s_BundleContext.GetDependencySuperbundles().ToList();
30+
31+
if (s_DepBundles.Count == 0 && s_DepSuperbundles.Count == 0)
32+
{
33+
p_Writer.WriteLine("No dependency bundles or superbundles found to check against.");
34+
return true;
35+
}
36+
37+
p_Writer.WriteLine("Removing duplicate items from dependency bundles...");
38+
39+
int s_RemovedPartitions = 0;
40+
int s_RemovedResources = 0;
41+
int s_RemovedChunks = 0;
42+
43+
foreach (var s_DepBndl in s_DepBundles)
44+
{
45+
try
46+
{
47+
// Partitions
48+
var s_BndlPartitions = s_Mounter.GetPartitionsInBundle(s_DepBndl);
49+
foreach (var s_Part in s_BndlPartitions)
50+
{
51+
if (s_BundleContext.GetPartitions().ContainsKey(s_Part))
52+
{
53+
s_BundleContext.RemovePartition(s_Part);
54+
p_Writer.WriteLine($"Removed duplicate partition: {s_Part} (Found in {s_DepBndl})");
55+
s_RemovedPartitions++;
56+
}
57+
}
58+
59+
// Resources
60+
var s_BndlResources = s_Mounter.GetResourcesInBundle(s_DepBndl);
61+
foreach (var s_Res in s_BndlResources)
62+
{
63+
if (s_BundleContext.GetResources().ContainsKey(s_Res.Name))
64+
{
65+
s_BundleContext.RemoveResource(s_Res.Name);
66+
p_Writer.WriteLine($"Removed duplicate resource: {s_Res.Name} (Found in {s_DepBndl})");
67+
s_RemovedResources++;
68+
}
69+
}
70+
71+
// Chunks
72+
var s_BndlChunks = s_Mounter.GetChunksInBundle(s_DepBndl);
73+
foreach (var s_Chunk in s_BndlChunks)
74+
{
75+
if (s_BundleContext.GetChunks().ContainsKey(s_Chunk))
76+
{
77+
s_BundleContext.RemoveChunk(s_Chunk);
78+
p_Writer.WriteLine($"Removed duplicate chunk: {s_Chunk} (Found in {s_DepBndl})");
79+
s_RemovedChunks++;
80+
}
81+
}
82+
}
83+
catch (Exception s_Ex)
84+
{
85+
p_Writer.WriteLine($"Warning: Failed to fetch items for dependency bundle '{s_DepBndl}': {s_Ex.Message}");
86+
}
87+
}
88+
89+
p_Writer.WriteLine("Removing duplicate chunks from dependency superbundles...");
90+
91+
foreach (var s_DepSuperbndl in s_DepSuperbundles)
92+
{
93+
try
94+
{
95+
// Chunks
96+
var s_SbChunks = s_Mounter.GetChunksInSuperbundle(s_DepSuperbndl);
97+
foreach (var s_Chunk in s_SbChunks)
98+
{
99+
if (s_BundleContext.GetChunks().ContainsKey(s_Chunk))
100+
{
101+
s_BundleContext.RemoveChunk(s_Chunk);
102+
p_Writer.WriteLine($"Removed duplicate chunk: {s_Chunk} (Found in superbundle {s_DepSuperbndl})");
103+
s_RemovedChunks++;
104+
}
105+
}
106+
}
107+
catch (Exception s_Ex)
108+
{
109+
p_Writer.WriteLine($"Warning: Failed to fetch items for dependency superbundle '{s_DepSuperbndl}': {s_Ex.Message}");
110+
}
111+
}
112+
113+
p_Writer.WriteLine($"Finished removing duplicates.");
114+
p_Writer.WriteLine($"Removed {s_RemovedPartitions} partitions, {s_RemovedResources} resources, and {s_RemovedChunks} chunks.");
115+
116+
return true;
117+
}
118+
}
119+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
using System;
2+
using System.IO;
3+
using System.Linq;
4+
using RimeLib.Cmd.Attributes;
5+
using RimeLib.Cmd.Contexts;
6+
using RimeLib.Content;
7+
using RimeLib.Content.Frostbite;
8+
using RimeLib.Content.Mounting;
9+
using RimeLib.Frostbite.Core;
10+
using RimeLib.IO;
11+
using RimeLib.Mesh.Frostbite;
12+
using RimeLib.Texture;
13+
14+
namespace RimeLib.Cmd.Commands.BundleBuilding
15+
{
16+
[CommandDescription("Resolves missing chunk dependencies for dxtextures and meshes in the current bundle.")]
17+
public class ResolveMissingChunksCommand : Command
18+
{
19+
public override bool Execute(ref ExecutionContext p_Context, TextWriter p_Writer)
20+
{
21+
var s_BundleContext = (BundleBuildingContext)p_Context;
22+
var s_SbBuildingContext = (SbBuildingContext)s_BundleContext.Parent!;
23+
var s_BaseContext = (BaseContext)s_SbBuildingContext.Parent!;
24+
25+
var s_Mounters = s_BaseContext.GetMounters();
26+
if (s_Mounters.Count == 0)
27+
{
28+
p_Writer.WriteLine("Error: No game mounter found.");
29+
return false;
30+
}
31+
var s_Mounter = s_Mounters.Values.First();
32+
33+
var s_Resources = s_BundleContext.GetResources().ToList();
34+
int s_AddedChunks = 0;
35+
36+
foreach (var s_Res in s_Resources)
37+
{
38+
var s_Type = s_Res.Value.GetResourceType();
39+
GUID s_ChunkId = GUID.Empty;
40+
41+
try
42+
{
43+
if (s_Type == ResourceType.DxTexture || s_Type == ResourceType.Ps3Texture)
44+
{
45+
p_Writer.WriteLine($"Searching texture chunk for resource {s_Res.Key}");
46+
var s_TextureConverter = EngineInterfaceRegistry.Create<ITextureConverter>(s_SbBuildingContext.EngineType);
47+
s_ChunkId = s_TextureConverter.GetTextureChunkId(s_Res.Value);
48+
}
49+
else if (s_Type == ResourceType.MeshSet)
50+
{
51+
p_Writer.WriteLine($"Searching mesh chunks for resource {s_Res.Key}");
52+
using var s_Reader1 = s_Res.Value.GetReader();
53+
var s_Data = s_Reader1.ReadBytes((int)s_Reader1.Length);
54+
using var s_Reader = new RimeReader(new MemoryStream(s_Data));
55+
56+
var s_MeshSetLayout = new MeshSetLayout(s_Reader);
57+
58+
for (var i = 0; i < s_MeshSetLayout.LodCount; i++)
59+
{
60+
var s_Lod = s_MeshSetLayout.Lods[i].Object;
61+
if (s_Lod != null && s_Lod.DataChunkId != GUID.Empty && (s_Lod.Flags & MeshLayout.MeshLayoutFlags.IsBaseLod) != 0)
62+
{
63+
if (!s_BundleContext.GetChunks().ContainsKey(s_Lod.DataChunkId))
64+
{
65+
if (s_Mounter.TryGetChunk(s_Lod.DataChunkId, out var s_ChunkObj))
66+
{
67+
s_BundleContext.AddChunk(s_Lod.DataChunkId, s_ChunkObj.FirstVariant);
68+
p_Writer.WriteLine($"Added missing mesh chunk: {s_Lod.DataChunkId} for resource {s_Res.Key}");
69+
s_AddedChunks++;
70+
}
71+
else
72+
{
73+
p_Writer.WriteLine($"Warning: Missing mesh chunk {s_Lod.DataChunkId} for resource {s_Res.Key} not found in mounter.");
74+
}
75+
}
76+
}
77+
}
78+
}
79+
80+
if (s_ChunkId != GUID.Empty && !s_BundleContext.GetChunks().ContainsKey(s_ChunkId))
81+
{
82+
if (s_Mounter.TryGetChunk(s_ChunkId, out var s_ChunkObj))
83+
{
84+
s_BundleContext.AddChunk(s_ChunkId, s_ChunkObj.FirstVariant);
85+
p_Writer.WriteLine($"Added missing chunk: {s_ChunkId} for resource {s_Res.Key}");
86+
s_AddedChunks++;
87+
}
88+
else
89+
{
90+
p_Writer.WriteLine($"Warning: Missing chunk {s_ChunkId} for resource {s_Res.Key} not found in mounter.");
91+
}
92+
}
93+
}
94+
catch (Exception p_Ex)
95+
{
96+
p_Writer.WriteLine($"Error resolving chunks for {s_Res.Key}: {p_Ex.Message}");
97+
}
98+
}
99+
100+
p_Writer.WriteLine($"Done tracking down missing chunks. Added {s_AddedChunks} missing chunks to bundle.");
101+
return true;
102+
}
103+
}
104+
}

0 commit comments

Comments
 (0)