From fd01445289e79891478a86ee1957204ad44871cd Mon Sep 17 00:00:00 2001 From: Henry Migo Date: Sat, 30 Oct 2021 13:48:20 +0100 Subject: [PATCH 01/15] Hide base member with 'new' --- Obsidian.API/_Interfaces/ILiving.cs | 2 +- Obsidian.API/_Interfaces/IPlayer.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Obsidian.API/_Interfaces/ILiving.cs b/Obsidian.API/_Interfaces/ILiving.cs index 2d1e6ca3d..90a8d82f6 100644 --- a/Obsidian.API/_Interfaces/ILiving.cs +++ b/Obsidian.API/_Interfaces/ILiving.cs @@ -4,7 +4,7 @@ public interface ILiving : IEntity { public LivingBitMask LivingBitMask { get; set; } - public float Health { get; set; } + public new float Health { get; set; } public uint ActiveEffectColor { get; } diff --git a/Obsidian.API/_Interfaces/IPlayer.cs b/Obsidian.API/_Interfaces/IPlayer.cs index 06815ec54..be1048bab 100644 --- a/Obsidian.API/_Interfaces/IPlayer.cs +++ b/Obsidian.API/_Interfaces/IPlayer.cs @@ -10,7 +10,7 @@ public interface IPlayer : ILiving public string Username { get; } - public Guid Uuid { get; } + public new Guid Uuid { get; } public bool IsOperator { get; } public Gamemode Gamemode { get; set; } From f53ceea8d1e39460395ec2991067663455c7c066 Mon Sep 17 00:00:00 2001 From: Henry Migo Date: Sat, 30 Oct 2021 13:52:09 +0100 Subject: [PATCH 02/15] Added nullable to base type and removed nullable from equals method --- Obsidian.API/Crafting/IRecipe.cs | 2 +- Obsidian.API/_Types/Inventory/ItemStack.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Obsidian.API/Crafting/IRecipe.cs b/Obsidian.API/Crafting/IRecipe.cs index 8ecf529b2..415d3f799 100644 --- a/Obsidian.API/Crafting/IRecipe.cs +++ b/Obsidian.API/Crafting/IRecipe.cs @@ -6,7 +6,7 @@ public interface IRecipe public CraftingType Type { get; set; } - public string Group { get; set; } + public string? Group { get; set; } public Ingredient Result { get; set; } } diff --git a/Obsidian.API/_Types/Inventory/ItemStack.cs b/Obsidian.API/_Types/Inventory/ItemStack.cs index d5e51b85e..267a3b63e 100644 --- a/Obsidian.API/_Types/Inventory/ItemStack.cs +++ b/Obsidian.API/_Types/Inventory/ItemStack.cs @@ -57,7 +57,7 @@ public ItemStack(Material type, short count = 1, ItemMeta? meta = null) return item; } - public bool Equals(ItemStack other) => (this.Type, this.ItemMeta) == (other?.Type, other?.ItemMeta); + public bool Equals(ItemStack other) => (this.Type, this.ItemMeta) == (other.Type, other.ItemMeta); public override bool Equals(object? obj) => obj is ItemStack itemStack && Equals(itemStack); From 99533db8c1b56d8085bdb122e24bb13e1c76c0ff Mon Sep 17 00:00:00 2001 From: Henry Migo Date: Sat, 30 Oct 2021 13:56:08 +0100 Subject: [PATCH 03/15] Added full stop to some summaries --- Obsidian/Entities/Player.cs | 2 +- Obsidian/Events/EventArgs/BasePacketEventArgs.cs | 4 ++-- Obsidian/NativeMethods.cs | 2 +- Obsidian/Net/Packets/Play/Clientbound/BlockBreakAnimation.cs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Obsidian/Entities/Player.cs b/Obsidian/Entities/Player.cs index e0b777f5c..4d6acd1d6 100644 --- a/Obsidian/Entities/Player.cs +++ b/Obsidian/Entities/Player.cs @@ -35,7 +35,7 @@ public class Player : Living, IPlayer public string Username { get; } /// - /// The players inventory + /// The players inventory. /// public Inventory Inventory { get; } public Inventory OpenedInventory { get; set; } diff --git a/Obsidian/Events/EventArgs/BasePacketEventArgs.cs b/Obsidian/Events/EventArgs/BasePacketEventArgs.cs index fe71c1cfa..8b49b7bf5 100644 --- a/Obsidian/Events/EventArgs/BasePacketEventArgs.cs +++ b/Obsidian/Events/EventArgs/BasePacketEventArgs.cs @@ -6,12 +6,12 @@ namespace Obsidian.Events.EventArgs public class BasePacketEventArgs : AsyncEventArgs { /// - /// The client that invoked the event + /// The client that invoked the event. /// public Client Client { get; set; } /// - /// The packet being used to invoke this event + /// The packet being used to invoke this event. /// public IPacket Packet { get; private set; } diff --git a/Obsidian/NativeMethods.cs b/Obsidian/NativeMethods.cs index 6947cbef7..a05fe1e1b 100644 --- a/Obsidian/NativeMethods.cs +++ b/Obsidian/NativeMethods.cs @@ -3,7 +3,7 @@ namespace Obsidian { /// - /// Native methods for Windows + /// Native methods for Windows. /// internal static class NativeMethods { diff --git a/Obsidian/Net/Packets/Play/Clientbound/BlockBreakAnimation.cs b/Obsidian/Net/Packets/Play/Clientbound/BlockBreakAnimation.cs index ad7acd96f..f0c882749 100644 --- a/Obsidian/Net/Packets/Play/Clientbound/BlockBreakAnimation.cs +++ b/Obsidian/Net/Packets/Play/Clientbound/BlockBreakAnimation.cs @@ -12,7 +12,7 @@ public partial class BlockBreakAnimation : IClientboundPacket public VectorF Position { get; init; } /// - /// 0-9 to set it, any other value to remove it + /// 0-9 to set it, any other value to remove it. /// [Field(2)] public sbyte DestroyStage { get; init; } From f3988d00bac167c15e0ba3c7ac15cd87f0729349 Mon Sep 17 00:00:00 2001 From: Henry Migo Date: Sat, 30 Oct 2021 14:08:48 +0100 Subject: [PATCH 04/15] nullability of reference types warning --- Obsidian.API/_Types/Inventory/ItemMeta.cs | 2 +- Obsidian.API/_Types/Inventory/ItemStack.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Obsidian.API/_Types/Inventory/ItemMeta.cs b/Obsidian.API/_Types/Inventory/ItemMeta.cs index f502bba64..4ea3dd41a 100644 --- a/Obsidian.API/_Types/Inventory/ItemMeta.cs +++ b/Obsidian.API/_Types/Inventory/ItemMeta.cs @@ -30,7 +30,7 @@ public bool Equals(ItemMeta other) => (this.Slot, this.CustomModelData, this.Name, this.RepairAmount, this.Durability, this.Unbreakable, this.Enchantments, this.StoredEnchantments, this.CanDestroy, this.Lore) == (other.Slot, other.CustomModelData, other.Name, other.RepairAmount, other.Durability, other.Unbreakable, other.Enchantments, other.StoredEnchantments, other.CanDestroy, other.Lore); - public override bool Equals(object obj) => obj is ItemMeta meta && Equals(meta); + public override bool Equals(object? obj) => obj is ItemMeta meta && Equals(meta); public static bool operator ==(ItemMeta left, ItemMeta right) => left.Equals(right); diff --git a/Obsidian.API/_Types/Inventory/ItemStack.cs b/Obsidian.API/_Types/Inventory/ItemStack.cs index 267a3b63e..6c367c396 100644 --- a/Obsidian.API/_Types/Inventory/ItemStack.cs +++ b/Obsidian.API/_Types/Inventory/ItemStack.cs @@ -57,7 +57,7 @@ public ItemStack(Material type, short count = 1, ItemMeta? meta = null) return item; } - public bool Equals(ItemStack other) => (this.Type, this.ItemMeta) == (other.Type, other.ItemMeta); + public bool Equals(ItemStack? other) => (this.Type, this.ItemMeta) == (other?.Type, other?.ItemMeta); public override bool Equals(object? obj) => obj is ItemStack itemStack && Equals(itemStack); From 4df2fcd91a10eab4ee512c2b3caf936c94debeb3 Mon Sep 17 00:00:00 2001 From: Henry Migo Date: Sat, 30 Oct 2021 14:31:27 +0100 Subject: [PATCH 05/15] Added constructors to resolve non-null property part 1 --- .../Crafting/Builders/CuttingRecipeBuilder.cs | 16 ++++++++-------- .../Crafting/Builders/ShapedRecipeBuilder.cs | 16 ++++++++-------- .../Builders/ShapelessRecipeBuilder.cs | 14 +++++++------- .../Builders/SmeltingRecipeBuilder.cs | 19 ++++++++++--------- .../Builders/SmithingRecipeBuilder.cs | 16 ++++++++-------- Obsidian.API/Crafting/CuttingRecipe.cs | 10 ++++++++++ Obsidian.API/Crafting/ShapedRecipe.cs | 12 +++++++++++- Obsidian.API/Crafting/ShapelessRecipe.cs | 9 +++++++++ Obsidian.API/Crafting/SmeltingRecipe.cs | 11 +++++++++++ Obsidian.API/Crafting/SmithingRecipe.cs | 10 ++++++++++ Obsidian.API/Events/BaseMinecraftEventArgs.cs | 1 + 11 files changed, 93 insertions(+), 41 deletions(-) diff --git a/Obsidian.API/Crafting/Builders/CuttingRecipeBuilder.cs b/Obsidian.API/Crafting/Builders/CuttingRecipeBuilder.cs index 22b3eaa36..a1f2002f8 100644 --- a/Obsidian.API/Crafting/Builders/CuttingRecipeBuilder.cs +++ b/Obsidian.API/Crafting/Builders/CuttingRecipeBuilder.cs @@ -57,14 +57,14 @@ public IRecipe Build() throw new InvalidOperationException("Recipe must atleast have 1 item as an ingredient"); return new CuttingRecipe - { - Name = this.Name ?? throw new NullReferenceException("Name must not be null"), - Type = CraftingType.Stonecutting, - Group = this.Group, - Ingredient = this.Ingredient ?? throw new NullReferenceException("Ingredient must not be null"), - Count = this.Count, - Result = this.Result != null ? new Ingredient { this.Result } : throw new NullReferenceException("Result is not set.") - }; + ( + this.Name ?? throw new NullReferenceException("Name must not be null"), + CraftingType.Stonecutting, + this.Group, + this.Result != null ? new Ingredient { this.Result } : throw new NullReferenceException("Result is not set."), + this.Ingredient ?? throw new NullReferenceException("Ingredient must not be null"), + this.Count + ); } } } diff --git a/Obsidian.API/Crafting/Builders/ShapedRecipeBuilder.cs b/Obsidian.API/Crafting/Builders/ShapedRecipeBuilder.cs index 34d250a18..5af39e7a5 100644 --- a/Obsidian.API/Crafting/Builders/ShapedRecipeBuilder.cs +++ b/Obsidian.API/Crafting/Builders/ShapedRecipeBuilder.cs @@ -56,14 +56,14 @@ public IRecipe Build() throw new InvalidOperationException("Keys cannot be empty."); return new ShapedRecipe - { - Name = this.Name ?? throw new NullReferenceException("Recipe must have a name"), - Type = CraftingType.CraftingShaped, - Group = this.Group, - Pattern = new ReadOnlyCollection(new List(this.pattern)), - Result = this.Result != null ? new Ingredient { this.Result } : throw new NullReferenceException("Result is not set."), - Key = new ReadOnlyDictionary(new Dictionary(this.key)) - }; + ( + this.Name ?? throw new NullReferenceException("Recipe must have a name"), + CraftingType.CraftingShaped, + this.Group, + this.Result != null ? new Ingredient { this.Result } : throw new NullReferenceException("Result is not set."), + new ReadOnlyCollection(new List(this.pattern)), + new ReadOnlyDictionary(new Dictionary(this.key)) + ); } public ShapedRecipeBuilder WithName(string name) diff --git a/Obsidian.API/Crafting/Builders/ShapelessRecipeBuilder.cs b/Obsidian.API/Crafting/Builders/ShapelessRecipeBuilder.cs index 79749ece9..f9f22fcf3 100644 --- a/Obsidian.API/Crafting/Builders/ShapelessRecipeBuilder.cs +++ b/Obsidian.API/Crafting/Builders/ShapelessRecipeBuilder.cs @@ -35,13 +35,13 @@ public IRecipe Build() throw new InvalidOperationException("Ingredients must be filled with atleast 1 item."); return new ShapelessRecipe - { - Name = this.Name ?? throw new NullReferenceException("Recipe must have a name"), - Type = CraftingType.CraftingShapeless, - Group = this.Group, - Ingredients = new ReadOnlyCollection(new List(this.ingredients)), - Result = this.Result != null ? new Ingredient { this.Result } : throw new NullReferenceException("Result is not set.") - }; + ( + this.Name ?? throw new NullReferenceException("Recipe must have a name"), + CraftingType.CraftingShapeless, + this.Group, + this.Result != null ? new Ingredient { this.Result } : throw new NullReferenceException("Result is not set."), + new ReadOnlyCollection(new List(this.ingredients)) + ); } public ShapelessRecipeBuilder WithName(string name) diff --git a/Obsidian.API/Crafting/Builders/SmeltingRecipeBuilder.cs b/Obsidian.API/Crafting/Builders/SmeltingRecipeBuilder.cs index 07ef8abbb..0fb9ac588 100644 --- a/Obsidian.API/Crafting/Builders/SmeltingRecipeBuilder.cs +++ b/Obsidian.API/Crafting/Builders/SmeltingRecipeBuilder.cs @@ -78,22 +78,23 @@ public IRecipe Build() SmeltingType.Default => CraftingType.Smelting, SmeltingType.Blasting => CraftingType.Blasting, SmeltingType.Smoking => CraftingType.Smoking, - SmeltingType.CampfireCooking => CraftingType.CampfireCooking + SmeltingType.CampfireCooking => CraftingType.CampfireCooking, + _ => throw new NotImplementedException() }; if (this.Ingredient.Count <= 0) throw new InvalidOperationException("Recipe must atleast have 1 item as an ingredient"); return new SmeltingRecipe - { - Name = this.Name ?? throw new NullReferenceException("Recipe must have a name"), - Type = type, + ( + this.Name ?? throw new NullReferenceException("Recipe must have a name"), + type, Group = this.Group, - Ingredient = this.Ingredient, - Cookingtime = this.CookingTime, - Experience = this.Experience, - Result = this.Result != null ? new Ingredient { this.Result } : throw new NullReferenceException("Result is not set.") - }; + this.Result != null ? new Ingredient { this.Result } : throw new NullReferenceException("Result is not set."), + this.Ingredient, + this.Experience, + this.CookingTime + ); } } diff --git a/Obsidian.API/Crafting/Builders/SmithingRecipeBuilder.cs b/Obsidian.API/Crafting/Builders/SmithingRecipeBuilder.cs index 03a7a0e5a..67d7c5a8e 100644 --- a/Obsidian.API/Crafting/Builders/SmithingRecipeBuilder.cs +++ b/Obsidian.API/Crafting/Builders/SmithingRecipeBuilder.cs @@ -62,14 +62,14 @@ public IRecipe Build() throw new InvalidOperationException("Sub ingredients must have atleast 1 item."); return new SmithingRecipe - { - Name = this.Name ?? throw new NullReferenceException("Recipe must have a name"), - Type = CraftingType.Smithing, - Group = this.Group, - Base = this.Base, - Addition = this.Addition, - Result = this.Result != null ? new Ingredient { this.Result } : throw new NullReferenceException("Result is not set.") - }; + ( + this.Name ?? throw new NullReferenceException("Recipe must have a name"), + CraftingType.Smithing, + this.Group, + this.Base, + this.Addition, + this.Result != null ? new Ingredient { this.Result } : throw new NullReferenceException("Result is not set.") + ); } } } diff --git a/Obsidian.API/Crafting/CuttingRecipe.cs b/Obsidian.API/Crafting/CuttingRecipe.cs index 45ad683f1..7b31d45ba 100644 --- a/Obsidian.API/Crafting/CuttingRecipe.cs +++ b/Obsidian.API/Crafting/CuttingRecipe.cs @@ -13,5 +13,15 @@ public sealed class CuttingRecipe : IRecipe public Ingredient Ingredient { get; set; } public int Count { get; set; } + + public CuttingRecipe(string name, CraftingType type, string? group, Ingredient result, Ingredient ingredient, int count) + { + Name = name; + Type = type; + Group = group; + Result = result; + Ingredient = ingredient; + Count = count; + } } } diff --git a/Obsidian.API/Crafting/ShapedRecipe.cs b/Obsidian.API/Crafting/ShapedRecipe.cs index 89fcd5f74..e4914f09e 100644 --- a/Obsidian.API/Crafting/ShapedRecipe.cs +++ b/Obsidian.API/Crafting/ShapedRecipe.cs @@ -8,12 +8,22 @@ public sealed class ShapedRecipe : IRecipe public CraftingType Type { get; set; } - public string Group { get; set; } + public string? Group { get; set; } public Ingredient Result { get; set; } public IReadOnlyList Pattern { get; set; } public IReadOnlyDictionary Key { get; set; } + + public ShapedRecipe(string name, CraftingType type, string? group, Ingredient result, IReadOnlyList pattern, IReadOnlyDictionary key) + { + Name = name; + Type = type; + Group = group; + Result = result; + Pattern = pattern; + Key = key; + } } } diff --git a/Obsidian.API/Crafting/ShapelessRecipe.cs b/Obsidian.API/Crafting/ShapelessRecipe.cs index 89c810c02..6d6b410ae 100644 --- a/Obsidian.API/Crafting/ShapelessRecipe.cs +++ b/Obsidian.API/Crafting/ShapelessRecipe.cs @@ -13,5 +13,14 @@ public sealed class ShapelessRecipe : IRecipe public Ingredient Result { get; set; } public IReadOnlyList Ingredients { get; set; } + + public ShapelessRecipe(string name, CraftingType type, string? group, Ingredient result, IReadOnlyList ingredients) + { + Name = name; + Type = type; + Group = group; + Result = result; + Ingredients = ingredients; + } } } diff --git a/Obsidian.API/Crafting/SmeltingRecipe.cs b/Obsidian.API/Crafting/SmeltingRecipe.cs index 915c6dc5a..d23457722 100644 --- a/Obsidian.API/Crafting/SmeltingRecipe.cs +++ b/Obsidian.API/Crafting/SmeltingRecipe.cs @@ -15,5 +15,16 @@ public sealed class SmeltingRecipe : IRecipe public float Experience { get; set; } public int Cookingtime { get; set; } + + public SmeltingRecipe(string name, CraftingType type, string? group, Ingredient result, Ingredient ingredient, float experience, int cookingTime) + { + Name = name; + Type = type; + Group = group; + Result = result; + Ingredient = ingredient; + Experience = experience; + Cookingtime = cookingTime; + } } } diff --git a/Obsidian.API/Crafting/SmithingRecipe.cs b/Obsidian.API/Crafting/SmithingRecipe.cs index def6dede9..613150f08 100644 --- a/Obsidian.API/Crafting/SmithingRecipe.cs +++ b/Obsidian.API/Crafting/SmithingRecipe.cs @@ -13,5 +13,15 @@ public sealed class SmithingRecipe : IRecipe public Ingredient Base { get; set; } public Ingredient Addition { get; set; } + + public SmithingRecipe(string name, CraftingType type, string? group, Ingredient result, Ingredient Base, Ingredient addition) + { + Name = name; + Type = type; + Group = group; + Result = result; + this.Base = Base; + Addition = addition; + } } } diff --git a/Obsidian.API/Events/BaseMinecraftEventArgs.cs b/Obsidian.API/Events/BaseMinecraftEventArgs.cs index 0b180a4f2..2edd7144c 100644 --- a/Obsidian.API/Events/BaseMinecraftEventArgs.cs +++ b/Obsidian.API/Events/BaseMinecraftEventArgs.cs @@ -12,6 +12,7 @@ public class BaseMinecraftEventArgs : AsyncEventArgs /// /// Constructs a new instance of the class. + /// /// The server that's handling this event. internal BaseMinecraftEventArgs(IServer server) { From b83bf9b3fe2043609e5a8e627c837d38e2497ede Mon Sep 17 00:00:00 2001 From: Henry Migo Date: Sat, 30 Oct 2021 15:10:49 +0100 Subject: [PATCH 06/15] Some compiler warning fixes --- Obsidian.API/Noise/BitShiftInput.cs | 5 +- Obsidian.API/Noise/Blend.cs | 4 +- .../Plugins/Services/IO/IFileService.cs | 123 +++++++++++++++--- Obsidian.API/_Types/ClickComponent.cs | 7 + Obsidian.API/_Types/HoverComponent.cs | 7 + Obsidian/Commands/MainCommandModule.cs | 3 +- Obsidian/WorldData/BlockUpdates.cs | 27 ++-- .../Overworld/Terrain/OverworldTerrain.cs | 2 - 8 files changed, 145 insertions(+), 33 deletions(-) diff --git a/Obsidian.API/Noise/BitShiftInput.cs b/Obsidian.API/Noise/BitShiftInput.cs index 40f56fadf..677aa5468 100644 --- a/Obsidian.API/Noise/BitShiftInput.cs +++ b/Obsidian.API/Noise/BitShiftInput.cs @@ -27,7 +27,10 @@ public class BitShiftInput : Module /// /// ctor. /// - public BitShiftInput() : base(1) { } + public BitShiftInput(Module source0) : base(1) + { + Source0 = source0; + } /// /// Retrieve noise value diff --git a/Obsidian.API/Noise/Blend.cs b/Obsidian.API/Noise/Blend.cs index 742b989b6..92e45636a 100644 --- a/Obsidian.API/Noise/Blend.cs +++ b/Obsidian.API/Noise/Blend.cs @@ -18,9 +18,9 @@ public class Blend : Module /// /// ctor. /// - public Blend() : base(1) + public Blend(Module source0) : base(1) { - + Source0 = source0; } /// diff --git a/Obsidian.API/Plugins/Services/IO/IFileService.cs b/Obsidian.API/Plugins/Services/IO/IFileService.cs index 8d94f4cff..39149e4da 100644 --- a/Obsidian.API/Plugins/Services/IO/IFileService.cs +++ b/Obsidian.API/Plugins/Services/IO/IFileService.cs @@ -19,10 +19,23 @@ public bool FileExists(string path) if (!IsUsable) throw new SecurityException(SecurityExceptionMessage); - var workingDirectory = GetWorkingDirectory(); - if (!Path.GetDirectoryName(Path.GetFullPath(path)).StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(path)) throw new UnauthorizedAccessException(path); + string workingDirectory = GetWorkingDirectory(); + var fullPath = Path.GetDirectoryName(Path.GetFullPath(path)); + var fullPathToCombine = Path.GetDirectoryName(Path.GetFullPath(workingDirectory)); + + if (fullPath == null) + { + throw new DirectoryNotFoundException(); + } + + if (fullPathToCombine == null) + { + throw new DirectoryNotFoundException(); + } + + if (!fullPath.StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(path)) throw new UnauthorizedAccessException(path); if (workingDirectory != null && !Path.IsPathFullyQualified(path)) - path = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(workingDirectory)), path); + path = Path.Combine(fullPathToCombine, path); return File.Exists(path); } @@ -37,9 +50,22 @@ public bool DirectoryExists(string path) throw new SecurityException(SecurityExceptionMessage); var workingDirectory = GetWorkingDirectory(); - if (!Path.GetDirectoryName(Path.GetFullPath(path)).StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(path)) throw new UnauthorizedAccessException(path); + var fullPath = Path.GetDirectoryName(Path.GetFullPath(path)); + var fullPathToCombine = Path.GetDirectoryName(Path.GetFullPath(workingDirectory)); + + if (fullPath == null) + { + throw new DirectoryNotFoundException(); + } + + if (fullPathToCombine == null) + { + throw new DirectoryNotFoundException(); + } + + if (!fullPath.StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(path)) throw new UnauthorizedAccessException(path); if (workingDirectory != null && !Path.IsPathFullyQualified(path)) - path = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(workingDirectory)), path); + path = Path.Combine(fullPathToCombine, path); return Directory.Exists(path); } @@ -49,13 +75,26 @@ public bool DirectoryExists(string path) /// public string CombinePath(params string[] paths) { - var workingDirectory = GetWorkingDirectory(); + string workingDirectory = GetWorkingDirectory(); for (int i = 0; i < paths.Length; i++) { var path = paths[i]; - if (!Path.GetDirectoryName(Path.GetFullPath(path)).StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(path)) throw new UnauthorizedAccessException(path); + var fullPath = Path.GetDirectoryName(Path.GetFullPath(path)); + var fullPathToCombine = Path.GetDirectoryName(Path.GetFullPath(workingDirectory)); + + if (fullPath == null) + { + throw new DirectoryNotFoundException(); + } + + if (fullPathToCombine == null) + { + throw new DirectoryNotFoundException(); + } + + if (!fullPath.StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(path)) throw new UnauthorizedAccessException(path); if (workingDirectory != null && !Path.IsPathFullyQualified(path)) - paths[i] = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(workingDirectory)), path); + paths[i] = Path.Combine(fullPathToCombine, path);; } return Path.Combine(paths); @@ -67,9 +106,22 @@ public string CombinePath(params string[] paths) public string GetExtension(string path) { var workingDirectory = GetWorkingDirectory(); - if (!Path.GetDirectoryName(Path.GetFullPath(path)).StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(path)) throw new UnauthorizedAccessException(path); + var fullPath = Path.GetDirectoryName(Path.GetFullPath(path)); + var fullPathToCombine = Path.GetDirectoryName(Path.GetFullPath(workingDirectory)); + + if (fullPath == null) + { + throw new DirectoryNotFoundException(); + } + + if (fullPathToCombine == null) + { + throw new DirectoryNotFoundException(); + } + + if (!fullPath.StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(path)) throw new UnauthorizedAccessException(path); if (workingDirectory != null && !Path.IsPathFullyQualified(path)) - path = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(workingDirectory)), path); + path = Path.Combine(fullPathToCombine, path); return Path.GetExtension(path); } @@ -80,9 +132,22 @@ public string GetExtension(string path) public string GetFileName(string path) { var workingDirectory = GetWorkingDirectory(); - if (!Path.GetDirectoryName(Path.GetFullPath(path)).StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(path)) throw new UnauthorizedAccessException(path); + var fullPath = Path.GetDirectoryName(Path.GetFullPath(path)); + var fullPathToCombine = Path.GetDirectoryName(Path.GetFullPath(workingDirectory)); + + if (fullPath == null) + { + throw new DirectoryNotFoundException(); + } + + if (fullPathToCombine == null) + { + throw new DirectoryNotFoundException(); + } + + if (!fullPath.StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(path)) throw new UnauthorizedAccessException(path); if (workingDirectory != null && !Path.IsPathFullyQualified(path)) - path = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(workingDirectory)), path); + path = Path.Combine(fullPathToCombine, path); return Path.GetFileName(path); } @@ -93,9 +158,22 @@ public string GetFileName(string path) public string GetFileNameWithoutExtension(string path) { var workingDirectory = GetWorkingDirectory(); - if (!Path.GetDirectoryName(Path.GetFullPath(path)).StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(path)) throw new UnauthorizedAccessException(path); + var fullPath = Path.GetDirectoryName(Path.GetFullPath(path)); + var fullPathToCombine = Path.GetDirectoryName(Path.GetFullPath(workingDirectory)); + + if (fullPath == null) + { + throw new DirectoryNotFoundException(); + } + + if (fullPathToCombine == null) + { + throw new DirectoryNotFoundException(); + } + + if (!fullPath.StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(path)) throw new UnauthorizedAccessException(path); if (workingDirectory != null && !Path.IsPathFullyQualified(path)) - path = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(workingDirectory)), path); + path = Path.Combine(fullPathToCombine, path); return Path.GetFileNameWithoutExtension(path); } @@ -106,9 +184,22 @@ public string GetFileNameWithoutExtension(string path) public string GetFullPath(string path) { var workingDirectory = GetWorkingDirectory(); - if (!Path.GetDirectoryName(Path.GetFullPath(path)).StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(path)) throw new UnauthorizedAccessException(path); + var fullPath = Path.GetDirectoryName(Path.GetFullPath(path)); + var fullPathToCombine = Path.GetDirectoryName(Path.GetFullPath(workingDirectory)); + + if (fullPath == null) + { + throw new DirectoryNotFoundException(); + } + + if (fullPathToCombine == null) + { + throw new DirectoryNotFoundException(); + } + + if (!fullPath.StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(path)) throw new UnauthorizedAccessException(path); if (workingDirectory != null && !Path.IsPathFullyQualified(path)) - path = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(workingDirectory)), path); + path = Path.Combine(fullPathToCombine, path); return Path.GetFullPath(path); } diff --git a/Obsidian.API/_Types/ClickComponent.cs b/Obsidian.API/_Types/ClickComponent.cs index 6d2254f00..3b527c012 100644 --- a/Obsidian.API/_Types/ClickComponent.cs +++ b/Obsidian.API/_Types/ClickComponent.cs @@ -7,5 +7,12 @@ public class ClickComponent public string Value { get; set; } public string Translate { get; set; } + + public ClickComponent(EClickAction action, string value, string translate) + { + Action = action; + Value = value; + Translate = translate; + } } } diff --git a/Obsidian.API/_Types/HoverComponent.cs b/Obsidian.API/_Types/HoverComponent.cs index f896248bd..73da3ba2b 100644 --- a/Obsidian.API/_Types/HoverComponent.cs +++ b/Obsidian.API/_Types/HoverComponent.cs @@ -7,5 +7,12 @@ public class HoverComponent public object Contents { get; set; } public string Translate { get; set; } + + public HoverComponent(EHoverAction action, object contents, string translate) + { + Action = action; + Contents = contents; + Translate = translate; + } } } diff --git a/Obsidian/Commands/MainCommandModule.cs b/Obsidian/Commands/MainCommandModule.cs index 851d91675..541aace9b 100644 --- a/Obsidian/Commands/MainCommandModule.cs +++ b/Obsidian/Commands/MainCommandModule.cs @@ -370,7 +370,8 @@ await Task.Run(() => [Command("time")] [CommandInfo("Sets declared time", "/time ")] [IssuerScope(CommandIssuers.Client)] - public async Task TimeAsync(CommandContext Context) => TimeAsync(Context, 1337); + public async Task TimeAsync(CommandContext Context) => await TimeAsync(Context, 1337); + [CommandOverload] public async Task TimeAsync(CommandContext Context,int time) { diff --git a/Obsidian/WorldData/BlockUpdates.cs b/Obsidian/WorldData/BlockUpdates.cs index 18e4256be..25ee36883 100644 --- a/Obsidian/WorldData/BlockUpdates.cs +++ b/Obsidian/WorldData/BlockUpdates.cs @@ -9,19 +9,24 @@ internal static class BlockUpdates { internal static async Task HandleFallingBlock(BlockUpdate blockUpdate) { - if (blockUpdate.block is null) { return false; } - var world = blockUpdate.world; - var location = blockUpdate.position; - var material = blockUpdate.block.Value.Material; - if (world.GetBlock(location + Vector.Down) is Block below && (Block.Replaceable.Contains(below.Material) || below.IsFluid)) + return await Task.Run(() => { - world.SetBlock(location, Block.Air); - world.SpawnFallingBlock(location, material); - return true; - } - return false; + if (blockUpdate.block is null) { return false; } + var world = blockUpdate.world; + var location = blockUpdate.position; + var material = blockUpdate.block.Value.Material; + if (world.GetBlock(location + Vector.Down) is Block below && (Block.Replaceable.Contains(below.Material) || below.IsFluid)) + { + world.SetBlock(location, Block.Air); + world.SpawnFallingBlock(location, material); + return true; + } + return false; + }); } + // TODO: This method will need to be implemented as above if it is going to be declared async + // HenryMigo 30/10/2021 internal static async Task HandleLiquidPhysics(BlockUpdate blockUpdate) { if (blockUpdate.block is null) { return false; } @@ -30,7 +35,7 @@ internal static async Task HandleLiquidPhysics(BlockUpdate blockUpdate) var location = blockUpdate.position; int state = block.State; Vector belowPos = location + Vector.Down; - + // Handle the initial search for closet path downwards. // Just going to do a crappy pathfind for now. We can do // proper pathfinding some other time. diff --git a/Obsidian/WorldData/Generators/Overworld/Terrain/OverworldTerrain.cs b/Obsidian/WorldData/Generators/Overworld/Terrain/OverworldTerrain.cs index f5149c4c7..f2255908e 100644 --- a/Obsidian/WorldData/Generators/Overworld/Terrain/OverworldTerrain.cs +++ b/Obsidian/WorldData/Generators/Overworld/Terrain/OverworldTerrain.cs @@ -20,8 +20,6 @@ public class OverworldTerrain private Module FinalBiomes; - - public OverworldTerrain(bool isUnitTest = false) { settings = OverworldGenerator.GeneratorSettings; From 9ffdc8d76f5952f4b983c6b58eff93cefba566c6 Mon Sep 17 00:00:00 2001 From: Henry Migo Date: Sat, 30 Oct 2021 15:26:45 +0100 Subject: [PATCH 07/15] Fix for constructure initiation --- Obsidian.API/Noise/Blur.cs | 5 +-- Obsidian.API/Noise/Interpolate.cs | 5 +-- Obsidian.API/_Types/ClickComponent.cs | 2 +- Obsidian.API/_Types/HoverComponent.cs | 2 +- Obsidian/Commands/MainCommandModule.cs | 41 +++++++++++-------- .../Overworld/Terrain/OverworldTerrain.cs | 10 ++--- 6 files changed, 34 insertions(+), 31 deletions(-) diff --git a/Obsidian.API/Noise/Blur.cs b/Obsidian.API/Noise/Blur.cs index c240788b7..c8a364d7f 100644 --- a/Obsidian.API/Noise/Blur.cs +++ b/Obsidian.API/Noise/Blur.cs @@ -29,11 +29,10 @@ public override double GetValue(double x, double y, double z) { // Bitshift the source module by 1 one so we can // "divide" each pixel into 4 quadrants - var shifted = new BitShiftInput + var shifted = new BitShiftInput(this.Source0) { Amount = 1, - Left = false, - Source0 = this.Source0 + Left = false }; var self = shifted.GetValue(x, y, z); diff --git a/Obsidian.API/Noise/Interpolate.cs b/Obsidian.API/Noise/Interpolate.cs index 405752bce..c31b8feb2 100644 --- a/Obsidian.API/Noise/Interpolate.cs +++ b/Obsidian.API/Noise/Interpolate.cs @@ -16,11 +16,10 @@ public override double GetValue(double x, double y, double z) { // Bitshift the source module by 1 one so we can // "divide" each pixel into 4 quadrants - var shifted = new BitShiftInput + var shifted = new BitShiftInput(this.Source0) { Amount = 1, - Left = false, - Source0 = this.Source0 + Left = false }; var center = shifted.GetValue(x, y, z); diff --git a/Obsidian.API/_Types/ClickComponent.cs b/Obsidian.API/_Types/ClickComponent.cs index 3b527c012..d110dc9c8 100644 --- a/Obsidian.API/_Types/ClickComponent.cs +++ b/Obsidian.API/_Types/ClickComponent.cs @@ -8,7 +8,7 @@ public class ClickComponent public string Translate { get; set; } - public ClickComponent(EClickAction action, string value, string translate) + public ClickComponent(EClickAction action, string value, string translate = "") { Action = action; Value = value; diff --git a/Obsidian.API/_Types/HoverComponent.cs b/Obsidian.API/_Types/HoverComponent.cs index 73da3ba2b..39b6b4f8e 100644 --- a/Obsidian.API/_Types/HoverComponent.cs +++ b/Obsidian.API/_Types/HoverComponent.cs @@ -8,7 +8,7 @@ public class HoverComponent public string Translate { get; set; } - public HoverComponent(EHoverAction action, object contents, string translate) + public HoverComponent(EHoverAction action, object contents, string translate = "") { Action = action; Contents = contents; diff --git a/Obsidian/Commands/MainCommandModule.cs b/Obsidian/Commands/MainCommandModule.cs index 541aace9b..444184fc5 100644 --- a/Obsidian/Commands/MainCommandModule.cs +++ b/Obsidian/Commands/MainCommandModule.cs @@ -75,15 +75,15 @@ public async Task HelpAsync(CommandContext Context, int page) { Text = $"\n{ChatColor.Gold}{usage}", ClickEvent = new ClickComponent - { - Action = EClickAction.SuggestCommand, - Value = usage.Contains(' ') ? $"{usage.Substring(0, usage.IndexOf(' '))} " : usage - }, + ( + EClickAction.SuggestCommand, + usage.Contains(' ') ? $"{usage.Substring(0, usage.IndexOf(' '))} " : usage + ), HoverEvent = new HoverComponent - { - Action = EHoverAction.ShowText, - Contents = $"Click to suggest the command" - } + ( + EHoverAction.ShowText, + $"Click to suggest the command" + ) }; commands.AddExtra(commandName); @@ -142,9 +142,14 @@ public async Task PluginsAsync(CommandContext Context) plugin.Text = pluginContainer.Info.Name; plugin.Color = colorByState; - plugin.HoverEvent = new HoverComponent { Action = EHoverAction.ShowText, Contents = $"{colorByState}{info.Name}{ChatColor.Reset}\nVersion: {colorByState}{info.Version}{ChatColor.Reset}\nAuthor(s): {colorByState}{info.Authors}{ChatColor.Reset}" }; + plugin.HoverEvent = new HoverComponent + ( + EHoverAction.ShowText, + $"{colorByState}{info.Name}{ChatColor.Reset}\nVersion: {colorByState}{info.Version}{ChatColor.Reset}\nAuthor(s): {colorByState}{info.Authors}{ChatColor.Reset}" + ); + if (pluginContainer.Info.ProjectUrl != null) - plugin.ClickEvent = new ClickComponent { Action = EClickAction.OpenUrl, Value = pluginContainer.Info.ProjectUrl.AbsoluteUri }; + plugin.ClickEvent = new ClickComponent (EClickAction.OpenUrl, pluginContainer.Info.ProjectUrl.AbsoluteUri); messages.Add(plugin); @@ -462,15 +467,15 @@ private ChatMessage SendCommandUsage(string commandUsage) { Text = $"{ChatColor.Red}{commandUsage}", ClickEvent = new ClickComponent - { - Action = EClickAction.SuggestCommand, - Value = $"{commandSuggest}" - }, + ( + EClickAction.SuggestCommand, + $"{commandSuggest}" + ), HoverEvent = new HoverComponent - { - Action = EHoverAction.ShowText, - Contents = $"Click to suggest the command" - } + ( + EHoverAction.ShowText, + $"Click to suggest the command" + ) }; var prefix = new ChatMessage diff --git a/Obsidian/WorldData/Generators/Overworld/Terrain/OverworldTerrain.cs b/Obsidian/WorldData/Generators/Overworld/Terrain/OverworldTerrain.cs index f2255908e..f64d7381d 100644 --- a/Obsidian/WorldData/Generators/Overworld/Terrain/OverworldTerrain.cs +++ b/Obsidian/WorldData/Generators/Overworld/Terrain/OverworldTerrain.cs @@ -117,15 +117,15 @@ public OverworldTerrain(bool isUnitTest = false) } }; - Module scaled = new Blend - { - Distance = 2, - Source0 = new TerrainSelect + Module scaled = new Blend( + new TerrainSelect { BiomeSelector = FinalBiomes, Control = biomeTransitionSel2, TerrainModules = biomesMap, - } + }) + { + Distance = 2 }; if (isUnitTest) From 8f13d29ba605d39eebf2c46a7e2104441bb62ec5 Mon Sep 17 00:00:00 2001 From: Henry Migo Date: Sat, 30 Oct 2021 16:41:54 +0100 Subject: [PATCH 08/15] Addressed couple hunderd warnings, 3692 relate to XML out of the 3708 total. 16 are other warnings. --- Obsidian.API/Noise/Blur.cs | 4 +- Obsidian.API/Noise/FuncRunner.cs | 5 +- Obsidian.API/Noise/FuncSelector.cs | 6 +- Obsidian.API/Noise/Interpolate.cs | 4 +- Obsidian.API/Noise/Polariaze.cs | 4 +- Obsidian.API/Noise/TerrainSelect.cs | 3 +- Obsidian.API/Noise/TransitionMap.cs | 5 +- Obsidian.API/Noise/Zoom.cs | 5 +- Obsidian.API/Particles/ItemParticle.cs | 5 + Obsidian.API/Plugins/DependencyAttribute.cs | 6 + Obsidian.API/Plugins/PluginAttribute.cs | 9 + Obsidian.API/Plugins/PluginBase.cs | 36 ++- Obsidian.API/Plugins/PluginWrapper.cs | 23 +- Obsidian.API/Plugins/Services/IDiagnoser.cs | 2 +- Obsidian.API/Plugins/Services/IFileReader.cs | 34 ++- Obsidian.API/Plugins/Services/IFileWriter.cs | 118 ++++++++-- Obsidian.API/Plugins/Services/ILogger.cs | 9 +- .../Plugins/Services/IO/IFileService.cs | 2 +- .../_Attributes/RequirePermissionAttribute.cs | 5 + .../_Types/Advancements/Advancement.cs | 9 + .../_Types/Advancements/AdvancementDisplay.cs | 12 + .../_Types/Advancements/AdvancementReward.cs | 7 + Obsidian.API/_Types/ChatMessage.cs | 22 ++ .../_Types/Inventory/ItemMetaBuilder.cs | 4 +- Obsidian.API/_Types/Score.cs | 6 + Obsidian.API/_Types/ScoreboardObjective.cs | 7 + Obsidian.Tests/Noise.cs | 50 ++-- Obsidian/Plugins/PluginContainer.cs | 2 +- Obsidian/Scoreboard.cs | 16 +- Obsidian/Utilities/RentedArray.cs | 8 +- Obsidian/WorldData/BlockUpdates.cs | 219 +++++++++--------- .../Overworld/Terrain/OverworldTerrain.cs | 11 +- Obsidian/WorldData/RegionFile.cs | 2 +- Obsidian/WorldData/World.cs | 9 +- SamplePlugin/SamplePlugin.cs | 8 +- 35 files changed, 456 insertions(+), 221 deletions(-) diff --git a/Obsidian.API/Noise/Blur.cs b/Obsidian.API/Noise/Blur.cs index c8a364d7f..8d9fba872 100644 --- a/Obsidian.API/Noise/Blur.cs +++ b/Obsidian.API/Noise/Blur.cs @@ -13,9 +13,9 @@ public class Blur : Module /// /// ctor. /// - public Blur() : base(1) + public Blur(Module source0) : base(1) { - + Source0 = source0; } /// diff --git a/Obsidian.API/Noise/FuncRunner.cs b/Obsidian.API/Noise/FuncRunner.cs index 36153e0ab..03cefa86d 100644 --- a/Obsidian.API/Noise/FuncRunner.cs +++ b/Obsidian.API/Noise/FuncRunner.cs @@ -11,9 +11,10 @@ public class FuncRunner : Module public int Utility { get; set; } = 0; - public FuncRunner() : base(1) + public FuncRunner(Module source0, Func conditionFunction) : base(1) { - + Source0 = source0; + ConditionFunction = conditionFunction; } public override double GetValue(double x, double y, double z) diff --git a/Obsidian.API/Noise/FuncSelector.cs b/Obsidian.API/Noise/FuncSelector.cs index c984f8098..e7ad6a096 100644 --- a/Obsidian.API/Noise/FuncSelector.cs +++ b/Obsidian.API/Noise/FuncSelector.cs @@ -26,9 +26,11 @@ public class FuncSelector : Module /// /// Ctor. /// - public FuncSelector() : base(2) + public FuncSelector(Module source0, Module source1, Func<(double, double, double), int> conditionFunction) : base(2) { - + Source0 = source0; + Source1 = source1; + ConditionFunction = conditionFunction; } /// diff --git a/Obsidian.API/Noise/Interpolate.cs b/Obsidian.API/Noise/Interpolate.cs index c31b8feb2..9b0f69281 100644 --- a/Obsidian.API/Noise/Interpolate.cs +++ b/Obsidian.API/Noise/Interpolate.cs @@ -7,9 +7,9 @@ public class Interpolate : Module { public Module Source0 { get; set; } - public Interpolate() : base(1) + public Interpolate(Module source0) : base(1) { - + Source0 = source0; } public override double GetValue(double x, double y, double z) diff --git a/Obsidian.API/Noise/Polariaze.cs b/Obsidian.API/Noise/Polariaze.cs index 593ec5fbb..d2e9f7afd 100644 --- a/Obsidian.API/Noise/Polariaze.cs +++ b/Obsidian.API/Noise/Polariaze.cs @@ -8,9 +8,9 @@ public class Polariaze : Module public double Center { get; set; } = 0; - public Polariaze() : base(1) + public Polariaze(Module source0) : base(1) { - + Source0 = source0; } public override double GetValue(double x, double y, double z) diff --git a/Obsidian.API/Noise/TerrainSelect.cs b/Obsidian.API/Noise/TerrainSelect.cs index 51717e880..65ba39e67 100644 --- a/Obsidian.API/Noise/TerrainSelect.cs +++ b/Obsidian.API/Noise/TerrainSelect.cs @@ -9,9 +9,10 @@ public class TerrainSelect : SharpNoise.Modules.Blend public Module BiomeSelector { get; set; } - public TerrainSelect() + public TerrainSelect(Module biomeSelector) { Source1 = new Constant { ConstantValue = 0 }; + BiomeSelector = biomeSelector; } public override double GetValue(double x, double y, double z) diff --git a/Obsidian.API/Noise/TransitionMap.cs b/Obsidian.API/Noise/TransitionMap.cs index 24baedff5..91078ac33 100644 --- a/Obsidian.API/Noise/TransitionMap.cs +++ b/Obsidian.API/Noise/TransitionMap.cs @@ -16,9 +16,10 @@ public class TransitionMap : Module /// /// ctor. /// - public TransitionMap() : base(1) + public TransitionMap(Module source0, int distance) : base (1) { - + Source0 = source0; + Distance = distance; } /// diff --git a/Obsidian.API/Noise/Zoom.cs b/Obsidian.API/Noise/Zoom.cs index 576cc88f6..34dbdb1c5 100644 --- a/Obsidian.API/Noise/Zoom.cs +++ b/Obsidian.API/Noise/Zoom.cs @@ -8,9 +8,10 @@ public class Zoom : Module public double Amount { get; set; } - public Zoom() : base(1) + public Zoom(Module source0, double amount) : base(1) { - + Source0 = source0; + Amount = amount; } public override double GetValue(double x, double y, double z) diff --git a/Obsidian.API/Particles/ItemParticle.cs b/Obsidian.API/Particles/ItemParticle.cs index 5dfcab007..376255c4a 100644 --- a/Obsidian.API/Particles/ItemParticle.cs +++ b/Obsidian.API/Particles/ItemParticle.cs @@ -2,6 +2,11 @@ { public class ItemParticle : IParticle { + public ItemParticle(ItemStack item) + { + Item = item; + } + public int Id => 36; public ItemStack Item { get; set; } diff --git a/Obsidian.API/Plugins/DependencyAttribute.cs b/Obsidian.API/Plugins/DependencyAttribute.cs index 929b197a3..e3e61f753 100644 --- a/Obsidian.API/Plugins/DependencyAttribute.cs +++ b/Obsidian.API/Plugins/DependencyAttribute.cs @@ -8,6 +8,12 @@ namespace Obsidian.API.Plugins [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = false)] public class DependencyAttribute : Attribute { + public DependencyAttribute(string minVersion, bool optional) + { + Optional = optional; + MinVersion = minVersion; + } + /// /// Indicates whether the plugin can run without this dependency. /// diff --git a/Obsidian.API/Plugins/PluginAttribute.cs b/Obsidian.API/Plugins/PluginAttribute.cs index c2d89141e..171d83ac0 100644 --- a/Obsidian.API/Plugins/PluginAttribute.cs +++ b/Obsidian.API/Plugins/PluginAttribute.cs @@ -8,6 +8,15 @@ namespace Obsidian.API.Plugins [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] public class PluginAttribute : Attribute { + public PluginAttribute(string name, string version, string authors, string description, string projectUrl) + { + Name = name; + Version = version; + Authors = authors; + Description = description; + ProjectUrl = projectUrl; + } + /// /// Name of the plugin. /// diff --git a/Obsidian.API/Plugins/PluginBase.cs b/Obsidian.API/Plugins/PluginBase.cs index d9f366f34..940e6a8d2 100644 --- a/Obsidian.API/Plugins/PluginBase.cs +++ b/Obsidian.API/Plugins/PluginBase.cs @@ -20,6 +20,18 @@ public abstract class PluginBase private Type typeCache; + public PluginBase(Type TypeCache) + { + typeCache = TypeCache; + } + +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + public PluginBase() +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + { + + } + public void RegisterCommand(Action action) { registerSingleCommand(action); @@ -31,7 +43,7 @@ public void RegisterCommand(Action action) public object? Invoke(string methodName, params object[] args) { var method = GetMethod(methodName, args); - return method.Invoke(this, args); + return method?.Invoke(this, args); } /// @@ -46,12 +58,12 @@ public Task FriendlyInvokeAsync(string methodName, params object[] args) args = args.Take(parameterCount).ToArray(); try { - var result = method.Invoke(this, args); - if (result is Task task) - return task; - else if (result is ValueTask valueTask) - return valueTask.AsTask(); - return Task.FromResult(result); + var result = method?.Invoke(this, args); + if (result is Task task) + return task; + else if (result is ValueTask valueTask) + return valueTask.AsTask(); + return Task.FromResult(result); } catch (Exception e) { @@ -66,7 +78,7 @@ public Task FriendlyInvokeAsync(string methodName, params object[] args) public Task InvokeAsync(string methodName, params object[] args) { var method = GetMethod(methodName, args); - var result = method.Invoke(this, args); + var result = method?.Invoke(this, args); if (result is Task task) return task; else if (result is ValueTask valueTask) @@ -80,7 +92,7 @@ public Task InvokeAsync(string methodName, params object[] args) public T? Invoke(string methodName, params object[] args) { var method = GetMethod(methodName, args); - return (T?)method.Invoke(this, args); + return (T?)method?.Invoke(this, args); } /// @@ -90,7 +102,7 @@ public Task InvokeAsync(string methodName, params object[] args) public Task InvokeAsync(string methodName, params object[] args) { var method = GetMethod(methodName, args); - var result = method.Invoke(this, args); + var result = method?.Invoke(this, args); if (result is Task task) return task; else if (result is ValueTask valueTask) @@ -137,7 +149,7 @@ protected void Unload() args = args.Take(parameterCount).ToArray(); try { - return method.Invoke(this, args); + return method?.Invoke(this, args); } catch (Exception e) { @@ -175,7 +187,7 @@ protected void Unload() } } - private MethodInfo GetMethod(string methodName, object[] args) + private MethodInfo? GetMethod(string methodName, object[] args) { args ??= Array.Empty(); var types = new Type[args.Length]; diff --git a/Obsidian.API/Plugins/PluginWrapper.cs b/Obsidian.API/Plugins/PluginWrapper.cs index 3ea00f3bd..278284936 100644 --- a/Obsidian.API/Plugins/PluginWrapper.cs +++ b/Obsidian.API/Plugins/PluginWrapper.cs @@ -7,9 +7,16 @@ namespace Obsidian.API.Plugins /// public abstract class PluginWrapper { - internal PluginBase plugin; + internal PluginBase Plugin; + public PluginWrapper(PluginBase plugin) + { + Plugin = plugin; + } + +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. public PluginWrapper() +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. { } @@ -17,17 +24,17 @@ public PluginWrapper() /// /// Invokes a method in the class. For repeated calls use GetMethod or make a plugin wrapper. /// - public object Invoke(string methodName, params object[] args) + public object? Invoke(string methodName, params object[] args) { - return plugin.Invoke(methodName, args); + return Plugin.Invoke(methodName, args); } /// /// Invokes a method in the class. For repeated calls use GetMethod or make a plugin wrapper. /// - public T Invoke(string methodName, params object[] args) + public T? Invoke(string methodName, params object[] args) { - return plugin.Invoke(methodName, args); + return Plugin.Invoke(methodName, args); } /// @@ -35,7 +42,7 @@ public T Invoke(string methodName, params object[] args) /// public T GetMethod(string methodName, params Type[] parameterTypes) where T : Delegate { - return plugin.GetMethod(methodName, parameterTypes); + return Plugin.GetMethod(methodName, parameterTypes); } /// @@ -43,7 +50,7 @@ public T GetMethod(string methodName, params Type[] parameterTypes) where T : /// public Func GetPropertyGetter(string propertyName) { - return plugin.GetPropertyGetter(propertyName); + return Plugin.GetPropertyGetter(propertyName); } /// @@ -51,7 +58,7 @@ public Func GetPropertyGetter(string propertyName) /// public Action GetPropertySetter(string propertyName) { - return plugin.GetPropertySetter(propertyName); + return Plugin.GetPropertySetter(propertyName); } } } diff --git a/Obsidian.API/Plugins/Services/IDiagnoser.cs b/Obsidian.API/Plugins/Services/IDiagnoser.cs index 86cc605f7..2d39b1414 100644 --- a/Obsidian.API/Plugins/Services/IDiagnoser.cs +++ b/Obsidian.API/Plugins/Services/IDiagnoser.cs @@ -31,7 +31,7 @@ public interface IDiagnoser : ISecuredService /// Indicates whether to start the process in a new window. /// Indicates whether to use the operating system shell to start the process. /// A new that is associated with the process resource, or null if no process resource is started. - public IProcess StartProcess(string fileName, string arguments = null, bool createWindow = true, bool useShell = false); + public IProcess StartProcess(string fileName, string arguments = "", bool createWindow = true, bool useShell = false); /// /// Returns a new instance of . diff --git a/Obsidian.API/Plugins/Services/IFileReader.cs b/Obsidian.API/Plugins/Services/IFileReader.cs index e731fafb9..4d0fa541a 100644 --- a/Obsidian.API/Plugins/Services/IFileReader.cs +++ b/Obsidian.API/Plugins/Services/IFileReader.cs @@ -64,9 +64,22 @@ public string[] GetDirectoryFiles(string path) throw new SecurityException(SecurityExceptionMessage); var workingDirectory = GetWorkingDirectory(); - if (!Path.GetDirectoryName(Path.GetFullPath(path)).StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(path)) throw new UnauthorizedAccessException(path); + var fullPath = Path.GetDirectoryName(Path.GetFullPath(path)); + var fullPathToCombine = Path.GetDirectoryName(Path.GetFullPath(workingDirectory)); + + if (fullPath == null) + { + throw new DirectoryNotFoundException(); + } + + if (fullPathToCombine == null) + { + throw new DirectoryNotFoundException(); + } + + if (!fullPath.StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(path)) throw new UnauthorizedAccessException(path); if (workingDirectory != null && !Path.IsPathFullyQualified(path)) - path = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(workingDirectory)), path); + path = Path.Combine(fullPathToCombine, path); return Directory.GetFiles(path); } @@ -81,9 +94,22 @@ public string[] GetSubdirectories(string path) throw new SecurityException(SecurityExceptionMessage); var workingDirectory = GetWorkingDirectory(); - if (!Path.GetDirectoryName(Path.GetFullPath(path)).StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(path)) throw new UnauthorizedAccessException(path); + var fullPath = Path.GetDirectoryName(Path.GetFullPath(path)); + var fullPathToCombine = Path.GetDirectoryName(Path.GetFullPath(workingDirectory)); + + if (fullPath == null) + { + throw new DirectoryNotFoundException(); + } + + if (fullPathToCombine == null) + { + throw new DirectoryNotFoundException(); + } + + if (!fullPath.StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(path)) throw new UnauthorizedAccessException(path); if (workingDirectory != null && !Path.IsPathFullyQualified(path)) - path = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(workingDirectory)), path); + path = Path.Combine(fullPathToCombine, path); return Directory.GetDirectories(path); } diff --git a/Obsidian.API/Plugins/Services/IFileWriter.cs b/Obsidian.API/Plugins/Services/IFileWriter.cs index 394533792..43af91404 100644 --- a/Obsidian.API/Plugins/Services/IFileWriter.cs +++ b/Obsidian.API/Plugins/Services/IFileWriter.cs @@ -76,9 +76,22 @@ public void CreateFile(string path) throw new SecurityException(SecurityExceptionMessage); var workingDirectory = GetWorkingDirectory(); - if (!Path.GetDirectoryName(Path.GetFullPath(path)).StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(path)) throw new UnauthorizedAccessException(path); + var fullPath = Path.GetDirectoryName(Path.GetFullPath(path)); + var fullPathToCombine = Path.GetDirectoryName(Path.GetFullPath(workingDirectory)); + + if (fullPath == null) + { + throw new DirectoryNotFoundException(); + } + + if (fullPathToCombine == null) + { + throw new DirectoryNotFoundException(); + } + + if (!fullPath.StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(path)) throw new UnauthorizedAccessException(path); if (workingDirectory != null && !Path.IsPathFullyQualified(path)) - path = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(workingDirectory)), path); + path = Path.Combine(fullPathToCombine, path); File.Create(path).Close(); } @@ -92,14 +105,30 @@ public void CopyFile(string sourceFileName, string destinationFileName) if (!IsUsable) throw new SecurityException(SecurityExceptionMessage); - var workingDirectory = GetWorkingDirectory(); - if (!Path.GetDirectoryName(Path.GetFullPath(sourceFileName)).StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(sourceFileName)) throw new UnauthorizedAccessException(sourceFileName); + string workingDirectory = GetWorkingDirectory(); + var fullPath1 = Path.GetDirectoryName(Path.GetFullPath(sourceFileName)); + var fullPath2 = Path.GetDirectoryName(Path.GetFullPath(destinationFileName)); + var fullPathToCombine = Path.GetDirectoryName(Path.GetFullPath(workingDirectory)); + + if (fullPath1 == null || fullPath2 == null) + { + throw new DirectoryNotFoundException(); + } + + if (fullPathToCombine == null) + { + throw new DirectoryNotFoundException(); + } + + if (!fullPath1.StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(sourceFileName)) throw new UnauthorizedAccessException(sourceFileName); if (workingDirectory != null && !Path.IsPathFullyQualified(sourceFileName)) - sourceFileName = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(workingDirectory)), sourceFileName); + sourceFileName = Path.Combine(fullPathToCombine, sourceFileName); + + workingDirectory = GetWorkingDirectory(); - if (!Path.GetDirectoryName(Path.GetFullPath(destinationFileName)).StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(destinationFileName)) throw new UnauthorizedAccessException(destinationFileName); + if (!fullPath2.StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(destinationFileName)) throw new UnauthorizedAccessException(destinationFileName); if (workingDirectory != null && !Path.IsPathFullyQualified(destinationFileName)) - destinationFileName = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(workingDirectory)), destinationFileName); + destinationFileName = Path.Combine(fullPathToCombine, destinationFileName); File.Copy(sourceFileName, destinationFileName, overwrite: true); } @@ -114,13 +143,29 @@ public void MoveFile(string sourceFileName, string destinationFileName) throw new SecurityException(SecurityExceptionMessage); var workingDirectory = GetWorkingDirectory(); - if (!Path.GetDirectoryName(Path.GetFullPath(sourceFileName)).StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(sourceFileName)) throw new UnauthorizedAccessException(sourceFileName); + var fullPath1 = Path.GetDirectoryName(Path.GetFullPath(sourceFileName)); + var fullPath2 = Path.GetDirectoryName(Path.GetFullPath(destinationFileName)); + var fullPathToCombine = Path.GetDirectoryName(Path.GetFullPath(workingDirectory)); + + if (fullPath1 == null || fullPath2 == null) + { + throw new DirectoryNotFoundException(); + } + + if (fullPathToCombine == null) + { + throw new DirectoryNotFoundException(); + } + + if (!fullPath1.StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(sourceFileName)) throw new UnauthorizedAccessException(sourceFileName); if (workingDirectory != null && !Path.IsPathFullyQualified(sourceFileName)) - sourceFileName = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(workingDirectory)), sourceFileName); + sourceFileName = Path.Combine(fullPathToCombine, sourceFileName); - if (!Path.GetDirectoryName(Path.GetFullPath(destinationFileName)).StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(destinationFileName)) throw new UnauthorizedAccessException(destinationFileName); + workingDirectory = GetWorkingDirectory(); + + if (!fullPath2.StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(destinationFileName)) throw new UnauthorizedAccessException(destinationFileName); if (workingDirectory != null && !Path.IsPathFullyQualified(destinationFileName)) - destinationFileName = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(workingDirectory)), destinationFileName); + destinationFileName = Path.Combine(fullPathToCombine, destinationFileName); File.Move(sourceFileName, destinationFileName); } @@ -135,9 +180,22 @@ public void DeleteFile(string path) throw new SecurityException(SecurityExceptionMessage); var workingDirectory = GetWorkingDirectory(); - if (!Path.GetDirectoryName(Path.GetFullPath(path)).StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(path)) throw new UnauthorizedAccessException(path); + var fullPath = Path.GetDirectoryName(Path.GetFullPath(path)); + var fullPathToCombine = Path.GetDirectoryName(Path.GetFullPath(workingDirectory)); + + if (fullPath == null) + { + throw new DirectoryNotFoundException(); + } + + if (fullPathToCombine == null) + { + throw new DirectoryNotFoundException(); + } + + if (!fullPath.StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(path)) throw new UnauthorizedAccessException(path); if (workingDirectory != null && !Path.IsPathFullyQualified(path)) - path = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(workingDirectory)), path); + path = Path.Combine(fullPathToCombine, path); File.Delete(path); } @@ -152,9 +210,22 @@ public void CreateDirectory(string path) throw new SecurityException(SecurityExceptionMessage); var workingDirectory = GetWorkingDirectory(); - if (!Path.GetDirectoryName(Path.GetFullPath(path)).StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(path)) throw new UnauthorizedAccessException(path); + var fullPath = Path.GetDirectoryName(Path.GetFullPath(path)); + var fullPathToCombine = Path.GetDirectoryName(Path.GetFullPath(workingDirectory)); + + if (fullPath == null) + { + throw new DirectoryNotFoundException(); + } + + if (fullPathToCombine == null) + { + throw new DirectoryNotFoundException(); + } + + if (!fullPath.StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(path)) throw new UnauthorizedAccessException(path); if (workingDirectory != null && !Path.IsPathFullyQualified(path)) - path = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(workingDirectory)), path); + path = Path.Combine(fullPathToCombine, path); Directory.CreateDirectory(path); } @@ -169,9 +240,22 @@ public void DeleteDirectory(string path) throw new SecurityException(SecurityExceptionMessage); var workingDirectory = GetWorkingDirectory(); - if (!Path.GetDirectoryName(Path.GetFullPath(path)).StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(path)) throw new UnauthorizedAccessException(path); + var fullPath = Path.GetDirectoryName(Path.GetFullPath(path)); + var fullPathToCombine = Path.GetDirectoryName(Path.GetFullPath(workingDirectory)); + + if (fullPath == null) + { + throw new DirectoryNotFoundException(); + } + + if (fullPathToCombine == null) + { + throw new DirectoryNotFoundException(); + } + + if (!fullPath.StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(path)) throw new UnauthorizedAccessException(path); if (workingDirectory != null && !Path.IsPathFullyQualified(path)) - path = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(workingDirectory)), path); + path = Path.Combine(fullPathToCombine, path); Directory.Delete(path, recursive: true); } diff --git a/Obsidian.API/Plugins/Services/ILogger.cs b/Obsidian.API/Plugins/Services/ILogger.cs index 29ded56dd..919eecfdf 100644 --- a/Obsidian.API/Plugins/Services/ILogger.cs +++ b/Obsidian.API/Plugins/Services/ILogger.cs @@ -53,7 +53,14 @@ public void LogTrace(string message) public void LogTrace(T exception) where T : Exception { Log($"{nameof(T)}: {exception.Message}"); - Log(exception.StackTrace); + if (exception.StackTrace != null) + { + Log(exception.StackTrace); + } + else + { + Log("No stack trace..."); + } } } } diff --git a/Obsidian.API/Plugins/Services/IO/IFileService.cs b/Obsidian.API/Plugins/Services/IO/IFileService.cs index 39149e4da..2905d9b9f 100644 --- a/Obsidian.API/Plugins/Services/IO/IFileService.cs +++ b/Obsidian.API/Plugins/Services/IO/IFileService.cs @@ -75,10 +75,10 @@ public bool DirectoryExists(string path) /// public string CombinePath(params string[] paths) { - string workingDirectory = GetWorkingDirectory(); for (int i = 0; i < paths.Length; i++) { var path = paths[i]; + var workingDirectory = GetWorkingDirectory(); var fullPath = Path.GetDirectoryName(Path.GetFullPath(path)); var fullPathToCombine = Path.GetDirectoryName(Path.GetFullPath(workingDirectory)); diff --git a/Obsidian.API/_Attributes/RequirePermissionAttribute.cs b/Obsidian.API/_Attributes/RequirePermissionAttribute.cs index 591baf91e..0399fb7f9 100644 --- a/Obsidian.API/_Attributes/RequirePermissionAttribute.cs +++ b/Obsidian.API/_Attributes/RequirePermissionAttribute.cs @@ -19,6 +19,11 @@ public RequirePermissionAttribute(PermissionCheckType checkType = PermissionChec public override Task RunChecksAsync(CommandContext context) { + if (context.Player == null) + { + throw new Exception("Player not found"); + } + if(context.Sender.Issuer == CommandIssuers.Console) return Task.FromResult(true); if (this.op && context.Player.IsOperator) diff --git a/Obsidian.API/_Types/Advancements/Advancement.cs b/Obsidian.API/_Types/Advancements/Advancement.cs index dded80031..917ea4528 100644 --- a/Obsidian.API/_Types/Advancements/Advancement.cs +++ b/Obsidian.API/_Types/Advancements/Advancement.cs @@ -4,6 +4,15 @@ namespace Obsidian.API.Advancements { public sealed class Advancement { + public Advancement(string identifier, string parent, AdvancementDisplay? display, AdvancementReward? reward, List criteria) + { + Identifier = identifier; + Parent = parent; + Display = display; + Reward = reward; + Criteria = criteria; + } + /// /// The identifier of the advancement. /// If a valid identifier is not detected this advancement will register with the obsidian namespace. diff --git a/Obsidian.API/_Types/Advancements/AdvancementDisplay.cs b/Obsidian.API/_Types/Advancements/AdvancementDisplay.cs index ee607e19b..cb952ed18 100644 --- a/Obsidian.API/_Types/Advancements/AdvancementDisplay.cs +++ b/Obsidian.API/_Types/Advancements/AdvancementDisplay.cs @@ -4,6 +4,18 @@ namespace Obsidian.API.Advancements { public sealed class AdvancementDisplay { + public AdvancementDisplay(ChatMessage title, ChatMessage description, Item icon, AdvancementFrameType advancementFrameType, AdvancementFlags flags, string backgroundTexture, float xCoord, float yCoord) + { + Title = title; + Description = description; + Icon = icon; + AdvancementFrameType = advancementFrameType; + Flags = flags; + BackgroundTexture = backgroundTexture; + XCoord = xCoord; + YCoord = yCoord; + } + public ChatMessage Title { get; init; } public ChatMessage Description { get; init; } diff --git a/Obsidian.API/_Types/Advancements/AdvancementReward.cs b/Obsidian.API/_Types/Advancements/AdvancementReward.cs index 90b4d063f..586e44304 100644 --- a/Obsidian.API/_Types/Advancements/AdvancementReward.cs +++ b/Obsidian.API/_Types/Advancements/AdvancementReward.cs @@ -4,6 +4,13 @@ namespace Obsidian.API.Advancements { public sealed class AdvancementReward { + public AdvancementReward(int? experience, List loot, List recipes) + { + Experience = experience; + Loot = loot; + Recipes = recipes; + } + public int? Experience { get; init; } public List Loot { get; init; } diff --git a/Obsidian.API/_Types/ChatMessage.cs b/Obsidian.API/_Types/ChatMessage.cs index 60a497ec8..5e50c389e 100644 --- a/Obsidian.API/_Types/ChatMessage.cs +++ b/Obsidian.API/_Types/ChatMessage.cs @@ -6,6 +6,28 @@ namespace Obsidian.API { public class ChatMessage { + public ChatMessage(string text, HexColor color, bool bold, bool italic, bool underlined, bool strikethrough, bool obfuscated, string insertion, ClickComponent clickEvent, HoverComponent hoverEvent, List extra) + { + Text = text; + Color = color; + Bold = bold; + Italic = italic; + Underlined = underlined; + Strikethrough = strikethrough; + Obfuscated = obfuscated; + Insertion = insertion; + ClickEvent = clickEvent; + HoverEvent = hoverEvent; + Extra = extra; + } + +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + public ChatMessage() +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + { + + } + public string Text { get; set; } public HexColor Color { get; set; } diff --git a/Obsidian.API/_Types/Inventory/ItemMetaBuilder.cs b/Obsidian.API/_Types/Inventory/ItemMetaBuilder.cs index 5bb6ef2f5..c01e1ed99 100644 --- a/Obsidian.API/_Types/Inventory/ItemMetaBuilder.cs +++ b/Obsidian.API/_Types/Inventory/ItemMetaBuilder.cs @@ -28,11 +28,11 @@ public class ItemMetaBuilder private readonly List lore = new List(); - public ItemMetaBuilder() + public ItemMetaBuilder(string name = "") { this.Enchantments = new ReadOnlyDictionary(this.enchantments); this.StoredEnchantments = new ReadOnlyDictionary(this.storedEnchantments); - + this.Name = name; this.CanDestroy = new ReadOnlyCollection(this.canDestroy); this.Lore = new ReadOnlyCollection(this.lore); diff --git a/Obsidian.API/_Types/Score.cs b/Obsidian.API/_Types/Score.cs index ce589ecd2..927125492 100644 --- a/Obsidian.API/_Types/Score.cs +++ b/Obsidian.API/_Types/Score.cs @@ -2,6 +2,12 @@ { public sealed class Score { + public Score(string displayText, int value) + { + DisplayText = displayText; + Value = value; + } + public string DisplayText { get; internal set; } public int Value { get; internal set; } diff --git a/Obsidian.API/_Types/ScoreboardObjective.cs b/Obsidian.API/_Types/ScoreboardObjective.cs index 91a5b4a40..4b7cdaa6d 100644 --- a/Obsidian.API/_Types/ScoreboardObjective.cs +++ b/Obsidian.API/_Types/ScoreboardObjective.cs @@ -2,6 +2,13 @@ { public sealed class ScoreboardObjective { + public ScoreboardObjective(string objectiveName, ChatMessage value, DisplayType displayType) + { + ObjectiveName = objectiveName; + Value = value; + DisplayType = displayType; + } + public string ObjectiveName { get; internal set; } public ChatMessage Value { get; internal set; } diff --git a/Obsidian.Tests/Noise.cs b/Obsidian.Tests/Noise.cs index 185009d4d..6fc1a2502 100644 --- a/Obsidian.Tests/Noise.cs +++ b/Obsidian.Tests/Noise.cs @@ -4,6 +4,7 @@ using SharpNoise; using SharpNoise.Builders; using SharpNoise.Utilities.Imaging; +using System.Threading.Tasks; using Xunit; namespace Obsidian.Tests @@ -13,37 +14,40 @@ public class Noise [Fact(DisplayName = "WorldGen", Timeout = 100)] public async void SameAsync() { - OverworldGenerator og = new OverworldGenerator("1"); - OverworldTerrain noiseGen = new OverworldTerrain(true); + await Task.Run(() => + { + OverworldGenerator og = new OverworldGenerator("1"); + OverworldTerrain noiseGen = new OverworldTerrain(true); - var map = new NoiseMap(); + var map = new NoiseMap(); - PlaneNoiseMapBuilder builder = new PlaneNoiseMapBuilder() - { - DestNoiseMap = map, - SourceModule = noiseGen.Result - }; + PlaneNoiseMapBuilder builder = new PlaneNoiseMapBuilder() + { + DestNoiseMap = map, + SourceModule = noiseGen.Result + }; - var image = new SharpNoise.Utilities.Imaging.Image(); - var renderer = new ImageRenderer() - { - SourceNoiseMap = map, - DestinationImage = image - }; + var image = new SharpNoise.Utilities.Imaging.Image(); + var renderer = new ImageRenderer() + { + SourceNoiseMap = map, + DestinationImage = image + }; - //renderer.BuildGrayscaleGradient(); - renderer.BuildTerrainGradient(); + //renderer.BuildGrayscaleGradient(); + renderer.BuildTerrainGradient(); - builder.SetBounds(-2000, 2000, -2000, 2000); - builder.SetDestSize(4000, 4000); - builder.Build(); + builder.SetBounds(-2000, 2000, -2000, 2000); + builder.SetDestSize(4000, 4000); + builder.Build(); - renderer.Render(); + renderer.Render(); - var bmp = renderer.DestinationImage.ToGdiBitmap(); - bmp.Save("terrain.bmp"); + var bmp = renderer.DestinationImage.ToGdiBitmap(); + bmp.Save("terrain.bmp"); - Assert.Equal(0, 0); + Assert.Equal(0, 0); + }); } } } \ No newline at end of file diff --git a/Obsidian/Plugins/PluginContainer.cs b/Obsidian/Plugins/PluginContainer.cs index eae288438..02dd5b6d8 100644 --- a/Obsidian/Plugins/PluginContainer.cs +++ b/Obsidian/Plugins/PluginContainer.cs @@ -157,7 +157,7 @@ private static object CreateInjection(Type targetType, PluginBase plugin, ILogge return null; } - wrapper.plugin = plugin; + wrapper.Plugin = plugin; Type pluginType = plugin.GetType(); var methods = pluginType.GetMethods(); diff --git a/Obsidian/Scoreboard.cs b/Obsidian/Scoreboard.cs index 7df17a420..3ca74f051 100644 --- a/Obsidian/Scoreboard.cs +++ b/Obsidian/Scoreboard.cs @@ -41,11 +41,11 @@ public async Task CreateOrUpdateObjectiveAsync(ChatMessage title, DisplayType di else { this.Objective = new ScoreboardObjective - { - ObjectiveName = this.name, - Value = title, - DisplayType = displayType - }; + ( + this.name, + title, + displayType + ); foreach (var (_, player) in this.server.OnlinePlayers) { @@ -70,11 +70,7 @@ await player.client.QueuePacketAsync(new UpdateScore public async Task CreateOrUpdateScoreAsync(string scoreName, string displayText, int? value = null) { - var score = new Score - { - DisplayText = displayText, - Value = value ?? 0 - }; + var score = new Score(displayText, value ?? 0); if (this.scores.TryGetValue(scoreName, out var cachedScore)) { diff --git a/Obsidian/Utilities/RentedArray.cs b/Obsidian/Utilities/RentedArray.cs index bf9d7ea7b..16a971780 100644 --- a/Obsidian/Utilities/RentedArray.cs +++ b/Obsidian/Utilities/RentedArray.cs @@ -27,13 +27,19 @@ namespace Obsidian.Utilities /// public Memory Memory => array.AsMemory(0, Length); +#nullable enable + /// + /// #nullable + /// + /// + /// public RentedArray(int length, ArrayPool? pool = null) { this.pool = pool ?? ArrayPool.Shared; array = this.pool.Rent(length); Length = length; } - +#nullable disable /// /// Returns the rented array to the pool diff --git a/Obsidian/WorldData/BlockUpdates.cs b/Obsidian/WorldData/BlockUpdates.cs index 25ee36883..f4c5fd78c 100644 --- a/Obsidian/WorldData/BlockUpdates.cs +++ b/Obsidian/WorldData/BlockUpdates.cs @@ -25,24 +25,24 @@ internal static async Task HandleFallingBlock(BlockUpdate blockUpdate) }); } - // TODO: This method will need to be implemented as above if it is going to be declared async - // HenryMigo 30/10/2021 internal static async Task HandleLiquidPhysics(BlockUpdate blockUpdate) { - if (blockUpdate.block is null) { return false; } - var block = blockUpdate.block.Value; - var world = blockUpdate.world; - var location = blockUpdate.position; - int state = block.State; - Vector belowPos = location + Vector.Down; - - // Handle the initial search for closet path downwards. - // Just going to do a crappy pathfind for now. We can do - // proper pathfinding some other time. - if (state == 0) + return await Task.Run(() => { - var validPaths = new List(); - var paths = new List() + if (blockUpdate.block is null) { return false; } + var block = blockUpdate.block.Value; + var world = blockUpdate.world; + var location = blockUpdate.position; + int state = block.State; + Vector belowPos = location + Vector.Down; + + // Handle the initial search for closet path downwards. + // Just going to do a crappy pathfind for now. We can do + // proper pathfinding some other time. + if (state == 0) + { + var validPaths = new List(); + var paths = new List() { { location + Vector.Forwards }, { location + Vector.Backwards }, @@ -50,59 +50,59 @@ internal static async Task HandleLiquidPhysics(BlockUpdate blockUpdate) { location + Vector.Right } }; - foreach (var pathLoc in paths) - { - if (world.GetBlock(pathLoc) is Block pathSide && (Block.Replaceable.Contains(pathSide.Material) || pathSide.IsFluid)) + foreach (var pathLoc in paths) { - var pathBelow = world.GetBlock(pathLoc + Vector.Down); - if (pathBelow is Block pBelow && (Block.Replaceable.Contains(pBelow.Material) || pBelow.IsFluid)) + if (world.GetBlock(pathLoc) is Block pathSide && (Block.Replaceable.Contains(pathSide.Material) || pathSide.IsFluid)) { - validPaths.Add(pathLoc); + var pathBelow = world.GetBlock(pathLoc + Vector.Down); + if (pathBelow is Block pBelow && (Block.Replaceable.Contains(pBelow.Material) || pBelow.IsFluid)) + { + validPaths.Add(pathLoc); + } } } - } - // if all directions are valid, or none are, use normal liquid spread physics instead - if (validPaths.Count != 4 && validPaths.Count != 0) - { - var path = validPaths[0]; - var newBlock = new Block(block.BaseId, state + 1); - world.SetBlock(path, newBlock); - var neighborUpdate = new BlockUpdate(world, path, newBlock); - world.ScheduleBlockUpdate(neighborUpdate); - return false; + // if all directions are valid, or none are, use normal liquid spread physics instead + if (validPaths.Count != 4 && validPaths.Count != 0) + { + var path = validPaths[0]; + var newBlock = new Block(block.BaseId, state + 1); + world.SetBlock(path, newBlock); + var neighborUpdate = new BlockUpdate(world, path, newBlock); + world.ScheduleBlockUpdate(neighborUpdate); + return false; + } } - } - if (state >= 8) // Falling water - { - // If above me is no longer water, than I should disappear too - if (world.GetBlock(location + Vector.Up) is Block up && !up.IsFluid) + if (state >= 8) // Falling water { - world.SetBlock(location, Block.Air); - world.ScheduleBlockUpdate(new BlockUpdate(world, belowPos)); - return false; - } + // If above me is no longer water, than I should disappear too + if (world.GetBlock(location + Vector.Up) is Block up && !up.IsFluid) + { + world.SetBlock(location, Block.Air); + world.ScheduleBlockUpdate(new BlockUpdate(world, belowPos)); + return false; + } - // Keep falling - if (world.GetBlock(belowPos) is Block below && Block.Replaceable.Contains(below.Material)) - { - var newBlock = new Block(block.BaseId, state); - world.SetBlock(belowPos, newBlock); - world.ScheduleBlockUpdate(new BlockUpdate(world, belowPos, newBlock)); - return false; - } - else - { - // Falling water has hit something solid. Change state to spread. - state = 1; - world.SetBlockUntracked(location, new Block(block.BaseId, state)); + // Keep falling + if (world.GetBlock(belowPos) is Block below && Block.Replaceable.Contains(below.Material)) + { + var newBlock = new Block(block.BaseId, state); + world.SetBlock(belowPos, newBlock); + world.ScheduleBlockUpdate(new BlockUpdate(world, belowPos, newBlock)); + return false; + } + else + { + // Falling water has hit something solid. Change state to spread. + state = 1; + world.SetBlockUntracked(location, new Block(block.BaseId, state)); + } } - } - if (state < 8) - { - var horizontalNeighbors = new Dictionary() + if (state < 8) + { + var horizontalNeighbors = new Dictionary() { { location + Vector.Forwards, world.GetBlock(location + Vector.Forwards) }, { location + Vector.Backwards, world.GetBlock(location + Vector.Backwards) }, @@ -110,75 +110,76 @@ internal static async Task HandleLiquidPhysics(BlockUpdate blockUpdate) { location + Vector.Right, world.GetBlock(location + Vector.Right) } }; - // Check infinite source blocks - if (state == 1 && block.Material == Material.Water) - { - // if 2 neighbors are source blocks (state = 0), then become source block - int sourceNeighborCount = 0; - foreach (var (loc, neighborBlock) in horizontalNeighbors) + // Check infinite source blocks + if (state == 1 && block.Material == Material.Water) { - if (neighborBlock is Block neighbor && neighbor.Material == block.Material && neighbor.State == 0) + // if 2 neighbors are source blocks (state = 0), then become source block + int sourceNeighborCount = 0; + foreach (var (loc, neighborBlock) in horizontalNeighbors) { - sourceNeighborCount++; + if (neighborBlock is Block neighbor && neighbor.Material == block.Material && neighbor.State == 0) + { + sourceNeighborCount++; + } + } + if (sourceNeighborCount > 1) + { + var newBlock = new Block(Material.Water); + world.SetBlock(location, newBlock); + return true; } } - if (sourceNeighborCount > 1) - { - var newBlock = new Block(Material.Water); - world.SetBlock(location, newBlock); - return true; - } - } - if (state > 0) - { - // On some side of the block, there should be another water block with a lower state. - int lowestState = state; - foreach (var (loc, neighborBlock) in horizontalNeighbors) + if (state > 0) { - if (neighborBlock.Value.Material == block.Material) - lowestState = Math.Min(lowestState, neighborBlock.Value.State); - } + // On some side of the block, there should be another water block with a lower state. + int lowestState = state; + foreach (var (loc, neighborBlock) in horizontalNeighbors) + { + if (neighborBlock.Value.Material == block.Material) + lowestState = Math.Min(lowestState, neighborBlock.Value.State); + } - // If not, turn to air and update neighbors. - if (lowestState >= state && world.GetBlock(location + Vector.Up).Value.Material != block.Material) - { - world.SetBlock(location, Block.Air); - return true; + // If not, turn to air and update neighbors. + if (lowestState >= state && world.GetBlock(location + Vector.Up).Value.Material != block.Material) + { + world.SetBlock(location, Block.Air); + return true; + } } - } - if (world.GetBlock(belowPos) is Block below) - { - if (below.Material == block.Material) { return false; } - if (Block.Replaceable.Contains(below.Material)) + if (world.GetBlock(belowPos) is Block below) { - var newBlock = new Block(block.BaseId, state + 8); - world.SetBlock(belowPos, newBlock); - var neighborUpdate = new BlockUpdate(world, belowPos, newBlock); - world.ScheduleBlockUpdate(neighborUpdate); - return false; + if (below.Material == block.Material) { return false; } + if (Block.Replaceable.Contains(below.Material)) + { + var newBlock = new Block(block.BaseId, state + 8); + world.SetBlock(belowPos, newBlock); + var neighborUpdate = new BlockUpdate(world, belowPos, newBlock); + world.ScheduleBlockUpdate(neighborUpdate); + return false; + } } - } - // the lowest level of water can only go down, so bail now. - if (state == 7) { return false; } + // the lowest level of water can only go down, so bail now. + if (state == 7) { return false; } - foreach (var (loc, neighborBlock) in horizontalNeighbors) - { - if (neighborBlock is null) { continue; } - var neighbor = neighborBlock.Value; - if (Block.Replaceable.Contains(neighbor.Material) || (neighbor.Material == block.Material && neighbor.State > state + 1)) + foreach (var (loc, neighborBlock) in horizontalNeighbors) { - var newBlock = new Block(block.BaseId, state + 1); - world.SetBlock(loc, newBlock); - var neighborUpdate = new BlockUpdate(world, loc, newBlock); - world.ScheduleBlockUpdate(neighborUpdate); + if (neighborBlock is null) { continue; } + var neighbor = neighborBlock.Value; + if (Block.Replaceable.Contains(neighbor.Material) || (neighbor.Material == block.Material && neighbor.State > state + 1)) + { + var newBlock = new Block(block.BaseId, state + 1); + world.SetBlock(loc, newBlock); + var neighborUpdate = new BlockUpdate(world, loc, newBlock); + world.ScheduleBlockUpdate(neighborUpdate); + } } } - } - return false; + return false; + }); } } } diff --git a/Obsidian/WorldData/Generators/Overworld/Terrain/OverworldTerrain.cs b/Obsidian/WorldData/Generators/Overworld/Terrain/OverworldTerrain.cs index f64d7381d..35e3605e2 100644 --- a/Obsidian/WorldData/Generators/Overworld/Terrain/OverworldTerrain.cs +++ b/Obsidian/WorldData/Generators/Overworld/Terrain/OverworldTerrain.cs @@ -110,19 +110,14 @@ public OverworldTerrain(bool isUnitTest = false) var biomeTransitionSel2 = new Cache { - Source0 = new TransitionMap - { - Distance = 5, - Source0 = FinalBiomes - } + Source0 = new TransitionMap(FinalBiomes, 5) }; Module scaled = new Blend( - new TerrainSelect + new TerrainSelect(FinalBiomes) { - BiomeSelector = FinalBiomes, Control = biomeTransitionSel2, - TerrainModules = biomesMap, + TerrainModules = biomesMap }) { Distance = 2 diff --git a/Obsidian/WorldData/RegionFile.cs b/Obsidian/WorldData/RegionFile.cs index 50237a7ce..b6656a8d5 100644 --- a/Obsidian/WorldData/RegionFile.cs +++ b/Obsidian/WorldData/RegionFile.cs @@ -233,7 +233,7 @@ protected virtual void Dispose(bool disposing) { if (disposing) { - FlushToDiskAsync(); + Task.Run(async () => await FlushToDiskAsync()); } // TODO: free unmanaged resources (unmanaged objects) and override finalizer diff --git a/Obsidian/WorldData/World.cs b/Obsidian/WorldData/World.cs index 18f3af2e4..54a0e2432 100644 --- a/Obsidian/WorldData/World.cs +++ b/Obsidian/WorldData/World.cs @@ -529,9 +529,12 @@ public async Task ManageChunksAsync() public async Task FlushRegionsAsync() { - Server.BroadcastMessage("Saving to disk..."); - Parallel.ForEach(Regions.Values, async r => await r.FlushAsync()); - Server.BroadcastMessage("Save complete."); + await Task.Run(() => + { + Server.BroadcastMessage("Saving to disk..."); + Parallel.ForEach(Regions.Values, async r => await r.FlushAsync()); + Server.BroadcastMessage("Save complete."); + }); } public IEntity SpawnFallingBlock(VectorF position, Material mat) diff --git a/SamplePlugin/SamplePlugin.cs b/SamplePlugin/SamplePlugin.cs index 9566b76ca..bac82b8b2 100644 --- a/SamplePlugin/SamplePlugin.cs +++ b/SamplePlugin/SamplePlugin.cs @@ -7,9 +7,9 @@ namespace SamplePlugin { - [Plugin(Name = "Sample Plugin", Version = "1.0", - Authors = "Obsidian Team", Description = "My sample plugin.", - ProjectUrl = "https://github.com/Naamloos/Obsidian")] + [Plugin("Sample Plugin", "1.0", + "Obsidian Team", "My sample plugin.", + "https://github.com/Naamloos/Obsidian")] public class SamplePlugin : PluginBase { // Any interface from Obsidian.Plugins.Services can be injected into properties @@ -19,7 +19,7 @@ public class SamplePlugin : PluginBase // Dependencies will be injected automatically, if dependency class and field/property names match // Plugins won't load until all their required dependencies are added // Optional dependencies may be injected at any time, if at all - [Dependency(MinVersion = "2.0", Optional = true), Alias("Sample Remote Plugin")] + [Dependency("2.0", true), Alias("Sample Remote Plugin")] public MyWrapper SampleRemotePlugin { get; set; } // One of server messages, called when an event occurs From 281190c5c05f87c470147b8bba48027080abda12 Mon Sep 17 00:00:00 2001 From: Henry Migo Date: Sun, 31 Oct 2021 10:06:29 +0000 Subject: [PATCH 09/15] PR Comments --- Obsidian.API/Plugins/PluginAttribute.cs | 18 +++-- Obsidian.API/Plugins/PluginBase.cs | 9 +-- Obsidian.API/Plugins/Services/IDiagnoser.cs | 2 +- Obsidian.API/Plugins/Services/ILogger.cs | 4 - .../_Attributes/RequirePermissionAttribute.cs | 7 +- Obsidian.API/_Types/Block.cs | 2 +- .../_Types/Inventory/ItemMetaBuilder.cs | 6 +- Obsidian/Plugins/Services/DiagnoserService.cs | 4 +- Obsidian/Utilities/RentedArray.cs | 5 -- Obsidian/WorldData/BlockUpdates.cs | 73 ++++++++++--------- Obsidian/WorldData/RegionFile.cs | 12 +-- Obsidian/WorldData/World.cs | 12 +-- 12 files changed, 75 insertions(+), 79 deletions(-) diff --git a/Obsidian.API/Plugins/PluginAttribute.cs b/Obsidian.API/Plugins/PluginAttribute.cs index 171d83ac0..65dcc01d0 100644 --- a/Obsidian.API/Plugins/PluginAttribute.cs +++ b/Obsidian.API/Plugins/PluginAttribute.cs @@ -8,6 +8,14 @@ namespace Obsidian.API.Plugins [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] public class PluginAttribute : Attribute { + /// + /// Plugin attribute constructor. + /// + /// + /// + /// + /// + /// public PluginAttribute(string name, string version, string authors, string description, string projectUrl) { Name = name; @@ -20,26 +28,26 @@ public PluginAttribute(string name, string version, string authors, string descr /// /// Name of the plugin. /// - public string Name { get; set; } + public string Name { get; } /// /// Version of the plugin. The string should contain the major, minor, [build], and [revision] numbers, split by a period character ('.'). /// - public string Version { get; set; } + public string Version { get; } /// /// Name(s) of the plugin's author(s). /// - public string Authors { get; set; } + public string Authors { get; } /// /// Description of the plugin. /// - public string Description { get; set; } + public string Description { get; } /// /// URL address of where the plugin is hosted. /// - public string ProjectUrl { get; set; } + public string ProjectUrl { get; } } } diff --git a/Obsidian.API/Plugins/PluginBase.cs b/Obsidian.API/Plugins/PluginBase.cs index 940e6a8d2..e8e34dc79 100644 --- a/Obsidian.API/Plugins/PluginBase.cs +++ b/Obsidian.API/Plugins/PluginBase.cs @@ -20,16 +20,9 @@ public abstract class PluginBase private Type typeCache; - public PluginBase(Type TypeCache) - { - typeCache = TypeCache; - } - -#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. public PluginBase() -#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. { - + typeCache ??= GetType(); } public void RegisterCommand(Action action) diff --git a/Obsidian.API/Plugins/Services/IDiagnoser.cs b/Obsidian.API/Plugins/Services/IDiagnoser.cs index 2d39b1414..0177b7d5f 100644 --- a/Obsidian.API/Plugins/Services/IDiagnoser.cs +++ b/Obsidian.API/Plugins/Services/IDiagnoser.cs @@ -31,7 +31,7 @@ public interface IDiagnoser : ISecuredService /// Indicates whether to start the process in a new window. /// Indicates whether to use the operating system shell to start the process. /// A new that is associated with the process resource, or null if no process resource is started. - public IProcess StartProcess(string fileName, string arguments = "", bool createWindow = true, bool useShell = false); + public IProcess StartProcess(string fileName, string? arguments = null, bool createWindow = true, bool useShell = false); /// /// Returns a new instance of . diff --git a/Obsidian.API/Plugins/Services/ILogger.cs b/Obsidian.API/Plugins/Services/ILogger.cs index 919eecfdf..6027de3cf 100644 --- a/Obsidian.API/Plugins/Services/ILogger.cs +++ b/Obsidian.API/Plugins/Services/ILogger.cs @@ -57,10 +57,6 @@ public void LogTrace(T exception) where T : Exception { Log(exception.StackTrace); } - else - { - Log("No stack trace..."); - } } } } diff --git a/Obsidian.API/_Attributes/RequirePermissionAttribute.cs b/Obsidian.API/_Attributes/RequirePermissionAttribute.cs index 0399fb7f9..2818f5dca 100644 --- a/Obsidian.API/_Attributes/RequirePermissionAttribute.cs +++ b/Obsidian.API/_Attributes/RequirePermissionAttribute.cs @@ -19,13 +19,10 @@ public RequirePermissionAttribute(PermissionCheckType checkType = PermissionChec public override Task RunChecksAsync(CommandContext context) { - if (context.Player == null) - { - throw new Exception("Player not found"); - } - if(context.Sender.Issuer == CommandIssuers.Console) return Task.FromResult(true); + if (context.Player == null) + return Task.FromResult(false); if (this.op && context.Player.IsOperator) return Task.FromResult(true); diff --git a/Obsidian.API/_Types/Block.cs b/Obsidian.API/_Types/Block.cs index 7aaaa6fa5..733eccaa5 100644 --- a/Obsidian.API/_Types/Block.cs +++ b/Obsidian.API/_Types/Block.cs @@ -139,7 +139,7 @@ public bool Is(Material material) return stateToMatch[baseId].numeric == (int)material; } - public override bool Equals(object obj) + public override bool Equals(object? obj) { return (obj is Block block) && block.StateId == StateId; } diff --git a/Obsidian.API/_Types/Inventory/ItemMetaBuilder.cs b/Obsidian.API/_Types/Inventory/ItemMetaBuilder.cs index c01e1ed99..cbaec86e1 100644 --- a/Obsidian.API/_Types/Inventory/ItemMetaBuilder.cs +++ b/Obsidian.API/_Types/Inventory/ItemMetaBuilder.cs @@ -8,7 +8,7 @@ public class ItemMetaBuilder internal byte Slot { get; set; } internal int CustomModelData { get; set; } - public ChatMessage Name { get; internal set; } + public ChatMessage? Name { get; internal set; } public int Durability { get; internal set; } @@ -28,13 +28,11 @@ public class ItemMetaBuilder private readonly List lore = new List(); - public ItemMetaBuilder(string name = "") + public ItemMetaBuilder() { this.Enchantments = new ReadOnlyDictionary(this.enchantments); this.StoredEnchantments = new ReadOnlyDictionary(this.storedEnchantments); - this.Name = name; this.CanDestroy = new ReadOnlyCollection(this.canDestroy); - this.Lore = new ReadOnlyCollection(this.lore); } diff --git a/Obsidian/Plugins/Services/DiagnoserService.cs b/Obsidian/Plugins/Services/DiagnoserService.cs index 63cde3dd4..55393bc7b 100644 --- a/Obsidian/Plugins/Services/DiagnoserService.cs +++ b/Obsidian/Plugins/Services/DiagnoserService.cs @@ -32,7 +32,7 @@ public IProcess[] GetProcesses() return Process.GetProcesses().Select(process => new ProcessService(process, this)).ToArray(); } - public IProcess StartProcess(string fileName, string arguments = null, bool createWindow = true, bool useShell = false) + public IProcess StartProcess(string fileName, string? arguments = null, bool createWindow = true, bool useShell = false) { if (!IsUsable) throw new SecurityException(IDiagnoser.SecurityExceptionMessage); @@ -40,7 +40,7 @@ public IProcess StartProcess(string fileName, string arguments = null, bool crea var processInfo = new ProcessStartInfo { FileName = fileName, - Arguments = arguments, + Arguments = arguments ?? string.Empty, CreateNoWindow = !createWindow, UseShellExecute = useShell }; diff --git a/Obsidian/Utilities/RentedArray.cs b/Obsidian/Utilities/RentedArray.cs index 16a971780..16eb5c02a 100644 --- a/Obsidian/Utilities/RentedArray.cs +++ b/Obsidian/Utilities/RentedArray.cs @@ -28,11 +28,6 @@ namespace Obsidian.Utilities public Memory Memory => array.AsMemory(0, Length); #nullable enable - /// - /// #nullable - /// - /// - /// public RentedArray(int length, ArrayPool? pool = null) { this.pool = pool ?? ArrayPool.Shared; diff --git a/Obsidian/WorldData/BlockUpdates.cs b/Obsidian/WorldData/BlockUpdates.cs index f4c5fd78c..4b7723b69 100644 --- a/Obsidian/WorldData/BlockUpdates.cs +++ b/Obsidian/WorldData/BlockUpdates.cs @@ -9,20 +9,20 @@ internal static class BlockUpdates { internal static async Task HandleFallingBlock(BlockUpdate blockUpdate) { - return await Task.Run(() => + if (blockUpdate.block is null) { return false; } + + var world = blockUpdate.world; + var location = blockUpdate.position; + var material = blockUpdate.block.Value.Material; + if (world.GetBlock(location + Vector.Down) is Block below && + (Block.Replaceable.Contains(below.Material) || below.IsFluid)) { - if (blockUpdate.block is null) { return false; } - var world = blockUpdate.world; - var location = blockUpdate.position; - var material = blockUpdate.block.Value.Material; - if (world.GetBlock(location + Vector.Down) is Block below && (Block.Replaceable.Contains(below.Material) || below.IsFluid)) - { - world.SetBlock(location, Block.Air); - world.SpawnFallingBlock(location, material); - return true; - } - return false; - }); + world.SetBlock(location, Block.Air); + world.SpawnFallingBlock(location, material); + return true; + } + + return false; } internal static async Task HandleLiquidPhysics(BlockUpdate blockUpdate) @@ -30,6 +30,7 @@ internal static async Task HandleLiquidPhysics(BlockUpdate blockUpdate) return await Task.Run(() => { if (blockUpdate.block is null) { return false; } + var block = blockUpdate.block.Value; var world = blockUpdate.world; var location = blockUpdate.position; @@ -42,20 +43,21 @@ internal static async Task HandleLiquidPhysics(BlockUpdate blockUpdate) if (state == 0) { var validPaths = new List(); - var paths = new List() - { - { location + Vector.Forwards }, - { location + Vector.Backwards }, - { location + Vector.Left }, - { location + Vector.Right } - }; + var paths = new List() { + {location + Vector.Forwards}, + {location + Vector.Backwards}, + {location + Vector.Left}, + {location + Vector.Right} + }; foreach (var pathLoc in paths) { - if (world.GetBlock(pathLoc) is Block pathSide && (Block.Replaceable.Contains(pathSide.Material) || pathSide.IsFluid)) + if (world.GetBlock(pathLoc) is Block pathSide && + (Block.Replaceable.Contains(pathSide.Material) || pathSide.IsFluid)) { var pathBelow = world.GetBlock(pathLoc + Vector.Down); - if (pathBelow is Block pBelow && (Block.Replaceable.Contains(pBelow.Material) || pBelow.IsFluid)) + if (pathBelow is Block pBelow && + (Block.Replaceable.Contains(pBelow.Material) || pBelow.IsFluid)) { validPaths.Add(pathLoc); } @@ -102,13 +104,12 @@ internal static async Task HandleLiquidPhysics(BlockUpdate blockUpdate) if (state < 8) { - var horizontalNeighbors = new Dictionary() - { - { location + Vector.Forwards, world.GetBlock(location + Vector.Forwards) }, - { location + Vector.Backwards, world.GetBlock(location + Vector.Backwards) }, - { location + Vector.Left, world.GetBlock(location + Vector.Left) }, - { location + Vector.Right, world.GetBlock(location + Vector.Right) } - }; + var horizontalNeighbors = new Dictionary() { + {location + Vector.Forwards, world.GetBlock(location + Vector.Forwards)}, + {location + Vector.Backwards, world.GetBlock(location + Vector.Backwards)}, + {location + Vector.Left, world.GetBlock(location + Vector.Left)}, + {location + Vector.Right, world.GetBlock(location + Vector.Right)} + }; // Check infinite source blocks if (state == 1 && block.Material == Material.Water) @@ -117,11 +118,13 @@ internal static async Task HandleLiquidPhysics(BlockUpdate blockUpdate) int sourceNeighborCount = 0; foreach (var (loc, neighborBlock) in horizontalNeighbors) { - if (neighborBlock is Block neighbor && neighbor.Material == block.Material && neighbor.State == 0) + if (neighborBlock is Block neighbor && neighbor.Material == block.Material && + neighbor.State == 0) { sourceNeighborCount++; } } + if (sourceNeighborCount > 1) { var newBlock = new Block(Material.Water); @@ -141,7 +144,8 @@ internal static async Task HandleLiquidPhysics(BlockUpdate blockUpdate) } // If not, turn to air and update neighbors. - if (lowestState >= state && world.GetBlock(location + Vector.Up).Value.Material != block.Material) + if (lowestState >= state && + world.GetBlock(location + Vector.Up).Value.Material != block.Material) { world.SetBlock(location, Block.Air); return true; @@ -151,6 +155,7 @@ internal static async Task HandleLiquidPhysics(BlockUpdate blockUpdate) if (world.GetBlock(belowPos) is Block below) { if (below.Material == block.Material) { return false; } + if (Block.Replaceable.Contains(below.Material)) { var newBlock = new Block(block.BaseId, state + 8); @@ -167,8 +172,10 @@ internal static async Task HandleLiquidPhysics(BlockUpdate blockUpdate) foreach (var (loc, neighborBlock) in horizontalNeighbors) { if (neighborBlock is null) { continue; } + var neighbor = neighborBlock.Value; - if (Block.Replaceable.Contains(neighbor.Material) || (neighbor.Material == block.Material && neighbor.State > state + 1)) + if (Block.Replaceable.Contains(neighbor.Material) || + (neighbor.Material == block.Material && neighbor.State > state + 1)) { var newBlock = new Block(block.BaseId, state + 1); world.SetBlock(loc, newBlock); @@ -182,4 +189,4 @@ internal static async Task HandleLiquidPhysics(BlockUpdate blockUpdate) }); } } -} +} \ No newline at end of file diff --git a/Obsidian/WorldData/RegionFile.cs b/Obsidian/WorldData/RegionFile.cs index b6656a8d5..152ed9eb5 100644 --- a/Obsidian/WorldData/RegionFile.cs +++ b/Obsidian/WorldData/RegionFile.cs @@ -8,7 +8,7 @@ namespace Obsidian.WorldData { - public class RegionFile : IDisposable + public class RegionFile : IAsyncDisposable { private readonly string filePath; private readonly int cubicRegionSize; @@ -227,13 +227,13 @@ public void SetOffsetSizeAtIndex(int tableIndex, int offset, int size) } #region IDisposable - protected virtual void Dispose(bool disposing) + protected async virtual Task DisposeAsync(bool disposing) { if (!disposedValue) { if (disposing) { - Task.Run(async () => await FlushToDiskAsync()); + await FlushToDiskAsync(); } // TODO: free unmanaged resources (unmanaged objects) and override finalizer @@ -249,10 +249,10 @@ protected virtual void Dispose(bool disposing) // Dispose(disposing: false); // } - public void Dispose() + public async ValueTask DisposeAsync() { - // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method - Dispose(disposing: true); + // Do not change this code. Put cleanup code in 'DisposeAsync(bool disposing)' method + await DisposeAsync(true); GC.SuppressFinalize(this); } #endregion IDisposable diff --git a/Obsidian/WorldData/World.cs b/Obsidian/WorldData/World.cs index 54a0e2432..a8029b09a 100644 --- a/Obsidian/WorldData/World.cs +++ b/Obsidian/WorldData/World.cs @@ -529,11 +529,13 @@ public async Task ManageChunksAsync() public async Task FlushRegionsAsync() { - await Task.Run(() => - { - Server.BroadcastMessage("Saving to disk..."); - Parallel.ForEach(Regions.Values, async r => await r.FlushAsync()); - Server.BroadcastMessage("Save complete."); + await Task.WhenAll(new List { + Task.Run(() => + { + Server.BroadcastMessage("Saving to disk..."); + Parallel.ForEach(Regions.Values, async r => await r.FlushAsync()); + Server.BroadcastMessage("Save complete."); + }) }); } From f13416390ce0415debee21d7db8d8a63e6843a3c Mon Sep 17 00:00:00 2001 From: Henry Migo Date: Sun, 31 Oct 2021 10:10:02 +0000 Subject: [PATCH 10/15] Changed Name in ItemMetaBuilder back to normal (Warning will return) --- Obsidian.API/_Types/Inventory/ItemMetaBuilder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Obsidian.API/_Types/Inventory/ItemMetaBuilder.cs b/Obsidian.API/_Types/Inventory/ItemMetaBuilder.cs index cbaec86e1..b53d37baf 100644 --- a/Obsidian.API/_Types/Inventory/ItemMetaBuilder.cs +++ b/Obsidian.API/_Types/Inventory/ItemMetaBuilder.cs @@ -8,7 +8,7 @@ public class ItemMetaBuilder internal byte Slot { get; set; } internal int CustomModelData { get; set; } - public ChatMessage? Name { get; internal set; } + public ChatMessage Name { get; internal set; } public int Durability { get; internal set; } From 285b7d7735b0ae5f0706822574124ffd80ec5f57 Mon Sep 17 00:00:00 2001 From: Henry Migo Date: Mon, 1 Nov 2021 13:05:25 +0000 Subject: [PATCH 11/15] Further PR Comments --- Obsidian.API/Plugins/PluginBase.cs | 15 ++++++++------- Obsidian.Tests/Noise.cs | 13 +++---------- Obsidian/Obsidian.csproj | 1 + Obsidian/Utilities/RentedArray.cs | 2 -- Obsidian/WorldData/World.cs | 9 +-------- SamplePlugin/SamplePlugin.cs | 24 ++++++++++++------------ 6 files changed, 25 insertions(+), 39 deletions(-) diff --git a/Obsidian.API/Plugins/PluginBase.cs b/Obsidian.API/Plugins/PluginBase.cs index e8e34dc79..708f70d71 100644 --- a/Obsidian.API/Plugins/PluginBase.cs +++ b/Obsidian.API/Plugins/PluginBase.cs @@ -51,12 +51,12 @@ public Task FriendlyInvokeAsync(string methodName, params object[] args) args = args.Take(parameterCount).ToArray(); try { - var result = method?.Invoke(this, args); - if (result is Task task) - return task; - else if (result is ValueTask valueTask) - return valueTask.AsTask(); - return Task.FromResult(result); + var result = method?.Invoke(this, args); + if (result is Task task) + return task; + else if (result is ValueTask valueTask) + return valueTask.AsTask(); + return Task.FromResult(result); } catch (Exception e) { @@ -230,6 +230,7 @@ protected void Unload() break; } } + if (match) return (method, parameters.Length); } @@ -237,4 +238,4 @@ protected void Unload() return (null, -1); } } -} +} \ No newline at end of file diff --git a/Obsidian.Tests/Noise.cs b/Obsidian.Tests/Noise.cs index 6fc1a2502..3e7f21056 100644 --- a/Obsidian.Tests/Noise.cs +++ b/Obsidian.Tests/Noise.cs @@ -21,18 +21,11 @@ await Task.Run(() => var map = new NoiseMap(); - PlaneNoiseMapBuilder builder = new PlaneNoiseMapBuilder() - { - DestNoiseMap = map, - SourceModule = noiseGen.Result - }; + PlaneNoiseMapBuilder builder = + new PlaneNoiseMapBuilder() {DestNoiseMap = map, SourceModule = noiseGen.Result}; var image = new SharpNoise.Utilities.Imaging.Image(); - var renderer = new ImageRenderer() - { - SourceNoiseMap = map, - DestinationImage = image - }; + var renderer = new ImageRenderer() {SourceNoiseMap = map, DestinationImage = image}; //renderer.BuildGrayscaleGradient(); renderer.BuildTerrainGradient(); diff --git a/Obsidian/Obsidian.csproj b/Obsidian/Obsidian.csproj index b4f6fb15a..09ca724e6 100644 --- a/Obsidian/Obsidian.csproj +++ b/Obsidian/Obsidian.csproj @@ -4,6 +4,7 @@ Exe net5.0 9.0 + enable diff --git a/Obsidian/Utilities/RentedArray.cs b/Obsidian/Utilities/RentedArray.cs index 16eb5c02a..5f9e2581f 100644 --- a/Obsidian/Utilities/RentedArray.cs +++ b/Obsidian/Utilities/RentedArray.cs @@ -27,14 +27,12 @@ namespace Obsidian.Utilities /// public Memory Memory => array.AsMemory(0, Length); -#nullable enable public RentedArray(int length, ArrayPool? pool = null) { this.pool = pool ?? ArrayPool.Shared; array = this.pool.Rent(length); Length = length; } -#nullable disable /// /// Returns the rented array to the pool diff --git a/Obsidian/WorldData/World.cs b/Obsidian/WorldData/World.cs index a8029b09a..63e0e5d0f 100644 --- a/Obsidian/WorldData/World.cs +++ b/Obsidian/WorldData/World.cs @@ -529,14 +529,7 @@ public async Task ManageChunksAsync() public async Task FlushRegionsAsync() { - await Task.WhenAll(new List { - Task.Run(() => - { - Server.BroadcastMessage("Saving to disk..."); - Parallel.ForEach(Regions.Values, async r => await r.FlushAsync()); - Server.BroadcastMessage("Save complete."); - }) - }); + await Task.WhenAll(Regions.Values.Select(r => r.FlushAsync())); } public IEntity SpawnFallingBlock(VectorF position, Material mat) diff --git a/SamplePlugin/SamplePlugin.cs b/SamplePlugin/SamplePlugin.cs index bac82b8b2..d2f99a39a 100644 --- a/SamplePlugin/SamplePlugin.cs +++ b/SamplePlugin/SamplePlugin.cs @@ -7,9 +7,9 @@ namespace SamplePlugin { - [Plugin("Sample Plugin", "1.0", - "Obsidian Team", "My sample plugin.", - "https://github.com/Naamloos/Obsidian")] + [Plugin(name: "Sample Plugin", version: "1.0", + authors: "Obsidian Team", description: "My sample plugin.", + projectUrl: "https://github.com/Naamloos/Obsidian")] public class SamplePlugin : PluginBase { // Any interface from Obsidian.Plugins.Services can be injected into properties @@ -19,38 +19,38 @@ public class SamplePlugin : PluginBase // Dependencies will be injected automatically, if dependency class and field/property names match // Plugins won't load until all their required dependencies are added // Optional dependencies may be injected at any time, if at all - [Dependency("2.0", true), Alias("Sample Remote Plugin")] + [Dependency(minVersion: "2.0", optional: true), Alias(identifier: "Sample Remote Plugin")] public MyWrapper SampleRemotePlugin { get; set; } // One of server messages, called when an event occurs public void OnLoad(IServer server) { - Logger.Log($"§a{Info.Name} §floaded! Hello §a{server.DefaultWorld.Name}§f!"); - Logger.Log($"Hello! I live at §a{FileReader.CreateWorkingDirectory()}§f!"); + Logger.Log(message: $"§a{Info.Name} §floaded! Hello §a{server.DefaultWorld.Name}§f!"); + Logger.Log(message: $"Hello! I live at §a{FileReader.CreateWorkingDirectory()}§f!"); } public void OnPermissionRevoked(PermissionRevokedEventArgs args) { - Logger.Log($"Permission {args.Permission} revoked from player {args.Player.Username}"); + Logger.Log(message: $"Permission {args.Permission} revoked from player {args.Player.Username}"); } public void OnPermissionGranted(PermissionGrantedEventArgs args) { - Logger.Log($"Permission {args.Permission} granted to player {args.Player.Username}"); + Logger.Log(message: $"Permission {args.Permission} granted to player {args.Player.Username}"); } public async Task OnPlayerJoin(PlayerJoinEventArgs playerJoinEvent) { var player = playerJoinEvent.Player; - await player.SendMessageAsync(ChatMessage.Simple($"Welcome {player.Username}!", ChatColor.Gold)); + await player.SendMessageAsync(message: ChatMessage.Simple(text: $"Welcome {player.Username}!", color: ChatColor.Gold)); } - [Command("plugincommand")] - [CommandInfo("woop dee doo this command is from within a plugin class!!")] + [Command(commandName: "plugincommand")] + [CommandInfo(description: "woop dee doo this command is from within a plugin class!!")] public async Task PluginCommandAsync(CommandContext ctx) { - await ctx.Sender.SendMessageAsync("Hello from plugin command implemented in Plugin class!"); + await ctx.Sender.SendMessageAsync(message: "Hello from plugin command implemented in Plugin class!"); } } From 9658bd4f73a03ba3e500fc4b36934cea3bc24c15 Mon Sep 17 00:00:00 2001 From: Henry Migo Date: Tue, 2 Nov 2021 13:21:29 +0000 Subject: [PATCH 12/15] Additional PR comments --- Obsidian.API/Crafting/SmithingRecipe.cs | 4 +- Obsidian.API/Plugins/PluginWrapper.cs | 14 +- Obsidian.API/Plugins/Services/IFileWriter.cs | 20 +- Obsidian.API/_Interfaces/ILiving.cs | 2 +- Obsidian.API/_Interfaces/IPlayer.cs | 2 +- Obsidian.API/_Types/ChatMessage.cs | 22 -- Obsidian/Plugins/PluginContainer.cs | 2 +- Obsidian/WorldData/BlockUpdates.cs | 253 +++++++++---------- Obsidian/WorldData/World.cs | 2 +- 9 files changed, 148 insertions(+), 173 deletions(-) diff --git a/Obsidian.API/Crafting/SmithingRecipe.cs b/Obsidian.API/Crafting/SmithingRecipe.cs index 613150f08..40eb616a2 100644 --- a/Obsidian.API/Crafting/SmithingRecipe.cs +++ b/Obsidian.API/Crafting/SmithingRecipe.cs @@ -14,13 +14,13 @@ public sealed class SmithingRecipe : IRecipe public Ingredient Addition { get; set; } - public SmithingRecipe(string name, CraftingType type, string? group, Ingredient result, Ingredient Base, Ingredient addition) + public SmithingRecipe(string name, CraftingType type, string? group, Ingredient result, Ingredient @base, Ingredient addition) { Name = name; Type = type; Group = group; Result = result; - this.Base = Base; + Base = @base; Addition = addition; } } diff --git a/Obsidian.API/Plugins/PluginWrapper.cs b/Obsidian.API/Plugins/PluginWrapper.cs index 278284936..571787f94 100644 --- a/Obsidian.API/Plugins/PluginWrapper.cs +++ b/Obsidian.API/Plugins/PluginWrapper.cs @@ -7,11 +7,11 @@ namespace Obsidian.API.Plugins /// public abstract class PluginWrapper { - internal PluginBase Plugin; + internal PluginBase plugin; public PluginWrapper(PluginBase plugin) { - Plugin = plugin; + this.plugin = plugin; } #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. @@ -26,7 +26,7 @@ public PluginWrapper() /// public object? Invoke(string methodName, params object[] args) { - return Plugin.Invoke(methodName, args); + return plugin.Invoke(methodName, args); } /// @@ -34,7 +34,7 @@ public PluginWrapper() /// public T? Invoke(string methodName, params object[] args) { - return Plugin.Invoke(methodName, args); + return plugin.Invoke(methodName, args); } /// @@ -42,7 +42,7 @@ public PluginWrapper() /// public T GetMethod(string methodName, params Type[] parameterTypes) where T : Delegate { - return Plugin.GetMethod(methodName, parameterTypes); + return plugin.GetMethod(methodName, parameterTypes); } /// @@ -50,7 +50,7 @@ public T GetMethod(string methodName, params Type[] parameterTypes) where T : /// public Func GetPropertyGetter(string propertyName) { - return Plugin.GetPropertyGetter(propertyName); + return plugin.GetPropertyGetter(propertyName); } /// @@ -58,7 +58,7 @@ public Func GetPropertyGetter(string propertyName) /// public Action GetPropertySetter(string propertyName) { - return Plugin.GetPropertySetter(propertyName); + return plugin.GetPropertySetter(propertyName); } } } diff --git a/Obsidian.API/Plugins/Services/IFileWriter.cs b/Obsidian.API/Plugins/Services/IFileWriter.cs index 43af91404..a6e7fed0b 100644 --- a/Obsidian.API/Plugins/Services/IFileWriter.cs +++ b/Obsidian.API/Plugins/Services/IFileWriter.cs @@ -106,11 +106,11 @@ public void CopyFile(string sourceFileName, string destinationFileName) throw new SecurityException(SecurityExceptionMessage); string workingDirectory = GetWorkingDirectory(); - var fullPath1 = Path.GetDirectoryName(Path.GetFullPath(sourceFileName)); - var fullPath2 = Path.GetDirectoryName(Path.GetFullPath(destinationFileName)); + var sourceFilePath = Path.GetDirectoryName(Path.GetFullPath(sourceFileName)); + var destinationFilePath = Path.GetDirectoryName(Path.GetFullPath(destinationFileName)); var fullPathToCombine = Path.GetDirectoryName(Path.GetFullPath(workingDirectory)); - if (fullPath1 == null || fullPath2 == null) + if (sourceFilePath == null || destinationFilePath == null) { throw new DirectoryNotFoundException(); } @@ -120,13 +120,13 @@ public void CopyFile(string sourceFileName, string destinationFileName) throw new DirectoryNotFoundException(); } - if (!fullPath1.StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(sourceFileName)) throw new UnauthorizedAccessException(sourceFileName); + if (!sourceFilePath.StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(sourceFileName)) throw new UnauthorizedAccessException(sourceFileName); if (workingDirectory != null && !Path.IsPathFullyQualified(sourceFileName)) sourceFileName = Path.Combine(fullPathToCombine, sourceFileName); workingDirectory = GetWorkingDirectory(); - if (!fullPath2.StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(destinationFileName)) throw new UnauthorizedAccessException(destinationFileName); + if (!destinationFilePath.StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(destinationFileName)) throw new UnauthorizedAccessException(destinationFileName); if (workingDirectory != null && !Path.IsPathFullyQualified(destinationFileName)) destinationFileName = Path.Combine(fullPathToCombine, destinationFileName); @@ -143,11 +143,11 @@ public void MoveFile(string sourceFileName, string destinationFileName) throw new SecurityException(SecurityExceptionMessage); var workingDirectory = GetWorkingDirectory(); - var fullPath1 = Path.GetDirectoryName(Path.GetFullPath(sourceFileName)); - var fullPath2 = Path.GetDirectoryName(Path.GetFullPath(destinationFileName)); + var sourceFilePath = Path.GetDirectoryName(Path.GetFullPath(sourceFileName)); + var destinationFilePath = Path.GetDirectoryName(Path.GetFullPath(destinationFileName)); var fullPathToCombine = Path.GetDirectoryName(Path.GetFullPath(workingDirectory)); - if (fullPath1 == null || fullPath2 == null) + if (sourceFilePath == null || destinationFilePath == null) { throw new DirectoryNotFoundException(); } @@ -157,13 +157,13 @@ public void MoveFile(string sourceFileName, string destinationFileName) throw new DirectoryNotFoundException(); } - if (!fullPath1.StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(sourceFileName)) throw new UnauthorizedAccessException(sourceFileName); + if (!sourceFilePath.StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(sourceFileName)) throw new UnauthorizedAccessException(sourceFileName); if (workingDirectory != null && !Path.IsPathFullyQualified(sourceFileName)) sourceFileName = Path.Combine(fullPathToCombine, sourceFileName); workingDirectory = GetWorkingDirectory(); - if (!fullPath2.StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(destinationFileName)) throw new UnauthorizedAccessException(destinationFileName); + if (!destinationFilePath.StartsWith(workingDirectory, true, null) && Path.IsPathFullyQualified(destinationFileName)) throw new UnauthorizedAccessException(destinationFileName); if (workingDirectory != null && !Path.IsPathFullyQualified(destinationFileName)) destinationFileName = Path.Combine(fullPathToCombine, destinationFileName); diff --git a/Obsidian.API/_Interfaces/ILiving.cs b/Obsidian.API/_Interfaces/ILiving.cs index 90a8d82f6..2d1e6ca3d 100644 --- a/Obsidian.API/_Interfaces/ILiving.cs +++ b/Obsidian.API/_Interfaces/ILiving.cs @@ -4,7 +4,7 @@ public interface ILiving : IEntity { public LivingBitMask LivingBitMask { get; set; } - public new float Health { get; set; } + public float Health { get; set; } public uint ActiveEffectColor { get; } diff --git a/Obsidian.API/_Interfaces/IPlayer.cs b/Obsidian.API/_Interfaces/IPlayer.cs index be1048bab..06815ec54 100644 --- a/Obsidian.API/_Interfaces/IPlayer.cs +++ b/Obsidian.API/_Interfaces/IPlayer.cs @@ -10,7 +10,7 @@ public interface IPlayer : ILiving public string Username { get; } - public new Guid Uuid { get; } + public Guid Uuid { get; } public bool IsOperator { get; } public Gamemode Gamemode { get; set; } diff --git a/Obsidian.API/_Types/ChatMessage.cs b/Obsidian.API/_Types/ChatMessage.cs index 5e50c389e..60a497ec8 100644 --- a/Obsidian.API/_Types/ChatMessage.cs +++ b/Obsidian.API/_Types/ChatMessage.cs @@ -6,28 +6,6 @@ namespace Obsidian.API { public class ChatMessage { - public ChatMessage(string text, HexColor color, bool bold, bool italic, bool underlined, bool strikethrough, bool obfuscated, string insertion, ClickComponent clickEvent, HoverComponent hoverEvent, List extra) - { - Text = text; - Color = color; - Bold = bold; - Italic = italic; - Underlined = underlined; - Strikethrough = strikethrough; - Obfuscated = obfuscated; - Insertion = insertion; - ClickEvent = clickEvent; - HoverEvent = hoverEvent; - Extra = extra; - } - -#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. - public ChatMessage() -#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. - { - - } - public string Text { get; set; } public HexColor Color { get; set; } diff --git a/Obsidian/Plugins/PluginContainer.cs b/Obsidian/Plugins/PluginContainer.cs index 02dd5b6d8..eae288438 100644 --- a/Obsidian/Plugins/PluginContainer.cs +++ b/Obsidian/Plugins/PluginContainer.cs @@ -157,7 +157,7 @@ private static object CreateInjection(Type targetType, PluginBase plugin, ILogge return null; } - wrapper.Plugin = plugin; + wrapper.plugin = plugin; Type pluginType = plugin.GetType(); var methods = pluginType.GetMethods(); diff --git a/Obsidian/WorldData/BlockUpdates.cs b/Obsidian/WorldData/BlockUpdates.cs index 4b7723b69..c465d6b0e 100644 --- a/Obsidian/WorldData/BlockUpdates.cs +++ b/Obsidian/WorldData/BlockUpdates.cs @@ -27,166 +27,163 @@ internal static async Task HandleFallingBlock(BlockUpdate blockUpdate) internal static async Task HandleLiquidPhysics(BlockUpdate blockUpdate) { - return await Task.Run(() => + if (blockUpdate.block is null) { return false; } + + var block = blockUpdate.block.Value; + var world = blockUpdate.world; + var location = blockUpdate.position; + int state = block.State; + Vector belowPos = location + Vector.Down; + + // Handle the initial search for closet path downwards. + // Just going to do a crappy pathfind for now. We can do + // proper pathfinding some other time. + if (state == 0) { - if (blockUpdate.block is null) { return false; } - - var block = blockUpdate.block.Value; - var world = blockUpdate.world; - var location = blockUpdate.position; - int state = block.State; - Vector belowPos = location + Vector.Down; - - // Handle the initial search for closet path downwards. - // Just going to do a crappy pathfind for now. We can do - // proper pathfinding some other time. - if (state == 0) + var validPaths = new List(); + var paths = new List() { + {location + Vector.Forwards}, + {location + Vector.Backwards}, + {location + Vector.Left}, + {location + Vector.Right} + }; + + foreach (var pathLoc in paths) { - var validPaths = new List(); - var paths = new List() { - {location + Vector.Forwards}, - {location + Vector.Backwards}, - {location + Vector.Left}, - {location + Vector.Right} - }; - - foreach (var pathLoc in paths) + if (world.GetBlock(pathLoc) is Block pathSide && + (Block.Replaceable.Contains(pathSide.Material) || pathSide.IsFluid)) { - if (world.GetBlock(pathLoc) is Block pathSide && - (Block.Replaceable.Contains(pathSide.Material) || pathSide.IsFluid)) + var pathBelow = world.GetBlock(pathLoc + Vector.Down); + if (pathBelow is Block pBelow && + (Block.Replaceable.Contains(pBelow.Material) || pBelow.IsFluid)) { - var pathBelow = world.GetBlock(pathLoc + Vector.Down); - if (pathBelow is Block pBelow && - (Block.Replaceable.Contains(pBelow.Material) || pBelow.IsFluid)) - { - validPaths.Add(pathLoc); - } + validPaths.Add(pathLoc); } } + } - // if all directions are valid, or none are, use normal liquid spread physics instead - if (validPaths.Count != 4 && validPaths.Count != 0) - { - var path = validPaths[0]; - var newBlock = new Block(block.BaseId, state + 1); - world.SetBlock(path, newBlock); - var neighborUpdate = new BlockUpdate(world, path, newBlock); - world.ScheduleBlockUpdate(neighborUpdate); - return false; - } + // if all directions are valid, or none are, use normal liquid spread physics instead + if (validPaths.Count != 4 && validPaths.Count != 0) + { + var path = validPaths[0]; + var newBlock = new Block(block.BaseId, state + 1); + world.SetBlock(path, newBlock); + var neighborUpdate = new BlockUpdate(world, path, newBlock); + world.ScheduleBlockUpdate(neighborUpdate); + return false; } + } - if (state >= 8) // Falling water + if (state >= 8) // Falling water + { + // If above me is no longer water, than I should disappear too + if (world.GetBlock(location + Vector.Up) is Block up && !up.IsFluid) { - // If above me is no longer water, than I should disappear too - if (world.GetBlock(location + Vector.Up) is Block up && !up.IsFluid) - { - world.SetBlock(location, Block.Air); - world.ScheduleBlockUpdate(new BlockUpdate(world, belowPos)); - return false; - } + world.SetBlock(location, Block.Air); + world.ScheduleBlockUpdate(new BlockUpdate(world, belowPos)); + return false; + } - // Keep falling - if (world.GetBlock(belowPos) is Block below && Block.Replaceable.Contains(below.Material)) - { - var newBlock = new Block(block.BaseId, state); - world.SetBlock(belowPos, newBlock); - world.ScheduleBlockUpdate(new BlockUpdate(world, belowPos, newBlock)); - return false; - } - else - { - // Falling water has hit something solid. Change state to spread. - state = 1; - world.SetBlockUntracked(location, new Block(block.BaseId, state)); - } + // Keep falling + if (world.GetBlock(belowPos) is Block below && Block.Replaceable.Contains(below.Material)) + { + var newBlock = new Block(block.BaseId, state); + world.SetBlock(belowPos, newBlock); + world.ScheduleBlockUpdate(new BlockUpdate(world, belowPos, newBlock)); + return false; + } + else + { + // Falling water has hit something solid. Change state to spread. + state = 1; + world.SetBlockUntracked(location, new Block(block.BaseId, state)); } + } - if (state < 8) + if (state < 8) + { + var horizontalNeighbors = new Dictionary() { + {location + Vector.Forwards, world.GetBlock(location + Vector.Forwards)}, + {location + Vector.Backwards, world.GetBlock(location + Vector.Backwards)}, + {location + Vector.Left, world.GetBlock(location + Vector.Left)}, + {location + Vector.Right, world.GetBlock(location + Vector.Right)} + }; + + // Check infinite source blocks + if (state == 1 && block.Material == Material.Water) { - var horizontalNeighbors = new Dictionary() { - {location + Vector.Forwards, world.GetBlock(location + Vector.Forwards)}, - {location + Vector.Backwards, world.GetBlock(location + Vector.Backwards)}, - {location + Vector.Left, world.GetBlock(location + Vector.Left)}, - {location + Vector.Right, world.GetBlock(location + Vector.Right)} - }; - - // Check infinite source blocks - if (state == 1 && block.Material == Material.Water) + // if 2 neighbors are source blocks (state = 0), then become source block + int sourceNeighborCount = 0; + foreach (var (loc, neighborBlock) in horizontalNeighbors) { - // if 2 neighbors are source blocks (state = 0), then become source block - int sourceNeighborCount = 0; - foreach (var (loc, neighborBlock) in horizontalNeighbors) + if (neighborBlock is Block neighbor && neighbor.Material == block.Material && + neighbor.State == 0) { - if (neighborBlock is Block neighbor && neighbor.Material == block.Material && - neighbor.State == 0) - { - sourceNeighborCount++; - } - } - - if (sourceNeighborCount > 1) - { - var newBlock = new Block(Material.Water); - world.SetBlock(location, newBlock); - return true; + sourceNeighborCount++; } } - if (state > 0) + if (sourceNeighborCount > 1) { - // On some side of the block, there should be another water block with a lower state. - int lowestState = state; - foreach (var (loc, neighborBlock) in horizontalNeighbors) - { - if (neighborBlock.Value.Material == block.Material) - lowestState = Math.Min(lowestState, neighborBlock.Value.State); - } - - // If not, turn to air and update neighbors. - if (lowestState >= state && - world.GetBlock(location + Vector.Up).Value.Material != block.Material) - { - world.SetBlock(location, Block.Air); - return true; - } + var newBlock = new Block(Material.Water); + world.SetBlock(location, newBlock); + return true; } + } - if (world.GetBlock(belowPos) is Block below) + if (state > 0) + { + // On some side of the block, there should be another water block with a lower state. + int lowestState = state; + foreach (var (loc, neighborBlock) in horizontalNeighbors) { - if (below.Material == block.Material) { return false; } + if (neighborBlock.Value.Material == block.Material) + lowestState = Math.Min(lowestState, neighborBlock.Value.State); + } - if (Block.Replaceable.Contains(below.Material)) - { - var newBlock = new Block(block.BaseId, state + 8); - world.SetBlock(belowPos, newBlock); - var neighborUpdate = new BlockUpdate(world, belowPos, newBlock); - world.ScheduleBlockUpdate(neighborUpdate); - return false; - } + // If not, turn to air and update neighbors. + if (lowestState >= state && + world.GetBlock(location + Vector.Up).Value.Material != block.Material) + { + world.SetBlock(location, Block.Air); + return true; } + } - // the lowest level of water can only go down, so bail now. - if (state == 7) { return false; } + if (world.GetBlock(belowPos) is Block below) + { + if (below.Material == block.Material) { return false; } - foreach (var (loc, neighborBlock) in horizontalNeighbors) + if (Block.Replaceable.Contains(below.Material)) { - if (neighborBlock is null) { continue; } + var newBlock = new Block(block.BaseId, state + 8); + world.SetBlock(belowPos, newBlock); + var neighborUpdate = new BlockUpdate(world, belowPos, newBlock); + world.ScheduleBlockUpdate(neighborUpdate); + return false; + } + } - var neighbor = neighborBlock.Value; - if (Block.Replaceable.Contains(neighbor.Material) || - (neighbor.Material == block.Material && neighbor.State > state + 1)) - { - var newBlock = new Block(block.BaseId, state + 1); - world.SetBlock(loc, newBlock); - var neighborUpdate = new BlockUpdate(world, loc, newBlock); - world.ScheduleBlockUpdate(neighborUpdate); - } + // the lowest level of water can only go down, so bail now. + if (state == 7) { return false; } + + foreach (var (loc, neighborBlock) in horizontalNeighbors) + { + if (neighborBlock is null) { continue; } + + var neighbor = neighborBlock.Value; + if (Block.Replaceable.Contains(neighbor.Material) || + (neighbor.Material == block.Material && neighbor.State > state + 1)) + { + var newBlock = new Block(block.BaseId, state + 1); + world.SetBlock(loc, newBlock); + var neighborUpdate = new BlockUpdate(world, loc, newBlock); + world.ScheduleBlockUpdate(neighborUpdate); } } + } - return false; - }); + return false; } } } \ No newline at end of file diff --git a/Obsidian/WorldData/World.cs b/Obsidian/WorldData/World.cs index 63e0e5d0f..6e0ca8b42 100644 --- a/Obsidian/WorldData/World.cs +++ b/Obsidian/WorldData/World.cs @@ -529,7 +529,7 @@ public async Task ManageChunksAsync() public async Task FlushRegionsAsync() { - await Task.WhenAll(Regions.Values.Select(r => r.FlushAsync())); + await Task.WhenAll(Regions.Select(pair => pair.Value.FlushAsync())); } public IEntity SpawnFallingBlock(VectorF position, Material mat) From bacb05e05038efdf9d621f61938f1322a215b383 Mon Sep 17 00:00:00 2001 From: Henry Migo Date: Tue, 2 Nov 2021 14:52:29 +0000 Subject: [PATCH 13/15] Changed to sync which returns task --- Obsidian/WorldData/BlockUpdates.cs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Obsidian/WorldData/BlockUpdates.cs b/Obsidian/WorldData/BlockUpdates.cs index c465d6b0e..757e32bb0 100644 --- a/Obsidian/WorldData/BlockUpdates.cs +++ b/Obsidian/WorldData/BlockUpdates.cs @@ -25,9 +25,9 @@ internal static async Task HandleFallingBlock(BlockUpdate blockUpdate) return false; } - internal static async Task HandleLiquidPhysics(BlockUpdate blockUpdate) + internal static Task HandleLiquidPhysics(BlockUpdate blockUpdate) { - if (blockUpdate.block is null) { return false; } + if (blockUpdate.block is null) { return Task.FromResult(false); } var block = blockUpdate.block.Value; var world = blockUpdate.world; @@ -70,7 +70,7 @@ internal static async Task HandleLiquidPhysics(BlockUpdate blockUpdate) world.SetBlock(path, newBlock); var neighborUpdate = new BlockUpdate(world, path, newBlock); world.ScheduleBlockUpdate(neighborUpdate); - return false; + return Task.FromResult(false); } } @@ -81,7 +81,7 @@ internal static async Task HandleLiquidPhysics(BlockUpdate blockUpdate) { world.SetBlock(location, Block.Air); world.ScheduleBlockUpdate(new BlockUpdate(world, belowPos)); - return false; + return Task.FromResult(false); } // Keep falling @@ -90,7 +90,7 @@ internal static async Task HandleLiquidPhysics(BlockUpdate blockUpdate) var newBlock = new Block(block.BaseId, state); world.SetBlock(belowPos, newBlock); world.ScheduleBlockUpdate(new BlockUpdate(world, belowPos, newBlock)); - return false; + return Task.FromResult(false); } else { @@ -127,7 +127,7 @@ internal static async Task HandleLiquidPhysics(BlockUpdate blockUpdate) { var newBlock = new Block(Material.Water); world.SetBlock(location, newBlock); - return true; + return Task.FromResult(true); } } @@ -146,13 +146,13 @@ internal static async Task HandleLiquidPhysics(BlockUpdate blockUpdate) world.GetBlock(location + Vector.Up).Value.Material != block.Material) { world.SetBlock(location, Block.Air); - return true; + return Task.FromResult(true); } } if (world.GetBlock(belowPos) is Block below) { - if (below.Material == block.Material) { return false; } + if (below.Material == block.Material) { return Task.FromResult(false); } if (Block.Replaceable.Contains(below.Material)) { @@ -160,12 +160,12 @@ internal static async Task HandleLiquidPhysics(BlockUpdate blockUpdate) world.SetBlock(belowPos, newBlock); var neighborUpdate = new BlockUpdate(world, belowPos, newBlock); world.ScheduleBlockUpdate(neighborUpdate); - return false; + return Task.FromResult(false); } } // the lowest level of water can only go down, so bail now. - if (state == 7) { return false; } + if (state == 7) { return Task.FromResult(false); } foreach (var (loc, neighborBlock) in horizontalNeighbors) { @@ -183,7 +183,7 @@ internal static async Task HandleLiquidPhysics(BlockUpdate blockUpdate) } } - return false; + return Task.FromResult(false); } } } \ No newline at end of file From 9aacdbcddc60aee163fb126f0e5996f756acbfb1 Mon Sep 17 00:00:00 2001 From: henrymigo Date: Thu, 4 Nov 2021 18:59:42 +0000 Subject: [PATCH 14/15] PR Comment for constructor on PluginAttribute.cs --- Obsidian.API/Plugins/PluginAttribute.cs | 18 +++++------------- SamplePlugin/SamplePlugin.cs | 6 +++--- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/Obsidian.API/Plugins/PluginAttribute.cs b/Obsidian.API/Plugins/PluginAttribute.cs index 65dcc01d0..fd668a998 100644 --- a/Obsidian.API/Plugins/PluginAttribute.cs +++ b/Obsidian.API/Plugins/PluginAttribute.cs @@ -12,17 +12,9 @@ public class PluginAttribute : Attribute /// Plugin attribute constructor. /// /// - /// - /// - /// - /// - public PluginAttribute(string name, string version, string authors, string description, string projectUrl) + public PluginAttribute(string name) { Name = name; - Version = version; - Authors = authors; - Description = description; - ProjectUrl = projectUrl; } /// @@ -33,21 +25,21 @@ public PluginAttribute(string name, string version, string authors, string descr /// /// Version of the plugin. The string should contain the major, minor, [build], and [revision] numbers, split by a period character ('.'). /// - public string Version { get; } + public string Version { get; set; } /// /// Name(s) of the plugin's author(s). /// - public string Authors { get; } + public string Authors { get; set; } /// /// Description of the plugin. /// - public string Description { get; } + public string Description { get; set; } /// /// URL address of where the plugin is hosted. /// - public string ProjectUrl { get; } + public string ProjectUrl { get; set; } } } diff --git a/SamplePlugin/SamplePlugin.cs b/SamplePlugin/SamplePlugin.cs index d2f99a39a..2285bceb3 100644 --- a/SamplePlugin/SamplePlugin.cs +++ b/SamplePlugin/SamplePlugin.cs @@ -7,9 +7,9 @@ namespace SamplePlugin { - [Plugin(name: "Sample Plugin", version: "1.0", - authors: "Obsidian Team", description: "My sample plugin.", - projectUrl: "https://github.com/Naamloos/Obsidian")] + [Plugin(name: "Sample Plugin", Version = "1.0", + Authors = "Obsidian Team", Description = "My sample plugin.", + ProjectUrl = "https://github.com/Naamloos/Obsidian")] public class SamplePlugin : PluginBase { // Any interface from Obsidian.Plugins.Services can be injected into properties From 6dbc8c6c0b689109ed64608da8b4d71f37aa72a8 Mon Sep 17 00:00:00 2001 From: henrymigo Date: Thu, 4 Nov 2021 19:17:02 +0000 Subject: [PATCH 15/15] Made properties nullable that are not in constructor --- Obsidian.API/Plugins/PluginAttribute.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Obsidian.API/Plugins/PluginAttribute.cs b/Obsidian.API/Plugins/PluginAttribute.cs index fd668a998..6fdf71ea8 100644 --- a/Obsidian.API/Plugins/PluginAttribute.cs +++ b/Obsidian.API/Plugins/PluginAttribute.cs @@ -25,21 +25,21 @@ public PluginAttribute(string name) /// /// Version of the plugin. The string should contain the major, minor, [build], and [revision] numbers, split by a period character ('.'). /// - public string Version { get; set; } + public string? Version { get; set; } /// /// Name(s) of the plugin's author(s). /// - public string Authors { get; set; } + public string? Authors { get; set; } /// /// Description of the plugin. /// - public string Description { get; set; } + public string? Description { get; set; } /// /// URL address of where the plugin is hosted. /// - public string ProjectUrl { get; set; } + public string? ProjectUrl { get; set; } } }