Skip to content

Commit e6a3529

Browse files
committed
Damage step API improvements
1 parent 05df366 commit e6a3529

File tree

8 files changed

+284
-76
lines changed

8 files changed

+284
-76
lines changed

src/main/java/org/spongepowered/api/event/cause/entity/damage/DamageModifier.java

Lines changed: 76 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,87 @@
2424
*/
2525
package org.spongepowered.api.event.cause.entity.damage;
2626

27+
import org.spongepowered.api.Sponge;
28+
import org.spongepowered.api.event.CauseStackManager;
29+
30+
import java.util.Optional;
31+
import java.util.function.Consumer;
32+
2733
/**
28-
* A damage modifier that will be applied before or after a {@link DamageStep}.
34+
* A damage modifier that will create a {@link DamageStep}.
2935
*/
30-
@FunctionalInterface
3136
public interface DamageModifier {
3237

3338
/**
34-
* Modifies the damage.
39+
* Gets the {@link DamageStepType} of this modifier.
40+
*
41+
* @return the step type
42+
*/
43+
DamageStepType type();
44+
45+
/**
46+
* Gets the consumer that will modify the cause frame.
3547
*
36-
* @param step The damage step this modifier is associated with.
37-
* @param damage The current damage value.
38-
* @return The next damage value
48+
* @return The cause frame modifier
3949
*/
40-
double modify(DamageStep step, double damage);
50+
Optional<Consumer<CauseStackManager.StackFrame>> frame();
51+
52+
/**
53+
* Gets the function that will modify the damage.
54+
* The function may be absent if the sole purpose of this modifier is to apply children steps.
55+
*
56+
* @return the damage modifier
57+
*/
58+
Optional<Function> damage();
59+
60+
@FunctionalInterface
61+
interface Function {
62+
/**
63+
* Modifies the damage.
64+
*
65+
* @param step The damage step this modifier is associated with.
66+
* @param damage The current damage value.
67+
* @return The next damage value
68+
*/
69+
double modify(DamageStep step, double damage);
70+
}
71+
72+
/**
73+
* Creates a new {@link Builder} to create {@link DamageModifier}s.
74+
*
75+
* @return The new builder
76+
*/
77+
static Builder builder() {
78+
return Sponge.game().builderProvider().provide(Builder.class);
79+
}
80+
81+
/**
82+
* A builder to create {@link DamageModifier}s.
83+
*/
84+
interface Builder extends org.spongepowered.api.util.Builder<DamageModifier, Builder> {
85+
86+
/**
87+
* Sets the {@link DamageStepType} for this modifier.
88+
*
89+
* @param type The damage step type
90+
* @return this builder for chaining
91+
*/
92+
Builder type(DamageStepType type);
93+
94+
/**
95+
* Sets the cause frame modifier.
96+
*
97+
* @param frameModifier The frame modifier
98+
* @return this builder for chaining
99+
*/
100+
Builder frame(Consumer<CauseStackManager.StackFrame> frameModifier);
101+
102+
/**
103+
* Sets the {@link Function} for this modifier.
104+
*
105+
* @param function The damage function
106+
* @return this builder for chaining
107+
*/
108+
Builder damage(Function function);
109+
}
41110
}

src/main/java/org/spongepowered/api/event/cause/entity/damage/DamageStep.java

Lines changed: 57 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -27,30 +27,35 @@
2727
import org.spongepowered.api.event.Cause;
2828

2929
import java.util.List;
30+
import java.util.Optional;
31+
import java.util.OptionalDouble;
3032

3133
/**
32-
* Represents a step in the damage calculation.
34+
* A step represent an operation made by the platform (vanilla and mods) or modifiers added by plugins.
35+
* Steps are structured as trees where children modify the input or output of the parent step.
36+
* A damage calculation is made of multiple trees of steps.
3337
*/
3438
public interface DamageStep {
3539

3640
/**
37-
* Gets the {@link DamageStepType} for this {@link DamageStep}.
41+
* Gets the {@link DamageStepType} of this step.
3842
*
39-
* @return The damage step type
43+
* @return the step type
4044
*/
4145
DamageStepType type();
4246

4347
/**
44-
* Gets the cause of this {@link DamageStep}.
48+
* Gets the {@link Cause} of this step.
4549
*
4650
* @return The cause of this step
4751
*/
4852
Cause cause();
4953

5054
/**
5155
* Gets whether this step is skipped.
52-
* When skipped, only the step and its side effects are ignored, modifiers are still applied.
53-
* A modifier willing to ignore every previous modifiers should revert the damage to {@link #damageBeforeModifiers()}.
56+
* When skipped, only the step itself and its side effects are ignored, children are still applied.
57+
* A modifier willing to ignore every previous children should revert the damage to {@link #damageBeforeChildren()},
58+
* or call {@link #skip} on each child.
5459
*
5560
* @return Whether this step is skipped
5661
*/
@@ -75,47 +80,77 @@ default void skip() {
7580
}
7681

7782
/**
78-
* The damage just before the modifiers of this step.
83+
* The damage just before the children of this step.
84+
* Returns empty if the value is not known yet.
7985
*
80-
* @return The damage before this step
86+
* @return The damage before the children of this step
8187
*/
82-
double damageBeforeModifiers();
88+
OptionalDouble damageBeforeChildren();
8389

8490
/**
8591
* The damage just before this step.
92+
* Returns empty if the value is not known yet.
8693
*
8794
* @return The damage before this step
88-
* @throws IllegalStateException if called before the "before" modifiers have finished.
8995
*/
90-
double damageBeforeStep();
96+
OptionalDouble damageBeforeSelf();
9197

9298
/**
9399
* The damage just after this step.
100+
* Returns empty if the value is not known yet.
94101
*
95102
* @return The damage after this step
96-
* @throws IllegalStateException if called before this step has finished
97103
*/
98-
double damageAfterStep();
104+
OptionalDouble damageAfterSelf();
99105

100106
/**
101-
* The damage just after the modifiers of this step.
107+
* The damage just after the children of this step.
108+
* Returns empty if the value is not known yet.
102109
*
103110
* @return The damage after this step
104-
* @throws IllegalStateException if called before the modifiers have finished.
105111
*/
106-
double damageAfterModifiers();
112+
OptionalDouble damageAfterChildren();
113+
114+
/**
115+
* Gets the {@link DamageStepHistory} this step belongs to.
116+
*
117+
* @return The history containing this step.
118+
*/
119+
DamageStepHistory history();
120+
121+
/**
122+
* Gets the parent of this step.
123+
* Returns empty if this step is the root of its tree.
124+
*
125+
* @return The parent of this step
126+
*/
127+
Optional<DamageStep> parent();
128+
129+
/**
130+
* Gets the root of this step.
131+
*
132+
* @return The root of this step
133+
*/
134+
default DamageStep root() {
135+
DamageStep step = this;
136+
Optional<DamageStep> parent;
137+
while ((parent = step.parent()).isPresent()) {
138+
step = parent.get();
139+
}
140+
return step;
141+
}
107142

108143
/**
109-
* Gets an immutable list of all modifiers that applies just before this step.
144+
* Gets an immutable list of all children steps that applies just before this step.
110145
*
111-
* @return The list of modifiers
146+
* @return The list of children steps
112147
*/
113-
List<DamageModifier> modifiersBefore();
148+
List<DamageStep> childrenBefore();
114149

115150
/**
116-
* Gets an immutable list of all modifiers that applies just after this step.
151+
* Gets an immutable list of all children steps that applies just after this step.
117152
*
118-
* @return The list of modifiers
153+
* @return The list of children steps
119154
*/
120-
List<DamageModifier> modifiersAfter();
155+
List<DamageStep> childrenAfter();
121156
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
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.cause.entity.damage;
26+
27+
import java.util.List;
28+
29+
/**
30+
* Captures the root steps occurring during a damage calculation.
31+
*/
32+
public interface DamageStepHistory {
33+
34+
/**
35+
* Gets the list of the captured root steps during the damage calculation in the order they have been applied.
36+
* Note that this list is not an exhaustive representation of all the operations applied,
37+
* especially in a modded environment.
38+
* The list is unmodifiable and will gradually grow during the damage calculation.
39+
*
40+
* @return The root steps.
41+
*/
42+
List<DamageStep> rootSteps();
43+
}

src/main/java/org/spongepowered/api/event/cause/entity/damage/DamageStepType.java

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,35 @@
2424
*/
2525
package org.spongepowered.api.event.cause.entity.damage;
2626

27-
import org.spongepowered.api.event.Cause;
27+
import org.spongepowered.api.Sponge;
2828
import org.spongepowered.api.registry.DefaultedRegistryValue;
2929
import org.spongepowered.api.util.annotation.CatalogedBy;
3030

3131
/**
32-
* A type of {@link DamageStep} that can apply a "grouping" so to speak
33-
* for the damage modifier. The use case is being able to differentiate between
34-
* various {@link DamageStep}s based on the {@link DamageStepType}
35-
* without digging through the {@link Cause} provided by
36-
* {@link DamageStep#cause()}.
32+
* Represents a type of {@link DamageStep}.
3733
*/
3834
@CatalogedBy(DamageStepTypes.class)
3935
public interface DamageStepType extends DefaultedRegistryValue {
4036

37+
/**
38+
* Creates a new {@link DamageStepType}.
39+
*
40+
* @return the new step type
41+
*/
42+
static DamageStepType create() {
43+
return Sponge.game().factoryProvider().provide(Factory.class).create();
44+
}
45+
46+
/**
47+
* A factory to create {@link DamageStepType}s.
48+
*/
49+
interface Factory {
50+
51+
/**
52+
* Creates a new {@link DamageStepType}.
53+
*
54+
* @return the new step type
55+
*/
56+
DamageStepType create();
57+
}
4158
}

src/main/java/org/spongepowered/api/event/cause/entity/damage/DamageStepTypes.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,13 @@ public final class DamageStepTypes {
108108
*/
109109
public static final DefaultedRegistryReference<DamageStepType> ENCHANTMENT_COOLDOWN = DamageStepTypes.key(ResourceKey.sponge("enchantment_cooldown"));
110110

111+
/**
112+
* Represents the last {@link DamageStep} applied during a damage calculation.
113+
* This step happens just before the {@link org.spongepowered.api.event.entity.DamageCalculationEvent.Post}.
114+
* This step does nothing but can be used to add modifiers to the final damage.
115+
*/
116+
public static final DefaultedRegistryReference<DamageStepType> END = DamageStepTypes.key(ResourceKey.sponge("end"));
117+
111118
/**
112119
* Represents a {@link DamageStep} that will modify freezing damage.
113120
* E.g. {@link org.spongepowered.api.entity.living.monster.Blaze} take more damage from freezing sources.
@@ -152,6 +159,13 @@ public final class DamageStepTypes {
152159
*/
153160
public static final DefaultedRegistryReference<DamageStepType> SHIELD = DamageStepTypes.key(ResourceKey.sponge("shield"));
154161

162+
/**
163+
* Represents the first {@link DamageStep} applied during a damage calculation.
164+
* This step happens just after the {@link org.spongepowered.api.event.entity.DamageCalculationEvent.Pre}.
165+
* This step does nothing but can be used to add modifiers to the base damage.
166+
*/
167+
public static final DefaultedRegistryReference<DamageStepType> START = DamageStepTypes.key(ResourceKey.sponge("start"));
168+
155169
/**
156170
* Represents a {@link DamageStep} that is applied for a sweeping attack.
157171
*/

0 commit comments

Comments
 (0)