feat: improve tablist (#1532)
* fix: setDisplayName in TabListEntry duplicating players on 1.7.10 (#1530) * feat: expose toggling hat layer in TabListEntry (#1531)
This commit is contained in:
@@ -40,6 +40,7 @@ public interface TabList {
|
||||
* Adds a {@link TabListEntry} to the {@link Player}'s tab list.
|
||||
*
|
||||
* @param entry to add to the tab list
|
||||
* @throws IllegalArgumentException on versions below 1.19.3, if an entry with the same UUID already exists
|
||||
*/
|
||||
void addEntry(TabListEntry entry);
|
||||
|
||||
@@ -47,6 +48,7 @@ public interface TabList {
|
||||
* Adds a {@link Iterable} of {@link TabListEntry}'s to the {@link Player}'s tab list.
|
||||
*
|
||||
* @param entries to add to the tab list
|
||||
* @throws IllegalArgumentException on versions below 1.19.3, if an entry with the same UUID already exists
|
||||
*/
|
||||
default void addEntries(Iterable<TabListEntry> entries) {
|
||||
for (TabListEntry entry : entries) {
|
||||
@@ -58,6 +60,7 @@ public interface TabList {
|
||||
* Adds an array of {@link TabListEntry}'s to the {@link Player}'s tab list.
|
||||
*
|
||||
* @param entries to add to the tab list
|
||||
* @throws IllegalArgumentException on versions below 1.19.3, if an entry with the same UUID already exists
|
||||
*/
|
||||
default void addEntries(TabListEntry... entries) {
|
||||
for (TabListEntry entry : entries) {
|
||||
@@ -187,6 +190,26 @@ public interface TabList {
|
||||
* @deprecated Internal usage. Use {@link TabListEntry.Builder} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
TabListEntry buildEntry(GameProfile profile, @Nullable Component displayName, int latency,
|
||||
int gameMode, @Nullable ChatSession chatSession, boolean listed, int listOrder);
|
||||
default TabListEntry buildEntry(GameProfile profile, @Nullable Component displayName, int latency,
|
||||
int gameMode, @Nullable ChatSession chatSession, boolean listed, int listOrder) {
|
||||
return buildEntry(profile, displayName, latency, gameMode, chatSession, listed, listOrder, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an entry in a {@link Player}'s tab list.
|
||||
*
|
||||
* @param profile the profile
|
||||
* @param displayName the display name
|
||||
* @param latency the latency
|
||||
* @param gameMode the game mode
|
||||
* @param chatSession the chat session
|
||||
* @param listed the visible status of entry
|
||||
* @param listOrder the order/priority of entry in the tab list
|
||||
* @param showHat the visibility of this entry's hat layer
|
||||
* @return the entry
|
||||
* @deprecated Internal usage. Use {@link TabListEntry.Builder} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
TabListEntry buildEntry(GameProfile profile, @Nullable Component displayName, int latency,
|
||||
int gameMode, @Nullable ChatSession chatSession, boolean listed, int listOrder, boolean showHat);
|
||||
}
|
||||
|
@@ -160,6 +160,27 @@ public interface TabListEntry extends KeyIdentifiable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this entry's hat layer is shown in the tab list.
|
||||
*
|
||||
* @return whether to show this entry's hat layer
|
||||
* @sinceMinecraft 1.21.4
|
||||
*/
|
||||
default boolean isShowHat() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether to show this entry's hat layer in the tab list.
|
||||
*
|
||||
* @param showHat whether to show this entry's hat layer
|
||||
* @return {@code this}, for chaining
|
||||
* @sinceMinecraft 1.21.4
|
||||
*/
|
||||
default TabListEntry setShowHat(boolean showHat) {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Builder} to create a {@link TabListEntry}.
|
||||
*
|
||||
@@ -183,6 +204,7 @@ public interface TabListEntry extends KeyIdentifiable {
|
||||
private int gameMode = 0;
|
||||
private boolean listed = true;
|
||||
private int listOrder = 0;
|
||||
private boolean showHat;
|
||||
|
||||
private @Nullable ChatSession chatSession;
|
||||
|
||||
@@ -268,7 +290,7 @@ public interface TabListEntry extends KeyIdentifiable {
|
||||
* Sets whether this entry should be visible.
|
||||
*
|
||||
* @param listed to set
|
||||
* @return ${code this}, for chaining
|
||||
* @return {@code this}, for chaining
|
||||
* @see TabListEntry#isListed()
|
||||
*/
|
||||
public Builder listed(boolean listed) {
|
||||
@@ -280,7 +302,7 @@ public interface TabListEntry extends KeyIdentifiable {
|
||||
* Sets the order/priority of this entry in the tab list.
|
||||
*
|
||||
* @param order to set
|
||||
* @return ${code this}, for chaining
|
||||
* @return {@code this}, for chaining
|
||||
* @sinceMinecraft 1.21.2
|
||||
* @see TabListEntry#getListOrder()
|
||||
*/
|
||||
@@ -289,6 +311,18 @@ public interface TabListEntry extends KeyIdentifiable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether this entry's hat layer should be shown in the tab list.
|
||||
*
|
||||
* @param showHat to set
|
||||
* @return {@code this}, for chaining
|
||||
* @see TabListEntry#isShowHat()
|
||||
*/
|
||||
public Builder showHat(boolean showHat) {
|
||||
this.showHat = showHat;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the {@link TabListEntry} specified by {@code this} {@link Builder}.
|
||||
*
|
||||
@@ -301,7 +335,7 @@ public interface TabListEntry extends KeyIdentifiable {
|
||||
if (profile == null) {
|
||||
throw new IllegalStateException("The GameProfile must be set when building a TabListEntry");
|
||||
}
|
||||
return tabList.buildEntry(profile, displayName, latency, gameMode, chatSession, listed, listOrder);
|
||||
return tabList.buildEntry(profile, displayName, latency, gameMode, chatSession, listed, listOrder, showHat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -166,7 +166,7 @@ public class KeyedVelocityTabList implements InternalTabList {
|
||||
|
||||
@Override
|
||||
public TabListEntry buildEntry(GameProfile profile, @Nullable Component displayName, int latency,
|
||||
int gameMode, @Nullable ChatSession chatSession, boolean listed, int listOrder) {
|
||||
int gameMode, @Nullable ChatSession chatSession, boolean listed, int listOrder, boolean showHat) {
|
||||
return buildEntry(profile, displayName, latency, gameMode, chatSession, listed);
|
||||
}
|
||||
|
||||
|
@@ -90,7 +90,7 @@ public class VelocityTabList implements InternalTabList {
|
||||
} else {
|
||||
entry = new VelocityTabListEntry(this, entry1.getProfile(),
|
||||
entry1.getDisplayNameComponent().orElse(null),
|
||||
entry1.getLatency(), entry1.getGameMode(), entry1.getChatSession(), entry1.isListed(), entry1.getListOrder());
|
||||
entry1.getLatency(), entry1.getGameMode(), entry1.getChatSession(), entry1.isListed(), entry1.getListOrder(), entry1.isShowHat());
|
||||
}
|
||||
|
||||
EnumSet<UpsertPlayerInfoPacket.Action> actions = EnumSet
|
||||
@@ -134,6 +134,11 @@ public class VelocityTabList implements InternalTabList {
|
||||
actions.add(UpsertPlayerInfoPacket.Action.UPDATE_LIST_ORDER);
|
||||
playerInfoEntry.setListOrder(entry.getListOrder());
|
||||
}
|
||||
if (!Objects.equals(previousEntry.isShowHat(), entry.isShowHat())
|
||||
&& player.getProtocolVersion().noLessThan(ProtocolVersion.MINECRAFT_1_21_4)) {
|
||||
actions.add(UpsertPlayerInfoPacket.Action.UPDATE_HAT);
|
||||
playerInfoEntry.setShowHat(entry.isShowHat());
|
||||
}
|
||||
if (!Objects.equals(previousEntry.getChatSession(), entry.getChatSession())) {
|
||||
ChatSession from = entry.getChatSession();
|
||||
if (from != null) {
|
||||
@@ -173,6 +178,10 @@ public class VelocityTabList implements InternalTabList {
|
||||
actions.add(UpsertPlayerInfoPacket.Action.UPDATE_LIST_ORDER);
|
||||
playerInfoEntry.setListOrder(entry.getListOrder());
|
||||
}
|
||||
if (!entry.isShowHat() && player.getProtocolVersion().noLessThan(ProtocolVersion.MINECRAFT_1_21_4)) {
|
||||
actions.add(UpsertPlayerInfoPacket.Action.UPDATE_HAT);
|
||||
playerInfoEntry.setShowHat(entry.isShowHat());
|
||||
}
|
||||
}
|
||||
return entry;
|
||||
});
|
||||
@@ -218,9 +227,9 @@ public class VelocityTabList implements InternalTabList {
|
||||
@Override
|
||||
public TabListEntry buildEntry(GameProfile profile, @Nullable Component displayName, int latency,
|
||||
int gameMode,
|
||||
@Nullable ChatSession chatSession, boolean listed, int listOrder) {
|
||||
@Nullable ChatSession chatSession, boolean listed, int listOrder, boolean showHat) {
|
||||
return new VelocityTabListEntry(this, profile, displayName, latency, gameMode, chatSession,
|
||||
listed, listOrder);
|
||||
listed, listOrder, showHat);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -258,7 +267,8 @@ public class VelocityTabList implements InternalTabList {
|
||||
-1,
|
||||
null,
|
||||
false,
|
||||
0
|
||||
0,
|
||||
true
|
||||
)
|
||||
);
|
||||
} else {
|
||||
|
@@ -40,6 +40,7 @@ public class VelocityTabListEntry implements TabListEntry {
|
||||
private int gameMode;
|
||||
private boolean listed;
|
||||
private int listOrder;
|
||||
private boolean showHat;
|
||||
private @Nullable ChatSession session;
|
||||
|
||||
/**
|
||||
@@ -47,7 +48,7 @@ public class VelocityTabListEntry implements TabListEntry {
|
||||
*/
|
||||
public VelocityTabListEntry(VelocityTabList tabList, GameProfile profile, Component displayName,
|
||||
int latency,
|
||||
int gameMode, @Nullable ChatSession session, boolean listed, int listOrder) {
|
||||
int gameMode, @Nullable ChatSession session, boolean listed, int listOrder, boolean showHat) {
|
||||
this.tabList = tabList;
|
||||
this.profile = profile;
|
||||
this.displayName = displayName;
|
||||
@@ -56,6 +57,7 @@ public class VelocityTabListEntry implements TabListEntry {
|
||||
this.session = session;
|
||||
this.listed = listed;
|
||||
this.listOrder = listOrder;
|
||||
this.showHat = showHat;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -173,4 +175,24 @@ public class VelocityTabListEntry implements TabListEntry {
|
||||
void setListOrderWithoutUpdate(int listOrder) {
|
||||
this.listOrder = listOrder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isShowHat() {
|
||||
return showHat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VelocityTabListEntry setShowHat(boolean showHat) {
|
||||
this.showHat = showHat;
|
||||
if (tabList.getPlayer().getProtocolVersion().noLessThan(ProtocolVersion.MINECRAFT_1_21_4)) {
|
||||
UpsertPlayerInfoPacket.Entry upsertEntry = this.tabList.createRawEntry(this);
|
||||
upsertEntry.setShowHat(showHat);
|
||||
tabList.emitActionRaw(UpsertPlayerInfoPacket.Action.UPDATE_HAT, upsertEntry);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
void setShowHatWithoutUpdate(boolean showHat) {
|
||||
this.showHat = showHat;
|
||||
}
|
||||
}
|
@@ -35,6 +35,8 @@ public class VelocityTabListEntryLegacy extends KeyedVelocityTabListEntry {
|
||||
@Override
|
||||
public TabListEntry setDisplayName(@Nullable Component displayName) {
|
||||
getTabList().removeEntry(getProfile().getId()); // We have to remove first if updating
|
||||
return super.setDisplayName(displayName);
|
||||
setDisplayNameInternal(displayName);
|
||||
getTabList().addEntry(this);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
@@ -19,6 +19,8 @@ package com.velocitypowered.proxy.tablist;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.velocitypowered.api.proxy.ProxyServer;
|
||||
import com.velocitypowered.api.proxy.crypto.IdentifiedKey;
|
||||
import com.velocitypowered.api.proxy.player.ChatSession;
|
||||
import com.velocitypowered.api.proxy.player.TabListEntry;
|
||||
import com.velocitypowered.api.util.GameProfile;
|
||||
import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
|
||||
@@ -133,9 +135,22 @@ public class VelocityTabListLegacy extends KeyedVelocityTabList {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TabListEntry buildEntry(GameProfile profile,
|
||||
net.kyori.adventure.text.@Nullable Component displayName,
|
||||
int latency, int gameMode, @Nullable IdentifiedKey key) {
|
||||
return new VelocityTabListEntryLegacy(this, profile, displayName, latency, gameMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TabListEntry buildEntry(GameProfile profile, @Nullable Component displayName, int latency,
|
||||
int gameMode) {
|
||||
int gameMode, @Nullable ChatSession chatSession, boolean listed) {
|
||||
return new VelocityTabListEntryLegacy(this, profile, displayName, latency, gameMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TabListEntry buildEntry(GameProfile profile, @Nullable Component displayName, int latency,
|
||||
int gameMode, @Nullable ChatSession chatSession, boolean listed, int listOrder, boolean showHat) {
|
||||
return new VelocityTabListEntryLegacy(this, profile, displayName, latency, gameMode);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user