Compare commits

...
10 Commits
Author SHA1 Message Date
Jones 9bc3d73cb7 Release 2.0.31 (#308) 2024-05-25 15:10:26 +02:00
Jones d3aaba4650 Update translations (#307)
* fix: some English grammar mistakes

* fix: add missing Dutch translation string

* fix: add missing Georgian translations
2024-05-23 20:21:49 +02:00
Jones 68d99dd59b Update and improve some packet-related code (#306)
* fix: allow packet encode and decode method to throw exceptions

* fix: remove unnecessary annotations from FinishConfigurationPacket

* fix: don't modify the received plugin message channel
2024-05-23 18:12:02 +02:00
Jones 5f77f21ee9 Improve networking performance (#305)
* refactor: small structural changes

* build(deps): bump adventure-nbt from 4.16.0 to 4.17.0

* feat(velocity): use MethodHandles for better performance on connection

* feat(bungee): use MethodHandles for better performance on connection
2024-05-16 21:18:29 +02:00
Jones c5e1d12424 Fix NullPointerException (#304)
* fix: NullPointerException with VerifiedPlayerController

* fix: NullPointerException with Metrics
2024-05-16 20:15:05 +02:00
Jones 25dbbf0b1f Bump Gradle from 8.6 to 8.7 (#303) 2024-05-16 19:55:32 +02:00
Jones cbf04f6f2e Fix error in French webhook translations (#302) 2024-05-15 20:04:47 +02:00
Jones 8966d7d0e8 Add French translations (#300)
* feat: add French translations

* fix: small mistakes in some translations
2024-05-15 19:42:38 +02:00
dependabot[bot] 064a3cee2a Bump adventure-text-serializer-gson to 4.17.0 (#297)
Bumps [net.kyori:adventure-text-serializer-gson](https://github.com/KyoriPowered/adventure) from 4.16.0 to 4.17.0.
- [Release notes](https://github.com/KyoriPowered/adventure/releases)
- [Commits](https://github.com/KyoriPowered/adventure/compare/v4.16.0...v4.17.0)

---
updated-dependencies:
- dependency-name: net.kyori:adventure-text-serializer-gson
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-13 13:51:56 +02:00
dependabot[bot] 260af8b2be Bump adventure-text-minimessage to 4.17.0 (#298)
Bumps [net.kyori:adventure-text-minimessage](https://github.com/KyoriPowered/adventure) from 4.16.0 to 4.17.0.
- [Release notes](https://github.com/KyoriPowered/adventure/releases)
- [Commits](https://github.com/KyoriPowered/adventure/compare/v4.16.0...v4.17.0)

---
updated-dependencies:
- dependency-name: net.kyori:adventure-text-minimessage
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-13 13:50:07 +02:00
53 changed files with 798 additions and 248 deletions

No files matched your search

+2 -2
View File
@@ -36,8 +36,8 @@ allprojects {
testAnnotationProcessor("org.projectlombok:lombok:1.18.32")
// adventure
compileOnly("net.kyori:adventure-text-minimessage:4.16.0")
compileOnly("net.kyori:adventure-text-serializer-gson:4.16.0")
compileOnly("net.kyori:adventure-text-minimessage:4.17.0")
compileOnly("net.kyori:adventure-text-serializer-gson:4.17.0")
compileOnly("com.j256.ormlite:ormlite-jdbc:6.1") // ORMLite
compileOnly("com.github.ben-manes.caffeine:caffeine:3.1.8") // caching
+1 -1
View File
@@ -1,3 +1,3 @@
group=xyz.jonesdev.sonar
version=2.0.30
version=2.0.31
description=Effective Anti-bot plugin for Velocity, BungeeCord, and Bukkit (1.7-latest)
+1 -1
View File
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Vendored
+9 -8
View File
@@ -83,7 +83,8 @@ done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
@@ -144,7 +145,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
@@ -152,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
@@ -201,11 +202,11 @@ fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
Vendored
+10 -10
View File
@@ -43,11 +43,11 @@ set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
@@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
@@ -33,7 +33,6 @@ import xyz.jonesdev.sonar.api.timer.SystemTimer;
import xyz.jonesdev.sonar.api.verbose.Notification;
import xyz.jonesdev.sonar.api.verbose.Verbose;
import java.io.File;
import java.net.InetAddress;
import java.text.DecimalFormat;
import java.util.UUID;
@@ -63,8 +62,6 @@ public interface Sonar {
*/
@NotNull LoggerWrapper getLogger();
@NotNull File getDataDirectory();
@NotNull SonarConfiguration getConfig();
@NotNull SubcommandRegistry getSubcommandRegistry();
+1 -5
View File
@@ -37,12 +37,8 @@ dependencies {
implementation("net.kyori:adventure-platform-bukkit:4.3.2")
implementation("net.kyori:adventure-platform-api:4.3.2")
implementation("net.kyori:adventure-platform-facet:4.3.2")
// adventure minimessage
compileOnly("net.kyori:adventure-text-minimessage:4.16.0")
compileOnly("net.kyori:adventure-text-serializer-gson:4.16.0")
// adventure nbt
implementation("net.kyori:adventure-nbt:4.16.0")
implementation("net.kyori:adventure-nbt:4.17.0")
// We have to use 1.8 for backwards compatibility
compileOnly("org.spigotmc:spigot-api:1.8.8-R0.1-SNAPSHOT")
@@ -40,9 +40,8 @@ public final class SonarBukkit extends SonarBootstrap<SonarBukkitPlugin> {
public static SonarBukkit INSTANCE;
public SonarBukkit(final @NotNull SonarBukkitPlugin plugin) {
super(plugin, new BukkitLibraryManager(
plugin, plugin.getDataFolder().getName()),
plugin.getDataFolder(), SonarPlatform.BUKKIT);
super(plugin, SonarPlatform.BUKKIT, plugin.getDataFolder(),
new BukkitLibraryManager(plugin, plugin.getDataFolder().getName()));
INSTANCE = this;
}
@@ -116,7 +115,9 @@ public final class SonarBukkit extends SonarBootstrap<SonarBukkitPlugin> {
@Override
public void disable() {
// Make sure to properly shutdown bStats metrics
metrics.shutdown();
if (metrics != null) {
// Make sure to properly shutdown bStats metrics
metrics.shutdown();
}
}
}
+1 -5
View File
@@ -23,12 +23,8 @@ dependencies {
implementation("net.kyori:adventure-platform-bungeecord:4.3.2")
implementation("net.kyori:adventure-platform-api:4.3.2")
implementation("net.kyori:adventure-platform-facet:4.3.2")
// adventure minimessage
compileOnly("net.kyori:adventure-text-minimessage:4.16.0")
compileOnly("net.kyori:adventure-text-serializer-gson:4.16.0")
// adventure nbt
implementation("net.kyori:adventure-nbt:4.16.0")
implementation("net.kyori:adventure-nbt:4.17.0")
// Implement bStats.org for metrics
implementation("org.bstats:bstats-bungeecord:3.0.2")
@@ -41,7 +41,7 @@ public final class SonarBungee extends SonarBootstrap<SonarBungeePlugin> {
public static SonarBungee INSTANCE;
public SonarBungee(final @NotNull SonarBungeePlugin plugin) {
super(plugin, new BungeeLibraryManager(plugin), plugin.getDataFolder(), SonarPlatform.BUNGEE);
super(plugin, SonarPlatform.BUNGEE, plugin.getDataFolder(), new BungeeLibraryManager(plugin));
INSTANCE = this;
}
@@ -117,7 +117,9 @@ public final class SonarBungee extends SonarBootstrap<SonarBungeePlugin> {
@Override
public void disable() {
// Make sure to properly shutdown bStats metrics
metrics.shutdown();
if (metrics != null) {
// Make sure to properly shutdown bStats metrics
metrics.shutdown();
}
}
}
@@ -22,19 +22,21 @@ import io.netty.channel.ChannelInitializer;
import lombok.RequiredArgsConstructor;
import xyz.jonesdev.sonar.api.ReflectiveOperationException;
import java.lang.reflect.Method;
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;
@RequiredArgsConstructor
public final class FallbackChannelInitializer extends ChannelInitializer<Channel> {
private static final Method INIT_CHANNEL_METHOD;
private static final MethodHandle INIT_CHANNEL_METHOD;
static {
try {
INIT_CHANNEL_METHOD = ChannelInitializer.class.getDeclaredMethod("initChannel", Channel.class);
INIT_CHANNEL_METHOD.setAccessible(true);
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);
}
@@ -46,7 +48,7 @@ public final class FallbackChannelInitializer extends ChannelInitializer<Channel
protected void initChannel(final Channel channel) throws Exception {
// Invoke the original method
try {
INIT_CHANNEL_METHOD.invoke(originalChannelInitializer, channel);
INIT_CHANNEL_METHOD.invokeExact(originalChannelInitializer, channel);
} catch (Throwable throwable) {
throw new ReflectiveOperationException(throwable);
}
+1 -1
View File
@@ -2,7 +2,7 @@ dependencies {
compileOnly(project(":api"))
// adventure nbt for packets
compileOnly("net.kyori:adventure-nbt:4.16.0")
compileOnly("net.kyori:adventure-nbt:4.17.0")
// CAPTCHA image generation
implementation("xyz.jonesdev:capja:1.0.3")
@@ -21,12 +21,11 @@ import com.alessiodp.libby.Library;
import com.alessiodp.libby.LibraryManager;
import lombok.experimental.UtilityClass;
import org.jetbrains.annotations.NotNull;
import xyz.jonesdev.sonar.api.Sonar;
import xyz.jonesdev.sonar.api.SonarPlatform;
@UtilityClass
class LibraryLoader {
void loadLibraries(final @NotNull LibraryManager libraryManager) {
void loadLibraries(final @NotNull LibraryManager libraryManager, final @NotNull SonarPlatform platform) {
libraryManager.addMavenCentral();
libraryManager.addJitPack();
libraryManager.loadLibraries(
@@ -74,19 +73,19 @@ class LibraryLoader {
.build()
);
// Only load adventure dependencies if needed
if (Sonar.get().getPlatform() != SonarPlatform.VELOCITY) {
// Only load adventure if not on Velocity
if (platform != SonarPlatform.VELOCITY) {
libraryManager.loadLibraries(
Library.builder()
.groupId("net{}kyori")
.artifactId("adventure-text-minimessage")
.version("4.16.0")
.version("4.17.0")
.relocate("net{}kyori", "xyz{}jonesdev{}sonar{}libs{}kyori")
.build(),
Library.builder()
.groupId("net{}kyori")
.artifactId("adventure-text-serializer-gson")
.version("4.16.0")
.version("4.17.0")
.relocate("net{}kyori", "xyz{}jonesdev{}sonar{}libs{}kyori")
.build()
);
@@ -54,27 +54,22 @@ public abstract class SonarBootstrap<T> implements Sonar {
private Notification notificationHandler;
private SonarConfiguration config;
private VerifiedPlayerController verifiedPlayerController;
private File dataDirectory;
private final LibraryManager libraryManager;
private final SonarStatistics statistics;
private final SonarPlatform platform;
private final SubcommandRegistry subcommandRegistry;
private final SystemTimer launchTimer = new SystemTimer();
public SonarBootstrap(final @NotNull T plugin,
final LibraryManager libraryManager,
final File dataDirectory,
final SonarPlatform platform) {
final @NotNull SonarPlatform platform,
final @NotNull File dataDirectory,
final @NotNull LibraryManager libraryManager) {
// Load all libraries before anything else
LibraryLoader.loadLibraries(libraryManager, platform);
// Set the Sonar API
SonarSupplier.set(this);
// Store our library manager for the API
this.libraryManager = libraryManager;
// Set the plugin instance
this.plugin = plugin;
this.dataDirectory = dataDirectory;
this.platform = platform;
// Load all libraries before anything else
LibraryLoader.loadLibraries(libraryManager);
// Load the rest of the components
this.statistics = new GlobalSonarStatistics();
this.verboseHandler = new Verbose();
@@ -178,8 +173,10 @@ public abstract class SonarBootstrap<T> implements Sonar {
getLogger().info("Starting shutdown process...");
// Interrupt threads
SonarServiceThreadManager.stop();
// Close database connection
verifiedPlayerController.close();
// Close database connection if present
if (verifiedPlayerController != null) {
verifiedPlayerController.close();
}
// Run the per-platform disable method
disable();
// Thank the user for using Sonar
@@ -28,7 +28,6 @@ import xyz.jonesdev.sonar.api.Sonar;
import xyz.jonesdev.sonar.api.fallback.Fallback;
import xyz.jonesdev.sonar.api.fallback.FallbackUser;
import xyz.jonesdev.sonar.api.fallback.protocol.ProtocolVersion;
import xyz.jonesdev.sonar.common.fallback.protocol.FallbackPreparer;
import xyz.jonesdev.sonar.common.statistics.GlobalSonarStatistics;
import xyz.jonesdev.sonar.common.util.GeyserDetection;
@@ -235,7 +234,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
if (Sonar.get().hasTooManyAccounts(inetAddress, maxOnlinePerIp)) {
customDisconnect(channel, protocolVersion, FallbackPreparer.tooManyOnlinePerIP, encoder, handler);
customDisconnect(channel, protocolVersion, tooManyOnlinePerIP, encoder, handler);
return;
}
}
@@ -51,6 +51,8 @@ import static xyz.jonesdev.sonar.api.fallback.FallbackPipelines.FALLBACK_PACKET_
import static xyz.jonesdev.sonar.api.fallback.FallbackUserState.*;
import static xyz.jonesdev.sonar.api.fallback.protocol.ProtocolVersion.*;
import static xyz.jonesdev.sonar.common.fallback.protocol.FallbackPreparer.*;
import static xyz.jonesdev.sonar.common.util.ProtocolUtil.BRAND_CHANNEL;
import static xyz.jonesdev.sonar.common.util.ProtocolUtil.BRAND_CHANNEL_LEGACY;
public final class FallbackVerificationHandler implements FallbackPacketListener {
private static final Random RANDOM = new Random();
@@ -398,7 +400,7 @@ public final class FallbackVerificationHandler implements FallbackPacketListener
checkFrame(validateClientLocale(user, clientSettings.getLocale()), "invalid locale");
// Clients sometimes mess up the ClientSettings or PluginMessage packet.
// Probably caused by some weird race condition in Minecraft 1.13+
// Probably caused by some race condition in Minecraft 1.13+
if (user.getState() == CLIENT_SETTINGS) {
user.setState(PLUGIN_MESSAGE);
}
@@ -411,9 +413,11 @@ public final class FallbackVerificationHandler implements FallbackPacketListener
if (packet instanceof PluginMessagePacket) {
final PluginMessagePacket pluginMessage = (PluginMessagePacket) packet;
final boolean usingModernChannel = pluginMessage.getChannel().equals(BRAND_CHANNEL);
final boolean usingLegacyChannel = pluginMessage.getChannel().equals(BRAND_CHANNEL_LEGACY);
// Only the brand channel is important, drop the rest
if (pluginMessage.getChannel().equals("MC|Brand")
|| pluginMessage.getChannel().equals("minecraft:brand")) {
if (usingModernChannel || usingLegacyChannel) {
// Check if the brand packet was sent twice,
// which is not possible when using a vanilla Minecraft client.
checkFrame(!resolvedClientBrand, "duplicate client brand packet");
@@ -422,7 +426,7 @@ public final class FallbackVerificationHandler implements FallbackPacketListener
// system ('minecraft:' + channel) and anything below 1.13 uses
// the legacy namespace system ('MC|' + channel).
final boolean v1_13 = user.getProtocolVersion().compareTo(MINECRAFT_1_13) >= 0;
checkFrame(pluginMessage.getChannel().equals("MC|Brand") || v1_13, "invalid channel");
checkFrame(usingLegacyChannel || v1_13, "invalid channel");
// Validate the client branding using a regex to filter unwanted characters.
if (Sonar.get().getConfig().getVerification().getBrand().isEnabled()) {
@@ -18,11 +18,9 @@
package xyz.jonesdev.sonar.common.fallback.protocol.packets.config;
import io.netty.buffer.ByteBuf;
import lombok.ToString;
import xyz.jonesdev.sonar.api.fallback.protocol.ProtocolVersion;
import xyz.jonesdev.sonar.common.fallback.protocol.FallbackPacket;
@ToString
public final class FinishConfigurationPacket implements FallbackPacket {
@Override
@@ -35,6 +33,7 @@ public final class FinishConfigurationPacket implements FallbackPacket {
@Override
public int expectedMaxLength(final ByteBuf byteBuf, final ProtocolVersion protocolVersion) {
// This packet is always empty; see https://wiki.vg/Protocol#Finish_Configuration
return 0;
}
}
@@ -41,7 +41,7 @@ public final class RegistryDataPacket implements FallbackPacket {
private List<RegistryDataPacket.Bundle> bundles;
@Override
public void encode(final @NotNull ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) {
public void encode(final @NotNull ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) throws Exception {
if (protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_20_5) < 0) {
writeNamelessCompoundTag(byteBuf, tag);
} else if (type != null) {
@@ -34,7 +34,7 @@ public final class LoginAcknowledgedPacket implements FallbackPacket {
@Override
public int expectedMaxLength(final ByteBuf byteBuf, final ProtocolVersion protocolVersion) {
// https://github.com/PaperMC/Velocity/blob/dev/3.0.0/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LoginAcknowledgedPacket.java#L41
// This packet is always empty; see https://wiki.vg/Protocol#Login_Acknowledged
return 0;
}
}
@@ -41,7 +41,7 @@ public final class LoginSuccessPacket implements FallbackPacket {
private String username;
@Override
public void encode(final ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) {
public void encode(final ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) throws Exception {
if (protocolVersion.compareTo(MINECRAFT_1_19) >= 0) {
writeUUID(byteBuf, uuid);
} else if (protocolVersion.compareTo(MINECRAFT_1_16) >= 0) {
@@ -66,7 +66,7 @@ public final class ChunkDataPacket implements FallbackPacket {
}
@Override
public void encode(final @NotNull ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) {
public void encode(final @NotNull ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) throws Exception {
byteBuf.writeInt(x);
byteBuf.writeInt(z);
@@ -35,7 +35,7 @@ public final class ClientAbilitiesPacket implements FallbackPacket {
private float flySpeed, walkSpeed;
@Override
public void encode(final @NotNull ByteBuf byteBuf, final ProtocolVersion protocolVersion) {
public void encode(final @NotNull ByteBuf byteBuf, final ProtocolVersion protocolVersion) throws Exception {
byteBuf.writeByte(encodedFlags);
byteBuf.writeFloat(flySpeed);
byteBuf.writeFloat(walkSpeed);
@@ -51,7 +51,7 @@ public final class ClientSettingsPacket implements FallbackPacket {
}
@Override
public void decode(final ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) {
public void decode(final ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) throws Exception {
locale = readString(byteBuf, 16);
viewDistance = byteBuf.readByte();
chatVisibility = readVarInt(byteBuf);
@@ -37,7 +37,7 @@ public final class DefaultSpawnPositionPacket implements FallbackPacket {
private int x, y, z;
@Override
public void encode(final ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) {
public void encode(final ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) throws Exception {
if (protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_8) < 0) {
byteBuf.writeInt(x);
byteBuf.writeInt(y);
@@ -37,7 +37,7 @@ public final class DisconnectPacket implements FallbackPacket {
private boolean login;
@Override
public void encode(final ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) {
public void encode(final ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) throws Exception {
componentHolder.write(byteBuf, login ? ProtocolVersion.MINECRAFT_1_20_2 : protocolVersion);
}
@@ -46,8 +46,7 @@ public final class DisconnectPacket implements FallbackPacket {
throw new UnsupportedOperationException();
}
public static @NotNull DisconnectPacket create(final @NotNull Component component,
final boolean login) {
return new DisconnectPacket(new ComponentHolder(component), login);
public static @NotNull DisconnectPacket create(final @NotNull Component component, final boolean duringLogin) {
return new DisconnectPacket(new ComponentHolder(component), duringLogin);
}
}
@@ -33,7 +33,7 @@ public final class GameEventPacket implements FallbackPacket {
private float value;
@Override
public void encode(final @NotNull ByteBuf byteBuf, final ProtocolVersion protocolVersion) {
public void encode(final @NotNull ByteBuf byteBuf, final ProtocolVersion protocolVersion) throws Exception {
byteBuf.writeByte(type);
byteBuf.writeFloat(value);
}
@@ -47,7 +47,7 @@ public final class JoinGamePacket implements FallbackPacket {
private String levelName;
@Override
public void encode(final @NotNull ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) {
public void encode(final @NotNull ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) throws Exception {
byteBuf.writeInt(entityId);
if (protocolVersion.inBetween(MINECRAFT_1_7_2, MINECRAFT_1_7_6)) {
@@ -39,7 +39,7 @@ public final class KeepAlivePacket implements FallbackPacket {
private long id;
@Override
public void encode(final ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) {
public void encode(final ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) throws Exception {
if (protocolVersion.compareTo(MINECRAFT_1_12_2) >= 0) {
byteBuf.writeLong(id);
} else if (protocolVersion.compareTo(MINECRAFT_1_8) >= 0) {
@@ -50,7 +50,7 @@ public final class KeepAlivePacket implements FallbackPacket {
}
@Override
public void decode(final ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) {
public void decode(final ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) throws Exception {
if (protocolVersion.compareTo(MINECRAFT_1_12_2) >= 0) {
id = byteBuf.readLong();
} else if (protocolVersion.compareTo(MINECRAFT_1_8) >= 0) {
@@ -39,7 +39,7 @@ public final class PaddleBoatPacket implements FallbackPacket {
}
@Override
public void decode(final ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) {
public void decode(final @NotNull ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) throws Exception {
leftPaddle = byteBuf.readBoolean();
rightPaddle = byteBuf.readBoolean();
}
@@ -40,7 +40,7 @@ public final class PlayerInputPacket implements FallbackPacket {
}
@Override
public void decode(final @NotNull ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) {
public void decode(final @NotNull ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) throws Exception {
sideways = byteBuf.readFloat();
forward = byteBuf.readFloat();
if (protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_8) < 0) {
@@ -39,7 +39,7 @@ public final class PlayerPositionIdlePacket implements FallbackPacket {
}
@Override
public void decode(final @NotNull ByteBuf byteBuf, final ProtocolVersion protocolVersion) {
public void decode(final @NotNull ByteBuf byteBuf, final ProtocolVersion protocolVersion) throws Exception {
onGround = byteBuf.readBoolean();
}
}
@@ -64,10 +64,10 @@ public final class PlayerPositionLookPacket implements FallbackPacket {
}
@Override
public void decode(final @NotNull ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) {
public void decode(final @NotNull ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) throws Exception {
x = byteBuf.readDouble();
y = byteBuf.readDouble();
if (protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_8) < 0) {
if (protocolVersion.compareTo(MINECRAFT_1_8) < 0) {
y = byteBuf.readDouble(); // Account for weird y positions on 1.7
}
z = byteBuf.readDouble();
@@ -78,7 +78,7 @@ public final class PlayerPositionLookPacket implements FallbackPacket {
@Override
public int expectedMaxLength(final ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) {
return protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_8) < 0 ? 41 : 33;
return protocolVersion.compareTo(MINECRAFT_1_8) < 0 ? 41 : 33;
}
@Override
@@ -26,6 +26,8 @@ import org.jetbrains.annotations.NotNull;
import xyz.jonesdev.sonar.api.fallback.protocol.ProtocolVersion;
import xyz.jonesdev.sonar.common.fallback.protocol.FallbackPacket;
import static xyz.jonesdev.sonar.api.fallback.protocol.ProtocolVersion.MINECRAFT_1_8;
@Getter
@ToString
@NoArgsConstructor
@@ -40,10 +42,10 @@ public final class PlayerPositionPacket implements FallbackPacket {
}
@Override
public void decode(final @NotNull ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) {
public void decode(final @NotNull ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) throws Exception {
x = byteBuf.readDouble();
y = byteBuf.readDouble();
if (protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_8) < 0) {
if (protocolVersion.compareTo(MINECRAFT_1_8) < 0) {
y = byteBuf.readDouble(); // Account for weird y positions on 1.7
}
z = byteBuf.readDouble();
@@ -52,7 +54,7 @@ public final class PlayerPositionPacket implements FallbackPacket {
@Override
public int expectedMaxLength(final ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) {
return protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_8) < 0 ? 33 : 25;
return protocolVersion.compareTo(MINECRAFT_1_8) < 0 ? 33 : 25;
}
@Override
@@ -24,9 +24,9 @@ import org.jetbrains.annotations.NotNull;
import xyz.jonesdev.sonar.api.fallback.protocol.ProtocolVersion;
import xyz.jonesdev.sonar.common.fallback.protocol.FallbackPacket;
import static xyz.jonesdev.sonar.api.fallback.protocol.ProtocolVersion.MINECRAFT_1_13;
import static xyz.jonesdev.sonar.api.fallback.protocol.ProtocolVersion.MINECRAFT_1_8;
import static xyz.jonesdev.sonar.common.util.ProtocolUtil.*;
import static xyz.jonesdev.sonar.common.util.ProtocolUtil.readRetainedByteBufSlice17;
import static xyz.jonesdev.sonar.common.util.ProtocolUtil.readString;
@Getter
@ToString
@@ -40,12 +40,8 @@ public final class PluginMessagePacket implements FallbackPacket {
}
@Override
public void decode(final ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) {
channel = readString(byteBuf, 512);
if (protocolVersion.compareTo(MINECRAFT_1_13) >= 0) {
channel = transformLegacyToModernChannel(channel);
}
public void decode(final ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) throws Exception {
channel = readString(byteBuf, 64);
if (protocolVersion.compareTo(MINECRAFT_1_8) >= 0) {
slicedBuffer = byteBuf.readRetainedSlice(byteBuf.readableBytes());
@@ -36,7 +36,7 @@ public final class RemoveEntitiesPacket implements FallbackPacket {
private int entityId; // We only need one entityId
@Override
public void encode(final ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) {
public void encode(final ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) throws Exception {
// No idea why Mojang decided that this is a good idea, but whatever
if (protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_17) != 0) {
writeVarInt(byteBuf, 1); // size
@@ -38,7 +38,7 @@ public final class SetExperiencePacket implements FallbackPacket {
private int totalExperience;
@Override
public void encode(final @NotNull ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) {
public void encode(final @NotNull ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) throws Exception {
byteBuf.writeFloat(experienceBar);
if (protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_8) < 0) {
byteBuf.writeShort(level);
@@ -36,7 +36,7 @@ public final class SetPassengersPacket implements FallbackPacket {
private int entityId, passengerId;
@Override
public void encode(final ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) {
public void encode(final ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) throws Exception {
// You can find this in the EntityAttach packet,
// which was later replaced by SetPassengers in 1.9+
if (protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_9) < 0) {
@@ -44,7 +44,7 @@ public final class SetSlotPacket implements FallbackPacket {
.build();
@Override
public void encode(final @NotNull ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) {
public void encode(final @NotNull ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) throws Exception {
byteBuf.writeByte(0); // windowId
if (protocolVersion.compareTo(MINECRAFT_1_17_1) >= 0) {
@@ -39,7 +39,7 @@ public final class SpawnEntityPacket implements FallbackPacket {
private double x, y, z;
@Override
public void encode(final ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) {
public void encode(final ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) throws Exception {
writeVarInt(byteBuf, entityId);
final boolean v1_9orHigher = protocolVersion.compareTo(MINECRAFT_1_8) > 0;
@@ -40,7 +40,7 @@ public final class TeleportConfirmPacket implements FallbackPacket {
}
@Override
public void decode(final ByteBuf byteBuf, final ProtocolVersion protocolVersion) {
public void decode(final ByteBuf byteBuf, final ProtocolVersion protocolVersion) throws Exception {
teleportId = readVarInt(byteBuf);
}
}
@@ -37,7 +37,7 @@ public final class TransactionPacket implements FallbackPacket {
private boolean accepted;
@Override
public void decode(final ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) {
public void decode(final ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) throws Exception {
if (protocolVersion.compareTo(MINECRAFT_1_17) < 0) {
windowId = byteBuf.readByte();
transactionId = byteBuf.readShort();
@@ -51,7 +51,7 @@ public final class TransactionPacket implements FallbackPacket {
}
@Override
public void encode(final ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) {
public void encode(final ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) throws Exception {
if (protocolVersion.compareTo(MINECRAFT_1_17) < 0) {
byteBuf.writeByte(windowId);
byteBuf.writeShort((short) transactionId);
@@ -38,7 +38,7 @@ public final class TransferPacket implements FallbackPacket {
private int destinationPort;
@Override
public void encode(final ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) {
public void encode(final ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) throws Exception {
writeString(byteBuf, destinationHost);
writeVarInt(byteBuf, destinationPort);
}
@@ -56,7 +56,7 @@ public final class UniversalChatPacket implements FallbackPacket {
}
@Override
public void encode(final ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) {
public void encode(final ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) throws Exception {
// Serialized message
componentHolder.write(byteBuf, protocolVersion);
@@ -77,7 +77,7 @@ public final class UniversalChatPacket implements FallbackPacket {
}
@Override
public void decode(final ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) {
public void decode(final ByteBuf byteBuf, final @NotNull ProtocolVersion protocolVersion) throws Exception {
message = readString(byteBuf, 256);
if (protocolVersion.compareTo(MINECRAFT_1_19) >= 0) {
@@ -31,21 +31,15 @@ import java.io.DataOutput;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.UUID;
import java.util.regex.Pattern;
// Taken from
// Mostly taken from
// https://github.com/PaperMC/Velocity/blob/dev/3.0.0/proxy/src/main/java/com/velocitypowered/proxy/protocol/ProtocolUtils.java
@UtilityClass
public class ProtocolUtil {
private static final int FORGE_MAX_ARRAY_LENGTH = Integer.MAX_VALUE & 0x1FFF9A;
private static final String BRAND_CHANNEL_LEGACY = "MC|Brand";
private static final String BRAND_CHANNEL = "minecraft:brand";
private static final String REGISTER_CHANNEL_LEGACY = "REGISTER";
private static final String REGISTER_CHANNEL = "minecraft:register";
private static final String UNREGISTER_CHANNEL_LEGACY = "UNREGISTER";
private static final String UNREGISTER_CHANNEL = "minecraft:unregister";
private static final Pattern INVALID_IDENTIFIER_REGEX = Pattern.compile("[^a-z0-9\\-_]*");
public static final String BRAND_CHANNEL_LEGACY = "MC|Brand";
public static final String BRAND_CHANNEL = "minecraft:brand";
public static int readVarInt(final ByteBuf byteBuf) {
int read = readVarIntSafely(byteBuf);
@@ -247,7 +241,7 @@ public class ProtocolUtil {
}
}
public static void writeCompoundTag(final ByteBuf byteBuf, final CompoundBinaryTag compoundTag) {
public static void writeCompoundTag(final @NotNull ByteBuf byteBuf, final @NotNull CompoundBinaryTag compoundTag) {
try {
BinaryTagIO.writer().write(compoundTag, (DataOutput) new ByteBufOutputStream(byteBuf));
} catch (IOException exception) {
@@ -310,26 +304,6 @@ public class ProtocolUtil {
return byteBuf.readRetainedSlice(length);
}
public static @NotNull String transformLegacyToModernChannel(@NotNull final String name) {
if (name.indexOf(':') != -1) {
return name;
}
switch (name) {
case REGISTER_CHANNEL_LEGACY:
return REGISTER_CHANNEL;
case UNREGISTER_CHANNEL_LEGACY:
return UNREGISTER_CHANNEL;
case BRAND_CHANNEL_LEGACY:
return BRAND_CHANNEL;
case "BungeeCord":
return "bungeecord:main";
default:
final String lower = name.toLowerCase();
return "legacy:" + INVALID_IDENTIFIER_REGEX.matcher(lower).replaceAll("");
}
}
private void checkFrame(final boolean expression, final String message) {
if (!expression) {
throw new CorruptedFrameException(message);
@@ -28,7 +28,7 @@ attack-tracker:
# Amount of time that has to pass in order for an attack to be over
# (This value represents the time in milliseconds: 1 second = 1000 milliseconds)
min-attack-duration: 30000
# Number of times an incident has to be reported in order to be acknowledged as an attack
# Number of times an incident has to be reported to be acknowledged as an attack
# This number acts as a buffer to filter out false attack notifications
min-attack-threshold: 2
# Amount of time that has to pass in order for a new attack to be detected
@@ -71,7 +71,7 @@ verification:
timing: ALWAYS
checks:
# Checks if the players' falling motion is following Minecraft's gravity formula
# All predicted motions are precalculated in order to save performance
# All predicted motions are precalculated to save performance
gravity:
# Should Sonar check for valid client gravity? (Recommended)
enabled: true
@@ -79,7 +79,7 @@ verification:
check-collisions: true
# Should Sonar make the player solve a CAPTCHA if they fail the gravity check?
captcha-on-fail: false
# Maximum number of ticks the player has to fall in order to be allowed to hit the platform
# Maximum number of ticks the player has to fall to be allowed to hit the platform
max-movement-ticks: 8
# The gamemode of the player during verification
# Possible types: SURVIVAL, CREATIVE, ADVENTURE
@@ -132,7 +132,7 @@ verification:
mix: 0.15
# Path to the background image Sonar uses for the CAPTCHA
# If the image isn't found, a noise will be used as the default background
# You can simply put the name of the file here if file is in the plugin directory
# You can put the name of the file here if the file is in the plugin directory
background: ''
# Should Sonar automatically detect the background color?
# This is done to create a contrast between the background image and the text
@@ -150,7 +150,7 @@ verification:
# It is not recommended to add numbers or letters that might look like one another
dictionary: '1235689'
# Checks if the players is sending a valid client brand to the server
# Checks if the players are sending a valid client brand to the server
client-brand:
# Should Sonar check for valid client brands? (Recommended)
enabled: true
@@ -163,7 +163,7 @@ verification:
valid-name-regex: ^[a-zA-Z0-9_]+$
# Regex for validating client locale during verification
valid-locale-regex: ^[a-zA-Z_]+$
# Ping a player has to have in order to timeout
# Ping a player has to have to timeout
# (This value represents the time in milliseconds: 1 second = 1000 milliseconds)
max-ping: 10000
# Maximum number of login packets the player has to send in order to be kicked
@@ -0,0 +1,222 @@
#
# /$$$$$$
# /$$__ $$
# | $$ \__/ /$$$$$$ /$$$$$$$ /$$$$$$ /$$$$$$
# | $$$$$$ /$$__ $$| $$__ $$ |____ $$ /$$__ $$
# \____ $$| $$ \ $$| $$ \ $$ /$$$$$$$| $$ \__/
# /$$ \ $$| $$ | $$| $$ | $$ /$$__ $$| $$
# | $$$$$$/| $$$$$$/| $$ | $$| $$$$$$$| $$
# \______/ \______/ |__/ |__/ \_______/|__/
#
# Besoin d'aide ou d'autres questions ? https://jonesdev.xyz/discord
# Code source : https://github.com/jonesdevelopment/sonar
# Droit d'auteur Jones Development, un contributeur Sonar, licence sous GPL-3.0
#
# Paramètre général de Sonar
general:
# Devrait Sonar enregistrer les adresses IP des joueurs dans la console ?
log-player-addresses: true
# Nombre maximum de joueurs en ligne avec la même IP
max-online-per-ip: 3
# Paramètre de détection d'attaque
# Modifier uniquement si vous savez ce que vous faites
attack-tracker:
# Nombre minimum de nouveaux joueurs pour qu'une attaque soit détectée
min-players-for-attack: 8
# Durée nécessaire pour qu'une attaque soit considérée comme terminée
# (Cette valeur représente le temps en millisecondes : 1 seconde = 1000 millisecondes)
min-attack-duration: 30000
# Nombre de fois qu'un incident doit être signalé pour être reconnu comme une attaque
# Ce nombre sert de tampon pour filtrer les fausses notifications d'attaque
min-attack-threshold: 2
# Durée nécessaire pour qu'une nouvelle attaque soit détectée
# (Cette valeur représente le temps en millisecondes : 1 seconde = 1000 millisecondes)
attack-cooldown-delay: 3000
# Vous pouvez connecter Sonar à une base de données pour conserver les joueurs vérifiés même après le redémarrage de votre serveur
# 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
type: NONE
# 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
port: 3306
# Nom de la base de données SQL
name: sonar
# Nom d'utilisateur pour l'authentification avec la base de données SQL
username: ''
# Mot de passe pour l'authentification avec la base de données SQL
password: ''
# Pendant combien de jours Sonar doit-il conserver les joueurs vérifiés dans la base de données ?
maximum-age: 5
# Chaque nouvelle demande de connexion sera mise en file d'attente pour éviter les attaques d'inscription par spam
# La file d'attente est mise à jour toutes les 1 seconde (20 ticks)
queue:
# Nombre maximum de demandes de connexion en file d'attente simultanées par seconde
max-polls: 30
# Chaque nouveau joueur qui se connecte pour la première fois sera envoyé à
# un serveur limbo léger où des vérifications avancées de bot sont effectuées
verification:
# Quand Sonar devrait-il vérifier les nouveaux joueurs ?
# Types possibles : ALWAYS, DURING_ATTACK, NEVER
# - ALWAYS : Les nouveaux joueurs seront toujours vérifiés (Recommandé)
# - DURING_ATTACK : Les nouveaux joueurs ne seront vérifiés que pendant une attaque
# - NEVER : Les nouveaux joueurs ne seront jamais vérifiés
timing: ALWAYS
checks:
# Vérifie si le mouvement de chute des joueurs suit la formule de la gravité de Minecraft
# Tous les mouvements prévus sont précalculés afin d'économiser les performances
gravity:
# Sonar devrait-il vérifier la gravité du client ? (Recommandé)
enabled: true
# Sonar devrait-il vérifier si le joueur entre en collision avec des blocs ? (Recommandé)
check-collisions: true
# Sonar devrait-il faire résoudre un CAPTCHA au joueur s'il échoue à la vérification de la gravité ?
captcha-on-fail: false
# Nombre maximum de ticks que le joueur a pour tomber avant de pouvoir toucher la plateforme
max-movement-ticks: 8
# Le mode de jeu du joueur pendant la vérification
# Types possibles : SURVIVAL, CREATIVE, ADVENTURE
# - SURVIVAL : tous les composants de l'interface utilisateur sont visibles
# - CREATIVE : la santé et la faim sont cachées
# - ADVENTURE : tous les composants de l'interface utilisateur sont visibles
gamemode: ADVENTURE
# Vérifie si le client envoie les paquets appropriés lorsqu'il monte dans un véhicule
vehicle:
# Types possibles : ALWAYS, DURING_ATTACK, NEVER
# - ALWAYS : Les nouveaux joueurs seront toujours montés dans un véhicule (Recommandé)
# - DURING_ATTACK : Les nouveaux joueurs ne seront montés dans un véhicule que pendant une attaque
# - NEVER : Les nouveaux joueurs ne seront jamais montés dans un véhicule
timing: ALWAYS
# Fait taper au joueur un code à partir d'une carte virtuelle dans le chat
map-captcha:
# Quand Sonar devrait-il faire résoudre un CAPTCHA au joueur ?
# Types possibles : ALWAYS, DURING_ATTACK, NEVER
# - ALWAYS : Les nouveaux joueurs recevront toujours un CAPTCHA
# - DURING_ATTACK : Les nouveaux joueurs ne recevront un CAPTCHA que pendant une attaque
# - NEVER : Les nouveaux joueurs ne recevront jamais de CAPTCHA (Recommandé)
timing: NEVER
# Options pour les effets sur l'image montrée au joueur
# Vous ne devriez modifier cela que si vous savez ce que vous faites
effects:
# Ajoute des lignes aléatoires à l'image
scratches: true
# Applique un filtre d'ondulation (effet ondulé)
ripple: true
# Applique un filtre de bosse (texte accentué)
bump: true
# Filtre de distorsion
distortion:
# Sonar devrait-il appliquer un filtre de distorsion ?
enabled: true
# Quelle forme Sonar devrait-il utiliser pour le filtre de distorsion ?
# Types possibles : 0, 1, 2, 3
# - 0 : Croix
# - 1 : Lignes
# - 2 : Cercles
# - 3 : Carrés
shape: 2
# Distance entre les pixels/objets déformés
distance: 5
# Densité des pixels/objets déformés
density: 0.1
# Quantité de mélange entre les couleurs des objets
mix: 0.15
# Chemin vers l'image d'arrière-plan que Sonar utilise pour le CAPTCHA
# Si l'image n'est pas trouvée, un bruit sera utilisé comme arrière-plan par défaut
# Vous pouvez simplement mettre le nom du fichier ici si le fichier est dans le répertoire du plugin
background: ''
# Sonar devrait-il détecter automatiquement la couleur de fond ?
# Cela est fait pour créer un contraste entre l'image d'arrière-plan et le texte
# Si cela est désactivé, Sonar utilisera un dégradé aléatoire pour les couleurs
auto-color: false
# Combien de réponses Sonar devrait-il préparer ?
# Cette tâche se déroule de manière asynchrone en arrière-plan
precompute: 500
# Combien de temps Sonar devrait-il attendre jusqu'à ce que le joueur échoue le CAPTCHA ?
# (Cette valeur représente le temps en millisecondes : 1 seconde = 1000 millisecondes)
max-duration: 30000
# Combien de fois un joueur doit-il échouer au CAPTCHA avant d'échouer la vérification ?
max-tries: 3
# Caractères (lettres et chiffres) autorisés à apparaître dans la réponse au CAPTCHA
# Il n'est pas recommandé d'ajouter des chiffres ou des lettres qui pourraient se ressembler
dictionary: '1235689'
# Vérifie si le joueur envoie une marque client valide au serveur
client-brand:
# Sonar devrait-il vérifier les marques client valides ? (Recommandé)
enabled: true
# Regex pour valider les marques client lors de la vérification
valid-regex: ^[!-~ ]+$
# Longueur maximale de la marque client lors de la vérification
max-length: 64
# Regex pour valider les noms d'utilisateur lors de la vérification
valid-name-regex: ^[a-zA-Z0-9_]+$
# Regex pour valider la locale client lors de la vérification
valid-locale-regex: ^[a-zA-Z_]+$
# Le ping qu'un joueur doit avoir pour dépasser le délai d'attente
# (Cette valeur représente le temps en millisecondes : 1 seconde = 1000 millisecondes)
max-ping: 10000
# Nombre maximal de paquets de connexion que le joueur doit envoyer pour être expulsé
max-login-packets: 256
# S'il est activé, le joueur sera renvoyé au serveur d'origine
# après avoir passé avec succès la vérification du bot.
# Cette fonctionnalité a été introduite par Mojang dans la version Minecraft 1.20.5
transfer:
# Sonar devrait-il transférer le joueur au serveur d'origine (au lieu de l'expulser) ?
# Pour que cela fonctionne, vous devez activer la fonctionnalité dans la configuration de votre serveur
# De plus, vous voudrez peut-être réduire la quantité de limitation de débit de connexion
# effectuée par Velocity ou d'autres proxys/plugins, car cela pourrait empêcher le
# joueur d'être transféré correctement.
enabled: false
# Quel serveur Sonar devrait-il utiliser pour transférer le joueur une fois la vérification réussie ?
# Veuillez entrer l'adresse IP du serveur que les joueurs utilisent normalement pour se connecter à votre serveur.
# Par exemple, vous pouvez mettre "mc.hypixel.net" ou une IP directe comme "1.1.1.1"
destination-host: "play.my-server.com"
# Quel port Sonar devrait-il utiliser pour transférer le joueur au serveur d'origine ?
# Si votre serveur n'a pas besoin d'un port pour se connecter, vous pouvez laisser celui-ci comme 25565.
destination-port: 25565
# Sonar devrait-il journaliser les nouvelles tentatives de vérification ?
log-connections: true
# Sonar devrait-il journaliser les nouvelles tentatives de vérification pendant les attaques ?
log-during-attack: false
# Sonar devrait-il journaliser chaque changement de position/mouvement pendant la vérification ?
# Ce n'est pas recommandé pour les serveurs de production mais peut être utile pour repérer les erreurs.
debug-xyz-positions: false
# Sonar devrait-il également vérifier les joueurs Geyser (Bedrock) ?
# Cette fonctionnalité est expérimentale et peut causer des problèmes
# Si cela est désactivé, les joueurs Bedrock seront ignorés
check-geyser-players: true
# Durée avant qu'un joueur ne soit déconnecté
# (Cette valeur représente le temps en millisecondes : 1 seconde = 1000 millisecondes)
read-timeout: 8000
# Combien de temps un joueur doit-il attendre avant de se reconnecter pendant la vérification
# (Cette valeur représente le temps en millisecondes : 1 seconde = 1000 millisecondes)
rejoin-delay: 8000
# Combien de temps Sonar doit-il se souvenir du nombre de vérifications échouées pour un joueur ?
# (Cette valeur représente le temps en millisecondes : 1 seconde = 1000 millisecondes)
remember-time: 120000
# Combien de temps une adresse IP doit-elle être interdite de connexion en cas d'échec trop fréquent de la vérification ?
# (Cette valeur représente le temps en millisecondes : 1 seconde = 1000 millisecondes)
blacklist-time: 600000
# Combien de fois un joueur doit-il échouer à la vérification pour être placé sur liste noire ?
# (Réglez cette valeur à 0 pour désactiver la liste noire entièrement)
blacklist-threshold: 2
# Liste des identifiants de protocole qui ne sont pas vérifiés par Sonar (bypass de vérification)
# Vous pouvez trouver la liste complète de tous les identifiants de protocole ici :
# https://wiki.vg/Protocol_version_numbers
# Par exemple, Minecraft 1.20 a l'ID 763.
whitelisted-protocols: []
# Liste des identifiants de protocole qui ne peuvent pas du tout rejoindre le serveur
blacklisted-protocols: []
@@ -66,7 +66,7 @@ verification:
# როდის უნდა გადაამოწმოს Sonar-მა ახალი მოთამაშეები?
# შესაძლო ტიპები: ALWAYS, DURING_ATTACK, NEVER
# - ALWAYS: ახალი მოთამაშეები ყოველთვის მოწმდება (რეკომენდებულია)
# - DURING_ATTACK: ახალი მოთამაშეები შემოწმდებიან მხოლოდ შეტევის დროს
# - DURING_ATTACK: ახალი მოთამაშეები შემოწმდებიან მხოლოდ შეტევის დროსდროს
# - NEVER: ახალი მოთამაშეები არასოდეს შემოწმდებიან
timing: ALWAYS
checks:
@@ -88,12 +88,12 @@ verification:
# - ADVENTURE: ყველა UI კომპონენტი ჩანს
gamemode: ADVENTURE
# Checks if the client sends proper packets when mounting a vehicle
# ამოწმებს, აგზავნის თუ არა კლიენტი შესაბამის პაკეტებს სატრანსპორტო საშუალებაზე დაჯდომის დროს
vehicle:
# Possible types: ALWAYS, DURING_ATTACK, NEVER
# - ALWAYS: New players will always be mounted on a vehicle (Recommended)
# - DURING_ATTACK: New players will only be mounted on a vehicle during an attack
# - NEVER: New players will never be mounted on a vehicle
# შესაძლო ტიპები: ALWAYS, DURING_ATTACK, NEVER
# - ALWAYS: ახალი მოთამაშეები ყოველთვის დაჯდებიან სატრანსპორტო საშუალებაზე
# - DURING_ATTACK: ახალი მოთამაშეები მხოლოდ ბოტების შემოტევის დროს დაჯდებიან სატრანსპორტო საშუალებაზე
# - NEVER: ახალი მოთამაშეები არასოდეს დაჯდებიან სატრანსპორტო საშუალებაზე (რეკომენდებულია)
timing: ALWAYS
# დააწერინეთ მოთამაშეს კოდი ჩატში, რომელიც იქნება ნაჩვენები ვირტუალურ მაპზე, რომელიც ხელში ეჭირებად
@@ -104,38 +104,39 @@ verification:
# - DURING_ATTACK: ახალი მოთამაშებს მოუწევთ CAPTCHA-ს გაკეთება მხოლოდ შეტევის დროს
# - NEVER: ახალ მოთამაშეებს არასდროს მოუწევთ CAPTCHA-ს გაკეთება (Recommended)
timing: NEVER
# Options for the effects on the image shown to the player
# You should only edit this if you know what you're doing
# ეფექტების პარამეტრები გამოსახულებაზე, რომელიც აჩვენა მოთამაშეს
# თქვენ უნდა შეცვალოთ ეს მხოლოდ იმ შემთხვევაში, თუ იცით, რას აკეთებთ
effects:
# Adds random lines to the image
# მატებს შემთხვევითი ხაზების ეფექტს გამოსახულებაზე
scratches: true
# Applies a ripple filter (wavy effect)
# აყენებს ტალღური ეფექტის ფილტრს (ტალღისებური ეფექტი)
ripple: true
# Applies a bump filter (sharpened text)
# აყენებს ამობურცული ტექსტის ფილტრს (გამხრწნილი ტექსტი)
bump: true
# Distortion filter
# დამახინჯების ფილტრი
distortion:
# Should Sonar apply a distortion filter?
# უნდა დაამატოს თუ არა Sonar-მა დამახინჯების ფილტრი?
enabled: true
# What shape should Sonar use for the distortion filter?
# Possible types: 0, 1, 2, 3
# - 0: Crosses
# - 1: Lines
# - 2: Circles
# - 3: Squares
# რა ფორმას უნდა გამოიყენოს Sonar-მა დამახინჯების ფილტრისთვის?
# შესაძლო ტიპები: 0, 1, 2, 3
# - 0: ჯვრები
# - 1: ხაზები
# - 2: წრეები
# - 3: კვადრატები
shape: 2
# Distance between distorted pixels/objects
# მანძილი დამახინჯებულ პიქსელებს/ობიექტებს შორის
distance: 5
# Density of the distorted pixels/objects
# დამახინჯებული პიქსელების/ობიექტების სიხშირე
density: 0.1
# Amount of blending between the colors of objects
# შერევის ხარისხი ობიექტების ფერებს შორის
mix: 0.15
# Path to the background image Sonar uses for the CAPTCHA
# If the image isn't found, a noise will be used as the default background
# CAPTCHA-სთვის Sonar-ის მიერ გამოყენებული ფონური გამოსახულების ბილიკი
# თუ გამოსახულება არ მოიძებნა, ფონად გამოყენებული იქნება noise ი
# შეგიძლიათ უბრალოდ ჩაწეროთ ფაილის სახელი, თუ ის პლაგინის დირექტორიაშია
background: ''
# Should Sonar automatically detect the background color?
# This is done to create a contrast between the background image and the text
# You can simply put the name of the file here if file is in the plugin directory
# უნდა განსაზღვროს თუ არა Sonar-მა ავტომატურად ფონის ფერი?
# ეს კეთდება იმისთვის, რომ შეიქმნას კონტრასტი ფონის გამოსახულებასა და ტექსტს შორის
# თუ ეს გამორთულია, Sonar-ი გამოიყენებს შემთხვევით გრადიენტს ფერებისთვის
auto-color: false
# რამდენი პასუხი უნდა მოამზადოს Sonar-მა?
# ეს ხდება ასინქრონულად უკანა ფონზე
@@ -146,10 +147,10 @@ verification:
# რამდენჯერ ვერ უდნა გაიაროს CAPTCHA მოთამაშემ სანამ ვერიფიკაციას ვერ გაივლის?
max-tries: 3
# სიმბოლოები (ასოები და რიცხვები), რომლებიც დაშვებულია გამოჩნდეს CAPTCHA-ს პასუხში
# It is not recommended to add numbers or letters that might look like one another
# არ არის რეკომენდებული რიცხვების ან ასოების დამატება, რომლებიც შეიძლება ერთმანეთს ჰგავდეს
dictionary: '1235689'
#ამოწმებს, აგზავნიან თუ არა მოთამაშეები სერვერზე რეალურ კლიენტის სახელს
# ამოწმებს, აგზავნიან თუ არა მოთამაშეები სერვერზე რეალურ კლიენტის სახელს
client-brand:
# უნდა შეამოწმოს თუ არა Sonar-მა ნამდვილია თუ არა მოთამაშის კლიენტის სახელი? (რეკომენდებულია)
enabled: true
@@ -168,22 +169,21 @@ verification:
# მაქსიმალური რაოდენობა ლოგინ პაკეტების, რომელიც მოთამაშემ უნდა გააგზავნოს სანამ გაიკიკება სერვერიდან
max-login-packets: 256
# If enabled, the player will be transferred back to the origin server
# after successfully passing the bot verification.
# This feature was introduced by Mojang in Minecraft version 1.20.5
# თუ ჩართულია, მოთამაშე გადავა საწყისი სერვერში ერიფიკაციის წარმატებით გავლის შემდეგ
# ეს ფუნქცია დაემატა Mojang-ის მიერ Minecraft-ის 1.20.5 ვერსიაში
transfer:
# Should Sonar transfer the player to the origin server (instead of kicking them)?
# For this to work, you must enable the feature in your server's configuration
# Additionally, you might want to reduce the amount of login rate-limiting
# performed by Velocity or other proxies/plugins, as this might prevent the
# player from being transferred correctly.
# უნდა გადაიყვანოს თუ არა Sonar-მა მოთამაშე საწყის სერვერზე (მათი გაკიკვის ნაცვლად)?
# ამისთვის, თქვენ უნდა ჩართოთ ეს ფუნქცია თქვენი სერვერის კონფიგურაციაში
# დამატებით, შეიძლება გინდოდეთ შეამციროთ შესვლის rate-limiting ი
# რომელსაც ახორციელებს Velocity ან სხვა პროქსები/პლაგინები, რადგან ეს შეიძლება ხელს უშლიდეს
# მოთამაშის სწორად გადაყვანას
enabled: false
# Which server should Sonar transfer the player to when the verification is passed?
# Please enter the server IP that is used by players to normally connect to your server.
# For example, you can put "mc.hypixel.net" or a direct IP like "1.1.1.1"
# რომელ სერვერზე უნდა გადაიყვანოს Sonar-მა მოთამაშე ვერიფიკაციის გავლის შემდეგ?
# გთხოვთ, შეიყვანოთ სერვერის IP მისამართი, რომლითაც მოთამაშეები ჩვეულებრივ უერთდებიან თქვენს სერვერს
# მაგალითად, შეგიძლიათ ჩაწეროთ "mc.hypixel.net" ან პირდაპირი IP როგორიცაა "1.1.1.1"
destination-host: "play.my-server.com"
# Which port should Sonar use when transferring the player to the origin server?
# If your server does not need a port to connect to, you can leave this as 25565.
# რომელი პორტი უნდა გამოიყენოს Sonar-მა მოთამაშის საწყის სერვერზე გადაყვანისას?
# თუ თქვენს სერვერს არ სჭირდება პორტი შესასვლელად, შეგიძლიათ დატოვოთ ეს 25565-ზე
destination-port: 25565
# ჩაიწეროს თუ არა Sonar-მა ახალი ვერიფიკაციის მცდელობები?
@@ -193,9 +193,9 @@ verification:
# ჩაიწეროს თუ არა Sonar-მა ყოველი მოძრაობა/პოზიცია ვერიფიკაციის დროს?
# ეს არ არის რეკომენდირებული აქტიურ სერვერებისთვის, მაგრამ შეიძლება გამოსადეგი იყოს ცრუ პოსიტივების გამოსასწორებლად.
debug-xyz-positions: false
# Should Sonar also check Geyser (Bedrock) players?
# This feature is experimental and might cause issues
# If this is disabled, Bedrock players will be skipped
# უნდა შეამოწმოს თუ არა Sonar-მა Geyser (Bedrock) მოთამაშეები?
# ეს ფუნქცია ექსპერიმენტულია და შეიძლება გამოიწვიოს პრობლემები
# თუ ეს გამორთულია, Bedrock მოთამაშეები გამოვლენილი იქნება
check-geyser-players: true
# დროის ოდენობა, რომელიც უნდა გავიდეს, სანამ მოთამაშე ტაიმაუტდება სერვერიდან.
# (ეს არის ნაჩვენები მილიწამებში: 1 წამი = 1000 მილიწამი)
@@ -203,7 +203,7 @@ verification:
# რამდენ ხანს უნდა დაელოდოს მოთამაშე ვერიფიკაციის დროს ხელახლა დაკავშირებამდე?
# (ეს არის ნაჩვენები მილიწამებში: 1 წამი = 1000 მილიწამი)
rejoin-delay: 8000
# How long should Sonar remember the amount of failed verifications for a player?
# რამდენ ხანს უნდა ახსოვდეს Sonar-ს მოთამაშე რამდენჯერ იყო წარუმატებელი ვერიფიკაციის დროს?
# (ეს არის ნაჩვენები მილიწამებში: 1 წამი = 1000 მილიწამი)
remember-time: 120000
# რამდენ ხნით უნდა აეკრძალოს IP მისამართს შესვლა, როდესაც ვერიფიკაციას ძალიან ხშირად ვერ აკეთებს?
@@ -24,7 +24,7 @@ header:
# Placeholder for every '%footer%' in this configuration file
footer:
- <gray>If you believe that this is an error, contact an administrator.
# Disconnect message that is shown when someone joins but there are too many online players with their IP address
# 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>There are too many players online with your IP address.
@@ -32,21 +32,21 @@ too-many-online-per-ip:
# Translations for commands
commands:
# Message that is shown when a player tries running /sonar without permission
# Message shown when a player tries running /sonar without permission
no-permission: '%prefix%<red>You do not have permission to execute this command.'
# Message that is shown when someone uses a command incorrectly
# Message shown when someone uses a command incorrectly
incorrect-usage: '%prefix%<red>Usage: /sonar %usage%'
# Message that is shown when someone provides an invalid IP address (Invalid format)
# Message shown when someone provides an invalid IP address (Invalid format)
invalid-ip-address: '%prefix%The IP address you provided seems to be invalid.'
# Message that is shown when the console runs a command that is player-only
# Message shown when the console runs a command that is player-only
player-only: '%prefix%<red>You can only execute this command as a player.'
# Message that is shown when a player runs a command that is console-only
# Message shown when a player runs a command that is console-only
console-only: '%prefix%<red>For security reasons, you can only execute this command
through console.'
# Message that is shown when a player executes Sonar commands too quickly
# Message shown when a player executes Sonar commands too quickly
cool-down: '%prefix%<red>You can only execute this command every 0.5 seconds.'
cool-down-left: '%prefix%<red>Please wait another <bold>%time-left%s<reset><red>.'
# Message that is shown when a player does not have permission to execute a certain subcommand
# Message shown when a player does not have permission to execute a certain subcommand
subcommand-no-permission: '%prefix%<red>You do not have permission to execute this
subcommand. <gray>(%permission%)'
@@ -71,73 +71,73 @@ commands:
# Translations for '/sonar reload'
reload:
# Message that is shown when someone starts reloading Sonar
# Message shown when someone starts reloading Sonar
start: '%prefix%Reloading Sonar...'
# Message that is shown when Sonar has finished reloading
# Message shown when Sonar has finished reloading
finish: '%prefix%<green>Successfully reloaded <gray>(%taken%ms)'
# Translations for '/sonar verbose'
verbose:
# Message that is shown when a player subscribes to Sonar verbose
# Message shown when a player subscribes to Sonar verbose
subscribed: '%prefix%You are now viewing Sonar verbose.'
# Message that is shown when a player unsubscribes from Sonar verbose
# Message shown when a player unsubscribes from Sonar verbose
unsubscribed: '%prefix%You are no longer viewing Sonar verbose.'
# Translations for '/sonar notify'
notify:
# Message that is shown when a player subscribes to Sonar attack notifications
# Message shown when a player subscribes to Sonar attack notifications
subscribed: '%prefix%You are now viewing Sonar attack notifications.'
# Message that is shown when a player unsubscribes from Sonar attack notifications
# Message shown when a player unsubscribes from Sonar attack notifications
unsubscribed: '%prefix%You are no longer viewing Sonar attack notifications.'
# Translations for '/sonar blacklist'
blacklist:
# Message that is shown when someone tries clearing the blacklist but is empty
# 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 that is shown when someone clears the blacklist
# Message shown when someone clears the blacklist
cleared: '%prefix%You successfully removed a total of %removed% IP address(es)
from the blacklist.'
# Message that is shown when someone checks the size of the blacklist
# Message shown when someone checks the size of the blacklist
size: '%prefix%The blacklist currently contains %amount% IP address(es).'
# Message that is shown when someone adds an IP address to the blacklist
# Message shown when someone adds an IP address to the blacklist
added: '%prefix%Successfully added %ip% to the blacklist.'
# Message that is shown when someone adds an IP address to the blacklist that is verified
# Message shown when someone adds an IP address to the blacklist that is verified
added-warning: '%prefix%<red>Warning: <white>%ip% is currently whitelisted. Consider
removing the IP address from the list of verified players to avoid potential
issues.'
# Message that is shown when someone removes an IP address from the blacklist
# Message shown when someone removes an IP address from the blacklist
removed: '%prefix%Successfully removed %ip% from the blacklist.'
# Message that is shown when someone adds an IP address to the blacklist, but it is already blacklisted
# Message shown when someone adds an IP address to the blacklist, but it is already blacklisted
duplicate-ip: '%prefix%The IP address you provided is already blacklisted.'
# Message that is shown when someone removes an IP address from the blacklist, but it is not blacklisted
# Message shown when someone removes an IP address from the blacklist, but it is not blacklisted
ip-not-found: '%prefix%The IP address you provided is not blacklisted.'
# Translations for '/sonar verified'
verified:
# Message that is shown when someone tries clearing the list of verified players but is empty
# 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 that is shown when someone clears the list of verified players
# Message shown when someone clears the list of verified players
cleared: '%prefix%You successfully unverified a total of %removed% unique player(s).'
# Message that is shown when someone checks the size of the list of verified players
# Message shown when someone checks the size of the list of verified players
size: '%prefix%There are currently %amount% unique player(s) verified.'
# Message that is shown when someone un-verifies an IP address
# Message shown when someone un-verifies an IP address
removed: '%prefix%Successfully unverified %ip%.'
# Message that is shown when someone verifies an IP address
# Message shown when someone verifies an IP address
added: '%prefix%Successfully verified %ip%.'
# Message that is shown when someone tries to verify an IP address/UUID that are already verified
# Message shown when someone tries to verify an IP address/UUID that are already verified
already: '%prefix%The IP address and UUID you provided are already verified.'
# Message that is shown when someone un-verifies an IP address, but it is not verified
# Message shown when someone un-verifies an IP address, but it is not verified
ip-not-found: '%prefix%The IP address you provided is not verified.'
# Message that is shown when someone tries un-verifying the same IP address twice (double operation)
# Message shown when someone tries un-verifying the same IP address twice (double operation)
blocked: '%prefix%Please wait for the current operation to finish.'
# Translations for '/sonar statistics'
statistics:
# Informational message that is shown above everything when viewing the statistics
header: '%prefix%Showing %type% statistics for this session:'
# Message that is shown when a player tries viewing an unknown statistic
# Message shown when a player tries viewing an unknown statistic
unknown-type: '%prefix%<red>Unknown statistics type! Available statistics: <gray>%statistics%'
# Format of the general statistics message
general:
@@ -174,21 +174,21 @@ commands:
verification:
# Translations for all debug messages during the verification
logs:
# Message that is logged to console whenever a new player joins the server
# Message logged to console whenever a new player joins the server
connection: '%name%%ip% (%protocol%) has connected.'
# Message that is logged to console whenever a player fails verification
# Message logged to console whenever a player fails verification
failed: '%ip% (%protocol%) has failed the bot check for: %reason%'
# Message that is logged to console whenever a player is blacklisted
# Message logged to console whenever a player is blacklisted
blacklisted: '%ip% (%protocol%) was blacklisted for too many failed attempts'
# Message that is logged to console whenever a player is verified
# Message logged to console whenever a player is verified
successful: '%name% has been verified successfully (%time%s!).'
# Messages that are shown to the player when they are supposed to enter the CAPTCHA
captcha:
# Message that is shown to the player when they have to enter the answer to the captcha
# Message shown to the player when they have to enter the answer to the captcha
enter-code: '%prefix%<green>Please enter the code in chat that is displayed on
the map.'
# Message that is shown to the player when they enter the wrong answer in chat
# Message shown to the player when they enter the wrong answer in chat
incorrect: '%prefix%<red>You have entered the wrong code. Please try again.'
# Disconnect message that is shown when someone joins while the captcha hasn't been prepared yet
@@ -0,0 +1,300 @@
#
# /$$$$$$
# /$$__ $$
# | $$ \__/ /$$$$$$ /$$$$$$$ /$$$$$$ /$$$$$$
# | $$$$$$ /$$__ $$| $$__ $$ |____ $$ /$$__ $$
# \____ $$| $$ \ $$| $$ \ $$ /$$$$$$$| $$ \__/
# /$$ \ $$| $$ | $$| $$ | $$ /$$__ $$| $$
# | $$$$$$/| $$$$$$/| $$ | $$| $$$$$$$| $$
# \______/ \______/ |__/ |__/ \_______/|__/
#
# Besoin d'aide ou d'autres questions ? https://jonesdev.xyz/discord
# Code source : https://github.com/jonesdevelopment/sonar
# Droit d'auteur Jones Development, un contributeur Sonar, licence sous GPL-3.0
#
# Espace réservé pour tout '%prefix%' dans ce fichier de configuration
prefix: <b><yellow>Sonar</b> <gray>» <white>
# Espace réservé pour tout '%support-url%' dans ce fichier de configuration
support-url: https://jonesdev.xyz/discord/
# Espace réservé pour tout '%header%' dans ce fichier de configuration
header:
- <b><yellow>Sonar</b><reset>
- ''
# Espace réservé pour tout '%footer%' dans ce fichier de configuration
footer:
- <gray>Si vous pensez que c'est une erreur, veuillez contacter un administrateur.
# Message de déconnexion affiché lorsqu'un joueur se connecte mais qu'il y a trop de joueurs en ligne avec leur adresse IP
too-many-online-per-ip:
- '%header%'
- <red>Il y a trop de joueurs en ligne avec votre adresse IP.
- '%footer%'
# Traductions pour les commandes
commands:
# Message affiché lorsqu'un joueur tente d'exécuter /sonar sans permission
no-permission: "%prefix%<red>Vous n'avez pas la permission d'exécuter cette commande."
# Message affiché lorsqu'une commande est utilisée de manière incorrecte
incorrect-usage: '%prefix%<red>Utilisation : /sonar %usage%'
# Message affiché lorsqu'une adresse IP invalide est fournie (format invalide)
invalid-ip-address: "%prefix%L'adresse IP que vous avez fournie semble invalide."
# Message affiché lorsque la console exécute une commande qui est uniquement pour les joueurs
player-only: "%prefix%<red>Vous ne pouvez exécuter cette commande qu'en tant que joueur."
# Message affiché lorsqu'un joueur exécute une commande qui est uniquement pour la console
console-only: '%prefix%<red>Pour des raisons de sécurité, vous ne pouvez exécuter cette commande que via la console.'
# Message affiché lorsqu'un joueur exécute trop rapidement les commandes Sonar
cool-down: "%prefix%<red>Vous ne pouvez exécuter cette commande qu'une fois toutes les 0,5 secondes."
cool-down-left: '%prefix%<red>Veuillez attendre encore <bold>%time-left%<reset><red>.'
# Message affiché lorsqu'un joueur n'a pas la permission d'exécuter une certaine sous-commande
subcommand-no-permission: "%prefix%<red>Vous n'avez pas la permission d'exécuter cette sous-commande. <gray>(%permission%)"
# Traductions pour '/sonar'
main:
# Message informatif affiché au-dessus de tout lors de l'exécution de la commande principale
header:
- <yellow>Exécution de <b>Sonar</b> %version% sur %platform%.
- <gray><click:open_url:'https://github.com/jonesdevelopment/sonar'>(C) %copyright_year%
Jones Development et les contributeurs de Sonar</click>
- ''
- <gray>Besoin d'aide ou avez-vous des questions ?
- <white><click:open_url:'https://jonesdev.xyz/discord/'><hover:show_text:'(Cliquez
pour ouvrir Discord)'>Ouvrez un ticket sur Discord </hover></click><click:open_url:'https://github.com/jonesdevelopment/sonar/issues'><hover:show_text:'(Cliquez
pour ouvrir GitHub)'>ou ouvrez un nouveau problème sur GitHub.
- ''
# Format de la liste des sous-commandes affichée lors de l'exécution de la commande principale
subcommands: '<click:suggest_command:''/sonar %subcommand% ''><hover:show_text:''<gray>Seulement pour les joueurs : </gray>%only_players%<br><gray>Nécessite la console : </gray>%require_console%<br><gray>Permission : </gray><white>%permission%<br><gray>Alias : </gray>%aliases%''><dark_aqua> ▪ <gray>/sonar %subcommand% <white>%description%'
# Traductions pour '/sonar reload'
reload:
# Message affiché lorsque quelqu'un commence à recharger Sonar
start: '%prefix%Rechargement de Sonar...'
# Message affiché lorsque Sonar a fini de recharger
finish: '%prefix%<green>Rechargement réussi <gray>(%taken%ms)'
# Traductions pour '/sonar verbose'
verbose:
# Message affiché lorsqu'un joueur s'abonne aux détails verbeux de Sonar
subscribed: '%prefix%Vous visualisez maintenant les détails verbeux de Sonar.'
# Message affiché lorsqu'un joueur se désabonne des détails verbeux de Sonar
unsubscribed: '%prefix%Vous ne visualisez plus les détails verbeux de Sonar.'
# Traductions pour '/sonar notify'
notify:
# 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
unsubscribed: "%prefix%Vous ne visualisez plus les notifications d'attaque de Sonar."
# Traductions pour '/sonar blacklist'
blacklist:
# 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
cleared: '%prefix%Vous avez réussi à supprimer un total de %removed% adresse(s) IP de la liste noire.'
# Message affiché lorsque quelqu'un vérifie la taille de la liste noire
size: '%prefix%La liste noire contient actuellement %amount% adresse(s) IP.'
# Message affiché lorsque quelqu'un ajoute une adresse IP à la liste noire
added: '%prefix%Adresse IP %ip% ajoutée avec succès à la liste noire.'
# Message affiché lorsque quelqu'un ajoute une adresse IP à la liste noire qui est vérifiée
added-warning: "%prefix%<red>Avertissement : <white>%ip% est actuellement sur liste blanche. Considérez la suppression de l'adresse IP de la liste des joueurs vérifiés pour éviter des problèmes potentiels."
# Message affiché lorsque quelqu'un supprime une adresse IP de la liste noire
removed: '%prefix%Adresse IP %ip% supprimée avec succès de la liste noire.'
# Message affiché lorsque quelqu'un ajoute une adresse IP à la liste noire, mais qu'elle est déjà en liste noire
duplicate-ip: "%prefix%L'adresse IP que vous avez fournie est déjà sur la liste noire."
# Message affiché lorsque quelqu'un supprime une adresse IP de la liste noire, mais qu'elle n'est pas en liste noire
ip-not-found: "%prefix%L'adresse IP que vous avez fournie ne figure pas sur la liste noire."
# Traductions pour '/sonar verified'
verified:
# 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
cleared: '%prefix%Vous avez réussi à désapprouver un total de %removed% joueur(s) unique(s).'
# Message affiché lorsque quelqu'un vérifie la taille de la liste des joueurs vérifiés
size: '%prefix%Il y a actuellement %amount% joueur(s) unique(s) vérifié(s).'
# Message affiché lorsque quelqu'un désapprouve une adresse IP
removed: '%prefix%Adresse IP %ip% désapprouvée avec succès.'
# Message affiché lorsque quelqu'un vérifie une adresse IP
added: '%prefix%Adresse IP %ip% vérifiée avec succès.'
# Message affiché lorsque quelqu'un tente de vérifier une adresse IP/UUID qui est déjà vérifiée
already: "%prefix%L'adresse IP et l'UUID que vous avez fournis sont déjà vérifiés."
# Message affiché lorsque quelqu'un désapprouve une adresse IP, mais qu'elle n'est pas vérifiée
ip-not-found: "%prefix%L'adresse IP que vous avez fournie n'est pas vérifiée."
# Message affiché lorsque quelqu'un tente de désapprouver la même adresse IP deux fois (double opération)
blocked: "%prefix%Veuillez attendre la fin de l'opération en cours."
# Traductions pour '/sonar statistics'
statistics:
# Message informatif affiché au-dessus de tout lors de la visualisation des statistiques
header: '%prefix%Affichage des statistiques %type% pour cette session :'
# Message affiché lorsqu'un joueur tente de visualiser une statistique inconnue
unknown-type: '%prefix%<red>Type de statistiques inconnu ! Statistiques disponibles : <gray>%statistics%'
# Format du message de statistiques général
general:
- ' <dark_aqua>▪ <gray>Adresses IP vérifiées : <white>%verified%'
- ' <dark_aqua>▪ <gray>En train de vérifier les adresses IP : <white>%verifying%'
- ' <dark_aqua>▪ <gray>Adresses IP en liste noire : <white>%blacklisted%'
- ' <dark_aqua>▪ <gray>Connexions en attente actuelles : <white>%queued%'
- ' <dark_aqua>▪ <gray>Total des connexions non uniques : <white>%total_joins%'
- ' <dark_aqua>▪ <gray>Total des tentatives de vérification : <white>%total_attempts%'
- ' <dark_aqua>▪ <gray>Total des vérifications échouées : <white>%total_failed%'
- ' <dark_aqua>▪ <gray>Temps de fonctionnement du serveur : <white>%uptime%'
# Format du message de statistiques CPU
cpu:
- ' <dark_aqua>▪ <gray>Utilisation actuelle du CPU du processus : <white>%process_cpu%%'
- ' <dark_aqua>▪ <gray>Utilisation actuelle du CPU du système : <white>%system_cpu%%'
- ' <dark_aqua>▪ <gray>Utilisation du CPU par cœur du processus : <white>%average_process_cpu%%'
- ' <dark_aqua>▪ <gray>Utilisation du CPU par cœur du système : <white>%average_system_cpu%%'
- ' <dark_aqua>▪ <gray>Charge système générale : <white>%load_average%%'
- ' <dark_aqua>▪ <gray>Nombre total de processeurs virtuels : <white>%virtual_cores%'
# Format du message de statistiques de mémoire
memory:
- ' <dark_aqua>▪ <gray>Mémoire libre totale : <white>%free_memory%'
- ' <dark_aqua>▪ <gray>Mémoire utilisée totale : <white>%used_memory%'
- ' <dark_aqua>▪ <gray>Mémoire maximale totale : <white>%max_memory%'
- ' <dark_aqua>▪ <gray>Mémoire allouée totale : <white>%total_memory%'
# Format du message de statistiques réseau
network:
- ' <dark_aqua>▪ <gray>Bande passante entrante actuelle utilisée : <white>%incoming%'
- ' <dark_aqua>▪ <gray>Bande passante sortante actuelle utilisée : <white>%outgoing%'
- ' <dark_aqua>▪ <gray>Bande passante entrante totale utilisée : <white>%ttl_incoming%'
- ' <dark_aqua>▪ <gray>Bande passante sortante totale utilisée : <white>%ttl_outgoing%'
# Traductions pour tous les messages pendant le processus de vérification
verification:
# Traductions pour tous les messages de débogage pendant la vérification
logs:
# Message enregistré dans la console chaque fois qu'un nouveau joueur rejoint le serveur
connection: "%name%%ip% (%protocol%) s'est connecté."
# Message enregistré dans la console chaque fois qu'un joueur échoue à la vérification
failed: '%ip% (%protocol%) a échoué au test du bot pour : %reason%'
# Message enregistré dans la console chaque fois qu'un joueur est sur liste noire
blacklisted: '%ip% (%protocol%) a été mis sur liste noire pour trop de tentatives échouées'
# Message enregistré dans la console chaque fois qu'un joueur est vérifié
successful: '%name% a été vérifié avec succès (%time%s !).'
# Messages affichés au joueur lorsqu'il doit entrer le CAPTCHA
captcha:
# Message affiché au joueur lorsqu'il doit entrer la réponse au CAPTCHA
enter-code: '%prefix%<green>Veuillez entrer le code affiché sur la carte.'
# Message affiché au joueur lorsqu'il entre la mauvaise réponse dans le chat
incorrect: '%prefix%<red>Vous avez entré le mauvais code. Veuillez réessayer.'
# Message de déconnexion affiché lorsque quelqu'un rejoint alors que le CAPTCHA n'a pas été préparé
currently-preparing:
- '%header%'
- <yellow>Vos données anti-bot n'ont pas encore été préparées.
- <gray>Veuillez patienter quelques secondes avant d'essayer de vous vérifier à nouveau.
- '%footer%'
# Message de déconnexion affiché lorsque quelqu'un se reconnecte trop rapidement pendant la vérification
too-fast-reconnect:
- '%header%'
- <gold>Vous avez rejoint trop rapidement, réessayez plus tard.
- <gray>Veuillez patienter quelques secondes avant d'essayer de vous vérifier à nouveau.
- '%footer%'
# Message de déconnexion affiché lorsque quelqu'un rejoint mais est déjà en vérification
already-verifying:
- '%header%'
- <red>Votre adresse IP est actuellement en cours de vérification.
- <red>Veuillez patienter quelques secondes avant d'essayer de vous vérifier à nouveau.
- '%footer%'
# Message de déconnexion affiché lorsque quelqu'un rejoint mais est déjà en attente de vérification
already-queued:
- '%header%'
- <red>Votre adresse IP est actuellement en attente de vérification.
- <red>Veuillez patienter quelques minutes avant d'essayer de vous vérifier à nouveau.
- '%footer%'
# Message de déconnexion affiché lorsque quelqu'un rejoint mais est temporairement mis sur liste noire
blacklisted:
- '%header%'
- <red>Vous êtes actuellement interdit d'entrer sur le serveur.
- <red>Veuillez patienter quelques minutes pour pouvoir rejoindre le serveur à nouveau.
- <gold>Erreur ? <gray>%support-url%
- '%footer%'
# Message de déconnexion affiché lorsque quelqu'un rejoint avec un nom d'utilisateur non valide
invalid-username:
- '%header%'
- <red>Votre nom d'utilisateur contient des caractères non valides.
- '%footer%'
# Message de déconnexion affiché lorsque quelqu'un rejoint avec une version sur liste noire
blacklisted-protocol:
- '%header%'
- <red>Vous utilisez une version non autorisée sur notre serveur.
- <gold>Besoin d'aide pour vous connecter ? <gray>%support-url%
- '%footer%'
# Message de déconnexion affiché lorsque quelqu'un réussit la vérification
success:
- '%header%'
- <green>Vous avez réussi la vérification.
- <white>Vous pouvez maintenant jouer sur le serveur lorsque vous vous reconnectez.
# Message de déconnexion affiché lorsque quelqu'un échoue à la vérification
failed:
- '%header%'
- <red>Vous avez échoué à la vérification du bot.
- <gray>Veuillez patienter quelques secondes avant d'essayer de vous vérifier à nouveau.
- <gold>Besoin d'aide ? <gray>%support-url%
- '%footer%'
# Translations for Sonar's actionbar verbose messages
verbose:
layout:
# Mise en page pour le verbeux de la barre d'action de Sonar
# Espacements réservés :
# - '%queued%' Nombre de connexions en attente
# - '%verifying%' Nombre de connexions en cours de vérification
# - '%blacklisted%' Nombre d'adresses IP sur liste noire
# - '%total-joins%' Nombre total de connexions tentées
# - '%verify-total%' Nombre total de tentatives de vérification
# - '%verify-success%' Nombre d'adresses IP vérifiées
# - '%verify-failed%' Nombre de vérifications échouées
# - '%logins-per-second%' Nombre de connexions par seconde
# - '%connections-per-second%' Nombre de connexions par seconde
# - '%attack-duration%' Durée de l'attaque actuelle
# - '%incoming-traffic%' Utilisation de la bande passante entrante par seconde
# - '%outgoing-traffic%' Utilisation de la bande passante sortante par seconde
# - '%incoming-traffic-ttl%' Utilisation totale de la bande passante entrante
# - '%outgoing-traffic-ttl%' Utilisation totale de la bande passante sortante
# - '%used-memory%' Quantité de mémoire utilisée par le processus
# - '%total-memory%' Quantité de mémoire totale du processus
# - '%max-memory%' Quantité de mémoire maximale du processus
# - '%free-memory%' Quantité de mémoire libre du processus
# - '%animation%' Symbole animé personnalisable
# Traductions pour la sortie verbeuse normale de Sonar
normal: '%prefix%<gray>CPS <white>%connections-per-second% <dark_aqua>╺ <gray>Logins/s
<white>%logins-per-second% <dark_aqua>╺ <gray>Vérification <white>%verifying% <dark_aqua>|
<green>⬆ <white>%outgoing-traffic%/s <red>⬇ <white>%incoming-traffic%/s <green><bold>%animation%<reset>'
# Traductions pour la sortie verbeuse lors d'une attaque
attack: '%prefix%<gray>CPS <white>%connections-per-second% <dark_aqua>╺ <gray>Logins/s
<white>%logins-per-second% <dark_aqua>╺ <gray>Queue <white>%queued% <dark_aqua>╺
<gray>Vérification <white>%verifying% <dark_aqua>╺ <gray>Durée <white>%attack-duration%
<dark_aqua>| <green>⬆ <white>%outgoing-traffic%/s <red>⬇ <white>%incoming-traffic%/s <green><bold>%animation%<reset>'
# Animation pour la sortie verbeuse
# Alternatives:
# - ▙, ▛, ▜, ▟
# - ⬈, ⬊, ⬋, ⬉
animation:
- ◜
- ◝
- ◞
- ◟
# Traductions pour les messages affichés en cas d'attaque
notifications:
# Mise en page du titre de la notification d'attaque de Sonar
title: <yellow><b>Sonar<reset>
# Mise en page du sous-titre de la notification d'attaque de Sonar
subtitle: <gray>A bot attack has been detected
# Mise en page de la notification d'attaque de Sonar dans le chat
chat:
- ''
- <yellow><b>Sonar<reset>
- ''
- <gray>Une attaque de bot a été détectée.
- ' <dark_aqua>▪ <gray>Connexions par seconde: <white>%logins-per-second%'
- ' <dark_aqua>▪ <gray>Vérification des joueurs: <white>%verifying%'
- ' <dark_aqua>▪ <gray>Joueurs en file d''attente: <white>%queued%'
- ''
- <gray>View more information using <white><click:run_command:'/sonar verbose'><hover:show_text:'(Click
to run)'>/sonar verbose</hover></click><gray> or <white><click:run_command:'/sonar
stats'><hover:show_text:'(Click to run)'>/sonar stats</hover></click><gray>.
- ''
@@ -294,7 +294,7 @@ notifications:
# Lay-out voor de titel van de aanval meldingen van Sonar
title: <yellow><b>Sonar<reset>
# Lay-out voor de ondertitel van Sonar's aanval meldingen
subtitle: <gray>A bot attack has been detected
subtitle: <gray>Er is een bot-aanval gedetecteerd
# Lay-out voor de aanval meldingen van Sonar in de chat
chat:
- ''
@@ -0,0 +1,60 @@
#
# /$$$$$$
# /$$__ $$
# | $$ \__/ /$$$$$$ /$$$$$$$ /$$$$$$ /$$$$$$
# | $$$$$$ /$$__ $$| $$__ $$ |____ $$ /$$__ $$
# \____ $$| $$ \ $$| $$ \ $$ /$$$$$$$| $$ \__/
# /$$ \ $$| $$ | $$| $$ | $$ /$$__ $$| $$
# | $$$$$$/| $$$$$$/| $$ | $$| $$$$$$$| $$
# \______/ \______/ |__/ |__/ \_______/|__/
#
# Besoin d'aide ou d'autres questions ? https://jonesdev.xyz/discord
# Code source : https://github.com/jonesdevelopment/sonar
# Droit d'auteur Jones Development, un contributeur Sonar, licence sous GPL-3.0
#
# Les notifications d'attaque bot peuvent être envoyé à discord via un webhook
webhook:
# Lien du webhook discord (Mettez '' pour désactiver les webhooks)
url: ''
# Nom d'utilisateur du webhook
username: Sonar
# Lien vers l'avatar du webhook (Mettez '' pour désactiver)
avatar-url: ''
# Message à envoyer (Mettez '' pour désactiver)
# Vous pouvez mentionner des personnes en utilisant <@idUtilisateur>
# Si vous voulez mentionner un rôle vous devriez utiliser <@&idRole>
content: ''
# Embed qui sera envoyé quand il y a une attaque
embed:
# Petit footer de l'embed
footer:
# Message du footer
text: © Jones Development et Contributeurs Sonar
# Lien de l'icône du footer
icon-url: ''
# Titre du webhook discord
title: '✅ Attaque mitigé'
# Lien clickable du titre
title-url: ''
# Description (message) de l'embed
description:
- 'L''attaque sur votre serveur a été mitigé'
- ''
- 'Démarré à: <t:%start-timestamp%:T>'
- 'Fini à: <t:%end-timestamp%:T>'
- 'Durée: %duration%'
- ''
- 'Pique du processeur: %peak-cpu%%'
- 'Pique de la mémoire ram: %peak-memory%'
- 'Pique du nombre de bots par secondes: %peak-bps%'
- ''
- "IP Blacklisté durant l'attaque: %total-blacklisted%"
- "Vérification échoué durant l'attaque: %total-failed%"
- "Vérification réussi durant l'attaque: %total-success%"
# Code couleur RGB pour l'embed
# Sélectionner la couleur: https://www.rapidtables.com/web/color/RGB_Color.html
color:
red: 0
green: 255
blue: 0
@@ -40,9 +40,9 @@ public final class SonarVelocity extends SonarBootstrap<SonarVelocityPlugin> {
public static SonarVelocity INSTANCE;
public SonarVelocity(final @NotNull SonarVelocityPlugin plugin) {
super(plugin, new VelocityLibraryManager<>(
plugin, plugin.getLogger(), plugin.getDataDirectory(), plugin.getServer().getPluginManager()),
plugin.getDataDirectory().toFile(), SonarPlatform.VELOCITY);
super(plugin, SonarPlatform.VELOCITY, plugin.getDataDirectory().toFile(),
new VelocityLibraryManager<>(plugin, plugin.getLogger(),
plugin.getDataDirectory(), plugin.getServer().getPluginManager()));
INSTANCE = this;
}
@@ -115,7 +115,9 @@ public final class SonarVelocity extends SonarBootstrap<SonarVelocityPlugin> {
@Override
public void disable() {
// Make sure to properly shutdown bStats metrics
metrics.shutdown();
if (metrics != null) {
// Make sure to properly shutdown bStats metrics
metrics.shutdown();
}
}
}
@@ -22,19 +22,21 @@ import io.netty.channel.ChannelInitializer;
import lombok.RequiredArgsConstructor;
import xyz.jonesdev.sonar.api.ReflectiveOperationException;
import java.lang.reflect.Method;
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 Method INIT_CHANNEL_METHOD;
private static final MethodHandle INIT_CHANNEL_METHOD;
static {
try {
INIT_CHANNEL_METHOD = ChannelInitializer.class.getDeclaredMethod("initChannel", Channel.class);
INIT_CHANNEL_METHOD.setAccessible(true);
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);
}
@@ -46,7 +48,7 @@ public final class FallbackChannelInitializer extends ChannelInitializer<Channel
protected void initChannel(final Channel channel) throws Exception {
// Invoke the original method
try {
INIT_CHANNEL_METHOD.invoke(originalChannelInitializer, channel);
INIT_CHANNEL_METHOD.invokeExact(originalChannelInitializer, channel);
} catch (Throwable throwable) {
throw new ReflectiveOperationException(throwable);
}