BillyGalbreath

Paper Mob Goal API Example

May 10th, 2021 (edited)
816
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2. This is a basic example of Paper's Mob Goal API. It simply adds a new goal
  3. to every villager when they are added to the world. The goal is a simple task
  4. of following the closest player holding an emerald (item, block, or ore).
  5. */
  6.  
  7. import com.destroystokyo.paper.entity.ai.Goal;
  8. import com.destroystokyo.paper.entity.ai.GoalKey;
  9. import com.destroystokyo.paper.entity.ai.GoalType;
  10. import com.destroystokyo.paper.event.entity.EntityAddToWorldEvent;
  11. import org.bukkit.Bukkit;
  12. import org.bukkit.GameMode;
  13. import org.bukkit.NamespacedKey;
  14. import org.bukkit.entity.EntityType;
  15. import org.bukkit.entity.Mob;
  16. import org.bukkit.entity.Player;
  17. import org.bukkit.entity.Villager;
  18. import org.bukkit.event.EventHandler;
  19. import org.bukkit.event.Listener;
  20. import org.bukkit.inventory.ItemStack;
  21. import org.bukkit.inventory.PlayerInventory;
  22. import org.bukkit.plugin.Plugin;
  23. import org.bukkit.plugin.java.JavaPlugin;
  24.  
  25. import java.util.Collection;
  26. import java.util.EnumSet;
  27.  
  28. public final class MyPlugin extends JavaPlugin {
  29.     @Override
  30.     public void onEnable() {
  31.         getServer().getPluginManager().registerEvents(new Listener() {
  32.             @EventHandler
  33.             public void on(EntityAddToWorldEvent event) {
  34.                 if (event.getEntityType() == EntityType.VILLAGER) {
  35.                     Villager villager = (Villager) event.getEntity();
  36.                     FollowEmeraldsGoal goal = new FollowEmeraldsGoal(MyPlugin.this, villager);
  37.                     if (!Bukkit.getMobGoals().hasGoal(villager, goal.getKey())) {
  38.                         Bukkit.getMobGoals().addGoal(villager, 3, goal);
  39.                     }
  40.                 }
  41.             }
  42.         }, this);
  43.     }
  44.  
  45.     public static class FollowEmeraldsGoal implements Goal<Villager> {
  46.         private final GoalKey<Villager> key;
  47.         private final Mob mob;
  48.         private Player closestPlayer;
  49.         private int cooldown;
  50.  
  51.         public FollowEmeraldsGoal(Plugin plugin, Mob mob) {
  52.             this.key = GoalKey.of(Villager.class, new NamespacedKey(plugin, "follow_emeralds"));
  53.             this.mob = mob;
  54.         }
  55.  
  56.         @Override
  57.         public boolean shouldActivate() {
  58.             if (cooldown > 0) {
  59.                 --cooldown;
  60.                 return false;
  61.             }
  62.             closestPlayer = getClosestPlayer();
  63.             if (closestPlayer == null) {
  64.                 return false;
  65.             }
  66.             return isHoldingEmerald(closestPlayer);
  67.         }
  68.  
  69.         @Override
  70.         public boolean shouldStayActive() {
  71.             return shouldActivate();
  72.         }
  73.  
  74.         @Override
  75.         public void start() {
  76.         }
  77.  
  78.         @Override
  79.         public void stop() {
  80.             mob.getPathfinder().stopPathfinding();
  81.             mob.setTarget(null);
  82.             cooldown = 100;
  83.         }
  84.  
  85.         @Override
  86.         public void tick() {
  87.             mob.setTarget(closestPlayer);
  88.             if (mob.getLocation().distanceSquared(closestPlayer.getLocation()) < 6.25) {
  89.                 mob.getPathfinder().stopPathfinding();
  90.             } else {
  91.                 mob.getPathfinder().moveTo(closestPlayer, 1.0D);
  92.             }
  93.         }
  94.  
  95.         @Override
  96.         public GoalKey<Villager> getKey() {
  97.             return key;
  98.         }
  99.  
  100.         @Override
  101.         public EnumSet<GoalType> getTypes() {
  102.             return EnumSet.of(GoalType.MOVE, GoalType.LOOK);
  103.         }
  104.  
  105.         private Player getClosestPlayer() {
  106.             Collection<Player> nearbyPlayers = mob.getWorld().getNearbyPlayers(mob.getLocation(), 10.0, player ->
  107.                     !player.isDead() && player.getGameMode() != GameMode.SPECTATOR && player.isValid());
  108.             double closestDistance = -1.0;
  109.             Player closestPlayer = null;
  110.             for (Player player : nearbyPlayers) {
  111.                 double distance = player.getLocation().distanceSquared(mob.getLocation());
  112.                 if (closestDistance != -1.0 && !(distance < closestDistance)) {
  113.                     continue;
  114.                 }
  115.                 closestDistance = distance;
  116.                 closestPlayer = player;
  117.             }
  118.             return closestPlayer;
  119.         }
  120.  
  121.         private boolean isHoldingEmerald(Player target) {
  122.             PlayerInventory inv = target.getInventory();
  123.             return isEmerald(inv.getItemInMainHand()) || isEmerald(inv.getItemInOffHand());
  124.         }
  125.  
  126.         private boolean isEmerald(ItemStack stack) {
  127.             switch (stack.getType()) {
  128.                 case EMERALD:
  129.                 case EMERALD_BLOCK:
  130.                 case EMERALD_ORE:
  131.                     return true;
  132.                 default:
  133.                     return false;
  134.             }
  135.         }
  136.     }
  137. }
RAW Paste Data