Skip to content
Open
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
2 changes: 1 addition & 1 deletion core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ plugins {
dependencies {
implementation("org.apache.commons:commons-math4-core:4.0-beta1")
implementation("com.github.ben-manes.caffeine:caffeine:3.2.2")
implementation("com.github.Chronoken:EffectLib:1da888c")
implementation("com.github.Chronoken:EffectLib:071cc3c")
implementation("org.incendo:cloud-paper:2.0.0-beta.16")
implementation("org.incendo:cloud-minecraft-extras:2.0.0-beta.16")
implementation("org.incendo:cloud-processors-requirements:1.0.0-rc.1")
Expand Down
39 changes: 27 additions & 12 deletions core/src/main/java/com/nisovin/magicspells/MagicSpells.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@
import java.util.function.Predicate;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.invoke.MethodType;
import java.lang.reflect.Constructor;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.annotation.Annotation;

import java.net.URL;
Expand Down Expand Up @@ -1955,20 +1959,30 @@ public static void registerEvents(final Listener listener, EventPriority customP
}

for (final Method method : methods) {
final EventHandler eh = method.getAnnotation(EventHandler.class);
if (eh == null) continue;
EventPriority priority = eh.priority();
final EventHandler handler = method.getAnnotation(EventHandler.class);
if (handler == null) continue;
EventPriority priority = handler.priority();

if (hasAnnotation(method, OverridePriority.class)) priority = customPriority;

final Class<?> checkClass = method.getParameterTypes()[0];
if (!Event.class.isAssignableFrom(checkClass) || method.getParameterTypes().length != 1) {
final Class<?>[] paramTypes = method.getParameterTypes();
if (paramTypes.length != 1 || !Event.class.isAssignableFrom(paramTypes[0])) {
plugin.getLogger().severe("Wrong method arguments used for event type registered");
continue;
}

final Class<? extends Event> eventClass = checkClass.asSubclass(Event.class);
final Class<? extends Event> eventClass = paramTypes[0].asSubclass(Event.class);
method.setAccessible(true);
final MethodHandle methodHandle;
try {
MethodHandle handle = MethodHandles.privateLookupIn(listener.getClass(), MethodHandles.lookup()).unreflect(method);
if (!Modifier.isStatic(method.getModifiers())) handle = handle.bindTo(listener);
methodHandle = handle.asType(MethodType.methodType(void.class, Event.class));
} catch (IllegalAccessException e) {
plugin.getLogger().severe("Failed to create method handle for " + method.getName() + ": " + e.getMessage());
continue;
}

EventExecutor executor = new EventExecutor() {
final String eventKey = plugin.enableProfiling ? "Event:" + listener.getClass().getName().replace("com.nisovin.magicspells.", "") + '.' + method.getName() + '(' + eventClass.getSimpleName() + ')' : null;

Expand All @@ -1977,23 +1991,24 @@ public void execute(@NotNull Listener listener, @NotNull Event event) {
try {
if (!eventClass.isAssignableFrom(event.getClass())) return;
long start = System.nanoTime();
method.invoke(listener, event);
methodHandle.invokeExact((Event) event);
if (plugin.enableProfiling) {
Long total = plugin.profilingTotalTime.get(eventKey);
if (total == null) total = (long) 0;
if (total == null) total = 0L;
total += System.nanoTime() - start;
plugin.profilingTotalTime.put(eventKey, total);
Integer runs = plugin.profilingRuns.get(eventKey);
if (runs == null) runs = 0;
runs += 1;
runs++;
plugin.profilingRuns.put(eventKey, runs);
}
} catch (Exception ex) {
handleException(ex);
} catch (Throwable ex) {
if (ex instanceof Error e) throw e;
handleException(ex instanceof Exception exception ? exception : new RuntimeException(ex));
}
}
};
Bukkit.getPluginManager().registerEvent(eventClass, listener, priority, executor, plugin, eh.ignoreCancelled());
Bukkit.getPluginManager().registerEvent(eventClass, listener, priority, executor, plugin, handler.ignoreCancelled());
}
}

Expand Down
28 changes: 20 additions & 8 deletions core/src/main/java/com/nisovin/magicspells/Spell.java
Original file line number Diff line number Diff line change
Expand Up @@ -1080,12 +1080,19 @@ public PostCastAction castSpell(LivingEntity caster, SpellCastState state, float
protected SpellCastState getCastState(LivingEntity caster) {
if (caster instanceof Player player && !MagicSpells.getSpellbook(player).canCast(this))
return SpellCastState.CANT_CAST;

if (worldRestrictions != null && !worldRestrictions.contains(caster.getWorld().getName()))
return SpellCastState.WRONG_WORLD;

if (MagicSpells.getNoMagicZoneManager() != null && MagicSpells.getNoMagicZoneManager().willFizzle(caster, this))
return SpellCastState.NO_MAGIC_ZONE;
if (onCooldown(caster)) return SpellCastState.ON_COOLDOWN;
if (!hasReagents(caster)) return SpellCastState.MISSING_REAGENTS;

if (onCooldown(caster))
return SpellCastState.ON_COOLDOWN;

if (!hasReagents(caster))
return SpellCastState.MISSING_REAGENTS;

return SpellCastState.NORMAL;
}

Expand Down Expand Up @@ -1145,7 +1152,7 @@ public SpellCastEvent preCast(@NotNull SpellData data) {
}

if (castEvent.hasSpellCastStateChanged()) debug(2, " Spell cast state changed: " + state);
if (Perm.NO_CAST_TIME.has(data.caster())) castEvent.setCastTime(0);
if (castEvent.getCastTime() > 0 && Perm.NO_CAST_TIME.has(data.caster())) castEvent.setCastTime(0);

return castEvent;
}
Expand Down Expand Up @@ -1331,15 +1338,20 @@ public ConfigData<Float> getCooldown() {
* @return whether the spell is on cooldown
*/
public boolean onCooldown(LivingEntity livingEntity) {
if (Perm.NO_COOLDOWN.has(livingEntity)) return false;
return hasActiveCooldown(livingEntity) && !Perm.NO_COOLDOWN.has(livingEntity);
}

ChargeState state = chargeStates.get(livingEntity.getUniqueId());
private boolean hasActiveCooldown(LivingEntity livingEntity) {
UUID uuid = livingEntity.getUniqueId();
long timeMillis = System.currentTimeMillis();

ChargeState state = chargeStates.get(uuid);
if (state != null && state.isDepleted()) return true;

if (serverCooldown > 0 && nextCastServer > System.currentTimeMillis()) return true;
if (serverCooldown > 0 && nextCastServer > timeMillis) return true;

Long next = nextCast.get(livingEntity.getUniqueId());
return next != null && next > System.currentTimeMillis();
Long next = nextCast.get(uuid);
return next != null && next > timeMillis;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,22 @@ public void onSpellTarget(SpellTargetEvent event) {
// Check if target has noTarget permission / is in noMagicZone / is an invisible marker armorstand
LivingEntity target = event.getTarget();
Spell spell = event.getSpell();
if (target == null) return;

if (Perm.NO_TARGET.has(target)) event.setCancelled(true);
if (spell != null && noMagicZoneManager != null && noMagicZoneManager.willFizzle(target, spell)) event.setCancelled(true);
if (isMSEntity(target)) event.setCancelled(true);
if (target == null)
return;

if (isMSEntity(target)) {
event.setCancelled(true);
return;
}

if (Perm.NO_TARGET.has(target)) {
event.setCancelled(true);
return;
}

if (spell != null && noMagicZoneManager != null && noMagicZoneManager.willFizzle(target, spell))
event.setCancelled(true);
}

@EventHandler
Expand Down
14 changes: 10 additions & 4 deletions core/src/main/java/com/nisovin/magicspells/util/SpellUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,7 @@ public static boolean hasReagents(LivingEntity livingEntity, SpellReagents reage
* @return true if the player has all the reagents, false otherwise
*/
public static boolean hasReagents(LivingEntity livingEntity, SpellReagents.ReagentItem[] reagents, double healthCost, int manaCost, int hungerCost, int experienceCost, int levelsCost, int durabilityCost, float moneyCost, Map<String, Double> variables) {
// Is the livingEntity exempt from reagent costs?
if (Perm.NO_REAGENTS.has(livingEntity)) return true;
if (!hasCosts(reagents, healthCost, manaCost, hungerCost, experienceCost, levelsCost, durabilityCost, moneyCost, variables) || Perm.NO_REAGENTS.has(livingEntity)) return true;

// player reagents
if (livingEntity instanceof Player player) {
Expand Down Expand Up @@ -102,7 +101,7 @@ public static boolean hasReagents(LivingEntity livingEntity, SpellReagents.Reage
// Health costs
if (healthCost > 0 && livingEntity.getHealth() <= healthCost) return false;

// Durabilty costs
// Durability costs
if (durabilityCost > 0) {
// Durability cost is charged from the main hand item
EntityEquipment equipment = livingEntity.getEquipment();
Expand Down Expand Up @@ -134,6 +133,13 @@ public static boolean hasReagents(LivingEntity livingEntity, SpellReagents.Reage
return true;
}

private static boolean hasCosts(SpellReagents.ReagentItem[] reagents, double healthCost, int manaCost, int hungerCost, int experienceCost, int levelsCost, int durabilityCost, float moneyCost, Map<String, Double> variables) {
return (reagents != null && reagents.length > 0)
|| healthCost != 0 || manaCost != 0 || hungerCost != 0
|| experienceCost != 0 || levelsCost != 0 || durabilityCost != 0
|| moneyCost != 0 || (variables != null && !variables.isEmpty());
}

public static void removeReagents(LivingEntity livingEntity, SpellReagents reagents) {
removeReagents(livingEntity, reagents.getItemsAsArray(), reagents.getHealth(), reagents.getMana(), reagents.getHunger(), reagents.getExperience(), reagents.getLevels(), reagents.getDurability(), reagents.getMoney(), reagents.getVariables());
}
Expand All @@ -147,7 +153,7 @@ public static void removeReagents(LivingEntity livingEntity, SpellReagents reage
* @param manaCost the mana to remove
*/
public static void removeReagents(LivingEntity livingEntity, SpellReagents.ReagentItem[] reagents, double healthCost, int manaCost, int hungerCost, int experienceCost, int levelsCost, int durabilityCost, float moneyCost, Map<String, Double> variables) {
if (Perm.NO_REAGENTS.has(livingEntity)) return;
if (!hasCosts(reagents, healthCost, manaCost, hungerCost, experienceCost, levelsCost, durabilityCost, moneyCost, variables) || Perm.NO_REAGENTS.has(livingEntity)) return;

if (reagents != null) {
for (SpellReagents.ReagentItem item : reagents) {
Expand Down
Loading