Compare commits

...

56 Commits

Author SHA1 Message Date
DGun Otto 82f29af1ae Merge branch 'Stabrinai:master' into master 2023-06-05 00:25:02 +08:00
Sattera 7e5d9ed1e8 [功能] 添加隐藏自动登录时发送登录成功消息 2023-06-02 20:06:49 +08:00
Cai Xukun 55152a62c4 Update README.md 2023-05-18 21:56:26 +08:00
Cai Xukun 1b12d1b7d5 Update README.md 2023-05-18 18:34:18 +08:00
Cai Xukun 527f7f21c7 Add files via upload 2023-05-14 21:16:17 +08:00
Cai Xukun 0205f585df Add files via upload 2023-05-14 15:22:30 +08:00
Cai Xukun d44792baa5 Add files via upload 2023-05-13 21:49:36 +08:00
Cai Xukun 68ac58686d Add files via upload 2023-05-13 16:31:45 +08:00
Cai Xukun 25caa602fd Add files via upload 2023-05-13 12:22:38 +08:00
Cai Xukun b36590c827 Add b11 hash 2023-05-06 20:32:21 +08:00
Cai Xukun af22c47017 Add files via upload 2023-04-24 22:00:52 +08:00
Cai Xukun bf5928e841 Add files via upload 2023-04-24 02:48:15 +08:00
Cai Xukun ebf8d55d60 Add b9 hash 2023-04-24 02:33:13 +08:00
Cai Xukun 9bb99ed355 Update maven.yml 2023-04-23 21:54:56 +08:00
Cai Xukun eaa30cc5eb upload b8 sha 2023-04-23 19:48:19 +08:00
Cai Xukun 4046105e87 upload b7 hash 2023-04-23 00:47:29 +08:00
Cai Xukun e782cccf72 Add files via upload 2023-04-22 21:31:47 +08:00
Cai Xukun eaa0fba587 Add files via upload 2023-04-22 21:29:16 +08:00
Cai Xukun cc248c3459 Add files via upload 2023-04-22 21:15:26 +08:00
Cai Xukun ab24793861 Add files via upload 2023-04-22 21:13:12 +08:00
Cai Xukun 25ebbf6f20 Add files via upload 2023-04-22 20:49:30 +08:00
Cai Xukun d3e463165d Update B6 sha file 2023-04-22 19:20:25 +08:00
Cai Xukun a459e6bad8 Add files via upload 2023-04-22 19:16:00 +08:00
Cai Xukun 6a91130aa8 Merge branch 'Stabrinai:master' into master 2023-04-20 20:38:12 +08:00
Sattera d25949fc3b 更新 2023-04-19 16:13:38 +08:00
HaHaWTH f63f00fade Update maven.yml 2023-04-06 21:43:55 +08:00
HaHaWTH 19c18987f6 Update maven.yml 2023-04-06 21:14:09 +08:00
HaHaWTH db1650c27f Update maven.yml 2023-04-06 20:59:28 +08:00
HaHaWTH f45696f82f Update maven.yml 2023-04-06 20:56:39 +08:00
HaHaWTH 1c1879ea01 Update maven.yml 2023-04-06 20:48:00 +08:00
HaHaWTH 812762db25 Merge branch 'Stabrinai:master' into master 2023-04-06 20:36:22 +08:00
Sattera a4bf7adb60 添加对 floodgate 的支持 2023-04-06 09:42:12 +08:00
Sattera 11c5237950 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	src/main/java/fr/xephi/authme/listener/PlayerListener.java
2023-04-06 09:38:13 +08:00
Sattera bc43afe3d0 添加对 floodgate 的支持 2023-04-06 09:37:57 +08:00
HaHaWTH ced3d17537 Update README.md 2023-04-06 02:19:03 +08:00
HaHaWTH d9b3c59f30 Update maven.yml 2023-04-06 01:58:08 +08:00
HaHaWTH 8c286ceceb Update maven.yml 2023-04-06 01:54:54 +08:00
HaHaWTH 2ce6b066cc Update maven.yml 2023-04-06 01:52:50 +08:00
HaHaWTH 585b69ecd2 Update maven.yml 2023-04-06 01:50:33 +08:00
HaHaWTH 17187b05c1 Update maven.yml 2023-04-06 01:49:05 +08:00
HaHaWTH 6f193f05ce Update maven.yml 2023-04-06 01:47:55 +08:00
HaHaWTH a626265b09 Update maven.yml 2023-04-06 01:42:51 +08:00
HaHaWTH bda8613f93 Update .gitignore 2023-04-06 01:19:09 +08:00
HaHaWTH 44136bb91f Update maven.yml 2023-04-06 01:08:45 +08:00
HaHaWTH 69514738f7 Update maven.yml 2023-04-06 01:01:54 +08:00
HaHaWTH 220b31bb99 Update maven.yml 2023-04-06 00:59:20 +08:00
HaHaWTH 3b58a0acc9 Update maven.yml 2023-04-06 00:57:06 +08:00
HaHaWTH 5efa360cb2 Update README.md 2023-04-06 00:25:56 +08:00
HaHaWTH 2269c93dee Update maven.yml 2023-04-06 00:22:41 +08:00
HaHaWTH bf6233c024 Update maven.yml 2023-04-05 23:32:01 +08:00
HaHaWTH 3cc6f535a8 Update maven.yml 2023-04-05 22:01:32 +08:00
HaHaWTH 95d9edddeb Merge branch 'Stabrinai:master' into master 2023-04-05 21:05:10 +08:00
Sattera 4a559a7ccf Merge remote-tracking branch 'origin/master'
# Conflicts:
#	src/main/java/fr/xephi/authme/listener/PlayerListener.java
2023-04-05 20:25:10 +08:00
Sattera baaabb22d4 添加对 floodgate 的支持 2023-04-05 20:24:55 +08:00
HaHaWTH 9e39f4a186 Create maven-publish.yml 2023-04-05 18:56:36 +08:00
Sattera c2b7a693b2 添加对 floodgate 的支持 2023-04-04 09:08:07 +08:00
63 changed files with 145 additions and 378 deletions
+34
View File
@@ -0,0 +1,34 @@
# This workflow will build a package using Maven and then publish it to GitHub packages when a release is created
# For more information see: https://github.com/actions/setup-java/blob/main/docs/advanced-usage.md#apache-maven-with-a-settings-path
name: Maven Package
on:
release:
types: [created]
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v3
- name: Set up JDK 11
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'temurin'
server-id: github # Value of the distributionManagement/repository/id field of the pom.xml
settings-path: ${{ github.workspace }} # location for the settings.xml file
- name: Build with Maven
run: mvn -B package --file pom.xml
- name: Publish to GitHub Packages Apache Maven
run: mvn deploy -s $GITHUB_WORKSPACE/settings.xml
env:
GITHUB_TOKEN: ${{ github.token }}
+4 -3
View File
@@ -7,11 +7,11 @@ on:
- master - master
jobs: jobs:
build_and_test: Build:
strategy: strategy:
matrix: matrix:
jdkversion: [11] jdkversion: [11]
runs-on: ubuntu-latest runs-on: windows-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-java@v3 - uses: actions/setup-java@v3
@@ -19,5 +19,6 @@ jobs:
distribution: 'temurin' distribution: 'temurin'
java-version: ${{ matrix.jdkversion }} java-version: ${{ matrix.jdkversion }}
cache: 'maven' cache: 'maven'
- name: Build with Maven - name: 使用Maven构建
run: mvn -V -B clean package --file pom.xml run: mvn -V -B clean package --file pom.xml
+1 -1
View File
@@ -24,7 +24,7 @@ hs_err_pid*
# Include the project's code style settings file # Include the project's code style settings file
!.idea/codeStyleSettings.xml !.idea/codeStyleSettings.xml
/target/class/
# File-based project format: # File-based project format:
*.ipr *.ipr
*.iws *.iws
+15 -138
View File
@@ -1,144 +1,21 @@
# AuthMeReloaded # AuthMeReReloaded
**"The best authentication plugin for the Bukkit modding API!"** **"A Fork of Authme that contains many bug fixes!"**
**请前往Releases下载最新版本**(**Download the latest version from Releases**)
<img src="wallpaper.png?raw=true" alt="AuthMeLogo"/>
| Type | Badges |
|-------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **General:** | ![](https://tokei.rs/b1/github/AuthMe/AuthMeReloaded?category=code) ![](https://tokei.rs/b1/github/AuthMe/AuthMeReloaded?category=files) |
| **Code quality:** | [![Code Climate](https://codeclimate.com/github/AuthMe/AuthMeReloaded/badges/gpa.svg)](https://codeclimate.com/github/AuthMe/AuthMeReloaded) [![Coverage status](https://coveralls.io/repos/AuthMe-Team/AuthMeReloaded/badge.svg?branch=master&service=github)](https://coveralls.io/github/AuthMe-Team/AuthMeReloaded?branch=master) |
| **Jenkins CI:** | [![Jenkins Status](https://img.shields.io/website-up-down-green-red/http/shields.io.svg?label=ci.codemc.org)](https://ci.codemc.org/) [![Build Status](https://ci.codemc.org/buildStatus/icon?job=AuthMe/AuthMeReloaded)](https://ci.codemc.org/job/AuthMe/job/AuthMeReloaded) ![Build Tests](https://img.shields.io/jenkins/t/https/ci.codemc.org/job/AuthMe/job/AuthMeReloaded.svg) |
| **Other CIs:** | [![Build Status](https://www.travis-ci.com/AuthMe/AuthMeReloaded.svg?branch=master)](https://www.travis-ci.com/AuthMe/AuthMeReloaded) |
## Description
Prevent username stealing on your server!<br>
Use it to secure your Offline mode server or to increase your Online mode server's protection!
AuthMeReloaded disallows players who aren't authenticated to do actions like placing blocks, moving,<br>
typing commands or using the inventory. It can also kick players with uncommonly long or short player names or kick players from banned countries.
With the Session Login feature you don't have to execute the authentication command every time you connect to the server!
Each command and every feature can be enabled or disabled from our well structured configuration file.
You can also create your own translation file and, if you want, you can share it with us! :)
#### Features:
<ul>
<li><strong>E-Mail Recovery System!</strong></li>
<li>Username spoofing protection.</li>
<li>Countries Whitelist/Blacklist! <a href="https://dev.maxmind.com/geoip/legacy/codes/iso3166/">(country codes)</a></li>
<li><strong>Built-in AntiBot System!</strong></li>
<li><strong>ForceLogin Feature: Admins can login with all account via console command!</strong></li>
<li><strong>Avoid the "Logged in from another location" message!</strong></li>
<li>Two-factor (2FA) support!</li>
<li>Session Login!</li>
<li>Editable translations and messages!</li>
<li><strong>MySQL and SQLite Backend support!</strong></li>
<li>Supported password encryption algorithms: SHA256, ARGON2, BCRYPT, PBKDF2, <a href="https://github.com/CypherX/xAuth/wiki/Password-Hashing">xAuth</a></li>
<li>Supported alternative registration methods:<br>
<ul>
<li>PHPBB, VBulletin: PHPBB - MD5VB</li>
<li>Xenforo: XFBCRYPT</li>
<li>MyBB: MYBB</li>
<li>IPB3: IPB3</li>
<li>IPB4: IPB4</li>
<li>PhpFusion: PHPFUSION</li>
<li>Joomla: JOOMLA</li>
<li>WBB3: WBB3*</li>
<li>SHA512: SALTEDSHA512</li>
<li>DoubleSaltedMD5: SALTED2MD5</li>
<li>WordPress: WORDPRESS</li>
<li><a href="https://github.com/AuthMe/AuthMeReloaded/blob/master/docs/hash_algorithms.md">List of all supported hashes</a></li>
</ul></li>
<li>Custom MySQL tables/columns names (useful with forum databases)</li>
<li><strong>Cached database queries!</strong></li>
<li><strong>Fully compatible with Citizens2, CombatTag, CombatTagPlus!</strong></li>
<li>Compatible with Minecraft mods like <strong>BuildCraft or RedstoneCraft</strong></li>
<li>Restricted users (associate a username with an IP)</li>
<li>Protect player's inventory until correct authentication (requires ProtocolLib)</li>
<li>Saves the quit location of the player</li>
<li>Automatic database backup</li>
<li>Available languages: <a href="https://github.com/AuthMe/AuthMeReloaded/blob/master/docs/translations.md">translations</a></li>
<li>Built-in Deprecated FlatFile (auths.db) to SQL (authme.sql) converter!</li>
<li><strong>Import your old database from other plugins like Rakamak, xAuth, CrazyLogin, RoyalAuth and vAuth!</strong></li>
</ul>
#### Configuration
[How to configure AuthMe](https://github.com/AuthMe/AuthMeReloaded/blob/master/docs/config.md)
#### Commands
[Command list and usage](https://github.com/AuthMe/AuthMeReloaded/blob/master/docs/commands.md)
#### Permissions
- authme.player.* - for all user commands
- authme.admin.* - for all admin commands
- [List of all permission nodes](http://github.com/AuthMe/AuthMeReloaded/blob/master/docs/permission_nodes.md)
#### How To
- [How to use the converter](https://github.com/AuthMe/AuthMeReloaded/wiki/Converters)
- [How to import database from xAuth](https://dev.bukkit.org/projects/authme-reloaded/pages/how-to-import-database-from-xauth)
- [Website integration](https://github.com/AuthMe/AuthMeReloaded/tree/master/samples/website_integration)
- [How to convert from Rakamak](https://dev.bukkit.org/projects/authme-reloaded/pages/how-to-import-database-from-rakamak)
- Convert between database types (e.g. SQLite to MySQL): /authme converter
## Links and Contacts
- **Support:**
- [GitHub issue tracker](https://github.com/AuthMe/AuthMeReloaded/issues)
- [Discord](https://discord.gg/Vn9eCyE)
- [BukkitDev page](https://dev.bukkit.org/projects/authme-reloaded)
- [Spigot page](https://www.spigotmc.org/resources/authmereloaded.6269/)
- **Dev resources:** Changes to the original AuthMe(相较于原版AuthMe的变化):
- <a href="https://ci.codemc.org/job/AuthMe/job/AuthMeReloaded/javadoc/">JavaDocs</a> 1.Memory improvement
- <a href="http://repo.codemc.org/repository/maven-public/">Maven Repository</a> 2.Fixed GeoIP database
```xml 3.Hook floodgate
<repositories> 4.Choose the best performance method by server brand
<repository> 5.Anti ghost player
<id>codemc-repo</id> 6.GUI captcha for unregistered players
<url>https://repo.codemc.org/repository/maven-public/</url> 7.Block unsafe passwords by querying API
</repository> 8.Self hash check to prevent jar virus infection
</repositories> 9.Updater
<dependencies>
<dependency>
<groupId>fr.xephi</groupId>
<artifactId>authme</artifactId>
<version>5.6.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
```
- **Statistics:** **Known Folia issue**
![Graph](https://bstats.org/signatures/bukkit/AuthMe.svg) 1.If the teleport distance too far away,the player may be frozen
## Requirements
##### Compiling requirements:
>- JDK 11 (JDK 17 is recommended)
>- Maven
>- Git/Github (Optional)
##### How to compile the project:
>- Clone the project with Git/GitHub
>- Execute command "mvn clean package"
##### Running requirements:
>- Java 8 (Java 17 is recommended)
>- Paper or Spigot (1.8.X and up)<br>
(In case you use Thermos, Cauldron or similar, you have to update the SpecialSource library to support Java 8 plugins.
HowTo: https://github.com/games647/FastLogin/issues/111#issuecomment-272331347)
>- ProtocolLib (optional, required by some features)
## Credits
##### Contributors:
Team members: <a href="https://github.com/AuthMe/AuthMeReloaded/wiki/Development-team">developers</a>, <a href="https://github.com/AuthMe/AuthMeReloaded/wiki/Translators">translators</a>
Credits for the old version of the plugin: d4rkwarriors, fabe1337, Whoami2 and pomo4ka
Thanks also to: AS1LV3RN1NJA, Hoeze and eprimex
##### GeoIP License:
This product uses data from the GeoLite API created by MaxMind, available at https://www.maxmind.com
+1
View File
@@ -0,0 +1 @@
d91307767d8526ac84a3055ac0e773e91f88d452b4b0031f7ecfed721ac6b641
+1
View File
@@ -0,0 +1 @@
d0aab9856defbd8ef31a9cd7257c5b5761e61a7e39807708c81decf82f599323
+1
View File
@@ -0,0 +1 @@
176a6c6ea03ad8cc37d1d11c3e3608d8b59c09f9f923eae287e8192731642ec8
+1
View File
@@ -0,0 +1 @@
61b1a691490d78af1028a442143f649d432618b92c5a9a7031eb4f94817d768b
+1
View File
@@ -0,0 +1 @@
222eb5ecb4c58f279b8e2f75d38a45495ceb875f249ae3217e3f2a36e50b7d39
+1
View File
@@ -0,0 +1 @@
da53060e21d7135e479a6a6a6fd090b8f41e1423742b94e4dbb1a9230b5621fd
View File
+1
View File
@@ -0,0 +1 @@
423084f2a50c27f62d1b5c85a95e78b9bc3df49d5bd9cefd6fe1aa9227b856c1
+1
View File
@@ -0,0 +1 @@
410df26b12703b82987b9d739c19211346418f1c954d214827805c13b5f82c98
+1
View File
@@ -0,0 +1 @@
20569ebc44a9847da0946de5a3bf2cd2b7855dffb03abc9d29204afcaa64b8bb
+1
View File
@@ -0,0 +1 @@
51a067778ad9b0938d57fd4e2975e0f8dce4914ee060efd0fd6755a8810da4f3
+16 -1
View File
@@ -598,11 +598,26 @@
<enabled>true</enabled> <enabled>true</enabled>
</snapshots> </snapshots>
</repository> </repository>
<repository>
<id>opencollab-snapshot</id>
<url>https://repo.opencollab.dev/maven-snapshots/</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories> </repositories>
<dependencies> <dependencies>
<!-- Java Libraries --> <!-- Java Libraries -->
<dependency>
<groupId>org.geysermc.floodgate</groupId>
<artifactId>api</artifactId>
<version>2.2.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<!-- Jalu Injector --> <!-- Jalu Injector -->
<dependency> <dependency>
<groupId>ch.jalu</groupId> <groupId>ch.jalu</groupId>
@@ -70,7 +70,7 @@ public class TotpCodeCommand extends PlayerCommand {
boolean isCodeValid = totpAuthenticator.checkCode(auth, inputCode); boolean isCodeValid = totpAuthenticator.checkCode(auth, inputCode);
if (isCodeValid) { if (isCodeValid) {
logger.debug("Successfully checked TOTP code for `{0}`", player.getName()); logger.debug("Successfully checked TOTP code for `{0}`", player.getName());
asynchronousLogin.performLogin(player, auth); asynchronousLogin.performLogin(player, auth,false);
} else { } else {
logger.debug("Input TOTP code was invalid for player `{0}`", player.getName()); logger.debug("Input TOTP code was invalid for player `{0}`", player.getName());
messages.send(player, MessageKey.TWO_FACTOR_INVALID_CODE); messages.send(player, MessageKey.TWO_FACTOR_INVALID_CODE);
@@ -93,7 +93,6 @@ public class PlayerListener implements Listener {
private PermissionsManager permissionsManager; private PermissionsManager permissionsManager;
@Inject @Inject
private QuickCommandsProtectionManager quickCommandsProtectionManager; private QuickCommandsProtectionManager quickCommandsProtectionManager;
// Lowest priority to apply fast protection checks // Lowest priority to apply fast protection checks
@EventHandler(priority = EventPriority.LOWEST) @EventHandler(priority = EventPriority.LOWEST)
public void onAsyncPlayerPreLoginEventLowest(AsyncPlayerPreLoginEvent event) { public void onAsyncPlayerPreLoginEventLowest(AsyncPlayerPreLoginEvent event) {
@@ -112,7 +111,10 @@ public class PlayerListener implements Listener {
if (validationService.isUnrestricted(name)) { if (validationService.isUnrestricted(name)) {
return; return;
} }
if (settings.getProperty(RestrictionSettings.HOOK_FLOODGATE_PLAYER) && org.geysermc.floodgate.api.FloodgateApi.getInstance().isFloodgateId(event.getUniqueId())){
return;
}
// Non-blocking checks // Non-blocking checks
try { try {
onJoinVerifier.checkIsValidName(name); onJoinVerifier.checkIsValidName(name);
@@ -120,6 +122,7 @@ public class PlayerListener implements Listener {
event.setKickMessage(messages.retrieveSingle(name, e.getReason(), e.getArgs())); event.setKickMessage(messages.retrieveSingle(name, e.getReason(), e.getArgs()));
event.setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_OTHER); event.setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_OTHER);
} }
} }
/* /*
@@ -35,9 +35,6 @@ public enum MessageKey {
/** In-game registration is disabled! */ /** In-game registration is disabled! */
REGISTRATION_DISABLED("registration.disabled"), REGISTRATION_DISABLED("registration.disabled"),
/** Logged-in due to Session Reconnection. */
SESSION_RECONNECTION("session.valid_session"),
/** Successful login! */ /** Successful login! */
LOGIN_SUCCESS("login.success"), LOGIN_SUCCESS("login.success"),
@@ -30,7 +30,6 @@ final class OldMessageKeysMigrater {
.put(MessageKey.WRONG_PASSWORD, "wrong_pwd") .put(MessageKey.WRONG_PASSWORD, "wrong_pwd")
.put(MessageKey.UNREGISTERED_SUCCESS, "unregistered") .put(MessageKey.UNREGISTERED_SUCCESS, "unregistered")
.put(MessageKey.REGISTRATION_DISABLED, "reg_disabled") .put(MessageKey.REGISTRATION_DISABLED, "reg_disabled")
.put(MessageKey.SESSION_RECONNECTION, "valid_session")
.put(MessageKey.ACCOUNT_NOT_ACTIVATED, "vb_nonActiv") .put(MessageKey.ACCOUNT_NOT_ACTIVATED, "vb_nonActiv")
.put(MessageKey.NAME_ALREADY_REGISTERED, "user_regged") .put(MessageKey.NAME_ALREADY_REGISTERED, "user_regged")
.put(MessageKey.NO_PERMISSION, "no_perm") .put(MessageKey.NO_PERMISSION, "no_perm")
@@ -54,7 +54,7 @@ public class Management {
} }
public void forceLogin(Player player) { public void forceLogin(Player player) {
runTask(() -> asynchronousLogin.forceLogin(player)); runTask(() -> asynchronousLogin.forceLogin(player,0));
} }
public void forceLogin(Player player, boolean quiet) { public void forceLogin(Player player, boolean quiet) {
@@ -19,6 +19,7 @@ import fr.xephi.authme.service.bungeecord.BungeeSender;
import fr.xephi.authme.service.bungeecord.MessageType; import fr.xephi.authme.service.bungeecord.MessageType;
import fr.xephi.authme.settings.commandconfig.CommandManager; import fr.xephi.authme.settings.commandconfig.CommandManager;
import fr.xephi.authme.settings.properties.HooksSettings; 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.RegistrationSettings;
import fr.xephi.authme.settings.properties.RestrictionSettings; import fr.xephi.authme.settings.properties.RestrictionSettings;
import fr.xephi.authme.util.InternetProtocolUtils; import fr.xephi.authme.util.InternetProtocolUtils;
@@ -128,18 +129,16 @@ public class AsynchronousJoin implements AsynchronousProcess {
// Session logic // Session logic
if (sessionService.canResumeSession(player)) { if (sessionService.canResumeSession(player)) {
service.send(player, MessageKey.SESSION_RECONNECTION);
// Run commands // Run commands
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask( bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(
() -> commandManager.runCommandsOnSessionLogin(player)); () -> commandManager.runCommandsOnSessionLogin(player));
bukkitService.runTaskOptionallyAsync(() -> asynchronousLogin.forceLogin(player)); bukkitService.runTaskOptionallyAsync(() -> asynchronousLogin.forceLogin(player,service.getProperty(PluginSettings.HIDE_SESSIONS_LOGIN) ? 1 : 0));
return; return;
} else if (proxySessionManager.shouldResumeSession(name)) { } else if (proxySessionManager.shouldResumeSession(name)) {
service.send(player, MessageKey.SESSION_RECONNECTION);
// Run commands // Run commands
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask( bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(
() -> commandManager.runCommandsOnSessionLogin(player)); () -> commandManager.runCommandsOnSessionLogin(player));
bukkitService.runTaskOptionallyAsync(() -> asynchronousLogin.forceLogin(player)); bukkitService.runTaskOptionallyAsync(() -> asynchronousLogin.forceLogin(player,service.getProperty(PluginSettings.HIDE_SESSIONS_LOGIN) ? 1 : 0));
logger.info("The user " + player.getName() + " has been automatically logged in, " logger.info("The user " + player.getName() + " has been automatically logged in, "
+ "as present in autologin queue."); + "as present in autologin queue.");
return; return;
@@ -102,7 +102,7 @@ public class AsynchronousLogin implements AsynchronousProcess {
limboService.getLimboPlayer(player.getName()).setState(LimboPlayerState.TOTP_REQUIRED); limboService.getLimboPlayer(player.getName()).setState(LimboPlayerState.TOTP_REQUIRED);
// TODO #1141: Check if we should check limbo state before processing password // TODO #1141: Check if we should check limbo state before processing password
} else { } else {
performLogin(player, auth); performLogin(player, auth, false);
} }
} }
} }
@@ -112,10 +112,10 @@ public class AsynchronousLogin implements AsynchronousProcess {
* *
* @param player the player to log in * @param player the player to log in
*/ */
public void forceLogin(Player player) { public void forceLogin(Player player,int quiet) {
PlayerAuth auth = getPlayerAuth(player); PlayerAuth auth = getPlayerAuth(player);
if (auth != null) { if (auth != null) {
performLogin(player, auth); performLogin(player, auth, quiet == 1);
} }
} }
@@ -128,7 +128,7 @@ public class AsynchronousLogin implements AsynchronousProcess {
public void forceLogin(Player player, boolean quiet) { public void forceLogin(Player player, boolean quiet) {
PlayerAuth auth = getPlayerAuth(player, quiet); PlayerAuth auth = getPlayerAuth(player, quiet);
if (auth != null) { if (auth != null) {
performLogin(player, auth); performLogin(player, auth, false);
} }
} }
@@ -265,7 +265,7 @@ public class AsynchronousLogin implements AsynchronousProcess {
* @param player the player to log in * @param player the player to log in
* @param auth the associated PlayerAuth object * @param auth the associated PlayerAuth object
*/ */
public void performLogin(Player player, PlayerAuth auth) { public void performLogin(Player player, PlayerAuth auth, boolean quiet) {
if (player.isOnline()) { if (player.isOnline()) {
boolean isFirstLogin = (auth.getLastLogin() == null); boolean isFirstLogin = (auth.getLastLogin() == null);
@@ -284,7 +284,7 @@ public class AsynchronousLogin implements AsynchronousProcess {
tempbanManager.resetCount(ip, name); tempbanManager.resetCount(ip, name);
player.setNoDamageTicks(0); player.setNoDamageTicks(0);
service.send(player, MessageKey.LOGIN_SUCCESS); if (!quiet) {service.send(player, MessageKey.LOGIN_SUCCESS);}
// Other auths // Other auths
List<String> auths = dataSource.getAllAuthsByIp(auth.getLastIp()); List<String> auths = dataSource.getAllAuthsByIp(auth.getLastIp());
@@ -89,9 +89,9 @@ abstract class AbstractPasswordRegisterExecutor<P extends AbstractPasswordRegist
final Player player = params.getPlayer(); final Player player = params.getPlayer();
if (performLoginAfterRegister(params)) { if (performLoginAfterRegister(params)) {
if (commonService.getProperty(PluginSettings.USE_ASYNC_TASKS)) { if (commonService.getProperty(PluginSettings.USE_ASYNC_TASKS)) {
bukkitService.runTaskAsynchronously(() -> asynchronousLogin.forceLogin(player)); bukkitService.runTaskAsynchronously(() -> asynchronousLogin.forceLogin(player,0));
} else { } else {
bukkitService.scheduleSyncDelayedTask(() -> asynchronousLogin.forceLogin(player), SYNC_LOGIN_DELAY); bukkitService.scheduleSyncDelayedTask(() -> asynchronousLogin.forceLogin(player,0), SYNC_LOGIN_DELAY);
} }
} }
syncProcessManager.processSyncPasswordRegister(player); syncProcessManager.processSyncPasswordRegister(player);
@@ -47,37 +47,21 @@ public class GeoIpService {
private static final String DATABASE_NAME = "GeoLite2-Country"; private static final String DATABASE_NAME = "GeoLite2-Country";
private static final String DATABASE_FILE = DATABASE_NAME + ".mmdb"; private static final String DATABASE_FILE = DATABASE_NAME + ".mmdb";
private static final String DATABASE_TMP_FILE = DATABASE_NAME + ".mmdb.tmp";
private static final String ARCHIVE_FILE = DATABASE_NAME + ".mmdb.gz";
private static final String ARCHIVE_URL =
"https://updates.maxmind.com/geoip/databases/" + DATABASE_NAME + "/update";
private static final int UPDATE_INTERVAL_DAYS = 30;
private final ConsoleLogger logger = ConsoleLoggerFactory.get(GeoIpService.class); private final ConsoleLogger logger = ConsoleLoggerFactory.get(GeoIpService.class);
private final Path dataFile; private final Path dataFile;
private final BukkitService bukkitService;
private final Settings settings;
private GeoIp2Provider databaseReader; private GeoIp2Provider databaseReader;
private volatile boolean downloading; private volatile boolean downloading;
@Inject @Inject
GeoIpService(@DataFolder File dataFolder, BukkitService bukkitService, Settings settings) { GeoIpService(@DataFolder File dataFolder) {
this.bukkitService = bukkitService;
this.dataFile = dataFolder.toPath().resolve(DATABASE_FILE); this.dataFile = dataFolder.toPath().resolve(DATABASE_FILE);
this.settings = settings;
// Fires download of recent data or the initialization of the look up service // Fires download of recent data or the initialization of the look up service
isDataAvailable(); isDataAvailable();
} }
@VisibleForTesting @VisibleForTesting
GeoIpService(@DataFolder File dataFolder, BukkitService bukkitService, Settings settings, GeoIp2Provider reader) { GeoIpService(@DataFolder File dataFolder, GeoIp2Provider reader) {
this.bukkitService = bukkitService;
this.settings = settings;
this.dataFile = dataFolder.toPath().resolve(DATABASE_FILE); this.dataFile = dataFolder.toPath().resolve(DATABASE_FILE);
this.databaseReader = reader; this.databaseReader = reader;
@@ -101,73 +85,19 @@ public class GeoIpService {
if (Files.exists(dataFile)) { if (Files.exists(dataFile)) {
try { try {
FileTime lastModifiedTime = Files.getLastModifiedTime(dataFile); startReading();
if (Duration.between(lastModifiedTime.toInstant(), Instant.now()).toDays() <= UPDATE_INTERVAL_DAYS) { // don't fire the update task - we are up to date
startReading(); return true;
// don't fire the update task - we are up to date
return true;
} else {
logger.debug("GEO IP database is older than " + UPDATE_INTERVAL_DAYS + " Days");
}
} catch (IOException ioEx) { } catch (IOException ioEx) {
logger.logException("Failed to load GeoLiteAPI database", ioEx); logger.logException("Failed to load GeoLiteAPI database", ioEx);
return false; return false;
} }
} }
//set the downloading flag in order to fix race conditions outside
downloading = true;
// File is outdated or doesn't exist - let's try to download the data file! // File is outdated or doesn't exist - let's try to download the data file!
// use bukkit's cached threads // use bukkit's cached threads
bukkitService.runTaskAsynchronously(this::updateDatabase);
return false; return false;
} }
/**
* Tries to update the database by downloading a new version from the website.
*/
private void updateDatabase() {
logger.info("Downloading GEO IP database, because the old database is older than "
+ UPDATE_INTERVAL_DAYS + " days or doesn't exist");
Path downloadFile = null;
Path tempFile = null;
try {
// download database to temporarily location
downloadFile = Files.createTempFile(ARCHIVE_FILE, null);
tempFile = Files.createTempFile(DATABASE_TMP_FILE, null);
String expectedChecksum = downloadDatabaseArchive(downloadFile);
if (expectedChecksum == null) {
logger.info("There is no newer GEO IP database uploaded to MaxMind. Using the old one for now.");
startReading();
return;
}
// tar extract database and copy to target destination
extractDatabase(downloadFile, tempFile);
// MD5 checksum verification
verifyChecksum(Hashing.md5(), tempFile, expectedChecksum);
Files.copy(tempFile, dataFile, StandardCopyOption.REPLACE_EXISTING);
//only set this value to false on success otherwise errors could lead to endless download triggers
logger.info("Successfully downloaded new GEO IP database to " + dataFile);
startReading();
} catch (IOException ioEx) {
logger.logException("Could not download GeoLiteAPI database", ioEx);
} finally {
// clean up
if (downloadFile != null) {
FileUtils.delete(downloadFile.toFile());
}
if (tempFile != null) {
FileUtils.delete(tempFile.toFile());
}
}
}
private void startReading() throws IOException { private void startReading() throws IOException {
databaseReader = new Reader(dataFile.toFile(), FileMode.MEMORY, new CHMCache()); databaseReader = new Reader(dataFile.toFile(), FileMode.MEMORY, new CHMCache());
@@ -177,101 +107,6 @@ public class GeoIpService {
downloading = false; 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
*/
private String downloadDatabaseArchive(Instant lastModified, Path destination) throws IOException {
String clientId = settings.getProperty(ProtectionSettings.MAXMIND_API_CLIENT_ID);
String licenseKey = settings.getProperty(ProtectionSettings.MAXMIND_API_LICENSE_KEY);
if (clientId.isEmpty() || licenseKey.isEmpty()) {
logger.warning("No MaxMind credentials found in the configuration file!"
+ " GeoIp protections will be disabled.");
return null;
}
HttpURLConnection connection = (HttpURLConnection) new URL(ARCHIVE_URL).openConnection();
String basicAuth = "Basic " + new String(Base64.getEncoder().encode((clientId + ":" + licenseKey).getBytes()));
connection.setRequestProperty("Authorization", basicAuth);
if (lastModified != null) {
// Only download if we actually need a newer version - this field is specified in GMT zone
ZonedDateTime zonedTime = lastModified.atZone(ZoneId.of("GMT"));
String timeFormat = DateTimeFormatter.RFC_1123_DATE_TIME.format(zonedTime);
connection.addRequestProperty("If-Modified-Since", timeFormat);
}
if (connection.getResponseCode() == HttpURLConnection.HTTP_NOT_MODIFIED) {
//we already have the newest version
connection.getInputStream().close();
return null;
}
String hash = connection.getHeaderField("X-Database-MD5");
String rawModifiedDate = connection.getHeaderField("Last-Modified");
Instant modifiedDate = Instant.from(DateTimeFormatter.RFC_1123_DATE_TIME.parse(rawModifiedDate));
Files.copy(connection.getInputStream(), destination, StandardCopyOption.REPLACE_EXISTING);
Files.setLastModifiedTime(destination, FileTime.from(modifiedDate));
return hash;
}
/**
* 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
*/
private String downloadDatabaseArchive(Path destination) throws IOException {
Instant lastModified = null;
if (Files.exists(dataFile)) {
lastModified = Files.getLastModifiedTime(dataFile).toInstant();
}
return downloadDatabaseArchive(lastModified, destination);
}
/**
* 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
*/
private void verifyChecksum(HashFunction function, Path file, String expectedChecksum) throws IOException {
HashCode actualHash = function.hashBytes(Files.readAllBytes(file));
HashCode expectedHash = HashCode.fromString(expectedChecksum);
if (!Objects.equals(actualHash, expectedHash)) {
throw new IOException("GEO IP Checksum verification failed. "
+ "Expected: " + expectedChecksum + "Actual:" + actualHash);
}
}
/**
* 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
*/
private void extractDatabase(Path inputFile, Path outputFile) throws IOException {
// .gz -> gzipped file
try (BufferedInputStream in = new BufferedInputStream(Files.newInputStream(inputFile));
GZIPInputStream gzipIn = new GZIPInputStream(in)) {
// found the database file and copy file
Files.copy(gzipIn, outputFile, StandardCopyOption.REPLACE_EXISTING);
// update the last modification date to be same as in the archive
Files.setLastModifiedTime(outputFile, Files.getLastModifiedTime(inputFile));
}
}
/** /**
* Get the country code of the given IP address. * Get the country code of the given IP address.
* *
@@ -65,7 +65,7 @@ public final class EmailSettings implements SettingsHolder {
newProperty("Email.emailOauth2Token", ""); newProperty("Email.emailOauth2Token", "");
@Comment("Email notifications when the server shuts down") @Comment("Email notifications when the server shuts down")
public static final Property<Boolean> SHUTDOWN_MAIL = public static final Property<Boolean> SHUTDOWN_MAIL =
newProperty("Email.shutDownEmail", true); newProperty("Email.shutDownEmail", false);
@Comment("Email notification address when the server is shut down") @Comment("Email notification address when the server is shut down")
public static final Property<String> SHUTDOWN_MAIL_ADDRESS = public static final Property<String> SHUTDOWN_MAIL_ADDRESS =
newProperty("Email.shutDownEmailAddress", "your@mail.com"); newProperty("Email.shutDownEmailAddress", "your@mail.com");
@@ -20,6 +20,12 @@ public final class PluginSettings implements SettingsHolder {
public static final Property<Boolean> SESSIONS_ENABLED = public static final Property<Boolean> SESSIONS_ENABLED =
newProperty("settings.sessions.enabled", true); 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({ @Comment({
"After how many minutes should a session expire?", "After how many minutes should a session expire?",
"A player's session ends after the timeout or if his IP has changed" "A player's session ends after the timeout or if his IP has changed"
@@ -20,17 +20,6 @@ public final class ProtectionSettings implements SettingsHolder {
public static final Property<Boolean> ENABLE_PROTECTION_REGISTERED = public static final Property<Boolean> ENABLE_PROTECTION_REGISTERED =
newProperty("Protection.enableProtectionRegistered", true); newProperty("Protection.enableProtectionRegistered", true);
@Comment({"The MaxMind clientId used to download the GeoIp database,",
"get one at https://www.maxmind.com/en/accounts/current/license-key",
"The EssentialsX project has a very useful tutorial on how to generate",
"the license key: https://github.com/EssentialsX/Wiki/blob/master/GeoIP.md"})
public static final Property<String> MAXMIND_API_CLIENT_ID =
newProperty("Protection.geoIpDatabase.clientId", "");
@Comment("The MaxMind licenseKey used to download the GeoIp database.")
public static final Property<String> MAXMIND_API_LICENSE_KEY =
newProperty("Protection.geoIpDatabase.licenseKey", "");
@Comment({ @Comment({
"Countries allowed to join the server and register. For country codes, see", "Countries allowed to join the server and register. For country codes, see",
"https://dev.maxmind.com/geoip/legacy/codes/iso3166/", "https://dev.maxmind.com/geoip/legacy/codes/iso3166/",
@@ -125,6 +125,9 @@ public final class RestrictionSettings implements SettingsHolder {
public static final Property<String> ALLOWED_NICKNAME_CHARACTERS = public static final Property<String> ALLOWED_NICKNAME_CHARACTERS =
newProperty("settings.restrictions.allowedNicknameCharacters", "[a-zA-Z0-9_]*"); 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({ @Comment({
"How far can unregistered players walk?", "How far can unregistered players walk?",
"Set to 0 for unlimited radius" "Set to 0 for unlimited radius"
Binary file not shown.
+1 -1
View File
@@ -66,7 +66,7 @@ misc:
# Session messages # Session messages
session: session:
valid_session: '&2Сесията е продължена.'
invalid_session: '&cТвоят IP се е променил и сесията беше прекратена.' invalid_session: '&cТвоят IP се е променил и сесията беше прекратена.'
# Error messages when joining # Error messages when joining
+1 -1
View File
@@ -69,7 +69,7 @@ misc:
# Mensagens de sessão # Mensagens de sessão
session: 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!' invalid_session: '&fO seu IP foi alterado e sua sessão expirou!'
# Mensagens de erro ao entrar # Mensagens de erro ao entrar
+1 -1
View File
@@ -66,7 +66,7 @@ misc:
# Session messages # Session messages
session: session:
valid_session: '&cAutomatické znovupřihlášení.'
invalid_session: '&cChyba: Počkej než vyprší tvoje relace.' invalid_session: '&cChyba: Počkej než vyprší tvoje relace.'
# Error messages when joining # Error messages when joining
+1 -1
View File
@@ -66,7 +66,7 @@ misc:
# Session messages # Session messages
session: session:
valid_session: '&2Erfolgreich eingeloggt!'
invalid_session: '&cUngültige Session. Bitte starte das Spiel neu oder warte, bis die Session abgelaufen ist.' invalid_session: '&cUngültige Session. Bitte starte das Spiel neu oder warte, bis die Session abgelaufen ist.'
# Error messages when joining # Error messages when joining
+1 -1
View File
@@ -66,7 +66,7 @@ misc:
# Session messages # Session messages
session: session:
invalid_session: '&cYour IP has been changed and your session data has expired!' 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 # Error messages when joining
on_join_validation: on_join_validation:
+1 -1
View File
@@ -66,7 +66,7 @@ misc:
# Session messages # Session messages
session: session:
valid_session: '&2Ensalutantojn pro Sesio Rekonektas.'
invalid_session: '&cVia IP estis ŝanĝita kaj via seanco datumoj finiĝis!' invalid_session: '&cVia IP estis ŝanĝita kaj via seanco datumoj finiĝis!'
# Error messages when joining # Error messages when joining
+1 -1
View File
@@ -67,7 +67,7 @@ misc:
# Session messages # Session messages
session: session:
valid_session: '&cInicio de sesión'
invalid_session: '&fLos datos de sesión no corresponden. Por favor espera a terminar la sesión.' invalid_session: '&fLos datos de sesión no corresponden. Por favor espera a terminar la sesión.'
# Error messages when joining # Error messages when joining
+1 -1
View File
@@ -66,7 +66,7 @@ misc:
# Session messages # Session messages
session: session:
invalid_session: '&cSinu IP-aadress muutus, seega sinu sessioon aegus!' invalid_session: '&cSinu IP-aadress muutus, seega sinu sessioon aegus!'
valid_session: '&2Sisse logitud sessiooni jätkumise tõttu.'
# Error messages when joining # Error messages when joining
on_join_validation: on_join_validation:
+1 -1
View File
@@ -66,7 +66,7 @@ misc:
# Session messages # Session messages
session: 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!' invalid_session: '&cZure IP helbidea aldatu da, eta horregatik zure sesioa iraungi da!'
# Error messages when joining # Error messages when joining
+1 -1
View File
@@ -66,7 +66,7 @@ misc:
# Session messages # Session messages
session: session:
valid_session: '&cIstunto jatkettu!'
invalid_session: '&fIstunto ei täsmää! Ole hyvä ja odota istunnon loppuun' invalid_session: '&fIstunto ei täsmää! Ole hyvä ja odota istunnon loppuun'
# Error messages when joining # Error messages when joining
+1 -1
View File
@@ -69,7 +69,7 @@ misc:
# Session # Session
session: session:
valid_session: '&aVous avez été automatiquement connecté !'
invalid_session: 'Session expirée suite à un changement d''IP.' invalid_session: 'Session expirée suite à un changement d''IP.'
# Erreurs lors d'une tentative connexion # Erreurs lors d'une tentative connexion
+1 -1
View File
@@ -66,7 +66,7 @@ misc:
# Session messages # Session messages
session: 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' invalid_session: '&fOs datos de sesión non corresponden, por favor, espere a que remate a sesión'
# Error messages when joining # Error messages when joining
+1 -1
View File
@@ -66,7 +66,7 @@ misc:
# Session messages # Session messages
session: 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.' invalid_session: '&cAz IP címed megváltozott, ezért a visszacsatlakozási időkereted lejárt.'
# Error messages when joining # Error messages when joining
+1 -1
View File
@@ -66,7 +66,7 @@ misc:
# Session messages # Session messages
session: session:
valid_session: '&2Otomatis login, karena sesi masih terhubung.'
invalid_session: '&cIP kamu telah berubah, dan sesi kamu telah berakhir!' invalid_session: '&cIP kamu telah berubah, dan sesi kamu telah berakhir!'
# Error messages when joining # Error messages when joining
+1 -1
View File
@@ -67,7 +67,7 @@ misc:
# Session messages # Session messages
session: session:
valid_session: '&2Autenticato automaticamente attraverso la precedente sessione!'
invalid_session: '&cIl tuo indirizzo IP è cambiato e la tua sessione è stata terminata!' invalid_session: '&cIl tuo indirizzo IP è cambiato e la tua sessione è stata terminata!'
# Error messages when joining # Error messages when joining
+1 -1
View File
@@ -68,7 +68,7 @@ misc:
# Session messages # Session messages
session: session:
valid_session: '&2세션 재 연결로 인해 로그인 되었습니다.'
invalid_session: '&cIP가 변경되어 세션이 만료되었습니다!' invalid_session: '&cIP가 변경되어 세션이 만료되었습니다!'
# Error messages when joining # Error messages when joining
+1 -1
View File
@@ -66,7 +66,7 @@ misc:
# Session messages # Session messages
session: session:
valid_session: '&aSesijos prisijungimas'
invalid_session: '&cSesijos laikai nesutampa, prasome palaukti kol secija baigsis.' invalid_session: '&cSesijos laikai nesutampa, prasome palaukti kol secija baigsis.'
# Error messages when joining # Error messages when joining
+1 -1
View File
@@ -66,7 +66,7 @@ misc:
# Session messages # Session messages
session: session:
valid_session: '&2Ingelogd wegens sessie-herverbinding.'
invalid_session: '&cJouw IP-adres is veranderd en je sessie is verlopen!' invalid_session: '&cJouw IP-adres is veranderd en je sessie is verlopen!'
# Error messages when joining # Error messages when joining
+1 -1
View File
@@ -66,7 +66,7 @@ misc:
# Session messages # Session messages
session: session:
valid_session: '&aZalogowano automatycznie z powodu sesji logowania.'
invalid_session: '&fSesja logowania zakończona!' invalid_session: '&fSesja logowania zakończona!'
# Error messages when joining # Error messages when joining
+1 -1
View File
@@ -66,7 +66,7 @@ misc:
# Session messages # Session messages
session: session:
valid_session: '&cSessão válida'
invalid_session: '&fDados de sessão não correspondem. Por favor aguarde o fim da sessão' invalid_session: '&fDados de sessão não correspondem. Por favor aguarde o fim da sessão'
# Error messages when joining # Error messages when joining
+1 -1
View File
@@ -66,7 +66,7 @@ misc:
# Session messages # Session messages
session: session:
invalid_session: '&cIP-ul tau a fost schimbat si sesiunea ta a expirat!' invalid_session: '&cIP-ul tau a fost schimbat si sesiunea ta a expirat!'
valid_session: '&2Conectat datorita reconectarii sesiunii.'
# Error messages when joining # Error messages when joining
on_join_validation: on_join_validation:
+1 -1
View File
@@ -61,7 +61,7 @@ misc:
# Session messages # Session messages
session: session:
valid_session: '&2Вы автоматически авторизовались!'
invalid_session: '&cСессия некорректна. Дождитесь, пока она закончится.' invalid_session: '&cСессия некорректна. Дождитесь, пока она закончится.'
# Error messages when joining # Error messages when joining
+1 -2
View File
@@ -65,7 +65,7 @@ misc:
# Session messages # Session messages
session: session:
valid_session: '&2Uspešna povezava.'
invalid_session: '&cVas IP je bil spremenjen in vasa seja je potekla!' invalid_session: '&cVas IP je bil spremenjen in vasa seja je potekla!'
# Error messages when joining # Error messages when joining
@@ -154,4 +154,3 @@ time:
hours: 'ure' hours: 'ure'
day: 'dan' day: 'dan'
days: 'dni' days: 'dni'
+1 -1
View File
@@ -72,7 +72,7 @@ misc:
# Session messages # Session messages
session: 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).' invalid_session: '&fTvoja IP sa zmenila a tvoje prihlásenie(relácia) vypršalo(/a).'
# Error messages when joining # Error messages when joining
+1 -1
View File
@@ -66,7 +66,7 @@ misc:
# Session messages # Session messages
session: session:
valid_session: '&2Ulogovani ste zbog ponovnog povezivanja sesije.'
invalid_session: '&cVaš IP je promenjen i vaši podaci o sesiji su istekli!' invalid_session: '&cVaš IP je promenjen i vaši podaci o sesiji su istekli!'
# Error messages when joining # Error messages when joining
+1 -1
View File
@@ -66,7 +66,7 @@ misc:
# Session messages # Session messages
session: session:
valid_session: '&2Oturuma girisiniz otomatikmen yapilmistir.'
invalid_session: '&cIP adresin degistirildi ve oturum suren doldu!' invalid_session: '&cIP adresin degistirildi ve oturum suren doldu!'
# Error messages when joining # Error messages when joining
+1 -1
View File
@@ -66,7 +66,7 @@ misc:
# Session messages # Session messages
session: session:
valid_session: '&2Сесію відновлено.'
invalid_session: '&cСесію було розірвано внаслідок зміни IP.' invalid_session: '&cСесію було розірвано внаслідок зміни IP.'
# Error messages when joining # Error messages when joining
+1 -1
View File
@@ -66,7 +66,7 @@ misc:
# Session messages # Session messages
session: 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!' 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 # Error messages when joining
@@ -68,7 +68,6 @@ misc:
# Session messages # Session messages
session: session:
valid_session: ''
invalid_session: '&c*** 请重新登录 ***' invalid_session: '&c*** 请重新登录 ***'
# Error messages when joining # Error messages when joining
@@ -69,7 +69,7 @@ misc:
# Session messages # Session messages
session: session:
valid_session: '&8[&6用戶系統&8] &b嗨 歡迎回來喔~'
invalid_session: '&8[&6用戶系統&8] &f登入階段資料已損壞,請等待登入階段結束。' invalid_session: '&8[&6用戶系統&8] &f登入階段資料已損壞,請等待登入階段結束。'
# Error messages when joining # Error messages when joining
@@ -66,7 +66,7 @@ misc:
# Session messages # Session messages
session: session:
valid_session: '&2由於會話重新連接而登錄.'
invalid_session: '&c您的IP已更改,並且您的會話數據已過期!' invalid_session: '&c您的IP已更改,並且您的會話數據已過期!'
# Error messages when joining # Error messages when joining
@@ -68,7 +68,7 @@ misc:
# Session messages # Session messages
session: session:
valid_session: '&b【AuthMe】&6您已經成功登入!'
invalid_session: '&b【AuthMe】&6Session驗證不相符!' invalid_session: '&b【AuthMe】&6Session驗證不相符!'
# Error messages when joining # Error messages when joining
+1
View File
@@ -15,6 +15,7 @@ softdepend:
- Essentials - Essentials
- EssentialsSpawn - EssentialsSpawn
- ProtocolLib - ProtocolLib
- floodgate
commands: commands:
authme: authme:
description: AuthMe op commands description: AuthMe op commands