papermc/Spigot-Server-Patches/0147-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch
Spottedleaf 5c7081fecc Update upstream & fix some chunk related issues (#2177)
* Updated Upstream (Bukkit/CraftBukkit)

Upstream has released updates that appears to apply and compile correctly.
This update has not been tested by PaperMC and as with ANY update, please do your own testing

Bukkit Changes:
45690fe9 SPIGOT-5047: Correct slot types for 1.14 inventories

CraftBukkit Changes:
4090d01f SPIGOT-5047: Correct slot types for 1.14 inventories
e8c08362 SPIGOT-5046: World#getLoadedChunks returning inaccessible cached chunks.
d445af3b SPIGOT-5067: Add item meta for 1.14 spawn eggs

* Bring Chunk load checks in-line with spigot

As of the last upstream merge spigot now checks ticket level status
when returning loaded chunks for a world from api. Now our checks
will respect that decision.

* Fix spawn ticket levels

Vanilla would keep the inner chunks of spawn available for ticking,
however my changes made all chunks non-ticking. Resolve by changing
ticket levels for spawn chunks inside the border to respect this
behavior.


* Make World#getChunkIfLoadedImmediately return only entity ticking chunks

Mojang appears to be using chunks with level > 33 (non-ticking chunks)
as cached chunks and not actually loaded chunks.

* Bring all loaded checks in line with spigot

Loaded chunks must be at least border  chunks, or level <= 33
2019-06-14 03:27:40 +01:00

305 lines
18 KiB
Diff

From bbce7176033db62b4eaeedb83fdc67644c8ca6ac 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 78b0e78474..03d3090b3f 100644
--- a/src/main/java/net/minecraft/server/Block.java
+++ b/src/main/java/net/minecraft/server/Block.java
@@ -511,13 +511,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/ContainerGrindstone.java b/src/main/java/net/minecraft/server/ContainerGrindstone.java
index 2d2cd09ad1..ed88e208d0 100644
--- a/src/main/java/net/minecraft/server/ContainerGrindstone.java
+++ b/src/main/java/net/minecraft/server/ContainerGrindstone.java
@@ -81,7 +81,7 @@ public class ContainerGrindstone extends Container {
int k = EntityExperienceOrb.getOrbValue(j);
j -= k;
- world.addEntity(new EntityExperienceOrb(world, (double) blockposition.getX(), (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, k));
+ world.addEntity(new EntityExperienceOrb(world, (double) blockposition.getX(), (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, k, org.bukkit.entity.ExperienceOrb.SpawnReason.GRINDSTONE, entityhuman)); // Paper
}
world.triggerEffect(1042, blockposition, 0);
diff --git a/src/main/java/net/minecraft/server/EntityEnderDragon.java b/src/main/java/net/minecraft/server/EntityEnderDragon.java
index 6ac0546029..0baec5e119 100644
--- a/src/main/java/net/minecraft/server/EntityEnderDragon.java
+++ b/src/main/java/net/minecraft/server/EntityEnderDragon.java
@@ -607,7 +607,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster {
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 bfba08fb24..49668f2c21 100644
--- a/src/main/java/net/minecraft/server/EntityExperienceOrb.java
+++ b/src/main/java/net/minecraft/server/EntityExperienceOrb.java
@@ -16,9 +16,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 {
+ this.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 (this.sourceEntityId != null) {
+ comp.setUUID("source", this.sourceEntityId);
+ }
+ if (this.triggerEntityId != null) {
+ comp.setUUID("trigger", triggerEntityId);
+ }
+ if (this.spawnReason != null && this.spawnReason != org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN) {
+ comp.setString("reason", this.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) {
this(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.setPosition(d0, d1, d2);
this.yaw = (float) (this.random.nextDouble() * 360.0D);
this.setMot((this.random.nextDouble() * 0.20000000298023224D - 0.10000000149011612D) * 2.0D, this.random.nextDouble() * 0.2D * 2.0D, (this.random.nextDouble() * 0.20000000298023224D - 0.10000000149011612D) * 2.0D);
@@ -155,6 +205,7 @@ public class EntityExperienceOrb extends Entity {
nbttagcompound.setShort("Health", (short) this.e);
nbttagcompound.setShort("Age", (short) this.c);
nbttagcompound.setShort("Value", (short) this.value);
+ this.savePaperNBT(nbttagcompound); // Paper
}
@Override
@@ -162,6 +213,7 @@ public class EntityExperienceOrb extends Entity {
this.e = nbttagcompound.getShort("Health");
this.c = nbttagcompound.getShort("Age");
this.value = nbttagcompound.getShort("Value");
+ this.loadPaperNBT(nbttagcompound); // Paper
}
@Override
diff --git a/src/main/java/net/minecraft/server/EntityFishingHook.java b/src/main/java/net/minecraft/server/EntityFishingHook.java
index 758559d35d..2a351701b4 100644
--- a/src/main/java/net/minecraft/server/EntityFishingHook.java
+++ b/src/main/java/net/minecraft/server/EntityFishingHook.java
@@ -404,7 +404,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 5622c08f19..b402818008 100644
--- a/src/main/java/net/minecraft/server/EntityLiving.java
+++ b/src/main/java/net/minecraft/server/EntityLiving.java
@@ -385,7 +385,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 4ac5cce062..05970c5644 100644
--- a/src/main/java/net/minecraft/server/EntityThrownExpBottle.java
+++ b/src/main/java/net/minecraft/server/EntityThrownExpBottle.java
@@ -43,7 +43,7 @@ public class EntityThrownExpBottle extends EntityProjectileThrowable {
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/EntityTurtle.java b/src/main/java/net/minecraft/server/EntityTurtle.java
index a18bd29fe8..89792eec45 100644
--- a/src/main/java/net/minecraft/server/EntityTurtle.java
+++ b/src/main/java/net/minecraft/server/EntityTurtle.java
@@ -512,7 +512,7 @@ public class EntityTurtle extends EntityAnimal {
Random random = this.animal.getRandom();
if (this.b.getGameRules().getBoolean("doMobLoot")) {
- this.b.addEntity(new EntityExperienceOrb(this.b, this.animal.locX, this.animal.locY, this.animal.locZ, random.nextInt(7) + 1));
+ this.b.addEntity(new EntityExperienceOrb(this.b, this.animal.locX, this.animal.locY, this.animal.locZ, random.nextInt(7) + 1, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer)); // Paper
}
}
diff --git a/src/main/java/net/minecraft/server/EntityVillager.java b/src/main/java/net/minecraft/server/EntityVillager.java
index 4119709cb8..b25f3d1592 100644
--- a/src/main/java/net/minecraft/server/EntityVillager.java
+++ b/src/main/java/net/minecraft/server/EntityVillager.java
@@ -426,7 +426,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation
}
if (merchantrecipe.isRewardExp()) {
- 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, this.getTrader(), this)); // Paper
}
}
diff --git a/src/main/java/net/minecraft/server/EntityVillagerTrader.java b/src/main/java/net/minecraft/server/EntityVillagerTrader.java
index f39de1131f..46a349e73a 100644
--- a/src/main/java/net/minecraft/server/EntityVillagerTrader.java
+++ b/src/main/java/net/minecraft/server/EntityVillagerTrader.java
@@ -147,7 +147,7 @@ public class EntityVillagerTrader extends EntityVillagerAbstract {
if (merchantrecipe.isRewardExp()) {
int i = 3 + this.random.nextInt(4);
- 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, this.getTrader(), this)); // Paper
}
}
diff --git a/src/main/java/net/minecraft/server/PathfinderGoalBreed.java b/src/main/java/net/minecraft/server/PathfinderGoalBreed.java
index d25a05736e..9d0b1ffefa 100644
--- a/src/main/java/net/minecraft/server/PathfinderGoalBreed.java
+++ b/src/main/java/net/minecraft/server/PathfinderGoalBreed.java
@@ -117,7 +117,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 23f64ad001..ff8b11e7ea 100644
--- a/src/main/java/net/minecraft/server/PlayerInteractManager.java
+++ b/src/main/java/net/minecraft/server/PlayerInteractManager.java
@@ -367,7 +367,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 d2698e847c..edc4a5c34e 100644
--- a/src/main/java/net/minecraft/server/SlotFurnaceResult.java
+++ b/src/main/java/net/minecraft/server/SlotFurnaceResult.java
@@ -2,7 +2,7 @@ package net.minecraft.server;
public class SlotFurnaceResult extends Slot {
- private final EntityHuman a;
+ private final EntityHuman a; public final EntityHuman getPlayer() { return this.a; } // Paper OBFHELPER
private int b;
public SlotFurnaceResult(EntityHuman entityhuman, IInventory iinventory, int i, int j, int k) {
diff --git a/src/main/java/net/minecraft/server/TileEntityFurnace.java b/src/main/java/net/minecraft/server/TileEntityFurnace.java
index d68826aa7b..0f6cd246ae 100644
--- a/src/main/java/net/minecraft/server/TileEntityFurnace.java
+++ b/src/main/java/net/minecraft/server/TileEntityFurnace.java
@@ -554,7 +554,7 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I
while (i > 0) {
j = EntityExperienceOrb.getOrbValue(i);
i -= j;
- entityhuman.world.addEntity(new EntityExperienceOrb(entityhuman.world, entityhuman.locX, entityhuman.locY + 0.5D, entityhuman.locZ + 0.5D, j));
+ entityhuman.world.addEntity(new EntityExperienceOrb(entityhuman.world, entityhuman.locX, entityhuman.locY + 0.5D, entityhuman.locZ + 0.5D, j, org.bukkit.entity.ExperienceOrb.SpawnReason.FURNACE, entityhuman)); // Paper
}
}
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 6f8c2a1d2b..9c68334377 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -1608,7 +1608,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 (LightningStrike.class.isAssignableFrom(clazz)) {
entity = new EntityLightning(world, x, y, z, false);
} else if (Firework.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 1b512cc45c..fbad045675 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java
@@ -20,6 +20,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