promotional bannermobile promotional banner

Combat Toggle

Combat Toggle is a lightweight server-side PvP control mod that prevents accidental or unwanted player combat by requiring mutual opt-in before PvP damage is allowed. Combat only activates when both players are in Combat mode.

File Details

Combat Toggle 1.2.0 (Forge 1.19.2)

  • R
  • May 8, 2026
  • 53.50 KB
  • 4.8K
  • 1.19.2
  • Forge

File Name

combattoggle-1.2.0.jar

Supported Versions

  • 1.19.2

Curse Maven Snippet

Forge

implementation fg.deobf("curse.maven:combat-toggle-1447882:8058931")
Curse Maven does not yet support mods that have disabled 3rd party sharing

Learn more about Curse Maven

[1.2.0] - 2026-05-08

The 1.19.2 line's first server-installable release. Vanilla clients can now join modded servers running Combat Toggle and use /ct without installing anything client-side. Internal architecture rewritten around a Forge capability and a hybrid common/server/client package layout. Breaking for the 1.1.x persistent-timer schema (mode preserved; tags and cooldowns reset on first login).

Server-installable, vanilla-client-tolerant

  • mods.toml now declares displayTest = "IGNORE_SERVER_VERSION". Vanilla clients no longer see the red ❌ in the multiplayer list when targeting a modded server.
  • The network channel uses NetworkRegistry.acceptMissingOr(PROTOCOL::equals). Vanilla clients pass the handshake; the channel quietly drops S2C packets to peers without it registered.
  • Player commands are the new baseline UX for vanilla-client users:
    • /ct toggles
    • /combat and /peace set explicitly
    • /combattoggle status and /combattoggle help view + discover

PvP enforcement hardening

  • Primary cancel moved from LivingHurtEvent to LivingAttackEvent (HIGH priority). Stops the hurt pipeline before knockback, hurt sound, and the PLAYER_HURT_ENTITY advancement criterion fire — no more free knockback shots on Peace targets. LivingHurtEvent remains as defence-in-depth and clears residual deltaMovement + hurtMarked.
  • Attacker resolution walks the standard ownership chain: direct hit → projectile owner → primed-TNT owner → tamed pet (OwnableEntity). Wolves, snow golems, ignited TNT are now correctly gated by Combat Toggle.

Capability-backed state

  • CombatToggleData is now a Forge capability attached to every Player. CombatToggleData.get(player) returns the same in-memory instance for the lifetime of that player — no per-call NBT alloc, no async-mutation races.
  • Time-based fields migrated from wall-clock millis to game ticks (level.getGameTime()). Monotonic, persisted, restart-safe.
  • Clone-on-respawn copies state via PlayerEvent.Clone with the standard reviveCaps / invalidateCaps dance.

One-shot legacy NBT migration

  • On first 1.2.0 login, the pre-1.2.0 combat_toggle compound on player.getPersistentData() is read. The enabled flag is preserved into the new capability; the wall-clock-millis timestamps (lastToggleMs, combatTagUntilMs, lastPvpMs) are dropped — they cannot be safely interpreted against the new game-tick clock. The legacy compound is removed after migration. Logged once per player as Migrated legacy combat_toggle data for {name} (preserved mode={MODE}, dropped expired timers).

Configurable HUD position

New client-config keys in combattoggle-client.toml:

Key Default Notes
hudEnabled true Master switch
hudShowInCombatMode true Hide while in Combat
hudShowInPeaceMode true Hide while in Peace
hudAnchor TOP_CENTER 9-anchor + CUSTOM (absolute screen coords)
hudOffsetX 0 Inward pixel offset from anchor
hudOffsetY 6 Inward pixel offset from anchor
hudScale 1.0 0.5 – 3.0
hudShowTimers true Tag + cooldown countdown text

The 1.1.0 server config key showHud is dropped — HUD visibility is purely client-side now. Operator configs keep the orphan key on first read with a Forge unused-key warning; harmless.

Architecture

Source split into three packages:

  • common/ — config spec, capability state + registration, network packets. No client-class imports; loadable on dedicated server.
  • server/ — gameplay logic (commands, lifecycle events, PvP enforcement, scoreboard teams). Loaded on every logical server (dedicated and integrated). Zero net.minecraft.client.* references.
  • client/ — HUD overlay, keybind, client-side cache. Every subscriber gated with @Mod.EventBusSubscriber(value = Dist.CLIENT) so dedicated server never classloads them.

Network

  • Protocol version "1" (1.2.x line). 1.1.x modded clients are cleanly handshake-rejected; vanilla clients pass through acceptMissing.
  • Wire format for S2CSyncStatePacket: boolean | varInt seconds | varInt seconds. ~5 bytes total.
  • C2SRequestTogglePacket carries no payload — the server identifies the requester via ctx.getSender().