3
0
Mirror von https://github.com/PaperMC/Velocity.git synchronisiert 2024-11-16 21:10:30 +01:00

Implement resource pack send event. (#625)

Dieser Commit ist enthalten in:
Corey Shupe 2022-02-01 23:30:45 -05:00 committet von GitHub
Ursprung b8f1df4470
Commit 596d4758ba
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden
GPG-Schlüssel-ID: 4AEE18F83AFDEB23
6 geänderte Dateien mit 191 neuen und 14 gelöschten Zeilen

Datei anzeigen

@ -0,0 +1,70 @@
/*
* Copyright (C) 2018 Velocity Contributors
*
* The Velocity API is licensed under the terms of the MIT License. For more details,
* reference the LICENSE file in the api top-level directory.
*/
package com.velocitypowered.api.event.player;
import com.velocitypowered.api.event.ResultedEvent;
import com.velocitypowered.api.event.annotation.AwaitingEvent;
import com.velocitypowered.api.proxy.ServerConnection;
import com.velocitypowered.api.proxy.player.ResourcePackInfo;
/**
* This event is fired when the downstream server tries to send a player a ResourcePack packet.
* The proxy will wait on this event to finish before forwarding the resource pack to the user.
* If this event is denied, it will retroactively send a DENIED status to the downstream
* server in response.
* If the downstream server has it set to "forced" it will forcefully disconnect the user.
*/
@AwaitingEvent
public class ServerResourcePackSendEvent implements ResultedEvent<ResultedEvent.GenericResult> {
private GenericResult result;
private final ResourcePackInfo receivedResourcePack;
private ResourcePackInfo providedResourcePack;
private final ServerConnection serverConnection;
/**
* Constructs a new ServerResourcePackSendEvent.
*
* @param receivedResourcePack The resource pack the server sent.
* @param serverConnection The connection this occurred on.
*/
public ServerResourcePackSendEvent(
ResourcePackInfo receivedResourcePack,
ServerConnection serverConnection
) {
this.result = ResultedEvent.GenericResult.allowed();
this.receivedResourcePack = receivedResourcePack;
this.serverConnection = serverConnection;
this.providedResourcePack = receivedResourcePack;
}
public ServerConnection getServerConnection() {
return serverConnection;
}
public ResourcePackInfo getReceivedResourcePack() {
return receivedResourcePack;
}
public ResourcePackInfo getProvidedResourcePack() {
return providedResourcePack;
}
public void setProvidedResourcePack(ResourcePackInfo providedResourcePack) {
this.providedResourcePack = providedResourcePack;
}
@Override
public GenericResult getResult() {
return this.result;
}
@Override
public void setResult(GenericResult result) {
this.result = result;
}
}

Datei anzeigen

@ -46,12 +46,48 @@ public interface ResourcePackInfo {
byte[] getHash();
/**
* Gets the {@link Origin} of the resource-pack.
* Gets the {@link Origin} of this resource-pack.
*
* @return the origin of the resource pack
*/
Origin getOrigin();
/**
* Gets the original {@link Origin} of the resource-pack.
* The original origin may differ if the resource pack was altered in the event
* {@link com.velocitypowered.api.event.player.ServerResourcePackSendEvent}.
*
* @return the origin of the resource pack
*/
Origin getOriginalOrigin();
/**
* Returns a copy of this {@link ResourcePackInfo} instance as a builder so that it can
* be modified.
* It is <b>not</b> guaranteed that
* {@code resourcePackInfo.asBuilder().build().equals(resourcePackInfo)} is true. That is due to
* the transient {@link ResourcePackInfo#getOrigin()} and
* {@link ResourcePackInfo#getOriginalOrigin()} fields.
*
*
* @return a content-copy of this instance as a {@link ResourcePackInfo.Builder}
*/
ResourcePackInfo.Builder asBuilder();
/**
* Returns a copy of this {@link ResourcePackInfo} instance as a builder with the new URL as the pack URL so that
* it can be modified.
* It is <b>not</b> guaranteed that
* {@code resourcePackInfo.asBuilder(resourcePackInfo.getUrl()).build().equals(resourcePackInfo)} is true.
* That is due to the transient {@link ResourcePackInfo#getOrigin()} and
* {@link ResourcePackInfo#getOriginalOrigin()} fields.
*
* @param newUrl The new URL to use in the updated builder.
*
* @return a content-copy of this instance as a {@link ResourcePackInfo.Builder}
*/
ResourcePackInfo.Builder asBuilder(String newUrl);
interface Builder {
/**

Datei anzeigen

@ -21,12 +21,12 @@ import static com.velocitypowered.proxy.connection.backend.BungeeCordMessageResp
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.mojang.brigadier.builder.ArgumentBuilder;
import com.mojang.brigadier.tree.CommandNode;
import com.mojang.brigadier.tree.RootCommandNode;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.event.command.PlayerAvailableCommandsEvent;
import com.velocitypowered.api.event.connection.PluginMessageEvent;
import com.velocitypowered.api.event.player.PlayerResourcePackStatusEvent;
import com.velocitypowered.api.event.player.ServerResourcePackSendEvent;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.api.proxy.messages.ChannelIdentifier;
import com.velocitypowered.api.proxy.player.ResourcePackInfo;
@ -45,6 +45,7 @@ import com.velocitypowered.proxy.protocol.packet.KeepAlive;
import com.velocitypowered.proxy.protocol.packet.PlayerListItem;
import com.velocitypowered.proxy.protocol.packet.PluginMessage;
import com.velocitypowered.proxy.protocol.packet.ResourcePackRequest;
import com.velocitypowered.proxy.protocol.packet.ResourcePackResponse;
import com.velocitypowered.proxy.protocol.packet.TabCompleteResponse;
import com.velocitypowered.proxy.protocol.util.PluginMessageUtil;
import io.netty.buffer.ByteBuf;
@ -52,7 +53,7 @@ import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.handler.timeout.ReadTimeoutException;
import java.util.Collection;
import java.util.regex.Pattern;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -140,15 +141,48 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
ResourcePackInfo.Builder builder = new VelocityResourcePackInfo.BuilderImpl(
Preconditions.checkNotNull(packet.getUrl()))
.setPrompt(packet.getPrompt())
.setShouldForce(packet.isRequired());
// Why SpotBugs decides that this is unsafe I have no idea;
if (packet.getHash() != null && !Preconditions.checkNotNull(packet.getHash()).isEmpty()) {
if (PLAUSIBLE_SHA1_HASH.matcher(packet.getHash()).matches()) {
builder.setHash(ByteBufUtil.decodeHexDump(packet.getHash()));
.setShouldForce(packet.isRequired())
.setOrigin(ResourcePackInfo.Origin.DOWNSTREAM_SERVER);
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);
server.getEventManager().fire(event).thenAcceptAsync(serverResourcePackSendEvent -> {
if (playerConnection.isClosed()) {
return;
}
if (serverResourcePackSendEvent.getResult().isAllowed()) {
ResourcePackInfo toSend = serverResourcePackSendEvent.getProvidedResourcePack();
if (toSend != serverResourcePackSendEvent.getReceivedResourcePack()) {
((VelocityResourcePackInfo) toSend)
.setOriginalOrigin(ResourcePackInfo.Origin.DOWNSTREAM_SERVER);
}
serverConn.getPlayer().queueResourcePack(builder.build());
} else if (serverConn.getConnection() != null) {
serverConn.getConnection().write(new ResourcePackResponse(
packet.getHash(),
PlayerResourcePackStatusEvent.Status.DECLINED
));
}
}, playerConnection.eventLoop()).exceptionally((ex) -> {
if (serverConn.getConnection() != null) {
serverConn.getConnection().write(new ResourcePackResponse(
packet.getHash(),
PlayerResourcePackStatusEvent.Status.DECLINED
));
}
logger.error("Exception while handling resource pack send for {}", playerConnection, ex);
return null;
});
return true;
}

Datei anzeigen

@ -985,7 +985,8 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
connection.eventLoop().execute(this::tickResourcePackQueue);
}
return queued != null && queued.getOrigin() == ResourcePackInfo.Origin.DOWNSTREAM_SERVER;
return queued != null
&& queued.getOriginalOrigin() == ResourcePackInfo.Origin.DOWNSTREAM_SERVER;
}
/**

Datei anzeigen

@ -28,6 +28,7 @@ public final class VelocityResourcePackInfo implements ResourcePackInfo {
private final boolean shouldForce;
private final @Nullable Component prompt; // 1.17+ only
private final Origin origin;
private Origin originalOrigin;
private VelocityResourcePackInfo(String url, @Nullable byte[] hash, boolean shouldForce,
@Nullable Component prompt, Origin origin) {
@ -36,6 +37,7 @@ public final class VelocityResourcePackInfo implements ResourcePackInfo {
this.shouldForce = shouldForce;
this.prompt = prompt;
this.origin = origin;
this.originalOrigin = origin;
}
@Override
@ -63,6 +65,31 @@ public final class VelocityResourcePackInfo implements ResourcePackInfo {
return origin;
}
public void setOriginalOrigin(Origin originalOrigin) {
this.originalOrigin = originalOrigin;
}
@Override
public Origin getOriginalOrigin() {
return originalOrigin;
}
@Override
public Builder asBuilder() {
return new BuilderImpl(url)
.setShouldForce(shouldForce)
.setHash(hash)
.setPrompt(prompt);
}
@Override
public Builder asBuilder(String newUrl) {
return new BuilderImpl(newUrl)
.setShouldForce(shouldForce)
.setHash(hash)
.setPrompt(prompt);
}
public static final class BuilderImpl implements ResourcePackInfo.Builder {
private final String url;
private boolean shouldForce;
@ -102,8 +129,9 @@ public final class VelocityResourcePackInfo implements ResourcePackInfo {
return new VelocityResourcePackInfo(url, hash, shouldForce, prompt, origin);
}
public void setOrigin(Origin origin) {
public BuilderImpl setOrigin(Origin origin) {
this.origin = origin;
return this;
}
}

Datei anzeigen

@ -31,6 +31,14 @@ public class ResourcePackResponse implements MinecraftPacket {
private String hash = "";
private @MonotonicNonNull Status status;
public ResourcePackResponse() {
}
public ResourcePackResponse(String hash, @MonotonicNonNull Status status) {
this.hash = hash;
this.status = status;
}
public Status getStatus() {
if (status == null) {
throw new IllegalStateException("Packet not yet deserialized");