diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java index 919f93c64..b1212a04b 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java @@ -51,6 +51,7 @@ import com.velocitypowered.proxy.protocol.util.PluginMessageUtil; import com.velocitypowered.proxy.server.VelocityRegisteredServer; import com.velocitypowered.proxy.tablist.VelocityTabList; import com.velocitypowered.proxy.tablist.VelocityTabListLegacy; +import com.velocitypowered.proxy.util.DurationUtils; import com.velocitypowered.proxy.util.VelocityMessages; import com.velocitypowered.proxy.util.collect.CappedSet; import io.netty.buffer.ByteBufUtil; @@ -279,6 +280,39 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { } } + @Override + public void showTitle(net.kyori.adventure.title.@NonNull Title title) { + Gson gson = VelocityServer.getGsonInstance(this.getProtocolVersion()); + + TitlePacket titlePkt = new TitlePacket(); + titlePkt.setAction(TitlePacket.SET_TITLE); + titlePkt.setComponent(gson.toJson(title.title())); + connection.delayedWrite(titlePkt); + + TitlePacket subtitlePkt = new TitlePacket(); + subtitlePkt.setAction(TitlePacket.SET_SUBTITLE); + subtitlePkt.setComponent(gson.toJson(title.subtitle())); + connection.delayedWrite(titlePkt); + + TitlePacket timesPkt = TitlePacket.timesForProtocolVersion(this.getProtocolVersion()); + timesPkt.setFadeIn((int) DurationUtils.convertDurationToTicks(title.fadeInTime())); + timesPkt.setStay((int) DurationUtils.convertDurationToTicks(title.stayTime())); + timesPkt.setFadeOut((int) DurationUtils.convertDurationToTicks(title.fadeOutTime())); + connection.delayedWrite(timesPkt); + + connection.flush(); + } + + @Override + public void clearTitle() { + connection.write(TitlePacket.hideForProtocolVersion(this.getProtocolVersion())); + } + + @Override + public void resetTitle() { + connection.write(TitlePacket.resetForProtocolVersion(this.getProtocolVersion())); + } + @Override public ConnectionRequestBuilder createConnectionRequest(RegisteredServer server) { return new ConnectionRequestBuilderImpl(server); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/StatusSessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/StatusSessionHandler.java index 62455d760..278fd7c4a 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/StatusSessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/StatusSessionHandler.java @@ -25,7 +25,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.concurrent.CompletableFuture; -import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/util/DurationUtils.java b/proxy/src/main/java/com/velocitypowered/proxy/util/DurationUtils.java new file mode 100644 index 000000000..d2bb07f23 --- /dev/null +++ b/proxy/src/main/java/com/velocitypowered/proxy/util/DurationUtils.java @@ -0,0 +1,24 @@ +package com.velocitypowered.proxy.util; + +import java.time.Duration; + +/** + * Provides utility functions for working with durations. + */ +public class DurationUtils { + private static final long ONE_TICK_IN_MILLISECONDS = 50; + + private DurationUtils() { + throw new AssertionError("Instances of this class should not be created."); + } + + /** + * Converts the given duration to Minecraft ticks. + * + * @param duration the duration to convert into Minecraft ticks + * @return the duration represented as the number of Minecraft ticks + */ + public static long convertDurationToTicks(Duration duration) { + return duration.toMillis() / ONE_TICK_IN_MILLISECONDS; + } +}