
SMP Swords
⚔️ SMP Swords – Custom Ability System for SMP Servers Transform your Minecraft SMP into a powerful custom ability experience! With a single command, every player receives a unique custom sword with special abilities. Designed for competitive SMP servers,
2.0.0
Compatibility
Changes
Release Notes — v2.0.0
Initial release. The plugin was completely rebuilt from a broken and incomplete source. Below is a comprehensive changelog of everything that was added, fixed, changed, and removed.
Added
Visuals & Custom Textures
- Custom 16×16 Textures: Added 5 distinct 16×16 sword textures (Fire, Lightning, Teleport, Life Steal, Freeze) featuring element-specific accent pixels.
- Model JSON Overrides: Configured custom model overrides for
netherite_swordmappingcustom_model_datavalues1001–1005to their respective custom sword models. - Bundled Resource Pack: Packaged the resource pack directly inside the JAR (
pack_format: 34,supported_formats: [34, 99]). It automatically extracts toplugins/SMPSwords/resourcepack/on first startup.
Core Commands & Tab Completion
/smp reload:** Added a command to reloadconfig.ymlon the fly without needing to restart the server./smp pack:** Added a command to force-push the configured resource pack to all online players.- Tab Completion: Implemented proper tab completion for player names in
/smp give <player> <type>. /smpswordsAlias:** Added/smpswordsas an alternative command alias for/smp.
Abilities & Gameplay Mechanics
- Safe-Landing Check (Teleport): The Teleport ability now performs a safety scan, walking up to 3 blocks up or down to find a solid, safe landing spot.
- Teleport Effects: Added immersive particle and sound feedback on teleportation (portal particles accompanied by the Enderman teleport sound).
- Action-Bar Cooldowns: Real-time cooldown countdown messages are now displayed on the action bar utilizing Spigot's
player.spigot().sendMessage(...)API. - Inventory Overflow Handling: If a player's inventory is full when receiving a sword, the item is dropped at their feet, and a chat warning is sent.
- Drop Intercept Feedback: Added a chat notification when a player attempts to drop a custom sword, clarifying why the action was blocked instead of cancelling silently.
- Clean Item Presentation: Attached item flags to hide the default enchantment glint and unbreakable tags on all custom swords.
Fixed
Build & Dependency Management
- Build Failure (XSeries Integration): Added the missing
com.github.cryptomorin:XSeries:11.2.1dependency and integrated thecom.gradleup.shadowplugin to bundle it into the final JAR. XSeries classes are relocated tocom.smpswords.libs.xseriesto eliminate conflicts with other plugins. - Missing
settings.gradle: Resolved a critical Gradle configuration issue where the project root could not be determined. - Missing Textures: Rectified an issue where only model JSON files existed while
layer0texture references pointed to non-existent PNGs (which previously caused swords to render as plain vanilla netherite swords). - Outdated Pack Format: Fixed an issue where
pack.mcmetatargetedpack_format: 15(Minecraft 1.19.4), causing Minecraft 1.21 to reject the resource pack. Bumped format to34. - Duplicate Resource Pack Folder: Eliminated a duplicate
resourcepack/folder sitting at the project root. Only the functional copy insidesrc/main/resources/remains.
Crash & Bug Fixes
LightningAbility.onRightClickNullPointerException (NPE): Fixed a crash whereplayer.getTargetBlock(null, 20)returned null and was dereferenced without protection. It now safely falls back to a targeted coordinate 15 blocks in front of the player's line of sight.- Griefing/Self-Damage via Lightning:
LightningAbilityoriginally usedstrikeLightning, which inadvertently spread fire and damaged the attacker. Switched tostrikeLightningEffectcombined with manualdamage()calls so only the intended target takes damage and no fire spreads. LifeStealAbilityCrash: Fixed anIllegalArgumentExceptionthrown when callingsetHealth()if the attacker died in the brief window between landing a hit and the ability firing. Added anisDead()/isValid()guard block and wrapped it in atry/catch.- Reflection-based Attribute Handling: Replaced the fragile reflection-based
XAttribute.of("generic.max_health")inLifeStealAbilitywith the direct vanillaAttribute.GENERIC_MAX_HEALTHenum. - Tangled Cooldown Logic: Cleaned up overlapping logic where
AbilityManager.triggerHitchecked the cooldown whileLightningAbilitysimultaneously checked and modified it. All cooldown tasks are now strictly centralized insideAbilityManager. - Outdated Resource Pack API: Upgraded
ResourcePackManagerfrom the deprecatedsetResourcePack(String)method—which ignored config options for prompts and required enforcement—to the modern Spigot 1.21 API:setResourcePack(String url, byte[] hash, String prompt, boolean required). It now correctly parses hex hashes intobyte[]. SwordInfoGUIOwnership Bug: Fixed a flaw wherehasSwordwas incorrectly calculated viatype == playerSwords.get(uuid). This caused issues since a player can carry multiple custom swords. The GUI now scans the player's active inventory for any matches.SwordManager.distributeToAllSkipping Flaw: Fixed a logic bug where a disabled sword type was only skipped once; if two consecutive types were disabled, the second one could still be distributed. The method now safely loops across all types until it matches an enabled option.- Thread Visibility Defect (
smpActive): MarkedSMPSwords.smpActiveasvolatileto fix a concurrency bug where state changes written by command threads weren't reliably seen by event threads. - Duplicate Listener Registration: Fixed a bug where
ResourcePackManagerregistered itself as an event listener twice (once in its constructor and again inSMPSwords.onEnable). - Ugly Tab Completion Console Warnings: Corrected a behavior where tab completion returned null for player names under
/smp give, producing console warnings. It now returns a properly filtered list of active player names. plugin.ymlSyntax Clean up: Quotedapi-version: "1.21"for strict YAML compliance and documented the usage properties for the new/smp reloadand/smp packsubcommands.
Changed
- Namespaced Texture Paths: Updated model JSON references to use the safer, fully-namespaced
minecraft:item/custom/<name>pathing structure instead of the looseritem/custom/<name>. - Stateless Abilities: Refactored all abilities to be entirely stateless. Abilities no longer call
plugin.getAbilityManager().isOnCooldown(...)internally; instead,AbilityManagerevaluates the cooldown window prior to execution and triggers the cooldown timer immediately after. - Startup Logs: Added a clean info notification inside
SMPSwords.onEnable()to log a proper startup confirmation message. - Configuration File Cleanup: Polished
config.ymlwith cleaner indentation, structured spacing, and descriptive inline documentation.
Removed
- Root-Level
resourcepack/Folder: Deleted the duplicate folder from the repository root to ensure all assets build cleanly out ofsrc/main/resources/resourcepack/.
Supplementary resources
| File | Type | Size | |
|---|---|---|---|
| SMPSwords-resourcepack.zip | Unknown | 6.93 KiB |
Projects on Modrinth are automatically available through a Maven repository for use with JVM build tools such as Gradle. To learn more about the Modrinth Maven API, click here.
Note: When available, you should use the creator's maven repo instead as it will have transitive dependency information that the Modrinth Maven API does not. You may also end up with duplicate dependencies if you use a mix of Modrinth and non-Modrinth Maven repositories for your dependencies, because the group identifier will be different when served through the Modrinth Maven API.
Maven coordinates:
Version ID:
build.gradle:
repositories {
exclusiveContent {
forRepository {
maven {
name = "Modrinth"
url = "https://api.modrinth.com/maven"
}
}
// forRepositories(fg.repository) // Uncomment when using ForgeGradle
filter {
includeGroup "maven.modrinth"
}
}
}
// Standard Gradle dependency
dependencies {
implementation "maven.modrinth:bXj9fo6w:rQpIyLxv"
}
// Legacy Loom dependency
dependencies {
modImplementation "maven.modrinth:bXj9fo6w:rQpIyLxv"
}
