|
@@ -1,64 +1,87 @@
|
|
package com.gmail.nossr50.chat.author;
|
|
package com.gmail.nossr50.chat.author;
|
|
|
|
|
|
|
|
+import com.gmail.nossr50.datatypes.chat.ChatChannel;
|
|
import com.gmail.nossr50.util.text.TextUtils;
|
|
import com.gmail.nossr50.util.text.TextUtils;
|
|
import com.google.common.base.Objects;
|
|
import com.google.common.base.Objects;
|
|
-import net.kyori.adventure.text.TextComponent;
|
|
|
|
import org.bukkit.entity.Player;
|
|
import org.bukkit.entity.Player;
|
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
|
import org.jetbrains.annotations.NotNull;
|
|
import org.jetbrains.annotations.NotNull;
|
|
-import org.jetbrains.annotations.Nullable;
|
|
|
|
|
|
|
|
|
|
+import java.util.HashMap;
|
|
import java.util.UUID;
|
|
import java.util.UUID;
|
|
|
|
|
|
public abstract class AbstractPlayerAuthor implements Author {
|
|
public abstract class AbstractPlayerAuthor implements Author {
|
|
private final @NotNull Player player;
|
|
private final @NotNull Player player;
|
|
- private @NotNull String displayName;
|
|
|
|
- private @Nullable TextComponent componentDisplayName;
|
|
|
|
- private @Nullable TextComponent componentUserName;
|
|
|
|
|
|
+ private @NotNull String lastKnownDisplayName;
|
|
|
|
+ private final @NotNull HashMap<ChatChannel, String> sanitizedNameCache;
|
|
|
|
|
|
public AbstractPlayerAuthor(@NotNull Player player) {
|
|
public AbstractPlayerAuthor(@NotNull Player player) {
|
|
this.player = player;
|
|
this.player = player;
|
|
- this.displayName = player.getDisplayName();
|
|
|
|
|
|
+ this.lastKnownDisplayName = player.getDisplayName();
|
|
|
|
+ this.sanitizedNameCache = new HashMap<>();
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * Grabs the {@link TextComponent} version of a players display name
|
|
|
|
- * Cached and only processed as needed
|
|
|
|
- * Always checks if the player display name has changed, if it has it regenerates the output
|
|
|
|
|
|
+ * Returns true if a players display name has changed
|
|
*
|
|
*
|
|
- * @return the {@link TextComponent} version of a players display name
|
|
|
|
|
|
+ * @return true if the players display name has changed
|
|
*/
|
|
*/
|
|
- public @NotNull TextComponent getComponentDisplayName() {
|
|
|
|
- //Not sure if this is expensive but it ensures always up to date names
|
|
|
|
- if(!player.getDisplayName().equals(displayName)) {
|
|
|
|
- displayName = player.getDisplayName();
|
|
|
|
- componentDisplayName = null;
|
|
|
|
- }
|
|
|
|
|
|
+ private boolean hasPlayerDisplayNameChanged() {
|
|
|
|
+ return !player.getDisplayName().equals(lastKnownDisplayName);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Player display names can change and this method will update the last known display name of this player
|
|
|
|
+ */
|
|
|
|
+ private void updateLastKnownDisplayName() {
|
|
|
|
+ lastKnownDisplayName = player.getDisplayName();
|
|
|
|
+ }
|
|
|
|
|
|
- if(componentDisplayName != null) {
|
|
|
|
- return componentDisplayName;
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Gets a sanitized name for a channel
|
|
|
|
+ * Sanitized names are names that are friendly to the {@link net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer}
|
|
|
|
+ * Sanitized names for authors are cached by channel and are only created as needed
|
|
|
|
+ * Sanitized names will update if a players display name has updated
|
|
|
|
+ *
|
|
|
|
+ * @param chatChannel target chat channel
|
|
|
|
+ * @return the sanitized name for a player
|
|
|
|
+ */
|
|
|
|
+ protected @NotNull String getSanitizedName(@NotNull ChatChannel chatChannel, boolean useDisplayName) {
|
|
|
|
+ //Already in cache
|
|
|
|
+ if(sanitizedNameCache.containsKey(chatChannel)) {
|
|
|
|
+ //Update cache
|
|
|
|
+ if(useDisplayName && hasPlayerDisplayNameChanged()) {
|
|
|
|
+ updateLastKnownDisplayName();
|
|
|
|
+ updateSanitizedNameCache(chatChannel, true);
|
|
|
|
+ }
|
|
} else {
|
|
} else {
|
|
- //convert to adventure component
|
|
|
|
- componentDisplayName = TextUtils.ofLegacyTextRaw(displayName);
|
|
|
|
|
|
+ //Update last known display name
|
|
|
|
+ if(useDisplayName && hasPlayerDisplayNameChanged()) {
|
|
|
|
+ updateLastKnownDisplayName();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //Add cache entry
|
|
|
|
+ updateSanitizedNameCache(chatChannel, useDisplayName);
|
|
}
|
|
}
|
|
- return componentDisplayName;
|
|
|
|
|
|
+
|
|
|
|
+ return sanitizedNameCache.get(chatChannel);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * Grabs the {@link TextComponent} version of a players current minecraft nickname
|
|
|
|
- * Cached and only processed as needed
|
|
|
|
|
|
+ * Update the sanitized name cache
|
|
|
|
+ * This will add entries if one didn't exit
|
|
|
|
+ * Sanitized names are associated with a {@link ChatChannel} as different chat channels have different chat name settings
|
|
*
|
|
*
|
|
- * @return the {@link TextComponent} version of a players current minecraft nickname
|
|
|
|
|
|
+ * @param chatChannel target chat channel
|
|
|
|
+ * @param useDisplayName whether or not to use this authors display name
|
|
*/
|
|
*/
|
|
- public @NotNull TextComponent getComponentUserName() {
|
|
|
|
- //Not sure if this is expensive but it ensures always up to date names
|
|
|
|
- if(componentUserName != null) {
|
|
|
|
- return componentUserName;
|
|
|
|
|
|
+ private void updateSanitizedNameCache(@NotNull ChatChannel chatChannel, boolean useDisplayName) {
|
|
|
|
+ if(useDisplayName) {
|
|
|
|
+ sanitizedNameCache.put(chatChannel, TextUtils.sanitizeForSerializer(player.getDisplayName()));
|
|
} else {
|
|
} else {
|
|
- //convert to adventure component
|
|
|
|
- componentUserName = TextUtils.ofLegacyTextRaw(player.getName());
|
|
|
|
|
|
+ //No need to sanitize a basic String
|
|
|
|
+ sanitizedNameCache.put(chatChannel, player.getName());
|
|
}
|
|
}
|
|
- return componentUserName;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@Override
|
|
@@ -85,11 +108,13 @@ public abstract class AbstractPlayerAuthor implements Author {
|
|
if (this == o) return true;
|
|
if (this == o) return true;
|
|
if (o == null || getClass() != o.getClass()) return false;
|
|
if (o == null || getClass() != o.getClass()) return false;
|
|
AbstractPlayerAuthor that = (AbstractPlayerAuthor) o;
|
|
AbstractPlayerAuthor that = (AbstractPlayerAuthor) o;
|
|
- return Objects.equal(player, that.player);
|
|
|
|
|
|
+ return Objects.equal(player, that.player) &&
|
|
|
|
+ Objects.equal(lastKnownDisplayName, that.lastKnownDisplayName) &&
|
|
|
|
+ Objects.equal(sanitizedNameCache, that.sanitizedNameCache);
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@Override
|
|
public int hashCode() {
|
|
public int hashCode() {
|
|
- return Objects.hashCode(player);
|
|
|
|
|
|
+ return Objects.hashCode(player, lastKnownDisplayName, sanitizedNameCache);
|
|
}
|
|
}
|
|
}
|
|
}
|