From 13516e204e15a8027c427ba13d506204c116d52e Mon Sep 17 00:00:00 2001 From: miku-666 <74728189+NessieHax@users.noreply.github.com> Date: Mon, 8 Dec 2025 16:47:18 +0100 Subject: [PATCH] Core - Update PckAudioFile class --- PCK-Studio/Controls/RawAssetsEditor.cs | 6 +- .../Forms/Editor/AudioEditor.Designer.cs | 4 +- PCK-Studio/Forms/Editor/AudioEditor.cs | 77 +++---- PCK-Studio/Forms/Editor/AudioEditor.resx | 192 +++++++++--------- PCK-Studio/MainForm.cs | 26 --- PckStudio.Core/DLC/DLCManager.cs | 154 ++++++++------ PckStudio.Core/Extensions/MathExtensions.cs | 7 +- .../TreeNodeCollectionExtensions.cs | 32 ++- PckStudio.Core/FileFormats/PckAudioFile.cs | 57 +++--- .../IO/PckAudio/PckAudioFileReader.cs | 8 +- 10 files changed, 284 insertions(+), 279 deletions(-) diff --git a/PCK-Studio/Controls/RawAssetsEditor.cs b/PCK-Studio/Controls/RawAssetsEditor.cs index 432c8560..5cddf930 100644 --- a/PCK-Studio/Controls/RawAssetsEditor.cs +++ b/PCK-Studio/Controls/RawAssetsEditor.cs @@ -729,9 +729,9 @@ namespace PckStudio.Controls private static PckAudioFile CreateNewAudioFile() { PckAudioFile audioFile = new PckAudioFile(); - audioFile.AddCategory(PckAudioFile.AudioCategory.EAudioType.Overworld); - audioFile.AddCategory(PckAudioFile.AudioCategory.EAudioType.Nether); - audioFile.AddCategory(PckAudioFile.AudioCategory.EAudioType.End); + audioFile.AddCategory(PckAudioFile.Category.Overworld); + audioFile.AddCategory(PckAudioFile.Category.Nether); + audioFile.AddCategory(PckAudioFile.Category.End); return audioFile; } diff --git a/PCK-Studio/Forms/Editor/AudioEditor.Designer.cs b/PCK-Studio/Forms/Editor/AudioEditor.Designer.cs index fbc1e30e..2b38f77f 100644 --- a/PCK-Studio/Forms/Editor/AudioEditor.Designer.cs +++ b/PCK-Studio/Forms/Editor/AudioEditor.Designer.cs @@ -269,7 +269,7 @@ namespace PckStudio.Forms.Editor // playOverworldInCreative // resources.ApplyResources(this.playOverworldInCreative, "playOverworldInCreative"); - this.playOverworldInCreative.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64))))); + this.playOverworldInCreative.BackColor = System.Drawing.Color.Transparent; this.playOverworldInCreative.ForeColor = System.Drawing.SystemColors.Window; this.playOverworldInCreative.Name = "playOverworldInCreative"; this.playOverworldInCreative.Theme = MetroFramework.MetroThemeStyle.Dark; @@ -281,6 +281,7 @@ namespace PckStudio.Forms.Editor // resources.ApplyResources(this.compressionUpDown, "compressionUpDown"); this.compressionUpDown.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64))))); + this.compressionUpDown.BorderStyle = System.Windows.Forms.BorderStyle.None; this.compressionUpDown.ForeColor = System.Drawing.SystemColors.Window; this.compressionUpDown.Maximum = new decimal(new int[] { 9, @@ -319,7 +320,6 @@ namespace PckStudio.Forms.Editor this.MinimizeBox = false; this.Name = "AudioEditor"; this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.AudioEditor_FormClosing); - this.Shown += new System.EventHandler(this.AudioEditor_Shown); this.contextMenuStrip1.ResumeLayout(false); this.menuStrip.ResumeLayout(false); this.menuStrip.PerformLayout(); diff --git a/PCK-Studio/Forms/Editor/AudioEditor.cs b/PCK-Studio/Forms/Editor/AudioEditor.cs index 7ac98946..0b3c08eb 100644 --- a/PCK-Studio/Forms/Editor/AudioEditor.cs +++ b/PCK-Studio/Forms/Editor/AudioEditor.cs @@ -24,7 +24,6 @@ namespace PckStudio.Forms.Editor public partial class AudioEditor : EditorForm { public string defaultType = "yes"; - MainForm parent = null; private static readonly List Categories = new List { @@ -53,15 +52,14 @@ namespace PckStudio.Forms.Editor SetUpTree(); } - private string GetCategoryFromId(PckAudioFile.AudioCategory.EAudioType categoryId) - => categoryId >= PckAudioFile.AudioCategory.EAudioType.Overworld && - categoryId <= PckAudioFile.AudioCategory.EAudioType.BuildOff + private string GetCategoryFromId(PckAudioFile.Category categoryId) + => Enum.IsDefined(typeof(PckAudioFile.Category), categoryId) ? Categories[(int)categoryId] : "Not valid"; - private PckAudioFile.AudioCategory.EAudioType GetCategoryId(string category) + private PckAudioFile.Category GetCategoryId(string category) { - return (PckAudioFile.AudioCategory.EAudioType)Categories.IndexOf(category); + return (PckAudioFile.Category)Categories.IndexOf(category); } public void SetUpTree() @@ -76,10 +74,10 @@ namespace PckStudio.Forms.Editor foreach (string songname in category.SongNames.FindAll(s => s.Contains('\\'))) category.SongNames[category.SongNames.IndexOf(songname)] = songname.Replace('\\', '/'); - if (category.AudioType == PckAudioFile.AudioCategory.EAudioType.Creative) + if (category.AudioType == PckAudioFile.Category.Creative) { if (category.Name == "include_overworld" && - EditorValue.TryGetCategory(PckAudioFile.AudioCategory.EAudioType.Overworld, out PckAudioFile.AudioCategory overworldCategory)) + EditorValue.TryGetCategory(PckAudioFile.Category.Overworld, out PckAudioFile.AudioCategory overworldCategory)) { foreach (var name in category.SongNames.ToList()) { @@ -95,7 +93,7 @@ namespace PckStudio.Forms.Editor treeNode.Tag = category; treeView1.Nodes.Add(treeNode); } - playOverworldInCreative.Enabled = EditorValue.HasCategory(PckAudioFile.AudioCategory.EAudioType.Creative); + playOverworldInCreative.Enabled = EditorValue.HasCategory(PckAudioFile.Category.Creative); treeView1.EndUpdate(); } @@ -105,9 +103,7 @@ namespace PckStudio.Forms.Editor return; TreeNode entry = treeView2.SelectedNode; - if (!parent.CreateDataFolder()) - return; - string fileName = Path.Combine(parent.GetDataPath(), entry.Text + ".binka"); + string fileName = Path.Combine(entry.Text + ".binka"); if (File.Exists(fileName)) MessageBox.Show(this, $"\"{entry.Text}.binka\" exists in the \"Data\" folder", "File found"); @@ -144,7 +140,7 @@ namespace PckStudio.Forms.Editor EditorValue.AddCategory(GetCategoryId(add.SelectedItem)); PckAudioFile.AudioCategory category = EditorValue.GetCategory(GetCategoryId(add.SelectedItem)); - if (GetCategoryId(add.SelectedItem) == PckAudioFile.AudioCategory.EAudioType.Creative) + if (GetCategoryId(add.SelectedItem) == PckAudioFile.Category.Creative) { playOverworldInCreative.Visible = true; playOverworldInCreative.Checked = false; @@ -161,9 +157,6 @@ namespace PckStudio.Forms.Editor { if (treeView1.SelectedNode is TreeNode t && t.Tag is PckAudioFile.AudioCategory) { - if (!parent.CreateDataFolder()) - return; - OpenFileDialog ofn = new OpenFileDialog(); ofn.Multiselect = true; ofn.Filter = "Supported audio files (*.binka,*.wav)|*.binka;*.wav"; @@ -183,7 +176,7 @@ namespace PckStudio.Forms.Editor if (treeView1.SelectedNode is TreeNode main && EditorValue.RemoveCategory(GetCategoryId(treeView1.SelectedNode.Text))) { - if(GetCategoryId(treeView1.SelectedNode.Text) == PckAudioFile.AudioCategory.EAudioType.Creative) + if(GetCategoryId(treeView1.SelectedNode.Text) == PckAudioFile.Category.Creative) { playOverworldInCreative.Visible = false; playOverworldInCreative.Checked = false; @@ -236,7 +229,7 @@ namespace PckStudio.Forms.Editor if (File.Exists(cacheSongFile)) File.Delete(cacheSongFile); - string new_loc = Path.Combine(parent.GetDataPath(), songName + ".binka"); + string new_loc = Path.Combine(songName + ".binka"); bool is_duplicate_file = false; // To handle if a file already in the pack is dropped back in bool loc_is_occupied = File.Exists(new_loc); if (loc_is_occupied) @@ -348,24 +341,21 @@ namespace PckStudio.Forms.Editor // Gets the MainForm so we can access the Save Location if (treeView1.SelectedNode != null) { - if (!parent.CreateDataFolder()) - return; - ProcessEntries((string[])e.Data.GetData(DataFormats.FileDrop, false)); } } private void saveToolStripMenuItem1_Click(object sender, EventArgs e) { - if (!EditorValue.HasCategory(PckAudioFile.AudioCategory.EAudioType.Overworld) || - !EditorValue.HasCategory(PckAudioFile.AudioCategory.EAudioType.Nether) || - !EditorValue.HasCategory(PckAudioFile.AudioCategory.EAudioType.End)) + if (!EditorValue.HasCategory(PckAudioFile.Category.Overworld) || + !EditorValue.HasCategory(PckAudioFile.Category.Nether) || + !EditorValue.HasCategory(PckAudioFile.Category.End)) { MessageBox.Show(this, "Your changes were not saved. The game will crash when loading your pack if the Overworld, Nether and End categories don't all exist with at least one valid song.", "Mandatory Categories Missing"); return; } - PckAudioFile.AudioCategory overworldCategory = EditorValue.GetCategory(PckAudioFile.AudioCategory.EAudioType.Overworld); + PckAudioFile.AudioCategory overworldCategory = EditorValue.GetCategory(PckAudioFile.Category.Overworld); bool songs_missing = false; foreach (PckAudioFile.AudioCategory category in EditorValue.Categories) @@ -378,7 +368,7 @@ namespace PckStudio.Forms.Editor foreach(var song in category.SongNames) { - string fileName = Path.Combine(parent.GetDataPath(), song + ".binka"); + string fileName = Path.Combine(song + ".binka"); if (!File.Exists(fileName)) { songs_missing = true; @@ -387,7 +377,7 @@ namespace PckStudio.Forms.Editor } category.Name = ""; - if (playOverworldInCreative.Checked && category.AudioType == PckAudioFile.AudioCategory.EAudioType.Creative) + if (playOverworldInCreative.Checked && category.AudioType == PckAudioFile.Category.Creative) { foreach (var name in overworldCategory.SongNames) { @@ -437,10 +427,8 @@ namespace PckStudio.Forms.Editor totalSongList.Add(song); } - if (!parent.CreateDataFolder()) - return; int totalDeleted = 0; - foreach (string song in Directory.GetFiles(parent.GetDataPath(), "*.binka")) + foreach (string song in Directory.GetFiles("*.binka")) { if (!totalSongList.Contains(Path.GetFileNameWithoutExtension(song))) { @@ -498,24 +486,11 @@ namespace PckStudio.Forms.Editor private void openDataFolderToolStripMenuItem_Click(object sender, EventArgs e) { - if (!parent.CreateDataFolder()) - return; - Process.Start("explorer.exe", parent.GetDataPath()); - } - - private void AudioEditor_Shown(object sender, EventArgs e) - { - if (Owner.Owner is MainForm p) - parent = p; - else - Close(); + //Process.Start("explorer.exe", parent.GetDataPath()); } private async void bulkReplaceExistingFilesToolStripMenuItem_Click(object sender, EventArgs e) { - if (!parent.CreateDataFolder()) - return; - int exitCode = 0; @@ -540,7 +515,7 @@ namespace PckStudio.Forms.Editor { string song_name = Path.GetFileNameWithoutExtension(file); string file_ext = Path.GetExtension(file).ToLower(); - string new_loc = Path.Combine(parent.GetDataPath(), Path.GetFileNameWithoutExtension(file) + ".binka"); + string new_loc = Path.Combine(Path.GetFileNameWithoutExtension(file) + ".binka"); if (!totalSongList.Contains(song_name) || file == new_loc) continue; @@ -566,7 +541,7 @@ namespace PckStudio.Forms.Editor continue; } else if(file_ext == ".binka") - File.Copy(file, Path.Combine(parent.GetDataPath(), Path.GetFileName(file))); + File.Copy(file, Path.Combine(Path.GetFileName(file))); } } @@ -574,7 +549,7 @@ namespace PckStudio.Forms.Editor { if (treeView2.SelectedNode != null && treeView1.SelectedNode.Tag is PckAudioFile.AudioCategory) { - Binka.ToWav(Path.Combine(parent.GetDataPath(), treeView2.SelectedNode.Text + ".binka"), Path.Combine(parent.GetDataPath())); + //Binka.ToWav(Path.Combine(treeView2.SelectedNode.Text + ".binka"), Path.Combine(parent.GetDataPath())); } } @@ -593,7 +568,7 @@ namespace PckStudio.Forms.Editor EditorValue.RemoveCategory(category.AudioType); - EditorValue.AddCategory(category.AudioType == PckAudioFile.AudioCategory.EAudioType.Overworld && playOverworldInCreative.Checked ? "include_overworld" : "", GetCategoryId(add.SelectedItem), category.ParameterType); + EditorValue.AddCategory(category.AudioType == PckAudioFile.Category.Overworld && playOverworldInCreative.Checked ? "include_overworld" : "", GetCategoryId(add.SelectedItem), category.ParameterType); PckAudioFile.AudioCategory newCategory = EditorValue.GetCategory(GetCategoryId(add.SelectedItem)); @@ -611,16 +586,16 @@ namespace PckStudio.Forms.Editor { if(MessageBox.Show(this, "This function will move all binka files in the \"Data\" folder into a \"Music\" folder, to keep your data better organized. Would you like to continue?", "Move tracks?", MessageBoxButtons.YesNo) == DialogResult.Yes) { - if (treeView1.Nodes.Count < 1 || !parent.CreateDataFolder()) + if (treeView1.Nodes.Count < 1) return; - string musicdir = Path.Combine(parent.GetDataPath(), "Music"); + string musicdir = Path.Combine("Music"); Directory.CreateDirectory(musicdir); foreach (PckAudioFile.AudioCategory category in EditorValue.Categories) { for (var i = 0; i < category.SongNames.Count; i++) // using standard for loop so the list can be modified { string song = category.SongNames[i]; - string songpath = Path.Combine(parent.GetDataPath(), song + ".binka"); + string songpath = Path.Combine(song + ".binka"); string new_path = Path.Combine(musicdir, Path.GetFileName(song) + ".binka"); if (File.Exists(songpath) && !File.Exists(new_path)) { diff --git a/PCK-Studio/Forms/Editor/AudioEditor.resx b/PCK-Studio/Forms/Editor/AudioEditor.resx index cad5e9bf..1b6a7194 100644 --- a/PCK-Studio/Forms/Editor/AudioEditor.resx +++ b/PCK-Studio/Forms/Editor/AudioEditor.resx @@ -125,32 +125,6 @@ 127, 8 - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO - vAAADrwBlbxySQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xMkMEa+wAAABSSURBVDhP5c0x - DsAgDENRxt7/wmkNSpRGf0CCCZAegxNMM7MlGMp3dIU6dxhKf/QMNxRogeQC8ivw5Vn7C0heJlFA+kL5 - jWAohxRkde4wnGftBS90axNmphIGAAAAAElFTkSuQmCC - - - - 168, 22 - - - Add Category - - - 168, 22 - - - Remove Category - - - 168, 22 - - - Set Category - 169, 70 @@ -172,7 +146,7 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAACK - NAAAAk1TRnQBSQFMAgEBCQEAAegBAAHoAQABEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA + NAAAAk1TRnQBSQFMAgEBCQEAAfABAAHwAQABEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA AwABMAMAAQEBAAEgBgABMBIAATkBXgFzAf8BOQFeAXMB/wE5AV4BcwH/AT4BYgF8Af8BMwFUAWkB/wEz AVQBaQH/AT4BYgF8Af8BMwFUAWkB/wE5AV4BcwH/ATkBXgFzAf8BOQFeAXMB/wEzAVQBaQH/ASYBPQFM Af8BMwFUAWkB/wEzAVQBaQH/ATkBXgFzAf/AAAFiAZgBvAH/AWIBmAG8Af8BTQGEAZ8B/wFNAYQBnwH/ @@ -426,12 +400,68 @@ 5 + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO + vAAADrwBlbxySQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xMkMEa+wAAABSSURBVDhP5c0x + DsAgDENRxt7/wmkNSpRGf0CCCZAegxNMM7MlGMp3dIU6dxhKf/QMNxRogeQC8ivw5Vn7C0heJlFA+kL5 + jWAohxRkde4wnGftBS90axNmphIGAAAAAElFTkSuQmCC + + + + 168, 22 + + + Add Category + + + 168, 22 + + + Remove Category + + + 168, 22 + + + Set Category + 19, 8 False + + 0, 0 + + + 450, 24 + + + 11 + + + menuStrip1 + + + menuStrip + + + System.Windows.Forms.MenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 7 + + + 37, 20 + + + File + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO @@ -448,11 +478,11 @@ Save - - 37, 20 + + 46, 20 - - File + + Tools 220, 22 @@ -478,11 +508,11 @@ Organize Tracks - - 46, 20 + + 44, 20 - - Tools + + Help 243, 22 @@ -514,42 +544,42 @@ BINKA Compression - - 44, 20 - - - Help - - - 0, 0 - - - 450, 24 - - - 11 - - - menuStrip1 - - - menuStrip - - - System.Windows.Forms.MenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 7 - Top, Bottom, Left, Right 282, 8 + + 174, 92 + + + contextMenuStrip2 + + + System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 151, 84 + + + 279, 208 + + + 13 + + + treeView2 + + + System.Windows.Forms.TreeView, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 6 + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO @@ -582,36 +612,6 @@ Convert To WAV - - 174, 92 - - - contextMenuStrip2 - - - System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 151, 84 - - - 279, 208 - - - 13 - - - treeView2 - - - System.Windows.Forms.TreeView, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 6 - True @@ -649,7 +649,7 @@ 310, 298 - 120, 20 + 120, 16 15 diff --git a/PCK-Studio/MainForm.cs b/PCK-Studio/MainForm.cs index e3b17515..5ddb4369 100644 --- a/PCK-Studio/MainForm.cs +++ b/PCK-Studio/MainForm.cs @@ -393,32 +393,6 @@ namespace PckStudio info.ShowDialog(this); } - [Obsolete("ReMove this")] - public string GetDataPath() - { - return ""; - } - - [Obsolete("Move this")] - public bool HasDataFolder() - { - return Directory.Exists(GetDataPath()); - } - - [Obsolete("Move this")] - public bool CreateDataFolder() - { - if (!HasDataFolder()) - { - DialogResult result = MessageBox.Show(this, "There is not a \"Data\" folder present in the pack folder. Would you like to create one?", "Folder missing", MessageBoxButtons.YesNo); - if (result == DialogResult.No) - return false; - else - Directory.CreateDirectory(GetDataPath()); - } - return true; - } - private void howToMakeABasicSkinPackToolStripMenuItem_Click(object sender, EventArgs e) => Process.Start("https://www.youtube.com/watch?v=A43aHRHkKxk"); private void howToMakeACustomSkinModelToolStripMenuItem_Click(object sender, EventArgs e) => Process.Start("https://www.youtube.com/watch?v=pEC_ug55lag"); diff --git a/PckStudio.Core/DLC/DLCManager.cs b/PckStudio.Core/DLC/DLCManager.cs index a570ebd9..93d4bc30 100644 --- a/PckStudio.Core/DLC/DLCManager.cs +++ b/PckStudio.Core/DLC/DLCManager.cs @@ -5,35 +5,35 @@ using System.Drawing; using System.Globalization; using System.IO; using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using System.Windows.Documents; using OMI; +using OMI.Formats.Color; using OMI.Formats.GameRule; using OMI.Formats.Languages; using OMI.Formats.Pck; +using OMI.Workers.Color; using OMI.Workers.GameRule; using OMI.Workers.Language; +using OMI.Workers.Material; using OMI.Workers.Pck; using PckStudio.Core.App; using PckStudio.Core.Deserializer; using PckStudio.Core.Extensions; using PckStudio.Core.Interfaces; using PckStudio.Core.IO.PckAudio; -using PckStudio.Core.Properties; using PckStudio.Interfaces; namespace PckStudio.Core.DLC { - public sealed class DLCManager + public class DLCManager { - public static DLCManager Default { get; } = new DLCManager(default, AppLanguage.SystemDefault); - internal const string DEFAULT_TEXTURE_PACK_FILENAME = "TexturePack.pck"; internal const string DEFAULT_MINIGAME_PACK_FILENAME = "WorldPack.pck"; internal const string DATA_DIRECTORY_NAME = "Data"; internal const string PACKAGE_DISPLAYNAME_ID = "IDS_DISPLAY_NAME"; + private const string BASE_SAVE_NAME_GRF_PARAMETER_KEY = "baseSaveName"; + private const string GRF_MAP_OPTIONS_NAME = "MapOptions"; + private const string TEXTURE_PACK_DATA_PATH_KEY = "DATAPATH"; + private const string CAPE_PATH_KEY = "CAPEPATH"; public ByteOrder ByteOrder => _byteOrder; @@ -117,7 +117,7 @@ namespace PckStudio.Core.DLC } int identifier = zeroAsset.HasProperty("PACKID") ? zeroAsset.GetProperty("PACKID", int.Parse) : -1; - if (identifier <= 0 || identifier > GameConstants.MAX_PACK_ID) + if (!identifier.IsWithinRangeOf(1, GameConstants.MAX_PACK_ID)) { Trace.TraceError($"{nameof(identifier)}({identifier}) was out of range!"); return new RawAssetDLCPackage(fileInfo.Name, pckFile, ByteOrder); @@ -204,19 +204,14 @@ namespace PckStudio.Core.DLC IEnumerable values = pck.GetAssetsByType(PckAssetType.GameRulesFile) .Concat(pck.GetAssetsByType(PckAssetType.GameRulesHeader)) .Select(asset => asset.GetData(reader)) - .SelectMany(grf => grf.Root.GetRules().Where(rule => rule.Name == "MapOptions" && rule.ContainsParameter("baseSaveName"))) - .Select(rule => rule.GetRule("MapOptions").GetParameterValue("baseSaveName")); + .SelectMany(grf => grf.Root.GetRules().Where(rule => rule.Name == GRF_MAP_OPTIONS_NAME && rule.ContainsParameter(BASE_SAVE_NAME_GRF_PARAMETER_KEY))) + .Select(rule => rule.GetParameterValue(BASE_SAVE_NAME_GRF_PARAMETER_KEY)); - Dictionary> saves = new Dictionary>(); - foreach (FileInfo worldFile in dataDirectory.EnumerateFiles("*.mcs").Where(file => values.Contains(file.Name))) - { - IDictionary save = MapReader.OpenSave(worldFile.OpenRead()); - saves.Add(worldFile.Name, save); + return dataDirectory.EnumerateFiles("*.mcs") + .Where(file => values.Contains(file.Name)) + .ToDictionary(worldFile => worldFile.Name, worldFile => MapReader.OpenSave(worldFile.OpenRead())); } - return saves; - } - private bool TryGetTexturePack(string name, string description, int identifier, DirectoryInfo dataDirectoryInfo, PckFile pckFile, PckFileReader pckFormatReader, out IDLCPackage texturePackage) { if (dataDirectoryInfo is null) @@ -232,7 +227,7 @@ namespace PckStudio.Core.DLC } DLCTexturePackage.TextureResolution resolution = DLCTexturePackage.GetTextureResolutionFromString(texturePackInfo.Filename); - string dataPath = texturePackInfo.GetProperty("DATAPATH"); + string dataPath = texturePackInfo.GetProperty(TEXTURE_PACK_DATA_PATH_KEY); if (string.IsNullOrWhiteSpace(dataPath)) { @@ -253,13 +248,8 @@ namespace PckStudio.Core.DLC PckFile texturePackPck = pckFormatReader.FromStream(texturePackFileStream); texturePackage = GetTexturePackageFromPckFile(name, description, identifier, infoPck, texturePackPck, resolution); - IEnumerable audioFiles = dataDirectoryInfo.EnumerateFiles("*.binka"); - IDictionary audios = new Dictionary(); - foreach (FileInfo audioFile in audioFiles) - { - byte[] data = File.ReadAllBytes(audioFile.FullName); - audios.Add(audioFile.Name, data); - } + IDictionary audios = dataDirectoryInfo.EnumerateFiles("*.binka") + .ToDictionary(audioFile => audioFile.Name, audioFile => File.ReadAllBytes(audioFile.FullName)); return texturePackage is not null; } @@ -270,68 +260,94 @@ namespace PckStudio.Core.DLC return null; if (!infoPck.TryGetAsset("comparison.png", PckAssetType.TextureFile, out PckAsset comparisonAsset)) - { Trace.TraceError($"Could not find 'comparison.png'."); - } + if (!infoPck.TryGetAsset("icon.png", PckAssetType.TextureFile, out PckAsset iconnAsset)) - { Trace.TraceError($"Could not find 'icon.png'."); - } Image comparisonImg = comparisonAsset?.GetTexture(); - Image iconImg = iconnAsset?.GetTexture() ?? Resources.unknown_pack; + Image iconImg = iconnAsset?.GetTexture(); DLCTexturePackage.MetaData metaData = new DLCTexturePackage.MetaData(comparisonImg, iconImg); bool hasTerrainAtlas = TryGetAtlasFromResourceCategory(dataPck, AtlasResource.AtlasType.BlockAtlas, out Atlas terrainAtlas); bool hasItemAtlas = TryGetAtlasFromResourceCategory(dataPck, AtlasResource.AtlasType.ItemAtlas, out Atlas itemAtlas); bool hasParticleAtlas = TryGetAtlasFromResourceCategory(dataPck, AtlasResource.AtlasType.ParticleAtlas, out Atlas particleAtlas); bool hasPaintingAtlas = TryGetAtlasFromResourceCategory(dataPck, AtlasResource.AtlasType.PaintingAtlas, out Atlas paintingAtlas); + bool hasMoonPhaseAtlas = TryGetAtlasFromResourceCategory(dataPck, AtlasResource.AtlasType.MoonPhaseAtlas, out Atlas moonPhaseAtlas); string itemAnimationAssetPath = ResourceLocation.GetPathFromCategory(ResourceCategory.ItemAnimation); IPckAssetDeserializer deserializer = AnimationDeserializer.DefaultDeserializer; - Animation compassAnimation = dataPck.TryGetAsset(itemAnimationAssetPath + "/compass.png", PckAssetType.TextureFile, out PckAsset compassAsset) ? comparisonAsset.GetDeserializedData(deserializer) : Animation.CreateEmpty(); - Animation clockAnimation = dataPck.TryGetAsset(itemAnimationAssetPath + "/clock.png", PckAssetType.TextureFile, out PckAsset clockAsset) ? clockAsset.GetDeserializedData(deserializer) : Animation.CreateEmpty(); - if (compassAnimation.FrameCount == 0) + IDictionary animations = dataPck.GetDirectoryContent(itemAnimationAssetPath, PckAssetType.TextureFile) + .ToDictionary(asset => Path.GetFileNameWithoutExtension(asset.Filename), deserializer.Deserialize); + + bool hasCompassAnimation = animations.ContainsKey("compass"); + bool hasClockAnimation = animations.ContainsKey("clock"); + + if (!hasCompassAnimation) Trace.TraceError("No compass animation found!"); - if (clockAnimation.FrameCount == 0) + if (!hasClockAnimation) Trace.TraceError("No clock animation found!"); - ITryGet tryGet = TryGet.FromDelegate((string path, out Image image) => + ITryGet tryGetTexture = TryGet.FromDelegate((string path, out Image image) => { bool success = dataPck.TryGetAsset(path, PckAssetType.TextureFile, out PckAsset asset); image = asset?.GetTexture(); return success; }); - Image[] blockEntityBreakingAnimation = new Image[10]; - for (int i = 0; i < blockEntityBreakingAnimation.Length; i++) - { - if (dataPck.TryGetAsset("", PckAssetType.TextureFile, out PckAsset asset)) - blockEntityBreakingAnimation[i] = asset.GetTexture(); - } + IEnumerable blockEntityBreakingFrames = dataPck.GetDirectoryContent("res/textures/", PckAssetType.TextureFile) + .Select(ImageDeserializer.DefaultDeserializer.Deserialize); + Animation blockEntityBreakAnimation = new Animation(blockEntityBreakingFrames); - ArmorSet[] armorSets = new ArmorSet[6] - { - ArmorSetDescription.Leather.GetArmorSet(tryGet), - ArmorSetDescription.Chain.GetArmorSet(tryGet), - ArmorSetDescription.Iron.GetArmorSet(tryGet), - ArmorSetDescription.Gold.GetArmorSet(tryGet), - ArmorSetDescription.Diamond.GetArmorSet(tryGet), - ArmorSetDescription.Turtle.GetArmorSet(tryGet) - }; - return new DLCTexturePackage(name, description, identifier, metaData, resolution, terrainAtlas, itemAtlas, particleAtlas, paintingAtlas, - armorSets, null, null, null, null, null, null, null, null); + ColorContainer colorContainer = dataPck.GetAssetsByType(PckAssetType.ColourTableFile).FirstOrDefault()?.GetData(new COLFileReader()) ?? new ColorContainer(); + + IDictionary colors = colorContainer.Colors + .GroupBy(c => c.Name) + .Select(grp => grp.FirstOrDefault()) + .ToDictionary(c => c.Name, c => c.ColorPallette); + IDictionary waterColors = colorContainer.WaterColors + .GroupBy(c => c.Name) + .Select(grp => grp.FirstOrDefault()) + .ToDictionary(c => c.Name, c => (c.SurfaceColor, c.UnderwaterColor, c.FogColor)); + + IDictionary environmentTextures = dataPck.GetDirectoryContent("res/environment/", PckAssetType.TextureFile) + .ToDictionary(a => Path.GetFileNameWithoutExtension(a.Filename), ImageDeserializer.DefaultDeserializer.Deserialize); + environmentTextures.TryGetValue("clouds", out Image clouds); + environmentTextures.TryGetValue("rain", out Image rain); + environmentTextures.TryGetValue("snow", out Image snow); + DLCTexturePackage.EnvironmentData environmentData = new DLCTexturePackage.EnvironmentData(clouds, rain, snow); + + IList> materials = dataPck.GetAssetsByType(PckAssetType.MaterialFile).FirstOrDefault()?.GetData(new MaterialFileReader()) + .Select(mat => new KeyValuePair(mat.Name, mat.Type)).ToList(); + + return new DLCTexturePackage(name, description, identifier, metaData, resolution, + terrainAtlas, itemAtlas, particleAtlas, paintingAtlas, moonPhaseAtlas, + ArmorSetDescription.Leather.GetArmorSet(tryGetTexture), + ArmorSetDescription.Chain.GetArmorSet(tryGetTexture), + ArmorSetDescription.Iron.GetArmorSet(tryGetTexture), + ArmorSetDescription.Gold.GetArmorSet(tryGetTexture), + ArmorSetDescription.Diamond.GetArmorSet(tryGetTexture), + ArmorSetDescription.Turtle.GetArmorSet(tryGetTexture), + environmentData, + colors, + waterColors: null, + customModels: null, + materials, + blockEntityBreakAnimation, + itemAnimations: null, + blockAnimations: null, + parentPackage: null); } private bool TryGetAtlasFromResourceCategory(PckFile pck, AtlasResource.AtlasType atlasType, out Atlas atlas) { - ResourceLocation resourceLocation = ResourceLocation.GetFromCategory((ResourceCategory)((int)ResourceCategory.Atlas | (int)atlasType)); + ResourceLocation resourceLocation = ResourceLocation.GetFromCategory(AtlasResource.GetId(atlasType)); if (!pck.TryGetAsset(resourceLocation.ToString(), PckAssetType.TextureFile, out PckAsset asset)) { - Trace.TraceWarning($"Could not find '{resourceLocation}'."); + Trace.TraceWarning($"Could not find '{resourceLocation.FullPath}'."); atlas = null; return false; } @@ -354,7 +370,7 @@ namespace PckStudio.Core.DLC Skin.Skin GetSkinWithCape(PckAsset skinAsset) { Skin.Skin skin = skinAsset.GetSkin(); - if (skinAsset.TryGetProperty("CAPEPATH", out string capeAssetPath) && pck.TryGetAsset(capeAssetPath, PckAssetType.CapeFile, out PckAsset capeAsset)) + if (skinAsset.TryGetProperty(CAPE_PATH_KEY, out string capeAssetPath) && pck.TryGetAsset(capeAssetPath, PckAssetType.CapeFile, out PckAsset capeAsset)) skin.CapeId = capeAsset.GetId(); return skin; } @@ -370,8 +386,32 @@ namespace PckStudio.Core.DLC skinPackage = new DLCSkinPackage(name, identifier, skins, capes, parentPackage); return true; } + + public static GameRuleFile.CompressionType GetCompressionTypeForPlatform(ConsolePlatform platform) + { + switch (platform) + { + case ConsolePlatform.Xbox360: + return GameRuleFile.CompressionType.XMem; + + case ConsolePlatform.PS3: + return GameRuleFile.CompressionType.Deflate; + + case ConsolePlatform.XboxOne: + case ConsolePlatform.PS4: + case ConsolePlatform.PSVita: + case ConsolePlatform.WiiU: + case ConsolePlatform.Switch: + return GameRuleFile.CompressionType.Zlib; + + case ConsolePlatform.Unknown: + default: + throw new ArgumentException("Platform was not set"); + } } + private GameRuleFile.CompressionType GetPlatformCompressionType() => GetCompressionTypeForPlatform(Platform); + private static string GetPreferredLanguage(AppLanguage appLanguage) { return appLanguage switch diff --git a/PckStudio.Core/Extensions/MathExtensions.cs b/PckStudio.Core/Extensions/MathExtensions.cs index 38fb5b2b..4faf8253 100644 --- a/PckStudio.Core/Extensions/MathExtensions.cs +++ b/PckStudio.Core/Extensions/MathExtensions.cs @@ -2,7 +2,7 @@ namespace PckStudio.Core.Extensions { - public class MathExtensions + public static class MathExtensions { public static T Clamp(T value, T min, T max) where T : IComparable { @@ -12,5 +12,10 @@ namespace PckStudio.Core.Extensions return max; return value; } + + public static bool IsWithinRangeOf(this T value, T min, T max) where T : IComparable + { + return value.CompareTo(min) >= 0 && value.CompareTo(max) <= 0; + } } } diff --git a/PckStudio.Core/Extensions/TreeNodeCollectionExtensions.cs b/PckStudio.Core/Extensions/TreeNodeCollectionExtensions.cs index 133b88f2..f04118b5 100644 --- a/PckStudio.Core/Extensions/TreeNodeCollectionExtensions.cs +++ b/PckStudio.Core/Extensions/TreeNodeCollectionExtensions.cs @@ -25,23 +25,35 @@ namespace PckStudio.Core.Extensions return node; } - public static TreeNode BuildNodeTreeBySeperator(this TreeNodeCollection root, string path, char seperator) + private static (string, string) Slice(this string s, int i) + => (s.Substring(0, i), s.Substring(i + 1)); + + public static TreeNode BuildNodeTreeBySeperator(this TreeNodeCollection root, string path, char seperator, int maxDepth = -1) + => root.BuildNodeTreeBySeperator(path, seperator.ToString(), maxDepth); + public static TreeNode BuildNodeTreeBySeperator(this TreeNodeCollection root, string path, string seperator, int maxDepth = -1) { _ = root ?? throw new ArgumentNullException(nameof(root)); - if (!path.Contains(seperator)) - { + if (maxDepth == 0 || !path.Contains(seperator)) return root.CreateNode(path); - } - string nodeText = path.Substring(0, path.IndexOf(seperator)); - string subPath = path.Substring(path.IndexOf(seperator) + 1); + + (string nodeText, string subPath) = path.Slice(path.IndexOf(seperator)); if (string.IsNullOrWhiteSpace(nodeText)) - { - return BuildNodeTreeBySeperator(root, subPath, seperator); - } + return BuildNodeTreeBySeperator(root, subPath, seperator, maxDepth - 1); TreeNode subNode = root.ContainsKey(nodeText) ? root[nodeText] : root.CreateNode(nodeText); - return BuildNodeTreeBySeperator(subNode.Nodes, subPath, seperator); + return BuildNodeTreeBySeperator(subNode.Nodes, subPath, seperator, maxDepth - 1); + } + + public static IEnumerable GetLeafNodes(this TreeNodeCollection root) + { + foreach (TreeNode node in root) + { + if (node.Nodes.Count == 0) + yield return node; + foreach (TreeNode ln in node.Nodes.GetLeafNodes()) + yield return ln; + } } } } diff --git a/PckStudio.Core/FileFormats/PckAudioFile.cs b/PckStudio.Core/FileFormats/PckAudioFile.cs index 0cf4b526..8466978f 100644 --- a/PckStudio.Core/FileFormats/PckAudioFile.cs +++ b/PckStudio.Core/FileFormats/PckAudioFile.cs @@ -15,34 +15,33 @@ namespace PckStudio.Core.FileFormats private AudioCategory[] _categories { get; } = new AudioCategory[9]; public Dictionary Credits { get; } = new Dictionary(); + public enum Category : int + { + Overworld, + Nether, + End, + Creative, + Menu, + Battle, + Tumble, + Glide, + BuildOff, + } + + public enum EAudioParameterType : int + { + Unk0, // dimension music + Unk1, // unused music ? + } public sealed class AudioCategory { - public enum EAudioType : int - { - Overworld, - Nether, - End, - Creative, - Menu, - Battle, - Tumble, - Glide, - BuildOff, - } - - public enum EAudioParameterType : int - { - Unk0, // dimension music - Unk1, // unused music ? - } - public string Name { get; set; } = string.Empty; - public EAudioType AudioType { get; } + public Category AudioType { get; } public List SongNames { get; } = new List(); public EAudioParameterType ParameterType { get; } - public AudioCategory(string name, EAudioParameterType parameterType, EAudioType audioType) + public AudioCategory(string name, EAudioParameterType parameterType, Category audioType) { Name = name; ParameterType = parameterType; @@ -98,17 +97,17 @@ namespace PckStudio.Core.FileFormats /// - public bool HasCategory(AudioCategory.EAudioType category) => GetCategory(category) is AudioCategory; + public bool HasCategory(Category category) => GetCategory(category) is AudioCategory; /// - public AudioCategory GetCategory(AudioCategory.EAudioType category) + public AudioCategory GetCategory(Category category) { - if (!Enum.IsDefined(typeof(AudioCategory.EAudioType), category)) + if (!Enum.IsDefined(typeof(Category), category)) throw new InvalidCategoryException(nameof(category)); return _categories[(int)category]; } - public bool TryGetCategory(AudioCategory.EAudioType category, out AudioCategory audioCategory) + public bool TryGetCategory(Category category, out AudioCategory audioCategory) { if (GetCategory(category) is AudioCategory audioCat) { @@ -121,9 +120,9 @@ namespace PckStudio.Core.FileFormats /// True when category was created, otherwise false /// - public bool AddCategory(string name, AudioCategory.EAudioType category, AudioCategory.EAudioParameterType parameterType) + public bool AddCategory(string name, Category category, EAudioParameterType parameterType) { - if (!Enum.IsDefined(typeof(AudioCategory.EAudioType), category)) + if (!Enum.IsDefined(typeof(Category), category)) throw new InvalidCategoryException(nameof(category)); bool exists = HasCategory(category); if (!exists) @@ -133,11 +132,11 @@ namespace PckStudio.Core.FileFormats /// True when category was created, otherwise false /// - public bool AddCategory(AudioCategory.EAudioType category) => AddCategory("", category, AudioCategory.EAudioParameterType.Unk0); + public bool AddCategory(Category category) => AddCategory("", category, EAudioParameterType.Unk0); /// True when category was removed, otherwise false /// - public bool RemoveCategory(AudioCategory.EAudioType category) + public bool RemoveCategory(Category category) { bool exists = HasCategory(category); if (exists) diff --git a/PckStudio.Core/IO/PckAudio/PckAudioFileReader.cs b/PckStudio.Core/IO/PckAudio/PckAudioFileReader.cs index a4489fe5..3b5e4633 100644 --- a/PckStudio.Core/IO/PckAudio/PckAudioFileReader.cs +++ b/PckStudio.Core/IO/PckAudio/PckAudioFileReader.cs @@ -16,7 +16,7 @@ namespace PckStudio.Core.IO.PckAudio private PckAudioFile _file; private ByteOrder _endianness; private List LUT = new List(); - private List _OriginalAudioTypeOrder = new List(); + private List _OriginalAudioTypeOrder = new List(); public PckAudioFileReader(ByteOrder endianness) { @@ -75,8 +75,8 @@ namespace PckStudio.Core.IO.PckAudio int categoryEntryCount = reader.ReadInt32(); for (; 0 < categoryEntryCount; categoryEntryCount--) { - var parameterType = (PckAudioFile.AudioCategory.EAudioParameterType)reader.ReadInt32(); - var audioType = (PckAudioFile.AudioCategory.EAudioType)reader.ReadInt32(); + var parameterType = (PckAudioFile.EAudioParameterType)reader.ReadInt32(); + var audioType = (PckAudioFile.Category)reader.ReadInt32(); string name = ReadString(reader); // AddCategory puts the file's categories out of order and causes some songs to be put in the wrong categories // This is my simple fix for the issue. @@ -89,7 +89,7 @@ namespace PckStudio.Core.IO.PckAudio { List credits = new List(); List creditIds = new List(); - foreach (PckAudioFile.AudioCategory.EAudioType c in _OriginalAudioTypeOrder) + foreach (PckAudioFile.Category c in _OriginalAudioTypeOrder) { int audioCount = reader.ReadInt32(); for (; 0 < audioCount; audioCount--)