Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import ch.njol.util.Math2;
import ch.njol.util.coll.CollectionUtils;
import org.bukkit.event.Event;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
import org.skriptlang.skript.bukkit.potion.util.PotionUtils;
import org.skriptlang.skript.bukkit.potion.util.SkriptPotionEffect;
Expand Down Expand Up @@ -63,7 +64,8 @@ public void change(Event event, Object @Nullable [] delta, ChangeMode mode) {
* @param change The timespan delta.
* @param mode The mode of change to perform.
*/
static void changeSafe(SkriptPotionEffect potionEffect, Timespan change, ChangeMode mode) {
@ApiStatus.Internal
public static void changeSafe(SkriptPotionEffect potionEffect, Timespan change, ChangeMode mode) {
Timespan duration;
if (mode == ChangeMode.SET || mode == ChangeMode.RESET) {
duration = change;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package org.skriptlang.skript.bukkit.potion.elements.expressions;

import ch.njol.skript.Skript;
import ch.njol.skript.aliases.ItemType;
import ch.njol.skript.classes.Changer.ChangeMode;
import ch.njol.skript.doc.Description;
import ch.njol.skript.doc.Example;
Expand All @@ -15,20 +14,17 @@
import ch.njol.skript.util.Timespan;
import ch.njol.util.Kleenean;
import ch.njol.util.coll.CollectionUtils;
import org.bukkit.entity.Entity;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
import org.skriptlang.skript.bukkit.potion.elements.expressions.ExprPotionEffects.State;
import org.skriptlang.skript.bukkit.potion.util.PotionUtils;
import org.skriptlang.skript.bukkit.potion.providers.PotionEffectProvider;
import org.skriptlang.skript.bukkit.potion.providers.PotionEffectProvider.RetrievalState;
import org.skriptlang.skript.bukkit.potion.util.SkriptPotionEffect;
import org.bukkit.entity.LivingEntity;
import org.bukkit.event.Event;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.skriptlang.skript.registration.SyntaxRegistry;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;

@Name("Potion Effect of Entity/Item")
Expand All @@ -50,23 +46,23 @@ public class ExprPotionEffect extends PropertyExpression<Object, SkriptPotionEff
public static void register(SyntaxRegistry registry) {
registry.register(SyntaxRegistry.EXPRESSION, infoBuilder(ExprPotionEffect.class, SkriptPotionEffect.class,
"[:active|:hidden|both:(active and hidden|hidden and active)] %potioneffecttypes% [potion] effect[s]",
"livingentities/itemtypes",
"entities/itemtypes",
false)
.supplier(ExprPotionEffect::new)
.build());
}

private Expression<PotionEffectType> types;
private State state;
private RetrievalState state;

@Override
public boolean init(Expression<?>[] expressions, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) {
//noinspection unchecked
types = (Expression<PotionEffectType>) expressions[matchedPattern % 2];
setExpr(expressions[(matchedPattern + 1) % 2]);
state = State.fromParseTag(parseResult.tags.isEmpty() ? "" : parseResult.tags.getFirst());
if (state.includesHidden() && ItemType.class.isAssignableFrom(getExpr().getReturnType())) {
Skript.error("Items (such as potions or stews) do not have hidden effects");
state = RetrievalState.fromParseTag(parseResult.tags.isEmpty() ? "" : parseResult.tags.getFirst());
if (state.includesHidden() && !getExpr().canReturn(Entity.class)) {
Skript.error("Only living entities have hidden effects");
return false;
}
return true;
Expand All @@ -77,34 +73,8 @@ protected SkriptPotionEffect[] get(Event event, Object[] source) {
List<SkriptPotionEffect> potionEffects = new ArrayList<>();
PotionEffectType[] types = this.types.getArray(event);
for (Object object : source) {
if (object instanceof LivingEntity livingEntity) {
for (PotionEffectType type : types) {
PotionEffect potionEffect = livingEntity.getPotionEffect(type);
if (potionEffect == null) {
continue;
}
if (state.includesActive()) {
potionEffects.add(SkriptPotionEffect.fromBukkitEffect(potionEffect, livingEntity));
}
if (state.includesHidden()) {
PotionEffect hiddenEffect = potionEffect.getHiddenPotionEffect();
while (hiddenEffect != null) {
// do not set source for hidden effects
potionEffects.add(SkriptPotionEffect.fromBukkitEffect(hiddenEffect));
hiddenEffect = hiddenEffect.getHiddenPotionEffect();
}
}
}
} else if (object instanceof ItemType itemType) {
for (PotionEffect effect : PotionUtils.getPotionEffects(itemType)) {
for (PotionEffectType type : types) {
if (type.equals(effect.getType())) {
potionEffects.add(SkriptPotionEffect.fromBukkitEffect(effect, itemType));
break;
}
}
}
}
potionEffects.addAll(PotionEffectProvider.of(object, this::error)
.get(types, state));
}
return potionEffects.toArray(new SkriptPotionEffect[0]);
}
Expand All @@ -130,23 +100,15 @@ public void change(Event event, Object @Nullable [] delta, ChangeMode mode) {
switch (mode) {
case DELETE, RESET -> {
for (Object holder : holders) {
if (holder instanceof LivingEntity entity) {
reset(entity, types);
} else if (holder instanceof ItemType itemType) {
PotionUtils.removePotionEffects(itemType, types);
}
PotionEffectProvider.of(holder, this::error)
.clear(types, state);
}
}
case ADD, REMOVE -> {
assert delta != null;
for (Object holder : holders) {
if (holder instanceof LivingEntity entity) {
modify(entity, types, delta, mode);
} else if (holder instanceof ItemType itemType) {
if (delta[0] instanceof Timespan change) {
modify(itemType, types, change, mode);
}
}
PotionEffectProvider.of(holder, this::error)
.modify(types, state, delta, mode);
}
}
default -> {
Expand All @@ -155,98 +117,6 @@ public void change(Event event, Object @Nullable [] delta, ChangeMode mode) {
}
}

private void reset(LivingEntity entity, PotionEffectType[] types) {
if (state == State.ACTIVE) { // preserve hidden effects
for (PotionEffectType type : types) {
PotionEffect potionEffect = entity.getPotionEffect(type);
if (potionEffect == null) {
continue;
}
Deque<PotionEffect> hiddenEffects = PotionUtils.getHiddenEffects(potionEffect);
entity.removePotionEffect(type);
entity.addPotionEffects(hiddenEffects);
}
} else if (state == State.HIDDEN) { // preserve active effect
for (PotionEffectType type : types) {
PotionEffect original = entity.getPotionEffect(type);
entity.removePotionEffect(type);
if (original != null) {
// applying a potion effect ignores the hidden effect value
entity.addPotionEffect(original);
}
}
} else {
for (PotionEffectType type : types) {
entity.removePotionEffect(type);
}
}
}

private void modify(LivingEntity entity, PotionEffectType[] types, Object[] delta, ChangeMode mode) {
for (PotionEffectType type : types) {
PotionEffect potionEffect = entity.getPotionEffect(type);
if (potionEffect == null) {
continue;
}

Deque<PotionEffect> finalEffects; // effects to be applied
Deque<PotionEffect> effects; // effects to be filtered
boolean madeChanges = false;

if (state.includesHidden()) { // modify hidden effects
finalEffects = new ArrayDeque<>();
effects = PotionUtils.getHiddenEffects(potionEffect);
} else { // otherwise, simply preserve the hidden effects
finalEffects = PotionUtils.getHiddenEffects(potionEffect);
effects = new ArrayDeque<>();
}

if (state.includesActive()) { // need to modify the active effect too
effects.addLast(potionEffect);
}

// filter effects
effectLoop: for (PotionEffect effect : effects) {
SkriptPotionEffect skriptEffect = SkriptPotionEffect.fromBukkitEffect(effect);
for (Object object : delta) {
if (object instanceof Timespan timespan) {
ExprPotionDuration.changeSafe(skriptEffect, timespan, mode);
madeChanges = true;
} else if (object instanceof SkriptPotionEffect base) {
if (base.matchesQualities(effect)) { // remove this effect
madeChanges = true;
continue effectLoop;
}
}
}
// since we iterate most to least hidden, we need to preserve that order
finalEffects.addLast(skriptEffect.asBukkitPotionEffect());
}
if (!madeChanges) { // no potion effects were modified, don't reapply effects
return;
}

if (!state.includesActive()) { // if we didn't modify the active effect, we need to push it now
effects.addLast(potionEffect);
}

entity.removePotionEffect(type);
entity.addPotionEffects(finalEffects);
}
}

private void modify(ItemType itemType, PotionEffectType[] types, Timespan change, ChangeMode mode) {
for (PotionEffect effect : PotionUtils.getPotionEffects(itemType)) {
for (PotionEffectType type : types) {
if (type.equals(effect.getType())) {
// use SkriptPotionEffect source system to handle removal and application
ExprPotionDuration.changeSafe(SkriptPotionEffect.fromBukkitEffect(effect, itemType), change, mode);
break;
}
}
}
}

@Override
public boolean isSingle() {
return types.isSingle() && !state.includesHidden();
Expand All @@ -272,7 +142,7 @@ public String toString(@Nullable Event event, boolean debug) {
}

@ApiStatus.Internal
public State getState() {
public RetrievalState getState() {
return state;
}

Expand Down
Loading
Loading