diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/TeleportWarmupTimerTask.java b/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/TeleportWarmupTimerTask.java index fcf0c11c1e2..1f909aed96b 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/TeleportWarmupTimerTask.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/tasks/TeleportWarmupTimerTask.java @@ -13,19 +13,21 @@ import com.palmergames.bukkit.towny.object.Translatable; import com.palmergames.bukkit.towny.object.Translation; import com.palmergames.bukkit.towny.object.economy.Account; +import com.palmergames.bukkit.towny.utils.SpawnUtil; import com.palmergames.bukkit.util.BukkitTools; -import io.papermc.lib.PaperLib; - import org.bukkit.Location; import org.bukkit.NamespacedKey; +import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Collection; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -64,8 +66,11 @@ public void run() { // Only teleport & add cooldown if player is valid if (player == null) continue; + + Collection entities = SpawnUtil.getPets(player); + entities.add(player); - PaperLib.teleportAsync(player, request.destinationLocation(), TeleportCause.COMMAND); + SpawnUtil.teleportEntities(request.destinationLocation(), entities, TeleportCause.COMMAND); if (request.cooldown() > 0) CooldownTimerTask.addCooldownTimer(resident.getName(), "teleport", request.cooldown()); diff --git a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/SpawnUtil.java b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/SpawnUtil.java index 854965fc89a..0b6551f6184 100644 --- a/Towny/src/main/java/com/palmergames/bukkit/towny/utils/SpawnUtil.java +++ b/Towny/src/main/java/com/palmergames/bukkit/towny/utils/SpawnUtil.java @@ -1,5 +1,7 @@ package com.palmergames.bukkit.towny.utils; +import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.Locale; import java.util.Objects; @@ -19,7 +21,11 @@ import io.papermc.lib.PaperLib; import org.bukkit.Bukkit; import org.bukkit.Location; +import org.bukkit.entity.AnimalTamer; +import org.bukkit.entity.Entity; import org.bukkit.entity.Player; +import org.bukkit.entity.Sittable; +import org.bukkit.entity.Tameable; import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; import com.palmergames.bukkit.towny.Towny; @@ -669,12 +675,59 @@ private static void initiateSpawn(Player player, Location spawnLoc, int cooldown // Don't use teleport warmup if (player.getVehicle() != null) player.getVehicle().eject(); - PaperLib.teleportAsync(player, spawnLoc, TeleportCause.COMMAND); + + Collection entities = getPets(player); + entities.add(player); + + teleportEntities(spawnLoc, entities, TeleportCause.COMMAND); if (cooldown > 0 && !hasPerm(player, PermissionNodes.TOWNY_SPAWN_ADMIN_NOCOOLDOWN)) CooldownTimerTask.addCooldownTimer(player.getName(), "teleport", cooldown); } } + /** + * Gets any conventional following/sittable pets owned by the specified player that are nearby them + * + * @param player The player to get the pets of + */ + public static Collection getPets(Player player) { + List pets = new ArrayList<>(); + + Collection entities = player.getWorld().getNearbyEntities( + player.getLocation(), + 16, 16, 16, + e -> e instanceof Tameable + ); + + for (Entity entity : entities) { + Tameable tameable = (Tameable) entity; + + AnimalTamer tamer = tameable.getOwner(); + if (tamer == null) continue; + + if (!(entity instanceof Sittable sittable)) continue; + if (sittable.isSitting()) continue; + + if (tamer.equals(player)) + pets.add(entity); + } + + return pets; + } + + /** + * Teleports all specified entities to the specified location + * + * @param loc Location to teleport to + * @param entities Entities to teleport + * @param cause What caused the teleport + */ + public static void teleportEntities(Location loc, Iterable entities, TeleportCause cause) { + for (Entity entity : entities) { + PaperLib.teleportAsync(entity, loc, cause); + } + } + /** * Begin a costed teleportation. * @@ -745,8 +798,11 @@ private static void initiatePluginTeleport(Resident resident, Location loc, bool final Player player = resident.getPlayer(); if (player == null) return; + + List pets = getPets(player); + pets.add(player); - plugin.getScheduler().runLater(player, () -> PaperLib.teleportAsync(resident.getPlayer(), loc, TeleportCause.PLUGIN), + plugin.getScheduler().runLater(player, () -> teleportEntities(loc, pets, TeleportCause.PLUGIN), ignoreWarmup ? 0 : TownySettings.getTeleportWarmupTime() * 20L); }