This commit is contained in:
Bjarne Koll
2024-06-14 11:59:44 +02:00
parent 8a6e31ec59
commit 7289589315
32 changed files with 19 additions and 272 deletions

View File

@@ -1,44 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Wed, 2 Dec 2020 21:03:02 -0800
Subject: [PATCH] Add config for mobs immune to default effects
diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java
+++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java
@@ -0,0 +0,0 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob
@Override
public boolean canBeAffected(MobEffectInstance effect) {
- return effect.is(MobEffects.WITHER) ? false : super.canBeAffected(effect);
+ return effect.is(MobEffects.WITHER) && this.level().paperConfig().entities.mobEffects.immuneToWitherEffect.wither ? false : super.canBeAffected(effect); // Paper - Add config for mobs immune to default effects
}
private class WitherDoNothingGoal extends Goal {
diff --git a/src/main/java/net/minecraft/world/entity/monster/Spider.java b/src/main/java/net/minecraft/world/entity/monster/Spider.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Spider.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Spider.java
@@ -0,0 +0,0 @@ public class Spider extends Monster {
@Override
public boolean canBeAffected(MobEffectInstance effect) {
- return effect.is(MobEffects.POISON) ? false : super.canBeAffected(effect);
+ return effect.is(MobEffects.POISON) && this.level().paperConfig().entities.mobEffects.spidersImmuneToPoisonEffect ? false : super.canBeAffected(effect); // Paper - Add config for mobs immune to default effects
}
public boolean isClimbing() {
diff --git a/src/main/java/net/minecraft/world/entity/monster/WitherSkeleton.java b/src/main/java/net/minecraft/world/entity/monster/WitherSkeleton.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/monster/WitherSkeleton.java
+++ b/src/main/java/net/minecraft/world/entity/monster/WitherSkeleton.java
@@ -0,0 +0,0 @@ public class WitherSkeleton extends AbstractSkeleton {
@Override
public boolean canBeAffected(MobEffectInstance effect) {
- return effect.is(MobEffects.WITHER) ? false : super.canBeAffected(effect);
+ return effect.is(MobEffects.WITHER) && this.level().paperConfig().entities.mobEffects.immuneToWitherEffect.witherSkeleton ? false : super.canBeAffected(effect); // Paper - Add config for mobs immune to default effects
}
}

View File

@@ -1,255 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Fri, 26 Apr 2024 23:15:27 -0700
Subject: [PATCH] Add experimental improved give command
Supports removing data components from itemstacks
diff --git a/src/main/java/net/minecraft/commands/arguments/item/ItemArgument.java b/src/main/java/net/minecraft/commands/arguments/item/ItemArgument.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/commands/arguments/item/ItemArgument.java
+++ b/src/main/java/net/minecraft/commands/arguments/item/ItemArgument.java
@@ -0,0 +0,0 @@ public class ItemArgument implements ArgumentType<ItemInput> {
private final ItemParser parser;
public ItemArgument(CommandBuildContext commandRegistryAccess) {
- this.parser = new ItemParser(commandRegistryAccess);
+ // Paper start - support component removals
+ this(commandRegistryAccess, false);
+ }
+ public ItemArgument(CommandBuildContext commandRegistryAccess, boolean allowRemovals) {
+ this.parser = new ItemParser(commandRegistryAccess, allowRemovals);
+ // Paper end - support component removals
}
public static ItemArgument item(CommandBuildContext commandRegistryAccess) {
@@ -0,0 +0,0 @@ public class ItemArgument implements ArgumentType<ItemInput> {
public ItemInput parse(StringReader stringReader) throws CommandSyntaxException {
ItemParser.ItemResult itemResult = this.parser.parse(stringReader);
- return new ItemInput(itemResult.item(), itemResult.components());
+ return new ItemInput(itemResult.item(), itemResult.components(), itemResult.patch()); // Paper - support component removals
}
public static <S> ItemInput getItem(CommandContext<S> context, String name) {
diff --git a/src/main/java/net/minecraft/commands/arguments/item/ItemInput.java b/src/main/java/net/minecraft/commands/arguments/item/ItemInput.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/commands/arguments/item/ItemInput.java
+++ b/src/main/java/net/minecraft/commands/arguments/item/ItemInput.java
@@ -0,0 +0,0 @@ public class ItemInput {
);
private final Holder<Item> item;
private final DataComponentMap components;
+ @javax.annotation.Nullable private final net.minecraft.core.component.DataComponentPatch patch; // Paper
public ItemInput(Holder<Item> item, DataComponentMap components) {
+ // Paper start
+ this(item, components, null);
+ }
+ public ItemInput(Holder<Item> item, DataComponentMap components, @javax.annotation.Nullable final net.minecraft.core.component.DataComponentPatch patch) {
+ this.patch = patch;
+ // Paper end
this.item = item;
this.components = components;
}
@@ -0,0 +0,0 @@ public class ItemInput {
public ItemStack createItemStack(int amount, boolean checkOverstack) throws CommandSyntaxException {
ItemStack itemStack = new ItemStack(this.item, amount);
- itemStack.applyComponents(this.components);
+ // Paper start - support component removals
+ if (this.patch != null) {
+ itemStack.applyComponents(this.patch);
+ } else {
+ itemStack.applyComponents(this.components);
+ }
+ // Paper end - support component removals
if (checkOverstack && amount > itemStack.getMaxStackSize()) {
throw ERROR_STACK_TOO_BIG.create(this.getItemName(), itemStack.getMaxStackSize());
} else {
diff --git a/src/main/java/net/minecraft/commands/arguments/item/ItemParser.java b/src/main/java/net/minecraft/commands/arguments/item/ItemParser.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/commands/arguments/item/ItemParser.java
+++ b/src/main/java/net/minecraft/commands/arguments/item/ItemParser.java
@@ -0,0 +0,0 @@ public class ItemParser {
static final Function<SuggestionsBuilder, CompletableFuture<Suggestions>> SUGGEST_NOTHING = SuggestionsBuilder::buildFuture;
final HolderLookup.RegistryLookup<Item> items;
final DynamicOps<Tag> registryOps;
+ final boolean allowRemoves; // Paper - support component removals
public ItemParser(HolderLookup.Provider registriesLookup) {
+ // Paper start - support component removals
+ this(registriesLookup, false);
+ }
+ public ItemParser(HolderLookup.Provider registriesLookup, boolean allowRemoves) {
+ this.allowRemoves = allowRemoves;
+ // Paper end - support component removals
this.items = registriesLookup.lookupOrThrow(Registries.ITEM);
this.registryOps = registriesLookup.createSerializationContext(NbtOps.INSTANCE);
}
@@ -0,0 +0,0 @@ public class ItemParser {
public ItemParser.ItemResult parse(StringReader reader) throws CommandSyntaxException {
final MutableObject<Holder<Item>> mutableObject = new MutableObject<>();
final DataComponentMap.Builder builder = DataComponentMap.builder();
+ final net.minecraft.core.component.DataComponentPatch.Builder patchBuilder = net.minecraft.core.component.DataComponentPatch.builder(); // Paper - support component removals
this.parse(reader, new ItemParser.Visitor() {
@Override
public void visitItem(Holder<Item> item) {
@@ -0,0 +0,0 @@ public class ItemParser {
@Override
public <T> void visitComponent(DataComponentType<T> type, T value) {
builder.set(type, value);
+ // Paper start - support component removals
+ patchBuilder.set(type, value);
+ }
+ @Override
+ public <T> void visitComponentRemove(final DataComponentType<T> type) {
+ patchBuilder.remove(type);
+ // Paper end - support component removals
}
});
Holder<Item> holder = Objects.requireNonNull(mutableObject.getValue(), "Parser gave no item");
DataComponentMap dataComponentMap = builder.build();
validateComponents(reader, holder, dataComponentMap);
- return new ItemParser.ItemResult(holder, dataComponentMap);
+ return new ItemParser.ItemResult(holder, dataComponentMap, this.allowRemoves ? patchBuilder.build() : null); // Paper - support component removals
}
private static void validateComponents(StringReader reader, Holder<Item> item, DataComponentMap components) throws CommandSyntaxException {
@@ -0,0 +0,0 @@ public class ItemParser {
return suggestionsVisitor.resolveSuggestions(builder, stringReader);
}
- public static record ItemResult(Holder<Item> item, DataComponentMap components) {
+ public static record ItemResult(Holder<Item> item, DataComponentMap components, @javax.annotation.Nullable net.minecraft.core.component.DataComponentPatch patch) { // Paper
}
class State {
@@ -0,0 +0,0 @@ public class ItemParser {
while (this.reader.canRead() && this.reader.peek() != ']') {
this.reader.skipWhitespace();
+ boolean removing = ItemParser.this.allowRemoves && this.reader.canRead() && this.reader.peek() == '!';
+ if (removing) {
+ this.reader.skip();
+ this.visitor.visitSuggestions(builder -> this.suggestComponentAssignment(builder, false));
+ }
DataComponentType<?> dataComponentType = readComponentType(this.reader);
if (!set.add(dataComponentType)) {
throw ItemParser.ERROR_REPEATED_COMPONENT.create(dataComponentType);
}
+ // Paper start - support component removals
+ if (removing) {
+ this.visitor.visitComponentRemove(dataComponentType);
+ } else {
+ // Paper end - support component removals
this.visitor.visitSuggestions(this::suggestAssignment);
this.reader.skipWhitespace();
this.reader.expect('=');
this.visitor.visitSuggestions(ItemParser.SUGGEST_NOTHING);
this.reader.skipWhitespace();
this.readComponent(dataComponentType);
+ } // Paper - support component removals
this.reader.skipWhitespace();
this.visitor.visitSuggestions(this::suggestNextOrEndComponents);
if (!this.reader.canRead() || this.reader.peek() != ',') {
@@ -0,0 +0,0 @@ public class ItemParser {
}
private CompletableFuture<Suggestions> suggestComponentAssignment(SuggestionsBuilder builder) {
+ // Paper start - support component removals
+ return this.suggestComponentAssignment(builder, true);
+ }
+ private CompletableFuture<Suggestions> suggestComponentAssignment(SuggestionsBuilder builder, boolean suggestRemove) {
String string = builder.getRemaining().toLowerCase(Locale.ROOT);
+ if (suggestRemove && string.isBlank()) builder.suggest("!", Component.literal("Remove a data component"));
+ // Paper end - support component removals
SharedSuggestionProvider.filterResources(BuiltInRegistries.DATA_COMPONENT_TYPE.entrySet(), string, entry -> entry.getKey().location(), entry -> {
DataComponentType<?> dataComponentType = entry.getValue();
if (dataComponentType.codec() != null) {
ResourceLocation resourceLocation = entry.getKey().location();
- builder.suggest(resourceLocation.toString() + "=");
+ builder.suggest(resourceLocation.toString() + (suggestRemove ? "=" : "")); // Paper - support component removals
}
});
return builder.buildFuture();
@@ -0,0 +0,0 @@ public class ItemParser {
default <T> void visitComponent(DataComponentType<T> type, T value) {
}
+ default <T> void visitComponentRemove(DataComponentType<T> type) {} // Paper
default void visitSuggestions(Function<SuggestionsBuilder, CompletableFuture<Suggestions>> suggestor) {
}
diff --git a/src/main/java/net/minecraft/server/commands/GiveCommand.java b/src/main/java/net/minecraft/server/commands/GiveCommand.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/commands/GiveCommand.java
+++ b/src/main/java/net/minecraft/server/commands/GiveCommand.java
@@ -0,0 +0,0 @@ public class GiveCommand {
})).then(net.minecraft.commands.Commands.argument("count", IntegerArgumentType.integer(1)).executes((commandcontext) -> {
return GiveCommand.giveItem((CommandSourceStack) commandcontext.getSource(), ItemArgument.getItem(commandcontext, "item"), EntityArgument.getPlayers(commandcontext, "targets"), IntegerArgumentType.getInteger(commandcontext, "count"));
})))));
+ // Paper start - support component removals with a custom pgive command
+ final com.mojang.brigadier.tree.CommandNode<net.minecraft.commands.CommandSourceStack> node = net.minecraft.commands.Commands
+ .literal("pgive").requires((css) -> css.hasPermission(2))
+ .then(net.minecraft.commands.Commands.argument("targets", EntityArgument.players())
+ .then(net.minecraft.commands.Commands.argument("item", new ItemArgument(commandRegistryAccess, true)).executes((ctx) -> {
+ return GiveCommand.giveItem(ctx.getSource(), ItemArgument.getItem(ctx, "item"), EntityArgument.getPlayers(ctx, "targets"), 1);
+ })
+ .then(net.minecraft.commands.Commands.argument("count", IntegerArgumentType.integer(1)).executes((ctx) -> {
+ return GiveCommand.giveItem(ctx.getSource(), ItemArgument.getItem(ctx, "item"), EntityArgument.getPlayers(ctx, "targets"), IntegerArgumentType.getInteger(ctx, "count"));
+ }))
+ )
+ ).build();
+ setClientNodes(node);
+ dispatcher.getRoot().addChild(node);
+ }
+ static void setClientNodes(com.mojang.brigadier.tree.CommandNode<net.minecraft.commands.CommandSourceStack> node) {
+ if (node instanceof com.mojang.brigadier.tree.ArgumentCommandNode<net.minecraft.commands.CommandSourceStack,?> argumentNode) {
+ if (argumentNode.getType() instanceof ItemArgument) {
+ node.clientNode = new com.mojang.brigadier.tree.ArgumentCommandNode<>(
+ argumentNode.getName(),
+ com.mojang.brigadier.arguments.StringArgumentType.greedyString(),
+ argumentNode.getCommand(),
+ argumentNode.getRequirement(),
+ argumentNode.getRedirect(),
+ argumentNode.getRedirectModifier(),
+ argumentNode.isFork(),
+ (ctx, builder) -> builder.buildFuture()
+ );
+ }
+ }
+ node.getChildren().forEach(GiveCommand::setClientNodes);
+ // Paper end - support component removals with a custom pgive command
}
private static int giveItem(CommandSourceStack source, ItemInput item, Collection<ServerPlayer> targets, int count) throws CommandSyntaxException {
diff --git a/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java b/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java
+++ b/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java
@@ -0,0 +0,0 @@ public final class VanillaCommandWrapper extends BukkitCommand {
vanillaCommand = vanillaCommand.getRedirect();
}
final String commandName = vanillaCommand.getName();
+ if ("pgive".equals(stripDefaultNamespace(commandName))) {
+ return "bukkit.command.paper.pgive";
+ }
return "minecraft.command." + stripDefaultNamespace(commandName);
}
diff --git a/src/test/java/io/papermc/paper/permissions/MinecraftCommandPermissionsTest.java b/src/test/java/io/papermc/paper/permissions/MinecraftCommandPermissionsTest.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/test/java/io/papermc/paper/permissions/MinecraftCommandPermissionsTest.java
+++ b/src/test/java/io/papermc/paper/permissions/MinecraftCommandPermissionsTest.java
@@ -0,0 +0,0 @@ public class MinecraftCommandPermissionsTest extends AbstractTestingBase {
Set<String> foundPerms = new HashSet<>();
for (CommandNode<CommandSourceStack> child : root.getChildren()) {
final String vanillaPerm = VanillaCommandWrapper.getPermission(child);
+ if ("bukkit.command.paper.pgive".equals(vanillaPerm)) { // skip our custom give command
+ continue;
+ }
if (!perms.contains(vanillaPerm)) {
missing.add("Missing permission for " + child.getName() + " (" + vanillaPerm + ") command");
} else {

View File

@@ -1,26 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: SoSeDiK <mrsosedik@gmail.com>
Date: Wed, 1 May 2024 07:44:50 +0300
Subject: [PATCH] Add missing fishing event state
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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java
@@ -0,0 +0,0 @@ public class FishingHook extends Projectile {
this.fishAngle = Mth.nextFloat(this.random, this.minLureAngle, this.maxLureAngle);
this.timeUntilHooked = Mth.nextInt(this.random, this.minLureTime, this.maxLureTime);
// CraftBukkit end
+ // Paper start - Add missing fishing event state
+ if (this.getPlayerOwner() != null) {
+ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) this.getPlayerOwner().getBukkitEntity(), null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.LURED);
+ if (!playerFishEvent.callEvent()) {
+ this.timeUntilHooked = 0;
+ return;
+ }
+ }
+ // Paper end - Add missing fishing event state
}
} else {
// CraftBukkit start - logic to modify fishing wait time

View File

@@ -1,56 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: nostalfinals <yuu8583@proton.me>
Date: Mon, 8 Apr 2024 23:24:38 +0800
Subject: [PATCH] Added API to get player ha proxy address
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/network/Connection.java
+++ b/src/main/java/net/minecraft/network/Connection.java
@@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
this.stopReadingPackets = true;
}
// Paper end - packet limiter
+ @Nullable public SocketAddress haProxyAddress; // Paper - Add API to get player's proxy address
public Connection(PacketFlow side) {
this.receiving = side;
diff --git a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java
+++ b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java
@@ -0,0 +0,0 @@ public class ServerConnectionListener {
Connection connection = (Connection) channel.pipeline().get("packet_handler");
connection.address = socketaddr;
+
+ // Paper start - Add API to get player's proxy address
+ final String proxyAddress = message.destinationAddress();
+ final int proxyPort = message.destinationPort();
+
+ connection.haProxyAddress = new java.net.InetSocketAddress(proxyAddress, proxyPort);
+ // Paper end - Add API to get player's proxy address
}
} else {
super.channelRead(ctx, msg);
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
}
}
+ // Paper start - Add API to get player's proxy address
+ @Override
+ public @Nullable InetSocketAddress getHAProxyAddress() {
+ if (this.getHandle().connection == null) return null;
+
+ return this.getHandle().connection.connection.haProxyAddress instanceof final InetSocketAddress inetSocketAddress ? inetSocketAddress : null;
+ }
+ // Paper end - Add API to get player's proxy address
+
public interface TransferCookieConnection {
boolean isTransferred();

View File

@@ -1,134 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Bjarne Koll <git@lynxplay.dev>
Date: Thu, 13 Jun 2024 11:02:36 +0200
Subject: [PATCH] Adopt MaterialRerouting
Adopts the paper-api to the material rerouting infrastructure introduced
by upstream.
diff --git a/src/main/java/org/bukkit/craftbukkit/legacy/MaterialRerouting.java b/src/main/java/org/bukkit/craftbukkit/legacy/MaterialRerouting.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/legacy/MaterialRerouting.java
+++ b/src/main/java/org/bukkit/craftbukkit/legacy/MaterialRerouting.java
@@ -0,0 +0,0 @@ public class MaterialRerouting {
public static void setBlocks(ToolComponent.ToolRule toolRule, Collection<Material> blocks) {
toolRule.setBlocks(blocks.stream().map(MaterialRerouting::transformToBlockType).toList());
}
+
+ // Paper start - register paper API specific material consumers in rerouting
+ // A lot of these methods do *not* run through MaterialRerouting to avoid the overhead of a system that
+ // currently is an effective noop.
+ // The only downside is that upstream moved the handling of legacy materials into transformFromXType methods.
+ // As such, methods introduced prior to 1.13 need to run through the transformation to make sure legacy material
+ // constants still work.
+
+ // Utility method for constructing a set from an existing one after mapping each element.
+ private static <I, O> Set<O> mapSet(final Set<I> input, final java.util.function.Function<I,O> mapper) {
+ final Set<O> output = new it.unimi.dsi.fastutil.objects.ObjectOpenHashSet<>(input.size());
+ for (final I i : input) {
+ output.add(mapper.apply(i));
+ }
+ return output;
+ }
+
+ // Method added post-1.13, noop (https://github.com/PaperMC/Paper/pull/4965)
+ public static org.bukkit.Material getMinecartMaterial(org.bukkit.entity.Minecart minecart, @InjectPluginVersion ApiVersion version) {
+ return minecart.getMinecartMaterial();
+ }
+
+ // Method added post-1.13, noop (https://github.com/PaperMC/Paper/pull/4965)
+ public static Material getBoatMaterial(Boat boat, @InjectPluginVersion ApiVersion version) {
+ return boat.getBoatMaterial();
+ }
+
+ // Method added post-1.13, noop (https://github.com/PaperMC/Paper/pull/3807)
+ public static Material getType(io.papermc.paper.event.player.PlayerItemCooldownEvent event, @InjectPluginVersion ApiVersion version) {
+ return event.getType();
+ }
+
+ // Method added post-1.13, noop (https://github.com/PaperMC/Paper/pull/3850)
+ public static Collection<Material> getInfiniburn(World world, @InjectPluginVersion ApiVersion version) {
+ return world.getInfiniburn();
+ }
+
+ // Method added pre-1.13, needs legacy rerouting (https://github.com/PaperMC/Paper/commit/3438e96192)
+ public static Set<Material> getTypes(
+ final com.destroystokyo.paper.event.player.PlayerArmorChangeEvent.SlotType slotType,
+ @InjectPluginVersion final ApiVersion apiVersion
+ ) {
+ if (apiVersion.isNewerThanOrSameAs(ApiVersion.FLATTENING)) return slotType.getTypes();
+ else return mapSet(slotType.getTypes(), MaterialRerouting::transformToItemType); // Needed as pre-flattening is hanled by transformToItemType
+ }
+
+ // Method added pre-1.13, needs legacy rerouting (https://github.com/PaperMC/Paper/commit/3438e96192)
+ @RerouteStatic("com/destroystokyo/paper/event/player/PlayerArmorChangeEvent$SlotType")
+ public static com.destroystokyo.paper.event.player.PlayerArmorChangeEvent.SlotType getByMaterial(
+ final Material material
+ ) {
+ return com.destroystokyo.paper.event.player.PlayerArmorChangeEvent.SlotType.getByMaterial(MaterialRerouting.transformToItemType(material));
+ }
+
+ // Method added pre-1.13, needs legacy rerouting (https://github.com/PaperMC/Paper/commit/3438e96192)
+ @RerouteStatic("com/destroystokyo/paper/event/player/PlayerArmorChangeEvent$SlotType")
+ public static boolean isEquipable(final Material material) {
+ return com.destroystokyo.paper.event.player.PlayerArmorChangeEvent.SlotType.isEquipable(MaterialRerouting.transformToItemType(material));
+ }
+
+ // Method added post 1.13, no-op (https://github.com/PaperMC/Paper/pull/1244)1
+ public static Material getMaterial(final com.destroystokyo.paper.event.block.AnvilDamagedEvent.DamageState damageState) {
+ return damageState.getMaterial();
+ }
+
+ // Method added post 1.13, no-op (https://github.com/PaperMC/Paper/pull/1244)1
+ @RerouteStatic("com/destroystokyo/paper/event/block/AnvilDamagedEvent$DamageState")
+ public static com.destroystokyo.paper.event.block.AnvilDamagedEvent.DamageState getState(
+ final Material material
+ ) {
+ return com.destroystokyo.paper.event.block.AnvilDamagedEvent.DamageState.getState(material);
+ }
+
+ // Method added post 1.13, no-op (https://github.com/PaperMC/Paper/pull/10290)
+ public static ItemStack withType(final ItemStack itemStack, final Material material) {
+ return itemStack.withType(material);
+ }
+ // Paper end - register paper API specific material consumers in rerouting
}
diff --git a/src/test/java/org/bukkit/craftbukkit/legacy/MaterialReroutingTest.java b/src/test/java/org/bukkit/craftbukkit/legacy/MaterialReroutingTest.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/test/java/org/bukkit/craftbukkit/legacy/MaterialReroutingTest.java
+++ b/src/test/java/org/bukkit/craftbukkit/legacy/MaterialReroutingTest.java
@@ -0,0 +0,0 @@ public class MaterialReroutingTest extends AbstractTestingBase {
.filter(entry -> !entry.getName().endsWith("ItemType.class"))
.filter(entry -> !entry.getName().endsWith("Registry.class"))
.filter(entry -> !entry.getName().startsWith("org/bukkit/material"))
+ // Paper start - types that cannot be translated to ItemType/BlockType
+ .filter(entry -> !entry.getName().equals("com/destroystokyo/paper/MaterialSetTag.class"))
+ // Paper end - types that cannot be translated to ItemType/BlockType
.map(entry -> {
try {
return MaterialReroutingTest.jarFile.getInputStream(entry);
@@ -0,0 +0,0 @@ public class MaterialReroutingTest extends AbstractTestingBase {
continue;
}
}
+ // Paper start - filter out more methods from rerouting test
+ if (methodNode.name.startsWith("lambda$")) continue;
+ if (isInternal(methodNode.invisibleAnnotations)) continue;
+ // Paper end - filter out more methods from rerouting test
if (!Commodore.rerouteMethods(Collections.emptySet(), MaterialReroutingTest.MATERIAL_METHOD_REROUTE, (methodNode.access & Opcodes.ACC_STATIC) != 0, classNode.name, methodNode.name, methodNode.desc, a -> { })) {
missingReroute.add(methodNode.name + " " + methodNode.desc + " " + methodNode.signature);
@@ -0,0 +0,0 @@ public class MaterialReroutingTest extends AbstractTestingBase {
}
}
+ // Paper start - filter out more methods from rerouting test
+ private static boolean isInternal(final List<org.objectweb.asm.tree.AnnotationNode> annotationNodes) {
+ return annotationNodes != null
+ && annotationNodes.stream().anyMatch(a -> a.desc.equals("Lorg/jetbrains/annotations/ApiStatus$Internal;"));
+ }
+ // Paper end - filter out more methods from rerouting test
+
@AfterAll
public static void clear() throws IOException {
if (MaterialReroutingTest.jarFile != null) {

View File

@@ -1,130 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
Date: Tue, 21 May 2024 13:18:15 -0700
Subject: [PATCH] Allow Bukkit plugin to use Paper PluginLoader API
diff --git a/src/main/java/io/papermc/paper/plugin/loader/PaperClasspathBuilder.java b/src/main/java/io/papermc/paper/plugin/loader/PaperClasspathBuilder.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/io/papermc/paper/plugin/loader/PaperClasspathBuilder.java
+++ b/src/main/java/io/papermc/paper/plugin/loader/PaperClasspathBuilder.java
@@ -0,0 +0,0 @@ public class PaperClasspathBuilder implements PluginClasspathBuilder {
}
public PaperPluginClassLoader buildClassLoader(Logger logger, Path source, JarFile jarFile, PaperPluginMeta configuration) {
- PaperLibraryStore paperLibraryStore = new PaperLibraryStore();
- for (ClassPathLibrary library : this.libraries) {
- library.register(paperLibraryStore);
- }
-
- List<Path> paths = paperLibraryStore.getPaths();
- if (PluginInitializerManager.instance().pluginRemapper != null) {
- paths = PluginInitializerManager.instance().pluginRemapper.remapLibraries(paths);
- }
+ List<Path> paths = this.buildLibraryPaths(true);
URL[] urls = new URL[paths.size()];
for (int i = 0; i < paths.size(); i++) {
Path path = paths.get(i);
@@ -0,0 +0,0 @@ public class PaperClasspathBuilder implements PluginClasspathBuilder {
throw new RuntimeException(exception);
}
}
+
+ public List<Path> buildLibraryPaths(final boolean remap) {
+ PaperLibraryStore paperLibraryStore = new PaperLibraryStore();
+ for (ClassPathLibrary library : this.libraries) {
+ library.register(paperLibraryStore);
+ }
+
+ List<Path> paths = paperLibraryStore.getPaths();
+ if (remap && PluginInitializerManager.instance().pluginRemapper != null) {
+ paths = PluginInitializerManager.instance().pluginRemapper.remapLibraries(paths);
+ }
+ return paths;
+ }
}
diff --git a/src/main/java/io/papermc/paper/plugin/provider/type/spigot/SpigotPluginProvider.java b/src/main/java/io/papermc/paper/plugin/provider/type/spigot/SpigotPluginProvider.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/io/papermc/paper/plugin/provider/type/spigot/SpigotPluginProvider.java
+++ b/src/main/java/io/papermc/paper/plugin/provider/type/spigot/SpigotPluginProvider.java
@@ -0,0 +0,0 @@ public class SpigotPluginProvider implements PluginProvider<JavaPlugin>, Provide
private final PluginDescriptionFile description;
private final JarFile jarFile;
private final Logger logger;
+ private final List<Path> paperLibraryPaths;
private final ComponentLogger componentLogger;
private ProviderStatus status;
private DependencyContext dependencyContext;
- SpigotPluginProvider(Path path, JarFile file, PluginDescriptionFile description) {
+ SpigotPluginProvider(Path path, JarFile file, PluginDescriptionFile description, List<Path> paperLibraryPaths) {
this.path = path;
this.jarFile = file;
this.description = description;
this.logger = PaperPluginLogger.getLogger(description);
+ this.paperLibraryPaths = paperLibraryPaths;
this.componentLogger = ComponentLogger.logger(this.logger.getName());
}
@@ -0,0 +0,0 @@ public class SpigotPluginProvider implements PluginProvider<JavaPlugin>, Provide
final PluginClassLoader loader;
try {
- loader = new PluginClassLoader(this.getClass().getClassLoader(), this.description, dataFolder, this.path.toFile(), LIBRARY_LOADER.createLoader(this.description), this.jarFile, this.dependencyContext); // Paper
+ loader = new PluginClassLoader(this.getClass().getClassLoader(), this.description, dataFolder, this.path.toFile(), LIBRARY_LOADER.createLoader(this.description, this.paperLibraryPaths), this.jarFile, this.dependencyContext); // Paper
} catch (InvalidPluginException ex) {
throw ex;
} catch (Throwable ex) {
diff --git a/src/main/java/io/papermc/paper/plugin/provider/type/spigot/SpigotPluginProviderFactory.java b/src/main/java/io/papermc/paper/plugin/provider/type/spigot/SpigotPluginProviderFactory.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/io/papermc/paper/plugin/provider/type/spigot/SpigotPluginProviderFactory.java
+++ b/src/main/java/io/papermc/paper/plugin/provider/type/spigot/SpigotPluginProviderFactory.java
@@ -0,0 +0,0 @@
package io.papermc.paper.plugin.provider.type.spigot;
+import com.destroystokyo.paper.utils.PaperPluginLogger;
+import io.papermc.paper.plugin.bootstrap.PluginProviderContextImpl;
import io.papermc.paper.plugin.entrypoint.classloader.BytecodeModifyingURLClassLoader;
+import io.papermc.paper.plugin.entrypoint.classloader.PaperSimplePluginClassLoader;
+import io.papermc.paper.plugin.loader.PaperClasspathBuilder;
+import io.papermc.paper.plugin.loader.PluginLoader;
import io.papermc.paper.plugin.provider.configuration.serializer.constraints.PluginConfigConstraints;
import io.papermc.paper.plugin.provider.type.PluginTypeFactory;
+import io.papermc.paper.plugin.provider.util.ProviderUtil;
import io.papermc.paper.util.MappingEnvironment;
+import java.util.List;
+import java.util.logging.Logger;
+import net.kyori.adventure.text.logger.slf4j.ComponentLogger;
import org.bukkit.plugin.InvalidDescriptionException;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.java.LibraryLoader;
@@ -0,0 +0,0 @@ class SpigotPluginProviderFactory implements PluginTypeFactory<SpigotPluginProvi
throw new InvalidDescriptionException("Restricted name, cannot use 0x20 (space character) in a plugin name.");
}
- return new SpigotPluginProvider(source, file, configuration);
+ final List<Path> paperLibraryPaths;
+ if (configuration.getPaperPluginLoader() != null) {
+ final Logger logger = PaperPluginLogger.getLogger(configuration);
+ PaperClasspathBuilder builder = new PaperClasspathBuilder(PluginProviderContextImpl.create(
+ configuration, ComponentLogger.logger(logger.getName()), source
+ ));
+
+ try (
+ PaperSimplePluginClassLoader simplePluginClassLoader = new PaperSimplePluginClassLoader(source, file, configuration, this.getClass().getClassLoader())
+ ) {
+ PluginLoader loader = ProviderUtil.loadClass(configuration.getPaperPluginLoader(), PluginLoader.class, simplePluginClassLoader);
+ loader.classloader(builder);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+
+ paperLibraryPaths = builder.buildLibraryPaths(false);
+ } else {
+ paperLibraryPaths = null;
+ }
+
+ return new SpigotPluginProvider(source, file, configuration, paperLibraryPaths);
}
@Override

File diff suppressed because it is too large Load Diff

View File

@@ -1,45 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: SoSeDiK <mrsosedik@gmail.com>
Date: Thu, 26 May 2022 03:30:05 +0300
Subject: [PATCH] Deep clone nbt tags in PDC
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
this.damage = meta.damage;
this.maxDamage = meta.maxDamage;
this.unhandledTags = meta.unhandledTags;
- this.persistentDataContainer.putAll(meta.persistentDataContainer.getRaw());
+ this.persistentDataContainer.putAll(meta.persistentDataContainer.getTagsCloned()); // Paper - deep clone NBT tags
this.customTag = meta.customTag;
@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
if (this.customTag != null) {
clone.customTag = this.customTag.copy();
}
- clone.persistentDataContainer = new CraftPersistentDataContainer(this.persistentDataContainer.getRaw(), CraftMetaItem.DATA_TYPE_REGISTRY);
+ clone.persistentDataContainer = new CraftPersistentDataContainer(this.persistentDataContainer.getTagsCloned(), CraftMetaItem.DATA_TYPE_REGISTRY); // Paper - deep clone NBT tags
clone.hideFlag = this.hideFlag;
clone.hideTooltip = this.hideTooltip;
clone.unbreakable = this.unbreakable;
diff --git a/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java
+++ b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java
@@ -0,0 +0,0 @@ public class CraftPersistentDataContainer implements PersistentDataContainer {
}
}
// Paper end - byte array serialization
+
+ // Paper start - deep clone tags
+ public Map<String, Tag> getTagsCloned() {
+ final Map<String, Tag> tags = new HashMap<>();
+ this.customDataTags.forEach((key, tag) -> tags.put(key, tag.copy()));
+ return tags;
+ }
+ // Paper end - deep clone tags
}

View File

@@ -1,26 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sat, 25 May 2024 09:51:13 -0700
Subject: [PATCH] Deprecate InvAction#HOTBAR_MOVE_AND_READD
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
Slot clickedSlot = this.player.containerMenu.getSlot(packet.getSlotNum());
if (clickedSlot.mayPickup(this.player)) {
ItemStack hotbar = this.player.getInventory().getItem(packet.getButtonNum());
- boolean canCleanSwap = hotbar.isEmpty() || (clickedSlot.container == this.player.getInventory() && clickedSlot.mayPlace(hotbar)); // the slot will accept the hotbar item
- if (clickedSlot.hasItem()) {
- if (canCleanSwap) {
- action = InventoryAction.HOTBAR_SWAP;
- } else {
- action = InventoryAction.HOTBAR_MOVE_AND_READD;
- }
- } else if (!clickedSlot.hasItem() && !hotbar.isEmpty() && clickedSlot.mayPlace(hotbar)) {
+ if ((!hotbar.isEmpty() && clickedSlot.mayPlace(hotbar)) || (hotbar.isEmpty() && clickedSlot.hasItem())) { // Paper - modernify this logic (no such thing as a "hotbar move and readd"
action = InventoryAction.HOTBAR_SWAP;
} else {
action = InventoryAction.NOTHING;

View File

@@ -1,47 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Fri, 26 Apr 2024 21:33:20 -0700
Subject: [PATCH] Don't lose removed data components in ItemMeta
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
return this;
}
+ // Paper start - support removing component types
+ <T> Applicator remove(DataComponentType<T> type) {
+ this.builder.remove(type);
+ return this;
+ }
+ // Paper end - support removing component types
+
DataComponentPatch build() {
return this.builder.build();
}
@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
Set<Map.Entry<DataComponentType<?>, Optional<?>>> keys = tag.entrySet();
for (Map.Entry<DataComponentType<?>, Optional<?>> key : keys) {
- if (!CraftMetaItem.getHandledTags().contains(key.getKey())) {
+ if (key.getValue().isEmpty()) {
+ this.unhandledTags.remove(key.getKey());
+ } else if (!CraftMetaItem.getHandledTags().contains(key.getKey())) {
key.getValue().ifPresentOrElse((value) -> {
this.unhandledTags.set((DataComponentType) key.getKey(), value);
}, () -> {
@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
}
for (Map.Entry<DataComponentType<?>, Optional<?>> e : this.unhandledTags.build().entrySet()) {
- e.getValue().ifPresent((value) -> {
+ e.getValue().ifPresentOrElse((value) -> {
itemTag.builder.set((DataComponentType) e.getKey(), value);
- });
+ }, () -> itemTag.remove(e.getKey()));
}
CompoundTag customTag = (this.customTag != null) ? this.customTag.copy() : null;

View File

@@ -1,38 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: SoSeDiK <mrsosedik@gmail.com>
Date: Wed, 1 May 2024 10:58:50 +0300
Subject: [PATCH] Expose #hasColor to leather armor
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaColorableArmor.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaColorableArmor.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaColorableArmor.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaColorableArmor.java
@@ -0,0 +0,0 @@ public class CraftMetaColorableArmor extends CraftMetaArmor implements Colorable
}
return original != hash ? CraftMetaColorableArmor.class.hashCode() ^ hash : hash;
}
+
+ // Paper start - Expose #hasColor to leather armor
+ @Override
+ public boolean isDyed() {
+ return hasColor();
+ }
+ // Paper end - Expose #hasColor to leather armor
}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaLeatherArmor.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaLeatherArmor.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaLeatherArmor.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaLeatherArmor.java
@@ -0,0 +0,0 @@ class CraftMetaLeatherArmor extends CraftMetaItem implements LeatherArmorMeta {
builder.put(CraftMetaLeatherArmor.COLOR.BUKKIT, meta.getColor());
}
}
+
+ // Paper start - Expose #hasColor to leather armor
+ @Override
+ public boolean isDyed() {
+ return hasColor();
+ }
+ // Paper end - Expose #hasColor to leather armor
}

View File

@@ -1,200 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sat, 27 Apr 2024 12:16:38 -0700
Subject: [PATCH] Fix ItemFlags
Re-adds missing functionality for HIDE_DESTROYS and
HIDE_PLACED_ON. Also adds new flag in HIDE_STORED_ENCHANTS
which was split from HIDE_ADDITIONAL_TOOLTIP.
== AT ==
public net.minecraft.world.item.AdventureModePredicate predicates
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaEnchantedBook.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaEnchantedBook.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaEnchantedBook.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaEnchantedBook.java
@@ -0,0 +0,0 @@ class CraftMetaEnchantedBook extends CraftMetaItem implements EnchantmentStorage
getOrEmpty(tag, CraftMetaEnchantedBook.STORED_ENCHANTMENTS).ifPresent((itemEnchantments) -> {
this.enchantments = buildEnchantments(itemEnchantments);
if (!itemEnchantments.showInTooltip) {
- this.addItemFlags(ItemFlag.HIDE_ADDITIONAL_TOOLTIP);
+ this.addItemFlags(ItemFlag.HIDE_STORED_ENCHANTS); // Paper - new ItemFlag
}
});
}
@@ -0,0 +0,0 @@ class CraftMetaEnchantedBook extends CraftMetaItem implements EnchantmentStorage
void applyToItem(CraftMetaItem.Applicator itemTag) {
super.applyToItem(itemTag);
- this.applyEnchantments(this.enchantments, itemTag, CraftMetaEnchantedBook.STORED_ENCHANTMENTS, ItemFlag.HIDE_ADDITIONAL_TOOLTIP);
+ this.applyEnchantments(this.enchantments, itemTag, CraftMetaEnchantedBook.STORED_ENCHANTMENTS, ItemFlag.HIDE_STORED_ENCHANTS);
}
@Override
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
static final ItemMetaKeyType<Unit> HIDE_ADDITIONAL_TOOLTIP = new ItemMetaKeyType(DataComponents.HIDE_ADDITIONAL_TOOLTIP);
@Specific(Specific.To.NBT)
static final ItemMetaKeyType<CustomData> CUSTOM_DATA = new ItemMetaKeyType<>(DataComponents.CUSTOM_DATA);
+ // Paper start - fix ItemFlags
+ static final ItemMetaKeyType<net.minecraft.world.item.AdventureModePredicate> CAN_PLACE_ON = new ItemMetaKeyType<>(DataComponents.CAN_PLACE_ON);
+ static final ItemMetaKeyType<net.minecraft.world.item.AdventureModePredicate> CAN_BREAK = new ItemMetaKeyType<>(DataComponents.CAN_BREAK);
+ private List<net.minecraft.advancements.critereon.BlockPredicate> canPlaceOnPredicates;
+ private List<net.minecraft.advancements.critereon.BlockPredicate> canBreakPredicates;
+ // Paper end - fix ItemFlags
// We store the raw original JSON representation of all text data. See SPIGOT-5063, SPIGOT-5656, SPIGOT-5304
private Component displayName;
@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
this.customTag = meta.customTag;
this.version = meta.version;
+ // Paper start
+ this.canPlaceOnPredicates = meta.canPlaceOnPredicates;
+ this.canBreakPredicates = meta.canBreakPredicates;
+ // Paper end
}
CraftMetaItem(DataComponentPatch tag) {
@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
this.customTag = null;
}
});
+ // Paper start - fix ItemFlags
+ CraftMetaItem.getOrEmpty(tag, CraftMetaItem.CAN_PLACE_ON).ifPresent(data -> {
+ this.canPlaceOnPredicates = List.copyOf(data.predicates);
+ if (!data.showInTooltip()) {
+ this.addItemFlags(ItemFlag.HIDE_PLACED_ON);
+ }
+ });
+ CraftMetaItem.getOrEmpty(tag, CraftMetaItem.CAN_BREAK).ifPresent(data -> {
+ this.canBreakPredicates = List.copyOf(data.predicates);
+ if (!data.showInTooltip()) {
+ this.addItemFlags(ItemFlag.HIDE_DESTROYS);
+ }
+ });
+ // Paper end - fix ItemFlags
Set<Map.Entry<DataComponentType<?>, Optional<?>>> keys = tag.entrySet();
for (Map.Entry<DataComponentType<?>, Optional<?>> key : keys) {
@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
ByteArrayInputStream buf = new ByteArrayInputStream(Base64.getDecoder().decode(unhandled));
try {
CompoundTag unhandledTag = NbtIo.readCompressed(buf, NbtAccounter.unlimitedHeap());
- this.unhandledTags.copy(DataComponentPatch.CODEC.parse(MinecraftServer.getDefaultRegistryAccess().createSerializationContext(NbtOps.INSTANCE), unhandledTag).result().get());
+ // Paper start
+ final net.minecraft.core.component.DataComponentPatch patch = net.minecraft.core.component.DataComponentPatch.CODEC.parse(net.minecraft.server.MinecraftServer.getDefaultRegistryAccess().createSerializationContext(net.minecraft.nbt.NbtOps.INSTANCE), unhandledTag).result().get();
+ CraftMetaItem.getOrEmpty(patch, CraftMetaItem.CAN_PLACE_ON).ifPresent(data -> {
+ this.canPlaceOnPredicates = List.copyOf(data.predicates);
+ });
+ CraftMetaItem.getOrEmpty(patch, CraftMetaItem.CAN_BREAK).ifPresent(data -> {
+ this.canBreakPredicates = List.copyOf(data.predicates);
+ });
+ this.unhandledTags.copy(patch.forget(type -> type == CraftMetaItem.CAN_PLACE_ON.TYPE || type == CraftMetaItem.CAN_BREAK.TYPE));
+ // Paper end
} catch (IOException ex) {
Logger.getLogger(CraftMetaItem.class.getName()).log(Level.SEVERE, null, ex);
}
@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
itemTag.put(CraftMetaItem.MAX_DAMAGE, this.maxDamage);
}
+ // Paper start
+ if (this.canPlaceOnPredicates != null && !this.canPlaceOnPredicates.isEmpty()) {
+ itemTag.put(CraftMetaItem.CAN_PLACE_ON, new net.minecraft.world.item.AdventureModePredicate(this.canPlaceOnPredicates, !this.hasItemFlag(ItemFlag.HIDE_PLACED_ON)));
+ }
+ if (this.canBreakPredicates != null && !this.canBreakPredicates.isEmpty()) {
+ itemTag.put(CraftMetaItem.CAN_BREAK, new net.minecraft.world.item.AdventureModePredicate(this.canBreakPredicates, !this.hasItemFlag(ItemFlag.HIDE_DESTROYS)));
+ }
+ // Paper end
+
for (Map.Entry<DataComponentType<?>, Optional<?>> e : this.unhandledTags.build().entrySet()) {
e.getValue().ifPresentOrElse((value) -> {
itemTag.builder.set((DataComponentType) e.getKey(), value);
@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
@Overridden
boolean isEmpty() {
- return !(this.hasDisplayName() || this.hasItemName() || this.hasLocalizedName() || this.hasEnchants() || (this.lore != null) || this.hasCustomModelData() || this.hasBlockData() || this.hasRepairCost() || !this.unhandledTags.build().isEmpty() || !this.persistentDataContainer.isEmpty() || this.hideFlag != 0 || this.isHideTooltip() || this.isUnbreakable() || this.hasEnchantmentGlintOverride() || this.isFireResistant() || this.hasMaxStackSize() || this.hasRarity() || this.hasFood() || this.hasTool() || this.hasDamage() || this.hasMaxDamage() || this.hasAttributeModifiers() || this.customTag != null);
+ return !(this.hasDisplayName() || this.hasItemName() || this.hasLocalizedName() || this.hasEnchants() || (this.lore != null) || this.hasCustomModelData() || this.hasBlockData() || this.hasRepairCost() || !this.unhandledTags.build().isEmpty() || !this.persistentDataContainer.isEmpty() || this.hideFlag != 0 || this.isHideTooltip() || this.isUnbreakable() || this.hasEnchantmentGlintOverride() || this.isFireResistant() || this.hasMaxStackSize() || this.hasRarity() || this.hasFood() || this.hasTool() || this.hasDamage() || this.hasMaxDamage() || this.hasAttributeModifiers() || this.customTag != null || this.canPlaceOnPredicates != null || this.canBreakPredicates != null); // Paper
}
// Paper start
@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
&& (this.hasTool() ? that.hasTool() && this.tool.equals(that.tool) : !that.hasTool())
&& (this.hasDamage() ? that.hasDamage() && this.damage == that.damage : !that.hasDamage())
&& (this.hasMaxDamage() ? that.hasMaxDamage() && this.maxDamage.equals(that.maxDamage) : !that.hasMaxDamage())
+ && (this.canPlaceOnPredicates != null ? that.canPlaceOnPredicates != null && this.canPlaceOnPredicates.equals(that.canPlaceOnPredicates) : that.canPlaceOnPredicates == null) // Paper
+ && (this.canBreakPredicates != null ? that.canBreakPredicates != null && this.canBreakPredicates.equals(that.canBreakPredicates) : that.canBreakPredicates == null) // Paper
&& (this.version == that.version);
}
@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
hash = 61 * hash + (this.hasDamage() ? this.damage : 0);
hash = 61 * hash + (this.hasMaxDamage() ? 1231 : 1237);
hash = 61 * hash + (this.hasAttributeModifiers() ? this.attributeModifiers.hashCode() : 0);
+ hash = 61 * hash + (this.canPlaceOnPredicates != null ? this.canPlaceOnPredicates.hashCode() : 0); // Paper
+ hash = 61 * hash + (this.canBreakPredicates != null ? this.canBreakPredicates.hashCode() : 0); // Paper
hash = 61 * hash + this.version;
return hash;
}
@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
clone.damage = this.damage;
clone.maxDamage = this.maxDamage;
clone.version = this.version;
+ // Paper start
+ if (this.canPlaceOnPredicates != null) {
+ clone.canPlaceOnPredicates = List.copyOf(this.canPlaceOnPredicates);
+ }
+ if (this.canBreakPredicates != null) {
+ clone.canBreakPredicates = List.copyOf(this.canBreakPredicates);
+ }
+ // Paper end
return clone;
} catch (CloneNotSupportedException e) {
throw new Error(e);
@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
}
}
+ // Paper start
+ final boolean canBreakAddToUnhandled = this.canBreakPredicates != null && !this.canBreakPredicates.isEmpty();
+ if (canBreakAddToUnhandled) {
+ this.unhandledTags.set(DataComponents.CAN_BREAK, new net.minecraft.world.item.AdventureModePredicate(this.canBreakPredicates, !this.hasItemFlag(ItemFlag.HIDE_DESTROYS)));
+ }
+ final boolean canPlaceOnAddToUnhandled = this.canPlaceOnPredicates != null && !this.canPlaceOnPredicates.isEmpty();
+ if (canPlaceOnAddToUnhandled) {
+ this.unhandledTags.set(DataComponents.CAN_PLACE_ON, new net.minecraft.world.item.AdventureModePredicate(this.canPlaceOnPredicates, !this.hasItemFlag(ItemFlag.HIDE_PLACED_ON)));
+ }
+ // Paper end
if (!this.unhandledTags.isEmpty()) {
Tag unhandled = DataComponentPatch.CODEC.encodeStart(MinecraftServer.getDefaultRegistryAccess().createSerializationContext(NbtOps.INSTANCE), this.unhandledTags.build()).getOrThrow(IllegalStateException::new);
try {
@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
Logger.getLogger(CraftMetaItem.class.getName()).log(Level.SEVERE, null, ex);
}
}
+ // Paper start
+ if (canBreakAddToUnhandled) {
+ this.unhandledTags.clear(DataComponents.CAN_BREAK);
+ }
+ if (canPlaceOnAddToUnhandled) {
+ this.unhandledTags.clear(DataComponents.CAN_PLACE_ON);
+ }
+ // Paper end
if (!this.persistentDataContainer.isEmpty()) { // Store custom tags, wrapped in their compound
builder.put(CraftMetaItem.BUKKIT_CUSTOM_TAG.BUKKIT, this.persistentDataContainer.serialize());
@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
CraftMetaItem.MAX_DAMAGE.TYPE,
CraftMetaItem.CUSTOM_DATA.TYPE,
CraftMetaItem.ATTRIBUTES.TYPE,
+ CraftMetaItem.CAN_PLACE_ON.TYPE, // Paper
+ CraftMetaItem.CAN_BREAK.TYPE, // Paper
CraftMetaArmor.TRIM.TYPE,
CraftMetaArmorStand.ENTITY_TAG.TYPE,
CraftMetaBanner.PATTERNS.TYPE,

View File

@@ -1,47 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Tamion <70228790+notTamion@users.noreply.github.com>
Date: Thu, 23 May 2024 11:02:20 +0200
Subject: [PATCH] Fix cancelling BlockPlaceEvent calling onRemove
diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/item/ItemStack.java
+++ b/src/main/java/net/minecraft/world/item/ItemStack.java
@@ -0,0 +0,0 @@ public final class ItemStack implements DataComponentHolder {
world.capturedTileEntities.clear(); // Paper - Allow chests to be placed with NBT data; clear out block entities as chests and such will pop loot
// revert back all captured blocks
world.preventPoiUpdated = true; // CraftBukkit - SPIGOT-5710
+ world.isBlockPlaceCancelled = true; // Paper - prevent calling cleanup logic when undoing a block place upon a cancelled BlockPlaceEvent
for (BlockState blockstate : blocks) {
blockstate.update(true, false);
}
+ world.isBlockPlaceCancelled = false; // Paper - prevent calling cleanup logic when undoing a block place upon a cancelled BlockPlaceEvent
world.preventPoiUpdated = false;
// Brute force all possible updates
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
public boolean preventPoiUpdated = false; // CraftBukkit - SPIGOT-5710
public boolean captureBlockStates = false;
public boolean captureTreeGeneration = false;
+ public boolean isBlockPlaceCancelled = false; // Paper - prevent calling cleanup logic when undoing a block place upon a cancelled BlockPlaceEvent
public Map<BlockPos, org.bukkit.craftbukkit.block.CraftBlockState> capturedBlockStates = new java.util.LinkedHashMap<>(); // Paper
public Map<BlockPos, BlockEntity> capturedTileEntities = new java.util.LinkedHashMap<>(); // Paper - Retain block place order when capturing blockstates
public List<ItemEntity> captureDrops;
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
@@ -0,0 +0,0 @@ public class LevelChunk extends ChunkAccess {
boolean flag3 = iblockdata1.hasBlockEntity();
- if (!this.level.isClientSide) {
+ if (!this.level.isClientSide && !this.level.isBlockPlaceCancelled) { // Paper - prevent calling cleanup logic when undoing a block place upon a cancelled BlockPlaceEvent
iblockdata1.onRemove(this.level, blockposition, iblockdata, flag);
} else if (!iblockdata1.is(block) && flag3) {
this.removeBlockEntity(blockposition);

View File

@@ -1,114 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Wed, 22 May 2024 10:01:19 -0700
Subject: [PATCH] Fix equipment slot and group API
Add test for EquipmentSlotGroup
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java
@@ -0,0 +0,0 @@ public class CraftInventoryPlayer extends CraftInventory implements org.bukkit.i
case HEAD:
this.setHelmet(item);
break;
+ // Paper start
+ case BODY:
+ throw new IllegalArgumentException("BODY is not valid for players!");
+ // Paper end
default:
throw new IllegalArgumentException("Not implemented. This is a bug");
}
@@ -0,0 +0,0 @@ public class CraftInventoryPlayer extends CraftInventory implements org.bukkit.i
return java.util.Objects.requireNonNullElseGet(this.getChestplate(), () -> new ItemStack(org.bukkit.Material.AIR)); // Paper - make nonnull
case HEAD:
return java.util.Objects.requireNonNullElseGet(this.getHelmet(), () -> new ItemStack(org.bukkit.Material.AIR)); // Paper - make nonnull
+ // Paper start
+ case BODY:
+ throw new IllegalArgumentException("BODY is not valid for players!");
+ // Paper end
default:
throw new IllegalArgumentException("Not implemented. This is a bug");
}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
if (this.attributeModifiers == null) return LinkedHashMultimap.create(); // Paper - don't change the components
SetMultimap<Attribute, AttributeModifier> result = LinkedHashMultimap.create();
for (Map.Entry<Attribute, AttributeModifier> entry : this.attributeModifiers.entries()) {
- if (entry.getValue().getSlot() == null || entry.getValue().getSlot() == slot) {
+ if (entry.getValue().getSlotGroup().test(slot)) { // Paper - correctly test slot against group
result.put(entry.getKey(), entry.getValue());
}
}
@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
while (iter.hasNext()) {
Map.Entry<Attribute, AttributeModifier> entry = iter.next();
- // Explicitly match against null because (as of MC 1.13) AttributeModifiers without a -
- // set slot are active in any slot.
- if (entry.getValue().getSlot() == null || entry.getValue().getSlot() == slot) {
+ if (entry.getValue().getSlotGroup().test(slot)) { // Paper - correctly test slot against group
iter.remove();
++removed;
}
diff --git a/src/test/java/io/papermc/paper/inventory/item/EquipmentSlotGroupTest.java b/src/test/java/io/papermc/paper/inventory/item/EquipmentSlotGroupTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
+++ b/src/test/java/io/papermc/paper/inventory/item/EquipmentSlotGroupTest.java
@@ -0,0 +0,0 @@
+package io.papermc.paper.inventory.item;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.List;
+import net.minecraft.world.entity.EquipmentSlot;
+import org.bukkit.craftbukkit.CraftEquipmentSlot;
+import org.bukkit.inventory.EquipmentSlotGroup;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.EnumSource;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+class EquipmentSlotGroupTest {
+
+ static List<EquipmentSlotGroup> apiValues() throws ReflectiveOperationException {
+ final List<EquipmentSlotGroup> apiValues = new ArrayList<>();
+ for (final Field field : EquipmentSlotGroup.class.getDeclaredFields()) {
+ if (!Modifier.isStatic(field.getModifiers()) || !Modifier.isFinal(field.getModifiers()) || !field.getType().equals(EquipmentSlotGroup.class)) {
+ continue;
+ }
+ apiValues.add((EquipmentSlotGroup) field.get(null));
+ }
+ if (apiValues.isEmpty()) {
+ throw new RuntimeException("Didn't find any api " + EquipmentSlotGroup.class.getSimpleName());
+ }
+ return apiValues;
+ }
+
+ @ParameterizedTest
+ @MethodSource("apiValues")
+ void testBukkitToNms(final EquipmentSlotGroup slotGroup) {
+ final net.minecraft.world.entity.EquipmentSlotGroup nmsGroup = CraftEquipmentSlot.getNMSGroup(slotGroup);
+ assertNotNull(nmsGroup, "No nms slot group found for " + slotGroup);
+ assertEquals(nmsGroup.getSerializedName(), slotGroup.toString(), "slot group name mismatch");
+ for (final EquipmentSlot slot : EquipmentSlot.values()) {
+ assertEquals(nmsGroup.test(slot), slotGroup.test(CraftEquipmentSlot.getSlot(slot)));
+ }
+ }
+
+ @ParameterizedTest
+ @EnumSource(net.minecraft.world.entity.EquipmentSlotGroup.class)
+ void testNmsToBukkit(final net.minecraft.world.entity.EquipmentSlotGroup slotGroup) {
+ final EquipmentSlotGroup apiGroup = CraftEquipmentSlot.getSlot(slotGroup);
+ assertNotNull(apiGroup, "No api slot group found for " + slotGroup);
+ assertEquals(apiGroup.toString(), slotGroup.getSerializedName(), "slot group name mismatch");
+ }
+}

View File

@@ -1,21 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com>
Date: Sat, 27 Apr 2024 21:51:58 +0200
Subject: [PATCH] Fix helmet damage reduction inconsistencies
Affect the falling stalactite damage type where the
reduction is not applied like in Vanilla
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -0,0 +0,0 @@ public class CraftEventFactory {
Map<DamageModifier, Function<? super Double, Double>> modifierFunctions = new EnumMap<>(DamageModifier.class);
modifiers.put(DamageModifier.BASE, rawDamage);
modifierFunctions.put(DamageModifier.BASE, CraftEventFactory.ZERO);
- if (source.is(DamageTypes.FALLING_BLOCK) || source.is(DamageTypes.FALLING_ANVIL)) {
+ if (source.is(DamageTypeTags.DAMAGES_HELMET)) { // Paper
modifiers.put(DamageModifier.HARD_HAT, hardHatModifier);
modifierFunctions.put(DamageModifier.HARD_HAT, hardHat);
}

View File

@@ -1,116 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sun, 12 May 2024 15:49:36 -0700
Subject: [PATCH] Fix issues with Recipe API
diff --git a/src/main/java/net/minecraft/world/item/crafting/ShapedRecipe.java b/src/main/java/net/minecraft/world/item/crafting/ShapedRecipe.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/item/crafting/ShapedRecipe.java
+++ b/src/main/java/net/minecraft/world/item/crafting/ShapedRecipe.java
@@ -0,0 +0,0 @@ public class ShapedRecipe extends io.papermc.paper.inventory.recipe.RecipeBookEx
char c = 'a';
for (Ingredient list : this.pattern.ingredients()) {
RecipeChoice choice = CraftRecipe.toBukkit(list);
- if (choice != null) {
+ if (choice != RecipeChoice.empty()) { // Paper
recipe.setIngredient(c, choice);
}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java
@@ -0,0 +0,0 @@ public interface CraftRecipe extends Recipe {
} else if (bukkit instanceof RecipeChoice.ExactChoice) {
stack = new Ingredient(((RecipeChoice.ExactChoice) bukkit).getChoices().stream().map((mat) -> new net.minecraft.world.item.crafting.Ingredient.ItemValue(CraftItemStack.asNMSCopy(mat))));
stack.exact = true;
+ // Paper start - support "empty" choices
+ } else if (bukkit == RecipeChoice.empty()) {
+ stack = Ingredient.EMPTY;
+ // Paper end
} else {
throw new IllegalArgumentException("Unknown recipe stack instance " + bukkit);
}
@@ -0,0 +0,0 @@ public interface CraftRecipe extends Recipe {
list.getItems();
if (list.itemStacks.length == 0) {
- return null;
+ return RecipeChoice.empty(); // Paper - null breaks API contracts
}
if (list.exact) {
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftSmithingTransformRecipe.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftSmithingTransformRecipe.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftSmithingTransformRecipe.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftSmithingTransformRecipe.java
@@ -0,0 +0,0 @@ public class CraftSmithingTransformRecipe extends SmithingTransformRecipe implem
public void addToCraftingManager() {
ItemStack result = this.getResult();
- MinecraftServer.getServer().getRecipeManager().addRecipe(new RecipeHolder<>(CraftNamespacedKey.toMinecraft(this.getKey()), new net.minecraft.world.item.crafting.SmithingTransformRecipe(this.toNMS(this.getTemplate(), true), this.toNMS(this.getBase(), true), this.toNMS(this.getAddition(), true), CraftItemStack.asNMSCopy(result), this.willCopyDataComponents()))); // Paper - Option to prevent data components copy
+ MinecraftServer.getServer().getRecipeManager().addRecipe(new RecipeHolder<>(CraftNamespacedKey.toMinecraft(this.getKey()), new net.minecraft.world.item.crafting.SmithingTransformRecipe(this.toNMS(this.getTemplate(), false), this.toNMS(this.getBase(), false), this.toNMS(this.getAddition(), false), CraftItemStack.asNMSCopy(result), this.willCopyDataComponents()))); // Paper - Option to prevent data components copy & support empty RecipeChoice
}
}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftSmithingTrimRecipe.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftSmithingTrimRecipe.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftSmithingTrimRecipe.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftSmithingTrimRecipe.java
@@ -0,0 +0,0 @@ public class CraftSmithingTrimRecipe extends SmithingTrimRecipe implements Craft
@Override
public void addToCraftingManager() {
- MinecraftServer.getServer().getRecipeManager().addRecipe(new RecipeHolder<>(CraftNamespacedKey.toMinecraft(this.getKey()), new net.minecraft.world.item.crafting.SmithingTrimRecipe(this.toNMS(this.getTemplate(), true), this.toNMS(this.getBase(), true), this.toNMS(this.getAddition(), true), this.willCopyDataComponents()))); // Paper - Option to prevent data components copy
+ MinecraftServer.getServer().getRecipeManager().addRecipe(new RecipeHolder<>(CraftNamespacedKey.toMinecraft(this.getKey()), new net.minecraft.world.item.crafting.SmithingTrimRecipe(this.toNMS(this.getTemplate(), false), this.toNMS(this.getBase(), false), this.toNMS(this.getAddition(), false), this.willCopyDataComponents()))); // Paper - Option to prevent data components copy & support empty RecipeChoice
}
}
diff --git a/src/test/java/io/papermc/paper/inventory/recipe/TestRecipeChoice.java b/src/test/java/io/papermc/paper/inventory/recipe/TestRecipeChoice.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
+++ b/src/test/java/io/papermc/paper/inventory/recipe/TestRecipeChoice.java
@@ -0,0 +0,0 @@
+package io.papermc.paper.inventory.recipe;
+
+import java.util.Iterator;
+import org.bukkit.Bukkit;
+import org.bukkit.inventory.Recipe;
+import org.bukkit.support.AbstractTestingBase;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class TestRecipeChoice extends AbstractTestingBase {
+
+ @Test
+ void testRecipeChoices() {
+ final Iterator<Recipe> iter = Bukkit.recipeIterator();
+ boolean foundRecipes = false;
+ while (iter.hasNext()) {
+ foundRecipes = true;
+ assertDoesNotThrow(iter::next, "Failed to convert a recipe to Bukkit recipe!");
+ }
+ assertTrue(foundRecipes, "No recipes found!");
+ }
+}
diff --git a/src/test/java/org/bukkit/support/DummyServer.java b/src/test/java/org/bukkit/support/DummyServer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/test/java/org/bukkit/support/DummyServer.java
+++ b/src/test/java/org/bukkit/support/DummyServer.java
@@ -0,0 +0,0 @@ public final class DummyServer {
when(instance.getTag(anyString(), any(org.bukkit.NamespacedKey.class), any())).thenAnswer(ignored -> new io.papermc.paper.util.EmptyTag());
// paper end - testing additions
+ // Paper start - add test for recipe conversion
+ when(instance.recipeIterator()).thenAnswer(ignored -> {
+ return com.google.common.collect.Iterators.transform(
+ AbstractTestingBase.DATA_PACK.getRecipeManager().byType.entries().iterator(),
+ input -> input.getValue().toBukkitRecipe());
+ });
+ // Paper end - add test for recipe conversion
+
Bukkit.setServer(instance);
} catch (Throwable t) {
throw new Error(t);

View File

@@ -1,21 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Thu, 30 May 2024 18:46:15 +0100
Subject: [PATCH] Fix sending disconnect packet in phases where it doesn't
exist
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/network/Connection.java
+++ b/src/main/java/net/minecraft/network/Connection.java
@@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
if (player != null) player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.ERRONEOUS_STATE; // Paper - Add API for quit reason
if (flag) {
Connection.LOGGER.debug("Failed to sent packet", throwable);
- if (this.getSending() == PacketFlow.CLIENTBOUND) {
+ boolean doesDisconnectExist = this.packetListener.protocol() != ConnectionProtocol.STATUS && this.packetListener.protocol() != ConnectionProtocol.HANDSHAKING; // Paper
+ if (this.getSending() == PacketFlow.CLIENTBOUND && doesDisconnectExist) { // Paper
Packet<?> packet = this.sendLoginDisconnect ? new ClientboundLoginDisconnectPacket(ichatmutablecomponent) : new ClientboundDisconnectPacket(ichatmutablecomponent);
this.send((Packet) packet, PacketSendListener.thenRun(() -> {

View File

@@ -1,22 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Fri, 26 Apr 2024 19:08:37 -0700
Subject: [PATCH] Fix shield disable inconsistency
In vanilla, if the damage source is tagged as a projectile,
it will not disable the shield if the attacker is holding
an axe item.
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 {
this.hurtCurrentlyUsedShield((float) -event.getDamage(DamageModifier.BLOCKING));
Entity entity = damagesource.getDirectEntity();
- if (entity instanceof LivingEntity && entity.distanceToSqr(this) <= (200.0D * 200.0D)) { // Paper - Improve boat collision performance
+ if (!damagesource.is(DamageTypeTags.IS_PROJECTILE) && entity instanceof LivingEntity && entity.distanceToSqr(this) <= (200.0D * 200.0D)) { // Paper - Improve boat collision performance
this.blockUsingShield((LivingEntity) entity);
}
}

View File

@@ -1,22 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: DungeonDev <dungeondevtn@gmail.com>
Date: Sun, 2 Jul 2023 02:34:54 +0100
Subject: [PATCH] Fix tripwire disarming not working as intended
Fixes MC-129055
diff --git a/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java b/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java
@@ -0,0 +0,0 @@ public class TripWireHookBlock extends Block {
BlockState iblockdata4 = aiblockdata[l];
if (iblockdata4 != null) {
+ if (world.getBlockState(blockposition2).is(Blocks.TRIPWIRE) || io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowTripwireDisarmingExploits) { // Paper - Fix tripwire disarming not working as intended
world.setBlock(blockposition2, (BlockState) iblockdata4.trySetValue(TripWireHookBlock.ATTACHED, flag4), 3);
- if (!world.getBlockState(blockposition2).isAir()) {
- ;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,135 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Tue, 27 Nov 2018 21:18:06 -0500
Subject: [PATCH] Handle Large Packets disconnecting client
If a players inventory is too big to send in a single packet,
split the inventory set into multiple packets instead.
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/network/Connection.java
+++ b/src/main/java/net/minecraft/network/Connection.java
@@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
}
public void exceptionCaught(ChannelHandlerContext channelhandlercontext, Throwable throwable) {
+ // Paper start - Handle large packets disconnecting client
+ if (throwable instanceof io.netty.handler.codec.EncoderException && throwable.getCause() instanceof PacketEncoder.PacketTooLargeException packetTooLargeException) {
+ final Packet<?> packet = packetTooLargeException.getPacket();
+ if (packet.packetTooLarge(this)) {
+ ProtocolSwapHandler.handleOutboundTerminalPacket(channelhandlercontext, packet);
+ return;
+ } else if (packet.isSkippable()) {
+ Connection.LOGGER.debug("Skipping packet due to errors", throwable.getCause());
+ ProtocolSwapHandler.handleOutboundTerminalPacket(channelhandlercontext, packet);
+ return;
+ } else {
+ throwable = throwable.getCause();
+ }
+ }
+ // Paper end - Handle large packets disconnecting client
if (throwable instanceof SkipPacketException) {
Connection.LOGGER.debug("Skipping packet due to errors", throwable.getCause());
} else {
diff --git a/src/main/java/net/minecraft/network/PacketEncoder.java b/src/main/java/net/minecraft/network/PacketEncoder.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/network/PacketEncoder.java
+++ b/src/main/java/net/minecraft/network/PacketEncoder.java
@@ -0,0 +0,0 @@ public class PacketEncoder<T extends PacketListener> extends MessageToByteEncode
throw var9;
} finally {
+ // Paper start - Handle large packets disconnecting client
+ int packetLength = byteBuf.readableBytes();
+ if (packetLength > MAX_PACKET_SIZE || (packetLength > MAX_FINAL_PACKET_SIZE && packet.hasLargePacketFallback())) {
+ throw new PacketTooLargeException(packet, packetLength);
+ }
+ // Paper end - Handle large packets disconnecting client
ProtocolSwapHandler.handleOutboundTerminalPacket(channelHandlerContext, packet);
}
}
+
+ // Paper start
+ // packet size is encoded into 3-byte varint
+ private static final int MAX_FINAL_PACKET_SIZE = (1 << 21) - 1;
+ // Vanilla Max size for the encoder (before compression)
+ private static final int MAX_PACKET_SIZE = 8388608;
+
+ public static class PacketTooLargeException extends RuntimeException {
+ private final Packet<?> packet;
+
+ PacketTooLargeException(Packet<?> packet, int packetLength) {
+ super("PacketTooLarge - " + packet.getClass().getSimpleName() + " is " + packetLength + ". Max is " + MAX_PACKET_SIZE);
+ this.packet = packet;
+ }
+
+ public Packet<?> getPacket() {
+ return this.packet;
+ }
+ }
+ // Paper end
}
diff --git a/src/main/java/net/minecraft/network/protocol/Packet.java b/src/main/java/net/minecraft/network/protocol/Packet.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/network/protocol/Packet.java
+++ b/src/main/java/net/minecraft/network/protocol/Packet.java
@@ -0,0 +0,0 @@ public interface Packet<T extends PacketListener> {
void handle(T listener);
+ // Paper start
+ default boolean hasLargePacketFallback() {
+ return false;
+ }
+
+ /**
+ * override {@link #hasLargePacketFallback()} to return true when overriding in subclasses
+ */
+ default boolean packetTooLarge(net.minecraft.network.Connection manager) {
+ return false;
+ }
+ // Paper end
+
default boolean isSkippable() {
return false;
}
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java
@@ -0,0 +0,0 @@ public class ClientboundContainerSetContentPacket implements Packet<ClientGamePa
this.carriedItem = ItemStack.OPTIONAL_STREAM_CODEC.decode(buf);
}
+ // Paper start - Handle large packets disconnecting client
+ @Override
+ public boolean hasLargePacketFallback() {
+ return true;
+ }
+
+ @Override
+ public boolean packetTooLarge(net.minecraft.network.Connection manager) {
+ for (int i = 0 ; i < this.items.size() ; i++) {
+ manager.send(new ClientboundContainerSetSlotPacket(this.containerId, this.stateId, i, this.items.get(i)));
+ }
+ return true;
+ }
+ // Paper end - Handle large packets disconnecting client
+
private void write(RegistryFriendlyByteBuf buf) {
buf.writeByte(this.containerId);
buf.writeVarInt(this.stateId);
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
@@ -0,0 +0,0 @@ public class ClientboundLevelChunkPacketData {
throw new RuntimeException("Can't read heightmap in packet for [" + x + ", " + z + "]");
} else {
int i = buf.readVarInt();
- if (i > 2097152) {
+ if (i > 2097152) { // Paper - diff on change - if this changes, update PacketEncoder
throw new RuntimeException("Chunk Packet trying to allocate too much memory on read.");
} else {
this.buffer = new byte[i];

View File

@@ -1,73 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: SoSeDiK <mrsosedik@gmail.com>
Date: Wed, 1 May 2024 08:22:13 +0300
Subject: [PATCH] More Chest Block API
== AT ==
public net.minecraft.world.level.block.ChestBlock isBlockedChestByBlock(Lnet/minecraft/world/level/BlockGetter;Lnet/minecraft/core/BlockPos;)Z
diff --git a/src/main/java/net/minecraft/world/level/block/EnderChestBlock.java b/src/main/java/net/minecraft/world/level/block/EnderChestBlock.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/EnderChestBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/EnderChestBlock.java
@@ -0,0 +0,0 @@ public class EnderChestBlock extends AbstractChestBlock<EnderChestBlockEntity> i
BlockEntity blockEntity = world.getBlockEntity(pos);
if (playerEnderChestContainer != null && blockEntity instanceof EnderChestBlockEntity) {
BlockPos blockPos = pos.above();
- if (world.getBlockState(blockPos).isRedstoneConductor(world, blockPos)) {
+ if (world.getBlockState(blockPos).isRedstoneConductor(world, blockPos)) { // Paper - diff on change; make sure that EnderChest#isBlocked uses the same logic
return InteractionResult.sidedSuccess(world.isClientSide);
} else if (world.isClientSide) {
return InteractionResult.SUCCESS;
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java
@@ -0,0 +0,0 @@ public class CraftChest extends CraftLootable<ChestBlockEntity> implements Chest
return getTileEntity().openersCounter.opened;
}
// Paper end - More Lidded Block API
+
+ // Paper start - More Chest Block API
+ @Override
+ public boolean isBlocked() {
+ // Method mimics vanilla logic in ChestBlock and DoubleBlockCombiner when trying to open chest's container
+ if (!isPlaced()) {
+ return false;
+ }
+ net.minecraft.world.level.LevelAccessor world = getWorldHandle();
+ if (ChestBlock.isChestBlockedAt(world, getPosition())) {
+ return true;
+ }
+ if (ChestBlock.getBlockType(this.data) == net.minecraft.world.level.block.DoubleBlockCombiner.BlockType.SINGLE) {
+ return false;
+ }
+ net.minecraft.core.Direction direction = ChestBlock.getConnectedDirection(this.data);
+ net.minecraft.core.BlockPos neighbourBlockPos = getPosition().relative(direction);
+ BlockState neighbourBlockState = world.getBlockStateIfLoaded(neighbourBlockPos);
+ return neighbourBlockState != null
+ && neighbourBlockState.is(this.data.getBlock())
+ && ChestBlock.getBlockType(neighbourBlockState) != net.minecraft.world.level.block.DoubleBlockCombiner.BlockType.SINGLE
+ && ChestBlock.getConnectedDirection(neighbourBlockState) == direction.getOpposite()
+ && ChestBlock.isChestBlockedAt(world, neighbourBlockPos);
+ }
+ // Paper end - More Chest Block API
}
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java b/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java
@@ -0,0 +0,0 @@ public class CraftEnderChest extends CraftBlockEntityState<EnderChestBlockEntity
return getTileEntity().openersCounter.opened;
}
// Paper end - More Lidded Block API
+
+ // Paper start - More Chest Block API
+ @Override
+ public boolean isBlocked() {
+ // Uses the same logic as EnderChestBlock's check for opening container
+ final net.minecraft.core.BlockPos abovePos = this.getPosition().above();
+ return this.isPlaced() && this.getWorldHandle().getBlockState(abovePos).isRedstoneConductor(this.getWorldHandle(), abovePos);
+ }
+ // Paper end - More Chest Block API
}

View File

@@ -1,24 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sun, 12 May 2024 21:57:23 -0700
Subject: [PATCH] Prevent NPE if hooked entity was cleared
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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java
@@ -0,0 +0,0 @@ public class FishingHook extends Projectile {
if (playerFishEvent.isCancelled()) {
return 0;
}
+ if (this.hookedIn != null) { // Paper - re-check to see if there is a hooked entity
// CraftBukkit end
this.pullEntity(this.hookedIn);
CriteriaTriggers.FISHING_ROD_HOOKED.trigger((ServerPlayer) entityhuman, usedItem, this, Collections.emptyList());
this.level().broadcastEntityEvent(this, (byte) 31);
i = this.hookedIn instanceof ItemEntity ? 3 : 5;
+ } // Paper - re-check to see if there is a hooked entity
} else if (this.nibble > 0) {
LootParams lootparams = (new LootParams.Builder((ServerLevel) this.level())).withParameter(LootContextParams.ORIGIN, this.position()).withParameter(LootContextParams.TOOL, usedItem).withParameter(LootContextParams.THIS_ENTITY, this).withLuck((float) this.luck + entityhuman.getLuck()).create(LootContextParamSets.FISHING);
LootTable loottable = this.level().getServer().reloadableRegistries().getLootTable(BuiltInLootTables.FISHING);

View File

@@ -1,228 +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
Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
diff --git a/src/main/java/io/papermc/paper/util/DataSanitizationUtil.java b/src/main/java/io/papermc/paper/util/DataSanitizationUtil.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
+++ b/src/main/java/io/papermc/paper/util/DataSanitizationUtil.java
@@ -0,0 +0,0 @@
+package io.papermc.paper.util;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.UnaryOperator;
+import net.minecraft.network.RegistryFriendlyByteBuf;
+import net.minecraft.network.codec.StreamCodec;
+import net.minecraft.world.item.ItemStack;
+import net.minecraft.world.item.Items;
+import net.minecraft.world.item.component.BundleContents;
+import net.minecraft.world.item.component.ChargedProjectiles;
+import net.minecraft.world.item.component.ItemContainerContents;
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.framework.qual.DefaultQualifier;
+
+@DefaultQualifier(NonNull.class)
+public final class DataSanitizationUtil {
+
+ private static final ThreadLocal<DataSanitizer> DATA_SANITIZER = ThreadLocal.withInitial(DataSanitizer::new);
+
+ public static DataSanitizer start(final boolean sanitize) {
+ final DataSanitizer sanitizer = DATA_SANITIZER.get();
+ if (sanitize) {
+ sanitizer.start();
+ }
+ return sanitizer;
+ }
+
+ public static final StreamCodec<RegistryFriendlyByteBuf, ChargedProjectiles> CHARGED_PROJECTILES = codec(ChargedProjectiles.STREAM_CODEC, DataSanitizationUtil::sanitizeChargedProjectiles);
+ public static final StreamCodec<RegistryFriendlyByteBuf, BundleContents> BUNDLE_CONTENTS = codec(BundleContents.STREAM_CODEC, DataSanitizationUtil::sanitizeBundleContents);
+ public static final StreamCodec<RegistryFriendlyByteBuf, ItemContainerContents> CONTAINER = codec(ItemContainerContents.STREAM_CODEC, contents -> ItemContainerContents.EMPTY);
+
+ private static ChargedProjectiles sanitizeChargedProjectiles(final ChargedProjectiles projectiles) {
+ if (projectiles.isEmpty()) {
+ return projectiles;
+ }
+ final List<ItemStack> items = projectiles.getItems();
+ final List<ItemStack> sanitized = new ArrayList<>();
+ for (int i = 0; i < Math.min(items.size(), 3); i++) {
+ // we want to preserve item type as vanilla client can change visuals based on type
+ sanitized.add(new ItemStack(items.get(i).getItemHolder()));
+ }
+ return ChargedProjectiles.of(sanitized);
+ }
+
+ private static BundleContents sanitizeBundleContents(final BundleContents contents) {
+ // Bundles change their texture based on their fullness.
+ int sizeUsed = 0;
+ for (final ItemStack item : contents.items()) {
+ final int scale = 64 / item.getMaxStackSize();
+ sizeUsed += scale * item.getCount();
+ }
+ // Now we add a single fake item that uses the same amount of slots as all other items.
+ final List<ItemStack> items = new ArrayList<>();
+ items.add(new ItemStack(Items.PAPER, sizeUsed));
+ return new BundleContents(items);
+ }
+
+ private static <B, A> StreamCodec<B, A> codec(final StreamCodec<B, A> delegate, final UnaryOperator<A> sanitizer) {
+ return new DataSanitizationCodec<>(delegate, sanitizer);
+ }
+
+ private record DataSanitizationCodec<B, A>(StreamCodec<B, A> delegate, UnaryOperator<A> sanitizer) implements StreamCodec<B, A> {
+
+ @Override
+ public @NonNull A decode(final @NonNull B buf) {
+ return this.delegate.decode(buf);
+ }
+
+ @Override
+ public void encode(final @NonNull B buf, final @NonNull A value) {
+ if (!DATA_SANITIZER.get().value().get()) {
+ this.delegate.encode(buf, value);
+ } else {
+ this.delegate.encode(buf, this.sanitizer.apply(value));
+ }
+ }
+ }
+
+ public record DataSanitizer(AtomicBoolean value) implements AutoCloseable {
+
+ public DataSanitizer() {
+ this(new AtomicBoolean(false));
+ }
+
+ public void start() {
+ this.value.compareAndSet(false, true);
+ }
+
+ @Override
+ public void close() {
+ this.value.compareAndSet(true, false);
+ }
+ }
+
+ private DataSanitizationUtil() {
+ }
+
+}
diff --git a/src/main/java/net/minecraft/core/component/DataComponents.java b/src/main/java/net/minecraft/core/component/DataComponents.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/core/component/DataComponents.java
+++ b/src/main/java/net/minecraft/core/component/DataComponents.java
@@ -0,0 +0,0 @@ public class DataComponents {
"map_post_processing", builder -> builder.networkSynchronized(MapPostProcessing.STREAM_CODEC)
);
public static final DataComponentType<ChargedProjectiles> CHARGED_PROJECTILES = register(
- "charged_projectiles", builder -> builder.persistent(ChargedProjectiles.CODEC).networkSynchronized(ChargedProjectiles.STREAM_CODEC).cacheEncoding()
+ "charged_projectiles", builder -> builder.persistent(ChargedProjectiles.CODEC).networkSynchronized(io.papermc.paper.util.DataSanitizationUtil.CHARGED_PROJECTILES).cacheEncoding() // Paper - sanitize charged projectiles
);
public static final DataComponentType<BundleContents> BUNDLE_CONTENTS = register(
- "bundle_contents", builder -> builder.persistent(BundleContents.CODEC).networkSynchronized(BundleContents.STREAM_CODEC).cacheEncoding()
+ "bundle_contents", builder -> builder.persistent(BundleContents.CODEC).networkSynchronized(io.papermc.paper.util.DataSanitizationUtil.BUNDLE_CONTENTS).cacheEncoding() // Paper - sanitize bundle contents
);
public static final DataComponentType<PotionContents> POTION_CONTENTS = register(
"potion_contents", builder -> builder.persistent(PotionContents.CODEC).networkSynchronized(PotionContents.STREAM_CODEC).cacheEncoding()
@@ -0,0 +0,0 @@ public class DataComponents {
"pot_decorations", builder -> builder.persistent(PotDecorations.CODEC).networkSynchronized(PotDecorations.STREAM_CODEC).cacheEncoding()
);
public static final DataComponentType<ItemContainerContents> CONTAINER = register(
- "container", builder -> builder.persistent(ItemContainerContents.CODEC).networkSynchronized(ItemContainerContents.STREAM_CODEC).cacheEncoding()
+ "container", builder -> builder.persistent(ItemContainerContents.CODEC).networkSynchronized(io.papermc.paper.util.DataSanitizationUtil.CONTAINER).cacheEncoding() // Paper - sanitize container contents
);
public static final DataComponentType<BlockItemStateProperties> BLOCK_STATE = register(
"block_state", builder -> builder.persistent(BlockItemStateProperties.CODEC).networkSynchronized(BlockItemStateProperties.STREAM_CODEC).cacheEncoding()
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetEntityDataPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetEntityDataPacket.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetEntityDataPacket.java
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetEntityDataPacket.java
@@ -0,0 +0,0 @@ public record ClientboundSetEntityDataPacket(int id, List<SynchedEntityData.Data
}
private static void pack(List<SynchedEntityData.DataValue<?>> trackedValues, RegistryFriendlyByteBuf buf) {
+ try (var ignored = io.papermc.paper.util.DataSanitizationUtil.start(true)) { // Paper - data sanitization
for (SynchedEntityData.DataValue<?> dataValue : trackedValues) {
dataValue.write(buf);
}
+ } // Paper - data sanitization
buf.writeByte(255);
}
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetEquipmentPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetEquipmentPacket.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetEquipmentPacket.java
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetEquipmentPacket.java
@@ -0,0 +0,0 @@ public class ClientboundSetEquipmentPacket implements Packet<ClientGamePacketLis
private final List<Pair<EquipmentSlot, ItemStack>> slots;
public ClientboundSetEquipmentPacket(int id, List<Pair<EquipmentSlot, ItemStack>> equipmentList) {
+ // Paper start - data sanitization
+ this(id, equipmentList, false);
+ }
+ private boolean sanitize = false;
+ public ClientboundSetEquipmentPacket(int id, List<Pair<EquipmentSlot, ItemStack>> equipmentList, boolean sanitize) {
+ this.sanitize = sanitize;
+ // Paper end - data sanitization
this.entity = id;
this.slots = equipmentList;
}
@@ -0,0 +0,0 @@ public class ClientboundSetEquipmentPacket implements Packet<ClientGamePacketLis
buf.writeVarInt(this.entity);
int i = this.slots.size();
+ try (var ignored = io.papermc.paper.util.DataSanitizationUtil.start(this.sanitize)) { // Paper - data sanitization
for (int j = 0; j < i; j++) {
Pair<EquipmentSlot, ItemStack> pair = this.slots.get(j);
EquipmentSlot equipmentSlot = pair.getFirst();
@@ -0,0 +0,0 @@ public class ClientboundSetEquipmentPacket implements Packet<ClientGamePacketLis
buf.writeByte(bl ? k | -128 : k);
ItemStack.OPTIONAL_STREAM_CODEC.encode(buf, pair.getSecond());
}
+ } // Paper - data sanitization
}
@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 {
}
if (!list.isEmpty()) {
- sender.accept(new ClientboundSetEquipmentPacket(this.entity.getId(), list));
+ sender.accept(new ClientboundSetEquipmentPacket(this.entity.getId(), list, true)); // Paper - data sanitization
}
((LivingEntity) this.entity).detectEquipmentUpdatesPublic(); // CraftBukkit - SPIGOT-3789: sync again immediately after sending
}
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
entity.refreshEntityData(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())));
+ 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()), true)); // Paper - sanitize
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 {
}
});
- ((ServerLevel) this.level()).getChunkSource().broadcast(this, new ClientboundSetEquipmentPacket(this.getId(), list));
+ ((ServerLevel) this.level()).getChunkSource().broadcast(this, new ClientboundSetEquipmentPacket(this.getId(), list, true)); // Paper - data sanitization
}
private ItemStack getLastArmorItem(EquipmentSlot slot) {

View File

@@ -1,24 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Nassim Jahnke <nassim@njahnke.dev>
Date: Thu, 9 May 2024 15:11:34 +0200
Subject: [PATCH] Print data component type on encoding error
diff --git a/src/main/java/net/minecraft/core/component/DataComponentPatch.java b/src/main/java/net/minecraft/core/component/DataComponentPatch.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/core/component/DataComponentPatch.java
+++ b/src/main/java/net/minecraft/core/component/DataComponentPatch.java
@@ -0,0 +0,0 @@ public final class DataComponentPatch {
}
private static <T> void encodeComponent(RegistryFriendlyByteBuf buf, DataComponentType<T> type, Object value) {
+ // Paper start - codec errors of random anonymous classes are useless
+ try {
type.streamCodec().encode(buf, (T) value); // CraftBukkit - decompile error
+ } catch (final Exception e) {
+ throw new RuntimeException("Error encoding component " + type, e);
+ }
+ // Paper end - codec errors of random anonymous classes are useless
}
};
private static final String REMOVED_PREFIX = "!";

View File

@@ -1,169 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Wed, 13 May 2020 23:01:26 -0400
Subject: [PATCH] Protect Bedrock and End Portal/Frames from being destroyed
This fixes exploits that let players destroy bedrock by Pistons, explosions
and Mushrooom/Tree generation.
These blocks are designed to not be broken except by creative players/commands.
So protect them from a multitude of methods of destroying them.
A config is provided if you rather let players use these exploits, and let
them destroy the worlds End Portals and get on top of the nether easy.
diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/Explosion.java
+++ b/src/main/java/net/minecraft/world/level/Explosion.java
@@ -0,0 +0,0 @@ public class Explosion {
for (float f1 = 0.3F; f > 0.0F; f -= 0.22500001F) {
BlockPos blockposition = BlockPos.containing(d4, d5, d6);
BlockState iblockdata = this.level.getBlockState(blockposition);
+ if (!iblockdata.isDestroyable()) continue; // Paper - Protect Bedrock and End Portal/Frames from being destroyed
FluidState fluid = iblockdata.getFluidState(); // Paper - Perf: Optimize call to getFluid for explosions
if (!this.level.isInWorldBounds(blockposition)) {
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
public boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth) {
// CraftBukkit start - tree generation
if (this.captureTreeGeneration) {
+ // Paper start - Protect Bedrock and End Portal/Frames from being destroyed
+ BlockState type = getBlockState(pos);
+ if (!type.isDestroyable()) return false;
+ // Paper end - Protect Bedrock and End Portal/Frames from being destroyed
CraftBlockState blockstate = this.capturedBlockStates.get(pos);
if (blockstate == null) {
blockstate = CapturedBlockState.getTreeBlockState(this, pos, flags);
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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/Block.java
+++ b/src/main/java/net/minecraft/world/level/block/Block.java
@@ -0,0 +0,0 @@ public class Block extends BlockBehaviour implements ItemLike {
protected final StateDefinition<Block, BlockState> stateDefinition;
private BlockState defaultBlockState;
// Paper start
+ public final boolean isDestroyable() {
+ return io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowPermanentBlockBreakExploits ||
+ this != Blocks.BEDROCK &&
+ this != Blocks.END_PORTAL_FRAME &&
+ this != Blocks.END_PORTAL &&
+ this != Blocks.END_GATEWAY &&
+ this != Blocks.COMMAND_BLOCK &&
+ this != Blocks.REPEATING_COMMAND_BLOCK &&
+ this != Blocks.CHAIN_COMMAND_BLOCK &&
+ this != Blocks.BARRIER &&
+ this != Blocks.STRUCTURE_BLOCK &&
+ this != Blocks.JIGSAW;
+ }
public co.aikar.timings.Timing timing;
public co.aikar.timings.Timing getTiming() {
if (timing == null) {
diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java
@@ -0,0 +0,0 @@ public class PistonBaseBlock extends DirectionalBlock {
@Override
protected boolean triggerEvent(BlockState state, Level world, BlockPos pos, int type, int data) {
Direction enumdirection = (Direction) state.getValue(PistonBaseBlock.FACING);
+ // Paper start - Protect Bedrock and End Portal/Frames from being destroyed; prevent retracting when we're facing the wrong way (we were replaced before retraction could occur)
+ Direction directionQueuedAs = Direction.from3DDataValue(data & 7); // Paper - copied from below
+ if (!io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowPermanentBlockBreakExploits && enumdirection != directionQueuedAs) {
+ return false;
+ }
+ // Paper end - Protect Bedrock and End Portal/Frames from being destroyed
BlockState iblockdata1 = (BlockState) state.setValue(PistonBaseBlock.EXTENDED, true);
if (!world.isClientSide) {
@@ -0,0 +0,0 @@ public class PistonBaseBlock extends DirectionalBlock {
}
// Paper end - Fix sticky pistons and BlockPistonRetractEvent
world.setBlock(pos, iblockdata2, 20);
- world.setBlockEntity(MovingPistonBlock.newMovingBlockEntity(pos, iblockdata2, (BlockState) this.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.from3DDataValue(data & 7)), enumdirection, false, true));
+ world.setBlockEntity(MovingPistonBlock.newMovingBlockEntity(pos, iblockdata2, (BlockState) this.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.from3DDataValue(data & 7)), enumdirection, false, true)); // Paper - Protect Bedrock and End Portal/Frames from being destroyed; diff on change
world.blockUpdated(pos, iblockdata2.getBlock());
iblockdata2.updateNeighbourShapes(world, pos, 2);
if (this.isSticky) {
@@ -0,0 +0,0 @@ public class PistonBaseBlock extends DirectionalBlock {
}
}
} else {
- world.removeBlock(pos.relative(enumdirection), false);
+ // Paper start - Protect Bedrock and End Portal/Frames from being destroyed; fix headless pistons breaking blocks
+ BlockPos headPos = pos.relative(enumdirection);
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowPermanentBlockBreakExploits || world.getBlockState(headPos) == Blocks.PISTON_HEAD.defaultBlockState().setValue(FACING, enumdirection)) { // double check to make sure we're not a headless piston.
+ world.removeBlock(headPos, false);
+ } else {
+ ((ServerLevel) world).getChunkSource().blockChanged(headPos); // ... fix client desync
+ }
+ // Paper end - Protect Bedrock and End Portal/Frames from being destroyed
}
world.playSound((Player) null, pos, SoundEvents.PISTON_CONTRACT, SoundSource.BLOCKS, 0.5F, world.random.nextFloat() * 0.15F + 0.6F);
diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
@@ -0,0 +0,0 @@ public abstract class BlockBehaviour implements FeatureElement {
}
protected void onExplosionHit(BlockState state, Level world, BlockPos pos, Explosion explosion, BiConsumer<ItemStack, BlockPos> stackMerger) {
- if (!state.isAir() && explosion.getBlockInteraction() != Explosion.BlockInteraction.TRIGGER_BLOCK) {
+ if (!state.isAir() && explosion.getBlockInteraction() != Explosion.BlockInteraction.TRIGGER_BLOCK && state.isDestroyable()) { // Paper - Protect Bedrock and End Portal/Frames from being destroyed
Block block = state.getBlock();
boolean flag = explosion.getIndirectSourceEntity() instanceof Player;
@@ -0,0 +0,0 @@ public abstract class BlockBehaviour implements FeatureElement {
}
protected boolean canBeReplaced(BlockState state, BlockPlaceContext context) {
- return state.canBeReplaced() && (context.getItemInHand().isEmpty() || !context.getItemInHand().is(this.asItem()));
+ return state.canBeReplaced() && (context.getItemInHand().isEmpty() || !context.getItemInHand().is(this.asItem())) && (state.isDestroyable() || (context.getPlayer() != null && context.getPlayer().getAbilities().instabuild)); // Paper - Protect Bedrock and End Portal/Frames from being destroyed
}
protected boolean canBeReplaced(BlockState state, Fluid fluid) {
@@ -0,0 +0,0 @@ public abstract class BlockBehaviour implements FeatureElement {
return this.legacySolid;
}
+ // Paper start - Protect Bedrock and End Portal/Frames from being destroyed
+ public final boolean isDestroyable() {
+ return getBlock().isDestroyable();
+ }
+ // Paper end - Protect Bedrock and End Portal/Frames from being destroyed
+
public boolean isValidSpawn(BlockGetter world, BlockPos pos, EntityType<?> type) {
return this.getBlock().properties.isValidSpawn.test(this.asState(), world, pos, type);
}
@@ -0,0 +0,0 @@ public abstract class BlockBehaviour implements FeatureElement {
}
public PushReaction getPistonPushReaction() {
- return this.pushReaction;
+ return !this.isDestroyable() ? PushReaction.BLOCK : this.pushReaction; // Paper - Protect Bedrock and End Portal/Frames from being destroyed
}
public boolean isSolidRender(BlockGetter world, BlockPos pos) {
diff --git a/src/main/java/net/minecraft/world/level/portal/PortalForcer.java b/src/main/java/net/minecraft/world/level/portal/PortalForcer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/portal/PortalForcer.java
+++ b/src/main/java/net/minecraft/world/level/portal/PortalForcer.java
@@ -0,0 +0,0 @@ public class PortalForcer {
for (int j = -1; j < 3; ++j) {
for (int k = -1; k < 4; ++k) {
temp.setWithOffset(pos, portalDirection.getStepX() * j + enumdirection1.getStepX() * distanceOrthogonalToPortal, k, portalDirection.getStepZ() * j + enumdirection1.getStepZ() * distanceOrthogonalToPortal);
+ // Paper start - Protect Bedrock and End Portal/Frames from being destroyed
+ if (!io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowPermanentBlockBreakExploits) {
+ if (!this.level.getBlockState(temp).isDestroyable()) {
+ return false;
+ }
+ }
+ // Paper end - Protect Bedrock and End Portal/Frames from being destroyed
if (k < 0 && !this.level.getBlockState(temp).isSolid()) {
return false;
}

View File

@@ -1,34 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sat, 27 Apr 2024 09:44:53 -0700
Subject: [PATCH] Revert to vanilla handling of LivingEntity#actuallyHurt
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 {
}
// CraftBukkit start
- protected boolean actuallyHurt(final DamageSource damagesource, float f) { // void -> boolean, add final
+ protected boolean actuallyHurt(final DamageSource damagesource, float f) { // void -> boolean, add final // Paper - return false ONLY if event cancelled
if (!this.isInvulnerableTo(damagesource)) {
final boolean human = this instanceof net.minecraft.world.entity.player.Player;
float originalDamage = f;
@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable {
return true;
} else {
- return originalDamage > 0;
+ return true; // Paper - return false ONLY if event was cancelled
}
// CraftBukkit end
}
}
- return false; // CraftBukkit
+ return true; // CraftBukkit // Paper - return false ONLY if event was cancelled
}
public CombatTracker getCombatTracker() {

View File

@@ -1,63 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Mon, 29 Jun 2020 03:26:17 -0400
Subject: [PATCH] Support old UUID format for NBT
We have stored UUID in plenty of places that did not get DFU'd
So just look for old format and load it if it exists.
diff --git a/src/main/java/net/minecraft/nbt/CompoundTag.java b/src/main/java/net/minecraft/nbt/CompoundTag.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/nbt/CompoundTag.java
+++ b/src/main/java/net/minecraft/nbt/CompoundTag.java
@@ -0,0 +0,0 @@ public class CompoundTag implements Tag {
}
public void putUUID(String key, UUID value) {
+ // Paper start - Support old UUID format
+ if (this.contains(key + "Most", net.minecraft.nbt.Tag.TAG_ANY_NUMERIC) && this.contains(key + "Least", net.minecraft.nbt.Tag.TAG_ANY_NUMERIC)) {
+ this.tags.remove(key + "Most");
+ this.tags.remove(key + "Least");
+ }
+ // Paper end - Support old UUID format
this.tags.put(key, NbtUtils.createUUID(value));
}
@@ -0,0 +0,0 @@ public class CompoundTag implements Tag {
* You must use {@link #hasUUID(String)} before or else it <b>will</b> throw an NPE.
*/
public UUID getUUID(String key) {
+ // Paper start - Support old UUID format
+ if (!contains(key, 11) && this.contains(key + "Most", net.minecraft.nbt.Tag.TAG_ANY_NUMERIC) && this.contains(key + "Least", net.minecraft.nbt.Tag.TAG_ANY_NUMERIC)) {
+ return new UUID(this.getLong(key + "Most"), this.getLong(key + "Least"));
+ }
+ // Paper end - Support old UUID format
return NbtUtils.loadUUID(this.get(key));
}
public boolean hasUUID(String key) {
+ // Paper start - Support old UUID format
+ if (this.contains(key + "Most", net.minecraft.nbt.Tag.TAG_ANY_NUMERIC) && this.contains(key + "Least", net.minecraft.nbt.Tag.TAG_ANY_NUMERIC)) {
+ return true;
+ }
+ // Paper end - Support old UUID format
Tag tag = this.get(key);
return tag != null && tag.getType() == IntArrayTag.TYPE && ((IntArrayTag)tag).getAsIntArray().length == 4;
}
diff --git a/src/main/java/net/minecraft/world/item/component/ResolvableProfile.java b/src/main/java/net/minecraft/world/item/component/ResolvableProfile.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/item/component/ResolvableProfile.java
+++ b/src/main/java/net/minecraft/world/item/component/ResolvableProfile.java
@@ -0,0 +0,0 @@ public record ResolvableProfile(Optional<String> name, Optional<UUID> id, Proper
instance -> instance.group(
ExtraCodecs.PLAYER_NAME.optionalFieldOf("name").forGetter(ResolvableProfile::name),
UUIDUtil.CODEC.optionalFieldOf("id").forGetter(ResolvableProfile::id),
+ UUIDUtil.STRING_CODEC.lenientOptionalFieldOf("Id").forGetter($ -> Optional.empty()), // Paper
ExtraCodecs.PROPERTY_MAP.optionalFieldOf("properties", new PropertyMap()).forGetter(ResolvableProfile::properties)
)
- .apply(instance, ResolvableProfile::new)
+ .apply(instance, (s, uuid, uuid2, propertyMap) -> new ResolvableProfile(s, uuid2.or(() -> uuid), propertyMap)) // Paper
);
public static final Codec<ResolvableProfile> CODEC = Codec.withAlternative(
FULL_CODEC, ExtraCodecs.PLAYER_NAME, name -> new ResolvableProfile(Optional.of(name), Optional.empty(), new PropertyMap())

View File

@@ -1,804 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Mon, 10 Jul 2023 16:10:15 -0700
Subject: [PATCH] improve checking handled tags in itemmeta
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
@@ -0,0 +0,0 @@ public final class CraftItemStack extends ItemStack {
} else if (this.handle == null) {
this.handle = new net.minecraft.world.item.ItemStack(CraftItemType.bukkitToMinecraft(type), 1);
} else {
+ final Material oldType = CraftMagicNumbers.getMaterial(this.handle.getItem()); // Paper
this.handle.setItem(CraftItemType.bukkitToMinecraft(type));
if (this.hasItemMeta()) {
// This will create the appropriate item meta, which will contain all the data we intend to keep
- CraftItemStack.setItemMeta(this.handle, CraftItemStack.getItemMeta(this.handle));
+ this.adjustTagForItemMeta(oldType); // Paper
}
}
this.setData(null);
@@ -0,0 +0,0 @@ public final class CraftItemStack extends ItemStack {
public ItemMeta getItemMeta() {
return CraftItemStack.getItemMeta(this.handle);
}
+ // Paper start - improve handled tags on type change
+ public void adjustTagForItemMeta(final Material oldType) {
+ final CraftMetaItem oldMeta = (CraftMetaItem) CraftItemFactory.instance().getItemMeta(oldType);
+ final ItemMeta newMeta;
+ if (oldMeta == null) {
+ newMeta = getItemMeta(this.handle);
+ } else {
+ final java.util.Set<net.minecraft.core.component.DataComponentType<?>> extraHandledDcts = new java.util.HashSet<>(CraftMetaItem.getTopLevelHandledDcts(oldMeta.getClass()));
+ newMeta = getItemMeta(this.handle, CraftItemStack.getType(this.handle), extraHandledDcts);
+ }
+ this.setItemMeta(newMeta);
+ }
+ // Paper end - improve handled tags on type change
// Paper start
public static void applyMetaToItem(net.minecraft.world.item.ItemStack itemStack, ItemMeta itemMeta) {
final CraftMetaItem.Applicator tag = new CraftMetaItem.Applicator();
@@ -0,0 +0,0 @@ public final class CraftItemStack extends ItemStack {
}
public static ItemMeta getItemMeta(net.minecraft.world.item.ItemStack item, Material material) {
// Paper end
+ // Paper start - handled tags on type change
+ return getItemMeta(item, material, null);
+ }
+ public static ItemMeta getItemMeta(net.minecraft.world.item.ItemStack item, Material material, final java.util.Set<net.minecraft.core.component.DataComponentType<?>> extraHandledDcts) {
+ // Paper end - handled tags on type change
if (!CraftItemStack.hasItemMeta(item)) {
return CraftItemFactory.instance().getItemMeta(material); // Paper
}
switch (material) { // Paper
case WRITTEN_BOOK:
- return new CraftMetaBookSigned(item.getComponentsPatch());
+ return new CraftMetaBookSigned(item.getComponentsPatch(), extraHandledDcts); // Paper
case WRITABLE_BOOK:
- return new CraftMetaBook(item.getComponentsPatch());
+ return new CraftMetaBook(item.getComponentsPatch(), extraHandledDcts); // Paper
case CREEPER_HEAD:
case CREEPER_WALL_HEAD:
case DRAGON_HEAD:
@@ -0,0 +0,0 @@ public final class CraftItemStack extends ItemStack {
case WITHER_SKELETON_WALL_SKULL:
case ZOMBIE_HEAD:
case ZOMBIE_WALL_HEAD:
- return new CraftMetaSkull(item.getComponentsPatch());
+ return new CraftMetaSkull(item.getComponentsPatch(), extraHandledDcts); // Paper
case CHAINMAIL_HELMET:
case CHAINMAIL_CHESTPLATE:
case CHAINMAIL_LEGGINGS:
@@ -0,0 +0,0 @@ public final class CraftItemStack extends ItemStack {
case NETHERITE_LEGGINGS:
case NETHERITE_BOOTS:
case TURTLE_HELMET:
- return new CraftMetaArmor(item.getComponentsPatch());
+ return new CraftMetaArmor(item.getComponentsPatch(), extraHandledDcts); // Paper
case LEATHER_HELMET:
case LEATHER_CHESTPLATE:
case LEATHER_LEGGINGS:
case LEATHER_BOOTS:
case WOLF_ARMOR:
- return new CraftMetaColorableArmor(item.getComponentsPatch());
+ return new CraftMetaColorableArmor(item.getComponentsPatch(), extraHandledDcts); // Paper
case LEATHER_HORSE_ARMOR:
- return new CraftMetaLeatherArmor(item.getComponentsPatch());
+ return new CraftMetaLeatherArmor(item.getComponentsPatch(), extraHandledDcts); // Paper
case POTION:
case SPLASH_POTION:
case LINGERING_POTION:
case TIPPED_ARROW:
- return new CraftMetaPotion(item.getComponentsPatch());
+ return new CraftMetaPotion(item.getComponentsPatch(), extraHandledDcts); // Paper
case FILLED_MAP:
- return new CraftMetaMap(item.getComponentsPatch());
+ return new CraftMetaMap(item.getComponentsPatch(), extraHandledDcts); // Paper
case FIREWORK_ROCKET:
- return new CraftMetaFirework(item.getComponentsPatch());
+ return new CraftMetaFirework(item.getComponentsPatch(), extraHandledDcts); // Paper
case FIREWORK_STAR:
- return new CraftMetaCharge(item.getComponentsPatch());
+ return new CraftMetaCharge(item.getComponentsPatch(), extraHandledDcts); // Paper;
case ENCHANTED_BOOK:
- return new CraftMetaEnchantedBook(item.getComponentsPatch());
+ return new CraftMetaEnchantedBook(item.getComponentsPatch(), extraHandledDcts); // Paper
case BLACK_BANNER:
case BLACK_WALL_BANNER:
case BLUE_BANNER:
@@ -0,0 +0,0 @@ public final class CraftItemStack extends ItemStack {
case WHITE_WALL_BANNER:
case YELLOW_BANNER:
case YELLOW_WALL_BANNER:
- return new CraftMetaBanner(item.getComponentsPatch());
+ return new CraftMetaBanner(item.getComponentsPatch(), extraHandledDcts); // Paper
case ARMADILLO_SPAWN_EGG:
case ALLAY_SPAWN_EGG:
case AXOLOTL_SPAWN_EGG:
@@ -0,0 +0,0 @@ public final class CraftItemStack extends ItemStack {
case ZOMBIE_SPAWN_EGG:
case ZOMBIE_VILLAGER_SPAWN_EGG:
case ZOMBIFIED_PIGLIN_SPAWN_EGG:
- return new CraftMetaSpawnEgg(item.getComponentsPatch());
+ return new CraftMetaSpawnEgg(item.getComponentsPatch(), extraHandledDcts); // Paper
case ARMOR_STAND:
- return new CraftMetaArmorStand(item.getComponentsPatch());
+ return new CraftMetaArmorStand(item.getComponentsPatch(), extraHandledDcts); // Paper
case KNOWLEDGE_BOOK:
- return new CraftMetaKnowledgeBook(item.getComponentsPatch());
+ return new CraftMetaKnowledgeBook(item.getComponentsPatch(), extraHandledDcts); // Paper
case FURNACE:
case CHEST:
case TRAPPED_CHEST:
@@ -0,0 +0,0 @@ public final class CraftItemStack extends ItemStack {
case CRAFTER:
case TRIAL_SPAWNER:
case VAULT:
- return new CraftMetaBlockState(item.getComponentsPatch(), CraftItemType.minecraftToBukkit(item.getItem()));
+ return new CraftMetaBlockState(item.getComponentsPatch(), CraftItemType.minecraftToBukkit(item.getItem()), extraHandledDcts); // Paper
case TROPICAL_FISH_BUCKET:
- return new CraftMetaTropicalFishBucket(item.getComponentsPatch());
+ return new CraftMetaTropicalFishBucket(item.getComponentsPatch(), extraHandledDcts); // Paper
case AXOLOTL_BUCKET:
- return new CraftMetaAxolotlBucket(item.getComponentsPatch());
+ return new CraftMetaAxolotlBucket(item.getComponentsPatch(), extraHandledDcts); // Paper
case CROSSBOW:
- return new CraftMetaCrossbow(item.getComponentsPatch());
+ return new CraftMetaCrossbow(item.getComponentsPatch(), extraHandledDcts); // Paper
case SUSPICIOUS_STEW:
- return new CraftMetaSuspiciousStew(item.getComponentsPatch());
+ return new CraftMetaSuspiciousStew(item.getComponentsPatch(), extraHandledDcts); // Paper
case COD_BUCKET:
case PUFFERFISH_BUCKET:
case SALMON_BUCKET:
@@ -0,0 +0,0 @@ public final class CraftItemStack extends ItemStack {
case ITEM_FRAME:
case GLOW_ITEM_FRAME:
case PAINTING:
- return new CraftMetaEntityTag(item.getComponentsPatch());
+ return new CraftMetaEntityTag(item.getComponentsPatch(), extraHandledDcts); // Paper
case COMPASS:
- return new CraftMetaCompass(item.getComponentsPatch());
+ return new CraftMetaCompass(item.getComponentsPatch(), extraHandledDcts); // Paper
case BUNDLE:
- return new CraftMetaBundle(item.getComponentsPatch());
+ return new CraftMetaBundle(item.getComponentsPatch(), extraHandledDcts); // Paper
case GOAT_HORN:
- return new CraftMetaMusicInstrument(item.getComponentsPatch());
+ return new CraftMetaMusicInstrument(item.getComponentsPatch(), extraHandledDcts); // Paper
case OMINOUS_BOTTLE:
- return new CraftMetaOminousBottle(item.getComponentsPatch());
+ return new CraftMetaOminousBottle(item.getComponentsPatch(), extraHandledDcts); // Paper
default:
- return new CraftMetaItem(item.getComponentsPatch());
+ return new CraftMetaItem(item.getComponentsPatch(), extraHandledDcts); // Paper
}
}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmor.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmor.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmor.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmor.java
@@ -0,0 +0,0 @@ public class CraftMetaArmor extends CraftMetaItem implements ArmorMeta {
}
}
- CraftMetaArmor(DataComponentPatch tag) {
- super(tag);
+ CraftMetaArmor(DataComponentPatch tag, java.util.Set<net.minecraft.core.component.DataComponentType<?>> extraHandledDcts) { // Paper
+ super(tag, extraHandledDcts); // Paper
getOrEmpty(tag, CraftMetaArmor.TRIM).ifPresent((trimCompound) -> {
TrimMaterial trimMaterial = org.bukkit.craftbukkit.CraftRegistry.unwrapAndConvertHolder(io.papermc.paper.registry.RegistryKey.TRIM_MATERIAL, trimCompound.material()).orElse(null); // Paper - fix upstream not being correct
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java
@@ -0,0 +0,0 @@ public class CraftMetaArmorStand extends CraftMetaItem implements com.destroysto
this.entityTag = armorStand.entityTag;
}
- CraftMetaArmorStand(DataComponentPatch tag) {
- super(tag);
+ CraftMetaArmorStand(DataComponentPatch tag, final java.util.Set<net.minecraft.core.component.DataComponentType<?>> extraHandledDcts) { // Paper
+ super(tag, extraHandledDcts); // Paper
getOrEmpty(tag, CraftMetaArmorStand.ENTITY_TAG).ifPresent((nbt) -> {
this.entityTag = nbt.copyTag();
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaAxolotlBucket.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaAxolotlBucket.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaAxolotlBucket.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaAxolotlBucket.java
@@ -0,0 +0,0 @@ public class CraftMetaAxolotlBucket extends CraftMetaItem implements AxolotlBuck
this.bucketEntityTag = bucket.bucketEntityTag;
}
- CraftMetaAxolotlBucket(DataComponentPatch tag) {
- super(tag);
+ CraftMetaAxolotlBucket(DataComponentPatch tag, final java.util.Set<net.minecraft.core.component.DataComponentType<?>> extraHandledDcts) { // Paper
+ super(tag, extraHandledDcts); // Paper
getOrEmpty(tag, CraftMetaAxolotlBucket.ENTITY_TAG).ifPresent((nbt) -> {
this.entityTag = nbt.copyTag();
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBanner.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBanner.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBanner.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBanner.java
@@ -0,0 +0,0 @@ public class CraftMetaBanner extends CraftMetaItem implements BannerMeta {
this.patterns = new ArrayList<Pattern>(banner.patterns);
}
- CraftMetaBanner(DataComponentPatch tag) {
- super(tag);
+ CraftMetaBanner(DataComponentPatch tag, final java.util.Set<net.minecraft.core.component.DataComponentType<?>> extraHandledDcts) { // Paper
+ super(tag, extraHandledDcts); // Paper
getOrEmpty(tag, CraftMetaBanner.PATTERNS).ifPresent((entityTag) -> {
List<BannerPatternLayers.Layer> patterns = entityTag.layers();
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBlockState.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBlockState.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBlockState.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBlockState.java
@@ -0,0 +0,0 @@ public class CraftMetaBlockState extends CraftMetaItem implements BlockStateMeta
this.blockEntityTag = te.blockEntityTag;
}
- CraftMetaBlockState(DataComponentPatch tag, Material material) {
- super(tag);
+ CraftMetaBlockState(DataComponentPatch tag, Material material, final Set<DataComponentType<?>> extraHandledDcts) { // Paper
+ super(tag, extraHandledDcts); // Paper
this.material = material;
getOrEmpty(tag, CraftMetaBlockState.BLOCK_ENTITY_TAG).ifPresent((nbt) -> {
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java
@@ -0,0 +0,0 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta, WritableBo
}
}
- CraftMetaBook(DataComponentPatch tag) {
- super(tag);
+ CraftMetaBook(DataComponentPatch tag, java.util.Set<net.minecraft.core.component.DataComponentType<?>> extraHandledDcts) { // Paper
+ super(tag, extraHandledDcts); // Paper
getOrEmpty(tag, CraftMetaBook.BOOK_CONTENT).ifPresent((writable) -> {
List<Filterable<String>> pages = writable.pages();
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java
@@ -0,0 +0,0 @@ public class CraftMetaBookSigned extends CraftMetaItem implements BookMeta {
}
}
- CraftMetaBookSigned(DataComponentPatch tag) {
- super(tag);
+ CraftMetaBookSigned(DataComponentPatch tag, java.util.Set<net.minecraft.core.component.DataComponentType<?>> extraHandledDcts) { // Paper
+ super(tag, extraHandledDcts); // Paper
getOrEmpty(tag, CraftMetaBookSigned.BOOK_CONTENT).ifPresent((written) -> {
this.title = written.title().raw();
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBundle.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBundle.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBundle.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBundle.java
@@ -0,0 +0,0 @@ public class CraftMetaBundle extends CraftMetaItem implements BundleMeta {
}
}
- CraftMetaBundle(DataComponentPatch tag) {
- super(tag);
+ CraftMetaBundle(DataComponentPatch tag, java.util.Set<net.minecraft.core.component.DataComponentType<?>> extraHandledDcts) { // Paper
+ super(tag, extraHandledDcts); // Paper
getOrEmpty(tag, CraftMetaBundle.ITEMS).ifPresent((bundle) -> {
bundle.items().forEach((item) -> {
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaCharge.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaCharge.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaCharge.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaCharge.java
@@ -0,0 +0,0 @@ class CraftMetaCharge extends CraftMetaItem implements FireworkEffectMeta {
this.setEffect(SerializableMeta.getObject(FireworkEffect.class, map, CraftMetaCharge.EXPLOSION.BUKKIT, true));
}
- CraftMetaCharge(DataComponentPatch tag) {
- super(tag);
+ CraftMetaCharge(DataComponentPatch tag, java.util.Set<net.minecraft.core.component.DataComponentType<?>> extraHandledDcts) { // Paper
+ super(tag, extraHandledDcts); // Paper
getOrEmpty(tag, CraftMetaCharge.EXPLOSION).ifPresent((f) -> {
try {
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaColorableArmor.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaColorableArmor.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaColorableArmor.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaColorableArmor.java
@@ -0,0 +0,0 @@ public class CraftMetaColorableArmor extends CraftMetaArmor implements Colorable
CraftMetaLeatherArmor.readColor(this, meta);
}
- CraftMetaColorableArmor(DataComponentPatch tag) {
- super(tag);
+ CraftMetaColorableArmor(DataComponentPatch tag, java.util.Set<net.minecraft.core.component.DataComponentType<?>> extraHandledDcts) { // Paper
+ super(tag, extraHandledDcts); // Paper
CraftMetaLeatherArmor.readColor(this, tag);
}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaCompass.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaCompass.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaCompass.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaCompass.java
@@ -0,0 +0,0 @@ public class CraftMetaCompass extends CraftMetaItem implements CompassMeta {
this.tracked = compassMeta.tracked;
}
- CraftMetaCompass(DataComponentPatch tag) {
- super(tag);
+ CraftMetaCompass(DataComponentPatch tag, java.util.Set<net.minecraft.core.component.DataComponentType<?>> extraHandledDcts) { // Paper
+ super(tag, extraHandledDcts); // Paper
getOrEmpty(tag, CraftMetaCompass.LODESTONE_TARGET).ifPresent((lodestoneTarget) -> {
lodestoneTarget.target().ifPresent((target) -> {
this.lodestoneWorld = target.dimension();
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaCrossbow.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaCrossbow.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaCrossbow.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaCrossbow.java
@@ -0,0 +0,0 @@ public class CraftMetaCrossbow extends CraftMetaItem implements CrossbowMeta {
}
}
- CraftMetaCrossbow(DataComponentPatch tag) {
- super(tag);
+ CraftMetaCrossbow(DataComponentPatch tag, java.util.Set<net.minecraft.core.component.DataComponentType<?>> extraHandledDcts) { // Paper
+ super(tag, extraHandledDcts); // Paper
getOrEmpty(tag, CraftMetaCrossbow.CHARGED_PROJECTILES).ifPresent((p) -> {
List<net.minecraft.world.item.ItemStack> list = p.getItems();
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaEnchantedBook.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaEnchantedBook.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaEnchantedBook.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaEnchantedBook.java
@@ -0,0 +0,0 @@ class CraftMetaEnchantedBook extends CraftMetaItem implements EnchantmentStorage
}
}
- CraftMetaEnchantedBook(DataComponentPatch tag) {
- super(tag);
+ CraftMetaEnchantedBook(DataComponentPatch tag, java.util.Set<net.minecraft.core.component.DataComponentType<?>> extraHandledDcts) { // Paper
+ super(tag, extraHandledDcts); // Paper
getOrEmpty(tag, CraftMetaEnchantedBook.STORED_ENCHANTMENTS).ifPresent((itemEnchantments) -> {
this.enchantments = buildEnchantments(itemEnchantments);
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaEntityTag.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaEntityTag.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaEntityTag.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaEntityTag.java
@@ -0,0 +0,0 @@ public class CraftMetaEntityTag extends CraftMetaItem {
this.entityTag = entity.entityTag;
}
- CraftMetaEntityTag(DataComponentPatch tag) {
- super(tag);
+ CraftMetaEntityTag(DataComponentPatch tag, final java.util.Set<net.minecraft.core.component.DataComponentType<?>> extraHandledDcts) { // Paper
+ super(tag, extraHandledDcts); // Paper
getOrEmpty(tag, CraftMetaEntityTag.ENTITY_TAG).ifPresent((nbt) -> {
this.entityTag = nbt.copyTag();
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaFirework.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaFirework.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaFirework.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaFirework.java
@@ -0,0 +0,0 @@ class CraftMetaFirework extends CraftMetaItem implements FireworkMeta {
}
}
- CraftMetaFirework(DataComponentPatch tag) {
- super(tag);
+ CraftMetaFirework(DataComponentPatch tag, java.util.Set<net.minecraft.core.component.DataComponentType<?>> extraHandledDcts) { // Paper
+ super(tag, extraHandledDcts); // Paper
getOrEmpty(tag, CraftMetaFirework.FIREWORKS).ifPresent((fireworks) -> {
this.power = fireworks.flightDuration();
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
// Paper end
}
- CraftMetaItem(DataComponentPatch tag) {
+ CraftMetaItem(DataComponentPatch tag, Set<DataComponentType<?>> extraHandledTags) { // Paper - improve handled tags on type changes
CraftMetaItem.getOrEmpty(tag, CraftMetaItem.NAME).ifPresent((component) -> {
this.displayName = component;
});
@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
});
// Paper end - fix ItemFlags
+ // Paper start - improve checking handled data component types
+ Set<DataComponentType<?>> handledTags = getTopLevelHandledDcts(this.getClass());
+ if (extraHandledTags != null) {
+ extraHandledTags.addAll(handledTags);
+ handledTags = extraHandledTags;
+ }
+ // Paper end - improve checking handled data component types
Set<Map.Entry<DataComponentType<?>, Optional<?>>> keys = tag.entrySet();
for (Map.Entry<DataComponentType<?>, Optional<?>> key : keys) {
if (key.getValue().isEmpty()) {
this.unhandledTags.remove(key.getKey());
- } else if (!CraftMetaItem.getHandledTags().contains(key.getKey())) {
+ } else if (!handledTags.contains(key.getKey())) { // Paper - improve checking handled data component types
key.getValue().ifPresentOrElse((value) -> {
this.unhandledTags.set((DataComponentType) key.getKey(), value);
}, () -> {
@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
this.version = version;
}
- public static Set<DataComponentType> getHandledTags() {
- synchronized (CraftMetaItem.HANDLED_TAGS) {
- if (CraftMetaItem.HANDLED_TAGS.isEmpty()) {
- CraftMetaItem.HANDLED_TAGS.addAll(Arrays.asList(
- CraftMetaItem.NAME.TYPE,
- CraftMetaItem.ITEM_NAME.TYPE,
- CraftMetaItem.LORE.TYPE,
- CraftMetaItem.CUSTOM_MODEL_DATA.TYPE,
- CraftMetaItem.BLOCK_DATA.TYPE,
- CraftMetaItem.REPAIR.TYPE,
- CraftMetaItem.ENCHANTMENTS.TYPE,
- CraftMetaItem.HIDE_ADDITIONAL_TOOLTIP.TYPE,
- CraftMetaItem.HIDE_TOOLTIP.TYPE,
- CraftMetaItem.UNBREAKABLE.TYPE,
- CraftMetaItem.ENCHANTMENT_GLINT_OVERRIDE.TYPE,
- CraftMetaItem.FIRE_RESISTANT.TYPE,
- CraftMetaItem.MAX_STACK_SIZE.TYPE,
- CraftMetaItem.RARITY.TYPE,
- CraftMetaItem.FOOD.TYPE,
- CraftMetaItem.TOOL.TYPE,
- CraftMetaItem.DAMAGE.TYPE,
- CraftMetaItem.MAX_DAMAGE.TYPE,
- CraftMetaItem.CUSTOM_DATA.TYPE,
- CraftMetaItem.ATTRIBUTES.TYPE,
- CraftMetaItem.CAN_PLACE_ON.TYPE, // Paper
- CraftMetaItem.CAN_BREAK.TYPE, // Paper
- CraftMetaArmor.TRIM.TYPE,
- CraftMetaArmorStand.ENTITY_TAG.TYPE,
- CraftMetaBanner.PATTERNS.TYPE,
- CraftMetaEntityTag.ENTITY_TAG.TYPE,
- CraftMetaLeatherArmor.COLOR.TYPE,
- CraftMetaMap.MAP_POST_PROCESSING.TYPE,
- CraftMetaMap.MAP_COLOR.TYPE,
- CraftMetaMap.MAP_ID.TYPE,
- CraftMetaPotion.POTION_CONTENTS.TYPE,
- CraftMetaSkull.SKULL_PROFILE.TYPE,
- CraftMetaSkull.NOTE_BLOCK_SOUND.TYPE,
- CraftMetaSpawnEgg.ENTITY_TAG.TYPE,
- CraftMetaBlockState.BLOCK_ENTITY_TAG.TYPE,
- CraftMetaBook.BOOK_CONTENT.TYPE,
- CraftMetaBookSigned.BOOK_CONTENT.TYPE,
- CraftMetaFirework.FIREWORKS.TYPE,
- CraftMetaEnchantedBook.STORED_ENCHANTMENTS.TYPE,
- CraftMetaCharge.EXPLOSION.TYPE,
- CraftMetaBlockState.BLOCK_ENTITY_TAG.TYPE,
- CraftMetaKnowledgeBook.BOOK_RECIPES.TYPE,
- CraftMetaTropicalFishBucket.ENTITY_TAG.TYPE,
- CraftMetaTropicalFishBucket.BUCKET_ENTITY_TAG.TYPE,
- CraftMetaAxolotlBucket.ENTITY_TAG.TYPE,
- CraftMetaAxolotlBucket.BUCKET_ENTITY_TAG.TYPE,
- CraftMetaCrossbow.CHARGED_PROJECTILES.TYPE,
- CraftMetaSuspiciousStew.EFFECTS.TYPE,
- CraftMetaCompass.LODESTONE_TARGET.TYPE,
- CraftMetaBundle.ITEMS.TYPE,
- CraftMetaMusicInstrument.GOAT_HORN_INSTRUMENT.TYPE,
- CraftMetaOminousBottle.OMINOUS_BOTTLE_AMPLIFIER.TYPE
- ));
- }
- return CraftMetaItem.HANDLED_TAGS;
+ // Paper start - improve checking handled tags
+ @org.jetbrains.annotations.VisibleForTesting
+ public static final Map<Class<? extends CraftMetaItem>, Set<DataComponentType<?>>> HANDLED_DCTS_PER_TYPE = new HashMap<>();
+ private static final Set<DataComponentType<?>> DEFAULT_HANDLED_DCTS = Set.of(
+ CraftMetaItem.NAME.TYPE,
+ CraftMetaItem.ITEM_NAME.TYPE,
+ CraftMetaItem.LORE.TYPE,
+ CraftMetaItem.CUSTOM_MODEL_DATA.TYPE,
+ CraftMetaItem.BLOCK_DATA.TYPE,
+ CraftMetaItem.REPAIR.TYPE,
+ CraftMetaItem.ENCHANTMENTS.TYPE,
+ CraftMetaItem.HIDE_ADDITIONAL_TOOLTIP.TYPE,
+ CraftMetaItem.HIDE_TOOLTIP.TYPE,
+ CraftMetaItem.UNBREAKABLE.TYPE,
+ CraftMetaItem.ENCHANTMENT_GLINT_OVERRIDE.TYPE,
+ CraftMetaItem.FIRE_RESISTANT.TYPE,
+ CraftMetaItem.MAX_STACK_SIZE.TYPE,
+ CraftMetaItem.RARITY.TYPE,
+ CraftMetaItem.FOOD.TYPE,
+ CraftMetaItem.TOOL.TYPE,
+ CraftMetaItem.DAMAGE.TYPE,
+ CraftMetaItem.MAX_DAMAGE.TYPE,
+ CraftMetaItem.CUSTOM_DATA.TYPE,
+ CraftMetaItem.ATTRIBUTES.TYPE,
+ CraftMetaItem.CAN_PLACE_ON.TYPE, // Paper
+ CraftMetaItem.CAN_BREAK.TYPE // Paper
+ );
+ public static Set<DataComponentType<?>> getTopLevelHandledDcts(final Class<? extends CraftMetaItem> clazz) {
+ synchronized (HANDLED_DCTS_PER_TYPE) {
+ if (HANDLED_DCTS_PER_TYPE.isEmpty()) {
+ final Map<Class<? extends CraftMetaItem>, Set<DataComponentType<?>>> map = new HashMap<>();
+ map.put(CraftMetaArmor.class, Set.of(CraftMetaArmor.TRIM.TYPE));
+ map.put(CraftMetaArmorStand.class, Set.of(CraftMetaArmorStand.ENTITY_TAG.TYPE));
+ map.put(CraftMetaAxolotlBucket.class, Set.of(CraftMetaAxolotlBucket.ENTITY_TAG.TYPE, CraftMetaAxolotlBucket.BUCKET_ENTITY_TAG.TYPE));
+ map.put(CraftMetaBanner.class, Set.of(/*CraftMetaBlockState.BLOCK_ENTITY_TAG.NBT, */CraftMetaBanner.PATTERNS.TYPE)); // banner uses same tag as block state
+ map.put(CraftMetaBlockState.class, Set.of(CraftMetaBlockState.BLOCK_ENTITY_TAG.TYPE));
+ map.put(CraftMetaBook.class, Set.of(CraftMetaBook.BOOK_CONTENT.TYPE));
+ map.put(CraftMetaBookSigned.class, Set.of(CraftMetaBookSigned.BOOK_CONTENT.TYPE));
+ map.put(CraftMetaBundle.class, Set.of(CraftMetaBundle.ITEMS.TYPE));
+ map.put(CraftMetaCharge.class, Set.of(CraftMetaCharge.EXPLOSION.TYPE));
+ map.put(CraftMetaColorableArmor.class, Set.of(CraftMetaArmor.TRIM.TYPE, CraftMetaLeatherArmor.COLOR.TYPE));
+ map.put(CraftMetaCompass.class, Set.of(CraftMetaCompass.LODESTONE_TARGET.TYPE));
+ map.put(CraftMetaCrossbow.class, Set.of(CraftMetaCrossbow.CHARGED_PROJECTILES.TYPE));
+ map.put(CraftMetaEnchantedBook.class, Set.of(CraftMetaEnchantedBook.STORED_ENCHANTMENTS.TYPE));
+ map.put(CraftMetaEntityTag.class, Set.of(CraftMetaEntityTag.ENTITY_TAG.TYPE));
+ map.put(CraftMetaFirework.class, Set.of(CraftMetaFirework.FIREWORKS.TYPE));
+ map.put(CraftMetaKnowledgeBook.class, Set.of(CraftMetaKnowledgeBook.BOOK_RECIPES.TYPE));
+ map.put(CraftMetaLeatherArmor.class, Set.of(CraftMetaLeatherArmor.COLOR.TYPE));
+ map.put(CraftMetaMap.class, Set.of(CraftMetaMap.MAP_COLOR.TYPE, CraftMetaMap.MAP_POST_PROCESSING.TYPE, CraftMetaMap.MAP_ID.TYPE));
+ map.put(CraftMetaMusicInstrument.class, Set.of(CraftMetaMusicInstrument.GOAT_HORN_INSTRUMENT.TYPE));
+ map.put(CraftMetaOminousBottle.class, Set.of(CraftMetaOminousBottle.OMINOUS_BOTTLE_AMPLIFIER.TYPE));
+ map.put(CraftMetaPotion.class, Set.of(CraftMetaPotion.POTION_CONTENTS.TYPE));
+ map.put(CraftMetaSkull.class, Set.of(CraftMetaSkull.SKULL_PROFILE.TYPE, CraftMetaSkull.NOTE_BLOCK_SOUND.TYPE));
+ map.put(CraftMetaSpawnEgg.class, Set.of(CraftMetaSpawnEgg.ENTITY_TAG.TYPE));
+ map.put(CraftMetaSuspiciousStew.class, Set.of(CraftMetaSuspiciousStew.EFFECTS.TYPE));
+ map.put(CraftMetaTropicalFishBucket.class, Set.of(CraftMetaTropicalFishBucket.ENTITY_TAG.TYPE, CraftMetaTropicalFishBucket.BUCKET_ENTITY_TAG.TYPE));
+
+ for (final Map.Entry<Class<? extends CraftMetaItem>, Set<DataComponentType<?>>> entry : map.entrySet()) {
+ final ArrayList<DataComponentType<?>> topLevelTags = new ArrayList<>(entry.getValue());
+ // add tags common to CraftMetaItem to all
+ topLevelTags.addAll(DEFAULT_HANDLED_DCTS);
+ HANDLED_DCTS_PER_TYPE.put(entry.getKey(), Set.copyOf(topLevelTags));
+ }
+ }
+ return HANDLED_DCTS_PER_TYPE.getOrDefault(clazz, DEFAULT_HANDLED_DCTS);
}
}
+ // Paper end - improve checking handled data component types
protected static <T> Optional<? extends T> getOrEmpty(DataComponentPatch tag, ItemMetaKeyType<T> type) {
Optional<? extends T> result = tag.get(type.TYPE);
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaKnowledgeBook.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaKnowledgeBook.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaKnowledgeBook.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaKnowledgeBook.java
@@ -0,0 +0,0 @@ public class CraftMetaKnowledgeBook extends CraftMetaItem implements KnowledgeBo
}
}
- CraftMetaKnowledgeBook(DataComponentPatch tag) {
- super(tag);
+ CraftMetaKnowledgeBook(DataComponentPatch tag, java.util.Set<net.minecraft.core.component.DataComponentType<?>> extraHandledDcts) { // Paper
+ super(tag, extraHandledDcts); // Paper
getOrEmpty(tag, CraftMetaKnowledgeBook.BOOK_RECIPES).ifPresent((pages) -> {
for (int i = 0; i < pages.size(); i++) {
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaLeatherArmor.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaLeatherArmor.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaLeatherArmor.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaLeatherArmor.java
@@ -0,0 +0,0 @@ class CraftMetaLeatherArmor extends CraftMetaItem implements LeatherArmorMeta {
CraftMetaLeatherArmor.readColor(this, meta);
}
- CraftMetaLeatherArmor(DataComponentPatch tag) {
- super(tag);
+ CraftMetaLeatherArmor(DataComponentPatch tag, java.util.Set<net.minecraft.core.component.DataComponentType<?>> extraHandledDcts) { // Paper
+ super(tag, extraHandledDcts); // Paper
CraftMetaLeatherArmor.readColor(this, tag);
}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaMap.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaMap.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaMap.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaMap.java
@@ -0,0 +0,0 @@ class CraftMetaMap extends CraftMetaItem implements MapMeta {
this.color = map.color;
}
- CraftMetaMap(DataComponentPatch tag) {
- super(tag);
+ CraftMetaMap(DataComponentPatch tag, java.util.Set<net.minecraft.core.component.DataComponentType<?>> extraHandledDcts) { // Paper
+ super(tag, extraHandledDcts); // Paper
getOrEmpty(tag, CraftMetaMap.MAP_ID).ifPresent((mapId) -> {
this.mapId = mapId.id();
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaMusicInstrument.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaMusicInstrument.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaMusicInstrument.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaMusicInstrument.java
@@ -0,0 +0,0 @@ public class CraftMetaMusicInstrument extends CraftMetaItem implements MusicInst
}
}
- CraftMetaMusicInstrument(DataComponentPatch tag) {
- super(tag);
+ CraftMetaMusicInstrument(DataComponentPatch tag, java.util.Set<net.minecraft.core.component.DataComponentType<?>> extraHandledDcts) { // Paper
+ super(tag, extraHandledDcts); // Paper
getOrEmpty(tag, CraftMetaMusicInstrument.GOAT_HORN_INSTRUMENT).ifPresent((instrument) -> {
this.instrument = org.bukkit.craftbukkit.CraftRegistry.unwrapAndConvertHolder(org.bukkit.Registry.INSTRUMENT, instrument).orElse(null); // Paper - fix upstream not handling custom instruments
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaOminousBottle.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaOminousBottle.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaOminousBottle.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaOminousBottle.java
@@ -0,0 +0,0 @@ public class CraftMetaOminousBottle extends CraftMetaItem implements OminousBott
this.ominousBottleAmplifier = bottleMeta.ominousBottleAmplifier;
}
- CraftMetaOminousBottle(DataComponentPatch tag) {
- super(tag);
+ CraftMetaOminousBottle(DataComponentPatch tag, java.util.Set<net.minecraft.core.component.DataComponentType<?>> extraHandledDcts) { // Paper
+ super(tag, extraHandledDcts); // Paper
getOrEmpty(tag, CraftMetaOminousBottle.OMINOUS_BOTTLE_AMPLIFIER).ifPresent((amplifier) -> {
this.ominousBottleAmplifier = amplifier;
});
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaPotion.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaPotion.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaPotion.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaPotion.java
@@ -0,0 +0,0 @@ class CraftMetaPotion extends CraftMetaItem implements PotionMeta {
}
}
- CraftMetaPotion(DataComponentPatch tag) {
- super(tag);
+ CraftMetaPotion(DataComponentPatch tag, java.util.Set<net.minecraft.core.component.DataComponentType<?>> extraHandledDcts) { // Paper
+ super(tag, extraHandledDcts); // Paper
getOrEmpty(tag, CraftMetaPotion.POTION_CONTENTS).ifPresent((potionContents) -> {
potionContents.potion().ifPresent((potion) -> {
this.type = CraftPotionType.minecraftHolderToBukkit(potion);
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java
@@ -0,0 +0,0 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta {
this.noteBlockSound = skullMeta.noteBlockSound;
}
- CraftMetaSkull(DataComponentPatch tag) {
- super(tag);
+ CraftMetaSkull(DataComponentPatch tag, java.util.Set<net.minecraft.core.component.DataComponentType<?>> extraHandledDcts) { // Paper
+ super(tag, extraHandledDcts); // Paper
getOrEmpty(tag, CraftMetaSkull.SKULL_PROFILE).ifPresent((resolvableProfile) -> {
this.setProfile(resolvableProfile.gameProfile());
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSpawnEgg.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSpawnEgg.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSpawnEgg.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSpawnEgg.java
@@ -0,0 +0,0 @@ public class CraftMetaSpawnEgg extends CraftMetaItem implements SpawnEggMeta {
this.entityTag = egg.entityTag;
}
- CraftMetaSpawnEgg(DataComponentPatch tag) {
- super(tag);
+ CraftMetaSpawnEgg(DataComponentPatch tag, java.util.Set<net.minecraft.core.component.DataComponentType<?>> extraHandledDcts) { // Paper
+ super(tag, extraHandledDcts); // Paper
getOrEmpty(tag, CraftMetaSpawnEgg.ENTITY_TAG).ifPresent((nbt) -> {
this.entityTag = nbt.copyTag();
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSuspiciousStew.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSuspiciousStew.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSuspiciousStew.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSuspiciousStew.java
@@ -0,0 +0,0 @@ public class CraftMetaSuspiciousStew extends CraftMetaItem implements Suspicious
}
}
- CraftMetaSuspiciousStew(DataComponentPatch tag) {
- super(tag);
+ CraftMetaSuspiciousStew(DataComponentPatch tag, java.util.Set<net.minecraft.core.component.DataComponentType<?>> extraHandledDcts) { // Paper
+ super(tag, extraHandledDcts); // Paper
getOrEmpty(tag, CraftMetaSuspiciousStew.EFFECTS).ifPresent((suspiciousStewEffects) -> {
List<SuspiciousStewEffects.Entry> list = suspiciousStewEffects.effects();
int length = list.size();
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaTropicalFishBucket.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaTropicalFishBucket.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaTropicalFishBucket.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaTropicalFishBucket.java
@@ -0,0 +0,0 @@ class CraftMetaTropicalFishBucket extends CraftMetaItem implements TropicalFishB
this.bucketEntityTag = bucket.bucketEntityTag;
}
- CraftMetaTropicalFishBucket(DataComponentPatch tag) {
- super(tag);
+ CraftMetaTropicalFishBucket(DataComponentPatch tag, java.util.Set<net.minecraft.core.component.DataComponentType<?>> extraHandledDcts) { // Paper
+ super(tag, extraHandledDcts); // Paper
getOrEmpty(tag, CraftMetaTropicalFishBucket.ENTITY_TAG).ifPresent((nbt) -> {
this.entityTag = nbt.copyTag();
diff --git a/src/test/java/org/bukkit/craftbukkit/inventory/DeprecatedItemMetaCustomValueTest.java b/src/test/java/org/bukkit/craftbukkit/inventory/DeprecatedItemMetaCustomValueTest.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/test/java/org/bukkit/craftbukkit/inventory/DeprecatedItemMetaCustomValueTest.java
+++ b/src/test/java/org/bukkit/craftbukkit/inventory/DeprecatedItemMetaCustomValueTest.java
@@ -0,0 +0,0 @@ public class DeprecatedItemMetaCustomValueTest extends AbstractTestingBase {
CraftMetaItem.Applicator compound = new CraftMetaItem.Applicator();
itemMeta.applyToItem(compound);
- assertEquals(itemMeta, new CraftMetaItem(compound.build()));
+ assertEquals(itemMeta, new CraftMetaItem(compound.build(), null)); // Paper
}
@Test
diff --git a/src/test/java/org/bukkit/craftbukkit/inventory/MetaHandledTagsTest.java b/src/test/java/org/bukkit/craftbukkit/inventory/MetaHandledTagsTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
+++ b/src/test/java/org/bukkit/craftbukkit/inventory/MetaHandledTagsTest.java
@@ -0,0 +0,0 @@
+package org.bukkit.craftbukkit.inventory;
+
+import io.github.classgraph.ClassGraph;
+import io.github.classgraph.ClassInfo;
+import io.github.classgraph.ClassInfoList;
+import io.github.classgraph.ScanResult;
+import org.bukkit.support.AbstractTestingBase;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+// in cb package because of package-private stuff
+class MetaHandledTagsTest extends AbstractTestingBase {
+
+ @Test
+ public void checkAllMetasHaveHandledTags() {
+ try (final ScanResult result = new ClassGraph()
+ .whitelistPackages("org.bukkit.craftbukkit.inventory")
+ .enableAllInfo().scan()) {
+ final ClassInfoList subclasses = result.getSubclasses(CraftMetaItem.class.getName());
+ assertFalse(subclasses.isEmpty(), "found 0 sub types");
+ for (final ClassInfo subclass : subclasses) {
+ final Class<CraftMetaItem> clazz = subclass.loadClass(CraftMetaItem.class);
+ CraftMetaItem.getTopLevelHandledDcts(clazz); // load into map
+ assertTrue(CraftMetaItem.HANDLED_DCTS_PER_TYPE.containsKey(clazz), subclass.getName() + " not found in handled tags map");
+ }
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/src/test/java/org/bukkit/craftbukkit/inventory/PersistentDataContainerTest.java b/src/test/java/org/bukkit/craftbukkit/inventory/PersistentDataContainerTest.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/test/java/org/bukkit/craftbukkit/inventory/PersistentDataContainerTest.java
+++ b/src/test/java/org/bukkit/craftbukkit/inventory/PersistentDataContainerTest.java
@@ -0,0 +0,0 @@ public class PersistentDataContainerTest extends AbstractTestingBase {
CraftMetaItem.Applicator compound = new CraftMetaItem.Applicator();
itemMeta.applyToItem(compound);
- assertEquals(itemMeta, new CraftMetaItem(compound.build()));
+ assertEquals(itemMeta, new CraftMetaItem(compound.build(), null)); // Paper
}
@Test
@@ -0,0 +0,0 @@ public class PersistentDataContainerTest extends AbstractTestingBase {
@Test
public void testEmptyListApplicationToAnyType() throws IOException {
- final CraftMetaItem craftItem = new CraftMetaItem(DataComponentPatch.EMPTY);
+ final CraftMetaItem craftItem = new CraftMetaItem(DataComponentPatch.EMPTY, null); // Paper
final PersistentDataContainer container = craftItem.getPersistentDataContainer();
container.set(PersistentDataContainerTest.requestKey("list"), PersistentDataType.LIST.strings(), List.of());
@@ -0,0 +0,0 @@ public class PersistentDataContainerTest extends AbstractTestingBase {
final CraftMetaItem.Applicator storage = new CraftMetaItem.Applicator();
craftItem.applyToItem(storage);
- final CraftMetaItem readItem = new CraftMetaItem(storage.build());
+ final CraftMetaItem readItem = new CraftMetaItem(storage.build(), null); // Paper
final PersistentDataContainer readContainer = readItem.getPersistentDataContainer();
assertTrue(readContainer.has(PersistentDataContainerTest.requestKey("list"), PersistentDataType.LIST.strings()));