PreventPotions
Turns potions off. Drinking, splash and lingering potions, and tipped arrows are blocked by default. Beacon effects and /effect can be switched off too. Each one is its own toggle, so you can ban splash potions and nothing else, for example.
Paper, Folia and Fabric, from 1.21.1 to 26.3.
What it blocks
| Rule | Default | Short version |
drink | on | Potions can't be drunk. |
splash | on | Splash potions can't be thrown. |
lingering | on | Lingering potions can't be thrown. |
tipped_arrows | on | Tipped arrows can't be fired, and get cleaned out of inventories. |
beacon | off | Beacons don't give players effects. |
commands | off | /effect doesn't work on players. |
The details, including where Paper and Fabric differ, are on What each rule does.
Features
- Nothing gets wasted. A blocked drink, throw or shot leaves the item where it was.
- A pause button.
/preventpotions toggle turns all blocking off for an event, then back on.
- Folia support. Every check runs on the thread that owns the player or item involved.
- Fabric build with the same rules and messages.
Install
Requirements
| Platform | Versions | Jar |
| Paper (and forks) | 1.21.1 – 26.3 | PreventPotions-paper-<version>.jar |
| Folia | 1.21.4 – 26.3 | Same jar as Paper |
| Fabric | 1.21.11 | PreventPotions-fabric-1.21.11-<version>.jar + Fabric API |
| Fabric | 26.3 | PreventPotions-fabric-26.3-<version>.jar + Fabric API |
Java 21 for 1.21.x, Java 25 for 26.x. Spigot isn't supported. The Paper jar is a Paper plugin (paper-plugin.yml), so it needs Paper or a fork.
Paper and Folia
- Put the Paper jar in
plugins/.
- Start the server.
plugins/PreventPotions/config.yml is created.
- Edit it and run
/preventpotions reload.
Fabric
- Install Fabric API.
- Put the jar for your exact Minecraft version in
mods/.
- Start the server. Settings are in
config/preventpotions.json.
The Fabric build only needs to be on the server. Players can join with a vanilla client.
Updating from 1.1
Swap the jar and restart. Your config carries over unchanged. One thing to know: /preventpotions now needs preventpotions.admin. In 1.1 anyone could run it, which meant any player could turn potion blocking off.
config.yml
Paper and Folia. plugins/PreventPotions/config.yml, applied with /preventpotions reload.
prevent
| Key | Default | Meaning |
drink | true | Block drinking. |
splash | true | Block throwing splash potions. |
lingering | true | Block throwing lingering potions. |
tipped_arrows | true | Block tipped arrows, everywhere they can turn up. |
beacon | false | Block beacon effects on players. |
commands | false | Block /effect on players. |
A missing key counts as false.
messages
One per rule, same names, sent to the player when that rule stops them. & colour codes. A missing message falls back to the default text.
Full default file
prevent:
drink: true
splash: true
lingering: true
tipped_arrows: true
beacon: false
commands: false
messages:
drink: "&cYou cannot drink potions on this server!"
splash: "&cSplash potions are disabled!"
lingering: "&cLingering potions are disabled!"
tipped_arrows: "&cTipped arrows are not allowed!"
beacon: "&cBeacon effects are disabled!"
commands: "&cPotion effects via commands are disabled!"
What each rule does
drink
Drinking is cancelled before it finishes. The potion stays in the hand and the player gets the message. Water bottles are potions too, as far as Minecraft is concerned, so they can't be drunk either. Pouring one on dirt to make mud still works, because that's using the bottle on a block rather than drinking it.
splash and lingering
The throw is cancelled and the potion stays in the inventory. On Paper and Folia the rule covers every thrower, not just players: dispensers can't fire blocked potions, and neither can witches. On Fabric only players are stopped.
tipped_arrows
The biggest one, since tipped arrows can arrive from so many places.
| Situation | Paper / Folia | Fabric |
| Firing a bow or crossbow | Tipped arrows are skipped when the bow picks ammo. With normal arrows in the inventory the bow fires those instead. With none, it won't draw. | The shot is refused and the arrow stays. |
| Crafting | The crafting grid shows no result. | Can be crafted, but is removed from the inventory within a second. |
| Villager trades | Villagers won't pick up new tipped-arrow trades. Ones they already had are still offered, but the arrows get deleted when clicked. | Removed from the inventory within a second. |
| Picking up from the ground | Blocked, for mobs too. | Blocked for players. |
| Clicking one in any inventory | The arrow is deleted. | Removed within a second anyway. |
| Already in the inventory on join | Removed. | Removed. |
Given by /give, loot, other plugins | Removed the first time it's clicked. | Removed within a second. |
Unlike the potion rules, this one destroys items. A tipped arrow that gets removed is gone, not returned. That's intended: it keeps them out of circulation altogether.
beacon
Beacons still work for everything except players. They hand out effects every few seconds, so with this on, players near a beacon see the message each time it tries. If that's too noisy, set messages.beacon to "".
commands
/effect give targeting a player does nothing to them, and the player gets the message. Mobs are unaffected. On Fabric, the command reports the player as a failed target, the same way vanilla reports a player who's immune.
Potions, beacons and commands are separate rules. Blocking commands doesn't block drinking, and the other way round.
Fabric config
config/preventpotions.json. Same keys as the YAML, in two maps. Rewritten on load, so keys added in newer versions appear in old files. Applied with /preventpotions reload.
{
"prevent": {
"drink": true,
"splash": true,
"lingering": true,
"tipped_arrows": true,
"beacon": false,
"commands": false
},
"messages": {
"drink": "&cYou cannot drink potions on this server!",
"splash": "&cSplash potions are disabled!",
"lingering": "&cLingering potions are disabled!",
"tipped_arrows": "&cTipped arrows are not allowed!",
"beacon": "&cBeacon effects are disabled!",
"commands": "&cPotion effects via commands are disabled!"
}
}
If the file doesn't parse, the server refuses to start and names the file, rather than quietly running with defaults. A /preventpotions reload with a broken file keeps the old settings and tells you why.
Commands
Reference
| Command | Permission | What it does |
/preventpotions reload | preventpotions.admin | Reloads the config. |
/preventpotions toggle | preventpotions.admin | Turns all blocking off, or back on. |
Toggle
Toggle is a server-wide pause. Every rule stops at once, without touching the config. It isn't saved: after a restart, blocking is on again. Handy for an event night where potions are allowed, as long as you remember to flip it back. Or just restart.
Permissions
All permissions
| Permission | Default | What it allows |
preventpotions.admin | op | /preventpotions reload and toggle. |
There's no bypass permission. The rules apply to everyone, ops included. On Fabric, without a permissions mod, preventpotions.admin falls back to permission level 2.
Paper events
There's no Java API. If you're writing a plugin that needs to get along with PreventPotions, this is what it listens to. Handlers marked “skips cancelled” ignore events another plugin already cancelled.
Listeners
| Event | Priority | Rule | Action |
PlayerItemConsumeEvent | normal, skips cancelled | drink | Cancels when the item is a potion |
PlayerLaunchProjectileEvent | normal, skips cancelled | splash, lingering | Cancels and keeps the item |
ProjectileLaunchEvent | normal, skips cancelled | splash, lingering | Cancels potions not thrown by a player (dispensers, witches) |
PlayerReadyArrowEvent | normal, skips cancelled | tipped_arrows | Cancels, so the bow skips that arrow |
PrepareItemCraftEvent | normal | tipped_arrows | Clears the result |
VillagerAcquireTradeEvent | normal, skips cancelled | tipped_arrows | Cancels the new trade |
EntityPickupItemEvent | normal, skips cancelled | tipped_arrows | Cancels |
InventoryClickEvent | low, skips cancelled | tipped_arrows | Cancels and deletes the clicked arrow |
PlayerJoinEvent | normal | tipped_arrows | Removes tipped arrows from the inventory |
EntityPotionEffectEvent | normal, skips cancelled | beacon, commands | Cancels for players when the cause is BEACON or COMMAND |
Working around it
To let something through in one case, say a custom potion from your plugin, cancel nothing and instead listen at HIGH or HIGHEST and un-cancel the event under your own conditions. PreventPotions runs at normal priority and never checks again afterwards.
@EventHandler(priority = EventPriority.HIGH)
public void allowSpecialPotion(PlayerItemConsumeEvent event) {
if (isMySpecialPotion(event.getItem())) {
event.setCancelled(false);
}
}
That works for every event in the table except PrepareItemCraftEvent and PlayerJoinEvent, which change items directly instead of cancelling, and the arrow-deleting click, which removes the item before you could undo it.
Threads
Each handler runs on the thread that owns the entity or inventory involved. On Folia that's the region thread. Settings are read from a read-only snapshot that's swapped on reload, so handlers never see a half-loaded config.
Fabric internals
Fabric has no events for most of this, so the Fabric build uses a few small mixins. If another mod changes the same vanilla methods, this is where to look.
Mixins
| Target | Injection | Rule |
BeaconBlockEntity.applyEffects | @WrapOperation around Player.addEffect | beacon |
EffectCommands.giveEffect | @WrapOperation around LivingEntity.addEffect | commands |
ProjectileWeaponItem.draw | @Inject at HEAD, returns an empty list | tipped_arrows |
ItemEntity.playerTouch | @Inject at HEAD, cancels | tipped_arrows |
The wraps come from MixinExtras, which ships with Fabric Loader, so they chain cleanly with other mods wrapping the same call. The draw inject returns before any ammo is used, which is why a refused shot costs nothing.
Events
| Fabric API event | Used for |
UseItemCallback | drink, splash, lingering. Returns FAIL to refuse. |
ServerPlayConnectionEvents.JOIN | Clearing tipped arrows on join |
ServerTickEvents.END_SERVER_TICK | The once-a-second tipped-arrow sweep |
Checking the rules from another mod
me.eyman.PreventPotions.fabric.PotionRules is public:
// true when that rule is on and prevention isn't paused
boolean blocked = PotionRules.blocks(PotionRules.SPLASH);
// same, but also sends the player the configured message
if (PotionRules.deny(serverPlayer, PotionRules.DRINK)) {
return InteractionResult.FAIL;
}
Rule names: DRINK, SPLASH, LINGERING, TIPPED_ARROWS, BEACON, COMMANDS. Call them on the server thread. Treat it as handy rather than stable, though: it's public because the mixins need it, not because it was designed as an API, and it may change.
Building from source
JDK 21 and JDK 25 required.
cd PreventPotions
./gradlew buildAll
Jars go to build/dist/. paper/ is the plugin, fabric-shared/ holds the Fabric code and mixins, and fabric-1.21/ and fabric-26/ build it per Minecraft version. ./gradlew :paper:check also compiles against the newest Paper API.
FAQ
Can staff be allowed to use potions?
Not with a permission. There's no bypass. /preventpotions toggle turns everything off for everyone. For per-player exceptions you'd need a small plugin that un-cancels the events, see Paper events.
Why can't players drink water?
A water bottle is the potion item with no effect, so the drink rule covers it. Turn drink off if your players need water bottles. Making mud still works either way.
Players get spammed near beacons
Beacons re-apply their effect every few seconds, and each attempt sends the message. Set messages.beacon: "" to block silently.
Do mobs get blocked too?
Beacon and command blocking only affect players. Splash and lingering are different on Paper and Folia: they stop any thrower, so witches can't throw blocked potions either. On Fabric, witches are left alone. Tipped-arrow pickup is blocked for mobs too on Paper.
Does it affect potion effects from food, totems or other plugins?
No. Only the six rules above. A golden apple, a totem or a plugin calling addPotionEffect still works.
Troubleshooting
Common problems
| Problem | Try this |
| Nothing is blocked | Someone may have run /preventpotions toggle. Run it again, or restart. Also check the rule is true in the config. |
/preventpotions says unknown command or no permission | It needs preventpotions.admin. Ops have it by default. |
| Tipped arrows keep appearing on Fabric | They're removed within a second. Tipped arrows sitting in chests stay until someone takes them out. |
| A custom potion from another plugin is blocked | Expected. Rules go by item type. Ask that plugin's author to un-cancel the event for their item, see Paper events. |
| Server won't start on Fabric, config error | config/preventpotions.json isn't valid JSON. Fix it or delete it to get a fresh one. |
| Won't load on Folia | Needs 1.2.0 or newer. |
Known limits
- No bypass permission and no per-world settings.
- Toggle isn't saved across restarts.
- On Fabric, tipped arrows aren't stopped in the crafting grid, only cleaned out afterwards.
Support
Questions and bug reports go through the Discord.
Join the Discord
What to include in a report
- Server software and version (Paper, Folia, a fork, or Fabric)
- Your PreventPotions version
- Your
config.yml or preventpotions.json
- Exactly what the player did, and what happened
- The console log from start-up