From 1753b33104c7e6b051b33bddacd1b8197ef90942 Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Sat, 12 Jun 2021 02:01:04 -0700 Subject: [PATCH] even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even even more work --- .../0045-IllegalPacketEvent.patch} | 0 .../0046-Fireworks-API-s.patch} | 0 .../0047-PlayerTeleportEndGatewayEvent.patch} | 0 ...ovide-E-TE-Chunk-count-stat-methods.patch} | 2 +- ...I-for-Reason-Source-Triggering-play.patch} | 0 .../server-remapped/0134-Firework-API-s.patch | 124 --------- ...rovide-E-TE-Chunk-count-stat-methods.patch | 61 ----- ...more-aggressive-in-the-chunk-unload-.patch | 47 ---- .../0143-Do-not-let-armorstands-drown.patch | 42 ---- ...2-Properly-fix-item-duplication-bug.patch} | 14 +- patches/server/0123-Firework-API-s.patch | 99 ++++++++ .../0124-PlayerTeleportEndGatewayEvent.patch} | 8 +- ...rovide-E-TE-Chunk-count-stat-methods.patch | 96 +++++++ .../0126-Enforce-Sync-Player-Saves.patch} | 8 +- ...low-entities-to-ride-themselves-572.patch} | 4 +- ...I-for-Reason-Source-Triggering-play.patch} | 235 ++++++++++-------- .../0129-Cap-Entity-Collisions.patch} | 14 +- ...-CraftScheduler-Async-Task-Debugger.patch} | 24 +- ...more-aggressive-in-the-chunk-unload-.patch | 38 +++ .../0132-Do-not-let-armorstands-drown.patch | 23 ++ ...e-async-calls-to-restart-the-server.patch} | 47 ++-- 21 files changed, 434 insertions(+), 452 deletions(-) rename patches/{api-unmapped/0044-IllegalPacketEvent.patch => api/0045-IllegalPacketEvent.patch} (100%) rename patches/{api-unmapped/0045-Fireworks-API-s.patch => api/0046-Fireworks-API-s.patch} (100%) rename patches/{api-unmapped/0046-PlayerTeleportEndGatewayEvent.patch => api/0047-PlayerTeleportEndGatewayEvent.patch} (100%) rename patches/{api-unmapped/0047-Provide-E-TE-Chunk-count-stat-methods.patch => api/0048-Provide-E-TE-Chunk-count-stat-methods.patch} (93%) rename patches/{api-unmapped/0048-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch => api/0049-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch} (100%) delete mode 100644 patches/server-remapped/0134-Firework-API-s.patch delete mode 100644 patches/server-remapped/0136-Provide-E-TE-Chunk-count-stat-methods.patch delete mode 100644 patches/server-remapped/0142-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch delete mode 100644 patches/server-remapped/0143-Do-not-let-armorstands-drown.patch rename patches/{server-remapped/0132-Properly-fix-item-duplication-bug.patch => server/0122-Properly-fix-item-duplication-bug.patch} (70%) create mode 100644 patches/server/0123-Firework-API-s.patch rename patches/{server-remapped/0135-PlayerTeleportEndGatewayEvent.patch => server/0124-PlayerTeleportEndGatewayEvent.patch} (80%) create mode 100644 patches/server/0125-Provide-E-TE-Chunk-count-stat-methods.patch rename patches/{server-remapped/0137-Enforce-Sync-Player-Saves.patch => server/0126-Enforce-Sync-Player-Saves.patch} (75%) rename patches/{server-remapped/0138-Don-t-allow-entities-to-ride-themselves-572.patch => server/0127-Don-t-allow-entities-to-ride-themselves-572.patch} (80%) rename patches/{server-remapped/0139-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch => server/0128-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch} (59%) rename patches/{server-remapped/0140-Cap-Entity-Collisions.patch => server/0129-Cap-Entity-Collisions.patch} (78%) rename patches/{server-remapped/0141-Remove-CraftScheduler-Async-Task-Debugger.patch => server/0130-Remove-CraftScheduler-Async-Task-Debugger.patch} (62%) create mode 100644 patches/server/0131-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch create mode 100644 patches/server/0132-Do-not-let-armorstands-drown.patch rename patches/{server-remapped/0144-Properly-handle-async-calls-to-restart-the-server.patch => server/0133-Properly-handle-async-calls-to-restart-the-server.patch} (88%) diff --git a/patches/api-unmapped/0044-IllegalPacketEvent.patch b/patches/api/0045-IllegalPacketEvent.patch similarity index 100% rename from patches/api-unmapped/0044-IllegalPacketEvent.patch rename to patches/api/0045-IllegalPacketEvent.patch diff --git a/patches/api-unmapped/0045-Fireworks-API-s.patch b/patches/api/0046-Fireworks-API-s.patch similarity index 100% rename from patches/api-unmapped/0045-Fireworks-API-s.patch rename to patches/api/0046-Fireworks-API-s.patch diff --git a/patches/api-unmapped/0046-PlayerTeleportEndGatewayEvent.patch b/patches/api/0047-PlayerTeleportEndGatewayEvent.patch similarity index 100% rename from patches/api-unmapped/0046-PlayerTeleportEndGatewayEvent.patch rename to patches/api/0047-PlayerTeleportEndGatewayEvent.patch diff --git a/patches/api-unmapped/0047-Provide-E-TE-Chunk-count-stat-methods.patch b/patches/api/0048-Provide-E-TE-Chunk-count-stat-methods.patch similarity index 93% rename from patches/api-unmapped/0047-Provide-E-TE-Chunk-count-stat-methods.patch rename to patches/api/0048-Provide-E-TE-Chunk-count-stat-methods.patch index fc838a6f02..5cd5541fcb 100644 --- a/patches/api-unmapped/0047-Provide-E-TE-Chunk-count-stat-methods.patch +++ b/patches/api/0048-Provide-E-TE-Chunk-count-stat-methods.patch @@ -7,7 +7,7 @@ Provides counts without the ineffeciency of using .getEntities().size() which creates copy of the collections. diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 6b5dbe4ea711807a1944cfe2aae2ce415d4f2638..789e070f6aee83e4b6426def784e05df98e1bc65 100644 +index d3519fa5b99e2888a194c6382415537785fbeef0..8804be419520859355b69660e6f3166d1aa8b1ea 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java @@ -40,6 +40,33 @@ import org.jetbrains.annotations.Nullable; diff --git a/patches/api-unmapped/0048-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch b/patches/api/0049-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch similarity index 100% rename from patches/api-unmapped/0048-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch rename to patches/api/0049-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch diff --git a/patches/server-remapped/0134-Firework-API-s.patch b/patches/server-remapped/0134-Firework-API-s.patch deleted file mode 100644 index e3dc3d3182..0000000000 --- a/patches/server-remapped/0134-Firework-API-s.patch +++ /dev/null @@ -1,124 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 28 Dec 2016 07:18:33 +0100 -Subject: [PATCH] Firework API's - - -diff --git a/src/main/java/net/minecraft/nbt/CompoundTag.java b/src/main/java/net/minecraft/nbt/CompoundTag.java -index 4c8f249e45e5deb7628997d4dbd9dab613ac5241..a91bf94ed9f2f353a685194fc91c4b101ccc1232 100644 ---- a/src/main/java/net/minecraft/nbt/CompoundTag.java -+++ b/src/main/java/net/minecraft/nbt/CompoundTag.java -@@ -153,6 +153,7 @@ public class CompoundTag implements Tag { - return NbtUtils.loadUUID(this.get(key)); - } - -+ public final boolean hasUUID(String s) { return this.hasUUID(s); } // Paper - OBFHELPER - public boolean hasUUID(String key) { - Tag nbtbase = this.get(key); - -diff --git a/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java b/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java -index 28a2c6a0fbc8b4c38f3899698504d8ca0d7ba3af..5669be107b580075fdffbcbb490513593a57fc9f 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java -@@ -37,7 +37,8 @@ public class FireworkRocketEntity extends Projectile { - public static final EntityDataAccessor DATA_SHOT_AT_ANGLE = SynchedEntityData.defineId(FireworkRocketEntity.class, EntityDataSerializers.BOOLEAN); - private int life; - public int lifetime; -- private LivingEntity attachedToEntity; -+ public LivingEntity attachedToEntity; // Paper - public -+ public java.util.UUID spawningEntity; // Paper - - public FireworkRocketEntity(EntityType type, Level world) { - super(type, world); -@@ -284,6 +285,11 @@ public class FireworkRocketEntity extends Projectile { - } - - tag.putBoolean("ShotAtAngle", (Boolean) this.entityData.get(FireworkRocketEntity.DATA_SHOT_AT_ANGLE)); -+ // Paper start -+ if (this.spawningEntity != null) { -+ tag.setUUID("SpawningEntity", this.spawningEntity); -+ } -+ // Paper end - } - - @Override -@@ -300,7 +306,11 @@ public class FireworkRocketEntity extends Projectile { - if (tag.contains("ShotAtAngle")) { - this.entityData.set(FireworkRocketEntity.DATA_SHOT_AT_ANGLE, tag.getBoolean("ShotAtAngle")); - } -- -+ // Paper start -+ if (tag.hasUUID("SpawningEntity")) { -+ this.spawningEntity = tag.getUUID("SpawningEntity"); -+ } -+ // Paper end - } - - @Override -diff --git a/src/main/java/net/minecraft/world/item/CrossbowItem.java b/src/main/java/net/minecraft/world/item/CrossbowItem.java -index 8a358872d3c8357775451e7dffe267cf9121f211..e1e58b7035e6dbafdad0a04cc5333464fc4febb8 100644 ---- a/src/main/java/net/minecraft/world/item/CrossbowItem.java -+++ b/src/main/java/net/minecraft/world/item/CrossbowItem.java -@@ -205,6 +205,7 @@ public class CrossbowItem extends ProjectileWeaponItem implements Vanishable { - - if (flag1) { - object = new FireworkRocketEntity(world, projectile, shooter, shooter.getX(), shooter.getEyeY() - 0.15000000596046448D, shooter.getZ(), true); -+ ((FireworkRocketEntity) object).spawningEntity = shooter.getUUID(); // Paper - } else { - object = getArrow(world, shooter, crossbow, projectile); - if (creative || simulated != 0.0F) { -diff --git a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java -index d3a045fc99ef77fa0905aac7c73a2e84772c73cf..dba52063d402eb2371441fa244b730a3313444fc 100644 ---- a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java -+++ b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java -@@ -27,6 +27,7 @@ public class FireworkRocketItem extends Item { - Vec3 vec3d = context.getClickLocation(); - Direction enumdirection = context.getClickedFace(); - FireworkRocketEntity entityfireworks = new FireworkRocketEntity(world, context.getPlayer(), vec3d.x + (double) enumdirection.getStepX() * 0.15D, vec3d.y + (double) enumdirection.getStepY() * 0.15D, vec3d.z + (double) enumdirection.getStepZ() * 0.15D, itemstack); -+ entityfireworks.spawningEntity = context.getPlayer().getUUID(); // Paper - - world.addFreshEntity(entityfireworks); - itemstack.shrink(1); -@@ -41,7 +42,11 @@ public class FireworkRocketItem extends Item { - ItemStack itemstack = user.getItemInHand(hand); - - if (!world.isClientSide) { -- world.addFreshEntity(new FireworkRocketEntity(world, itemstack, user)); -+ // Paper start -+ final FireworkRocketEntity entityfireworks = new FireworkRocketEntity(world, itemstack, user); -+ entityfireworks.spawningEntity = user.getUUID(); -+ world.addFreshEntity(entityfireworks); -+ // Paper end - if (!user.abilities.instabuild) { - itemstack.shrink(1); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java -index 5901a53b25449430ed02a80b022f83755f83a440..0fbbdd6e3fda3f834d0b0d68d868dbff1aebb673 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java -@@ -1,6 +1,7 @@ - package org.bukkit.craftbukkit.entity; - - import java.util.Random; -+import net.minecraft.world.entity.LivingEntity; - import net.minecraft.world.entity.projectile.FireworkRocketEntity; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.Items; -@@ -78,4 +79,17 @@ public class CraftFirework extends CraftProjectile implements Firework { - public void setShotAtAngle(boolean shotAtAngle) { - getHandle().getEntityData().set(FireworkRocketEntity.DATA_SHOT_AT_ANGLE, shotAtAngle); - } -+ -+ // Paper start -+ @Override -+ public java.util.UUID getSpawningEntity() { -+ return getHandle().spawningEntity; -+ } -+ -+ @Override -+ public org.bukkit.entity.LivingEntity getBoostedEntity() { -+ LivingEntity boostedEntity = getHandle().attachedToEntity; -+ return boostedEntity != null ? (org.bukkit.entity.LivingEntity) boostedEntity.getBukkitEntity() : null; -+ } -+ // Paper end - } diff --git a/patches/server-remapped/0136-Provide-E-TE-Chunk-count-stat-methods.patch b/patches/server-remapped/0136-Provide-E-TE-Chunk-count-stat-methods.patch deleted file mode 100644 index 7b2dc85ab1..0000000000 --- a/patches/server-remapped/0136-Provide-E-TE-Chunk-count-stat-methods.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 7 Jan 2017 15:24:46 -0500 -Subject: [PATCH] Provide E/TE/Chunk count stat methods - -Provides counts without the ineffeciency of using .getEntities().size() -which creates copy of the collections. - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index ca189e5d160d2655175c9fab9366ff93bded2fee..6782888f7df4eea4e6378ee850424e14c5136afd 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -264,6 +264,48 @@ public class CraftWorld implements World { - private int waterAmbientSpawn = -1; - private int ambientSpawn = -1; - -+ // Paper start - Provide fast information methods -+ public int getEntityCount() { -+ int ret = 0; -+ for (net.minecraft.world.entity.Entity entity : world.entitiesById.values()) { -+ if (entity.isChunkLoaded()) { -+ ++ret; -+ } -+ } -+ return ret; -+ } -+ public int getTileEntityCount() { -+ // We don't use the full world tile entity list, so we must iterate chunks -+ Long2ObjectLinkedOpenHashMap chunks = world.getChunkSource().chunkMap.visibleChunkMap; -+ int size = 0; -+ for (ChunkHolder playerchunk : chunks.values()) { -+ net.minecraft.world.level.chunk.LevelChunk chunk = playerchunk.getTickingChunk(); -+ if (chunk == null) { -+ continue; -+ } -+ size += chunk.blockEntities.size(); -+ } -+ return size; -+ } -+ public int getTickableTileEntityCount() { -+ return world.tickableBlockEntities.size(); -+ } -+ public int getChunkCount() { -+ int ret = 0; -+ -+ for (ChunkHolder chunkHolder : world.getChunkSource().chunkMap.visibleChunkMap.values()) { -+ if (chunkHolder.getTickingChunk() != null) { -+ ++ret; -+ } -+ } -+ -+ return ret; -+ } -+ public int getPlayerCount() { -+ return world.players.size(); -+ } -+ // Paper end -+ - private static final Random rand = new Random(); - - public CraftWorld(ServerLevel world, ChunkGenerator gen, Environment env) { diff --git a/patches/server-remapped/0142-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch b/patches/server-remapped/0142-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch deleted file mode 100644 index 740c39b430..0000000000 --- a/patches/server-remapped/0142-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Brokkonaut -Date: Tue, 7 Feb 2017 16:55:35 -0600 -Subject: [PATCH] Make targetSize more aggressive in the chunk unload queue - - -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 175bf535066afc42de8a3f0d11c46af66f3e3e52..3b6f35b695117bd2b0c71b994efc55fa1084eddc 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -119,7 +119,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - private final PlayerMap playerMap; - public final Int2ObjectMap entityMap; - private final Long2ByteMap chunkTypeCache; -- private final Queue unloadQueue; -+ private final Queue unloadQueue; private final Queue getUnloadQueueTasks() { return this.unloadQueue; } // Paper - OBFHELPER - private int viewDistance; - - // CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback() -@@ -177,7 +177,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - this.playerMap = new PlayerMap(); - this.entityMap = new Int2ObjectOpenHashMap(); - this.chunkTypeCache = new Long2ByteOpenHashMap(); -- this.unloadQueue = Queues.newConcurrentLinkedQueue(); -+ this.unloadQueue = new com.destroystokyo.paper.utils.CachedSizeConcurrentLinkedQueue<>(); // Paper - need constant-time size() - this.structureManager = definedstructuremanager; - this.storageFolder = convertable_conversionsession.getDimensionPath(worldserver.dimension()); - this.level = worldserver; -@@ -435,7 +435,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - // Spigot start - org.spigotmc.SlackActivityAccountant activityAccountant = this.level.getServer().slackActivityAccountant; - activityAccountant.startActivity(0.5); -- int targetSize = (int) (this.toDrop.size() * UNLOAD_QUEUE_RESIZE_FACTOR); -+ int targetSize = Math.min(this.toDrop.size() - 100, (int) (this.toDrop.size() * UNLOAD_QUEUE_RESIZE_FACTOR)); // Paper - Make more aggressive - // Spigot end - while (longiterator.hasNext()) { // Spigot - long j = longiterator.nextLong(); -@@ -457,7 +457,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - - Runnable runnable; - -- while ((shouldKeepTicking.getAsBoolean() || this.unloadQueue.size() > 2000) && (runnable = (Runnable) this.unloadQueue.poll()) != null) { -+ int queueTarget = Math.min(this.getUnloadQueueTasks().size() - 100, (int) (this.getUnloadQueueTasks().size() * UNLOAD_QUEUE_RESIZE_FACTOR)); // Paper - Target this queue as well -+ while ((shouldKeepTicking.getAsBoolean() || this.getUnloadQueueTasks().size() > queueTarget) && (runnable = (Runnable)this.getUnloadQueueTasks().poll()) != null) { // Paper - Target this queue as well - runnable.run(); - } - diff --git a/patches/server-remapped/0143-Do-not-let-armorstands-drown.patch b/patches/server-remapped/0143-Do-not-let-armorstands-drown.patch deleted file mode 100644 index d8f5fab54d..0000000000 --- a/patches/server-remapped/0143-Do-not-let-armorstands-drown.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown -Date: Sat, 18 Feb 2017 19:29:58 -0600 -Subject: [PATCH] Do not let armorstands drown - - -diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 3908f54e2216c635d47f8256bac455e7207a5bc6..c1786fcabeaee5732e9197db04268c5c4e164339 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -335,6 +335,7 @@ public abstract class LivingEntity extends Entity { - super.checkFallDamage(heightDifference, onGround, landedState, landedPosition); - } - -+ public boolean canBreatheUnderwater() { return this.canBreatheUnderwater(); } // Paper - OBFHELPER - public boolean canBreatheUnderwater() { - return this.getMobType() == MobType.UNDEAD; - } -@@ -378,7 +379,7 @@ public abstract class LivingEntity extends Entity { - - if (this.isAlive()) { - if (this.isEyeInFluid((Tag) FluidTags.WATER) && !this.level.getBlockState(new BlockPos(this.getX(), this.getEyeY(), this.getZ())).is(Blocks.BUBBLE_COLUMN)) { -- if (!this.canBreatheUnderwater() && !MobEffectUtil.c(this) && !flag1) { -+ if (!this.canBreatheUnderwater() && !MobEffectUtil.c(this) && !flag1) { // Paper - use OBFHELPER so it can be overridden - this.setAirSupply(this.decreaseAirSupply(this.getAirSupply())); - if (this.getAirSupply() == -20) { - this.setAirSupply(0); -diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -index 8b6ec9ddf0d47bf4369b247e764f75893ab15781..59239e202e8e99870ce3be515d2f040ad9786892 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -@@ -868,5 +868,10 @@ public class ArmorStand extends LivingEntity { - super.move(type, movement); - } - } -+ -+ @Override -+ public boolean canBreatheUnderwater() { // Skips a bit of damage handling code, probably a micro-optimization -+ return true; -+ } - // Paper end - } diff --git a/patches/server-remapped/0132-Properly-fix-item-duplication-bug.patch b/patches/server/0122-Properly-fix-item-duplication-bug.patch similarity index 70% rename from patches/server-remapped/0132-Properly-fix-item-duplication-bug.patch rename to patches/server/0122-Properly-fix-item-duplication-bug.patch index aa2398aa87..8262c3fe06 100644 --- a/patches/server-remapped/0132-Properly-fix-item-duplication-bug.patch +++ b/patches/server/0122-Properly-fix-item-duplication-bug.patch @@ -6,25 +6,23 @@ Subject: [PATCH] Properly fix item duplication bug Credit to prplz for figuring out the real issue diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 3cde25c2479adcc4ce3014e5ac2ec0710bffeea9..4ff66138fa43cf932b95d6d3dc050a9cd7b28ad4 100644 +index c60d42c835ed9a1bcc938aa1647c5266b87a05c5..1c4f3a1cfe808d59333e45c170caf0d760a709c9 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -2066,8 +2066,8 @@ public class ServerPlayer extends Player implements ContainerListener { - } +@@ -2124,7 +2124,7 @@ public class ServerPlayer extends Player { @Override -- public boolean isImmobile() { -- return super.isImmobile() || !getBukkitEntity().isOnline(); -+ protected boolean isImmobile() { + public boolean isImmobile() { +- return super.isImmobile() || !this.getBukkitEntity().isOnline(); + return super.isImmobile() || (this.connection != null && this.connection.isDisconnected()); // Paper } @Override diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 1b92c669bbe69bcc07a554b7b43ee99bfebc1af4..ecc393ad94332ec2a59d29f30bd60bade4e1f18e 100644 +index b33ef48a4372dd8ac4a86bdd386a5a7d42583c72..624776a85a3e3268665571635f0b837cb810a62e 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -2818,7 +2818,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -2822,7 +2822,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser } public final boolean isDisconnected() { diff --git a/patches/server/0123-Firework-API-s.patch b/patches/server/0123-Firework-API-s.patch new file mode 100644 index 0000000000..1b1127a6c4 --- /dev/null +++ b/patches/server/0123-Firework-API-s.patch @@ -0,0 +1,99 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 28 Dec 2016 07:18:33 +0100 +Subject: [PATCH] Firework API's + + +diff --git a/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java b/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java +index 15ba8033dc7b5d533f29ab061b1db6dabfba560f..4cd6e5d62dcd319329d617e075aa3a61cdf01e0d 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java +@@ -38,7 +38,8 @@ public class FireworkRocketEntity extends Projectile implements ItemSupplier { + private int life; + public int lifetime; + @Nullable +- private LivingEntity attachedToEntity; ++ public LivingEntity attachedToEntity; // Paper - private -> public ++ public java.util.UUID spawningEntity; // Paper + + public FireworkRocketEntity(EntityType type, Level world) { + super(type, world); +@@ -315,6 +316,11 @@ public class FireworkRocketEntity extends Projectile implements ItemSupplier { + } + + nbt.putBoolean("ShotAtAngle", (Boolean) this.entityData.get(FireworkRocketEntity.DATA_SHOT_AT_ANGLE)); ++ // Paper start ++ if (this.spawningEntity != null) { ++ nbt.setUUID("SpawningEntity", this.spawningEntity); ++ } ++ // Paper end + } + + @Override +@@ -331,7 +337,11 @@ public class FireworkRocketEntity extends Projectile implements ItemSupplier { + if (nbt.contains("ShotAtAngle")) { + this.entityData.set(FireworkRocketEntity.DATA_SHOT_AT_ANGLE, nbt.getBoolean("ShotAtAngle")); + } +- ++ // Paper start ++ if (nbt.hasUUID("SpawningEntity")) { ++ this.spawningEntity = nbt.getUUID("SpawningEntity"); ++ } ++ // Paper end + } + + @Override +diff --git a/src/main/java/net/minecraft/world/item/CrossbowItem.java b/src/main/java/net/minecraft/world/item/CrossbowItem.java +index d336b44f9486ddc93b57938413d8dec4503710fa..35f3f3887c0696b757553af9a5997506c97b24c0 100644 +--- a/src/main/java/net/minecraft/world/item/CrossbowItem.java ++++ b/src/main/java/net/minecraft/world/item/CrossbowItem.java +@@ -222,6 +222,7 @@ public class CrossbowItem extends ProjectileWeaponItem implements Vanishable { + + if (flag1) { + object = new FireworkRocketEntity(world, projectile, shooter, shooter.getX(), shooter.getEyeY() - 0.15000000596046448D, shooter.getZ(), true); ++ ((FireworkRocketEntity) object).spawningEntity = shooter.getUUID(); // Paper + } else { + object = CrossbowItem.getArrow(world, shooter, crossbow, projectile); + if (creative || simulated != 0.0F) { +diff --git a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java +index 409b3c50b87cafba69259ab2232ef607bfce755a..10385dcb851bb435821afba322ed11f59e7ad3e6 100644 +--- a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java ++++ b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java +@@ -46,6 +46,7 @@ public class FireworkRocketItem extends Item { + Vec3 vec3 = context.getClickLocation(); + Direction direction = context.getClickedFace(); + FireworkRocketEntity fireworkRocketEntity = new FireworkRocketEntity(level, context.getPlayer(), vec3.x + (double)direction.getStepX() * 0.15D, vec3.y + (double)direction.getStepY() * 0.15D, vec3.z + (double)direction.getStepZ() * 0.15D, itemStack); ++ fireworkRocketEntity.spawningEntity = context.getPlayer() == null ? null : context.getPlayer().getUUID(); // Paper + level.addFreshEntity(fireworkRocketEntity); + itemStack.shrink(1); + } +@@ -59,6 +60,7 @@ public class FireworkRocketItem extends Item { + ItemStack itemStack = user.getItemInHand(hand); + if (!world.isClientSide) { + FireworkRocketEntity fireworkRocketEntity = new FireworkRocketEntity(world, itemStack, user); ++ fireworkRocketEntity.spawningEntity = user.getUUID(); // Paper + world.addFreshEntity(fireworkRocketEntity); + if (!user.getAbilities().instabuild) { + itemStack.shrink(1); +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java +index 3a1c3d20ecc3612421e346edbbb74ab47f16a137..be86114eac3975b82ca74d4d6ed3f0402a642e8a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java +@@ -78,4 +78,17 @@ public class CraftFirework extends CraftProjectile implements Firework { + public void setShotAtAngle(boolean shotAtAngle) { + this.getHandle().getEntityData().set(FireworkRocketEntity.DATA_SHOT_AT_ANGLE, shotAtAngle); + } ++ ++ // Paper start ++ @Override ++ public java.util.UUID getSpawningEntity() { ++ return getHandle().spawningEntity; ++ } ++ ++ @Override ++ public org.bukkit.entity.LivingEntity getBoostedEntity() { ++ net.minecraft.world.entity.LivingEntity boostedEntity = getHandle().attachedToEntity; ++ return boostedEntity != null ? (org.bukkit.entity.LivingEntity) boostedEntity.getBukkitEntity() : null; ++ } ++ // Paper end + } diff --git a/patches/server-remapped/0135-PlayerTeleportEndGatewayEvent.patch b/patches/server/0124-PlayerTeleportEndGatewayEvent.patch similarity index 80% rename from patches/server-remapped/0135-PlayerTeleportEndGatewayEvent.patch rename to patches/server/0124-PlayerTeleportEndGatewayEvent.patch index 98fb21f40b..99e4760063 100644 --- a/patches/server-remapped/0135-PlayerTeleportEndGatewayEvent.patch +++ b/patches/server/0124-PlayerTeleportEndGatewayEvent.patch @@ -6,10 +6,10 @@ Subject: [PATCH] PlayerTeleportEndGatewayEvent Allows you to access the Gateway being used in a teleport event diff --git a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java -index 07d89af8111673087b0534ca9fac043d3e89662b..2c974f9801d209907733bed8e6c4c9ef46e2b610 100644 +index cf57c89db3082edf22bad89a3e2f1974f682aaa6..2bf65c8da827c6bdbfb74a9d8ee5754584c40c53 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java -@@ -10,6 +10,7 @@ import net.minecraft.data.worldgen.Features; +@@ -11,6 +11,7 @@ import net.minecraft.data.worldgen.Features; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtUtils; import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; @@ -17,12 +17,12 @@ index 07d89af8111673087b0534ca9fac043d3e89662b..2c974f9801d209907733bed8e6c4c9ef import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.util.Mth; -@@ -177,7 +178,7 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity implements +@@ -211,7 +212,7 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity { location.setPitch(player.getLocation().getPitch()); location.setYaw(player.getLocation().getYaw()); - PlayerTeleportEvent teleEvent = new PlayerTeleportEvent(player, player.getLocation(), location, PlayerTeleportEvent.TeleportCause.END_GATEWAY); -+ PlayerTeleportEvent teleEvent = new com.destroystokyo.paper.event.player.PlayerTeleportEndGatewayEvent(player, player.getLocation(), location, new org.bukkit.craftbukkit.block.CraftEndGateway(MCUtil.toLocation(level, this.getBlockPos()).getBlock())); // Paper ++ PlayerTeleportEvent teleEvent = new com.destroystokyo.paper.event.player.PlayerTeleportEndGatewayEvent(player, player.getLocation(), location, new org.bukkit.craftbukkit.block.CraftEndGateway(net.minecraft.server.MCUtil.toLocation(worldserver, blockEntity.getBlockPos()).getBlock())); // Paper Bukkit.getPluginManager().callEvent(teleEvent); if (teleEvent.isCancelled()) { return; diff --git a/patches/server/0125-Provide-E-TE-Chunk-count-stat-methods.patch b/patches/server/0125-Provide-E-TE-Chunk-count-stat-methods.patch new file mode 100644 index 0000000000..dacafbaa5b --- /dev/null +++ b/patches/server/0125-Provide-E-TE-Chunk-count-stat-methods.patch @@ -0,0 +1,96 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 7 Jan 2017 15:24:46 -0500 +Subject: [PATCH] Provide E/TE/Chunk count stat methods + +Provides counts without the ineffeciency of using .getEntities().size() +which creates copy of the collections. + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 8323ddb363f49d266dd95f11241a30a9a27250aa..2cd34f326f374e3ad46a4eea8c84be326cd489a0 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -173,7 +173,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + public static final BlockPos END_SPAWN_POINT = new BlockPos(100, 50, 0); + private static final Logger LOGGER = LogManager.getLogger(); + private static final int EMPTY_TIME_NO_TICK = 300; +- final List players; ++ final List players; public final int getPlayerListSize() { return this.players.size(); } // Paper + public final ServerChunkCache chunkSource; // Paper - public + private final MinecraftServer server; + public final PrimaryLevelData serverLevelData; // CraftBukkit - type +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 52d80086deff664fcfd8952b7cabbfa1f48ad131..a86b5272c0ac4dd64f796f7fd025c7a34a5d2f8d 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -110,7 +110,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public static final int TICKS_PER_DAY = 24000; + public static final int MAX_ENTITY_SPAWN_Y = 20000000; + public static final int MIN_ENTITY_SPAWN_Y = -20000000; +- protected final List blockEntityTickers = Lists.newArrayList(); ++ protected final List blockEntityTickers = Lists.newArrayList(); public final int getTotalTileEntityTickers() { return this.blockEntityTickers.size(); } // Paper + private final List pendingBlockEntityTickers = Lists.newArrayList(); + private boolean tickingBlockEntities; + public final Thread thread; +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 5133febf4b3a83b2870fee2f9e45b1d12894df54..e11a1a21bff1fc5e730d6c63c5b0c623b3b2e037 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -270,6 +270,57 @@ public class CraftWorld implements World { + private int waterAmbientSpawn = -1; + private int ambientSpawn = -1; + ++ // Paper start - Provide fast information methods ++ @Override ++ public int getEntityCount() { ++ int ret = 0; ++ for (net.minecraft.world.entity.Entity entity : world.getEntities().getAll()) { ++ if (entity.isChunkLoaded()) { ++ ++ret; ++ } ++ } ++ return ret; ++ } ++ ++ @Override ++ public int getTileEntityCount() { ++ // We don't use the full world tile entity list, so we must iterate chunks ++ Long2ObjectLinkedOpenHashMap chunks = world.getChunkSource().chunkMap.visibleChunkMap; ++ int size = 0; ++ for (ChunkHolder playerchunk : chunks.values()) { ++ net.minecraft.world.level.chunk.LevelChunk chunk = playerchunk.getTickingChunk(); ++ if (chunk == null) { ++ continue; ++ } ++ size += chunk.blockEntities.size(); ++ } ++ return size; ++ } ++ ++ @Override ++ public int getTickableTileEntityCount() { ++ return world.getTotalTileEntityTickers(); ++ } ++ ++ @Override ++ public int getChunkCount() { ++ int ret = 0; ++ ++ for (ChunkHolder chunkHolder : world.getChunkSource().chunkMap.visibleChunkMap.values()) { ++ if (chunkHolder.getTickingChunk() != null) { ++ ++ret; ++ } ++ } ++ ++ return ret; ++ } ++ ++ @Override ++ public int getPlayerCount() { ++ return world.getPlayerListSize(); ++ } ++ // Paper end ++ + private static final Random rand = new Random(); + + public CraftWorld(ServerLevel world, ChunkGenerator gen, Environment env) { diff --git a/patches/server-remapped/0137-Enforce-Sync-Player-Saves.patch b/patches/server/0126-Enforce-Sync-Player-Saves.patch similarity index 75% rename from patches/server-remapped/0137-Enforce-Sync-Player-Saves.patch rename to patches/server/0126-Enforce-Sync-Player-Saves.patch index 09ab2be15a..5b8d18bd8c 100644 --- a/patches/server-remapped/0137-Enforce-Sync-Player-Saves.patch +++ b/patches/server/0126-Enforce-Sync-Player-Saves.patch @@ -7,18 +7,18 @@ Saving players async is extremely dangerous. This will force it to main the same way we handle async chunk loads. diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 59fb19cfebe4f488fd02f02db31029d44b65e408..cebf536e9d16d44c4b2a91b5b4be053cd7f44045 100644 +index b9c4428bc9653e81ed046bda94e248218c1fa9c9..3eaf106f8f17288857ce1a149d0366cf04235307 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -1043,11 +1043,13 @@ public abstract class PlayerList { +@@ -1027,11 +1027,13 @@ public abstract class PlayerList { } public void saveAll() { -+ MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main ++ net.minecraft.server.MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main MinecraftTimings.savePlayers.startTiming(); // Paper for (int i = 0; i < this.players.size(); ++i) { - this.save((ServerPlayer) this.players.get(i)); -+ this.savePlayerFile((EntityPlayer) this.players.get(i)); ++ this.save(this.players.get(i)); } MinecraftTimings.savePlayers.stopTiming(); // Paper + return null; }); // Paper - ensure main diff --git a/patches/server-remapped/0138-Don-t-allow-entities-to-ride-themselves-572.patch b/patches/server/0127-Don-t-allow-entities-to-ride-themselves-572.patch similarity index 80% rename from patches/server-remapped/0138-Don-t-allow-entities-to-ride-themselves-572.patch rename to patches/server/0127-Don-t-allow-entities-to-ride-themselves-572.patch index da9f57d585..bd141e95f7 100644 --- a/patches/server-remapped/0138-Don-t-allow-entities-to-ride-themselves-572.patch +++ b/patches/server/0127-Don-t-allow-entities-to-ride-themselves-572.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Don't allow entities to ride themselves - #572 diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index c3aece8e5001828edea304b2a8377e9a28b34cfe..a9ed1c3ce6361a86dd58501f5b0ce5d6bbfb8adf 100644 +index 416dd12638540312aa48b530e24ba3ad7ab6079c..ee0efcc86fba880472a6f26f3133d2354a56bf5f 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2045,6 +2045,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -2219,6 +2219,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } protected boolean addPassenger(Entity entity) { // CraftBukkit diff --git a/patches/server-remapped/0139-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch b/patches/server/0128-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch similarity index 59% rename from patches/server-remapped/0139-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch rename to patches/server/0128-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch index 44aa5bf7e5..d3d79693ea 100644 --- a/patches/server-remapped/0139-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch +++ b/patches/server/0128-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch @@ -8,26 +8,26 @@ 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/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -index ed4309d5e567b20fd4aa025e7c82d8943bf1d8e1..26ce794cb8d089c03fab5dd0a0c910783d10b72e 100644 +index f0462770e5e56b28d734f5d097d95de8faee8bbf..9d303a962950c7464d1d4a2a0ce3f658628cc785 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -@@ -409,7 +409,7 @@ public class ServerPlayerGameMode { +@@ -406,7 +406,7 @@ public class ServerPlayerGameMode { // Drop event experience if (flag && event != null) { - iblockdata.getBlock().popExperience(this.level, pos, event.getExpToDrop()); -+ iblockdata.getBlock().dropExperience(this.level, pos, event.getExpToDrop(), this.player); // Paper ++ iblockdata.getBlock().popExperience(this.level, pos, event.getExpToDrop(), this.player); // Paper } return true; diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java -index f932fc4f8240b48f8e518af05d1521bc8ff9cbee..3ddb0a9f15c920c9a2080f76edfda0504c1e287a 100644 +index 1953739fd2ead7680273ef63d8506e546758dc9b..337e861a8b1a89b73560601b704c18dcf446a144 100644 --- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java -@@ -30,13 +30,63 @@ public class ExperienceOrb extends Entity { +@@ -38,13 +38,63 @@ public class ExperienceOrb extends Entity { public int value; + private int count; private Player followingPlayer; - private int followingTime; + // Paper start + public java.util.UUID sourceEntityId; + public java.util.UUID triggerEntityId; @@ -71,11 +71,11 @@ index f932fc4f8240b48f8e518af05d1521bc8ff9cbee..3ddb0a9f15c920c9a2080f76edfda050 + this(world, x, y, z, amount, null, null); + } + -+ public EntityExperienceOrb(Level world, double d0, double d1, double d2, int i, org.bukkit.entity.ExperienceOrb.SpawnReason reason, Entity triggerId) { ++ public ExperienceOrb(Level 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(Level world, double d0, double d1, double d2, int i, org.bukkit.entity.ExperienceOrb.SpawnReason reason, Entity triggerId, Entity sourceId) { ++ public ExperienceOrb(Level world, double d0, double d1, double d2, int i, org.bukkit.entity.ExperienceOrb.SpawnReason reason, Entity triggerId, Entity sourceId) { this(EntityType.EXPERIENCE_ORB, world); - this.setPos(x, y, z); + this.sourceEntityId = sourceId != null ? sourceId.getUUID() : null; @@ -83,61 +83,83 @@ index f932fc4f8240b48f8e518af05d1521bc8ff9cbee..3ddb0a9f15c920c9a2080f76edfda050 + this.spawnReason = reason != null ? reason : org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN; + // Paper end + this.setPos(d0, d1, d2); - this.yRot = (float) (this.random.nextDouble() * 360.0D); + this.setYRot((float) (this.random.nextDouble() * 360.0D)); this.setDeltaMovement((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); - this.value = amount; + this.value = i; } public ExperienceOrb(EntityType type, Level world) { -@@ -167,6 +217,7 @@ public class ExperienceOrb extends Entity { - tag.putShort("Health", (short) this.health); - tag.putShort("Age", (short) this.age); - tag.putShort("Value", (short) this.value); -+ this.savePaperNBT(tag); // Paper +@@ -154,12 +204,20 @@ public class ExperienceOrb extends Entity { + } + + public static void award(ServerLevel world, Vec3 pos, int amount) { ++ // Paper start - add reasons for orbs ++ award(world, pos, amount, null, null, null); ++ } ++ public static void award(ServerLevel world, Vec3 pos, int amount, org.bukkit.entity.ExperienceOrb.SpawnReason reason, Entity triggerId) { ++ award(world, pos, amount, reason, triggerId, null); ++ } ++ public static void award(ServerLevel world, Vec3 pos, int amount, org.bukkit.entity.ExperienceOrb.SpawnReason reason, Entity triggerId, Entity sourceId) { ++ // Paper end - add reasons for orbs + while (amount > 0) { + int j = ExperienceOrb.getExperienceValue(amount); + + amount -= j; + if (!ExperienceOrb.tryMergeToExisting(world, pos, j)) { +- world.addFreshEntity(new ExperienceOrb(world, pos.x(), pos.y(), pos.z(), j)); ++ world.addFreshEntity(new ExperienceOrb(world, pos.x(), pos.y(), pos.z(), j, reason, triggerId, sourceId)); // Paper - add reason + } + } + +@@ -230,6 +288,7 @@ public class ExperienceOrb extends Entity { + nbt.putShort("Age", (short) this.age); + nbt.putShort("Value", (short) this.value); + nbt.putInt("Count", this.count); ++ this.savePaperNBT(nbt); // Paper } @Override -@@ -174,6 +225,7 @@ public class ExperienceOrb extends Entity { - this.health = tag.getShort("Health"); - this.age = tag.getShort("Age"); - this.value = tag.getShort("Value"); -+ this.loadPaperNBT(tag); // Paper +@@ -238,6 +297,7 @@ public class ExperienceOrb extends Entity { + this.age = nbt.getShort("Age"); + this.value = nbt.getShort("Value"); + this.count = Math.max(nbt.getInt("Count"), 1); ++ this.loadPaperNBT(nbt); // Paper } @Override diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 1131d86080b3100437aa18a00c6277fcea4b7ea8..c6aa5328907f85cd210b1c20ff407e60d9b03349 100644 +index 041a61e037e7f6fddd94567f2954be600c737811..971e4c6d742e0c63b3c5dfa6d87b2468f8ce5010 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -1591,7 +1591,8 @@ public abstract class LivingEntity extends Entity { - int j = ExperienceOrb.getExperienceValue(i); - - i -= j; -- this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY(), this.getZ(), j)); -+ LivingEntity attacker = lastHurtByPlayer != null ? lastHurtByPlayer : lastHurtByMob; // Paper -+ this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY(), this.getZ(), j, this instanceof ServerPlayer ? org.bukkit.entity.ExperienceOrb.SpawnReason.PLAYER_DEATH : org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, attacker, this)); // Paper - } +@@ -1699,7 +1699,8 @@ public abstract class LivingEntity extends Entity { + protected void dropExperience() { + // CraftBukkit start - Update getExpReward() above if the removed if() changes! + if (true) { +- ExperienceOrb.award((ServerLevel) this.level, this.position(), this.expToDrop); ++ LivingEntity attacker = this.lastHurtByPlayer != null ? this.lastHurtByPlayer : this.lastHurtByMob; // Paper ++ ExperienceOrb.award((ServerLevel) this.level, this.position(), this.expToDrop, this instanceof ServerPlayer ? 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/world/entity/animal/Animal.java b/src/main/java/net/minecraft/world/entity/animal/Animal.java -index ab2a19554aa1541e924104a70364f957ff8b33f9..e0f2a70870ff97ae2e8f216a202787bbcba6c6a9 100644 +index b8163a04f5aad326e78416b270dc64ffc913ccc5..5a503a255b4e7e684a8f42d8190430397ca81683 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Animal.java +++ b/src/main/java/net/minecraft/world/entity/animal/Animal.java -@@ -260,7 +260,7 @@ public abstract class Animal extends AgableMob { - if (worldserver.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { +@@ -264,7 +264,7 @@ public abstract class Animal extends AgeableMob { + if (world.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { // CraftBukkit start - use event experience if (experience > 0) { -- worldserver.addFreshEntity(new ExperienceOrb(worldserver, this.getX(), this.getY(), this.getZ(), experience)); -+ worldserver.addFreshEntity(new ExperienceOrb(worldserver, this.getX(), this.getY(), this.getZ(), experience, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer, entityageable)); // Paper +- world.addFreshEntity(new ExperienceOrb(world, this.getX(), this.getY(), this.getZ(), experience)); ++ world.addFreshEntity(new ExperienceOrb(world, this.getX(), this.getY(), this.getZ(), experience, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer, entityageable)); // Paper } // CraftBukkit end } diff --git a/src/main/java/net/minecraft/world/entity/animal/Fox.java b/src/main/java/net/minecraft/world/entity/animal/Fox.java -index 83fcfd888a335e3c054174e1f55e92fea878f7ab..c2d98222f575d7383e4c040730f6d531bdb0d7b6 100644 +index 0fd1dfacca88cd5399e05cb7ebc0150491e8f59c..c1cdb1905536bda76f34ad3fc796996443839767 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Fox.java +++ b/src/main/java/net/minecraft/world/entity/animal/Fox.java -@@ -1306,7 +1306,7 @@ public class Fox extends Animal { +@@ -883,7 +883,7 @@ public class Fox extends Animal { if (this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { // CraftBukkit start - use event experience if (experience > 0) { @@ -147,10 +169,10 @@ index 83fcfd888a335e3c054174e1f55e92fea878f7ab..c2d98222f575d7383e4c040730f6d531 // CraftBukkit end } diff --git a/src/main/java/net/minecraft/world/entity/animal/Turtle.java b/src/main/java/net/minecraft/world/entity/animal/Turtle.java -index 2ae59200ed67ab68645b569ba03839e8cedc9aa8..c54f4b83b9f2fdb15ddb363be0a179a05eb3693b 100644 +index 593442f0f2d58e2e0a0a86d6f16aea90cc36d184..b782d278463a72b8514719e9b14986f268828772 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Turtle.java +++ b/src/main/java/net/minecraft/world/entity/animal/Turtle.java -@@ -561,7 +561,7 @@ public class Turtle extends Animal { +@@ -455,7 +455,7 @@ public class Turtle extends Animal { Random random = this.animal.getRandom(); if (this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { @@ -160,23 +182,32 @@ index 2ae59200ed67ab68645b569ba03839e8cedc9aa8..c54f4b83b9f2fdb15ddb363be0a179a0 } diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java -index 39298b69918da890c3faa516f80d1a69adb88fe2..ae3cf71f14526e1f356216dfaa899c8f5083d46d 100644 +index 9d6d8bf5f38ec11f26665ae676c46e4ef089670b..e286d4ed03eba05b862741cb98db8a031224cd98 100644 --- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java -@@ -661,7 +661,7 @@ public class EnderDragon extends Mob implements Enemy { - int j = ExperienceOrb.getExperienceValue(amount); +@@ -634,7 +634,7 @@ public class EnderDragon extends Mob implements Enemy { - amount -= j; -- this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY(), this.getZ(), j)); -+ this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY(), this.getZ(), j, org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, this.lastHurtByPlayer, this)); // Paper - } + if (this.level instanceof ServerLevel) { + if (this.dragonDeathTime > 150 && this.dragonDeathTime % 5 == 0 && flag) { +- ExperienceOrb.award((ServerLevel) this.level, this.position(), Mth.floor((float) short0 * 0.08F)); ++ ExperienceOrb.award((ServerLevel) this.level, this.position(), Mth.floor((float) short0 * 0.08F), org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, this.lastHurtByPlayer, this); // Paper + } - } + if (this.dragonDeathTime == 1 && !this.isSilent()) { +@@ -665,7 +665,7 @@ public class EnderDragon extends Mob implements Enemy { + this.yBodyRot = this.getYRot(); + if (this.dragonDeathTime == 200 && this.level instanceof ServerLevel) { + if (flag) { +- ExperienceOrb.award((ServerLevel) this.level, this.position(), Mth.floor((float) short0 * 0.2F)); ++ ExperienceOrb.award((ServerLevel) this.level, this.position(), Mth.floor((float) short0 * 0.2F), org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, this.lastHurtByPlayer, this); // Paper + } + + if (this.dragonFight != null) { diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java -index 5648a4a4d8511ac8c46c61245a7ff83753a3e51f..a66fab2e04a5d87ced139ed15d2434c5ffcec695 100644 +index 731aea63eedb8cb37291bb2238ff8ab2e3a5f6eb..6a9e2105b2d9a4ee83c0a2516d5ef26dc3b99053 100644 --- a/src/main/java/net/minecraft/world/entity/npc/Villager.java +++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java -@@ -599,7 +599,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -616,7 +616,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler } if (offer.shouldRewardExp()) { @@ -186,10 +217,10 @@ index 5648a4a4d8511ac8c46c61245a7ff83753a3e51f..a66fab2e04a5d87ced139ed15d2434c5 } diff --git a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java -index 15570b9ba2443ce8c6f48dfbc13cdf45de8b45ac..69d92590d265abe8a04d8bf48bbe9a6ae606ae50 100644 +index 892603dabb17e77ac0b038617f00f2d3d1c728ac..59c4ab697ef0a336ffce19d215952f3a8ff0852b 100644 --- a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java +++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java -@@ -188,7 +188,7 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill +@@ -187,7 +187,7 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill if (offer.shouldRewardExp()) { int i = 3 + this.random.nextInt(4); @@ -199,10 +230,10 @@ index 15570b9ba2443ce8c6f48dfbc13cdf45de8b45ac..69d92590d265abe8a04d8bf48bbe9a6a } diff --git a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java -index fa078167dd9e0cae80516549eef0e554c13938a3..7bff012f3cd4458673ee02e5f5f830fc0ef983a3 100644 +index d25fe9cb2cf755f3e34a79ce87ed38c1ffada53f..0258d0699afe7ceec19154c669b10298e6e1bf95 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java +++ b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java -@@ -500,7 +500,7 @@ public class FishingHook extends Projectile { +@@ -516,7 +516,7 @@ public class FishingHook extends Projectile { this.level.addFreshEntity(entityitem); // CraftBukkit start - this.random.nextInt(6) + 1 -> playerFishEvent.getExpToDrop() if (playerFishEvent.getExpToDrop() > 0) { @@ -210,25 +241,25 @@ index fa078167dd9e0cae80516549eef0e554c13938a3..7bff012f3cd4458673ee02e5f5f830fc + entityhuman.level.addFreshEntity(new ExperienceOrb(entityhuman.level, entityhuman.getX(), entityhuman.getY() + 0.5D, entityhuman.getZ() + 0.5D, playerFishEvent.getExpToDrop(), org.bukkit.entity.ExperienceOrb.SpawnReason.FISHING, this.getPlayerOwner(), this)); // Paper } // CraftBukkit end - if (itemstack1.getItem().is((Tag) ItemTags.FISHES)) { + if (itemstack1.is((Tag) ItemTags.FISHES)) { diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java -index 85b8f8f52c5035054ad9f665fce735260a54c270..42c7371355b6e36e31daf055317f015240761b8b 100644 +index 467f9814e0991d31bff7259f266262c81328f05f..11d1db5ef709dfb6fa596ebc4f5fff1415ad4f6d 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java +++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java -@@ -54,7 +54,7 @@ public class ThrownExperienceBottle extends ThrowableItemProjectile { - int j = ExperienceOrb.getExperienceValue(i); - - i -= j; -- this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY(), this.getZ(), j)); -+ this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY(), this.getZ(), j, org.bukkit.entity.ExperienceOrb.SpawnReason.EXP_BOTTLE, getOwner(), this)); // Paper +@@ -51,7 +51,7 @@ public class ThrownExperienceBottle extends ThrowableItemProjectile { } + // CraftBukkit end + +- ExperienceOrb.award((ServerLevel) this.level, this.position(), i); ++ ExperienceOrb.award((ServerLevel) this.level, this.position(), i, org.bukkit.entity.ExperienceOrb.SpawnReason.EXP_BOTTLE, this.getOwner(), this); // Paper + this.discard(); + } - this.remove(); diff --git a/src/main/java/net/minecraft/world/inventory/FurnaceResultSlot.java b/src/main/java/net/minecraft/world/inventory/FurnaceResultSlot.java -index ea6e1a96bd1fa9fbb87f65a169aa1e5af0589f34..5b9111d502bc12ab9e5c37e4d66c21aa37007b53 100644 +index d486b8d7d80bc79c5af6106de56a3ba49021258e..6f26688347ff2c206ab0b3ccae30b95ee7475fa2 100644 --- a/src/main/java/net/minecraft/world/inventory/FurnaceResultSlot.java +++ b/src/main/java/net/minecraft/world/inventory/FurnaceResultSlot.java -@@ -7,7 +7,7 @@ import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; +@@ -8,7 +8,7 @@ import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; public class FurnaceResultSlot extends Slot { @@ -238,81 +269,69 @@ index ea6e1a96bd1fa9fbb87f65a169aa1e5af0589f34..5b9111d502bc12ab9e5c37e4d66c21aa public FurnaceResultSlot(Player player, Container inventory, int index, int x, int y) { diff --git a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java -index e8bc37e1f7aebd192f048d7b056a41c50ceef9f5..e9e830117fe3e4e02a51eef8671a3d3b48c2858e 100644 +index 473e17d87637cd1a85880e2956f83de0b510b488..34574f3945d2a7b4ab6a71adb2408b9811a3cb0d 100644 --- a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java +++ b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java -@@ -93,7 +93,7 @@ public class GrindstoneMenu extends AbstractContainerMenu { - int k = ExperienceOrb.getExperienceValue(j); - - j -= k; -- world.addFreshEntity(new ExperienceOrb(world, (double) blockposition.getX(), (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, k)); -+ world.addFreshEntity(new ExperienceOrb(world, (double) blockposition.getX(), (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, k, org.bukkit.entity.ExperienceOrb.SpawnReason.GRINDSTONE, player)); // Paper +@@ -98,7 +98,7 @@ public class GrindstoneMenu extends AbstractContainerMenu { + public void onTake(net.minecraft.world.entity.player.Player player, ItemStack stack) { + context.execute((world, blockposition) -> { + if (world instanceof ServerLevel) { +- ExperienceOrb.award((ServerLevel) world, Vec3.atCenterOf((Vec3i) blockposition), this.getExperienceAmount(world)); ++ ExperienceOrb.award((ServerLevel) world, Vec3.atCenterOf((Vec3i) blockposition), this.getExperienceAmount(world), org.bukkit.entity.ExperienceOrb.SpawnReason.GRINDSTONE, player); // Paper } world.levelEvent(1042, blockposition, 0); diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java -index 2ae786b8fc6da19ca2a40252b0606f9e06d31ded..9d2e4adddae481735053c64eec0ee7259c61f1a4 100644 +index c27e755f93a2b2e203b305e0cae2c782a34e38cc..27016f964d2f6458298a9052d031a44b3d9f5f4b 100644 --- a/src/main/java/net/minecraft/world/level/block/Block.java +++ b/src/main/java/net/minecraft/world/level/block/Block.java -@@ -267,13 +267,13 @@ public class Block extends BlockBehaviour implements ItemLike { - } +@@ -374,8 +374,13 @@ public class Block extends BlockBehaviour implements ItemLike { } -- public void popExperience(ServerLevel world, BlockPos pos, int size) { -- if (world.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) { -- while (size > 0) { -- int j = ExperienceOrb.getExperienceValue(size); -+ public void dropExperience(ServerLevel worldserver, BlockPos blockposition, int i, net.minecraft.server.level.ServerPlayer player) { // Paper -+ if (worldserver.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) { -+ while (i > 0) { -+ int j = ExperienceOrb.getExperienceValue(i); - -- size -= j; -- world.addFreshEntity(new ExperienceOrb(world, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, j)); -+ i -= j; -+ worldserver.addFreshEntity(new ExperienceOrb(worldserver, (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 - } + public void popExperience(ServerLevel world, BlockPos pos, int size) { ++ // Paper start - add player parameter ++ popExperience(world, pos, size, null); ++ } ++ public void popExperience(ServerLevel world, BlockPos pos, int size, net.minecraft.server.level.ServerPlayer player) { ++ // Paper end - add player parameter + if (world.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) { +- ExperienceOrb.award(world, Vec3.atCenterOf((Vec3i) pos), size); ++ ExperienceOrb.award(world, Vec3.atCenterOf((Vec3i) pos), size, org.bukkit.entity.ExperienceOrb.SpawnReason.BLOCK_BREAK, player); // Paper } + } diff --git a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -index 7a2554c5cd18e0c5e482ba8ba68a098d533b6a4f..8c55c1d88ef2e20e82bcdae0b9b3d381e562051f 100644 +index 11ed01b3ebe4c71e3d3c767887a5dca6033fdf3c..52b2b27f8f8b542a930d649ed6904b4bf808906c 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -@@ -601,7 +601,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit - int k = ExperienceOrb.getExperienceValue(j); - - j -= k; -- world.addFreshEntity(new ExperienceOrb(world, vec3d.x, vec3d.y, vec3d.z, k)); -+ world.addFreshEntity(new ExperienceOrb(world, vec3d.x, vec3d.y, vec3d.z, k, org.bukkit.entity.ExperienceOrb.SpawnReason.FURNACE, entityhuman)); // Paper +@@ -606,7 +606,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit } + // CraftBukkit end +- ExperienceOrb.award(worldserver, vec3d, j); ++ ExperienceOrb.award(worldserver, vec3d, j, org.bukkit.entity.ExperienceOrb.SpawnReason.FURNACE, entityhuman); // Paper } + + @Override diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 6782888f7df4eea4e6378ee850424e14c5136afd..88658d4deacc29128c537e2e02fdc8f684090a2c 100644 +index e11a1a21bff1fc5e730d6c63c5b0c623b3b2e037..e396450366ebee663dd5ad5f59e5d6bccece0679 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -1817,7 +1817,7 @@ public class CraftWorld implements World { +@@ -1836,7 +1836,7 @@ public class CraftWorld implements World { } else if (TNTPrimed.class.isAssignableFrom(clazz)) { - entity = new PrimedTnt(world, x, y, z, null); + entity = new PrimedTnt(this.world, x, y, z, null); } else if (ExperienceOrb.class.isAssignableFrom(clazz)) { -- entity = new net.minecraft.world.entity.ExperienceOrb(world, x, y, z, 0); -+ entity = new net.minecraft.world.entity.ExperienceOrb(world, x, y, z, 0, org.bukkit.entity.ExperienceOrb.SpawnReason.CUSTOM, null, null); // Paper +- entity = new net.minecraft.world.entity.ExperienceOrb(this.world, x, y, z, 0); ++ entity = new net.minecraft.world.entity.ExperienceOrb(this.world, x, y, z, 0, org.bukkit.entity.ExperienceOrb.SpawnReason.CUSTOM, null, null); // Paper } else if (LightningStrike.class.isAssignableFrom(clazz)) { entity = net.minecraft.world.entity.EntityType.LIGHTNING_BOLT.create(world); } else if (AreaEffectCloud.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 3b450d97302bab30cdb975c8332b81318470503e..d5b8fd76ec3bd7d2621231480eb3e694a90aa037 100644 +index 40713228b149b4532fcee3a54bbe63e161318258..84899284703baeb04bfc79251941265d52ac07e8 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java -@@ -1,5 +1,6 @@ - package org.bukkit.craftbukkit.entity; - -+import SpawnReason; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.entity.EntityType; - import org.bukkit.entity.ExperienceOrb; -@@ -19,6 +20,18 @@ public class CraftExperienceOrb extends CraftEntity implements ExperienceOrb { - getHandle().value = value; +@@ -19,6 +19,18 @@ public class CraftExperienceOrb extends CraftEntity implements ExperienceOrb { + this.getHandle().value = value; } + // Paper start diff --git a/patches/server-remapped/0140-Cap-Entity-Collisions.patch b/patches/server/0129-Cap-Entity-Collisions.patch similarity index 78% rename from patches/server-remapped/0140-Cap-Entity-Collisions.patch rename to patches/server/0129-Cap-Entity-Collisions.patch index 7b28bfe328..60e8f97038 100644 --- a/patches/server-remapped/0140-Cap-Entity-Collisions.patch +++ b/patches/server/0129-Cap-Entity-Collisions.patch @@ -27,10 +27,10 @@ index 2dc58b9f769ea43b737804456aafab47ecc143b8..c611b5a63498f5ad1f50a75ccd5d7299 + } } diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index a9ed1c3ce6361a86dd58501f5b0ce5d6bbfb8adf..a017fa55002d6674124befa3f6e81eb70c9ce8f7 100644 +index ee0efcc86fba880472a6f26f3133d2354a56bf5f..0204bde9802429aca5470c235cb10232e5c8f58a 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -267,6 +267,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -301,6 +301,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); public final boolean defaultActivationState; public long activatedTick = Integer.MIN_VALUE; @@ -39,19 +39,19 @@ index a9ed1c3ce6361a86dd58501f5b0ce5d6bbfb8adf..a017fa55002d6674124befa3f6e81eb7 // Spigot end diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index c6aa5328907f85cd210b1c20ff407e60d9b03349..3908f54e2216c635d47f8256bac455e7207a5bc6 100644 +index 971e4c6d742e0c63b3c5dfa6d87b2468f8ce5010..f0357f9d7b6a39bbdf6486a9d35d890942cc5e4c 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -2900,8 +2900,11 @@ public abstract class LivingEntity extends Entity { +@@ -3224,8 +3224,11 @@ public abstract class LivingEntity extends Entity { } } - for (j = 0; j < list.size(); ++j) { -+ numCollisions = Math.max(0, numCollisions - level.paperConfig.maxCollisionsPerEntity); // Paper -+ for (j = 0; j < list.size() && numCollisions < level.paperConfig.maxCollisionsPerEntity; ++j) { // Paper ++ this.numCollisions = Math.max(0, this.numCollisions - this.level.paperConfig.maxCollisionsPerEntity); // Paper ++ for (j = 0; j < list.size() && this.numCollisions < this.level.paperConfig.maxCollisionsPerEntity; ++j) { // Paper Entity entity = (Entity) list.get(j); + entity.numCollisions++; // Paper -+ numCollisions++; // Paper ++ this.numCollisions++; // Paper this.doPush(entity); } diff --git a/patches/server-remapped/0141-Remove-CraftScheduler-Async-Task-Debugger.patch b/patches/server/0130-Remove-CraftScheduler-Async-Task-Debugger.patch similarity index 62% rename from patches/server-remapped/0141-Remove-CraftScheduler-Async-Task-Debugger.patch rename to patches/server/0130-Remove-CraftScheduler-Async-Task-Debugger.patch index db58842a96..7ce11b5799 100644 --- a/patches/server-remapped/0141-Remove-CraftScheduler-Async-Task-Debugger.patch +++ b/patches/server/0130-Remove-CraftScheduler-Async-Task-Debugger.patch @@ -9,24 +9,24 @@ One report of a suspected memory leak with the system. This adds additional overhead to asynchronous task dispatching diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index 9b6d9373abb59a30c2835ca891282d07559281f5..0e0f361c3af363539d5d1d865603114bdb84fd67 100644 +index 0735c2fe139ce8d47a04fdba045fe462492723eb..6435d53dcddc1a43420f1ea66fa08e154b82586d 100644 --- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java @@ -430,7 +430,7 @@ public class CraftScheduler implements BukkitScheduler { } - parsePending(); + this.parsePending(); } else { -- debugTail = debugTail.setNext(new CraftAsyncDebugger(currentTick + RECENT_TICKS, task.getOwner(), task.getTaskClass())); -+ //debugTail = debugTail.setNext(new CraftAsyncDebugger(currentTick + RECENT_TICKS, task.getOwner(), task.getTaskClass())); // Paper - executor.execute(new ServerSchedulerReportingWrapper(task)); // Paper +- this.debugTail = this.debugTail.setNext(new CraftAsyncDebugger(currentTick + CraftScheduler.RECENT_TICKS, task.getOwner(), task.getTaskClass())); ++ //this.debugTail = this.debugTail.setNext(new CraftAsyncDebugger(currentTick + CraftScheduler.RECENT_TICKS, task.getOwner(), task.getTaskClass())); // Paper + this.executor.execute(new ServerSchedulerReportingWrapper(task)); // Paper // We don't need to parse pending // (async tasks must live with race-conditions if they attempt to cancel between these few lines of code) @@ -447,7 +447,7 @@ public class CraftScheduler implements BukkitScheduler { - pending.addAll(temp); + this.pending.addAll(temp); temp.clear(); - MinecraftTimings.bukkitSchedulerFinishTimer.stopTiming(); -- debugHead = debugHead.getNextHead(currentTick); -+ //debugHead = debugHead.getNextHead(currentTick); // Paper + MinecraftTimings.bukkitSchedulerFinishTimer.stopTiming(); // Paper +- this.debugHead = this.debugHead.getNextHead(currentTick); ++ //this.debugHead = this.debugHead.getNextHead(currentTick); // Paper } private void addTask(final CraftTask task) { @@ -37,9 +37,9 @@ index 9b6d9373abb59a30c2835ca891282d07559281f5..0e0f361c3af363539d5d1d865603114b + // Paper start + return ""; + /* - int debugTick = currentTick; - StringBuilder string = new StringBuilder("Recent tasks from ").append(debugTick - RECENT_TICKS).append('-').append(debugTick).append('{'); - debugHead.debugTo(string); + int debugTick = this.currentTick; + StringBuilder string = new StringBuilder("Recent tasks from ").append(debugTick - CraftScheduler.RECENT_TICKS).append('-').append(debugTick).append('{'); + this.debugHead.debugTo(string); return string.append('}').toString(); + */ + // Paper end diff --git a/patches/server/0131-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch b/patches/server/0131-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch new file mode 100644 index 0000000000..091d6d3c36 --- /dev/null +++ b/patches/server/0131-Make-targetSize-more-aggressive-in-the-chunk-unload-.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Brokkonaut +Date: Tue, 7 Feb 2017 16:55:35 -0600 +Subject: [PATCH] Make targetSize more aggressive in the chunk unload queue + + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index da97afe93a98daac33f143c6da0b42f71db25dba..5a80ea6bee72921454fbbd6ee202dc114c481ea1 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -185,7 +185,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.playerMap = new PlayerMap(); + this.entityMap = new Int2ObjectOpenHashMap(); + this.chunkTypeCache = new Long2ByteOpenHashMap(); +- this.unloadQueue = Queues.newConcurrentLinkedQueue(); ++ this.unloadQueue = new com.destroystokyo.paper.utils.CachedSizeConcurrentLinkedQueue<>(); // Paper - need constant-time size() + this.structureManager = structureManager; + this.storageFolder = session.getDimensionPath(world.dimension()); + this.level = world; +@@ -478,7 +478,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + // Spigot start + org.spigotmc.SlackActivityAccountant activityAccountant = this.level.getServer().slackActivityAccountant; + activityAccountant.startActivity(0.5); +- int targetSize = (int) (this.toDrop.size() * ChunkMap.UNLOAD_QUEUE_RESIZE_FACTOR); ++ int targetSize = Math.min(this.toDrop.size() - 100, (int) (this.toDrop.size() * ChunkMap.UNLOAD_QUEUE_RESIZE_FACTOR)); // Paper - Make more aggressive + // Spigot end + while (longiterator.hasNext()) { // Spigot + long j = longiterator.nextLong(); +@@ -500,7 +500,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + Runnable runnable; + +- while ((shouldKeepTicking.getAsBoolean() || this.unloadQueue.size() > 2000) && (runnable = (Runnable) this.unloadQueue.poll()) != null) { ++ int queueTarget = Math.min(this.unloadQueue.size() - 100, (int) (this.unloadQueue.size() * UNLOAD_QUEUE_RESIZE_FACTOR)); // Paper - Target this queue as well ++ while ((shouldKeepTicking.getAsBoolean() || this.unloadQueue.size() > queueTarget) && (runnable = (Runnable)this.unloadQueue.poll()) != null) { // Paper - Target this queue as well + runnable.run(); + } + diff --git a/patches/server/0132-Do-not-let-armorstands-drown.patch b/patches/server/0132-Do-not-let-armorstands-drown.patch new file mode 100644 index 0000000000..466f346419 --- /dev/null +++ b/patches/server/0132-Do-not-let-armorstands-drown.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown +Date: Sat, 18 Feb 2017 19:29:58 -0600 +Subject: [PATCH] Do not let armorstands drown + + +diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +index ef382aaeb86ca41356a076ff4adfe5fb652b43c5..cda073a8ab9daed75f284cbbe4459991fba348f0 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +@@ -936,5 +936,12 @@ public class ArmorStand extends LivingEntity { + super.move(type, movement); + } + } ++ ++ // Paper start ++ @Override ++ public boolean canBreatheUnderwater() { // Skips a bit of damage handling code, probably a micro-optimization ++ return true; ++ } ++ // Paper end + // Paper end + } diff --git a/patches/server-remapped/0144-Properly-handle-async-calls-to-restart-the-server.patch b/patches/server/0133-Properly-handle-async-calls-to-restart-the-server.patch similarity index 88% rename from patches/server-remapped/0144-Properly-handle-async-calls-to-restart-the-server.patch rename to patches/server/0133-Properly-handle-async-calls-to-restart-the-server.patch index 761e1f8b83..71da2cb2bf 100644 --- a/patches/server-remapped/0144-Properly-handle-async-calls-to-restart-the-server.patch +++ b/patches/server/0133-Properly-handle-async-calls-to-restart-the-server.patch @@ -30,10 +30,10 @@ will have plugins and worlds saving to the disk has a high potential to result in corruption/dataloss. diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 211251fe7cd08074c040df2f4642f37d5f90d856..f41d79c6630fd8daae28476ffc854f7e65d841e6 100644 +index 74073d3f8c9dda6f10e9fb34071dae079b73fb24..1617c59bf689e5f67c2af5c3a22ce5791d47b408 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -199,6 +199,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop, ServerLevel> levels; private PlayerList playerList; private volatile boolean running; @@ -41,67 +41,50 @@ index 211251fe7cd08074c040df2f4642f37d5f90d856..f41d79c6630fd8daae28476ffc854f7e private boolean stopped; private int tickCount; protected final Proxy proxy; -@@ -858,7 +859,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop