From 9805d9df718dea5bd23abbb5796765cb82671128 Mon Sep 17 00:00:00 2001
From: Spigot <noreply+git-spigot@papermc.io>
Date: Sat, 15 Jun 2013 19:10:13 +1000
Subject: [PATCH] Implemented Bukkit and CraftBukkit pulls #859 and #1137
 respectively

By: Andy Shulman <andy.shulman@hotmail.com>
---
 ...titySpawnEvent-and-SpawnerSpawnEvent.patch | 220 ++++++++++++++++++
 .../0053-Implement-SpawnerSpawnEvent.patch    | 103 ++++++++
 2 files changed, 323 insertions(+)
 create mode 100644 Bukkit-Patches/0009-Define-EntitySpawnEvent-and-SpawnerSpawnEvent.patch
 create mode 100644 CraftBukkit-Patches/0053-Implement-SpawnerSpawnEvent.patch

diff --git a/Bukkit-Patches/0009-Define-EntitySpawnEvent-and-SpawnerSpawnEvent.patch b/Bukkit-Patches/0009-Define-EntitySpawnEvent-and-SpawnerSpawnEvent.patch
new file mode 100644
index 0000000000..915c9d7565
--- /dev/null
+++ b/Bukkit-Patches/0009-Define-EntitySpawnEvent-and-SpawnerSpawnEvent.patch
@@ -0,0 +1,220 @@
+From 7721d6589c0ef0abdd8077125c3798a56215d42f Mon Sep 17 00:00:00 2001
+From: Andy Shulman <andy.shulman@hotmail.com>
+Date: Mon, 15 Apr 2013 20:06:01 -0500
+Subject: [PATCH] Define EntitySpawnEvent and SpawnerSpawnEvent
+
+Defines EntitySpawnEvent and SpawnerSpawnEvent. Adds BUKKIT-267 and BUKKIT-1559
+
+diff --git a/src/main/java/org/bukkit/event/entity/CreatureSpawnEvent.java b/src/main/java/org/bukkit/event/entity/CreatureSpawnEvent.java
+index 24c4ebf..ed9c4a0 100644
+--- a/src/main/java/org/bukkit/event/entity/CreatureSpawnEvent.java
++++ b/src/main/java/org/bukkit/event/entity/CreatureSpawnEvent.java
+@@ -4,17 +4,13 @@ import org.bukkit.Location;
+ import org.bukkit.entity.CreatureType;
+ import org.bukkit.entity.Entity;
+ import org.bukkit.entity.LivingEntity;
+-import org.bukkit.event.Cancellable;
+-import org.bukkit.event.HandlerList;
+ 
+ /**
+  * Called when a creature is spawned into a world.
+  * <p>
+  * If a Creature Spawn event is cancelled, the creature will not spawn.
+  */
+-public class CreatureSpawnEvent extends EntityEvent implements Cancellable {
+-    private static final HandlerList handlers = new HandlerList();
+-    private boolean canceled;
++public class CreatureSpawnEvent extends EntitySpawnEvent {
+     private final SpawnReason spawnReason;
+ 
+     public CreatureSpawnEvent(final LivingEntity spawnee, final SpawnReason spawnReason) {
+@@ -28,29 +24,12 @@ public class CreatureSpawnEvent extends EntityEvent implements Cancellable {
+         spawnReason = reason;
+     }
+ 
+-    public boolean isCancelled() {
+-        return canceled;
+-    }
+-
+-    public void setCancelled(boolean cancel) {
+-        canceled = cancel;
+-    }
+-
+     @Override
+     public LivingEntity getEntity() {
+         return (LivingEntity) entity;
+     }
+ 
+     /**
+-     * Gets the location at which the creature is spawning.
+-     *
+-     * @return The location at which the creature is spawning
+-     */
+-    public Location getLocation() {
+-        return getEntity().getLocation();
+-    }
+-
+-    /**
+      * Gets the type of creature being spawned.
+      *
+      * @return A CreatureType value detailing the type of creature being spawned
+@@ -70,15 +49,6 @@ public class CreatureSpawnEvent extends EntityEvent implements Cancellable {
+         return spawnReason;
+     }
+ 
+-    @Override
+-    public HandlerList getHandlers() {
+-        return handlers;
+-    }
+-
+-    public static HandlerList getHandlerList() {
+-        return handlers;
+-    }
+-
+     /**
+      * An enum to specify the type of spawning
+      */
+diff --git a/src/main/java/org/bukkit/event/entity/EntitySpawnEvent.java b/src/main/java/org/bukkit/event/entity/EntitySpawnEvent.java
+new file mode 100644
+index 0000000..5dcf98f
+--- /dev/null
++++ b/src/main/java/org/bukkit/event/entity/EntitySpawnEvent.java
+@@ -0,0 +1,45 @@
++package org.bukkit.event.entity;
++
++import org.bukkit.Location;
++import org.bukkit.entity.Entity;
++import org.bukkit.event.HandlerList;
++
++/**
++ * Called when an entity is spawned into a world.
++ * <p>
++ * If an Entity Spawn event is cancelled, the entity will not spawn.
++ */
++public class EntitySpawnEvent extends EntityEvent implements org.bukkit.event.Cancellable {
++    private static final HandlerList handlers = new HandlerList();
++    private boolean canceled;
++
++    public EntitySpawnEvent(final Entity spawnee) {
++        super(spawnee);
++    }
++
++    public boolean isCancelled() {
++        return canceled;
++    }
++
++    public void setCancelled(boolean cancel) {
++        canceled = cancel;
++    }
++
++    /**
++     * Gets the location at which the entity is spawning.
++     *
++     * @return The location at which the entity is spawning
++     */
++    public Location getLocation() {
++        return getEntity().getLocation();
++    }
++
++    @Override
++    public HandlerList getHandlers() {
++        return handlers;
++    }
++
++    public static HandlerList getHandlerList() {
++        return handlers;
++    }
++}
+diff --git a/src/main/java/org/bukkit/event/entity/ItemSpawnEvent.java b/src/main/java/org/bukkit/event/entity/ItemSpawnEvent.java
+index bafd934..776f8e7 100644
+--- a/src/main/java/org/bukkit/event/entity/ItemSpawnEvent.java
++++ b/src/main/java/org/bukkit/event/entity/ItemSpawnEvent.java
+@@ -1,51 +1,23 @@
+ package org.bukkit.event.entity;
+ 
+-import org.bukkit.entity.Item;
+ import org.bukkit.Location;
+-import org.bukkit.event.Cancellable;
+-import org.bukkit.event.HandlerList;
++import org.bukkit.entity.Item;
+ 
+ /**
+  * Called when an item is spawned into a world
+  */
+-public class ItemSpawnEvent extends EntityEvent implements Cancellable {
+-    private static final HandlerList handlers = new HandlerList();
+-    private final Location location;
+-    private boolean canceled;
+-
+-    public ItemSpawnEvent(final Item spawnee, final Location loc) {
++public class ItemSpawnEvent extends EntitySpawnEvent {
++    public ItemSpawnEvent(final Item spawnee) {
+         super(spawnee);
+-        this.location = loc;
+     }
+ 
+-    public boolean isCancelled() {
+-        return canceled;
+-    }
+-
+-    public void setCancelled(boolean cancel) {
+-        canceled = cancel;
++    @Deprecated
++    public ItemSpawnEvent(final Item spawnee, final Location loc) {
++        this(spawnee);
+     }
+ 
+     @Override
+     public Item getEntity() {
+         return (Item) entity;
+     }
+-
+-    /**
+-     * Gets the location at which the item is spawning.
+-     *
+-     * @return The location at which the item is spawning
+-     */
+-    public Location getLocation() {
+-        return location;
+-    }
+-
+-    @Override
+-    public HandlerList getHandlers() {
+-        return handlers;
+-    }
+-
+-    public static HandlerList getHandlerList() {
+-        return handlers;
+-    }
+ }
+diff --git a/src/main/java/org/bukkit/event/entity/SpawnerSpawnEvent.java b/src/main/java/org/bukkit/event/entity/SpawnerSpawnEvent.java
+new file mode 100644
+index 0000000..1acb3c4
+--- /dev/null
++++ b/src/main/java/org/bukkit/event/entity/SpawnerSpawnEvent.java
+@@ -0,0 +1,22 @@
++package org.bukkit.event.entity;
++
++import org.bukkit.block.CreatureSpawner;
++import org.bukkit.entity.Entity;
++
++/**
++ * Called when an entity is spawned into a world by a spawner.
++ * <p>
++ * If a Spawner Spawn event is cancelled, the entity will not spawn.
++ */
++public class SpawnerSpawnEvent extends EntitySpawnEvent {
++    private final CreatureSpawner spawner;
++
++    public SpawnerSpawnEvent(final Entity spawnee, final CreatureSpawner spawner) {
++        super(spawnee);
++        this.spawner = spawner;
++    }
++
++    public CreatureSpawner getSpawner() {
++        return spawner;
++    }
++}
+-- 
+1.8.1.2
+
diff --git a/CraftBukkit-Patches/0053-Implement-SpawnerSpawnEvent.patch b/CraftBukkit-Patches/0053-Implement-SpawnerSpawnEvent.patch
new file mode 100644
index 0000000000..7188935ce8
--- /dev/null
+++ b/CraftBukkit-Patches/0053-Implement-SpawnerSpawnEvent.patch
@@ -0,0 +1,103 @@
+From 462f9dc0b2a9667fcac966fdc931fc0c27d334d0 Mon Sep 17 00:00:00 2001
+From: Andy Shulman <andy.shulman@hotmail.com>
+Date: Mon, 15 Apr 2013 20:06:37 -0500
+Subject: [PATCH] Implement SpawnerSpawnEvent.
+
+Adds BUKKIT-267
+
+diff --git a/src/main/java/net/minecraft/server/MobSpawnerAbstract.java b/src/main/java/net/minecraft/server/MobSpawnerAbstract.java
+index 4ba4735..d860c88 100644
+--- a/src/main/java/net/minecraft/server/MobSpawnerAbstract.java
++++ b/src/main/java/net/minecraft/server/MobSpawnerAbstract.java
+@@ -5,7 +5,11 @@ import java.util.Collection;
+ import java.util.Iterator;
+ import java.util.List;
+ 
+-import org.bukkit.event.entity.CreatureSpawnEvent; // CraftBukkit
++// CraftBukkit start
++import org.bukkit.craftbukkit.event.CraftEventFactory;
++import org.bukkit.event.entity.CreatureSpawnEvent;
++import org.bukkit.event.entity.SpawnerSpawnEvent;
++// CraftBukkit end
+ 
+ public abstract class MobSpawnerAbstract {
+ 
+@@ -127,7 +131,12 @@ public abstract class MobSpawnerAbstract {
+ 
+             entity.f(nbttagcompound);
+             if (entity.world != null) {
+-                entity.world.addEntity(entity, CreatureSpawnEvent.SpawnReason.SPAWNER); // CraftBukkit
++                // CraftBukkit start - call SpawnerSpawnEvent, abort if cancelled
++                SpawnerSpawnEvent event = CraftEventFactory.callSpawnerSpawnEvent(entity, this.b(), this.c(), this.d());
++                if (!event.isCancelled()) {
++                    entity.world.addEntity(entity, CreatureSpawnEvent.SpawnReason.SPAWNER);
++                }
++                // CraftBukkit end
+             }
+ 
+             NBTTagCompound nbttagcompound1;
+@@ -150,6 +159,12 @@ public abstract class MobSpawnerAbstract {
+ 
+                     entity2.f(nbttagcompound2);
+                     entity2.setPositionRotation(entity1.locX, entity1.locY, entity1.locZ, entity1.yaw, entity1.pitch);
++                    // CraftBukkit start - call SpawnerSpawnEvent, skip if cancelled
++                    SpawnerSpawnEvent event = CraftEventFactory.callSpawnerSpawnEvent(entity2, this.b(), this.c(), this.d());
++                    if (event.isCancelled()) {
++                        continue;
++                    }
++                    // CraftBukkit end
+                     this.a().addEntity(entity2, CreatureSpawnEvent.SpawnReason.SPAWNER); // CraftBukkit);
+                     entity1.mount(entity2);
+                 }
+@@ -158,7 +173,12 @@ public abstract class MobSpawnerAbstract {
+             }
+         } else if (entity instanceof EntityLiving && entity.world != null) {
+             ((EntityLiving) entity).bJ();
+-            this.a().addEntity(entity, CreatureSpawnEvent.SpawnReason.SPAWNER); // CraftBukkit);
++            // CraftBukkit start - call SpawnerSpawnEvent, abort if cancelled
++            SpawnerSpawnEvent event = CraftEventFactory.callSpawnerSpawnEvent(entity, this.b(), this.c(), this.d());
++            if (!event.isCancelled()) {
++                this.a().addEntity(entity, CreatureSpawnEvent.SpawnReason.SPAWNER);
++            }
++            // CraftBukkit end
+         }
+ 
+         return entity;
+diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+index 2b56c75..4ba43a0 100644
+--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+@@ -34,6 +34,7 @@ import org.bukkit.Material;
+ import org.bukkit.block.Block;
+ import org.bukkit.block.BlockFace;
+ import org.bukkit.block.BlockState;
++import org.bukkit.block.CreatureSpawner;
+ import org.bukkit.craftbukkit.CraftServer;
+ import org.bukkit.craftbukkit.CraftWorld;
+ import org.bukkit.craftbukkit.block.CraftBlock;
+@@ -115,6 +116,22 @@ public class CraftEventFactory {
+     }
+ 
+     /**
++     * Mob spawner event
++     */
++    public static SpawnerSpawnEvent callSpawnerSpawnEvent(Entity spawnee, int spawnerX, int spawnerY, int spawnerZ) {
++        org.bukkit.craftbukkit.entity.CraftEntity entity = spawnee.getBukkitEntity();
++        BlockState state = entity.getWorld().getBlockAt(spawnerX, spawnerY, spawnerZ).getState();
++
++        if (!(state instanceof CreatureSpawner)) {
++            state = null;
++        }
++
++        SpawnerSpawnEvent event = new SpawnerSpawnEvent(entity, (CreatureSpawner) state);
++        entity.getServer().getPluginManager().callEvent(event);
++        return event;
++    }
++
++    /**
+      * Bucket methods
+      */
+     public static PlayerBucketEmptyEvent callPlayerBucketEmptyEvent(EntityHuman who, int clickedX, int clickedY, int clickedZ, int clickedFace, ItemStack itemInHand) {
+-- 
+1.8.1.2
+