Minor Version Update 1.1.0

Changes:
  - Converted messaging to Kyori Adventure Components
  - Miscellaneous code tweaks and organization
This commit is contained in:
Paldiu 2021-12-05 17:55:00 -06:00
parent 1e4ebd1ff8
commit ac5d4cde39
32 changed files with 298 additions and 318 deletions

View File

@ -4,7 +4,7 @@ plugins {
} }
version project.properties["pluginVersion"] version project.properties["pluginVersion"]
targetCompatibility = sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = sourceCompatibility = JavaVersion.VERSION_17
repositories { repositories {
mavenCentral() mavenCentral()
@ -13,10 +13,7 @@ repositories {
[ [
"https://jitpack.io", "https://jitpack.io",
"https://papermc.io/repo/repository/maven-public/", "https://papermc.io/repo/repository/maven-public/",
"https://oss.sonatype.org/content/groups/public/", "https://os1.oss.sonatype.org/content/groups/public/"
"https://repo.extendedclip.com/content/repositories/placeholderapi/",
"http://repo.comphenix.net/content/repositories/releases/",
"http://repo.comphenix.net/content/repositories/snapshots/"
].each { s -> ].each { s ->
maven { maven {
url s url s
@ -27,24 +24,15 @@ repositories {
dependencies { dependencies {
//provided //provided
[ [
"com.destroystokyo.paper:paper-api:1.16.4-R0.1-SNAPSHOT", "io.papermc.paper:paper-api:1.18-R0.1-SNAPSHOT",
"net.md-5:bungeecord-api:1.16-R0.4-SNAPSHOT",
"io.github.waterfallmc:waterfall-api:1.16-R0.4-SNAPSHOT",
"me.clip:placeholderapi:2.10.9",
files("libs/spigot-1.16.5.jar"),
files("libs/spigot-1.16.4.jar")
].each {s -> ].each {s ->
compileOnly s compileOnly s
} }
compileOnly ("com.github.dmulloy2:ProtocolLib:4.5.1") {
exclude group: "com.comphenix.executors"
}
//compile //compile
[ [
"org.jetbrains:annotations:20.1.0", "org.jetbrains:annotations:23.0.0",
"org.reflections:reflections:0.9.12" "org.reflections:reflections:0.10.2"
].each {s -> ].each {s ->
implementation s implementation s
} }
@ -63,6 +51,17 @@ shadowJar {
} }
} }
apply plugin: 'maven-publish'
apply plugin: 'signing'
signing {
sign configurations.archives
}
group = "io.github.simplexdevelopment"
archivesBaseName = "simplex-core"
version = "1.0.0"
processResources { processResources {
//update resources when building //update resources when building
doFirst { doFirst {

View File

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

View File

@ -1,6 +1,7 @@
package io.github.simplexdev.api; package io.github.simplexdev.api;
import io.github.simplexdev.simplexcore.ban.BanType; import io.github.simplexdev.simplexcore.ban.BanType;
import net.kyori.adventure.text.Component;
import java.util.Date; import java.util.Date;
import java.util.UUID; import java.util.UUID;
@ -10,7 +11,7 @@ public interface IBan {
String getSender(); String getSender();
String getBanReason(); Component getBanReason();
String getBanId(); String getBanId();

View File

@ -1,6 +1,7 @@
package io.github.simplexdev.api; package io.github.simplexdev.api;
import io.github.simplexdev.api.func.ClickAction; import io.github.simplexdev.api.func.ClickAction;
import net.kyori.adventure.text.Component;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory; import org.bukkit.inventory.Inventory;
@ -74,10 +75,10 @@ public interface IGUI {
* Creates a new ItemStack instance to place in the inventory provided by the interface instance. * Creates a new ItemStack instance to place in the inventory provided by the interface instance.
* @param material The item material * @param material The item material
* @param name The name of the item * @param name The name of the item
* @param lore Optional item descriptions * @param lore Optional item descriptions, as components.
* @return The newly created item * @return The newly created item
*/ */
ItemStack newItem(@NotNull Material material, @NotNull String name, String... lore); ItemStack newItem(@NotNull Material material, @NotNull String name, Component... lore);
/** /**
* Creates a new ItemStack instance to place in the inventory provided by the interface instance. * Creates a new ItemStack instance to place in the inventory provided by the interface instance.

View File

@ -1,10 +1,12 @@
package io.github.simplexdev.api.func; package io.github.simplexdev.api.func;
import org.jetbrains.annotations.NotNull;
@FunctionalInterface @FunctionalInterface
public interface VoidSupplier { public interface VoidSupplier {
void get(); void get();
default VoidSupplier after(VoidSupplier supplier) { default VoidSupplier after(@NotNull VoidSupplier supplier) {
supplier.get(); supplier.get();
return this; return this;
} }

View File

@ -7,18 +7,10 @@ public class CoreState {
public CoreState(SimplexCorePlugin plugin) { public CoreState(SimplexCorePlugin plugin) {
this.plugin = plugin; this.plugin = plugin;
switch (getState()) { switch (getState()) {
case ON: case ON -> message = "The Core is currently ON";
message = "The Core is currently ON"; case SUSPENDED -> message = "The Core is currently SUSPENDED. Please report this to the developer.";
break; case DEBUG -> message = "The Core is currently in DEBUG mode. Do not use this if you don't know what you're doing.";
case SUSPENDED: case VOLATILE -> message = "The Core state is currently unknown! Please report this to the developer!";
message = "The Core is currently SUSPENDED. Please report this to the developer.";
break;
case DEBUG:
message = "The Core is currently in DEBUG mode. Do not use this if you don't know what you're doing.";
break;
case VOLATILE:
message = "The Core state is currently unknown! Please report this to the developer!";
break;
} }
} }

View File

@ -9,6 +9,7 @@ import io.github.simplexdev.simplexcore.listener.SimplexListener;
import io.github.simplexdev.simplexcore.module.SimplexModule; import io.github.simplexdev.simplexcore.module.SimplexModule;
import io.github.simplexdev.simplexcore.utils.TickedTime; import io.github.simplexdev.simplexcore.utils.TickedTime;
import io.github.simplexdev.simplexcore.utils.Utilities; import io.github.simplexdev.simplexcore.utils.Utilities;
import net.kyori.adventure.text.Component;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -33,7 +34,7 @@ public abstract class Ban implements IBan {
private final SimplexModule<?> plugin; private final SimplexModule<?> plugin;
private final String banId; private final String banId;
private final String banReason; private final Component banReason;
/** /**
* Creates a new Ban Entry. * Creates a new Ban Entry.
@ -79,7 +80,7 @@ public abstract class Ban implements IBan {
* @param banDate The date when the ban was created. * @param banDate The date when the ban was created.
* @param banDuration How long the ban should last. * @param banDuration How long the ban should last.
*/ */
public Ban(SimplexModule<?> plugin, Player player, CommandSender sender, BanType type, String banId, String banReason, Date banDate, long banDuration) { public Ban(SimplexModule<?> plugin, Player player, CommandSender sender, BanType type, String banId, Component banReason, Date banDate, long banDuration) {
this.plugin = plugin; this.plugin = plugin;
this.player = player; this.player = player;
this.sender = sender; this.sender = sender;
@ -92,18 +93,20 @@ public abstract class Ban implements IBan {
/** /**
* Writes the Ban to a file. * Writes the Ban to a file.
* @param separateFiles Whether or not to create individual files for players or store them all in one bans.yml file. * @param separateFiles Whether to create individual files for players or store
* them all in one bans.yml file.
*/ */
public void writeToFile(boolean separateFiles) { public void writeToFile(boolean separateFiles) {
File fileLocation = new File(plugin.getParentFolder(), "bans"); File fileLocation = new File(plugin.getParentFolder(), "bans");
Yaml yaml;
if (separateFiles) { if (separateFiles) {
Yaml yaml = new YamlFactory(plugin).from(null, fileLocation, player.getName() + ".yml"); yaml = new YamlFactory(plugin).from(null, fileLocation, player.getName() + ".yml");
ConfigurationSection section = yaml.getConfig().createSection(getOffender().toString()); ConfigurationSection section = yaml.getConfig().createSection(getOffender().toString());
section.set("name", player.getName()); section.set("name", player.getName());
section.set("ban_id", banId); section.set("ban_id", banId);
section.set("sender", sender.getName()); section.set("sender", sender.getName());
section.set("reason", banReason); section.set("reason", banReason.toString());
section.set("duration", banDuration); section.set("duration", banDuration);
section.set("date", banDate.getTime()); section.set("date", banDate.getTime());
section.set("type", type.toString()); section.set("type", type.toString());
@ -112,14 +115,13 @@ public abstract class Ban implements IBan {
} catch (IOException e) { } catch (IOException e) {
plugin.getLogger().severe(e.getMessage()); plugin.getLogger().severe(e.getMessage());
} }
yaml.reload();
} else { } else {
Yaml yaml = new YamlFactory(plugin).from(null, fileLocation, "bans.yml"); yaml = new YamlFactory(plugin).from(null, fileLocation, "bans.yml");
ConfigurationSection section = yaml.getConfig().createSection(getOffender().toString()); ConfigurationSection section = yaml.getConfig().createSection(getOffender().toString());
section.set("name", player.getName()); section.set("name", player.getName());
section.set("ban_id", banId); section.set("ban_id", banId);
section.set("sender", sender.getName()); section.set("sender", sender.getName());
section.set("reason", banReason); section.set("reason", banReason.toString());
section.set("duration", banDuration); section.set("duration", banDuration);
section.set("date", banDate.getTime()); section.set("date", banDate.getTime());
section.set("type", type.toString()); section.set("type", type.toString());
@ -128,7 +130,7 @@ public abstract class Ban implements IBan {
} catch (IOException ex) { } catch (IOException ex) {
plugin.getLogger().severe(ex.getMessage()); plugin.getLogger().severe(ex.getMessage());
} }
yaml.reload();
} }
yaml.reload();
} }
} }

View File

@ -4,12 +4,15 @@ import io.github.simplexdev.api.IBan;
import io.github.simplexdev.api.func.VoidSupplier; import io.github.simplexdev.api.func.VoidSupplier;
import io.github.simplexdev.simplexcore.chat.Messages; import io.github.simplexdev.simplexcore.chat.Messages;
import io.github.simplexdev.simplexcore.config.Yaml; import io.github.simplexdev.simplexcore.config.Yaml;
import io.github.simplexdev.simplexcore.config.YamlFactory;
import io.github.simplexdev.simplexcore.module.SimplexModule; import io.github.simplexdev.simplexcore.module.SimplexModule;
import io.github.simplexdev.simplexcore.utils.TickedTime; import io.github.simplexdev.simplexcore.utils.TickedTime;
import io.github.simplexdev.simplexcore.utils.Utilities; import io.github.simplexdev.simplexcore.utils.Utilities;
import net.kyori.adventure.text.Component;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File; import java.io.File;
import java.util.Date; import java.util.Date;
@ -24,7 +27,7 @@ public final class BanFactory {
private final Date banDate; private final Date banDate;
private final BanType type; private final BanType type;
private final String banId; private final String banId;
private String banReason; private Component banReason;
private long banDuration; private long banDuration;
public BanFactory(SimplexModule<?> plugin, Player player, CommandSender sender, Date banDate, BanType type) { public BanFactory(SimplexModule<?> plugin, Player player, CommandSender sender, Date banDate, BanType type) {
@ -46,13 +49,13 @@ public final class BanFactory {
* @param banReason The reason for the ban. By default, this uses Messages#BAN for the message. * @param banReason The reason for the ban. By default, this uses Messages#BAN for the message.
* @return The current instance of BanFactory. * @return The current instance of BanFactory.
*/ */
public BanFactory defineOptional(long banDuration, String banReason) { public BanFactory defineOptional(long banDuration, Component banReason) {
this.banDuration = banDuration; this.banDuration = banDuration;
this.banReason = banReason; this.banReason = banReason;
return this; return this;
} }
public void write(Yaml yaml, IBan ban) { public void write(@NotNull Yaml yaml, @NotNull IBan ban) {
yaml.set(pathway("offender"), ban.getOffender()); yaml.set(pathway("offender"), ban.getOffender());
yaml.set(pathway("sender"), ban.getSender()); yaml.set(pathway("sender"), ban.getSender());
yaml.set(pathway("duration"), ban.getBanDuration()); yaml.set(pathway("duration"), ban.getBanDuration());
@ -63,7 +66,8 @@ public final class BanFactory {
yaml.create(); yaml.create();
} }
public Yaml read(File yamlFile) { @Contract(pure = true)
public @Nullable Yaml read(File yamlFile) {
return null; return null;
} }
@ -72,7 +76,8 @@ public final class BanFactory {
* *
* @return A new ban instance. * @return A new ban instance.
*/ */
public Ban create() { @Contract(" -> new")
public @NotNull Ban create() {
return new Ban(plugin, player, sender, type, banDuration) { return new Ban(plugin, player, sender, type, banDuration) {
@Override @Override
public UUID getOffender() { public UUID getOffender() {
@ -85,7 +90,7 @@ public final class BanFactory {
} }
@Override @Override
public String getBanReason() { public Component getBanReason() {
return banReason; return banReason;
} }
@ -115,19 +120,23 @@ public final class BanFactory {
// TODO // TODO
} }
public IBan getBan(String banId) { @Contract(pure = true)
public @Nullable IBan getBan(String banId) {
return null; return null;
} }
public IBan getBan(Player player) { @Contract(pure = true)
public @Nullable IBan getBan(Player player) {
return null; return null;
} }
public IBan getBan(UUID offenderUUID) { @Contract(pure = true)
public @Nullable IBan getBan(UUID offenderUUID) {
return null; return null;
} }
private VoidSupplier assignBanDuration(Long... time) { @Contract(pure = true)
private @NotNull VoidSupplier assignBanDuration(Long... time) {
return () -> { return () -> {
if (type.equals(BanType.PERMANENT)) { if (type.equals(BanType.PERMANENT)) {
banDuration = TickedTime.YEAR * 99; banDuration = TickedTime.YEAR * 99;
@ -145,7 +154,7 @@ public final class BanFactory {
}; };
} }
private String createBanId() { private @NotNull String createBanId() {
return Utilities.generateBanId(type); return Utilities.generateBanId(type);
} }
} }

View File

@ -7,6 +7,7 @@ import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer; import org.bukkit.OfflinePlayer;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent; import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.Date; import java.util.Date;
@ -19,11 +20,9 @@ import static org.bukkit.event.player.AsyncPlayerPreLoginEvent.Result;
public final class BanManager extends SimplexListener { public final class BanManager extends SimplexListener {
private final Map<Ban, BanType> banMap = new HashMap<>(); private final Map<Ban, BanType> banMap = new HashMap<>();
private final SimplexModule<?> plugin;
BanManager(SimplexModule<?> plugin) { BanManager(SimplexModule<?> plugin) {
this.plugin = plugin; super(plugin);
register(this, plugin);
} }
public void addBan(Ban ban) { public void addBan(Ban ban) {
@ -47,7 +46,7 @@ public final class BanManager extends SimplexListener {
} }
@EventHandler @EventHandler
public void banHandler(AsyncPlayerPreLoginEvent event) { public void banHandler(@NotNull AsyncPlayerPreLoginEvent event) {
UUID player = event.getUniqueId(); UUID player = event.getUniqueId();
OfflinePlayer op = Bukkit.getOfflinePlayer(player); OfflinePlayer op = Bukkit.getOfflinePlayer(player);
Ban ban = getBan(op); Ban ban = getBan(op);

View File

@ -1,5 +1,7 @@
package io.github.simplexdev.simplexcore.ban; package io.github.simplexdev.simplexcore.ban;
import org.jetbrains.annotations.NotNull;
public enum BanType { public enum BanType {
PERMANENT("P-"), PERMANENT("P-"),
TEMPORARY("T-"), TEMPORARY("T-"),
@ -12,7 +14,7 @@ public enum BanType {
this.prefix = prefix; this.prefix = prefix;
} }
public static String value(BanType type) { public static @NotNull String value(@NotNull BanType type) {
if (type.equals(PERMANENT)) { if (type.equals(PERMANENT)) {
return "Permanent"; return "Permanent";
} else if (type.equals(TEMPORARY)) { } else if (type.equals(TEMPORARY)) {
@ -22,7 +24,7 @@ public enum BanType {
} }
} }
public static BanType getFromId(String banId) { public static BanType getFromId(@NotNull String banId) {
if (banId.startsWith("P")) { if (banId.startsWith("P")) {
return PERMANENT; return PERMANENT;
} else if (banId.startsWith("T")) { } else if (banId.startsWith("T")) {

View File

@ -5,6 +5,7 @@ import io.github.simplexdev.api.func.VoidSupplier;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Sign; import org.bukkit.block.Sign;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@ -19,7 +20,7 @@ public abstract class AbstractSign implements IUsableSign {
protected VoidSupplier executeScript = null; protected VoidSupplier executeScript = null;
protected boolean canInteract = false; protected boolean canInteract = false;
protected AbstractSign(Sign sign) { protected AbstractSign(@NotNull Sign sign) {
this.sign = sign; this.sign = sign;
this.location = sign.getLocation(); this.location = sign.getLocation();
this.world = sign.getWorld(); this.world = sign.getWorld();

View File

@ -1,17 +1,20 @@
package io.github.simplexdev.simplexcore.chat; package io.github.simplexdev.simplexcore.chat;
import net.md_5.bungee.api.chat.TextComponent; import net.kyori.adventure.text.Component;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
public final class ChatUtils { public final class ChatUtils {
protected final CommandSender target; private final CommandSender target;
protected final TextComponentFactory factory = new TextComponentFactory(); private final TextComponentFactory factory = new TextComponentFactory();
private <T extends CommandSender> ChatUtils(T target) { private <T extends CommandSender> ChatUtils(T target) {
this.target = target; this.target = target;
} }
public static <T extends CommandSender> ChatUtils target(T target) { @Contract("_ -> new")
public static <T extends CommandSender> @NotNull ChatUtils msgTarget(T target) {
return new ChatUtils(target); return new ChatUtils(target);
} }
@ -19,21 +22,11 @@ public final class ChatUtils {
target.sendMessage(message); target.sendMessage(message);
} }
public void msg(TextComponent component) { public void msg(Component component) {
target.spigot().sendMessage(component); target.sendMessage(component);
} }
public void err(Messages message) { public void err(@NotNull Messages message) {
target.sendMessage(message.getMessage()); target.sendMessage(message.getMessage());
} }
public void color(String message) {
target.sendMessage(factory.colorize(message));
}
public void color(TextComponent component) {
target.sendMessage(factory.colorize(component.getText()));
}
} }

View File

@ -1,22 +1,23 @@
package io.github.simplexdev.simplexcore.chat; package io.github.simplexdev.simplexcore.chat;
import io.github.simplexdev.simplexcore.CoreState; import net.kyori.adventure.text.Component;
public enum Messages { public enum Messages {
NO_PERMS("You do not have permission to use this command!"), NO_PERMS(Component.text("You do not have permission to use this command!")),
DISCORD("https://discord.gg/Rumx5dTJuf"), DISCORD(Component.text("https://discord.gg/Rumx5dTJuf")),
BAN("You have been banned from this server."), BAN(Component.text("You have been banned from this server.")),
KICK("You have been kicked by a moderator."), KICK(Component.text("You have been kicked by a moderator.")),
AFK_KICK("You were kicked to ensure space for active players."), AFK_KICK(Component.text("You were kicked to ensure space for active players.")),
PERMBAN("You are permanently banned from this server."); PERMBAN(Component.text("You are permanently banned from this server."));
String message;
Messages(String message) { final Component message;
Messages(Component message) {
this.message = message; this.message = message;
} }
public String getMessage() { public Component getMessage() {
return message; return message;
} }
} }

View File

@ -1,72 +1,43 @@
package io.github.simplexdev.simplexcore.chat; package io.github.simplexdev.simplexcore.chat;
import net.md_5.bungee.api.ChatColor; import net.kyori.adventure.key.Key;
import net.md_5.bungee.api.chat.ClickEvent; import net.kyori.adventure.text.Component;
import net.md_5.bungee.api.chat.HoverEvent; import net.kyori.adventure.text.TextComponent;
import net.md_5.bungee.api.chat.TextComponent; import net.kyori.adventure.text.event.ClickEvent;
import net.md_5.bungee.api.chat.hover.content.Text; import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.format.TextColor;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
public final class TextComponentFactory { public final class TextComponentFactory {
@NotNull @NotNull
public TextComponent textComponent(@NotNull String message) { public TextComponent textComponent(@NotNull String message) {
TextComponent component = new TextComponent(); return Component.text(message);
component.setText(message);
return component;
} }
@NotNull @NotNull
public TextComponent clickableComponent(@NotNull String message, @NotNull String clickAction, @NotNull ClickEvent.Action actionType) { public Component clickableComponent(@NotNull String message, @NotNull String clickAction, @NotNull ClickEvent.Action actionType) {
TextComponent comp = new TextComponent(); Component comp = Component.text(message);
ClickEvent onClick = new ClickEvent(actionType, clickAction); ClickEvent onClick = ClickEvent.clickEvent(actionType, clickAction);
comp.setText(message); return comp.clickEvent(onClick);
comp.setClickEvent(onClick);
return comp;
} }
@NotNull @NotNull
public TextComponent coloredComponent(@NotNull String message, @Nullable ChatColor color) { public Component addColor(@NotNull Component component, @NotNull TextColor color) {
TextComponent component = new TextComponent(); return component.color(color);
if (color != null) component.setColor(color);
component.setText(message);
return component;
} }
@NotNull @NotNull
public TextComponent clickableColored(@NotNull String message, @NotNull String clickMessage, @NotNull ClickEvent.Action actionType, @Nullable ChatColor color) { public Component resetColor(@NotNull Component component) {
TextComponent comp = new TextComponent(); return component.color(TextColor.fromHexString("#FFFFFF"));
ClickEvent onClick = new ClickEvent(actionType, clickMessage);
if (color != null) comp.setColor(color);
comp.setText(message);
comp.setClickEvent(onClick);
return comp;
} }
@NotNull @NotNull
public TextComponent addColor(@NotNull TextComponent component, @NotNull ChatColor color) { public Component hoverText(@NotNull String message, @NotNull String hoverMessage) {
component.setColor(color); Component comp = Component.text(message);
return component; Component msg = Component.text(hoverMessage);
} HoverEvent<Component> event = HoverEvent.showText(msg);
return comp.hoverEvent(event);
@NotNull
public TextComponent resetColor(@NotNull TextComponent component) {
component.setColor(ChatColor.RESET);
return component;
}
@NotNull
public TextComponent hoverableText(@NotNull String message, @NotNull String hoverMessage, @NotNull HoverEvent.Action action) {
TextComponent comp = new TextComponent();
comp.setText(message);
Text text = new Text(hoverMessage);
HoverEvent event = new HoverEvent(action, text);
comp.setHoverEvent(event);
return comp;
}
@NotNull
public String colorize(@NotNull String message) {
return ChatColor.translateAlternateColorCodes('&', message);
} }
} }

View File

@ -2,6 +2,7 @@ package io.github.simplexdev.simplexcore.command;
import io.github.simplexdev.api.annotations.CommandInfo; import io.github.simplexdev.api.annotations.CommandInfo;
import io.github.simplexdev.simplexcore.SimplexCorePlugin; import io.github.simplexdev.simplexcore.SimplexCorePlugin;
import io.github.simplexdev.simplexcore.chat.TextComponentFactory;
import io.github.simplexdev.simplexcore.module.SimplexModule; import io.github.simplexdev.simplexcore.module.SimplexModule;
import io.github.simplexdev.simplexcore.utils.ReflectionTools; import io.github.simplexdev.simplexcore.utils.ReflectionTools;
import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandExecutor;
@ -35,7 +36,6 @@ public final class CommandLoader {
/** /**
* Prepares the CommandLoader to load your plugin's commands from its own package location. * Prepares the CommandLoader to load your plugin's commands from its own package location.
* This is synchronized, so it only registers commands from one plugin at a time.
* All your commands MUST be placed in their own package. * All your commands MUST be placed in their own package.
* <p> * <p>
* If your command classes do not have the {@link CommandInfo} annotation, they will not be loaded. * If your command classes do not have the {@link CommandInfo} annotation, they will not be loaded.
@ -78,6 +78,8 @@ public final class CommandLoader {
throw new CommandLoaderException("Please run CommandLoader#classpath(SimplexModule, Class) first!"); throw new CommandLoaderException("Please run CommandLoader#classpath(SimplexModule, Class) first!");
} }
TextComponentFactory factory = new TextComponentFactory();
reflections.getTypesAnnotatedWith(CommandInfo.class).forEach(annotated -> { reflections.getTypesAnnotatedWith(CommandInfo.class).forEach(annotated -> {
CommandInfo info = annotated.getDeclaredAnnotation(CommandInfo.class); CommandInfo info = annotated.getDeclaredAnnotation(CommandInfo.class);
@ -105,7 +107,7 @@ public final class CommandLoader {
command.setExecutor(getExecutorFromName(info.name())); command.setExecutor(getExecutorFromName(info.name()));
command.setLabel(info.name().toLowerCase()); command.setLabel(info.name().toLowerCase());
command.setPermission(info.permission()); command.setPermission(info.permission());
command.setPermissionMessage(info.permissionMessage()); command.permissionMessage(factory.textComponent(info.permissionMessage()));
command.setTabCompleter(getTabFromName(info.name())); command.setTabCompleter(getTabFromName(info.name()));
command.setUsage(info.usage()); command.setUsage(info.usage());
registry.registerCommand(command); registry.registerCommand(command);

View File

@ -3,6 +3,9 @@ package io.github.simplexdev.simplexcore.command;
import io.github.simplexdev.simplexcore.SimplexCorePlugin; import io.github.simplexdev.simplexcore.SimplexCorePlugin;
import io.github.simplexdev.simplexcore.module.SimplexModule; import io.github.simplexdev.simplexcore.module.SimplexModule;
import io.github.simplexdev.simplexcore.utils.Utilities; import io.github.simplexdev.simplexcore.utils.Utilities;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.ComponentBuilder;
import net.kyori.adventure.text.JoinConfiguration;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
@ -14,6 +17,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.atomic.AtomicReference;
public abstract class SimplexCommand implements CommandExecutor, TabCompleter { public abstract class SimplexCommand implements CommandExecutor, TabCompleter {
private final SimplexModule<?> plugin; private final SimplexModule<?> plugin;
@ -71,23 +75,47 @@ public abstract class SimplexCommand implements CommandExecutor, TabCompleter {
* @param player The Player to send a message to * @param player The Player to send a message to
* @param messages The messages to send. * @param messages The messages to send.
*/ */
public void playerMsg(Player player, String... messages) { public void playerMsg(@NotNull Player player, String... messages) {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
Utilities.forEach(messages, builder::append); Utilities.forEach(messages, builder::append);
player.sendMessage(builder.toString()); player.sendMessage(Component.text(builder.toString()));
} }
/** /**
* Send a message or a group of messages to a {@link CommandSender} * Send a message or a group of messages to a {@link CommandSender}
* If you want the messages to send on new lines, put \n at the end of each message to send. * If you want the messages to send on separate lines,
* put \n at the end of each message to send.
* *
* @param sender The CommandSender to send a message to. * @param sender The CommandSender to send a message to.
* @param messages The messages to send. * @param messages The messages to send.
*/ */
public void msg(CommandSender sender, String... messages) { public void msg(@NotNull CommandSender sender, String... messages) {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
Utilities.forEach(messages, builder::append); Utilities.forEach(messages, builder::append);
sender.sendMessage(builder.toString()); sender.sendMessage(Component.text(builder.toString()));
}
/**
* Send a component or a group of components to a {@link CommandSender}.
* If you want the components to occupy separate lines,
* use the separator boolean.
*
* @param sender The CommandSender to send components to
* @param components The components to send.
*/
public void msg(@NotNull CommandSender sender, boolean separator, Component... components) {
if (separator) {
AtomicReference<Component> primary = new AtomicReference<>(Component.text(""));
AtomicReference<Component> temp = new AtomicReference<>(Component.text(""));
Utilities.forEach(components, component -> {
temp.set(Component.newline().append(component));
primary.set(primary.get().append(temp.get()));
}); // The way I'm doing this is probably unnecessary, but I did it anyway.
sender.sendMessage(primary.get());
return;
}
sender.sendMessage(Component.join(JoinConfiguration.builder().build(), components));
} }
@Nullable @Nullable

View File

@ -4,6 +4,7 @@ import io.github.simplexdev.api.annotations.CommandInfo;
import io.github.simplexdev.simplexcore.chat.Messages; import io.github.simplexdev.simplexcore.chat.Messages;
import io.github.simplexdev.simplexcore.command.SimplexCommand; import io.github.simplexdev.simplexcore.command.SimplexCommand;
import io.github.simplexdev.simplexcore.module.SimplexModule; import io.github.simplexdev.simplexcore.module.SimplexModule;
import net.kyori.adventure.text.Component;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;

View File

@ -3,6 +3,7 @@ package io.github.simplexdev.simplexcore.command.defaults;
import io.github.simplexdev.api.annotations.CommandInfo; import io.github.simplexdev.api.annotations.CommandInfo;
import io.github.simplexdev.simplexcore.command.SimplexCommand; import io.github.simplexdev.simplexcore.command.SimplexCommand;
import io.github.simplexdev.simplexcore.module.SimplexModule; import io.github.simplexdev.simplexcore.module.SimplexModule;
import net.kyori.adventure.text.Component;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -15,7 +16,7 @@ public final class DefaultCommand extends SimplexCommand {
@Override @Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
sender.sendMessage("If you are seeing this when running your command, your command didn't register properly."); msg(sender, "If you are seeing this when running your command, your command didn't register properly.");
return true; return true;
} }
} }

View File

@ -7,6 +7,8 @@ import io.github.simplexdev.simplexcore.module.SimplexModule;
import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.configuration.file.YamlConfiguration;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -22,7 +24,7 @@ public final class Yaml implements IConfig {
private File file; private File file;
// Package private ;) // Package private ;)
Yaml(SimplexModule<?> plugin, String fileName, File directory, String resourcePath) { Yaml(SimplexModule<?> plugin, @NotNull String fileName, File directory, String resourcePath) {
if (!fileName.endsWith(".yml")) { if (!fileName.endsWith(".yml")) {
fileName += ".yml"; fileName += ".yml";
} }
@ -38,71 +40,74 @@ public final class Yaml implements IConfig {
} }
@Override @Override
public final void set(Path path, Object value) { public final void set(@NotNull Path path, Object value) {
this.getConfig().set(path.getPath(), value); this.getConfig().set(path.getPath(), value);
} }
public boolean contains(Path path) { public boolean contains(@NotNull Path path) {
return this.getConfig().contains(path.getPath()); return this.getConfig().contains(path.getPath());
} }
public ConfigurationSection getConfigurationSection(Path path) { public ConfigurationSection getConfigurationSection(@NotNull Path path) {
return this.getConfig().getConfigurationSection(path.getPath()); return this.getConfig().getConfigurationSection(path.getPath());
} }
public List<String> getStringList(Path path) { public @NotNull List<String> getStringList(@NotNull Path path) {
return this.getConfig().getStringList(path.getPath()); return this.getConfig().getStringList(path.getPath());
} }
public long getLong(Path path) { public long getLong(@NotNull Path path) {
return this.getConfig().getLong(path.getPath()); return this.getConfig().getLong(path.getPath());
} }
public List<?> getList(Path path) { public List<?> getList(@NotNull Path path) {
return this.getConfig().getList(path.getPath()); return this.getConfig().getList(path.getPath());
} }
public boolean getBoolean(Path path) { public boolean getBoolean(@NotNull Path path) {
return this.getConfig().getBoolean(path.getPath()); return this.getConfig().getBoolean(path.getPath());
} }
public int getInt(Path path) { public int getInt(@NotNull Path path) {
return this.getConfig().getInt(path.getPath()); return this.getConfig().getInt(path.getPath());
} }
public double getDouble(Path path) { public double getDouble(@NotNull Path path) {
return this.getConfig().getDouble(path.getPath()); return this.getConfig().getDouble(path.getPath());
} }
public String getString(Path path) { public String getString(@NotNull Path path) {
return this.getConfig().getString(path.getPath()); return this.getConfig().getString(path.getPath());
} }
public long getLong(Path path, long def) { public long getLong(@NotNull Path path, long def) {
return this.getConfig().getLong(path.getPath(), def); return this.getConfig().getLong(path.getPath(), def);
} }
public List<?> getList(Path path, List<?> def) { @Contract("_, !null -> !null")
public List<?> getList(@NotNull Path path, List<?> def) {
return this.getConfig().getList(path.getPath(), def); return this.getConfig().getList(path.getPath(), def);
} }
public boolean getBoolean(Path path, boolean def) { public boolean getBoolean(@NotNull Path path, boolean def) {
return this.getConfig().getBoolean(path.getPath(), def); return this.getConfig().getBoolean(path.getPath(), def);
} }
public int getInt(Path path, int def) { public int getInt(@NotNull Path path, int def) {
return this.getConfig().getInt(path.getPath(), def); return this.getConfig().getInt(path.getPath(), def);
} }
public double getDouble(Path path, double def) { public double getDouble(@NotNull Path path, double def) {
return this.getConfig().getDouble(path.getPath(), def); return this.getConfig().getDouble(path.getPath(), def);
} }
public String getString(Path path, String def) { @Contract("_, !null -> !null")
public String getString(@NotNull Path path, String def) {
return this.getConfig().getString(path.getPath(), def); return this.getConfig().getString(path.getPath(), def);
} }
public Object get(Path path, Object def) { @Contract("_, !null -> !null")
public Object get(@NotNull Path path, Object def) {
return this.getConfig().get(path.getPath(), def); return this.getConfig().get(path.getPath(), def);
} }

View File

@ -4,6 +4,8 @@ import io.github.simplexdev.simplexcore.module.SimplexModule;
import io.github.simplexdev.simplexcore.utils.Trio; import io.github.simplexdev.simplexcore.utils.Trio;
import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.configuration.file.YamlConfiguration;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import java.io.File; import java.io.File;
@ -17,22 +19,26 @@ public final class YamlFactory {
this.plugin = plugin; this.plugin = plugin;
} }
public Yaml from(String resourcePath, File directory, String fileName) { @Contract("_, _, _ -> new")
public @NotNull Yaml from(String resourcePath, File directory, String fileName) {
this.resourcePath = resourcePath; this.resourcePath = resourcePath;
this.directory = directory; this.directory = directory;
this.fileName = fileName; this.fileName = fileName;
return new Yaml(plugin, fileName, directory, resourcePath); return new Yaml(plugin, fileName, directory, resourcePath);
} }
public FileConfiguration load(File yamlFile) { @Contract("_ -> new")
public @NotNull FileConfiguration load(File yamlFile) {
return YamlConfiguration.loadConfiguration(yamlFile); return YamlConfiguration.loadConfiguration(yamlFile);
} }
public Yaml setDefaultPathways() { @Contract(" -> new")
public @NotNull Yaml setDefaultPathways() {
return from("config.yml", plugin.getDataFolder(), "config.yml"); return from("config.yml", plugin.getDataFolder(), "config.yml");
} }
public Trio<String, File, String> pathways() { @Contract(value = " -> new", pure = true)
public @NotNull Trio<String, File, String> pathways() {
return new Trio<>(resourcePath, directory, fileName); return new Trio<>(resourcePath, directory, fileName);
} }
} }

View File

@ -9,6 +9,7 @@ import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays; import java.util.Arrays;
@ -90,7 +91,7 @@ public class ItemBuilder {
* Create a new AttributeModifier for an ItemStack's ItemMeta. * Create a new AttributeModifier for an ItemStack's ItemMeta.
* @param name The name of the modifier. * @param name The name of the modifier.
* @param amount The amount to add * @param amount The amount to add
* @param scalar Whether or not it should add as a number or a magnitude. * @param scalar Whether it should add as a number or a magnitude.
* @return A new AttributeModifier. * @return A new AttributeModifier.
*/ */
public AttributeModifier add(String name, double amount, boolean scalar) { public AttributeModifier add(String name, double amount, boolean scalar) {
@ -117,7 +118,7 @@ public class ItemBuilder {
/** /**
* @param stack The item to work from. * @param stack The item to work from.
*/ */
public Worker(ItemStack stack) { public Worker(@NotNull ItemStack stack) {
this.stack = stack; this.stack = stack;
this.meta = stack.getItemMeta(); this.meta = stack.getItemMeta();
} }
@ -127,7 +128,7 @@ public class ItemBuilder {
* @param lore The item lore to add. * @param lore The item lore to add.
* @return An appendable worker instance. * @return An appendable worker instance.
*/ */
public final Worker addLore(String... lore) { public Worker addLore(String... lore) {
meta.setLore(Arrays.asList(lore)); meta.setLore(Arrays.asList(lore));
stack.setItemMeta(meta); stack.setItemMeta(meta);
return this; return this;
@ -138,7 +139,7 @@ public class ItemBuilder {
* @param customName The new name of the item. * @param customName The new name of the item.
* @return An appendable worker instance. * @return An appendable worker instance.
*/ */
public final Worker setName(String customName) { public Worker setName(String customName) {
meta.setDisplayName(customName); meta.setDisplayName(customName);
stack.setItemMeta(meta); stack.setItemMeta(meta);
return this; return this;
@ -150,7 +151,7 @@ public class ItemBuilder {
* @param level The level of the enchantment. This is non-restrictive. * @param level The level of the enchantment. This is non-restrictive.
* @return An appendable worker instance. * @return An appendable worker instance.
*/ */
public final Worker addEnchant(Enchantment enchantment, int level) { public Worker addEnchant(Enchantment enchantment, int level) {
meta.addEnchant(enchantment, level, true); meta.addEnchant(enchantment, level, true);
stack.setItemMeta(meta); stack.setItemMeta(meta);
return this; return this;
@ -162,7 +163,7 @@ public class ItemBuilder {
* @param modifier The type of attribute modifier to use. * @param modifier The type of attribute modifier to use.
* @return An appendable worker instance. * @return An appendable worker instance.
*/ */
public final Worker addAttribute(Attribute attribute, AttributeModifier modifier) { public Worker addAttribute(Attribute attribute, AttributeModifier modifier) {
meta.addAttributeModifier(attribute, modifier); meta.addAttributeModifier(attribute, modifier);
stack.setItemMeta(meta); stack.setItemMeta(meta);
return this; return this;
@ -173,7 +174,7 @@ public class ItemBuilder {
* @param flags Any amount of ItemFlags to add to the item. * @param flags Any amount of ItemFlags to add to the item.
* @return An appendable worker instance. * @return An appendable worker instance.
*/ */
public final Worker addItemFlags(ItemFlag... flags) { public Worker addItemFlags(ItemFlag... flags) {
meta.addItemFlags(flags); meta.addItemFlags(flags);
stack.setItemMeta(meta); stack.setItemMeta(meta);
return this; return this;
@ -184,17 +185,17 @@ public class ItemBuilder {
* @param amount The amount of items this stack should represent. * @param amount The amount of items this stack should represent.
* @return An appendable worker instance. * @return An appendable worker instance.
*/ */
public final Worker setAmount(int amount) { public Worker setAmount(int amount) {
stack.setAmount(amount); stack.setAmount(amount);
return this; return this;
} }
public final Worker setType(Material material) { public Worker setType(Material material) {
stack.setType(material); stack.setType(material);
return this; return this;
} }
public final Worker setUnbreakable(boolean unbreakable) { public Worker setUnbreakable(boolean unbreakable) {
meta.setUnbreakable(unbreakable); meta.setUnbreakable(unbreakable);
stack.setItemMeta(meta); stack.setItemMeta(meta);
return this; return this;
@ -203,14 +204,14 @@ public class ItemBuilder {
/** /**
* @return The final item. * @return The final item.
*/ */
public final ItemStack getItem() { public ItemStack getItem() {
return stack; return stack;
} }
/** /**
* @return The ItemMeta of the item. * @return The ItemMeta of the item.
*/ */
public final ItemMeta getItemMeta() { public ItemMeta getItemMeta() {
return meta; return meta;
} }
} }

View File

@ -12,6 +12,7 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.Recipe; import org.bukkit.inventory.Recipe;
import org.bukkit.inventory.ShapedRecipe; import org.bukkit.inventory.ShapedRecipe;
import org.bukkit.inventory.ShapelessRecipe; import org.bukkit.inventory.ShapelessRecipe;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -35,7 +36,8 @@ public final class RecipeBuilder {
* @param isShaped Whether or not the recipe is shaped or shapeless. * @param isShaped Whether or not the recipe is shaped or shapeless.
* @return A new appendable RecipeBuilder Worker instance based on the given parameters. * @return A new appendable RecipeBuilder Worker instance based on the given parameters.
*/ */
public final Worker newRecipe(ItemStack result, String recipeName, boolean isShaped) { @Contract("_, _, _ -> new")
public @NotNull Worker newRecipe(ItemStack result, String recipeName, boolean isShaped) {
return new Worker(result, recipeName, isShaped); return new Worker(result, recipeName, isShaped);
} }
@ -60,7 +62,7 @@ public final class RecipeBuilder {
this.shaped = isShaped; this.shaped = isShaped;
} }
private ShapelessRecipe nosha() { private @NotNull ShapelessRecipe nosha() {
ShapelessRecipe recipe = new ShapelessRecipe(key, stack); ShapelessRecipe recipe = new ShapelessRecipe(key, stack);
if (materials.size() > 9 || materials.isEmpty()) return recipe; if (materials.size() > 9 || materials.isEmpty()) return recipe;
materials.forEach(recipe::addIngredient); materials.forEach(recipe::addIngredient);
@ -68,7 +70,7 @@ public final class RecipeBuilder {
return recipe; return recipe;
} }
private ShapedRecipe sha() { private @NotNull ShapedRecipe sha() {
ShapedRecipe recipe = new ShapedRecipe(key, stack); ShapedRecipe recipe = new ShapedRecipe(key, stack);
if (ingredients.isEmpty()) return recipe; if (ingredients.isEmpty()) return recipe;
recipe.shape(shape); recipe.shape(shape);

View File

@ -2,6 +2,7 @@ package io.github.simplexdev.simplexcore.gui;
import io.github.simplexdev.api.func.ClickAction; import io.github.simplexdev.api.func.ClickAction;
import io.github.simplexdev.api.IGUI; import io.github.simplexdev.api.IGUI;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -13,35 +14,34 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.*; import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
public abstract class AbstractGUI implements InventoryHolder, IGUI { public abstract class AbstractGUI implements InventoryHolder, IGUI {
private final Inventory INV; private final Inventory INV;
private final Map<Integer, ClickAction> actions; private final Map<Integer, ClickAction> actions;
private final UUID uuid; private final UUID uuid;
private final Map<IGUI, List<AbstractGUI>> pagesByGUI = new HashMap<>();
private final List<Integer> validSize = new ArrayList<>(){{
add(9);
add(18);
add(27);
add(36);
add(45);
add(54);
}};
private int pages = 0;
public static final Map<UUID, IGUI> invByUUId = new HashMap<>(); public static final Map<UUID, IGUI> invByUUId = new HashMap<>();
public static final Map<UUID, UUID> openInvs = new HashMap<>(); public static final Map<UUID, UUID> openInvs = new HashMap<>();
private final Map<Integer, AbstractGUI> pages = new HashMap<>();
public AbstractGUI(int size, String name) { public AbstractGUI(int size, String name) {
uuid = UUID.randomUUID(); uuid = UUID.randomUUID();
List<Integer> validSize = new ArrayList<>() {{
add(9);
add(18);
add(27);
add(36);
add(45);
add(54);
}};
if (!validSize.contains(size)) { if (!validSize.contains(size)) {
throw new NumberFormatException("Inventory sizes must be a multiple of nine!"); throw new NumberFormatException("Inventory sizes must be a multiple of nine, and no larger than 54.");
} }
INV = Bukkit.createInventory(null, size, name); INV = Bukkit.createInventory(null, size, Component.text(name));
actions = new HashMap<>(); actions = new HashMap<>();
invByUUId.put(getInvUUId(), this); invByUUId.put(getInvUUId(), this);
pages.put(0, this);
} }
@Override @Override
@ -91,16 +91,25 @@ public abstract class AbstractGUI implements InventoryHolder, IGUI {
invByUUId.remove(getInvUUId()); invByUUId.remove(getInvUUId());
} }
// Maybe just use pages.size() ?
public void addPage(AbstractGUI page) { public void addPage(AbstractGUI page) {
pages += 1; pages.put(pages.size() + 1, page);
} }
public void deletePage(AbstractGUI page) { public void deletePage(AbstractGUI page) {
if (pages == 0) { if (pages.isEmpty()) {
return; return;
} }
pages -= 1; AtomicInteger key = new AtomicInteger(0);
pages.forEach((key1, value) -> {
if (page.equals(value)) {
key.set(key1);
}
});
if (key.get() != 0) {
pages.remove(key, page);
}
} }
public static Map<UUID, IGUI> getInvByUUId() { public static Map<UUID, IGUI> getInvByUUId() {
@ -117,21 +126,21 @@ public abstract class AbstractGUI implements InventoryHolder, IGUI {
} }
@Override @Override
public ItemStack newItem(@NotNull Material material, @NotNull String name, String... lore) { public ItemStack newItem(@NotNull Material material, @NotNull String name, Component... lore) {
ItemStack item = new ItemStack(material, 1); ItemStack item = new ItemStack(material, 1);
ItemMeta meta = item.getItemMeta(); ItemMeta meta = item.getItemMeta();
if (meta == null) { if (meta == null) {
return item; return item;
} }
meta.setDisplayName(name); meta.displayName(Component.text(name));
ArrayList<String> metaLore = new ArrayList<>(Arrays.asList(lore)); ArrayList<Component> metaLore = new ArrayList<>(Arrays.asList(lore));
meta.setLore(metaLore); meta.lore(metaLore);
item.setItemMeta(meta); item.setItemMeta(meta);
return item; return item;
} }
@Override @Override
public ItemStack newItem(@NotNull Material material, @NotNull String name) { public ItemStack newItem(@NotNull Material material, @NotNull String name) {
return newItem(material, name, ""); return newItem(material, name, Component.text(""));
} }
} }

View File

@ -9,21 +9,21 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent; import org.bukkit.event.inventory.InventoryCloseEvent;
import org.jetbrains.annotations.NotNull;
import java.util.UUID; import java.util.UUID;
public final class GUIHandler extends SimplexListener { public final class GUIHandler extends SimplexListener {
public GUIHandler(SimplexModule<?> plugin) { public GUIHandler(SimplexModule<?> plugin) {
register(this, plugin); super(plugin);
} }
@EventHandler(priority = EventPriority.NORMAL) @EventHandler(priority = EventPriority.NORMAL)
public void invClick(InventoryClickEvent event) { public void invClick(@NotNull InventoryClickEvent event) {
if (!(event.getWhoClicked() instanceof Player)) { if (!(event.getWhoClicked() instanceof Player player)) {
return; return;
} }
Player player = (Player) event.getWhoClicked();
UUID pID = player.getUniqueId(); UUID pID = player.getUniqueId();
UUID invUUID = AbstractGUI.getOpenInvs().get(pID); UUID invUUID = AbstractGUI.getOpenInvs().get(pID);
@ -38,7 +38,7 @@ public final class GUIHandler extends SimplexListener {
} }
@EventHandler(priority = EventPriority.NORMAL) @EventHandler(priority = EventPriority.NORMAL)
public void onClose(InventoryCloseEvent event) { public void onClose(@NotNull InventoryCloseEvent event) {
Player player = (Player) event.getPlayer(); Player player = (Player) event.getPlayer();
AbstractGUI.getOpenInvs().remove(player.getUniqueId()); AbstractGUI.getOpenInvs().remove(player.getUniqueId());
} }

View File

@ -1,38 +1,18 @@
package io.github.simplexdev.simplexcore.listener; package io.github.simplexdev.simplexcore.listener;
import io.github.simplexdev.simplexcore.SimplexCorePlugin;
import io.github.simplexdev.simplexcore.module.SimplexModule; import io.github.simplexdev.simplexcore.module.SimplexModule;
import io.github.simplexdev.simplexcore.utils.ReflectionTools;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public abstract class SimplexListener implements Listener { public abstract class SimplexListener implements Listener {
/** protected final SimplexModule<?> plugin;
* This will register your listener by its class. This requires your class to have a single constructor which takes no parameters.
* This also requires the class in question to extend SimplexListener.
*
* @param cls The class to register.
*/
public static void registerFromClass(Class<? extends SimplexListener> cls, SimplexModule<?> plugin) {
if (!SimplexListener.class.isAssignableFrom(cls)) {
SimplexCorePlugin.getInstance().getLogger().severe("You can only register subclasses of SimplexListener with this method.");
return;
}
Constructor<? extends SimplexListener> constr = ReflectionTools.getDeclaredConstructor(cls); public SimplexListener(@NotNull SimplexModule<?> plugin) {
register(ReflectionTools.initConstructor(constr), plugin); this.plugin = plugin;
plugin.getManager().registerEvents(this, plugin);
} }
/** protected final SimplexModule<?> getPlugin() {
* Registers your listener with the server plugin manager. return plugin;
*
* @param listener The listener instance
* @param plugin Your plugin instance
* @param <T> Type of which extends SimplexListener.
*/
public static <T extends SimplexListener> void register(T listener, SimplexModule<?> plugin) {
SimplexCorePlugin.getInstance().getManager().registerEvents(listener, plugin);
} }
} }

View File

@ -3,6 +3,8 @@ package io.github.simplexdev.simplexcore.module;
import io.github.simplexdev.api.annotations.ReqType; import io.github.simplexdev.api.annotations.ReqType;
import io.github.simplexdev.api.annotations.Requires; import io.github.simplexdev.api.annotations.Requires;
import io.github.simplexdev.simplexcore.SimplexCorePlugin; import io.github.simplexdev.simplexcore.SimplexCorePlugin;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
@ -11,62 +13,19 @@ public final class ModuleRegistry {
private static final ModuleRegistry instance = new ModuleRegistry(); private static final ModuleRegistry instance = new ModuleRegistry();
private final Set<SimplexModule<?>> modules = new HashSet<>(); private final Set<SimplexModule<?>> modules = new HashSet<>();
protected ModuleRegistry() { private ModuleRegistry() {
} }
public static synchronized ModuleRegistry getInstance() { public static ModuleRegistry getInstance() {
return instance; return instance;
} }
public <T extends SimplexModule<T>> boolean isPaper(T addon) { @Contract(pure = true)
try { private boolean checkAnnotation(@NotNull Requires info, ReqType type) {
Class.forName(com.destroystokyo.paper.Namespaced.class.getName());
return true;
} catch (ClassNotFoundException ignored) {
addon.stop();
SimplexCorePlugin.getInstance().getLogger().severe(addon.getName() + " has been disabled: This module requires Paper!");
return false;
}
}
public <T extends SimplexModule<T>> boolean isSpigot(T addon) {
try {
Class.forName(org.spigotmc.WatchdogThread.class.getName());
return true;
} catch (ClassNotFoundException ignored) {
addon.stop();
SimplexCorePlugin.getInstance().getLogger().severe(addon.getName() + " has been disabled: This module requires Paper!");
return false;
}
}
private <T extends SimplexModule<T>> boolean isBungee(T addon) {
try {
Class.forName(net.md_5.bungee.Util.class.getName());
return true;
} catch (ClassNotFoundException ignored) {
addon.stop();
SimplexCorePlugin.getInstance().getLogger().severe(addon.getName() + " has been disabled: This module requires Bungeecord!");
return false;
}
}
private boolean checkAnnotation(Requires info, ReqType type) {
return info.value() == type; return info.value() == type;
} }
public <T extends SimplexModule<T>> void register(T addon) { public <T extends SimplexModule<T>> void register(T addon) {
if (addon.getClass().isAnnotationPresent(Requires.class)) {
Requires info = addon.getClass().getDeclaredAnnotation(Requires.class);
if (checkAnnotation(info, ReqType.SPIGOT)
&& (!isSpigot(addon) || !isPaper(addon))) {
return;
}
if (checkAnnotation(info, ReqType.BUNGEECORD)
&& !isBungee(addon)) {
return;
}
}
getModules().add(addon); getModules().add(addon);
} }

View File

@ -11,6 +11,7 @@ import org.bukkit.entity.AreaEffectCloud;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffect;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -131,7 +132,7 @@ public final class ParticleFactory {
}; };
} }
public void spawnParticleCloud(IParticleEffect effect, Location location) { public void spawnParticleCloud(IParticleEffect effect, @NotNull Location location) {
World world = location.getWorld(); World world = location.getWorld();
if (world == null) return; if (world == null) return;
AreaEffectCloud cloud = (AreaEffectCloud) world.spawnEntity(location, EntityType.AREA_EFFECT_CLOUD); AreaEffectCloud cloud = (AreaEffectCloud) world.spawnEntity(location, EntityType.AREA_EFFECT_CLOUD);
@ -145,25 +146,27 @@ public final class ParticleFactory {
cloud.setPersistent(true); cloud.setPersistent(true);
} }
public void spawnDirectionalParticle(Particle particle, Location location, double xDirection, double yDirection, double zDirection) { public void spawnDirectionalParticle(Particle particle, @NotNull Location location, double xDirection, double yDirection, double zDirection) {
World world = location.getWorld(); World world = location.getWorld();
if (world == null) return; if (world == null) return;
world.spawnParticle(particle, location, 0, xDirection, yDirection, zDirection); world.spawnParticle(particle, location, 0, xDirection, yDirection, zDirection);
} }
public void spawnRedstoneParticle(Location location, int count, Particle.DustOptions options) { public void spawnRedstoneParticle(@NotNull Location location, int count, Particle.DustOptions options) {
World world = location.getWorld(); World world = location.getWorld();
if (world == null) return; if (world == null) return;
world.spawnParticle(Particle.REDSTONE, location, count, options); world.spawnParticle(Particle.REDSTONE, location, count, options);
} }
public static Particle.DustOptions options(IParticleEffect effect, float size) { @Contract("_, _ -> new")
public static Particle.@NotNull DustOptions options(@NotNull IParticleEffect effect, float size) {
return new Particle.DustOptions(effect.getParticleColor(), size); return new Particle.DustOptions(effect.getParticleColor(), size);
} }
public static Particle.DustOptions options(int red, int green, int blue, float size) { @Contract("_, _, _, _ -> new")
public static Particle.@NotNull DustOptions options(int red, int green, int blue, float size) {
if (red > 255) { if (red > 255) {
red = 255; red = 255;
} }
@ -176,7 +179,7 @@ public final class ParticleFactory {
return new Particle.DustOptions(Color.fromRGB(red, green, blue), size); return new Particle.DustOptions(Color.fromRGB(red, green, blue), size);
} }
public void spawnParticle(IParticleEffect effect, Location location, int count) { public void spawnParticle(IParticleEffect effect, @NotNull Location location, int count) {
World world = location.getWorld(); World world = location.getWorld();
if (world == null) return; if (world == null) return;
@ -220,7 +223,7 @@ public final class ParticleFactory {
} }
} }
public final SimplexModule<?> getPlugin() { public SimplexModule<?> getPlugin() {
return plugin; return plugin;
} }

View File

@ -36,7 +36,7 @@ public final class PotionEffectFactory {
* @param effects The {@link PotionEffectType}(s) you want to be included. * @param effects The {@link PotionEffectType}(s) you want to be included.
* @return A new compound effect. * @return A new compound effect.
*/ */
public static ICompoundEffect compoundEffect(SimplexModule<?> plugin, String name, int duration, int amplifier, PotionEffectType... effects) { public static @NotNull ICompoundEffect compoundEffect(SimplexModule<?> plugin, String name, int duration, int amplifier, PotionEffectType... effects) {
List<PotionEffect> list = new ArrayList<>(); List<PotionEffect> list = new ArrayList<>();
Utilities.forEach(effects, effect -> { Utilities.forEach(effects, effect -> {
@ -83,7 +83,7 @@ public final class PotionEffectFactory {
* @param amplifier How strong the potion is. * @param amplifier How strong the potion is.
* @return A new {@link PotionEffect}. * @return A new {@link PotionEffect}.
*/ */
public static PotionEffect potionEffect(PotionEffectType type, int duration, int amplifier) { public static @NotNull PotionEffect potionEffect(@NotNull PotionEffectType type, int duration, int amplifier) {
return type.createEffect(duration, amplifier); return type.createEffect(duration, amplifier);
} }
@ -91,7 +91,7 @@ public final class PotionEffectFactory {
* Applies the compound effect to the defined player. * Applies the compound effect to the defined player.
* @param effect The {@link ICompoundEffect} to apply. * @param effect The {@link ICompoundEffect} to apply.
*/ */
public void applyCompoundEffect(ICompoundEffect effect) { public void applyCompoundEffect(@NotNull ICompoundEffect effect) {
effect.getEffects().forEach(player::addPotionEffect); effect.getEffects().forEach(player::addPotionEffect);
map.put(player, effect); map.put(player, effect);
} }
@ -99,7 +99,7 @@ public final class PotionEffectFactory {
/** /**
* Checks if a player currently has a compound effect. * Checks if a player currently has a compound effect.
* @param effect The {@link ICompoundEffect} to look for * @param effect The {@link ICompoundEffect} to look for
* @return Whether or not the player has the compound effect. * @return Whether the player has the compound effect.
*/ */
public boolean hasPotionEffect(ICompoundEffect effect) { public boolean hasPotionEffect(ICompoundEffect effect) {
return (map.containsKey(player) && map.get(player).equals(effect)); return (map.containsKey(player) && map.get(player).equals(effect));

View File

@ -1,5 +1,7 @@
package io.github.simplexdev.simplexcore.sql; package io.github.simplexdev.simplexcore.sql;
import org.jetbrains.annotations.Nullable;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
@ -75,7 +77,7 @@ public class Database {
return false; return false;
} }
public static String getString(String table, String column, String gate, Object gate_value) { public static @Nullable String getString(String table, String column, String gate, Object gate_value) {
PreparedStatement ps; PreparedStatement ps;
try { try {
ps = MySQL.getConnection().prepareStatement("SELECT ? FROM ? WHERE ?=?"); ps = MySQL.getConnection().prepareStatement("SELECT ? FROM ? WHERE ?=?");
@ -119,7 +121,7 @@ public class Database {
return 0; return 0;
} }
public static Double getDouble(String table, String column, String gate, Object gate_value) { public static @Nullable Double getDouble(String table, String column, String gate, Object gate_value) {
PreparedStatement ps; PreparedStatement ps;
try { try {
ps = MySQL.getConnection().prepareStatement("SELECT ? FROM ? WHERE ?=?"); ps = MySQL.getConnection().prepareStatement("SELECT ? FROM ? WHERE ?=?");
@ -185,7 +187,7 @@ public class Database {
return 0; return 0;
} }
public static Object get(String table, String column, String gate, Object gate_value) { public static @Nullable Object get(String table, String column, String gate, Object gate_value) {
PreparedStatement ps; PreparedStatement ps;
try { try {
ps = MySQL.getConnection().prepareStatement("SELECT ? FROM ? WHERE ?=?"); ps = MySQL.getConnection().prepareStatement("SELECT ? FROM ? WHERE ?=?");

View File

@ -13,18 +13,19 @@ import java.lang.reflect.Method;
import java.util.Set; import java.util.Set;
public final class ReflectionTools { public final class ReflectionTools {
@Contract("_ -> new")
@NotNull @NotNull
public static Reflections reflect(Class<?> loadFrom) { public static Reflections reflect(@NotNull Class<?> loadFrom) {
return new Reflections(loadFrom.getName()); return new Reflections(loadFrom.getName());
} }
@NotNull @NotNull
public static Set<Class<?>> getAnnotatedClasses(Class<?> loadFrom, Class<? extends Annotation> annotation) { public static Set<Class<?>> getAnnotatedClasses(@NotNull Class<?> loadFrom, Class<? extends Annotation> annotation) {
return new Reflections(loadFrom.getName()).getTypesAnnotatedWith(annotation); return new Reflections(loadFrom.getName()).getTypesAnnotatedWith(annotation);
} }
@Nullable @Nullable
public static <T> Field getField(Class<T> cls, String name) { public static <T> Field getField(@NotNull Class<T> cls, String name) {
try { try {
return asAccessible(cls.getField(name)); return asAccessible(cls.getField(name));
} catch (NoSuchFieldException ignored) { } catch (NoSuchFieldException ignored) {
@ -33,7 +34,7 @@ public final class ReflectionTools {
} }
@Nullable @Nullable
public static <T> Field getDeclaredField(Class<T> cls, String name) { public static <T> Field getDeclaredField(@NotNull Class<T> cls, String name) {
try { try {
return asAccessible(cls.getDeclaredField(name)); return asAccessible(cls.getDeclaredField(name));
} catch (ReflectiveOperationException ignored) { } catch (ReflectiveOperationException ignored) {
@ -42,7 +43,7 @@ public final class ReflectionTools {
} }
@Nullable @Nullable
public static <T> Constructor<T> getConstructor(Class<T> cls, Class<?>... initializers) { public static <T> Constructor<T> getConstructor(@NotNull Class<T> cls, Class<?>... initializers) {
try { try {
return asAccessible(cls.getConstructor(initializers)); return asAccessible(cls.getConstructor(initializers));
} catch (NoSuchMethodException ignored) { } catch (NoSuchMethodException ignored) {
@ -51,7 +52,7 @@ public final class ReflectionTools {
} }
@Nullable @Nullable
public static <T> Constructor<T> getDeclaredConstructor(Class<T> cls, Class<?>... initializers) { public static <T> Constructor<T> getDeclaredConstructor(@NotNull Class<T> cls, Class<?>... initializers) {
try { try {
return asAccessible(cls.getDeclaredConstructor(initializers)); return asAccessible(cls.getDeclaredConstructor(initializers));
} catch (NoSuchMethodException ignored) { } catch (NoSuchMethodException ignored) {
@ -60,7 +61,7 @@ public final class ReflectionTools {
} }
@Nullable @Nullable
public static <T> T initConstructor(Constructor<? extends T> constructor, Object... initializers) { public static <T> T initConstructor(@NotNull Constructor<? extends T> constructor, Object... initializers) {
try { try {
return constructor.newInstance(initializers); return constructor.newInstance(initializers);
} catch (ReflectiveOperationException e) { } catch (ReflectiveOperationException e) {
@ -69,7 +70,7 @@ public final class ReflectionTools {
} }
@Nullable @Nullable
public static <T> Method getMethod(Class<T> clazz, String name, Class<?>... params) { public static <T> Method getMethod(@NotNull Class<T> clazz, String name, Class<?>... params) {
try { try {
return asAccessible(clazz.getMethod(name, params)); return asAccessible(clazz.getMethod(name, params));
} catch (NoSuchMethodException e) { } catch (NoSuchMethodException e) {
@ -78,7 +79,7 @@ public final class ReflectionTools {
} }
@Nullable @Nullable
public static <T> Method getDeclaredMethod(Class<T> clazz, String name, Class<?>... params) { public static <T> Method getDeclaredMethod(@NotNull Class<T> clazz, String name, Class<?>... params) {
try { try {
return asAccessible(clazz.getDeclaredMethod(name, params)); return asAccessible(clazz.getDeclaredMethod(name, params));
} catch (ReflectiveOperationException ignored) { } catch (ReflectiveOperationException ignored) {
@ -88,7 +89,7 @@ public final class ReflectionTools {
@NotNull @NotNull
@Contract(pure = true) @Contract(pure = true)
public static <T extends AccessibleObject> T asAccessible(T object) { public static <T extends AccessibleObject> T asAccessible(@NotNull T object) {
object.setAccessible(true); object.setAccessible(true);
return object; return object;
} }

View File

@ -2,6 +2,7 @@ package io.github.simplexdev.simplexcore.utils;
import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.commons.lang.builder.HashCodeBuilder;
import org.jetbrains.annotations.NotNull;
public final class Trio<A, B, C> { public final class Trio<A, B, C> {
private final A primary; private final A primary;
@ -52,7 +53,7 @@ public final class Trio<A, B, C> {
} }
@Override @Override
public String toString() { public @NotNull String toString() {
return getPrimary().toString() + return getPrimary().toString() +
"\n" + "\n" +
getSecondary().toString() + getSecondary().toString() +

View File

@ -4,12 +4,15 @@ import io.github.simplexdev.api.func.Path;
import io.github.simplexdev.simplexcore.SimplexCorePlugin; import io.github.simplexdev.simplexcore.SimplexCorePlugin;
import io.github.simplexdev.simplexcore.ban.BanType; import io.github.simplexdev.simplexcore.ban.BanType;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.SplittableRandom; import java.util.SplittableRandom;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.stream.IntStream;
import java.util.stream.Stream; import java.util.stream.Stream;
public final class Utilities { public final class Utilities {
@ -36,17 +39,18 @@ public final class Utilities {
throw new AssertionError(); throw new AssertionError();
} }
public static <T> void forEach(T[] array, Consumer<? super T> action) { public static <T> void forEach(T @NotNull [] array, Consumer<? super T> action) {
for (T obj : array) { for (T obj : array) {
action.accept(obj); action.accept(obj);
} }
} }
public static <T> Stream<T> stream(T[] array) { @Contract(pure = true)
public static <T> @NotNull Stream<T> stream(T[] array) {
return Arrays.stream(array); return Arrays.stream(array);
} }
public static String generateBanId(BanType type) { public static @NotNull String generateBanId(@NotNull BanType type) {
final String charList = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"; final String charList = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
final String numList = "0123456789"; final String numList = "0123456789";
final int length = charList.length(); final int length = charList.length();
@ -56,10 +60,10 @@ public final class Utilities {
sb.append(type.getPrefix()); sb.append(type.getPrefix());
for (int x = 0; x < 4; x++) { IntStream.range(0, 4).forEach(x -> {
sb.append(charList.charAt(random.nextInt(length - 1))); sb.append(charList.charAt(random.nextInt(length - 1)));
sb.append(numList.charAt(numbers.nextInt(lng - 1))); sb.append(numList.charAt(numbers.nextInt(lng - 1)));
} });
sb.setCharAt(2, capitalize(sb.charAt(2))); sb.setCharAt(2, capitalize(sb.charAt(2)));
return sb.toString(); return sb.toString();
@ -74,15 +78,17 @@ public final class Utilities {
return temp.charAt(0); return temp.charAt(0);
} }
public static Path pathway(String pathway) { @Contract(pure = true)
public static @NotNull Path pathway(String pathway) {
return () -> pathway; return () -> pathway;
} }
public static String getNMSVersion() { public static @NotNull String getNMSVersion() {
return Bukkit.getServer().getClass().getPackage().getName().substring(23).replaceFirst("v", ""); return Bukkit.getServer().getClass().getPackage().getName().substring(23).replaceFirst("v", "");
} }
public static String[] formatVersion(String version) { @Contract(pure = true)
public static String @NotNull [] formatVersion(@NotNull String version) {
return (version).split(":"); return (version).split(":");
} }