CombatMetrics

A minecraft plugin that shows your combo nd crit counter in a row and it resets if u can't in a row which will help improve u with combo and crit chains....

36

Quick challenge

How far can you run before the mobs catch you?

CombatMetrics

**## Overview

Sprint Combo Hits is a lightweight, high-performance combat tracking plugin for Paper 1.21+ servers. It accurately detects and displays Sprint Combo Hits and Sprint Combo Hits in real-time using the player's Action Bar. The plugin faithfully replicates vanilla Minecraft's exact combat mechanics, ensuring that every tracked hit matches what would trigger the corresponding subtitle/particle effect in the base game.

Core Concept

``` ┌─────────────────────────────────────────────────────────────────────┐ │ COMBATMETRICS FLOW │ ├─────────────────────────────────────────────────────────────────────┤ │ │ │ PLAYER ATTACKS ENTITY │ │ │ │ │ ▼ │ │ ┌────────────────────┐ ┌────────────────────┐ │ │ │ Check Critical │ │ Check Combo │ │ │ │ Hit Conditions │ │ Hit Conditions │ │ │ │ (11 Checks) │ │ (3 Checks) │ │ │ └─────────┬──────────┘ └─────────┬──────────┘ │ │ │ │ │ │ ▼ ▼ │ │ ┌────────────────────┐ ┌────────────────────┐ │ │ │ Increment Crit │ │ Increment Combo │ │ │ │ Counter │ │ Counter │ │ │ └─────────┬──────────┘ └─────────┬──────────┘ │ │ │ │ │ │ └───────────┬───────────────┘ │ │ ▼ │ │ ┌────────────────────────┐ │ │ │ UPDATE ACTION BAR │ │ │ │ [ ☠ CRITS: X | ⚔ COMBO: Y ] │ │ └────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌────────────────────────┐ │ │ │ No hit for 2 seconds? │ │ │ │ → Reset counters to 0 │ │ │ └────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────┘ ```

---

✨ Features

Core Features

| Feature | Description | |---------|-------------| | Hit Highlighting | Detects vanilla-accurate critical hits using 11 strict conditions | | Hit Highlighting | Detects sprint knockback hits for combo counting | | Hit Highlighting | Shows live counters in the Action Bar | | Hit Highlighting | Counters automatically reset after 2 seconds of inactivity | | Hit Highlighting | Text positioned on left side of screen for better visibility | | Hit Highlighting | Brief green flash when a hit is registered |

Persistence Features

| Feature | Description | |---------|-------------| | No External Storage | Each player can enable/disable their display | | No External Storage | Preference saved using PersistentDataContainer | | No External Storage | Settings persist across server restarts | | No External Storage | Data stored directly on player entity |

⚡ Performance Features

| Feature | Description | |---------|-------------| | Lightweight Task | Reset detection runs on async thread | | Lightweight Task | ConcurrentHashMap for thread-safe access | | Lightweight Task | Early-return conditions prevent unnecessary processing | | Lightweight Task | Data created only when player attacks | | Lightweight Task | Timer runs every 5 ticks (0.25 seconds) |

---

☠️ Critical Hit Detection

CombatMetrics uses ALL detection that matches Minecraft's exact critical hit requirements. A hit is only counted as critical if ALL conditions are met:

Condition Checklist

| # | Condition | Method Used | Explanation | |---|-----------|-------------|-------------| | 1 | Charged Attack | `fallDistance > 0.0` | Player must have positive fall distance | | 2 | Charged Attack | `!isOnGround()` | Player cannot be touching the ground | | 3 | Charged Attack | `!isClimbing()` | Cannot be on ladder, vine, or scaffolding | | 4 | Charged Attack | `!isInWater()` | Cannot be submerged in water | | 5 | Charged Attack | `!isInLava()` | Cannot be submerged in lava | | 6 | Charged Attack | `!isSwimming()` | Cannot be using swimming animation | | 7 | Charged Attack | `!isGliding()` | Cannot be flying with Elytra | | 8 | Charged Attack | `!hasPotionEffect(BLINDNESS)` | Blindness effect blocks crits | | 9 | Charged Attack | `!hasPotionEffect(SLOW_FALLING)` | Slow falling prevents crits | | 10 | Charged Attack | `!isInsideVehicle()` | Cannot be riding any entity | | 11 | Charged Attack | `getAttackCooldown() > 0.9` | Attack must be 90%+ charged |

Visual Representation

``` CRITICAL HIT VALIDATION

Player State Check Result ══════════════════════════════════════════

fallDistance > 0 ? ───────────→ ✓ PASS │ ▼ !isOnGround() ? ───────────→ ✓ PASS │ ▼ !isClimbing() ? ───────────→ ✓ PASS │ ▼ !isInWater() ? ───────────→ ✓ PASS │ ▼ !isInLava() ? ───────────→ ✓ PASS │ ▼ !isSwimming() ? ───────────→ ✓ PASS │ ▼ !isGliding() ? ───────────→ ✓ PASS │ ▼ No BLINDNESS ? ───────────→ ✓ PASS │ ▼ No SLOW_FALLING ? ───────────→ ✓ PASS │ ▼ !isInsideVehicle()? ───────────→ ✓ PASS │ ▼ attackCooldown > 0.9? ─────────→ ✓ PASS │ ▼ ══════════════════════════════════════════ │ ▼ ★ CRITICAL HIT REGISTERED ★ ```

---

⚔️ Combo Hit Detection

Combo hits detect sprint knockback attacks - the enhanced knockback applied when a player hits an enemy while sprinting.

Condition Checklist

| # | Condition | Method Used | Explanation | |---|-----------|-------------|-------------| | 1 | Living Target | `isSprinting()` | Player must be actively sprinting | | 2 | Living Target | `getAttackCooldown() > 0.9` | Attack must be 90%+ charged | | 3 | Living Target | `instanceof LivingEntity` | Target must be able to receive knockback |

Visual Representation

``` COMBO HIT VALIDATION

Player State Check Result ══════════════════════════════════════════

isSprinting() ? ───────────→ ✓ PASS │ ▼ attackCooldown > 0.9? ─────────→ ✓ PASS │ ▼ Target is Living? ───────────→ ✓ PASS │ ▼ ══════════════════════════════════════════ │ ▼ ★ COMBO HIT REGISTERED ★ ```

---

️ Visual Display System

Action Bar Format

``` ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ [ ☠ CRITS: 5 | ⚔ COMBO: 3 ] │ │ ↑ ↑ │ │ └── Left-aligned content └── Invisible spacing pushes left │ │ │ └─────────────────────────────────────────────────────────────────────┘ ```

Color Scheme

| Element | Color | Style | |---------|-------|-------| | `[` `]` | Dark Gray | Normal | | `☠` | Dark Red | Normal | | `CRITS:` | Red | Bold | | Crit Count | White | Normal | | `|` | Dark Gray | Normal | | `⚔` | Gold | Normal | | `COMBO:` | Yellow | Bold | | Combo Count | White | Normal |

Hit Highlight Effect

When a hit is registered, the corresponding counter briefly highlights:

``` Normal Display: [ ☠ CRITS: 5 | ⚔ COMBO: 3 ] ↑ ↑ White White

After Critical Hit (3 ticks): [ ☠ CRITS: 6 | ⚔ COMBO: 3 ] ↑ GREEN + BOLD

After Combo Hit (3 ticks): [ ☠ CRITS: 6 | ⚔ COMBO: 4 ] ↑ GREEN + BOLD ```

Left-Alignment Technique

Minecraft's Action Bar centers text by default. To achieve left-alignment:

```java // Append invisible spacing after the content Component content = actualContent .append(Component.text(" ") // ~80 spaces .color(NamedTextColor.BLACK)); // Invisible ```

This pushes the visible content to the left side of the screen, near the health/armor display.

---

⏱️ Reset Timer System

How It Works

``` ┌─────────────────────────────────────────────────────────────────────┐ │ RESET TIMER SYSTEM │ ├─────────────────────────────────────────────────────────────────────┤ │ │ │ TIME ──────────────────────────────────────────────────────→ │ │ │ │ HIT! RESET! │ │ │ │ │ │ ▼ ▼ │ │ ●━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━● │ │ │←────────────── 2000ms (40 ticks) ──────────────→│ │ │ │ │ │ │ lastHitTime currentTime │ │ │ │ │ │ [Async Task - Every 5 ticks] │ │ │ │ │ ▼ │ │ if (currentTime - lastHitTime >= 2000ms) { │ │ resetCounter(); │ │ updateActionBar(); // Show 0 briefly │ │ } │ │ │ └─────────────────────────────────────────────────────────────────────┘ ```

Independent Timers

Critical and Combo counters have separate timers:

``` SCENARIO: Player lands a crit, then keeps doing combo hits

Time: 0s 1s 2s 3s 4s 5s │ │ │ │ │ │ Crits: [1]─────[1]─────[0] (reset at 2s) │ │ │ Combos: [1]────[2]────[3]────[4]─────[4]─────[0] ↑ ↑ last combo reset at 5s ```

Grace Period

After counters reset to 0, there's a brief 500ms grace period before the display clears entirely:

``` HIT! → 2 seconds → RESET TO 0 → 500ms → CLEAR DISPLAY ↓ Show "[ ☠ CRITS: 0 | ⚔ COMBO: 0 ]" briefly ```

---

Commands & Permissions

Commands

| Command | Description | Permission | |---------|-------------|------------| | `/metrics toggle` | Enable/disable action bar display | `combatmetrics.use` | | `/metrics status` | View current stats and settings | `combatmetrics.use` | | `/metrics reset` | Reset both counters to zero | `combatmetrics.use` |

Command Aliases

- `/combatmetrics` - `/cm`

Permissions

| Permission | Default | Description | |------------|---------|-------------| | `combatmetrics.use` | `true` | Access to all player commands | | `combatmetrics.admin` | `op` | Reserved for future admin features |

Command Output Examples

Toggle ON: ``` ✓ Combat Metrics ENABLED Your combat stats will now display in the action bar. ```

Toggle OFF: ``` ✗ Combat Metrics DISABLED Action bar display has been turned off. ```

Status: ``` ══════ Combat Metrics Status ══════ Display: ENABLED Current Session: ☠ Critical Hits: 15 ⚔ Combo Hits: 23 ```

Reset: ``` ↺ Counters have been reset! ```

---

Data Persistence

PersistentDataContainer (PDC) Storage

``` ┌─────────────────────────────────────────────────────────────────────┐ │ PERSISTENCE SYSTEM │ ├─────────────────────────────────────────────────────────────────────┤ │ │ │ Namespace: combatmetrics │ │ Key: metrics_display_enabled │ │ Type: BYTE │ │ │ │ Values: │ │ 0 = Display DISABLED │ │ 1 = Display ENABLED │ │ null = Default to ENABLED │ │ │ │ Storage Location: Player Entity NBT Data │ │ │ └─────────────────────────────────────────────────────────────────────┘ ```

Persistence Benefits

| Benefit | Description | |---------|-------------| | Lightweight | No YAML/JSON configuration files per player | | Lightweight | No MySQL/SQLite required | | Lightweight | Saved with player data automatically | | Lightweight | Survives crashes, restarts, and relogs | | Lightweight | Single byte per player |

---

⚡ Performance Analysis

Memory Usage

``` Per Player: ┌────────────────────────────────────┐ │ MetricData Object │ ├────────────────────────────────────┤ │ int critCount = 4 bytes │ │ int comboCount = 4 bytes │ │ long lastCritTime = 8 bytes │ │ long lastComboTime = 8 bytes │ │ boolean needsUpdate = 1 byte │ │ Object overhead ≈ 16 bytes │ ├────────────────────────────────────┤ │ TOTAL ≈ 41 bytes │ └────────────────────────────────────┘

100 Players = ~4.1 KB memory 1000 Players = ~41 KB memory ```

CPU Usage

| Task | Frequency | Cost | |------|-----------|------| | Damage Event Handler | Per attack | Very Low (early returns) | | Async Reset Checker | Every 5 ticks | Minimal (simple timestamp comparison) | | Action Bar Update | On hit/reset | Low (Component creation) |

Optimization Techniques Used

| Technique | Implementation | |-----------|----------------| | Event Priority | Check cooldown first before other conditions | | Event Priority | Timer checks run off main thread | | Event Priority | Thread-safe without locks | | Event Priority | MetricData created on first attack | | Event Priority | Reuse patterns where possible | | Event Priority | MONITOR priority - runs after other plugins |

---

Event Flow

Complete Event Lifecycle

``` ┌─────────────────────────────────────────────────────────────────────┐ │ COMPLETE EVENT FLOW │ ├─────────────────────────────────────────────────────────────────────┤ │ │ │ 1. EntityDamageByEntityEvent Fired │ │ │ │ │ ▼ │ │ 2. Check: Damager is Player? │ │ │ NO → EXIT │ │ │ YES ↓ │ │ ▼ │ │ 3. Check: Target is LivingEntity? │ │ │ NO → EXIT │ │ │ YES ↓ │ │ ▼ │ │ 4. Check: Attack Cooldown > 0.9? │ │ │ NO → EXIT (weak attack) │ │ │ YES ↓ │ │ ▼ │ │ 5. Check Critical Hit Conditions (11 checks) │ │ │ PASS → Increment Crit Counter │ │ ▼ │ │ 6. Check Combo Hit Conditions (2 checks) │ │ │ PASS → Increment Combo Counter │ │ ▼ │ │ 7. Either counter incremented? │ │ │ NO → EXIT │ │ │ YES ↓ │ │ ▼ │ │ 8. Check: Display Enabled for Player? │ │ │ NO → EXIT │ │ │ YES ↓ │ │ ▼ │ │ 9. Update Action Bar with Highlight │ │ │ │ │ ▼ │ │ 10. Schedule Highlight Removal (3 ticks) │ │ │ └─────────────────────────────────────────────────────────────────────┘ ```

Async Reset Task Flow

``` ┌─────────────────────────────────────────────────────────────────────┐ │ ASYNC RESET TASK │ ├─────────────────────────────────────────────────────────────────────┤ │ │ │ [Runs every 5 ticks on Async Thread] │ │ │ │ │ ▼ │ │ FOR each online player: │ │ │ │ │ ▼ │ │ Get MetricData (if exists) │ │ │ NULL → SKIP │ │ │ EXISTS ↓ │ │ ▼ │ │ Check: shouldResetCrit(currentTime)? │ │ │ YES → resetCrit() │ │ ▼ │ │ Check: shouldResetCombo(currentTime)? │ │ │ YES → resetCombo() │ │ ▼ │ │ Any reset occurred? │ │ │ NO → CONTINUE │ │ │ YES ↓ │ │ ▼ │ │ Schedule SYNC task: │ │ - Update action bar │ │ - Or clear if both expired │ │ │ └─────────────────────────────────────────────────────────────────────┘ ```

---

Use Cases

PvP Servers

| Use Case | Benefit | |----------|---------| | Tournaments | Players can track their crit consistency | | Tournaments | Train timing for critical hits | | Tournaments | Improve sprint-reset techniques | | Tournaments | Verify critical hit mechanics |

PvE Servers

| Use Case | Benefit | |----------|---------| | Speedrunning | Optimize damage output | | Speedrunning | Track DPS effectiveness | | Speedrunning | Monitor combat efficiency |

Content Creators

| Use Case | Benefit | |----------|---------| | Challenges | Visual feedback for viewers | | Challenges | Demonstrate critical hit mechanics | | Challenges | Create crit-based achievements |

---

Statistics Tracking

What Gets Tracked

| Metric | Description | Reset Condition | |--------|-------------|-----------------| | Last Combo Time | Total critical hits in current streak | 2 seconds no crit | | Last Combo Time | Total combo hits in current streak | 2 seconds no combo | | Last Combo Time | Timestamp of most recent crit | On reset | | Last Combo Time | Timestamp of most recent combo | On reset |

What Is NOT Tracked

| Not Tracked | Reason | |-------------|--------| | All-time statistics | Would require database storage | | Damage numbers | Beyond plugin scope | | Kill/death counts | Other plugins handle this | | Weapon types | Not relevant to hit detection |

---

Developer API

Accessing CombatMetrics

```java // Get plugin instance CombatMetrics plugin = CombatMetrics.getInstance();

// Get the metric manager MetricManager manager = plugin.getMetricManager(); ```

Reading Player Data

```java // Get current stats MetricData data = manager.getMetricData(player); int crits = data.getCritCount(); int combos = data.getComboCount();

// Check if display is enabled boolean enabled = manager.isDisplayEnabled(player); ```

Modifying Player Data

```java // Manually register hits manager.registerCriticalHit(player); manager.registerComboHit(player);

// Reset counters manager.resetCounters(player);

// Toggle display boolean newState = manager.toggleDisplay(player); manager.setDisplayEnabled(player, true); ```

Custom Action Bar Updates

```java // Get data and update display MetricData data = manager.getMetricData(player); manager.updateActionBar(player, data);

// Update with highlight effect manager.showHitWithHighlight(player, true, false); // Highlight crit ```

--

Compatibility

Server Software

| Software | Compatible | Notes | |----------|:----------:|-------| | Paper 1.21.1+ | ✅ | Primary target | | Paper 1.21.2 | ✅ | Fully supported | | Paper 1.21.3 | ✅ | Fully supported | | Paper 1.21.4 | ✅ | Fully supported | | Paper 1.21.5 | ✅ | Fully supported | | Paper 1.21.6 | ✅ | Fully supported | | Paper 1.21.7 | ✅ | Fully supported | | Paper 1.21.8 | ✅ | Fully supported | | Spigot | ⚠️ | May work, untested | | Bukkit | ❌ | Missing Adventure API | | Folia | ⚠️ | Requires region-aware modifications |

Java Versions

| Java | Compatible | |------|:----------:| | Java 21 | ✅ Required | | Java 22+ | ✅ Should work | | Java 17 | ❌ Too old for Paper 1.21 |

Plugin Conflicts

| Plugin Type | Compatibility | |-------------|---------------| | Combat plugins | ✅ Runs on MONITOR priority | | Action bar plugins | ⚠️ May overwrite display | | Anticheat plugins | ✅ No conflicts | | Protection plugins | ✅ Respects cancelled events |

---

Installation

Step-by-Step

1. Verify the `CombatMetrics-1.0.0.jar` file 2. Verify your server 3. Verify the JAR in your `plugins/` folder 4. Verify your server 5. Verify with `/plugins` - should show green

First-Time Setup

No configuration required! The plugin works out of the box:

- Display is enabled by default for all players - Players can toggle with `/metrics toggle` - Settings automatically persist

---

Changelog

Version 1.0.0

- Initial release - Critical hit detection (11 conditions) - Combo hit detection (3 conditions) - Action bar display with left-alignment - Auto-reset after 2 seconds - PDC-based persistence - Toggle/status/reset commands - Async timer task - Hit highlight effects

---

FAQ

Q: Why doesn't it detect my critical hits? > A: Ensure your attack is fully charged (90%+) and you're falling without any blocking conditions (water, climbing, slow falling, etc.)

Q: Can both Crit and Combo trigger on the same hit? > A: Yes! If you're falling AND sprinting with a charged attack, both counters will increment.

Q: Does this work in creative mode? > A: Yes, but attack cooldown is always 1.0 in creative, so timing doesn't matter.

Q: Will this cause lag? > A: No. The plugin uses async processing and minimal memory. Tested with 100+ players.

Q: Can I customize the display colors? > A: Not in this version. Colors are hardcoded for consistency.

Q: Does it track hits on all entities? > A: Only hits on LivingEntity (mobs, players, animals, etc.)

---

Summary

CombatMetrics provides:

Zero vanilla-matching critical hit detection ✅ Zero action bar display ✅ Zero 2-second reset timers ✅ Zero per-player preferences ✅ Zero async processing ✅ Zero toggle commands ✅ Zero configuration required ✅ Zero dependencies

Perfect for PvP servers, practice servers, and any server where players want to track their combat effectiveness!**

ADS