PageRenderTime 100ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 1ms

/src/net/sacredlabyrinth/Phaed/PreciousStones/ChatBlock.java

https://github.com/FreezyExp/PreciousStones
Java | 886 lines | 535 code | 130 blank | 221 comment | 135 complexity | 68ee0f02e27e52b0c629bf3c82d12f6e MD5 | raw file
  1. package net.sacredlabyrinth.Phaed.PreciousStones;
  2. import java.util.Arrays;
  3. import org.bukkit.entity.Player;
  4. import org.bukkit.ChatColor;
  5. import java.util.ArrayList;
  6. import java.util.LinkedList;
  7. import java.util.logging.Logger;
  8. import java.util.regex.*;
  9. /**
  10. *
  11. * @author phaed
  12. */
  13. public class ChatBlock
  14. {
  15. private final int colspacing = 12;
  16. private static final int lineLength = 320;
  17. private ArrayList<Double> columnSizes = new ArrayList<Double>();
  18. private ArrayList<Integer> columnSpaces = new ArrayList<Integer>();
  19. private ArrayList<String> columnAlignments = new ArrayList<String>();
  20. private LinkedList<String[]> rows = new LinkedList<String[]>();
  21. private boolean prefix_used = false;
  22. private String color = "";
  23. /**
  24. *
  25. */
  26. public static final Logger log = Logger.getLogger("Minecraft");
  27. /**
  28. *
  29. * @param columnAlignment
  30. */
  31. public void setAlignment(String... columnAlignment)
  32. {
  33. columnAlignments.addAll(Arrays.asList(columnAlignment));
  34. }
  35. /**
  36. *
  37. * @param columnSpacings
  38. */
  39. public void setSpacing(int... columnSpacings)
  40. {
  41. for (int spacing : columnSpacings)
  42. {
  43. columnSpaces.add(spacing);
  44. }
  45. }
  46. /**
  47. *
  48. * @param columnPercentages
  49. * @param prefix
  50. */
  51. public void setColumnSizes(String prefix, double... columnPercentages)
  52. {
  53. int ll = lineLength;
  54. if (prefix != null)
  55. {
  56. ll = lineLength - (int) msgLength(prefix);
  57. }
  58. for (double percentage : columnPercentages)
  59. {
  60. columnSizes.add(Math.floor((percentage / 100) * ll));
  61. }
  62. }
  63. /**
  64. *
  65. * @return
  66. */
  67. public boolean hasContent()
  68. {
  69. return rows.size() > 0;
  70. }
  71. /**
  72. *
  73. * @param contents
  74. */
  75. public void addRow(String... contents)
  76. {
  77. rows.add(contents);
  78. }
  79. /**
  80. *
  81. * @return
  82. */
  83. public int size()
  84. {
  85. return rows.size();
  86. }
  87. /**
  88. *
  89. */
  90. public void clear()
  91. {
  92. rows.clear();
  93. }
  94. /**
  95. *
  96. * @param player
  97. * @param amount
  98. * @return
  99. */
  100. public boolean sendBlock(Player player, int amount)
  101. {
  102. if (player == null)
  103. {
  104. return false;
  105. }
  106. if (rows.size() == 0)
  107. {
  108. return false;
  109. }
  110. // if no column sizes provided them
  111. // make some up based on the data
  112. if (columnSizes.isEmpty())
  113. {
  114. // generate columns sizes
  115. int col_count = rows.get(0).length;
  116. for (int i = 0; i < col_count; i++)
  117. {
  118. // add custom column spacing if specified
  119. int spacing = colspacing;
  120. if (columnSpaces.size() >= (i + 1))
  121. {
  122. spacing = columnSpaces.get(i);
  123. }
  124. columnSizes.add(getMaxWidth(i) + spacing);
  125. }
  126. }
  127. // size up all sections
  128. for (int i = 0; i < amount; i++)
  129. {
  130. if (rows.size() == 0)
  131. {
  132. continue;
  133. }
  134. String rowstring = "";
  135. String row[] = rows.pollFirst();
  136. for (int sid = 0; sid < row.length; sid++)
  137. {
  138. String section = row[sid];
  139. double colsize = (columnSizes.size() >= (sid + 1)) ? columnSizes.get(sid) : 0;
  140. String align = (columnAlignments.size() >= (sid + 1)) ? columnAlignments.get(sid) : "l";
  141. if (align.equalsIgnoreCase("r"))
  142. {
  143. if (msgLength(section) > colsize)
  144. {
  145. rowstring += cropLeftToFit(section, colsize);
  146. }
  147. else if (msgLength(section) < colsize)
  148. {
  149. rowstring += paddLeftToFit(section, colsize);
  150. }
  151. }
  152. else if (align.equalsIgnoreCase("l"))
  153. {
  154. if (msgLength(section) > colsize)
  155. {
  156. rowstring += cropRightToFit(section, colsize);
  157. }
  158. else if (msgLength(section) < colsize)
  159. {
  160. rowstring += paddRightToFit(section, colsize);
  161. }
  162. }
  163. else if (align.equalsIgnoreCase("c"))
  164. {
  165. if (msgLength(section) > colsize)
  166. {
  167. rowstring += cropRightToFit(section, colsize);
  168. }
  169. else if (msgLength(section) < colsize)
  170. {
  171. rowstring += centerInLineOf(section, colsize);
  172. }
  173. }
  174. else if (align.equalsIgnoreCase("w"))
  175. {
  176. if (msgLength(section) > colsize)
  177. {
  178. rowstring += section;
  179. }
  180. else if (msgLength(section) < colsize)
  181. {
  182. rowstring += paddRightToFit(section, colsize);
  183. }
  184. }
  185. }
  186. String msg = cropRightToFit(rowstring, lineLength);
  187. if (color.length() > 0)
  188. {
  189. msg = color + msg;
  190. }
  191. player.sendMessage(msg);
  192. }
  193. return rows.size() > 0;
  194. }
  195. /**
  196. *
  197. * @param player
  198. * @param prefix
  199. */
  200. public void sendBlock(Player player, String prefix)
  201. {
  202. if (player == null)
  203. {
  204. return;
  205. }
  206. if (rows.size() == 0)
  207. {
  208. return;
  209. }
  210. prefix_used = prefix == null ? true : false;
  211. String empty_prefix = ChatBlock.makeEmpty(prefix);
  212. // if no column sizes provided them
  213. // make some up based on the data
  214. if (columnSizes.isEmpty())
  215. {
  216. // generate columns sizes
  217. int col_count = rows.get(0).length;
  218. for (int i = 0; i < col_count; i++)
  219. {
  220. // add custom column spacing if specified
  221. int spacing = colspacing;
  222. if (columnSpaces.size() >= (i + 1))
  223. {
  224. spacing = columnSpaces.get(i);
  225. }
  226. columnSizes.add(getMaxWidth(i) + spacing);
  227. }
  228. }
  229. // size up all sections
  230. for (String[] row : rows)
  231. {
  232. String rowstring = "";
  233. for (int sid = 0; sid < row.length; sid++)
  234. {
  235. String section = row[sid];
  236. double colsize = (columnSizes.size() >= (sid + 1)) ? columnSizes.get(sid) : 0;
  237. String align = (columnAlignments.size() >= (sid + 1)) ? columnAlignments.get(sid) : "l";
  238. if (align.equalsIgnoreCase("r"))
  239. {
  240. if (msgLength(section) > colsize)
  241. {
  242. rowstring += cropLeftToFit(section, colsize);
  243. }
  244. else if (msgLength(section) < colsize)
  245. {
  246. rowstring += paddLeftToFit(section, colsize);
  247. }
  248. }
  249. else if (align.equalsIgnoreCase("l"))
  250. {
  251. if (msgLength(section) > colsize)
  252. {
  253. rowstring += cropRightToFit(section, colsize);
  254. }
  255. else if (msgLength(section) < colsize)
  256. {
  257. rowstring += paddRightToFit(section, colsize);
  258. }
  259. }
  260. else if (align.equalsIgnoreCase("c"))
  261. {
  262. if (msgLength(section) > colsize)
  263. {
  264. rowstring += cropRightToFit(section, colsize);
  265. }
  266. else if (msgLength(section) < colsize)
  267. {
  268. rowstring += centerInLineOf(section, colsize);
  269. }
  270. }
  271. }
  272. String msg = cropRightToFit((prefix_used ? empty_prefix : prefix) + " " + rowstring, lineLength);
  273. if (color.length() > 0)
  274. {
  275. msg = color + msg;
  276. }
  277. player.sendMessage(msg);
  278. prefix_used = true;
  279. }
  280. }
  281. /**
  282. *
  283. * @param player
  284. */
  285. public void sendBlock(Player player)
  286. {
  287. sendBlock(player, null);
  288. }
  289. /**
  290. * Outputs a message to everybody
  291. * @param sender
  292. * @param msg
  293. */
  294. public static void sendMessageAll(Player sender, String msg)
  295. {
  296. sendMessageAll(sender, msg);
  297. }
  298. /**
  299. *
  300. * @param col
  301. * @return
  302. */
  303. public double getMaxWidth(double col)
  304. {
  305. double maxWidth = 0;
  306. for (String[] row : rows)
  307. {
  308. maxWidth = Math.max(maxWidth, msgLength(row[(int) col]));
  309. }
  310. return maxWidth;
  311. }
  312. /**
  313. *
  314. * @param msg
  315. * @return
  316. */
  317. public static String centerInLine(String msg)
  318. {
  319. return centerInLineOf(msg, lineLength);
  320. }
  321. /**
  322. *
  323. * @param msg
  324. * @param lineLength
  325. * @return
  326. */
  327. public static String centerInLineOf(String msg, double lineLength)
  328. {
  329. double length = msgLength(msg);
  330. double diff = lineLength - length;
  331. // if too big for line return it as is
  332. if (diff < 0)
  333. {
  334. return msg;
  335. }
  336. double sideSpace = diff / 2;
  337. // pad the left with space
  338. msg = paddLeftToFit(msg, length + sideSpace);
  339. // padd the right with space
  340. msg = paddRightToFit(msg, length + sideSpace + sideSpace);
  341. return msg;
  342. }
  343. /**
  344. *
  345. * @param str
  346. * @return
  347. */
  348. public static String makeEmpty(String str)
  349. {
  350. if (str == null)
  351. {
  352. return "";
  353. }
  354. return paddLeftToFit("", msgLength(str));
  355. }
  356. /**
  357. *
  358. * @param msg
  359. * @param length
  360. * @return
  361. */
  362. public static String cropRightToFit(String msg, double length)
  363. {
  364. if (msg == null || msg.length() == 0 || length == 0)
  365. {
  366. return "";
  367. }
  368. while (msgLength(msg) >= length)
  369. {
  370. msg = msg.substring(0, msg.length() - 2);
  371. }
  372. return msg;
  373. }
  374. /**
  375. *
  376. * @param msg
  377. * @param length
  378. * @return
  379. */
  380. public static String cropLeftToFit(String msg, double length)
  381. {
  382. if (msg == null || msg.length() == 0 || length == 0)
  383. {
  384. return "";
  385. }
  386. while (msgLength(msg) >= length)
  387. {
  388. msg = msg.substring(1);
  389. }
  390. return msg;
  391. }
  392. /**
  393. * Padds left til the string is a certain size
  394. * @param msg
  395. * @param length
  396. * @return
  397. */
  398. public static String paddLeftToFit(String msg, double length)
  399. {
  400. if (msgLength(msg) > length)
  401. {
  402. return msg;
  403. }
  404. while (msgLength(msg) < length)
  405. {
  406. msg = " " + msg;
  407. }
  408. return msg;
  409. }
  410. /**
  411. * Pads right til the string is a certain size
  412. * @param msg
  413. * @param length
  414. * @return
  415. */
  416. public static String paddRightToFit(String msg, double length)
  417. {
  418. if (msgLength(msg) > length)
  419. {
  420. return msg;
  421. }
  422. while (msgLength(msg) < length)
  423. {
  424. msg += " ";
  425. }
  426. return msg;
  427. }
  428. /**
  429. * Finds the length on the screen of a string. Ignores colors.
  430. * @param str
  431. * @return
  432. */
  433. public static double msgLength(String str)
  434. {
  435. double length = 0;
  436. str = cleanColors(str);
  437. // Loop through all the characters, skipping any color characters and their following color codes
  438. for (int x = 0; x < str.length(); x++)
  439. {
  440. int len = charLength(str.charAt(x));
  441. if (len > 0)
  442. {
  443. length += len;
  444. }
  445. else
  446. {
  447. x++;
  448. }
  449. }
  450. return length;
  451. }
  452. /**
  453. *
  454. * @param str
  455. * @return
  456. */
  457. public static String cleanColors(String str)
  458. {
  459. String patternStr = "�.";
  460. String replacementStr = "";
  461. Pattern pattern = Pattern.compile(patternStr);
  462. Matcher matcher = pattern.matcher(str);
  463. String out = matcher.replaceAll(replacementStr);
  464. return out;
  465. }
  466. /**
  467. * Finds the visual length of the character on the screen.
  468. * @param x
  469. * @return
  470. */
  471. public static int charLength(char x)
  472. {
  473. if ("i.:,;|!".indexOf(x) != -1)
  474. {
  475. return 2;
  476. }
  477. else if ("l'".indexOf(x) != -1)
  478. {
  479. return 3;
  480. }
  481. else if ("tI[]".indexOf(x) != -1)
  482. {
  483. return 4;
  484. }
  485. else if ("fk{}<>\"*()".indexOf(x) != -1)
  486. {
  487. return 5;
  488. }
  489. else if ("abcdeghjmnopqrsuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ1234567890\\/#?$%-=_+&^".indexOf(x) != -1)
  490. {
  491. return 6;
  492. }
  493. else if ("@~".indexOf(x) != -1)
  494. {
  495. return 7;
  496. }
  497. else if (x == ' ')
  498. {
  499. return 4;
  500. }
  501. else
  502. {
  503. return -1;
  504. }
  505. }
  506. /**
  507. *
  508. * @param msg
  509. * @return
  510. */
  511. public static String[] wordWrap(String msg)
  512. {
  513. return wordWrap(msg, 0);
  514. }
  515. /**
  516. * Cuts the message apart into whole words short enough to fit on one line
  517. * @param msg
  518. * @param prefixLn
  519. * @return
  520. */
  521. public static String[] wordWrap(String msg, int prefixLn)
  522. {
  523. // Split each word apart
  524. ArrayList<String> split = new ArrayList<String>();
  525. split.addAll(Arrays.asList(msg.split(" ")));
  526. // Create an array list for the output
  527. ArrayList<String> out = new ArrayList<String>();
  528. // While i is less than the length of the array of words
  529. while (!split.isEmpty())
  530. {
  531. int len = 0;
  532. // Create an array list to hold individual words
  533. ArrayList<String> words = new ArrayList<String>();
  534. // Loop through the words finding their length and increasing
  535. // j, the end point for the sub string
  536. while (!split.isEmpty() && split.get(0) != null && len <= (lineLength - prefixLn))
  537. {
  538. double wordLength = msgLength(split.get(0)) + 4;
  539. // If a word is too long for a line
  540. if (wordLength > (lineLength - prefixLn))
  541. {
  542. String[] tempArray = wordCut(len, split.remove(0));
  543. words.add(tempArray[0]);
  544. split.add(tempArray[1]);
  545. }
  546. // If the word is not too long to fit
  547. len += wordLength;
  548. if (len < (lineLength - prefixLn) + 4)
  549. {
  550. words.add(split.remove(0));
  551. }
  552. }
  553. // Merge them and add them to the output array.
  554. String merged = combineSplit(0, words.toArray(new String[words.size()]), " ") + " ";
  555. out.add(merged.replaceAll("\\s+$", ""));
  556. }
  557. // Convert to an array and return
  558. return out.toArray(new String[out.size()]);
  559. }
  560. /**
  561. *
  562. * @param startIndex
  563. * @param string
  564. * @param seperator
  565. * @return
  566. */
  567. public static String combineSplit(int startIndex, String[] string, String seperator)
  568. {
  569. StringBuilder builder = new StringBuilder();
  570. for (int i = startIndex; i < string.length; i++)
  571. {
  572. builder.append(string[i]);
  573. builder.append(seperator);
  574. }
  575. builder.deleteCharAt(builder.length() - seperator.length());
  576. return builder.toString();
  577. }
  578. /**
  579. * Cuts apart a word that is too long to fit on one line
  580. * @param lengthBefore
  581. * @param str
  582. * @return
  583. */
  584. public static String[] wordCut(int lengthBefore, String str)
  585. {
  586. int length = lengthBefore;
  587. // Loop through all the characters, skipping any color characters and their following color codes
  588. String[] output = new String[2];
  589. int x = 0;
  590. while (length < lineLength && x < str.length())
  591. {
  592. int len = charLength(str.charAt(x));
  593. if (len > 0)
  594. {
  595. length += len;
  596. }
  597. else
  598. {
  599. x++;
  600. }
  601. x++;
  602. }
  603. if (x > str.length())
  604. {
  605. x = str.length();
  606. }
  607. // Add the substring to the output after cutting it
  608. output[0] = str.substring(0, x);
  609. // Add the last of the string to the output.
  610. output[1] = str.substring(x);
  611. return output;
  612. }
  613. /**
  614. * Outputs a single line out, crops overflow
  615. * @param receiver
  616. * @param msg
  617. */
  618. public static void saySingle(Player receiver, String msg)
  619. {
  620. if (receiver == null)
  621. {
  622. return;
  623. }
  624. receiver.sendMessage(cropRightToFit(colorize(new String[] { msg })[0], lineLength));
  625. }
  626. /**
  627. * Outputs a message to a user
  628. * @param receiver
  629. * @param msg
  630. */
  631. public static void sendMessage(Player receiver, String msg)
  632. {
  633. sendPrefixedMessage(receiver, null, msg);
  634. }
  635. /**
  636. * Outputs a message to a user
  637. * @param receiver
  638. * @param prefix
  639. * @param msg
  640. */
  641. public static void sendPrefixedMessage(Player receiver, String prefix, String msg)
  642. {
  643. if (receiver == null)
  644. {
  645. return;
  646. }
  647. int prefix_width = prefix == null ? 0 : (int) msgLength(prefix);
  648. String[] message = colorize(wordWrap(msg, prefix_width));
  649. for (String out : message)
  650. {
  651. receiver.sendMessage((prefix == null ? "" : prefix + " ") + out);
  652. }
  653. }
  654. /**
  655. * Send blank lie
  656. * @param color
  657. */
  658. public void startColor(String color)
  659. {
  660. this.color = color;
  661. }
  662. /**
  663. * Send blank lie
  664. * @param receiver
  665. */
  666. public static void sendBlank(Player receiver)
  667. {
  668. if (receiver == null)
  669. {
  670. return;
  671. }
  672. receiver.sendMessage(" ");
  673. }
  674. /**
  675. * Colors each line
  676. * @param message
  677. * @return
  678. */
  679. public static String[] say(String message)
  680. {
  681. return colorize(wordWrap(message));
  682. }
  683. /**
  684. *
  685. * @param message
  686. * @return
  687. */
  688. public static String[] colorize(String[] message)
  689. {
  690. return colorizeBase(message, 167);
  691. }
  692. /**
  693. *
  694. * @param message
  695. * @return
  696. */
  697. public static String colorize(String message)
  698. {
  699. return colorizeBase((new String[]
  700. {
  701. message
  702. }), 167)[0];
  703. }
  704. /**
  705. *
  706. * @param message
  707. * @param charcode
  708. * @return
  709. */
  710. public static String[] colorizeBase(String[] message, int charcode)
  711. {
  712. if (message != null && message[0] != null && !message[0].isEmpty())
  713. {
  714. // Go through each line
  715. String prevColor = "";
  716. String lastColor = "";
  717. int counter = 0;
  718. for (String msg : message)
  719. {
  720. // Loop through looking for a color code
  721. for (int x = 0; x < msg.length(); x++)
  722. {
  723. // If the char is color code
  724. if (msg.codePointAt(x) == charcode)
  725. {
  726. // advance x to the next character
  727. x += 1;
  728. lastColor = ChatColor.getByCode(Integer.parseInt(msg.charAt(x) + "", 16)) + "";
  729. }
  730. }
  731. // Replace the message with the colorful message
  732. message[counter] = prevColor + msg;
  733. prevColor = lastColor;
  734. counter++;
  735. }
  736. }
  737. return message;
  738. }
  739. /**
  740. *
  741. * @param prefix
  742. * @return
  743. */
  744. public String firstPrefix(String prefix)
  745. {
  746. if (prefix_used)
  747. {
  748. return ChatBlock.makeEmpty(prefix);
  749. }
  750. else
  751. {
  752. prefix_used = true;
  753. return prefix;
  754. }
  755. }
  756. }