BetterTridents/src/main/java/de/jeff_media/bettertridents/tasks/WatchTrident.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();
}
}
}