3
0
Mirror von https://github.com/ViaVersion/ViaVersion.git synchronisiert 2024-11-03 14:50:30 +01:00

Re-send last resource pack on server switch

Dieser Commit ist enthalten in:
Nassim Jahnke 2023-09-19 11:54:03 +10:00
Ursprung 53aca791dd
Commit fe5646a68c
3 geänderte Dateien mit 84 neuen und 9 gelöschten Zeilen

Datei anzeigen

@ -18,6 +18,7 @@
package com.viaversion.viaversion.protocols.protocol1_20_2to1_20; package com.viaversion.viaversion.protocols.protocol1_20_2to1_20;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.google.gson.JsonElement;
import com.viaversion.viaversion.api.Via; import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection; import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.MappingData; import com.viaversion.viaversion.api.data.MappingData;
@ -45,6 +46,7 @@ import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.rewriter.BlockIt
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.rewriter.EntityPacketRewriter1_20_2; import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.rewriter.EntityPacketRewriter1_20_2;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.storage.ConfigurationState; import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.storage.ConfigurationState;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.storage.ConfigurationState.BridgePhase; import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.storage.ConfigurationState.BridgePhase;
import com.viaversion.viaversion.protocols.protocol1_20_2to1_20.storage.LastResourcePack;
import com.viaversion.viaversion.rewriter.SoundRewriter; import com.viaversion.viaversion.rewriter.SoundRewriter;
import java.util.UUID; import java.util.UUID;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
@ -68,6 +70,14 @@ public final class Protocol1_20_2To1_20 extends AbstractProtocol<ClientboundPack
soundRewriter.register1_19_3Sound(ClientboundPackets1_19_4.SOUND); soundRewriter.register1_19_3Sound(ClientboundPackets1_19_4.SOUND);
soundRewriter.registerEntitySound(ClientboundPackets1_19_4.ENTITY_SOUND); soundRewriter.registerEntitySound(ClientboundPackets1_19_4.ENTITY_SOUND);
registerClientbound(ClientboundPackets1_19_4.RESOURCE_PACK, wrapper -> {
final String url = wrapper.passthrough(Type.STRING);
final String hash = wrapper.passthrough(Type.STRING);
final boolean required = wrapper.passthrough(Type.BOOLEAN);
final JsonElement prompt = wrapper.passthrough(Type.OPTIONAL_COMPONENT);
wrapper.user().put(new LastResourcePack(url, hash, required, prompt));
});
registerClientbound(ClientboundPackets1_19_4.DISPLAY_SCOREBOARD, wrapper -> { registerClientbound(ClientboundPackets1_19_4.DISPLAY_SCOREBOARD, wrapper -> {
final byte slot = wrapper.read(Type.BYTE); final byte slot = wrapper.read(Type.BYTE);
wrapper.write(Type.VAR_INT, (int) slot); wrapper.write(Type.VAR_INT, (int) slot);
@ -115,7 +125,8 @@ public final class Protocol1_20_2To1_20 extends AbstractProtocol<ClientboundPack
registerServerbound(State.CONFIGURATION, ServerboundConfigurationPackets1_20_2.CUSTOM_PAYLOAD.getId(), -1, queueServerboundPacket(ServerboundPackets1_20_2.PLUGIN_MESSAGE)); registerServerbound(State.CONFIGURATION, ServerboundConfigurationPackets1_20_2.CUSTOM_PAYLOAD.getId(), -1, queueServerboundPacket(ServerboundPackets1_20_2.PLUGIN_MESSAGE));
registerServerbound(State.CONFIGURATION, ServerboundConfigurationPackets1_20_2.KEEP_ALIVE.getId(), -1, queueServerboundPacket(ServerboundPackets1_20_2.KEEP_ALIVE)); registerServerbound(State.CONFIGURATION, ServerboundConfigurationPackets1_20_2.KEEP_ALIVE.getId(), -1, queueServerboundPacket(ServerboundPackets1_20_2.KEEP_ALIVE));
registerServerbound(State.CONFIGURATION, ServerboundConfigurationPackets1_20_2.PONG.getId(), -1, queueServerboundPacket(ServerboundPackets1_20_2.PONG)); registerServerbound(State.CONFIGURATION, ServerboundConfigurationPackets1_20_2.PONG.getId(), -1, queueServerboundPacket(ServerboundPackets1_20_2.PONG));
registerServerbound(State.CONFIGURATION, ServerboundConfigurationPackets1_20_2.RESOURCE_PACK.getId(), -1, queueServerboundPacket(ServerboundPackets1_20_2.RESOURCE_PACK_STATUS)); // Cancel this, as it will always just be the response to a re-sent pack from us
registerServerbound(State.CONFIGURATION, ServerboundConfigurationPackets1_20_2.RESOURCE_PACK.getId(), -1, PacketWrapper::cancel);
cancelClientbound(ClientboundPackets1_19_4.UPDATE_ENABLED_FEATURES); // TODO Sad emoji cancelClientbound(ClientboundPackets1_19_4.UPDATE_ENABLED_FEATURES); // TODO Sad emoji
registerServerbound(ServerboundPackets1_20_2.CONFIGURATION_ACKNOWLEDGED, null, wrapper -> { registerServerbound(ServerboundPackets1_20_2.CONFIGURATION_ACKNOWLEDGED, null, wrapper -> {
@ -128,7 +139,9 @@ public final class Protocol1_20_2To1_20 extends AbstractProtocol<ClientboundPack
// Reenter the configuration state // Reenter the configuration state
configurationState.setBridgePhase(BridgePhase.CONFIGURATION); configurationState.setBridgePhase(BridgePhase.CONFIGURATION);
sendConfigurationPackets(wrapper.user(), configurationState.getReenterInfo().dimensionRegistry());
final LastResourcePack lastResourcePack = wrapper.user().get(LastResourcePack.class);
sendConfigurationPackets(wrapper.user(), configurationState.getReenterInfo().dimensionRegistry(), lastResourcePack);
configurationState.setReenterInfo(null); configurationState.setReenterInfo(null);
}); });
cancelServerbound(ServerboundPackets1_20_2.CHUNK_BATCH_RECEIVED); cancelServerbound(ServerboundPackets1_20_2.CHUNK_BATCH_RECEIVED);
@ -165,14 +178,14 @@ public final class Protocol1_20_2To1_20 extends AbstractProtocol<ClientboundPack
return; return;
} }
final boolean reentering = configurationBridge.getReenterInfo() != null;
if (direction == Direction.SERVERBOUND) { if (direction == Direction.SERVERBOUND) {
// Client and server will be on different protocol states, pick the right client protocol state // Client and server will be on different protocol states, pick the right client protocol state
super.transform(direction, phase == BridgePhase.PROFILE_SENT ? State.LOGIN : reentering ? State.PLAY : State.CONFIGURATION, packetWrapper); super.transform(direction, phase == BridgePhase.PROFILE_SENT ? State.LOGIN
: phase == BridgePhase.REENTERING_CONFIGURATION ? State.PLAY : State.CONFIGURATION, packetWrapper);
return; return;
} }
if (phase == BridgePhase.PROFILE_SENT || reentering) { if (phase == BridgePhase.PROFILE_SENT || phase == BridgePhase.REENTERING_CONFIGURATION) {
// Queue packets sent by the server while we wait for the client to transition to the configuration state // Queue packets sent by the server while we wait for the client to transition to the configuration state
configurationBridge.addPacketToQueue(packetWrapper, true); configurationBridge.addPacketToQueue(packetWrapper, true);
throw CancelException.generate(); throw CancelException.generate();
@ -207,14 +220,13 @@ public final class Protocol1_20_2To1_20 extends AbstractProtocol<ClientboundPack
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.KEEP_ALIVE); packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.KEEP_ALIVE);
} else if (unmappedId == ClientboundPackets1_19_4.PING.getId()) { } else if (unmappedId == ClientboundPackets1_19_4.PING.getId()) {
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.PING); packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.PING);
} else if (unmappedId == ClientboundPackets1_19_4.RESOURCE_PACK.getId()) {
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.RESOURCE_PACK);
} else if (unmappedId == ClientboundPackets1_19_4.UPDATE_ENABLED_FEATURES.getId()) { } else if (unmappedId == ClientboundPackets1_19_4.UPDATE_ENABLED_FEATURES.getId()) {
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.UPDATE_ENABLED_FEATURES); packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.UPDATE_ENABLED_FEATURES);
} else if (unmappedId == ClientboundPackets1_19_4.TAGS.getId()) { } else if (unmappedId == ClientboundPackets1_19_4.TAGS.getId()) {
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.UPDATE_TAGS); packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.UPDATE_TAGS);
} else { } else {
// Not a packet that can be mapped to the configuration protocol // Not a packet that can be mapped to the configuration protocol
// Includes resource pack packets to make sure it is not applied sooner than the server expects
configurationBridge.addPacketToQueue(packetWrapper, true); configurationBridge.addPacketToQueue(packetWrapper, true);
throw CancelException.generate(); throw CancelException.generate();
} }
@ -226,7 +238,7 @@ public final class Protocol1_20_2To1_20 extends AbstractProtocol<ClientboundPack
super.transform(direction, State.CONFIGURATION, packetWrapper); super.transform(direction, State.CONFIGURATION, packetWrapper);
} }
public static void sendConfigurationPackets(final UserConnection connection, final CompoundTag dimensionRegistry) throws Exception { public static void sendConfigurationPackets(final UserConnection connection, final CompoundTag dimensionRegistry, @Nullable final LastResourcePack lastResourcePack) throws Exception {
final PacketWrapper registryDataPacket = PacketWrapper.create(ClientboundConfigurationPackets1_20_2.REGISTRY_DATA, connection); final PacketWrapper registryDataPacket = PacketWrapper.create(ClientboundConfigurationPackets1_20_2.REGISTRY_DATA, connection);
registryDataPacket.write(Type.NAMELESS_NBT, dimensionRegistry); registryDataPacket.write(Type.NAMELESS_NBT, dimensionRegistry);
registryDataPacket.send(Protocol1_20_2To1_20.class); registryDataPacket.send(Protocol1_20_2To1_20.class);
@ -238,6 +250,16 @@ public final class Protocol1_20_2To1_20 extends AbstractProtocol<ClientboundPack
enableFeaturesPacket.write(Type.STRING, "minecraft:vanilla"); enableFeaturesPacket.write(Type.STRING, "minecraft:vanilla");
enableFeaturesPacket.send(Protocol1_20_2To1_20.class); enableFeaturesPacket.send(Protocol1_20_2To1_20.class);
if (lastResourcePack != null) {
// The client for some reason drops the resource pack when reentering the configuration state
final PacketWrapper resourcePackPacket = PacketWrapper.create(ClientboundConfigurationPackets1_20_2.RESOURCE_PACK, connection);
resourcePackPacket.write(Type.STRING, lastResourcePack.url());
resourcePackPacket.write(Type.STRING, lastResourcePack.hash());
resourcePackPacket.write(Type.BOOLEAN, lastResourcePack.required());
resourcePackPacket.write(Type.OPTIONAL_COMPONENT, lastResourcePack.prompt());
resourcePackPacket.send(Protocol1_20_2To1_20.class);
}
final PacketWrapper finishConfigurationPacket = PacketWrapper.create(ClientboundConfigurationPackets1_20_2.FINISH_CONFIGURATION, connection); final PacketWrapper finishConfigurationPacket = PacketWrapper.create(ClientboundConfigurationPackets1_20_2.FINISH_CONFIGURATION, connection);
finishConfigurationPacket.send(Protocol1_20_2To1_20.class); finishConfigurationPacket.send(Protocol1_20_2To1_20.class);
} }

Datei anzeigen

@ -114,7 +114,7 @@ public final class EntityPacketRewriter1_20_2 extends EntityRewriter<Clientbound
return; return;
} }
Protocol1_20_2To1_20.sendConfigurationPackets(wrapper.user(), dimensionRegistry); Protocol1_20_2To1_20.sendConfigurationPackets(wrapper.user(), dimensionRegistry, null);
// Manually send it at the end and hope nothing breaks // Manually send it at the end and hope nothing breaks
configurationBridge.setJoinGamePacket(wrapper); configurationBridge.setJoinGamePacket(wrapper);

Datei anzeigen

@ -0,0 +1,53 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2023 ViaVersion 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 com.viaversion.viaversion.protocols.protocol1_20_2to1_20.storage;
import com.google.gson.JsonElement;
import com.viaversion.viaversion.api.connection.StorableObject;
import org.checkerframework.checker.nullness.qual.Nullable;
public final class LastResourcePack implements StorableObject {
private final String url;
private final String hash;
private final boolean required;
private final JsonElement prompt;
public LastResourcePack(final String url, final String hash, final boolean required, @Nullable final JsonElement prompt) {
this.url = url;
this.hash = hash;
this.required = required;
this.prompt = prompt;
}
public String url() {
return url;
}
public String hash() {
return hash;
}
public boolean required() {
return required;
}
public @Nullable JsonElement prompt() {
return prompt;
}
}