geforkt von Mirrors/Velocity
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.ResourceUtils;
|
||||
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.Ratelimiters;
|
||||
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 boolean shutdown = false;
|
||||
private final VelocityPluginManager pluginManager;
|
||||
private final AdventureBossBarManager bossBarManager;
|
||||
|
||||
private final Map<UUID, ConnectedPlayer> connectionsByUuid = new ConcurrentHashMap<>();
|
||||
private final Map<String, ConnectedPlayer> connectionsByName = new ConcurrentHashMap<>();
|
||||
@ -173,7 +171,6 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
|
||||
servers = new ServerMap(this);
|
||||
serverListPingHandler = new ServerListPingHandler(this);
|
||||
this.options = options;
|
||||
this.bossBarManager = new AdventureBossBarManager();
|
||||
}
|
||||
|
||||
public KeyPair getServerKeyPair() {
|
||||
@ -660,7 +657,7 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
|
||||
public void unregisterConnection(ConnectedPlayer connection) {
|
||||
connectionsByName.remove(connection.getUsername().toLowerCase(Locale.US), connection);
|
||||
connectionsByUuid.remove(connection.getUniqueId(), connection);
|
||||
bossBarManager.onDisconnect(connection);
|
||||
connection.disconnected();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -770,10 +767,6 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
|
||||
return audiences;
|
||||
}
|
||||
|
||||
public AdventureBossBarManager getBossBarManager() {
|
||||
return bossBarManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.ModInfo;
|
||||
import com.velocitypowered.proxy.VelocityServer;
|
||||
import com.velocitypowered.proxy.adventure.VelocityBossBarImplementation;
|
||||
import com.velocitypowered.proxy.connection.MinecraftConnection;
|
||||
import com.velocitypowered.proxy.connection.MinecraftConnectionAssociation;
|
||||
import com.velocitypowered.proxy.connection.backend.VelocityServerConnection;
|
||||
@ -89,10 +90,12 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionException;
|
||||
@ -148,6 +151,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player,
|
||||
private @Nullable VelocityServerConnection connectionInFlight;
|
||||
private @Nullable PlayerSettings settings;
|
||||
private @Nullable ModInfo modInfo;
|
||||
private final Set<VelocityBossBarImplementation> bossBars = new HashSet<>();
|
||||
private Component playerListHeader = Component.empty();
|
||||
private Component playerListFooter = Component.empty();
|
||||
private final InternalTabList tabList;
|
||||
@ -198,6 +202,15 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player,
|
||||
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() {
|
||||
return chatBuilderFactory;
|
||||
}
|
||||
@ -516,14 +529,20 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player,
|
||||
@Override
|
||||
public void hideBossBar(@NonNull BossBar bar) {
|
||||
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
|
||||
public void showBossBar(@NonNull BossBar bar) {
|
||||
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.ProtocolUtils;
|
||||
import com.velocitypowered.proxy.protocol.packet.chat.ComponentHolder;
|
||||
import com.velocitypowered.proxy.util.collect.Enum2IntMap;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import net.kyori.adventure.bossbar.BossBar;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
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 REMOVE = 1;
|
||||
public static final int UPDATE_PERCENT = 2;
|
||||
@ -42,6 +70,66 @@ public class BossBarPacket implements MinecraftPacket {
|
||||
private int overlay;
|
||||
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() {
|
||||
if (uuid == null) {
|
||||
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
|
||||
public boolean handle(MinecraftSessionHandler handler) {
|
||||
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;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import com.velocitypowered.proxy.util.TranslatableMapper;
|
||||
import net.kyori.adventure.text.logger.slf4j.ComponentLogger;
|
||||
import net.kyori.adventure.text.logger.slf4j.ComponentLoggerProvider;
|
||||
@ -27,6 +28,7 @@ import org.slf4j.LoggerFactory;
|
||||
/**
|
||||
* Velocity ComponentLogger Provider.
|
||||
*/
|
||||
@AutoService(ComponentLoggerProvider.class)
|
||||
@SuppressWarnings("UnstableApiUsage")
|
||||
public final class ComponentLoggerProviderImpl implements ComponentLoggerProvider {
|
||||
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…
In neuem Issue referenzieren
Einen Benutzer sperren