Document, add preliminary resource pack support.

This commit is contained in:
Owen1212055 2025-04-16 13:38:58 -04:00
parent 83d4a9dbcf
commit d929733f77
No known key found for this signature in database
GPG Key ID: 2133292072886A30
8 changed files with 84 additions and 22 deletions

View File

@ -1,9 +1,14 @@
package io.papermc.paper.connection; package io.papermc.paper.connection;
import net.kyori.adventure.resource.ResourcePackRequest;
import net.kyori.adventure.resource.ResourcePackRequestLike;
import org.bukkit.ServerLinks; import org.bukkit.ServerLinks;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jspecify.annotations.NullMarked; import org.jspecify.annotations.NullMarked;
import java.util.Map; import java.util.Map;
import java.util.UUID;
/** /**
* Represents a connection that has properties shared between the GAME and CONFIG stage. * Represents a connection that has properties shared between the GAME and CONFIG stage.
@ -11,6 +16,12 @@ import java.util.Map;
@NullMarked @NullMarked
public interface PlayerCommonConnection extends CookieConnection { public interface PlayerCommonConnection extends CookieConnection {
void sendResourcePacks(final @NotNull ResourcePackRequest request);
void removeResourcePacks(final @NotNull UUID id, final @NotNull UUID... others);
void clearResourcePacks();
/** /**
* Sends data to appear in this connection's report logs. * Sends data to appear in this connection's report logs.
* This is useful for debugging server state that may be causing * This is useful for debugging server state that may be causing

View File

@ -3,7 +3,9 @@ package io.papermc.paper.event.connection.configuration;
import io.papermc.paper.connection.PlayerConfigurationConnection; import io.papermc.paper.connection.PlayerConfigurationConnection;
import io.papermc.paper.connection.PlayerLoginConnection; import io.papermc.paper.connection.PlayerLoginConnection;
import org.bukkit.event.Event; import org.bukkit.event.Event;
import org.jetbrains.annotations.ApiStatus;
@ApiStatus.Internal
abstract class PlayerConfigurationConnectionEvent extends Event { abstract class PlayerConfigurationConnectionEvent extends Event {
private final PlayerConfigurationConnection loginConnection; private final PlayerConfigurationConnection loginConnection;

View File

@ -304,6 +304,11 @@ public class AsyncPlayerPreLoginEvent extends Event {
return this.transferred; return this.transferred;
} }
/**
* Gets the connection for the player logging in.
* @return connection
*/
@NotNull
public PlayerLoginConnection getPlayerLoginConnection() { public PlayerLoginConnection getPlayerLoginConnection() {
return playerLoginConnection; return playerLoginConnection;
} }

View File

@ -1,8 +1,8 @@
package org.bukkit.event.player; package org.bukkit.event.player;
import io.papermc.paper.connection.PlayerCommonConnection;
import io.papermc.paper.connection.PlayerConfigurationConnection; import io.papermc.paper.connection.PlayerConfigurationConnection;
import org.bukkit.ServerLinks; import org.bukkit.ServerLinks;
import org.bukkit.entity.Player;
import org.bukkit.event.Event; import org.bukkit.event.Event;
import org.bukkit.event.HandlerList; import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
@ -17,11 +17,11 @@ public class PlayerLinksSendEvent extends Event {
private static final HandlerList HANDLER_LIST = new HandlerList(); private static final HandlerList HANDLER_LIST = new HandlerList();
private final ServerLinks links; private final ServerLinks links;
private final PlayerConfigurationConnection configurationConnection; private final PlayerCommonConnection connection;
@ApiStatus.Internal @ApiStatus.Internal
public PlayerLinksSendEvent(@NotNull final PlayerConfigurationConnection connection, @NotNull final ServerLinks links) { public PlayerLinksSendEvent(@NotNull final PlayerConfigurationConnection connection, @NotNull final ServerLinks links) {
this.configurationConnection = connection; this.connection = connection;
this.links = links; this.links = links;
} }
@ -29,8 +29,9 @@ public class PlayerLinksSendEvent extends Event {
* Gets the connection that received the links. * Gets the connection that received the links.
* @return connection * @return connection
*/ */
public PlayerConfigurationConnection getConfigurationConnection() { @NotNull
return configurationConnection; public PlayerCommonConnection getConnection() {
return connection;
} }
/** /**

View File

@ -336,10 +336,10 @@ index 7de11ba404f0b60e7f7b7c16954811a343688219..bd07e6a5aa1883786d789ea71711a0c0
this.channels this.channels
.add( .add(
diff --git a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java diff --git a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
index fc82af47a6be4afc7380d317b0ab91e95860ef26..4261db0f3b274632964323ff499961d9e7b5e2de 100644 index 7b85b777bec03370d0886a357e7937e14fc63b95..f37d43d1c31037ff810977ecd125f662956c2ee3 100644
--- a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java --- a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +++ b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
@@ -253,11 +253,9 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener, @@ -255,11 +255,9 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
} }
SecretKey secretKey = packet.getSecretKey(_private); SecretKey secretKey = packet.getSecretKey(_private);

View File

@ -67,13 +67,26 @@
} }
} }
@@ -97,21 +_,28 @@ @@ -97,21 +_,40 @@
PacketUtils.ensureRunningOnSameThread(packet, this, this.server); PacketUtils.ensureRunningOnSameThread(packet, this, this.server);
if (packet.action() == ServerboundResourcePackPacket.Action.DECLINED && this.server.isResourcePackRequired()) { if (packet.action() == ServerboundResourcePackPacket.Action.DECLINED && this.server.isResourcePackRequired()) {
LOGGER.info("Disconnecting {} due to resource pack {} rejection", this.playerProfile().getName(), packet.id()); LOGGER.info("Disconnecting {} due to resource pack {} rejection", this.playerProfile().getName(), packet.id());
- this.disconnect(Component.translatable("multiplayer.requiredTexturePrompt.disconnect")); - this.disconnect(Component.translatable("multiplayer.requiredTexturePrompt.disconnect"));
- }
+ this.disconnect(Component.translatable("multiplayer.requiredTexturePrompt.disconnect"), io.papermc.paper.connection.DisconnectionReason.RESOURCE_PACK_REJECTION); // Paper - kick event cause + this.disconnect(Component.translatable("multiplayer.requiredTexturePrompt.disconnect"), io.papermc.paper.connection.DisconnectionReason.RESOURCE_PACK_REJECTION); // Paper - kick event cause
} + }
+ // Paper start - adventure pack callbacks
+ // call the callbacks before the previously-existing event so the event has final say
+ final net.kyori.adventure.resource.ResourcePackCallback callback;
+ if (packet.action().isTerminal()) {
+ callback = this.packCallbacks.remove(packet.id());
+ } else {
+ callback = this.packCallbacks.get(packet.id());
+ }
+ if (callback != null) {
+ callback.packEventReceived(packet.id(), net.kyori.adventure.resource.ResourcePackStatus.valueOf(packet.action().name()), null); // TODO TODO:
+ }
+ // Paper end
} }
@Override @Override

View File

@ -2591,7 +2591,7 @@
if (!this.receivedMovementThisTick) { if (!this.receivedMovementThisTick) {
this.player.setKnownMovement(Vec3.ZERO); this.player.setKnownMovement(Vec3.ZERO);
} }
@@ -2048,4 +_,156 @@ @@ -2048,4 +_,144 @@
interface EntityInteraction { interface EntityInteraction {
InteractionResult run(ServerPlayer player, Entity entity, InteractionHand hand); InteractionResult run(ServerPlayer player, Entity entity, InteractionHand hand);
} }
@ -2701,18 +2701,6 @@
+ @Override + @Override
+ public void handleResourcePackResponse(final net.minecraft.network.protocol.common.ServerboundResourcePackPacket packet) { + public void handleResourcePackResponse(final net.minecraft.network.protocol.common.ServerboundResourcePackPacket packet) {
+ super.handleResourcePackResponse(packet); + super.handleResourcePackResponse(packet);
+ // Paper start - adventure pack callbacks
+ // call the callbacks before the previously-existing event so the event has final say
+ final net.kyori.adventure.resource.ResourcePackCallback callback;
+ if (packet.action().isTerminal()) {
+ callback = this.packCallbacks.remove(packet.id());
+ } else {
+ callback = this.packCallbacks.get(packet.id());
+ }
+ if (callback != null) {
+ callback.packEventReceived(packet.id(), net.kyori.adventure.resource.ResourcePackStatus.valueOf(packet.action().name()), this.getCraftPlayer());
+ }
+ // Paper end
+ // Paper start - store last pack status + // Paper start - store last pack status
+ org.bukkit.event.player.PlayerResourcePackStatusEvent.Status packStatus = org.bukkit.event.player.PlayerResourcePackStatusEvent.Status.values()[packet.action().ordinal()]; + org.bukkit.event.player.PlayerResourcePackStatusEvent.Status packStatus = org.bukkit.event.player.PlayerResourcePackStatusEvent.Status.values()[packet.action().ordinal()];
+ this.player.getBukkitEntity().resourcePackStatus = packStatus; + this.player.getBukkitEntity().resourcePackStatus = packStatus;

View File

@ -1,15 +1,25 @@
package io.papermc.paper.connection; package io.papermc.paper.connection;
import io.papermc.paper.adventure.PaperAdventure; import io.papermc.paper.adventure.PaperAdventure;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import net.kyori.adventure.resource.ResourcePackRequest;
import net.kyori.adventure.resource.ResourcePackRequestLike;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.minecraft.network.protocol.common.ClientboundCustomReportDetailsPacket; import net.minecraft.network.protocol.common.ClientboundCustomReportDetailsPacket;
import net.minecraft.network.protocol.common.ClientboundResourcePackPopPacket;
import net.minecraft.network.protocol.common.ClientboundResourcePackPushPacket;
import net.minecraft.network.protocol.common.ClientboundServerLinksPacket; import net.minecraft.network.protocol.common.ClientboundServerLinksPacket;
import net.minecraft.network.protocol.common.ClientboundTransferPacket; import net.minecraft.network.protocol.common.ClientboundTransferPacket;
import net.minecraft.server.network.ServerCommonPacketListenerImpl; import net.minecraft.server.network.ServerCommonPacketListenerImpl;
import net.minecraft.server.network.ServerConfigurationPacketListenerImpl; import net.minecraft.server.network.ServerConfigurationPacketListenerImpl;
import org.bukkit.ServerLinks; import org.bukkit.ServerLinks;
import org.bukkit.craftbukkit.CraftServerLinks; import org.bukkit.craftbukkit.CraftServerLinks;
import org.jetbrains.annotations.NotNull;
public abstract class PaperCommonConnection<T extends ServerCommonPacketListenerImpl> extends CommonCookieConnection implements PlayerCommonConnection { public abstract class PaperCommonConnection<T extends ServerCommonPacketListenerImpl> extends CommonCookieConnection implements PlayerCommonConnection {
@ -20,6 +30,38 @@ public abstract class PaperCommonConnection<T extends ServerCommonPacketListener
this.handle = serverConfigurationPacketListenerImpl; this.handle = serverConfigurationPacketListenerImpl;
} }
@Override
public void sendResourcePacks(@NotNull ResourcePackRequest request) {
final List<ClientboundResourcePackPushPacket> packs = new java.util.ArrayList<>(request.packs().size());
if (request.replace()) {
this.clearResourcePacks();
}
final net.minecraft.network.chat.Component prompt = io.papermc.paper.adventure.PaperAdventure.asVanilla(request.prompt());
for (final java.util.Iterator<net.kyori.adventure.resource.ResourcePackInfo> iter = request.packs().iterator(); iter.hasNext();) {
final net.kyori.adventure.resource.ResourcePackInfo pack = iter.next();
packs.add(new ClientboundResourcePackPushPacket(pack.id(), pack.uri().toASCIIString(), pack.hash(), request.required(), iter.hasNext() ? Optional.empty() : Optional.ofNullable(prompt)));
if (request.callback() != net.kyori.adventure.resource.ResourcePackCallback.noOp()) {
this.handle.packCallbacks.put(pack.id(), request.callback()); // just override if there is a previously existing callback
}
}
this.sendBundle(packs);
}
@Override
public void removeResourcePacks(@NotNull UUID id, @NotNull UUID... others) {
this.sendBundle(net.kyori.adventure.util.MonkeyBars.nonEmptyArrayToList(pack -> new ClientboundResourcePackPopPacket(Optional.of(pack)), id, others));
}
@Override
public void clearResourcePacks() {
this.handle.connection.send(new ClientboundResourcePackPopPacket(Optional.empty()));
}
@SuppressWarnings({"unchecked", "rawtypes"})
void sendBundle(final List<? extends net.minecraft.network.protocol.Packet<? extends net.minecraft.network.protocol.common.ClientCommonPacketListener>> packet) {
this.handle.connection.send(new net.minecraft.network.protocol.game.ClientboundBundlePacket((List) packet));
}
@Override @Override
public void sendReportDetails(final Map<String, String> details) { public void sendReportDetails(final Map<String, String> details) {
this.handle.send(new ClientboundCustomReportDetailsPacket(details)); this.handle.send(new ClientboundCustomReportDetailsPacket(details));