├── src
└── main
│ ├── resources
│ ├── config.yml
│ └── plugin.yml
│ └── java
│ └── me
│ └── messageofdeath
│ └── commandnpc
│ ├── Utilities
│ ├── IDHolder.java
│ ├── CooldownManager
│ │ ├── Cooldown.java
│ │ └── CooldownManager.java
│ ├── BungeeCord
│ │ └── BungeeCordUtil.java
│ ├── CitizenBackend
│ │ └── CitizenCommandRegister.java
│ ├── queue
│ │ └── QueueSystem.java
│ ├── Utilities.java
│ └── Metrics
│ │ └── Metrics.java
│ ├── Database
│ ├── ClickType.java
│ ├── PluginSettings
│ │ ├── PluginConfiguration.java
│ │ └── PluginSettings.java
│ ├── LanguageSettings
│ │ ├── LanguageConfiguration.java
│ │ └── LanguageSettings.java
│ ├── CommandDatabase.java
│ └── YamlDatabase.java
│ ├── NPCDataManager
│ ├── NPCDataManager.java
│ ├── NPCData.java
│ └── NPCCommand.java
│ ├── commands
│ ├── ReloadCommand.java
│ └── CitizenCommands.java
│ ├── CommandNPC.java
│ └── Listeners
│ └── NPCListener.java
├── .idea
└── libraries
│ └── Maven__net_milkbowl_vault_VaultAPI_1_6.xml
└── pom.xml
/src/main/resources/config.yml:
--------------------------------------------------------------------------------
1 | ClickType: Both
2 | CoolDown: 20
3 | ExecuteCommandMessage: true
4 | BungeeCord: true
5 |
--------------------------------------------------------------------------------
/src/main/resources/plugin.yml:
--------------------------------------------------------------------------------
1 | name: ${project.name}
2 | version: ${project.version}
3 | main: me.messageofdeath.commandnpc.CommandNPC
4 |
5 | author: messageofdeath
6 |
7 | depend: [Citizens]
8 | softdepend: [Vault, PlaceholderAPI]
9 | commands:
10 | commandnpc:
11 | description: Reload this plugin.
12 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__net_milkbowl_vault_VaultAPI_1_6.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/main/java/me/messageofdeath/commandnpc/Utilities/IDHolder.java:
--------------------------------------------------------------------------------
1 | package me.messageofdeath.commandnpc.Utilities;
2 |
3 | public class IDHolder {
4 |
5 | private int ID;
6 | private Object object;
7 |
8 | public IDHolder(int ID, Object object) {
9 | this.ID = ID;
10 | this.object = object;
11 | }
12 |
13 | public int getID() {
14 | return this.ID;
15 | }
16 |
17 | public Object getObject() {
18 | return this.object;
19 | }
20 |
21 | public void setID(int ID) {
22 | this.ID = ID;
23 | }
24 |
25 | public void setObject(Object object) {
26 | this.object = object;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/me/messageofdeath/commandnpc/Utilities/CooldownManager/Cooldown.java:
--------------------------------------------------------------------------------
1 | package me.messageofdeath.commandnpc.Utilities.CooldownManager;
2 |
3 | import java.util.UUID;
4 |
5 | public class Cooldown {
6 |
7 | private UUID uuid;
8 | private int npcID;
9 | private int commandID;
10 |
11 | public Cooldown(UUID uuid, int npcID, int commandID) {
12 | this.uuid = uuid;
13 | this.npcID = npcID;
14 | this.commandID = commandID;
15 | }
16 |
17 | public UUID getUuid() {
18 | return uuid;
19 | }
20 |
21 | public int getNpcID() {
22 | return npcID;
23 | }
24 |
25 | public int getCommandID() {
26 | return commandID;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/me/messageofdeath/commandnpc/Database/ClickType.java:
--------------------------------------------------------------------------------
1 | package me.messageofdeath.commandnpc.Database;
2 |
3 | public enum ClickType {
4 |
5 | LEFT(new String[] {"punch"}),
6 |
7 | RIGHT(new String[] {"interact"}),
8 |
9 | BOTH(new String[] {"all"});
10 |
11 | private final String[] alternatives;
12 |
13 | ClickType(String[] alternatives) {
14 | this.alternatives = alternatives;
15 | }
16 |
17 | public static boolean hasClickType(String clickType) {
18 | return ClickType.getClickType(clickType) != null;
19 | }
20 |
21 | public static ClickType getClickType(String clickType) {
22 | for(ClickType type : ClickType.values()) {
23 | if(type.name().equalsIgnoreCase(clickType)) {
24 | return type;
25 | }
26 | for(String alternatives : type.alternatives) {
27 | if(clickType.equalsIgnoreCase(alternatives)) {
28 | return type;
29 | }
30 | }
31 | }
32 | return null;
33 | }
34 | }
--------------------------------------------------------------------------------
/src/main/java/me/messageofdeath/commandnpc/NPCDataManager/NPCDataManager.java:
--------------------------------------------------------------------------------
1 | package me.messageofdeath.commandnpc.NPCDataManager;
2 |
3 | import java.util.ArrayList;
4 |
5 | public class NPCDataManager {
6 |
7 | private final ArrayList data;
8 |
9 | public NPCDataManager() {
10 | this.data = new ArrayList<>();
11 | }
12 |
13 | public void addNPCData(NPCData data) {
14 | if(!this.hasNPCData(data.getId())) {
15 | this.data.add(data);
16 | }
17 | }
18 |
19 | public void removeNPCData(int id) {
20 | if(this.hasNPCData(id)) {
21 | this.data.remove(this.getNPCData(id));
22 | }
23 | }
24 |
25 | public boolean hasNPCData(int id) {
26 | return this.getNPCData(id) != null;
27 | }
28 |
29 | public NPCData getNPCData(int id) {
30 | for(NPCData data : this.data) {
31 | if(data.getId() == id) {
32 | return data;
33 | }
34 | }
35 | return null;
36 | }
37 |
38 | public ArrayList getNPCDatas() {
39 | ArrayList data = new ArrayList<>();
40 | data.addAll(this.data);
41 | return data;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/java/me/messageofdeath/commandnpc/Utilities/BungeeCord/BungeeCordUtil.java:
--------------------------------------------------------------------------------
1 | package me.messageofdeath.commandnpc.Utilities.BungeeCord;
2 |
3 | import org.bukkit.entity.Player;
4 | import org.bukkit.plugin.java.JavaPlugin;
5 |
6 | import com.google.common.io.ByteArrayDataOutput;
7 | import com.google.common.io.ByteStreams;
8 |
9 | import me.messageofdeath.commandnpc.CommandNPC;
10 |
11 | public class BungeeCordUtil {
12 |
13 | public static void setupUtil() {
14 | JavaPlugin plugin = CommandNPC.getInstance();
15 | plugin.getServer().getMessenger().registerOutgoingPluginChannel(plugin, "BungeeCord");
16 | }
17 |
18 | public static void disableUtil() {
19 | JavaPlugin plugin = CommandNPC.getInstance();
20 | plugin.getServer().getMessenger().unregisterOutgoingPluginChannel(plugin, "BungeeCord");
21 | }
22 |
23 | public static void sendPlayerToServer(Player player, String serverName) {
24 | ByteArrayDataOutput out = ByteStreams.newDataOutput();
25 | out.writeUTF("Connect");
26 | out.writeUTF(serverName);
27 | player.sendPluginMessage(CommandNPC.getInstance(), "BungeeCord", out.toByteArray());
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/me/messageofdeath/commandnpc/Utilities/CitizenBackend/CitizenCommandRegister.java:
--------------------------------------------------------------------------------
1 | package me.messageofdeath.commandnpc.Utilities.CitizenBackend;
2 |
3 | import java.lang.reflect.Field;
4 |
5 | import me.messageofdeath.commandnpc.CommandNPC;
6 | import net.citizensnpcs.api.CitizensAPI;
7 | import net.citizensnpcs.api.command.CommandManager;
8 |
9 | public class CitizenCommandRegister {
10 |
11 | private final CommandNPC instance;
12 |
13 | public CitizenCommandRegister(CommandNPC instance) {
14 | this.instance = instance;
15 | }
16 |
17 | public void registerCitizenCommand(Class> classx) {
18 | try {
19 | Field field = CitizensAPI.getPlugin().getClass().getDeclaredField("commands");
20 | field.setAccessible(true);
21 | Object obj = field.get(CitizensAPI.getPlugin());
22 | CommandManager manager = (CommandManager) obj;
23 | manager.register(classx);
24 | field.setAccessible(false);
25 | } catch (Exception e) {
26 | this.instance.logError("Citizens", "CitizenCommandRegister", "registerCitizenCommand(Class)", "Couldn't implement commands into citizens! " + "Shutting down!");
27 | this.instance.getServer().getPluginManager().disablePlugin(this.instance);
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/me/messageofdeath/commandnpc/Utilities/CooldownManager/CooldownManager.java:
--------------------------------------------------------------------------------
1 | package me.messageofdeath.commandnpc.Utilities.CooldownManager;
2 |
3 | import java.util.ArrayList;
4 | import java.util.UUID;
5 |
6 | public class CooldownManager {
7 |
8 | private ArrayList cooldowns;
9 |
10 | public CooldownManager() {
11 | cooldowns = new ArrayList<>();
12 | }
13 |
14 | public void addCooldown(Cooldown cooldown) {
15 | if(cooldowns.stream().noneMatch(search -> search.getUuid() == cooldown.getUuid())) {
16 | cooldowns.add(cooldown);
17 | }
18 | }
19 |
20 | public void removeCooldown(UUID uuid) {
21 | cooldowns.stream().filter(search -> search.getUuid() == uuid).findFirst().ifPresent(cooldowns::remove);
22 | }
23 |
24 | public boolean hasCooldown(UUID uuid) {
25 | return cooldowns.stream().anyMatch(search -> search.getUuid() == uuid);
26 | }
27 |
28 | public Cooldown getCooldown(UUID uuid) {
29 | return cooldowns.stream().filter(search -> search.getUuid() == uuid).findFirst().orElse(null);
30 | }
31 |
32 | public Cooldown[] getCooldowns(UUID uuid) {
33 | return cooldowns.stream().filter(search -> search.getUuid() == uuid).toArray(Cooldown[]::new);
34 | }
35 |
36 | public ArrayList getCooldowns() {
37 | return cooldowns;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/me/messageofdeath/commandnpc/Database/PluginSettings/PluginConfiguration.java:
--------------------------------------------------------------------------------
1 | package me.messageofdeath.commandnpc.Database.PluginSettings;
2 |
3 | import me.messageofdeath.commandnpc.CommandNPC;
4 | import me.messageofdeath.commandnpc.Database.YamlDatabase;
5 |
6 | public class PluginConfiguration {
7 |
8 | protected final CommandNPC instance;
9 | private YamlDatabase config;
10 |
11 | public PluginConfiguration(CommandNPC instance) {
12 | this.instance = instance;
13 | }
14 |
15 | public void initConfiguration() {
16 | this.config = new YamlDatabase(this.instance, "config", false);
17 | this.config.onStartUp();
18 | this.config.saveOnSet = false;
19 | boolean changes = false;
20 | for (PluginSettings setting : PluginSettings.values()) {
21 | if (!this.config.contains(setting.getName().replace("_", "."))) {
22 | changes = true;
23 | this.config.set(setting.getName().replace("_", "."), setting.getDefaultSetting());
24 | }
25 | }
26 | if (changes) {
27 | this.config.save();
28 | }
29 | this.config.saveOnSet = true;
30 | }
31 |
32 | public YamlDatabase getConfig() {
33 | return this.config;
34 | }
35 |
36 | public void loadConfiguration() {
37 | for (PluginSettings setting : PluginSettings.values()) {
38 | setting.setSetting(this.config.getString(setting.getName().replace("_", "."), setting.getDefaultSetting()));
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/me/messageofdeath/commandnpc/Database/LanguageSettings/LanguageConfiguration.java:
--------------------------------------------------------------------------------
1 | package me.messageofdeath.commandnpc.Database.LanguageSettings;
2 |
3 | import me.messageofdeath.commandnpc.CommandNPC;
4 | import me.messageofdeath.commandnpc.Database.YamlDatabase;
5 |
6 | public class LanguageConfiguration {
7 |
8 | protected final CommandNPC instance;
9 | private YamlDatabase config;
10 |
11 | public LanguageConfiguration(CommandNPC instance) {
12 | this.instance = instance;
13 | }
14 |
15 | public void initConfiguration() {
16 | this.config = new YamlDatabase(this.instance, "language", false);
17 | this.config.onStartUp();
18 | this.config.saveOnSet = false;
19 | boolean changes = false;
20 | for(LanguageSettings setting : LanguageSettings.values()) {
21 | if (!this.config.contains(setting.getName().replace("_", "."))) {
22 | changes = true;
23 | this.config.set(setting.getName().replace("_", "."), setting.getDefaultSetting());
24 | }
25 | }
26 | if(changes) {
27 | this.config.save();
28 | }
29 | this.config.saveOnSet = true;
30 | }
31 |
32 | public YamlDatabase getConfig() {
33 | return this.config;
34 | }
35 |
36 | public void loadConfiguration() {
37 | for(LanguageSettings setting : LanguageSettings.values()) {
38 | setting.setSetting(this.config.getString(setting.getName().replace("_", "."), setting.getDefaultSetting()));
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/me/messageofdeath/commandnpc/Database/PluginSettings/PluginSettings.java:
--------------------------------------------------------------------------------
1 | package me.messageofdeath.commandnpc.Database.PluginSettings;
2 |
3 | import me.messageofdeath.commandnpc.Utilities.Utilities;
4 |
5 | public enum PluginSettings {
6 |
7 | /**-------------------------------------- General --------------------------------------**/
8 | ClickType("both"),
9 | CoolDown("20"),
10 | ExecuteCommandMessage("false"),
11 | BungeeCord("false"),
12 | CooldownMessage("true");
13 |
14 | private String setting;
15 | private final String defaultSetting;
16 |
17 | PluginSettings(String defaultSetting) {
18 | this.defaultSetting = defaultSetting;
19 | }
20 |
21 | public String getName() {
22 | return toString();
23 | }
24 |
25 | public void setSetting(String setting) {
26 | this.setting = setting;
27 | }
28 |
29 | public void setDefaultSetting() {
30 | this.setting = this.defaultSetting;
31 | }
32 |
33 | public String getSetting() {
34 | return this.setting;
35 | }
36 |
37 | public Integer getInteger() {
38 | if(Utilities.isInteger(this.setting)) {
39 | return Integer.parseInt(this.setting);
40 | }else{
41 | return -1;
42 | }
43 | }
44 |
45 | public Double getDouble() {
46 | if(Utilities.isDouble(this.setting)) {
47 | return Double.parseDouble(this.setting);
48 | }else{
49 | return -1.0;
50 | }
51 | }
52 |
53 | public boolean getBoolean() {
54 | return Boolean.parseBoolean(this.setting);
55 | }
56 |
57 | public String getDefaultSetting() {
58 | return this.defaultSetting;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/me/messageofdeath/commandnpc/commands/ReloadCommand.java:
--------------------------------------------------------------------------------
1 | package me.messageofdeath.commandnpc.commands;
2 |
3 | import net.citizensnpcs.api.util.Messaging;
4 |
5 | import org.bukkit.command.Command;
6 | import org.bukkit.command.CommandExecutor;
7 | import org.bukkit.command.CommandSender;
8 |
9 | import me.messageofdeath.commandnpc.CommandNPC;
10 | import me.messageofdeath.commandnpc.Database.LanguageSettings.LanguageSettings;
11 | import me.messageofdeath.commandnpc.Database.PluginSettings.PluginSettings;
12 | import me.messageofdeath.commandnpc.Utilities.BungeeCord.BungeeCordUtil;
13 |
14 | public class ReloadCommand implements CommandExecutor {
15 |
16 | @Override
17 | public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
18 | if(args.length == 1) {
19 | if (args[0].equalsIgnoreCase("reload")) {
20 | if(sender.hasPermission("commandnpc.admin") || sender.isOp()) {
21 | if(PluginSettings.BungeeCord.getBoolean()) {
22 | BungeeCordUtil.disableUtil();
23 | }
24 | CommandNPC.getInstance().reloadConfigX();
25 | Messaging.send(sender, LanguageSettings.Commands_CmdNPC_Reload.getSetting());
26 | if(PluginSettings.BungeeCord.getBoolean()) {
27 | BungeeCordUtil.setupUtil();
28 | }
29 | return true;
30 | }else{
31 | Messaging.sendError(sender, LanguageSettings.Commands_NoPermission.getSetting());
32 | }
33 | }else{
34 | Messaging.sendError(sender, LanguageSettings.Commands_WrongArgs.getSetting());
35 | }
36 | }else{
37 | Messaging.sendError(sender, LanguageSettings.Commands_WrongArgs.getSetting());
38 | }
39 | return false;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/me/messageofdeath/commandnpc/Utilities/queue/QueueSystem.java:
--------------------------------------------------------------------------------
1 | package me.messageofdeath.commandnpc.Utilities.queue;
2 |
3 | import java.util.LinkedList;
4 |
5 | public class QueueSystem {
6 |
7 | private volatile boolean stop, interrupt;
8 | private final QueueExecutor[] threads;
9 | private final LinkedList queue;
10 |
11 | public QueueSystem(int nThreads) {
12 | queue = new LinkedList<>();
13 | stop = false;
14 | interrupt = false;
15 | threads = new QueueExecutor[nThreads];
16 | for(int i = 0; i < nThreads; i++) {
17 | threads[i] = new QueueExecutor(i);
18 | threads[i].start();
19 | }
20 | }
21 |
22 | public void execute(Runnable r) {
23 | synchronized (queue) {
24 | queue.addLast(r);
25 | queue.notify();
26 | }
27 | }
28 |
29 | public synchronized void stop() {
30 | stop = true;
31 | if(queue.isEmpty()) {
32 | interrupt = true;
33 | for(Thread thread : threads) {
34 | thread.interrupt();
35 | }
36 | }
37 | }
38 |
39 | private class QueueExecutor extends Thread {
40 |
41 | final int id;
42 |
43 | private QueueExecutor(int id) {
44 | this.id = id;
45 | }
46 |
47 | public void run() {
48 | synchronized (queue) {
49 | while(!stop || stop && !queue.isEmpty()) {
50 | if(queue.isEmpty()) {
51 | try {
52 | queue.wait();
53 | } catch (InterruptedException e) {
54 | if (!interrupt) {
55 | e.printStackTrace();
56 | }
57 | continue;
58 | }
59 | }
60 | try {
61 | queue.removeFirst().run();
62 | } catch (RuntimeException e) {
63 | e.printStackTrace();
64 | }
65 | }
66 | }
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/main/java/me/messageofdeath/commandnpc/Database/LanguageSettings/LanguageSettings.java:
--------------------------------------------------------------------------------
1 | package me.messageofdeath.commandnpc.Database.LanguageSettings;
2 |
3 | public enum LanguageSettings {
4 |
5 | /**-------------------------------------- General --------------------------------------**/
6 | General_PluginTag("&8[&2CommandNPC&8] &6"),
7 | General_ErrorTag("&0[&cError&0] &c"),
8 |
9 | /**-------------------------------------- commandnpc NPC --------------------------------------**/
10 | CmdNPC_Cooldown("You cannot do this yet!"),
11 | CmdNPC_NoMoney("You do not have enough money for this!"),
12 | CmdNPC_Executed("Command Executed."),
13 |
14 | /**-------------------------------------- General Commands --------------------------------------**/
15 | Commands_NoPermission("You do not have permission for this!"),
16 | Commands_WrongArgs("Wrong Args. Use /commandnpc reload"),
17 | Commands_MustBeNumeric("The argument '%arg' must be numeric!"),
18 | Commands_AlreadyExists("A %type with that name already exists!"),
19 | Commands_DoesNotExist("A %type with that name doesn't exist!"),
20 | Commands_List_Header("Available %type:"),
21 | Commands_List_Line(" &8 -&a %name"),
22 | Commands_List_InfoHeader("Information for NPC '%id':"),
23 | Commands_List_InfoLineHeader(" &7%name: &6%value"),
24 | Commands_List_InfoLinePrefix(" &8- "),
25 | Commands_List_InfoLine("&2%name: &b%value"),
26 | Commands_SetTo_Header("You have set the following variables:"),
27 | Commands_SetTo_Line(" &8- &6%variable to&8: &b%value"),
28 | Commands_SetTo_Nothing(" &8- &4Nothing's changed..."),
29 |
30 | /**-------------------------------------- commandnpc Commands --------------------------------------**/
31 | Commands_CmdNPC_Reload("You have successfully reloaded the commandnpc configuration file!"),
32 |
33 | /**-------------------------------------- Citizens Commands --------------------------------------**/
34 | Commands_Citizens_Add("You have successfully added the command to the NPC!"),
35 | Commands_Citizens_Reset("You have successfully reset the commands for this NPC!"),
36 | Commands_Citizens_Removed("You have successfully removed the command!"),
37 | Commands_Citizens_NumBetween("You must enter a number between %num1 and %num2!"),
38 | Commands_Citizens_ValueFlagT("For value flag 't', you must use 'left', 'right', or 'both'!"),
39 | Commands_Citizens_NoCmdInput("You didn't input a command!"),
40 | Commands_Citizens_NoCommands("There are no set commands at the moment for this NPC!");
41 |
42 | private String setting;
43 | private final String defaultSetting;
44 |
45 | LanguageSettings(String defaultSetting) {
46 | this.defaultSetting = defaultSetting;
47 | }
48 |
49 | public String getName() {
50 | return toString();
51 | }
52 |
53 | public void setSetting(String setting) {
54 | this.setting = setting;
55 | }
56 |
57 | public void setDefaultSetting() {
58 | this.setting = this.defaultSetting;
59 | }
60 |
61 | public String getSetting() {
62 | return this.setting;
63 | }
64 |
65 | public String getDefaultSetting() {
66 | return this.defaultSetting;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/main/java/me/messageofdeath/commandnpc/NPCDataManager/NPCData.java:
--------------------------------------------------------------------------------
1 | package me.messageofdeath.commandnpc.NPCDataManager;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Comparator;
5 |
6 | public class NPCData {
7 |
8 | private final int npcID;
9 | private ArrayList commands;
10 |
11 | public NPCData(int npcID) {
12 | this.npcID = npcID;
13 | this.commands = new ArrayList<>();
14 | }
15 |
16 | public NPCData(int npcID, NPCCommand command) {
17 | this(npcID);
18 | this.addCommand(command);
19 | }
20 |
21 | public NPCData(int npcID, ArrayList commands) {
22 | this(npcID);
23 | for(NPCCommand cmd : commands) {
24 | this.addCommand(cmd);
25 | }
26 | }
27 |
28 | public int getId() {
29 | return this.npcID;
30 | }
31 |
32 | public boolean isRandom() {
33 | return commands.stream().anyMatch(NPCCommand::isRandom);
34 | }
35 |
36 | public void addCommand(NPCCommand command) {
37 | this.commands.add(command);
38 | checkPositions();
39 | }
40 |
41 | public void removeCommand(int id) {
42 | commands.stream().filter(cmd -> cmd.getID() == id).findFirst().ifPresent(commands::remove);
43 | checkPositions();
44 | }
45 |
46 | public boolean hasCommand(int id) {
47 | return commands.stream().anyMatch(cmd -> cmd.getID() == id);
48 | }
49 |
50 | public NPCCommand getCommand(int id) {
51 | return commands.stream().filter(cmd -> cmd.getID() == id).findFirst().orElse(null);
52 | }
53 |
54 | public ArrayList getCommands() {
55 | return commands;
56 | }
57 |
58 | private void checkPositions() {
59 | ArrayList commands = this.commands;
60 | commands.sort(comparePosition());
61 | if (!commands.isEmpty()) {
62 | int lastPosition = 0;
63 | int difference;
64 | NPCCommand commandx;
65 | for (int i = 0; i < commands.size(); i++) {
66 | commandx = commands.get(i);
67 | if (lastPosition != commandx.getID()) {
68 | difference = commandx.getID() - lastPosition;
69 | if (difference > 1) {
70 | for (int x = i; x < commands.size(); x++) {
71 | commands.get(x).setID(commands.get(x).getID() - difference);
72 | }
73 | }
74 | difference = commandx.getID() - lastPosition;
75 | if (difference == 0) {
76 | for (int x = i; x < commands.size(); x++) {
77 | commands.get(x).setID(commands.get(x).getID() + 1);
78 | }
79 | }
80 | lastPosition = commandx.getID();
81 | }else if(lastPosition == commandx.getID()){
82 | commandx.setID(commandx.getID() + 1);
83 | lastPosition = commandx.getID();
84 | }
85 | }
86 | commands.sort(comparePosition());
87 | this.commands = commands;
88 | }
89 | }
90 |
91 | private static Comparator comparePosition() {
92 | return (cmd1, cmd2) -> {
93 | if (cmd1.getID() > cmd2.getID()) {
94 | return 1;
95 | }
96 | if (cmd1.getID() < cmd2.getID()) {
97 | return -1;
98 | }
99 | return 0;
100 | };
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/src/main/java/me/messageofdeath/commandnpc/NPCDataManager/NPCCommand.java:
--------------------------------------------------------------------------------
1 | package me.messageofdeath.commandnpc.NPCDataManager;
2 |
3 | import me.messageofdeath.commandnpc.Database.ClickType;
4 |
5 | public class NPCCommand {
6 |
7 | private int id;
8 | private int delay;
9 | private int cooldown;
10 | private String command;
11 | private String permission;
12 | private String cooldownMessage;
13 | private ClickType clickType;
14 | private boolean inConsole;
15 | private boolean asOp;
16 | private boolean isRandom;
17 | private boolean ignorePermMsg;
18 | private boolean ignoreMoneyMsg;
19 | private double cost;
20 |
21 | public NPCCommand(String command, String permission, String cooldownMessage, ClickType clickType, boolean inConsole, boolean asOp, boolean isRandom, boolean ignorePermMsg,
22 | boolean ignoreMoneyMsg, double cost, int delay, int cooldown) {
23 | this(1000, command, permission, cooldownMessage, clickType, inConsole, asOp, isRandom, ignorePermMsg, ignoreMoneyMsg, cost, delay, cooldown);
24 | }
25 |
26 | public NPCCommand(int id, String command, String permission, String cooldownMessage, ClickType clickType, boolean inConsole, boolean asOp, boolean isRandom, boolean ignorePermMsg,
27 | boolean ignoreMoneyMsg, double cost, int delay, int cooldown) {
28 | this.id = id;
29 | this.command = command;
30 | this.permission = permission;
31 | this.cooldownMessage = cooldownMessage;
32 | this.clickType = clickType;
33 | this.inConsole = inConsole;
34 | this.asOp = asOp;
35 | this.isRandom = isRandom;
36 | this.ignorePermMsg = ignorePermMsg;
37 | this.ignoreMoneyMsg = ignoreMoneyMsg;
38 | this.cost = cost;
39 | this.delay = delay;
40 | this.cooldown = cooldown;
41 | }
42 |
43 | public int getID() {
44 | return this.id;
45 | }
46 |
47 | public String getCommand() {
48 | return this.command;
49 | }
50 |
51 | public String getPermission() {
52 | return this.permission;
53 | }
54 |
55 | public String getCooldownMessage() {
56 | return this.cooldownMessage;
57 | }
58 |
59 | public ClickType getClickType() {
60 | return this.clickType;
61 | }
62 |
63 | public boolean inConsole() {
64 | return this.inConsole;
65 | }
66 |
67 | public boolean asOp() {
68 | return this.asOp;
69 | }
70 |
71 | public boolean isRandom() {
72 | return this.isRandom;
73 | }
74 |
75 | public boolean isIgnorePermMsg() {
76 | return this.ignorePermMsg;
77 | }
78 |
79 | public boolean isIgnoreMoneyMsg() {
80 | return this.ignoreMoneyMsg;
81 | }
82 |
83 | public double getCost() {
84 | return this.cost;
85 | }
86 |
87 | public int getDelay() {
88 | return this.delay;
89 | }
90 |
91 | public int getCooldown() {
92 | return this.cooldown;
93 | }
94 |
95 | public void setID(int id) {
96 | this.id = id;
97 | }
98 |
99 | public void setCommand(String command) {
100 | this.command = command;
101 | }
102 |
103 | public void setPermission(String permission) {
104 | this.permission = permission;
105 | }
106 |
107 | public void setCooldownMessage(String cooldownMessage) {
108 | this.cooldownMessage = cooldownMessage;
109 | }
110 |
111 | public void setClickType(ClickType clickType) {
112 | this.clickType = clickType;
113 | }
114 |
115 | public void setInConsole(boolean inConsole) {
116 | this.inConsole = inConsole;
117 | }
118 |
119 | public void setAsOP(boolean asOp) {
120 | this.asOp = asOp;
121 | }
122 |
123 | public void setIsRandom(boolean isRandom) {
124 | this.isRandom = isRandom;
125 | }
126 |
127 | public void setIgnorePermMsg(boolean ignorePermMsg) {
128 | this.ignorePermMsg = ignorePermMsg;
129 | }
130 |
131 | public void setIgnoreMoneyMsg(boolean ignoreMoneyMsg) {
132 | this.ignoreMoneyMsg = ignoreMoneyMsg;
133 | }
134 |
135 | public void setCost(double cost) {
136 | this.cost = cost;
137 | }
138 |
139 | public void setDelay(int delay) {
140 | this.delay = delay;
141 | }
142 |
143 | public void setCooldown(int cooldown) {
144 | this.cooldown = cooldown;
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/src/main/java/me/messageofdeath/commandnpc/Utilities/Utilities.java:
--------------------------------------------------------------------------------
1 | package me.messageofdeath.commandnpc.Utilities;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Comparator;
5 |
6 | public class Utilities {
7 |
8 | private static final String alpha = "^[a-zA-Z]*$";
9 | private static final String alphaNumeric = "^[a-zA-Z0-9]*$";
10 | private static final String intRegex = "\\d+";
11 | private static final String floatRegex = "[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)";
12 | private static final String Digits = "(\\p{Digit}+)";
13 | private static final String HexDigits = "(\\p{XDigit}+)";
14 | private static final String Exp = "[eE][+-]?"+Digits;
15 | private static final String doubleRegex = ("[\\x00-\\x20]*"+"[+-]?("+"NaN|"+"Infinity|"+"((("+Digits+"(\\.)?("+Digits+"?)("+Exp+")?)|"+
16 | "(\\.("+Digits+")("+Exp+")?)|"+"(("+"(0[xX]"+HexDigits+"(\\.)?)|"+"(0[xX]"+HexDigits+"?(\\.)"+HexDigits+")"+")[pP][+-]?"+Digits+"))"+
17 | "[fFdD]?))"+"[\\x00-\\x20]*");
18 |
19 | public static boolean isAlpha(String total) {
20 | return total.matches(alpha);
21 | }
22 |
23 | public static boolean isAlphanumeric(String total) {
24 | return total.matches(alphaNumeric);
25 | }
26 |
27 | public static boolean isNumeric(String total) {
28 | return isInteger(total) || isFloat(total) || isDouble(total);
29 | }
30 |
31 | public static boolean isDouble(String total) {
32 | return total.matches(doubleRegex);
33 | }
34 |
35 | public static boolean isInteger(String total) {
36 | return total.matches(intRegex);
37 | }
38 |
39 | public static boolean isFloat(String total) {
40 | return total.matches(floatRegex);
41 | }
42 |
43 | public static String getOrdinal(int n) {
44 | char[] args = (n + "").toCharArray();
45 | char last = args[args.length - 1];
46 | if(last == '1') {
47 | return n + "st";
48 | }else if(last == '2') {
49 | return n + "nd";
50 | }else if(last == '3') {
51 | return n + "rd";
52 | }else{
53 | return n + "th";
54 | }
55 | }
56 |
57 | public static String getTime(int time) {
58 | int days = time >= 60*60*24 ? time / (60*60*24) : 0;
59 | time -= days*60*60*24;
60 | int hours = time >= 60*60 ? time / (60*60) : 0;
61 | time -= hours*60*60;
62 | int minutes = time >= 60 ? time / 60 : 0;
63 | time -= minutes*60;
64 | int seconds = time;
65 | return (days != 0 ? days + (days == 1 ? " day" : " days") : "") + (hours != 0 ? hours + (hours == 1 ? " hour" : " hours") : "") +
66 | (minutes != 0 ? minutes + (minutes == 1 ? " minute" : " minutes") : "") + (seconds != 0 ? seconds + (seconds == 1 ? " second" : " seconds") : "");
67 | }
68 |
69 | public static ArrayList sortIDs(ArrayList holders) {
70 | if (!holders.isEmpty()) {
71 | holders.sort(Utilities.compareIDs());
72 | int lastPosition = 0;
73 | int difference;
74 | IDHolder holder;
75 | for (int i = 0; i < holders.size(); i++) {
76 | holder = holders.get(i);
77 | if (lastPosition != holder.getID()) {
78 | difference = holder.getID() - lastPosition;
79 | if (difference > 1) {
80 | for (int x = i; x < holders.size(); x++) {
81 | holders.get(x).setID(holders.get(x).getID() - difference);
82 | }
83 | }
84 | difference = holder.getID() - lastPosition;
85 | if (difference == 0) {
86 | for (int x = i; x < holders.size(); x++) {
87 | holders.get(x).setID(holders.get(x).getID() + 1);
88 | }
89 | }
90 | lastPosition = holder.getID();
91 | }else if(lastPosition == holder.getID()){
92 | holder.setID(holder.getID() + 1);
93 | lastPosition = holder.getID();
94 | }
95 | }
96 | holders.sort(Utilities.compareIDs());
97 | }
98 | return holders;
99 | }
100 |
101 | public static ArrayList setID(int oldID, int newID, ArrayList holders) {
102 | boolean has = false;
103 | for(IDHolder holder : holders) {
104 | if(holder.getID() == oldID) {
105 | has = true;
106 | holder.setID(newID);
107 | continue;
108 | }
109 | if(has) {
110 | holder.setID(holder.getID() + 1);
111 | }
112 | }
113 | return Utilities.sortIDs(holders);
114 | }
115 |
116 | public static int getNextID(ArrayList holders) {
117 | ArrayList ids = new ArrayList<>();
118 | for (IDHolder holder : holders) {
119 | ids.add(holder.getID());
120 | }
121 | for(int i = 1; i < ids.size(); i++) {
122 | if (!ids.contains(i)) {
123 | return i;
124 | }
125 | }
126 | return 0;
127 | }
128 |
129 | private static Comparator compareIDs() {
130 | return (holder1, holder2) -> {
131 | if (holder1.getID() > holder2.getID()) {
132 | return 1;
133 | }
134 | if (holder1.getID() < holder2.getID()) {
135 | return -1;
136 | }
137 | return 0;
138 | };
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/src/main/java/me/messageofdeath/commandnpc/Database/CommandDatabase.java:
--------------------------------------------------------------------------------
1 | package me.messageofdeath.commandnpc.Database;
2 |
3 | import java.util.ArrayList;
4 |
5 | import me.messageofdeath.commandnpc.CommandNPC;
6 | import me.messageofdeath.commandnpc.Database.PluginSettings.PluginSettings;
7 | import me.messageofdeath.commandnpc.NPCDataManager.NPCCommand;
8 | import me.messageofdeath.commandnpc.NPCDataManager.NPCData;
9 |
10 | public class CommandDatabase {
11 |
12 | private final CommandNPC instance;
13 | private YamlDatabase database;
14 |
15 | public CommandDatabase(CommandNPC instance) {
16 | this.instance = instance;
17 | }
18 |
19 | public void initDatabase() {
20 | database = new YamlDatabase(instance, "commands");
21 | database.onStartUp();
22 | }
23 |
24 | public void loadDatabase() {
25 | CommandNPC.getQueueSystem().execute(() -> {
26 | for (String idx : database.getSection("NPCS", new ArrayList<>())) {
27 | NPCData data = new NPCData(Integer.parseInt(idx));
28 | for (String commands : database.getStringArray("NPCS." + idx + ".Commands", new ArrayList<>())) {
29 | String[] args = commands.split("~~~");
30 | ClickType clickType;
31 | if (args.length == 13) {//Version 1.9.1
32 | clickType = this.getClickType(args);
33 | data.addCommand(new NPCCommand(Integer.parseInt(args[0]), args[1], args[2], args[4], clickType, Boolean.parseBoolean(args[5]),
34 | Boolean.parseBoolean(args[6]), Boolean.parseBoolean(args[7]), Boolean.parseBoolean(args[11]), Boolean.parseBoolean(args[12]),
35 | Double.parseDouble(args[8]), Integer.parseInt(args[9]), Integer.parseInt(args[10])));
36 | continue;
37 | }else if (args.length == 11) {//Version 1.9.0
38 | clickType = this.getClickType(args);
39 | data.addCommand(new NPCCommand(Integer.parseInt(args[0]), args[1], args[2], args[4], clickType, Boolean.parseBoolean(args[5]),
40 | Boolean.parseBoolean(args[6]), Boolean.parseBoolean(args[7]), false, false, Double.parseDouble(args[8]), Integer.parseInt(args[9]), Integer.parseInt(args[10])));
41 | continue;
42 | }else if (args.length == 9) {//Version 1.8.8-1.8.9
43 | clickType = this.getClickType(args);
44 | data.addCommand(new NPCCommand(Integer.parseInt(args[0]), args[1], args[2], "", clickType, Boolean.parseBoolean(args[4]),
45 | Boolean.parseBoolean(args[5]), Boolean.parseBoolean(args[6]), false, false, Double.parseDouble(args[7]), Integer.parseInt(args[8]), 0));
46 | continue;
47 | }else if (args.length == 8) {//Version 1.8.7
48 | clickType = this.getClickType(args);
49 | data.addCommand(new NPCCommand(Integer.parseInt(args[0]), args[1], args[2], "", clickType, Boolean.parseBoolean(args[4]),
50 | Boolean.parseBoolean(args[5]), false, false, false, Double.parseDouble(args[6]), Integer.parseInt(args[7]), 0));
51 | continue;
52 | }
53 | args = commands.split("~");
54 | if (args.length == 7) {// Version 1.8.6
55 | clickType = this.getClickType(args);
56 | data.addCommand(new NPCCommand(Integer.parseInt(args[0]), args[1], args[2], "", clickType, Boolean.parseBoolean(args[4]),
57 | Boolean.parseBoolean(args[5]), false, false, false, Double.parseDouble(args[6]), 0, 0));
58 | }else if (args.length == 5) {//Version 1.8.5
59 | String cmd = args[2];
60 | if (cmd.toLowerCase().contains("-c")) {
61 | cmd = cmd.replace("-c", "");
62 | }
63 | data.addCommand(new NPCCommand(args[0], args[1], "", ClickType.getClickType(PluginSettings.ClickType.getSetting()), Boolean.parseBoolean(cmd),
64 | Boolean.parseBoolean(args[3]), false, false, false, Double.parseDouble(args[4]), 0, 0));
65 | }else{
66 | instance.logError("Loading Command", "CommandDatabase", "loadDatabase()", "Incompatible command! ***Not detrimental*** ID: "+idx+" | Line: " + commands);
67 | }
68 | }
69 | CommandNPC.getCommandManager().addNPCData(data);
70 | }
71 | instance.log("Loading commands complete!", true);
72 | });
73 | }
74 |
75 | public void deleteNPC(int id) {
76 | CommandNPC.getQueueSystem().execute(() -> database.set("NPCS." + id, null));
77 | }
78 |
79 | public void saveDatabase() {
80 | CommandNPC.getQueueSystem().execute(() -> {
81 | for (NPCData data : CommandNPC.getCommandManager().getNPCDatas()) {
82 | ArrayList commands = new ArrayList<>();
83 | for (NPCCommand command : data.getCommands()) {
84 | commands.add(command.getID() + "~~~" + command.getCommand() + "~~~" + command.getPermission() + "~~~" + command.getClickType().name() + "~~~" +
85 | command.getCooldownMessage() + "~~~" + command.inConsole() + "~~~" + command.asOp() + "~~~" + command.isRandom() + "~~~" +
86 | command.getCost() + "~~~" + command.getDelay() + "~~~" + command.getCooldown() + "~~~" + command.isIgnorePermMsg() + "~~~" + command.isIgnoreMoneyMsg());
87 | }
88 | database.set("NPCS." + data.getId() + ".Commands", commands);
89 | }
90 | });
91 | }
92 |
93 | private ClickType getClickType(String[] args) {
94 | return args.length > 3 && ClickType.hasClickType(args[3]) ? ClickType.getClickType(args[3]) : ClickType.getClickType(PluginSettings.ClickType.getSetting());
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | me.messageofdeath
8 | commandnpc
9 | CommandNPC
10 | 1.9.1
11 | jar
12 |
13 |
14 | UTF-8
15 | 1.8
16 | 1.12-R0.1-SNAPSHOT
17 | 2.0.22-SNAPSHOT
18 | 1.6
19 | 2.0.8
20 |
21 |
22 |
23 |
24 | spigot-repo
25 | https://hub.spigotmc.org/nexus/content/repositories/snapshots/
26 |
27 |
28 | vault-repo
29 | http://nexus.hc.to/content/repositories/pub_releases
30 |
31 |
32 | citizens-repo
33 | http://repo.citizensnpcs.co
34 |
35 |
36 | placeholderapi
37 | http://repo.extendedclip.com/content/repositories/placeholderapi/
38 |
39 |
40 |
41 |
42 |
43 | org.spigotmc
44 | spigot-api
45 | ${bukkit.version}
46 | provided
47 |
48 |
49 | org.bukkit
50 | bukkit
51 | ${bukkit.version}
52 | provided
53 |
54 |
55 | net.milkbowl.vault
56 | VaultAPI
57 | ${vault.version}
58 | provided
59 |
60 |
61 | net.citizensnpcs
62 | citizensapi
63 | ${citizensapi.version}
64 | provided
65 |
66 |
67 | me.clip
68 | placeholderapi
69 | ${placeholderapi.version}
70 | provided
71 |
72 |
73 |
74 |
75 | clean install
76 | src/main/java
77 | ${project.name}-${project.version}
78 |
79 |
80 |
81 | .
82 | ${basedir}/src/main/resources
83 | true
84 |
85 | **/*
86 |
87 |
88 |
89 |
90 |
91 |
92 | org.apache.maven.plugins
93 | maven-compiler-plugin
94 | 3.6.1
95 |
96 | ${jdk.version}
97 | ${jdk.version}
98 | true
99 |
100 |
101 |
102 | org.apache.maven.plugins
103 | maven-jar-plugin
104 | 3.0.2
105 |
106 |
107 | false
108 |
109 | ${project.name}
110 | ${project.version}
111 |
112 |
113 |
114 |
115 |
116 |
117 | org.apache.maven.plugins
118 | maven-shade-plugin
119 | 3.0.0
120 |
121 |
122 | package
123 |
124 | shade
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
--------------------------------------------------------------------------------
/src/main/java/me/messageofdeath/commandnpc/CommandNPC.java:
--------------------------------------------------------------------------------
1 | package me.messageofdeath.commandnpc;
2 |
3 | import java.util.ArrayList;
4 |
5 | import me.messageofdeath.commandnpc.Database.CommandDatabase;
6 | import me.messageofdeath.commandnpc.Database.LanguageSettings.LanguageConfiguration;
7 | import me.messageofdeath.commandnpc.Database.LanguageSettings.LanguageSettings;
8 | import me.messageofdeath.commandnpc.Database.PluginSettings.PluginConfiguration;
9 | import me.messageofdeath.commandnpc.Database.PluginSettings.PluginSettings;
10 | import me.messageofdeath.commandnpc.Listeners.NPCListener;
11 | import me.messageofdeath.commandnpc.NPCDataManager.NPCDataManager;
12 | import me.messageofdeath.commandnpc.Utilities.BungeeCord.BungeeCordUtil;
13 | import me.messageofdeath.commandnpc.Utilities.CitizenBackend.CitizenCommandRegister;
14 | import me.messageofdeath.commandnpc.Utilities.Metrics.Metrics;
15 | import me.messageofdeath.commandnpc.Utilities.queue.QueueSystem;
16 | import me.messageofdeath.commandnpc.commands.CitizenCommands;
17 | import me.messageofdeath.commandnpc.commands.ReloadCommand;
18 | import net.milkbowl.vault.economy.Economy;
19 |
20 | import org.bukkit.ChatColor;
21 | import org.bukkit.plugin.RegisteredServiceProvider;
22 | import org.bukkit.plugin.java.JavaPlugin;
23 |
24 | public class CommandNPC extends JavaPlugin {
25 |
26 | public static String prefix;
27 |
28 | private static CommandDatabase database;
29 |
30 | private static JavaPlugin instance;
31 |
32 | private static PluginConfiguration config;
33 |
34 | private static NPCDataManager manager;
35 |
36 | private static Economy econ = null;
37 |
38 | private static QueueSystem queueSystem;
39 |
40 | private static boolean placeHolderAPI = false;
41 |
42 | private static boolean econAvailable = false;
43 |
44 | @Override
45 | public void onEnable() {
46 | CommandNPC.queueSystem = new QueueSystem(1);
47 | new Metrics(this);
48 | LanguageConfiguration langConfig = new LanguageConfiguration(this);
49 | langConfig.initConfiguration();
50 | langConfig.loadConfiguration();
51 | this.reloadConfigX();
52 | CommandNPC.prefix = CommandNPC.getColorized(LanguageSettings.General_PluginTag.getSetting());
53 | /** --------------Checking for Dependencies-------------- **/
54 | if (!getServer().getPluginManager().isPluginEnabled("Citizens")) {
55 | this.logError("Required Dependencies", "commandnpc", "onEnable()", "Citizens 2 not found! commandnpc will now shut down.");
56 | super.getServer().getPluginManager().disablePlugin(this);
57 | return;
58 | }
59 | if (getServer().getPluginManager().isPluginEnabled("PlaceholderAPI")) {
60 | placeHolderAPI = true;
61 | }
62 | this.setupEconomy();
63 |
64 | /** --------------Initiation of Databases, Managers, and Parsers-------------- **/
65 | CommandNPC.instance = this;
66 | CommandNPC.manager = new NPCDataManager();
67 | CitizenCommandRegister commandRegister = new CitizenCommandRegister(this);
68 | /** --------------Initiation of the Listener-------------- **/
69 | super.getServer().getPluginManager().registerEvents(new NPCListener(), this);
70 | /** --------------Initiation and Loading of Databases-------------- **/
71 | this.log("Initiating Database", true);
72 | CommandNPC.database = new CommandDatabase(this);
73 | CommandNPC.database.initDatabase();
74 | CommandNPC.database.loadDatabase();
75 | /** --------------Registering Commands-------------- **/
76 | this.log("Injecting command info into Citizens.", true);
77 | commandRegister.registerCitizenCommand(CitizenCommands.class);
78 | super.getCommand("commandnpc").setExecutor(new ReloadCommand());
79 | if(PluginSettings.BungeeCord.getBoolean()) {
80 | this.log("Setting up BungeeCord", true);
81 | BungeeCordUtil.setupUtil();
82 | }
83 | this.log("CommandNPC successfully loaded!", true);
84 | }
85 |
86 | @Override
87 | public void onDisable() {
88 | if (database != null) {
89 | database.saveDatabase();
90 | }
91 | queueSystem.stop();
92 | if(PluginSettings.BungeeCord.getBoolean()) {
93 | this.log("Disabling BungeeCord Support", true);
94 | BungeeCordUtil.disableUtil();
95 | }
96 | }
97 |
98 | public static Economy getEcon() {
99 | return econ;
100 | }
101 |
102 | private static String getColorized(String input) {
103 | return ChatColor.translateAlternateColorCodes('&', input);
104 | }
105 |
106 | public void log(String log, boolean prefix) {
107 | getServer().getConsoleSender().sendMessage(CommandNPC.getColorized((prefix ? CommandNPC.prefix : "") + log));
108 | }
109 |
110 | public static NPCDataManager getCommandManager() {
111 | return manager;
112 | }
113 |
114 | public static QueueSystem getQueueSystem() {
115 | return queueSystem;
116 | }
117 |
118 | public static CommandDatabase getCommandDatabase() {
119 | return database;
120 | }
121 |
122 | public static PluginConfiguration getConfigX() {
123 | return config;
124 | }
125 |
126 | public static boolean hasPlaceHolderAPI() {
127 | return placeHolderAPI;
128 | }
129 |
130 | public void reloadConfigX() {
131 | config = new PluginConfiguration(this);
132 | config.initConfiguration();
133 | config.loadConfiguration();
134 | }
135 |
136 | public static CommandNPC getInstance() {
137 | return (CommandNPC)instance;
138 | }
139 |
140 | public static boolean isEconAvailable() {
141 | return econAvailable;
142 | }
143 |
144 | public void logError(String topic, String classx, String method, String error) {
145 | final String space = " ";
146 | String text = "&cTopic";
147 | topic = "&c" + topic;
148 | log("&4---------------------&b{&2CommandNPC &cError&b}&4---------------------", false);
149 | log(space.substring((space.length() + text.length()) / 2, space.length()) + text, false);
150 | log(space.substring((space.length() + topic.length()) / 2, space.length()) + topic, false);
151 | log("", false);
152 | for (String s : getLines(error, space)) {
153 | log("&b" + space.substring((space.length() + s.length()) / 2, space.length()) + s, false);
154 | }
155 | log("", false);
156 | String cl = "&8Class: &c" + classx + " &8Method: &c" + method;
157 | for (String s : getLines(cl, space)) {
158 | log("&c" + space.substring((space.length() + s.length()) / 2, space.length()) + s, false);
159 | }
160 | log("", false);
161 | log("&4---------------------&b{&2CommandNPC &cError&b}&4---------------------", false);
162 | }
163 |
164 | private ArrayList getLines(String parse, final String space) {
165 | ArrayList lines = new ArrayList<>();
166 | String s = "";
167 | String[] split = parse.split(" ");
168 | final int length = split.length;
169 | for (int i = 0; i < length; i++) {
170 | if (s.length() + split[i].length() < space.length()) {
171 | s += split[i] + " ";
172 | } else {
173 | lines.add(s);
174 | s = split[i] + " ";
175 | }
176 | if (i + 1 == length) {
177 | lines.add(s);
178 | }
179 | }
180 | return lines;
181 | }
182 |
183 | private void setupEconomy() {
184 | if (getServer().getPluginManager().getPlugin("Vault") == null) {
185 | log("Vault not found! Economy support for CommandNPC has been disabled.", true);
186 | return;
187 | }
188 | RegisteredServiceProvider rsp = getServer().getServicesManager().getRegistration(Economy.class);
189 | if (rsp == null) {
190 | log("Vault compatible economy not found! Economy support for CommandNPC has been disabled.", true);
191 | return;
192 | }
193 | econ = rsp.getProvider();
194 | if (econ != null) {
195 | log("Vault compatible economy found! Economy support for CommandNPC has been enabled.", true);
196 | econAvailable = true;
197 | }
198 | }
199 | }
200 |
--------------------------------------------------------------------------------
/src/main/java/me/messageofdeath/commandnpc/Listeners/NPCListener.java:
--------------------------------------------------------------------------------
1 | package me.messageofdeath.commandnpc.Listeners;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Arrays;
5 | import java.util.Random;
6 | import java.util.UUID;
7 |
8 | import me.clip.placeholderapi.PlaceholderAPI;
9 | import me.messageofdeath.commandnpc.CommandNPC;
10 | import me.messageofdeath.commandnpc.Database.ClickType;
11 | import me.messageofdeath.commandnpc.Database.LanguageSettings.LanguageSettings;
12 | import me.messageofdeath.commandnpc.Database.PluginSettings.PluginSettings;
13 | import me.messageofdeath.commandnpc.NPCDataManager.NPCCommand;
14 | import me.messageofdeath.commandnpc.NPCDataManager.NPCData;
15 | import me.messageofdeath.commandnpc.Utilities.BungeeCord.BungeeCordUtil;
16 | import me.messageofdeath.commandnpc.Utilities.CooldownManager.Cooldown;
17 | import me.messageofdeath.commandnpc.Utilities.CooldownManager.CooldownManager;
18 | import net.citizensnpcs.api.event.NPCLeftClickEvent;
19 | import net.citizensnpcs.api.event.NPCRemoveEvent;
20 | import net.citizensnpcs.api.event.NPCRightClickEvent;
21 | import net.citizensnpcs.api.npc.NPC;
22 | import net.citizensnpcs.api.util.Messaging;
23 |
24 | import org.bukkit.Bukkit;
25 | import org.bukkit.entity.Player;
26 | import org.bukkit.event.EventHandler;
27 | import org.bukkit.event.EventPriority;
28 | import org.bukkit.event.Listener;
29 | import org.bukkit.scheduler.BukkitScheduler;
30 |
31 | public class NPCListener implements Listener {
32 |
33 | private final ArrayList coolingDown = new ArrayList<>();//To prevent server overloads
34 | private final long delay = PluginSettings.CoolDown.getInteger();
35 | private final CooldownManager cooldown;
36 |
37 | public NPCListener() {
38 | cooldown = new CooldownManager();
39 | }
40 |
41 | @EventHandler(priority = EventPriority.HIGHEST)
42 | public void onNPCDelete(NPCRemoveEvent event) {
43 | if (CommandNPC.getCommandManager().hasNPCData(event.getNPC().getId())) {
44 | CommandNPC.getCommandManager().removeNPCData(event.getNPC().getId());
45 | }
46 | }
47 |
48 | @EventHandler(priority = EventPriority.HIGHEST)
49 | public void onRight(NPCRightClickEvent event) {
50 | if (CommandNPC.getCommandManager().hasNPCData(event.getNPC().getId()) && coolingDown.contains(event.getClicker().getUniqueId())) {
51 | if(PluginSettings.CooldownMessage.getBoolean()) {
52 | Messaging.send(event.getClicker(), LanguageSettings.CmdNPC_Cooldown.getSetting());
53 | }
54 | return;
55 | }
56 | this.onClick(event.getClicker(), event.getNPC(), ClickType.RIGHT);
57 | }
58 |
59 | @EventHandler(priority = EventPriority.HIGHEST)
60 | public void onLeft(NPCLeftClickEvent event) {
61 | if (CommandNPC.getCommandManager().hasNPCData(event.getNPC().getId()) && coolingDown.contains(event.getClicker().getUniqueId())) {
62 | if(PluginSettings.CooldownMessage.getBoolean()) {
63 | Messaging.send(event.getClicker(), LanguageSettings.CmdNPC_Cooldown.getSetting());
64 | }
65 | return;
66 | }
67 | this.onClick(event.getClicker(), event.getNPC(), ClickType.LEFT);
68 | }
69 |
70 | private void onClick(final Player player, NPC npc, ClickType clickType) {
71 | if (CommandNPC.getCommandManager().hasNPCData(npc.getId())) {
72 | BukkitScheduler scheduler = Bukkit.getServer().getScheduler();
73 | if(delay > 0) {
74 | coolingDown.add(player.getUniqueId());
75 | scheduler.scheduleSyncDelayedTask(CommandNPC.getInstance(), () -> coolingDown.remove(player.getUniqueId()), this.delay);
76 | }
77 | NPCData data = CommandNPC.getCommandManager().getNPCData(npc.getId());
78 | boolean isOp = player.isOp();
79 | ArrayList commands = new ArrayList<>();
80 | if(data.isRandom()) {
81 | commands.add(data.getCommands().get(new Random().nextInt(data.getCommands().size())));
82 | }else{
83 | commands = data.getCommands();
84 | }
85 | for(NPCCommand command : commands) {
86 | if(command.getClickType() == clickType || command.getClickType() == ClickType.BOTH) {
87 | if(command.getPermission().isEmpty() || player.hasPermission(command.getPermission()) || command.getPermission().equalsIgnoreCase("noPerm")) {
88 | //------------ Cooldown ------------
89 | if(cooldown.hasCooldown(player.getUniqueId())) {
90 | if(Arrays.stream(cooldown.getCooldowns(player.getUniqueId())).anyMatch(search ->
91 | search.getNpcID() == npc.getId() && search.getCommandID() == command.getID())) {
92 | if (command.getCooldownMessage() != null && !command.getCooldownMessage().isEmpty()) {
93 | Messaging.sendError(player, command.getCooldownMessage());
94 | }
95 | continue;
96 | }
97 | }
98 | //------------ Economy ------------
99 | if(command.getCost() > 0 && CommandNPC.isEconAvailable()) {
100 | if(CommandNPC.getEcon().has(player, command.getCost())) {
101 | CommandNPC.getEcon().withdrawPlayer(player, command.getCost());
102 | }else{
103 | if(!command.isIgnoreMoneyMsg()) {
104 | Messaging.sendError(player, LanguageSettings.CmdNPC_NoMoney.getSetting());
105 | }
106 | continue;
107 | }
108 | }
109 | //------------ BungeeCord ------------
110 | if(command.getCommand().toLowerCase().startsWith("server ")) {
111 | if(PluginSettings.BungeeCord.getBoolean()) {
112 | String[] args = command.getCommand().split(" ");
113 | if(args.length == 2) {
114 | if(command.getDelay() > 0) {
115 | scheduler.scheduleSyncDelayedTask(CommandNPC.getInstance(), () -> {
116 | BungeeCordUtil.sendPlayerToServer(player, args[1]);
117 | CommandNPC.getInstance().log("Sent '"+player.getName()+"' to server '"+args[1]+"'!", true);
118 | }, command.getDelay());
119 | }else{
120 | BungeeCordUtil.sendPlayerToServer(player, args[1]);
121 | CommandNPC.getInstance().log("Sent '"+player.getName()+"' to server '"+args[1]+"'!", true);
122 | }
123 | executeCooldown(player.getUniqueId(), npc.getId(), command.getID(), command.getCooldown());
124 | continue;
125 | }else{
126 | Messaging.sendError(player, "Inform the system administrator to look in console for error.");
127 | CommandNPC.getInstance().logError("BungeeCord Command", "NPCListener", "onClick(Player, NPC, ClickType)", "/server command for NPC " +
128 | "ID: " + npc.getId() + ", Command ID: " + command.getID() + ", does not follow the format of /server ");
129 | continue;
130 | }
131 | }else{
132 | Messaging.sendError(player, "Inform the system administrator to look in console for error.");
133 | CommandNPC.getInstance().logError("BungeeCord Command", "NPCListener", "onClick(Player, NPC, ClickType)", "BungeeCord is " +
134 | "disabled in config.yml, yet an NPC has the command /server registered to it.");
135 | continue;
136 | }
137 | }
138 | //------------ Execute Command ------------
139 | if(!command.inConsole()) {
140 | try{
141 | if(command.asOp() && !isOp) {
142 | player.setOp(true);
143 | }
144 | if(command.getDelay() > 0) {
145 | scheduler.scheduleSyncDelayedTask(CommandNPC.getInstance(), () -> {
146 | player.chat("/" + process(player, command.getCommand()));
147 | if(PluginSettings.ExecuteCommandMessage.getBoolean()) {
148 | Messaging.send(player, LanguageSettings.CmdNPC_Executed.getSetting());
149 | }
150 | }, command.getDelay());
151 | }else{
152 | player.chat("/" + process(player, command.getCommand()));
153 | if(PluginSettings.ExecuteCommandMessage.getBoolean()) {
154 | Messaging.send(player, LanguageSettings.CmdNPC_Executed.getSetting());
155 | }
156 | }
157 | }finally{
158 | player.setOp(isOp);
159 | }
160 | }else{
161 | if(command.getDelay() > 0) {
162 | scheduler.scheduleSyncDelayedTask(CommandNPC.getInstance(), () -> {
163 | Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), process(player, command.getCommand()));
164 | if(PluginSettings.ExecuteCommandMessage.getBoolean()) {
165 | Messaging.send(player, LanguageSettings.CmdNPC_Executed.getSetting());
166 | }
167 | }, command.getDelay());
168 | }else{
169 | Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), process(player, command.getCommand()));
170 | if(PluginSettings.ExecuteCommandMessage.getBoolean()) {
171 | Messaging.send(player, LanguageSettings.CmdNPC_Executed.getSetting());
172 | }
173 | }
174 | }
175 | //------------ Cooldown ------------
176 | executeCooldown(player.getUniqueId(), npc.getId(), command.getID(), command.getCooldown());
177 | }else{
178 | if(!command.isIgnorePermMsg()) {
179 | Messaging.sendError(player, LanguageSettings.Commands_NoPermission.getSetting());
180 | }
181 | }
182 | }//Wrong clickType (Do nothing)
183 | }
184 | }
185 | }
186 |
187 | private String process(Player player, String cmd) {
188 | return CommandNPC.hasPlaceHolderAPI() ? PlaceholderAPI.setPlaceholders(player, cmd.replace("%name", player.getName()))
189 | : cmd.replace("%name", player.getName());
190 | }
191 |
192 | private void executeCooldown(UUID uuid, int npcID, int commandID, int cd) {
193 | if(cd > 0) {
194 | cooldown.addCooldown(new Cooldown(uuid, npcID, commandID));
195 | Bukkit.getScheduler().scheduleSyncDelayedTask(CommandNPC.getInstance(), () -> cooldown.removeCooldown(uuid), cd);
196 | }
197 | }
198 | }
199 |
--------------------------------------------------------------------------------
/src/main/java/me/messageofdeath/commandnpc/Database/YamlDatabase.java:
--------------------------------------------------------------------------------
1 | package me.messageofdeath.commandnpc.Database;
2 |
3 | import java.io.File;
4 | import java.io.FileOutputStream;
5 | import java.io.InputStream;
6 | import java.io.OutputStream;
7 | import java.util.ArrayList;
8 |
9 | import org.bukkit.Material;
10 | import org.bukkit.configuration.ConfigurationSection;
11 | import org.bukkit.configuration.file.FileConfiguration;
12 | import org.bukkit.configuration.file.YamlConfiguration;
13 | import org.bukkit.plugin.java.JavaPlugin;
14 |
15 | /**
16 | * @author messageofDEATH
17 | */
18 |
19 | public class YamlDatabase {
20 |
21 | public JavaPlugin plugin = null;
22 | public String fileName = null, fileExtension = null, fileLocation = null;
23 | public File file = null;
24 | public FileConfiguration fileConfig = null;
25 | public boolean createdFile = false, saveOnSet = true, copyFileOnStart = true;
26 |
27 | /**
28 | * Creates a new instance of YamlDatabase with the default fileLocation.
29 | * @param plugin
30 | * @return new YamlDatabase
31 | */
32 |
33 | public YamlDatabase(JavaPlugin plugin) {
34 | this.plugin = plugin;
35 | this.fileExtension = ".yml";
36 | this.fileConfig = new YamlConfiguration();
37 | }
38 |
39 | /**
40 | * Creates a new instance of YamlDatabase with the default fileLocation.
41 | * @param plugin
42 | * @param fileName
43 | * @return new YamlDatabase
44 | */
45 | public YamlDatabase(JavaPlugin plugin, String fileName) {
46 | this.plugin = plugin;
47 | this.fileName = fileName;
48 | this.fileExtension = ".yml";
49 | this.fileConfig = new YamlConfiguration();
50 | }
51 |
52 | public YamlDatabase(JavaPlugin plugin, String fileName, boolean copyFileOnStart) {
53 | this.plugin = plugin;
54 | this.fileName = fileName;
55 | this.fileExtension = ".yml";
56 | this.fileConfig = new YamlConfiguration();
57 | this.copyFileOnStart = copyFileOnStart;
58 | }
59 |
60 | /**
61 | * Creates a new instance of YamlDatabase with a set fileLocation.
62 | * @param plugin
63 | * @param fileName
64 | * @param fileLocation
65 | * @return new YamlDatabase
66 | */
67 |
68 | public YamlDatabase(JavaPlugin plugin, String fileName, String fileLocation) {
69 | this.plugin = plugin;
70 | this.fileName = fileName;
71 | this.fileExtension = ".yml";
72 | this.fileConfig = new YamlConfiguration();
73 | this.fileLocation = fileLocation;
74 | }
75 |
76 | /**
77 | * Checks if file exists, if not creates one and puts default.
78 | */
79 | public void changeFile(String fileName) {
80 | this.changeFile(fileName, this.plugin.getDataFolder().getPath());
81 | }
82 |
83 | public void changeFile(String fileName, String fileLocation) {
84 | this.fileName = fileName;
85 | this.fileLocation = fileLocation;
86 | this.onStartUp();
87 | }
88 |
89 | public void onStartUp() {
90 | if(this.fileLocation == null)
91 | this.file = new File(this.plugin.getDataFolder(), this.fileName + this.fileExtension);
92 | else
93 | this.file = new File(this.fileLocation, this.fileName + this.fileExtension);
94 | try{
95 | // *** Config ***
96 | this.fileConfig = YamlConfiguration.loadConfiguration(this.file);
97 | if(!this.file.exists()){
98 | this.file.getParentFile().mkdirs();
99 | this.file.createNewFile();
100 | if(copyFileOnStart && this.plugin.getResource(this.fileName + this.fileExtension) != null)
101 | copy(this.plugin.getResource(this.fileName + this.fileExtension), this.file);
102 | this.createdFile = true;
103 | }
104 | //this.fileConfig.load(this.file);
105 | }catch (Exception e){e.getCause();}
106 | }
107 |
108 | /**
109 | * Saves the file.
110 | */
111 |
112 | public void onShutDown() {
113 | this.save();
114 | }
115 |
116 | private void copy(InputStream in, File file) {
117 | try{
118 | OutputStream out = new FileOutputStream(file);
119 | byte[] buf = new byte[1024];
120 | int len;
121 | while ((len = in.read(buf)) > 0){
122 | out.write(buf, 0, len);
123 | }
124 | out.close();
125 | in.close();
126 | }catch (Exception e){
127 | e.printStackTrace();
128 | }
129 | }
130 |
131 | /**
132 | * Reloads the file
133 | */
134 |
135 | public void reload() {
136 | try{
137 | this.fileConfig.load(this.file);
138 | }catch (Exception ignored){
139 |
140 | }
141 | }
142 |
143 | /**
144 | * Saves the file
145 | */
146 |
147 | public void save() {
148 | try{
149 | this.fileConfig.save(this.file);
150 | }catch(Exception ignored) {
151 |
152 | }
153 | }
154 |
155 | /**
156 | * Gets a ConfigurationSection value from the file.
157 | * @param key
158 | * @param fallback
159 | * @return the ConfigurationSection for the key, if exists.
160 | * @return fallback when the key doesn't exist.
161 | */
162 |
163 | public ConfigurationSection getConfigurationSection(String key, ConfigurationSection fallback) {
164 | if(this.fileConfig.contains(key)) {
165 | return this.fileConfig.getConfigurationSection(key);
166 | }else{
167 | return fallback;
168 | }
169 | }
170 |
171 | /**
172 | * Gets the ConfigurationSection in a List value from the file.
173 | * @param key
174 | * @return the List for the key, if exists.
175 | * @return fallback when the key doesn't exist.
176 | */
177 |
178 | public ArrayList getSection(String key, ArrayList fallback) {
179 | if(this.fileConfig.contains(key)) {
180 | ArrayList section = new ArrayList<>();
181 | for(Object str : getConfigurationSection(key, null).getKeys(false).toArray()) {
182 | section.add(String.valueOf(str));
183 | }
184 | return section;
185 | }else{
186 | return fallback;
187 | }
188 | }
189 |
190 | /**
191 | * Gets an integer value from the file.
192 | * @param key
193 | * @param fallback
194 | * @return the integer for the key, if exists.
195 | * @return fallback when the key doesn't exist.
196 | */
197 | public int getInteger(String key, int fallback){
198 | if(this.fileConfig.contains(key)) {
199 | return this.fileConfig.getInt(key);
200 | }else{
201 | return fallback;
202 | }
203 | }
204 |
205 | /**
206 | * Gets an string value from the file.
207 | * @param key
208 | * @param fallback
209 | * @return the string for the key, if exists.
210 | * @return fallback when the key doesn't exist.
211 | */
212 | public String getString(String key, String fallback){
213 | if(this.fileConfig.contains(key)) {
214 | return this.fileConfig.getString(key);
215 | }else{
216 | return fallback;
217 | }
218 | }
219 |
220 | /**
221 | * Gets an float value from the file.
222 | * @param key
223 | * @return whether it exists or not
224 | */
225 |
226 | public boolean contains(String key) {
227 | return this.fileConfig.contains(key);
228 | }
229 |
230 | /**
231 | * Gets an boolean value from the file. It will accept "true" and "false".
232 | * @param key
233 | * @param fallback
234 | * @return the boolean for the key, if exists.
235 | * @return fallback when the key doesn't exist.
236 | */
237 | public boolean getBoolean(String key, boolean fallback){
238 | if(this.fileConfig.contains(key)) {
239 | return this.fileConfig.getBoolean(key);
240 | }else{
241 | return fallback;
242 | }
243 | }
244 |
245 | /**
246 | * Gets a List value from the file.
247 | * @param key
248 | * @param fallback
249 | * @return the List for the key, if exists.
250 | * @return fallback when the key doesn't exist.
251 | */
252 |
253 | public ArrayList getStringArray(String key, ArrayList fallback) {
254 | if(this.fileConfig.contains(key)) {
255 | return (ArrayList)this.fileConfig.getStringList(key);
256 | }else{
257 | return fallback;
258 | }
259 | }
260 |
261 | /**
262 | * Gets an double value from the file.
263 | * @param key
264 | * @param fallback
265 | * @return the double for the key, if exists.
266 | * @return fallback when the key doesn't exist.
267 | */
268 | public double getDouble(String key, double fallback){
269 | if(this.fileConfig.contains(key)) {
270 | return this.fileConfig.getDouble(key);
271 | }else{
272 | return fallback;
273 | }
274 | }
275 |
276 | /**
277 | * Gets an Object value from the file.
278 | * @param key
279 | * @param fallback
280 | * @return the Object for the key, if exists.
281 | * @return fallback when the key doesn't exist.
282 | */
283 |
284 | public Object getObject(String key, Object fallback) {
285 | if(this.fileConfig.contains(key)) {
286 | return this.fileConfig.get(key);
287 | }else{
288 | return fallback;
289 | }
290 | }
291 | /**
292 | * Gets an float value from the file.
293 | * @param key
294 | * @param fallback
295 | * @return the float for the key, if exists.
296 | * @return fallback when the key doesn't exist.
297 | */
298 | public float getFloat(String key, float fallback){
299 | if(this.fileConfig.contains(key)) {
300 | return (float) this.fileConfig.getDouble(key);
301 | }else{
302 | return fallback;
303 | }
304 | }
305 |
306 | /**
307 | * Gets an material value from the file. It parses material-ids as well as Bukkit-Material names.
308 | * @param key
309 | * @param fallback
310 | * @return the material for the key, if exists.
311 | * @return fallback when the key doesn't exist.
312 | */
313 | public Material getMaterial(String key, Material fallback){
314 | if(this.fileConfig.contains(key)) {
315 | return this.fileConfig.getItemStack(key).getType();
316 | }else{
317 | return fallback;
318 | }
319 | }
320 |
321 | /**
322 | * When one key exists multiple times, use this method to get all values as strings in a list.
323 | * @param key the key to search
324 | * @return all values for that key.
325 | */
326 |
327 | /**
328 | * Writes the keySet to the file
329 | */
330 |
331 | public void set(String key, Object set) {
332 | this.fileConfig.set(key, set);
333 | if(this.saveOnSet) {
334 | this.save();
335 | }
336 | }
337 | }
338 |
--------------------------------------------------------------------------------
/src/main/java/me/messageofdeath/commandnpc/commands/CitizenCommands.java:
--------------------------------------------------------------------------------
1 | package me.messageofdeath.commandnpc.commands;
2 |
3 | import java.util.ArrayList;
4 |
5 | import org.bukkit.command.CommandSender;
6 |
7 | import me.messageofdeath.commandnpc.CommandNPC;
8 | import me.messageofdeath.commandnpc.Database.ClickType;
9 | import me.messageofdeath.commandnpc.Database.LanguageSettings.LanguageSettings;
10 | import me.messageofdeath.commandnpc.Database.PluginSettings.PluginSettings;
11 | import me.messageofdeath.commandnpc.NPCDataManager.NPCCommand;
12 | import me.messageofdeath.commandnpc.NPCDataManager.NPCData;
13 | import me.messageofdeath.commandnpc.Utilities.Utilities;
14 | import net.citizensnpcs.api.command.Command;
15 | import net.citizensnpcs.api.command.CommandContext;
16 | import net.citizensnpcs.api.command.Requirements;
17 | import net.citizensnpcs.api.npc.NPC;
18 | import net.citizensnpcs.api.util.Messaging;
19 |
20 | @Requirements(selected = true, ownership = true)
21 | public class CitizenCommands {
22 |
23 | @Command(aliases = { "npc" }, usage = "cmdadd [-c console] [-o Op] [-r random] [-i ignorePermMsg] [-l ignoreMoneyMsg] [--v price] [--t clickType] " +
24 | "[--d delay] [--cd cooldown] [--p custom.permission.node] ",
25 | desc = "Add a command to a NPC", modifiers = { "cmdadd" }, min = 2, flags = "coril", permission = "commandnpc.admin")
26 | public void addCmd(CommandContext args, CommandSender sender, NPC npc) {
27 | int id = npc.getId();
28 | String permission = "noPerm";
29 | ClickType clickType;
30 | if(ClickType.hasClickType(PluginSettings.ClickType.getSetting())) {
31 | clickType = ClickType.getClickType(PluginSettings.ClickType.getSetting());
32 | }else{
33 | clickType = ClickType.BOTH;
34 | CommandNPC.getInstance().logError("ClickType", "CitizensCommands", "addCmd(CommandContext, CommandSender, NPC)", "ClickType from config.yml did not resolve! "
35 | + "Resulting to ClickType BOTH!");
36 | }
37 | boolean inConsole = false;
38 | boolean isRandom = false;
39 | boolean asOp = false;
40 | boolean ignorePerm = false;
41 | boolean ignoreMoney = false;
42 | String cmd;
43 | double cost = 0;
44 | int delay = 0;
45 | int cooldown = 0;
46 |
47 | if (args.hasFlag('c')) {
48 | inConsole = true;
49 | }
50 | if (args.hasFlag('o')) {
51 | asOp = true;
52 | }
53 | if (args.hasFlag('r')) {
54 | isRandom = true;
55 | }
56 | if (args.hasFlag('i')) {
57 | ignorePerm = true;
58 | }
59 | if (args.hasFlag('l')) {
60 | ignoreMoney = true;
61 | }
62 | if(args.hasValueFlag("t")) {
63 | String value = args.getFlag("t");
64 | if(ClickType.hasClickType(value)) {
65 | clickType = ClickType.getClickType(value);
66 | }else{
67 | Messaging.sendError(sender, LanguageSettings.Commands_Citizens_ValueFlagT.getSetting());
68 | }
69 | }
70 | if (args.hasValueFlag("p")) {
71 | permission = args.getFlag("p");
72 | }
73 | if (args.hasValueFlag("v")) {
74 | if(Utilities.isDouble(args.getFlag("v"))) {
75 | cost = args.getFlagDouble("v");
76 | }else{
77 | Messaging.sendError(sender, LanguageSettings.Commands_MustBeNumeric.getSetting().replace("%arg", "price"));
78 | }
79 | }
80 | if (args.hasValueFlag("d")) {
81 | if(Utilities.isInteger(args.getFlag("d"))) {
82 | delay = args.getFlagInteger("d");
83 | }else{
84 | Messaging.sendError(sender, LanguageSettings.Commands_MustBeNumeric.getSetting().replace("%arg", "delay"));
85 | }
86 | }
87 | if(args.hasValueFlag("cd")) {
88 | if(Utilities.isInteger(args.getFlag("cd"))) {
89 | cooldown = args.getFlagInteger("cd");
90 | }else{
91 | Messaging.sendError(sender, LanguageSettings.Commands_MustBeNumeric.getSetting().replace("%arg", "cooldown"));
92 | }
93 | }
94 | cmd = args.getJoinedStrings(1);
95 | if (cmd != null) {
96 | NPCCommand npcCommand = new NPCCommand(cmd, permission, "", clickType, inConsole, asOp, isRandom, ignorePerm, ignoreMoney, cost, delay, cooldown);
97 | if (CommandNPC.getCommandManager().hasNPCData(id)) {
98 | CommandNPC.getCommandManager().getNPCData(id).addCommand(npcCommand);
99 | } else {
100 | CommandNPC.getCommandManager().addNPCData(new NPCData(id, npcCommand));
101 | }
102 | CommandNPC.getCommandDatabase().saveDatabase();
103 | Messaging.send(sender, LanguageSettings.Commands_Citizens_Add.getSetting());
104 | }else{
105 | Messaging.send(sender, LanguageSettings.Commands_Citizens_NoCmdInput.getSetting());
106 | }
107 | }
108 |
109 | @Command(aliases = { "npc" }, usage = "cmdremove ", desc = "Remove a command on the NPC.", modifiers = { "cmdremove" }, min = 2, max = 2,
110 | permission = "commandnpc.admin")
111 | public void removeCmd(CommandContext args, CommandSender sender, NPC npc) {
112 | int id = npc.getId();
113 | if(CommandNPC.getCommandManager().hasNPCData(id)) {
114 | NPCData data = CommandNPC.getCommandManager().getNPCData(id);
115 | if(Utilities.isInteger(args.getString(1))) {
116 | if(data.hasCommand(args.getInteger(1))) {
117 | data.removeCommand(args.getInteger(1));
118 | Messaging.send(sender, LanguageSettings.Commands_Citizens_Removed.getSetting());
119 | }else{
120 | Messaging.sendError(sender, LanguageSettings.Commands_DoesNotExist.getSetting().replace("%type", "ID")); }
121 | }else{
122 | Messaging.sendError(sender, LanguageSettings.Commands_Citizens_NumBetween.getSetting().replace("%num1", "1").replace("%num2", data.getCommands().size() + ""));
123 | }
124 | }else{
125 | Messaging.sendError(sender, LanguageSettings.Commands_Citizens_NoCommands.getSetting());
126 | }
127 | }
128 |
129 | @Command(aliases = { "npc" }, usage = "cmdset [-c console] [-o Op] [-r random] [-m cdMsg] [-i ignorePermMsg] [-l ignoreMoneyMsg] [--v price] " +
130 | "[--t clickType] [--d delay] [--cd cooldown] [--p custom.permission.node] [command | cdMsg...]",
131 | desc = "Set various variables for the command.", modifiers = { "cmdset" }, min = 2, flags = "cormil", permission = "commandnpc.admin")
132 | public void setCmd(CommandContext args, CommandSender sender, NPC npc) {
133 | int npcID = npc.getId();
134 | if(Utilities.isInteger(args.getString(1))) {
135 | int id = args.getInteger(1);
136 | if(CommandNPC.getCommandManager().hasNPCData(npcID)) {
137 | NPCData data = CommandNPC.getCommandManager().getNPCData(npcID);
138 | if(data.hasCommand(id)) {
139 | NPCCommand command = data.getCommand(id);
140 | Messaging.send(sender, CommandNPC.prefix + LanguageSettings.Commands_SetTo_Header.getSetting());
141 | if(args.hasFlag('c')) {
142 | command.setInConsole(!command.inConsole());
143 | Messaging.send(sender, LanguageSettings.Commands_SetTo_Line.getSetting().replace("%variable", "Console")
144 | .replace("%value", command.inConsole() + ""));
145 | }
146 | if(args.hasFlag('o')) {
147 | command.setAsOP(!command.asOp());
148 | Messaging.send(sender, LanguageSettings.Commands_SetTo_Line.getSetting().replace("%variable", "Op")
149 | .replace("%value", command.asOp() + ""));
150 | }
151 | if(args.hasFlag('r')) {
152 | command.setIsRandom(!command.isRandom());
153 | Messaging.send(sender, LanguageSettings.Commands_SetTo_Line.getSetting().replace("%variable", "Random")
154 | .replace("%value", command.isRandom() + ""));
155 | }
156 | if(args.hasFlag('i')) {
157 | command.setIgnorePermMsg(!command.isIgnorePermMsg());
158 | Messaging.send(sender, LanguageSettings.Commands_SetTo_Line.getSetting().replace("%variable", "Ignore Perm Message")
159 | .replace("%value", command.isIgnorePermMsg() + ""));
160 | }
161 | if(args.hasFlag('l')) {
162 | command.setIgnoreMoneyMsg(!command.isIgnoreMoneyMsg());
163 | Messaging.send(sender, LanguageSettings.Commands_SetTo_Line.getSetting().replace("%variable", "Ignore Money Message")
164 | .replace("%value", command.isIgnoreMoneyMsg() + ""));
165 | }
166 | if(args.hasValueFlag("p")) {
167 | command.setPermission(args.getFlag("p"));
168 | Messaging.send(sender, LanguageSettings.Commands_SetTo_Line.getSetting().replace("%variable", "Permission")
169 | .replace("%value", command.getPermission()));
170 | }
171 | if(args.hasValueFlag("v")) {
172 | if(Utilities.isDouble(args.getFlag("v"))) {
173 | command.setCost(args.getFlagDouble("v"));
174 | Messaging.send(sender, LanguageSettings.Commands_SetTo_Line.getSetting().replace("%variable", "Cost")
175 | .replace("%value", command.getCost() + ""));
176 | }else{
177 | Messaging.sendError(sender, LanguageSettings.Commands_MustBeNumeric.getSetting().replace("%arg", "cost"));
178 | }
179 | }
180 | if (args.hasValueFlag("d")) {
181 | if(Utilities.isInteger(args.getFlag("d"))) {
182 | command.setDelay(args.getFlagInteger("d"));
183 | Messaging.send(sender, LanguageSettings.Commands_SetTo_Line.getSetting().replace("%variable", "Delay")
184 | .replace("%value", command.getDelay() + ""));
185 | }else{
186 | Messaging.sendError(sender, LanguageSettings.Commands_MustBeNumeric.getSetting().replace("%arg", "delay"));
187 | }
188 | }
189 | if(args.hasValueFlag("cd")) {
190 | if(Utilities.isInteger(args.getFlag("cd"))) {
191 | command.setCooldown(args.getFlagInteger("cd"));
192 | Messaging.send(sender, LanguageSettings.Commands_SetTo_Line.getSetting().replace("%variable", "Cooldown")
193 | .replace("%value", command.getCooldown() + ""));
194 | }else{
195 | Messaging.sendError(sender, LanguageSettings.Commands_MustBeNumeric.getSetting().replace("%arg", "cooldown"));
196 | }
197 | }
198 | if(args.hasValueFlag("t")) {
199 | String value = args.getFlag("t");
200 | if(ClickType.hasClickType(value)) {
201 | command.setClickType(ClickType.getClickType(value));
202 | Messaging.send(sender, LanguageSettings.Commands_SetTo_Line.getSetting().replace("%variable", "ClickType")
203 | .replace("%value", command.getClickType().name()));
204 | }else{
205 | Messaging.sendError(sender, LanguageSettings.Commands_Citizens_ValueFlagT.getSetting());
206 | }
207 | }
208 | if(args.argsLength() > 2) {
209 | if(args.hasFlag('m')) {
210 | command.setCooldownMessage(args.getJoinedStrings(2));
211 | Messaging.send(sender, LanguageSettings.Commands_SetTo_Line.getSetting().replace("%variable", "Cooldown Message")
212 | .replace("%value", command.getCooldownMessage()));
213 | }else {
214 | command.setCommand(args.getJoinedStrings(2));
215 | Messaging.send(sender, LanguageSettings.Commands_SetTo_Line.getSetting().replace("%variable", "Command")
216 | .replace("%value", command.getCommand()));
217 | }
218 | }
219 | CommandNPC.getCommandDatabase().saveDatabase();
220 | }else{
221 | Messaging.sendError(sender, LanguageSettings.Commands_Citizens_NumBetween.getSetting().replace("%num1", "1")
222 | .replace("%num2", data.getCommands().size() + ""));
223 | }
224 | }else{
225 | Messaging.sendError(sender, LanguageSettings.Commands_Citizens_NoCommands.getSetting());
226 | }
227 | }else{
228 | Messaging.sendError(sender, LanguageSettings.Commands_MustBeNumeric.getSetting().replace("%arg", "ID"));
229 | }
230 | }
231 |
232 | @Command(aliases = { "npc" }, usage = "cmdinfo [ID]", desc = "Displays various information about the commands of an NPC.", modifiers = { "cmdinfo" }, min = 1, max = 2,
233 | permission = "commandnpc.admin")
234 | public void infoCmds(CommandContext args, CommandSender sender, NPC npc) {
235 | int id = npc.getId();
236 | if(CommandNPC.getCommandManager().hasNPCData(id)) {
237 | NPCData data = CommandNPC.getCommandManager().getNPCData(id);
238 | ArrayList commands;
239 | if(args.argsLength() == 2) {
240 | if(Utilities.isInteger(args.getString(1))) {
241 | int cmdID = args.getInteger(1);
242 | if(data.hasCommand(cmdID)) {
243 | commands = new ArrayList<>();
244 | commands.add(data.getCommand(cmdID));
245 | }else{
246 | Messaging.sendError(sender, LanguageSettings.Commands_Citizens_NumBetween.getSetting().replace("%num1", "1")
247 | .replace("%num2", data.getCommands().size() + ""));
248 | return;
249 | }
250 | }else{
251 | Messaging.sendError(sender, LanguageSettings.Commands_MustBeNumeric.getSetting().replace("%arg", "ID"));
252 | return;
253 | }
254 | }else{
255 | commands = data.getCommands();
256 | }
257 | //npc cmdset 2 -c -o -r -m -i -l --v 25 --t left --d 60 --cd 200 --p custom.permission This is a test cooldown message
258 | Messaging.send(sender, CommandNPC.prefix + LanguageSettings.Commands_List_InfoHeader.getSetting().replace("%id", id + ""));
259 | String prefix = LanguageSettings.Commands_List_InfoLinePrefix.getSetting();
260 | String infoLine = LanguageSettings.Commands_List_InfoLine.getSetting();
261 | String spacer = " &8| ";
262 | for(NPCCommand command : commands) {
263 | Messaging.send(sender, LanguageSettings.Commands_List_InfoLineHeader.getSetting().replace("%name", "Command ID")
264 | .replace("%value", "" + command.getID()));
265 | Messaging.send(sender, prefix + infoLine.replace("%name", "Command").replace("%value", command.getCommand()));
266 | Messaging.send(sender, prefix + infoLine.replace("%name", "Permission").replace("%value", command.getPermission()));
267 | Messaging.send(sender, prefix + infoLine.replace("%name", "Cooldown Message").replace("%value", command.getCooldownMessage()));
268 | Messaging.send(sender, prefix + infoLine.replace("%name", "Ignore Perm Message").replace("%value", command.isIgnorePermMsg() + "")
269 | + spacer + infoLine.replace("%name", "Ignore Money Message").replace("%value", command.isIgnoreMoneyMsg() + ""));
270 | Messaging.send(sender, prefix + infoLine.replace("%name", "ClickType").replace("%value", command.getClickType().name().toLowerCase())
271 | + spacer + infoLine.replace("%name", "Cost").replace("%value", command.getCost() + "")
272 | + spacer + infoLine.replace("%name", "Cooldown").replace("%value", command.getCooldown() + ""));
273 | Messaging.send(sender, prefix + infoLine.replace("%name", "In Console").replace("%value", command.inConsole() + "")
274 | + spacer + infoLine.replace("%name", "As Op").replace("%value", command.asOp() + ""));
275 | }
276 | }else{
277 | Messaging.sendError(sender, LanguageSettings.Commands_Citizens_NoCommands.getSetting());
278 | }
279 | }
280 |
281 | @Command(aliases = { "npc" }, usage = "cmdreset", desc = "Reset the commands on the NPC.", modifiers = { "cmdreset" }, min = 1, max = 1, permission = "commandnpc.admin")
282 | public void resetCmds(CommandContext args, CommandSender sender, NPC npc) {
283 | int id = npc.getId();
284 | if(CommandNPC.getCommandManager().hasNPCData(id)) {
285 | CommandNPC.getCommandManager().removeNPCData(id);
286 | CommandNPC.getCommandDatabase().deleteNPC(id);
287 | Messaging.send(sender, LanguageSettings.Commands_Citizens_Reset.getSetting());
288 | }else{
289 | Messaging.sendError(sender, LanguageSettings.Commands_Citizens_NoCommands.getSetting());
290 | }
291 | }
292 | }
293 |
--------------------------------------------------------------------------------
/src/main/java/me/messageofdeath/commandnpc/Utilities/Metrics/Metrics.java:
--------------------------------------------------------------------------------
1 | package me.messageofdeath.commandnpc.Utilities.Metrics;
2 |
3 | import org.bukkit.Bukkit;
4 | import org.bukkit.configuration.file.YamlConfiguration;
5 | import org.bukkit.plugin.ServicePriority;
6 | import org.bukkit.plugin.java.JavaPlugin;
7 | import org.json.simple.JSONArray;
8 | import org.json.simple.JSONObject;
9 |
10 | import javax.net.ssl.HttpsURLConnection;
11 | import java.io.ByteArrayOutputStream;
12 | import java.io.DataOutputStream;
13 | import java.io.File;
14 | import java.io.IOException;
15 | import java.lang.reflect.InvocationTargetException;
16 | import java.net.URL;
17 | import java.util.ArrayList;
18 | import java.util.HashMap;
19 | import java.util.List;
20 | import java.util.Locale;
21 | import java.util.Map;
22 | import java.util.Timer;
23 | import java.util.TimerTask;
24 | import java.util.UUID;
25 | import java.util.logging.Level;
26 | import java.util.zip.GZIPOutputStream;
27 |
28 | /**
29 | * bStats collects some data for plugin authors.
30 | *
31 | * Check out https://bStats.org/ to learn more about bStats!
32 | */
33 | public class Metrics {
34 |
35 | static {
36 | // Maven's Relocate is clever and changes strings, too. So we have to use this little "trick" ... :D
37 | final String defaultPackage = new String(new byte[] { 'o', 'r', 'g', '.', 'b', 's', 't', 'a', 't', 's' });
38 | final String examplePackage = new String(new byte[] { 'y', 'o', 'u', 'r', '.', 'p', 'a', 'c', 'k', 'a', 'g', 'e' });
39 | // We want to make sure nobody just copy & pastes the example and use the wrong package names
40 | if (Metrics.class.getPackage().getName().equals(defaultPackage) || Metrics.class.getPackage().getName().equals(examplePackage)) {
41 | throw new IllegalStateException("bStats Metrics class has not been relocated correctly!");
42 | }
43 | }
44 |
45 | // The version of this bStats class
46 | private static final int B_STATS_VERSION = 1;
47 |
48 | // The url to which the data is sent
49 | private static final String URL = "https://bStats.org/submitData/bukkit";
50 |
51 | // Should failed requests be logged?
52 | private static boolean logFailedRequests;
53 |
54 | // The uuid of the server
55 | private static String serverUUID;
56 |
57 | // The plugin
58 | private final JavaPlugin plugin;
59 |
60 | // A list with all custom charts
61 | private final List charts = new ArrayList<>();
62 |
63 | /**
64 | * Class constructor.
65 | *
66 | * @param plugin The plugin which stats should be submitted.
67 | */
68 | public Metrics(JavaPlugin plugin) {
69 | if (plugin == null) {
70 | throw new IllegalArgumentException("Plugin cannot be null!");
71 | }
72 | this.plugin = plugin;
73 |
74 | // Get the config file
75 | File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats");
76 | File configFile = new File(bStatsFolder, "config.yml");
77 | YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile);
78 |
79 | // Check if the config file exists
80 | if (!config.isSet("serverUuid")) {
81 |
82 | // Add default values
83 | config.addDefault("enabled", true);
84 | // Every server gets it's unique random id.
85 | config.addDefault("serverUuid", UUID.randomUUID().toString());
86 | // Should failed request be logged?
87 | config.addDefault("logFailedRequests", false);
88 |
89 | // Inform the server owners about bStats
90 | config.options().header(
91 | "bStats collects some data for plugin authors like how many servers are using their plugins.\n" +
92 | "To honor their work, you should not disable it.\n" +
93 | "This has nearly no effect on the server performance!\n" +
94 | "Check out https://bStats.org/ to learn more :)"
95 | ).copyDefaults(true);
96 | try {
97 | config.save(configFile);
98 | } catch (IOException ignored) { }
99 | }
100 |
101 | // Load the data
102 | serverUUID = config.getString("serverUuid");
103 | logFailedRequests = config.getBoolean("logFailedRequests", false);
104 | if (config.getBoolean("enabled", true)) {
105 | boolean found = false;
106 | // Search for all other bStats Metrics classes to see if we are the first one
107 | for (Class> service : Bukkit.getServicesManager().getKnownServices()) {
108 | try {
109 | service.getField("B_STATS_VERSION"); // Our identifier :)
110 | found = true; // We aren't the first
111 | break;
112 | } catch (NoSuchFieldException ignored) { }
113 | }
114 | // Register our service
115 | Bukkit.getServicesManager().register(Metrics.class, this, plugin, ServicePriority.Normal);
116 | if (!found) {
117 | // We are the first!
118 | startSubmitting();
119 | }
120 | }
121 | }
122 |
123 | /**
124 | * Adds a custom chart.
125 | *
126 | * @param chart The chart to add.
127 | */
128 | public void addCustomChart(CustomChart chart) {
129 | if (chart == null) {
130 | throw new IllegalArgumentException("Chart cannot be null!");
131 | }
132 | charts.add(chart);
133 | }
134 |
135 | /**
136 | * Starts the Scheduler which submits our data every 30 minutes.
137 | */
138 | private void startSubmitting() {
139 | final Timer timer = new Timer(true); // We use a timer cause the Bukkit scheduler is affected by server lags
140 | timer.scheduleAtFixedRate(new TimerTask() {
141 | @Override
142 | public void run() {
143 | if (!plugin.isEnabled()) { // Plugin was disabled
144 | timer.cancel();
145 | return;
146 | }
147 | // Nevertheless we want our code to run in the Bukkit main thread, so we have to use the Bukkit scheduler
148 | // Don't be afraid! The connection to the bStats server is still async, only the stats collection is sync ;)
149 | Bukkit.getScheduler().runTask(plugin, new Runnable() {
150 | @Override
151 | public void run() {
152 | submitData();
153 | }
154 | });
155 | }
156 | }, 1000*60*5, 1000*60*30);
157 | // Submit the data every 30 minutes, first time after 5 minutes to give other plugins enough time to start
158 | // WARNING: Changing the frequency has no effect but your plugin WILL be blocked/deleted!
159 | // WARNING: Just don't do it!
160 | }
161 |
162 | /**
163 | * Gets the plugin specific data.
164 | * This method is called using Reflection.
165 | *
166 | * @return The plugin specific data.
167 | */
168 | public JSONObject getPluginData() {
169 | JSONObject data = new JSONObject();
170 |
171 | String pluginName = plugin.getDescription().getName();
172 | String pluginVersion = plugin.getDescription().getVersion();
173 |
174 | data.put("pluginName", pluginName); // Append the name of the plugin
175 | data.put("pluginVersion", pluginVersion); // Append the version of the plugin
176 | JSONArray customCharts = new JSONArray();
177 | for (CustomChart customChart : charts) {
178 | // Add the data of the custom charts
179 | JSONObject chart = customChart.getRequestJsonObject();
180 | if (chart == null) { // If the chart is null, we skip it
181 | continue;
182 | }
183 | customCharts.add(chart);
184 | }
185 | data.put("customCharts", customCharts);
186 |
187 | return data;
188 | }
189 |
190 | /**
191 | * Gets the server specific data.
192 | *
193 | * @return The server specific data.
194 | */
195 | private JSONObject getServerData() {
196 | // Minecraft specific data
197 | int playerAmount = Bukkit.getOnlinePlayers().size();
198 | int onlineMode = Bukkit.getOnlineMode() ? 1 : 0;
199 | String bukkitVersion = org.bukkit.Bukkit.getVersion();
200 | bukkitVersion = bukkitVersion.substring(bukkitVersion.indexOf("MC: ") + 4, bukkitVersion.length() - 1);
201 |
202 | // OS/Java specific data
203 | String javaVersion = System.getProperty("java.version");
204 | String osName = System.getProperty("os.name");
205 | String osArch = System.getProperty("os.arch");
206 | String osVersion = System.getProperty("os.version");
207 | int coreCount = Runtime.getRuntime().availableProcessors();
208 |
209 | JSONObject data = new JSONObject();
210 |
211 | data.put("serverUUID", serverUUID);
212 |
213 | data.put("playerAmount", playerAmount);
214 | data.put("onlineMode", onlineMode);
215 | data.put("bukkitVersion", bukkitVersion);
216 |
217 | data.put("javaVersion", javaVersion);
218 | data.put("osName", osName);
219 | data.put("osArch", osArch);
220 | data.put("osVersion", osVersion);
221 | data.put("coreCount", coreCount);
222 |
223 | return data;
224 | }
225 |
226 | /**
227 | * Collects the data and sends it afterwards.
228 | */
229 | private void submitData() {
230 | final JSONObject data = getServerData();
231 |
232 | JSONArray pluginData = new JSONArray();
233 | // Search for all other bStats Metrics classes to get their plugin data
234 | for (Class> service : Bukkit.getServicesManager().getKnownServices()) {
235 | try {
236 | service.getField("B_STATS_VERSION"); // Our identifier :)
237 | } catch (NoSuchFieldException ignored) {
238 | continue; // Continue "searching"
239 | }
240 | // Found one!
241 | try {
242 | pluginData.add(service.getMethod("getPluginData").invoke(Bukkit.getServicesManager().load(service)));
243 | } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) { }
244 | }
245 |
246 | data.put("plugins", pluginData);
247 |
248 | // Create a new thread for the connection to the bStats server
249 | new Thread(new Runnable() {
250 | @Override
251 | public void run() {
252 | try {
253 | // Send the data
254 | sendData(data);
255 | } catch (Exception e) {
256 | // Something went wrong! :(
257 | if (logFailedRequests) {
258 | plugin.getLogger().log(Level.WARNING, "Could not submit plugin stats of " + plugin.getName(), e);
259 | }
260 | }
261 | }
262 | }).start();
263 | }
264 |
265 | /**
266 | * Sends the data to the bStats server.
267 | *
268 | * @param data The data to send.
269 | * @throws Exception If the request failed.
270 | */
271 | private static void sendData(JSONObject data) throws Exception {
272 | if (data == null) {
273 | throw new IllegalArgumentException("Data cannot be null!");
274 | }
275 | if (Bukkit.isPrimaryThread()) {
276 | throw new IllegalAccessException("This method must not be called from the main thread!");
277 | }
278 | HttpsURLConnection connection = (HttpsURLConnection) new URL(URL).openConnection();
279 |
280 | // Compress the data to save bandwidth
281 | byte[] compressedData = compress(data.toString());
282 |
283 | // Add headers
284 | connection.setRequestMethod("POST");
285 | connection.addRequestProperty("Accept", "application/json");
286 | connection.addRequestProperty("Connection", "close");
287 | connection.addRequestProperty("Content-Encoding", "gzip"); // We gzip our request
288 | connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length));
289 | connection.setRequestProperty("Content-Type", "application/json"); // We send our data in JSON format
290 | connection.setRequestProperty("User-Agent", "MC-Server/" + B_STATS_VERSION);
291 |
292 | // Send data
293 | connection.setDoOutput(true);
294 | DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream());
295 | outputStream.write(compressedData);
296 | outputStream.flush();
297 | outputStream.close();
298 |
299 | connection.getInputStream().close(); // We don't care about the response - Just send our data :)
300 | }
301 |
302 | /**
303 | * Gzips the given String.
304 | *
305 | * @param str The string to gzip.
306 | * @return The gzipped String.
307 | * @throws IOException If the compression failed.
308 | */
309 | private static byte[] compress(final String str) throws IOException {
310 | if (str == null) {
311 | return null;
312 | }
313 | ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
314 | GZIPOutputStream gzip = new GZIPOutputStream(outputStream);
315 | gzip.write(str.getBytes("UTF-8"));
316 | gzip.close();
317 | return outputStream.toByteArray();
318 | }
319 |
320 | /**
321 | * Represents a custom chart.
322 | */
323 | public static abstract class CustomChart {
324 |
325 | // The id of the chart
326 | protected final String chartId;
327 |
328 | /**
329 | * Class constructor.
330 | *
331 | * @param chartId The id of the chart.
332 | */
333 | public CustomChart(String chartId) {
334 | if (chartId == null || chartId.isEmpty()) {
335 | throw new IllegalArgumentException("ChartId cannot be null or empty!");
336 | }
337 | this.chartId = chartId;
338 | }
339 |
340 | protected JSONObject getRequestJsonObject() {
341 | JSONObject chart = new JSONObject();
342 | chart.put("chartId", chartId);
343 | try {
344 | JSONObject data = getChartData();
345 | if (data == null) {
346 | // If the data is null we don't send the chart.
347 | return null;
348 | }
349 | chart.put("data", data);
350 | } catch (Throwable t) {
351 | if (logFailedRequests) {
352 | Bukkit.getLogger().log(Level.WARNING, "Failed to get data for custom chart with id " + chartId, t);
353 | }
354 | return null;
355 | }
356 | return chart;
357 | }
358 |
359 | protected abstract JSONObject getChartData();
360 |
361 | }
362 |
363 | /**
364 | * Represents a custom simple pie.
365 | */
366 | public static abstract class SimplePie extends CustomChart {
367 |
368 | /**
369 | * Class constructor.
370 | *
371 | * @param chartId The id of the chart.
372 | */
373 | public SimplePie(String chartId) {
374 | super(chartId);
375 | }
376 |
377 | /**
378 | * Gets the value of the pie.
379 | *
380 | * @return The value of the pie.
381 | */
382 | public abstract String getValue();
383 |
384 | @Override
385 | protected JSONObject getChartData() {
386 | JSONObject data = new JSONObject();
387 | String value = getValue();
388 | if (value == null || value.isEmpty()) {
389 | // Null = skip the chart
390 | return null;
391 | }
392 | data.put("value", value);
393 | return data;
394 | }
395 | }
396 |
397 | /**
398 | * Represents a custom advanced pie.
399 | */
400 | public static abstract class AdvancedPie extends CustomChart {
401 |
402 | /**
403 | * Class constructor.
404 | *
405 | * @param chartId The id of the chart.
406 | */
407 | public AdvancedPie(String chartId) {
408 | super(chartId);
409 | }
410 |
411 | /**
412 | * Gets the values of the pie.
413 | *
414 | * @param valueMap Just an empty map. The only reason it exists is to make your life easier.
415 | * You don't have to create a map yourself!
416 | * @return The values of the pie.
417 | */
418 | public abstract HashMap getValues(HashMap valueMap);
419 |
420 | @Override
421 | protected JSONObject getChartData() {
422 | JSONObject data = new JSONObject();
423 | JSONObject values = new JSONObject();
424 | HashMap map = getValues(new HashMap());
425 | if (map == null || map.isEmpty()) {
426 | // Null = skip the chart
427 | return null;
428 | }
429 | boolean allSkipped = true;
430 | for (Map.Entry entry : map.entrySet()) {
431 | if (entry.getValue() == 0) {
432 | continue; // Skip this invalid
433 | }
434 | allSkipped = false;
435 | values.put(entry.getKey(), entry.getValue());
436 | }
437 | if (allSkipped) {
438 | // Null = skip the chart
439 | return null;
440 | }
441 | data.put("values", values);
442 | return data;
443 | }
444 | }
445 |
446 | /**
447 | * Represents a custom single line chart.
448 | */
449 | public static abstract class SingleLineChart extends CustomChart {
450 |
451 | /**
452 | * Class constructor.
453 | *
454 | * @param chartId The id of the chart.
455 | */
456 | public SingleLineChart(String chartId) {
457 | super(chartId);
458 | }
459 |
460 | /**
461 | * Gets the value of the chart.
462 | *
463 | * @return The value of the chart.
464 | */
465 | public abstract int getValue();
466 |
467 | @Override
468 | protected JSONObject getChartData() {
469 | JSONObject data = new JSONObject();
470 | int value = getValue();
471 | if (value == 0) {
472 | // Null = skip the chart
473 | return null;
474 | }
475 | data.put("value", value);
476 | return data;
477 | }
478 |
479 | }
480 |
481 | /**
482 | * Represents a custom multi line chart.
483 | */
484 | public static abstract class MultiLineChart extends CustomChart {
485 |
486 | /**
487 | * Class constructor.
488 | *
489 | * @param chartId The id of the chart.
490 | */
491 | public MultiLineChart(String chartId) {
492 | super(chartId);
493 | }
494 |
495 | /**
496 | * Gets the values of the chart.
497 | *
498 | * @param valueMap Just an empty map. The only reason it exists is to make your life easier.
499 | * You don't have to create a map yourself!
500 | * @return The values of the chart.
501 | */
502 | public abstract HashMap getValues(HashMap valueMap);
503 |
504 | @Override
505 | protected JSONObject getChartData() {
506 | JSONObject data = new JSONObject();
507 | JSONObject values = new JSONObject();
508 | HashMap map = getValues(new HashMap());
509 | if (map == null || map.isEmpty()) {
510 | // Null = skip the chart
511 | return null;
512 | }
513 | boolean allSkipped = true;
514 | for (Map.Entry entry : map.entrySet()) {
515 | if (entry.getValue() == 0) {
516 | continue; // Skip this invalid
517 | }
518 | allSkipped = false;
519 | values.put(entry.getKey(), entry.getValue());
520 | }
521 | if (allSkipped) {
522 | // Null = skip the chart
523 | return null;
524 | }
525 | data.put("values", values);
526 | return data;
527 | }
528 |
529 | }
530 |
531 | /**
532 | * Represents a custom simple bar chart.
533 | */
534 | public static abstract class SimpleBarChart extends CustomChart {
535 |
536 | /**
537 | * Class constructor.
538 | *
539 | * @param chartId The id of the chart.
540 | */
541 | public SimpleBarChart(String chartId) {
542 | super(chartId);
543 | }
544 |
545 | /**
546 | * Gets the value of the chart.
547 | *
548 | * @param valueMap Just an empty map. The only reason it exists is to make your life easier.
549 | * You don't have to create a map yourself!
550 | * @return The value of the chart.
551 | */
552 | public abstract HashMap getValues(HashMap valueMap);
553 |
554 | @Override
555 | protected JSONObject getChartData() {
556 | JSONObject data = new JSONObject();
557 | JSONObject values = new JSONObject();
558 | HashMap map = getValues(new HashMap());
559 | if (map == null || map.isEmpty()) {
560 | // Null = skip the chart
561 | return null;
562 | }
563 | for (Map.Entry entry : map.entrySet()) {
564 | JSONArray categoryValues = new JSONArray();
565 | categoryValues.add(entry.getValue());
566 | values.put(entry.getKey(), categoryValues);
567 | }
568 | data.put("values", values);
569 | return data;
570 | }
571 |
572 | }
573 |
574 | /**
575 | * Represents a custom advanced bar chart.
576 | */
577 | public static abstract class AdvancedBarChart extends CustomChart {
578 |
579 | /**
580 | * Class constructor.
581 | *
582 | * @param chartId The id of the chart.
583 | */
584 | public AdvancedBarChart(String chartId) {
585 | super(chartId);
586 | }
587 |
588 | /**
589 | * Gets the value of the chart.
590 | *
591 | * @param valueMap Just an empty map. The only reason it exists is to make your life easier.
592 | * You don't have to create a map yourself!
593 | * @return The value of the chart.
594 | */
595 | public abstract HashMap getValues(HashMap valueMap);
596 |
597 | @Override
598 | protected JSONObject getChartData() {
599 | JSONObject data = new JSONObject();
600 | JSONObject values = new JSONObject();
601 | HashMap map = getValues(new HashMap());
602 | if (map == null || map.isEmpty()) {
603 | // Null = skip the chart
604 | return null;
605 | }
606 | boolean allSkipped = true;
607 | for (Map.Entry entry : map.entrySet()) {
608 | if (entry.getValue().length == 0) {
609 | continue; // Skip this invalid
610 | }
611 | allSkipped = false;
612 | JSONArray categoryValues = new JSONArray();
613 | for (int categoryValue : entry.getValue()) {
614 | categoryValues.add(categoryValue);
615 | }
616 | values.put(entry.getKey(), categoryValues);
617 | }
618 | if (allSkipped) {
619 | // Null = skip the chart
620 | return null;
621 | }
622 | data.put("values", values);
623 | return data;
624 | }
625 |
626 | }
627 |
628 | /**
629 | * Represents a custom simple map chart.
630 | */
631 | public static abstract class SimpleMapChart extends CustomChart {
632 |
633 | /**
634 | * Class constructor.
635 | *
636 | * @param chartId The id of the chart.
637 | */
638 | public SimpleMapChart(String chartId) {
639 | super(chartId);
640 | }
641 |
642 | /**
643 | * Gets the value of the chart.
644 | *
645 | * @return The value of the chart.
646 | */
647 | public abstract Country getValue();
648 |
649 | @Override
650 | protected JSONObject getChartData() {
651 | JSONObject data = new JSONObject();
652 | Country value = getValue();
653 |
654 | if (value == null) {
655 | // Null = skip the chart
656 | return null;
657 | }
658 | data.put("value", value.getCountryIsoTag());
659 | return data;
660 | }
661 |
662 | }
663 |
664 | /**
665 | * Represents a custom advanced map chart.
666 | */
667 | public static abstract class AdvancedMapChart extends CustomChart {
668 |
669 | /**
670 | * Class constructor.
671 | *
672 | * @param chartId The id of the chart.
673 | */
674 | public AdvancedMapChart(String chartId) {
675 | super(chartId);
676 | }
677 |
678 | /**
679 | * Gets the value of the chart.
680 | *
681 | * @param valueMap Just an empty map. The only reason it exists is to make your life easier.
682 | * You don't have to create a map yourself!
683 | * @return The value of the chart.
684 | */
685 | public abstract HashMap getValues(HashMap valueMap);
686 |
687 | @Override
688 | protected JSONObject getChartData() {
689 | JSONObject data = new JSONObject();
690 | JSONObject values = new JSONObject();
691 | HashMap map = getValues(new HashMap());
692 | if (map == null || map.isEmpty()) {
693 | // Null = skip the chart
694 | return null;
695 | }
696 | boolean allSkipped = true;
697 | for (Map.Entry entry : map.entrySet()) {
698 | if (entry.getValue() == 0) {
699 | continue; // Skip this invalid
700 | }
701 | allSkipped = false;
702 | values.put(entry.getKey().getCountryIsoTag(), entry.getValue());
703 | }
704 | if (allSkipped) {
705 | // Null = skip the chart
706 | return null;
707 | }
708 | data.put("values", values);
709 | return data;
710 | }
711 |
712 | }
713 |
714 | /**
715 | * A enum which is used for custom maps.
716 | */
717 | public enum Country {
718 |
719 | /**
720 | * bStats will use the country of the server.
721 | */
722 | AUTO_DETECT("AUTO", "Auto Detected"),
723 |
724 | ANDORRA("AD", "Andorra"),
725 | UNITED_ARAB_EMIRATES("AE", "United Arab Emirates"),
726 | AFGHANISTAN("AF", "Afghanistan"),
727 | ANTIGUA_AND_BARBUDA("AG", "Antigua and Barbuda"),
728 | ANGUILLA("AI", "Anguilla"),
729 | ALBANIA("AL", "Albania"),
730 | ARMENIA("AM", "Armenia"),
731 | NETHERLANDS_ANTILLES("AN", "Netherlands Antilles"),
732 | ANGOLA("AO", "Angola"),
733 | ANTARCTICA("AQ", "Antarctica"),
734 | ARGENTINA("AR", "Argentina"),
735 | AMERICAN_SAMOA("AS", "American Samoa"),
736 | AUSTRIA("AT", "Austria"),
737 | AUSTRALIA("AU", "Australia"),
738 | ARUBA("AW", "Aruba"),
739 | ALAND_ISLANDS("AX", "Åland Islands"),
740 | AZERBAIJAN("AZ", "Azerbaijan"),
741 | BOSNIA_AND_HERZEGOVINA("BA", "Bosnia and Herzegovina"),
742 | BARBADOS("BB", "Barbados"),
743 | BANGLADESH("BD", "Bangladesh"),
744 | BELGIUM("BE", "Belgium"),
745 | BURKINA_FASO("BF", "Burkina Faso"),
746 | BULGARIA("BG", "Bulgaria"),
747 | BAHRAIN("BH", "Bahrain"),
748 | BURUNDI("BI", "Burundi"),
749 | BENIN("BJ", "Benin"),
750 | SAINT_BARTHELEMY("BL", "Saint Barthélemy"),
751 | BERMUDA("BM", "Bermuda"),
752 | BRUNEI("BN", "Brunei"),
753 | BOLIVIA("BO", "Bolivia"),
754 | BONAIRE_SINT_EUSTATIUS_AND_SABA("BQ", "Bonaire, Sint Eustatius and Saba"),
755 | BRAZIL("BR", "Brazil"),
756 | BAHAMAS("BS", "Bahamas"),
757 | BHUTAN("BT", "Bhutan"),
758 | BOUVET_ISLAND("BV", "Bouvet Island"),
759 | BOTSWANA("BW", "Botswana"),
760 | BELARUS("BY", "Belarus"),
761 | BELIZE("BZ", "Belize"),
762 | CANADA("CA", "Canada"),
763 | COCOS_ISLANDS("CC", "Cocos Islands"),
764 | THE_DEMOCRATIC_REPUBLIC_OF_CONGO("CD", "The Democratic Republic Of Congo"),
765 | CENTRAL_AFRICAN_REPUBLIC("CF", "Central African Republic"),
766 | CONGO("CG", "Congo"),
767 | SWITZERLAND("CH", "Switzerland"),
768 | COTE_D_IVOIRE("CI", "Côte d'Ivoire"),
769 | COOK_ISLANDS("CK", "Cook Islands"),
770 | CHILE("CL", "Chile"),
771 | CAMEROON("CM", "Cameroon"),
772 | CHINA("CN", "China"),
773 | COLOMBIA("CO", "Colombia"),
774 | COSTA_RICA("CR", "Costa Rica"),
775 | CUBA("CU", "Cuba"),
776 | CAPE_VERDE("CV", "Cape Verde"),
777 | CURACAO("CW", "Curaçao"),
778 | CHRISTMAS_ISLAND("CX", "Christmas Island"),
779 | CYPRUS("CY", "Cyprus"),
780 | CZECH_REPUBLIC("CZ", "Czech Republic"),
781 | GERMANY("DE", "Germany"),
782 | DJIBOUTI("DJ", "Djibouti"),
783 | DENMARK("DK", "Denmark"),
784 | DOMINICA("DM", "Dominica"),
785 | DOMINICAN_REPUBLIC("DO", "Dominican Republic"),
786 | ALGERIA("DZ", "Algeria"),
787 | ECUADOR("EC", "Ecuador"),
788 | ESTONIA("EE", "Estonia"),
789 | EGYPT("EG", "Egypt"),
790 | WESTERN_SAHARA("EH", "Western Sahara"),
791 | ERITREA("ER", "Eritrea"),
792 | SPAIN("ES", "Spain"),
793 | ETHIOPIA("ET", "Ethiopia"),
794 | FINLAND("FI", "Finland"),
795 | FIJI("FJ", "Fiji"),
796 | FALKLAND_ISLANDS("FK", "Falkland Islands"),
797 | MICRONESIA("FM", "Micronesia"),
798 | FAROE_ISLANDS("FO", "Faroe Islands"),
799 | FRANCE("FR", "France"),
800 | GABON("GA", "Gabon"),
801 | UNITED_KINGDOM("GB", "United Kingdom"),
802 | GRENADA("GD", "Grenada"),
803 | GEORGIA("GE", "Georgia"),
804 | FRENCH_GUIANA("GF", "French Guiana"),
805 | GUERNSEY("GG", "Guernsey"),
806 | GHANA("GH", "Ghana"),
807 | GIBRALTAR("GI", "Gibraltar"),
808 | GREENLAND("GL", "Greenland"),
809 | GAMBIA("GM", "Gambia"),
810 | GUINEA("GN", "Guinea"),
811 | GUADELOUPE("GP", "Guadeloupe"),
812 | EQUATORIAL_GUINEA("GQ", "Equatorial Guinea"),
813 | GREECE("GR", "Greece"),
814 | SOUTH_GEORGIA_AND_THE_SOUTH_SANDWICH_ISLANDS("GS", "South Georgia And The South Sandwich Islands"),
815 | GUATEMALA("GT", "Guatemala"),
816 | GUAM("GU", "Guam"),
817 | GUINEA_BISSAU("GW", "Guinea-Bissau"),
818 | GUYANA("GY", "Guyana"),
819 | HONG_KONG("HK", "Hong Kong"),
820 | HEARD_ISLAND_AND_MCDONALD_ISLANDS("HM", "Heard Island And McDonald Islands"),
821 | HONDURAS("HN", "Honduras"),
822 | CROATIA("HR", "Croatia"),
823 | HAITI("HT", "Haiti"),
824 | HUNGARY("HU", "Hungary"),
825 | INDONESIA("ID", "Indonesia"),
826 | IRELAND("IE", "Ireland"),
827 | ISRAEL("IL", "Israel"),
828 | ISLE_OF_MAN("IM", "Isle Of Man"),
829 | INDIA("IN", "India"),
830 | BRITISH_INDIAN_OCEAN_TERRITORY("IO", "British Indian Ocean Territory"),
831 | IRAQ("IQ", "Iraq"),
832 | IRAN("IR", "Iran"),
833 | ICELAND("IS", "Iceland"),
834 | ITALY("IT", "Italy"),
835 | JERSEY("JE", "Jersey"),
836 | JAMAICA("JM", "Jamaica"),
837 | JORDAN("JO", "Jordan"),
838 | JAPAN("JP", "Japan"),
839 | KENYA("KE", "Kenya"),
840 | KYRGYZSTAN("KG", "Kyrgyzstan"),
841 | CAMBODIA("KH", "Cambodia"),
842 | KIRIBATI("KI", "Kiribati"),
843 | COMOROS("KM", "Comoros"),
844 | SAINT_KITTS_AND_NEVIS("KN", "Saint Kitts And Nevis"),
845 | NORTH_KOREA("KP", "North Korea"),
846 | SOUTH_KOREA("KR", "South Korea"),
847 | KUWAIT("KW", "Kuwait"),
848 | CAYMAN_ISLANDS("KY", "Cayman Islands"),
849 | KAZAKHSTAN("KZ", "Kazakhstan"),
850 | LAOS("LA", "Laos"),
851 | LEBANON("LB", "Lebanon"),
852 | SAINT_LUCIA("LC", "Saint Lucia"),
853 | LIECHTENSTEIN("LI", "Liechtenstein"),
854 | SRI_LANKA("LK", "Sri Lanka"),
855 | LIBERIA("LR", "Liberia"),
856 | LESOTHO("LS", "Lesotho"),
857 | LITHUANIA("LT", "Lithuania"),
858 | LUXEMBOURG("LU", "Luxembourg"),
859 | LATVIA("LV", "Latvia"),
860 | LIBYA("LY", "Libya"),
861 | MOROCCO("MA", "Morocco"),
862 | MONACO("MC", "Monaco"),
863 | MOLDOVA("MD", "Moldova"),
864 | MONTENEGRO("ME", "Montenegro"),
865 | SAINT_MARTIN("MF", "Saint Martin"),
866 | MADAGASCAR("MG", "Madagascar"),
867 | MARSHALL_ISLANDS("MH", "Marshall Islands"),
868 | MACEDONIA("MK", "Macedonia"),
869 | MALI("ML", "Mali"),
870 | MYANMAR("MM", "Myanmar"),
871 | MONGOLIA("MN", "Mongolia"),
872 | MACAO("MO", "Macao"),
873 | NORTHERN_MARIANA_ISLANDS("MP", "Northern Mariana Islands"),
874 | MARTINIQUE("MQ", "Martinique"),
875 | MAURITANIA("MR", "Mauritania"),
876 | MONTSERRAT("MS", "Montserrat"),
877 | MALTA("MT", "Malta"),
878 | MAURITIUS("MU", "Mauritius"),
879 | MALDIVES("MV", "Maldives"),
880 | MALAWI("MW", "Malawi"),
881 | MEXICO("MX", "Mexico"),
882 | MALAYSIA("MY", "Malaysia"),
883 | MOZAMBIQUE("MZ", "Mozambique"),
884 | NAMIBIA("NA", "Namibia"),
885 | NEW_CALEDONIA("NC", "New Caledonia"),
886 | NIGER("NE", "Niger"),
887 | NORFOLK_ISLAND("NF", "Norfolk Island"),
888 | NIGERIA("NG", "Nigeria"),
889 | NICARAGUA("NI", "Nicaragua"),
890 | NETHERLANDS("NL", "Netherlands"),
891 | NORWAY("NO", "Norway"),
892 | NEPAL("NP", "Nepal"),
893 | NAURU("NR", "Nauru"),
894 | NIUE("NU", "Niue"),
895 | NEW_ZEALAND("NZ", "New Zealand"),
896 | OMAN("OM", "Oman"),
897 | PANAMA("PA", "Panama"),
898 | PERU("PE", "Peru"),
899 | FRENCH_POLYNESIA("PF", "French Polynesia"),
900 | PAPUA_NEW_GUINEA("PG", "Papua New Guinea"),
901 | PHILIPPINES("PH", "Philippines"),
902 | PAKISTAN("PK", "Pakistan"),
903 | POLAND("PL", "Poland"),
904 | SAINT_PIERRE_AND_MIQUELON("PM", "Saint Pierre And Miquelon"),
905 | PITCAIRN("PN", "Pitcairn"),
906 | PUERTO_RICO("PR", "Puerto Rico"),
907 | PALESTINE("PS", "Palestine"),
908 | PORTUGAL("PT", "Portugal"),
909 | PALAU("PW", "Palau"),
910 | PARAGUAY("PY", "Paraguay"),
911 | QATAR("QA", "Qatar"),
912 | REUNION("RE", "Reunion"),
913 | ROMANIA("RO", "Romania"),
914 | SERBIA("RS", "Serbia"),
915 | RUSSIA("RU", "Russia"),
916 | RWANDA("RW", "Rwanda"),
917 | SAUDI_ARABIA("SA", "Saudi Arabia"),
918 | SOLOMON_ISLANDS("SB", "Solomon Islands"),
919 | SEYCHELLES("SC", "Seychelles"),
920 | SUDAN("SD", "Sudan"),
921 | SWEDEN("SE", "Sweden"),
922 | SINGAPORE("SG", "Singapore"),
923 | SAINT_HELENA("SH", "Saint Helena"),
924 | SLOVENIA("SI", "Slovenia"),
925 | SVALBARD_AND_JAN_MAYEN("SJ", "Svalbard And Jan Mayen"),
926 | SLOVAKIA("SK", "Slovakia"),
927 | SIERRA_LEONE("SL", "Sierra Leone"),
928 | SAN_MARINO("SM", "San Marino"),
929 | SENEGAL("SN", "Senegal"),
930 | SOMALIA("SO", "Somalia"),
931 | SURINAME("SR", "Suriname"),
932 | SOUTH_SUDAN("SS", "South Sudan"),
933 | SAO_TOME_AND_PRINCIPE("ST", "Sao Tome And Principe"),
934 | EL_SALVADOR("SV", "El Salvador"),
935 | SINT_MAARTEN_DUTCH_PART("SX", "Sint Maarten (Dutch part)"),
936 | SYRIA("SY", "Syria"),
937 | SWAZILAND("SZ", "Swaziland"),
938 | TURKS_AND_CAICOS_ISLANDS("TC", "Turks And Caicos Islands"),
939 | CHAD("TD", "Chad"),
940 | FRENCH_SOUTHERN_TERRITORIES("TF", "French Southern Territories"),
941 | TOGO("TG", "Togo"),
942 | THAILAND("TH", "Thailand"),
943 | TAJIKISTAN("TJ", "Tajikistan"),
944 | TOKELAU("TK", "Tokelau"),
945 | TIMOR_LESTE("TL", "Timor-Leste"),
946 | TURKMENISTAN("TM", "Turkmenistan"),
947 | TUNISIA("TN", "Tunisia"),
948 | TONGA("TO", "Tonga"),
949 | TURKEY("TR", "Turkey"),
950 | TRINIDAD_AND_TOBAGO("TT", "Trinidad and Tobago"),
951 | TUVALU("TV", "Tuvalu"),
952 | TAIWAN("TW", "Taiwan"),
953 | TANZANIA("TZ", "Tanzania"),
954 | UKRAINE("UA", "Ukraine"),
955 | UGANDA("UG", "Uganda"),
956 | UNITED_STATES_MINOR_OUTLYING_ISLANDS("UM", "United States Minor Outlying Islands"),
957 | UNITED_STATES("US", "United States"),
958 | URUGUAY("UY", "Uruguay"),
959 | UZBEKISTAN("UZ", "Uzbekistan"),
960 | VATICAN("VA", "Vatican"),
961 | SAINT_VINCENT_AND_THE_GRENADINES("VC", "Saint Vincent And The Grenadines"),
962 | VENEZUELA("VE", "Venezuela"),
963 | BRITISH_VIRGIN_ISLANDS("VG", "British Virgin Islands"),
964 | U_S__VIRGIN_ISLANDS("VI", "U.S. Virgin Islands"),
965 | VIETNAM("VN", "Vietnam"),
966 | VANUATU("VU", "Vanuatu"),
967 | WALLIS_AND_FUTUNA("WF", "Wallis And Futuna"),
968 | SAMOA("WS", "Samoa"),
969 | YEMEN("YE", "Yemen"),
970 | MAYOTTE("YT", "Mayotte"),
971 | SOUTH_AFRICA("ZA", "South Africa"),
972 | ZAMBIA("ZM", "Zambia"),
973 | ZIMBABWE("ZW", "Zimbabwe");
974 |
975 | private String isoTag;
976 | private String name;
977 |
978 | Country(String isoTag, String name) {
979 | this.isoTag = isoTag;
980 | this.name = name;
981 | }
982 |
983 | /**
984 | * Gets the name of the country.
985 | *
986 | * @return The name of the country.
987 | */
988 | public String getCountryName() {
989 | return name;
990 | }
991 |
992 | /**
993 | * Gets the iso tag of the country.
994 | *
995 | * @return The iso tag of the country.
996 | */
997 | public String getCountryIsoTag() {
998 | return isoTag;
999 | }
1000 |
1001 | /**
1002 | * Gets a country by it's iso tag.
1003 | *
1004 | * @param isoTag The iso tag of the county.
1005 | * @return The country with the given iso tag or null if unknown.
1006 | */
1007 | public static Country byIsoTag(String isoTag) {
1008 | for (Country country : Country.values()) {
1009 | if (country.getCountryIsoTag().equals(isoTag)) {
1010 | return country;
1011 | }
1012 | }
1013 | return null;
1014 | }
1015 |
1016 | /**
1017 | * Gets a country by a locale.
1018 | *
1019 | * @param locale The locale.
1020 | * @return The country from the giben locale or null if unknown country or
1021 | * if the locale does not contain a country.
1022 | */
1023 | public static Country byLocale(Locale locale) {
1024 | return byIsoTag(locale.getCountry());
1025 | }
1026 |
1027 | }
1028 |
1029 | }
--------------------------------------------------------------------------------