mirror of
https://github.com/jonesdevelopment/sonar.git
synced 2026-11-05 09:20:15 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
af12ef535c | ||
|
|
7de08ffa98 | ||
|
|
c56d41cd77 | ||
|
|
4b30729138 | ||
|
|
1254514ad2 | ||
|
|
b4673d8e9f | ||
|
|
5eaaf88ec8 | ||
|
|
367ce07cb0 | ||
|
|
901b49b063 | ||
|
|
a3cdc08f90 | ||
|
|
150a3575b2 | ||
|
|
6082bf944d | ||
|
|
e6d20e2b94 | ||
|
|
6f3a8432a7 | ||
|
|
350ae02ff0 | ||
|
|
32c37c0337 | ||
|
|
b8e552dff9 |
No files matched your search
@@ -49,22 +49,68 @@ public interface Sonar {
|
||||
@ApiStatus.Internal
|
||||
@NotNull Audience sender(final @NotNull Object object);
|
||||
|
||||
/**
|
||||
* Gets the platform Sonar is running on (e.g., Bukkit, BungeeCord, Velocity).
|
||||
*
|
||||
* @return The {@link SonarPlatform} enum representing the current platform.
|
||||
*/
|
||||
@NotNull SonarPlatform getPlatform();
|
||||
|
||||
/**
|
||||
* Gets the logger instance for Sonar.
|
||||
*
|
||||
* @return The {@link LoggerWrapper} instance.
|
||||
*/
|
||||
@NotNull LoggerWrapper getLogger();
|
||||
|
||||
/**
|
||||
* Gets the Sonar configuration.
|
||||
*
|
||||
* @return The {@link SonarConfiguration} instance.
|
||||
*/
|
||||
@NotNull SonarConfiguration getConfig();
|
||||
|
||||
/**
|
||||
* Gets the subcommand registry for Sonar commands.
|
||||
*
|
||||
* @return The {@link SubcommandRegistry} instance.
|
||||
*/
|
||||
@NotNull SubcommandRegistry getSubcommandRegistry();
|
||||
|
||||
/**
|
||||
* Gets the controller for verified players.
|
||||
* Used for managing players who have passed the verification.
|
||||
*
|
||||
* @return The {@link VerifiedPlayerController} instance.
|
||||
*/
|
||||
VerifiedPlayerController getVerifiedPlayerController();
|
||||
|
||||
/**
|
||||
* Gets the handler for action bar notifications.
|
||||
*
|
||||
* @return The {@link ActionBarNotificationHandler} instance.
|
||||
*/
|
||||
@NotNull ActionBarNotificationHandler getActionBarNotificationHandler();
|
||||
|
||||
/**
|
||||
* Gets the handler for chat notifications.
|
||||
*
|
||||
* @return The {@link ChatNotificationHandler} instance.
|
||||
*/
|
||||
@NotNull ChatNotificationHandler getChatNotificationHandler();
|
||||
|
||||
/**
|
||||
* Gets the system timer used for tracking plugin launch time.
|
||||
*
|
||||
* @return The {@link SystemTimer} instance.
|
||||
*/
|
||||
@NotNull SystemTimer getLaunchTimer();
|
||||
|
||||
/**
|
||||
* Gets the statistics tracker for Sonar.
|
||||
*
|
||||
* @return The {@link SonarStatistics} instance.
|
||||
*/
|
||||
@NotNull SonarStatistics getStatistics();
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@@ -73,25 +119,67 @@ public interface Sonar {
|
||||
@SuppressWarnings("unused")
|
||||
void setChatNotificationHandler(final @NotNull ChatNotificationHandler notificationHandler);
|
||||
|
||||
/**
|
||||
* Reloads the Sonar configuration.
|
||||
*/
|
||||
void reload();
|
||||
|
||||
/**
|
||||
* Gets the current version of Sonar.
|
||||
*
|
||||
* @return The {@link SonarVersion} instance.
|
||||
*/
|
||||
@NotNull default SonarVersion getVersion() {
|
||||
return SonarVersion.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the event manager for Sonar.
|
||||
*
|
||||
* @return The {@link SonarEventManager} instance.
|
||||
*/
|
||||
@NotNull default SonarEventManager getEventManager() {
|
||||
return SonarEventManager.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the attack tracker for Sonar.
|
||||
*
|
||||
* @return The {@link AttackTracker} instance.
|
||||
*/
|
||||
@NotNull default AttackTracker getAttackTracker() {
|
||||
return AttackTracker.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the anti-bot handler (called "Fallback") for Sonar.
|
||||
*
|
||||
* @return The {@link Fallback} instance.
|
||||
*/
|
||||
@NotNull default Fallback getFallback() {
|
||||
return Fallback.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the instance of the Sonar API.
|
||||
*
|
||||
* @return The {@link Sonar} instance.
|
||||
* @throws IllegalStateException If Sonar has not been initialized.
|
||||
*/
|
||||
@NotNull static Sonar get() {
|
||||
return SonarSupplier.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the instance of the Sonar API.
|
||||
* Only use this method if you understand the implications,
|
||||
* and have a specific reason to bypass the standard {@link #get()} method.
|
||||
* In most cases, {@link #get()} is the preferred way to access the Sonar API.
|
||||
*
|
||||
* @return The Sonar instance.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
@NotNull static Sonar get0() {
|
||||
return SonarSupplier.sonar;
|
||||
}
|
||||
}
|
||||
@@ -30,4 +30,11 @@ public class SonarSupplier {
|
||||
}
|
||||
sonar = _sonar;
|
||||
}
|
||||
|
||||
public Sonar get() {
|
||||
if (sonar == null) {
|
||||
throw new IllegalStateException("Sonar is not initialized yet");
|
||||
}
|
||||
return sonar;
|
||||
}
|
||||
}
|
||||
@@ -36,8 +36,8 @@ public interface SonarCommand {
|
||||
default void handle(final @NotNull InvocationSource source, final String @NotNull [] args) {
|
||||
// Check if the player actually has the permission to run the command
|
||||
if (source.isPlayer() && !source.getPermissionFunction().test("sonar.command")) {
|
||||
if (Sonar.get().getConfig().getNoPermission() != null) {
|
||||
source.sendMessage(Sonar.get().getConfig().getNoPermission());
|
||||
if (Sonar.get0().getConfig().getNoPermission() != null) {
|
||||
source.sendMessage(Sonar.get0().getConfig().getNoPermission());
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -46,7 +46,7 @@ public interface SonarCommand {
|
||||
|
||||
if (args.length > 0) {
|
||||
// Search subcommand if command arguments are present
|
||||
subcommand = Sonar.get().getSubcommandRegistry().getSubcommands().stream()
|
||||
subcommand = Sonar.get0().getSubcommandRegistry().getSubcommands().stream()
|
||||
.filter(sub -> sub.getInfo().name().equalsIgnoreCase(args[0])
|
||||
|| Arrays.stream(sub.getInfo().aliases()).anyMatch(alias -> alias.equalsIgnoreCase(args[0])))
|
||||
.findFirst();
|
||||
@@ -57,8 +57,8 @@ public interface SonarCommand {
|
||||
if (!command.getInfo().onlyConsole()
|
||||
&& !source.getPermissionFunction().test(command.getPermission())) {
|
||||
source.sendMessage(MiniMessage.miniMessage().deserialize(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("commands.subcommand-no-permission"),
|
||||
Placeholder.component("prefix", Sonar.get().getConfig().getPrefix()),
|
||||
Sonar.get0().getConfig().getMessagesConfig().getString("commands.subcommand-no-permission"),
|
||||
Placeholder.component("prefix", Sonar.get0().getConfig().getPrefix()),
|
||||
Placeholder.unparsed("permission", command.getPermission())));
|
||||
return;
|
||||
}
|
||||
@@ -66,28 +66,28 @@ public interface SonarCommand {
|
||||
command.invoke(source, args);
|
||||
}, () -> {
|
||||
final UpdateChecker.CheckResult checkResult = UpdateChecker.getLastCheckResult();
|
||||
Component version = Component.text(Sonar.get().getVersion().getFormatted());
|
||||
Component version = Component.text(Sonar.get0().getVersion().getFormatted());
|
||||
if (checkResult.getConfigKey() != null) {
|
||||
version = version.append(MiniMessage.miniMessage().deserialize(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("commands.main." + checkResult.getConfigKey())));
|
||||
Sonar.get0().getConfig().getMessagesConfig().getString("commands.main." + checkResult.getConfigKey())));
|
||||
}
|
||||
|
||||
// Print standard help message
|
||||
source.sendMessage(MiniMessage.miniMessage().deserialize(
|
||||
String.join("<newline>",
|
||||
Sonar.get().getConfig().getMessagesConfig().getStringList("commands.main.header")),
|
||||
Sonar.get0().getConfig().getMessagesConfig().getStringList("commands.main.header")),
|
||||
Placeholder.component("version", version),
|
||||
Placeholder.unparsed("platform", Sonar.get().getPlatform().getDisplayName()),
|
||||
Placeholder.unparsed("platform", Sonar.get0().getPlatform().getDisplayName()),
|
||||
Placeholder.unparsed("copyright-year", String.valueOf(Calendar.getInstance().get(Calendar.YEAR)))));
|
||||
|
||||
final Component yes = MiniMessage.miniMessage().deserialize(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("commands.main.tick"));
|
||||
Sonar.get0().getConfig().getMessagesConfig().getString("commands.main.tick"));
|
||||
final Component no = MiniMessage.miniMessage().deserialize(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("commands.main.cross"));
|
||||
Sonar.get0().getConfig().getMessagesConfig().getString("commands.main.cross"));
|
||||
|
||||
Sonar.get().getSubcommandRegistry().getSubcommands().forEach(command -> {
|
||||
Sonar.get0().getSubcommandRegistry().getSubcommands().forEach(command -> {
|
||||
source.sendMessage(MiniMessage.miniMessage().deserialize(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("commands.main.subcommands"),
|
||||
Sonar.get0().getConfig().getMessagesConfig().getString("commands.main.subcommands"),
|
||||
TagResolver.resolver("suggest-subcommand",
|
||||
(queue, context) -> Tag.styling(ClickEvent.suggestCommand("/sonar " + command.getInfo().name()))),
|
||||
Placeholder.unparsed("subcommand", command.getInfo().name()),
|
||||
@@ -103,7 +103,7 @@ public interface SonarCommand {
|
||||
static void prepareCachedTabSuggestions() {
|
||||
if (TAB_SUGGESTIONS.isEmpty()) {
|
||||
final List<String> subcommandsAndAliases = new ArrayList<>();
|
||||
for (final Subcommand subcommand : Sonar.get().getSubcommandRegistry().getSubcommands()) {
|
||||
for (final Subcommand subcommand : Sonar.get0().getSubcommandRegistry().getSubcommands()) {
|
||||
subcommandsAndAliases.add(subcommand.getInfo().name());
|
||||
|
||||
final List<String> arguments = Arrays.asList(subcommand.getInfo().arguments());
|
||||
|
||||
@@ -48,8 +48,8 @@ public abstract class Subcommand {
|
||||
protected static @Nullable String validateIP(final InvocationSource source, final String raw) {
|
||||
if (!IPv4_REGEX.matcher(raw).matches() && !IPv6_REGEX.matcher(raw).matches()) {
|
||||
source.sendMessage(MiniMessage.miniMessage().deserialize(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("commands.invalid-ip-address"),
|
||||
Placeholder.component("prefix", Sonar.get().getConfig().getPrefix())));
|
||||
Sonar.get0().getConfig().getMessagesConfig().getString("commands.invalid-ip-address"),
|
||||
Placeholder.component("prefix", Sonar.get0().getConfig().getPrefix())));
|
||||
return null;
|
||||
}
|
||||
return raw;
|
||||
@@ -61,8 +61,8 @@ public abstract class Subcommand {
|
||||
|
||||
protected final void incorrectUsage(final @NotNull InvocationSource invocationSource, final String usage) {
|
||||
invocationSource.sendMessage(MiniMessage.miniMessage().deserialize(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("commands.incorrect-usage"),
|
||||
Placeholder.component("prefix", Sonar.get().getConfig().getPrefix()),
|
||||
Sonar.get0().getConfig().getMessagesConfig().getString("commands.incorrect-usage"),
|
||||
Placeholder.component("prefix", Sonar.get0().getConfig().getPrefix()),
|
||||
Placeholder.unparsed("subcommand-usage", usage)));
|
||||
}
|
||||
|
||||
@@ -70,16 +70,16 @@ public abstract class Subcommand {
|
||||
// Check if the subcommand can only be executed by players
|
||||
if (info.onlyPlayers() && !invocationSource.isPlayer()) {
|
||||
invocationSource.sendMessage(MiniMessage.miniMessage().deserialize(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("commands.player-only"),
|
||||
Placeholder.component("prefix", Sonar.get().getConfig().getPrefix())));
|
||||
Sonar.get0().getConfig().getMessagesConfig().getString("commands.player-only"),
|
||||
Placeholder.component("prefix", Sonar.get0().getConfig().getPrefix())));
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the subcommand can only be executed though console
|
||||
if (info.onlyConsole() && invocationSource.isPlayer()) {
|
||||
invocationSource.sendMessage(MiniMessage.miniMessage().deserialize(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("commands.console-only"),
|
||||
Placeholder.component("prefix", Sonar.get().getConfig().getPrefix())));
|
||||
Sonar.get0().getConfig().getMessagesConfig().getString("commands.console-only"),
|
||||
Placeholder.component("prefix", Sonar.get0().getConfig().getPrefix())));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ public abstract class Subcommand {
|
||||
|
||||
public final @NotNull String getDescription() {
|
||||
final String path = String.format("commands.%s.description", info.name());
|
||||
return Objects.requireNonNull(Sonar.get().getConfig().getMessagesConfig().getString(path));
|
||||
return Objects.requireNonNull(Sonar.get0().getConfig().getMessagesConfig().getString(path));
|
||||
}
|
||||
|
||||
protected abstract void execute(final @NotNull InvocationSource source, final String @NotNull [] args);
|
||||
|
||||
@@ -89,7 +89,7 @@ public final class SimpleYamlConfig {
|
||||
|
||||
public int getInt(final String path) {
|
||||
if (!yaml.contains(path)) {
|
||||
Sonar.get().getLogger().warn("Could not find {} in {}.", path, file.getName());
|
||||
Sonar.get0().getLogger().warn("Could not find {} in {}.", path, file.getName());
|
||||
return 0;
|
||||
}
|
||||
return yaml.getInt(path);
|
||||
@@ -97,7 +97,7 @@ public final class SimpleYamlConfig {
|
||||
|
||||
public boolean getBoolean(final String path) {
|
||||
if (!yaml.contains(path)) {
|
||||
Sonar.get().getLogger().warn("Could not find {} in {}.", path, file.getName());
|
||||
Sonar.get0().getLogger().warn("Could not find {} in {}.", path, file.getName());
|
||||
return false;
|
||||
}
|
||||
return yaml.getBoolean(path);
|
||||
@@ -105,7 +105,7 @@ public final class SimpleYamlConfig {
|
||||
|
||||
public @NotNull String getString(final String path) {
|
||||
if (!yaml.contains(path)) {
|
||||
Sonar.get().getLogger().warn("Could not find {} in {}.", path, file.getName());
|
||||
Sonar.get0().getLogger().warn("Could not find {} in {}.", path, file.getName());
|
||||
return "";
|
||||
}
|
||||
final Object object = yaml.get(path);
|
||||
@@ -117,7 +117,7 @@ public final class SimpleYamlConfig {
|
||||
|
||||
public List<String> getStringList(final String path) {
|
||||
if (!yaml.contains(path)) {
|
||||
Sonar.get().getLogger().warn("Could not find {} in {}.", path, file.getName());
|
||||
Sonar.get0().getLogger().warn("Could not find {} in {}.", path, file.getName());
|
||||
return new ArrayList<>(0);
|
||||
}
|
||||
return yaml.getStringList(path);
|
||||
@@ -125,7 +125,7 @@ public final class SimpleYamlConfig {
|
||||
|
||||
public List<Integer> getIntList(final String path) {
|
||||
if (!yaml.contains(path)) {
|
||||
Sonar.get().getLogger().warn("Could not find {} in {}.", path, file.getName());
|
||||
Sonar.get0().getLogger().warn("Could not find {} in {}.", path, file.getName());
|
||||
return new ArrayList<>(0);
|
||||
}
|
||||
return yaml.getIntegerList(path);
|
||||
|
||||
@@ -66,14 +66,14 @@ public final class SonarConfiguration {
|
||||
final URL defaultLanguageFile = Sonar.class.getResource("/assets/language.properties");
|
||||
// Make sure the file actually exists before trying to copy it
|
||||
if (defaultLanguageFile == null) {
|
||||
Sonar.get().getLogger().error("Cannot check for custom language (is the file missing?)");
|
||||
Sonar.get0().getLogger().error("Cannot check for custom language (is the file missing?)");
|
||||
return DEFAULT_FALLBACK_LANGUAGE;
|
||||
}
|
||||
// Copy the file to the plugin data directory
|
||||
try (final InputStream inputStream = defaultLanguageFile.openStream()) {
|
||||
Files.copy(inputStream, languageFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||
} catch (IOException exception) {
|
||||
Sonar.get().getLogger().error("Error copying file: {}", exception);
|
||||
Sonar.get0().getLogger().error("Error copying file: {}", exception);
|
||||
return DEFAULT_FALLBACK_LANGUAGE;
|
||||
}
|
||||
}
|
||||
@@ -87,13 +87,13 @@ public final class SonarConfiguration {
|
||||
// Try parsing the property as a language
|
||||
return Language.fromCode(property);
|
||||
} catch (Throwable throwable) {
|
||||
Sonar.get().getLogger().error("Could not find requested language: {}", throwable);
|
||||
Sonar.get().getLogger().error("You can view a full list of valid language codes here:");
|
||||
Sonar.get().getLogger().error("https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes");
|
||||
Sonar.get().getLogger().error("If a translation does not exist yet, Sonar will use English (en).");
|
||||
Sonar.get0().getLogger().error("Could not find requested language: {}", throwable);
|
||||
Sonar.get0().getLogger().error("You can view a full list of valid language codes here:");
|
||||
Sonar.get0().getLogger().error("https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes");
|
||||
Sonar.get0().getLogger().error("If a translation does not exist yet, Sonar will use English (en).");
|
||||
}
|
||||
} catch (IOException exception) {
|
||||
Sonar.get().getLogger().error("Error reading language file: {}", exception);
|
||||
Sonar.get0().getLogger().error("Error reading language file: {}", exception);
|
||||
}
|
||||
return DEFAULT_FALLBACK_LANGUAGE;
|
||||
}
|
||||
@@ -112,13 +112,13 @@ public final class SonarConfiguration {
|
||||
final String property = System.getProperty("user.language", "en");
|
||||
language = Language.fromCode(property);
|
||||
// Make sure the user knows that we're using the system language for translations
|
||||
Sonar.get().getLogger().info("Using system language ({}) for translations.", language);
|
||||
Sonar.get0().getLogger().info("Using system language ({}) for translations.", language);
|
||||
} catch (Exception exception) {
|
||||
Sonar.get().getLogger().warn("Could not use system language for translations.");
|
||||
Sonar.get().getLogger().warn("Using default language ({}) for translations.", language);
|
||||
Sonar.get0().getLogger().warn("Could not use system language for translations.");
|
||||
Sonar.get0().getLogger().warn("Using default language ({}) for translations.", language);
|
||||
}
|
||||
} else {
|
||||
Sonar.get().getLogger().info("Using custom language ({}) for translations.", language);
|
||||
Sonar.get0().getLogger().info("Using custom language ({}) for translations.", language);
|
||||
}
|
||||
|
||||
// Load all configurations
|
||||
@@ -158,12 +158,12 @@ public final class SonarConfiguration {
|
||||
verification.timing = Verification.Timing.valueOf(generalConfig.getString("verification.timing"));
|
||||
// Warn the user if the verification timing is set to NEVER
|
||||
if (verification.timing == Verification.Timing.NEVER) {
|
||||
Sonar.get().getLogger().warn(" ");
|
||||
Sonar.get().getLogger().warn("You have set the verification timing to 'NEVER'.");
|
||||
Sonar.get().getLogger().warn("Sonar will NOT perform the bot verification at all, therefore making it useless.");
|
||||
Sonar.get().getLogger().warn("It is highly suggested to set this option to either 'DURING_ATTACK' or 'ALWAYS'.");
|
||||
Sonar.get().getLogger().warn("Please only edit this option if you really know what you are doing.");
|
||||
Sonar.get().getLogger().warn(" ");
|
||||
Sonar.get0().getLogger().warn(" ");
|
||||
Sonar.get0().getLogger().warn("You have set the verification timing to 'NEVER'.");
|
||||
Sonar.get0().getLogger().warn("Sonar will NOT perform the bot verification at all, therefore making it useless.");
|
||||
Sonar.get0().getLogger().warn("It is highly suggested to set this option to either 'DURING_ATTACK' or 'ALWAYS'.");
|
||||
Sonar.get0().getLogger().warn("Please only edit this option if you really know what you are doing.");
|
||||
Sonar.get0().getLogger().warn(" ");
|
||||
}
|
||||
|
||||
verification.gravity.enabled = generalConfig.getBoolean("verification.checks.gravity.enabled");
|
||||
@@ -187,7 +187,7 @@ public final class SonarConfiguration {
|
||||
if (backgroundFile.exists()) {
|
||||
verification.map.backgroundImage = backgroundFile;
|
||||
} else {
|
||||
Sonar.get().getLogger().error("Could not find background image {}", backgroundFile.getAbsolutePath());
|
||||
Sonar.get0().getLogger().error("Could not find background image {}", backgroundFile.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -288,7 +288,7 @@ public final class SonarConfiguration {
|
||||
final String resourceName = url + "/" + language.getCode() + ".yml";
|
||||
URL result = Sonar.class.getResource("/assets/" + resourceName);
|
||||
if (result == null) {
|
||||
Sonar.get().getLogger().warn("Could not find " + resourceName + "! Using en.yml!");
|
||||
Sonar.get0().getLogger().warn("Could not find " + resourceName + "! Using en.yml!");
|
||||
result = Objects.requireNonNull(Sonar.class.getResource("/assets/" + url + "/en.yml"));
|
||||
}
|
||||
return result;
|
||||
@@ -297,7 +297,7 @@ public final class SonarConfiguration {
|
||||
private static int clamp(final int v, final int max, final int min) {
|
||||
final int output = Math.max(Math.min(v, min), max);
|
||||
if (output != v) {
|
||||
Sonar.get().getLogger().warn("Clamped configuration value {} to {}", v, output);
|
||||
Sonar.get0().getLogger().warn("Clamped configuration value {} to {}", v, output);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
+11
-11
@@ -56,17 +56,17 @@ public final class VerifiedPlayerController {
|
||||
private final ExecutorService updateService = Executors.newSingleThreadExecutor();
|
||||
|
||||
public VerifiedPlayerController(final @NotNull LibraryManager libraryManager) {
|
||||
final SonarConfiguration.Database database = Sonar.get().getConfig().getDatabase();
|
||||
final SonarConfiguration.Database database = Sonar.get0().getConfig().getDatabase();
|
||||
cachedDatabaseType = database.getType();
|
||||
|
||||
if (cachedDatabaseType == SonarConfiguration.Database.Type.NONE) {
|
||||
Sonar.get().getLogger().warn("Configure a database to save verified players.");
|
||||
Sonar.get0().getLogger().warn("Configure a database to save verified players.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure to only load the driver once per database type
|
||||
if (!cachedDatabaseType.isLoaded()) {
|
||||
Sonar.get().getLogger().info("Loading {} driver version {}",
|
||||
Sonar.get0().getLogger().info("Loading {} driver version {}",
|
||||
cachedDatabaseType.getDatabaseType().getDatabaseName(),
|
||||
cachedDatabaseType.getDatabaseDriver().getVersion());
|
||||
libraryManager.loadLibrary(cachedDatabaseType.getDatabaseDriver());
|
||||
@@ -79,20 +79,20 @@ public final class VerifiedPlayerController {
|
||||
// H2 has a different JDBC URL layout
|
||||
// https://www.codejava.net/java-se/jdbc/connect-to-h2-database-examples
|
||||
if (cachedDatabaseType == SonarConfiguration.Database.Type.H2) {
|
||||
final File file = new File(Sonar.get().getConfig().getPluginFolder(),
|
||||
Sonar.get().getConfig().getGeneralConfig().getString("database.filename"));
|
||||
final File file = new File(Sonar.get0().getConfig().getPluginFolder(),
|
||||
Sonar.get0().getConfig().getGeneralConfig().getString("database.filename"));
|
||||
jdbcURL = String.format(cachedDatabaseType.getConnectionString(), file.getAbsolutePath());
|
||||
} else {
|
||||
// Normal JDBC URL layout for MySQL/MariaDB/...
|
||||
jdbcURL = String.format(cachedDatabaseType.getConnectionString(),
|
||||
Sonar.get().getConfig().getGeneralConfig().getString("database.host"),
|
||||
Sonar.get().getConfig().getGeneralConfig().getInt("database.port"),
|
||||
Sonar.get().getConfig().getGeneralConfig().getString("database.name"));
|
||||
Sonar.get0().getConfig().getGeneralConfig().getString("database.host"),
|
||||
Sonar.get0().getConfig().getGeneralConfig().getInt("database.port"),
|
||||
Sonar.get0().getConfig().getGeneralConfig().getString("database.name"));
|
||||
}
|
||||
|
||||
connectionSource = new JdbcConnectionSource(jdbcURL,
|
||||
Sonar.get().getConfig().getGeneralConfig().getString("database.username"),
|
||||
Sonar.get().getConfig().getGeneralConfig().getString("database.password"),
|
||||
Sonar.get0().getConfig().getGeneralConfig().getString("database.username"),
|
||||
Sonar.get0().getConfig().getGeneralConfig().getString("database.password"),
|
||||
cachedDatabaseType.getDatabaseType());
|
||||
|
||||
try {
|
||||
@@ -159,7 +159,7 @@ public final class VerifiedPlayerController {
|
||||
for (final VerifiedPlayer player : oldEntries) {
|
||||
dao.delete(player);
|
||||
}
|
||||
Sonar.get().getLogger().info("Removed {} database entries older than {} days.",
|
||||
Sonar.get0().getLogger().info("Removed {} database entries older than {} days.",
|
||||
oldEntries.size(), maximumAge);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ public final class SonarEventManager {
|
||||
try {
|
||||
eventListener.handle(event);
|
||||
} catch (Throwable throwable) {
|
||||
Sonar.get().getLogger().error("Could not pass {} to listener: {}",
|
||||
Sonar.get0().getLogger().error("Could not pass {} to listener: {}",
|
||||
event.getClass().getSimpleName(), throwable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,16 +49,16 @@ public final class Fallback {
|
||||
private Ratelimiter<InetAddress> ratelimiter;
|
||||
|
||||
public boolean shouldVerifyNewPlayers() {
|
||||
return shouldPerform(Sonar.get().getConfig().getVerification().getTiming());
|
||||
return shouldPerform(Sonar.get0().getConfig().getVerification().getTiming());
|
||||
}
|
||||
|
||||
public boolean shouldPerformCaptcha() {
|
||||
return shouldPerform(Sonar.get().getConfig().getVerification().getMap().getTiming());
|
||||
return shouldPerform(Sonar.get0().getConfig().getVerification().getMap().getTiming());
|
||||
}
|
||||
|
||||
private static boolean shouldPerform(final SonarConfiguration.Verification.Timing timing) {
|
||||
return timing == SonarConfiguration.Verification.Timing.ALWAYS
|
||||
|| (timing == SonarConfiguration.Verification.Timing.DURING_ATTACK
|
||||
&& Sonar.get().getAttackTracker().getCurrentAttack() != null);
|
||||
&& Sonar.get0().getAttackTracker().getCurrentAttack() != null);
|
||||
}
|
||||
}
|
||||
@@ -38,7 +38,7 @@ public final class FallbackLoginQueue {
|
||||
private final ConcurrentMap<InetAddress, Runnable> players = new ConcurrentHashMap<>(512);
|
||||
|
||||
public void poll() {
|
||||
final int maxQueuePolls = Math.min(players.size(), Sonar.get().getConfig().getQueue().getMaxQueuePolls());
|
||||
final int maxQueuePolls = Math.min(players.size(), Sonar.get0().getConfig().getQueue().getMaxQueuePolls());
|
||||
// No need to initiate an executor service task if nobody is currently queued
|
||||
if (maxQueuePolls <= 0) return;
|
||||
// We need to be cautious here since we don't want any concurrency issues
|
||||
|
||||
+19
-19
@@ -44,29 +44,29 @@ public final class ActionBarNotificationHandler extends NotificationHandler {
|
||||
}
|
||||
|
||||
// Prepare the action bar verbose
|
||||
final AttackTracker.AttackStatistics attackStatistics = Sonar.get().getAttackTracker().getCurrentAttack();
|
||||
final AttackTracker.AttackStatistics attackStatistics = Sonar.get0().getAttackTracker().getCurrentAttack();
|
||||
final SystemTimer attackTimer = attackStatistics == null ? null : attackStatistics.getDuration();
|
||||
final String attackDuration = attackTimer == null ? "00:00" : DATE_FORMATTER.format(attackTimer.delay());
|
||||
|
||||
final Component actionBarComponent = MiniMessage.miniMessage().deserialize(attackTimer == null
|
||||
? Sonar.get().getConfig().getMessagesConfig().getString("verbose.layout.normal")
|
||||
: Sonar.get().getConfig().getMessagesConfig().getString("verbose.layout.attack"),
|
||||
Placeholder.component("prefix", Sonar.get().getConfig().getPrefix()),
|
||||
? Sonar.get0().getConfig().getMessagesConfig().getString("verbose.layout.normal")
|
||||
: Sonar.get0().getConfig().getMessagesConfig().getString("verbose.layout.attack"),
|
||||
Placeholder.component("prefix", Sonar.get0().getConfig().getPrefix()),
|
||||
Placeholder.unparsed("attack-duration", attackDuration),
|
||||
Placeholder.unparsed("animation", nextAnimation()),
|
||||
Placeholder.unparsed("queued", DECIMAL_FORMAT.format(Sonar.get().getFallback().getQueue().getPlayers().size())),
|
||||
Placeholder.unparsed("verifying", DECIMAL_FORMAT.format(Sonar.get().getFallback().getConnected().size())),
|
||||
Placeholder.unparsed("blacklisted", DECIMAL_FORMAT.format(Sonar.get().getFallback().getBlacklist().estimatedSize())),
|
||||
Placeholder.unparsed("total-joins", DECIMAL_FORMAT.format(Sonar.get().getStatistics().getTotalPlayersJoined())),
|
||||
Placeholder.unparsed("logins-per-second", DECIMAL_FORMAT.format(Sonar.get().getStatistics().getLoginsPerSecond())),
|
||||
Placeholder.unparsed("connections-per-second", DECIMAL_FORMAT.format(Sonar.get().getStatistics().getConnectionsPerSecond())),
|
||||
Placeholder.unparsed("verify-total", DECIMAL_FORMAT.format(Sonar.get().getStatistics().getTotalAttemptedVerifications())),
|
||||
Placeholder.unparsed("verify-success", DECIMAL_FORMAT.format(Sonar.get().getStatistics().getTotalSuccessfulVerifications())),
|
||||
Placeholder.unparsed("verify-failed", DECIMAL_FORMAT.format(Sonar.get().getStatistics().getTotalFailedVerifications())),
|
||||
Placeholder.unparsed("incoming-traffic", Sonar.get().getStatistics().getPerSecondIncomingBandwidthFormatted()),
|
||||
Placeholder.unparsed("outgoing-traffic", Sonar.get().getStatistics().getPerSecondOutgoingBandwidthFormatted()),
|
||||
Placeholder.unparsed("incoming-traffic-ttl", formatMemory(Sonar.get().getStatistics().getTotalIncomingBandwidth())),
|
||||
Placeholder.unparsed("outgoing-traffic-ttl", formatMemory(Sonar.get().getStatistics().getTotalOutgoingBandwidth())),
|
||||
Placeholder.unparsed("queued", DECIMAL_FORMAT.format(Sonar.get0().getFallback().getQueue().getPlayers().size())),
|
||||
Placeholder.unparsed("verifying", DECIMAL_FORMAT.format(Sonar.get0().getFallback().getConnected().size())),
|
||||
Placeholder.unparsed("blacklisted", DECIMAL_FORMAT.format(Sonar.get0().getFallback().getBlacklist().estimatedSize())),
|
||||
Placeholder.unparsed("total-joins", DECIMAL_FORMAT.format(Sonar.get0().getStatistics().getTotalPlayersJoined())),
|
||||
Placeholder.unparsed("logins-per-second", DECIMAL_FORMAT.format(Sonar.get0().getStatistics().getLoginsPerSecond())),
|
||||
Placeholder.unparsed("connections-per-second", DECIMAL_FORMAT.format(Sonar.get0().getStatistics().getConnectionsPerSecond())),
|
||||
Placeholder.unparsed("verify-total", DECIMAL_FORMAT.format(Sonar.get0().getStatistics().getTotalAttemptedVerifications())),
|
||||
Placeholder.unparsed("verify-success", DECIMAL_FORMAT.format(Sonar.get0().getStatistics().getTotalSuccessfulVerifications())),
|
||||
Placeholder.unparsed("verify-failed", DECIMAL_FORMAT.format(Sonar.get0().getStatistics().getTotalFailedVerifications())),
|
||||
Placeholder.unparsed("incoming-traffic", Sonar.get0().getStatistics().getPerSecondIncomingBandwidthFormatted()),
|
||||
Placeholder.unparsed("outgoing-traffic", Sonar.get0().getStatistics().getPerSecondOutgoingBandwidthFormatted()),
|
||||
Placeholder.unparsed("incoming-traffic-ttl", formatMemory(Sonar.get0().getStatistics().getTotalIncomingBandwidth())),
|
||||
Placeholder.unparsed("outgoing-traffic-ttl", formatMemory(Sonar.get0().getStatistics().getTotalOutgoingBandwidth())),
|
||||
Placeholder.unparsed("used-memory", formatMemory(getUsedMemory())),
|
||||
Placeholder.unparsed("free-memory", formatMemory(getFreeMemory())),
|
||||
Placeholder.unparsed("total-memory", formatMemory(getTotalMemory())),
|
||||
@@ -74,7 +74,7 @@ public final class ActionBarNotificationHandler extends NotificationHandler {
|
||||
|
||||
// Send the action bar to all online players
|
||||
for (final UUID subscriber : subscribers) {
|
||||
final Audience audience = Sonar.get().audience(subscriber);
|
||||
final Audience audience = Sonar.get0().audience(subscriber);
|
||||
if (audience == null) continue;
|
||||
|
||||
// Send the action bar to all online subscribers
|
||||
@@ -83,7 +83,7 @@ public final class ActionBarNotificationHandler extends NotificationHandler {
|
||||
}
|
||||
|
||||
public String nextAnimation() {
|
||||
final var animations = Sonar.get().getConfig().getVerboseAnimation();
|
||||
final var animations = Sonar.get0().getConfig().getVerboseAnimation();
|
||||
final int nextIndex = ++animationIndex % animations.size();
|
||||
return animations.toArray(new String[0])[nextIndex];
|
||||
}
|
||||
|
||||
+19
-19
@@ -43,30 +43,30 @@ public final class ChatNotificationHandler extends NotificationHandler {
|
||||
|
||||
// Prepare the chat notification
|
||||
final Component notificationTitle = MiniMessage.miniMessage().deserialize(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("notifications.title"));
|
||||
Sonar.get0().getConfig().getMessagesConfig().getString("notifications.title"));
|
||||
final Component notificationSubtitle = MiniMessage.miniMessage().deserialize(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("notifications.subtitle"));
|
||||
Sonar.get0().getConfig().getMessagesConfig().getString("notifications.subtitle"));
|
||||
final Title title = Title.title(notificationTitle, notificationSubtitle);
|
||||
|
||||
final List<String> chatNotification = Sonar.get().getConfig().getMessagesConfig().getStringList("notifications.chat");
|
||||
final List<String> chatNotification = Sonar.get0().getConfig().getMessagesConfig().getStringList("notifications.chat");
|
||||
final Component[] chatNotificationComponents = new Component[chatNotification.size()];
|
||||
|
||||
for (int i = 0; i < chatNotificationComponents.length; i++) {
|
||||
chatNotificationComponents[i] = MiniMessage.miniMessage().deserialize(chatNotification.get(i),
|
||||
Placeholder.component("prefix", Sonar.get().getConfig().getPrefix()),
|
||||
Placeholder.unparsed("queued", DECIMAL_FORMAT.format(Sonar.get().getFallback().getQueue().getPlayers().size())),
|
||||
Placeholder.unparsed("verifying", DECIMAL_FORMAT.format(Sonar.get().getFallback().getConnected().size())),
|
||||
Placeholder.unparsed("blacklisted", DECIMAL_FORMAT.format(Sonar.get().getFallback().getBlacklist().estimatedSize())),
|
||||
Placeholder.unparsed("total-joins", DECIMAL_FORMAT.format(Sonar.get().getStatistics().getTotalPlayersJoined())),
|
||||
Placeholder.unparsed("logins-per-second", DECIMAL_FORMAT.format(Sonar.get().getStatistics().getLoginsPerSecond())),
|
||||
Placeholder.unparsed("connections-per-second", DECIMAL_FORMAT.format(Sonar.get().getStatistics().getConnectionsPerSecond())),
|
||||
Placeholder.unparsed("verify-total", DECIMAL_FORMAT.format(Sonar.get().getStatistics().getTotalAttemptedVerifications())),
|
||||
Placeholder.unparsed("verify-success", DECIMAL_FORMAT.format(Sonar.get().getStatistics().getTotalSuccessfulVerifications())),
|
||||
Placeholder.unparsed("verify-failed", DECIMAL_FORMAT.format(Sonar.get().getStatistics().getTotalFailedVerifications())),
|
||||
Placeholder.unparsed("incoming-traffic", Sonar.get().getStatistics().getPerSecondIncomingBandwidthFormatted()),
|
||||
Placeholder.unparsed("outgoing-traffic", Sonar.get().getStatistics().getPerSecondOutgoingBandwidthFormatted()),
|
||||
Placeholder.unparsed("incoming-traffic-ttl", formatMemory(Sonar.get().getStatistics().getTotalIncomingBandwidth())),
|
||||
Placeholder.unparsed("outgoing-traffic-ttl", formatMemory(Sonar.get().getStatistics().getTotalOutgoingBandwidth())),
|
||||
Placeholder.component("prefix", Sonar.get0().getConfig().getPrefix()),
|
||||
Placeholder.unparsed("queued", DECIMAL_FORMAT.format(Sonar.get0().getFallback().getQueue().getPlayers().size())),
|
||||
Placeholder.unparsed("verifying", DECIMAL_FORMAT.format(Sonar.get0().getFallback().getConnected().size())),
|
||||
Placeholder.unparsed("blacklisted", DECIMAL_FORMAT.format(Sonar.get0().getFallback().getBlacklist().estimatedSize())),
|
||||
Placeholder.unparsed("total-joins", DECIMAL_FORMAT.format(Sonar.get0().getStatistics().getTotalPlayersJoined())),
|
||||
Placeholder.unparsed("logins-per-second", DECIMAL_FORMAT.format(Sonar.get0().getStatistics().getLoginsPerSecond())),
|
||||
Placeholder.unparsed("connections-per-second", DECIMAL_FORMAT.format(Sonar.get0().getStatistics().getConnectionsPerSecond())),
|
||||
Placeholder.unparsed("verify-total", DECIMAL_FORMAT.format(Sonar.get0().getStatistics().getTotalAttemptedVerifications())),
|
||||
Placeholder.unparsed("verify-success", DECIMAL_FORMAT.format(Sonar.get0().getStatistics().getTotalSuccessfulVerifications())),
|
||||
Placeholder.unparsed("verify-failed", DECIMAL_FORMAT.format(Sonar.get0().getStatistics().getTotalFailedVerifications())),
|
||||
Placeholder.unparsed("incoming-traffic", Sonar.get0().getStatistics().getPerSecondIncomingBandwidthFormatted()),
|
||||
Placeholder.unparsed("outgoing-traffic", Sonar.get0().getStatistics().getPerSecondOutgoingBandwidthFormatted()),
|
||||
Placeholder.unparsed("incoming-traffic-ttl", formatMemory(Sonar.get0().getStatistics().getTotalIncomingBandwidth())),
|
||||
Placeholder.unparsed("outgoing-traffic-ttl", formatMemory(Sonar.get0().getStatistics().getTotalOutgoingBandwidth())),
|
||||
Placeholder.unparsed("used-memory", formatMemory(getUsedMemory())),
|
||||
Placeholder.unparsed("free-memory", formatMemory(getFreeMemory())),
|
||||
Placeholder.unparsed("total-memory", formatMemory(getTotalMemory())),
|
||||
@@ -74,8 +74,8 @@ public final class ChatNotificationHandler extends NotificationHandler {
|
||||
}
|
||||
|
||||
// Send the title and chat messages to all online players
|
||||
for (final UUID subscriber : Sonar.get().getChatNotificationHandler().getSubscribers()) {
|
||||
final Audience audience = Sonar.get().audience(subscriber);
|
||||
for (final UUID subscriber : Sonar.get0().getChatNotificationHandler().getSubscribers()) {
|
||||
final Audience audience = Sonar.get0().audience(subscriber);
|
||||
if (audience == null) continue;
|
||||
|
||||
// Send the message to all online subscribers
|
||||
|
||||
@@ -52,10 +52,10 @@ public final class AttackTracker {
|
||||
}
|
||||
|
||||
public void checkIfUnderAttack() {
|
||||
final long joinsPerSecond = Sonar.get().getStatistics().getLoginsPerSecond();
|
||||
final int verifyingPlayers = Sonar.get().getFallback().getConnected().size();
|
||||
final int queuedPlayers = Sonar.get().getFallback().getQueue().getPlayers().size();
|
||||
final int minPlayers = Sonar.get().getConfig().getMinPlayersForAttack();
|
||||
final long joinsPerSecond = Sonar.get0().getStatistics().getLoginsPerSecond();
|
||||
final int verifyingPlayers = Sonar.get0().getFallback().getConnected().size();
|
||||
final int queuedPlayers = Sonar.get0().getFallback().getQueue().getPlayers().size();
|
||||
final int minPlayers = Sonar.get0().getConfig().getMinPlayersForAttack();
|
||||
|
||||
if (joinsPerSecond > minPlayers // Check the number of bots/joins per second.
|
||||
|| verifyingPlayers > minPlayers // Check the number of verifying players.
|
||||
@@ -66,10 +66,10 @@ public final class AttackTracker {
|
||||
// An attack has been detected
|
||||
if (currentAttack == null) {
|
||||
currentAttack = new AttackStatistics();
|
||||
currentAttack.successfulVerifications = Sonar.get().getVerifiedPlayerController().getCache().size();
|
||||
currentAttack.failedVerifications = Sonar.get().getStatistics().getTotalFailedVerifications();
|
||||
Sonar.get().getEventManager().publish(new AttackDetectedEvent());
|
||||
Sonar.get().getChatNotificationHandler().handleNotification();
|
||||
currentAttack.successfulVerifications = Sonar.get0().getVerifiedPlayerController().getCache().size();
|
||||
currentAttack.failedVerifications = Sonar.get0().getStatistics().getTotalFailedVerifications();
|
||||
Sonar.get0().getEventManager().publish(new AttackDetectedEvent());
|
||||
Sonar.get0().getChatNotificationHandler().handleNotification();
|
||||
} else {
|
||||
// Reset attack timer if we're still under attack
|
||||
currentAttack.timer.reset();
|
||||
@@ -80,7 +80,7 @@ public final class AttackTracker {
|
||||
// Update joins per second peak if necessary
|
||||
currentAttack.peakJoinsPerSecond = joinsPerSecond;
|
||||
}
|
||||
final long connectionsPerSecond = Sonar.get().getStatistics().getConnectionsPerSecond();
|
||||
final long connectionsPerSecond = Sonar.get0().getStatistics().getConnectionsPerSecond();
|
||||
if (connectionsPerSecond > currentAttack.peakConnectionsPerSecond) {
|
||||
// Update connections per second peak if necessary
|
||||
currentAttack.peakConnectionsPerSecond = connectionsPerSecond;
|
||||
@@ -96,14 +96,14 @@ public final class AttackTracker {
|
||||
currentAttack.peakProcessMemoryUsage = processMemoryUsage;
|
||||
}
|
||||
} else if (currentAttack != null) {
|
||||
if (currentAttack.duration.delay() > Sonar.get().getConfig().getMinAttackDuration()
|
||||
&& currentAttack.timer.delay() > Sonar.get().getConfig().getAttackCooldownDelay()) {
|
||||
if (currentAttack.duration.delay() > Sonar.get0().getConfig().getMinAttackDuration()
|
||||
&& currentAttack.timer.delay() > Sonar.get0().getConfig().getAttackCooldownDelay()) {
|
||||
// The current attack has stopped
|
||||
Sonar.get().getEventManager().publish(new AttackMitigatedEvent(currentAttack));
|
||||
Sonar.get0().getEventManager().publish(new AttackMitigatedEvent(currentAttack));
|
||||
|
||||
if (++attackThreshold > Sonar.get().getConfig().getMinAttackThreshold()) {
|
||||
if (++attackThreshold > Sonar.get0().getConfig().getMinAttackThreshold()) {
|
||||
// Post webhook to Discord
|
||||
Optional.ofNullable(Sonar.get().getConfig().getWebhook().getDiscordWebhook())
|
||||
Optional.ofNullable(Sonar.get0().getConfig().getWebhook().getDiscordWebhook())
|
||||
.ifPresent(webhook -> {
|
||||
// Save attack statistics
|
||||
final long deltaInMillis = currentAttack.duration.delay();
|
||||
@@ -116,15 +116,15 @@ public final class AttackTracker {
|
||||
final String formattedDuration = String.format("%d minutes, %.0f seconds", minutes, seconds);
|
||||
final String startTimestamp = String.valueOf(currentAttack.duration.getStart() / 1000L);
|
||||
final String endTimestamp = String.valueOf(System.currentTimeMillis() / 1000L);
|
||||
final long blacklisted = Sonar.get().getFallback().getBlacklist().estimatedSize();
|
||||
final long blacklisted = Sonar.get0().getFallback().getBlacklist().estimatedSize();
|
||||
// Calculate during-attack-statistics using their deltas
|
||||
final long totalVerified = Sonar.get().getVerifiedPlayerController().getCache().size();
|
||||
final long totalVerified = Sonar.get0().getVerifiedPlayerController().getCache().size();
|
||||
final long verified = Math.max(totalVerified - currentAttack.successfulVerifications, 0);
|
||||
final long totalFailed = Sonar.get().getStatistics().getTotalFailedVerifications();
|
||||
final long totalFailed = Sonar.get0().getStatistics().getTotalFailedVerifications();
|
||||
final long failed = Math.max(totalFailed - currentAttack.failedVerifications, 0);
|
||||
|
||||
webhook.post(() -> {
|
||||
final SonarConfiguration.Webhook.Embed config = Sonar.get().getConfig().getWebhook().getEmbed();
|
||||
final SonarConfiguration.Webhook.Embed config = Sonar.get0().getConfig().getWebhook().getEmbed();
|
||||
final String description = config.getDescription()
|
||||
.replace("<start-timestamp>", startTimestamp)
|
||||
.replace("<end-timestamp>", endTimestamp)
|
||||
|
||||
@@ -48,23 +48,23 @@ public class UpdateChecker {
|
||||
final JsonObject json = parseJson(urlConnection);
|
||||
final String latestStableRelease = json.get("tag_name").getAsString();
|
||||
final int convertedLatestVersion = convertVersion(latestStableRelease);
|
||||
final int convertedCurrentVersion = convertVersion(Sonar.get().getVersion().getVersion());
|
||||
final int convertedCurrentVersion = convertVersion(Sonar.get0().getVersion().getVersion());
|
||||
|
||||
if (convertedCurrentVersion < convertedLatestVersion) {
|
||||
Sonar.get().getLogger().warn("A new version of Sonar is available: {}", latestStableRelease);
|
||||
Sonar.get().getLogger().warn("Please make sure to update to the latest version to ensure stability and security:");
|
||||
Sonar.get().getLogger().warn("https://github.com/jonesdevelopment/sonar/releases/latest");
|
||||
Sonar.get0().getLogger().warn("A new version of Sonar is available: {}", latestStableRelease);
|
||||
Sonar.get0().getLogger().warn("Please make sure to update to the latest version to ensure stability and security:");
|
||||
Sonar.get0().getLogger().warn("https://github.com/jonesdevelopment/sonar/releases/latest");
|
||||
lastCheckResult = CheckResult.OUTDATED_VERSION;
|
||||
} else if (convertedCurrentVersion > convertedLatestVersion || !Sonar.get().getVersion().getGitBranch().equals("main")) {
|
||||
Sonar.get().getLogger().warn("You are currently using an unreleased version of Sonar!");
|
||||
Sonar.get().getLogger().warn("The contributors of Sonar are not responsible for any damage done by using an unstable version");
|
||||
} else if (convertedCurrentVersion > convertedLatestVersion || !Sonar.get0().getVersion().getGitBranch().equals("main")) {
|
||||
Sonar.get0().getLogger().warn("You are currently using an unreleased version of Sonar!");
|
||||
Sonar.get0().getLogger().warn("The contributors of Sonar are not responsible for any damage done by using an unstable version");
|
||||
lastCheckResult = CheckResult.UNSTABLE_VERSION;
|
||||
} else if (lastCheckResult != CheckResult.LATEST_VERSION) {
|
||||
Sonar.get().getLogger().info("You are currently using the latest stable release of Sonar!");
|
||||
Sonar.get0().getLogger().info("You are currently using the latest stable release of Sonar!");
|
||||
lastCheckResult = CheckResult.LATEST_VERSION;
|
||||
}
|
||||
} catch (Throwable throwable) {
|
||||
Sonar.get().getLogger().warn("Unable to retrieve version information: {}", throwable);
|
||||
Sonar.get0().getLogger().warn("Unable to retrieve version information: {}", throwable);
|
||||
lastCheckResult = CheckResult.API_ERROR;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -59,18 +59,18 @@ public final class DiscordWebhook {
|
||||
// Discord replies with HTTP_NO_CONTENT (204) if the request is successful
|
||||
final int code = urlConnection.getResponseCode();
|
||||
if (code != HTTP_NO_CONTENT) {
|
||||
Sonar.get().getLogger().warn("Unexpected Discord webhook response code {}", code);
|
||||
Sonar.get0().getLogger().warn("Unexpected Discord webhook response code {}", code);
|
||||
}
|
||||
} catch (Exception exception) {
|
||||
Sonar.get().getLogger().error("Could not send webhook: {}", exception);
|
||||
Sonar.get0().getLogger().error("Could not send webhook: {}", exception);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static String prepareSerializedContent(final SonarConfiguration.Webhook.@NotNull Embed embed) {
|
||||
final String content = Sonar.get().getConfig().getWebhook().getContent();
|
||||
final String username = Sonar.get().getConfig().getWebhook().getUsername();
|
||||
final String avatarUrl = Sonar.get().getConfig().getWebhook().getAvatarUrl();
|
||||
final String content = Sonar.get0().getConfig().getWebhook().getContent();
|
||||
final String username = Sonar.get0().getConfig().getWebhook().getUsername();
|
||||
final String avatarUrl = Sonar.get0().getConfig().getWebhook().getAvatarUrl();
|
||||
|
||||
int rgb = embed.getR();
|
||||
rgb = (rgb << 8) + embed.getG();
|
||||
@@ -78,8 +78,8 @@ public final class DiscordWebhook {
|
||||
|
||||
final Webhook.EmbedMessage embedMessage = new Webhook.EmbedMessage(
|
||||
embed.getTitle(), embed.getDescription(), embed.getTitleUrl(), rgb, new Webhook.Field[0],
|
||||
new Webhook.Footer(Sonar.get().getConfig().getWebhook().getFooter().getText(),
|
||||
Sonar.get().getConfig().getWebhook().getFooter().getIconUrl()));
|
||||
new Webhook.Footer(Sonar.get0().getConfig().getWebhook().getFooter().getText(),
|
||||
Sonar.get0().getConfig().getWebhook().getFooter().getIconUrl()));
|
||||
final List<Webhook.EmbedMessage> embeds = Collections.singletonList(embedMessage);
|
||||
|
||||
final Webhook webhook = new Webhook(content, username, avatarUrl, false, embeds);
|
||||
|
||||
@@ -40,7 +40,7 @@ public final class BukkitSonarCommand implements CommandExecutor, TabExecutor, S
|
||||
// Create our own invocation source wrapper to handle messages properly
|
||||
final InvocationSource invocationSource = new InvocationSource(
|
||||
sender instanceof Player ? ((Player) sender).getUniqueId() : null,
|
||||
Sonar.get().sender(sender),
|
||||
Sonar.get0().sender(sender),
|
||||
sender::hasPermission);
|
||||
// Pass the invocation source and command arguments to our command handler
|
||||
handle(invocationSource, args);
|
||||
|
||||
@@ -267,7 +267,7 @@ public class FallbackBukkitInjector {
|
||||
return;
|
||||
}
|
||||
} catch (Exception exception) {
|
||||
Sonar.get().getLogger().error("An error occurred while injecting {}", exception);
|
||||
Sonar.get0().getLogger().error("An error occurred while injecting {}", exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -92,7 +92,7 @@ public final class BukkitJoinListener implements Listener {
|
||||
channel.close();
|
||||
}
|
||||
} catch (Throwable throwable) {
|
||||
Sonar.get().getLogger().warn("Couldn't find {}: {}", event.getPlayer().getName(), throwable);
|
||||
Sonar.get0().getLogger().warn("Couldn't find {}: {}", event.getPlayer().getName(), throwable);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -86,6 +86,10 @@ public final class SonarBungee extends SonarBootstrap<SonarBungeePlugin> {
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
// Add warning because of questionable design choices that haunt me in my dreams.
|
||||
logger.warn("The use of BungeeCord is supported but not condoned.");
|
||||
logger.warn("Consider upgrading to Velocity (https://velocitypowered.com)");
|
||||
|
||||
// Initialize bStats.org metrics
|
||||
metrics = new Metrics(getPlugin(), getPlatform().getMetricsId());
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ public final class BungeeSonarCommand extends Command implements TabExecutor, So
|
||||
// Create our own invocation source wrapper to handle messages properly
|
||||
final InvocationSource invocationSource = new InvocationSource(
|
||||
sender instanceof ProxiedPlayer ? ((ProxiedPlayer) sender).getUniqueId() : null,
|
||||
Sonar.get().sender(sender),
|
||||
Sonar.get0().sender(sender),
|
||||
sender::hasPermission);
|
||||
// Pass the invocation source and command arguments to our command handler
|
||||
handle(invocationSource, args);
|
||||
|
||||
+55
-18
@@ -20,7 +20,11 @@ package xyz.jonesdev.sonar.bungee.fallback;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import lombok.val;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.netty.PipelineUtils;
|
||||
import net.md_5.bungee.protocol.channel.BungeeChannelInitializer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import sun.misc.Unsafe;
|
||||
import xyz.jonesdev.sonar.api.Sonar;
|
||||
import xyz.jonesdev.sonar.common.fallback.netty.FallbackInjectedChannelInitializer;
|
||||
@@ -34,26 +38,59 @@ import static xyz.jonesdev.sonar.api.fallback.FallbackPipelines.FALLBACK_PACKET_
|
||||
public class FallbackBungeeInjector {
|
||||
public void inject() {
|
||||
try {
|
||||
final Field childField = PipelineUtils.class.getField("SERVER_CHILD");
|
||||
final Field childField;
|
||||
|
||||
try {
|
||||
// This field only exists on BungeeCord build 1908 and below.
|
||||
// See https://github.com/SpigotMC/BungeeCord/pull/3776 for more info.
|
||||
//noinspection all
|
||||
childField = PipelineUtils.class.getField("SERVER_CHILD");
|
||||
} catch (NoSuchFieldException exception) {
|
||||
injectOnModernBungeeCord();
|
||||
return;
|
||||
}
|
||||
|
||||
childField.setAccessible(true);
|
||||
|
||||
// Make sure to store the original channel initializer
|
||||
final ChannelInitializer<Channel> originalInitializer = PipelineUtils.SERVER_CHILD;
|
||||
final ChannelInitializer<Channel> injectedInitializer = new FallbackInjectedChannelInitializer(
|
||||
originalInitializer, pipeline -> pipeline.addAfter(PACKET_DECODER, FALLBACK_PACKET_HANDLER,
|
||||
new FallbackBungeeInboundHandler()));
|
||||
|
||||
final Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
|
||||
unsafeField.setAccessible(true);
|
||||
final Unsafe unsafe = (Unsafe) unsafeField.get(null);
|
||||
|
||||
final Object base = unsafe.staticFieldBase(childField);
|
||||
final long offset = unsafe.staticFieldOffset(childField);
|
||||
|
||||
// Replace the original channel initializer with our new injected initializer
|
||||
unsafe.putObject(base, offset, injectedInitializer);
|
||||
injectOnOldBungeeCord(childField);
|
||||
} catch (Exception exception) {
|
||||
Sonar.get().getLogger().error("An error occurred while injecting {}", exception);
|
||||
Sonar.get0().getLogger().error("An error occurred while injecting {}", exception);
|
||||
}
|
||||
}
|
||||
|
||||
private static void injectOnOldBungeeCord(final @NotNull Field childField) throws Exception {
|
||||
// Make sure to store the original channel initializer
|
||||
//noinspection unchecked
|
||||
val originalInitializer = (ChannelInitializer<Channel>) childField.get(null);
|
||||
final ChannelInitializer<Channel> injectedInitializer = new FallbackInjectedChannelInitializer(
|
||||
originalInitializer, pipeline -> pipeline.addAfter(PACKET_DECODER, FALLBACK_PACKET_HANDLER,
|
||||
new FallbackBungeeInboundHandler()));
|
||||
|
||||
final Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
|
||||
unsafeField.setAccessible(true);
|
||||
final Unsafe unsafe = (Unsafe) unsafeField.get(null);
|
||||
|
||||
final Object base = unsafe.staticFieldBase(childField);
|
||||
final long offset = unsafe.staticFieldOffset(childField);
|
||||
|
||||
// Replace the original channel initializer with our new injected initializer
|
||||
unsafe.putObject(base, offset, injectedInitializer);
|
||||
}
|
||||
|
||||
// See https://github.com/SpigotMC/BungeeCord/pull/3787
|
||||
private static void injectOnModernBungeeCord() {
|
||||
// The order is important...
|
||||
final BungeeChannelInitializer original = ProxyServer.getInstance().unsafe().getFrontendChannelInitializer();
|
||||
final BungeeChannelInitializer newInitializer = BungeeChannelInitializer.create(
|
||||
channel -> {
|
||||
// https://github.com/SpigotMC/BungeeCord/pull/3787#issuecomment-2661059876
|
||||
if (!original.getChannelAcceptor().accept(channel)) {
|
||||
return false;
|
||||
}
|
||||
FallbackInjectedChannelInitializer.inject(channel,
|
||||
pipeline -> pipeline.addAfter(PACKET_DECODER, FALLBACK_PACKET_HANDLER,
|
||||
new FallbackBungeeInboundHandler()));
|
||||
return true;
|
||||
});
|
||||
ProxyServer.getInstance().unsafe().setFrontendChannelInitializer(newInitializer);
|
||||
}
|
||||
}
|
||||
@@ -55,11 +55,11 @@ public final class FallbackInboundHandler extends ChannelInboundHandlerAdapter {
|
||||
// Account for this by checking if the inetAddress has been set yet
|
||||
if (inetAddress != null) {
|
||||
// Remove the IP address from the queue
|
||||
Sonar.get().getFallback().getQueue().getPlayers().compute(inetAddress, (ignored, action) -> {
|
||||
Sonar.get0().getFallback().getQueue().getPlayers().compute(inetAddress, (ignored, action) -> {
|
||||
// The player is not queued, so we need to remove them from other maps as well
|
||||
if (action == null) {
|
||||
// Remove the IP address from the connected players, if needed
|
||||
Sonar.get().getFallback().getConnected().compute(inetAddress, (__, v) -> {
|
||||
Sonar.get0().getFallback().getConnected().compute(inetAddress, (__, v) -> {
|
||||
/*
|
||||
* Remove this account from the online players or decrement the number of accounts
|
||||
* with the same IP, but only if the player is logging into the backend server.
|
||||
@@ -67,7 +67,7 @@ public final class FallbackInboundHandler extends ChannelInboundHandlerAdapter {
|
||||
* we've never actually incremented it in the first place ¯\_(ツ)_/¯
|
||||
*/
|
||||
if (v == null) {
|
||||
Sonar.get().getFallback().getOnline().compute(inetAddress,
|
||||
Sonar.get0().getFallback().getOnline().compute(inetAddress,
|
||||
(ignored1, count) -> count == null || count <= 1 ? null : count - 1);
|
||||
}
|
||||
return null;
|
||||
|
||||
+15
-15
@@ -97,22 +97,22 @@ public abstract class FallbackInboundHandlerAdapter extends ChannelInboundHandle
|
||||
ctx.pipeline().get(FallbackInboundHandler.class).setInetAddress(inetAddress);
|
||||
|
||||
// Check if Fallback is already verifying a player with the same IP address
|
||||
if (Sonar.get().getFallback().getConnected().containsKey(inetAddress)) {
|
||||
if (Sonar.get0().getFallback().getConnected().containsKey(inetAddress)) {
|
||||
customDisconnect(ctx.channel(), alreadyVerifying, protocolVersion);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the protocol ID of the player is not allowed to enter the server
|
||||
if (Sonar.get().getConfig().getVerification().getBlacklistedProtocols().contains(protocolVersion.getProtocol())) {
|
||||
if (Sonar.get0().getConfig().getVerification().getBlacklistedProtocols().contains(protocolVersion.getProtocol())) {
|
||||
customDisconnect(ctx.channel(), protocolBlacklisted, protocolVersion);
|
||||
return;
|
||||
}
|
||||
|
||||
final String hostAddress = inetAddress.getHostAddress();
|
||||
// Check if the player failed the verification too many times
|
||||
final int limit = Sonar.get().getConfig().getVerification().getBlacklistThreshold();
|
||||
final int limit = Sonar.get0().getConfig().getVerification().getBlacklistThreshold();
|
||||
if (limit > 0) {
|
||||
final int score = Sonar.get().getFallback().getBlacklist().asMap().getOrDefault(hostAddress, 0);
|
||||
final int score = Sonar.get0().getFallback().getBlacklist().asMap().getOrDefault(hostAddress, 0);
|
||||
if (score >= limit) {
|
||||
customDisconnect(ctx.channel(), blacklisted, protocolVersion);
|
||||
return;
|
||||
@@ -120,27 +120,27 @@ public abstract class FallbackInboundHandlerAdapter extends ChannelInboundHandle
|
||||
}
|
||||
|
||||
// Don't continue the verification process if the verification is disabled
|
||||
if (!Sonar.get().getFallback().shouldVerifyNewPlayers()) {
|
||||
if (!Sonar.get0().getFallback().shouldVerifyNewPlayers()) {
|
||||
initialLogin(ctx.channel(), inetAddress, initialLoginAction);
|
||||
return;
|
||||
}
|
||||
|
||||
// Completely skip Geyser connections if configured
|
||||
final boolean geyser = GeyserUtil.isGeyserConnection(ctx.channel(), socketAddress);
|
||||
if (geyser && !Sonar.get().getConfig().getVerification().isCheckGeyser()) {
|
||||
if (geyser && !Sonar.get0().getConfig().getVerification().isCheckGeyser()) {
|
||||
initialLogin(ctx.channel(), inetAddress, initialLoginAction);
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure we actually have to verify the player
|
||||
final String fingerprint = FingerprintingUtil.getFingerprint(username, hostAddress);
|
||||
if (Sonar.get().getVerifiedPlayerController().getCache().contains(fingerprint)) {
|
||||
if (Sonar.get0().getVerifiedPlayerController().getCache().contains(fingerprint)) {
|
||||
initialLogin(ctx.channel(), inetAddress, initialLoginAction);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the IP address is currently being rate-limited
|
||||
if (!Sonar.get().getFallback().getRatelimiter().attempt(inetAddress)) {
|
||||
if (!Sonar.get0().getFallback().getRatelimiter().attempt(inetAddress)) {
|
||||
customDisconnect(ctx.channel(), reconnectedTooFast, protocolVersion);
|
||||
return;
|
||||
}
|
||||
@@ -149,7 +149,7 @@ public abstract class FallbackInboundHandlerAdapter extends ChannelInboundHandle
|
||||
rewriteProtocol(ctx, channelRemovalListener);
|
||||
|
||||
// Queue the connection for further processing
|
||||
Sonar.get().getFallback().getQueue().getPlayers().compute(inetAddress, (__, runnable) -> {
|
||||
Sonar.get0().getFallback().getQueue().getPlayers().compute(inetAddress, (__, runnable) -> {
|
||||
// Check if the player is already queued since we don't want bots to flood the queue
|
||||
if (runnable != null) {
|
||||
customDisconnect(ctx.channel(), alreadyQueued, protocolVersion);
|
||||
@@ -168,8 +168,8 @@ public abstract class FallbackInboundHandlerAdapter extends ChannelInboundHandle
|
||||
protected final void initialLogin(final @NotNull Channel channel,
|
||||
final @NotNull InetAddress inetAddress,
|
||||
final @NotNull Runnable loginPacket) throws Exception {
|
||||
Sonar.get().getFallback().getOnline().compute(inetAddress, (__, count) -> {
|
||||
final int maxOnlinePerIp = Sonar.get().getConfig().getMaxOnlinePerIp();
|
||||
Sonar.get0().getFallback().getOnline().compute(inetAddress, (__, count) -> {
|
||||
final int maxOnlinePerIp = Sonar.get0().getConfig().getMaxOnlinePerIp();
|
||||
// Skip the maximum online per IP check if it's disabled in the configuration
|
||||
if (count != null && maxOnlinePerIp > 0) {
|
||||
// Check if the number of online players using the same IP address as
|
||||
@@ -206,8 +206,8 @@ public abstract class FallbackInboundHandlerAdapter extends ChannelInboundHandle
|
||||
}
|
||||
// Add our read/write timeout handler
|
||||
ctx.pipeline().addFirst(FALLBACK_TIMEOUT, new FallbackTimeoutHandler(
|
||||
Sonar.get().getConfig().getVerification().getReadTimeout(),
|
||||
Sonar.get().getConfig().getVerification().getWriteTimeout(),
|
||||
Sonar.get0().getConfig().getVerification().getReadTimeout(),
|
||||
Sonar.get0().getConfig().getVerification().getWriteTimeout(),
|
||||
TimeUnit.MILLISECONDS));
|
||||
}
|
||||
|
||||
@@ -231,11 +231,11 @@ public abstract class FallbackInboundHandlerAdapter extends ChannelInboundHandle
|
||||
final @NotNull ProtocolVersion protocolVersion) {
|
||||
// TODO: recode this
|
||||
// Remove the connection handler pipeline to completely take over the channel
|
||||
final String handler = Sonar.get().getPlatform().getConnectionHandler();
|
||||
final String handler = Sonar.get0().getPlatform().getConnectionHandler();
|
||||
if (channel.pipeline().context(handler) != null) {
|
||||
channel.pipeline().remove(handler);
|
||||
}
|
||||
final String encoder = Sonar.get().getPlatform().getEncoder().apply(channel.pipeline());
|
||||
final String encoder = Sonar.get0().getPlatform().getEncoder().apply(channel.pipeline());
|
||||
final ChannelHandler currentEncoder = channel.pipeline().get(encoder);
|
||||
// Close the channel if no encoder exists
|
||||
if (currentEncoder != null) {
|
||||
|
||||
@@ -76,18 +76,18 @@ public final class FallbackUserWrapper implements FallbackUser {
|
||||
|
||||
GlobalSonarStatistics.totalAttemptedVerifications++;
|
||||
|
||||
if (Sonar.get().getConfig().getVerification().isLogConnections()
|
||||
&& (Sonar.get().getAttackTracker().getCurrentAttack() == null
|
||||
|| Sonar.get().getConfig().getVerification().isLogDuringAttack())) {
|
||||
Sonar.get().getLogger().info(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("verification.logs.connection")
|
||||
if (Sonar.get0().getConfig().getVerification().isLogConnections()
|
||||
&& (Sonar.get0().getAttackTracker().getCurrentAttack() == null
|
||||
|| Sonar.get0().getConfig().getVerification().isLogDuringAttack())) {
|
||||
Sonar.get0().getLogger().info(
|
||||
Sonar.get0().getConfig().getMessagesConfig().getString("verification.logs.connection")
|
||||
.replace("<username>", username)
|
||||
.replace("<ip>", Sonar.get().getConfig().formatAddress(inetAddress))
|
||||
.replace("<ip>", Sonar.get0().getConfig().formatAddress(inetAddress))
|
||||
.replace("<protocol>", protocolVersion.getName()));
|
||||
}
|
||||
|
||||
// Call the VerifyJoinEvent for external API usage
|
||||
Sonar.get().getEventManager().publish(new UserVerifyJoinEvent(this));
|
||||
Sonar.get0().getEventManager().publish(new UserVerifyJoinEvent(this));
|
||||
|
||||
// Run this in the channel's event loop to avoid issues
|
||||
channel.eventLoop().execute(() -> {
|
||||
@@ -97,7 +97,7 @@ public final class FallbackUserWrapper implements FallbackUser {
|
||||
}
|
||||
|
||||
// Mark the player as connected by caching them in a map of verifying players
|
||||
Sonar.get().getFallback().getConnected().compute(inetAddress, (__, v) -> true);
|
||||
Sonar.get0().getFallback().getConnected().compute(inetAddress, (__, v) -> true);
|
||||
|
||||
// Replace normal encoder to allow custom packets
|
||||
final FallbackPacketEncoder newEncoder = new FallbackPacketEncoder(protocolVersion);
|
||||
|
||||
+6
-2
@@ -60,13 +60,17 @@ public final class FallbackInjectedChannelInitializer extends ChannelInitializer
|
||||
throw new ReflectiveOperationException(throwable);
|
||||
}
|
||||
|
||||
inject(channel, sonarPipelineInjector);
|
||||
}
|
||||
|
||||
public static void inject(final @NotNull Channel channel, final Consumer<ChannelPipeline> sonarPipelineInjector) {
|
||||
// Inject Sonar's channel handler into the pipeline;
|
||||
// Also make sure the player is not a fake player to avoid compatibility issues
|
||||
if (channel.isActive() && !FakeChannelUtil.isFakeChannel(channel)) {
|
||||
final FallbackInboundHandler inboundHandler = new FallbackInboundHandler(sonarPipelineInjector);
|
||||
// We need to be careful on Bukkit, as the encoder can be different
|
||||
if (Sonar.get().getPlatform() == SonarPlatform.BUKKIT) {
|
||||
final String encoder = Sonar.get().getPlatform().getEncoder().apply(channel.pipeline());
|
||||
if (Sonar.get0().getPlatform() == SonarPlatform.BUKKIT) {
|
||||
final String encoder = Sonar.get0().getPlatform().getEncoder().apply(channel.pipeline());
|
||||
channel.pipeline().addBefore(encoder, FALLBACK_INBOUND_HANDLER, inboundHandler);
|
||||
} else {
|
||||
channel.pipeline().addFirst(FALLBACK_INBOUND_HANDLER, inboundHandler);
|
||||
|
||||
+7
-7
@@ -44,12 +44,12 @@ public class CaptchaPreparer {
|
||||
}
|
||||
|
||||
final SystemTimer timer = new SystemTimer();
|
||||
Sonar.get().getLogger().info("Asynchronously preparing CAPTCHA answers...");
|
||||
Sonar.get().getLogger().info("Players will be able to join even if the preparation isn't finished");
|
||||
Sonar.get0().getLogger().info("Asynchronously preparing CAPTCHA answers...");
|
||||
Sonar.get0().getLogger().info("Players will be able to join even if the preparation isn't finished");
|
||||
|
||||
// Prepare cache
|
||||
final int precomputeAmount = Sonar.get().getConfig().getVerification().getMap().getPrecomputeAmount();
|
||||
final char[] alphabet = Sonar.get().getConfig().getVerification().getMap().getAlphabet().toCharArray();
|
||||
final int precomputeAmount = Sonar.get0().getConfig().getVerification().getMap().getPrecomputeAmount();
|
||||
final char[] alphabet = Sonar.get0().getConfig().getVerification().getMap().getAlphabet().toCharArray();
|
||||
|
||||
preparedAmount = 0;
|
||||
cached = new MapCaptchaInfo[precomputeAmount];
|
||||
@@ -62,13 +62,13 @@ public class CaptchaPreparer {
|
||||
for (int j = 0; j < answer.length; j++) {
|
||||
answer[j] = alphabet[RANDOM.nextInt(alphabet.length)];
|
||||
}
|
||||
final BufferedImage image = Sonar.get().getFallback().getCaptchaGenerator().createImage(answer);
|
||||
final BufferedImage image = Sonar.get0().getFallback().getCaptchaGenerator().createImage(answer);
|
||||
// Convert and cache converted Minecraft map bytes
|
||||
cached[preparedAmount++] = new MapCaptchaInfo(new String(answer), MapColorPalette.imageToBuffer(image));
|
||||
}
|
||||
|
||||
Sonar.get().getLogger().info("Finished preparing {} CAPTCHA answers ({}s)!", preparedAmount, timer);
|
||||
Sonar.get().getEventManager().publish(new CaptchaGenerationEndEvent(timer, preparedAmount));
|
||||
Sonar.get0().getLogger().info("Finished preparing {} CAPTCHA answers ({}s)!", preparedAmount, timer);
|
||||
Sonar.get0().getEventManager().publish(new CaptchaGenerationEndEvent(timer, preparedAmount));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@ public final class FallbackPacketSnapshot implements FallbackPacket {
|
||||
try {
|
||||
originalPacket.encode(byteBuf, protocolVersion);
|
||||
} catch (Throwable throwable) {
|
||||
Sonar.get().getLogger().error("Could not encode packet {} for version {}: {}",
|
||||
Sonar.get0().getLogger().error("Could not encode packet {} for version {}: {}",
|
||||
originalPacket, protocolVersion, throwable);
|
||||
break;
|
||||
}
|
||||
|
||||
+34
-34
@@ -119,15 +119,15 @@ public class FallbackPreparer {
|
||||
|
||||
public static int maxMovementTick, dynamicSpawnYPosition, maxTotalPacketsSent;
|
||||
|
||||
@SuppressWarnings("ResultOfMethodCallIgnored")
|
||||
public void prepare() {
|
||||
// Preload the packet registry to avoid CPU/RAM issues on 1st connection
|
||||
Sonar.get().getLogger().info("Preloading all registered packets...");
|
||||
Sonar.get0().getLogger().info("Preloading all registered packets...");
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
FallbackPacketRegistry.values();
|
||||
|
||||
// Prepare LoginSuccess packet with capped username to 16 characters
|
||||
final UUID uuid = UUID.randomUUID();
|
||||
String username = Sonar.get().getConfig().getGeneralConfig().getString("verification.cached-username");
|
||||
String username = Sonar.get0().getConfig().getGeneralConfig().getString("verification.cached-username");
|
||||
if (username.length() > 16) {
|
||||
username = username.substring(0, 16);
|
||||
}
|
||||
@@ -135,16 +135,16 @@ public class FallbackPreparer {
|
||||
|
||||
// Prepare JoinGame packet
|
||||
joinGame = new FallbackPacketSnapshot(new JoinGamePacket(PLAYER_ENTITY_ID,
|
||||
Sonar.get().getConfig().getVerification().getGamemode().getId(),
|
||||
Sonar.get0().getConfig().getVerification().getGamemode().getId(),
|
||||
-1, 0, 0,
|
||||
RANDOM.nextInt(3), 1, 0, 0,
|
||||
new String[]{"lol"}, "lol", "flat",
|
||||
new String[]{"minecraft:overworld"}, "minecraft:overworld", "flat",
|
||||
DimensionType.OVERWORLD, RANDOM.nextLong() & 1337,
|
||||
false, true, false,
|
||||
false, false, false, true));
|
||||
|
||||
// Prepare the gravity check
|
||||
maxMovementTick = Sonar.get().getConfig().getVerification().getGravity().getMaxMovementTicks();
|
||||
maxMovementTick = Sonar.get0().getConfig().getVerification().getGravity().getMaxMovementTicks();
|
||||
|
||||
double motionY = 0, fallDistance = 0;
|
||||
|
||||
@@ -184,25 +184,25 @@ public class FallbackPreparer {
|
||||
}
|
||||
|
||||
// Prepare disconnect packets during login
|
||||
blacklisted = new FallbackPacketSnapshot(new DisconnectPacket(Sonar.get().getConfig().getVerification().getBlacklisted(), true));
|
||||
alreadyVerifying = new FallbackPacketSnapshot(new DisconnectPacket(Sonar.get().getConfig().getVerification().getAlreadyVerifying(), true));
|
||||
alreadyQueued = new FallbackPacketSnapshot(new DisconnectPacket(Sonar.get().getConfig().getVerification().getAlreadyQueued(), true));
|
||||
protocolBlacklisted = new FallbackPacketSnapshot(new DisconnectPacket(Sonar.get().getConfig().getVerification().getProtocolBlacklisted(), true));
|
||||
reconnectedTooFast = new FallbackPacketSnapshot(new DisconnectPacket(Sonar.get().getConfig().getVerification().getTooFastReconnect(), true));
|
||||
unsupportedVersion = new FallbackPacketSnapshot(new DisconnectPacket(Sonar.get().getConfig().getVerification().getUnsupportedVersion(), true));
|
||||
tooManyOnlinePerIP = new FallbackPacketSnapshot(new DisconnectPacket(Sonar.get().getConfig().getTooManyOnlinePerIp(), true));
|
||||
blacklisted = new FallbackPacketSnapshot(new DisconnectPacket(Sonar.get0().getConfig().getVerification().getBlacklisted(), true));
|
||||
alreadyVerifying = new FallbackPacketSnapshot(new DisconnectPacket(Sonar.get0().getConfig().getVerification().getAlreadyVerifying(), true));
|
||||
alreadyQueued = new FallbackPacketSnapshot(new DisconnectPacket(Sonar.get0().getConfig().getVerification().getAlreadyQueued(), true));
|
||||
protocolBlacklisted = new FallbackPacketSnapshot(new DisconnectPacket(Sonar.get0().getConfig().getVerification().getProtocolBlacklisted(), true));
|
||||
reconnectedTooFast = new FallbackPacketSnapshot(new DisconnectPacket(Sonar.get0().getConfig().getVerification().getTooFastReconnect(), true));
|
||||
unsupportedVersion = new FallbackPacketSnapshot(new DisconnectPacket(Sonar.get0().getConfig().getVerification().getUnsupportedVersion(), true));
|
||||
tooManyOnlinePerIP = new FallbackPacketSnapshot(new DisconnectPacket(Sonar.get0().getConfig().getTooManyOnlinePerIp(), true));
|
||||
|
||||
// Prepare transfer packet
|
||||
if (Sonar.get().getConfig().getGeneralConfig().getBoolean("verification.transfer.enabled")) {
|
||||
if (Sonar.get0().getConfig().getGeneralConfig().getBoolean("verification.transfer.enabled")) {
|
||||
transferToOrigin = new FallbackPacketSnapshot(new TransferPacket(
|
||||
Sonar.get().getConfig().getGeneralConfig().getString("verification.transfer.destination-host"),
|
||||
Sonar.get().getConfig().getGeneralConfig().getInt("verification.transfer.destination-port")));
|
||||
Sonar.get0().getConfig().getGeneralConfig().getString("verification.transfer.destination-host"),
|
||||
Sonar.get0().getConfig().getGeneralConfig().getInt("verification.transfer.destination-port")));
|
||||
} else {
|
||||
transferToOrigin = null;
|
||||
}
|
||||
|
||||
// Prepare update time packet
|
||||
final int timeOfDay = Sonar.get().getConfig().getVerification().getTimeOfDay();
|
||||
final int timeOfDay = Sonar.get0().getConfig().getVerification().getTimeOfDay();
|
||||
if (timeOfDay != 1000) {
|
||||
updateTime = new UpdateTimePacket(0L, timeOfDay, false);
|
||||
} else {
|
||||
@@ -210,29 +210,29 @@ public class FallbackPreparer {
|
||||
}
|
||||
|
||||
// If the welcome message is empty, we don't need to send a message to the player
|
||||
final String welcome = Sonar.get().getConfig().getMessagesConfig().getString("verification.welcome");
|
||||
final String welcome = Sonar.get0().getConfig().getMessagesConfig().getString("verification.welcome");
|
||||
if (welcome.isEmpty()) {
|
||||
welcomeMessage = null;
|
||||
} else {
|
||||
welcomeMessage = new FallbackPacketSnapshot(new SystemChatPacket(new ComponentHolder(
|
||||
MiniMessage.miniMessage().deserialize(welcome,
|
||||
Placeholder.component("prefix", Sonar.get().getConfig().getPrefix())))));
|
||||
Placeholder.component("prefix", Sonar.get0().getConfig().getPrefix())))));
|
||||
}
|
||||
|
||||
if (Sonar.get().getConfig().getVerification().getMap().getTiming() != SonarConfiguration.Verification.Timing.NEVER
|
||||
|| Sonar.get().getConfig().getVerification().getGravity().isCaptchaOnFail()) {
|
||||
if (Sonar.get0().getConfig().getVerification().getMap().getTiming() != SonarConfiguration.Verification.Timing.NEVER
|
||||
|| Sonar.get0().getConfig().getVerification().getGravity().isCaptchaOnFail()) {
|
||||
// Prepare CAPTCHA messages
|
||||
enterCodeMessage = new FallbackPacketSnapshot(new SystemChatPacket(new ComponentHolder(
|
||||
MiniMessage.miniMessage().deserialize(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("verification.captcha.enter"),
|
||||
Placeholder.component("prefix", Sonar.get().getConfig().getPrefix())))));
|
||||
Sonar.get0().getConfig().getMessagesConfig().getString("verification.captcha.enter"),
|
||||
Placeholder.component("prefix", Sonar.get0().getConfig().getPrefix())))));
|
||||
incorrectCaptcha = new FallbackPacketSnapshot(new SystemChatPacket(new ComponentHolder(
|
||||
MiniMessage.miniMessage().deserialize(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("verification.captcha.incorrect"),
|
||||
Placeholder.component("prefix", Sonar.get().getConfig().getPrefix())))));
|
||||
Sonar.get0().getConfig().getMessagesConfig().getString("verification.captcha.incorrect"),
|
||||
Placeholder.component("prefix", Sonar.get0().getConfig().getPrefix())))));
|
||||
|
||||
// Prepare countdown
|
||||
xpCountdown = new FallbackPacket[Sonar.get().getConfig().getVerification().getMap().getMaxDuration() / 1000];
|
||||
xpCountdown = new FallbackPacket[Sonar.get0().getConfig().getVerification().getMap().getMaxDuration() / 1000];
|
||||
|
||||
for (int i = 0; i < xpCountdown.length; i++) {
|
||||
final float bar = (float) i / xpCountdown.length;
|
||||
@@ -241,15 +241,15 @@ public class FallbackPreparer {
|
||||
|
||||
// Update the CAPTCHA generator if necessary
|
||||
final CaptchaGenerationStartEvent generationStartEvent = new CaptchaGenerationStartEvent(
|
||||
Sonar.get().getFallback().getCaptchaGenerator());
|
||||
Sonar.get().getEventManager().publish(generationStartEvent);
|
||||
Sonar.get0().getFallback().getCaptchaGenerator());
|
||||
Sonar.get0().getEventManager().publish(generationStartEvent);
|
||||
|
||||
if (generationStartEvent.getCaptchaGenerator() == null
|
||||
|| generationStartEvent.getCaptchaGenerator() instanceof StandardCaptchaGenerator) {
|
||||
Sonar.get().getFallback().setCaptchaGenerator(new StandardCaptchaGenerator(
|
||||
Sonar.get().getConfig().getVerification().getMap().getBackgroundImage()));
|
||||
Sonar.get0().getFallback().setCaptchaGenerator(new StandardCaptchaGenerator(
|
||||
Sonar.get0().getConfig().getVerification().getMap().getBackgroundImage()));
|
||||
} else {
|
||||
Sonar.get().getLogger().info("Custom CAPTCHA generator detected, skipping reinitialization.");
|
||||
Sonar.get0().getLogger().info("Custom CAPTCHA generator detected, skipping reinitialization.");
|
||||
}
|
||||
|
||||
// Prepare CAPTCHA answers
|
||||
@@ -259,13 +259,13 @@ public class FallbackPreparer {
|
||||
enterCodeMessage = null;
|
||||
incorrectCaptcha = null;
|
||||
xpCountdown = null;
|
||||
Sonar.get().getFallback().setCaptchaGenerator(null);
|
||||
Sonar.get0().getFallback().setCaptchaGenerator(null);
|
||||
}
|
||||
|
||||
maxTotalPacketsSent = maxMovementTick + 2
|
||||
+ (xpCountdown == null ? 0 : xpCountdown.length) * 20 + 5
|
||||
+ Sonar.get().getConfig().getVerification().getVehicle().getMinimumPackets() * 4
|
||||
+ Sonar.get().getConfig().getVerification().getMap().getMaxTries()
|
||||
+ Sonar.get0().getConfig().getVerification().getVehicle().getMinimumPackets() * 4
|
||||
+ Sonar.get0().getConfig().getVerification().getMap().getMaxTries()
|
||||
+ 150 /* some arbitrary leeway */;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -58,7 +58,7 @@ public final class DimensionRegistry {
|
||||
try (final InputStream inputStream = Sonar.class.getResourceAsStream("/assets/codecs/" + fileName)) {
|
||||
return BinaryTagIO.unlimitedReader().read(Objects.requireNonNull(inputStream), BinaryTagIO.Compression.GZIP);
|
||||
} catch (Throwable throwable) {
|
||||
Sonar.get().getLogger().error("Could not load mappings for {}: {}", fileName, throwable);
|
||||
Sonar.get0().getLogger().error("Could not load mappings for {}: {}", fileName, throwable);
|
||||
throw new IllegalStateException(throwable);
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -24,7 +24,9 @@ import lombok.RequiredArgsConstructor;
|
||||
@RequiredArgsConstructor
|
||||
public enum DimensionType {
|
||||
OVERWORLD("minecraft:overworld", 0, 0),
|
||||
@Deprecated
|
||||
THE_NETHER("minecraft:the_nether", -1, 1),
|
||||
@Deprecated
|
||||
THE_END("minecraft:the_end", 1, 2);
|
||||
|
||||
private final String key;
|
||||
|
||||
+4
-4
@@ -37,11 +37,11 @@ public final class FallbackCaptchaHandler extends FallbackVerificationHandler {
|
||||
|
||||
// Disconnect the player if there is no CAPTCHA available at the moment
|
||||
if (!CaptchaPreparer.isCaptchaAvailable()) {
|
||||
user.disconnect(Sonar.get().getConfig().getVerification().getCurrentlyPreparing());
|
||||
user.disconnect(Sonar.get0().getConfig().getVerification().getCurrentlyPreparing());
|
||||
throw QuietDecoderException.INSTANCE;
|
||||
}
|
||||
|
||||
this.tries = Sonar.get().getConfig().getVerification().getMap().getMaxTries();
|
||||
this.tries = Sonar.get0().getConfig().getVerification().getMap().getMaxTries();
|
||||
|
||||
// We may not be on slot 4, so we need to make sure to synchronize the current slot
|
||||
user.delayedWrite(CAPTCHA_HELD_ITEM_SLOT);
|
||||
@@ -66,7 +66,7 @@ public final class FallbackCaptchaHandler extends FallbackVerificationHandler {
|
||||
@Override
|
||||
public void handle(final @NotNull FallbackPacket packet) {
|
||||
// Check if the player took too long to enter the CAPTCHA
|
||||
final int maxDuration = Sonar.get().getConfig().getVerification().getMap().getMaxDuration();
|
||||
final int maxDuration = Sonar.get0().getConfig().getVerification().getMap().getMaxDuration();
|
||||
checkState(!user.getLoginTimer().elapsed(maxDuration), "took too long to enter CAPTCHA");
|
||||
|
||||
if (packet instanceof SystemChatPacket) {
|
||||
@@ -83,7 +83,7 @@ public final class FallbackCaptchaHandler extends FallbackVerificationHandler {
|
||||
} else if (packet instanceof SetPlayerPositionPacket
|
||||
|| packet instanceof SetPlayerPositionRotationPacket) {
|
||||
// A position packet is sent approximately every second
|
||||
if (Sonar.get().getConfig().getVerification().getGamemode().isSurvivalOrAdventure()) {
|
||||
if (Sonar.get0().getConfig().getVerification().getGamemode().isSurvivalOrAdventure()) {
|
||||
final long difference = maxDuration - user.getLoginTimer().delay();
|
||||
final int index = (int) (difference / 1000D);
|
||||
// Make sure we can safely get and send the packet
|
||||
|
||||
+6
-6
@@ -38,14 +38,14 @@ public final class FallbackGravityHandler extends FallbackVerificationHandler {
|
||||
// Bedrock users start falling immediately
|
||||
this.canFall = user.isGeyser();
|
||||
// We don't want to check Geyser players for valid gravity, as this might cause issues because of the protocol
|
||||
this.enableGravityCheck = !user.isGeyser() && Sonar.get().getConfig().getVerification().getGravity().isEnabled();
|
||||
this.enableCollisionsCheck = !user.isGeyser() && Sonar.get().getConfig().getVerification().getGravity().isCheckCollisions();
|
||||
this.enableGravityCheck = !user.isGeyser() && Sonar.get0().getConfig().getVerification().getGravity().isEnabled();
|
||||
this.enableCollisionsCheck = !user.isGeyser() && Sonar.get0().getConfig().getVerification().getGravity().isCheckCollisions();
|
||||
|
||||
// First, write the JoinGame packet to the buffer
|
||||
user.delayedWrite(joinGame);
|
||||
// Then, write the ClientAbilities packet to the buffer
|
||||
// This is only necessary if the player is in creative mode
|
||||
if (Sonar.get().getConfig().getVerification().getGamemode() == CREATIVE) {
|
||||
if (Sonar.get0().getConfig().getVerification().getGamemode() == CREATIVE) {
|
||||
user.delayedWrite(DEFAULT_ABILITIES);
|
||||
}
|
||||
// Write the DefaultSpawnPosition packet to the buffer
|
||||
@@ -188,8 +188,8 @@ public final class FallbackGravityHandler extends FallbackVerificationHandler {
|
||||
this.y = y;
|
||||
|
||||
// Log/debug position if enabled in the configuration
|
||||
if (Sonar.get().getConfig().getVerification().isDebugXYZPositions()) {
|
||||
Sonar.get().getLogger().info("{}: {}/{}/{} ly={}, dy={}, h={}, g={}, r={}",
|
||||
if (Sonar.get0().getConfig().getVerification().isDebugXYZPositions()) {
|
||||
Sonar.get0().getLogger().info("{}: {}/{}/{} ly={}, dy={}, h={}, g={}, r={}",
|
||||
user.getUsername(), x, y, z, lastY, deltaY, blockHeight, onGround, rotated);
|
||||
}
|
||||
|
||||
@@ -262,7 +262,7 @@ public final class FallbackGravityHandler extends FallbackVerificationHandler {
|
||||
|
||||
private void failOrShowCaptcha(final String debug) {
|
||||
// Do not throw an exception if the user configured to display the CAPTCHA instead
|
||||
if (Sonar.get().getConfig().getVerification().getGravity().isCaptchaOnFail()) {
|
||||
if (Sonar.get0().getConfig().getVerification().getGravity().isCaptchaOnFail()) {
|
||||
user.setForceCaptcha(true);
|
||||
markSuccess();
|
||||
return;
|
||||
|
||||
+6
-6
@@ -135,7 +135,7 @@ public final class FallbackPreJoinHandler extends FallbackVerificationHandler {
|
||||
"illegal PluginMessage channel: " + pluginMessage.getChannel());
|
||||
|
||||
// Validate the client branding using a regex to filter unwanted characters.
|
||||
if (Sonar.get().getConfig().getVerification().getBrand().isEnabled()) {
|
||||
if (Sonar.get0().getConfig().getVerification().getBrand().isEnabled()) {
|
||||
validateClientBrand(pluginMessage.getData());
|
||||
}
|
||||
|
||||
@@ -157,8 +157,8 @@ public final class FallbackPreJoinHandler extends FallbackVerificationHandler {
|
||||
|
||||
private void markSuccess() {
|
||||
if (user.channel().isActive()) {
|
||||
if (!Sonar.get().getConfig().getVerification().getValidNameRegex().matcher(user.getUsername()).matches()) {
|
||||
user.disconnect(Sonar.get().getConfig().getVerification().getInvalidUsername());
|
||||
if (!Sonar.get0().getConfig().getVerification().getValidNameRegex().matcher(user.getUsername()).matches()) {
|
||||
user.disconnect(Sonar.get0().getConfig().getVerification().getInvalidUsername());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -183,7 +183,7 @@ public final class FallbackPreJoinHandler extends FallbackVerificationHandler {
|
||||
// Check if the client brand is too short. It has to have at least 2 bytes.
|
||||
checkState(data.length > 1, "client brand is too short");
|
||||
// Check if the decoded client brand string is too long
|
||||
checkState(data.length < Sonar.get().getConfig().getVerification().getBrand().getMaxLength(),
|
||||
checkState(data.length < Sonar.get0().getConfig().getVerification().getBrand().getMaxLength(),
|
||||
"client brand contains too much data: " + data.length);
|
||||
// https://discord.com/channels/923308209769426994/1116066363887321199/1256929441053933608
|
||||
String brand = new String(data, StandardCharsets.UTF_8);
|
||||
@@ -194,14 +194,14 @@ public final class FallbackPreJoinHandler extends FallbackVerificationHandler {
|
||||
// Check for illegal client brands
|
||||
checkState(!brand.equals("Vanilla"), "illegal client brand: " + brand);
|
||||
// Regex pattern for validating client brands
|
||||
final Pattern pattern = Sonar.get().getConfig().getVerification().getBrand().getValidRegex();
|
||||
final Pattern pattern = Sonar.get0().getConfig().getVerification().getBrand().getValidRegex();
|
||||
checkState(pattern.matcher(brand).matches(), "client brand does not match pattern: " + brand);
|
||||
}
|
||||
|
||||
private void validateClientLocale(final @NotNull String locale) {
|
||||
// Check the client locale by performing a simple regex check
|
||||
// that disallows non-ascii characters by default.
|
||||
final Pattern pattern = Sonar.get().getConfig().getVerification().getValidLocaleRegex();
|
||||
final Pattern pattern = Sonar.get0().getConfig().getVerification().getValidLocaleRegex();
|
||||
checkState(pattern.matcher(locale).matches(), "client locale does not match pattern: " + locale);
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -170,9 +170,9 @@ public final class FallbackProtocolHandler extends FallbackVerificationHandler {
|
||||
|
||||
private void markSuccess() {
|
||||
// Pass the player to the next best verification handler
|
||||
if (!user.isGeyser() && Sonar.get().getConfig().getVerification().getVehicle().isEnabled()) {
|
||||
if (!user.isGeyser() && Sonar.get0().getConfig().getVerification().getVehicle().isEnabled()) {
|
||||
user.channel().pipeline().get(FallbackPacketDecoder.class).setListener(new FallbackVehicleHandler(user));
|
||||
} else if (user.isForceCaptcha() || Sonar.get().getFallback().shouldPerformCaptcha()) {
|
||||
} else if (user.isForceCaptcha() || Sonar.get0().getFallback().shouldPerformCaptcha()) {
|
||||
user.channel().pipeline().get(FallbackPacketDecoder.class).setListener(new FallbackCaptchaHandler(user));
|
||||
} else {
|
||||
// The player has passed all checks
|
||||
|
||||
+2
-2
@@ -142,7 +142,7 @@ public final class FallbackVehicleHandler extends FallbackVerificationHandler {
|
||||
|
||||
private void markSuccess() {
|
||||
// Pass the player to the next best verification handler
|
||||
if (user.isForceCaptcha() || Sonar.get().getFallback().shouldPerformCaptcha()) {
|
||||
if (user.isForceCaptcha() || Sonar.get0().getFallback().shouldPerformCaptcha()) {
|
||||
user.channel().pipeline().get(FallbackPacketDecoder.class).setListener(new FallbackCaptchaHandler(user));
|
||||
} else {
|
||||
finishVerification();
|
||||
@@ -185,7 +185,7 @@ public final class FallbackVehicleHandler extends FallbackVerificationHandler {
|
||||
inputs++;
|
||||
|
||||
// Check if we've received more than the minimum number of packets
|
||||
final int minimumPackets = Sonar.get().getConfig().getVerification().getVehicle().getMinimumPackets();
|
||||
final int minimumPackets = Sonar.get0().getConfig().getVerification().getVehicle().getMinimumPackets();
|
||||
if (inputs > minimumPackets && rotations > minimumPackets
|
||||
&& paddles > minimumPackets && vehicleMoves > minimumPackets) {
|
||||
// Move on to the next stage
|
||||
|
||||
+19
-19
@@ -49,11 +49,11 @@ public abstract class FallbackVerificationHandler implements FallbackPacketListe
|
||||
GlobalSonarStatistics.totalSuccessfulVerifications++;
|
||||
|
||||
// Add verified player to the database
|
||||
Sonar.get().getVerifiedPlayerController().add(new VerifiedPlayer(
|
||||
Sonar.get0().getVerifiedPlayerController().add(new VerifiedPlayer(
|
||||
user.getFingerprint(), user.getLoginTimer().getStart()));
|
||||
|
||||
// Call the VerifySuccessEvent for external API usage
|
||||
Sonar.get().getEventManager().publish(new UserVerifySuccessEvent(user));
|
||||
Sonar.get0().getEventManager().publish(new UserVerifySuccessEvent(user));
|
||||
|
||||
// If enabled, transfer the player back to the origin server.
|
||||
// This feature was introduced by Mojang in Minecraft version 1.20.5.
|
||||
@@ -71,11 +71,11 @@ public abstract class FallbackVerificationHandler implements FallbackPacketListe
|
||||
}
|
||||
} else {
|
||||
// Disconnect player with the verification success message
|
||||
user.disconnect(Sonar.get().getConfig().getVerification().getVerificationSuccess());
|
||||
user.disconnect(Sonar.get0().getConfig().getVerification().getVerificationSuccess());
|
||||
}
|
||||
|
||||
Sonar.get().getLogger().info(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("verification.logs.successful")
|
||||
Sonar.get0().getLogger().info(
|
||||
Sonar.get0().getConfig().getMessagesConfig().getString("verification.logs.successful")
|
||||
.replace("<username>", user.getUsername())
|
||||
.replace("<time-taken>", user.getLoginTimer().toString()));
|
||||
}
|
||||
@@ -83,46 +83,46 @@ public abstract class FallbackVerificationHandler implements FallbackPacketListe
|
||||
protected final void fail(final @NotNull String reason) {
|
||||
GlobalSonarStatistics.totalFailedVerifications++;
|
||||
|
||||
user.disconnect(Sonar.get().getConfig().getVerification().getVerificationFailed());
|
||||
user.disconnect(Sonar.get0().getConfig().getVerification().getVerificationFailed());
|
||||
|
||||
final boolean shouldLog = Sonar.get().getAttackTracker().getCurrentAttack() == null
|
||||
|| Sonar.get().getConfig().getVerification().isLogDuringAttack();
|
||||
final boolean shouldLog = Sonar.get0().getAttackTracker().getCurrentAttack() == null
|
||||
|| Sonar.get0().getConfig().getVerification().isLogDuringAttack();
|
||||
|
||||
if (shouldLog) {
|
||||
Sonar.get().getLogger().info(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("verification.logs.failed")
|
||||
Sonar.get0().getLogger().info(
|
||||
Sonar.get0().getConfig().getMessagesConfig().getString("verification.logs.failed")
|
||||
.replace("<username>", user.getUsername())
|
||||
.replace("<ip>", Sonar.get().getConfig().formatAddress(user.getInetAddress()))
|
||||
.replace("<ip>", Sonar.get0().getConfig().formatAddress(user.getInetAddress()))
|
||||
.replace("<protocol>", user.getProtocolVersion().getName())
|
||||
.replace("<reason>", reason));
|
||||
}
|
||||
|
||||
// Call the VerifyFailedEvent for external API usage
|
||||
Sonar.get().getEventManager().publish(new UserVerifyFailedEvent(user, reason));
|
||||
Sonar.get0().getEventManager().publish(new UserVerifyFailedEvent(user, reason));
|
||||
|
||||
// Use a label, so we can easily add more code beneath this method in the future
|
||||
blacklist: {
|
||||
final String hostAddress = user.getInetAddress().getHostAddress();
|
||||
final int score = Sonar.get().getFallback().getBlacklist().get(hostAddress, __ -> 0);
|
||||
final int score = Sonar.get0().getFallback().getBlacklist().get(hostAddress, __ -> 0);
|
||||
final int newScore = score + 1;
|
||||
|
||||
Sonar.get().getFallback().getBlacklist().put(hostAddress, newScore);
|
||||
Sonar.get0().getFallback().getBlacklist().put(hostAddress, newScore);
|
||||
|
||||
// The user is allowed to disable the blacklist entirely by setting the threshold to 0
|
||||
final int limit = Sonar.get().getConfig().getVerification().getBlacklistThreshold();
|
||||
final int limit = Sonar.get0().getConfig().getVerification().getBlacklistThreshold();
|
||||
// The player hasn't been blacklisted yet, so skip this iteration
|
||||
if (newScore < limit) break blacklist;
|
||||
|
||||
GlobalSonarStatistics.totalBlacklistedPlayers++;
|
||||
|
||||
// Call the BotBlacklistedEvent for external API usage
|
||||
Sonar.get().getEventManager().publish(new UserBlacklistedEvent(user));
|
||||
Sonar.get0().getEventManager().publish(new UserBlacklistedEvent(user));
|
||||
|
||||
if (shouldLog) {
|
||||
Sonar.get().getLogger().info(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("verification.logs.blacklisted")
|
||||
Sonar.get0().getLogger().info(
|
||||
Sonar.get0().getConfig().getMessagesConfig().getString("verification.logs.blacklisted")
|
||||
.replace("<username>", user.getUsername())
|
||||
.replace("<ip>", Sonar.get().getConfig().formatAddress(user.getInetAddress()))
|
||||
.replace("<ip>", Sonar.get0().getConfig().formatAddress(user.getInetAddress()))
|
||||
.replace("<protocol>", user.getProtocolVersion().getName()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,21 +47,21 @@ public final class ScheduledServiceManager {
|
||||
VERBOSE.scheduleAtFixedRate(() -> {
|
||||
// Make sure to clean up the cached statistics since we don't want to display wrong values
|
||||
GlobalSonarStatistics.cleanUpCaches();
|
||||
Sonar.get().getFallback().getBlacklist().cleanUp();
|
||||
Sonar.get0().getFallback().getBlacklist().cleanUp();
|
||||
// Update the attack tracker
|
||||
Sonar.get().getAttackTracker().checkIfUnderAttack();
|
||||
Sonar.get0().getAttackTracker().checkIfUnderAttack();
|
||||
// Publish the action bar notifications
|
||||
Sonar.get().getActionBarNotificationHandler().handleNotification();
|
||||
Sonar.get0().getActionBarNotificationHandler().handleNotification();
|
||||
}, 0L, 250L, TimeUnit.MILLISECONDS);
|
||||
|
||||
FALLBACK_QUEUE.scheduleAtFixedRate(() -> Sonar.get().getFallback().getQueue().poll(),
|
||||
FALLBACK_QUEUE.scheduleAtFixedRate(() -> Sonar.get0().getFallback().getQueue().poll(),
|
||||
1L, 1L, TimeUnit.SECONDS);
|
||||
|
||||
STATISTICS.scheduleAtFixedRate(GlobalSonarStatistics::hitEverySecond,
|
||||
0L, 1L, TimeUnit.SECONDS);
|
||||
|
||||
// This config setting only updates when the server is restarted
|
||||
if (Sonar.get().getConfig().getGeneralConfig().getBoolean("general.check-for-updates")) {
|
||||
if (Sonar.get0().getConfig().getGeneralConfig().getBoolean("general.check-for-updates")) {
|
||||
UPDATE_NOTIFIER.scheduleAtFixedRate(UpdateChecker::checkForUpdates,
|
||||
0L, 2L, TimeUnit.HOURS);
|
||||
}
|
||||
|
||||
+3
-3
@@ -130,7 +130,7 @@ public final class GlobalSonarStatistics implements SonarStatistics {
|
||||
|
||||
@Override
|
||||
public int getTotalPlayersVerified() {
|
||||
return Sonar.get().getVerifiedPlayerController().getCache().size();
|
||||
return Sonar.get0().getVerifiedPlayerController().getCache().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -145,7 +145,7 @@ public final class GlobalSonarStatistics implements SonarStatistics {
|
||||
|
||||
@Override
|
||||
public long getCurrentAttemptedVerifications() {
|
||||
return Sonar.get().getFallback().getConnected().size();
|
||||
return Sonar.get0().getFallback().getConnected().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -155,7 +155,7 @@ public final class GlobalSonarStatistics implements SonarStatistics {
|
||||
|
||||
@Override
|
||||
public long getCurrentBlacklistSize() {
|
||||
return Sonar.get().getFallback().getBlacklist().estimatedSize();
|
||||
return Sonar.get0().getFallback().getBlacklist().estimatedSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -44,18 +44,18 @@ public final class BlacklistCommand extends Subcommand {
|
||||
// Make sure the given IP address is valid
|
||||
if (rawAddress == null) return;
|
||||
|
||||
if (Sonar.get().getFallback().getBlacklist().asMap().containsKey(rawAddress)) {
|
||||
if (Sonar.get0().getFallback().getBlacklist().asMap().containsKey(rawAddress)) {
|
||||
source.sendMessage(MiniMessage.miniMessage().deserialize(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("commands.blacklist.ip-duplicate"),
|
||||
Placeholder.component("prefix", Sonar.get().getConfig().getPrefix()),
|
||||
Sonar.get0().getConfig().getMessagesConfig().getString("commands.blacklist.ip-duplicate"),
|
||||
Placeholder.component("prefix", Sonar.get0().getConfig().getPrefix()),
|
||||
Placeholder.unparsed("ip", rawAddress)));
|
||||
return;
|
||||
}
|
||||
|
||||
Sonar.get().getFallback().getBlacklist().put(rawAddress, 1337 /* arbitrarily high number */);
|
||||
Sonar.get0().getFallback().getBlacklist().put(rawAddress, 1337 /* arbitrarily high number */);
|
||||
source.sendMessage(MiniMessage.miniMessage().deserialize(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("commands.blacklist.add"),
|
||||
Placeholder.component("prefix", Sonar.get().getConfig().getPrefix()),
|
||||
Sonar.get0().getConfig().getMessagesConfig().getString("commands.blacklist.add"),
|
||||
Placeholder.component("prefix", Sonar.get0().getConfig().getPrefix()),
|
||||
Placeholder.unparsed("ip", rawAddress)));
|
||||
break;
|
||||
}
|
||||
@@ -70,45 +70,45 @@ public final class BlacklistCommand extends Subcommand {
|
||||
// Make sure the given IP address is valid
|
||||
if (rawAddress == null) return;
|
||||
|
||||
if (!Sonar.get().getFallback().getBlacklist().asMap().containsKey(rawAddress)) {
|
||||
if (!Sonar.get0().getFallback().getBlacklist().asMap().containsKey(rawAddress)) {
|
||||
source.sendMessage(MiniMessage.miniMessage().deserialize(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("commands.blacklist.ip-not-found"),
|
||||
Placeholder.component("prefix", Sonar.get().getConfig().getPrefix())));
|
||||
Sonar.get0().getConfig().getMessagesConfig().getString("commands.blacklist.ip-not-found"),
|
||||
Placeholder.component("prefix", Sonar.get0().getConfig().getPrefix())));
|
||||
return;
|
||||
}
|
||||
|
||||
Sonar.get().getFallback().getBlacklist().invalidate(rawAddress);
|
||||
Sonar.get0().getFallback().getBlacklist().invalidate(rawAddress);
|
||||
source.sendMessage(MiniMessage.miniMessage().deserialize(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("commands.blacklist.remove"),
|
||||
Placeholder.component("prefix", Sonar.get().getConfig().getPrefix()),
|
||||
Sonar.get0().getConfig().getMessagesConfig().getString("commands.blacklist.remove"),
|
||||
Placeholder.component("prefix", Sonar.get0().getConfig().getPrefix()),
|
||||
Placeholder.unparsed("ip", rawAddress)));
|
||||
break;
|
||||
}
|
||||
|
||||
case "clear": {
|
||||
final long blacklistSize = Sonar.get().getFallback().getBlacklist().estimatedSize();
|
||||
final long blacklistSize = Sonar.get0().getFallback().getBlacklist().estimatedSize();
|
||||
|
||||
if (blacklistSize == 0) {
|
||||
source.sendMessage(MiniMessage.miniMessage().deserialize(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("commands.blacklist.empty"),
|
||||
Placeholder.component("prefix", Sonar.get().getConfig().getPrefix())));
|
||||
Sonar.get0().getConfig().getMessagesConfig().getString("commands.blacklist.empty"),
|
||||
Placeholder.component("prefix", Sonar.get0().getConfig().getPrefix())));
|
||||
return;
|
||||
}
|
||||
|
||||
Sonar.get().getFallback().getBlacklist().invalidateAll();
|
||||
Sonar.get0().getFallback().getBlacklist().invalidateAll();
|
||||
source.sendMessage(MiniMessage.miniMessage().deserialize(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("commands.blacklist.clear"),
|
||||
Placeholder.component("prefix", Sonar.get().getConfig().getPrefix()),
|
||||
Sonar.get0().getConfig().getMessagesConfig().getString("commands.blacklist.clear"),
|
||||
Placeholder.component("prefix", Sonar.get0().getConfig().getPrefix()),
|
||||
Placeholder.unparsed("amount", Sonar.DECIMAL_FORMAT.format(blacklistSize))));
|
||||
break;
|
||||
}
|
||||
|
||||
case "size": {
|
||||
final long blacklistSize = Sonar.get().getFallback().getBlacklist().estimatedSize();
|
||||
final long blacklistSize = Sonar.get0().getFallback().getBlacklist().estimatedSize();
|
||||
|
||||
source.sendMessage(MiniMessage.miniMessage().deserialize(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("commands.blacklist.size"),
|
||||
Placeholder.component("prefix", Sonar.get().getConfig().getPrefix()),
|
||||
Sonar.get0().getConfig().getMessagesConfig().getString("commands.blacklist.size"),
|
||||
Placeholder.component("prefix", Sonar.get0().getConfig().getPrefix()),
|
||||
Placeholder.unparsed("amount", Sonar.DECIMAL_FORMAT.format(blacklistSize))));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -49,10 +49,10 @@ public final class DumpCommand extends Subcommand {
|
||||
protected void execute(final @NotNull InvocationSource source, final String @NotNull [] args) {
|
||||
final var mappings = new WeakHashMap<String, Object>();
|
||||
mappings.put("sonar", new Dump.Sonar(
|
||||
Sonar.get().getVersion().getFormatted(),
|
||||
Sonar.get().getPlatform(),
|
||||
Sonar.get().getVersion().getGitBranch(),
|
||||
Sonar.get().getVersion().getGitCommit()
|
||||
Sonar.get0().getVersion().getFormatted(),
|
||||
Sonar.get0().getPlatform(),
|
||||
Sonar.get0().getVersion().getGitBranch(),
|
||||
Sonar.get0().getVersion().getGitCommit()
|
||||
));
|
||||
mappings.put("runtime", new Dump.Runtime(
|
||||
getVirtualCores(),
|
||||
@@ -72,7 +72,7 @@ public final class DumpCommand extends Subcommand {
|
||||
formatMemory(getFreeMemory()),
|
||||
formatMemory(getUsedMemory())
|
||||
));
|
||||
Sonar.get().getLogger().info(Sonar.get().getConfig().getMessagesConfig().getString("commands.dump.log")
|
||||
Sonar.get0().getLogger().info(Sonar.get0().getConfig().getMessagesConfig().getString("commands.dump.log")
|
||||
.replace("<dumped-json-data>", GSON.toJson(mappings)));
|
||||
}
|
||||
|
||||
|
||||
@@ -33,17 +33,17 @@ public final class NotifyCommand extends Subcommand {
|
||||
|
||||
@Override
|
||||
protected void execute(final @NotNull InvocationSource source, final String @NotNull [] args) {
|
||||
if (Sonar.get().getChatNotificationHandler().isSubscribed(source.getUuid())) {
|
||||
Sonar.get().getChatNotificationHandler().unsubscribe(source.getUuid());
|
||||
if (Sonar.get0().getChatNotificationHandler().isSubscribed(source.getUuid())) {
|
||||
Sonar.get0().getChatNotificationHandler().unsubscribe(source.getUuid());
|
||||
source.sendMessage(MiniMessage.miniMessage().deserialize(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("commands.notify.unsubscribe"),
|
||||
Placeholder.component("prefix", Sonar.get().getConfig().getPrefix())));
|
||||
Sonar.get0().getConfig().getMessagesConfig().getString("commands.notify.unsubscribe"),
|
||||
Placeholder.component("prefix", Sonar.get0().getConfig().getPrefix())));
|
||||
return;
|
||||
}
|
||||
|
||||
Sonar.get().getChatNotificationHandler().subscribe(source.getUuid());
|
||||
Sonar.get0().getChatNotificationHandler().subscribe(source.getUuid());
|
||||
source.sendMessage(MiniMessage.miniMessage().deserialize(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("commands.notify.subscribe"),
|
||||
Placeholder.component("prefix", Sonar.get().getConfig().getPrefix())));
|
||||
Sonar.get0().getConfig().getMessagesConfig().getString("commands.notify.subscribe"),
|
||||
Placeholder.component("prefix", Sonar.get0().getConfig().getPrefix())));
|
||||
}
|
||||
}
|
||||
@@ -34,16 +34,16 @@ public final class ReloadCommand extends Subcommand {
|
||||
@Override
|
||||
protected void execute(final @NotNull InvocationSource source, final String @NotNull [] args) {
|
||||
source.sendMessage(MiniMessage.miniMessage().deserialize(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("commands.reload.start"),
|
||||
Placeholder.component("prefix", Sonar.get().getConfig().getPrefix())));
|
||||
Sonar.get0().getConfig().getMessagesConfig().getString("commands.reload.start"),
|
||||
Placeholder.component("prefix", Sonar.get0().getConfig().getPrefix())));
|
||||
|
||||
final SystemTimer timer = new SystemTimer();
|
||||
|
||||
Sonar.get().reload();
|
||||
Sonar.get0().reload();
|
||||
|
||||
source.sendMessage(MiniMessage.miniMessage().deserialize(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("commands.reload.finish"),
|
||||
Placeholder.component("prefix", Sonar.get().getConfig().getPrefix()),
|
||||
Sonar.get0().getConfig().getMessagesConfig().getString("commands.reload.finish"),
|
||||
Placeholder.component("prefix", Sonar.get0().getConfig().getPrefix()),
|
||||
Placeholder.unparsed("time-taken", String.valueOf(timer.delay()))));
|
||||
}
|
||||
}
|
||||
@@ -47,16 +47,16 @@ public final class StatisticsCommand extends Subcommand {
|
||||
type = args[1].toLowerCase();
|
||||
} catch (Exception exception) {
|
||||
source.sendMessage(MiniMessage.miniMessage().deserialize(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("commands.statistics.unknown-type"),
|
||||
Placeholder.component("prefix", Sonar.get().getConfig().getPrefix()),
|
||||
Sonar.get0().getConfig().getMessagesConfig().getString("commands.statistics.unknown-type"),
|
||||
Placeholder.component("prefix", Sonar.get0().getConfig().getPrefix()),
|
||||
Placeholder.unparsed("statistics", getArguments())));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
source.sendMessage(MiniMessage.miniMessage().deserialize(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("commands.statistics.header"),
|
||||
Placeholder.component("prefix", Sonar.get().getConfig().getPrefix()),
|
||||
Sonar.get0().getConfig().getMessagesConfig().getString("commands.statistics.header"),
|
||||
Placeholder.component("prefix", Sonar.get0().getConfig().getPrefix()),
|
||||
Placeholder.unparsed("statistics-type", type)));
|
||||
source.sendMessage(Component.empty());
|
||||
|
||||
@@ -64,29 +64,29 @@ public final class StatisticsCommand extends Subcommand {
|
||||
|
||||
switch (type) {
|
||||
case "general": {
|
||||
final long seconds = Sonar.get().getLaunchTimer().delay() / 1000L;
|
||||
final long seconds = Sonar.get0().getLaunchTimer().delay() / 1000L;
|
||||
final long days = seconds / (24L * 60L * 60L);
|
||||
final long hours = (seconds % (24L * 60L * 60L)) / (60L * 60L);
|
||||
final long minutes = (seconds % (60L * 60L)) / 60L;
|
||||
final String serverUptime = String.format("%dd %dh %dm %ds", days, hours, minutes, seconds % 60L);
|
||||
|
||||
placeholders = new TagResolver.Single[]{
|
||||
Placeholder.component("prefix", Sonar.get().getConfig().getPrefix()),
|
||||
Placeholder.unparsed("verified", Sonar.DECIMAL_FORMAT.format(Sonar.get().getVerifiedPlayerController().getCache().size())),
|
||||
Placeholder.unparsed("verifying", Sonar.DECIMAL_FORMAT.format(Sonar.get().getFallback().getConnected().size())),
|
||||
Placeholder.unparsed("blacklisted", Sonar.DECIMAL_FORMAT.format(Sonar.get().getFallback().getBlacklist().estimatedSize())),
|
||||
Placeholder.unparsed("queued", Sonar.DECIMAL_FORMAT.format(Sonar.get().getFallback().getQueue().getPlayers().size())),
|
||||
Placeholder.component("prefix", Sonar.get0().getConfig().getPrefix()),
|
||||
Placeholder.unparsed("verified", Sonar.DECIMAL_FORMAT.format(Sonar.get0().getVerifiedPlayerController().getCache().size())),
|
||||
Placeholder.unparsed("verifying", Sonar.DECIMAL_FORMAT.format(Sonar.get0().getFallback().getConnected().size())),
|
||||
Placeholder.unparsed("blacklisted", Sonar.DECIMAL_FORMAT.format(Sonar.get0().getFallback().getBlacklist().estimatedSize())),
|
||||
Placeholder.unparsed("queued", Sonar.DECIMAL_FORMAT.format(Sonar.get0().getFallback().getQueue().getPlayers().size())),
|
||||
Placeholder.unparsed("server-uptime", serverUptime),
|
||||
Placeholder.unparsed("total-joins", Sonar.DECIMAL_FORMAT.format(Sonar.get().getStatistics().getTotalPlayersJoined())),
|
||||
Placeholder.unparsed("total-attempts", Sonar.DECIMAL_FORMAT.format(Sonar.get().getStatistics().getTotalAttemptedVerifications())),
|
||||
Placeholder.unparsed("total-failed", Sonar.DECIMAL_FORMAT.format(Sonar.get().getStatistics().getTotalFailedVerifications()))
|
||||
Placeholder.unparsed("total-joins", Sonar.DECIMAL_FORMAT.format(Sonar.get0().getStatistics().getTotalPlayersJoined())),
|
||||
Placeholder.unparsed("total-attempts", Sonar.DECIMAL_FORMAT.format(Sonar.get0().getStatistics().getTotalAttemptedVerifications())),
|
||||
Placeholder.unparsed("total-failed", Sonar.DECIMAL_FORMAT.format(Sonar.get0().getStatistics().getTotalFailedVerifications()))
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
case "cpu": {
|
||||
placeholders = new TagResolver.Single[]{
|
||||
Placeholder.component("prefix", Sonar.get().getConfig().getPrefix()),
|
||||
Placeholder.component("prefix", Sonar.get0().getConfig().getPrefix()),
|
||||
Placeholder.unparsed("process-cpu", Sonar.DECIMAL_FORMAT.format(getProcessCPUUsage())),
|
||||
Placeholder.unparsed("system-cpu", Sonar.DECIMAL_FORMAT.format(getSystemCPUUsage())),
|
||||
Placeholder.unparsed("average-process-cpu", Sonar.DECIMAL_FORMAT.format(getAverageProcessCPUUsage())),
|
||||
@@ -98,7 +98,7 @@ public final class StatisticsCommand extends Subcommand {
|
||||
|
||||
case "memory": {
|
||||
placeholders = new TagResolver.Single[]{
|
||||
Placeholder.component("prefix", Sonar.get().getConfig().getPrefix()),
|
||||
Placeholder.component("prefix", Sonar.get0().getConfig().getPrefix()),
|
||||
Placeholder.unparsed("free-memory", formatMemory(getFreeMemory())),
|
||||
Placeholder.unparsed("used-memory", formatMemory(getUsedMemory())),
|
||||
Placeholder.unparsed("max-memory", formatMemory(getMaxMemory())),
|
||||
@@ -109,17 +109,17 @@ public final class StatisticsCommand extends Subcommand {
|
||||
|
||||
case "network": {
|
||||
placeholders = new TagResolver.Single[]{
|
||||
Placeholder.component("prefix", Sonar.get().getConfig().getPrefix()),
|
||||
Placeholder.unparsed("incoming-traffic", Sonar.get().getStatistics().getPerSecondIncomingBandwidthFormatted()),
|
||||
Placeholder.unparsed("outgoing-traffic", Sonar.get().getStatistics().getPerSecondOutgoingBandwidthFormatted()),
|
||||
Placeholder.unparsed("incoming-traffic-ttl", formatMemory(Sonar.get().getStatistics().getTotalIncomingBandwidth())),
|
||||
Placeholder.unparsed("outgoing-traffic-ttl", formatMemory(Sonar.get().getStatistics().getTotalOutgoingBandwidth())),
|
||||
Placeholder.component("prefix", Sonar.get0().getConfig().getPrefix()),
|
||||
Placeholder.unparsed("incoming-traffic", Sonar.get0().getStatistics().getPerSecondIncomingBandwidthFormatted()),
|
||||
Placeholder.unparsed("outgoing-traffic", Sonar.get0().getStatistics().getPerSecondOutgoingBandwidthFormatted()),
|
||||
Placeholder.unparsed("incoming-traffic-ttl", formatMemory(Sonar.get0().getStatistics().getTotalIncomingBandwidth())),
|
||||
Placeholder.unparsed("outgoing-traffic-ttl", formatMemory(Sonar.get0().getStatistics().getTotalOutgoingBandwidth())),
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
final List<String> parts = Sonar.get().getConfig().getMessagesConfig().getStringList(
|
||||
final List<String> parts = Sonar.get0().getConfig().getMessagesConfig().getStringList(
|
||||
"commands.statistics." + type);
|
||||
for (final String msg : parts) {
|
||||
source.sendMessage(MiniMessage.miniMessage().deserialize(msg, placeholders));
|
||||
|
||||
@@ -34,19 +34,19 @@ public final class VerboseCommand extends Subcommand {
|
||||
|
||||
@Override
|
||||
protected void execute(final @NotNull InvocationSource source, final String @NotNull [] args) {
|
||||
if (Sonar.get().getActionBarNotificationHandler().isSubscribed(source.getUuid())) {
|
||||
Sonar.get().getActionBarNotificationHandler().unsubscribe(source.getUuid());
|
||||
if (Sonar.get0().getActionBarNotificationHandler().isSubscribed(source.getUuid())) {
|
||||
Sonar.get0().getActionBarNotificationHandler().unsubscribe(source.getUuid());
|
||||
// Reset ActionBar component when unsubscribing
|
||||
source.getAudience().sendActionBar(Component.empty());
|
||||
source.sendMessage(MiniMessage.miniMessage().deserialize(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("commands.verbose.unsubscribe"),
|
||||
Placeholder.component("prefix", Sonar.get().getConfig().getPrefix())));
|
||||
Sonar.get0().getConfig().getMessagesConfig().getString("commands.verbose.unsubscribe"),
|
||||
Placeholder.component("prefix", Sonar.get0().getConfig().getPrefix())));
|
||||
return;
|
||||
}
|
||||
|
||||
Sonar.get().getActionBarNotificationHandler().subscribe(source.getUuid());
|
||||
Sonar.get0().getActionBarNotificationHandler().subscribe(source.getUuid());
|
||||
source.sendMessage(MiniMessage.miniMessage().deserialize(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("commands.verbose.subscribe"),
|
||||
Placeholder.component("prefix", Sonar.get().getConfig().getPrefix())));
|
||||
Sonar.get0().getConfig().getMessagesConfig().getString("commands.verbose.subscribe"),
|
||||
Placeholder.component("prefix", Sonar.get0().getConfig().getPrefix())));
|
||||
}
|
||||
}
|
||||
@@ -49,17 +49,17 @@ public final class VerifiedCommand extends Subcommand {
|
||||
final String username = args[3];
|
||||
final String fingerprint = FingerprintingUtil.getFingerprint(username, hostAddress);
|
||||
|
||||
if (!Sonar.get().getVerifiedPlayerController().getCache().contains(fingerprint)) {
|
||||
if (!Sonar.get0().getVerifiedPlayerController().getCache().contains(fingerprint)) {
|
||||
source.sendMessage(MiniMessage.miniMessage().deserialize(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("commands.verified.ip-not-found"),
|
||||
Placeholder.component("prefix", Sonar.get().getConfig().getPrefix())));
|
||||
Sonar.get0().getConfig().getMessagesConfig().getString("commands.verified.ip-not-found"),
|
||||
Placeholder.component("prefix", Sonar.get0().getConfig().getPrefix())));
|
||||
return;
|
||||
}
|
||||
|
||||
Sonar.get().getVerifiedPlayerController().remove(fingerprint);
|
||||
Sonar.get0().getVerifiedPlayerController().remove(fingerprint);
|
||||
source.sendMessage(MiniMessage.miniMessage().deserialize(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("commands.verified.remove"),
|
||||
Placeholder.component("prefix", Sonar.get().getConfig().getPrefix()),
|
||||
Sonar.get0().getConfig().getMessagesConfig().getString("commands.verified.remove"),
|
||||
Placeholder.component("prefix", Sonar.get0().getConfig().getPrefix()),
|
||||
Placeholder.unparsed("ip", hostAddress),
|
||||
Placeholder.unparsed("username", username)));
|
||||
break;
|
||||
@@ -78,46 +78,46 @@ public final class VerifiedCommand extends Subcommand {
|
||||
final String username = args[3];
|
||||
final String fingerprint = FingerprintingUtil.getFingerprint(username, hostAddress);
|
||||
|
||||
if (Sonar.get().getVerifiedPlayerController().getCache().contains(fingerprint)) {
|
||||
if (Sonar.get0().getVerifiedPlayerController().getCache().contains(fingerprint)) {
|
||||
source.sendMessage(MiniMessage.miniMessage().deserialize(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("commands.verified.already"),
|
||||
Placeholder.component("prefix", Sonar.get().getConfig().getPrefix())));
|
||||
Sonar.get0().getConfig().getMessagesConfig().getString("commands.verified.already"),
|
||||
Placeholder.component("prefix", Sonar.get0().getConfig().getPrefix())));
|
||||
return;
|
||||
}
|
||||
|
||||
Sonar.get().getVerifiedPlayerController().add(new VerifiedPlayer(fingerprint, System.currentTimeMillis()));
|
||||
Sonar.get0().getVerifiedPlayerController().add(new VerifiedPlayer(fingerprint, System.currentTimeMillis()));
|
||||
source.sendMessage(MiniMessage.miniMessage().deserialize(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("commands.verified.add"),
|
||||
Placeholder.component("prefix", Sonar.get().getConfig().getPrefix()),
|
||||
Sonar.get0().getConfig().getMessagesConfig().getString("commands.verified.add"),
|
||||
Placeholder.component("prefix", Sonar.get0().getConfig().getPrefix()),
|
||||
Placeholder.unparsed("ip", hostAddress),
|
||||
Placeholder.unparsed("username", username)));
|
||||
break;
|
||||
}
|
||||
|
||||
case "clear": {
|
||||
final int verifiedSize = Sonar.get().getVerifiedPlayerController().getCache().size();
|
||||
final int verifiedSize = Sonar.get0().getVerifiedPlayerController().getCache().size();
|
||||
|
||||
if (verifiedSize == 0) {
|
||||
source.sendMessage(MiniMessage.miniMessage().deserialize(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("commands.verified.empty"),
|
||||
Placeholder.component("prefix", Sonar.get().getConfig().getPrefix())));
|
||||
Sonar.get0().getConfig().getMessagesConfig().getString("commands.verified.empty"),
|
||||
Placeholder.component("prefix", Sonar.get0().getConfig().getPrefix())));
|
||||
return;
|
||||
}
|
||||
|
||||
Sonar.get().getVerifiedPlayerController().clearAll();
|
||||
Sonar.get0().getVerifiedPlayerController().clearAll();
|
||||
source.sendMessage(MiniMessage.miniMessage().deserialize(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("commands.verified.clear"),
|
||||
Placeholder.component("prefix", Sonar.get().getConfig().getPrefix()),
|
||||
Sonar.get0().getConfig().getMessagesConfig().getString("commands.verified.clear"),
|
||||
Placeholder.component("prefix", Sonar.get0().getConfig().getPrefix()),
|
||||
Placeholder.unparsed("amount", Sonar.DECIMAL_FORMAT.format(verifiedSize))));
|
||||
break;
|
||||
}
|
||||
|
||||
case "size": {
|
||||
final int verifiedSize = Sonar.get().getVerifiedPlayerController().getCache().size();
|
||||
final int verifiedSize = Sonar.get0().getVerifiedPlayerController().getCache().size();
|
||||
|
||||
source.sendMessage(MiniMessage.miniMessage().deserialize(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("commands.verified.size"),
|
||||
Placeholder.component("prefix", Sonar.get().getConfig().getPrefix()),
|
||||
Sonar.get0().getConfig().getMessagesConfig().getString("commands.verified.size"),
|
||||
Placeholder.component("prefix", Sonar.get0().getConfig().getPrefix()),
|
||||
Placeholder.unparsed("amount", Sonar.DECIMAL_FORMAT.format(verifiedSize))));
|
||||
break;
|
||||
}
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ public final class ReflectiveOperationException extends RuntimeException {
|
||||
public ReflectiveOperationException(final Throwable throwable) {
|
||||
super(throwable);
|
||||
|
||||
Sonar.get().getLogger().error("A reflective operation resulted in error:");
|
||||
Sonar.get0().getLogger().error("A reflective operation resulted in error:");
|
||||
throwable.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
group=xyz.jonesdev
|
||||
version=2.1.23
|
||||
version=2.1.26
|
||||
description=A lightweight, effective, and easy-to-use anti-bot plugin for Velocity, BungeeCord, and Bukkit.
|
||||
@@ -1,5 +1,5 @@
|
||||
[versions]
|
||||
netty = "4.1.117.Final"
|
||||
netty = "4.1.118.Final"
|
||||
adventure = "4.18.0"
|
||||
adventure-platform = "4.3.4"
|
||||
bstats = "3.1.0"
|
||||
@@ -8,7 +8,7 @@ pluginyml = "0.6.0"
|
||||
|
||||
[plugins]
|
||||
indra-git = "net.kyori.indra.git:3.1.3"
|
||||
shadow = "com.gradleup.shadow:8.3.5"
|
||||
shadow = "com.gradleup.shadow:8.3.6"
|
||||
spotless = "com.diffplug.spotless:7.0.2"
|
||||
pluginyml-bungee = { id = "net.minecrell.plugin-yml.bungee", version.ref = "pluginyml" }
|
||||
pluginyml-bukkit = { id = "net.minecrell.plugin-yml.bukkit", version.ref = "pluginyml" }
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
@@ -86,8 +86,7 @@ done
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
|
||||
' "$PWD" ) || exit
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
Reference in new issue
Block a user