Filter invalid remove teams packets in 1.20.3->1.20.5 (#4643)

Closes https://github.com/ViaVersion/ViaVersion/issues/4564
This commit is contained in:
EnZaXD authored and GitHub committed 2025-09-13 11:23:18 +02:00
1 parent 5a303996a1
commit 3ba518650c
3 files changed
+115

No files matched your search

@@ -52,6 +52,7 @@ import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.rewriter.EntityPacket
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.rewriter.ParticleRewriter1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.storage.AcknowledgedMessagesStorage;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.storage.ArmorTrimStorage;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.storage.ScoreboardTeamStorage;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.storage.TagKeys;
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ServerboundConfigurationPackets1_20_2;
import com.viaversion.viaversion.rewriter.SoundRewriter;
@@ -60,6 +61,7 @@ import com.viaversion.viaversion.rewriter.TagRewriter;
import com.viaversion.viaversion.rewriter.text.JsonNBTComponentRewriter;
import com.viaversion.viaversion.util.ProtocolLogger;
import java.util.BitSet;
import java.util.Objects;
import java.util.UUID;
import static com.viaversion.viaversion.util.ProtocolUtil.packetTypeMap;
@@ -222,6 +224,51 @@ public final class Protocol1_20_3To1_20_5 extends AbstractProtocol<ClientboundPa
wrapper.write(Types.BOOLEAN, strictErrorHandling);
});
registerClientbound(ClientboundPackets1_20_3.SET_PLAYER_TEAM, wrapper -> {
final String teamName = wrapper.passthrough(Types.STRING);
final byte action = wrapper.passthrough(Types.BYTE);
if (action == 2) {
return;
}
final ScoreboardTeamStorage storage = wrapper.user().get(ScoreboardTeamStorage.class);
if (action == 1) {
storage.removeTeam(teamName);
return;
} else if (action == 0) {
storage.createTeam(teamName);
wrapper.passthrough(Types.TAG); // Display name
wrapper.passthrough(Types.BYTE); // Flags
wrapper.passthrough(Types.STRING); // Name Tag Visibility
wrapper.passthrough(Types.STRING); // Collision rule
wrapper.passthrough(Types.VAR_INT); // Color
wrapper.passthrough(Types.TAG); // Prefix
wrapper.passthrough(Types.TAG); // Suffix
final String[] players = wrapper.passthrough(Types.STRING_ARRAY);
storage.addPlayerToTeam(teamName, players);
return;
}
final String[] players = wrapper.passthrough(Types.STRING_ARRAY);
if (action == 3) {
storage.addPlayerToTeam(teamName, players);
} else if (action != 4) {
return;
}
// Drop invalid remove packets to not break when plugins do that, since strict error handling is enforced in newer protocols.
for (final String player : players) {
final String team = storage.getPlayerTeam(player);
if (!Objects.equals(team, teamName)) {
wrapper.cancel();
return;
}
storage.removeFromTeam(teamName, player);
}
});
cancelServerbound(State.LOGIN, ServerboundLoginPackets.COOKIE_RESPONSE.getId());
cancelServerbound(ServerboundConfigurationPackets1_20_5.COOKIE_RESPONSE);
cancelServerbound(ServerboundConfigurationPackets1_20_5.SELECT_KNOWN_PACKS);
@@ -300,6 +347,7 @@ public final class Protocol1_20_3To1_20_5 extends AbstractProtocol<ClientboundPa
addEntityTracker(connection, new EntityTrackerBase(connection, EntityTypes1_20_5.PLAYER));
connection.put(new AcknowledgedMessagesStorage());
connection.put(new ArmorTrimStorage());
connection.put(new ScoreboardTeamStorage());
}
@Override
@@ -48,6 +48,7 @@ import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundCon
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.storage.AcknowledgedMessagesStorage;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.storage.ArmorTrimStorage;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.storage.ScoreboardTeamStorage;
import com.viaversion.viaversion.rewriter.EntityRewriter;
import com.viaversion.viaversion.util.Key;
import com.viaversion.viaversion.util.KeyMappings;
@@ -297,6 +298,8 @@ public final class EntityPacketRewriter1_20_5 extends EntityRewriter<Clientbound
final byte gamemode = wrapper.passthrough(Types.BYTE);
sendRangeAttributes(wrapper.user(), gamemode == GameMode.CREATIVE.id());
wrapper.user().put(new ScoreboardTeamStorage());
});
protocol.registerClientbound(ClientboundPackets1_20_3.UPDATE_MOB_EFFECT, wrapper -> {
@@ -0,0 +1,64 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 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.v1_20_3to1_20_5.storage;
import com.viaversion.viaversion.api.connection.StorableObject;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public final class ScoreboardTeamStorage implements StorableObject {
private final Map<String, Set<String>> teams = new HashMap<>();
public void createTeam(final String name) {
if (this.teams.containsKey(name)) {
return;
}
this.teams.put(name, new HashSet<>());
}
public void removeTeam(final String name) {
this.teams.remove(name);
}
public void addPlayerToTeam(final String team, final String[] player) {
final Set<String> players = this.teams.computeIfAbsent(team, k -> new HashSet<>());
Collections.addAll(players, player);
}
public void removeFromTeam(final String team, final String player) {
final Set<String> players = this.teams.get(team);
if (players != null) {
players.remove(player);
}
}
public String getPlayerTeam(final String player) {
for (final Map.Entry<String, Set<String>> entry : this.teams.entrySet()) {
if (entry.getValue().contains(player)) {
return entry.getKey();
}
}
return null;
}
}