From 7d999cf3dac51163d57f645bf694a44653d25f4f Mon Sep 17 00:00:00 2001 From: Kenny van Vulpen Date: Wed, 13 Oct 2021 18:30:28 +0200 Subject: [PATCH] Move resourcepack stuff around --- .../Abstraction/IColor.cs | 10 ++ .../Bedrock/MCPackModule.cs | 26 ++++ .../Bedrock/ResourceModule.cs | 19 +++ .../{MCSkinPack.cs => Bedrock/SkinModule.cs} | 61 +-------- .../Exceptions/UnknownModuleException.cs | 12 ++ .../Components/AppearanceComponent.cs | 60 --------- .../Bedrock/Particles/Components/Flipbook.cs | 27 ++++ .../Particles/Components/ParticleUV.cs | 45 +++++++ .../Particles/ParticleColorConverter.cs | 2 +- .../Json/Models/Entities/EntityModel.cs | 5 +- .../Json/Sound/SoundDefinition.cs | 117 +----------------- .../Json/Sound/SoundElement.cs | 11 ++ .../Json/Sound/SoundElementConverter.cs | 43 +++++++ .../Json/Sound/SoundMetadata.cs | 28 +++++ .../Json/Sound/SoundType.cs | 7 ++ .../Json/Sound/TypeEnumConverter.cs | 39 ++++++ .../Json/Textures/Converter.cs | 20 +++ .../Json/Textures/FrameElement.cs | 11 ++ .../Json/Textures/FrameElementConverter.cs | 42 +++++++ .../Json/Textures/TextureAnimation.cs | 21 ++++ .../Json/Textures/TextureData.cs | 13 ++ .../Json/Textures/TextureFrame.cs | 13 ++ .../Json/Textures/TextureMeta.cs | 103 +-------------- src/Alex.ResourcePackLib/MCPack.cs | 12 +- .../Gamestates/MainMenu/Profile/SkinEntry.cs | 1 + .../Gamestates/MainMenu/SkinSelectionState.cs | 3 +- src/Alex/Net/Bedrock/BedrockClient.cs | 14 +++ src/Alex/ResourceManager.cs | 10 +- 28 files changed, 432 insertions(+), 343 deletions(-) create mode 100644 src/Alex.ResourcePackLib/Abstraction/IColor.cs create mode 100644 src/Alex.ResourcePackLib/Bedrock/MCPackModule.cs create mode 100644 src/Alex.ResourcePackLib/Bedrock/ResourceModule.cs rename src/Alex.ResourcePackLib/{MCSkinPack.cs => Bedrock/SkinModule.cs} (70%) create mode 100644 src/Alex.ResourcePackLib/Exceptions/UnknownModuleException.cs create mode 100644 src/Alex.ResourcePackLib/Json/Bedrock/Particles/Components/Flipbook.cs create mode 100644 src/Alex.ResourcePackLib/Json/Bedrock/Particles/Components/ParticleUV.cs create mode 100644 src/Alex.ResourcePackLib/Json/Sound/SoundElement.cs create mode 100644 src/Alex.ResourcePackLib/Json/Sound/SoundElementConverter.cs create mode 100644 src/Alex.ResourcePackLib/Json/Sound/SoundMetadata.cs create mode 100644 src/Alex.ResourcePackLib/Json/Sound/SoundType.cs create mode 100644 src/Alex.ResourcePackLib/Json/Sound/TypeEnumConverter.cs create mode 100644 src/Alex.ResourcePackLib/Json/Textures/Converter.cs create mode 100644 src/Alex.ResourcePackLib/Json/Textures/FrameElement.cs create mode 100644 src/Alex.ResourcePackLib/Json/Textures/FrameElementConverter.cs create mode 100644 src/Alex.ResourcePackLib/Json/Textures/TextureAnimation.cs create mode 100644 src/Alex.ResourcePackLib/Json/Textures/TextureData.cs create mode 100644 src/Alex.ResourcePackLib/Json/Textures/TextureFrame.cs diff --git a/src/Alex.ResourcePackLib/Abstraction/IColor.cs b/src/Alex.ResourcePackLib/Abstraction/IColor.cs new file mode 100644 index 000000000..46130b2cc --- /dev/null +++ b/src/Alex.ResourcePackLib/Abstraction/IColor.cs @@ -0,0 +1,10 @@ +namespace Alex.ResourcePackLib.Abstraction +{ + public interface IColor + { + byte R { get; set; } + byte G { get; set; } + byte B { get; set; } + uint PackedValue { get; set; } + } +} \ No newline at end of file diff --git a/src/Alex.ResourcePackLib/Bedrock/MCPackModule.cs b/src/Alex.ResourcePackLib/Bedrock/MCPackModule.cs new file mode 100644 index 000000000..a1d8a9bdf --- /dev/null +++ b/src/Alex.ResourcePackLib/Bedrock/MCPackModule.cs @@ -0,0 +1,26 @@ +using Alex.ResourcePackLib.IO.Abstract; + +namespace Alex.ResourcePackLib.Bedrock +{ + public class MCPackModule + { + public virtual string Name + { + get + { + return Entry.Name; + } + } + + protected IFilesystem Entry { get; } + protected MCPackModule(IFilesystem entry) + { + Entry = entry; + } + + internal virtual bool Load() + { + return false; + } + } +} \ No newline at end of file diff --git a/src/Alex.ResourcePackLib/Bedrock/ResourceModule.cs b/src/Alex.ResourcePackLib/Bedrock/ResourceModule.cs new file mode 100644 index 000000000..e3b4ff72e --- /dev/null +++ b/src/Alex.ResourcePackLib/Bedrock/ResourceModule.cs @@ -0,0 +1,19 @@ +using Alex.ResourcePackLib.IO.Abstract; + +namespace Alex.ResourcePackLib.Bedrock +{ + public class ResourceModule : MCPackModule + { + /// + public ResourceModule(IFilesystem entry) : base(entry) + { + + } + + /// + internal override bool Load() + { + return base.Load(); + } + } +} \ No newline at end of file diff --git a/src/Alex.ResourcePackLib/MCSkinPack.cs b/src/Alex.ResourcePackLib/Bedrock/SkinModule.cs similarity index 70% rename from src/Alex.ResourcePackLib/MCSkinPack.cs rename to src/Alex.ResourcePackLib/Bedrock/SkinModule.cs index 92fd6afff..19c1bd1d1 100644 --- a/src/Alex.ResourcePackLib/MCSkinPack.cs +++ b/src/Alex.ResourcePackLib/Bedrock/SkinModule.cs @@ -1,47 +1,22 @@ using System; using System.Collections.Generic; using System.IO; -using System.IO.Compression; using Alex.Common.Resources; using Alex.Common.Utils; using Alex.ResourcePackLib.Abstraction; -using Alex.ResourcePackLib.IO; using Alex.ResourcePackLib.IO.Abstract; using Alex.ResourcePackLib.Json; using Alex.ResourcePackLib.Json.Bedrock; using Alex.ResourcePackLib.Json.Models.Entities; using Alex.ResourcePackLib.Json.Textures; using NLog; -using NLog.Fluent; using SixLabors.ImageSharp; using SixLabors.ImageSharp.Formats.Png; using SixLabors.ImageSharp.PixelFormats; -namespace Alex.ResourcePackLib +namespace Alex.ResourcePackLib.Bedrock { - public class MCPackModule - { - public virtual string Name - { - get - { - return Entry.Name; - } - } - - protected IFilesystem Entry { get; } - protected MCPackModule(IFilesystem entry) - { - Entry = entry; - } - - internal virtual bool Load() - { - return false; - } - } - - public class MCSkinPack : MCPackModule, ITextureProvider + public class SkinModule : MCPackModule, ITextureProvider { private static readonly ILogger Log = LogManager.GetCurrentClassLogger(); @@ -65,7 +40,7 @@ public override string Name { public IReadOnlyDictionary EntityModels { get; private set; } /// - internal MCSkinPack(IFilesystem entry) : base(entry) + internal SkinModule(IFilesystem entry) : base(entry) { } @@ -75,8 +50,6 @@ internal override bool Load() { try { - List skins = new List(); - var archive = Entry; //using (var archive = new ZipFileSystem(Entry.Open(), Entry.Name)) { @@ -91,34 +64,6 @@ internal override bool Load() if (geometryEntry != null) { ProcessGeometryJson(geometryEntry); - /*Dictionary models = - MCJsonConvert.DeserializeObject>( - geometryEntry.ReadAsString()); - - foreach (var skin in Info.Skins) - { - EntityModel model; - - if (!models.TryGetValue(skin.Geometry, out model)) - continue; - - var textureEntry = archive.GetEntry(skin.Texture); - - if (textureEntry == null) - continue; - - Image img; - - using (var s = textureEntry.Open()) - { - //img = new Bitmap(s); - img = Image.Load(s.ReadToSpan(textureEntry.Length), PngDecoder); - } - - LoadedSkin loaded = new LoadedSkin(skin.LocalizationName, model, img); - skins.Add(loaded); - //skin. - }*/ } else { diff --git a/src/Alex.ResourcePackLib/Exceptions/UnknownModuleException.cs b/src/Alex.ResourcePackLib/Exceptions/UnknownModuleException.cs new file mode 100644 index 000000000..a357a6994 --- /dev/null +++ b/src/Alex.ResourcePackLib/Exceptions/UnknownModuleException.cs @@ -0,0 +1,12 @@ +using System; + +namespace Alex.ResourcePackLib.Exceptions +{ + public class UnknownModuleException : Exception + { + public UnknownModuleException(string message) : base(message) + { + + } + } +} \ No newline at end of file diff --git a/src/Alex.ResourcePackLib/Json/Bedrock/Particles/Components/AppearanceComponent.cs b/src/Alex.ResourcePackLib/Json/Bedrock/Particles/Components/AppearanceComponent.cs index 2ef1cb621..346abb9a4 100644 --- a/src/Alex.ResourcePackLib/Json/Bedrock/Particles/Components/AppearanceComponent.cs +++ b/src/Alex.ResourcePackLib/Json/Bedrock/Particles/Components/AppearanceComponent.cs @@ -1,8 +1,6 @@ -using Alex.MoLang.Parser; using Alex.MoLang.Runtime; using Alex.ResourcePackLib.Json.Bedrock.Entity; using Alex.ResourcePackLib.Json.Bedrock.MoLang; -using Microsoft.Xna.Framework; using Newtonsoft.Json; namespace Alex.ResourcePackLib.Json.Bedrock.Particles.Components @@ -59,62 +57,4 @@ public override void Update(IParticle particle, MoLangRuntime runtime) } } } - - public class ParticleUV - { - [JsonProperty("texture_width")] - public float TextureWidth { get; set; } - - [JsonProperty("texture_height")] - public float TextureHeight { get; set; } - - [JsonProperty("uv")] - public MoLangVector2Expression Uv { get; set; } = null; - - [JsonProperty("uv_size")] - public MoLangVector2Expression Size { get; set; } = null; - - [JsonProperty("flipbook")] - public Flipbook Flipbook { get; set; } - - public Vector2 GetUv(MoLangRuntime runtime) - { - if (Flipbook?.Base != null) - { - return Flipbook.Base.Evaluate(runtime, Vector2.Zero); - } - - return Uv?.Evaluate(runtime, Vector2.Zero) ?? Vector2.Zero; - } - - public Vector2 GetSize(MoLangRuntime runtime) - { - if (Flipbook?.Size != null) - { - return Flipbook.Size.Value; - } - - return (Size?.Evaluate(runtime, Vector2.One) ?? (Vector2.One)); - } - } - - public class Flipbook - { - [JsonProperty("base_UV")] - public MoLangVector2Expression Base { get; set; } - - [JsonProperty("size_UV")] - public Vector2? Size { get; set; } = null; - - [JsonProperty("step_UV")] - public Vector2 Step { get; set; } = Vector2.Zero; - - [JsonProperty("frames_per_second")] public float? FPS { get; set; } = 8; - - [JsonProperty("max_frame")] public IExpression[] MaxFrame { get; set; } - - [JsonProperty("stretch_to_lifetime")] public bool StretchToLifetime { get; set; } - - [JsonProperty("loop")] public bool Loop { get; set; } = true; - } } \ No newline at end of file diff --git a/src/Alex.ResourcePackLib/Json/Bedrock/Particles/Components/Flipbook.cs b/src/Alex.ResourcePackLib/Json/Bedrock/Particles/Components/Flipbook.cs new file mode 100644 index 000000000..e2bc89321 --- /dev/null +++ b/src/Alex.ResourcePackLib/Json/Bedrock/Particles/Components/Flipbook.cs @@ -0,0 +1,27 @@ +using Alex.MoLang.Parser; +using Alex.ResourcePackLib.Json.Bedrock.MoLang; +using Microsoft.Xna.Framework; +using Newtonsoft.Json; + +namespace Alex.ResourcePackLib.Json.Bedrock.Particles.Components +{ + public class Flipbook + { + [JsonProperty("base_UV")] + public MoLangVector2Expression Base { get; set; } + + [JsonProperty("size_UV")] + public Vector2? Size { get; set; } = null; + + [JsonProperty("step_UV")] + public Vector2 Step { get; set; } = Vector2.Zero; + + [JsonProperty("frames_per_second")] public float? FPS { get; set; } = 8; + + [JsonProperty("max_frame")] public IExpression[] MaxFrame { get; set; } + + [JsonProperty("stretch_to_lifetime")] public bool StretchToLifetime { get; set; } + + [JsonProperty("loop")] public bool Loop { get; set; } = true; + } +} \ No newline at end of file diff --git a/src/Alex.ResourcePackLib/Json/Bedrock/Particles/Components/ParticleUV.cs b/src/Alex.ResourcePackLib/Json/Bedrock/Particles/Components/ParticleUV.cs new file mode 100644 index 000000000..a7511526b --- /dev/null +++ b/src/Alex.ResourcePackLib/Json/Bedrock/Particles/Components/ParticleUV.cs @@ -0,0 +1,45 @@ +using Alex.MoLang.Runtime; +using Alex.ResourcePackLib.Json.Bedrock.MoLang; +using Microsoft.Xna.Framework; +using Newtonsoft.Json; + +namespace Alex.ResourcePackLib.Json.Bedrock.Particles.Components +{ + public class ParticleUV + { + [JsonProperty("texture_width")] + public float TextureWidth { get; set; } + + [JsonProperty("texture_height")] + public float TextureHeight { get; set; } + + [JsonProperty("uv")] + public MoLangVector2Expression Uv { get; set; } = null; + + [JsonProperty("uv_size")] + public MoLangVector2Expression Size { get; set; } = null; + + [JsonProperty("flipbook")] + public Flipbook Flipbook { get; set; } + + public Vector2 GetUv(MoLangRuntime runtime) + { + if (Flipbook?.Base != null) + { + return Flipbook.Base.Evaluate(runtime, Vector2.Zero); + } + + return Uv?.Evaluate(runtime, Vector2.Zero) ?? Vector2.Zero; + } + + public Vector2 GetSize(MoLangRuntime runtime) + { + if (Flipbook?.Size != null) + { + return Flipbook.Size.Value; + } + + return (Size?.Evaluate(runtime, Vector2.One) ?? (Vector2.One)); + } + } +} \ No newline at end of file diff --git a/src/Alex.ResourcePackLib/Json/Converters/Particles/ParticleColorConverter.cs b/src/Alex.ResourcePackLib/Json/Converters/Particles/ParticleColorConverter.cs index a0777efc5..02ddd41a0 100644 --- a/src/Alex.ResourcePackLib/Json/Converters/Particles/ParticleColorConverter.cs +++ b/src/Alex.ResourcePackLib/Json/Converters/Particles/ParticleColorConverter.cs @@ -39,7 +39,7 @@ public Color GetValue(MoLangRuntime runtime) if (_expression != null) return new Color(_expression.Evaluate(runtime, new Vector4(1, 1, 1, 1f))); - + if (_gradientColors != null) return _gradientColors.GetValue(runtime); diff --git a/src/Alex.ResourcePackLib/Json/Models/Entities/EntityModel.cs b/src/Alex.ResourcePackLib/Json/Models/Entities/EntityModel.cs index c622732c9..413dafe75 100644 --- a/src/Alex.ResourcePackLib/Json/Models/Entities/EntityModel.cs +++ b/src/Alex.ResourcePackLib/Json/Models/Entities/EntityModel.cs @@ -44,7 +44,10 @@ public class EntityModel { foreach (var bone in baseEntity.Bones) { - bones.Add(bone.Name, bone.Clone()); + if (!bones.TryAdd(bone.Name, bone.Clone())) + { + Log.Warn($"Duplicate bone: {bone.Name}"); + } } } diff --git a/src/Alex.ResourcePackLib/Json/Sound/SoundDefinition.cs b/src/Alex.ResourcePackLib/Json/Sound/SoundDefinition.cs index aeccb0484..4ef407601 100644 --- a/src/Alex.ResourcePackLib/Json/Sound/SoundDefinition.cs +++ b/src/Alex.ResourcePackLib/Json/Sound/SoundDefinition.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Globalization; using Newtonsoft.Json; @@ -14,47 +13,7 @@ public partial class SoundDefinition [JsonProperty("subtitle", NullValueHandling = NullValueHandling.Ignore)] public string Subtitle { get; set; } - public static Dictionary FromJson(string json) => JsonConvert.DeserializeObject>(json, Converter.Settings); - } - - public partial class SoundClass - { - [JsonProperty("name")] - public string Name { get; set; } - - [JsonProperty("stream", NullValueHandling = NullValueHandling.Ignore)] - public bool? Stream { get; set; } - - [JsonProperty("volume", NullValueHandling = NullValueHandling.Ignore)] - public double? Volume { get; set; } - - [JsonProperty("weight", NullValueHandling = NullValueHandling.Ignore)] - public long? Weight { get; set; } - - [JsonProperty("pitch", NullValueHandling = NullValueHandling.Ignore)] - public double? Pitch { get; set; } - - [JsonProperty("attenuation_distance", NullValueHandling = NullValueHandling.Ignore)] - public long? AttenuationDistance { get; set; } - - [JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)] - public TypeEnum? Type { get; set; } - } - - public enum TypeEnum { Event }; - - public partial struct SoundElement - { - public SoundClass SoundClass; - public string Path; - - public static implicit operator SoundElement(SoundClass soundClass) => new SoundElement { SoundClass = soundClass }; - public static implicit operator SoundElement(string path) => new SoundElement { Path = path }; - } - - internal static class Converter - { - public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings + public static Dictionary FromJson(string json) => JsonConvert.DeserializeObject>(json, new JsonSerializerSettings { MetadataPropertyHandling = MetadataPropertyHandling.Ignore, DateParseHandling = DateParseHandling.None, @@ -64,78 +23,6 @@ internal static class Converter TypeEnumConverter.Singleton, new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal } }, - }; - } - - internal class SoundElementConverter : JsonConverter - { - public override bool CanConvert(Type t) => t == typeof(SoundElement) || t == typeof(SoundElement?); - - public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer) - { - switch (reader.TokenType) - { - case JsonToken.String: - case JsonToken.Date: - var stringValue = serializer.Deserialize(reader); - return new SoundElement { Path = stringValue }; - case JsonToken.StartObject: - var objectValue = serializer.Deserialize(reader); - return new SoundElement { SoundClass = objectValue }; - } - throw new Exception("Cannot unmarshal type SoundElement"); - } - - public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer) - { - var value = (SoundElement)untypedValue; - if (value.Path != null) - { - serializer.Serialize(writer, value.Path); - return; - } - if (value.SoundClass != null) - { - serializer.Serialize(writer, value.SoundClass); - return; - } - throw new Exception("Cannot marshal type SoundElement"); - } - - public static readonly SoundElementConverter Singleton = new SoundElementConverter(); - } - - internal class TypeEnumConverter : JsonConverter - { - public override bool CanConvert(Type t) => t == typeof(TypeEnum) || t == typeof(TypeEnum?); - - public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer) - { - if (reader.TokenType == JsonToken.Null) return null; - var value = serializer.Deserialize(reader); - if (value == "event") - { - return TypeEnum.Event; - } - throw new Exception("Cannot unmarshal type TypeEnum"); - } - - public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer) - { - if (untypedValue == null) - { - serializer.Serialize(writer, null); - return; - } - var value = (TypeEnum)untypedValue; - if (value == TypeEnum.Event) - { - serializer.Serialize(writer, "event"); - return; - } - throw new Exception("Cannot marshal type TypeEnum"); - } - - public static readonly TypeEnumConverter Singleton = new TypeEnumConverter(); + }); } } diff --git a/src/Alex.ResourcePackLib/Json/Sound/SoundElement.cs b/src/Alex.ResourcePackLib/Json/Sound/SoundElement.cs new file mode 100644 index 000000000..27e783c6f --- /dev/null +++ b/src/Alex.ResourcePackLib/Json/Sound/SoundElement.cs @@ -0,0 +1,11 @@ +namespace Alex.ResourcePackLib.Json.Sound +{ + public partial struct SoundElement + { + public SoundMetadata SoundMetadata; + public string Path; + + public static implicit operator SoundElement(SoundMetadata soundMetadata) => new SoundElement { SoundMetadata = soundMetadata }; + public static implicit operator SoundElement(string path) => new SoundElement { Path = path }; + } +} \ No newline at end of file diff --git a/src/Alex.ResourcePackLib/Json/Sound/SoundElementConverter.cs b/src/Alex.ResourcePackLib/Json/Sound/SoundElementConverter.cs new file mode 100644 index 000000000..792f84327 --- /dev/null +++ b/src/Alex.ResourcePackLib/Json/Sound/SoundElementConverter.cs @@ -0,0 +1,43 @@ +using System; +using Newtonsoft.Json; + +namespace Alex.ResourcePackLib.Json.Sound +{ + internal class SoundElementConverter : JsonConverter + { + public override bool CanConvert(Type t) => t == typeof(SoundElement) || t == typeof(SoundElement?); + + public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer) + { + switch (reader.TokenType) + { + case JsonToken.String: + case JsonToken.Date: + var stringValue = serializer.Deserialize(reader); + return new SoundElement { Path = stringValue }; + case JsonToken.StartObject: + var objectValue = serializer.Deserialize(reader); + return new SoundElement { SoundMetadata = objectValue }; + } + throw new Exception("Cannot unmarshal type SoundElement"); + } + + public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer) + { + var value = (SoundElement)untypedValue; + if (value.Path != null) + { + serializer.Serialize(writer, value.Path); + return; + } + if (value.SoundMetadata != null) + { + serializer.Serialize(writer, value.SoundMetadata); + return; + } + throw new Exception("Cannot marshal type SoundElement"); + } + + public static readonly SoundElementConverter Singleton = new SoundElementConverter(); + } +} \ No newline at end of file diff --git a/src/Alex.ResourcePackLib/Json/Sound/SoundMetadata.cs b/src/Alex.ResourcePackLib/Json/Sound/SoundMetadata.cs new file mode 100644 index 000000000..ad4fc5ed9 --- /dev/null +++ b/src/Alex.ResourcePackLib/Json/Sound/SoundMetadata.cs @@ -0,0 +1,28 @@ +using Newtonsoft.Json; + +namespace Alex.ResourcePackLib.Json.Sound +{ + public partial class SoundMetadata + { + [JsonProperty("name")] + public string Name { get; set; } + + [JsonProperty("stream", NullValueHandling = NullValueHandling.Ignore)] + public bool? Stream { get; set; } + + [JsonProperty("volume", NullValueHandling = NullValueHandling.Ignore)] + public double? Volume { get; set; } + + [JsonProperty("weight", NullValueHandling = NullValueHandling.Ignore)] + public long? Weight { get; set; } + + [JsonProperty("pitch", NullValueHandling = NullValueHandling.Ignore)] + public double? Pitch { get; set; } + + [JsonProperty("attenuation_distance", NullValueHandling = NullValueHandling.Ignore)] + public double? AttenuationDistance { get; set; } + + [JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)] + public SoundType? Type { get; set; } + } +} \ No newline at end of file diff --git a/src/Alex.ResourcePackLib/Json/Sound/SoundType.cs b/src/Alex.ResourcePackLib/Json/Sound/SoundType.cs new file mode 100644 index 000000000..a823f1480 --- /dev/null +++ b/src/Alex.ResourcePackLib/Json/Sound/SoundType.cs @@ -0,0 +1,7 @@ +namespace Alex.ResourcePackLib.Json.Sound +{ + public enum SoundType + { + Event + }; +} \ No newline at end of file diff --git a/src/Alex.ResourcePackLib/Json/Sound/TypeEnumConverter.cs b/src/Alex.ResourcePackLib/Json/Sound/TypeEnumConverter.cs new file mode 100644 index 000000000..d26f43b93 --- /dev/null +++ b/src/Alex.ResourcePackLib/Json/Sound/TypeEnumConverter.cs @@ -0,0 +1,39 @@ +using System; +using Newtonsoft.Json; + +namespace Alex.ResourcePackLib.Json.Sound +{ + internal class TypeEnumConverter : JsonConverter + { + public override bool CanConvert(Type t) => t == typeof(SoundType) || t == typeof(SoundType?); + + public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer) + { + if (reader.TokenType == JsonToken.Null) return null; + var value = serializer.Deserialize(reader); + if (value == "event") + { + return SoundType.Event; + } + throw new Exception("Cannot unmarshal type TypeEnum"); + } + + public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer) + { + if (untypedValue == null) + { + serializer.Serialize(writer, null); + return; + } + var value = (SoundType)untypedValue; + if (value == SoundType.Event) + { + serializer.Serialize(writer, "event"); + return; + } + throw new Exception("Cannot marshal type TypeEnum"); + } + + public static readonly TypeEnumConverter Singleton = new TypeEnumConverter(); + } +} \ No newline at end of file diff --git a/src/Alex.ResourcePackLib/Json/Textures/Converter.cs b/src/Alex.ResourcePackLib/Json/Textures/Converter.cs new file mode 100644 index 000000000..f3b759251 --- /dev/null +++ b/src/Alex.ResourcePackLib/Json/Textures/Converter.cs @@ -0,0 +1,20 @@ +using System.Globalization; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; + +namespace Alex.ResourcePackLib.Json.Textures +{ + internal static class Converter + { + public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings + { + MetadataPropertyHandling = MetadataPropertyHandling.Ignore, + DateParseHandling = DateParseHandling.None, + Converters = + { + FrameElementConverter.Singleton, + new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal } + }, + }; + } +} \ No newline at end of file diff --git a/src/Alex.ResourcePackLib/Json/Textures/FrameElement.cs b/src/Alex.ResourcePackLib/Json/Textures/FrameElement.cs new file mode 100644 index 000000000..b6fa1e74a --- /dev/null +++ b/src/Alex.ResourcePackLib/Json/Textures/FrameElement.cs @@ -0,0 +1,11 @@ +namespace Alex.ResourcePackLib.Json.Textures +{ + public struct FrameElement + { + public TextureFrame FrameInfo; + public long? Integer; + + public static implicit operator FrameElement(TextureFrame frame) => new FrameElement { FrameInfo = frame }; + public static implicit operator FrameElement(long integer) => new FrameElement { Integer = integer }; + } +} \ No newline at end of file diff --git a/src/Alex.ResourcePackLib/Json/Textures/FrameElementConverter.cs b/src/Alex.ResourcePackLib/Json/Textures/FrameElementConverter.cs new file mode 100644 index 000000000..9521d11e5 --- /dev/null +++ b/src/Alex.ResourcePackLib/Json/Textures/FrameElementConverter.cs @@ -0,0 +1,42 @@ +using System; +using Newtonsoft.Json; + +namespace Alex.ResourcePackLib.Json.Textures +{ + internal class FrameElementConverter : JsonConverter + { + public override bool CanConvert(Type t) => t == typeof(FrameElement) || t == typeof(FrameElement?); + + public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer) + { + switch (reader.TokenType) + { + case JsonToken.Integer: + var integerValue = serializer.Deserialize(reader); + return new FrameElement { Integer = integerValue }; + case JsonToken.StartObject: + var objectValue = serializer.Deserialize(reader); + return new FrameElement { FrameInfo = objectValue }; + } + throw new Exception("Cannot unmarshal type FrameElement"); + } + + public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer) + { + var value = (FrameElement)untypedValue; + if (value.Integer != null) + { + serializer.Serialize(writer, value.Integer.Value); + return; + } + if (value.FrameInfo != null) + { + serializer.Serialize(writer, value.FrameInfo); + return; + } + throw new Exception("Cannot marshal type FrameElement"); + } + + public static readonly FrameElementConverter Singleton = new FrameElementConverter(); + } +} \ No newline at end of file diff --git a/src/Alex.ResourcePackLib/Json/Textures/TextureAnimation.cs b/src/Alex.ResourcePackLib/Json/Textures/TextureAnimation.cs new file mode 100644 index 000000000..b1111c12a --- /dev/null +++ b/src/Alex.ResourcePackLib/Json/Textures/TextureAnimation.cs @@ -0,0 +1,21 @@ +using Newtonsoft.Json; + +namespace Alex.ResourcePackLib.Json.Textures +{ + public class TextureAnimation + { + [JsonProperty("interpolate")] + public bool Interpolate { get; set; } + + [JsonProperty("width")] + public long Width { get; set; } + + [JsonProperty("height")] + public long Height { get; set; } + + [JsonProperty("frametime")] public int Frametime { get; set; } = 1; + + [JsonProperty("frames")] + public FrameElement[] Frames { get; set; } + } +} \ No newline at end of file diff --git a/src/Alex.ResourcePackLib/Json/Textures/TextureData.cs b/src/Alex.ResourcePackLib/Json/Textures/TextureData.cs new file mode 100644 index 000000000..5a6be60b7 --- /dev/null +++ b/src/Alex.ResourcePackLib/Json/Textures/TextureData.cs @@ -0,0 +1,13 @@ +using Newtonsoft.Json; + +namespace Alex.ResourcePackLib.Json.Textures +{ + public class TextureData + { + [JsonProperty("blur")] + public bool Blur { get; set; } + + [JsonProperty("clamp")] + public bool Clamp { get; set; } + } +} \ No newline at end of file diff --git a/src/Alex.ResourcePackLib/Json/Textures/TextureFrame.cs b/src/Alex.ResourcePackLib/Json/Textures/TextureFrame.cs new file mode 100644 index 000000000..63b05911e --- /dev/null +++ b/src/Alex.ResourcePackLib/Json/Textures/TextureFrame.cs @@ -0,0 +1,13 @@ +using Newtonsoft.Json; + +namespace Alex.ResourcePackLib.Json.Textures +{ + public class TextureFrame + { + [JsonProperty("index")] + public long Index { get; set; } + + [JsonProperty("time")] + public double Time { get; set; } + } +} \ No newline at end of file diff --git a/src/Alex.ResourcePackLib/Json/Textures/TextureMeta.cs b/src/Alex.ResourcePackLib/Json/Textures/TextureMeta.cs index ffafd822d..affca63ce 100644 --- a/src/Alex.ResourcePackLib/Json/Textures/TextureMeta.cs +++ b/src/Alex.ResourcePackLib/Json/Textures/TextureMeta.cs @@ -1,114 +1,15 @@ -using System; - -using System.Globalization; using Newtonsoft.Json; -using Newtonsoft.Json.Converters; namespace Alex.ResourcePackLib.Json.Textures { public class TextureMeta { [JsonProperty("animation")] - public Animation Animation { get; set; } + public TextureAnimation Animation { get; set; } [JsonProperty("texture")] - public Texture Texture { get; set; } + public TextureData Texture { get; set; } public static TextureMeta FromJson(string json) => JsonConvert.DeserializeObject(json, Converter.Settings); } - - public class Animation - { - [JsonProperty("interpolate")] - public bool Interpolate { get; set; } - - [JsonProperty("width")] - public long Width { get; set; } - - [JsonProperty("height")] - public long Height { get; set; } - - [JsonProperty("frametime")] public int Frametime { get; set; } = 1; - - [JsonProperty("frames")] - public FrameElement[] Frames { get; set; } - } - - public class FrameClass - { - [JsonProperty("index")] - public long Index { get; set; } - - [JsonProperty("time")] - public long Time { get; set; } - } - - public class Texture - { - [JsonProperty("blur")] - public bool Blur { get; set; } - - [JsonProperty("clamp")] - public bool Clamp { get; set; } - } - - public struct FrameElement - { - public FrameClass FrameClass; - public long? Integer; - - public static implicit operator FrameElement(FrameClass FrameClass) => new FrameElement { FrameClass = FrameClass }; - public static implicit operator FrameElement(long Integer) => new FrameElement { Integer = Integer }; - } - - internal static class Converter - { - public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings - { - MetadataPropertyHandling = MetadataPropertyHandling.Ignore, - DateParseHandling = DateParseHandling.None, - Converters = - { - FrameElementConverter.Singleton, - new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal } - }, - }; - } - - internal class FrameElementConverter : JsonConverter - { - public override bool CanConvert(Type t) => t == typeof(FrameElement) || t == typeof(FrameElement?); - - public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer) - { - switch (reader.TokenType) - { - case JsonToken.Integer: - var integerValue = serializer.Deserialize(reader); - return new FrameElement { Integer = integerValue }; - case JsonToken.StartObject: - var objectValue = serializer.Deserialize(reader); - return new FrameElement { FrameClass = objectValue }; - } - throw new Exception("Cannot unmarshal type FrameElement"); - } - - public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer) - { - var value = (FrameElement)untypedValue; - if (value.Integer != null) - { - serializer.Serialize(writer, value.Integer.Value); - return; - } - if (value.FrameClass != null) - { - serializer.Serialize(writer, value.FrameClass); - return; - } - throw new Exception("Cannot marshal type FrameElement"); - } - - public static readonly FrameElementConverter Singleton = new FrameElementConverter(); - } } \ No newline at end of file diff --git a/src/Alex.ResourcePackLib/MCPack.cs b/src/Alex.ResourcePackLib/MCPack.cs index 0a2d65468..35c4564ea 100644 --- a/src/Alex.ResourcePackLib/MCPack.cs +++ b/src/Alex.ResourcePackLib/MCPack.cs @@ -3,6 +3,7 @@ using System.IO; using System.IO.Compression; using System.Linq; +using Alex.ResourcePackLib.Bedrock; using Alex.ResourcePackLib.Exceptions; using Alex.ResourcePackLib.IO.Abstract; using Alex.ResourcePackLib.Json; @@ -46,17 +47,22 @@ private void Load(IFilesystem archive) { switch (module.Type.ToLower()) { + //case "resources": + // modules.Add(new ResourceModule(archive)); + // break; case "skin_pack": try { - MCSkinPack skinPack = new MCSkinPack(archive); - modules.Add(skinPack); + modules.Add(new SkinModule(archive)); } catch { } break; + default: + Log.Warn($"Unknown resourcepack module type found in pack! Found '{module.Type}' in manifest '{Manifest.Header.Name}'"); + break; } } @@ -67,11 +73,11 @@ private void Load(IFilesystem archive) try { loaded = module.Load(); - loaded = true; } catch (Exception ex) { Log.Error(ex,$"Failed to load MCPack module: {module.Name} from {Manifest.Header.Name}: {ex}"); + loaded = false; //toRemove.Add(module); } diff --git a/src/Alex/Gamestates/MainMenu/Profile/SkinEntry.cs b/src/Alex/Gamestates/MainMenu/Profile/SkinEntry.cs index 6bcf39020..2efac99ea 100644 --- a/src/Alex/Gamestates/MainMenu/Profile/SkinEntry.cs +++ b/src/Alex/Gamestates/MainMenu/Profile/SkinEntry.cs @@ -8,6 +8,7 @@ using Alex.Gui.Elements; using Alex.Gui.Elements.Context3D; using Alex.ResourcePackLib; +using Alex.ResourcePackLib.Bedrock; using Alex.Utils; using Microsoft.Xna.Framework; using RocketUI; diff --git a/src/Alex/Gamestates/MainMenu/SkinSelectionState.cs b/src/Alex/Gamestates/MainMenu/SkinSelectionState.cs index f0fa64ffe..a9d062199 100644 --- a/src/Alex/Gamestates/MainMenu/SkinSelectionState.cs +++ b/src/Alex/Gamestates/MainMenu/SkinSelectionState.cs @@ -13,6 +13,7 @@ using Alex.Graphics.Models.Entity; using Alex.Gui; using Alex.ResourcePackLib; +using Alex.ResourcePackLib.Bedrock; using Alex.ResourcePackLib.Json; using Microsoft.Xna.Framework; using NLog; @@ -187,7 +188,7 @@ private void LoadItems(int start, int count) if (index >= start + count) break; - foreach (var module in skinPack.Modules.Where(x => x is MCSkinPack).Cast()) + foreach (var module in skinPack.Modules.Where(x => x is SkinModule).Cast()) { if (index >= start + count) break; diff --git a/src/Alex/Net/Bedrock/BedrockClient.cs b/src/Alex/Net/Bedrock/BedrockClient.cs index bfeba0d07..aaa8ea11c 100755 --- a/src/Alex/Net/Bedrock/BedrockClient.cs +++ b/src/Alex/Net/Bedrock/BedrockClient.cs @@ -1118,6 +1118,9 @@ public override void HeldItemChanged(Item item, short slot) public override void DropItem(BlockCoordinates position, BlockFace face, Item item, bool dropFullStack) { var player = World.Player; + byte inventoryId = 28; + byte slot = (byte)(player.Inventory.HotbarOffset + player.Inventory.SelectedSlot); + var newItem = item.Clone(); var dropItem = item.Clone(); @@ -1166,6 +1169,17 @@ public override void DropItem(BlockCoordinates position, BlockFace face, Item it }, Slot = 0 } + }, + RequestRecords = new List() + { + new RequestRecord() + { + ContainerId = inventoryId, + Slots = new List() + { + slot + } + } } }; diff --git a/src/Alex/ResourceManager.cs b/src/Alex/ResourceManager.cs index 6ce43b64e..cd101b1d9 100644 --- a/src/Alex/ResourceManager.cs +++ b/src/Alex/ResourceManager.cs @@ -8,6 +8,7 @@ using System.Net; using System.Reflection; using System.Text; +using System.Text.RegularExpressions; using Alex.Blocks; using Alex.Blocks.Mapping; using Alex.Blocks.Minecraft; @@ -790,16 +791,19 @@ private void ProcessBedrockResources(IProgressReceiver progress, GraphicsDevice Log.Debug($"== End Processing \"{resourcePack.Info.Name}\" ==\n"); } + private static Regex _bedrockSearchPattern = new Regex( + @"$(?<=.(zip|mcpack))", + RegexOptions.IgnoreCase | RegexOptions.Compiled); public void LoadBedrockPacks(IProgressReceiver progressReceiver, DirectoryInfo directoryInfo) { progressReceiver?.UpdateProgress(0, "Loading bedrock .MCPack files..."); - var files = directoryInfo.EnumerateFiles("*.mcpack").ToArray(); + var files = directoryInfo.EnumerateFiles().Where(x => _bedrockSearchPattern.IsMatch(x.Name)).ToArray(); for (var index = 0; index < files.Length; index++) { var file = files[index]; - progressReceiver?.UpdateProgress(index, files.Length, "Loading bedrock .MCPack files...", file.Name); + progressReceiver?.UpdateProgress(index, files.Length, "Loading bedrock resourcepack files...", file.Name); try { @@ -811,7 +815,7 @@ public void LoadBedrockPacks(IProgressReceiver progressReceiver, DirectoryInfo d } catch (Exception ex) { - Log.Warn(ex, $"Failed to load bedrock .MCPack file: {file.Name}: {ex}"); + Log.Warn(ex, $"Failed to load bedrockpack file: {file.Name}: {ex}"); } } }