summaryrefslogtreecommitdiff
path: root/src/main/java/net/nemez/chatapi/ChatAPI.java
blob: 0e8b8bb7b68c2948a7db334b7ab6e1c0650418e8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package net.nemez.chatapi;

import net.md_5.bungee.api.ChatMessageType;
import net.md_5.bungee.api.chat.TextComponent;
import net.nemez.chatapi.click.CallbackCommand;
import net.nemez.chatapi.click.Message;
import net.nemez.chatapi.click.PlayerQuitListener;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandMap;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;

import java.lang.reflect.Field;
import java.util.Random;

public class ChatAPI {

	/* message coloring permission */
	public static final String PERMISSION_CHAT_COLOR         = "chat.color";
	/* message formatting permission */
	public static final String PERMISSION_CHAT_FORMAT        = "chat.format";
	/* message magic formatting permission */
	public static final String PERMISSION_CHAT_MAGIC         = "chat.magic";
	/* permission to send messages in chat */
	public static final String PERMISSION_CHAT_USE           = "chat.use";
	/* message to send when the internal command is not ran correctly (ran by user) */
	public static final String MESSAGE_HELP_CLICK_CALLBACK   = "&cThis is an internal command for ChatAPI and should not be ran by players manually.";
	/* message to send when the internal command is not ran by a player */
	public static final String MESSAGE_PLAYER_CLICK_CALLBACK = "&cThis command can only be run by a player";
	/* the actual command name for use in click callbacks */
	private static      String internalCommandName;

	/** Initializes ChatAPI and registers the required commands for clickable chat to function. */
	public static void initialize(JavaPlugin plugin) {
		if (internalCommandName != null) {
			return;
		}
		Random rand = new Random(System.currentTimeMillis());
		internalCommandName = "chatapi-exec-" + Integer.toHexString(rand.nextInt(0xEFFF) + 0x1000);
		try {
			final Field cmdMap = Bukkit.getServer().getClass().getDeclaredField("commandMap");
			cmdMap.setAccessible(true);
			CommandMap map = (CommandMap) cmdMap.get(Bukkit.getServer());
			map.register("net/nemez/chatapi", new CallbackCommand(internalCommandName));
		} catch (Exception e) {
			plugin.getLogger().severe("Failed to register internal command '" + internalCommandName + "'");
			e.printStackTrace();
		}
		// For some reason the "chatapi:..." cmd is no longer registered. Disabling this until further investigation and fixing.
		// internalCommandName = "chatapi:" + internalCommandName;
		plugin.getServer().getPluginManager().registerEvents(new PlayerQuitListener(), plugin);
		plugin.getLogger().info("ChatAPI initialized");
	}

	/**
	 * Sends a colorified message to the command sender.
	 *
	 * @param sender  the command sender to whom to send the message.
	 * @param message the message to send.
	 */
	public static void send(CommandSender sender, String message) {
		if (sender == null) {
			return;
		}
		sender.sendMessage(colorify(null, message));
	}

	/**
	 * Colorifies a message using &format codes. Respects permissions.
	 *
	 * @param sender  the command sender whose permissions to use. null if permissions are to be ignored.
	 * @param message the message to color
	 *
	 * @return colored message
	 */
	public static String colorify(CommandSender sender, String message) {
		if (sender == null || sender.hasPermission(PERMISSION_CHAT_COLOR)) {
			message = message.replaceAll("&([0-9a-fA-FrR])", "§$1");
		}
		if (sender == null || sender.hasPermission(PERMISSION_CHAT_FORMAT)) {
			message = message.replaceAll("&([l-oL-OrR])", "§$1");
		}
		if (sender == null || sender.hasPermission(PERMISSION_CHAT_MAGIC)) {
			message = message.replaceAll("&([kKrR])", "§$1");
		}
		message = message.replace("&§", "&");
		return message;
	}

	/**
	 * Sends a colorified action bar message to the command sender.
	 *
	 * @param sender  the command sender to whom to send the action bar message.
	 * @param message the message to send.
	 */
	public static void sendActionBar(CommandSender sender, String message) {
		if (sender instanceof Player) {
			((Player) sender).spigot().sendMessage(ChatMessageType.ACTION_BAR, new TextComponent(colorify(null, message)));
		}

	}

	/**
	 * Checks if a command sender has the permission node required to send chat messages.
	 *
	 * @param sender the command sender to check.
	 *
	 * @return true/false if sender can chat or is null.
	 */
	public static boolean canChat(CommandSender sender) {
		if (sender == null) {
			return true;
		} else {
			return sender.hasPermission(PERMISSION_CHAT_USE);
		}
	}

	/**
	 * Creates a new message object that will be sent to the given command sender.
	 *
	 * @param sender the command sender to whom to send the message.
	 *
	 * @return message object.
	 */
	public static Message createMessage(CommandSender sender) {
		return createMessage(sender, null);
	}

	/**
	 * Creates a new message object that will be sent to the given command sender with regards to the second command sender's permissions.
	 *
	 * @param sender           the command sender to whom to send the message.
	 * @param permissionSender the command sender whose permissions to use.
	 *
	 * @return message object
	 */
	public static Message createMessage(CommandSender sender, CommandSender permissionSender) {
		return new Message(sender, permissionSender);
	}

	/**
	 * Gets the name of the internal ChatAPI command used for click callbacks.
	 * This function is used internally and you don't need to worry about it.
	 *
	 * @return callback command name
	 */
	public static String getInternalCallbackCommand() {
		return internalCommandName;
	}
}