From 084b100716809ddb5c563ed03318c2cb010f7382 Mon Sep 17 00:00:00 2001
From: Techcable <Techcable@outlook.com>
Date: Mon, 29 Feb 2016 20:02:40 -0600
Subject: [PATCH] Player Tab List and Title APIs


diff --git a/src/main/java/com/destroystokyo/paper/Title.java b/src/main/java/com/destroystokyo/paper/Title.java
new file mode 100644
index 0000000..e1ecd44
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/Title.java
@@ -0,0 +1,358 @@
+package com.destroystokyo.paper;
+
+import net.md_5.bungee.api.chat.BaseComponent;
+import net.md_5.bungee.api.chat.TextComponent;
+
+import org.bukkit.entity.Player;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+/**
+ * Represents a title to may be sent to a {@link Player}.
+ * <p>
+ * <p>A title can be sent without subtitle text.</p>
+ */
+public final class Title {
+
+    /**
+     * The default number of ticks for the title to fade in.
+     */
+    public static final int DEFAULT_FADE_IN = 20;
+    /**
+     * The default number of ticks for the title to stay.
+     */
+    public static final int DEFAULT_STAY = 200;
+    /**
+     * The default number of ticks for the title to fade out.
+     */
+    public static final int DEFAULT_FADE_OUT = 20;
+
+    private final BaseComponent[] title;
+    private final BaseComponent[] subtitle;
+    private final int fadeIn;
+    private final int stay;
+    private final int fadeOut;
+
+    /**
+     * Create a title with the default time values and no subtitle.
+     * <p>
+     * <p>Times use default values.</p>
+     *
+     * @param title the main text of the title
+     * @throws NullPointerException if the title is null
+     */
+    public Title(BaseComponent title) {
+        this(title, null);
+    }
+
+    /**
+     * Create a title with the default time values and no subtitle.
+     * <p>
+     * <p>Times use default values.</p>
+     *
+     * @param title the main text of the title
+     * @throws NullPointerException if the title is null
+     */
+    public Title(BaseComponent[] title) {
+        this(title, null);
+    }
+
+    /**
+     * Create a title with the default time values and no subtitle.
+     * <p>
+     * <p>Times use default values.</p>
+     *
+     * @param title the main text of the title
+     * @throws NullPointerException if the title is null
+     */
+    public Title(String title) {
+        this(title, null);
+    }
+
+    /**
+     * Create a title with the default time values.
+     * <p>
+     * <p>Times use default values.</p>
+     *
+     * @param title    the main text of the title
+     * @param subtitle the secondary text of the title
+     */
+    public Title(BaseComponent title, BaseComponent subtitle) {
+        this(title, subtitle, DEFAULT_FADE_IN, DEFAULT_STAY, DEFAULT_FADE_OUT);
+    }
+
+    /**
+     * Create a title with the default time values.
+     * <p>
+     * <p>Times use default values.</p>
+     *
+     * @param title    the main text of the title
+     * @param subtitle the secondary text of the title
+     */
+    public Title(BaseComponent[] title, BaseComponent[] subtitle) {
+        this(title, subtitle, DEFAULT_FADE_IN, DEFAULT_STAY, DEFAULT_FADE_OUT);
+    }
+
+    /**
+     * Create a title with the default time values.
+     * <p>
+     * <p>Times use default values.</p>
+     *
+     * @param title    the main text of the title
+     * @param subtitle the secondary text of the title
+     */
+    public Title(String title, String subtitle) {
+        this(title, subtitle, DEFAULT_FADE_IN, DEFAULT_STAY, DEFAULT_FADE_OUT);
+    }
+
+    /**
+     * Creates a new title.
+     *
+     * @param title    the main text of the title
+     * @param subtitle the secondary text of the title
+     * @param fadeIn   the number of ticks for the title to fade in
+     * @param stay     the number of ticks for the title to stay on screen
+     * @param fadeOut  the number of ticks for the title to fade out
+     * @throws IllegalArgumentException if any of the times are negative
+     */
+    public Title(BaseComponent title, BaseComponent subtitle, int fadeIn, int stay, int fadeOut) {
+        this(
+                new BaseComponent[]{checkNotNull(title, "title")},
+                subtitle == null ? null : new BaseComponent[]{subtitle},
+                fadeIn,
+                stay,
+                fadeOut
+        );
+    }
+
+    /**
+     * Creates a new title.
+     *
+     * @param title    the main text of the title
+     * @param subtitle the secondary text of the title
+     * @param fadeIn   the number of ticks for the title to fade in
+     * @param stay     the number of ticks for the title to stay on screen
+     * @param fadeOut  the number of ticks for the title to fade out
+     * @throws IllegalArgumentException if any of the times are negative
+     */
+    public Title(BaseComponent[] title, BaseComponent[] subtitle, int fadeIn, int stay, int fadeOut) {
+        checkArgument(fadeIn >= 0, "Negative fadeIn: %s", fadeIn);
+        checkArgument(stay >= 0, "Negative stay: %s", stay);
+        checkArgument(fadeOut >= 0, "Negative fadeOut: %s", fadeOut);
+        this.title = checkNotNull(title, "title");
+        this.subtitle = subtitle;
+        this.fadeIn = fadeIn;
+        this.stay = stay;
+        this.fadeOut = fadeOut;
+    }
+
+    /**
+     * Creates a new title.
+     * <p>
+     * <p>It is recommended to the {@link BaseComponent} constrctors.</p>
+     *
+     * @param title    the main text of the title
+     * @param subtitle the secondary text of the title
+     * @param fadeIn   the number of ticks for the title to fade in
+     * @param stay     the number of ticks for the title to stay on screen
+     * @param fadeOut  the number of ticks for the title to fade out
+     */
+    public Title(String title, String subtitle, int fadeIn, int stay, int fadeOut) {
+        this(
+                TextComponent.fromLegacyText(checkNotNull(title, "title")),
+                subtitle == null ? null : TextComponent.fromLegacyText(subtitle),
+                fadeIn,
+                stay,
+                fadeOut
+        );
+    }
+
+    /**
+     * Gets the text of this title
+     *
+     * @return the text
+     */
+    public BaseComponent[] getTitle() {
+        return this.title;
+    }
+
+    /**
+     * Gets the text of this title's subtitle
+     *
+     * @return the text
+     */
+    public BaseComponent[] getSubtitle() {
+        return this.subtitle;
+    }
+
+    /**
+     * Gets the number of ticks to fade in.
+     * <p>
+     * <p>The returned value is never negative.</p>
+     *
+     * @return the number of ticks to fade in
+     */
+    public int getFadeIn() {
+        return this.fadeIn;
+    }
+
+    /**
+     * Gets the number of ticks to stay.
+     * <p>
+     * <p>The returned value is never negative.</p>
+     *
+     * @return the number of ticks to stay
+     */
+    public int getStay() {
+        return this.stay;
+    }
+
+    /**
+     * Gets the number of ticks to fade out.
+     * <p>
+     * <p>The returned value is never negative.</p>
+     *
+     * @return the number of ticks to fade out
+     */
+    public int getFadeOut() {
+        return this.fadeOut;
+    }
+
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    /**
+     * A builder for creating titles
+     */
+    public static final class Builder {
+
+        private BaseComponent[] title;
+        private BaseComponent[] subtitle;
+        private int fadeIn = DEFAULT_FADE_IN;
+        private int stay = DEFAULT_STAY;
+        private int fadeOut = DEFAULT_FADE_OUT;
+
+        /**
+         * Sets the title to the given text.
+         *
+         * @param title the title text
+         * @return this builder instance
+         * @throws NullPointerException if the title is null
+         */
+        public Builder title(BaseComponent title) {
+            return this.title(new BaseComponent[]{checkNotNull(title, "title")});
+        }
+
+        /**
+         * Sets the title to the given text.
+         *
+         * @param title the title text
+         * @return this builder instance
+         * @throws NullPointerException if the title is null
+         */
+        public Builder title(BaseComponent[] title) {
+            this.title = checkNotNull(title, "title");
+            return this;
+        }
+
+        /**
+         * Sets the title to the given text.
+         * <p>
+         * <p>It is recommended to the {@link BaseComponent} methods.</p>
+         *
+         * @param title the title text
+         * @return this builder instance
+         * @throws NullPointerException if the title is null
+         */
+        public Builder title(String title) {
+            return this.title(TextComponent.fromLegacyText(checkNotNull(title, "title")));
+        }
+
+        /**
+         * Sets the subtitle to the given text.
+         *
+         * @param subtitle the title text
+         * @return this builder instance
+         */
+        public Builder subtitle(BaseComponent subtitle) {
+            return this.subtitle(subtitle == null ? null : new BaseComponent[]{subtitle});
+        }
+
+        /**
+         * Sets the subtitle to the given text.
+         *
+         * @param subtitle the title text
+         * @return this builder instance
+         */
+        public Builder subtitle(BaseComponent[] subtitle) {
+            this.subtitle = subtitle;
+            return this;
+        }
+
+        /**
+         * Sets the subtitle to the given text.
+         * <p>
+         * <p>It is recommended to the {@link BaseComponent} methods.</p>
+         *
+         * @param subtitle the title text
+         * @return this builder instance
+         */
+        public Builder subtitle(String subtitle) {
+            return this.subtitle(subtitle == null ? null : TextComponent.fromLegacyText(subtitle));
+        }
+
+        /**
+         * Sets the number of ticks for the title to fade in
+         *
+         * @param fadeIn the number of ticks to fade in
+         * @return this builder instance
+         * @throws IllegalArgumentException if it is negative
+         */
+        public Builder fadeIn(int fadeIn) {
+            checkArgument(fadeIn >= 0, "Negative fadeIn: %s", fadeIn);
+            this.fadeIn = fadeIn;
+            return this;
+        }
+
+
+        /**
+         * Sets the number of ticks for the title to stay.
+         *
+         * @param stay the number of ticks to stay
+         * @return this builder instance
+         * @throws IllegalArgumentException if it is negative
+         */
+        public Builder stay(int stay) {
+            checkArgument(stay >= 0, "Negative stay: %s", stay);
+            this.stay = stay;
+            return this;
+        }
+
+        /**
+         * Sets the number of ticks for the title to fade out.
+         *
+         * @param fadeOut the number of ticks to fade out
+         * @return this builder instance
+         * @throws IllegalArgumentException if it is negative
+         */
+        public Builder fadeOut(int fadeOut) {
+            checkArgument(fadeOut >= 0, "Negative fadeOut: %s", fadeOut);
+            this.fadeOut = fadeOut;
+            return this;
+        }
+
+        /**
+         * Create a title based on the values in the builder.
+         *
+         * @return a title from the values in this builder
+         * @throws IllegalStateException if title isn't specified
+         */
+        public Title build() {
+            checkState(title != null, "Title not specified");
+            return new Title(this.title, this.subtitle, this.fadeIn, this.stay, this.fadeOut);
+        }
+    }
+}
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
index 024b8dd..50a6a41 100644
--- a/src/main/java/org/bukkit/entity/Player.java
+++ b/src/main/java/org/bukkit/entity/Player.java
@@ -2,6 +2,7 @@ package org.bukkit.entity;
 
 import java.net.InetSocketAddress;
 
+import com.destroystokyo.paper.Title;
 import org.bukkit.Achievement;
 import org.bukkit.ChatColor;
 import org.bukkit.Effect;
@@ -345,6 +346,116 @@ public interface Player extends HumanEntity, Conversable, CommandSender, Offline
      * @param components the components to send
      */
     public void sendMessage(net.md_5.bungee.api.chat.BaseComponent... components);
+
+    /**
+     * Set the text displayed in the player list header and footer for this player
+     *
+     * @param header content for the top of the player list
+     * @param footer content for the bottom of the player list
+     */
+    public void setPlayerListHeaderFooter(net.md_5.bungee.api.chat.BaseComponent[] header, net.md_5.bungee.api.chat.BaseComponent[] footer);
+
+    /**
+     * Set the text displayed in the player list header and footer for this player
+     *
+     * @param header content for the top of the player list
+     * @param footer content for the bottom of the player list
+     */
+    public void setPlayerListHeaderFooter(net.md_5.bungee.api.chat.BaseComponent header, net.md_5.bungee.api.chat.BaseComponent footer);
+
+    /**
+     * Update the times for titles displayed to the player
+     *
+     * @param fadeInTicks  ticks to fade-in
+     * @param stayTicks    ticks to stay visible
+     * @param fadeOutTicks ticks to fade-out
+     * @deprecated Use {@link #updateTitle(Title)}
+     */
+    @Deprecated
+    public void setTitleTimes(int fadeInTicks, int stayTicks, int fadeOutTicks);
+
+    /**
+     * Update the subtitle of titles displayed to the player
+     *
+     * @deprecated Use {@link #updateTitle(Title)}
+     */
+    @Deprecated
+    public void setSubtitle(net.md_5.bungee.api.chat.BaseComponent[] subtitle);
+
+    /**
+     * Update the subtitle of titles displayed to the player
+     *
+     * @deprecated Use {@link #updateTitle(Title)}
+     */
+    @Deprecated
+    public void setSubtitle(net.md_5.bungee.api.chat.BaseComponent subtitle);
+
+    /**
+     * Show the given title to the player, along with the last subtitle set, using the last set times
+     *
+     * @deprecated Use {@link #sendTitle(Title)} or {@link #updateTitle(Title)}
+     */
+    @Deprecated
+    public void showTitle(net.md_5.bungee.api.chat.BaseComponent[] title);
+
+    /**
+     * Show the given title to the player, along with the last subtitle set, using the last set times
+     *
+     * @deprecated Use {@link #sendTitle(Title)} or {@link #updateTitle(Title)}
+     */
+    @Deprecated
+    public void showTitle(net.md_5.bungee.api.chat.BaseComponent title);
+
+    /**
+     * Show the given title and subtitle to the player using the given times
+     *
+     * @param title        big text
+     * @param subtitle     little text under it
+     * @param fadeInTicks  ticks to fade-in
+     * @param stayTicks    ticks to stay visible
+     * @param fadeOutTicks ticks to fade-out
+     * @deprecated Use {@link #sendTitle(Title)} or {@link #updateTitle(Title)}
+     */
+    @Deprecated
+    public void showTitle(net.md_5.bungee.api.chat.BaseComponent[] title, net.md_5.bungee.api.chat.BaseComponent[] subtitle, int fadeInTicks, int stayTicks, int fadeOutTicks);
+
+    /**
+     * Show the given title and subtitle to the player using the given times
+     *
+     * @param title        big text
+     * @param subtitle     little text under it
+     * @param fadeInTicks  ticks to fade-in
+     * @param stayTicks    ticks to stay visible
+     * @param fadeOutTicks ticks to fade-out
+     * @deprecated Use {@link #sendTitle(Title)} or {@link #updateTitle(Title)}
+     */
+    @Deprecated
+    public void showTitle(net.md_5.bungee.api.chat.BaseComponent title, net.md_5.bungee.api.chat.BaseComponent subtitle, int fadeInTicks, int stayTicks, int fadeOutTicks);
+
+    /**
+     * Show the title to the player, overriding any previously displayed title.
+     * <p>
+     * <p>This method overrides any previous title, use {@link #updateTitle(Title)} to change the existing one.</p>
+     *
+     * @param title the title to send
+     * @throws NullPointerException if the title is null
+     */
+    void sendTitle(Title title);
+
+    /**
+     * Show the title to the player, overriding any previously displayed title.
+     * <p>
+     * <p>This method doesn't override previous titles, but changes their values.</p>
+     *
+     * @param title the title to send
+     * @throws NullPointerException if title is null
+     */
+    void updateTitle(Title title);
+
+    /**
+     * Hide any title that is currently visible to the player
+     */
+    public void hideTitle();
     // Paper end
 
     /**
@@ -1089,7 +1200,7 @@ public interface Player extends HumanEntity, Conversable, CommandSender, Offline
      * Resets the title displayed to the player.
      * @deprecated API subject to change.
      */
-    @Deprecated
+    // Paper - undeprecate
     public void resetTitle();
 
 
-- 
2.7.2