feat: Implement SkinSource for Player and GameProfile (#1721)

This commit is contained in:
Emil
2026-01-30 19:09:27 +01:00
committed by GitHub
parent 9bfe19f795
commit 14160e1988
2 changed files with 34 additions and 2 deletions

View File

@@ -39,6 +39,7 @@ import net.kyori.adventure.sound.SoundStop;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.HoverEvent; import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.event.HoverEventSource; import net.kyori.adventure.text.event.HoverEventSource;
import net.kyori.adventure.text.object.PlayerHeadObjectContents;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -49,7 +50,8 @@ public interface Player extends
/* Fundamental Velocity interfaces */ /* Fundamental Velocity interfaces */
CommandSource, InboundConnection, ChannelMessageSource, ChannelMessageSink, CommandSource, InboundConnection, ChannelMessageSource, ChannelMessageSink,
/* Adventure-specific interfaces */ /* Adventure-specific interfaces */
Identified, HoverEventSource<HoverEvent.ShowEntity>, Keyed, KeyIdentifiable, Sound.Emitter { Identified, HoverEventSource<HoverEvent.ShowEntity>, Keyed, KeyIdentifiable, Sound.Emitter,
PlayerHeadObjectContents.SkinSource {
/** /**
* Returns the player's current username. * Returns the player's current username.
@@ -339,6 +341,16 @@ public interface Player extends
Component.text(getUsername())))); Component.text(getUsername()))));
} }
@SuppressWarnings("UnstableApiUsage") // permitted implementation
@Override
default void applySkinToPlayerHeadContents(
final PlayerHeadObjectContents.@NotNull Builder builder) {
builder.skin(this.getGameProfile());
if (this.hasSentPlayerSettings()) {
builder.hat(this.getPlayerSettings().getSkinParts().hasHat());
}
}
/** /**
* Gets the player's client brand. * Gets the player's client brand.
* *

View File

@@ -11,11 +11,14 @@ import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors;
import net.kyori.adventure.text.object.PlayerHeadObjectContents;
import org.jetbrains.annotations.NotNull;
/** /**
* Represents a Mojang game profile. This class is immutable. * Represents a Mojang game profile. This class is immutable.
*/ */
public final class GameProfile { public final class GameProfile implements PlayerHeadObjectContents.SkinSource {
private final UUID id; private final UUID id;
private final String undashedId; private final String undashedId;
@@ -169,6 +172,23 @@ public final class GameProfile {
ImmutableList.of()); ImmutableList.of());
} }
@SuppressWarnings("UnstableApiUsage") // permitted implementation
@Override
public void applySkinToPlayerHeadContents(
final PlayerHeadObjectContents.@NotNull Builder builder) {
if (this.properties.isEmpty()) {
builder.id(this.id);
return;
}
builder.id(this.id)
.name(this.name)
.profileProperties(this.properties.stream()
.map(property -> PlayerHeadObjectContents.property(property.getName(),
property.getValue(), property.getSignature()))
.collect(Collectors.toList()));
}
@Override @Override
public String toString() { public String toString() {
return "GameProfile{" return "GameProfile{"