From 46394cb8b05edf134014d3654da963418d952e31 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Tue, 19 Dec 2017 22:57:46 -0500
Subject: [PATCH] ExperienceOrbMergeEvent

Fired when the server is about to merge 2 experience orbs
Plugins can cancel this if they want to ensure experience orbs do not lose important
metadata such as spawn reason, or conditionally move data from source to target.
---
 .../0078-ExperienceOrbMergeEvent.patch        | 100 ++++++++++++++++++
 .../0258-ExperienceOrbMergeEvent.patch        |  25 +++++
 2 files changed, 125 insertions(+)
 create mode 100644 Spigot-API-Patches/0078-ExperienceOrbMergeEvent.patch
 create mode 100644 Spigot-Server-Patches/0258-ExperienceOrbMergeEvent.patch

diff --git a/Spigot-API-Patches/0078-ExperienceOrbMergeEvent.patch b/Spigot-API-Patches/0078-ExperienceOrbMergeEvent.patch
new file mode 100644
index 0000000000..db04cdc083
--- /dev/null
+++ b/Spigot-API-Patches/0078-ExperienceOrbMergeEvent.patch
@@ -0,0 +1,100 @@
+From 1e771a4b19373d4a328f569bb97193d8aea8961c Mon Sep 17 00:00:00 2001
+From: Aikar <aikar@aikar.co>
+Date: Tue, 19 Dec 2017 22:56:24 -0500
+Subject: [PATCH] ExperienceOrbMergeEvent
+
+Fired when the server is about to merge 2 experience orbs
+Plugins can cancel this if they want to ensure experience orbs do not lose important
+metadata such as spawn reason, or conditionally move data from source to target.
+
+diff --git a/src/main/java/com/destroystokyo/paper/event/entity/ExperienceOrbMergeEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/ExperienceOrbMergeEvent.java
+new file mode 100644
+index 00000000..fb5b4b86
+--- /dev/null
++++ b/src/main/java/com/destroystokyo/paper/event/entity/ExperienceOrbMergeEvent.java
+@@ -0,0 +1,82 @@
++/*
++ * Copyright (c) 2017 Daniel Ennis (Aikar) MIT License
++ *
++ *  Permission is hereby granted, free of charge, to any person obtaining
++ *  a copy of this software and associated documentation files (the
++ *  "Software"), to deal in the Software without restriction, including
++ *  without limitation the rights to use, copy, modify, merge, publish,
++ *  distribute, sublicense, and/or sell copies of the Software, and to
++ *  permit persons to whom the Software is furnished to do so, subject to
++ *  the following conditions:
++ *
++ *  The above copyright notice and this permission notice shall be
++ *  included in all copies or substantial portions of the Software.
++ *
++ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
++ *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
++ *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
++ *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
++ */
++
++package com.destroystokyo.paper.event.entity;
++
++import org.bukkit.entity.ExperienceOrb;
++import org.bukkit.event.Cancellable;
++import org.bukkit.event.HandlerList;
++import org.bukkit.event.entity.EntityEvent;
++
++/**
++ * Fired anytime the server is about to merge 2 experience orbs into one
++ */
++public class ExperienceOrbMergeEvent extends EntityEvent implements Cancellable {
++    private final ExperienceOrb mergeTarget;
++    private final ExperienceOrb mergeSource;
++
++    public ExperienceOrbMergeEvent(ExperienceOrb mergeTarget, ExperienceOrb mergeSource) {
++        super(mergeTarget);
++        this.mergeTarget = mergeTarget;
++        this.mergeSource = mergeSource;
++    }
++
++    /**
++     * @return The orb that will absorb the other experience orb
++     */
++    public ExperienceOrb getMergeTarget() {
++        return mergeTarget;
++    }
++
++    /**
++     * @return The orb that is subject to being removed and merged into the target orb
++     */
++    public ExperienceOrb getMergeSource() {
++        return mergeSource;
++    }
++
++    private static final HandlerList handlers = new HandlerList();
++
++    public HandlerList getHandlers() {
++        return handlers;
++    }
++
++    public static HandlerList getHandlerList() {
++        return handlers;
++    }
++
++    private boolean cancelled = false;
++
++    @Override
++    public boolean isCancelled() {
++        return cancelled;
++    }
++
++    /**
++     * @param cancel true if you wish to cancel this event, and prevent the orbs from merging
++     */
++    @Override
++    public void setCancelled(boolean cancel) {
++        cancelled = cancel;
++    }
++}
+-- 
+2.15.1
+
diff --git a/Spigot-Server-Patches/0258-ExperienceOrbMergeEvent.patch b/Spigot-Server-Patches/0258-ExperienceOrbMergeEvent.patch
new file mode 100644
index 0000000000..bcfb123a29
--- /dev/null
+++ b/Spigot-Server-Patches/0258-ExperienceOrbMergeEvent.patch
@@ -0,0 +1,25 @@
+From 4756610ec863cc75f8e66891aaf6f0f2257afb23 Mon Sep 17 00:00:00 2001
+From: Aikar <aikar@aikar.co>
+Date: Tue, 19 Dec 2017 22:57:26 -0500
+Subject: [PATCH] ExperienceOrbMergeEvent
+
+Fired when the server is about to merge 2 experience orbs
+Plugins can cancel this if they want to ensure experience orbs do not lose important
+metadata such as spawn reason, or conditionally move data from source to target.
+
+diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
+index eb8a1c43c..ad927cbd5 100644
+--- a/src/main/java/net/minecraft/server/World.java
++++ b/src/main/java/net/minecraft/server/World.java
+@@ -1153,7 +1153,7 @@ public abstract class World implements IBlockAccess {
+                 for (Entity e : entities) {
+                     if (e instanceof EntityExperienceOrb) {
+                         EntityExperienceOrb loopItem = (EntityExperienceOrb) e;
+-                        if (!loopItem.dead && !(maxValue > 0 && loopItem.value >= maxValue)) { // Paper
++                        if (!loopItem.dead && !(maxValue > 0 && loopItem.value >= maxValue) && new com.destroystokyo.paper.event.entity.ExperienceOrbMergeEvent((org.bukkit.entity.ExperienceOrb) entity.getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) loopItem.getBukkitEntity()).callEvent()) { // Paper
+                             xp.value += loopItem.value;
+                             // Paper start
+                             if (!mergeUnconditionally && xp.value > maxValue) {
+-- 
+2.15.1
+