1010import java .util .*;
1111
1212/**
13- * Light Bukkit ScoreBoard API with 1.7-1.13 support
13+ * Simple Bukkit ScoreBoard API with 1.7 to 1.13.2 support !
14+ * Everything is at packet level so you don't need to use it in the main server thread.
1415 * <p>
1516 * You can find the project on <a href="https://github.com/MrMicky-FR/FastBoard">GitHub</a>
1617 *
@@ -79,7 +80,6 @@ public class FastBoard {
7980 }
8081
8182 ENUM_SB_HEALTH_DISPLAY_INTEGER = FastReflection .enumValueOf (ENUM_SB_HEALTH_DISPLAY , "INTEGER" );
82-
8383 ENUM_SB_ACTION_CHANGE = FastReflection .enumValueOf (ENUM_SB_ACTION , "CHANGE" );
8484 ENUM_SB_ACTION_REMOVE = FastReflection .enumValueOf (ENUM_SB_ACTION , "REMOVE" );
8585 } else {
@@ -101,6 +101,11 @@ public class FastBoard {
101101 private String title ;
102102 private List <String > lines = new ArrayList <>();
103103
104+ /**
105+ * Create a new FastBoard for a player
106+ *
107+ * @param player the player the scoreboard is for
108+ */
104109 public FastBoard (Player player ) {
105110 this .player = player ;
106111
@@ -114,6 +119,22 @@ public FastBoard(Player player) {
114119 }
115120 }
116121
122+ /**
123+ * Get the current title of the scoreboard.
124+ *
125+ * @return current scoreboard title
126+ */
127+ public String getTitle () {
128+ return title ;
129+ }
130+
131+ /**
132+ * Update the scoreboard title. The title can't be longer than 32 chars
133+ *
134+ * @param title the new scoreboard title
135+ * @throws IllegalArgumentException if the title is longer than 32 chars
136+ * @throws IllegalStateException if {@link #delete()} was call before
137+ */
117138 public void updateTitle (String title ) {
118139 if (title .equals (this .title )) {
119140 return ;
@@ -132,10 +153,35 @@ public void updateTitle(String title) {
132153 }
133154 }
134155
156+ /**
157+ * Get the current lines of the scoreboard
158+ *
159+ * @return the current lines of the scoreboard
160+ */
161+ public List <String > getLines () {
162+ List <String > lines = new ArrayList <>(this .lines );
163+ Collections .reverse (lines );
164+ return lines ;
165+ }
166+
167+ /**
168+ * Update the lines of the scoreboard
169+ *
170+ * @param lines the new scoreboard lines
171+ * @throws IllegalArgumentException if one line is longer than 30 chars
172+ * @throws IllegalStateException if {@link #delete()} was call before
173+ */
135174 public void updateLines (String ... lines ) {
136175 updateLines (Arrays .asList (lines ));
137176 }
138177
178+ /**
179+ * Update the lines of the scoreboard
180+ *
181+ * @param newLines the new scoreboard lines
182+ * @throws IllegalArgumentException if one line is longer than 30 chars
183+ * @throws IllegalStateException if {@link #delete()} was call before
184+ */
139185 public void updateLines (List <String > newLines ) {
140186 int lineCount = 0 ;
141187 for (String s : newLines ) {
@@ -145,13 +191,11 @@ public void updateLines(List<String> newLines) {
145191 lineCount ++;
146192 }
147193
148- List <String > lines = new ArrayList <>(newLines );
194+ List <String > oldLines = new ArrayList <>(lines );
195+ lines .clear ();
196+ lines .addAll (newLines );
149197 Collections .reverse (lines );
150198
151- List <String > oldLines = this .lines ;
152-
153- this .lines = lines ;
154-
155199 try {
156200 if (oldLines .size () != lines .size ()) {
157201 List <String > oldLinesCopy = new ArrayList <>(oldLines );
@@ -160,13 +204,13 @@ public void updateLines(List<String> newLines) {
160204 for (int i = oldLinesCopy .size (); i > lines .size (); i --) {
161205 sendTeamPacket (i - 1 , TeamMode .REMOVE );
162206
163- sendScorePacket (i - 1 , true );
207+ sendScorePacket (i - 1 , ScoreboardAction . REMOVE );
164208
165209 oldLines .remove (oldLines .size () - 1 );
166210 }
167211 } else {
168212 for (int i = oldLinesCopy .size (); i < lines .size (); i ++) {
169- sendScorePacket (i , false );
213+ sendScorePacket (i , ScoreboardAction . CHANGE );
170214
171215 sendTeamPacket (i , TeamMode .CREATE );
172216
@@ -175,10 +219,6 @@ public void updateLines(List<String> newLines) {
175219 }
176220 }
177221
178- if (lines .isEmpty ()) {
179- return ;
180- }
181-
182222 for (int i = 0 ; i < lines .size (); i ++) {
183223 if (!Objects .equals (oldLines .get (i ), lines .get (i ))) {
184224 sendTeamPacket (i , TeamMode .UPDATE );
@@ -189,16 +229,21 @@ public void updateLines(List<String> newLines) {
189229 }
190230 }
191231
192- public List <String > getLines () {
193- List <String > lines = new ArrayList <>(this .lines );
194- Collections .reverse (lines );
195- return lines ;
196- }
197-
232+ /**
233+ * Get the player associated with this FastBoard
234+ *
235+ * @return current player for this FastBoard
236+ */
198237 public Player getPlayer () {
199238 return player ;
200239 }
201240
241+ /**
242+ * Delete this FastBoard, and will remove the scoreboard for the associated player if he is online.
243+ * After this, all uses of {@link #updateLines} and {@link #updateTitle} will throws an {@link IllegalStateException}
244+ *
245+ * @throws IllegalStateException if this was already call before
246+ */
202247 public void delete () {
203248 try {
204249 for (int i = 0 ; i < lines .size (); i ++) {
@@ -241,22 +286,18 @@ private void sendDisplayObjectivePacket() throws ReflectiveOperationException {
241286 sendPacket (packet );
242287 }
243288
244- private void sendScorePacket (int score , boolean remove ) throws ReflectiveOperationException {
289+ private void sendScorePacket (int score , ScoreboardAction action ) throws ReflectiveOperationException {
245290 Object packet = PACKET_SB_SCORE .newInstance ();
246291
247292 setField (packet , String .class , getColorCode (score ), 0 );
248293
249294 if (VersionType .V1_8 .isHigherOrEqual ()) {
250- if (remove ) {
251- setField (packet , ENUM_SB_ACTION , ENUM_SB_ACTION_REMOVE );
252- } else {
253- setField (packet , ENUM_SB_ACTION , ENUM_SB_ACTION_CHANGE );
254- }
295+ setField (packet , ENUM_SB_ACTION , action == ScoreboardAction .REMOVE ? ENUM_SB_ACTION_REMOVE : ENUM_SB_ACTION_CHANGE );
255296 } else {
256- setField (packet , int .class , remove ? 1 : 0 , 1 );
297+ setField (packet , int .class , action . ordinal () , 1 );
257298 }
258299
259- if (! remove ) {
300+ if (action == ScoreboardAction . CHANGE ) {
260301 setField (packet , String .class , id , 1 );
261302 setField (packet , int .class , score );
262303 }
@@ -314,12 +355,14 @@ private String getColorCode(int score) {
314355
315356 private void sendPacket (Object packet ) throws ReflectiveOperationException {
316357 if (player == null ) {
317- throw new IllegalStateException ("FastBoard is deleted" );
358+ throw new IllegalStateException ("This FastBoard is deleted" );
318359 }
319360
320- Object entityPlayer = PLAYER_GET_HANDLE .invoke (player );
321- Object playerConnection = PLAYER_CONNECTION .get (entityPlayer );
322- SEND_PACKET .invoke (playerConnection , packet );
361+ if (player .isOnline ()) {
362+ Object entityPlayer = PLAYER_GET_HANDLE .invoke (player );
363+ Object playerConnection = PLAYER_CONNECTION .get (entityPlayer );
364+ SEND_PACKET .invoke (playerConnection , packet );
365+ }
323366 }
324367
325368 private void setField (Object object , Class <?> fieldType , Object value ) throws ReflectiveOperationException {
@@ -364,6 +407,12 @@ enum TeamMode {
364407
365408 }
366409
410+ enum ScoreboardAction {
411+
412+ CHANGE , REMOVE
413+
414+ }
415+
367416 enum VersionType {
368417
369418 V1_7 , V1_8 , V1_13 ;
0 commit comments