Skip to content

Commit

Permalink
Damage step frames
Browse files Browse the repository at this point in the history
  • Loading branch information
Yeregorix committed Feb 10, 2025
1 parent 25fb89a commit 3b613f1
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 77 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ public class SpongeAttackTracker extends SpongeDamageTracker {
private float attackStrength;
private boolean strongSprint = false;

public SpongeAttackTracker(final DamageCalculationEvent.Pre preEvent, final ItemStack weapon) {
super(preEvent);
public SpongeAttackTracker(final DamageCalculationEvent.Pre preEvent, final DamageSource source, final ItemStack weapon) {
super(preEvent, source);
this.weapon = weapon;
this.weaponSnapshot = ItemStackUtil.snapshotOf(weapon);
}
Expand Down Expand Up @@ -91,7 +91,7 @@ public boolean callAttackPostEvent(final Entity entity, final DamageSource sourc
throw new IllegalStateException("Post event already fired");
}

finalDamage = (float) this.newStep(DamageStepTypes.END, this).apply(finalDamage);
finalDamage = (float) this.newStep(DamageStepTypes.END).apply(finalDamage);

try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) {
SpongeDamageTracker.generateCauseFor(source, frame);
Expand All @@ -114,10 +114,10 @@ public boolean callAttackPostEvent(final Entity entity, final DamageSource sourc
return null;
}

tracker = new SpongeAttackTracker(event, weapon);
tracker = new SpongeAttackTracker(event, source, weapon);
}

tracker.newStep(DamageStepTypes.START, tracker).apply(baseDamage);
tracker.newStep(DamageStepTypes.START).apply(baseDamage);
return tracker;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,42 +25,19 @@
package org.spongepowered.common.event.cause.entity.damage;

import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.api.event.Cause;
import org.spongepowered.api.event.CauseStackManager;
import org.spongepowered.api.event.cause.entity.damage.DamageModifier;
import org.spongepowered.api.event.cause.entity.damage.DamageStepType;

import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;

public class SpongeDamageModifier implements DamageModifier {
protected final DamageStepType type;
protected final Cause cause;
protected final @Nullable Function function;

public SpongeDamageModifier(final DamageStepType type, final Cause cause, final @Nullable Function function) {
this.type = type;
this.cause = cause;
this.function = function;
}

@Override
public final DamageStepType type() {
return this.type;
}

@Override
public final Cause cause() {
return this.cause;
}

@Override
public final Optional<Function> function() {
return Optional.ofNullable(this.function);
}
public record SpongeDamageModifier(DamageStepType type, Optional<Consumer<CauseStackManager.StackFrame>> frame, Optional<Function> damage) implements DamageModifier {

public static class Builder implements DamageModifier.Builder {
private @Nullable DamageStepType type;
private @Nullable Cause cause;
private @Nullable Consumer<CauseStackManager.StackFrame> frame;
private Function function;

public Builder() {
Expand All @@ -70,7 +47,7 @@ public Builder() {
@Override
public DamageModifier.Builder reset() {
this.type = null;
this.cause = null;
this.frame = null;
this.function = (step, damage) -> damage;
return this;
}
Expand All @@ -82,13 +59,13 @@ public DamageModifier.Builder type(DamageStepType type) {
}

@Override
public DamageModifier.Builder cause(Cause cause) {
this.cause = Objects.requireNonNull(cause, "cause");
public DamageModifier.Builder frame(Consumer<CauseStackManager.StackFrame> frame) {
this.frame = Objects.requireNonNull(frame, "frame");
return this;
}

@Override
public DamageModifier.Builder function(Function function) {
public DamageModifier.Builder damage(Function function) {
this.function = Objects.requireNonNull(function, "function");
return this;
}
Expand All @@ -98,10 +75,7 @@ public DamageModifier build() {
if (this.type == null) {
throw new IllegalStateException("type must be set");
}
if (this.cause == null) {
throw new IllegalStateException("cause must be set");
}
return new SpongeDamageModifier(this.type, this.cause, this.function);
return new SpongeDamageModifier(this.type, Optional.ofNullable(this.frame), Optional.ofNullable(this.function));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,31 @@
import org.apache.logging.log4j.Logger;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.api.event.Cause;
import org.spongepowered.api.event.CauseStackManager;
import org.spongepowered.api.event.cause.entity.damage.DamageModifier;
import org.spongepowered.api.event.cause.entity.damage.DamageStep;
import org.spongepowered.api.event.cause.entity.damage.DamageStepHistory;
import org.spongepowered.api.event.cause.entity.damage.DamageStepType;
import org.spongepowered.common.event.tracking.PhaseTracker;

import java.util.*;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.OptionalDouble;
import java.util.Set;
import java.util.StringJoiner;
import java.util.function.Consumer;

public final class SpongeDamageStep extends SpongeDamageModifier implements DamageStep {
public final class SpongeDamageStep implements DamageStep {
private static final Logger LOGGER = LogManager.getLogger();

private final SpongeDamageTracker tracker;
private final DamageStepType type;
private final @Nullable SpongeDamageStep parent;
private final @Nullable Consumer<CauseStackManager.StackFrame> frameModifier;
private final DamageModifier.@Nullable Function damageFunction;

private Cause cause;
private boolean skipped;

private OptionalDouble damageBeforeChildren = OptionalDouble.empty();
Expand All @@ -52,13 +64,25 @@ public final class SpongeDamageStep extends SpongeDamageModifier implements Dama
private List<SpongeDamageStep> childrenBefore;
private List<SpongeDamageStep> childrenAfter;

public SpongeDamageStep(
final DamageStepType type, final Cause cause, final @Nullable Function function,
final SpongeDamageTracker tracker, final @Nullable SpongeDamageStep parent
) {
super(type, cause, function);
public SpongeDamageStep(final SpongeDamageTracker tracker, final DamageStepType type, final Object[] causes) {
this.tracker = tracker;
this.parent = null;
this.type = type;
this.frameModifier = (frame) -> {
SpongeDamageTracker.generateCauseFor(tracker.source, frame);
for (Object cause : causes) {
frame.pushCause(cause);
}
};
this.damageFunction = null;
}

public SpongeDamageStep(final SpongeDamageStep parent, final DamageModifier modifier) {
this.tracker = parent.tracker;
this.parent = parent;
this.type = modifier.type();
this.frameModifier = modifier.frame().orElse(null);
this.damageFunction = modifier.damage().orElse(null);
}

void populateChildren() {
Expand All @@ -73,7 +97,7 @@ private void populateChildren(final Set<DamageStepType> parentTypes) {
if (parentTypes.contains(modifier.type())) {
LOGGER.warn("Modifier {} is supposed to be a child before step {} but this would cause a cycle so it will be ignored.", modifier, this);
} else {
before.add(new SpongeDamageStep(modifier.type(), modifier.cause(), modifier.function().orElse(null), this.tracker, this));
before.add(new SpongeDamageStep(this, modifier));
}
}
this.childrenBefore = before.build();
Expand All @@ -83,21 +107,44 @@ private void populateChildren(final Set<DamageStepType> parentTypes) {
if (parentTypes.contains(modifier.type())) {
LOGGER.warn("Modifier {} is supposed to be a child after step {} but this would cause a cycle so it will be ignored.", modifier, this);
} else {
after.add(new SpongeDamageStep(modifier.type(), modifier.cause(), modifier.function().orElse(null), this.tracker, this));
after.add(new SpongeDamageStep(this, modifier));
}
}
this.childrenAfter = after.build();

for (final SpongeDamageStep child : this.childrenBefore) {
child.populateChildren(parentTypes);
}
for (final SpongeDamageStep child : this.childrenAfter) {
child.populateChildren(parentTypes);
final PhaseTracker phaseTracker = PhaseTracker.getInstance();
try (final CauseStackManager.StackFrame frame = this.frameModifier == null ? null : phaseTracker.pushCauseFrame()) {
if (frame != null) {
try {
this.frameModifier.accept(frame);
} catch (final Throwable t) {
LOGGER.error("Failed to apply frame modifier of step {}", this, t);
}
}

this.cause = phaseTracker.currentCause();

for (final SpongeDamageStep child : this.childrenBefore) {
child.populateChildren(parentTypes);
}
for (final SpongeDamageStep child : this.childrenAfter) {
child.populateChildren(parentTypes);
}
}

parentTypes.remove(this.type);
}

@Override
public DamageStepType type() {
return this.type;
}

@Override
public Cause cause() {
return this.cause;
}

@Override
public boolean isSkipped() {
return this.skipped;
Expand Down Expand Up @@ -157,7 +204,8 @@ public String toString() {
return new StringJoiner(", ", SpongeDamageStep.class.getSimpleName() + "[", "]")
.add("type=" + this.type)
.add("cause=" + this.cause)
.add("function=" + this.function)
.add("frameModifier=" + this.frameModifier)
.add("damageFunction=" + this.damageFunction)
.add("skipped=" + this.skipped)
.add("damageBeforeChildren=" + this.damageBeforeChildren)
.add("damageBeforeSelf=" + this.damageBeforeSelf)
Expand Down Expand Up @@ -200,11 +248,11 @@ public double applyChildrenAfter(double damage) {

public double apply(double damage) {
damage = this.applyChildrenBefore(damage);
if (!this.skipped && this.function != null) {
if (!this.skipped && this.damageFunction != null) {
try {
damage = this.function.modify(this, damage);
} catch (Exception e) {
LOGGER.error("Failed to apply function of step {}", this, e);
damage = this.damageFunction.modify(this, damage);
} catch (final Throwable t) {
LOGGER.error("Failed to apply damage function of step {}", this, t);
}
}
damage = this.applyChildrenAfter(damage);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,7 @@
import org.apache.logging.log4j.Logger;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.api.entity.Entity;
import org.spongepowered.api.event.Cause;
import org.spongepowered.api.event.CauseStackManager;
import org.spongepowered.api.event.EventContext;
import org.spongepowered.api.event.EventContextKeys;
import org.spongepowered.api.event.SpongeEventFactory;
import org.spongepowered.api.event.cause.entity.damage.DamageStep;
Expand All @@ -60,10 +58,12 @@ public class SpongeDamageTracker implements DamageStepHistory {

private final List<SpongeDamageStep> rootSteps = new ArrayList<>();
protected final DamageCalculationEvent.Pre preEvent;
protected final DamageSource source;
protected DamageCalculationEvent.Post postEvent;

public SpongeDamageTracker(final DamageCalculationEvent.Pre preEvent) {
public SpongeDamageTracker(final DamageCalculationEvent.Pre preEvent, final DamageSource source) {
this.preEvent = preEvent;
this.source = source;
}

@Override
Expand All @@ -84,7 +84,7 @@ public DamageCalculationEvent.Post postEvent() {

public SpongeDamageStep newStep(final DefaultedRegistryReference<DamageStepType> typeRef, final Object... causes) {
final DamageStepType type = typeRef.get();
final SpongeDamageStep step = new SpongeDamageStep(type, Cause.of(EventContext.empty(), List.of(causes)), null, this, null);
final SpongeDamageStep step = new SpongeDamageStep(this, type, causes);
step.populateChildren();

if (this.postEvent != null) {
Expand Down Expand Up @@ -153,7 +153,7 @@ public float callDamagePostEvent(final Entity entity, float finalDamage) {
throw new IllegalStateException("Post event already fired");
}

finalDamage = (float) this.newStep(DamageStepTypes.END, this).apply(finalDamage);
finalDamage = (float) this.newStep(DamageStepTypes.END).apply(finalDamage);

try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) {
SpongeDamageTracker.generateCauseFor((DamageSource) this.preEvent.source(), frame);
Expand Down Expand Up @@ -195,10 +195,10 @@ protected static void generateCauseFor(final DamageSource source, final CauseSta
return null;
}

tracker = new SpongeDamageTracker(event);
tracker = new SpongeDamageTracker(event, source);
}

tracker.newStep(DamageStepTypes.START, tracker).apply(baseDamage);
tracker.newStep(DamageStepTypes.START).apply(baseDamage);
return tracker;
}

Expand Down
Loading

0 comments on commit 3b613f1

Please sign in to comment.