@@ -521,11 +534,38 @@ public final class Bukkit { * Minecraft default: 1. * * @return the default ticks per water underground creature spawn value + * @deprecated Deprecated in favor of {@link #getTicksPerSpawns(SpawnCategory)} */ + @Deprecated public static int getTicksPerWaterUndergroundCreatureSpawns() { return server.getTicksPerWaterUndergroundCreatureSpawns(); } + /** + * Gets the default ticks per {@link SpawnCategory} spawns value. + *
+ * Example Usage: + *
+ * Note: If set to 0, {@link SpawnCategory} mobs spawning will be disabled. + *
+ * Minecraft default: 1.
+ *
+ * Note: the {@link SpawnCategory#MISC} are not consider.
+ *
+ * @param spawnCategory the category of spawn
+ * @return the default ticks per {@link SpawnCategory} mobs spawn value
+ */
+ public static int getTicksPerSpawns(@NotNull SpawnCategory spawnCategory) {
+ return server.getTicksPerSpawns(spawnCategory);
+ }
+
/**
* Gets a player object by the given username.
*
@@ -1048,6 +1088,45 @@ public final class Bukkit {
return server.getOfflinePlayer(id);
}
+ /**
+ * Creates a new {@link PlayerProfile}.
+ *
+ * @param uniqueId the unique id
+ * @param name the name
+ * @return the new PlayerProfile
+ * @throws IllegalArgumentException if both the unique id is
+ * null
and the name is null
or blank
+ */
+ @NotNull
+ public static PlayerProfile createPlayerProfile(@Nullable UUID uniqueId, @Nullable String name) {
+ return server.createPlayerProfile(uniqueId, name);
+ }
+
+ /**
+ * Creates a new {@link PlayerProfile}.
+ *
+ * @param uniqueId the unique id
+ * @return the new PlayerProfile
+ * @throws IllegalArgumentException if the unique id is null
+ */
+ @NotNull
+ public static PlayerProfile createPlayerProfile(@NotNull UUID uniqueId) {
+ return server.createPlayerProfile(uniqueId);
+ }
+
+ /**
+ * Creates a new {@link PlayerProfile}.
+ *
+ * @param name the name
+ * @return the new PlayerProfile
+ * @throws IllegalArgumentException if the name is null
or
+ * blank
+ */
+ @NotNull
+ public static PlayerProfile createPlayerProfile(@NotNull String name) {
+ return server.createPlayerProfile(name);
+ }
+
/**
* Gets a set containing all current IPs that are banned.
*
@@ -1282,7 +1361,9 @@ public final class Bukkit {
* chunk.
*
* @return the monster spawn limit
+ * @deprecated Deprecated in favor of {@link #getSpawnLimit(SpawnCategory)}
*/
+ @Deprecated
public static int getMonsterSpawnLimit() {
return server.getMonsterSpawnLimit();
}
@@ -1292,7 +1373,9 @@ public final class Bukkit {
* chunk.
*
* @return the animal spawn limit
+ * @deprecated Deprecated in favor of {@link #getSpawnLimit(SpawnCategory)}
*/
+ @Deprecated
public static int getAnimalSpawnLimit() {
return server.getAnimalSpawnLimit();
}
@@ -1302,7 +1385,9 @@ public final class Bukkit {
* a chunk.
*
* @return the water animal spawn limit
+ * @deprecated Deprecated in favor of {@link #getSpawnLimit(SpawnCategory)}
*/
+ @Deprecated
public static int getWaterAnimalSpawnLimit() {
return server.getWaterAnimalSpawnLimit();
}
@@ -1312,7 +1397,9 @@ public final class Bukkit {
* in a chunk.
*
* @return the water ambient spawn limit
+ * @deprecated Deprecated in favor of {@link #getSpawnLimit(SpawnCategory)}
*/
+ @Deprecated
public static int getWaterAmbientSpawnLimit() {
return server.getAmbientSpawnLimit();
}
@@ -1320,8 +1407,11 @@ public final class Bukkit {
/**
* Get user-specified limit for number of water creature underground that can spawn
* in a chunk.
+ *
* @return the water underground creature limit
+ * @deprecated Deprecated in favor of {@link #getSpawnLimit(SpawnCategory)}
*/
+ @Deprecated
public static int getWaterUndergroundCreatureSpawnLimit() {
return server.getWaterUndergroundCreatureSpawnLimit();
}
@@ -1331,11 +1421,26 @@ public final class Bukkit {
* a chunk.
*
* @return the ambient spawn limit
+ * @deprecated Deprecated in favor of {@link #getSpawnLimit(SpawnCategory)}
*/
+ @Deprecated
public static int getAmbientSpawnLimit() {
return server.getAmbientSpawnLimit();
}
+ /**
+ * Gets user-specified limit for number of {@link SpawnCategory} mobs that can spawn in
+ * a chunk.
+ *
+ * Note: the {@link SpawnCategory#MISC} are not consider.
+ *
+ * @param spawnCategory the category spawn
+ * @return the {@link SpawnCategory} spawn limit
+ */
+ public static int getSpawnLimit(@NotNull SpawnCategory spawnCategory) {
+ return server.getSpawnLimit(spawnCategory);
+ }
+
/**
* Checks the current thread against the expected primary thread for the
* server.
diff --git a/src/main/java/org/bukkit/OfflinePlayer.java b/src/main/java/org/bukkit/OfflinePlayer.java
index 58313929..76e511e7 100644
--- a/src/main/java/org/bukkit/OfflinePlayer.java
+++ b/src/main/java/org/bukkit/OfflinePlayer.java
@@ -6,6 +6,7 @@ import org.bukkit.entity.AnimalTamer;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.permissions.ServerOperator;
+import org.bukkit.profile.PlayerProfile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -39,6 +40,18 @@ public interface OfflinePlayer extends ServerOperator, AnimalTamer, Configuratio
@NotNull
public UUID getUniqueId();
+ /**
+ * Gets a copy of the player's profile.
+ *
+ * If the player is online, the returned profile will be complete.
+ * Otherwise, only the unique id is guaranteed to be present. You can use
+ * {@link PlayerProfile#update()} to complete the returned profile.
+ *
+ * @return the player's profile
+ */
+ @NotNull
+ PlayerProfile getPlayerProfile();
+
/**
* Checks if this player is banned or not
*
diff --git a/src/main/java/org/bukkit/Particle.java b/src/main/java/org/bukkit/Particle.java
index dc514246..8d048a8f 100644
--- a/src/main/java/org/bukkit/Particle.java
+++ b/src/main/java/org/bukkit/Particle.java
@@ -36,13 +36,25 @@ public enum Particle {
FLAME,
LAVA,
CLOUD,
+ /**
+ * Uses {@link Particle.DustOptions} as DataType
+ */
REDSTONE(DustOptions.class),
SNOWBALL,
SNOW_SHOVEL,
SLIME,
HEART,
+ /**
+ * Uses {@link ItemStack} as DataType
+ */
ITEM_CRACK(ItemStack.class),
+ /**
+ * Uses {@link BlockData} as DataType
+ */
BLOCK_CRACK(BlockData.class),
+ /**
+ * Uses {@link BlockData} as DataType
+ */
BLOCK_DUST(BlockData.class),
WATER_DROP,
MOB_APPEARANCE,
@@ -50,6 +62,9 @@ public enum Particle {
END_ROD,
DAMAGE_INDICATOR,
SWEEP_ATTACK,
+ /**
+ * Uses {@link BlockData} as DataType
+ */
FALLING_DUST(BlockData.class),
TOTEM,
SPIT,
@@ -81,7 +96,13 @@ public enum Particle {
LANDING_OBSIDIAN_TEAR,
REVERSE_PORTAL,
WHITE_ASH,
+ /**
+ * Uses {@link DustTransition} as DataType
+ */
DUST_COLOR_TRANSITION(DustTransition.class),
+ /**
+ * Uses {@link Vibration} as DataType
+ */
VIBRATION(Vibration.class),
FALLING_SPORE_BLOSSOM,
SPORE_BLOSSOM_AIR,
@@ -97,10 +118,22 @@ public enum Particle {
WAX_OFF,
ELECTRIC_SPARK,
SCRAPE,
+ /**
+ * Uses {@link BlockData} as DataType
+ */
BLOCK_MARKER(BlockData.class),
// ----- Legacy Separator -----
+ /**
+ * Uses {@link MaterialData} as DataType
+ */
LEGACY_BLOCK_CRACK(MaterialData.class),
+ /**
+ * Uses {@link MaterialData} as DataType
+ */
LEGACY_BLOCK_DUST(MaterialData.class),
+ /**
+ * Uses {@link MaterialData} as DataType
+ */
LEGACY_FALLING_DUST(MaterialData.class);
private final Class> dataType;
diff --git a/src/main/java/org/bukkit/RegionAccessor.java b/src/main/java/org/bukkit/RegionAccessor.java
index e285d544..a89fff5c 100644
--- a/src/main/java/org/bukkit/RegionAccessor.java
+++ b/src/main/java/org/bukkit/RegionAccessor.java
@@ -3,6 +3,7 @@ package org.bukkit;
import java.util.Collection;
import java.util.List;
import java.util.Random;
+import java.util.function.Predicate;
import org.bukkit.block.Biome;
import org.bukkit.block.BlockState;
import org.bukkit.block.data.BlockData;
@@ -183,6 +184,26 @@ public interface RegionAccessor {
*/
boolean generateTree(@NotNull Location location, @NotNull Random random, @NotNull TreeType type, @Nullable Consumer
+ * The provided predicate gets called for every block which gets changed
+ * as a result of the tree generation. When the predicate gets called no
+ * modifications to the world are done yet. Which means, that calling
+ * {@link #getBlockState(Location)} in the predicate will return the state
+ * of the block before the generation.
+ *
+ * If the predicate returns {@code true} the block gets set in the world.
+ * If it returns {@code false} the block won't get set in the world.
+ *
+ * @param location Location to spawn the tree
+ * @param random Random to use to generated the tree
+ * @param type Type of the tree to create
+ * @param statePredicate The predicate which should get used to test if a block should be set or not.
+ * @return true if the tree was created successfully, otherwise false
+ */
+ boolean generateTree(@NotNull Location location, @NotNull Random random, @NotNull TreeType type, @Nullable Predicate
+ * Example Usage:
+ *
+ * Note: If set to 0, {@link SpawnCategory} mobs spawning will be disabled.
+ *
+ * Minecraft default: 1.
+ *
@@ -880,6 +917,39 @@ public interface Server extends PluginMessageRecipient {
@NotNull
public OfflinePlayer getOfflinePlayer(@NotNull UUID id);
+ /**
+ * Creates a new {@link PlayerProfile}.
+ *
+ * @param uniqueId the unique id
+ * @param name the name
+ * @return the new PlayerProfile
+ * @throws IllegalArgumentException if both the unique id is
+ *
* Minecraft default: 1.
*
- * @return The world's ticks per ambient mob spawns value
+ * @return the default ticks per ambient mobs spawn value
+ * @deprecated Deprecated in favor of {@link #getTicksPerSpawns(SpawnCategory)}
*/
+ @Deprecated
public long getTicksPerAmbientSpawns();
/**
@@ -1896,15 +1920,70 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
*
* @param ticksPerAmbientSpawns the ticks per ambient mob spawns value you
* want to set the world to
+ * @deprecated Deprecated in favor of {@link #setTicksPerSpawns(SpawnCategory, int)}
*/
+ @Deprecated
public void setTicksPerAmbientSpawns(int ticksPerAmbientSpawns);
+ /**
+ * Gets the world's ticks per {@link SpawnCategory} mob spawns value
+ *
+ * This value determines how many ticks there are between attempts to
+ * spawn {@link SpawnCategory} mobs.
+ *
+ * Example Usage:
+ *
+ * Note:
+ * If set to 0, {@link SpawnCategory} mobs spawning will be disabled for this world.
+ *
+ * Minecraft default: 1.
+ *
+ * @param spawnCategory the category spawn
+ * @return The world's ticks per {@link SpawnCategory} mob spawns value
+ */
+ public long getTicksPerSpawns(@NotNull SpawnCategory spawnCategory);
+
+ /**
+ * Sets the world's ticks per {@link SpawnCategory} mob spawns value
+ *
+ * This value determines how many ticks there are between attempts to
+ * spawn {@link SpawnCategory} mobs.
+ *
+ * Example Usage:
+ *
+ * Note:
+ * If set to 0, {@link SpawnCategory} mobs spawning will be disabled for this world.
+ *
+ * Minecraft default: 1.
+ *
+ * @param spawnCategory the category spawn
+ * @param ticksPerCategorySpawn the ticks per {@link SpawnCategory} mob spawns value you
+ * want to set the world to
+ */
+ public void setTicksPerSpawns(@NotNull SpawnCategory spawnCategory, int ticksPerCategorySpawn);
+
/**
* Gets limit for number of monsters that can spawn in a chunk in this
* world
*
* @return The monster spawn limit
+ * @deprecated Deprecated in favor of {@link #getSpawnLimit(SpawnCategory)}
*/
+ @Deprecated
int getMonsterSpawnLimit();
/**
@@ -1915,7 +1994,9 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
* server-wide spawn limit instead.
*
* @param limit the new mob limit
+ * @deprecated Deprecated in favor of {@link #setSpawnLimit(SpawnCategory, int)}
*/
+ @Deprecated
void setMonsterSpawnLimit(int limit);
/**
@@ -1923,7 +2004,9 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
* world
*
* @return The animal spawn limit
+ * @deprecated Deprecated in favor of {@link #getSpawnLimit(SpawnCategory)}
*/
+ @Deprecated
int getAnimalSpawnLimit();
/**
@@ -1934,7 +2017,9 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
* server-wide spawn limit instead.
*
* @param limit the new mob limit
+ * @deprecated Deprecated in favor of {@link #getSpawnLimit(SpawnCategory)}
*/
+ @Deprecated
void setAnimalSpawnLimit(int limit);
/**
@@ -1942,7 +2027,9 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
* this world
*
* @return The water animal spawn limit
+ * @deprecated Deprecated in favor of {@link #getSpawnLimit(SpawnCategory)}
*/
+ @Deprecated
int getWaterAnimalSpawnLimit();
/**
@@ -1953,7 +2040,9 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
* server-wide spawn limit instead.
*
* @param limit the new mob limit
+ * @deprecated Deprecated in favor of {@link #setSpawnLimit(SpawnCategory, int)}
*/
+ @Deprecated
void setWaterAnimalSpawnLimit(int limit);
/**
@@ -1961,7 +2050,9 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
* this world
*
* @return The water underground creature spawn limit
+ * @deprecated Deprecated in favor of {@link #getSpawnLimit(SpawnCategory)}
*/
+ @Deprecated
int getWaterUndergroundCreatureSpawnLimit();
/**
@@ -1972,7 +2063,9 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
* server-wide spawn limit instead.
*
* @param limit the new mob limit
+ * @deprecated Deprecated in favor of {@link #setSpawnLimit(SpawnCategory, int)}
*/
+ @Deprecated
void setWaterUndergroundCreatureSpawnLimit(int limit);
/**
@@ -1980,7 +2073,9 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
* in a chunk.
*
* @return the water ambient spawn limit
+ * @deprecated Deprecated in favor of {@link #getSpawnLimit(SpawnCategory)}
*/
+ @Deprecated
int getWaterAmbientSpawnLimit();
/**
@@ -1991,7 +2086,9 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
* server-wide spawn limit instead.
*
* @param limit the new mob limit
+ * @deprecated Deprecated in favor of {@link #setSpawnLimit(SpawnCategory, int)}
*/
+ @Deprecated
void setWaterAmbientSpawnLimit(int limit);
/**
@@ -1999,7 +2096,9 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
* this world
*
* @return The ambient spawn limit
+ * @deprecated Deprecated in favor of {@link #getSpawnLimit(SpawnCategory)}
*/
+ @Deprecated
int getAmbientSpawnLimit();
/**
@@ -2010,11 +2109,34 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
* server-wide spawn limit instead.
*
* @param limit the new mob limit
+ * @deprecated Deprecated in favor of {@link #setSpawnLimit(SpawnCategory, int)}
*/
+ @Deprecated
void setAmbientSpawnLimit(int limit);
/**
- * Play a Sound at the provided Location in the World
+ * Gets the limit for number of {@link SpawnCategory} entities that can spawn in a chunk in
+ * this world
+ *
+ * @param spawnCategory the entity category
+ * @return The ambient spawn limit
+ */
+ int getSpawnLimit(@NotNull SpawnCategory spawnCategory);
+
+ /**
+ * Sets the limit for number of {@link SpawnCategory} entities that can spawn in a chunk in
+ * this world
+ *
+ * Note: If set to a negative number the world will use the
+ * server-wide spawn limit instead.
+ *
+ * @param spawnCategory the entity category
+ * @param limit the new mob limit
+ */
+ void setSpawnLimit(@NotNull SpawnCategory spawnCategory, int limit);
+
+ /**
+ * Play a Sound at the provided Location in the World.
*
* This function will fail silently if Location or Sound are null.
*
@@ -2067,6 +2189,31 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
*/
void playSound(@NotNull Location location, @NotNull String sound, @NotNull SoundCategory category, float volume, float pitch);
+ /**
+ * Play a Sound at the location of the provided entity in the World.
+ *
+ * This function will fail silently if Entity or Sound are null.
+ *
+ * @param entity The entity to play the sound
+ * @param sound The sound to play
+ * @param volume The volume of the sound
+ * @param pitch The pitch of the sound
+ */
+ void playSound(@NotNull Entity entity, @NotNull Sound sound, float volume, float pitch);
+
+ /**
+ * Play a Sound at the location of the provided entity in the World.
+ *
+ * This function will fail silently if Entity or Sound are null.
+ *
+ * @param entity The entity to play the sound
+ * @param sound The sound to play
+ * @param category the category of the sound
+ * @param volume The volume of the sound
+ * @param pitch The pitch of the sound
+ */
+ void playSound(@NotNull Entity entity, @NotNull Sound sound, @NotNull SoundCategory category, float volume, float pitch);
+
/**
* Get an array containing the names of all the {@link GameRule}s.
*
diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java
index ce1e1e6c..b4094e04 100644
--- a/src/main/java/org/bukkit/block/Block.java
+++ b/src/main/java/org/bukkit/block/Block.java
@@ -448,11 +448,11 @@ public interface Block extends Metadatable {
* into account tools, potion effects, whether or not the player is in
* water, enchantments, etc.
*
- * The returned value is the amount of progress made in breaking the block.
- * When the total breaking progress reaches {@code 1.0f}, the block is
- * broken. Note that the break speed can change in the course of breaking a
- * block, e.g. if a potion effect is applied or expires, or the player
- * jumps/enters water.
+ * The returned value is the amount of progress made in breaking the block
+ * each tick. When the total breaking progress reaches {@code 1.0f}, the
+ * block is broken. Note that the break speed can change in the course of
+ * breaking a block, e.g. if a potion effect is applied or expires, or the
+ * player jumps/enters water.
*
* @param player player breaking the block
* @return the speed at which the player breaks this block
diff --git a/src/main/java/org/bukkit/block/Furnace.java b/src/main/java/org/bukkit/block/Furnace.java
index c5a8c96f..ac3b24c5 100644
--- a/src/main/java/org/bukkit/block/Furnace.java
+++ b/src/main/java/org/bukkit/block/Furnace.java
@@ -1,5 +1,7 @@
package org.bukkit.block;
+import java.util.Map;
+import org.bukkit.inventory.CookingRecipe;
import org.bukkit.inventory.FurnaceInventory;
import org.jetbrains.annotations.NotNull;
@@ -61,6 +63,17 @@ public interface Furnace extends Container {
*/
public void setCookTimeTotal(int cookTimeTotal);
+ /**
+ * Get the recipes used in this furnace.
+ *
+ * Note: These recipes used are reset when the result item is
+ * manually taken from the furnace.
+ *
+ * @return An immutable map with the recipes used and the times used
+ */
+ @NotNull
+ public Map
+ * The profile must contain both a unique id and a skin texture. If either
+ * of these is missing, the profile must contain a name by which the server
+ * will then attempt to look up the unique id and skin texture.
+ *
+ * @param profile the profile of the owning player
+ * @throws IllegalArgumentException if the profile does not contain the
+ * necessary information
+ */
+ void setOwnerProfile(@Nullable PlayerProfile profile);
+
/**
* Gets the rotation of the skull in the world (or facing direction if this
* is a wall mounted skull).
diff --git a/src/main/java/org/bukkit/command/TabCompleter.java b/src/main/java/org/bukkit/command/TabCompleter.java
index e9cf71f5..ed6f6525 100644
--- a/src/main/java/org/bukkit/command/TabCompleter.java
+++ b/src/main/java/org/bukkit/command/TabCompleter.java
@@ -16,12 +16,12 @@ public interface TabCompleter {
* command inside of a command block, this will be the player, not
* the command block.
* @param command Command which was executed
- * @param alias The alias used
+ * @param label Alias of the command which was used
* @param args The arguments passed to the command, including final
- * partial argument to be completed and command label
+ * partial argument to be completed
* @return A List of possible completions for the final argument, or null
* to default to the command executor
*/
@Nullable
- public List
+ * This function will fail silently if Entity or Sound are null.
+ *
+ * @param entity The entity to play the sound
+ * @param sound The sound to play
+ * @param volume The volume of the sound
+ * @param pitch The pitch of the sound
+ */
+ public void playSound(@NotNull Entity entity, @NotNull Sound sound, float volume, float pitch);
+
+ /**
+ * Play a sound for a player at the location of the entity.
+ *
+ * This function will fail silently if Entity or Sound are null.
+ *
+ * @param entity The entity to play the sound
+ * @param sound The sound to play
+ * @param category The category of the sound
+ * @param volume The volume of the sound
+ * @param pitch The pitch of the sound
+ */
+ public void playSound(@NotNull Entity entity, @NotNull Sound sound, @NotNull SoundCategory category, float volume, float pitch);
+
/**
* Stop the specified sound from playing.
*
@@ -545,6 +570,14 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
@Deprecated
public void updateInventory();
+ /**
+ * Gets this player's previous {@link GameMode}
+ *
+ * @return Previous game mode or null
+ */
+ @Nullable
+ public GameMode getPreviousGameMode();
+
/**
* Sets the current time on the player's client. When relative is true the
* player's time will be kept synchronized to its world time with the
diff --git a/src/main/java/org/bukkit/entity/SpawnCategory.java b/src/main/java/org/bukkit/entity/SpawnCategory.java
new file mode 100644
index 00000000..a2772ada
--- /dev/null
+++ b/src/main/java/org/bukkit/entity/SpawnCategory.java
@@ -0,0 +1,43 @@
+package org.bukkit.entity;
+
+/**
+ * Represents groups of entities with shared spawn behaviors and mob caps.
+ *
+ * @see Minecraft Wiki
+ */
+public enum SpawnCategory {
+
+ /**
+ * Entities related to Monsters, eg: Witch, Zombie, Creeper, etc.
+ */
+ MONSTER,
+ /**
+ * Entities related to Animals, eg: Strider, Cow, Turtle, etc.
+ */
+ ANIMAL,
+ /**
+ * Entities related to Water Animals, eg: Squid or Dolphin.
+ */
+ WATER_ANIMAL,
+ /**
+ * Entities related to Water Ambient, eg: Cod, PufferFish, Tropical Fish,
+ * Salmon, etc.
+ */
+ WATER_AMBIENT,
+ /**
+ * Entities related to Water Underground, eg: Glow Squid.
+ */
+ WATER_UNDERGROUND_CREATURE,
+ /**
+ * Entities related to Ambient, eg: Bat.
+ */
+ AMBIENT,
+ /**
+ * All the Axolotl are represented by this Category.
+ */
+ AXOLOTL,
+ /**
+ * Entities not related to a mob, eg: Player, ArmorStand, Boat, etc.
+ */
+ MISC;
+}
diff --git a/src/main/java/org/bukkit/event/block/BlockDamageAbortEvent.java b/src/main/java/org/bukkit/event/block/BlockDamageAbortEvent.java
new file mode 100644
index 00000000..7d49b862
--- /dev/null
+++ b/src/main/java/org/bukkit/event/block/BlockDamageAbortEvent.java
@@ -0,0 +1,54 @@
+package org.bukkit.event.block;
+
+import org.bukkit.block.Block;
+import org.bukkit.entity.Player;
+import org.bukkit.event.HandlerList;
+import org.bukkit.inventory.ItemStack;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Called when a player stops damaging a Block.
+ */
+public class BlockDamageAbortEvent extends BlockEvent {
+
+ private static final HandlerList handlers = new HandlerList();
+ private final Player player;
+ private final ItemStack itemstack;
+
+ public BlockDamageAbortEvent(@NotNull final Player player, @NotNull final Block block, @NotNull final ItemStack itemInHand) {
+ super(block);
+ this.player = player;
+ this.itemstack = itemInHand;
+ }
+
+ /**
+ * Gets the player that stopped damaging the block involved in this event.
+ *
+ * @return The player that stopped damaging the block
+ */
+ @NotNull
+ public Player getPlayer() {
+ return player;
+ }
+
+ /**
+ * Gets the ItemStack for the item currently in the player's hand.
+ *
+ * @return The ItemStack for the item currently in the player's hand
+ */
+ @NotNull
+ public ItemStack getItemInHand() {
+ return itemstack;
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+}
diff --git a/src/main/java/org/bukkit/event/entity/CreatureSpawnEvent.java b/src/main/java/org/bukkit/event/entity/CreatureSpawnEvent.java
index cb0d91c0..d843f4ad 100644
--- a/src/main/java/org/bukkit/event/entity/CreatureSpawnEvent.java
+++ b/src/main/java/org/bukkit/event/entity/CreatureSpawnEvent.java
@@ -174,9 +174,13 @@ public class CreatureSpawnEvent extends EntitySpawnEvent {
*/
BEEHIVE,
/**
- * When a piglin is converted to a zombified piglib.
+ * When a piglin is converted to a zombified piglin.
*/
PIGLIN_ZOMBIFIED,
+ /**
+ * When an entity is created by a cast spell.
+ */
+ SPELL,
/**
* When an entity is shaking in Powder Snow and a new entity spawns.
*/
diff --git a/src/main/java/org/bukkit/event/entity/StriderTemperatureChangeEvent.java b/src/main/java/org/bukkit/event/entity/StriderTemperatureChangeEvent.java
index 5778f9a6..26a4f88a 100644
--- a/src/main/java/org/bukkit/event/entity/StriderTemperatureChangeEvent.java
+++ b/src/main/java/org/bukkit/event/entity/StriderTemperatureChangeEvent.java
@@ -7,7 +7,7 @@ import org.jetbrains.annotations.NotNull;
/**
* Called when a {@link Strider}'s temperature has changed as a result of
- * entering or existing blocks it considers warm.
+ * entering or exiting blocks it considers warm.
*/
public class StriderTemperatureChangeEvent extends EntityEvent implements Cancellable {
diff --git a/src/main/java/org/bukkit/event/player/PlayerHideEntityEvent.java b/src/main/java/org/bukkit/event/player/PlayerHideEntityEvent.java
new file mode 100644
index 00000000..d8a73cd2
--- /dev/null
+++ b/src/main/java/org/bukkit/event/player/PlayerHideEntityEvent.java
@@ -0,0 +1,52 @@
+package org.bukkit.event.player;
+
+import org.bukkit.Warning;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.Player;
+import org.bukkit.event.HandlerList;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Called when a visible entity is hidden from a player.
+ *
+ * This event is only called when the entity's visibility status is actually
+ * changed.
+ *
+ * This event is called regardless of if the entity was within tracking range.
+ *
+ * @see Player#hideEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)
+ * @deprecated draft API
+ */
+@Deprecated
+@Warning(false)
+public class PlayerHideEntityEvent extends PlayerEvent {
+
+ private static final HandlerList handlers = new HandlerList();
+ private final Entity entity;
+
+ public PlayerHideEntityEvent(@NotNull Player who, @NotNull Entity entity) {
+ super(who);
+ this.entity = entity;
+ }
+
+ /**
+ * Gets the entity which has been hidden from the player.
+ *
+ * @return the hidden entity
+ */
+ @NotNull
+ public Entity getEntity() {
+ return entity;
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+}
diff --git a/src/main/java/org/bukkit/event/player/PlayerShowEntityEvent.java b/src/main/java/org/bukkit/event/player/PlayerShowEntityEvent.java
new file mode 100644
index 00000000..5408a8c1
--- /dev/null
+++ b/src/main/java/org/bukkit/event/player/PlayerShowEntityEvent.java
@@ -0,0 +1,53 @@
+package org.bukkit.event.player;
+
+import org.bukkit.Warning;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.Player;
+import org.bukkit.event.HandlerList;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Called when a hidden entity is shown to a player.
+ *
+ * This event is only called when the entity's visibility status is actually
+ * changed.
+ *
+ * This event is called regardless of whether the entity was within tracking
+ * range.
+ *
+ * @see Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)
+ * @deprecated draft API
+ */
+@Deprecated
+@Warning(false)
+public class PlayerShowEntityEvent extends PlayerEvent {
+
+ private static final HandlerList handlers = new HandlerList();
+ private final Entity entity;
+
+ public PlayerShowEntityEvent(@NotNull Player who, @NotNull Entity entity) {
+ super(who);
+ this.entity = entity;
+ }
+
+ /**
+ * Gets the entity which has been shown to the player.
+ *
+ * @return the shown entity
+ */
+ @NotNull
+ public Entity getEntity() {
+ return entity;
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+}
diff --git a/src/main/java/org/bukkit/inventory/AnvilInventory.java b/src/main/java/org/bukkit/inventory/AnvilInventory.java
index 4af56242..52519cd8 100644
--- a/src/main/java/org/bukkit/inventory/AnvilInventory.java
+++ b/src/main/java/org/bukkit/inventory/AnvilInventory.java
@@ -16,6 +16,20 @@ public interface AnvilInventory extends Inventory {
@Nullable
String getRenameText();
+ /**
+ * Get the item cost (in amount) to complete the current repair.
+ *
+ * @return the amount
+ */
+ int getRepairCostAmount();
+
+ /**
+ * Set the item cost (in amount) to complete the current repair.
+ *
+ * @param amount the amount
+ */
+ void setRepairCostAmount(int amount);
+
/**
* Get the experience cost (in levels) to complete the current repair.
*
diff --git a/src/main/java/org/bukkit/inventory/meta/FireworkMeta.java b/src/main/java/org/bukkit/inventory/meta/FireworkMeta.java
index fe239481..cdbcc8db 100644
--- a/src/main/java/org/bukkit/inventory/meta/FireworkMeta.java
+++ b/src/main/java/org/bukkit/inventory/meta/FireworkMeta.java
@@ -86,8 +86,8 @@ public interface FireworkMeta extends ItemMeta {
* Sets the approximate power of the firework. Each level of power is half
* a second of flight time.
*
- * @param power the power of the firework, from 0-128
- * @throws IllegalArgumentException if {@literal height<0 or height>128}
+ * @param power the power of the firework, from 0-127
+ * @throws IllegalArgumentException if {@literal height<0 or height>127}
*/
void setPower(int power) throws IllegalArgumentException;
diff --git a/src/main/java/org/bukkit/inventory/meta/Repairable.java b/src/main/java/org/bukkit/inventory/meta/Repairable.java
index 0a1d543d..fe053bcb 100644
--- a/src/main/java/org/bukkit/inventory/meta/Repairable.java
+++ b/src/main/java/org/bukkit/inventory/meta/Repairable.java
@@ -5,7 +5,7 @@ import org.jetbrains.annotations.NotNull;
/**
* Represents an item that can be repaired at an anvil.
*/
-public interface Repairable {
+public interface Repairable extends ItemMeta {
/**
* Checks to see if this has a repair penalty
@@ -30,5 +30,6 @@ public interface Repairable {
@SuppressWarnings("javadoc")
@NotNull
+ @Override
Repairable clone();
}
diff --git a/src/main/java/org/bukkit/inventory/meta/SkullMeta.java b/src/main/java/org/bukkit/inventory/meta/SkullMeta.java
index 496254f9..dcefd0ee 100644
--- a/src/main/java/org/bukkit/inventory/meta/SkullMeta.java
+++ b/src/main/java/org/bukkit/inventory/meta/SkullMeta.java
@@ -1,6 +1,7 @@
package org.bukkit.inventory.meta;
import org.bukkit.OfflinePlayer;
+import org.bukkit.profile.PlayerProfile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -55,6 +56,29 @@ public interface SkullMeta extends ItemMeta {
*/
boolean setOwningPlayer(@Nullable OfflinePlayer owner);
+ /**
+ * Gets the profile of the player who owns the skull. This player profile
+ * may appear as the texture depending on skull type.
+ *
+ * @return the profile of the owning player
+ */
+ @Nullable
+ PlayerProfile getOwnerProfile();
+
+ /**
+ * Sets the profile of the player who owns the skull. This player profile
+ * may appear as the texture depending on skull type.
+ *
+ * The profile must contain both a unique id and a skin texture. If either
+ * of these is missing, the profile must contain a name by which the server
+ * will then attempt to look up the unique id and skin texture.
+ *
+ * @param profile the profile of the owning player
+ * @throws IllegalArgumentException if the profile does not contain the
+ * necessary information
+ */
+ void setOwnerProfile(@Nullable PlayerProfile profile);
+
@Override
@NotNull
SkullMeta clone();
diff --git a/src/main/java/org/bukkit/loot/LootTable.java b/src/main/java/org/bukkit/loot/LootTable.java
index 73aa119b..b7529fc7 100644
--- a/src/main/java/org/bukkit/loot/LootTable.java
+++ b/src/main/java/org/bukkit/loot/LootTable.java
@@ -6,6 +6,7 @@ import org.bukkit.Keyed;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
/**
* LootTables are technical files that represent what items should be in
@@ -25,7 +26,7 @@ public interface LootTable extends Keyed {
* @return a list of ItemStacks
*/
@NotNull
- Collection
+ * A player profile always provides a unique id, a non-empty name, or both. Its
+ * unique id and name are immutable, but other properties (such as its textures)
+ * can be altered.
+ *
+ * New profiles can be created via
+ * {@link Server#createPlayerProfile(UUID, String)}.
+ */
+public interface PlayerProfile extends Cloneable, ConfigurationSerializable {
+
+ /**
+ * Gets the player's unique id.
+ *
+ * @return the player's unique id, or
+ * A profile is currently considered complete if it has a name, a unique id,
+ * and textures.
+ *
+ * @return
+ * 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}.
+ *
+ * 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.
+ *
+ * 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:
+ *
+ * Modifying the textures immediately invalidates and clears any previously
+ * present attributes that are specific to official player profiles, such as the
+ * {@link #getTimestamp() timestamp} and {@link #isSigned() signature}.
+ */
+public interface PlayerTextures {
+
+ /**
+ * The different Minecraft skin models.
+ */
+ enum SkinModel {
+ /**
+ * The classic Minecraft skin model.
+ */
+ CLASSIC,
+ /**
+ * The slim model has slimmer arms than the classic model.
+ */
+ SLIM;
+ }
+
+ /**
+ * Checks if the profile stores no textures.
+ *
+ * @return
+ * The URL must point to the Minecraft texture server. Example URL:
+ *
+ * The URL must point to the Minecraft texture server. Example URL:
+ *
+ * A skin model of
+ * This returns {@link SkinModel#CLASSIC} if no skin is set.
+ *
+ * @return the model of the player's skin
+ */
+ @NotNull
+ SkinModel getSkinModel();
+
+ /**
+ * Gets the URL that points to the player's cape.
+ *
+ * @return the URL of the player's cape, or
+ * The URL must point to the Minecraft texture server. Example URL:
+ *
* Schedules a once off task to occur after a delay. This task will be
@@ -93,7 +93,7 @@ public interface BukkitScheduler {
public int scheduleAsyncDelayedTask(@NotNull Plugin plugin, @NotNull Runnable task, long delay);
/**
- * Asynchronous tasks should never access any API in Bukkit. Great care
+ * Asynchronous tasks should never access any API in Bukkit. Great care
* should be taken to assure the thread-safety of asynchronous tasks.
*
* Schedules a once off task to occur as soon as possible. This task will
@@ -109,7 +109,7 @@ public interface BukkitScheduler {
public int scheduleAsyncDelayedTask(@NotNull Plugin plugin, @NotNull Runnable task);
/**
- * Asynchronous tasks should never access any API in Bukkit. Great care
+ * Asynchronous tasks should never access any API in Bukkit. Great care
* should be taken to assure the thread-safety of asynchronous tasks.
*
* Schedules a repeating task. This task will be executed by a thread
@@ -242,7 +242,7 @@ public interface BukkitScheduler {
public BukkitTask runTask(@NotNull Plugin plugin, @NotNull BukkitRunnable task) throws IllegalArgumentException;
/**
- * Asynchronous tasks should never access any API in Bukkit. Great care
+ * Asynchronous tasks should never access any API in Bukkit. Great care
* should be taken to assure the thread-safety of asynchronous tasks.
*
* Returns a task that will run asynchronously.
@@ -257,7 +257,7 @@ public interface BukkitScheduler {
public BukkitTask runTaskAsynchronously(@NotNull Plugin plugin, @NotNull Runnable task) throws IllegalArgumentException;
/**
- * Asynchronous tasks should never access any API in Bukkit. Great care
+ * Asynchronous tasks should never access any API in Bukkit. Great care
* should be taken to assure the thread-safety of asynchronous tasks.
*
* Returns a task that will run asynchronously.
@@ -321,7 +321,7 @@ public interface BukkitScheduler {
public BukkitTask runTaskLater(@NotNull Plugin plugin, @NotNull BukkitRunnable task, long delay) throws IllegalArgumentException;
/**
- * Asynchronous tasks should never access any API in Bukkit. Great care
+ * Asynchronous tasks should never access any API in Bukkit. Great care
* should be taken to assure the thread-safety of asynchronous tasks.
*
* Returns a task that will run asynchronously after the specified number
@@ -338,7 +338,7 @@ public interface BukkitScheduler {
public BukkitTask runTaskLaterAsynchronously(@NotNull Plugin plugin, @NotNull Runnable task, long delay) throws IllegalArgumentException;
/**
- * Asynchronous tasks should never access any API in Bukkit. Great care
+ * Asynchronous tasks should never access any API in Bukkit. Great care
* should be taken to assure the thread-safety of asynchronous tasks.
*
* Returns a task that will run asynchronously after the specified number
@@ -408,7 +408,7 @@ public interface BukkitScheduler {
public BukkitTask runTaskTimer(@NotNull Plugin plugin, @NotNull BukkitRunnable task, long delay, long period) throws IllegalArgumentException;
/**
- * Asynchronous tasks should never access any API in Bukkit. Great care
+ * Asynchronous tasks should never access any API in Bukkit. Great care
* should be taken to assure the thread-safety of asynchronous tasks.
*
* Returns a task that will repeatedly run asynchronously until cancelled,
@@ -427,7 +427,7 @@ public interface BukkitScheduler {
public BukkitTask runTaskTimerAsynchronously(@NotNull Plugin plugin, @NotNull Runnable task, long delay, long period) throws IllegalArgumentException;
/**
- * Asynchronous tasks should never access any API in Bukkit. Great care
+ * Asynchronous tasks should never access any API in Bukkit. Great care
* should be taken to assure the thread-safety of asynchronous tasks.
*
* Returns a task that will repeatedly run asynchronously until cancelled,
diff --git a/src/test/java/org/bukkit/configuration/file/YamlConfigurationTest.java b/src/test/java/org/bukkit/configuration/file/YamlConfigurationTest.java
index a0ff42ab..3522baa0 100644
--- a/src/test/java/org/bukkit/configuration/file/YamlConfigurationTest.java
+++ b/src/test/java/org/bukkit/configuration/file/YamlConfigurationTest.java
@@ -174,4 +174,31 @@ public class YamlConfigurationTest extends FileConfigurationTest {
assertEquals(expected, result);
}
+
+ @Test
+ public void testUnusualMappingKeys() throws InvalidConfigurationException {
+ YamlConfiguration config = getConfig();
+ String content = "[1]: odd\n"
+ + "{2}: choice\n"
+ + "\"3\": of\n"
+ + "4: keys\n"
+ + "null: A\n"
+ + "'null': B\n"
+ + "!!null null: C\n"
+ + "'!!null': X\n";
+ // The keys are parsed as arbitrary Yaml types and then converted to their String representation during config loading.
+ // Consequently, the String representation used by the loaded config might be different to how these keys were originally represented.
+ // Since SnakeYaml does not preserve the original representation in its parsed node tree, we are also not able to reconstruct the original keys during config loading.
+ config.loadFromString(content);
+
+ // This difference in representations also becomes apparent when the config is written back.
+ // Also note: All keys that are parsed as null overwrite each other's values.
+ String expected = "'[1]': odd\n"
+ + "'{2=null}': choice\n"
+ + "'3': of\n"
+ + "'4': keys\n"
+ + "'null': C\n"
+ + "'!!null': X\n";
+ assertEquals(expected, config.saveToString());
+ }
}
+ *
+ *
+ * Note: the {@link SpawnCategory#MISC} are not consider.
+ *
+ * @param spawnCategory the category of spawn
+ * @return the default ticks per {@link SpawnCategory} mobs spawn value
+ */
+ public int getTicksPerSpawns(@NotNull SpawnCategory spawnCategory);
+
/**
* Gets a player object by the given username.
* null
and the name is null
or blank
+ */
+ @NotNull
+ PlayerProfile createPlayerProfile(@Nullable UUID uniqueId, @Nullable String name);
+
+ /**
+ * Creates a new {@link PlayerProfile}.
+ *
+ * @param uniqueId the unique id
+ * @return the new PlayerProfile
+ * @throws IllegalArgumentException if the unique id is null
+ */
+ @NotNull
+ PlayerProfile createPlayerProfile(@NotNull UUID uniqueId);
+
+ /**
+ * Creates a new {@link PlayerProfile}.
+ *
+ * @param name the name
+ * @return the new PlayerProfile
+ * @throws IllegalArgumentException if the name is null
or
+ * blank
+ */
+ @NotNull
+ PlayerProfile createPlayerProfile(@NotNull String name);
+
/**
* Gets a set containing all current IPs that are banned.
*
@@ -1078,7 +1148,9 @@ public interface Server extends PluginMessageRecipient {
* chunk.
*
* @return the monster spawn limit
+ * @deprecated Deprecated in favor of {@link #getSpawnLimit(SpawnCategory)}
*/
+ @Deprecated
int getMonsterSpawnLimit();
/**
@@ -1086,7 +1158,9 @@ public interface Server extends PluginMessageRecipient {
* chunk.
*
* @return the animal spawn limit
+ * @deprecated Deprecated in favor of {@link #getSpawnLimit(SpawnCategory)}
*/
+ @Deprecated
int getAnimalSpawnLimit();
/**
@@ -1094,7 +1168,9 @@ public interface Server extends PluginMessageRecipient {
* a chunk.
*
* @return the water animal spawn limit
+ * @deprecated Deprecated in favor of {@link #getSpawnLimit(SpawnCategory)}
*/
+ @Deprecated
int getWaterAnimalSpawnLimit();
/**
@@ -1102,14 +1178,18 @@ public interface Server extends PluginMessageRecipient {
* in a chunk.
*
* @return the water ambient spawn limit
+ * @deprecated Deprecated in favor of {@link #getSpawnLimit(SpawnCategory)}
*/
+ @Deprecated
int getWaterAmbientSpawnLimit();
/**
* Get user-specified limit for number of water creature underground that can spawn
* in a chunk.
* @return the water underground creature limit
+ * @deprecated Deprecated in favor of {@link #getSpawnLimit(SpawnCategory)}
*/
+ @Deprecated
int getWaterUndergroundCreatureSpawnLimit();
/**
@@ -1117,9 +1197,22 @@ public interface Server extends PluginMessageRecipient {
* a chunk.
*
* @return the ambient spawn limit
+ * @deprecated Deprecated in favor of {@link #getSpawnLimit(SpawnCategory)}
*/
+ @Deprecated
int getAmbientSpawnLimit();
+ /**
+ * Gets user-specified limit for number of {@link SpawnCategory} mobs that can spawn in
+ * a chunk.
+ *
+ * Note: the {@link SpawnCategory#MISC} are not consider.
+ *
+ * @param spawnCategory the category spawn
+ * @return the {@link SpawnCategory} spawn limit
+ */
+ int getSpawnLimit(@NotNull SpawnCategory spawnCategory);
+
/**
* Checks the current thread against the expected primary thread for the
* server.
diff --git a/src/main/java/org/bukkit/StructureType.java b/src/main/java/org/bukkit/StructureType.java
index 8acb2b9d..9d96f4b3 100644
--- a/src/main/java/org/bukkit/StructureType.java
+++ b/src/main/java/org/bukkit/StructureType.java
@@ -19,7 +19,7 @@ import org.jetbrains.annotations.Nullable;
* The registration of new {@link StructureType}s is case-sensitive.
*/
// Order is retrieved from WorldGenFactory
-public final class StructureType {
+public final class StructureType implements Keyed {
private static final Map
+ *
+ *
+ *
+ * null
if not available
+ */
+ @Nullable
+ UUID getUniqueId();
+
+ /**
+ * Gets the player name.
+ *
+ * @return the player name, or null
if not available
+ */
+ @Nullable
+ String getName();
+
+ /**
+ * Gets the {@link PlayerTextures} of this profile.
+ *
+ * @return the textures, not null
+ */
+ @NotNull
+ PlayerTextures getTextures();
+
+ /**
+ * Copies the given textures.
+ *
+ * @param textures the textures to copy, or null
to clear the
+ * textures
+ */
+ void setTextures(@Nullable PlayerTextures textures);
+
+ /**
+ * Checks whether this profile is complete.
+ * true
if this profile is complete
+ */
+ boolean isComplete();
+
+ /**
+ * Produces an updated player profile based on this profile.
+ *
+ * profile.update().thenAcceptAsync(updatedProfile -> {
+ * // Do something with the updated profile:
+ * // ...
+ * }, runnable -> Bukkit.getScheduler().runTask(plugin, runnable));
+ *
+ *
+ * @return a completable future that gets completed with the updated
+ * PlayerProfile once it is available
+ */
+ @NotNull
+ CompletableFuturetrue
if the profile stores no textures
+ */
+ boolean isEmpty();
+
+ /**
+ * Clears the textures.
+ */
+ void clear();
+
+ /**
+ * Gets the URL that points to the player's skin.
+ *
+ * @return the URL of the player's skin, or null
if not set
+ */
+ @Nullable
+ URL getSkin();
+
+ /**
+ * Sets the player's skin to the specified URL, and the skin model to
+ * {@link SkinModel#CLASSIC}.
+ *
+ * http://textures.minecraft.net/texture/b3fbd454b599df593f57101bfca34e67d292a8861213d2202bb575da7fd091ac
+ *
+ *
+ * @param skinUrl the URL of the player's skin, or null
to
+ * unset it
+ */
+ void setSkin(@Nullable URL skinUrl);
+
+ /**
+ * Sets the player's skin and {@link SkinModel}.
+ *
+ * http://textures.minecraft.net/texture/b3fbd454b599df593f57101bfca34e67d292a8861213d2202bb575da7fd091ac
+ *
+ * null
results in {@link SkinModel#CLASSIC} to
+ * be used.
+ *
+ * @param skinUrl the URL of the player's skin, or null
to
+ * unset it
+ * @param skinModel the skin model, ignored if the skin URL is
+ * null
+ */
+ void setSkin(@Nullable URL skinUrl, @Nullable SkinModel skinModel);
+
+ /**
+ * Gets the model of the player's skin.
+ * null
if not set
+ */
+ @Nullable
+ URL getCape();
+
+ /**
+ * Sets the URL that points to the player's cape.
+ *
+ * http://textures.minecraft.net/texture/2340c0e03dd24a11b15a8b33c2a7e9e32abb2051b2481d0ba7defd635ca7a933
+ *
+ *
+ * @param capeUrl the URL of the player's cape, or null
to
+ * unset it
+ */
+ void setCape(@Nullable URL capeUrl);
+
+ /**
+ * Gets the timestamp at which the profile was last updated.
+ *
+ * @return the timestamp, or 0
if unknown
+ */
+ long getTimestamp();
+
+ /**
+ * Checks if the textures are signed and the signature is valid.
+ *
+ * @return true
if the textures are signed and the signature is
+ * valid
+ */
+ boolean isSigned();
+}
diff --git a/src/main/java/org/bukkit/profile/package-info.java b/src/main/java/org/bukkit/profile/package-info.java
new file mode 100644
index 00000000..6f3ed4f0
--- /dev/null
+++ b/src/main/java/org/bukkit/profile/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Classes relevant to player profiles.
+ */
+package org.bukkit.profile;
diff --git a/src/main/java/org/bukkit/scheduler/BukkitScheduler.java b/src/main/java/org/bukkit/scheduler/BukkitScheduler.java
index c239c4de..5aefb7f2 100644
--- a/src/main/java/org/bukkit/scheduler/BukkitScheduler.java
+++ b/src/main/java/org/bukkit/scheduler/BukkitScheduler.java
@@ -76,7 +76,7 @@ public interface BukkitScheduler {
public int scheduleSyncRepeatingTask(@NotNull Plugin plugin, @NotNull BukkitRunnable task, long delay, long period);
/**
- * Asynchronous tasks should never access any API in Bukkit. Great care
+ * Asynchronous tasks should never access any API in Bukkit. Great care
* should be taken to assure the thread-safety of asynchronous tasks.
*