03.02.2016, 18:34
(
Последний раз редактировалось Alf21; 03.02.2016 в 18:38.
Причина: Added link for the original article
)
This is an info chat (written in Java for the Shoebill Plugin), which created PlayerTextdraws and displays them animated in a adjustable duration.
ChatMessage.java
Chat.java
Installation:
Initialize the chat in a Plugin in onEnable() or in Gamemode in onInit()! You need to save the reference (Chat chat = new Chat()). So on, uninitialize the chat in onDisable() with chat.destroy();
Example use:
A Command:
Coming updates: Performance improvement (better visibility) with pre-calculation!
Please leave a command, thanks
ChatMessage.java
Код:
/** * */ package me.alf21.util.chat; import java.util.regex.Matcher; import java.util.regex.Pattern; import net.gtaun.shoebill.constant.TextDrawAlign; import net.gtaun.shoebill.constant.TextDrawFont; import net.gtaun.shoebill.data.Color; import net.gtaun.shoebill.object.Destroyable; import net.gtaun.shoebill.object.Player; import net.gtaun.shoebill.object.PlayerTextdraw; import net.gtaun.shoebill.object.Timer; /** * @author Alf21 * */ public class ChatMessage implements Destroyable{ private PlayerTextdraw textdraw; private int slot; private Timer timer; private boolean sliding; private String text; private int count; private Player player; private Long time; private int currentEndIndex; public ChatMessage(Player player, String text, int slot) { this.player = player; this.text = removeNonColorCodes(text).trim(); this.slot = slot; count = 1; createTextdraw(0,0); time = System.currentTimeMillis(); } public void slideIn() { sliding = true; reset(); final int length = getTextLength(); final int interval = (int) Chat.slideTime/length; currentEndIndex = 0; timer = Timer.create(interval, length, (factualInterval) -> { currentEndIndex++; currentEndIndex = cutTextIn(currentEndIndex); textdraw.hide(); textdraw.setText(text.substring(0, currentEndIndex)); textdraw.show(); if(count == length) { sliding = false; timer.stop(); } count++; }); timer.start(); } public void slideOut() { sliding = true; reset(); final int length = getTextLength(); final int interval = (int) Chat.slideTime/length; currentEndIndex = text.length(); timer = Timer.create(interval, length-1, (factualInterval) -> { currentEndIndex--; currentEndIndex = cutTextOut(currentEndIndex); textdraw.hide(); textdraw.setText(text.substring(0, currentEndIndex)); textdraw.show(); if(count == length-1) { sliding = false; timer.stop(); } count++; }); timer.start(); } public void moveUp() { reset(); final int maxCount = 15; final int interval = (int) Chat.slideTime/maxCount; timer = Timer.create(interval, maxCount, (factualInterval) -> { textdraw.hide(); textdraw.destroy(); createTextdraw(0, (float) -count*(15f/(float) maxCount)); textdraw.show(); if(count == maxCount) { slot++; timer.stop(); } count++; }); timer.start(); } public void hide() { textdraw.hide(); } public void show() { textdraw.show(); } private void reset() { if(timer != null) timer.destroy(); count = 1; } private void createTextdraw(float x, float y) { textdraw = PlayerTextdraw.create(player, 630+x, 385-15*slot+y); textdraw.setText(text); textdraw.setAlignment(TextDrawAlign.RIGHT); textdraw.setBackgroundColor(Color.BLACK); textdraw.setFont(TextDrawFont.get(1)); textdraw.setLetterSize(0.5f, 1); textdraw.setColor(Color.WHITE); textdraw.setOutlineSize(1); textdraw.setProportional(true); textdraw.setSelectable(false); } /** * @return the sliding */ public boolean isSliding() { return sliding; } /** * @param sliding the sliding to set */ public void setSliding(boolean sliding) { this.sliding = sliding; } /** * @return the time when textdraw was created */ public Long getTime() { return time; } /** * @return the textdraw */ public PlayerTextdraw getTextdraw() { return textdraw; } /** * @return the player */ public Player getPlayer() { return player; } /* (non-Javadoc) * @see net.gtaun.shoebill.object.Destroyable#destroy() */ @Override public void destroy() { if(timer != null) { if(timer.isRunning()) timer.stop(); timer.destroy(); timer = null; } if(textdraw != null) { textdraw.hide(); textdraw.destroy(); textdraw = null; } } /* (non-Javadoc) * @see net.gtaun.shoebill.object.Destroyable#isDestroyed() */ @Override public boolean isDestroyed() { if(timer != null || textdraw != null) return false; return true; } private String removeNonColorCodes(String text) { final String prefixOfColorCodes = "COLOR"; //The prefix of any color code like "COLOR_RED" <- HERE>> if String == "": "_RED" final String connectionOfColorCodes = "\u005F"; //The connection label or Unicode, here: "\u005F" == "_" <- HERE>> if String == "": "COLORRED" String replaceStr = prefixOfColorCodes + connectionOfColorCodes; text = text.replaceAll("\u007E" + "w" + "\u007E", replaceStr + "WHITE"); text = text.replaceAll("\u007E" + "r" + "\u007E", replaceStr + "RED"); text = text.replaceAll("\u007E" + "g" + "\u007E", replaceStr + "GREEN"); text = text.replaceAll("\u007E" + "b" + "\u007E", replaceStr + "DARK" + connectionOfColorCodes + "BLUE"); text = text.replaceAll("\u007E" + "y" + "\u007E", replaceStr + "YELLOW"); text = text.replaceAll("\u007E" + "p" + "\u007E", replaceStr + "PURPLE"); text = text.replaceAll("\u007E" + "l" + "\u007E", replaceStr + "BLACK"); text = text.replaceAll("\u007E" + "h" + "\u007E", replaceStr + "LIGHTER"); text = text.replaceAll("\u007E+([\\w[\u003C\u003E&&[\\S]]]?)\u007E", ""); //replace unknown colors and Commands text = text.replaceAll("\u007E", ""); //replace other "~" text = text.replaceAll(replaceStr + "WHITE", "\u007E" + "w" + "\u007E"); text = text.replaceAll(replaceStr + "RED", "\u007E" + "r" + "\u007E"); text = text.replaceAll(replaceStr + "GREEN", "\u007E" + "g" + "\u007E"); text = text.replaceAll(replaceStr + "DARK" + connectionOfColorCodes + "BLUE", "\u007E" + "b" + "\u007E"); text = text.replaceAll(replaceStr + "YELLOW", "\u007E" + "y" + "\u007E"); text = text.replaceAll(replaceStr + "PURPLE", "\u007E" + "p" + "\u007E"); text = text.replaceAll(replaceStr + "BLACK", "\u007E" + "l" + "\u007E"); text = text.replaceAll(replaceStr + "LIGHTER", "\u007E" + "h" + "\u007E"); return text; } private int cutTextIn(int endIndex) { int currentEndIndex = endIndex; String string = text.substring(0, currentEndIndex); while(string.trim().length() < string.length()){ currentEndIndex++; string = text.substring(0, currentEndIndex); } //check whether string contains color codes Matcher matcher = Pattern.compile("\u007E+([\\w[\u003C\u003E&&[\\S]]]{1})\u007E").matcher(text); //~r~| if(matcher.find()) { //match ~ int matcherState = 0; matcher = Pattern.compile("\u007E+([\\w[\u003C\u003E&&[\\S]]]{1})\u007E\\z").matcher(string); //~r~|... Matcher matcher2 = Pattern.compile("\u007E+([\\w[\u003C\u003E&&[\\S]]]{1})\u007E+([\\w[\u003C\u003E&&[\\S]]]{1})\u007E\\z").matcher(string); //~s~r~|... if(matcher.find() && !matcher2.find()) { matcher = Pattern.compile("\u007E+([\\w[\u003C\u003E&&[\\S]]]{1})\u007E\\z").matcher(string); //~r~|... matcherState = 3; } else { matcher = Pattern.compile("\u007E+([\\w[\u003C\u003E&&[\\S]]]{1})\\z").matcher(string); //~r|... if(matcher.find()) { matcher = Pattern.compile("\u007E+([\\w[\u003C\u003E&&[\\S]]]{1})\\z").matcher(string); //~r|... matcherState = 4; } else { matcher = Pattern.compile("\u007E\\z").matcher(string); //~|... matcherState = 5; } } while(matcher.find()) { //check whether color code is after this color code if(currentEndIndex+matcherState <= text.length()) { currentEndIndex += matcherState; string = text.substring(0, currentEndIndex); while(string.trim().length() < string.length()){ currentEndIndex++; string = text.substring(0, currentEndIndex); } matcher = Pattern.compile("\u007E+([\\w[\u003C\u003E&&[\\S]]]{1})\u007E\\z").matcher(string); //~r~| <- update the matcher if(!matcher.find()) { currentEndIndex -= 2; string = text.substring(0, currentEndIndex); } else matcher = Pattern.compile("\u007E+([\\w[\u003C\u003E&&[\\S]]]{1})\u007E\\z").matcher(string); //~r~| <- update the matcher matcherState = 3; } } string = text.substring(0, currentEndIndex); while(string.trim().length() < string.length()){ currentEndIndex++; string = text.substring(0, currentEndIndex); } matcher2 = Pattern.compile("\u007E\\z").matcher(string); //~|... if(matcher2.find()) { if(currentEndIndex+3 <= text.length()) currentEndIndex += 3; } } return currentEndIndex; } private int cutTextOut(int endIndex) { int currentEndIndex = endIndex; String string = text.substring(0, currentEndIndex); while(string.trim().length() < string.length()){ currentEndIndex--; string = text.substring(0, currentEndIndex); } //check whether string contains color codes Matcher matcher = Pattern.compile("\u007E+([\\w[\u003C\u003E&&[\\S]]]{1})\u007E").matcher(text); //~r~| if(matcher.find()) { //match ~ int matcherState = 0; matcher = Pattern.compile("\u007E+([\\w[\u003C\u003E&&[\\S]]]{1})\u007E\\z").matcher(string); //~r~|... if(matcher.find()) { matcher = Pattern.compile("\u007E+([\\w[\u003C\u003E&&[\\S]]]{1})\u007E\\z").matcher(string); //~r~|... matcherState = 3; } else { matcher = Pattern.compile("\u007E+([\\w[\u003C\u003E&&[\\S]]]{1})\\z").matcher(string); //~r|... String string2 = text.substring(0, currentEndIndex+1); Matcher matcher2 = Pattern.compile("\u007E+([\\w[\u003C\u003E&&[\\S]]]{1})\u007E\\z").matcher(string2); //~r~|... if(matcher.find() && matcher2.find()) { matcher = Pattern.compile("\u007E+([\\w[\u003C\u003E&&[\\S]]]{1})\\z").matcher(string); //~r|... matcherState = 2; } else { matcher = Pattern.compile("\u007E\\z").matcher(string); //~|... matcherState = 1; } } while(matcher.find()) { //check whether color code is before this color code if(currentEndIndex-matcherState > 0) { currentEndIndex -= matcherState; string = text.substring(0, currentEndIndex); while(string.trim().length() < string.length()){ currentEndIndex--; string = text.substring(0, currentEndIndex); } matcher = Pattern.compile("\u007E+([\\w[\u003C\u003E&&[\\S]]]{1})\u007E\\z").matcher(string); //~r~| <- update the matcher matcherState = 3; } } string = text.substring(0, currentEndIndex); while(string.trim().length() < string.length()){ currentEndIndex--; string = text.substring(0, currentEndIndex); } } return currentEndIndex; } private int getTextLength() { int length = text.replace(" ", "").length(); Matcher matcher = Pattern.compile("\u007E+([\\w[\u003C\u003E&&[\\S]]]{1})\u007E").matcher(text); //~r~ while(matcher.find()) { length -= 3; } return length; } }
Код:
/** * */ package me.alf21.util.chat; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import net.gtaun.shoebill.object.Destroyable; import net.gtaun.shoebill.object.Player; import net.gtaun.shoebill.object.Timer; /** * @author Alf21 */ public class Chat implements Destroyable { private Timer timer; public static final int updateDelay = 50; public static final int displayTime = 5000; public static final int slideTime = 500; private ArrayList<ChatMessage> chatMessages; private ChatMessage currentChatMessage; private Map<Player, String> queue; public Chat() { reset(); initializeTimer(); } //TODO Chat right bottom Corner, with new Infos sliding down if new message received // 5 Slots, 6 available Textdraws public void sendMessage(Player player, String text) { if(chatMessages != null && chatMessages.size() > 5) { //slide getSlot > 5 out } queue.put(player, text); if(!timer.isRunning()) timer.start(); } private void reset() { if(chatMessages != null && !chatMessages.isEmpty()) { chatMessages.stream().forEach((chatMessage) -> { chatMessage.hide(); chatMessage.destroy(); }); } chatMessages = new ArrayList<ChatMessage>(); queue = new HashMap<Player, String>(); currentChatMessage = null; } private void initializeTimer() { timer = Timer.create(updateDelay, (factualInterval) -> { Long systemTime = System.currentTimeMillis(); ArrayList<ChatMessage> removeMessages = new ArrayList<ChatMessage>(); //TODO Solution with Iterator if(chatMessages != null && !chatMessages.isEmpty()) { chatMessages.stream().forEach((chatMessage) -> { if(systemTime-chatMessage.getTime() >= slideTime) { if(currentChatMessage != null) { currentChatMessage = null; } } if(systemTime-chatMessage.getTime() >= displayTime+2*slideTime) { removeMessages.add(chatMessage); } else if(systemTime-chatMessage.getTime() >= displayTime+slideTime) { if(!chatMessage.isSliding()) { chatMessage.slideOut(); } } }); removeMessages.stream().forEach((removeMessage) -> { removeChatMessage(removeMessage); }); removeMessages.clear(); } if(currentChatMessage == null && !queue.isEmpty()) { Map.Entry<Player,String> entry = queue.entrySet().iterator().next(); Player player = entry.getKey(); currentChatMessage = new ChatMessage(player, entry.getValue(), 0); queue.remove(player); chatMessages.add(currentChatMessage); } if(currentChatMessage != null) { if(chatMessages.size() > 1) { chatMessages.stream().forEach((chatMessage) -> { if(chatMessage != currentChatMessage) chatMessage.moveUp(); }); } if(!currentChatMessage.isSliding()) { currentChatMessage.slideIn(); } } if(chatMessages != null && chatMessages.isEmpty()) { timer.stop(); reset(); } }); } private void removeChatMessage(ChatMessage chatMessage) { if(chatMessages.contains(chatMessage)) { chatMessages.remove(chatMessage); } chatMessage.destroy(); } /* (non-Javadoc) * @see net.gtaun.shoebill.object.Destroyable#destroy() */ @Override public void destroy() { if(timer != null) { if(timer.isRunning()) timer.stop(); timer.destroy(); timer = null; } if(currentChatMessage != null) { currentChatMessage.destroy(); currentChatMessage = null; } if(chatMessages != null) { chatMessages.stream().forEach((chatMessage) -> chatMessage.destroy()); chatMessages = null; } if(queue != null) { queue = null; } } /* (non-Javadoc) * @see net.gtaun.shoebill.object.Destroyable#isDestroyed() */ @Override public boolean isDestroyed() { if(timer != null || currentChatMessage != null || chatMessages != null || queue != null) return false; return true; } //TODO: add background box and increase if new message and resize on message destroy }
Initialize the chat in a Plugin in onEnable() or in Gamemode in onInit()! You need to save the reference (Chat chat = new Chat()). So on, uninitialize the chat in onDisable() with chat.destroy();
Example use:
A Command:
Код:
@Command @CommandHelp("/chatme") public boolean chatme(Player player, String msg) { EventSystem.getInstance().getChat().sendMessage(player, msg); return true; }
Please leave a command, thanks
