diff --git a/PCK-Studio/Controls/PckEditor.cs b/PCK-Studio/Controls/PckEditor.cs index dc461bac..c29e6f84 100644 --- a/PCK-Studio/Controls/PckEditor.cs +++ b/PCK-Studio/Controls/PckEditor.cs @@ -722,9 +722,9 @@ namespace PckStudio.Controls if (EditorValue is not null && TryGetLocFile(out LOCFile locfile) && locfile.HasLocEntry("IDS_DISPLAY_NAME") && - locfile.Languages.Contains("en-EN")) + locfile.Languages.Contains(DLCManager.Default.PreferredLanguage)) { - RPC.SetPresence("Editing a Pack:", $" > {locfile.GetLocEntry("IDS_DISPLAY_NAME", "en-EN")}"); + RPC.SetPresence("Editing a Pack:", $" > {locfile.GetLocEntry("IDS_DISPLAY_NAME", DLCManager.Default.PreferredLanguage)}"); return; } // default diff --git a/PCK-Studio/Forms/Additional-Popups/CreateTexturePackPrompt.Designer.cs b/PCK-Studio/Forms/Additional-Popups/CreateTexturePackPrompt.Designer.cs index 9dbc2d42..a9a14734 100644 --- a/PCK-Studio/Forms/Additional-Popups/CreateTexturePackPrompt.Designer.cs +++ b/PCK-Studio/Forms/Additional-Popups/CreateTexturePackPrompt.Designer.cs @@ -86,16 +86,6 @@ // this.resolutionComboBox.FormattingEnabled = true; resources.ApplyResources(this.resolutionComboBox, "resolutionComboBox"); - this.resolutionComboBox.Items.AddRange(new object[] { - resources.GetString("resolutionComboBox.Items"), - resources.GetString("resolutionComboBox.Items1"), - resources.GetString("resolutionComboBox.Items2"), - resources.GetString("resolutionComboBox.Items3"), - resources.GetString("resolutionComboBox.Items4"), - resources.GetString("resolutionComboBox.Items5"), - resources.GetString("resolutionComboBox.Items6"), - resources.GetString("resolutionComboBox.Items7"), - resources.GetString("resolutionComboBox.Items8")}); this.resolutionComboBox.Name = "resolutionComboBox"; this.resolutionComboBox.Style = MetroFramework.MetroColorStyle.Silver; this.resolutionComboBox.Theme = MetroFramework.MetroThemeStyle.Dark; diff --git a/PCK-Studio/Forms/Additional-Popups/CreateTexturePackPrompt.cs b/PCK-Studio/Forms/Additional-Popups/CreateTexturePackPrompt.cs index 52f8fe9d..93272581 100644 --- a/PCK-Studio/Forms/Additional-Popups/CreateTexturePackPrompt.cs +++ b/PCK-Studio/Forms/Additional-Popups/CreateTexturePackPrompt.cs @@ -1,6 +1,7 @@ using System; using System.Windows.Forms; using MetroFramework.Forms; +using PckStudio.Core; namespace PckStudio { @@ -16,6 +17,7 @@ namespace PckStudio public CreateTexturePackPrompt() { InitializeComponent(); + resolutionComboBox.Items.AddRange(Enum.GetNames(typeof(DLCTexturePackage.TextureResolution))); } private void OKBtn_Click(object sender, EventArgs e) diff --git a/PCK-Studio/Forms/Additional-Popups/CreateTexturePackPrompt.resx b/PCK-Studio/Forms/Additional-Popups/CreateTexturePackPrompt.resx index 5c08d9b8..88ebb5e2 100644 --- a/PCK-Studio/Forms/Additional-Popups/CreateTexturePackPrompt.resx +++ b/PCK-Studio/Forms/Additional-Popups/CreateTexturePackPrompt.resx @@ -213,33 +213,6 @@ 23 - - x8 - - - x16 - - - x32 - - - x48 - - - x64 - - - x80 - - - x96 - - - x112 - - - x128 - 76, 40 diff --git a/PCK-Studio/MainForm.cs b/PCK-Studio/MainForm.cs index 300609d0..8c31c33a 100644 --- a/PCK-Studio/MainForm.cs +++ b/PCK-Studio/MainForm.cs @@ -37,8 +37,10 @@ namespace PckStudio public MainForm() { InitializeComponent(); - - Text = Application.ProductName; +#if DEBUG + DLCManager.Default.Platform = ConsolePlatform.WiiU; +#endif + Text = Application.ProductName; labelVersion.Text = $"{Application.ProductName}: {ApplicationScope.CurrentVersion}"; @@ -57,6 +59,8 @@ namespace PckStudio public void LoadPckFromFile(string filepath) { + Core.Interfaces.IDLCPackage dlcPackage = DLCManager.Default.OpenDLCPackage(filepath); + Debug.WriteLine(dlcPackage?.GetDLCPackageType()); AddEditorPage(filepath); } diff --git a/PckStudio.Core/ConsolePlatform.cs b/PckStudio.Core/ConsolePlatform.cs new file mode 100644 index 00000000..a727029d --- /dev/null +++ b/PckStudio.Core/ConsolePlatform.cs @@ -0,0 +1,14 @@ +namespace PckStudio.Core +{ + public enum ConsolePlatform + { + Unknown, + Xbox360, + XboxOne, + PS3, + PS4, + PSVita, + WiiU, + Switch + } +} \ No newline at end of file diff --git a/PckStudio.Core/DLCBattlePackage.cs b/PckStudio.Core/DLCBattlePackage.cs new file mode 100644 index 00000000..a10a516c --- /dev/null +++ b/PckStudio.Core/DLCBattlePackage.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using PckStudio.Core.Interfaces; + +namespace PckStudio.Core +{ + internal sealed class DLCBattlePackage : DLCPackage + { + + private List _maps = new List(); + + public DLCBattlePackage(string name, int identifier, IDLCPackageLocationInfo packageInfo = null, IDLCPackage parentPackage = null) + : base(name, identifier, packageInfo, parentPackage) + { + } + + public void AddMap(string name, Image thumbnail, MapSize mapSize, NamedData world) + { + _maps.Add(new MapData(name, thumbnail, MiniGameId.Battle, mapSize, world)); + } + + public override DLCPackageType GetDLCPackageType() => DLCPackageType.MG01; + } +} diff --git a/PckStudio.Core/DLCManager.cs b/PckStudio.Core/DLCManager.cs new file mode 100644 index 00000000..c1952c1d --- /dev/null +++ b/PckStudio.Core/DLCManager.cs @@ -0,0 +1,268 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using OMI.Formats.GameRule; +using OMI.Formats.Languages; +using OMI.Formats.Pck; +using OMI.Workers.GameRule; +using OMI.Workers.Language; +using OMI.Workers.Pck; +using PckStudio.Core.Deserializer; +using PckStudio.Core.Extensions; +using PckStudio.Core.Interfaces; + +namespace PckStudio.Core +{ + public sealed class DLCManager + { + public static DLCManager Default { get; } = new DLCManager(default, default, AvailableLanguages.English); + + public OMI.ByteOrder ByteOrder { get; set; } + + public ConsolePlatform Platform { get; set; } + + /// + /// See for details. + /// + public string PreferredLanguage { get; set; } + + private const string PackageDisplayNameId = "IDS_DISPLAY_NAME"; + private readonly IDictionary _openPackages = new Dictionary(); + private readonly IDictionary _localisationFiles = new Dictionary(); + private readonly Random _rng = new Random(); + + /// + /// + /// + /// + /// + /// See for details. + public DLCManager(OMI.ByteOrder byteOrder, ConsolePlatform platform, string preferredLanguage) + { + ByteOrder = byteOrder; + Platform = platform; + PreferredLanguage = preferredLanguage; + } + + public IDLCPackage CreateNewPackage(string name, DLCPackageType packageType) + { + int identifier = _rng.Next(8000, GameConstants.MAX_PACK_ID); + IDLCPackage package = packageType switch + { + DLCPackageType.SkinPack => DLCSkinPackage.CreateEmpty(name, identifier), + DLCPackageType.TexturePack => DLCTexturePackage.CreateDefaultPackage(name, "", identifier), + DLCPackageType.MashUpPack => new DLCMashUpPackage(name, "", identifier), + //! TODO: implemnt minigame dlc packages -null + DLCPackageType.MG01 => new DLCBattlePackage(name, identifier), + DLCPackageType.MG02 => throw new NotImplementedException(), + DLCPackageType.MG03 => throw new NotImplementedException(), + DLCPackageType.Invalid => InvalidDLCPackage.Instance, + _ => throw new ArgumentException("Unable to create DLC Package of 'Unknown' type."), + }; + + LOCFile localisation = new LOCFile(); + localisation.AddLanguage(PreferredLanguage); + localisation.AddLocKey(PackageDisplayNameId, name); + _localisationFiles.Add(identifier, localisation); + _openPackages.Add(identifier, package); + + return package; + } + + public IDLCPackage OpenDLCPackage(string filepath) => OpenDLCPackage(new FileInfo(filepath)); + + public IDLCPackage OpenDLCPackage(FileInfo fileInfo) + { + if (!IsValidPckFile(fileInfo)) + return InvalidDLCPackage.Instance; + + using Stream stream = fileInfo.OpenRead(); + + PckFileReader fileReader = new PckFileReader(ByteOrder); + + PckFile pckFile = fileReader.FromStream(stream); + + Debug.Assert(pckFile.TryGetAsset("0", PckAssetType.InfoFile, out PckAsset zeroAsset), "Could not find asset named:'0'."); + + int identifier = (zeroAsset?.HasProperty("PACKID") ?? default) ? zeroAsset.GetProperty("PACKID", int.Parse) : -1; + if (identifier <= 0 || identifier > GameConstants.MAX_PACK_ID) + { + Trace.TraceError($"{nameof(identifier)}({identifier}) was out of range!"); + return InvalidDLCPackage.Instance; + } + + if (_openPackages.ContainsKey(identifier)) + return _openPackages[identifier]; + + LOCFile localisation = pckFile.GetAssetsByType(PckAssetType.LocalisationFile).FirstOrDefault()?.GetData(new LOCFileReader()); + if (localisation is null) + return InvalidDLCPackage.Instance; + _localisationFiles.Add(identifier, localisation); + + IDLCPackage package = ScanForPackageType(fileInfo, identifier, pckFile, localisation, fileReader); + _openPackages.Add(identifier, package); + return package; + } + + internal LOCFile GetLocalisation(int identifier) + { + return _localisationFiles.ContainsKey(identifier) ? _localisationFiles[identifier] : default; + } + + private bool IsValidPckFile(FileInfo fileInfo) + { + if (!fileInfo.Exists) + throw new FileNotFoundException(fileInfo.FullName); + + if (fileInfo.Extension != ".pck") + throw new FileFormatException("File does not end with '.pck'."); + return true; + } + + private IDLCPackage ScanForPackageType(FileInfo fileInfo, int identifier, PckFile pckFile, LOCFile localisation, PckFileReader fileReader) + { + bool hasLanguage = localisation?.Languages?.Contains(PreferredLanguage) ?? default; + + string name = hasLanguage && (localisation?.HasLocEntry(PackageDisplayNameId) ?? default) + ? localisation.GetLocEntry(PackageDisplayNameId, PreferredLanguage) : fileInfo.Name; + + string description = hasLanguage && (localisation?.HasLocEntry(DLCTexturePackage.TexturePackDescriptionId) ?? default) + ? localisation.GetLocEntry(DLCTexturePackage.TexturePackDescriptionId, PreferredLanguage) : string.Empty; + + bool couldBeTexturePack = fileInfo.Name == "TexturePack.pck"; + + bool hasSkins = pckFile.Contains(PckAssetType.SkinFile) || pckFile.Contains(PckAssetType.SkinDataFile); + + DLCPackageType dlcPackageType = hasSkins ? DLCPackageType.SkinPack : DLCPackageType.Unknown; + + IDLCPackage skinPackage = hasSkins ? GetDLCSkinPackage(name, identifier, pckFile, fileReader) : null; + + PckAsset texturePackInfo = pckFile.GetAssetsByType(PckAssetType.TexturePackInfoFile).FirstOrDefault(); + string dataPath = texturePackInfo is not null ? texturePackInfo.GetProperty("DATAPATH") : string.Empty; + + DirectoryInfo dataDirectoryInfo = fileInfo.Directory.EnumerateDirectories().Where(dirInfo => dirInfo.Name == "Data").FirstOrDefault(); + bool hasDataFolder = dataDirectoryInfo is not null; + + if (hasDataFolder && !string.IsNullOrWhiteSpace(dataPath)) + { + PckFile infoPck = texturePackInfo.GetData(fileReader); + FileInfo texturePackFileInfo = dataDirectoryInfo.EnumerateFiles().Where(fileInfo => fileInfo.Name == dataPath).FirstOrDefault(); + if (IsValidPckFile(texturePackFileInfo)) + { + using Stream texturePackFileStream = texturePackFileInfo.OpenRead(); + PckFile texturePackPck = fileReader.FromStream(texturePackFileStream); + IDLCPackage texturePackage = GetTexturePackageFromPckFile(infoPck, texturePackPck); + dlcPackageType = DLCPackageType.TexturePack; + } + + bool hasSavefile = dataDirectoryInfo.EnumerateFiles("*.mcs").Any(); + PckAsset gameRuleAsset = null; + if (Platform == ConsolePlatform.Unknown) + throw new Exception($"{nameof(Platform)} is Unknown."); + bool hasGameRuleFile = pckFile.Contains("GameRules.grf", PckAssetType.GameRulesFile) && pckFile.TryGetAsset("GameRules.grf", PckAssetType.GameRulesFile, out gameRuleAsset); + + if (hasSavefile && hasGameRuleFile) + { + GameRuleFile gameRuleFile = gameRuleAsset.GetData(new GameRuleFileReader(GetPlatformCompressionType())); + dlcPackageType = DLCPackageType.MashUpPack; + } + } + Debug.WriteLine(dlcPackageType); + return InvalidDLCPackage.Instance; + } + + private GameRuleFile.CompressionType GetPlatformCompressionType() + { + 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: + return GameRuleFile.CompressionType.Unknown; + } + } + + private IDLCPackage GetTexturePackageFromPckFile(PckFile infoPck, PckFile dataPck) + { + if (!infoPck.TryGetAsset("comparison.png", PckAssetType.TextureFile, out PckAsset comparisonAsset)) + { + Trace.TraceError($"Could not find 'comparison.png'."); + return InvalidDLCPackage.Instance; + } + if (!infoPck.TryGetAsset("icon.png", PckAssetType.TextureFile, out PckAsset iconnAsset)) + { + Trace.TraceError($"Could not find 'icon.png'."); + return InvalidDLCPackage.Instance; + } + + Image comparisonImg = comparisonAsset.GetTexture(); + Image iconImg = iconnAsset.GetTexture(); + DLCTexturePackage.MetaData metaData = new DLCTexturePackage.MetaData(comparisonImg, iconImg); + + + bool a = TryGetAtlasFromResourceCategory(dataPck, ResourceCategory.BlockAtlas, out Atlas terrainAtlas); + bool b = TryGetAtlasFromResourceCategory(dataPck, ResourceCategory.ItemAtlas, out Atlas itemAtlas); + + string itemAnimationResourcePath = ResourceLocation.GetPathFromCategory(ResourceCategory.ItemAnimation); + if (dataPck != null && + dataPck.TryGetAsset(itemAnimationResourcePath + "/compass.png", PckAssetType.TextureFile, out PckAsset compassAsset) && + dataPck.TryGetAsset(itemAnimationResourcePath + "/clock.png", PckAssetType.TextureFile, out PckAsset clockAsset)) + { + + } + return null; + } + + private bool TryGetAtlasFromResourceCategory(PckFile pck, ResourceCategory resourceCategory, out Atlas atlas) + { + ResourceLocation resourceLocation = ResourceLocation.GetFromCategory(resourceCategory); + if (!pck.TryGetAsset(resourceLocation.ToString(), PckAssetType.TextureFile, out PckAsset asset)) + { + Trace.TraceWarning($"Could not find '{resourceLocation}'."); + atlas = null; + return false; + } + atlas = asset.GetDeserializedData(new AtlasDeserializer(resourceLocation)); + return true; + } + + private IDLCPackage GetDLCSkinPackage(string name, int identifier, PckFile pck, PckFileReader fileReader, IDLCPackage parentPackage = null) + { + 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)) + skin.CapeTexture = capeAsset.GetTexture(); + return skin; + } + + IEnumerable skins = pck.GetAssetsByType(PckAssetType.SkinFile).Select(GetSkinWithCape); + + skins = skins.Concat(pck.GetAssetsByType(PckAssetType.SkinDataFile) + .Select(asset => asset.GetData(fileReader)) + .SelectMany(pck => pck.GetAssetsByType(PckAssetType.SkinFile)) + .Select(GetSkinWithCape) + ); + + return new DLCSkinPackage(name, identifier, skins, null, parentPackage); + } + } +} \ No newline at end of file diff --git a/PckStudio.Core/DLCMashUpPackage.cs b/PckStudio.Core/DLCMashUpPackage.cs new file mode 100644 index 00000000..385b48d4 --- /dev/null +++ b/PckStudio.Core/DLCMashUpPackage.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using OMI.Formats.GameRule; +using PckStudio.Core.Interfaces; + +namespace PckStudio.Core +{ + public sealed class DLCMashUpPackage : DLCPackage + { + public override string Description { get; } + + private IDLCPackage _skinPackage; + private IDLCPackage _texturePackage; + private GameRuleFile _gameRule; + private IList> _audioData; + private NamedData _savegameData; + + internal DLCMashUpPackage(string name, string description, int identifier, IDLCPackageLocationInfo packageInfo, GameRuleFile gameRule, IDLCPackage parentPackage, IDLCPackage skinPackage = null, IDLCPackage texturePackage = null) + : base(name, identifier, packageInfo, parentPackage) + { + Description = description; + _gameRule = gameRule; + _skinPackage = skinPackage; + _texturePackage = texturePackage; + } + + internal DLCMashUpPackage(string name, string description, int identifier) + : this(name, description, identifier, null, new GameRuleFile(), null) + { + _skinPackage = DLCSkinPackage.CreateEmpty(this); + _texturePackage = DLCTexturePackage.CreateDefaultPackage(this); + _savegameData = new NamedData("world.mcs", Array.Empty()); + _audioData = new List>(); + + _gameRule.AddRule("MapOptions", + new GameRuleFile.IntParameter("seed", 0), + new GameRuleFile.GameRuleParameter("baseSaveName", _savegameData.Name), + new GameRuleFile.BoolParameter("flatworld", false), + new GameRuleFile.IntParameter("texturePackId", Identifier) + ); + _gameRule.AddRule("LevelRules") + .AddRule("UpdatePlayer", + new GameRuleFile.FloatParameter("yRot", 0f), + new GameRuleFile.FloatParameter("xRot", 0f), + new GameRuleFile.IntParameter("spawnX", 0), + new GameRuleFile.IntParameter("spawnY", 0), + new GameRuleFile.IntParameter("spawnZ", 0) + ); + } + + public IDLCPackage GetSkinPackage() => _skinPackage; + public IDLCPackage GetTexturePackage() => _texturePackage; + + public override DLCPackageType GetDLCPackageType() => DLCPackageType.MashUpPack; + } +} diff --git a/PckStudio.Core/DLCPackage.cs b/PckStudio.Core/DLCPackage.cs new file mode 100644 index 00000000..5549c213 --- /dev/null +++ b/PckStudio.Core/DLCPackage.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using PckStudio.Core.Interfaces; + +namespace PckStudio.Core +{ + public abstract class DLCPackage : IDLCPackage + { + protected DLCPackage(string name, int identifier, IDLCPackageLocationInfo packageInfo, IDLCPackage parentPackage) + { + Name = name; + Identifier = identifier; + PackageInfo = packageInfo; + ParentPackage = parentPackage; + } + + public int Identifier { get; } + + public IDLCPackageLocationInfo PackageInfo { get; } + + public string Name { get; } = string.Empty; + + public virtual string Description { get; } = string.Empty; + + public abstract DLCPackageType GetDLCPackageType(); + + public IDLCPackage ParentPackage { get; } + + public bool IsRootPackage => ParentPackage is null; + } +} diff --git a/PckStudio.Core/DLCPackageType.cs b/PckStudio.Core/DLCPackageType.cs new file mode 100644 index 00000000..333cf391 --- /dev/null +++ b/PckStudio.Core/DLCPackageType.cs @@ -0,0 +1,15 @@ +namespace PckStudio.Core +{ + public enum DLCPackageType + { + Unknown = -1, + Invalid, + SkinPack, + TexturePack, + MashUpPack, + //! TODO: Add DLCPackage class for minigames... -null + MG01, + MG02, + MG03, + } +} \ No newline at end of file diff --git a/PckStudio.Core/DLCSkinPackage.cs b/PckStudio.Core/DLCSkinPackage.cs new file mode 100644 index 00000000..bff1bbeb --- /dev/null +++ b/PckStudio.Core/DLCSkinPackage.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using PckStudio.Core.Interfaces; +using PckStudio.Core.Skin; + +namespace PckStudio.Core +{ + public enum DLCSkinPackageOrder + { + ById, + CapesFirst, + SkinsFirst + } + + public sealed class DLCSkinPackage : DLCPackage + { + public DLCSkinPackageOrder SkinPackageOrder { get; set; } = DLCSkinPackageOrder.CapesFirst; + + private readonly Dictionary _skins; + + internal DLCSkinPackage(string name, int identifier, IEnumerable skins, IDLCPackageLocationInfo packageInfo, IDLCPackage parentPackage) + : base(name, identifier, packageInfo, parentPackage) + { + _skins = skins.ToDictionary(skin => skin.Identifier); + } + + internal DLCSkinPackage(string name, int identifier, IDLCPackage parentPackage = null) + : this(name, identifier, Enumerable.Empty(), null, parentPackage) + { + } + + internal static IDLCPackage CreateEmpty(string name, int identifier, IDLCPackage parentPackage = null) => new DLCSkinPackage(name, identifier, parentPackage); + internal static IDLCPackage CreateEmpty(IDLCPackage parentPackage) => CreateEmpty(parentPackage.Name, parentPackage.Identifier, parentPackage); + + public bool TryGetSkin(SkinIdentifier skinIdentifier, out Skin.Skin skin) => _skins.TryGetValue(skinIdentifier, out skin); + + public bool ContainsSkin(SkinIdentifier skinIdentifier) => _skins.ContainsKey(skinIdentifier); + + public void AddSkin(Skin.Skin skin) => _skins.Add(skin.Identifier, skin); + + public bool RemoveSkin(SkinIdentifier skinIdentifier) => _skins.Remove(skinIdentifier); + + public Skin.Skin GetSkin(SkinIdentifier skinIdentifier) => _skins[skinIdentifier]; + + public IReadOnlyCollection GetSkins() => _skins.Values.Cast().ToArray(); + + public override DLCPackageType GetDLCPackageType() => DLCPackageType.SkinPack; + } +} \ No newline at end of file diff --git a/PckStudio.Core/DLCTexturePackage.cs b/PckStudio.Core/DLCTexturePackage.cs new file mode 100644 index 00000000..24957a2a --- /dev/null +++ b/PckStudio.Core/DLCTexturePackage.cs @@ -0,0 +1,142 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using OMI.Formats.Color; +using OMI.Formats.Material; +using OMI.Formats.Model; +using OMI.Formats.Pck; +using OMI.Workers.Color; +using PckStudio.Core.Interfaces; +using PckStudio.Core.Properties; + +namespace PckStudio.Core +{ + public sealed class DLCTexturePackage : DLCPackage + { + public enum TextureResolution + { + x8, + x16, + x32, + x48, + x64, + x80, + x96, + x112, + x128 + } + + public override string Description { get; } + internal const string TexturePackDescriptionId = "IDS_TP_DESCRIPTION"; + + private TextureResolution _resolution; + + //! Data for x{_resolution}Info.pck + public sealed class MetaData + { + public Image ComparisonImg { get; } + public Image IconImg { get; } + + public MetaData(Image comparisonImg, Image iconImg) + { + ComparisonImg = comparisonImg; + IconImg = iconImg; + } + } + + public MetaData Info { get; } + + //! Data for x{16}Data.pck + //! => colours.col + private IDictionary _colors; + private IDictionary _waterColors; + private ModelContainer _customModels; //! => models.bin + private MaterialContainer _materials; + + //! terrain mipmaps will be generated automatically. Add mipmap option to settings menu ? -null + private Atlas _terrainAtlas; + private Atlas _itemsAtlas; + private Atlas _particlesAtlas; + private Atlas _paintingAtlas; + + private Image[] _blockEntityBreakImages; //! max = 10! + private IDictionary _itemAnimations; + private IDictionary _blockAnimations; + + internal DLCTexturePackage( + string name, + string description, + int identifier, + MetaData metaData, + TextureResolution resolution, + Atlas terrainAtlas, + Atlas itemsAtlas, + Atlas particlesAtlas, + Atlas paintingAtlas, + IDictionary colors, + IDictionary waterColors, + ModelContainer customModels, + MaterialContainer materials, + Image[] blockEntityBreakImages, + IDictionary itemAnimations, + IDictionary blockAnimations, + IDLCPackageLocationInfo packageInfo, + IDLCPackage parentPackage + ) + : base(name, identifier, packageInfo, parentPackage) + { + Description = description; + Info = metaData; + _resolution = resolution; + _terrainAtlas = terrainAtlas; + _itemsAtlas = itemsAtlas; + _particlesAtlas = particlesAtlas; + _paintingAtlas = paintingAtlas; + _colors = colors; + _waterColors = waterColors; + _customModels = customModels; + _materials = materials; + _blockEntityBreakImages = blockEntityBreakImages; + _itemAnimations = itemAnimations; + _blockAnimations = blockAnimations; + } + + public TextureResolution GetResolution() => _resolution; + + public override DLCPackageType GetDLCPackageType() => DLCPackageType.TexturePack; + + internal static IDLCPackage CreateDefaultPackage(IDLCPackage parentPackage) + => CreateDefaultPackage(parentPackage.Name, parentPackage.Description, parentPackage.Identifier, parentPackage); + + internal static IDLCPackage CreateDefaultPackage(string name, string description, int identifier, IDLCPackage parentPackage = null) + { + TextureResolution resolution = TextureResolution.x16; + MetaData metadata = new MetaData(Resources.Comparison, Resources.TexturePackIcon); + + Atlas terrain = Atlas.FromResourceLocation(Resources.terrain_atlas , ResourceLocation.GetFromCategory(ResourceCategory.BlockAtlas)); + Atlas items = Atlas.FromResourceLocation(Resources.items_atlas , ResourceLocation.GetFromCategory(ResourceCategory.ItemAtlas)); + Atlas particles = Atlas.FromResourceLocation(Resources.particles_atlas, ResourceLocation.GetFromCategory(ResourceCategory.ParticleAtlas)); + Atlas painting = Atlas.FromResourceLocation(Resources.paintings_atlas, ResourceLocation.GetFromCategory(ResourceCategory.PaintingAtlas)); + //ColorContainer colors = new COLFileReader().FromStream(new MemoryStream()); + IDictionary colors = null; + IDictionary waterColors = null; + Image[] blockEntityBreakImages = terrain.GetRange(0, 15, 10, ImageLayoutDirection.Horizontal).Select(t => t.Texture).ToArray(); + + return new DLCTexturePackage( + name, description, identifier, metadata, resolution, + terrain, items, particles, painting, + colors, waterColors, + new ModelContainer(), + new MaterialContainer(), + blockEntityBreakImages, + null, null, + null, parentPackage + ); + } + } +} \ No newline at end of file diff --git a/PckStudio.Core/Interfaces/IDLCPackage.cs b/PckStudio.Core/Interfaces/IDLCPackage.cs new file mode 100644 index 00000000..82ec6910 --- /dev/null +++ b/PckStudio.Core/Interfaces/IDLCPackage.cs @@ -0,0 +1,17 @@ +namespace PckStudio.Core.Interfaces +{ + public interface IDLCPackage + { + string Name { get; } + string Description { get; } + int Identifier { get; } + + bool IsRootPackage { get; } + + IDLCPackageLocationInfo PackageInfo { get; } + + DLCPackageType GetDLCPackageType(); + + IDLCPackage ParentPackage { get; } + } +} diff --git a/PckStudio.Core/Interfaces/IDLCPackageLocationInfo.cs b/PckStudio.Core/Interfaces/IDLCPackageLocationInfo.cs new file mode 100644 index 00000000..01425d20 --- /dev/null +++ b/PckStudio.Core/Interfaces/IDLCPackageLocationInfo.cs @@ -0,0 +1,7 @@ +namespace PckStudio.Core.Interfaces +{ + public interface IDLCPackageLocationInfo + { + + } +} diff --git a/PckStudio.Core/InvalidDLCPackage.cs b/PckStudio.Core/InvalidDLCPackage.cs new file mode 100644 index 00000000..e4456f21 --- /dev/null +++ b/PckStudio.Core/InvalidDLCPackage.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using PckStudio.Core.Interfaces; + +namespace PckStudio.Core +{ + // Dummy class + internal sealed class InvalidDLCPackage : DLCPackage + { + internal static IDLCPackage Instance { get; } = new InvalidDLCPackage(); + + private InvalidDLCPackage(string name, int identifier, IDLCPackageLocationInfo packageInfo, IDLCPackage parentPackage) + : base(name, identifier, packageInfo, parentPackage) + { + } + + private InvalidDLCPackage() + : this(nameof(InvalidDLCPackage), -1, null, null) + { + + } + + public override DLCPackageType GetDLCPackageType() => DLCPackageType.Invalid; + } +} diff --git a/PckStudio.Core/MapData.cs b/PckStudio.Core/MapData.cs new file mode 100644 index 00000000..61d92776 --- /dev/null +++ b/PckStudio.Core/MapData.cs @@ -0,0 +1,47 @@ +using System.Drawing; +using OMI.Formats.GameRule; + +namespace PckStudio.Core +{ + public enum MiniGameId : int + { + None, + Battle, + Tumble, + Glide + } + + public enum MapSize : int + { + Small, + Large, + Huge + } + + public class MapData + { + public string Name { get; } + public Image Thumbnail { get; } + public GameRuleFile Grf { get; } + public NamedData World { get; } + + public MapData(string name, Image thumbnail, MiniGameId miniGame, MapSize mapSize, NamedData world) + { + Name = name; + Thumbnail = thumbnail; + Grf = new GameRuleFile(); + Grf.AddRule("MapOptions", + new GameRuleFile.IntParameter("seed", 0), + new GameRuleFile.IntParameter("spawnX", 0), + new GameRuleFile.IntParameter("spawnY", 0), + new GameRuleFile.IntParameter("spawnZ", 0), + new GameRuleFile.BoolParameter("flatworld", false), + new GameRuleFile.IntParameter("mapSize", (int)mapSize), + new GameRuleFile.IntParameter("themeId", 0) + ); + Grf.AddRule("LevelRules", [new GameRuleFile.IntParameter("ruleType", (int)miniGame)]); + + World = world; + } + } +} diff --git a/PckStudio.Core/PckStudio.Core.csproj b/PckStudio.Core/PckStudio.Core.csproj index 19f40da6..366b2edb 100644 --- a/PckStudio.Core/PckStudio.Core.csproj +++ b/PckStudio.Core/PckStudio.Core.csproj @@ -1,7 +1,7 @@ - + Debug AnyCPU {345EABED-F0D1-4D04-B409-BABDEF747352} @@ -12,8 +12,8 @@ PckStudio.Core true v4.8 - 12 - 512 + 12 + 512 true true True @@ -59,11 +59,18 @@ + + + + + + + @@ -91,12 +98,15 @@ + + + @@ -120,10 +130,12 @@ + + @@ -151,10 +163,10 @@ 13.0.3 - - 1.9.2 - - + + 1.9.2 + + diff --git a/PckStudio.Core/ResourceLocation.cs b/PckStudio.Core/ResourceLocation.cs index d633b8a6..95dbd5d4 100644 --- a/PckStudio.Core/ResourceLocation.cs +++ b/PckStudio.Core/ResourceLocation.cs @@ -121,27 +121,7 @@ namespace PckStudio.Core ["misc/additionalmapicons.png"] = new ResourceLocation("misc/additionalmapicons.png", ResourceCategory.AdditionalMapIconsAtlas, 4, tilesInfo: Tiles.AdditionalMapIconTileInfos), }; - public static string GetPathFromCategory(ResourceCategory category) - { - return category switch - { - ResourceCategory.ItemAnimation => _categoryLookUp["textures/items"].ToString(), - ResourceCategory.BlockAnimation => _categoryLookUp["textures/blocks"].ToString(), - ResourceCategory.MobEntityTextures => _categoryLookUp["mob"].ToString(), - ResourceCategory.ItemEntityTextures => _categoryLookUp["item"].ToString(), - ResourceCategory.BlockAtlas => _categoryLookUp["terrain.png"].ToString(), - ResourceCategory.ItemAtlas => _categoryLookUp["items.png"].ToString(), - ResourceCategory.ParticleAtlas => _categoryLookUp["particles.png"].ToString(), - ResourceCategory.BannerAtlas => _categoryLookUp["item/banner/Banner_Atlas.png"].ToString(), - ResourceCategory.PaintingAtlas => _categoryLookUp["art/kz.png"].ToString(), - ResourceCategory.ExplosionAtlas => _categoryLookUp["misc/explosion.png"].ToString(), - ResourceCategory.ExperienceOrbAtlas => _categoryLookUp["item/xporb.png"].ToString(), - ResourceCategory.MoonPhaseAtlas => _categoryLookUp["terrain/moon_phases.png"].ToString(), - ResourceCategory.MapIconAtlas => _categoryLookUp["misc/mapicons.png"].ToString(), - ResourceCategory.AdditionalMapIconsAtlas => _categoryLookUp["misc/additionalmapicons.png"].ToString(), - _ => string.Empty - }; - } + public static string GetPathFromCategory(ResourceCategory category) => GetFromCategory(category).ToString(); public static ResourceCategory GetCategoryFromPath(string path) => GetFromPath(path).Category; @@ -204,5 +184,27 @@ namespace PckStudio.Core { return "res/" + Path; } + + internal static ResourceLocation GetFromCategory(ResourceCategory category) + { + return category switch + { + ResourceCategory.ItemAnimation => _categoryLookUp["textures/items"], + ResourceCategory.BlockAnimation => _categoryLookUp["textures/blocks"], + ResourceCategory.MobEntityTextures => _categoryLookUp["mob"], + ResourceCategory.ItemEntityTextures => _categoryLookUp["item"], + ResourceCategory.BlockAtlas => _categoryLookUp["terrain.png"], + ResourceCategory.ItemAtlas => _categoryLookUp["items.png"], + ResourceCategory.ParticleAtlas => _categoryLookUp["particles.png"], + ResourceCategory.BannerAtlas => _categoryLookUp["item/banner/Banner_Atlas.png"], + ResourceCategory.PaintingAtlas => _categoryLookUp["art/kz.png"], + ResourceCategory.ExplosionAtlas => _categoryLookUp["misc/explosion.png"], + ResourceCategory.ExperienceOrbAtlas => _categoryLookUp["item/xporb.png"], + ResourceCategory.MoonPhaseAtlas => _categoryLookUp["terrain/moon_phases.png"], + ResourceCategory.MapIconAtlas => _categoryLookUp["misc/mapicons.png"], + ResourceCategory.AdditionalMapIconsAtlas => _categoryLookUp["misc/additionalmapicons.png"], + _ => Unknown + }; + } } } diff --git a/Vendor/OMI-Lib b/Vendor/OMI-Lib index 384aad45..0c8f3717 160000 --- a/Vendor/OMI-Lib +++ b/Vendor/OMI-Lib @@ -1 +1 @@ -Subproject commit 384aad45b3b4979ba21d42c97463006d34c06ae9 +Subproject commit 0c8f37177fb25b72b9a7c30a377f89a58b123084