neoLegacy/Minecraft.Server.FourKit/Enchantments/Enchantment.cs
itsRevela 42a582fb9f feat: add FourKit plugin host with dual server build
Adds the FourKit .NET 10 plugin host as a second dedicated server
build flavour alongside the existing vanilla server. Both flavours
build from the same source tree, with FourKit gated by the
MINECRAFT_SERVER_FOURKIT_BUILD preprocessor define.

Build layout:

  Minecraft.Server         vanilla, no plugin support, no .NET dep
  Minecraft.Server.FourKit FourKit-enabled, ships with bundled
                           .NET 10 self-contained runtime in runtime/
                           and an empty plugins/ folder

Both produce a Minecraft.Server.exe in their own per-target output
dir. The variant identity lives in the directory name, not the
binary name, so either flavour can be shipped as a drop-in.

Native bridge (Minecraft.Server/FourKit*.{cpp,h}):

* FourKitRuntime: hosts CoreCLR via hostfxr's command-line init API
  (the runtime-config API does not support self-contained components)
* FourKitBridge: ~50 Fire* event entry points, with inline no-op
  stubs for the standalone build so gameplay code can call them
  unconditionally
* FourKitNatives: ~80 native callbacks the managed side invokes
  for player/world/inventory mutations
* FourKitMappers: type and enum mapping helpers

Managed plugin host (Minecraft.Server.FourKit/):

* Bukkit-style API: Player, World, Block, Inventory, Command,
  Listener, EventHandler attribute, ~54 event classes
* PluginLoader with per-plugin AssemblyLoadContext
* FourKitHost as the [UnmanagedCallersOnly] entry point table
* Runtime resolves plugins relative to the host process so they
  always live next to Minecraft.Server.exe regardless of where the
  managed assembly itself is loaded from

Engine hooks (Minecraft.Client/, Minecraft.World/):

* Player lifecycle (PreLogin, Login, Join, Quit, Kick, Move,
  Teleport, Portal, Death) wired into PendingConnection and
  PlayerConnection without disturbing the cipher handshake or
  identity-token security flow
* Inventory open/click/drop hooks across every container menu type
* Block place/break/grow/burn/spread/from-to hooks across the
  full tile family
* Bed enter/leave, sign change, entity damage/death, ender pearl
  teleport hooks

Regression fixes preserved while applying donor diffs:

* ServerPlayer::die() retains the LCE-Revelations hardcore branch
  (setGameMode(ADVENTURE) + banPlayerForHardcoreDeath) in both the
  FourKit and non-FourKit code paths
* ServerLevel::entityAdded() retains the sub-entity ID reassignment
  loop required by the client's handleAddMob offset, fixing Ender
  Dragon and Wither boss multi-part hit detection
* LivingEntity::travel() retains the raw Player* cast and the
  cached frictionTile, both Revelations perf wins that the donor
  silently reverted
* ServerLogger.cpp keeps the file-logging code donor stripped
* PlayerList.cpp end portal transition fix and UIScene_EndPoem
  bounds-check are intact

Build system:

* Top-level CMakeLists.txt adds the Minecraft.Server.FourKit
  subdirectory and pulls in the new shared cmake/ServerTarget.cmake
  helper
* Minecraft.Server/cmake/sources/Common.cmake is now location
  independent (uses CMAKE_CURRENT_LIST_DIR) so the source list
  can be consumed from either server target's CMakeLists.txt
* The seven FourKit*.cpp/h files live in their own
  _MINECRAFT_SERVER_COMMON_SERVER_FOURKIT variable so the
  standalone target omits them
* configure-time .NET 10 SDK check fails fast with a clear
  download link if the SDK is missing
* global.json pins the SDK to 10.0.100 with latestFeature
  rollforward

Sample plugin (samples/HelloPlugin/) demonstrates the loader and
the PlayerJoinEvent listener pattern.

CI:

* nightly.yml builds both server flavours, ships
  LCE-Revelations-Server-Win64.zip and
  LCE-Revelations-Server-Win64-FourKit.zip, attests both, and
  updates release notes for the dual-flavour layout
* pull-request.yml pulls in actions/setup-dotnet so the FourKit
  publish step works in PR validation
* All zip artifacts and the client zip are renamed from
  LCREWindows64 to LCE-Revelations-{Client,Server}-Win64

Documentation:

* COMPILE.md gets a VS 2022 quick start, .NET 10 prereq section,
  server flavours explanation, and a troubleshooting section
* docs/FOURKIT_PORT_RECON.md captures the file-by-file recon that
  drove the port
* docs/FOURKIT_PARITY.md is the canonical reference for which
  events FourKit fires

Docker:

* docker-compose.dedicated-server.yml MC_RUNTIME_DIR default points
  at the vanilla CMake output. The FourKit Docker image is
  intentionally NOT shipped yet because hosting .NET 10 self
  contained inside Wine has not been smoke-tested
2026-04-08 03:02:48 -05:00

274 lines
11 KiB
C#

namespace Minecraft.Server.FourKit.Enchantments;
using Minecraft.Server.FourKit.Inventory;
/// <summary>
/// Represents the applicable target for a Enchantment
/// </summary>
public enum EnchantmentTarget
{
/// <summary>
/// Allows the Enchantment to be placed on all items
/// </summary>
ALL,
/// <summary>
/// Allows the Enchantment to be placed on armor
/// </summary>
ARMOR,
/// <summary>
/// Allows the Enchantment to be placed on feet slot armor
/// </summary>
ARMOR_FEET,
/// <summary>
/// Allows the Enchantment to be placed on head slot armor
/// </summary>
ARMOR_HEAD,
/// <summary>
/// Allows the Enchantment to be placed on leg slot armor
/// </summary>
ARMOR_LEGS,
/// <summary>
/// Allows the Enchantment to be placed on torso slot armor
/// </summary>
ARMOR_TORSO,
/// <summary>
/// Allows the Enchantment to be placed on bows.
/// </summary>
BOW,
/// <summary>
/// Allows the Enchantment to be placed on tools (spades, pickaxe, hoes, axes)
/// </summary>
TOOL,
/// <summary>
/// Allows the Enchantment to be placed on weapons (swords)
/// </summary>
WEAPON,
}
//these numbers match the same ones that the enchants register as, Enchantment.cpp - 41
/// <summary>
/// The various type of enchantments that may be added to armour or weapons
/// </summary>
public enum EnchantmentType
{
/// <summary>
/// Provides extra damage when shooting arrows from bows
/// </summary>
ARROW_DAMAGE = 48,
/// <summary>
/// Sets entities on fire when hit by arrows shot from a bow
/// </summary>
ARROW_FIRE = 50,
/// <summary>
/// Provides infinite arrows when shooting a bow
/// </summary>
ARROW_INFINITE = 51,
/// <summary>
/// Provides a knockback when an entity is hit by an arrow from a bow
/// </summary>
ARROW_KNOCKBACK = 49,
/// <summary>
/// Increases damage against all targets
/// </summary>
DAMAGE_ALL = 16,
/// <summary>
/// Increases damage against arthropod targets
/// </summary>
DAMAGE_ARTHOPODS = 18,
/// <summary>
/// Increases damage against undead targets
/// </summary>
DAMAGE_UNDEAD = 17,
/// <summary>
/// Increases the rate at which you mine/dig
/// </summary>
DIG_SPEAD = 32,
/// <summary>
/// Decreases the rate at which a tool looses durability
/// </summary>
DURABILITY = 34,
/// <summary>
/// When attacking a target, has a chance to set them on fire
/// </summary>
FIRE_ASPECT = 20,
/// <summary>
/// All damage to other targets will knock them back when hit
/// </summary>
KNOCKBACK = 19,
/// <summary>
/// Provides a chance of gaining extra loot when destroying blocks
/// </summary>
LOOT_BONUS_BLOCKS = 35,
/// <summary>
/// Provides a chance of gaining extra loot when killing monsters
/// </summary>
LOOT_BONUS_MOBS = 21,
/// <summary>
/// Decreases the rate of air loss whilst underwater
/// </summary>
OXYGEN = 5,
/// <summary>
/// Provides protection against environmental damage
/// </summary>
PROTECTION_ENVIRONMENTAL = 0,
/// <summary>
/// Provides protection against explosive damage
/// </summary>
PROTECTION_EXPLOSIVE = 3,
/// <summary>
/// Provides protection against fall damage
/// </summary>
PROTECTION_FALL = 2,
/// <summary>
/// Provides protection against fire damage
/// </summary>
PROTECTION_FIRE = 1,
/// <summary>
/// Provides protection against projectile damage
/// </summary>
PROTECTION_PROJECTILE = 4,
/// <summary>
/// Allows blocks to drop themselves instead of fragments (for example, stone instead of cobblestone)
/// </summary>
SILK_TOUCH = 33,
/// <summary>
/// Damages the attacker
/// </summary>
THORNS = 7,
/// <summary>
/// Increases the speed at which a player may mine underwater
/// </summary>
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<EnchantmentType, Enchantment> _registry = new Dictionary<EnchantmentType, Enchantment>()
{
{ 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() },
};
/// <summary>
/// Checks if this Enchantment may be applied to the given <see cref="ItemStack"/>. This does not check if it conflicts with any enchantments already applied to the item.
/// </summary>
/// <param name="item">Item to test</param>
/// <returns>True if the enchantment may be applied, otherwise False</returns>
public abstract bool canEnchantItem(ItemStack item);
/// <summary>
/// Check if this enchantment conflicts with another enchantment.
/// </summary>
/// <param name="other">The enchantment to check against </param>
/// <returns>True if there is a conflict.</returns>
public abstract bool conflictsWith(Enchantment other);
//public abstract Enchantment getById(int id); //deprecated by bukkit
/// <summary>
/// Gets the Enchantment at the specified name
/// </summary>
/// <param name="name">Name to fetch.</param>
/// <returns>Resulting Enchantment, or null if not found</returns>
public static Enchantment? getByName(string name)
{
foreach (KeyValuePair<EnchantmentType, Enchantment> enchantmentPair in _registry)
{
if (enchantmentPair.Value.getName().Equals(name)) return enchantmentPair.Value;
}
return null;
}
/// <summary>
/// Gets the Enchantment at the specified type
/// </summary>
/// <param name="type">Type to fetch.</param>
/// <returns>Resulting Enchantment, or null if not found</returns>
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
/// <summary>
/// Gets the type of <see cref="ItemStack"/> that may fit this Enchantment.
/// </summary>
/// <returns>Gets the type of <see cref="ItemStack"/> that may fit this Enchantment.</returns>
public abstract EnchantmentTarget getItemTarget();
/// <summary>
/// Returns the <see cref="EnchantmentType"/>.
/// </summary>
/// <returns>Gets the enchantment type.</returns>
public abstract EnchantmentType getEnchantType();
/// <summary>
/// Gets the maximum level that this Enchantment may become.
/// </summary>
/// <returns>Maximum level of the Enchantment</returns>
public abstract int getMaxLevel();
/// <summary>
/// Gets the unique name of this enchantment
/// </summary>
/// <returns>Unique name</returns>
public abstract string getName();
/// <summary>
/// Gets the level that this Enchantment should start at
/// </summary>
/// <returns>Starting level of the Enchantment</returns>
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
}