Skip to content

Commit 326bc20

Browse files
committed
!feat: Add CompositeEvent
This also breaks InteractBlockEvent.Secondary and SpawnEntityEvent.Pre
1 parent 1fb6e5b commit 326bc20

File tree

5 files changed

+184
-34
lines changed

5 files changed

+184
-34
lines changed

build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ tasks {
137137

138138
outputFactory = "org.spongepowered.api.event.SpongeEventFactory"
139139
include("org/spongepowered/api/event/*/**/*")
140+
include("org/spongepowered/api/event/CompositeEvent.java")
140141
exclude("org/spongepowered/api/event/action/InteractEvent.java")
141142
exclude("org/spongepowered/api/event/cause/")
142143
exclude("org/spongepowered/api/event/entity/AffectEntityEvent.java")
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
* This file is part of SpongeAPI, licensed under the MIT License (MIT).
3+
*
4+
* Copyright (c) SpongePowered <https://www.spongepowered.org>
5+
* Copyright (c) contributors
6+
*
7+
* Permission is hereby granted, free of charge, to any person obtaining a copy
8+
* of this software and associated documentation files (the "Software"), to deal
9+
* in the Software without restriction, including without limitation the rights
10+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
* copies of the Software, and to permit persons to whom the Software is
12+
* furnished to do so, subject to the following conditions:
13+
*
14+
* The above copyright notice and this permission notice shall be included in
15+
* all copies or substantial portions of the Software.
16+
*
17+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+
* THE SOFTWARE.
24+
*/
25+
package org.spongepowered.api.event;
26+
27+
import org.spongepowered.api.event.impl.AbstractCompositeEvent;
28+
import org.spongepowered.api.util.annotation.eventgen.GenerateFactoryMethod;
29+
import org.spongepowered.api.util.annotation.eventgen.ImplementedBy;
30+
import org.spongepowered.api.util.annotation.eventgen.PropertySettings;
31+
32+
import java.util.List;
33+
import java.util.function.Consumer;
34+
35+
/**
36+
* A {@link CompositeEvent} is an {@link Event} that contains multiple
37+
* side effectual {@link Event Events}, which may have their own side effects
38+
* and may be {@link Cancellable}. In some cases, the interactions of this event
39+
* may be cancellable as a whole, but are not guaranteed to revert all side
40+
* effects on the {@link org.spongepowered.api.Game}. The {@link #children()} of
41+
* this event are ordered in a "best-effort" basis, and may not be guaranteed
42+
* to be in any particular order.
43+
* <p>Using {@link #setCancelled(boolean)} will perform a best effort cancellation
44+
* on each of the children events.
45+
*/
46+
@GenerateFactoryMethod
47+
@ImplementedBy(AbstractCompositeEvent.class)
48+
public interface CompositeEvent<E extends Event> extends Event, Cancellable {
49+
50+
E baseEvent();
51+
52+
List<Event> children();
53+
54+
default <E extends Event> List<? extends E> event(Class<E> type) {
55+
return this.children().stream()
56+
.filter(type::isInstance)
57+
.map(type::cast)
58+
.toList();
59+
}
60+
61+
default <E extends Event> void applyTo(Class<E> type, Consumer<? super E> consumer) {
62+
this.children().stream()
63+
.filter(type::isInstance)
64+
.map(type::cast)
65+
.forEach(consumer);
66+
}
67+
68+
/**
69+
* {@inheritDoc}
70+
*
71+
* Cancels this event and all related events captured {@link #children()}.
72+
* Selectively, if individual events are wished to be cancelled,
73+
* the individual events should be cancelled instead.
74+
*
75+
* @param cancel The new cancelled state
76+
*/
77+
@PropertySettings(generateMethods = false)
78+
@Override
79+
void setCancelled(boolean cancel);
80+
}

src/main/java/org/spongepowered/api/event/block/InteractBlockEvent.java

Lines changed: 44 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,12 @@
2929
import org.spongepowered.api.block.BlockTypes;
3030
import org.spongepowered.api.entity.living.player.Player;
3131
import org.spongepowered.api.event.Cancellable;
32+
import org.spongepowered.api.event.CompositeEvent;
3233
import org.spongepowered.api.event.action.InteractEvent;
3334
import org.spongepowered.api.item.inventory.ItemStack;
3435
import org.spongepowered.api.util.Direction;
3536
import org.spongepowered.api.util.Tristate;
37+
import org.spongepowered.api.util.annotation.eventgen.GenerateFactoryMethod;
3638
import org.spongepowered.api.world.server.ServerLocation;
3739
import org.spongepowered.math.vector.Vector3d;
3840

@@ -101,7 +103,8 @@ interface Finish extends Primary, Cancellable {
101103
*
102104
* <p>This is usually right-click.</p>
103105
*/
104-
interface Secondary extends InteractBlockEvent, Cancellable {
106+
@GenerateFactoryMethod
107+
interface Secondary extends InteractBlockEvent {
105108

106109
Tristate originalUseItemResult();
107110

@@ -143,43 +146,51 @@ interface Secondary extends InteractBlockEvent, Cancellable {
143146
*/
144147
Tristate useBlockResult();
145148

146-
/**
147-
* Sets whether the {@link Player#itemInHand} should be used.
148-
*
149-
* <ul>
150-
* <li>FALSE: The {@link ItemStack} will never be used.</li>
151-
* <li>UNDEFINED: The {@link ItemStack} will be used if the block fails.
152-
* </li>
153-
* <li>TRUE: The {@link ItemStack} will always be used.</li>
154-
* </ul>
155-
*
156-
* <p>Note: These results may differ depending on implementation.</p>
157-
*
158-
* @param result Whether the {@link Player#itemInHand} should be used
159-
*/
160-
void setUseItemResult(Tristate result);
161-
162-
/**
163-
* Sets whether the interacted {@link BlockSnapshot} should be used.
164-
*
165-
* <ul>
166-
* <li>FALSE: {@link BlockSnapshot} will never be used.</li>
167-
* <li>UNDEFINED: {@link BlockSnapshot} will be used as normal.</li>
168-
* <li>TRUE: {@link BlockSnapshot} will always be used.</li>
169-
* </ul>
170-
*
171-
* <p>Note: These results may differ depending on implementation.</p>
172-
*
173-
* @param result Whether the interacted {@link BlockSnapshot} should be
174-
* used
175-
*/
176-
void setUseBlockResult(Tristate result);
177-
178149
/**
179150
* Gets the point of interaction where the interaction occurred as a {@link Vector3d}.
180151
*
181152
* @return The interaction point
182153
*/
183154
Vector3d interactionPoint();
155+
156+
interface Pre extends Secondary, Cancellable {
157+
158+
/**
159+
* Sets whether the {@link Player#itemInHand} should be used.
160+
*
161+
* <ul>
162+
* <li>FALSE: The {@link ItemStack} will never be used.</li>
163+
* <li>UNDEFINED: The {@link ItemStack} will be used if the block fails.
164+
* </li>
165+
* <li>TRUE: The {@link ItemStack} will always be used.</li>
166+
* </ul>
167+
*
168+
* <p>Note: These results may differ depending on implementation.</p>
169+
*
170+
* @param result Whether the {@link Player#itemInHand} should be used
171+
*/
172+
void setUseItemResult(Tristate result);
173+
174+
/**
175+
* Sets whether the interacted {@link BlockSnapshot} should be used.
176+
*
177+
* <ul>
178+
* <li>FALSE: {@link BlockSnapshot} will never be used.</li>
179+
* <li>UNDEFINED: {@link BlockSnapshot} will be used as normal.</li>
180+
* <li>TRUE: {@link BlockSnapshot} will always be used.</li>
181+
* </ul>
182+
*
183+
* <p>Note: These results may differ depending on implementation.</p>
184+
*
185+
* @param result Whether the interacted {@link BlockSnapshot} should be
186+
* used
187+
*/
188+
void setUseBlockResult(Tristate result);
189+
}
190+
191+
interface Post extends CompositeEvent<InteractBlockEvent.Secondary> {
192+
193+
}
194+
184195
}
185196
}

src/main/java/org/spongepowered/api/event/entity/SpawnEntityEvent.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
import org.spongepowered.api.entity.Entity;
2828
import org.spongepowered.api.event.Cause;
29+
import org.spongepowered.api.event.impl.entity.AbstractAffectEntityEvent;
2930
import org.spongepowered.api.event.impl.entity.AbstractSpawnEntityEvent;
3031
import org.spongepowered.api.util.annotation.eventgen.GenerateFactoryMethod;
3132
import org.spongepowered.api.util.annotation.eventgen.ImplementedBy;
@@ -51,7 +52,8 @@ public interface SpawnEntityEvent extends AffectEntityEvent {
5152
* will result in no awareness to the client that the entity was being
5253
* spawned and later cancelled.
5354
*/
54-
interface Pre extends SpawnEntityEvent {}
55+
@ImplementedBy(value = AbstractAffectEntityEvent.class, priority = 2)
56+
interface Pre extends AffectEntityEvent {}
5557

5658
interface Custom extends SpawnEntityEvent {}
5759
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* This file is part of SpongeAPI, licensed under the MIT License (MIT).
3+
*
4+
* Copyright (c) SpongePowered <https://www.spongepowered.org>
5+
* Copyright (c) contributors
6+
*
7+
* Permission is hereby granted, free of charge, to any person obtaining a copy
8+
* of this software and associated documentation files (the "Software"), to deal
9+
* in the Software without restriction, including without limitation the rights
10+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
* copies of the Software, and to permit persons to whom the Software is
12+
* furnished to do so, subject to the following conditions:
13+
*
14+
* The above copyright notice and this permission notice shall be included in
15+
* all copies or substantial portions of the Software.
16+
*
17+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+
* THE SOFTWARE.
24+
*/
25+
package org.spongepowered.api.event.impl;
26+
27+
import org.spongepowered.api.event.Cancellable;
28+
import org.spongepowered.api.event.CompositeEvent;
29+
import org.spongepowered.api.event.Event;
30+
import org.spongepowered.api.util.annotation.eventgen.UseField;
31+
32+
import java.util.Collections;
33+
import java.util.List;
34+
35+
public abstract class AbstractCompositeEvent<E extends Event> extends AbstractEvent implements CompositeEvent<E> {
36+
37+
@UseField(overrideToString = true)
38+
protected List<Event> children;
39+
40+
@UseField
41+
protected boolean cancelled;
42+
43+
public final void postInit() {
44+
this.children = Collections.unmodifiableList(this.children);
45+
}
46+
47+
@Override
48+
public void setCancelled(boolean cancel) {
49+
this.cancelled = cancel;
50+
this.children().forEach(event -> {
51+
if (event instanceof Cancellable cancellable) {
52+
cancellable.setCancelled(cancel);
53+
}
54+
});
55+
}
56+
}

0 commit comments

Comments
 (0)