mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2024-08-21 20:22:45 +02:00
[Merge] Version 4.5.1 (#780)
This commit is contained in:
commit
b1da4ba18b
|
@ -3,7 +3,7 @@
|
|||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.djrapitops</groupId>
|
||||
<artifactId>Plan</artifactId>
|
||||
<version>4.5.0-SNAPSHOT</version>
|
||||
<version>4.5.0-SNAPSHOT</version>
|
||||
<build>
|
||||
<sourceDirectory>${basedir}/src/main/java</sourceDirectory>
|
||||
<testSourceDirectory>${basedir}/src/test/java</testSourceDirectory>
|
||||
|
@ -20,7 +20,7 @@
|
|||
<include>**/*.js</include>
|
||||
<include>**/*.css</include>
|
||||
<include>locale/*.txt</include>
|
||||
<include>**/*.ico</include>
|
||||
<include>**/*.ico</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</resources>
|
||||
|
@ -32,28 +32,28 @@
|
|||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>com.google.dagger</groupId>
|
||||
<artifactId>dagger-compiler</artifactId>
|
||||
<version>2.17</version>
|
||||
</path>
|
||||
<path>
|
||||
<groupId>com.velocitypowered</groupId>
|
||||
<artifactId>velocity-api</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</path>
|
||||
<path>
|
||||
<groupId>org.spongepowered</groupId>
|
||||
<artifactId>spongeapi</artifactId>
|
||||
<version>7.1.0</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>com.google.dagger</groupId>
|
||||
<artifactId>dagger-compiler</artifactId>
|
||||
<version>2.17</version>
|
||||
</path>
|
||||
<path>
|
||||
<groupId>com.velocitypowered</groupId>
|
||||
<artifactId>velocity-api</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</path>
|
||||
<path>
|
||||
<groupId>org.spongepowered</groupId>
|
||||
<artifactId>spongeapi</artifactId>
|
||||
<version>7.1.0</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.1.1</version>
|
||||
<version>3.2.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
|
@ -76,7 +76,6 @@
|
|||
<exclude>org.mockito:*</exclude>
|
||||
<exclude>org.easymock:*</exclude>
|
||||
<exclude>junit:*</exclude>
|
||||
<exclued>org.slf4j:*</exclued>
|
||||
</excludes>
|
||||
</artifactSet>
|
||||
<relocations>
|
||||
|
@ -99,6 +98,14 @@
|
|||
<pattern>com.zaxxer</pattern>
|
||||
<shadedPattern>plan.com.zaxxer</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.h2</pattern>
|
||||
<shadedPattern>plan.org.h2</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.slf4j</pattern>
|
||||
<shadedPattern>plan.org.slf4j</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.bstats</pattern>
|
||||
<shadedPattern>com.djrapitops.plan.utilities.metrics</shadedPattern>
|
||||
|
@ -162,13 +169,13 @@
|
|||
<url>https://repo.spongepowered.org/maven</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>velocity-repo</id>
|
||||
<url>https://repo.velocitypowered.com/snapshots/</url>
|
||||
<id>velocity-repo</id>
|
||||
<url>https://repo.velocitypowered.com/snapshots/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>md_5-snapshots</id>
|
||||
<url>http://repo.md-5.net/content/repositories/snapshots/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>md_5-snapshots</id>
|
||||
<url>http://repo.md-5.net/content/repositories/snapshots/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>bstats-repo</id>
|
||||
<url>http://repo.bstats.org/content/repositories/releases/</url>
|
||||
|
@ -312,109 +319,103 @@
|
|||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.velocitypowered</groupId>
|
||||
<artifactId>velocity-api</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>text</artifactId>
|
||||
<groupId>net.kyori</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>toml4j</artifactId>
|
||||
<groupId>com.moandjiezana.toml</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>guice</artifactId>
|
||||
<groupId>com.google.inject</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>checker-qual</artifactId>
|
||||
<groupId>org.checkerframework</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>gson</artifactId>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>guava</artifactId>
|
||||
<groupId>com.google.guava</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
<groupId>com.velocitypowered</groupId>
|
||||
<artifactId>velocity-api</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>text</artifactId>
|
||||
<groupId>net.kyori</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>toml4j</artifactId>
|
||||
<groupId>com.moandjiezana.toml</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>guice</artifactId>
|
||||
<groupId>com.google.inject</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>checker-qual</artifactId>
|
||||
<groupId>org.checkerframework</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>gson</artifactId>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>guava</artifactId>
|
||||
<groupId>com.google.guava</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<dependency>
|
||||
<groupId>org.spongepowered</groupId>
|
||||
<artifactId>spongeapi</artifactId>
|
||||
<version>7.1.0</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>error_prone_annotations</artifactId>
|
||||
<groupId>com.google.errorprone</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>guava</artifactId>
|
||||
<groupId>com.github.ben-manes.caffeine</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>plugin-meta</artifactId>
|
||||
<groupId>org.spongepowered</groupId>
|
||||
<artifactId>spongeapi</artifactId>
|
||||
<version>7.1.0</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>error_prone_annotations</artifactId>
|
||||
<groupId>com.google.errorprone</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>guava</artifactId>
|
||||
<groupId>com.github.ben-manes.caffeine</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>plugin-meta</artifactId>
|
||||
<groupId>org.spongepowered</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>configurate-hocon</artifactId>
|
||||
<groupId>org.spongepowered</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>configurate-gson</artifactId>
|
||||
<groupId>org.spongepowered</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>configurate-yaml</artifactId>
|
||||
<groupId>org.spongepowered</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>flow-math</artifactId>
|
||||
<groupId>com.flowpowered</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>flow-noise</artifactId>
|
||||
<groupId>com.flowpowered</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>jsr305</artifactId>
|
||||
<groupId>com.google.code.findbugs</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>guice</artifactId>
|
||||
<groupId>com.google.inject</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>asm</artifactId>
|
||||
<groupId>org.ow2.asm</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>gson</artifactId>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>guava</artifactId>
|
||||
<groupId>com.google.guava</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>configurate-hocon</artifactId>
|
||||
<groupId>org.spongepowered</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>configurate-gson</artifactId>
|
||||
<groupId>org.spongepowered</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>configurate-yaml</artifactId>
|
||||
<groupId>org.spongepowered</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>flow-math</artifactId>
|
||||
<groupId>com.flowpowered</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>flow-noise</artifactId>
|
||||
<groupId>com.flowpowered</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>jsr305</artifactId>
|
||||
<groupId>com.google.code.findbugs</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>guice</artifactId>
|
||||
<groupId>com.google.inject</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>asm</artifactId>
|
||||
<groupId>org.ow2.asm</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>gson</artifactId>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>guava</artifactId>
|
||||
<groupId>com.google.guava</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.imaginarycode.minecraft</groupId>
|
||||
<artifactId>RedisBungee</artifactId>
|
||||
<version>0.3.8-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-nop</artifactId>
|
||||
<version>1.7.25</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
|
|
14
Plan/pom.xml
14
Plan/pom.xml
|
@ -171,6 +171,13 @@
|
|||
<version>1.5.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- H2 -->
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<version>1.4.196</version> <!-- This version is necessary so Sponge will not crash -->
|
||||
</dependency>
|
||||
|
||||
<!-- Mockito (Test Dependency) -->
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
|
@ -179,6 +186,7 @@
|
|||
<type>jar</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- SQLite (Test Dependency) -->
|
||||
<dependency>
|
||||
<groupId>org.xerial</groupId>
|
||||
|
@ -256,7 +264,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.1.1</version>
|
||||
<version>3.2.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
|
@ -302,6 +310,10 @@
|
|||
<pattern>com.zaxxer</pattern>
|
||||
<shadedPattern>plan.com.zaxxer</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.h2</pattern>
|
||||
<shadedPattern>plan.org.h2</shadedPattern>
|
||||
</relocation>
|
||||
<!--<relocation>-->
|
||||
<!--<pattern>org.slf4j</pattern>-->
|
||||
<!--<shadedPattern>plan.org.slf4j</shadedPattern>-->
|
||||
|
|
|
@ -43,7 +43,7 @@ import java.io.InputStream;
|
|||
@Plugin(
|
||||
id = "plan",
|
||||
name = "Plan",
|
||||
version = "4.5.0",
|
||||
version = "4.5.1",
|
||||
description = "Player Analytics Plugin by Rsl1122",
|
||||
authors = {"Rsl1122"},
|
||||
dependencies = {
|
||||
|
|
|
@ -46,7 +46,7 @@ import java.nio.file.Path;
|
|||
@Plugin(
|
||||
id = "plan",
|
||||
name = "Plan",
|
||||
version = "4.5.0",
|
||||
version = "4.5.1",
|
||||
description = "Player Analytics Plugin by Rsl1122",
|
||||
authors = {"Rsl1122"}
|
||||
)
|
||||
|
|
|
@ -26,6 +26,6 @@ import com.djrapitops.plan.system.database.databases.Database;
|
|||
public class UnsupportedTransferDatabaseException extends WebException {
|
||||
|
||||
public UnsupportedTransferDatabaseException(Database db) {
|
||||
super(db.getName() + " does not support Transfer operations!");
|
||||
super(db.getType().getName() + " does not support Transfer operations!");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,7 +76,7 @@ public class InfoCommand extends CommandNode {
|
|||
"",
|
||||
locale.getString(CommandLang.INFO_VERSION, plugin.getVersion()),
|
||||
locale.getString(CommandLang.INFO_UPDATE, updateAvailable),
|
||||
locale.getString(CommandLang.INFO_DATABASE, dbSystem.getDatabase().getName()),
|
||||
locale.getString(CommandLang.INFO_DATABASE, dbSystem.getDatabase().getType().getName()),
|
||||
locale.getString(CommandLang.INFO_BUNGEE_CONNECTION, connectedToBungee),
|
||||
"",
|
||||
">"
|
||||
|
|
|
@ -19,6 +19,7 @@ package com.djrapitops.plan.command.commands.manage;
|
|||
import com.djrapitops.plan.api.exceptions.database.DBException;
|
||||
import com.djrapitops.plan.api.exceptions.database.DBInitException;
|
||||
import com.djrapitops.plan.system.database.DBSystem;
|
||||
import com.djrapitops.plan.system.database.databases.DBType;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plan.system.database.databases.sql.SQLiteDB;
|
||||
import com.djrapitops.plan.system.locale.Locale;
|
||||
|
@ -93,7 +94,7 @@ public class ManageBackupCommand extends CommandNode {
|
|||
|
||||
String dbName = args[0].toLowerCase();
|
||||
|
||||
boolean isCorrectDB = Verify.equalsOne(dbName, "sqlite", "mysql");
|
||||
boolean isCorrectDB = DBType.exists(dbName);
|
||||
Verify.isTrue(isCorrectDB,
|
||||
() -> new IllegalArgumentException(locale.getString(ManageLang.FAIL_INCORRECT_DB, dbName)));
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ package com.djrapitops.plan.command.commands.manage;
|
|||
import com.djrapitops.plan.api.exceptions.database.DBInitException;
|
||||
import com.djrapitops.plan.api.exceptions.database.DBOpException;
|
||||
import com.djrapitops.plan.system.database.DBSystem;
|
||||
import com.djrapitops.plan.system.database.databases.DBType;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plan.system.locale.Locale;
|
||||
import com.djrapitops.plan.system.locale.lang.CmdHelpLang;
|
||||
|
@ -78,7 +79,7 @@ public class ManageClearCommand extends CommandNode {
|
|||
|
||||
String dbName = args[0].toLowerCase();
|
||||
|
||||
boolean isCorrectDB = "sqlite".equals(dbName) || "mysql".equals(dbName);
|
||||
boolean isCorrectDB = DBType.exists(dbName);
|
||||
Verify.isTrue(isCorrectDB,
|
||||
() -> new IllegalArgumentException(locale.getString(ManageLang.FAIL_INCORRECT_DB, dbName)));
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ package com.djrapitops.plan.command.commands.manage;
|
|||
|
||||
import com.djrapitops.plan.PlanPlugin;
|
||||
import com.djrapitops.plan.system.database.DBSystem;
|
||||
import com.djrapitops.plan.system.database.databases.DBType;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plan.system.locale.Locale;
|
||||
import com.djrapitops.plan.system.locale.lang.CmdHelpLang;
|
||||
|
@ -73,11 +74,11 @@ public class ManageHotSwapCommand extends CommandNode {
|
|||
|
||||
String dbName = args[0].toLowerCase();
|
||||
|
||||
boolean isCorrectDB = Verify.equalsOne(dbName, "sqlite", "mysql");
|
||||
boolean isCorrectDB = DBType.exists(dbName);
|
||||
Verify.isTrue(isCorrectDB,
|
||||
() -> new IllegalArgumentException(locale.getString(ManageLang.FAIL_INCORRECT_DB, dbName)));
|
||||
|
||||
Verify.isFalse(dbName.equals(dbSystem.getDatabase().getConfigName()),
|
||||
Verify.isFalse(dbName.equals(dbSystem.getDatabase().getType().getConfigName()),
|
||||
() -> new IllegalArgumentException(locale.getString(ManageLang.FAIL_SAME_DB)));
|
||||
|
||||
try {
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package com.djrapitops.plan.command.commands.manage;
|
||||
|
||||
import com.djrapitops.plan.system.database.DBSystem;
|
||||
import com.djrapitops.plan.system.database.databases.DBType;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plan.system.locale.Locale;
|
||||
import com.djrapitops.plan.system.locale.lang.CmdHelpLang;
|
||||
|
@ -77,12 +78,12 @@ public class ManageMoveCommand extends CommandNode {
|
|||
() -> new IllegalArgumentException(locale.getString(CommandLang.FAIL_REQ_ARGS, 2, Arrays.toString(this.getArguments()))));
|
||||
|
||||
String fromDB = args[0].toLowerCase();
|
||||
boolean isCorrectDB = Verify.equalsOne(fromDB, "sqlite", "mysql");
|
||||
boolean isCorrectDB = DBType.exists(fromDB);
|
||||
Verify.isTrue(isCorrectDB,
|
||||
() -> new IllegalArgumentException(locale.getString(ManageLang.FAIL_INCORRECT_DB, fromDB)));
|
||||
|
||||
String toDB = args[1].toLowerCase();
|
||||
isCorrectDB = Verify.equalsOne(toDB, "sqlite", "mysql");
|
||||
isCorrectDB = DBType.exists(toDB);
|
||||
Verify.isTrue(isCorrectDB,
|
||||
() -> new IllegalArgumentException(locale.getString(ManageLang.FAIL_INCORRECT_DB, toDB)));
|
||||
|
||||
|
@ -115,9 +116,9 @@ public class ManageMoveCommand extends CommandNode {
|
|||
|
||||
sender.sendMessage(locale.getString(ManageLang.PROGRESS_SUCCESS));
|
||||
|
||||
boolean movingToCurrentDB = toDatabase.getConfigName().equalsIgnoreCase(dbSystem.getDatabase().getConfigName());
|
||||
boolean movingToCurrentDB = toDatabase.getType() == dbSystem.getDatabase().getType();
|
||||
if (movingToCurrentDB) {
|
||||
sender.sendMessage(locale.getString(ManageLang.HOTSWAP_REMINDER, toDatabase.getConfigName()));
|
||||
sender.sendMessage(locale.getString(ManageLang.HOTSWAP_REMINDER, toDatabase.getType().getConfigName()));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
errorHandler.log(L.ERROR, this.getClass(), e);
|
||||
|
|
|
@ -110,7 +110,7 @@ public class ManageRemoveCommand extends CommandNode {
|
|||
if (!Verify.contains("-a", args)) {
|
||||
sender.sendMessage(
|
||||
locale.getString(ManageLang.CONFIRMATION,
|
||||
locale.getString(ManageLang.CONFIRM_REMOVAL, db.getName())
|
||||
locale.getString(ManageLang.CONFIRM_REMOVAL, db.getType().getName())
|
||||
)
|
||||
);
|
||||
return;
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package com.djrapitops.plan.command.commands.manage;
|
||||
|
||||
import com.djrapitops.plan.system.database.DBSystem;
|
||||
import com.djrapitops.plan.system.database.databases.DBType;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plan.system.database.databases.sql.SQLiteDB;
|
||||
import com.djrapitops.plan.system.file.PlanFiles;
|
||||
|
@ -84,7 +85,7 @@ public class ManageRestoreCommand extends CommandNode {
|
|||
String backupDbName = args[0];
|
||||
|
||||
String dbName = args[1].toLowerCase();
|
||||
boolean isCorrectDB = Verify.equalsOne(dbName, "sqlite", "mysql");
|
||||
boolean isCorrectDB = DBType.exists(dbName);
|
||||
Verify.isTrue(isCorrectDB,
|
||||
() -> new IllegalArgumentException(locale.getString(ManageLang.FAIL_INCORRECT_DB, dbName)));
|
||||
|
||||
|
@ -96,7 +97,7 @@ public class ManageRestoreCommand extends CommandNode {
|
|||
database.init();
|
||||
|
||||
if (!Verify.contains("-a", args)) {
|
||||
sender.sendMessage(locale.getString(ManageLang.CONFIRMATION, locale.getString(ManageLang.CONFIRM_OVERWRITE, database.getName())));
|
||||
sender.sendMessage(locale.getString(ManageLang.CONFIRMATION, locale.getString(ManageLang.CONFIRM_OVERWRITE, database.getType().getName())));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -160,7 +160,7 @@ public class SessionsMutator {
|
|||
|
||||
public long toMedianSessionLength() {
|
||||
List<Long> sessionLengths = sessions.stream().map(Session::getLength).collect(Collectors.toList());
|
||||
return (long) Median.forLong(sessionLengths).calculate();
|
||||
return (long) Median.forList(sessionLengths).calculate();
|
||||
}
|
||||
|
||||
public int toAverageUniqueJoinsPerDay() {
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package com.djrapitops.plan.system.database;
|
||||
|
||||
import com.djrapitops.plan.api.exceptions.EnableException;
|
||||
import com.djrapitops.plan.system.database.databases.sql.H2DB;
|
||||
import com.djrapitops.plan.system.database.databases.sql.MySQLDB;
|
||||
import com.djrapitops.plan.system.database.databases.sql.SQLiteDB;
|
||||
import com.djrapitops.plan.system.locale.Locale;
|
||||
|
@ -44,15 +45,17 @@ public class BukkitDBSystem extends DBSystem {
|
|||
Locale locale,
|
||||
MySQLDB mySQLDB,
|
||||
SQLiteDB.Factory sqLiteDB,
|
||||
H2DB.Factory h2DB,
|
||||
PlanConfig config,
|
||||
PluginLogger logger,
|
||||
Timings timings,
|
||||
ErrorHandler errorHandler
|
||||
) {
|
||||
super(locale, sqLiteDB, logger, timings, errorHandler);
|
||||
super(locale, sqLiteDB, h2DB, logger, timings, errorHandler);
|
||||
this.config = config;
|
||||
|
||||
databases.add(mySQLDB);
|
||||
databases.add(h2DB.usingDefaultFile());
|
||||
databases.add(sqLiteDB.usingDefaultFile());
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ import com.djrapitops.plan.api.exceptions.database.DBException;
|
|||
import com.djrapitops.plan.api.exceptions.database.DBInitException;
|
||||
import com.djrapitops.plan.system.SubSystem;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plan.system.database.databases.sql.H2DB;
|
||||
import com.djrapitops.plan.system.database.databases.sql.SQLiteDB;
|
||||
import com.djrapitops.plan.system.locale.Locale;
|
||||
import com.djrapitops.plan.system.locale.lang.PluginLang;
|
||||
|
@ -44,6 +45,7 @@ public abstract class DBSystem implements SubSystem {
|
|||
|
||||
protected final Locale locale;
|
||||
private final SQLiteDB.Factory sqLiteFactory;
|
||||
private final H2DB.Factory h2Factory;
|
||||
protected final PluginLogger logger;
|
||||
protected final Timings timings;
|
||||
protected final ErrorHandler errorHandler;
|
||||
|
@ -54,12 +56,14 @@ public abstract class DBSystem implements SubSystem {
|
|||
public DBSystem(
|
||||
Locale locale,
|
||||
SQLiteDB.Factory sqLiteDB,
|
||||
H2DB.Factory h2Factory,
|
||||
PluginLogger logger,
|
||||
Timings timings,
|
||||
ErrorHandler errorHandler
|
||||
) {
|
||||
this.locale = locale;
|
||||
sqLiteFactory = sqLiteDB;
|
||||
this.sqLiteFactory = sqLiteDB;
|
||||
this.h2Factory = h2Factory;
|
||||
this.logger = logger;
|
||||
this.timings = timings;
|
||||
this.errorHandler = errorHandler;
|
||||
|
@ -68,7 +72,7 @@ public abstract class DBSystem implements SubSystem {
|
|||
|
||||
public Database getActiveDatabaseByName(String dbName) {
|
||||
for (Database database : getDatabases()) {
|
||||
String dbConfigName = database.getConfigName();
|
||||
String dbConfigName = database.getType().getConfigName();
|
||||
if (Verify.equalsIgnoreCase(dbName, dbConfigName)) {
|
||||
return database;
|
||||
}
|
||||
|
@ -100,11 +104,11 @@ public abstract class DBSystem implements SubSystem {
|
|||
try {
|
||||
db.init();
|
||||
db.scheduleClean(20L);
|
||||
logger.info(locale.getString(PluginLang.ENABLED_DATABASE, db.getName()));
|
||||
logger.info(locale.getString(PluginLang.ENABLED_DATABASE, db.getType().getName()));
|
||||
} catch (DBInitException e) {
|
||||
Throwable cause = e.getCause();
|
||||
String message = cause == null ? e.getMessage() : cause.getMessage();
|
||||
throw new EnableException((db != null ? db.getName() : "Database") + " init failure: " + message, cause);
|
||||
throw new EnableException((db != null ? db.getType().getName() : "Database") + " init failure: " + message, cause);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,4 +120,8 @@ public abstract class DBSystem implements SubSystem {
|
|||
public SQLiteDB.Factory getSqLiteFactory() {
|
||||
return sqLiteFactory;
|
||||
}
|
||||
|
||||
public H2DB.Factory getH2Factory() {
|
||||
return h2Factory;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
*/
|
||||
package com.djrapitops.plan.system.database;
|
||||
|
||||
import com.djrapitops.plan.system.database.databases.sql.H2DB;
|
||||
import com.djrapitops.plan.system.database.databases.sql.MySQLDB;
|
||||
import com.djrapitops.plan.system.database.databases.sql.SQLiteDB;
|
||||
import com.djrapitops.plan.system.locale.Locale;
|
||||
|
@ -39,11 +40,12 @@ public class ProxyDBSystem extends DBSystem {
|
|||
Locale locale,
|
||||
MySQLDB mySQLDB,
|
||||
SQLiteDB.Factory sqLiteDB,
|
||||
H2DB.Factory h2DB,
|
||||
PluginLogger logger,
|
||||
Timings timings,
|
||||
ErrorHandler errorHandler
|
||||
) {
|
||||
super(locale, sqLiteDB, logger, timings, errorHandler);
|
||||
super(locale, sqLiteDB, h2DB, logger, timings, errorHandler);
|
||||
databases.add(mySQLDB);
|
||||
db = mySQLDB;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package com.djrapitops.plan.system.database;
|
||||
|
||||
import com.djrapitops.plan.api.exceptions.EnableException;
|
||||
import com.djrapitops.plan.system.database.databases.sql.H2DB;
|
||||
import com.djrapitops.plan.system.database.databases.sql.SQLiteDB;
|
||||
import com.djrapitops.plan.system.database.databases.sql.SpongeMySQLDB;
|
||||
import com.djrapitops.plan.system.locale.Locale;
|
||||
|
@ -44,16 +45,18 @@ public class SpongeDBSystem extends DBSystem {
|
|||
Locale locale,
|
||||
SpongeMySQLDB spongeMySQLDB,
|
||||
SQLiteDB.Factory sqLiteDB,
|
||||
H2DB.Factory h2DB,
|
||||
PlanConfig config,
|
||||
PluginLogger logger,
|
||||
Timings timings,
|
||||
ErrorHandler errorHandler
|
||||
) {
|
||||
super(locale, sqLiteDB, logger, timings, errorHandler);
|
||||
super(locale, sqLiteDB, h2DB, logger, timings, errorHandler);
|
||||
this.config = config;
|
||||
|
||||
databases.add(spongeMySQLDB);
|
||||
databases.add(sqLiteDB.usingDefaultFile());
|
||||
databases.add(h2DB.usingDefaultFile());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* This file is part of Player Analytics (Plan).
|
||||
*
|
||||
* Plan is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the LGNU Lesser General Public License v3 as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Plan is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* LGNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.djrapitops.plan.system.database.databases;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* An enum which stores the name, the config name and if the Database supports MySQL Queries
|
||||
*
|
||||
* @author Fuzzlemann
|
||||
* @since 4.5.1
|
||||
*/
|
||||
public enum DBType {
|
||||
|
||||
MySQL("MySQL", true),
|
||||
SQLite("SQLite", false),
|
||||
H2("H2", true);
|
||||
|
||||
private final String name;
|
||||
private final String configName;
|
||||
private final boolean supportingMySQLQueries;
|
||||
|
||||
DBType(String name, boolean supportingMySQLQueries) {
|
||||
this.name = name;
|
||||
this.configName = name.toLowerCase().trim();
|
||||
this.supportingMySQLQueries = supportingMySQLQueries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the {@code DBType}
|
||||
*
|
||||
* @return the name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the config name of the {@code DBType}
|
||||
*
|
||||
* @return the config name
|
||||
*/
|
||||
public String getConfigName() {
|
||||
return configName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to check if the {@code DBType} supports <b>most</b> MySQL Queries.<p>
|
||||
* When specific Statements are not compatible, the {@code DBType} should be checked.
|
||||
*
|
||||
* @return if the database supports MySQL Queries
|
||||
*/
|
||||
public boolean supportsMySQLQueries() {
|
||||
return supportingMySQLQueries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an {@code Optional<DBType>} which matches {@code name}.<p>
|
||||
* This method is case-insensitive.<p>
|
||||
* The {@code Optional<DBType>} is empty when no {@code DBType} is found.
|
||||
*
|
||||
* @param name the name of the {@code DBType}
|
||||
* @return an {@code Optional<DBType>}
|
||||
*/
|
||||
public static Optional<DBType> getForName(String name) {
|
||||
for (DBType dbType : DBType.values()) {
|
||||
if (dbType.getName().equalsIgnoreCase(name)) {
|
||||
return Optional.of(dbType);
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the name of a {@code DBType} corresponds to {@code name}.<p>
|
||||
* This method is case-insensitive.
|
||||
*
|
||||
* @param name the name of the {@code DBType}
|
||||
* @return if the {@code DBType} exists
|
||||
* @see DBType#getForName(String)
|
||||
*/
|
||||
public static boolean exists(String name) {
|
||||
for (DBType dbType : DBType.values()) {
|
||||
if (dbType.getName().equalsIgnoreCase(name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -29,7 +29,7 @@ import com.djrapitops.plan.system.database.databases.operation.*;
|
|||
*/
|
||||
public abstract class Database {
|
||||
|
||||
protected boolean open = false;
|
||||
protected volatile boolean open = false;
|
||||
|
||||
public abstract void init() throws DBInitException;
|
||||
|
||||
|
@ -47,18 +47,13 @@ public abstract class Database {
|
|||
|
||||
public abstract SaveOperations save();
|
||||
|
||||
public abstract String getName();
|
||||
|
||||
/**
|
||||
* Used to get the config name of the database type.
|
||||
* <p>
|
||||
* Thread safe.
|
||||
* Used to get the {@code DBType} of the Database
|
||||
*
|
||||
* @return sqlite/mysql
|
||||
* @return the {@code DBType}
|
||||
* @see DBType
|
||||
*/
|
||||
public String getConfigName() {
|
||||
return getName().toLowerCase().trim();
|
||||
}
|
||||
public abstract DBType getType();
|
||||
|
||||
public abstract void close() throws DBException;
|
||||
|
||||
|
|
|
@ -0,0 +1,240 @@
|
|||
/*
|
||||
* This file is part of Player Analytics (Plan).
|
||||
*
|
||||
* Plan is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the LGNU Lesser General Public License v3 as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Plan is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* LGNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.djrapitops.plan.system.database.databases.sql;
|
||||
|
||||
import com.djrapitops.plan.api.exceptions.database.DBInitException;
|
||||
import com.djrapitops.plan.data.store.containers.NetworkContainer;
|
||||
import com.djrapitops.plan.system.database.databases.DBType;
|
||||
import com.djrapitops.plan.system.file.PlanFiles;
|
||||
import com.djrapitops.plan.system.info.server.ServerInfo;
|
||||
import com.djrapitops.plan.system.locale.Locale;
|
||||
import com.djrapitops.plan.system.settings.Settings;
|
||||
import com.djrapitops.plan.system.settings.config.PlanConfig;
|
||||
import com.djrapitops.plan.utilities.MiscUtils;
|
||||
import com.djrapitops.plugin.benchmarking.Timings;
|
||||
import com.djrapitops.plugin.logging.L;
|
||||
import com.djrapitops.plugin.logging.console.PluginLogger;
|
||||
import com.djrapitops.plugin.logging.error.ErrorHandler;
|
||||
import com.djrapitops.plugin.task.PluginTask;
|
||||
import com.djrapitops.plugin.task.RunnableFactory;
|
||||
import dagger.Lazy;
|
||||
import org.h2.jdbcx.JdbcDataSource;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.io.File;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Implementation of the H2 database
|
||||
*
|
||||
* @author Fuzzlemann
|
||||
* @since 4.5.1
|
||||
*/
|
||||
public class H2DB extends SQLDB {
|
||||
|
||||
private final File databaseFile;
|
||||
private final String dbName;
|
||||
private Connection connection;
|
||||
private PluginTask connectionPingTask;
|
||||
|
||||
private H2DB(
|
||||
File databaseFile,
|
||||
Locale locale,
|
||||
PlanConfig config,
|
||||
Lazy<ServerInfo> serverInfo,
|
||||
NetworkContainer.Factory networkContainerFactory,
|
||||
RunnableFactory runnableFactory,
|
||||
PluginLogger logger,
|
||||
Timings timings,
|
||||
ErrorHandler errorHandler
|
||||
) {
|
||||
super(() -> serverInfo.get().getServerUUID(), locale, config, networkContainerFactory, runnableFactory, logger, timings, errorHandler);
|
||||
dbName = databaseFile.getName();
|
||||
this.databaseFile = databaseFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupDataSource() throws DBInitException {
|
||||
try {
|
||||
Class.forName("org.h2.Driver");
|
||||
} catch (ClassNotFoundException e) {
|
||||
errorHandler.log(L.CRITICAL, this.getClass(), e);
|
||||
}
|
||||
|
||||
try {
|
||||
connection = getNewConnection(databaseFile);
|
||||
} catch (SQLException e) {
|
||||
throw new DBInitException(e);
|
||||
}
|
||||
|
||||
execute("SET REFERENTIAL_INTEGRITY FALSE");
|
||||
startConnectionPingTask();
|
||||
}
|
||||
|
||||
public Connection getNewConnection(File dbFile) throws SQLException {
|
||||
String dbFilePath = dbFile.getAbsolutePath();
|
||||
|
||||
Connection newConnection = getConnectionFor(dbFilePath);
|
||||
logger.debug("H2 " + dbName + ": Opened a new Connection");
|
||||
newConnection.setAutoCommit(false);
|
||||
return newConnection;
|
||||
}
|
||||
|
||||
private Connection getConnectionFor(String dbFilePath) throws SQLException {
|
||||
String username = config.getString(Settings.DB_USER);
|
||||
String password = config.getString(Settings.DB_PASS);
|
||||
|
||||
JdbcDataSource jdbcDataSource = new JdbcDataSource();
|
||||
jdbcDataSource.setURL("jdbc:h2:file:" + dbFilePath + ";mode=MySQL");
|
||||
jdbcDataSource.setUser(username);
|
||||
jdbcDataSource.setPassword(password);
|
||||
|
||||
return jdbcDataSource.getConnection();
|
||||
}
|
||||
|
||||
private void startConnectionPingTask() {
|
||||
stopConnectionPingTask();
|
||||
try {
|
||||
// Maintains Connection.
|
||||
connectionPingTask = runnableFactory.create("DBConnectionPingTask " + getType().getName(),
|
||||
new KeepAliveTask(connection, () -> getNewConnection(databaseFile), logger, errorHandler)
|
||||
).runTaskTimerAsynchronously(60L * 20L, 60L * 20L);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
private void stopConnectionPingTask() {
|
||||
if (connectionPingTask != null) {
|
||||
try {
|
||||
connectionPingTask.cancel();
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DBType getType() {
|
||||
return DBType.H2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection getConnection() throws SQLException {
|
||||
if (connection == null) {
|
||||
connection = getNewConnection(databaseFile);
|
||||
}
|
||||
|
||||
return connection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
super.close();
|
||||
stopConnectionPingTask();
|
||||
|
||||
if (connection != null) {
|
||||
logger.debug("H2DB " + dbName + ": Closed Connection");
|
||||
MiscUtils.close(connection);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commit(Connection connection) {
|
||||
try {
|
||||
connection.commit();
|
||||
} catch (SQLException e) {
|
||||
if (!e.getMessage().contains("cannot commit")) {
|
||||
errorHandler.log(L.ERROR, this.getClass(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void returnToPool(Connection connection) {
|
||||
// Connection pool not in use, no action required.
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
if (!super.equals(o)) return false;
|
||||
H2DB h2DB = (H2DB) o;
|
||||
return Objects.equals(dbName, h2DB.dbName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), dbName);
|
||||
}
|
||||
|
||||
@Singleton
|
||||
public static class Factory {
|
||||
|
||||
private final Locale locale;
|
||||
private final PlanConfig config;
|
||||
private final Lazy<ServerInfo> serverInfo;
|
||||
private final NetworkContainer.Factory networkContainerFactory;
|
||||
private final RunnableFactory runnableFactory;
|
||||
private final PluginLogger logger;
|
||||
private final Timings timings;
|
||||
private final ErrorHandler errorHandler;
|
||||
private PlanFiles files;
|
||||
|
||||
@Inject
|
||||
public Factory(
|
||||
Locale locale,
|
||||
PlanConfig config,
|
||||
PlanFiles files,
|
||||
Lazy<ServerInfo> serverInfo,
|
||||
NetworkContainer.Factory networkContainerFactory,
|
||||
RunnableFactory runnableFactory,
|
||||
PluginLogger logger,
|
||||
Timings timings,
|
||||
ErrorHandler errorHandler
|
||||
) {
|
||||
this.locale = locale;
|
||||
this.config = config;
|
||||
this.files = files;
|
||||
this.serverInfo = serverInfo;
|
||||
this.networkContainerFactory = networkContainerFactory;
|
||||
this.runnableFactory = runnableFactory;
|
||||
this.logger = logger;
|
||||
this.timings = timings;
|
||||
this.errorHandler = errorHandler;
|
||||
}
|
||||
|
||||
public H2DB usingDefaultFile() {
|
||||
return usingFileCalled("h2database");
|
||||
}
|
||||
|
||||
public H2DB usingFileCalled(String fileName) {
|
||||
return usingFile(files.getFileFromPluginFolder(fileName));
|
||||
}
|
||||
|
||||
public H2DB usingFile(File databaseFile) {
|
||||
return new H2DB(databaseFile,
|
||||
locale, config, serverInfo,
|
||||
networkContainerFactory,
|
||||
runnableFactory, logger, timings, errorHandler
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package com.djrapitops.plan.system.database.databases.sql;
|
||||
|
||||
import com.djrapitops.plan.utilities.MiscUtils;
|
||||
import com.djrapitops.plugin.logging.L;
|
||||
import com.djrapitops.plugin.logging.console.PluginLogger;
|
||||
import com.djrapitops.plugin.logging.error.ErrorHandler;
|
||||
import com.djrapitops.plugin.task.AbsRunnable;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
|
||||
/**
|
||||
* The task which handles the upkeep of the {@code Connection}
|
||||
*
|
||||
* @author Fuzzlemann
|
||||
* @since 4.5.1
|
||||
*/
|
||||
public class KeepAliveTask extends AbsRunnable {
|
||||
private Connection connection;
|
||||
private final IReconnect iReconnect;
|
||||
private final PluginLogger logger;
|
||||
private final ErrorHandler errorHandler;
|
||||
|
||||
public KeepAliveTask(Connection connection, IReconnect iReconnect, PluginLogger logger, ErrorHandler errorHandler) {
|
||||
this.connection = connection;
|
||||
this.iReconnect = iReconnect;
|
||||
this.logger = logger;
|
||||
this.errorHandler = errorHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Statement statement = null;
|
||||
ResultSet resultSet = null;
|
||||
try {
|
||||
if (connection != null && !connection.isClosed()) {
|
||||
statement = connection.createStatement();
|
||||
resultSet = statement.executeQuery("/* ping */ SELECT 1");
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
logger.debug("Something went wrong during SQL Connection upkeep task.");
|
||||
try {
|
||||
connection = iReconnect.reconnect();
|
||||
} catch (SQLException e1) {
|
||||
errorHandler.log(L.ERROR, this.getClass(), e1);
|
||||
logger.error("SQL connection maintaining task had to be closed due to exception.");
|
||||
this.cancel();
|
||||
}
|
||||
} finally {
|
||||
MiscUtils.close(statement, resultSet);
|
||||
}
|
||||
}
|
||||
|
||||
public interface IReconnect {
|
||||
Connection reconnect() throws SQLException;
|
||||
}
|
||||
}
|
|
@ -19,6 +19,7 @@ package com.djrapitops.plan.system.database.databases.sql;
|
|||
import com.djrapitops.plan.api.exceptions.database.DBInitException;
|
||||
import com.djrapitops.plan.api.exceptions.database.DBOpException;
|
||||
import com.djrapitops.plan.data.store.containers.NetworkContainer;
|
||||
import com.djrapitops.plan.system.database.databases.DBType;
|
||||
import com.djrapitops.plan.system.info.server.ServerInfo;
|
||||
import com.djrapitops.plan.system.locale.Locale;
|
||||
import com.djrapitops.plan.system.locale.lang.PluginLang;
|
||||
|
@ -67,12 +68,9 @@ public class MySQLDB extends SQLDB {
|
|||
increment++;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the name of the Database
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "MySQL";
|
||||
public DBType getType() {
|
||||
return DBType.MySQL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -136,10 +134,11 @@ public class MySQLDB extends SQLDB {
|
|||
|
||||
@Override
|
||||
public void close() {
|
||||
super.close();
|
||||
|
||||
if (dataSource instanceof HikariDataSource) {
|
||||
((HikariDataSource) dataSource).close();
|
||||
}
|
||||
super.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -158,11 +157,6 @@ public class MySQLDB extends SQLDB {
|
|||
returnToPool(connection);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUsingMySQL() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
|
|
@ -288,6 +288,10 @@ public abstract class SQLDB extends Database {
|
|||
public abstract void returnToPool(Connection connection);
|
||||
|
||||
public boolean execute(ExecStatement statement) {
|
||||
if (!isOpen()) {
|
||||
throw new DBOpException("SQL Statement tried to execute while connection closed");
|
||||
}
|
||||
|
||||
Connection connection = null;
|
||||
try {
|
||||
connection = getConnection();
|
||||
|
@ -328,6 +332,10 @@ public abstract class SQLDB extends Database {
|
|||
}
|
||||
|
||||
public void executeBatch(ExecStatement statement) {
|
||||
if (!isOpen()) {
|
||||
throw new DBOpException("SQL Batch tried to execute while connection closed");
|
||||
}
|
||||
|
||||
Connection connection = null;
|
||||
try {
|
||||
connection = getConnection();
|
||||
|
@ -346,6 +354,10 @@ public abstract class SQLDB extends Database {
|
|||
}
|
||||
|
||||
public <T> T query(QueryStatement<T> statement) {
|
||||
if (!isOpen()) {
|
||||
throw new DBOpException("SQL Query tried to execute while connection closed");
|
||||
}
|
||||
|
||||
Connection connection = null;
|
||||
try {
|
||||
connection = getConnection();
|
||||
|
@ -419,10 +431,6 @@ public abstract class SQLDB extends Database {
|
|||
return pingTable;
|
||||
}
|
||||
|
||||
public boolean isUsingMySQL() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BackupOperations backup() {
|
||||
return backupOps;
|
||||
|
@ -468,12 +476,12 @@ public abstract class SQLDB extends Database {
|
|||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
SQLDB sqldb = (SQLDB) o;
|
||||
return getName().equals(sqldb.getName());
|
||||
return getType() == sqldb.getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(getName());
|
||||
return Objects.hash(getType().getName());
|
||||
}
|
||||
|
||||
public Supplier<UUID> getServerUUIDSupplier() {
|
||||
|
|
|
@ -18,6 +18,7 @@ package com.djrapitops.plan.system.database.databases.sql;
|
|||
|
||||
import com.djrapitops.plan.api.exceptions.database.DBInitException;
|
||||
import com.djrapitops.plan.data.store.containers.NetworkContainer;
|
||||
import com.djrapitops.plan.system.database.databases.DBType;
|
||||
import com.djrapitops.plan.system.file.PlanFiles;
|
||||
import com.djrapitops.plan.system.info.server.ServerInfo;
|
||||
import com.djrapitops.plan.system.locale.Locale;
|
||||
|
@ -28,7 +29,6 @@ import com.djrapitops.plugin.benchmarking.Timings;
|
|||
import com.djrapitops.plugin.logging.L;
|
||||
import com.djrapitops.plugin.logging.console.PluginLogger;
|
||||
import com.djrapitops.plugin.logging.error.ErrorHandler;
|
||||
import com.djrapitops.plugin.task.AbsRunnable;
|
||||
import com.djrapitops.plugin.task.PluginTask;
|
||||
import com.djrapitops.plugin.task.RunnableFactory;
|
||||
import dagger.Lazy;
|
||||
|
@ -36,7 +36,9 @@ import dagger.Lazy;
|
|||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.io.File;
|
||||
import java.sql.*;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
|
@ -104,30 +106,9 @@ public class SQLiteDB extends SQLDB {
|
|||
stopConnectionPingTask();
|
||||
try {
|
||||
// Maintains Connection.
|
||||
connectionPingTask = runnableFactory.create("DBConnectionPingTask " + getName(), new AbsRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Statement statement = null;
|
||||
ResultSet resultSet = null;
|
||||
try {
|
||||
if (connection != null && !connection.isClosed()) {
|
||||
statement = connection.createStatement();
|
||||
resultSet = statement.executeQuery("/* ping */ SELECT 1");
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
logger.debug("Something went wrong during SQLite Connection upkeep task.");
|
||||
try {
|
||||
connection = getNewConnection(databaseFile);
|
||||
} catch (SQLException e1) {
|
||||
errorHandler.log(L.ERROR, this.getClass(), e1);
|
||||
logger.error("SQLite connection maintaining task had to be closed due to exception.");
|
||||
this.cancel();
|
||||
}
|
||||
} finally {
|
||||
MiscUtils.close(statement, resultSet);
|
||||
}
|
||||
}
|
||||
}).runTaskTimerAsynchronously(60L * 20L, 60L * 20L);
|
||||
connectionPingTask = runnableFactory.create("DBConnectionPingTask " + getType().getName(),
|
||||
new KeepAliveTask(connection, () -> getNewConnection(databaseFile), logger, errorHandler)
|
||||
).runTaskTimerAsynchronously(60L * 20L, 60L * 20L);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
@ -141,12 +122,9 @@ public class SQLiteDB extends SQLDB {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the name of the Database
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "SQLite";
|
||||
public DBType getType() {
|
||||
return DBType.SQLite;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -159,12 +137,13 @@ public class SQLiteDB extends SQLDB {
|
|||
|
||||
@Override
|
||||
public void close() {
|
||||
super.close();
|
||||
stopConnectionPingTask();
|
||||
|
||||
if (connection != null) {
|
||||
logger.debug("SQLite " + dbName + ": Closed Connection");
|
||||
MiscUtils.close(connection);
|
||||
}
|
||||
super.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -250,4 +229,5 @@ public class SQLiteDB extends SQLDB {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import com.djrapitops.plan.data.store.mutators.PerServerMutator;
|
|||
import com.djrapitops.plan.data.store.mutators.PlayersMutator;
|
||||
import com.djrapitops.plan.data.store.mutators.SessionsMutator;
|
||||
import com.djrapitops.plan.data.store.objects.DateObj;
|
||||
import com.djrapitops.plan.data.store.objects.Nickname;
|
||||
import com.djrapitops.plan.data.time.WorldTimes;
|
||||
import com.djrapitops.plan.system.cache.SessionCache;
|
||||
import com.djrapitops.plan.system.database.databases.operation.FetchOperations;
|
||||
|
@ -123,6 +124,7 @@ public class SQLFetchOps extends SQLOps implements FetchOperations {
|
|||
Map<UUID, Integer> timesKicked = usersTable.getAllTimesKicked();
|
||||
Map<UUID, List<GeoInfo>> geoInfo = geoInfoTable.getAllGeoInfo();
|
||||
Map<UUID, List<Ping>> allPings = pingTable.getAllPings();
|
||||
Map<UUID, List<Nickname>> allNicknames = nicknamesTable.getAllNicknamesUnmapped();
|
||||
|
||||
Map<UUID, List<Session>> sessions = sessionsTable.getSessionInfoOfServer(serverUUID);
|
||||
Map<UUID, Map<UUID, List<Session>>> map = new HashMap<>();
|
||||
|
@ -144,7 +146,7 @@ public class SQLFetchOps extends SQLOps implements FetchOperations {
|
|||
container.putRawData(PlayerKeys.KICK_COUNT, timesKicked.get(uuid));
|
||||
container.putRawData(PlayerKeys.GEO_INFO, geoInfo.get(uuid));
|
||||
container.putRawData(PlayerKeys.PING, allPings.get(uuid));
|
||||
container.putCachingSupplier(PlayerKeys.NICKNAMES, () -> nicknamesTable.getNicknameInformation(uuid));
|
||||
container.putRawData(PlayerKeys.NICKNAMES, allNicknames.get(uuid));
|
||||
container.putRawData(PlayerKeys.PER_SERVER, perServerInfo.get(uuid));
|
||||
|
||||
container.putRawData(PlayerKeys.BANNED, userInfo.isBanned());
|
||||
|
@ -187,6 +189,7 @@ public class SQLFetchOps extends SQLOps implements FetchOperations {
|
|||
Map<UUID, Integer> timesKicked = usersTable.getAllTimesKicked();
|
||||
Map<UUID, List<GeoInfo>> geoInfo = geoInfoTable.getAllGeoInfo();
|
||||
Map<UUID, List<Ping>> allPings = pingTable.getAllPings();
|
||||
Map<UUID, List<Nickname>> allNicknames = nicknamesTable.getAllNicknamesUnmapped();
|
||||
|
||||
Map<UUID, Map<UUID, List<Session>>> sessions = sessionsTable.getAllSessions(false);
|
||||
Map<UUID, List<UserInfo>> allUserInfo = userInfoTable.getAllUserInfo();
|
||||
|
@ -202,7 +205,7 @@ public class SQLFetchOps extends SQLOps implements FetchOperations {
|
|||
container.putRawData(PlayerKeys.KICK_COUNT, timesKicked.get(uuid));
|
||||
container.putRawData(PlayerKeys.GEO_INFO, geoInfo.get(uuid));
|
||||
container.putRawData(PlayerKeys.PING, allPings.get(uuid));
|
||||
container.putCachingSupplier(PlayerKeys.NICKNAMES, () -> nicknamesTable.getNicknameInformation(uuid));
|
||||
container.putRawData(PlayerKeys.NICKNAMES, allNicknames.get(uuid));
|
||||
container.putRawData(PlayerKeys.PER_SERVER, perServerInfo.get(uuid));
|
||||
|
||||
container.putCachingSupplier(PlayerKeys.SESSIONS, () -> {
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
*/
|
||||
package com.djrapitops.plan.system.database.databases.sql.patches;
|
||||
|
||||
import com.djrapitops.plan.system.database.databases.DBType;
|
||||
import com.djrapitops.plan.system.database.databases.sql.SQLDB;
|
||||
import com.djrapitops.plan.system.database.databases.sql.processing.QueryAllStatement;
|
||||
import com.djrapitops.plan.system.database.databases.sql.processing.QueryStatement;
|
||||
|
@ -30,11 +31,11 @@ import java.util.UUID;
|
|||
public abstract class Patch {
|
||||
|
||||
protected final SQLDB db;
|
||||
protected final boolean usingMySQL;
|
||||
protected final DBType dbType;
|
||||
|
||||
public Patch(SQLDB db) {
|
||||
this.db = db;
|
||||
usingMySQL = db.isUsingMySQL();
|
||||
this.dbType = db.getType();
|
||||
}
|
||||
|
||||
public abstract boolean hasBeenApplied();
|
||||
|
@ -46,15 +47,25 @@ public abstract class Patch {
|
|||
}
|
||||
|
||||
public boolean hasTable(String tableName) {
|
||||
String sql = usingMySQL ?
|
||||
"SELECT * FROM information_schema.TABLES WHERE table_name=? AND TABLE_SCHEMA=? LIMIT 1" :
|
||||
"SELECT tbl_name FROM sqlite_master WHERE tbl_name=?";
|
||||
boolean secondParameter;
|
||||
|
||||
String sql;
|
||||
if (dbType == DBType.H2) {
|
||||
sql = "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME=?";
|
||||
secondParameter = false;
|
||||
} else if (dbType.supportsMySQLQueries()) {
|
||||
sql = "SELECT * FROM information_schema.TABLES WHERE table_name=? AND TABLE_SCHEMA=? LIMIT 1";
|
||||
secondParameter = true;
|
||||
} else {
|
||||
sql = "SELECT tbl_name FROM sqlite_master WHERE tbl_name=?";
|
||||
secondParameter = false;
|
||||
}
|
||||
|
||||
return query(new QueryStatement<Boolean>(sql) {
|
||||
@Override
|
||||
public void prepare(PreparedStatement statement) throws SQLException {
|
||||
statement.setString(1, tableName);
|
||||
if (usingMySQL) {
|
||||
if (secondParameter) {
|
||||
statement.setString(2, db.getConfig().getString(Settings.DB_DATABASE));
|
||||
}
|
||||
}
|
||||
|
@ -67,36 +78,49 @@ public abstract class Patch {
|
|||
}
|
||||
|
||||
protected boolean hasColumn(String tableName, String columnName) {
|
||||
return usingMySQL ?
|
||||
query(new QueryStatement<Boolean>("SELECT * FROM information_schema.COLUMNS" +
|
||||
" WHERE TABLE_NAME=? AND COLUMN_NAME=? AND TABLE_SCHEMA=?") {
|
||||
@Override
|
||||
public void prepare(PreparedStatement statement) throws SQLException {
|
||||
statement.setString(1, tableName);
|
||||
statement.setString(2, columnName);
|
||||
if (dbType.supportsMySQLQueries()) {
|
||||
String query;
|
||||
|
||||
if (dbType == DBType.H2) {
|
||||
query = "SELECT * FROM INFORMATION_SCHEMA.COLUMNS" +
|
||||
" WHERE TABLE_NAME=? AND COLUMN_NAME=?";
|
||||
} else {
|
||||
query = "SELECT * FROM information_schema.COLUMNS" +
|
||||
" WHERE TABLE_NAME=? AND COLUMN_NAME=? AND TABLE_SCHEMA=?";
|
||||
}
|
||||
|
||||
return query(new QueryStatement<Boolean>(query) {
|
||||
@Override
|
||||
public void prepare(PreparedStatement statement) throws SQLException {
|
||||
statement.setString(1, tableName);
|
||||
statement.setString(2, columnName);
|
||||
if (dbType != DBType.H2) {
|
||||
statement.setString(3, db.getConfig().getString(Settings.DB_DATABASE));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean processResults(ResultSet set) throws SQLException {
|
||||
return set.next();
|
||||
}
|
||||
}) :
|
||||
query(new QueryAllStatement<Boolean>("PRAGMA table_info(" + tableName + ")") {
|
||||
@Override
|
||||
public Boolean processResults(ResultSet set) throws SQLException {
|
||||
while (set.next()) {
|
||||
if (columnName.equals(set.getString("name"))) {
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public Boolean processResults(ResultSet set) throws SQLException {
|
||||
return set.next();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return query(new QueryAllStatement<Boolean>("PRAGMA table_info(" + tableName + ")") {
|
||||
@Override
|
||||
public Boolean processResults(ResultSet set) throws SQLException {
|
||||
while (set.next()) {
|
||||
if (columnName.equals(set.getString("name"))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
protected void addColumn(String tableName, String columnInfo) {
|
||||
db.executeUnsafe("ALTER TABLE " + tableName + " ADD " + (usingMySQL ? "" : "COLUMN ") + columnInfo);
|
||||
db.executeUnsafe("ALTER TABLE " + tableName + " ADD " + (dbType.supportsMySQLQueries() ? "" : "COLUMN ") + columnInfo);
|
||||
}
|
||||
|
||||
protected void dropTable(String name) {
|
||||
|
@ -104,7 +128,7 @@ public abstract class Patch {
|
|||
}
|
||||
|
||||
protected void renameTable(String from, String to) {
|
||||
String sql = usingMySQL ?
|
||||
String sql = dbType.supportsMySQLQueries() ?
|
||||
"RENAME TABLE " + from + " TO " + to :
|
||||
"ALTER TABLE " + from + " RENAME TO " + to;
|
||||
db.execute(sql);
|
||||
|
|
|
@ -109,7 +109,7 @@ public class Version10Patch extends Patch {
|
|||
" FROM " + tempNickTableName;
|
||||
db.execute(statement);
|
||||
try {
|
||||
if (usingMySQL) {
|
||||
if (dbType.supportsMySQLQueries()) {
|
||||
db.execute("SET foreign_key_checks = 0");
|
||||
}
|
||||
statement = "INSERT INTO plan_kills " +
|
||||
|
@ -118,7 +118,7 @@ public class Version10Patch extends Patch {
|
|||
" FROM " + tempKillsTableName;
|
||||
db.execute(statement);
|
||||
} finally {
|
||||
if (usingMySQL) {
|
||||
if (dbType.supportsMySQLQueries()) {
|
||||
db.execute("SET foreign_key_checks = 1");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,11 +62,11 @@ public class CommandUseTable extends Table {
|
|||
public void createTable() throws DBInitException {
|
||||
ServerTable serverTable = db.getServerTable();
|
||||
createTable(TableSqlParser.createTable(tableName)
|
||||
.primaryKeyIDColumn(usingMySQL, Col.COMMAND_ID)
|
||||
.primaryKeyIDColumn(supportsMySQLQueries, Col.COMMAND_ID)
|
||||
.column(Col.COMMAND, Sql.varchar(20)).notNull()
|
||||
.column(Col.TIMES_USED, Sql.INT).notNull()
|
||||
.column(Col.SERVER_ID, Sql.INT).notNull()
|
||||
.primaryKey(usingMySQL, Col.COMMAND_ID)
|
||||
.primaryKey(supportsMySQLQueries, Col.COMMAND_ID)
|
||||
.foreignKey(Col.SERVER_ID, serverTable.toString(), ServerTable.Col.SERVER_ID)
|
||||
.toString()
|
||||
);
|
||||
|
|
|
@ -81,8 +81,6 @@ public class NicknamesTable extends UserIDTable {
|
|||
|
||||
/**
|
||||
* Get nicknames of the user on a server.
|
||||
* <p>
|
||||
* Get's nicknames from other servers as well.
|
||||
*
|
||||
* @param uuid UUID of the Player
|
||||
* @param serverUUID UUID of the server
|
||||
|
@ -119,8 +117,6 @@ public class NicknamesTable extends UserIDTable {
|
|||
|
||||
/**
|
||||
* Get nicknames of the user on THIS server.
|
||||
* <p>
|
||||
* Get's nicknames from other servers as well.
|
||||
*
|
||||
* @param uuid UUID of the Player
|
||||
* @return The nicknames of the User
|
||||
|
@ -166,6 +162,42 @@ public class NicknamesTable extends UserIDTable {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get nicknames of all users but doesn't map them by Server
|
||||
*
|
||||
* @return a {@code Map<UUID, List<Nickname>} with all nicknames of all users
|
||||
* @see NicknamesTable#getAllNicknames();
|
||||
*/
|
||||
public Map<UUID, List<Nickname>> getAllNicknamesUnmapped() {
|
||||
String usersIDColumn = usersTable + "." + UsersTable.Col.ID;
|
||||
String usersUUIDColumn = usersTable + "." + UsersTable.Col.UUID + " as uuid";
|
||||
String serverIDColumn = serverTable + "." + ServerTable.Col.SERVER_ID;
|
||||
String serverUUIDColumn = serverTable + "." + ServerTable.Col.SERVER_UUID + " as s_uuid";
|
||||
String sql = "SELECT " +
|
||||
Col.NICKNAME + ", " +
|
||||
Col.LAST_USED + ", " +
|
||||
usersUUIDColumn + ", " +
|
||||
serverUUIDColumn +
|
||||
" FROM " + tableName +
|
||||
" INNER JOIN " + usersTable + " on " + usersIDColumn + "=" + Col.USER_ID +
|
||||
" INNER JOIN " + serverTable + " on " + serverIDColumn + "=" + Col.SERVER_ID;
|
||||
return query(new QueryAllStatement<Map<UUID, List<Nickname>>>(sql, 5000) {
|
||||
@Override
|
||||
public Map<UUID, List<Nickname>> processResults(ResultSet set) throws SQLException {
|
||||
Map<UUID, List<Nickname>> map = new HashMap<>();
|
||||
while (set.next()) {
|
||||
UUID uuid = UUID.fromString(set.getString("uuid"));
|
||||
UUID serverUUID = UUID.fromString(set.getString("s_uuid"));
|
||||
List<Nickname> nicknames = map.computeIfAbsent(uuid, x -> new ArrayList<>());
|
||||
nicknames.add(new Nickname(
|
||||
set.getString(Col.NICKNAME.get()), set.getLong(Col.LAST_USED.get()), serverUUID
|
||||
));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void saveUserName(UUID uuid, Nickname name) {
|
||||
List<Nickname> saved = getNicknameInformation(uuid);
|
||||
if (saved.contains(name)) {
|
||||
|
|
|
@ -56,14 +56,14 @@ public class PingTable extends UserIDTable {
|
|||
@Override
|
||||
public void createTable() throws DBInitException {
|
||||
createTable(TableSqlParser.createTable(TABLE_NAME)
|
||||
.primaryKeyIDColumn(usingMySQL, Col.ID)
|
||||
.primaryKeyIDColumn(supportsMySQLQueries, Col.ID)
|
||||
.column(Col.USER_ID, Sql.INT).notNull()
|
||||
.column(Col.SERVER_ID, Sql.INT).notNull()
|
||||
.column(Col.DATE, Sql.LONG).notNull()
|
||||
.column(Col.MAX_PING, Sql.INT).notNull()
|
||||
.column(Col.MIN_PING, Sql.INT).notNull()
|
||||
.column(Col.AVG_PING, Sql.DOUBLE).notNull()
|
||||
.primaryKey(usingMySQL, Col.ID)
|
||||
.primaryKey(supportsMySQLQueries, Col.ID)
|
||||
.foreignKey(Col.USER_ID, usersTable.getTableName(), UsersTable.Col.ID)
|
||||
.foreignKey(Col.SERVER_ID, ServerTable.TABLE_NAME, ServerTable.Col.SERVER_ID)
|
||||
.toString());
|
||||
|
|
|
@ -63,13 +63,13 @@ public class ServerTable extends Table {
|
|||
@Override
|
||||
public void createTable() throws DBInitException {
|
||||
createTable(TableSqlParser.createTable(tableName)
|
||||
.primaryKeyIDColumn(usingMySQL, Col.SERVER_ID)
|
||||
.primaryKeyIDColumn(supportsMySQLQueries, Col.SERVER_ID)
|
||||
.column(Col.SERVER_UUID, Sql.varchar(36)).notNull().unique()
|
||||
.column(Col.NAME, Sql.varchar(100))
|
||||
.column(Col.WEBSERVER_ADDRESS, Sql.varchar(100))
|
||||
.column(Col.INSTALLED, Sql.BOOL).notNull().defaultValue(true)
|
||||
.column(Col.MAX_PLAYERS, Sql.INT).notNull().defaultValue("-1")
|
||||
.primaryKey(usingMySQL, Col.SERVER_ID)
|
||||
.primaryKey(supportsMySQLQueries, Col.SERVER_ID)
|
||||
.toString()
|
||||
);
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ public class SessionsTable extends UserIDTable {
|
|||
@Override
|
||||
public void createTable() throws DBInitException {
|
||||
createTable(TableSqlParser.createTable(this.tableName)
|
||||
.primaryKeyIDColumn(usingMySQL, Col.ID)
|
||||
.primaryKeyIDColumn(supportsMySQLQueries, Col.ID)
|
||||
.column(Col.USER_ID, Sql.INT).notNull()
|
||||
.column(Col.SERVER_ID, Sql.INT).notNull()
|
||||
.column(Col.SESSION_START, Sql.LONG).notNull()
|
||||
|
@ -76,7 +76,7 @@ public class SessionsTable extends UserIDTable {
|
|||
.column(Col.AFK_TIME, Sql.LONG).notNull()
|
||||
.foreignKey(Col.USER_ID, usersTable.getTableName(), UsersTable.Col.ID)
|
||||
.foreignKey(Col.SERVER_ID, serverTable.getTableName(), ServerTable.Col.SERVER_ID)
|
||||
.primaryKey(usingMySQL, Col.ID)
|
||||
.primaryKey(supportsMySQLQueries, Col.ID)
|
||||
.toString()
|
||||
);
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ public abstract class Table {
|
|||
|
||||
protected final String tableName;
|
||||
protected final SQLDB db;
|
||||
protected final boolean usingMySQL;
|
||||
protected final boolean supportsMySQLQueries;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
|
@ -48,7 +48,7 @@ public abstract class Table {
|
|||
public Table(String name, SQLDB db) {
|
||||
this.tableName = name;
|
||||
this.db = db;
|
||||
this.usingMySQL = db != null && db.isUsingMySQL();
|
||||
this.supportsMySQLQueries = db != null && db.getType().supportsMySQLQueries();
|
||||
}
|
||||
|
||||
public abstract void createTable() throws DBInitException;
|
||||
|
@ -118,13 +118,13 @@ public abstract class Table {
|
|||
|
||||
protected void addColumns(String... columnInfo) {
|
||||
for (int i = 0; i < columnInfo.length; i++) {
|
||||
columnInfo[i] = "ALTER TABLE " + tableName + " ADD " + (usingMySQL ? "" : "COLUMN ") + columnInfo[i];
|
||||
columnInfo[i] = "ALTER TABLE " + tableName + " ADD " + (supportsMySQLQueries ? "" : "COLUMN ") + columnInfo[i];
|
||||
}
|
||||
executeUnsafe(columnInfo);
|
||||
}
|
||||
|
||||
protected void removeColumns(String... columnNames) {
|
||||
if (usingMySQL) {
|
||||
if (supportsMySQLQueries) {
|
||||
StringBuilder sqlBuild = new StringBuilder();
|
||||
sqlBuild.append("ALTER TABLE ").append(tableName);
|
||||
for (int i = 0; i < columnNames.length; i++) {
|
||||
|
@ -147,7 +147,7 @@ public abstract class Table {
|
|||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Table table = (Table) o;
|
||||
return usingMySQL == table.usingMySQL &&
|
||||
return supportsMySQLQueries == table.supportsMySQLQueries &&
|
||||
Objects.equal(tableName, table.tableName) &&
|
||||
Objects.equal(db, table.db);
|
||||
}
|
||||
|
@ -162,7 +162,7 @@ public abstract class Table {
|
|||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(tableName, db, usingMySQL);
|
||||
return Objects.hashCode(tableName, db, supportsMySQLQueries);
|
||||
}
|
||||
|
||||
protected boolean execute(ExecStatement statement) {
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package com.djrapitops.plan.system.database.databases.sql.tables;
|
||||
|
||||
import com.djrapitops.plan.api.exceptions.database.DBInitException;
|
||||
import com.djrapitops.plan.system.database.databases.DBType;
|
||||
import com.djrapitops.plan.system.database.databases.sql.SQLDB;
|
||||
import com.djrapitops.plan.system.database.databases.sql.processing.ExecStatement;
|
||||
import com.djrapitops.plan.system.database.databases.sql.processing.QueryStatement;
|
||||
|
@ -51,15 +52,33 @@ public class TransferTable extends Table {
|
|||
super(TABLE_NAME, db);
|
||||
|
||||
serverTable = db.getServerTable();
|
||||
insertStatementNoParts = "REPLACE INTO " + tableName + " (" +
|
||||
Col.SENDER_ID + ", " +
|
||||
Col.EXPIRY + ", " +
|
||||
Col.INFO_TYPE + ", " +
|
||||
Col.EXTRA_VARIABLES + ", " +
|
||||
Col.CONTENT +
|
||||
") VALUES (" +
|
||||
serverTable.statementSelectServerID + ", " +
|
||||
"?, ?, ?, ?)";
|
||||
|
||||
if (db.getType() == DBType.H2) {
|
||||
insertStatementNoParts = "INSERT INTO " + tableName + " (" +
|
||||
Col.SENDER_ID + ", " +
|
||||
Col.EXPIRY + ", " +
|
||||
Col.INFO_TYPE + ", " +
|
||||
Col.EXTRA_VARIABLES + ", " +
|
||||
Col.CONTENT +
|
||||
") VALUES (" +
|
||||
serverTable.statementSelectServerID + ", " +
|
||||
"?, ?, ?, ?)" +
|
||||
" ON DUPLICATE KEY UPDATE" +
|
||||
" " + Col.EXPIRY + "=?," +
|
||||
" " + Col.INFO_TYPE + "=?," +
|
||||
" " + Col.EXTRA_VARIABLES + "=?," +
|
||||
" " + Col.CONTENT + "=?";
|
||||
} else {
|
||||
insertStatementNoParts = "REPLACE INTO " + tableName + " (" +
|
||||
Col.SENDER_ID + ", " +
|
||||
Col.EXPIRY + ", " +
|
||||
Col.INFO_TYPE + ", " +
|
||||
Col.EXTRA_VARIABLES + ", " +
|
||||
Col.CONTENT +
|
||||
") VALUES (" +
|
||||
serverTable.statementSelectServerID + ", " +
|
||||
"?, ?, ?, ?)";
|
||||
}
|
||||
|
||||
selectStatement = "SELECT * FROM " + tableName +
|
||||
" WHERE " + Col.INFO_TYPE + "= ?" +
|
||||
|
@ -75,7 +94,7 @@ public class TransferTable extends Table {
|
|||
.column(Col.EXPIRY, Sql.LONG).notNull().defaultValue("0")
|
||||
.column(Col.INFO_TYPE, Sql.varchar(100)).notNull()
|
||||
.column(Col.EXTRA_VARIABLES, Sql.varchar(255)).defaultValue("''")
|
||||
.column(Col.CONTENT, usingMySQL ? "MEDIUMTEXT" : Sql.varchar(1)) // SQLite does not enforce varchar limits.
|
||||
.column(Col.CONTENT, supportsMySQLQueries ? "MEDIUMTEXT" : Sql.varchar(1)) // SQLite does not enforce varchar limits.
|
||||
.column(Col.PART, Sql.LONG).notNull().defaultValue("0")
|
||||
.foreignKey(Col.SENDER_ID, serverTable.toString(), ServerTable.Col.SERVER_ID)
|
||||
.toString()
|
||||
|
@ -111,11 +130,21 @@ public class TransferTable extends Table {
|
|||
execute(new ExecStatement(insertStatementNoParts) {
|
||||
@Override
|
||||
public void prepare(PreparedStatement statement) throws SQLException {
|
||||
long expiration = System.currentTimeMillis() + TimeUnit.HOURS.toMillis(1L);
|
||||
|
||||
statement.setString(1, getServerUUID().toString());
|
||||
statement.setLong(2, System.currentTimeMillis() + TimeUnit.HOURS.toMillis(1L));
|
||||
statement.setLong(2, expiration);
|
||||
statement.setString(3, "configSettings");
|
||||
statement.setString(4, null);
|
||||
statement.setString(5, encodedSettingString);
|
||||
|
||||
if (db.getType() == DBType.H2) {
|
||||
statement.setLong(6, expiration);
|
||||
statement.setString(7, "configSettings");
|
||||
statement.setString(8, null);
|
||||
statement.setString(9, encodedSettingString);
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ public class UserInfoTable extends UserIDTable {
|
|||
|
||||
public void registerUserInfo(UUID uuid, long registered) {
|
||||
if (!usersTable.isRegistered(uuid)) {
|
||||
usersTable.registerUser(uuid, registered, "Waiting for Update..");
|
||||
usersTable.registerUser(uuid, registered, "waitingForUpdate");
|
||||
}
|
||||
|
||||
String sql = "INSERT INTO " + tableName + " (" +
|
||||
|
@ -187,8 +187,7 @@ public class UserInfoTable extends UserIDTable {
|
|||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
Map<UUID, String> playerNames = usersTable.getPlayerNames();
|
||||
Map<Integer, UUID> uuidsByID = usersTable.getUUIDsByID();
|
||||
Map<Integer, Map.Entry<UUID, String>> uuidsAndNamesByID = usersTable.getUUIDsAndNamesByID();
|
||||
|
||||
String sql = "SELECT * FROM " + tableName +
|
||||
" WHERE " + Col.SERVER_ID + "=?";
|
||||
|
@ -207,8 +206,11 @@ public class UserInfoTable extends UserIDTable {
|
|||
boolean op = set.getBoolean(Col.OP.get());
|
||||
boolean banned = set.getBoolean(Col.BANNED.get());
|
||||
int userId = set.getInt(Col.USER_ID.get());
|
||||
UUID uuid = uuidsByID.get(userId);
|
||||
String name = playerNames.getOrDefault(uuid, "Unknown");
|
||||
|
||||
Map.Entry<UUID, String> uuidNameEntry = uuidsAndNamesByID.get(userId);
|
||||
UUID uuid = uuidNameEntry.getKey();
|
||||
String name = uuidNameEntry.getValue();
|
||||
|
||||
UserInfo info = new UserInfo(uuid, name, registered, op, banned);
|
||||
if (!userInfo.contains(info)) {
|
||||
userInfo.add(info);
|
||||
|
|
|
@ -59,12 +59,12 @@ public class UsersTable extends UserIDTable {
|
|||
@Override
|
||||
public void createTable() throws DBInitException {
|
||||
createTable(TableSqlParser.createTable(tableName)
|
||||
.primaryKeyIDColumn(usingMySQL, Col.ID)
|
||||
.primaryKeyIDColumn(supportsMySQLQueries, Col.ID)
|
||||
.column(Col.UUID, Sql.varchar(36)).notNull().unique()
|
||||
.column(Col.REGISTERED, Sql.LONG).notNull()
|
||||
.column(Col.USER_NAME, Sql.varchar(16)).notNull()
|
||||
.column(Col.TIMES_KICKED, Sql.INT).notNull().defaultValue("0")
|
||||
.primaryKey(usingMySQL, Col.ID)
|
||||
.primaryKey(supportsMySQLQueries, Col.ID)
|
||||
.toString()
|
||||
);
|
||||
}
|
||||
|
@ -261,13 +261,13 @@ public class UsersTable extends UserIDTable {
|
|||
* @return a list of distinct names.
|
||||
*/
|
||||
public List<String> getMatchingNames(String name) {
|
||||
String searchString = "%" + name.toLowerCase() + "%";
|
||||
String searchString = "%" + name + "%";
|
||||
NicknamesTable nicknamesTable = db.getNicknamesTable();
|
||||
String sql = "SELECT DISTINCT " + Col.USER_NAME + " FROM " + tableName +
|
||||
" WHERE " + Col.USER_NAME + " LIKE ?" +
|
||||
" WHERE LOWER(" + Col.USER_NAME + ") LIKE LOWER(?)" +
|
||||
" UNION SELECT DISTINCT " + Col.USER_NAME + " FROM " + tableName +
|
||||
" INNER JOIN " + nicknamesTable + " on " + Col.ID + "=" + nicknamesTable + "." + NicknamesTable.Col.USER_ID +
|
||||
" WHERE " + NicknamesTable.Col.NICKNAME + " LIKE ?";
|
||||
" WHERE LOWER(" + NicknamesTable.Col.NICKNAME + ") LIKE LOWER(?)";
|
||||
|
||||
return query(new QueryStatement<List<String>>(sql, 5000) {
|
||||
@Override
|
||||
|
@ -416,6 +416,30 @@ public class UsersTable extends UserIDTable {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@code UUID} and the name of the player mapped to the user ID
|
||||
*
|
||||
* @return a {@code Map<Integer, Map.Entry<UUID, String>>} where the key is the user ID
|
||||
* and the value is an {@code Map.Entry<UUID, String>>} of the player's {@code UUID} and name
|
||||
*/
|
||||
public Map<Integer, Map.Entry<UUID, String>> getUUIDsAndNamesByID() {
|
||||
String sql = Select.from(tableName, Col.ID, Col.UUID, Col.USER_NAME).toString();
|
||||
return query(new QueryAllStatement<Map<Integer, Map.Entry<UUID, String>>>(sql, 20000) {
|
||||
@Override
|
||||
public Map<Integer, Map.Entry<UUID, String>> processResults(ResultSet set) throws SQLException {
|
||||
Map<Integer, Map.Entry<UUID, String>> uuidsAndNamesByID = new TreeMap<>();
|
||||
while (set.next()) {
|
||||
int id = set.getInt(Col.ID.get());
|
||||
UUID uuid = UUID.fromString(set.getString(Col.UUID.get()));
|
||||
String name = set.getString(Col.USER_NAME.get());
|
||||
uuidsAndNamesByID.put(id, new AbstractMap.SimpleEntry<>(uuid, name));
|
||||
}
|
||||
return uuidsAndNamesByID;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public DataContainer getUserInformation(UUID uuid) {
|
||||
Key<DataContainer> user_data = new Key<>(DataContainer.class, "plan_users_data");
|
||||
DataContainer returnValue = new DataContainer();
|
||||
|
|
|
@ -57,10 +57,10 @@ public class WorldTable extends Table {
|
|||
@Override
|
||||
public void createTable() throws DBInitException {
|
||||
createTable(TableSqlParser.createTable(tableName)
|
||||
.primaryKeyIDColumn(usingMySQL, Col.ID)
|
||||
.primaryKeyIDColumn(supportsMySQLQueries, Col.ID)
|
||||
.column(Col.NAME, Sql.varchar(100)).notNull()
|
||||
.column(Col.SERVER_ID, Sql.INT).notNull()
|
||||
.primaryKey(usingMySQL, Col.ID)
|
||||
.primaryKey(supportsMySQLQueries, Col.ID)
|
||||
.foreignKey(Col.SERVER_ID, ServerTable.TABLE_NAME, ServerTable.Col.SERVER_ID)
|
||||
.toString()
|
||||
);
|
||||
|
|
|
@ -37,7 +37,7 @@ public class TransferTable extends Table {
|
|||
}
|
||||
|
||||
protected void renameTable(String from, String to) {
|
||||
String sql = usingMySQL ?
|
||||
String sql = supportsMySQLQueries ?
|
||||
"RENAME TABLE " + from + " TO " + to :
|
||||
"ALTER TABLE " + from + " RENAME TO " + to;
|
||||
execute(sql);
|
||||
|
|
|
@ -84,6 +84,6 @@ public class PingInsertProcessor implements CriticalRunnable {
|
|||
}
|
||||
|
||||
int getMeanValue(List<DateObj<Integer>> history) {
|
||||
return (int) Median.forInt(history.stream().map(DateObj::getValue).collect(Collectors.toList())).calculate();
|
||||
return (int) Median.forList(history.stream().map(DateObj::getValue).collect(Collectors.toList())).calculate();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package com.djrapitops.plan.system.tasks;
|
||||
|
||||
import com.djrapitops.plan.Plan;
|
||||
import com.djrapitops.plan.ShutdownHook;
|
||||
import com.djrapitops.plan.system.settings.Settings;
|
||||
import com.djrapitops.plan.system.settings.config.PlanConfig;
|
||||
import com.djrapitops.plan.system.tasks.server.BootAnalysisTask;
|
||||
|
@ -40,12 +41,14 @@ import java.util.concurrent.TimeUnit;
|
|||
public class BukkitTaskSystem extends ServerTaskSystem {
|
||||
|
||||
private final Plan plugin;
|
||||
private final ShutdownHook shutdownHook;
|
||||
private final PingCountTimerBukkit pingCountTimer;
|
||||
|
||||
@Inject
|
||||
public BukkitTaskSystem(
|
||||
Plan plugin,
|
||||
PlanConfig config,
|
||||
ShutdownHook shutdownHook,
|
||||
RunnableFactory runnableFactory,
|
||||
PaperTPSCountTimer paperTPSCountTimer,
|
||||
BukkitTPSCountTimer bukkitTPSCountTimer,
|
||||
|
@ -64,6 +67,7 @@ public class BukkitTaskSystem extends ServerTaskSystem {
|
|||
logsFolderCleanTask,
|
||||
playersPageRefreshTask);
|
||||
this.plugin = plugin;
|
||||
this.shutdownHook = shutdownHook;
|
||||
this.pingCountTimer = pingCountTimer;
|
||||
}
|
||||
|
||||
|
@ -78,6 +82,7 @@ public class BukkitTaskSystem extends ServerTaskSystem {
|
|||
} catch (ExceptionInInitializerError | NoClassDefFoundError ignore) {
|
||||
// Running CraftBukkit
|
||||
}
|
||||
shutdownHook.register();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package com.djrapitops.plan.system.tasks;
|
||||
|
||||
import com.djrapitops.plan.PlanSponge;
|
||||
import com.djrapitops.plan.ShutdownHook;
|
||||
import com.djrapitops.plan.system.settings.Settings;
|
||||
import com.djrapitops.plan.system.settings.config.PlanConfig;
|
||||
import com.djrapitops.plan.system.tasks.server.BootAnalysisTask;
|
||||
|
@ -34,12 +35,14 @@ import java.util.concurrent.TimeUnit;
|
|||
public class SpongeTaskSystem extends ServerTaskSystem {
|
||||
|
||||
private final PlanSponge plugin;
|
||||
private final ShutdownHook shutdownHook;
|
||||
private final PingCountTimerSponge pingCountTimer;
|
||||
|
||||
@Inject
|
||||
public SpongeTaskSystem(
|
||||
PlanSponge plugin,
|
||||
PlanConfig config,
|
||||
ShutdownHook shutdownHook,
|
||||
RunnableFactory runnableFactory,
|
||||
SpongeTPSCountTimer spongeTPSCountTimer,
|
||||
BootAnalysisTask bootAnalysisTask,
|
||||
|
@ -57,6 +60,7 @@ public class SpongeTaskSystem extends ServerTaskSystem {
|
|||
logsFolderCleanTask,
|
||||
playersPageRefreshTask);
|
||||
this.plugin = plugin;
|
||||
this.shutdownHook = shutdownHook;
|
||||
this.pingCountTimer = pingCountTimer;
|
||||
}
|
||||
|
||||
|
@ -68,6 +72,8 @@ public class SpongeTaskSystem extends ServerTaskSystem {
|
|||
long startDelay = TimeAmount.toTicks(config.getNumber(Settings.PING_SERVER_ENABLE_DELAY), TimeUnit.SECONDS);
|
||||
runnableFactory.create("PingCountTimer", pingCountTimer)
|
||||
.runTaskTimer(startDelay, PingCountTimerSponge.PING_INTERVAL);
|
||||
|
||||
shutdownHook.register();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -116,7 +116,7 @@ public class BukkitTPSCountTimer extends TPSCountTimer {
|
|||
|
||||
return TPSBuilder.get()
|
||||
.date(now)
|
||||
.tps(0)
|
||||
.tps(tpsN)
|
||||
.playersOnline(playersOnline)
|
||||
.usedCPU(cpuUsage)
|
||||
.usedMemory(usedMemory)
|
||||
|
|
|
@ -122,7 +122,7 @@ public class PingCountTimerBukkit extends AbsRunnable implements Listener {
|
|||
private static boolean isPingMethodAvailable() {
|
||||
try {
|
||||
//Only available in Paper
|
||||
Class.forName("org.bukkit.entity.Player.Spigot").getDeclaredMethod("getPing");
|
||||
Class.forName("org.bukkit.entity.Player$Spigot").getDeclaredMethod("getPing");
|
||||
return true;
|
||||
} catch (ClassNotFoundException | NoSuchMethodException noSuchMethodEx) {
|
||||
return false;
|
||||
|
|
|
@ -27,6 +27,12 @@ import com.googlecode.htmlcompressor.compressor.HtmlCompressor;
|
|||
*/
|
||||
public class PageResponse extends Response {
|
||||
|
||||
private static final HtmlCompressor HTML_COMPRESSOR = new HtmlCompressor();
|
||||
|
||||
static {
|
||||
HTML_COMPRESSOR.setRemoveIntertagSpaces(true);
|
||||
}
|
||||
|
||||
public PageResponse(ResponseType type) {
|
||||
super(type);
|
||||
}
|
||||
|
@ -36,8 +42,6 @@ public class PageResponse extends Response {
|
|||
|
||||
@Override
|
||||
public void setContent(String content) {
|
||||
HtmlCompressor compressor = new HtmlCompressor();
|
||||
compressor.setRemoveIntertagSpaces(true);
|
||||
super.setContent(compressor.compress(content));
|
||||
super.setContent(HTML_COMPRESSOR.compress(content));
|
||||
}
|
||||
}
|
|
@ -16,37 +16,34 @@
|
|||
*/
|
||||
package com.djrapitops.plan.utilities.analysis;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Math utility for calculating the median from Integer values.
|
||||
*
|
||||
* @param <T> a {@code Number} object which implements {@code Comparable} (In general every standard Java number)
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class Median {
|
||||
public class Median<T extends Number & Comparable<? super T>> {
|
||||
|
||||
private final List<Long> values;
|
||||
private final List<T> values;
|
||||
private int size;
|
||||
|
||||
private Median(Collection<Integer> values, int b) {
|
||||
this(values.stream().map(i -> (long) i).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
private Median(List<Long> values) {
|
||||
private Median(List<T> values) {
|
||||
this.values = values;
|
||||
Collections.sort(values);
|
||||
size = values.size();
|
||||
}
|
||||
|
||||
public static Median forInt(Collection<Integer> integers) {
|
||||
return new Median(integers, 0);
|
||||
}
|
||||
|
||||
public static Median forLong(List<Long> longs) {
|
||||
return new Median(longs);
|
||||
/**
|
||||
* Creates a Median instance
|
||||
*
|
||||
* @param list the input list
|
||||
* @return an instance of {@code Median} for the List given
|
||||
*/
|
||||
public static <T extends Number & Comparable<? super T>> Median<T> forList(List<T> list) {
|
||||
return new Median<>(list);
|
||||
}
|
||||
|
||||
public double calculate() {
|
||||
|
@ -62,13 +59,13 @@ public class Median {
|
|||
|
||||
private double calculateEven() {
|
||||
int half = size / 2;
|
||||
double x1 = values.get(half);
|
||||
double x2 = values.get(half - 1);
|
||||
double x1 = values.get(half).doubleValue();
|
||||
double x2 = values.get(half - 1).doubleValue();
|
||||
return (x1 + x2) / 2;
|
||||
}
|
||||
|
||||
private double calculateOdd() {
|
||||
int half = size / 2;
|
||||
return (double) values.get(half);
|
||||
return values.get(half).doubleValue();
|
||||
}
|
||||
}
|
|
@ -28,14 +28,14 @@ import java.text.DecimalFormat;
|
|||
*/
|
||||
public class DecimalFormatter implements Formatter<Double> {
|
||||
|
||||
private final PlanConfig config;
|
||||
private volatile DecimalFormat decimalFormat;
|
||||
|
||||
public DecimalFormatter(PlanConfig config) {
|
||||
this.config = config;
|
||||
decimalFormat = new DecimalFormat(config.getString(Settings.FORMAT_DECIMALS));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apply(Double value) {
|
||||
return new DecimalFormat(config.getString(Settings.FORMAT_DECIMALS)).format(value);
|
||||
return decimalFormat.format(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -227,7 +227,7 @@ public class DebugPage implements Page {
|
|||
.append(" (").append(serverProperties.getVersion());
|
||||
content.append(")<br>");
|
||||
|
||||
content.append("**Database:** ").append(database.getName());
|
||||
content.append("**Database:** ").append(database.getType().getName());
|
||||
content.append("<br><br>");
|
||||
|
||||
Properties properties = System.getProperties();
|
||||
|
|
|
@ -41,7 +41,7 @@ public class BStatsBukkit {
|
|||
if ("CraftBukkit".equals(serverType) && Check.isSpigotAvailable()) {
|
||||
serverType = "Spigot";
|
||||
}
|
||||
String databaseType = plugin.getSystem().getDatabaseSystem().getDatabase().getName();
|
||||
String databaseType = plugin.getSystem().getDatabaseSystem().getDatabase().getType().getName();
|
||||
|
||||
addStringSettingPie("server_type", serverType);
|
||||
addStringSettingPie("database_type", databaseType);
|
||||
|
|
|
@ -46,7 +46,7 @@ public class BStatsBungee {
|
|||
|
||||
private void registerConfigSettingGraphs() {
|
||||
String serverType = plugin.getProxy().getName();
|
||||
String databaseType = database.getName();
|
||||
String databaseType = database.getType().getName();
|
||||
|
||||
addStringSettingPie("server_type", serverType);
|
||||
addStringSettingPie("database_type", databaseType);
|
||||
|
|
|
@ -39,7 +39,7 @@ public class BStatsSponge {
|
|||
|
||||
private void registerConfigSettingGraphs() {
|
||||
String serverType = "Sponge";
|
||||
String databaseType = database.getName();
|
||||
String databaseType = database.getType().getName();
|
||||
|
||||
addStringSettingPie("server_type", serverType);
|
||||
addStringSettingPie("database_type", databaseType);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
name: Plan
|
||||
author: Rsl1122
|
||||
main: com.djrapitops.plan.PlanBungee
|
||||
version: 4.5.0
|
||||
version: 4.5.1
|
||||
softdepend:
|
||||
- AdvancedBan
|
||||
- LiteBans
|
||||
|
|
|
@ -314,22 +314,22 @@ WebServer FAIL - SSL Context || WebServer: SSL Context Initia
|
|||
WebServer FAIL - Store Load || WebServer: SSL Zertifikat konnte nicht geladen werden.
|
||||
Yesterday || 'Gestern'
|
||||
Today || 'Heute'
|
||||
Health - Active Playtime Comparison Decrease || Aktive Spieler haben möglicherweise nichts mehr zu tun (Gespielt ${0} vs ${1}. Das zeigt der Vergleich der letzten zwei Wochen zu den vorherigen 2 Wochen)
|
||||
Health - Active Playtime Comparison Increase || Aktive Spieler haben möglicherweise etwas zu tun (Gespielt ${0} vs ${1}. Das zeigt der Vergleich der letzten zwei Wochen zu den vorherigen 2 Wochen)
|
||||
Health - Active Playtime Comparison Decrease || Aktive Spieler haben möglicherweise nichts mehr zu tun (Vergleich der letzten zwei Wochen: ${0} zu den vorletzten zwei Wochen: ${1}.
|
||||
Health - Active Playtime Comparison Increase || Aktive Spieler haben möglicherweise mehr zu tun (Vergleich der letzten zwei Wochen: ${0} ; zu den vorletzten zwei Wochen: ${1}.
|
||||
Health - Downtime || Gesamte Serverdowntime (Keine Daten) war ${0}
|
||||
Health - New Player Join Players, No || Neue Spieler haben möglicherweise keine anderen Spielern, mit denen sie spielen können. (${0} im Durchschnitt)
|
||||
Health - New Player Join Players, Yes || Neue Spieler haben andere Spieler, mit denen Spielen können. (${0} im Durchschnitt)
|
||||
Health - New Player Stickiness || ${0} von den neuen Spieler sind geblieben (${1}/${2})
|
||||
Health - No Servers Inaccuracy || Es sind keine Bukkit/Sponge-Server verfügbar um Sessiondaten zu sammeln - Diese Messungen sind ungenau.
|
||||
Health - Player Play on Network || Spieler spieltn im Netzwerk:
|
||||
Health - Player Play on Network || Spieler spielten im Netzwerk. Auf den Servern sieht's wie folgt aus:
|
||||
Health - Player Register Server || Spieler wurden auf dem Server pro Tag/Server im Durchschnitt registriert.
|
||||
Health - Player Visit Server || Spieler haben den Server am Tag/Server im Durchschnitt besucht.
|
||||
Health - Regular Activity Change || Anzahl an regelmässigen Spielern beträgt
|
||||
Health - Regular Activity Change || Anzahl an regelmässigen Spielern
|
||||
Health - Regular Activity Change Decrease || verringert um (${0})
|
||||
Health - Regular Activity Change Increase || Erhöht um (+${0})
|
||||
Health - Regular Activity Change Increase || erhöht um (+${0})
|
||||
Health - Regular Activity Change Zero || Bleibt gleich (+${0})
|
||||
Health - Regular Activity Remain || ${0} von den regelmässigen Spielern sind aktiv geblieben (${1}/${2})
|
||||
Health - Single Servers Inaccuracy || Einzelner Bukkit/Sponge um Sessiondaten zu sammelnm.
|
||||
Health - Single Servers Inaccuracy || Einzelner Bukkit/Sponge um Sessiondaten zu sammeln.
|
||||
Health - TPS Above Low Threshold || Durchschnittliche TPS war über der unteren Grenze ${0} in der Zeit.
|
||||
Health - TPS Low Dips || Durchschnittliche TPS war unter der unteren Grenze. (${0}) ${1} male.
|
||||
HTML - FREE_DISK_SPACE || Freier Festplattenspeicher
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
name: Plan
|
||||
author: Rsl1122
|
||||
main: com.djrapitops.plan.Plan
|
||||
version: 4.5.0
|
||||
version: 4.5.1
|
||||
softdepend:
|
||||
- EssentialsX
|
||||
- Towny
|
||||
|
|
|
@ -1,7 +1,18 @@
|
|||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
* This file is part of Player Analytics (Plan).
|
||||
*
|
||||
* Plan is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the LGNU Lesser General Public License v3 as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Plan is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* LGNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.djrapitops.plan.data;
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* This file is part of Player Analytics (Plan).
|
||||
*
|
||||
* Plan is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the LGNU Lesser General Public License v3 as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Plan is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* LGNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.djrapitops.plan.system.database.databases;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Test for the H2 database
|
||||
*
|
||||
* @author Rsl1122, Fuzzlemann
|
||||
* @see SQLiteTest
|
||||
* @since 4.5.1
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.Silent.class)
|
||||
public class H2Test extends CommonDBTest {
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass() throws Exception {
|
||||
handleSetup("H2");
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDownClass() {
|
||||
system.disable();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testH2GetConfigName() {
|
||||
assertEquals("h2", db.getType().getConfigName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testH2GetName() {
|
||||
assertEquals("H2", db.getType().getName());
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -37,7 +37,7 @@ public class PingInsertProcessorTest {
|
|||
public void medianCalculation() {
|
||||
List<Integer> collect = testPing.stream().map(DateObj::getValue).sorted().collect(Collectors.toList());
|
||||
|
||||
int expected = (int) Median.forInt(collect).calculate();
|
||||
int expected = (int) Median.forList(collect).calculate();
|
||||
int result = new PingInsertProcessor(TestConstants.PLAYER_ONE_UUID, TestConstants.SERVER_UUID, new ArrayList<>(), null)
|
||||
.getMeanValue(testPing);
|
||||
|
||||
|
|
|
@ -1,7 +1,18 @@
|
|||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
* This file is part of Player Analytics (Plan).
|
||||
*
|
||||
* Plan is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the LGNU Lesser General Public License v3 as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Plan is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* LGNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.djrapitops.plan.utilities;
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.djrapitops.plan.utilities.analysis;
|
|||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
@ -20,7 +21,7 @@ public class MedianTest {
|
|||
List<Integer> testValues = Arrays.asList(1, 3, 3, 6, 7, 8, 9);
|
||||
Collections.shuffle(testValues);
|
||||
double expected = 6;
|
||||
double result = Median.forInt(testValues).calculate();
|
||||
double result = Median.forList(testValues).calculate();
|
||||
|
||||
assertEquals(expected, result, 0.01);
|
||||
}
|
||||
|
@ -30,7 +31,7 @@ public class MedianTest {
|
|||
List<Integer> testValues = Arrays.asList(1, 2, 3, 4, 5, 6, 8, 9);
|
||||
Collections.shuffle(testValues);
|
||||
double expected = 4.5;
|
||||
double result = Median.forInt(testValues).calculate();
|
||||
double result = Median.forList(testValues).calculate();
|
||||
|
||||
assertEquals(expected, result, 0.01);
|
||||
}
|
||||
|
@ -38,7 +39,7 @@ public class MedianTest {
|
|||
@Test
|
||||
public void empty() {
|
||||
double expected = -1;
|
||||
double result = Median.forInt(Collections.emptyList()).calculate();
|
||||
double result = Median.forList(new ArrayList<Integer>()).calculate();
|
||||
|
||||
assertEquals(expected, result, 0.01);
|
||||
}
|
||||
|
@ -46,7 +47,7 @@ public class MedianTest {
|
|||
@Test
|
||||
public void singleValue() {
|
||||
double expected = 50;
|
||||
double result = Median.forInt(Collections.singletonList((int) expected)).calculate();
|
||||
double result = Median.forList(Collections.singletonList((int) expected)).calculate();
|
||||
|
||||
assertEquals(expected, result, 0.01);
|
||||
}
|
||||
|
@ -55,7 +56,7 @@ public class MedianTest {
|
|||
public void twoValues() {
|
||||
List<Integer> testValues = Arrays.asList(1, 2);
|
||||
double expected = 1.5;
|
||||
double result = Median.forInt(testValues).calculate();
|
||||
double result = Median.forList(testValues).calculate();
|
||||
|
||||
assertEquals(expected, result, 0.01);
|
||||
}
|
||||
|
@ -64,7 +65,7 @@ public class MedianTest {
|
|||
public void overflowOdd() {
|
||||
List<Integer> testValues = Arrays.asList(Integer.MIN_VALUE, 2, Integer.MAX_VALUE);
|
||||
double expected = 2;
|
||||
double result = Median.forInt(testValues).calculate();
|
||||
double result = Median.forList(testValues).calculate();
|
||||
|
||||
assertEquals(expected, result, 0.01);
|
||||
}
|
||||
|
@ -73,7 +74,7 @@ public class MedianTest {
|
|||
public void overflowEven() {
|
||||
List<Integer> testValues = Arrays.asList(Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE);
|
||||
double expected = -0.5;
|
||||
double result = Median.forInt(testValues).calculate();
|
||||
double result = Median.forList(testValues).calculate();
|
||||
|
||||
assertEquals(expected, result, 0.01);
|
||||
}
|
||||
|
@ -82,7 +83,7 @@ public class MedianTest {
|
|||
public void overflowEven2() {
|
||||
List<Integer> testValues = Arrays.asList(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE);
|
||||
double expected = Integer.MAX_VALUE;
|
||||
double result = Median.forInt(testValues).calculate();
|
||||
double result = Median.forList(testValues).calculate();
|
||||
|
||||
assertEquals(expected, result, 0.01);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,18 @@
|
|||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
* This file is part of Player Analytics (Plan).
|
||||
*
|
||||
* Plan is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the LGNU Lesser General Public License v3 as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Plan is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* LGNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.djrapitops.plan.utilities.html;
|
||||
|
||||
|
|
|
@ -1,7 +1,18 @@
|
|||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
* This file is part of Player Analytics (Plan).
|
||||
*
|
||||
* Plan is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the LGNU Lesser General Public License v3 as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Plan is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* LGNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.djrapitops.plan.utilities.html;
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ import com.djrapitops.plugin.logging.debug.DebugLogger;
|
|||
import com.djrapitops.plugin.logging.debug.MemoryDebugLogger;
|
||||
import com.djrapitops.plugin.logging.error.ConsoleErrorLogger;
|
||||
import com.djrapitops.plugin.logging.error.ErrorHandler;
|
||||
import com.djrapitops.plugin.task.thread.ThreadRunnableFactory;
|
||||
import com.djrapitops.plugin.task.RunnableFactory;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.plugin.InvalidDescriptionException;
|
||||
|
@ -23,6 +23,7 @@ import org.bukkit.scheduler.BukkitScheduler;
|
|||
import org.mockito.Mockito;
|
||||
import utilities.TestConstants;
|
||||
import utilities.mocks.objects.TestLogger;
|
||||
import utilities.mocks.objects.TestRunnableFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
|
@ -54,7 +55,7 @@ public class PlanBukkitMocker extends Mocker {
|
|||
doReturn("1.0.0").when(planMock).getVersion();
|
||||
|
||||
TestLogger testLogger = new TestLogger();
|
||||
ThreadRunnableFactory runnableFactory = new ThreadRunnableFactory();
|
||||
RunnableFactory runnableFactory = new TestRunnableFactory();
|
||||
PluginLogger testPluginLogger = new TestPluginLogger();
|
||||
DebugLogger debugLogger = new CombineDebugLogger(new MemoryDebugLogger());
|
||||
ErrorHandler consoleErrorLogger = new ConsoleErrorLogger(testPluginLogger);
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* License is provided in the jar as LICENSE also here:
|
||||
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/LICENSE
|
||||
*/
|
||||
package utilities.mocks.objects;
|
||||
|
||||
import com.djrapitops.plugin.api.TimeAmount;
|
||||
import com.djrapitops.plugin.task.AbsRunnable;
|
||||
import com.djrapitops.plugin.task.PluginRunnable;
|
||||
import com.djrapitops.plugin.task.PluginTask;
|
||||
import com.djrapitops.plugin.task.RunnableFactory;
|
||||
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author Fuzzlemann
|
||||
* @since 4.5.1
|
||||
*/
|
||||
public class TestRunnableFactory extends RunnableFactory {
|
||||
|
||||
private final ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
|
||||
|
||||
@Override
|
||||
protected PluginRunnable createNewRunnable(String name, AbsRunnable absRunnable, long l) {
|
||||
return new PluginRunnable() {
|
||||
@Override
|
||||
public String getTaskName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
absRunnable.cancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTaskId() {
|
||||
return absRunnable.getTaskId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginTask runTask() {
|
||||
absRunnable.run();
|
||||
return createPluginTask(getTaskId(), true, absRunnable::cancel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginTask runTaskAsynchronously() {
|
||||
executorService.submit(absRunnable);
|
||||
return createPluginTask(getTaskId(), false, absRunnable::cancel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginTask runTaskLater(long l) {
|
||||
return runTaskLaterAsynchronously(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginTask runTaskLaterAsynchronously(long l) {
|
||||
executorService.schedule(absRunnable, TimeAmount.ticksToMillis(l), TimeUnit.MILLISECONDS);
|
||||
return createPluginTask(getTaskId(), false, absRunnable::cancel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginTask runTaskTimer(long l, long l1) {
|
||||
return runTaskLaterAsynchronously(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginTask runTaskTimerAsynchronously(long l, long l1) {
|
||||
executorService.scheduleAtFixedRate(absRunnable, TimeAmount.ticksToMillis(l), TimeAmount.ticksToMillis(l1), TimeUnit.MILLISECONDS);
|
||||
return createPluginTask(getTaskId(), false, absRunnable::cancel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTime() {
|
||||
return l;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelAllKnownTasks() {
|
||||
executorService.shutdownNow();
|
||||
}
|
||||
|
||||
private PluginTask createPluginTask(int taskID, boolean sync, ICloseTask closeTask) {
|
||||
return new PluginTask() {
|
||||
@Override
|
||||
public int getTaskId() {
|
||||
return taskID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSync() {
|
||||
return sync;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
if (closeTask != null) {
|
||||
closeTask.close();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private interface ICloseTask {
|
||||
void close();
|
||||
}
|
||||
}
|
Binary file not shown.
|
@ -33,7 +33,7 @@ import java.util.UUID;
|
|||
* @author Rsl1122
|
||||
* @since 4.1.0
|
||||
*/
|
||||
class PlayerHackKickListener implements Listener {
|
||||
public class PlayerHackKickListener implements Listener {
|
||||
|
||||
private final HackerTable hackerTable;
|
||||
private final Processing processing;
|
||||
|
|
|
@ -52,11 +52,11 @@ public class ReactDataTable extends Table {
|
|||
@Override
|
||||
public void createTable() throws DBInitException {
|
||||
createTable(TableSqlParser.createTable(TABLE_NAME)
|
||||
.primaryKey(usingMySQL, Col.ID)
|
||||
.primaryKey(supportsMySQLQueries, Col.ID)
|
||||
.column(Col.DATE, Sql.LONG)
|
||||
.column(Col.SAMPLED_TYPE, Sql.varchar(30))
|
||||
.column(Col.MINUTE_AVERAGE, Sql.DOUBLE)
|
||||
.primaryKeyIDColumn(usingMySQL, Col.ID)
|
||||
.primaryKeyIDColumn(supportsMySQLQueries, Col.ID)
|
||||
.toString());
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ import java.util.UUID;
|
|||
* @author Rsl1122
|
||||
* @since 3.5.0
|
||||
*/
|
||||
class BukkitPlayerVersionListener implements Listener {
|
||||
public class BukkitPlayerVersionListener implements Listener {
|
||||
|
||||
private final ViaAPI viaAPI;
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ import java.util.UUID;
|
|||
* @author Rsl1122
|
||||
* @since 3.5.0
|
||||
*/
|
||||
class BungeePlayerVersionListener implements Listener {
|
||||
public class BungeePlayerVersionListener implements Listener {
|
||||
|
||||
private final ViaAPI viaAPI;
|
||||
|
||||
|
|
|
@ -27,3 +27,4 @@ Documentation can be found [On the Wiki](https://github.com/Rsl1122/Plan-PlayerA
|
|||
- **[jQuery Datatables](https://datatables.net/)** | [MIT License](https://datatables.net/license/mit)
|
||||
- **[Font Awesome Icons](http://fontawesome.io/icons/)** | [SIL Open Font License](http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL)
|
||||
- **[MaxMind GeoIP2](https://www.maxmind.com/en/geoip-demo)** | [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/)
|
||||
- **[H2 Database](http://www.h2database.com)** | [MPL 2.0](http://www.h2database.com/html/license.html#mpl2) or [EPL 1.0](http://www.h2database.com/html/license.html#eclipse_license)
|
||||
|
|
Loading…
Reference in New Issue
Block a user