Add Skin.cs and utilities to Serialize and Deserialize them

This commit is contained in:
miku-666
2024-03-08 12:31:28 +01:00
parent ea7084e959
commit 075c662e1a
13 changed files with 350 additions and 210 deletions

View File

@@ -7,8 +7,10 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OMI.Formats.Languages;
using OMI.Formats.Pck;
using OMI.Workers;
using PckStudio.Internal;
namespace PckStudio.Extensions
{
@@ -26,18 +28,107 @@ namespace PckStudio.Extensions
{
throw new Exception("File is not suitable to contain image data.");
}
using (var stream = new MemoryStream(file.Data))
using var stream = new MemoryStream(file.Data);
try
{
try
{
return Image.FromStream(stream);
}
catch(Exception ex)
{
Trace.WriteLine($"Failed to read image from pck file data({file.Filename}).", category: nameof(PckFileDataExtensions) + "." + nameof(GetTexture));
Debug.WriteLine(ex.Message);
return EmptyImage;
}
return Image.FromStream(stream);
}
catch (Exception ex)
{
Trace.TraceError($"Failed to read image from pck file data({file.Filename}).");
Debug.WriteLine(ex.Message);
return EmptyImage;
}
}
/// <summary>
/// Tries to get the skin id of the skin <paramref name="file"/>
/// </summary>
/// <param name="file"></param>
/// <returns>Non-zero base number on success, otherwise 0</returns>
/// <exception cref="InvalidOperationException"></exception>
internal static int GetSkinId(this PckFileData file)
{
if (file.Filetype != PckFileType.SkinFile)
throw new InvalidOperationException("File is not a skin file");
string filename = Path.GetFileNameWithoutExtension(file.Filename);
if (!filename.StartsWith("dlcskin"))
{
Trace.TraceWarning($"[{nameof(GetSkin)}] File does not start with 'dlcskin'");
return 0;
}
int skinId = 0;
if (!int.TryParse(filename.Substring("dlcskin".Length), out skinId))
{
Trace.TraceWarning($"[{nameof(GetSkin)}] Failed to parse Skin Id");
}
return skinId;
}
internal static Skin GetSkin(this PckFileData file)
{
if (file.Filetype != PckFileType.SkinFile)
throw new InvalidOperationException("File is not a skin file");
if (file.Properties.Contains("CAPEPATH"))
Debug.WriteLine($"[{nameof(GetSkin)}] TODO: add cape texture/path.");
int skinId = file.GetSkinId();
string name = file.Properties.GetPropertyValue("DISPLAYNAME");
Image texture = file.GetTexture();
SkinANIM anim = file.Properties.GetPropertyValue("ANIM", SkinANIM.FromString);
IEnumerable<SkinBOX> boxes = file.Properties.GetProperties("BOX").Select(kv => SkinBOX.FromString(kv.Value));
IEnumerable<SkinPartOffset> offsets = file.Properties.GetProperties("OFFSET").Select(kv => SkinPartOffset.FromString(kv.Value));
return new Skin(name, skinId, texture, anim, boxes, offsets);
}
internal static void SetSkin(this PckFileData file, Skin skin, LOCFile localizationFile)
{
if (file.Filetype != PckFileType.SkinFile)
throw new InvalidOperationException("File is not a skin file");
file.SetData(skin.Texture, ImageFormat.Png);
string skinId = skin.Id.ToString("d08");
// TODO: keep filepath
file.Filename = $"dlcskin{skinId}.png";
string skinLocKey = $"IDS_dlcskin{skinId}_DISPLAYNAME";
file.Properties.SetProperty("DISPLAYNAME", skin.Name);
file.Properties.SetProperty("DISPLAYNAMEID", skinLocKey);
localizationFile.AddLocKey(skinLocKey, skin.Name);
if (!string.IsNullOrEmpty(skin.Theme))
{
file.Properties.SetProperty("THEMENAME", skin.Theme);
file.Properties.SetProperty("THEMENAMEID", $"IDS_dlcskin{skinId}_THEMENAME");
localizationFile.AddLocKey($"IDS_dlcskin{skinId}_THEMENAME", skin.Theme);
}
if (skin.HasCape)
{
file.Properties.SetProperty("CAPEPATH", $"dlccape{skinId}.png");
}
file.Properties.SetProperty("ANIM", skin.ANIM.ToString());
file.Properties.SetProperty("GAME_FLAGS", "0x18");
file.Properties.SetProperty("FREE", "1");
file.Properties.RemoveAll(kv => kv.Key == "BOX");
file.Properties.RemoveAll(kv => kv.Key == "OFFSET");
foreach (SkinBOX box in skin.AdditionalBoxes)
{
file.Properties.Add(box.ToProperty());
}
foreach (SkinPartOffset offset in skin.PartOffsets)
{
file.Properties.Add(offset.ToProperty());
}
}