mirror of
https://github.com/jonesdevelopment/sonar.git
synced 2026-11-06 09:42:32 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fc9c1026b1 | ||
|
|
aae49aeb63 | ||
|
|
f7a6f04792 | ||
|
|
e36ba9840c | ||
|
|
40bceb71f1 | ||
|
|
2d3bf91444 | ||
|
|
45ab258a6f | ||
|
|
600277660c | ||
|
|
6918afae52 | ||
|
|
07cfc4ad1c | ||
|
|
65eb9a503f | ||
|
|
f5d7cc1511 | ||
|
|
2cb0a48657 | ||
|
|
646f296039 | ||
|
|
a698c26d39 | ||
|
|
25136d6332 | ||
|
|
ee4b1ffef4 | ||
|
|
fe145836fe | ||
|
|
47100f4071 | ||
|
|
57311996c8 | ||
|
|
7ad8e48431 | ||
|
|
154d999b88 | ||
|
|
bde637c9c5 | ||
|
|
cb1c62f478 | ||
|
|
3727742419 | ||
|
|
f79bb38740 | ||
|
|
7d60ba85e7 | ||
|
|
cec7fa07c2 | ||
|
|
2be2380e3f | ||
|
|
ae99ade03a |
No files matched your search
+1
-1
@@ -7,7 +7,7 @@ indent_size = 2
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[{*.java,*.kt}]
|
||||
[*.java]
|
||||
ij_java_wrap_long_lines = true
|
||||
|
||||
[{*.md,*.yml}]
|
||||
|
||||
@@ -9,9 +9,9 @@ name: Sonar CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main", "dev" ]
|
||||
branches: [ "main" ]
|
||||
pull_request:
|
||||
branches: [ "main", "dev" ]
|
||||
branches: [ "main" ]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -22,12 +22,41 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'temurin'
|
||||
|
||||
- name: Build with Gradle
|
||||
uses: gradle/gradle-build-action@bd5760595778326ba7f1441bcf7e88b49de61a25 # v2.6.0
|
||||
uses: gradle/gradle-build-action@v3
|
||||
with:
|
||||
arguments: build-sonar
|
||||
|
||||
- name: Upload Bukkit Artifact
|
||||
uses: actions/upload-artifact@v3.1.3
|
||||
with:
|
||||
# Artifact name
|
||||
name: Sonar
|
||||
# A file, directory or wildcard pattern that describes what to upload
|
||||
path: bukkit/build/libs/Sonar-Bukkit.jar
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload BungeeCord Artifact
|
||||
uses: actions/upload-artifact@v3.1.3
|
||||
with:
|
||||
# Artifact name
|
||||
name: Sonar
|
||||
# A file, directory or wildcard pattern that describes what to upload
|
||||
path: bungeecord/build/libs/Sonar-Bungee.jar
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload Velocity Artifact
|
||||
uses: actions/upload-artifact@v3.1.3
|
||||
with:
|
||||
# Artifact name
|
||||
name: Sonar
|
||||
# A file, directory or wildcard pattern that describes what to upload
|
||||
path: velocity/build/libs/Sonar-Velocity.jar
|
||||
if-no-files-found: error
|
||||
@@ -9,5 +9,11 @@ dependencies {
|
||||
compileOnly(rootProject.libs.annotations)
|
||||
}
|
||||
|
||||
tasks {
|
||||
shadowJar {
|
||||
archiveFileName = "sonar-api-${rootProject.version}.jar"
|
||||
}
|
||||
}
|
||||
|
||||
java.sourceCompatibility = JavaVersion.VERSION_11
|
||||
java.targetCompatibility = JavaVersion.VERSION_11
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+10
-2
@@ -26,6 +26,7 @@ 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.update.UpdateChecker;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -66,11 +67,18 @@ public interface SonarCommand {
|
||||
// Invoke subcommand
|
||||
command.invoke(source, args);
|
||||
}, () -> {
|
||||
final UpdateChecker.CheckResult checkResult = UpdateChecker.getLastCheckResult();
|
||||
Component version = Component.text(Sonar.get().getVersion().getFormatted());
|
||||
if (checkResult.getConfigKey() != null) {
|
||||
version = version.append(MiniMessage.miniMessage().deserialize(
|
||||
Sonar.get().getConfig().getMessagesConfig().getString("commands.main." + checkResult.getConfigKey())));
|
||||
}
|
||||
|
||||
// Print standard help message
|
||||
source.sendMessage(MiniMessage.miniMessage().deserialize(
|
||||
String.join("<newline>",
|
||||
Sonar.get().getConfig().getMessagesConfig().getStringList("commands.main.header")),
|
||||
Placeholder.unparsed("version", Sonar.get().getVersion().getFormatted()),
|
||||
Placeholder.component("version", version),
|
||||
Placeholder.unparsed("platform", Sonar.get().getPlatform().getDisplayName()),
|
||||
Placeholder.unparsed("copyright-year", String.valueOf(Calendar.getInstance().get(Calendar.YEAR)))));
|
||||
|
||||
@@ -94,7 +102,7 @@ public interface SonarCommand {
|
||||
});
|
||||
}
|
||||
|
||||
static void prepareCachedMessages() {
|
||||
static void prepareCachedTabSuggestions() {
|
||||
// Don't re-cache tab suggestions
|
||||
if (!TAB_SUGGESTIONS.isEmpty()) return;
|
||||
// Cache tab suggestions
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+7
-6
@@ -183,10 +183,11 @@ public final class SonarConfiguration {
|
||||
|
||||
final String backgroundPath = generalConfig.getString("verification.checks.map-captcha.background");
|
||||
if (!backgroundPath.isEmpty()) {
|
||||
try (final InputStream inputStream = new FileInputStream(backgroundPath)) {
|
||||
verification.map.backgroundImage = inputStream;
|
||||
} catch (IOException exception) {
|
||||
Sonar.get().getLogger().error("Could not find background image", exception);
|
||||
final File backgroundFile = new File(pluginFolder, backgroundPath);
|
||||
if (backgroundFile.exists()) {
|
||||
verification.map.backgroundImage = backgroundFile;
|
||||
} else {
|
||||
Sonar.get().getLogger().error("Could not find background image {}", backgroundFile.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,7 +245,7 @@ public final class SonarConfiguration {
|
||||
noPermission = MiniMessage.miniMessage().deserialize(messagesConfig.getString("commands.no-permission"),
|
||||
Placeholder.component("prefix", prefix));
|
||||
|
||||
SonarCommand.prepareCachedMessages();
|
||||
SonarCommand.prepareCachedTabSuggestions();
|
||||
|
||||
supportUrl = messagesConfig.getString("support-url");
|
||||
header = MiniMessage.miniMessage().deserialize(
|
||||
@@ -366,7 +367,7 @@ public final class SonarConfiguration {
|
||||
private int maxDuration;
|
||||
private int maxTries;
|
||||
private String alphabet;
|
||||
private InputStream backgroundImage;
|
||||
private File backgroundImage;
|
||||
}
|
||||
|
||||
@Getter
|
||||
-1
@@ -99,7 +99,6 @@ public final class VerifiedPlayerController {
|
||||
try {
|
||||
TableUtils.createTableIfNotExists(connectionSource, VerifiedPlayer.class);
|
||||
} catch (SQLException ignored) {
|
||||
ignored.printStackTrace();
|
||||
/*
|
||||
* This is caused by a duplicate index;
|
||||
* I know this isn't the best method of handling it,
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+4
-4
@@ -17,13 +17,13 @@
|
||||
|
||||
package xyz.jonesdev.sonar.api.event;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface SonarEventListener {
|
||||
|
||||
/**
|
||||
* Handles the publishing of an event
|
||||
*
|
||||
* @param event [Cancellable] Sonar event
|
||||
* Handles the publishing of an event through Sonar's API
|
||||
*/
|
||||
void handle(final SonarEvent event);
|
||||
void handle(final @NotNull SonarEvent event);
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 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.api.event.impl;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.ToString;
|
||||
import xyz.jonesdev.sonar.api.event.SonarEvent;
|
||||
import xyz.jonesdev.sonar.api.timer.SystemTimer;
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
@RequiredArgsConstructor
|
||||
public final class CaptchaGenerationEndEvent implements SonarEvent {
|
||||
private final SystemTimer timer;
|
||||
private final int amountGenerated;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 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.api.event.impl;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import xyz.jonesdev.sonar.api.event.SonarEvent;
|
||||
import xyz.jonesdev.sonar.api.fallback.captcha.CaptchaGenerator;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
public final class CaptchaGenerationStartEvent implements SonarEvent {
|
||||
private CaptchaGenerator captchaGenerator;
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+2
-9
@@ -22,7 +22,6 @@ import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import xyz.jonesdev.sonar.api.Sonar;
|
||||
import xyz.jonesdev.sonar.api.config.SonarConfiguration;
|
||||
import xyz.jonesdev.sonar.api.fallback.captcha.CaptchaGenerator;
|
||||
@@ -37,21 +36,15 @@ import java.util.concurrent.ConcurrentMap;
|
||||
public final class Fallback {
|
||||
public static final Fallback INSTANCE = new Fallback();
|
||||
|
||||
// Map of all players connected to the server in general
|
||||
private final ConcurrentMap<InetAddress, Integer> online = new ConcurrentHashMap<>(128);
|
||||
// Map of all connected IP addresses (used for fast checking)
|
||||
// TODO: Is there a way to improve this?
|
||||
// (E.g. no map needed without concurrency issues)
|
||||
private final ConcurrentMap<InetAddress, Byte> connected = new ConcurrentHashMap<>(256);
|
||||
// Cache of all blacklisted IP addresses to ensure each entry can expire after the given time
|
||||
private final ConcurrentMap<InetAddress, Boolean> connected = new ConcurrentHashMap<>(256);
|
||||
private final FallbackLoginQueue queue = new FallbackLoginQueue();
|
||||
@Setter
|
||||
private Cache<String, Integer> blacklist;
|
||||
@Setter
|
||||
private long blacklistTime;
|
||||
@Setter
|
||||
private CaptchaGenerator captchaGenerator;
|
||||
|
||||
private final @NotNull FallbackQueue queue = new FallbackQueue();
|
||||
@Setter
|
||||
private Ratelimiter<InetAddress> ratelimiter;
|
||||
|
||||
+12
-17
@@ -23,8 +23,6 @@ import lombok.RequiredArgsConstructor;
|
||||
import xyz.jonesdev.sonar.api.Sonar;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
@@ -32,27 +30,24 @@ import java.util.concurrent.Executors;
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor(access = AccessLevel.PROTECTED)
|
||||
public final class FallbackQueue {
|
||||
public final class FallbackLoginQueue {
|
||||
// Fixed thread pool executor for all new verifications
|
||||
private static final int THREAD_POOL_SIZE = Math.min(0x7fff, Runtime.getRuntime().availableProcessors() * 2);
|
||||
private static final ExecutorService QUEUE_EXECUTOR = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
|
||||
|
||||
private final ConcurrentMap<InetAddress, Runnable> players = new ConcurrentHashMap<>(
|
||||
128, 0.75f, Runtime.getRuntime().availableProcessors());
|
||||
private final ConcurrentMap<InetAddress, Runnable> players = new ConcurrentHashMap<>(512);
|
||||
|
||||
public void poll() {
|
||||
final int maxQueuePolls = Sonar.get().getConfig().getQueue().getMaxQueuePolls();
|
||||
int index = 0;
|
||||
|
||||
// Iterate through the map and process up to maxQueuePolls entries
|
||||
final int maxQueuePolls = Math.min(players.size(), Sonar.get().getConfig().getQueue().getMaxQueuePolls());
|
||||
// No need to initiate an executor service task if nobody is currently queued
|
||||
if (maxQueuePolls <= 0) return;
|
||||
// We need to be cautious here since we don't want any concurrency issues
|
||||
final Iterator<Map.Entry<InetAddress, Runnable>> iterator = players.entrySet().iterator();
|
||||
while (iterator.hasNext() && index++ < maxQueuePolls) {
|
||||
// Run the cached runnable
|
||||
final Map.Entry<InetAddress, Runnable> entry = iterator.next();
|
||||
QUEUE_EXECUTOR.execute(entry.getValue());
|
||||
// Remove runnable from the map
|
||||
iterator.remove();
|
||||
}
|
||||
QUEUE_EXECUTOR.execute(() -> {
|
||||
final var iterator = players.entrySet().iterator();
|
||||
for (int index = 0; index < maxQueuePolls && iterator.hasNext(); index++) {
|
||||
iterator.next().getValue().run();
|
||||
iterator.remove();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
+7
-1
@@ -17,9 +17,15 @@
|
||||
|
||||
package xyz.jonesdev.sonar.api.fallback.captcha;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface CaptchaGenerator {
|
||||
BufferedImage createImage(final char[] answer);
|
||||
|
||||
/**
|
||||
* Generates a {@link java.awt.image.BufferedImage} that shows the answer to the CAPTCHA
|
||||
*/
|
||||
@NotNull BufferedImage createImage(final char @NotNull [] answer);
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+4
-4
@@ -63,10 +63,10 @@ public final class ActionBarNotificationHandler extends NotificationHandler {
|
||||
Placeholder.unparsed("verify-total", DECIMAL_FORMAT.format(Sonar.get().getStatistics().getTotalAttemptedVerifications())),
|
||||
Placeholder.unparsed("verify-success", DECIMAL_FORMAT.format(Sonar.get().getStatistics().getTotalSuccessfulVerifications())),
|
||||
Placeholder.unparsed("verify-failed", DECIMAL_FORMAT.format(Sonar.get().getStatistics().getTotalFailedVerifications())),
|
||||
Placeholder.unparsed("incoming-traffic", Sonar.get().getStatistics().getCurrentIncomingBandwidthFormatted()),
|
||||
Placeholder.unparsed("outgoing-traffic", Sonar.get().getStatistics().getCurrentOutgoingBandwidthFormatted()),
|
||||
Placeholder.unparsed("incoming-traffic-ttl", Sonar.get().getStatistics().getTotalIncomingBandwidthFormatted()),
|
||||
Placeholder.unparsed("outgoing-traffic-ttl", Sonar.get().getStatistics().getTotalOutgoingBandwidthFormatted()),
|
||||
Placeholder.unparsed("incoming-traffic", Sonar.get().getStatistics().getPerSecondIncomingBandwidthFormatted()),
|
||||
Placeholder.unparsed("outgoing-traffic", Sonar.get().getStatistics().getPerSecondOutgoingBandwidthFormatted()),
|
||||
Placeholder.unparsed("incoming-traffic-ttl", formatMemory(Sonar.get().getStatistics().getTotalIncomingBandwidth())),
|
||||
Placeholder.unparsed("outgoing-traffic-ttl", formatMemory(Sonar.get().getStatistics().getTotalOutgoingBandwidth())),
|
||||
Placeholder.unparsed("used-memory", formatMemory(getUsedMemory())),
|
||||
Placeholder.unparsed("free-memory", formatMemory(getFreeMemory())),
|
||||
Placeholder.unparsed("total-memory", formatMemory(getTotalMemory())),
|
||||
+4
-4
@@ -63,10 +63,10 @@ public final class ChatNotificationHandler extends NotificationHandler {
|
||||
Placeholder.unparsed("verify-total", DECIMAL_FORMAT.format(Sonar.get().getStatistics().getTotalAttemptedVerifications())),
|
||||
Placeholder.unparsed("verify-success", DECIMAL_FORMAT.format(Sonar.get().getStatistics().getTotalSuccessfulVerifications())),
|
||||
Placeholder.unparsed("verify-failed", DECIMAL_FORMAT.format(Sonar.get().getStatistics().getTotalFailedVerifications())),
|
||||
Placeholder.unparsed("incoming-traffic", Sonar.get().getStatistics().getCurrentIncomingBandwidthFormatted()),
|
||||
Placeholder.unparsed("outgoing-traffic", Sonar.get().getStatistics().getCurrentOutgoingBandwidthFormatted()),
|
||||
Placeholder.unparsed("incoming-traffic-ttl", Sonar.get().getStatistics().getTotalIncomingBandwidthFormatted()),
|
||||
Placeholder.unparsed("outgoing-traffic-ttl", Sonar.get().getStatistics().getTotalOutgoingBandwidthFormatted()),
|
||||
Placeholder.unparsed("incoming-traffic", Sonar.get().getStatistics().getPerSecondIncomingBandwidthFormatted()),
|
||||
Placeholder.unparsed("outgoing-traffic", Sonar.get().getStatistics().getPerSecondOutgoingBandwidthFormatted()),
|
||||
Placeholder.unparsed("incoming-traffic-ttl", formatMemory(Sonar.get().getStatistics().getTotalIncomingBandwidth())),
|
||||
Placeholder.unparsed("outgoing-traffic-ttl", formatMemory(Sonar.get().getStatistics().getTotalOutgoingBandwidth())),
|
||||
Placeholder.unparsed("used-memory", formatMemory(getUsedMemory())),
|
||||
Placeholder.unparsed("free-memory", formatMemory(getFreeMemory())),
|
||||
Placeholder.unparsed("total-memory", formatMemory(getTotalMemory())),
|
||||
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 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.api.statistics;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public interface SonarStatistics {
|
||||
long getConnectionsPerSecond();
|
||||
|
||||
long getLoginsPerSecond();
|
||||
|
||||
long getCurrentIncomingBandwidth();
|
||||
|
||||
long getCurrentOutgoingBandwidth();
|
||||
|
||||
long getTotalIncomingBandwidth();
|
||||
|
||||
long getTotalOutgoingBandwidth();
|
||||
|
||||
String getPerSecondIncomingBandwidthFormatted();
|
||||
|
||||
String getPerSecondOutgoingBandwidthFormatted();
|
||||
|
||||
int getTotalPlayersJoined();
|
||||
|
||||
int getTotalPlayersVerified();
|
||||
|
||||
int getTotalSuccessfulVerifications();
|
||||
|
||||
int getTotalFailedVerifications();
|
||||
|
||||
long getCurrentAttemptedVerifications();
|
||||
|
||||
int getTotalAttemptedVerifications();
|
||||
|
||||
long getCurrentBlacklistSize();
|
||||
|
||||
long getTotalBlacklistSize();
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
+23
-3
@@ -15,10 +15,12 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package xyz.jonesdev.sonar.common.update;
|
||||
package xyz.jonesdev.sonar.api.update;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import xyz.jonesdev.sonar.api.Sonar;
|
||||
@@ -35,6 +37,8 @@ import java.util.concurrent.Executors;
|
||||
@UtilityClass
|
||||
public class UpdateChecker {
|
||||
private final ExecutorService ASYNC_EXECUTOR = Executors.newSingleThreadExecutor();
|
||||
@Getter
|
||||
private CheckResult lastCheckResult = CheckResult.UNRESOLVED;
|
||||
|
||||
public void checkForUpdates() {
|
||||
ASYNC_EXECUTOR.execute(() -> {
|
||||
@@ -49,15 +53,19 @@ public class UpdateChecker {
|
||||
if (convertedCurrentVersion < convertedLatestVersion) {
|
||||
Sonar.get().getLogger().warn("A new version of Sonar is available: {}", latestStableRelease);
|
||||
Sonar.get().getLogger().warn("Please make sure to update to the latest version to ensure stability and security:");
|
||||
Sonar.get().getLogger().warn("https://github.com/jonesdevelopment/sonar/releases/tag/{}", latestStableRelease);
|
||||
Sonar.get().getLogger().warn("https://github.com/jonesdevelopment/sonar/releases/latest");
|
||||
lastCheckResult = CheckResult.OUTDATED_VERSION;
|
||||
} else if (convertedCurrentVersion > convertedLatestVersion || !Sonar.get().getVersion().getGitBranch().equals("main")) {
|
||||
Sonar.get().getLogger().warn("You are currently using an unreleased version of Sonar!");
|
||||
Sonar.get().getLogger().warn("The contributors of Sonar are not responsible for any damage done by using an unstable version");
|
||||
} else {
|
||||
lastCheckResult = CheckResult.UNSTABLE_VERSION;
|
||||
} else if (lastCheckResult != CheckResult.LATEST_VERSION) {
|
||||
Sonar.get().getLogger().info("You are currently using the latest stable release of Sonar!");
|
||||
lastCheckResult = CheckResult.LATEST_VERSION;
|
||||
}
|
||||
} catch (Throwable throwable) {
|
||||
Sonar.get().getLogger().warn("Unable to retrieve version information: {}", throwable);
|
||||
lastCheckResult = CheckResult.API_ERROR;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -99,4 +107,16 @@ public class UpdateChecker {
|
||||
final int patch = Integer.parseInt(convertedParts[2]);
|
||||
return convertedMajor + convertedMinor + patch; // sum the converted version parts
|
||||
}
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum CheckResult {
|
||||
API_ERROR("api-error"),
|
||||
OUTDATED_VERSION("outdated-version"),
|
||||
UNSTABLE_VERSION("unstable-version"),
|
||||
LATEST_VERSION(null),
|
||||
UNRESOLVED(null);
|
||||
|
||||
private final String configKey;
|
||||
}
|
||||
}
|
||||
File renamed without changes.
+1
-1
@@ -86,7 +86,7 @@ allprojects {
|
||||
tasks {
|
||||
// This is a small wrapper tasks to simplify the building process
|
||||
register("build-sonar") {
|
||||
val subprojects = listOf("api", "common", "bukkit", "bungee", "velocity")
|
||||
val subprojects = listOf("api", "captcha", "common", "bukkit", "bungeecord", "velocity")
|
||||
val buildTasks = subprojects.flatMap { listOf("$it:clean", "$it:shadowJar") }
|
||||
dependsOn(buildTasks)
|
||||
}
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -26,6 +26,8 @@ dependencies {
|
||||
tasks {
|
||||
shadowJar {
|
||||
relocate("net.kyori", "xyz.jonesdev.sonar.libs.kyori")
|
||||
|
||||
archiveFileName = "Sonar-Bungee.jar" // Hardcode a shortened version of the name
|
||||
}
|
||||
}
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+16
-10
@@ -33,8 +33,8 @@ import java.awt.font.FontRenderContext;
|
||||
import java.awt.font.GlyphVector;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
|
||||
@@ -69,12 +69,12 @@ public final class StandardCaptchaGenerator implements CaptchaGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
private final int width, height;
|
||||
private final @Nullable InputStream background;
|
||||
private BufferedImage backgroundImage;
|
||||
private final int width = 128, height = 128;
|
||||
private final @Nullable File background;
|
||||
private @Nullable BufferedImage backgroundImage;
|
||||
|
||||
@Override
|
||||
public @NotNull BufferedImage createImage(final char[] answer) {
|
||||
public @NotNull BufferedImage createImage(final char @NotNull [] answer) {
|
||||
final BufferedImage image = createBackgroundImage();
|
||||
final Graphics2D graphics = image.createGraphics();
|
||||
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
@@ -91,16 +91,22 @@ public final class StandardCaptchaGenerator implements CaptchaGenerator {
|
||||
}
|
||||
|
||||
private @NotNull BufferedImage createBackgroundImage() {
|
||||
// Create a new image buffer with a 3-byte color spectrum
|
||||
final BufferedImage image = new BufferedImage(width, height, TYPE_3BYTE_BGR);
|
||||
if (background == null) {
|
||||
final BufferedImage image = new BufferedImage(width, height, TYPE_3BYTE_BGR);
|
||||
// Fill the entire image with a noise texture
|
||||
return FBM.filter(image, image);
|
||||
}
|
||||
try {
|
||||
return backgroundImage == null ? backgroundImage = ImageIO.read(background) : backgroundImage;
|
||||
} catch (IOException exception) {
|
||||
throw new IllegalStateException("Could not read background image", exception);
|
||||
// Try to load the image from a file if it doesn't exist yet
|
||||
if (backgroundImage == null) {
|
||||
try {
|
||||
backgroundImage = ImageIO.read(background);
|
||||
} catch (IOException exception) {
|
||||
throw new IllegalStateException("Could not read background image", exception);
|
||||
}
|
||||
}
|
||||
image.createGraphics().drawImage(backgroundImage, 0, 0, Color.WHITE, null);
|
||||
return image;
|
||||
}
|
||||
|
||||
private void applyRandomColorGradient(final @NotNull Graphics2D graphics) {
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -28,7 +28,7 @@ import java.util.Random;
|
||||
public class Main {
|
||||
public void main(final String... args) throws IOException {
|
||||
final Random random = new Random();
|
||||
final StandardCaptchaGenerator standardCaptchaGenerator = new StandardCaptchaGenerator(128, 128, null);
|
||||
final StandardCaptchaGenerator standardCaptchaGenerator = new StandardCaptchaGenerator(null);
|
||||
|
||||
final long start = System.currentTimeMillis();
|
||||
final char[] dictionary = {'a', 'b', 'c', 'd', 'e', 'f'/*, 'g'*/, 'h'/*, 'i'*/, 'j',
|
||||
File renamed without changes.
File renamed without changes.
+3
-17
@@ -39,10 +39,9 @@ import xyz.jonesdev.sonar.api.timer.SystemTimer;
|
||||
import xyz.jonesdev.sonar.common.fallback.protocol.FallbackPreparer;
|
||||
import xyz.jonesdev.sonar.common.fallback.ratelimit.CaffeineCacheRatelimiter;
|
||||
import xyz.jonesdev.sonar.common.fallback.ratelimit.NoopCacheRatelimiter;
|
||||
import xyz.jonesdev.sonar.common.service.SonarServiceManager;
|
||||
import xyz.jonesdev.sonar.common.service.ScheduledServiceManager;
|
||||
import xyz.jonesdev.sonar.common.statistics.GlobalSonarStatistics;
|
||||
import xyz.jonesdev.sonar.common.subcommand.*;
|
||||
import xyz.jonesdev.sonar.common.update.UpdateChecker;
|
||||
import xyz.jonesdev.sonar.common.util.ProtocolUtil;
|
||||
|
||||
import java.io.File;
|
||||
@@ -99,13 +98,6 @@ public abstract class SonarBootstrap<T> implements Sonar {
|
||||
}
|
||||
|
||||
public final void initialize() {
|
||||
// Check if the branch is not the main branch to warn about unstable versions
|
||||
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");
|
||||
}
|
||||
|
||||
getLogger().info("Successfully booted in {}s!", launchTimer);
|
||||
getLogger().info("Initializing shared components...");
|
||||
|
||||
@@ -121,7 +113,7 @@ public abstract class SonarBootstrap<T> implements Sonar {
|
||||
|
||||
// Start threads
|
||||
getLogger().info("Starting all managed threads...");
|
||||
SonarServiceManager.start();
|
||||
ScheduledServiceManager.start();
|
||||
|
||||
// Done
|
||||
getLogger().info("Done ({}s)!", launchTimer);
|
||||
@@ -129,12 +121,6 @@ public abstract class SonarBootstrap<T> implements Sonar {
|
||||
// An error has occurred
|
||||
getLogger().error("An error has occurred while launching Sonar: {}", throwable);
|
||||
throwable.printStackTrace(System.err);
|
||||
return; // Do not check for updates if the launch failed
|
||||
}
|
||||
|
||||
// Check if a new version has been released if enabled in the configuration
|
||||
if (Sonar.get().getConfig().getGeneralConfig().getBoolean("general.check-for-updates")) {
|
||||
UpdateChecker.checkForUpdates();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,7 +176,7 @@ public abstract class SonarBootstrap<T> implements Sonar {
|
||||
// Initialize the shutdown process
|
||||
getLogger().info("Starting shutdown process...");
|
||||
// Interrupt threads
|
||||
SonarServiceManager.stop();
|
||||
ScheduledServiceManager.stop();
|
||||
// Close database connection if present
|
||||
if (verifiedPlayerController != null) {
|
||||
verifiedPlayerController.close();
|
||||
+7
-14
@@ -25,9 +25,7 @@ import io.netty.channel.ChannelPromise;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import static xyz.jonesdev.sonar.common.statistics.BandwidthStatistics.INCOMING;
|
||||
import static xyz.jonesdev.sonar.common.statistics.BandwidthStatistics.OUTGOING;
|
||||
import xyz.jonesdev.sonar.common.statistics.GlobalSonarStatistics;
|
||||
|
||||
@ChannelHandler.Sharable
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
@@ -35,27 +33,22 @@ public final class FallbackBandwidthHandler extends ChannelDuplexHandler {
|
||||
public static final ChannelHandler INSTANCE = new FallbackBandwidthHandler();
|
||||
|
||||
@Override
|
||||
public void channelRead(final @NotNull ChannelHandlerContext ctx,
|
||||
final @NotNull Object msg) throws Exception {
|
||||
// We can only get the size of a message if it's a ByteBuf
|
||||
public void channelRead(final ChannelHandlerContext ctx, final @NotNull Object msg) throws Exception {
|
||||
if (msg instanceof ByteBuf) {
|
||||
// Increment the incoming traffic by the number of readable bytes
|
||||
INCOMING.increment(((ByteBuf) msg).readableBytes());
|
||||
final int readableBytes = ((ByteBuf) msg).readableBytes();
|
||||
GlobalSonarStatistics.perSecondIncomingTraffic += readableBytes;
|
||||
}
|
||||
// Make sure to let the server handle the rest
|
||||
ctx.fireChannelRead(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final @NotNull ChannelHandlerContext ctx,
|
||||
final @NotNull Object msg,
|
||||
final ChannelPromise promise) throws Exception {
|
||||
// We can only get the size of a message if it's a ByteBuf
|
||||
public void write(final ChannelHandlerContext ctx, final Object msg, final ChannelPromise promise) throws Exception {
|
||||
if (msg instanceof ByteBuf) {
|
||||
// Increment the outgoing traffic by the number of readable bytes
|
||||
OUTGOING.increment(((ByteBuf) msg).readableBytes());
|
||||
final int readableBytes = ((ByteBuf) msg).readableBytes();
|
||||
GlobalSonarStatistics.perSecondOutgoingTraffic += readableBytes;
|
||||
}
|
||||
// Make sure to let the server handle the rest
|
||||
ctx.write(msg, promise);
|
||||
}
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
+1
-1
@@ -99,7 +99,7 @@ public final class FallbackUserWrapper implements FallbackUser {
|
||||
}
|
||||
|
||||
// Mark the player as connected by caching them in a map of verifying players
|
||||
Sonar.get().getFallback().getConnected().compute(inetAddress, (__, v) -> (byte) 0);
|
||||
Sonar.get().getFallback().getConnected().compute(inetAddress, (__, v) -> true);
|
||||
|
||||
// Replace normal encoder to allow custom packets
|
||||
final FallbackPacketEncoder newEncoder = new FallbackPacketEncoder(protocolVersion);
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+2
-3
@@ -96,10 +96,9 @@ public final class FallbackPacketDecoder extends ChannelInboundHandlerAdapter {
|
||||
// Let our verification handler process the packet
|
||||
if (listener != null) {
|
||||
listener.handle(packet);
|
||||
// Make sure to let the timeout handler know about this packet
|
||||
ctx.fireChannelRead(packet);
|
||||
}
|
||||
|
||||
// Fire channel read to avoid timeout
|
||||
ctx.fireChannelRead(packet);
|
||||
} finally {
|
||||
// Release the ByteBuf to avoid memory leaks
|
||||
byteBuf.release();
|
||||
+1
-1
@@ -50,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 = protocolRegistry.getPacketId(originalPacket);
|
||||
final int packetId = protocolRegistry.getPacketId(originalPacket.getClass());
|
||||
writeVarInt(out, packetId);
|
||||
packet.encode(out, protocolVersion);
|
||||
}
|
||||
File renamed without changes.
+83
-93
@@ -20,8 +20,8 @@ package xyz.jonesdev.sonar.common.fallback.protocol;
|
||||
import io.netty.util.collection.IntObjectHashMap;
|
||||
import io.netty.util.collection.IntObjectMap;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Data;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.ToString;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import xyz.jonesdev.sonar.api.fallback.protocol.ProtocolVersion;
|
||||
import xyz.jonesdev.sonar.common.fallback.protocol.packets.configuration.FinishConfigurationPacket;
|
||||
@@ -32,7 +32,10 @@ import xyz.jonesdev.sonar.common.fallback.protocol.packets.login.LoginStartPacke
|
||||
import xyz.jonesdev.sonar.common.fallback.protocol.packets.login.LoginSuccessPacket;
|
||||
import xyz.jonesdev.sonar.common.fallback.protocol.packets.play.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.EnumMap;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static xyz.jonesdev.sonar.api.fallback.protocol.ProtocolVersion.*;
|
||||
@@ -64,11 +67,11 @@ public enum FallbackPacketRegistry {
|
||||
map(0x01, MINECRAFT_1_20_2, true),
|
||||
map(0x02, MINECRAFT_1_20_5, true));
|
||||
clientbound.register(FinishConfigurationPacket.class, FinishConfigurationPacket::new,
|
||||
map(0x02, MINECRAFT_1_20_2, false),
|
||||
map(0x03, MINECRAFT_1_20_5, false));
|
||||
map(0x02, MINECRAFT_1_20_2, true),
|
||||
map(0x03, MINECRAFT_1_20_5, true));
|
||||
clientbound.register(KeepAlivePacket.class, KeepAlivePacket::new,
|
||||
map(0x03, MINECRAFT_1_20_2, false),
|
||||
map(0x04, MINECRAFT_1_20_5, false));
|
||||
map(0x03, MINECRAFT_1_20_2, true),
|
||||
map(0x04, MINECRAFT_1_20_5, true));
|
||||
clientbound.register(RegistryDataPacket.class, RegistryDataPacket::new,
|
||||
map(0x05, MINECRAFT_1_20_2, true),
|
||||
map(0x07, MINECRAFT_1_20_5, true));
|
||||
@@ -104,20 +107,20 @@ public enum FallbackPacketRegistry {
|
||||
map(0x29, MINECRAFT_1_20_2, true),
|
||||
map(0x2B, MINECRAFT_1_20_5, true));
|
||||
clientbound.register(KeepAlivePacket.class, KeepAlivePacket::new,
|
||||
map(0x00, MINECRAFT_1_7_2, false),
|
||||
map(0x1F, MINECRAFT_1_9, false),
|
||||
map(0x21, MINECRAFT_1_13, false),
|
||||
map(0x20, MINECRAFT_1_14, false),
|
||||
map(0x21, MINECRAFT_1_15, false),
|
||||
map(0x20, MINECRAFT_1_16, false),
|
||||
map(0x1F, MINECRAFT_1_16_2, false),
|
||||
map(0x21, MINECRAFT_1_17, false),
|
||||
map(0x1E, MINECRAFT_1_19, false),
|
||||
map(0x20, MINECRAFT_1_19_1, false),
|
||||
map(0x1F, MINECRAFT_1_19_3, false),
|
||||
map(0x23, MINECRAFT_1_19_4, false),
|
||||
map(0x24, MINECRAFT_1_20_2, false),
|
||||
map(0x26, MINECRAFT_1_20_5, false));
|
||||
map(0x00, MINECRAFT_1_7_2, true),
|
||||
map(0x1F, MINECRAFT_1_9, true),
|
||||
map(0x21, MINECRAFT_1_13, true),
|
||||
map(0x20, MINECRAFT_1_14, true),
|
||||
map(0x21, MINECRAFT_1_15, true),
|
||||
map(0x20, MINECRAFT_1_16, true),
|
||||
map(0x1F, MINECRAFT_1_16_2, true),
|
||||
map(0x21, MINECRAFT_1_17, true),
|
||||
map(0x1E, MINECRAFT_1_19, true),
|
||||
map(0x20, MINECRAFT_1_19_1, true),
|
||||
map(0x1F, MINECRAFT_1_19_3, true),
|
||||
map(0x23, MINECRAFT_1_19_4, true),
|
||||
map(0x24, MINECRAFT_1_20_2, true),
|
||||
map(0x26, MINECRAFT_1_20_5, true));
|
||||
clientbound.register(DisconnectPacket.class, DisconnectPacket::new,
|
||||
map(0x40, MINECRAFT_1_7_2, true),
|
||||
map(0x1A, MINECRAFT_1_9, true),
|
||||
@@ -214,19 +217,19 @@ public enum FallbackPacketRegistry {
|
||||
map(0x5D, MINECRAFT_1_20_3, true),
|
||||
map(0x5F, MINECRAFT_1_20_5, true));
|
||||
clientbound.register(VehicleMovePacket.class, VehicleMovePacket::new,
|
||||
map(0x29, MINECRAFT_1_9, false),
|
||||
map(0x2B, MINECRAFT_1_13, false),
|
||||
map(0x2C, MINECRAFT_1_14, false),
|
||||
map(0x2D, MINECRAFT_1_15, false),
|
||||
map(0x2C, MINECRAFT_1_16, false),
|
||||
map(0x2B, MINECRAFT_1_16_2, false),
|
||||
map(0x2C, MINECRAFT_1_17, false),
|
||||
map(0x29, MINECRAFT_1_19, false),
|
||||
map(0x2B, MINECRAFT_1_19_1, false),
|
||||
map(0x2A, MINECRAFT_1_19_3, false),
|
||||
map(0x2E, MINECRAFT_1_19_4, false),
|
||||
map(0x2F, MINECRAFT_1_20_2, false),
|
||||
map(0x31, MINECRAFT_1_20_5, false));
|
||||
map(0x29, MINECRAFT_1_9, true),
|
||||
map(0x2B, MINECRAFT_1_13, true),
|
||||
map(0x2C, MINECRAFT_1_14, true),
|
||||
map(0x2D, MINECRAFT_1_15, true),
|
||||
map(0x2C, MINECRAFT_1_16, true),
|
||||
map(0x2B, MINECRAFT_1_16_2, true),
|
||||
map(0x2C, MINECRAFT_1_17, true),
|
||||
map(0x29, MINECRAFT_1_19, true),
|
||||
map(0x2B, MINECRAFT_1_19_1, true),
|
||||
map(0x2A, MINECRAFT_1_19_3, true),
|
||||
map(0x2E, MINECRAFT_1_19_4, true),
|
||||
map(0x2F, MINECRAFT_1_20_2, true),
|
||||
map(0x31, MINECRAFT_1_20_5, true));
|
||||
clientbound.register(SpawnEntityPacket.class, SpawnEntityPacket::new,
|
||||
map(0x0E, MINECRAFT_1_7_2, true),
|
||||
map(0x00, MINECRAFT_1_9, true),
|
||||
@@ -320,19 +323,19 @@ public enum FallbackPacketRegistry {
|
||||
map(0x5A, MINECRAFT_1_20_3, true),
|
||||
map(0x5C, MINECRAFT_1_20_5, true));
|
||||
clientbound.register(SystemChatPacket.class, SystemChatPacket::new,
|
||||
map(0x02, MINECRAFT_1_7_2, false),
|
||||
map(0x0F, MINECRAFT_1_9, false),
|
||||
map(0x0E, MINECRAFT_1_13, false),
|
||||
map(0x0F, MINECRAFT_1_15, false),
|
||||
map(0x0E, MINECRAFT_1_16, false),
|
||||
map(0x0F, MINECRAFT_1_17, false),
|
||||
map(0x5F, MINECRAFT_1_19, false),
|
||||
map(0x62, MINECRAFT_1_19_1, false),
|
||||
map(0x60, MINECRAFT_1_19_3, false),
|
||||
map(0x64, MINECRAFT_1_19_4, false),
|
||||
map(0x67, MINECRAFT_1_20_2, false),
|
||||
map(0x69, MINECRAFT_1_20_3, false),
|
||||
map(0x6C, MINECRAFT_1_20_5, false));
|
||||
map(0x02, MINECRAFT_1_7_2, true),
|
||||
map(0x0F, MINECRAFT_1_9, true),
|
||||
map(0x0E, MINECRAFT_1_13, true),
|
||||
map(0x0F, MINECRAFT_1_15, true),
|
||||
map(0x0E, MINECRAFT_1_16, true),
|
||||
map(0x0F, MINECRAFT_1_17, true),
|
||||
map(0x5F, MINECRAFT_1_19, true),
|
||||
map(0x62, MINECRAFT_1_19_1, true),
|
||||
map(0x60, MINECRAFT_1_19_3, true),
|
||||
map(0x64, MINECRAFT_1_19_4, true),
|
||||
map(0x67, MINECRAFT_1_20_2, true),
|
||||
map(0x69, MINECRAFT_1_20_3, true),
|
||||
map(0x6C, MINECRAFT_1_20_5, true));
|
||||
clientbound.register(GameEventPacket.class, GameEventPacket::new,
|
||||
map(0x20, MINECRAFT_1_20_3, true),
|
||||
map(0x22, MINECRAFT_1_20_5, true));
|
||||
@@ -603,30 +606,28 @@ public enum FallbackPacketRegistry {
|
||||
return (direction == Direction.SERVERBOUND ? serverbound : clientbound).getProtocolRegistry(version);
|
||||
}
|
||||
|
||||
public static class PacketRegistry {
|
||||
private final Map<ProtocolVersion, ProtocolRegistry> versions;
|
||||
public static final class PacketRegistry {
|
||||
private final Map<ProtocolVersion, ProtocolRegistry> registries = new EnumMap<>(ProtocolVersion.class);
|
||||
|
||||
PacketRegistry() {
|
||||
final Map<ProtocolVersion, ProtocolRegistry> mutableVersions = new EnumMap<>(ProtocolVersion.class);
|
||||
for (final ProtocolVersion version : ProtocolVersion.values()) {
|
||||
if (!version.isUnknown()) {
|
||||
mutableVersions.put(version, new ProtocolRegistry(version));
|
||||
for (final ProtocolVersion protocolVersion : ProtocolVersion.values()) {
|
||||
if (!protocolVersion.isUnknown()) {
|
||||
registries.put(protocolVersion, new ProtocolRegistry(protocolVersion));
|
||||
}
|
||||
}
|
||||
this.versions = Collections.unmodifiableMap(mutableVersions);
|
||||
}
|
||||
|
||||
ProtocolRegistry getProtocolRegistry(final ProtocolVersion version) {
|
||||
final ProtocolRegistry registry = versions.get(version);
|
||||
private @NotNull ProtocolRegistry getProtocolRegistry(final @NotNull ProtocolVersion protocolVersion) {
|
||||
final ProtocolRegistry registry = registries.get(protocolVersion);
|
||||
if (registry == null) {
|
||||
throw new IllegalArgumentException("Could not find data for protocol version " + version);
|
||||
throw new IllegalArgumentException("Could not find data for protocol version " + protocolVersion);
|
||||
}
|
||||
return registry;
|
||||
}
|
||||
|
||||
<P extends FallbackPacket> void register(final Class<P> clazz,
|
||||
final Supplier<P> packetSupplier,
|
||||
final PacketMapping @NotNull ... mappings) {
|
||||
private <T extends FallbackPacket> void register(final @NotNull Class<T> clazz,
|
||||
final @NotNull Supplier<T> supplier,
|
||||
final PacketMapping @NotNull ... mappings) {
|
||||
if (mappings.length == 0) {
|
||||
throw new IllegalArgumentException("At least one mapping must be provided.");
|
||||
}
|
||||
@@ -636,21 +637,21 @@ public enum FallbackPacketRegistry {
|
||||
final PacketMapping next = (i + 1 < mappings.length) ? mappings[i + 1] : current;
|
||||
|
||||
final ProtocolVersion from = current.protocolVersion;
|
||||
final ProtocolVersion to = getProtocolVersion(current, next);
|
||||
final ProtocolVersion to = current == next ? LATEST_VERSION : next.protocolVersion;
|
||||
|
||||
for (final ProtocolVersion protocol : EnumSet.range(from, to)) {
|
||||
if (protocol == to && next != current) {
|
||||
for (final ProtocolVersion protocolVersion : EnumSet.range(from, to)) {
|
||||
if (protocolVersion == to && next != current) {
|
||||
break;
|
||||
}
|
||||
|
||||
final ProtocolRegistry registry = versions.get(protocol);
|
||||
final ProtocolRegistry registry = registries.get(protocolVersion);
|
||||
if (registry == null) {
|
||||
throw new IllegalArgumentException("Unknown protocol version " + from);
|
||||
throw new IllegalArgumentException("Unknown protocol version " + protocolVersion);
|
||||
}
|
||||
|
||||
if (registry.packetIdToSupplier.containsKey(current.id)) {
|
||||
if (registry.packetIdToSupplier.containsKey(current.packetId)) {
|
||||
throw new IllegalArgumentException("Can not register class " + clazz.getSimpleName()
|
||||
+ " with id " + current.id + " for " + registry.protocolVersion
|
||||
+ " with id " + current.packetId + " for " + registry.protocolVersion
|
||||
+ " because another packet is already registered");
|
||||
}
|
||||
|
||||
@@ -660,18 +661,12 @@ public enum FallbackPacketRegistry {
|
||||
}
|
||||
|
||||
if (!current.encodeOnly) {
|
||||
registry.packetIdToSupplier.put(current.id, packetSupplier);
|
||||
registry.packetIdToSupplier.put(current.packetId, supplier);
|
||||
}
|
||||
registry.packetClassToId.put(clazz, current.id);
|
||||
registry.packetClassToId.put(clazz, current.packetId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static ProtocolVersion getProtocolVersion(final @NotNull PacketMapping current,
|
||||
final @NotNull PacketMapping next) {
|
||||
return current == next ? LATEST_VERSION : next.protocolVersion;
|
||||
}
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
@@ -682,43 +677,38 @@ public enum FallbackPacketRegistry {
|
||||
private final Map<Class<? extends FallbackPacket>, Integer> packetClassToId =
|
||||
new HashMap<>(16, 0.5f);
|
||||
|
||||
public FallbackPacket createPacket(final int id) {
|
||||
final Supplier<? extends FallbackPacket> supplier = packetIdToSupplier.get(id);
|
||||
|
||||
if (supplier == null) {
|
||||
return null;
|
||||
}
|
||||
return supplier.get();
|
||||
public FallbackPacket createPacket(final int packetId) {
|
||||
final var supplier = packetIdToSupplier.get(packetId);
|
||||
return supplier == null ? null : supplier.get();
|
||||
}
|
||||
|
||||
public int getPacketId(final @NotNull FallbackPacket packet) {
|
||||
final int id = packetClassToId.getOrDefault(packet.getClass(), Integer.MIN_VALUE);
|
||||
|
||||
if (id == Integer.MIN_VALUE) {
|
||||
throw new IllegalArgumentException("Could not find packet");
|
||||
public int getPacketId(final @NotNull Class<? extends FallbackPacket> clazz) {
|
||||
final int packetId = packetClassToId.getOrDefault(clazz, -1);
|
||||
if (packetId == -1) {
|
||||
throw new IllegalArgumentException("Could not find packet ID for " + clazz.getSimpleName());
|
||||
}
|
||||
return id;
|
||||
return packetId;
|
||||
}
|
||||
}
|
||||
|
||||
@Data
|
||||
@ToString
|
||||
public static final class PacketMapping {
|
||||
private final int id;
|
||||
private final int packetId;
|
||||
private final ProtocolVersion protocolVersion;
|
||||
private final boolean encodeOnly;
|
||||
|
||||
PacketMapping(final int id,
|
||||
PacketMapping(final int packetId,
|
||||
final ProtocolVersion protocolVersion,
|
||||
final boolean encodeOnly) {
|
||||
this.id = id;
|
||||
this.packetId = packetId;
|
||||
this.protocolVersion = protocolVersion;
|
||||
this.encodeOnly = encodeOnly;
|
||||
}
|
||||
}
|
||||
|
||||
private static @NotNull PacketMapping map(final int id,
|
||||
private static @NotNull PacketMapping map(final int packetId,
|
||||
final ProtocolVersion protocolVersion,
|
||||
final boolean encodeOnly) {
|
||||
return new PacketMapping(id, protocolVersion, encodeOnly);
|
||||
return new PacketMapping(packetId, protocolVersion, encodeOnly);
|
||||
}
|
||||
}
|
||||
File renamed without changes.
+22
-15
@@ -24,6 +24,7 @@ import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
|
||||
import xyz.jonesdev.sonar.api.Sonar;
|
||||
import xyz.jonesdev.sonar.api.config.SonarConfiguration;
|
||||
import xyz.jonesdev.sonar.api.event.impl.CaptchaGenerationStartEvent;
|
||||
import xyz.jonesdev.sonar.captcha.StandardCaptchaGenerator;
|
||||
import xyz.jonesdev.sonar.common.fallback.protocol.block.BlockType;
|
||||
import xyz.jonesdev.sonar.common.fallback.protocol.block.BlockUpdate;
|
||||
@@ -75,7 +76,7 @@ public class FallbackPreparer {
|
||||
public final FallbackPacket[] REGISTRY_SYNC_1_20_5 = RegistryDataPacket.of(DimensionRegistry.CODEC_1_20);
|
||||
public final FallbackPacket[] REGISTRY_SYNC_1_21 = RegistryDataPacket.of(DimensionRegistry.CODEC_1_21);
|
||||
public final FallbackPacket START_WRITING_CHUNKS = new GameEventPacket(13, 0);
|
||||
public final static FallbackPacket CACHED_HELD_ITEM_RESET = new SetHeldItemPacket(~4);
|
||||
public final static FallbackPacket CACHED_HELD_ITEM_SLOT = new SetHeldItemPacket(~4);
|
||||
public final FallbackPacket CAPTCHA_KEEP_ALIVE = new KeepAlivePacket(RANDOM.nextInt());
|
||||
|
||||
public static FallbackPacket loginSuccess;
|
||||
@@ -116,15 +117,15 @@ public class FallbackPreparer {
|
||||
|
||||
// Prepare JoinGame packet
|
||||
joinGame = new FallbackPacketSnapshot(new JoinGamePacket(PLAYER_ENTITY_ID,
|
||||
Sonar.get().getConfig().getVerification().getGamemode().getId(),
|
||||
RANDOM.nextLong(), false, 0,
|
||||
true, false, false,
|
||||
new String[]{"minecraft:overworld"}, "minecraft:overworld"));
|
||||
Sonar.get().getConfig().getVerification().getGamemode().getId(), RANDOM.nextLong(),
|
||||
0, 0, false, true, false,
|
||||
false, false, false, true,
|
||||
new String[]{"minecraft:overworld"}, "minecraft:overworld", "flat"));
|
||||
|
||||
// Prepare the gravity check
|
||||
maxMovementTick = Sonar.get().getConfig().getVerification().getGravity().getMaxMovementTicks();
|
||||
|
||||
double motionY = 0, fallDistance = 1;
|
||||
double motionY = 0, fallDistance = 0;
|
||||
|
||||
for (int i = 0; i < maxMovementTick; i++) {
|
||||
motionY = (motionY - 0.1) * 0.98f;
|
||||
@@ -183,10 +184,12 @@ public class FallbackPreparer {
|
||||
removeBoat = new RemoveEntitiesPacket(VEHICLE_BOAT_ENTITY_ID);
|
||||
teleportMinecart = new TeleportEntityPacket(
|
||||
VEHICLE_MINECART_ENTITY_ID, SPAWN_X_POSITION, IN_VOID_Y_POSITION, SPAWN_Z_POSITION, false);
|
||||
spawnBoatEntity = new FallbackPacketSnapshot(new SpawnEntityPacket(
|
||||
VEHICLE_BOAT_ENTITY_ID, EntityType.BOAT, SPAWN_X_POSITION, IN_AIR_Y_POSITION, SPAWN_Z_POSITION));
|
||||
spawnMinecartEntity = new FallbackPacketSnapshot(new SpawnEntityPacket(
|
||||
VEHICLE_MINECART_ENTITY_ID, EntityType.MINECART, SPAWN_X_POSITION, IN_AIR_Y_POSITION, SPAWN_Z_POSITION));
|
||||
spawnBoatEntity = new FallbackPacketSnapshot(new SpawnEntityPacket(VEHICLE_BOAT_ENTITY_ID,
|
||||
EntityType.BOAT, RANDOM.nextInt(16), IN_AIR_Y_POSITION, RANDOM.nextInt(16),
|
||||
0, 0, 0, 0));
|
||||
spawnMinecartEntity = new FallbackPacketSnapshot(new SpawnEntityPacket(VEHICLE_MINECART_ENTITY_ID,
|
||||
EntityType.MINECART, RANDOM.nextInt(16), IN_AIR_Y_POSITION, RANDOM.nextInt(16),
|
||||
0, 0, 0, 0));
|
||||
setBoatPassengers = new FallbackPacketSnapshot(new SetPassengersPacket(VEHICLE_BOAT_ENTITY_ID, PLAYER_ENTITY_ID));
|
||||
setMinecartPassengers = new FallbackPacketSnapshot(new SetPassengersPacket(VEHICLE_MINECART_ENTITY_ID, PLAYER_ENTITY_ID));
|
||||
|
||||
@@ -211,9 +214,13 @@ public class FallbackPreparer {
|
||||
}
|
||||
|
||||
// Update the CAPTCHA generator if necessary
|
||||
if (Sonar.get().getFallback().getCaptchaGenerator() == null
|
||||
|| Sonar.get().getFallback().getCaptchaGenerator() instanceof StandardCaptchaGenerator) {
|
||||
Sonar.get().getFallback().setCaptchaGenerator(new StandardCaptchaGenerator(128, 128,
|
||||
final CaptchaGenerationStartEvent generationStartEvent = new CaptchaGenerationStartEvent(
|
||||
Sonar.get().getFallback().getCaptchaGenerator());
|
||||
Sonar.get().getEventManager().publish(generationStartEvent);
|
||||
|
||||
if (generationStartEvent.getCaptchaGenerator() == null
|
||||
|| generationStartEvent.getCaptchaGenerator() instanceof StandardCaptchaGenerator) {
|
||||
Sonar.get().getFallback().setCaptchaGenerator(new StandardCaptchaGenerator(
|
||||
Sonar.get().getConfig().getVerification().getMap().getBackgroundImage()));
|
||||
} else {
|
||||
Sonar.get().getLogger().info("Custom CAPTCHA generator detected, skipping reinitialization.");
|
||||
@@ -229,8 +236,8 @@ public class FallbackPreparer {
|
||||
Sonar.get().getFallback().setCaptchaGenerator(null);
|
||||
}
|
||||
|
||||
maxTotalPacketsSent = maxMovementTick
|
||||
+ (xpCountdown == null ? 0 : xpCountdown.length) * 3
|
||||
maxTotalPacketsSent = maxMovementTick + 2
|
||||
+ (xpCountdown == null ? 0 : xpCountdown.length) * 20 + 5
|
||||
+ Sonar.get().getConfig().getVerification().getVehicle().getMinimumPackets() * 4
|
||||
+ Sonar.get().getConfig().getVerification().getMap().getMaxTries()
|
||||
+ 150 /* some arbitrary leeway */;
|
||||
File renamed without changes.
File renamed without changes.
+2
@@ -19,6 +19,7 @@ package xyz.jonesdev.sonar.common.fallback.protocol.captcha;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
import xyz.jonesdev.sonar.api.Sonar;
|
||||
import xyz.jonesdev.sonar.api.event.impl.CaptchaGenerationEndEvent;
|
||||
import xyz.jonesdev.sonar.api.timer.SystemTimer;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
@@ -65,6 +66,7 @@ public class CaptchaPreparer {
|
||||
}
|
||||
|
||||
Sonar.get().getLogger().info("Finished preparing {} CAPTCHA answers ({}s)!", preparedAmount, timer);
|
||||
Sonar.get().getEventManager().publish(new CaptchaGenerationEndEvent(timer, preparedAmount));
|
||||
});
|
||||
}
|
||||
|
||||
File renamed without changes.
Loaded 100 of 220 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user