diff --git a/src/main/java/me/youhavetrouble/preventstabby/PreventStabby.java b/src/main/java/me/youhavetrouble/preventstabby/PreventStabby.java index f27a037..3aa6acc 100644 --- a/src/main/java/me/youhavetrouble/preventstabby/PreventStabby.java +++ b/src/main/java/me/youhavetrouble/preventstabby/PreventStabby.java @@ -7,6 +7,7 @@ import me.youhavetrouble.preventstabby.hooks.WorldGuardHook; import me.youhavetrouble.preventstabby.data.PlayerListener; import me.youhavetrouble.preventstabby.data.PlayerManager; import me.youhavetrouble.preventstabby.listeners.PlayerDamageListener; +import me.youhavetrouble.preventstabby.listeners.UtilListener; import me.youhavetrouble.preventstabby.util.*; import org.bstats.bukkit.Metrics; import org.bukkit.command.CommandSender; @@ -32,6 +33,7 @@ public final class PreventStabby extends JavaPlugin { playerManager = new PlayerManager(this); // Register listeners TODO + getServer().getPluginManager().registerEvents(new UtilListener(), this); getServer().getPluginManager().registerEvents(new PlayerListener(), this); getServer().getPluginManager().registerEvents(new PlayerDamageListener(this), this); diff --git a/src/main/java/me/youhavetrouble/preventstabby/data/Target.java b/src/main/java/me/youhavetrouble/preventstabby/data/Target.java index 3fedecd..69abaa7 100644 --- a/src/main/java/me/youhavetrouble/preventstabby/data/Target.java +++ b/src/main/java/me/youhavetrouble/preventstabby/data/Target.java @@ -1,9 +1,13 @@ package me.youhavetrouble.preventstabby.data; +import org.bukkit.NamespacedKey; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.entity.Projectile; import org.bukkit.entity.Tameable; +import org.bukkit.persistence.PersistentDataContainer; +import org.bukkit.persistence.PersistentDataHolder; +import org.bukkit.persistence.PersistentDataType; import org.jetbrains.annotations.NotNull; import javax.annotation.Nullable; @@ -11,6 +15,8 @@ import java.util.UUID; public class Target { + public static final NamespacedKey playerSourceIdKey = new NamespacedKey("preventstabby", "playerSource"); + /** * The unique identifier for a player. */ @@ -59,7 +65,27 @@ public class Target { } } - return null; + // Try to get player's id from other various entities + PersistentDataContainer pdc = entity.getPersistentDataContainer(); + if (!pdc.has(playerSourceIdKey)) return null; + String id = pdc.get(playerSourceIdKey, PersistentDataType.STRING); + if (id == null) return null; + try { + UUID uuid = UUID.fromString(id); + return new Target(uuid, EntityClassifier.OTHER); + } catch (Exception e) { + return null; + } + + } + + /** + * Assigns the player source ID to the given data holder. + * @param dataHolder The persistent data holder to assign the player source ID to. + * @param id The UUID of the player source ID to assign. + */ + public static void assignPlayerSourceId(@NotNull PersistentDataHolder dataHolder, @NotNull UUID id) { + dataHolder.getPersistentDataContainer().set(playerSourceIdKey, PersistentDataType.STRING, id.toString()); } public enum EntityClassifier { diff --git a/src/main/java/me/youhavetrouble/preventstabby/listeners/UtilListener.java b/src/main/java/me/youhavetrouble/preventstabby/listeners/UtilListener.java new file mode 100644 index 0000000..a23fb46 --- /dev/null +++ b/src/main/java/me/youhavetrouble/preventstabby/listeners/UtilListener.java @@ -0,0 +1,76 @@ +package me.youhavetrouble.preventstabby.listeners; + +import me.youhavetrouble.preventstabby.data.Target; +import org.bukkit.entity.EnderCrystal; +import org.bukkit.entity.Player; +import org.bukkit.entity.Projectile; +import org.bukkit.entity.TNTPrimed; +import org.bukkit.entity.minecart.ExplosiveMinecart; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityPlaceEvent; +import org.bukkit.event.entity.ExplosionPrimeEvent; +import org.bukkit.event.vehicle.VehicleEntityCollisionEvent; + +/** + * This class is a listener that performs various operations related to tagging entities with player UUIDs. + */ +public class UtilListener implements Listener { + + /** + * Tag TNT minecart with uuid of player who placed it + */ + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onPlayerPlacedTntMinecart(EntityPlaceEvent event) { + if (!(event.getEntity() instanceof ExplosiveMinecart minecart)) return; + if (event.getPlayer() == null) return; + Target.assignPlayerSourceId(minecart, event.getPlayer().getUniqueId()); + } + + /** + * Tag TNT minecart with uuid of player who last nudged it + */ + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onPlayerNudgedTntMinecart(VehicleEntityCollisionEvent event) { + if (!(event.getVehicle() instanceof ExplosiveMinecart minecart)) return; + if (!(event.getEntity() instanceof Player player)) return; + Target.assignPlayerSourceId(minecart, player.getUniqueId()); + } + + /** + * Tag primed TNT with players uuid + */ + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onPlayerPrimedTnt(ExplosionPrimeEvent event) { + if (!(event.getEntity() instanceof TNTPrimed tntPrimed)) return; + if (tntPrimed.getSource() instanceof TNTPrimed primingTnt) { + Target primingTntTarget = Target.getTarget(primingTnt); + if (primingTntTarget == null) return; + Target.assignPlayerSourceId(tntPrimed, primingTntTarget.playerUuid); + return; + } + if (tntPrimed.getSource() instanceof Player primingPlayer) { + Target.assignPlayerSourceId(tntPrimed, primingPlayer.getUniqueId()); + return; + } + } + + /** + * Tags ender crystal with exploding players uuid + */ + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onPlayerHitEnderCrystal(EntityDamageByEntityEvent event) { + if (!(event.getEntity() instanceof EnderCrystal enderCrystal)) return; + if (event.getDamager() instanceof Player player) { + Target.assignPlayerSourceId(enderCrystal, player.getUniqueId()); + return; + } + if (event.getDamager() instanceof Projectile projectile && projectile.getShooter() instanceof Player player) { + Target.assignPlayerSourceId(enderCrystal, player.getUniqueId()); + return; + } + } + +}