More patch work
This commit is contained in:
		
					parent
					
						
							
								bd5d09cb3f
							
						
					
				
			
			
				commit
				
					
						fe5f51f44e
					
				
			
		
					 35 changed files with 68 additions and 419 deletions
				
			
		| 
						 | 
				
			
			@ -39,9 +39,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 | 
			
		|||
+                        // Paper start - ItemFactory#getSpawnEgg (paper had original method that returned ItemStack, upstream added identical but returned Material)
 | 
			
		||||
+                        if (owner.equals("org/bukkit/inventory/ItemFactory") && name.equals("getSpawnEgg") && desc.equals("(Lorg/bukkit/entity/EntityType;)Lorg/bukkit/inventory/ItemStack;")) {
 | 
			
		||||
+                            super.visitInsn(Opcodes.SWAP); // has 1 param, this moves the owner instance to the top for the checkcast
 | 
			
		||||
+                            super.visitTypeInsn(Opcodes.CHECKCAST, CB_PACKAGE + "/inventory/CraftItemFactory");
 | 
			
		||||
+                            super.visitTypeInsn(Opcodes.CHECKCAST, CB_PACKAGE_PREFIX + "inventory/CraftItemFactory");
 | 
			
		||||
+                            super.visitInsn(Opcodes.SWAP); // moves param back to the the top of stack
 | 
			
		||||
+                            super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, CB_PACKAGE + "/inventory/CraftItemFactory", "getSpawnEgg0", desc, false);
 | 
			
		||||
+                            super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, CB_PACKAGE_PREFIX + "inventory/CraftItemFactory", "getSpawnEgg0", desc, false);
 | 
			
		||||
+                            return;
 | 
			
		||||
+                        }
 | 
			
		||||
+                        // Paper end - ItemFactory#getSpawnEgg
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,13 +9,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 | 
			
		|||
--- a/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java
 | 
			
		||||
+++ b/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java
 | 
			
		||||
@@ -0,0 +0,0 @@ package net.minecraft.world.entity.decoration;
 | 
			
		||||
 
 | 
			
		||||
 import com.mojang.logging.LogUtils;
 | 
			
		||||
 import java.util.OptionalInt;
 | 
			
		||||
 import javax.annotation.Nullable;
 | 
			
		||||
+import io.papermc.paper.event.player.PlayerItemFrameChangeEvent; // Paper - Add PlayerItemFrameChangeEvent
 | 
			
		||||
 import net.minecraft.core.BlockPos;
 | 
			
		||||
 import net.minecraft.core.Direction;
 | 
			
		||||
 import net.minecraft.nbt.CompoundTag;
 | 
			
		||||
 import net.minecraft.core.component.DataComponents;
 | 
			
		||||
@@ -0,0 +0,0 @@ public class ItemFrame extends HangingEntity {
 | 
			
		||||
                     return true;
 | 
			
		||||
                 }
 | 
			
		||||
| 
						 | 
				
			
			@ -43,9 +43,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 | 
			
		|||
+                    this.setItem(ItemStack.fromBukkitCopy(event.getItemStack()));
 | 
			
		||||
+                    // Paper end - Add PlayerItemFrameChangeEvent
 | 
			
		||||
                     this.gameEvent(GameEvent.BLOCK_CHANGE, player);
 | 
			
		||||
                     if (!player.getAbilities().instabuild) {
 | 
			
		||||
                         itemstack.shrink(1);
 | 
			
		||||
                     }
 | 
			
		||||
                     itemstack.consume(1, player);
 | 
			
		||||
                 }
 | 
			
		||||
             } else {
 | 
			
		||||
+                // Paper start - Add PlayerItemFrameChangeEvent
 | 
			
		||||
| 
						 | 
				
			
			@ -52,7 +52,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 | 
			
		|||
 
 | 
			
		||||
     @Override
 | 
			
		||||
@@ -0,0 +0,0 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable {
 | 
			
		||||
         ContainerHelper.saveAllItems(nbt, this.items, true);
 | 
			
		||||
         ContainerHelper.saveAllItems(nbt, this.items, true, registryLookup);
 | 
			
		||||
         nbt.putIntArray("CookingTimes", this.cookingProgress);
 | 
			
		||||
         nbt.putIntArray("CookingTotalTimes", this.cookingTime);
 | 
			
		||||
+        // Paper start - Add more Campfire API
 | 
			
		||||
| 
						 | 
				
			
			@ -70,8 +70,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 | 
			
		|||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftCampfire.java
 | 
			
		||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftCampfire.java
 | 
			
		||||
@@ -0,0 +0,0 @@ public class CraftCampfire extends CraftBlockEntityState<CampfireBlockEntity> im
 | 
			
		||||
     public CraftCampfire copy() {
 | 
			
		||||
         return new CraftCampfire(this);
 | 
			
		||||
     public CraftCampfire copy(Location location) {
 | 
			
		||||
         return new CraftCampfire(this, location);
 | 
			
		||||
     }
 | 
			
		||||
+
 | 
			
		||||
+    // Paper start
 | 
			
		||||
| 
						 | 
				
			
			@ -18,8 +18,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 | 
			
		|||
         for (int i = 0; i < cs.length; i++) {
 | 
			
		||||
-            CompoundTag data = new CompoundTag();
 | 
			
		||||
 
 | 
			
		||||
-            data.put("block_states", ChunkSerializer.BLOCK_STATE_CODEC.encodeStart(NbtOps.INSTANCE, cs[i].getStates()).get().left().get());
 | 
			
		||||
-            sectionBlockIDs[i] = ChunkSerializer.BLOCK_STATE_CODEC.parse(NbtOps.INSTANCE, data.getCompound("block_states")).get().left().get();
 | 
			
		||||
-            data.put("block_states", ChunkSerializer.BLOCK_STATE_CODEC.encodeStart(NbtOps.INSTANCE, cs[i].getStates()).getOrThrow());
 | 
			
		||||
-            sectionBlockIDs[i] = ChunkSerializer.BLOCK_STATE_CODEC.parse(NbtOps.INSTANCE, data.getCompound("block_states")).getOrThrow(ChunkSerializer.ChunkReadException::new);
 | 
			
		||||
+            // Paper start - Fix ChunkSnapshot#isSectionEmpty(int); and remove codec usage
 | 
			
		||||
+            sectionEmpty[i] = cs[i].hasOnlyAir(); // fix sectionEmpty array not being filled
 | 
			
		||||
+            if (!sectionEmpty[i]) {
 | 
			
		||||
| 
						 | 
				
			
			@ -35,8 +35,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 | 
			
		|||
             }
 | 
			
		||||
 
 | 
			
		||||
             if (biome != null) {
 | 
			
		||||
-                data.put("biomes", biomeCodec.encodeStart(NbtOps.INSTANCE, cs[i].getBiomes()).get().left().get());
 | 
			
		||||
-                biome[i] = biomeCodec.parse(NbtOps.INSTANCE, data.getCompound("biomes")).get().left().get();
 | 
			
		||||
-                data.put("biomes", biomeCodec.encodeStart(NbtOps.INSTANCE, cs[i].getBiomes()).getOrThrow());
 | 
			
		||||
-                biome[i] = biomeCodec.parse(NbtOps.INSTANCE, data.getCompound("biomes")).getOrThrow(ChunkSerializer.ChunkReadException::new);
 | 
			
		||||
+                biome[i] = ((PalettedContainer<Holder<net.minecraft.world.level.biome.Biome>>) cs[i].getBiomes()).copy(); // Paper - Perf: use copy instead of round tripping with codecs
 | 
			
		||||
             }
 | 
			
		||||
         }
 | 
			
		||||
| 
						 | 
				
			
			@ -81,7 +81,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 | 
			
		|||
+++ b/src/main/java/net/minecraft/world/level/block/MangrovePropaguleBlock.java
 | 
			
		||||
@@ -0,0 +0,0 @@ public class MangrovePropaguleBlock extends SaplingBlock implements SimpleWaterl
 | 
			
		||||
     @Override
 | 
			
		||||
     public void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
 | 
			
		||||
     protected void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
 | 
			
		||||
         if (!isHanging(state)) {
 | 
			
		||||
-            if (random.nextInt(7) == 0) {
 | 
			
		||||
+            if (random.nextFloat() < (world.spigotConfig.saplingModifier / (100.0F * 7))) { // Paper - Fix Spigot growth modifiers
 | 
			
		||||
| 
						 | 
				
			
			@ -8,7 +8,7 @@ diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/jav
 | 
			
		|||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 | 
			
		||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
 | 
			
		||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
 | 
			
		||||
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
 | 
			
		||||
@@ -0,0 +0,0 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
 | 
			
		||||
     }
 | 
			
		||||
 
 | 
			
		||||
     public void restoreFrom(Entity original) {
 | 
			
		||||
| 
						 | 
				
			
			@ -22,7 +22,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 | 
			
		|||
         CompoundTag nbttagcompound = original.saveWithoutId(new CompoundTag());
 | 
			
		||||
 
 | 
			
		||||
         nbttagcompound.remove("Dimension");
 | 
			
		||||
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
 | 
			
		||||
@@ -0,0 +0,0 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
 | 
			
		||||
                         }
 | 
			
		||||
                     }
 | 
			
		||||
                     // CraftBukkit end
 | 
			
		||||
| 
						 | 
				
			
			@ -17,8 +17,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 | 
			
		|||
+        return new ClientboundSetPlayerTeamPacket(team.getName(), operation == ClientboundSetPlayerTeamPacket.Action.ADD ? 3 : 4, Optional.empty(), players);
 | 
			
		||||
+    }
 | 
			
		||||
+    // Paper end - Multiple Entries with Scoreboards
 | 
			
		||||
+
 | 
			
		||||
     public ClientboundSetPlayerTeamPacket(FriendlyByteBuf buf) {
 | 
			
		||||
     private ClientboundSetPlayerTeamPacket(RegistryFriendlyByteBuf buf) {
 | 
			
		||||
         this.name = buf.readUtf();
 | 
			
		||||
         this.method = buf.readByte();
 | 
			
		||||
diff --git a/src/main/java/net/minecraft/server/ServerScoreboard.java b/src/main/java/net/minecraft/server/ServerScoreboard.java
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,40 @@
 | 
			
		|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Nassim Jahnke <nassim@njahnke.dev>
 | 
			
		||||
Date: Thu, 25 Nov 2021 10:25:09 +0100
 | 
			
		||||
Subject: [PATCH] Prevent excessive velocity through repeated crits
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
 | 
			
		||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 | 
			
		||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
 | 
			
		||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
 | 
			
		||||
@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable {
 | 
			
		||||
         return this.hasEffect(MobEffects.JUMP) ? 0.1F * ((float) this.getEffect(MobEffects.JUMP).getAmplifier() + 1.0F) : 0.0F;
 | 
			
		||||
     }
 | 
			
		||||
 
 | 
			
		||||
+    protected long lastJumpTime = 0L; // Paper - Prevent excessive velocity through repeated crits
 | 
			
		||||
     protected void jumpFromGround() {
 | 
			
		||||
         float f = this.getJumpPower();
 | 
			
		||||
 
 | 
			
		||||
         if (f > 1.0E-5F) {
 | 
			
		||||
             Vec3 vec3d = this.getDeltaMovement();
 | 
			
		||||
+            // Paper start - Prevent excessive velocity through repeated crits
 | 
			
		||||
+            long time = System.nanoTime();
 | 
			
		||||
+            boolean canCrit = true;
 | 
			
		||||
+            if (this instanceof net.minecraft.world.entity.player.Player) {
 | 
			
		||||
+                canCrit = false;
 | 
			
		||||
+                if (time - this.lastJumpTime > (long)(0.250e9)) {
 | 
			
		||||
+                    this.lastJumpTime = time;
 | 
			
		||||
+                    canCrit = true;
 | 
			
		||||
+                }
 | 
			
		||||
+            }
 | 
			
		||||
+            // Paper end - Prevent excessive velocity through repeated crits
 | 
			
		||||
 
 | 
			
		||||
             this.setDeltaMovement(vec3d.x, (double) f, vec3d.z);
 | 
			
		||||
             if (this.isSprinting()) {
 | 
			
		||||
                 float f1 = this.getYRot() * 0.017453292F;
 | 
			
		||||
-
 | 
			
		||||
+                if (canCrit) // Paper - Prevent excessive velocity through repeated crits
 | 
			
		||||
                 this.addDeltaMovement(new Vec3((double) (-Mth.sin(f1)) * 0.2D, 0.0D, (double) Mth.cos(f1) * 0.2D));
 | 
			
		||||
             }
 | 
			
		||||
 
 | 
			
		||||
| 
						 | 
				
			
			@ -9,19 +9,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 | 
			
		|||
--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
 | 
			
		||||
+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
 | 
			
		||||
@@ -0,0 +0,0 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
 | 
			
		||||
     public GameProfile authenticatedProfile; // Paper - public
 | 
			
		||||
     private final String serverId;
 | 
			
		||||
     private final boolean transferred;
 | 
			
		||||
     private ServerPlayer player; // CraftBukkit
 | 
			
		||||
+    public boolean iKnowThisMayNotBeTheBestIdeaButPleaseDisableUsernameValidation = false; // Paper - username validation overriding
 | 
			
		||||
 
 | 
			
		||||
     public ServerLoginPacketListenerImpl(MinecraftServer server, Connection connection) {
 | 
			
		||||
     public ServerLoginPacketListenerImpl(MinecraftServer server, Connection connection, boolean transferred) {
 | 
			
		||||
         this.state = ServerLoginPacketListenerImpl.State.HELLO;
 | 
			
		||||
@@ -0,0 +0,0 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
 | 
			
		||||
     @Override
 | 
			
		||||
     public void handleHello(ServerboundHelloPacket packet) {
 | 
			
		||||
         Validate.validState(this.state == ServerLoginPacketListenerImpl.State.HELLO, "Unexpected hello packet", new Object[0]);
 | 
			
		||||
-        Validate.validState(Player.isValidUsername(packet.name()), "Invalid characters in username", new Object[0]);
 | 
			
		||||
+        if (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode() && io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.performUsernameValidation && !this.iKnowThisMayNotBeTheBestIdeaButPleaseDisableUsernameValidation) Validate.validState(Player.isValidUsername(packet.name()), "Invalid characters in username", new Object[0]); // Paper - config username validation
 | 
			
		||||
-        Validate.validState(StringUtil.isValidPlayerName(packet.name()), "Invalid characters in username", new Object[0]);
 | 
			
		||||
+        if (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode() && io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.performUsernameValidation && !this.iKnowThisMayNotBeTheBestIdeaButPleaseDisableUsernameValidation) Validate.validState(StringUtil.isValidPlayerName(packet.name()), "Invalid characters in username", new Object[0]); // Paper - config username validation
 | 
			
		||||
         this.requestedUsername = packet.name();
 | 
			
		||||
         GameProfile gameprofile = this.server.getSingleplayerProfile();
 | 
			
		||||
 
 | 
			
		||||
| 
						 | 
				
			
			@ -38,17 +38,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 | 
			
		|||
                 list.add(entityplayer);
 | 
			
		||||
             }
 | 
			
		||||
         }
 | 
			
		||||
diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java
 | 
			
		||||
diff --git a/src/main/java/net/minecraft/util/StringUtil.java b/src/main/java/net/minecraft/util/StringUtil.java
 | 
			
		||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 | 
			
		||||
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
 | 
			
		||||
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
 | 
			
		||||
@@ -0,0 +0,0 @@ public abstract class Player extends LivingEntity {
 | 
			
		||||
--- a/src/main/java/net/minecraft/util/StringUtil.java
 | 
			
		||||
+++ b/src/main/java/net/minecraft/util/StringUtil.java
 | 
			
		||||
@@ -0,0 +0,0 @@ public class StringUtil {
 | 
			
		||||
     }
 | 
			
		||||
 
 | 
			
		||||
     public static boolean isValidUsername(String name) {
 | 
			
		||||
-        return name.length() > 16 ? false : name.chars().filter((i) -> {
 | 
			
		||||
-            return i <= 32 || i >= 127;
 | 
			
		||||
-        }).findAny().isEmpty();
 | 
			
		||||
     public static boolean isValidPlayerName(String name) {
 | 
			
		||||
-        return name.length() <= 16 && name.chars().filter(c -> c <= 32 || c >= 127).findAny().isEmpty();
 | 
			
		||||
+        // Paper start - username validation overriding
 | 
			
		||||
+        if (name == null || name.isEmpty() || name.length() > 16) {
 | 
			
		||||
+            return false;
 | 
			
		||||
| 
						 | 
				
			
			@ -68,4 +66,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 | 
			
		|||
+        // Paper end - username validation overriding
 | 
			
		||||
     }
 | 
			
		||||
 
 | 
			
		||||
     public static float getPickRange(boolean creative) {
 | 
			
		||||
     public static String filterText(String string) {
 | 
			
		||||
| 
						 | 
				
			
			@ -8,7 +8,7 @@ diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/jav
 | 
			
		|||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 | 
			
		||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
 | 
			
		||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
 | 
			
		||||
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
 | 
			
		||||
@@ -0,0 +0,0 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
 | 
			
		||||
     // CraftBukkit start
 | 
			
		||||
     public void postTick() {
 | 
			
		||||
         // No clean way to break out of ticking once the entity has been copied to a new world, so instead we move the portalling later in the tick cycle
 | 
			
		||||
| 
						 | 
				
			
			@ -1,19 +0,0 @@
 | 
			
		|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
 | 
			
		||||
Date: Mon, 21 Jun 2021 22:12:53 -0400
 | 
			
		||||
Subject: [PATCH] Always allow item changing in Fireball
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
diff --git a/src/main/java/net/minecraft/world/entity/projectile/Fireball.java b/src/main/java/net/minecraft/world/entity/projectile/Fireball.java
 | 
			
		||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 | 
			
		||||
--- a/src/main/java/net/minecraft/world/entity/projectile/Fireball.java
 | 
			
		||||
+++ b/src/main/java/net/minecraft/world/entity/projectile/Fireball.java
 | 
			
		||||
@@ -0,0 +0,0 @@ public abstract class Fireball extends AbstractHurtingProjectile implements Item
 | 
			
		||||
     }
 | 
			
		||||
 
 | 
			
		||||
     public void setItem(ItemStack stack) {
 | 
			
		||||
-        if (!stack.is(Items.FIRE_CHARGE) || stack.hasTag()) {
 | 
			
		||||
+        if (true || !stack.is(Items.FIRE_CHARGE) || stack.hasTag()) { // Paper - always allow item changing
 | 
			
		||||
             this.getEntityData().set(Fireball.DATA_ITEM_STACK, stack.copyWithCount(1));
 | 
			
		||||
         }
 | 
			
		||||
 
 | 
			
		||||
| 
						 | 
				
			
			@ -1,49 +0,0 @@
 | 
			
		|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
 | 
			
		||||
Date: Sat, 21 Aug 2021 21:54:16 -0700
 | 
			
		||||
Subject: [PATCH] Fix bees aging inside hives
 | 
			
		||||
 | 
			
		||||
Fixes bees incorrectly being aged up due to upstream's
 | 
			
		||||
resetting the ticks inside hive on a failed release
 | 
			
		||||
 | 
			
		||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java
 | 
			
		||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 | 
			
		||||
--- a/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java
 | 
			
		||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java
 | 
			
		||||
@@ -0,0 +0,0 @@ public class BeehiveBlockEntity extends BlockEntity {
 | 
			
		||||
 
 | 
			
		||||
         for (Iterator iterator = bees.iterator(); iterator.hasNext(); ++tileentitybeehive_hivebee.ticksInHive) {
 | 
			
		||||
             tileentitybeehive_hivebee = (BeehiveBlockEntity.BeeData) iterator.next();
 | 
			
		||||
-            if (tileentitybeehive_hivebee.ticksInHive > tileentitybeehive_hivebee.minOccupationTicks) {
 | 
			
		||||
+            if (tileentitybeehive_hivebee.exitTickCounter > tileentitybeehive_hivebee.minOccupationTicks) { // Paper - Fix bees aging inside hives; use exitTickCounter
 | 
			
		||||
                 BeehiveBlockEntity.BeeReleaseStatus tileentitybeehive_releasestatus = tileentitybeehive_hivebee.entityData.getBoolean("HasNectar") ? BeehiveBlockEntity.BeeReleaseStatus.HONEY_DELIVERED : BeehiveBlockEntity.BeeReleaseStatus.BEE_RELEASED;
 | 
			
		||||
 
 | 
			
		||||
                 if (BeehiveBlockEntity.releaseOccupant(world, pos, state, tileentitybeehive_hivebee, (List) null, tileentitybeehive_releasestatus, flowerPos)) {
 | 
			
		||||
@@ -0,0 +0,0 @@ public class BeehiveBlockEntity extends BlockEntity {
 | 
			
		||||
                     iterator.remove();
 | 
			
		||||
                     // CraftBukkit start
 | 
			
		||||
                 } else {
 | 
			
		||||
-                    tileentitybeehive_hivebee.ticksInHive = tileentitybeehive_hivebee.minOccupationTicks / 2; // Not strictly Vanilla behaviour in cases where bees cannot spawn but still reasonable
 | 
			
		||||
+                    tileentitybeehive_hivebee.exitTickCounter = tileentitybeehive_hivebee.minOccupationTicks / 2; // Not strictly Vanilla behaviour in cases where bees cannot spawn but still reasonable // Paper - Fix bees aging inside hives; use exitTickCounter to keep actual bee life
 | 
			
		||||
                     // CraftBukkit end
 | 
			
		||||
                 }
 | 
			
		||||
             }
 | 
			
		||||
+            tileentitybeehive_hivebee.exitTickCounter++; // Paper - Fix bees aging inside hives
 | 
			
		||||
         }
 | 
			
		||||
 
 | 
			
		||||
         if (flag) {
 | 
			
		||||
@@ -0,0 +0,0 @@ public class BeehiveBlockEntity extends BlockEntity {
 | 
			
		||||
 
 | 
			
		||||
         final CompoundTag entityData;
 | 
			
		||||
         int ticksInHive;
 | 
			
		||||
+        int exitTickCounter; // Paper - Fix bees aging inside hives; separate counter for checking if bee should exit to reduce exit attempts
 | 
			
		||||
         final int minOccupationTicks;
 | 
			
		||||
 
 | 
			
		||||
         BeeData(CompoundTag entityData, int ticksInHive, int minOccupationTicks) {
 | 
			
		||||
             BeehiveBlockEntity.removeIgnoredBeeTags(entityData);
 | 
			
		||||
             this.entityData = entityData;
 | 
			
		||||
             this.ticksInHive = ticksInHive;
 | 
			
		||||
+            this.exitTickCounter = ticksInHive; // Paper - Fix bees aging inside hives
 | 
			
		||||
             this.minOccupationTicks = minOccupationTicks;
 | 
			
		||||
         }
 | 
			
		||||
     }
 | 
			
		||||
| 
						 | 
				
			
			@ -1,50 +0,0 @@
 | 
			
		|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
 | 
			
		||||
Date: Tue, 30 Nov 2021 12:01:56 -0800
 | 
			
		||||
Subject: [PATCH] Fix removing recipes from RecipeIterator
 | 
			
		||||
 | 
			
		||||
== AT ==
 | 
			
		||||
public net.minecraft.world.item.crafting.RecipeManager byName
 | 
			
		||||
 | 
			
		||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/RecipeIterator.java b/src/main/java/org/bukkit/craftbukkit/inventory/RecipeIterator.java
 | 
			
		||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 | 
			
		||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/RecipeIterator.java
 | 
			
		||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/RecipeIterator.java
 | 
			
		||||
@@ -0,0 +0,0 @@ import org.bukkit.inventory.Recipe;
 | 
			
		||||
 public class RecipeIterator implements Iterator<Recipe> {
 | 
			
		||||
     private final Iterator<Map.Entry<RecipeType<?>, Object2ObjectLinkedOpenHashMap<ResourceLocation, RecipeHolder<?>>>> recipes;
 | 
			
		||||
     private Iterator<RecipeHolder<?>> current;
 | 
			
		||||
+    private Recipe currentRecipe; // Paper - fix removing recipes from RecipeIterator
 | 
			
		||||
 
 | 
			
		||||
     public RecipeIterator() {
 | 
			
		||||
         this.recipes = MinecraftServer.getServer().getRecipeManager().recipes.entrySet().iterator();
 | 
			
		||||
@@ -0,0 +0,0 @@ public class RecipeIterator implements Iterator<Recipe> {
 | 
			
		||||
     public Recipe next() {
 | 
			
		||||
         if (this.current == null || !this.current.hasNext()) {
 | 
			
		||||
             this.current = this.recipes.next().getValue().values().iterator();
 | 
			
		||||
-            return this.next();
 | 
			
		||||
+            // Paper start - fix removing recipes from RecipeIterator
 | 
			
		||||
+            this.currentRecipe = this.next();
 | 
			
		||||
+            return this.currentRecipe;
 | 
			
		||||
+            // Paper end - fix removing recipes from RecipeIterator
 | 
			
		||||
         }
 | 
			
		||||
 
 | 
			
		||||
-        return this.current.next().toBukkitRecipe();
 | 
			
		||||
+        // Paper start - fix removing recipes from RecipeIterator
 | 
			
		||||
+        this.currentRecipe = this.current.next().toBukkitRecipe();
 | 
			
		||||
+        return this.currentRecipe;
 | 
			
		||||
+        // Paper end - fix removing recipes from RecipeIterator
 | 
			
		||||
     }
 | 
			
		||||
 
 | 
			
		||||
     @Override
 | 
			
		||||
     public void remove() {
 | 
			
		||||
         Preconditions.checkState(this.current != null, "next() not yet called");
 | 
			
		||||
+
 | 
			
		||||
+        // Paper start - fix removing recipes from RecipeIterator
 | 
			
		||||
+        if (this.currentRecipe instanceof org.bukkit.Keyed keyed) {
 | 
			
		||||
+            MinecraftServer.getServer().getRecipeManager().byName.remove(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(keyed.getKey()));
 | 
			
		||||
+        }
 | 
			
		||||
+        // Paper end - fix removing recipes from RecipeIterator
 | 
			
		||||
         this.current.remove();
 | 
			
		||||
     }
 | 
			
		||||
 }
 | 
			
		||||
| 
						 | 
				
			
			@ -1,125 +0,0 @@
 | 
			
		|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Noah van der Aa <ndvdaa@gmail.com>
 | 
			
		||||
Date: Tue, 3 Aug 2021 17:28:27 +0200
 | 
			
		||||
Subject: [PATCH] Hide unnecessary itemmeta from clients
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java
 | 
			
		||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 | 
			
		||||
--- a/src/main/java/net/minecraft/server/level/ServerEntity.java
 | 
			
		||||
+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java
 | 
			
		||||
@@ -0,0 +0,0 @@ public class ServerEntity {
 | 
			
		||||
                 if (!itemstack.isEmpty()) {
 | 
			
		||||
                     // Paper start - prevent oversized data
 | 
			
		||||
                     final ItemStack sanitized = LivingEntity.sanitizeItemStack(itemstack.copy(), false);
 | 
			
		||||
-                    list.add(Pair.of(enumitemslot, sanitized));
 | 
			
		||||
+                    list.add(Pair.of(enumitemslot, ((LivingEntity) this.entity).stripMeta(sanitized, false))); // Paper - Hide unnecessary item meta
 | 
			
		||||
                     // Paper end - prevent oversized data
 | 
			
		||||
                 }
 | 
			
		||||
             }
 | 
			
		||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
 | 
			
		||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 | 
			
		||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
 | 
			
		||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
 | 
			
		||||
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
 | 
			
		||||
                                 // Refresh the current entity metadata
 | 
			
		||||
                                 entity.getEntityData().refresh(ServerGamePacketListenerImpl.this.player);
 | 
			
		||||
                                 // SPIGOT-7136 - Allays
 | 
			
		||||
-                                if (entity instanceof Allay) {
 | 
			
		||||
-                                    ServerGamePacketListenerImpl.this.send(new ClientboundSetEquipmentPacket(entity.getId(), Arrays.stream(net.minecraft.world.entity.EquipmentSlot.values()).map((slot) -> Pair.of(slot, ((LivingEntity) entity).getItemBySlot(slot).copy())).collect(Collectors.toList())));
 | 
			
		||||
+                                if (entity instanceof Allay allay) { // Paper - Hide unnecessary item meta
 | 
			
		||||
+                                    ServerGamePacketListenerImpl.this.send(new ClientboundSetEquipmentPacket(entity.getId(), Arrays.stream(net.minecraft.world.entity.EquipmentSlot.values()).map((slot) -> Pair.of(slot, allay.stripMeta(allay.getItemBySlot(slot), true))).collect(Collectors.toList()))); // Paper - Hide unnecessary item meta
 | 
			
		||||
                                     ServerGamePacketListenerImpl.this.player.containerMenu.sendAllDataToRemote();
 | 
			
		||||
                                 }
 | 
			
		||||
                             }
 | 
			
		||||
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
 | 
			
		||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 | 
			
		||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
 | 
			
		||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
 | 
			
		||||
@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable {
 | 
			
		||||
 
 | 
			
		||||
             // Paper start - prevent oversized data
 | 
			
		||||
             ItemStack toSend = sanitizeItemStack(itemstack1, true);
 | 
			
		||||
-            list.add(Pair.of(enumitemslot, toSend));
 | 
			
		||||
+            list.add(Pair.of(enumitemslot, stripMeta(toSend, toSend == itemstack1))); // Paper - Hide unnecessary item meta
 | 
			
		||||
             // Paper end - prevent oversized data
 | 
			
		||||
             switch (enumitemslot.getType()) {
 | 
			
		||||
                 case HAND:
 | 
			
		||||
@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable {
 | 
			
		||||
         ((ServerLevel) this.level()).getChunkSource().broadcast(this, new ClientboundSetEquipmentPacket(this.getId(), list));
 | 
			
		||||
     }
 | 
			
		||||
 
 | 
			
		||||
+    // Paper start - Hide unnecessary item meta
 | 
			
		||||
+    public ItemStack stripMeta(final ItemStack itemStack, final boolean copyItemStack) {
 | 
			
		||||
+        if (itemStack.isEmpty() || (!itemStack.hasTag() && itemStack.getCount() < 2)) {
 | 
			
		||||
+            return itemStack;
 | 
			
		||||
+        }
 | 
			
		||||
+
 | 
			
		||||
+        final ItemStack copy = copyItemStack ? itemStack.copy() : itemStack;
 | 
			
		||||
+        if (this.level().paperConfig().anticheat.obfuscation.items.hideDurability) {
 | 
			
		||||
+            // Only show damage values for elytra's, since they show a different texture when broken.
 | 
			
		||||
+            if (!copy.is(Items.ELYTRA) || copy.getDamageValue() < copy.getMaxDamage() - 1) {
 | 
			
		||||
+                copy.setDamageValue(0);
 | 
			
		||||
+            }
 | 
			
		||||
+        }
 | 
			
		||||
+
 | 
			
		||||
+        final CompoundTag tag = copy.getTag();
 | 
			
		||||
+        if (this.level().paperConfig().anticheat.obfuscation.items.hideItemmeta) {
 | 
			
		||||
+            // Some resource packs show different textures when there is more than one item. Since this shouldn't provide a big advantage,
 | 
			
		||||
+            // we'll tell the client if there's one or (more than) two items.
 | 
			
		||||
+            copy.setCount(copy.getCount() > 1 ? 2 : 1);
 | 
			
		||||
+            // We can't just strip out display, leather helmets still use the display.color tag.
 | 
			
		||||
+            if (tag != null) {
 | 
			
		||||
+                if (tag.get("display") instanceof CompoundTag displayTag) {
 | 
			
		||||
+                    displayTag.remove("Lore");
 | 
			
		||||
+                    displayTag.remove("Name");
 | 
			
		||||
+                }
 | 
			
		||||
+
 | 
			
		||||
+                if (tag.get("Enchantments") instanceof ListTag enchantmentsTag && !enchantmentsTag.isEmpty()) {
 | 
			
		||||
+                    // The client still renders items with the enchantment glow if the enchantments tag contains at least one (empty) child.
 | 
			
		||||
+                    ListTag enchantments = new ListTag();
 | 
			
		||||
+                    CompoundTag fakeEnchantment = new CompoundTag();
 | 
			
		||||
+                    // Soul speed boots generate client side particles.
 | 
			
		||||
+                    if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SOUL_SPEED, itemStack) > 0) {
 | 
			
		||||
+                        fakeEnchantment.putString("id", org.bukkit.enchantments.Enchantment.SOUL_SPEED.getKey().asString());
 | 
			
		||||
+                        fakeEnchantment.putInt("lvl", 1);
 | 
			
		||||
+                    }
 | 
			
		||||
+                    enchantments.add(fakeEnchantment);
 | 
			
		||||
+                    tag.put("Enchantments", enchantments);
 | 
			
		||||
+                }
 | 
			
		||||
+                tag.remove("AttributeModifiers");
 | 
			
		||||
+                tag.remove("Unbreakable");
 | 
			
		||||
+                tag.remove("PublicBukkitValues"); // Persistent data container1
 | 
			
		||||
+
 | 
			
		||||
+                // Books
 | 
			
		||||
+                tag.remove("author");
 | 
			
		||||
+                tag.remove("filtered_title");
 | 
			
		||||
+                tag.remove("pages");
 | 
			
		||||
+                tag.remove("filtered_pages");
 | 
			
		||||
+                tag.remove("title");
 | 
			
		||||
+                tag.remove("generation");
 | 
			
		||||
+
 | 
			
		||||
+                // Filled maps
 | 
			
		||||
+                tag.remove("map");
 | 
			
		||||
+                tag.remove("map_scale_direction");
 | 
			
		||||
+                tag.remove("map_to_lock");
 | 
			
		||||
+            }
 | 
			
		||||
+        }
 | 
			
		||||
+
 | 
			
		||||
+        if (this.level().paperConfig().anticheat.obfuscation.items.hideItemmetaWithVisualEffects && tag != null) {
 | 
			
		||||
+            // Lodestone compasses
 | 
			
		||||
+            tag.remove("LodestonePos");
 | 
			
		||||
+            if (tag.contains("LodestoneDimension")) {
 | 
			
		||||
+                // The client shows the glint if either the position or the dimension is present, so we just wipe
 | 
			
		||||
+                // the position and fake the dimension
 | 
			
		||||
+                tag.putString("LodestoneDimension", "paper:paper");
 | 
			
		||||
+            }
 | 
			
		||||
+        }
 | 
			
		||||
+
 | 
			
		||||
+        return copy;
 | 
			
		||||
+    }
 | 
			
		||||
+    // Paper end - Hide unnecessary item meta
 | 
			
		||||
+
 | 
			
		||||
     // Paper start - prevent oversized data
 | 
			
		||||
     public static ItemStack sanitizeItemStack(final ItemStack itemStack, final boolean copyItemStack) {
 | 
			
		||||
         if (itemStack.isEmpty() || !itemStack.hasTag()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1,20 +0,0 @@
 | 
			
		|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
 | 
			
		||||
Date: Tue, 21 Dec 2021 22:13:26 -0800
 | 
			
		||||
Subject: [PATCH] Load effect amplifiers greater than 127 correctly
 | 
			
		||||
 | 
			
		||||
MOJIRA: MC-118857
 | 
			
		||||
 | 
			
		||||
diff --git a/src/main/java/net/minecraft/world/effect/MobEffectInstance.java b/src/main/java/net/minecraft/world/effect/MobEffectInstance.java
 | 
			
		||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 | 
			
		||||
--- a/src/main/java/net/minecraft/world/effect/MobEffectInstance.java
 | 
			
		||||
+++ b/src/main/java/net/minecraft/world/effect/MobEffectInstance.java
 | 
			
		||||
@@ -0,0 +0,0 @@ public class MobEffectInstance implements Comparable<MobEffectInstance> {
 | 
			
		||||
     }
 | 
			
		||||
 
 | 
			
		||||
     private static MobEffectInstance loadSpecifiedEffect(MobEffect type, CompoundTag nbt) {
 | 
			
		||||
-        int i = nbt.getByte("amplifier");
 | 
			
		||||
+        int i = Byte.toUnsignedInt(nbt.getByte("amplifier")); // Paper - correctly load amplifiers > 127
 | 
			
		||||
         int j = nbt.getInt("duration");
 | 
			
		||||
         boolean bl = nbt.getBoolean("ambient");
 | 
			
		||||
         boolean bl2 = true;
 | 
			
		||||
| 
						 | 
				
			
			@ -1,37 +0,0 @@
 | 
			
		|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Nassim Jahnke <nassim@njahnke.dev>
 | 
			
		||||
Date: Thu, 25 Nov 2021 10:25:09 +0100
 | 
			
		||||
Subject: [PATCH] Prevent excessive velocity through repeated crits
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
 | 
			
		||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 | 
			
		||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
 | 
			
		||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
 | 
			
		||||
@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable {
 | 
			
		||||
         return this.hasEffect(MobEffects.JUMP) ? 0.1F * ((float) this.getEffect(MobEffects.JUMP).getAmplifier() + 1.0F) : 0.0F;
 | 
			
		||||
     }
 | 
			
		||||
 
 | 
			
		||||
+    protected long lastJumpTime = 0L; // Paper - Prevent excessive velocity through repeated crits
 | 
			
		||||
     protected void jumpFromGround() {
 | 
			
		||||
         Vec3 vec3d = this.getDeltaMovement();
 | 
			
		||||
+        // Paper start - Prevent excessive velocity through repeated crits
 | 
			
		||||
+        long time = System.nanoTime();
 | 
			
		||||
+        boolean canCrit = true;
 | 
			
		||||
+        if (this instanceof net.minecraft.world.entity.player.Player) {
 | 
			
		||||
+            canCrit = false;
 | 
			
		||||
+            if (time - this.lastJumpTime > (long)(0.250e9)) {
 | 
			
		||||
+                this.lastJumpTime = time;
 | 
			
		||||
+                canCrit = true;
 | 
			
		||||
+            }
 | 
			
		||||
+        }
 | 
			
		||||
+        // Paper end - Prevent excessive velocity through repeated crits
 | 
			
		||||
 
 | 
			
		||||
         this.setDeltaMovement(vec3d.x, (double) this.getJumpPower(), vec3d.z);
 | 
			
		||||
         if (this.isSprinting()) {
 | 
			
		||||
             float f = this.getYRot() * 0.017453292F;
 | 
			
		||||
 
 | 
			
		||||
+            if (canCrit) // Paper - Prevent excessive velocity through repeated crits
 | 
			
		||||
             this.setDeltaMovement(this.getDeltaMovement().add((double) (-Mth.sin(f) * 0.2F), 0.0D, (double) (Mth.cos(f) * 0.2F)));
 | 
			
		||||
         }
 | 
			
		||||
 
 | 
			
		||||
| 
						 | 
				
			
			@ -1,86 +0,0 @@
 | 
			
		|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Nassim Jahnke <nassim@njahnke.dev>
 | 
			
		||||
Date: Wed, 1 Dec 2021 12:36:25 +0100
 | 
			
		||||
Subject: [PATCH] Prevent sending oversized item data in equipment and metadata
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
diff --git a/src/main/java/net/minecraft/network/syncher/EntityDataSerializers.java b/src/main/java/net/minecraft/network/syncher/EntityDataSerializers.java
 | 
			
		||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 | 
			
		||||
--- a/src/main/java/net/minecraft/network/syncher/EntityDataSerializers.java
 | 
			
		||||
+++ b/src/main/java/net/minecraft/network/syncher/EntityDataSerializers.java
 | 
			
		||||
@@ -0,0 +0,0 @@ public class EntityDataSerializers {
 | 
			
		||||
     public static final EntityDataSerializer<ItemStack> ITEM_STACK = new EntityDataSerializer<ItemStack>() {
 | 
			
		||||
         @Override
 | 
			
		||||
         public void write(FriendlyByteBuf buf, ItemStack value) {
 | 
			
		||||
-            buf.writeItem(value);
 | 
			
		||||
+            buf.writeItem(net.minecraft.world.entity.LivingEntity.sanitizeItemStack(value, true)); // Paper - prevent oversized data
 | 
			
		||||
         }
 | 
			
		||||
 
 | 
			
		||||
         @Override
 | 
			
		||||
diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java
 | 
			
		||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 | 
			
		||||
--- a/src/main/java/net/minecraft/server/level/ServerEntity.java
 | 
			
		||||
+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java
 | 
			
		||||
@@ -0,0 +0,0 @@ public class ServerEntity {
 | 
			
		||||
                 ItemStack itemstack = ((LivingEntity) this.entity).getItemBySlot(enumitemslot);
 | 
			
		||||
 
 | 
			
		||||
                 if (!itemstack.isEmpty()) {
 | 
			
		||||
-                    list.add(Pair.of(enumitemslot, itemstack.copy()));
 | 
			
		||||
+                    // Paper start - prevent oversized data
 | 
			
		||||
+                    final ItemStack sanitized = LivingEntity.sanitizeItemStack(itemstack.copy(), false);
 | 
			
		||||
+                    list.add(Pair.of(enumitemslot, sanitized));
 | 
			
		||||
+                    // Paper end - prevent oversized data
 | 
			
		||||
                 }
 | 
			
		||||
             }
 | 
			
		||||
 
 | 
			
		||||
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
 | 
			
		||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 | 
			
		||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
 | 
			
		||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
 | 
			
		||||
@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable {
 | 
			
		||||
         equipmentChanges.forEach((enumitemslot, itemstack) -> {
 | 
			
		||||
             ItemStack itemstack1 = itemstack.copy();
 | 
			
		||||
 
 | 
			
		||||
-            list.add(Pair.of(enumitemslot, itemstack1));
 | 
			
		||||
+            // Paper start - prevent oversized data
 | 
			
		||||
+            ItemStack toSend = sanitizeItemStack(itemstack1, true);
 | 
			
		||||
+            list.add(Pair.of(enumitemslot, toSend));
 | 
			
		||||
+            // Paper end - prevent oversized data
 | 
			
		||||
             switch (enumitemslot.getType()) {
 | 
			
		||||
                 case HAND:
 | 
			
		||||
                     this.setLastHandItem(enumitemslot, itemstack1);
 | 
			
		||||
@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable {
 | 
			
		||||
         ((ServerLevel) this.level()).getChunkSource().broadcast(this, new ClientboundSetEquipmentPacket(this.getId(), list));
 | 
			
		||||
     }
 | 
			
		||||
 
 | 
			
		||||
+    // Paper start - prevent oversized data
 | 
			
		||||
+    public static ItemStack sanitizeItemStack(final ItemStack itemStack, final boolean copyItemStack) {
 | 
			
		||||
+        if (itemStack.isEmpty() || !itemStack.hasTag()) {
 | 
			
		||||
+            return itemStack;
 | 
			
		||||
+        }
 | 
			
		||||
+
 | 
			
		||||
+        final ItemStack copy = copyItemStack ? itemStack.copy() : itemStack;
 | 
			
		||||
+        final CompoundTag tag = copy.getTag();
 | 
			
		||||
+        if (copy.is(Items.BUNDLE) && tag.get("Items") instanceof ListTag oldItems && !oldItems.isEmpty()) {
 | 
			
		||||
+            // Bundles change their texture based on their fullness.
 | 
			
		||||
+            org.bukkit.inventory.meta.BundleMeta bundleMeta = (org.bukkit.inventory.meta.BundleMeta) copy.asBukkitMirror().getItemMeta();
 | 
			
		||||
+            int sizeUsed = 0;
 | 
			
		||||
+            for (org.bukkit.inventory.ItemStack item : bundleMeta.getItems()) {
 | 
			
		||||
+                int scale = 64 / item.getMaxStackSize();
 | 
			
		||||
+                sizeUsed += scale * item.getAmount();
 | 
			
		||||
+            }
 | 
			
		||||
+            // Now we add a single fake item that uses the same amount of slots as all other items.
 | 
			
		||||
+            ListTag items = new ListTag();
 | 
			
		||||
+            items.add(new ItemStack(Items.PAPER, sizeUsed).save(new CompoundTag()));
 | 
			
		||||
+            tag.put("Items", items);
 | 
			
		||||
+        }
 | 
			
		||||
+        if (tag.get("BlockEntityTag") instanceof CompoundTag blockEntityTag) {
 | 
			
		||||
+            blockEntityTag.remove("Items");
 | 
			
		||||
+        }
 | 
			
		||||
+        return copy;
 | 
			
		||||
+    }
 | 
			
		||||
+    // Paper end - prevent oversized data
 | 
			
		||||
+
 | 
			
		||||
     private ItemStack getLastArmorItem(EquipmentSlot slot) {
 | 
			
		||||
         return (ItemStack) this.lastArmorItemStacks.get(slot.getIndex());
 | 
			
		||||
     }
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue