mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2024-08-21 20:22:45 +02:00
[Merge] Merge apf-3.3.0-merging to apf-3.3.0
This Commit fixes merge and commit issues in the merge.
This commit is contained in:
commit
e6a263e071
11
.github/ISSUE_TEMPLATE
vendored
11
.github/ISSUE_TEMPLATE
vendored
|
@ -1,11 +0,0 @@
|
|||
Instructions for issue reporting:
|
||||
- Write description of the issue
|
||||
- Copy possible errors here, If you're using 4.0.7+ head to `<address>/debug` & copy the information to the ticket.
|
||||
|
||||
For suggestions use any format you want. :)
|
||||
|
||||
----
|
||||
|
||||
**Description of the issue**
|
||||
|
||||
<REPLACE with error / debug-page contents>
|
28
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
28
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
---
|
||||
name: Bug report
|
||||
about: Create a report to help improving the plugin
|
||||
|
||||
---
|
||||
|
||||
### Describe the bug
|
||||
<!-- A clear and concise description of what the bug is. Post possible exceptions further down below -->
|
||||
|
||||
|
||||
|
||||
### Server information
|
||||
<!-- This information can be found on the /debug page (Server version, Plan version, etc.) -->
|
||||
|
||||
|
||||
|
||||
### Exceptions & Other Logs
|
||||
<!-- This information can be found on the /debug page, or from /plugins/Plan/logs if not available -->
|
||||
<!-- Try to only include relevant information -->
|
||||
|
||||
|
||||
|
||||
### Additional information
|
||||
<!-- Any additional information -->
|
||||
|
||||
**Frequency of occurrence**: <>
|
||||
|
||||
**Other:**
|
16
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
16
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
---
|
||||
name: Suggestion
|
||||
about: Feature request or an addition
|
||||
---
|
||||
|
||||
### Is your feature request related to a problem? Please describe.
|
||||
<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->
|
||||
|
||||
### Describe the solution you'd like
|
||||
<!-- A clear and concise description of what you want to happen. -->
|
||||
|
||||
### Describe alternatives you've considered
|
||||
<!-- A clear and concise description of any alternative solutions or features you've considered. -->
|
||||
|
||||
### Additional context
|
||||
<!-- Add any other context or screenshots about the feature request here. -->
|
|
@ -2,14 +2,11 @@ language: java
|
|||
sudo: false
|
||||
install: true
|
||||
before_install:
|
||||
- pwd
|
||||
- cd PlanPluginBridge
|
||||
- ls
|
||||
- mvn install:install-file -Dfile=./PlanPluginBridge-4.4.0.jar -DpomFile=./pom.xml
|
||||
- cd ../Plan
|
||||
- ls
|
||||
install:
|
||||
- mvn install -DskipTests
|
||||
- mvn clean
|
||||
addons:
|
||||
sonarcloud:
|
||||
organization: "player-analytics-plan"
|
||||
|
@ -18,9 +15,8 @@ addons:
|
|||
jdk:
|
||||
- oraclejdk8
|
||||
script:
|
||||
- pwd
|
||||
- 'if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then mvn test; fi'
|
||||
- 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent package sonar:sonar; fi'
|
||||
- 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then mvn org.jacoco:jacoco-maven-plugin:prepare-agent package sonar:sonar; fi'
|
||||
cache:
|
||||
directories:
|
||||
- '$HOME/.m2/repository'
|
||||
|
|
|
@ -90,14 +90,11 @@
|
|||
<relocation>
|
||||
<pattern>org.slf4j</pattern>
|
||||
<shadedPattern>plan.org.slf4j</shadedPattern>
|
||||
<excludes>
|
||||
<exclude>org.slf4j.Logger</exclude>
|
||||
</excludes>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.bstats</pattern>
|
||||
<shadedPattern>com.djrapitops.plan.utilities.metrics</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.bstats</pattern>
|
||||
<shadedPattern>com.djrapitops.plan.utilities.metrics</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
@ -156,14 +153,14 @@
|
|||
<id>sponge-repo</id>
|
||||
<url>https://repo.spongepowered.org/maven</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>
|
||||
</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>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
|
@ -316,10 +313,6 @@
|
|||
<artifactId>guice</artifactId>
|
||||
<groupId>com.google.inject</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>caffeine</artifactId>
|
||||
<groupId>com.github.ben-manes.caffeine</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>guava</artifactId>
|
||||
<groupId>com.github.ben-manes.caffeine</groupId>
|
||||
|
@ -366,12 +359,12 @@
|
|||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.imaginarycode.minecraft</groupId>
|
||||
<artifactId>RedisBungee</artifactId>
|
||||
<version>0.3.8-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.imaginarycode.minecraft</groupId>
|
||||
<artifactId>RedisBungee</artifactId>
|
||||
<version>0.3.8-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
|
@ -395,7 +388,7 @@
|
|||
<dependency>
|
||||
<groupId>org.xerial</groupId>
|
||||
<artifactId>sqlite-jdbc</artifactId>
|
||||
<version>3.23.1</version>
|
||||
<version>3.23.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
32
Plan/pom.xml
32
Plan/pom.xml
|
@ -24,6 +24,10 @@
|
|||
<id>sponge-repo</id>
|
||||
<url>https://repo.spongepowered.org/maven</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>velocity-repo</id>
|
||||
<url>https://repo.velocitypowered.com/snapshots/</url>
|
||||
</repository>
|
||||
<!-- RedisBungee Repository -->
|
||||
<repository>
|
||||
<id>md_5-snapshots</id>
|
||||
|
@ -79,6 +83,14 @@
|
|||
<type>jar</type>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- Velocity -->
|
||||
<dependency>
|
||||
<groupId>com.velocitypowered</groupId>
|
||||
<artifactId>velocity-api</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<type>jar</type>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- SpongePowered -->
|
||||
<dependency>
|
||||
<groupId>org.spongepowered</groupId>
|
||||
|
@ -112,7 +124,7 @@
|
|||
<dependency>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
<artifactId>HikariCP</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.2.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Geo IP -->
|
||||
|
@ -122,6 +134,13 @@
|
|||
<version>2.9.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Cache with invalidation -->
|
||||
<dependency>
|
||||
<groupId>com.github.ben-manes.caffeine</groupId>
|
||||
<artifactId>caffeine</artifactId>
|
||||
<version>2.6.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Metrics -->
|
||||
<dependency>
|
||||
<groupId>org.bstats</groupId>
|
||||
|
@ -139,6 +158,13 @@
|
|||
<version>1.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- HTML Compression -->
|
||||
<dependency>
|
||||
<groupId>com.googlecode.htmlcompressor</groupId>
|
||||
<artifactId>htmlcompressor</artifactId>
|
||||
<version>1.5.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Mockito (Test Dependency) -->
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
|
@ -236,6 +262,7 @@
|
|||
<exclude>org.mockito:*</exclude>
|
||||
<exclude>org.easymock:*</exclude>
|
||||
<exclude>junit:*</exclude>
|
||||
<!--<exclued>org.slf4j:*</exclued>-->
|
||||
</excludes>
|
||||
</artifactSet>
|
||||
<relocations>
|
||||
|
@ -261,9 +288,6 @@
|
|||
<relocation>
|
||||
<pattern>org.slf4j</pattern>
|
||||
<shadedPattern>plan.org.slf4j</shadedPattern>
|
||||
<excludes>
|
||||
<exclude>org.slf4j.Logger</exclude>
|
||||
</excludes>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.bstats</pattern>
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.spongepowered.api.config.ConfigDir;
|
|||
import org.spongepowered.api.event.Listener;
|
||||
import org.spongepowered.api.event.game.state.GameStartedServerEvent;
|
||||
import org.spongepowered.api.event.game.state.GameStoppingServerEvent;
|
||||
import org.spongepowered.api.plugin.Dependency;
|
||||
import org.spongepowered.api.plugin.Plugin;
|
||||
|
||||
import javax.inject.Named;
|
||||
|
@ -80,7 +81,17 @@ class SpongePlanModule {
|
|||
}
|
||||
}
|
||||
|
||||
@Plugin(id = "plan", name = "Plan", version = "4.4.3", description = "Player Analytics Plugin by Rsl1122", authors = {"Rsl1122"})
|
||||
@Plugin(
|
||||
id = "plan",
|
||||
name = "Plan",
|
||||
version = "4.4.7",
|
||||
description = "Player Analytics Plugin by Rsl1122",
|
||||
authors = {"Rsl1122"},
|
||||
dependencies = {
|
||||
@Dependency(id = "nucleus", optional = true),
|
||||
@Dependency(id = "luckperms", optional = true)
|
||||
}
|
||||
)
|
||||
public class PlanSponge extends SpongePlugin implements PlanPlugin {
|
||||
|
||||
@Inject
|
||||
|
|
136
Plan/src/main/java/com/djrapitops/plan/PlanVelocity.java
Normal file
136
Plan/src/main/java/com/djrapitops/plan/PlanVelocity.java
Normal file
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* License is provided in the jar as LICENSE also here:
|
||||
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/LICENSE
|
||||
*/
|
||||
package com.djrapitops.plan;
|
||||
|
||||
import com.djrapitops.plan.api.exceptions.EnableException;
|
||||
import com.djrapitops.plan.command.PlanVelocityCommand;
|
||||
import com.djrapitops.plan.system.VelocitySystem;
|
||||
import com.djrapitops.plan.system.locale.Locale;
|
||||
import com.djrapitops.plan.system.locale.lang.PluginLang;
|
||||
import com.djrapitops.plan.system.settings.theme.PlanColorScheme;
|
||||
import com.djrapitops.plugin.StaticHolder;
|
||||
import com.djrapitops.plugin.VelocityPlugin;
|
||||
import com.djrapitops.plugin.api.Benchmark;
|
||||
import com.djrapitops.plugin.api.utility.log.DebugLog;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
import com.djrapitops.plugin.settings.ColorScheme;
|
||||
import com.google.inject.Inject;
|
||||
import com.velocitypowered.api.plugin.Plugin;
|
||||
import com.velocitypowered.api.plugin.annotation.DataDirectory;
|
||||
import com.velocitypowered.api.proxy.ProxyServer;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Path;
|
||||
|
||||
/**
|
||||
* Velocity Main class.
|
||||
*
|
||||
* Based on the PlanBungee class
|
||||
*
|
||||
* @author MicleBrick
|
||||
*/
|
||||
@Plugin(id = "plan", name = "Plan", version = "4.4.6", description = "Player Analytics Plugin by Rsl1122", authors = {"Rsl1122"})
|
||||
public class PlanVelocity extends VelocityPlugin implements PlanPlugin {
|
||||
|
||||
private VelocitySystem system;
|
||||
private Locale locale;
|
||||
|
||||
public static PlanVelocity getInstance() {
|
||||
return (PlanVelocity) StaticHolder.getInstance(PlanVelocity.class);
|
||||
}
|
||||
|
||||
@Inject
|
||||
@DataDirectory
|
||||
private Path dataFolderPath;
|
||||
|
||||
@Override
|
||||
public File getDataFolder() {
|
||||
return dataFolderPath.toFile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
super.onEnable();
|
||||
try {
|
||||
system = new VelocitySystem(this);
|
||||
locale = system.getLocaleSystem().getLocale();
|
||||
system.enable();
|
||||
|
||||
Log.info(locale.getString(PluginLang.ENABLED));
|
||||
} catch (AbstractMethodError e) {
|
||||
Log.error("Plugin ran into AbstractMethodError - Server restart is required. Likely cause is updating the jar without a restart.");
|
||||
} catch (EnableException e) {
|
||||
Log.error("----------------------------------------");
|
||||
Log.error("Error: " + e.getMessage());
|
||||
Log.error("----------------------------------------");
|
||||
Log.error("Plugin Failed to Initialize Correctly. If this issue is caused by config settings you can use /planvelocity reload");
|
||||
onDisable();
|
||||
} catch (Exception e) {
|
||||
getLogger().error(this.getClass().getSimpleName() + "-v" + getVersion(), e);
|
||||
Log.error("Plugin Failed to Initialize Correctly. If this issue is caused by config settings you can use /planvelocity reload");
|
||||
Log.error("This error should be reported at https://github.com/Rsl1122/Plan-PlayerAnalytics/issues");
|
||||
onDisable();
|
||||
}
|
||||
registerCommand("planvelocity", new PlanVelocityCommand(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
system.disable();
|
||||
|
||||
Log.info(locale.getString(PluginLang.DISABLED));
|
||||
Benchmark.pluginDisabled(PlanVelocity.class);
|
||||
DebugLog.pluginDisabled(PlanVelocity.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return getClass().getAnnotation(Plugin.class).version();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onReload() {
|
||||
// Nothing to be done, systems are disabled
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getResource(String resource) {
|
||||
return getClass().getResourceAsStream(resource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ColorScheme getColorScheme() {
|
||||
return PlanColorScheme.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VelocitySystem getSystem() {
|
||||
return system;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReloading() {
|
||||
return reloading;
|
||||
}
|
||||
|
||||
@Inject
|
||||
private ProxyServer proxy;
|
||||
|
||||
@Override
|
||||
public ProxyServer getProxy() {
|
||||
return proxy;
|
||||
}
|
||||
|
||||
@Inject
|
||||
private Logger logger;
|
||||
|
||||
@Override
|
||||
protected Logger getLogger() {
|
||||
return logger;
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ package com.djrapitops.plan.command;
|
|||
import com.djrapitops.plan.command.commands.*;
|
||||
import com.djrapitops.plan.command.commands.manage.ManageConDebugCommand;
|
||||
import com.djrapitops.plan.command.commands.manage.ManageRawDataCommand;
|
||||
import com.djrapitops.plan.command.commands.manage.ManageUninstalledCommand;
|
||||
import com.djrapitops.plan.system.locale.Locale;
|
||||
import com.djrapitops.plan.system.locale.lang.DeepHelpLang;
|
||||
import com.djrapitops.plan.system.settings.Permissions;
|
||||
|
@ -36,6 +37,7 @@ public class PlanBungeeCommand extends TreeCmdNode {
|
|||
private final BungeeSetupToggleCommand setupToggleCommand;
|
||||
private final ReloadCommand reloadCommand;
|
||||
private final DisableCommand disableCommand;
|
||||
private final ManageUninstalledCommand uninstalledCommand;
|
||||
|
||||
private boolean commandsRegistered;
|
||||
|
||||
|
@ -54,10 +56,12 @@ public class PlanBungeeCommand extends TreeCmdNode {
|
|||
ManageConDebugCommand conDebugCommand,
|
||||
ManageRawDataCommand rawDataCommand,
|
||||
BungeeSetupToggleCommand setupToggleCommand,
|
||||
ManageUninstalledCommand uninstalledCommand,
|
||||
ReloadCommand reloadCommand,
|
||||
DisableCommand disableCommand
|
||||
) {
|
||||
super("planbungee", Permissions.MANAGE.getPermission(), CommandType.CONSOLE, null);
|
||||
this.uninstalledCommand = uninstalledCommand;
|
||||
|
||||
commandsRegistered = false;
|
||||
|
||||
|
@ -94,6 +98,7 @@ public class PlanBungeeCommand extends TreeCmdNode {
|
|||
conDebugCommand,
|
||||
rawDataCommand,
|
||||
setupToggleCommand,
|
||||
uninstalledCommand,
|
||||
reloadCommand,
|
||||
disableCommand
|
||||
};
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
package com.djrapitops.plan.command;
|
||||
|
||||
import com.djrapitops.plan.command.commands.*;
|
||||
import com.djrapitops.plan.command.commands.manage.ManageConDebugCommand;
|
||||
import com.djrapitops.plan.command.commands.manage.ManageRawDataCommand;
|
||||
import com.djrapitops.plan.command.commands.manage.ManageUninstalledCommand;
|
||||
import com.djrapitops.plan.system.locale.Locale;
|
||||
import com.djrapitops.plan.system.locale.lang.DeepHelpLang;
|
||||
import com.djrapitops.plan.system.settings.Permissions;
|
||||
import com.djrapitops.plugin.command.ColorScheme;
|
||||
import com.djrapitops.plugin.command.CommandNode;
|
||||
import com.djrapitops.plugin.command.CommandType;
|
||||
import com.djrapitops.plugin.command.TreeCmdNode;
|
||||
import dagger.Lazy;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
/**
|
||||
* TreeCommand for the /plan command, and all subcommands.
|
||||
* <p>
|
||||
* Uses the Abstract Plugin Framework for easier command management.
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Singleton
|
||||
public class PlanBungeeCommand extends TreeCmdNode {
|
||||
|
||||
private final NetworkCommand networkCommand;
|
||||
private final ListServersCommand listServersCommand;
|
||||
private final ListPlayersCommand listPlayersCommand;
|
||||
private final RegisterCommand registerCommand;
|
||||
private final Lazy<WebUserCommand> webUserCommand;
|
||||
private final ManageConDebugCommand conDebugCommand;
|
||||
private final ManageRawDataCommand rawDataCommand;
|
||||
private final BungeeSetupToggleCommand setupToggleCommand;
|
||||
private final ReloadCommand reloadCommand;
|
||||
private final DisableCommand disableCommand;
|
||||
private final ManageUninstalledCommand uninstalledCommand;
|
||||
|
||||
private boolean commandsRegistered;
|
||||
|
||||
@Inject
|
||||
public PlanBungeeCommand(
|
||||
ColorScheme colorScheme,
|
||||
Locale locale,
|
||||
// Group 1
|
||||
NetworkCommand networkCommand,
|
||||
ListServersCommand listServersCommand,
|
||||
ListPlayersCommand listPlayersCommand,
|
||||
// Group 2
|
||||
RegisterCommand registerCommand,
|
||||
Lazy<WebUserCommand> webUserCommand,
|
||||
// Group 3
|
||||
ManageConDebugCommand conDebugCommand,
|
||||
ManageRawDataCommand rawDataCommand,
|
||||
BungeeSetupToggleCommand setupToggleCommand,
|
||||
ManageUninstalledCommand uninstalledCommand,
|
||||
ReloadCommand reloadCommand,
|
||||
DisableCommand disableCommand
|
||||
) {
|
||||
super("planbungee", Permissions.MANAGE.getPermission(), CommandType.CONSOLE, null);
|
||||
this.uninstalledCommand = uninstalledCommand;
|
||||
|
||||
commandsRegistered = false;
|
||||
|
||||
this.networkCommand = networkCommand;
|
||||
this.listServersCommand = listServersCommand;
|
||||
this.listPlayersCommand = listPlayersCommand;
|
||||
this.registerCommand = registerCommand;
|
||||
this.webUserCommand = webUserCommand;
|
||||
this.conDebugCommand = conDebugCommand;
|
||||
this.rawDataCommand = rawDataCommand;
|
||||
this.setupToggleCommand = setupToggleCommand;
|
||||
this.reloadCommand = reloadCommand;
|
||||
this.disableCommand = disableCommand;
|
||||
|
||||
setColorScheme(colorScheme);
|
||||
setInDepthHelp(locale.getArray(DeepHelpLang.PLAN));
|
||||
}
|
||||
|
||||
public void registerCommands() {
|
||||
if (commandsRegistered) {
|
||||
return;
|
||||
}
|
||||
|
||||
CommandNode[] analyticsGroup = {
|
||||
networkCommand,
|
||||
listServersCommand,
|
||||
listPlayersCommand
|
||||
};
|
||||
CommandNode[] webGroup = {
|
||||
registerCommand,
|
||||
webUserCommand.get()
|
||||
};
|
||||
CommandNode[] manageGroup = {
|
||||
conDebugCommand,
|
||||
rawDataCommand,
|
||||
setupToggleCommand,
|
||||
uninstalledCommand,
|
||||
reloadCommand,
|
||||
disableCommand
|
||||
};
|
||||
setNodeGroups(analyticsGroup, webGroup, manageGroup);
|
||||
commandsRegistered = true;
|
||||
}
|
||||
}
|
|
@ -2,7 +2,6 @@ package com.djrapitops.plan.command.commands.manage;
|
|||
|
||||
import com.djrapitops.plan.api.exceptions.database.DBOpException;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plan.system.info.connection.ConnectionSystem;
|
||||
import com.djrapitops.plan.system.info.server.Server;
|
||||
import com.djrapitops.plan.system.info.server.ServerInfo;
|
||||
import com.djrapitops.plan.system.locale.Locale;
|
||||
|
@ -90,7 +89,7 @@ public class ManageUninstalledCommand extends CommandNode {
|
|||
}
|
||||
|
||||
private Optional<Server> getServer(String[] args) {
|
||||
if (args.length >= 1 && connectionSystem.isServerAvailable()) {
|
||||
if (args.length >= 1) {
|
||||
Map<UUID, Server> bukkitServers = database.fetch().getBukkitServers();
|
||||
String serverIdentifier = getGivenIdentifier(args);
|
||||
for (Map.Entry<UUID, Server> entry : bukkitServers.entrySet()) {
|
||||
|
|
|
@ -152,11 +152,11 @@ public class Session extends DataContainer implements DateHolder {
|
|||
}
|
||||
|
||||
public void setWorldTimes(WorldTimes worldTimes) {
|
||||
putRawData(SessionKeys.WORLD_TIMES, worldTimes);
|
||||
this.worldTimes = worldTimes;
|
||||
}
|
||||
|
||||
public void setPlayerKills(List<PlayerKill> playerKills) {
|
||||
putRawData(SessionKeys.PLAYER_KILLS, playerKills);
|
||||
this.playerKills = playerKills;
|
||||
}
|
||||
|
||||
public boolean isFetchedFromDB() {
|
||||
|
@ -180,14 +180,8 @@ public class Session extends DataContainer implements DateHolder {
|
|||
getValue(SessionKeys.END).orElse(-1L).equals(session.getValue(SessionKeys.END).orElse(-1L)) &&
|
||||
mobKills == session.mobKills &&
|
||||
deaths == session.deaths &&
|
||||
Objects.equals(
|
||||
getValue(SessionKeys.WORLD_TIMES).orElse(null),
|
||||
session.getValue(SessionKeys.WORLD_TIMES).orElse(null)
|
||||
) &&
|
||||
Objects.equals(
|
||||
getValue(SessionKeys.PLAYER_KILLS).orElse(new ArrayList<>()),
|
||||
session.getValue(SessionKeys.PLAYER_KILLS).orElse(new ArrayList<>())
|
||||
);
|
||||
Objects.equals(playerKills, session.playerKills) &&
|
||||
Objects.equals(worldTimes, session.worldTimes);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -203,7 +197,7 @@ public class Session extends DataContainer implements DateHolder {
|
|||
return worldTimes;
|
||||
}
|
||||
|
||||
private List<PlayerKill> getPlayerKills() {
|
||||
public List<PlayerKill> getPlayerKills() {
|
||||
return playerKills;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
package com.djrapitops.plan.data.element;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
|
@ -25,18 +27,18 @@ import java.util.TreeMap;
|
|||
*/
|
||||
public class InspectContainer {
|
||||
|
||||
protected TreeMap<String, String> values;
|
||||
protected List<String> values;
|
||||
protected TreeMap<String, String> html;
|
||||
protected TreeMap<String, TableContainer> tables;
|
||||
|
||||
public InspectContainer() {
|
||||
values = new TreeMap<>();
|
||||
values = new ArrayList<>();
|
||||
html = new TreeMap<>();
|
||||
tables = new TreeMap<>();
|
||||
}
|
||||
|
||||
public final void addValue(String label, Serializable value) {
|
||||
values.put(label, value.toString());
|
||||
values.add(label + ": " + value.toString());
|
||||
}
|
||||
|
||||
public final void addHtml(String key, String html) {
|
||||
|
@ -52,8 +54,8 @@ public class InspectContainer {
|
|||
|
||||
if (!values.isEmpty()) {
|
||||
parsed.append("<div class=\"body\">");
|
||||
for (Map.Entry<String, String> entry : values.entrySet()) {
|
||||
parsed.append("<p>").append(entry.getKey()).append(": ").append(entry.getValue()).append("</p>");
|
||||
for (String value : values) {
|
||||
parsed.append("<p>").append(value).append("</p>");
|
||||
}
|
||||
parsed.append("</div>");
|
||||
}
|
||||
|
|
|
@ -90,9 +90,9 @@ public class AnalysisContainer extends DataContainer {
|
|||
}
|
||||
|
||||
private void addAnalysisSuppliers() {
|
||||
putSupplier(AnalysisKeys.SESSIONS_MUTATOR, () -> SessionsMutator.forContainer(serverContainer));
|
||||
putSupplier(AnalysisKeys.TPS_MUTATOR, () -> TPSMutator.forContainer(serverContainer));
|
||||
putSupplier(AnalysisKeys.PLAYERS_MUTATOR, () -> PlayersMutator.forContainer(serverContainer));
|
||||
putCachingSupplier(AnalysisKeys.SESSIONS_MUTATOR, () -> SessionsMutator.forContainer(serverContainer));
|
||||
putCachingSupplier(AnalysisKeys.TPS_MUTATOR, () -> TPSMutator.forContainer(serverContainer));
|
||||
putCachingSupplier(AnalysisKeys.PLAYERS_MUTATOR, () -> PlayersMutator.forContainer(serverContainer));
|
||||
|
||||
addConstants();
|
||||
addPlayerSuppliers();
|
||||
|
@ -123,7 +123,7 @@ public class AnalysisContainer extends DataContainer {
|
|||
}
|
||||
|
||||
private void addServerProperties() {
|
||||
putSupplier(AnalysisKeys.SERVER_NAME, () ->
|
||||
putCachingSupplier(AnalysisKeys.SERVER_NAME, () ->
|
||||
getUnsafe(serverNames).getOrDefault(serverContainer.getUnsafe(ServerKeys.SERVER_UUID), "Plan")
|
||||
);
|
||||
|
||||
|
@ -147,7 +147,7 @@ public class AnalysisContainer extends DataContainer {
|
|||
}
|
||||
|
||||
private void addPlayerSuppliers() {
|
||||
putSupplier(AnalysisKeys.PLAYER_NAMES, () -> serverContainer.getValue(ServerKeys.PLAYERS).orElse(new ArrayList<>())
|
||||
putCachingSupplier(AnalysisKeys.PLAYER_NAMES, () -> serverContainer.getValue(ServerKeys.PLAYERS).orElse(new ArrayList<>())
|
||||
.stream().collect(Collectors.toMap(
|
||||
p -> p.getUnsafe(PlayerKeys.UUID), p -> p.getValue(PlayerKeys.NAME).orElse("?"))
|
||||
)
|
||||
|
@ -190,22 +190,22 @@ public class AnalysisContainer extends DataContainer {
|
|||
Key<PlayersMutator> uniqueDay = new Key<>(PlayersMutator.class, "UNIQUE_DAY");
|
||||
Key<PlayersMutator> uniqueWeek = new Key<>(PlayersMutator.class, "UNIQUE_WEEK");
|
||||
Key<PlayersMutator> uniqueMonth = new Key<>(PlayersMutator.class, "UNIQUE_MONTH");
|
||||
putSupplier(newDay, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)
|
||||
putCachingSupplier(newDay, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)
|
||||
.filterRegisteredBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_DAY_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
|
||||
);
|
||||
putSupplier(newWeek, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)
|
||||
putCachingSupplier(newWeek, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)
|
||||
.filterRegisteredBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_WEEK_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
|
||||
);
|
||||
putSupplier(newMonth, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)
|
||||
putCachingSupplier(newMonth, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)
|
||||
.filterRegisteredBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_MONTH_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
|
||||
);
|
||||
putSupplier(uniqueDay, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)
|
||||
putCachingSupplier(uniqueDay, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)
|
||||
.filterPlayedBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_DAY_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
|
||||
);
|
||||
putSupplier(uniqueWeek, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)
|
||||
putCachingSupplier(uniqueWeek, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)
|
||||
.filterPlayedBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_WEEK_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
|
||||
);
|
||||
putSupplier(uniqueMonth, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)
|
||||
putCachingSupplier(uniqueMonth, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)
|
||||
.filterPlayedBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_MONTH_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
|
||||
);
|
||||
|
||||
|
@ -231,7 +231,7 @@ public class AnalysisContainer extends DataContainer {
|
|||
|
||||
Key<Integer> retentionDay = new Key<>(Integer.class, "RETENTION_DAY");
|
||||
// compareAndFindThoseLikelyToBeRetained can throw exception.
|
||||
putSupplier(retentionDay, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR).compareAndFindThoseLikelyToBeRetained(
|
||||
putCachingSupplier(retentionDay, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR).compareAndFindThoseLikelyToBeRetained(
|
||||
getUnsafe(newDay).all(), getUnsafe(AnalysisKeys.ANALYSIS_TIME_MONTH_AGO),
|
||||
getUnsafe(AnalysisKeys.PLAYERS_ONLINE_RESOLVER),
|
||||
config.getNumber(Settings.ACTIVE_PLAY_THRESHOLD),
|
||||
|
@ -245,13 +245,13 @@ public class AnalysisContainer extends DataContainer {
|
|||
return 0;
|
||||
}
|
||||
});
|
||||
putSupplier(AnalysisKeys.PLAYERS_RETAINED_WEEK, () ->
|
||||
putCachingSupplier(AnalysisKeys.PLAYERS_RETAINED_WEEK, () ->
|
||||
getUnsafe(newWeek).filterRetained(
|
||||
getUnsafe(AnalysisKeys.ANALYSIS_TIME_WEEK_AGO),
|
||||
getUnsafe(AnalysisKeys.ANALYSIS_TIME)
|
||||
).count()
|
||||
);
|
||||
putSupplier(AnalysisKeys.PLAYERS_RETAINED_MONTH, () ->
|
||||
putCachingSupplier(AnalysisKeys.PLAYERS_RETAINED_MONTH, () ->
|
||||
getUnsafe(newMonth).filterRetained(
|
||||
getUnsafe(AnalysisKeys.ANALYSIS_TIME_MONTH_AGO),
|
||||
getUnsafe(AnalysisKeys.ANALYSIS_TIME)
|
||||
|
@ -283,8 +283,8 @@ public class AnalysisContainer extends DataContainer {
|
|||
|
||||
private void addSessionSuppliers() {
|
||||
Key<SessionAccordion> sessionAccordion = new Key<>(SessionAccordion.class, "SESSION_ACCORDION");
|
||||
putSupplier(serverNames, () -> database.fetch().getServerNames());
|
||||
putSupplier(sessionAccordion, () -> accordions.serverSessionAccordion(
|
||||
putCachingSupplier(serverNames, () -> database.fetch().getServerNames());
|
||||
putCachingSupplier(sessionAccordion, () -> accordions.serverSessionAccordion(
|
||||
getUnsafe(AnalysisKeys.SESSIONS_MUTATOR).all(),
|
||||
getSupplier(serverNames),
|
||||
() -> getUnsafe(AnalysisKeys.PLAYER_NAMES)
|
||||
|
@ -325,13 +325,13 @@ public class AnalysisContainer extends DataContainer {
|
|||
Key<SessionsMutator> sessionsDay = new Key<>(SessionsMutator.class, "SESSIONS_DAY");
|
||||
Key<SessionsMutator> sessionsWeek = new Key<>(SessionsMutator.class, "SESSIONS_WEEK");
|
||||
Key<SessionsMutator> sessionsMonth = new Key<>(SessionsMutator.class, "SESSIONS_MONTH");
|
||||
putSupplier(sessionsDay, () -> getUnsafe(AnalysisKeys.SESSIONS_MUTATOR)
|
||||
putCachingSupplier(sessionsDay, () -> getUnsafe(AnalysisKeys.SESSIONS_MUTATOR)
|
||||
.filterSessionsBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_DAY_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
|
||||
);
|
||||
putSupplier(sessionsWeek, () -> getUnsafe(AnalysisKeys.SESSIONS_MUTATOR)
|
||||
putCachingSupplier(sessionsWeek, () -> getUnsafe(AnalysisKeys.SESSIONS_MUTATOR)
|
||||
.filterSessionsBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_WEEK_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
|
||||
);
|
||||
putSupplier(sessionsMonth, () -> getUnsafe(AnalysisKeys.SESSIONS_MUTATOR)
|
||||
putCachingSupplier(sessionsMonth, () -> getUnsafe(AnalysisKeys.SESSIONS_MUTATOR)
|
||||
.filterSessionsBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_MONTH_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
|
||||
);
|
||||
|
||||
|
@ -344,7 +344,7 @@ public class AnalysisContainer extends DataContainer {
|
|||
|
||||
private void addGraphSuppliers() {
|
||||
Key<WorldPie> worldPie = new Key<>(WorldPie.class, "WORLD_PIE");
|
||||
putSupplier(worldPie, () -> graphs.pie().worldPie(
|
||||
putCachingSupplier(worldPie, () -> graphs.pie().worldPie(
|
||||
serverContainer.getValue(ServerKeys.WORLD_TIMES).orElse(new WorldTimes(new HashMap<>()))
|
||||
));
|
||||
putSupplier(AnalysisKeys.WORLD_PIE_SERIES, () -> getUnsafe(worldPie).toHighChartsSeries());
|
||||
|
@ -361,12 +361,12 @@ public class AnalysisContainer extends DataContainer {
|
|||
graphs.special().worldMap(getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)).toHighChartsSeries()
|
||||
);
|
||||
Key<BarGraph> geolocationBarChart = new Key<>(BarGraph.class, "GEOLOCATION_BAR_GRAPH");
|
||||
putSupplier(geolocationBarChart, () -> graphs.bar().geolocationBarGraph(getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)));
|
||||
putCachingSupplier(geolocationBarChart, () -> graphs.bar().geolocationBarGraph(getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)));
|
||||
putSupplier(AnalysisKeys.COUNTRY_CATEGORIES, () -> getUnsafe(geolocationBarChart).toHighChartsCategories());
|
||||
putSupplier(AnalysisKeys.COUNTRY_SERIES, () -> getUnsafe(geolocationBarChart).toHighChartsSeries());
|
||||
|
||||
Key<PingGraph> pingGraph = new Key<>(PingGraph.class, "PING_GRAPH");
|
||||
putSupplier(pingGraph, () ->
|
||||
putCachingSupplier(pingGraph, () ->
|
||||
graphs.line().pingGraph(PingMutator.forContainer(serverContainer).mutateToByMinutePings().all())
|
||||
);
|
||||
putSupplier(AnalysisKeys.AVG_PING_SERIES, () -> getUnsafe(pingGraph).toAvgSeries());
|
||||
|
@ -379,9 +379,9 @@ public class AnalysisContainer extends DataContainer {
|
|||
getUnsafe(AnalysisKeys.NEW_PLAYERS_PER_DAY)
|
||||
).toCalendarSeries());
|
||||
|
||||
putSupplier(AnalysisKeys.ACTIVITY_DATA, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR).toActivityDataMap(getUnsafe(AnalysisKeys.ANALYSIS_TIME), config.getNumber(Settings.ACTIVE_PLAY_THRESHOLD), config.getNumber(Settings.ACTIVE_LOGIN_THRESHOLD)));
|
||||
putCachingSupplier(AnalysisKeys.ACTIVITY_DATA, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR).toActivityDataMap(getUnsafe(AnalysisKeys.ANALYSIS_TIME), config.getNumber(Settings.ACTIVE_PLAY_THRESHOLD), config.getNumber(Settings.ACTIVE_LOGIN_THRESHOLD)));
|
||||
Key<StackGraph> activityStackGraph = new Key<>(StackGraph.class, "ACTIVITY_STACK_GRAPH");
|
||||
putSupplier(activityStackGraph, () -> graphs.stack().activityStackGraph(getUnsafe(AnalysisKeys.ACTIVITY_DATA)));
|
||||
putCachingSupplier(activityStackGraph, () -> graphs.stack().activityStackGraph(getUnsafe(AnalysisKeys.ACTIVITY_DATA)));
|
||||
putSupplier(AnalysisKeys.ACTIVITY_STACK_CATEGORIES, () -> getUnsafe(activityStackGraph).toHighChartsLabels());
|
||||
putSupplier(AnalysisKeys.ACTIVITY_STACK_SERIES, () -> getUnsafe(activityStackGraph).toHighChartsSeries());
|
||||
putSupplier(AnalysisKeys.ACTIVITY_PIE_SERIES, () -> graphs.pie().activityPie(
|
||||
|
@ -402,17 +402,17 @@ public class AnalysisContainer extends DataContainer {
|
|||
Key<TPSMutator> tpsWeek = new Key<>(TPSMutator.class, "TPS_WEEK");
|
||||
Key<TPSMutator> tpsDay = new Key<>(TPSMutator.class, "TPS_DAY");
|
||||
|
||||
putSupplier(tpsMonth, () -> getUnsafe(AnalysisKeys.TPS_MUTATOR)
|
||||
putCachingSupplier(tpsMonth, () -> getUnsafe(AnalysisKeys.TPS_MUTATOR)
|
||||
.filterDataBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_MONTH_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
|
||||
);
|
||||
putSupplier(tpsWeek, () -> getUnsafe(AnalysisKeys.TPS_MUTATOR)
|
||||
putCachingSupplier(tpsWeek, () -> getUnsafe(AnalysisKeys.TPS_MUTATOR)
|
||||
.filterDataBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_WEEK_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
|
||||
);
|
||||
putSupplier(tpsDay, () -> getUnsafe(AnalysisKeys.TPS_MUTATOR)
|
||||
putCachingSupplier(tpsDay, () -> getUnsafe(AnalysisKeys.TPS_MUTATOR)
|
||||
.filterDataBetween(getUnsafe(AnalysisKeys.ANALYSIS_TIME_DAY_AGO), getUnsafe(AnalysisKeys.ANALYSIS_TIME))
|
||||
);
|
||||
|
||||
putSupplier(AnalysisKeys.PLAYERS_ONLINE_RESOLVER, () -> new PlayersOnlineResolver(getUnsafe(AnalysisKeys.TPS_MUTATOR)));
|
||||
putCachingSupplier(AnalysisKeys.PLAYERS_ONLINE_RESOLVER, () -> new PlayersOnlineResolver(getUnsafe(AnalysisKeys.TPS_MUTATOR)));
|
||||
|
||||
int threshold = config.getNumber(Settings.THEME_GRAPH_TPS_THRESHOLD_MED);
|
||||
|
||||
|
@ -444,7 +444,7 @@ public class AnalysisContainer extends DataContainer {
|
|||
|
||||
private void addServerHealth() {
|
||||
Key<HealthInformation> healthInformation = new Key<>(HealthInformation.class, "HEALTH_INFORMATION");
|
||||
putSupplier(healthInformation, () -> new HealthInformation(
|
||||
putCachingSupplier(healthInformation, () -> new HealthInformation(
|
||||
this,
|
||||
config.getNumber(Settings.THEME_GRAPH_TPS_THRESHOLD_MED),
|
||||
config.getNumber(Settings.ACTIVE_PLAY_THRESHOLD),
|
||||
|
@ -458,7 +458,7 @@ public class AnalysisContainer extends DataContainer {
|
|||
private void addPluginSuppliers() {
|
||||
// TODO Refactor into a system that supports running the analysis on Bungee
|
||||
Key<String[]> navAndTabs = new Key<>(new Type<String[]>() {}, "NAV_AND_TABS");
|
||||
putSupplier(navAndTabs, () -> pluginsTabContentCreator.createContent(this));
|
||||
putCachingSupplier(navAndTabs, () -> pluginsTabContentCreator.createContent(this));
|
||||
putSupplier(AnalysisKeys.PLUGINS_TAB_NAV, () -> getUnsafe(navAndTabs)[0]);
|
||||
putSupplier(AnalysisKeys.PLUGINS_TAB, () -> getUnsafe(navAndTabs)[1]);
|
||||
}
|
||||
|
|
|
@ -44,6 +44,13 @@ public class DataContainer {
|
|||
}
|
||||
|
||||
public <T> void putSupplier(Key<T> key, Supplier<T> supplier) {
|
||||
if (supplier == null) {
|
||||
return;
|
||||
}
|
||||
map.put(key, supplier);
|
||||
}
|
||||
|
||||
public <T> void putCachingSupplier(Key<T> key, Supplier<T> supplier) {
|
||||
if (supplier == null) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ public class NetworkContainer extends DataContainer {
|
|||
this.formatters = formatters;
|
||||
this.graphs = graphs;
|
||||
|
||||
putSupplier(NetworkKeys.PLAYERS_MUTATOR, () -> PlayersMutator.forContainer(bungeeContainer));
|
||||
putCachingSupplier(NetworkKeys.PLAYERS_MUTATOR, () -> PlayersMutator.forContainer(bungeeContainer));
|
||||
|
||||
addConstants();
|
||||
addServerBoxes();
|
||||
|
@ -99,14 +99,14 @@ public class NetworkContainer extends DataContainer {
|
|||
|
||||
private void addNetworkHealth() {
|
||||
Key<NetworkHealthInformation> healthInformation = new Key<>(NetworkHealthInformation.class, "HEALTH_INFORMATION");
|
||||
putSupplier(healthInformation, () -> new NetworkHealthInformation(
|
||||
putCachingSupplier(healthInformation, () -> new NetworkHealthInformation(
|
||||
this,
|
||||
config.getNumber(Settings.ACTIVE_PLAY_THRESHOLD),
|
||||
config.getNumber(Settings.ACTIVE_LOGIN_THRESHOLD),
|
||||
formatters.timeAmount(), formatters.decimals(), formatters.percentage()
|
||||
));
|
||||
putSupplier(NetworkKeys.HEALTH_INDEX, () -> getUnsafe(healthInformation).getServerHealth());
|
||||
putSupplier(NetworkKeys.HEALTH_NOTES, () -> getUnsafe(healthInformation).toHtml());
|
||||
putCachingSupplier(NetworkKeys.HEALTH_INDEX, () -> getUnsafe(healthInformation).getServerHealth());
|
||||
putCachingSupplier(NetworkKeys.HEALTH_NOTES, () -> getUnsafe(healthInformation).toHtml());
|
||||
}
|
||||
|
||||
private void addConstants() {
|
||||
|
@ -120,7 +120,7 @@ public class NetworkContainer extends DataContainer {
|
|||
putRawData(NetworkKeys.VERSION, version);
|
||||
putSupplier(NetworkKeys.TIME_ZONE, config::getTimeZoneOffsetHours);
|
||||
|
||||
putSupplier(NetworkKeys.NETWORK_NAME, () ->
|
||||
putCachingSupplier(NetworkKeys.NETWORK_NAME, () ->
|
||||
Check.isBungeeAvailable() ?
|
||||
config.getString(Settings.BUNGEE_NETWORK_NAME) :
|
||||
bungeeContainer.getValue(ServerKeys.NAME).orElse("Plan")
|
||||
|
@ -176,22 +176,22 @@ public class NetworkContainer extends DataContainer {
|
|||
Key<PlayersMutator> uniqueDay = new Key<>(PlayersMutator.class, "UNIQUE_DAY");
|
||||
Key<PlayersMutator> uniqueWeek = new Key<>(PlayersMutator.class, "UNIQUE_WEEK");
|
||||
Key<PlayersMutator> uniqueMonth = new Key<>(PlayersMutator.class, "UNIQUE_MONTH");
|
||||
putSupplier(newDay, () -> getUnsafe(NetworkKeys.PLAYERS_MUTATOR)
|
||||
putCachingSupplier(newDay, () -> getUnsafe(NetworkKeys.PLAYERS_MUTATOR)
|
||||
.filterRegisteredBetween(getUnsafe(NetworkKeys.REFRESH_TIME_DAY_AGO), getUnsafe(NetworkKeys.REFRESH_TIME))
|
||||
);
|
||||
putSupplier(newWeek, () -> getUnsafe(NetworkKeys.PLAYERS_MUTATOR)
|
||||
putCachingSupplier(newWeek, () -> getUnsafe(NetworkKeys.PLAYERS_MUTATOR)
|
||||
.filterRegisteredBetween(getUnsafe(NetworkKeys.REFRESH_TIME_WEEK_AGO), getUnsafe(NetworkKeys.REFRESH_TIME))
|
||||
);
|
||||
putSupplier(newMonth, () -> getUnsafe(NetworkKeys.PLAYERS_MUTATOR)
|
||||
putCachingSupplier(newMonth, () -> getUnsafe(NetworkKeys.PLAYERS_MUTATOR)
|
||||
.filterRegisteredBetween(getUnsafe(NetworkKeys.REFRESH_TIME_MONTH_AGO), getUnsafe(NetworkKeys.REFRESH_TIME))
|
||||
);
|
||||
putSupplier(uniqueDay, () -> getUnsafe(NetworkKeys.PLAYERS_MUTATOR)
|
||||
putCachingSupplier(uniqueDay, () -> getUnsafe(NetworkKeys.PLAYERS_MUTATOR)
|
||||
.filterPlayedBetween(getUnsafe(NetworkKeys.REFRESH_TIME_DAY_AGO), getUnsafe(NetworkKeys.REFRESH_TIME))
|
||||
);
|
||||
putSupplier(uniqueWeek, () -> getUnsafe(NetworkKeys.PLAYERS_MUTATOR)
|
||||
putCachingSupplier(uniqueWeek, () -> getUnsafe(NetworkKeys.PLAYERS_MUTATOR)
|
||||
.filterPlayedBetween(getUnsafe(NetworkKeys.REFRESH_TIME_WEEK_AGO), getUnsafe(NetworkKeys.REFRESH_TIME))
|
||||
);
|
||||
putSupplier(uniqueMonth, () -> getUnsafe(NetworkKeys.PLAYERS_MUTATOR)
|
||||
putCachingSupplier(uniqueMonth, () -> getUnsafe(NetworkKeys.PLAYERS_MUTATOR)
|
||||
.filterPlayedBetween(getUnsafe(NetworkKeys.REFRESH_TIME_MONTH_AGO), getUnsafe(NetworkKeys.REFRESH_TIME))
|
||||
);
|
||||
|
||||
|
@ -203,6 +203,10 @@ public class NetworkContainer extends DataContainer {
|
|||
putSupplier(NetworkKeys.PLAYERS_MONTH, () -> getUnsafe(uniqueMonth).count());
|
||||
}
|
||||
|
||||
public ServerContainer getBungeeContainer() {
|
||||
return bungeeContainer;
|
||||
}
|
||||
|
||||
@Singleton
|
||||
public static class Factory {
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import com.djrapitops.plan.data.store.containers.DataContainer;
|
|||
import com.djrapitops.plan.data.store.keys.CommonKeys;
|
||||
import com.djrapitops.plan.data.store.keys.SessionKeys;
|
||||
import com.djrapitops.plan.data.time.WorldTimes;
|
||||
import com.djrapitops.plan.utilities.analysis.Median;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Predicate;
|
||||
|
@ -142,13 +143,8 @@ public class SessionsMutator {
|
|||
}
|
||||
|
||||
public long toMedianSessionLength() {
|
||||
List<Long> sessionLengths = sessions.stream().map(Session::getLength)
|
||||
.sorted()
|
||||
.collect(Collectors.toList());
|
||||
if (sessionLengths.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
return sessionLengths.get(sessionLengths.size() / 2);
|
||||
List<Long> sessionLengths = sessions.stream().map(Session::getLength).collect(Collectors.toList());
|
||||
return (long) Median.forLong(sessionLengths).calculate();
|
||||
}
|
||||
|
||||
public int toAverageUniqueJoinsPerDay() {
|
||||
|
@ -200,5 +196,4 @@ public class SessionsMutator {
|
|||
return toPlayerDeathList().size();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package com.djrapitops.plan.modules.bungee.proxy;
|
||||
|
||||
/**
|
||||
* //TODO Class Javadoc Comment
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class ProxySuperClassBindingModule {
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package com.djrapitops.plan.modules.proxy.velocity;
|
||||
|
||||
/**
|
||||
* //TODO Class Javadoc Comment
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class VelocityServerProperties {
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package com.djrapitops.plan.modules.proxy.bungee;
|
||||
|
||||
import com.djrapitops.plan.system.info.server.BungeeServerInfo;
|
||||
import com.djrapitops.plan.system.info.server.ServerInfo;
|
||||
import com.djrapitops.plan.system.listeners.BungeeListenerSystem;
|
||||
import com.djrapitops.plan.system.listeners.ListenerSystem;
|
||||
import com.djrapitops.plan.system.settings.config.BungeeConfigSystem;
|
||||
import com.djrapitops.plan.system.settings.config.ConfigSystem;
|
||||
import com.djrapitops.plan.system.tasks.BungeeTaskSystem;
|
||||
import com.djrapitops.plan.system.tasks.TaskSystem;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
/**
|
||||
* Module for binding Bungee specific classes to the interface implementations.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
@Module
|
||||
public class BungeeSuperClassBindingModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
ServerInfo provideBungeeServerInfo(BungeeServerInfo bungeeServerInfo) {
|
||||
return bungeeServerInfo;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
ConfigSystem provideBungeeConfigSystem(BungeeConfigSystem bungeeConfigSystem) {
|
||||
return bungeeConfigSystem;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
TaskSystem provideBungeeTaskSystem(BungeeTaskSystem bungeeTaskSystem) {
|
||||
return bungeeTaskSystem;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
ListenerSystem provideBungeeListenerSystem(BungeeListenerSystem bungeeListenerSystem) {
|
||||
return bungeeListenerSystem;
|
||||
}
|
||||
}
|
|
@ -66,4 +66,14 @@ public class AFKTracker {
|
|||
lastMovement.remove(uuid);
|
||||
usedAFKCommand.remove(uuid);
|
||||
}
|
||||
|
||||
public boolean isAfk(UUID uuid) {
|
||||
long time = System.currentTimeMillis();
|
||||
|
||||
Long lastMoved = lastMovement.get(uuid);
|
||||
if (lastMoved == null || lastMoved == -1) {
|
||||
return false;
|
||||
}
|
||||
return time - lastMoved > afkThresholdMs;
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
package com.djrapitops.plan.system.cache;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* CacheSystem for Bungee.
|
||||
* <p>
|
||||
* Used for overriding {@link DataCache} with {@link BungeeDataCache}
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class BungeeCacheSystem extends CacheSystem {
|
||||
|
||||
@Inject
|
||||
public BungeeCacheSystem(BungeeDataCache dataCache, GeolocationCache geolocationCache) {
|
||||
super(dataCache, geolocationCache);
|
||||
}
|
||||
|
||||
}
|
|
@ -19,6 +19,7 @@ import javax.inject.Singleton;
|
|||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.URL;
|
||||
import java.net.UnknownHostException;
|
||||
|
@ -158,8 +159,12 @@ public class GeolocationCache implements SubSystem {
|
|||
return;
|
||||
}
|
||||
URL downloadSite = new URL("http://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.mmdb.gz");
|
||||
try (ReadableByteChannel rbc = Channels.newChannel(new GZIPInputStream(downloadSite.openStream()));
|
||||
FileOutputStream fos = new FileOutputStream(geolocationDB.getAbsoluteFile())) {
|
||||
try (
|
||||
InputStream in = downloadSite.openStream();
|
||||
GZIPInputStream gzipIn = new GZIPInputStream(in);
|
||||
ReadableByteChannel rbc = Channels.newChannel(gzipIn);
|
||||
FileOutputStream fos = new FileOutputStream(geolocationDB.getAbsoluteFile())
|
||||
) {
|
||||
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,23 +8,23 @@ import javax.inject.Singleton;
|
|||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Bungee specific DataCache.
|
||||
* Proxy server specific DataCache.
|
||||
* <p>
|
||||
* Used for overriding {@link SessionCache#endSession(UUID, long)}.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
@Singleton
|
||||
public class BungeeDataCache extends DataCache {
|
||||
public class ProxyDataCache extends DataCache {
|
||||
|
||||
@Inject
|
||||
public BungeeDataCache(Database database, ErrorHandler errorHandler) {
|
||||
public ProxyDataCache(Database database, ErrorHandler errorHandler) {
|
||||
super(database, errorHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endSession(UUID uuid, long time) {
|
||||
removeSessionFromCache(uuid);
|
||||
/* Bungee should not save sessions so session is not removed.. */
|
||||
/* Proxy should not save sessions so session is not removed.. */
|
||||
}
|
||||
}
|
|
@ -83,7 +83,7 @@ public abstract class DBSystem implements SubSystem {
|
|||
public void enable() throws EnableException {
|
||||
try {
|
||||
db.init();
|
||||
db.scheduleClean(1L);
|
||||
db.scheduleClean(20L);
|
||||
logger.info(locale.getString(PluginLang.ENABLED_DATABASE, db.getName()));
|
||||
} catch (DBInitException e) {
|
||||
Throwable cause = e.getCause();
|
||||
|
|
|
@ -19,10 +19,10 @@ import javax.inject.Singleton;
|
|||
* @author Rsl1122
|
||||
*/
|
||||
@Singleton
|
||||
public class BungeeDBSystem extends DBSystem {
|
||||
public class ProxyDBSystem extends DBSystem {
|
||||
|
||||
@Inject
|
||||
public BungeeDBSystem(Locale locale, MySQLDB mySQLDB,
|
||||
public ProxyDBSystem(Locale locale, MySQLDB mySQLDB,
|
||||
PluginLogger logger, Timings timings, ErrorHandler errorHandler) {
|
||||
super(locale, logger, timings, errorHandler);
|
||||
databases.add(mySQLDB);
|
|
@ -0,0 +1,56 @@
|
|||
package com.djrapitops.plan.system.database.databases.sql;
|
||||
|
||||
import com.djrapitops.plan.PlanPlugin;
|
||||
import com.djrapitops.plan.system.database.databases.sql.patches.Patch;
|
||||
import com.djrapitops.plan.system.locale.Locale;
|
||||
import com.djrapitops.plan.system.locale.lang.PluginLang;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
import com.djrapitops.plugin.task.AbsRunnable;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Task that is in charge on patching the database when the database enables.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class PatchTask extends AbsRunnable {
|
||||
|
||||
private final Patch[] patches;
|
||||
private final Supplier<Locale> locale;
|
||||
|
||||
public PatchTask(Patch[] patches, Supplier<Locale> locale) {
|
||||
this.patches = patches;
|
||||
this.locale = locale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
boolean didApply = applyPatches();
|
||||
Log.info(locale.get().getString(
|
||||
didApply ? PluginLang.DB_APPLIED_PATCHES : PluginLang.DB_APPLIED_PATCHES_ALREADY
|
||||
));
|
||||
} catch (Exception e) {
|
||||
Log.error("----------------------------------------------------");
|
||||
Log.error(locale.get().getString(PluginLang.ENABLE_FAIL_DB_PATCH));
|
||||
Log.error("----------------------------------------------------");
|
||||
Log.toLog(this.getClass(), e);
|
||||
PlanPlugin.getInstance().onDisable();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean applyPatches() {
|
||||
boolean didApply = false;
|
||||
for (Patch patch : patches) {
|
||||
if (!patch.hasBeenApplied()) {
|
||||
String patchName = patch.getClass().getSimpleName();
|
||||
Log.info(locale.get().getString(PluginLang.DB_APPLY_PATCH, patchName));
|
||||
patch.apply();
|
||||
didApply = true;
|
||||
}
|
||||
}
|
||||
return didApply;
|
||||
}
|
||||
|
||||
}
|
|
@ -183,30 +183,12 @@ public abstract class SQLDB extends Database {
|
|||
new VersionTableRemovalPatch(this)
|
||||
};
|
||||
|
||||
runnableFactory.create("Database Patch", new AbsRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
boolean applied = false;
|
||||
for (Patch patch : patches) {
|
||||
if (!patch.hasBeenApplied()) {
|
||||
String patchName = patch.getClass().getSimpleName();
|
||||
logger.info(locale.getString(PluginLang.DB_APPLY_PATCH, patchName));
|
||||
patch.apply();
|
||||
applied = true;
|
||||
}
|
||||
}
|
||||
logger.info(locale.getString(
|
||||
applied ? PluginLang.DB_APPLIED_PATCHES : PluginLang.DB_APPLIED_PATCHES_ALREADY
|
||||
));
|
||||
} catch (Exception e) {
|
||||
logger.error("----------------------------------------------------");
|
||||
logger.error(locale.getString(PluginLang.ENABLE_FAIL_DB_PATCH));
|
||||
logger.error("----------------------------------------------------");
|
||||
errorHandler.log(L.CRITICAL, this.getClass(), e);
|
||||
}
|
||||
}
|
||||
}).runTaskLaterAsynchronously(TimeAmount.toTicks(5L, TimeUnit.SECONDS));
|
||||
try {
|
||||
runnableFactory.createNew("Database Patch", new PatchTask(patches, locale))
|
||||
.runTaskLaterAsynchronously(TimeAmount.SECOND.ticks() * 5L);
|
||||
} catch (Exception ignore) {
|
||||
// Task failed to register because plugin is being disabled
|
||||
}
|
||||
} catch (DBOpException e) {
|
||||
throw new DBInitException("Failed to set-up Database", e);
|
||||
}
|
||||
|
|
|
@ -9,9 +9,11 @@ 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.time.WorldTimes;
|
||||
import com.djrapitops.plan.system.cache.SessionCache;
|
||||
import com.djrapitops.plan.system.database.databases.operation.FetchOperations;
|
||||
import com.djrapitops.plan.system.database.databases.sql.SQLDB;
|
||||
import com.djrapitops.plan.system.info.server.Server;
|
||||
import com.djrapitops.plan.system.info.server.ServerInfo;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -25,7 +27,7 @@ public class SQLFetchOps extends SQLOps implements FetchOperations {
|
|||
@Override
|
||||
public NetworkContainer getNetworkContainer() {
|
||||
NetworkContainer networkContainer = db.getNetworkContainerFactory().forBungeeContainer(getBungeeServerContainer());
|
||||
networkContainer.putSupplier(NetworkKeys.BUKKIT_SERVERS, () -> getBukkitServers().values());
|
||||
networkContainer.putCachingSupplier(NetworkKeys.BUKKIT_SERVERS, () -> getBukkitServers().values());
|
||||
return networkContainer;
|
||||
}
|
||||
|
||||
|
@ -36,8 +38,8 @@ public class SQLFetchOps extends SQLOps implements FetchOperations {
|
|||
}
|
||||
|
||||
ServerContainer container = getServerContainer(bungeeInfo.get().getUuid());
|
||||
container.putSupplier(ServerKeys.PLAYERS, this::getAllPlayerContainers);
|
||||
container.putSupplier(ServerKeys.TPS, tpsTable::getNetworkOnlineData);
|
||||
container.putCachingSupplier(ServerKeys.PLAYERS, this::getAllPlayerContainers);
|
||||
container.putCachingSupplier(ServerKeys.TPS, tpsTable::getNetworkOnlineData);
|
||||
container.putSupplier(ServerKeys.WORLD_TIMES, null); // Additional Session information not supported
|
||||
container.putSupplier(ServerKeys.PLAYER_KILLS, null);
|
||||
container.putSupplier(ServerKeys.PLAYER_KILL_COUNT, null);
|
||||
|
@ -56,12 +58,12 @@ public class SQLFetchOps extends SQLOps implements FetchOperations {
|
|||
|
||||
container.putRawData(ServerKeys.SERVER_UUID, serverUUID);
|
||||
container.putRawData(ServerKeys.NAME, serverInfo.get().getName());
|
||||
container.putSupplier(ServerKeys.PLAYERS, () -> getPlayerContainers(serverUUID));
|
||||
container.putCachingSupplier(ServerKeys.PLAYERS, () -> getPlayerContainers(serverUUID));
|
||||
container.putSupplier(ServerKeys.PLAYER_COUNT, () -> container.getUnsafe(ServerKeys.PLAYERS).size());
|
||||
|
||||
container.putSupplier(ServerKeys.TPS, () -> tpsTable.getTPSData(serverUUID));
|
||||
container.putSupplier(ServerKeys.PING, () -> PlayersMutator.forContainer(container).pings());
|
||||
container.putSupplier(ServerKeys.ALL_TIME_PEAK_PLAYERS, () -> {
|
||||
container.putCachingSupplier(ServerKeys.TPS, () -> tpsTable.getTPSData(serverUUID));
|
||||
container.putCachingSupplier(ServerKeys.PING, () -> PlayersMutator.forContainer(container).pings());
|
||||
container.putCachingSupplier(ServerKeys.ALL_TIME_PEAK_PLAYERS, () -> {
|
||||
Optional<TPS> allTimePeak = tpsTable.getAllTimePeak(serverUUID);
|
||||
if (allTimePeak.isPresent()) {
|
||||
TPS peak = allTimePeak.get();
|
||||
|
@ -69,7 +71,7 @@ public class SQLFetchOps extends SQLOps implements FetchOperations {
|
|||
}
|
||||
return null;
|
||||
});
|
||||
container.putSupplier(ServerKeys.RECENT_PEAK_PLAYERS, () -> {
|
||||
container.putCachingSupplier(ServerKeys.RECENT_PEAK_PLAYERS, () -> {
|
||||
long twoDaysAgo = System.currentTimeMillis() - (TimeUnit.DAYS.toMillis(2L));
|
||||
Optional<TPS> lastPeak = tpsTable.getPeakPlayerCount(serverUUID, twoDaysAgo);
|
||||
if (lastPeak.isPresent()) {
|
||||
|
@ -79,16 +81,22 @@ public class SQLFetchOps extends SQLOps implements FetchOperations {
|
|||
return null;
|
||||
});
|
||||
|
||||
container.putSupplier(ServerKeys.COMMAND_USAGE, () -> commandUseTable.getCommandUse(serverUUID));
|
||||
container.putSupplier(ServerKeys.WORLD_TIMES, () -> worldTimesTable.getWorldTimesOfServer(serverUUID));
|
||||
container.putCachingSupplier(ServerKeys.COMMAND_USAGE, () -> commandUseTable.getCommandUse(serverUUID));
|
||||
container.putCachingSupplier(ServerKeys.WORLD_TIMES, () -> worldTimesTable.getWorldTimesOfServer(serverUUID));
|
||||
|
||||
// Calculating getters
|
||||
container.putSupplier(ServerKeys.OPERATORS, () -> PlayersMutator.forContainer(container).operators());
|
||||
container.putSupplier(ServerKeys.SESSIONS, () -> PlayersMutator.forContainer(container).getSessions());
|
||||
container.putSupplier(ServerKeys.PLAYER_KILLS, () -> SessionsMutator.forContainer(container).toPlayerKillList());
|
||||
container.putSupplier(ServerKeys.PLAYER_KILL_COUNT, () -> container.getUnsafe(ServerKeys.PLAYER_KILLS).size());
|
||||
container.putSupplier(ServerKeys.MOB_KILL_COUNT, () -> SessionsMutator.forContainer(container).toMobKillCount());
|
||||
container.putSupplier(ServerKeys.DEATH_COUNT, () -> SessionsMutator.forContainer(container).toDeathCount());
|
||||
container.putCachingSupplier(ServerKeys.OPERATORS, () -> PlayersMutator.forContainer(container).operators());
|
||||
container.putCachingSupplier(ServerKeys.SESSIONS, () -> {
|
||||
List<Session> sessions = PlayersMutator.forContainer(container).getSessions();
|
||||
if (serverUUID.equals(serverInfo.get().getUuid())) {
|
||||
sessions.addAll(SessionCache.getActiveSessions().values());
|
||||
}
|
||||
return sessions;
|
||||
});
|
||||
container.putCachingSupplier(ServerKeys.PLAYER_KILLS, () -> SessionsMutator.forContainer(container).toPlayerKillList());
|
||||
container.putCachingSupplier(ServerKeys.PLAYER_KILL_COUNT, () -> container.getUnsafe(ServerKeys.PLAYER_KILLS).size());
|
||||
container.putCachingSupplier(ServerKeys.MOB_KILL_COUNT, () -> SessionsMutator.forContainer(container).toMobKillCount());
|
||||
container.putCachingSupplier(ServerKeys.DEATH_COUNT, () -> SessionsMutator.forContainer(container).toDeathCount());
|
||||
|
||||
return container;
|
||||
}
|
||||
|
@ -121,13 +129,13 @@ 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.putSupplier(PlayerKeys.NICKNAMES, () -> nicknamesTable.getNicknameInformation(uuid));
|
||||
container.putCachingSupplier(PlayerKeys.NICKNAMES, () -> nicknamesTable.getNicknameInformation(uuid));
|
||||
container.putRawData(PlayerKeys.PER_SERVER, perServerInfo.get(uuid));
|
||||
|
||||
container.putRawData(PlayerKeys.BANNED, userInfo.isBanned());
|
||||
container.putRawData(PlayerKeys.OPERATOR, userInfo.isOperator());
|
||||
|
||||
container.putSupplier(PlayerKeys.SESSIONS, () -> {
|
||||
container.putCachingSupplier(PlayerKeys.SESSIONS, () -> {
|
||||
List<Session> playerSessions = sessions.getOrDefault(uuid, new ArrayList<>());
|
||||
container.getValue(PlayerKeys.ACTIVE_SESSION).ifPresent(playerSessions::add);
|
||||
return playerSessions;
|
||||
|
@ -135,7 +143,7 @@ public class SQLFetchOps extends SQLOps implements FetchOperations {
|
|||
);
|
||||
|
||||
// Calculating getters
|
||||
container.putSupplier(PlayerKeys.WORLD_TIMES, () -> {
|
||||
container.putCachingSupplier(PlayerKeys.WORLD_TIMES, () -> {
|
||||
WorldTimes worldTimes = new PerServerMutator(container.getUnsafe(PlayerKeys.PER_SERVER)).flatMapWorldTimes();
|
||||
container.getValue(PlayerKeys.ACTIVE_SESSION)
|
||||
.ifPresent(session -> worldTimes.add(
|
||||
|
@ -179,10 +187,10 @@ 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.putSupplier(PlayerKeys.NICKNAMES, () -> nicknamesTable.getNicknameInformation(uuid));
|
||||
container.putCachingSupplier(PlayerKeys.NICKNAMES, () -> nicknamesTable.getNicknameInformation(uuid));
|
||||
container.putRawData(PlayerKeys.PER_SERVER, perServerInfo.get(uuid));
|
||||
|
||||
container.putSupplier(PlayerKeys.SESSIONS, () -> {
|
||||
container.putCachingSupplier(PlayerKeys.SESSIONS, () -> {
|
||||
List<Session> playerSessions = PerServerMutator.forContainer(container).flatMapSessions();
|
||||
container.getValue(PlayerKeys.ACTIVE_SESSION).ifPresent(playerSessions::add);
|
||||
return playerSessions;
|
||||
|
@ -277,21 +285,21 @@ public class SQLFetchOps extends SQLOps implements FetchOperations {
|
|||
container.putRawData(PlayerKeys.UUID, uuid);
|
||||
|
||||
container.putAll(usersTable.getUserInformation(uuid));
|
||||
container.putSupplier(PlayerKeys.GEO_INFO, () -> geoInfoTable.getGeoInfo(uuid));
|
||||
container.putSupplier(PlayerKeys.PING, () -> pingTable.getPing(uuid));
|
||||
container.putSupplier(PlayerKeys.NICKNAMES, () -> nicknamesTable.getNicknameInformation(uuid));
|
||||
container.putSupplier(PlayerKeys.PER_SERVER, () -> getPerServerData(uuid));
|
||||
container.putCachingSupplier(PlayerKeys.GEO_INFO, () -> geoInfoTable.getGeoInfo(uuid));
|
||||
container.putCachingSupplier(PlayerKeys.PING, () -> pingTable.getPing(uuid));
|
||||
container.putCachingSupplier(PlayerKeys.NICKNAMES, () -> nicknamesTable.getNicknameInformation(uuid));
|
||||
container.putCachingSupplier(PlayerKeys.PER_SERVER, () -> getPerServerData(uuid));
|
||||
|
||||
container.putSupplier(PlayerKeys.BANNED, () -> new PerServerMutator(container.getUnsafe(PlayerKeys.PER_SERVER)).isBanned());
|
||||
container.putSupplier(PlayerKeys.OPERATOR, () -> new PerServerMutator(container.getUnsafe(PlayerKeys.PER_SERVER)).isOperator());
|
||||
|
||||
container.putSupplier(PlayerKeys.SESSIONS, () -> {
|
||||
container.putCachingSupplier(PlayerKeys.SESSIONS, () -> {
|
||||
List<Session> sessions = new PerServerMutator(container.getUnsafe(PlayerKeys.PER_SERVER)).flatMapSessions();
|
||||
container.getValue(PlayerKeys.ACTIVE_SESSION).ifPresent(sessions::add);
|
||||
return sessions;
|
||||
}
|
||||
);
|
||||
container.putSupplier(PlayerKeys.WORLD_TIMES, () ->
|
||||
container.putCachingSupplier(PlayerKeys.WORLD_TIMES, () ->
|
||||
{
|
||||
WorldTimes worldTimes = new PerServerMutator(container.getUnsafe(PlayerKeys.PER_SERVER)).flatMapWorldTimes();
|
||||
container.getValue(PlayerKeys.ACTIVE_SESSION).ifPresent(session -> worldTimes.add(
|
||||
|
|
|
@ -16,7 +16,7 @@ public class GeoInfoLastUsedPatch extends Patch {
|
|||
|
||||
@Override
|
||||
public void apply() {
|
||||
addColumns(GeoInfoTable.TABLE_NAME,
|
||||
addColumn(GeoInfoTable.TABLE_NAME,
|
||||
GeoInfoTable.Col.LAST_USED + " bigint NOT NULL DEFAULT 0"
|
||||
);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,6 @@ public class IPHashPatch extends Patch {
|
|||
|
||||
@Override
|
||||
public void apply() {
|
||||
addColumns(GeoInfoTable.Col.IP_HASH.get() + " varchar(200) DEFAULT ''");
|
||||
addColumn(GeoInfoTable.TABLE_NAME, GeoInfoTable.Col.IP_HASH.get() + " varchar(200) DEFAULT ''");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ public class KillsServerIDPatch extends Patch {
|
|||
|
||||
@Override
|
||||
public void apply() {
|
||||
addColumns(KillsTable.Col.SERVER_ID + " integer NOT NULL DEFAULT 0");
|
||||
addColumn(KillsTable.TABLE_NAME, KillsTable.Col.SERVER_ID + " integer NOT NULL DEFAULT 0");
|
||||
|
||||
Map<Integer, Integer> sessionIDServerIDRelation = db.getSessionsTable().getIDServerIDRelation();
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ public class NicknameLastSeenPatch extends Patch {
|
|||
|
||||
@Override
|
||||
public void apply() {
|
||||
addColumns(NicknamesTable.TABLE_NAME,
|
||||
addColumn(NicknamesTable.TABLE_NAME,
|
||||
NicknamesTable.Col.LAST_USED + " bigint NOT NULL DEFAULT '0'"
|
||||
);
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ 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;
|
||||
import com.djrapitops.plan.system.database.databases.sql.statements.TableSqlParser;
|
||||
import com.djrapitops.plan.system.settings.Settings;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
|
@ -30,13 +31,16 @@ public abstract class Patch {
|
|||
|
||||
public boolean hasTable(String tableName) {
|
||||
String sql = usingMySQL ?
|
||||
"SELECT * FROM information_schema.TABLES WHERE table_name=? LIMIT 1" :
|
||||
"SELECT * FROM information_schema.TABLES WHERE table_name=? AND TABLE_SCHEMA=? LIMIT 1" :
|
||||
"SELECT tbl_name FROM sqlite_master WHERE tbl_name=?";
|
||||
|
||||
return query(new QueryStatement<Boolean>(sql) {
|
||||
@Override
|
||||
public void prepare(PreparedStatement statement) throws SQLException {
|
||||
statement.setString(1, tableName);
|
||||
if (usingMySQL) {
|
||||
statement.setString(2, Settings.DB_DATABASE.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -49,11 +53,12 @@ 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=?") {
|
||||
" 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);
|
||||
statement.setString(3, Settings.DB_DATABASE.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -74,11 +79,8 @@ public abstract class Patch {
|
|||
});
|
||||
}
|
||||
|
||||
protected void addColumns(String tableName, String... columnInfo) {
|
||||
for (int i = 0; i < columnInfo.length; i++) {
|
||||
columnInfo[i] = "ALTER TABLE " + tableName + " ADD " + (usingMySQL ? "" : "COLUMN ") + columnInfo[i];
|
||||
}
|
||||
db.executeUnsafe(columnInfo);
|
||||
protected void addColumn(String tableName, String columnInfo) {
|
||||
db.executeUnsafe("ALTER TABLE " + tableName + " ADD " + (usingMySQL ? "" : "COLUMN ") + columnInfo);
|
||||
}
|
||||
|
||||
protected void dropTable(String name) {
|
||||
|
|
|
@ -16,7 +16,7 @@ public class SessionAFKTimePatch extends Patch {
|
|||
|
||||
@Override
|
||||
public void apply() {
|
||||
addColumns(SessionsTable.TABLE_NAME,
|
||||
addColumn(SessionsTable.TABLE_NAME,
|
||||
SessionsTable.Col.AFK_TIME + " bigint NOT NULL DEFAULT 0"
|
||||
);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,6 @@ public class TransferPartitionPatch extends Patch {
|
|||
|
||||
@Override
|
||||
public void apply() {
|
||||
addColumns(TransferTable.TABLE_NAME, TransferTable.Col.PART + " bigint NOT NULL DEFAULT 0");
|
||||
addColumn(TransferTable.TABLE_NAME, TransferTable.Col.PART + " bigint NOT NULL DEFAULT 0");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ public class VersionTableRemovalPatch extends Patch {
|
|||
|
||||
@Override
|
||||
public boolean hasBeenApplied() {
|
||||
return hasTable("plan_version");
|
||||
return !hasTable("plan_version");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -118,7 +118,7 @@ public class KillsTable extends UserIDTable {
|
|||
String victimName = set.getString("victim_name");
|
||||
long date = set.getLong(Col.DATE.get());
|
||||
String weapon = set.getString(Col.WEAPON.get());
|
||||
session.getUnsafe(SessionKeys.PLAYER_KILLS).add(new PlayerKill(victim, weapon, date, victimName));
|
||||
session.getPlayerKills().add(new PlayerKill(victim, weapon, date, victimName));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -295,7 +295,7 @@ public class KillsTable extends UserIDTable {
|
|||
for (Session session : sessions) {
|
||||
int sessionID = session.getUnsafe(SessionKeys.DB_ID);
|
||||
// Every kill
|
||||
for (PlayerKill kill : session.getUnsafe(SessionKeys.PLAYER_KILLS)) {
|
||||
for (PlayerKill kill : session.getPlayerKills()) {
|
||||
UUID victim = kill.getVictim();
|
||||
long date = kill.getDate();
|
||||
String weapon = kill.getWeapon();
|
||||
|
|
|
@ -367,7 +367,7 @@ public class ServerTable extends Table {
|
|||
}
|
||||
|
||||
public void setAsUninstalled(UUID serverUUID) {
|
||||
String sql = "UPDATE " + tableName + " SET (" + Col.INSTALLED + "=?) WHERE " + Col.SERVER_UUID + "=?";
|
||||
String sql = "UPDATE " + tableName + " SET " + Col.INSTALLED + "=? WHERE " + Col.SERVER_UUID + "=?";
|
||||
|
||||
execute(new ExecStatement(sql) {
|
||||
@Override
|
||||
|
|
|
@ -112,7 +112,7 @@ public class SessionsTable extends UserIDTable {
|
|||
}
|
||||
|
||||
db.getWorldTimesTable().saveWorldTimes(uuid, sessionID, session.getUnsafe(SessionKeys.WORLD_TIMES));
|
||||
db.getKillsTable().savePlayerKills(uuid, sessionID, session.getUnsafe(SessionKeys.PLAYER_KILLS));
|
||||
db.getKillsTable().savePlayerKills(uuid, sessionID, session.getPlayerKills());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -147,9 +147,12 @@ public class TPSTable extends Table {
|
|||
}
|
||||
|
||||
public Optional<TPS> getPeakPlayerCount(UUID serverUUID, long afterDate) {
|
||||
String subStatement = "SELECT MAX(" + Col.PLAYERS_ONLINE + ") FROM " + tableName +
|
||||
" WHERE " + Col.SERVER_ID + "=" + serverTable.statementSelectServerID +
|
||||
" AND " + Col.DATE + ">= ?";
|
||||
String sql = Select.all(tableName)
|
||||
.where(Col.SERVER_ID + "=" + serverTable.statementSelectServerID)
|
||||
.and(Col.PLAYERS_ONLINE + "= (SELECT MAX(" + Col.PLAYERS_ONLINE + ") FROM " + tableName + ")")
|
||||
.and(Col.PLAYERS_ONLINE + "= (" + subStatement + ")")
|
||||
.and(Col.DATE + ">= ?")
|
||||
.toString();
|
||||
|
||||
|
@ -157,13 +160,14 @@ public class TPSTable extends Table {
|
|||
@Override
|
||||
public void prepare(PreparedStatement statement) throws SQLException {
|
||||
statement.setString(1, serverUUID.toString());
|
||||
statement.setLong(2, afterDate);
|
||||
statement.setString(2, serverUUID.toString());
|
||||
statement.setLong(3, afterDate);
|
||||
statement.setLong(4, afterDate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<TPS> processResults(ResultSet set) throws SQLException {
|
||||
if (set.next()) {
|
||||
|
||||
TPS tps = TPSBuilder.get()
|
||||
.date(set.getLong(Col.DATE.get()))
|
||||
.tps(set.getDouble(Col.TPS.get()))
|
||||
|
|
|
@ -276,4 +276,28 @@ public class UserImportData {
|
|||
return new UserImportData(name, uuid, nicknames, registered, op, banned, timesKicked, ips, worldTimes, kills, mobKills, deaths);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof UserImportData)) return false;
|
||||
UserImportData that = (UserImportData) o;
|
||||
return registered == that.registered &&
|
||||
op == that.op &&
|
||||
banned == that.banned &&
|
||||
timesKicked == that.timesKicked &&
|
||||
mobKills == that.mobKills &&
|
||||
deaths == that.deaths &&
|
||||
Objects.equals(name, that.name) &&
|
||||
Objects.equals(uuid, that.uuid) &&
|
||||
Objects.equals(nicknames, that.nicknames) &&
|
||||
Objects.equals(ips, that.ips) &&
|
||||
Objects.equals(worldTimes, that.worldTimes) &&
|
||||
Objects.equals(kills, that.kills);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(name, uuid, nicknames, registered, op, banned, timesKicked, ips, worldTimes, kills, mobKills, deaths);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,10 +7,7 @@ package com.djrapitops.plan.system.info;
|
|||
import com.djrapitops.plan.api.exceptions.connection.NoServersException;
|
||||
import com.djrapitops.plan.api.exceptions.connection.WebException;
|
||||
import com.djrapitops.plan.system.info.connection.ConnectionSystem;
|
||||
import com.djrapitops.plan.system.info.request.CacheRequest;
|
||||
import com.djrapitops.plan.system.info.request.GenerateInspectPageRequest;
|
||||
import com.djrapitops.plan.system.info.request.InfoRequest;
|
||||
import com.djrapitops.plan.system.info.request.InfoRequestFactory;
|
||||
import com.djrapitops.plan.system.info.request.*;
|
||||
import com.djrapitops.plan.system.info.server.ServerInfo;
|
||||
import com.djrapitops.plan.system.webserver.WebServer;
|
||||
import com.djrapitops.plugin.logging.console.PluginLogger;
|
||||
|
@ -25,10 +22,10 @@ import javax.inject.Singleton;
|
|||
* @author Rsl1122
|
||||
*/
|
||||
@Singleton
|
||||
public class BungeeInfoSystem extends InfoSystem {
|
||||
public class ProxyInfoSystem extends InfoSystem {
|
||||
|
||||
@Inject
|
||||
public BungeeInfoSystem(
|
||||
public ProxyInfoSystem(
|
||||
InfoRequestFactory infoRequestFactory,
|
||||
ConnectionSystem connectionSystem,
|
||||
ServerInfo serverInfo,
|
||||
|
@ -41,7 +38,9 @@ public class BungeeInfoSystem extends InfoSystem {
|
|||
@Override
|
||||
public void runLocally(InfoRequest infoRequest) throws WebException {
|
||||
if (infoRequest instanceof CacheRequest
|
||||
|| infoRequest instanceof GenerateInspectPageRequest) {
|
||||
|| infoRequest instanceof GenerateInspectPageRequest
|
||||
|| infoRequest instanceof GenerateInspectPluginsTabRequest
|
||||
) {
|
||||
infoRequest.runLocally();
|
||||
} else {
|
||||
// runLocally is called when ConnectionSystem has no servers.
|
|
@ -144,6 +144,7 @@ public class ConnectionOut {
|
|||
|
||||
post.setHeader("Content-Type", "application/x-www-form-urlencoded");
|
||||
post.setHeader("charset", "UTF-8");
|
||||
post.setHeader("Connection", "close");
|
||||
|
||||
byte[] toSend = parameters.getBytes();
|
||||
post.setEntity(new ByteArrayEntity(toSend));
|
||||
|
|
|
@ -22,12 +22,12 @@ import java.util.UUID;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* ConnectionSystem for Bungee.
|
||||
* ConnectionSystem for proxy servers.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
@Singleton
|
||||
public class BungeeConnectionSystem extends ConnectionSystem {
|
||||
public class ProxyConnectionSystem extends ConnectionSystem {
|
||||
|
||||
private final Database database;
|
||||
private final Lazy<WebServer> webServer;
|
||||
|
@ -37,7 +37,7 @@ public class BungeeConnectionSystem extends ConnectionSystem {
|
|||
private long latestServerMapRefresh;
|
||||
|
||||
@Inject
|
||||
public BungeeConnectionSystem(
|
||||
public ProxyConnectionSystem(
|
||||
Database database,
|
||||
Lazy<WebServer> webServer,
|
||||
ConnectionLog connectionLog,
|
||||
|
@ -52,7 +52,6 @@ public class BungeeConnectionSystem extends ConnectionSystem {
|
|||
this.webServer = webServer;
|
||||
this.errorHandler = errorHandler;
|
||||
this.webExceptionLogger = webExceptionLogger;
|
||||
|
||||
latestServerMapRefresh = 0;
|
||||
}
|
||||
|
||||
|
@ -71,7 +70,9 @@ public class BungeeConnectionSystem extends ConnectionSystem {
|
|||
protected Server selectServerForRequest(InfoRequest infoRequest) throws NoServersException {
|
||||
refreshServerMap();
|
||||
Server server = null;
|
||||
if (infoRequest instanceof CacheRequest || infoRequest instanceof GenerateInspectPageRequest) {
|
||||
if (infoRequest instanceof CacheRequest
|
||||
|| infoRequest instanceof GenerateInspectPageRequest
|
||||
|| infoRequest instanceof GenerateInspectPluginsTabRequest) {
|
||||
// Run locally
|
||||
return serverInfo.getServer();
|
||||
} else if (infoRequest instanceof GenerateAnalysisPageRequest) {
|
||||
|
@ -93,6 +94,10 @@ public class BungeeConnectionSystem extends ConnectionSystem {
|
|||
for (Server server : bukkitServers.values()) {
|
||||
webExceptionLogger.logIfOccurs(this.getClass(), () -> sendInfoRequest(infoRequest, server));
|
||||
}
|
||||
// Quick hack
|
||||
if (infoRequest instanceof GenerateInspectPluginsTabRequest) {
|
||||
webExceptionLogger.logIfOccurs(this.getClass(), () -> InfoSystem.getInstance().sendRequest(infoRequest));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* License is provided in the jar as LICENSE also here:
|
||||
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/LICENSE
|
||||
*/
|
||||
package com.djrapitops.plan.system.info.server;
|
||||
|
||||
import com.djrapitops.plan.PlanVelocity;
|
||||
import com.djrapitops.plan.api.exceptions.EnableException;
|
||||
import com.djrapitops.plan.api.exceptions.database.DBOpException;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plan.system.info.server.properties.VelocityServerProperties;
|
||||
import com.djrapitops.plan.system.info.server.properties.ServerProperties;
|
||||
import com.djrapitops.plan.system.webserver.WebServerSystem;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Manages Server information on the Velocity instance.
|
||||
*
|
||||
* Based on BungeeServerInfo
|
||||
*
|
||||
* @author MicleBrick
|
||||
*/
|
||||
public class VelocityServerInfo extends ServerInfo {
|
||||
|
||||
public VelocityServerInfo(PlanVelocity plugin) {
|
||||
super(new VelocityServerProperties(plugin.getProxy()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Server loadServerInfo() throws EnableException {
|
||||
checkIfDefaultIP();
|
||||
|
||||
try {
|
||||
Database db = Database.getActive();
|
||||
// doesn't seem like this would need to be different for velocity, perhaps rename to getProxyInformation()?
|
||||
Optional<Server> velocityInfo = db.fetch().getBungeeInformation();
|
||||
if (velocityInfo.isPresent()) {
|
||||
server = velocityInfo.get();
|
||||
updateServerInfo(db);
|
||||
} else {
|
||||
server = registerVelocityInfo(db);
|
||||
}
|
||||
} catch (DBOpException e) {
|
||||
throw new EnableException("Failed to read Server information from Database.");
|
||||
}
|
||||
return server;
|
||||
}
|
||||
|
||||
private void updateServerInfo(Database db) {
|
||||
String accessAddress = WebServerSystem.getInstance().getWebServer().getAccessAddress();
|
||||
if (!accessAddress.equals(server.getWebAddress())) {
|
||||
server.setWebAddress(accessAddress);
|
||||
db.save().serverInfoForThisServer(server);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkIfDefaultIP() throws EnableException {
|
||||
String ip = ServerInfo.getServerProperties().getIp();
|
||||
if ("0.0.0.0".equals(ip)) {
|
||||
Log.error("IP setting still 0.0.0.0 - Configure AlternativeIP/IP that connects to the Proxy server.");
|
||||
Log.info("Player Analytics partially enabled (Use /planvelocity to reload config)");
|
||||
throw new EnableException("IP setting still 0.0.0.0 - Configure AlternativeIP/IP that connects to the Proxy server.");
|
||||
}
|
||||
}
|
||||
|
||||
private Server registerVelocityInfo(Database db) throws EnableException {
|
||||
ServerProperties properties = ServerInfo.getServerProperties();
|
||||
UUID serverUUID = generateNewUUID(properties);
|
||||
String accessAddress = WebServerSystem.getInstance().getWebServer().getAccessAddress();
|
||||
|
||||
Server velocityCord = new Server(-1, serverUUID, "VelocityCord", accessAddress, properties.getMaxPlayers());
|
||||
db.save().serverInfoForThisServer(velocityCord);
|
||||
|
||||
Optional<Server> velocityInfo = db.fetch().getBungeeInformation();
|
||||
if (velocityInfo.isPresent()) {
|
||||
return velocityInfo.get();
|
||||
}
|
||||
throw new EnableException("VelocityCord registration failed (DB)");
|
||||
}
|
||||
|
||||
private UUID generateNewUUID(ServerProperties properties) {
|
||||
String seed = properties.getName() + properties.getIp() + properties.getPort() + properties.getVersion() + properties.getImplVersion();
|
||||
return UUID.nameUUIDFromBytes(seed.getBytes());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package com.djrapitops.plan.system.info.server.properties;
|
||||
|
||||
import com.djrapitops.plan.system.settings.Settings;
|
||||
import com.velocitypowered.api.proxy.ProxyServer;
|
||||
|
||||
/**
|
||||
* ServerProperties for Velocity.
|
||||
* <p>
|
||||
* Supports RedisBungee for Players online getting.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class VelocityServerProperties extends ServerProperties {
|
||||
|
||||
public VelocityServerProperties(ProxyServer server) {
|
||||
super(
|
||||
server.getAllServers().toString(),
|
||||
"Velocity",
|
||||
server.getBoundAddress().getPort(),
|
||||
// not sure how to get these
|
||||
server.getClass().getPackage().getImplementationVersion(),
|
||||
server.getClass().getPackage().getImplementationVersion(),
|
||||
Settings.BUNGEE_IP::toString,
|
||||
-1, // not sure how to get this
|
||||
RedisCheck.isClassAvailable() ? new RedisPlayersOnlineSupplier() : server::getPlayerCount
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package com.djrapitops.plan.system.listeners;
|
||||
|
||||
import com.djrapitops.plan.PlanVelocity;
|
||||
import com.djrapitops.plan.system.listeners.velocity.PlayerOnlineListener;
|
||||
|
||||
public class VelocityListenerSystem extends ListenerSystem {
|
||||
|
||||
private final PlanVelocity plugin;
|
||||
|
||||
public VelocityListenerSystem(PlanVelocity plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerListeners() {
|
||||
plugin.registerListener(new PlayerOnlineListener());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void unregisterListeners() {
|
||||
plugin.getProxy().getEventManager().unregisterListeners(plugin);
|
||||
}
|
||||
}
|
|
@ -15,6 +15,8 @@ import org.bukkit.event.player.PlayerEvent;
|
|||
import org.bukkit.event.player.PlayerMoveEvent;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
|
@ -30,11 +32,13 @@ public class AFKListener implements Listener {
|
|||
// Static so that /reload does not cause afk tracking to fail.
|
||||
static AFKTracker AFK_TRACKER;
|
||||
|
||||
private final Map<UUID, Boolean> ignorePermissionInfo;
|
||||
private final ErrorHandler errorHandler;
|
||||
|
||||
@Inject
|
||||
public AFKListener(PlanConfig config, ErrorHandler errorHandler) {
|
||||
this.errorHandler = errorHandler;
|
||||
this.ignorePermissionInfo = new HashMap<>();
|
||||
|
||||
AFKListener.assignAFKTracker(config);
|
||||
}
|
||||
|
@ -51,8 +55,15 @@ public class AFKListener implements Listener {
|
|||
UUID uuid = player.getUniqueId();
|
||||
long time = System.currentTimeMillis();
|
||||
|
||||
if (player.hasPermission(Permissions.IGNORE_AFK.getPermission())) {
|
||||
Boolean ignored = ignorePermissionInfo.get(uuid);
|
||||
if (ignored == null) {
|
||||
ignored = player.hasPermission(Permissions.IGNORE_AFK.getPermission());
|
||||
}
|
||||
if (ignored) {
|
||||
AFK_TRACKER.hasIgnorePermission(uuid);
|
||||
ignorePermissionInfo.put(uuid, true);
|
||||
} else {
|
||||
ignorePermissionInfo.put(uuid, false);
|
||||
}
|
||||
|
||||
AFK_TRACKER.performedAction(uuid, time);
|
||||
|
|
|
@ -92,6 +92,10 @@ public class PlayerOnlineListener implements Listener {
|
|||
return;
|
||||
}
|
||||
UUID uuid = event.getPlayer().getUniqueId();
|
||||
if (AFKListener.AFK_TRACKER.isAfk(uuid)) {
|
||||
return;
|
||||
}
|
||||
|
||||
processing.submit(processors.player().kickProcessor(uuid));
|
||||
} catch (Exception e) {
|
||||
errorHandler.log(L.ERROR, this.getClass(), e);
|
||||
|
|
|
@ -16,8 +16,8 @@ import com.djrapitops.plan.system.webserver.cache.ResponseCache;
|
|||
import com.djrapitops.plugin.logging.L;
|
||||
import com.djrapitops.plugin.logging.error.ErrorHandler;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
|
||||
import net.md_5.bungee.api.event.PostLoginEvent;
|
||||
import net.md_5.bungee.api.event.ServerDisconnectEvent;
|
||||
import net.md_5.bungee.api.event.ServerSwitchEvent;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
|
@ -81,7 +81,7 @@ public class PlayerOnlineListener implements Listener {
|
|||
}
|
||||
|
||||
@EventHandler
|
||||
public void onLogout(ServerDisconnectEvent event) {
|
||||
public void onLogout(PlayerDisconnectEvent event) {
|
||||
try {
|
||||
ProxiedPlayer player = event.getPlayer();
|
||||
UUID uuid = player.getUniqueId();
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.djrapitops.plan.system.listeners.sponge;
|
|||
import com.djrapitops.plan.data.container.Session;
|
||||
import com.djrapitops.plan.system.cache.SessionCache;
|
||||
import com.djrapitops.plan.system.info.server.ServerInfo;
|
||||
import com.djrapitops.plan.system.listeners.bukkit.AFKListener;
|
||||
import com.djrapitops.plan.system.processing.Processing;
|
||||
import com.djrapitops.plan.system.processing.processors.Processors;
|
||||
import com.djrapitops.plan.system.settings.Settings;
|
||||
|
@ -81,6 +82,10 @@ public class SpongePlayerListener {
|
|||
public void onKick(KickPlayerEvent event) {
|
||||
try {
|
||||
UUID uuid = event.getTargetEntity().getUniqueId();
|
||||
// TODO
|
||||
if (AFKListener.AFK_TRACKER.isAfk(uuid)) {
|
||||
return;
|
||||
}
|
||||
processing.submit(processors.player().kickProcessor(uuid));
|
||||
} catch (Exception e) {
|
||||
errorHandler.log(L.ERROR, this.getClass(), e);
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* License is provided in the jar as LICENSE also here:
|
||||
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/LICENSE
|
||||
*/
|
||||
package com.djrapitops.plan.system.listeners.velocity;
|
||||
|
||||
import com.djrapitops.plan.data.container.Session;
|
||||
import com.djrapitops.plan.system.cache.SessionCache;
|
||||
import com.djrapitops.plan.system.info.server.ServerInfo;
|
||||
import com.djrapitops.plan.system.processing.Processing;
|
||||
import com.djrapitops.plan.system.processing.processors.info.PlayerPageUpdateProcessor;
|
||||
import com.djrapitops.plan.system.processing.processors.player.BungeePlayerRegisterProcessor;
|
||||
import com.djrapitops.plan.system.processing.processors.player.IPUpdateProcessor;
|
||||
import com.djrapitops.plan.system.webserver.cache.PageId;
|
||||
import com.djrapitops.plan.system.webserver.cache.ResponseCache;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
import com.velocitypowered.api.event.Subscribe;
|
||||
import com.velocitypowered.api.event.connection.DisconnectEvent;
|
||||
import com.velocitypowered.api.event.connection.PostLoginEvent;
|
||||
import com.velocitypowered.api.event.player.ServerConnectedEvent;
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Player Join listener for Velocity.
|
||||
*
|
||||
* Based on the bungee version.
|
||||
*
|
||||
* @author MicleBrick
|
||||
*/
|
||||
public class PlayerOnlineListener {
|
||||
|
||||
@Subscribe
|
||||
public void onPostLogin(PostLoginEvent event) {
|
||||
try {
|
||||
Player player = event.getPlayer();
|
||||
UUID uuid = player.getUniqueId();
|
||||
String name = player.getUsername();
|
||||
InetAddress address = player.getRemoteAddress().getAddress();
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
SessionCache.getInstance().cacheSession(uuid, new Session(uuid, now, "", ""));
|
||||
|
||||
// maybe rename to ProxyPlayerRegisterProcessor?
|
||||
Processing.submit(new BungeePlayerRegisterProcessor(uuid, name, now,
|
||||
new IPUpdateProcessor(uuid, address, now))
|
||||
);
|
||||
Processing.submit(new PlayerPageUpdateProcessor(uuid));
|
||||
ResponseCache.clearResponse(PageId.SERVER.of(ServerInfo.getServerUUID()));
|
||||
} catch (Exception e) {
|
||||
Log.toLog(this.getClass(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onLogout(DisconnectEvent event) {
|
||||
try {
|
||||
Player player = event.getPlayer();
|
||||
UUID uuid = player.getUniqueId();
|
||||
|
||||
SessionCache.getInstance().endSession(uuid, System.currentTimeMillis());
|
||||
Processing.submit(new PlayerPageUpdateProcessor(uuid));
|
||||
ResponseCache.clearResponse(PageId.SERVER.of(ServerInfo.getServerUUID()));
|
||||
} catch (Exception e) {
|
||||
Log.toLog(this.getClass(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onServerSwitch(ServerConnectedEvent event) {
|
||||
try {
|
||||
Player player = event.getPlayer();
|
||||
UUID uuid = player.getUniqueId();
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
// Replaces the current session in the cache.
|
||||
SessionCache.getInstance().cacheSession(uuid, new Session(uuid, now, "", ""));
|
||||
Processing.submit(new PlayerPageUpdateProcessor(uuid));
|
||||
} catch (Exception e) {
|
||||
Log.toLog(this.getClass(), e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,14 +1,16 @@
|
|||
package com.djrapitops.plan.system.locale;
|
||||
|
||||
import com.djrapitops.plan.PlanPlugin;
|
||||
import com.djrapitops.plan.system.locale.lang.Lang;
|
||||
import com.djrapitops.plan.system.locale.lang.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
|
@ -67,10 +69,22 @@ public class Locale extends HashMap<Lang, Message> {
|
|||
|
||||
String replaced = from;
|
||||
|
||||
// Longest first so that entries that contain each other don't partially replace.
|
||||
List<Entry<Lang, Message>> entries = entrySet().stream().sorted(
|
||||
(one, two) -> Integer.compare(two.getKey().getIdentifier().length(), one.getKey().getIdentifier().length())
|
||||
).collect(Collectors.toList());
|
||||
Lang[][] langs = new Lang[][]{
|
||||
NetworkPageLang.values(),
|
||||
PlayerPageLang.values(),
|
||||
ServerPageLang.values(),
|
||||
CommonHtmlLang.values()
|
||||
};
|
||||
|
||||
List<Entry<Lang, Message>> entries = Arrays.stream(langs)
|
||||
.flatMap(Arrays::stream)
|
||||
.collect(Collectors.toMap(Function.identity(), this::get))
|
||||
.entrySet().stream()
|
||||
// Longest first so that entries that contain each other don't partially replace.
|
||||
.sorted((one, two) -> Integer.compare(
|
||||
two.getKey().getIdentifier().length(),
|
||||
one.getKey().getIdentifier().length()
|
||||
)).collect(Collectors.toList());
|
||||
|
||||
for (Entry<Lang, Message> entry : entries) {
|
||||
String defaultValue = entry.getKey().getDefault();
|
||||
|
|
|
@ -8,6 +8,7 @@ import com.djrapitops.plugin.logging.L;
|
|||
import com.djrapitops.plugin.logging.console.PluginLogger;
|
||||
import com.djrapitops.plugin.logging.error.ErrorHandler;
|
||||
import dagger.Lazy;
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
@ -33,8 +34,8 @@ public class Processing implements SubSystem {
|
|||
this.locale = locale;
|
||||
this.logger = logger;
|
||||
this.errorHandler = errorHandler;
|
||||
nonCriticalExecutor = Executors.newFixedThreadPool(6);
|
||||
criticalExecutor = Executors.newFixedThreadPool(2);
|
||||
nonCriticalExecutor = Executors.newFixedThreadPool(6, new ThreadFactoryBuilder().setNameFormat("Plan Non critical-pool-%d").build());
|
||||
criticalExecutor = Executors.newFixedThreadPool(2, new ThreadFactoryBuilder().setNameFormat("Plan Critical-pool-%d").build());
|
||||
}
|
||||
|
||||
public void submit(Runnable runnable) {
|
||||
|
|
|
@ -1,51 +1,23 @@
|
|||
package com.djrapitops.plan.system.processing.processors.info;
|
||||
|
||||
import com.djrapitops.plan.system.info.InfoSystem;
|
||||
import com.djrapitops.plan.system.info.connection.WebExceptionLogger;
|
||||
import com.djrapitops.plugin.api.Check;
|
||||
import com.djrapitops.plugin.api.TimeAmount;
|
||||
import com.djrapitops.plugin.task.AbsRunnable;
|
||||
import com.djrapitops.plugin.task.RunnableFactory;
|
||||
import com.djrapitops.plan.system.webserver.cache.PageId;
|
||||
import com.djrapitops.plan.system.webserver.cache.ResponseCache;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class PlayerPageUpdateProcessor implements Runnable {
|
||||
|
||||
private final UUID uuid;
|
||||
|
||||
private final InfoSystem infoSystem;
|
||||
private final WebExceptionLogger webExceptionLogger;
|
||||
private final RunnableFactory runnableFactory;
|
||||
|
||||
// TODO Factory method fix
|
||||
PlayerPageUpdateProcessor(
|
||||
UUID uuid,
|
||||
InfoSystem infoSystem,
|
||||
WebExceptionLogger webExceptionLogger,
|
||||
RunnableFactory runnableFactory
|
||||
UUID uuid
|
||||
) {
|
||||
this.uuid = uuid;
|
||||
this.infoSystem = infoSystem;
|
||||
this.webExceptionLogger = webExceptionLogger;
|
||||
this.runnableFactory = runnableFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (!infoSystem.getConnectionSystem().isServerAvailable() || Check.isBungeeAvailable()) {
|
||||
runnableFactory.create("Generate Inspect page: " + uuid, new AbsRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
|
||||
webExceptionLogger.logIfOccurs(PlayerPageUpdateProcessor.class,
|
||||
() -> infoSystem.generateAndCachePlayerPage(uuid)
|
||||
);
|
||||
} finally {
|
||||
cancel();
|
||||
}
|
||||
}
|
||||
}).runTaskLaterAsynchronously(TimeAmount.toTicks(20L, TimeUnit.SECONDS));
|
||||
}
|
||||
ResponseCache.clearResponse(PageId.PLAYER.of(uuid));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,10 +8,12 @@ import com.djrapitops.plan.data.container.Ping;
|
|||
import com.djrapitops.plan.data.store.objects.DateObj;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plan.system.processing.CriticalRunnable;
|
||||
import com.djrapitops.plan.utilities.analysis.Median;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.OptionalInt;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Processes 60s values of a Ping list.
|
||||
|
@ -51,20 +53,25 @@ public class PingInsertProcessor implements CriticalRunnable {
|
|||
return;
|
||||
}
|
||||
|
||||
int minValue = history.stream()
|
||||
.mapToInt(DateObj::getValue)
|
||||
.filter(i -> i > 0 && i < 4000)
|
||||
.min().orElse(-1);
|
||||
int minValue = getMinValue(history);
|
||||
|
||||
double avgValue = history.stream()
|
||||
.mapToInt(DateObj::getValue)
|
||||
.filter(i -> i > 0 && i < 4000)
|
||||
.average().orElse(-1);
|
||||
int meanValue = getMeanValue(history);
|
||||
|
||||
int maxValue = max.getAsInt();
|
||||
|
||||
Ping ping = new Ping(lastDate, serverUUID, minValue, maxValue, avgValue);
|
||||
Ping ping = new Ping(lastDate, serverUUID, minValue, maxValue, meanValue);
|
||||
|
||||
database.save().ping(uuid, ping);
|
||||
}
|
||||
|
||||
int getMinValue(List<DateObj<Integer>> history) {
|
||||
return history.stream()
|
||||
.mapToInt(DateObj::getValue)
|
||||
.filter(i -> i > 0 && i < 4000)
|
||||
.min().orElse(-1);
|
||||
}
|
||||
|
||||
int getMeanValue(List<DateObj<Integer>> history) {
|
||||
return (int) Median.forInt(history.stream().map(DateObj::getValue).collect(Collectors.toList())).calculate();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,8 +10,8 @@ public enum Permissions {
|
|||
|
||||
HELP("plan.?"),
|
||||
|
||||
INSPECT("plan.inspect"),
|
||||
QUICK_INSPECT("plan.qinspect"),
|
||||
INSPECT("plan.inspect.base"),
|
||||
QUICK_INSPECT("plan.qinspect.base"),
|
||||
INSPECT_OTHER("plan.inspect.other"),
|
||||
QUICK_INSPECT_OTHER("plan.qinspect.other"),
|
||||
|
||||
|
@ -36,7 +36,7 @@ public enum Permissions {
|
|||
/**
|
||||
* Returns the permission node in plugin.yml.
|
||||
*
|
||||
* @return permission node eg. plan.inspect
|
||||
* @return permission node eg. plan.inspect.base
|
||||
*/
|
||||
public String getPermission() {
|
||||
return permission;
|
||||
|
@ -45,7 +45,7 @@ public enum Permissions {
|
|||
/**
|
||||
* Same as {@link #getPermission()}.
|
||||
*
|
||||
* @return permission node eg. plan.inspect
|
||||
* @return permission node eg. plan.inspect.base
|
||||
*/
|
||||
public String getPerm() {
|
||||
return getPermission();
|
||||
|
|
|
@ -44,6 +44,8 @@ public enum Settings implements Setting {
|
|||
AFK_THRESHOLD_MINUTES("Data.AFKThresholdMinutes"),
|
||||
KEEP_LOGS_DAYS("Plugin.KeepLogsForXDays"),
|
||||
KEEP_INACTIVE_PLAYERS_DAYS("Data.KeepInactivePlayerDataForDays"),
|
||||
PING_SERVER_ENABLE_DELAY("Data.Ping.ServerEnableDelaySeconds"),
|
||||
PING_PLAYER_LOGIN_DELAY("Data.Ping.PlayerLoginDelaySeconds"),
|
||||
|
||||
// String
|
||||
DEBUG("Plugin.Debug"),
|
||||
|
|
|
@ -201,7 +201,9 @@ public class NetworkSettings {
|
|||
AFK_THRESHOLD_MINUTES,
|
||||
DATA_GEOLOCATIONS,
|
||||
KEEP_LOGS_DAYS,
|
||||
KEEP_INACTIVE_PLAYERS_DAYS
|
||||
KEEP_INACTIVE_PLAYERS_DAYS,
|
||||
PING_SERVER_ENABLE_DELAY,
|
||||
PING_PLAYER_LOGIN_DELAY
|
||||
};
|
||||
logger.debug("NetworkSettings: Adding Config Values..");
|
||||
PlanConfig planConfig = config.get();
|
||||
|
|
|
@ -5,13 +5,16 @@
|
|||
package com.djrapitops.plan.system.tasks;
|
||||
|
||||
import com.djrapitops.plan.Plan;
|
||||
import com.djrapitops.plan.system.settings.Settings;
|
||||
import com.djrapitops.plan.system.settings.config.PlanConfig;
|
||||
import com.djrapitops.plan.system.tasks.server.*;
|
||||
import com.djrapitops.plugin.api.Check;
|
||||
import com.djrapitops.plugin.api.TimeAmount;
|
||||
import com.djrapitops.plugin.task.RunnableFactory;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* TaskSystem responsible for registering tasks for Bukkit.
|
||||
|
@ -53,8 +56,10 @@ public class BukkitTaskSystem extends ServerTaskSystem {
|
|||
super.enable();
|
||||
try {
|
||||
plugin.registerListener(pingCountTimer);
|
||||
// TODO config
|
||||
long startDelay = TimeAmount.toTicks(Settings.PING_SERVER_ENABLE_DELAY.getNumber(), TimeUnit.SECONDS);
|
||||
registerTask("PingCountTimer", pingCountTimer)
|
||||
.runTaskTimer(20L, PingCountTimer.PING_INTERVAL);
|
||||
.runTaskTimer(startDelay, 40L);
|
||||
} catch (ExceptionInInitializerError | NoClassDefFoundError ignore) {
|
||||
// Running CraftBukkit
|
||||
}
|
||||
|
|
|
@ -4,9 +4,11 @@
|
|||
*/
|
||||
package com.djrapitops.plan.system.tasks;
|
||||
|
||||
import com.djrapitops.plan.system.settings.Settings;
|
||||
import com.djrapitops.plan.system.settings.config.PlanConfig;
|
||||
import com.djrapitops.plan.system.tasks.bungee.BungeeTPSCountTimer;
|
||||
import com.djrapitops.plan.system.tasks.server.NetworkPageRefreshTask;
|
||||
import com.djrapitops.plan.system.tasks.server.PingCountTimerBungee;
|
||||
import com.djrapitops.plugin.api.TimeAmount;
|
||||
import com.djrapitops.plugin.task.AbsRunnable;
|
||||
import com.djrapitops.plugin.task.RunnableFactory;
|
||||
|
@ -55,5 +57,12 @@ public class BungeeTaskSystem extends TaskSystem {
|
|||
config.getNetworkSettings().placeSettingsToDB();
|
||||
}
|
||||
}).runTaskAsynchronously();
|
||||
|
||||
// TODO Move this elsewhere
|
||||
PingCountTimerBungee pingCountTimer = new PingCountTimerBungee();
|
||||
plugin.registerListener(pingCountTimer);
|
||||
long startDelay = TimeAmount.SECOND.ticks() * (long) Settings.PING_SERVER_ENABLE_DELAY.getNumber();
|
||||
RunnableFactory.createNew("PingCountTimer", pingCountTimer)
|
||||
.runTaskTimer(startDelay, PingCountTimerBungee.PING_INTERVAL);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,7 +48,11 @@ public class LogsFolderCleanTask extends AbsRunnable {
|
|||
} catch (NullPointerException ignore) {
|
||||
/* Ignored - not supposed to occur. */
|
||||
} finally {
|
||||
cancel();
|
||||
try {
|
||||
cancel();
|
||||
} catch (Exception ignore) {
|
||||
/* Ignored, TaskCenter concurrent modification exception, will be fixed later in apf-3.3.0. */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,8 +5,12 @@ import com.djrapitops.plan.system.settings.config.PlanConfig;
|
|||
import com.djrapitops.plan.system.tasks.server.BootAnalysisTask;
|
||||
import com.djrapitops.plan.system.tasks.server.NetworkPageRefreshTask;
|
||||
import com.djrapitops.plan.system.tasks.server.PeriodicAnalysisTask;
|
||||
import com.djrapitops.plan.system.settings.Settings;
|
||||
import com.djrapitops.plan.system.tasks.server.PingCountTimerSponge;
|
||||
import com.djrapitops.plan.system.tasks.server.SpongeTPSCountTimer;
|
||||
import com.djrapitops.plugin.task.RunnableFactory;
|
||||
import com.djrapitops.plugin.api.TimeAmount;
|
||||
import com.djrapitops.plugin.task.RunnableFactory;
|
||||
import org.spongepowered.api.Sponge;
|
||||
import org.spongepowered.api.scheduler.Task;
|
||||
|
||||
|
@ -38,6 +42,18 @@ public class SpongeTaskSystem extends ServerTaskSystem {
|
|||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
super.enable();
|
||||
|
||||
// TODO Move elsewhere
|
||||
PingCountTimerSponge pingCountTimer = new PingCountTimerSponge();
|
||||
plugin.registerListener(pingCountTimer);
|
||||
long startDelay = TimeAmount.SECOND.ticks() * (long) Settings.PING_SERVER_ENABLE_DELAY.getNumber();
|
||||
RunnableFactory.createNew("PingCountTimer", pingCountTimer)
|
||||
.runTaskTimer(startDelay, PingCountTimerSponge.PING_INTERVAL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disable() {
|
||||
super.disable();
|
||||
|
|
|
@ -8,6 +8,8 @@ import com.djrapitops.plugin.logging.console.PluginLogger;
|
|||
import com.djrapitops.plugin.logging.error.ErrorHandler;
|
||||
import com.djrapitops.plugin.task.AbsRunnable;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.OperatingSystemMXBean;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -64,4 +66,27 @@ public abstract class TPSCountTimer extends AbsRunnable {
|
|||
public int getLatestPlayersOnline() {
|
||||
return latestPlayersOnline;
|
||||
}
|
||||
|
||||
protected long getUsedMemory() {
|
||||
Runtime runtime = Runtime.getRuntime();
|
||||
long totalMemory = runtime.totalMemory();
|
||||
return (totalMemory - runtime.freeMemory()) / 1000000;
|
||||
}
|
||||
|
||||
protected double getCPUUsage() {
|
||||
double averageCPUUsage;
|
||||
|
||||
OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();
|
||||
if (osBean instanceof com.sun.management.OperatingSystemMXBean) {
|
||||
com.sun.management.OperatingSystemMXBean nativeOsBean = (com.sun.management.OperatingSystemMXBean) osBean;
|
||||
averageCPUUsage = nativeOsBean.getSystemCpuLoad();
|
||||
} else {
|
||||
int availableProcessors = osBean.getAvailableProcessors();
|
||||
averageCPUUsage = osBean.getSystemLoadAverage() / availableProcessors;
|
||||
}
|
||||
if (averageCPUUsage < 0) { // If unavailable, getSystemLoadAverage() returns -1
|
||||
averageCPUUsage = -1;
|
||||
}
|
||||
return averageCPUUsage * 100.0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* License is provided in the jar as LICENSE also here:
|
||||
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/LICENSE
|
||||
*/
|
||||
package com.djrapitops.plan.system.tasks;
|
||||
|
||||
import com.djrapitops.plan.PlanVelocity;
|
||||
import com.djrapitops.plan.system.settings.Settings;
|
||||
import com.djrapitops.plan.system.tasks.proxy.EnableConnectionTask;
|
||||
import com.djrapitops.plan.system.tasks.velocity.VelocityTPSCountTimer;
|
||||
import com.djrapitops.plan.system.tasks.server.NetworkPageRefreshTask;
|
||||
import com.djrapitops.plan.system.tasks.server.PingCountTimerVelocity;
|
||||
import com.djrapitops.plan.utilities.file.export.HtmlExport;
|
||||
import com.djrapitops.plugin.api.TimeAmount;
|
||||
import com.djrapitops.plugin.task.RunnableFactory;
|
||||
|
||||
/**
|
||||
* TaskSystem responsible for registering tasks for Velocity.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class VelocityTaskSystem extends TaskSystem {
|
||||
|
||||
private final PlanVelocity plugin;
|
||||
|
||||
public VelocityTaskSystem(PlanVelocity plugin) {
|
||||
super(new VelocityTPSCountTimer(plugin));
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
registerTasks();
|
||||
}
|
||||
|
||||
private void registerTasks() {
|
||||
registerTask(new EnableConnectionTask()).runTaskAsynchronously();
|
||||
registerTask(tpsCountTimer).runTaskTimerAsynchronously(1000, TimeAmount.SECOND.ticks());
|
||||
registerTask(new NetworkPageRefreshTask()).runTaskTimerAsynchronously(1500, TimeAmount.MINUTE.ticks());
|
||||
if (Settings.ANALYSIS_EXPORT.isTrue()) {
|
||||
registerTask(new HtmlExport(plugin)).runTaskAsynchronously();
|
||||
}
|
||||
PingCountTimerVelocity pingCountTimer = new PingCountTimerVelocity();
|
||||
plugin.registerListener(pingCountTimer);
|
||||
long startDelay = TimeAmount.SECOND.ticks() * (long) Settings.PING_SERVER_ENABLE_DELAY.getNumber();
|
||||
RunnableFactory.createNew("PingCountTimer", pingCountTimer)
|
||||
.runTaskTimer(startDelay, PingCountTimerVelocity.PING_INTERVAL);
|
||||
}
|
||||
}
|
|
@ -36,6 +36,10 @@ public class BungeeTPSCountTimer extends TPSCountTimer {
|
|||
.date(now)
|
||||
.skipTPS()
|
||||
.playersOnline(onlineCount)
|
||||
.usedCPU(getCPUUsage())
|
||||
.usedMemory(getUsedMemory())
|
||||
.entities(-1)
|
||||
.chunksLoaded(-1)
|
||||
.toTPS();
|
||||
|
||||
history.add(tps);
|
||||
|
|
|
@ -62,10 +62,7 @@ public class BukkitTPSCountTimer extends TPSCountTimer {
|
|||
private TPS calculateTPS(long diff, long now) {
|
||||
double averageCPUUsage = getCPUUsage();
|
||||
|
||||
Runtime runtime = Runtime.getRuntime();
|
||||
|
||||
long totalMemory = runtime.totalMemory();
|
||||
long usedMemory = (totalMemory - runtime.freeMemory()) / 1000000;
|
||||
long usedMemory = getUsedMemory();
|
||||
|
||||
int playersOnline = serverProperties.getOnlinePlayers();
|
||||
latestPlayersOnline = playersOnline;
|
||||
|
@ -77,22 +74,6 @@ public class BukkitTPSCountTimer extends TPSCountTimer {
|
|||
return getTPS(diff, now, averageCPUUsage, usedMemory, entityCount, loadedChunks, playersOnline);
|
||||
}
|
||||
|
||||
private double getCPUUsage() {
|
||||
double averageCPUUsage;
|
||||
|
||||
OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();
|
||||
if (osBean instanceof com.sun.management.OperatingSystemMXBean) {
|
||||
com.sun.management.OperatingSystemMXBean nativeOsBean = (com.sun.management.OperatingSystemMXBean) osBean;
|
||||
averageCPUUsage = nativeOsBean.getSystemCpuLoad();
|
||||
} else {
|
||||
int availableProcessors = osBean.getAvailableProcessors();
|
||||
averageCPUUsage = osBean.getSystemLoadAverage() / availableProcessors;
|
||||
}
|
||||
if (averageCPUUsage < 0) { // If unavailable, getSystemLoadAverage() returns -1
|
||||
averageCPUUsage = -1;
|
||||
}
|
||||
return averageCPUUsage * 100.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the TPS for Spigot / Bukkit
|
||||
|
|
|
@ -26,6 +26,7 @@ package com.djrapitops.plan.system.tasks.server;
|
|||
import com.djrapitops.plan.data.store.objects.DateObj;
|
||||
import com.djrapitops.plan.system.processing.Processing;
|
||||
import com.djrapitops.plan.system.processing.processors.Processors;
|
||||
import com.djrapitops.plan.system.settings.Settings;
|
||||
import com.djrapitops.plan.utilities.java.Reflection;
|
||||
import com.djrapitops.plugin.api.TimeAmount;
|
||||
import com.djrapitops.plugin.task.AbsRunnable;
|
||||
|
@ -57,23 +58,23 @@ import java.util.logging.Logger;
|
|||
* @author games647
|
||||
*/
|
||||
@Singleton
|
||||
public class PingCountTimer extends AbsRunnable implements Listener {
|
||||
public class PingCountTimerBukkit extends AbsRunnable implements Listener {
|
||||
|
||||
//the server is pinging the client every 40 Ticks (2 sec) - so check it then
|
||||
//https://github.com/bergerkiller/CraftSource/blob/master/net.minecraft.server/PlayerConnection.java#L178
|
||||
public static final int PING_INTERVAL = 2 * 20;
|
||||
|
||||
private static final boolean pingMethodAvailable;
|
||||
private static final boolean PING_METHOD_AVAILABLE;
|
||||
|
||||
private static final MethodHandle pingField;
|
||||
private static final MethodHandle getHandleMethod;
|
||||
private static final MethodHandle PING_FIELD;
|
||||
private static final MethodHandle GET_HANDLE_METHOD;
|
||||
|
||||
static {
|
||||
pingMethodAvailable = isPingMethodAvailable();
|
||||
PING_METHOD_AVAILABLE = isPingMethodAvailable();
|
||||
|
||||
MethodHandle localHandle = null;
|
||||
MethodHandle localPing = null;
|
||||
if (!pingMethodAvailable) {
|
||||
if (!PING_METHOD_AVAILABLE) {
|
||||
Class<?> craftPlayerClass = Reflection.getCraftBukkitClass("entity.CraftPlayer");
|
||||
Class<?> entityPlayer = Reflection.getMinecraftClass("EntityPlayer");
|
||||
|
||||
|
@ -92,8 +93,8 @@ public class PingCountTimer extends AbsRunnable implements Listener {
|
|||
}
|
||||
}
|
||||
|
||||
getHandleMethod = localHandle;
|
||||
pingField = localPing;
|
||||
GET_HANDLE_METHOD = localHandle;
|
||||
PING_FIELD = localPing;
|
||||
}
|
||||
|
||||
private final Map<UUID, List<DateObj<Integer>>> playerHistory;
|
||||
|
@ -103,7 +104,7 @@ public class PingCountTimer extends AbsRunnable implements Listener {
|
|||
private final RunnableFactory runnableFactory;
|
||||
|
||||
@Inject
|
||||
public PingCountTimer(
|
||||
public PingCountTimerBukkit(
|
||||
Processors processors,
|
||||
Processing processing,
|
||||
RunnableFactory runnableFactory
|
||||
|
@ -157,7 +158,7 @@ public class PingCountTimer extends AbsRunnable implements Listener {
|
|||
}
|
||||
|
||||
private int getPing(Player player) {
|
||||
if (pingMethodAvailable) {
|
||||
if (PING_METHOD_AVAILABLE) {
|
||||
return player.spigot().getPing();
|
||||
}
|
||||
|
||||
|
@ -166,8 +167,8 @@ public class PingCountTimer extends AbsRunnable implements Listener {
|
|||
|
||||
private int getReflectionPing(Player player) {
|
||||
try {
|
||||
Object entityPlayer = getHandleMethod.invoke(player);
|
||||
return (int) pingField.invoke(entityPlayer);
|
||||
Object entityPlayer = GET_HANDLE_METHOD.invoke(player);
|
||||
return (int) PING_FIELD.invoke(entityPlayer);
|
||||
} catch (Exception ex) {
|
||||
return -1;
|
||||
} catch (Throwable throwable) {
|
||||
|
@ -184,8 +185,8 @@ public class PingCountTimer extends AbsRunnable implements Listener {
|
|||
if (player.isOnline()) {
|
||||
addPlayer(player);
|
||||
}
|
||||
}
|
||||
}).runTaskLater(TimeAmount.toTicks(15L, TimeUnit.SECONDS));
|
||||
}// TODO Config
|
||||
}).runTaskLater(TimeAmount.toTicks(Settings.PING_PLAYER_LOGIN_DELAY.getNumber(), TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
@EventHandler
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016-2018
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.djrapitops.plan.system.tasks.server;
|
||||
|
||||
import com.djrapitops.plan.data.store.objects.DateObj;
|
||||
import com.djrapitops.plan.system.processing.Processing;
|
||||
import com.djrapitops.plan.system.processing.processors.player.PingInsertProcessor;
|
||||
import com.djrapitops.plan.system.settings.Settings;
|
||||
import com.djrapitops.plugin.api.TimeAmount;
|
||||
import com.djrapitops.plugin.task.AbsRunnable;
|
||||
import com.djrapitops.plugin.task.RunnableFactory;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.event.ServerConnectedEvent;
|
||||
import net.md_5.bungee.api.event.ServerDisconnectEvent;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Task that handles player ping calculation on Bungee based servers.
|
||||
*
|
||||
* @author BrainStone
|
||||
*/
|
||||
public class PingCountTimerBungee extends AbsRunnable implements Listener {
|
||||
|
||||
//the server is pinging the client every 40 Ticks (2 sec) - so check it then
|
||||
//https://github.com/bergerkiller/CraftSource/blob/master/net.minecraft.server/PlayerConnection.java#L178
|
||||
public static final int PING_INTERVAL = 2 * 20;
|
||||
|
||||
private final Map<UUID, List<DateObj<Integer>>> playerHistory = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
List<UUID> loggedOut = new ArrayList<>();
|
||||
long time = System.currentTimeMillis();
|
||||
playerHistory.forEach((uuid, history) -> {
|
||||
ProxiedPlayer player = ProxyServer.getInstance().getPlayer(uuid);
|
||||
if (player != null) {
|
||||
int ping = getPing(player);
|
||||
if (ping < -1 || ping > TimeAmount.SECOND.ms() * 8L) {
|
||||
// Don't accept bad values
|
||||
return;
|
||||
}
|
||||
history.add(new DateObj<>(time, ping));
|
||||
if (history.size() >= 30) {
|
||||
Processing.submit(new PingInsertProcessor(uuid, new ArrayList<>(history)));
|
||||
history.clear();
|
||||
}
|
||||
} else {
|
||||
loggedOut.add(uuid);
|
||||
}
|
||||
});
|
||||
loggedOut.forEach(playerHistory::remove);
|
||||
}
|
||||
|
||||
public void addPlayer(ProxiedPlayer player) {
|
||||
playerHistory.put(player.getUniqueId(), new ArrayList<>());
|
||||
}
|
||||
|
||||
public void removePlayer(ProxiedPlayer player) {
|
||||
playerHistory.remove(player.getUniqueId());
|
||||
}
|
||||
|
||||
private int getPing(ProxiedPlayer player) {
|
||||
return player.getPing();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerJoin(ServerConnectedEvent joinEvent) {
|
||||
ProxiedPlayer player = joinEvent.getPlayer();
|
||||
RunnableFactory.createNew("Add Player to Ping list", new AbsRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (player.isConnected()) {
|
||||
addPlayer(player);
|
||||
}
|
||||
}
|
||||
}).runTaskLater(TimeAmount.SECOND.ticks() * (long) Settings.PING_PLAYER_LOGIN_DELAY.getNumber());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerQuit(ServerDisconnectEvent quitEvent) {
|
||||
removePlayer(quitEvent.getPlayer());
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
playerHistory.clear();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016-2018
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.djrapitops.plan.system.tasks.server;
|
||||
|
||||
import com.djrapitops.plan.data.store.objects.DateObj;
|
||||
import com.djrapitops.plan.system.processing.Processing;
|
||||
import com.djrapitops.plan.system.processing.processors.player.PingInsertProcessor;
|
||||
import com.djrapitops.plan.system.settings.Settings;
|
||||
import com.djrapitops.plugin.api.TimeAmount;
|
||||
import com.djrapitops.plugin.task.AbsRunnable;
|
||||
import com.djrapitops.plugin.task.RunnableFactory;
|
||||
import org.spongepowered.api.Sponge;
|
||||
import org.spongepowered.api.entity.living.player.Player;
|
||||
import org.spongepowered.api.event.Listener;
|
||||
import org.spongepowered.api.event.network.ClientConnectionEvent;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Task that handles player ping calculation on Sponge based servers.
|
||||
*
|
||||
* @author BrainStone
|
||||
*/
|
||||
public class PingCountTimerSponge extends AbsRunnable {
|
||||
|
||||
//the server is pinging the client every 40 Ticks (2 sec) - so check it then
|
||||
//https://github.com/bergerkiller/CraftSource/blob/master/net.minecraft.server/PlayerConnection.java#L178
|
||||
public static final int PING_INTERVAL = 2 * 20;
|
||||
|
||||
private final Map<UUID, List<DateObj<Integer>>> playerHistory = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
List<UUID> loggedOut = new ArrayList<>();
|
||||
long time = System.currentTimeMillis();
|
||||
playerHistory.forEach((uuid, history) -> {
|
||||
Optional<Player> player = Sponge.getServer().getPlayer(uuid);
|
||||
if (player.isPresent()) {
|
||||
int ping = getPing(player.get());
|
||||
if (ping < -1 || ping > TimeAmount.SECOND.ms() * 8L) {
|
||||
// Don't accept bad values
|
||||
return;
|
||||
}
|
||||
history.add(new DateObj<>(time, ping));
|
||||
if (history.size() >= 30) {
|
||||
Processing.submit(new PingInsertProcessor(uuid, new ArrayList<>(history)));
|
||||
history.clear();
|
||||
}
|
||||
} else {
|
||||
loggedOut.add(uuid);
|
||||
}
|
||||
});
|
||||
loggedOut.forEach(playerHistory::remove);
|
||||
}
|
||||
|
||||
public void addPlayer(Player player) {
|
||||
playerHistory.put(player.getUniqueId(), new ArrayList<>());
|
||||
}
|
||||
|
||||
public void removePlayer(Player player) {
|
||||
playerHistory.remove(player.getUniqueId());
|
||||
}
|
||||
|
||||
private int getPing(Player player) {
|
||||
return player.getConnection().getLatency();
|
||||
}
|
||||
|
||||
@Listener
|
||||
public void onPlayerJoin(ClientConnectionEvent.Join joinEvent) {
|
||||
Player player = joinEvent.getTargetEntity();
|
||||
RunnableFactory.createNew("Add Player to Ping list", new AbsRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (player.isOnline()) {
|
||||
addPlayer(player);
|
||||
}
|
||||
}
|
||||
}).runTaskLater(TimeAmount.SECOND.ticks() * (long) Settings.PING_PLAYER_LOGIN_DELAY.getNumber());
|
||||
}
|
||||
|
||||
@Listener
|
||||
public void onPlayerQuit(ClientConnectionEvent.Disconnect quitEvent) {
|
||||
removePlayer(quitEvent.getTargetEntity());
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
playerHistory.clear();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016-2018
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.djrapitops.plan.system.tasks.server;
|
||||
|
||||
import com.djrapitops.plan.PlanVelocity;
|
||||
import com.djrapitops.plan.data.store.objects.DateObj;
|
||||
import com.djrapitops.plan.system.processing.Processing;
|
||||
import com.djrapitops.plan.system.processing.processors.player.PingInsertProcessor;
|
||||
import com.djrapitops.plan.system.settings.Settings;
|
||||
import com.djrapitops.plugin.api.TimeAmount;
|
||||
import com.djrapitops.plugin.task.AbsRunnable;
|
||||
import com.djrapitops.plugin.task.RunnableFactory;
|
||||
import com.velocitypowered.api.event.Subscribe;
|
||||
import com.velocitypowered.api.event.connection.DisconnectEvent;
|
||||
import com.velocitypowered.api.event.player.ServerConnectedEvent;
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Task that handles player ping calculation on Velocity based servers.
|
||||
*
|
||||
* Based on PingCountTimerBungee
|
||||
*
|
||||
* @author MicleBrick
|
||||
*/
|
||||
public class PingCountTimerVelocity extends AbsRunnable {
|
||||
|
||||
//the server is pinging the client every 40 Ticks (2 sec) - so check it then
|
||||
//https://github.com/bergerkiller/CraftSource/blob/master/net.minecraft.server/PlayerConnection.java#L178
|
||||
public static final int PING_INTERVAL = 2 * 20;
|
||||
|
||||
private final Map<UUID, List<DateObj<Integer>>> playerHistory = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
List<UUID> loggedOut = new ArrayList<>();
|
||||
long time = System.currentTimeMillis();
|
||||
playerHistory.forEach((uuid, history) -> {
|
||||
Player player = PlanVelocity.getInstance().getProxy().getPlayer(uuid).orElse(null);
|
||||
if (player != null) {
|
||||
int ping = getPing(player);
|
||||
if (ping < -1 || ping > TimeAmount.SECOND.ms() * 8L) {
|
||||
// Don't accept bad values
|
||||
return;
|
||||
}
|
||||
history.add(new DateObj<>(time, ping));
|
||||
if (history.size() >= 30) {
|
||||
Processing.submit(new PingInsertProcessor(uuid, new ArrayList<>(history)));
|
||||
history.clear();
|
||||
}
|
||||
} else {
|
||||
loggedOut.add(uuid);
|
||||
}
|
||||
});
|
||||
loggedOut.forEach(playerHistory::remove);
|
||||
}
|
||||
|
||||
public void addPlayer(Player player) {
|
||||
playerHistory.put(player.getUniqueId(), new ArrayList<>());
|
||||
}
|
||||
|
||||
public void removePlayer(Player player) {
|
||||
playerHistory.remove(player.getUniqueId());
|
||||
}
|
||||
|
||||
private int getPing(Player player) {
|
||||
return (int) player.getPing();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onPlayerJoin(ServerConnectedEvent joinEvent) {
|
||||
Player player = joinEvent.getPlayer();
|
||||
RunnableFactory.createNew("Add Player to Ping list", new AbsRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (player.isActive()) {
|
||||
addPlayer(player);
|
||||
}
|
||||
}
|
||||
}).runTaskLater(TimeAmount.SECOND.ticks() * (long) Settings.PING_PLAYER_LOGIN_DELAY.getNumber());
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onPlayerQuit(DisconnectEvent quitEvent) {
|
||||
removePlayer(quitEvent.getPlayer());
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
playerHistory.clear();
|
||||
}
|
||||
}
|
|
@ -56,18 +56,9 @@ public class SpongeTPSCountTimer extends TPSCountTimer {
|
|||
* @return the TPS
|
||||
*/
|
||||
private TPS calculateTPS(long now) {
|
||||
OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean();
|
||||
int availableProcessors = operatingSystemMXBean.getAvailableProcessors();
|
||||
double averageCPUUsage = operatingSystemMXBean.getSystemLoadAverage() / availableProcessors * 100.0;
|
||||
double averageCPUUsage = getCPUUsage();
|
||||
|
||||
if (averageCPUUsage < 0) { // If unavailable, getSystemLoadAverage() returns -1
|
||||
averageCPUUsage = -1;
|
||||
}
|
||||
|
||||
Runtime runtime = Runtime.getRuntime();
|
||||
|
||||
long totalMemory = runtime.totalMemory();
|
||||
long usedMemory = (totalMemory - runtime.freeMemory()) / 1000000;
|
||||
long usedMemory = getUsedMemory();
|
||||
|
||||
double tps = Sponge.getGame().getServer().getTicksPerSecond();
|
||||
int playersOnline = serverProperties.getOnlinePlayers();
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
package com.djrapitops.plan.system.tasks.velocity;
|
||||
|
||||
import com.djrapitops.plan.PlanVelocity;
|
||||
import com.djrapitops.plan.data.container.TPS;
|
||||
import com.djrapitops.plan.data.container.builders.TPSBuilder;
|
||||
import com.djrapitops.plan.system.info.server.ServerInfo;
|
||||
import com.djrapitops.plan.system.tasks.TPSCountTimer;
|
||||
|
||||
public class VelocityTPSCountTimer extends TPSCountTimer<PlanVelocity> {
|
||||
|
||||
public VelocityTPSCountTimer(PlanVelocity plugin) {
|
||||
super(plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addNewTPSEntry(long nanoTime, long now) {
|
||||
int onlineCount = ServerInfo.getServerProperties().getOnlinePlayers();
|
||||
TPS tps = TPSBuilder.get()
|
||||
.date(now)
|
||||
.skipTPS()
|
||||
.playersOnline(onlineCount)
|
||||
.usedCPU(getCPUUsage())
|
||||
.usedMemory(getUsedMemory())
|
||||
.entities(-1)
|
||||
.chunksLoaded(-1)
|
||||
.toTPS();
|
||||
|
||||
history.add(tps);
|
||||
latestPlayersOnline = onlineCount;
|
||||
}
|
||||
}
|
|
@ -12,6 +12,7 @@ import com.djrapitops.plugin.api.Check;
|
|||
import com.djrapitops.plugin.logging.L;
|
||||
import com.djrapitops.plugin.logging.console.PluginLogger;
|
||||
import com.djrapitops.plugin.logging.error.ErrorHandler;
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import com.sun.net.httpserver.HttpServer;
|
||||
import com.sun.net.httpserver.HttpsConfigurator;
|
||||
import com.sun.net.httpserver.HttpsParameters;
|
||||
|
@ -29,9 +30,7 @@ import java.nio.file.Paths;
|
|||
import java.security.*;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
/**
|
||||
* @author Rsl1122
|
||||
|
@ -121,7 +120,11 @@ public class WebServer implements SubSystem {
|
|||
}
|
||||
server.createContext("/", requestHandler);
|
||||
|
||||
server.setExecutor(new ThreadPoolExecutor(4, 8, 30, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100)));
|
||||
ExecutorService executor = new ThreadPoolExecutor(
|
||||
4, 8, 30, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100),
|
||||
new ThreadFactoryBuilder().setNameFormat("Plan WebServer Thread-%d").build()
|
||||
);
|
||||
server.setExecutor(executor);
|
||||
server.start();
|
||||
|
||||
enabled = true;
|
||||
|
@ -212,12 +215,26 @@ public class WebServer implements SubSystem {
|
|||
@Override
|
||||
public void disable() {
|
||||
if (server != null) {
|
||||
shutdown();
|
||||
logger.info(locale.getString(PluginLang.DISABLED_WEB_SERVER));
|
||||
server.stop(0);
|
||||
}
|
||||
enabled = false;
|
||||
}
|
||||
|
||||
private void shutdown() {
|
||||
server.stop(0);
|
||||
Executor executor = server.getExecutor();
|
||||
if (executor instanceof ExecutorService) {
|
||||
ExecutorService service = (ExecutorService) executor;
|
||||
service.shutdown();
|
||||
try {
|
||||
service.awaitTermination(5, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException timeoutExceededEx) {
|
||||
service.shutdownNow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getProtocol() {
|
||||
return usingHttps ? "https" : "http";
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
package com.djrapitops.plan.system.webserver.cache;
|
||||
|
||||
import com.djrapitops.plan.system.webserver.response.Response;
|
||||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
|
@ -19,7 +20,9 @@ import java.util.function.Supplier;
|
|||
*/
|
||||
public class ResponseCache {
|
||||
|
||||
private static final Map<String, Response> cache = new HashMap<>();
|
||||
private static final Cache<String, Response> cache = Caffeine.newBuilder()
|
||||
.expireAfterWrite(5, TimeUnit.MINUTES)
|
||||
.build();
|
||||
|
||||
/**
|
||||
* Constructor used to hide the public constructor
|
||||
|
@ -41,17 +44,7 @@ public class ResponseCache {
|
|||
* @return The Response that was cached or created by the the {@link Response} {@link Supplier}
|
||||
*/
|
||||
public static Response loadResponse(String identifier, Supplier<Response> loader) {
|
||||
Response response = loadResponse(identifier);
|
||||
|
||||
if (response != null) {
|
||||
return response;
|
||||
}
|
||||
|
||||
response = loader.get();
|
||||
|
||||
cache.put(identifier, response);
|
||||
|
||||
return response;
|
||||
return cache.get(identifier, k -> loader.get());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -61,7 +54,7 @@ public class ResponseCache {
|
|||
* @return The Response that was cached or {@code null} if it wasn't
|
||||
*/
|
||||
public static Response loadResponse(String identifier) {
|
||||
return cache.get(identifier);
|
||||
return cache.getIfPresent(identifier);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -84,21 +77,25 @@ public class ResponseCache {
|
|||
* @return true if the page is cached
|
||||
*/
|
||||
public static boolean isCached(String identifier) {
|
||||
return cache.containsKey(identifier);
|
||||
return cache.getIfPresent(identifier) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the cache from all its contents.
|
||||
*/
|
||||
public static void clearCache() {
|
||||
cache.clear();
|
||||
cache.invalidateAll();
|
||||
}
|
||||
|
||||
public static Set<String> getCacheKeys() {
|
||||
return cache.keySet();
|
||||
return cache.asMap().keySet();
|
||||
}
|
||||
|
||||
public static long getEstimatedSize() {
|
||||
return cache.estimatedSize();
|
||||
}
|
||||
|
||||
public static void clearResponse(String identifier) {
|
||||
cache.remove(identifier);
|
||||
cache.invalidate(identifier);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,8 +96,10 @@ public abstract class Response {
|
|||
}
|
||||
sentContent = theme.replaceThemeColors(sentContent);
|
||||
|
||||
try (GZIPOutputStream out = new GZIPOutputStream(exchange.getResponseBody());
|
||||
ByteArrayInputStream bis = new ByteArrayInputStream(sentContent.getBytes(StandardCharsets.UTF_8))) {
|
||||
try (
|
||||
GZIPOutputStream out = new GZIPOutputStream(exchange.getResponseBody());
|
||||
ByteArrayInputStream bis = new ByteArrayInputStream(sentContent.getBytes(StandardCharsets.UTF_8))
|
||||
) {
|
||||
byte[] buffer = new byte[2048];
|
||||
int count;
|
||||
while ((count = bis.read(buffer)) != -1) {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
package com.djrapitops.plan.system.webserver.response.errors;
|
||||
|
||||
import com.djrapitops.plan.system.file.PlanFiles;
|
||||
import com.djrapitops.plan.system.webserver.response.Response;
|
||||
import com.djrapitops.plan.system.webserver.response.pages.PageResponse;
|
||||
import org.apache.commons.text.StringSubstitutor;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -17,7 +17,7 @@ import java.util.Map;
|
|||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class ErrorResponse extends Response {
|
||||
public class ErrorResponse extends PageResponse {
|
||||
|
||||
private String title;
|
||||
private String paragraph;
|
||||
|
|
|
@ -6,7 +6,7 @@ import com.djrapitops.plan.system.webserver.response.Response;
|
|||
* @author Rsl1122
|
||||
* @since 3.5.2
|
||||
*/
|
||||
public class AnalysisPageResponse extends Response {
|
||||
public class AnalysisPageResponse extends PageResponse {
|
||||
|
||||
public AnalysisPageResponse(String html) {
|
||||
super.setHeader("HTTP/1.1 200 OK");
|
||||
|
|
|
@ -8,13 +8,14 @@ import org.apache.commons.text.StringSubstitutor;
|
|||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Rsl1122
|
||||
* @since 3.5.2
|
||||
*/
|
||||
public class InspectPageResponse extends Response {
|
||||
public class InspectPageResponse extends PageResponse {
|
||||
|
||||
private final UUID uuid;
|
||||
|
||||
|
@ -39,4 +40,18 @@ public class InspectPageResponse extends Response {
|
|||
private String[] getCalculating() {
|
||||
return new String[]{"<li><i class=\"fa fa-spin fa-refresh\"></i><a> Calculating...</a></li>", ""};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof InspectPageResponse)) return false;
|
||||
if (!super.equals(o)) return false;
|
||||
InspectPageResponse that = (InspectPageResponse) o;
|
||||
return Objects.equals(uuid, that.uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), uuid);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@ package com.djrapitops.plan.system.webserver.response.pages;
|
|||
|
||||
import com.djrapitops.plan.api.exceptions.ParseException;
|
||||
import com.djrapitops.plan.system.webserver.response.Response;
|
||||
import com.djrapitops.plan.data.store.containers.NetworkContainer;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plan.utilities.html.pages.NetworkPage;
|
||||
|
||||
/**
|
||||
|
@ -9,7 +11,7 @@ import com.djrapitops.plan.utilities.html.pages.NetworkPage;
|
|||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class NetworkPageResponse extends Response {
|
||||
public class NetworkPageResponse extends PageResponse {
|
||||
|
||||
public NetworkPageResponse(NetworkPage networkPage) throws ParseException {
|
||||
setHeader("HTTP/1.1 200 OK");
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
package com.djrapitops.plan.system.webserver.response.pages;
|
||||
|
||||
import com.djrapitops.plan.system.webserver.response.Response;
|
||||
import com.djrapitops.plan.system.webserver.response.ResponseType;
|
||||
import com.googlecode.htmlcompressor.compressor.HtmlCompressor;
|
||||
|
||||
/**
|
||||
* Response for all HTML Page responses.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class PageResponse extends Response {
|
||||
|
||||
public PageResponse(ResponseType type) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
public PageResponse() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContent(String content) {
|
||||
HtmlCompressor compressor = new HtmlCompressor();
|
||||
compressor.setRemoveIntertagSpaces(true);
|
||||
super.setContent(compressor.compress(content));
|
||||
}
|
||||
}
|
|
@ -1,14 +1,13 @@
|
|||
package com.djrapitops.plan.system.webserver.response.pages;
|
||||
|
||||
import com.djrapitops.plan.api.exceptions.ParseException;
|
||||
import com.djrapitops.plan.system.webserver.response.Response;
|
||||
import com.djrapitops.plan.utilities.html.pages.PlayersPage;
|
||||
|
||||
/**
|
||||
* @author Rsl1122
|
||||
* @since 3.5.2
|
||||
*/
|
||||
public class PlayersPageResponse extends Response {
|
||||
public class PlayersPageResponse extends PageResponse {
|
||||
|
||||
public PlayersPageResponse(PlayersPage playersPage) throws ParseException {
|
||||
setHeader("HTTP/1.1 200 OK");
|
||||
|
|
|
@ -8,7 +8,7 @@ import com.djrapitops.plan.data.element.InspectContainer;
|
|||
import com.djrapitops.plan.data.plugin.HookHandler;
|
||||
import com.djrapitops.plan.data.plugin.PluginData;
|
||||
import com.djrapitops.plan.system.info.server.ServerInfo;
|
||||
import com.djrapitops.plan.system.webserver.response.Response;
|
||||
import com.djrapitops.plan.system.webserver.response.pages.PageResponse;
|
||||
import com.djrapitops.plan.utilities.comparators.PluginDataNameComparator;
|
||||
import com.djrapitops.plan.utilities.html.Html;
|
||||
import com.djrapitops.plan.utilities.html.HtmlStructure;
|
||||
|
@ -23,7 +23,7 @@ import java.util.*;
|
|||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class InspectPagePluginsContent extends Response {
|
||||
public class InspectPagePluginsContent extends PageResponse {
|
||||
|
||||
// ServerUUID, {nav, html}
|
||||
private final Map<UUID, String[]> pluginsTab;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*/
|
||||
package com.djrapitops.plan.system.webserver.response.pages.parts;
|
||||
|
||||
import com.djrapitops.plan.system.webserver.response.Response;
|
||||
import com.djrapitops.plan.system.webserver.response.pages.PageResponse;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
@ -15,7 +15,7 @@ import java.util.*;
|
|||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class NetworkPageContent extends Response {
|
||||
public class NetworkPageContent extends PageResponse {
|
||||
|
||||
private final Map<String, String> content;
|
||||
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
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.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class Median {
|
||||
|
||||
private final List<Long> 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) {
|
||||
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);
|
||||
}
|
||||
|
||||
public double calculate() {
|
||||
if (values.isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
if (size % 2 == 0) {
|
||||
return calculateEven();
|
||||
} else {
|
||||
return calculateOdd();
|
||||
}
|
||||
}
|
||||
|
||||
private double calculateEven() {
|
||||
int half = size / 2;
|
||||
double x1 = values.get(half);
|
||||
double x2 = values.get(half - 1);
|
||||
return (x1 + x2) / 2;
|
||||
}
|
||||
|
||||
private double calculateOdd() {
|
||||
int half = size / 2;
|
||||
return (double) values.get(half);
|
||||
}
|
||||
}
|
|
@ -65,20 +65,13 @@ public class TimeAmountFormatter implements Formatter<Long> {
|
|||
return formattedTime;
|
||||
}
|
||||
|
||||
private void appendSeconds(StringBuilder builder, long seconds, long minutes, long hours, String fHours, String fMinutes, String fSeconds) {
|
||||
if (seconds != 0) {
|
||||
String s = fSeconds.replace(SECONDS_PH, String.valueOf(seconds));
|
||||
if (minutes == 0 && s.contains(MINUTES_PH)) {
|
||||
if (hours == 0 && fMinutes.contains(HOURS_PH)) {
|
||||
builder.append(fHours.replace(ZERO_PH, "0").replace(HOURS_PH, "0"));
|
||||
}
|
||||
builder.append(fMinutes.replace(HOURS_PH, "").replace(ZERO_PH, "0").replace(MINUTES_PH, "0"));
|
||||
}
|
||||
s = s.replace(MINUTES_PH, "");
|
||||
if (s.contains(ZERO_PH) && String.valueOf(seconds).length() == 1) {
|
||||
private void appendHours(StringBuilder builder, long hours, String fHours) {
|
||||
if (hours != 0) {
|
||||
String h = fHours.replace(HOURS_PH, String.valueOf(hours));
|
||||
if (h.contains(ZERO_PH) && String.valueOf(hours).length() == 1) {
|
||||
builder.append('0');
|
||||
}
|
||||
builder.append(s);
|
||||
builder.append(h);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -97,13 +90,20 @@ public class TimeAmountFormatter implements Formatter<Long> {
|
|||
}
|
||||
}
|
||||
|
||||
private void appendHours(StringBuilder builder, long hours, String fHours) {
|
||||
if (hours != 0) {
|
||||
String h = fHours.replace(HOURS_PH, String.valueOf(hours));
|
||||
if (h.contains(ZERO_PH) && String.valueOf(hours).length() == 1) {
|
||||
private void appendSeconds(StringBuilder builder, long seconds, long minutes, long hours, String fHours, String fMinutes, String fSeconds) {
|
||||
if (seconds != 0 || fSeconds.contains(ZERO_PH)) {
|
||||
String s = fSeconds.replace(SECONDS_PH, String.valueOf(seconds));
|
||||
if (minutes == 0 && s.contains(MINUTES_PH)) {
|
||||
if (hours == 0 && fMinutes.contains(HOURS_PH)) {
|
||||
builder.append(fHours.replace(ZERO_PH, "0").replace(HOURS_PH, "0"));
|
||||
}
|
||||
builder.append(fMinutes.replace(HOURS_PH, "").replace(ZERO_PH, "0").replace(MINUTES_PH, "0"));
|
||||
}
|
||||
s = s.replace(MINUTES_PH, "");
|
||||
if (s.contains(ZERO_PH) && String.valueOf(seconds).length() == 1) {
|
||||
builder.append('0');
|
||||
}
|
||||
builder.append(h);
|
||||
builder.append(s);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
package com.djrapitops.plan.utilities.html.graphs;
|
||||
|
||||
import com.djrapitops.plan.data.store.mutators.formatting.Formatters;
|
||||
|
||||
/**
|
||||
* Utility for creating ProgressBars.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class ProgressBar {
|
||||
|
||||
private final int obtained;
|
||||
private final int max;
|
||||
|
||||
private final String color;
|
||||
|
||||
public ProgressBar(int obtained, int max) {
|
||||
this(obtained, max, "teal");
|
||||
}
|
||||
|
||||
public ProgressBar(int obtained, int max, String color) {
|
||||
this.obtained = obtained;
|
||||
this.max = max;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public String toHtml() {
|
||||
double percentage = obtained * 1.0 / max;
|
||||
int percentageRounded = (int) percentage;
|
||||
|
||||
return "<div class=\"progress\"><div class=\"progress-bar bg-" + color + "\" role=\"progressbar\"" +
|
||||
" aria-valuenow=\"" + obtained + "\"" +
|
||||
" aria-valuemin=\"0\" aria-valuemax=\"" + max + "\"" +
|
||||
" style=\"width: " + percentageRounded + "%;\">" +
|
||||
obtained + " / " + max + " (" + Formatters.percentage().apply(percentage) + ")" +
|
||||
"</div></div>";
|
||||
}
|
||||
|
||||
}
|
|
@ -10,6 +10,7 @@ import com.djrapitops.plan.data.store.keys.NetworkKeys;
|
|||
import com.djrapitops.plan.system.file.PlanFiles;
|
||||
import com.djrapitops.plan.system.info.server.properties.ServerProperties;
|
||||
import com.djrapitops.plan.utilities.formatting.PlaceholderReplacer;
|
||||
import com.djrapitops.plan.utilities.html.structure.AnalysisPluginsTabContentCreator;
|
||||
|
||||
import static com.djrapitops.plan.data.store.keys.NetworkKeys.*;
|
||||
|
||||
|
@ -55,6 +56,14 @@ public class NetworkPage implements Page {
|
|||
SERVERS_TAB
|
||||
);
|
||||
|
||||
// TODO Fix
|
||||
String[] content = AnalysisPluginsTabContentCreator.createContent(networkContainer.getUnsafe(NetworkKeys.PLAYERS_MUTATOR), null);
|
||||
String nav = content[0];
|
||||
String tabs = content[1];
|
||||
|
||||
placeholderReplacer.put("navPluginsTabs", nav);
|
||||
placeholderReplacer.put("tabsPlugins", tabs);
|
||||
|
||||
return placeholderReplacer.apply(files.readCustomizableResourceFlat("web/network.html"));
|
||||
} catch (Exception e) {
|
||||
throw new ParseException(e);
|
||||
|
|
|
@ -55,7 +55,7 @@ public class AnalysisPluginsTabContentCreator {
|
|||
com.djrapitops.plan.data.store.containers.AnalysisContainer analysisContainer
|
||||
) {
|
||||
PlayersMutator mutator = analysisContainer.getValue(AnalysisKeys.PLAYERS_MUTATOR).orElse(new PlayersMutator(new ArrayList<>()));
|
||||
|
||||
|
||||
if (mutator.all().isEmpty()) {
|
||||
return new String[]{"<li><a>No Data</a></li>", ""};
|
||||
}
|
||||
|
@ -143,6 +143,7 @@ public class AnalysisPluginsTabContentCreator {
|
|||
errorHandler.log(L.WARN, this.getClass(), e);
|
||||
} finally {
|
||||
timings.end(DebugChannels.ANALYSIS, "Source " + source.getSourcePlugin());
|
||||
source.setAnalysisData(null);
|
||||
}
|
||||
});
|
||||
return containers;
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
name: Plan
|
||||
author: Rsl1122
|
||||
main: com.djrapitops.plan.PlanBungee
|
||||
version: 4.4.3
|
||||
version: 4.4.7
|
||||
softdepend:
|
||||
- AdvancedBan
|
||||
- LiteBans
|
||||
- LuckPerms
|
||||
- ViaVersion
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user