Added option to fake accept resource packs

This commit is contained in:
RaphiMC 2024-06-07 18:32:24 +02:00
parent 581160fa3f
commit 7948f7508f
No known key found for this signature in database
GPG key ID: 0F6BB0657A03AC94
9 changed files with 169 additions and 1 deletions

View file

@ -73,6 +73,7 @@ public class ViaProxyConfig extends Config implements com.viaversion.viaversion.
private final OptionSpec<String> optionResourcePackUrl;
private final OptionSpec<WildcardDomainHandling> optionWildcardDomainHandling;
private final OptionSpec<Boolean> optionSimpleVoiceChatSupport;
private final OptionSpec<Boolean> optionFakeAcceptResourcePacks;
private SocketAddress bindAddress = AddressUtil.parse("0.0.0.0:25568", null);
private SocketAddress targetAddress = AddressUtil.parse("127.0.0.1:25565", null);
@ -94,6 +95,7 @@ public class ViaProxyConfig extends Config implements com.viaversion.viaversion.
private String resourcePackUrl = "";
private WildcardDomainHandling wildcardDomainHandling = WildcardDomainHandling.NONE;
private boolean simpleVoiceChatSupport = false;
private boolean fakeAcceptResourcePacks = false;
public ViaProxyConfig(final File configFile) {
super(configFile, LOGGER);
@ -120,6 +122,7 @@ public class ViaProxyConfig extends Config implements com.viaversion.viaversion.
this.optionResourcePackUrl = this.optionParser.accepts("resource-pack-url").withRequiredArg().ofType(String.class).defaultsTo(this.resourcePackUrl);
this.optionWildcardDomainHandling = this.optionParser.accepts("wildcard-domain-handling").withRequiredArg().ofType(WildcardDomainHandling.class).defaultsTo(this.wildcardDomainHandling);
this.optionSimpleVoiceChatSupport = this.optionParser.accepts("simple-voice-chat-support").withRequiredArg().ofType(Boolean.class).defaultsTo(this.simpleVoiceChatSupport);
this.optionFakeAcceptResourcePacks = this.optionParser.accepts("fake-accept-resource-packs").withRequiredArg().ofType(Boolean.class).defaultsTo(this.fakeAcceptResourcePacks);
}
@Override
@ -153,6 +156,7 @@ public class ViaProxyConfig extends Config implements com.viaversion.viaversion.
this.resourcePackUrl = this.getString("resource-pack-url", this.resourcePackUrl);
this.wildcardDomainHandling = WildcardDomainHandling.byName(this.getString("wildcard-domain-handling", this.wildcardDomainHandling.name()));
this.simpleVoiceChatSupport = this.getBoolean("simple-voice-chat-support", this.simpleVoiceChatSupport);
this.fakeAcceptResourcePacks = this.getBoolean("fake-accept-resource-packs", this.fakeAcceptResourcePacks);
}
public void loadFromArguments(final String[] args) throws IOException {
@ -190,6 +194,7 @@ public class ViaProxyConfig extends Config implements com.viaversion.viaversion.
this.resourcePackUrl = options.valueOf(this.optionResourcePackUrl);
this.wildcardDomainHandling = options.valueOf(this.optionWildcardDomainHandling);
this.simpleVoiceChatSupport = options.valueOf(this.optionSimpleVoiceChatSupport);
this.fakeAcceptResourcePacks = options.valueOf(this.optionFakeAcceptResourcePacks);
ViaProxy.EVENT_MANAGER.call(new PostOptionsParseEvent(options));
return;
} catch (OptionException e) {
@ -406,6 +411,15 @@ public class ViaProxyConfig extends Config implements com.viaversion.viaversion.
this.set("simple-voice-chat-support", simpleVoiceChatSupport);
}
public boolean shouldFakeAcceptResourcePacks() {
return this.fakeAcceptResourcePacks;
}
public void setFakeAcceptResourcePacks(final boolean fakeAcceptResourcePacks) {
this.fakeAcceptResourcePacks = fakeAcceptResourcePacks;
this.set("fake-accept-resource-packs", fakeAcceptResourcePacks);
}
private void checkTargetVersion() {
if (this.targetVersion == null) {
this.targetVersion = ProtocolTranslator.AUTO_DETECT_PROTOCOL;

View file

@ -229,6 +229,9 @@ public class Client2ProxyHandler extends SimpleChannelInboundHandler<IPacket> {
if (ViaProxy.getConfig().shouldSupportSimpleVoiceChat() && serverVersion.newerThan(ProtocolVersion.v1_14) && clientVersion.newerThan(ProtocolVersion.v1_14)) {
this.proxyConnection.getPacketHandlers().add(new SimpleVoiceChatPacketHandler(this.proxyConnection));
}
if (ViaProxy.getConfig().shouldFakeAcceptResourcePacks() && serverVersion.newerThanOrEqualTo(LegacyProtocolVersion.r1_3_1tor1_3_2)) {
this.proxyConnection.getPacketHandlers().add(new ResourcePackSpooferPacketHandler(this.proxyConnection));
}
if (clientVersion.newerThanOrEqualTo(ProtocolVersion.v1_8)) {
this.proxyConnection.getPacketHandlers().add(new BrandCustomPayloadPacketHandler(this.proxyConnection));
}

View file

@ -33,6 +33,7 @@ import net.raphimc.viaproxy.proxy.session.ProxyConnection;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
public class ResourcePackPacketHandler extends PacketHandler {
@ -63,7 +64,22 @@ public class ResourcePackPacketHandler extends PacketHandler {
private void sendResourcePack() {
if (!ViaProxy.getConfig().getResourcePackUrl().isBlank()) {
this.proxyConnection.getChannel().eventLoop().schedule(() -> {
if (this.proxyConnection.getClientVersion().newerThanOrEqualTo(ProtocolVersion.v1_8)) {
if (this.proxyConnection.getClientVersion().newerThanOrEqualTo(ProtocolVersion.v1_20_3)) {
final ByteBuf resourcePackPushPacket = Unpooled.buffer();
PacketTypes.writeVarInt(resourcePackPushPacket, MCPackets.S2C_RESOURCE_PACK_PUSH.getId(this.proxyConnection.getClientVersion().getVersion()));
PacketTypes.writeUuid(resourcePackPushPacket, UUID.randomUUID()); // pack id
PacketTypes.writeString(resourcePackPushPacket, ViaProxy.getConfig().getResourcePackUrl()); // url
PacketTypes.writeString(resourcePackPushPacket, ""); // hash
resourcePackPushPacket.writeBoolean(Via.getConfig().isForcedUse1_17ResourcePack()); // required
final JsonElement promptMessage = Via.getConfig().get1_17ResourcePackPrompt();
if (promptMessage != null) {
resourcePackPushPacket.writeBoolean(true); // has message
PacketTypes.writeString(resourcePackPushPacket, promptMessage.toString()); // message
} else {
resourcePackPushPacket.writeBoolean(false); // has message
}
this.proxyConnection.getC2P().writeAndFlush(resourcePackPushPacket).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
} else if (this.proxyConnection.getClientVersion().newerThanOrEqualTo(ProtocolVersion.v1_8)) {
final ByteBuf resourcePackPacket = Unpooled.buffer();
PacketTypes.writeVarInt(resourcePackPacket, MCPackets.S2C_RESOURCE_PACK.getId(this.proxyConnection.getClientVersion().getVersion()));
PacketTypes.writeString(resourcePackPacket, ViaProxy.getConfig().getResourcePackUrl()); // url

View file

@ -0,0 +1,116 @@
/*
* This file is part of ViaProxy - https://github.com/RaphiMC/ViaProxy
* Copyright (C) 2021-2024 RK_01/RaphiMC and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.raphimc.viaproxy.proxy.packethandler;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import net.raphimc.netminecraft.constants.ConnectionState;
import net.raphimc.netminecraft.constants.MCPackets;
import net.raphimc.netminecraft.packet.IPacket;
import net.raphimc.netminecraft.packet.PacketTypes;
import net.raphimc.netminecraft.packet.UnknownPacket;
import net.raphimc.viabedrock.protocol.data.enums.java.ResourcePackAction;
import net.raphimc.viaproxy.proxy.session.ProxyConnection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
public class ResourcePackSpooferPacketHandler extends PacketHandler {
private final int s2cResourcePackId;
private final int s2cConfigResourcePackId;
private final int resourcePackPushId;
private final int configResourcePackPushId;
private final int resourcePackPopId;
private final int configResourcePackPopId;
private final int c2sResourcePackId;
private final int c2sConfigResourcePackId;
private final Set<UUID> resourcePacks = new HashSet<>();
public ResourcePackSpooferPacketHandler(ProxyConnection proxyConnection) {
super(proxyConnection);
this.s2cResourcePackId = MCPackets.S2C_RESOURCE_PACK.getId(this.proxyConnection.getClientVersion().getVersion());
this.s2cConfigResourcePackId = MCPackets.S2C_CONFIG_RESOURCE_PACK.getId(this.proxyConnection.getClientVersion().getVersion());
this.resourcePackPushId = MCPackets.S2C_RESOURCE_PACK_PUSH.getId(this.proxyConnection.getClientVersion().getVersion());
this.configResourcePackPushId = MCPackets.S2C_CONFIG_RESOURCE_PACK_PUSH.getId(this.proxyConnection.getClientVersion().getVersion());
this.resourcePackPopId = MCPackets.S2C_RESOURCE_PACK_POP.getId(this.proxyConnection.getClientVersion().getVersion());
this.configResourcePackPopId = MCPackets.S2C_CONFIG_RESOURCE_PACK_POP.getId(this.proxyConnection.getClientVersion().getVersion());
this.c2sResourcePackId = MCPackets.C2S_RESOURCE_PACK.getId(this.proxyConnection.getClientVersion().getVersion());
this.c2sConfigResourcePackId = MCPackets.C2S_CONFIG_RESOURCE_PACK.getId(this.proxyConnection.getClientVersion().getVersion());
}
@Override
public boolean handleP2S(IPacket packet, List<ChannelFutureListener> listeners) {
if (packet instanceof UnknownPacket unknownPacket
&& (unknownPacket.packetId == this.resourcePackPushId && this.proxyConnection.getP2sConnectionState() == ConnectionState.PLAY
|| unknownPacket.packetId == this.configResourcePackPushId && this.proxyConnection.getP2sConnectionState() == ConnectionState.CONFIGURATION)) {
final ByteBuf data = Unpooled.wrappedBuffer(unknownPacket.data);
final UUID packId = PacketTypes.readUuid(data); // pack id
this.resourcePacks.add(packId);
this.sendResponse(packId, null, ResourcePackAction.ACCEPTED.ordinal());
for (UUID resourcePack : this.resourcePacks) {
this.sendResponse(resourcePack, null, ResourcePackAction.SUCCESSFULLY_LOADED.ordinal());
}
return false;
} else if (packet instanceof UnknownPacket unknownPacket
&& (unknownPacket.packetId == this.resourcePackPopId && this.proxyConnection.getP2sConnectionState() == ConnectionState.PLAY
|| unknownPacket.packetId == this.configResourcePackPopId && this.proxyConnection.getP2sConnectionState() == ConnectionState.CONFIGURATION)) {
final ByteBuf data = Unpooled.wrappedBuffer(unknownPacket.data);
if (data.readBoolean()) { // has pack id
final UUID packId = PacketTypes.readUuid(data); // pack id
this.resourcePacks.remove(packId);
} else {
this.resourcePacks.clear();
}
for (UUID resourcePack : this.resourcePacks) {
this.sendResponse(resourcePack, null, ResourcePackAction.SUCCESSFULLY_LOADED.ordinal());
}
return false;
} else if (packet instanceof UnknownPacket unknownPacket
&& (unknownPacket.packetId == this.s2cResourcePackId && this.proxyConnection.getP2sConnectionState() == ConnectionState.PLAY
|| unknownPacket.packetId == this.s2cConfigResourcePackId && this.proxyConnection.getP2sConnectionState() == ConnectionState.CONFIGURATION)) {
final ByteBuf data = Unpooled.wrappedBuffer(unknownPacket.data);
PacketTypes.readString(data, Short.MAX_VALUE); // url
final String hash = PacketTypes.readString(data, 40); // hash
this.sendResponse(null, hash, ResourcePackAction.ACCEPTED.ordinal());
this.sendResponse(null, hash, ResourcePackAction.SUCCESSFULLY_LOADED.ordinal());
return false;
}
return true;
}
private void sendResponse(final UUID packId, final String hash, final int status) {
final ByteBuf resourcePackResponse = Unpooled.buffer();
PacketTypes.writeVarInt(resourcePackResponse, this.proxyConnection.getP2sConnectionState() == ConnectionState.PLAY ? this.c2sResourcePackId : this.c2sConfigResourcePackId);
if (this.proxyConnection.getClientVersion().newerThanOrEqualTo(ProtocolVersion.v1_20_3)) {
PacketTypes.writeUuid(resourcePackResponse, packId); // pack id
} else if (this.proxyConnection.getClientVersion().olderThanOrEqualTo(ProtocolVersion.v1_9)) {
PacketTypes.writeString(resourcePackResponse, hash); // hash
}
PacketTypes.writeVarInt(resourcePackResponse, status); // status
this.proxyConnection.getChannel().writeAndFlush(resourcePackResponse).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
}
}

View file

@ -50,6 +50,7 @@ public class AdvancedTab extends UITab {
JCheckBox ignorePacketTranslationErrors;
JCheckBox allowBetaPinging;
JCheckBox simpleVoiceChatSupport;
JCheckBox fakeAcceptResourcePacks;
JButton viaVersionDumpButton;
JButton uploadLogsButton;
@ -133,6 +134,13 @@ public class AdvancedTab extends UITab {
this.simpleVoiceChatSupport.setSelected(ViaProxy.getConfig().shouldSupportSimpleVoiceChat());
checkboxes.add(this.simpleVoiceChatSupport);
}
{
this.fakeAcceptResourcePacks = new JCheckBox(I18n.get("tab.advanced.fake_accept_resource_packs.label"));
this.fakeAcceptResourcePacks.setToolTipText(I18n.get("tab.advanced.fake_accept_resource_packs.tooltip"));
this.fakeAcceptResourcePacks.setSelected(false);
this.fakeAcceptResourcePacks.setSelected(ViaProxy.getConfig().shouldFakeAcceptResourcePacks());
checkboxes.add(this.fakeAcceptResourcePacks);
}
GBC.create(body).grid(0, gridy++).insets(BODY_BLOCK_PADDING, BORDER_PADDING, 0, BODY_BLOCK_PADDING).fill(GBC.BOTH).weight(1, 1).add(checkboxes);
parent.add(body, BorderLayout.NORTH);
@ -210,6 +218,7 @@ public class AdvancedTab extends UITab {
ViaProxy.getConfig().setIgnoreProtocolTranslationErrors(this.ignorePacketTranslationErrors.isSelected());
ViaProxy.getConfig().setAllowBetaPinging(this.allowBetaPinging.isSelected());
ViaProxy.getConfig().setSimpleVoiceChatSupport(this.simpleVoiceChatSupport.isSelected());
ViaProxy.getConfig().setFakeAcceptResourcePacks(this.fakeAcceptResourcePacks.isSelected());
}
}

View file

@ -212,6 +212,8 @@ public class GeneralTab extends UITab {
this.viaProxyWindow.advancedTab.chatSigning.setEnabled(state);
this.viaProxyWindow.advancedTab.ignorePacketTranslationErrors.setEnabled(state);
this.viaProxyWindow.advancedTab.allowBetaPinging.setEnabled(state);
this.viaProxyWindow.advancedTab.simpleVoiceChatSupport.setEnabled(state);
this.viaProxyWindow.advancedTab.fakeAcceptResourcePacks.setEnabled(state);
if (state) this.serverVersion.getActionListeners()[0].actionPerformed(null);
}

View file

@ -58,6 +58,8 @@ tab.advanced.allow_beta_pinging.label=Aktiviere Pings für <= b1.7.3
tab.advanced.allow_beta_pinging.tooltip=Aktiviert das Pingen für <= b1.7.3 Server. Das könnte zu Problemen bei Servern, welche zu schnelle Verbindungen blockieren führen.
tab.advanced.simple_voice_chat_support.label=Simple Voice Chat Unterstützung
tab.advanced.simple_voice_chat_support.tooltip=Aktiviert lesen und ändern der Simple Voice Chat Mod Pakete.
tab.advanced.fake_accept_resource_packs.label=Überspringe Resourcenpakete
tab.advanced.fake_accept_resource_packs.tooltip=Akzeptiere Resourcenpakete ohne diese dem Client zu senden.\nDiese Option ist erforderlich um auf Servern zu spielen, welche Resourcenpakete benötigen, diese aber vom Client aufgrund der unterschiedlichen Version nicht geladen werden können.
tab.advanced.create_viaversion_dump.label=ViaVersion Dump erstellen
tab.advanced.create_viaversion_dump.success=Der ViaVersion Dump Link wurde in die Zwischenablage kopiert.
tab.advanced.upload_latest_log.label=Neueste Log-Datei hochladen

View file

@ -58,6 +58,8 @@ tab.advanced.allow_beta_pinging.label=Allow <= b1.7.3 pinging
tab.advanced.allow_beta_pinging.tooltip=Enabling this will allow you to ping <= b1.7.3 servers. This may cause issues with servers that block too frequent connections.
tab.advanced.simple_voice_chat_support.label=Simple Voice Chat Support
tab.advanced.simple_voice_chat_support.tooltip=Enables handling and rewriting of Simple Voice Chat mod packets.
tab.advanced.fake_accept_resource_packs.label=Fake accept resource packs
tab.advanced.fake_accept_resource_packs.tooltip=Accepts resource packs from the server without showing a prompt to the client.\nThis is required for servers that require a resource pack, but the client can't load it due to version differences.
tab.advanced.create_viaversion_dump.label=Create ViaVersion dump
tab.advanced.create_viaversion_dump.success=Copied ViaVersion dump link to clipboard.
tab.advanced.upload_latest_log.label=Upload latest log file

View file

@ -75,5 +75,9 @@ wildcard-domain-handling: "none"
# Enables handling and rewriting of Simple Voice Chat mod packets.
simple-voice-chat-support: false
#
# Accepts resource packs from the server without showing a prompt to the client.
# This is required for servers that require a resource pack, but the client can't load it due to version differences.
fake-accept-resource-packs: false
#
# Configuration version. Do not change this.
config-version: 1