diff --git a/PckStudio.Core/Animation.cs b/PckStudio.Core/Animation.cs
index ec297c8c..145ea5ef 100644
--- a/PckStudio.Core/Animation.cs
+++ b/PckStudio.Core/Animation.cs
@@ -114,11 +114,11 @@ namespace PckStudio.Core
return new ReadOnlyCollection(_frames);
}
- public IReadOnlyCollection GetInterpolatedFrames()
+ public IEnumerable GetInterpolatedFrames()
{
if (Interpolate)
{
- return new ReadOnlyCollection(InternalGetInterpolatedFrames().ToList());
+ return InternalGetInterpolatedFrames();
}
return GetFrames();
}
@@ -133,7 +133,7 @@ namespace PckStudio.Core
nextFrame = _frames[i + 1];
for (int tick = 0; tick < currentFrame.Ticks; tick++)
{
- double delta = 1.0f - tick / (double)currentFrame.Ticks;
+ float delta = 1.0f - tick / (float)currentFrame.Ticks;
yield return new Frame(currentFrame.Texture.Interpolate(nextFrame.Texture, delta));
}
}
diff --git a/PckStudio.Core/DLC/DLCManager.cs b/PckStudio.Core/DLC/DLCManager.cs
index e9ec2913..17df9f70 100644
--- a/PckStudio.Core/DLC/DLCManager.cs
+++ b/PckStudio.Core/DLC/DLCManager.cs
@@ -9,17 +9,21 @@ using OMI;
using OMI.Formats.Color;
using OMI.Formats.GameRule;
using OMI.Formats.Languages;
+using OMI.Formats.Model;
using OMI.Formats.Pck;
using OMI.Workers.Color;
using OMI.Workers.GameRule;
using OMI.Workers.Language;
using OMI.Workers.Material;
+using OMI.Workers.Model;
using OMI.Workers.Pck;
using PckStudio.Core.App;
using PckStudio.Core.Deserializer;
using PckStudio.Core.Extensions;
+using PckStudio.Core.FileFormats;
using PckStudio.Core.Interfaces;
using PckStudio.Core.IO.PckAudio;
+using PckStudio.Core.Model;
using PckStudio.Interfaces;
namespace PckStudio.Core.DLC
@@ -39,6 +43,8 @@ namespace PckStudio.Core.DLC
public ConsolePlatform Platform => _platform;
+ public DLCPackageContentSerilasationType ContentSerilasationType { get; set; } = DLCPackageContentSerilasationType.Local;
+
///
/// See for details.
///
@@ -48,6 +54,7 @@ namespace PckStudio.Core.DLC
private readonly Random _rng = new Random();
private ByteOrder _byteOrder;
private ConsolePlatform _platform;
+ private PckFileCompiler _pckFileCompiler;
///
@@ -57,6 +64,7 @@ namespace PckStudio.Core.DLC
{
_platform = platform;
_byteOrder = GetByteOrderForPlatform(Platform);
+ _pckFileCompiler = new PckFileCompiler(_byteOrder, GetPlatformCompressionType(), GameRuleFile.CompressionLevel.None);
SetPreferredLanguage(preferredLanguage);
}
@@ -90,7 +98,7 @@ namespace PckStudio.Core.DLC
localisation.AddLanguage(PreferredLanguage);
localisation.AddLocKey(PACKAGE_DISPLAYNAME_ID, name);
_packageRegistry.RegisterPackage(identifier, package, localisation);
-
+
return package;
}
@@ -138,9 +146,11 @@ namespace PckStudio.Core.DLC
{
_packageRegistry.RegisterPackage(identifier, package, localisation);
}
- return package;
+ return new RawAssetDLCPackage(fileInfo.Name, pckFile, ByteOrder);
}
+ public bool CloseDLCPackage(int identifier) => _packageRegistry.UnregisterPackage(identifier);
+
internal LOCFile GetLocalisation(int identifier)
{
return _packageRegistry.ContainsPackage(identifier) ? _packageRegistry.GetLocalisation(identifier) : default;
@@ -173,47 +183,61 @@ namespace PckStudio.Core.DLC
bool couldBeMiniGamePack = fileInfo.Name == DEFAULT_MINIGAME_PACK_FILENAME;
bool hasSkins = TryGetDLCSkinPackage(name, identifier, pckFile, fileReader, out IDLCPackage skinPackage);
- DLCPackageType dlcPackageType = hasSkins ? DLCPackageType.SkinPack : DLCPackageType.RawAssets;
DirectoryInfo dataDirectoryInfo = fileInfo.Directory.EnumerateDirectories().Where(dirInfo => dirInfo.Name == DATA_DIRECTORY_NAME).FirstOrDefault();
if (dataDirectoryInfo is null)
- return hasSkins ? skinPackage : InvalidDLCPackage.Instance;
+ {
+ Trace.TraceInformation("No data directory found.");
+ return skinPackage ?? new RawAssetDLCPackage(name, pckFile, ByteOrder);
+ }
bool hasTexturePack = TryGetTexturePack(name, description, identifier, dataDirectoryInfo, pckFile, fileReader, out IDLCPackage texturePackage);
- if (hasTexturePack)
+ if (!hasTexturePack)
{
- dlcPackageType = DLCPackageType.TexturePack;
- }
+ Trace.TraceWarning("Couldn't parse texturepack.");
+ return skinPackage ?? new RawAssetDLCPackage(name, pckFile, ByteOrder);
+ }
- Dictionary> mapData = GetMapData(pckFile, dataDirectoryInfo);
+ PckAudioFile pckAudioFile = pckFile.GetAssetsByType(PckAssetType.AudioFile).FirstOrDefault()?.GetData(new PckAudioFileReader(ByteOrder));
+ IDictionary audios = default;
+ if (pckAudioFile != null)
+ {
+ var songs = pckAudioFile.Categories.SelectMany(audioCategory => audioCategory.SongNames).ToList();
+ audios = dataDirectoryInfo.EnumerateFiles("*.binka")
+ .Where(audioFile => songs.Contains(Path.GetFileNameWithoutExtension(audioFile.Name)))
+ .ToDictionary(audioFile => audioFile.Name, audioFile => File.ReadAllBytes(audioFile.FullName));
+ }
+
+ GameRuleFile.CompressionType compressionType = GetPlatformCompressionType();
+ var reader = new GameRuleFileReader(compressionType);
+ IEnumerable gameRules = pckFile.GetAssetsByType(PckAssetType.GameRulesFile)
+ .Concat(pckFile.GetAssetsByType(PckAssetType.GameRulesHeader))
+ .Select(asset => asset.GetData(reader));
+
+ Dictionary mapData = GetMapData(gameRules, dataDirectoryInfo);
+ if (mapData.Count == 0)
+ return texturePackage ?? skinPackage ?? new RawAssetDLCPackage(name, pckFile, ByteOrder);
if (mapData.Count == 1)
- {
- dlcPackageType = DLCPackageType.MashUpPack;
- }
-
- Debug.WriteLine(dlcPackageType);
+ return new DLCMashUpPackage(name, description, identifier, null, null, pckAudioFile, audios, parentPackage: null, skinPackage: skinPackage, texturePackage: texturePackage);
+
return new RawAssetDLCPackage(name, pckFile, ByteOrder);
}
- private Dictionary> GetMapData(PckFile pck, DirectoryInfo dataDirectory)
- {
- GameRuleFile.CompressionType compressionType = GetPlatformCompressionType();
- var reader = new GameRuleFileReader(compressionType);
- IEnumerable values = pck.GetAssetsByType(PckAssetType.GameRulesFile)
- .Concat(pck.GetAssetsByType(PckAssetType.GameRulesHeader))
- .Select(asset => asset.GetData(reader))
+ private Dictionary GetMapData(IEnumerable gameRuleFiles, DirectoryInfo dataDirectory)
+ {
+ IEnumerable values = gameRuleFiles
.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));
return dataDirectory.EnumerateFiles("*.mcs")
.Where(file => values.Contains(file.Name))
- .ToDictionary(worldFile => worldFile.Name, worldFile => MapReader.OpenSave(worldFile.OpenRead()));
- }
+ .ToDictionary(worldFile => worldFile.Name, worldFile => MapReader.OpenSaveData(worldFile.OpenRead()));
+ }
private bool TryGetTexturePack(string name, string description, int identifier, DirectoryInfo dataDirectoryInfo, PckFile pckFile, PckFileReader pckFormatReader, out IDLCPackage texturePackage)
- {
+ {
if (dataDirectoryInfo is null)
{
texturePackage = default;
@@ -233,13 +257,13 @@ namespace PckStudio.Core.DLC
{
texturePackage = default;
return false;
- }
+ }
PckFile infoPck = texturePackInfo.GetData(pckFormatReader);
FileInfo texturePackFileInfo = dataDirectoryInfo.EnumerateFiles().Where(fileInfo => fileInfo.Name == dataPath).FirstOrDefault();
if (!IsValidPckFile(texturePackFileInfo))
- {
+ {
texturePackage = null;
return false;
}
@@ -248,11 +272,8 @@ namespace PckStudio.Core.DLC
PckFile texturePackPck = pckFormatReader.FromStream(texturePackFileStream);
texturePackage = GetTexturePackageFromPckFile(name, description, identifier, infoPck, texturePackPck, resolution);
- IDictionary audios = dataDirectoryInfo.EnumerateFiles("*.binka")
- .ToDictionary(audioFile => audioFile.Name, audioFile => File.ReadAllBytes(audioFile.FullName));
-
return texturePackage is not null;
- }
+ }
private IDLCPackage GetTexturePackageFromPckFile(string name, string description, int identifier, PckFile infoPck, PckFile dataPck, DLCTexturePackage.TextureResolution resolution)
{
@@ -260,35 +281,38 @@ namespace PckStudio.Core.DLC
return null;
if (!infoPck.TryGetAsset("comparison.png", PckAssetType.TextureFile, out PckAsset comparisonAsset))
- Trace.TraceError($"Could not find 'comparison.png'.");
+ Trace.TraceWarning($"Could not find 'comparison.png'.");
if (!infoPck.TryGetAsset("icon.png", PckAssetType.TextureFile, out PckAsset iconnAsset))
- Trace.TraceError($"Could not find 'icon.png'.");
+ Trace.TraceWarning($"Could not find 'icon.png'.");
- Image comparisonImg = comparisonAsset?.GetTexture();
- Image iconImg = iconnAsset?.GetTexture();
- DLCTexturePackage.MetaData metaData = new DLCTexturePackage.MetaData(comparisonImg, iconImg);
+ DLCTexturePackage.MetaData metaData = new DLCTexturePackage.MetaData(comparisonAsset?.GetTexture(), iconnAsset?.GetTexture());
- 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);
+ TryGetAtlasFromResourceCategory(dataPck, AtlasResource.AtlasType.BlockAtlas, out Atlas terrainAtlas);
+ TryGetAtlasFromResourceCategory(dataPck, AtlasResource.AtlasType.ItemAtlas, out Atlas itemAtlas);
+ TryGetAtlasFromResourceCategory(dataPck, AtlasResource.AtlasType.ParticleAtlas, out Atlas particleAtlas);
+ TryGetAtlasFromResourceCategory(dataPck, AtlasResource.AtlasType.PaintingAtlas, out Atlas paintingAtlas);
+ TryGetAtlasFromResourceCategory(dataPck, AtlasResource.AtlasType.MoonPhaseAtlas, out Atlas moonPhaseAtlas);
+ TryGetAtlasFromResourceCategory(dataPck, AtlasResource.AtlasType.MapIconAtlas, out Atlas mapIconsAtlas);
+ TryGetAtlasFromResourceCategory(dataPck, AtlasResource.AtlasType.AdditionalMapIconsAtlas, out Atlas additionalMapIconsAtlas);
string itemAnimationAssetPath = ResourceLocation.GetPathFromCategory(ResourceCategory.ItemAnimation);
+ string blockAnimationAssetPath = ResourceLocation.GetPathFromCategory(ResourceCategory.BlockAnimation);
IPckAssetDeserializer deserializer = AnimationDeserializer.DefaultDeserializer;
- IDictionary animations = dataPck.GetDirectoryContent(itemAnimationAssetPath, PckAssetType.TextureFile)
+ IDictionary itemAnimations = dataPck.GetDirectoryContent(itemAnimationAssetPath, PckAssetType.TextureFile)
+ .Where(asset => !asset.IsMipmappedFile())
.ToDictionary(asset => Path.GetFileNameWithoutExtension(asset.Filename), deserializer.Deserialize);
- bool hasCompassAnimation = animations.ContainsKey("compass");
- bool hasClockAnimation = animations.ContainsKey("clock");
+ IDictionary blockAnimations = dataPck.GetDirectoryContent(blockAnimationAssetPath, PckAssetType.TextureFile)
+ .Where(asset => !asset.IsMipmappedFile())
+ .ToDictionary(asset => Path.GetFileNameWithoutExtension(asset.Filename), deserializer.Deserialize);
- if (!hasCompassAnimation)
+ if (!itemAnimations.ContainsKey("compass"))
Trace.TraceError("No compass animation found!");
- if (!hasClockAnimation)
+ if (!itemAnimations.ContainsKey("clock"))
Trace.TraceError("No clock animation found!");
ITryGet tryGetTexture = TryGet.FromDelegate((string path, out Image image) =>
@@ -297,9 +321,10 @@ namespace PckStudio.Core.DLC
image = asset?.GetTexture();
return success;
});
-
+
+ ImageDeserializer defaultDeserializer = ImageDeserializer.DefaultDeserializer;
IEnumerable blockEntityBreakingFrames = dataPck.GetDirectoryContent("res/textures/", PckAssetType.TextureFile)
- .Select(ImageDeserializer.DefaultDeserializer.Deserialize);
+ .Select(defaultDeserializer.Deserialize);
Animation blockEntityBreakAnimation = new Animation(blockEntityBreakingFrames);
ColorContainer colorContainer = dataPck.GetAssetsByType(PckAssetType.ColourTableFile).FirstOrDefault()?.GetData(new COLFileReader()) ?? new ColorContainer();
@@ -314,17 +339,31 @@ namespace PckStudio.Core.DLC
.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);
+ .ToDictionary(a => Path.GetFileNameWithoutExtension(a.Filename), 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();
+ IDictionary terrainTextures = dataPck.GetDirectoryContent("res/terrain/", PckAssetType.TextureFile)
+ .ToDictionary(a => Path.GetFileNameWithoutExtension(a.Filename), defaultDeserializer.Deserialize);
+
+ terrainTextures.TryGetValue("sun", out Image sun);
+ terrainTextures.TryGetValue("moon", out Image moon);
+
+ AbstractModelContainer customModels = null;
+ if (dataPck.TryGetAsset("models.bin", PckAssetType.ModelsFile, out PckAsset modelsAsset))
+ {
+ ModelContainer models = modelsAsset.GetData(new ModelFileReader());
+ customModels = AbstractModelContainer.FromModelContainer(models, null);
+ }
+
+ IDictionary materials = dataPck.GetAssetsByType(PckAssetType.MaterialFile).FirstOrDefault()?.GetData(new MaterialFileReader())
+ .ToDictionary(mat => mat.Name, mat => mat.Type);
return new DLCTexturePackage(name, description, identifier, metaData, resolution,
- terrainAtlas, itemAtlas, particleAtlas, paintingAtlas, moonPhaseAtlas,
+ terrainAtlas, itemAtlas, particleAtlas, paintingAtlas, moonPhaseAtlas, mapIconsAtlas, additionalMapIconsAtlas,
ArmorSetDescription.Leather.GetArmorSet(tryGetTexture),
ArmorSetDescription.Chain.GetArmorSet(tryGetTexture),
ArmorSetDescription.Iron.GetArmorSet(tryGetTexture),
@@ -333,19 +372,20 @@ namespace PckStudio.Core.DLC
ArmorSetDescription.Turtle.GetArmorSet(tryGetTexture),
environmentData,
colors,
- waterColors: null,
- customModels: null,
+ waterColors,
+ customModels,
materials,
blockEntityBreakAnimation,
- itemAnimations: null,
- blockAnimations: null,
+ itemAnimations,
+ blockAnimations,
+ sun, moon,
parentPackage: null);
}
private bool TryGetAtlasFromResourceCategory(PckFile pck, AtlasResource.AtlasType atlasType, out Atlas atlas)
{
ResourceLocation resourceLocation = ResourceLocation.GetFromCategory(AtlasResource.GetId(atlasType));
- if (!pck.TryGetAsset(resourceLocation.ToString(), PckAssetType.TextureFile, out PckAsset asset))
+ if (!pck.TryGetAsset(resourceLocation.FullPath, PckAssetType.TextureFile, out PckAsset asset))
{
Trace.TraceWarning($"Could not find '{resourceLocation.FullPath}'.");
atlas = null;
@@ -468,6 +508,25 @@ namespace PckStudio.Core.DLC
_byteOrder = GetByteOrderForPlatform(platform);
}
- public bool CloseDLCPackage(int identifier) => _packageRegistry.UnregisterPackage(identifier);
+ public DLCPackageContent CompilePackage(IDLCPackage package)
+ {
+ LOCFile localisation = GetLocalisation(package.Identifier);
+ switch (package.GetDLCPackageType())
+ {
+ case DLCPackageType.Invalid:
+ break;
+ case DLCPackageType.RawAssets: return _pckFileCompiler.CompileRawAssets(package);
+ case DLCPackageType.SkinPack: return _pckFileCompiler.CompileSkinPackage(package, localisation);
+ case DLCPackageType.TexturePack: return _pckFileCompiler.CompileTexturePackage(package, localisation);
+ case DLCPackageType.MashUpPack: return _pckFileCompiler.CompileMashUpPackage(package, localisation);
+ case DLCPackageType.MG01:
+ break;
+ case DLCPackageType.MG02:
+ break;
+ case DLCPackageType.MG03:
+ break;
+ }
+ return DLCPackageContent.Empty;
+ }
}
}
\ No newline at end of file
diff --git a/PckStudio.Core/DLC/DLCMashUpPackage.cs b/PckStudio.Core/DLC/DLCMashUpPackage.cs
index 5f8f022a..134b1081 100644
--- a/PckStudio.Core/DLC/DLCMashUpPackage.cs
+++ b/PckStudio.Core/DLC/DLCMashUpPackage.cs
@@ -15,7 +15,7 @@ namespace PckStudio.Core.DLC
public sealed class DLCMashUpPackage : DLCPackage
{
public override string Description { get; }
- private AbstractGameRule _gameRule { get; }
+ private AbstractGameRule _gameRule;
public bool HasAudioData => _pckAudio is not null && _audioData.Count > 0;
private IDLCPackage _skinPackage;
@@ -24,30 +24,45 @@ namespace PckStudio.Core.DLC
private IDictionary _audioData;
private PckAudioFile _pckAudio;
- internal DLCMashUpPackage(string name, string description, int identifier, AbstractGameRule gameRule, IDLCPackage parentPackage, IDLCPackage skinPackage = null, IDLCPackage texturePackage = null)
+ internal DLCMashUpPackage(string name, string description, int identifier, AbstractGameRule gameRule, MapData mapData, PckAudioFile pckAudio, IDictionary audioData, IDLCPackage parentPackage, IDLCPackage skinPackage = null, IDLCPackage texturePackage = null)
: base(name, identifier, parentPackage)
{
Description = description;
_gameRule = gameRule;
_skinPackage = skinPackage;
_texturePackage = texturePackage;
+ _mapData = mapData;
+ _audioData = new Dictionary();
+ _pckAudio = pckAudio;
+ _audioData = audioData;
}
internal DLCMashUpPackage(string name, string description, int identifier)
- : this(name, description, identifier, new RootGameRule(), null)
+ : this(name, description, identifier, new RootGameRule(), null, new PckAudioFile(), null, null)
{
_skinPackage = DLCSkinPackage.CreateEmpty(this);
_texturePackage = DLCTexturePackage.CreateDefaultPackage(this);
- _audioData = new Dictionary();
- _pckAudio = new PckAudioFile();
}
+ public override DLCPackageType GetDLCPackageType() => DLCPackageType.MashUpPack;
+
public IDLCPackage GetSkinPackage() => _skinPackage;
public IDLCPackage GetTexturePackage() => _texturePackage;
- public AbstractGameRule GetGameRule() => _gameRule;
- public PckAudioFile GetAudioPack() => _pckAudio;
- public override DLCPackageType GetDLCPackageType() => DLCPackageType.MashUpPack;
+ public bool AddAudio(string name, byte[] audioData, PckAudioFile.Category category)
+ {
+ if (_audioData.ContainsKey(name) || !_pckAudio.HasCategory(category))
+ return false;
+ if (_pckAudio.TryGetCategory(category, out PckAudioFile.AudioCategory audioCategory))
+ {
+ audioCategory.SongNames.Add(name);
+ return true;
+ }
+ return false;
+ }
+
+ public AbstractGameRule GetGameRule() => _gameRule;
+ internal PckAudioFile GetAudioPack() => _pckAudio;
internal NamedData[] GetAudioFiles() => _audioData.Select(kv => new NamedData(kv.Key, kv.Value)).ToArray();
}
diff --git a/PckStudio.Core/DLC/DLCPackageContent.cs b/PckStudio.Core/DLC/DLCPackageContent.cs
new file mode 100644
index 00000000..a3b4965c
--- /dev/null
+++ b/PckStudio.Core/DLC/DLCPackageContent.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+using OMI.Formats.Pck;
+
+namespace PckStudio.Core.DLC
+{
+ public class DLCPackageContent
+ {
+ public static DLCPackageContent Empty => new DLCPackageContent(default);
+
+ internal bool IsEmpty { get; }
+
+ internal PckFile MainPck { get; }
+
+ internal DLCDataFolderContent DataFolder { get; }
+
+ public record DLCDataFolderContent
+ {
+ public NamedData TexturePck { get; }
+ public List> Files { get; }
+
+ public DLCDataFolderContent(NamedData texturePck, NamedData[] files)
+ {
+ TexturePck = texturePck;
+ Files = new List>(files);
+ }
+
+ public void AddFile(NamedData namedData) => Files.Add(namedData);
+ public void AddFiles(NamedData[] namedData) => Files.AddRange(namedData);
+ public void AddFile(string name, byte[] data) => AddFile(new NamedData(name, data));
+ }
+
+ public DLCPackageContent(PckFile mainPck, NamedData texturePck, NamedData[] dataFiles)
+ : this(mainPck, new(texturePck, dataFiles ?? Array.Empty>()))
+ {
+ }
+
+ public DLCPackageContent(PckFile mainPck, DLCDataFolderContent dataFolderContent)
+ {
+ MainPck = mainPck;
+ DataFolder = dataFolderContent;
+ IsEmpty = mainPck is null;
+ }
+
+ public DLCPackageContent(PckFile mainPck) : this(mainPck, default) { }
+ }
+}
\ No newline at end of file
diff --git a/PckStudio.Core/DLC/DLCPackageContentSerilasationType.cs b/PckStudio.Core/DLC/DLCPackageContentSerilasationType.cs
new file mode 100644
index 00000000..8e227afb
--- /dev/null
+++ b/PckStudio.Core/DLC/DLCPackageContentSerilasationType.cs
@@ -0,0 +1,8 @@
+namespace PckStudio.Core.DLC
+{
+ public enum DLCPackageContentSerilasationType : int
+ {
+ Local, //! create local folder with the value of: ('IDS_DISPLAY_NAME') and write all content into it.
+ Share //! zip file if texture or mashup pack, else just the pck file.
+ }
+}
\ No newline at end of file
diff --git a/PckStudio.Core/DLC/DLCSkinPackage.cs b/PckStudio.Core/DLC/DLCSkinPackage.cs
index 9adb9397..7e9a2c0f 100644
--- a/PckStudio.Core/DLC/DLCSkinPackage.cs
+++ b/PckStudio.Core/DLC/DLCSkinPackage.cs
@@ -11,13 +11,12 @@ namespace PckStudio.Core.DLC
public enum DLCSkinPackageOrder
{
ById,
- CapesFirst,
- SkinsFirst
+ ByName,
}
public sealed class DLCSkinPackage : DLCPackage
{
- public DLCSkinPackageOrder SkinPackageOrder { get; set; } = DLCSkinPackageOrder.CapesFirst;
+ public DLCSkinPackageOrder SkinPackageOrder { get; set; } = DLCSkinPackageOrder.ById;
private readonly IDictionary _capes;
private readonly IDictionary _skins;
@@ -38,6 +37,7 @@ namespace PckStudio.Core.DLC
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 TryGetCape(int capeId, out Image cape) => _capes.TryGetValue(capeId, out cape);
public bool ContainsSkin(SkinIdentifier skinIdentifier) => _skins.ContainsKey(skinIdentifier);
diff --git a/PckStudio.Core/DLC/DLCTexturePackage.cs b/PckStudio.Core/DLC/DLCTexturePackage.cs
index b77c8ae8..779de771 100644
--- a/PckStudio.Core/DLC/DLCTexturePackage.cs
+++ b/PckStudio.Core/DLC/DLCTexturePackage.cs
@@ -6,13 +6,9 @@ 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.Extensions;
using PckStudio.Core.Interfaces;
+using PckStudio.Core.Model;
using PckStudio.Core.Properties;
namespace PckStudio.Core.DLC
@@ -43,11 +39,11 @@ namespace PckStudio.Core.DLC
public Image IconImg { get; } = iconImg;
}
- public sealed class EnvironmentData
+ public sealed class EnvironmentData(Image clouds, Image rain, Image snow)
{
- public Image Clouds;
- public Image Rain;
- public Image Snow;
+ public Image Clouds = clouds;
+ public Image Rain = rain;
+ public Image Snow = snow;
}
public MetaData Info { get; }
@@ -56,20 +52,32 @@ namespace PckStudio.Core.DLC
//! => colours.col
private IDictionary _colors;
private IDictionary _waterColors;
- private ModelContainer _customModels; //! can be null.. => models.bin
- private MaterialContainer _materials; //! can be null..
+ private AbstractModelContainer _customModels; //! can be null.. => models.bin
+ private IDictionary _materials; //! can be null..
//! 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 ArmorSet[] _armorSets = new ArmorSet[6];
+ private Atlas _moonPhaseAtlas;
+ private ArmorSet _leatherArmorSet;
+ private ArmorSet _chainArmorSet;
+ private ArmorSet _ironArmorSet;
+ private ArmorSet _goldArmorSet;
+ private ArmorSet _diamondArmorSet;
+ private ArmorSet _turtleArmorSet;
+ private Atlas _mapIconsAtlas;
+ private Atlas _additionalMapIconsAtlas;
private EnvironmentData _environmentData;
private Animation _blockEntityBreakAnimation;
private IDictionary _itemAnimations;
private IDictionary _blockAnimations;
+ private Image _sun;
+ private Image _moon;
+
+ //! TODO: add resources from "res/misc/"
internal DLCTexturePackage(
string name,
@@ -81,14 +89,25 @@ namespace PckStudio.Core.DLC
Atlas itemsAtlas,
Atlas particlesAtlas,
Atlas paintingAtlas,
- ArmorSet[] armorSets,
+ Atlas moonPhaseAtlas,
+ Atlas mapIconsAtlas,
+ Atlas additionalMapIconsAtlas,
+ ArmorSet leatherArmorSet,
+ ArmorSet chainArmorSet,
+ ArmorSet ironArmorSet,
+ ArmorSet goldArmorSet,
+ ArmorSet diamondArmorSet,
+ ArmorSet turtleArmorSet,
+ EnvironmentData environmentData,
IDictionary colors,
IDictionary waterColors,
- ModelContainer customModels,
- MaterialContainer materials,
+ AbstractModelContainer customModels,
+ IDictionary materials,
Animation blockEntityBreakAnimation,
IDictionary itemAnimations,
IDictionary blockAnimations,
+ Image sun,
+ Image moon,
IDLCPackage parentPackage
)
: base(name, identifier, parentPackage)
@@ -100,14 +119,25 @@ namespace PckStudio.Core.DLC
_itemsAtlas = itemsAtlas;
_particlesAtlas = particlesAtlas;
_paintingAtlas = paintingAtlas;
- _armorSets = armorSets;
- _colors = colors;
- _waterColors = waterColors;
+ _moonPhaseAtlas = moonPhaseAtlas;
+ _mapIconsAtlas = mapIconsAtlas;
+ _additionalMapIconsAtlas = additionalMapIconsAtlas;
+ _leatherArmorSet = leatherArmorSet;
+ _chainArmorSet = chainArmorSet;
+ _ironArmorSet = ironArmorSet;
+ _goldArmorSet = goldArmorSet;
+ _diamondArmorSet = diamondArmorSet;
+ _turtleArmorSet = turtleArmorSet;
+ _environmentData = environmentData;
+ _colors = colors ?? new Dictionary();
+ _waterColors = waterColors ?? new Dictionary();
_customModels = customModels;
_materials = materials;
_blockEntityBreakAnimation = blockEntityBreakAnimation;
- _itemAnimations = itemAnimations;
- _blockAnimations = blockAnimations;
+ _itemAnimations = itemAnimations ?? new Dictionary();
+ _blockAnimations = blockAnimations ?? new Dictionary();
+ _sun = sun;
+ _moon = moon;
}
public TextureResolution GetResolution() => _resolution;
@@ -166,28 +196,36 @@ namespace PckStudio.Core.DLC
Atlas items = Atlas.FromResourceLocation(Resources.items_atlas, ResourceLocation.GetFromCategory(AtlasResource.GetId(AtlasResource.AtlasType.ItemAtlas)));
Atlas particles = Atlas.FromResourceLocation(Resources.particles_atlas, ResourceLocation.GetFromCategory(AtlasResource.GetId(AtlasResource.AtlasType.ParticleAtlas)));
Atlas painting = Atlas.FromResourceLocation(Resources.paintings_atlas, ResourceLocation.GetFromCategory(AtlasResource.GetId(AtlasResource.AtlasType.PaintingAtlas)));
+ Atlas moonPhases = Atlas.FromResourceLocation(Resources.moon_phases_atlas, ResourceLocation.GetFromCategory(AtlasResource.GetId(AtlasResource.AtlasType.MoonPhaseAtlas)));
+ Atlas mapIconsAtlas = Atlas.FromResourceLocation(Resources.map_icons_atlas, ResourceLocation.GetFromCategory(AtlasResource.GetId(AtlasResource.AtlasType.MapIconAtlas)));
+ Atlas additionalMapIconsAtlas = Atlas.FromResourceLocation(Resources.additional_map_icons_atlas, ResourceLocation.GetFromCategory(AtlasResource.GetId(AtlasResource.AtlasType.AdditionalMapIconsAtlas)));
//ColorContainer colors = new COLFileReader().FromStream(new MemoryStream());
IDictionary colors = null;
IDictionary waterColors = null;
-
+
Animation blockEntityBreakAnimation = new Animation(terrain.GetRange(0, 15, 10, ImageLayoutDirection.Horizontal).Select(t => t.Texture).ToArray(), true, 3);
-
- ArmorSet[] armorSets = GetArmorSets();
IDictionary itemAnimations = GetItemAnimations();
-
IDictionary blockAnimations = GetBlockAnimations();
return new DLCTexturePackage(
name, description, identifier, metadata, resolution,
- terrain, items, particles, painting,
- armorSets,
+ terrain, items, particles, painting, moonPhases, mapIconsAtlas, additionalMapIconsAtlas,
+ new ArmorSet(ArmorSetDescription.CLOTH, Resources.cloth, Resources.cloth_b),
+ new ArmorSet(ArmorSetDescription.CHAIN, Resources.chain, default),
+ new ArmorSet(ArmorSetDescription.IRON, Resources.iron, default),
+ new ArmorSet(ArmorSetDescription.GOLD, Resources.gold, default),
+ new ArmorSet(ArmorSetDescription.DIAMOND, Resources.diamond, default),
+ new ArmorSet(ArmorSetDescription.TURTLE, Resources.turtle, default),
+ new EnvironmentData(Resources.clouds, Resources.rain, Resources.snow),
colors, waterColors,
- new ModelContainer(),
- new MaterialContainer(),
+ new AbstractModelContainer(),
+ new Dictionary(),
blockEntityBreakAnimation,
itemAnimations,
blockAnimations,
+ sun: null,
+ moon: null,
parentPackage
);
}
@@ -200,19 +238,6 @@ namespace PckStudio.Core.DLC
internal Atlas GetPaintingAtlas() => _paintingAtlas;
- private static ArmorSet[] GetArmorSets()
- {
- return new ArmorSet[6]
- {
- new ArmorSet(ArmorSetDescription.CLOTH, Resources.cloth, Resources.cloth_b),
- new ArmorSet(ArmorSetDescription.CHAIN, Resources.chain, default),
- new ArmorSet(ArmorSetDescription.IRON, Resources.iron, default),
- new ArmorSet(ArmorSetDescription.GOLD, Resources.gold, default),
- new ArmorSet(ArmorSetDescription.DIAMOND, Resources.diamond, default),
- new ArmorSet(ArmorSetDescription.TURTLE, Resources.turtle, default)
- };
- }
-
private static IDictionary GetItemAnimations()
{
return new Dictionary()
diff --git a/PckStudio.Core/DLC/PckFileCompiler.cs b/PckStudio.Core/DLC/PckFileCompiler.cs
new file mode 100644
index 00000000..5e3ec54f
--- /dev/null
+++ b/PckStudio.Core/DLC/PckFileCompiler.cs
@@ -0,0 +1,139 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using OMI;
+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.Extensions;
+using PckStudio.Core.Interfaces;
+using PckStudio.Core.IO.PckAudio;
+
+namespace PckStudio.Core.DLC
+{
+ internal sealed class PckFileCompiler
+ {
+ private ByteOrder _byteOrder;
+ private GameRuleFile.CompressionType _compressionType;
+ private GameRuleFile.CompressionLevel _compressionLevel;
+
+ internal PckFileCompiler(ByteOrder byteOrder, GameRuleFile.CompressionType compressionType, GameRuleFile.CompressionLevel compressionLevel)
+ {
+ _byteOrder = byteOrder;
+ _compressionType = compressionType;
+ _compressionLevel = compressionLevel;
+ }
+
+ private PckFile CreateRootPckFile(int packId, int packVerison, LOCFile localisation)
+ {
+ PckFile mainPck = new PckFile();
+ PckAsset meta = mainPck.CreateNewAsset("0", PckAssetType.InfoFile);
+ meta.AddProperty("PACKID", packId);
+ meta.AddProperty("PACKVERSION", packVerison);
+ mainPck.CreateNewAsset("localisation.loc", PckAssetType.LocalisationFile, new LOCFileWriter(localisation, 2));
+ return mainPck;
+ }
+
+ internal DLCPackageContent CompileSkinPackage(IDLCPackage package, LOCFile localisation)
+ {
+ if (package is not DLCSkinPackage skinPackage)
+ return DLCPackageContent.Empty;
+
+ PckFile skinsPck = skinPackage.IsRootPackage ? CreateRootPckFile(package.Identifier, 0, localisation) : new PckFile();
+ foreach (KeyValuePair kv in skinPackage.GetCapes())
+ {
+ PckAsset capeAsset = skinsPck.CreateNewAsset($"dlccape{kv.Key:08}.png", PckAssetType.CapeFile);
+ capeAsset.SetTexture(kv.Value);
+ }
+ foreach (Skin.Skin skin in skinPackage.GetSkins())
+ {
+ skinsPck.AddSkin("", skin, localisation);
+ }
+
+ return new DLCPackageContent(skinsPck);
+ }
+
+ internal DLCPackageContent CompileTexturePackage(IDLCPackage package, LOCFile localisation)
+ {
+ if (package is not DLCTexturePackage texturePackage)
+ return DLCPackageContent.Empty;
+
+ PckFile texturePackInfoPck = new PckFile();
+ {
+ texturePackInfoPck.AddTexture("comparison.png", texturePackage.Info.ComparisonImg);
+ texturePackInfoPck.AddTexture("icon.png", texturePackage.Info.IconImg);
+ }
+
+ PckFile texturePck = new PckFile();
+ {
+ texturePck.AddTexture(ResourceLocations.GetPathFromCategory(AtlasResource.GetId(AtlasResource.AtlasType.ParticleAtlas)), texturePackage.GetParticleAtlas());
+ texturePck.AddTexture(ResourceLocations.GetPathFromCategory(AtlasResource.GetId(AtlasResource.AtlasType.ItemAtlas)), texturePackage.GetItemsAtlas());
+ texturePck.AddTexture(ResourceLocations.GetPathFromCategory(AtlasResource.GetId(AtlasResource.AtlasType.BlockAtlas)), texturePackage.GetTerrainAtlas());
+ texturePck.AddTexture(ResourceLocations.GetPathFromCategory(AtlasResource.GetId(AtlasResource.AtlasType.PaintingAtlas)), texturePackage.GetPaintingAtlas());
+ }
+
+ if (package.IsRootPackage)
+ {
+ PckFile mainPck = CreateRootPckFile(package.Identifier, 0, localisation);
+ DLCTexturePackage.TextureResolution res = texturePackage.GetResolution();
+ PckAsset textureInfoAsset = mainPck.CreateNewAsset($"{res}/{res}Info.pck", PckAssetType.TexturePackInfoFile, new PckFileWriter(texturePackInfoPck, _byteOrder));
+ textureInfoAsset.AddProperty("PACKID", "0");
+ textureInfoAsset.AddProperty("DATAPATH", $"{res}Data.pck");
+ return new DLCPackageContent(mainPck, new NamedData($"{res}Data.pck", texturePck), default);
+ }
+
+ return new DLCPackageContent(texturePackInfoPck);
+ }
+
+ internal DLCPackageContent CompileMashUpPackage(IDLCPackage package, LOCFile localisation)
+ {
+ if (package is not DLCMashUpPackage mashUpPackage)
+ return DLCPackageContent.Empty;
+
+ PckFile skinsPck = CompileSkinPackage(mashUpPackage.GetSkinPackage(), localisation).MainPck;
+
+ DLCTexturePackage texturePackage = mashUpPackage.GetTexturePackage() as DLCTexturePackage;
+ DLCPackageContent texturePackContent = CompileTexturePackage(texturePackage, localisation);
+ DLCTexturePackage.TextureResolution res = texturePackage.GetResolution();
+ PckFile texturePackInfoPck = texturePackContent.MainPck;
+ PckFile texturePck = texturePackContent.DataFolder.TexturePck.Value;
+
+ PckFile mainPck = CreateRootPckFile(package.Identifier, 0, localisation);
+ _ = mainPck.CreateNewAssetIf(skinsPck is PckFile && skinsPck.AssetCount > 0, "Skins.pck", PckAssetType.SkinDataFile, new PckFileWriter(skinsPck, _byteOrder));
+
+ if (texturePackInfoPck is PckFile && texturePackInfoPck.AssetCount > 0)
+ {
+ PckAsset textureInfoAsset = mainPck.CreateNewAsset($"{res}/{res}Info.pck", PckAssetType.TexturePackInfoFile, new PckFileWriter(texturePackInfoPck, _byteOrder));
+ textureInfoAsset.AddProperty("PACKID", "0");
+ textureInfoAsset.AddProperty("DATAPATH", texturePackContent.DataFolder.TexturePck.Name);
+ }
+
+
+ {
+ GameRuleFile grf = mashUpPackage.GetGameRule();
+ grf.Header.CompressionType = _compressionType;
+ grf.Header.CompressionLevel = _compressionLevel;
+ mainPck.CreateNewAsset("GameRule.grf", PckAssetType.GameRulesFile, new GameRuleFileWriter(grf));
+ }
+
+ if (mashUpPackage.HasAudioData)
+ {
+ mainPck.CreateNewAsset("audio.pck", PckAssetType.AudioFile, new PckAudioFileWriter(mashUpPackage.GetAudioPack(), _byteOrder));
+ texturePackContent.DataFolder.AddFiles(mashUpPackage.GetAudioFiles());
+ }
+
+ return new DLCPackageContent(mainPck, texturePackContent.DataFolder);
+ }
+
+ internal DLCPackageContent CompileRawAssets(IDLCPackage package)
+ {
+ return package is RawAssetDLCPackage rawAssetDLCPackage ? new DLCPackageContent(rawAssetDLCPackage.PckFile) : DLCPackageContent.Empty;
+ }
+ }
+}
diff --git a/PckStudio.Core/Extensions/AnimationExtensions.cs b/PckStudio.Core/Extensions/AnimationExtensions.cs
index 4229ba26..5d99c839 100644
--- a/PckStudio.Core/Extensions/AnimationExtensions.cs
+++ b/PckStudio.Core/Extensions/AnimationExtensions.cs
@@ -1,4 +1,7 @@
-using System.Drawing;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Threading.Tasks;
using AnimatedGif;
namespace PckStudio.Core.Extensions
@@ -23,5 +26,26 @@ namespace PckStudio.Core.Extensions
ms.Position = 0;
return Image.FromStream(ms);
}
+
+ public static Animation Combine(this Animation first, Animation second, ImageLayoutDirection layoutDirection)
+ {
+ if (first == null)
+ return second;
+ if (second == null)
+ return first;
+ if (first.TextureCount != second.TextureCount)
+ return first;
+ if (first.FrameCount != second.FrameCount)
+ return first;
+
+ Image[] secondTextures = second.GetTextures().ToArray();
+
+ Animation animation = new Animation(first.GetTextures().enumerate().Select(ift => ift.value.Combine(secondTextures[ift.index], layoutDirection)));
+ foreach ((int texId, int frameTime) item in first.GetFrames().Select(f => (texId: first.GetTextureIndex(f.Texture), frameTime: f.Ticks)))
+ {
+ animation.AddFrame(item.texId, item.frameTime);
+ }
+ return animation;
+ }
}
}
diff --git a/PckStudio.Core/Extensions/ColorExtensions.cs b/PckStudio.Core/Extensions/ColorExtensions.cs
index 4a64fa9e..0cb29dce 100644
--- a/PckStudio.Core/Extensions/ColorExtensions.cs
+++ b/PckStudio.Core/Extensions/ColorExtensions.cs
@@ -54,15 +54,15 @@ namespace PckStudio.Core.Extensions
return MathExtensions.Clamp(resultValue, 0.0f, 1.0f);
}
- public static byte Mix(double ratio, byte val1, byte val2)
+ public static byte Mix(float ratio, byte val1, byte val2)
{
- ratio = MathExtensions.Clamp(ratio, 0.0, 1.0);
+ ratio = MathExtensions.Clamp(ratio, 0.0f, 1.0f);
return (byte)(ratio * val1 + (1.0 - ratio) * val2);
}
- public static Color Mix(this Color c1, Color c2, double ratio)
+ public static Color Mix(this Color c1, Color c2, float ratio)
{
- ratio = MathExtensions.Clamp(ratio, 0.0, 1.0);
+ ratio = MathExtensions.Clamp(ratio, 0.0f, 1.0f);
return Color.FromArgb(c1.A,
Mix(ratio, c1.R, c2.R),
Mix(ratio, c1.G, c2.G),
diff --git a/PckStudio.Core/Extensions/ImageExtensions.cs b/PckStudio.Core/Extensions/ImageExtensions.cs
index 6f9549f4..660e5727 100644
--- a/PckStudio.Core/Extensions/ImageExtensions.cs
+++ b/PckStudio.Core/Extensions/ImageExtensions.cs
@@ -273,9 +273,9 @@ namespace PckStudio.Core.Extensions
return bitmapResult;
}
- public static Image Interpolate(this Image source, Image target, double delta)
+ public static Image Interpolate(this Image source, Image target, float delta)
{
- delta = MathExtensions.Clamp(delta, 0.0, 1.0);
+ delta = MathExtensions.Clamp(delta, 0.0f, 1.0f);
if (source is not Bitmap baseImage || target is not Bitmap overlayImage ||
source.Width != target.Width || source.Height != target.Height)
return source;
diff --git a/PckStudio.Core/MapData.cs b/PckStudio.Core/MapData.cs
index 655c0a0c..674b4927 100644
--- a/PckStudio.Core/MapData.cs
+++ b/PckStudio.Core/MapData.cs
@@ -39,8 +39,8 @@ namespace PckStudio.Core
Thumbnail = thumbnail;
World = world;
- var levelData = MapReader.OpenSave(new MemoryStream(world.Value))["level.dat"];
- TagCompound? levelDat = NbtDocument.LoadDocument(new MemoryStream(levelData))!.DocumentRoot?["Data"] as TagCompound;
+ SaveData saveData = MapReader.OpenSaveData(new MemoryStream(world.Value));
+ TagCompound? levelDat = saveData.LevelData.DocumentRoot?["Data"] as TagCompound;
_ = levelDat ?? throw new NullReferenceException(nameof(levelDat));
Vector3 spawn = levelDat.GetVector3("Spawn");
diff --git a/PckStudio.Core/MapReader.cs b/PckStudio.Core/MapReader.cs
index 6f2d8411..fd5ef342 100644
--- a/PckStudio.Core/MapReader.cs
+++ b/PckStudio.Core/MapReader.cs
@@ -1,13 +1,42 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using System.IO;
+using System.Linq;
+using Cyotek.Data.Nbt;
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
using OMI;
+using PckStudio.Core.Extensions;
namespace PckStudio.Core
{
+ public class SaveData
+ {
+ public NbtDocument LevelData { get; }
+ public IDictionary Players { get; }
+
+
+ private IDictionary _worldArchive;
+
+ public SaveData(IDictionary worldArchive)
+ {
+ _worldArchive = worldArchive;
+ if (_worldArchive.TryGetValue("levels.dat", out byte[] levelData))
+ {
+ Stream stream = new MemoryStream(levelData);
+ LevelData = NbtDocument.LoadDocument(stream);
+ }
+ Players = _worldArchive
+ .Where(kv => kv.Key.StartsWith("players/"))
+ .ToDictionary(
+ kv => Guid.Parse(Path.GetFileNameWithoutExtension(kv.Key)),
+ kv => NbtDocument.LoadDocument(new MemoryStream(kv.Value)));
+ }
+ }
+
+
public class MapReader
{
- public static IDictionary OpenSave(Stream stream)
+ public static SaveData OpenSaveData(Stream stream)
{
EndiannessAwareBinaryReader reader = new EndiannessAwareBinaryReader(stream, ByteOrder.BigEndian);
_ = reader.ReadInt32();
@@ -35,7 +64,7 @@ namespace PckStudio.Core
res.Add(path, data);
}
- return res;
+ return new SaveData(res);
}
}
}
diff --git a/PckStudio.Core/PckStudio.Core.csproj b/PckStudio.Core/PckStudio.Core.csproj
index 6e09711c..928b5e1d 100644
--- a/PckStudio.Core/PckStudio.Core.csproj
+++ b/PckStudio.Core/PckStudio.Core.csproj
@@ -77,9 +77,12 @@
+
+
+
diff --git a/PckStudio.Core/Skin/SkinIdentifier.cs b/PckStudio.Core/Skin/SkinIdentifier.cs
index cec8e9aa..b7fba1ee 100644
--- a/PckStudio.Core/Skin/SkinIdentifier.cs
+++ b/PckStudio.Core/Skin/SkinIdentifier.cs
@@ -5,19 +5,19 @@ namespace PckStudio.Core.Skin
{
public sealed class SkinIdentifier : IFormattable
{
- public int Id { get; }
+ private readonly int _id;
public SkinIdentifier(int id)
{
- Id = id;
+ _id = id;
}
- public static implicit operator int(SkinIdentifier _this) => _this.Id;
+ public static implicit operator int(SkinIdentifier @this) => @this._id;
- public string ToString(string format, IFormatProvider formatProvider) => Id.ToString(format, formatProvider);
+ public string ToString(string format, IFormatProvider formatProvider) => _id.ToString(format, formatProvider);
- public string ToString(string format) => Id.ToString(format, NumberFormatInfo.CurrentInfo);
+ public string ToString(string format) => _id.ToString(format, NumberFormatInfo.CurrentInfo);
- public override string ToString() => Id.ToString(NumberFormatInfo.CurrentInfo);
+ public override string ToString() => _id.ToString(NumberFormatInfo.CurrentInfo);
}
}