{"id":13717011,"url":"https://github.com/TogAr2/MinestomPvP","last_synced_at":"2025-05-07T06:31:51.705Z","repository":{"id":40254073,"uuid":"378733785","full_name":"TogAr2/MinestomPvP","owner":"TogAr2","description":"Combat library for Minestom","archived":false,"fork":false,"pushed_at":"2025-05-06T18:11:29.000Z","size":1170,"stargazers_count":119,"open_issues_count":9,"forks_count":41,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-05-06T19:32:17.560Z","etag":null,"topics":["combat","legacy-minecraft","minecraft","minecraft-combat","minestom","minestom-library","pvp"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TogAr2.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-06-20T20:25:18.000Z","updated_at":"2025-05-06T18:11:33.000Z","dependencies_parsed_at":"2024-05-01T21:55:22.176Z","dependency_job_id":"6cfddfbf-9cf5-4047-8f14-1f003ec32229","html_url":"https://github.com/TogAr2/MinestomPvP","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TogAr2%2FMinestomPvP","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TogAr2%2FMinestomPvP/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TogAr2%2FMinestomPvP/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TogAr2%2FMinestomPvP/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TogAr2","download_url":"https://codeload.github.com/TogAr2/MinestomPvP/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252826896,"owners_count":21810200,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["combat","legacy-minecraft","minecraft","minecraft-combat","minestom","minestom-library","pvp"],"created_at":"2024-08-03T00:01:16.728Z","updated_at":"2025-05-07T06:31:51.697Z","avatar_url":"https://github.com/TogAr2.png","language":"Java","funding_links":[],"categories":["Extensions"],"sub_categories":[],"readme":"# MinestomPvP\n\n[![license](https://img.shields.io/github/license/TogAr2/MinestomPvP.svg?style=for-the-badge)](LICENSE)\n[![platform](https://img.shields.io/badge/platform-Minestom-ff69b4?style=for-the-badge)](https://github.com/Minestom/Minestom)\n\nMinestomPvP is a combat library for Minestom.\nIt tries to mimic vanilla (modern **and** pre-1.9) PvP as good as possible, while also focusing on customizability and usability.\n\nNot only does MinestomPvP provide combat mechanics, it also provides several related features (e.g., status effects and food).\nYou can easily declare which features you want to use.\n\nThe maven repository is available on [jitpack](https://jitpack.io/#TogAr2/MinestomPvP).\n\n## Table of Contents\n\n- [Features](#features)\n- [Future Plans](#plans)\n- [Usage](#usage)\n- [Customization](#customization)\n- [Legacy PvP](#legacy-pvp)\n- [Knockback](#knockback)\n- [Integration](#integration)\n- [Registries](#registries)\n- [Events](#events)\n- [Custom combat features](#custom-combat-features)\n- [Contributing](#contributing)\n- [Credits](#credits)\n\n## Features\n\nCurrently, most vanilla PvP mechanics are supported.\n\n- Attack cooldown\n- Damage invulnerability\n- Weapons\n- Armor\n- Shields (or sword blocking)\n- Food\n- Totems\n- Bows and crossbows\n- Tridents (with riptide or loyalty)\n- Fishing rods (only hooking entities or legacy knockback, not fishing)\n- Other projectiles (potions, snowballs, eggs, ender pearls)\n- All enchantments possible with the above features (this includes protection, sharpness, knockback, ...)\n- Fall damage\n- End crystals\n- TNT\n- Respawn anchors (explosion only)\n\n## Plans\n\n- Lingering potions\n- Fireworks (for crossbows)\n- Support for (some) water mechanics (e.g. slowing projectiles down)\n- 1.21 features (the library is already 1.21 compatible, just doesn't support its combat features)\n- Rework of the tool \u0026 armor registry to allow for customization\n\n## Usage\n\nBefore doing anything else, you should call `MinestomPvP.init()`. This will make sure everything is registered correctly.\n\n\u003e [!NOTE]\n\u003e `MinestomPvP.init()` has a few side effects which may be unwanted and can be disabled: see [Integration](#integration).\n\nAfter you've initialized the library, you can start using combat features.\nA very basic setup would be:\n```java\nMinestomPvP.init();\n\nCombatFeatureSet modernVanilla = CombatFeatures.modernVanilla();\nMinecraftServer.getGlobalEventHandler().addChild(modernVanilla.createNode());\n```\n\nThis will give you a full vanilla experience without any customization.\n\nEvery combat feature has a `createNode()` method, which returns an `EventNode` with all listeners of the feature attached.\nThis event node can be added to another event node to enable the feature within that scope.\nIn the example above, it is being added to the global event handler, which means the feature will work everywhere.\n\nThe combat feature used in this example is a `CombatFeatureSet`.\nThis is essentially a container for a list of combat features.\nThere are two feature sets already defined by MinestomPvP:\n- Full modern combat, `CombatFeatures.modernVanilla()`\n- Full legacy (pre-1.9) combat, `CombatFeatures.legacyVanilla()`\n\n### Customization\n\nThe `CombatFeatures` class contains a field for every individual combat feature which has been defined by MinestomPvP itself.\nFor example, you can add fall damage to your instance like so:\n\n```java\nInstance instance;\n\nCombatFeatureSet featureSet = CombatFeatures.empty()\n        .version(CombatVersion.MODERN)\n        .add(CombatFeatures.VANILLA_FALL)\n        .add(CombatFeatures.VANILLA_PLAYER_STATE)\n        .build();\ninstance.eventNode().addChild(featureSet.createNode());\n```\n\nAs you can see, `CombatFeatures.empty()` provides you with a builder-like structure (`CombatConfiguration`) to which features can be added.\n\nThis combat configuration also contains convenience methods:\n- `version(CombatVersion)` to set a combat version, which is used by some vanilla features to adjust values which are different across versions\n- `difficulty(DifficultyProvider)` to set a difficulty provider, which is used by some vanilla features containing behavior which is different depending on the difficulty\n\nIn the example above, a `PLAYER_STATE` feature is added alongside the `FALL` feature, because the fall feature depends on it.\n`CombatConfiguration` takes care of handling these dependencies for you. The order in which the features are added does not matter.\nIt is also possible to leave out the `PLAYER_STATE` feature: a `NO_OP` feature will then be used, which in this case will always signal to the fall feature that the player is not climbing.\n\nUpon calling `CombatConfiguration#build()`, the combat configuration resolves all these dependencies and creates a `CombatFeatureSet` in which all the features are instantiated.\n\n\u003e [!NOTE]\n\u003e Features defined inside the `CombatFeatures` class are not yet instantiated, but are a `DefinedFeature`.\n\u003e The `CombatConfiguration` will instantiate the features for you, which will turn them into `CombatFeature` instances.\n\u003e An instantiated feature always knows its dependencies.\n\n### Legacy PvP\n\nEarlier minecraft versions (pre-1.9) used a different PvP system, which to this day is still preferred by some. *Legacy* is the term used to describe this type of PvP throughout the library.\nYou can get the `CombatFeatureSet` for legacy PvP using `CombatFeatures.legacyVanilla()`.\n\nTo disable attack cooldown for a player, use `MinestomPvP.setLegacyAttack(player, true)`.\nTo enable the cooldown again, use `false` instead of `true`.\n\n### Knockback\n\nA lot of servers like to customize their knockback. It is also possible to do so with this library.\nIn `EntityKnockbackEvent`, you can set a `KnockbackSettings` object. It contains information about how the knockback is calculated.\nA builder is obtainable by using `KnockbackSettings.builder()`. For more information, check the [config of BukkitOldCombatMechanics](https://github.com/kernitus/BukkitOldCombatMechanics/blob/d222286fd84fe983fdbdff79699182837871ab9b/src/main/resources/config.yml#L279).\n\n\u003e [!NOTE]\n\u003e Despite this config being designed for legacy combat, `KnockbackSettings` also works for modern combat.\n\nSome servers also use latency-compensated knockback to improve the experience fighting against and playing with high ping.\nMinestomPvP provides `FairKnockbackFeature` for this purpose. It has two modes: `ONLY_RISING` and `RISING_AND_FALLING`.\nFor more information, see the documentation of [`FairKnockbackFeature`](src/main/java/io/github/togar2/pvp/feature/knockback/FairKnockbackFeature.java).\n\n### Integration\n\nTo integrate this extension into your minestom server, you may have to tweak a little bit to make sure everything works correctly.\n\nAmong other things, the initialization method `MinestomPvP.init()` will:\n- register a custom player implementation\n- register a custom packet listener for `ClientKeepAlivePacket`\n\nThese effects can be disabled by using `MinestomPvP.init(false, false)`.\n\n\u003e [!CAUTION]\n\u003e It is **not** recommended to disable the custom player implementation, since it makes some important changes to handling of player movement.\n\nIf you are using a custom player implementation yourself, it is recommended to extend `CombatPlayerImpl`, or implement `CombatPlayer` in a similar fashion.\nYour implementation needs to be registered after the call to `MinestomPvP.init()`.\n\nThe custom packet listener increases the accuracy of latency measurements between server and clients, which is used in the latency-compensated `FairKnockbackFeature`.\n\u003e [!NOTE]\n\u003e If you are using `FairKnockbackFeature`, you may also benefit from decreasing the `minestom.keep-alive-delay` server flag.\n\nTo allow explosions, you have to register an explosion supplier to every instance in which they are used.\nImplementations of `ExplosionFeature` might provide an explosion supplier.\n\n```java\nCombatFeatureSet featureSet;\nInstance instance;\n\ninstance.setExplosionSupplier(featureSet.get(FeatureType.EXPLOSION).getExplosionSupplier());\n```\n\nKeep in mind that the explosion supplier can be different depending on the explosion feature,\nso always register the one from the explosion feature which is active in the instance.\n\n### Registries\n\nMinestomPvP has several registries, which you can also register to in order to create custom behavior:\n- `CombatEnchantments`: a registry of enchantment behaviors, used by `EnchantmentFeature`\n- `CombatPotionEffects`: a registry of potion effect behaviors, used by `EffectFeature`\n- `CombatPotionTypes`: a registry of potion types and which effects they contain, used by `EffectFeature`\n\nYou can use the static `#register(...)` method in those classes to add custom entries.\n\nYou can also use the class `Tool`, which contains all tools and their properties (not all properties are currently included, will change soon).\nThe same applies to `ToolMaterial` (wood, stone, ...) and `ArmorMaterial`.\n\n### Events\n\nThe library provides several events:\n\n- `AnchorChargeEvent`: cancellable, called when a player charges a respawn anchor.\n- `AnchorExplodeEvent`: cancellable, called when a player clicks on a respawn anchor to explode it.\n- `CrystalPlaceEvent`: cancellable, called when a player places an end crystal.\n- `DamageBlockEvent`: cancellable, called when an entity blocks damage using a shield. This event can be used to set the remaining damage.\n- `EntityKnockbackEvent`: cancellable, called when an entity gets knocked back by another entity. Gets called twice for weapons with the knockback enchantment (once for default damage knockback, once for the extra knockback). This event can be used to change the knockback settings.\n- `EntityPreDeathEvent`: cancellable, a form of `EntityDeathEvent` but cancellable and with a damage type. Can be used to cancel the death while still applying after-damage effects, such as attack sounds.\n- `EquipmentDamageEvent`: cancellable, called when an item in an equipment slot gets damaged.\n- `ExplosionEvent`: cancellable, called when an explosion will take place. Can be used to modify the affected blocks.\n- `ExplosivePrimeEvent`: cancellable, called when a tnt gets ignited, either by a player or by a nearby explosion.\n- `FinalAttackEvent`: cancellable, called when a player attacks an entity. Can be used to set a few variables like sprint, critical, sweeping, etc.\n- `FinalDamageEvent`: cancellable, called when the final damage calculation (including armor and effects) is completed. This event should be used instead of `EntityDamageEvent`, unless you want to detect how much damage was originally dealt.\n- `FishingBobberRetrieveEvent`: cancellable, called when a player retrieves a fishing bobber.\n- `PrepareAttackEvent`: cancellable, called before calculations for a given melee attack are done. Can be used to cancel the attack from happening in known situations where attacks shouldn't occur - ie; in a lobby/waiting phase.\n- `PickupEntityEvent`: cancellable, called when a player picks up an entity (arrow or trident).\n- `PlayerExhaustEvent`: cancellable, called when a players' exhaustion level changes.\n- `PlayerRegenerateEvent`: cancellable, called when a player naturally regenerates health.\n- `PlayerSpectateEvent`: cancellable, called when a spectator tries to spectate an entity by attacking it.\n- `PotionVisibilityEvent`: cancellable, called when an entities potion state (ambient, particle color and invisibility) is updated.\n- `TotemUseEvent`: cancellable, called when a totem prevents an entity from dying.\n\n### Custom combat features\n\nIt is possible to create your own combat features, which can extend an existing one or be completely independent.\nBelow is an explanation followed by an example.\n\nIn order to be compatible with the library, your combat features must implement `CombatFeature`.\nIt is also possible to implement `RegistrableFeature` instead, which will provide you with a `createNode()` method.\nIn this case, you must also implement `RegistrableFeature#init(EventNode)`, which attaches all the listeners to the given event node.\n\nAfter this, you must create a `FeatureType` for your custom feature.\nIf you are implementing an existing feature, use existing feature types in the `FeatureType` class.\nOtherwise, you can create your own using `FeatureType.of(String, F)`.\nThe first argument will be the name, the second the `NO_OP` feature which will be used when no implementation is present.\nIt is recommended to create an interface for your custom feature type which extends `CombatFeature` (or `RegistrableFeature`).\nThis way, you can easily specify methods to expose to other features.\n\nLastly, it is needed to create a `DefinedFeature` instance for your custom implementation.\nThis defined feature defines an implementation of your feature type, and it can be used to add your implementation to a combat configuration.\n\nExample of a custom feature type, with 1 method which can be used by other features:\n\n```java\ninterface MyCustomFeature extends CombatFeature {\n\tMyCustomFeature NO_OP = new MyCustomFeature() {};\n\t\n\tFeatureType TYPE = FeatureType.of(\"MY_CUSTOM\", NO_OP);\n\t\n\tboolean isItWorking();\n}\n```\n\nExample of an implementation of this custom feature type, which listens for events and implements the method:\n\n```java\nclass MyCustomFeatureImpl implements MyCustomFeature, RegistrableFeature {\n    public static final DefinedFeature\u003cMyCustomFeatureImpl\u003e DEFINED = new DefinedFeature\u003c\u003e(\n            MyCustomFeature.TYPE, configuration -\u003e new MyCustomFeatureImpl()\n    );\n\n    @Override\n    public void init(EventNode\u003cPlayerInstanceEvent\u003e node) {\n        node.addListener(PlayerChatEvent.class, event -\u003e {\n            // Do something...\n        });\n    }\n\n    @Override\n    public boolean isItWorking() {\n        return true;\n    }\n}\n```\n\nNow you can use your own feature:\n\n```java\nMinecraftServer.getGlobalEventHandler().addChild(\n        CombatFeatures.single(MyCustomFeatureImpl.DEFINED)\n);\n```\n\nAs you can see, it is also possible to use `CombatFeatures.single(DefinedFeature)` to instantiate a single feature without dependencies.\n\n#### Depending on other features\n\nSay, you want to access a players fall distance in your own feature. You can do this by depending on `FallFeature`.\n\n```java\nclass MyCustomFeatureImpl implements MyCustomFeature {\n    public static final DefinedFeature\u003cMyCustomFeatureImpl\u003e DEFINED = new DefinedFeature\u003c\u003e(\n            MyCustomFeature.TYPE, configuration -\u003e new MyCustomFeatureImpl(configuration),\n            FeatureType.FALL\n    );\n\n    private final FeatureConfiguration configuration;\n    private FallFeature fallFeature;\n\n    public MyCustomFeatureImpl(FeatureConfiguration configuration) {\n        this.configuration = configuration;\n    }\n\n    @Override\n    public void initDependencies() {\n        this.fallFeature = configuration.get(FeatureType.FALL);\n    }\n\n    @Override\n    public boolean isItWorking() {\n        Player player; // Some player\n        return fallFeature.getFallDistance(player) \u003e 3;\n    }\n}\n```\n\nNote that the `FeatureConfiguration` which can be used to get the `FallFeature` from is only ready when `initDependencies()` is called.\nThis is due to complications with recursive dependencies between features.\n\n#### Player init\n\nYou might want to initialize certain things for a player upon joining or whenever they get reset (respawn).\nThis is possible by using the player init of a defined feature. Its constructor can also take a `DefinedFeature.PlayerInit`.\nThis is a class whose `init(Player player, boolean firstInit)` method will be called upon a player join or reset.\n\nYou can for example use this player init to set tags on a player. The vanilla implementation of `FallFeature` uses it to set the fall distance tag on the player to 0.\n\nThere are two criteria to use the player init:\n- The logic does not depend on other features and as such can be defined once for every feature implementation, and not for every instance of this implementation.\n- The logic is required to be ran for the feature to work. If this is done inside the feature itself it might be out of scope (e.g. player join event is not called on an instance, so the feature might miss it).\n\n## Contributing\n\nYou can contribute in multiple ways.\nIf you have an issue or a great idea, you can open an issue.\nYou may also open a new pull request if you have made something for this project and you think it will fit in well.\n\nIf anything does not integrate with your project, you can also open an issue (or submit a pull request).\nI aim towards making this extension as usable as possible!\n\n## Credits\n\nThanks to [kiip1](https://github.com/kiip1) for testing and finding bugs.\n\nI used [BukkitOldCombatMechanics](https://github.com/kernitus/BukkitOldCombatMechanics) as a resource for recreating legacy pvp.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FTogAr2%2FMinestomPvP","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FTogAr2%2FMinestomPvP","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FTogAr2%2FMinestomPvP/lists"}