Don't send the attribute packet if the login packet hasn't been sent yet

This commit is contained in:
Nassim Jahnke 2024-06-16 15:44:02 +02:00
parent 4b44ecf6fa
commit d1d279cfea
No known key found for this signature in database
GPG Key ID: EF6771C01F6EF02F
4 changed files with 89 additions and 21 deletions

View File

@ -20,11 +20,9 @@ package com.viaversion.viaversion.bukkit.listeners.v1_20_5to1_21;
import com.viaversion.viaversion.ViaVersionPlugin;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.bukkit.listeners.ViaBukkitListener;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.Protocol1_20_5To1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.storage.EfficiencyAttributeStorage;
import io.papermc.paper.event.player.PlayerInventorySlotChangeEvent;
import org.bukkit.NamespacedKey;
import org.bukkit.enchantments.Enchantment;
@ -41,7 +39,6 @@ import org.checkerframework.checker.nullness.qual.Nullable;
*/
public final class PlayerChangeItemListener extends ViaBukkitListener {
private static final int MINING_EFFICIENCY_ID = 19;
private final Enchantment efficiency = Enchantment.getByKey(NamespacedKey.minecraft("efficiency"));
public PlayerChangeItemListener(final ViaVersionPlugin plugin) {
@ -70,24 +67,12 @@ public final class PlayerChangeItemListener extends ViaBukkitListener {
return;
}
final int efficiencyLevel = item != null ? item.getEnchantmentLevel(efficiency) : 0;
final PacketWrapper attributesPacket = PacketWrapper.create(ClientboundPackets1_21.UPDATE_ATTRIBUTES, connection);
attributesPacket.write(Types.VAR_INT, player.getEntityId());
attributesPacket.write(Types.VAR_INT, 1); // Size
attributesPacket.write(Types.VAR_INT, MINING_EFFICIENCY_ID); // Attribute ID
attributesPacket.write(Types.DOUBLE, 0D); // Base
if (efficiencyLevel > 0) {
final double modifierAmount = (efficiencyLevel * efficiencyLevel) + 1D;
attributesPacket.write(Types.VAR_INT, 1); // Modifiers
attributesPacket.write(Types.STRING, "minecraft:enchantment.efficiency/mainhand"); // Id
attributesPacket.write(Types.DOUBLE, modifierAmount);
attributesPacket.write(Types.BYTE, (byte) 0); // 'Add' operation
} else {
attributesPacket.write(Types.VAR_INT, 0); // Modifiers
final EfficiencyAttributeStorage storage = connection.get(EfficiencyAttributeStorage.class);
if (storage == null) {
return;
}
attributesPacket.scheduleSend(Protocol1_20_5To1_21.class);
final int efficiencyLevel = item != null ? item.getEnchantmentLevel(efficiency) : 0;
storage.setEfficiencyLevel(new EfficiencyAttributeStorage.StoredEfficiency(player.getEntityId(), efficiencyLevel), connection);
}
}

View File

@ -44,6 +44,7 @@ import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPacke
import com.viaversion.viaversion.protocols.v1_20_5to1_21.rewriter.BlockItemPacketRewriter1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.rewriter.ComponentRewriter1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.rewriter.EntityPacketRewriter1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.storage.EfficiencyAttributeStorage;
import com.viaversion.viaversion.rewriter.ComponentRewriter;
import com.viaversion.viaversion.rewriter.SoundRewriter;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
@ -220,6 +221,7 @@ public final class Protocol1_20_5To1_21 extends AbstractProtocol<ClientboundPack
@Override
public void init(final UserConnection connection) {
addEntityTracker(connection, new EntityTrackerBase(connection, EntityTypes1_20_5.PLAYER));
connection.put(new EfficiencyAttributeStorage());
}
@Override

View File

@ -35,6 +35,7 @@ import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPac
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.Protocol1_20_5To1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.data.Paintings1_20_5;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.storage.EfficiencyAttributeStorage;
import com.viaversion.viaversion.rewriter.EntityRewriter;
import com.viaversion.viaversion.util.Key;
@ -114,6 +115,7 @@ public final class EntityPacketRewriter1_21 extends EntityRewriter<ClientboundPa
map(Types.STRING); // World
handler(worldDataTrackerHandlerByKey1_20_5(3));
handler(playerTrackerHandler());
handler(wrapper -> wrapper.user().get(EfficiencyAttributeStorage.class).onLoginSent(wrapper.user()));
}
});

View File

@ -0,0 +1,79 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 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_5to1_21.storage;
import com.viaversion.viaversion.api.connection.StorableObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.Protocol1_20_5To1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21;
public final class EfficiencyAttributeStorage implements StorableObject {
private static final int MINING_EFFICIENCY_ID = 19;
private final Object lock = new Object(); // Slightly sloppy locking, but should be good enough
private volatile boolean loginSent;
private volatile StoredEfficiency efficiencyLevel;
public void setEfficiencyLevel(final StoredEfficiency efficiencyLevel, final UserConnection connection) {
this.efficiencyLevel = efficiencyLevel;
sendAttributesPacket(connection);
}
public void onLoginSent(final UserConnection connection) {
this.loginSent = true;
sendAttributesPacket(connection);
}
private void sendAttributesPacket(final UserConnection connection) {
final StoredEfficiency efficiency;
synchronized (lock) {
// Older servers (and often Bungee) will send world state packets before sending the login packet
if (!loginSent || efficiencyLevel == null) {
return;
}
efficiency = efficiencyLevel;
efficiencyLevel = null;
}
final PacketWrapper attributesPacket = PacketWrapper.create(ClientboundPackets1_21.UPDATE_ATTRIBUTES, connection);
attributesPacket.write(Types.VAR_INT, efficiency.entityId());
attributesPacket.write(Types.VAR_INT, 1); // Size
attributesPacket.write(Types.VAR_INT, MINING_EFFICIENCY_ID); // Attribute ID
attributesPacket.write(Types.DOUBLE, 0D); // Base
final int level = efficiency.level;
if (level > 0) {
final double modifierAmount = (level * level) + 1D;
attributesPacket.write(Types.VAR_INT, 1); // Modifiers
attributesPacket.write(Types.STRING, "minecraft:enchantment.efficiency/mainhand"); // Id
attributesPacket.write(Types.DOUBLE, modifierAmount);
attributesPacket.write(Types.BYTE, (byte) 0); // 'Add' operation
} else {
attributesPacket.write(Types.VAR_INT, 0); // Modifiers
}
attributesPacket.scheduleSend(Protocol1_20_5To1_21.class);
}
public record StoredEfficiency(int entityId, int level) {
}
}