mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/PCK-Studio.git
synced 2026-05-30 17:56:39 +00:00
Core - Massive DLCManager changes
This commit is contained in:
@@ -114,11 +114,11 @@ namespace PckStudio.Core
|
||||
return new ReadOnlyCollection<Frame>(_frames);
|
||||
}
|
||||
|
||||
public IReadOnlyCollection<Frame> GetInterpolatedFrames()
|
||||
public IEnumerable<Frame> GetInterpolatedFrames()
|
||||
{
|
||||
if (Interpolate)
|
||||
{
|
||||
return new ReadOnlyCollection<Frame>(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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// See <see cref="AvailableLanguages"/> for details.
|
||||
/// </summary>
|
||||
@@ -48,6 +54,7 @@ namespace PckStudio.Core.DLC
|
||||
private readonly Random _rng = new Random();
|
||||
private ByteOrder _byteOrder;
|
||||
private ConsolePlatform _platform;
|
||||
private PckFileCompiler _pckFileCompiler;
|
||||
|
||||
|
||||
/// <param name="byteOrder"></param>
|
||||
@@ -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<string, IDictionary<string, byte[]>> mapData = GetMapData(pckFile, dataDirectoryInfo);
|
||||
PckAudioFile pckAudioFile = pckFile.GetAssetsByType(PckAssetType.AudioFile).FirstOrDefault()?.GetData(new PckAudioFileReader(ByteOrder));
|
||||
IDictionary<string, byte[]> 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<GameRuleFile> gameRules = pckFile.GetAssetsByType(PckAssetType.GameRulesFile)
|
||||
.Concat(pckFile.GetAssetsByType(PckAssetType.GameRulesHeader))
|
||||
.Select(asset => asset.GetData(reader));
|
||||
|
||||
Dictionary<string, SaveData> 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<string, IDictionary<string, byte[]>> GetMapData(PckFile pck, DirectoryInfo dataDirectory)
|
||||
{
|
||||
GameRuleFile.CompressionType compressionType = GetPlatformCompressionType();
|
||||
var reader = new GameRuleFileReader(compressionType);
|
||||
IEnumerable<string> values = pck.GetAssetsByType(PckAssetType.GameRulesFile)
|
||||
.Concat(pck.GetAssetsByType(PckAssetType.GameRulesHeader))
|
||||
.Select(asset => asset.GetData(reader))
|
||||
private Dictionary<string, SaveData> GetMapData(IEnumerable<GameRuleFile> gameRuleFiles, DirectoryInfo dataDirectory)
|
||||
{
|
||||
IEnumerable<string> 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<string, byte[]> 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<Animation> deserializer = AnimationDeserializer.DefaultDeserializer;
|
||||
|
||||
IDictionary<string, Animation> animations = dataPck.GetDirectoryContent(itemAnimationAssetPath, PckAssetType.TextureFile)
|
||||
IDictionary<string, Animation> 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<string, Animation> 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<string, Image> tryGetTexture = TryGet<string, Image>.FromDelegate((string path, out Image image) =>
|
||||
@@ -297,9 +321,10 @@ namespace PckStudio.Core.DLC
|
||||
image = asset?.GetTexture();
|
||||
return success;
|
||||
});
|
||||
|
||||
|
||||
ImageDeserializer defaultDeserializer = ImageDeserializer.DefaultDeserializer;
|
||||
IEnumerable<Image> 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<string, Image> 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<KeyValuePair<string, string>> materials = dataPck.GetAssetsByType(PckAssetType.MaterialFile).FirstOrDefault()?.GetData(new MaterialFileReader())
|
||||
.Select(mat => new KeyValuePair<string, string>(mat.Name, mat.Type)).ToList();
|
||||
IDictionary<string, Image> 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<string, string> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<string, byte[]> _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<string, byte[]> 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<string, byte[]>();
|
||||
_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<string, byte[]>();
|
||||
_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<byte[]>[] GetAudioFiles() => _audioData.Select(kv => new NamedData<byte[]>(kv.Key, kv.Value)).ToArray();
|
||||
}
|
||||
|
||||
47
PckStudio.Core/DLC/DLCPackageContent.cs
Normal file
47
PckStudio.Core/DLC/DLCPackageContent.cs
Normal file
@@ -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<PckFile> TexturePck { get; }
|
||||
public List<NamedData<byte[]>> Files { get; }
|
||||
|
||||
public DLCDataFolderContent(NamedData<PckFile> texturePck, NamedData<byte[]>[] files)
|
||||
{
|
||||
TexturePck = texturePck;
|
||||
Files = new List<NamedData<byte[]>>(files);
|
||||
}
|
||||
|
||||
public void AddFile(NamedData<byte[]> namedData) => Files.Add(namedData);
|
||||
public void AddFiles(NamedData<byte[]>[] namedData) => Files.AddRange(namedData);
|
||||
public void AddFile(string name, byte[] data) => AddFile(new NamedData<byte[]>(name, data));
|
||||
}
|
||||
|
||||
public DLCPackageContent(PckFile mainPck, NamedData<PckFile> texturePck, NamedData<byte[]>[] dataFiles)
|
||||
: this(mainPck, new(texturePck, dataFiles ?? Array.Empty<NamedData<byte[]>>()))
|
||||
{
|
||||
}
|
||||
|
||||
public DLCPackageContent(PckFile mainPck, DLCDataFolderContent dataFolderContent)
|
||||
{
|
||||
MainPck = mainPck;
|
||||
DataFolder = dataFolderContent;
|
||||
IsEmpty = mainPck is null;
|
||||
}
|
||||
|
||||
public DLCPackageContent(PckFile mainPck) : this(mainPck, default) { }
|
||||
}
|
||||
}
|
||||
8
PckStudio.Core/DLC/DLCPackageContentSerilasationType.cs
Normal file
8
PckStudio.Core/DLC/DLCPackageContentSerilasationType.cs
Normal file
@@ -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.
|
||||
}
|
||||
}
|
||||
@@ -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<int, Image> _capes;
|
||||
private readonly IDictionary<SkinIdentifier, Skin.Skin> _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);
|
||||
|
||||
|
||||
@@ -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<string, Color> _colors;
|
||||
private IDictionary<string, (Color surface, Color underwater, Color fog)> _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<string, string> _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<string, Animation> _itemAnimations;
|
||||
private IDictionary<string, Animation> _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<string, Color> colors,
|
||||
IDictionary<string, (Color surface, Color underwater, Color fog)> waterColors,
|
||||
ModelContainer customModels,
|
||||
MaterialContainer materials,
|
||||
AbstractModelContainer customModels,
|
||||
IDictionary<string, string> materials,
|
||||
Animation blockEntityBreakAnimation,
|
||||
IDictionary<string, Animation> itemAnimations,
|
||||
IDictionary<string, Animation> 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<string, Color>();
|
||||
_waterColors = waterColors ?? new Dictionary<string, (Color, Color, Color)>();
|
||||
_customModels = customModels;
|
||||
_materials = materials;
|
||||
_blockEntityBreakAnimation = blockEntityBreakAnimation;
|
||||
_itemAnimations = itemAnimations;
|
||||
_blockAnimations = blockAnimations;
|
||||
_itemAnimations = itemAnimations ?? new Dictionary<string, Animation>();
|
||||
_blockAnimations = blockAnimations ?? new Dictionary<string, Animation>();
|
||||
_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<string, Color> colors = null;
|
||||
IDictionary<string, (Color, Color, Color)> waterColors = null;
|
||||
|
||||
|
||||
Animation blockEntityBreakAnimation = new Animation(terrain.GetRange(0, 15, 10, ImageLayoutDirection.Horizontal).Select(t => t.Texture).ToArray(), true, 3);
|
||||
|
||||
ArmorSet[] armorSets = GetArmorSets();
|
||||
|
||||
IDictionary<string, Animation> itemAnimations = GetItemAnimations();
|
||||
|
||||
IDictionary<string, Animation> 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<string, string>(),
|
||||
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<string, Animation> GetItemAnimations()
|
||||
{
|
||||
return new Dictionary<string, Animation>()
|
||||
|
||||
139
PckStudio.Core/DLC/PckFileCompiler.cs
Normal file
139
PckStudio.Core/DLC/PckFileCompiler.cs
Normal file
@@ -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<int, Image> 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<PckFile>($"{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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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<Guid, NbtDocument> Players { get; }
|
||||
|
||||
|
||||
private IDictionary<string, byte[]> _worldArchive;
|
||||
|
||||
public SaveData(IDictionary<string, byte[]> 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<string, byte[]> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,9 +77,12 @@
|
||||
<Compile Include="DLC\DLCMashUpPackage.cs" />
|
||||
<Compile Include="DLC\DLCMiniGamePackage.cs" />
|
||||
<Compile Include="DLC\DLCPackage.cs" />
|
||||
<Compile Include="DLC\DLCPackageContent.cs" />
|
||||
<Compile Include="DLC\DLCPackageContentSerilasationType.cs" />
|
||||
<Compile Include="DLC\DLCPackageRegistry.cs" />
|
||||
<Compile Include="DLC\DLCSkinPackage.cs" />
|
||||
<Compile Include="DLC\DLCTexturePackage.cs" />
|
||||
<Compile Include="DLC\PckFileCompiler.cs" />
|
||||
<Compile Include="DLC\RawAssetDLCPackage.cs" />
|
||||
<Compile Include="Extensions\AnimationExtensions.cs" />
|
||||
<Compile Include="Extensions\BlendMode.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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user