diff --git a/patches/api/Adventure.patch b/patches/api/Adventure.patch
index 5960fc458c..6ca30aca54 100644
--- a/patches/api/Adventure.patch
+++ b/patches/api/Adventure.patch
@@ -567,7 +567,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer;
+import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
+import org.bukkit.Bukkit;
++import org.bukkit.command.CommandSender;
++import org.bukkit.entity.Entity;
+import org.jetbrains.annotations.NotNull;
++import org.jetbrains.annotations.Nullable;
++
++import java.io.IOException;
+
+/**
+ * Paper API-specific methods for working with {@link Component}s and related.
@@ -578,6 +583,66 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+
+ /**
++ * Resolves a component with a specific command sender and subject.
++ *
++ * Note that in Vanilla, elevated permissions are usually required to use
++ * '@' selectors in various component types, but this method should not
++ * check such permissions from the sender.
++ *
++ * A {@link CommandSender} argument is required to resolve:
++ *
++ * - {@link net.kyori.adventure.text.NBTComponent}
++ * - {@link net.kyori.adventure.text.ScoreComponent}
++ * - {@link net.kyori.adventure.text.SelectorComponent}
++ *
++ * A {@link Entity} argument is optional to help resolve:
++ *
++ * - {@link net.kyori.adventure.text.ScoreComponent}
++ *
++ * {@link net.kyori.adventure.text.TranslatableComponent}s don't require any extra arguments.
++ *
++ * @param input the component to resolve
++ * @param context the command sender to resolve with
++ * @param scoreboardSubject the scoreboard subject to use (for use with {@link net.kyori.adventure.text.ScoreComponent}s)
++ * @return the resolved component
++ * @throws IOException if a syntax error tripped during resolving
++ */
++ public static @NotNull Component resolveWithContext(@NotNull Component input, @Nullable CommandSender context, @Nullable Entity scoreboardSubject) throws IOException {
++ return resolveWithContext(input, context, scoreboardSubject, true);
++ }
++
++ /**
++ * Resolves a component with a specific command sender and subject.
++ *
++ * Note that in Vanilla, elevated permissions are required to use
++ * '@' selectors in various component types. If the boolean {@code bypassPermissions}
++ * argument is {@code false}, the {@link CommandSender} argument will be used to query
++ * those permissions.
++ *
++ * A {@link CommandSender} argument is required to resolve:
++ *
++ * - {@link net.kyori.adventure.text.NBTComponent}
++ * - {@link net.kyori.adventure.text.ScoreComponent}
++ * - {@link net.kyori.adventure.text.SelectorComponent}
++ *
++ * A {@link Entity} argument is optional to help resolve:
++ *
++ * - {@link net.kyori.adventure.text.ScoreComponent}
++ *
++ * {@link net.kyori.adventure.text.TranslatableComponent}s don't require any extra arguments.
++ *
++ * @param input the component to resolve
++ * @param context the command sender to resolve with
++ * @param scoreboardSubject the scoreboard subject to use (for use with {@link net.kyori.adventure.text.ScoreComponent}s)
++ * @param bypassPermissions true to bypass permissions checks for resolving components
++ * @return the resolved component
++ * @throws IOException if a syntax error tripped during resolving
++ */
++ public static @NotNull Component resolveWithContext(@NotNull Component input, @Nullable CommandSender context, @Nullable Entity scoreboardSubject, boolean bypassPermissions) throws IOException {
++ return Bukkit.getUnsafe().resolveWithContext(input, context, scoreboardSubject, bypassPermissions);
++ }
++
++ /**
+ * Return a component flattener that can use game data to resolve extra information about components.
+ *
+ * @return a component flattener
@@ -1317,6 +1382,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ @Deprecated(forRemoval = true) net.kyori.adventure.text.serializer.gson.GsonComponentSerializer gsonComponentSerializer();
+ @Deprecated(forRemoval = true) net.kyori.adventure.text.serializer.gson.GsonComponentSerializer colorDownsamplingGsonComponentSerializer();
+ @Deprecated(forRemoval = true) net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer legacyComponentSerializer();
++ net.kyori.adventure.text.Component resolveWithContext(net.kyori.adventure.text.Component component, org.bukkit.command.CommandSender context, org.bukkit.entity.Entity scoreboardSubject, boolean bypassPermissions) throws java.io.IOException;
+ // Paper end
Material toLegacy(Material material);
diff --git a/patches/api/Timings-v2.patch b/patches/api/Timings-v2.patch
index 55a514b5ea..957431f78d 100644
--- a/patches/api/Timings-v2.patch
+++ b/patches/api/Timings-v2.patch
@@ -2838,7 +2838,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/org/bukkit/UnsafeValues.java
+++ b/src/main/java/org/bukkit/UnsafeValues.java
@@ -0,0 +0,0 @@ public interface UnsafeValues {
- @Deprecated(forRemoval = true) net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer legacyComponentSerializer();
+ net.kyori.adventure.text.Component resolveWithContext(net.kyori.adventure.text.Component component, org.bukkit.command.CommandSender context, org.bukkit.entity.Entity scoreboardSubject, boolean bypassPermissions) throws java.io.IOException;
// Paper end
+ void reportTimings(); // Paper
diff --git a/patches/server/Adventure.patch b/patches/server/Adventure.patch
index ef581ebaed..04c1559384 100644
--- a/patches/server/Adventure.patch
+++ b/patches/server/Adventure.patch
@@ -726,17 +726,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+import net.kyori.adventure.translation.Translator;
+import net.kyori.adventure.util.Codec;
+import net.minecraft.ChatFormatting;
++import net.minecraft.commands.CommandSourceStack;
+import net.minecraft.locale.Language;
+import net.minecraft.nbt.CompoundTag;
+import net.minecraft.nbt.ListTag;
+import net.minecraft.nbt.StringTag;
+import net.minecraft.nbt.TagParser;
++import net.minecraft.network.chat.ComponentUtils;
+import net.minecraft.resources.ResourceLocation;
+import net.minecraft.sounds.SoundSource;
+import net.minecraft.world.BossEvent;
+import net.minecraft.world.item.ItemStack;
+import net.minecraft.world.item.WrittenBookItem;
-+import org.bukkit.ChatColor;
++import org.bukkit.command.CommandSender;
++import org.bukkit.craftbukkit.command.VanillaCommandWrapper;
++import org.bukkit.craftbukkit.entity.CraftEntity;
++import org.bukkit.entity.Entity;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
@@ -894,6 +899,24 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ );
+ }
+
++ public static Component resolveWithContext(final @NotNull Component component, final @Nullable CommandSender context, final @Nullable Entity scoreboardSubject, final boolean bypassPermissions) throws IOException {
++ final CommandSourceStack css = context != null ? VanillaCommandWrapper.getListener(context) : null;
++ Boolean previous = null;
++ if (css != null && bypassPermissions) {
++ previous = css.bypassSelectorPermissions;
++ css.bypassSelectorPermissions = true;
++ }
++ try {
++ return asAdventure(ComponentUtils.updateForEntity(css, asVanilla(component), scoreboardSubject == null ? null : ((CraftEntity) scoreboardSubject).getHandle(), 0));
++ } catch (CommandSyntaxException e) {
++ throw new IOException(e);
++ } finally {
++ if (css != null && previous != null) {
++ css.bypassSelectorPermissions = previous;
++ }
++ }
++ }
++
+ // BossBar
+
+ public static BossEvent.BossBarColor asVanilla(final BossBar.Color color) {
@@ -1423,6 +1446,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@Nullable
public static ChatFormatting getById(int colorIndex) {
if (colorIndex < 0) {
+diff --git a/src/main/java/net/minecraft/commands/CommandSourceStack.java b/src/main/java/net/minecraft/commands/CommandSourceStack.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/net/minecraft/commands/CommandSourceStack.java
++++ b/src/main/java/net/minecraft/commands/CommandSourceStack.java
+@@ -0,0 +0,0 @@ public class CommandSourceStack implements SharedSuggestionProvider {
+ private final CommandSigningContext signingContext;
+ private final TaskChainer chatMessageChainer;
+ public volatile CommandNode currentCommand; // CraftBukkit
++ public boolean bypassSelectorPermissions = false; // Paper
+
+ public CommandSourceStack(CommandSource output, Vec3 pos, Vec2 rot, ServerLevel world, int level, String name, Component displayName, MinecraftServer server, @Nullable Entity entity) {
+ this(output, pos, rot, world, level, name, displayName, server, entity, false, (commandcontext, flag, j) -> {
diff --git a/src/main/java/net/minecraft/commands/arguments/MessageArgument.java b/src/main/java/net/minecraft/commands/arguments/MessageArgument.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/commands/arguments/MessageArgument.java
@@ -1445,6 +1480,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
MessageArgument.logResolutionFailure(source, completableFuture);
return completableFuture;
}
+diff --git a/src/main/java/net/minecraft/commands/arguments/selector/EntitySelector.java b/src/main/java/net/minecraft/commands/arguments/selector/EntitySelector.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/net/minecraft/commands/arguments/selector/EntitySelector.java
++++ b/src/main/java/net/minecraft/commands/arguments/selector/EntitySelector.java
+@@ -0,0 +0,0 @@ public class EntitySelector {
+ }
+
+ private void checkPermissions(CommandSourceStack source) throws CommandSyntaxException {
+- if (this.usesSelector && !source.hasPermission(2, "minecraft.command.selector")) { // CraftBukkit
++ if (source.bypassSelectorPermissions || (this.usesSelector && !source.hasPermission(2, "minecraft.command.selector"))) { // CraftBukkit // Paper
+ throw EntityArgument.ERROR_SELECTORS_NOT_ALLOWED.create();
+ }
+ }
diff --git a/src/main/java/net/minecraft/network/FriendlyByteBuf.java b/src/main/java/net/minecraft/network/FriendlyByteBuf.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/network/FriendlyByteBuf.java
@@ -1693,6 +1741,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
JsonObject jsonobject = new JsonObject();
if (!ichatbasecomponent.getStyle().isEmpty()) {
+diff --git a/src/main/java/net/minecraft/network/chat/ComponentUtils.java b/src/main/java/net/minecraft/network/chat/ComponentUtils.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/net/minecraft/network/chat/ComponentUtils.java
++++ b/src/main/java/net/minecraft/network/chat/ComponentUtils.java
+@@ -0,0 +0,0 @@ public class ComponentUtils {
+ if (depth > 100) {
+ return text.copy();
+ } else {
++ // Paper start
++ if (text instanceof io.papermc.paper.adventure.AdventureComponent adventureComponent) {
++ text = adventureComponent.deepConverted();
++ }
++ // Paper end
+ MutableComponent mutableComponent = text.getContents().resolve(source, sender, depth + 1);
+
+ for(Component component : text.getSiblings()) {
diff --git a/src/main/java/net/minecraft/network/chat/OutgoingPlayerChatMessage.java b/src/main/java/net/minecraft/network/chat/OutgoingPlayerChatMessage.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/network/chat/OutgoingPlayerChatMessage.java
@@ -4432,6 +4496,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ public net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer legacyComponentSerializer() {
+ return net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection();
+ }
++
++ @Override
++ public net.kyori.adventure.text.Component resolveWithContext(final net.kyori.adventure.text.Component component, final org.bukkit.command.CommandSender context, final org.bukkit.entity.Entity scoreboardSubject, final boolean bypassPermissions) throws IOException {
++ return io.papermc.paper.adventure.PaperAdventure.resolveWithContext(component, context, scoreboardSubject, bypassPermissions);
++ }
+ // Paper end
+
public static BlockState getBlock(MaterialData material) {
diff --git a/patches/server/Fix-EntityArgument-suggestion-permissions-to-align-w.patch b/patches/server/Fix-EntityArgument-suggestion-permissions-to-align-w.patch
index f0ee32fff5..057b09bf41 100644
--- a/patches/server/Fix-EntityArgument-suggestion-permissions-to-align-w.patch
+++ b/patches/server/Fix-EntityArgument-suggestion-permissions-to-align-w.patch
@@ -19,7 +19,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- EntitySelectorParser argumentparserselector = new EntitySelectorParser(stringreader, icompletionprovider.hasPermission(2), true); // Paper
+ // Paper start
+ final boolean permission = object instanceof CommandSourceStack stack
-+ ? stack.hasPermission(2, "minecraft.command.selector")
++ ? stack.bypassSelectorPermissions || stack.hasPermission(2, "minecraft.command.selector")
+ : icompletionprovider.hasPermission(2);
+ EntitySelectorParser argumentparserselector = new EntitySelectorParser(stringreader, permission, true); // Paper
+ // Paper end
diff --git a/patches/server/MC-Dev-fixes.patch b/patches/server/MC-Dev-fixes.patch
index 8ae926ca28..4226451200 100644
--- a/patches/server/MC-Dev-fixes.patch
+++ b/patches/server/MC-Dev-fixes.patch
@@ -128,6 +128,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
private static final int MIN_PROTOCOL_ID = -1;
private static final int MAX_PROTOCOL_ID = 2;
private static final ConnectionProtocol[] LOOKUP = new ConnectionProtocol[4];
+diff --git a/src/main/java/net/minecraft/network/chat/ComponentUtils.java b/src/main/java/net/minecraft/network/chat/ComponentUtils.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/net/minecraft/network/chat/ComponentUtils.java
++++ b/src/main/java/net/minecraft/network/chat/ComponentUtils.java
+@@ -0,0 +0,0 @@ public class ComponentUtils {
+ ComponentContents string = text.getContents();
+ if (string instanceof TranslatableContents) {
+ TranslatableContents translatableContents = (TranslatableContents)string;
+- String string = translatableContents.getKey();
+- return Language.getInstance().has(string);
++ return Language.getInstance().has(translatableContents.getKey()); // Paper - decompile fix
+ }
+ }
+
diff --git a/src/main/java/net/minecraft/resources/RegistryLoader.java b/src/main/java/net/minecraft/resources/RegistryLoader.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/resources/RegistryLoader.java
diff --git a/patches/server/Thread-Safe-Vanilla-Command-permission-checking.patch b/patches/server/Thread-Safe-Vanilla-Command-permission-checking.patch
index 0f37478e4c..c6d2445035 100644
--- a/patches/server/Thread-Safe-Vanilla-Command-permission-checking.patch
+++ b/patches/server/Thread-Safe-Vanilla-Command-permission-checking.patch
@@ -35,9 +35,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
private final TaskChainer chatMessageChainer;
- public volatile CommandNode currentCommand; // CraftBukkit
+ public java.util.Map currentCommand = new java.util.concurrent.ConcurrentHashMap<>(); // CraftBukkit // Paper
+ public boolean bypassSelectorPermissions = false; // Paper
public CommandSourceStack(CommandSource output, Vec3 pos, Vec2 rot, ServerLevel world, int level, String name, Component displayName, MinecraftServer server, @Nullable Entity entity) {
- this(output, pos, rot, world, level, name, displayName, server, entity, false, (commandcontext, flag, j) -> {
@@ -0,0 +0,0 @@ public class CommandSourceStack implements SharedSuggestionProvider, com.destroy
@Override
public boolean hasPermission(int level) {