Mirror von
https://github.com/PaperMC/Velocity.git
synchronisiert 2025-01-11 23:51:22 +01:00
Refactor bossbar implementation (#1209)
* Refactor bossbar implementation * Move to adventure package * Use AutoService instead of manual service declaration --------- Co-authored-by: Adrian <adriangonzalesval@gmail.com>
Dieser Commit ist enthalten in:
Ursprung
5f27edf3c2
Commit
5afcd72bbd
@ -60,7 +60,6 @@ import com.velocitypowered.proxy.util.AddressUtil;
|
|||||||
import com.velocitypowered.proxy.util.ClosestLocaleMatcher;
|
import com.velocitypowered.proxy.util.ClosestLocaleMatcher;
|
||||||
import com.velocitypowered.proxy.util.ResourceUtils;
|
import com.velocitypowered.proxy.util.ResourceUtils;
|
||||||
import com.velocitypowered.proxy.util.VelocityChannelRegistrar;
|
import com.velocitypowered.proxy.util.VelocityChannelRegistrar;
|
||||||
import com.velocitypowered.proxy.util.bossbar.AdventureBossBarManager;
|
|
||||||
import com.velocitypowered.proxy.util.ratelimit.Ratelimiter;
|
import com.velocitypowered.proxy.util.ratelimit.Ratelimiter;
|
||||||
import com.velocitypowered.proxy.util.ratelimit.Ratelimiters;
|
import com.velocitypowered.proxy.util.ratelimit.Ratelimiters;
|
||||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||||
@ -151,7 +150,6 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
|
|||||||
private final AtomicBoolean shutdownInProgress = new AtomicBoolean(false);
|
private final AtomicBoolean shutdownInProgress = new AtomicBoolean(false);
|
||||||
private boolean shutdown = false;
|
private boolean shutdown = false;
|
||||||
private final VelocityPluginManager pluginManager;
|
private final VelocityPluginManager pluginManager;
|
||||||
private final AdventureBossBarManager bossBarManager;
|
|
||||||
|
|
||||||
private final Map<UUID, ConnectedPlayer> connectionsByUuid = new ConcurrentHashMap<>();
|
private final Map<UUID, ConnectedPlayer> connectionsByUuid = new ConcurrentHashMap<>();
|
||||||
private final Map<String, ConnectedPlayer> connectionsByName = new ConcurrentHashMap<>();
|
private final Map<String, ConnectedPlayer> connectionsByName = new ConcurrentHashMap<>();
|
||||||
@ -173,7 +171,6 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
|
|||||||
servers = new ServerMap(this);
|
servers = new ServerMap(this);
|
||||||
serverListPingHandler = new ServerListPingHandler(this);
|
serverListPingHandler = new ServerListPingHandler(this);
|
||||||
this.options = options;
|
this.options = options;
|
||||||
this.bossBarManager = new AdventureBossBarManager();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public KeyPair getServerKeyPair() {
|
public KeyPair getServerKeyPair() {
|
||||||
@ -660,7 +657,7 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
|
|||||||
public void unregisterConnection(ConnectedPlayer connection) {
|
public void unregisterConnection(ConnectedPlayer connection) {
|
||||||
connectionsByName.remove(connection.getUsername().toLowerCase(Locale.US), connection);
|
connectionsByName.remove(connection.getUsername().toLowerCase(Locale.US), connection);
|
||||||
connectionsByUuid.remove(connection.getUniqueId(), connection);
|
connectionsByUuid.remove(connection.getUniqueId(), connection);
|
||||||
bossBarManager.onDisconnect(connection);
|
connection.disconnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -770,10 +767,6 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
|
|||||||
return audiences;
|
return audiences;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AdventureBossBarManager getBossBarManager() {
|
|
||||||
return bossBarManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a Gson instance for use in serializing server ping instances.
|
* Returns a Gson instance for use in serializing server ping instances.
|
||||||
*
|
*
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020-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.adventure;
|
||||||
|
|
||||||
|
import com.google.auto.service.AutoService;
|
||||||
|
import net.kyori.adventure.bossbar.BossBar;
|
||||||
|
import net.kyori.adventure.bossbar.BossBarImplementation;
|
||||||
|
|
||||||
|
@AutoService(BossBarImplementation.Provider.class)
|
||||||
|
@SuppressWarnings("MissingJavadocType")
|
||||||
|
public class BossBarImplementationProvider implements BossBarImplementation.Provider {
|
||||||
|
@Override
|
||||||
|
public BossBarImplementation create(final BossBar bar) {
|
||||||
|
final VelocityBossBarImplementation impl = new VelocityBossBarImplementation(bar);
|
||||||
|
bar.addListener(impl);
|
||||||
|
return impl;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,138 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020-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.adventure;
|
||||||
|
|
||||||
|
import com.google.common.collect.MapMaker;
|
||||||
|
import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
|
||||||
|
import com.velocitypowered.proxy.protocol.packet.BossBarPacket;
|
||||||
|
import com.velocitypowered.proxy.protocol.packet.chat.ComponentHolder;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
import net.kyori.adventure.bossbar.BossBar;
|
||||||
|
import net.kyori.adventure.bossbar.BossBarImplementation;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of a {@link BossBarImplementation}.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("MissingJavadocMethod")
|
||||||
|
public final class VelocityBossBarImplementation implements BossBar.Listener,
|
||||||
|
BossBarImplementation {
|
||||||
|
private final Set<ConnectedPlayer> viewers = Collections.newSetFromMap(
|
||||||
|
new MapMaker().weakKeys().makeMap());
|
||||||
|
private final UUID id = UUID.randomUUID();
|
||||||
|
private final BossBar bar;
|
||||||
|
|
||||||
|
public static VelocityBossBarImplementation get(final BossBar bar) {
|
||||||
|
return BossBarImplementation.get(bar, VelocityBossBarImplementation.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
VelocityBossBarImplementation(final BossBar bar) {
|
||||||
|
this.bar = bar;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean viewerAdd(final ConnectedPlayer viewer) {
|
||||||
|
if (this.viewers.add(viewer)) {
|
||||||
|
final ComponentHolder name = new ComponentHolder(
|
||||||
|
viewer.getProtocolVersion(),
|
||||||
|
viewer.translateMessage(this.bar.name())
|
||||||
|
);
|
||||||
|
viewer.getConnection().write(BossBarPacket.createAddPacket(this.id, this.bar, name));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean viewerRemove(final ConnectedPlayer viewer) {
|
||||||
|
if (this.viewers.remove(viewer)) {
|
||||||
|
viewer.getConnection().write(BossBarPacket.createRemovePacket(this.id, this.bar));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void viewerDisconnected(final ConnectedPlayer viewer) {
|
||||||
|
this.viewers.remove(viewer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void bossBarNameChanged(
|
||||||
|
final BossBar bar,
|
||||||
|
final Component oldName,
|
||||||
|
final Component newName
|
||||||
|
) {
|
||||||
|
for (final ConnectedPlayer viewer : this.viewers) {
|
||||||
|
final Component translated = viewer.translateMessage(newName);
|
||||||
|
final BossBarPacket packet = BossBarPacket.createUpdateNamePacket(
|
||||||
|
this.id,
|
||||||
|
this.bar,
|
||||||
|
new ComponentHolder(viewer.getProtocolVersion(), translated)
|
||||||
|
);
|
||||||
|
viewer.getConnection().write(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void bossBarProgressChanged(
|
||||||
|
final BossBar bar,
|
||||||
|
final float oldProgress,
|
||||||
|
final float newProgress
|
||||||
|
) {
|
||||||
|
final BossBarPacket packet = BossBarPacket.createUpdateProgressPacket(this.id, this.bar);
|
||||||
|
for (final ConnectedPlayer viewer : this.viewers) {
|
||||||
|
viewer.getConnection().write(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void bossBarColorChanged(
|
||||||
|
final BossBar bar,
|
||||||
|
final BossBar.Color oldColor,
|
||||||
|
final BossBar.Color newColor
|
||||||
|
) {
|
||||||
|
final BossBarPacket packet = BossBarPacket.createUpdateStylePacket(this.id, this.bar);
|
||||||
|
for (final ConnectedPlayer viewer : this.viewers) {
|
||||||
|
viewer.getConnection().write(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void bossBarOverlayChanged(
|
||||||
|
final BossBar bar,
|
||||||
|
final BossBar.Overlay oldOverlay,
|
||||||
|
final BossBar.Overlay newOverlay
|
||||||
|
) {
|
||||||
|
final BossBarPacket packet = BossBarPacket.createUpdateStylePacket(this.id, this.bar);
|
||||||
|
for (final ConnectedPlayer viewer : this.viewers) {
|
||||||
|
viewer.getConnection().write(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void bossBarFlagsChanged(
|
||||||
|
final BossBar bar,
|
||||||
|
final Set<BossBar.Flag> flagsAdded,
|
||||||
|
final Set<BossBar.Flag> flagsRemoved
|
||||||
|
) {
|
||||||
|
final BossBarPacket packet = BossBarPacket.createUpdatePropertiesPacket(this.id, this.bar);
|
||||||
|
for (final ConnectedPlayer viewer : this.viewers) {
|
||||||
|
viewer.getConnection().write(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -50,6 +50,7 @@ import com.velocitypowered.api.proxy.server.RegisteredServer;
|
|||||||
import com.velocitypowered.api.util.GameProfile;
|
import com.velocitypowered.api.util.GameProfile;
|
||||||
import com.velocitypowered.api.util.ModInfo;
|
import com.velocitypowered.api.util.ModInfo;
|
||||||
import com.velocitypowered.proxy.VelocityServer;
|
import com.velocitypowered.proxy.VelocityServer;
|
||||||
|
import com.velocitypowered.proxy.adventure.VelocityBossBarImplementation;
|
||||||
import com.velocitypowered.proxy.connection.MinecraftConnection;
|
import com.velocitypowered.proxy.connection.MinecraftConnection;
|
||||||
import com.velocitypowered.proxy.connection.MinecraftConnectionAssociation;
|
import com.velocitypowered.proxy.connection.MinecraftConnectionAssociation;
|
||||||
import com.velocitypowered.proxy.connection.backend.VelocityServerConnection;
|
import com.velocitypowered.proxy.connection.backend.VelocityServerConnection;
|
||||||
@ -89,10 +90,12 @@ import java.util.ArrayList;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.CompletionException;
|
import java.util.concurrent.CompletionException;
|
||||||
@ -148,6 +151,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player,
|
|||||||
private @Nullable VelocityServerConnection connectionInFlight;
|
private @Nullable VelocityServerConnection connectionInFlight;
|
||||||
private @Nullable PlayerSettings settings;
|
private @Nullable PlayerSettings settings;
|
||||||
private @Nullable ModInfo modInfo;
|
private @Nullable ModInfo modInfo;
|
||||||
|
private final Set<VelocityBossBarImplementation> bossBars = new HashSet<>();
|
||||||
private Component playerListHeader = Component.empty();
|
private Component playerListHeader = Component.empty();
|
||||||
private Component playerListFooter = Component.empty();
|
private Component playerListFooter = Component.empty();
|
||||||
private final InternalTabList tabList;
|
private final InternalTabList tabList;
|
||||||
@ -198,6 +202,15 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player,
|
|||||||
this.chatBuilderFactory = new ChatBuilderFactory(this.getProtocolVersion());
|
this.chatBuilderFactory = new ChatBuilderFactory(this.getProtocolVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used for cleaning up resources during a disconnection.
|
||||||
|
*/
|
||||||
|
public void disconnected() {
|
||||||
|
for (final VelocityBossBarImplementation bar : this.bossBars) {
|
||||||
|
bar.viewerDisconnected(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public ChatBuilderFactory getChatBuilderFactory() {
|
public ChatBuilderFactory getChatBuilderFactory() {
|
||||||
return chatBuilderFactory;
|
return chatBuilderFactory;
|
||||||
}
|
}
|
||||||
@ -516,14 +529,20 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player,
|
|||||||
@Override
|
@Override
|
||||||
public void hideBossBar(@NonNull BossBar bar) {
|
public void hideBossBar(@NonNull BossBar bar) {
|
||||||
if (this.getProtocolVersion().noLessThan(ProtocolVersion.MINECRAFT_1_9)) {
|
if (this.getProtocolVersion().noLessThan(ProtocolVersion.MINECRAFT_1_9)) {
|
||||||
this.server.getBossBarManager().removeBossBar(this, bar);
|
final VelocityBossBarImplementation impl = VelocityBossBarImplementation.get(bar);
|
||||||
|
if (impl.viewerRemove(this)) {
|
||||||
|
this.bossBars.remove(impl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void showBossBar(@NonNull BossBar bar) {
|
public void showBossBar(@NonNull BossBar bar) {
|
||||||
if (this.getProtocolVersion().noLessThan(ProtocolVersion.MINECRAFT_1_9)) {
|
if (this.getProtocolVersion().noLessThan(ProtocolVersion.MINECRAFT_1_9)) {
|
||||||
this.server.getBossBarManager().addBossBar(this, bar);
|
final VelocityBossBarImplementation impl = VelocityBossBarImplementation.get(bar);
|
||||||
|
if (impl.viewerAdd(this)) {
|
||||||
|
this.bossBars.add(impl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,12 +22,40 @@ import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
|||||||
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
||||||
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
||||||
import com.velocitypowered.proxy.protocol.packet.chat.ComponentHolder;
|
import com.velocitypowered.proxy.protocol.packet.chat.ComponentHolder;
|
||||||
|
import com.velocitypowered.proxy.util.collect.Enum2IntMap;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import net.kyori.adventure.bossbar.BossBar;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
public class BossBarPacket implements MinecraftPacket {
|
public class BossBarPacket implements MinecraftPacket {
|
||||||
|
|
||||||
|
private static final Enum2IntMap<BossBar.Color> COLORS_TO_PROTOCOL =
|
||||||
|
new Enum2IntMap.Builder<>(BossBar.Color.class)
|
||||||
|
.put(BossBar.Color.PINK, 0)
|
||||||
|
.put(BossBar.Color.BLUE, 1)
|
||||||
|
.put(BossBar.Color.RED, 2)
|
||||||
|
.put(BossBar.Color.GREEN, 3)
|
||||||
|
.put(BossBar.Color.YELLOW, 4)
|
||||||
|
.put(BossBar.Color.PURPLE, 5)
|
||||||
|
.put(BossBar.Color.WHITE, 6)
|
||||||
|
.build();
|
||||||
|
private static final Enum2IntMap<BossBar.Overlay> OVERLAY_TO_PROTOCOL =
|
||||||
|
new Enum2IntMap.Builder<>(BossBar.Overlay.class)
|
||||||
|
.put(BossBar.Overlay.PROGRESS, 0)
|
||||||
|
.put(BossBar.Overlay.NOTCHED_6, 1)
|
||||||
|
.put(BossBar.Overlay.NOTCHED_10, 2)
|
||||||
|
.put(BossBar.Overlay.NOTCHED_12, 3)
|
||||||
|
.put(BossBar.Overlay.NOTCHED_20, 4)
|
||||||
|
.build();
|
||||||
|
private static final Enum2IntMap<BossBar.Flag> FLAG_BITS_TO_PROTOCOL =
|
||||||
|
new Enum2IntMap.Builder<>(BossBar.Flag.class)
|
||||||
|
.put(BossBar.Flag.DARKEN_SCREEN, 0x1)
|
||||||
|
.put(BossBar.Flag.PLAY_BOSS_MUSIC, 0x2)
|
||||||
|
.put(BossBar.Flag.CREATE_WORLD_FOG, 0x4)
|
||||||
|
.build();
|
||||||
|
|
||||||
public static final int ADD = 0;
|
public static final int ADD = 0;
|
||||||
public static final int REMOVE = 1;
|
public static final int REMOVE = 1;
|
||||||
public static final int UPDATE_PERCENT = 2;
|
public static final int UPDATE_PERCENT = 2;
|
||||||
@ -42,6 +70,66 @@ public class BossBarPacket implements MinecraftPacket {
|
|||||||
private int overlay;
|
private int overlay;
|
||||||
private short flags;
|
private short flags;
|
||||||
|
|
||||||
|
public static BossBarPacket createAddPacket(
|
||||||
|
final UUID id,
|
||||||
|
final BossBar bar,
|
||||||
|
final ComponentHolder name
|
||||||
|
) {
|
||||||
|
final BossBarPacket packet = new BossBarPacket();
|
||||||
|
packet.setUuid(id);
|
||||||
|
packet.setAction(BossBarPacket.ADD);
|
||||||
|
packet.setName(name);
|
||||||
|
packet.setColor(COLORS_TO_PROTOCOL.get(bar.color()));
|
||||||
|
packet.setOverlay(OVERLAY_TO_PROTOCOL.get(bar.overlay()));
|
||||||
|
packet.setPercent(bar.progress());
|
||||||
|
packet.setFlags(serializeFlags(bar.flags()));
|
||||||
|
return packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BossBarPacket createRemovePacket(final UUID id, final BossBar bar) {
|
||||||
|
final BossBarPacket packet = new BossBarPacket();
|
||||||
|
packet.setUuid(id);
|
||||||
|
packet.setAction(REMOVE);
|
||||||
|
return packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BossBarPacket createUpdateProgressPacket(final UUID id, final BossBar bar) {
|
||||||
|
final BossBarPacket packet = new BossBarPacket();
|
||||||
|
packet.setUuid(id);
|
||||||
|
packet.setAction(UPDATE_PERCENT);
|
||||||
|
packet.setPercent(bar.progress());
|
||||||
|
return packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BossBarPacket createUpdateNamePacket(
|
||||||
|
final UUID id,
|
||||||
|
final BossBar bar,
|
||||||
|
final ComponentHolder name
|
||||||
|
) {
|
||||||
|
final BossBarPacket packet = new BossBarPacket();
|
||||||
|
packet.setUuid(id);
|
||||||
|
packet.setAction(UPDATE_NAME);
|
||||||
|
packet.setName(name);
|
||||||
|
return packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BossBarPacket createUpdateStylePacket(final UUID id, final BossBar bar) {
|
||||||
|
final BossBarPacket packet = new BossBarPacket();
|
||||||
|
packet.setUuid(id);
|
||||||
|
packet.setAction(UPDATE_STYLE);
|
||||||
|
packet.setColor(COLORS_TO_PROTOCOL.get(bar.color()));
|
||||||
|
packet.setOverlay(OVERLAY_TO_PROTOCOL.get(bar.overlay()));
|
||||||
|
return packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BossBarPacket createUpdatePropertiesPacket(final UUID id, final BossBar bar) {
|
||||||
|
final BossBarPacket packet = new BossBarPacket();
|
||||||
|
packet.setUuid(id);
|
||||||
|
packet.setAction(UPDATE_PROPERTIES);
|
||||||
|
packet.setFlags(serializeFlags(bar.flags()));
|
||||||
|
return packet;
|
||||||
|
}
|
||||||
|
|
||||||
public UUID getUuid() {
|
public UUID getUuid() {
|
||||||
if (uuid == null) {
|
if (uuid == null) {
|
||||||
throw new IllegalStateException("No boss bar UUID specified");
|
throw new IllegalStateException("No boss bar UUID specified");
|
||||||
@ -187,15 +275,16 @@ public class BossBarPacket implements MinecraftPacket {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static byte serializeFlags(Set<BossBar.Flag> flags) {
|
||||||
|
byte val = 0x0;
|
||||||
|
for (BossBar.Flag flag : flags) {
|
||||||
|
val |= FLAG_BITS_TO_PROTOCOL.get(flag);
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean handle(MinecraftSessionHandler handler) {
|
public boolean handle(MinecraftSessionHandler handler) {
|
||||||
return handler.handle(this);
|
return handler.handle(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BossBarPacket createRemovePacket(UUID id) {
|
|
||||||
BossBarPacket packet = new BossBarPacket();
|
|
||||||
packet.setUuid(id);
|
|
||||||
packet.setAction(REMOVE);
|
|
||||||
return packet;
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
package com.velocitypowered.proxy.provider;
|
package com.velocitypowered.proxy.provider;
|
||||||
|
|
||||||
|
import com.google.auto.service.AutoService;
|
||||||
import com.velocitypowered.proxy.util.TranslatableMapper;
|
import com.velocitypowered.proxy.util.TranslatableMapper;
|
||||||
import net.kyori.adventure.text.logger.slf4j.ComponentLogger;
|
import net.kyori.adventure.text.logger.slf4j.ComponentLogger;
|
||||||
import net.kyori.adventure.text.logger.slf4j.ComponentLoggerProvider;
|
import net.kyori.adventure.text.logger.slf4j.ComponentLoggerProvider;
|
||||||
@ -27,6 +28,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
/**
|
/**
|
||||||
* Velocity ComponentLogger Provider.
|
* Velocity ComponentLogger Provider.
|
||||||
*/
|
*/
|
||||||
|
@AutoService(ComponentLoggerProvider.class)
|
||||||
@SuppressWarnings("UnstableApiUsage")
|
@SuppressWarnings("UnstableApiUsage")
|
||||||
public final class ComponentLoggerProviderImpl implements ComponentLoggerProvider {
|
public final class ComponentLoggerProviderImpl implements ComponentLoggerProvider {
|
||||||
private static final ANSIComponentSerializer SERIALIZER = ANSIComponentSerializer.builder()
|
private static final ANSIComponentSerializer SERIALIZER = ANSIComponentSerializer.builder()
|
||||||
|
@ -1,281 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2020-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.util.bossbar;
|
|
||||||
|
|
||||||
import com.google.common.collect.MapMaker;
|
|
||||||
import com.velocitypowered.api.network.ProtocolVersion;
|
|
||||||
import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
|
|
||||||
import com.velocitypowered.proxy.protocol.packet.BossBarPacket;
|
|
||||||
import com.velocitypowered.proxy.protocol.packet.chat.ComponentHolder;
|
|
||||||
import com.velocitypowered.proxy.util.collect.Enum2IntMap;
|
|
||||||
import com.velocitypowered.proxy.util.concurrent.Once;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
|
||||||
import net.kyori.adventure.bossbar.BossBar;
|
|
||||||
import net.kyori.adventure.bossbar.BossBar.Color;
|
|
||||||
import net.kyori.adventure.bossbar.BossBar.Flag;
|
|
||||||
import net.kyori.adventure.bossbar.BossBar.Overlay;
|
|
||||||
import net.kyori.adventure.text.Component;
|
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Manages all boss bars known to the proxy.
|
|
||||||
*/
|
|
||||||
public class AdventureBossBarManager implements BossBar.Listener {
|
|
||||||
|
|
||||||
private static final Enum2IntMap<Color> COLORS_TO_PROTOCOL =
|
|
||||||
new Enum2IntMap.Builder<>(Color.class)
|
|
||||||
.put(Color.PINK, 0)
|
|
||||||
.put(Color.BLUE, 1)
|
|
||||||
.put(Color.RED, 2)
|
|
||||||
.put(Color.GREEN, 3)
|
|
||||||
.put(Color.YELLOW, 4)
|
|
||||||
.put(Color.PURPLE, 5)
|
|
||||||
.put(Color.WHITE, 6)
|
|
||||||
.build();
|
|
||||||
private static final Enum2IntMap<Overlay> OVERLAY_TO_PROTOCOL =
|
|
||||||
new Enum2IntMap.Builder<>(Overlay.class)
|
|
||||||
.put(Overlay.PROGRESS, 0)
|
|
||||||
.put(Overlay.NOTCHED_6, 1)
|
|
||||||
.put(Overlay.NOTCHED_10, 2)
|
|
||||||
.put(Overlay.NOTCHED_12, 3)
|
|
||||||
.put(Overlay.NOTCHED_20, 4)
|
|
||||||
.build();
|
|
||||||
private static final Enum2IntMap<Flag> FLAG_BITS_TO_PROTOCOL =
|
|
||||||
new Enum2IntMap.Builder<>(Flag.class)
|
|
||||||
.put(Flag.DARKEN_SCREEN, 0x1)
|
|
||||||
.put(Flag.PLAY_BOSS_MUSIC, 0x2)
|
|
||||||
.put(Flag.CREATE_WORLD_FOG, 0x4)
|
|
||||||
.build();
|
|
||||||
private final Map<BossBar, BossBarHolder> bars;
|
|
||||||
|
|
||||||
public AdventureBossBarManager() {
|
|
||||||
this.bars = new MapMaker().weakKeys().makeMap();
|
|
||||||
}
|
|
||||||
|
|
||||||
private @Nullable BossBarHolder getHandler(BossBar bar) {
|
|
||||||
return this.bars.get(bar);
|
|
||||||
}
|
|
||||||
|
|
||||||
private BossBarHolder getOrCreateHandler(BossBar bar) {
|
|
||||||
BossBarHolder holder = this.bars.computeIfAbsent(bar, k -> new BossBarHolder(bar));
|
|
||||||
holder.register();
|
|
||||||
return holder;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when a player disconnects from the proxy. Removes the player from any boss bar
|
|
||||||
* subscriptions.
|
|
||||||
*
|
|
||||||
* @param player the player to remove
|
|
||||||
*/
|
|
||||||
public void onDisconnect(ConnectedPlayer player) {
|
|
||||||
for (BossBarHolder holder : bars.values()) {
|
|
||||||
holder.subscribers.remove(player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds the specified player to the boss bar's viewers and spawns the boss bar, registering the
|
|
||||||
* boss bar if needed.
|
|
||||||
*
|
|
||||||
* @param player the intended viewer
|
|
||||||
* @param bar the boss bar to show
|
|
||||||
*/
|
|
||||||
public void addBossBar(ConnectedPlayer player, BossBar bar) {
|
|
||||||
BossBarHolder holder = this.getOrCreateHandler(bar);
|
|
||||||
if (holder.subscribers.add(player)) {
|
|
||||||
player.getConnection().write(holder.createAddPacket(player));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the specified player to the boss bar's viewers and despawns the boss bar.
|
|
||||||
*
|
|
||||||
* @param player the intended viewer
|
|
||||||
* @param bar the boss bar to hide
|
|
||||||
*/
|
|
||||||
public void removeBossBar(ConnectedPlayer player, BossBar bar) {
|
|
||||||
BossBarHolder holder = this.getHandler(bar);
|
|
||||||
if (holder != null && holder.subscribers.remove(player)) {
|
|
||||||
player.getConnection().write(holder.createRemovePacket());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void bossBarNameChanged(@NonNull BossBar bar, @NonNull Component oldName,
|
|
||||||
@NonNull Component newName) {
|
|
||||||
BossBarHolder holder = this.getHandler(bar);
|
|
||||||
if (holder == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (ConnectedPlayer player : holder.subscribers) {
|
|
||||||
Component translated = player.translateMessage(newName);
|
|
||||||
BossBarPacket packet = holder.createTitleUpdate(
|
|
||||||
translated, player.getProtocolVersion());
|
|
||||||
player.getConnection().write(packet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void bossBarProgressChanged(@NonNull BossBar bar, float oldPercent, float newPercent) {
|
|
||||||
BossBarHolder holder = this.getHandler(bar);
|
|
||||||
if (holder == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
BossBarPacket packet = holder
|
|
||||||
.createPercentUpdate(newPercent);
|
|
||||||
for (ConnectedPlayer player : holder.subscribers) {
|
|
||||||
player.getConnection().write(packet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void bossBarColorChanged(@NonNull BossBar bar, @NonNull Color oldColor,
|
|
||||||
@NonNull Color newColor) {
|
|
||||||
BossBarHolder holder = this.getHandler(bar);
|
|
||||||
if (holder == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
BossBarPacket packet = holder.createColorUpdate(newColor);
|
|
||||||
for (ConnectedPlayer player : holder.subscribers) {
|
|
||||||
player.getConnection().write(packet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void bossBarOverlayChanged(@NonNull BossBar bar, @NonNull Overlay oldOverlay,
|
|
||||||
@NonNull Overlay newOverlay) {
|
|
||||||
BossBarHolder holder = this.getHandler(bar);
|
|
||||||
if (holder == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
BossBarPacket packet = holder
|
|
||||||
.createOverlayUpdate(newOverlay);
|
|
||||||
for (ConnectedPlayer player : holder.subscribers) {
|
|
||||||
player.getConnection().write(packet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void bossBarFlagsChanged(@NonNull BossBar bar, @NonNull Set<Flag> added,
|
|
||||||
@NonNull Set<Flag> removed) {
|
|
||||||
BossBarHolder holder = this.getHandler(bar);
|
|
||||||
if (holder == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
BossBarPacket packet = holder.createFlagsUpdate();
|
|
||||||
for (ConnectedPlayer player : holder.subscribers) {
|
|
||||||
player.getConnection().write(packet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class BossBarHolder {
|
|
||||||
|
|
||||||
private final UUID id = UUID.randomUUID();
|
|
||||||
private final BossBar bar;
|
|
||||||
private final Set<ConnectedPlayer> subscribers = Collections.newSetFromMap(
|
|
||||||
new MapMaker().weakKeys().makeMap());
|
|
||||||
private final Once registrationOnce = new Once();
|
|
||||||
|
|
||||||
BossBarHolder(BossBar bar) {
|
|
||||||
this.bar = bar;
|
|
||||||
}
|
|
||||||
|
|
||||||
void register() {
|
|
||||||
registrationOnce.run(() -> this.bar.addListener(AdventureBossBarManager.this));
|
|
||||||
}
|
|
||||||
|
|
||||||
BossBarPacket createRemovePacket() {
|
|
||||||
return BossBarPacket.createRemovePacket(this.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
BossBarPacket createAddPacket(ConnectedPlayer player) {
|
|
||||||
BossBarPacket packet = new BossBarPacket();
|
|
||||||
packet.setUuid(this.id);
|
|
||||||
packet.setAction(BossBarPacket.ADD);
|
|
||||||
packet.setName(
|
|
||||||
new ComponentHolder(player.getProtocolVersion(), player.translateMessage(bar.name())));
|
|
||||||
packet.setColor(COLORS_TO_PROTOCOL.get(bar.color()));
|
|
||||||
packet.setOverlay(OVERLAY_TO_PROTOCOL.get(bar.overlay()));
|
|
||||||
packet.setPercent(bar.progress());
|
|
||||||
packet.setFlags(serializeFlags(bar.flags()));
|
|
||||||
return packet;
|
|
||||||
}
|
|
||||||
|
|
||||||
BossBarPacket createPercentUpdate(float newPercent) {
|
|
||||||
BossBarPacket packet = new BossBarPacket();
|
|
||||||
packet.setUuid(this.id);
|
|
||||||
packet.setAction(BossBarPacket.UPDATE_PERCENT);
|
|
||||||
packet.setPercent(newPercent);
|
|
||||||
return packet;
|
|
||||||
}
|
|
||||||
|
|
||||||
BossBarPacket createColorUpdate(Color color) {
|
|
||||||
BossBarPacket packet = new BossBarPacket();
|
|
||||||
packet.setUuid(this.id);
|
|
||||||
packet.setAction(BossBarPacket.UPDATE_STYLE);
|
|
||||||
packet.setColor(COLORS_TO_PROTOCOL.get(color));
|
|
||||||
packet.setOverlay(OVERLAY_TO_PROTOCOL.get(bar.overlay()));
|
|
||||||
packet.setFlags(serializeFlags(bar.flags()));
|
|
||||||
return packet;
|
|
||||||
}
|
|
||||||
|
|
||||||
BossBarPacket createTitleUpdate(Component name,
|
|
||||||
ProtocolVersion version) {
|
|
||||||
BossBarPacket packet = new BossBarPacket();
|
|
||||||
packet.setUuid(this.id);
|
|
||||||
packet.setAction(BossBarPacket.UPDATE_NAME);
|
|
||||||
packet.setName(new ComponentHolder(version, name));
|
|
||||||
return packet;
|
|
||||||
}
|
|
||||||
|
|
||||||
BossBarPacket createFlagsUpdate() {
|
|
||||||
return createFlagsUpdate(bar.flags());
|
|
||||||
}
|
|
||||||
|
|
||||||
BossBarPacket createFlagsUpdate(Set<Flag> newFlags) {
|
|
||||||
BossBarPacket packet = new BossBarPacket();
|
|
||||||
packet.setUuid(this.id);
|
|
||||||
packet.setAction(BossBarPacket.UPDATE_PROPERTIES);
|
|
||||||
packet.setColor(COLORS_TO_PROTOCOL.get(this.bar.color()));
|
|
||||||
packet.setFlags(this.serializeFlags(newFlags));
|
|
||||||
return packet;
|
|
||||||
}
|
|
||||||
|
|
||||||
BossBarPacket createOverlayUpdate(Overlay overlay) {
|
|
||||||
BossBarPacket packet = new BossBarPacket();
|
|
||||||
packet.setUuid(this.id);
|
|
||||||
packet.setAction(BossBarPacket.UPDATE_STYLE);
|
|
||||||
packet.setColor(COLORS_TO_PROTOCOL.get(bar.color()));
|
|
||||||
packet.setOverlay(OVERLAY_TO_PROTOCOL.get(overlay));
|
|
||||||
return packet;
|
|
||||||
}
|
|
||||||
|
|
||||||
private byte serializeFlags(Set<Flag> flags) {
|
|
||||||
byte val = 0x0;
|
|
||||||
for (Flag flag : flags) {
|
|
||||||
val |= FLAG_BITS_TO_PROTOCOL.get(flag);
|
|
||||||
}
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
com.velocitypowered.proxy.provider.ComponentLoggerProviderImpl
|
|
Laden…
x
In neuem Issue referenzieren
Einen Benutzer sperren