Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ExplodeEvent and Improvement in Spigot Explode events #11840

Open
wants to merge 36 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
ccaf71f
Improvement Explosion events
Doc94 Dec 27, 2024
44bb708
Remove unused CraftBukkit imports in ServerExplosion
Doc94 Dec 27, 2024
123e6aa
[ci skip] ups with test paper plugin...
Doc94 Dec 27, 2024
cf2f8e4
Create Paper ExplodeEvent and minor changes in CB events
Doc94 Dec 30, 2024
a0379b4
ReWork in ServerExplosion for new paper explode event
Doc94 Dec 30, 2024
da47576
[ci skip] Mark the Spigot explode event obsolete
Doc94 Dec 30, 2024
cd3a15e
Call the paper event
Doc94 Dec 30, 2024
bf03569
Remove block from explosion
Doc94 Dec 30, 2024
8b85170
[ci skip] Modify ExplodeEvent#blockList() for mention mutability
Doc94 Dec 31, 2024
f30c1f4
[ci skip] Minor changes in docs
Doc94 Dec 31, 2024
2fea4f4
[ci skip] Remove paper comment
Doc94 Dec 31, 2024
4ab5e69
Expose DamageSource to ExplodeEvent
Doc94 Jan 16, 2025
77ec43c
Fix bad return of blocks handled in Bukkit ExplodeEvents
Doc94 Jan 16, 2025
297f42c
[ci skip] Set final DamageSource in ExplodeEvent
Doc94 Jan 18, 2025
824e035
Simplify entity check for Explosion
Doc94 Jan 18, 2025
e354b08
Minor changes for the conversion of BlockPosition to Block for event
Doc94 Jan 18, 2025
044de0d
Rollback docs for ExplosionResult#KEEP
Doc94 Jan 18, 2025
3cd2d02
Minor changes in ServerExplosion Event things
Doc94 Jan 18, 2025
2b9d1e4
Minor Improvements for ExplosionEvent in CraftEventFactory
Doc94 Jan 18, 2025
53a713b
Remove shuffle of blocks in KEEP explosion
Doc94 Jan 18, 2025
0bd147a
Not filter empty blocks if the explosion is used include fire
Doc94 Jan 18, 2025
c3eafc7
cancel explode if event is cancelled in the keep behaviour
Doc94 Jan 22, 2025
61445b4
pass current cancel status of ServerExplosion to event
Doc94 Jan 22, 2025
f63b551
remove filter for blocks for make the event know all the blocks expec…
Doc94 Jan 22, 2025
99f43d4
expose fire behaviour in ExplodeEvent
Doc94 Jan 22, 2025
4905ba9
move cancel check for handle all explosions calls
Doc94 Jan 22, 2025
954eade
rollback filter remove for bukkit events
Doc94 Jan 22, 2025
da70c6b
not fire if explosion was canceled instead of just return and mess wi…
Doc94 Jan 24, 2025
526e150
not change order of blocks in paper ExplodeEvent
Doc94 Jan 25, 2025
549ad6c
clean up 1
Lulu13022002 Jan 25, 2025
97e42e5
clean up 2
Lulu13022002 Jan 26, 2025
859def7
Some more cleanup
lynxplay Jan 26, 2025
4a47bd8
Partial work towards source interface
lynxplay Jan 26, 2025
845a66e
fix EnderDragon compile issue with explosion events
Doc94 Jan 27, 2025
5bbae33
[ci skip] fix import order/style
Doc94 Jan 27, 2025
083f579
modify fake DamageSource generated in EnderDragon break walls
Doc94 Jan 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build-data/paper.at
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,7 @@ public net.minecraft.world.level.Level rainLevel
public net.minecraft.world.level.Level thread
public net.minecraft.world.level.Level thunderLevel
public net.minecraft.world.level.NaturalSpawner SPAWNING_CATEGORIES
public net.minecraft.world.level.ServerExplosion fire
public net.minecraft.world.level.StructureManager level
public net.minecraft.world.level.biome.Biome climateSettings
public net.minecraft.world.level.biome.Biome getTemperature(Lnet/minecraft/core/BlockPos;I)F
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
package io.papermc.paper.event.world;

import java.util.List;
import org.bukkit.ExplosionResult;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.damage.DamageSource;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.world.WorldEvent;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked;

/**
* Called when an explosion happens on the server.
* This includes explosions that are visual only or will not affect blocks due to set gamerules.
*/
@NullMarked
public class ExplodeEvent extends WorldEvent implements Cancellable {

private static final HandlerList HANDLER_LIST = new HandlerList();

private final DamageSource damageSource;
private final ExplodeEventSource eventSource;
private final Location location;
private final List<Block> blocks;
private final boolean spreadFire;
private final ExplosionResult result;

private float yield;
private boolean cancelled;

@ApiStatus.Internal
public ExplodeEvent(
final Location location,
final DamageSource damageSource,
final ExplodeEventSource eventSource,
final List<Block> blocks,
final float yield,
final boolean spreadFire,
final ExplosionResult result
) {
super(location.getWorld());
this.damageSource = damageSource;
this.eventSource = eventSource;
this.location = location;
this.blocks = blocks;
this.yield = yield;
this.spreadFire = spreadFire;
this.result = result;
}

/**
* Gets the source of damage.
*
* @return a damage source detailing the source of the damage from the explosion
* @apiNote by default, it's the explosion but data-packs using custom explode effect can set other type of damages
*/
public DamageSource getDamageSource() {
return this.damageSource;
}

/**
* Returns the location where the explosion happened.
*
* @return the location of the explosion
*/
public Location getLocation() {
return this.location.clone();
}

/**
* Yields the source of this explode event.
* <p>
* The returned interface is sealed and is expected to either be pattern matched or checked via instance of for
* further consumption.
* Retrieving and processing only entities that caused the explosion could hence be implemented as follows:
* <pre>{@code
* if (!(event.getSource() instanceof final ExplodeEventSource.EntitySource entitySource)) return;
* final Entity entity = entitySource.entity();
* ....
* }</pre>
* <p>
* Alternatively, pattern matching may be used to process different types of sources easily:
* <pre>
* {@code
* switch (event.getSource()) {
* case final ExplodeEventSource.BlockSource blockSource -> {
* final BlockState blockState = blockSource.blockState();
* }
* case final ExplodeEventSource.EnchantmentSource enchantmentSource -> {
* final ItemStack itemStack = enchantmentSource.itemStack();
* }
* case final ExplodeEventSource.EntitySource entitySource -> {
* final Entity entity = entitySource.entity();
* }
* case final ExplodeEventSource.UnknownSource ignored -> {
* }
* }
* }
* </pre>
*
* @return the source of this explosion.
*/
public ExplodeEventSource getSource() {
return this.eventSource;
}

/**
* Returns a mutable list of blocks that would have been caught in the explosion.
*
* @return all blocks caught in the explosion
* @apiNote the behaviors with these blocks depends on {@link #getExplosionResult()}
*/
@ApiStatus.Experimental
public List<Block> getAffectedBlocks() {
return this.blocks;
Doc94 marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* Returns the percentage of blocks to drop from this explosion.
*
* @return the yield percentage
* @apiNote this behavior depends on {@link #getExplosionResult()}
*/
public float getYield() {
return this.yield;
}

/**
* Sets the percentage of blocks to drop from this explosion.
*
* @param yield the new yield percentage
*/
public void setYield(float yield) {
this.yield = yield;
}

/**
* Checks if this explosion should spread fire
* on the ground.
*
* @return if this explosion should spread fire
*/
public boolean shouldSpreadFire() {
return this.spreadFire;
}

/**
* Returns the result of the explosion if it is not cancelled.
*
* @return the result of the explosion
*/
public ExplosionResult getExplosionResult() {
return this.result;
}

@Override
public boolean isCancelled() {
return this.cancelled;
}

@Override
public void setCancelled(final boolean cancel) {
this.cancelled = cancel;
}

@Override
public HandlerList getHandlers() {
return HANDLER_LIST;
}

public static HandlerList getHandlerList() {
return HANDLER_LIST;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package io.papermc.paper.event.world;

import org.bukkit.block.BlockState;
import org.bukkit.block.BlockType;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.TNTPrimed;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Contract;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;

/**
* Represents the source of an explosion that triggered a {@link ExplodeEvent}.
*/
@NullMarked
public sealed interface ExplodeEventSource permits ExplodeEventSource.BlockSource, ExplodeEventSource.EnchantmentSource, ExplodeEventSource.EntitySource, ExplodeEventSource.UnknownSource {

/**
* A block explode event source.
* <p>
* Yielded by {@link ExplodeEvent#getSource()} if a block exploded, like {@link BlockType#RESPAWN_ANCHOR} does
* outside the nether.
*/
non-sealed interface BlockSource extends ExplodeEventSource {

/**
* Yields the block state of the block prior to exploding.
* Useful as {@link ExplodeEvent#getLocation()}'s block is already exploded to air.
*
* @return the block state of the block prior to exploding.
*/
BlockState blockState();
}

/**
* An entity explode event source.
* <p>
* Yielded by {@link ExplodeEvent#getSource()} if an entity was the cause of an explosion, such as {@link TNTPrimed}.
*/
non-sealed interface EntitySource extends ExplodeEventSource {

/**
* Yields the entity that exploded.
*
* @return the entity instance.
*/
Entity entity();
}

/**
* An enchantment explode event source.
* <p>
* Yielded by {@link ExplodeEvent#getSource()} if the explosion was caused by an enchantment effect, like
* {@link Enchantment#WIND_BURST}.
*/
non-sealed interface EnchantmentSource extends ExplodeEventSource {

/**
* The itemstack that was enchanted to cause this explosion.
*
* @return a copy of the itemstack.
*/
@Contract("-> new")
ItemStack itemStack();

/**
* The owner of the enchanted item.
* The owner is understood as the further entity related to the item causing this explosion, such as the wielder
* of a weapon or the shooter of an arrow.
*
* @return the item owner.
*/
@Nullable
LivingEntity itemOwner();

/**
* The entity affected by this explosion.
* Other than the {@link #itemOwner()}, this may be the shot arrow, the victim, or the
* attacker (depending on the enchantment definition).
*
* @return the affected entity.
*/
Entity affected();
}

/**
* The unknown explode event source.
* Yielded if the api cannot or does not expose any further information about the source.
*/
non-sealed interface UnknownSource extends ExplodeEventSource {
/**
* The static instance of the unknown source.
*/
UnknownSource INSTANCE = new UnknownSource() {
};
}
}
6 changes: 3 additions & 3 deletions paper-api/src/main/java/org/bukkit/ExplosionResult.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ public enum ExplosionResult {

/**
* Represents an explosion where no change took place.
*
* <br>
* This is the case when {@link org.bukkit.GameRule#MOB_GRIEFING} is
* disabled.
*/
KEEP,
/**
* Represents an explosion where all destroyed blocks drop their items.
*
* <br>
* This is the case when
* {@link org.bukkit.GameRule#TNT_EXPLOSION_DROP_DECAY} or
* {@link org.bukkit.GameRule#BLOCK_EXPLOSION_DROP_DECAY} is disabled.
Expand All @@ -29,7 +29,7 @@ public enum ExplosionResult {
DESTROY_WITH_DECAY,
/**
* Represents an explosion where a block change/update has happened.
*
* <br>
* For example, when a wind charge is used it will cause nearby buttons,
* levers and bells to be activated.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package org.bukkit.event.block;

import java.util.List;

Lulu13022002 marked this conversation as resolved.
Show resolved Hide resolved
import io.papermc.paper.event.world.ExplodeEvent;
import org.bukkit.ExplosionResult;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;

/**
Expand All @@ -17,7 +20,9 @@
* <p>
* The event isn't called if the {@link org.bukkit.GameRule#MOB_GRIEFING}
* is disabled as no block interaction will occur.
* @see ExplodeEvent
*/
@ApiStatus.Obsolete
public class BlockExplodeEvent extends BlockEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private boolean cancel;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
package org.bukkit.event.entity;

import java.util.List;

import io.papermc.paper.event.world.ExplodeEvent;
import org.bukkit.ExplosionResult;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;

/**
* Called when an entity explodes interacting with blocks. The
* event isn't called if the {@link org.bukkit.GameRule#MOB_GRIEFING}
* is disabled as no block interaction will occur.
* @see ExplodeEvent
*/
@ApiStatus.Obsolete
public class EntityExplodeEvent extends EntityEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private boolean cancel;
Expand Down Expand Up @@ -72,7 +77,7 @@ public List<Block> blockList() {
*/
@NotNull
public Location getLocation() {
return location.clone(); // Paper - clone to avoid changes
return location.clone();
}

/**
Expand Down
Loading
Loading