Compare commits

..

4 Commits

Author SHA1 Message Date
DGun Otto 6f19a5442f Update README.md 2023-07-12 00:40:44 +08:00
DGun Otto 3019e33945 Update README.md 2023-07-12 00:37:53 +08:00
HaHaWTH 7e49e26735 reupload files 2023-07-11 20:45:01 +08:00
HaHaWTH b014da245d Del all files 2023-07-11 20:42:24 +08:00
85 changed files with 752 additions and 346 deletions
+2 -19
View File
@@ -1,21 +1,4 @@
# AuthMeReReloaded
**"A Fork of Authme that contains many bug fixes!"**
**请前往Releases下载最新版本**(**Download the latest version from Releases**)
**"A fork of the best authentication plugin for the Bukkit modding API!"**
Changes to the original AuthMe(相较于原版AuthMe的变化):
1.Memory improvement
2.Fixed GeoIP database
3.Hook floodgate
4.Choose the best performance method by server brand
5.Anti ghost player
6.GUI captcha for unregistered players
7.Block unsafe passwords by querying API
8.Self hash check to prevent jar virus infection(abandoned)
9.Updater
**Known Folia issue**
1.If the teleport distance too far away,the player may be frozen
![Graph](https://bstats.org/signatures/bukkit/AuthMeReloaded-Fork.svg)
-1
View File
@@ -1 +0,0 @@
d91307767d8526ac84a3055ac0e773e91f88d452b4b0031f7ecfed721ac6b641
-1
View File
@@ -1 +0,0 @@
d0aab9856defbd8ef31a9cd7257c5b5761e61a7e39807708c81decf82f599323
-1
View File
@@ -1 +0,0 @@
176a6c6ea03ad8cc37d1d11c3e3608d8b59c09f9f923eae287e8192731642ec8
-1
View File
@@ -1 +0,0 @@
61b1a691490d78af1028a442143f649d432618b92c5a9a7031eb4f94817d768b
-1
View File
@@ -1 +0,0 @@
222eb5ecb4c58f279b8e2f75d38a45495ceb875f249ae3217e3f2a36e50b7d39
-1
View File
@@ -1 +0,0 @@
da53060e21d7135e479a6a6a6fd090b8f41e1423742b94e4dbb1a9230b5621fd
View File
-1
View File
@@ -1 +0,0 @@
423084f2a50c27f62d1b5c85a95e78b9bc3df49d5bd9cefd6fe1aa9227b856c1
-1
View File
@@ -1 +0,0 @@
410df26b12703b82987b9d739c19211346418f1c954d214827805c13b5f82c98
-1
View File
@@ -1 +0,0 @@
20569ebc44a9847da0946de5a3bf2cd2b7855dffb03abc9d29204afcaa64b8bb
-1
View File
@@ -1 +0,0 @@
51a067778ad9b0938d57fd4e2975e0f8dce4914ee060efd0fd6755a8810da4f3
+10 -10
View File
@@ -6,10 +6,10 @@
<groupId>fr.xephi</groupId>
<artifactId>authme</artifactId>
<version>5.6.0-SNAPSHOT</version>
<version>5.6.0-FORK</version>
<name>AuthMeReloaded</name>
<description>The first authentication plugin for the Bukkit API!</description>
<name>AuthMeReReloaded</name>
<description>Fork of the first authentication plugin for the Bukkit API!</description>
<inceptionYear>2013</inceptionYear>
<url>https://github.com/AuthMe/AuthMeReloaded</url>
@@ -324,7 +324,7 @@
<goal>shade</goal>
</goals>
<configuration>
<finalName>${project.finalNameBase}-legacy</finalName>
<finalName>${project.finalNameBase}-Spigot-Universal</finalName>
<relocations>
<relocation>
<pattern>com.google.common</pattern>
@@ -616,7 +616,7 @@
<groupId>org.geysermc.floodgate</groupId>
<artifactId>api</artifactId>
<version>2.2.0-SNAPSHOT</version>
<scope>provided</scope>
<scope>compile</scope>
</dependency>
<!-- Jalu Injector -->
<dependency>
@@ -757,7 +757,7 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.0.1-jre</version>
<version>31.1-jre</version>
<optional>true</optional>
<exclusions>
<exclusion>
@@ -770,7 +770,7 @@
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.9</version>
<version>2.10.1</version>
<optional>true</optional>
</dependency>
@@ -794,7 +794,7 @@
<dependency>
<groupId>org.bstats</groupId>
<artifactId>bstats-bukkit</artifactId>
<version>3.0.0</version>
<version>3.0.1</version>
<optional>true</optional>
</dependency>
@@ -802,7 +802,7 @@
<dependency>
<groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib</artifactId>
<version>4.8.0</version>
<version>5.0.0</version>
<scope>provided</scope>
<exclusions>
<exclusion>
@@ -1068,7 +1068,7 @@
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.39.3.0</version>
<version>3.40.1.0</version>
<scope>test</scope>
</dependency>
<dependency>
+175 -18
View File
@@ -2,13 +2,27 @@ package fr.xephi.authme;
import ch.jalu.injector.Injector;
import ch.jalu.injector.InjectorBuilder;
import com.google.gson.annotations.Since;
import fr.xephi.authme.api.v3.AuthMeApi;
import fr.xephi.authme.command.CommandArgumentDescription;
import fr.xephi.authme.command.CommandHandler;
import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.initialization.DataFolder;
import fr.xephi.authme.initialization.DataSourceProvider;
import fr.xephi.authme.initialization.OnShutdownPlayerSaver;
import fr.xephi.authme.initialization.OnStartupTasks;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import fr.xephi.authme.initialization.SettingsProvider;
import fr.xephi.authme.initialization.TaskCloser;
import fr.xephi.authme.listener.BlockListener;
@@ -17,6 +31,8 @@ import fr.xephi.authme.listener.PlayerListener;
import fr.xephi.authme.listener.PlayerListener111;
import fr.xephi.authme.listener.PlayerListener19;
import fr.xephi.authme.listener.PlayerListener19Spigot;
import fr.xephi.authme.listener.PlayerQuitListener;
import fr.xephi.authme.listener.RegisterListener;
import fr.xephi.authme.listener.ServerListener;
import fr.xephi.authme.mail.EmailService;
import fr.xephi.authme.output.ConsoleLoggerFactory;
@@ -29,26 +45,40 @@ import fr.xephi.authme.service.yaml.YamlParseException;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.SettingsWarner;
import fr.xephi.authme.settings.properties.EmailSettings;
import fr.xephi.authme.settings.properties.RegistrationSettings;
import fr.xephi.authme.settings.properties.SecuritySettings;
import fr.xephi.authme.task.CleanupTask;
import fr.xephi.authme.task.purge.PurgeService;
import fr.xephi.authme.util.ExceptionUtils;
import fr.xephi.authme.util.TeleportUtils;
import org.bstats.bukkit.Metrics;
import org.bukkit.Bukkit;
import org.bukkit.Server;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitScheduler;
import org.jetbrains.annotations.NotNull;
import fr.xephi.authme.listener.PlayerQuitListener;
import javax.inject.Inject;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Scanner;
import java.util.function.Consumer;
import java.util.logging.Level;
import static fr.xephi.authme.service.BukkitService.TICKS_PER_MINUTE;
import static fr.xephi.authme.util.Utils.isClassLoaded;
import static org.bukkit.Bukkit.getServer;
import static org.bukkit.Bukkit.isHardcore;
/**
* The AuthMe main class.
@@ -61,12 +91,14 @@ public class AuthMe extends JavaPlugin {
private static final int CLEANUP_INTERVAL = 5 * TICKS_PER_MINUTE;
// Version and build number values
private static String pluginVersion = "5.6.0";
private static String pluginBuildNumber = "Custom";
private static String pluginVersion = "5.6.0-Fork";
private static final String pluginBuild = "b";
private static String pluginBuildNumber = "17";
protected final Boolean SHAEnabled = false;
// Private instances
private EmailService emailService;
private CommandHandler commandHandler;
@Inject
private Settings settings;
private DataSource database;
private BukkitService bukkitService;
@@ -79,7 +111,8 @@ public class AuthMe extends JavaPlugin {
*/
public AuthMe() {
}
public static Boolean SATEnabled = false;
public static Boolean GUIEnabled = false;
/**
* Get the plugin's name.
*
@@ -107,31 +140,34 @@ public class AuthMe extends JavaPlugin {
return pluginBuildNumber;
}
/**
* Method called when the server enables the plugin.
*/
@Override
public void onEnable() {
AuthMe.GUIEnabled = false;
AuthMe.SATEnabled = false;
// Load the plugin version data from the plugin description file
loadPluginInfo(getDescription().getVersion());
// Set the Logger instance and log file path
ConsoleLogger.initialize(getLogger(), new File(getDataFolder(), LOG_FILENAME));
logger = ConsoleLoggerFactory.get(AuthMe.class);
logger.info("您正在加载的是由第三方Fork并修复众多错误的 AuthMeReReloaded!");
// Check server version
if (!isClassLoaded("org.spigotmc.event.player.PlayerSpawnLocationEvent")
|| !isClassLoaded("org.bukkit.event.player.PlayerInteractAtEntityEvent")) {
logger.warning("You are running an unsupported server version (" + getServerNameVersionSafe() + "). "
+ "AuthMe requires Spigot 1.8.X or later!");
logger.warning("你正在运行不受支持的服务器版本 (" + getServerNameVersionSafe() + "). "
+ "AuthMe 仅支持Spigot 1.9及之后的版本!");
stopOrUnload();
return;
}
// Prevent running AuthMeBridge due to major exploit issues
if (getServer().getPluginManager().isPluginEnabled("AuthMeBridge")) {
logger.warning("Detected AuthMeBridge, support for it has been dropped as it was "
+ "causing exploit issues, please use AuthMeBungee instead! Aborting!");
logger.warning("检测到 AuthMeBridge被加载, 对AuthMeBridge的支持已经停止 "
+ "且可能会造成严重漏洞! 已中止加载!");
stopOrUnload();
return;
}
@@ -142,11 +178,11 @@ public class AuthMe extends JavaPlugin {
} catch (Throwable th) {
YamlParseException yamlParseException = ExceptionUtils.findThrowableInCause(YamlParseException.class, th);
if (yamlParseException == null) {
logger.logException("Aborting initialization of AuthMe:", th);
logger.logException("已中止AuthMeReReloaded的初始化,原因:", th);
th.printStackTrace();
} else {
logger.logException("File '" + yamlParseException.getFile() + "' contains invalid YAML. "
+ "Please run its contents through https://yamllint.com", yamlParseException);
logger.logException("文件 '" + yamlParseException.getFile() + "' 包含YAML语法错误. "
+ "请尝试在 https://yamllint.com 中运行文件内容", yamlParseException);
}
stopOrUnload();
return;
@@ -158,7 +194,6 @@ public class AuthMe extends JavaPlugin {
// Schedule clean up task
CleanupTask cleanupTask = injector.getSingleton(CleanupTask.class);
cleanupTask.runTaskTimerAsynchronously(this, CLEANUP_INTERVAL, CLEANUP_INTERVAL);
// Do a backup on start
backupService.doBackup(BackupService.BackupCause.START);
@@ -166,18 +201,43 @@ public class AuthMe extends JavaPlugin {
OnStartupTasks.sendMetrics(this, settings);
// Successful message
logger.info("AuthMeReloaded successfully enabled!");
logger.info("AuthMeReReloaded 已成功启动!");
// Purge on start if enabled
PurgeService purgeService = injector.getSingleton(PurgeService.class);
purgeService.runAutoPurge();
// 注册玩家退出事件监听
if (settings.getProperty(SecuritySettings.ANTI_GHOST_PLAYERS) || settings.getProperty(SecuritySettings.SMART_ASYNC_TELEPORT)/* || settings.getProperty(SecuritySettings.GUI_CAPTCHA)*/) {
if (settings.getProperty(SecuritySettings.ANTI_GHOST_PLAYERS)) {
getServer().getPluginManager().registerEvents(new PlayerQuitListener((Plugin) this), this);
}
if (settings.getProperty(SecuritySettings.SMART_ASYNC_TELEPORT)) {
logger.info("(RC2)SmartAsyncTeleport功能已注册");
AuthMe.SATEnabled = true;
}
if (settings.getProperty(SecuritySettings.GUI_CAPTCHA) && getServer().getPluginManager().isPluginEnabled("ProtocolLib")) {
getServer().getPluginManager().registerEvents(new RegisterListener((Plugin) this), this);
logger.info("(RC2)GUI验证码功能已注册");
AuthMe.GUIEnabled = true;
} else if (settings.getProperty(SecuritySettings.GUI_CAPTCHA) && !getServer().getPluginManager().isPluginEnabled("ProtocolLib")) {
logger.warning("ProtocolLib未加载,GUI验证码功能无法使用");
}
logger.info("以上功能尚在测试中,如有问题请反馈,如需关闭请前往config.yml修改");
logger.info("反馈地址: github.com/HaHaWTH/AuthMeReReloaded/issues");
}
if (settings.getProperty(SecuritySettings.CHECK_FOR_UPDATES)) {
checkForUpdates();
}
if (SHAEnabled){
//shaChecker();
}
}
public File pluginfile = getFile();
/**
* Load the version and build number of the plugin from the description file.
*
* @param versionRaw the version as given by the plugin description file
*/
private static void loadPluginInfo(String versionRaw) {
int index = versionRaw.lastIndexOf("-");
if (index != -1) {
@@ -320,9 +380,106 @@ public class AuthMe extends JavaPlugin {
// Disabled correctly
Consumer<String> infoLogMethod = logger == null ? getLogger()::info : logger::info;
infoLogMethod.accept("AuthMe " + this.getDescription().getVersion() + " disabled!");
infoLogMethod.accept("AuthMe " + this.getDescription().getVersion() + " 已卸载!");
ConsoleLogger.closeFileWriter();
}
private static final String owner = "HaHaWTH";
private static final String owner_gitee = "Shixuehan114514";
private static final String repo = "AuthMeReReloaded";
private void checkForUpdates() {
logger.info("正在检查更新...");
Bukkit.getScheduler().runTaskAsynchronously(this, () -> {
try {
// Get the latest version number from GitHub
URL url = new URL("https://api.github.com/repos/" + owner + "/" + repo + "/releases/latest");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(10000); // 设置连接超时为10秒
conn.setReadTimeout(10000); // 设置读取超时为10秒
Scanner scanner = new Scanner(conn.getInputStream());
String response = scanner.useDelimiter("\\Z").next();
scanner.close();
// Parse JSON response and extract version number
String latestVersion = response.substring(response.indexOf("tag_name") + 11);
latestVersion = latestVersion.substring(0, latestVersion.indexOf("\""));
if ((pluginBuild + pluginBuildNumber).equals(latestVersion)) {
getLogger().log(Level.INFO,"当前为最新版本");
}
if (!(pluginBuild + pluginBuildNumber).equals(latestVersion)) {
// Display update message to users
String message = "有新版本可用! 最新版本:" + latestVersion + " 当前版本:" + pluginBuild + pluginBuildNumber;
getLogger().log(Level.INFO, message);
getLogger().log(Level.INFO,"下载地址:github.com/HaHaWTH/AuthMeReReloaded/releases/latest");
}
}catch (IOException e) {
getLogger().log(Level.WARNING,"从GitHub检查更新时出现错误,原因: " + e.getMessage());
}
});
}
private static final String SHA_URL = "https://raw.githubusercontent.com/"+ owner +"/"+ repo + "/master/"+pluginBuild +pluginBuildNumber+ ".sha";
private static final String ALGORITHM = "SHA-256";
private static final String PROXY_URL = "https://ghproxy.com/";
private static final String SHA_URL_GITEE = "https://gitee.com/"+ owner_gitee +"/"+ repo + "/raw/master/"+pluginBuild+pluginBuildNumber+ ".sha";
// public void shaChecker() {
// // 请求SHA文件
//
// String actualSha;
// try {
// URL url;
// if(settings.getProperty(SecuritySettings.SHA_CHECK_METHOD).equals("github")) {
// url = new URL(SHA_URL);
// logger.info("正在检查文件完整性...(GitHub)");
// } else if(settings.getProperty(SecuritySettings.SHA_CHECK_METHOD).equals("ghproxy")) {
// url = new URL(PROXY_URL + SHA_URL);
// logger.info("正在检查文件完整性...(GhProxy)");
// } else if (settings.getProperty(SecuritySettings.SHA_CHECK_METHOD).equals("gitee")) {
// url = new URL(SHA_URL_GITEE);
// logger.info("正在检查文件完整性...(Gitee)");
// }else {
// logger.warning("未知的SHA检查方法,将从GitHub获取SHA文件");
// url = new URL(SHA_URL);
// }
//
//
// HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// conn.setConnectTimeout(10000);
// conn.setReadTimeout(9000);
// conn.setRequestMethod("GET");
// InputStream stream = conn.getInputStream();
// ByteArrayOutputStream result = new ByteArrayOutputStream();
// byte[] buffer = new byte[1024];
// int length;
// while ((length = stream.read(buffer)) != -1) {
// result.write(buffer, 0, length);
// }
// String expectedSha = result.toString().trim();
// // 计算插件文件的SHA值
// MessageDigest md = MessageDigest.getInstance(ALGORITHM);
// byte[] fileBytes = Files.readAllBytes(pluginfile.toPath());
// byte[] hashBytes = md.digest(fileBytes);
// StringBuilder sb = new StringBuilder();
// for (byte b : hashBytes) {
// sb.append(String.format("%02x", b));
// }
// actualSha = sb.toString();
//
// // 比较SHA值并加载插件
// if (expectedSha.equals(actualSha)) {
// logger.info("SHA联网安全校验完毕");
// } else {
// // SHA值不匹配,插件可能被篡改
// logger.warning("SHA值不匹配,插件被篡改");
// stopOrUnload();
// }
// }catch (NoSuchAlgorithmException | IOException e){
// logger.warning("SHA校验失败,请尝试切换校验API");
// logger.warning("您当前请求的API为:" + settings.getProperty(SecuritySettings.SHA_CHECK_METHOD));
// stopOrUnload();
// }
// }
/**
* Handle Bukkit commands.
@@ -106,7 +106,7 @@ public final class ConsoleLogger {
*/
public void warning(String message) {
logger.warning(message);
writeLog("[WARN] " + message);
writeLog("[警告] " + message);
}
/**
@@ -128,7 +128,7 @@ public final class ConsoleLogger {
*/
public void info(String message) {
logger.info(message);
writeLog("[INFO] " + message);
writeLog("[信息] " + message);
}
/**
@@ -142,7 +142,7 @@ public final class ConsoleLogger {
public void fine(String message) {
if (logLevel.includes(LogLevel.FINE)) {
logger.info(message);
writeLog("[FINE] " + message);
writeLog("[信息:调试] " + message);
}
}
@@ -215,7 +215,7 @@ public final class ConsoleLogger {
}
private void logAndWriteWithDebugPrefix(String message) {
String debugMessage = "[DEBUG] " + message;
String debugMessage = "[信息:调试] " + message;
logger.info(debugMessage);
writeLog(debugMessage);
}
@@ -29,7 +29,6 @@ import fr.xephi.authme.command.executable.authme.TotpViewStatusCommand;
import fr.xephi.authme.command.executable.authme.UnregisterAdminCommand;
import fr.xephi.authme.command.executable.authme.UpdateHelpMessagesCommand;
import fr.xephi.authme.command.executable.authme.VersionCommand;
import fr.xephi.authme.command.executable.authme.WhitelistCommand;
import fr.xephi.authme.command.executable.authme.debug.DebugCommand;
import fr.xephi.authme.command.executable.captcha.CaptchaCommand;
import fr.xephi.authme.command.executable.changepassword.ChangePasswordCommand;
@@ -421,16 +420,6 @@ public class CommandInitializer {
.executableCommand(SwitchAntiBotCommand.class)
.register();
CommandDescription.builder()
.parent(authmeBase)
.labels("whitelist")
.description("Switch whitelist mode")
.detailedDescription("Switch or toggle the whitelist mode to the specified state.")
.withArgument("mode", "ON / OFF", OPTIONAL)
.permission(AdminPermission.SWITCH_ANTIBOT)
.executableCommand(WhitelistCommand.class)
.register();
// Register the reload command
CommandDescription.builder()
.parent(authmeBase)
@@ -17,9 +17,9 @@ public abstract class PlayerCommand implements ExecutableCommand {
} else {
String alternative = getAlternativeCommand();
if (alternative != null) {
sender.sendMessage("Player only! Please use " + alternative + " instead.");
sender.sendMessage("此命令仅限玩家使用!请使用 " + alternative + " .");
} else {
sender.sendMessage("This command is only for players.");
sender.sendMessage("此命令只能被玩家执行.");
}
}
}
@@ -1,9 +1,13 @@
package fr.xephi.authme.command.executable.authme;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.command.PlayerCommand;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.SpawnLoader;
import fr.xephi.authme.settings.properties.SecuritySettings;
import fr.xephi.authme.util.TeleportUtils;
import org.bukkit.entity.Player;
import fr.xephi.authme.AuthMe;
import javax.inject.Inject;
import java.util.List;
@@ -11,16 +15,22 @@ import java.util.List;
* Teleports the player to the first spawn.
*/
public class FirstSpawnCommand extends PlayerCommand {
@Inject
private Settings settings;
@Inject
private SpawnLoader spawnLoader;
@Override
public void runCommand(Player player, List<String> arguments) {
if (spawnLoader.getFirstSpawn() == null) {
player.sendMessage("[AuthMe] First spawn has failed, please try to define the first spawn");
} else {
player.teleport(spawnLoader.getFirstSpawn());
//String name= player.getName();
if(AuthMe.SATEnabled) {
TeleportUtils.teleport(player, spawnLoader.getFirstSpawn());
} else {
player.teleport(spawnLoader.getFirstSpawn());
}
//player.teleport(spawnLoader.getFirstSpawn());
}
}
}
@@ -1,40 +0,0 @@
package fr.xephi.authme.command.executable.authme;
import fr.xephi.authme.command.ExecutableCommand;
import fr.xephi.authme.service.WhiteListService;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import javax.inject.Inject;
import java.util.List;
/**
* Display or change the status of the antibot mod.
*/
public class WhitelistCommand implements ExecutableCommand {
@Inject
private WhiteListService whiteListService;
@Override
public void executeCommand(final CommandSender sender, List<String> arguments) {
if (arguments.isEmpty()) {
sender.sendMessage("[AuthMe] WhiteList: " + whiteListService.getWhiteListStatus().name());
return;
}
String newState = arguments.get(0);
// Enable or disable the mod
if ("ON".equalsIgnoreCase(newState)) {
whiteListService.overrideWhiteListStatus(true);
sender.sendMessage("[AuthMe] WhiteList enabled!");
} else if ("OFF".equalsIgnoreCase(newState)) {
sender.sendMessage("[AuthMe] WhiteList disabled!");
whiteListService.overrideWhiteListStatus(false);
} else {
sender.sendMessage(ChatColor.GOLD + "Detailed help: " + ChatColor.WHITE + "/authme help whitelist");
}
}
}
@@ -42,6 +42,12 @@ public class ChangePasswordCommand extends PlayerCommand {
commonService.send(player, MessageKey.NOT_LOGGED_IN);
return;
}
// Check if the user has been verified or not
if (codeManager.isVerificationRequired(player)) {
codeManager.codeExistOrGenerateNew(name);
commonService.send(player, MessageKey.VERIFICATION_CODE_REQUIRED);
return;
}
String oldPassword = arguments.get(0);
String newPassword = arguments.get(1);
@@ -70,7 +70,7 @@ public class TotpCodeCommand extends PlayerCommand {
boolean isCodeValid = totpAuthenticator.checkCode(auth, inputCode);
if (isCodeValid) {
logger.debug("Successfully checked TOTP code for `{0}`", player.getName());
asynchronousLogin.performLogin(player, auth,false);
asynchronousLogin.performLogin(player, auth);
} else {
logger.debug("Input TOTP code was invalid for player `{0}`", player.getName());
messages.send(player, MessageKey.TWO_FACTOR_INVALID_CODE);
@@ -53,7 +53,7 @@ public class OnStartupTasks {
* @param settings the settings
*/
public static void sendMetrics(AuthMe plugin, Settings settings) {
final Metrics metrics = new Metrics(plugin, 164);
final Metrics metrics = new Metrics(plugin, 18479);
metrics.addCustomChart(new SimplePie("messages_language",
() -> settings.getProperty(PluginSettings.MESSAGES_LANGUAGE)));
@@ -1,30 +1,40 @@
package fr.xephi.authme.listener;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.api.v3.AuthMeApi;
import fr.xephi.authme.data.auth.PlayerCache;
import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.initialization.SettingsDependent;
import fr.xephi.authme.service.ValidationService;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.RegistrationSettings;
import fr.xephi.authme.settings.properties.SecuritySettings;
import fr.xephi.authme.util.PlayerUtils;
import org.bukkit.Material;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.entity.EntityEvent;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryOpenEvent;
import org.bukkit.event.player.PlayerEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import javax.inject.Inject;
import java.util.Objects;
/**
* Service class for the AuthMe listeners to determine whether an event should be canceled.
*/
class ListenerService implements SettingsDependent {
private final AuthMeApi authmeApi = AuthMeApi.getInstance();
private final DataSource dataSource;
private final PlayerCache playerCache;
private final ValidationService validationService;
private boolean isRegistrationForced;
@Inject
ListenerService(Settings settings, DataSource dataSource, PlayerCache playerCache,
ValidationService validationService) {
@@ -76,9 +86,18 @@ class ListenerService implements SettingsDependent {
* @param player the player to verify
* @return true if the associated event should be canceled, false otherwise
*/
public boolean shouldCancelEvent(Player player) {
return player != null && !checkAuth(player.getName()) && !PlayerUtils.isNpc(player);
}
public boolean shouldCancelInvEvent(Player player) {
try {
return !AuthMe.GUIEnabled || authmeApi.isRegistered(player.getName()) || RegisterListener.closeReasonMap.containsKey(player)/* || !player.getOpenInventory().getTitle().equals("请验证你是真人")*/;
} catch (Exception e) {
return true;
}
}
@Override
public void reload(Settings settings) {
@@ -93,7 +112,7 @@ class ListenerService implements SettingsDependent {
* @return true if the player may play, false otherwise
*/
private boolean checkAuth(String name) {
if (validationService.isUnrestricted(name) || playerCache.isAuthenticated(name)) {
if (validationService.isUnrestricted(name) || playerCache.isAuthenticated(name)){
return true;
}
if (!isRegistrationForced && !dataSource.isAuthAvailable(name)) {
@@ -7,13 +7,11 @@ import fr.xephi.authme.initialization.Reloadable;
import fr.xephi.authme.message.MessageKey;
import fr.xephi.authme.message.Messages;
import fr.xephi.authme.output.ConsoleLoggerFactory;
import fr.xephi.authme.permission.AdminPermission;
import fr.xephi.authme.permission.PermissionsManager;
import fr.xephi.authme.permission.PlayerStatePermission;
import fr.xephi.authme.service.AntiBotService;
import fr.xephi.authme.service.BukkitService;
import fr.xephi.authme.service.ValidationService;
import fr.xephi.authme.service.WhiteListService;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.ProtectionSettings;
import fr.xephi.authme.settings.properties.RegistrationSettings;
@@ -48,8 +46,6 @@ public class OnJoinVerifier implements Reloadable {
@Inject
private AntiBotService antiBotService;
@Inject
private WhiteListService whiteListService;
@Inject
private ValidationService validationService;
@Inject
private BukkitService bukkitService;
@@ -85,18 +81,6 @@ public class OnJoinVerifier implements Reloadable {
throw new FailedVerificationException(MessageKey.KICK_ANTIBOT);
}
}
public void checkWhitelist(String name, boolean isAuthAvailable) throws FailedVerificationException {
if (isAuthAvailable || permissionsManager.hasPermissionOffline(name, PlayerStatePermission.WHITELIST)) {
return;
} else {
bukkitService.getOnlinePlayers().stream()
.filter(player -> permissionsManager.hasPermission(player, AdminPermission.WHITELIST_MESSAGE))
.forEach(player -> messages.send(player, MessageKey.WHITELIST_KICK, name));
}
if (whiteListService.shouldKick()) {
throw new FailedVerificationException(MessageKey.KICK_WHITELIST);
}
}
/**
* Checks whether non-registered players should be kicked, and if so, whether the player should be kicked.
@@ -1,5 +1,13 @@
package fr.xephi.authme.listener;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.events.ListenerPriority;
import com.comphenix.protocol.events.PacketAdapter;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.listener.RegisterListener;
import com.comphenix.protocol.events.PacketEvent;
import fr.xephi.authme.api.v3.AuthMeApi;
import fr.xephi.authme.data.QuickCommandsProtectionManager;
import fr.xephi.authme.data.auth.PlayerAuth;
import fr.xephi.authme.datasource.DataSource;
@@ -18,9 +26,12 @@ import fr.xephi.authme.settings.SpawnLoader;
import fr.xephi.authme.settings.properties.HooksSettings;
import fr.xephi.authme.settings.properties.RegistrationSettings;
import fr.xephi.authme.settings.properties.RestrictionSettings;
import fr.xephi.authme.settings.properties.SecuritySettings;
import fr.xephi.authme.util.TeleportUtils;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@@ -51,10 +62,15 @@ import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.event.player.PlayerShearEntityEvent;
import org.bukkit.event.player.PlayerSwapHandItemsEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryView;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.plugin.Plugin;
import javax.inject.Inject;
import java.util.Locale;
import java.util.Objects;
import java.util.Set;
import static fr.xephi.authme.settings.properties.RestrictionSettings.ALLOWED_MOVEMENT_RADIUS;
@@ -63,7 +79,11 @@ import static fr.xephi.authme.settings.properties.RestrictionSettings.ALLOW_UNAU
/**
* Listener class for player events.
*/
public class PlayerListener implements Listener {
public class PlayerListener implements Listener{
private final AuthMeApi authmeApi = AuthMeApi.getInstance();
@Inject
private Settings settings;
@@ -93,9 +113,12 @@ public class PlayerListener implements Listener {
private PermissionsManager permissionsManager;
@Inject
private QuickCommandsProtectionManager quickCommandsProtectionManager;
// Lowest priority to apply fast protection checks
@EventHandler(priority = EventPriority.LOWEST)
public void onAsyncPlayerPreLoginEventLowest(AsyncPlayerPreLoginEvent event) {
if (event.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) {
return;
}
@@ -111,8 +134,7 @@ public class PlayerListener implements Listener {
if (validationService.isUnrestricted(name)) {
return;
}
if (settings.getProperty(RestrictionSettings.HOOK_FLOODGATE_PLAYER) && org.geysermc.floodgate.api.FloodgateApi.getInstance().isFloodgateId(event.getUniqueId())){
if (settings.getProperty(HooksSettings.HOOK_FLOODGATE_PLAYER) && org.geysermc.floodgate.api.FloodgateApi.getInstance().isFloodgateId(event.getUniqueId())){
return;
}
// Non-blocking checks
@@ -121,8 +143,8 @@ public class PlayerListener implements Listener {
} catch (FailedVerificationException e) {
event.setKickMessage(messages.retrieveSingle(name, e.getReason(), e.getArgs()));
event.setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_OTHER);
}
}
}
/*
@@ -148,7 +170,6 @@ public class PlayerListener implements Listener {
final PlayerAuth auth = dataSource.getAuth(name);
final boolean isAuthAvailable = auth != null;
onJoinVerifier.checkKickNonRegistered(isAuthAvailable);
onJoinVerifier.checkWhitelist(name, isAuthAvailable);
onJoinVerifier.checkAntibot(name, isAuthAvailable);
onJoinVerifier.checkNameCasing(name, auth);
final String ip = event.getAddress().getHostAddress();
@@ -185,7 +206,7 @@ public class PlayerListener implements Listener {
@EventHandler(priority = EventPriority.NORMAL)
public void onPlayerJoin(PlayerJoinEvent event) {
final Player player = event.getPlayer();
final AuthMeApi authmeApi = AuthMeApi.getInstance();
if (!PlayerListener19Spigot.isPlayerSpawnLocationEventCalled()) {
teleportationService.teleportOnJoin(player);
}
@@ -195,12 +216,15 @@ public class PlayerListener implements Listener {
management.performJoin(player);
teleportationService.teleportNewPlayerToFirstSpawn(player);
}
@EventHandler(priority = EventPriority.HIGH) // HIGH as EssentialsX listens at HIGHEST
public void onJoinMessage(PlayerJoinEvent event) {
final Player player = event.getPlayer();
// Note: join message can be null, despite api documentation says not
if (settings.getProperty(RegistrationSettings.REMOVE_JOIN_MESSAGE)) {
event.setJoinMessage(null);
@@ -335,12 +359,12 @@ public class PlayerListener implements Listener {
}
/*
* Limit player X and Z movements to 1 block
* Limit player X and Z movements
* Deny player Y+ movements (allows falling)
*/
if (from.getBlockX() == to.getBlockX()
&& from.getBlockZ() == to.getBlockZ()
if (from.getX() == to.getX()
&& from.getZ() == to.getZ()
&& from.getY() - to.getY() >= 0) {
return;
}
@@ -363,9 +387,17 @@ public class PlayerListener implements Listener {
Location spawn = spawnLoader.getSpawnLocation(player);
if (spawn != null && spawn.getWorld() != null) {
if (!player.getWorld().equals(spawn.getWorld())) {
player.teleport(spawn);
if(AuthMe.SATEnabled) {
TeleportUtils.teleport(player,spawn);
} else {
player.teleport(spawn);
}
} else if (spawn.distance(player.getLocation()) > settings.getProperty(ALLOWED_MOVEMENT_RADIUS)) {
player.teleport(spawn);
if(AuthMe.SATEnabled) {
TeleportUtils.teleport(player,spawn);
} else {
player.teleport(spawn);
}
}
}
}
@@ -489,15 +521,16 @@ public class PlayerListener implements Listener {
return false;
}
Set<String> whitelist = settings.getProperty(RestrictionSettings.UNRESTRICTED_INVENTORIES);
//append a string for String whitelist
return whitelist.contains(ChatColor.stripColor(inventory.getTitle()).toLowerCase(Locale.ROOT));
}
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
public void onPlayerInventoryOpen(InventoryOpenEvent event) {
final HumanEntity player = event.getPlayer();
Player ply = (Player) event.getPlayer();
if (listenerService.shouldCancelEvent(player)
&& !isInventoryWhitelisted(event.getView())) {
&& !isInventoryWhitelisted(event.getView()) && listenerService.shouldCancelInvEvent(ply)) {
event.setCancelled(true);
/*
@@ -0,0 +1,31 @@
package fr.xephi.authme.listener;
//Prevent Ghost Players
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.plugin.Plugin;
import java.util.Objects;
public class PlayerQuitListener implements Listener {
private final Plugin plugin;
public PlayerQuitListener(Plugin plugin) {
this.plugin = plugin;
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent event) {
Player player = event.getPlayer();
String LastAddr = Objects.requireNonNull(player.getAddress()).getAddress().getHostAddress();
Bukkit.getScheduler().runTaskLater(plugin, new Runnable() {
@Override
public void run() {
if (player.isOnline()) {
player.kickPlayer("You have been disconnected.");
}
}
}, 20L); // 20 ticks = 1 second
}
}
@@ -0,0 +1,133 @@
package fr.xephi.authme.listener;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.events.ListenerPriority;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.events.PacketListener;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.api.v3.AuthMeApi;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.inventory.InventoryOpenEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.plugin.Plugin;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Random;
import java.util.UUID;
import java.util.logging.Level;
import static org.bukkit.Bukkit.getLogger;
public class RegisterListener implements Listener {
private final AuthMeApi authmeApi = AuthMeApi.getInstance();
private final Plugin plugin;
public static boolean enabled=true;
// 创建一个储存玩家关闭箱子GUI的原因的HashMap
public static HashMap<Player, String> closeReasonMap = new HashMap<>();
// Add a timer to kick the player if they don't verify in time
public RegisterListener(Plugin plugin) {
this.plugin = plugin;
}
@EventHandler
public void onInventoryClick(InventoryClickEvent event) {
if (event.getWhoClicked() instanceof Player) {
Player player = (Player) event.getWhoClicked();
ItemStack item = event.getCurrentItem();
// 获取点击事件的容器
Inventory inventory = event.getInventory();
if (event.getView().getTitle().equals("请验证你是真人")&&!authmeApi.isRegistered(player.getName())) {
if (Objects.requireNonNull(event.getCurrentItem()).getType().equals(Material.REDSTONE_BLOCK)) {
event.setCancelled(true);
closeReasonMap.put(player, "verified");
player.closeInventory();
player.sendMessage("§a验证完成");
//force to string
// ProtocolLibrary.getProtocolManager().removePacketListeners(this.plugin);
}
}
}
}
@EventHandler(ignoreCancelled = true,priority = EventPriority.HIGHEST)
public void onPlayerJoin(PlayerJoinEvent event) {
Random random_blockpos = new Random();
int random_num = random_blockpos.nextInt(26);
Inventory menu = Bukkit.createInventory(null, 27, "请验证你是真人");
ItemStack item = new ItemStack(Material.REDSTONE_BLOCK);
ItemMeta meta = item.getItemMeta();
if (meta != null) {
meta.setDisplayName("§a我是真人");
}
item.setItemMeta(meta);
menu.setItem(random_num, item);
Player playerunreg = event.getPlayer();
String name = playerunreg.getName();
if (!authmeApi.isRegistered(name)) {
// getLogger().log(Level.INFO, "TESTTEST");
Bukkit.getScheduler().runTaskLater(this.plugin, () -> {
playerunreg.openInventory(menu);
}, 1L);
ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(this.plugin, ListenerPriority.HIGHEST, PacketType.Play.Client.CLOSE_WINDOW) {
@Override
public void onPacketReceiving(PacketEvent event) {
if (event.getPlayer() == playerunreg && !closeReasonMap.containsKey(playerunreg)) {
playerunreg.sendMessage("§c请先完成验证!");
event.setCancelled(true);
Bukkit.getScheduler().runTask(plugin, () -> {
playerunreg.openInventory(menu);
//playerunreg.kickPlayer("§c请先完成人机验证!");
});
}
}
});
ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(this.plugin, ListenerPriority.HIGHEST, PacketType.Play.Client.CHAT) {
@Override
public void onPacketReceiving(PacketEvent event) {
if (event.getPlayer() == playerunreg && !closeReasonMap.containsKey(playerunreg)) {
playerunreg.sendMessage("§c请先完成验证!");
event.setCancelled(true);
}
}
});
// chatListener = new PacketAdapter(this.plugin, ListenerPriority.HIGHEST, PacketType.Play.Client.CHAT) {
// @Override
// public void onPacketReceiving(PacketEvent event) {
// if (event.getPlayer() == player) {
// event.setCancelled(true);
//
// }
// }
// };
}
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent event){
Player player = event.getPlayer();
String name = player.getName();
if (!authmeApi.isRegistered(name)){closeReasonMap.remove(player);}
}
}
@@ -114,10 +114,6 @@ class InventoryPacketAdapter extends PacketAdapter {
itemListModifier.write(0, Arrays.asList(blankInventory));
}
try {
protocolManager.sendServerPacket(player, inventoryPacket, false);
} catch (InvocationTargetException invocationExc) {
logger.logException("Error during sending blank inventory", invocationExc);
}
protocolManager.sendServerPacket(player, inventoryPacket, false);
}
}
@@ -16,9 +16,6 @@ public enum MessageKey {
/** AntiBot protection mode is enabled! You have to wait some minutes before joining the server. */
KICK_ANTIBOT("antibot.kick_antibot"),
KICK_WHITELIST("on_join_validation.kick_whitelist"),
WHITELIST_ENABLED_MESSAGE("misc.whitelist_enabled"),
WHITELIST_DISABLED_MESSAGE("misc.whitelist_disabled"),
/** This user isn't registered! */
UNKNOWN_USER("error.unregistered_user"),
@@ -38,6 +35,9 @@ public enum MessageKey {
/** In-game registration is disabled! */
REGISTRATION_DISABLED("registration.disabled"),
/** Logged-in due to Session Reconnection. */
SESSION_RECONNECTION("session.valid_session"),
/** Successful login! */
LOGIN_SUCCESS("login.success"),
@@ -80,6 +80,9 @@ public enum MessageKey {
/** The chosen password isn't safe, please choose another one... */
PASSWORD_UNSAFE_ERROR("password.unsafe_password"),
/** Your chosen password is not secure. It was used %pwned_count times already! Please use a stronger password... */
PASSWORD_PWNED_ERROR("password.pwned_password", "%pwned_count"),
/** Your password contains illegal characters. Allowed chars: %valid_chars */
PASSWORD_CHARACTERS_ERROR("password.forbidden_characters", "%valid_chars"),
@@ -199,7 +202,6 @@ public enum MessageKey {
/** [AntiBotService] AntiBot disabled after %m minutes! */
ANTIBOT_AUTO_DISABLED_MESSAGE("antibot.auto_disabled", "%m"),
WHITELIST_KICK("misc.whitelist_kick", "%p"),
/** The email address is already being used */
EMAIL_ALREADY_USED_ERROR("email.already_used"),
@@ -30,6 +30,7 @@ final class OldMessageKeysMigrater {
.put(MessageKey.WRONG_PASSWORD, "wrong_pwd")
.put(MessageKey.UNREGISTERED_SUCCESS, "unregistered")
.put(MessageKey.REGISTRATION_DISABLED, "reg_disabled")
.put(MessageKey.SESSION_RECONNECTION, "valid_session")
.put(MessageKey.ACCOUNT_NOT_ACTIVATED, "vb_nonActiv")
.put(MessageKey.NAME_ALREADY_REGISTERED, "user_regged")
.put(MessageKey.NO_PERMISSION, "no_perm")
@@ -124,7 +124,6 @@ public enum AdminPermission implements PermissionNode {
* Permission to see Antibot messages.
*/
ANTIBOT_MESSAGES("authme.admin.antibotmessages"),
WHITELIST_MESSAGE("authme.admin.whitelistmessage"),
/**
* Permission to use the update messages command.
@@ -10,7 +10,6 @@ public enum PlayerStatePermission implements PermissionNode {
* Permission node to bypass AntiBot protection.
*/
BYPASS_ANTIBOT("authme.bypassantibot", DefaultPermission.OP_ONLY),
WHITELIST("authme.whitelist", DefaultPermission.OP_ONLY),
/**
* Permission node to bypass BungeeCord server teleportation.
@@ -54,7 +54,7 @@ public class Management {
}
public void forceLogin(Player player) {
runTask(() -> asynchronousLogin.forceLogin(player,0));
runTask(() -> asynchronousLogin.forceLogin(player));
}
public void forceLogin(Player player, boolean quiet) {
@@ -19,7 +19,6 @@ import fr.xephi.authme.service.bungeecord.BungeeSender;
import fr.xephi.authme.service.bungeecord.MessageType;
import fr.xephi.authme.settings.commandconfig.CommandManager;
import fr.xephi.authme.settings.properties.HooksSettings;
import fr.xephi.authme.settings.properties.PluginSettings;
import fr.xephi.authme.settings.properties.RegistrationSettings;
import fr.xephi.authme.settings.properties.RestrictionSettings;
import fr.xephi.authme.util.InternetProtocolUtils;
@@ -129,16 +128,18 @@ public class AsynchronousJoin implements AsynchronousProcess {
// Session logic
if (sessionService.canResumeSession(player)) {
service.send(player, MessageKey.SESSION_RECONNECTION);
// Run commands
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(
() -> commandManager.runCommandsOnSessionLogin(player));
bukkitService.runTaskOptionallyAsync(() -> asynchronousLogin.forceLogin(player,service.getProperty(PluginSettings.HIDE_SESSIONS_LOGIN) ? 1 : 0));
bukkitService.runTaskOptionallyAsync(() -> asynchronousLogin.forceLogin(player));
return;
} else if (proxySessionManager.shouldResumeSession(name)) {
service.send(player, MessageKey.SESSION_RECONNECTION);
// Run commands
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(
() -> commandManager.runCommandsOnSessionLogin(player));
bukkitService.runTaskOptionallyAsync(() -> asynchronousLogin.forceLogin(player,service.getProperty(PluginSettings.HIDE_SESSIONS_LOGIN) ? 1 : 0));
bukkitService.runTaskOptionallyAsync(() -> asynchronousLogin.forceLogin(player));
logger.info("The user " + player.getName() + " has been automatically logged in, "
+ "as present in autologin queue.");
return;
@@ -102,7 +102,7 @@ public class AsynchronousLogin implements AsynchronousProcess {
limboService.getLimboPlayer(player.getName()).setState(LimboPlayerState.TOTP_REQUIRED);
// TODO #1141: Check if we should check limbo state before processing password
} else {
performLogin(player, auth, false);
performLogin(player, auth);
}
}
}
@@ -112,10 +112,10 @@ public class AsynchronousLogin implements AsynchronousProcess {
*
* @param player the player to log in
*/
public void forceLogin(Player player,int quiet) {
public void forceLogin(Player player) {
PlayerAuth auth = getPlayerAuth(player);
if (auth != null) {
performLogin(player, auth, quiet == 1);
performLogin(player, auth);
}
}
@@ -128,7 +128,7 @@ public class AsynchronousLogin implements AsynchronousProcess {
public void forceLogin(Player player, boolean quiet) {
PlayerAuth auth = getPlayerAuth(player, quiet);
if (auth != null) {
performLogin(player, auth, false);
performLogin(player, auth);
}
}
@@ -265,7 +265,7 @@ public class AsynchronousLogin implements AsynchronousProcess {
* @param player the player to log in
* @param auth the associated PlayerAuth object
*/
public void performLogin(Player player, PlayerAuth auth, boolean quiet) {
public void performLogin(Player player, PlayerAuth auth) {
if (player.isOnline()) {
boolean isFirstLogin = (auth.getLastLogin() == null);
@@ -284,7 +284,7 @@ public class AsynchronousLogin implements AsynchronousProcess {
tempbanManager.resetCount(ip, name);
player.setNoDamageTicks(0);
if (!quiet) {service.send(player, MessageKey.LOGIN_SUCCESS);}
service.send(player, MessageKey.LOGIN_SUCCESS);
// Other auths
List<String> auths = dataSource.getAllAuthsByIp(auth.getLastIp());
@@ -89,9 +89,9 @@ abstract class AbstractPasswordRegisterExecutor<P extends AbstractPasswordRegist
final Player player = params.getPlayer();
if (performLoginAfterRegister(params)) {
if (commonService.getProperty(PluginSettings.USE_ASYNC_TASKS)) {
bukkitService.runTaskAsynchronously(() -> asynchronousLogin.forceLogin(player,0));
bukkitService.runTaskAsynchronously(() -> asynchronousLogin.forceLogin(player));
} else {
bukkitService.scheduleSyncDelayedTask(() -> asynchronousLogin.forceLogin(player,0), SYNC_LOGIN_DELAY);
bukkitService.scheduleSyncDelayedTask(() -> asynchronousLogin.forceLogin(player), SYNC_LOGIN_DELAY);
}
}
syncProcessManager.processSyncPasswordRegister(player);
@@ -42,18 +42,21 @@ import java.util.zip.GZIPInputStream;
public class GeoIpService {
private static final String LICENSE =
"[LICENSE] This product includes GeoLite2 data created by MaxMind, available at https://www.maxmind.com";
//private static final String LICENSE =
//"[LICENSE] This product includes GeoLite2 data created by MaxMind, available at https://www.maxmind.com";
private static final String DATABASE_NAME = "GeoLite2-Country";
private static final String DATABASE_FILE = DATABASE_NAME + ".mmdb";
private final ConsoleLogger logger = ConsoleLoggerFactory.get(GeoIpService.class);
private final Path dataFile;
private GeoIp2Provider databaseReader;
private volatile boolean downloading;
@Inject
GeoIpService(@DataFolder File dataFolder) {
GeoIpService(@DataFolder File dataFolder){
this.dataFile = dataFolder.toPath().resolve(DATABASE_FILE);
// Fires download of recent data or the initialization of the look up service
@@ -86,27 +89,63 @@ public class GeoIpService {
if (Files.exists(dataFile)) {
try {
startReading();
// don't fire the update task - we are up to date
return true;
} catch (IOException ioEx) {
logger.logException("Failed to load GeoLiteAPI database", ioEx);
return false;
}
}
// File is outdated or doesn't exist - let's try to download the data file!
// use bukkit's cached threads
return false;
}
/**
*
*/
private void startReading() throws IOException {
databaseReader = new Reader(dataFile.toFile(), FileMode.MEMORY, new CHMCache());
logger.info(LICENSE);
// clear downloading flag, because we now have working reader instance
downloading = false;
}
/**
* Downloads the archive to the destination file if it's newer than the locally version.
*
* @param lastModified modification timestamp of the already present file
* @param destination save file
* @return null if no updates were found, the MD5 hash of the downloaded archive if successful
* @throws IOException if failed during downloading and writing to destination file
*/
/**
* Downloads the archive to the destination file if it's newer than the locally version.
*
* @param destination save file
* @return null if no updates were found, the MD5 hash of the downloaded archive if successful
* @throws IOException if failed during downloading and writing to destination file
*/
/**
* Verify if the expected checksum is equal to the checksum of the given file.
*
* @param function the checksum function like MD5, SHA256 used to generate the checksum from the file
* @param file the file we want to calculate the checksum from
* @param expectedChecksum the expected checksum
* @throws IOException on I/O error reading the file or the checksum verification failed
*/
/**
* Extract the database from gzipped data. Existing outputFile will be replaced if it already exists.
*
* @param inputFile gzipped database input file
* @param outputFile destination file for the database
* @throws IOException on I/O error reading the archive, or writing the output
*/
/**
* Get the country code of the given IP address.
*
@@ -11,6 +11,7 @@ import fr.xephi.authme.message.MessageKey;
import fr.xephi.authme.output.ConsoleLoggerFactory;
import fr.xephi.authme.permission.PermissionsManager;
import fr.xephi.authme.permission.PlayerStatePermission;
import fr.xephi.authme.security.HashUtils;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.EmailSettings;
import fr.xephi.authme.settings.properties.ProtectionSettings;
@@ -21,6 +22,11 @@ import fr.xephi.authme.util.Utils;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.io.DataInputStream;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.net.URL;
import java.util.Arrays;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import java.net.InetSocketAddress;
@@ -28,6 +34,7 @@ import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.concurrent.TimeoutException;
import java.util.regex.Pattern;
import static fr.xephi.authme.util.StringUtils.isInsideString;
@@ -84,7 +91,15 @@ public class ValidationService implements Reloadable {
return new ValidationResult(MessageKey.INVALID_PASSWORD_LENGTH);
} else if (settings.getProperty(SecuritySettings.UNSAFE_PASSWORDS).contains(passLow)) {
return new ValidationResult(MessageKey.PASSWORD_UNSAFE_ERROR);
} else if (settings.getProperty(SecuritySettings.HAVE_I_BEEN_PWNED_CHECK)) {
HaveIBeenPwnedResults results = validatePasswordHaveIBeenPwned(password);
if (results != null
&& results.isPwned()
&& results.getPwnCount() > settings.getProperty(SecuritySettings.HAVE_I_BEEN_PWNED_LIMIT)) {
return new ValidationResult(MessageKey.PASSWORD_PWNED_ERROR, String.valueOf(results.getPwnCount()));
}
}
return new ValidationResult();
}
@@ -225,6 +240,47 @@ public class ValidationService implements Reloadable {
}
return restrictions;
}
/**
* Check haveibeenpwned.com for the given password.
*
* @param password password to check for
* @return Results of the check
*/
public HaveIBeenPwnedResults validatePasswordHaveIBeenPwned(String password) {
String hash = HashUtils.sha1(password);
String hashPrefix = hash.substring(0, 5);
try {
String url = String.format("https://api.pwnedpasswords.com/range/%s", hashPrefix);
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("User-Agent", "AuthMeReloaded");
connection.setConnectTimeout(5000);
connection.setReadTimeout(5000);
connection.setDoInput(true);
StringBuilder outStr = new StringBuilder();
try (DataInputStream input = new DataInputStream(connection.getInputStream())) {
for (int c = input.read(); c != -1; c = input.read())
outStr.append((char) c);
}
String[] hashes = outStr.toString().split("\n");
for (String hashSuffix : hashes) {
String[] hashSuffixParts = hashSuffix.trim().split(":");
if (hashSuffixParts[0].equalsIgnoreCase(hash.substring(5))) {
return new HaveIBeenPwnedResults(true, Integer.parseInt(hashSuffixParts[1]));
}
}
return new HaveIBeenPwnedResults(false, 0);
} catch (java.io.IOException e) {
logger.warning("验证密码时出现错误,这可能是由于网络问题,如果无法解决,请关闭HaveIBeenPwned检查");
}
return null;
}
public static final class ValidationResult {
private final MessageKey messageKey;
@@ -266,4 +322,22 @@ public class ValidationService implements Reloadable {
return args;
}
}
public static final class HaveIBeenPwnedResults {
private final boolean isPwned;
private final int pwnCount;
public HaveIBeenPwnedResults(boolean isPwned, int pwnCount) {
this.isPwned = isPwned;
this.pwnCount = pwnCount;
}
public boolean isPwned() {
return isPwned;
}
public int getPwnCount() {
return pwnCount;
}
}
}
@@ -1,82 +0,0 @@
package fr.xephi.authme.service;
import fr.xephi.authme.initialization.SettingsDependent;
import fr.xephi.authme.message.MessageKey;
import fr.xephi.authme.message.Messages;
import fr.xephi.authme.permission.AdminPermission;
import fr.xephi.authme.permission.PermissionsManager;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.ProtectionSettings;
import org.bukkit.scheduler.BukkitTask;
import javax.inject.Inject;
import java.util.Locale;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* The AntiBot Service Management class.
*/
public class WhiteListService implements SettingsDependent {
private final PermissionsManager permissionsManager;
private final Messages messages;
private final BukkitService bukkitService;
private WhiteListStatus whiteListStatus;
@Inject
WhiteListService(Settings settings, Messages messages, PermissionsManager permissionsManager,
BukkitService bukkitService) {
// Instances
this.messages = messages;
this.permissionsManager = permissionsManager;
this.bukkitService = bukkitService;
// Initial status
whiteListStatus = WhiteListStatus.DISABLED;
// Load settings and start if required
reload(settings);
}
@Override
public void reload(Settings settings) {
}
private void startProtection() {
if (whiteListStatus == WhiteListStatus.ACTIVE) {
return;
}
whiteListStatus = WhiteListStatus.ACTIVE;
bukkitService.getOnlinePlayers().stream()
.filter(player -> permissionsManager.hasPermission(player, AdminPermission.WHITELIST_MESSAGE))
.forEach(player -> messages.send(player, MessageKey.WHITELIST_ENABLED_MESSAGE));
}
private void stopProtection() {
if (whiteListStatus == WhiteListStatus.DISABLED) {
return;
}
whiteListStatus = WhiteListStatus.DISABLED;
bukkitService.getOnlinePlayers().stream()
.filter(player -> permissionsManager.hasPermission(player, AdminPermission.WHITELIST_MESSAGE))
.forEach(player -> messages.send(player, MessageKey.WHITELIST_DISABLED_MESSAGE));
}
public WhiteListStatus getWhiteListStatus() {
return whiteListStatus;
}
public void overrideWhiteListStatus(boolean started) {
if (started) {
startProtection();
} else {
stopProtection();
}
}
public boolean shouldKick() {
return whiteListStatus != WhiteListStatus.DISABLED;
}
public enum WhiteListStatus {
DISABLED,
ACTIVE
}
}
@@ -19,6 +19,11 @@ public final class HooksSettings implements SettingsHolder {
public static final Property<Boolean> BUNGEECORD =
newProperty("Hooks.bungeecord", false);
@Comment("Allow FloodGatePlayer Join Without checkIsValidName()")
public static final Property<Boolean> HOOK_FLOODGATE_PLAYER =
newProperty("Hooks.floodgate", false);
@Comment("Send player to this BungeeCord server after register/login")
public static final Property<String> BUNGEECORD_SERVER =
newProperty("Hooks.sendPlayerTo", "");
@@ -20,12 +20,6 @@ public final class PluginSettings implements SettingsHolder {
public static final Property<Boolean> SESSIONS_ENABLED =
newProperty("settings.sessions.enabled", true);
@Comment({
"Do you want to hide login success message to player?"
})
public static final Property<Boolean> HIDE_SESSIONS_LOGIN =
newProperty("settings.sessions.hidelogin", true);
@Comment({
"After how many minutes should a session expire?",
"A player's session ends after the timeout or if his IP has changed"
@@ -19,9 +19,7 @@ public final class ProtectionSettings implements SettingsHolder {
@Comment("Apply the protection also to registered usernames")
public static final Property<Boolean> ENABLE_PROTECTION_REGISTERED =
newProperty("Protection.enableProtectionRegistered", true);
@Comment("Only allow registed usernames join server")
public static final Property<Boolean> ENABLE_WHITELIST =
newProperty("Protection.enableWhiteList", true);
@Comment({
"Countries allowed to join the server and register. For country codes, see",
"https://dev.maxmind.com/geoip/legacy/codes/iso3166/",
@@ -18,7 +18,7 @@ public final class RegistrationSettings implements SettingsHolder {
"Send every X seconds a message to a player to",
"remind him that he has to login/register"})
public static final Property<Integer> MESSAGE_INTERVAL =
newProperty("settings.registration.messageInterval", 600);
newProperty("settings.registration.messageInterval", 5);
@Comment({
"Only registered and logged in players can play.",
@@ -33,7 +33,7 @@ public final class RegistrationSettings implements SettingsHolder {
"More info at https://github.com/AuthMe/AuthMeReloaded/wiki/Registration"
})
public static final Property<RegistrationType> REGISTRATION_TYPE =
newProperty(RegistrationType.class, "settings.registration.type", RegistrationType.EMAIL);
newProperty(RegistrationType.class, "settings.registration.type", RegistrationType.PASSWORD);
@Comment({
"Second argument the /register command should take: ",
@@ -44,7 +44,7 @@ public final class RegistrationSettings implements SettingsHolder {
})
public static final Property<RegisterSecondaryArgument> REGISTER_SECOND_ARGUMENT =
newProperty(RegisterSecondaryArgument.class, "settings.registration.secondArg",
RegisterSecondaryArgument.NONE);
RegisterSecondaryArgument.CONFIRMATION);
@Comment({
"Do we force kick a player after a successful registration?",
@@ -4,6 +4,8 @@ import ch.jalu.configme.Comment;
import ch.jalu.configme.SettingsHolder;
import ch.jalu.configme.properties.Property;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -113,21 +115,19 @@ public final class RestrictionSettings implements SettingsHolder {
@Comment("Can unregistered players walk around?")
public static final Property<Boolean> ALLOW_UNAUTHED_MOVEMENT =
newProperty("settings.restrictions.allowMovement", true);
newProperty("settings.restrictions.allowMovement", false);
@Comment({
"After how many seconds should players who fail to login or register",
"be kicked? Set to 0 to disable."})
public static final Property<Integer> TIMEOUT =
newProperty("settings.restrictions.timeout", 0);
newProperty("settings.restrictions.timeout", 120);
@Comment("Regex pattern of allowed characters in the player name.")
public static final Property<String> ALLOWED_NICKNAME_CHARACTERS =
newProperty("settings.restrictions.allowedNicknameCharacters", "[a-zA-Z0-9_]*");
@Comment("Allow FloodGatePlayer Join Without checkIsValidName()")
public static final Property<Boolean> HOOK_FLOODGATE_PLAYER =
newProperty("settings.restrictions.hookFloodGatePlayer", false);
@Comment({
"How far can unregistered players walk?",
"Set to 0 for unlimited radius"
@@ -163,7 +163,7 @@ public final class RestrictionSettings implements SettingsHolder {
@Comment("AuthMe will NEVER teleport players if set to true!")
public static final Property<Boolean> NO_TELEPORT =
newProperty("settings.restrictions.noTeleport", true);
newProperty("settings.restrictions.noTeleport", false);
@Comment({
"Regex syntax for allowed chars in passwords. The default [!-~] allows all visible ASCII",
@@ -175,7 +175,7 @@ public final class RestrictionSettings implements SettingsHolder {
@Comment("Regex syntax for allowed chars in email.")
public static final Property<String> ALLOWED_EMAIL_REGEX =
newProperty("settings.restrictions.allowedEmailCharacters", "^[A-Za-z0-9]{4,15}@(outlook|163|gmail|icloud).com$");
newProperty("settings.restrictions.allowedEmailCharacters", "^[A-Za-z0-9]{4,15}@(qq|outlook|163|gmail|icloud).com$");
@Comment("Force survival gamemode when player joins?")
@@ -194,6 +194,7 @@ public final class RestrictionSettings implements SettingsHolder {
public static final Property<Set<String>> UNRESTRICTED_NAMES =
newLowercaseStringSetProperty("settings.unrestrictions.UnrestrictedName");
@Comment({
"Below you can list all inventories names that AuthMe will ignore",
"for registration or login. Configure it at your own risk!!",
@@ -206,7 +207,9 @@ public final class RestrictionSettings implements SettingsHolder {
public static final Property<Set<String>> UNRESTRICTED_INVENTORIES =
newLowercaseStringSetProperty("settings.unrestrictions.UnrestrictedInventories");
private RestrictionSettings() {
}
}
@@ -2,12 +2,12 @@ package fr.xephi.authme.settings.properties;
import ch.jalu.configme.Comment;
import ch.jalu.configme.SettingsHolder;
import ch.jalu.configme.properties.BooleanProperty;
import ch.jalu.configme.properties.Property;
import fr.xephi.authme.security.HashAlgorithm;
import fr.xephi.authme.settings.EnumSetProperty;
import java.util.Set;
import fr.xephi.authme.listener.PlayerQuitListener;
import static ch.jalu.configme.properties.PropertyInitializer.newLowercaseStringSetProperty;
import static ch.jalu.configme.properties.PropertyInitializer.newProperty;
@@ -19,14 +19,50 @@ public final class SecuritySettings implements SettingsHolder {
public static final Property<Boolean> STOP_SERVER_ON_PROBLEM =
newProperty("Security.SQLProblem.stopServer", true);
@Comment("Enable the new feature to prevent ghost players?")
public static final Property<Boolean> ANTI_GHOST_PLAYERS = newProperty("3rdPartyFeature.fixes.antiGhostPlayer", false);
@Comment({"(BETA Feature)Choose the best teleport method by server brand?",
"(Enable this if you are using Paper)"})
public static final Property<Boolean> SMART_ASYNC_TELEPORT = newProperty("3rdPartyFeature.optimizes.smartAsyncTeleport",false);
@Comment("(BETA Feature)Send a GUI captcha to unregistered players?")
public static final Property<Boolean> GUI_CAPTCHA = newProperty("3rdPartyFeature.captcha.guiCaptcha",false);
// @Comment({"Kick the players when they didn't finish the gui captcha in time? " ,
// "(0 is disabled)"})
// public static final Property<Integer> CAPTCHA_TIMEOUT = newProperty("3rdPartyFeature.captcha.timeout",0);
//@Comment({"Using which API to get hash data?",
//"Available options: github, gitee, ghproxy (if your server is in China, please use gitee or ghproxy.)"})
//public static final Property<String> SHA_CHECK_METHOD = newProperty("Plugin.hashing.hashApi","github");
//@Comment("Should we use the local cache sometimes instead of requesting API?")
//public static final Property<Boolean> USE_LOCAL_CACHE = newProperty("Plugin.hashing.useLocalCache",false);
//@Comment("DON'T TOUCH!!!")
//public static final Property<String> SHA_CHECK_CACHE = newProperty("Plugin.hashing.hashCached","");
@Comment("Copy AuthMe log output in a separate file as well?")
public static final Property<Boolean> USE_LOGGING =
newProperty("Security.console.logConsole", true);
@Comment({"Query haveibeenpwned.com with a hashed version of the password.",
"This is used to check whether it is safe."})
public static final Property<Boolean> HAVE_I_BEEN_PWNED_CHECK =
newProperty("Security.account.haveIBeenPwned.check", false);
@Comment({"If the password is used more than this number of times, it is considered unsafe."})
public static final Property<Integer> HAVE_I_BEEN_PWNED_LIMIT =
newProperty("Security.account.haveIBeenPwned.limit", 0);
@Comment("Enable captcha when a player uses wrong password too many times")
public static final Property<Boolean> ENABLE_LOGIN_FAILURE_CAPTCHA =
newProperty("Security.captcha.useCaptcha", false);
@Comment("Check for updates on enabled from GitHub?")
public static final Property<Boolean> CHECK_FOR_UPDATES =
newProperty("Plugin.updates.checkForUpdates", true);
@Comment("Max allowed tries before a captcha is required")
public static final Property<Integer> MAX_LOGIN_TRIES_BEFORE_CAPTCHA =
newProperty("Security.captcha.maxLoginTry", 8);
@@ -0,0 +1,55 @@
package fr.xephi.authme.util;
import fr.xephi.authme.ConsoleLogger;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import javax.inject.Inject;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.logging.Level;
import java.util.logging.Logger;
//
//public class TeleportUtils {
// public static void teleport(Player player, Location location) {
// try {
// Class<?> paperClass = Class.forName("com.destroystokyo.paper.PaperConfig");
// // Paper API is loaded, use teleportAsync
// Method teleportAsyncMethod = player.getClass().getMethod("teleportAsync", Location.class);
// teleportAsyncMethod.setAccessible(true);
// teleportAsyncMethod.invoke(player, location);
// } catch (ClassNotFoundException | InvocationTargetException | NoSuchMethodException | IllegalAccessException e) {
// // Paper API is not loaded, use normal teleport
// player.teleport(location);
// }
// }
//}
public class TeleportUtils {
private static Method teleportAsyncMethod;
static {
try {//Detect Paper class
Class<?> paperClass = Class.forName("com.destroystokyo.paper.PaperConfig");
teleportAsyncMethod = Player.class.getMethod("teleportAsync", Location.class);
// if detected,use teleportAsync()
} catch (ClassNotFoundException | NoSuchMethodException e) {
teleportAsyncMethod = null;
//if not, set method to null
}
}
public static void teleport(Player player, Location location) {
if (teleportAsyncMethod != null) {
try {
teleportAsyncMethod.setAccessible(true);
teleportAsyncMethod.invoke(player, location);
} catch (IllegalAccessException | InvocationTargetException e) {
player.teleport(location);
}
} else {
player.teleport(location);
}
}
}
+1 -4
View File
@@ -41,10 +41,7 @@
# executor: CONSOLE
# ifNumberOfAccountsAtLeast: 5
# Commands to run for players logging in whose 'last login date' was empty
onFirstLogin:
broadcast:
command: 'cmi broadcast &b欢迎 &r%p &7( %ip ) &b光临服务器,请大家多多关照!'
executor: CONSOLE
onFirstLogin: {}
onJoin: {}
onLogin: {}
# These commands are called whenever a logged in player uses /logout or quits.
+2 -2
View File
@@ -102,8 +102,8 @@
<tbody>
<tr>
<td>
<p style="color:#b0adc5;">© 2023 IrisCraft. All rights reserved.</p>
<a href="https://www.mcbbs.net/thread-1263385-1-1.html" target="_blank" style="text-decoration: none; font-size: 16px">iriscraft.work</a>
<p style="color:#b0adc5;">© 2023 HomoCraft. All rights reserved.</p>
<a href="1919810.com" target="_blank" style="text-decoration: none; font-size: 16px">homomc.cc</a>
</td>
</tr>
</tbody>
+1 -1
View File
@@ -66,7 +66,7 @@ misc:
# Session messages
session:
valid_session: '&2Сесията е продължена.'
invalid_session: '&cТвоят IP се е променил и сесията беше прекратена.'
# Error messages when joining
+1 -1
View File
@@ -69,7 +69,7 @@ misc:
# Mensagens de sessão
session:
valid_session: '&2Você deslogou recentemente, então sua sessão foi retomada!'
invalid_session: '&fO seu IP foi alterado e sua sessão expirou!'
# Mensagens de erro ao entrar
+1 -1
View File
@@ -66,7 +66,7 @@ misc:
# Session messages
session:
valid_session: '&cAutomatické znovupřihlášení.'
invalid_session: '&cChyba: Počkej než vyprší tvoje relace.'
# Error messages when joining
+1 -1
View File
@@ -66,7 +66,7 @@ misc:
# Session messages
session:
valid_session: '&2Erfolgreich eingeloggt!'
invalid_session: '&cUngültige Session. Bitte starte das Spiel neu oder warte, bis die Session abgelaufen ist.'
# Error messages when joining
+2 -1
View File
@@ -20,6 +20,7 @@ password:
unsafe_password: '&cThe chosen password isn''t safe, please choose another one...'
forbidden_characters: '&4Your password contains illegal characters. Allowed chars: %valid_chars'
wrong_length: '&cYour password is too short or too long! Please try with another one!'
pwned_password: '&cYour chosen password is not secure. It was used %pwned_count times already! Please use a strong password...'
# Login
login:
@@ -66,7 +67,7 @@ misc:
# Session messages
session:
invalid_session: '&cYour IP has been changed and your session data has expired!'
valid_session: '&2Logged-in due to Session Reconnection.'
# Error messages when joining
on_join_validation:
+1 -1
View File
@@ -66,7 +66,7 @@ misc:
# Session messages
session:
valid_session: '&2Ensalutantojn pro Sesio Rekonektas.'
invalid_session: '&cVia IP estis ŝanĝita kaj via seanco datumoj finiĝis!'
# Error messages when joining
+1 -1
View File
@@ -67,7 +67,7 @@ misc:
# Session messages
session:
valid_session: '&cInicio de sesión'
invalid_session: '&fLos datos de sesión no corresponden. Por favor espera a terminar la sesión.'
# Error messages when joining
+1 -1
View File
@@ -66,7 +66,7 @@ misc:
# Session messages
session:
invalid_session: '&cSinu IP-aadress muutus, seega sinu sessioon aegus!'
valid_session: '&2Sisse logitud sessiooni jätkumise tõttu.'
# Error messages when joining
on_join_validation:
+1 -1
View File
@@ -66,7 +66,7 @@ misc:
# Session messages
session:
valid_session: '&cSesioa mantendu eta beraz ez daukazu saioa hasi beharrik.'
invalid_session: '&cZure IP helbidea aldatu da, eta horregatik zure sesioa iraungi da!'
# Error messages when joining
+1 -1
View File
@@ -66,7 +66,7 @@ misc:
# Session messages
session:
valid_session: '&cIstunto jatkettu!'
invalid_session: '&fIstunto ei täsmää! Ole hyvä ja odota istunnon loppuun'
# Error messages when joining
+1 -1
View File
@@ -69,7 +69,7 @@ misc:
# Session
session:
valid_session: '&aVous avez été automatiquement connecté !'
invalid_session: 'Session expirée suite à un changement d''IP.'
# Erreurs lors d'une tentative connexion
+1 -1
View File
@@ -66,7 +66,7 @@ misc:
# Session messages
session:
valid_session: '&cIdentificado mediante a sesión'
invalid_session: '&fOs datos de sesión non corresponden, por favor, espere a que remate a sesión'
# Error messages when joining
+1 -1
View File
@@ -66,7 +66,7 @@ misc:
# Session messages
session:
valid_session: '&2A megadott időkereten belül csatlakoztál vissza, így a rendszer automatikusan beléptetett.'
invalid_session: '&cAz IP címed megváltozott, ezért a visszacsatlakozási időkereted lejárt.'
# Error messages when joining
+1 -1
View File
@@ -66,7 +66,7 @@ misc:
# Session messages
session:
valid_session: '&2Otomatis login, karena sesi masih terhubung.'
invalid_session: '&cIP kamu telah berubah, dan sesi kamu telah berakhir!'
# Error messages when joining
+1 -1
View File
@@ -67,7 +67,7 @@ misc:
# Session messages
session:
valid_session: '&2Autenticato automaticamente attraverso la precedente sessione!'
invalid_session: '&cIl tuo indirizzo IP è cambiato e la tua sessione è stata terminata!'
# Error messages when joining
+1 -1
View File
@@ -68,7 +68,7 @@ misc:
# Session messages
session:
valid_session: '&2세션 재 연결로 인해 로그인 되었습니다.'
invalid_session: '&cIP가 변경되어 세션이 만료되었습니다!'
# Error messages when joining
+1 -1
View File
@@ -66,7 +66,7 @@ misc:
# Session messages
session:
valid_session: '&aSesijos prisijungimas'
invalid_session: '&cSesijos laikai nesutampa, prasome palaukti kol secija baigsis.'
# Error messages when joining
+1 -1
View File
@@ -66,7 +66,7 @@ misc:
# Session messages
session:
valid_session: '&2Ingelogd wegens sessie-herverbinding.'
invalid_session: '&cJouw IP-adres is veranderd en je sessie is verlopen!'
# Error messages when joining
+1 -1
View File
@@ -66,7 +66,7 @@ misc:
# Session messages
session:
valid_session: '&aZalogowano automatycznie z powodu sesji logowania.'
invalid_session: '&fSesja logowania zakończona!'
# Error messages when joining
+1 -1
View File
@@ -66,7 +66,7 @@ misc:
# Session messages
session:
valid_session: '&cSessão válida'
invalid_session: '&fDados de sessão não correspondem. Por favor aguarde o fim da sessão'
# Error messages when joining
+1 -1
View File
@@ -66,7 +66,7 @@ misc:
# Session messages
session:
invalid_session: '&cIP-ul tau a fost schimbat si sesiunea ta a expirat!'
valid_session: '&2Conectat datorita reconectarii sesiunii.'
# Error messages when joining
on_join_validation:
+1 -1
View File
@@ -61,7 +61,7 @@ misc:
# Session messages
session:
valid_session: '&2Вы автоматически авторизовались!'
invalid_session: '&cСессия некорректна. Дождитесь, пока она закончится.'
# Error messages when joining
+2 -1
View File
@@ -65,7 +65,7 @@ misc:
# Session messages
session:
valid_session: '&2Uspešna povezava.'
invalid_session: '&cVas IP je bil spremenjen in vasa seja je potekla!'
# Error messages when joining
@@ -154,3 +154,4 @@ time:
hours: 'ure'
day: 'dan'
days: 'dni'
+1 -1
View File
@@ -72,7 +72,7 @@ misc:
# Session messages
session:
valid_session: '&cAutomatické prihlásenie z dôvodu pokračovania relácie.'
invalid_session: '&fTvoja IP sa zmenila a tvoje prihlásenie(relácia) vypršalo(/a).'
# Error messages when joining
+1 -1
View File
@@ -66,7 +66,7 @@ misc:
# Session messages
session:
valid_session: '&2Ulogovani ste zbog ponovnog povezivanja sesije.'
invalid_session: '&cVaš IP je promenjen i vaši podaci o sesiji su istekli!'
# Error messages when joining
+1 -1
View File
@@ -66,7 +66,7 @@ misc:
# Session messages
session:
valid_session: '&2Oturuma girisiniz otomatikmen yapilmistir.'
invalid_session: '&cIP adresin degistirildi ve oturum suren doldu!'
# Error messages when joining
+1 -1
View File
@@ -66,7 +66,7 @@ misc:
# Session messages
session:
valid_session: '&2Сесію відновлено.'
invalid_session: '&cСесію було розірвано внаслідок зміни IP.'
# Error messages when joining
+1 -1
View File
@@ -66,7 +66,7 @@ misc:
# Session messages
session:
valid_session: '&2Phiên đăng nhập đã được kết nối trở lại.'
invalid_session: '&cIP của bạn đã bị thay đổi và phiên đăng nhập của bạn đã hết hạn!'
# Error messages when joining
+7 -11
View File
@@ -7,8 +7,8 @@
registration:
disabled: '&c注册已被禁止'
name_taken: '&c此用户已经在此服务器注册过'
register_request: '&7请输入“/register <邮箱>”以注册'
command_usage: '&c正确用法:“/register <邮箱>”'
register_request: '&b请输入“&a/reg <密码> <重复密码>&b”以注册'
command_usage: '&c正确用法:“/reg <密码> <重复密码>”'
reg_only: '&c只允许注册过的玩家进服!'
success: '&a*** 已成功注册 ***'
@@ -19,13 +19,14 @@ password:
unsafe_password: '&c您不能使用安全性过低的密码。 '
forbidden_characters: '&4您的密码包含了非法字符.可使用的字符: %valid_chars'
wrong_length: '&4您的密码没有达到要求!'
pwned_password: '&c你使用的密码并不安全。它已经被使用了 %pwned_count 次! 请使用一个更强大的密码...'
# Login
login:
command_usage: '&c正确用法:“/login <密码>”'
command_usage: '&c正确用法:“/l <密码>”'
wrong_password: '&c*** 密码错误 ***'
success: '&a*** 已成功登录 ***'
login_request: '&c请输入“/login <密码>”以登录'
login_request: '&c请输入“/l <密码>”以登录'
timeout_error: '给您登录的时间已经过了'
# Errors
@@ -65,12 +66,10 @@ misc:
usage_change_password: '&a正确用法:“/changepassword 旧密码 新密码”'
accounts_owned_self: '您拥有 %count 个账户:'
accounts_owned_other: '玩家 %name 拥有 %count 个账户:'
whitelist_enabled: '&c*** 服务器已暂停注册 ***'
whitelist_disabled: '&a*** 服务器已开放注册 ***'
whitelist_kick: '&7玩家 &c%p &7请求加入服务器,但是被拒绝了.'
# Session messages
session:
valid_session: ''
invalid_session: '&c*** 请重新登录 ***'
# Error messages when joining
@@ -90,10 +89,7 @@ on_join_validation:
&c如果您并不知情,请更换您的用户名重新加入该服务器.
invalid_name_case: '&c您应该使用 %valid 登录服务器,当前名字: %invalid .'
quick_command: '&c您发送命令的速度太快了,请重新加入服务器等待一会后再使用命令'
kick_whitelist: |-
&6[&b&lAccount Security System&6]
&c本服务器已经暂停注册,请用下面的联系方式了解详细情况.
&cQQ群聊号码: 550984860 &b| &c QQ: 2125368097 &b| &cTelegram: @Stabrinai
# Email
email:
add_email_request: ''
@@ -69,7 +69,7 @@ misc:
# Session messages
session:
valid_session: '&8[&6用戶系統&8] &b嗨 歡迎回來喔~'
invalid_session: '&8[&6用戶系統&8] &f登入階段資料已損壞,請等待登入階段結束。'
# Error messages when joining
@@ -66,7 +66,7 @@ misc:
# Session messages
session:
valid_session: '&2由於會話重新連接而登錄.'
invalid_session: '&c您的IP已更改,並且您的會話數據已過期!'
# Error messages when joining
@@ -68,7 +68,7 @@ misc:
# Session messages
session:
valid_session: '&b【AuthMe】&6您已經成功登入!'
invalid_session: '&b【AuthMe】&6Session驗證不相符!'
# Error messages when joining
+2 -2
View File
@@ -108,8 +108,8 @@
<tbody>
<tr>
<td>
<p style="color:#b0adc5;">© 2023 IrisCraft. All rights reserved.</p>
<a href="https://www.mcbbs.net/thread-1263385-1-1.html" target="_blank" style="text-decoration: none; font-size: 16px">iriscraft.work</a>
<p style="color:#b0adc5;">© 2023 HomoCraft. All rights reserved.</p>
<a href="1919810.com" target="_blank" style="text-decoration: none; font-size: 16px">homomc.cc</a>
</td>
</tr>
</tbody>
+3 -7
View File
@@ -1,9 +1,9 @@
name: ${pluginDescription.name}
authors: [${pluginDescription.authors}]
website: ${project.url}
description: ${project.description}
website: http://github.com/HaHaWTH/AuthMeReReloaded/
description: A fork of AuthMeReloaded that contains bug fixes
main: ${pluginDescription.main}
version: ${pluginDescription.version}
version: 5.6.0-FORK-b17
api-version: 1.13
softdepend:
- Vault
@@ -28,7 +28,6 @@ commands:
usage: /login <password>
aliases:
- l
- log
logout:
description: Logout command
usage: /logout
@@ -184,9 +183,6 @@ permissions:
authme.bypassantibot:
description: Permission node to bypass AntiBot protection.
default: op
authme.whitelist:
description: Permission node to whitelist.
default: op
authme.bypasscountrycheck:
description: Permission to bypass the GeoIp country code check.
default: false
+2 -2
View File
@@ -101,8 +101,8 @@
<tbody>
<tr>
<td>
<p style="color:#b0adc5;">© 2023 IrisCraft. All rights reserved.</p>
<a href="https://www.mcbbs.net/thread-1263385-1-1.html" target="_blank" style="text-decoration: none; font-size: 16px">iriscraft.work</a>
<p style="color:#b0adc5;">© 2023 HomoCraft. All rights reserved.</p>
<a href="191980.com" target="_blank" style="text-decoration: none; font-size: 16px">homomc.cc</a>
</td>
</tr>
</tbody>
+2 -2
View File
@@ -99,8 +99,8 @@
<tbody>
<tr>
<td>
<p style="color:#b0adc5;">© 2023 IrisCraft. All rights reserved.</p>
<a href="https://www.mcbbs.net/thread-1263385-1-1.html" target="_blank" style="text-decoration: none; font-size: 16px">iriscraft.work</a>
<p style="color:#b0adc5;">© 2023 HomoCraft. All rights reserved.</p>
<a href="1919810.com" target="_blank" style="text-decoration: none; font-size: 16px">homomc.cc</a>
</td>
</tr>
</tbody>
@@ -101,8 +101,8 @@
<tbody>
<tr>
<td>
<p style="color:#b0adc5;">© 2023 IrisCraft. All rights reserved.</p>
<a href="https://www.mcbbs.net/thread-1263385-1-1.html" target="_blank" style="text-decoration: none; font-size: 16px">iriscraft.work</a>
<p style="color:#b0adc5;">© 2023 HomoCraft. All rights reserved.</p>
<a href="1919810.com" target="_blank" style="text-decoration: none; font-size: 16px">homomc.cc</a>
</td>
</tr>
</tbody>