Files
blitzkit/src/BlitzKit.CLI/Functions/Mangler.cs
T

149 lines
4.4 KiB
C#
Raw Normal View History

2025-02-25 15:15:03 -06:00
using System.Data;
2025-02-25 18:28:08 -06:00
using System.Text;
2025-03-01 23:08:22 -06:00
using System.Text.RegularExpressions;
2025-02-25 18:28:08 -06:00
using System.Text.Unicode;
2025-01-29 19:14:46 -06:00
using Blitzkit;
2025-01-28 12:59:59 -06:00
using BlitzKit.CLI.Models;
2025-03-01 23:08:22 -06:00
using BlitzKit.CLI.Utils;
2025-02-25 15:15:03 -06:00
using CUE4Parse.UE4.Assets.Exports;
2025-02-02 00:25:47 -06:00
using CUE4Parse.UE4.Assets.Exports.Engine;
using CUE4Parse.UE4.Assets.Exports.StaticMesh;
2025-02-25 15:15:03 -06:00
using CUE4Parse.UE4.Assets.Objects;
2025-02-25 17:23:25 -06:00
using CUE4Parse.UE4.Objects.UObject;
2025-02-25 18:28:08 -06:00
using CUE4Parse.UE4.Pak.Objects;
2025-03-01 23:08:22 -06:00
using Google.Protobuf;
2025-01-30 12:49:15 -06:00
using Google.Protobuf.Collections;
2025-01-29 19:14:46 -06:00
using Newtonsoft.Json.Linq;
2025-01-27 22:17:13 -06:00
2025-01-28 12:59:59 -06:00
namespace BlitzKit.CLI.Functions
2025-01-26 21:17:25 -06:00
{
2025-02-25 17:55:05 -06:00
public class Mangler(string[] args)
2025-01-26 21:17:25 -06:00
{
2025-02-25 17:55:05 -06:00
readonly BlitzProvider provider = new(args.Contains("--depot"));
2025-02-25 17:23:25 -06:00
readonly List<FileChange> changes = [];
2025-01-27 22:17:13 -06:00
2025-02-25 17:23:25 -06:00
public async Task Mangle()
2025-02-01 21:21:12 -06:00
{
var nationDirs = provider.RootDirectory.GetDirectory("Blitz/Content/Tanks").Directories;
foreach (var nationDir in nationDirs)
2025-01-27 22:17:13 -06:00
{
2025-01-30 11:31:55 -06:00
if (nationDir.Key == "TankStub")
2025-01-27 22:17:13 -06:00
continue;
2025-02-01 21:21:12 -06:00
MangleNation(nationDir.Value);
2025-01-27 22:17:13 -06:00
}
2025-02-25 17:23:25 -06:00
await BlitzKitAssets.CommitAssets("ue assets", changes);
2025-01-30 12:54:37 -06:00
}
2025-01-29 19:14:46 -06:00
2025-02-25 15:15:03 -06:00
void MangleNation(VFS nation)
2025-01-30 12:54:37 -06:00
{
2025-03-01 23:08:22 -06:00
Tanks tanks = new();
2025-02-01 21:21:12 -06:00
foreach (var tankDir in nation.Directories)
2025-01-30 12:54:37 -06:00
{
2025-02-25 15:36:34 -06:00
// if (tankDir.Value.Name != "R90_IS_4")
// continue;
2025-01-30 12:54:37 -06:00
2025-02-01 21:21:12 -06:00
var tank = MangleTank(tankDir.Value);
2025-01-30 12:54:37 -06:00
2025-03-01 23:08:22 -06:00
if (!tank.Name.Locales.TryGetValue("en", out var nameEn))
{
throw new Exception($"Failed to get name for {tankDir.Value.Name}");
}
2025-02-01 22:01:06 -06:00
2025-03-01 23:08:22 -06:00
var seoId = Diacritics.Remove(nameEn).ToLower();
seoId = Regex.Replace(seoId, "[^a-z0-9]", "-");
seoId = Regex.Replace(seoId, "--+", "-");
seoId = Regex.Replace(seoId, "-$", "");
Console.WriteLine($"{nameEn} -> {seoId}");
TankMeta tankMeta = new() { Id = tank.Id, SeoId = seoId };
tanks.Tanks_.Add(tankMeta);
2025-02-01 21:21:12 -06:00
}
2025-03-01 23:08:22 -06:00
FileChange change = new("definitions/tanks.pb", tanks.ToByteArray());
changes.Add(change);
2025-01-26 21:17:25 -06:00
}
2025-01-30 11:31:55 -06:00
2025-03-01 23:08:22 -06:00
Tank MangleTank(VFS tankDir)
2025-02-01 21:21:12 -06:00
{
var pdaName = $"PDA_{tankDir.Name}";
2025-02-25 15:15:03 -06:00
var pda = provider.LoadObject($"{tankDir.Path}/{pdaName}.{pdaName}");
2025-02-25 17:23:25 -06:00
var tankId = PropertyUtil.Get<FName>(pda, "TankId").Text;
2025-02-25 17:55:05 -06:00
Console.WriteLine($"Mangling {tankId}...");
2025-02-25 17:23:25 -06:00
2025-02-25 15:15:03 -06:00
var hulls = PropertyUtil.Get<UDataTable>(pda, "DT_Hulls");
UDataTableUtility.TryGetDataTableRow(hulls, "hull", StringComparison.Ordinal, out var hull);
var hullVisualData = PropertyUtil.Get<UObject>(hull, "VisualData");
var hullMeshSettings = PropertyUtil.Get<FStructFallback>(hullVisualData, "MeshSettings");
var hullCollision = PropertyUtil.Get<UStaticMesh>(hullMeshSettings, "CollisionMesh");
2025-02-25 15:36:34 -06:00
MonoGltf hullCollisionGltf = new(hullCollision);
2025-02-25 17:23:25 -06:00
changes.Add(new($"tanks/{tankId}/collision/hull.glb", hullCollisionGltf.Write()));
2025-02-01 22:01:06 -06:00
2025-03-01 23:08:22 -06:00
I18n Name = new();
Name.Locales.Add("en", tankId);
return new() { Id = tankId, Name = Name };
2025-02-01 21:21:12 -06:00
}
Dictionary<string, CrewType> CrewTypes = new()
2025-01-30 12:49:15 -06:00
{
{ "EModuleOrTankmen::Commander", CrewType.Commander },
{ "EModuleOrTankmen::Driver", CrewType.Driver },
{ "EModuleOrTankmen::Gunner1", CrewType.Gunner1 },
{ "EModuleOrTankmen::Gunner2", CrewType.Gunner2 },
{ "EModuleOrTankmen::Loader1", CrewType.Loader1 },
{ "EModuleOrTankmen::Loader2", CrewType.Loader2 },
};
2025-02-01 21:21:12 -06:00
void MangleCrewHealth(RepeatedField<CrewHealth> map, JArray array)
2025-01-30 12:49:15 -06:00
{
foreach (var member in array.Cast<JObject>())
{
var key = member["Key"]!.Value<string>()!;
if (CrewTypes.TryGetValue(key, out var crewType))
{
CrewHealth crewHealth = new()
{
Type = crewType,
MaxHealth = member["Value"]!["MaxHealth"]!.Value<float>(),
};
map.Add(crewHealth);
}
else
{
throw new Exception($"Unrecognized CrewType: {key}");
}
}
}
2025-02-01 21:21:12 -06:00
ModuleHealth MangleModuleHealth(JObject obj)
2025-01-30 11:31:55 -06:00
{
ModuleHealth moduleHealth = new()
{
MaxHealth = obj["MaxHealth"]!.Value<float>(),
MaxRegenHealth = obj["MaxRegenHealth"]!.Value<float>(),
HealthRegenPerSec = obj["HealthRegenPerSec"]!.Value<float>(),
};
if (obj.TryGetValue("HysteresisHealth", out var hysteresis))
{
moduleHealth.HysteresisHealth = hysteresis.Value<float>();
}
if (obj.TryGetValue("HealthBurnPerSec", out var burn))
{
moduleHealth.HealthBurnPerSec = burn.Value<float>();
}
return moduleHealth;
}
2025-01-26 21:17:25 -06:00
}
}