Integrations
Everything in settings.yml that talks to something other than Ecstacy: clients, Discord, and the
two systems that make the server look like it runs a different anticheat.
Client brand detection
client-brand:
notify: true
kick: true
blacklist:
- Impact
- Wurst
- LiquidBounce
- Aristois
- Sigma
- Vape
kick-message: "&cThis client is not allowed on this server."| Key | Default | Meaning |
|---|---|---|
notify |
true |
Tell staff when a player joins with a detected client |
kick |
true |
Kick players on the blacklist automatically |
blacklist |
six entries | Client brands, case-insensitive |
kick-message |
n/a | Shown to the kicked player |
Note
Brand is what the client reports about itself. A cheat client that lies about its brand will not appear here. This catches the ones that do not bother, which is more of them than you would expect, but it is a filter and not a detection.
Lunar, Badlion and Feather
Ecstacy can disable specific mods for players on these clients through each client's own API.
lunar:
enabled: true
disabled-mods:
- Freelook
- Minimap
- Waypoints
- Zoom
badlion:
enabled: true
disabled-mods:
- Freelook
- Minimap
- Waypoints
- Zoom
feather:
enabled: true
disabled-mods:
- perspective
- autoperspective
- waypoints
- zoomLunar and Badlion take the mod names as shown in their own menus. Feather uses slug names from the
Feather API documentation. Note the lowercase, and that perspective and autoperspective are
Feather's names for freelook.
Discord. Use webhooks.yml
Warning
There are two Discord configurations in the plugin folder and only one of them works. The
discord: section of settings.yml is inert in the current build. Nothing reads it. Put your
webhook in webhooks.yml. Filling in settings.yml produces no messages and no error.
webhooks.yml gives three independent webhooks, each with its own URL, bot name, avatar and
embed colour, rather than one URL with event toggles.
webhooks:
enabled: true
timeout_ms: 5000
retry_attempts: 2
violation:
enabled: true
url: "https://discord.com/api/webhooks/…"
username: "Ecstacy"
color: 16733525
filters:
checks: [] # empty = every check
min_flags: 1 # post from the first flag
punishment:
enabled: true
url: "https://discord.com/api/webhooks/…"
reputation:
enabled: true
url: "https://discord.com/api/webhooks/…"
bad_below: 30| Webhook | Fires on | Embed contains |
|---|---|---|
violation |
Every flag | Player, check, type, VL (vl/maxVl), info |
punishment |
A punishment being applied | Player, check, type, reason |
reputation |
A player joining with reputation at or below bad_below |
Player and score |
violation.filters narrows the noise without touching detection: checks limits which checks
post (empty means all), min_flags sets how many flags a player needs before anything is posted.
Sends run on virtual threads, so a slow or dead webhook never blocks the main thread.
Create the webhook URL under Server Settings → Integrations → Webhooks in Discord.
Caution
A webhook URL is a credential. Anyone holding it can post to that channel as your bot. Do not
commit webhooks.yml to a public repository with a live URL in it.
Spoofer
Registers fake anticheat commands so a cheater probing for what the server runs gets an answer that is not the truth.
spoofer:
enabled: true
type:
- "GRIM"
- "VULCAN"Valid values: GRIM, VULCAN, NONE.
Mimic
A configurable version of the same idea: you define the commands, the responses, and where the
version number comes from. It is independent of spoofer and both can run together.
mimic:
enabled: false
commands:
- name: "grim"
aliases: []
version-source: "GITHUB"
version-repo: "GrimAnticheat/Grim"
version-url: ""
static-version: "2.3.72"
response-format: "&bGrim &8» &fThis server is running GrimAC v{version}"
subcommands:
- name: "alerts"
response: "&bGrim &8» &fAlerts are now toggled"
patterns: []| Key | Meaning |
|---|---|
version-source |
GITHUB, MCMARKET, SPIGOT or STATIC |
version-repo |
For GITHUB: owner/repo |
version-url |
For MCMARKET and SPIGOT: the full resource page URL |
static-version |
Used when the source is STATIC, and as the fallback when a fetch fails |
response-format |
{version} is substituted |
subcommands |
Each with its own fixed response |
patterns defines transaction patterns from config instead of implementing the
TransactionPattern interface:
mimic:
patterns:
- name: "example-logger"
type: "BOTH" # PRE, POST or BOTH
condition: "always"
action: "log" # log | broadcast | command:<cmd>command: actions accept {player}, {uuid} and {time}.
Addons can hook the fake commands through EcstacyFakeCommandEvent and the transaction pipeline
through the TransactionPattern interface. See the developer API.
Bait
bait:
enabled: falsePassive NPC bait, detection-only and off by default. Experimental.
When an integration is not working
Work down this table before changing configuration. Most reports turn out to be the first row.
| Symptom | Check first |
|---|---|
| A client integration does nothing | The client's own API plugin is installed and loaded. Ecstacy softdepends on them, so a missing one is silent |
| Mod control has no effect on some players | Those players are not on that client. A vanilla or third-party client reports a brand and nothing else |
| Discord webhook posts nothing | The URL, and whether the event type is enabled. A webhook Discord has revoked also fails silently |
| Discord posts stop after working | Discord rate-limits webhooks. High-volume servers should raise fail.alert.every rather than the webhook rate |
| The brand blacklist catches nobody | Brands are self-reported and trivially changed. It is a filter for lazy clients, not a detection |
| The spoofer replies to nothing | It only answers the commands it implements. mimic is the configurable version |
mimic shows the wrong version |
The remote fetch failed and it fell back to static-version. Set that to something plausible |
Note
Everything under spoofer and mimic is theatre by design. It makes the server look like it
runs a different anticheat. It detects nothing on its own and no flag ever comes from it. Treat
it as deterrence, and do not let a convincing fake reply become the reason you skipped a real
check.
What integrations are and are not for
Client integrations control what a player's client is allowed to load. That is a different job from detection and the two do not overlap:
- Blocking a mod through Lunar, Badlion or Feather relies on the client cooperating. Those clients do cooperate. That is the point of their APIs. But a player who leaves for a client without an API simply is not covered.
- The brand blacklist reads what the client says it is. Any cheat client that cares will report
vanilla. - Neither of these produces a violation, a VL or a punishment. If you want a player detected rather than restricted, that is the checks, not this page.
The practical combination on a competitive server is: mod control through the client APIs to keep honest players honest, brand blacklist to catch the careless, and the detection families for everyone else.
Order of operations
When you are setting integrations up for the first time:
- Install the client API plugins you intend to use, and restart. Confirm they are loaded before configuring anything in Ecstacy.
- Enable one integration, restart, and verify with a real account on that client. Mod control fails quietly when the client-side half is missing, so testing from the server console proves nothing.
- Add the Discord webhook once flags are actually being produced, so you can see the volume you are signing up for.
- Leave
spooferandmimicuntil last. They change nothing about protection and are the easiest thing to misread as broken while a real problem sits elsewhere.