diff --git a/Spigot-API-Patches/Improve-death-events.patch b/Spigot-API-Patches/Improve-death-events.patch
new file mode 100644
index 0000000000..63c744285f
--- /dev/null
+++ b/Spigot-API-Patches/Improve-death-events.patch
@@ -0,0 +1,175 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Phoenix616 <mail@moep.tv>
+Date: Tue, 21 Aug 2018 01:32:28 +0100
+Subject: [PATCH] Improve death events
+
+This adds the ability to cancel the death events and to modify the sound
+an entity makes when dying. (In cases were no sound should it will be
+called with shouldPlaySound set to false allowing unsilencing of silent
+entities)
+
+It makes handling of entity deaths a lot nicer as you no longer need
+to listen on the damage event and calculate if the entity dies yourself
+to cancel the death which has the benefit of also receiving the dropped
+items and experience which is otherwise only properly possible by using
+internal code.
+
+diff --git a/src/main/java/org/bukkit/event/entity/EntityDeathEvent.java b/src/main/java/org/bukkit/event/entity/EntityDeathEvent.java
+index ab9e81fd..a7b8f869 100644
+--- a/src/main/java/org/bukkit/event/entity/EntityDeathEvent.java
++++ b/src/main/java/org/bukkit/event/entity/EntityDeathEvent.java
+@@ -0,0 +0,0 @@ import org.bukkit.inventory.ItemStack;
+ /**
+  * Thrown whenever a LivingEntity dies
+  */
+-public class EntityDeathEvent extends EntityEvent {
++public class EntityDeathEvent extends EntityEvent implements org.bukkit.event.Cancellable {  // Paper - make cancellable
+     private static final HandlerList handlers = new HandlerList();
+     private final List<ItemStack> drops;
+     private int dropExp = 0;
++    // Paper start - make cancellable
++    private boolean cancelled;
++    private double reviveHealth = 0;
++    private boolean shouldPlayDeathSound;
++    private org.bukkit.Sound deathSound;
++    private org.bukkit.SoundCategory deathSoundCategory;
++    private float deathSoundVolume;
++    private float deathSoundPitch;
++    // Paper end
+ 
+     public EntityDeathEvent(final LivingEntity entity, final List<ItemStack> drops) {
+         this(entity, drops, 0);
+@@ -0,0 +0,0 @@ public class EntityDeathEvent extends EntityEvent {
+     public static HandlerList getHandlerList() {
+         return handlers;
+     }
++
++    // Paper start - make cancellable
++    @Override
++    public boolean isCancelled() {
++        return cancelled;
++    }
++
++    @Override
++    public void setCancelled(boolean cancel) {
++        cancelled = cancel;
++    }
++
++    /**
++     * Get the amount of health that the entity should revive with after cancelling the event.
++     * Set to the entity's max health by default.
++     *
++     * @return The amount of health
++     */
++    public double getReviveHealth() {
++        return reviveHealth;
++    }
++
++    /**
++     * Set the amount of health that the entity should revive with after cancelling the event.
++     * Revive health value must be between 0 (exclusive) and the entity's max health (inclusive).
++     *
++     * @param reviveHealth The amount of health
++     * @throws IllegalArgumentException Thrown if the health is {@literal <= 0 or >} max health
++     */
++    public void setReviveHealth(double reviveHealth) throws IllegalArgumentException {
++        double maxHealth = ((LivingEntity) entity).getAttribute(org.bukkit.attribute.Attribute.GENERIC_MAX_HEALTH).getValue();
++        if ((reviveHealth <= 0) || (reviveHealth > maxHealth)) {
++            throw new IllegalArgumentException("Health must be between 0 (exclusive) and " + maxHealth + " (inclusive), but was " + reviveHealth);
++        }
++        this.reviveHealth = reviveHealth;
++    }
++
++
++    /**
++     * Whether or not the death sound should play when the entity dies. If the event is cancelled it does not play!
++     *
++     * @return Whether or not the death sound should play. Event is called with this set to false if the entity is silent.
++     */
++    public boolean shouldPlayDeathSound() {
++        return shouldPlayDeathSound;
++    }
++
++    /**
++     * Set whether or not the death sound should play when the entity dies. If the event is cancelled it does not play!
++     *
++     * @param playDeathSound Enable or disable the death sound
++     */
++    public void setShouldPlayDeathSound(boolean playDeathSound) {
++        this.shouldPlayDeathSound = playDeathSound;
++    }
++
++    /**
++     * Get the sound that the entity makes when dying
++     *
++     * @return The sound that the entity makes
++     */
++    public org.bukkit.Sound getDeathSound() {
++        return deathSound;
++    }
++
++    /**
++     * Set the sound that the entity makes when dying
++     *
++     * @param sound The sound that the entity should make when dying
++     */
++    public void setDeathSound(org.bukkit.Sound sound) {
++        deathSound = sound;
++    }
++
++    /**
++     * Get the sound category that the death sound should play in
++     *
++     * @return The sound category
++     */
++    public org.bukkit.SoundCategory getDeathSoundCategory() {
++        return deathSoundCategory;
++    }
++
++    /**
++     * Set the sound category that the death sound should play in.
++     *
++     * @param soundCategory The sound category
++     */
++    public void setDeathSoundCategory(org.bukkit.SoundCategory soundCategory) {
++        this.deathSoundCategory = soundCategory;
++    }
++
++    /**
++     * Get the volume that the death sound will play at.
++     *
++     * @return The volume the death sound will play at
++     */
++    public float getDeathSoundVolume() {
++        return deathSoundVolume;
++    }
++
++    /**
++     * Set the volume the death sound should play at. If the event is cancelled this will not play the sound!
++     *
++     * @param volume The volume the death sound should play at
++     */
++    public void setDeathSoundVolume(float volume) {
++        this.deathSoundVolume = volume;
++    }
++
++    /**
++     * Get the pitch that the death sound will play with.
++     *
++     * @return The pitch the death sound will play with
++     */
++    public float getDeathSoundPitch() {
++        return deathSoundPitch;
++    }
++
++    /**
++     * GSetet the pitch that the death sound should play with.
++     *
++     * @param pitch The pitch the death sound should play with
++     */
++    public void setDeathSoundPitch(float pitch) {
++        this.deathSoundPitch = pitch;
++    }
++    // Paper end
+ }
+--
\ No newline at end of file
diff --git a/Spigot-Server-Patches/Improve-death-events.patch b/Spigot-Server-Patches/Improve-death-events.patch
new file mode 100644
index 0000000000..f5f776fdfc
--- /dev/null
+++ b/Spigot-Server-Patches/Improve-death-events.patch
@@ -0,0 +1,414 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Phoenix616 <mail@moep.tv>
+Date: Tue, 21 Aug 2018 01:39:35 +0100
+Subject: [PATCH] Improve death events
+
+This adds the ability to cancel the death events and to modify the sound
+an entity makes when dying. (In cases were no sound should it will be
+called with shouldPlaySound set to false allowing unsilencing of silent
+entities)
+
+It makes handling of entity deaths a lot nicer as you no longer need
+to listen on the damage event and calculate if the entity dies yourself
+to cancel the death which has the benefit of also receiving the dropped
+items and experience which is otherwise only properly possible by using
+internal code.
+
+diff --git a/src/main/java/net/minecraft/server/CombatTracker.java b/src/main/java/net/minecraft/server/CombatTracker.java
+index 7a076f3e4..bddd66e79 100644
+--- a/src/main/java/net/minecraft/server/CombatTracker.java
++++ b/src/main/java/net/minecraft/server/CombatTracker.java
+@@ -0,0 +0,0 @@ public class CombatTracker {
+         this.h = null;
+     }
+ 
++    public void reset() { this.g(); } // Paper - OBFHELPER
+     public void g() {
+         int i = this.f ? 300 : 100;
+ 
+diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
+index b0b49f4ff..d0dcce945 100644
+--- a/src/main/java/net/minecraft/server/Entity.java
++++ b/src/main/java/net/minecraft/server/Entity.java
+@@ -0,0 +0,0 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper
+         return false;
+     }
+ 
++    public void runKillTrigger(Entity entity, int kills, DamageSource damageSource) { this.a(entity, kills, damageSource); } // Paper - OBFHELPER
+     public void a(Entity entity, int i, DamageSource damagesource) {
+         if (entity instanceof EntityPlayer) {
+             CriterionTriggers.c.a((EntityPlayer) entity, this, damagesource);
+@@ -0,0 +0,0 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper
+ 
+     }
+ 
++    public void onKill(EntityLiving entityLiving) { this.b(entityLiving); } // Paper - OBFHELPER
+     public void b(EntityLiving entityliving) {}
+ 
+     protected boolean i(double d0, double d1, double d2) {
+@@ -0,0 +0,0 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper
+         return EnumPistonReaction.NORMAL;
+     }
+ 
++    public SoundCategory getDeathSoundCategory() { return bK();} // Paper - OBFHELPER
+     public SoundCategory bK() {
+         return SoundCategory.NEUTRAL;
+     }
+diff --git a/src/main/java/net/minecraft/server/EntityArmorStand.java b/src/main/java/net/minecraft/server/EntityArmorStand.java
+index dca497072..454c1e7d0 100644
+--- a/src/main/java/net/minecraft/server/EntityArmorStand.java
++++ b/src/main/java/net/minecraft/server/EntityArmorStand.java
+@@ -0,0 +0,0 @@ public class EntityArmorStand extends EntityLiving {
+     }
+ 
+     public void killEntity() {
+-        org.bukkit.craftbukkit.event.CraftEventFactory.callEntityDeathEvent(this, drops); // CraftBukkit - call event
++        org.bukkit.event.entity.EntityDeathEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityDeathEvent(this, drops); // CraftBukkit - call event // Paper - make cancellable
++        if (event.isCancelled()) return; // Paper - make cancellable
+         this.die();
+     }
+ 
+diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java
+index 14637be49..dec4b442c 100644
+--- a/src/main/java/net/minecraft/server/EntityLiving.java
++++ b/src/main/java/net/minecraft/server/EntityLiving.java
+@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity {
+     public float aR;
+     public EntityHuman killer;
+     public int lastDamageByPlayerTime; // Paper - public
+-    protected boolean aU;
++    protected boolean aU; protected void setDying(boolean dying) { this.aU = dying; } protected boolean isDying() { return this.aU; } // Paper - OBFHELPER
+     protected int ticksFarFromPlayer;
+     protected float aW;
+     protected float aX;
+     protected float aY;
+     protected float aZ;
+     protected float ba;
+-    protected int bb;
++    protected int bb; protected int getKillCount() { return this.bb; } // Paper - OBFHELPER
+     public float lastDamage;
+     protected boolean bd;
+     public float be;
+@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity {
+     public org.bukkit.craftbukkit.attribute.CraftAttributeMap craftAttributes;
+     public boolean collides = true;
+     public boolean canPickUpLoot;
++    public boolean silentDeath = false; // Paper - mark entity as dying silently for cancellable death event
+ 
+     @Override
+     public float getBukkitYaw() {
+@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity {
+ 
+                 if (this.getHealth() <= 0.0F) {
+                     if (!this.e(damagesource)) {
+-                        SoundEffect soundeffect = this.cf();
++                        // Paper start - moved into CraftEventFactory event caller for cancellable death event
++                        //SoundEffect soundeffect = this.cf();
+ 
+-                        if (flag1 && soundeffect != null) {
+-                            this.a(soundeffect, this.cq(), this.cr());
+-                        }
++                        //if (flag1 && soundeffect != null) {
++                        //    this.a(soundeffect, this.cq(), this.cr());
++                        //}
++                        this.silentDeath = !flag1; // mark entity as dying silently
++                        // Paper end
+ 
+                         this.die(damagesource);
++                        this.silentDeath = false; // Paper - cancellable death event - reset to default
+                     }
+                 } else if (flag1) {
+                     this.c(damagesource);
+@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity {
+             Entity entity = damagesource.getEntity();
+             EntityLiving entityliving = this.ci();
+ 
+-            if (this.bb >= 0 && entityliving != null) {
+-                entityliving.a(this, this.bb, damagesource);
+-            }
++            // Paper start - move down to make death event cancellable
++            //if (this.bb >= 0 && entityliving != null) {
++            //    entityliving.a(this, this.bb, damagesource);
++            //}
+ 
+-            if (entity != null) {
+-                entity.b(this);
+-            }
++            //if (entity != null) {
++            //    entity.b(this);
++            //}
+ 
+-            this.aU = true;
+-            this.getCombatTracker().g();
++            //this.aU = true;
++            //this.getCombatTracker().g();
++
++            org.bukkit.event.entity.EntityDeathEvent deathEvent = null;
++            //Paper end
+             if (!this.world.isClientSide) {
+                 int i = 0;
+ 
+@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity {
+ 
+                     this.a(flag, i, damagesource);
+                     // CraftBukkit start - Call death event
+-                    CraftEventFactory.callEntityDeathEvent(this, this.drops);
++                    deathEvent = CraftEventFactory.callEntityDeathEvent(this, this.drops); // Paper - cancellable death event
+                     this.drops = new ArrayList<org.bukkit.inventory.ItemStack>();
+                 } else {
+-                    CraftEventFactory.callEntityDeathEvent(this);
++                    deathEvent = CraftEventFactory.callEntityDeathEvent(this); // Paper - cancellable death event
+                     // CraftBukkit end
+                 }
+             }
+ 
+-            this.world.broadcastEntityEffect(this, (byte) 3);
++            // Paper start - cancellable death event
++            if (deathEvent == null || !deathEvent.isCancelled()) {
++                // triggers and stats got moved down
++                if (this.getKillCount() >= 0 && entityliving != null) {
++                    entityliving.runKillTrigger(this, this.getKillCount(), damagesource);
++                }
++
++                if (entity != null) {
++                    entity.onKill(this);
++                }
++
++                this.getCombatTracker().reset();
++                this.setDying(true);
++                this.world.broadcastEntityEffect(this, (byte) 3);
++            } else {
++                this.setHealth((float) deathEvent.getReviveHealth());
++            }
++            // Paper end
+         }
+     }
+ 
+@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity {
+         return SoundEffects.bX;
+     }
+ 
++    @Nullable public SoundEffect getDeathSoundEffect() { return cf();} // Paper - OBFHELPER
+     @Nullable
+     protected SoundEffect cf() {
+         return SoundEffects.bS;
+@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity {
+ 
+     }
+ 
++    public float getDeathSoundVolume() { return cq();} // Paper - OBFHELPER
+     protected float cq() {
+         return 1.0F;
+     }
+ 
++    public float getDeathSoundPitch() { return cr();} // Paper - OBFHELPER
+     protected float cr() {
+         return this.isBaby() ? (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.5F : (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F;
+     }
+diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java
+index 4ff505cfa..6afb6cf7b 100644
+--- a/src/main/java/net/minecraft/server/EntityPlayer.java
++++ b/src/main/java/net/minecraft/server/EntityPlayer.java
+@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
+     }
+     // Paper end
+     private int containerUpdateDelay; // Paper
++    // Paper start - cancellable death event
++    public boolean queueHealthUpdatePacket = false;
++    public net.minecraft.server.PacketPlayOutUpdateHealth queuedHealthUpdatePacket;
++    // Paper end
+ 
+     // CraftBukkit start
+     public String displayName;
+@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
+     public void die(DamageSource damagesource) {
+         boolean flag = this.world.getGameRules().getBoolean("showDeathMessages");
+ 
+-        this.playerConnection.sendPacket(new PacketPlayOutCombatEvent(this.getCombatTracker(), PacketPlayOutCombatEvent.EnumCombatEventType.ENTITY_DIED, flag));
++        //this.playerConnection.sendPacket(new PacketPlayOutCombatEvent(this.getCombatTracker(), PacketPlayOutCombatEvent.EnumCombatEventType.ENTITY_DIED, flag)); // Paper - moved down for cancellable death event
+         // CraftBukkit start - fire PlayerDeathEvent
+         if (this.dead) {
++            this.playerConnection.sendPacket(new PacketPlayOutCombatEvent(this.getCombatTracker(), PacketPlayOutCombatEvent.EnumCombatEventType.ENTITY_DIED, flag)); // Paper - moved down for cancellable death event
+             return;
+         }
+         java.util.List<org.bukkit.inventory.ItemStack> loot = new java.util.ArrayList<org.bukkit.inventory.ItemStack>(this.inventory.getSize());
+@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
+ 
+         String deathmessage = chatmessage.toPlainText();
+         org.bukkit.event.entity.PlayerDeathEvent event = CraftEventFactory.callPlayerDeathEvent(this, loot, deathmessage, keepInventory);
++        // Paper start - cancellable death event
++        if (event.isCancelled()) {
++            // make compatible with plugins that might have already set the health in an event listener
++            if (this.getHealth() <= 0) {
++                this.setHealth((float) event.getReviveHealth());
++            }
++            return;
++        }
++        this.playerConnection.sendPacket(new PacketPlayOutCombatEvent(this.getCombatTracker(), PacketPlayOutCombatEvent.EnumCombatEventType.ENTITY_DIED, flag));
++        // Paper end
+ 
+         String deathMessage = event.getDeathMessage();
+ 
+@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
+                         }
+                     }
+                 }
+-
+-                return super.damageEntity(damagesource, f);
++                // Paper start - cancellable death events
++                //return super.damageEntity(damagesource, f);
++                this.queueHealthUpdatePacket = true;
++                boolean damaged = super.damageEntity(damagesource, f);
++                this.queueHealthUpdatePacket = false;
++                if (this.queuedHealthUpdatePacket != null) {
++                    this.playerConnection.sendPacket(this.queuedHealthUpdatePacket);
++                    this.queuedHealthUpdatePacket = null;
++                }
++                return damaged;
++                // Paper end
+             }
+         }
+     }
+diff --git a/src/main/java/net/minecraft/server/RegistryMaterials.java b/src/main/java/net/minecraft/server/RegistryMaterials.java
+index d26abb419..aaedbc3b7 100644
+--- a/src/main/java/net/minecraft/server/RegistryMaterials.java
++++ b/src/main/java/net/minecraft/server/RegistryMaterials.java
+@@ -0,0 +0,0 @@ public class RegistryMaterials<K, V> extends RegistrySimple<K, V> implements Reg
+         return super.get(k0);
+     }
+ 
++    @Nullable public K getByValue(V value) { return this.b(value); } // Paper - OBFHELPER
+     @Nullable
+     public K b(V v0) {
+         return this.b.get(v0);
+diff --git a/src/main/java/net/minecraft/server/SoundEffect.java b/src/main/java/net/minecraft/server/SoundEffect.java
+index ec37e237f..8e0da7bd7 100644
+--- a/src/main/java/net/minecraft/server/SoundEffect.java
++++ b/src/main/java/net/minecraft/server/SoundEffect.java
+@@ -0,0 +0,0 @@ package net.minecraft.server;
+ 
+ public class SoundEffect {
+ 
+-    public static final RegistryMaterials<MinecraftKey, SoundEffect> a = new RegistryMaterials();
++    public static final RegistryMaterials<MinecraftKey, SoundEffect> a = new RegistryMaterials(); public static RegistryMaterials<MinecraftKey, SoundEffect> getRegistry() { return a; }// Paper - OBFHELPER
+     private final MinecraftKey b;
+     private static int c;
+ 
+diff --git a/src/main/java/org/bukkit/craftbukkit/CraftSound.java b/src/main/java/org/bukkit/craftbukkit/CraftSound.java
+index 8871c6f3a..84f4cb91e 100644
+--- a/src/main/java/org/bukkit/craftbukkit/CraftSound.java
++++ b/src/main/java/org/bukkit/craftbukkit/CraftSound.java
+@@ -0,0 +0,0 @@ public enum CraftSound {
+     WEATHER_RAIN_ABOVE("weather.rain.above");
+     private final String minecraftKey;
+ 
++    // Paper start - cancellable death event
++    public static CraftSound getBySoundEffect(final SoundEffect effect) {
++        MinecraftKey key = SoundEffect.getRegistry().getByValue(effect);
++        Preconditions.checkArgument(key != null, "Key for sound effect %s not found?", effect.toString());
++
++        return valueOf(key.getKey().replace('.', '_').toUpperCase(java.util.Locale.ENGLISH));
++    }
++
++    public static Sound getSoundByEffect(final SoundEffect effect) {
++        return Sound.valueOf(getBySoundEffect(effect).name());
++    }
++
++    public static SoundEffect getSoundEffect(final Sound sound) {
++        return getSoundEffect(getSound(sound));
++    }
++    // Paper end
+     CraftSound(String minecraftKey) {
+         this.minecraftKey = minecraftKey;
+     }
+diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+index 5f480ac06..d59d86efc 100644
+--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
+     }
+ 
+     public void sendHealthUpdate() {
+-        getHandle().playerConnection.sendPacket(new PacketPlayOutUpdateHealth(getScaledHealth(), getHandle().getFoodData().getFoodLevel(), getHandle().getFoodData().getSaturationLevel()));
++        // Paper start - cancellable death event
++        //getHandle().playerConnection.sendPacket(new PacketPlayOutUpdateHealth(getScaledHealth(), getHandle().getFoodData().getFoodLevel(), getHandle().getFoodData().getSaturationLevel()));
++        PacketPlayOutUpdateHealth packet = new PacketPlayOutUpdateHealth(getScaledHealth(), getHandle().getFoodData().getFoodLevel(), getHandle().getFoodData().getSaturationLevel());
++        if (this.getHandle().queueHealthUpdatePacket) {
++            this.getHandle().queuedHealthUpdatePacket = packet;
++        } else {
++            this.getHandle().playerConnection.sendPacket(packet);
++        }
++        // Paper end
+     }
+ 
+     public void injectScaledMaxHealth(Collection<AttributeInstance> collection, boolean force) {
+diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+index cce4acc0b..f1a3ca950 100644
+--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+@@ -0,0 +0,0 @@ public class CraftEventFactory {
+     public static EntityDeathEvent callEntityDeathEvent(EntityLiving victim, List<org.bukkit.inventory.ItemStack> drops) {
+         CraftLivingEntity entity = (CraftLivingEntity) victim.getBukkitEntity();
+         EntityDeathEvent event = new EntityDeathEvent(entity, drops, victim.getExpReward());
++        populateFields(victim, event); // Paper - make cancellable
+         CraftWorld world = (CraftWorld) entity.getWorld();
+         Bukkit.getServer().getPluginManager().callEvent(event);
+ 
++        // Paper start - make cancellable
++        if (event.isCancelled()) {
++            return event;
++        }
++        playDeathSound(victim, event);
++        // Paper end
+         victim.expToDrop = event.getDroppedExp();
+ 
+         for (org.bukkit.inventory.ItemStack stack : event.getDrops()) {
+@@ -0,0 +0,0 @@ public class CraftEventFactory {
+         CraftPlayer entity = victim.getBukkitEntity();
+         PlayerDeathEvent event = new PlayerDeathEvent(entity, drops, victim.getExpReward(), 0, deathMessage);
+         event.setKeepInventory(keepInventory);
++        populateFields(victim, event); // Paper - make cancellable
+         org.bukkit.World world = entity.getWorld();
+         Bukkit.getServer().getPluginManager().callEvent(event);
++        // Paper start - make cancellable
++        if (event.isCancelled()) {
++            return event;
++        }
++        playDeathSound(victim, event);
++        // Paper end
+ 
+         victim.keepLevel = event.getKeepLevel();
+         victim.newLevel = event.getNewLevel();
+@@ -0,0 +0,0 @@ public class CraftEventFactory {
+         return event;
+     }
+ 
++    // Paper start - helper methods for making death event cancellable
++    // Add information to death event
++    private static void populateFields(EntityLiving victim, EntityDeathEvent event) {
++        event.setReviveHealth(event.getEntity().getAttribute(org.bukkit.attribute.Attribute.GENERIC_MAX_HEALTH).getValue());
++        event.setShouldPlayDeathSound(!victim.silentDeath && !victim.isSilent());
++        SoundEffect soundEffect = victim.getDeathSoundEffect();
++        event.setDeathSound(soundEffect != null ? org.bukkit.craftbukkit.CraftSound.getSoundByEffect(soundEffect) : null);
++        event.setDeathSoundCategory(org.bukkit.SoundCategory.valueOf(victim.getDeathSoundCategory().name()));
++        event.setDeathSoundVolume(victim.getDeathSoundVolume());
++        event.setDeathSoundPitch(victim.getDeathSoundPitch());
++    }
++
++    // Play death sound manually
++    private static void playDeathSound(EntityLiving victim, EntityDeathEvent event) {
++        if (event.shouldPlayDeathSound() && event.getDeathSound() != null && event.getDeathSoundCategory() != null) {
++            EntityHuman source = victim instanceof EntityHuman ? (EntityHuman) victim : null;
++            double x = event.getEntity().getLocation().getX();
++            double y = event.getEntity().getLocation().getY();
++            double z = event.getEntity().getLocation().getZ();
++            SoundEffect soundEffect = org.bukkit.craftbukkit.CraftSound.getSoundEffect(event.getDeathSound());
++            SoundCategory soundCategory = SoundCategory.valueOf(event.getDeathSoundCategory().name());
++            victim.world.sendSoundEffect(source, x, y, z, soundEffect, soundCategory, event.getDeathSoundVolume(), event.getDeathSoundPitch());
++        }
++    }
++    // Paper end
+     /**
+      * Server methods
+      */
+--
\ No newline at end of file
diff --git a/Spigot-Server-Patches/MC-Dev-fixes.patch b/Spigot-Server-Patches/MC-Dev-fixes.patch
index 0dcabebdb3..a8746064d1 100644
--- a/Spigot-Server-Patches/MC-Dev-fixes.patch
+++ b/Spigot-Server-Patches/MC-Dev-fixes.patch
@@ -110,19 +110,19 @@ index a540167d6..b2860555d 100644
              return this.a(jsonelement, type, jsondeserializationcontext);
          }
      }
+diff --git a/src/main/java/net/minecraft/server/Registry.java b/src/main/java/net/minecraft/server/Registry.java
+index 723372f26..c38c3768c 100644
+--- a/src/main/java/net/minecraft/server/Registry.java
++++ b/src/main/java/net/minecraft/server/Registry.java
+@@ -0,0 +0,0 @@
+ package net.minecraft.server;
+ 
+-public interface Registry extends Iterable {}
++public interface Registry<T> extends Iterable<T> {} // Paper - decompile fix
 diff --git a/src/main/java/net/minecraft/server/RegistryBlockID.java b/src/main/java/net/minecraft/server/RegistryBlockID.java
-index 58f47d0de..8860a0129 100644
+index 58f47d0de..03894df54 100644
 --- a/src/main/java/net/minecraft/server/RegistryBlockID.java
 +++ b/src/main/java/net/minecraft/server/RegistryBlockID.java
-@@ -0,0 +0,0 @@ import java.util.Iterator;
- import java.util.List;
- import javax.annotation.Nullable;
- 
--public class RegistryBlockID<T> implements Registry<T> {
-+public class RegistryBlockID<T> implements Registry { // Paper - Fix decompile error
- 
-     private final IdentityHashMap<T, Integer> a;
-     private final List<T> b;
 @@ -0,0 +0,0 @@ public class RegistryBlockID<T> implements Registry<T> {
          this.a.put(t0, Integer.valueOf(i));
  
diff --git a/scripts/importmcdev.sh b/scripts/importmcdev.sh
index 9e16057186..bc3b21f90e 100755
--- a/scripts/importmcdev.sh
+++ b/scripts/importmcdev.sh
@@ -56,6 +56,7 @@ import ChunkCoordIntPair
 import ChunkProviderFlat
 import ChunkProviderGenerate
 import ChunkProviderHell
+import CombatTracker
 import CommandAbstract
 import CommandScoreboard
 import CommandWhitelist
@@ -103,10 +104,13 @@ import PersistentScoreboard
 import PersistentVillage
 import PlayerConnectionUtils
 import RegionFile
+import Registry
 import RegistryBlockID
+import RegistryMaterials
 import RemoteControlListener
 import RecipeBookServer
 import ServerPing
+import SoundEffect
 import StructureBoundingBox
 import StructurePiece
 import StructureStart