All versions
๐ด
๐ด
๐
2.2.0
Release
CombatGunSSS 2.2.03 months ago 27
Compatibility
Minecraft: Java Edition
1.21.x
Platforms
Bukkit
Paper
Purpur
Spigot
Changes
[2.2.0] - 2026-07-18
Fixed
๐ด GunCommand โ Every player-facing subcommand blocked for non-admins (Critical)
- Root cause:
onCommand()gated the entire/guncommand tree behindcombatgun.adminbefore dispatching to any subcommand, andplugin.ymladditionally declaredpermission: combatgun.admindirectly on the command โ so Bukkit's own command dispatcher rejected non-admins beforeonCommand()ever ran. This silently broke/gun buy(the Vault shop),/gun attach//gun detach//gun attachments,/gun stats,/gun leaderboard, and/gun recipefor every player withoutcombatgun.admin, even though several of these handlers already contained their owncombatgun.usecheck โ a check that could never actually execute. - Fix: Removed the command-level
permission:entry fromplugin.yml.onCommand()now checks a newPLAYER_SUBCOMMANDSset โbuy, attach, detach, attachments, stats, leaderboard, recipe, the self-service subcommands that take no target-player argument โ againstcombatgun.useORcombatgun.admin. Every other subcommand (give, giveammo, givepart, station, book, givepouch, givethrowable, inspect, reload, statsreset, seasonreset) still requirescombatgun.admin, since each of those can act on an arbitrary target player and is not meant to be self-service.
๐ด GunCommand.onTabComplete() โ Same admin-only gate hid tab-completion for regular players (High)
- Root cause: Identical bug to the one above โ
onTabComplete()returned an empty list for any sender withoutcombatgun.admin. Even after fixingonCommand(), non-admins would still see zero suggestions when typing/gun. - Fix:
onTabComplete()now mirrors thePLAYER_SUBCOMMANDSpermission split โ non-admins withcombatgun.usesee the subcommand names they're allowed to run, and id-completion for/gun recipe <id>(a read-only lookup) is available to them as well. Argument completion for admin-only give/inspect/config subcommands remains gated behindcombatgun.admin.
๐ VaultHook.buyGun() โ Purchased weapon silently lost when inventory is full (Medium)
- Root cause:
player.getInventory().addItem(gunItem)was called without checking its return value.addItem()silently drops anyItemStackthat doesn't fit, so a player with a full inventory was charged the full price but never actually received the gun. - Fix: The leftover
ItemStacks returned byaddItem()are now dropped at the player's feet viadropItemNaturally(), and the player receives an additional chat message letting them know the purchase was dropped rather than lost.
Added
CraftingManager โ Recipe Browser split into Gun / Melee / Ammo tabs
- The recipe browser (opened from the Mechanical Crafting Table's book icon) now shows three clickable category tabs in its bottom row instead of one long mixed list, so players can find what they want to craft without scrolling past unrelated items.
- New
CraftingManager.BrowserCategoryenum (GUN,MELEE,AMMO). Guns and melee weapons are both stored underRecipeData.RecipeKind.GUNinternally, so the split is done by checkingGunData.isMelee()rather than changing the existing recipe-kind enum โ this avoids touching the exhaustiveswitchonRecipeKindinCustomItemManager. - Each player's last-viewed tab is remembered in-memory (keyed by UUID) so paging with prev/next stays on the same category instead of resetting to Gun; the cache entry is cleared on
PlayerQuitEventto avoid unbounded growth. - A category with no recipes configured shows an explicit "No recipes here" placeholder instead of an empty page.
openRecipeBrowser(Player, int)is preserved for existing call sites and now delegates to a newopenRecipeBrowser(Player, int, BrowserCategory)overload.
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:BSt2YZOI:BH1DmUo0"
}
// Legacy Loom dependency
dependencies {
modImplementation "maven.modrinth:BSt2YZOI:BH1DmUo0"
}

