mirror of
https://github.com/jonesdevelopment/sonar.git
synced 2026-11-05 17:22:34 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
58d0c57ee8 | ||
|
|
5546d2695d | ||
|
|
64688ba06b | ||
|
|
e85036dd13 | ||
|
|
2b2b481c14 | ||
|
|
e0cc9bdab3 | ||
|
|
8aa05563d5 | ||
|
|
21eb949bae | ||
|
|
3a978b39ee | ||
|
|
efc435df61 | ||
|
|
8baa920279 | ||
|
|
647931c31e | ||
|
|
c8c3685355 | ||
|
|
b759082416 | ||
|
|
31a09d60ac | ||
|
|
45fb866c1c | ||
|
|
9f8d828622 |
No files matched your search
+12
-7
@@ -1,13 +1,9 @@
|
||||
import net.kyori.indra.git.IndraGitExtension
|
||||
|
||||
plugins {
|
||||
java
|
||||
alias(libs.plugins.shadow)
|
||||
alias(libs.plugins.versioner) apply true
|
||||
}
|
||||
|
||||
versioner {
|
||||
pattern {
|
||||
pattern = "$version-%h-%c-%b"
|
||||
}
|
||||
alias(libs.plugins.indra.git) apply true
|
||||
}
|
||||
|
||||
allprojects {
|
||||
@@ -53,6 +49,7 @@ allprojects {
|
||||
relocate("com.mysql", "xyz.jonesdev.sonar.libs.mysql")
|
||||
relocate("org.mariadb", "xyz.jonesdev.sonar.libs.mariadb")
|
||||
relocate("xyz.jonesdev.capja", "xyz.jonesdev.sonar.libs.capja")
|
||||
relocate("org.h2", "xyz.jonesdev.sonar.libs.h2")
|
||||
|
||||
// Exclude unnecessary metadata information
|
||||
exclude("META-INF/*/**")
|
||||
@@ -69,10 +66,18 @@ allprojects {
|
||||
|
||||
jar {
|
||||
manifest {
|
||||
val indra = rootProject.extensions.getByType(IndraGitExtension::class.java)
|
||||
val gitBranch = indra.branchName() ?: "unknown"
|
||||
val gitCommit = indra.commit()?.name?.substring(0, 8) ?: "unknown"
|
||||
|
||||
// Set the implementation version, so we can create exact version
|
||||
// information in-game and make it accessible to the user.
|
||||
attributes["Implementation-Title"] = rootProject.name
|
||||
attributes["Implementation-Version"] = rootProject.version
|
||||
attributes["Implementation-Vendor"] = "Jones Development, Sonar Contributors"
|
||||
// Include the Git branch and Git commit SHA
|
||||
attributes["Git-Branch"] = gitBranch
|
||||
attributes["Git-Commit"] = gitCommit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
group=xyz.jonesdev.sonar
|
||||
version=2.0.34
|
||||
version=2.0.36
|
||||
description=A lightweight, effective, and easy-to-use anti-bot plugin for Velocity, BungeeCord, and Bukkit.
|
||||
@@ -6,8 +6,8 @@ bstats = "3.0.2"
|
||||
libby = "2.0.0-SNAPSHOT"
|
||||
|
||||
[plugins]
|
||||
versioner = "io.toolebox.git-versioner:1.6.7"
|
||||
shadow = "io.github.goooler.shadow:8.1.7"
|
||||
indra-git = "net.kyori.indra.git:3.1.3"
|
||||
shadow = "io.github.goooler.shadow:8.1.8"
|
||||
|
||||
[libraries]
|
||||
netty = { module = "io.netty:netty-all", version.ref = "netty" }
|
||||
@@ -27,7 +27,7 @@ bstats-bukkit = { module = "org.bstats:bstats-bukkit", version.ref = "bstats" }
|
||||
bstats-velocity = { module = "org.bstats:bstats-velocity", version.ref = "bstats" }
|
||||
caffeine = "com.github.ben-manes.caffeine:caffeine:3.1.8"
|
||||
ormlite = "com.j256.ormlite:ormlite-jdbc:6.1"
|
||||
lombok = "org.projectlombok:lombok:1.18.32"
|
||||
lombok = "org.projectlombok:lombok:1.18.34"
|
||||
capja = "xyz.jonesdev:capja:1.0.3"
|
||||
bungeecord = "net.md_5:bungeecord-proxy:master-SNAPSHOT"
|
||||
velocity = "com.velocitypowered:velocity-proxy:3.3.0-SNAPSHOT"
|
||||
|
||||
@@ -89,7 +89,7 @@ public interface Sonar {
|
||||
|
||||
@NotNull
|
||||
default SonarVersion getVersion() {
|
||||
return SonarVersion.GET;
|
||||
return SonarVersion.INSTANCE;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -18,35 +18,49 @@
|
||||
package xyz.jonesdev.sonar.api;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
@Getter
|
||||
public final class SonarVersion {
|
||||
static final SonarVersion GET = new SonarVersion();
|
||||
private final String semanticVersion, full, formatted, commitSHA;
|
||||
private final int build;
|
||||
private final boolean isOnMainBranch;
|
||||
static final SonarVersion INSTANCE = new SonarVersion();
|
||||
|
||||
private final String version, formatted, gitBranch, gitCommit;
|
||||
|
||||
SonarVersion() {
|
||||
final Package manifest = Sonar.class.getPackage();
|
||||
final String versionString = manifest.getImplementationVersion();
|
||||
// No need to null-check since we'll always just throw an exception if
|
||||
// we can't find the version information in this file.
|
||||
final Manifest manifest = getManifest();
|
||||
|
||||
if (versionString == null) {
|
||||
this.full = "<could not retrieve version>";
|
||||
this.semanticVersion = "<unknown version>";
|
||||
this.commitSHA = "<unknown commit>";
|
||||
this.build = -1;
|
||||
this.isOnMainBranch = false;
|
||||
this.formatted = full;
|
||||
Sonar.get().getLogger().warn("Could not find version information. Is the manifest missing?");
|
||||
return;
|
||||
this.version = manifest.getMainAttributes().getValue("Implementation-Version");
|
||||
this.gitBranch = manifest.getMainAttributes().getValue("Git-Branch");
|
||||
this.gitCommit = manifest.getMainAttributes().getValue("Git-Commit");
|
||||
this.formatted = version + " (" + gitCommit + ")";
|
||||
}
|
||||
|
||||
// Taken from
|
||||
// https://github.com/PaperMC/Velocity/pull/1336/
|
||||
private static @NotNull Manifest getManifest() {
|
||||
final String classLocation = "/" + Sonar.class.getName().replace(".", "/") + ".class";
|
||||
final URL resource = Sonar.class.getResource(classLocation);
|
||||
|
||||
if (resource == null) {
|
||||
throw new IllegalStateException("Could not find version information. Is the manifest missing?");
|
||||
}
|
||||
|
||||
this.full = versionString;
|
||||
this.semanticVersion = versionString.split("-")[0];
|
||||
this.commitSHA = versionString.split("-")[1];
|
||||
this.build = Integer.parseInt(versionString.split("-")[2]);
|
||||
this.isOnMainBranch = versionString.split("-")[3].equals("main");
|
||||
this.formatted = semanticVersion + " build " + build + " (" + commitSHA + ")";
|
||||
final String classFilePath = resource.toString().replace("\\", "/");
|
||||
final String archivePath = classFilePath.substring(0, classFilePath.length() - classLocation.length());
|
||||
final String manifestPath = archivePath + "/META-INF/MANIFEST.MF";
|
||||
|
||||
try (final InputStream stream = new URL(manifestPath).openStream()) {
|
||||
return new Manifest(stream);
|
||||
} catch (IOException exception) {
|
||||
throw new IllegalStateException(exception);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -26,10 +26,8 @@ import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import xyz.jonesdev.sonar.api.Sonar;
|
||||
import xyz.jonesdev.sonar.api.command.subcommand.Subcommand;
|
||||
import xyz.jonesdev.sonar.api.command.subcommand.argument.Argument;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
|
||||
@@ -76,17 +74,18 @@ public interface SonarCommand {
|
||||
Placeholder.unparsed("platform", Sonar.get().getPlatform().getDisplayName()),
|
||||
Placeholder.unparsed("copyright-year", String.valueOf(Calendar.getInstance().get(Calendar.YEAR)))));
|
||||
|
||||
final Component yes = MiniMessage.miniMessage().deserialize("<green>✔</green>");
|
||||
final Component no = MiniMessage.miniMessage().deserialize("<red>✗</red>");
|
||||
final Component yes = MiniMessage.miniMessage().deserialize(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("commands.main.tick"));
|
||||
final Component no = MiniMessage.miniMessage().deserialize(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("commands.main.cross"));
|
||||
|
||||
Sonar.get().getSubcommandRegistry().getSubcommands().forEach(command -> {
|
||||
source.sendMessage(MiniMessage.miniMessage().deserialize(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("commands.main.subcommands"),
|
||||
TagResolver.resolver("suggest-subcommand", (argumentQueue, context) -> {
|
||||
return Tag.styling(ClickEvent.suggestCommand("/sonar " + command.getInfo().name()));
|
||||
}),
|
||||
TagResolver.resolver("suggest-subcommand",
|
||||
(queue, context) -> Tag.styling(ClickEvent.suggestCommand("/sonar " + command.getInfo().name()))),
|
||||
Placeholder.unparsed("subcommand", command.getInfo().name()),
|
||||
Placeholder.unparsed("description", command.getInfo().description()),
|
||||
Placeholder.unparsed("description", command.getDescription()),
|
||||
Placeholder.unparsed("permission", command.getPermission()),
|
||||
Placeholder.unparsed("aliases", command.getAliases()),
|
||||
Placeholder.component("only-players", command.getInfo().onlyPlayers() ? yes : no),
|
||||
@@ -104,12 +103,10 @@ public interface SonarCommand {
|
||||
if (subcommand.getInfo().aliases().length > 0) {
|
||||
TAB_SUGGESTIONS.addAll(Arrays.asList(subcommand.getInfo().aliases()));
|
||||
}
|
||||
final List<String> parsedArguments = Arrays.stream(subcommand.getInfo().arguments())
|
||||
.map(Argument::value)
|
||||
.collect(Collectors.toList());
|
||||
ARG_TAB_SUGGESTIONS.put(subcommand.getInfo().name(), parsedArguments);
|
||||
final List<String> arguments = Arrays.asList(subcommand.getInfo().arguments());
|
||||
ARG_TAB_SUGGESTIONS.put(subcommand.getInfo().name(), arguments);
|
||||
for (final String alias : subcommand.getInfo().aliases()) {
|
||||
ARG_TAB_SUGGESTIONS.put(alias, parsedArguments);
|
||||
ARG_TAB_SUGGESTIONS.put(alias, arguments);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -118,8 +115,8 @@ public interface SonarCommand {
|
||||
if (arguments.length <= 1) {
|
||||
return TAB_SUGGESTIONS;
|
||||
} else if (arguments.length == 2) {
|
||||
final String subCommandName = arguments[0].toLowerCase();
|
||||
return ARG_TAB_SUGGESTIONS.getOrDefault(subCommandName, emptyList());
|
||||
final String subcommandName = arguments[0].toLowerCase();
|
||||
return ARG_TAB_SUGGESTIONS.getOrDefault(subcommandName, emptyList());
|
||||
}
|
||||
return emptyList();
|
||||
}
|
||||
|
||||
@@ -25,11 +25,9 @@ import org.jetbrains.annotations.Nullable;
|
||||
import xyz.jonesdev.sonar.api.Sonar;
|
||||
import xyz.jonesdev.sonar.api.command.CommandInvocation;
|
||||
import xyz.jonesdev.sonar.api.command.InvocationSource;
|
||||
import xyz.jonesdev.sonar.api.command.subcommand.argument.Argument;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Getter
|
||||
public abstract class Subcommand {
|
||||
@@ -37,14 +35,12 @@ public abstract class Subcommand {
|
||||
private final String permission, aliases, arguments;
|
||||
|
||||
public Subcommand() {
|
||||
this.info = getClass().getAnnotation(SubcommandInfo.class);
|
||||
this.info = Objects.requireNonNull(getClass().getAnnotation(SubcommandInfo.class));
|
||||
this.permission = "sonar." + info.name();
|
||||
this.aliases = info.aliases().length == 0 ? "No aliases."
|
||||
: String.join(", ", info.aliases());
|
||||
this.arguments = info.arguments().length == 0 ? ""
|
||||
: Arrays.stream(info.arguments())
|
||||
.map(Argument::value)
|
||||
.collect(Collectors.joining(", "));
|
||||
: String.join(", ", info.arguments());
|
||||
}
|
||||
|
||||
private static final Pattern IPv4_REGEX = Pattern.compile("^((25[0-5]|(2[0-4]|1\\d|[1-9]|)\\d)\\.?\\b){4}$");
|
||||
@@ -98,5 +94,10 @@ public abstract class Subcommand {
|
||||
execute(new CommandInvocation(invocationSource, arguments));
|
||||
}
|
||||
|
||||
public final @NotNull String getDescription() {
|
||||
final String path = String.format("commands.%s.description", info.name());
|
||||
return Objects.requireNonNull(Sonar.get().getConfig().getMessagesConfig().getString(path));
|
||||
}
|
||||
|
||||
protected abstract void execute(final @NotNull CommandInvocation invocation);
|
||||
}
|
||||
+1
-8
@@ -17,8 +17,6 @@
|
||||
|
||||
package xyz.jonesdev.sonar.api.command.subcommand;
|
||||
|
||||
import xyz.jonesdev.sonar.api.command.subcommand.argument.Argument;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
@@ -33,11 +31,6 @@ public @interface SubcommandInfo {
|
||||
*/
|
||||
String name();
|
||||
|
||||
/**
|
||||
* @return Description of the subcommand
|
||||
*/
|
||||
String description();
|
||||
|
||||
/**
|
||||
* @return Aliases of the subcommand
|
||||
*/
|
||||
@@ -46,7 +39,7 @@ public @interface SubcommandInfo {
|
||||
/**
|
||||
* @return Arguments of the subcommand
|
||||
*/
|
||||
Argument[] arguments() default {};
|
||||
String[] arguments() default {};
|
||||
|
||||
/**
|
||||
* @return Whether the subcommands requires arguments
|
||||
|
||||
+8
-14
@@ -17,30 +17,24 @@
|
||||
|
||||
package xyz.jonesdev.sonar.api.command.subcommand;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Unmodifiable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
|
||||
public interface SubcommandRegistry {
|
||||
List<Subcommand> SUBCOMMANDS = new Vector<>();
|
||||
|
||||
@NotNull
|
||||
@Unmodifiable
|
||||
default List<Subcommand> getSubcommands() {
|
||||
return Collections.unmodifiableList(SUBCOMMANDS);
|
||||
}
|
||||
@Getter
|
||||
public final class SubcommandRegistry {
|
||||
private final List<Subcommand> subcommands = new Vector<>();
|
||||
|
||||
/**
|
||||
* Registers a single or multiple subcommand(s)
|
||||
*
|
||||
* @param subcommand Array of Subcommands to register
|
||||
*/
|
||||
default void register(final Subcommand @NotNull ... subcommand) {
|
||||
SUBCOMMANDS.addAll(Arrays.asList(subcommand));
|
||||
public void register(final Subcommand @NotNull ... subcommand) {
|
||||
subcommands.addAll(Arrays.asList(subcommand));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,7 +43,7 @@ public interface SubcommandRegistry {
|
||||
* @param subcommand Array of Subcommands to unregister
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
default void unregister(final Subcommand @NotNull ... subcommand) {
|
||||
SUBCOMMANDS.removeAll(Arrays.asList(subcommand));
|
||||
public void unregister(final Subcommand @NotNull ... subcommand) {
|
||||
subcommands.removeAll(Arrays.asList(subcommand));
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import xyz.jonesdev.sonar.api.Sonar;
|
||||
import xyz.jonesdev.sonar.api.command.SonarCommand;
|
||||
import xyz.jonesdev.sonar.api.logger.LoggerWrapper;
|
||||
import xyz.jonesdev.sonar.api.ormlite.H2DatabaseTypeAdapter;
|
||||
import xyz.jonesdev.sonar.api.ormlite.MariaDbDatabaseTypeAdapter;
|
||||
import xyz.jonesdev.sonar.api.ormlite.MysqlDatabaseTypeAdapter;
|
||||
import xyz.jonesdev.sonar.api.webhook.DiscordWebhook;
|
||||
@@ -45,6 +46,7 @@ import java.util.regex.Pattern;
|
||||
public final class SonarConfiguration {
|
||||
@Getter
|
||||
private final SimpleYamlConfig generalConfig, messagesConfig, webhookConfig;
|
||||
@Getter
|
||||
private final File languageFile, pluginFolder;
|
||||
|
||||
static final LoggerWrapper LOGGER = new LoggerWrapper() {
|
||||
@@ -163,6 +165,7 @@ public final class SonarConfiguration {
|
||||
|
||||
// Database
|
||||
database.type = Database.Type.valueOf(generalConfig.getString("database.type").toUpperCase());
|
||||
database.filename = generalConfig.getString("database.filename");
|
||||
database.host = generalConfig.getString("database.host");
|
||||
database.port = generalConfig.getInt("database.port");
|
||||
database.name = generalConfig.getString("database.name");
|
||||
@@ -486,6 +489,7 @@ public final class SonarConfiguration {
|
||||
public enum Type {
|
||||
MYSQL("jdbc:mysql://%s:%d/%s", new MysqlDatabaseTypeAdapter()),
|
||||
MARIADB("jdbc:mariadb://%s:%d/%s", new MariaDbDatabaseTypeAdapter()),
|
||||
H2("jdbc:h2:file:%s", new H2DatabaseTypeAdapter()),
|
||||
NONE(null, null);
|
||||
|
||||
private final String connectionString;
|
||||
@@ -493,6 +497,7 @@ public final class SonarConfiguration {
|
||||
}
|
||||
|
||||
private Type type;
|
||||
private String filename;
|
||||
private String host;
|
||||
private int port;
|
||||
private String name;
|
||||
|
||||
+14
-6
@@ -33,6 +33,7 @@ import xyz.jonesdev.sonar.api.config.SonarConfiguration;
|
||||
import xyz.jonesdev.sonar.api.logger.LoggerWrapper;
|
||||
import xyz.jonesdev.sonar.api.model.VerifiedPlayer;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.Instant;
|
||||
@@ -81,16 +82,24 @@ public final class VerifiedPlayerController {
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize MySQL/MariaDB driver
|
||||
database.getType().getDatabaseType().loadDriver();
|
||||
|
||||
try {
|
||||
connectionSource = new JdbcPooledConnectionSource(
|
||||
String.format(database.getType().getConnectionString(),
|
||||
database.getHost(), database.getPort(), database.getName()),
|
||||
String jdbcURL = String.format(database.getType().getConnectionString(),
|
||||
database.getHost(), database.getPort(), database.getName());
|
||||
|
||||
// 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().getDatabase().getFilename());
|
||||
jdbcURL = String.format(database.getType().getConnectionString(), file.getAbsolutePath());
|
||||
}
|
||||
|
||||
connectionSource = new JdbcPooledConnectionSource(jdbcURL,
|
||||
database.getUsername(), database.getPassword(), database.getType().getDatabaseType());
|
||||
|
||||
// Create table
|
||||
// Create database table
|
||||
try {
|
||||
TableUtils.createTableIfNotExists(connectionSource, VerifiedPlayer.class);
|
||||
} catch (SQLException exception) {
|
||||
@@ -126,7 +135,6 @@ public final class VerifiedPlayerController {
|
||||
// The connection source will always be null if the database type is NONE.
|
||||
if (connectionSource != null) {
|
||||
try {
|
||||
// Properly close the connection
|
||||
connectionSource.close();
|
||||
} catch (Exception exception) {
|
||||
LOGGER.error("Error closing database: {}", exception);
|
||||
|
||||
@@ -21,7 +21,6 @@ import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.util.ReferenceCountUtil;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import xyz.jonesdev.sonar.api.fallback.protocol.ProtocolVersion;
|
||||
import xyz.jonesdev.sonar.api.timer.SystemTimer;
|
||||
@@ -60,10 +59,8 @@ public interface FallbackUser {
|
||||
* using our custom Disconnect packet.
|
||||
*
|
||||
* @param reason Disconnect message component
|
||||
* @param duringLogin True, if the player has not joined yet
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
void disconnect(final @NotNull Component reason, final boolean duringLogin);
|
||||
void disconnect(final @NotNull Component reason);
|
||||
|
||||
/**
|
||||
* Takes over the channel and begins the verification process
|
||||
|
||||
+10
-14
@@ -15,21 +15,17 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package xyz.jonesdev.sonar.common.subcommand;
|
||||
package xyz.jonesdev.sonar.api.ormlite;
|
||||
|
||||
import xyz.jonesdev.sonar.api.command.subcommand.SubcommandRegistry;
|
||||
import xyz.jonesdev.sonar.common.subcommand.impl.*;
|
||||
import com.j256.ormlite.jdbc.db.H2DatabaseType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public final class SubcommandRegistryHolder implements SubcommandRegistry {
|
||||
public SubcommandRegistryHolder() {
|
||||
register(
|
||||
new BlacklistCommand(),
|
||||
new VerifiedCommand(),
|
||||
new StatisticsCommand(),
|
||||
new VerboseCommand(),
|
||||
new ReloadCommand(),
|
||||
new DumpCommand(),
|
||||
new NotifyCommand()
|
||||
);
|
||||
public final class H2DatabaseTypeAdapter extends H2DatabaseType {
|
||||
|
||||
// We need to override the default driver class name
|
||||
// to use the custom relocated H2 driver
|
||||
@Override
|
||||
protected String @NotNull [] getDriverClassNames() {
|
||||
return new String[]{"xyz.jonesdev.sonar.libs.h2.Driver"};
|
||||
}
|
||||
}
|
||||
+2
-5
@@ -22,11 +22,8 @@ import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public final class MariaDbDatabaseTypeAdapter extends MariaDbDatabaseType {
|
||||
|
||||
/**
|
||||
* We need to override the default driver class name
|
||||
* in order to use the custom relocated MariaDB driver
|
||||
* Read more: {@link MysqlDatabaseTypeAdapter}
|
||||
*/
|
||||
// We need to override the default driver class name
|
||||
// to use the custom relocated MariaDB driver
|
||||
@Override
|
||||
protected String @NotNull [] getDriverClassNames() {
|
||||
return new String[]{"xyz.jonesdev.sonar.libs.mariadb.jdbc.Driver"};
|
||||
|
||||
+2
-5
@@ -22,11 +22,8 @@ import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public final class MysqlDatabaseTypeAdapter extends MysqlDatabaseType {
|
||||
|
||||
/**
|
||||
* We need to override the default driver class name
|
||||
* in order to use the custom relocated MySQL driver
|
||||
* Read more: {@link MariaDbDatabaseTypeAdapter}
|
||||
*/
|
||||
// We need to override the default driver class name
|
||||
// to use the custom relocated MySQL driver
|
||||
@Override
|
||||
protected String @NotNull [] getDriverClassNames() {
|
||||
return new String[]{"xyz.jonesdev.sonar.libs.mysql.cj.jdbc.Driver"};
|
||||
|
||||
@@ -7,7 +7,7 @@ plugins {
|
||||
bukkit {
|
||||
name = rootProject.name
|
||||
description = rootProject.description
|
||||
version = rootProject.version.toString().split("-")[0]
|
||||
version = rootProject.version.toString()
|
||||
main = "xyz.jonesdev.sonar.bukkit.SonarBukkitPlugin"
|
||||
authors = listOf("Jones Development", "Sonar Contributors")
|
||||
website = "https://jonesdev.xyz/discord/"
|
||||
|
||||
@@ -5,7 +5,7 @@ plugins {
|
||||
bungee {
|
||||
name = rootProject.name
|
||||
description = rootProject.description
|
||||
version = rootProject.version.toString().split("-")[0]
|
||||
version = rootProject.version.toString()
|
||||
main = "xyz.jonesdev.sonar.bungee.SonarBungeePlugin"
|
||||
author = "Jones Development, Sonar Contributors"
|
||||
softDepends = setOf("Geyser-BungeeCord", "floodgate", "Protocolize", "ViaVersion", "packetevents", "FastLogin")
|
||||
|
||||
@@ -28,7 +28,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import xyz.jonesdev.sonar.api.SonarPlatform;
|
||||
import xyz.jonesdev.sonar.api.logger.LoggerWrapper;
|
||||
import xyz.jonesdev.sonar.bungee.command.BungeeSonarCommand;
|
||||
import xyz.jonesdev.sonar.bungee.fallback.FallbackInjectionHelper;
|
||||
import xyz.jonesdev.sonar.bungee.fallback.FallbackBungeeInjector;
|
||||
import xyz.jonesdev.sonar.common.boot.SonarBootstrap;
|
||||
|
||||
import java.util.UUID;
|
||||
@@ -96,7 +96,7 @@ public final class SonarBungee extends SonarBootstrap<SonarBungeePlugin> {
|
||||
getPlugin().getServer().getPluginManager().registerCommand(getPlugin(), new BungeeSonarCommand());
|
||||
|
||||
// Make sure to inject into the server's connection handler
|
||||
FallbackInjectionHelper.inject();
|
||||
FallbackBungeeInjector.inject();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
-2
@@ -35,9 +35,9 @@ import java.net.InetSocketAddress;
|
||||
|
||||
import static net.md_5.bungee.netty.PipelineUtils.*;
|
||||
|
||||
public final class FallbackChannelHandler extends FallbackChannelHandlerAdapter {
|
||||
public final class FallbackBungeeChannelHandler extends FallbackChannelHandlerAdapter {
|
||||
|
||||
public FallbackChannelHandler(final @NotNull Channel channel) {
|
||||
public FallbackBungeeChannelHandler(final @NotNull Channel channel) {
|
||||
super(channel);
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ public final class FallbackChannelHandler extends FallbackChannelHandlerAdapter
|
||||
|
||||
@Override
|
||||
public void channelRead(final @NotNull ChannelHandlerContext ctx, final Object msg) throws Exception {
|
||||
// TODO: put this into a separate handler
|
||||
// Intercept any packets processed by BungeeCord
|
||||
if (listenForPackets && msg instanceof PacketWrapper) {
|
||||
final PacketWrapper packetWrapper = (PacketWrapper) msg;
|
||||
+8
-2
@@ -23,11 +23,15 @@ import lombok.experimental.UtilityClass;
|
||||
import net.md_5.bungee.netty.PipelineUtils;
|
||||
import sun.misc.Unsafe;
|
||||
import xyz.jonesdev.sonar.api.ReflectiveOperationException;
|
||||
import xyz.jonesdev.sonar.common.fallback.injection.FallbackInjectedChannelInitializer;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import static net.md_5.bungee.netty.PipelineUtils.PACKET_DECODER;
|
||||
import static xyz.jonesdev.sonar.api.fallback.FallbackPipelines.FALLBACK_HANDLER;
|
||||
|
||||
@UtilityClass
|
||||
public class FallbackInjectionHelper {
|
||||
public class FallbackBungeeInjector {
|
||||
public void inject() {
|
||||
try {
|
||||
final Field childField = PipelineUtils.class.getField("SERVER_CHILD");
|
||||
@@ -35,7 +39,9 @@ public class FallbackInjectionHelper {
|
||||
|
||||
// Make sure to store the original channel initializer
|
||||
final ChannelInitializer<Channel> originalInitializer = PipelineUtils.SERVER_CHILD;
|
||||
final ChannelInitializer<Channel> fallbackInitializer = new FallbackChannelInitializer(originalInitializer);
|
||||
final ChannelInitializer<Channel> fallbackInitializer = new FallbackInjectedChannelInitializer(
|
||||
originalInitializer, pipeline -> pipeline.addAfter(PACKET_DECODER, FALLBACK_HANDLER,
|
||||
new FallbackBungeeChannelHandler(pipeline.channel())));
|
||||
|
||||
final Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
|
||||
unsafeField.setAccessible(true);
|
||||
@@ -61,15 +61,22 @@ class LibraryLoader {
|
||||
Library.builder()
|
||||
.groupId("com{}mysql")
|
||||
.artifactId("mysql-connector-j")
|
||||
.version("8.3.0")
|
||||
.version("8.4.0")
|
||||
.relocate("com{}mysql", "xyz{}jonesdev{}sonar{}libs{}mysql")
|
||||
.build(),
|
||||
// MariaDB driver
|
||||
Library.builder()
|
||||
.groupId("org{}mariadb{}jdbc")
|
||||
.artifactId("mariadb-java-client")
|
||||
.version("3.3.3")
|
||||
.version("3.4.0")
|
||||
.relocate("org{}mariadb", "xyz{}jonesdev{}sonar{}libs{}mariadb")
|
||||
.build(),
|
||||
// H2 driver
|
||||
Library.builder()
|
||||
.groupId("com{}h2database")
|
||||
.artifactId("h2")
|
||||
.version("2.1.214")
|
||||
.relocate("org{}h2", "xyz{}jonesdev{}sonar{}libs{}h2")
|
||||
.build()
|
||||
);
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ import xyz.jonesdev.sonar.api.verbose.Verbose;
|
||||
import xyz.jonesdev.sonar.common.fallback.protocol.FallbackPreparer;
|
||||
import xyz.jonesdev.sonar.common.service.SonarServiceManager;
|
||||
import xyz.jonesdev.sonar.common.statistics.GlobalSonarStatistics;
|
||||
import xyz.jonesdev.sonar.common.subcommand.SubcommandRegistryHolder;
|
||||
import xyz.jonesdev.sonar.common.subcommands.*;
|
||||
import xyz.jonesdev.sonar.common.update.UpdateChecker;
|
||||
|
||||
import java.io.File;
|
||||
@@ -76,14 +76,23 @@ public abstract class SonarBootstrap<T> implements Sonar {
|
||||
this.verboseHandler = new Verbose();
|
||||
this.notificationHandler = new Notification();
|
||||
this.config = new SonarConfiguration(dataDirectory);
|
||||
this.subcommandRegistry = new SubcommandRegistryHolder();
|
||||
this.subcommandRegistry = new SubcommandRegistry();
|
||||
// Register all subcommands
|
||||
this.subcommandRegistry.register(
|
||||
new BlacklistCommand(),
|
||||
new VerifiedCommand(),
|
||||
new StatisticsCommand(),
|
||||
new VerboseCommand(),
|
||||
new ReloadCommand(),
|
||||
new DumpCommand(),
|
||||
new NotifyCommand());
|
||||
// Hide unnecessary debug information
|
||||
Logger.setGlobalLogLevel(Level.WARNING);
|
||||
}
|
||||
|
||||
public final void initialize() {
|
||||
// Check if the branch is not the main branch to warn about unstable versions
|
||||
if (!getVersion().isOnMainBranch()) {
|
||||
if (!getVersion().getGitBranch().equals("main")) {
|
||||
getLogger().warn("You are currently using an unofficial experimental branch.");
|
||||
getLogger().warn("It is highly recommended to use the latest stable release of Sonar:");
|
||||
getLogger().warn("https://github.com/jonesdevelopment/sonar/releases");
|
||||
|
||||
+1
-1
@@ -232,7 +232,7 @@ public class FallbackChannelHandlerAdapter extends ChannelInboundHandlerAdapter
|
||||
// Check if the number of online players using the same IP address as
|
||||
// the connecting player is greater than the configured amount
|
||||
final int onlinePerIp = FALLBACK.getOnline().getOrDefault(inetAddress, 0);
|
||||
if (onlinePerIp > maxOnlinePerIp) {
|
||||
if (onlinePerIp >= maxOnlinePerIp) {
|
||||
customDisconnect(channel, protocolVersion, tooManyOnlinePerIP, encoder, handler);
|
||||
return;
|
||||
}
|
||||
|
||||
+10
-14
@@ -53,7 +53,7 @@ import static xyz.jonesdev.sonar.common.fallback.protocol.FallbackPacketRegistry
|
||||
import static xyz.jonesdev.sonar.common.fallback.protocol.FallbackPacketRegistry.GAME;
|
||||
|
||||
@Getter
|
||||
@ToString(of = {"protocolVersion", "inetAddress"})
|
||||
@ToString(of = {"protocolVersion", "inetAddress", "geyser"})
|
||||
public final class FallbackUserWrapper implements FallbackUser {
|
||||
private final Channel channel;
|
||||
private final ChannelPipeline pipeline;
|
||||
@@ -78,7 +78,9 @@ public final class FallbackUserWrapper implements FallbackUser {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect(final @NotNull Component reason, final boolean duringLogin) {
|
||||
public void disconnect(final @NotNull Component reason) {
|
||||
final FallbackPacketEncoder encoder = pipeline.get(FallbackPacketEncoder.class);
|
||||
final boolean duringLogin = encoder != null && encoder.getPacketRegistry() != GAME;
|
||||
closeWith(channel, protocolVersion, DisconnectPacket.create(reason, duringLogin));
|
||||
}
|
||||
|
||||
@@ -131,23 +133,17 @@ public final class FallbackUserWrapper implements FallbackUser {
|
||||
// The LoginSuccess packet has been sent, now we can change the registry state
|
||||
newEncoder.updateRegistry(protocolVersion.compareTo(MINECRAFT_1_20_2) >= 0 ? CONFIG : GAME);
|
||||
|
||||
try {
|
||||
// Replace normal decoder to allow custom packets
|
||||
final FallbackPacketDecoder fallbackPacketDecoder = new FallbackPacketDecoder(protocolVersion);
|
||||
pipeline.replace(decoder, FALLBACK_PACKET_DECODER, fallbackPacketDecoder);
|
||||
// Listen for all incoming packets by setting the packet listener
|
||||
fallbackPacketDecoder.setListener(new FallbackLoginSessionHandler(this, username, uuid));
|
||||
} catch (Throwable throwable) {
|
||||
// This rarely happens when the channel hangs and the player is still connecting
|
||||
// I honestly have no idea how else I'm supposed to fix this
|
||||
channel.close();
|
||||
}
|
||||
// Replace normal decoder to allow custom packets
|
||||
final FallbackPacketDecoder fallbackPacketDecoder = new FallbackPacketDecoder(protocolVersion);
|
||||
pipeline.replace(decoder, FALLBACK_PACKET_DECODER, fallbackPacketDecoder);
|
||||
// Listen for all incoming packets by setting the packet listener
|
||||
fallbackPacketDecoder.setListener(new FallbackLoginSessionHandler(this, username, uuid));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fail(final @NotNull String reason) {
|
||||
disconnect(Sonar.get().getConfig().getVerification().getVerificationFailed(), false);
|
||||
disconnect(Sonar.get().getConfig().getVerification().getVerificationFailed());
|
||||
|
||||
// Only log the failed message if the server isn't currently under attack.
|
||||
// However, we let the user override this through the configuration.
|
||||
|
||||
+8
-7
@@ -15,22 +15,21 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package xyz.jonesdev.sonar.bungee.fallback;
|
||||
package xyz.jonesdev.sonar.common.fallback.injection;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import xyz.jonesdev.sonar.api.ReflectiveOperationException;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
|
||||
import static net.md_5.bungee.netty.PipelineUtils.PACKET_DECODER;
|
||||
import static xyz.jonesdev.sonar.api.fallback.FallbackPipelines.FALLBACK_HANDLER;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public final class FallbackChannelInitializer extends ChannelInitializer<Channel> {
|
||||
public final class FallbackInjectedChannelInitializer extends ChannelInitializer<Channel> {
|
||||
private static final MethodHandle INIT_CHANNEL_METHOD;
|
||||
|
||||
static {
|
||||
@@ -43,6 +42,7 @@ public final class FallbackChannelInitializer extends ChannelInitializer<Channel
|
||||
}
|
||||
|
||||
private final ChannelInitializer<Channel> originalChannelInitializer;
|
||||
private final Consumer<ChannelPipeline> sonarPipelineInjector;
|
||||
|
||||
@Override
|
||||
protected void initChannel(final Channel channel) throws Exception {
|
||||
@@ -53,8 +53,9 @@ public final class FallbackChannelInitializer extends ChannelInitializer<Channel
|
||||
throw new ReflectiveOperationException(throwable);
|
||||
}
|
||||
|
||||
if (channel.pipeline().get(PACKET_DECODER) != null) {
|
||||
channel.pipeline().addAfter(PACKET_DECODER, FALLBACK_HANDLER, new FallbackChannelHandler(channel));
|
||||
// Inject Sonar's channel handler into the pipeline
|
||||
if (channel.isActive()) {
|
||||
sonarPipelineInjector.accept(channel.pipeline());
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
-4
@@ -20,6 +20,7 @@ package xyz.jonesdev.sonar.common.fallback.protocol;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
import lombok.Getter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import xyz.jonesdev.sonar.api.fallback.protocol.ProtocolVersion;
|
||||
|
||||
@@ -29,15 +30,18 @@ import static xyz.jonesdev.sonar.common.util.ProtocolUtil.writeVarInt;
|
||||
|
||||
public final class FallbackPacketEncoder extends MessageToByteEncoder<FallbackPacket> {
|
||||
private final ProtocolVersion protocolVersion;
|
||||
private FallbackPacketRegistry.ProtocolRegistry registry;
|
||||
@Getter
|
||||
private FallbackPacketRegistry packetRegistry;
|
||||
private FallbackPacketRegistry.ProtocolRegistry protocolRegistry;
|
||||
|
||||
public FallbackPacketEncoder(final ProtocolVersion protocolVersion) {
|
||||
this.protocolVersion = protocolVersion;
|
||||
updateRegistry(LOGIN);
|
||||
}
|
||||
|
||||
public void updateRegistry(final @NotNull FallbackPacketRegistry registry) {
|
||||
this.registry = registry.getProtocolRegistry(CLIENTBOUND, protocolVersion);
|
||||
public void updateRegistry(final @NotNull FallbackPacketRegistry packetRegistry) {
|
||||
this.packetRegistry = packetRegistry;
|
||||
this.protocolRegistry = packetRegistry.getProtocolRegistry(CLIENTBOUND, protocolVersion);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -46,7 +50,7 @@ public final class FallbackPacketEncoder extends MessageToByteEncoder<FallbackPa
|
||||
final ByteBuf out) throws Exception {
|
||||
final FallbackPacket originalPacket = packet instanceof FallbackPacketSnapshot
|
||||
? ((FallbackPacketSnapshot) packet).getOriginalPacket() : packet;
|
||||
final int packetId = registry.getPacketId(originalPacket);
|
||||
final int packetId = protocolRegistry.getPacketId(originalPacket);
|
||||
writeVarInt(out, packetId);
|
||||
packet.encode(out, protocolVersion);
|
||||
}
|
||||
|
||||
+2
-2
@@ -34,11 +34,11 @@ import xyz.jonesdev.sonar.common.util.ComponentHolder;
|
||||
@AllArgsConstructor
|
||||
public final class DisconnectPacket implements FallbackPacket {
|
||||
private @NotNull ComponentHolder componentHolder;
|
||||
private boolean login;
|
||||
private boolean duringLogin;
|
||||
|
||||
@Override
|
||||
public void encode(final ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) throws Exception {
|
||||
componentHolder.write(byteBuf, login ? ProtocolVersion.MINECRAFT_1_20_2 : protocolVersion);
|
||||
componentHolder.write(byteBuf, duringLogin ? ProtocolVersion.MINECRAFT_1_20_2 : protocolVersion);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+16
-17
@@ -33,7 +33,9 @@ import java.util.Random;
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static xyz.jonesdev.sonar.api.fallback.protocol.ProtocolVersion.*;
|
||||
import static xyz.jonesdev.sonar.api.fallback.protocol.ProtocolVersion.MINECRAFT_1_13;
|
||||
import static xyz.jonesdev.sonar.api.fallback.protocol.ProtocolVersion.MINECRAFT_1_20_5;
|
||||
import static xyz.jonesdev.sonar.common.fallback.FallbackUserWrapper.closeWith;
|
||||
import static xyz.jonesdev.sonar.common.fallback.protocol.FallbackPreparer.transferToOrigin;
|
||||
import static xyz.jonesdev.sonar.common.util.ProtocolUtil.BRAND_CHANNEL;
|
||||
import static xyz.jonesdev.sonar.common.util.ProtocolUtil.BRAND_CHANNEL_LEGACY;
|
||||
@@ -70,12 +72,11 @@ public abstract class FallbackSessionHandler implements FallbackPacketListener {
|
||||
// This feature was introduced by Mojang in Minecraft version 1.20.5.
|
||||
if (transferToOrigin != null
|
||||
&& user.getProtocolVersion().compareTo(MINECRAFT_1_20_5) >= 0) {
|
||||
user.write(transferToOrigin);
|
||||
// Close the channel to ensure that the connection is closed
|
||||
user.getChannel().close();
|
||||
// Send the transfer packet to the player and close the channel
|
||||
closeWith(user.getChannel(), user.getProtocolVersion(), transferToOrigin);
|
||||
} else {
|
||||
// Disconnect player with the verification success message
|
||||
user.disconnect(Sonar.get().getConfig().getVerification().getVerificationSuccess(), false);
|
||||
user.disconnect(Sonar.get().getConfig().getVerification().getVerificationSuccess());
|
||||
}
|
||||
|
||||
Sonar.get().getFallback().getLogger().info(
|
||||
@@ -121,22 +122,20 @@ public abstract class FallbackSessionHandler implements FallbackPacketListener {
|
||||
}
|
||||
|
||||
protected final void validateClientBrand(final byte @NotNull [] data) {
|
||||
// No need to check for empty brands since ProtocolUtil#readBrandMessage
|
||||
// already performs invalid string checks by default.
|
||||
String read = new String(data, StandardCharsets.UTF_8);
|
||||
checkState(read.length() > 1, "client brand is too short");
|
||||
// Remove the invalid character at the beginning of the client brand
|
||||
if (user.getProtocolVersion().compareTo(MINECRAFT_1_8) >= 0) {
|
||||
read = read.substring(1);
|
||||
}
|
||||
// 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(read.length() < Sonar.get().getConfig().getVerification().getBrand().getMaxLength(),
|
||||
"client brand is too long: " + read.length());
|
||||
checkState(data.length < Sonar.get().getConfig().getVerification().getBrand().getMaxLength(),
|
||||
"client brand contains too much data: " + data.length);
|
||||
// Don't even ask - Minecraft 1.7 simply sends the string, but all other versions send something else
|
||||
// This is pretty much a lazy-fix, but, hey, it works; I'm not complaining.
|
||||
// Read more: https://discord.com/channels/923308209769426994/1116066363887321199/1256929441053933608
|
||||
final String brand = new String(data, StandardCharsets.UTF_8).replaceFirst("\7", "");
|
||||
// Check for illegal client brands
|
||||
checkState(!read.equals("Vanilla"), "illegal client brand: " + read);
|
||||
checkState(!brand.equals("Vanilla"), "illegal client brand: " + brand);
|
||||
// Regex pattern for validating client brands
|
||||
final Pattern pattern = Sonar.get().getConfig().getVerification().getBrand().getValidRegex();
|
||||
checkState(pattern.matcher(read).matches(), "client brand does not match pattern");
|
||||
checkState(pattern.matcher(brand).matches(), "client brand does not match pattern");
|
||||
}
|
||||
|
||||
protected final void validateClientLocale(final @NotNull String locale) {
|
||||
|
||||
+2
-9
@@ -15,7 +15,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package xyz.jonesdev.sonar.common.subcommand.impl;
|
||||
package xyz.jonesdev.sonar.common.subcommands;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
@@ -26,20 +26,13 @@ import xyz.jonesdev.sonar.api.Sonar;
|
||||
import xyz.jonesdev.sonar.api.command.CommandInvocation;
|
||||
import xyz.jonesdev.sonar.api.command.subcommand.Subcommand;
|
||||
import xyz.jonesdev.sonar.api.command.subcommand.SubcommandInfo;
|
||||
import xyz.jonesdev.sonar.api.command.subcommand.argument.Argument;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
@SubcommandInfo(
|
||||
name = "blacklist",
|
||||
description = "Manage blacklisted IP addresses",
|
||||
arguments = {
|
||||
@Argument("add"),
|
||||
@Argument("remove"),
|
||||
@Argument("clear"),
|
||||
@Argument("size")
|
||||
}
|
||||
arguments = {"add", "remove", "clear", "size"}
|
||||
)
|
||||
public final class BlacklistCommand extends Subcommand {
|
||||
|
||||
+8
-6
@@ -15,7 +15,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package xyz.jonesdev.sonar.common.subcommand.impl;
|
||||
package xyz.jonesdev.sonar.common.subcommands;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
@@ -38,7 +38,6 @@ import static xyz.jonesdev.sonar.api.jvm.JVMProcessInformation.*;
|
||||
// the Sonar contributors to fix issues more quickly
|
||||
@SubcommandInfo(
|
||||
name = "dump",
|
||||
description = "Print developer information",
|
||||
onlyConsole = true
|
||||
)
|
||||
public final class DumpCommand extends Subcommand {
|
||||
@@ -50,9 +49,10 @@ public final class DumpCommand extends Subcommand {
|
||||
protected void execute(final @NotNull CommandInvocation invocation) {
|
||||
final var mappings = new WeakHashMap<String, Object>();
|
||||
mappings.put("sonar", new Dump.Sonar(
|
||||
Sonar.get().getVersion().getFull(),
|
||||
Sonar.get().getVersion().getFormatted(),
|
||||
Sonar.get().getPlatform(),
|
||||
Sonar.get().getVersion().isOnMainBranch()
|
||||
Sonar.get().getVersion().getGitBranch(),
|
||||
Sonar.get().getVersion().getGitCommit()
|
||||
));
|
||||
mappings.put("runtime", new Dump.Runtime(
|
||||
getVirtualCores(),
|
||||
@@ -72,7 +72,8 @@ public final class DumpCommand extends Subcommand {
|
||||
formatMemory(getFreeMemory()),
|
||||
formatMemory(getUsedMemory())
|
||||
));
|
||||
Sonar.get().getLogger().info("Generated dump: {}", GSON.toJson(mappings));
|
||||
Sonar.get().getLogger().info(Sonar.get().getConfig().getMessagesConfig().getString("commands.dump.log")
|
||||
.replace("<dumped-json-data>", GSON.toJson(mappings)));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@@ -82,7 +83,8 @@ public final class DumpCommand extends Subcommand {
|
||||
private static final class Sonar {
|
||||
private final String version;
|
||||
private final SonarPlatform platform;
|
||||
private final boolean isOnMainBranch;
|
||||
private final String gitBranch;
|
||||
private final String gitCommit;
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
+1
-2
@@ -15,7 +15,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package xyz.jonesdev.sonar.common.subcommand.impl;
|
||||
package xyz.jonesdev.sonar.common.subcommands;
|
||||
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
|
||||
@@ -27,7 +27,6 @@ import xyz.jonesdev.sonar.api.command.subcommand.SubcommandInfo;
|
||||
|
||||
@SubcommandInfo(
|
||||
name = "notify",
|
||||
description = "Enable or disable attack notifications",
|
||||
onlyPlayers = true
|
||||
)
|
||||
public final class NotifyCommand extends Subcommand {
|
||||
+2
-3
@@ -15,7 +15,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package xyz.jonesdev.sonar.common.subcommand.impl;
|
||||
package xyz.jonesdev.sonar.common.subcommands;
|
||||
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
|
||||
@@ -27,8 +27,7 @@ import xyz.jonesdev.sonar.api.command.subcommand.SubcommandInfo;
|
||||
import xyz.jonesdev.sonar.api.timer.SystemTimer;
|
||||
|
||||
@SubcommandInfo(
|
||||
name = "reload",
|
||||
description = "Reload all configurations"
|
||||
name = "reload"
|
||||
)
|
||||
public final class ReloadCommand extends Subcommand {
|
||||
|
||||
+2
-8
@@ -15,7 +15,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package xyz.jonesdev.sonar.common.subcommand.impl;
|
||||
package xyz.jonesdev.sonar.common.subcommands;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
@@ -26,7 +26,6 @@ import xyz.jonesdev.sonar.api.Sonar;
|
||||
import xyz.jonesdev.sonar.api.command.CommandInvocation;
|
||||
import xyz.jonesdev.sonar.api.command.subcommand.Subcommand;
|
||||
import xyz.jonesdev.sonar.api.command.subcommand.SubcommandInfo;
|
||||
import xyz.jonesdev.sonar.api.command.subcommand.argument.Argument;
|
||||
import xyz.jonesdev.sonar.common.statistics.CachedBandwidthStatistics;
|
||||
|
||||
import static xyz.jonesdev.sonar.api.Sonar.DECIMAL_FORMAT;
|
||||
@@ -35,12 +34,7 @@ import static xyz.jonesdev.sonar.api.jvm.JVMProcessInformation.*;
|
||||
@SubcommandInfo(
|
||||
name = "statistics",
|
||||
aliases = {"stats"},
|
||||
description = "Show session statistics of this server",
|
||||
arguments = {
|
||||
@Argument("network"),
|
||||
@Argument("memory"),
|
||||
@Argument("cpu")
|
||||
},
|
||||
arguments = {"network", "memory", "cpu"},
|
||||
argumentsRequired = false
|
||||
)
|
||||
public final class StatisticsCommand extends Subcommand {
|
||||
+1
-2
@@ -15,7 +15,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package xyz.jonesdev.sonar.common.subcommand.impl;
|
||||
package xyz.jonesdev.sonar.common.subcommands;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
@@ -28,7 +28,6 @@ import xyz.jonesdev.sonar.api.command.subcommand.SubcommandInfo;
|
||||
|
||||
@SubcommandInfo(
|
||||
name = "verbose",
|
||||
description = "Enable or disable Sonar verbose",
|
||||
onlyPlayers = true
|
||||
)
|
||||
public final class VerboseCommand extends Subcommand {
|
||||
+2
-10
@@ -15,7 +15,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package xyz.jonesdev.sonar.common.subcommand.impl;
|
||||
package xyz.jonesdev.sonar.common.subcommands;
|
||||
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
|
||||
@@ -24,7 +24,6 @@ import xyz.jonesdev.sonar.api.Sonar;
|
||||
import xyz.jonesdev.sonar.api.command.CommandInvocation;
|
||||
import xyz.jonesdev.sonar.api.command.subcommand.Subcommand;
|
||||
import xyz.jonesdev.sonar.api.command.subcommand.SubcommandInfo;
|
||||
import xyz.jonesdev.sonar.api.command.subcommand.argument.Argument;
|
||||
import xyz.jonesdev.sonar.api.model.VerifiedPlayer;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
@@ -32,14 +31,7 @@ import java.util.UUID;
|
||||
|
||||
@SubcommandInfo(
|
||||
name = "verified",
|
||||
description = "Manage verified IP addresses",
|
||||
arguments = {
|
||||
@Argument("history"),
|
||||
@Argument("remove"),
|
||||
@Argument("add"),
|
||||
@Argument("clear"),
|
||||
@Argument("size")
|
||||
}
|
||||
arguments = {"add", "remove", "clear", "size", "history"}
|
||||
)
|
||||
public final class VerifiedCommand extends Subcommand {
|
||||
|
||||
@@ -55,6 +55,56 @@ public class UpdateChecker {
|
||||
}
|
||||
};
|
||||
|
||||
public void checkForUpdates() {
|
||||
ASYNC_EXECUTOR.execute(() -> {
|
||||
try {
|
||||
final URL url = new URL("https://api.github.com/repos/jonesdevelopment/sonar/releases/latest");
|
||||
final HttpsURLConnection urlConnection = prepareConnection(url);
|
||||
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());
|
||||
|
||||
if (convertedCurrentVersion < convertedLatestVersion) {
|
||||
LOGGER.warn("A new version of Sonar is available: {}", latestStableRelease);
|
||||
LOGGER.warn("Please make sure to update to the latest version to ensure stability and security:");
|
||||
LOGGER.warn("https://github.com/jonesdevelopment/sonar/releases/tag/{}", latestStableRelease);
|
||||
} else if (convertedCurrentVersion > convertedLatestVersion || !Sonar.get().getVersion().getGitBranch().equals("main")) {
|
||||
LOGGER.warn("You are currently using an unreleased version of Sonar!");
|
||||
LOGGER.warn("The contributors of Sonar are not responsible for any damage done by using an unstable version");
|
||||
} else {
|
||||
LOGGER.info("You are currently using the latest stable release of Sonar!");
|
||||
}
|
||||
} catch (Throwable throwable) {
|
||||
LOGGER.warn("Unable to retrieve version information: {}", throwable);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private @NotNull JsonObject parseJson(final @NotNull HttpsURLConnection urlConnection) throws IOException {
|
||||
try (final InputStream inputStream = urlConnection.getInputStream();
|
||||
final InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
|
||||
final BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {
|
||||
// Parse site content as JSON using Gson
|
||||
final JsonParser jsonParser = new JsonParser();
|
||||
return jsonParser.parse(bufferedReader).getAsJsonObject();
|
||||
}
|
||||
}
|
||||
|
||||
private @NotNull HttpsURLConnection prepareConnection(final @NotNull URL url) throws Exception {
|
||||
final HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
|
||||
// Set connection timeout
|
||||
urlConnection.setConnectTimeout(15000);
|
||||
urlConnection.setReadTimeout(15000);
|
||||
// Set necessary properties
|
||||
urlConnection.setRequestProperty("Accept", "application/vnd.github.v3+json");
|
||||
// Only continue if the connection is a success
|
||||
if (urlConnection.getResponseCode() != 200) {
|
||||
throw new IllegalStateException("Unexpected response code " + urlConnection.getResponseCode());
|
||||
}
|
||||
return urlConnection;
|
||||
}
|
||||
|
||||
private int convertVersion(final @NotNull String version) throws NumberFormatException, IllegalStateException {
|
||||
final String[] convertedParts = version.split("\\.");
|
||||
// Validate the length of the converted parts
|
||||
@@ -68,66 +118,4 @@ public class UpdateChecker {
|
||||
final int patch = Integer.parseInt(convertedParts[2]);
|
||||
return convertedMajor + convertedMinor + patch; // sum the converted version parts
|
||||
}
|
||||
|
||||
public void checkForUpdates() {
|
||||
ASYNC_EXECUTOR.execute(() -> {
|
||||
try {
|
||||
final URL url = new URL("https://api.github.com/repos/jonesdevelopment/sonar/releases/latest");
|
||||
final HttpsURLConnection urlConnection = prepareConnection(url);
|
||||
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().getSemanticVersion());
|
||||
|
||||
if (convertedCurrentVersion < convertedLatestVersion) {
|
||||
LOGGER.warn("A new version of Sonar is available: {}", latestStableRelease);
|
||||
LOGGER.warn("Please make sure to update to the latest version to ensure stability and security:");
|
||||
LOGGER.warn("https://github.com/jonesdevelopment/sonar/releases/tag/{}", latestStableRelease);
|
||||
} else if (convertedCurrentVersion > convertedLatestVersion || !Sonar.get().getVersion().isOnMainBranch()) {
|
||||
LOGGER.warn("You are currently using an unreleased version of Sonar!");
|
||||
LOGGER.warn("The contributors of Sonar are not responsible for any damage done by using an unstable version");
|
||||
} else {
|
||||
LOGGER.info("You are currently using the latest stable release of Sonar!");
|
||||
}
|
||||
} catch (Exception exception) {
|
||||
LOGGER.warn("Could not retrieve latest version information: {}", exception);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private @NotNull JsonObject parseJson(final @NotNull HttpsURLConnection urlConnection) throws IOException {
|
||||
try (final InputStream inputStream = urlConnection.getInputStream()) {
|
||||
try (final InputStreamReader inputStreamReader = new InputStreamReader(inputStream)) {
|
||||
final StringBuilder content = new StringBuilder();
|
||||
|
||||
// Read the entire page content
|
||||
try (final BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {
|
||||
String line;
|
||||
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
content.append(line);
|
||||
}
|
||||
}
|
||||
|
||||
// Parse site content as JSON using Gson
|
||||
final JsonParser jsonParser = new JsonParser();
|
||||
return jsonParser.parse(content.toString()).getAsJsonObject();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private @NotNull HttpsURLConnection prepareConnection(final @NotNull URL url) throws Exception {
|
||||
final HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
|
||||
// Set connection timeout
|
||||
urlConnection.setConnectTimeout(15000);
|
||||
urlConnection.setReadTimeout(15000);
|
||||
// Set necessary properties
|
||||
urlConnection.setRequestMethod("GET");
|
||||
urlConnection.setRequestProperty("Accept", "application/vnd.github.v3+json");
|
||||
// Only continue if the connection is a success
|
||||
if (urlConnection.getResponseCode() != 200) {
|
||||
throw new IllegalStateException("Unexpected response code " + urlConnection.getResponseCode());
|
||||
}
|
||||
return urlConnection;
|
||||
}
|
||||
}
|
||||
@@ -43,8 +43,10 @@ attack-tracker:
|
||||
# Nicméně, IP adresy nemůžou být vystopovány zpátky k hráči, protože Sonar používá UUID na ukládní místo jmeno hráčů
|
||||
database:
|
||||
# Typy datábázi se kterýma Sonar bude pracovat
|
||||
# Typy: NONE, MYSQL, MARIADB
|
||||
# Typy: NONE, MYSQL, MARIADB, H2
|
||||
type: NONE
|
||||
# Soubor v adresáři zásuvných modulů Sonaru použitý pro databázi H2
|
||||
filename: verified_players
|
||||
# Host adresa pro verifikování hráčů s SQL databází
|
||||
host: localhost
|
||||
# Port pro verifikaci s databází
|
||||
|
||||
@@ -40,8 +40,10 @@ attack-tracker:
|
||||
# Beachte: IP adressen werden im Klartext gespeichert. Du bist für die Sicherheit der Datenbank verantwortlich
|
||||
database:
|
||||
# Typ von Datenbank die Sonar verwenden soll, um verifizierte Spielerdaten zu speichern
|
||||
# Mögliche Typen: NONE, MYSQL, MARIADB
|
||||
# Mögliche Typen: NONE, MYSQL, MARIADB, H2
|
||||
type: NONE
|
||||
# Datei im Plugin-Verzeichnis von Sonar, die für die H2-Datenbank verwendet wird
|
||||
filename: verified_players
|
||||
# HOST für die Authentifizierung mit der SQL Datenbank
|
||||
host: localhost
|
||||
# Port für die Authentifizierung mit der SQL Datenbank
|
||||
|
||||
@@ -42,8 +42,10 @@ attack-tracker:
|
||||
# Note: IP addresses are saved in plain text. You are responsible for keeping your database safe!
|
||||
database:
|
||||
# Type of database Sonar uses to store verified players
|
||||
# Possible types: NONE, MYSQL, MARIADB
|
||||
# Possible types: NONE, MYSQL, MARIADB, H2
|
||||
type: NONE
|
||||
# File in Sonar's plugin directory used for the H2 database
|
||||
filename: verified_players
|
||||
# Host address for authenticating with the SQL database
|
||||
host: localhost
|
||||
# Port for authenticating with the SQL database
|
||||
|
||||
@@ -42,8 +42,10 @@ attack-tracker:
|
||||
# Remarque : Les adresses IP sont enregistrées en texte brut. Vous êtes responsable de la sécurité de votre base de données !
|
||||
database:
|
||||
# Type de base de données utilisé par Sonar pour stocker les joueurs vérifiés
|
||||
# Types possibles : NONE, MYSQL, MARIADB
|
||||
# Types possibles : NONE, MYSQL, MARIADB, H2
|
||||
type: NONE
|
||||
# Fichier dans le répertoire des plugins de Sonar utilisé pour la base de données H2
|
||||
filename: verified_players
|
||||
# Adresse de l'hôte pour l'authentification avec la base de données SQL
|
||||
host: localhost
|
||||
# Port pour l'authentification avec la base de données SQL
|
||||
|
||||
@@ -42,8 +42,10 @@ attack-tracker:
|
||||
# შენიშვნა: IP მისამართები ინახება უბრალო ტექსტში. თქვენ ხართ პასუხისმგებელი თქვენი მონაცემთა ბაზის უსაფრთხოებაზე!
|
||||
database:
|
||||
# მონაცემთა ბაზის ტიპები, რომლებიც Sonar-ს შეუძლია გამოიყენოს ვერიფირებული მოთამაშეების შესანახად
|
||||
# შესაძლო ტიპები: NONE, MYSQL, MARIADB
|
||||
# შესაძლო ტიპები: NONE, MYSQL, MARIADB, H2
|
||||
type: NONE
|
||||
# File in Sonar's plugin directory used for the H2 database
|
||||
filename: verified_players
|
||||
# ჰოსტის მისამართი SQL მონაცემთა ბაზის ავთენტიფიკაციისთვის
|
||||
host: localhost
|
||||
# პორტი SQL მონაცემთა ბაზის ავთენტიფიკაციისთვის
|
||||
|
||||
@@ -42,8 +42,10 @@ attack-tracker:
|
||||
# Let op: IP-adressen worden opgeslagen in platte tekst. U bent verantwoordelijk voor het veilig houden van uw database!
|
||||
database:
|
||||
# Type database dat Sonar gebruikt om geverifieerde spelers op te slaan
|
||||
# Mogelijke typen: NONE, MYSQL, MARIADB
|
||||
# Mogelijke typen: NONE, MYSQL, MARIADB, H2
|
||||
type: NONE
|
||||
# Bestand in de plugin-directory van Sonar dat wordt gebruikt voor de H2-database
|
||||
filename: verified_players
|
||||
# Adres voor authenticatie met de SQL-database
|
||||
host: localhost
|
||||
# Poort voor authenticatie met de SQL-database
|
||||
|
||||
@@ -42,8 +42,10 @@ attack-tracker:
|
||||
# Примечание: IP-адреса сохраняются в виде обычного текста. Вы сами отвечаете за сохранность своей базы данных!
|
||||
database:
|
||||
# Тип базы данных, которую Sonar использует для хранения проверенных игроков.
|
||||
# Возможные типы: NONE, MYSQL, MARIADB
|
||||
# Возможные типы: NONE, MYSQL, MARIADB, H2
|
||||
type: NONE
|
||||
# Файл в каталоге плагинов Sonar, используемый для базы данных H2
|
||||
filename: verified_players
|
||||
# Адрес хоста для аутентификации в базе данных SQL
|
||||
host: localhost
|
||||
# Порт для аутентификации с базой данных SQL
|
||||
|
||||
@@ -42,8 +42,10 @@ attack-tracker:
|
||||
# 提示: IP 地址将以纯文本形式保存 请确保您的数据库安全!
|
||||
database:
|
||||
# 要连接到的数据库类型
|
||||
# 可用类型: NONE (不使用数据库), MYSQL, MARIADB
|
||||
# 可用类型: NONE (不使用数据库), MYSQL, MARIADB, H2
|
||||
type: NONE
|
||||
# Sonar 插件目录中用于 H2 数据库的文件
|
||||
filename: verified_players
|
||||
# 数据库的地址
|
||||
host: localhost
|
||||
# 数据库的端口
|
||||
|
||||
@@ -58,9 +58,14 @@ commands:
|
||||
- ''
|
||||
# Formatierung der Liste der Unterbefehle, die angezeigt wird, wenn der Hauptbefehl ausgeführt wird
|
||||
subcommands: '<suggest-subcommand><hover:show_text:''<gray>Nur Spieler: </gray><only-players><br><gray>Erfordert Konsole: </gray><only-console><br><gray>Berechtigung: </gray><white><permission><br><gray>Aliase: </gray><aliases>''><dark_aqua> ▪ <gray>/sonar <subcommand> <white><description></hover></suggest-subcommand>'
|
||||
# Formatierung für Ja- (cross) und Nein- (tick) Werte in den Unterbefehlen hover Text
|
||||
tick: '<green>✔</green>'
|
||||
cross: '<red>✗</red>'
|
||||
|
||||
# Übersetzungen für '/sonar reload'
|
||||
reload:
|
||||
# Beschreibung für diesen Unterbefehl
|
||||
description: "Alle Konfigurationen neu laden"
|
||||
# Nachricht, die angezeigt wird, wenn jemand mit dem Neuladen von Sonar beginnt
|
||||
start: '<prefix>Sonar wird neu geladen...'
|
||||
# Nachricht, die angezeigt wird, wenn Sonar erfolgreich neu geladen wurde
|
||||
@@ -68,6 +73,8 @@ commands:
|
||||
|
||||
# Übersetzungen für '/sonar verbose'
|
||||
verbose:
|
||||
# Beschreibung für diesen Unterbefehl
|
||||
description: "Aktivieren oder deaktivieren Sie Verbose-Informationen"
|
||||
# Nachricht, die angezeigt wird, wenn ein Spieler Sonar Verbose-Informationen abonniert
|
||||
subscribe: '<prefix>Du siehst jetzt Sonar Verbose-Informationen.'
|
||||
# Nachricht, die angezeigt wird, wenn ein Spieler Sonar Verbose-Informationen abbestellt
|
||||
@@ -75,6 +82,8 @@ commands:
|
||||
|
||||
# Übersetzungen für '/sonar notify'
|
||||
notify:
|
||||
# Beschreibung für diesen Unterbefehl
|
||||
description: "Aktivieren oder deaktivieren Sie Angriffsbenachrichtigungen"
|
||||
# Nachricht, die angezeigt wird, wenn ein Spieler Sonar Angriffsbenachrichtigungen abonniert
|
||||
subscribe: '<prefix>Du siehst jetzt Sonar Angriffsbenachrichtigungen.'
|
||||
# Nachricht, die angezeigt wird, wenn ein Spieler Sonar Angriffsbenachrichtigungen abbestellt
|
||||
@@ -82,6 +91,8 @@ commands:
|
||||
|
||||
# Übersetzungen für '/sonar blacklist'
|
||||
blacklist:
|
||||
# Beschreibung für diesen Unterbefehl
|
||||
description: "Verwalten von IP-Adressen auf der schwarzen Liste"
|
||||
# Nachricht, die angezeigt wird, wenn jemand versucht, die Blacklist zu leeren, aber sie leer ist
|
||||
empty: '<prefix>Die Blacklist ist derzeit leer. Daher wurden keine IP-Adressen von der Blacklist entfernt.'
|
||||
# Nachricht, die angezeigt wird, wenn jemand die Blacklist leert
|
||||
@@ -101,6 +112,8 @@ commands:
|
||||
|
||||
# Übersetzungen für '/sonar verified'
|
||||
verified:
|
||||
# Beschreibung für diesen Unterbefehl
|
||||
description: "Verwalten Sie verifizierte IP-Adressen"
|
||||
# Nachricht, die angezeigt wird, wenn jemand versucht, die Liste der verifizierten Spieler zu leeren, aber sie leer ist
|
||||
empty: '<prefix>Die Liste der verifizierten Spieler ist derzeit leer. Daher wurden keine Spieler unverifiziert.'
|
||||
# Nachricht, die angezeigt wird, wenn jemand die Liste der verifizierten Spieler leert
|
||||
@@ -121,6 +134,8 @@ commands:
|
||||
|
||||
# Übersetzungen für '/sonar statistics'
|
||||
statistics:
|
||||
# Beschreibung für diesen Unterbefehl
|
||||
description: "Sitzungsstatistiken für diesen Server anzeigen"
|
||||
# Informationsnachricht, die oben angezeigt wird, wenn die Statistiken angesehen werden
|
||||
header: '<prefix>Anzeige der <statistics-type>-Statistiken für diese Sitzung:'
|
||||
# Nachricht, die angezeigt wird, wenn ein Spieler versucht, eine unbekannte Statistik anzusehen
|
||||
@@ -155,6 +170,13 @@ commands:
|
||||
- ' <dark_aqua>▪ <gray>Gesamte genutzte eingehende Bandbreite: <white><incoming-traffic-ttl>'
|
||||
- ' <dark_aqua>▪ <gray>Gesamte genutzte ausgehende Bandbreite: <white><outgoing-traffic-ttl>'
|
||||
|
||||
# Übersetzungen für '/sonar dump'
|
||||
dump:
|
||||
# Beschreibung für diesen Unterbefehl
|
||||
description: "Entwicklerinformationen ausgeben"
|
||||
# Format der an die Konsole gesendeten Informationen
|
||||
log: "Erstellter Dump: <dumped-json-data>"
|
||||
|
||||
# Übersetzungen für alle Nachrichten während des Übergabeprozesses
|
||||
verification:
|
||||
# Übersetzungen für alle Debug-Nachrichten während der Überprüfung
|
||||
|
||||
@@ -57,9 +57,14 @@ commands:
|
||||
- ''
|
||||
# Formatting of the list of subcommands shown when running the main command
|
||||
subcommands: '<suggest-subcommand><hover:show_text:''<gray>Only players: </gray><only-players><br><gray>Require console: </gray><only-console><br><gray>Permission: </gray><white><permission><br><gray>Aliases: </gray><aliases>''><dark_aqua> ▪ <gray>/sonar <subcommand> <white><description></hover></suggest-subcommand>'
|
||||
# Formatting for yes (tick) and no (cross) values in the subcommands hover text
|
||||
tick: '<green>✔</green>'
|
||||
cross: '<red>✗</red>'
|
||||
|
||||
# Translations for '/sonar reload'
|
||||
reload:
|
||||
# Description for this subcommand
|
||||
description: "Reload all configurations"
|
||||
# Message shown when someone starts reloading Sonar
|
||||
start: '<prefix>Reloading Sonar...'
|
||||
# Message shown when Sonar has finished reloading
|
||||
@@ -67,6 +72,8 @@ commands:
|
||||
|
||||
# Translations for '/sonar verbose'
|
||||
verbose:
|
||||
# Description for this subcommand
|
||||
description: "Enable or disable Sonar verbose"
|
||||
# Message shown when a player subscribes to Sonar verbose
|
||||
subscribe: '<prefix>You are now viewing Sonar verbose.'
|
||||
# Message shown when a player unsubscribes from Sonar verbose
|
||||
@@ -74,6 +81,8 @@ commands:
|
||||
|
||||
# Translations for '/sonar notify'
|
||||
notify:
|
||||
# Description for this subcommand
|
||||
description: "Enable or disable attack notifications"
|
||||
# Message shown when a player subscribes to Sonar attack notifications
|
||||
subscribe: '<prefix>You are now viewing Sonar attack notifications.'
|
||||
# Message shown when a player unsubscribes from Sonar attack notifications
|
||||
@@ -81,6 +90,8 @@ commands:
|
||||
|
||||
# Translations for '/sonar blacklist'
|
||||
blacklist:
|
||||
# Description for this subcommand
|
||||
description: "Manage blacklisted IP addresses"
|
||||
# Message shown when someone tries clearing the blacklist but is empty
|
||||
empty: '<prefix>The blacklist is currently empty. Therefore, no IP addresses were removed from the blacklist.'
|
||||
# Message shown when someone clears the blacklist
|
||||
@@ -100,6 +111,8 @@ commands:
|
||||
|
||||
# Translations for '/sonar verified'
|
||||
verified:
|
||||
# Description for this subcommand
|
||||
description: "Manage verified IP addresses"
|
||||
# Message shown when someone tries clearing the list of verified players but is empty
|
||||
empty: '<prefix>The list of verified players is currently empty. Therefore, no players were unverified.'
|
||||
# Message shown when someone clears the list of verified players
|
||||
@@ -120,6 +133,8 @@ commands:
|
||||
|
||||
# Translations for '/sonar statistics'
|
||||
statistics:
|
||||
# Description for this subcommand
|
||||
description: "Show session statistics of this server"
|
||||
# Informational message that is shown above everything when viewing the statistics
|
||||
header: '<prefix>Showing <statistics-type> statistics for this session:'
|
||||
# Message shown when a player tries viewing an unknown statistic
|
||||
@@ -154,6 +169,13 @@ commands:
|
||||
- ' <dark_aqua>▪ <gray>Total incoming used bandwidth: <white><incoming-traffic-ttl>'
|
||||
- ' <dark_aqua>▪ <gray>Total outgoing used bandwidth: <white><incoming-traffic-ttl>'
|
||||
|
||||
# Translations for '/sonar dump'
|
||||
dump:
|
||||
# Description for this subcommand
|
||||
description: "Print developer information"
|
||||
# Format of the information sent to console
|
||||
log: "Generated dump: <dumped-json-data>"
|
||||
|
||||
# Translations for all messages during the verification process
|
||||
verification:
|
||||
# Translations for all debug messages during the verification
|
||||
|
||||
@@ -0,0 +1,288 @@
|
||||
#
|
||||
# /$$$$$$
|
||||
# /$$__ $$
|
||||
# | $$ \__/ /$$$$$$ /$$$$$$$ /$$$$$$ /$$$$$$
|
||||
# | $$$$$$ /$$__ $$| $$__ $$ |____ $$ /$$__ $$
|
||||
# \____ $$| $$ \ $$| $$ \ $$ /$$$$$$$| $$ \__/
|
||||
# /$$ \ $$| $$ | $$| $$ | $$ /$$__ $$| $$
|
||||
# | $$$$$$/| $$$$$$/| $$ | $$| $$$$$$$| $$
|
||||
# \______/ \______/ |__/ |__/ \_______/|__/
|
||||
#
|
||||
# ¿Necesita ayuda o tiene alguna pregunta? https://jonesdev.xyz/discord
|
||||
# Código fuente: https://github.com/jonesdevelopment/sonar
|
||||
# Copyright Jones Development and Sonar Contributors, bajo licencia GPL-3.0
|
||||
#
|
||||
|
||||
# Placeholder for every '<prefix>' in this configuration file
|
||||
prefix: <b><yellow>Sonar</b> <gray>» <white>
|
||||
# Placeholder for every '<support-url>' in this configuration file
|
||||
support-url: https://jonesdev.xyz/discord/
|
||||
# Placeholder for every '<header>' in this configuration file
|
||||
header:
|
||||
- <b><yellow>Sonar</b><reset>
|
||||
- ''
|
||||
# Placeholder for every '<footer>' in this configuration file
|
||||
footer:
|
||||
- <gray>Si cree que se trata de un error, por favor comuníquese con un administrador.
|
||||
# Disconnect message that is shown when someone joins, but there are too many online players with their IP address
|
||||
too-many-online-per-ip:
|
||||
- <header>
|
||||
- <red>Hay demasiados jugadores en línea con tu dirección IP.
|
||||
- <footer>
|
||||
|
||||
# Translations for commands
|
||||
commands:
|
||||
# Message shown when a player tries running /sonar without permission
|
||||
no-permission: <prefix><red>No tienes permiso para ejecutar ese comando.
|
||||
# Message shown when someone uses a command incorrectly
|
||||
incorrect-usage: '<prefix><red>Uso correcto: <subcommand-usage>'
|
||||
# Message shown when someone provides an invalid IP address (Invalid format)
|
||||
invalid-ip-address: <prefix>La dirección IP que proporcionó parece no ser válida.
|
||||
# Message shown when the console runs a command that is player-only
|
||||
player-only: <prefix><red>Solo puedes ejecutar este comando como jugador.
|
||||
# Message shown when a player runs a command that is console-only
|
||||
console-only: <prefix><red>Por razones de seguridad, solo puedes ejecutar este comando a través de consola.
|
||||
# Message shown when a player does not have permission to execute a certain subcommand
|
||||
subcommand-no-permission: <prefix><red>No tienes permiso para ejecutar ese subcomando. <gray>(<permission>)
|
||||
|
||||
# Translations for '/sonar'
|
||||
main:
|
||||
# Informational message that is shown above everything when running the main command
|
||||
header:
|
||||
- <yellow>Ejecutando <b>Sonar</b> <version> en <platform>.
|
||||
- <gray><click:open_url:'https://github.com/jonesdevelopment/sonar'>(C) <copyright-year>Jones Development and Sonar Contributors</click>
|
||||
- ''
|
||||
- <gray>¿Necesita ayuda o tiene alguna pregunta?
|
||||
- <white><click:open_url:'https://jonesdev.xyz/discord/'><hover:show_text:'(Haga clic para abrir Discord)'>Abrir un ticket en Discord </hover></click><click:open_url:'https://github.com/jonesdevelopment/sonar/issues'><hover:show_text:'(Haga click para abrir GitHub)'>o abra una nueva Issue en GitHub.
|
||||
- ''
|
||||
# Formatting of the list of subcommands shown when running the main command
|
||||
subcommands: '<suggest-subcommand><hover:show_text:''<gray>Solo jugadores: </gray><only-players><br><gray>Requiere consola: </gray><only-console><br><gray>Permiso: </gray><white><permission><br><gray>Alias: </gray><aliases>''><dark_aqua> ▪ <gray>/sonar <subcommand> <white><description></hover></suggest-subcommand>'
|
||||
# Formato para los valores sí (tick) y no (cross) en el texto hover de los subcomandos
|
||||
tick: '<green>✔</green>'
|
||||
cross: '<red>✗</red>'
|
||||
|
||||
# Translations for '/sonar reload'
|
||||
reload:
|
||||
# Descripción para este subcomando
|
||||
description: "Recargar todas las configuraciones"
|
||||
# Message shown when someone starts reloading Sonar
|
||||
start: <prefix>Recargando Sonar...
|
||||
# Message shown when Sonar has finished reloading
|
||||
finish: <prefix><green>Recargado con éxito <gray>(<time-taken>ms)
|
||||
|
||||
# Translations for '/sonar verbose'
|
||||
verbose:
|
||||
# Descripción para este subcomando
|
||||
description: "Activar o desactivar detallado (verbose)"
|
||||
# Message shown when a player subscribes to Sonar verbose
|
||||
subscribe: <prefix>Ahora estás viendo Sonar detallado (verbose).
|
||||
# Message shown when a player unsubscribes from Sonar verbose
|
||||
unsubscribe: <prefix>Ya no estás viendo Sonar detallado (verbose).
|
||||
|
||||
# Translations for '/sonar notify'
|
||||
notify:
|
||||
# Descripción para este subcomando
|
||||
description: "Activar o desactivar las notificaciones de ataques"
|
||||
# Message shown when a player subscribes to Sonar attack notifications
|
||||
subscribe: <prefix>Ahora estás viendo las notificaciones de ataques de Sonar.
|
||||
# Message shown when a player unsubscribes from Sonar attack notifications
|
||||
unsubscribe: <prefix>Ya no ves las notificaciones de ataques de Sonar.
|
||||
|
||||
# Translations for '/sonar blacklist'
|
||||
blacklist:
|
||||
# Descripción para este subcomando
|
||||
description: "Gestionar las direcciones IP de la lista negra"
|
||||
# Message shown when someone tries clearing the blacklist but is empty
|
||||
empty: <prefix>La lista negra está actualmente vacía. Por lo tanto, no se eliminó ninguna dirección IP de la lista negra.
|
||||
# Message shown when someone clears the blacklist
|
||||
clear: <prefix>Eliminaste con éxito un total de <amount> direcciones IP de la lista negra.
|
||||
# Message shown when someone checks the size of the blacklist
|
||||
size: <prefix>La lista negra actualmente contiene <amount> direccion(es) IP.
|
||||
# Message shown when someone removes an IP address from the blacklist
|
||||
remove: <prefix>Se eliminó con éxito <ip> de la lista negra.
|
||||
# Message shown when someone adds an IP address to the blacklist
|
||||
add: <prefix>Añadida con éxito <ip> a la lista negra.
|
||||
# Message shown when someone adds an IP address to the blacklist that is verified
|
||||
add-warning: '<prefix><red>Advertencia: <white><ip> Actualmente está en la lista blanca. Considere eliminar la dirección IP de la lista de jugadores verificados para evitar posibles problemas.'
|
||||
# Message shown when someone adds an IP address to the blacklist, but it is already blacklisted
|
||||
ip-duplicate: <prefix>La dirección IP que proporcionó ya está en la lista negra.
|
||||
# Message shown when someone removes an IP address from the blacklist, but it is not blacklisted
|
||||
ip-not-found: <prefix>La dirección IP que proporcionó no está en la lista negra.
|
||||
|
||||
# Translations for '/sonar verified'
|
||||
verified:
|
||||
# Descripción para este subcomando
|
||||
description: "Gestionar direcciones IP verificadas"
|
||||
# Message shown when someone tries clearing the list of verified players but is empty
|
||||
empty: <prefix>La lista de jugadores verificados está actualmente vacía. Por lo tanto, ningún jugador ha sido verificado.
|
||||
# Message shown when someone clears the list of verified players
|
||||
clear: <prefix>Eliminaste de la lista de verificados exitosamente un total de <amount> jugador(es) único(s).
|
||||
# Message shown when someone checks the size of the list of verified players
|
||||
size: <prefix>Actualmente hay <amount> jugador(es) único(s) verificado(s).
|
||||
# Message shown when someone un-verifies an IP address
|
||||
remove: <prefix>Eliminaste de la lista de verificados la IP <ip>.
|
||||
# Message shown when someone verifies an IP address
|
||||
add: <prefix>Verificaste con éxito la IP <ip>.
|
||||
# Message shown when someone tries to verify an IP address/UUID that are already verified
|
||||
already: <prefix>La dirección IP y el UUID que proporcionó ya están verificados.
|
||||
# Message shown when someone un-verifies an IP address, but it is not verified
|
||||
ip-not-found: <prefix>La dirección IP que proporcionó no está verificada.
|
||||
# Message shown when someone looks up the verification history of an IP address
|
||||
history: '<prefix><yellow>UUIDs anteriores para <ip>:'
|
||||
history-entry: ' <gray>▪ <white><uuid>'
|
||||
|
||||
# Translations for '/sonar statistics'
|
||||
statistics:
|
||||
# Descripción para este subcomando
|
||||
description: "Mostrar estadísticas de sesión de este servidor"
|
||||
# Informational message that is shown above everything when viewing the statistics
|
||||
header: '<prefix>Mostrando estadísticas de <statistics-type> para esta sesión:'
|
||||
# Message shown when a player tries viewing an unknown statistic
|
||||
unknown-type: '<prefix><red>¡Tipo de estadísticas desconocido! Estadísticas disponibles: <gray><statistics>'
|
||||
# Format of the general statistics message
|
||||
general:
|
||||
- ' <dark_aqua>▪ <gray>Direcciones IP verificadas: <white><verified>'
|
||||
- ' <dark_aqua>▪ <gray>Verificación de direcciones IP: <white><verifying>'
|
||||
- ' <dark_aqua>▪ <gray>Direcciones IP en lista negra: <white><blacklisted>'
|
||||
- ' <dark_aqua>▪ <gray>Inicios de sesión actualmente en cola: <white><queued>'
|
||||
- ' <dark_aqua>▪ <gray>Total de uniones no únicas: <white><total-joins>'
|
||||
- ' <dark_aqua>▪ <gray>Total de intentos de verificación: <white><total-attempts>'
|
||||
- ' <dark_aqua>▪ <gray>Total de verificaciones fallidas: <white><total-failed>'
|
||||
- ' <dark_aqua>▪ <gray>Tiempo de actividad del servidor: <white><server-uptime>'
|
||||
# Format of the CPU statistics message
|
||||
cpu:
|
||||
- ' <dark_aqua>▪ <gray>Uso de la CPU del proceso ahora mismo: <white><process-cpu>%'
|
||||
- ' <dark_aqua>▪ <gray>Uso de la CPU del sistema en este momento: <white><system-cpu>%'
|
||||
- ' <dark_aqua>▪ <gray>Uso de CPU de proceso por núcleo: <white><average-process-cpu>%'
|
||||
- ' <dark_aqua>▪ <gray>Uso de CPU del sistema por núcleo: <white><average-system-cpu>%'
|
||||
- ' <dark_aqua>▪ <gray>Cantidad total de CPU virtuales: <white><virtual-core-count>'
|
||||
# Format of the memory statistics message
|
||||
memory:
|
||||
- ' <dark_aqua>▪ <gray>Memoria libre total: <white><free-memory>'
|
||||
- ' <dark_aqua>▪ <gray>Memoria total utilizada: <white><used-memory>'
|
||||
- ' <dark_aqua>▪ <gray>Memoria máxima total: <white><max-memory>'
|
||||
- ' <dark_aqua>▪ <gray>Memoria total asignada: <white><total-memory>'
|
||||
# Format of the network statistics message
|
||||
network:
|
||||
- ' <dark_aqua>▪ <gray>Ancho de banda entrante utilizado actualmente: <white><incoming-traffic>'
|
||||
- ' <dark_aqua>▪ <gray>Ancho de banda utilizado saliente actual: <white><outgoing-traffic>'
|
||||
- ' <dark_aqua>▪ <gray>Ancho de banda entrante total utilizado: <white><incoming-traffic-ttl>'
|
||||
- ' <dark_aqua>▪ <gray>Ancho de banda total utilizado saliente: <white><incoming-traffic-ttl>'
|
||||
|
||||
# Translations for '/sonar dump'
|
||||
dump:
|
||||
# Descripción para este subcomando
|
||||
description: "Imprimir información del promotor"
|
||||
# Formato de la información enviada a la consola
|
||||
log: "Log generado: <dumped-json-data>"
|
||||
|
||||
# Translations for all messages during the verification process
|
||||
verification:
|
||||
# Translations for all debug messages during the verification
|
||||
logs:
|
||||
# Message logged to console whenever a new player joins the server
|
||||
connection: <username><ip> (<protocol>) se ha conectado.
|
||||
# Message logged to console whenever a player fails verification
|
||||
failed: '<ip> (<protocol>) no ha pasado la verificación de bot por: <reason>'
|
||||
# Message logged to console whenever a player is blacklisted
|
||||
blacklisted: <ip> (<protocol>) fue incluido en la lista negra por demasiados intentos fallidos.
|
||||
# Message logged to console whenever a player is verified
|
||||
successful: <username> ha sido verificado exitosamente. (<time-taken>s!).
|
||||
|
||||
# Messages that are shown to the player when they are supposed to enter the CAPTCHA
|
||||
captcha:
|
||||
# Message shown to the player when they have to enter the answer to the captcha
|
||||
enter-code: <prefix><green>Por favor ingresa en el chat el código que se muestra en el mapa.
|
||||
# Message shown to the player when they enter the wrong answer in chat
|
||||
incorrect: <prefix><red>Ha ingresado el código incorrecto. Inténtalo de nuevo.
|
||||
|
||||
# Disconnect message that is shown when someone joins while the captcha hasn't been prepared yet
|
||||
currently-preparing:
|
||||
- <header>
|
||||
- <yellow>Tus datos anti-bot aún no se han preparado.
|
||||
- <gray>Espere unos segundos antes de intentar realizar la verificación nuevamente.
|
||||
- <footer>
|
||||
# Disconnect message that is shown when someone rejoins too fast during verification
|
||||
too-fast-reconnect:
|
||||
- <header>
|
||||
- <gold>Te reconectaste demasiado rápido, inténtalo de nuevo en un momento.
|
||||
- <gray>Espere unos segundos antes de intentar realizar la verificación nuevamente.
|
||||
- <footer>
|
||||
# Disconnect message that is shown when someone joins but is already verifying
|
||||
already-verifying:
|
||||
- <header>
|
||||
- <red>Su dirección IP se está verificando.
|
||||
- <red>Espere unos segundos antes de intentar realizar la verificación nuevamente.
|
||||
- <footer>
|
||||
# Disconnect message that is shown when someone joins but is already queued for verification
|
||||
already-queued:
|
||||
- <header>
|
||||
- <red>Su dirección IP está actualmente en cola para verificación.
|
||||
- <red>Espere unos minutos antes de intentar realizar la verificación nuevamente.
|
||||
- <footer>
|
||||
# Disconnect message that is shown when someone joins but is temporarily blacklisted
|
||||
blacklisted:
|
||||
- <header>
|
||||
- <red>Actualmente no puedes ingresar al servidor.
|
||||
- <red>Espere unos minutos para poder unirse nuevamente al servidor.
|
||||
- <gold>¿Falso positivo? <gray><support-url>
|
||||
- <footer>
|
||||
# Disconnect message that is shown when someone joins with an invalid username
|
||||
invalid-username:
|
||||
- <header>
|
||||
- <red>Tu nombre de usuario contiene caracteres inválidos.
|
||||
- <footer>
|
||||
# Disconnect message that is shown when someone joins with a blacklisted version
|
||||
blacklisted-protocol:
|
||||
- <header>
|
||||
- <red>Estás utilizando una versión que no está permitida en nuestro servidor.
|
||||
- <gold>¿Necesitas ayuda para iniciar sesión? <gray><support-url>
|
||||
- <footer>
|
||||
# Disconnect message that is shown when someone verifies successfully
|
||||
success:
|
||||
- <header>
|
||||
- <green>Ha pasado con éxito la verificación.
|
||||
- <white>Ahora podrás jugar en el servidor cuando te vuelvas a conectar.
|
||||
# Disconnect message that is shown when someone fails verification
|
||||
failed:
|
||||
- <header>
|
||||
- <red>No pasaste la verificación del bot.
|
||||
- <gray>Espere unos segundos antes de intentar realizar la verificación nuevamente.
|
||||
- <gold>¿Necesitas ayuda para iniciar sesión? <gray><support-url>
|
||||
- <footer>
|
||||
|
||||
# Translations for Sonar's actionbar verbose messages
|
||||
verbose:
|
||||
layout:
|
||||
# Layout for Sonar's actionbar verbose
|
||||
normal: <prefix><gray>CPS <white><connections-per-second> <dark_aqua>╺ <gray>Inicios de sesión/s <white><logins-per-second> <dark_aqua>╺ <gray>Verificando <white><verifying> <dark_aqua>| <green>⬆ <white><outgoing-traffic>/s <red>⬇ <white><incoming-traffic>/s <green><bold><animation>
|
||||
# Layout for Sonar's actionbar verbose during an attack
|
||||
attack: <prefix><gray>CPS <white><connections-per-second> <dark_aqua>╺ <gray>Logins/s <white><logins-per-second> <dark_aqua>╺ <gray>Cola <white><queued> <dark_aqua>╺ <gray>Verificando <white><verifying> <dark_aqua>╺ <gray>Duración <white><attack-duration> <dark_aqua>| <green>⬆ <white><outgoing-traffic>/s <red>⬇ <white><incoming-traffic>/s <green><bold><animation>
|
||||
# Animation for the action bar
|
||||
# Alternatives:
|
||||
# - ▙, ▛, ▜, ▟
|
||||
# - ⬈, ⬊, ⬋, ⬉
|
||||
animation:
|
||||
- ◜
|
||||
- ◝
|
||||
- ◞
|
||||
- ◟
|
||||
|
||||
# Translations for Sonar's attack notification messages
|
||||
notifications:
|
||||
# Layout for Sonar's attack notification title
|
||||
title: <yellow><b>Sonar<reset>
|
||||
# Layout for Sonar's attack notification subtitle
|
||||
subtitle: <gray>Se ha detectado un ataque de bots
|
||||
# Layout for Sonar's attack notification in chat
|
||||
chat:
|
||||
- ''
|
||||
- <yellow><b>Sonar<reset>
|
||||
- ''
|
||||
- <gray>Se ha detectado un ataque de bots.
|
||||
- ' <dark_aqua>▪ <gray>Inicios de sesión por segundo: <white><logins-per-second>'
|
||||
- ' <dark_aqua>▪ <gray>Verificando jugadores: <white><verifying>'
|
||||
- ' <dark_aqua>▪ <gray>Jugadores en cola: <white><queued>'
|
||||
- ''
|
||||
- <gray>Ver más información usando <white><click:run_command:'/sonar verbose'><hover:show_text:'(Haga clic para ejecutar)'>/sonar verbose</hover></click><gray> or <white><click:run_command:'/sonar stats'><hover:show_text:'(Haga clic para ejecutar)'>/sonar stats</hover></click><gray>.
|
||||
- ''
|
||||
@@ -57,9 +57,14 @@ commands:
|
||||
- ''
|
||||
# Format de la liste des sous-commandes affichée lors de l'exécution de la commande principale
|
||||
subcommands: '<suggest-subcommand><hover:show_text:''<gray>Seulement pour les joueurs : </gray><only-players><br><gray>Nécessite la console : </gray><only-console><br><gray>Permission : </gray><white><permission><br><gray>Alias : </gray><aliases>''><dark_aqua> ▪ <gray>/sonar <subcommand> <white><description></hover></suggest-subcommand>'
|
||||
# Formatage des valeurs oui (tick) et non (cross) dans le texte de survol des sous-commandes
|
||||
tick: '<green>✔</green>'
|
||||
cross: '<red>✗</red>'
|
||||
|
||||
# Traductions pour '/sonar reload'
|
||||
reload:
|
||||
# Description de cette sous-commande
|
||||
description: "Recharger toutes les configurations"
|
||||
# Message affiché lorsque quelqu'un commence à recharger Sonar
|
||||
start: '<prefix>Rechargement de Sonar...'
|
||||
# Message affiché lorsque Sonar a fini de recharger
|
||||
@@ -67,6 +72,8 @@ commands:
|
||||
|
||||
# Traductions pour '/sonar verbose'
|
||||
verbose:
|
||||
# Description de cette sous-commande
|
||||
description: "Activer ou désactiver la détails verbeux"
|
||||
# Message affiché lorsqu'un joueur s'abonne aux détails verbeux de Sonar
|
||||
subscribe: '<prefix>Vous visualisez maintenant les détails verbeux de Sonar.'
|
||||
# Message affiché lorsqu'un joueur se désabonne des détails verbeux de Sonar
|
||||
@@ -74,6 +81,8 @@ commands:
|
||||
|
||||
# Traductions pour '/sonar notify'
|
||||
notify:
|
||||
# Description de cette sous-commande
|
||||
description: "Activer ou désactiver les notifications d'attaque"
|
||||
# Message affiché lorsqu'un joueur s'abonne aux notifications d'attaque de Sonar
|
||||
subscribed: "<prefix>Vous visualisez maintenant les notifications d'attaque de Sonar."
|
||||
# Message affiché lorsqu'un joueur se désabonne des notifications d'attaque de Sonar
|
||||
@@ -81,6 +90,8 @@ commands:
|
||||
|
||||
# Traductions pour '/sonar blacklist'
|
||||
blacklist:
|
||||
# Description de cette sous-commande
|
||||
description: "Gérer les adresses IP sur liste noire"
|
||||
# Message affiché lorsque quelqu'un tente de vider la liste noire mais qu'elle est vide
|
||||
empty: "<prefix>La liste noire est actuellement vide. Par conséquent, aucune adresse IP n'a été supprimée de la liste noire."
|
||||
# Message affiché lorsque quelqu'un vide la liste noire
|
||||
@@ -100,6 +111,8 @@ commands:
|
||||
|
||||
# Traductions pour '/sonar verified'
|
||||
verified:
|
||||
# Description de cette sous-commande
|
||||
description: "Gérer les adresses IP vérifiées"
|
||||
# Message affiché lorsque quelqu'un tente de vider la liste des joueurs vérifiés mais qu'elle est vide
|
||||
empty: "<prefix>La liste des joueurs vérifiés est actuellement vide. Par conséquent, aucun joueur n'a été désapprouvé."
|
||||
# Message affiché lorsque quelqu'un vide la liste des joueurs vérifiés
|
||||
@@ -120,6 +133,8 @@ commands:
|
||||
|
||||
# Traductions pour '/sonar statistics'
|
||||
statistics:
|
||||
# Description de cette sous-commande
|
||||
description: "Afficher les statistiques de session de ce serveur"
|
||||
# Message informatif affiché au-dessus de tout lors de la visualisation des statistiques
|
||||
header: '<prefix>Affichage des statistiques <statistics-type> pour cette session :'
|
||||
# Message affiché lorsqu'un joueur tente de visualiser une statistique inconnue
|
||||
@@ -154,6 +169,13 @@ commands:
|
||||
- ' <dark_aqua>▪ <gray>Bande passante entrante totale utilisée : <white><incoming-traffic-ttl>'
|
||||
- ' <dark_aqua>▪ <gray>Bande passante sortante totale utilisée : <white><outgoing-traffic-ttl>'
|
||||
|
||||
# Traductions pour '/sonar dump'
|
||||
dump:
|
||||
# Description de cette sous-commande
|
||||
description: "Imprimer les informations sur le développeur"
|
||||
# Format des informations envoyées à la console
|
||||
log: "Informations générées : <dumped-json-data>"
|
||||
|
||||
# Traductions pour tous les messages pendant le processus de vérification
|
||||
verification:
|
||||
# Traductions pour tous les messages de débogage pendant la vérification
|
||||
|
||||
@@ -0,0 +1,288 @@
|
||||
#
|
||||
# /$$$$$$
|
||||
# /$$__ $$
|
||||
# | $$ \__/ /$$$$$$ /$$$$$$$ /$$$$$$ /$$$$$$
|
||||
# | $$$$$$ /$$__ $$| $$__ $$ |____ $$ /$$__ $$
|
||||
# \____ $$| $$ \ $$| $$ \ $$ /$$$$$$$| $$ \__/
|
||||
# /$$ \ $$| $$ | $$| $$ | $$ /$$__ $$| $$
|
||||
# | $$$$$$/| $$$$$$/| $$ | $$| $$$$$$$| $$
|
||||
# \______/ \______/ |__/ |__/ \_______/|__/
|
||||
#
|
||||
# Butuh bantuan atau memiliki pertanyaan? https://jonesdev.xyz/discord
|
||||
# Kode sumber: https://github.com/jonesdevelopment/sonar
|
||||
# Hak cipta Jones Development dan Kontributor Sonar, dilisensikan di bawah GPL-3.0
|
||||
#
|
||||
|
||||
# Placeholder untuk setiap '<prefix>' dalam file konfigurasi ini
|
||||
prefix: <b><yellow>Sonar</b> <gray>» <white>
|
||||
# Placeholder untuk setiap '<support-url>' dalam file konfigurasi ini
|
||||
support-url: https://jonesdev.xyz/discord/
|
||||
# Placeholder untuk setiap '<header>' dalam file konfigurasi ini
|
||||
header:
|
||||
- <b><yellow>Sonar</b><reset>
|
||||
- ''
|
||||
# Placeholder untuk setiap '<footer>' dalam file konfigurasi ini
|
||||
footer:
|
||||
- <gray>Jika Anda yakin ini adalah kesalahan, hubungi administrator.
|
||||
# Pesan pemutusan yang ditampilkan saat seseorang bergabung, tetapi ada terlalu banyak pemain online dengan alamat IP mereka
|
||||
too-many-online-per-ip:
|
||||
- '<header>'
|
||||
- <red>Ada terlalu banyak pemain online dengan alamat IP Anda.
|
||||
- '<footer>'
|
||||
|
||||
# Terjemahan untuk perintah
|
||||
commands:
|
||||
# Pesan yang ditampilkan saat pemain mencoba menjalankan /sonar tanpa izin
|
||||
no-permission: '<prefix><red>Anda tidak memiliki izin untuk menjalankan perintah ini.'
|
||||
# Pesan yang ditampilkan saat seseorang menggunakan perintah dengan salah
|
||||
incorrect-usage: '<prefix><red>Penggunaan: /sonar <subcommand-usage>'
|
||||
# Pesan yang ditampilkan saat seseorang memberikan alamat IP yang tidak valid (Format tidak valid)
|
||||
invalid-ip-address: '<prefix>Alamat IP yang Anda berikan tampaknya tidak valid.'
|
||||
# Pesan yang ditampilkan saat konsol menjalankan perintah yang hanya untuk pemain
|
||||
player-only: '<prefix><red>Anda hanya dapat menjalankan perintah ini sebagai pemain.'
|
||||
# Pesan yang ditampilkan saat pemain menjalankan perintah yang hanya untuk konsol
|
||||
console-only: '<prefix><red>Demi alasan keamanan, Anda hanya dapat menjalankan perintah ini melalui konsol.'
|
||||
# Pesan yang ditampilkan saat pemain tidak memiliki izin untuk menjalankan sub-perintah tertentu
|
||||
subcommand-no-permission: '<prefix><red>Anda tidak memiliki izin untuk menjalankan sub-perintah ini. <gray>(<permission>)'
|
||||
|
||||
# Terjemahan untuk '/sonar'
|
||||
main:
|
||||
# Pesan informasi yang ditampilkan di atas segalanya saat menjalankan perintah utama
|
||||
header:
|
||||
- <yellow>Menjalankan <b>Sonar</b> <version> di <platform>.
|
||||
- <gray><click:open_url:'https://github.com/jonesdevelopment/sonar'>(C) <copyright-year> Jones Development dan Kontributor Sonar</click>
|
||||
- ''
|
||||
- <gray>Butuh bantuan atau memiliki pertanyaan?
|
||||
- <white><click:open_url:'https://jonesdev.xyz/discord/'><hover:show_text:'(Klik untuk membuka Discord)'>Buka tiket di Discord </hover></click><click:open_url:'https://github.com/jonesdevelopment/sonar/issues'><hover:show_text:'(Klik untuk membuka GitHub)'>atau buka masalah baru di GitHub.
|
||||
- ''
|
||||
# Format daftar sub-perintah yang ditampilkan saat menjalankan perintah utama
|
||||
subcommands: '<suggest-subcommand><hover:show_text:''<gray>Hanya pemain: </gray><only-players><br><gray>Membutuhkan konsol: </gray><only-console><br><gray>Izin: </gray><white><permission><br><gray>Alias: </gray><aliases>''><dark_aqua> ▪ <gray>/sonar <subcommand> <white><description></hover></suggest-subcommand>'
|
||||
# Format untuk nilai ya (centang) dan tidak (silang) dalam teks hover sub-perintah
|
||||
tick: '<green>✔</green>'
|
||||
cross: '<red>✗</red>'
|
||||
|
||||
# Terjemahan untuk '/sonar reload'
|
||||
reload:
|
||||
# Deskripsi untuk sub-perintah ini
|
||||
description: "Muat ulang semua konfigurasi"
|
||||
# Pesan yang ditampilkan saat seseorang mulai memuat ulang Sonar
|
||||
start: '<prefix>Memuat ulang Sonar...'
|
||||
# Pesan yang ditampilkan saat Sonar selesai memuat ulang
|
||||
finish: '<prefix><green>Berhasil memuat ulang <gray>(<time-taken>ms)'
|
||||
|
||||
# Terjemahan untuk '/sonar verbose'
|
||||
verbose:
|
||||
# Deskripsi untuk sub-perintah ini
|
||||
description: "Aktifkan atau nonaktifkan verbose Sonar"
|
||||
# Pesan yang ditampilkan saat pemain berlangganan verbose Sonar
|
||||
subscribe: '<prefix>Anda sekarang melihat verbose Sonar.'
|
||||
# Pesan yang ditampilkan saat pemain berhenti berlangganan verbose Sonar
|
||||
unsubscribe: '<prefix>Anda tidak lagi melihat verbose Sonar.'
|
||||
|
||||
# Terjemahan untuk '/sonar notify'
|
||||
notify:
|
||||
# Deskripsi untuk sub-perintah ini
|
||||
description: "Aktifkan atau nonaktifkan notifikasi serangan"
|
||||
# Pesan yang ditampilkan saat pemain berlangganan notifikasi serangan Sonar
|
||||
subscribe: '<prefix>Anda sekarang melihat notifikasi serangan Sonar.'
|
||||
# Pesan yang ditampilkan saat pemain berhenti berlangganan notifikasi serangan Sonar
|
||||
unsubscribe: '<prefix>Anda tidak lagi melihat notifikasi serangan Sonar.'
|
||||
|
||||
# Terjemahan untuk '/sonar blacklist'
|
||||
blacklist:
|
||||
# Deskripsi untuk sub-perintah ini
|
||||
description: "Kelola alamat IP yang masuk daftar hitam"
|
||||
# Pesan yang ditampilkan saat seseorang mencoba mengosongkan daftar hitam tetapi kosong
|
||||
empty: '<prefix>Daftar hitam saat ini kosong. Oleh karena itu, tidak ada alamat IP yang dihapus dari daftar hitam.'
|
||||
# Pesan yang ditampilkan saat seseorang mengosongkan daftar hitam
|
||||
clear: '<prefix>Anda berhasil menghapus total <amount> alamat IP dari daftar hitam.'
|
||||
# Pesan yang ditampilkan saat seseorang memeriksa ukuran daftar hitam
|
||||
size: '<prefix>Daftar hitam saat ini berisi <amount> alamat IP.'
|
||||
# Pesan yang ditampilkan saat seseorang menghapus alamat IP dari daftar hitam
|
||||
remove: '<prefix>Berhasil menghapus <ip> dari daftar hitam.'
|
||||
# Pesan yang ditampilkan saat seseorang menambahkan alamat IP ke daftar hitam
|
||||
add: '<prefix>Berhasil menambahkan <ip> ke daftar hitam.'
|
||||
# Pesan yang ditampilkan saat seseorang menambahkan alamat IP ke daftar hitam yang diverifikasi
|
||||
add-warning: '<prefix><red>Peringatan: <white><ip> saat ini di daftar putih. Pertimbangkan untuk menghapus alamat IP dari daftar pemain yang diverifikasi untuk menghindari masalah potensial.'
|
||||
# Pesan yang ditampilkan saat seseorang menambahkan alamat IP ke daftar hitam, tetapi sudah masuk daftar hitam
|
||||
ip-duplicate: '<prefix>Alamat IP yang Anda berikan sudah masuk daftar hitam.'
|
||||
# Pesan yang ditampilkan saat seseorang menghapus alamat IP dari daftar hitam, tetapi tidak masuk daftar hitam
|
||||
ip-not-found: '<prefix>Alamat IP yang Anda berikan tidak masuk daftar hitam.'
|
||||
|
||||
# Translations for '/sonar verified'
|
||||
verified:
|
||||
# Deskripsi untuk sub-perintah ini
|
||||
description: "Kelola alamat IP yang diverifikasi"
|
||||
# Pesan yang ditampilkan saat seseorang mencoba mengosongkan daftar pemain yang diverifikasi tetapi kosong
|
||||
empty: '<prefix>Daftar pemain yang diverifikasi saat ini kosong. Oleh karena itu, tidak ada pemain yang dibatalkan verifikasinya.'
|
||||
# Pesan yang ditampilkan saat seseorang mengosongkan daftar pemain yang diverifikasi
|
||||
clear: '<prefix>Anda berhasil membatalkan verifikasi total <amount> pemain unik.'
|
||||
# Pesan yang ditampilkan saat seseorang memeriksa ukuran daftar pemain yang diverifikasi
|
||||
size: '<prefix>Saat ini ada <amount> pemain unik yang diverifikasi.'
|
||||
# Pesan yang ditampilkan saat seseorang membatalkan verifikasi alamat IP
|
||||
remove: '<prefix>Berhasil membatalkan verifikasi <ip>.'
|
||||
# Pesan yang ditampilkan saat seseorang memverifikasi alamat IP
|
||||
add: '<prefix>Berhasil memverifikasi <ip>.'
|
||||
# Pesan yang ditampilkan saat seseorang mencoba memverifikasi alamat IP/UUID yang sudah diverifikasi
|
||||
already: '<prefix>Alamat IP dan UUID yang Anda berikan sudah diverifikasi.'
|
||||
# Pesan yang ditampilkan saat seseorang membatalkan verifikasi alamat IP, tetapi tidak diverifikasi
|
||||
ip-not-found: '<prefix>Alamat IP yang Anda berikan tidak diverifikasi.'
|
||||
# Pesan yang ditampilkan saat seseorang melihat riwayat verifikasi alamat IP
|
||||
history: '<prefix><yellow>UUID sebelumnya untuk <ip>:'
|
||||
history-entry: ' <gray>▪ <white><uuid>'
|
||||
|
||||
# Terjemahan untuk '/sonar statistics'
|
||||
statistics:
|
||||
# Deskripsi untuk sub-perintah ini
|
||||
description: "Tampilkan statistik sesi server ini"
|
||||
# Pesan informasi yang ditampilkan di atas segalanya saat melihat statistik
|
||||
header: '<prefix>Menampilkan statistik <statistics-type> untuk sesi ini:'
|
||||
# Pesan yang ditampilkan saat pemain mencoba melihat statistik yang tidak dikenal
|
||||
unknown-type: '<prefix><red>Tipe statistik tidak dikenal! Statistik yang tersedia: <gray><statistics>'
|
||||
# Format pesan statistik umum
|
||||
general:
|
||||
- ' <dark_aqua>▪ <gray>Alamat IP yang diverifikasi: <white><verified>'
|
||||
- ' <dark_aqua>▪ <gray>Memverifikasi alamat IP: <white><verifying>'
|
||||
- ' <dark_aqua>▪ <gray>Alamat IP yang masuk daftar hitam: <white><blacklisted>'
|
||||
- ' <dark_aqua>▪ <gray>Antrian login saat ini: <white><queued>'
|
||||
- ' <dark_aqua>▪ <gray>Total join non-unik: <white><total-joins>'
|
||||
- ' <dark_aqua>▪ <gray>Total percobaan verifikasi: <white><total-attempts>'
|
||||
- ' <dark_aqua>▪ <gray>Total verifikasi yang gagal: <white><total-failed>'
|
||||
- ' <dark_aqua>▪ <gray>Waktu aktif server: <white><server-uptime>'
|
||||
# Format pesan statistik CPU
|
||||
cpu:
|
||||
- ' <dark_aqua>▪ <gray>Penggunaan CPU proses saat ini: <white><process-cpu>%'
|
||||
- ' <dark_aqua>▪ <gray>Penggunaan CPU sistem saat ini: <white><system-cpu>%'
|
||||
- ' <dark_aqua>▪ <gray>Penggunaan CPU proses per-core: <white><average-process-cpu>%'
|
||||
- ' <dark_aqua>▪ <gray>Penggunaan CPU sistem per-core: <white><average-system-cpu>%'
|
||||
- ' <dark_aqua>▪ <gray>Total jumlah vCPU: <white><virtual-core-count>'
|
||||
# Format pesan statistik memori
|
||||
memory:
|
||||
- ' <dark_aqua>▪ <gray>Total memori bebas: <white><free-memory>'
|
||||
- ' <dark_aqua>▪ <gray>Total memori terpakai: <white><used-memory>'
|
||||
- ' <dark_aqua>▪ <gray>Total memori maksimum: <white><max-memory>'
|
||||
- ' <dark_aqua>▪ <gray>Total memori dialokasikan: <white><total-memory>'
|
||||
# Format pesan statistik jaringan
|
||||
network:
|
||||
- ' <dark_aqua>▪ <gray>Bandwidth masuk saat ini: <white><incoming-traffic>'
|
||||
- ' <dark_aqua>▪ <gray>Bandwidth keluar saat ini: <white><outgoing-traffic>'
|
||||
- ' <dark_aqua>▪ <gray>Total bandwidth masuk: <white><incoming-traffic-ttl>'
|
||||
- ' <dark_aqua>▪ <gray>Total bandwidth keluar: <white><outgoing-traffic-ttl>'
|
||||
|
||||
# Terjemahan untuk '/sonar dump'
|
||||
dump:
|
||||
# Deskripsi untuk sub-perintah ini
|
||||
description: "Cetak informasi pengembang"
|
||||
# Format informasi yang dikirim ke konsol
|
||||
log: "Dump yang dihasilkan: <dumped-json-data>"
|
||||
|
||||
# Terjemahan untuk semua pesan selama proses verifikasi
|
||||
verification:
|
||||
# Terjemahan untuk semua pesan debug selama proses verifikasi
|
||||
logs:
|
||||
# Pesan yang dicatat ke konsol setiap kali pemain baru bergabung ke server
|
||||
connection: '<username><ip> (<protocol>) telah terhubung.'
|
||||
# Pesan yang dicatat ke konsol setiap kali pemain gagal verifikasi
|
||||
failed: '<ip> (<protocol>) telah gagal dalam pemeriksaan bot untuk: <reason>'
|
||||
# Pesan yang dicatat ke konsol setiap kali pemain masuk daftar hitam
|
||||
blacklisted: '<ip> (<protocol>) masuk daftar hitam karena terlalu banyak percobaan yang gagal'
|
||||
# Pesan yang dicatat ke konsol setiap kali pemain berhasil diverifikasi
|
||||
successful: '<username> berhasil diverifikasi dalam waktu (<time-taken>s!).'
|
||||
|
||||
# Pesan yang ditampilkan kepada pemain saat mereka seharusnya memasukkan CAPTCHA
|
||||
captcha:
|
||||
# Pesan yang ditampilkan kepada pemain saat mereka harus memasukkan jawaban untuk captcha
|
||||
enter-code: '<prefix><green>Silakan masukkan kode di chat yang ditampilkan di peta.'
|
||||
# Pesan yang ditampilkan kepada pemain saat mereka memasukkan jawaban yang salah di chat
|
||||
incorrect: '<prefix><red>Anda memasukkan kode yang salah. Silakan coba lagi.'
|
||||
|
||||
# Pesan putus yang ditampilkan saat seseorang bergabung sementara captcha belum disiapkan
|
||||
currently-preparing:
|
||||
- '<header>'
|
||||
- <yellow>Data anti-bot Anda belum disiapkan.
|
||||
- <gray>Silakan tunggu beberapa detik sebelum mencoba verifikasi lagi.
|
||||
- '<footer>'
|
||||
# Pesan putus yang ditampilkan saat seseorang bergabung kembali terlalu cepat selama verifikasi
|
||||
too-fast-reconnect:
|
||||
- '<header>'
|
||||
- <gold>Anda terhubung kembali terlalu cepat, coba lagi nanti.
|
||||
- <gray>Silakan tunggu beberapa detik sebelum mencoba verifikasi lagi.
|
||||
- '<footer>'
|
||||
# Pesan putus yang ditampilkan saat seseorang bergabung tetapi sudah dalam proses verifikasi
|
||||
already-verifying:
|
||||
- '<header>'
|
||||
- <red>Alamat IP Anda saat ini sedang diverifikasi.
|
||||
- <red>Silakan tunggu beberapa detik sebelum mencoba verifikasi lagi.
|
||||
- '<footer>'
|
||||
# Pesan putus yang ditampilkan saat seseorang bergabung tetapi sudah antri untuk verifikasi
|
||||
already-queued:
|
||||
- '<header>'
|
||||
- <red>Alamat IP Anda saat ini sedang antri untuk verifikasi.
|
||||
- <red>Silakan tunggu beberapa menit sebelum mencoba verifikasi lagi.
|
||||
- '<footer>'
|
||||
# Pesan putus yang ditampilkan saat seseorang bergabung tetapi sedang masuk daftar hitam sementara
|
||||
blacklisted:
|
||||
- '<header>'
|
||||
- <red>Anda saat ini ditolak untuk masuk ke server.
|
||||
- <red>Silakan tunggu beberapa menit agar bisa bergabung ke server lagi.
|
||||
- <gold>Positif palsu? <gray><support-url>
|
||||
- '<footer>'
|
||||
# Pesan putus yang ditampilkan saat seseorang bergabung dengan username yang tidak valid
|
||||
invalid-username:
|
||||
- '<header>'
|
||||
- <red>Username Anda mengandung karakter yang tidak valid.
|
||||
- '<footer>'
|
||||
# Pesan putus yang ditampilkan saat seseorang bergabung dengan versi yang masuk daftar hitam
|
||||
blacklisted-protocol:
|
||||
- '<header>'
|
||||
- <red>Anda menggunakan versi yang tidak diizinkan di server kami.
|
||||
- <gold>Butuh bantuan masuk? <gray><support-url>
|
||||
- '<footer>'
|
||||
# Pesan putus yang ditampilkan saat seseorang berhasil verifikasi
|
||||
success:
|
||||
- '<header>'
|
||||
- <green>Anda telah berhasil melewati verifikasi.
|
||||
- <white>Anda sekarang dapat bermain di server saat Anda terhubung kembali.
|
||||
# Pesan putus yang ditampilkan saat seseorang gagal verifikasi
|
||||
failed:
|
||||
- '<header>'
|
||||
- <red>Anda telah gagal dalam verifikasi bot.
|
||||
- <gray>Silakan tunggu beberapa detik sebelum mencoba verifikasi lagi.
|
||||
- <gold>Butuh bantuan masuk? <gray><support-url>
|
||||
- '<footer>'
|
||||
|
||||
# Terjemahan untuk pesan verbose actionbar Sonar
|
||||
verbose:
|
||||
layout:
|
||||
# Tata letak untuk actionbar verbose Sonar
|
||||
normal: '<prefix><gray>CPS <white><connections-per-second> <dark_aqua>╺ <gray>Logins/s <white><logins-per-second> <dark_aqua>╺ <gray>Verifikasi <white><verifying> <dark_aqua>| <green>⬆ <white><outgoing-traffic>/s <red>⬇ <white><incoming-traffic>/s <green><bold><animation>'
|
||||
# Tata letak untuk actionbar verbose Sonar selama serangan
|
||||
attack: '<prefix><gray>CPS <white><connections-per-second> <dark_aqua>╺ <gray>Logins/s <white><logins-per-second> <dark_aqua>╺ <gray>Antrian <white><queued> <dark_aqua>╺ <gray>Verifikasi <white><verifying> <dark_aqua>╺ <gray>Durasi <white><attack-duration> <dark_aqua>| <green>⬆ <white><outgoing-traffic>/s <red>⬇ <white><incoming-traffic>/s <green><bold><animation>'
|
||||
# Animasi untuk action bar
|
||||
# Alternatif:
|
||||
# - ▙, ▛, ▜, ▟
|
||||
# - ⬈, ⬊, ⬋, ⬉
|
||||
animation:
|
||||
- ◜
|
||||
- ◝
|
||||
- ◞
|
||||
- ◟
|
||||
|
||||
# Terjemahan untuk pesan notifikasi serangan Sonar
|
||||
notifications:
|
||||
# Tata letak untuk judul notifikasi serangan Sonar
|
||||
title: <yellow><b>Sonar<reset>
|
||||
# Tata letak untuk subjudul notifikasi serangan Sonar
|
||||
subtitle: <gray>Serangan bot terdeteksi
|
||||
# Tata letak untuk notifikasi serangan Sonar di chat
|
||||
chat:
|
||||
- ''
|
||||
- <yellow><b>Sonar<reset>
|
||||
- ''
|
||||
- <gray>Serangan bot terdeteksi.
|
||||
- ' <dark_aqua>▪ <gray>Login per detik: <white><logins-per-second>'
|
||||
- ' <dark_aqua>▪ <gray>Pemain yang diverifikasi: <white><verifying>'
|
||||
- ' <dark_aqua>▪ <gray>Pemain yang antri: <white><queued>'
|
||||
- ''
|
||||
- <gray>Lihat lebih banyak informasi menggunakan <white><click:run_command:'/sonar verbose'><hover:show_text:'(Klik untuk menjalankan)'>/sonar verbose</hover></click><gray> atau <white><click:run_command:'/sonar stats'><hover:show_text:'(Klik untuk menjalankan)'>/sonar stats</hover></click><gray>.
|
||||
- ''
|
||||
@@ -57,9 +57,14 @@ commands:
|
||||
- ''
|
||||
# Opmaak van de lijst met subcommand die wordt weergegeven bij het uitvoeren van de hoofdopdracht
|
||||
subcommands: '<suggest-subcommand><hover:show_text:''<gray>Alleen spelers: </gray><only-players><br><gray>Vereist console: </gray><only-console><br><gray>Toestemming: </gray><white><permission><br><gray>Aliassen: </gray><aliases>''><dark_aqua> ▪ <gray>/sonar <subcommand> <white><description></hover></suggest-subcommand>'
|
||||
# Opmaak voor ja- (tick) en nee- (cross) waarden in de hover-tekst van de subcommands
|
||||
tick: '<green>✔</green>'
|
||||
cross: '<red>✗</red>'
|
||||
|
||||
# Vertalingen voor '/sonar reload'
|
||||
reload:
|
||||
# Beschrijving van dit subcommand
|
||||
description: "Alle configuraties opnieuw laden"
|
||||
# Bericht dat wordt weergegeven wanneer iemand Sonar begint te herladen
|
||||
start: '<prefix>Sonar opnieuw laden...'
|
||||
# Bericht dat wordt weergegeven wanneer Sonar klaar is met herladen
|
||||
@@ -67,6 +72,8 @@ commands:
|
||||
|
||||
# Vertalingen voor '/sonar verbose'
|
||||
verbose:
|
||||
# Beschrijving van dit subcommand
|
||||
description: "Sonar verbose in- of uitschakelen"
|
||||
# Bericht dat wordt weergegeven wanneer een speler zich abonneert op Sonar uitgebreid
|
||||
subscribe: '<prefix>U bekijkt nu Sonar uitgebreid.'
|
||||
# Bericht dat wordt weergegeven wanneer een speler zich afmeldt voor Sonar uitgebreid
|
||||
@@ -74,6 +81,8 @@ commands:
|
||||
|
||||
# Vertalingen voor '/sonar notify'
|
||||
notify:
|
||||
# Beschrijving van dit subcommand
|
||||
description: "Aanval meldingen in- of uitschakelen"
|
||||
# Bericht dat wordt weergegeven wanneer een speler zich abonneert op Sonar aanval meldingen
|
||||
subscribe: '<prefix>U bekijkt nu Sonar aanval meldingen.'
|
||||
# Bericht dat wordt weergegeven wanneer een speler zich afmeldt voor Sonar aanval meldingen
|
||||
@@ -81,6 +90,8 @@ commands:
|
||||
|
||||
# Vertalingen voor '/sonar blacklist'
|
||||
blacklist:
|
||||
# Beschrijving van dit subcommand
|
||||
description: "Beheer IP-adressen op de zwarte lijst"
|
||||
# Bericht dat wordt weergegeven wanneer iemand de zwarte lijst probeert te wissen, maar deze leeg is
|
||||
empty: '<prefix>De zwarte lijst is momenteel leeg. Daarom waren er geen IP-adressen verwijderd van de zwarte lijst.'
|
||||
# Bericht dat wordt weergegeven wanneer iemand de zwarte lijst wist
|
||||
@@ -100,6 +111,8 @@ commands:
|
||||
|
||||
# Vertalingen voor '/sonar verified'
|
||||
verified:
|
||||
# Beschrijving van dit subcommand
|
||||
description: "Geverifieerde IP-adressen beheren"
|
||||
# Bericht dat wordt weergegeven wanneer iemand de lijst met geverifieerde spelers probeert te wissen, maar leeg is
|
||||
empty: '<prefix>De lijst met geverifieerde spelers is momenteel leeg. Daarom nee spelers waren niet geverifieerd.'
|
||||
# Bericht dat wordt weergegeven wanneer iemand de lijst met geverifieerde spelers wist
|
||||
@@ -120,6 +133,8 @@ commands:
|
||||
|
||||
# Vertalingen voor '/sonar statistics'
|
||||
statistics:
|
||||
# Beschrijving van dit subcommand
|
||||
description: "Toon sessie statistieken van deze server"
|
||||
# Informatieve boodschap die boven alles wordt getoond bij het bekijken van de statistieken
|
||||
header: '<prefix>Er worden <statistics-type> statistieken voor deze sessie weergegeven:'
|
||||
# Bericht dat wordt weergegeven wanneer een speler een onbekende statistiek probeert te bekijken
|
||||
@@ -154,6 +169,13 @@ commands:
|
||||
- ' <dark_aqua>▪ <gray>Totale inkomende gebruikte bandbreedte: <white><incoming-traffic-ttl>'
|
||||
- ' <dark_aqua>▪ <gray>Totale uitgaande gebruikte bandbreedte: <white><outgoing-traffic-ttl>'
|
||||
|
||||
# Vertalingen voor '/sonar dump
|
||||
dump:
|
||||
# Beschrijving van dit subcommand
|
||||
description: "Informatie ontwikkelaar afdrukken"
|
||||
# Formaat van de informatie die naar de console wordt gestuurd
|
||||
log: "Informatie gegenereerd: <dumped-json-data>"
|
||||
|
||||
# Vertalingen voor alle berichten tijdens het verificatieproces
|
||||
verification:
|
||||
# Vertalingen voor alle debug-berichten tijdens de verificatie
|
||||
|
||||
@@ -57,9 +57,14 @@ commands:
|
||||
- ''
|
||||
# Форматирование списка подкоманд
|
||||
subcommands: '<suggest-subcommand><hover:show_text:''<gray>Только игроки: </gray><only-players><br><gray>Требуется консоль: </gray><only-console><br><gray>Permission: </gray><white><permission><br><gray>Псевдонимы: </gray><aliases>''><dark_aqua> ▪ <gray>/sonar <subcommand> <white><description></hover></suggest-subcommand>'
|
||||
# Форматирование значений "да" (tick) и "нет" (cross) в наведенном тексте подкоманд
|
||||
tick: '<green>✔</green>'
|
||||
cross: '<red>✗</red>'
|
||||
|
||||
# Перевод для '/sonar reload'
|
||||
reload:
|
||||
# Описание для этой подкоманды
|
||||
description: "Перезагрузить все конфигурации"
|
||||
# Сообщение, которое отображается, когда кто-то начинает перезагружать Sonar
|
||||
start: '<prefix>Перезагрузка...'
|
||||
# Сообщение, которое отображается, когда Sonar завершает перезагрузку
|
||||
@@ -67,6 +72,8 @@ commands:
|
||||
|
||||
# Перевод для '/sonar verbose'
|
||||
verbose:
|
||||
# Описание для этой подкоманды
|
||||
description: "Включить или отключить подробную информацию"
|
||||
# Сообщение, которое отображается, когда игрок прослушивает Sonar verbose
|
||||
subscribe: '<prefix>Вы просматриваете подробную информацию о Sonar.'
|
||||
# Сообщение, которое отображается, когда игрок перестает прослушивать Sonar verbose
|
||||
@@ -74,6 +81,8 @@ commands:
|
||||
|
||||
# Перевод для '/sonar notify'
|
||||
notify:
|
||||
# Описание для этой подкоманды
|
||||
description: "Включить или отключить уведомления об атаках"
|
||||
# Сообщение, которое отображается, когда игрок подписывается на уведомления об атаках
|
||||
subscribe: '<prefix>Вы получаете уведомления об атаках.'
|
||||
# Сообщение, которое отображается, когда игрок отписывается на уведомления об атаках
|
||||
@@ -81,6 +90,8 @@ commands:
|
||||
|
||||
# Перевод для '/sonar blacklist'
|
||||
blacklist:
|
||||
# Описание для этой подкоманды
|
||||
description: "Управление IP-адресами из черного списка"
|
||||
# Сообщение, которое отображается, когда кто-то пытается очистить черный список, но он пустой
|
||||
empty: '<prefix>В настоящее время черный список пуст. Поэтому ни один IP-адрес не был удален из черного списка.'
|
||||
# Сообщение, которое показывается, когда кто-то очищает черный список
|
||||
@@ -100,6 +111,8 @@ commands:
|
||||
|
||||
# Перевод для '/sonar verified'
|
||||
verified:
|
||||
# Описание для этой подкоманды
|
||||
description: "Управление проверенными IP-адресами"
|
||||
# Сообщение, которое отображается, когда кто-то пытается очистить список проверенных игроков, но он пустой
|
||||
empty: '<prefix>Список проверенных игроков в настоящее время пуст. Поэтому, ни один игрок не был удален.'
|
||||
# Сообщение, которое отображается когда кто-то отчистил список уникальных игроков
|
||||
@@ -120,6 +133,8 @@ commands:
|
||||
|
||||
# Перевод для '/sonar statistics'
|
||||
statistics:
|
||||
# Описание для этой подкоманды
|
||||
description: "Показать статистику сеансов этого сервера"
|
||||
# Информационное сообщение, которое отображается поверх всего при просмотре статистики
|
||||
header: '<prefix>Показываем статистику <statistics-type> для этой сессии:'
|
||||
# Сообщение, которое отображается, когда игрок пытается просмотреть неизвестную статистику
|
||||
@@ -154,6 +169,13 @@ commands:
|
||||
- ' <dark_aqua>▪ <gray>Общая входящая использованная полоса пропускания: <white><incoming-traffic-ttl>'
|
||||
- ' <dark_aqua>▪ <gray>Общая исходящая использованная полоса пропускания: <white><outgoing-traffic-ttl>'
|
||||
|
||||
# Перевод для '/sonar dump'
|
||||
dump:
|
||||
# Описание для этой подкоманды
|
||||
description: "Вывести информацию о разработчике"
|
||||
# Формат информации, отправляемой в консоль
|
||||
log: "Сгенерированный дамп: <dumped-json-data>"
|
||||
|
||||
# Переводы всех сообщений во время проверки
|
||||
verification:
|
||||
# Переводы всех консольных сообщений во время проверки
|
||||
|
||||
@@ -57,9 +57,14 @@ commands:
|
||||
- ''
|
||||
# Ana komutu çalıştırırken gösterilen alt komutların listesi için biçimlendirme
|
||||
subcommands: '<suggest-subcommand><hover:show_text:''<gray>Sadece oyuncular: </gray><only-players><br><gray>Konsol gerekli: </gray><only-console><br><gray>İzin: </gray><white><permission><br><gray>Diğer isimler: </gray><aliases>''><dark_aqua> ▪ <gray>/sonar <suggest-subcommand><subcommand></suggest-subcommand> <white><description></hover></suggest-subcommand>'
|
||||
# Alt komutların üzerine gelinen metindeki evet (tick) ve hayır (cross) değerleri için biçimlendirme
|
||||
tick: '<green>✔</green>'
|
||||
cross: '<red>✗</red>'
|
||||
|
||||
# '/sonar reload' için çeviriler
|
||||
reload:
|
||||
# Bu alt komut için açıklama
|
||||
description: "Tüm konfigürasyonları yeniden yükle"
|
||||
# Birisi Sonar'ı yeniden yüklemeye başladığında gösterilen mesaj
|
||||
start: '<prefix>Sonar yeniden yükleniyor...'
|
||||
# Sonar yeniden yüklendiğinde gösterilen mesaj
|
||||
@@ -67,6 +72,8 @@ commands:
|
||||
|
||||
# '/sonar verbose' için çeviriler
|
||||
verbose:
|
||||
# Bu alt komut için açıklama
|
||||
description: "Sonar verbose özelliğini etkinleştirme veya devre dışı bırakma"
|
||||
# Bir oyuncu Sonar detaylı bilgilerini görmeye başladığında gösterilen mesaj
|
||||
subscribe: '<prefix>Artık Sonar detaylı bilgilerini görüntülüyorsunuz.'
|
||||
# Bir oyuncu Sonar detaylı bilgilerinden çıktığında gösterilen mesaj
|
||||
@@ -74,6 +81,8 @@ commands:
|
||||
|
||||
# '/sonar notify' için çeviriler
|
||||
notify:
|
||||
# Bu alt komut için açıklama
|
||||
description: "Saldırı bildirimlerini etkinleştirme veya devre dışı bırakma"
|
||||
# Bir oyuncu Sonar saldırı bildirimlerini görmeye başladığında gösterilen mesaj
|
||||
subscribe: '<prefix>Artık Sonar saldırı bildirimlerini görüntülüyorsunuz.'
|
||||
# Bir oyuncu Sonar saldırı bildirimlerinden çıktığında gösterilen mesaj
|
||||
@@ -81,6 +90,8 @@ commands:
|
||||
|
||||
# '/sonar blacklist' için çeviriler
|
||||
blacklist:
|
||||
# Bu alt komut için açıklama
|
||||
description: "Kara listeye alınmış IP adreslerini yönetme"
|
||||
# Birisi blacklist'i temizlemeye çalıştığında ama boş olduğunda gösterilen mesaj
|
||||
empty: '<prefix>Kara liste şu anda boş. Bu nedenle, kara listeden hiçbir IP adresi kaldırılmadı.'
|
||||
# Birisi kara listeyi temizlediğinde gösterilen mesaj
|
||||
@@ -100,6 +111,8 @@ commands:
|
||||
|
||||
# '/sonar verified' için çeviriler
|
||||
verified:
|
||||
# Bu alt komut için açıklama
|
||||
description: "Doğrulanmış IP adreslerini yönetme"
|
||||
# Birisi doğrulanmış oyuncular listesini temizlemeye çalıştığında ama boş olduğunda gösterilen mesaj
|
||||
empty: '<prefix>Doğrulanmış oyuncular listesi şu anda boş. Bu nedenle, hiçbir oyuncu doğrulanmamış olarak işaretlenmedi.'
|
||||
# Birisi doğrulanmış oyuncular listesini temizlediğinde gösterilen mesaj
|
||||
@@ -120,6 +133,8 @@ commands:
|
||||
|
||||
# '/sonar statistics' için çeviriler
|
||||
statistics:
|
||||
# Bu alt komut için açıklama
|
||||
description: "Bu sunucunun oturum istatistiklerini göster"
|
||||
# İstatistikleri görüntülerken her şeyin üzerinde gösterilen bilgilendirme mesajı
|
||||
header: 'Bu oturum için <statistics-type> istatistikleri gösteriliyor:'
|
||||
# Message that is shown when a player tries viewing an unknown statistic
|
||||
@@ -154,6 +169,13 @@ commands:
|
||||
- ' <dark_aqua>▪ <gray>Toplam gelen kullanılan bant genişliği: <white><incoming-traffic-ttl>'
|
||||
- ' <dark_aqua>▪ <gray>Toplam giden kullanılan bant genişliği: <white><outgoing-traffic-ttl>'
|
||||
|
||||
# '/sonar dump' için çeviriler
|
||||
dump:
|
||||
# Bu alt komut için açıklama
|
||||
description: "Geliştirici bilgilerini yazdır"
|
||||
# Konsola gönderilen bilginin biçimi
|
||||
log: "Oluşturulan döküm: <dumped-json-data>"
|
||||
|
||||
# Doğrulama işlemi sırasında tüm mesajlar için çeviriler
|
||||
verification:
|
||||
# Doğrulama sırasında tüm hata ayıklama mesajları için çeviriler
|
||||
|
||||
@@ -57,9 +57,14 @@ commands:
|
||||
- ''
|
||||
# 执行根命令时 对于子命令的描述.
|
||||
subcommands: '<suggest-subcommand><hover:show_text:''<gray>只有玩家可以执行该命令: </gray><only-players><br><gray>只有控制台可以执行该命令: </gray><only-console><br><gray>需要的权限: </gray><white><permission><br><gray>别名: </gray><aliases>''><dark_aqua> ▪ <gray>/sonar <subcommand> <white><description></hover></suggest-subcommand>'
|
||||
# 子命令悬停文本中 "是"(tick)和 "否"(cross)值的格式设置
|
||||
tick: '<green>✔</green>'
|
||||
cross: '<red>✗</red>'
|
||||
|
||||
# 重新加载命令
|
||||
reload:
|
||||
# 该子命令的描述
|
||||
description: "重新加载所有配置"
|
||||
# 当有人开始重载插件时显示的消息
|
||||
start: '<prefix>正在重新加载 Sonar...'
|
||||
# 插件完成重载时显示的消息
|
||||
@@ -67,6 +72,8 @@ commands:
|
||||
|
||||
# '/sonar verbose' 命令的消息
|
||||
verbose:
|
||||
# 该子命令的描述
|
||||
description: "启用或禁用 Sonar 冗余"
|
||||
# 玩家订阅详细信息时显示的消息
|
||||
subscribe: '<prefix>已为您显示 Sonar 的详细信息.'
|
||||
# 玩家取消订阅详细信息时显示的消息
|
||||
@@ -74,6 +81,8 @@ commands:
|
||||
|
||||
# '/sonar notify' 命令的消息
|
||||
notify:
|
||||
# 该子命令的描述
|
||||
description: "启用或禁用攻击通知"
|
||||
# 玩家订阅攻击通知时显示的消息
|
||||
subscribe: '<prefix>已订阅攻击通知. 当服务器受到攻击时将会提醒您.'
|
||||
# 玩家取消订阅攻击通知时显示的消息
|
||||
@@ -81,6 +90,8 @@ commands:
|
||||
|
||||
# '/sonar blacklist' 命令的消息
|
||||
blacklist:
|
||||
# 该子命令的描述
|
||||
description: "管理黑名单 IP 地址"
|
||||
# 当尝试清理黑名单但黑名单中没有任何 IP 地址显示的消息
|
||||
empty: '<prefix>黑名单中没有任何 IP 地址.'
|
||||
# 当成功清理黑名单时显示的消息
|
||||
@@ -100,6 +111,8 @@ commands:
|
||||
|
||||
# '/sonar verified' 命令的消息
|
||||
verified:
|
||||
# 该子命令的描述
|
||||
description: "管理已验证的 IP 地址"
|
||||
# 当尝试清除白名单但为空时显示的消息
|
||||
empty: '<prefix>白名单中没有任何玩家.'
|
||||
# 当成功清理白名单时显示的消息
|
||||
@@ -120,6 +133,8 @@ commands:
|
||||
|
||||
# '/sonar statistics' 命令的消息
|
||||
statistics:
|
||||
# 该子命令的描述
|
||||
description: "显示该服务器的会话统计信息"
|
||||
# 执行该命令时显示在所有输出内容(由该命令输出的消息)上方的消息
|
||||
header: '<prefix>当前会话中的 <statistics-type> 类型的统计信息:'
|
||||
# 当查看一个未知的统计信息时显示的消息
|
||||
@@ -154,6 +169,13 @@ commands:
|
||||
- ' <dark_aqua>▪ <gray>下行总量: <white><incoming-traffic-ttl>'
|
||||
- ' <dark_aqua>▪ <gray>上行总量: <white><outgoing-traffic-ttl>'
|
||||
|
||||
# '/sonar dump' 命令的消息
|
||||
dump:
|
||||
# 该子命令的描述
|
||||
description: "打印开发人员信息"
|
||||
# 发送到控制台的信息格式
|
||||
log: "生成信息: <dumped-json-data>"
|
||||
|
||||
# 验证过程中所有消息的翻译
|
||||
verification:
|
||||
# 验证过程中向控制台打印的调试信息
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
#
|
||||
# /$$$$$$
|
||||
# /$$__ $$
|
||||
# | $$ \__/ /$$$$$$ /$$$$$$$ /$$$$$$ /$$$$$$
|
||||
# | $$$$$$ /$$__ $$| $$__ $$ |____ $$ /$$__ $$
|
||||
# \____ $$| $$ \ $$| $$ \ $$ /$$$$$$$| $$ \__/
|
||||
# /$$ \ $$| $$ | $$| $$ | $$ /$$__ $$| $$
|
||||
# | $$$$$$/| $$$$$$/| $$ | $$| $$$$$$$| $$
|
||||
# \______/ \______/ |__/ |__/ \_______/|__/
|
||||
#
|
||||
# ¿Necesita ayuda o tiene alguna pregunta? https://jonesdev.xyz/discord
|
||||
# Código fuente: https://github.com/jonesdevelopment/sonar
|
||||
# Copyright Jones Development and Sonar Contributors, bajo licencia GPL-3.0
|
||||
#
|
||||
|
||||
# Bot attack notifications can also be sent to your Discord server using webhooks
|
||||
webhook:
|
||||
# URL of the Discord webhook (Set this to '' to disable webhooks)
|
||||
url: ''
|
||||
# Username of the Discord webhook sender
|
||||
username: Sonar
|
||||
# URL to the avatar of the Discord webhook sender (Set this to '' to disable)
|
||||
avatar-url: ''
|
||||
# Content of the Discord webhook message (Set this to '' to disable)
|
||||
# You can use this to e.g. ping staff members using <@userId>
|
||||
# If you want to ping roles, you will need to use <@&roleId>
|
||||
content: ''
|
||||
# Embed Discord webhook message that is sent when an attack has stopped
|
||||
embed:
|
||||
# Small footer message of the Discord webhook embed
|
||||
footer:
|
||||
# Content of the footer message of the Discord webhook embed
|
||||
text: © Jones Development and Sonar Contributors
|
||||
# URL of the footer message icon of the Discord webhook embed
|
||||
icon-url: ''
|
||||
# Title of the Discord webhook embed
|
||||
title: ':white_check_mark: Ataque mitigado'
|
||||
# Clickable URL of the title of the Discord webhook embed
|
||||
title-url: ''
|
||||
# Description (content) of the Discord webhook embed
|
||||
description:
|
||||
- El ataque a su servidor ha sido mitigado.
|
||||
- ''
|
||||
- 'Inicio del ataque: <t:<start-timestamp>:T>'
|
||||
- 'Fin del ataque: <t:<end-timestamp>:T>'
|
||||
- 'Duración del ataque: <attack-duration>'
|
||||
- ''
|
||||
- 'Uso máximo de CPU del proceso durante el ataque: <peak-cpu>%'
|
||||
- 'Uso máximo de memoria de proceso durante el ataque: <peak-memory>'
|
||||
- 'Bots máximos por segundo durante el ataque: <peak-bps>'
|
||||
- ''
|
||||
- 'Direcciones IP incluidas en la lista negra durante el ataque: <total-blacklisted>'
|
||||
- 'Verificaciones fallidas durante el ataque: <total-failed>'
|
||||
- 'Verificaciones exitosas durante el ataque: <total-success>'
|
||||
# RGB colors of the Discord webhook embed
|
||||
# Color picker: https://www.rapidtables.com/web/color/RGB_Color.html
|
||||
color:
|
||||
red: 0
|
||||
green: 255
|
||||
blue: 0
|
||||
@@ -0,0 +1,60 @@
|
||||
#
|
||||
# /$$$$$$
|
||||
# /$$__ $$
|
||||
# | $$ \__/ /$$$$$$ /$$$$$$$ /$$$$$$ /$$$$$$
|
||||
# | $$$$$$ /$$__ $$| $$__ $$ |____ $$ /$$__ $$
|
||||
# \____ $$| $$ \ $$| $$ \ $$ /$$$$$$$| $$ \__/
|
||||
# /$$ \ $$| $$ | $$| $$ | $$ /$$__ $$| $$
|
||||
# | $$$$$$/| $$$$$$/| $$ | $$| $$$$$$$| $$
|
||||
# \______/ \______/ |__/ |__/ \_______/|__/
|
||||
#
|
||||
# Butuh bantuan atau punya pertanyaan? https://jonesdev.xyz/discord
|
||||
# Kode sumber: https://github.com/jonesdevelopment/sonar
|
||||
# Hak cipta Jones Development dan Kontributor Sonar, dilisensikan di bawah GPL-3.0
|
||||
#
|
||||
|
||||
# Notifikasi serangan bot juga dapat dikirim ke server Discord Anda menggunakan webhook
|
||||
webhook:
|
||||
# URL dari webhook Discord (Atur ini ke '' untuk menonaktifkan webhook)
|
||||
url: ''
|
||||
# Nama pengguna pengirim webhook Discord
|
||||
username: Sonar
|
||||
# URL avatar pengirim webhook Discord (Atur ini ke '' untuk menonaktifkan)
|
||||
avatar-url: ''
|
||||
# Konten pesan webhook Discord (Atur ini ke '' untuk menonaktifkan)
|
||||
# Anda dapat menggunakan ini untuk misalnya memberi ping ke anggota staf menggunakan <@userId>
|
||||
# Jika Anda ingin memberi ping ke peran, Anda harus menggunakan <@&roleId>
|
||||
content: ''
|
||||
# Pesan embed webhook Discord yang dikirim ketika serangan telah berhenti
|
||||
embed:
|
||||
# Pesan footer kecil dari embed webhook Discord
|
||||
footer:
|
||||
# Konten pesan footer dari embed webhook Discord
|
||||
text: © Jones Development dan Kontributor Sonar
|
||||
# URL ikon pesan footer dari embed webhook Discord
|
||||
icon-url: ''
|
||||
# Judul dari embed webhook Discord
|
||||
title: '✅ Serangan berhasil diatasi'
|
||||
# URL yang dapat diklik dari judul embed webhook Discord
|
||||
title-url: ''
|
||||
# Deskripsi (konten) dari embed webhook Discord
|
||||
description:
|
||||
- Serangan pada server Anda telah berhasil diatasi.
|
||||
- ''
|
||||
- 'Mulai serangan: <t:<start-timestamp>:T>'
|
||||
- 'Akhir serangan: <t:<end-timestamp>:T>'
|
||||
- 'Durasi serangan: <attack-duration>'
|
||||
- ''
|
||||
- 'Penggunaan CPU proses puncak selama serangan: <peak-cpu>%'
|
||||
- 'Penggunaan memori proses puncak selama serangan: <peak-memory>'
|
||||
- 'Bot per detik puncak selama serangan: <peak-bps>'
|
||||
- ''
|
||||
- 'Alamat IP yang masuk daftar hitam selama serangan: <total-blacklisted>'
|
||||
- 'Verifikasi yang gagal selama serangan: <total-failed>'
|
||||
- 'Verifikasi yang berhasil selama serangan: <total-success>'
|
||||
# Warna RGB dari embed webhook Discord
|
||||
# Pemilih warna: https://www.rapidtables.com/web/color/RGB_Color.html
|
||||
color:
|
||||
red: 0
|
||||
green: 255
|
||||
blue: 0
|
||||
@@ -12,7 +12,7 @@ dependencies {
|
||||
tasks {
|
||||
processResources {
|
||||
val props = mapOf(
|
||||
"version" to rootProject.version.toString().split("-")[0],
|
||||
"version" to rootProject.version.toString(),
|
||||
"description" to rootProject.description,
|
||||
"url" to "https://jonesdev.xyz/discord/",
|
||||
"main" to "xyz.jonesdev.sonar.velocity.SonarVelocityPlugin"
|
||||
|
||||
@@ -28,7 +28,7 @@ import xyz.jonesdev.sonar.api.SonarPlatform;
|
||||
import xyz.jonesdev.sonar.api.logger.LoggerWrapper;
|
||||
import xyz.jonesdev.sonar.common.boot.SonarBootstrap;
|
||||
import xyz.jonesdev.sonar.velocity.command.VelocitySonarCommand;
|
||||
import xyz.jonesdev.sonar.velocity.fallback.FallbackInjectionHelper;
|
||||
import xyz.jonesdev.sonar.velocity.fallback.FallbackVelocityInjector;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -95,7 +95,7 @@ public final class SonarVelocity extends SonarBootstrap<SonarVelocityPlugin> {
|
||||
getPlugin().getServer().getCommandManager().register("sonar", new VelocitySonarCommand());
|
||||
|
||||
// Make sure to inject into the server's connection handler
|
||||
FallbackInjectionHelper.inject(getPlugin().getServer());
|
||||
FallbackVelocityInjector.inject(getPlugin().getServer());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
-60
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023-2024 Sonar Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package xyz.jonesdev.sonar.velocity.fallback;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import xyz.jonesdev.sonar.api.ReflectiveOperationException;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
|
||||
import static com.velocitypowered.proxy.network.Connections.MINECRAFT_DECODER;
|
||||
import static xyz.jonesdev.sonar.api.fallback.FallbackPipelines.FALLBACK_HANDLER;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public final class FallbackChannelInitializer extends ChannelInitializer<Channel> {
|
||||
private static final MethodHandle INIT_CHANNEL_METHOD;
|
||||
|
||||
static {
|
||||
try {
|
||||
INIT_CHANNEL_METHOD = MethodHandles.privateLookupIn(ChannelInitializer.class, MethodHandles.lookup())
|
||||
.findVirtual(ChannelInitializer.class, "initChannel", MethodType.methodType(void.class, Channel.class));
|
||||
} catch (Throwable throwable) {
|
||||
throw new ReflectiveOperationException(throwable);
|
||||
}
|
||||
}
|
||||
|
||||
private final ChannelInitializer<Channel> originalChannelInitializer;
|
||||
|
||||
@Override
|
||||
protected void initChannel(final Channel channel) throws Exception {
|
||||
// Invoke the original method
|
||||
try {
|
||||
INIT_CHANNEL_METHOD.invokeExact(originalChannelInitializer, channel);
|
||||
} catch (Throwable throwable) {
|
||||
throw new ReflectiveOperationException(throwable);
|
||||
}
|
||||
|
||||
if (channel.pipeline().get(MINECRAFT_DECODER) != null) {
|
||||
channel.pipeline().addAfter(MINECRAFT_DECODER, FALLBACK_HANDLER, new FallbackChannelHandler(channel));
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-2
@@ -29,14 +29,15 @@ import java.net.InetSocketAddress;
|
||||
|
||||
import static com.velocitypowered.proxy.network.Connections.*;
|
||||
|
||||
public final class FallbackChannelHandler extends FallbackChannelHandlerAdapter {
|
||||
public final class FallbackVelocityChannelHandler extends FallbackChannelHandlerAdapter {
|
||||
|
||||
public FallbackChannelHandler(final @NotNull Channel channel) {
|
||||
public FallbackVelocityChannelHandler(final @NotNull Channel channel) {
|
||||
super(channel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelRead(final @NotNull ChannelHandlerContext ctx, final Object msg) throws Exception {
|
||||
// TODO: put this into a separate handler
|
||||
// Intercept any handshake packet by the client
|
||||
if (listenForPackets) {
|
||||
if (msg instanceof HandshakePacket handshake) {
|
||||
+9
-4
@@ -17,7 +17,6 @@
|
||||
|
||||
package xyz.jonesdev.sonar.velocity.fallback;
|
||||
|
||||
import com.velocitypowered.api.proxy.ProxyServer;
|
||||
import com.velocitypowered.proxy.VelocityServer;
|
||||
import com.velocitypowered.proxy.network.ConnectionManager;
|
||||
import com.velocitypowered.proxy.network.ServerChannelInitializerHolder;
|
||||
@@ -25,11 +24,15 @@ import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import xyz.jonesdev.sonar.api.ReflectiveOperationException;
|
||||
import xyz.jonesdev.sonar.common.fallback.injection.FallbackInjectedChannelInitializer;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import static com.velocitypowered.proxy.network.Connections.MINECRAFT_DECODER;
|
||||
import static xyz.jonesdev.sonar.api.fallback.FallbackPipelines.FALLBACK_HANDLER;
|
||||
|
||||
@UtilityClass
|
||||
public class FallbackInjectionHelper {
|
||||
public class FallbackVelocityInjector {
|
||||
private final Field CONNECTION_MANAGER_FIELD;
|
||||
private final Field SERVER_CHANNEL_INITIALIZER_FIELD;
|
||||
|
||||
@@ -45,13 +48,15 @@ public class FallbackInjectionHelper {
|
||||
}
|
||||
}
|
||||
|
||||
public void inject(final ProxyServer proxyServer) {
|
||||
public void inject(final Object proxyServer) {
|
||||
try {
|
||||
final ConnectionManager connectionManager = (ConnectionManager) CONNECTION_MANAGER_FIELD.get(proxyServer);
|
||||
|
||||
// Make sure to store the original channel initializer
|
||||
final ChannelInitializer<Channel> originalInitializer = connectionManager.serverChannelInitializer.get();
|
||||
final ChannelInitializer<Channel> fallbackInitializer = new FallbackChannelInitializer(originalInitializer);
|
||||
final ChannelInitializer<Channel> fallbackInitializer = new FallbackInjectedChannelInitializer(
|
||||
originalInitializer, pipeline -> pipeline.addAfter(MINECRAFT_DECODER, FALLBACK_HANDLER,
|
||||
new FallbackVelocityChannelHandler(pipeline.channel())));
|
||||
|
||||
// Replace the original channel initializer
|
||||
SERVER_CHANNEL_INITIALIZER_FIELD.set(connectionManager.getServerChannelInitializer(), fallbackInitializer);
|
||||
Reference in new issue
Block a user