diff --git a/README.md b/README.md
index c3d3058..8cfef9c 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,8 @@ are commonly exploited on online servers.
- **Get Support / Contact Us**
- Please join the [ArcanePlugins Discord](https://discord.gg/arcaneplugins-752310043214479462) and use the `#other-lokka30-plugins` channel.
+ Please join the [ArcanePlugins Discord](https://discord.gg/arcaneplugins-752310043214479462) and use
+ the `#other-lokka30-plugins` channel.
Alternatively, [please message lokka30](https://www.spigotmc.org/conversations/add?to=lokka30) on SpigotMC.
@@ -28,7 +29,8 @@ are commonly exploited on online servers.
- **Command Blocking**
- Featuring a comprehensive command blocker, supporting blacklist/whitelisting, regex, powerful custom command rule chains, colon syntax blocking (`/plugin:command`), and more.
+ Featuring a comprehensive command blocker, supporting blacklist/whitelisting, regex, powerful custom command rule
+ chains, colon syntax blocking (`/plugin:command`), and more.
The default configuration blocks common commands used by players to check installed plugins and versions.
@@ -38,17 +40,21 @@ are commonly exploited on online servers.
- **Unit Testing**
- Standard component logic, such as the Command Blocking logic, is unit-tested to ensure it is working correctly before any version can be shipped out.
+ Standard component logic, such as the Command Blocking logic, is unit-tested to ensure it is working correctly before
+ any version can be shipped out.
- **Simple & Reliable**
- BlackWidow is built to be robust and lightweight, and doesn't mash half-baked features together to seem appealing (..only to break next update).
+ BlackWidow is built to be robust and lightweight, and doesn't mash half-baked features together to seem appealing (
+ ..only to break next update).
- **Plenty more to come!**
- There are a [variety of other features](https://github.com/orgs/ArcanePlugins/projects/5) planned, some major, such as command spying. It has the goal of being a pretty comprehensive security suite.
+ There are a [variety of other features](https://github.com/orgs/ArcanePlugins/projects/5) planned, some major, such as
+ command spying. It has the goal of being a pretty comprehensive security suite.
- However, we currently have no plans for BlackWidow to become an 'anticheat' plugin in the usual sense, which seems to be fulfilled by existing solutions well enough.
+ However, we currently have no plans for BlackWidow to become an 'anticheat' plugin in the usual sense, which seems to
+ be fulfilled by existing solutions well enough.
Feel free to see a variety of screenshots below:
@@ -83,7 +89,8 @@ Feel free to see a variety of screenshots below:
Firstly, make sure your software setup is compatible with BlackWidow.
-Please reference the [Requirements](https://github.com/ArcanePlugins/BlackWidow/wiki/Requirements) page for the most up-to-date and descriptive information on the requirements of running BlackWidow.
+Please reference the [Requirements](https://github.com/ArcanePlugins/BlackWidow/wiki/Requirements) page for the most
+up-to-date and descriptive information on the requirements of running BlackWidow.
The best-case scenario to run BlackWidow is:
@@ -95,11 +102,15 @@ Please be advised:
> We are considering adding future support for Velocity, BungeeCord, and Minestom. Let us know if you're interested!
-> Derivatives of Spigot/Paper, such as Purpur or Pufferfish may work fine, but we don't support these setups. That being said, still give it a shot and see if everything works. :)
+> Derivatives of Spigot/Paper, such as Purpur or Pufferfish may work fine, but we don't support these setups. That being
+> said, still give it a shot and see if everything works. :)
-> Please note that we are not interested in backporting BlackWidow to older versions of Minecraft/Java/etc. Please update your software, or feel free to fork BlackWidow and backport it.
+> Please note that we are not interested in backporting BlackWidow to older versions of Minecraft/Java/etc. Please
+> update your software, or feel free to fork BlackWidow and backport it.
-> **We do NOT recommend** using any server software like Magma, Mohist, and Arclight which *try* to make Forge mods work with Bukkit plugins. Bukkit was *never* designed to work with Forge/Fabric/etc mods. Trying to mix the two often causes lots of unusual issues which burden server owners and plugin maintainers.
+> **We do NOT recommend** using any server software like Magma, Mohist, and Arclight which *try* to make Forge mods work
+> with Bukkit plugins. Bukkit was *never* designed to work with Forge/Fabric/etc mods. Trying to mix the two often causes
+> lots of unusual issues which burden server owners and plugin maintainers.
## Projects Used
@@ -128,14 +139,14 @@ Thanks to all the other projects used, such as SpigotMC, IntelliJ, etc.
Copyright (C) 2024 lokka30 ([email](mailto:lachy@lachy.space))
> This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
+> it under the terms of the GNU General Public License as published by
+> the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
>
> This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+> but WITHOUT ANY WARRANTY; without even the implied warranty of
+> MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+> GNU General Public License for more details.
You should have [received a copy](LICENSE.md) of the GNU General Public License
-along with this program. If not, see .
+along with this program. If not, see .
diff --git a/blackwidowlib/pom.xml b/blackwidowlib/pom.xml
index 6c5eebf..e64b3d7 100644
--- a/blackwidowlib/pom.xml
+++ b/blackwidowlib/pom.xml
@@ -65,6 +65,13 @@
test
+
+ org.jetbrains
+ annotations
+ 26.0.1
+ provided
+
+
diff --git a/blackwidowlib/src/main/java/io/github/arcaneplugins/blackwidow/lib/cmdblocking/Chain.java b/blackwidowlib/src/main/java/io/github/arcaneplugins/blackwidow/lib/cmdblocking/Chain.java
index a90de37..9035c83 100644
--- a/blackwidowlib/src/main/java/io/github/arcaneplugins/blackwidow/lib/cmdblocking/Chain.java
+++ b/blackwidowlib/src/main/java/io/github/arcaneplugins/blackwidow/lib/cmdblocking/Chain.java
@@ -64,12 +64,12 @@ public class Chain {
* @since 1.0.0
*/
public Chain(
- final String id,
- final boolean enabled,
- final Policy policy,
- final Collection rules,
- final boolean isRegex,
- final Collection causeFilters
+ final String id,
+ final boolean enabled,
+ final Policy policy,
+ final Collection rules,
+ final boolean isRegex,
+ final Collection causeFilters
) {
this.id = Objects.requireNonNull(id, "id");
this.enabled = enabled;
@@ -86,12 +86,12 @@ public Chain(
if (!isRegex()) {
for (final String rule : rules()) {
- if(rule.startsWith("/")) {
+ if (rule.startsWith("/")) {
continue;
}
throw new IllegalArgumentException("Rule string='" + rule + "' in chain id='" + id() + "' does" +
- "not start with a slash (/); for a non-regex chain, all rules must start with a slash");
+ "not start with a slash (/); for a non-regex chain, all rules must start with a slash");
}
}
@@ -233,7 +233,7 @@ public final String id() {
* @since 1.0.0
*/
protected static String[] transformToArgs(
- final String str
+ final String str
) {
if (str.isEmpty()) {
throw new IllegalArgumentException("str parameter must not be empty");
@@ -244,10 +244,10 @@ protected static String[] transformToArgs(
}
return str
- .substring(1) // we don't want the starting slash.
- .toLowerCase(Locale.ROOT) // let's use lowercase for case insensitivity.
- .trim() // trim leading and trialing whitespace otherwise it can break String#split below.
- .split("\\s+"); // finally, split by whitespace via regex.
+ .substring(1) // we don't want the starting slash.
+ .toLowerCase(Locale.ROOT) // let's use lowercase for case insensitivity.
+ .trim() // trim leading and trialing whitespace otherwise it can break String#split below.
+ .split("\\s+"); // finally, split by whitespace via regex.
}
/**
@@ -262,11 +262,11 @@ protected static String[] transformToArgs(
* @since 1.0.0
*/
private MatchResult matchRulePattern(
- final String command,
- final String rule,
- final Pattern pattern,
- final EvalCause cause,
- final Consumer> debugger
+ final String command,
+ final String rule,
+ final Pattern pattern,
+ final EvalCause cause,
+ final Consumer> debugger
) {
Objects.requireNonNull(command, "command");
Objects.requireNonNull(rule, "rule");
@@ -298,9 +298,9 @@ private MatchResult matchRulePattern(
}
return new MatchResult(
- pattern.matcher(command).find(),
- rule,
- "regex pattern match find result"
+ pattern.matcher(command).find(),
+ rule,
+ "regex pattern match find result"
);
}
@@ -315,12 +315,12 @@ private MatchResult matchRulePattern(
* @since 1.0.0
*/
private MatchResult matchRuleArgs(
- final String cmd,
- final String[] cmdArgs,
- final String rule,
- final String[] ruleArgs,
- final EvalCause cause,
- final Consumer> debugger
+ final String cmd,
+ final String[] cmdArgs,
+ final String rule,
+ final String[] ruleArgs,
+ final EvalCause cause,
+ final Consumer> debugger
) {
Objects.requireNonNull(cmd, "cmd");
Objects.requireNonNull(cmdArgs, "cmdArgs");
@@ -339,10 +339,10 @@ private MatchResult matchRuleArgs(
final int minLen = Math.min(cmdArgs.length, ruleArgs.length);
debugger.accept(() -> "matchRule: Checking cmd='" + cmd + "', " +
- "rule='" + rule + "', " +
- "minLen='" + minLen + "', " +
- "cmdArgs='" + Arrays.toString(cmdArgs) + "' (len='" + cmdArgs.length + "'), " +
- "ruleArgs='" + Arrays.toString(ruleArgs) + "' (len='" + ruleArgs.length + "').");
+ "rule='" + rule + "', " +
+ "minLen='" + minLen + "', " +
+ "cmdArgs='" + Arrays.toString(cmdArgs) + "' (len='" + cmdArgs.length + "'), " +
+ "ruleArgs='" + Arrays.toString(ruleArgs) + "' (len='" + ruleArgs.length + "').");
if (ruleArgs.length == 0 && cmdArgs.length == 0) {
debugger.accept(() -> "matchRule: Yes, because rule args and cmd args are both empty arrays.");
@@ -351,9 +351,9 @@ private MatchResult matchRuleArgs(
if (ruleArgs.length > cmdArgs.length) {
debugger.accept(() -> "matchRule: No, because it's impossible for this command to match this rule, " +
- "because it doesn't have an equal or greater number args.");
+ "because it doesn't have an equal or greater number args.");
return new MatchResult(false, rule, "rule has more args than cmd, thus " +
- "impossible to match");
+ "impossible to match");
}
for (int i = 0; i < minLen; i++) {
@@ -367,7 +367,7 @@ private MatchResult matchRuleArgs(
if (!cmdArg.equals(ruleArg) && !ruleArg.equals("*")) {
debugger.accept(() -> "matchRule: No, since args don't match and ruleArg is not a wildcard");
return new MatchResult(false, rule, "arg at index '" + i + "' didn't match, and " +
- "ruleArg is not a wildcard");
+ "ruleArg is not a wildcard");
}
// if we're looking at the last arg of the rule, we've found a match.
@@ -394,9 +394,9 @@ private MatchResult matchRuleArgs(
* @since 1.0.0
*/
public final MatchResult matches(
- final String command,
- final EvalCause cause,
- final Consumer> debugger
+ final String command,
+ final EvalCause cause,
+ final Consumer> debugger
) {
Objects.requireNonNull(command, "command");
Objects.requireNonNull(debugger, "debugger");
@@ -422,15 +422,15 @@ public final MatchResult matches(
debugger.accept(() -> "matches: Checking rule '" + rule + "'.");
final MatchResult res = isRegex() ?
- matchRulePattern(command, rule, rulesRegexPatterns().get(rule), cause, debugger) :
- matchRuleArgs(command, transformToArgs(command), rule, rulesAsArgs().get(rule), cause, debugger);
+ matchRulePattern(command, rule, rulesRegexPatterns().get(rule), cause, debugger) :
+ matchRuleArgs(command, transformToArgs(command), rule, rulesAsArgs().get(rule), cause, debugger);
if (res.matched()) {
debugger.accept(() -> "matches: Matched!");
return new MatchResult(
- true,
- res.rule(),
- "in rule '" + rule + "'; " + res.description()
+ true,
+ res.rule(),
+ "in rule '" + rule + "'; " + res.description()
);
}
diff --git a/blackwidowlib/src/main/java/io/github/arcaneplugins/blackwidow/lib/cmdblocking/Evaluation.java b/blackwidowlib/src/main/java/io/github/arcaneplugins/blackwidow/lib/cmdblocking/Evaluation.java
index 96f9929..d4d17cc 100644
--- a/blackwidowlib/src/main/java/io/github/arcaneplugins/blackwidow/lib/cmdblocking/Evaluation.java
+++ b/blackwidowlib/src/main/java/io/github/arcaneplugins/blackwidow/lib/cmdblocking/Evaluation.java
@@ -53,11 +53,11 @@ public final class Evaluation {
* @since 1.0.0
*/
public Evaluation(
- final String command,
- final Policy policy,
- final Chain chain,
- final String rule,
- final String description
+ final String command,
+ final Policy policy,
+ final Chain chain,
+ final String rule,
+ final String description
) {
this.command = Objects.requireNonNull(command, "command");
this.policy = Objects.requireNonNull(policy, "policy");
diff --git a/blackwidowlib/src/main/java/io/github/arcaneplugins/blackwidow/lib/cmdblocking/Evaluator.java b/blackwidowlib/src/main/java/io/github/arcaneplugins/blackwidow/lib/cmdblocking/Evaluator.java
index feccac8..182da1e 100644
--- a/blackwidowlib/src/main/java/io/github/arcaneplugins/blackwidow/lib/cmdblocking/Evaluator.java
+++ b/blackwidowlib/src/main/java/io/github/arcaneplugins/blackwidow/lib/cmdblocking/Evaluator.java
@@ -29,13 +29,13 @@ public class Evaluator {
public static final AtomicBoolean SUPPRESS_EXCEPTION_MESSAGES = new AtomicBoolean(false);
public static Evaluation evaluate(
- final String cmd,
- final Collection extends Chain> chains,
- final Policy defaultPolicy,
- final boolean denyColonInFirstArg,
- final EvalCause cause,
- final Consumer> debugLogger,
- final Consumer> warningLogger
+ final String cmd,
+ final Collection extends Chain> chains,
+ final Policy defaultPolicy,
+ final boolean denyColonInFirstArg,
+ final EvalCause cause,
+ final Consumer> debugLogger,
+ final Consumer> warningLogger
) {
try {
Objects.requireNonNull(cmd, "cmd");
@@ -57,11 +57,11 @@ public static Evaluation evaluate(
final MatchResult res = chain.matches(cmd, cause, debugLogger);
if (res.matched()) {
return new Evaluation(
- cmd,
- chain.policy(),
- chain,
- res.rule(),
- "in chain #" + i + " (id='" + chain.id() + "'; " + res.description()
+ cmd,
+ chain.policy(),
+ chain,
+ res.rule(),
+ "in chain #" + i + " (id='" + chain.id() + "'; " + res.description()
);
}
i++;
@@ -69,33 +69,33 @@ public static Evaluation evaluate(
if (denyColonInFirstArg && Chain.transformToArgs(cmd)[0].contains(":")) {
return new Evaluation(cmd, Policy.DENY, null, null, "colon found in first arg")
- .withDueToColonInFirstArg(true);
+ .withDueToColonInFirstArg(true);
}
} catch (Exception ex) {
if (!SUPPRESS_EXCEPTION_MESSAGES.get()) {
warningLogger.accept(() ->
- "An exception was caught whilst evaluating cmd '" + cmd + "': '" + ex.getClass().getSimpleName() +
- "'. For best security practice, this cmd will be forcefully denied due to the error. " +
- "Message: '" + ex.getMessage() + "'; Stack trace:\n"
+ "An exception was caught whilst evaluating cmd '" + cmd + "': '" + ex.getClass().getSimpleName() +
+ "'. For best security practice, this cmd will be forcefully denied due to the error. " +
+ "Message: '" + ex.getMessage() + "'; Stack trace:\n"
);
//noinspection CallToPrintStackTrace
ex.printStackTrace();
}
return new Evaluation(
- cmd == null ? "/??? NULL COMMAND ???" : cmd,
- Policy.DENY,
- null,
- null,
- "exception caught, denying for security"
+ cmd == null ? "/??? NULL COMMAND ???" : cmd,
+ Policy.DENY,
+ null,
+ null,
+ "exception caught, denying for security"
).withDueToException(true);
}
return new Evaluation(
- cmd,
- defaultPolicy,
- null,
- null,
- "default policy, no chains matched"
+ cmd,
+ defaultPolicy,
+ null,
+ null,
+ "default policy, no chains matched"
).withDueToDefaultPolicy(true);
}
}
diff --git a/blackwidowlib/src/main/java/io/github/arcaneplugins/blackwidow/lib/cmdblocking/MatchResult.java b/blackwidowlib/src/main/java/io/github/arcaneplugins/blackwidow/lib/cmdblocking/MatchResult.java
index 8061e25..ae9dc73 100644
--- a/blackwidowlib/src/main/java/io/github/arcaneplugins/blackwidow/lib/cmdblocking/MatchResult.java
+++ b/blackwidowlib/src/main/java/io/github/arcaneplugins/blackwidow/lib/cmdblocking/MatchResult.java
@@ -46,9 +46,9 @@ public final class MatchResult {
* @since 1.0.0
*/
public MatchResult(
- final boolean matched,
- final String rule,
- final String description
+ final boolean matched,
+ final String rule,
+ final String description
) {
this.matched = matched;
this.rule = rule;
diff --git a/blackwidowlib/src/main/java/io/github/arcaneplugins/blackwidow/lib/cmdblocking/UpdateChecker.java b/blackwidowlib/src/main/java/io/github/arcaneplugins/blackwidow/lib/cmdblocking/UpdateChecker.java
new file mode 100644
index 0000000..5d0b84c
--- /dev/null
+++ b/blackwidowlib/src/main/java/io/github/arcaneplugins/blackwidow/lib/cmdblocking/UpdateChecker.java
@@ -0,0 +1,24 @@
+package io.github.arcaneplugins.blackwidow.lib.cmdblocking;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Scanner;
+import java.util.function.Consumer;
+
+public class UpdateChecker {
+ public static void getLatestVersion(final String resourceName, final Consumer consumer)
+ throws IOException, URISyntaxException {
+ try (InputStream inputStream = new URI(
+ "https://hangar.papermc.io/api/v1/projects/" +
+ resourceName + "/latest?channel=Release")
+ .toURL().openStream()){
+
+ final Scanner scanner = new Scanner(inputStream);
+ if (scanner.hasNext()){
+ consumer.accept(scanner.next());
+ }
+ }
+ }
+}
diff --git a/blackwidowlib/src/test/java/io/github/arcaneplugins/blackwidow/lib/cmdblocking/TestCmdEvaluation.java b/blackwidowlib/src/test/java/io/github/arcaneplugins/blackwidow/lib/cmdblocking/TestCmdEvaluation.java
index d9ecd99..4cbdf3a 100644
--- a/blackwidowlib/src/test/java/io/github/arcaneplugins/blackwidow/lib/cmdblocking/TestCmdEvaluation.java
+++ b/blackwidowlib/src/test/java/io/github/arcaneplugins/blackwidow/lib/cmdblocking/TestCmdEvaluation.java
@@ -34,66 +34,66 @@ public final class TestCmdEvaluation {
// Various 'plugin checking' commands
private static final String[] TEST_PLUGIN_CMDS = {
- "/plugins", "/pl", "/version", "/ver", "/icanhasbukkit",
- "/about", "/?", "/help", "/ehelp", "/paper", "/spigot"
+ "/plugins", "/pl", "/version", "/ver", "/icanhasbukkit",
+ "/about", "/?", "/help", "/ehelp", "/paper", "/spigot"
};
// Various programatically defined chains of rules, some regex ones provided at the bottom.
// Chains should NOT contain 'donotuseinchains', doing so will make some tests fail (by design).
private static final Collection TEST_CHAINS = Arrays.asList(
- new Chain("0", true, Policy.DENY, Arrays.asList("/cd reload *", "/"), false, EvalCause.setValues()),
- new Chain("1", true, Policy.ALLOW, Collections.singletonList("/cd reload"), false, EvalCause.setValues()),
- new Chain("2", true, Policy.DENY, Collections.singletonList("/cd"), false, EvalCause.setValues()),
- new Chain("3", true, Policy.DENY, Arrays.asList(TEST_PLUGIN_CMDS), false, EvalCause.setValues()),
- new Chain("4", true, Policy.ALLOW, Collections.singletonList("/es version"), false, EvalCause.setValues()),
- new Chain("5", true, Policy.DENY, Arrays.asList("/es give", "/es enchant"), false, EvalCause.setValues()),
- new Chain("6", true, Policy.ALLOW, Collections.singletonList("^(/heywhats(up)?(?:$|\\W)cool(beans)?(?:$|\\W).*)"), true, EvalCause.setValues()),
- new Chain("7", true, Policy.DENY, Collections.singletonList("^(/heywhats(up)?(?:$|\\W).*)"), true, EvalCause.setValues()),
- new Chain("8", false, Policy.DENY, Collections.singletonList("/thisshouldnotbedenied"), false, EvalCause.setValues()),
- new Chain("9", true, Policy.DENY, Collections.singletonList("/blocksuggestionsonly"), false, EnumSet.of(EvalCause.CMD_SUGGESTION))
+ new Chain("0", true, Policy.DENY, Arrays.asList("/cd reload *", "/"), false, EvalCause.setValues()),
+ new Chain("1", true, Policy.ALLOW, Collections.singletonList("/cd reload"), false, EvalCause.setValues()),
+ new Chain("2", true, Policy.DENY, Collections.singletonList("/cd"), false, EvalCause.setValues()),
+ new Chain("3", true, Policy.DENY, Arrays.asList(TEST_PLUGIN_CMDS), false, EvalCause.setValues()),
+ new Chain("4", true, Policy.ALLOW, Collections.singletonList("/es version"), false, EvalCause.setValues()),
+ new Chain("5", true, Policy.DENY, Arrays.asList("/es give", "/es enchant"), false, EvalCause.setValues()),
+ new Chain("6", true, Policy.ALLOW, Collections.singletonList("^(/heywhats(up)?(?:$|\\W)cool(beans)?(?:$|\\W).*)"), true, EvalCause.setValues()),
+ new Chain("7", true, Policy.DENY, Collections.singletonList("^(/heywhats(up)?(?:$|\\W).*)"), true, EvalCause.setValues()),
+ new Chain("8", false, Policy.DENY, Collections.singletonList("/thisshouldnotbedenied"), false, EvalCause.setValues()),
+ new Chain("9", true, Policy.DENY, Collections.singletonList("/blocksuggestionsonly"), false, EnumSet.of(EvalCause.CMD_SUGGESTION))
);
// Commands to be tested which are expected to be evaluated with a DENY policy.
public static final String[] TEST_CMDS_EXPECTING_DENY = {
- "/cd abc", "/cd reloada", "/cd reloa", "/cd reload abc",
- "/plugins", "/pl", "/version", "/ver", "/icanhasbukkit",
- "/about", "/?", "/help", "/ehelp", "/paper", "/spigot",
- "/es give", "/es enchant", "/cd", "/", "/:", "/hello:how",
- "/the:quick brown fox", "/bukkit:help",
- // regex:
- "/heywhats",
- "/heywhats coolio",
- "/heywhats verycool",
- "/heywhatsup",
- "/heywhatsup coolio",
- "/heywhatsup verycool",
+ "/cd abc", "/cd reloada", "/cd reloa", "/cd reload abc",
+ "/plugins", "/pl", "/version", "/ver", "/icanhasbukkit",
+ "/about", "/?", "/help", "/ehelp", "/paper", "/spigot",
+ "/es give", "/es enchant", "/cd", "/", "/:", "/hello:how",
+ "/the:quick brown fox", "/bukkit:help",
+ // regex:
+ "/heywhats",
+ "/heywhats coolio",
+ "/heywhats verycool",
+ "/heywhatsup",
+ "/heywhatsup coolio",
+ "/heywhatsup verycool",
};
// Commands to be tested which are expected to be evaluated with an ALLOW policy.
public static final String[] TEST_CMDS_EXPECTING_ALLOW = {
- "/cd reload", "/CD RELOAD", "//", "/es", "/es version", "/abcdefg", "/thisshouldnotbedenied",
- // regex:
- "/heywhats cool",
- "/heywhats coolbeans",
- "/heywhatsup cool",
- "/heywhatsup coolbeans",
- "/heywhatsup cool beans",
+ "/cd reload", "/CD RELOAD", "//", "/es", "/es version", "/abcdefg", "/thisshouldnotbedenied",
+ // regex:
+ "/heywhats cool",
+ "/heywhats coolbeans",
+ "/heywhatsup cool",
+ "/heywhatsup coolbeans",
+ "/heywhatsup cool beans",
};
// Commands to be tested which contains colons.
// 'donotuseinchains' term is used to make it clear PLEASE DO NOT USE THIS TERM IN ANY CHAINS or it can mess
// up the tests.
public static final String[] TEST_CMDS_WITH_COLONS = {
- "/donotuseinchains:donotuseinchains",
- "/donotuseinchains:donotuseinchains donotuseinchains",
+ "/donotuseinchains:donotuseinchains",
+ "/donotuseinchains:donotuseinchains donotuseinchains",
};
// Commands to be tested which do NOT contain colons.
// 'donotuseinchains' term is used to make it clear PLEASE DO NOT USE THIS TERM IN ANY CHAINS or it can mess
// up the tests.
public static final String[] TEST_CMDS_WITHOUT_COLONS = {
- "/donotuseinchains",
- "/donotuseinchains donotuseinchains",
+ "/donotuseinchains",
+ "/donotuseinchains donotuseinchains",
};
// Default policy to be used during these tests. ALLOW here represents a whitelist which is the usual setup.
@@ -114,17 +114,17 @@ public final class TestCmdEvaluation {
* @return {@link Evaluation Evaluation} made with the provided parameters.
*/
private static Evaluation testEvaluation(
- final String cmd,
- final boolean denyColonInFirstArg
+ final String cmd,
+ final boolean denyColonInFirstArg
) {
return Evaluator.evaluate(
- cmd,
- TEST_CHAINS,
- TEST_DEFAULT_POLICY,
- denyColonInFirstArg,
- EvalCause.CMD_EXECUTION,
- debugLogger,
- warningLogger
+ cmd,
+ TEST_CHAINS,
+ TEST_DEFAULT_POLICY,
+ denyColonInFirstArg,
+ EvalCause.CMD_EXECUTION,
+ debugLogger,
+ warningLogger
);
}
@@ -137,14 +137,14 @@ private static Evaluation testEvaluation(
@Test
public void testChainsMustStartWithSlash() {
for (final Chain chain : TEST_CHAINS) {
- if(chain.isRegex()) {
+ if (chain.isRegex()) {
continue;
}
- for(final String rule : chain.rules()) {
+ for (final String rule : chain.rules()) {
Assertions.assertTrue(
- rule.startsWith("/"),
- "Non-regex chain rules must start with a slash, failed on rule='" + rule + "'"
+ rule.startsWith("/"),
+ "Non-regex chain rules must start with a slash, failed on rule='" + rule + "'"
);
}
}
@@ -162,7 +162,7 @@ public void testRulesExpectingDeny() {
final Evaluation eval = testEvaluation(cmd, true);
Assertions.assertFalse(eval.dueToException(), "Exception not expected here");
Assertions.assertEquals(eval.policy(), Policy.DENY, "Wrong policy evaluated for cmd='" +
- cmd + "'; description='" + eval.description() + "'");
+ cmd + "'; description='" + eval.description() + "'");
}
}
@@ -178,7 +178,7 @@ public void testRulesExpectingAllow() {
final Evaluation eval = testEvaluation(cmd, true);
Assertions.assertFalse(eval.dueToException(), "Exception not expected here");
Assertions.assertEquals(eval.policy(), Policy.ALLOW, "Wrong policy evaluated for cmd='" +
- cmd + "'; description='" + eval.description() + "'");
+ cmd + "'; description='" + eval.description() + "'");
}
}
@@ -198,8 +198,8 @@ public void testColonBlocking() {
Assertions.assertFalse(eval.dueToException(), "Exception not expected here");
Assertions.assertTrue(eval.dueToColonInFirstArg(), "Colon in first arg expected to be cause");
Assertions.assertEquals(eval.policy(), Policy.DENY,
- "Wrong policy evaluated for cmd='" + cmd + "'; description='" +
- eval.description() + "'");
+ "Wrong policy evaluated for cmd='" + cmd + "'; description='" +
+ eval.description() + "'");
}
{
@@ -208,8 +208,8 @@ public void testColonBlocking() {
Assertions.assertFalse(eval.dueToException(), "Exception not expected here");
Assertions.assertFalse(eval.dueToColonInFirstArg(), "Colon in first arg unexpected to be cause");
Assertions.assertEquals(eval.policy(), Policy.ALLOW,
- "Wrong policy evaluated for cmd='" + cmd + "'; description='" +
- eval.description() + "'");
+ "Wrong policy evaluated for cmd='" + cmd + "'; description='" +
+ eval.description() + "'");
}
}
@@ -220,8 +220,8 @@ public void testColonBlocking() {
Assertions.assertFalse(eval.dueToException(), "Exception not expected here");
Assertions.assertFalse(eval.dueToColonInFirstArg(), "Colon in first arg unexpected to be cause");
Assertions.assertEquals(eval.policy(), Policy.ALLOW,
- "Wrong policy evaluated for cmd='" + cmd + "'; description='" +
- eval.description() + "'");
+ "Wrong policy evaluated for cmd='" + cmd + "'; description='" +
+ eval.description() + "'");
}
{
@@ -229,8 +229,8 @@ public void testColonBlocking() {
Assertions.assertFalse(eval.dueToException(), "Exception not expected here");
Assertions.assertFalse(eval.dueToColonInFirstArg(), "Colon in first arg unexpected to be cause");
Assertions.assertEquals(eval.policy(), Policy.ALLOW,
- "Wrong policy evaluated for cmd='" + cmd + "'; description='" +
- eval.description() + "'");
+ "Wrong policy evaluated for cmd='" + cmd + "'; description='" +
+ eval.description() + "'");
}
}
}
@@ -269,13 +269,13 @@ public void testPluginCheckingRegex() {
@Test
public void testDenyDefaultPolicy() {
final Evaluation eval = Evaluator.evaluate(
- "/donotuseinchains",
- TEST_CHAINS,
- Policy.DENY,
- true,
- EvalCause.CMD_EXECUTION,
- debugLogger,
- warningLogger
+ "/donotuseinchains",
+ TEST_CHAINS,
+ Policy.DENY,
+ true,
+ EvalCause.CMD_EXECUTION,
+ debugLogger,
+ warningLogger
);
Assertions.assertFalse(eval.dueToException(), "Exception not expected here");
@@ -317,13 +317,13 @@ public void testEvalCauseFiltering() {
final String cmd = "/blocksuggestionsonly";
final Function eval = (cause) -> Evaluator.evaluate(
- cmd,
- TEST_CHAINS,
- TEST_DEFAULT_POLICY,
- true,
- cause,
- debugLogger,
- warningLogger
+ cmd,
+ TEST_CHAINS,
+ TEST_DEFAULT_POLICY,
+ true,
+ cause,
+ debugLogger,
+ warningLogger
);
final Evaluation evalExecution = eval.apply(EvalCause.CMD_EXECUTION);
diff --git a/blackwidowpluginbukkit/pom.xml b/blackwidowpluginbukkit/pom.xml
index 1733e65..b3d8b94 100644
--- a/blackwidowpluginbukkit/pom.xml
+++ b/blackwidowpluginbukkit/pom.xml
@@ -101,7 +101,8 @@
3.6.0
- package
+ package
+
shade
diff --git a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/BlackWidow.java b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/BlackWidow.java
index 67a6175..a1f9ec8 100644
--- a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/BlackWidow.java
+++ b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/BlackWidow.java
@@ -24,6 +24,7 @@
import io.github.arcaneplugins.blackwidow.plugin.bukkit.command.CommandManager;
import io.github.arcaneplugins.blackwidow.plugin.bukkit.component.cmdblocking.CmdBlocker;
import io.github.arcaneplugins.blackwidow.plugin.bukkit.listener.ListenerManager;
+import io.github.arcaneplugins.blackwidow.plugin.bukkit.logic.BukkitVersionChecker;
import io.github.arcaneplugins.blackwidow.plugin.bukkit.logic.LogicManager;
import io.github.arcaneplugins.blackwidow.plugin.bukkit.util.ClassUtil;
import io.github.arcaneplugins.blackwidow.plugin.bukkit.util.DebugCategory;
@@ -31,6 +32,7 @@
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import net.kyori.adventure.text.minimessage.MiniMessage;
import org.bukkit.plugin.java.JavaPlugin;
+import org.jetbrains.annotations.NotNull;
import java.util.EnumSet;
import java.util.List;
@@ -54,6 +56,7 @@ public final class BlackWidow extends JavaPlugin {
private final LogicManager logicManager = new LogicManager(this);
private final EnumSet debugCategories = EnumSet.noneOf(DebugCategory.class);
private final MiniMessage miniMessage = MiniMessage.miniMessage();
+ private final BukkitVersionChecker bukkitVersionChecker = new BukkitVersionChecker(this);
private boolean usingPaper = false;
private BukkitAudiences adventure = null;
@@ -97,6 +100,7 @@ public void onEnable() {
loadComponents();
listenerManager().load();
commandManager().load();
+ bukkitVersionChecker.load(true);
} catch (Exception ex) {
ExceptionUtil.logException(this, ex, "An error occurred whilst enabling BlackWidow.");
return;
@@ -149,6 +153,7 @@ public void softReload() {
loadConfigs();
logicManager().load();
loadComponents();
+ bukkitVersionChecker.load(false);
} catch (Exception ex) {
ExceptionUtil.logException(this, ex, "An error occurred whilst performing a soft-reload.");
return;
@@ -208,8 +213,8 @@ private void loadComponents() {
* @since 1.0.0
*/
public void debugLog(
- final DebugCategory cat,
- final Supplier strSupp
+ final DebugCategory cat,
+ final Supplier strSupp
) {
if (!enabledDebugCategories().contains(cat)) {
return;
@@ -318,4 +323,9 @@ public BukkitAudiences adventure() {
public MiniMessage miniMessage() {
return Objects.requireNonNull(miniMessage, "miniMessage");
}
+
+ @NotNull
+ public BukkitVersionChecker bukkitVersionChecker() {
+ return Objects.requireNonNull(bukkitVersionChecker, "bukkitVersionChecker");
+ }
}
diff --git a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/cfg/YamlCfg.java b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/cfg/YamlCfg.java
index 53cd711..e18ca48 100644
--- a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/cfg/YamlCfg.java
+++ b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/cfg/YamlCfg.java
@@ -40,11 +40,11 @@ public abstract class YamlCfg {
private CommentedConfigurationNode root;
public YamlCfg(
- final BlackWidow plugin,
- final String filePathStr,
- final String fileName,
- final String description,
- final int latestFileVersion
+ final BlackWidow plugin,
+ final String filePathStr,
+ final String fileName,
+ final String description,
+ final int latestFileVersion
) {
this.plugin = Objects.requireNonNull(plugin, "plugin");
this.filePathStr = Objects.requireNonNull(filePathStr, "filePathStr");
@@ -67,10 +67,10 @@ public YamlCfg(
}
this.loader = YamlConfigurationLoader.builder()
- .path(filePath())
- .indent(2)
- .nodeStyle(NodeStyle.BLOCK)
- .build();
+ .path(filePath())
+ .indent(2)
+ .nodeStyle(NodeStyle.BLOCK)
+ .build();
}
public final void load() {
@@ -83,22 +83,30 @@ public final void load() {
final int latestVer = latestFileVersion();
if (installedVer <= 0) {
throw new IllegalArgumentException("Config '" + fileName() + "' has an installed file version below " +
- "or equal to 0, indicating it has almost certainly been manually tampered with. Please address " +
- "this issue ASAP, as a manually-adjusted file version can cause instability.");
+ "or equal to 0, indicating it has almost certainly been manually tampered with. Please address " +
+ "this issue ASAP, as a manually-adjusted file version can cause instability.");
}
if (installedVer < latestVer) {
+ int lastVersion = installedFileVersion();
plugin().getLogger().info("Config '" + fileName() + "' is outdated, automatically upgrading.");
while (installedVer < latestFileVersion()) {
plugin().getLogger().info("Upgrading '" + fileName() + "' from v" +
- installedVer + " to v" + (installedVer + 1) + ".");
+ installedVer + " to v" + (installedVer + 1) + ".");
upgradeFile();
write();
installedVer = installedFileVersion();
+ if (installedVer == lastVersion) {
+ // prevent potential endless loop
+ plugin().getLogger().warning("There was an error upgrading the file version, " +
+ "the version number was not incremented");
+ break;
+ }
+ lastVersion = installedVer;
}
} else if (installedVer > latestVer) {
plugin().getLogger().warning("Config '" + fileName() + "' apparently has version '" + installedVer +
- "' but the latest is '" + latestVer + "'. Was the file version manually tampered with, or used " +
- "on a newer version of the plugin? Please address ASAP as this may cause instability.");
+ "' but the latest is '" + latestVer + "'. Was the file version manually tampered with, or used " +
+ "on a newer version of the plugin? Please address ASAP as this may cause instability.");
}
// lastly, set 'context' metadata if not already present
@@ -109,8 +117,8 @@ public final void load() {
//noinspection deprecation,UnstableApiUsage
final String version = plugin().usePaperFeatures() ?
- plugin().getPluginMeta().getVersion() :
- plugin().getDescription().getVersion();
+ plugin().getPluginMeta().getVersion() :
+ plugin().getDescription().getVersion();
node.set(plugin().getName() + " " + version);
diff --git a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/cfg/settings/Settings.java b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/cfg/settings/Settings.java
index e11ebc0..800f65f 100644
--- a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/cfg/settings/Settings.java
+++ b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/cfg/settings/Settings.java
@@ -21,7 +21,9 @@
import io.github.arcaneplugins.blackwidow.plugin.bukkit.BlackWidow;
import io.github.arcaneplugins.blackwidow.plugin.bukkit.cfg.YamlCfg;
import io.github.arcaneplugins.blackwidow.plugin.bukkit.util.DebugCategory;
+import org.spongepowered.configurate.CommentedConfigurationNode;
import org.spongepowered.configurate.ConfigurateException;
+import org.spongepowered.configurate.serialize.SerializationException;
import java.util.Collections;
import java.util.Objects;
@@ -32,17 +34,17 @@ public final class Settings extends YamlCfg {
// REMEMBER TO UPDATE THE METHOD BELOW 'upgradeFile' IF THIS IS INCREMENTED.
// ALSO REMEMBER TO UPDATE THE FILE ITSELF - BOTH THE 'original' AND 'installed' VALUES SHOULD MATCH THIS.
// <<< !!! WARNING !!! NOTICE THIS MESSAGE !!! >>>
- private static final int LATEST_FILE_VERSION = 1;
+ private static final int LATEST_FILE_VERSION = 2;
public Settings(
- final BlackWidow plugin
+ final BlackWidow plugin
) {
super(
- plugin,
- "settings.yml",
- "settings.yml",
- "Settings",
- LATEST_FILE_VERSION
+ plugin,
+ "settings.yml",
+ "settings.yml",
+ "Settings",
+ LATEST_FILE_VERSION
);
}
@@ -57,12 +59,12 @@ protected void loadMore() {
try {
plugin().enabledDebugCategories().clear();
plugin().enabledDebugCategories().addAll(
- Objects.requireNonNullElse(
- root()
- .node("debug-categories")
- .getList(DebugCategory.class),
- Collections.emptySet()
- )
+ Objects.requireNonNullElse(
+ root()
+ .node("debug-categories")
+ .getList(DebugCategory.class),
+ Collections.emptySet()
+ )
);
} catch (final ConfigurateException ex) {
throw new RuntimeException(ex.getMessage(), ex);
@@ -81,10 +83,18 @@ public void upgradeFile() {
//noinspection SwitchStatementWithTooFewBranches
switch (installedVer) {
case 1 -> {
- // Do nothing.
+ final CommentedConfigurationNode updChkNode = root().node("update-checker");
+ try {
+ updChkNode.node("enabled").set(true);
+ updChkNode.node("run-on-startup").set(true);
+ updChkNode.node("repeat-timer-duration-mins").set(60);
+ updChkNode.node("log-updates").set(true);
+ updChkNode.node("notify-players-with-permission").set(true);
- //noinspection UnnecessaryBreak
- break;
+ root().node("do-not-touch", "version", "installed").set(2);
+ } catch (SerializationException e) {
+ plugin().getLogger().warning("");
+ }
}
default -> throw new IllegalArgumentException("No upgrade logic defined for file version v" + installedVer);
}
diff --git a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/cfg/translations/Translation.java b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/cfg/translations/Translation.java
index 1ec2ac7..af2ce83 100644
--- a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/cfg/translations/Translation.java
+++ b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/cfg/translations/Translation.java
@@ -34,41 +34,41 @@
public enum Translation {
COMMAND_BLACKWIDOW_RELOAD_STARTED(
- new String[]{"command", "blackwidow", "reload", "started"},
- true,
- List.of("%prefix%Reloading BlackWidow.")
+ new String[]{"command", "blackwidow", "reload", "started"},
+ true,
+ List.of("%prefix%Reloading BlackWidow.")
),
COMMAND_BLACKWIDOW_RELOAD_FAILED(
- new String[]{"command", "blackwidow", "reload", "failed"},
- true,
- List.of("%prefix%Reload failed! Please see your server console for more details.")
+ new String[]{"command", "blackwidow", "reload", "failed"},
+ true,
+ List.of("%prefix%Reload failed! Please see your server console for more details.")
),
COMMAND_BLACKWIDOW_RELOAD_COMPLETE(
- new String[]{"command", "blackwidow", "reload", "complete"},
- true,
- List.of("%prefix%Reload complete.")
+ new String[]{"command", "blackwidow", "reload", "complete"},
+ true,
+ List.of("%prefix%Reload complete.")
),
COMMAND_BLACKWIDOW_VERSION(
- new String[]{"command", "blackwidow", "version"},
- true,
- List.of("*---* BlackWidowA security solution for Minecraft.'>BlackWidow v%version% *---*A security solution for Minecraft.From ArcanePlugins by %authors%.")
+ new String[]{"command", "blackwidow", "version"},
+ true,
+ List.of("*---* BlackWidowA security solution for Minecraft.'>BlackWidow v%version% *---*A security solution for Minecraft.From ArcanePlugins by %authors%.")
),
PREFIX(
- new String[]{"prefix"},
- false,
- "BlackWidow" +
- "A security solution for Minecraft.'>BW: " +
- ""
+ new String[]{"prefix"},
+ false,
+ "BlackWidow" +
+ "A security solution for Minecraft.'>BW: " +
+ ""
),
LIST_DELIMITER(
- new String[]{"list-delimeter"},
- false,
- ", "
+ new String[]{"list-delimeter"},
+ false,
+ ", "
);
private final String[] nodePath;
@@ -76,9 +76,9 @@ public enum Translation {
private final Object defValue;
Translation(
- final String[] nodePath,
- final boolean isList,
- final Object defValue
+ final String[] nodePath,
+ final boolean isList,
+ final Object defValue
) {
this.nodePath = nodePath;
this.isList = isList;
@@ -98,7 +98,7 @@ public final Object defValue() {
}
public String strSingle(
- final BlackWidow plugin
+ final BlackWidow plugin
) {
if (isList()) {
throw new IllegalStateException("Translation is list type, but called `str` instead of `strList`");
@@ -108,9 +108,9 @@ public String strSingle(
}
public static String placeholerify(
- final BlackWidow plugin,
- final String msg,
- final Map> placeholders
+ final BlackWidow plugin,
+ final String msg,
+ final Map> placeholders
) {
// temp var to hold latest placeholderified version of `msg`
String formattedMsg = msg;
@@ -134,31 +134,31 @@ public static String placeholerify(
}
public static String joinSeparatedStrings(
- final BlackWidow plugin,
- final Collection strings
+ final BlackWidow plugin,
+ final Collection strings
) {
return String.join(
- LIST_DELIMITER.strSingle(plugin),
- strings
+ LIST_DELIMITER.strSingle(plugin),
+ strings
);
}
public static Component formatify(
- final BlackWidow plugin,
- final String msg,
- final Map> placeholders
+ final BlackWidow plugin,
+ final String msg,
+ final Map> placeholders
) {
return plugin.miniMessage().deserialize(
- placeholerify(
- plugin,
- msg,
- placeholders
- )
+ placeholerify(
+ plugin,
+ msg,
+ placeholders
+ )
);
}
public final List strList(
- final BlackWidow plugin
+ final BlackWidow plugin
) {
if (!isList()) {
throw new IllegalStateException("Translation is not list type, but called `strList` instead of `str`");
@@ -167,8 +167,8 @@ public final List strList(
try {
//noinspection unchecked
return Objects.requireNonNullElse(
- plugin.translations().root().node((Object[]) nodePath()).getList(String.class),
- (List) defValue()
+ plugin.translations().root().node((Object[]) nodePath()).getList(String.class),
+ (List) defValue()
);
} catch (final ConfigurateException ex) {
throw new RuntimeException(ex.getMessage(), ex);
@@ -176,9 +176,9 @@ public final List strList(
}
public final void sendTo(
- final BlackWidow plugin,
- final Audience audience,
- final Map> placeholders
+ final BlackWidow plugin,
+ final Audience audience,
+ final Map> placeholders
) {
Objects.requireNonNull(plugin, "plugin");
Objects.requireNonNull(audience, "audience");
@@ -193,9 +193,9 @@ public final void sendTo(
}
public final void sendTo(
- final BlackWidow plugin,
- final CommandSender sender,
- final Map> placeholders
+ final BlackWidow plugin,
+ final CommandSender sender,
+ final Map> placeholders
) {
Objects.requireNonNull(plugin, "plugin");
Objects.requireNonNull(sender, "sender");
@@ -204,9 +204,9 @@ public final void sendTo(
@SuppressWarnings("unused")
public final void sendTo(
- final BlackWidow plugin,
- final Player player,
- final Map> placeholders
+ final BlackWidow plugin,
+ final Player player,
+ final Map> placeholders
) {
Objects.requireNonNull(plugin, "plugin");
Objects.requireNonNull(player, "player");
diff --git a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/cfg/translations/Translations.java b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/cfg/translations/Translations.java
index 0fc961b..8ed63c4 100644
--- a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/cfg/translations/Translations.java
+++ b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/cfg/translations/Translations.java
@@ -36,14 +36,14 @@ public final class Translations extends YamlCfg {
* @since 1.0.0
*/
public Translations(
- final BlackWidow plugin
+ final BlackWidow plugin
) {
super(
- plugin,
- "translations.yml",
- "translations.yml",
- "Translations",
- LATEST_FILE_VERSION
+ plugin,
+ "translations.yml",
+ "translations.yml",
+ "Translations",
+ LATEST_FILE_VERSION
);
}
diff --git a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/command/CommandManager.java b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/command/CommandManager.java
index d45c5ab..6aaa740 100644
--- a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/command/CommandManager.java
+++ b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/command/CommandManager.java
@@ -29,7 +29,7 @@ public final class CommandManager {
private final BlackWidow plugin;
public CommandManager(
- final BlackWidow plugin
+ final BlackWidow plugin
) {
this.plugin = plugin;
}
@@ -37,10 +37,10 @@ public CommandManager(
public void init() {
plugin().getLogger().info("Initialising commands.");
CommandAPI.onLoad(
- new CommandAPIBukkitConfig(plugin())
- .verboseOutput(false)
- .silentLogs(true)
- .usePluginNamespace()
+ new CommandAPIBukkitConfig(plugin())
+ .verboseOutput(false)
+ .silentLogs(true)
+ .usePluginNamespace()
);
registerCommands();
}
@@ -59,10 +59,10 @@ public void disable() {
CommandAPI.unregister("blackwidow", true);
CommandAPI.onDisable();
CommandAPI.getRegisteredCommands()
- .stream()
- .map(RegisteredCommand::commandName)
- .iterator()
- .forEachRemaining(CommandAPI::unregister);
+ .stream()
+ .map(RegisteredCommand::commandName)
+ .iterator()
+ .forEachRemaining(CommandAPI::unregister);
}
private BlackWidow plugin() {
diff --git a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/command/blackwidow/BlackWidowCommand.java b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/command/blackwidow/BlackWidowCommand.java
index bcf818f..04703f2 100644
--- a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/command/blackwidow/BlackWidowCommand.java
+++ b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/command/blackwidow/BlackWidowCommand.java
@@ -30,7 +30,7 @@ public final class BlackWidowCommand extends CommandAPICommand {
private final BlackWidow plugin;
public BlackWidowCommand(
- final BlackWidow plugin
+ final BlackWidow plugin
) {
super("blackwidow");
this.plugin = plugin;
@@ -39,8 +39,8 @@ public BlackWidowCommand(
withShortDescription("Base command to view info of and manage the BlackWidow plugin.");
withFullDescription("Base command to view and manage the BlackWidow plugin.");
withSubcommands(
- new ReloadSubcommand(plugin()),
- new VersionSubcommand(plugin())
+ new ReloadSubcommand(plugin()),
+ new VersionSubcommand(plugin())
);
}
diff --git a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/command/blackwidow/subcommand/ReloadSubcommand.java b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/command/blackwidow/subcommand/ReloadSubcommand.java
index ed73d65..fd1ddc1 100644
--- a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/command/blackwidow/subcommand/ReloadSubcommand.java
+++ b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/command/blackwidow/subcommand/ReloadSubcommand.java
@@ -30,7 +30,7 @@ public final class ReloadSubcommand extends CommandAPICommand {
private final BlackWidow plugin;
public ReloadSubcommand(
- final BlackWidow plugin
+ final BlackWidow plugin
) {
super("reload");
this.plugin = plugin;
diff --git a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/command/blackwidow/subcommand/VersionSubcommand.java b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/command/blackwidow/subcommand/VersionSubcommand.java
index 4b494b8..359db6b 100644
--- a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/command/blackwidow/subcommand/VersionSubcommand.java
+++ b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/command/blackwidow/subcommand/VersionSubcommand.java
@@ -30,7 +30,7 @@ public final class VersionSubcommand extends CommandAPICommand {
private final BlackWidow plugin;
public VersionSubcommand(
- final BlackWidow plugin
+ final BlackWidow plugin
) {
super("version");
this.plugin = plugin;
@@ -41,13 +41,13 @@ public VersionSubcommand(
executes((sender, args) -> {
//noinspection deprecation
Translation.COMMAND_BLACKWIDOW_VERSION.sendTo(
- plugin(),
- sender,
- Map.of(
- "version", () -> plugin().getDescription().getVersion(),
- "authors", () -> Translation
- .joinSeparatedStrings(plugin(), plugin().getDescription().getAuthors())
- )
+ plugin(),
+ sender,
+ Map.of(
+ "version", () -> plugin().getDescription().getVersion(),
+ "authors", () -> Translation
+ .joinSeparatedStrings(plugin(), plugin().getDescription().getAuthors())
+ )
);
});
}
diff --git a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/component/cmdblocking/BukkitChain.java b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/component/cmdblocking/BukkitChain.java
index 9593186..81c14d0 100644
--- a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/component/cmdblocking/BukkitChain.java
+++ b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/component/cmdblocking/BukkitChain.java
@@ -52,15 +52,15 @@ public final class BukkitChain extends Chain {
* @since 1.0.0
*/
public BukkitChain(
- final BlackWidow plugin,
- final String id,
- final boolean enabled,
- final Policy policy,
- final Collection rules,
- final boolean isRegex,
- final Collection causeFilters,
- final Collection requirements,
- final Collection actions
+ final BlackWidow plugin,
+ final String id,
+ final boolean enabled,
+ final Policy policy,
+ final Collection rules,
+ final boolean isRegex,
+ final Collection causeFilters,
+ final Collection requirements,
+ final Collection actions
) {
super(id, enabled, policy, rules, isRegex, causeFilters);
this.plugin = Objects.requireNonNull(plugin, "plugin");
@@ -69,19 +69,19 @@ public BukkitChain(
}
public BukkitChain(
- final BlackWidow plugin,
- final CommentedConfigurationNode node
+ final BlackWidow plugin,
+ final CommentedConfigurationNode node
) {
this(
- Objects.requireNonNull(plugin, "plugin"),
- node.node("id").getString(),
- node.node("enabled").getBoolean(true),
- parsePolicyAtNode(node.node("policy")),
- parseStringListAtNode(node.node("rules")),
- node.node("regex").getBoolean(false),
- parseEvalCauseListAtNode(node.node("cause-filters")),
- plugin.logicManager().parseRequirementsInChildrenOfNode(node.node("requirements")),
- plugin.logicManager().parseActionsInChildrenOfNode(node.node("actions"))
+ Objects.requireNonNull(plugin, "plugin"),
+ node.node("id").getString(),
+ node.node("enabled").getBoolean(true),
+ parsePolicyAtNode(node.node("policy")),
+ parseStringListAtNode(node.node("rules")),
+ node.node("regex").getBoolean(false),
+ parseEvalCauseListAtNode(node.node("cause-filters")),
+ plugin.logicManager().parseRequirementsInChildrenOfNode(node.node("requirements")),
+ plugin.logicManager().parseActionsInChildrenOfNode(node.node("actions"))
);
}
@@ -91,7 +91,7 @@ private BlackWidow plugin() {
}
private static Policy parsePolicyAtNode(
- final CommentedConfigurationNode node
+ final CommentedConfigurationNode node
) {
try {
return node.get(Policy.class, Policy.DENY);
@@ -101,7 +101,7 @@ private static Policy parsePolicyAtNode(
}
private static List parseStringListAtNode(
- final CommentedConfigurationNode node
+ final CommentedConfigurationNode node
) {
try {
return node.getList(String.class);
@@ -119,7 +119,7 @@ public Collection actions() {
}
public static Collection parseEvalCauseListAtNode(
- final CommentedConfigurationNode node
+ final CommentedConfigurationNode node
) {
Objects.requireNonNull(node, "node");
diff --git a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/component/cmdblocking/CmdBlocker.java b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/component/cmdblocking/CmdBlocker.java
index de19aab..daef955 100644
--- a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/component/cmdblocking/CmdBlocker.java
+++ b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/component/cmdblocking/CmdBlocker.java
@@ -97,7 +97,7 @@ public Evaluation evalAndProcess(final Context context, final String cmd, final
final Player player = context.player(false);
if (player != null && player.isOp() && operatorsBypassCompletely()) {
return new Evaluation(cmd, Policy.ALLOW, null, null, "Operators configured to bypass command blocking")
- .withDueToOperatorsBypassCmdBlocking(true);
+ .withDueToOperatorsBypassCmdBlocking(true);
}
// copy chains into a new LinkedHashSet, remove chains not applicable to context.
diff --git a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/event/LoadActionsReadyEvent.java b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/event/LoadActionsReadyEvent.java
index d234c80..89fbc24 100644
--- a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/event/LoadActionsReadyEvent.java
+++ b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/event/LoadActionsReadyEvent.java
@@ -36,8 +36,8 @@ public final class LoadActionsReadyEvent extends Event {
private static final HandlerList HANDLERS = new HandlerList();
public LoadActionsReadyEvent(
- final BlackWidow plugin,
- final Map> actParsers
+ final BlackWidow plugin,
+ final Map> actParsers
) {
this.plugin = Objects.requireNonNull(plugin, "plugin");
this.actParsers = Objects.requireNonNull(actParsers, "actParsers");
diff --git a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/event/LoadRequirementsReadyEvent.java b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/event/LoadRequirementsReadyEvent.java
index 3cd5bf0..08ab31e 100644
--- a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/event/LoadRequirementsReadyEvent.java
+++ b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/event/LoadRequirementsReadyEvent.java
@@ -36,8 +36,8 @@ public final class LoadRequirementsReadyEvent extends Event {
private static final HandlerList HANDLERS = new HandlerList();
public LoadRequirementsReadyEvent(
- final BlackWidow plugin,
- final Map> reqParsers
+ final BlackWidow plugin,
+ final Map> reqParsers
) {
this.plugin = Objects.requireNonNull(plugin, "plugin");
this.reqParsers = Objects.requireNonNull(reqParsers, "reqParsers");
diff --git a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/listener/ListenerManager.java b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/listener/ListenerManager.java
index 9196c3c..d971019 100644
--- a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/listener/ListenerManager.java
+++ b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/listener/ListenerManager.java
@@ -21,11 +21,13 @@
import io.github.arcaneplugins.blackwidow.plugin.bukkit.BlackWidow;
import io.github.arcaneplugins.blackwidow.plugin.bukkit.listener.bukkit.PlayerCommandPreprocessListener;
import io.github.arcaneplugins.blackwidow.plugin.bukkit.listener.bukkit.PlayerCommandSendListener;
+import io.github.arcaneplugins.blackwidow.plugin.bukkit.listener.bukkit.PlayerJoinListener;
import io.github.arcaneplugins.blackwidow.plugin.bukkit.listener.paper.AsyncPlayerCommandSendListener;
import org.bukkit.event.Listener;
import java.util.Collection;
import java.util.LinkedHashSet;
+import java.util.List;
public final class ListenerManager {
@@ -33,20 +35,21 @@ public final class ListenerManager {
private final Collection listeners = new LinkedHashSet<>();
public ListenerManager(
- final BlackWidow plugin
+ final BlackWidow plugin
) {
this.plugin = plugin;
}
private void constructListeners() {
- listeners().add(
- new PlayerCommandPreprocessListener(plugin())
- );
+ listeners().addAll(List.of(
+ new PlayerCommandPreprocessListener(plugin()),
+ new PlayerJoinListener(plugin())
+ ));
listeners().add(
- plugin().usingPaper() && plugin().usePaperFeatures() ?
- new AsyncPlayerCommandSendListener(plugin()) :
- new PlayerCommandSendListener(plugin())
+ plugin().usingPaper() && plugin().usePaperFeatures() ?
+ new AsyncPlayerCommandSendListener(plugin()) :
+ new PlayerCommandSendListener(plugin())
);
}
diff --git a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/listener/bukkit/PlayerCommandPreprocessListener.java b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/listener/bukkit/PlayerCommandPreprocessListener.java
index 16b78a0..e80e30d 100644
--- a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/listener/bukkit/PlayerCommandPreprocessListener.java
+++ b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/listener/bukkit/PlayerCommandPreprocessListener.java
@@ -35,7 +35,7 @@ public final class PlayerCommandPreprocessListener implements Listener {
private final BlackWidow plugin;
public PlayerCommandPreprocessListener(
- final BlackWidow plugin
+ final BlackWidow plugin
) {
this.plugin = plugin;
}
@@ -50,13 +50,13 @@ public void handle(final PlayerCommandPreprocessEvent event) {
final Player player = event.getPlayer();
final Context context = new Context(plugin())
- .withPlayer(player)
- .withCommands(List.of(event.getMessage()));
+ .withPlayer(player)
+ .withCommands(List.of(event.getMessage()));
if (plugin().cmdBlocker().filterCmdExecution()) {
final Evaluation eval = plugin()
- .cmdBlocker()
- .evalAndProcess(context, event.getMessage(), true, EvalCause.CMD_EXECUTION);
+ .cmdBlocker()
+ .evalAndProcess(context, event.getMessage(), true, EvalCause.CMD_EXECUTION);
switch (eval.policy()) {
case ALLOW:
@@ -69,7 +69,7 @@ public void handle(final PlayerCommandPreprocessEvent event) {
case null, default:
event.setCancelled(true);
throw new IllegalStateException("Unexpected policy '" + eval.policy() + "', prevented " +
- "command execution for best-practice security purposes.");
+ "command execution for best-practice security purposes.");
}
// TODO Debug log the evaluation's description.
diff --git a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/listener/bukkit/PlayerCommandSendListener.java b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/listener/bukkit/PlayerCommandSendListener.java
index 45bfaee..6496d6f 100644
--- a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/listener/bukkit/PlayerCommandSendListener.java
+++ b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/listener/bukkit/PlayerCommandSendListener.java
@@ -33,7 +33,7 @@ public final class PlayerCommandSendListener implements Listener {
private final BlackWidow plugin;
public PlayerCommandSendListener(
- final BlackWidow plugin
+ final BlackWidow plugin
) {
this.plugin = plugin;
}
@@ -48,19 +48,19 @@ public void handle(final PlayerCommandSendEvent event) {
final Player player = event.getPlayer();
final Context context = new Context(plugin())
- .withPlayer(player)
- .withCommands(event.getCommands().stream().map(cmd -> "/" + cmd).toList());
+ .withPlayer(player)
+ .withCommands(event.getCommands().stream().map(cmd -> "/" + cmd).toList());
if (plugin().cmdBlocker().filterCmdSuggestion()) {
event.getCommands().removeIf(cmd -> {
final Evaluation eval = plugin()
- .cmdBlocker()
- .evalAndProcess(context, "/" + cmd, false, EvalCause.CMD_SUGGESTION);
+ .cmdBlocker()
+ .evalAndProcess(context, "/" + cmd, false, EvalCause.CMD_SUGGESTION);
if (eval.policy() == null || (eval.policy() != Policy.ALLOW && eval.policy() != Policy.DENY)) {
event.getCommands().clear();
throw new IllegalStateException("Unexpected policy '" + eval.policy() + "', prevented " +
- "all command suggestions for best-practice security purposes.");
+ "all command suggestions for best-practice security purposes.");
}
// TODO Debug log the evaluation's description.
diff --git a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/listener/bukkit/PlayerJoinListener.java b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/listener/bukkit/PlayerJoinListener.java
new file mode 100644
index 0000000..2c47ca6
--- /dev/null
+++ b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/listener/bukkit/PlayerJoinListener.java
@@ -0,0 +1,54 @@
+package io.github.arcaneplugins.blackwidow.plugin.bukkit.listener.bukkit;
+
+import io.github.arcaneplugins.blackwidow.plugin.bukkit.BlackWidow;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.player.PlayerJoinEvent;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Objects;
+
+/**
+ * Listens for PlayerJoinEvent events.
+ *
+ * @author stumper66
+ * @since 1.1.0
+ */
+public final class PlayerJoinListener implements Listener {
+
+ private final BlackWidow plugin;
+
+ public PlayerJoinListener(
+ @NotNull final BlackWidow plugin
+ ) {
+ this.plugin = plugin;
+ }
+
+ @EventHandler(ignoreCancelled = true)
+ public void handle(
+ @NotNull final PlayerJoinEvent event
+ ) {
+ handleUpdateChecking(event);
+ }
+
+ private void handleUpdateChecking(
+ @NotNull final PlayerJoinEvent event
+ ) {
+ if (!plugin().bukkitVersionChecker().getNotifyPlayers()) {
+ return;
+ }
+
+ final String message = plugin().bukkitVersionChecker().getNotifyMessage();
+
+ if (message == null) {
+ return;
+ }
+
+ event.getPlayer().sendMessage(message);
+ }
+
+ @NotNull
+ private BlackWidow plugin() {
+ return Objects.requireNonNull(plugin, "plugin");
+ }
+}
diff --git a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/listener/paper/AsyncPlayerCommandSendListener.java b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/listener/paper/AsyncPlayerCommandSendListener.java
index 5f93d21..f546773 100644
--- a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/listener/paper/AsyncPlayerCommandSendListener.java
+++ b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/listener/paper/AsyncPlayerCommandSendListener.java
@@ -33,19 +33,19 @@ public final class AsyncPlayerCommandSendListener implements Listener {
private final BlackWidow plugin;
public AsyncPlayerCommandSendListener(
- final BlackWidow plugin
+ final BlackWidow plugin
) {
this.plugin = plugin;
}
@EventHandler
public void handle(
- final AsyncPlayerSendCommandsEvent extends CommandSourceStack> event
+ final AsyncPlayerSendCommandsEvent extends CommandSourceStack> event
) {
// Event Javadocs:
// https://jd.papermc.io/paper/1.21/com/destroystokyo/paper/event/brigadier/AsyncPlayerSendCommandsEvent.html
- if(!event.isAsynchronous() && !event.hasFiredAsync()) {
+ if (!event.isAsynchronous() && !event.hasFiredAsync()) {
// as per paper API docs, this event can fire twice, once async and once sync.
// let's make sure we only handle the async scenario.
// OR, if the event will not be fired async, then handle it anyways.
@@ -58,9 +58,9 @@ public void handle(
//TODO Implement for Paper
plugin().debugLog(
- DebugCategory.ASYNC_PLAYER_COMMAND_SEND_LISTENER,
- () -> "AsyncPlayerCommandSendListener{player=" + player.getName() + ", commandNode.toString=" +
- commandNode + "};"
+ DebugCategory.ASYNC_PLAYER_COMMAND_SEND_LISTENER,
+ () -> "AsyncPlayerCommandSendListener{player=" + player.getName() + ", commandNode.toString=" +
+ commandNode + "};"
);
}
diff --git a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/logic/Action.java b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/logic/Action.java
index bf6ce7d..0356b43 100644
--- a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/logic/Action.java
+++ b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/logic/Action.java
@@ -28,8 +28,8 @@ public abstract class Action implements LogicUnit {
private final String id;
public Action(
- final BlackWidow plugin,
- final String id
+ final BlackWidow plugin,
+ final String id
) {
this.plugin = Objects.requireNonNull(plugin, "plugin");
this.id = Objects.requireNonNull(id, "id");
diff --git a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/logic/BukkitVersionChecker.java b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/logic/BukkitVersionChecker.java
new file mode 100644
index 0000000..3af91a0
--- /dev/null
+++ b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/logic/BukkitVersionChecker.java
@@ -0,0 +1,178 @@
+package io.github.arcaneplugins.blackwidow.plugin.bukkit.logic;
+
+import io.github.arcaneplugins.blackwidow.lib.cmdblocking.UpdateChecker;
+import io.github.arcaneplugins.blackwidow.plugin.bukkit.BlackWidow;
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+import org.bukkit.scheduler.BukkitRunnable;
+import org.bukkit.scheduler.BukkitTask;
+import org.spongepowered.configurate.CommentedConfigurationNode;
+
+import java.io.FileNotFoundException;
+import java.io.InvalidObjectException;
+
+/**
+ * Handles the update checker for Bukkit implementations
+ *
+ * @author stumper66
+ * @since 1.1.0
+ */
+public class BukkitVersionChecker {
+ public BukkitVersionChecker(final BlackWidow plugin) {
+ this.plugin = plugin;
+ }
+
+ private final BlackWidow plugin;
+ private BukkitTask notifyTask;
+ boolean logUpdates;
+ private boolean notifyPlayers;
+ private String notifyMessage;
+ private int lastTimerDuration;
+
+ public void load(final boolean isStartup) {
+ final CommentedConfigurationNode settings = plugin.settings().root()
+ .node("update-checker");
+
+ final boolean enabled = settings.node("enabled").getBoolean(true);
+ final boolean runOnStartup = settings.node("run-on-startup").getBoolean(true);
+ final int repeatTimerDuration = settings.node("repeat-timer-duration-mins").getInt();
+ logUpdates = settings.node("log-updates").getBoolean(true);
+ notifyPlayers = settings.node("notify-players-with-permission").getBoolean(true);
+
+ if (!enabled) {
+ disableChecker();
+ return;
+ }
+
+ startTimerIfNeeded(repeatTimerDuration);
+
+ if (runOnStartup && isStartup) {
+ getLatestVersion();
+ }
+ }
+
+ public boolean getNotifyPlayers() {
+ return notifyPlayers;
+ }
+
+ public String getNotifyMessage() {
+ return notifyMessage;
+ }
+
+ private void disableChecker() {
+ if (notifyTask != null && !notifyTask.isCancelled()) {
+ notifyTask.cancel();
+ notifyTask = null;
+ }
+ }
+
+ private void startTimerIfNeeded(final int repeatTimerDuration) {
+ if (repeatTimerDuration <= 0) {
+ disableChecker();
+ return;
+ }
+
+ if (notifyTask != null && !notifyTask.isCancelled()
+ && repeatTimerDuration == lastTimerDuration) {
+ return;
+ }
+
+ disableChecker();
+
+ final BukkitRunnable runnable = new BukkitRunnable() {
+ @Override
+ public void run() {
+ getLatestVersion();
+ }
+ };
+
+ lastTimerDuration = repeatTimerDuration;
+ final long delay = repeatTimerDuration * 20L * 60L;
+ this.notifyTask = runnable.runTaskTimerAsynchronously(plugin, delay, delay);
+ }
+
+ private void getLatestVersion() {
+ new BukkitRunnable() {
+ @Override
+ public void run() {
+ checkForLatestVersion();
+ }
+ }.runTaskAsynchronously(plugin);
+ }
+
+ private void checkForLatestVersion() {
+ try {
+ UpdateChecker.getLatestVersion("BlackWidow", latestVersion -> {
+ //noinspection deprecation
+ final String currentVersion = plugin.getDescription().getVersion()
+ .split(" ")[0];
+
+ if (latestVersion == null) {
+ if (logUpdates){
+ plugin.getLogger().warning("Error check for latest version, string was null");
+ }
+
+ return;
+ }
+
+ final VersionInfo thisVersion;
+ final VersionInfo hangarVersion;
+ boolean isOutOfDate;
+ boolean isNewerVersion = false;
+ boolean wasUpToDate = false;
+
+ try {
+ thisVersion = new VersionInfo(currentVersion);
+ hangarVersion = new VersionInfo(latestVersion);
+
+ isOutOfDate = (thisVersion.compareTo(hangarVersion) < 0);
+ isNewerVersion = (thisVersion.compareTo(hangarVersion) > 0);
+ } catch (InvalidObjectException e) {
+ plugin.getLogger().warning("Got exception creating version objects: " + e.getMessage());
+ isOutOfDate = !currentVersion.equals(latestVersion);
+ }
+
+ if (isNewerVersion) {
+ notifyMessage = "Your BlackWindow version is a pre-release. Latest release version is " + latestVersion + ". (You're running " + currentVersion + ")";
+ } else if (isOutOfDate) {
+ notifyMessage = "Your BlackWidow version is outdated! Please update to " + latestVersion + " as soon as possible. (You're running " + currentVersion + ")";
+ } else {
+ notifyMessage = "Your BlackWidow version is up to date (You're running " + currentVersion + ")";
+ wasUpToDate = true;
+ }
+
+ if (logUpdates) {
+ plugin.getLogger().info(notifyMessage);
+ }
+
+ if (!wasUpToDate) {
+ notifyPlayers();
+ }
+ });
+ } catch (FileNotFoundException e) {
+ // this exception occurs if the dest URL is incorrect such as a typo in the resource name
+ plugin.getLogger().warning("Error getting latest version, file not found: " + e.getMessage());
+ } catch (Exception e) {
+ plugin.getLogger().warning("Error getting latest version: " + e.getMessage());
+ }
+ }
+
+ private void notifyPlayers() {
+ if (!notifyPlayers || notifyMessage == null) {
+ return;
+ }
+
+ final String requiredPermission = "blackwidow.notifyupdates";
+
+ for (final Player player : Bukkit.getOnlinePlayers()) {
+ if (!player.isValid()) {
+ continue;
+ }
+ if (!player.hasPermission(requiredPermission)) {
+ continue;
+ }
+
+ player.sendMessage(notifyMessage);
+ }
+ }
+}
diff --git a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/logic/Context.java b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/logic/Context.java
index 84aa943..0f37bbc 100644
--- a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/logic/Context.java
+++ b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/logic/Context.java
@@ -34,7 +34,7 @@ public final class Context {
private CommandSender sender;
public Context(
- final BlackWidow plugin
+ final BlackWidow plugin
) {
this.plugin = Objects.requireNonNull(plugin, "plugin");
}
@@ -77,7 +77,7 @@ private static final class ContextException extends RuntimeException {
private final String message;
public ContextException(
- final String message
+ final String message
) {
this.message = message;
}
diff --git a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/logic/LogicManager.java b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/logic/LogicManager.java
index 27bdc67..0b91a97 100644
--- a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/logic/LogicManager.java
+++ b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/logic/LogicManager.java
@@ -41,7 +41,7 @@ public final class LogicManager {
private final BlackWidow plugin;
public LogicManager(
- final BlackWidow plugin
+ final BlackWidow plugin
) {
this.plugin = plugin;
}
@@ -61,8 +61,8 @@ private void loadStdRequirements() {
private void loadThirdPartyRequirements() {
final LoadRequirementsReadyEvent event = new LoadRequirementsReadyEvent(
- plugin(),
- requirementParsers()
+ plugin(),
+ requirementParsers()
);
plugin().getServer().getPluginManager().callEvent(event);
}
@@ -73,37 +73,37 @@ private void loadStdActions() {
private void loadThirdPartyActions() {
final LoadActionsReadyEvent event = new LoadActionsReadyEvent(
- plugin(),
- actionParsers()
+ plugin(),
+ actionParsers()
);
plugin().getServer().getPluginManager().callEvent(event);
}
public Action parseActionAtNode(
- final CommentedConfigurationNode node
+ final CommentedConfigurationNode node
) {
final String id = Objects.requireNonNull(
- node.node("id").getString(),
- "Action node at path '" + node.path() + "' must define an ID with 'id'"
+ node.node("id").getString(),
+ "Action node at path '" + node.path() + "' must define an ID with 'id'"
);
try {
return Objects.requireNonNull(
- actionParsers().get(id),
- "Action node at path '" + node.path() + "' must define the ID ('id') of an Action that" +
- "exists (did you make a typo?), but got '" + id + "'"
+ actionParsers().get(id),
+ "Action node at path '" + node.path() + "' must define the ID ('id') of an Action that" +
+ "exists (did you make a typo?), but got '" + id + "'"
).apply(node);
} catch (final Exception ex) {
throw new RuntimeException(
- "Unable to parse Action with ID '" + id + "' at node path '" + node.path() + "': " +
- ex.getLocalizedMessage(),
- ex
+ "Unable to parse Action with ID '" + id + "' at node path '" + node.path() + "': " +
+ ex.getLocalizedMessage(),
+ ex
);
}
}
public Collection parseActionsInChildrenOfNode(
- final CommentedConfigurationNode nodes
+ final CommentedConfigurationNode nodes
) {
final Collection actions = new LinkedHashSet<>();
for (final CommentedConfigurationNode node : nodes.childrenList()) {
@@ -113,30 +113,30 @@ public Collection parseActionsInChildrenOfNode(
}
public Requirement parseRequirementAtNode(
- final CommentedConfigurationNode node
+ final CommentedConfigurationNode node
) {
final String id = Objects.requireNonNull(
- node.node("id").getString(),
- "Requirement node at path '" + node.path() + "' must define an ID with 'id'"
+ node.node("id").getString(),
+ "Requirement node at path '" + node.path() + "' must define an ID with 'id'"
);
try {
return Objects.requireNonNull(
- requirementParsers().get(id),
- "Requirement node at path '" + node.path() + "' must define the ID ('id') of a Requirement that" +
- "exists (did you make a typo?), but got '" + id + "'"
+ requirementParsers().get(id),
+ "Requirement node at path '" + node.path() + "' must define the ID ('id') of a Requirement that" +
+ "exists (did you make a typo?), but got '" + id + "'"
).apply(node);
} catch (final Exception ex) {
throw new RuntimeException(
- "Unable to parse Requirement with ID '" + id + "' at node path '" + node.path() + "': " +
- ex.getLocalizedMessage(),
- ex
+ "Unable to parse Requirement with ID '" + id + "' at node path '" + node.path() + "': " +
+ ex.getLocalizedMessage(),
+ ex
);
}
}
public Collection parseRequirementsInChildrenOfNode(
- final CommentedConfigurationNode nodes
+ final CommentedConfigurationNode nodes
) {
final Collection requirements = new LinkedHashSet<>();
for (final CommentedConfigurationNode node : nodes.childrenList()) {
diff --git a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/logic/Requirement.java b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/logic/Requirement.java
index 185fab7..da81393 100644
--- a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/logic/Requirement.java
+++ b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/logic/Requirement.java
@@ -29,9 +29,9 @@ public abstract class Requirement implements LogicUnit {
private final boolean inverted;
public Requirement(
- final BlackWidow plugin,
- final String id,
- final boolean inverted
+ final BlackWidow plugin,
+ final String id,
+ final boolean inverted
) {
this.plugin = plugin;
this.id = id;
diff --git a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/logic/VersionInfo.java b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/logic/VersionInfo.java
new file mode 100644
index 0000000..c3f6269
--- /dev/null
+++ b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/logic/VersionInfo.java
@@ -0,0 +1,102 @@
+package io.github.arcaneplugins.blackwidow.plugin.bukkit.logic;
+
+import io.github.arcaneplugins.blackwidow.plugin.bukkit.util.ClassUtil;
+import io.github.arcaneplugins.blackwidow.plugin.bukkit.util.StringUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.InvalidObjectException;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * A custom implementation for comparing program versions
+ *
+ * @author stumper66
+ * @since 1.1.0
+ */
+public final class VersionInfo implements Comparable {
+
+ public VersionInfo(
+ @NotNull final String verStr
+ ) throws InvalidObjectException {
+ Objects.requireNonNull(verStr, "verStr");
+
+ this.verStr = verStr;
+
+ for (final String numTemp : verStr.split("\\.")) {
+ if (!StringUtil.isDouble(numTemp)) {
+ throw new InvalidObjectException("Version can only contain numbers and periods");
+ }
+ final int intD = Integer.parseInt(numTemp);
+ verSplit().add(intD);
+ }
+
+ for (int i = 4; i < verSplit().size(); i++) {
+ verSplit().add(0);
+ }
+ }
+
+ private final String verStr;
+ private final List verSplit = new LinkedList<>();
+
+ @Override
+ public boolean equals(final Object o) {
+ if (o == null) {
+ return false;
+ }
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof VersionInfo)) {
+ return false;
+ }
+
+ return this.verStr.equals(((VersionInfo) o).verStr());
+ }
+
+ @Override
+ @NotNull
+ public String toString() {
+ return verStr();
+ }
+
+ @NotNull
+ private String verStr() {
+ return Objects.requireNonNull(verStr, "verStr");
+ }
+
+ @Override
+ public int compareTo(
+ @NotNull final VersionInfo other
+ ) {
+ for (int i = 0; i < 4; i++) {
+
+ if (other.verSplit().size() <= i && this.verSplit().size() - 1 <= i) {
+ break;
+ }
+
+ // if one has extra digits we'll assume that one is newer
+ else if (other.verSplit().size() <= i) {
+ return 1;
+ } else if (verSplit().size() <= i) {
+ return -1;
+ }
+
+ final int compareInt = other.verSplit().get(i);
+ final int thisInt = this.verSplit().get(i);
+
+ if (thisInt > compareInt) {
+ return 1;
+ } else if (thisInt < compareInt) {
+ return -1;
+ }
+ }
+
+ return 0;
+ }
+
+ private List verSplit() {
+ return Objects.requireNonNull(verSplit, "verSplit");
+ }
+}
\ No newline at end of file
diff --git a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/logic/inbuilt/action/SendMessageAction.java b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/logic/inbuilt/action/SendMessageAction.java
index 7bef17c..d3c0926 100644
--- a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/logic/inbuilt/action/SendMessageAction.java
+++ b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/logic/inbuilt/action/SendMessageAction.java
@@ -37,26 +37,26 @@ public final class SendMessageAction extends Action {
private final Collection message;
public SendMessageAction(
- final BlackWidow plugin,
- final Collection message
+ final BlackWidow plugin,
+ final Collection message
) {
super(plugin, ID);
this.message = Objects.requireNonNull(message, "message");
}
public SendMessageAction(
- final BlackWidow plugin,
- final CommentedConfigurationNode node
+ final BlackWidow plugin,
+ final CommentedConfigurationNode node
) {
super(
- plugin,
- Objects.requireNonNull(node.node("id").getString(), "id")
+ plugin,
+ Objects.requireNonNull(node.node("id").getString(), "id")
);
try {
this.message = Objects.requireNonNull(
- node.node("msg").getList(String.class),
- "msg"
+ node.node("msg").getList(String.class),
+ "msg"
);
} catch (final SerializationException ex) {
throw new RuntimeException("Unable to read msg string list", ex);
@@ -76,12 +76,12 @@ public Collection message() {
@Override
public void run(Context context) {
final Audience advPlayer = plugin()
- .adventure()
- .player(context.player(true));
+ .adventure()
+ .player(context.player(true));
message()
- .stream()
- .map(msg -> Translation.formatify(plugin(), msg, Collections.emptyMap()))
- .forEachOrdered(advPlayer::sendMessage);
+ .stream()
+ .map(msg -> Translation.formatify(plugin(), msg, Collections.emptyMap()))
+ .forEachOrdered(advPlayer::sendMessage);
}
}
diff --git a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/logic/inbuilt/requirement/HasPermissionRequirement.java b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/logic/inbuilt/requirement/HasPermissionRequirement.java
index 869f348..02c9433 100644
--- a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/logic/inbuilt/requirement/HasPermissionRequirement.java
+++ b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/logic/inbuilt/requirement/HasPermissionRequirement.java
@@ -32,22 +32,22 @@ public final class HasPermissionRequirement extends Requirement {
private final String permission;
public HasPermissionRequirement(
- final BlackWidow plugin,
- final String permission,
- final boolean inverted
+ final BlackWidow plugin,
+ final String permission,
+ final boolean inverted
) {
super(plugin, ID, inverted);
this.permission = Objects.requireNonNull(permission, "permission");
}
public HasPermissionRequirement(
- final BlackWidow plugin,
- final CommentedConfigurationNode node
+ final BlackWidow plugin,
+ final CommentedConfigurationNode node
) {
this(
- plugin,
- Objects.requireNonNull(node.node("permission").getString(), "permission"),
- node.node("inverted").getBoolean(false)
+ plugin,
+ Objects.requireNonNull(node.node("permission").getString(), "permission"),
+ node.node("inverted").getBoolean(false)
);
}
@@ -60,8 +60,8 @@ public HasPermissionRequirement(
@Override
public boolean validateImpl(final Context context) {
return Objects.requireNonNullElse(
- context.player(false),
- context.commandSender(false)
+ context.player(false),
+ context.commandSender(false)
).hasPermission(permission());
}
diff --git a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/logic/inbuilt/requirement/InWorldRequirement.java b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/logic/inbuilt/requirement/InWorldRequirement.java
index 1409015..12cbaba 100644
--- a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/logic/inbuilt/requirement/InWorldRequirement.java
+++ b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/logic/inbuilt/requirement/InWorldRequirement.java
@@ -32,22 +32,22 @@ public final class InWorldRequirement extends Requirement {
private final String worldName;
public InWorldRequirement(
- final BlackWidow plugin,
- final String worldName,
- final boolean inverted
+ final BlackWidow plugin,
+ final String worldName,
+ final boolean inverted
) {
super(plugin, ID, inverted);
this.worldName = Objects.requireNonNull(worldName, "worldName");
}
public InWorldRequirement(
- final BlackWidow plugin,
- final CommentedConfigurationNode node
+ final BlackWidow plugin,
+ final CommentedConfigurationNode node
) {
this(
- plugin,
- Objects.requireNonNull(node.node("world-name").getString(), "worldName"),
- node.node("inverted").getBoolean(false)
+ plugin,
+ Objects.requireNonNull(node.node("world-name").getString(), "worldName"),
+ node.node("inverted").getBoolean(false)
);
}
diff --git a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/util/ExceptionUtil.java b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/util/ExceptionUtil.java
index f9e84fa..1034618 100644
--- a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/util/ExceptionUtil.java
+++ b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/util/ExceptionUtil.java
@@ -29,9 +29,9 @@ private ExceptionUtil() {
}
public static void logException(
- final BlackWidow plugin,
- final Exception ex,
- final String msg
+ final BlackWidow plugin,
+ final Exception ex,
+ final String msg
) {
final Logger logger = plugin.getLogger();
@@ -42,10 +42,10 @@ public static void logException(
logger.severe("");
logger.severe(minidiv + "Warning: Please Read Below Carefully");
logger.severe("\tBlackWidow has detected an issue, please carefully read the below and attempt to " +
- "resolve the issue (or otherwise, report it to the maintainers via the details also provided below).");
+ "resolve the issue (or otherwise, report it to the maintainers via the details also provided below).");
logger.severe("");
logger.severe("\tSometimes, these are simple errors caused when users misconfigure the plugin, other " +
- "times, it can be a bug (issue) with the plugin's code which the maintainers might not know about.");
+ "times, it can be a bug (issue) with the plugin's code which the maintainers might not know about.");
logger.severe("");
logger.severe(bigdiv);
logger.severe("");
@@ -60,11 +60,11 @@ public static void logException(
logger.severe("");
logger.severe(minidiv + "Contacting Maintainers for Assistance");
logger.severe("If this is an issue you can't fix, or if it is a bug report, please contact the " +
- "maintainers by checking for recommended links in the GitHub repository description.");
+ "maintainers by checking for recommended links in the GitHub repository description.");
logger.severe("Please visit: < https://github.com/ArcanePlugins/BlackWidow/ >");
logger.severe("");
logger.severe("Our Discord Server (should be linked within the page above) is usually the best avenue " +
- "for users to report issues like these.");
+ "for users to report issues like these.");
logger.severe("");
logger.severe("It's usually worth checking the Frequently Asked Questions page (if applicable).");
logger.severe("");
diff --git a/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/util/StringUtil.java b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/util/StringUtil.java
new file mode 100644
index 0000000..7eb601e
--- /dev/null
+++ b/blackwidowpluginbukkit/src/main/java/io/github/arcaneplugins/blackwidow/plugin/bukkit/util/StringUtil.java
@@ -0,0 +1,46 @@
+/*
+ * BlackWidow: Security modifications for Minecraft servers and proxies
+ * Copyright (c) 2024 lokka30.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package io.github.arcaneplugins.blackwidow.plugin.bukkit.util;
+
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * {@link StringUtil} contains a variety of utilities related to {@link String Java String objects}.
+ *
+ * @author lokka30
+ * @since 1.1.0
+ */
+public final class StringUtil {
+
+ @SuppressWarnings("BooleanMethodIsAlwaysInverted")
+ public static boolean isDouble(
+ @Nullable final String str
+ ) {
+ if (str == null || str.isBlank()) {
+ return false;
+ }
+
+ try {
+ Double.parseDouble(str);
+ return true;
+ } catch (final NumberFormatException ex) {
+ return false;
+ }
+ }
+}
diff --git a/blackwidowpluginbukkit/src/main/resources/settings.yml b/blackwidowpluginbukkit/src/main/resources/settings.yml
index 1a3923a..4d65d63 100644
--- a/blackwidowpluginbukkit/src/main/resources/settings.yml
+++ b/blackwidowpluginbukkit/src/main/resources/settings.yml
@@ -34,8 +34,14 @@ cmd-blocking:
execution: true
suggestion: true
operators-bypass-completely: true
+update-checker:
+ enabled: true
+ run-on-startup: true
+ repeat-timer-duration-mins: 60
+ log-updates: true
+ notify-players-with-permission: true
do-not-touch:
version:
context: ""
- original: 1
- installed: 1
+ original: 2
+ installed: 2
diff --git a/settings.xml b/settings.xml
index 474cabf..d4dc949 100644
--- a/settings.xml
+++ b/settings.xml
@@ -16,7 +16,8 @@
~ along with this program. If not, see .
-->
-
+
github