From 017f42b7cd486c4e3d77fb23c9a736a70c23528e Mon Sep 17 00:00:00 2001 From: DrPerkyLegit <116128211+DrPerkyLegit@users.noreply.github.com> Date: Sat, 28 Mar 2026 14:33:54 -0400 Subject: [PATCH] add enchantments (#7) * adding enchantments added enchantments, changed minor apis to ensure c# stays synced with the c++ server * add missing enchant apis, oops * add proper docs, and fix namings for stuff in itemmeta --------- Co-authored-by: sylvessa <225480449+sylvessa@users.noreply.github.com> --- Minecraft.Server.FourKit/.editorconfig | 4 + .../Enchantments/AquaAffinityEnchantment.cs | 26 ++ .../BaneOfArthopodsEnchantment.cs | 31 ++ .../BlastProtectionEnchantment.cs | 34 +++ .../Enchantments/EfficiencyEnchantment.cs | 32 ++ .../Enchantments/Enchantment.cs | 274 ++++++++++++++++++ .../Enchantments/FeatherFallingEnchantment.cs | 26 ++ .../Enchantments/FireAspectEnchantment.cs | 27 ++ .../Enchantments/FireProtectionEnchantment.cs | 34 +++ .../Enchantments/FlameEnchantment.cs | 26 ++ .../Enchantments/FortuneEnchantment.cs | 31 ++ .../Enchantments/InfinityEnchantment.cs | 26 ++ .../Enchantments/KnockbackEnchantment.cs | 27 ++ .../Enchantments/LootingEnchantment.cs | 27 ++ .../Enchantments/PowerEnchantment.cs | 26 ++ .../ProjectileProtectionEnchantment.cs | 34 +++ .../Enchantments/ProtectionEnchantment.cs | 34 +++ .../Enchantments/PunchEnchantment.cs | 26 ++ .../Enchantments/RespirationEnchantment.cs | 26 ++ .../Enchantments/SharpnessEnchantment.cs | 30 ++ .../Enchantments/SilkTouchEnchantment.cs | 33 +++ .../Enchantments/SmiteEnchantment.cs | 30 ++ .../Enchantments/ThornsEnchantment.cs | 30 ++ .../Enchantments/UnbreakingEnchantment.cs | 39 +++ .../Inventory/ItemStack.cs | 1 + .../Inventory/Meta/ItemMeta.cs | 112 ++++++- .../Inventory/PlayerInventory.cs | 58 +++- Minecraft.Server/FourKitNatives.cpp | 81 +++++- 28 files changed, 1181 insertions(+), 4 deletions(-) create mode 100644 Minecraft.Server.FourKit/.editorconfig create mode 100644 Minecraft.Server.FourKit/Enchantments/AquaAffinityEnchantment.cs create mode 100644 Minecraft.Server.FourKit/Enchantments/BaneOfArthopodsEnchantment.cs create mode 100644 Minecraft.Server.FourKit/Enchantments/BlastProtectionEnchantment.cs create mode 100644 Minecraft.Server.FourKit/Enchantments/EfficiencyEnchantment.cs create mode 100644 Minecraft.Server.FourKit/Enchantments/Enchantment.cs create mode 100644 Minecraft.Server.FourKit/Enchantments/FeatherFallingEnchantment.cs create mode 100644 Minecraft.Server.FourKit/Enchantments/FireAspectEnchantment.cs create mode 100644 Minecraft.Server.FourKit/Enchantments/FireProtectionEnchantment.cs create mode 100644 Minecraft.Server.FourKit/Enchantments/FlameEnchantment.cs create mode 100644 Minecraft.Server.FourKit/Enchantments/FortuneEnchantment.cs create mode 100644 Minecraft.Server.FourKit/Enchantments/InfinityEnchantment.cs create mode 100644 Minecraft.Server.FourKit/Enchantments/KnockbackEnchantment.cs create mode 100644 Minecraft.Server.FourKit/Enchantments/LootingEnchantment.cs create mode 100644 Minecraft.Server.FourKit/Enchantments/PowerEnchantment.cs create mode 100644 Minecraft.Server.FourKit/Enchantments/ProjectileProtectionEnchantment.cs create mode 100644 Minecraft.Server.FourKit/Enchantments/ProtectionEnchantment.cs create mode 100644 Minecraft.Server.FourKit/Enchantments/PunchEnchantment.cs create mode 100644 Minecraft.Server.FourKit/Enchantments/RespirationEnchantment.cs create mode 100644 Minecraft.Server.FourKit/Enchantments/SharpnessEnchantment.cs create mode 100644 Minecraft.Server.FourKit/Enchantments/SilkTouchEnchantment.cs create mode 100644 Minecraft.Server.FourKit/Enchantments/SmiteEnchantment.cs create mode 100644 Minecraft.Server.FourKit/Enchantments/ThornsEnchantment.cs create mode 100644 Minecraft.Server.FourKit/Enchantments/UnbreakingEnchantment.cs diff --git a/Minecraft.Server.FourKit/.editorconfig b/Minecraft.Server.FourKit/.editorconfig new file mode 100644 index 000000000..d7a83b70c --- /dev/null +++ b/Minecraft.Server.FourKit/.editorconfig @@ -0,0 +1,4 @@ +[*.cs] + +# IDE1006: Naming Styles +dotnet_diagnostic.IDE1006.severity = suggestion diff --git a/Minecraft.Server.FourKit/Enchantments/AquaAffinityEnchantment.cs b/Minecraft.Server.FourKit/Enchantments/AquaAffinityEnchantment.cs new file mode 100644 index 000000000..970ea0df1 --- /dev/null +++ b/Minecraft.Server.FourKit/Enchantments/AquaAffinityEnchantment.cs @@ -0,0 +1,26 @@ +using Minecraft.Server.FourKit.Inventory; + +namespace Minecraft.Server.FourKit.Enchantments; + +public class AquaAffinityEnchantment : Enchantment +{ + static readonly Material[] supportedItems = { + Material.LEATHER_HELMET, Material.CHAINMAIL_HELMET, Material.GOLD_HELMET, Material.IRON_HELMET, Material.DIAMOND_HELMET, + }; + + static readonly EnchantmentType[] conflictedEnchants = { }; + + public override bool canEnchantItem(ItemStack item) => supportedItems.Contains(item.getType()); + + public override bool conflictsWith(Enchantment other) => conflictedEnchants.Contains(other.getEnchantType()); + + public override EnchantmentTarget getItemTarget() => EnchantmentTarget.ARMOR_HEAD; + + public override EnchantmentType getEnchantType() => EnchantmentType.WATER_WORKER; + + public override int getMaxLevel() => 1; + + public override string getName() => "aquaaffinity"; + + public override int getStartLevel() => 1; +} diff --git a/Minecraft.Server.FourKit/Enchantments/BaneOfArthopodsEnchantment.cs b/Minecraft.Server.FourKit/Enchantments/BaneOfArthopodsEnchantment.cs new file mode 100644 index 000000000..1d5654e35 --- /dev/null +++ b/Minecraft.Server.FourKit/Enchantments/BaneOfArthopodsEnchantment.cs @@ -0,0 +1,31 @@ +using Minecraft.Server.FourKit.Inventory; + +namespace Minecraft.Server.FourKit.Enchantments; + +//name could be changed +public class BaneOfArthropodsEnchantment : Enchantment +{ + static readonly Material[] supportedItems = { + Material.WOOD_SWORD, Material.STONE_SWORD, Material.IRON_SWORD, Material.GOLD_SWORD, Material.DIAMOND_SWORD, + Material.WOOD_AXE, Material.STONE_AXE, Material.IRON_AXE, Material.GOLD_AXE, Material.DIAMOND_AXE, + }; + + static readonly EnchantmentType[] conflictedEnchants = { + EnchantmentType.DAMAGE_ALL, + EnchantmentType.DAMAGE_UNDEAD, + }; + + public override bool canEnchantItem(ItemStack item) => supportedItems.Contains(item.getType()); + + public override bool conflictsWith(Enchantment other) => conflictedEnchants.Contains(other.getEnchantType()); + + public override EnchantmentTarget getItemTarget() => EnchantmentTarget.WEAPON; + + public override EnchantmentType getEnchantType() => EnchantmentType.DAMAGE_ARTHOPODS; + + public override int getMaxLevel() => 5; + + public override string getName() => "arthopods"; //could be changed + + public override int getStartLevel() => 1; +} diff --git a/Minecraft.Server.FourKit/Enchantments/BlastProtectionEnchantment.cs b/Minecraft.Server.FourKit/Enchantments/BlastProtectionEnchantment.cs new file mode 100644 index 000000000..3034302be --- /dev/null +++ b/Minecraft.Server.FourKit/Enchantments/BlastProtectionEnchantment.cs @@ -0,0 +1,34 @@ +using Minecraft.Server.FourKit.Inventory; + +namespace Minecraft.Server.FourKit.Enchantments; + +public class BlastProtectionEnchantment : Enchantment +{ + static readonly Material[] supportedItems = { + Material.LEATHER_HELMET, Material.LEATHER_CHESTPLATE, Material.LEATHER_LEGGINGS, Material.LEATHER_BOOTS, + Material.CHAINMAIL_HELMET, Material.CHAINMAIL_CHESTPLATE, Material.CHAINMAIL_LEGGINGS, Material.CHAINMAIL_BOOTS, + Material.GOLD_HELMET, Material.GOLD_CHESTPLATE, Material.GOLD_LEGGINGS, Material.GOLD_BOOTS, + Material.IRON_HELMET, Material.IRON_CHESTPLATE, Material.IRON_LEGGINGS, Material.IRON_BOOTS, + Material.DIAMOND_HELMET, Material.DIAMOND_CHESTPLATE, Material.DIAMOND_LEGGINGS, Material.DIAMOND_BOOTS, + }; + + static readonly EnchantmentType[] conflictedEnchants = { + EnchantmentType.PROTECTION_ENVIRONMENTAL, + EnchantmentType.PROTECTION_FIRE, + EnchantmentType.PROTECTION_PROJECTILE, + }; + + public override bool canEnchantItem(ItemStack item) => supportedItems.Contains(item.getType()); + + public override bool conflictsWith(Enchantment other) => conflictedEnchants.Contains(other.getEnchantType()); + + public override EnchantmentTarget getItemTarget() => EnchantmentTarget.ARMOR; + + public override EnchantmentType getEnchantType() => EnchantmentType.PROTECTION_EXPLOSIVE; + + public override int getMaxLevel() => 4; + + public override string getName() => "blastprotection"; + + public override int getStartLevel() => 1; +} diff --git a/Minecraft.Server.FourKit/Enchantments/EfficiencyEnchantment.cs b/Minecraft.Server.FourKit/Enchantments/EfficiencyEnchantment.cs new file mode 100644 index 000000000..5428ae878 --- /dev/null +++ b/Minecraft.Server.FourKit/Enchantments/EfficiencyEnchantment.cs @@ -0,0 +1,32 @@ +using Minecraft.Server.FourKit.Inventory; + +namespace Minecraft.Server.FourKit.Enchantments; + +public class EfficiencyEnchantment : Enchantment +{ + static readonly Material[] supportedItems = { + Material.WOOD_SWORD, Material.STONE_SWORD, Material.IRON_SWORD, Material.GOLD_SWORD, Material.DIAMOND_SWORD, + Material.WOOD_PICKAXE, Material.STONE_PICKAXE, Material.IRON_PICKAXE, Material.GOLD_PICKAXE, Material.DIAMOND_PICKAXE, + Material.WOOD_AXE, Material.STONE_AXE, Material.IRON_AXE, Material.GOLD_AXE, Material.DIAMOND_AXE, + Material.WOOD_SPADE, Material.STONE_SPADE, Material.IRON_SPADE, Material.GOLD_SPADE, Material.DIAMOND_SPADE, + Material.WOOD_HOE, Material.STONE_HOE, Material.IRON_HOE, Material.GOLD_HOE, Material.DIAMOND_HOE, + + Material.SHEARS + }; + + static readonly EnchantmentType[] conflictedEnchants = { }; + + public override bool canEnchantItem(ItemStack item) => supportedItems.Contains(item.getType()); + + public override bool conflictsWith(Enchantment other) => conflictedEnchants.Contains(other.getEnchantType()); + + public override EnchantmentTarget getItemTarget() => EnchantmentTarget.TOOL; + + public override EnchantmentType getEnchantType() => EnchantmentType.DIG_SPEAD; + + public override int getMaxLevel() => 5; + + public override string getName() => "efficiency"; + + public override int getStartLevel() => 1; +} diff --git a/Minecraft.Server.FourKit/Enchantments/Enchantment.cs b/Minecraft.Server.FourKit/Enchantments/Enchantment.cs new file mode 100644 index 000000000..e3daa5492 --- /dev/null +++ b/Minecraft.Server.FourKit/Enchantments/Enchantment.cs @@ -0,0 +1,274 @@ +namespace Minecraft.Server.FourKit.Enchantments; + +using Minecraft.Server.FourKit.Inventory; + +/// +/// Represents the applicable target for a Enchantment +/// +public enum EnchantmentTarget +{ + /// + /// Allows the Enchantment to be placed on all items + /// + ALL, + /// + /// Allows the Enchantment to be placed on armor + /// + ARMOR, + /// + /// Allows the Enchantment to be placed on feet slot armor + /// + ARMOR_FEET, + /// + /// Allows the Enchantment to be placed on head slot armor + /// + ARMOR_HEAD, + /// + /// Allows the Enchantment to be placed on leg slot armor + /// + ARMOR_LEGS, + /// + /// Allows the Enchantment to be placed on torso slot armor + /// + ARMOR_TORSO, + /// + /// Allows the Enchantment to be placed on bows. + /// + BOW, + /// + /// Allows the Enchantment to be placed on tools (spades, pickaxe, hoes, axes) + /// + TOOL, + /// + /// Allows the Enchantment to be placed on weapons (swords) + /// + WEAPON, +} + +//these numbers match the same ones that the enchants register as, Enchantment.cpp - 41 + +/// +/// The various type of enchantments that may be added to armour or weapons +/// +public enum EnchantmentType +{ + /// + /// Provides extra damage when shooting arrows from bows + /// + ARROW_DAMAGE = 48, + /// + /// Sets entities on fire when hit by arrows shot from a bow + /// + ARROW_FIRE = 50, + /// + /// Provides infinite arrows when shooting a bow + /// + ARROW_INFINITE = 51, + /// + /// Provides a knockback when an entity is hit by an arrow from a bow + /// + ARROW_KNOCKBACK = 49, + /// + /// Increases damage against all targets + /// + DAMAGE_ALL = 16, + /// + /// Increases damage against arthropod targets + /// + DAMAGE_ARTHOPODS = 18, + /// + /// Increases damage against undead targets + /// + DAMAGE_UNDEAD = 17, + /// + /// Increases the rate at which you mine/dig + /// + DIG_SPEAD = 32, + /// + /// Decreases the rate at which a tool looses durability + /// + DURABILITY = 34, + /// + /// When attacking a target, has a chance to set them on fire + /// + FIRE_ASPECT = 20, + /// + /// All damage to other targets will knock them back when hit + /// + KNOCKBACK = 19, + /// + /// Provides a chance of gaining extra loot when destroying blocks + /// + LOOT_BONUS_BLOCKS = 35, + /// + /// Provides a chance of gaining extra loot when killing monsters + /// + LOOT_BONUS_MOBS = 21, + /// + /// Decreases the rate of air loss whilst underwater + /// + OXYGEN = 5, + /// + /// Provides protection against environmental damage + /// + PROTECTION_ENVIRONMENTAL = 0, + /// + /// Provides protection against explosive damage + /// + PROTECTION_EXPLOSIVE = 3, + /// + /// Provides protection against fall damage + /// + PROTECTION_FALL = 2, + /// + /// Provides protection against fire damage + /// + PROTECTION_FIRE = 1, + /// + /// Provides protection against projectile damage + /// + PROTECTION_PROJECTILE = 4, + /// + /// Allows blocks to drop themselves instead of fragments (for example, stone instead of cobblestone) + /// + SILK_TOUCH = 33, + /// + /// Damages the attacker + /// + THORNS = 7, + /// + /// Increases the speed at which a player may mine underwater + /// + WATER_WORKER = 6 +} + +public abstract class Enchantment +{ + public static Enchantment PowerEnchantment => _registry[EnchantmentType.ARROW_DAMAGE]; + public static Enchantment FlameEnchantment => _registry[EnchantmentType.ARROW_FIRE]; + public static Enchantment InfinityEnchantment => _registry[EnchantmentType.ARROW_INFINITE]; + public static Enchantment PunchEnchantment => _registry[EnchantmentType.ARROW_KNOCKBACK]; + public static Enchantment SharpnessEnchantment => _registry[EnchantmentType.DAMAGE_ALL]; + public static Enchantment BaneOfArthropodsEnchantment => _registry[EnchantmentType.DAMAGE_ARTHOPODS]; + public static Enchantment SmiteEnchantment => _registry[EnchantmentType.DAMAGE_UNDEAD]; + public static Enchantment EfficiencyEnchantment => _registry[EnchantmentType.DIG_SPEAD]; + public static Enchantment UnbreakingEnchantment => _registry[EnchantmentType.DURABILITY]; + public static Enchantment FireAspectEnchantment => _registry[EnchantmentType.FIRE_ASPECT]; + public static Enchantment KnockbackEnchantment => _registry[EnchantmentType.KNOCKBACK]; + public static Enchantment FortuneEnchantment => _registry[EnchantmentType.LOOT_BONUS_BLOCKS]; + public static Enchantment LootingEnchantment => _registry[EnchantmentType.LOOT_BONUS_MOBS]; + public static Enchantment RespirationEnchantment => _registry[EnchantmentType.OXYGEN]; + public static Enchantment ProtectionEnchantment => _registry[EnchantmentType.PROTECTION_ENVIRONMENTAL]; + public static Enchantment BlastProtectionEnchantment => _registry[EnchantmentType.PROTECTION_EXPLOSIVE]; + public static Enchantment FeatherFallingEnchantment => _registry[EnchantmentType.PROTECTION_FALL]; + public static Enchantment FireProtectionEnchantment => _registry[EnchantmentType.PROTECTION_FIRE]; + public static Enchantment ProjectileProtectionEnchantment => _registry[EnchantmentType.PROTECTION_PROJECTILE]; + public static Enchantment SilkTouchEnchantment => _registry[EnchantmentType.SILK_TOUCH]; + public static Enchantment ThornsEnchantment => _registry[EnchantmentType.THORNS]; + public static Enchantment AquaAffinityEnchantment => _registry[EnchantmentType.WATER_WORKER]; + + + private static Dictionary _registry = new Dictionary() + { + { EnchantmentType.ARROW_DAMAGE, new PowerEnchantment() }, + { EnchantmentType.ARROW_FIRE, new FlameEnchantment() }, + { EnchantmentType.ARROW_INFINITE, new InfinityEnchantment() }, + { EnchantmentType.ARROW_KNOCKBACK, new PunchEnchantment() }, + { EnchantmentType.DAMAGE_ALL, new SharpnessEnchantment() }, + { EnchantmentType.DAMAGE_ARTHOPODS, new BaneOfArthropodsEnchantment() }, + { EnchantmentType.DAMAGE_UNDEAD, new SmiteEnchantment() }, + { EnchantmentType.DIG_SPEAD, new EfficiencyEnchantment() }, + { EnchantmentType.DURABILITY, new UnbreakingEnchantment() }, + { EnchantmentType.FIRE_ASPECT, new FireAspectEnchantment() }, + { EnchantmentType.KNOCKBACK, new KnockbackEnchantment() }, + { EnchantmentType.LOOT_BONUS_BLOCKS, new FortuneEnchantment() }, + { EnchantmentType.LOOT_BONUS_MOBS, new LootingEnchantment() }, + { EnchantmentType.OXYGEN, new RespirationEnchantment() }, + { EnchantmentType.PROTECTION_ENVIRONMENTAL, new ProtectionEnchantment() }, + { EnchantmentType.PROTECTION_EXPLOSIVE, new BlastProtectionEnchantment() }, + { EnchantmentType.PROTECTION_FALL, new FeatherFallingEnchantment() }, + { EnchantmentType.PROTECTION_FIRE, new FireProtectionEnchantment() }, + { EnchantmentType.PROTECTION_PROJECTILE, new ProjectileProtectionEnchantment() }, + { EnchantmentType.SILK_TOUCH, new SilkTouchEnchantment() }, + { EnchantmentType.THORNS, new ThornsEnchantment() }, + { EnchantmentType.WATER_WORKER, new AquaAffinityEnchantment() }, + }; + + /// + /// Checks if this Enchantment may be applied to the given . This does not check if it conflicts with any enchantments already applied to the item. + /// + /// Item to test + /// True if the enchantment may be applied, otherwise False + public abstract bool canEnchantItem(ItemStack item); + + /// + /// Check if this enchantment conflicts with another enchantment. + /// + /// The enchantment to check against + /// True if there is a conflict. + public abstract bool conflictsWith(Enchantment other); + //public abstract Enchantment getById(int id); //deprecated by bukkit + + /// + /// Gets the Enchantment at the specified name + /// + /// Name to fetch. + /// Resulting Enchantment, or null if not found + public static Enchantment? getByName(string name) + { + foreach (KeyValuePair enchantmentPair in _registry) + { + if (enchantmentPair.Value.getName().Equals(name)) return enchantmentPair.Value; + } + + return null; + } + + /// + /// Gets the Enchantment at the specified type + /// + /// Type to fetch. + /// Resulting Enchantment, or null if not found + public static Enchantment getByType(EnchantmentType type) + { + return _registry[type]; //we should always have the enchant based on the type + } + + //public abstract int getId(); //deprecated by bukkit + + /// + /// Gets the type of that may fit this Enchantment. + /// + /// Gets the type of that may fit this Enchantment. + public abstract EnchantmentTarget getItemTarget(); + + /// + /// Returns the . + /// + /// Gets the enchantment type. + public abstract EnchantmentType getEnchantType(); + + /// + /// Gets the maximum level that this Enchantment may become. + /// + /// Maximum level of the Enchantment + public abstract int getMaxLevel(); + + + /// + /// Gets the unique name of this enchantment + /// + /// Unique name + public abstract string getName(); + + /// + /// Gets the level that this Enchantment should start at + /// + /// Starting level of the Enchantment + public abstract int getStartLevel(); + + //public static bool isAcceptingRegistrations(); //we dont have enchant registrations + //public static void registerEnchantment(Enchantment enchantment); //we dont have enchant registrations + //public static void stopAcceptingRegistrations(); //we dont have enchant registrations + +} \ No newline at end of file diff --git a/Minecraft.Server.FourKit/Enchantments/FeatherFallingEnchantment.cs b/Minecraft.Server.FourKit/Enchantments/FeatherFallingEnchantment.cs new file mode 100644 index 000000000..f27e56d27 --- /dev/null +++ b/Minecraft.Server.FourKit/Enchantments/FeatherFallingEnchantment.cs @@ -0,0 +1,26 @@ +using Minecraft.Server.FourKit.Inventory; + +namespace Minecraft.Server.FourKit.Enchantments; + +public class FeatherFallingEnchantment : Enchantment +{ + static readonly Material[] supportedItems = { + Material.LEATHER_BOOTS, Material.LEATHER_BOOTS, Material.CHAINMAIL_BOOTS, Material.GOLD_BOOTS, Material.IRON_BOOTS, Material.DIAMOND_BOOTS, + }; + + static readonly EnchantmentType[] conflictedEnchants = { }; + + public override bool canEnchantItem(ItemStack item) => supportedItems.Contains(item.getType()); + + public override bool conflictsWith(Enchantment other) => conflictedEnchants.Contains(other.getEnchantType()); + + public override EnchantmentTarget getItemTarget() => EnchantmentTarget.ARMOR_FEET; + + public override EnchantmentType getEnchantType() => EnchantmentType.PROTECTION_FALL; + + public override int getMaxLevel() => 4; + + public override string getName() => "featherfalling"; + + public override int getStartLevel() => 1; +} diff --git a/Minecraft.Server.FourKit/Enchantments/FireAspectEnchantment.cs b/Minecraft.Server.FourKit/Enchantments/FireAspectEnchantment.cs new file mode 100644 index 000000000..c7a8b5c59 --- /dev/null +++ b/Minecraft.Server.FourKit/Enchantments/FireAspectEnchantment.cs @@ -0,0 +1,27 @@ +using Minecraft.Server.FourKit.Inventory; + +namespace Minecraft.Server.FourKit.Enchantments; + +public class FireAspectEnchantment : Enchantment +{ + static readonly Material[] supportedItems = { + Material.WOOD_SWORD, Material.STONE_SWORD, Material.IRON_SWORD, Material.GOLD_SWORD, Material.DIAMOND_SWORD, + Material.WOOD_AXE, Material.STONE_AXE, Material.IRON_AXE, Material.GOLD_AXE, Material.DIAMOND_AXE, + }; + + static readonly EnchantmentType[] conflictedEnchants = { }; + + public override bool canEnchantItem(ItemStack item) => supportedItems.Contains(item.getType()); + + public override bool conflictsWith(Enchantment other) => conflictedEnchants.Contains(other.getEnchantType()); + + public override EnchantmentTarget getItemTarget() => EnchantmentTarget.WEAPON; + + public override EnchantmentType getEnchantType() => EnchantmentType.FIRE_ASPECT; + + public override int getMaxLevel() => 2; + + public override string getName() => "fireaspect"; + + public override int getStartLevel() => 1; +} diff --git a/Minecraft.Server.FourKit/Enchantments/FireProtectionEnchantment.cs b/Minecraft.Server.FourKit/Enchantments/FireProtectionEnchantment.cs new file mode 100644 index 000000000..09f2c8eaf --- /dev/null +++ b/Minecraft.Server.FourKit/Enchantments/FireProtectionEnchantment.cs @@ -0,0 +1,34 @@ +using Minecraft.Server.FourKit.Inventory; + +namespace Minecraft.Server.FourKit.Enchantments; + +public class FireProtectionEnchantment : Enchantment +{ + static readonly Material[] supportedItems = { + Material.LEATHER_HELMET, Material.LEATHER_CHESTPLATE, Material.LEATHER_LEGGINGS, Material.LEATHER_BOOTS, + Material.CHAINMAIL_HELMET, Material.CHAINMAIL_CHESTPLATE, Material.CHAINMAIL_LEGGINGS, Material.CHAINMAIL_BOOTS, + Material.GOLD_HELMET, Material.GOLD_CHESTPLATE, Material.GOLD_LEGGINGS, Material.GOLD_BOOTS, + Material.IRON_HELMET, Material.IRON_CHESTPLATE, Material.IRON_LEGGINGS, Material.IRON_BOOTS, + Material.DIAMOND_HELMET, Material.DIAMOND_CHESTPLATE, Material.DIAMOND_LEGGINGS, Material.DIAMOND_BOOTS, + }; + + static readonly EnchantmentType[] conflictedEnchants = { + EnchantmentType.PROTECTION_ENVIRONMENTAL, + EnchantmentType.PROTECTION_EXPLOSIVE, + EnchantmentType.PROTECTION_PROJECTILE, + }; + + public override bool canEnchantItem(ItemStack item) => supportedItems.Contains(item.getType()); + + public override bool conflictsWith(Enchantment other) => conflictedEnchants.Contains(other.getEnchantType()); + + public override EnchantmentTarget getItemTarget() => EnchantmentTarget.ARMOR; + + public override EnchantmentType getEnchantType() => EnchantmentType.PROTECTION_FIRE; + + public override int getMaxLevel() => 4; + + public override string getName() => "fireprotection"; + + public override int getStartLevel() => 1; +} diff --git a/Minecraft.Server.FourKit/Enchantments/FlameEnchantment.cs b/Minecraft.Server.FourKit/Enchantments/FlameEnchantment.cs new file mode 100644 index 000000000..4166170b1 --- /dev/null +++ b/Minecraft.Server.FourKit/Enchantments/FlameEnchantment.cs @@ -0,0 +1,26 @@ +using Minecraft.Server.FourKit.Inventory; + +namespace Minecraft.Server.FourKit.Enchantments; + +public class FlameEnchantment : Enchantment +{ + static readonly Material[] supportedItems = { + Material.BOW + }; + + static readonly EnchantmentType[] conflictedEnchants = { }; + + public override bool canEnchantItem(ItemStack item) => supportedItems.Contains(item.getType()); + + public override bool conflictsWith(Enchantment other) => conflictedEnchants.Contains(other.getEnchantType()); + + public override EnchantmentTarget getItemTarget() => EnchantmentTarget.BOW; + + public override EnchantmentType getEnchantType() => EnchantmentType.ARROW_FIRE; + + public override int getMaxLevel() => 1; + + public override string getName() => "flame"; + + public override int getStartLevel() => 1; +} diff --git a/Minecraft.Server.FourKit/Enchantments/FortuneEnchantment.cs b/Minecraft.Server.FourKit/Enchantments/FortuneEnchantment.cs new file mode 100644 index 000000000..d3477b270 --- /dev/null +++ b/Minecraft.Server.FourKit/Enchantments/FortuneEnchantment.cs @@ -0,0 +1,31 @@ +using Minecraft.Server.FourKit.Inventory; + +namespace Minecraft.Server.FourKit.Enchantments; + +public class FortuneEnchantment : Enchantment +{ + static readonly Material[] supportedItems = { + Material.WOOD_PICKAXE, Material.STONE_PICKAXE, Material.IRON_PICKAXE, Material.GOLD_PICKAXE, Material.DIAMOND_PICKAXE, + Material.WOOD_AXE, Material.STONE_AXE, Material.IRON_AXE, Material.GOLD_AXE, Material.DIAMOND_AXE, + Material.WOOD_SPADE, Material.STONE_SPADE, Material.IRON_SPADE, Material.GOLD_SPADE, Material.DIAMOND_SPADE, + Material.WOOD_HOE, Material.STONE_HOE, Material.IRON_HOE, Material.GOLD_HOE, Material.DIAMOND_HOE, + }; + + static readonly EnchantmentType[] conflictedEnchants = { + EnchantmentType.SILK_TOUCH + }; + + public override bool canEnchantItem(ItemStack item) => supportedItems.Contains(item.getType()); + + public override bool conflictsWith(Enchantment other) => conflictedEnchants.Contains(other.getEnchantType()); + + public override EnchantmentTarget getItemTarget() => EnchantmentTarget.TOOL; + + public override EnchantmentType getEnchantType() => EnchantmentType.LOOT_BONUS_BLOCKS; + + public override int getMaxLevel() => 3; + + public override string getName() => "fortune"; + + public override int getStartLevel() => 1; +} diff --git a/Minecraft.Server.FourKit/Enchantments/InfinityEnchantment.cs b/Minecraft.Server.FourKit/Enchantments/InfinityEnchantment.cs new file mode 100644 index 000000000..f1c697b7b --- /dev/null +++ b/Minecraft.Server.FourKit/Enchantments/InfinityEnchantment.cs @@ -0,0 +1,26 @@ +using Minecraft.Server.FourKit.Inventory; + +namespace Minecraft.Server.FourKit.Enchantments; + +public class InfinityEnchantment : Enchantment +{ + static readonly Material[] supportedItems = { + Material.BOW + }; + + static readonly EnchantmentType[] conflictedEnchants = { }; + + public override bool canEnchantItem(ItemStack item) => supportedItems.Contains(item.getType()); + + public override bool conflictsWith(Enchantment other) => conflictedEnchants.Contains(other.getEnchantType()); + + public override EnchantmentTarget getItemTarget() => EnchantmentTarget.BOW; + + public override EnchantmentType getEnchantType() => EnchantmentType.ARROW_INFINITE; + + public override int getMaxLevel() => 1; + + public override string getName() => "infinity"; + + public override int getStartLevel() => 1; +} diff --git a/Minecraft.Server.FourKit/Enchantments/KnockbackEnchantment.cs b/Minecraft.Server.FourKit/Enchantments/KnockbackEnchantment.cs new file mode 100644 index 000000000..5a508a421 --- /dev/null +++ b/Minecraft.Server.FourKit/Enchantments/KnockbackEnchantment.cs @@ -0,0 +1,27 @@ +using Minecraft.Server.FourKit.Inventory; + +namespace Minecraft.Server.FourKit.Enchantments; + +public class KnockbackEnchantment : Enchantment +{ + static readonly Material[] supportedItems = { + Material.WOOD_SWORD, Material.STONE_SWORD, Material.IRON_SWORD, Material.GOLD_SWORD, Material.DIAMOND_SWORD, + Material.WOOD_AXE, Material.STONE_AXE, Material.IRON_AXE, Material.GOLD_AXE, Material.DIAMOND_AXE, + }; + + static readonly EnchantmentType[] conflictedEnchants = { }; + + public override bool canEnchantItem(ItemStack item) => supportedItems.Contains(item.getType()); + + public override bool conflictsWith(Enchantment other) => conflictedEnchants.Contains(other.getEnchantType()); + + public override EnchantmentTarget getItemTarget() => EnchantmentTarget.WEAPON; + + public override EnchantmentType getEnchantType() => EnchantmentType.KNOCKBACK; + + public override int getMaxLevel() => 2; + + public override string getName() => "knockback"; + + public override int getStartLevel() => 1; +} diff --git a/Minecraft.Server.FourKit/Enchantments/LootingEnchantment.cs b/Minecraft.Server.FourKit/Enchantments/LootingEnchantment.cs new file mode 100644 index 000000000..710b65188 --- /dev/null +++ b/Minecraft.Server.FourKit/Enchantments/LootingEnchantment.cs @@ -0,0 +1,27 @@ +using Minecraft.Server.FourKit.Inventory; + +namespace Minecraft.Server.FourKit.Enchantments; + +public class LootingEnchantment : Enchantment +{ + static readonly Material[] supportedItems = { + Material.WOOD_PICKAXE, Material.STONE_PICKAXE, Material.IRON_PICKAXE, Material.GOLD_PICKAXE, Material.DIAMOND_PICKAXE, + Material.WOOD_AXE, Material.STONE_AXE, Material.IRON_AXE, Material.GOLD_AXE, Material.DIAMOND_AXE, + }; + + static readonly EnchantmentType[] conflictedEnchants = { }; + + public override bool canEnchantItem(ItemStack item) => supportedItems.Contains(item.getType()); + + public override bool conflictsWith(Enchantment other) => conflictedEnchants.Contains(other.getEnchantType()); + + public override EnchantmentTarget getItemTarget() => EnchantmentTarget.WEAPON; + + public override EnchantmentType getEnchantType() => EnchantmentType.LOOT_BONUS_MOBS; + + public override int getMaxLevel() => 3; + + public override string getName() => "looting"; + + public override int getStartLevel() => 1; +} diff --git a/Minecraft.Server.FourKit/Enchantments/PowerEnchantment.cs b/Minecraft.Server.FourKit/Enchantments/PowerEnchantment.cs new file mode 100644 index 000000000..f5e93e5a7 --- /dev/null +++ b/Minecraft.Server.FourKit/Enchantments/PowerEnchantment.cs @@ -0,0 +1,26 @@ +using Minecraft.Server.FourKit.Inventory; + +namespace Minecraft.Server.FourKit.Enchantments; + +public class PowerEnchantment : Enchantment +{ + static readonly Material[] supportedItems = { + Material.BOW + }; + + static readonly EnchantmentType[] conflictedEnchants = { }; + + public override bool canEnchantItem(ItemStack item) => supportedItems.Contains(item.getType()); + + public override bool conflictsWith(Enchantment other) => conflictedEnchants.Contains(other.getEnchantType()); + + public override EnchantmentTarget getItemTarget() => EnchantmentTarget.BOW; + + public override EnchantmentType getEnchantType() => EnchantmentType.ARROW_DAMAGE; + + public override int getMaxLevel() => 5; + + public override string getName() => "power"; + + public override int getStartLevel() => 1; +} diff --git a/Minecraft.Server.FourKit/Enchantments/ProjectileProtectionEnchantment.cs b/Minecraft.Server.FourKit/Enchantments/ProjectileProtectionEnchantment.cs new file mode 100644 index 000000000..31706216d --- /dev/null +++ b/Minecraft.Server.FourKit/Enchantments/ProjectileProtectionEnchantment.cs @@ -0,0 +1,34 @@ +using Minecraft.Server.FourKit.Inventory; + +namespace Minecraft.Server.FourKit.Enchantments; + +public class ProjectileProtectionEnchantment : Enchantment +{ + static readonly Material[] supportedItems = { + Material.LEATHER_HELMET, Material.LEATHER_CHESTPLATE, Material.LEATHER_LEGGINGS, Material.LEATHER_BOOTS, + Material.CHAINMAIL_HELMET, Material.CHAINMAIL_CHESTPLATE, Material.CHAINMAIL_LEGGINGS, Material.CHAINMAIL_BOOTS, + Material.GOLD_HELMET, Material.GOLD_CHESTPLATE, Material.GOLD_LEGGINGS, Material.GOLD_BOOTS, + Material.IRON_HELMET, Material.IRON_CHESTPLATE, Material.IRON_LEGGINGS, Material.IRON_BOOTS, + Material.DIAMOND_HELMET, Material.DIAMOND_CHESTPLATE, Material.DIAMOND_LEGGINGS, Material.DIAMOND_BOOTS, + }; + + static readonly EnchantmentType[] conflictedEnchants = { + EnchantmentType.PROTECTION_ENVIRONMENTAL, + EnchantmentType.PROTECTION_EXPLOSIVE, + EnchantmentType.PROTECTION_FIRE, + }; + + public override bool canEnchantItem(ItemStack item) => supportedItems.Contains(item.getType()); + + public override bool conflictsWith(Enchantment other) => conflictedEnchants.Contains(other.getEnchantType()); + + public override EnchantmentTarget getItemTarget() => EnchantmentTarget.ARMOR; + + public override EnchantmentType getEnchantType() => EnchantmentType.PROTECTION_PROJECTILE; + + public override int getMaxLevel() => 4; + + public override string getName() => "projectileprotection"; + + public override int getStartLevel() => 1; +} diff --git a/Minecraft.Server.FourKit/Enchantments/ProtectionEnchantment.cs b/Minecraft.Server.FourKit/Enchantments/ProtectionEnchantment.cs new file mode 100644 index 000000000..70fe5d857 --- /dev/null +++ b/Minecraft.Server.FourKit/Enchantments/ProtectionEnchantment.cs @@ -0,0 +1,34 @@ +using Minecraft.Server.FourKit.Inventory; + +namespace Minecraft.Server.FourKit.Enchantments; + +public class ProtectionEnchantment : Enchantment +{ + static readonly Material[] supportedItems = { + Material.LEATHER_HELMET, Material.LEATHER_CHESTPLATE, Material.LEATHER_LEGGINGS, Material.LEATHER_BOOTS, + Material.CHAINMAIL_HELMET, Material.CHAINMAIL_CHESTPLATE, Material.CHAINMAIL_LEGGINGS, Material.CHAINMAIL_BOOTS, + Material.GOLD_HELMET, Material.GOLD_CHESTPLATE, Material.GOLD_LEGGINGS, Material.GOLD_BOOTS, + Material.IRON_HELMET, Material.IRON_CHESTPLATE, Material.IRON_LEGGINGS, Material.IRON_BOOTS, + Material.DIAMOND_HELMET, Material.DIAMOND_CHESTPLATE, Material.DIAMOND_LEGGINGS, Material.DIAMOND_BOOTS, + }; + + static readonly EnchantmentType[] conflictedEnchants = { + EnchantmentType.PROTECTION_EXPLOSIVE, + EnchantmentType.PROTECTION_FIRE, + EnchantmentType.PROTECTION_PROJECTILE, + }; + + public override bool canEnchantItem(ItemStack item) => supportedItems.Contains(item.getType()); + + public override bool conflictsWith(Enchantment other) => conflictedEnchants.Contains(other.getEnchantType()); + + public override EnchantmentTarget getItemTarget() => EnchantmentTarget.ARMOR; + + public override EnchantmentType getEnchantType() => EnchantmentType.PROTECTION_ENVIRONMENTAL; + + public override int getMaxLevel() => 4; + + public override string getName() => "protection"; + + public override int getStartLevel() => 1; +} diff --git a/Minecraft.Server.FourKit/Enchantments/PunchEnchantment.cs b/Minecraft.Server.FourKit/Enchantments/PunchEnchantment.cs new file mode 100644 index 000000000..3fb5b3e0d --- /dev/null +++ b/Minecraft.Server.FourKit/Enchantments/PunchEnchantment.cs @@ -0,0 +1,26 @@ +using Minecraft.Server.FourKit.Inventory; + +namespace Minecraft.Server.FourKit.Enchantments; + +public class PunchEnchantment : Enchantment +{ + static readonly Material[] supportedItems = { + Material.BOW + }; + + static readonly EnchantmentType[] conflictedEnchants = { }; + + public override bool canEnchantItem(ItemStack item) => supportedItems.Contains(item.getType()); + + public override bool conflictsWith(Enchantment other) => conflictedEnchants.Contains(other.getEnchantType()); + + public override EnchantmentTarget getItemTarget() => EnchantmentTarget.BOW; + + public override EnchantmentType getEnchantType() => EnchantmentType.ARROW_KNOCKBACK; + + public override int getMaxLevel() => 2; + + public override string getName() => "punch"; + + public override int getStartLevel() => 1; +} diff --git a/Minecraft.Server.FourKit/Enchantments/RespirationEnchantment.cs b/Minecraft.Server.FourKit/Enchantments/RespirationEnchantment.cs new file mode 100644 index 000000000..8d599077e --- /dev/null +++ b/Minecraft.Server.FourKit/Enchantments/RespirationEnchantment.cs @@ -0,0 +1,26 @@ +using Minecraft.Server.FourKit.Inventory; + +namespace Minecraft.Server.FourKit.Enchantments; + +public class RespirationEnchantment : Enchantment +{ + static readonly Material[] supportedItems = { + Material.LEATHER_HELMET, Material.CHAINMAIL_HELMET, Material.GOLD_HELMET, Material.IRON_HELMET, Material.DIAMOND_HELMET, + }; + + static readonly EnchantmentType[] conflictedEnchants = { }; + + public override bool canEnchantItem(ItemStack item) => supportedItems.Contains(item.getType()); + + public override bool conflictsWith(Enchantment other) => conflictedEnchants.Contains(other.getEnchantType()); + + public override EnchantmentTarget getItemTarget() => EnchantmentTarget.ARMOR_HEAD; + + public override EnchantmentType getEnchantType() => EnchantmentType.OXYGEN; + + public override int getMaxLevel() => 3; + + public override string getName() => "respiration"; + + public override int getStartLevel() => 1; +} diff --git a/Minecraft.Server.FourKit/Enchantments/SharpnessEnchantment.cs b/Minecraft.Server.FourKit/Enchantments/SharpnessEnchantment.cs new file mode 100644 index 000000000..00421a7b7 --- /dev/null +++ b/Minecraft.Server.FourKit/Enchantments/SharpnessEnchantment.cs @@ -0,0 +1,30 @@ +using Minecraft.Server.FourKit.Inventory; + +namespace Minecraft.Server.FourKit.Enchantments; + +public class SharpnessEnchantment : Enchantment +{ + static readonly Material[] supportedItems = { + Material.WOOD_SWORD, Material.STONE_SWORD, Material.IRON_SWORD, Material.GOLD_SWORD, Material.DIAMOND_SWORD, + Material.WOOD_AXE, Material.STONE_AXE, Material.IRON_AXE, Material.GOLD_AXE, Material.DIAMOND_AXE, + }; + + static readonly EnchantmentType[] conflictedEnchants = { + EnchantmentType.DAMAGE_ARTHOPODS, + EnchantmentType.DAMAGE_UNDEAD + }; + + public override bool canEnchantItem(ItemStack item) => supportedItems.Contains(item.getType()); + + public override bool conflictsWith(Enchantment other) => conflictedEnchants.Contains(other.getEnchantType()); + + public override EnchantmentTarget getItemTarget() => EnchantmentTarget.WEAPON; + + public override EnchantmentType getEnchantType() => EnchantmentType.DAMAGE_ALL; + + public override int getMaxLevel() => 5; + + public override string getName() => "sharpness"; + + public override int getStartLevel() => 1; +} diff --git a/Minecraft.Server.FourKit/Enchantments/SilkTouchEnchantment.cs b/Minecraft.Server.FourKit/Enchantments/SilkTouchEnchantment.cs new file mode 100644 index 000000000..01c2bbce2 --- /dev/null +++ b/Minecraft.Server.FourKit/Enchantments/SilkTouchEnchantment.cs @@ -0,0 +1,33 @@ +using Minecraft.Server.FourKit.Inventory; + +namespace Minecraft.Server.FourKit.Enchantments; + +public class SilkTouchEnchantment : Enchantment +{ + static readonly Material[] supportedItems = { + Material.WOOD_PICKAXE, Material.STONE_PICKAXE, Material.IRON_PICKAXE, Material.GOLD_PICKAXE, Material.DIAMOND_PICKAXE, + Material.WOOD_AXE, Material.STONE_AXE, Material.IRON_AXE, Material.GOLD_AXE, Material.DIAMOND_AXE, + Material.WOOD_SPADE, Material.STONE_SPADE, Material.IRON_SPADE, Material.GOLD_SPADE, Material.DIAMOND_SPADE, + Material.WOOD_HOE, Material.STONE_HOE, Material.IRON_HOE, Material.GOLD_HOE, Material.DIAMOND_HOE, + + Material.SHEARS + }; + + static readonly EnchantmentType[] conflictedEnchants = { + EnchantmentType.LOOT_BONUS_BLOCKS + }; + + public override bool canEnchantItem(ItemStack item) => supportedItems.Contains(item.getType()); + + public override bool conflictsWith(Enchantment other) => conflictedEnchants.Contains(other.getEnchantType()); + + public override EnchantmentTarget getItemTarget() => EnchantmentTarget.TOOL; + + public override EnchantmentType getEnchantType() => EnchantmentType.SILK_TOUCH; + + public override int getMaxLevel() => 1; + + public override string getName() => "silktouch"; + + public override int getStartLevel() => 1; +} diff --git a/Minecraft.Server.FourKit/Enchantments/SmiteEnchantment.cs b/Minecraft.Server.FourKit/Enchantments/SmiteEnchantment.cs new file mode 100644 index 000000000..6bc95082b --- /dev/null +++ b/Minecraft.Server.FourKit/Enchantments/SmiteEnchantment.cs @@ -0,0 +1,30 @@ +using Minecraft.Server.FourKit.Inventory; + +namespace Minecraft.Server.FourKit.Enchantments; + +public class SmiteEnchantment : Enchantment +{ + static readonly Material[] supportedItems = { + Material.WOOD_SWORD, Material.STONE_SWORD, Material.IRON_SWORD, Material.GOLD_SWORD, Material.DIAMOND_SWORD, + Material.WOOD_AXE, Material.STONE_AXE, Material.IRON_AXE, Material.GOLD_AXE, Material.DIAMOND_AXE, + }; + + static readonly EnchantmentType[] conflictedEnchants = { + EnchantmentType.DAMAGE_ALL, + EnchantmentType.DAMAGE_ARTHOPODS + }; + + public override bool canEnchantItem(ItemStack item) => supportedItems.Contains(item.getType()); + + public override bool conflictsWith(Enchantment other) => conflictedEnchants.Contains(other.getEnchantType()); + + public override EnchantmentTarget getItemTarget() => EnchantmentTarget.WEAPON; + + public override EnchantmentType getEnchantType() => EnchantmentType.DAMAGE_UNDEAD; + + public override int getMaxLevel() => 5; + + public override string getName() => "smite"; + + public override int getStartLevel() => 1; +} diff --git a/Minecraft.Server.FourKit/Enchantments/ThornsEnchantment.cs b/Minecraft.Server.FourKit/Enchantments/ThornsEnchantment.cs new file mode 100644 index 000000000..fc6ea8e28 --- /dev/null +++ b/Minecraft.Server.FourKit/Enchantments/ThornsEnchantment.cs @@ -0,0 +1,30 @@ +using Minecraft.Server.FourKit.Inventory; + +namespace Minecraft.Server.FourKit.Enchantments; + +public class ThornsEnchantment : Enchantment +{ + static readonly Material[] supportedItems = { + Material.LEATHER_HELMET, Material.LEATHER_CHESTPLATE, Material.LEATHER_LEGGINGS, Material.LEATHER_BOOTS, + Material.CHAINMAIL_HELMET, Material.CHAINMAIL_CHESTPLATE, Material.CHAINMAIL_LEGGINGS, Material.CHAINMAIL_BOOTS, + Material.GOLD_HELMET, Material.GOLD_CHESTPLATE, Material.GOLD_LEGGINGS, Material.GOLD_BOOTS, + Material.IRON_HELMET, Material.IRON_CHESTPLATE, Material.IRON_LEGGINGS, Material.IRON_BOOTS, + Material.DIAMOND_HELMET, Material.DIAMOND_CHESTPLATE, Material.DIAMOND_LEGGINGS, Material.DIAMOND_BOOTS, + }; + + static readonly EnchantmentType[] conflictedEnchants = { }; + + public override bool canEnchantItem(ItemStack item) => supportedItems.Contains(item.getType()); + + public override bool conflictsWith(Enchantment other) => conflictedEnchants.Contains(other.getEnchantType()); + + public override EnchantmentTarget getItemTarget() => EnchantmentTarget.ARMOR; + + public override EnchantmentType getEnchantType() => EnchantmentType.THORNS; + + public override int getMaxLevel() => 3; + + public override string getName() => "thorns"; + + public override int getStartLevel() => 1; +} diff --git a/Minecraft.Server.FourKit/Enchantments/UnbreakingEnchantment.cs b/Minecraft.Server.FourKit/Enchantments/UnbreakingEnchantment.cs new file mode 100644 index 000000000..a83039ab0 --- /dev/null +++ b/Minecraft.Server.FourKit/Enchantments/UnbreakingEnchantment.cs @@ -0,0 +1,39 @@ +using Minecraft.Server.FourKit.Inventory; + +namespace Minecraft.Server.FourKit.Enchantments; + +public class UnbreakingEnchantment : Enchantment +{ + static readonly Material[] supportedItems = { + Material.WOOD_SWORD, Material.STONE_SWORD, Material.IRON_SWORD, Material.GOLD_SWORD, Material.DIAMOND_SWORD, + Material.WOOD_PICKAXE, Material.STONE_PICKAXE, Material.IRON_PICKAXE, Material.GOLD_PICKAXE, Material.DIAMOND_PICKAXE, + Material.WOOD_AXE, Material.STONE_AXE, Material.IRON_AXE, Material.GOLD_AXE, Material.DIAMOND_AXE, + Material.WOOD_SPADE, Material.STONE_SPADE, Material.IRON_SPADE, Material.GOLD_SPADE, Material.DIAMOND_SPADE, + Material.WOOD_HOE, Material.STONE_HOE, Material.IRON_HOE, Material.GOLD_HOE, Material.DIAMOND_HOE, + + Material.LEATHER_HELMET, Material.LEATHER_CHESTPLATE, Material.LEATHER_LEGGINGS, Material.LEATHER_BOOTS, + Material.CHAINMAIL_HELMET, Material.CHAINMAIL_CHESTPLATE, Material.CHAINMAIL_LEGGINGS, Material.CHAINMAIL_BOOTS, + Material.GOLD_HELMET, Material.GOLD_CHESTPLATE, Material.GOLD_LEGGINGS, Material.GOLD_BOOTS, + Material.IRON_HELMET, Material.IRON_CHESTPLATE, Material.IRON_LEGGINGS, Material.IRON_BOOTS, + Material.DIAMOND_HELMET, Material.DIAMOND_CHESTPLATE, Material.DIAMOND_LEGGINGS, Material.DIAMOND_BOOTS, + + Material.FISHING_ROD, Material.BOW, + Material.SHEARS, Material.FLINT_AND_STEEL, Material.CARROT_STICK + }; + + static readonly EnchantmentType[] conflictedEnchants = { }; + + public override bool canEnchantItem(ItemStack item) => supportedItems.Contains(item.getType()); + + public override bool conflictsWith(Enchantment other) => conflictedEnchants.Contains(other.getEnchantType()); + + public override EnchantmentTarget getItemTarget() => EnchantmentTarget.ALL; + + public override EnchantmentType getEnchantType() => EnchantmentType.DURABILITY; + + public override int getMaxLevel() => 3; + + public override string getName() => "unbreaking"; + + public override int getStartLevel() => 1; +} diff --git a/Minecraft.Server.FourKit/Inventory/ItemStack.cs b/Minecraft.Server.FourKit/Inventory/ItemStack.cs index e5c9a5b59..5af48d3f5 100644 --- a/Minecraft.Server.FourKit/Inventory/ItemStack.cs +++ b/Minecraft.Server.FourKit/Inventory/ItemStack.cs @@ -126,6 +126,7 @@ public class ItemStack public bool setItemMeta(ItemMeta? itemMeta) { _meta = itemMeta?.clone(); + SyncToOwner(); return true; } diff --git a/Minecraft.Server.FourKit/Inventory/Meta/ItemMeta.cs b/Minecraft.Server.FourKit/Inventory/Meta/ItemMeta.cs index 5da46c5ac..60ba224cf 100644 --- a/Minecraft.Server.FourKit/Inventory/Meta/ItemMeta.cs +++ b/Minecraft.Server.FourKit/Inventory/Meta/ItemMeta.cs @@ -1,11 +1,14 @@ namespace Minecraft.Server.FourKit.Inventory.Meta; +using Minecraft.Server.FourKit.Enchantments; + /// /// Represents the metadata of an , including display name and lore. /// public class ItemMeta { private string? _displayName; + private Dictionary? _enchants; private List? _lore; /// @@ -49,16 +52,123 @@ public class ItemMeta _lore = lore != null ? new List(lore) : null; } + /// + /// Adds the specified enchantment to this item meta. + /// + /// Enchantment to add + /// Level for the enchantment + /// Indicates the enchantment should be applied, ignoring the level limit + /// true if the item meta changed as a result of this call, false otherwise + public bool addEnchant(EnchantmentType enchantment, int level, bool ignoreLevelRestriction) + { + if (_enchants == null) + _enchants = new Dictionary(); + + if (!ignoreLevelRestriction) + { + Enchantment enchant = Enchantment.getByType(enchantment); + + if (enchant.getMaxLevel() < level) return false; + } + + try + { + _enchants.Add(enchantment, level); + return true; + } catch { } + + return false; + } + + /// + /// Removes the specified enchantment from this item meta. + /// + /// Enchantment to remove + /// true if the item meta changed as a result of this call, false otherwise + public bool removeEnchant(EnchantmentType enchantment) + { + if (!hasEnchant(enchantment)) return false; + + return _enchants.Remove(enchantment); + } + + /// + /// Returns a copy of the enchantments in this ItemMeta. Returns an empty map if none. + /// + /// An immutable copy of the enchantments + public Dictionary getEnchants() => _enchants != null ? new Dictionary(_enchants) { } : new Dictionary(); + + /// + /// Checks for the level of the specified enchantment. + /// + /// Enchantment to check + /// The level that the specified enchantment has, or 0 if none + public int getEnchantLevel(EnchantmentType enchantment) + { + if (!hasEnchant(enchantment)) return 0; + + return _enchants[enchantment]; //this cant be invalid, we check above + } + + /// + /// Checks if the specified enchantment conflicts with any enchantments in this ItemMeta. + /// + /// Enchantment to test + /// true if the enchantment conflicts, false otherwise + public bool hasConflictingEnchant(EnchantmentType enchantment) + { + Enchantment enchantmentClass = Enchantment.getByType(enchantment); + if (enchantmentClass == null) return false; //this should never happen + + foreach (KeyValuePair ench in _enchants) + { + Enchantment enchClass = Enchantment.getByType(ench.Key); + + if (enchClass == null) continue; //this should never happen + + if (enchClass.conflictsWith(enchantmentClass)) + { + return true; + } + } + + return false; + } + + /// + /// Checks for existence of the specified enchantment. + /// + /// Enchantment to check + /// true if this enchantment exists for this meta + public bool hasEnchant(EnchantmentType enchantment) => hasEnchants() && _enchants.ContainsKey(enchantment); + + /// + /// Checks for the existence of any enchantments. + /// + /// true if an enchantment exists on this meta + public bool hasEnchants() => _enchants != null && _enchants.Count > 0; + + /// + /// Sets the enchantments for this item meta. + /// + /// The enchantments to set. + public void setEnchants(Dictionary? enchants) + { + enchants = enchants != null ? new Dictionary(enchants) : null; + } + + public ItemMeta clone() { var copy = new ItemMeta(); copy._displayName = _displayName; + copy._enchants = _enchants != null ? new Dictionary(_enchants) : null; copy._lore = _lore != null ? new List(_lore) : null; return copy; } internal bool isEmpty() { - return _displayName == null && (_lore == null || _lore.Count == 0); + return _displayName == null && (_lore == null || _lore.Count == 0) && (_enchants == null || _enchants.Count == 0); } } diff --git a/Minecraft.Server.FourKit/Inventory/PlayerInventory.cs b/Minecraft.Server.FourKit/Inventory/PlayerInventory.cs index 6a165d30a..bc33a9ea7 100644 --- a/Minecraft.Server.FourKit/Inventory/PlayerInventory.cs +++ b/Minecraft.Server.FourKit/Inventory/PlayerInventory.cs @@ -1,7 +1,9 @@ namespace Minecraft.Server.FourKit.Inventory; +using System.Diagnostics; using System.Runtime.InteropServices; using System.Text; +using Minecraft.Server.FourKit.Enchantments; using Minecraft.Server.FourKit.Entity; using Minecraft.Server.FourKit.Inventory.Meta; @@ -154,7 +156,10 @@ public class PlayerInventory : Inventory /// Gets the item the player is currently holding. /// /// The held ItemStack. - public ItemStack? getItemInHand() => getItem(_heldItemSlot); + public ItemStack? getItemInHand() { + EnsureSynced(); + return getItem(_heldItemSlot); + } /// /// Sets the item in the player's hand. @@ -278,7 +283,33 @@ public class PlayerInventory : Inventory } } - if (displayName == null && (lore == null || lore.Count == 0)) + int enchantCount = 0; + if (offset + 4 <= bytesWritten) + { + enchantCount = BitConverter.ToInt32(buf, offset); + offset += 4; + } + + Dictionary? enchants = null; + if (enchantCount > 0) + { + enchants = new Dictionary(enchantCount); + for (int i = 0; i < enchantCount; i++) + { + if (offset + (4 + 4) > bytesWritten) + break; + + int type = BitConverter.ToInt32(buf, offset); + offset += 4; + + int level = BitConverter.ToInt32(buf, offset); + offset += 4; + + enchants.Add((EnchantmentType)type, level); + } + } + + if (displayName == null && (lore == null || lore.Count == 0) && (enchants == null || enchants.Count == 0)) return null; var meta = new ItemMeta(); @@ -286,6 +317,8 @@ public class PlayerInventory : Inventory meta.setDisplayName(displayName); if (lore != null && lore.Count > 0) meta.setLore(lore); + if (enchants != null && enchants.Count > 0) + meta.setEnchants(enchants); return meta; } @@ -330,6 +363,27 @@ public class PlayerInventory : Inventory bw.Write(0); } + if (meta.hasEnchants()) + { + + Debug.WriteLine("Writting Enchants"); + var enchants = meta.getEnchants(); + bw.Write(enchants.Count); + foreach (var enchant in enchants) + { + Debug.WriteLine("Wrote A Enchant"); + + bw.Write((int)enchant.Key); + bw.Write(enchant.Value); + } + } + else + { + Debug.WriteLine("Had No Enchants"); + + bw.Write(0); + } + bw.Flush(); byte[] data = ms.ToArray(); var gh = GCHandle.Alloc(data, GCHandleType.Pinned); diff --git a/Minecraft.Server/FourKitNatives.cpp b/Minecraft.Server/FourKitNatives.cpp index 00c072da0..dc6c843cb 100644 --- a/Minecraft.Server/FourKitNatives.cpp +++ b/Minecraft.Server/FourKitNatives.cpp @@ -41,6 +41,7 @@ #include "Access\Access.h" #include "Common\NetworkUtils.h" #include "ServerLogManager.h" +#include "../Minecraft.World/ItemInstance.cpp" namespace { @@ -751,10 +752,12 @@ void __cdecl NativeOpenVirtualContainer(int entityId, int nativeType, const char player->openContainer(container); } - +//didnt update this for enchants // [nameLen:int32][nameUTF8:bytes][loreCount:int32][lore0Len:int32][lore0UTF8:bytes] int __cdecl NativeGetItemMeta(int entityId, int slot, char *outBuf, int bufSize) { + printf("NativeGetItemMeta::entry\n"); + auto player = FindPlayer(entityId); if (!player || !player->inventory) return 0; @@ -775,6 +778,8 @@ int __cdecl NativeGetItemMeta(int entityId, int slot, char *outBuf, int bufSize) bool hasName = display->contains(L"Name"); bool hasLore = display->contains(L"Lore"); + bool hasEnchantments = item->isEnchanted(); + if (!hasName && !hasLore) return 0; @@ -827,6 +832,34 @@ int __cdecl NativeGetItemMeta(int entityId, int slot, char *outBuf, int bufSize) offset += 4; } + if (hasEnchantments) { + ListTag* list = item->getEnchantmentTags(); + if (list != nullptr) { + int listSize = list->size(); + + if ((offset + 4 + (listSize * (4 + 4))) > bufSize) return 0; + + memcpy(outBuf + offset, &listSize, 4); + offset += 4; + for (int i = 0; i < listSize; i++) { + int type = list->get(i)->getShort((wchar_t*)ItemInstance::TAG_ENCH_ID); + int level = list->get(i)->getShort((wchar_t*)ItemInstance::TAG_ENCH_LEVEL); + + memcpy(outBuf + offset, &type, 4); + offset += 4; + + memcpy(outBuf + offset, &level, 4); + offset += 4; + } + } + } + else { + int zero = 0; + if (offset + 4 > bufSize) return 0; + memcpy(outBuf + offset, &zero, 4); + offset += 4; + } + return offset; } @@ -861,6 +894,11 @@ void __cdecl NativeSetItemMeta(int entityId, int slot, const char *inBuf, int bu item->setTag(nullptr); } } + + if (tag && tag->contains(L"ench")) + { + tag->remove(L"ench"); + } } return; } @@ -925,6 +963,47 @@ void __cdecl NativeSetItemMeta(int entityId, int slot, const char *inBuf, int bu tag->getCompound(L"display")->remove(L"Lore"); } } + + if (offset + 4 > bufSize) return; + int enchantCount = 0; + memcpy(&enchantCount, inBuf + offset, 4); + offset += 4; + + if (enchantCount > 0) + { + if (!item->hasTag()) item->setTag(new CompoundTag()); + CompoundTag* tag = item->getTag(); + if (!tag->contains(L"ench")) tag->put(L"ench", new ListTag(L"ench")); + ListTag* enchantments = static_cast *>(tag->get(L"ench")); + + for (int i = 0; i < enchantCount; i++) { + if (offset + (4 + 4) > bufSize) break; + + int type = 0; + memcpy(&type, inBuf + offset, 4); + offset += 4; + + int level = 0; + memcpy(&level, inBuf + offset, 4); + offset += 4; + + CompoundTag* ench = new CompoundTag(); + ench->putShort((wchar_t*)ItemInstance::TAG_ENCH_ID, static_cast(type)); + ench->putShort((wchar_t*)ItemInstance::TAG_ENCH_LEVEL, static_cast(level)); + enchantments->add(ench); + } + } + else + { + if (item->hasTag()) + { + CompoundTag* tag = item->getTag(); + if (tag && tag->contains(L"ench")) + { + tag->remove(L"ench"); + } + } + } } void __cdecl NativeSetHeldItemSlot(int entityId, int slot)