├── .gitignore ├── core ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── coalesce │ │ ├── Core.java │ │ ├── CoreConfig.java │ │ ├── chat │ │ ├── CoFormatter.java │ │ ├── FontInfo.java │ │ └── TextComponent.java │ │ ├── command │ │ ├── CoCommand.java │ │ ├── CommandBuilder.java │ │ ├── CommandContext.java │ │ ├── CommandExecutor.java │ │ ├── CommandRegister.java │ │ ├── base │ │ │ ├── AbstractCommandContext.java │ │ │ ├── AbstractTabContext.java │ │ │ ├── ICommandContext.java │ │ │ └── ITabContext.java │ │ └── tabcomplete │ │ │ ├── TabContext.java │ │ │ └── TabExecutor.java │ │ ├── config │ │ ├── ConfigFormat.java │ │ ├── IConfig.java │ │ ├── IEntry.java │ │ ├── ISection.java │ │ ├── common │ │ │ └── Section.java │ │ ├── json │ │ │ ├── JsonConfig.java │ │ │ └── JsonEntry.java │ │ └── yml │ │ │ ├── YamlConfig.java │ │ │ └── YamlEntry.java │ │ ├── gui │ │ ├── Gui.java │ │ ├── ItemBuilder.java │ │ └── PlayerGui.java │ │ ├── http │ │ └── CoHTTP.java │ │ ├── plugin │ │ ├── CoLogger.java │ │ ├── CoModule.java │ │ ├── CoPlugin.java │ │ └── PluginUtil.java │ │ ├── scoreboard │ │ ├── CoScoreboard.java │ │ ├── PlayerScoreboard.java │ │ └── StaticScoreboard.java │ │ └── updater │ │ ├── AutoUpdateThread.java │ │ └── UpdateCheck.java │ └── resources │ └── plugin.yml ├── examples ├── ExampleCoHTTP.java ├── ExampleCommand.java ├── ExampleGui.java ├── ExamplePlayerCoScoreboard.java ├── ExampleStaticCoScoreboard.java └── ExampleYamlConfig.java └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | out 2 | gen 3 | 4 | ### Intellij ### 5 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm 6 | 7 | *.iml 8 | 9 | ## Directory-based project format: 10 | .idea/ 11 | # if you remove the above rule, at least ignore the following: 12 | 13 | # User-specific stuff: 14 | # .idea/workspace.xml 15 | # .idea/tasks.xml 16 | # .idea/dictionaries 17 | # .idea/shelf 18 | 19 | # Sensitive or high-churn files: 20 | # .idea/dataSources.ids 21 | # .idea/dataSources.xml 22 | # .idea/sqlDataSources.xml 23 | # .idea/dynamic.xml 24 | # .idea/uiDesigner.xml 25 | 26 | # Gradle: 27 | # .idea/gradle.xml 28 | # .idea/libraries 29 | 30 | # Mongo Explorer plugin: 31 | # .idea/mongoSettings.xml 32 | 33 | ## File-based project format: 34 | *.ipr 35 | *.iws 36 | 37 | ## Plugin-specific files: 38 | 39 | # IntelliJ 40 | /out/ 41 | 42 | # mpeltonen/sbt-idea plugin 43 | .idea_modules/ 44 | 45 | # JIRA plugin 46 | atlassian-ide-plugin.xml 47 | 48 | # Crashlytics plugin (for Android Studio and IntelliJ) 49 | com_crashlytics_export_strings.xml 50 | crashlytics.properties 51 | crashlytics-build.properties 52 | fabric.properties 53 | 54 | 55 | ### Java ### 56 | *.class 57 | 58 | # Mobile Tools for Java (J2ME) 59 | .mtj.tmp/ 60 | 61 | # Package Files # 62 | # *.jar 63 | *.war 64 | *.ear 65 | 66 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 67 | hs_err_pid* 68 | 69 | 70 | ### Maven ### 71 | target/ 72 | jars/ 73 | docs/ 74 | pom.xml.tag 75 | pom.xml.releaseBackup 76 | pom.xml.versionsBackup 77 | pom.xml.next 78 | release.properties 79 | dependency-reduced-pom.xml 80 | buildNumber.properties 81 | .mvn/timing.properties 82 | 83 | 84 | ### Eclipse ### 85 | *.pydevproject 86 | .metadata 87 | .gradle 88 | bin/ 89 | tmp/ 90 | *.tmp 91 | *.bak 92 | *.swp 93 | *~.nib 94 | local.properties 95 | .settings/ 96 | .loadpath 97 | 98 | # Eclipse Core 99 | .project 100 | 101 | # External tool builders 102 | .externalToolBuilders/ 103 | 104 | # Locally stored "Eclipse launch configurations" 105 | *.launch 106 | 107 | # CDT-specific 108 | .cproject 109 | 110 | # JDT-specific (Eclipse Java Development Tools) 111 | .classpath 112 | 113 | # Java annotation processor (APT) 114 | .factorypath 115 | 116 | # PDT-specific 117 | .buildpath 118 | 119 | # sbteclipse plugin 120 | .target 121 | 122 | # TeXlipse plugin 123 | .texlipse 124 | 125 | # STS (Spring Tool Suite) 126 | .springBeans 127 | plugins/out/ -------------------------------------------------------------------------------- /core/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | parent 8 | com.coalesce 9 | 1.0 10 | 11 | 12 | CoalesceCore 13 | 1.0.1 14 | jar 15 | 16 | 17 | 18 | 19 | org.jetbrains 20 | annotations 21 | 15.0 22 | compile 23 | 24 | 25 | 26 | org.projectlombok 27 | lombok 28 | 1.16.16 29 | compile 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /core/src/main/java/com/coalesce/Core.java: -------------------------------------------------------------------------------- 1 | package com.coalesce; 2 | 3 | import com.coalesce.plugin.CoPlugin; 4 | 5 | import static org.bukkit.plugin.ServicePriority.Normal; 6 | 7 | public class Core extends CoPlugin { 8 | 9 | private static Core instance; 10 | private CoreConfig config; 11 | 12 | @Override 13 | public void onPluginEnable() { 14 | 15 | getServer().getServicesManager().register(Core.class, this, this, Normal); 16 | 17 | this.config = new CoreConfig(this); 18 | 19 | //TODO: Remove this 20 | updateCheck("Project-Coalesce", "Core", true); //This is an example, this will be changed back once we get the updater working 21 | 22 | } 23 | 24 | @Override 25 | public void onPluginDisable() { 26 | instance = null; 27 | } 28 | 29 | /** 30 | * Grabs the instance of the core. 31 | * Make sure you don't call this before nor after {@link #onPluginDisable()}. 32 | * 33 | * @return The core instance. 34 | */ 35 | public static Core getInstance() { 36 | return instance; 37 | } 38 | 39 | /** 40 | * Gets the core configuration. 41 | * 42 | * @return The core config. 43 | */ 44 | public CoreConfig getCoreConfig() { 45 | return config; 46 | } 47 | 48 | private M checkCoreEnabled(M instance) { 49 | if (!isEnabled()) { 50 | throw new IllegalStateException("Core plugin is not enabled"); 51 | } 52 | return instance; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /core/src/main/java/com/coalesce/CoreConfig.java: -------------------------------------------------------------------------------- 1 | package com.coalesce; 2 | 3 | import com.coalesce.config.yml.YamlConfig; 4 | import com.coalesce.plugin.CoPlugin; 5 | 6 | public final class CoreConfig extends YamlConfig { 7 | 8 | protected CoreConfig(CoPlugin plugin) { 9 | super("config", plugin); 10 | addEntry("log-download-process", true); 11 | } 12 | 13 | /** 14 | * Checks whether to log download process for plugin updates. 15 | * 16 | * @return True if download processes are logged, false otherwise. 17 | */ 18 | public boolean logDLProcess() { 19 | return getBoolean("log-download-process"); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /core/src/main/java/com/coalesce/chat/CoFormatter.java: -------------------------------------------------------------------------------- 1 | package com.coalesce.chat; 2 | 3 | import com.coalesce.plugin.CoPlugin; 4 | import org.bukkit.ChatColor; 5 | 6 | import static org.bukkit.ChatColor.*; 7 | 8 | public final class CoFormatter { 9 | private String prefix; 10 | 11 | //Constants 12 | private final static int CENTER_PX = 154; 13 | 14 | public CoFormatter() { 15 | this.prefix = GRAY + "[" + AQUA + "CoalesceCore" + GRAY + "]" + RESET; 16 | } 17 | 18 | public CoFormatter(CoPlugin plugin) { 19 | this.prefix = GRAY + "[" + WHITE + plugin.getDisplayName() + GRAY + "]" + RESET; 20 | } 21 | 22 | public String format(String message) { 23 | return prefix + " " + message; 24 | } 25 | 26 | /** 27 | * Centers a string for chat. 28 | * 29 | * @param message The message to center in chat. 30 | * @return A centered string. 31 | */ 32 | public String centerString(String message) { 33 | if (message == null || message.equals("")) { 34 | return ""; 35 | } 36 | message = ChatColor.translateAlternateColorCodes('&', message); 37 | 38 | int messagePxSize = getWidth(message); 39 | 40 | int halvedMessageSize = messagePxSize / 2; 41 | int toCompensate = CENTER_PX - halvedMessageSize; 42 | int spaceLength = FontInfo.getCharSize(' '); 43 | int compensated = 0; 44 | StringBuilder sb = new StringBuilder(); 45 | while (compensated < toCompensate) { 46 | sb.append(" "); 47 | compensated += spaceLength; 48 | } 49 | return sb.toString() + message; 50 | } 51 | 52 | /** 53 | * Gets the width of the string message. 54 | * 55 | * @param message The message to get the width of. 56 | * @return The width (in pixels) of the string in minecraft. 57 | */ 58 | public int getWidth(String message) { 59 | int messagePxSize = 0; 60 | boolean previousCode = false; 61 | boolean isBold = false; 62 | 63 | for (char c : message.toCharArray()) { 64 | if (c == '\u00A7') { 65 | previousCode = true; 66 | continue; 67 | } else if (previousCode == true) { 68 | previousCode = false; 69 | if (c == 'l' || c == 'L') { 70 | isBold = true; 71 | continue; 72 | } else { 73 | isBold = false; 74 | } 75 | } else { 76 | messagePxSize += FontInfo.getCharSize(c, isBold); 77 | } 78 | } 79 | return messagePxSize; 80 | } 81 | 82 | /** 83 | * Alternate color codes in a string, if the chars variable is null then it will use a rainbow effect. 84 | * If string already contains color codes, they will be stripped. 85 | * 86 | * @param str String to add color to. 87 | * @param chars Colors that will be alternated in the string, if null then its rainbow. 88 | * @return Changed String 89 | */ 90 | public String rainbowifyString(String str, char... chars) { 91 | str = ChatColor.stripColor(str); 92 | if (chars == null || chars.length == 0) { 93 | chars = new char[]{'c', '6', 'e', 'a', 'b', '3', 'd'}; 94 | } 95 | 96 | int index = 0; 97 | String returnValue = ""; 98 | for (char c : str.toCharArray()) { 99 | returnValue += "&" + chars[index] + c; 100 | index++; 101 | if (index == chars.length) { 102 | index = 0; 103 | } 104 | } 105 | 106 | return ChatColor.translateAlternateColorCodes('&', returnValue); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /core/src/main/java/com/coalesce/chat/FontInfo.java: -------------------------------------------------------------------------------- 1 | package com.coalesce.chat; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | public class FontInfo { 7 | 8 | private static Map charSizes; 9 | 10 | /** 11 | * Gets the size of a char and ignores if its bolded or not. 12 | * 13 | * @param c The char to get the size of. 14 | * @return The char size. 15 | */ 16 | public static int getCharSize(char c) { 17 | return getCharSize(c, false); 18 | } 19 | 20 | /** 21 | * Returns the size of a character according to our character sizes hashmap. 22 | * 23 | * @param c The character to get the size of. 24 | * @param bold If this character is bolded or not. 25 | * @return The size of this character. 26 | */ 27 | public static int getCharSize(char c, boolean bold) { 28 | 29 | if (charSizes == null) { 30 | initSizes(); 31 | } 32 | 33 | int size = charSizes.get(c); 34 | if (bold && c != ' ') { 35 | size += 1; 36 | } 37 | 38 | return size; 39 | } 40 | 41 | private static void initSizes() { 42 | charSizes = new HashMap<>(); 43 | charSizes.put('A', 5); 44 | charSizes.put('a', 5); 45 | charSizes.put('B', 5); 46 | charSizes.put('b', 5); 47 | charSizes.put('C', 5); 48 | charSizes.put('c', 5); 49 | charSizes.put('D', 5); 50 | charSizes.put('d', 5); 51 | charSizes.put('E', 5); 52 | charSizes.put('e', 5); 53 | charSizes.put('F', 5); 54 | charSizes.put('f', 4); 55 | charSizes.put('G', 5); 56 | charSizes.put('g', 5); 57 | charSizes.put('H', 5); 58 | charSizes.put('h', 5); 59 | charSizes.put('I', 3); 60 | charSizes.put('i', 1); 61 | charSizes.put('J', 5); 62 | charSizes.put('j', 5); 63 | charSizes.put('K', 5); 64 | charSizes.put('k', 4); 65 | charSizes.put('L', 5); 66 | charSizes.put('l', 1); 67 | charSizes.put('M', 5); 68 | charSizes.put('m', 5); 69 | charSizes.put('N', 5); 70 | charSizes.put('n', 5); 71 | charSizes.put('O', 5); 72 | charSizes.put('o', 5); 73 | charSizes.put('P', 5); 74 | charSizes.put('p', 5); 75 | charSizes.put('Q', 5); 76 | charSizes.put('q', 5); 77 | charSizes.put('R', 5); 78 | charSizes.put('r', 5); 79 | charSizes.put('S', 5); 80 | charSizes.put('s', 5); 81 | charSizes.put('T', 5); 82 | charSizes.put('t', 4); 83 | charSizes.put('U', 5); 84 | charSizes.put('u', 5); 85 | charSizes.put('V', 5); 86 | charSizes.put('v', 5); 87 | charSizes.put('W', 5); 88 | charSizes.put('w', 5); 89 | charSizes.put('X', 5); 90 | charSizes.put('x', 5); 91 | charSizes.put('Y', 5); 92 | charSizes.put('y', 5); 93 | charSizes.put('Z', 5); 94 | charSizes.put('z', 5); 95 | charSizes.put('1', 5); 96 | charSizes.put('2', 5); 97 | charSizes.put('3', 5); 98 | charSizes.put('4', 5); 99 | charSizes.put('5', 5); 100 | charSizes.put('6', 5); 101 | charSizes.put('7', 5); 102 | charSizes.put('8', 5); 103 | charSizes.put('9', 5); 104 | charSizes.put('0', 5); 105 | charSizes.put('!', 1); 106 | charSizes.put('@', 6); 107 | charSizes.put('#', 5); 108 | charSizes.put('$', 5); 109 | charSizes.put('%', 5); 110 | charSizes.put('^', 5); 111 | charSizes.put('&', 5); 112 | charSizes.put('*', 5); 113 | charSizes.put('(', 4); 114 | charSizes.put(')', 4); 115 | charSizes.put('-', 5); 116 | charSizes.put('_', 5); 117 | charSizes.put('+', 5); 118 | charSizes.put('=', 5); 119 | charSizes.put('{', 4); 120 | charSizes.put('}', 4); 121 | charSizes.put('[', 3); 122 | charSizes.put(']', 3); 123 | charSizes.put(':', 1); 124 | charSizes.put(';', 1); 125 | charSizes.put('"', 3); 126 | charSizes.put('\'', 1); 127 | charSizes.put('<', 4); 128 | charSizes.put('>', 4); 129 | charSizes.put('?', 5); 130 | charSizes.put('/', 5); 131 | charSizes.put('\\', 5); 132 | charSizes.put('|', 1); 133 | charSizes.put('~', 5); 134 | charSizes.put('`', 2); 135 | charSizes.put('.', 1); 136 | charSizes.put(',', 1); 137 | charSizes.put(' ', 3); 138 | charSizes.put('a', 4); 139 | } 140 | 141 | } 142 | -------------------------------------------------------------------------------- /core/src/main/java/com/coalesce/chat/TextComponent.java: -------------------------------------------------------------------------------- 1 | package com.coalesce.chat; 2 | 3 | public final class TextComponent { 4 | 5 | private final ClickAction clickAction; 6 | private final String clickActionValue; 7 | private final String hoverValue; 8 | private final String text; 9 | 10 | private TextComponent(Builder builder) { 11 | this.text = builder.text; 12 | this.hoverValue = builder.hoverValue; 13 | this.clickAction = builder.clickAction; 14 | this.clickActionValue = builder.clickActionValue; 15 | } 16 | 17 | public String getRawText() { 18 | return text; 19 | } 20 | 21 | public String getHoverValue() { 22 | return hoverValue; 23 | } 24 | 25 | public String getClickActionValue() { 26 | return clickActionValue; 27 | } 28 | 29 | public ClickAction getClickAction() { 30 | return clickAction; 31 | } 32 | 33 | @Override 34 | public String toString() { 35 | StringBuilder sb = new StringBuilder(); 36 | sb.append("{\"text\":\"" + text + "\""); 37 | if (clickAction != ClickAction.NONE) { 38 | sb.append(",\"clickEvent\":{\"action\":\""); 39 | sb.append(clickAction.getAction()); 40 | sb.append("\",\"value\":\"" + clickActionValue + "\"}"); 41 | } 42 | 43 | if (hoverValue != null && hoverValue != "") { 44 | sb.append(",\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"\",\"extra\":[{\"text\":\"" + hoverValue + "\"}]}}"); 45 | } 46 | 47 | sb.append("}"); 48 | return sb.toString(); 49 | } 50 | 51 | public static class Builder { 52 | 53 | private ClickAction clickAction = ClickAction.NONE; 54 | private String clickActionValue = ""; 55 | private String hoverValue = ""; 56 | private String text = ""; 57 | 58 | public Builder text(String text) { 59 | this.text = text; 60 | return this; 61 | } 62 | 63 | public Builder hover(String hoverValue) { 64 | this.hoverValue = hoverValue; 65 | return this; 66 | } 67 | 68 | public Builder clickActionValue(String clickActionValue) { 69 | this.clickActionValue = clickActionValue; 70 | return this; 71 | } 72 | 73 | public Builder clickAction(ClickAction clickAction) { 74 | this.clickAction = clickAction; 75 | return this; 76 | } 77 | 78 | public TextComponent build() { 79 | return new TextComponent(this); 80 | } 81 | 82 | } 83 | 84 | public enum ClickAction { 85 | OPEN_URL("open_url"), 86 | OPEN_FILE("open_file"), 87 | RUN_COMMAND("run_command"), 88 | SUGGEST_COMMAND("suggest_command"), 89 | CHANGE_PAGE("change_page"), 90 | NONE("none"); 91 | 92 | private final String action; 93 | 94 | ClickAction(String action) { 95 | this.action = action; 96 | } 97 | 98 | public String getAction() { 99 | return action; 100 | } 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /core/src/main/java/com/coalesce/command/CoCommand.java: -------------------------------------------------------------------------------- 1 | package com.coalesce.command; 2 | 3 | import com.coalesce.command.base.ICommandContext; 4 | import com.coalesce.command.base.ITabContext; 5 | import com.coalesce.command.tabcomplete.TabContext; 6 | import com.coalesce.command.tabcomplete.TabExecutor; 7 | import com.coalesce.plugin.CoPlugin; 8 | import com.google.common.collect.Lists; 9 | import org.bukkit.ChatColor; 10 | import org.bukkit.command.CommandSender; 11 | 12 | import java.util.ArrayList; 13 | import java.util.HashSet; 14 | import java.util.List; 15 | import java.util.Set; 16 | import java.util.function.Predicate; 17 | import java.util.stream.Collectors; 18 | import java.util.stream.Stream; 19 | 20 | public final class CoCommand { 21 | 22 | private Predicate permissionCheck; 23 | private boolean requiresOperator = false; 24 | private CommandExecutor commandExecutor; 25 | private boolean playerOnly = false; 26 | private String description = ""; 27 | private Set children; 28 | private TabExecutor tabExecutor; 29 | private final CoPlugin plugin; 30 | private Set aliases; 31 | private String usage = ""; 32 | private String permission; 33 | private int minArgs = -1; 34 | private int maxArgs = -1; 35 | private String name; 36 | 37 | public CoCommand(CoPlugin plugin, String name) { 38 | this.plugin = plugin; 39 | this.name = name; 40 | 41 | //Defaults 42 | aliases = new HashSet<>(); 43 | children = new HashSet<>(); 44 | } 45 | 46 | /** 47 | * The main execute method for a CoCommand. 48 | * 49 | * @param context The command context. 50 | */ 51 | public void execute(ICommandContext context) { 52 | 53 | //If there were no child commands that matched the context 54 | if (!checkChildren(context)) { 55 | 56 | //Check if console is trying to use a player only command 57 | if (context.isConsole() && playerOnly) { 58 | context.pluginMessage(ChatColor.RED + "This command can only be used by players!"); 59 | return; 60 | } 61 | 62 | //Check if the sender has perms 63 | if (permission != null && !context.getSender().hasPermission(permission)) { 64 | context.pluginMessage(ChatColor.RED + "You do not have permission for this command! Required Permission: " + ChatColor.GRAY + permission); 65 | return; 66 | } 67 | if (requiresOperator && !context.getSender().isOp()) { 68 | context.pluginMessage(ChatColor.RED + "You do not have permission for this command! Required Permission: " + ChatColor.GRAY + "OPERATOR"); 69 | return; 70 | } 71 | if (permissionCheck != null && !permissionCheck.test(context.getSender())) { 72 | context.pluginMessage(ChatColor.RED + "You do not have permission for this command!"); 73 | return; 74 | } 75 | 76 | //Check for too many args 77 | if (context.getArgs().size() > maxArgs && maxArgs > -1) { 78 | context.pluginMessage(ChatColor.RED + "Too many arguments!" + " Input: " + ChatColor.GRAY + context.getArgs().size() + ChatColor.RED + " Max: " + ChatColor.GRAY + maxArgs); 79 | if (usage != null) { 80 | context.pluginMessage(ChatColor.GRAY + "Correct Usage: " + usage); 81 | } 82 | return; 83 | } 84 | 85 | //Check for not enough args 86 | if (context.getArgs().size() < minArgs && minArgs > -1) { 87 | context.pluginMessage(ChatColor.RED + "Not enough arguments!" + " Input: " + ChatColor.GRAY + context.getArgs().size() + ChatColor.RED + " Min: " + ChatColor.GRAY + minArgs); 88 | if (usage != null) { 89 | context.pluginMessage(ChatColor.GRAY + "Correct Usage: " + usage); 90 | } 91 | return; 92 | } 93 | 94 | //Everything seems okay, so lets execute the command 95 | commandExecutor.execute((CommandContext)context); 96 | } 97 | } 98 | 99 | /** 100 | * To execute the TabCompleter 101 | *

102 | *

103 | *

Just a note, if the command has child commands and a custom tab completer exists, you will need to write in the implementation for the completion

104 | * 105 | * @param tabContext The CompleteContext 106 | */ 107 | public List completer(ITabContext tabContext) { 108 | List sub = Lists.newArrayList(); 109 | if (tabExecutor == null) { //If no executor exists for this command it defaults into looking for the command children 110 | if (tabContext.getCommandChildren().isEmpty()) { //If no children exist then there will be no tab complete. 111 | return null; 112 | } 113 | if (tabContext.getLength() == 0) { 114 | List children = new ArrayList<>(); 115 | tabContext.getCommandChildren().forEach(child -> children.add(child.getName())); 116 | return children; //List of children commands. 117 | } 118 | return null; //Dont want the child commands going past argument 1 119 | } 120 | tabExecutor.complete((TabContext)tabContext); 121 | for (String completion : tabContext.currentPossibleCompletion()) { 122 | if (completion.toLowerCase().startsWith(tabContext.getContext().argAt(tabContext.getContext().getArgs().size() - 1))) { 123 | sub.add(completion); 124 | } 125 | } 126 | return sub; //Custom completer. 127 | } 128 | 129 | /** 130 | * This method checks if any children match the command context. 131 | * If one is found, the child is executed. 132 | * 133 | * @param context The command context 134 | * @return True if a child was found, false otherwise 135 | */ 136 | private boolean checkChildren(ICommandContext context) { 137 | if (children.isEmpty()) { 138 | return false; 139 | } 140 | if (!context.hasArgs()) { 141 | return false; 142 | } 143 | for (CoCommand childCommand : children) { 144 | //This is safe because we know that there is at least one argument 145 | if (childCommand.matchesCommand(context.argAt(0))) { 146 | 147 | context.getArgs().remove(0); 148 | childCommand.execute(context); 149 | return true; 150 | } 151 | } 152 | return false; 153 | } 154 | 155 | /** 156 | * Gets the command Executor for this command. 157 | */ 158 | public CommandExecutor getCommandExecutor() { 159 | return commandExecutor; 160 | } 161 | 162 | /** 163 | * Sets the executor of this command. 164 | */ 165 | public void setCommandExecutor(CommandExecutor commandExecutor) { 166 | this.commandExecutor = commandExecutor; 167 | } 168 | 169 | /** 170 | * Checks if the String matches this commands name, or aliases 171 | * 172 | * @param input The string to compare it to 173 | * @return if the string matches 174 | */ 175 | public boolean matchesCommand(String input) { 176 | input = input.toLowerCase(); 177 | return (input.equals(name) || aliases.contains(input)); 178 | } 179 | 180 | /** 181 | * Returns the plugin this command belongs too. 182 | * 183 | * @return The host plugin 184 | */ 185 | public CoPlugin getPlugin() { 186 | return plugin; 187 | } 188 | 189 | /** 190 | * The name of this command 191 | * 192 | * @return The name of this command. 193 | */ 194 | public String getName() { 195 | return name; 196 | } 197 | 198 | /** 199 | * Sets the name of this command. 200 | * 201 | * @param name The new name of this command. 202 | */ 203 | public void setName(String name) { 204 | this.name = name; 205 | } 206 | 207 | /** 208 | * A set of aliases for this command. 209 | * 210 | * @return The alias set for this command. 211 | */ 212 | public Set getAliases() { 213 | return aliases; 214 | } 215 | 216 | /** 217 | * Sets the aliases for this command. 218 | * 219 | * @param aliases All the aliases for this command. 220 | */ 221 | public void setAliases(Set aliases) { 222 | this.aliases = aliases; 223 | } 224 | 225 | /** 226 | * Sets the aliases for this command. 227 | * 228 | * @param aliases All the aliases for this command. 229 | */ 230 | public void setAliases(String... aliases) { 231 | this.aliases = Stream.of(aliases).map(String::toLowerCase).collect(Collectors.toSet()); 232 | } 233 | 234 | /** 235 | * Checks if this command has any aliases whatsoever. 236 | * 237 | * @return True if it has aliases, false otherwise. 238 | */ 239 | public boolean hasAliases() { 240 | return aliases.size() > 0; 241 | } 242 | 243 | /** 244 | * Gets the description of this command. 245 | * 246 | * @return The command description. 247 | */ 248 | public String getDescription() { 249 | return description; 250 | } 251 | 252 | /** 253 | * Sets the description of this command. 254 | * 255 | * @param description The description of this command. 256 | */ 257 | public void setDescription(String description) { 258 | this.description = description; 259 | } 260 | 261 | /** 262 | * Gets the usage of this command. 263 | * 264 | * @return The command usage. 265 | */ 266 | public String getUsage() { 267 | return usage; 268 | } 269 | 270 | /** 271 | * Sets the usage of this command. 272 | * 273 | * @param usage The command usage of this command. 274 | */ 275 | public void setUsage(String usage) { 276 | this.usage = usage; 277 | } 278 | 279 | public String getPermission() { 280 | return permission; 281 | } 282 | 283 | /** 284 | * Sets the permission needed for this command 285 | * 286 | * @param permission The permission needed for this command. 287 | */ 288 | public void setPermission(String permission) { 289 | this.permission = permission; 290 | } 291 | 292 | /** 293 | * Checks if this command needs operator to be ran. 294 | * 295 | * @param requiresOperator True for operators only, false otherwise. 296 | */ 297 | public void setRequiresOperator(boolean requiresOperator) { 298 | this.requiresOperator = requiresOperator; 299 | } 300 | 301 | /** 302 | * Sets the permission check of the command. 303 | * 304 | * @param permissionCheck The permission check. 305 | */ 306 | public void setPermissionCheck(Predicate permissionCheck) { 307 | this.permissionCheck = permissionCheck; 308 | } 309 | 310 | /** 311 | * Gets the minimum amount of allowed arguments for this command. 312 | * 313 | * @return The minimum amount of arguments. 314 | */ 315 | public int getMinArgs() { 316 | return minArgs; 317 | } 318 | 319 | /** 320 | * Sets the minimum amount of arguments for this command before throwing an error. 321 | * 322 | * @param minArgs The minimum amount of arguments without throwing an error. 323 | */ 324 | public void setMinArgs(int minArgs) { 325 | this.minArgs = minArgs; 326 | } 327 | 328 | /** 329 | * The maximum amount of arguments allowed in this command before throwing an error.. 330 | * 331 | * @return The maximum amount of allowed arguments. 332 | */ 333 | public int getMaxArgs() { 334 | return maxArgs; 335 | } 336 | 337 | /** 338 | * Sets the maximum amount of arguments for this command before sending an error. 339 | * 340 | * @param maxArgs The maximum amount of arguments allowed for this command. (Default is -1 for no limit) 341 | */ 342 | public void setMaxArgs(int maxArgs) { 343 | this.maxArgs = maxArgs; 344 | } 345 | 346 | /** 347 | * Checks if this command is for players only. 348 | * 349 | * @return True if its for players only, false otherwise. 350 | */ 351 | public boolean isPlayerOnly() { 352 | return playerOnly; 353 | } 354 | 355 | /** 356 | * Sets this command as player only if true. 357 | * 358 | * @param playerOnly If true, this is only for players, false otherwise. 359 | */ 360 | public void setPlayerOnly(boolean playerOnly) { 361 | this.playerOnly = playerOnly; 362 | } 363 | 364 | /** 365 | * Gets all the sub commands for this command 366 | * 367 | * @return A set of subCommands. 368 | */ 369 | public Set getChildren() { 370 | return children; 371 | } 372 | 373 | /** 374 | * Sets a list of possible sub commands for this command. 375 | * 376 | * @param children The subCommand set this command has. 377 | */ 378 | public void setChildren(Set children) { 379 | this.children = children; 380 | } 381 | 382 | /** 383 | * The tab executor for this command. 384 | * 385 | * @return The command tab Completer. 386 | */ 387 | public TabExecutor getTabExecutor() { 388 | return tabExecutor; 389 | } 390 | 391 | /** 392 | * Sets the tab executor method for this command. 393 | * 394 | * @param tabExecutor The tab executor. 395 | */ 396 | public void setTabExecutor(TabExecutor tabExecutor) { 397 | this.tabExecutor = tabExecutor; 398 | } 399 | } 400 | -------------------------------------------------------------------------------- /core/src/main/java/com/coalesce/command/CommandBuilder.java: -------------------------------------------------------------------------------- 1 | package com.coalesce.command; 2 | 3 | import com.coalesce.command.base.AbstractCommandContext; 4 | import com.coalesce.command.base.AbstractTabContext; 5 | import com.coalesce.command.base.ICommandContext; 6 | import com.coalesce.command.tabcomplete.TabExecutor; 7 | import com.coalesce.plugin.CoPlugin; 8 | import org.bukkit.command.CommandSender; 9 | 10 | import java.util.Set; 11 | import java.util.function.Predicate; 12 | import java.util.stream.Collectors; 13 | import java.util.stream.Stream; 14 | 15 | public final class CommandBuilder { 16 | 17 | private CoCommand command; 18 | 19 | /** 20 | * Creates a new command Builder 21 | * 22 | * @param plugin The host plugin 23 | * @param name The name of the command. 24 | */ 25 | public CommandBuilder(CoPlugin plugin, String name) { 26 | command = new CoCommand(plugin, name); 27 | } 28 | 29 | /** 30 | * The method the command needs to run. 31 | * 32 | * @param executor The method of this command. Should be this::method_name 33 | */ 34 | public CommandBuilder executor(CommandExecutor executor) { 35 | command.setCommandExecutor(executor); 36 | return this; 37 | } 38 | 39 | /** 40 | * The method the command needs to create a tab completion. 41 | * 42 | * @param executor The method of this command's tab completer 43 | */ 44 | public CommandBuilder completer(TabExecutor executor) { 45 | command.setTabExecutor(executor); 46 | return this; 47 | } 48 | 49 | /** 50 | * The list of aliases for this command. 51 | * 52 | * @param aliases List of aliases. 53 | */ 54 | public CommandBuilder aliases(String... aliases) { 55 | command.setAliases(aliases); 56 | return this; 57 | } 58 | 59 | /** 60 | * The list of aliases for this command. 61 | * 62 | * @param aliases List of aliases. 63 | */ 64 | public CommandBuilder aliases(Set aliases) { 65 | command.setAliases(aliases); 66 | return this; 67 | } 68 | 69 | /** 70 | * The command description. 71 | * 72 | * @param description The command description. 73 | */ 74 | public CommandBuilder description(String description) { 75 | command.setDescription(description); 76 | return this; 77 | } 78 | 79 | /** 80 | * The command usage. 81 | * 82 | * @param usage The command usage. 83 | */ 84 | public CommandBuilder usage(String usage) { 85 | command.setUsage(usage); 86 | return this; 87 | } 88 | 89 | /** 90 | * The needed permissions for this command. 91 | * 92 | * @param permission The required permission node. 93 | */ 94 | public CommandBuilder permission(String permission) { 95 | command.setPermission(permission); 96 | return this; 97 | } 98 | 99 | /** 100 | * Forces the sender of this command to be an operator. 101 | */ 102 | public CommandBuilder requireOp() { 103 | command.setRequiresOperator(true); 104 | return this; 105 | } 106 | 107 | /** 108 | * Sets the require operator variable 109 | * 110 | * @param requires True = require operator, false does opposite. 111 | */ 112 | public CommandBuilder requiresOp(boolean requires) { 113 | command.setRequiresOperator(requires); 114 | return this; 115 | } 116 | 117 | /** 118 | * Checks if the sender has permissions. 119 | */ 120 | public CommandBuilder permissionCheck(Predicate predicate) { 121 | command.setPermissionCheck(predicate); 122 | return this; 123 | } 124 | 125 | /** 126 | * Minimum amount of arguments allowed in a command without throwing an error. 127 | * 128 | * @param minArgs The min amount of args without error. 129 | */ 130 | public CommandBuilder minArgs(int minArgs) { 131 | command.setMinArgs(minArgs); 132 | return this; 133 | } 134 | 135 | /** 136 | * Sets the maximum amount of arguments allowed in a command without throwing an error. 137 | * 138 | * @param maxArgs The max amount of args without error. 139 | */ 140 | public CommandBuilder maxArgs(int maxArgs) { 141 | command.setMaxArgs(maxArgs); 142 | return this; 143 | } 144 | 145 | /** 146 | * Makes this command for players only. 147 | */ 148 | public CommandBuilder playerOnly() { 149 | command.setPlayerOnly(true); 150 | return this; 151 | } 152 | 153 | /** 154 | * A list of CoCommands that also act as subcommands. 155 | * 156 | * @param subCommands The list of CoCommands. 157 | */ 158 | public CommandBuilder children(CoCommand... subCommands) { 159 | command.setChildren(Stream.of(subCommands).collect(Collectors.toSet())); 160 | return this; 161 | } 162 | 163 | /** 164 | * A set of CoCommands that also act as subcommands. 165 | * 166 | * @param subCommands The set of CoCommands. 167 | */ 168 | public CommandBuilder children(Set subCommands) { 169 | command.setChildren(subCommands); 170 | return this; 171 | } 172 | 173 | /** 174 | * This builds the CoCommand. 175 | * 176 | * @return A new CoCommand. 177 | */ 178 | public CoCommand build() { 179 | return command; 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /core/src/main/java/com/coalesce/command/CommandContext.java: -------------------------------------------------------------------------------- 1 | package com.coalesce.command; 2 | 3 | import com.coalesce.command.base.AbstractCommandContext; 4 | import com.coalesce.plugin.CoPlugin; 5 | import org.bukkit.command.CommandSender; 6 | 7 | public class CommandContext extends AbstractCommandContext { 8 | 9 | public CommandContext(CommandSender sender, String[] args, CoPlugin plugin) { 10 | super(sender, args, plugin); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /core/src/main/java/com/coalesce/command/CommandExecutor.java: -------------------------------------------------------------------------------- 1 | package com.coalesce.command; 2 | 3 | @FunctionalInterface 4 | public interface CommandExecutor { 5 | 6 | /** 7 | * The command execution method. 8 | * 9 | * @param commandMethod The method reference to a command. 10 | */ 11 | void execute(CommandContext commandMethod); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /core/src/main/java/com/coalesce/command/CommandRegister.java: -------------------------------------------------------------------------------- 1 | package com.coalesce.command; 2 | 3 | import com.coalesce.command.tabcomplete.TabContext; 4 | import com.coalesce.plugin.CoPlugin; 5 | import org.bukkit.command.Command; 6 | import org.bukkit.command.CommandSender; 7 | import org.bukkit.command.PluginIdentifiableCommand; 8 | import org.bukkit.plugin.Plugin; 9 | 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | public final class CommandRegister extends Command implements PluginIdentifiableCommand { 14 | 15 | private final CoCommand command; 16 | private final CoPlugin plugin; 17 | 18 | /** 19 | * Registers a command for the given plugin. 20 | * 21 | * @param command The CoCommand to register. 22 | * @param plugin The plugin to register the command for. 23 | */ 24 | public CommandRegister(CoCommand command, CoPlugin plugin) { 25 | super(command.getName()); 26 | this.plugin = plugin; 27 | this.command = command; 28 | this.description = command.getDescription(); 29 | this.usageMessage = command.getUsage(); 30 | List aliases = new ArrayList<>(); 31 | command.getAliases().forEach(alias -> aliases.add(alias)); 32 | this.setAliases(aliases); 33 | } 34 | 35 | @Override 36 | public boolean execute(CommandSender sender, String commandLabel, String[] args) { 37 | if (command.matchesCommand(commandLabel)) { 38 | command.execute(new CommandContext(sender, args, plugin)); 39 | return true; 40 | } 41 | return false; 42 | } 43 | 44 | @Override 45 | public List tabComplete(CommandSender sender, String alias, String[] args) throws IllegalArgumentException { 46 | return command.completer(new TabContext(plugin, command, new CommandContext(sender, args, plugin))); 47 | } 48 | 49 | @Override 50 | public Plugin getPlugin() { 51 | return plugin; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /core/src/main/java/com/coalesce/command/base/AbstractCommandContext.java: -------------------------------------------------------------------------------- 1 | package com.coalesce.command.base; 2 | 3 | import com.coalesce.plugin.CoPlugin; 4 | import org.bukkit.command.CommandSender; 5 | import org.bukkit.command.ConsoleCommandSender; 6 | import org.bukkit.entity.Player; 7 | 8 | import java.util.ArrayList; 9 | import java.util.Arrays; 10 | import java.util.List; 11 | import java.util.stream.Stream; 12 | 13 | public abstract class AbstractCommandContext implements ICommandContext { 14 | 15 | private CommandSender sender; 16 | private List args; 17 | private CoPlugin plugin; 18 | 19 | public AbstractCommandContext(CommandSender sender, String[] args, CoPlugin plugin) { 20 | this.sender = sender; 21 | this.plugin = plugin; 22 | List list = new ArrayList<>(); 23 | list.addAll(Arrays.asList(args)); 24 | this.args = list; 25 | } 26 | 27 | @Override 28 | public CoPlugin getPlugin() { 29 | return plugin; 30 | } 31 | 32 | @Override 33 | public void pluginMessage(String message) { 34 | send(plugin.getFormatter().format(message)); 35 | } 36 | 37 | @Override 38 | public boolean isPlayer() { 39 | return sender instanceof Player; 40 | } 41 | 42 | @Override 43 | public Player asPlayer() { 44 | return (Player)sender; 45 | } 46 | 47 | @Override 48 | public boolean isConsole() { 49 | return sender instanceof ConsoleCommandSender; 50 | } 51 | 52 | @Override 53 | public ConsoleCommandSender asConsole() { 54 | return (ConsoleCommandSender)sender; 55 | } 56 | 57 | @Override 58 | public CommandSender getSender() { 59 | return sender; 60 | } 61 | 62 | @Override 63 | public List getArgs() { 64 | return args; 65 | } 66 | 67 | @Override 68 | public boolean hasArgs() { 69 | return !args.isEmpty(); 70 | } 71 | 72 | @Override 73 | public String argAt(int index) { 74 | if (index < 0 || index >= args.size()) { 75 | return null; 76 | } 77 | return args.get(index); 78 | } 79 | 80 | @Override 81 | public String joinArgs(int start, int finish) { 82 | if (args.isEmpty()) { 83 | return ""; 84 | } 85 | return String.join(" ", args.subList(start, finish)); 86 | } 87 | 88 | @Override 89 | public String joinArgs(int start) { 90 | return joinArgs(start, args.size()); 91 | } 92 | 93 | @Override 94 | public String joinArgs() { 95 | return joinArgs(0); 96 | } 97 | 98 | @Override 99 | public void send(String message) { 100 | sender.sendMessage(message); 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /core/src/main/java/com/coalesce/command/base/AbstractTabContext.java: -------------------------------------------------------------------------------- 1 | package com.coalesce.command.base; 2 | 3 | import com.coalesce.command.CoCommand; 4 | import com.coalesce.plugin.CoPlugin; 5 | import org.bukkit.Bukkit; 6 | import org.bukkit.command.CommandSender; 7 | import org.bukkit.entity.Player; 8 | 9 | import java.util.ArrayList; 10 | import java.util.Arrays; 11 | import java.util.List; 12 | import java.util.Set; 13 | import java.util.function.Predicate; 14 | 15 | public abstract class AbstractTabContext implements ITabContext { 16 | 17 | private final CoPlugin plugin; 18 | private final CoCommand command; 19 | private final ICommandContext commandContext; 20 | private List possible = new ArrayList<>(); 21 | 22 | /** 23 | * A new tab completer context. 24 | * 25 | * @param plugin The plugin this completer belongs to. 26 | * @param command The command this completer is linked to. 27 | * @param commandContext The command context the command is linked to. 28 | */ 29 | public AbstractTabContext(CoPlugin plugin, CoCommand command, ICommandContext commandContext) { 30 | this.plugin = plugin; 31 | this.command = command; 32 | this.commandContext = commandContext; 33 | } 34 | 35 | @Override 36 | public CoCommand getCommand() { 37 | return command; 38 | } 39 | 40 | @Override 41 | public CoPlugin getPlugin() { 42 | return plugin; 43 | } 44 | 45 | @Override 46 | public ICommandContext getContext() { 47 | return commandContext; 48 | } 49 | 50 | @Override 51 | public CommandSender getSender() { 52 | return commandContext.getSender(); 53 | } 54 | 55 | @Override 56 | public Set getCommandChildren() { 57 | return command.getChildren(); 58 | } 59 | 60 | @Override 61 | public int getLength() { 62 | return commandContext.getArgs().size() - 1; 63 | } 64 | 65 | @Override 66 | public boolean length(int length) { 67 | return getLength() == length; 68 | } 69 | 70 | @Override 71 | public String getPrevious() { 72 | return commandContext.getArgs().get(getLength()); 73 | } 74 | 75 | @Override 76 | public boolean previous(String previousArg) { 77 | return getPrevious().matches(previousArg); 78 | } 79 | 80 | @Override 81 | public void playerCompletion(int index, Predicate predicate) { 82 | if (length(index)) { 83 | possible.clear(); 84 | Bukkit.getOnlinePlayers().stream().filter(predicate).forEach(p -> possible.add(p.getName())); 85 | } 86 | } 87 | 88 | @Override 89 | public void playerCompletion(int index) { 90 | if (length(index)) { 91 | possible.clear(); 92 | Bukkit.getOnlinePlayers().forEach(p -> possible.add(p.getName())); 93 | } 94 | } 95 | 96 | @Override 97 | public void completion(String... completions) { 98 | possible.clear(); 99 | possible.addAll(Arrays.asList(completions)); 100 | } 101 | 102 | @Override 103 | public void completionAt(int index, String... completions) { 104 | if (length(index)) { 105 | possible.clear(); 106 | possible.addAll(Arrays.asList(completions)); 107 | } 108 | } 109 | 110 | @Override 111 | public void completionAfter(String previousText, String... completions) { 112 | if (previous(previousText)) { 113 | possible.clear(); 114 | possible.addAll(Arrays.asList(completions)); 115 | } 116 | } 117 | 118 | @Override 119 | public List currentPossibleCompletion() { 120 | return possible; 121 | } 122 | 123 | } 124 | -------------------------------------------------------------------------------- /core/src/main/java/com/coalesce/command/base/ICommandContext.java: -------------------------------------------------------------------------------- 1 | package com.coalesce.command.base; 2 | 3 | import com.coalesce.plugin.CoPlugin; 4 | import org.bukkit.command.CommandSender; 5 | import org.bukkit.command.ConsoleCommandSender; 6 | import org.bukkit.entity.Player; 7 | 8 | import java.util.List; 9 | 10 | public interface ICommandContext { 11 | 12 | /** 13 | * The current plugin. 14 | * 15 | * @return The current plugin being used. 16 | */ 17 | CoPlugin getPlugin(); 18 | 19 | /** 20 | * Sends a formatted plguin message. 21 | *

22 | *

Ex. [PlguinName] MESSAGE FROM THE PARAMETER

23 | * 24 | * @param message The message to send with the plugin name before it. 25 | */ 26 | void pluginMessage(String message); 27 | 28 | /** 29 | * Checks if the CommandSender is a player. 30 | * 31 | * @return True if the sender is a player, false otherwise. 32 | */ 33 | boolean isPlayer(); 34 | 35 | /** 36 | * Changes the sender of this command to a player. 37 | * 38 | * @return Returns the player sending this command. 39 | */ 40 | Player asPlayer(); 41 | 42 | /** 43 | * Checks if the CommandSender is the console. 44 | * 45 | * @return True if the sender is the Console, false otherwise. 46 | */ 47 | boolean isConsole(); 48 | 49 | /** 50 | * Changes the sender of this command to the Console. 51 | * 52 | * @return Returns the console sending this command. 53 | */ 54 | ConsoleCommandSender asConsole(); 55 | 56 | /** 57 | * Gets the CommandSender of this command. 58 | * 59 | * @return The command CommandSender. 60 | */ 61 | CommandSender getSender(); 62 | 63 | /** 64 | * Gets a list of all the arguments in this command. 65 | * 66 | * @return List of arguments. 67 | */ 68 | List getArgs(); 69 | 70 | /** 71 | * Checks if the command has any arguments. 72 | * 73 | * @return Returns true if the command has any arguments, false otherwise. 74 | */ 75 | boolean hasArgs(); 76 | 77 | /** 78 | * Gets an argument at a specified index. 79 | * 80 | * @param index The index of the argument. 81 | * @return The argument at the index provided. 82 | */ 83 | String argAt(int index); 84 | 85 | /** 86 | * Joins all the arguments in the command from the start index to the finish index. 87 | * 88 | * @param start Index to start at. 89 | * @param finish Index to finish at. 90 | * @return One string for the args between the start and finish index. 91 | */ 92 | String joinArgs(int start, int finish); 93 | 94 | /** 95 | * Joins all the arguments after a given point. 96 | * 97 | * @param start Where to start joining the arguments. 98 | * @return One string for all the arguments after start. 99 | */ 100 | String joinArgs(int start); 101 | 102 | /** 103 | * Joins all the arguments into one string. 104 | * 105 | * @return One string for the command arguments. 106 | */ 107 | String joinArgs(); 108 | 109 | /** 110 | * Sends a message to the player/console. 111 | * 112 | * @param message The message to send. 113 | */ 114 | void send(String message); 115 | 116 | } 117 | -------------------------------------------------------------------------------- /core/src/main/java/com/coalesce/command/base/ITabContext.java: -------------------------------------------------------------------------------- 1 | package com.coalesce.command.base; 2 | 3 | import com.coalesce.command.CoCommand; 4 | import com.coalesce.plugin.CoPlugin; 5 | import org.bukkit.command.CommandSender; 6 | import org.bukkit.entity.Player; 7 | 8 | import java.util.List; 9 | import java.util.Set; 10 | import java.util.function.Predicate; 11 | 12 | public interface ITabContext { 13 | 14 | /** 15 | * The CoCommand this TabCompletion comes from. 16 | * 17 | * @return CoCommand 18 | */ 19 | CoCommand getCommand(); 20 | 21 | /** 22 | * The CoPlugin this TabCompletion is held in. 23 | * 24 | * @return The current plugin. 25 | */ 26 | CoPlugin getPlugin(); 27 | 28 | /** 29 | * Get the command context from the current command. 30 | * 31 | * @return The command context of the current command. 32 | */ 33 | ICommandContext getContext(); 34 | 35 | /** 36 | * Gets the command sender of this command. 37 | * 38 | * @return The command sender. 39 | */ 40 | CommandSender getSender(); 41 | 42 | /** 43 | * Gets a Set of children from this command if any exist. 44 | * 45 | * @return The set of children commands, null if none exist. 46 | */ 47 | Set getCommandChildren(); 48 | 49 | /** 50 | * Autocompletes a list of players online. This has a filter for quickly and easily filtering layers out 51 | * 52 | * @param index The index for these completions to run 53 | */ 54 | void playerCompletion(int index, Predicate predicate); 55 | 56 | /** 57 | * Autocompletes a list of players online. 58 | * 59 | * @param index The index for these completions to run. 60 | */ 61 | void playerCompletion(int index); 62 | 63 | /** 64 | * Gets the length of the arguments. 65 | * 66 | * @return The argument length. 67 | */ 68 | int getLength(); 69 | 70 | /** 71 | * Quick way to check if the command argument size equals the correct length. 72 | * 73 | * @param length The length to check. 74 | * @return True if the length equals the command argument size. 75 | */ 76 | boolean length(int length); 77 | 78 | /** 79 | * Gets the previous argument. 80 | * 81 | * @return The previous argument. 82 | */ 83 | String getPrevious(); 84 | 85 | /** 86 | * Checks if the previous argument matches the specified string. 87 | * 88 | * @param previousArg The string to look for. 89 | * @return True if the previous arg matches the given string, false otherwise. 90 | */ 91 | boolean previous(String previousArg); 92 | 93 | /** 94 | * A list of completions 95 | * 96 | * @param completions The completions to add. 97 | */ 98 | void completion(String... completions); 99 | 100 | /** 101 | * Have specific completions at a certain index. 102 | * 103 | * @param index The index for these completions to run. 104 | * @param completions The completions to add. 105 | */ 106 | void completionAt(int index, String... completions); 107 | 108 | /** 109 | * Have specific completions after a certain word. 110 | * 111 | * @param previousText The word these completions show up after. 112 | * @param completions The completions to add. 113 | */ 114 | void completionAfter(String previousText, String... completions); 115 | 116 | /** 117 | * Returns the current tab completion list. 118 | * 119 | * @return The tab completion list. 120 | */ 121 | List currentPossibleCompletion(); 122 | 123 | } 124 | -------------------------------------------------------------------------------- /core/src/main/java/com/coalesce/command/tabcomplete/TabContext.java: -------------------------------------------------------------------------------- 1 | package com.coalesce.command.tabcomplete; 2 | 3 | import com.coalesce.command.CoCommand; 4 | import com.coalesce.command.CommandContext; 5 | import com.coalesce.command.base.AbstractCommandContext; 6 | import com.coalesce.command.base.AbstractTabContext; 7 | import com.coalesce.command.base.ICommandContext; 8 | import com.coalesce.plugin.CoPlugin; 9 | import org.bukkit.command.CommandSender; 10 | 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | import java.util.Set; 14 | import java.util.stream.Stream; 15 | 16 | public class TabContext extends AbstractTabContext { 17 | 18 | /** 19 | * A new tab completer context. 20 | * 21 | * @param plugin The plugin this completer belongs to. 22 | * @param command The command this completer is linked to. 23 | * @param commandContext The command context the command is linked to. 24 | */ 25 | public TabContext(CoPlugin plugin, CoCommand command, ICommandContext commandContext) { 26 | super(plugin, command, commandContext); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /core/src/main/java/com/coalesce/command/tabcomplete/TabExecutor.java: -------------------------------------------------------------------------------- 1 | package com.coalesce.command.tabcomplete; 2 | 3 | public interface TabExecutor { 4 | 5 | /** 6 | * The tab completer method 7 | * 8 | * @param context The tab complete context 9 | */ 10 | void complete(TabContext context); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /core/src/main/java/com/coalesce/config/ConfigFormat.java: -------------------------------------------------------------------------------- 1 | package com.coalesce.config; 2 | 3 | public enum ConfigFormat { 4 | 5 | JSON, 6 | YAML; 7 | 8 | } 9 | -------------------------------------------------------------------------------- /core/src/main/java/com/coalesce/config/IConfig.java: -------------------------------------------------------------------------------- 1 | package com.coalesce.config; 2 | 3 | import com.coalesce.plugin.CoPlugin; 4 | 5 | import java.io.File; 6 | import java.util.Collection; 7 | import java.util.List; 8 | 9 | public interface IConfig { 10 | /** 11 | * Gets an entry from a config. 12 | * 13 | * @param path The path in the config. 14 | * @return The entry that is at that path. 15 | */ 16 | IEntry getEntry(String path); 17 | 18 | /** 19 | * Gets a value from a config entry. 20 | * 21 | * @param path The path in the configuration. 22 | * @return A string from the specified path. 23 | */ 24 | String getString(String path); 25 | 26 | /** 27 | * Gets a value from a config entry. 28 | * 29 | * @param path The path in the configuration. 30 | * @return A double from the specified path. 31 | */ 32 | double getDouble(String path); 33 | 34 | /** 35 | * Gets a value from a config entry. 36 | * 37 | * @param path The path in the configuration. 38 | * @return An integer from the specified path. 39 | */ 40 | int getInt(String path); 41 | 42 | /** 43 | * Gets a value from a config entry. 44 | * 45 | * @param path The path in the configuration. 46 | * @return A long from the specified path. 47 | */ 48 | long getLong(String path); 49 | 50 | /** 51 | * Gets a value from a config entry. 52 | * 53 | * @param path The path in the configuration. 54 | * @return A boolean from the specified path. 55 | */ 56 | boolean getBoolean(String path); 57 | 58 | /** 59 | * Gets a value from a config entry. 60 | * 61 | * @param path The path in the configuration. 62 | * @return A list from the specified path. 63 | */ 64 | List getList(String path); 65 | 66 | /** 67 | * Gets a List of Strings from a path in this config. 68 | * 69 | * @param path The path to get the strings from. 70 | * @return A list from the specified path. 71 | */ 72 | List getStringList(String path); 73 | 74 | /** 75 | * Gets a value from a config entry. 76 | * 77 | * @param path The path in the configuration. 78 | * @return An object from the specified path. 79 | */ 80 | Object getValue(String path); 81 | 82 | /** 83 | * Gets an entry based on its value instead of path. 84 | * 85 | * @param value The value you are looking for. 86 | * @return The entry that was found with this value. 87 | *

88 | * NOTE: This will likely change into an array of entries. 89 | */ 90 | Collection getEntryFromValue(Object value); 91 | 92 | /** 93 | * Gets all the entries in a config. 94 | * 95 | * @return A collection of entries in a config. 96 | */ 97 | Collection getEntries(); 98 | 99 | /** 100 | * Adds a new entry to the current config. 101 | * 102 | * @param path The path in the config. 103 | * @param value The value to set this entry to. 104 | */ 105 | void addEntry(String path, Object value); 106 | 107 | /** 108 | * Adds a new entry to the current config. If the 109 | * config already has a value at the path location 110 | * it will be updated with the new value supplied 111 | * from this method. 112 | * 113 | * @param path The path in the config. 114 | * @param value The value to set the path to. 115 | */ 116 | void setEntry(String path, Object value); 117 | 118 | /** 119 | * Removes an entry from the config via the Entry Object. 120 | * 121 | * @param entry The entry to remove. 122 | */ 123 | void removeEntry(IEntry entry); 124 | 125 | /** 126 | * Removes an entry from the config via the entry path. 127 | * 128 | * @param path The path to this entry. 129 | */ 130 | void removeEntry(String path); 131 | 132 | /** 133 | * Returns this config. 134 | * 135 | * @return This current config. 136 | */ 137 | IConfig getConfig(); 138 | 139 | /** 140 | * Clears all the entries in this configuration. 141 | */ 142 | void clear(); 143 | 144 | /** 145 | * Backs up this configuration. 146 | */ 147 | void backup(); 148 | 149 | /** 150 | * Deletes the configuration file. 151 | */ 152 | void delete(); 153 | 154 | /** 155 | * The name of the config 156 | * 157 | * @return The name of the current config. 158 | */ 159 | String getName(); 160 | 161 | /** 162 | * Gets the config file. 163 | * 164 | * @return The file of this config. 165 | */ 166 | File getFile(); 167 | 168 | /** 169 | * Identifies the format of this configuration. 170 | * 171 | * @return YAML or GSON 172 | */ 173 | ConfigFormat getFormat(); 174 | 175 | /** 176 | * Gets a section of a configuration from a path. 177 | * 178 | * @param path The path to start getting the section from. 179 | * @return A Section of the config. 180 | */ 181 | ISection getSection(String path); 182 | 183 | /** 184 | * Checks whether the configuration contains a path. 185 | * 186 | * @param path The path to look for. 187 | * @param exact True to look for the exact path, false to find a path that starts with the path provided. 188 | *

189 | *

190 | * Ex. contains("groups", false);

191 | *

192 | * ==Configuration==
193 | * groups.test
194 | * groups.test.another-test

195 | *

196 | * ==Results==
197 | * contains would return true because one or more of those paths contains the groups section. 198 | *

199 | */ 200 | boolean contains(String path, boolean exact); 201 | 202 | /** 203 | * Returns the plugin this configuration is for. 204 | * 205 | * @return The host plugin. 206 | */ 207 | E getPlugin(); 208 | } 209 | -------------------------------------------------------------------------------- /core/src/main/java/com/coalesce/config/IEntry.java: -------------------------------------------------------------------------------- 1 | package com.coalesce.config; 2 | 3 | import java.util.List; 4 | 5 | public interface IEntry { 6 | 7 | /** 8 | * Gets a value from a config entry. 9 | * 10 | * @return A string from the specified path. 11 | */ 12 | String getString(); 13 | 14 | /** 15 | * Gets a value from a config entry. 16 | * 17 | * @return A double from the specified path. 18 | */ 19 | double getDouble(); 20 | 21 | /** 22 | * Gets a value from a config entry. 23 | * 24 | * @return An integer from the specified path. 25 | */ 26 | int getInt(); 27 | 28 | /** 29 | * Gets a value from a config entry. 30 | * 31 | * @return A long from the specified path. 32 | */ 33 | long getLong(); 34 | 35 | /** 36 | * Gets a value from a config entry. 37 | * 38 | * @return A boolean from the specified path. 39 | */ 40 | boolean getBoolean(); 41 | 42 | /** 43 | * Gets a value from a config entry. 44 | * 45 | * @return A list from the specified path. 46 | */ 47 | List getList(); 48 | 49 | /** 50 | * Gets a string list from an entry. 51 | * 52 | * @return The String list. 53 | */ 54 | List getStringList(); 55 | 56 | /** 57 | * Gets the path of this entry. 58 | * 59 | * @return The path in the config. 60 | */ 61 | String getPath(); 62 | 63 | /** 64 | * Gets the value of this entry. 65 | * 66 | * @return The value of this entry. 67 | */ 68 | Object getValue(); 69 | 70 | /** 71 | * Sets the path of this entry. 72 | * 73 | * @param newpath The new path this entry will have. 74 | */ 75 | IEntry setPath(String newpath); 76 | 77 | /** 78 | * Sets the value of this entry. 79 | * 80 | * @param value The new value of this entry. 81 | */ 82 | IEntry setValue(Object value); 83 | 84 | /** 85 | * Gets the database this entry is held in. 86 | * 87 | * @return The entry's database. 88 | */ 89 | IConfig getConfig(); 90 | 91 | /** 92 | * Gets the name of this entry. 93 | * 94 | * @return The entry name. 95 | */ 96 | String getName(); 97 | 98 | /** 99 | * Allows quick removal and moving of an Entry to another configuration file. 100 | * 101 | * @param config The new configuration file. 102 | * @return The new entry. 103 | */ 104 | IEntry setConfig(IConfig config); 105 | 106 | /** 107 | * Removes the entry. 108 | */ 109 | void remove(); 110 | 111 | } 112 | -------------------------------------------------------------------------------- /core/src/main/java/com/coalesce/config/ISection.java: -------------------------------------------------------------------------------- 1 | package com.coalesce.config; 2 | 3 | import com.coalesce.plugin.CoPlugin; 4 | 5 | import java.util.Set; 6 | 7 | public interface ISection { 8 | 9 | /** 10 | * Gets a set of keys that is in this section. 11 | * 12 | * @param deep Whether to get the keys of the keys (and so on) in this section. 13 | * @return A Set of Keys. 14 | */ 15 | Set getKeys(boolean deep); 16 | 17 | /** 18 | * Gets all the entries that exist in this configuration section. 19 | * 20 | * @return A set of entries in this section. 21 | */ 22 | Set getEntries(); 23 | 24 | /** 25 | * Gets a section from within this section. 26 | * 27 | * @param path The path from the start of this section.

Note: dont use the string provided originally to get this current section

28 | * @return A section of the configuration. 29 | */ 30 | ISection getSection(String path); 31 | 32 | /** 33 | * Check whether a section contains a path. 34 | * 35 | * @param path The path to look for 36 | * @return True if the path exists, false otherwise. 37 | */ 38 | boolean contains(String path); 39 | 40 | /** 41 | * Gets the current path of the configuration section. 42 | * 43 | * @return The current path 44 | */ 45 | String getCurrentPath(); 46 | 47 | /** 48 | * The name of the section. 49 | * 50 | * @return The name of the section. 51 | */ 52 | String getName(); 53 | 54 | /** 55 | * Gets the base configuration of this section. 56 | * 57 | * @return The current configuration 58 | */ 59 | IConfig getConfig(); 60 | 61 | /** 62 | * Gets the host plugin. 63 | * 64 | * @return The host plugin. 65 | */ 66 | CoPlugin getPlugin(); 67 | 68 | /** 69 | * Gets an entry from a section 70 | * 71 | * @param path The path to the entry.

Note: dont use the string provided originally to get this entry

//TODO: elaborate more and create getEntry Implementations in Json and yml config. 72 | */ 73 | IEntry getEntry(String path); 74 | 75 | /** 76 | * Gets the parent section to the current section. 77 | * 78 | * @return THe previous section, returns null if no previous section exists. 79 | */ 80 | ISection getParent(); 81 | 82 | 83 | } 84 | -------------------------------------------------------------------------------- /core/src/main/java/com/coalesce/config/common/Section.java: -------------------------------------------------------------------------------- 1 | package com.coalesce.config.common; 2 | 3 | import com.coalesce.config.IConfig; 4 | import com.coalesce.config.IEntry; 5 | import com.coalesce.config.ISection; 6 | import com.coalesce.plugin.CoPlugin; 7 | 8 | import java.util.HashSet; 9 | import java.util.Set; 10 | 11 | public final class Section implements ISection { 12 | 13 | private final String path; 14 | private final IConfig config; 15 | private final CoPlugin plugin; 16 | 17 | public Section(String path, IConfig config, CoPlugin plugin) { 18 | this.path = path; 19 | this.config = config; 20 | this.plugin = plugin; 21 | } 22 | 23 | @Override 24 | public Set getKeys(boolean deep) { 25 | Set keys = new HashSet<>(); 26 | if (deep) { 27 | config.getEntries().stream().filter(e -> e.getPath().startsWith(path + ".")).forEach(e -> keys.add(e.getPath())); 28 | } else { 29 | config.getEntries().stream().filter(e -> e.getPath().startsWith(path + ".")).forEach(e -> { 30 | String key = e.getPath().substring(path.length() + 1); 31 | int size = key.indexOf("."); 32 | if (size < 0) { 33 | size = key.length(); 34 | } 35 | keys.add(key.substring(0, size)); 36 | }); 37 | } 38 | return keys; 39 | } 40 | 41 | @Override 42 | public Set getEntries() { 43 | Set entries = new HashSet<>(); 44 | config.getEntries().stream().filter(e -> e.getPath().startsWith(path + ".")).forEach(entries::add); 45 | return entries; 46 | } 47 | 48 | @Override 49 | public ISection getSection(String path) { 50 | return new Section(this.path + "." + path, config, plugin); 51 | } 52 | 53 | @Override 54 | public boolean contains(String path) { 55 | return getKeys(false).contains(path); 56 | } 57 | 58 | @Override 59 | public String getCurrentPath() { 60 | return path; 61 | } 62 | 63 | @Override 64 | public String getName() { 65 | return path.substring(path.lastIndexOf(".")); 66 | } 67 | 68 | @Override 69 | public IConfig getConfig() { 70 | return config; 71 | } 72 | 73 | @Override 74 | public CoPlugin getPlugin() { 75 | return plugin; 76 | } 77 | 78 | @Override 79 | public IEntry getEntry(String path) { 80 | return config.getEntry(this.path + "." + path); 81 | } 82 | 83 | @Override 84 | public ISection getParent() { 85 | if (!path.contains(".")) { 86 | return null; 87 | } 88 | return new Section(path.substring(0, path.lastIndexOf(".")), config, plugin); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /core/src/main/java/com/coalesce/config/json/JsonConfig.java: -------------------------------------------------------------------------------- 1 | package com.coalesce.config.json; 2 | 3 | import com.coalesce.config.ConfigFormat; 4 | import com.coalesce.config.IConfig; 5 | import com.coalesce.config.IEntry; 6 | import com.coalesce.config.ISection; 7 | import com.coalesce.config.common.Section; 8 | import com.coalesce.plugin.CoPlugin; 9 | import com.google.common.io.Files; 10 | import com.google.gson.Gson; 11 | import com.google.gson.GsonBuilder; 12 | import lombok.Getter; 13 | import org.json.simple.JSONObject; 14 | import org.json.simple.parser.JSONParser; 15 | 16 | import java.io.*; 17 | import java.text.DateFormat; 18 | import java.text.SimpleDateFormat; 19 | import java.util.*; 20 | 21 | public abstract class JsonConfig implements IConfig { 22 | 23 | private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); 24 | private Collection entries = new ArrayList<>(); 25 | private final ConfigFormat format; 26 | private final CoPlugin plugin; 27 | private final File dir, file; 28 | private final String name; 29 | @Getter private JSONObject json; 30 | 31 | protected JsonConfig(String name, CoPlugin plugin) { 32 | this.name = name; 33 | this.format = ConfigFormat.JSON; 34 | this.plugin = plugin; 35 | 36 | dir = plugin.getDataFolder(); 37 | file = new File(dir, name.replaceAll("/", String.valueOf(File.separatorChar)) + ".json"); 38 | 39 | if (file.exists()) { 40 | try { 41 | FileReader reader = new FileReader(file); 42 | json = (JSONObject)new JSONParser().parse(reader); 43 | reader.close(); 44 | } 45 | catch (Exception e) { 46 | plugin.getCoLogger().error("An error occured while attempting to read configuration file at " + file.getAbsolutePath() + ":"); 47 | e.printStackTrace(); 48 | } 49 | } else { 50 | json = new JSONObject(); 51 | } 52 | 53 | if (!plugin.getConfigurations().contains(this)) { 54 | plugin.getConfigurations().add(this); 55 | } 56 | } 57 | 58 | @Override 59 | public IEntry getEntry(String path) { 60 | for (IEntry entry : entries) { 61 | if (entry.getPath().matches(path)) { 62 | return entry; 63 | } 64 | } 65 | return null; 66 | } 67 | 68 | @Override 69 | public void setEntry(String path, Object value) { 70 | IEntry entry = new JsonEntry(this, path, value); 71 | if (getEntry(path) == null) { 72 | putJSON(entry.getPath(), entry.getValue()); 73 | entries.add(entry); 74 | return; 75 | } 76 | entries.remove(entry); 77 | entry = entry.setValue(value); 78 | entries.add(entry); 79 | save(); 80 | } 81 | 82 | @Override 83 | public void addEntry(String path, Object value) { //This needs to be updated to match Yaml's functionality. 84 | IEntry entry; 85 | if (!json.containsKey(path)) { 86 | entry = new JsonEntry(this, path, value); 87 | putJSON(entry.getPath(), entry.getValue()); 88 | } else { 89 | entry = new JsonEntry(this, path, json.get(path)); 90 | } 91 | entries.add(entry); 92 | save(); 93 | } 94 | 95 | private void putJSON(String path, Object value) { 96 | String[] fullPath = path.split("\\."); 97 | if (fullPath.length == 1) { 98 | json.put(path, value); 99 | return; 100 | } 101 | resolveSubObjects(json, value, new ArrayList<>(Arrays.asList(fullPath))); 102 | } 103 | 104 | private void resolveSubObjects(JSONObject object, Object finalObject, List path) { 105 | if (path.size() == 1) { 106 | object.put(path.get(0), finalObject); 107 | } else { 108 | JSONObject subObject = object.containsKey(path.get(0)) && object.get(path.get(0)) instanceof JSONObject ? (JSONObject)object.get(path.get(0)) : new JSONObject(); 109 | resolveSubObjects(subObject, finalObject, path.subList(1, path.size())); 110 | object.put(path.get(0), subObject); 111 | } 112 | } 113 | 114 | @Override 115 | public String getString(String path) { 116 | return getEntry(path).getString(); 117 | } 118 | 119 | @Override 120 | public double getDouble(String path) { 121 | return getEntry(path).getDouble(); 122 | } 123 | 124 | @Override 125 | public int getInt(String path) { 126 | return getEntry(path).getInt(); 127 | } 128 | 129 | @Override 130 | public long getLong(String path) { 131 | return getEntry(path).getLong(); 132 | } 133 | 134 | @Override 135 | public boolean getBoolean(String path) { 136 | return getEntry(path).getBoolean(); 137 | } 138 | 139 | @Override 140 | public List getList(String path) { 141 | return getEntry(path).getList(); 142 | } 143 | 144 | @Override 145 | public Object getValue(String path) { 146 | return getEntry(path).getValue(); 147 | } 148 | 149 | @Override 150 | public Collection getEntryFromValue(Object value) { 151 | Collection found = new ArrayList<>(); 152 | entries.forEach(entry -> { 153 | if (entry.getValue().equals(value)) { 154 | found.add(entry); 155 | } 156 | }); 157 | return found; 158 | } 159 | 160 | @Override 161 | public Collection getEntries() { 162 | json.forEach((k, v) -> entries.add(new JsonEntry(this, (String)k, v))); 163 | return entries; 164 | } 165 | 166 | @Override 167 | public void removeEntry(IEntry entry) { 168 | entry.remove(); 169 | save(); 170 | } 171 | 172 | @Override 173 | public void removeEntry(String path) { 174 | getEntry(path).remove(); 175 | save(); 176 | } 177 | 178 | @Override 179 | public IConfig getConfig() { 180 | return this; 181 | } 182 | 183 | @Override 184 | public ISection getSection(String path) { 185 | return new Section(path, this, plugin); 186 | } 187 | 188 | @Override 189 | public List getStringList(String path) { 190 | return (List)getList(path); 191 | } 192 | 193 | @Override 194 | public boolean contains(String path, boolean exact) { 195 | if (exact) { 196 | return getEntry(path) == null; 197 | } 198 | for (IEntry entry : entries) { 199 | if (entry.getPath().startsWith(path)) { 200 | return true; 201 | } 202 | } 203 | return false; 204 | } 205 | 206 | @Override 207 | public void clear() { 208 | entries.forEach(IEntry::remove); 209 | json.clear(); 210 | save(); 211 | } 212 | 213 | @Override 214 | public void backup() { 215 | DateFormat format = new SimpleDateFormat("yyyy.dd.MM-hh.mm.ss"); 216 | File file = new File(dir + File.separator + "backups"); 217 | File bckp = new File(file + File.separator + name + format.format(new Date()) + ".json"); 218 | if (!dir.exists() || bckp.exists() || !this.file.exists()) { 219 | return; 220 | } 221 | if (!file.exists()) { 222 | file.mkdir(); 223 | } 224 | try { 225 | Files.copy(this.file, bckp); 226 | } 227 | catch (IOException e) { 228 | e.printStackTrace(); 229 | } 230 | } 231 | 232 | private void save() { 233 | try { 234 | synchronized (file) { 235 | if (file.exists()) { 236 | file.delete(); 237 | } 238 | if (!file.getParentFile().exists()) { 239 | file.getParentFile().mkdirs(); 240 | } 241 | file.createNewFile(); 242 | 243 | FileWriter writer = new FileWriter(file); 244 | 245 | try { 246 | writer.write(GSON.toJson(json)); 247 | } 248 | catch (Exception e) { 249 | plugin.getCoLogger().error("An error occured while attempting to write saved data for configuration file at " + file.getAbsolutePath() + ":"); 250 | e.printStackTrace(); 251 | } 252 | 253 | writer.close(); 254 | } 255 | } 256 | catch (IOException e) { 257 | plugin.getCoLogger().error("An error occured while attempting to save configuration file at " + file.getAbsolutePath() + ":"); 258 | e.printStackTrace(); 259 | } 260 | } 261 | 262 | @Override 263 | public void delete() { 264 | file.delete(); 265 | } 266 | 267 | @Override 268 | public String getName() { 269 | return name; 270 | } 271 | 272 | @Override 273 | public File getFile() { 274 | return file; 275 | } 276 | 277 | @Override 278 | public ConfigFormat getFormat() { 279 | return format; 280 | } 281 | 282 | @Override 283 | public CoPlugin getPlugin() { 284 | return plugin; 285 | } 286 | 287 | } 288 | -------------------------------------------------------------------------------- /core/src/main/java/com/coalesce/config/json/JsonEntry.java: -------------------------------------------------------------------------------- 1 | package com.coalesce.config.json; 2 | 3 | import com.coalesce.config.IConfig; 4 | import com.coalesce.config.IEntry; 5 | 6 | import java.util.List; 7 | 8 | public final class JsonEntry implements IEntry { 9 | 10 | private String key; 11 | private Object value; 12 | private final IConfig config; 13 | 14 | public JsonEntry(IConfig config, String key) { 15 | this.config = config; 16 | this.key = key; 17 | this.value = getConfig().getValue(key); 18 | } 19 | 20 | public JsonEntry(IConfig config, String key, Object value) { 21 | this.config = config; 22 | this.key = key; 23 | this.value = value; 24 | } 25 | 26 | @Override 27 | public String getString() { 28 | return (String)value; 29 | } 30 | 31 | @Override 32 | public double getDouble() { 33 | return (Double)value; 34 | } 35 | 36 | @Override 37 | public int getInt() { 38 | return (Integer)value; 39 | } 40 | 41 | @Override 42 | public long getLong() { 43 | return (Long)value; 44 | } 45 | 46 | @Override 47 | public boolean getBoolean() { 48 | return (Boolean)value; 49 | } 50 | 51 | @Override 52 | public List getList() { 53 | return (List)value; 54 | } 55 | 56 | @Override 57 | public String getPath() { 58 | return key; 59 | } 60 | 61 | @Override 62 | public Object getValue() { 63 | return value; 64 | } 65 | 66 | @Override 67 | public List getStringList() { 68 | return (List)getList(); 69 | } 70 | 71 | @Override 72 | public IEntry setPath(String newpath) { 73 | remove(); 74 | setValue(newpath, value); 75 | return this; 76 | } 77 | 78 | @Override 79 | public IEntry setValue(Object value) { 80 | setValue(key, value); 81 | return this; 82 | } 83 | 84 | @Override 85 | public IConfig getConfig() { 86 | return config; 87 | } 88 | 89 | @Override 90 | public String getName() { 91 | if (getPath().contains(".")) { 92 | return getPath().substring(getPath().lastIndexOf(".") + 1); 93 | } 94 | return getPath(); 95 | } 96 | 97 | @Override 98 | public IEntry setConfig(IConfig config) { 99 | return null; 100 | } 101 | 102 | @Override 103 | public void remove() { 104 | setValue(key, null); 105 | } 106 | 107 | private void setValue(String key, Object value) { 108 | JsonConfig jsonConfig = (JsonConfig)config; 109 | jsonConfig.getJson().put(key, value); //If anyone could remove the annoying bitching from intellij, that would be great. 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /core/src/main/java/com/coalesce/config/yml/YamlConfig.java: -------------------------------------------------------------------------------- 1 | package com.coalesce.config.yml; 2 | 3 | import com.coalesce.config.ConfigFormat; 4 | import com.coalesce.config.IConfig; 5 | import com.coalesce.config.IEntry; 6 | import com.coalesce.config.ISection; 7 | import com.coalesce.config.common.Section; 8 | import com.coalesce.plugin.CoPlugin; 9 | import com.google.common.io.Files; 10 | import org.bukkit.configuration.file.YamlConfiguration; 11 | 12 | import java.io.File; 13 | import java.io.IOException; 14 | import java.text.DateFormat; 15 | import java.text.SimpleDateFormat; 16 | import java.util.ArrayList; 17 | import java.util.Collection; 18 | import java.util.Date; 19 | import java.util.List; 20 | 21 | public abstract class YamlConfig implements IConfig { 22 | 23 | private Collection entries = new ArrayList<>(); 24 | private final ConfigFormat format; 25 | private YamlConfiguration config; 26 | private final CoPlugin plugin; 27 | private final File dir, file; 28 | private final String name; 29 | 30 | protected YamlConfig(String name, CoPlugin plugin) { 31 | this.name = name; 32 | this.plugin = plugin; 33 | this.format = ConfigFormat.YAML; 34 | 35 | //Creating the correct directory and generating the file. 36 | if (!name.contains(File.separator)) { 37 | this.dir = plugin.getDataFolder(); 38 | this.file = new File(dir.getAbsolutePath() + File.separator + name + ".yml"); 39 | } else { 40 | int last = name.lastIndexOf(File.separator); 41 | String fileName = name.substring(last + 1); 42 | String path = name.substring(0, last); 43 | this.dir = new File(plugin.getDataFolder().getAbsolutePath() + File.separator + path); 44 | this.file = new File(dir + File.separator + fileName + ".yml"); 45 | } 46 | if (!dir.exists()) { 47 | dir.mkdirs(); 48 | } 49 | try { 50 | file.createNewFile(); 51 | } 52 | catch (IOException e) { 53 | e.printStackTrace(); 54 | } 55 | 56 | //Loading the configuration. 57 | this.config = YamlConfiguration.loadConfiguration(file); 58 | if (!plugin.getConfigurations().contains(this)) { //Registers this configuration 59 | plugin.getConfigurations().add(this); 60 | } 61 | getBase().getKeys(true).forEach(entry -> { //Adds entries to the entries collection. 62 | if (getEntry(entry) == null) { 63 | entries.add(new YamlEntry(this, entry, getBase().get(entry))); 64 | } 65 | }); 66 | } 67 | 68 | @Override 69 | public IEntry getEntry(String path) { 70 | for (IEntry entry : entries) { 71 | if (entry.getPath().matches(path)) { 72 | return entry; 73 | } 74 | } 75 | return null; 76 | } 77 | 78 | @Override 79 | public String getString(String path) { 80 | return getEntry(path).getString(); 81 | } 82 | 83 | @Override 84 | public double getDouble(String path) { 85 | return getEntry(path).getDouble(); 86 | } 87 | 88 | @Override 89 | public int getInt(String path) { 90 | return getEntry(path).getInt(); 91 | } 92 | 93 | @Override 94 | public long getLong(String path) { 95 | return getEntry(path).getLong(); 96 | } 97 | 98 | @Override 99 | public boolean getBoolean(String path) { 100 | return getEntry(path).getBoolean(); 101 | } 102 | 103 | @Override 104 | public List getList(String path) { 105 | return getEntry(path).getList(); 106 | } 107 | 108 | @Override 109 | public Object getValue(String path) { 110 | return getEntry(path).getValue(); 111 | } 112 | 113 | @Override 114 | public boolean contains(String path, boolean exact) { 115 | if (exact) { 116 | return getEntry(path) == null; 117 | } 118 | for (IEntry entry : entries) { 119 | if (entry.getPath().startsWith(path)) { 120 | return true; 121 | } 122 | } 123 | return false; 124 | } 125 | 126 | @Override 127 | public Collection getEntryFromValue(Object value) { 128 | Collection found = new ArrayList<>(); 129 | entries.forEach(entry -> { 130 | if (entry.getValue().equals(value)) { 131 | found.add(entry); 132 | } 133 | }); 134 | return found; 135 | } 136 | 137 | @Override 138 | public Collection getEntries() { 139 | getBase().getKeys(true).forEach(entry -> { 140 | if (getEntry(entry) == null) { 141 | entries.add(new YamlEntry(this, entry, getBase().get(entry))); 142 | } 143 | }); 144 | return entries; 145 | } 146 | 147 | @Override 148 | public void setEntry(String path, Object value) { 149 | IEntry entry = new YamlEntry(this, path, value); 150 | if (getEntry(path) == null) { 151 | setValue(entry.getPath(), entry.getValue()); 152 | entries.add(entry); 153 | return; 154 | } 155 | entries.remove(entry); 156 | entry = getEntry(path).setValue(value); 157 | entries.add(entry); 158 | } 159 | 160 | @Override 161 | public void addEntry(String path, Object value) { 162 | IEntry entry; 163 | if (getBase().get(path) == null) { 164 | entry = new YamlEntry(this, path, value); 165 | setValue(entry.getPath(), entry.getValue()); 166 | } else { 167 | entry = new YamlEntry(this, path, getBase().get(path)); 168 | } 169 | entries.add(entry); 170 | } 171 | 172 | @Override 173 | public void removeEntry(IEntry entry) { 174 | entry.remove(); 175 | } 176 | 177 | @Override 178 | public void removeEntry(String path) { 179 | getEntry(path).remove(); 180 | } 181 | 182 | @Override 183 | public IConfig getConfig() { 184 | return this; 185 | } 186 | 187 | @Override 188 | public void clear() { 189 | entries.forEach(IEntry::remove); 190 | } 191 | 192 | @Override 193 | public void backup() { 194 | DateFormat format = new SimpleDateFormat("yyyy.dd.MM-hh.mm.ss"); 195 | File file = new File(dir + File.separator + "backups"); 196 | File bckp = new File(file + File.separator + name + format.format(new Date()) + ".yml"); 197 | if (!dir.exists() || bckp.exists() || !this.file.exists()) { 198 | return; 199 | } 200 | if (!file.exists()) { 201 | file.mkdir(); 202 | } 203 | try { 204 | Files.copy(this.file, bckp); 205 | } 206 | catch (IOException e) { 207 | e.printStackTrace(); 208 | } 209 | } 210 | 211 | @Override 212 | public void delete() { 213 | file.delete(); 214 | } 215 | 216 | @Override 217 | public String getName() { 218 | return name; 219 | } 220 | 221 | @Override 222 | public File getFile() { 223 | return file; 224 | } 225 | 226 | @Override 227 | public ConfigFormat getFormat() { 228 | return format; 229 | } 230 | 231 | @Override 232 | public CoPlugin getPlugin() { 233 | return plugin; 234 | } 235 | 236 | @Override 237 | public ISection getSection(String path) { 238 | return new Section(path, this, plugin); 239 | } 240 | 241 | @Override 242 | public List getStringList(String path) { 243 | return (List)getList(path); 244 | } 245 | 246 | /** 247 | * The base YAML file. 248 | * 249 | * @return YamlConfiguration from the Bukkit API 250 | */ 251 | public YamlConfiguration getBase() { 252 | return config; 253 | } 254 | 255 | private void setValue(String path, Object value) { 256 | getBase().set(path, value); 257 | try { 258 | getBase().save(file); 259 | } 260 | catch (IOException e) { 261 | e.printStackTrace(); 262 | } 263 | } 264 | } 265 | -------------------------------------------------------------------------------- /core/src/main/java/com/coalesce/config/yml/YamlEntry.java: -------------------------------------------------------------------------------- 1 | package com.coalesce.config.yml; 2 | 3 | import com.coalesce.config.IConfig; 4 | import com.coalesce.config.IEntry; 5 | 6 | import java.io.IOException; 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | public final class YamlEntry implements IEntry { 11 | 12 | private String key; 13 | private Object value; 14 | private final IConfig config; 15 | 16 | public YamlEntry(IConfig config, String key) { 17 | this.config = config; 18 | this.key = key; 19 | this.value = getConfig().getValue(key); 20 | } 21 | 22 | public YamlEntry(IConfig config, String key, Object value) { 23 | this.config = config; 24 | this.key = key; 25 | this.value = value; 26 | } 27 | 28 | @Override 29 | public String getString() { 30 | return (String)value; 31 | } 32 | 33 | @Override 34 | public double getDouble() { 35 | return (Double)value; 36 | } 37 | 38 | @Override 39 | public int getInt() { 40 | return (Integer)value; 41 | } 42 | 43 | @Override 44 | public long getLong() { 45 | return (Long)value; 46 | } 47 | 48 | @Override 49 | public boolean getBoolean() { 50 | return (Boolean)value; 51 | } 52 | 53 | @Override 54 | public List getList() { 55 | //From Bukkit MemorySection#getList 56 | return (value instanceof List) ? (List)value : null; 57 | } 58 | 59 | @Override 60 | public List getStringList() { 61 | //From Bukkit MemorySection#getStringList 62 | if (getList() == null) { 63 | return new ArrayList<>(0); 64 | } 65 | 66 | List result = new ArrayList<>(); 67 | 68 | for (Object object : getList()) { 69 | if (object instanceof String) { 70 | result.add(String.valueOf(object)); 71 | } 72 | } 73 | 74 | return result; 75 | } 76 | 77 | @Override 78 | public String getName() { 79 | if (getPath().contains(".")) { 80 | return getPath().substring(getPath().lastIndexOf(".") + 1); 81 | } 82 | return getPath(); 83 | } 84 | 85 | @Override 86 | public String getPath() { 87 | return key; 88 | } 89 | 90 | @Override 91 | public Object getValue() { 92 | return value; 93 | } 94 | 95 | @Override 96 | public IEntry setPath(String newpath) { 97 | remove(); 98 | setValue(newpath, value); 99 | return this; 100 | } 101 | 102 | @Override 103 | public IEntry setValue(Object value) { 104 | setValue(key, value); 105 | return this; 106 | } 107 | 108 | @Override 109 | public IConfig getConfig() { 110 | return config; 111 | } 112 | 113 | @Override 114 | public IEntry setConfig(IConfig config) { 115 | return null; 116 | } 117 | 118 | @Override 119 | public void remove() { 120 | setValue(key, null); 121 | } 122 | 123 | private void setValue(String key, Object value) { 124 | YamlConfig cfg = ((YamlConfig)config); 125 | this.value = value; 126 | cfg.getBase().set(key, value); 127 | try { 128 | cfg.getBase().save(cfg.getFile()); 129 | } 130 | catch (IOException e) { 131 | e.printStackTrace(); 132 | } 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /core/src/main/java/com/coalesce/gui/Gui.java: -------------------------------------------------------------------------------- 1 | package com.coalesce.gui; 2 | 3 | import org.bukkit.entity.Player; 4 | import org.bukkit.event.inventory.InventoryClickEvent; 5 | 6 | import java.util.function.Consumer; 7 | 8 | /** 9 | * Provides a general contract for a graphical user interface based around icons arrayed on a menu. 10 | * 11 | * @param The type of clickable icons. 12 | * @param The type of this gui (used to allow chaining method calls). 13 | */ 14 | public interface Gui { 15 | 16 | /** 17 | * Add an item to the first available slot, and set the method to run when the item is clicked 18 | * 19 | * @param item the item 20 | * @param onClick the Consumer to run on click 21 | * @return this, for chaining 22 | */ 23 | T addItem(F item, Consumer onClick); 24 | 25 | /** 26 | * Set an item in the given slot, and set the method to run when the item is clicked 27 | * 28 | * @param index the index in the inventory 29 | * @param item the item 30 | * @param onClick the Consumer to run on click 31 | * @return this, for chaining 32 | */ 33 | T setItem(int index, F item, Consumer onClick); 34 | 35 | /** 36 | * Removes an item from the provided slot 37 | * 38 | * @param index the slot to remove the item from 39 | * @return this, for chaining 40 | */ 41 | T removeItem(int index); 42 | 43 | /** 44 | * Open the inventory 45 | * 46 | * @param player the player 47 | */ 48 | void open(Player player); 49 | 50 | /** 51 | * Clear the inventory(s) 52 | */ 53 | void clear(); 54 | 55 | } -------------------------------------------------------------------------------- /core/src/main/java/com/coalesce/gui/ItemBuilder.java: -------------------------------------------------------------------------------- 1 | package com.coalesce.gui; 2 | 3 | import org.bukkit.ChatColor; 4 | import org.bukkit.Material; 5 | import org.bukkit.enchantments.Enchantment; 6 | import org.bukkit.inventory.ItemFlag; 7 | import org.bukkit.inventory.ItemStack; 8 | import org.bukkit.inventory.meta.ItemMeta; 9 | 10 | import java.util.List; 11 | import java.util.stream.Collectors; 12 | import java.util.stream.Stream; 13 | 14 | /** 15 | * Simple Builder class for the {@link ItemStack} class. 16 | */ 17 | public class ItemBuilder { 18 | 19 | private ItemStack itemStack; 20 | 21 | public ItemBuilder(Material material) { 22 | this.itemStack = new ItemStack(material); 23 | } 24 | 25 | public ItemBuilder amount(int amount) { 26 | itemStack.setAmount(amount); 27 | return this; 28 | } 29 | 30 | public ItemBuilder durability(int durability) { 31 | itemStack.setDurability((short)durability); 32 | return this; 33 | } 34 | 35 | public ItemBuilder displayName(String displayName) { 36 | ItemMeta meta = itemStack.getItemMeta(); 37 | meta.setDisplayName(displayName); 38 | itemStack.setItemMeta(meta); 39 | return this; 40 | } 41 | 42 | public ItemBuilder lore(String... lore) { 43 | ItemMeta meta = itemStack.getItemMeta(); 44 | meta.setLore(Stream.of(lore).map(s -> ChatColor.WHITE + s).collect(Collectors.toList())); 45 | itemStack.setItemMeta(meta); 46 | return this; 47 | } 48 | 49 | public ItemBuilder lore(List lore) { 50 | ItemMeta meta = itemStack.getItemMeta(); 51 | meta.setLore(lore); 52 | itemStack.setItemMeta(meta); 53 | return this; 54 | } 55 | 56 | public ItemBuilder itemFlags(ItemFlag... flags) { 57 | ItemMeta meta = itemStack.getItemMeta(); 58 | meta.addItemFlags(flags); 59 | itemStack.setItemMeta(meta); 60 | return this; 61 | } 62 | 63 | public ItemBuilder enchant(Enchantment enchantment, int level) { 64 | itemStack.addUnsafeEnchantment(enchantment, level); 65 | return this; 66 | } 67 | 68 | public ItemBuilder unbreakable() { 69 | ItemMeta meta = itemStack.getItemMeta(); 70 | meta.setUnbreakable(true); 71 | itemStack.setItemMeta(meta); 72 | return this; 73 | } 74 | 75 | public ItemStack build() { 76 | return itemStack; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /core/src/main/java/com/coalesce/gui/PlayerGui.java: -------------------------------------------------------------------------------- 1 | package com.coalesce.gui; 2 | 3 | import com.coalesce.plugin.CoPlugin; 4 | import org.bukkit.Bukkit; 5 | import org.bukkit.entity.Player; 6 | import org.bukkit.event.Event.Result; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.inventory.InventoryClickEvent; 10 | import org.bukkit.event.inventory.InventoryCloseEvent; 11 | import org.bukkit.event.inventory.InventoryDragEvent; 12 | import org.bukkit.inventory.Inventory; 13 | import org.bukkit.inventory.ItemStack; 14 | 15 | import java.util.HashMap; 16 | import java.util.Map; 17 | import java.util.UUID; 18 | import java.util.function.Consumer; 19 | import java.util.function.Function; 20 | 21 | /** 22 | * Represents an inventory that can change between players. 23 | */ 24 | public abstract class PlayerGui implements Gui, PlayerGui>, Listener { 25 | 26 | /** 27 | * The plugin 28 | */ 29 | protected final CoPlugin plugin; 30 | 31 | /** 32 | * The size of the inventory 33 | */ 34 | protected final int size; 35 | /** 36 | * The function to apply to get the title 37 | */ 38 | protected final Function title; 39 | /** 40 | * The functions to apply to get each item 41 | */ 42 | private final Function[] items; 43 | 44 | /** 45 | * The consumers to run when each item is clicked 46 | */ 47 | private final Consumer[] listeners; 48 | 49 | /** 50 | * Map of current inventories, entries are removed on close 51 | */ 52 | protected final Map inventories; 53 | 54 | @SuppressWarnings( "unchecked" ) 55 | public PlayerGui(CoPlugin plugin, int size, Function title) { 56 | this.plugin = plugin; 57 | this.size = size; 58 | this.title = title; 59 | this.items = new Function[size]; 60 | this.listeners = new Consumer[size]; 61 | this.inventories = new HashMap<>(); 62 | 63 | Bukkit.getPluginManager().registerEvents(this, plugin); 64 | } 65 | 66 | public PlayerGui(CoPlugin plugin, int size, String title) { 67 | this(plugin, size, p -> title); 68 | } 69 | 70 | @Override 71 | public PlayerGui addItem(Function item, Consumer onClick) { 72 | for (int i = 0; i < items.length; i++) { 73 | if (items[i] == null) { 74 | this.items[i] = item; 75 | this.listeners[i] = onClick; 76 | break; 77 | } 78 | } 79 | return this; 80 | } 81 | 82 | @Override 83 | public PlayerGui setItem(int index, Function item, Consumer onClick) { 84 | this.items[index] = item; 85 | this.listeners[index] = onClick; 86 | return this; 87 | } 88 | 89 | @Override 90 | public PlayerGui removeItem(int index) { 91 | 92 | this.items[index] = null; 93 | this.listeners[index] = null; 94 | return this; 95 | } 96 | 97 | public PlayerGui removeItems(int startIndex, int countToRemove) { 98 | 99 | for (int i = startIndex; i < startIndex + countToRemove; i++) { 100 | if (i >= size) { 101 | break; 102 | } 103 | 104 | this.items[i] = null; 105 | this.listeners[i] = null; 106 | } 107 | return this; 108 | } 109 | 110 | public void update(Player player) { 111 | Inventory inventory = inventories.computeIfAbsent(player.getUniqueId(), uuid -> this.getNewInventory(player)); 112 | buildInventory(player, inventory); 113 | player.updateInventory(); 114 | } 115 | 116 | @Override 117 | public void open(Player player) { 118 | Inventory inventory = inventories.computeIfAbsent(player.getUniqueId(), uuid -> this.getNewInventory(player)); 119 | player.openInventory(inventory); 120 | } 121 | 122 | 123 | private Inventory getNewInventory(Player player) { 124 | Inventory inventory = Bukkit.createInventory(null, this.size, this.title.apply(player)); 125 | buildInventory(player, inventory); 126 | return inventory; 127 | } 128 | 129 | private void buildInventory(Player player, Inventory inventory) { 130 | inventory.clear(); 131 | for (int i = 0; i < items.length; i++) { 132 | Function function = items[i]; 133 | if (function != null) { 134 | ItemStack item = function.apply(player); 135 | inventory.setItem(i, item); 136 | } 137 | } 138 | } 139 | 140 | @Override 141 | public void clear() { 142 | Bukkit.getOnlinePlayers().stream().filter(p -> inventories.containsKey(p.getUniqueId())).forEach(p -> p.closeInventory()); 143 | inventories.clear(); 144 | } 145 | 146 | /** 147 | * Unregisters all listeners of the GUI. This is done to get rid of useless {@link Listener}s that are no longer used 148 | */ 149 | public void destroy() { 150 | 151 | InventoryCloseEvent.getHandlerList().unregister(this); 152 | InventoryDragEvent.getHandlerList().unregister(this); 153 | InventoryCloseEvent.getHandlerList().unregister(this); 154 | 155 | inventories.clear(); 156 | } 157 | 158 | @EventHandler 159 | public void onInventoryClick(InventoryClickEvent event) { 160 | if (!(event.getWhoClicked() instanceof Player) || event.getClickedInventory() == null) { 161 | return; 162 | } 163 | Player player = (Player)event.getWhoClicked(); 164 | Inventory inventory = inventories.get(player.getUniqueId()); 165 | if (inventory == null) { 166 | return; 167 | } 168 | 169 | if (inventory.equals(event.getClickedInventory())) { 170 | event.setCancelled(true); 171 | Consumer onClick = listeners[event.getSlot()]; 172 | if (onClick != null) { 173 | try { 174 | onClick.accept(event); 175 | } 176 | catch (Exception e) { 177 | throw new RuntimeException("Failed to handle inventory click event", e); 178 | } 179 | } 180 | } else if (inventories.containsValue(event.getView().getTopInventory())) { 181 | event.setResult(Result.DENY); 182 | event.setCancelled(true); 183 | } 184 | } 185 | 186 | @EventHandler 187 | public void onInventoryDrag(InventoryDragEvent event) { 188 | if (inventories.containsValue(event.getInventory()) && event.getWhoClicked() instanceof Player) { 189 | event.setResult(Result.DENY); 190 | event.setCancelled(true); 191 | ((Player)event.getWhoClicked()).updateInventory(); 192 | } 193 | } 194 | 195 | @EventHandler 196 | public void onInventoryClose(InventoryCloseEvent event) { 197 | this.onClose(event); 198 | } 199 | 200 | public void onClose(InventoryCloseEvent event) { 201 | if (!(event.getPlayer() instanceof Player) || !inventories.values().stream().anyMatch(inv -> event.getInventory().equals(inv))) { 202 | return; 203 | } 204 | 205 | inventories.remove(event.getPlayer().getUniqueId()); 206 | } 207 | } -------------------------------------------------------------------------------- /core/src/main/java/com/coalesce/http/CoHTTP.java: -------------------------------------------------------------------------------- 1 | package com.coalesce.http; 2 | 3 | import com.google.common.util.concurrent.ListenableFuture; 4 | import com.google.common.util.concurrent.ListeningExecutorService; 5 | import com.google.common.util.concurrent.MoreExecutors; 6 | 7 | import java.io.BufferedReader; 8 | import java.io.DataOutputStream; 9 | import java.io.FileNotFoundException; 10 | import java.io.InputStreamReader; 11 | import java.net.HttpURLConnection; 12 | import java.net.URL; 13 | import java.util.HashMap; 14 | import java.util.concurrent.Executors; 15 | 16 | public class CoHTTP { 17 | 18 | private static ListeningExecutorService executor; 19 | 20 | // HTTP GET request 21 | public static ListenableFuture sendGet(String url, String userAgent) { 22 | 23 | return getExecutor().submit(() -> { 24 | 25 | StringBuffer response = new StringBuffer(); 26 | 27 | try { 28 | URL obj = new URL(url); 29 | 30 | HttpURLConnection con = (HttpURLConnection)obj.openConnection(); 31 | 32 | con.setRequestMethod("GET"); 33 | con.setRequestProperty("User-Agent", userAgent); 34 | 35 | BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream())); 36 | 37 | String inputLine; 38 | response = new StringBuffer(); 39 | 40 | while ((inputLine = in.readLine()) != null) { 41 | response.append(inputLine); 42 | } 43 | in.close(); 44 | } 45 | catch (FileNotFoundException e) { 46 | 47 | } 48 | catch (Exception e) { 49 | e.printStackTrace(); 50 | } 51 | 52 | return response.toString(); 53 | }); 54 | 55 | } 56 | 57 | // HTTP POST request 58 | public static ListenableFuture sendPost(String url, HashMap arguments, String userAgent) { 59 | 60 | return getExecutor().submit(() -> { 61 | 62 | URL obj = new URL(url); 63 | HttpURLConnection con = (HttpURLConnection)obj.openConnection(); 64 | 65 | // add reuqest header 66 | con.setRequestMethod("POST"); 67 | con.setRequestProperty("User-Agent", userAgent); 68 | con.setRequestProperty("Accept-Language", "en-US,en;q=0.5"); 69 | 70 | StringBuilder sb = new StringBuilder(); 71 | for (String str : arguments.keySet()) { 72 | if (sb.length() != 0) { 73 | sb.append("&"); 74 | } 75 | sb.append(str).append("=").append(arguments.get(str)); 76 | } 77 | 78 | // Send post request 79 | con.setDoOutput(true); 80 | DataOutputStream wr = new DataOutputStream(con.getOutputStream()); 81 | wr.writeBytes(sb.toString()); 82 | wr.flush(); 83 | wr.close(); 84 | 85 | BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream())); 86 | String inputLine; 87 | StringBuffer response = new StringBuffer(); 88 | 89 | while ((inputLine = in.readLine()) != null) { 90 | response.append(inputLine); 91 | } 92 | in.close(); 93 | 94 | // return result 95 | return response.toString(); 96 | 97 | }); 98 | 99 | } 100 | 101 | private static ListeningExecutorService getExecutor() { 102 | if (executor == null) { 103 | executor = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool()); 104 | } 105 | 106 | return executor; 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /core/src/main/java/com/coalesce/plugin/CoLogger.java: -------------------------------------------------------------------------------- 1 | package com.coalesce.plugin; 2 | 3 | import org.bukkit.command.ConsoleCommandSender; 4 | 5 | import static org.bukkit.ChatColor.*; 6 | 7 | public class CoLogger { 8 | 9 | private CoPlugin plugin; 10 | 11 | public CoLogger(CoPlugin plugin) { 12 | this.plugin = plugin; 13 | } 14 | 15 | /** 16 | * Logs to console with logging level as INFO. 17 | * 18 | * @param message The message to log. 19 | */ 20 | public void info(String message) { 21 | LogLevel.INFO.log(getConsole(), plugin, message); 22 | } 23 | 24 | /** 25 | * Logs to console with logging level as WARN. 26 | * 27 | * @param message The message to log. 28 | */ 29 | public void warn(String message) { 30 | LogLevel.WARN.log(getConsole(), plugin, message); 31 | } 32 | 33 | /** 34 | * Logs to console with logging level as ERROR. 35 | * 36 | * @param message The message to log. 37 | */ 38 | public void error(String message) { 39 | LogLevel.ERROR.log(getConsole(), plugin, message); 40 | } 41 | 42 | /** 43 | * Logs to console with logging level as DEBUG. 44 | * 45 | * @param message The message to log. 46 | */ 47 | public void debug(String message) { 48 | LogLevel.DEBUG.log(getConsole(), plugin, message); 49 | } 50 | 51 | private ConsoleCommandSender getConsole() { 52 | return plugin.getServer().getConsoleSender(); 53 | } 54 | 55 | enum LogLevel { 56 | 57 | INFO(WHITE + "Info"), 58 | DEBUG(BLUE + "Debug"), 59 | WARN(YELLOW + "Warn"), 60 | ERROR(RED + "Error"); 61 | 62 | private final String prefix; 63 | 64 | LogLevel(String prefix) { 65 | this.prefix = GRAY + "[" + AQUA + "%s " + prefix + GRAY + "]" + RESET; 66 | } 67 | 68 | public String getPrefix() { 69 | return prefix; 70 | } 71 | 72 | public void log(ConsoleCommandSender console, CoPlugin plugin, String message) { 73 | console.sendMessage(String.format(prefix, plugin.getDisplayName()) + ' ' + message); 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /core/src/main/java/com/coalesce/plugin/CoModule.java: -------------------------------------------------------------------------------- 1 | package com.coalesce.plugin; 2 | 3 | import org.bukkit.event.Listener; 4 | 5 | import static org.bukkit.ChatColor.DARK_RED; 6 | 7 | /** 8 | * Base class for sub "plugins", allows for modular servers 9 | */ 10 | public abstract class CoModule implements Listener { 11 | 12 | private final CoPlugin plugin; 13 | 14 | private final String name; 15 | private boolean isEnabled; 16 | 17 | /** 18 | * Create a new module 19 | * 20 | * @param plugin The plugin that's creating this module 21 | * @param name The name of this module 22 | */ 23 | public CoModule(CoPlugin plugin, String name) { 24 | this.plugin = plugin; 25 | this.name = name; 26 | } 27 | 28 | /** 29 | * Get the {@link CoPlugin} that created this module 30 | * 31 | * @return The {@link CoPlugin} 32 | */ 33 | public CoPlugin getPlugin() { 34 | return plugin; 35 | } 36 | 37 | public boolean isEnabled() { 38 | return isEnabled; 39 | } 40 | 41 | public String getName() { 42 | return name; 43 | } 44 | 45 | public void enable() { 46 | if (isEnabled) { 47 | throw new IllegalStateException("Module " + getName() + " is already enabled"); 48 | } 49 | 50 | try { 51 | onEnable(); 52 | getPlugin().registerListener(this); 53 | } 54 | catch (Exception e) { 55 | plugin.getCoLogger().error(DARK_RED + "Failed to enable module " + getName()); 56 | e.printStackTrace(); 57 | return; 58 | } 59 | 60 | isEnabled = true; 61 | } 62 | 63 | public void disable() { 64 | if (!isEnabled) { 65 | throw new IllegalStateException("Module " + getName() + " isn't enabled"); 66 | } 67 | 68 | isEnabled = false; 69 | try { 70 | onDisable(); 71 | getPlugin().unregisterListener(this); 72 | } 73 | catch (Exception e) { 74 | plugin.getCoLogger().warn(DARK_RED + "Failed to disable module " + getName()); 75 | e.printStackTrace(); 76 | } 77 | } 78 | 79 | 80 | /** 81 | * Called when this module is successfully enabled 82 | */ 83 | protected abstract void onEnable() throws Exception; 84 | 85 | /** 86 | * Called when this module is successfully disabled 87 | */ 88 | protected abstract void onDisable() throws Exception; 89 | 90 | } 91 | -------------------------------------------------------------------------------- /core/src/main/java/com/coalesce/plugin/CoPlugin.java: -------------------------------------------------------------------------------- 1 | package com.coalesce.plugin; 2 | 3 | import com.coalesce.chat.CoFormatter; 4 | import com.coalesce.command.CoCommand; 5 | import com.coalesce.command.CommandRegister; 6 | import com.coalesce.config.IConfig; 7 | import com.coalesce.updater.UpdateCheck; 8 | import com.google.common.collect.ImmutableList; 9 | import org.bukkit.Bukkit; 10 | import org.bukkit.ChatColor; 11 | import org.bukkit.command.CommandMap; 12 | import org.bukkit.event.HandlerList; 13 | import org.bukkit.event.Listener; 14 | import org.bukkit.plugin.java.JavaPlugin; 15 | 16 | import java.io.File; 17 | import java.lang.reflect.Field; 18 | import java.util.*; 19 | 20 | import static org.bukkit.ChatColor.DARK_RED; 21 | 22 | public abstract class CoPlugin extends JavaPlugin implements Listener { 23 | 24 | private final List modules = new LinkedList<>(); 25 | private Collection configs = new ArrayList<>(); 26 | private Set commands = new HashSet<>(); 27 | private ChatColor pluginColor = ChatColor.WHITE; 28 | private CoFormatter formatter; 29 | private String displayName; 30 | private CoLogger logger; 31 | 32 | @Override 33 | public final void onEnable() { 34 | 35 | this.displayName = pluginColor + getName(); 36 | 37 | //Setup basic things 38 | logger = new CoLogger(this); 39 | formatter = new CoFormatter(this); 40 | 41 | //Try to call the onEnable 42 | try { 43 | onPluginEnable(); 44 | } 45 | catch (Exception e) { 46 | logger.error(DARK_RED + "Failed to enable module " + getName()); 47 | e.printStackTrace(); 48 | return; 49 | } 50 | 51 | enableModules(); 52 | } 53 | 54 | @Override 55 | public final void onDisable() { 56 | disableModules(); 57 | try { 58 | onPluginDisable(); 59 | } 60 | catch (Exception e) { 61 | logger.warn(DARK_RED + "Failed to disable module " + getName()); 62 | e.printStackTrace(); 63 | } 64 | } 65 | 66 | @Override 67 | public final void onLoad() { 68 | 69 | try { 70 | onPluginLoad(); 71 | } 72 | catch (Exception e) { 73 | logger.error(DARK_RED + "Failed to load module " + getName()); 74 | e.printStackTrace(); 75 | return; 76 | } 77 | 78 | } 79 | 80 | public void onPluginEnable() throws Exception { 81 | } 82 | 83 | public void onPluginDisable() throws Exception { 84 | } 85 | 86 | public void onPluginLoad() throws Exception { 87 | } 88 | 89 | /** 90 | * The color of the plugin name in pluginMessages etc. 91 | * 92 | * @param color The color you want this plugin to show up as in plugin messages. 93 | */ 94 | public void setPluginColor(ChatColor color) { 95 | this.pluginColor = color; 96 | this.displayName = pluginColor + getName() + ChatColor.RESET; 97 | } 98 | 99 | /** 100 | * Gets the displayname of the plugin. 101 | * 102 | * @return Returns a formatted displayName for this plugin. 103 | */ 104 | public String getDisplayName() { 105 | return displayName; 106 | } 107 | 108 | /** 109 | * Adds a module to the plugin. 110 | * 111 | * @param modules The module to add. 112 | */ 113 | protected final void addModules(CoModule... modules) { 114 | Collections.addAll(this.modules, modules); 115 | } 116 | 117 | /** 118 | * Gives a list of all the modules in this plugin. 119 | * 120 | * @return A list of modules. 121 | */ 122 | public final List getModules() { 123 | return ImmutableList.copyOf(modules); 124 | } 125 | 126 | /** 127 | * Gets a module. 128 | * 129 | * @param clazz The class that extends CoModule. 130 | * @param A module class. 131 | * @return The specified module. 132 | */ 133 | public final Optional getModule(Class clazz) { 134 | Iterator iterator = getModules().stream().filter(coModule -> coModule.getClass().equals(clazz)).map(coModule -> ((M)coModule)).iterator(); 135 | return Optional.ofNullable(iterator.hasNext() ? iterator.next() : null); 136 | } 137 | 138 | /** 139 | * Enables all the modules. 140 | */ 141 | public final void enableModules() { 142 | getModules().forEach(CoModule::enable); 143 | } 144 | 145 | /** 146 | * Disables all the plugins modules. 147 | */ 148 | public final void disableModules() { 149 | getModules().forEach(CoModule::disable); 150 | } 151 | 152 | /** 153 | * Registers one listener. 154 | * 155 | * @param listener The listener to register. 156 | */ 157 | public final void registerListener(Listener listener) { 158 | getServer().getPluginManager().registerEvents(listener, this); 159 | } 160 | 161 | /** 162 | * Registers an array of listeners. 163 | * 164 | * @param listeners The array of listeners to add. 165 | */ 166 | public final void registerListeners(Listener... listeners) { 167 | Arrays.asList(listeners).forEach(this::registerListener); 168 | } 169 | 170 | /** 171 | * Unregisters a Listener from the server. 172 | * 173 | * @param listener The listener to unregister. 174 | */ 175 | public final void unregisterListener(Listener listener) { 176 | HandlerList.unregisterAll(listener); 177 | } 178 | 179 | /** 180 | * Gets the Coalesce Logger. 181 | * 182 | * @return CoLogger 183 | */ 184 | public final CoLogger getCoLogger() { 185 | return logger; 186 | } 187 | 188 | /** 189 | * Gets the Coalesce Formatter. 190 | * 191 | * @return CoFormatter 192 | */ 193 | public final CoFormatter getFormatter() { 194 | return formatter; 195 | } 196 | 197 | /** 198 | * A collection of all the current configurations of a plugin. 199 | * 200 | * @return A configuration file list. 201 | */ 202 | public final Collection getConfigurations() { 203 | return configs; 204 | } 205 | 206 | /** 207 | * Looks for a config of any type. (If the config being looked up does not exist, it defaults to creating it in yml) 208 | * 209 | * @param name The name of the config you're looking for. 210 | * @return The config. 211 | */ 212 | public final IConfig getConfig(String name) { 213 | for (IConfig config : configs) { 214 | if (config.getName().equals(name)) { 215 | return config; 216 | } 217 | } 218 | return null; 219 | } 220 | 221 | /** 222 | * Add several commands to the plugin. 223 | * 224 | * @param commands The command to add. 225 | */ 226 | public final void addCommand(CoCommand... commands) { 227 | CommandMap map = null; 228 | Field field; 229 | 230 | try { 231 | field = Bukkit.getServer().getClass().getDeclaredField("commandMap"); 232 | field.setAccessible(true); 233 | map = (CommandMap)field.get(Bukkit.getServer()); 234 | } 235 | catch (NoSuchFieldException | IllegalAccessException e) { 236 | e.printStackTrace(); 237 | } 238 | for (CoCommand command : commands) { 239 | if (map.getCommand(command.getName()) == null) { 240 | this.commands.add(command); 241 | map.register(getDisplayName(), new CommandRegister(command, this)); 242 | } 243 | } 244 | } 245 | 246 | /** 247 | * Adds a command to the plugin. 248 | * 249 | * @param command The command to add. 250 | */ 251 | public final void addCommand(CoCommand command) { 252 | CommandMap map = null; 253 | Field field; 254 | 255 | try { 256 | field = Bukkit.getServer().getClass().getDeclaredField("commandMap"); 257 | field.setAccessible(true); 258 | map = (CommandMap)field.get(Bukkit.getServer()); 259 | } 260 | catch (NoSuchFieldException | IllegalAccessException e) { 261 | e.printStackTrace(); 262 | } 263 | if (map.getCommand(command.getName()) == null) { 264 | this.commands.add(command); 265 | map.register(getDisplayName(), new CommandRegister(command, this)); 266 | } 267 | } 268 | 269 | /** 270 | * Gets a set of all the commands in this plugin. 271 | * 272 | * @return A command set. 273 | */ 274 | public final Set getCommands() { 275 | return commands; 276 | } 277 | 278 | /** 279 | * Checks if an update exists for this plugin. 280 | * 281 | * @param repositoryOwner The user or organization that this repository is held in. 282 | * @param repositoryName The name of the repository. 283 | * @param autoUpdate Whether or not to download a new version if it's out. 284 | */ 285 | public final void updateCheck(String repositoryOwner, String repositoryName, boolean autoUpdate) { 286 | new UpdateCheck(this, repositoryOwner, repositoryName, getFile(), autoUpdate); 287 | } 288 | } 289 | -------------------------------------------------------------------------------- /core/src/main/java/com/coalesce/plugin/PluginUtil.java: -------------------------------------------------------------------------------- 1 | package com.coalesce.plugin; 2 | 3 | import org.bukkit.Bukkit; 4 | import org.bukkit.command.Command; 5 | import org.bukkit.command.PluginCommand; 6 | import org.bukkit.command.SimpleCommandMap; 7 | import org.bukkit.event.Event; 8 | import org.bukkit.plugin.*; 9 | 10 | import java.io.File; 11 | import java.io.IOException; 12 | import java.lang.reflect.Field; 13 | import java.net.URLClassLoader; 14 | import java.util.Iterator; 15 | import java.util.List; 16 | import java.util.Map; 17 | import java.util.SortedSet; 18 | 19 | public class PluginUtil { 20 | 21 | /** 22 | * Loads and enables a plugin. 23 | * 24 | * @param file The plugin file 25 | * @return Whether the plugin was successfully loaded 26 | */ 27 | public static Plugin load(File file) { 28 | 29 | Plugin target = null; 30 | 31 | if (!file.getName().endsWith(".jar")) { 32 | return null; 33 | } 34 | 35 | try { 36 | target = Bukkit.getPluginManager().loadPlugin(file); 37 | 38 | } 39 | catch (InvalidDescriptionException e) { 40 | e.printStackTrace(); 41 | return null; 42 | } 43 | catch (InvalidPluginException e) { 44 | e.printStackTrace(); 45 | return null; 46 | } 47 | 48 | target.onLoad(); 49 | Bukkit.getPluginManager().enablePlugin(target); 50 | 51 | return target; 52 | } 53 | 54 | /** 55 | * Unload a plugin. 56 | * 57 | * @param plugin the plugin to unload 58 | * @return the message to send to the user. 59 | */ 60 | public static void unload(Plugin plugin) throws NoSuchFieldException, IllegalAccessException, IOException { 61 | 62 | String name = plugin.getName(); 63 | 64 | PluginManager pluginManager = Bukkit.getPluginManager(); 65 | 66 | SimpleCommandMap commandMap = null; 67 | 68 | List plugins = null; 69 | 70 | Map names = null; 71 | Map commands = null; 72 | Map> listeners = null; 73 | 74 | boolean reloadlisteners = true; 75 | 76 | if (pluginManager != null) { 77 | 78 | pluginManager.disablePlugin(plugin); 79 | 80 | Field pluginsField = Bukkit.getPluginManager().getClass().getDeclaredField("plugins"); 81 | pluginsField.setAccessible(true); 82 | plugins = (List)pluginsField.get(pluginManager); 83 | 84 | Field lookupNamesField = Bukkit.getPluginManager().getClass().getDeclaredField("lookupNames"); 85 | lookupNamesField.setAccessible(true); 86 | names = (Map)lookupNamesField.get(pluginManager); 87 | 88 | try { 89 | Field listenersField = Bukkit.getPluginManager().getClass().getDeclaredField("listeners"); 90 | listenersField.setAccessible(true); 91 | listeners = (Map>)listenersField.get(pluginManager); 92 | } 93 | catch (Exception e) { 94 | reloadlisteners = false; 95 | } 96 | 97 | Field commandMapField = Bukkit.getPluginManager().getClass().getDeclaredField("commandMap"); 98 | commandMapField.setAccessible(true); 99 | commandMap = (SimpleCommandMap)commandMapField.get(pluginManager); 100 | 101 | Field knownCommandsField = SimpleCommandMap.class.getDeclaredField("knownCommands"); 102 | knownCommandsField.setAccessible(true); 103 | commands = (Map)knownCommandsField.get(commandMap); 104 | 105 | } 106 | 107 | pluginManager.disablePlugin(plugin); 108 | 109 | if (plugins != null && plugins.contains(plugin)) { 110 | plugins.remove(plugin); 111 | } 112 | 113 | if (names != null && names.containsKey(name)) { 114 | names.remove(name); 115 | } 116 | 117 | if (listeners != null && reloadlisteners) { 118 | for (SortedSet set : listeners.values()) { 119 | for (Iterator it = set.iterator(); it.hasNext(); ) { 120 | RegisteredListener value = it.next(); 121 | if (value.getPlugin() == plugin) { 122 | it.remove(); 123 | } 124 | } 125 | } 126 | } 127 | 128 | if (commandMap != null) { 129 | for (Iterator> it = commands.entrySet().iterator(); it.hasNext(); ) { 130 | Map.Entry entry = it.next(); 131 | if (entry.getValue() instanceof PluginCommand) { 132 | PluginCommand c = (PluginCommand)entry.getValue(); 133 | if (c.getPlugin() == plugin) { 134 | c.unregister(commandMap); 135 | it.remove(); 136 | } 137 | } 138 | } 139 | } 140 | 141 | // Attempt to close the classloader to unlock any handles on the plugin's jar file. 142 | ClassLoader cl = plugin.getClass().getClassLoader(); 143 | 144 | if (cl instanceof URLClassLoader) { 145 | 146 | 147 | Field pluginField = cl.getClass().getDeclaredField("plugin"); 148 | pluginField.setAccessible(true); 149 | pluginField.set(cl, null); 150 | 151 | Field pluginInitField = cl.getClass().getDeclaredField("pluginInit"); 152 | pluginInitField.setAccessible(true); 153 | pluginInitField.set(cl, null); 154 | 155 | 156 | ((URLClassLoader)cl).close(); 157 | 158 | } 159 | 160 | // Will not work on processes started with the -XX:+DisableExplicitGC flag, but lets try it anyway. 161 | // This tries to get around the issue where Windows refuses to unlock jar files that were previously loaded into the JVM. 162 | System.gc(); 163 | } 164 | 165 | } 166 | -------------------------------------------------------------------------------- /core/src/main/java/com/coalesce/scoreboard/CoScoreboard.java: -------------------------------------------------------------------------------- 1 | package com.coalesce.scoreboard; 2 | 3 | import org.bukkit.entity.Player; 4 | import org.bukkit.scoreboard.Scoreboard; 5 | 6 | import java.util.Collection; 7 | 8 | /** 9 | * Provides a general contract for scoreboard display interfaces consisting of String data mapped to Integer scores 10 | * 11 | * @param The type of data to be displayed in the Scoreboard. 12 | */ 13 | public interface CoScoreboard { 14 | 15 | //Max number of entries that are allowed in a CoScoreboard 16 | int MAX_ENTRIES = 16; 17 | 18 | /** 19 | * Sends the {@link Scoreboard} representation of the CoScoreboard to the player 20 | * 21 | * @param player The player to send the {@link Scoreboard} to. 22 | */ 23 | void send(Player player); 24 | 25 | /** 26 | * Sends the {@link Scoreboard} representation of the CoScoreboard to the provided Collection of players 27 | * 28 | * @param players The players to send the {@link Scoreboard} to. 29 | */ 30 | void send(Collection players); 31 | 32 | /** 33 | * Sets the title to the provided element 34 | * 35 | * @param titleEntry The entry to set the title to 36 | */ 37 | void setTitle(T titleEntry); 38 | 39 | /** 40 | * Adds an entry to the CoScoreboard 41 | * 42 | * @param entry The entry to add 43 | * @param score The score of the entry 44 | */ 45 | void addEntry(T entry, int score); 46 | 47 | /** 48 | * Removes an entry from the CoScoreboard. 49 | * Nothing is done if the entry does not exist. 50 | * 51 | * @param entry The entry to remove 52 | */ 53 | void removeEntry(T entry); 54 | 55 | /** 56 | * Clears all entries from the CoScoreboard 57 | */ 58 | void clearEntries(); 59 | 60 | } 61 | -------------------------------------------------------------------------------- /core/src/main/java/com/coalesce/scoreboard/PlayerScoreboard.java: -------------------------------------------------------------------------------- 1 | package com.coalesce.scoreboard; 2 | 3 | import org.bukkit.Bukkit; 4 | import org.bukkit.entity.Player; 5 | import org.bukkit.scoreboard.DisplaySlot; 6 | import org.bukkit.scoreboard.Objective; 7 | import org.bukkit.scoreboard.Scoreboard; 8 | 9 | import java.util.Collection; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | import java.util.function.Function; 13 | import java.util.stream.Stream; 14 | 15 | public class PlayerScoreboard implements CoScoreboard> { 16 | 17 | private Function title; 18 | private final Map, Integer> entries; 19 | 20 | private PlayerScoreboard(Builder builder) { 21 | 22 | title = builder.title; 23 | entries = builder.entries; 24 | } 25 | 26 | @Override 27 | public void send(Player player) { 28 | 29 | Scoreboard scoreboard = generateScoreboard(player); 30 | player.setScoreboard(scoreboard); 31 | } 32 | 33 | @Override 34 | public void send(Collection players) { 35 | players.forEach(this::send); 36 | } 37 | 38 | private Scoreboard generateScoreboard(Player player) { 39 | 40 | Scoreboard scoreboard = Bukkit.getScoreboardManager().getNewScoreboard(); 41 | String titleString = title.apply(player); 42 | 43 | Objective scoreboardObjective = scoreboard.registerNewObjective(titleString, "dummy"); 44 | scoreboardObjective.setDisplayName(titleString); 45 | scoreboardObjective.setDisplaySlot(DisplaySlot.SIDEBAR); 46 | 47 | entries.forEach((playerStringFunction, score) -> { 48 | 49 | String entryString = playerStringFunction.apply(player); 50 | scoreboardObjective.getScore(entryString).setScore(score); 51 | 52 | }); 53 | 54 | return scoreboard; 55 | } 56 | 57 | @Override 58 | public void setTitle(Function titleEntry) { 59 | this.title = titleEntry; 60 | } 61 | 62 | @Override 63 | public void addEntry(Function entry, int score) { 64 | 65 | entries.put(entry, score); 66 | } 67 | 68 | public void addEntry(Function entry) { 69 | 70 | addEntry(entry, MAX_ENTRIES - entries.size()); 71 | } 72 | 73 | public void addEntries(Collection> entries) { 74 | 75 | entries.forEach(this::addEntry); 76 | } 77 | 78 | @Override 79 | public void removeEntry(Function entry) { 80 | entries.remove(entry); 81 | } 82 | 83 | @Override 84 | public void clearEntries() { 85 | entries.clear(); 86 | } 87 | 88 | public static class Builder { 89 | 90 | private Function title; 91 | private Map, Integer> entries; 92 | 93 | public Builder() { 94 | this.title = (player -> ""); 95 | 96 | entries = new HashMap<>(MAX_ENTRIES); 97 | } 98 | 99 | public Builder title(Function title) { 100 | this.title = title; 101 | 102 | return this; 103 | } 104 | 105 | public Builder title(String title) { 106 | this.title = (player -> title); 107 | 108 | return this; 109 | } 110 | 111 | public Builder addEntry(Function entry) { 112 | 113 | entries.put(entry, MAX_ENTRIES - entries.size()); 114 | return this; 115 | } 116 | 117 | public Builder addEntries(Function... entries) { 118 | 119 | Stream.of(entries).forEach(this::addEntry); 120 | 121 | return this; 122 | } 123 | 124 | public Builder addEntry(Function entry, int score) { 125 | 126 | entries.put(entry, score); 127 | return this; 128 | } 129 | 130 | public PlayerScoreboard build() { 131 | return new PlayerScoreboard(this); 132 | } 133 | } 134 | 135 | } 136 | -------------------------------------------------------------------------------- /core/src/main/java/com/coalesce/scoreboard/StaticScoreboard.java: -------------------------------------------------------------------------------- 1 | package com.coalesce.scoreboard; 2 | 3 | import org.bukkit.Bukkit; 4 | import org.bukkit.ChatColor; 5 | import org.bukkit.entity.Player; 6 | import org.bukkit.scoreboard.DisplaySlot; 7 | import org.bukkit.scoreboard.Objective; 8 | import org.bukkit.scoreboard.Scoreboard; 9 | 10 | import java.util.Collection; 11 | import java.util.HashMap; 12 | import java.util.Map; 13 | import java.util.stream.Stream; 14 | 15 | public class StaticScoreboard implements CoScoreboard { 16 | 17 | private final Scoreboard scoreboard; 18 | private Objective scoreboardObjective; 19 | private String title; 20 | private final Map entries; 21 | 22 | private StaticScoreboard(Builder builder) { 23 | 24 | scoreboard = Bukkit.getScoreboardManager().getNewScoreboard(); 25 | 26 | title = builder.title; 27 | entries = builder.entries; 28 | 29 | update(); 30 | } 31 | 32 | public void update() { 33 | 34 | if (scoreboardObjective != null) { 35 | scoreboardObjective.unregister(); 36 | } 37 | 38 | //Update the objective 39 | scoreboardObjective = scoreboard.registerNewObjective(title, "dummy"); 40 | scoreboardObjective.setDisplayName(this.title); 41 | scoreboardObjective.setDisplaySlot(DisplaySlot.SIDEBAR); 42 | 43 | //Sets the data to the scoreboard 44 | entries.forEach((entry, score) -> { 45 | 46 | scoreboardObjective.getScore(entry).setScore(score); 47 | }); 48 | } 49 | 50 | @Override 51 | public void send(Player player) { 52 | 53 | player.setScoreboard(scoreboard); 54 | } 55 | 56 | @Override 57 | public void send(Collection players) { 58 | players.forEach(this::send); 59 | } 60 | 61 | @Override 62 | public void setTitle(String titleEntry) { 63 | this.title = titleEntry; 64 | } 65 | 66 | @Override 67 | public void addEntry(String message, int score) { 68 | 69 | while (entries.containsKey(message)) { 70 | message = message + ChatColor.RESET; 71 | } 72 | 73 | entries.put(message, score); 74 | } 75 | 76 | public void addEntry(String message) { 77 | 78 | addEntry(message, MAX_ENTRIES - entries.size()); 79 | } 80 | 81 | public void addEntries(Collection messages) { 82 | 83 | messages.forEach(this::addEntry); 84 | } 85 | 86 | @Override 87 | public void removeEntry(String entry) { 88 | entries.remove(entry); 89 | } 90 | 91 | @Override 92 | public void clearEntries() { 93 | entries.clear(); 94 | } 95 | 96 | public static class Builder { 97 | 98 | private String title; 99 | private Map entries; 100 | 101 | public Builder() { 102 | 103 | this.title = ""; 104 | entries = new HashMap<>(MAX_ENTRIES); 105 | } 106 | 107 | public Builder title(String title) { 108 | 109 | this.title = title; 110 | 111 | return this; 112 | } 113 | 114 | public Builder addEntry(String message) { 115 | 116 | while (entries.containsKey(message)) { 117 | message = message + ChatColor.RESET; 118 | } 119 | 120 | entries.put(message, MAX_ENTRIES - entries.size()); 121 | 122 | return this; 123 | } 124 | 125 | public Builder addEntries(String... messages) { 126 | 127 | Stream.of(messages).forEach(this::addEntry); 128 | 129 | return this; 130 | } 131 | 132 | public Builder addEntry(String message, int score) { 133 | 134 | while (entries.containsKey(message)) { 135 | message = message + ChatColor.RESET; 136 | } 137 | 138 | entries.put(message, score); 139 | 140 | return this; 141 | } 142 | 143 | public StaticScoreboard build() { 144 | return new StaticScoreboard(this); 145 | } 146 | } 147 | 148 | } 149 | -------------------------------------------------------------------------------- /core/src/main/java/com/coalesce/updater/AutoUpdateThread.java: -------------------------------------------------------------------------------- 1 | package com.coalesce.updater; 2 | 3 | import com.coalesce.plugin.CoPlugin; 4 | import com.coalesce.plugin.PluginUtil; 5 | import org.bukkit.plugin.Plugin; 6 | import org.bukkit.scheduler.BukkitRunnable; 7 | 8 | import java.io.File; 9 | import java.io.FileOutputStream; 10 | import java.io.InputStream; 11 | import java.net.HttpURLConnection; 12 | import java.net.URL; 13 | import java.util.logging.Level; 14 | 15 | public class AutoUpdateThread extends Thread { 16 | 17 | private final CoPlugin plugin; 18 | private final URL downloadUrl; 19 | 20 | private File pluginJar; 21 | private String name; 22 | 23 | private HttpURLConnection connection; 24 | private FileOutputStream outputStream; 25 | private long downloaded; 26 | 27 | private static final byte[] BUFFER = new byte[1024]; 28 | 29 | public AutoUpdateThread(CoPlugin plugin, URL downloadUrl, File pluginJar, String name) throws Exception { 30 | 31 | this.plugin = plugin; 32 | this.downloadUrl = downloadUrl; 33 | 34 | this.pluginJar = pluginJar; 35 | this.name = name; 36 | downloaded = 0L; 37 | 38 | setName("Auto-Update"); 39 | setDaemon(false); 40 | } 41 | 42 | @Override 43 | public void run() { 44 | 45 | try { 46 | connection = (HttpURLConnection)downloadUrl.openConnection(); 47 | connection.setRequestProperty("User-Agent", plugin.getDisplayName() + " Spigot Plugin"); 48 | 49 | //Create a temp file. We dont want to delete the plugin if it is still in use, or if the download fails 50 | File tempDownloadFile = new File(pluginJar.getParentFile() + File.separator + name); 51 | tempDownloadFile.createNewFile(); 52 | 53 | InputStream in = connection.getInputStream(); 54 | outputStream = new FileOutputStream(tempDownloadFile); 55 | 56 | UpdateLogger logger; 57 | logger = new UpdateLogger(this); 58 | logger.runTaskTimerAsynchronously(plugin, 20L, 20L); 59 | int count; 60 | while ((count = in.read(BUFFER, 0, 1024)) != -1) { 61 | outputStream.write(BUFFER, 0, count); 62 | downloaded += count; 63 | } 64 | logger.cancel(); 65 | 66 | plugin.getCoLogger().info("Downloading update..."); 67 | 68 | outputStream.close(); 69 | in.close(); 70 | plugin.getCoLogger().info("Update downloaded!"); 71 | 72 | //Unload the plugin 73 | PluginUtil.unload(plugin); 74 | 75 | //Delete the original jar 76 | if (!pluginJar.getAbsoluteFile().delete()) { 77 | //If it failed 78 | throw new RuntimeException("Failed to delete the original plugin!"); 79 | } 80 | 81 | //Enable the new jar 82 | Plugin updatedPlugin = PluginUtil.load(tempDownloadFile); 83 | if (updatedPlugin == null) { 84 | throw new RuntimeException("Failed enable update!"); 85 | } 86 | 87 | updatedPlugin.getLogger().log(Level.INFO, "Successfully updated!"); 88 | 89 | } 90 | catch (Exception e) { 91 | if (outputStream != null) { 92 | try { 93 | outputStream.close(); 94 | } 95 | catch (Exception ignored) { 96 | } 97 | } 98 | e.printStackTrace(); 99 | } 100 | } 101 | 102 | public static class UpdateLogger extends BukkitRunnable { 103 | 104 | private AutoUpdateThread updateThread; 105 | private String totalSize; 106 | private long local; 107 | 108 | private UpdateLogger(AutoUpdateThread autoUpdateThread) { 109 | 110 | this.updateThread = autoUpdateThread; 111 | totalSize = bytes(autoUpdateThread.connection.getContentLengthLong()); 112 | 113 | } 114 | 115 | @Override 116 | public void run() { 117 | 118 | long downloaded = updateThread.downloaded; 119 | long downloadedThisSecond = downloaded - local; 120 | local = downloaded; 121 | 122 | updateThread.plugin.getCoLogger().info(String.format("Download progress: %s/%s @%s/s", bytes(downloaded), totalSize, bytes(downloadedThisSecond))); 123 | 124 | } 125 | 126 | private String bytes(long n) { 127 | 128 | if (n <= 999) { 129 | return n + "B"; 130 | } else if (n >= 1000 && n <= 999999) { 131 | return (float)((int)n / 100) / 10 + "KB"; 132 | } else if (n >= 1000000 && n <= 999999999) { 133 | return (float)((int)n / 100000) / 10 + "MB"; 134 | } else if (n >= 10000000 && n <= 999999999999L) { 135 | return (float)((int)n / 100000000) / 10 + "GB"; 136 | } else { 137 | return (float)((int)n / 100000000000L) / 10 + "TB"; 138 | } 139 | 140 | } 141 | 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /core/src/main/java/com/coalesce/updater/UpdateCheck.java: -------------------------------------------------------------------------------- 1 | package com.coalesce.updater; 2 | 3 | import com.coalesce.http.CoHTTP; 4 | import com.coalesce.plugin.CoPlugin; 5 | import com.google.common.util.concurrent.ListenableFuture; 6 | import com.google.gson.Gson; 7 | import com.google.gson.annotations.SerializedName; 8 | import org.bukkit.Bukkit; 9 | 10 | import java.io.File; 11 | import java.net.URL; 12 | import java.util.List; 13 | import java.util.stream.Collectors; 14 | 15 | public final class UpdateCheck { 16 | 17 | private final CoPlugin plugin; 18 | private UpdateData data; 19 | private File jarFile; 20 | 21 | //First is owner string, then repo 22 | private static final String GITHUB_ADDRESS = "https://api.github.com/repos/%s/%s/releases/latest"; 23 | 24 | public UpdateCheck(CoPlugin plugin, String owner, String repo, File pluginJarFile, boolean autoUpdate) { 25 | 26 | this.plugin = plugin; 27 | this.jarFile = pluginJarFile; 28 | 29 | plugin.getCoLogger().info("Looking for updates to " + plugin.getDisplayName() + "..."); 30 | 31 | ListenableFuture future = CoHTTP.sendGet(String.format(GITHUB_ADDRESS, owner, repo), plugin.getDisplayName() + " Spigot Plugin"); 32 | 33 | future.addListener(() -> { 34 | try { 35 | this.data = new Gson().fromJson(future.get(), UpdateData.class); 36 | 37 | if (!plugin.getDescription().getVersion().matches(data.getVersion())) { 38 | plugin.getCoLogger().info("New version was found! [" + data.getVersion() + "]"); 39 | 40 | if (autoUpdate) { 41 | List javaAssets = data.assets.stream().filter(check -> check.assetName.substring((check.assetName.length() - 3)).equalsIgnoreCase("jar")).collect(Collectors.toList()); 42 | 43 | if (javaAssets.size() == 0) { 44 | plugin.getCoLogger().info(String.format("No jars were found in the release \"%s\". Aborting auto-update. You can update manually.", data.getUrl())); 45 | return; 46 | } else if (javaAssets.size() == 1) { 47 | Asset download = javaAssets.get(0); 48 | new AutoUpdateThread(plugin, new URL(download.downloadURL), jarFile, download.assetName).start(); 49 | return; 50 | } 51 | 52 | List labeledAssets = javaAssets.stream().filter(check -> check.label != null && check.label.equals("Auto-Download")).collect(Collectors.toList()); 53 | 54 | if (labeledAssets.size() != 1) { 55 | plugin.getCoLogger().info(String.format("More than one possible jar was found in the release \"%s\". Aborting auto-update. You can update manually.", data.getUrl())); 56 | return; 57 | } 58 | 59 | Asset download = labeledAssets.get(0); 60 | new AutoUpdateThread(plugin, new URL(download.downloadURL), jarFile, download.assetName).start(); 61 | } else { 62 | plugin.getCoLogger().info("Download it at: " + data.getUrl()); 63 | } 64 | 65 | return; 66 | } 67 | plugin.getCoLogger().info(plugin.getDisplayName() + " is up to date."); 68 | } 69 | catch (NullPointerException e) { 70 | plugin.getCoLogger().warn("Could not find latest released version from GitHub. (This plugin may not have a public release yet)"); 71 | } 72 | catch (Exception e) { 73 | plugin.getCoLogger().warn("There was an error checking for updates."); 74 | } 75 | 76 | }, task -> Bukkit.getScheduler().runTask(plugin, task)); 77 | } 78 | 79 | private static class UpdateData { 80 | 81 | private String message; 82 | 83 | private List assets; 84 | 85 | @SerializedName( "html_url" ) private String url; 86 | 87 | @SerializedName( "tag_name" ) private String version; 88 | 89 | /** 90 | * Gets the assets from the resource post. 91 | * 92 | * @return The assets. 93 | */ 94 | public List getAssets() { 95 | return assets; 96 | } 97 | 98 | /** 99 | * Gets the HTML URL to redirect for the user. 100 | * 101 | * @return URL in string. 102 | */ 103 | public String getUrl() { 104 | return url; 105 | } 106 | 107 | /** 108 | * Gets a message to check if the page exists or not. 109 | *

110 | *

This is mainly used to check for missing releases.

111 | *

112 | *

If no releases exist the message will be "Not Found", otherwise the message will be null

113 | * 114 | * @return A message if no release is found. 115 | */ 116 | public String getMessage() { 117 | return message; 118 | } 119 | 120 | /** 121 | * Gets the tagged version for this release. 122 | * 123 | * @return The release version. 124 | */ 125 | public String getVersion() { 126 | return version; 127 | } 128 | } 129 | 130 | private static class Asset { 131 | 132 | @SerializedName( "browser_download_url" ) private String downloadURL; 133 | 134 | @SerializedName( "name" ) private String assetName; 135 | 136 | private String label; 137 | 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /core/src/main/resources/plugin.yml: -------------------------------------------------------------------------------- 1 | name: CoalesceCore 2 | version: 1.0.0 3 | main: com.coalesce.Core 4 | author: ProjectCoalesce 5 | load: STARTUP -------------------------------------------------------------------------------- /examples/ExampleCoHTTP.java: -------------------------------------------------------------------------------- 1 | package example; 2 | 3 | import com.google.common.util.concurrent.ListenableFuture; 4 | 5 | import java.util.concurrent.ExecutionException; 6 | 7 | public class ExampleCoHTTP { 8 | 9 | public ExampleCoHTTP() { 10 | get(); 11 | post(); 12 | } 13 | 14 | public void get() { 15 | // Get 16 | ListenableFuture responce = CoHTTP.sendGet("https://www.theartex.net/cloud/api/?sec=announcements", "Example App/1.0"); 17 | responce.addListener(() -> { 18 | try { 19 | System.out.println(responce.get()); 20 | } 21 | catch (InterruptedException | ExecutionException e) { 22 | e.printStackTrace(); 23 | } 24 | }, command -> command.run()); 25 | } 26 | 27 | public void post() { 28 | // Create POST parameters 29 | HashMap postParametets = new HashMap<>(); 30 | postParametets.put("sec", "login"); 31 | postParametets.put("username", username); 32 | postParametets.put("password", hashedPassword); 33 | 34 | // Create POST request 35 | ListenableFuture out = CoHTTP.sendPost("https://www.theartex.net/cloud/api/", postParametets, "Example-CoHTTP/1.0"); 36 | 37 | // Add a listener to wait for response 38 | out.addListener(() -> { 39 | try { 40 | // Get response with `out.get()` 41 | String response = out.get(); 42 | // Do what you want with response 43 | // In this case the response is JSON and you can go from here 44 | } 45 | catch (InterruptedException | ExecutionException e) { 46 | e.printStackTrace(); 47 | } 48 | }, command -> command.run()); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /examples/ExampleCommand.java: -------------------------------------------------------------------------------- 1 | package example; 2 | 3 | import com.coalesce.command.CoCommand; 4 | import com.coalesce.command.CommandBuilder; 5 | import com.coalesce.command.CommandContext; 6 | import com.coalesce.plugin.CoModule; 7 | import com.coalesce.ttb.TextToBlock; 8 | import com.coalesce.ttb.blocks.FontLoader; 9 | import com.coalesce.ttb.config.FontsConfig; 10 | import com.coalesce.ttb.gui.TextMenu; 11 | import com.coalesce.ttb.session.SessionHolder; 12 | import com.coalesce.ttb.session.TextSession; 13 | import org.bukkit.ChatColor; 14 | 15 | /** 16 | * Note: This does not need to extend CoModule 17 | */ 18 | public final class TTBCommands extends CoModule { 19 | 20 | public TTBCommands(CoPlugin plugin) { 21 | super(plugin, "Commands Module"); //Creates a module with the name of "Commands Module" 22 | 23 | CoCommand hiCommand = new CommandBuilder(plugin, "hi") //This is the CoCommand Builder. You will use this generated CoCommand (hiCommand) to register it in the server. 24 | .executor(this::hi) //Refrences the hi command method 25 | .usage("/hi").description("Hello!").permission("core.hi").playerOnly().build(); 26 | 27 | CoCommand helloCommand = new CommandBuilder(plugin, "hello").executor(this::hello).maxArgs(0).permission("core.hello").usage("/hello").description("Hi!").playerOnly().build(); 28 | 29 | CoCommand leaveCommand = new CommandBuilder(plugin, "leave").executor(this::leave).maxArgs(0).permission("core.leave").usage("/leave").description("Cya round!").consoleOnly().build(); 30 | 31 | plugin.addCommand(hiCommand, helloCommand, leaveCommand); 32 | } 33 | 34 | @Override 35 | protected void onEnable() throws Exception { 36 | //You only need the onEnable and onDisable if this is a module. 37 | } 38 | 39 | @Override 40 | protected void onDisable() throws Exception { 41 | 42 | } 43 | 44 | public void hi(CommandContext context) { 45 | context.send("Hi there"); 46 | } 47 | 48 | public void hello(CommandContext context) { 49 | context.send("Hello " + context.asPlayer().getName() + "!"); 50 | } 51 | 52 | public void leave(CommandContext context) { 53 | context.send("You gotta go... Cya!"); 54 | } 55 | } -------------------------------------------------------------------------------- /examples/ExampleGui.java: -------------------------------------------------------------------------------- 1 | package example; 2 | 3 | import org.bukkit.inventory.ItemStack; 4 | import org.bukkit.plugin.java.JavaPlugin; 5 | import com.coalesce.gui.*; 6 | 7 | /** 8 | * A contrived example to display the usage of {@link PlayerGui}. 9 | */ 10 | public class ExampleGui extends PlayerGui { 11 | 12 | private static final int SIZE = 9; 13 | 14 | public ExampleGui(JavaPlugin plugin) { 15 | super(plugin, SIZE, "Shop"); 16 | 17 | ItemStack[] items = new ItemStack[0]; // some series of item stacks to display 18 | for (ItemStack stack : items) { 19 | 20 | setItem(0, player -> { 21 | // can do per-player things here, like displaying their currency or some such 22 | int money = 42; // someCurrencyApi.getBalance(someCurrency, player); 23 | return new IconBuilder(stack).name("Balance: " + money).lore(" ", "Click to buy", " ", "Costs x", " ", "You have $" + money).build().getItemStack(); 24 | }, p -> { 25 | // on click 26 | // update user's balance, add item to inventory, etc. 27 | }); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /examples/ExamplePlayerCoScoreboard.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | import com.coalesce.plugin.CoPlugin; 4 | import com.coalesce.scoreboard.PlayerScoreboard; 5 | import org.bukkit.Bukkit; 6 | import org.bukkit.ChatColor; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.player.PlayerJoinEvent; 10 | import org.bukkit.scheduler.BukkitRunnable; 11 | 12 | public class ExamplePlayerCoScoreboard implements Listener { 13 | 14 | private final CoPlugin coPlugin; 15 | 16 | public ExamplePlayerCoScoreboard(CoPlugin coPlugin) { 17 | this.coPlugin = coPlugin; 18 | } 19 | 20 | @EventHandler 21 | public void onPlayerJoin(PlayerJoinEvent event) { 22 | new BukkitRunnable() { 23 | @Override 24 | public void run() { 25 | final PlayerScoreboard scoreboard = new PlayerScoreboard.Builder().title(ChatColor.YELLOW + "" + ChatColor.STRIKETHROUGH + "--" + ChatColor.YELLOW + " Server Craft " + ChatColor.YELLOW + "" + ChatColor.STRIKETHROUGH + "--").addEntries(player -> ChatColor.AQUA + "IP:", player -> ChatColor.GRAY + "server.craft.com", player -> "", player -> "", player -> ChatColor.AQUA + "Website:", player -> ChatColor.GRAY + "www.craft.com", player -> "", player -> ChatColor.AQUA + "Players Online:", player -> ChatColor.GRAY + "" + Bukkit.getOnlinePlayers().size(), player -> "", player -> ChatColor.AQUA + "World Time:", player -> ChatColor.GRAY + "" + event.getPlayer().getWorld().getTime(), player -> ChatColor.YELLOW + "" + ChatColor.STRIKETHROUGH + "------------------").build(); 26 | scoreboard.send(event.getPlayer()); 27 | } 28 | }.runTaskTimer(coPlugin, 0L, 3L); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /examples/ExampleStaticCoScoreboard.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | import com.coalesce.plugin.CoPlugin; 4 | import com.coalesce.scoreboard.StaticScoreboard; 5 | import org.bukkit.Bukkit; 6 | import org.bukkit.event.EventHandler; 7 | import org.bukkit.event.Listener; 8 | import org.bukkit.event.player.PlayerJoinEvent; 9 | import org.bukkit.scheduler.BukkitRunnable; 10 | 11 | public class ExampleStaticCoScoreboard implements Listener { 12 | 13 | final StaticScoreboard scoreboard; 14 | 15 | public ExampleStaticCoScoreboard(CoPlugin coPlugin) { 16 | // Create scoreboard 17 | scoreboard = new StaticScoreboard.Builder().build(); 18 | 19 | // Add all players that are currently on the server 20 | Bukkit.getOnlinePlayers().forEach(scoreboard::send); 21 | 22 | // Create a bukkit runnable to update scoreboards 23 | new BukkitRunnable() { 24 | @Override 25 | public void run() { 26 | // Clear all the entries 27 | scoreboard.clearEntries(); 28 | 29 | // Re-add the entries 30 | scoreboard.addEntry("§bIP:"); 31 | scoreboard.addEntry("§7server.craft.com"); 32 | scoreboard.addEntry(""); 33 | scoreboard.addEntry("§bWebsite:"); 34 | scoreboard.addEntry("§7www.craft.com"); 35 | scoreboard.addEntry(""); 36 | scoreboard.addEntry("§bPlayers Online:"); 37 | scoreboard.addEntry("§7" + Bukkit.getOnlinePlayers().size()); 38 | scoreboard.addEntry("§m§e------------------"); 39 | 40 | // Update the scoreboard 41 | scoreboard.update(); 42 | } 43 | }.runTaskTimer(coPlugin, 0L, 3L); // Set timer 44 | } 45 | 46 | @EventHandler 47 | public void onPlayerJoin(PlayerJoinEvent event) { 48 | scoreboard.send(event.getPlayer()); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /examples/ExampleYamlConfig.java: -------------------------------------------------------------------------------- 1 | package com.coalesce.ttb.config; 2 | 3 | import com.coalesce.config.yml.YamlEntry; 4 | import com.coalesce.config.yml.YamlConfig; 5 | import com.coalesce.plugin.CoPlugin; 6 | import org.bukkit.Material; 7 | 8 | 9 | public final class FontsConfig extends YamlConfig { 10 | 11 | private final CoPlugin plugin; 12 | private final YamlConfig config; 13 | 14 | public FontsConfig(CoPlugin plugin) { 15 | super("config", plugin); 16 | this.plugin = plugin; 17 | this.config = (FontsConfig) plugin.getConfig("config"); 18 | config.addEntry(new YamlEntry(config, "font.maxFontSize", 100)); 19 | config.addEntry(new YamlEntry(config, "font.fallbackFontSize", 12)); 20 | config.addEntry(new YamlEntry(config, "font.fallbackFont", "blocked")); 21 | config.addEntry(new YamlEntry(config, "font.fallbackMaterial", Material.QUARTZ_BLOCK.name())); 22 | config.addEntry(new YamlEntry(config, "operations.historySize", 10)); 23 | } 24 | 25 | public int getMaxFontSize() { 26 | return (int) getEntry("font.maxFontSize").getValue(); 27 | } 28 | 29 | public void setMaxFontSize(int maxFontSize) { 30 | getEntry("font.maxFontSize").setValue(maxFontSize); 31 | } 32 | 33 | public int getMaxOperations() { 34 | return (int) getEntry("operations.historySize").getValue(); 35 | } 36 | 37 | public void setMaxOperations(int maxOperations) { 38 | getEntry("operations.historySize").setValue(maxOperations); 39 | } 40 | 41 | public String getFallbackFont() { 42 | return (String) config.getEntry("font.fallbackFont").getValue(); 43 | } 44 | 45 | public void setFallbackFont(String fallbackFont) { 46 | getEntry("font.fallbackFont").setValue(fallbackFont); 47 | } 48 | 49 | public float getFallbackFontSize() { 50 | return (float) getEntry("font.fallbackFontSize").getValue(); 51 | } 52 | 53 | public void setFallbackFontSize(float fallbackFontSize) { 54 | config.getEntry("font.fallbackFontSize").setValue(fallbackFontSize); 55 | } 56 | 57 | public Material getFallbackMaterial() { 58 | return (Material) getEntry("font.fallbackMaterial").getValue(); 59 | } 60 | 61 | public void setFallbackMaterial(Material material) { 62 | getEntry("font.fallbackMaterial").setValue(material.name()); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.coalesce 8 | parent 9 | 1.0 10 | pom 11 | 12 | 13 | 1.8 14 | 1.8 15 | UTF-8 16 | 17 | 1.12-R0.1-SNAPSHOT 18 | 15.0 19 | 20 | 3.0.0 21 | 3.0.0 22 | 3.0.1 23 | 2.10.4 24 | 25 | 26 | 27 | core 28 | 29 | 30 | 31 | 32 | spigot-repo 33 | https://hub.spigotmc.org/nexus/content/repositories/snapshots/ 34 | 35 | 36 | 37 | 38 | 39 | 40 | org.spigotmc 41 | spigot-api 42 | ${versionSpigot} 43 | provided 44 | 45 | 46 | 47 | 48 | junit 49 | junit 50 | 4.12 51 | test 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | org.apache.maven.plugins 62 | maven-jar-plugin 63 | 3.0.2 64 | 65 | jars/ 66 | 67 | 68 | 69 | 70 | 71 | org.apache.maven.plugins 72 | maven-source-plugin 73 | ${versionMavenSources} 74 | 75 | 76 | attach-sources 77 | 78 | jar 79 | 80 | 81 | 82 | 83 | jars/ 84 | 85 | 86 | 87 | 88 | 89 | org.apache.maven.plugins 90 | maven-javadoc-plugin 91 | ${versionMavenJavaDoc} 92 | 93 | 94 | attach-javadocs 95 | 96 | jar 97 | 98 | 99 | 100 | 101 | docs/ 102 | jars/ 103 | -Xdoclint:none 104 | 105 | 106 | 107 | 108 | 109 | org.apache.maven.plugins 110 | maven-shade-plugin 111 | ${versionMavenShade} 112 | 113 | 114 | package 115 | 116 | shade 117 | 118 | 119 | 120 | 121 | jars/ 122 | 123 | 124 | 125 | 126 | 127 | org.apache.maven.plugins 128 | maven-clean-plugin 129 | 3.0.0 130 | 131 | 132 | default-clean 133 | package 134 | 135 | clean 136 | 137 | 138 | 139 | 140 | 141 | 142 | docs/ 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | --------------------------------------------------------------------------------