From 4de1d10c76e74caa93a1c41fe7708c76183e0d16 Mon Sep 17 00:00:00 2001 From: Aikar Date: Mon, 15 Jan 2018 21:46:46 -0500 Subject: [PATCH] Basic PlayerProfile API Provides basic elements of a PlayerProfile to be used by future API/events diff --git a/src/main/java/com/destroystokyo/paper/profile/PlayerProfile.java b/src/main/java/com/destroystokyo/paper/profile/PlayerProfile.java new file mode 100644 index 000000000..62f7aa2c8 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/profile/PlayerProfile.java @@ -0,0 +1,151 @@ +package com.destroystokyo.paper.profile; + +import com.mojang.authlib.GameProfile; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Collection; +import java.util.Set; +import java.util.UUID; + +/** + * Represents a players profile for the game, such as UUID, Name, and textures. + */ +public interface PlayerProfile { + + /** + * @return The players name, if set + */ + @Nullable String getName(); + + /** + * Sets this profiles Name + * + * @param name The new Name + * @return The previous Name + */ + String setName(@Nullable String name); + + /** + * @return The players unique identifier, if set + */ + @Nullable UUID getId(); + + /** + * Sets this profiles UUID + * + * @param uuid The new UUID + * @return The previous UUID + */ + UUID setId(@Nullable UUID uuid); + + /** + * @return A Mutable set of this players properties, such as textures. + * Values specified here are subject to implementation details. + */ + @Nonnull Set getProperties(); + + /** + * Check if the Profile has the specified property + * @param property Property name to check + * @return If the property is set + */ + boolean hasProperty(String property); + + /** + * Sets a property. If the property already exists, the previous one will be replaced + * @param property Property to set. + */ + void setProperty(ProfileProperty property); + + /** + * Sets multiple properties. If any of the set properties already exist, it will be replaced + * @param properties The properties to set + */ + void setProperties(Collection properties); + + /** + * Removes a specific property from this profile + * @param property The property to remove + * @return If a property was removed + */ + boolean removeProperty(String property); + + /** + * Removes a specific property from this profile + * @param property The property to remove + * @return If a property was removed + */ + default boolean removeProperty(@Nonnull ProfileProperty property) { + return removeProperty(property.getName()); + } + + /** + * Removes all properties in the collection + * @param properties The properties to remove + * @return If any property was removed + */ + default boolean removeProperties(Collection properties) { + boolean removed = false; + for (ProfileProperty property : properties) { + if (removeProperty(property)) { + removed = true; + } + } + return removed; + } + + /** + * Clears all properties on this profile + */ + void clearProperties(); + + /** + * @return If the profile is now complete (has UUID and Name) + */ + boolean isComplete(); + + /** + * Like {@link #complete(boolean)} but will try only from cache, and not make network calls + * Does not account for textures. + * + * @return If the profile is now complete (has UUID and Name) + */ + boolean completeFromCache(); + + /** + * If this profile is not complete, then make the API call to complete it. + * This is a blocking operation and should be done asynchronously. + * + * This will also complete textures. If you do not want to load textures, use {{@link #complete(boolean)}} + * @return If the profile is now complete (has UUID and Name) (if you get rate limited, this operation may fail) + */ + default boolean complete() { + return complete(true); + } + + /** + * If this profile is not complete, then make the API call to complete it. + * This is a blocking operation and should be done asynchronously. + * + * Optionally will also fill textures. + * @param textures controls if we should fill the profile with texture properties + * @return If the profile is now complete (has UUID and Name) (if you get rate limited, this operation may fail) + */ + boolean complete(boolean textures); + + /** + * Whether or not this Profile has textures associated to it + * @return If has a textures property + */ + default boolean hasTextures() { + return hasProperty("textures"); + } + + /** + * @deprecated Will be removed in 1.13 + * @return the GameProfile for this PlayerProfile + */ + @Deprecated + GameProfile getGameProfile(); +} diff --git a/src/main/java/com/destroystokyo/paper/profile/ProfileProperty.java b/src/main/java/com/destroystokyo/paper/profile/ProfileProperty.java new file mode 100644 index 000000000..d17061e66 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/profile/ProfileProperty.java @@ -0,0 +1,72 @@ +package com.destroystokyo.paper.profile; + +import com.google.common.base.Preconditions; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Objects; + +/** + * Represents a property on a {@link PlayerProfile} + */ +public class ProfileProperty { + private final String name; + private final String value; + private final String signature; + + public ProfileProperty(@Nonnull String name, @Nonnull String value) { + this(name, value, null); + } + + public ProfileProperty(@Nonnull String name, @Nonnull String value, @Nullable String signature) { + this.name = Preconditions.checkNotNull(name, "ProfileProperty name can not be null"); + this.value = Preconditions.checkNotNull(value, "ProfileProperty value can not be null"); + this.signature = signature; + } + + /** + * @return The property name, ie "textures" + */ + @Nonnull + public String getName() { + return name; + } + + /** + * @return The property value, likely to be base64 encoded + */ + @Nonnull + public String getValue() { + return value; + } + + /** + * @return A signature from Mojang for signed properties + */ + @Nullable + public String getSignature() { + return signature; + } + + /** + * @return If this property has a signature or not + */ + public boolean isSigned() { + return this.signature != null; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ProfileProperty that = (ProfileProperty) o; + return Objects.equals(name, that.name) && + Objects.equals(value, that.value) && + Objects.equals(signature, that.signature); + } + + @Override + public int hashCode() { + return Objects.hash(name); + } +} diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java index ed403c333..690d9c071 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java @@ -44,6 +44,9 @@ import org.bukkit.generator.ChunkGenerator; import org.bukkit.inventory.ItemFactory; import org.bukkit.inventory.meta.ItemMeta; +import javax.annotation.Nullable; // Paper +import javax.annotation.Nonnull; // Paper + /** * Represents the Bukkit core, for version and Server singleton handling */ @@ -1216,6 +1219,37 @@ public final class Bukkit { public static boolean suggestPlayerNamesWhenNullTabCompletions() { return server.suggestPlayerNamesWhenNullTabCompletions(); } + + /** + * Creates a PlayerProfile for the specified uuid, with name as null + * @param uuid UUID to create profile for + * @return A PlayerProfile object + */ + public static com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nonnull UUID uuid) { + return server.createProfile(uuid); + } + + /** + * Creates a PlayerProfile for the specified name, with UUID as null + * @param name Name to create profile for + * @return A PlayerProfile object + */ + public static com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nonnull String name) { + return server.createProfile(name); + } + + /** + * Creates a PlayerProfile for the specified name/uuid + * + * Both UUID and Name can not be null at same time. One must be supplied. + * + * @param uuid UUID to create profile for + * @param name Name to create profile for + * @return A PlayerProfile object + */ + public static com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nullable UUID uuid, @Nullable String name) { + return server.createProfile(uuid, name); + } // Paper end public static Server.Spigot spigot() diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java index 87ab9d2b8..f2ee6516e 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java @@ -45,6 +45,9 @@ import org.bukkit.generator.ChunkGenerator; import org.bukkit.inventory.ItemFactory; import org.bukkit.inventory.meta.ItemMeta; +import javax.annotation.Nullable; // Paper +import javax.annotation.Nonnull; // Paper + /** * Represents a server implementation. */ @@ -1041,5 +1044,30 @@ public interface Server extends PluginMessageRecipient { * @return true if player names should be suggested */ boolean suggestPlayerNamesWhenNullTabCompletions(); + + /** + * Creates a PlayerProfile for the specified uuid, with name as null + * @param uuid UUID to create profile for + * @return A PlayerProfile object + */ + com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nonnull UUID uuid); + + /** + * Creates a PlayerProfile for the specified name, with UUID as null + * @param name Name to create profile for + * @return A PlayerProfile object + */ + com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nonnull String name); + + /** + * Creates a PlayerProfile for the specified name/uuid + * + * Both UUID and Name can not be null at same time. One must be supplied. + * + * @param uuid UUID to create profile for + * @param name Name to create profile for + * @return A PlayerProfile object + */ + com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nullable UUID uuid, @Nullable String name); // Paper end } -- 2.18.0