Merge branch 'master' of https://github.com/AuthMe/AuthMeReloaded into 1524-migrate-old-2fa-hash

This commit is contained in:
ljacqu 2019-02-25 08:26:58 +01:00
commit 72411d884c
65 changed files with 1107 additions and 2337 deletions

View File

@ -1,52 +0,0 @@
version: 2
jobs:
build_and_test_jdk8:
working_directory: ~/authmereloaded-jdk8
docker:
- image: circleci/openjdk:8-jdk
environment:
MAVEN_OPTS: -Xmx2048m
steps:
- checkout
- restore_cache:
keys:
- authmereloaded-{{ checksum "pom.xml" }}
- authmereloaded-
- run: mvn -T 2 -B dependency:go-offline
- save_cache:
paths:
- ~/.m2
key: authmereloaded-{{ checksum "pom.xml" }}
- run: mvn -T 2 -B package
- store_test_results:
path: target/surefire-reports
- store_artifacts:
path: target/*.jar
build_and_test_jdk10:
working_directory: ~/authmereloaded-jdk10
docker:
- image: circleci/openjdk:10-jdk
environment:
MAVEN_OPTS: -Xmx2048m
steps:
- checkout
- restore_cache:
keys:
- authmereloaded-{{ checksum "pom.xml" }}
- authmereloaded-
- run: mvn -T 2 -B dependency:go-offline
- save_cache:
paths:
- ~/.m2
key: authmereloaded-{{ checksum "pom.xml" }}
- run: mvn -T 2 -B package
- store_test_results:
path: target/surefire-reports
- store_artifacts:
path: target/*.jar
workflows:
version: 2
build_and_test:
jobs:
- build_and_test_jdk8
- build_and_test_jdk10

10
.travis.yml Normal file
View File

@ -0,0 +1,10 @@
sudo: false
dist: trusty
language: java
jdk:
- oraclejdk8
- openjdk11
cache:
directories:
- '$HOME/.m2/repository'

View File

@ -7,7 +7,7 @@
| **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:** | [![CircleCI](https://circleci.com/gh/AuthMe/AuthMeReloaded.svg?style=svg)](https://circleci.com/gh/AuthMe/AuthMeReloaded) |
| **Other CIs:** | [![Build Status](https://travis-ci.org/AuthMe/AuthMeReloaded.svg?branch=master)](https://travis-ci.org/AuthMe/AuthMeReloaded) |
## Description
@ -114,9 +114,6 @@ You can also create your own translation file and, if you want, you can share it
## Credits
##### Sponsor:
[FastVM.io](https://fastvm.io) is leader in VPS hosting solutions. With its own DataCenter offers Anti-DDoS solutions at affordable prices.
##### 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>

251
pom.xml
View File

@ -6,13 +6,12 @@
<groupId>fr.xephi</groupId>
<artifactId>authme</artifactId>
<version>5.5.0-SNAPSHOT</version>
<version>5.5.1-SNAPSHOT</version>
<name>AuthMeReloaded</name>
<description>The first authentication plugin for the Bukkit API!</description>
<inceptionYear>2013</inceptionYear>
<url>http://dev.bukkit.org/bukkit-plugins/authme-reloaded/</url>
<!-- See also: https://www.spigotmc.org/resources/authme-reloaded.6269/ -->
<url>https://github.com/AuthMe/AuthMeReloaded</url>
<organization>
<name>AuthMe-Team</name>
@ -55,31 +54,31 @@
</licenses>
<properties>
<!-- Project properties -->
<!-- Build cycle properties -->
<project.skipExtendedHashTests>false</project.skipExtendedHashTests>
<!-- Environment properties -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<jdk.version>1.8</jdk.version>
<java.version>1.8</java.version>
<maven.minimumVersion>3.3.9</maven.minimumVersion>
<!-- Output properties -->
<!-- Dependencies versions -->
<spigot.version>1.13.2-R0.1-SNAPSHOT</spigot.version>
<!-- Versioning properties -->
<project.outputName>AuthMe</project.outputName>
<project.buildNumber>CUSTOM</project.buildNumber>
<project.skipExtendedHashTests>false</project.skipExtendedHashTests>
<project.versionCode>${project.version}-b${project.buildNumber}</project.versionCode>
<project.finalNameBase>${project.outputName}-${project.version}</project.finalNameBase>
<!-- BukkitPlugin properties -->
<bukkitplugin.name>${project.outputName}</bukkitplugin.name>
<bukkitplugin.version>${project.versionCode}</bukkitplugin.version>
<bukkitplugin.main>${project.groupId}.${project.artifactId}.${bukkitplugin.name}</bukkitplugin.main>
<bukkitplugin.authors>Xephi, sgdc3, DNx5, timvisee, games647, ljacqu, Gnat008</bukkitplugin.authors>
<!-- Change Bukkit Version HERE! -->
<bukkit.version>1.13-R0.1-SNAPSHOT</bukkit.version>
<!-- Plugin description file properties -->
<pluginDescription.name>${project.outputName}</pluginDescription.name>
<pluginDescription.version>${project.versionCode}</pluginDescription.version>
<pluginDescription.main>${project.groupId}.${project.artifactId}.${pluginDescription.name}</pluginDescription.main>
<pluginDescription.authors>Xephi, sgdc3, DNx5, timvisee, games647, ljacqu, Gnat008</pluginDescription.authors>
</properties>
<prerequisites>
<maven>3.3.9</maven>
</prerequisites>
<!-- Jenkins profile -->
<profiles>
<!-- Set the buildNumber using the jenkins env. variable -->
@ -109,8 +108,9 @@
</profiles>
<build>
<defaultGoal>clean install</defaultGoal>
<finalName>${project.outputName}-${project.version}-noshade</finalName>
<defaultGoal>clean package</defaultGoal>
<!-- Little hack to make the shade plugin output a file with the right name -->
<finalName>${project.finalNameBase}-noshade</finalName>
<resources>
<resource>
@ -132,29 +132,55 @@
</resources>
<plugins>
<!-- Enforce build environment -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.4.1</version>
<executions>
<execution>
<id>enforce-environment</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireMavenVersion>
<version>${maven.minimumVersion}</version>
</requireMavenVersion>
</rules>
<fail>true</fail>
</configuration>
</execution>
</executions>
</plugin>
<!-- Clean the target folder content -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- Include resource files -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- Compile and include classes -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>${jdk.version}</source>
<target>${jdk.version}</target>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<!-- Generate test coverage reports -->
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.2</version>
<version>0.8.3</version>
<executions>
<execution>
<id>pre-unit-test</id>
@ -170,10 +196,11 @@
</execution>
</executions>
</plugin>
<!-- Unit testing -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.0</version>
<version>2.22.1</version>
<configuration>
<!-- Force the right file encoding during unit testing -->
<!-- Set language to English in order to get consistent results for localized time formatting -->
@ -181,17 +208,24 @@
<systemPropertyVariables>
<project.skipExtendedHashTests>${project.skipExtendedHashTests}</project.skipExtendedHashTests>
</systemPropertyVariables>
<!-- Don't trim stack traces -->
<trimStackTrace>false</trimStackTrace>
</configuration>
</plugin>
<!-- Generate a jar containing classes and resources -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<version>3.1.1</version>
</plugin>
<!-- Generate a jar containing the source javadoc -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.0.1</version>
<configuration>
<finalName>${project.finalNameBase}</finalName>
</configuration>
<executions>
<execution>
<id>attach-javadoc</id>
@ -199,23 +233,16 @@
<goal>jar</goal>
</goals>
</execution>
<execution>
<id>aggregate-javadoc</id>
<goals>
<goal>aggregate</goal>
</goals>
</execution>
</executions>
<configuration>
<finalName>${project.outputName}-${project.version}</finalName>
<show>public</show>
<failOnError>false</failOnError>
</configuration>
</plugin>
<!-- Generate a jar containing the java sources -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.0.1</version>
<configuration>
<finalName>${project.finalNameBase}</finalName>
</configuration>
<executions>
<execution>
<id>attach-sources</id>
@ -224,14 +251,12 @@
</goals>
</execution>
</executions>
<configuration>
<finalName>${project.outputName}-${project.version}</finalName>
</configuration>
</plugin>
<!-- Generate a jar containing classes, resources and shaded libraries -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.1</version>
<version>3.2.1</version>
<executions>
<execution>
<phase>package</phase>
@ -241,20 +266,18 @@
</execution>
</executions>
<configuration>
<!-- Don't create the reduced pom file, as we don't deploy the shaded jar -->
<createDependencyReducedPom>false</createDependencyReducedPom>
<!-- Deploy the non shaded jar as main artifact -->
<shadedArtifactAttached>true</shadedArtifactAttached>
<finalName>${project.outputName}-${project.version}</finalName>
<!-- Use the base jar name, to help server owners download the right jar -->
<finalName>${project.finalNameBase}</finalName>
<!--
Relocate all lib we use in order to fix class loading errors if we use different versions
than already loaded libs (i.e. by Mojang -> gson)
than already loaded libs
-->
<relocations>
<!-- Include all google libraries, because they are not available before 1.12 -->
<relocation>
<pattern>com.google</pattern>
<shadedPattern>fr.xephi.authme.libs.com.google</shadedPattern>
</relocation>
<relocation>
<pattern>ch.jalu</pattern>
<shadedPattern>fr.xephi.authme.libs.ch.jalu</shadedPattern>
@ -299,15 +322,15 @@
<pattern>at.favre.lib</pattern>
<shadedPattern>fr.xephi.authme.libs.at.favre.lib</shadedPattern>
</relocation>
<relocation>
<pattern>org.postgresql</pattern>
<shadedPattern>fr.xephi.authme.libs.org.postgresql</shadedPattern>
</relocation>
<!-- bStats metrics class -->
<relocation>
<pattern>org.bstats</pattern>
<shadedPattern>fr.xephi.authme.libs.org.bstats</shadedPattern>
</relocation>
<relocation>
<pattern>org.postgresql</pattern>
<shadedPattern>fr.xephi.authme.libs.org.postgresql</shadedPattern>
</relocation>
</relocations>
<filters>
<!-- Ignore manifest signatures for shading the project into an uber-jar to fix -->
@ -323,27 +346,31 @@
</filters>
</configuration>
</plugin>
<!-- Install the jars as artifacts into the local repository -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<!-- Deploy the jars as artifacts into the remote repository -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- Handle documentation generation, required by other plugins -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<!-- Publish coveralls test coverage reports, not included in the build cycle by default -->
<plugin>
<groupId>org.eluder.coveralls</groupId>
<artifactId>coveralls-maven-plugin</artifactId>
<version>4.3.0</version>
<configuration>
<!-- The secret token is provided with a command-line parameter! -->
<!-- The secret token is provided with a command-line parameter -->
<failOnServiceError>false</failOnServiceError>
</configuration>
</plugin>
@ -357,10 +384,16 @@
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots</url>
</repository>
<!-- Essentials Repo -->
<!-- CodeMC Repo (Contains many required libraries) -->
<repository>
<id>ess-repo</id>
<url>http://repo.ess3.net/content/groups/essentials</url>
<id>codemc-repo</id>
<url>https://repo.codemc.org/repository/maven-public/</url>
</repository>
<!-- EssentialsX Repo -->
<repository>
<id>enderzone-repo</id>
<url>https://ci.ender.zone/plugin/repository/everything</url>
</repository>
<!-- ProtocolLib Repo -->
@ -380,18 +413,6 @@
<id>vault-repo</id>
<url>http://nexus.hc.to/content/repositories/pub_releases</url>
</repository>
<!-- Our Repo (Many libs) -->
<repository>
<id>codemc-repo</id>
<url>https://repo.codemc.org/repository/maven-public/</url>
</repository>
<!-- bStats Repo -->
<repository>
<id>bstats-repo</id>
<url>http://repo.bstats.org/content/groups/public</url>
</repository>
</repositories>
<dependencies>
@ -413,22 +434,6 @@
<optional>true</optional>
</dependency>
<!-- GSON (required to provide 1.7.10 and below compatibility) -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
<optional>true</optional>
</dependency>
<!-- Guava (required to allow compatibility with any version since 1.7.10) -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>26.0-jre</version>
<optional>true</optional>
</dependency>
<!-- MaxMind GEO IP with our modifications to use GSON in replacement of the big Jackson dependency -->
<!-- GSON is already included and therefore it reduces the file size in comparison to the original version -->
<dependency>
@ -436,6 +441,12 @@
<artifactId>maxmind-db-gson</artifactId>
<version>2.0.2-SNAPSHOT</version>
<optional>true</optional>
<exclusions>
<exclusion>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Library for tar archives -->
@ -466,7 +477,7 @@
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>3.2.0</version>
<version>3.3.1</version>
<optional>true</optional>
<exclusions>
<exclusion>
@ -479,7 +490,7 @@
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.25</version>
<version>1.7.26</version>
<optional>true</optional>
</dependency>
@ -495,7 +506,7 @@
<dependency>
<groupId>de.mkammerer</groupId>
<artifactId>argon2-jvm-nolibs</artifactId>
<version>2.4</version>
<version>2.5</version>
<optional>true</optional>
</dependency>
@ -511,31 +522,37 @@
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>${bukkit.version}</version>
<version>${spigot.version}</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<artifactId>junit</artifactId>
<groupId>junit</groupId>
</exclusion>
<exclusion>
<artifactId>persistence-api</artifactId>
<groupId>javax.persistence</groupId>
</exclusion>
<exclusion>
<artifactId>guava</artifactId>
<groupId>com.google.guava</groupId>
</exclusion>
<exclusion>
<artifactId>bungeecord-chat</artifactId>
<groupId>net.md-5</groupId>
</exclusion>
<exclusion>
<artifactId>gson</artifactId>
<groupId>com.google.code.gson</groupId>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Keep in sync with spigot 1.8.8 -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>17.0</version>
<scope>provided</scope>
</dependency>
<!-- Keep in sync with spigot 1.8.8 -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.2.4</version>
<scope>provided</scope>
</dependency>
<!-- Bukkit Libraries -->
@ -557,7 +574,7 @@
<dependency>
<groupId>org.bstats</groupId>
<artifactId>bstats-bukkit</artifactId>
<version>1.2</version>
<version>1.4</version>
<optional>true</optional>
</dependency>
@ -565,7 +582,7 @@
<dependency>
<groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib-API</artifactId>
<version>4.3.0</version>
<version>4.4.0</version>
<scope>provided</scope>
<exclusions>
<exclusion>
@ -583,7 +600,7 @@
<dependency>
<groupId>me.lucko.luckperms</groupId>
<artifactId>luckperms-api</artifactId>
<version>4.2</version>
<version>4.3</version>
<scope>provided</scope>
</dependency>
@ -766,29 +783,19 @@
</exclusions>
</dependency>
<!-- Essentials plugin -->
<!-- EssentialsX plugin -->
<dependency>
<groupId>net.ess3</groupId>
<artifactId>Essentials</artifactId>
<version>2.13.1</version>
<artifactId>EssentialsX</artifactId>
<version>2.15.0</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
</exclusion>
<exclusion>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- BCrypt implementation -->
<dependency>
<groupId>at.favre.lib</groupId>
<artifactId>bcrypt</artifactId>
<version>0.5.0</version>
<version>0.7.0</version>
<optional>true</optional>
</dependency>
@ -867,7 +874,7 @@
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
<version>2.22.0</version>
<version>2.24.5</version>
<exclusions>
<exclusion>
<artifactId>hamcrest-core</artifactId>
@ -876,17 +883,25 @@
</exclusions>
</dependency>
<!-- Required to mock the LuckPerms API-->
<dependency>
<groupId>org.checkerframework</groupId>
<artifactId>checker-qual</artifactId>
<version>2.6.0</version>
<scope>test</scope>
</dependency>
<!-- JDBC drivers for datasource integration tests -->
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.23.1</version>
<version>3.25.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.197</version>
<version>1.4.198</version>
<scope>test</scope>
</dependency>

View File

@ -3,24 +3,11 @@ package fr.xephi.authme;
import ch.jalu.injector.Injector;
import ch.jalu.injector.InjectorBuilder;
import com.google.common.annotations.VisibleForTesting;
import fr.xephi.authme.api.NewAPI;
import fr.xephi.authme.api.v3.AuthMeApi;
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 fr.xephi.authme.initialization.SettingsProvider;
import fr.xephi.authme.initialization.TaskCloser;
import fr.xephi.authme.listener.BlockListener;
import fr.xephi.authme.listener.EntityListener;
import fr.xephi.authme.listener.PlayerListener;
import fr.xephi.authme.listener.PlayerListener111;
import fr.xephi.authme.listener.PlayerListener16;
import fr.xephi.authme.listener.PlayerListener18;
import fr.xephi.authme.listener.PlayerListener19;
import fr.xephi.authme.listener.PlayerListener19Spigot;
import fr.xephi.authme.listener.ServerListener;
import fr.xephi.authme.initialization.*;
import fr.xephi.authme.listener.*;
import fr.xephi.authme.security.crypts.Sha256;
import fr.xephi.authme.service.BackupService;
import fr.xephi.authme.service.BukkitService;
@ -112,17 +99,6 @@ public class AuthMe extends JavaPlugin {
return pluginBuildNumber;
}
/**
* Method used to obtain the v2 plugin's api instance
* @deprecated Will be removed in 5.5, use {@link fr.xephi.authme.api.v3.AuthMeApi} instead
*
* @return The plugin's api instance
*/
@Deprecated
public static NewAPI getApi() {
return NewAPI.getInstance();
}
/**
* Method called when the server enables the plugin.
*/
@ -131,6 +107,21 @@ public class AuthMe extends JavaPlugin {
// Load the plugin version data from the plugin description file
loadPluginInfo(getDescription().getVersion());
// Check server version
if (!isClassLoaded("org.bukkit.event.player.PlayerInteractAtEntityEvent")) {
ConsoleLogger.warning("You are running an unsupported server version! AuthMe requires MC 1.8.X or later!");
stopOrUnload();
return;
}
// Prevent running AuthMeBridge due to major exploit issues
if (getServer().getPluginManager().isPluginEnabled("AuthMeBridge")) {
ConsoleLogger.warning("Detected AuthMeBridge, support for it has been dropped as it was "
+ "causing exploit issues, please use AuthMeBungee instead! Aborting!");
stopOrUnload();
return;
}
// Initialize the plugin
try {
initialize();
@ -155,11 +146,6 @@ public class AuthMe extends JavaPlugin {
// Set up Metrics
OnStartupTasks.sendMetrics(this, settings);
// Sponsor messages
ConsoleLogger.info("Development builds are available on our jenkins, thanks to FastVM.io");
ConsoleLogger.info("Do you want a good vps for your game server? Look at our sponsor FastVM.io leader "
+ "as virtual server provider!");
// Successful message
ConsoleLogger.info("AuthMe " + getPluginVersion() + " build n." + getPluginBuildNumber()
+ " correctly enabled!");
@ -257,8 +243,7 @@ public class AuthMe extends JavaPlugin {
injector.getSingleton(BungeeReceiver.class);
// Trigger construction of API classes; they will keep track of the singleton
injector.getSingleton(fr.xephi.authme.api.v3.AuthMeApi.class);
injector.getSingleton(NewAPI.class);
injector.getSingleton(AuthMeApi.class);
}
/**
@ -276,16 +261,6 @@ public class AuthMe extends JavaPlugin {
pluginManager.registerEvents(injector.getSingleton(EntityListener.class), this);
pluginManager.registerEvents(injector.getSingleton(ServerListener.class), this);
// Try to register 1.6 player listeners
if (isClassLoaded("org.bukkit.event.player.PlayerEditBookEvent")) {
pluginManager.registerEvents(injector.getSingleton(PlayerListener16.class), this);
}
// Try to register 1.8 player listeners
if (isClassLoaded("org.bukkit.event.player.PlayerInteractAtEntityEvent")) {
pluginManager.registerEvents(injector.getSingleton(PlayerListener18.class), this);
}
// Try to register 1.9 player listeners
if (isClassLoaded("org.bukkit.event.player.PlayerSwapHandItemsEvent")) {
pluginManager.registerEvents(injector.getSingleton(PlayerListener19.class), this);
@ -345,7 +320,6 @@ public class AuthMe extends JavaPlugin {
* @param cmd The command (Bukkit).
* @param commandLabel The command label (Bukkit).
* @param args The command arguments (Bukkit).
*
* @return True if the command was executed, false otherwise.
*/
@Override

View File

@ -1,258 +0,0 @@
package fr.xephi.authme.api;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.data.auth.PlayerAuth;
import fr.xephi.authme.data.auth.PlayerCache;
import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.process.Management;
import fr.xephi.authme.process.register.executors.ApiPasswordRegisterParams;
import fr.xephi.authme.process.register.executors.RegistrationMethod;
import fr.xephi.authme.security.PasswordSecurity;
import fr.xephi.authme.security.crypts.HashedPassword;
import fr.xephi.authme.service.ValidationService;
import fr.xephi.authme.util.PlayerUtils;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import javax.inject.Inject;
import java.util.ArrayList;
import java.util.List;
/**
* The v2 API of AuthMe.
*
* Recommended method of retrieving the API object:
* <code>
* NewAPI authmeApi = NewAPI.getInstance();
* </code>
*
* @deprecated Will be removed in 5.5! Use {@link fr.xephi.authme.api.v3.AuthMeApi} instead.
*/
@SuppressWarnings({"checkstyle:AbbreviationAsWordInName"}) // Justification: Class name cannot be changed anymore
@Deprecated
public class NewAPI {
private static NewAPI singleton;
private final AuthMe plugin;
private final DataSource dataSource;
private final PasswordSecurity passwordSecurity;
private final Management management;
private final ValidationService validationService;
private final PlayerCache playerCache;
/*
* Constructor for NewAPI.
*/
@Inject
NewAPI(AuthMe plugin, DataSource dataSource, PasswordSecurity passwordSecurity,
Management management, ValidationService validationService, PlayerCache playerCache) {
this.plugin = plugin;
this.dataSource = dataSource;
this.passwordSecurity = passwordSecurity;
this.management = management;
this.validationService = validationService;
this.playerCache = playerCache;
NewAPI.singleton = this;
}
/**
* Get the API object for AuthMe.
*
* @return The API object, or null if the AuthMe plugin is not enabled or not fully initialized yet
*/
public static NewAPI getInstance() {
return singleton;
}
/**
* Return the plugin instance.
*
* @return The AuthMe instance
*/
public AuthMe getPlugin() {
return plugin;
}
/**
* Gather the version number of the plugin.
* This can be used to determine whether certain API features are available or not.
*
* @return Plugin version identifier as a string.
*/
public String getPluginVersion() {
return AuthMe.getPluginVersion();
}
/**
* Return whether the given player is authenticated.
*
* @param player The player to verify
* @return true if the player is authenticated
*/
public boolean isAuthenticated(Player player) {
return playerCache.isAuthenticated(player.getName());
}
/**
* Check whether the given player is an NPC.
*
* @param player The player to verify
* @return true if the player is an npc
*/
public boolean isNPC(Player player) {
return PlayerUtils.isNpc(player);
}
/**
* Check whether the given player is unrestricted. For such players, AuthMe will not require
* them to authenticate.
*
* @param player The player to verify
* @return true if the player is unrestricted
* @see fr.xephi.authme.settings.properties.RestrictionSettings#UNRESTRICTED_NAMES
*/
public boolean isUnrestricted(Player player) {
return validationService.isUnrestricted(player.getName());
}
/**
* Get the last location of an online player.
*
* @param player The player to process
* @return Location The location of the player
*/
public Location getLastLocation(Player player) {
PlayerAuth auth = playerCache.getAuth(player.getName());
if (auth != null) {
return new Location(Bukkit.getWorld(auth.getWorld()),
auth.getQuitLocX(), auth.getQuitLocY(), auth.getQuitLocZ());
}
return null;
}
/**
* Return whether the player is registered.
*
* @param playerName The player name to check
* @return true if player is registered, false otherwise
*/
public boolean isRegistered(String playerName) {
String player = playerName.toLowerCase();
return dataSource.isAuthAvailable(player);
}
/**
* Check the password for the given player.
*
* @param playerName The player to check the password for
* @param passwordToCheck The password to check
* @return true if the password is correct, false otherwise
*/
public boolean checkPassword(String playerName, String passwordToCheck) {
return passwordSecurity.comparePassword(passwordToCheck, playerName);
}
/**
* Register an OFFLINE/ONLINE player with the given password.
*
* @param playerName The player to register
* @param password The password to register the player with
*
* @return true if the player was registered successfully
*/
public boolean registerPlayer(String playerName, String password) {
String name = playerName.toLowerCase();
if (isRegistered(name)) {
return false;
}
HashedPassword result = passwordSecurity.computeHash(password, name);
PlayerAuth auth = PlayerAuth.builder()
.name(name)
.password(result)
.realName(playerName)
.registrationDate(System.currentTimeMillis())
.build();
return dataSource.saveAuth(auth);
}
/**
* Force a player to login, i.e. the player is logged in without needing his password.
*
* @param player The player to log in
*/
public void forceLogin(Player player) {
management.forceLogin(player);
}
/**
* Force a player to logout.
*
* @param player The player to log out
*/
public void forceLogout(Player player) {
management.performLogout(player);
}
/**
* Force an ONLINE player to register.
*
* @param player The player to register
* @param password The password to use
* @param autoLogin Should the player be authenticated automatically after the registration?
*/
public void forceRegister(Player player, String password, boolean autoLogin) {
management.performRegister(RegistrationMethod.API_REGISTRATION,
ApiPasswordRegisterParams.of(player, password, autoLogin));
}
/**
* Register an ONLINE player with the given password.
*
* @param player The player to register
* @param password The password to use
*/
public void forceRegister(Player player, String password) {
forceRegister(player, password, true);
}
/**
* Unregister a player from AuthMe.
*
* @param player The player to unregister
*/
public void forceUnregister(Player player) {
management.performUnregisterByAdmin(null, player.getName(), player);
}
/**
* Unregister a player from AuthMe by name.
*
* @param name the name of the player (case-insensitive)
*/
public void forceUnregister(String name) {
management.performUnregisterByAdmin(null, name, Bukkit.getPlayer(name));
}
/**
* Get all the registered names (lowercase)
*
* @return registered names
*/
public List<String> getRegisteredNames() {
List<String> registeredNames = new ArrayList<>();
dataSource.getAllAuths().forEach(auth -> registeredNames.add(auth.getNickname()));
return registeredNames;
}
/**
* Get all the registered real-names (original case)
*
* @return registered real-names
*/
public List<String> getRegisteredRealNames() {
List<String> registeredNames = new ArrayList<>();
dataSource.getAllAuths().forEach(auth -> registeredNames.add(auth.getRealName()));
return registeredNames;
}
}

View File

@ -36,7 +36,7 @@ public class VersionCommand implements ExecutableCommand {
sender.sendMessage(ChatColor.GOLD + "License: " + ChatColor.WHITE + "GNU GPL v3.0"
+ ChatColor.GRAY + ChatColor.ITALIC + " (See LICENSE file)");
sender.sendMessage(ChatColor.GOLD + "Copyright: " + ChatColor.WHITE
+ "Copyright (c) AuthMe-Team 2017. All rights reserved.");
+ "Copyright (c) AuthMe-Team 2019. Released under GPL v3 License.");
}
/**

View File

@ -4,8 +4,8 @@ import fr.xephi.authme.security.crypts.HashedPassword;
import org.bukkit.Location;
import java.util.Objects;
import java.util.Optional;
import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.common.base.Preconditions.checkNotNull;
@ -227,8 +227,8 @@ public class PlayerAuth {
public PlayerAuth build() {
PlayerAuth auth = new PlayerAuth();
auth.nickname = checkNotNull(name).toLowerCase();
auth.realName = firstNonNull(realName, "Player");
auth.password = firstNonNull(password, new HashedPassword(""));
auth.realName = Optional.ofNullable(realName).orElse("Player");
auth.password = Optional.ofNullable(password).orElse(new HashedPassword(""));
auth.totpKey = totpKey;
auth.email = DB_EMAIL_DEFAULT.equals(email) ? null : email;
auth.lastIp = lastIp; // Don't check against default value 127.0.0.1 as it may be a legit value
@ -240,7 +240,7 @@ public class PlayerAuth {
auth.x = x;
auth.y = y;
auth.z = z;
auth.world = firstNonNull(world, "world");
auth.world = Optional.ofNullable(world).orElse("world");
auth.yaw = yaw;
auth.pitch = pitch;
return auth;

View File

@ -57,7 +57,7 @@ class DistributedFilesPersistenceHandler implements LimboPersistenceHandler {
@Override
public LimboPlayer getLimboPlayer(Player player) {
String uuid = PlayerUtils.getUuidOrName(player);
String uuid = player.getUniqueId().toString();
File file = getPlayerSegmentFile(uuid);
Map<String, LimboPlayer> entries = readLimboPlayers(file);
return entries == null ? null : entries.get(uuid);
@ -65,7 +65,7 @@ class DistributedFilesPersistenceHandler implements LimboPersistenceHandler {
@Override
public void saveLimboPlayer(Player player, LimboPlayer limbo) {
String uuid = PlayerUtils.getUuidOrName(player);
String uuid = player.getUniqueId().toString();
File file = getPlayerSegmentFile(uuid);
Map<String, LimboPlayer> entries = null;
@ -79,17 +79,17 @@ class DistributedFilesPersistenceHandler implements LimboPersistenceHandler {
entries = new HashMap<>();
}
entries.put(PlayerUtils.getUuidOrName(player), limbo);
entries.put(uuid, limbo);
saveEntries(entries, file);
}
@Override
public void removeLimboPlayer(Player player) {
String uuid = PlayerUtils.getUuidOrName(player);
String uuid = player.getUniqueId().toString();
File file = getPlayerSegmentFile(uuid);
if (file.exists()) {
Map<String, LimboPlayer> entries = readLimboPlayers(file);
if (entries != null && entries.remove(PlayerUtils.getUuidOrName(player)) != null) {
if (entries != null && entries.remove(uuid) != null) {
saveEntries(entries, file);
}
}

View File

@ -39,7 +39,7 @@ class IndividualFilesPersistenceHandler implements LimboPersistenceHandler {
@Override
public LimboPlayer getLimboPlayer(Player player) {
String id = PlayerUtils.getUuidOrName(player);
String id = player.getUniqueId().toString();
File file = new File(cacheDir, id + File.separator + "data.json");
if (!file.exists()) {
return null;
@ -56,7 +56,7 @@ class IndividualFilesPersistenceHandler implements LimboPersistenceHandler {
@Override
public void saveLimboPlayer(Player player, LimboPlayer limboPlayer) {
String id = PlayerUtils.getUuidOrName(player);
String id = player.getUniqueId().toString();
try {
File file = new File(cacheDir, id + File.separator + "data.json");
Files.createParentDirs(file);
@ -75,7 +75,7 @@ class IndividualFilesPersistenceHandler implements LimboPersistenceHandler {
*/
@Override
public void removeLimboPlayer(Player player) {
String id = PlayerUtils.getUuidOrName(player);
String id = player.getUniqueId().toString();
File file = new File(cacheDir, id);
if (file.exists()) {
FileUtils.purgeDirectory(file);

View File

@ -9,9 +9,6 @@ public enum DataSourceType {
POSTGRESQL,
SQLITE,
@Deprecated
FILE
SQLITE
}

View File

@ -1,437 +0,0 @@
package fr.xephi.authme.datasource;
import ch.jalu.datasourcecolumns.data.DataSourceValue;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.data.auth.PlayerAuth;
import fr.xephi.authme.security.crypts.HashedPassword;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
/**
* Deprecated flat file datasource. The only method guaranteed to work is {@link FlatFile#getAllAuths()}
* as to migrate the entries to {@link SQLite} when AuthMe starts.
*/
@Deprecated
public class FlatFile implements DataSource {
/*
* file layout:
*
* PLAYERNAME:HASHSUM:IP:LOGININMILLIESECONDS:LASTPOSX:LASTPOSY:LASTPOSZ:
* LASTPOSWORLD:EMAIL
*
* Old but compatible:
* PLAYERNAME:HASHSUM:IP:LOGININMILLIESECONDS:LASTPOSX:LASTPOSY
* :LASTPOSZ:LASTPOSWORLD PLAYERNAME:HASHSUM:IP:LOGININMILLIESECONDS
* PLAYERNAME:HASHSUM:IP PLAYERNAME:HASHSUM
*/
private final File source;
public FlatFile(File source) throws IOException {
this.source = source;
if (!source.exists() && !source.createNewFile()) {
throw new IOException("Could not create file '" + source.getPath() + "'");
}
}
@Override
public void reload() {
throw new UnsupportedOperationException("Flatfile no longer supported");
}
@Override
public synchronized boolean isAuthAvailable(String user) {
try (BufferedReader br = new BufferedReader(new FileReader(source))) {
String line;
while ((line = br.readLine()) != null) {
String[] args = line.split(":");
if (args.length > 1 && args[0].equalsIgnoreCase(user)) {
return true;
}
}
} catch (IOException ex) {
ConsoleLogger.warning(ex.getMessage());
return false;
}
return false;
}
@Override
public HashedPassword getPassword(String user) {
PlayerAuth auth = getAuth(user);
if (auth != null) {
return auth.getPassword();
}
return null;
}
@Override
public synchronized boolean saveAuth(PlayerAuth auth) {
if (isAuthAvailable(auth.getNickname())) {
return false;
}
try (BufferedWriter bw = new BufferedWriter(new FileWriter(source, true))) {
bw.write(auth.getNickname() + ":" + auth.getPassword().getHash() + ":" + auth.getLastIp()
+ ":" + auth.getLastLogin() + ":" + auth.getQuitLocX() + ":" + auth.getQuitLocY()
+ ":" + auth.getQuitLocZ() + ":" + auth.getWorld() + ":" + auth.getEmail() + "\n");
} catch (IOException ex) {
ConsoleLogger.warning(ex.getMessage());
return false;
}
return true;
}
@Override
public synchronized boolean updatePassword(PlayerAuth auth) {
return updatePassword(auth.getNickname(), auth.getPassword());
}
@Override
// Note ljacqu 20151230: This does not persist the salt; it is not supported in flat file.
public boolean updatePassword(String user, HashedPassword password) {
user = user.toLowerCase();
if (!isAuthAvailable(user)) {
return false;
}
PlayerAuth newAuth = null;
try (BufferedReader br = new BufferedReader(new FileReader(source))) {
String line;
while ((line = br.readLine()) != null) {
String[] args = line.split(":");
if (args[0].equals(user)) {
newAuth = buildAuthFromArray(args);
if (newAuth != null) {
newAuth.setPassword(password);
}
break;
}
}
} catch (IOException ex) {
ConsoleLogger.warning(ex.getMessage());
return false;
}
if (newAuth != null) {
removeAuth(user);
saveAuth(newAuth);
}
return true;
}
@Override
public boolean updateSession(PlayerAuth auth) {
if (!isAuthAvailable(auth.getNickname())) {
return false;
}
PlayerAuth newAuth = null;
try (BufferedReader br = new BufferedReader(new FileReader(source))) {
String line;
while ((line = br.readLine()) != null) {
String[] args = line.split(":");
if (args[0].equalsIgnoreCase(auth.getNickname())) {
newAuth = buildAuthFromArray(args);
if (newAuth != null) {
newAuth.setLastLogin(auth.getLastLogin());
newAuth.setLastIp(auth.getLastIp());
}
break;
}
}
} catch (IOException ex) {
ConsoleLogger.warning(ex.getMessage());
return false;
}
if (newAuth != null) {
removeAuth(auth.getNickname());
saveAuth(newAuth);
}
return true;
}
@Override
public boolean updateQuitLoc(PlayerAuth auth) {
if (!isAuthAvailable(auth.getNickname())) {
return false;
}
PlayerAuth newAuth = null;
try (BufferedReader br = new BufferedReader(new FileReader(source))) {
String line;
while ((line = br.readLine()) != null) {
String[] args = line.split(":");
if (args[0].equalsIgnoreCase(auth.getNickname())) {
newAuth = buildAuthFromArray(args);
if (newAuth != null) {
newAuth.setQuitLocX(auth.getQuitLocX());
newAuth.setQuitLocY(auth.getQuitLocY());
newAuth.setQuitLocZ(auth.getQuitLocZ());
newAuth.setWorld(auth.getWorld());
newAuth.setEmail(auth.getEmail());
}
break;
}
}
} catch (IOException ex) {
ConsoleLogger.warning(ex.getMessage());
return false;
}
if (newAuth != null) {
removeAuth(auth.getNickname());
saveAuth(newAuth);
}
return true;
}
@Override
public Set<String> getRecordsToPurge(long until) {
throw new UnsupportedOperationException("Flat file no longer supported");
}
@Override
public void purgeRecords(Collection<String> toPurge) {
throw new UnsupportedOperationException("Flat file no longer supported");
}
@Override
public synchronized boolean removeAuth(String user) {
if (!isAuthAvailable(user)) {
return false;
}
ArrayList<String> lines = new ArrayList<>();
try (BufferedReader br = new BufferedReader(new FileReader(source))) {
String line;
while ((line = br.readLine()) != null) {
String[] args = line.split(":");
if (args.length > 1 && !args[0].equals(user)) {
lines.add(line);
}
}
try (BufferedWriter bw = new BufferedWriter(new FileWriter(source))) {
for (String l : lines) {
bw.write(l + "\n");
}
}
} catch (IOException ex) {
ConsoleLogger.warning(ex.getMessage());
return false;
}
return true;
}
@Override
public synchronized PlayerAuth getAuth(String user) {
try (BufferedReader br = new BufferedReader(new FileReader(source))) {
String line;
while ((line = br.readLine()) != null) {
String[] args = line.split(":");
if (args[0].equalsIgnoreCase(user)) {
return buildAuthFromArray(args);
}
}
} catch (IOException ex) {
ConsoleLogger.warning(ex.getMessage());
return null;
}
return null;
}
@Override
public void closeConnection() {
}
@Override
public boolean updateEmail(PlayerAuth auth) {
if (!isAuthAvailable(auth.getNickname())) {
return false;
}
PlayerAuth newAuth = null;
try (BufferedReader br = new BufferedReader(new FileReader(source))) {
String line;
while ((line = br.readLine()) != null) {
String[] args = line.split(":");
if (args[0].equals(auth.getNickname())) {
newAuth = buildAuthFromArray(args);
if (newAuth != null) {
newAuth.setEmail(auth.getEmail());
}
break;
}
}
} catch (IOException ex) {
ConsoleLogger.warning(ex.getMessage());
return false;
}
if (newAuth != null) {
removeAuth(auth.getNickname());
saveAuth(newAuth);
}
return true;
}
@Override
public List<String> getAllAuthsByIp(String ip) {
List<String> countIp = new ArrayList<>();
try (BufferedReader br = new BufferedReader(new FileReader(source))) {
String line;
while ((line = br.readLine()) != null) {
String[] args = line.split(":");
if (args.length > 3 && args[2].equals(ip)) {
countIp.add(args[0]);
}
}
return countIp;
} catch (IOException ex) {
ConsoleLogger.warning(ex.getMessage());
return new ArrayList<>();
}
}
@Override
public int countAuthsByEmail(String email) {
int countEmail = 0;
try (BufferedReader br = new BufferedReader(new FileReader(source))) {
String line;
while ((line = br.readLine()) != null) {
String[] args = line.split(":");
if (args.length > 8 && args[8].equals(email)) {
++countEmail;
}
}
return countEmail;
} catch (IOException ex) {
ConsoleLogger.warning(ex.getMessage());
}
return 0;
}
@Override
public DataSourceType getType() {
return DataSourceType.FILE;
}
@Override
public boolean isLogged(String user) {
throw new UnsupportedOperationException("Flat file no longer supported");
}
@Override
public void setLogged(String user) {
}
@Override
public void setUnlogged(String user) {
}
@Override
public boolean hasSession(String user) {
throw new UnsupportedOperationException("Flat file no longer supported");
}
@Override
public void grantSession(String user) {
}
@Override
public void revokeSession(String user) {
}
@Override
public void purgeLogged() {
}
@Override
public int getAccountsRegistered() {
int result = 0;
try (BufferedReader br = new BufferedReader(new FileReader(source))) {
while ((br.readLine()) != null) {
result++;
}
} catch (Exception ex) {
ConsoleLogger.warning(ex.getMessage());
return result;
}
return result;
}
@Override
public boolean updateRealName(String user, String realName) {
throw new UnsupportedOperationException("Flat file no longer supported");
}
@Override
public DataSourceValue<String> getEmail(String user) {
throw new UnsupportedOperationException("Flat file no longer supported");
}
@Override
public List<PlayerAuth> getAllAuths() {
List<PlayerAuth> auths = new ArrayList<>();
try (BufferedReader br = new BufferedReader(new FileReader(source))) {
String line;
while ((line = br.readLine()) != null) {
String[] args = line.split(":");
PlayerAuth auth = buildAuthFromArray(args);
if (auth != null) {
auths.add(auth);
}
}
} catch (IOException ex) {
ConsoleLogger.logException("Error while getting auths from flatfile:", ex);
}
return auths;
}
@Override
public List<String> getLoggedPlayersWithEmptyMail() {
throw new UnsupportedOperationException("Flat file no longer supported");
}
@Override
public List<PlayerAuth> getRecentlyLoggedInPlayers() {
throw new UnsupportedOperationException("Flat file no longer supported");
}
@Override
public boolean setTotpKey(String user, String totpKey) {
throw new UnsupportedOperationException("Flat file no longer supported");
}
/**
* Creates a PlayerAuth object from the read data.
*
* @param args the data read from the line
* @return the player auth object with the data
*/
@SuppressWarnings("checkstyle:NeedBraces")
private static PlayerAuth buildAuthFromArray(String[] args) {
// Format allows 2, 3, 4, 7, 8, 9 fields. Anything else is unknown
if (args.length >= 2 && args.length <= 9 && args.length != 5 && args.length != 6) {
PlayerAuth.Builder builder = PlayerAuth.builder()
.name(args[0]).realName(args[0]).password(args[1], null);
if (args.length >= 3) builder.lastIp(args[2]);
if (args.length >= 4) builder.lastLogin(parseNullableLong(args[3]));
if (args.length >= 7) {
builder.locX(Double.parseDouble(args[4]))
.locY(Double.parseDouble(args[5]))
.locZ(Double.parseDouble(args[6]));
}
if (args.length >= 8) builder.locWorld(args[7]);
if (args.length >= 9) builder.email(args[8]);
return builder.build();
}
return null;
}
private static Long parseNullableLong(String str) {
return "null".equals(str) ? null : Long.parseLong(str);
}
}

View File

@ -59,49 +59,11 @@ final class MySqlMigrater {
columnType = rs.getInt("DATA_TYPE");
}
if (columnType == Types.TIMESTAMP) {
migrateLastLoginColumnFromTimestamp(st, tableName, col);
} else if (columnType == Types.INTEGER) {
if (columnType == Types.INTEGER) {
migrateLastLoginColumnFromInt(st, tableName, col);
}
}
/**
* Performs conversion of lastlogin column from timestamp type to bigint.
*
* @param st Statement object to the database
* @param tableName the table name
* @param col the column names configuration
* @see <a href="https://github.com/AuthMe/AuthMeReloaded/issues/477">#477</a>
*/
private static void migrateLastLoginColumnFromTimestamp(Statement st, String tableName,
Columns col) throws SQLException {
ConsoleLogger.info("Migrating lastlogin column from timestamp to bigint");
final String lastLoginOld = col.LAST_LOGIN + "_old";
// Rename lastlogin to lastlogin_old
String sql = String.format("ALTER TABLE %s CHANGE COLUMN %s %s BIGINT",
tableName, col.LAST_LOGIN, lastLoginOld);
st.execute(sql);
// Create lastlogin column
sql = String.format("ALTER TABLE %s ADD COLUMN %s "
+ "BIGINT NOT NULL DEFAULT 0 AFTER %s",
tableName, col.LAST_LOGIN, col.LAST_IP);
st.execute(sql);
// Set values of lastlogin based on lastlogin_old
sql = String.format("UPDATE %s SET %s = UNIX_TIMESTAMP(%s) * 1000",
tableName, col.LAST_LOGIN, lastLoginOld);
st.execute(sql);
// Drop lastlogin_old
sql = String.format("ALTER TABLE %s DROP COLUMN %s",
tableName, lastLoginOld);
st.execute(sql);
ConsoleLogger.info("Finished migration of lastlogin (timestamp to bigint)");
}
/**
* Performs conversion of lastlogin column from int to bigint.
*

View File

@ -75,6 +75,8 @@ public class SQLite extends AbstractSqlDataSource {
/**
* Initializes the connection to the SQLite database.
*
* @throws SQLException when an SQL error occurs while connecting
*/
protected void connect() throws SQLException {
try {
@ -90,6 +92,8 @@ public class SQLite extends AbstractSqlDataSource {
/**
* Creates the table if necessary, or adds any missing columns to the table.
*
* @throws SQLException when an SQL error occurs while initializing the database
*/
@VisibleForTesting
protected void setup() throws SQLException {

View File

@ -78,7 +78,7 @@ public final class AuthMeColumnsHandler {
*/
public <T> boolean update(String name, DataSourceColumn<T> column, T value) {
try {
return internalHandler.update(name, column, value);
return internalHandler.update(name.toLowerCase(), column, value);
} catch (SQLException e) {
logSqlException(e);
return false;

View File

@ -2,8 +2,8 @@ package fr.xephi.authme.datasource.columnshandler;
import fr.xephi.authme.settings.Settings;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Context for resolving the properties of {@link AuthMeColumns} entries.
@ -11,7 +11,7 @@ import java.util.Map;
public class ColumnContext {
private final Settings settings;
private final Map<DataSourceColumn<?>, String> columnNames = new HashMap<>();
private final Map<DataSourceColumn<?>, String> columnNames = new ConcurrentHashMap<>();
private final boolean hasDefaultSupport;
/**

View File

@ -1,36 +0,0 @@
package fr.xephi.authme.datasource.converter;
import fr.xephi.authme.data.auth.PlayerAuth;
import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.datasource.FlatFile;
/**
* Mandatory migration from the deprecated flat file datasource to SQLite.
*/
public class ForceFlatToSqlite extends AbstractDataSourceConverter<FlatFile> {
private final FlatFile source;
/**
* Constructor.
*
* @param source The datasource to convert (flatfile)
* @param destination The datasource to copy the data to (sqlite)
*/
public ForceFlatToSqlite(FlatFile source, DataSource destination) {
super(destination, destination.getType());
this.source = source;
}
@Override
public FlatFile getSource() {
return source;
}
@Override
protected void adaptPlayerAuth(PlayerAuth auth) {
// Issue #1120: FlatFile returns PlayerAuth objects with realname = lower-case name all the time.
// We don't want to take this over into the new data source.
auth.setRealName("Player");
}
}

View File

@ -5,8 +5,6 @@ import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import javax.annotation.Nullable;
/**
* This event is called when a player adds or changes his email address.
*/
@ -26,7 +24,7 @@ public class EmailChangedEvent extends CustomEvent implements Cancellable {
* the email is trying to set.
* @param isAsync should this event be called asynchronously?
*/
public EmailChangedEvent(Player player, @Nullable String oldEmail, String newEmail, boolean isAsync) {
public EmailChangedEvent(Player player, String oldEmail, String newEmail, boolean isAsync) {
super(isAsync);
this.player = player;
this.oldEmail = oldEmail;
@ -52,7 +50,7 @@ public class EmailChangedEvent extends CustomEvent implements Cancellable {
*
* @return old email stored on file. Can be null when user never had an email and adds a new one.
*/
public @Nullable String getOldEmail() {
public String getOldEmail() {
return this.oldEmail;
}

View File

@ -5,11 +5,9 @@ import fr.xephi.authme.data.auth.PlayerCache;
import fr.xephi.authme.datasource.CacheDataSource;
import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.datasource.DataSourceType;
import fr.xephi.authme.datasource.FlatFile;
import fr.xephi.authme.datasource.MySQL;
import fr.xephi.authme.datasource.PostgreSqlDataSource;
import fr.xephi.authme.datasource.SQLite;
import fr.xephi.authme.datasource.converter.ForceFlatToSqlite;
import fr.xephi.authme.datasource.mysqlextensions.MySqlExtensionsFactory;
import fr.xephi.authme.service.BukkitService;
import fr.xephi.authme.settings.Settings;
@ -26,7 +24,6 @@ import java.sql.SQLException;
*/
public class DataSourceProvider implements Provider<DataSource> {
private static final String FLATFILE_FILENAME = "auths.db";
private static final int SQLITE_MAX_SIZE = 4000;
@Inject
@ -65,10 +62,6 @@ public class DataSourceProvider implements Provider<DataSource> {
DataSourceType dataSourceType = settings.getProperty(DatabaseSettings.BACKEND);
DataSource dataSource;
switch (dataSourceType) {
case FILE:
File source = new File(dataFolder, FLATFILE_FILENAME);
dataSource = new FlatFile(source);
break;
case MYSQL:
dataSource = new MySQL(settings, mySqlExtensionsFactory);
break;
@ -82,8 +75,6 @@ public class DataSourceProvider implements Provider<DataSource> {
throw new UnsupportedOperationException("Unknown data source type '" + dataSourceType + "'");
}
dataSource = convertFlatfileToSqlite(dataSource);
if (settings.getProperty(DatabaseSettings.USE_CACHING)) {
dataSource = new CacheDataSource(dataSource, playerCache);
}
@ -102,31 +93,4 @@ public class DataSourceProvider implements Provider<DataSource> {
}
});
}
/**
* Converts the data source from the deprecated FLATFILE type to SQLITE.
*
* @param dataSource the data source to convert if necessary
* @return the data source to use: the converted datasource (SQLite),
* or the same data source if no conversion was performed
*/
private DataSource convertFlatfileToSqlite(DataSource dataSource) {
if (DataSourceType.FILE == settings.getProperty(DatabaseSettings.BACKEND)) {
ConsoleLogger.warning("FlatFile backend has been detected and is now deprecated; it will be changed "
+ "to SQLite... Connection will be impossible until conversion is done!");
FlatFile flatFile = (FlatFile) dataSource;
try {
SQLite sqlite = new SQLite(settings, dataFolder);
ForceFlatToSqlite converter = new ForceFlatToSqlite(flatFile, sqlite);
converter.execute(null);
settings.setProperty(DatabaseSettings.BACKEND, DataSourceType.SQLITE);
settings.save();
return sqlite;
} catch (Exception e) {
ConsoleLogger.logException("Error during conversion from Flatfile to SQLite", e);
throw new IllegalStateException(e);
}
}
return dataSource;
}
}

View File

@ -35,24 +35,8 @@ import org.bukkit.event.block.SignChangeEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryOpenEvent;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
import org.bukkit.event.player.PlayerBedEnterEvent;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.event.player.PlayerFishEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerItemConsumeEvent;
import org.bukkit.event.player.PlayerItemHeldEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerKickEvent;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerPickupItemEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.event.player.PlayerShearEntityEvent;
import org.bukkit.event.player.*;
import org.bukkit.inventory.Inventory;
import javax.inject.Inject;
import java.util.HashSet;
@ -284,11 +268,7 @@ public class PlayerListener implements Listener {
// Keep pre-UUID compatibility
try {
try {
permissionsManager.loadUserData(event.getUniqueId());
} catch (NoSuchMethodError e) {
permissionsManager.loadUserData(name);
}
permissionsManager.loadUserData(event.getUniqueId());
} catch (PermissionLoadUserException e) {
ConsoleLogger.logException("Unable to load the permission data of user " + name, e);
}
@ -411,11 +391,20 @@ public class PlayerListener implements Listener {
}
}
private boolean isInventoryWhitelisted(Inventory inventory) {
if (inventory == null) {
return false;
}
Set<String> whitelist = settings.getProperty(RestrictionSettings.UNRESTRICTED_INVENTORIES);
return whitelist.contains(ChatColor.stripColor(inventory.getName()));
}
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
public void onPlayerInventoryOpen(InventoryOpenEvent event) {
final HumanEntity player = event.getPlayer();
if (listenerService.shouldCancelEvent(player)) {
if (listenerService.shouldCancelEvent(player)
&& !isInventoryWhitelisted(event.getInventory())) {
event.setCancelled(true);
/*
@ -428,7 +417,8 @@ public class PlayerListener implements Listener {
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
public void onPlayerInventoryClick(InventoryClickEvent event) {
if (listenerService.shouldCancelEvent(event.getWhoClicked())) {
if (listenerService.shouldCancelEvent(event.getWhoClicked())
&& !isInventoryWhitelisted(event.getClickedInventory())) {
event.setCancelled(true);
}
}
@ -509,4 +499,18 @@ public class PlayerListener implements Listener {
}
}
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
public void onPlayerEditBook(PlayerEditBookEvent event) {
if (listenerService.shouldCancelEvent(event)) {
event.setCancelled(true);
}
}
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
public void onPlayerInteractAtEntity(PlayerInteractAtEntityEvent event) {
if (listenerService.shouldCancelEvent(event)) {
event.setCancelled(true);
}
}
}

View File

@ -1,25 +0,0 @@
package fr.xephi.authme.listener;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerEditBookEvent;
import javax.inject.Inject;
/**
* Listener of player events for events introduced in Minecraft 1.6.
*/
public class PlayerListener16 implements Listener {
@Inject
private ListenerService listenerService;
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
public void onPlayerEditBook(PlayerEditBookEvent event) {
if (listenerService.shouldCancelEvent(event)) {
event.setCancelled(true);
}
}
}

View File

@ -1,25 +0,0 @@
package fr.xephi.authme.listener;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerInteractAtEntityEvent;
import javax.inject.Inject;
/**
* Listener of player events for events introduced in Minecraft 1.8.
*/
public class PlayerListener18 implements Listener {
@Inject
private ListenerService listenerService;
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
public void onPlayerInteractAtEntity(PlayerInteractAtEntityEvent event) {
if (listenerService.shouldCancelEvent(event)) {
event.setCancelled(true);
}
}
}

View File

@ -27,6 +27,8 @@ import com.comphenix.protocol.reflect.StructureModifier;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.data.auth.PlayerCache;
import fr.xephi.authme.service.BukkitService;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
@ -63,8 +65,14 @@ class InventoryPacketAdapter extends PacketAdapter {
}
}
public void register() {
public void register(BukkitService bukkitService, boolean hideNow) {
ProtocolLibrary.getProtocolManager().addPacketListener(this);
if (hideNow) {
bukkitService.getOnlinePlayers().stream()
.filter(player -> playerCache.isAuthenticated(player.getName()))
.forEach(this::sendBlankInventoryPacket);
}
}
public void unregister() {

View File

@ -58,8 +58,9 @@ public class ProtocolLibService implements SettingsDependent {
// Set up packet adapters
if (protectInvBeforeLogin) {
if (inventoryPacketAdapter == null) {
// register the packet listener and start hiding it for all already online players (reload)
inventoryPacketAdapter = new InventoryPacketAdapter(plugin, playerCache);
inventoryPacketAdapter.register();
inventoryPacketAdapter.register(bukkitService, true);
}
} else if (inventoryPacketAdapter != null) {
inventoryPacketAdapter.unregister();

View File

@ -455,11 +455,7 @@ public class PermissionsManager implements Reloadable {
*/
public boolean loadUserData(OfflinePlayer offlinePlayer) {
try {
try {
loadUserData(offlinePlayer.getUniqueId());
} catch (NoSuchMethodError e) {
loadUserData(offlinePlayer.getName());
}
loadUserData(offlinePlayer.getUniqueId());
} catch (PermissionLoadUserException e) {
ConsoleLogger.logException("Unable to load the permission data of user " + offlinePlayer.getName(), e);
return false;
@ -480,16 +476,4 @@ public class PermissionsManager implements Reloadable {
handler.loadUserData(uuid);
}
/**
* Loads the permission data of the given player name.
*
* @param name the name of the player.
* @throws PermissionLoadUserException if the action failed.
*/
public void loadUserData(String name) throws PermissionLoadUserException {
if (!isEnabled()) {
return;
}
handler.loadUserData(name);
}
}

View File

@ -14,7 +14,7 @@ public enum PlayerStatePermission implements PermissionNode {
/**
* Permission node to bypass BungeeCord server teleportation.
*/
BYPASS_BUNGEE_SEND("authme.bypassbungeesend", DefaultPermission.OP_ONLY),
BYPASS_BUNGEE_SEND("authme.bypassbungeesend", DefaultPermission.NOT_ALLOWED),
/**
* Permission for users to bypass force-survival mode.

View File

@ -197,13 +197,4 @@ public class LuckPermsHandler implements PermissionHandler {
}
}
@Override
public void loadUserData(String name) throws PermissionLoadUserException {
try {
UUID uuid = luckPermsApi.getUserManager().lookupUuid(name).get(5, TimeUnit.SECONDS);
loadUserData(uuid);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
throw new PermissionLoadUserException("Unable to load the permission data of the user " + name, e);
}
}
}

View File

@ -110,6 +110,4 @@ public interface PermissionHandler {
default void loadUserData(UUID uuid) throws PermissionLoadUserException {
}
default void loadUserData(String name) throws PermissionLoadUserException {
}
}

View File

@ -1,5 +1,6 @@
package fr.xephi.authme.permission.handlers;
import com.google.common.annotations.VisibleForTesting;
import fr.xephi.authme.permission.PermissionNode;
import fr.xephi.authme.permission.PermissionsSystemType;
import net.milkbowl.vault.permission.Permission;
@ -8,6 +9,7 @@ import org.bukkit.Server;
import org.bukkit.plugin.RegisteredServiceProvider;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
@ -24,7 +26,15 @@ public class VaultHandler implements PermissionHandler {
this.vaultProvider = getVaultPermission(server);
}
private static Permission getVaultPermission(Server server) throws PermissionHandlerException {
/**
* Returns the Vault Permission interface.
*
* @param server the bukkit server instance
* @return the vault permission instance
* @throws PermissionHandlerException if the vault permission instance cannot be retrieved
*/
@VisibleForTesting
Permission getVaultPermission(Server server) throws PermissionHandlerException {
// Get the permissions provider service
RegisteredServiceProvider<Permission> permissionProvider = server
.getServicesManager().getRegistration(Permission.class);
@ -76,7 +86,8 @@ public class VaultHandler implements PermissionHandler {
@Override
public List<String> getGroups(OfflinePlayer player) {
return Arrays.asList(vaultProvider.getPlayerGroups(null, player));
String[] groups = vaultProvider.getPlayerGroups(null, player);
return groups == null ? Collections.emptyList() : Arrays.asList(groups);
}
@Override

View File

@ -83,8 +83,6 @@ public class BackupService {
private boolean doBackup() {
DataSourceType dataSourceType = settings.getProperty(DatabaseSettings.BACKEND);
switch (dataSourceType) {
case FILE:
return performFileBackup("auths.db");
case MYSQL:
return performMySqlBackup();
case SQLITE:

View File

@ -2,7 +2,6 @@ package fr.xephi.authme.service;
import com.google.common.collect.Iterables;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.initialization.SettingsDependent;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.PluginSettings;
@ -20,11 +19,8 @@ import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.scheduler.BukkitTask;
import javax.inject.Inject;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Optional;
import java.util.Set;
@ -41,14 +37,12 @@ public class BukkitService implements SettingsDependent {
public static final int TICKS_PER_MINUTE = 60 * TICKS_PER_SECOND;
private final AuthMe authMe;
private final boolean getOnlinePlayersIsCollection;
private Method getOnlinePlayers;
private boolean useAsyncTasks;
@Inject
BukkitService(AuthMe authMe, Settings settings) {
this.authMe = authMe;
getOnlinePlayersIsCollection = doesOnlinePlayersMethodReturnCollection();
reload(settings);
}
@ -237,40 +231,12 @@ public class BukkitService implements SettingsDependent {
}
/**
* Safe way to retrieve the list of online players from the server. Depending on the
* implementation of the server, either an array of {@link Player} instances is being returned,
* or a Collection. Always use this wrapper to retrieve online players instead of {@link
* Bukkit#getOnlinePlayers()} directly.
* Gets a view of all currently online players.
*
* @return collection of online players
*
* @see <a href="https://www.spigotmc.org/threads/solved-cant-use-new-getonlineplayers.33061/">SpigotMC
* forum</a>
* @see <a href="http://stackoverflow.com/questions/32130851/player-changed-from-array-to-collection">StackOverflow</a>
*/
@SuppressWarnings("unchecked")
public Collection<? extends Player> getOnlinePlayers() {
if (getOnlinePlayersIsCollection) {
return Bukkit.getOnlinePlayers();
}
try {
// The lookup of a method via Reflections is rather expensive, so we keep a reference to it
if (getOnlinePlayers == null) {
getOnlinePlayers = Bukkit.class.getDeclaredMethod("getOnlinePlayers");
}
Object obj = getOnlinePlayers.invoke(null);
if (obj instanceof Collection<?>) {
return (Collection<? extends Player>) obj;
} else if (obj instanceof Player[]) {
return Arrays.asList((Player[]) obj);
} else {
String type = (obj == null) ? "null" : obj.getClass().getName();
ConsoleLogger.warning("Unknown list of online players of type " + type);
}
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
ConsoleLogger.logException("Could not retrieve list of online players:", e);
}
return Collections.emptyList();
return Bukkit.getOnlinePlayers();
}
/**
@ -346,23 +312,6 @@ public class BukkitService implements SettingsDependent {
}
}
/**
* Method run upon initialization to verify whether or not the Bukkit implementation
* returns the online players as a {@link Collection}.
*
* @return true if a collection is returned by the bukkit implementation, false otherwise
* @see #getOnlinePlayers()
*/
private static boolean doesOnlinePlayersMethodReturnCollection() {
try {
Method method = Bukkit.class.getDeclaredMethod("getOnlinePlayers");
return method.getReturnType() == Collection.class;
} catch (NoSuchMethodException e) {
ConsoleLogger.warning("Error verifying if getOnlinePlayers is a collection! Method doesn't exist");
}
return false;
}
/**
* Adds a ban to the this list. If a previous ban exists, this will
* update the previous entry.

View File

@ -56,9 +56,10 @@ public class BungeeReceiver implements PluginMessageListener, SettingsDependent
final ByteArrayDataInput dataIn = ByteStreams.newDataInput(dataBytes);
// Parse type
final Optional<MessageType> type = MessageType.fromId(dataIn.readUTF());
final String typeId = dataIn.readUTF();
final Optional<MessageType> type = MessageType.fromId(typeId);
if (!type.isPresent()) {
ConsoleLogger.debug("Received unsupported forwarded bungeecord message type! ({0})", type);
ConsoleLogger.debug("Received unsupported forwarded bungeecord message type! ({0})", typeId);
return;
}
@ -88,9 +89,10 @@ public class BungeeReceiver implements PluginMessageListener, SettingsDependent
private void handle(final ByteArrayDataInput in) {
// Parse type
final Optional<MessageType> type = MessageType.fromId(in.readUTF());
final String typeId = in.readUTF();
final Optional<MessageType> type = MessageType.fromId(typeId);
if (!type.isPresent()) {
ConsoleLogger.debug("Received unsupported bungeecord message type! ({0})", type);
ConsoleLogger.debug("Received unsupported bungeecord message type! ({0})", typeId);
return;
}

View File

@ -2,7 +2,7 @@ package fr.xephi.authme.service.yaml;
import ch.jalu.configme.exception.ConfigMeException;
import static com.google.common.base.MoreObjects.firstNonNull;
import java.util.Optional;
/**
* Exception when a YAML file could not be parsed.
@ -18,7 +18,7 @@ public class YamlParseException extends RuntimeException {
* @param configMeException the caught exception from ConfigMe
*/
public YamlParseException(String file, ConfigMeException configMeException) {
super(firstNonNull(configMeException.getCause(), configMeException));
super(Optional.ofNullable(configMeException.getCause()).orElse(configMeException));
this.file = file;
}

View File

@ -4,7 +4,6 @@ import ch.jalu.configme.configurationdata.ConfigurationData;
import ch.jalu.configme.migration.PlainMigrationService;
import ch.jalu.configme.properties.Property;
import ch.jalu.configme.resource.PropertyReader;
import com.google.common.base.MoreObjects;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.initialization.DataFolder;
import fr.xephi.authme.output.LogLevel;
@ -23,6 +22,7 @@ import java.io.FileWriter;
import java.io.IOException;
import java.util.EnumSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import static ch.jalu.configme.properties.PropertyInitializer.newListProperty;
@ -229,7 +229,7 @@ public class SettingsMigrationService extends PlainMigrationService {
final Property<LogLevel> newProperty = PluginSettings.LOG_LEVEL;
if (!newProperty.isPresent(reader) && reader.contains(oldPath)) {
ConsoleLogger.info("Moving '" + oldPath + "' to '" + newProperty.getPath() + "'");
boolean oldValue = MoreObjects.firstNonNull(reader.getBoolean(oldPath), false);
boolean oldValue = Optional.ofNullable(reader.getBoolean(oldPath)).orElse(false);
LogLevel level = oldValue ? LogLevel.INFO : LogLevel.FINE;
configData.setValue(newProperty, level);
return true;

View File

@ -74,6 +74,10 @@ public class WelcomeMessageConfiguration implements Reloadable {
@PostConstruct
@Override
public void reload() {
if (!(service.getProperty(RegistrationSettings.USE_WELCOME_MESSAGE))) {
return;
}
List<String> welcomeMessage = new ArrayList<>();
for (String line : readWelcomeFile()) {
welcomeMessage.add(ChatColor.translateAlternateColorCodes('&', line));
@ -111,6 +115,10 @@ public class WelcomeMessageConfiguration implements Reloadable {
* @return the lines of the welcome message file
*/
private List<String> readWelcomeFile() {
if (!(service.getProperty(RegistrationSettings.USE_WELCOME_MESSAGE))) {
return Collections.emptyList();
}
File welcomeFile = new File(pluginFolder, "welcome.txt");
if (copyFileFromResource(welcomeFile, "welcome.txt")) {
try {

View File

@ -181,6 +181,18 @@ 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!!",
"This option adds compatibility with some mods.",
"It is case-insensitive! Example:",
"UnrestrictedInventories:",
"- 'myCustomInventory1'",
"- 'myCustomInventory2'"
})
public static final Property<Set<String>> UNRESTRICTED_INVENTORIES =
newLowercaseStringSetProperty("settings.unrestrictions.UnrestrictedInventories");
private RestrictionSettings() {
}

View File

@ -7,7 +7,6 @@ import fr.xephi.authme.service.BukkitService;
import fr.xephi.authme.service.PluginHookService;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.PurgeSettings;
import fr.xephi.authme.util.PlayerUtils;
import org.bukkit.ChatColor;
import org.bukkit.OfflinePlayer;
import org.bukkit.Server;
@ -160,7 +159,7 @@ public class PurgeExecutor {
makePath(settings.getProperty(PurgeSettings.DEFAULT_WORLD), "players"));
for (OfflinePlayer offlinePlayer : cleared) {
File playerFile = new File(dataFolder, PlayerUtils.getUuidOrName(offlinePlayer) + ".dat");
File playerFile = new File(dataFolder, offlinePlayer.getUniqueId() + ".dat");
if (playerFile.delete()) {
i++;
}
@ -192,7 +191,7 @@ public class PurgeExecutor {
int deletedFiles = 0;
for (OfflinePlayer offlinePlayer : cleared) {
File playerFile = new File(userDataFolder, PlayerUtils.getUuidOrName(offlinePlayer) + ".yml");
File playerFile = new File(userDataFolder, offlinePlayer.getUniqueId() + ".yml");
if (playerFile.exists() && playerFile.delete()) {
deletedFiles++;
}

View File

@ -1,6 +1,5 @@
package fr.xephi.authme.util;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
/**
@ -12,42 +11,24 @@ public final class PlayerUtils {
private PlayerUtils() {
}
/**
* Get player's UUID if can, name otherwise.
*
* @param player Player to retrieve
*
* @return player's UUID or Name in String.
*/
public static String getUuidOrName(OfflinePlayer player) {
// We may made this configurable in future
// so we can have uuid support.
try {
return player.getUniqueId().toString();
} catch (NoSuchMethodError ignore) {
return player.getName();
}
}
/**
* Returns the IP of the given player.
*
* @param p The player to return the IP address for
*
* @param player The player to return the IP address for
* @return The player's IP address
*/
public static String getPlayerIp(Player p) {
return p.getAddress().getAddress().getHostAddress();
public static String getPlayerIp(Player player) {
return player.getAddress().getAddress().getHostAddress();
}
/**
* Returns if the player is an NPC or not.
*
* @param player The player to check
*
* @return True if the player is an NPC, false otherwise
*/
public static boolean isNpc(Player player) {
return player.hasMetadata("NPC");
return player.hasMetadata("NPC");
}
}

View File

@ -0,0 +1,335 @@
common:
header: ==========[ AuthMeReloaded - Помощ ]==========
optional: Опция
hasPermission: Имате права
noPermission: Нямате права
default: Стандартно
result: Резултат
defaultPermissions:
notAllowed: Не е разрешено
opOnly: Само за Оператори (OP)
allowed: Позволено за всички
section:
command: Команда
description: Кратко описание
detailedDescription: Подробно описание
arguments: Аргументи
alternatives: Алтернативи
permissions: Права
children: Команди
commands:
authme:
description: AuthMe op commands
detailedDescription: The main AuthMeReloaded command. The root for all admin commands.
authme.register:
description: Регистриране на играч
detailedDescription: Регистриране на играч с дадена парола.
arg1:
label: Играч
description: Име на играча
arg2:
label: парола
description: Парола
authme.unregister:
description: Премахване на регистрацията на играча
detailedDescription: Премахване на регистрацията на даден играч от базата данни.
arg1:
label: играч
description: име на играча
authme.forcelogin:
description: Удостоверяване на играча
detailedDescription: Удостоверяване на даденият играч.
arg1:
label: играч
description: име на играча
authme.password:
description: Промяна на парола
detailedDescription: Променя паролата на дадения играч.
arg1:
label: играч
description: име на играча
arg2:
label: парола
description: нова парола
authme.lastlogin:
description: Последен вход на играча
detailedDescription: Показва дата и час на последното влизане на дадения играч.
arg1:
label: играч
description: име на играча
authme.accounts:
description: Акаунти на играча
detailedDescription: Изброява всички акаунти на играча, според името и IP-адреса
arg1:
label: играч
description: име на играча или IP-адрес
authme.email:
description: Имейл адрес на играча
detailedDescription: Показва имейл адреса на посочения играч.
arg1:
label: играч
description: име на играча
authme.setemail:
description: Смяна на имейл на играча.
detailedDescription: Променя имейл адреса на дадения играч.
arg1:
label: играч
description: име на играча
arg2:
label: имейл
description: имейл на играча
authme.getip:
description: IP-адрес
detailedDescription: Показва текущият IP-адрес на посочения играч.
arg1:
label: играч
description: име на играча
authme.spawn:
description: Място на съживяване
detailedDescription: Телепортиране на мястото на съживяване.
authme.setspawn:
description: Задаване на място на съживяване.
detailedDescription: Задава точката на съживяване на текущото местонахождение.
authme.firstspawn:
description: Първоначално място на съживяване.
detailedDescription: Избира се първоначалното място на съживяване.
authme.setfirstspawn:
description: Задаване на първоначално място на съживяване.
detailedDescription: Задава първоначалната точка на съживяване на текущото местонахождение.
authme.purge:
description: Изтриване на стари данни.
detailedDescription: Изтрива стари данни според указаното количество дни.
arg1:
label: дни
description: брой дни
authme.purgeplayer:
description: Изтрива данните на даден играч.
detailedDescription: Изтрива всички данни на даден играч.
arg1:
label: Играч
description: Името на играча, за което трябва да се изтрият данните.
arg2:
label: Опции
description: '''force'' за да се изтрие без проверка дали играча е регистриран.'
authme.backup:
description: Създаване на резервно копие
detailedDescription: Създава резервно копие на всички регистрирани играчи.
authme.resetpos:
description: Рестартиране позиция на играч
detailedDescription: Рестартира последното известно местонахождение на указания
играч, или на всички играчи.
arg1:
label: играч|*
description: име на играча/всички играчи
authme.purgebannedplayers:
description: Изтриване на данни за блокирани играчи.
detailedDescription: Изтрива всички данни за блокираните играчи от базата данни.
authme.switchantibot:
description: Промяна на AntiBot-режима
detailedDescription: Променя режима на AntiBot системата според указанието.
arg1:
label: ON|OFF
description: включено/изключено
authme.reload:
description: Презареждане на плъгина.
detailedDescription: Презарежда плъгина AuthMeReloaded.
authme.version:
description: Информация за версията
detailedDescription: Показва подробна информация за версията на AuthMeReloaded,
неговите разработчици, помощници и лиценз.
authme.converter:
description: Преобразувател
detailedDescription: Преубразовател за базата данни.
arg1:
label: тип
description: 'тип преобразуване: xauth / crazylogin / rakamak / royalauth /
vauth / sqliteToSql / mysqlToSqlite'
authme.messages:
description: Добавяне на липсващи съобщения в помощния файл.
detailedDescription: Добавя всички стойности (на англ. език) в помощният файл.
authme.recent:
description: Проверка на скоро влизалите играчи.
detailedDescription: Показва последните играчи, които са били успешно влезли в играта.
authme.debug:
description: Отстраняване на грешки.
detailedDescription: Позволява различни опции за записване на грешки от плъгина.
arg1:
label: секция
description: Секцията за отстраняване на грешки, която да бъде изпълнена.
arg2:
label: аргумент
description: Аргумент (Зависи от избора на секция за отстраняване на грешки)
arg3:
label: аргумент
description: Аргумент (Зависи от избора на секция за отстраняване на грешки)
authme.help:
description: Помощ
detailedDescription: Показва помощ за командите започващи с /authme.
arg1:
label: команда
description: команда, за която е необходимо да се покаже помощ.
email:
description: Добавя имейл или възстановява парола.
detailedDescription: Основната команда на AuthMeReloaded свързана с имейлите.
email.show:
description: Показва Имейл
detailedDescription: Показва текущият Ви имейл.
email.add:
description: Добавяне на имейл.
detailedDescription: Добавя нов имейл адрес към Вашият акаунт.
arg1:
label: имейл
description: Имейл адрес
arg2:
label: Потвърждение
description: Потвърждение на имейл адреса.
email.change:
description: Смяна на Имейл
detailedDescription: Смяна на имейл адреса на Вашият акаунт.
arg1:
label: стар-имейл
description: Текущия имейл използван към Вашият акаунт
arg2:
label: нов-имейл
description: Новия имейл, който да бъде задеден към акаунта.
email.recover:
description: Възстановяване на парола чрез имейл.
detailedDescription: Възстановяване на Вашият акаунт, използвайки Имейл с нова парола.
arg1:
label: имейл
description: Имейл адреса на Вашият акаунт.
email.code:
description: Изпращане на код за възстановяване на парола.
detailedDescription: Възстановяване на Вашият акаунт чрез код, изпратен по имейл.
arg1:
label: код
description: Код за възстановяване
email.setpassword:
description: Задаване на нова парола след възстановяване.
detailedDescription: Задаване на нова парола след успешно възстановяване на Вашият акаунт.
arg1:
label: парола
description: Нова парола
email.help:
description: Помощ
detailedDescription: Подробна помощ за /email командите.
arg1:
label: команда
description: Командата за която да се покаже помощ (или за всички).
login:
description: вход
detailedDescription: Командата която се използва за идентификация в сървъра на Вашият акаунт.
arg1:
label: парола
description: Паролата на акаунта Ви.
login.help:
description: Помощ
detailedDescription: Подробна помощ за /login командите.
arg1:
label: команда
description: Командата за която да се покаже помощ (или за всички).
logout:
description: Изход
detailedDescription: Командата за изход от Вашият акаунт.
logout.help:
description: помощ
detailedDescription: КПодробна помощ за /logout командите.
arg1:
label: команда
description: Командата за която да се покаже помощ (или за всички).
register:
description: Регистрация на акаунт.
detailedDescription: Команда за регистриране на Вашият акаунт.
arg1:
label: парола
description: Парола
arg2:
label: Потвърждение
description: Потвърждение на паролата
register.help:
description: Помощ
detailedDescription: Детайлна помощ за /register командите.
arg1:
label: команда
description: Командата за която да се покаже помощ (или за всички).
unregister:
description: Дерегистриране на акаунт.
detailedDescription: Команда за премахване на регистрацията на Вашият акаунт.
arg1:
label: парола
description: Вашата парола.
unregister.help:
description: Помощ
detailedDescription: Детайлна помощ за /unregister командите.
arg1:
label: команда
description: Командата за която да се покаже помощ (или за всички).
changepassword:
description: Смяна на парола
detailedDescription: Смяна на паролата за Вашият акаунт.
arg1:
label: текуща-парола
description: Текущата парола на Вашият акаунт.
arg2:
label: Нова парола
description: Новата парола, която да бъде използвана за Вашият акаунт.
changepassword.help:
description: Помощ
detailedDescription: Детайлна помощ за /changepassword командите.
arg1:
label: команда
description: Командата за която да се покаже помощ (или за всички).
totp:
description: TOTP команди
detailedDescription: Команди свързани с допълнителната сигурност на акаунта Ви чрез секретен код.
totp.code:
description: Команда за вход
detailedDescription: Изпълнява проверката на секретния код на Вашият акаунт при влизане.
arg1:
label: код
description: Секретният код, използван за влизане.
totp.add:
description: Включване на TOTP
detailedDescription: Включване на защитата със секретен код за Вашият акаунт.
totp.confirm:
description: Активиране на TOTP след въвеждане на правилен секретен код.
detailedDescription: Запазва генерираният секретен код след потвърждение.
arg1:
label: код
description: Секретният код след изпълняване на командата /totp add
totp.remove:
description: Изключване на TOTP
detailedDescription: Изключване на защитата със секретен код за Вашият акаунт.
arg1:
label: код
description: Текущ секретен код
totp.help:
description: Помощ
detailedDescription: Детайлна помощ за /totp командите.
arg1:
label: команда
description: Командата за която да се покаже помощ (или за всички).
captcha:
description: Код за сигурност
detailedDescription: Команда за код за сигурност.
arg1:
label: код
description: Код за сигурност
captcha.help:
description: Помощ
detailedDescription: Детайлна помощ за /captcha командите.
arg1:
label: команда
description: Командата за която да се покаже помощ (или за всички).
verification:
description: Команда за потвърждение.
detailedDescription: Команда за потвърждение.
arg1:
label: код
description: Код за потвърждение.
verification.help:
description: Помощ
detailedDescription: Детайлна помощ за /verification командите.
arg1:
label: команда
description: Командата за която да се покаже помощ (или за всички).

View File

@ -5,14 +5,14 @@
common:
header: '==========[ AuthMeReloaded ABI ]=========='
optional: 'Valikuline'
hasPermission: 'Sul ei ole õigust'
noPermission: 'Õigus puudub'
hasPermission: 'Sul on õigus'
noPermission: 'Pole õigust'
default: 'Vaikimisi'
result: 'Tulemus'
defaultPermissions:
notAllowed: 'Pole õigust'
opOnly: 'Ainult operaatoritele'
allowed: 'Kõigile lubatud'
opOnly: 'Ainult operaatorid'
allowed: 'Õigus kõigil'
# -------------------------------------------------------
# Titles of the individual help sections
@ -20,8 +20,8 @@ common:
# alternatives: ''
section:
command: 'Käsklus'
description: 'Lühike selgitus'
detailedDescription: 'Detailne selgitus'
description: 'Lühike kirjeldus'
detailedDescription: 'Detailne kirjeldus'
arguments: 'Argumendid'
permissions: 'Õigused'
alternatives: 'Alternatiivid'
@ -39,7 +39,7 @@ commands:
detailedDescription: 'Registreeri valitud mängija valitud parooliga.'
arg1:
label: 'mängija'
description: 'mängija nimi'
description: 'Mängija nimi'
arg2:
label: 'parool'
description: 'parool'
description: 'Parool'

View File

@ -7,16 +7,16 @@
registration:
disabled: '&cРегистрациите са изключени!'
name_taken: '&cПотребителското име е заетo!'
register_request: '&3Моля регистрирайте се с: /register парола парола'
register_request: '&3Моля регистрирайте се с: /register парола парола.'
command_usage: '&cКоманда: /register парола парола'
reg_only: '&4Само регистрирани потребители могат да влизат в сървъра! Моля посетете http://example.com, за да се регистрирате!'
success: '&2Успешна регистрация!'
kicked_admin_registered: 'Ти беше регистриран от администратора, моля влезте отново'
kicked_admin_registered: 'Вие бяхте регистриран от администратора, моля да влезете отново!'
# Password errors on registration
password:
match_error: '&cПаролите не съвпадат, провете ги отново!'
name_in_password: '&cНе можеш да използваш потребителското си име за парола, моля изберете друга парола.'
name_in_password: '&cНе можете да използвате потребителското си име за парола, моля изберете друга парола.'
unsafe_password: '&cИзбраната парола не е безопасна, моля изберете друга парола.'
forbidden_characters: '&4Паролата съдържа непозволени символи. Позволени символи: %valid_chars'
wrong_length: '&cПаролата е твърде къса или прекалено дълга! Моля опитайте с друга парола.'
@ -26,25 +26,25 @@ login:
command_usage: '&cКоманда: /login парола'
wrong_password: '&cГрешна парола!'
success: '&2Успешен вход!'
login_request: '&cМоля влезте с: /login парола'
timeout_error: '&4Времето за вход изтече, беше кикнат от сървъра. Моля опитайте отново!'
login_request: '&cМоля влезте с: /login парола !'
timeout_error: '&4Времето за вход изтече, бяхте кикнат от сървъра. Моля опитайте отново!'
# Errors
error:
denied_command: '&cЗа да използваш тази команда трябва да си си влезнал в акаунта!'
denied_chat: '&cЗа да пишеш в чата трябва даи сиси влезнал в акаунта!'
denied_command: '&cЗа да използвате тази команда трябва да сте си влезли в акаунта!'
denied_chat: '&cЗа да пишете в чата трябва да сте си влезли в акаунта!'
unregistered_user: '&cПотребителското име не е регистрирано!'
not_logged_in: '&cНе си влязъл!'
no_permission: '&4Нямаш нужните права за това действие!'
not_logged_in: '&cНе сте влезли!'
no_permission: '&4Нямате нужните права за това действие!'
unexpected_error: '&4Получи се неочаквана грешка, моля свържете се с администратора!'
max_registration: '&cТи си достигнал максималният брой регистрации (%reg_count/%max_acc %reg_names)!'
logged_in: '&cВече си вписан!'
kick_for_vip: '&3VIP потребител влезе докато сървъра беше пълен, ти беше изгонен!'
tempban_max_logins: '&cТи беше баннат временно, понеже си сгрешил паролата прекалено много пъти.'
max_registration: '&cВие сте достигнали максималният брой регистрации (%reg_count/%max_acc %reg_names)!'
logged_in: '&cВече сте влезли!'
kick_for_vip: '&3VIP потребител влезе докато сървъра беше пълен, вие бяхте изгонен!'
tempban_max_logins: '&cВие бяхте баннат временно, понеже сте си сгрешили паролата прекалено много пъти.'
# AntiBot
antibot:
kick_antibot: 'Защитата от ботове е включена! Трябва да изчакаш няколко минути преди да влезеш в сървъра.'
kick_antibot: 'Защитата от ботове е включена! Трябва да изчакате няколко минути преди да влезете в сървъра.'
auto_enabled: '&4Защитата за ботове е включена заради потенциална атака!'
auto_disabled: '&2Защитата за ботове ще се изключи след %m минута/и!'
@ -55,12 +55,12 @@ unregister:
# Other messages
misc:
account_not_activated: '&cТвоят акаунт все още не е актириван, моля провете своят email адрес!'
account_not_activated: '&cВашият акаунт все още не е актириван, моля провете своят email адрес!'
password_changed: '&2Паротала е променена успешно!'
logout: '&2Излязохте успешно!'
reload: '&2Конфигурацията и база данните бяха презаредени правилно!'
usage_change_password: '&cКоманда: /changepassword Стара-Парола Нова-Парола'
accounts_owned_self: 'Претежаваш %count акаунт/а:'
accounts_owned_self: 'Притежавате %count акаунт/а:'
accounts_owned_other: 'Потребителят %name има %count акаунт/а:'
# Session messages
@ -71,14 +71,14 @@ session:
# Error messages when joining
on_join_validation:
same_ip_online: 'Вече има потребител със същото IP в сървъра!'
same_nick_online: '&4Вече има потребител, който играете в сървъра със същото потребителско име!'
name_length: '&4Потребителското име е прекалено късо или дълга. Моля опитайте с друго потребителско име!'
same_nick_online: '&4Вече има потребител, който играе в сървъра със същото потребителско име!'
name_length: '&4Потребителското име е прекалено късо или дълго. Моля опитайте с друго потребителско име!'
characters_in_name: '&4Потребителското име съдържа забранени знаци. Позволени знаци: %valid_chars'
kick_full_server: '&4Сървъра е пълен, моля опитайте отново!'
country_banned: '&4Твоята държава е забранена в този сървър!'
not_owner_error: 'Ти не си собственика на този акаунт. Моля избери друго потребителско име!'
invalid_name_case: 'Трябва да влезеш с %valid, а не с %invalid.'
# TODO quick_command: 'You used a command too fast! Please, join the server again and wait more before using any command.'
invalid_name_case: 'Трябва да влезеш с %valid, а не с %invalid!'
quick_command: 'Използвате команди твърде бързо! Моля, влезте отново в сървъра и изчакайте малко преди да използвате команди.'
# Email
email:
@ -89,17 +89,17 @@ email:
old_email_invalid: '&cСтарият имейл е грешен, опитайте отново!'
invalid: '&cИмейла е невалиден, опитайте с друг!'
added: '&2Имейл адреса е добавен!'
# TODO add_not_allowed: '&cAdding email was not allowed'
request_confirmation: '&cМоля потвърди своя имейл адрес!'
add_not_allowed: '&cДобавянето на имейл не е разрешено!'
request_confirmation: '&cМоля потвърдете своя имейл адрес!'
changed: '&2Имейл адреса е сменен!'
# TODO change_not_allowed: '&cChanging email was not allowed'
email_show: '&2Твоят имейл адрес е: &f%email'
change_not_allowed: '&cСмяната на имейл адреса не е разрешена!'
email_show: '&2Вашият имейл адрес е: &f%email'
no_email_for_account: '&2Няма добавен имейл адрес към акаунта.'
already_used: '&4Имейл адреса вече се използва, опитайте с друг.'
incomplete_settings: 'Грешка: Не всички настройки са написани за изпращане на имейл адрес. Моля свържете се с администратора!'
send_failure: 'Съобщението не беше изпратено. Моля свържете се с администратора.'
# TODO change_password_expired: 'You cannot change your password using this command anymore.'
email_cooldown_error: '&cВече е бил изпратен имейл адрес. Трябва а изчакаш %time преди да пратиш нов.'
change_password_expired: 'Вече не е възможно да смените паролата си с тази команда.'
email_cooldown_error: '&cВече е бил изпратен имейл адрес. Трябва а изчакате %time преди да изпратите нов.'
# Password recovery by email
recovery:
@ -107,29 +107,29 @@ recovery:
command_usage: '&cКоманда: /email recovery имейл'
email_sent: '&2Възстановяващият имейл е изпратен успешно. Моля провете пощата си!'
code:
code_sent: 'Възстановяващият код беше изпратен на твоят email адрес.'
incorrect: 'Възстановяващият код е неправилен! Използвайте: /email recovery имейл, за да генерирате нов'
# TODO tries_exceeded: 'You have exceeded the maximum number attempts to enter the recovery code. Use "/email recovery [email]" to generate a new one.'
# TODO correct: 'Recovery code entered correctly!'
# TODO change_password: 'Please use the command /email setpassword <new password> to change your password immediately.'
code_sent: 'Възстановяващият код беше изпратен на вашият email адрес.'
incorrect: 'Възстановяващият код е неправилен! Използвайте: /email recovery имейл, за да генерирате нов.'
tries_exceeded: 'Вие надвишихте максималният брой опити да въведете кода за възстановяване. Използвайте "/email recovery имейл" за да генерирате нов.'
correct: 'Кода за възстановяване е успешно въведен!'
change_password: 'Моля използвайте командата /email setpassword нова-парола за да смените Вашата парола веднага.'
# Captcha
captcha:
usage_captcha: '&3Моля въведе цифрите/буквите от капчата: /captcha %captcha_code'
usage_captcha: '&3Моля въведе цифрите/буквите от кода за сигурност: /captcha %captcha_code'
wrong_captcha: '&cКода е грешен, използвайте: "/captcha %captcha_code" в чата!'
valid_captcha: '&2Кода е валиден!'
# TODO captcha_for_registration: 'To register you have to solve a captcha first, please use the command: /captcha %captcha_code'
# TODO register_captcha_valid: '&2Valid captcha! You may now register with /register'
valid_captcha: '&2Кода е валиден!'
captcha_for_registration: 'За да се регистрирате, трябва да въведете цифрите / буквите от кода за сигурност, използвайте командата: /captcha %captcha_code'
register_captcha_valid: '&2Кода е валиден! Вие вече може да се регистрирате с команда /register'
# Verification code
verification:
# TODO code_required: '&3This command is sensitive and requires an email verification! Check your inbox and follow the email''s instructions.'
# TODO command_usage: '&cUsage: /verification <code>'
# TODO incorrect_code: '&cIncorrect code, please type "/verification <code>" into the chat, using the code you received by email'
# TODO success: '&2Your identity has been verified! You can now execute all commands within the current session!'
# TODO already_verified: '&2You can already execute every sensitive command within the current session!'
# TODO code_expired: '&3Your code has expired! Execute another sensitive command to get a new code!'
# TODO email_needed: '&3To verify your identity you need to link an email address with your account!!'
code_required: '&3Тази команда е чувствителна и изисква потвърждение по имейл! Моля проверете си имейла и следвайте инструкциите в него.'
command_usage: '&cКоманда: /verification код'
incorrect_code: '&cНеправилен код, моля използвайте "/verification код" като използвате кода, който сте получили на Вашият имейл.'
success: '&2Вашата самоличност е потвърдена! Вие може да използвате всички команди в текущата Ви сесия!'
already_verified: '&2Вие вече можете да изпълнявате чувствителни команди в текущата Ви сесия!'
code_expired: '&3Вашият код е изтекъл. Изпълнете друга чувствителна команда за да генерирате нов код!'
email_needed: '&3За да потвърдите Вашата самоличност е необходимо да добавите имейл адрес към Вашият акаунт!!'
# Time units
time:
@ -140,17 +140,17 @@ time:
hour: 'час'
hours: 'часа'
day: 'ден'
days: ена'
days: ни'
# Two-factor authentication
two_factor:
code_created: '&2Кода е %code. Можеш да го провериш оттука: %url'
# TODO confirmation_required: 'Please confirm your code with /2fa confirm <code>'
# TODO code_required: 'Please submit your two-factor authentication code with /2fa code <code>'
# TODO already_enabled: 'Two-factor authentication is already enabled for your account!'
# TODO enable_error_no_code: 'No 2fa key has been generated for you or it has expired. Please run /2fa add'
# TODO enable_success: 'Successfully enabled two-factor authentication for your account'
# TODO enable_error_wrong_code: 'Wrong code or code has expired. Please run /2fa add'
# TODO not_enabled_error: 'Two-factor authentication is not enabled for your account. Run /2fa add'
# TODO removed_success: 'Successfully removed two-factor auth from your account'
# TODO invalid_code: 'Invalid code!'
code_created: '&2Кода е %code. Можете да го проверите от тук: %url'
confirmation_required: 'Моля потвърдете Вашият код с команда /2fa confirm <код>'
code_required: 'Моля изпратете Вашият секретен код с команда /2fa code <код>'
already_enabled: 'Използването на секретен код е вече включено за Вашият акаунт!'
enable_error_no_code: 'Нямате добавен секретен код или кода е изтекъл. Моля изпълнете команда /2fa add'
enable_success: 'Успешно активирахте защита със секретен код за Вашият акаунт.'
enable_error_wrong_code: 'Грешен секретен код или е изтекъл. Моля изпълнете команда /2fa add'
not_enabled_error: 'Защитата със секретен код не е включена за Вашият акаунт. Моля изпълнете команда /2fa add'
removed_success: 'Успешно изключихте защитата със секретен код от Вашият акаунт!'
invalid_code: 'Невалиден код!'

View File

@ -1,10 +1,10 @@
#Tradução pt/br Authme Reloaded
#Feito por GabrielDev(DeathRush) e Frani (PotterCraft_)
#Feito por GabrielDev(DeathRush) e Eufranio (Eufranio#0800)
# http://gamersboard.com.br/ | www.magitechserver.com
# List of global tags:
# %nl% - Goes to new line.
# %username% - Replaces the username of the player receiving the message.
# %displayname% - Replaces the nickname (and colors) of the player receiving the message.
# Lista de tags globais:
# %nl% - Pula uma linha
# %username% - Substitui pelo nome do jogador RECEBENDO a mensagem
# %displayname% - Substitui o nickname (e cores) do jogador RECEBENDO a mensagem
# Registration
registration:
@ -121,18 +121,18 @@ captcha:
usage_captcha: '&3Para iniciar sessão você tem que resolver um código captcha, utilize o comando "/captcha %captcha_code"'
wrong_captcha: '&cCaptcha errado, por favor, escreva "/captcha %captcha_code" no chat!'
valid_captcha: '&2Código Captcha resolvido corretamente!'
# TODO captcha_for_registration: 'To register you have to solve a captcha first, please use the command: /captcha %captcha_code'
# TODO register_captcha_valid: '&2Valid captcha! You may now register with /register'
captcha_for_registration: 'Para se registrar você tem que resolver um código captcha, utilize o comando "/captcha %captcha_code"'
register_captcha_valid: '&2Código correto! Agora você pode se registrar com /register!'
# Verification code
verification:
# TODO code_required: '&3This command is sensitive and requires an email verification! Check your inbox and follow the email''s instructions.'
# TODO command_usage: '&cUsage: /verification <code>'
# TODO incorrect_code: '&cIncorrect code, please type "/verification <code>" into the chat, using the code you received by email'
# TODO success: '&2Your identity has been verified! You can now execute all commands within the current session!'
# TODO already_verified: '&2You can already execute every sensitive command within the current session!'
# TODO code_expired: '&3Your code has expired! Execute another sensitive command to get a new code!'
# TODO email_needed: '&3To verify your identity you need to link an email address with your account!!'
code_required: '&3Esse comando é importante e precisa de uma verificação via e-mail! Cheque sua caixa de entrada e siga as instruções do e-mail.'
command_usage: '&cUso correto: /verification <código>'
incorrect_code: '&cCódigo incorreto, utilize "/verification <código>" usando o código que você recebeu no e-mail!'
success: '&2Sua identidade foi verificada, agora você pode usar todos os comandos nessa sessão.'
already_verified: '&2Você já pode executar comandos importantes nessa sessão!'
code_expired: '&3Seu código expirou! Execute outro comando importante para criar um novo.'
email_needed: '&3Para verificar sua identidade, você precisa ligar um e-mail à sua conta!'
# Time units
time:
@ -148,12 +148,12 @@ time:
# Two-factor authentication
two_factor:
code_created: '&2O seu código secreto é %code. Você pode verificá-lo a partir daqui %url'
# TODO confirmation_required: 'Please confirm your code with /2fa confirm <code>'
# TODO code_required: 'Please submit your two-factor authentication code with /2fa code <code>'
# TODO already_enabled: 'Two-factor authentication is already enabled for your account!'
# TODO enable_error_no_code: 'No 2fa key has been generated for you or it has expired. Please run /2fa add'
# TODO enable_success: 'Successfully enabled two-factor authentication for your account'
# TODO enable_error_wrong_code: 'Wrong code or code has expired. Please run /2fa add'
# TODO not_enabled_error: 'Two-factor authentication is not enabled for your account. Run /2fa add'
# TODO removed_success: 'Successfully removed two-factor auth from your account'
# TODO invalid_code: 'Invalid code!'
confirmation_required: 'Confirme seu código com /2fa confirm <código>'
code_required: 'Registre seu código de autenticação de 2 fatores com /2fa code <código>'
already_enabled: 'A autenticação em 2 fatores já está ativada para sua conta!'
enable_error_no_code: 'Nenhuma chave de autenticação foi gerada, ou expirou. Por favor, use /2fa add'
enable_success: 'Autenticação em 2 fatores ativada com sucesso para sua conta!'
enable_error_wrong_code: 'Código errado ou expirado! Use /2fa add'
not_enabled_error: 'A autenticação em 2 fatores não está ativada para sua conta. Use /2fa add'
removed_success: 'Autenticação em 2 fatores desativada com sucesso para sua conta.'
invalid_code: 'Código inválido!'

View File

@ -5,152 +5,150 @@
# Registration
registration:
disabled: '&cMängusisene registreerimine välja lülitatud!'
name_taken: '&cKasutajanimi juba registreeritud!'
register_request: '&3Palun registreeri käsklusega /register <Parool> <KinnitaParool>'
command_usage: '&cKasutus: /register <KinnitaParool> <KinnitaParool>'
reg_only: '&4Ainult registreeritud mängijad saavad liituda! Külasta veebilehte http://example.com, et ennast regsitreerida.'
success: '&2Edukalt registreeritud!'
kicked_admin_registered: 'Administraator registreeris sind, palun lahku korra serverist ja liitu tagasi.'
register_request: '&3Palun registreeri käsklusega: /register <parool> <KinnitaParool>'
command_usage: '&cKasutus: /register <parool> <KinnitaParool>'
reg_only: '&4Vaid registreeritud mängijad saavad liituda serveriga! Külasta http://example.com enda kasutaja registreerimiseks!'
kicked_admin_registered: 'Administraator registreeris su kasutaja, palun logi uuesti sisse.'
success: '&2Edukalt registreeritud!'
disabled: '&cMängusisene registreerimine on välja lülitatud!'
name_taken: '&cSee kasutaja on juba registreeritud!'
# Password errors on registration
password:
match_error: '&cParoolid ei klapi, kontrolli neid!'
name_in_password: '&cSa ei saa kasutada oma kasutajanime paroolina, vali teine parool.'
unsafe_password: '&cSee parool ei ole turvaline, vali teistsugune.'
forbidden_characters: '&44Su parool sisaldab keelatud karaktereid. Lubatud karakterid: %valid_chars'
wrong_length: '&cSu parool on liiga pikk või lühike, vali teine!'
match_error: '&cParoolid ei kattu, palun proovi uuesti!'
name_in_password: '&cSa ei saa kasutada oma kasutajanime paroolina, palun vali mõni teine parool.'
unsafe_password: '&cSee parool ei ole turvaline, palun vali mõni teine parool.'
forbidden_characters: '&4Su parool sisaldab keelatud täherke. Lubatud tähergid: %valid_chars'
wrong_length: '&cSu parool on liiga pikk või lühike, palun vali mõni teine parool.'
# Login
login:
command_usage: '&cKasutus: /login <Parool>'
wrong_password: '&cVale salasõna!'
success: '&2Edukalt sisselogitud!'
login_request: '&cPalun logi sisse kasutades käsklust: /login <Parool>'
timeout_error: '&4Sisselogimise taimer täis, palun logi sisse ja proovi uuesti!'
command_usage: '&cKasutus: /login <parool>'
wrong_password: '&cVale parool!'
success: '&2Edukalt sisselogitud!'
login_request: '&cPalun logi sisse kasutades käsklust: /login <parool>'
timeout_error: '&4Sisselogimiseks antud aeg on läbi, palun proovi uuesti!'
# Errors
error:
denied_command: '&cSelle käskluse kasutamiseks pead sa olema audenditud!'
denied_chat: '&cChati kasutamiseks pead sa olema audenditud!'
unregistered_user: '&cSee kasutaja ei ole registreeritud.'
not_logged_in: '&cSa ei ole sisse loginud!'
no_permission: '&4Sul ei ole selle käskluse kasutamiseks õigust.'
unexpected_error: '&4Süsteemi viga, teata sellest serveri meeskonda.'
max_registration: '&cSu IP peal (%reg_count/%max_acc %reg_names) on liiga palju kontosid!'
logged_in: '&cJuba sisselogitud!'
kick_for_vip: '&3VIP kasutaja liitus serveriga, kui see oli täis. Sind visati välja, et talle ruumi teha.'
tempban_max_logins: '&cSind on ajutiselt pagendatud serverist, sest sul ebaõnnestus sisse logida liiga palju kordi.'
unregistered_user: '&cSee kasutaja ei ole registreeritud!'
denied_command: '&cSelle käskluse kasutamiseks pead sisse logima!'
denied_chat: '&cRääkimiseks pead sisse logima!'
not_logged_in: '&cSa ei ole sisselogitud!'
tempban_max_logins: '&cSind blokeeriti ajutiselt serverist, sest sisestasid mitu korda vale parooli.'
max_registration: '&cSu IP aadressile on registreeritud liiga palju kasutajaid! (%reg_count/%max_acc %reg_names)'
no_permission: '&4Sul ei ole õigust selle käskluse kasutamiseks.'
unexpected_error: '&4Süsteemis tekkis viga, teata sellest administraatorile!'
kick_for_vip: '&3VIP mängija liitus serveriga ajal, mil see oli täis!'
logged_in: '&cSa oled juba sisselogitud!'
# AntiBot
antibot:
kick_antibot: 'AntiBot on sisse lülitatud! Sa pead ootama mõned minutid enne kui uuesti sisse logid.'
auto_enabled: '&4[AntiBot] AntiBot sisse lülitatud suure liikluse tõttu!'
auto_disabled: '&2[AntiBot] AntiBot välja lülitatud peale %m minutit!'
kick_antibot: 'AntiBot kaitse sisse lülitatud! Pead ootama mõne minuti enne kui serveriga liituda saad.'
auto_enabled: '&4[AntiBotKaitse] AntiBot sisselülitatud!'
auto_disabled: '&2[AntiBotKaitse] AntiBot välja lülitatud peale %m minutit!'
# Unregister
unregister:
success: '&cKonto edukalt kustutatud!'
command_usage: '&cKasutus: /unregister <Parool>'
success: '&cKasutaja edukalt kustutatud!'
command_usage: '&cKasutus: /unregister <parool>'
# Other messages
misc:
account_not_activated: '&cSu konto pole veel aktiveeritud, vaata oma postkasti.'
password_changed: '&2Parool edukalt vahetatud!'
logout: '&2Edukalt välja logitud!!'
reload: '&2Andmebaas uuendatud!'
usage_change_password: '&cKasutus: /changepassword <vanaParool> <UusParool>'
accounts_owned_self: 'Sa omad %count kontot:'
accounts_owned_other: 'Mängijal %name on %count kontot:'
accounts_owned_self: 'Sa omad %count kontot:'
accounts_owned_other: 'Mängijal %name on %count kontot:'
account_not_activated: '&cSu konto ei ole veel aktiveeritud, kontrolli oma meili!'
password_changed: '&2Parool vahetatud!'
logout: '&2Edukalt välja logitud!'
reload: '&2Andmebaas edukalt laetud!'
usage_change_password: '&cKasutus: /changepassword <vanaParool> <uusParool>'
# Session messages
session:
valid_session: '&2Sisselogitud eelneva sessiooni tõttu.'
invalid_session: '&cSu IP on vahetunud ja sessiooni info on aegunud!'
invalid_session: '&cSu IP aadress muutus mistõttu sinu sessioon aegus!'
valid_session: '&2Sisse logitud sessiooni jätkumise tõttu.'
# Error messages when joining
on_join_validation:
same_ip_online: 'Sama IP-ga mängija on juba sees!'
same_nick_online: '&4Sama kasutajanimi mängib juba serveris.'
name_length: '&4Su kasutajanimi on liiga pikk või lühike!'
characters_in_name: '&4Su kasutajanimes on keelatud karaktereid. Lubatud karakterid: %valid_chars'
kick_full_server: '&4Server on täis, proovi hiljem uuesti.'
country_banned: '&4Su riik on siin serveris keelatud!'
not_owner_error: 'Sa ei ole selle konto omanik. Vali teine nimi.'
invalid_name_case: 'Logi sisse kasutajanimega %valid, mitte kasutajanimega %invalid.'
# TODO quick_command: 'You used a command too fast! Please, join the server again and wait more before using any command.'
name_length: '&4Su kasutajanimi on liiga pikk või lühike!'
characters_in_name: '&4Su kasutajanimi sisaldab keelatud tähemärke. Lubatud tähemärgid: %valid_chars'
country_banned: '&4Sinu riigist ei ole võimalik ühenduda sellesse serverisse!'
not_owner_error: 'Sa ei ole selle kasutaja omanik. Vali teine nimi!!'
kick_full_server: '&4Server täis, proovi uuesti!'
same_nick_online: '&4Sama kasutaja on juba ühendatud serveriga!'
invalid_name_case: 'Sa peaksid liituma nimega %valid, mitte nimega %invalid.'
same_ip_online: 'Sama IP aadressiga mängija juba mängib!'
quick_command: 'Sa kasutasid käsklust liiga kiiresti! Palun liitu serveriga ja oota kauem enne kui käsklust kasutad.'
# Email
email:
add_email_request: '&3Lisa oma meiliaadress kasutades käsklust: /email add <Email> <KinnitaEmail>'
usage_email_add: '&cKasutus: /email add <email> <KinnitaEmail>'
usage_email_change: '&cKasutus: /email change <VanaEmail> <UusEmail>'
new_email_invalid: '&cVale meiliaadress, proovi uuesti.'
old_email_invalid: '&cVale vana meiliaadress, proovi uuesti.'
invalid: '&cVale meiliaadress, proovi uuesti.'
added: '&2Meiliaadress edukalt vahetatud!'
# TODO add_not_allowed: '&cAdding email was not allowed'
request_confirmation: '&cPalun kinnita oma meiliaadress.'
changed: '&2Meiliaadress edukalt vahetatud.'
# TODO change_not_allowed: '&cChanging email was not allowed'
email_show: '&2Su meiliaadress on: &f%email'
no_email_for_account: '&2Selle kasutajaga pole seotud ühtegi meiliaadressi.'
already_used: '&4Meiliaadress juba kasutuses.'
incomplete_settings: 'Viga: Meiliaadressi kinnitamiseks vajalikud seaded pole serveri poolt paigas. Kontakteeru meeskonnaga.'
send_failure: 'Meili ei õnnestunud saata. Kontakteeru meeskonnaga.'
change_password_expired: '&3Enam ei saa vahetada oma parooli kasutades seda käsklust.'
email_cooldown_error: '&cEmail juba saadeti. Sa pead ootama %time ennem, kui saad uuesti saata.'
usage_email_add: '&cKasutus: /email add <email> <kinnitaEmail>'
usage_email_change: '&cKasutus: /email change <vanaEmail> <uusEmail>'
new_email_invalid: '&cUus meiliaadress on vale, proovi uuesti!'
old_email_invalid: '&cVana meiliaadress on vale, proovi uuesti!'
invalid: '&cVale meiliaadress, proovi uuesti!'
added: '&2Meiliaadress edukalt lisatud!'
request_confirmation: '&cPalun kinnita oma meiliaadress!'
changed: '&2Meiliaadress edukalt muudetud!'
email_show: '&2Su praegune meiliaadress on: &f%email'
incomplete_settings: 'Viga: meili saatmiseks pole kõik vajalikud seaded seadistatud. Teata sellest administraatorile.'
already_used: '&4See meiliaadress on juba kasutuses!'
send_failure: 'Meili ei õnnestunud saata. Teata sellest administraatorile.'
no_email_for_account: '&2Selle kasutajaga ei ole seotud ühtegi meiliaadressi.'
add_email_request: '&3Palun seo oma kasutajaga meiliaadress kasutades käsklust: /email add <sinuEmail> <kinnitaEmail>'
change_password_expired: 'Selle käsklusega ei saa sa enam parooli muuta.'
email_cooldown_error: '&cMeil on juba saadetud. Sa pead ootama %time enne kui saad küsida uue saatmist.'
add_not_allowed: '&cMeiliaadressi lisamine ei ole lubatud.'
change_not_allowed: '&cMeiliaadressi muutmine ei ole lubatud.'
# Password recovery by email
recovery:
forgot_password_hint: '&3Unustasid salasõna? Kasuta käsklust: /email recovery <Email>'
command_usage: '&cKasutus: /email recovery <Email>'
email_sent: '&2Taastuskood edukalt saadetud su meiliaadressile. Kontrolli oma postkasti.'
code:
code_sent: 'Taastuskood saadeti su meilile.'
incorrect: 'Taastuskood ei ole õige! Sul on %count proovi järelejäänud.'
tries_exceeded: 'Sa oled liiga palju proovinud taastuskoodi sisestada. Kasuta "/email recovery [email]" et genereerida uut koodi.'
correct: 'Taastuskood on õige!'
change_password: 'Palun kasuta käsklust /email setpassword <UusParool> et vahetada oma parooli koheselt.'
forgot_password_hint: '&3Unustasid oma parooli? Kasuta käsklust: /email recovery <sinuEmail>'
command_usage: '&cKasutus: /email recovery <Email>'
email_sent: '&2Konto taastamiseks vajalik meil saadetud! Vaata oma postkasti.'
code:
code_sent: 'Konto taastamise kood on saadetud!'
incorrect: 'Kood vale! Sul on %count katset jäänud.'
tries_exceeded: 'Sul on katsed otsas. Kasuta käsklust "/email recovery [email]" uue koodi saamiseks.'
correct: 'Kood õigesti sisestatud!'
change_password: 'Palun kasuta käsklust /email setpassword <uusParool> parooli muutmiseks.'
# Captcha
captcha:
usage_captcha: '&3Sisselogimiseks pead lahendama captcha. Tee seda kasutades käsklust: /captcha %captcha_code'
wrong_captcha: '&cVale captcha, kirjuta "/captcha %captcha_code" chatti!'
valid_captcha: '&2Captcha lahendatud!'
# TODO captcha_for_registration: 'To register you have to solve a captcha first, please use the command: /captcha %captcha_code'
# TODO register_captcha_valid: '&2Valid captcha! You may now register with /register'
usage_captcha: '&3Sisselogimiseks lahenda captcha käsklusega: /captcha %captcha_code'
wrong_captcha: '&cVale captcha, kasuta käsklust "/captcha %captcha_code"!'
valid_captcha: '&2Captcha lahendatud!'
captcha_for_registration: 'Registreerimiseks lahenda captcha kasutades käsklust: /captcha %captcha_code'
register_captcha_valid: '&2Captcha lahendatud! Võid nüüd registreerida kasutades käsklust /register'
# Verification code
verification:
# TODO code_required: '&3This command is sensitive and requires an email verification! Check your inbox and follow the email''s instructions.'
# TODO command_usage: '&cUsage: /verification <code>'
# TODO incorrect_code: '&cIncorrect code, please type "/verification <code>" into the chat, using the code you received by email'
# TODO success: '&2Your identity has been verified! You can now execute all commands within the current session!'
# TODO already_verified: '&2You can already execute every sensitive command within the current session!'
# TODO code_expired: '&3Your code has expired! Execute another sensitive command to get a new code!'
# TODO email_needed: '&3To verify your identity you need to link an email address with your account!!'
code_required: '&3See käsklus on ohtlik mistõttu saatsime sulle meili. Kontrolli oma meili ja järgi saadetud meili juhiseid.'
command_usage: '&cKasutus: /verification <kood>'
incorrect_code: '&cVale kood, palun kasuta käsklust "/verification <kood>" koodiga, mille saatsime sulle meilile.'
success: '&2Konto kinnitatud!'
already_verified: '&2Sa juba saad kasutada kõiki ohtlikke käsklusi!'
code_expired: '&3Kood aegunud! Kasuta mõnda ohtlikku käsklust, et saada uus kood!'
email_needed: '&3Konto kinnitamiseks pead siduma oma kontoga enda meiliaadressi!'
two_factor:
code_created: '&2Sinu privaatne kood on %code. Sa saad selle skännida aadressil %url'
confirmation_required: 'Palun kinnita oma kaheastmeline autentimise kood käsklusega /2fa confirm <kood>'
code_required: 'Palun sisesta kaheastmeline autentimise kood kasutades /2fa code <kood>'
already_enabled: 'Kaheastmeline autentimine on juba sisselülitatud!'
enable_error_no_code: '2fa võtit ei ole genereeritud või on see aegunud. Kasuta käsklust /2fa add'
enable_success: 'Kaheastmeline autentimine edukalt sisselülitatud!'
enable_error_wrong_code: 'Vale kood või kood on aegunud. Kasuta käsklust /2fa add'
not_enabled_error: 'Kaheastmeline autentimine ei ole su kontol sisse lülitatud. Kasuta käsklust /2fa add'
removed_success: 'Sinu kontolt on edukalt eemaldatud kaheastmeline autentimine.'
invalid_code: 'Vale kood!'
# Time units
time:
second: 'sekund'
seconds: 'sekundit'
minute: 'minut'
minutes: 'minutit'
hour: 'tund'
hours: 'tundi'
day: 'päev'
days: 'päeva'
# Two-factor authentication
two_factor:
code_created: '&2Su salajane kood on %code. Skänni see siin: %url'
# TODO confirmation_required: 'Please confirm your code with /2fa confirm <code>'
# TODO code_required: 'Please submit your two-factor authentication code with /2fa code <code>'
# TODO already_enabled: 'Two-factor authentication is already enabled for your account!'
# TODO enable_error_no_code: 'No 2fa key has been generated for you or it has expired. Please run /2fa add'
# TODO enable_success: 'Successfully enabled two-factor authentication for your account'
# TODO enable_error_wrong_code: 'Wrong code or code has expired. Please run /2fa add'
# TODO not_enabled_error: 'Two-factor authentication is not enabled for your account. Run /2fa add'
# TODO removed_success: 'Successfully removed two-factor auth from your account'
# TODO invalid_code: 'Invalid code!'
second: 'sekund'
seconds: 'sekundit'
minute: 'minut'
minutes: 'minutit'
hour: 'tund'
hours: 'tundi'
day: 'päev'
days: 'päeva'

View File

@ -1,12 +1,12 @@
# Traduction par: André & Twonox
# Pour afficher une apostrophe, vous devez en mettre deux consécutivement (ex: «J''ai» au lieu de «J'ai»)
# List of global tags:
# %nl% - Pour passer à la ligne.
# %username% - Replaces the username of the player receiving the message.
# %displayname% - Replaces the nickname (and colors) of the player receiving the message.
# Liste des tags globaux:
# %nl% - Permet de passer à la ligne.
# %username% - Affiche le pseudo du joueur recevant le message.
# %displayname% - Affiche le pseudo, avec couleurs, du joueur recevant le message.
# Registration
# Enregistrement
registration:
disabled: '&cL''inscription est désactivée.'
name_taken: '&cUtilisateur déjà inscrit.'
@ -16,7 +16,7 @@ registration:
success: '&aInscription effectuée !'
kicked_admin_registered: 'Un admin vient de vous inscrire, veuillez vous reconnecter.'
# Password errors on registration
# Erreurs de mot de passe lors de l'enregistrement
password:
match_error: '&cLe mot de passe de confirmation ne correspond pas.'
name_in_password: '&cVous ne pouvez pas utiliser votre pseudo comme mot de passe.'
@ -24,15 +24,15 @@ password:
forbidden_characters: '&cVotre mot de passe contient des caractères non autorisés. Caractères permis : %valid_chars'
wrong_length: '&cVotre mot de passe est trop court ou trop long !'
# Login
# Identification
login:
command_usage: '&cUsage: /login <MotDePasse>'
wrong_password: '&cMauvais mot de passe !'
success: '&aConnexion effectuée !'
login_request: '&cPour vous connecter, utilisez "/login <MotDePasse>"'
timeout_error: 'Vous avez été expulsé car vous êtes trop lent pour vous enregistrer/connecter !'
success: '&aIdentification effectuée !'
login_request: '&cPour vous identifier, utilisez "/login <MotDePasse>"'
timeout_error: 'Vous avez été expulsé car vous êtes trop lent pour vous enregistrer/identifier !'
# Errors
# Erreurs
error:
denied_command: '&cVous devez être connecté pour pouvoir utiliser cette commande.'
denied_chat: '&cVous devez être connecté pour pouvoir écrire dans le chat.'
@ -51,12 +51,12 @@ antibot:
auto_enabled: 'L''AntiBot a été activé automatiquement à cause de nombreuses connexions !'
auto_disabled: 'L''AntiBot a été désactivé automatiquement après %m minutes, espérons que l''invasion se soit arrêtée !'
# Unregister
# Dé-enregistrement
unregister:
success: '&aCompte supprimé !'
command_usage: '&cPour supprimer votre compte, utilisez "/unregister <MotDePasse>"'
# Other messages
# Messages divers
misc:
account_not_activated: '&fCe compte n''est pas actif, consultez vos mails !'
password_changed: '&aMot de passe changé avec succès !'
@ -66,12 +66,12 @@ misc:
accounts_owned_self: 'Vous avez %count comptes:'
accounts_owned_other: 'Le joueur %name a %count comptes:'
# Session messages
# Messages de sessions
session:
valid_session: '&aVous avez été automatiquement connecté !'
invalid_session: 'Session expirée suite à un changement d''IP.'
# Error messages when joining
# Messages d'erreurs lors de la connexion
on_join_validation:
same_ip_online: 'Un joueur avec la même adresse IP joue déjà !'
same_nick_online: 'Un joueur ayant le même pseudo est déjà connecté.'
@ -81,7 +81,7 @@ on_join_validation:
country_banned: 'Votre pays est banni de ce serveur.'
not_owner_error: 'Vous n''êtes pas le propriétaire de ce compte. Veuillez utiliser un autre pseudo !'
invalid_name_case: 'Veuillez vous connecter avec "%valid" et non pas avec "%invalid".'
# TODO quick_command: 'You used a command too fast! Please, join the server again and wait more before using any command.'
quick_command: '&cUtilisation trop rapide de commande! Veuillez vous reconnecter et attendre un peu avant d''executer une commande.'
# Email
email:
@ -92,10 +92,10 @@ email:
old_email_invalid: '&cAncien email invalide !'
invalid: '&cL''email inscrit est invalide !'
added: '&aEmail enregistré. En cas de perte de MDP, faites "/email recover <Email>"'
# TODO add_not_allowed: '&cAdding email was not allowed'
add_not_allowed: '&cVous n''êtes pas autorisé à ajouter une adresse mail.'
request_confirmation: '&cLa confirmation de l''email est manquante ou éronnée.'
changed: '&aVotre email a été mis à jour.'
# TODO change_not_allowed: '&cChanging email was not allowed'
change_not_allowed: '&cVous n''êtes pas autorisé à modifier l''adresse mail.'
email_show: '&fL''email enregistré pour votre compte est: %email'
no_email_for_account: '&c&oVous n''avez aucun email enregistré sur votre compte.'
already_used: '&cCet email est déjà utilisé !'
@ -104,7 +104,7 @@ email:
change_password_expired: 'Vous ne pouvez pas changer votre mot de passe avec cette commande.'
email_cooldown_error: '&cUn mail de récupération a déjà été envoyé récemment. Veuillez attendre %time pour le demander de nouveau.'
# Password recovery by email
# Récupération de mot de passe par mail
recovery:
forgot_password_hint: '&cVous avez oublié votre Mot de Passe? Utilisez "/email recovery <votreEmail>"'
command_usage: '&fUsage: /email recovery <Email>'
@ -124,7 +124,7 @@ captcha:
captcha_for_registration: 'Avant de vous inscrire veuillez rentrer un captcha en faisant "/captcha %captcha_code"'
register_captcha_valid: '&aCaptcha validé! Vous pouvez maintenant vous inscrire.'
# Verification code
# Code de vérification
verification:
code_required: '&cCette commande est sensible, elle nécessite donc une confirmation par email.%nl%&cVeuillez suivre les instructions qui viennent de vous être envoyées par email.'
command_usage: '&cUsage: /verification <code>'
@ -134,7 +134,20 @@ verification:
code_expired: '&cVotre code d''identification a expiré !%nl%&cVeuillez re-exécuter une commande sensible pour recevoir un nouveau code.'
email_needed: '&cAfin de vérifier votre identité, vous devez avoir un email lié à votre compte.%nl%&cPour cela, faites "/email add <Email> <ConfirmerEmail>"'
# Time units
# Authentification à double facteur
two_factor:
code_created: '&aVotre code secret est &2%code&a. Vous pouvez le scanner depuis &2%url'
code_required: 'Veuillez indiquer votre code secret en écrivant "/2fa code <Code>"'
confirmation_required: 'Veuillez confirmer votre code secret en écrivant "/2fa confirm <Code>"'
already_enabled: '&aL''authentification à double facteur est déjà active !'
enable_error_no_code: '&cAucun code secret n''a été généré ou bien celui-ci a expiré. Veuillez écrire "/2fa add"'
enable_success: '&aL''authentification à double facteur a été activé pour votre compte !'
enable_error_wrong_code: '&cLe code secret est faux ou bien celui-ci a expiré. Veuillez écrire "/2fa add"'
not_enabled_error: '&cL''authentification à double facteur n''est pas active sur votre compte. Faites "/2fa add" pour l''activer.'
removed_success: '&cL''authentification à double facteur a été désactivé pour votre compte !'
invalid_code: '&cCode secret invalide !'
# Unités de temps
time:
second: 'seconde'
seconds: 'secondes'
@ -144,16 +157,3 @@ time:
hours: 'heures'
day: 'jour'
days: 'jours'
# Two-factor authentication
two_factor:
code_created: '&aVotre code secret est &2%code&a. Vous pouvez le scanner depuis &2%url'
# TODO confirmation_required: 'Please confirm your code with /2fa confirm <code>'
# TODO code_required: 'Please submit your two-factor authentication code with /2fa code <code>'
# TODO already_enabled: 'Two-factor authentication is already enabled for your account!'
# TODO enable_error_no_code: 'No 2fa key has been generated for you or it has expired. Please run /2fa add'
# TODO enable_success: 'Successfully enabled two-factor authentication for your account'
# TODO enable_error_wrong_code: 'Wrong code or code has expired. Please run /2fa add'
# TODO not_enabled_error: 'Two-factor authentication is not enabled for your account. Run /2fa add'
# TODO removed_success: 'Successfully removed two-factor auth from your account'
# TODO invalid_code: 'Invalid code!'

View File

@ -7,32 +7,32 @@
registration:
disabled: '&cRegister dalam game tidak diaktifkan!'
name_taken: '&cKamu telah mendaftarkan username ini!'
register_request: '&3Silahkan mendaftar ke server menggunakan command "/register <password> <ulangiPassword>"'
# TODO command_usage: '&cUsage: /register <password> <ConfirmPassword>'
reg_only: '&4Hanya pengguna terdaftar yg bisa bergabung! Silahkan kunjungi http://example.com untuk mendaftar!'
register_request: '&3Silahkan mendaftar ke server menggunakan perintah "/register <password> <ulangiPassword>"'
command_usage: '&cPenggunaan: /register <password> <KonfirmasiPassword>'
reg_only: '&4Hanya pengguna terdaftar yang bisa bergabung! Silahkan kunjungi http://example.com untuk mendaftar!'
success: '&2Register berhasil!'
# TODO kicked_admin_registered: 'An admin just registered you; please log in again'
kicked_admin_registered: 'Administrator sudah meregistrasi kamu; dimohon untuk login kembali'
# Password errors on registration
password:
match_error: '&cPassword tidak cocok, silahkan periksa dan ulangi kembali!'
name_in_password: '&cKamu tidak bisa menggunakan namamu sebagai password, silahkan coba yg lain...'
unsafe_password: '&cPassword yg kamu pilih tidak aman, silahkan coba yg lain...'
# TODO forbidden_characters: '&4Your password contains illegal characters. Allowed chars: %valid_chars'
wrong_length: '&cPassword kamu terlalu panjang/pendek! Silahkan pilih yg lain!'
name_in_password: '&cKamu tidak bisa menggunakan namamu sebagai password, silahkan coba yang lain...'
unsafe_password: '&cPassword yang kamu pilih tidak aman, silahkan coba yang lain...'
forbidden_characters: '&4Password kamu memiliki karakter illegal. Karakter yang diperbolehkan: %valid_chars'
wrong_length: '&cPassword kamu terlalu panjang/pendek! Silahkan pilih yang lain!'
# Login
login:
command_usage: '&cUsage: /login <password>'
command_usage: '&cPenggunaan: /login <password>'
wrong_password: '&cPassword salah!'
success: '&2Login berhasil!'
login_request: '&cSilahkan login menggunakan command "/login <password>"'
timeout_error: '&4Jangka waktu login telah habis, kamu di keluarkan dari server. Silahkan coba lagi!'
login_request: '&cSilahkan login menggunakan perintah "/login <password>"'
timeout_error: '&4Jangka waktu login telah habis, kamu dikeluarkan dari server. Silahkan coba lagi!'
# Errors
error:
# TODO denied_command: '&cIn order to use this command you must be authenticated!'
# TODO denied_chat: '&cIn order to chat you must be authenticated!'
denied_command: '&cUntuk menggunakan perintah ini, kamu harus terautentikasi!'
denied_chat: '&cUntuk mengobrol, kamu harus terautentikasi!'
unregistered_user: '&cUser ini belum terdaftar!'
not_logged_in: '&cKamu belum login!'
no_permission: '&4Kamu tidak mempunyai izin melakukan ini!'
@ -40,18 +40,18 @@ error:
max_registration: '&Kamu telah mencapai batas maksimum pendaftaran di server ini!'
logged_in: '&cKamu telah login!'
kick_for_vip: '&3Player VIP mencoba masuk pada saat server sedang penuh!'
# TODO tempban_max_logins: '&cYou have been temporarily banned for failing to log in too many times.'
tempban_max_logins: '&cKamu untuk sementara diblokir karena terlalu sering salah saat login.'
# AntiBot
antibot:
# TODO kick_antibot: 'AntiBot protection mode is enabled! You have to wait some minutes before joining the server.'
kick_antibot: 'Proteksi AntiBot diaktifkan! Kamu harus menunggu beberapa menit sebelum masuk server.'
auto_enabled: '&4[AntiBotService] AntiBot diaktifkan dikarenakan banyak koneksi yg diterima!'
auto_disabled: '&2[AntiBotService] AntiBot dimatikan setelah %m menit!'
# Unregister
unregister:
success: '&cUnregister berhasil!'
# TODO command_usage: '&cUsage: /unregister <password>'
command_usage: '&cPenggunaan: /unregister <password>'
# Other messages
misc:
@ -59,9 +59,9 @@ misc:
password_changed: '&2Berhasil mengubah password!'
logout: '&2Berhasil logout!'
reload: '&2Konfigurasi dan database telah dimuat ulang!'
usage_change_password: '&cUsage: /changepassword <passwordLama> <passwordBaru>'
# TODO accounts_owned_self: 'You own %count accounts:'
# TODO accounts_owned_other: 'The player %name has %count accounts:'
usage_change_password: '&cPenggunaan: /changepassword <passwordLama> <passwordBaru>'
accounts_owned_self: 'Kamu memiliki %count akun:'
accounts_owned_other: 'Pengguna akun %name memiliki %count akun:'
# Session messages
session:
@ -70,56 +70,56 @@ session:
# Error messages when joining
on_join_validation:
# TODO same_ip_online: 'A player with the same IP is already in game!'
same_ip_online: 'Seorang pemain dengan IP yang sama sudah didalam permainan!'
same_nick_online: '&4Username yg sama telah bermain di server ini!'
name_length: '&4Username kamu terlalu panjang atau terlalu pendek!'
characters_in_name: '&4Username kamu mengandung karakter illegal. Karakter yg diijinkan: %valid_chars'
characters_in_name: '&4Username kamu mengandung karakter illegal. Karakter yg diizinkan: %valid_chars'
kick_full_server: '&4Server sedang penuh, silahkan coba lagi nanti!'
# TODO country_banned: '&4Your country is banned from this server!'
# TODO not_owner_error: 'You are not the owner of this account. Please choose another name!'
# TODO invalid_name_case: 'You should join using username %valid, not %invalid.'
# TODO quick_command: 'You used a command too fast! Please, join the server again and wait more before using any command.'
country_banned: '&4Negara kamu diblokir dari server ini!'
not_owner_error: 'Kamu bukan pemilik dari akun ini. Tolong pilih nama lain!'
invalid_name_case: 'Kamu seharusnya masuk menggunakan username %valid, bukan %invalid.'
quick_command: 'Kamu menggunakan perintah terlalu cepat! Tolong masuk kembali ke server dan tunggu sebentar sebelum menggunakan perintah lagi.'
# Email
email:
add_email_request: '&3Silahkan tambahkan email ke akunmu menggunakan command "/email add <emailKamu> <ulangiEmail>"'
usage_email_add: '&cUsage: /email add <email> <ulangiEmail>'
usage_email_change: '&cUsage: /email change <emailLama> <emailBaru>'
add_email_request: '&3Silahkan tambahkan email ke akunmu menggunakan perintah "/email add <emailKamu> <ulangiEmail>"'
usage_email_add: '&cPenggunaan: /email add <email> <ulangiEmail>'
usage_email_change: '&cPenggunaan: /email change <emailLama> <emailBaru>'
new_email_invalid: '&cEmail baru tidak valid, coba lagi!'
old_email_invalid: '&cEmail lama tidak valid, coba lagi!'
invalid: '&cAlamat email tidak valid, coba lagi!'
added: '&2Berhasil menambahkan alamat email ke akunmu!'
# TODO add_not_allowed: '&cAdding email was not allowed'
add_not_allowed: '&cMenambah email tidak diperbolehkan'
request_confirmation: '&cSilahkan konfirmasi alamat email kamu!'
changed: '&2Alamat email telah diubah dengan benar!'
# TODO change_not_allowed: '&cChanging email was not allowed'
# TODO email_show: '&2Your current email address is: &f%email'
# TODO no_email_for_account: '&2You currently don''t have email address associated with this account.'
# TODO already_used: '&4The email address is already being used'
# TODO incomplete_settings: 'Error: not all required settings are set for sending emails. Please contact an admin.'
# TODO send_failure: 'The email could not be sent. Please contact an administrator.'
# TODO change_password_expired: 'You cannot change your password using this command anymore.'
# TODO email_cooldown_error: '&cAn email was already sent recently. You must wait %time before you can send a new one.'
change_not_allowed: '&cMengubah email tidak diperbolehkan'
email_show: '&2Emailmu saat ini: &f%email'
no_email_for_account: '&2Kamu tidak memiliki alamat email terkait dengan akun ini.'
already_used: '&4Alamat email sudah terpakai'
incomplete_settings: 'Error: tidak semua syarat setelan disetel untuk mengirim email. Tolong kontak Administrator.'
send_failure: 'Email tidak dapat dikirim. Tolong kontak Administrator.'
change_password_expired: 'Kamu tidak dapat mengubah password menggunakan perintah ini lagi.'
email_cooldown_error: '&cSebuah email telah dikirim beberapa waktu lalu. Kamu harus menunggu %time sebelum kamu mengirim yang baru.'
# Password recovery by email
recovery:
forgot_password_hint: '&3Lupa password? silahkan gunakan command "/email recovery <emailKamu>"'
command_usage: '&cUsage: /email recovery <Email>'
command_usage: '&cPenggunaan: /email recovery <Email>'
email_sent: '&2Email pemulihan akun telah dikirim! Silahkan periksa kotak masuk emailmu!'
code:
# TODO code_sent: 'A recovery code to reset your password has been sent to your email.'
# TODO incorrect: 'The recovery code is not correct! You have %count tries remaining.'
# TODO tries_exceeded: 'You have exceeded the maximum number attempts to enter the recovery code. Use "/email recovery [email]" to generate a new one.'
# TODO correct: 'Recovery code entered correctly!'
# TODO change_password: 'Please use the command /email setpassword <new password> to change your password immediately.'
code_sent: 'Sebuah kode pemulihan untuk mengatur ulang passwordmu telah terkirim ke emailmu.'
incorrect: 'Kode pemulihan salah! Kamu memiliki %count kali kesempatan tersisa.'
tries_exceeded: 'Kamu telah mencapai batas maksimal untuk memasukkan kode pemulihan. Gunakan "/email recovery [email]" membuat yang baru.'
correct: 'Kode pemulihan berhasil dimasukkan!'
change_password: 'Tolong gunakan perintah /email setpassword <password baru> untuk mengubah passwordmu segera.'
# Captcha
captcha:
usage_captcha: '&3Kamu harus menyelesaikan kode captcha untuk login, silahkan gunakan command "/captcha %captcha_code"'
wrong_captcha: '&cCaptcha salah, gunakan command "/captcha %captcha_code" pada chat!'
usage_captcha: '&3Kamu harus menyelesaikan kode captcha untuk login, silahkan gunakan perintah "/captcha %captcha_code"'
wrong_captcha: '&cCaptcha salah, gunakan perintah "/captcha %captcha_code" pada komentar!'
valid_captcha: '&2Kode captcha terselesaikan!'
# TODO captcha_for_registration: 'To register you have to solve a captcha first, please use the command: /captcha %captcha_code'
# TODO register_captcha_valid: '&2Valid captcha! You may now register with /register'
captcha_for_registration: 'Untuk meregistrasi, kamu harus menyelesaikan captcha terlebih dahulu, tolong gunakan perintah: /captcha %captcha_code'
register_captcha_valid: '&2Captcha terselesaikan! Kini kamu dapat mendaftar dengan /register'
# Verification code
verification:
@ -133,24 +133,24 @@ verification:
# Time units
time:
# TODO second: 'second'
# TODO seconds: 'seconds'
# TODO minute: 'minute'
# TODO minutes: 'minutes'
# TODO hour: 'hour'
# TODO hours: 'hours'
# TODO day: 'day'
# TODO days: 'days'
second: 'detik'
seconds: 'detik'
minute: 'menit'
minutes: 'menit'
hour: 'jam'
hours: 'jam'
day: 'hari'
days: 'hari'
# Two-factor authentication
two_factor:
# TODO code_created: '&2Your secret code is %code. You can scan it from here %url'
# TODO confirmation_required: 'Please confirm your code with /2fa confirm <code>'
# TODO code_required: 'Please submit your two-factor authentication code with /2fa code <code>'
# TODO already_enabled: 'Two-factor authentication is already enabled for your account!'
# TODO enable_error_no_code: 'No 2fa key has been generated for you or it has expired. Please run /2fa add'
# TODO enable_success: 'Successfully enabled two-factor authentication for your account'
# TODO enable_error_wrong_code: 'Wrong code or code has expired. Please run /2fa add'
# TODO not_enabled_error: 'Two-factor authentication is not enabled for your account. Run /2fa add'
# TODO removed_success: 'Successfully removed two-factor auth from your account'
# TODO invalid_code: 'Invalid code!'
code_created: '&2Kode rahasiamu adalah %code. Kamu dapat memindainya di %url'
confirmation_required: 'Tolong konfirmasi kodemu dengan /2fa confirm <code>'
code_required: 'Mohon kirimkan kode dari autentikasi dua langkah dengan /2fa code <code>'
already_enabled: 'Autentikasi dua langkah sudah diaktifkan untuk akunmu!'
enable_error_no_code: 'Tidak ada kunci autentikasi dua langkah atau sudah kadaluarsa. Tolong jalankan /2fa add'
enable_success: 'Sukses mengaktifkan autentikasi dua langkah untuk akunmu'
enable_error_wrong_code: 'Kode salah atau kode sudah kadaluarsa. Tolong jalankan /2fa add'
not_enabled_error: 'Autentikasi dua langkah tidak diaktifkan untuk akunmu. Jalankan /2fa add'
removed_success: 'Sukses menghapus autentikasi dua langkah dari akunmu'
invalid_code: 'Kode tidak valid!'

View File

@ -1,4 +1,4 @@
#Translated by Kirito (kds123321@naver.com), System32(me@syst32.com), Adeuran(adeuran@tistory.com)
#Translated by Kirito (kds123321@naver.com), Spectre (me@ptr.kr), Adeuran(adeuran@tistory.com)
#14.05.2017 Thanks for use
# List of global tags:
# %nl% - Goes to new line.
@ -7,12 +7,12 @@
# Registration
registration:
disabled: '&c게임 안에서의 회원가입은 비활성화 되어 있습니다!'
name_taken: '&c이미 이 닉네임으로 회원가입이 되어 있습니다!'
disabled: '&c현재 회원 가입이 비활성화 되어 있습니다!'
name_taken: '&c이미 이 닉네임으로 회원 가입이 되어 있습니다!'
register_request: '&3다음 명령어로 서버에 가입해주세요: /register <비밀번호> <비밀번호 확인>'
command_usage: '&c사용법: /register <비밀번호> <비밀번호 확인>'
reg_only: '&4등록된 유저만 서버에 접속할 수 있습니다! 서버 홈페이지에 방문하여 가입해 주세요!'
success: '&2회원가입이 완료되었습니다!'
success: '&2회원 가입이 완료되었습니다!'
kicked_admin_registered: '관리자가 방금 이 닉네임을 등록했습니다. 다시 로그인 해주세요'
# Password errors on registration
@ -41,7 +41,7 @@ error:
unexpected_error: '&4예기치 않은 오류가 발생했습니다, 관리자에게 알려주세요!'
max_registration: '&c당신은 가입할 수 있는 계정 한도를 초과했습니다 (%reg_count/%max_acc %reg_names)!'
logged_in: '&c이미 로그인되어 있습니다!'
kick_for_vip: '&3서버가 꽉 차있을 VIP 플레이어만 접속이 가능합니다!'
kick_for_vip: '&3서버가 꽉 차있을 때는 VIP 플레이어만 접속이 가능합니다!'
tempban_max_logins: '&c너무 많이 로그인에 실패하여 잠시 서버에서 차단되었습니다.'
# AntiBot
@ -80,7 +80,7 @@ on_join_validation:
country_banned: '&4당신의 국가에서는 이 서버를 이용하실 수 없습니다!'
not_owner_error: '이 계정의 소유자가 아닙니다. 다른 닉네임을 선택하세요!'
invalid_name_case: '%invalid가 아닌, %valid 사용하여 접속해야 합니다.'
# TODO quick_command: 'You used a command too fast! Please, join the server again and wait more before using any command.'
quick_command: '명령어를 너무 빠르게 입력하고 있습니다! 서버에 다시 접속한 후 조금만 기다려주시기 바랍니다.'
# Email
email:
@ -91,10 +91,10 @@ email:
old_email_invalid: '&c예전 이메일 주소가 잘못되었습니다. 다시 시도해보세요!'
invalid: '&c이메일 주소가 잘못되었습니다. 다시 시도해보세요!'
added: '&2계정에 이메일 주소를 추가했습니다!'
# TODO add_not_allowed: '&cAdding email was not allowed'
add_not_allowed: '&c이메일 주소의 추가가 제한된 상태입니다.'
request_confirmation: '&c이메일 주소를 확인해주세요!'
changed: '&2이메일 주소가 변경되었습니다!'
# TODO change_not_allowed: '&cChanging email was not allowed'
change_not_allowed: '&c이메일 주소의 변경이 제한된 상태입니다.'
email_show: '&2현재 이메일 주소: &f%email'
no_email_for_account: '&2현재 이 계정과 연결된 이메일 주소가 없습니다.'
already_used: '&4이메일 주소가 이미 사용 중입니다.'
@ -120,8 +120,8 @@ captcha:
usage_captcha: '&3로그인 하려면 CAPTCHA 코드를 입력해야 합니다. 이 명령어를 사용하세요: /captcha %captcha_code'
wrong_captcha: '&c잘못된 CAPTCHA 코드 입니다. "/captcha %captcha_code" 형태로 입력해주세요!'
valid_captcha: '&2CAPTCHA 코드가 확인되었습니다!'
captcha_for_registration: '회원가입을 하기 위해서는 먼저 CAPTCHA 코드를 입력해야합니다. 이 명령어를 이 명령어를 사용하세요: /captcha %captcha_code'
register_captcha_valid: '&2올바른 CAPTCHA 코드입니다! 이제 /register 명령어를 이용하여 회원가입할 수 있습니다.'
captcha_for_registration: '회원 가입을 하기 위해서는 먼저 CAPTCHA 코드를 입력해야합니다. 이 명령어를 이 명령어를 사용하세요: /captcha %captcha_code'
register_captcha_valid: '&2올바른 CAPTCHA 코드입니다! 이제 /register 명령어를 이용하여 회원 가입할 수 있습니다.'
# Verification code
verification:
@ -146,13 +146,13 @@ time:
# Two-factor authentication
two_factor:
code_created: '&2당신의 비밀 코드는 %code 입니다. %url 에서 스캔할 수 있습니다'
# TODO confirmation_required: 'Please confirm your code with /2fa confirm <code>'
# TODO code_required: 'Please submit your two-factor authentication code with /2fa code <code>'
# TODO already_enabled: 'Two-factor authentication is already enabled for your account!'
# TODO enable_error_no_code: 'No 2fa key has been generated for you or it has expired. Please run /2fa add'
# TODO enable_success: 'Successfully enabled two-factor authentication for your account'
# TODO enable_error_wrong_code: 'Wrong code or code has expired. Please run /2fa add'
# TODO not_enabled_error: 'Two-factor authentication is not enabled for your account. Run /2fa add'
# TODO removed_success: 'Successfully removed two-factor auth from your account'
# TODO invalid_code: 'Invalid code!'
code_created: '&2당신의 2단계 인증 코드는 %code 입니다. %url 에서 스캔할 수 있습니다'
confirmation_required: '/2fa confirm <code> 명령어를 통해 귀하의 코드를 확인해 주시기 바랍니다.'
code_required: '/2fa code <code> 명령어를 통해 2단계 인증을 진행해주세요.'
already_enabled: '2단계 인증 기능을 이미 활성화하셨습니다!'
enable_error_no_code: '2단계 인증 키가 생성되지 않았거나 만료되었습니다. /2fa add 명령어를 통해 새로 생성해주세요.'
enable_success: '2단계 인증 기능을 성공적으로 활성화하였습니다.'
enable_error_wrong_code: '잘못되었거나 만료된 코드입니다. /2fa add 명령어를 통해 새로 생성해주세요.'
not_enabled_error: '2단계 인증 기능을 활성화하시지 않았습니다. /2fa add 명령어를 통해 활성화해주세요.'
removed_success: '2단계 인증 기능을 성공적으로 비활성화하였습니다.'
invalid_code: '올바르지 않은 인증 코드입니다!'

View File

@ -1,7 +1,3 @@
# List of global tags:
# %nl% - Goes to new line.
# %username% - Replaces the username of the player receiving the message.
# %displayname% - Replaces the nickname (and colors) of the player receiving the message.
# Registration
registration:
@ -12,7 +8,6 @@ registration:
reg_only: '&4Вход только для зарегистрированных! Посетите http://сайт_сервера.ru для регистрации.'
success: '&2Вы успешно зарегистрировались!'
kicked_admin_registered: 'Администратор зарегистрировал вас. Авторизируйтесь снова.'
# Password errors on registration
password:
match_error: '&cПароли не совпадают.'
@ -20,7 +15,6 @@ password:
unsafe_password: '&cТакой пароль небезопасен.'
forbidden_characters: '&4Пароль содержит запрещённые символы. Разрешённые: %valid_chars'
wrong_length: '&cПароль слишком длинный/короткий.'
# Login
login:
command_usage: '&cИспользование: /login <пароль>'
@ -28,7 +22,6 @@ login:
success: '&2Вы успешно вошли!'
login_request: '&3Авторизация: /login <Пароль>'
timeout_error: '&4Время авторизации истекло.'
# Errors
error:
denied_command: '&cНеобходимо авторизоваться для использования этой команды!'
@ -41,18 +34,15 @@ error:
logged_in: '&cВы уже авторизированы!'
kick_for_vip: '&3VIP-игрок зашёл на переполненный сервер.'
tempban_max_logins: '&cВы временно заблокированы из-за большого количества неудачных попыток авторизоваться.'
# AntiBot
antibot:
kick_antibot: 'Сработала защита против ботов! Необходимо подождать перед следующим входом на сервер.'
auto_enabled: '&4[AuthMe] AntiBot-режим включился из-за большого количества входов!'
auto_disabled: '&2[AuthMe] AntiBot-режим отключился спустя %m мин.'
# Unregister
unregister:
success: '&cУчётная запись успешно удалена!'
command_usage: '&cИспользование: /unregister <пароль>'
# Other messages
misc:
account_not_activated: '&cВаша уч. запись ещё не активирована. Проверьте электронную почту!'
@ -62,12 +52,10 @@ misc:
usage_change_password: '&cИспользование: /changepassword <пароль> <новый пароль>'
accounts_owned_self: 'У вас %count уч. записей:'
accounts_owned_other: 'У игрока %name %count уч. записей:'
# Session messages
session:
valid_session: '&2Вы автоматически авторизовались!'
invalid_session: '&cСессия некорректна. Дождитесь, пока она закончится.'
# Error messages when joining
on_join_validation:
same_ip_online: 'Игрок с данным IP-адресом уже играет на сервере!'
@ -79,7 +67,6 @@ on_join_validation:
not_owner_error: 'Вы не являетесь владельцем данной уч. записи. Выберите себе другое имя!'
invalid_name_case: 'Неверное имя! Зайдите под именем %valid, а не %invalid.'
quick_command: 'Вы вводили команды слишком часто! Пожалуйста заходите снова и вводите команды помедленнее.'
# Email
email:
add_email_request: '&3Добавьте электронную почту: /email add <эл. почта> <повтор эл. почты>'
@ -100,7 +87,6 @@ email:
send_failure: 'Письмо не может быть отправлено. Свяжитесь в администратором.'
change_password_expired: 'Больше нельзя сменить свой пароль, используя эту команду.'
email_cooldown_error: '&cПисьмо было отправлено недавно. Подождите %time, прежде чем отправить новое.'
# Password recovery by email
recovery:
forgot_password_hint: '&Забыли пароль? Используйте «/email recovery <эл. почта>».'
@ -112,7 +98,6 @@ recovery:
tries_exceeded: 'Вы слишком много раз неверно ввели код восстановления. Используйте «/email recovery [эл. почта]», чтобы получить новый код.'
correct: 'Код восстановления введён верно!'
change_password: 'Используйте «/email setpassword <новый пароль>», чтобы сменить свой пароль.'
# Captcha
captcha:
usage_captcha: '&3Необходимо ввести текст с каптчи. Используйте «/captcha %captcha_code»'
@ -120,7 +105,6 @@ captcha:
valid_captcha: '&2Вы успешно решили каптчу!'
captcha_for_registration: 'Чтобы зарегистрироваться, решите каптчу используя команду: «/captcha %captcha_code»'
register_captcha_valid: '&2Вы успешно решили каптчу! Теперь вы можете зарегистрироваться командой «/register»'
# Verification code
verification:
code_required: '&3Эта команда чувствительна и требует подтверждения электронной почты! Проверьте свою почту и следуйте инструкциям в письме.'
@ -130,7 +114,6 @@ verification:
already_verified: '&2Вы уже можете выполнять все чувствительные команды в текущем сеансе!'
code_expired: '&3Срок действия кода истёк! Выполните чувствительную команду, чтобы получить новый код!'
email_needed: '&3Чтобы подтвердить вашу личность, необходимо привязать электронную почту к учётной записи!!'
# Time units
time:
second: 'с.'
@ -141,16 +124,15 @@ time:
hours: 'ч.'
day: 'дн.'
days: 'дн.'
# Two-factor authentication
two_factor:
code_created: '&2Ваш секретный код — %code. Просканируйте его здесь: %url'
confirmation_required: 'Пожалуйста, подтвердите ваш код с помощью /2fa confirm <код>'
# TODO code_required: 'Please submit your two-factor authentication code with /2fa code <code>'
# TODO already_enabled: 'Two-factor authentication is already enabled for your account!'
# TODO enable_error_no_code: 'No 2fa key has been generated for you or it has expired. Please run /2fa add'
code_required: 'Пожалуйста, введите ваш код двухфакторной аутентификации используя команду /2fa code <код>'
already_enabled: 'Двухфакторная аутентификация уже активирована для вашего аккаунта!'
enable_error_no_code: 'Код двухфакторной аутентификации не был сгенерирован или истек. Пожалуйста, введите /2fa add'
enable_success: 'Двухфакторная аутентификация для вашего аккаунта успешно подключена'
# TODO enable_error_wrong_code: 'Wrong code or code has expired. Please run /2fa add'
# TODO not_enabled_error: 'Two-factor authentication is not enabled for your account. Run /2fa add'
# TODO removed_success: 'Successfully removed two-factor auth from your account'
# TODO invalid_code: 'Invalid code!'
enable_error_wrong_code: 'Срок действия кода истек или код неверный. Введите /2fa add'
not_enabled_error: 'Двухфакторная аутентификация не включена для вашего аккаунта. Введите /2fa add'
removed_success: 'Двухфакторная аутентификация успешно удалена с вашего аккаунта!'
invalid_code: 'Неверный код!'

View File

@ -17,13 +17,13 @@ registration:
command_usage: '&cPoužitie: /register <heslo> <zopakujHeslo>'
reg_only: '&fIba zaregistrovaný hráči sa môžu pripojiť na tento server! Navštív http://example.com pre registráciu.'
success: '&cBol si úspešne zaregistrovaný.'
kicked_admin_registered: 'Admin ťa zaregistroval; prosím prihlás sa znovu.'
kicked_admin_registered: 'Admin ťa zaregistroval. Prosím, prihlás sa znovu.'
# Password errors on registration
password:
match_error: '&fHeslá sa nezhodujú.'
name_in_password: '&cNemôžeš použiť tvoje meno ako heslo, prosím zvoľ si iné...'
unsafe_password: '&cTvoje heslo nieje bezpečné, prosím zvoľ si iné...'
name_in_password: '&cNemôžeš použiť tvoje meno ako heslo. Prosím, zvoľ si iné...'
unsafe_password: '&cTvoje heslo nieje bezpečné. Prosím, zvoľ si iné...'
forbidden_characters: '&4Tvoje heslo obsahuje zakázané znaky. Povolené znaky: %valid_chars'
wrong_length: '&fHeslo je veľmi krátke alebo veľmi dlhé.'
@ -40,7 +40,7 @@ error:
denied_command: '&cPre použitie tohto príkazu sa musíš prihlásiť!'
denied_chat: '&cMusíš byť prihlásený ak chceš použiť chat!'
unregistered_user: '&cZadané meno nie je zaregistrované!'
not_logged_in: '&cNie si ešte prihlásený!'
not_logged_in: '&cEšte nie si prihlásený!'
no_permission: '&cNemáš dostatočné práva na vykonanie tejto činnosti.'
unexpected_error: '&fNastala chyba, prosím kontaktuj Administrátora.'
max_registration: '&fPrekročil si maximum registrovaných účtov(%reg_count/%max_acc|%reg_names).'
@ -77,13 +77,13 @@ session:
# Error messages when joining
on_join_validation:
same_ip_online: 'Hráč s tvojou IP už hrá na tomto serveri!'
same_nick_online: '&fHrác s týmto nickom už hrá!'
same_nick_online: '&fHráč s týmto nickom už hrá!'
name_length: '&cTvoje meno je veľmi krátke alebo veľmi dlhé.'
characters_in_name: '&cTvoje meno obsahuje zakázané znaky. Povolené znaky: %valid_chars'
kick_full_server: '&4Server je plný, skús znovu neskôr!'
kick_full_server: '&4Server je plný, skús to znovu neskôr!'
country_banned: '&4Tvoja krajina je zabanovaná na tomto serveri!'
not_owner_error: 'Niesi majiteľ tohto účtu. Prosím zvoľ si iné meno!'
invalid_name_case: 'Mal by si sa pripojiť s nickom %valid, nie %invalid -pozor na veľké a malé písmená.'
not_owner_error: 'Nie si majiteľom tohto účtu. Prosím zvoľ si iné meno!'
invalid_name_case: 'Mal by si sa pripojiť s nickom %valid, nie %invalid - pozor na veľké a malé písmená.'
# TODO quick_command: 'You used a command too fast! Please, join the server again and wait more before using any command.'
# Email

View File

@ -2,6 +2,7 @@
# %nl% - Goes to new line.
# %username% - Replaces the username of the player receiving the message.
# %displayname% - Replaces the nickname (and colors) of the player receiving the message.
# Edited: 2018/09/16 MCBBS ID:CH1
# Registration
registration:
@ -78,7 +79,7 @@ on_join_validation:
country_banned: '这个服务器禁止该国家登陆'
not_owner_error: '&8[&6玩家系统&8] &4警告 &c你并不是此帐户持有人请立即登出。 '
invalid_name_case: '&8[&6玩家系统&8] &c你应该使用「%valid」而并非「%invalid」登入游戏。 '
# TODO quick_command: 'You used a command too fast! Please, join the server again and wait more before using any command.'
quick_command: '&8[&6玩家系统&8] &c您发送命令的速度太快了请重新加入服务器等待一会后再使用命令'
# Email
email:
@ -144,13 +145,13 @@ time:
# Two-factor authentication
two_factor:
code_created: '&8[&6玩家系统&8] &2你的代码是 %code你可以使用 %url 来扫描'
# TODO confirmation_required: 'Please confirm your code with /2fa confirm <code>'
# TODO code_required: 'Please submit your two-factor authentication code with /2fa code <code>'
# TODO already_enabled: 'Two-factor authentication is already enabled for your account!'
# TODO enable_error_no_code: 'No 2fa key has been generated for you or it has expired. Please run /2fa add'
# TODO enable_success: 'Successfully enabled two-factor authentication for your account'
# TODO enable_error_wrong_code: 'Wrong code or code has expired. Please run /2fa add'
# TODO not_enabled_error: 'Two-factor authentication is not enabled for your account. Run /2fa add'
# TODO removed_success: 'Successfully removed two-factor auth from your account'
# TODO invalid_code: 'Invalid code!'
code_created: '&8[&6玩家系统&8] &a你的代码是 %code你可以使用 %url 来进行扫描'
confirmation_required: '&8[&6玩家系统&8] &3请输入 &a/2fa confirm <验证码> &3来确认两步验证'
code_required: '&8[&6玩家系统&8] &c请输入 &a/2fa code <验证码> &c来提交两步验证验证码'
already_enabled: '&8[&6玩家系统&8] &a两步验证码已在您的账号上启用'
enable_error_no_code: '&8[&6玩家系统&8] &c两步验证密钥不存在或已过期请输入 &a/2fa add &c来添加'
enable_success: '&8[&6玩家系统&8] &a已成功启用两步验证码'
enable_error_wrong_code: '&8[&6玩家系统&8] &c两步验证代码错误或者已经过期请重新执行 &a/2fa add'
not_enabled_error: '&8[&6玩家系统&8] &c两步验证码未在您的账号上启用请使用 &a/2fa add &c来启用'
removed_success: '&8[&6玩家系统&8] &c两步验证码已从您的账号上删除'
invalid_code: '&8[&6玩家系统&8] &c无效的验证码'

View File

@ -1,5 +1,5 @@
# Translator: lifehome<m@lifeho.me> #
# Last modif: 1508689979 UTC #
# Last modif: 1541690611 UTC #
# -------------------------------------------- #
# List of global tags:
# %nl% - Goes to new line.
@ -10,7 +10,7 @@
registration:
disabled: '&8[&6用戶系統&8] &c本伺服器已停止新玩家註冊。'
name_taken: '&8[&6用戶系統&8] &c此用戶名已經註冊過了。'
register_request: '&8[&6用戶系統&8] &c請使用這個指令來註冊/register <密碼> <重覆密碼> 》'
register_request: '&8[&6用戶系統&8] &c請使用這個指令來註冊&f/register <密碼> <重覆密碼>&c 》'
command_usage: '&8[&6用戶系統&8] &f用法《 /register <密碼> <重覆密碼> 》'
reg_only: '&8[&6用戶系統&8] &f限已註冊會員請先到本服網站進行註冊。'
success: '&8[&6用戶系統&8] &b你成功註冊了。'
@ -19,17 +19,17 @@ registration:
# Password errors on registration
password:
match_error: '&8[&6用戶系統&8] &f密碼不符合。'
name_in_password: '&8[&6用戶系統&8] &c這個密碼太不安全了'
unsafe_password: '&8[&6用戶系統&8] &c這個密碼太不安全了'
name_in_password: '&8[&6用戶系統&8] &c這個密碼太不安全了 '
unsafe_password: '&8[&6用戶系統&8] &c這個密碼太不安全了 '
forbidden_characters: '&8[&6用戶系統&8] &4密碼字符只能含有這些喔%valid_chars'
wrong_length: '&8[&6用戶系統&8] &f嗯你的密碼並不符合規定長度。'
wrong_length: '&8[&6用戶系統&8] &f嗯... 你的密碼並不符合規定長度。'
# Login
login:
command_usage: '&8[&6用戶系統&8] &f用法《 /login <密碼> 》'
wrong_password: '&8[&6用戶系統&8] &c你輸入了錯誤的密碼。'
success: '&8[&6用戶系統&8] &a你成功登入了。'
login_request: '&8[&6用戶系統&8] &c請使用這個指令來登入/login <密碼> 》'
login_request: '&8[&6用戶系統&8] &c請使用這個指令來登入&f/login <密碼>&c 》'
timeout_error: '&8[&6用戶系統&8] &f登入逾時。'
# Errors
@ -42,18 +42,18 @@ error:
unexpected_error: '&8[&6用戶系統&8] &f發生錯誤請與管理員聯絡。'
max_registration: '&8[&6用戶系統&8] &f你的IP地址已達到註冊數上限。 &7(info: %reg_count/%max_acc %reg_names)'
logged_in: '&8[&6用戶系統&8] &c你已經登入過了。'
kick_for_vip: '&c喔因為有VIP玩家登入了伺服器。'
kick_for_vip: '&c喔 因為有VIP玩家登入了伺服器。'
tempban_max_logins: '&8[&6用戶系統&8] &c因為多次登入失敗你已被暫時封禁。'
# AntiBot
antibot:
kick_antibot: '&8[&6用戶系統&8] &c伺服器錯誤!請稍候再嘗試登入吧。 &7(err: kick_due2_bot)'
kick_antibot: '&8[&6用戶系統&8] &c伺服器錯誤 !請稍候再嘗試登入吧。 &7(err: kick_due2_bot)'
auto_enabled: '&8[&6用戶系統&8] &3防止機械人程序已因應現時大量不尋常連線而啟用。'
auto_disabled: '&8[&6用戶系統&8] &3不正常連接數已減少防止機械人程序將於 %m 分鐘後停止。'
# Unregister
unregister:
success: '&8[&6用戶系統&8] &c已成功刪除會員註冊記錄。'
success: '&8[&6用戶系統&8] &c已成功刪除會員註冊記錄。'
command_usage: '&8[&6用戶系統&8] &f用法《 /unregister <密碼> 》'
# Other messages
@ -73,15 +73,15 @@ session:
# Error messages when joining
on_join_validation:
same_ip_online: '&8[&6用戶系統&8] 你正使用的 IP 位址已被其他玩家佔用。'
same_ip_online: '&8[&6用戶系統&8] &c你正使用的 IP 位址已被其他玩家佔用。'
same_nick_online: '&8[&6用戶系統&8] &f同名玩家已在遊玩。'
name_length: '&8[&6用戶系統&8] &c你的用戶名不符合規定長度。'
characters_in_name: '&8[&6用戶系統&8] &c用戶名稱錯誤 登入系統只接受以下字符:%valid_chars'
kick_full_server: '&c抱歉 因為伺服器滿人了,所以你目前未能登入伺服器。'
country_banned: '&8[&6用戶系統&8] &4本伺服器已停止對你的國家提供遊戲服務。'
not_owner_error: '&8[&6用戶系統&8] &4警告&c你並不是此帳戶持有人請立即登出。'
invalid_name_case: '&8[&6用戶系統&8] &4警告&c你應該使用「%valid」而並非「%invalid」登入遊戲。'
# TODO quick_command: 'You used a command too fast! Please, join the server again and wait more before using any command.'
characters_in_name: '&8[&6用戶系統&8] &c用戶名稱錯誤 登入系統只接受以下字符:%valid_chars'
kick_full_server: '&c抱歉 因為伺服器滿人了,所以你目前未能登入伺服器。'
country_banned: '&8[&6用戶系統&8] &c抱歉 &4本伺服器已停止對你的國家提供遊戲服務。'
not_owner_error: '&8[&6用戶系統&8] &4警告 &c你並不是此帳戶持有人請立即登出。'
invalid_name_case: '&8[&6用戶系統&8] &4警告 &c你應該使用「%valid」而並非「%invalid」登入遊戲。'
quick_command: '&8[&6用戶系統&8] &4警告 &c你使用指令的速度太快了請重新登入並稍等一會才再次使用指令。'
# Email
email:
@ -92,17 +92,17 @@ email:
old_email_invalid: '&8[&6用戶系統&8] &c你所填寫的舊電郵地址並不正確。'
invalid: '&8[&6用戶系統&8] &c你所填寫的電郵地址並不正確。'
added: '&8[&6用戶系統&8] &a已新增你的電郵地址。'
# TODO add_not_allowed: '&cAdding email was not allowed'
add_not_allowed: '&8[&6用戶系統&8] &c你不能新增電郵地址到你的帳戶。'
request_confirmation: '&8[&6用戶系統&8] &5請重覆輸入你的電郵地址。'
changed: '&8[&6用戶系統&8] &a你的電郵地址已更改。'
# TODO change_not_allowed: '&cChanging email was not allowed'
email_show: '&8[&6用戶系統&8] &2你所使用的電郵地址為&f%email'
change_not_allowed: '&8[&6用戶系統&8] &c你不能更改你的電郵地址。'
email_show: '&8[&6用戶系統&8] &2你所使用的電郵地址為 &f%email'
no_email_for_account: '&8[&6用戶系統&8] &2你並未有綁定電郵地址到此帳戶。'
already_used: '&8[&6用戶系統&8] &4這個電郵地址已被使用。'
incomplete_settings: '&8[&6用戶系統&8] &c電郵系統錯誤請聯絡伺服器管理員。 &7(err: mailconfig_incomplete)'
send_failure: '&8[&6用戶系統&8] &c電郵系統錯誤請聯絡伺服器管理員。 &7(err: smtperr)'
change_password_expired: '&8[&6用戶系統&8] 此指令已過期,請重新辦理。'
email_cooldown_error: '&8[&6用戶系統&8] &c你已經辦理過重寄郵件,請等待 %time 後再嘗試吧。'
change_password_expired: '&8[&6用戶系統&8] &c此指令已過期,請重新辦理。'
email_cooldown_error: '&8[&6用戶系統&8] &c你最近已經辦理過重寄郵件,請等待 %time 後再嘗試吧。'
# Password recovery by email
recovery:
@ -112,27 +112,40 @@ recovery:
code:
code_sent: '&8[&6用戶系統&8] &b帳戶驗證碼已發送到你的郵箱請查收。'
incorrect: '&8[&6用戶系統&8] &c帳戶驗證碼無效。 &7(你尚餘 %count 次嘗試機會)'
tries_exceeded: '&8[&6用戶系統&8] &c此驗證碼已因多次嘗試後失效請使用《 /email recovery <電郵地址> 》重新辦理。'
tries_exceeded: '&8[&6用戶系統&8] &c此驗證碼已因多次嘗試後失效請使用《 &f/email recovery <電郵地址>&c 》重新辦理。'
correct: '&8[&6用戶系統&8] &a帳戶驗證碼輸入正確。'
change_password: '&8[&6用戶系統&8] 請立即使用《 /email setpassword <新密碼> 》指令,以重設你的帳戶密碼。'
change_password: '&8[&6用戶系統&8] &c請立即使用《 &f/email setpassword <新密碼>&c 》指令,以重設你的帳戶密碼。'
# Captcha
captcha:
usage_captcha: '&8[&6用戶系統&8] &f用法《 /captcha %captcha_code 》'
wrong_captcha: '&8[&6用戶系統&8] &c你所輸入的驗證碼無效請使用 《 /captcha %captcha_code 》 再次輸入。'
wrong_captcha: '&8[&6用戶系統&8] &c你所輸入的驗證碼無效請使用 《 &f/captcha %captcha_code&c 》 再次輸入。'
valid_captcha: '&8[&6用戶系統&8] &c你所輸入的驗證碼無效 '
# TODO captcha_for_registration: 'To register you have to solve a captcha first, please use the command: /captcha %captcha_code'
# TODO register_captcha_valid: '&2Valid captcha! You may now register with /register'
captcha_for_registration: '&8[&6用戶系統&8] &2要完成玩家註冊程序請先執行驗証指令《 &f/captcha %captcha_code&2 》'
register_captcha_valid: '&8[&6用戶系統&8] &2驗證成功 !你現在可以使用指令《 &f/register&2 》進行註冊了~'
# Verification code
verification:
# TODO code_required: '&3This command is sensitive and requires an email verification! Check your inbox and follow the email''s instructions.'
# TODO command_usage: '&cUsage: /verification <code>'
# TODO incorrect_code: '&cIncorrect code, please type "/verification <code>" into the chat, using the code you received by email'
# TODO success: '&2Your identity has been verified! You can now execute all commands within the current session!'
# TODO already_verified: '&2You can already execute every sensitive command within the current session!'
# TODO code_expired: '&3Your code has expired! Execute another sensitive command to get a new code!'
# TODO email_needed: '&3To verify your identity you need to link an email address with your account!!'
code_required: '&8[&6用戶系統&8] &e這個高級魔法指令需要再一次進行電郵驗證方可使用請查收電郵並按信件內容進行驗證。'
command_usage: '&8[&6用戶系統&8] &f用法《 /verification <驗證碼> 》'
incorrect_code: '&8[&6用戶系統&8] &c錯誤的驗證碼請使用指令《 &f/verification <驗證碼>&c 》再次嘗試驗證。'
success: '&8[&6用戶系統&8] &2身份驗證成功 !你現在可以在目前的登入階段執行所有等級的指令了 '
already_verified: '&8[&6用戶系統&8] &2你已經爲目前的登入階段成功通過電郵身份驗證了毋須再次驗證。'
code_expired: '&8[&6用戶系統&8] &c你的驗證碼已經過期請執行另一個高等魔法指令以觸發新的身份驗證挑戰。'
email_needed: '&8[&6用戶系統&8] &c嗯... 你的帳戶沒有已經連結的電郵地址,不能使用電郵驗證功能。'
# Two-factor authentication
two_factor:
code_created: '&8[&6用戶系統&8] &b你的登入金鑰為&9 %c%code&9 &b掃描連結為%nl%&c %url'
confirmation_required: '&8[&6用戶系統&8] &b請使用指令《 &f/2fa confirm <驗證碼>&b 》以確認你的身份。'
code_required: '&8[&6用戶系統&8] &b請使用指令《 &f/2fa code <驗證碼>&b 》以驗證你的帳戶。'
already_enabled: '&8[&6用戶系統&8] &2嗯...這個帳戶已經啓用了兩步驗證功能,毋須再次啓用。'
enable_error_no_code: '&8[&6用戶系統&8] &c無效的登入金鑰 &f你可以使用指令《 /2fa add 》再次嘗試啓用此功能。'
enable_success: '&8[&6用戶系統&8] &2你已成功啓用兩步驗證功能 '
enable_error_wrong_code: '&8[&6用戶系統&8] &c無效的兩步驗證碼 &f你可以使用指令《 /2fa add 》再次嘗試啓用此功能。'
not_enabled_error: '&8[&6用戶系統&8] &c你的帳戶尚未啓用兩步驗證功能 &f你可以使用指令《 /2fa add 》以啓用此功能。'
removed_success: '&8[&6用戶系統&8] &2你已成功關閉兩步驗證功能&c為保障帳戶安全請儘快於可行的情況下重新啟用本功能。'
invalid_code: '&8[&6用戶系統&8] &c無效的兩步驗證碼 '
# Time units
time:
@ -144,16 +157,3 @@ time:
hours: '小時'
day: '日'
days: '日'
# Two-factor authentication
two_factor:
code_created: '&8[&6用戶系統 - 兩步驗證碼&8] &b你的登入金鑰為&9「%c%code&9」&b掃描連結為&c %url'
# TODO confirmation_required: 'Please confirm your code with /2fa confirm <code>'
# TODO code_required: 'Please submit your two-factor authentication code with /2fa code <code>'
# TODO already_enabled: 'Two-factor authentication is already enabled for your account!'
# TODO enable_error_no_code: 'No 2fa key has been generated for you or it has expired. Please run /2fa add'
# TODO enable_success: 'Successfully enabled two-factor authentication for your account'
# TODO enable_error_wrong_code: 'Wrong code or code has expired. Please run /2fa add'
# TODO not_enabled_error: 'Two-factor authentication is not enabled for your account. Run /2fa add'
# TODO removed_success: 'Successfully removed two-factor auth from your account'
# TODO invalid_code: 'Invalid code!'

View File

@ -1,9 +1,9 @@
name: ${bukkitplugin.name}
authors: [${bukkitplugin.authors}]
name: ${pluginDescription.name}
authors: [${pluginDescription.authors}]
website: ${project.url}
description: ${project.description}
main: ${bukkitplugin.main}
version: ${bukkitplugin.version}
main: ${pluginDescription.main}
version: ${pluginDescription.version}
api-version: 1.13
softdepend:
- Vault
@ -170,7 +170,7 @@ permissions:
default: op
authme.bypassbungeesend:
description: Permission node to bypass BungeeCord server teleportation.
default: op
default: false
authme.bypassantibot:
description: Permission node to bypass AntiBot protection.
default: op

View File

@ -1,367 +0,0 @@
package fr.xephi.authme.api;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ReflectionTestUtils;
import fr.xephi.authme.data.auth.PlayerAuth;
import fr.xephi.authme.data.auth.PlayerCache;
import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.process.Management;
import fr.xephi.authme.process.register.executors.ApiPasswordRegisterParams;
import fr.xephi.authme.process.register.executors.RegistrationMethod;
import fr.xephi.authme.security.PasswordSecurity;
import fr.xephi.authme.security.crypts.HashedPassword;
import fr.xephi.authme.service.ValidationService;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import static fr.xephi.authme.IsEqualByReflectionMatcher.hasEqualValuesOnAllFields;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.nullValue;
import static org.hamcrest.Matchers.sameInstance;
import static org.junit.Assert.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.only;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.hamcrest.MockitoHamcrest.argThat;
/**
* Test for {@link fr.xephi.authme.api.NewAPI}.
*/
@RunWith(MockitoJUnitRunner.class)
public class NewAPITest {
@InjectMocks
private NewAPI api;
@Mock
private ValidationService validationService;
@Mock
private DataSource dataSource;
@Mock
private Management management;
@Mock
private PasswordSecurity passwordSecurity;
@Mock
private PlayerCache playerCache;
@Mock
private AuthMe authMe;
@Test
public void shouldReturnInstanceOrNull() {
NewAPI result = NewAPI.getInstance();
assertThat(result, sameInstance(api));
ReflectionTestUtils.setField(NewAPI.class, null, "singleton", null);
assertThat(NewAPI.getInstance(), nullValue());
}
@Test
public void shouldReturnIfPlayerIsAuthenticated() {
// given
String name = "Bobby";
Player player = mockPlayerWithName(name);
given(playerCache.isAuthenticated(name)).willReturn(true);
// when
boolean result = api.isAuthenticated(player);
// then
verify(playerCache).isAuthenticated(name);
assertThat(result, equalTo(true));
}
@Test
public void shouldReturnIfPlayerIsNpc() {
// given
Player player = mock(Player.class);
given(player.hasMetadata("NPC")).willReturn(true);
// when
boolean result = api.isNPC(player);
// then
assertThat(result, equalTo(true));
verify(player).hasMetadata("NPC");
}
@Test
public void shouldReturnIfPlayerIsUnrestricted() {
// given
String name = "Tester";
Player player = mockPlayerWithName(name);
given(validationService.isUnrestricted(name)).willReturn(true);
// when
boolean result = api.isUnrestricted(player);
// then
verify(validationService).isUnrestricted(name);
assertThat(result, equalTo(true));
}
@Test
public void shouldGetLastLocation() {
// given
String name = "Gary";
Player player = mockPlayerWithName(name);
PlayerAuth auth = PlayerAuth.builder().name(name)
.locWorld("world")
.locX(12.4)
.locY(24.6)
.locZ(-438.2)
.locYaw(3.41f)
.locPitch(0.29f)
.build();
given(playerCache.getAuth(name)).willReturn(auth);
Server server = mock(Server.class);
ReflectionTestUtils.setField(Bukkit.class, null, "server", server);
World world = mock(World.class);
given(server.getWorld(auth.getWorld())).willReturn(world);
// when
Location result = api.getLastLocation(player);
// then
assertThat(result, not(nullValue()));
assertThat(result.getX(), equalTo(auth.getQuitLocX()));
assertThat(result.getY(), equalTo(auth.getQuitLocY()));
assertThat(result.getZ(), equalTo(auth.getQuitLocZ()));
assertThat(result.getWorld(), equalTo(world));
}
@Test
public void shouldReturnNullForUnavailablePlayer() {
// given
String name = "Numan";
Player player = mockPlayerWithName(name);
given(playerCache.getAuth(name)).willReturn(null);
// when
Location result = api.getLastLocation(player);
// then
assertThat(result, nullValue());
}
@Test
public void shouldCheckForRegisteredName() {
// given
String name = "toaster";
given(dataSource.isAuthAvailable(name)).willReturn(true);
// when
boolean result = api.isRegistered(name);
// then
assertThat(result, equalTo(true));
}
@Test
public void shouldCheckPassword() {
// given
String playerName = "Robert";
String password = "someSecretPhrase2983";
given(passwordSecurity.comparePassword(password, playerName)).willReturn(true);
// when
boolean result = api.checkPassword(playerName, password);
// then
verify(passwordSecurity).comparePassword(password, playerName);
assertThat(result, equalTo(true));
}
@Test
public void shouldReturnAuthNames() {
// given
String[] names = {"bobby", "peter", "elisabeth", "craig"};
List<PlayerAuth> auths = Arrays.stream(names)
.map(name -> PlayerAuth.builder().name(name).build())
.collect(Collectors.toList());
given(dataSource.getAllAuths()).willReturn(auths);
// when
List<String> result = api.getRegisteredNames();
// then
assertThat(result, contains(names));
}
@Test
public void shouldReturnAuthRealNames() {
// given
String[] names = {"Bobby", "peter", "Elisabeth", "CRAIG"};
List<PlayerAuth> auths = Arrays.stream(names)
.map(name -> PlayerAuth.builder().name(name).realName(name).build())
.collect(Collectors.toList());
given(dataSource.getAllAuths()).willReturn(auths);
// when
List<String> result = api.getRegisteredRealNames();
// then
assertThat(result, contains(names));
}
@Test
public void shouldUnregisterPlayer() {
// given
Player player = mock(Player.class);
String name = "Donald";
given(player.getName()).willReturn(name);
// when
api.forceUnregister(player);
// then
verify(management).performUnregisterByAdmin(null, name, player);
}
@Test
public void shouldUnregisterPlayerByName() {
// given
Server server = mock(Server.class);
ReflectionTestUtils.setField(Bukkit.class, null, "server", server);
String name = "tristan";
Player player = mock(Player.class);
given(server.getPlayer(name)).willReturn(player);
// when
api.forceUnregister(name);
// then
verify(management).performUnregisterByAdmin(null, name, player);
}
@Test
public void shouldReturnAuthMeInstance() {
// given / when
AuthMe result = api.getPlugin();
// then
assertThat(result, equalTo(authMe));
}
@Test
public void shouldReturnVersion() {
// given / when
String result = api.getPluginVersion();
// then
assertThat(result, equalTo(AuthMe.getPluginVersion()));
}
@Test
public void shouldForceLogin() {
// given
Player player = mock(Player.class);
// when
api.forceLogin(player);
// then
verify(management).forceLogin(player);
}
@Test
public void shouldForceLogout() {
// given
Player player = mock(Player.class);
// when
api.forceLogout(player);
// then
verify(management).performLogout(player);
}
@Test
public void shouldForceRegister() {
// given
Player player = mock(Player.class);
String pass = "test235";
// when
api.forceRegister(player, pass);
// then
verify(management).performRegister(eq(RegistrationMethod.API_REGISTRATION),
argThat(hasEqualValuesOnAllFields(ApiPasswordRegisterParams.of(player, pass, true))));
}
@Test
public void shouldForceRegisterAndNotAutoLogin() {
// given
Player player = mock(Player.class);
String pass = "test235";
// when
api.forceRegister(player, pass, false);
// then
verify(management).performRegister(eq(RegistrationMethod.API_REGISTRATION),
argThat(hasEqualValuesOnAllFields(ApiPasswordRegisterParams.of(player, pass, false))));
}
@Test
public void shouldRegisterPlayer() {
// given
String name = "Marco";
String password = "myP4ss";
HashedPassword hashedPassword = new HashedPassword("0395872SLKDFJOWEIUTEJSD");
given(passwordSecurity.computeHash(password, name.toLowerCase())).willReturn(hashedPassword);
given(dataSource.saveAuth(any(PlayerAuth.class))).willReturn(true);
// when
boolean result = api.registerPlayer(name, password);
// then
assertThat(result, equalTo(true));
verify(passwordSecurity).computeHash(password, name.toLowerCase());
ArgumentCaptor<PlayerAuth> authCaptor = ArgumentCaptor.forClass(PlayerAuth.class);
verify(dataSource).saveAuth(authCaptor.capture());
assertThat(authCaptor.getValue().getNickname(), equalTo(name.toLowerCase()));
assertThat(authCaptor.getValue().getRealName(), equalTo(name));
assertThat(authCaptor.getValue().getPassword(), equalTo(hashedPassword));
}
@Test
public void shouldNotRegisterAlreadyRegisteredPlayer() {
// given
String name = "jonah";
given(dataSource.isAuthAvailable(name)).willReturn(true);
// when
boolean result = api.registerPlayer(name, "pass");
// then
assertThat(result, equalTo(false));
verify(dataSource, only()).isAuthAvailable(name);
verifyZeroInteractions(management, passwordSecurity);
}
private static Player mockPlayerWithName(String name) {
Player player = mock(Player.class);
given(player.getName()).willReturn(name);
return player;
}
}

View File

@ -452,7 +452,7 @@ public abstract class AbstractDataSourceIntegrationTest {
DataSource dataSource = getDataSource();
// when
dataSource.grantSession("bobby");
dataSource.grantSession("Bobby");
dataSource.grantSession("doesNotExist");
// then

View File

@ -1,100 +0,0 @@
package fr.xephi.authme.datasource;
import com.google.common.io.Files;
import fr.xephi.authme.TestHelper;
import fr.xephi.authme.data.auth.PlayerAuth;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import static fr.xephi.authme.AuthMeMatchers.equalToHash;
import static fr.xephi.authme.AuthMeMatchers.hasAuthBasicData;
import static fr.xephi.authme.AuthMeMatchers.hasAuthLocation;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.hasSize;
import static org.junit.Assert.assertThat;
/**
* Integration test for the deprecated {@link FlatFile} datasource. The flatfile datasource is no longer used.
* Essentially, the only time we use it is in {@link fr.xephi.authme.datasource.converter.ForceFlatToSqlite},
* which requires {@link FlatFile#getAllAuths()}.
*/
public class FlatFileIntegrationTest {
@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
private DataSource dataSource;
@Before
public void copyFileToTemporaryFolder() throws IOException {
File originalFile = TestHelper.getJarFile(TestHelper.PROJECT_ROOT + "datasource/flatfile-test.txt");
File copy = temporaryFolder.newFile();
Files.copy(originalFile, copy);
dataSource = new FlatFile(copy);
}
@Test
public void shouldReturnIfAuthIsAvailableOrNot() {
// given / when
boolean isBobbyAvailable = dataSource.isAuthAvailable("bobby");
boolean isChrisAvailable = dataSource.isAuthAvailable("chris");
boolean isUserAvailable = dataSource.isAuthAvailable("USER");
// then
assertThat(isBobbyAvailable, equalTo(true));
assertThat(isChrisAvailable, equalTo(false));
assertThat(isUserAvailable, equalTo(true));
}
@Test
public void shouldReturnAllAuths() {
// given / when
List<PlayerAuth> authList = dataSource.getAllAuths();
// then
assertThat(authList, hasSize(7));
assertThat(getName("bobby", authList), hasAuthBasicData("bobby", "bobby", null, "123.45.67.89"));
assertThat(getName("bobby", authList), hasAuthLocation(1.05, 2.1, 4.2, "world", 0, 0));
assertThat(getName("bobby", authList).getPassword(), equalToHash("$SHA$11aa0706173d7272$dbba966"));
assertThat(getName("twofields", authList), hasAuthBasicData("twofields", "twofields", null, null));
assertThat(getName("twofields", authList).getPassword(), equalToHash("hash1234"));
assertThat(getName("threefields", authList), hasAuthBasicData("threefields", "threefields", null, "33.33.33.33"));
assertThat(getName("fourfields", authList), hasAuthBasicData("fourfields", "fourfields", null, "4.4.4.4"));
assertThat(getName("fourfields", authList).getLastLogin(), equalTo(404040404L));
assertThat(getName("sevenfields", authList), hasAuthLocation(7.7, 14.14, 21.21, "world", 0, 0));
assertThat(getName("eightfields", authList), hasAuthLocation(8.8, 17.6, 26.4, "eightworld", 0, 0));
assertThat(getName("eightfields", authList).getLastLogin(), equalTo(1234567888L));
assertThat(getName("eightfields", authList).getPassword(), equalToHash("hash8168"));
}
@Test
public void shouldAddAuth() {
// given / when
boolean response = dataSource.saveAuth(
PlayerAuth.builder().name("Test").email("user@EXAMPLE.org").lastIp("123.45.67.77").build());
List<PlayerAuth> authList = dataSource.getAllAuths();
// then
assertThat(response, equalTo(true));
assertThat(authList, hasSize(8));
assertThat(authList, hasItem(hasAuthBasicData("test", "test", "user@EXAMPLE.org", "123.45.67.77")));
}
private static PlayerAuth getName(String name, Collection<PlayerAuth> auths) {
for (PlayerAuth auth : auths) {
if (name.equals(auth.getNickname())) {
return auth;
}
}
throw new IllegalStateException("Did not find auth with name '" + name + "'");
}
}

View File

@ -1,74 +0,0 @@
package fr.xephi.authme.datasource.converter;
import com.google.common.io.Files;
import fr.xephi.authme.TestHelper;
import fr.xephi.authme.data.auth.PlayerAuth;
import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.datasource.DataSourceType;
import fr.xephi.authme.datasource.FlatFile;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.mockito.ArgumentCaptor;
import java.io.File;
import java.io.IOException;
import java.util.List;
import static fr.xephi.authme.AuthMeMatchers.hasAuthBasicData;
import static fr.xephi.authme.AuthMeMatchers.hasAuthLocation;
import static org.hamcrest.Matchers.hasItem;
import static org.junit.Assert.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
/**
* Test for {@link ForceFlatToSqlite}.
*/
public class ForceFlatToSqliteTest {
@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
private FlatFile flatFile;
@BeforeClass
public static void setup() {
TestHelper.setupLogger();
}
@Before
public void copyFile() throws IOException {
File source = TestHelper.getJarFile(TestHelper.PROJECT_ROOT + "datasource/flatfile-test.txt");
File destination = temporaryFolder.newFile();
Files.copy(source, destination);
flatFile = new FlatFile(destination);
}
@Test
public void shouldConvertToSqlite() {
// given
DataSource dataSource = mock(DataSource.class);
given(dataSource.getType()).willReturn(DataSourceType.MYSQL);
ForceFlatToSqlite converter = new ForceFlatToSqlite(flatFile, dataSource);
// when
converter.execute(null);
// then
ArgumentCaptor<PlayerAuth> authCaptor = ArgumentCaptor.forClass(PlayerAuth.class);
verify(dataSource, times(7)).saveAuth(authCaptor.capture());
List<PlayerAuth> auths = authCaptor.getAllValues();
assertThat(auths, hasItem(hasAuthBasicData("bobby", "Player", null, "123.45.67.89")));
assertThat(auths, hasItem(hasAuthLocation(1.05, 2.1, 4.2, "world", 0, 0)));
assertThat(auths, hasItem(hasAuthBasicData("user", "Player", "user@example.org", "34.56.78.90")));
assertThat(auths, hasItem(hasAuthLocation(124.1, 76.3, -127.8, "nether", 0, 0)));
assertThat(auths, hasItem(hasAuthBasicData("eightfields", "Player", null, "6.6.6.66")));
assertThat(auths, hasItem(hasAuthLocation(8.8, 17.6, 26.4, "eightworld", 0, 0)));
}
}

View File

@ -55,7 +55,7 @@ public class TaskCloserTest {
Server server = mock(Server.class);
given(server.getScheduler()).willReturn(bukkitScheduler);
ReflectionTestUtils.setField(JavaPlugin.class, authMe, "server", server);
ReflectionTestUtils.setField(JavaPlugin.class, authMe, "logger", logger);
given(authMe.getLogger()).willReturn(logger);
taskCloser = spy(new TaskCloser(authMe, dataSource));
}

View File

@ -1,30 +0,0 @@
package fr.xephi.authme.listener;
import org.bukkit.event.player.PlayerEditBookEvent;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import static fr.xephi.authme.listener.EventCancelVerifier.withServiceMock;
/**
* Test for {@link PlayerListener16}.
*/
@RunWith(MockitoJUnitRunner.class)
public class PlayerListener16Test {
@InjectMocks
private PlayerListener16 listener;
@Mock
private ListenerService listenerService;
@Test
public void shouldCancelEvent() {
withServiceMock(listenerService)
.check(listener::onPlayerEditBook, PlayerEditBookEvent.class);
}
}

View File

@ -1,30 +0,0 @@
package fr.xephi.authme.listener;
import org.bukkit.event.player.PlayerInteractAtEntityEvent;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import static fr.xephi.authme.listener.EventCancelVerifier.withServiceMock;
/**
* Test for {@link PlayerListener18}.
*/
@RunWith(MockitoJUnitRunner.class)
public class PlayerListener18Test {
@InjectMocks
private PlayerListener18 listener;
@Mock
private ListenerService listenerService;
@Test
public void shouldCancelEvent() {
withServiceMock(listenerService)
.check(listener::onPlayerInteractAtEntity, PlayerInteractAtEntityEvent.class);
}
}

View File

@ -28,21 +28,7 @@ import org.bukkit.event.block.SignChangeEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryOpenEvent;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.event.player.PlayerBedEnterEvent;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.event.player.PlayerFishEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerItemConsumeEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerKickEvent;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerPickupItemEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerShearEntityEvent;
import org.bukkit.event.player.*;
import org.bukkit.inventory.InventoryView;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -890,6 +876,18 @@ public class PlayerListenerTest {
verify(joinMessageService).putMessage("thename0", "thename0 is joining us");
}
@Test
public void shouldCancelPlayerEditBookEvent() {
withServiceMock(listenerService)
.check(listener::onPlayerEditBook, PlayerEditBookEvent.class);
}
@Test
public void shouldCancelPlayerInteractAtEntityEvent() {
withServiceMock(listenerService)
.check(listener::onPlayerInteractAtEntity, PlayerInteractAtEntityEvent.class);
}
private static Player mockPlayerWithName(String name) {
Player player = mock(Player.class);
given(player.getName()).willReturn(name);

View File

@ -38,6 +38,7 @@ import static fr.xephi.authme.permission.PermissionsSystemType.LUCK_PERMS;
import static fr.xephi.authme.permission.PermissionsSystemType.PERMISSIONS_EX;
import static fr.xephi.authme.permission.PermissionsSystemType.VAULT;
import static fr.xephi.authme.permission.PermissionsSystemType.Z_PERMISSIONS;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertThat;
@ -89,6 +90,7 @@ public class PermissionsManagerInitializationTest {
// then
PermissionHandler handler = getHandlerFieldValue();
assertThat(handler, instanceOf(expectedHandlerType));
assertThat(handler.getPermissionSystem(), equalTo(permissionsSystemType));
}
@Test

View File

@ -0,0 +1,80 @@
package fr.xephi.authme.permission.handlers;
import net.milkbowl.vault.permission.Permission;
import org.bukkit.Server;
import org.bukkit.entity.Player;
import org.junit.Test;
import java.util.List;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.empty;
import static org.junit.Assert.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
/**
* Test for {@link VaultHandler}.
*/
public class VaultHandlerTest {
private VaultHandlerTestImpl vaultHandlerTest = VaultHandlerTestImpl.create();
@Test
public void shouldReturnGroups() {
// given
Permission permissionMock = vaultHandlerTest.permissionMock;
Player player = mock(Player.class);
given(permissionMock.getPlayerGroups(null, player)).willReturn(new String[]{"abc", "test"});
// when
List<String> result = vaultHandlerTest.getGroups(player);
// then
assertThat(result, contains("abc", "test"));
verify(permissionMock).getPlayerGroups(null, player);
}
/**
* Bug #1702: VaultHandler may return null for groups list.
*/
@Test
public void shouldHandleNullAsGroups() {
// given
Permission permissionMock = vaultHandlerTest.permissionMock;
Player player = mock(Player.class);
given(permissionMock.getPlayerGroups(null, player)).willReturn(null);
// when
List<String> result = vaultHandlerTest.getGroups(player);
// then
assertThat(result, empty());
verify(permissionMock).getPlayerGroups(null, player);
}
/** Test implementation using a mock Vault Permission instance. */
private static final class VaultHandlerTestImpl extends VaultHandler {
private Permission permissionMock;
VaultHandlerTestImpl() throws PermissionHandlerException {
super(null);
}
static VaultHandlerTestImpl create() {
try {
return new VaultHandlerTestImpl();
} catch (PermissionHandlerException e) {
throw new IllegalStateException(e);
}
}
@Override
Permission getVaultPermission(Server server) {
permissionMock = mock(Permission.class);
return permissionMock;
}
}
}

View File

@ -21,10 +21,7 @@ import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.Collection;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasSize;
import static org.junit.Assert.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;
@ -62,34 +59,6 @@ public class BukkitServiceTest {
bukkitService = new BukkitService(authMe, settings);
}
/**
* Checks that {@link BukkitService#getOnlinePlayersIsCollection} is initialized to {@code true} on startup;
* the test scope is configured with a Bukkit implementation that returns a Collection and not an array.
*/
@Test
public void shouldHavePlayerListAsCollectionMethod() {
// given / when
boolean doesMethodReturnCollection = ReflectionTestUtils
.getFieldValue(BukkitService.class, bukkitService, "getOnlinePlayersIsCollection");
// then
assertThat(doesMethodReturnCollection, equalTo(true));
}
@Test
public void shouldRetrieveListOfOnlinePlayersFromReflectedMethod() {
// given
ReflectionTestUtils.setField(BukkitService.class, bukkitService, "getOnlinePlayersIsCollection", false);
ReflectionTestUtils.setField(BukkitService.class, bukkitService, "getOnlinePlayers",
ReflectionTestUtils.getMethod(BukkitServiceTest.class, "onlinePlayersImpl"));
// when
Collection<? extends Player> players = bukkitService.getOnlinePlayers();
// then
assertThat(players, hasSize(2));
}
@Test
public void shouldDispatchCommand() {
// given

View File

@ -9,6 +9,7 @@ import fr.xephi.authme.initialization.DataFolder;
import fr.xephi.authme.service.BukkitService;
import fr.xephi.authme.service.CommonService;
import fr.xephi.authme.service.GeoIpService;
import fr.xephi.authme.settings.properties.RegistrationSettings;
import org.bukkit.Server;
import org.bukkit.World;
import org.bukkit.entity.Player;
@ -66,6 +67,7 @@ public class WelcomeMessageConfigurationTest {
testPluginFolder = temporaryFolder.newFolder();
welcomeFile = new File(testPluginFolder, "welcome.txt");
welcomeFile.createNewFile();
given(service.getProperty(RegistrationSettings.USE_WELCOME_MESSAGE)).willReturn(true);
}
@Test

View File

@ -36,35 +36,6 @@ public class PlayerUtilsTest {
assertThat(result, equalTo(ip));
}
@Test
public void shouldGetUuid() {
// given
UUID uuid = UUID.randomUUID();
Player player = mock(Player.class);
given(player.getUniqueId()).willReturn(uuid);
// when
String result = PlayerUtils.getUuidOrName(player);
// then
assertThat(result, equalTo(uuid.toString()));
}
@Test
public void shouldFallbackToName() {
// given
Player player = mock(Player.class);
doThrow(NoSuchMethodError.class).when(player).getUniqueId();
String name = "Bobby12";
given(player.getName()).willReturn(name);
// when
String result = PlayerUtils.getUuidOrName(player);
// then
assertThat(result, equalTo(name));
}
@Test
public void shouldHaveHiddenConstructor() {
// given / when / then

View File

@ -10,10 +10,9 @@ import tools.utils.ToolsConstants;
import java.util.Arrays;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import static com.google.common.base.MoreObjects.firstNonNull;
/**
* Generates the translations page in docs.
*/
@ -47,7 +46,7 @@ public class TranslationPageGenerator implements AutoToolTask {
for (TranslationInfo translation : gatherer.getTranslationInfo()) {
int percentage = (int) Math.round(translation.getPercentTranslated() * 100);
String name = firstNonNull(LANGUAGE_NAMES.get(translation.getCode()), "?");
String name = Optional.ofNullable(LANGUAGE_NAMES.get(translation.getCode())).orElse("?");
TagValueHolder valueHolder = TagValueHolder.create()
.put("code", translation.getCode())
.put("name", name)