
CombatGunSSS
Adds 45 unique guns to Minecraft, each with custom damage, recoil, fire rate, and reload mechanics, enhancing combat with balanced gameplay, multiple weapon types, and flexible customization for varied playstyles
124
3
CombatGunSSS 2.0.3
release18 апреля 2026 г.[2.0.3] - 2026-04-18
Fixed
🔴 AmmoPouchManager.unpackPouch() — Pouch lost when inventory is full (Critical)
- Root cause: When partially unpacking (only a few slots left in inventory), the code always called
pouch.setAmount(0)regardless of how many bullets were actually transferred. The entire pouch was destroyed even if bullets remained inside. - Fix: If
remaining > 0(unpack not completed), update the PDCpouch_quantityto the remaining amount and refresh the lore instead of destroying the pouch. Only callsetAmount(0)when all bullets have been successfully transferred.
🔴 ReloadManager — Reload task running every 1 tick causing high CPU usage (Critical)
- Root cause:
runTaskTimer(plugin, 0L, 1L)scheduled 20 times per second for every player reloading. With 10 players reloading simultaneously, this resulted in 200 task calls per second just for the progress bar. - Fix: Changed to
runTaskTimer(plugin, 0L, 2L)and adjustedtotalTicks = reloadTime * 10.0so reload duration remains unchanged. This reduces reload system CPU load by approximately 50%.
🔴 GunListener.isHeadshot() — Inaccurate headshots while player is crouching (Critical)
- Root cause: Used fixed
entity.getHeight() * 0.8without accounting for crouching players (hitbox shrinks to ~1.5 blocks instead of 1.8). - Fix: Detect
player.isSneaking()and multiplyheight *= 0.85before calculating headY threshold. Headshot detection is now accurate for both standing and crouching states.
🔴 CraftingManager.craftFromStation() — No rollback when crafting fails (Critical)
- Root cause:
consumeIngredients()ran beforecreateResultItem(). IfcreateResultItem()returnednull(invalid gun ID, config error, etc.), ingredients were consumed but no item was given → permanent item loss. - Fix: Snapshot all input slots before consuming. If
createResultItem()returnsnull, restore ingredients from the snapshot.
🟡 GunListener.applyRecoil() — Potential NPE when AntiCheatHook is disabled (Medium)
- Root cause:
if (hm2 != null) hm2.getAntiCheatHook().exempt(player)— checkedhm2but notgetAntiCheatHook(). If the hook was disabled,getAntiCheatHook()could return an uninitialized instance. - Fix: Added full guard:
hm2 != null && hm2.getAntiCheatHook() != null && hm2.getAntiCheatHook().isActive()before callingexempt().
🟡 BleedingManager — Incorrect damage during server lag (Medium)
- Root cause: Task used
elapsed += 20to count ticks, but when the server lagged (>50ms per tick), actual damage was lower than the configureddamage_per_second. - Fix: Switched to
System.currentTimeMillis()for real-time tracking.lastDamageTimeis now updated only when damage is actually applied, ensuring exactly 1 second between damage ticks regardless of server lag.
🟡 CraftingManager.consumeIngredients() — Incorrect null-check order (Medium)
- Root cause:
identifyIngredient(item)was called before checkingitem == null, causing potential NPE with empty inventory slots in some edge cases. - Fix: Moved
if (item == null || item.getType().isAir()) continue;before callingidentifyIngredient().
🟡 GunListener.onItemHeldChange() — Race condition when switching slots rapidly (Medium)
- Root cause: Task with 0-tick delay read
getItemInMainHand()— if the player switched slots again before the task ran, it would process the wrong slot's item. - Fix: Store
newSlot = event.getNewSlot()before scheduling the task. Inside the task, checkplayer.getInventory().getHeldItemSlot() != newSlotand abort if the player has switched slots again.
CombatGunSSS 2.0.2
release14 апреля 2026 г.[2.0.2] - 2026-04-14
Fixed
NullPointerException: HudManager.sendNow() when shooting any gun
- Root cause:
GunListenercachedplugin.getHudManager()into afinal HudManager hudManagerfield inside its constructor. However,GunListeneris instantiated inregisterListeners()which runs beforestartServices()whereHudManageris created. The field was alwaysnullat the time of assignment. - Fix: Removed the cached
hudManagerfield entirely. All two call-sites now useplugin.getHudManager()inline with a null-guard:if (plugin.getHudManager() != null) plugin.getHudManager().sendNow(player). This makes the call lazy — it resolves the reference at the moment of use rather than at construction time, so startup order no longer matters.
CombatGunSSS 2.0.1
release14 апреля 2026 г.[2.0.1] - 2026-04-14
Fixed
Plugin crash on startup (onEnable exception → plugin disabled)
- Root cause: Any uncaught exception inside
onEnable()caused Bukkit to calldisablePlugin()immediately, leaving the plugin in a broken state where commands responded with "plugin is disabled" instead of a useful error message. - Fix: Refactored
onEnable()into isolated private methods (initManagers(),registerListeners(),startServices(),registerCommands()). Each step is now wrapped in a top-level try-catch. A detailed stack trace is printed to console before the plugin gracefully self-disables — making the actual root cause visible instead of a cryptic command error.
StatsManager (SQLite) failure no longer kills the plugin
statsManager.init()is now wrapped in its own try-catch. If SQLite initialisation fails (missing driver, file permission error, corrupted DB), the plugin logs a warning, setsstatsManager = null, and continues loading. All stats-dependent features (/gun stats,/gun leaderboard, PAPI%combatgun_kills%etc.) degrade gracefully with a user-friendly error message.
HookManager failure no longer kills the plugin
hookManager.initAll()is wrapped in a try-catch. If any soft-depend integration throws an unexpected exception, the hook manager is set tonulland the plugin runs without integrations rather than crashing entirely.
Null pointer exceptions when hookManager or statsManager are null
GunListener.isAllowed()— WorldGuard check now guards withhm != nullbefore callingcanShoot().GunListener.applyRecoil()— AntiCheat exempt call guarded withhm2 != null.GunCommand.handleBuy()— Vault access guarded; returns a friendly error if hook manager is unavailable.GunCommand.handleStats()/handleLeaderboard()— Guarded withstatsManager != nullcheck; returns a friendly error if stats are disabled.EntityDeathListener— Stats recording guarded withstatsManager != null.
Material.GREY_DYE compile error
ThrowableManagerused the pre-1.13 material nameGREY_DYEwhich no longer exists. Corrected toGRAY_DYE(American English naming introduced in the 1.13 flattening).
Changed
onEnable()restructured intoinitManagers(),registerListeners(),startServices(),registerCommands(),scheduleCleanup(),printStartupBanner()for clarity and fault isolation.onDisable()wraps each cleanup call in its own try-catch so a failure in one manager never prevents the others from shutting down cleanly.- Startup banner now correctly reads version from
plugin.ymlat runtime viagetDescription().getVersion()— no hardcoded version strings in Java code.
CombatGunSSS 2.0.0
release13 апреля 2026 г.[2.0.0] - 2026-04-12
Added
Weapon Attachment System
- Four attachment types with stackable stat modifiers:
SILENCER— reduces sound radius (config:sound_radius_multiplier) with optional damage penalty.EXTENDED_MAG— adds flat magazine capacity (config:magazine_bonus).GRIP— reduces pitch recoil and bullet spread (config:recoil_pitch_multiplier,spread_multiplier).SCOPE— enables precision scope spread at runtime, even on guns wherescopeable: false.
- Each gun holds at most one attachment per slot. Attaching a second of the same type replaces the first.
- Attachments persist on the gun item via PersistentDataContainer keys (
combatgun:attach_silencer, etc.). - Commands:
/gun attach <id>,/gun detach <TYPE>,/gun attachments(inspect held gun). - Config: Defined under
combatgun.attachments.<id>inconfig.yml. Five built-in definitions included (silencer, extended_mag_ar, extended_mag_smg, tactical_grip, acog_scope). AttachmentManagerexposes stat modifier helpers used at shoot time:soundMultiplier(),damageMultiplier(),magBonus(),spreadMultiplier(),recoilPitchMultiplier(),hasScopeAttachment().
Throwable Items (Grenades)
- Three throwable types, all thrown as Snowball projectiles and detonated on
ProjectileHitEventor after fuse:FRAG— Creates a visual explosion and deals falloff damage to nearby entities.SMOKE— Spawns a timed smoke particle cloud (campfire smoke particles for 10 seconds by default).FLASHBANG— Applies Blindness and Slowness (simulated deafness) to nearby players, scaled by distance.
- Command:
/gun givethrowable <id> [player]. - Config: Defined under
combatgun.throwables.<id>with full control over fuse, radius, damage, duration, and effect ticks. Three built-in throwables included. ThrowableListenerhandles right-click throw and projectile landing. Registered as a separate listener fromGunListener.- Projectiles are tracked in
ThrowableManager.liveProjectilesand auto-detonate afterfuse_ticksif they don't land.
Kill Statistics & Leaderboard
- New
StatsManagerbacked by SQLite (plugins/CombatGunSSS/stats.db). No external database required. - Tracks per-player: kills, deaths, headshots, and per-gun kill counts.
- Write buffer flushes to DB every 5 minutes and on plugin disable — minimises disk writes while keeping data safe.
- Commands:
/gun stats [player](view stats),/gun leaderboard(top 10 by kills). - New PlaceholderAPI placeholders:
%combatgun_kills%,%combatgun_deaths%,%combatgun_headshots%,%combatgun_kd%. EntityDeathListenernow callsStatsManager.recordKill()andrecordDeath()on every gun kill.- SQLite JDBC shaded into the jar via
maven-shade-pluginwith relocation todev.duong2012g.combatgun.libs.sqlite— no external jar needed.
Changed
CombatGunSSSPlugin— registersAttachmentManager,ThrowableManager,StatsManager; registersThrowableListener;onDisable()callsstatsManager.shutdown(); startup log prints attachment/throwable counts and stats DB status.GunCommand— addedattach,detach,attachments,givethrowable,stats,leaderboardtoSUB_COMMANDS, switch, tab completion, and help.PlaceholderHook— addedkills,deaths,headshots,kdplaceholders (total 12 placeholders now).EntityDeathListener— records kill/death toStatsManageron every confirmed gun kill.plugin.yml— version bumped to2.0.0.pom.xml— version bumped to2.0.0; addedsqlite-jdbc 3.45.1.0as compile dependency; addedmaven-shade-pluginto shade and relocate SQLite.config.yml— addedcombatgun.attachmentsandcombatgun.throwablessections with default definitions.
CombatGunSSS 1.1.0
release10 апреля 2026 г.[1.1.0] - 2026-04-10
Added
PlaceholderAPI Integration
- New soft-depend on PlaceholderAPI. When the plugin is present, CombatGunSSS registers a
%combatgun_*%expansion with 8 real-time placeholders:
| Placeholder | Example | Description |
|---|---|---|
%combatgun_gun_name% | AK47 | Display name of held gun |
%combatgun_gun_id% | ak47 | Internal ID of held gun |
%combatgun_gun_rarity% | epic | Rarity of held gun |
%combatgun_ammo% | 24 | Current magazine ammo |
%combatgun_ammo_max% | 30 | Magazine capacity |
%combatgun_ammo_reserve% | 90 | Reserve ammo in inventory |
%combatgun_is_reloading% | true | Whether player is reloading |
%combatgun_is_gun% | true | Whether held item is a gun |
- All placeholders return safe empty-string or
0defaults when the player holds no gun. - Compatible with scoreboard plugins (AdvancedHud, TAB, AnimatedScoreboard, etc).
Vault Economy / Shop
- New soft-depend on Vault. When an economy provider is found and
combatgun.shop.enabled: true, players can purchase weapons via/gun buy <gun_id>. - Prices are configured per gun in
config.ymlundercombatgun.shop.guns. All 45 built-in weapons have default prices included in the generated config. - Admin shortcut:
/gun buy <gun_id> freegives the weapon at no cost (requirescombatgun.admin). - Clear failure messages for insufficient funds, missing price entry, and unavailable economy.
/gun buyadded to tab completion and/gunhelp output.VaultHookis a standalone class —VaultHook.buyGun()can be called from third-party plugins that depend on CombatGunSSS.
WorldGuard Region Protection
- New soft-depend on WorldGuard. When present, a custom flag
gun-shootingis registered duringonLoad()(before WorldGuard reads region data). - Shooting is blocked in any region where
gun-shootingis set todeny:/rg flag <region> gun-shooting deny # block all gun use /rg flag <region> gun-shooting allow # explicitly allow - Falls back to WorldGuard's built-in
PVPflag whengun-shootingis not configured on a region. - Applies to all ranged shots and is checked inside
isAllowed()— same path as world and permission checks. Players receive an action-bar message:⛔ Guns are disabled in this region. - Fails open on unexpected errors to avoid breaking gameplay.
Anti-Cheat Exemptions (Vulcan & Matrix)
- New soft-depend detection for Vulcan and Matrix anti-cheat plugins.
- When either plugin is detected,
AntiCheatHook.exempt(player)is called immediately beforeapplyRecoil()— preventing false-positive flags on the camera pitch/yaw changes that recoil applies. - Exemption is automatically removed after
combatgun.anticheat.exempt_ticksticks (default3). - Both exemption and un-exemption calls are fully wrapped in try-catch — an API version mismatch in either anti-cheat never crashes CombatGunSSS.
Central HookManager
- New
HookManagerclass owns all hook instances (PlaceholderHook,VaultHook,WorldGuardHook,AntiCheatHook). - Initialized once in
onEnable(). Each hook initializes independently — a failure in one never prevents others from loading. - Accessible via
plugin.getHookManager()for third-party plugins that want to query hook state. - Startup log now prints
Shop: ON (Vault)andWGuard: ONlines based on detected integrations.
Changed
pom.xml— addedprovideddependencies for PlaceholderAPI2.11.6, VaultAPI1.7, and WorldGuard7.0.9. All three are compile-time only (never shaded into the jar).plugin.yml— version bumped to1.1.0; addedsoftdependlist:[PlaceholderAPI, Vault, WorldGuard, Vulcan, Matrix]; updated command description to includebuy; updated plugin description.config.yml— addedcombatgun.shopsection withenabled,currency_symbol, and per-gun price list for all 45 built-in weapons; addedcombatgun.anticheat.exempt_tickskey; added inline documentation comments for WorldGuard.GunCommand— addedbuytoSUB_COMMANDSlist, switch statement, tab completion, and help text; addedhandleBuy()method.GunListener.isAllowed()— added WorldGuard region check between world check and permission check.GunListener.applyRecoil()— callsantiCheatHook.exempt(player)before applying camera rotation.CombatGunSSSPlugin.onLoad()— addedWorldGuardHook.registerFlags()call (required before WorldGuard reads region data).CombatGunSSSPlugin.onEnable()— initializesHookManagerafter all managers are ready; startup log prints hook status lines.
Совместимость
Создатели
Детали
Лицензия:Apache-2.0
Опубликован:3 недели назад
Обновлён:1 день назад
