Do not apply a resource pack that has already been applied (#1236)
* Do not apply a resource pack that has already been applied * Throw IllegalStateException in case of applying a resource pack already applied from the API * Updated some dependencies * Added support for ServerResourcePackSendEvent resource pack modification
This commit is contained in:
@@ -174,36 +174,49 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(ResourcePackRequestPacket packet) {
|
||||
ResourcePackInfo.Builder builder = new VelocityResourcePackInfo.BuilderImpl(
|
||||
public boolean handle(final ResourcePackRequestPacket packet) {
|
||||
final ResourcePackInfo.Builder builder = new VelocityResourcePackInfo.BuilderImpl(
|
||||
Preconditions.checkNotNull(packet.getUrl()))
|
||||
.setId(packet.getId())
|
||||
.setPrompt(packet.getPrompt() == null ? null : packet.getPrompt().getComponent())
|
||||
.setShouldForce(packet.isRequired())
|
||||
.setOrigin(ResourcePackInfo.Origin.DOWNSTREAM_SERVER);
|
||||
|
||||
String hash = packet.getHash();
|
||||
final String hash = packet.getHash();
|
||||
if (hash != null && !hash.isEmpty()) {
|
||||
if (PLAUSIBLE_SHA1_HASH.matcher(hash).matches()) {
|
||||
builder.setHash(ByteBufUtil.decodeHexDump(hash));
|
||||
}
|
||||
}
|
||||
|
||||
ServerResourcePackSendEvent event = new ServerResourcePackSendEvent(
|
||||
builder.build(), this.serverConn);
|
||||
|
||||
final ResourcePackInfo resourcePackInfo = builder.build();
|
||||
final ServerResourcePackSendEvent event = new ServerResourcePackSendEvent(
|
||||
resourcePackInfo, this.serverConn);
|
||||
server.getEventManager().fire(event).thenAcceptAsync(serverResourcePackSendEvent -> {
|
||||
if (playerConnection.isClosed()) {
|
||||
return;
|
||||
}
|
||||
if (serverResourcePackSendEvent.getResult().isAllowed()) {
|
||||
final ResourcePackInfo toSend = serverResourcePackSendEvent.getProvidedResourcePack();
|
||||
boolean modifiedPack = false;
|
||||
if (toSend != serverResourcePackSendEvent.getReceivedResourcePack()) {
|
||||
((VelocityResourcePackInfo) toSend)
|
||||
.setOriginalOrigin(ResourcePackInfo.Origin.DOWNSTREAM_SERVER);
|
||||
modifiedPack = true;
|
||||
}
|
||||
if (serverConn.getPlayer().resourcePackHandler().hasPackAppliedByHash(toSend.getHash())) {
|
||||
// Do not apply a resource pack that has already been applied
|
||||
if (serverConn.getConnection() != null) {
|
||||
serverConn.getConnection().write(new ResourcePackResponsePacket(
|
||||
packet.getId(), packet.getHash(), PlayerResourcePackStatusEvent.Status.ACCEPTED));
|
||||
}
|
||||
if (modifiedPack) {
|
||||
logger.warn("A plugin has tried to modify a ResourcePack provided by the backend server "
|
||||
+ "with a ResourcePack already applied, the applying of the resource pack will be skipped.");
|
||||
}
|
||||
} else {
|
||||
serverConn.getPlayer().resourcePackHandler().queueResourcePack(toSend);
|
||||
}
|
||||
|
||||
serverConn.getPlayer().resourcePackHandler().queueResourcePack(toSend);
|
||||
} else if (serverConn.getConnection() != null) {
|
||||
serverConn.getConnection().write(new ResourcePackResponsePacket(
|
||||
packet.getId(),
|
||||
|
@@ -45,7 +45,6 @@ import com.velocitypowered.proxy.protocol.packet.config.TagsUpdatePacket;
|
||||
import com.velocitypowered.proxy.protocol.util.PluginMessageUtil;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.regex.Pattern;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
@@ -54,8 +53,6 @@ import org.apache.logging.log4j.Logger;
|
||||
* 1.20.2+ switching. Yes, some of this is exceptionally stupid.
|
||||
*/
|
||||
public class ConfigSessionHandler implements MinecraftSessionHandler {
|
||||
|
||||
private static final Pattern PLAUSIBLE_SHA1_HASH = Pattern.compile("^[a-z0-9]{40}$");
|
||||
private static final Logger logger = LogManager.getLogger(ConfigSessionHandler.class);
|
||||
private final VelocityServer server;
|
||||
private final VelocityServerConnection serverConn;
|
||||
@@ -118,25 +115,39 @@ public class ConfigSessionHandler implements MinecraftSessionHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(ResourcePackRequestPacket packet) {
|
||||
public boolean handle(final ResourcePackRequestPacket packet) {
|
||||
final MinecraftConnection playerConnection = serverConn.getPlayer().getConnection();
|
||||
|
||||
ServerResourcePackSendEvent event =
|
||||
new ServerResourcePackSendEvent(packet.toServerPromptedPack(), this.serverConn);
|
||||
final ResourcePackInfo resourcePackInfo = packet.toServerPromptedPack();
|
||||
final ServerResourcePackSendEvent event =
|
||||
new ServerResourcePackSendEvent(resourcePackInfo, this.serverConn);
|
||||
|
||||
server.getEventManager().fire(event).thenAcceptAsync(serverResourcePackSendEvent -> {
|
||||
if (playerConnection.isClosed()) {
|
||||
return;
|
||||
}
|
||||
if (serverResourcePackSendEvent.getResult().isAllowed()) {
|
||||
ResourcePackInfo toSend = serverResourcePackSendEvent.getProvidedResourcePack();
|
||||
final ResourcePackInfo toSend = serverResourcePackSendEvent.getProvidedResourcePack();
|
||||
boolean modifiedPack = false;
|
||||
if (toSend != serverResourcePackSendEvent.getReceivedResourcePack()) {
|
||||
((VelocityResourcePackInfo) toSend).setOriginalOrigin(
|
||||
ResourcePackInfo.Origin.DOWNSTREAM_SERVER);
|
||||
modifiedPack = true;
|
||||
}
|
||||
if (serverConn.getPlayer().resourcePackHandler().hasPackAppliedByHash(toSend.getHash())) {
|
||||
// Do not apply a resource pack that has already been applied
|
||||
if (serverConn.getConnection() != null) {
|
||||
serverConn.getConnection().write(new ResourcePackResponsePacket(
|
||||
packet.getId(), packet.getHash(), PlayerResourcePackStatusEvent.Status.ACCEPTED));
|
||||
}
|
||||
if (modifiedPack) {
|
||||
logger.warn("A plugin has tried to modify a ResourcePack provided by the backend server "
|
||||
+ "with a ResourcePack already applied, the applying of the resource pack will be skipped.");
|
||||
}
|
||||
} else {
|
||||
resourcePackToApply = null;
|
||||
serverConn.getPlayer().resourcePackHandler().queueResourcePack(toSend);
|
||||
}
|
||||
|
||||
resourcePackToApply = null;
|
||||
serverConn.getPlayer().resourcePackHandler().queueResourcePack(toSend);
|
||||
} else if (serverConn.getConnection() != null) {
|
||||
serverConn.getConnection().write(new ResourcePackResponsePacket(
|
||||
packet.getId(), packet.getHash(), PlayerResourcePackStatusEvent.Status.DECLINED));
|
||||
|
@@ -1027,6 +1027,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player,
|
||||
|
||||
@Override
|
||||
public void sendResourcePackOffer(ResourcePackInfo packInfo) {
|
||||
this.resourcePackHandler.checkAlreadyAppliedPack(packInfo.getHash());
|
||||
if (this.getProtocolVersion().noLessThan(ProtocolVersion.MINECRAFT_1_8)) {
|
||||
Preconditions.checkNotNull(packInfo, "packInfo");
|
||||
this.resourcePackHandler.queueResourcePack(packInfo);
|
||||
|
@@ -23,6 +23,7 @@ import com.velocitypowered.api.proxy.player.ResourcePackInfo;
|
||||
import com.velocitypowered.proxy.VelocityServer;
|
||||
import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
@@ -169,6 +170,12 @@ public sealed class LegacyResourcePackHandler extends ResourcePackHandler
|
||||
return handleResponseResult(queued, bundle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPackAppliedByHash(final byte[] hash) {
|
||||
return this.appliedResourcePack != null
|
||||
&& Arrays.equals(this.appliedResourcePack.getHash(), hash);
|
||||
}
|
||||
|
||||
protected boolean shouldDisconnectForForcePack(final PlayerResourcePackStatusEvent event) {
|
||||
return event.getStatus() == PlayerResourcePackStatusEvent.Status.DECLINED
|
||||
&& event.getPackInfo() != null && event.getPackInfo().getShouldForce();
|
||||
|
@@ -23,6 +23,7 @@ import com.velocitypowered.api.event.player.PlayerResourcePackStatusEvent;
|
||||
import com.velocitypowered.api.proxy.player.ResourcePackInfo;
|
||||
import com.velocitypowered.proxy.VelocityServer;
|
||||
import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@@ -167,4 +168,17 @@ public final class ModernResourcePackHandler extends ResourcePackHandler {
|
||||
|
||||
return handleResponseResult(queued, bundle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPackAppliedByHash(final byte[] hash) {
|
||||
if (hash == null) {
|
||||
return false;
|
||||
}
|
||||
for (final Map.Entry<UUID, ResourcePackInfo> appliedPack : appliedResourcePacks.entrySet()) {
|
||||
if (Arrays.equals(appliedPack.getValue().getHash(), hash)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@@ -92,7 +92,9 @@ public abstract sealed class ResourcePackHandler
|
||||
*/
|
||||
public void queueResourcePack(final @NotNull ResourcePackRequest request) {
|
||||
for (final net.kyori.adventure.resource.ResourcePackInfo pack : request.packs()) {
|
||||
queueResourcePack(VelocityResourcePackInfo.fromAdventureRequest(request, pack));
|
||||
final ResourcePackInfo resourcePackInfo = VelocityResourcePackInfo.fromAdventureRequest(request, pack);
|
||||
this.checkAlreadyAppliedPack(resourcePackInfo.getHash());
|
||||
queueResourcePack(resourcePackInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,4 +158,18 @@ public abstract sealed class ResourcePackHandler
|
||||
}
|
||||
return handled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a pack has already been applied.
|
||||
*
|
||||
* @param hash the resource pack hash
|
||||
*/
|
||||
public abstract boolean hasPackAppliedByHash(final byte[] hash);
|
||||
|
||||
@SuppressWarnings("checkstyle:MissingJavadocMethod")
|
||||
public void checkAlreadyAppliedPack(final byte[] hash) {
|
||||
if (this.hasPackAppliedByHash(hash)) {
|
||||
throw new IllegalStateException("Cannot apply a resource pack already applied");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user