aboutsummaryrefslogtreecommitdiffhomepage
path: root/Spigot-Server-Patches/0168-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch
blob: 079b7aad2a2c13154e4b797e7d8d6e9e7b66a33b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
From e9824b65b2515743090f724cbc535d1297ffb033 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Tue, 19 Dec 2017 16:31:46 -0500
Subject: [PATCH] ExperienceOrbs API for Reason/Source/Triggering player

Adds lots of information about why this orb exists.

Replaces isFromBottle() with logic that persists entity reloads too.

diff --git a/src/main/java/net/minecraft/server/Block.java b/src/main/java/net/minecraft/server/Block.java
index 1dc13fcc3..c674aa13d 100644
--- a/src/main/java/net/minecraft/server/Block.java
+++ b/src/main/java/net/minecraft/server/Block.java
@@ -450,13 +450,13 @@ public class Block implements IMaterial {
         }
     }
 
-    protected void dropExperience(World world, BlockPosition blockposition, int i) {
+    protected void dropExperience(World world, BlockPosition blockposition, int i, EntityPlayer player) { // Paper
         if (!world.isClientSide && world.getGameRules().getBoolean("doTileDrops")) {
             while (i > 0) {
                 int j = EntityExperienceOrb.getOrbValue(i);
 
                 i -= j;
-                world.addEntity(new EntityExperienceOrb(world, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, j));
+                world.addEntity(new EntityExperienceOrb(world, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, j, org.bukkit.entity.ExperienceOrb.SpawnReason.BLOCK_BREAK, player)); // Paper
             }
         }
 
diff --git a/src/main/java/net/minecraft/server/EntityEnderDragon.java b/src/main/java/net/minecraft/server/EntityEnderDragon.java
index b3fbc8249..79d8be8d4 100644
--- a/src/main/java/net/minecraft/server/EntityEnderDragon.java
+++ b/src/main/java/net/minecraft/server/EntityEnderDragon.java
@@ -618,7 +618,7 @@ public class EntityEnderDragon extends EntityInsentient implements IComplex, IMo
             int j = EntityExperienceOrb.getOrbValue(i);
 
             i -= j;
-            this.world.addEntity(new EntityExperienceOrb(this.world, this.locX, this.locY, this.locZ, j));
+            this.world.addEntity(new EntityExperienceOrb(this.world, this.locX, this.locY, this.locZ, j, org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, this.killer, this)); // Paper
         }
 
     }
diff --git a/src/main/java/net/minecraft/server/EntityExperienceOrb.java b/src/main/java/net/minecraft/server/EntityExperienceOrb.java
index 3030dd9c3..404a222b4 100644
--- a/src/main/java/net/minecraft/server/EntityExperienceOrb.java
+++ b/src/main/java/net/minecraft/server/EntityExperienceOrb.java
@@ -15,9 +15,59 @@ public class EntityExperienceOrb extends Entity {
     public int value;
     private EntityHuman targetPlayer;
     private int targetTime;
+    // Paper start
+    public java.util.UUID sourceEntityId;
+    public java.util.UUID triggerEntityId;
+    public org.bukkit.entity.ExperienceOrb.SpawnReason spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN;
+
+    private void loadPaperNBT(NBTTagCompound nbttagcompound) {
+        if (!nbttagcompound.hasKeyOfType("Paper.ExpData", 10)) { // 10 = compound
+            return;
+        }
+        NBTTagCompound comp = nbttagcompound.getCompound("Paper.ExpData");
+        if (comp.hasUUID("source")) {
+            this.sourceEntityId = comp.getUUID("source");
+        }
+        if (comp.hasUUID("trigger")) {
+            this.triggerEntityId = comp.getUUID("trigger");
+        }
+        if (comp.hasKey("reason")) {
+            String reason = comp.getString("reason");
+            try {
+                spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.valueOf(reason);
+            } catch (Exception e) {
+                this.world.getServer().getLogger().warning("Invalid spawnReason set for experience orb: " + e.getMessage() + " - " + reason);
+            }
+        }
+    }
+    private void savePaperNBT(NBTTagCompound nbttagcompound) {
+        NBTTagCompound comp = new NBTTagCompound();
+        if (sourceEntityId != null) {
+            comp.setUUID("source", sourceEntityId);
+        }
+        if (triggerEntityId != null) {
+            comp.setUUID("trigger", triggerEntityId);
+        }
+        if (spawnReason != null && spawnReason != org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN) {
+            comp.setString("reason", spawnReason.name());
+        }
+        nbttagcompound.set("Paper.ExpData", comp);
+    }
 
     public EntityExperienceOrb(World world, double d0, double d1, double d2, int i) {
+        this(world, d0, d1, d2, i, null, null);
+    }
+
+    public EntityExperienceOrb(World world, double d0, double d1, double d2, int i, org.bukkit.entity.ExperienceOrb.SpawnReason reason, Entity triggerId) {
+        this(world, d0, d1, d2, i, reason, triggerId, null);
+    }
+
+    public EntityExperienceOrb(World world, double d0, double d1, double d2, int i, org.bukkit.entity.ExperienceOrb.SpawnReason reason, Entity triggerId, Entity sourceId) {
         super(EntityTypes.EXPERIENCE_ORB, world);
+        this.sourceEntityId = sourceId != null ? sourceId.getUniqueID() : null;
+        this.triggerEntityId = triggerId != null ? triggerId.getUniqueID() : null;
+        this.spawnReason = reason != null ? reason : org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN;
+        // Paper end
         this.setSize(0.5F, 0.5F);
         this.setPosition(d0, d1, d2);
         this.yaw = (float) (Math.random() * 360.0D);
@@ -156,12 +206,14 @@ public class EntityExperienceOrb extends Entity {
         nbttagcompound.setShort("Health", (short) this.d);
         nbttagcompound.setShort("Age", (short) this.b);
         nbttagcompound.setShort("Value", (short) this.value);
+        savePaperNBT(nbttagcompound); // Paper
     }
 
     public void a(NBTTagCompound nbttagcompound) {
         this.d = nbttagcompound.getShort("Health");
         this.b = nbttagcompound.getShort("Age");
         this.value = nbttagcompound.getShort("Value");
+        loadPaperNBT(nbttagcompound); // Paper
     }
 
     public void d(EntityHuman entityhuman) {
diff --git a/src/main/java/net/minecraft/server/EntityFishingHook.java b/src/main/java/net/minecraft/server/EntityFishingHook.java
index c13e1ff6f..7fb136a2d 100644
--- a/src/main/java/net/minecraft/server/EntityFishingHook.java
+++ b/src/main/java/net/minecraft/server/EntityFishingHook.java
@@ -468,7 +468,7 @@ public class EntityFishingHook extends Entity {
                     this.world.addEntity(entityitem);
                     // CraftBukkit start - this.random.nextInt(6) + 1 -> playerFishEvent.getExpToDrop()
                     if (playerFishEvent.getExpToDrop() > 0) {
-                        this.owner.world.addEntity(new EntityExperienceOrb(this.owner.world, this.owner.locX, this.owner.locY + 0.5D, this.owner.locZ + 0.5D, playerFishEvent.getExpToDrop()));
+                        this.owner.world.addEntity(new EntityExperienceOrb(this.owner.world, this.owner.locX, this.owner.locY + 0.5D, this.owner.locZ + 0.5D, playerFishEvent.getExpToDrop(), org.bukkit.entity.ExperienceOrb.SpawnReason.FISHING, this.owner, this)); // Paper
                     }
                     // CraftBukkit end
                     if (itemstack1.getItem().a(TagsItem.FISHES)) {
diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java
index c0ef0c51f..3bc1f8f9b 100644
--- a/src/main/java/net/minecraft/server/EntityLiving.java
+++ b/src/main/java/net/minecraft/server/EntityLiving.java
@@ -354,7 +354,8 @@ public abstract class EntityLiving extends Entity {
                 int j = EntityExperienceOrb.getOrbValue(i);
 
                 i -= j;
-                this.world.addEntity(new EntityExperienceOrb(this.world, this.locX, this.locY, this.locZ, j));
+                EntityLiving attacker = killer != null ? killer : lastDamager; // Paper
+                this.world.addEntity(new EntityExperienceOrb(this.world, this.locX, this.locY, this.locZ, j, this instanceof EntityPlayer ? org.bukkit.entity.ExperienceOrb.SpawnReason.PLAYER_DEATH : org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, attacker, this)); // Paper
             }
             this.expToDrop = 0;
             // CraftBukkit end
diff --git a/src/main/java/net/minecraft/server/EntityThrownExpBottle.java b/src/main/java/net/minecraft/server/EntityThrownExpBottle.java
index a5e1939e0..e73dba09a 100644
--- a/src/main/java/net/minecraft/server/EntityThrownExpBottle.java
+++ b/src/main/java/net/minecraft/server/EntityThrownExpBottle.java
@@ -36,7 +36,7 @@ public class EntityThrownExpBottle extends EntityProjectile {
                 int j = EntityExperienceOrb.getOrbValue(i);
 
                 i -= j;
-                this.world.addEntity(new EntityExperienceOrb(this.world, this.locX, this.locY, this.locZ, j));
+                this.world.addEntity(new EntityExperienceOrb(this.world, this.locX, this.locY, this.locZ, j, org.bukkit.entity.ExperienceOrb.SpawnReason.EXP_BOTTLE, getShooter(), this)); // Paper
             }
 
             this.die();
diff --git a/src/main/java/net/minecraft/server/EntityVillager.java b/src/main/java/net/minecraft/server/EntityVillager.java
index ebe397b15..78acac4ca 100644
--- a/src/main/java/net/minecraft/server/EntityVillager.java
+++ b/src/main/java/net/minecraft/server/EntityVillager.java
@@ -412,7 +412,7 @@ public class EntityVillager extends EntityAgeable implements NPC, IMerchant {
         }
 
         if (merchantrecipe.j()) {
-            this.world.addEntity(new EntityExperienceOrb(this.world, this.locX, this.locY + 0.5D, this.locZ, i));
+            this.world.addEntity(new EntityExperienceOrb(this.world, this.locX, this.locY + 0.5D, this.locZ, i, org.bukkit.entity.ExperienceOrb.SpawnReason.VILLAGER_TRADE, tradingPlayer, this)); // Paper
         }
 
         if (this.tradingPlayer instanceof EntityPlayer) {
diff --git a/src/main/java/net/minecraft/server/PathfinderGoalBreed.java b/src/main/java/net/minecraft/server/PathfinderGoalBreed.java
index bf061cf06..55f978768 100644
--- a/src/main/java/net/minecraft/server/PathfinderGoalBreed.java
+++ b/src/main/java/net/minecraft/server/PathfinderGoalBreed.java
@@ -122,7 +122,7 @@ public class PathfinderGoalBreed extends PathfinderGoal {
             if (this.b.getGameRules().getBoolean("doMobLoot")) {
                 // CraftBukkit start - use event experience
                 if (experience > 0) {
-                    this.b.addEntity(new EntityExperienceOrb(this.b, this.animal.locX, this.animal.locY, this.animal.locZ, experience));
+                    this.b.addEntity(new EntityExperienceOrb(this.b, this.animal.locX, this.animal.locY, this.animal.locZ, experience, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer, entityageable)); // Paper
                 }
                 // CraftBukkit end
             }
diff --git a/src/main/java/net/minecraft/server/PlayerInteractManager.java b/src/main/java/net/minecraft/server/PlayerInteractManager.java
index 0baf0100c..6ae6afa33 100644
--- a/src/main/java/net/minecraft/server/PlayerInteractManager.java
+++ b/src/main/java/net/minecraft/server/PlayerInteractManager.java
@@ -391,7 +391,7 @@ public class PlayerInteractManager {
 
                 // CraftBukkit start - Drop event experience
                 if (flag && event != null) {
-                    iblockdata.getBlock().dropExperience(this.world, blockposition, event.getExpToDrop());
+                    iblockdata.getBlock().dropExperience(this.world, blockposition, event.getExpToDrop(), this.player); // Paper
                 }
                 // CraftBukkit end
 
diff --git a/src/main/java/net/minecraft/server/SlotFurnaceResult.java b/src/main/java/net/minecraft/server/SlotFurnaceResult.java
index 5ac554d65..d70c4dda5 100644
--- a/src/main/java/net/minecraft/server/SlotFurnaceResult.java
+++ b/src/main/java/net/minecraft/server/SlotFurnaceResult.java
@@ -9,7 +9,7 @@ import org.bukkit.event.inventory.FurnaceExtractEvent;
 
 public class SlotFurnaceResult extends Slot {
 
-    private final EntityHuman a;
+    private final EntityHuman a;public EntityHuman getPlayer() { return a; } // Paper OBFHELPER
     private int b;
 
     public SlotFurnaceResult(EntityHuman entityhuman, IInventory iinventory, int i, int j, int k) {
@@ -85,7 +85,7 @@ public class SlotFurnaceResult extends Slot {
                 while (i > 0) {
                     j = EntityExperienceOrb.getOrbValue(i);
                     i -= j;
-                    this.a.world.addEntity(new EntityExperienceOrb(this.a.world, this.a.locX, this.a.locY + 0.5D, this.a.locZ + 0.5D, j));
+                    this.a.world.addEntity(new EntityExperienceOrb(this.a.world, this.a.locX, this.a.locY + 0.5D, this.a.locZ + 0.5D, j, org.bukkit.entity.ExperienceOrb.SpawnReason.FURNACE, getPlayer())); // Paper
                 }
             }
 
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 671802819..d72f393a7 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -1354,7 +1354,7 @@ public class CraftWorld implements World {
         } else if (TNTPrimed.class.isAssignableFrom(clazz)) {
             entity = new EntityTNTPrimed(world, x, y, z, null);
         } else if (ExperienceOrb.class.isAssignableFrom(clazz)) {
-            entity = new EntityExperienceOrb(world, x, y, z, 0);
+            entity = new EntityExperienceOrb(world, x, y, z, 0, org.bukkit.entity.ExperienceOrb.SpawnReason.CUSTOM, null, null); // Paper
         } else if (Weather.class.isAssignableFrom(clazz)) {
             // not sure what this can do
             if (LightningStrike.class.isAssignableFrom(clazz)) {
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java
index 3a09cab3d..3302af0e4 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java
@@ -18,6 +18,18 @@ public class CraftExperienceOrb extends CraftEntity implements ExperienceOrb {
         getHandle().value = value;
     }
 
+    // Paper start
+    public java.util.UUID getTriggerEntityId() {
+        return getHandle().triggerEntityId;
+    }
+    public java.util.UUID getSourceEntityId() {
+        return getHandle().sourceEntityId;
+    }
+    public SpawnReason getSpawnReason() {
+        return getHandle().spawnReason;
+    }
+    // Paper end
+
     @Override
     public EntityExperienceOrb getHandle() {
         return (EntityExperienceOrb) entity;
-- 
2.21.0