mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-30 16:19:03 +01:00
Basic PlayerProfile API
Provides basic elements of a PlayerProfile to be used by future API/events
This commit is contained in:
parent
95384179d4
commit
ccd4375fa5
5 changed files with 478 additions and 1 deletions
|
@ -0,0 +1,246 @@
|
||||||
|
package com.destroystokyo.paper.profile;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import org.bukkit.profile.PlayerTextures;
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a players profile for the game, such as UUID, Name, and textures.
|
||||||
|
*/
|
||||||
|
@NullMarked
|
||||||
|
public interface PlayerProfile extends org.bukkit.profile.PlayerProfile {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The players name, if set
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
String getName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets this profiles Name
|
||||||
|
*
|
||||||
|
* @param name The new Name
|
||||||
|
* @return The previous Name
|
||||||
|
*/
|
||||||
|
@Deprecated(forRemoval = true, since = "1.18.1")
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
@Deprecated(forRemoval = true, since = "1.18.1")
|
||||||
|
@Nullable
|
||||||
|
UUID setId(@Nullable UUID uuid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the {@link PlayerTextures} of this profile.
|
||||||
|
* This will build a snapshot of the current texture data once
|
||||||
|
* requested inside PlayerTextures.
|
||||||
|
*
|
||||||
|
* @return the textures, not <code>null</code>
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
PlayerTextures getTextures();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies the given textures.
|
||||||
|
*
|
||||||
|
* @param textures the textures to copy, or <code>null</code> to clear the
|
||||||
|
* textures
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
void setTextures(@Nullable PlayerTextures textures);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return A Mutable set of this players properties, such as textures.
|
||||||
|
* Values specified here are subject to implementation details.
|
||||||
|
*/
|
||||||
|
Set<ProfileProperty> getProperties();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the Profile has the specified property
|
||||||
|
*
|
||||||
|
* @param property Property name to check
|
||||||
|
* @return If the property is set
|
||||||
|
*/
|
||||||
|
boolean hasProperty(@Nullable String property);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a property. If the property already exists, the previous one will be replaced
|
||||||
|
*
|
||||||
|
* @param property Property to set.
|
||||||
|
* @throws IllegalArgumentException if setting the property results in more than 16 properties
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
* @throws IllegalArgumentException if the number of properties exceeds 16
|
||||||
|
*/
|
||||||
|
void setProperties(Collection<ProfileProperty> properties);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a specific property from this profile
|
||||||
|
*
|
||||||
|
* @param property The property to remove
|
||||||
|
* @return If a property was removed
|
||||||
|
*/
|
||||||
|
boolean removeProperty(@Nullable String property);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a specific property from this profile
|
||||||
|
*
|
||||||
|
* @param property The property to remove
|
||||||
|
* @return If a property was removed
|
||||||
|
*/
|
||||||
|
default boolean removeProperty(final ProfileProperty property) {
|
||||||
|
return this.removeProperty(property.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes all properties in the collection
|
||||||
|
*
|
||||||
|
* @param properties The properties to remove
|
||||||
|
* @return If any property was removed
|
||||||
|
*/
|
||||||
|
default boolean removeProperties(final Collection<ProfileProperty> properties) {
|
||||||
|
boolean removed = false;
|
||||||
|
for (final ProfileProperty property : properties) {
|
||||||
|
if (this.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)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
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();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Like {@link #complete(boolean)} but will try only from cache, and not make network calls
|
||||||
|
* Does not account for textures.
|
||||||
|
*
|
||||||
|
* @param onlineMode Treat this as online mode or not
|
||||||
|
* @return If the profile is now complete (has UUID and Name)
|
||||||
|
*/
|
||||||
|
boolean completeFromCache(boolean onlineMode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Like {@link #complete(boolean)} but will try only from cache, and not make network calls
|
||||||
|
* Does not account for textures.
|
||||||
|
*
|
||||||
|
* @param lookupUUID If only name is supplied, should we do a UUID lookup
|
||||||
|
* @param onlineMode Treat this as online mode or not
|
||||||
|
* @return If the profile is now complete (has UUID and Name)
|
||||||
|
*/
|
||||||
|
boolean completeFromCache(boolean lookupUUID, boolean onlineMode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If this profile is not complete, then make the API call to complete it.
|
||||||
|
* This is a blocking operation and should be done asynchronously.
|
||||||
|
* <p>
|
||||||
|
* 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 this.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.
|
||||||
|
* <p>
|
||||||
|
* Optionally will also fill textures.
|
||||||
|
* <p>
|
||||||
|
* Online mode will be automatically determined
|
||||||
|
*
|
||||||
|
* @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);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If this profile is not complete, then make the API call to complete it.
|
||||||
|
* This is a blocking operation and should be done asynchronously.
|
||||||
|
* <p>
|
||||||
|
* Optionally will also fill textures.
|
||||||
|
*
|
||||||
|
* @param textures controls if we should fill the profile with texture properties
|
||||||
|
* @param onlineMode Treat this server as online mode or not
|
||||||
|
* @return If the profile is now complete (has UUID and Name) (if you get rate limited, this operation may fail)
|
||||||
|
*/
|
||||||
|
boolean complete(boolean textures, boolean onlineMode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Produces an updated player profile based on this profile.
|
||||||
|
* <p>
|
||||||
|
* This tries to produce a completed profile by filling in missing
|
||||||
|
* properties (name, unique id, textures, etc.), and updates existing
|
||||||
|
* properties (e.g. name, textures, etc.) to their official and up-to-date
|
||||||
|
* values. This operation does not alter the current profile, but produces a
|
||||||
|
* new updated {@link PlayerProfile}.
|
||||||
|
* <p>
|
||||||
|
* If no player exists for the unique id or name of this profile, this
|
||||||
|
* operation yields a profile that is equal to the current profile, which
|
||||||
|
* might not be complete.
|
||||||
|
* <p>
|
||||||
|
* This is an asynchronous operation: Updating the profile can result in an
|
||||||
|
* outgoing connection in another thread in order to fetch the latest
|
||||||
|
* profile properties. The returned {@link CompletableFuture} will be
|
||||||
|
* completed once the updated profile is available. In order to not block
|
||||||
|
* the server's main thread, you should not wait for the result of the
|
||||||
|
* returned CompletableFuture on the server's main thread. Instead, if you
|
||||||
|
* want to do something with the updated player profile on the server's main
|
||||||
|
* thread once it is available, you could do something like this:
|
||||||
|
* <pre>
|
||||||
|
* profile.update().thenAcceptAsync(updatedProfile -> {
|
||||||
|
* // Do something with the updated profile:
|
||||||
|
* // ...
|
||||||
|
* }, runnable -> Bukkit.getScheduler().runTask(plugin, runnable));
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
CompletableFuture<PlayerProfile> update();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether this Profile has textures associated to it
|
||||||
|
*
|
||||||
|
* @return If it has a textures property
|
||||||
|
*/
|
||||||
|
default boolean hasTextures() {
|
||||||
|
return this.hasProperty("textures");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
package com.destroystokyo.paper.profile;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
import java.util.Objects;
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a property on a {@link PlayerProfile}
|
||||||
|
*/
|
||||||
|
@NullMarked
|
||||||
|
public final class ProfileProperty {
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
private final String value;
|
||||||
|
private final @Nullable String signature;
|
||||||
|
|
||||||
|
public ProfileProperty(final String name, final String value) {
|
||||||
|
this(name, value, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProfileProperty(final String name, final String value, final @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;
|
||||||
|
Preconditions.checkArgument(name.length() <= 64, "ProfileProperty name can not be longer than 64 characters");
|
||||||
|
Preconditions.checkArgument(value.length() <= Short.MAX_VALUE, "ProfileProperty value can not be longer than 32767 characters");
|
||||||
|
Preconditions.checkArgument(signature == null || signature.length() <= 1024, "ProfileProperty signature can not be longer than 1024 characters");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The property name, ie "textures"
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The property value, likely to be base64 encoded
|
||||||
|
*/
|
||||||
|
public String getValue() {
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return A signature from Mojang for signed properties
|
||||||
|
*/
|
||||||
|
public @Nullable String getSignature() {
|
||||||
|
return this.signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return If this property has a signature or not
|
||||||
|
*/
|
||||||
|
public boolean isSigned() {
|
||||||
|
return this.signature != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final @Nullable Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || this.getClass() != o.getClass()) return false;
|
||||||
|
final ProfileProperty that = (ProfileProperty) o;
|
||||||
|
return Objects.equals(this.name, that.name) &&
|
||||||
|
Objects.equals(this.value, that.value) &&
|
||||||
|
Objects.equals(this.signature, that.signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(this.name);
|
||||||
|
}
|
||||||
|
}
|
|
@ -2424,6 +2424,89 @@ public final class Bukkit {
|
||||||
public static boolean suggestPlayerNamesWhenNullTabCompletions() {
|
public static boolean suggestPlayerNamesWhenNullTabCompletions() {
|
||||||
return server.suggestPlayerNamesWhenNullTabCompletions();
|
return server.suggestPlayerNamesWhenNullTabCompletions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a PlayerProfile for the specified uuid, with name as null.
|
||||||
|
*
|
||||||
|
* If a player with the passed uuid exists on the server at the time of creation, the returned player profile will
|
||||||
|
* be populated with the properties of said player (including their uuid and name).
|
||||||
|
*
|
||||||
|
* @param uuid UUID to create profile for
|
||||||
|
* @return A PlayerProfile object
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public static com.destroystokyo.paper.profile.PlayerProfile createProfile(@NotNull UUID uuid) {
|
||||||
|
return server.createProfile(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a PlayerProfile for the specified name, with UUID as null.
|
||||||
|
*
|
||||||
|
* If a player with the passed name exists on the server at the time of creation, the returned player profile will
|
||||||
|
* be populated with the properties of said player (including their uuid and name).
|
||||||
|
* <p>
|
||||||
|
* E.g. if the player 'jeb_' is currently playing on the server, calling {@code createProfile("JEB_")} will
|
||||||
|
* yield a profile with the name 'jeb_', their uuid and their textures.
|
||||||
|
* To bypass this pre-population on a case-insensitive name match, see {@link #createProfileExact(UUID, String)}.
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* @param name Name to create profile for
|
||||||
|
* @return A PlayerProfile object
|
||||||
|
* @throws IllegalArgumentException if the name is longer than 16 characters
|
||||||
|
* @throws IllegalArgumentException if the name contains invalid characters
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public static com.destroystokyo.paper.profile.PlayerProfile createProfile(@NotNull 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.
|
||||||
|
* If a player with the passed uuid or name exists on the server at the time of creation, the returned player
|
||||||
|
* profile will be populated with the properties of said player (including their uuid and name).
|
||||||
|
* <p>
|
||||||
|
* E.g. if the player 'jeb_' is currently playing on the server, calling {@code createProfile(null, "JEB_")} will
|
||||||
|
* yield a profile with the name 'jeb_', their uuid and their textures.
|
||||||
|
* To bypass this pre-population on an case-insensitive name match, see {@link #createProfileExact(UUID, String)}.
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* The name comparison will compare the {@link String#toLowerCase()} version of both the passed name parameter and
|
||||||
|
* a players name to honour the case-insensitive nature of a mojang profile lookup.
|
||||||
|
*
|
||||||
|
* @param uuid UUID to create profile for
|
||||||
|
* @param name Name to create profile for
|
||||||
|
* @return A PlayerProfile object
|
||||||
|
* @throws IllegalArgumentException if the name is longer than 16 characters
|
||||||
|
* @throws IllegalArgumentException if the name contains invalid characters
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public static com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nullable UUID uuid, @Nullable String name) {
|
||||||
|
return server.createProfile(uuid, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an exact PlayerProfile for the specified name/uuid
|
||||||
|
*
|
||||||
|
* Both UUID and Name can not be null at same time. One must be supplied.
|
||||||
|
* If a player with the passed uuid or name exists on the server at the time of creation, the returned player
|
||||||
|
* profile will be populated with the properties of said player.
|
||||||
|
* <p>
|
||||||
|
* Compared to {@link #createProfile(UUID, String)}, this method will never mutate the passed uuid or name.
|
||||||
|
* If a player with either the same uuid or a matching name (case-insensitive) is found on the server, their
|
||||||
|
* properties, such as textures, will be pre-populated in the profile, however the passed uuid and name stay intact.
|
||||||
|
*
|
||||||
|
* @param uuid UUID to create profile for
|
||||||
|
* @param name Name to create profile for
|
||||||
|
* @return A PlayerProfile object
|
||||||
|
* @throws IllegalArgumentException if the name is longer than 16 characters
|
||||||
|
* @throws IllegalArgumentException if the name contains invalid characters
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public static com.destroystokyo.paper.profile.PlayerProfile createProfileExact(@Nullable UUID uuid, @Nullable String name) {
|
||||||
|
return server.createProfileExact(uuid, name);
|
||||||
|
}
|
||||||
// Paper end
|
// Paper end
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|
|
@ -2108,5 +2108,80 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
|
||||||
* @return true if player names should be suggested
|
* @return true if player names should be suggested
|
||||||
*/
|
*/
|
||||||
boolean suggestPlayerNamesWhenNullTabCompletions();
|
boolean suggestPlayerNamesWhenNullTabCompletions();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a PlayerProfile for the specified uuid, with name as null.
|
||||||
|
*
|
||||||
|
* If a player with the passed uuid exists on the server at the time of creation, the returned player profile will
|
||||||
|
* be populated with the properties of said player (including their uuid and name).
|
||||||
|
*
|
||||||
|
* @param uuid UUID to create profile for
|
||||||
|
* @return A PlayerProfile object
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
com.destroystokyo.paper.profile.PlayerProfile createProfile(@NotNull UUID uuid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a PlayerProfile for the specified name, with UUID as null.
|
||||||
|
*
|
||||||
|
* If a player with the passed name exists on the server at the time of creation, the returned player profile will
|
||||||
|
* be populated with the properties of said player (including their uuid and name).
|
||||||
|
* <p>
|
||||||
|
* E.g. if the player 'jeb_' is currently playing on the server, calling {@code createProfile("JEB_")} will
|
||||||
|
* yield a profile with the name 'jeb_', their uuid and their textures.
|
||||||
|
* To bypass this pre-population on a case-insensitive name match, see {@link #createProfileExact(UUID, String)}.
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* @param name Name to create profile for
|
||||||
|
* @return A PlayerProfile object
|
||||||
|
* @throws IllegalArgumentException if the name is longer than 16 characters
|
||||||
|
* @throws IllegalArgumentException if the name contains invalid characters
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
com.destroystokyo.paper.profile.PlayerProfile createProfile(@NotNull 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.
|
||||||
|
* If a player with the passed uuid or name exists on the server at the time of creation, the returned player
|
||||||
|
* profile will be populated with the properties of said player (including their uuid and name).
|
||||||
|
* <p>
|
||||||
|
* E.g. if the player 'jeb_' is currently playing on the server, calling {@code createProfile(null, "JEB_")} will
|
||||||
|
* yield a profile with the name 'jeb_', their uuid and their textures.
|
||||||
|
* To bypass this pre-population on an case-insensitive name match, see {@link #createProfileExact(UUID, String)}.
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* The name comparison will compare the {@link String#toLowerCase()} version of both the passed name parameter and
|
||||||
|
* a players name to honour the case-insensitive nature of a mojang profile lookup.
|
||||||
|
*
|
||||||
|
* @param uuid UUID to create profile for
|
||||||
|
* @param name Name to create profile for
|
||||||
|
* @return A PlayerProfile object
|
||||||
|
* @throws IllegalArgumentException if the name is longer than 16 characters
|
||||||
|
* @throws IllegalArgumentException if the name contains invalid characters
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nullable UUID uuid, @Nullable String name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an exact PlayerProfile for the specified name/uuid
|
||||||
|
*
|
||||||
|
* Both UUID and Name can not be null at same time. One must be supplied.
|
||||||
|
* If a player with the passed uuid or name exists on the server at the time of creation, the returned player
|
||||||
|
* profile will be populated with the properties of said player.
|
||||||
|
* <p>
|
||||||
|
* Compared to {@link #createProfile(UUID, String)}, this method will never mutate the passed uuid or name.
|
||||||
|
* If a player with either the same uuid or a matching name (case-insensitive) is found on the server, their
|
||||||
|
* properties, such as textures, will be pre-populated in the profile, however the passed uuid and name stay intact.
|
||||||
|
*
|
||||||
|
* @param uuid UUID to create profile for
|
||||||
|
* @param name Name to create profile for
|
||||||
|
* @return A PlayerProfile object
|
||||||
|
* @throws IllegalArgumentException if the name is longer than 16 characters
|
||||||
|
* @throws IllegalArgumentException if the name contains invalid characters
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
com.destroystokyo.paper.profile.PlayerProfile createProfileExact(@Nullable UUID uuid, @Nullable String name);
|
||||||
// Paper end
|
// Paper end
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,7 +93,7 @@ public interface PlayerProfile extends Cloneable, ConfigurationSerializable {
|
||||||
* PlayerProfile once it is available
|
* PlayerProfile once it is available
|
||||||
*/
|
*/
|
||||||
@NotNull
|
@NotNull
|
||||||
CompletableFuture<PlayerProfile> update();
|
CompletableFuture<? extends PlayerProfile> update(); // Paper
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
PlayerProfile clone();
|
PlayerProfile clone();
|
||||||
|
|
Loading…
Reference in a new issue