fix(assassin): preserve external potion effects
Release / release (push) Successful in 2m46s
CI / build (push) Successful in 1m8s

This commit is contained in:
dmg
2026-08-18 23:50:15 -04:00
parent 323d177573
commit 3d65576010
4 changed files with 210 additions and 16 deletions
@@ -3,6 +3,7 @@ package games.dmg.spigottyrant;
import java.time.Clock;
import java.time.Instant;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import org.bukkit.GameMode;
@@ -17,6 +18,7 @@ public final class AssassinEffectController implements Runnable {
private final Server server;
private final PluginSettings settings;
private final Clock clock;
private final EffectApplier effectApplier;
private final Set<UUID> grantedFlight = new HashSet<>();
public AssassinEffectController(
@@ -25,10 +27,21 @@ public final class AssassinEffectController implements Runnable {
PluginSettings settings,
Clock clock
) {
this.stateManager = stateManager;
this.server = server;
this.settings = settings;
this.clock = clock;
this(stateManager, server, settings, clock, new BukkitEffectApplier());
}
AssassinEffectController(
TyrantStateManager stateManager,
Server server,
PluginSettings settings,
Clock clock,
EffectApplier effectApplier
) {
this.stateManager = Objects.requireNonNull(stateManager, "stateManager");
this.server = Objects.requireNonNull(server, "server");
this.settings = Objects.requireNonNull(settings, "settings");
this.clock = Objects.requireNonNull(clock, "clock");
this.effectApplier = Objects.requireNonNull(effectApplier, "effectApplier");
}
@Override
@@ -43,15 +56,15 @@ public final class AssassinEffectController implements Runnable {
}
applyWhileActive(
player, state, Ability.ASSASSIN_INVISIBILITY_ACTIVE,
PotionEffectType.INVISIBILITY, 0, false
EffectKind.INVISIBILITY, 0, false
);
applyWhileActive(
player, state, Ability.ASSASSIN_SPEED_ACTIVE,
PotionEffectType.SPEED, 0, true
EffectKind.SPEED, 0, true
);
applyWhileActive(
player, state, Ability.ASSASSIN_WEAKNESS_ACTIVE,
PotionEffectType.WEAKNESS, settings.assassinWeaknessLevel() - 1, true
EffectKind.WEAKNESS, settings.assassinWeaknessLevel() - 1, true
);
boolean jumpReady = !state.cooldownEnds().getOrDefault(
Ability.ASSASSIN_DOUBLE_JUMP, Instant.MIN
@@ -71,29 +84,52 @@ public final class AssassinEffectController implements Runnable {
Player player,
PlayerState state,
Ability ability,
PotionEffectType type,
EffectKind effect,
int amplifier,
boolean particles
) {
if (state.cooldownEnds().getOrDefault(ability, Instant.MIN).isAfter(clock.instant())) {
player.addPotionEffect(new PotionEffect(
type, EFFECT_TICKS, amplifier, false, particles, true
));
} else {
player.removePotionEffect(type);
effectApplier.apply(player, effect, amplifier, particles);
}
}
private void clear(Player player) {
player.removePotionEffect(PotionEffectType.INVISIBILITY);
player.removePotionEffect(PotionEffectType.SPEED);
player.removePotionEffect(PotionEffectType.WEAKNESS);
if (grantedFlight.remove(player.getUniqueId()) && isSurvivalLike(player)) {
player.setAllowFlight(false);
player.setFlying(false);
}
}
enum EffectKind {
INVISIBILITY,
SPEED,
WEAKNESS
}
@FunctionalInterface
interface EffectApplier {
void apply(Player player, EffectKind effect, int amplifier, boolean particles);
}
private static final class BukkitEffectApplier implements EffectApplier {
@Override
public void apply(
Player player,
EffectKind effect,
int amplifier,
boolean particles
) {
PotionEffectType type = switch (effect) {
case INVISIBILITY -> PotionEffectType.INVISIBILITY;
case SPEED -> PotionEffectType.SPEED;
case WEAKNESS -> PotionEffectType.WEAKNESS;
};
player.addPotionEffect(new PotionEffect(
type, EFFECT_TICKS, amplifier, false, particles, true
));
}
}
private static boolean isGrounded(Player player) {
return !player.getLocation().clone().subtract(0.0, 0.1, 0.0)
.getBlock().isPassable();