Skip to content
impossiblesmc-devPublic

About

Detects client mods on Paper by asking the client to translate something only that mod can translate. Sign translation-key probing over PacketEvents.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ModProbe

Detects client mods on a Paper server by asking the client to translate something only that mod can translate.

Paper 1.21.11, Java 21, PacketEvents. No NMS, no world edits, no database.

How it works

A sign line is a chat component, and a translate component carries a fallback the client renders when it has no entry for that key. So a sign whose lines are translate components keyed to a mod's language entries reads back as the fallback on vanilla, and as the mod's own wording on a client that ships those entries. The client hands the rendered lines straight back in UPDATE_SIGN, which is the whole detection.

The sequence per probe:

  1. BLOCK_CHANGE turns a block below the player into a sign, for that client only.
  2. BLOCK_ENTITY_DATA sets its four lines to translate components.
  3. OPEN_SIGN_EDITOR then CLOSE_WINDOW, so the client renders the lines without the editor reaching the screen.
  4. The client replies with UPDATE_SIGN. Any line that is not the fallback names a mod that is present.
  5. BLOCK_CHANGE puts the original block back.

Nothing is placed in the world. The block is only ever changed for one client, and the state captured before the swap is what gets restored.

Four keys per probe

A sign has four lines, so each round trip tests four mods rather than one. Sixteen targets cost four probes. The batching is in ProbeSettings.batches().

Configuration

fallback: "mp0"

targets:
  "Meteor": "key.meteor-client.open-gui"
  "Freecam": "key.freecam.toggle"

start-delay-ticks: 20
response-timeout-ticks: 100
probe-depth: 5
sign-block: "minecraft:oak_sign"

on-detect:
  type: message
  content:
    - "<red>ModProbe: <white>%mod%<red> is not allowed here."

on-timeout:
  type: none
  content: []

type is none, message, kick or command. Content is MiniMessage, with %mod% and %player% replaced.

Finding translation keys

Open the mod's jar, read assets/<modid>/lang/en_us.json, and pick a key the mod is certain to ship and unlikely to share with anything else. Keybind and config-screen titles are good choices. A key that vanilla also defines will match everyone, so check it is not in the vanilla language file.

A timeout is not a detection

If the client never replies, the verdict is inconclusive and on-timeout defaults to doing nothing. A silent client is a loading or lagging client far more often than a modded one, and a check that punishes a bad connection is worse than no check.

Two other things the probe cannot tell you: a mod that ships no language entry for the key you chose is invisible to it, and a client can lie about what it renders. Treat a hit as evidence, not proof.

Build

Needs JDK 21 or newer.

mvn package

Output is target/ModProbe-1.0.0.jar. Compiles at -Xlint:all -Werror.

Drop it in plugins/ alongside PacketEvents.

Where it breaks first

Symptom Cause
Every player flagged for one mod The key is also defined by vanilla or by a resource pack
Nobody ever flagged The mod ships no entry for that key, or the key is misspelled
Everyone inconclusive start-delay-ticks is too low and clients are still loading
Warning about the sign block on boot sign-block is not a valid state string for this server version
Phantom sign under a player A probe was interrupted before the restore; it clears on relog or chunk reload

Licence

MIT. A derivative of the technique shown by AppleModDetector, also MIT.

About

Detects client mods on Paper by asking the client to translate something only that mod can translate. Sign translation-key probing over PacketEvents.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages