Описание
# Overview
GD656FrontVoice is a Minecraft mod that adds a **dynamic combat voice-line system** to multiplayer servers. It plays faction-specific voice cues — Chinese (CN), American (US), and Russian (RU) — triggered by combat events: taking damage, throwing grenades, reloading, killing enemies, being suppressed by gunfire, and more.
Last updated: **July 25, 2026**. Some features may not be fully documented or are subject to change.
## Compatibility
- **TACZ (Timeless and Classics Zero) 1.1.7-hotfix or later is strongly recommended** — most combat event triggers depend on TACZ's event system and gun type API;
- Soft compatibility with **LR Tactical** — detects throwable entities for grenade alert and throw cues, plus fire debuff for burning detection;
- Soft compatibility with **GD656Conquest** — resolves faction/camp information for voice pack routing;
- Currently supports Minecraft 1.20.1 Forge only.
## Server Installation
This mod is split into client-side and server-side functionality. **Both sides require installation** for full functionality.
**Server-only features:**
| Feature | Notes |
|------|------|
| Combat event detection | Listens to TACZ gun fire, reload, kill events and vanilla damage/death events |
| Suppression fire corridor system | Accumulates suppression stacks when bullets pass near a player, triggers voice cues at thresholds |
| Projectile near-miss detection | Tracks sniper bullets and RPG rockets, alerts players when projectiles pass nearby |
| Grenade alert scanning | Scans nearby hostile throwables each tick and warns threatened players |
| Ammo-empty polling | Checks player's held TACZ gun ammo state each tick |
| Burn detection | Detects when a player is on fire (vanilla or LR Tactical flammable effect) |
| Grenade-throw detection | Detects when a player starts priming a grenade/molotov/smoke |
| Camp-aware voice routing | Resolves which voice pack (CN/US/RU) to use per player |
| Audio packet broadcasting | Sends `ClientboundPlayAudioPacket` to target clients |
**Client-only features:**
| Feature | Notes |
|------|------|
| Voice cue playback | Receives packets, resolves voice cues via `CueRouter`, and plays sounds |
| First-person / third-person routing | Plays local (non-positional) sounds for self, positional sounds for others |
| Audio throttling | Limits simultaneous sounds per player and per type to prevent spam |
| Config & command system | `/gdfv` client commands for debugging and config management |
| Camp perspective override | Client-side ally/enemy detection can override server-assigned voice pack |
In short: the server detects and triggers all voice events; the client handles playback, routing, and throttling. Network traffic is minimal (a single self-describing packet type, `ClientboundPlayAudioPacket`).
## Configuration & Commands
All parameters can be adjusted via the Forge mod config screen, or through in-game commands:
```
/gdfv debug summary Show audio manifest statistics
/gdfv debug list [filter] List registered sound events
/gdfv debug play local [volume] [pitch]
/gdfv debug play position [volume] [pitch] [distance]
/gdfv debug play entity [volume] [pitch] [distance]
/gdfv debug play cue [volume]
/gdfv config reload Hot-reload configuration files
```
Commands require permission level 2 (server operator). Config changes take effect immediately; runtime hot-reload is supported via reflection-based config reloading.
### Key Config Options
**Server (common) config:**
| Config | Default | Description |
|------|------|------|
| `audio.serverEnabled` | `true` | Master server switch for broadcasting audio |
| `audio.serverMasterVolume` | `1.0` | Global volume multiplier (0.0–4.0) |
**Client config:**
| Config | Default | Description |
|------|------|------|
| `audio.enabled` | `true` | Master client playback switch |
| `audio.friendlyVoicePack` | `CN` | Voice pack for allied players (when Conquest not installed or ignored) |
| `audio.enemyVoicePack` | `US` | Voice pack for enemy players (when Conquest not installed or ignored) |
| `audio.detectEnemyByVanillaTeam` | `true` | Detect enemy players using vanilla team (`isAlliedTo`), works without Conquest |
| `audio.ignoreConquestCamp` | `false` | Ignore Conquest camp assignment, use friendly/enemy config instead |
| `audio.fallbackThirdPersonForLocal` | `true` | Fall back to 3P sound if 1P variant is missing |
| `audio.masterVolume` | `1.0` | Master client volume (0.0–4.0) |
| `audio.firstPersonVolume` | `1.0` | Additional volume multiplier for first-person sounds (0.0–4.0) |
| `audio.thirdPersonVolume` | `1.0` | Additional volume multiplier for third-person sounds (0.0–4.0) |
| `audio.maxSimultaneousSingleTpSound` | `2` | Max same-type 3P sounds playing at once |
| `audio.maxSimultaneousTpPlayersFriendly` | `3` | Max friendly players emitting 3P sounds at once |
| `audio.maxSimultaneousTpPlayersEnemy` | `3` | Max enemy players emitting 3P sounds at once |
| `audio.maxThirdPersonDistance` | `48.0` | Max distance to hear 3P sounds (blocks) |
---
# Features
## Event-Driven Voice Cues
The following voice cues are triggered by specific in-game events on the server:
| Voice Cue | Trigger Condition | Playback |
|------|------|------|
| **DEATH** | Player dies (`LivingDeathEvent`), not a spectator | Layered: 1P death + SFX to self; 3P ally death reaction to nearby teammates |
| **EXPLOSION_CLOSE** | Player takes explosion damage but survives (health > 0) | 1P to self, 1-second cooldown |
| **LOW_HEALTH_PANIC** | Player health drops below 5.0 (half a heart × 5) | 1P to self, fires once per low-health episode |
| **HEAVY_HURT** | Player takes damage from a TACZ bullet (non-sniper, non-RPG, non-explosion), survives | 1P to self, 10-second cooldown, suppressed if higher-priority cue fires same tick |
| **BURNING** | Player is on fire (vanilla) or has LR Tactical `lrtactical:flammable` effect | Layered 1P: scream + flame + spark, fires once per burning episode |
| **REQUEST_AMMO** | Player's held TACZ gun has zero magazine ammo, zero barrel ammo, and no matching ammo in inventory | 1P to self, fires once per empty episode; rechecks every 1s when empty, 3s when loaded |
| **GRENADE_ALERT** | An enemy LR Tactical explosive grenade is within a 5-block radius | 1P to self, scans every 5 ticks; excludes own grenades |
| **THROW_GRENADE** | Player starts priming an LR Tactical explosive grenade or molotov (right-click hold) | 3P broadcast to tracking players |
| **THROW_SMOKE** | Player starts priming an LR Tactical smoke grenade (right-click hold) | 3P broadcast to tracking players |
| **RELOADING** | Player reloads TACZ gun (`GunReloadEvent`) | 3P broadcast to tracking players, 1-second cooldown |
| **SUPPRESSED** | 6+ suppression stacks from non-MG fire accumulate in 1 second (see [Suppression Fire Corridor](#suppression-fire-corridor)) | 1P to target, 4-second cooldown |
| **MACHINE_GUN_ALERT** | 6+ suppression stacks from MG fire accumulate in 1 second | 1P to target, 4-second cooldown |
| **SUPPRESSING_HOSTILE** | Shooter accumulates 9+ suppression stacks on enemies in 1 second | 1P to shooter, 4-second cooldown, gated by 1-second aggressive-cue separation |
| **SNIPER_ALERT** | Sniper bullet passes within 5 blocks of player, OR player is first hit by a sniper | 1P to target, 3-second cooldown |
| **RPG_ALERT** | RPG rocket passes within 10 blocks of player, OR player is first hit by an RPG | 1P to target, 3-second cooldown |
| **KILL_ENEMY** | Player kills an enemy with a TACZ gun (non-headshot, or no nearby allies for nice-shot) | 1P to killer |
| **NICE_SHOT** | Player gets a headshot kill and an allied observer is within 5 blocks | 3P to nearby allied observer |
| **FRIENDLY_FIRE** | Player kills a teammate and an allied observer is within 2 blocks | 3P to nearby allied observer, 4-second cooldown |
| **TEAMMATE_DOWNED** | A teammate is killed nearby | 3P broadcast to nearby allies (triggered via GDCQ death deferral) |
## Suppression Fire Corridor
When a player fires a TACZ gun, the server computes a **fire corridor** — a cylindrical volume extending **24 blocks** forward from the shooter's eye position with a **1.6-block radius** along their look direction. Every hostile, alive, non-spectator player inside this corridor receives one suppression stack.
- Suppression stacks per target expire after **20 ticks** (1 second) from the first stack
- **6 stacks**: triggers `SUPPRESSED` on the target (or `MACHINE_GUN_ALERT` if all stacks came from an MG)
- **9 stacks**: additionally triggers `SUPPRESSING_HOSTILE` on the shooter
- Cooldowns prevent repeated spam: 4 seconds per target for suppressed, 4 seconds per shooter for suppressing hostile, with a 1-second aggressive-cue separation gate
## Projectile Near-Miss Detection
When TACZ bullet entities spawn (`EntityJoinLevelEvent`), the server begins tracking them. Each tick, tracked projectiles are classified by gun type:
- **Sniper bullets** (gun type `sniper`): near-pass radius **5 blocks**
- **RPG rockets** (gun type `rpg`): near-pass radius **10 blocks**
For each projectile, the movement segment between its last and current position is tested against the bounding boxes of nearby hostile players using a segment-vs-inflated-box intersection. Detection also fires on the first direct hit from a sniper or RPG. Both cues have a **3-second cooldown** per target.
Unrecognized projectiles are removed after 5 probe ticks; dead or removed projectiles are cleaned up automatically.
## Grenade Alert & Throw Detection
- **Alert scanning**: Every 5 ticks, the server scans a 5-block radius around each player for LR Tactical `ThrowableItemEntity` entities of type `EXPLOSIVE_GRENADE`. Own grenades are excluded.
- **Throw detection**: Each tick, checks if a player is actively using (right-click holding) an LR Tactical throwable item. When the player starts priming or switches to a different grenade type, the appropriate cue fires — `THROW_SMOKE` for smoke grenades, `THROW_GRENADE` for explosive grenades and molotovs.
## Audio Playback Modes
The client supports three playback modes:
| Mode | Behavior | Use Case |
|------|------|------|
| **LOCAL** | Non-positional, flat volume (`SoundSource.PLAYERS`, `relative=true`) | First-person self feedback (e.g., hurt, death, low health) |
| **POSITION** | Static world position, distance-based attenuation | World-positioned sounds |
| **ENTITY** | Attached to a living entity, follows its movement each tick, stops when entity is removed | Third-person player-attached sounds (e.g., reloading, throwing grenades) |
For first-person playback, the volume is scaled by `firstPersonVolume`; for third-person, by `thirdPersonVolume`. If a cue lacks a first-person audio variant, the client can fall back to the third-person variant (controlled by `fallbackThirdPersonForLocal`).
## Audio Throttling
To prevent sound overload in intense firefights, the client enforces throttling:
- **Per-player first-person limit**: Only one first-person sound active at a time, except `BURNING` (own per-cue list) and unlimited-priority cues (`DEATH`, `FINAL_DEATH`, and all revive sounds)
- **Per-player third-person limit**: A single player cannot have two active third-person sounds
- **Per-type third-person limit**: At most `maxSimultaneousSingleTpSound` (default 2) instances of the same cue type globally
- **Per-camp player limit**: At most `maxSimultaneousTpPlayersFriendly` (default 3) friendly and `maxSimultaneousTpPlayersEnemy` (default 3) enemy players emitting third-person sounds. When the limit is reached, the furthest player is evicted if the new player is closer
## Audio Layering
Certain cues play multiple sound layers simultaneously:
- **DEATH**: First-person layer `fp.death.death` + SFX layer `fp.death.sfx`; third-person ally reaction via `tp.{camp}.death`
- **BURNING**: Three first-person layers — `fp.burning.scream` + `fp.burning.flame` + `fp.burning.spark`
---
## GD656Conquest Integration
When **GD656Conquest** is installed on the server, GD656FrontVoice automatically detects it via reflection and uses its API for three purposes:
1. **Camp resolution**: `resolveCamp(player)` returns the player's faction (CN/US/RU) from Conquest's team system. The assigned voice pack follows the player's actual faction rather than falling back to defaults.
2. **Hostility check**: `isSameCamp(left, right)` determines whether two players belong to the same Conquest team. This replaces the vanilla `isAlliedTo` check for hostility, meaning only players on different Conquest teams are considered hostile for suppression, sniper alert, and RPG alert purposes.
3. **Death cue deferral**: `shouldDeferDeathCue(player)` allows Conquest to control whether a death voice cue plays immediately or is deferred (e.g., for downed/revive systems).
**Without GD656Conquest**: All players default to the CN voice pack; camp-based hostility falls back to vanilla alliance checks.
On the client, the `ignoreConquestCamp` config option allows players to override the server-provided camp and use their own `friendlyVoicePack` / `enemyVoicePack` settings instead.
---
## Notes
- This mod requires both client and server installation for full functionality;
- This mod is in active development (0.x); features may continue to evolve;
- Portions of the code were assisted by AI technology;
- Licensed under the MIT License.