Fredashay's Welcome Book icon

Fredashay's Welcome Book -----

This plugin gives new players a welcome book.




Updated for Minecraft 1.20.
----------, Nov 11, 2023

Three time's the charm :p
----------, Dec 19, 2020

Starting with Minecraft 1.16.4, the event PlayerJoinEvent is being fired twice each time a player joins the game, causing my plugin to give a new player two Welcome Books. I fixed this by checking if a brand new player already has a Welcome Book before giving him one :-/
----------, Dec 19, 2020

Recompiled for 1.16
----------, Dec 19, 2020

This plugin gives new players a welcome book.

First create a text file in your Minecraft folder named: book(welcome).txt

You can change the file title of the book from (welcome) to whatever else you prefer in the properties file, and also the welcome message.

Edit this file with Notepad. Do not use a word processor like MS Word or Wordpad! The book file must be a pure text file.

A book file looks like this:

^T Book Title
^A Author Name
^C Chapter Title
^P Paragraph
^P Another paragraph
^P Yet another paragraph
^C Another Chapter Title
^P Paragraph
^P Another paragraph
^P Yet another paragraph
^B A line break

See my BOOK plugin for more information...

Code (Text):

package FredashaySpigotWelcomeBook;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.logging.Logger;

import org.bukkit.Material;
import org.bukkit.command.CommandExecutor;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import org.bukkit.inventory.meta.BookMeta;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.java.JavaPlugin;

public class MyPlugin extends JavaPlugin implements Listener, CommandExecutor {
   
   final static char CRLF = (char) 0x0a;  
   final static int pageWidth = 114;
   final static int PageLines = 13;
   final static int pageChars = 240;  

   private static Logger logger = null;
   private static PluginDescriptionFile pdfFile = null;
   private static Properties props = new Properties();
   private static String welcomeMessage = "Please read the welcome book you now have!";
   private static String fileTitle = "welcome";
   
   @Override
    public void onEnable() {
       logger = Logger.getLogger("Minecraft");
       pdfFile = getDescription();
       String propertiesFileName = pdfFile.getName() + ".properties";  
       getProperties(propertiesFileName);  
       getServer().getPluginManager().registerEvents(this,this);
        }  
   
   private void getProperties(String fileName) {
       InputStream input = null;
       try {
           input = new FileInputStream(fileName);
           props.load(input);
           }
       catch (FileNotFoundException ok) {
             saveProperties(fileName);
             }
       catch (IOException oops) {
           logger.info("[" + pdfFile.getName() + "] Error reading properties file '" + fileName + "'. ");          
           oops.printStackTrace(System.err);
           }
       finally {
           if (input != null) {
               try {
                   input.close();
                   }
               catch (IOException oops) {
                   oops.printStackTrace(System.err);
                   }
               }
           }
       if (props.getProperty("TITLE") != null) {
           fileTitle = props.getProperty("TITLE");
           }

       if (props.getProperty("MESSAGE") != null) {
           welcomeMessage = props.getProperty("MESSAGE");
           }
       }
   
   private void saveProperties(String fileName) {
       OutputStream output = null;
       try {
           output = new FileOutputStream(fileName);
           props.setProperty("TITLE", fileTitle);
           props.setProperty("MESSAGE", welcomeMessage);
           props.store(output, null);
           }
       catch (IOException oops) {
           logger.info("[" + pdfFile.getName() + "] Error writing properties file '" + fileName + "'. ");
           oops.printStackTrace(System.err);
           }
       finally {
           try {
               output.close();
               }
           catch (IOException oops) {
               oops.printStackTrace(System.err);
               }
           }
       }
   
   @EventHandler
   public void onPlayerJoin(PlayerJoinEvent event) {
       String fileName = null;              
       Player player = event.getPlayer();
       if (!(event.getPlayer().hasPlayedBefore())) {
           fileName = getFileName(fileTitle);
           if (fileName != null) {
               String rawBook = readBook(fileName, player);
               String bookText = scanBook(rawBook);
               long fileDate = getFileDate(fileName);
               String title = getTitle(bookText);
                String author = getAuthor(bookText);
                String bookPages[] = formatBook(bookText, fileDate);
                ItemStack myBook = createBook(title, author, bookPages);  
                giveItemToPlayer(player, myBook, title);
                logger.info("[" + pdfFile.getName() + "] Gave welcome book to new player '" + player.getName() + "'. ");
               }                              
           }      
       }
   
    private String getFileName(String bookName) {
       String fileName = null;
       String searchName = null;
       File dir = null;
       File files[] = null;
       File file = null;
       int index = 0;
        fileName = null;  
         dir = new File(".");
         files = dir.listFiles();
        index = 0;
        searchName = "";
        while (index < files.length) {
            file = files[index];
             if (file.isFile()) {
                 searchName = file.getName();
                 if (searchName.equalsIgnoreCase("BOOK(" + bookName + ").TXT")) {
                     fileName = searchName;
                     }                      
                 }
             index = index + 1;
            }
        return(fileName);
       }
   
    private String readBook(String fileName, Player plr) {
       File bookFile = null;  
       BufferedReader reader = null;
       String recordBuffer = null;
       String fullText = null;
       bookFile = new File(fileName);
       if (bookFile.exists()) {          
           try {
               fullText = "";
               reader = new BufferedReader(new FileReader(fileName));                              
               recordBuffer = reader.readLine();  
               while (recordBuffer != null) {
                   if (recordBuffer.length() > 0) {
                       fullText = fullText.trim() + " " + recordBuffer.trim();
                       }  
                   recordBuffer = reader.readLine();
                   }
               }
           catch (IOException oops) {
               logger.info("[" + pdfFile.getName() + "] Problem with file '" + fileName + "'. ");          
               fullText = null;
               }              
           finally {
               try {
                   reader.close();
                   }
               catch (IOException oops) {
                   logger.info("[" + pdfFile.getName() + "] Problem with file '" + fileName + "'. ");
                   fullText = null;
                   }
               }          
           }          
       else {
           logger.info("[" + pdfFile.getName() + "] Problem with file '" + fileName + "'. ");
           fullText = null;
           }
       return (fullText);
       }
   
    private String scanBook (String bookIn) {
       String bookOut = "";
       char bookChar = ' ';
       int index = 0;
       while (index < bookIn.length()) {
           bookChar = bookIn.charAt(index);
           if (bookChar == '"') {
               bookOut = bookOut + "\\" + bookChar;
               }
           else if (bookChar == '\\') {
               bookOut = bookOut + "\\" + bookChar;
               }
           else {
               bookOut = bookOut + bookChar;
               }
           index = index + 1;
           }
       return (bookOut);      
       }
   
    private long getFileDate(String fileName) {              
       File bookFile = null;
       long fileDate = 0;
       bookFile = new File(fileName);
       fileDate = 0;
       if (bookFile.exists()) {                  
           fileDate = bookFile.lastModified();
           }
       return(fileDate);
       }
   
   private String getTitle(String fullText) {
       String wordArray[] = null;  
       String word = null;
       int wordIndex = 0;
       String code = null;
       char mode = ' ';
       String title = null;
       wordArray = fullText.split("\\s\\s*");
       wordIndex = 0;  
       title = "";
       while (wordIndex < wordArray.length) {
           word = wordArray[wordIndex].trim();              
           if (word.startsWith("^")) {
               if (word.length() > 1) {
                   code = word.substring(1, 2);
                   if (code.equalsIgnoreCase("T")) {
                       title = "";
                       mode = 'T';
                       wordArray[wordIndex] = "";
                       }
                   else {
                       mode = ' ';
                       }
                   }                                      
               }
           else if (mode == 'T') {
               if (title.length() == 0) {
                   title = word;                    
                   }
               else {
                   title = title + " " + word;
                   }
               wordArray[wordIndex] = "";
               }
           wordIndex = wordIndex + 1;
           }  
       return (title);
       }
   
   private String getAuthor(String fullText) {
       String wordArray[] = null;  
       String word = null;
       int wordIndex = 0;
       String code = null;
       char mode = ' ';
       String author = null;
       wordArray = fullText.split("\\s\\s*");
       wordIndex = 0;  
       author = "";
       while (wordIndex < wordArray.length) {
           word = wordArray[wordIndex].trim();              
           if (word.startsWith("^")) {
               if (word.length() > 1) {
                   code = word.substring(1, 2);
                   if (code.equalsIgnoreCase("A")) {
                       author = "";
                       mode = 'A';
                       wordArray[wordIndex] = "";
                       }
                   else {
                       mode = ' ';
                       }
                   }                                      
               }
           else if (mode == 'A') {
               if (author.length() == 0) {
                   author = word;                    
                   }
               else {
                   author = author + " " + word;
                   }
               wordArray[wordIndex] = "";
               }
           wordIndex = wordIndex + 1;
           }
       return (author);
       }
   
   private String[] formatBook(String fullText, long bookDate) {      
       String wordArray[] = null;  
       String word = null;
       int wordIndex = 0;
       String code = null;
       char mode = ' ';
       String title = null;
       String author = null;
       String pages[] = null;
       String titleWords[] = null;
       int titleIndex = 0;
       String authorWords[] = null;
       int authorIndex = 0;
       int fillerNeeded = 0;
       String by = "by";
       boolean newPage = false;
       int currentPage = 0;
       int lineCount = 0;
       int lineWidth = 0;
       int nextWidth = 0;
       SimpleDateFormat sdf = null;
       String prettyDate = null;      
       Date myDate = null;
       int arrayLength = 0;
       int controlIndex = 0;
       wordArray = fullText.split("\\s\\s*");
       wordIndex = 0;  
       title = "";
       author = "";
       while (wordIndex < wordArray.length) {
           word = wordArray[wordIndex].trim();              
           if (word.startsWith("^")) {
               if (word.length() > 1) {
                   code = word.substring(1, 2);
                   if (code.equalsIgnoreCase("T")) {
                       title = "";
                       mode = 'T';
                       wordArray[wordIndex] = "";
                       }
                   else if (code.equalsIgnoreCase("A")) {
                       author = "";
                       mode = 'A';
                       wordArray[wordIndex] = "";
                       }
                   else {
                       mode = ' ';
                       }
                   }                                      
               }
           else if (mode == 'T') {
               if (title.length() == 0) {
                   title = word;                    
                   }
               else {
                   title = title + " " + word;
                   }
               wordArray[wordIndex] = "";
               }
           else if (mode == 'A') {
               if (author.length() == 0) {
                   author = word;
                   }
               else {
                   author = author + " " + word;
                   }
               wordArray[wordIndex] = "";
               }
           wordIndex = wordIndex + 1;
           }  
       wordIndex = 0;
       pages = new String[1];
       pages[0] = " " + CRLF + CRLF;      
       if (textWidth(title) <= pageWidth) {
           fillerNeeded = pageWidth - textWidth(title);
           pages[0] = pages[0] + spaces(fillerNeeded / 2) + title + CRLF;      
           }
       else {
           titleWords = title.split(" ");
           titleIndex = 0;
           while (titleIndex < titleWords.length) {
               fillerNeeded = pageWidth - textWidth(titleWords[titleIndex]);
               pages[0] = pages[0] + spaces(fillerNeeded / 2) + titleWords[titleIndex] + CRLF;              
               titleIndex = titleIndex + 1;
               }          
           }
       if (author.length() > 0) {
           pages[0] = pages[0] + CRLF;      
           fillerNeeded = pageWidth - textWidth(by);
           pages[0] = pages[0] + spaces(fillerNeeded / 2) + by + CRLF;                  
           if (author.length() <= pageWidth) {
               fillerNeeded = pageWidth - textWidth(author);
               pages[0] = pages[0] + spaces(fillerNeeded / 2) + author + CRLF;
               }
           else {
               authorWords = author.split(" ");
               authorIndex = 0;
               while (authorIndex < authorWords.length) {
                   fillerNeeded = pageWidth - textWidth(authorWords[authorIndex]);
                   pages[0] = pages[0] + spaces(fillerNeeded / 2) + authorWords[authorIndex] + CRLF;              
                   authorIndex = authorIndex + 1;
                   }          
               }          
           }      
       if (bookDate > 0) {
           pages[0] = pages[0] + CRLF;
           myDate = new java.sql.Date(bookDate);                            
           sdf = new SimpleDateFormat("dd-MMM-yyyy");
           prettyDate = sdf.format(myDate);
           fillerNeeded = pageWidth - textWidth(prettyDate);
           pages[0] = pages[0] + spaces(fillerNeeded / 2) + prettyDate;        
           }          
       pages = createNewPage(pages);
       newPage = true;
       currentPage = pages.length - 1;  
       lineCount = 1;
       wordIndex = 0;
       while (wordIndex < wordArray.length) {
           controlIndex = wordIndex;
           if (textWidth(wordArray[wordIndex]) > pageWidth) {
               arrayLength = wordArray[wordIndex].length();
               while (textWidth(subString(wordArray[wordIndex], 0, arrayLength)) > pageWidth) {
                   arrayLength = arrayLength - 1;
                   }
               arrayLength = arrayLength - 1;
               word = subString(wordArray[wordIndex], 0, arrayLength) + "-";
               wordArray[wordIndex] = subString(wordArray[wordIndex], arrayLength, wordArray[wordIndex].length() - arrayLength);
               }
           else {
               word = wordArray[wordIndex].trim();
               wordIndex = wordIndex + 1;
               }
           if (word.length() > 0) {
               if (word.startsWith("^")) {
                   if (word.length() > 1) {
                       code = word.substring(1, 2);
                       if (code.equalsIgnoreCase("C")) {
                           mode = 'C';
                           if (!newPage) {
                               pages = createNewPage(pages);
                               newPage = true;
                               lineWidth = 0;
                               lineCount = 1;
                               currentPage = pages.length - 1;  
                               }                          
                           }
                       else if (code.equalsIgnoreCase("P")) {
                           pages[currentPage] = pages[currentPage] + CRLF + CRLF;
                           lineWidth = 0;
                           lineCount = lineCount + 2;
                           }
                       else if (code.equalsIgnoreCase("B")) {
                           pages[currentPage] = pages[currentPage] + CRLF;
                           lineWidth = 0;
                           lineCount = lineCount + 1;
                           }
                       else {
                           mode = ' ';
                           }
                       }
                   else {
                       mode = ' ';
                       }
                   wordArray[controlIndex] = "";
                   }
               else {
                   if (word.contains("%")) {
                       word = hexDecode(word);
                       }
                   nextWidth = textWidth(word) + textWidth(" ");
                   if (lineWidth + nextWidth > pageWidth) {
                       while ((pages[currentPage].endsWith(" ")) && (pages[currentPage].length() > 1)) {
                           pages[currentPage] = subString(pages[currentPage], 0, pages[currentPage].length() - 1);                          
                           }
                       pages[currentPage] = pages[currentPage] + CRLF;  
                       lineWidth = 0;
                       lineCount = lineCount + 1;                      
                       }
                   if (lineCount > PageLines) {
                       pages = createNewPage(pages);
                       newPage = true;
                       currentPage = pages.length - 1;
                       lineWidth = 0;
                       lineCount = 1;
                       }
                   else if (pages[currentPage].length() >= (pageChars - 4)) {
                       pages = createNewPage(pages);
                       newPage = true;
                       currentPage = pages.length - 1;
                       lineWidth = 0;
                       lineCount = 1;
                       }
                   pages[currentPage] = pages[currentPage] + word + " ";
                   lineWidth = lineWidth + nextWidth;
                   newPage = false;
                   }
               }          
           }      
       return (pages);
       }
   
   private String spaces(int filler) {
       String spaces = "";
       
       while (filler > 0) {
           spaces = spaces + " ";          
           filler = filler - 4;
           }
       return (spaces);
       }
   
   private int textWidth(String word) {          
       int count = 0;
       int index = 0;
       char myChar = ' ';
       
       count = 0;
       index = 0;      
       while (index < word.length()) {
           myChar = word.charAt(index);
           if (myChar == 'I') {
               count = count + 4;
               }
           else if (myChar == 'i') {
               count = count + 2;
               }
           else if (myChar == 'l') {
               count = count + 3;
               }
           else if (myChar == '+') {
               count = count + 3;
               }
           else if (myChar == 'f') {
               count = count + 5;
               }
           else if (myChar == 'k') {
               count = count + 2;
               }
           else if (myChar == '@') {
               count = count + 7;
               }
           else if (myChar == '~') {
               count = count + 7;
               }
           else if (myChar == ' ') {
               count = count + 4;
               }
           else if (myChar == ',') {
               count = count + 2;
               }
           else if (myChar == '.') {
               count = count + 2;
               }
           else if (myChar == '|') {
               count = count + 2;
               }
           else if (myChar == ':') {
               count = count + 2;
               }
           else if (myChar == ';') {
               count = count + 2;
               }
           else if (myChar == '!') {
               count = count + 2;
               }
           else if (myChar == '`') {
               count = count + 3;
               }
           else if (myChar == '\'') {
               count = count + 3;
               }
           else if (myChar == '"') {
               count = count + 5;
               }
           else if (myChar == '*') {
               count = count + 5;
               }
           else if (myChar == '(') {
               count = count + 5;              
               }
           else if (myChar == ')') {
               count = count + 5;
               }
           else if (myChar == '{') {
               count = count + 5;              
               }
           else if (myChar == '}') {
               count = count + 5;
               }
           else if (myChar == '[') {
               count = count + 4;              
               }
           else if (myChar == ']') {
               count = count + 4;
               }
           else {
               count = count + 6;
               }
           index = index + 1;
           }                      
       return(count);
       }
   
   private String hexDecode(String word) {
       int index = 0;
       String hexString = null;
       char funkyChar = ' ';
       index = 0;
       while (index < word.length()) {          
           if ((word.charAt(index) == '%') && (word.length() >= (index + 3))) {
               hexString = subString(word, index + 1, 2);
               funkyChar = (char)Integer.parseInt(hexString, 16);
               word = subString(word, 0, index) + funkyChar + subString(word, (index + 3), (word.length() - (index + 3)));
               }
           index = index + 1;
           }      
       return(word);
       }
   
   private String subString(String stringIn, int start, int length) {
       int stringLength = 0;
       stringLength = start + length;
       if (stringLength > stringIn.length()) {
           stringLength = stringIn.length();
           }
       String stringOut = stringIn.substring(start, stringLength);      
       return(stringOut);
       }
   
   private String[] createNewPage(String[] oldPages) {
       int newPage = oldPages.length + 1;
       String newPages[] = new String[newPage];
       int pageIndex = 0;
       
       pageIndex = 0;
       while (pageIndex < oldPages.length) {
           newPages[pageIndex] = oldPages[pageIndex];
           pageIndex = pageIndex + 1;
           }
       newPages[pageIndex] = "";
       return (newPages);
       }
   
   private ItemStack createBook(String title, String author, String page[]) {
       ItemStack myBook = new ItemStack(Material.WRITTEN_BOOK);
       BookMeta bookData = (BookMeta) myBook.getItemMeta();
       bookData.setTitle(title);
        bookData.setAuthor(author);
        int pageIx = 0;
        List<String> bookPages = new ArrayList<String>();
        if (page.length > 0) {
           pageIx = 0;
           while (pageIx < page.length) {
               bookPages.add(pageIx, page[pageIx]);
               pageIx = pageIx + 1;
               }
            }  
        bookData.setPages(bookPages);
       myBook.setItemMeta(bookData);                      
       return (myBook);
       }
   
   private void giveItemToPlayer(Player player, ItemStack item, String title) {
       PlayerInventory inventoryList = player.getInventory();
       if (inventoryList.getItemInMainHand().getAmount() == 0) {
           inventoryList.setItemInMainHand(item);
           player.updateInventory();
           player.sendMessage("<WELCOME> " + welcomeMessage);
           }
       else if (inventoryList.getItemInOffHand().getAmount() == 0) {
           inventoryList.setItemInOffHand(item);
           player.updateInventory();          
           player.sendMessage("<WELCOME> " + welcomeMessage);      
           }
       else {
           boolean searching = true;
           int invIx = 0;
           while (searching) {
               if (invIx >= inventoryList.getSize()) {
                   logger.info("[" + pdfFile.getName() + "] New player '" + player.getName() + "' has no empty inventory slots?!?!. ");
                   searching = false;
                   }
               else {
                   if (inventoryList.getItem(invIx) == null) {
                       inventoryList.setItem(invIx, item);
                       player.updateInventory();                      
                       player.sendMessage("<WELCOME> " + welcomeMessage);
                       searching = false;
                       }                  
                   }              
               invIx = invIx + 1;
               }
           }
       }
   
   // public void doNothing() { }  
           
    }
 
----------, Sep 30, 2017

Resource Information
Author:
----------
Total Downloads: 680
First Release: Sep 19, 2017
Last Update: Nov 11, 2023
Category: ---------------
All-Time Rating:
0 ratings
Find more info at minecraft-server-list.com...
Version -----
Released: --------------------
Downloads: ------
Version Rating:
----------------------
-- ratings