Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,23 @@ public boolean viewerAdd(final ConnectedPlayer viewer) {
viewer.getProtocolVersion(),
viewer.translateMessage(this.bar.name())
);
viewer.getConnection().write(BossBarPacket.createAddPacket(this.id, this.bar, name));
viewer.getBossBarManager().writeUpdate(this, BossBarPacket.createAddPacket(this.id, this.bar, name));
return true;
}
return false;
}

public void createDirect(final ConnectedPlayer viewer) {
final ComponentHolder name = new ComponentHolder(
viewer.getProtocolVersion(),
viewer.translateMessage(this.bar.name())
);
viewer.getConnection().write(BossBarPacket.createAddPacket(this.id, this.bar, name));
}

public boolean viewerRemove(final ConnectedPlayer viewer) {
if (this.viewers.remove(viewer)) {
viewer.getConnection().write(BossBarPacket.createRemovePacket(this.id, this.bar));
viewer.getBossBarManager().remove(this, BossBarPacket.createRemovePacket(this.id, this.bar));
return true;
}
return false;
Expand All @@ -84,7 +92,7 @@ public void bossBarNameChanged(
this.bar,
new ComponentHolder(viewer.getProtocolVersion(), translated)
);
viewer.getConnection().write(packet);
viewer.getBossBarManager().writeUpdate(this, packet);
}
}

Expand All @@ -96,7 +104,7 @@ public void bossBarProgressChanged(
) {
final BossBarPacket packet = BossBarPacket.createUpdateProgressPacket(this.id, this.bar);
for (final ConnectedPlayer viewer : this.viewers) {
viewer.getConnection().write(packet);
viewer.getBossBarManager().writeUpdate(this, packet);
}
}

Expand All @@ -108,7 +116,7 @@ public void bossBarColorChanged(
) {
final BossBarPacket packet = BossBarPacket.createUpdateStylePacket(this.id, this.bar);
for (final ConnectedPlayer viewer : this.viewers) {
viewer.getConnection().write(packet);
viewer.getBossBarManager().writeUpdate(this, packet);
}
}

Expand All @@ -120,7 +128,7 @@ public void bossBarOverlayChanged(
) {
final BossBarPacket packet = BossBarPacket.createUpdateStylePacket(this.id, this.bar);
for (final ConnectedPlayer viewer : this.viewers) {
viewer.getConnection().write(packet);
viewer.getBossBarManager().writeUpdate(this, packet);
}
}

Expand All @@ -132,7 +140,7 @@ public void bossBarFlagsChanged(
) {
final BossBarPacket packet = BossBarPacket.createUpdatePropertiesPacket(this.id, this.bar);
for (final ConnectedPlayer viewer : this.viewers) {
viewer.getConnection().write(packet);
viewer.getBossBarManager().writeUpdate(this, packet);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -177,10 +177,12 @@ public boolean handle(DisconnectPacket packet) {

@Override
public boolean handle(BossBarPacket packet) {
if (packet.getAction() == BossBarPacket.ADD) {
playerSessionHandler.getServerBossBars().add(packet.getUuid());
} else if (packet.getAction() == BossBarPacket.REMOVE) {
playerSessionHandler.getServerBossBars().remove(packet.getUuid());
if (serverConn.getPlayer().getProtocolVersion().lessThan(ProtocolVersion.MINECRAFT_1_20_2)) {
if (packet.getAction() == BossBarPacket.ADD) {
playerSessionHandler.getServerBossBars().add(packet.getUuid());
} else if (packet.getAction() == BossBarPacket.REMOVE) {
playerSessionHandler.getServerBossBars().remove(packet.getUuid());
}
}
return false; // forward
}
Expand Down Expand Up @@ -516,4 +518,4 @@ public void writabilityChanged() {

playerConnection.setAutoReading(writable);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -535,9 +535,13 @@ public CompletableFuture<Void> doSwitch() {

// Config state clears everything in the client. No need to clear later.
spawned = false;
serverBossBars.clear();
player.clearPlayerListHeaderAndFooterSilent();
player.getTabList().clearAllSilent();
if (player.getProtocolVersion().noLessThan(ProtocolVersion.MINECRAFT_1_20_2)) {
player.getBossBarManager().dropPackets();
} else {
serverBossBars.clear();
}
}

player.switchToConfigState();
Expand Down Expand Up @@ -576,16 +580,19 @@ public void handleBackendJoinGame(JoinGamePacket joinGame, VelocityServerConnect
}

destination.setEntityId(joinGame.getEntityId()); // used for sound api

// Remove previous boss bars. These don't get cleared when sending JoinGame, thus the need to
// track them.
for (UUID serverBossBar : serverBossBars) {
BossBarPacket deletePacket = new BossBarPacket();
deletePacket.setUuid(serverBossBar);
deletePacket.setAction(BossBarPacket.REMOVE);
player.getConnection().delayedWrite(deletePacket);
if (player.getProtocolVersion().noLessThan(ProtocolVersion.MINECRAFT_1_20_2)) {
player.getBossBarManager().sendBossBars();
} else {
// Remove previous boss bars. These don't get cleared when sending JoinGame (up until 1.20.2),
// thus the need to track them.
for (UUID serverBossBar : serverBossBars) {
BossBarPacket deletePacket = new BossBarPacket();
deletePacket.setUuid(serverBossBar);
deletePacket.setAction(BossBarPacket.REMOVE);
player.getConnection().delayedWrite(deletePacket);
}
serverBossBars.clear();
}
serverBossBars.clear();

// Tell the server about the proxy's plugin message channels.
ProtocolVersion serverVersion = serverMc.getProtocolVersion();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
import com.velocitypowered.proxy.connection.MinecraftConnection;
import com.velocitypowered.proxy.connection.MinecraftConnectionAssociation;
import com.velocitypowered.proxy.connection.backend.VelocityServerConnection;
import com.velocitypowered.proxy.connection.player.bossbar.BossBarManager;
import com.velocitypowered.proxy.connection.player.bundle.BundleDelimiterHandler;
import com.velocitypowered.proxy.connection.player.resourcepack.VelocityResourcePackInfo;
import com.velocitypowered.proxy.connection.player.resourcepack.handler.ResourcePackHandler;
Expand Down Expand Up @@ -201,6 +202,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player,
private @Nullable ClientSettingsPacket clientSettingsPacket;
private volatile ChatQueue chatQueue;
private final ChatBuilderFactory chatBuilderFactory;
private final BossBarManager bossBarManager;

ConnectedPlayer(VelocityServer server, GameProfile profile, MinecraftConnection connection,
@Nullable InetSocketAddress virtualHost, @Nullable String rawVirtualHost, boolean onlineMode,
Expand All @@ -227,6 +229,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player,
this.chatQueue = new ChatQueue(this);
this.chatBuilderFactory = new ChatBuilderFactory(this.getProtocolVersion());
this.resourcePackHandler = ResourcePackHandler.create(this, server);
this.bossBarManager = new BossBarManager(this);
}

/**
Expand Down Expand Up @@ -1431,6 +1434,10 @@ public HandshakeIntent getHandshakeIntent() {
return handshakeIntent;
}

public BossBarManager getBossBarManager() {
return bossBarManager;
}

private final class ConnectionRequestBuilderImpl implements ConnectionRequestBuilder {

private final RegisteredServer toConnect;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Copyright (C) 2019-2023 Velocity 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 <https://www.gnu.org/licenses/>.
*/

package com.velocitypowered.proxy.connection.player.bossbar;

import com.velocitypowered.proxy.adventure.VelocityBossBarImplementation;
import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
import com.velocitypowered.proxy.protocol.packet.BossBarPacket;
import java.util.HashSet;
import java.util.Set;

/**
* Handles dropping and resending boss bar packets on versions 1.20.2 and newer because the client now
* deletes all boss bars during the login phase, and sending update packets would cause the client to be disconnected.
*/
public final class BossBarManager {

private final ConnectedPlayer player;
private final Set<VelocityBossBarImplementation> bossBars = new HashSet<>();

private boolean dropPackets = false;

public BossBarManager(ConnectedPlayer player) {
this.player = player;
}

/**
* Records the specified boss bar to be re-sent when a player changes server, and sends the update packet
* if the client is able to receive it and not be disconnected.
*/
public synchronized void writeUpdate(VelocityBossBarImplementation bar, BossBarPacket packet) {
this.bossBars.add(bar);
if (!this.dropPackets) {
this.player.getConnection().write(packet);
}
}

/**
* Removes the specified boss bar from the player to ensure it is not re-sent.
*/
public synchronized void remove(VelocityBossBarImplementation bar, BossBarPacket packet) {
this.bossBars.remove(bar);
if (!this.dropPackets) {
this.player.getConnection().write(packet);
}
}

/**
* Re-creates the boss bars the player can see with any updates that may have occurred in the meantime,
* and allows update packets for those boss bars to be sent.
*/
public synchronized void sendBossBars() {
for (VelocityBossBarImplementation bossBar : bossBars) {
bossBar.createDirect(player);
}
this.dropPackets = false;
}

/**
* Prevents the player from receiving boss bar update packets while logging in to a new server.
*/
public synchronized void dropPackets() {
this.dropPackets = true;
}
}