108 lines
3.3 KiB
Java
108 lines
3.3 KiB
Java
package de.jeff_media.bettertridents.tasks;
|
|
|
|
import com.jeff_media.jefflib.WorldUtils;
|
|
import de.jeff_media.bettertridents.Main;
|
|
import com.jeff_media.jefflib.ReflUtils;
|
|
import org.bukkit.Location;
|
|
import org.bukkit.Material;
|
|
import org.bukkit.entity.Trident;
|
|
import org.bukkit.scheduler.BukkitRunnable;
|
|
import org.bukkit.util.Vector;
|
|
|
|
import java.lang.reflect.Field;
|
|
import java.lang.reflect.Method;
|
|
|
|
public class WatchTrident extends BukkitRunnable {
|
|
|
|
private static final int MAX_TICKS = 1200;
|
|
private static Field damageDealtField;
|
|
private static Method getHandleMethod;
|
|
|
|
static {
|
|
int fieldCount = 0;
|
|
Class<?> entityThrownTridentClass = null;
|
|
try {
|
|
entityThrownTridentClass = ReflUtils.getNMSClass("EntityThrownTrident");
|
|
} catch (Throwable ignored) {
|
|
// 1.17+
|
|
}
|
|
|
|
try {
|
|
if(entityThrownTridentClass == null) {
|
|
// 1.17+
|
|
entityThrownTridentClass = Class.forName("net.minecraft.world.entity.projectile.EntityThrownTrident");
|
|
}
|
|
getHandleMethod = ReflUtils.getOBCClass("entity.CraftTrident").getMethod("getHandle");
|
|
for (Field field : entityThrownTridentClass.getDeclaredFields()) {
|
|
if (field.getType() == Boolean.TYPE) {
|
|
damageDealtField = field;
|
|
damageDealtField.setAccessible(true);
|
|
fieldCount++;
|
|
}
|
|
}
|
|
} catch (Exception e) {
|
|
damageDealtField = null;
|
|
getHandleMethod = null;
|
|
//e.printStackTrace();
|
|
}
|
|
|
|
if (fieldCount == 1) {
|
|
Main.getInstance().debug("Tridents will be rescued using reflection (Field: " + damageDealtField.getName() + ")");
|
|
} else {
|
|
damageDealtField = null;
|
|
Main.getInstance().debug("Tridents will be rescued using the legacy setBlock method");
|
|
}
|
|
}
|
|
|
|
private final Trident trident;
|
|
private int ticks = 0;
|
|
|
|
public WatchTrident(Trident trident) {
|
|
this.trident = trident;
|
|
}
|
|
|
|
private void legacyRescue() {
|
|
Location nextLocation = trident.getLocation().add(trident.getVelocity());
|
|
|
|
if (nextLocation.getBlockY() > 1) return;
|
|
if (!nextLocation.getBlock().getType().isAir()) return;
|
|
|
|
if (nextLocation.getBlockY() < 0) {
|
|
nextLocation.setY(0);
|
|
trident.teleport(nextLocation.clone().add(0, 1, 0));
|
|
trident.setVelocity(new Vector(0, -1, 0));
|
|
}
|
|
|
|
nextLocation.getBlock().setType(Material.BARRIER);
|
|
new RemoveBarrier(trident, nextLocation.getBlock()).runTaskTimer(Main.getInstance(), 1, 1);
|
|
cancel();
|
|
}
|
|
|
|
private void rescue() {
|
|
if (trident.getLocation().getY() >= WorldUtils.getWorldMinHeight(trident.getWorld()) - 20) return;
|
|
try {
|
|
damageDealtField.set(getHandleMethod.invoke(trident), true);
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
cancel();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void run() {
|
|
|
|
ticks++;
|
|
if (ticks >= MAX_TICKS || trident == null || trident.isDead() || !trident.isValid() || trident.getVelocity().length() == 0) {
|
|
cancel();
|
|
return;
|
|
}
|
|
|
|
if (damageDealtField != null) {
|
|
rescue();
|
|
} else {
|
|
legacyRescue();
|
|
}
|
|
|
|
}
|
|
}
|