From dfd0193583bd64e2391b72772165221857c7b830 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sun, 21 Apr 2024 15:25:40 -0700 Subject: [PATCH] !feat: Add CompositeEvent This also breaks InteractBlockEvent.Secondary and SpawnEntityEvent.Pre --- .../api/event/CompositeEvent.java | 51 +++++++++++++ .../api/event/block/InteractBlockEvent.java | 75 +++++++++++-------- .../api/event/entity/SpawnEntityEvent.java | 4 +- 3 files changed, 96 insertions(+), 34 deletions(-) create mode 100644 src/main/java/org/spongepowered/api/event/CompositeEvent.java diff --git a/src/main/java/org/spongepowered/api/event/CompositeEvent.java b/src/main/java/org/spongepowered/api/event/CompositeEvent.java new file mode 100644 index 00000000000..4ef7486393c --- /dev/null +++ b/src/main/java/org/spongepowered/api/event/CompositeEvent.java @@ -0,0 +1,51 @@ +package org.spongepowered.api.event; + +import org.spongepowered.api.util.annotation.eventgen.NoFactoryMethod; + +import java.util.List; +import java.util.function.Consumer; + +/** + * A {@link CompositeEvent} is an {@link Event} that contains multiple + * side effectual {@link Event Events}, which may have their own side effects + * and may be {@link Cancellable}. In some cases, the interactions of this event + * may be cancellable as a whole, but are not guaranteed to revert all side + * effects on the {@link org.spongepowered.api.Game}. The {@link #children()} of + * this event are ordered in a "best-effort" basis, and may not be guaranteed + * to be in any particular order. + *

Using {@link #setCancelled(boolean)} will perform a best effort cancellation + * on each of the children events. + */ +@NoFactoryMethod +public interface CompositeEvent extends Event, Cancellable { + + E baseEvent(); + + List children(); + + default List event(Class type) { + return this.children().stream() + .filter(type::isInstance) + .map(type::cast) + .toList(); + } + + default void applyTo(Class type, Consumer consumer) { + this.children().stream() + .filter(type::isInstance) + .map(type::cast) + .forEach(consumer); + } + + /** + * {@inheritDoc} + * + * Cancels this event and all related events captured {@link #children()}. + * Selectively, if individual events are wished to be cancelled, + * the individual events should be cancelled instead. + * + * @param cancel The new cancelled state + */ + @Override + void setCancelled(boolean cancel); +} diff --git a/src/main/java/org/spongepowered/api/event/block/InteractBlockEvent.java b/src/main/java/org/spongepowered/api/event/block/InteractBlockEvent.java index 161452c8bdf..ee26311ba3e 100644 --- a/src/main/java/org/spongepowered/api/event/block/InteractBlockEvent.java +++ b/src/main/java/org/spongepowered/api/event/block/InteractBlockEvent.java @@ -29,13 +29,18 @@ import org.spongepowered.api.block.BlockTypes; import org.spongepowered.api.entity.living.player.Player; import org.spongepowered.api.event.Cancellable; +import org.spongepowered.api.event.CompositeEvent; import org.spongepowered.api.event.action.InteractEvent; +import org.spongepowered.api.event.entity.SpawnEntityEvent; +import org.spongepowered.api.event.item.inventory.ChangeInventoryEvent; import org.spongepowered.api.item.inventory.ItemStack; import org.spongepowered.api.util.Direction; import org.spongepowered.api.util.Tristate; import org.spongepowered.api.world.server.ServerLocation; import org.spongepowered.math.vector.Vector3d; +import java.util.Optional; + /** * Base event for all interactions involving a {@link BlockSnapshot} at a * {@link ServerLocation}. @@ -101,7 +106,7 @@ interface Finish extends Primary, Cancellable { * *

This is usually right-click.

*/ - interface Secondary extends InteractBlockEvent, Cancellable { + interface Secondary extends InteractBlockEvent { Tristate originalUseItemResult(); @@ -143,43 +148,47 @@ interface Secondary extends InteractBlockEvent, Cancellable { */ Tristate useBlockResult(); - /** - * Sets whether the {@link Player#itemInHand} should be used. - * - * - * - *

Note: These results may differ depending on implementation.

- * - * @param result Whether the {@link Player#itemInHand} should be used - */ - void setUseItemResult(Tristate result); - - /** - * Sets whether the interacted {@link BlockSnapshot} should be used. - * - * - * - *

Note: These results may differ depending on implementation.

- * - * @param result Whether the interacted {@link BlockSnapshot} should be - * used - */ - void setUseBlockResult(Tristate result); - /** * Gets the point of interaction where the interaction occurred as a {@link Vector3d}. * * @return The interaction point */ Vector3d interactionPoint(); + + interface Pre extends Secondary, Cancellable { + + /** + * Sets whether the {@link Player#itemInHand} should be used. + * + * + * + *

Note: These results may differ depending on implementation.

+ * + * @param result Whether the {@link Player#itemInHand} should be used + */ + void setUseItemResult(Tristate result); + + /** + * Sets whether the interacted {@link BlockSnapshot} should be used. + * + * + * + *

Note: These results may differ depending on implementation.

+ * + * @param result Whether the interacted {@link BlockSnapshot} should be + * used + */ + void setUseBlockResult(Tristate result); + } + } } diff --git a/src/main/java/org/spongepowered/api/event/entity/SpawnEntityEvent.java b/src/main/java/org/spongepowered/api/event/entity/SpawnEntityEvent.java index f459b856f79..81e4f127143 100644 --- a/src/main/java/org/spongepowered/api/event/entity/SpawnEntityEvent.java +++ b/src/main/java/org/spongepowered/api/event/entity/SpawnEntityEvent.java @@ -26,6 +26,7 @@ import org.spongepowered.api.entity.Entity; import org.spongepowered.api.event.Cause; +import org.spongepowered.api.event.impl.entity.AbstractAffectEntityEvent; import org.spongepowered.api.event.impl.entity.AbstractSpawnEntityEvent; import org.spongepowered.api.util.annotation.eventgen.GenerateFactoryMethod; import org.spongepowered.api.util.annotation.eventgen.ImplementedBy; @@ -51,7 +52,8 @@ public interface SpawnEntityEvent extends AffectEntityEvent { * will result in no awareness to the client that the entity was being * spawned and later cancelled. */ - interface Pre extends SpawnEntityEvent {} + @ImplementedBy(value = AbstractAffectEntityEvent.class, priority = 2) + interface Pre extends AffectEntityEvent {} interface Custom extends SpawnEntityEvent {} }