From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Sat, 4 May 2019 00:57:16 -0500
Subject: [PATCH] Ridables


diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/VanillaGoal.java b/src/main/java/com/destroystokyo/paper/entity/ai/VanillaGoal.java
index 83c51bb5e09549a8205d27a53ff0102f9439d60a..177143c9764e82981423879ed35625edd25d3ebf 100644
--- a/src/main/java/com/destroystokyo/paper/entity/ai/VanillaGoal.java
+++ b/src/main/java/com/destroystokyo/paper/entity/ai/VanillaGoal.java
@@ -209,5 +209,7 @@ public interface VanillaGoal<T extends Mob> extends Goal<T> {
     // Purpur start
     GoalKey<Phantom> FIND_CRYSTAL_GOAL = GoalKey.of(Phantom.class, NamespacedKey.minecraft("find_crystal_goal"));
     GoalKey<Phantom> ORBIT_CRYSTAL_GOAL = GoalKey.of(Phantom.class, NamespacedKey.minecraft("orbit_crystal_goal"));
+    GoalKey<Mob> HAS_RIDER = GoalKey.of(Mob.class, NamespacedKey.minecraft("has_rider"));
+    GoalKey<AbstractHorse> HORSE_HAS_RIDER = GoalKey.of(AbstractHorse.class, NamespacedKey.minecraft("horse_has_rider"));
     // Purpur end
 }
diff --git a/src/main/java/net/pl3x/purpur/event/entity/RidableMoveEvent.java b/src/main/java/net/pl3x/purpur/event/entity/RidableMoveEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..48e7ac392fe5efac8a4ce549e31a05ed817417e4
--- /dev/null
+++ b/src/main/java/net/pl3x/purpur/event/entity/RidableMoveEvent.java
@@ -0,0 +1,103 @@
+package net.pl3x.purpur.event.entity;
+
+import com.google.common.base.Preconditions;
+import org.bukkit.Location;
+import org.bukkit.entity.Mob;
+import org.bukkit.entity.Player;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.entity.EntityEvent;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Triggered when a ridable mob moves with a rider
+ */
+public class RidableMoveEvent extends EntityEvent implements Cancellable {
+    private static final HandlerList handlers = new HandlerList();
+    private boolean canceled;
+    private final Player rider;
+    private Location from;
+    private Location to;
+
+    public RidableMoveEvent(@NotNull Mob entity, @NotNull Player rider, @NotNull Location from, @NotNull Location to) {
+        super(entity);
+        this.rider = rider;
+        this.from = from;
+        this.to = to;
+    }
+
+    @Override
+    @NotNull
+    public Mob getEntity() {
+        return (Mob) entity;
+    }
+
+    @NotNull
+    public Player getRider() {
+        return rider;
+    }
+
+    public boolean isCancelled() {
+        return canceled;
+    }
+
+    public void setCancelled(boolean cancel) {
+        canceled = cancel;
+    }
+
+    /**
+     * Gets the location this entity moved from
+     *
+     * @return Location the entity moved from
+     */
+    @NotNull
+    public Location getFrom() {
+        return from;
+    }
+
+    /**
+     * Sets the location to mark as where the entity moved from
+     *
+     * @param from New location to mark as the entity's previous location
+     */
+    public void setFrom(@NotNull Location from) {
+        validateLocation(from);
+        this.from = from;
+    }
+
+    /**
+     * Gets the location this entity moved to
+     *
+     * @return Location the entity moved to
+     */
+    @NotNull
+    public Location getTo() {
+        return to;
+    }
+
+    /**
+     * Sets the location that this entity will move to
+     *
+     * @param to New Location this entity will move to
+     */
+    public void setTo(@NotNull Location to) {
+        validateLocation(to);
+        this.to = to;
+    }
+
+    private void validateLocation(@NotNull Location loc) {
+        Preconditions.checkArgument(loc != null, "Cannot use null location!");
+        Preconditions.checkArgument(loc.getWorld() != null, "Cannot use null location with null world!");
+    }
+
+    @Override
+    @NotNull
+    public HandlerList getHandlers() {
+        return handlers;
+    }
+
+    @NotNull
+    public static HandlerList getHandlerList() {
+        return handlers;
+    }
+}
diff --git a/src/main/java/net/pl3x/purpur/event/entity/RidableSpacebarEvent.java b/src/main/java/net/pl3x/purpur/event/entity/RidableSpacebarEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..c0ec5a130985e8da4cc9e596a6b70503d2550f77
--- /dev/null
+++ b/src/main/java/net/pl3x/purpur/event/entity/RidableSpacebarEvent.java
@@ -0,0 +1,37 @@
+package net.pl3x.purpur.event.entity;
+
+import org.bukkit.entity.Entity;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.entity.EntityEvent;
+import org.jetbrains.annotations.NotNull;
+
+public class RidableSpacebarEvent extends EntityEvent implements Cancellable {
+    private static final HandlerList handlers = new HandlerList();
+    private boolean cancelled;
+
+    public RidableSpacebarEvent(@NotNull Entity entity) {
+        super(entity);
+    }
+
+    @Override
+    public boolean isCancelled() {
+        return cancelled;
+    }
+
+    @Override
+    public void setCancelled(boolean cancel) {
+        cancelled = cancel;
+    }
+
+    @Override
+    @NotNull
+    public HandlerList getHandlers() {
+        return handlers;
+    }
+
+    @NotNull
+    public static HandlerList getHandlerList() {
+        return handlers;
+    }
+}
diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java
index 428daeb04d0a35a443467e2f657d2356bcfdd7d7..7dc06b28af9fa45b2b49a6d37c1ed829257f812a 100644
--- a/src/main/java/org/bukkit/entity/Entity.java
+++ b/src/main/java/org/bukkit/entity/Entity.java
@@ -704,4 +704,35 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent
      */
     public boolean isTicking();
     // Paper end
+
+    // Purpur start
+    /**
+     * Get the riding player
+     *
+     * @return Riding player
+     */
+    @Nullable
+    Player getRider();
+
+    /**
+     * Check if entity is being ridden
+     *
+     * @return True if being ridden
+     */
+    boolean hasRider();
+
+    /**
+     * Check if entity is ridable
+     *
+     * @return True if ridable
+     */
+    boolean isRidable();
+
+    /**
+     * Check if entity is ridable in water
+     *
+     * @return True if ridable in water
+     */
+    boolean isRidableInWater();
+    // Purpur end
 }
