From 0a9de233539021c8a342e747be941bbe33823569 Mon Sep 17 00:00:00 2001 From: nulli0n Date: Thu, 11 May 2023 18:06:28 +0600 Subject: [PATCH] More improvements --- .../engine/api/command/AbstractCommand.java | 123 +++++++++++++++--- .../engine/api/command/CommandFlag.java | 77 +++++++++++ .../engine/api/command/CommandResult.java | 81 ++++++++++++ .../engine/api/command/GeneralCommand.java | 9 ++ .../nexmedia/engine/api/config/JOption.java | 62 ++++++++- .../su/nexmedia/engine/api/config/JYML.java | 8 ++ .../api/data/AbstractUserDataHandler.java | 2 +- .../engine/api/editor/InputHandler.java | 67 ++++++++++ .../engine/api/menu/item/ItemOptions.java | 11 ++ .../api/placeholder/PlaceholderMap.java | 6 + .../engine/command/CommandRegister.java | 4 +- .../su/nexmedia/engine/utils/PlayerUtil.java | 15 ++- .../su/nexmedia/engine/utils/TriFunction.java | 14 ++ .../su/nexmedia/engine/utils/random/Rnd.java | 8 +- 14 files changed, 454 insertions(+), 33 deletions(-) create mode 100644 NexEngine/src/main/java/su/nexmedia/engine/api/command/CommandFlag.java create mode 100644 NexEngine/src/main/java/su/nexmedia/engine/api/command/CommandResult.java create mode 100644 NexEngine/src/main/java/su/nexmedia/engine/api/editor/InputHandler.java create mode 100644 NexEngine/src/main/java/su/nexmedia/engine/utils/TriFunction.java diff --git a/NexEngine/src/main/java/su/nexmedia/engine/api/command/AbstractCommand.java b/NexEngine/src/main/java/su/nexmedia/engine/api/command/AbstractCommand.java index 7ebbd82..a072142 100644 --- a/NexEngine/src/main/java/su/nexmedia/engine/api/command/AbstractCommand.java +++ b/NexEngine/src/main/java/su/nexmedia/engine/api/command/AbstractCommand.java @@ -6,11 +6,10 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import su.nexmedia.engine.NexPlugin; +import su.nexmedia.engine.api.lang.LangMessage; import su.nexmedia.engine.api.manager.IPlaceholder; import su.nexmedia.engine.lang.EngineLang; import su.nexmedia.engine.utils.Colorizer; -import su.nexmedia.engine.utils.StringUtil; -import su.nexmedia.engine.utils.message.NexParser; import su.nexmedia.engine.utils.regex.RegexUtil; import java.util.*; @@ -25,13 +24,20 @@ public abstract class AbstractCommand

> implements IPlaceh public static final String PLACEHOLDER_DESCRIPTION = "%command_description%"; public static final String PLACEHOLDER_LABEL = "%command_label%"; - private final Map flags; + @Deprecated private static final String FLAG_PATTERN = "(.*?)(?:-|$)"; - protected P plugin; - protected String[] aliases; - protected String permission; - protected Map> childrens; - protected AbstractCommand

parent; + @Deprecated private final Map flags; + + protected final P plugin; + protected final Map> childrens; + protected final Set> commandFlags; + + protected AbstractCommand

parent; + protected String[] aliases; + protected String permission; + protected String usage; + protected String description; + protected boolean playerOnly; public AbstractCommand(@NotNull P plugin, @NotNull List aliases) { this(plugin, aliases.toArray(new String[0])); @@ -58,6 +64,7 @@ public AbstractCommand(@NotNull P plugin, @NotNull String[] aliases, @Nullable S this.aliases = Stream.of(aliases).map(String::toLowerCase).toArray(String[]::new); this.permission = permission; this.childrens = new TreeMap<>(); + this.commandFlags = new HashSet<>(); this.flags = new HashMap<>(); } @@ -113,13 +120,41 @@ public final String getPermission() { return this.permission; } + public void setPermission(@Nullable Permission permission) { + this.setPermission(permission == null ? null : permission.getName()); + } + + public void setPermission(@Nullable String permission) { + this.permission = permission; + } + @NotNull + @Deprecated public Set getFlags() { return new HashSet<>(this.flags.keySet()); } + @NotNull + public Set> getCommandFlags() { + return commandFlags; + } + + public final void addFlag(@NotNull CommandFlag... flags) { + for (CommandFlag flag : flags) this.addFlag(flag); + } + + public final void addFlag(@NotNull CommandFlag flag) { + this.getCommandFlags().add(flag); + } + + @Deprecated + public final void registerFlag(@NotNull String... flags) { + for (String flag : flags) this.registerFlag(flag); + } + + @Deprecated public final void registerFlag(@NotNull String flag) { - this.flags.put(flag, Pattern.compile("-" + flag + NexParser.OPTION_PATTERN)); + this.flags.put(flag, Pattern.compile("-" + flag + FLAG_PATTERN));//NexParser.OPTION_PATTERN)); } public final void unregisterFlag(@NotNull String flag) { @@ -127,19 +162,56 @@ public final void unregisterFlag(@NotNull String flag) { } @NotNull - public abstract String getUsage(); + public String getUsage() { + return this.usage == null ? "" : this.usage; + } + + public void setUsage(@NotNull LangMessage message) { + this.setUsage(message.getLocalized()); + } + + public void setUsage(@NotNull String usage) { + this.usage = usage; + } @NotNull - public abstract String getDescription(); + public String getDescription() { + return this.description == null ? "" : this.description; + } - public abstract boolean isPlayerOnly(); + public void setDescription(@NotNull LangMessage message) { + this.setDescription(message.getLocalized()); + } + + public void setDescription(@NotNull String description) { + this.description = description; + } + + public boolean isPlayerOnly() { + return this.playerOnly; + } + + public void setPlayerOnly(boolean playerOnly) { + this.playerOnly = playerOnly; + } + + public final boolean hasPermission(@NotNull CommandSender sender) { + return this.permission == null || sender.hasPermission(this.permission); + } @NotNull public List getTab(@NotNull Player player, int arg, @NotNull String[] args) { - return Collections.emptyList(); + return this.getCommandFlags().stream().map(CommandFlag::getNamePrefixed).toList(); } - protected abstract void onExecute(@NotNull CommandSender sender, @NotNull String label, @NotNull String[] args, @NotNull Map flags); + @Deprecated + protected void onExecute(@NotNull CommandSender sender, @NotNull String label, @NotNull String[] args, @NotNull Map flags) { + + } + + protected void onExecute(@NotNull CommandSender sender, @NotNull CommandResult result) { + + } public final void execute(@NotNull CommandSender sender, @NotNull String label, @NotNull String[] args) { if (this.isPlayerOnly() && !(sender instanceof Player)) { @@ -160,18 +232,31 @@ public final void execute(@NotNull CommandSender sender, @NotNull String label, Matcher matcher = RegexUtil.getMatcher(pattern, argLine); if (RegexUtil.matcherFind(matcher)) { - flags.put(flag, Colorizer.legacyHex(matcher.group(1))); - argLine = StringUtil.oneSpace(argLine.replace(matcher.group(0), "")); + flags.put(flag, Colorizer.legacyHex(matcher.group(2))); + argLine = /*StringUtil.oneSpace(*/argLine.replace(matcher.group(1), "")/*)*/; } } args = argLine.split(" "); } this.onExecute(sender, label, args, flags); - } - public final boolean hasPermission(@NotNull CommandSender sender) { - return this.permission == null || sender.hasPermission(this.permission); + // API UPGRADE + CommandResult result = new CommandResult(label, args, new HashMap<>()); + String argLine = String.join(" ", args); + for (CommandFlag flag : this.getCommandFlags()) { + String name = flag.getName(); + Pattern pattern = flag.getPattern(); + + Matcher matcher = RegexUtil.getMatcher(pattern, argLine); + if (RegexUtil.matcherFind(matcher)) { + result.getFlags().put(flag, matcher.group(2).trim()); + argLine = argLine.replace(matcher.group(0), ""); + } + } + result.setArgs(argLine.isEmpty() ? new String[0] : argLine.trim().split(" ")); + + this.onExecute(sender, result); } @NotNull diff --git a/NexEngine/src/main/java/su/nexmedia/engine/api/command/CommandFlag.java b/NexEngine/src/main/java/su/nexmedia/engine/api/command/CommandFlag.java new file mode 100644 index 0000000..b2e590f --- /dev/null +++ b/NexEngine/src/main/java/su/nexmedia/engine/api/command/CommandFlag.java @@ -0,0 +1,77 @@ +package su.nexmedia.engine.api.command; + +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.jetbrains.annotations.NotNull; +import su.nexmedia.engine.utils.Colorizer; +import su.nexmedia.engine.utils.StringUtil; + +import java.util.function.Function; +import java.util.regex.Pattern; + +public class CommandFlag { + + private final String name; + private final Pattern pattern; + private final Function parser; + + public CommandFlag(@NotNull String name, @NotNull Function parser) { + this.name = name; + //this.pattern = Pattern.compile("(-" + name + "(.*?))(?:-|$)"); + //this.pattern = Pattern.compile("-" + name + "(.*?(?:-|$|\\S+))"); + + //this.pattern = Pattern.compile("-" + name + "(\\s|$)((?=-)|\\S*)"); valid + this.pattern = Pattern.compile("-" + name + "(\\s|$)([^-]*)"); // experimantal + this.parser = parser; + } + + @NotNull + public static CommandFlag worldFlag(@NotNull String name) { + return new CommandFlag<>(name, Bukkit::getWorld); + } + + @NotNull + public static CommandFlag stringFlag(@NotNull String name) { + return new CommandFlag<>(name, Function.identity()); + } + + @NotNull + public static CommandFlag textFlag(@NotNull String name) { + return new CommandFlag<>(name, Colorizer::apply); + } + + @NotNull + public static CommandFlag intFlag(@NotNull String name) { + return new CommandFlag<>(name, str -> StringUtil.getInteger(str, 0, true)); + } + + @NotNull + public static CommandFlag doubleFlag(@NotNull String name) { + return new CommandFlag<>(name, str -> StringUtil.getDouble(str, 0, true)); + } + + @NotNull + public static CommandFlag booleanFlag(@NotNull String name) { + return new CommandFlag<>(name, str -> true); + } + + @NotNull + public String getName() { + return name; + } + + @NotNull + public String getNamePrefixed() { + return "-" + name; + } + + @NotNull + public Pattern getPattern() { + return pattern; + } + + @NotNull + public Function getParser() { + return parser; + } +} diff --git a/NexEngine/src/main/java/su/nexmedia/engine/api/command/CommandResult.java b/NexEngine/src/main/java/su/nexmedia/engine/api/command/CommandResult.java new file mode 100644 index 0000000..1e0ce45 --- /dev/null +++ b/NexEngine/src/main/java/su/nexmedia/engine/api/command/CommandResult.java @@ -0,0 +1,81 @@ +package su.nexmedia.engine.api.command; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import su.nexmedia.engine.utils.StringUtil; + +import java.util.Map; + +public class CommandResult { + + private final String label; + private final Map, String> flags; + + private String[] args; + + public CommandResult(@NotNull String label, String[] args, @NotNull Map, String> flags) { + this.label = label; + this.flags = flags; + this.setArgs(args); + } + + public int length() { + return this.args.length; + } + + public void setArgs(@NotNull String[] args) { + this.args = args; + } + + @NotNull + public String getArg(int index) { + return this.getArgs()[index]; + } + + @NotNull + public String getArg(int index, @NotNull String def) { + if (index >= this.length()) return def; + + return this.getArgs()[index]; + } + + public int getInt(int index, int def) { + return StringUtil.getInteger(this.getArg(index, ""), def, true); + } + + public double getDouble(int index, double def) { + return StringUtil.getDouble(this.getArg(index, ""), def, true); + } + + public boolean hasFlag(@NotNull CommandFlag flag) { + return this.getFlags().containsKey(flag); + } + + @Nullable + public T getFlag(@NotNull CommandFlag flag) { + String value = this.getFlags().get(flag); + if (value == null) return null; + + return flag.getParser().apply(value); + } + + @NotNull + public T getFlag(@NotNull CommandFlag flag, @NotNull T def) { + T value = this.getFlag(flag); + return value == null ? def : value; + } + + @NotNull + public String getLabel() { + return label; + } + + public String[] getArgs() { + return args; + } + + @NotNull + public Map, String> getFlags() { + return flags; + } +} diff --git a/NexEngine/src/main/java/su/nexmedia/engine/api/command/GeneralCommand.java b/NexEngine/src/main/java/su/nexmedia/engine/api/command/GeneralCommand.java index b933ab3..38c4c44 100644 --- a/NexEngine/src/main/java/su/nexmedia/engine/api/command/GeneralCommand.java +++ b/NexEngine/src/main/java/su/nexmedia/engine/api/command/GeneralCommand.java @@ -18,6 +18,7 @@ public abstract class GeneralCommand

> extends AbstractCommand

implements CommandExecutor, TabExecutor { + private Command fallback; private AbstractCommand

defaultCommand; public GeneralCommand(@NotNull P plugin, @NotNull List aliases) { @@ -49,6 +50,14 @@ public void addDefaultCommand(@NotNull AbstractCommand

command) { this.defaultCommand = command; } + public Command getFallback() { + return fallback; + } + + public void setFallback(@NotNull Command fallback) { + this.fallback = fallback; + } + @NotNull public AbstractCommand

findChildren(@NotNull String[] args) { AbstractCommand

command = this;//.defaultCommand; diff --git a/NexEngine/src/main/java/su/nexmedia/engine/api/config/JOption.java b/NexEngine/src/main/java/su/nexmedia/engine/api/config/JOption.java index 79f6ccb..29663f7 100644 --- a/NexEngine/src/main/java/su/nexmedia/engine/api/config/JOption.java +++ b/NexEngine/src/main/java/su/nexmedia/engine/api/config/JOption.java @@ -4,11 +4,13 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import su.nexmedia.engine.api.particle.SimpleParticle; +import su.nexmedia.engine.utils.TriFunction; -import java.util.List; -import java.util.Set; +import java.util.*; +import java.util.function.Function; import java.util.function.Supplier; import java.util.function.UnaryOperator; +import java.util.stream.Collectors; public class JOption { @@ -91,6 +93,62 @@ public static JOption create(@NotNull String path, @NotNull Simp .setWriter((cfg, path1, particle) -> SimpleParticle.write(particle, cfg, path1)); } + @NotNull + public static JOption> forSet(@NotNull String path, @NotNull Function valFun, + @NotNull Supplier> defaultValue, @NotNull String... description) { + return forSet(path, valFun, defaultValue.get(), description); + } + + @NotNull + public static JOption> forSet(@NotNull String path, @NotNull Function valFun, + @NotNull Set defaultValue, @NotNull String... description) { + return new JOption<>(path, + (cfg, path1, def) -> cfg.getStringSet(path1).stream().map(valFun).filter(Objects::nonNull).collect(Collectors.toCollection(HashSet::new)), + defaultValue, + description); + } + + @NotNull + public static JOption> forMap(@NotNull String path, + @NotNull Function keyFun, + @NotNull TriFunction valFun, + @NotNull Supplier> defaultValue, @NotNull String... description) { + return forMap(path, keyFun, valFun, defaultValue.get(), description); + } + + @NotNull + public static JOption> forMap(@NotNull String path, + @NotNull Function keyFun, + @NotNull TriFunction valFun, + @NotNull Map defaultValue, @NotNull String... description) { + return new JOption<>(path, + (cfg, path1, def) -> { + Map map = new HashMap<>(); + for (String id : cfg.getSection(path1)) { + K key = keyFun.apply(id); + V val = valFun.apply(cfg, path1, id); + if (key == null || val == null) continue; + + map.put(key, val); + } + return map; + }, + defaultValue, + description); + } + + @NotNull + public static JOption> forMap(@NotNull String path, @NotNull TriFunction function, + @NotNull Supplier> defaultValue, @NotNull String... description) { + return forMap(path, String::toLowerCase, function, defaultValue.get(), description); + } + + @NotNull + public static JOption> forMap(@NotNull String path, @NotNull TriFunction function, + @NotNull Map defaultValue, @NotNull String... description) { + return forMap(path, String::toLowerCase, function, defaultValue, description); + } + @NotNull public T read(@NotNull JYML cfg) { if (!cfg.contains(this.getPath())) { diff --git a/NexEngine/src/main/java/su/nexmedia/engine/api/config/JYML.java b/NexEngine/src/main/java/su/nexmedia/engine/api/config/JYML.java index 5e9617a..a621f8f 100644 --- a/NexEngine/src/main/java/su/nexmedia/engine/api/config/JYML.java +++ b/NexEngine/src/main/java/su/nexmedia/engine/api/config/JYML.java @@ -50,6 +50,14 @@ public JYML(@NotNull File file) { this.reload(); } + @NotNull + public static JYML loadOrExtract(@NotNull NexPlugin plugin, @NotNull String path, @NotNull String file) { + if (!path.endsWith("/")) { + path += "/"; + } + return loadOrExtract(plugin, path + file); + } + @NotNull public static JYML loadOrExtract(@NotNull NexPlugin plugin, @NotNull String filePath) { if (!filePath.startsWith("/")) { diff --git a/NexEngine/src/main/java/su/nexmedia/engine/api/data/AbstractUserDataHandler.java b/NexEngine/src/main/java/su/nexmedia/engine/api/data/AbstractUserDataHandler.java index d26cb59..21c2eb0 100644 --- a/NexEngine/src/main/java/su/nexmedia/engine/api/data/AbstractUserDataHandler.java +++ b/NexEngine/src/main/java/su/nexmedia/engine/api/data/AbstractUserDataHandler.java @@ -111,7 +111,7 @@ public U getUser(@NotNull Player player) { @Nullable public final U getUser(@NotNull String name) { return this.load(this.tableUsers, this.getFunctionToUser(), this.getReadColumns(), - Collections.singletonList(SQLCondition.equal(COLUMN_USER_NAME.asLowerCase().toValue(name))) + Collections.singletonList(SQLCondition.equal(COLUMN_USER_NAME.asLowerCase().toValue(name.toLowerCase()))) ).orElse(null); } diff --git a/NexEngine/src/main/java/su/nexmedia/engine/api/editor/InputHandler.java b/NexEngine/src/main/java/su/nexmedia/engine/api/editor/InputHandler.java new file mode 100644 index 0000000..b1faf4a --- /dev/null +++ b/NexEngine/src/main/java/su/nexmedia/engine/api/editor/InputHandler.java @@ -0,0 +1,67 @@ +package su.nexmedia.engine.api.editor; + +import org.bukkit.event.player.AsyncPlayerChatEvent; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import su.nexmedia.engine.utils.Colorizer; +import su.nexmedia.engine.utils.StringUtil; + +public class InputHandler { + + private final String text; + private final String textRaw; + private final String textColored; + + public InputHandler(@NotNull AsyncPlayerChatEvent e) { + this.text = e.getMessage(); + this.textRaw = Colorizer.restrip(e.getMessage()); + this.textColored = Colorizer.apply(e.getMessage()); + } + + public int asInt() { + return this.asInt(0); + } + + public int asInt(int def) { + return StringUtil.getInteger(this.getTextRaw(), def); + } + + public double asDouble() { + return this.asDouble(0D); + } + + public double asDouble(double def) { + return StringUtil.getDouble(this.getTextRaw(), def); + } + + @Nullable + public > E asEnum(@NotNull Class clazz) { + return StringUtil.getEnum(this.getTextRaw(), clazz).orElse(null); + } + + @NotNull + public > E asEnum(@NotNull Class clazz, @NotNull E def) { + return StringUtil.getEnum(this.getTextRaw(), clazz).orElse(def); + } + + @NotNull + @Deprecated + public String getMessage() { + return this.text; + } + + @NotNull + public String getText() { + return text; + } + + @NotNull + public String getTextRaw() { + return textRaw; + } + + @NotNull + public String getTextColored() { + return textColored; + } +} diff --git a/NexEngine/src/main/java/su/nexmedia/engine/api/menu/item/ItemOptions.java b/NexEngine/src/main/java/su/nexmedia/engine/api/menu/item/ItemOptions.java index 4a5b79f..8244e08 100644 --- a/NexEngine/src/main/java/su/nexmedia/engine/api/menu/item/ItemOptions.java +++ b/NexEngine/src/main/java/su/nexmedia/engine/api/menu/item/ItemOptions.java @@ -89,4 +89,15 @@ public ItemOptions setDisplayModifier(@Nullable BiConsumer displayModifier) { + if (this.displayModifier == null) { + this.displayModifier = displayModifier; + } + else { + this.displayModifier = this.displayModifier.andThen(displayModifier); + } + return this; + } } diff --git a/NexEngine/src/main/java/su/nexmedia/engine/api/placeholder/PlaceholderMap.java b/NexEngine/src/main/java/su/nexmedia/engine/api/placeholder/PlaceholderMap.java index 6a226f3..6913289 100644 --- a/NexEngine/src/main/java/su/nexmedia/engine/api/placeholder/PlaceholderMap.java +++ b/NexEngine/src/main/java/su/nexmedia/engine/api/placeholder/PlaceholderMap.java @@ -26,6 +26,12 @@ public List>> getKeys() { return keys; } + @NotNull + public PlaceholderMap add(@NotNull PlaceholderMap other) { + this.getKeys().addAll(other.getKeys()); + return this; + } + @NotNull public PlaceholderMap add(@NotNull String key, @NotNull String replacer) { this.add(key, () -> replacer); diff --git a/NexEngine/src/main/java/su/nexmedia/engine/command/CommandRegister.java b/NexEngine/src/main/java/su/nexmedia/engine/command/CommandRegister.java index 98763e7..4406fde 100644 --- a/NexEngine/src/main/java/su/nexmedia/engine/command/CommandRegister.java +++ b/NexEngine/src/main/java/su/nexmedia/engine/command/CommandRegister.java @@ -33,7 +33,9 @@ public static void register(@NotNull Plugin plugin, @NotNull GeneralCommand c CommandRegister register = new CommandRegister(plugin, command, command, command.getAliases(), command.getDescription(), command.getUsage()); register.setPermission(command.getPermission()); - getCommandMap().register(plugin.getDescription().getName(), register); + if (getCommandMap().register(plugin.getDescription().getName(), register)) { + command.setFallback(register); + } } public static void syncCommands() { diff --git a/NexEngine/src/main/java/su/nexmedia/engine/utils/PlayerUtil.java b/NexEngine/src/main/java/su/nexmedia/engine/utils/PlayerUtil.java index 889ef3a..bc46795 100644 --- a/NexEngine/src/main/java/su/nexmedia/engine/utils/PlayerUtil.java +++ b/NexEngine/src/main/java/su/nexmedia/engine/utils/PlayerUtil.java @@ -4,7 +4,6 @@ import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.World; -import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; @@ -22,18 +21,20 @@ public static boolean isBedrockPlayer(@NotNull Player player) { return Hooks.hasFloodgate() && FloodgateApi.getInstance().isFloodgatePlayer(player.getUniqueId()); } - public static void dispatchCommand(@NotNull Player player, @NotNull String command) { - CommandSender sender = player; - if (command.startsWith("[CONSOLE]")) { - command = command.replace("[CONSOLE]", ""); - sender = Bukkit.getConsoleSender(); + public static void dispatchCommands(@NotNull Player player, @NotNull String... commands) { + for (String command : commands) { + dispatchCommand(player, command); } + } + + public static void dispatchCommand(@NotNull Player player, @NotNull String command) { + command = command.replace("[CONSOLE]", ""); command = command.trim().replace("%player%", player.getName()); command = Placeholders.Player.replacer(player).apply(command); if (Hooks.hasPlaceholderAPI()) { command = PlaceholderAPI.setPlaceholders(player, command); } - Bukkit.dispatchCommand(sender, command); + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command); } public static boolean hasEmptyInventory(@NotNull Player player) { diff --git a/NexEngine/src/main/java/su/nexmedia/engine/utils/TriFunction.java b/NexEngine/src/main/java/su/nexmedia/engine/utils/TriFunction.java new file mode 100644 index 0000000..51450ee --- /dev/null +++ b/NexEngine/src/main/java/su/nexmedia/engine/utils/TriFunction.java @@ -0,0 +1,14 @@ +package su.nexmedia.engine.utils; + +import java.util.Objects; +import java.util.function.Function; + +public interface TriFunction { + + R apply(T t, U u, V v); + + default TriFunction andThen(Function after) { + Objects.requireNonNull(after); + return (T t, U u, V v) -> after.apply(apply(t, u, v)); + } +} diff --git a/NexEngine/src/main/java/su/nexmedia/engine/utils/random/Rnd.java b/NexEngine/src/main/java/su/nexmedia/engine/utils/random/Rnd.java index 9688a3b..ababbc0 100644 --- a/NexEngine/src/main/java/su/nexmedia/engine/utils/random/Rnd.java +++ b/NexEngine/src/main/java/su/nexmedia/engine/utils/random/Rnd.java @@ -46,12 +46,14 @@ public static int get(int[] list) { return list[get(list.length)]; } - @Nullable + @NotNull public static E get(@NotNull List list) { - return list.isEmpty() ? null : list.get(get(list.size())); + if (list.isEmpty()) throw new NoSuchElementException("Empty list provided!"); + + return list.get(get(list.size())); } - @Nullable + @NotNull public static E get(@NotNull Set list) { return get(new ArrayList<>(list)); }