Merge pull request #376 from Rsl1122/4.0.3

Pull Request for 4.0.3
This commit is contained in:
Rsl1122 2017-10-29 13:21:23 +02:00 committed by GitHub
commit fefe7e0824
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
58 changed files with 548 additions and 279 deletions

View File

@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.djrapitops</groupId> <groupId>com.djrapitops</groupId>
<artifactId>Plan</artifactId> <artifactId>Plan</artifactId>
<version>4.0.0</version> <version>4.0.3</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<repositories> <repositories>
<repository> <repository>
@ -70,7 +70,7 @@
<dependency> <dependency>
<groupId>com.djrapitops</groupId> <groupId>com.djrapitops</groupId>
<artifactId>PlanPluginBridge</artifactId> <artifactId>PlanPluginBridge</artifactId>
<version>4.0.0</version> <version>4.0.3</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<!-- Testing --> <!-- Testing -->

View File

@ -10,7 +10,7 @@ import com.djrapitops.plugin.settings.ColorScheme;
import com.djrapitops.plugin.task.AbsRunnable; import com.djrapitops.plugin.task.AbsRunnable;
import main.java.com.djrapitops.plan.api.IPlan; import main.java.com.djrapitops.plan.api.IPlan;
import main.java.com.djrapitops.plan.api.exceptions.DatabaseInitException; import main.java.com.djrapitops.plan.api.exceptions.DatabaseInitException;
import main.java.com.djrapitops.plan.command.commands.ReloadCommand; import main.java.com.djrapitops.plan.command.PlanBungeeCommand;
import main.java.com.djrapitops.plan.database.Database; import main.java.com.djrapitops.plan.database.Database;
import main.java.com.djrapitops.plan.database.databases.MySQLDB; import main.java.com.djrapitops.plan.database.databases.MySQLDB;
import main.java.com.djrapitops.plan.locale.Locale; import main.java.com.djrapitops.plan.locale.Locale;
@ -27,7 +27,7 @@ import main.java.com.djrapitops.plan.utilities.Benchmark;
import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ChatColor;
import java.io.InputStream; import java.io.InputStream;
import java.util.List; import java.sql.SQLException;
import java.util.UUID; import java.util.UUID;
/** /**
@ -66,10 +66,10 @@ public class PlanBungee extends BungeePlugin<PlanBungee> implements IPlan {
Log.info(Locale.get(Msg.ENABLE_DB_INIT).toString()); Log.info(Locale.get(Msg.ENABLE_DB_INIT).toString());
initDatabase(); initDatabase();
registerCommand(new ReloadCommand(this)); registerCommand(new PlanBungeeCommand(this));
String ip = variableHolder.getIp(); String ip = variableHolder.getIp();
if ("0.0.0.0" .equals(ip)) { 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.error("IP setting still 0.0.0.0 - Configure AlternativeIP/IP that connects to the Proxy server.");
Log.info("Player Analytics partially enabled (Use /planbungee to reload config)"); Log.info("Player Analytics partially enabled (Use /planbungee to reload config)");
return; return;
@ -98,6 +98,12 @@ public class PlanBungee extends BungeePlugin<PlanBungee> implements IPlan {
}).runTaskAsynchronously(); }).runTaskAsynchronously();
getRunnableFactory().createNew("Player Count task", new TPSCountTimer(this)) getRunnableFactory().createNew("Player Count task", new TPSCountTimer(this))
.runTaskTimerAsynchronously(1000, TimeAmount.SECOND.ticks()); .runTaskTimerAsynchronously(1000, TimeAmount.SECOND.ticks());
getRunnableFactory().createNew("NetworkPageContentUpdateTask", new AbsRunnable("NetworkPageContentUpdateTask") {
@Override
public void run() {
infoManager.updateNetworkPageContent();
}
}).runTaskTimerAsynchronously(1500, TimeAmount.MINUTE.ticks());
// getProxy().registerChannel("Plan"); // getProxy().registerChannel("Plan");
// registerListener(new BungeePluginChannelListener(this)); // registerListener(new BungeePluginChannelListener(this));
@ -122,10 +128,20 @@ public class PlanBungee extends BungeePlugin<PlanBungee> implements IPlan {
@Override @Override
public void onDisable() { public void onDisable() {
if (processingQueue != null) { if (processingQueue != null) {
List<Processor> processors = processingQueue.stopAndReturnLeftovers(); try {
Log.info("Processing unprocessed processors. (" + processors.size() + ")"); processingQueue.stop();
for (Processor processor : processors) { } catch (IllegalArgumentException ignored) {
processor.process(); /*ignored*/
}
}
if (webServer != null) {
webServer.stop();
}
if (db != null) {
try {
db.close();
} catch (SQLException e) {
Log.toLog(this.getClass().getName(), e);
} }
} }
Log.info(Locale.get(Msg.DISABLED).toString()); Log.info(Locale.get(Msg.DISABLED).toString());

View File

@ -26,6 +26,7 @@ public enum Settings {
WRITE_NEW_LOCALE("Plugin.WriteNewLocaleFileOnStart"), WRITE_NEW_LOCALE("Plugin.WriteNewLocaleFileOnStart"),
DEV_MODE("Plugin.Dev"), DEV_MODE("Plugin.Dev"),
USE_SERVER_TIME("Customization.UseServerTime"), USE_SERVER_TIME("Customization.UseServerTime"),
DISPLAY_SESSIONS_AS_TABLE("Customization.Display.SessionsAsTable"),
// Integer // Integer
WEBSERVER_PORT("WebServer.Port"), WEBSERVER_PORT("WebServer.Port"),

View File

@ -27,14 +27,14 @@ import java.util.UUID;
* @author Rsl1122 * @author Rsl1122
* @see PluginData * @see PluginData
* @see AnalysisType * @see AnalysisType
* @since 2.0.0 * @since 4.0.0
*/ */
public class API { public class API {
private final Plan plugin; private final Plan plugin;
/** /**
* Class Constructor. * Creates a new API instance - not supposed to be called outside {@code Plan.onEnable}.
* *
* @param plugin Current instance of Plan * @param plugin Current instance of Plan
*/ */
@ -78,7 +78,7 @@ public class API {
* {@code <a href="Link">PlayerName</a>} * {@code <a href="Link">PlayerName</a>}
* *
* @param name Name of the player * @param name Name of the player
* @return ./player/PlayerName * @return {@code ../player/PlayerName}
*/ */
public String getPlayerInspectPageLink(String name) { public String getPlayerInspectPageLink(String name) {
String link = "../player/" + name; String link = "../player/" + name;
@ -86,7 +86,7 @@ public class API {
} }
/** /**
* Check if Players's Inspect page is cached to pagecache. * Check if Players's Inspect page is cached to PageCache.
* *
* @param uuid UUID of the player. * @param uuid UUID of the player.
* @return true/false * @return true/false
@ -97,12 +97,21 @@ public class API {
return isPlayerHtmlCached(uuid); return isPlayerHtmlCached(uuid);
} }
/**
* Check if Players's Inspect page is cached to PageCache of the providing WebServer.
* <p>
* Using BungeeCord: Will send a {@code IsCachedWebAPI} request to check if the page is in Bungee's PageCache.
* Only Bukkit: Checks PageCache for page.
*
* @param uuid UUID of the player.
* @return true/false
*/
public boolean isPlayerHtmlCached(UUID uuid) { public boolean isPlayerHtmlCached(UUID uuid) {
return plugin.getInfoManager().isCached(uuid); return plugin.getInfoManager().isCached(uuid);
} }
/** /**
* Cache Players's Inspect page to the PageCache of the WebServer. * Cache Players's Inspect page to the PageCache of the providing WebServer.
* *
* @param uuid UUID of the player. * @param uuid UUID of the player.
* @deprecated use {@code cachePlayerHtml} * @deprecated use {@code cachePlayerHtml}
@ -113,9 +122,13 @@ public class API {
} }
/** /**
* Cache Players's Inspect page to the PageCache of the WebServer. * Cache Players's Inspect page to the PageCache of the providing WebServer.
* <p>
* Using BungeeCord: Will send a {@code PostHtmlWebAPI} request after calculating the inspect page.
* Only Bukkit: Calculates inspect page and places it in the PageCache.
* *
* @param uuid UUID of the player. * @param uuid UUID of the player.
* @deprecated use {@code cachePlayerHtml}
*/ */
public void cachePlayerHtml(UUID uuid) { public void cachePlayerHtml(UUID uuid) {
plugin.getInfoManager().cachePlayer(uuid); plugin.getInfoManager().cachePlayer(uuid);
@ -124,7 +137,7 @@ public class API {
/** /**
* Used to get the full Html of the Inspect page as a string. * Used to get the full Html of the Inspect page as a string.
* <p> * <p>
* Check if the data is cached to InspectCache before calling this. * Re-calculates the inspect html on this server.
* *
* @param uuid UUID of the player. * @param uuid UUID of the player.
* @return player.html with all placeholders replaced. * @return player.html with all placeholders replaced.

View File

@ -5,7 +5,7 @@
package main.java.com.djrapitops.plan.api.exceptions; package main.java.com.djrapitops.plan.api.exceptions;
/** /**
* Thrown when something goes wrong with creating tables with Table#createTable. * Thrown when something goes wrong with creating tables with {@code Table#createTable}.
* *
* @author Rsl1122 * @author Rsl1122
*/ */

View File

@ -5,7 +5,7 @@
package main.java.com.djrapitops.plan.api.exceptions; package main.java.com.djrapitops.plan.api.exceptions;
/** /**
* Thrown when something goes wrong in the database, generic exception. * Thrown when something goes wrong with the Database, generic exception.
* *
* @author Rsl1122 * @author Rsl1122
*/ */

View File

@ -5,7 +5,7 @@
package main.java.com.djrapitops.plan.api.exceptions; package main.java.com.djrapitops.plan.api.exceptions;
/** /**
* Thrown when something goes wrong with Database#init. * Thrown when something goes wrong with {@code Database#init}.
* *
* @author Rsl1122 * @author Rsl1122
*/ */

View File

@ -5,7 +5,7 @@
package main.java.com.djrapitops.plan.api.exceptions; package main.java.com.djrapitops.plan.api.exceptions;
/** /**
* Exception thrown when Html page parsing fails. * Exception thrown when PageParser encounters an Exception.
* *
* @author Rsl1122 * @author Rsl1122
*/ */

View File

@ -5,7 +5,7 @@
package main.java.com.djrapitops.plan.api.exceptions; package main.java.com.djrapitops.plan.api.exceptions;
/** /**
* Thrown when WebAPI fails to connect. * Thrown when WebAPI fails to connect to an address.
* *
* @author Rsl1122 * @author Rsl1122
*/ */

View File

@ -5,7 +5,7 @@
package main.java.com.djrapitops.plan.api.exceptions; package main.java.com.djrapitops.plan.api.exceptions;
/** /**
* Thrown when web api post request fails. * Thrown when WebAPI POST-request fails, general Exception.
* *
* @author Rsl1122 * @author Rsl1122
*/ */

View File

@ -0,0 +1,50 @@
package main.java.com.djrapitops.plan.command;
import com.djrapitops.plugin.command.CommandType;
import com.djrapitops.plugin.command.TreeCommand;
import com.djrapitops.plugin.command.defaultcmds.StatusCommand;
import main.java.com.djrapitops.plan.Permissions;
import main.java.com.djrapitops.plan.PlanBungee;
import main.java.com.djrapitops.plan.command.commands.*;
import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg;
/**
* TreeCommand for the /plan command, and all subcommands.
* <p>
* Uses the Abstract Plugin Framework for easier command management.
*
* @author Rsl1122
* @since 1.0.0
*/
public class PlanBungeeCommand extends TreeCommand<PlanBungee> {
/**
* CommandExecutor class Constructor.
* <p>
* Initializes Subcommands
*
* @param plugin Current instance of Plan
*/
public PlanBungeeCommand(PlanBungee plugin) {
super(plugin, "planbungee", CommandType.CONSOLE, "", "", "planbungee");
super.setDefaultCommand("help");
}
@Override
public String[] addHelp() {
return Locale.get(Msg.CMD_HELP_PLAN).toArray();
}
@Override
public void addCommands() {
commands.add(new ReloadCommand(plugin));
commands.add(new StatusCommand<>(plugin, Permissions.MANAGE.getPermission()));
commands.add(new ListCommand());
RegisterCommand registerCommand = new RegisterCommand(plugin);
commands.add(registerCommand);
commands.add(new WebUserCommand(plugin, registerCommand));
commands.add(new NetworkCommand(plugin));
commands.add(new ListServersCommand(plugin));
}
}

View File

@ -5,9 +5,9 @@ import com.djrapitops.plugin.command.CommandUtils;
import com.djrapitops.plugin.command.ISender; import com.djrapitops.plugin.command.ISender;
import com.djrapitops.plugin.command.SubCommand; import com.djrapitops.plugin.command.SubCommand;
import main.java.com.djrapitops.plan.Permissions; import main.java.com.djrapitops.plan.Permissions;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.locale.Locale; import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg; import main.java.com.djrapitops.plan.locale.Msg;
import main.java.com.djrapitops.plan.utilities.MiscUtils;
/** /**
* Command used to display link to the player list webpage. * Command used to display link to the player list webpage.
@ -43,7 +43,7 @@ public class ListCommand extends SubCommand {
sender.sendMessage(Locale.get(Msg.CMD_CONSTANT_FOOTER).parse()); sender.sendMessage(Locale.get(Msg.CMD_CONSTANT_FOOTER).parse());
// Link // Link
String url = Plan.getInstance().getInfoManager().getLinkTo("/players"); String url = MiscUtils.getIPlan().getInfoManager().getLinkTo("/players/");
String message = Locale.get(Msg.CMD_INFO_LINK).toString(); String message = Locale.get(Msg.CMD_INFO_LINK).toString();
boolean console = !CommandUtils.isPlayer(sender); boolean console = !CommandUtils.isPlayer(sender);
if (console) { if (console) {

View File

@ -6,7 +6,6 @@ import com.djrapitops.plugin.command.SubCommand;
import com.djrapitops.plugin.settings.ColorScheme; import com.djrapitops.plugin.settings.ColorScheme;
import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Permissions; import main.java.com.djrapitops.plan.Permissions;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.api.IPlan; import main.java.com.djrapitops.plan.api.IPlan;
import main.java.com.djrapitops.plan.locale.Locale; import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg; import main.java.com.djrapitops.plan.locale.Msg;
@ -29,11 +28,11 @@ public class ListServersCommand extends SubCommand {
* *
* @param plugin Current instance of Plan * @param plugin Current instance of Plan
*/ */
public ListServersCommand(Plan plugin) { public ListServersCommand(IPlan plugin) {
super("servers, serverlist, listservers, sl", super("servers, serverlist, listservers, sl",
CommandType.CONSOLE, CommandType.CONSOLE,
Permissions.MANAGE.getPermission(), Permissions.MANAGE.getPermission(),
Locale.get(Msg.CMD_USG_RELOAD).toString()); "List servers in the network");
this.plugin = plugin; this.plugin = plugin;
} }

View File

@ -5,7 +5,7 @@ import com.djrapitops.plugin.command.CommandUtils;
import com.djrapitops.plugin.command.ISender; import com.djrapitops.plugin.command.ISender;
import com.djrapitops.plugin.command.SubCommand; import com.djrapitops.plugin.command.SubCommand;
import main.java.com.djrapitops.plan.Permissions; import main.java.com.djrapitops.plan.Permissions;
import main.java.com.djrapitops.plan.Plan; import main.java.com.djrapitops.plan.api.IPlan;
import main.java.com.djrapitops.plan.locale.Locale; import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg; import main.java.com.djrapitops.plan.locale.Msg;
@ -19,22 +19,21 @@ import main.java.com.djrapitops.plan.locale.Msg;
*/ */
public class NetworkCommand extends SubCommand { public class NetworkCommand extends SubCommand {
private final Plan plugin; private final IPlan plugin;
/** /**
* Class Constructor. * Class Constructor.
*/ */
public NetworkCommand(Plan plugin) { public NetworkCommand(IPlan plugin) {
super("network, n, netw", CommandType.CONSOLE, Permissions.ANALYZE.getPermission(), Locale.get(Msg.CMD_USG_LIST).toString(), ""); super("network, n, netw",
CommandType.CONSOLE,
Permissions.ANALYZE.getPermission(),
"Get the link to the network page");
this.plugin = plugin; this.plugin = plugin;
} }
@Override @Override
public boolean onCommand(ISender sender, String commandLabel, String[] args) { public boolean onCommand(ISender sender, String commandLabel, String[] args) {
if (plugin.getInfoManager().isUsingAnotherWebServer()) {
sender.sendMessage("§cNot using Bungee WebServer!");
return true;
}
sendNetworkMsg(sender); sendNetworkMsg(sender);
return true; return true;
} }
@ -43,7 +42,7 @@ public class NetworkCommand extends SubCommand {
sender.sendMessage(Locale.get(Msg.CMD_CONSTANT_FOOTER).parse()); sender.sendMessage(Locale.get(Msg.CMD_CONSTANT_FOOTER).parse());
// Link // Link
String url = Plan.getInstance().getInfoManager().getLinkTo("/network"); String url = plugin.getInfoManager().getLinkTo("/network/");
String message = Locale.get(Msg.CMD_INFO_LINK).toString(); String message = Locale.get(Msg.CMD_INFO_LINK).toString();
boolean console = !CommandUtils.isPlayer(sender); boolean console = !CommandUtils.isPlayer(sender);
if (console) { if (console) {

View File

@ -5,17 +5,16 @@ import com.djrapitops.plugin.command.CommandUtils;
import com.djrapitops.plugin.command.ISender; import com.djrapitops.plugin.command.ISender;
import com.djrapitops.plugin.command.SubCommand; import com.djrapitops.plugin.command.SubCommand;
import com.djrapitops.plugin.task.AbsRunnable; import com.djrapitops.plugin.task.AbsRunnable;
import com.djrapitops.plugin.utilities.Compatibility;
import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Permissions; import main.java.com.djrapitops.plan.Permissions;
import main.java.com.djrapitops.plan.Plan; import main.java.com.djrapitops.plan.api.IPlan;
import main.java.com.djrapitops.plan.data.WebUser; import main.java.com.djrapitops.plan.data.WebUser;
import main.java.com.djrapitops.plan.database.tables.SecurityTable; import main.java.com.djrapitops.plan.database.tables.SecurityTable;
import main.java.com.djrapitops.plan.locale.Locale; import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg; import main.java.com.djrapitops.plan.locale.Msg;
import main.java.com.djrapitops.plan.utilities.Check; import main.java.com.djrapitops.plan.utilities.Check;
import main.java.com.djrapitops.plan.utilities.PassEncryptUtil; import main.java.com.djrapitops.plan.utilities.PassEncryptUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.Logger;
/** /**
* Command for registering web users. * Command for registering web users.
@ -31,16 +30,18 @@ import org.apache.logging.log4j.core.Logger;
*/ */
public class RegisterCommand extends SubCommand { public class RegisterCommand extends SubCommand {
private final Plan plugin; private final IPlan plugin;
public RegisterCommand(Plan plugin) { public RegisterCommand(IPlan plugin) {
super("register", super("register",
CommandType.CONSOLE_WITH_ARGUMENTS, CommandType.CONSOLE_WITH_ARGUMENTS,
"", // No Permission Requirement "", // No Permission Requirement
Locale.get(Msg.CMD_USG_WEB_REGISTER).toString(), Locale.get(Msg.CMD_USG_WEB_REGISTER).toString(),
"<password> [name] [access lvl]"); "<password> [name] [access lvl]");
this.plugin = plugin; this.plugin = plugin;
setupFilter(); if (Compatibility.isBukkitAvailable()) {
setupFilter();
}
} }
@Override @Override
@ -140,7 +141,6 @@ public class RegisterCommand extends SubCommand {
* Setups the command console output filter * Setups the command console output filter
*/ */
private void setupFilter() { private void setupFilter() {
Logger logger = (Logger) LogManager.getRootLogger(); new RegisterCommandFilter().registerFilter();
logger.addFilter(new RegisterCommandFilter());
} }
} }

View File

@ -2,6 +2,7 @@ package main.java.com.djrapitops.plan.command.commands;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import org.apache.logging.log4j.Level; import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Marker; import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.core.LogEvent; import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.Logger; import org.apache.logging.log4j.core.Logger;
@ -20,6 +21,11 @@ public class RegisterCommandFilter extends AbstractFilter {
private final Set<String> censoredCommands = ImmutableSet.of("/plan web register", "/plan webuser register", "/plan register"); private final Set<String> censoredCommands = ImmutableSet.of("/plan web register", "/plan webuser register", "/plan register");
public void registerFilter() {
Logger logger = (Logger) LogManager.getRootLogger();
logger.addFilter(this);
}
@Override @Override
public Result filter(LogEvent event) { public Result filter(LogEvent event) {
if (event == null) { if (event == null) {

View File

@ -4,8 +4,6 @@ import com.djrapitops.plugin.command.CommandType;
import com.djrapitops.plugin.command.ISender; import com.djrapitops.plugin.command.ISender;
import com.djrapitops.plugin.command.SubCommand; import com.djrapitops.plugin.command.SubCommand;
import main.java.com.djrapitops.plan.Permissions; import main.java.com.djrapitops.plan.Permissions;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.PlanBungee;
import main.java.com.djrapitops.plan.api.IPlan; import main.java.com.djrapitops.plan.api.IPlan;
import main.java.com.djrapitops.plan.locale.Locale; import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg; import main.java.com.djrapitops.plan.locale.Msg;
@ -25,7 +23,7 @@ public class ReloadCommand extends SubCommand {
* *
* @param plugin Current instance of Plan * @param plugin Current instance of Plan
*/ */
public ReloadCommand(Plan plugin) { public ReloadCommand(IPlan plugin) {
super("reload", super("reload",
CommandType.CONSOLE, CommandType.CONSOLE,
Permissions.MANAGE.getPermission(), Permissions.MANAGE.getPermission(),
@ -34,15 +32,6 @@ public class ReloadCommand extends SubCommand {
this.plugin = plugin; this.plugin = plugin;
} }
public ReloadCommand(PlanBungee plugin) {
super("planbungee",
CommandType.CONSOLE,
Permissions.MANAGE.getPermission(),
Locale.get(Msg.CMD_USG_RELOAD).toString());
this.plugin = plugin;
}
@Override @Override
public boolean onCommand(ISender sender, String commandLabel, String[] args) { public boolean onCommand(ISender sender, String commandLabel, String[] args) {
plugin.restart(); plugin.restart();

View File

@ -3,7 +3,7 @@ package main.java.com.djrapitops.plan.command.commands;
import com.djrapitops.plugin.command.CommandType; import com.djrapitops.plugin.command.CommandType;
import com.djrapitops.plugin.command.TreeCommand; import com.djrapitops.plugin.command.TreeCommand;
import main.java.com.djrapitops.plan.Permissions; import main.java.com.djrapitops.plan.Permissions;
import main.java.com.djrapitops.plan.Plan; import main.java.com.djrapitops.plan.api.IPlan;
import main.java.com.djrapitops.plan.command.commands.webuser.WebCheckCommand; import main.java.com.djrapitops.plan.command.commands.webuser.WebCheckCommand;
import main.java.com.djrapitops.plan.command.commands.webuser.WebDeleteCommand; import main.java.com.djrapitops.plan.command.commands.webuser.WebDeleteCommand;
import main.java.com.djrapitops.plan.command.commands.webuser.WebLevelCommand; import main.java.com.djrapitops.plan.command.commands.webuser.WebLevelCommand;
@ -17,9 +17,9 @@ import main.java.com.djrapitops.plan.locale.Msg;
* @author Rsl1122 * @author Rsl1122
* @since 3.5.2 * @since 3.5.2
*/ */
public class WebUserCommand extends TreeCommand<Plan> { public class WebUserCommand extends TreeCommand<IPlan> {
public WebUserCommand(Plan plugin, RegisterCommand register) { public WebUserCommand(IPlan plugin, RegisterCommand register) {
super(plugin, "webuser, web", super(plugin, "webuser, web",
CommandType.CONSOLE, CommandType.CONSOLE,
Permissions.MANAGE_WEB.getPerm(), Permissions.MANAGE_WEB.getPerm(),

View File

@ -55,6 +55,10 @@ public class ManageSetupCommand extends SubCommand {
return true; return true;
} }
String address = args[0].toLowerCase(); String address = args[0].toLowerCase();
if (!address.startsWith("http")) {
sender.sendMessage("§cMake sure you're using the full address (Starts with http:// or https://) - Check Bungee enable log for the full address.");
return true;
}
if (address.endsWith("/")) { if (address.endsWith("/")) {
address = address.substring(0, address.length() - 1); address = address.substring(0, address.length() - 1);
} }

View File

@ -6,7 +6,7 @@ import com.djrapitops.plugin.command.SubCommand;
import com.djrapitops.plugin.task.AbsRunnable; import com.djrapitops.plugin.task.AbsRunnable;
import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Permissions; import main.java.com.djrapitops.plan.Permissions;
import main.java.com.djrapitops.plan.Plan; import main.java.com.djrapitops.plan.api.IPlan;
import main.java.com.djrapitops.plan.data.WebUser; import main.java.com.djrapitops.plan.data.WebUser;
import main.java.com.djrapitops.plan.database.tables.SecurityTable; import main.java.com.djrapitops.plan.database.tables.SecurityTable;
import main.java.com.djrapitops.plan.locale.Locale; import main.java.com.djrapitops.plan.locale.Locale;
@ -22,9 +22,9 @@ import org.bukkit.ChatColor;
*/ */
public class WebCheckCommand extends SubCommand { public class WebCheckCommand extends SubCommand {
private final Plan plugin; private final IPlan plugin;
public WebCheckCommand(Plan plugin) { public WebCheckCommand(IPlan plugin) {
super("check", super("check",
CommandType.CONSOLE_WITH_ARGUMENTS, CommandType.CONSOLE_WITH_ARGUMENTS,
Permissions.MANAGE_WEB.getPerm(), Permissions.MANAGE_WEB.getPerm(),

View File

@ -6,7 +6,7 @@ import com.djrapitops.plugin.command.SubCommand;
import com.djrapitops.plugin.task.AbsRunnable; import com.djrapitops.plugin.task.AbsRunnable;
import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Permissions; import main.java.com.djrapitops.plan.Permissions;
import main.java.com.djrapitops.plan.Plan; import main.java.com.djrapitops.plan.api.IPlan;
import main.java.com.djrapitops.plan.database.tables.SecurityTable; import main.java.com.djrapitops.plan.database.tables.SecurityTable;
import main.java.com.djrapitops.plan.locale.Locale; import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg; import main.java.com.djrapitops.plan.locale.Msg;
@ -21,9 +21,9 @@ import net.md_5.bungee.api.ChatColor;
*/ */
public class WebDeleteCommand extends SubCommand { public class WebDeleteCommand extends SubCommand {
private final Plan plugin; private final IPlan plugin;
public WebDeleteCommand(Plan plugin) { public WebDeleteCommand(IPlan plugin) {
super("delete, remove", super("delete, remove",
CommandType.CONSOLE_WITH_ARGUMENTS, CommandType.CONSOLE_WITH_ARGUMENTS,
Permissions.MANAGE_WEB.getPerm(), Permissions.MANAGE_WEB.getPerm(),

View File

@ -5,7 +5,7 @@ import com.djrapitops.plugin.command.ISender;
import com.djrapitops.plugin.command.SubCommand; import com.djrapitops.plugin.command.SubCommand;
import com.djrapitops.plugin.settings.ColorScheme; import com.djrapitops.plugin.settings.ColorScheme;
import main.java.com.djrapitops.plan.Permissions; import main.java.com.djrapitops.plan.Permissions;
import main.java.com.djrapitops.plan.Plan; import main.java.com.djrapitops.plan.api.IPlan;
import main.java.com.djrapitops.plan.locale.Locale; import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg; import main.java.com.djrapitops.plan.locale.Msg;
@ -17,9 +17,9 @@ import main.java.com.djrapitops.plan.locale.Msg;
*/ */
public class WebLevelCommand extends SubCommand { public class WebLevelCommand extends SubCommand {
private final Plan plugin; private final IPlan plugin;
public WebLevelCommand(Plan plugin) { public WebLevelCommand(IPlan plugin) {
super("level", super("level",
CommandType.CONSOLE, CommandType.CONSOLE,
Permissions.MANAGE_WEB.getPerm(), Permissions.MANAGE_WEB.getPerm(),

View File

@ -7,7 +7,7 @@ import com.djrapitops.plugin.settings.ColorScheme;
import com.djrapitops.plugin.task.AbsRunnable; import com.djrapitops.plugin.task.AbsRunnable;
import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Permissions; import main.java.com.djrapitops.plan.Permissions;
import main.java.com.djrapitops.plan.Plan; import main.java.com.djrapitops.plan.api.IPlan;
import main.java.com.djrapitops.plan.data.WebUser; import main.java.com.djrapitops.plan.data.WebUser;
import main.java.com.djrapitops.plan.locale.Locale; import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg; import main.java.com.djrapitops.plan.locale.Msg;
@ -23,9 +23,9 @@ import java.util.List;
*/ */
public class WebListUsersCommand extends SubCommand { public class WebListUsersCommand extends SubCommand {
private final Plan plugin; private final IPlan plugin;
public WebListUsersCommand(Plan plugin) { public WebListUsersCommand(IPlan plugin) {
super("list", CommandType.CONSOLE, Permissions.MANAGE_WEB.getPerm(), "List registered web users & permission levels."); super("list", CommandType.CONSOLE, Permissions.MANAGE_WEB.getPerm(), "List registered web users & permission levels.");
this.plugin = plugin; this.plugin = plugin;
} }

View File

@ -1,6 +1,5 @@
package main.java.com.djrapitops.plan.data; package main.java.com.djrapitops.plan.data;
import com.djrapitops.plugin.utilities.Verify;
import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.data.analysis.*; import main.java.com.djrapitops.plan.data.analysis.*;
import main.java.com.djrapitops.plan.utilities.Benchmark; import main.java.com.djrapitops.plan.utilities.Benchmark;
@ -38,7 +37,6 @@ public class AnalysisData extends RawData {
private final TPSPart tpsPart; private final TPSPart tpsPart;
private final WorldPart worldPart; private final WorldPart worldPart;
private long refreshDate; private long refreshDate;
private String planVersion;
private String pluginsTabLayout; private String pluginsTabLayout;
private Map<String, Serializable> additionalDataReplaceMap; private Map<String, Serializable> additionalDataReplaceMap;
private String playersTable; private String playersTable;
@ -97,26 +95,10 @@ public class AnalysisData extends RawData {
worldPart); worldPart);
} }
public String getPlanVersion() {
return planVersion;
}
public void setPlanVersion(String planVersion) {
this.planVersion = planVersion;
}
public String getPluginsTabLayout() {
return pluginsTabLayout;
}
public void setPluginsTabLayout(String pluginsTabLayout) { public void setPluginsTabLayout(String pluginsTabLayout) {
this.pluginsTabLayout = pluginsTabLayout; this.pluginsTabLayout = pluginsTabLayout;
} }
public Map<String, Serializable> getAdditionalDataReplaceMap() {
return additionalDataReplaceMap;
}
public void setAdditionalDataReplaceMap(Map<String, Serializable> additionalDataReplaceMap) { public void setAdditionalDataReplaceMap(Map<String, Serializable> additionalDataReplaceMap) {
this.additionalDataReplaceMap = additionalDataReplaceMap; this.additionalDataReplaceMap = additionalDataReplaceMap;
} }
@ -127,12 +109,15 @@ public class AnalysisData extends RawData {
@Override @Override
protected void analyse() { protected void analyse() {
Verify.nullCheck(playersTable); if (playersTable == null) {
Verify.nullCheck(pluginsTabLayout); playersTable = "";
Verify.nullCheck(planVersion); }
if (pluginsTabLayout == null) {
pluginsTabLayout = "";
}
addValue("tableBodyPlayerList", playersTable); addValue("tableBodyPlayerList", playersTable);
addValue("version", planVersion); addValue("version", MiscUtils.getIPlan().getVersion());
final List<RawData> parts = getAllParts(); final List<RawData> parts = getAllParts();
parts.forEach(part -> { parts.forEach(part -> {
@ -157,8 +142,4 @@ public class AnalysisData extends RawData {
public long getRefreshDate() { public long getRefreshDate() {
return refreshDate; return refreshDate;
} }
public void setRefreshDate(long refreshDate) {
this.refreshDate = refreshDate;
}
} }

View File

@ -27,6 +27,7 @@ public class UserInfo {
this.registered = registered; this.registered = registered;
this.opped = opped; this.opped = opped;
this.banned = banned; this.banned = banned;
lastSeen = 0L;
} }
public UUID getUuid() { public UUID getUuid() {

View File

@ -5,6 +5,7 @@ import com.djrapitops.plugin.utilities.Verify;
import main.java.com.djrapitops.plan.data.Session; import main.java.com.djrapitops.plan.data.Session;
import main.java.com.djrapitops.plan.utilities.MiscUtils; import main.java.com.djrapitops.plan.utilities.MiscUtils;
import main.java.com.djrapitops.plan.utilities.analysis.AnalysisUtils; import main.java.com.djrapitops.plan.utilities.analysis.AnalysisUtils;
import main.java.com.djrapitops.plan.utilities.html.structure.SessionTabStructureCreator;
import main.java.com.djrapitops.plan.utilities.html.tables.SessionsTableCreator; import main.java.com.djrapitops.plan.utilities.html.tables.SessionsTableCreator;
import java.util.*; import java.util.*;
@ -61,7 +62,10 @@ public class JoinInfoPart extends RawData {
} }
private void sessionTables() { private void sessionTables() {
String[] tables = SessionsTableCreator.createTables(this); String[] tables = SessionsTableCreator.createTable(this);
String[] sessionContent = SessionTabStructureCreator.creteStructure(this);
addValue("contentSessions", sessionContent[0]);
addValue("sessionTabGraphViewFunctions", sessionContent[1]);
addValue("tableBodySessions", tables[0]); addValue("tableBodySessions", tables[0]);
addValue("tableBodyRecentLogins", tables[1]); addValue("tableBodyRecentLogins", tables[1]);
} }

View File

@ -109,7 +109,7 @@ public abstract class SQLDB extends Database {
if (newDatabase) { if (newDatabase) {
Log.info("New Database created."); Log.info("New Database created.");
setVersion(11); setVersion(12);
} }
int version = getVersion(); int version = getVersion();
@ -131,6 +131,11 @@ public abstract class SQLDB extends Database {
serverTable.alterTableV11(); serverTable.alterTableV11();
setVersion(11); setVersion(11);
} }
if (version < 12) {
actionsTable.alterTableV12();
ipsTable.alterTableV12();
setVersion(12);
}
} catch (SQLException e) { } catch (SQLException e) {
throw new DatabaseInitException("Failed to set-up Database", e); throw new DatabaseInitException("Failed to set-up Database", e);
} }

View File

@ -68,12 +68,18 @@ public class ActionsTable extends UserIDTable {
.column(columnServerID, Sql.INT).notNull() .column(columnServerID, Sql.INT).notNull()
.column(columnDate, Sql.LONG).notNull() .column(columnDate, Sql.LONG).notNull()
.column(columnActionID, Sql.INT).notNull() .column(columnActionID, Sql.INT).notNull()
.column(columnAdditionalInfo, Sql.varchar(100)) .column(columnAdditionalInfo, Sql.varchar(300))
.foreignKey(columnUserID, usersTable.toString(), usersTable.getColumnID()) .foreignKey(columnUserID, usersTable.toString(), usersTable.getColumnID())
.foreignKey(columnServerID, serverTable.toString(), serverTable.getColumnID()) .foreignKey(columnServerID, serverTable.toString(), serverTable.getColumnID())
.toString()); .toString());
} }
public void alterTableV12() throws SQLException {
if (usingMySQL) {
executeUnsafe("ALTER TABLE " + tableName + " MODIFY " + columnAdditionalInfo + " VARCHAR(300)");
}
}
public void insertAction(UUID uuid, Action action) throws SQLException { public void insertAction(UUID uuid, Action action) throws SQLException {
execute(new ExecStatement(insertStatement) { execute(new ExecStatement(insertStatement) {
@Override @Override

View File

@ -43,13 +43,19 @@ public class IPsTable extends UserIDTable {
public void createTable() throws DBCreateTableException { public void createTable() throws DBCreateTableException {
createTable(TableSqlParser.createTable(tableName) createTable(TableSqlParser.createTable(tableName)
.column(columnUserID, Sql.INT).notNull() .column(columnUserID, Sql.INT).notNull()
.column(columnIP, Sql.varchar(20)).notNull() .column(columnIP, Sql.varchar(39)).notNull()
.column(columnGeolocation, Sql.varchar(50)).notNull() .column(columnGeolocation, Sql.varchar(50)).notNull()
.foreignKey(columnUserID, usersTable.getTableName(), usersTable.getColumnID()) .foreignKey(columnUserID, usersTable.getTableName(), usersTable.getColumnID())
.toString() .toString()
); );
} }
public void alterTableV12() throws SQLException {
if (usingMySQL) {
executeUnsafe("ALTER TABLE " + tableName + " MODIFY " + columnIP + " VARCHAR(39) NOT NULL");
}
}
/** /**
* @param uuid UUID of the user. * @param uuid UUID of the user.
* @return Users's Login Geolocations. * @return Users's Login Geolocations.

View File

@ -130,7 +130,7 @@ public class BukkitInformationManager extends InformationManager {
HookHandler hookHandler = plugin.getHookHandler(); HookHandler hookHandler = plugin.getHookHandler();
List<PluginData> plugins = hookHandler.getAdditionalDataSources(); List<PluginData> plugins = hookHandler.getAdditionalDataSources();
Map<String, Serializable> replaceMap = hookHandler.getAdditionalInspectReplaceRules(uuid); Map<String, Serializable> replaceMap = hookHandler.getAdditionalInspectReplaceRules(uuid);
String contents = HtmlStructure.createInspectPageTabContent(serverName, plugins, replaceMap); String contents = HtmlStructure.createInspectPluginsTabContent(serverName, plugins, replaceMap);
cacheInspectPluginsTab(uuid, contents); cacheInspectPluginsTab(uuid, contents);
} }
} }

View File

@ -15,16 +15,14 @@ import main.java.com.djrapitops.plan.systems.info.parsing.NetworkPageParser;
import main.java.com.djrapitops.plan.systems.info.server.BungeeServerInfoManager; import main.java.com.djrapitops.plan.systems.info.server.BungeeServerInfoManager;
import main.java.com.djrapitops.plan.systems.info.server.ServerInfo; import main.java.com.djrapitops.plan.systems.info.server.ServerInfo;
import main.java.com.djrapitops.plan.systems.webserver.PageCache; import main.java.com.djrapitops.plan.systems.webserver.PageCache;
import main.java.com.djrapitops.plan.systems.webserver.response.InspectPageResponse; import main.java.com.djrapitops.plan.systems.webserver.response.*;
import main.java.com.djrapitops.plan.systems.webserver.response.InternalErrorResponse;
import main.java.com.djrapitops.plan.systems.webserver.response.NotFoundResponse;
import main.java.com.djrapitops.plan.systems.webserver.response.Response;
import main.java.com.djrapitops.plan.systems.webserver.webapi.WebAPIManager; import main.java.com.djrapitops.plan.systems.webserver.webapi.WebAPIManager;
import main.java.com.djrapitops.plan.systems.webserver.webapi.bukkit.AnalysisReadyWebAPI; import main.java.com.djrapitops.plan.systems.webserver.webapi.bukkit.AnalysisReadyWebAPI;
import main.java.com.djrapitops.plan.systems.webserver.webapi.bukkit.AnalyzeWebAPI; import main.java.com.djrapitops.plan.systems.webserver.webapi.bukkit.AnalyzeWebAPI;
import main.java.com.djrapitops.plan.systems.webserver.webapi.bukkit.InspectWebAPI; import main.java.com.djrapitops.plan.systems.webserver.webapi.bukkit.InspectWebAPI;
import main.java.com.djrapitops.plan.systems.webserver.webapi.bukkit.IsOnlineWebAPI; import main.java.com.djrapitops.plan.systems.webserver.webapi.bukkit.IsOnlineWebAPI;
import main.java.com.djrapitops.plan.systems.webserver.webapi.bungee.RequestPluginsTabWebAPI; import main.java.com.djrapitops.plan.systems.webserver.webapi.bungee.RequestPluginsTabWebAPI;
import main.java.com.djrapitops.plan.utilities.MiscUtils;
import main.java.com.djrapitops.plan.utilities.html.HtmlStructure; import main.java.com.djrapitops.plan.utilities.html.HtmlStructure;
import java.sql.SQLException; import java.sql.SQLException;
@ -158,7 +156,14 @@ public class BungeeInformationManager extends InformationManager {
*/ */
private ServerInfo getInspectRequestProcessorServer(UUID uuid) { private ServerInfo getInspectRequestProcessorServer(UUID uuid) {
if (bukkitServers.isEmpty()) { if (bukkitServers.isEmpty()) {
throw new IllegalStateException("No Bukkit Servers."); try {
refreshBukkitServerMap();
} catch (SQLException e) {
Log.toLog(this.getClass().getName(), e);
}
if (bukkitServers.isEmpty()) {
throw new IllegalStateException("No Bukkit Servers.");
}
} }
Collection<ServerInfo> onlineServers = serverInfoManager.getOnlineBukkitServers(); Collection<ServerInfo> onlineServers = serverInfoManager.getOnlineBukkitServers();
@ -319,6 +324,7 @@ public class BungeeInformationManager extends InformationManager {
public void cacheNetworkPageContent(UUID serverUUID, String html) { public void cacheNetworkPageContent(UUID serverUUID, String html) {
networkPageContent.put(serverUUID, html); networkPageContent.put(serverUUID, html);
updateNetworkPageContent();
} }
public void removeNetworkPageContent(UUID serverUUID) { public void removeNetworkPageContent(UUID serverUUID) {
@ -348,9 +354,7 @@ public class BungeeInformationManager extends InformationManager {
@Override @Override
public void updateNetworkPageContent() { public void updateNetworkPageContent() {
Collection<ServerInfo> online = serverInfoManager.getOnlineBukkitServers(); PageCache.cachePage("analysisPage:" + MiscUtils.getIPlan().getServerUuid(), () -> new AnalysisPageResponse(this));
online.stream().map(ServerInfo::getUuid)
.forEach(this::removeNetworkPageContent);
} }
public void sendConfigSettings() { public void sendConfigSettings() {

View File

@ -13,6 +13,8 @@ import main.java.com.djrapitops.plan.data.Action;
import main.java.com.djrapitops.plan.data.PlayerKill; import main.java.com.djrapitops.plan.data.PlayerKill;
import main.java.com.djrapitops.plan.data.Session; import main.java.com.djrapitops.plan.data.Session;
import main.java.com.djrapitops.plan.data.UserInfo; import main.java.com.djrapitops.plan.data.UserInfo;
import main.java.com.djrapitops.plan.data.time.GMTimes;
import main.java.com.djrapitops.plan.data.time.WorldTimes;
import main.java.com.djrapitops.plan.database.Database; import main.java.com.djrapitops.plan.database.Database;
import main.java.com.djrapitops.plan.database.tables.SessionsTable; import main.java.com.djrapitops.plan.database.tables.SessionsTable;
import main.java.com.djrapitops.plan.database.tables.UsersTable; import main.java.com.djrapitops.plan.database.tables.UsersTable;
@ -98,10 +100,10 @@ public class InspectPageParser extends PageParser {
Map<String, List<Session>> sessions = sessionsTable.getSessions(uuid); Map<String, List<Session>> sessions = sessionsTable.getSessions(uuid);
List<Session> allSessions = sessions.values().stream() List<Session> allSessions = sessions.values().stream()
.flatMap(Collection::stream) .flatMap(Collection::stream)
.sorted(new SessionStartComparator()) .sorted(new SessionStartComparator()) // Sorted Newest first.
.collect(Collectors.toList()); .collect(Collectors.toList());
String[] sessionsTabContent = HtmlStructure.createSessionsTabContent(sessions, allSessions); String[] sessionsTabContent = HtmlStructure.createSessionsTabContentInspectPage(sessions, allSessions, uuid);
addValue("contentSessions", sessionsTabContent[0]); addValue("contentSessions", sessionsTabContent[0]);
addValue("sessionTabGraphViewFunctions", sessionsTabContent[1]); addValue("sessionTabGraphViewFunctions", sessionsTabContent[1]);
addValue("contentServerOverview", HtmlStructure.createServerOverviewColumn(sessions)); addValue("contentServerOverview", HtmlStructure.createServerOverviewColumn(sessions));
@ -154,7 +156,18 @@ public class InspectPageParser extends PageParser {
addValue("playtimeTotal", FormatUtils.formatTimeAmount(playTime)); addValue("playtimeTotal", FormatUtils.formatTimeAmount(playTime));
String punchCardData = PunchCardGraphCreator.createDataSeries(allSessions); String punchCardData = PunchCardGraphCreator.createDataSeries(allSessions);
String[] worldPieData = WorldPieCreator.createSeriesData(db.getWorldTimesTable().getWorldTimesOfUser(uuid)); WorldTimes worldTimes = db.getWorldTimesTable().getWorldTimesOfUser(uuid);
// Add 0 time for worlds not present.
Set<String> nonZeroWorlds = worldTimes.getWorldTimes().keySet();
for (String world : db.getWorldTable().getWorlds()) {
if (nonZeroWorlds.contains(world)) {
continue;
}
worldTimes.setGMTimesForWorld(world, new GMTimes());
}
String[] worldPieData = WorldPieCreator.createSeriesData(worldTimes);
addValue("worldPieSeries", worldPieData[0]); addValue("worldPieSeries", worldPieData[0]);
addValue("gmSeries", worldPieData[1]); addValue("gmSeries", worldPieData[1]);

View File

@ -48,7 +48,6 @@ public class NetworkPageParser extends PageParser {
addValue("playersOnlineSeries", PlayerActivityGraphCreator.buildSeriesDataString(networkOnlineData)); addValue("playersOnlineSeries", PlayerActivityGraphCreator.buildSeriesDataString(networkOnlineData));
addValue("playersGraphColor", Colors.PLAYERS_ONLINE.getColor()); addValue("playersGraphColor", Colors.PLAYERS_ONLINE.getColor());
addValue("playersOnline", plugin.getProxy().getOnlineCount()); addValue("playersOnline", plugin.getProxy().getOnlineCount());
addValue("playersMax", plugin.getProxy().getConfig().getPlayerLimit());
addValue("playersTotal", db.getUsersTable().getPlayerCount()); addValue("playersTotal", db.getUsersTable().getPlayerCount());

View File

@ -97,7 +97,7 @@ public class BukkitServerInfoManager {
} }
private UUID generateNewUUID(ServerVariableHolder variableHolder) { private UUID generateNewUUID(ServerVariableHolder variableHolder) {
String seed = variableHolder.getName() + variableHolder.getIp() + variableHolder.getPort() + variableHolder.getVersion() + variableHolder.getImplVersion(); String seed = plugin.getServer().getServerId() + variableHolder.getName() + variableHolder.getIp() + variableHolder.getPort() + variableHolder.getVersion() + variableHolder.getImplVersion();
return UUID.nameUUIDFromBytes(seed.getBytes()); return UUID.nameUUIDFromBytes(seed.getBytes());
} }

View File

@ -129,6 +129,9 @@ public class BungeeServerInfoManager {
} }
public void serverConnected(UUID serverUUID) { public void serverConnected(UUID serverUUID) {
if (plugin.getServerUuid().equals(serverUUID)) {
return;
}
Log.info("Received a connection from a Bukkit server.."); Log.info("Received a connection from a Bukkit server..");
if (onlineServers.contains(serverUUID)) { if (onlineServers.contains(serverUUID)) {
sendConfigSettings(serverUUID); sendConfigSettings(serverUUID);

View File

@ -34,9 +34,7 @@ public class NewNickActionProcessor extends PlayerProcessor {
public void process() { public void process() {
UUID uuid = getUUID(); UUID uuid = getUUID();
String n = HtmlUtils.swapColorsToSpan(displayName); String info = HtmlUtils.removeXSS(displayName);
String info = HtmlUtils.removeXSS(n);
Action action = new Action(MiscUtils.getTime(), Actions.NEW_NICKNAME, info); Action action = new Action(MiscUtils.getTime(), Actions.NEW_NICKNAME, info);

View File

@ -49,12 +49,12 @@ public class RegisterProcessor extends PlayerProcessor {
if (!usersTable.isRegistered(uuid)) { if (!usersTable.isRegistered(uuid)) {
usersTable.registerUser(uuid, registered, name); usersTable.registerUser(uuid, registered, name);
} }
if (db.getActionsTable().getActions(uuid).size() > 0) {
return;
}
if (!userInfoTable.isRegistered(uuid)) { if (!userInfoTable.isRegistered(uuid)) {
userInfoTable.registerUserInfo(uuid, registered); userInfoTable.registerUserInfo(uuid, registered);
} }
if (db.getActionsTable().getActions(uuid).size() > 0) {
return;
}
plugin.getDataCache().markFirstSession(uuid); plugin.getDataCache().markFirstSession(uuid);
db.getActionsTable().insertAction(uuid, new Action(time, Actions.FIRST_SESSION, "Online: " + playersOnline + " Players")); db.getActionsTable().insertAction(uuid, new Action(time, Actions.FIRST_SESSION, "Online: " + playersOnline + " Players"));
} catch (SQLException e) { } catch (SQLException e) {

View File

@ -13,6 +13,7 @@ import main.java.com.djrapitops.plan.api.exceptions.WebAPIException;
import main.java.com.djrapitops.plan.systems.info.BukkitInformationManager; import main.java.com.djrapitops.plan.systems.info.BukkitInformationManager;
import main.java.com.djrapitops.plan.systems.webserver.response.Response; import main.java.com.djrapitops.plan.systems.webserver.response.Response;
import main.java.com.djrapitops.plan.systems.webserver.webapi.WebAPI; import main.java.com.djrapitops.plan.systems.webserver.webapi.WebAPI;
import main.java.com.djrapitops.plan.utilities.MiscUtils;
import java.io.IOException; import java.io.IOException;
import java.util.Map; import java.util.Map;
@ -53,6 +54,7 @@ public class PingWebAPI extends WebAPI {
public void sendRequest(String address, String accessCode) throws WebAPIException { public void sendRequest(String address, String accessCode) throws WebAPIException {
addVariable("accessKey", accessCode); addVariable("accessKey", accessCode);
addVariable("version", MiscUtils.getIPlan().getVersion());
sendRequest(address); sendRequest(address);
} }
} }

View File

@ -119,6 +119,11 @@ public class FormatUtils {
} }
if (minutes != 0) { if (minutes != 0) {
String m = Settings.FORMAT_MINUTES.toString().replace("%minutes%", String.valueOf(minutes)); String m = Settings.FORMAT_MINUTES.toString().replace("%minutes%", String.valueOf(minutes));
if (hours == 0 && m.contains("%hours%")) {
m = m.replace("%hours%", Settings.FORMAT_MINUTES.toString().replace("%zero%", "0") + "0");
} else {
m = m.replace("%hours", "");
}
if (m.contains("%zero%") && String.valueOf(minutes).length() == 1) { if (m.contains("%zero%") && String.valueOf(minutes).length() == 1) {
builder.append('0'); builder.append('0');
} }
@ -126,6 +131,11 @@ public class FormatUtils {
} }
if (seconds != 0) { if (seconds != 0) {
String s = Settings.FORMAT_SECONDS.toString().replace("%seconds%", String.valueOf(seconds)); String s = Settings.FORMAT_SECONDS.toString().replace("%seconds%", String.valueOf(seconds));
if (minutes == 0 && s.contains("%minutes%")) {
s = s.replace("%minutes%", Settings.FORMAT_MINUTES.toString().replace("%hours", "").replace("%zero%", "0") + 0);
} else {
s = s.replace("%minutes%", "");
}
if (s.contains("%zero%") && String.valueOf(seconds).length() == 1) { if (s.contains("%zero%") && String.valueOf(seconds).length() == 1) {
builder.append('0'); builder.append('0');
} }

View File

@ -11,6 +11,7 @@ import main.java.com.djrapitops.plan.data.additional.AnalysisType;
import main.java.com.djrapitops.plan.data.additional.HookHandler; import main.java.com.djrapitops.plan.data.additional.HookHandler;
import main.java.com.djrapitops.plan.data.additional.PluginData; import main.java.com.djrapitops.plan.data.additional.PluginData;
import main.java.com.djrapitops.plan.data.analysis.*; import main.java.com.djrapitops.plan.data.analysis.*;
import main.java.com.djrapitops.plan.data.time.GMTimes;
import main.java.com.djrapitops.plan.data.time.WorldTimes; import main.java.com.djrapitops.plan.data.time.WorldTimes;
import main.java.com.djrapitops.plan.database.Database; import main.java.com.djrapitops.plan.database.Database;
import main.java.com.djrapitops.plan.database.tables.TPSTable; import main.java.com.djrapitops.plan.database.tables.TPSTable;
@ -110,7 +111,6 @@ public class Analysis {
AnalysisData analysisData = new AnalysisData(); AnalysisData analysisData = new AnalysisData();
List<PluginData> thirdPartyPlugins = plugin.getHookHandler().getAdditionalDataSources(); List<PluginData> thirdPartyPlugins = plugin.getHookHandler().getAdditionalDataSources();
analysisData.setPluginsTabLayout(HtmlStructure.createAnalysisPluginsTabLayout(thirdPartyPlugins)); analysisData.setPluginsTabLayout(HtmlStructure.createAnalysisPluginsTabLayout(thirdPartyPlugins));
analysisData.setPlanVersion(plugin.getVersion());
Benchmark.stop("Analysis", "Create Empty dataset"); Benchmark.stop("Analysis", "Create Empty dataset");
fillDataset(analysisData, db); fillDataset(analysisData, db);
@ -261,17 +261,12 @@ public class Analysis {
} }
} }
Map<UUID, UserInfo> mappedUserInfo = new HashMap<>();
userInfo.forEach(u -> mappedUserInfo.put(u.getUuid(), u));
Map<UUID, Long> lastSeen = db.getSessionsTable().getLastSeenForAllPlayers(); Map<UUID, Long> lastSeen = db.getSessionsTable().getLastSeenForAllPlayers();
for (Map.Entry<UUID, Long> entry : lastSeen.entrySet()) { for (UserInfo info : userInfo) {
UserInfo user = mappedUserInfo.get(entry.getKey()); Long userLastSeen = lastSeen.getOrDefault(info.getUuid(), 0L);
if (user == null) { info.setLastSeen(userLastSeen);
continue;
}
user.setLastSeen(entry.getValue());
} }
userInfo.sort(new UserInfoLastPlayedComparator()); userInfo.sort(new UserInfoLastPlayedComparator());
activity.setRecentPlayersUUIDs(userInfo.stream().map(UserInfo::getUuid).collect(Collectors.toList())); activity.setRecentPlayersUUIDs(userInfo.stream().map(UserInfo::getUuid).collect(Collectors.toList()));
@ -279,7 +274,7 @@ public class Analysis {
playerCount.addPlayers(userInfo.stream().map(UserInfo::getUuid).collect(Collectors.toSet())); playerCount.addPlayers(userInfo.stream().map(UserInfo::getUuid).collect(Collectors.toSet()));
Map<UUID, Long> registered = mappedUserInfo.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().getRegistered())); Map<UUID, Long> registered = userInfo.stream().collect(Collectors.toMap(UserInfo::getUuid, UserInfo::getRegistered));
joinInfo.addRegistered(registered); joinInfo.addRegistered(registered);
activity.addBans(userInfo.stream().filter(UserInfo::isBanned).map(UserInfo::getUuid).collect(Collectors.toSet())); activity.addBans(userInfo.stream().filter(UserInfo::isBanned).map(UserInfo::getUuid).collect(Collectors.toSet()));
@ -292,15 +287,25 @@ public class Analysis {
joinInfo.addSessions(sessions); joinInfo.addSessions(sessions);
} }
Map<UUID, List<String>> geolocations = db.getIpsTable().getAllGeolocations();
geolocPart.addGeoLocations(geolocations);
analysisData.setPlayersTable(PlayersTableCreator.createTable(userInfo, joinInfo, geolocPart)); analysisData.setPlayersTable(PlayersTableCreator.createTable(userInfo, joinInfo, geolocPart));
Map<UUID, List<PlayerKill>> playerKills = db.getKillsTable().getPlayerKills(); Map<UUID, List<PlayerKill>> playerKills = db.getKillsTable().getPlayerKills();
killPart.addKills(playerKills); killPart.addKills(playerKills);
Map<UUID, List<String>> geolocations = db.getIpsTable().getAllGeolocations();
geolocPart.addGeoLocations(geolocations);
WorldTimes worldTimes = db.getWorldTimesTable().getWorldTimesOfServer(); WorldTimes worldTimes = db.getWorldTimesTable().getWorldTimesOfServer();
// Add 0 time for worlds not present.
Set<String> nonZeroWorlds = worldTimes.getWorldTimes().keySet();
for (String world : db.getWorldTable().getWorlds()) {
if (nonZeroWorlds.contains(world)) {
continue;
}
worldTimes.setGMTimesForWorld(world, new GMTimes());
}
worldPart.setWorldTimes(worldTimes); worldPart.setWorldTimes(worldTimes);
playtime.setTotalPlaytime(db.getSessionsTable().getPlaytimeOfServer()); playtime.setTotalPlaytime(db.getSessionsTable().getPlaytimeOfServer());

View File

@ -1,6 +1,5 @@
package main.java.com.djrapitops.plan.utilities.html; package main.java.com.djrapitops.plan.utilities.html;
import com.djrapitops.plugin.utilities.Verify;
import org.apache.commons.lang3.text.StrSubstitutor; import org.apache.commons.lang3.text.StrSubstitutor;
import java.io.Serializable; import java.io.Serializable;
@ -34,13 +33,27 @@ public enum Html {
BUTTON("<a class=\"button\" href=\"${0}\">${1}</a>"), BUTTON("<a class=\"button\" href=\"${0}\">${1}</a>"),
BUTTON_CLASS("class=\"button\""), BUTTON_CLASS("class=\"button\""),
LINK("<a class=\"link\" href=\"${0}\">${1}</a>"), LINK("<a class=\"link\" href=\"${0}\">${1}</a>"),
LINK_TOOLTIP("<a title=\"${2}\" class=\"link\" href=\"${0}\">${1}</a>"),
LINK_EXTERNAL("<a class=\"link\" target=\"_blank\" href=\"${0}\">${1}</a>"), LINK_EXTERNAL("<a class=\"link\" target=\"_blank\" href=\"${0}\">${1}</a>"),
LINK_CLASS("class=\"link\""), LINK_CLASS("class=\"link\""),
IMG("<img src=\"${0}\">"), IMG("<img src=\"${0}\">"),
// //
PARAGRAPH("<p>${0}</p>"),
HEADER("<h1>${0}</h1>"),
HEADER_2("<h2>${0}</h2>"),
//
DIV_W_CLASS("<div class=\"${0}\">${1}</div>"),
DIV_W_CLASS_STYLE("<div class=\"${0}\" style=\"${1}\">${2}</div>"),
//
ROW(DIV_W_CLASS.parse("row", "${0}")),
//
TABLE_END("</tbody></table>"),
TABLE_START_2("<table class=\"sortable table\"><thead><tr><th>${0}</th><th>${1}</th></tr></thead><tbody>"), TABLE_START_2("<table class=\"sortable table\"><thead><tr><th>${0}</th><th>${1}</th></tr></thead><tbody>"),
TABLE_START_3("<table class=\"sortable table\"><thead><tr><th>${0}</th><th>${1}</th><th>${2}</th></tr></thead><tbody>"), TABLE_START_3("<table class=\"sortable table\"><thead><tr><th>${0}</th><th>${1}</th><th>${2}</th></tr></thead><tbody>"),
TABLE_START_4("<table class=\"sortable table\"><thead><tr><th>${0}</th><th>${1}</th><th>${2}</th><th>${3}</th></tr></thead><tbody>"), TABLE_START_4("<table class=\"sortable table\"><thead><tr><th>${0}</th><th>${1}</th><th>${2}</th><th>${3}</th></tr></thead><tbody>"),
TABLE_SESSIONS(DIV_W_CLASS_STYLE.parse("box-footer scrollbar", "padding: 2px;",
TABLE_START_4.parse("Player", "Started", "Length", "World - Time") + "${0}" + TABLE_END.parse())
),
TABLE_SESSIONS_START(TABLE_START_3.parse("Session Started", "Session Ended", "Session Length")), TABLE_SESSIONS_START(TABLE_START_3.parse("Session Started", "Session Ended", "Session Length")),
TABLE_KILLS_START(TABLE_START_3.parse(FONT_AWESOME_ICON.parse("clock-o") + " Time", "Killed", "With")), TABLE_KILLS_START(TABLE_START_3.parse(FONT_AWESOME_ICON.parse("clock-o") + " Time", "Killed", "With")),
TABLE_FACTIONS_START(TABLE_START_4.parse(FONT_AWESOME_ICON.parse("flag") + " Faction", FONT_AWESOME_ICON.parse("bolt") + " Power", FONT_AWESOME_ICON.parse("map-o") + " Land", FONT_AWESOME_ICON.parse("user") + " Leader")), TABLE_FACTIONS_START(TABLE_START_4.parse(FONT_AWESOME_ICON.parse("flag") + " Faction", FONT_AWESOME_ICON.parse("bolt") + " Power", FONT_AWESOME_ICON.parse("map-o") + " Land", FONT_AWESOME_ICON.parse("user") + " Leader")),
@ -50,8 +63,7 @@ public enum Html {
TABLELINE_4("<tr><td><b>${0}</b></td><td>${1}</td><td>${2}</td><td>${3}</td></tr>"), TABLELINE_4("<tr><td><b>${0}</b></td><td>${1}</td><td>${2}</td><td>${3}</td></tr>"),
TABLELINE_PLAYERS("<tr><td>${0}</td><td>${1}</td><td sorttable_customkey=\"${2}\">${3}</td><td>${4}</td><td sorttable_customkey=\"${5}\">${6}</td>" + "<td sorttable_customkey=\"${7}\">${8}</td><td>${9}</td></tr>"), TABLELINE_PLAYERS("<tr><td>${0}</td><td>${1}</td><td sorttable_customkey=\"${2}\">${3}</td><td>${4}</td><td sorttable_customkey=\"${5}\">${6}</td>" + "<td sorttable_customkey=\"${7}\">${8}</td><td>${9}</td></tr>"),
TABLELINE_3_CUSTOMKEY("<tr><td sorttable_customkey=\"${0}\">${1}</td><td sorttable_customkey=\"${2}\">${3}</td><td sorttable_customkey=\"${4}\">${5}</td></tr>"), TABLELINE_3_CUSTOMKEY("<tr><td sorttable_customkey=\"${0}\">${1}</td><td sorttable_customkey=\"${2}\">${3}</td><td sorttable_customkey=\"${4}\">${5}</td></tr>"),
TABLELINE_3_CUSTOMKEY_1("<tr><td sorttable_customkey=\"${0}\">${1}</td><td>${2}</td><td>${3}</td></tr>"), TABLELINE_3_CUSTOMKEY_1("<tr><td sorttable_customkey=\"${0}\">${1}</td><td>${2}</td><td>${3}</td></tr>");
TABLE_END("</tbody></table>");
private final String html; private final String html;

View File

@ -12,8 +12,8 @@ import main.java.com.djrapitops.plan.data.additional.PluginData;
import main.java.com.djrapitops.plan.systems.info.BukkitInformationManager; import main.java.com.djrapitops.plan.systems.info.BukkitInformationManager;
import main.java.com.djrapitops.plan.utilities.FormatUtils; import main.java.com.djrapitops.plan.utilities.FormatUtils;
import main.java.com.djrapitops.plan.utilities.analysis.AnalysisUtils; import main.java.com.djrapitops.plan.utilities.analysis.AnalysisUtils;
import main.java.com.djrapitops.plan.utilities.html.graphs.WorldPieCreator; import main.java.com.djrapitops.plan.utilities.html.structure.SessionTabStructureCreator;
import main.java.com.djrapitops.plan.utilities.html.tables.KillsTableCreator; import main.java.com.djrapitops.plan.utilities.html.tables.SessionsTableCreator;
import org.apache.commons.lang3.text.StrSubstitutor; import org.apache.commons.lang3.text.StrSubstitutor;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
@ -92,114 +92,33 @@ public class HtmlStructure {
return builder.toString(); return builder.toString();
} }
public static String[] createSessionsTabContent(Map<String, List<Session>> sessions, List<Session> allSessions) throws FileNotFoundException { public static String[] createSessionsTabContentInspectPage(Map<String, List<Session>> sessions, List<Session> allSessions, UUID uuid) throws FileNotFoundException {
Map<Integer, String> serverNameIDRelationMap = new HashMap<>(); Map<UUID, Map<String, List<Session>>> map = new HashMap<>();
map.put(uuid, sessions);
if (Verify.isEmpty(allSessions)) { return SessionTabStructureCreator.creteStructure(map, allSessions, false);
return new String[]{"<div class=\"session column\">" +
"<div class=\"session-header\">" +
"<div class=\"session-col\" style=\"width: 200%;\">" +
"<h3>No Sessions</h3>" +
"</div></div></div>", ""};
}
for (Map.Entry<String, List<Session>> entry : sessions.entrySet()) {
String serverName = entry.getKey();
List<Session> serverSessions = entry.getValue();
for (Session session : serverSessions) {
serverNameIDRelationMap.put(session.getSessionID(), serverName);
}
}
StringBuilder html = new StringBuilder();
StringBuilder viewScript = new StringBuilder();
int i = 0;
for (Session session : allSessions) {
if (i >= 50) {
break;
}
String sessionStart = FormatUtils.formatTimeStampYear(session.getSessionStart());
String sessionLength = FormatUtils.formatTimeAmount(session.getLength());
String sessionEnd = FormatUtils.formatTimeStampYear(session.getSessionEnd());
String dotSeparated = separateWithDots(sessionStart, sessionLength);
// Session-column starts & header.
html.append("<div class=\"session column\">")
.append("<div class=\"session-header\">")
.append("<div class=\"session-col\" style=\"width: 200%;\">")
.append("<h3><i style=\"color:#777\" class=\"fa fa-chevron-down\" aria-hidden=\"true\"></i> ").append(dotSeparated).append("</h3>")
.append("</div>")
.append("</div>");
String serverName = serverNameIDRelationMap.get(session.getSessionID());
// Left side of Session box
html.append("<div class=\"session-content\">")
.append("<div class=\"row\">") //
.append("<div class=\"session-col\" style=\"padding: 0px;\">");
// Left side header
html.append("<div class=\"box-header\" style=\"margin: 0px;\">")
.append("<h2><i class=\"fa fa-calendar\" aria-hidden=\"true\"></i> ")
.append(sessionStart)
.append("</h2>")
.append("</div>");
// Left side content
html.append("<div class=\"box\" style=\"margin: 0px;\">")
.append("<p>Session Length: ").append(sessionLength).append("<br>")
.append("Session Ended: ").append(sessionEnd).append("<br>")
.append("Server: ").append(serverName).append("<br><br>")
.append("Mob Kills: ").append(session.getMobKills()).append("<br>")
.append("Deaths: ").append(session.getDeaths()).append("</p>");
html.append(KillsTableCreator.createTable(session.getPlayerKills()))
.append("</div>"); // Left Side content ends
// Left side ends & Right side starts
html.append("</div>")
.append("<div class=\"session-col\">");
String id = "worldPie" + session.getSessionStart() + i;
html.append("<div id=\"").append(id).append("\" style=\"width: 100%; height: 400px;\"></div>");
String[] worldData = WorldPieCreator.createSeriesData(session.getWorldTimes());
html.append("<script>")
.append("var ").append(id).append("series = {name:'World Playtime',colors: worldPieColors,colorByPoint:true,data:").append(worldData[0]).append("};")
.append("var ").append(id).append("gmseries = ").append(worldData[1]).append(";")
.append("</script>");
viewScript.append("worldPie(")
.append(id).append(", ")
.append(id).append("series, ")
.append(id).append("gmseries")
.append(");");
// Session-col, Row, Session-Content, Session-column ends.
html.append("</div>")
.append("</div>")
.append("</div>")
.append("</div>");
i++;
}
return new String[]{html.toString(), viewScript.toString()};
} }
public static String createInspectPageTabContent(String serverName, List<PluginData> plugins, Map<String, Serializable> replaceMap) { private static String[] getSessionsAsTable(Map<String, List<Session>> sessions, List<Session> allSessions, UUID uuid) {
Map<Integer, UUID> uuidByID = new HashMap<>();
for (List<Session> sessionList : sessions.values()) {
for (Session session : sessionList) {
uuidByID.put(session.getSessionID(), uuid);
}
}
return new String[]{Html.TABLE_SESSIONS.parse(SessionsTableCreator.createTable(uuidByID, allSessions)[0]), ""};
}
public static String createInspectPluginsTabContent(String serverName, List<PluginData> plugins, Map<String, Serializable> replaceMap) {
if (plugins.isEmpty()) { if (plugins.isEmpty()) {
return "<div class=\"plugins-server\">" + String icon = Html.FONT_AWESOME_ICON.parse("server");
"<div class=\"plugins-header\">" + // TODO Move plain text to Locale
"<div class=\"row\">" + String headerText = Html.HEADER_2.parse(icon + " " + serverName) + Html.PARAGRAPH.parse("No Compatible Plugins");
"<div class=\"column\">" + return Html.DIV_W_CLASS.parse("plugins-server",
"<div class=\"box-header\">" + Html.DIV_W_CLASS.parse("plugins-header",
"<h2><i class=\"fa fa-server\" aria-hidden=\"true\"></i> " + serverName + Html.ROW.parse(Html.DIV_W_CLASS.parse("box-header", headerText))
"</h2><p>No Compatible Plugins</p>" + )
"</div></div></div></div></div>"; );
} }
Map<String, List<String>> placeholders = getPlaceholdersInspect(plugins); Map<String, List<String>> placeholders = getPlaceholdersInspect(plugins);
@ -213,7 +132,7 @@ public class HtmlStructure {
.append("<div class=\"box-header\">") .append("<div class=\"box-header\">")
.append("<h2><i style=\"padding: 8px;\" class=\"fa fa-chevron-down\" aria-hidden=\"true\"></i> ") .append("<h2><i style=\"padding: 8px;\" class=\"fa fa-chevron-down\" aria-hidden=\"true\"></i> ")
.append(serverName) .append(serverName)
.append(" <i class=\"fa fa-server\" aria-hidden=\"true\"></i></h2>") .append("</h2>")
.append("</div>") .append("</div>")
.append("</div>") .append("</div>")
.append("</div>") .append("</div>")
@ -385,6 +304,7 @@ public class HtmlStructure {
int i = 0; int i = 0;
StringBuilder b = new StringBuilder(); StringBuilder b = new StringBuilder();
List<String> values = new ArrayList<>(networkPageContents.values()); List<String> values = new ArrayList<>(networkPageContents.values());
Collections.sort(values);
int size = values.size(); int size = values.size();
int extra = size % 3; int extra = size % 3;
for (int j = 0; j < extra; j++) { for (int j = 0; j < extra; j++) {

View File

@ -3,6 +3,9 @@ package main.java.com.djrapitops.plan.utilities.html.graphs;
import main.java.com.djrapitops.plan.data.time.GMTimes; import main.java.com.djrapitops.plan.data.time.GMTimes;
import main.java.com.djrapitops.plan.data.time.WorldTimes; import main.java.com.djrapitops.plan.data.time.WorldTimes;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -25,11 +28,13 @@ public class WorldPieCreator {
Map<String, Long> playtimePerWorld = worldTimes.getWorldTimes().entrySet().stream() Map<String, Long> playtimePerWorld = worldTimes.getWorldTimes().entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().getTotal())); .collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().getTotal()));
List<String> worlds = new ArrayList<>(playtimePerWorld.keySet());
Collections.sort(worlds);
int size = playtimePerWorld.size(); int size = playtimePerWorld.size();
for (Map.Entry<String, Long> world : playtimePerWorld.entrySet()) { for (String worldName : worlds) {
String worldName = world.getKey();
seriesBuilder.append("{name:'").append(worldName) seriesBuilder.append("{name:'").append(worldName)
.append("',y:").append(world.getValue()) .append("',y:").append(playtimePerWorld.getOrDefault(worldName, 0L))
.append(",drilldown: '").append(worldName).append("'"); .append(",drilldown: '").append(worldName).append("'");
seriesBuilder.append("}"); seriesBuilder.append("}");

View File

@ -0,0 +1,197 @@
/*
* Licence is provided in the jar as license.yml also here:
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
*/
package main.java.com.djrapitops.plan.utilities.html.structure;
import com.djrapitops.plugin.utilities.Verify;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.Settings;
import main.java.com.djrapitops.plan.data.Session;
import main.java.com.djrapitops.plan.data.analysis.JoinInfoPart;
import main.java.com.djrapitops.plan.data.time.GMTimes;
import main.java.com.djrapitops.plan.data.time.WorldTimes;
import main.java.com.djrapitops.plan.utilities.FormatUtils;
import main.java.com.djrapitops.plan.utilities.MiscUtils;
import main.java.com.djrapitops.plan.utilities.comparators.SessionStartComparator;
import main.java.com.djrapitops.plan.utilities.html.Html;
import main.java.com.djrapitops.plan.utilities.html.HtmlStructure;
import main.java.com.djrapitops.plan.utilities.html.graphs.WorldPieCreator;
import main.java.com.djrapitops.plan.utilities.html.tables.KillsTableCreator;
import main.java.com.djrapitops.plan.utilities.html.tables.SessionsTableCreator;
import java.sql.SQLException;
import java.util.*;
import java.util.stream.Collectors;
/**
* //TODO Class Javadoc Comment
*
* @author Rsl1122
*/
public class SessionTabStructureCreator {
public static String[] creteStructure(Map<UUID, Map<String, List<Session>>> sessions, List<Session> allSessions, boolean appendName) {
Map<Integer, UUID> uuidsByID = generateIDtoUUIDMap(sessions);
if (Settings.DISPLAY_SESSIONS_AS_TABLE.isTrue()) {
return new String[]{Html.TABLE_SESSIONS.parse(SessionsTableCreator.createTable(uuidsByID, allSessions)[0]), ""};
}
if (Verify.isEmpty(allSessions)) {
return new String[]{"<div class=\"session column\">" +
"<div class=\"session-header\">" +
"<div class=\"session-col\" style=\"width: 200%;\">" +
"<h3>No Sessions</h3>" +
"</div></div></div>", ""};
}
Map<Integer, String> serverNameIDMap = generateIDtoServerNameMap(sessions);
StringBuilder html = new StringBuilder();
StringBuilder viewScript = new StringBuilder();
int i = 0;
for (Session session : allSessions) {
if (i >= 50) {
break;
}
int sessionID = session.getSessionID();
UUID uuid = uuidsByID.get(sessionID);
String serverName = serverNameIDMap.get(sessionID);
String sessionStart = FormatUtils.formatTimeStampYear(session.getSessionStart());
String sessionLength = FormatUtils.formatTimeAmount(session.getLength());
String sessionEnd = FormatUtils.formatTimeStampYear(session.getSessionEnd());
String name = Plan.getInstance().getDataCache().getName(uuid);
String link = Html.LINK.parse(Plan.getPlanAPI().getPlayerInspectPageLink(name), name);
String dotSeparated = appendName ?
HtmlStructure.separateWithDots(link, sessionStart, sessionLength) :
HtmlStructure.separateWithDots(sessionStart, sessionLength);
// Session-column starts & header.
html.append("<div class=\"session column\">")
.append("<div title=\"Session ID: ").append(sessionID).append("\" class=\"session-header\">")
.append("<div class=\"session-col\" style=\"width: 200%;\">")
.append("<h3><i style=\"color:#777\" class=\"fa fa-chevron-down\" aria-hidden=\"true\"></i> ").append(dotSeparated).append("</h3>")
.append("</div>")
.append("</div>");
// Left side of Session box
html.append("<div class=\"session-content\">")
.append("<div class=\"row\">") //
.append("<div class=\"session-col\" style=\"padding: 0px;\">");
// Left side header
html.append("<div class=\"box-header\" style=\"margin: 0px;\">")
.append("<h2><i class=\"fa fa-calendar\" aria-hidden=\"true\"></i> ")
.append(sessionStart)
.append("</h2>")
.append("</div>");
// Left side content
html.append("<div class=\"box\" style=\"margin: 0px;\">")
.append("<p>Session Length: ").append(sessionLength).append("<br>")
.append("Session Ended: ").append(sessionEnd).append("<br>")
.append("Server: ").append(serverName).append("<br><br>")
.append("Mob Kills: ").append(session.getMobKills()).append("<br>")
.append("Deaths: ").append(session.getDeaths()).append("</p>");
html.append(KillsTableCreator.createTable(session.getPlayerKills()))
.append("</div>"); // Left Side content ends
// Left side ends & Right side starts
html.append("</div>")
.append("<div class=\"session-col\">");
String id = "worldPie" + session.getSessionStart() + i;
html.append("<div id=\"").append(id).append("\" style=\"width: 100%; height: 400px;\"></div>");
WorldTimes worldTimes = session.getWorldTimes();
try {
// Add 0 time for worlds not present.
Set<String> nonZeroWorlds = worldTimes.getWorldTimes().keySet();
for (String world : MiscUtils.getIPlan().getDB().getWorldTable().getWorlds()) {
if (nonZeroWorlds.contains(world)) {
continue;
}
worldTimes.setGMTimesForWorld(world, new GMTimes());
}
} catch (SQLException e) {
Log.toLog("SessionTabStructureCreator", e);
}
String[] worldData = WorldPieCreator.createSeriesData(worldTimes);
html.append("<script>")
.append("var ").append(id).append("series = {name:'World Playtime',colors: worldPieColors,colorByPoint:true,data:").append(worldData[0]).append("};")
.append("var ").append(id).append("gmseries = ").append(worldData[1]).append(";")
.append("</script>");
viewScript.append("worldPie(")
.append(id).append(", ")
.append(id).append("series, ")
.append(id).append("gmseries")
.append(");");
// Session-col, Row, Session-Content, Session-column ends.
html.append("</div>")
.append("</div>")
.append("</div>")
.append("</div>");
i++;
}
return new String[]{html.toString(), viewScript.toString()};
}
private static Map<Integer, String> generateIDtoServerNameMap(Map<UUID, Map<String, List<Session>>> sessions) {
Map<Integer, String> serverNameIDRelationMap = new HashMap<>();
for (Map<String, List<Session>> map : sessions.values()) {
for (Map.Entry<String, List<Session>> entry : map.entrySet()) {
String serverName = entry.getKey();
List<Session> serverSessions = entry.getValue();
for (Session session : serverSessions) {
serverNameIDRelationMap.put(session.getSessionID(), serverName);
}
}
}
return serverNameIDRelationMap;
}
private static Map<Integer, UUID> generateIDtoUUIDMap(Map<UUID, Map<String, List<Session>>> sessions) {
Map<Integer, UUID> uuidsByID = new HashMap<>();
for (Map.Entry<UUID, Map<String, List<Session>>> entry : sessions.entrySet()) {
UUID uuid = entry.getKey();
for (List<Session> sessionList : entry.getValue().values()) {
for (Session session : sessionList) {
uuidsByID.put(session.getSessionID(), uuid);
}
}
}
return uuidsByID;
}
public static String[] creteStructure(JoinInfoPart joinInfoPart) {
Map<UUID, Map<String, List<Session>>> map = new HashMap<>();
Map<UUID, List<Session>> sessions = joinInfoPart.getSessions();
for (Map.Entry<UUID, List<Session>> entry : sessions.entrySet()) {
Map<String, List<Session>> serverSpecificMap = new HashMap<>();
serverSpecificMap.put("This server", entry.getValue());
map.put(entry.getKey(), serverSpecificMap);
}
List<Session> allSessions = sessions.values().stream()
.flatMap(Collection::stream)
.sorted(new SessionStartComparator())
.collect(Collectors.toList());
return creteStructure(map, allSessions, true);
}
}

View File

@ -24,7 +24,7 @@ import java.util.*;
*/ */
public class SessionsTableCreator { public class SessionsTableCreator {
public static String[] createTables(JoinInfoPart joinInfoPart) { public static String[] createTable(JoinInfoPart joinInfoPart) {
Map<Integer, UUID> uuidByID = new HashMap<>(); Map<Integer, UUID> uuidByID = new HashMap<>();
for (Map.Entry<UUID, List<Session>> entry : joinInfoPart.getSessions().entrySet()) { for (Map.Entry<UUID, List<Session>> entry : joinInfoPart.getSessions().entrySet()) {
List<Session> sessions = entry.getValue(); List<Session> sessions = entry.getValue();
@ -34,6 +34,10 @@ public class SessionsTableCreator {
} }
List<Session> allSessions = joinInfoPart.getAllSessions(); List<Session> allSessions = joinInfoPart.getAllSessions();
return createTable(uuidByID, allSessions);
}
public static String[] createTable(Map<Integer, UUID> uuidByID, List<Session> allSessions) {
if (allSessions.isEmpty()) { if (allSessions.isEmpty()) {
return new String[]{Html.TABLELINE_4.parse("<b>No Sessions</b>", "", "", ""), return new String[]{Html.TABLELINE_4.parse("<b>No Sessions</b>", "", "", ""),
Html.TABLELINE_2.parse("<b>No Sessions</b>", "")}; Html.TABLELINE_2.parse("<b>No Sessions</b>", "")};
@ -73,8 +77,9 @@ public class SessionsTableCreator {
String world = getLongestWorldPlayed(session); String world = getLongestWorldPlayed(session);
String inspectUrl = Plan.getPlanAPI().getPlayerInspectPageLink(name); String inspectUrl = Plan.getPlanAPI().getPlayerInspectPageLink(name);
String toolTip = "Session ID: " + (session.isFetchedFromDB() ? session.getSessionID() : "Not Saved.");
sessionTableBuilder.append(Html.TABLELINE_4.parse( sessionTableBuilder.append(Html.TABLELINE_4.parse(
Html.LINK.parse(inspectUrl, name), Html.LINK_TOOLTIP.parse(inspectUrl, name, toolTip),
start, start,
length, length,
world world

View File

@ -1,4 +1,4 @@
name: Plan name: Plan
author: Rsl1122 author: Rsl1122
main: main.java.com.djrapitops.plan.PlanBungee main: main.java.com.djrapitops.plan.PlanBungee
version: 4.0.2 version: 4.0.3

View File

@ -52,6 +52,8 @@ Data:
Customization: Customization:
UseServerTime: true UseServerTime: true
Display:
SessionsAsTable: false
Formatting: Formatting:
DecimalPoints: '#.##' DecimalPoints: '#.##'
TimeAmount: TimeAmount:

View File

@ -41,7 +41,7 @@
<h2><i class="fa fa-info-circle"></i> Information</h2> <h2><i class="fa fa-info-circle"></i> Information</h2>
</div> </div>
<div class="box" style="height: 75%;"> <div class="box" style="height: 75%;">
<p>${playersOnline}/${playersMax} Players Online</p> <p>${playersOnline} Players Online</p>
<p>${playersTotal} Total Players</p> <p>${playersTotal} Total Players</p>
<p>${playersNewDay} New Players Today<br>${playersNewWeek} New Players This Week</p> <p>${playersNewDay} New Players Today<br>${playersNewWeek} New Players This Week</p>
</div> </div>

View File

@ -14,6 +14,10 @@
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script> <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
</head> </head>
<body> <body>
<script>
var worldPieColors = [${worldPieColors}];
var gmPieColors = [${gmPieColors}];
</script>
<header> <header>
<div> <div>
<div class="right fa-stack fa-lg" style="padding: 23px; margin:8px"> <div class="right fa-stack fa-lg" style="padding: 23px; margin:8px">
@ -183,21 +187,7 @@
<div class="box-header"> <div class="box-header">
<h2><i class="fa fa-calendar"></i> 50 Most Recent Sessions</h2> <h2><i class="fa fa-calendar"></i> 50 Most Recent Sessions</h2>
</div> </div>
<div class="box-footer scrollbar" style="padding: 2px;"> ${contentSessions}
<table class="sortable table">
<thead>
<tr>
<th>Player</th>
<th>Started</th>
<th>Length</th>
<th>World - Time</th>
</tr>
</thead>
<tbody>
${tableBodySessions}
</tbody>
</table>
</div>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
@ -358,6 +348,7 @@
<script src="./js/performanceGraph.js"></script> <script src="./js/performanceGraph.js"></script>
<script src="./js/worldMap.js"></script> <script src="./js/worldMap.js"></script>
<script src="./js/worldPie.js"></script> <script src="./js/worldPie.js"></script>
<script src="./js/sessionTabExpand.js"></script>
<script> <script>
Highcharts.setOptions({ Highcharts.setOptions({
lang: {noData: "No Data to Display"}, lang: {noData: "No Data to Display"},
@ -449,8 +440,6 @@
y: ${banned} y: ${banned}
}] }]
}; };
var worldPieColors = [${worldPieColors}];
var gmPieColors = [${gmPieColors}];
var worldSeries = { var worldSeries = {
name: 'World Playtime', name: 'World Playtime',
colorByPoint: true, colorByPoint: true,
@ -473,7 +462,14 @@
</script> </script>
<script> <script>
$( function() { $( function() {
$( "#tabs" ).tabs(); var resourceTab = window.sessionStorage.getItem("AnalysisResourceTab");
if (resourceTab == null) {
resourceTab = 1;
}
$( "#tabs" ).tabs({active: resourceTab});
$( "#tabs" ).on("tabsactivate", function(event, ui) {
window.sessionStorage.setItem("AnalysisResourceTab", $( "#tabs" ).tabs( "option", "active" ));
});
}); });
</script> </script>
<script> <script>
@ -502,6 +498,7 @@
worldChart('worldGraph', entitySeries, chunkSeries, playersOnlineSeries); worldChart('worldGraph', entitySeries, chunkSeries, playersOnlineSeries);
worldMap('choropleth', '#EEFFEE', '#267f00', mapSeries); worldMap('choropleth', '#EEFFEE', '#267f00', mapSeries);
punchCard('punchcard', punchcardSeries); punchCard('punchcard', punchcardSeries);
${sessionTabGraphViewFunctions}
/*countUpTimer();*/ /*countUpTimer();*/
function openFunc(i) { function openFunc(i) {

View File

@ -1,7 +1,7 @@
name: Plan name: Plan
author: Rsl1122 author: Rsl1122
main: main.java.com.djrapitops.plan.Plan main: main.java.com.djrapitops.plan.Plan
version: 4.0.2 version: 4.0.3
softdepend: softdepend:
- OnTime - OnTime
- EssentialsX - EssentialsX

View File

@ -437,6 +437,11 @@ public class DatabaseTest {
assertNull(sessions.get(worlds.get(1))); assertNull(sessions.get(worlds.get(1)));
assertEquals(session, savedSessions.get(0)); assertEquals(session, savedSessions.get(0));
Map<UUID, Long> lastSeen = sessionsTable.getLastSeenForAllPlayers();
assertTrue(lastSeen.containsKey(uuid));
assertFalse(lastSeen.containsKey(uuid2));
assertEquals(22345L, (long) lastSeen.get(uuid));
} }
@Test @Test

View File

@ -67,9 +67,10 @@ public class ComparatorTest {
longValues.sort(Long::compare); longValues.sort(Long::compare);
Collections.reverse(longValues); Collections.reverse(longValues);
System.out.println(longValues);
userInfo.sort(new UserInfoLastPlayedComparator()); userInfo.sort(new UserInfoLastPlayedComparator());
List<Long> afterSort = userInfo.stream().map(UserInfo::getLastSeen).collect(Collectors.toList()); List<Long> afterSort = userInfo.stream().map(UserInfo::getLastSeen).collect(Collectors.toList());
System.out.println(afterSort);
assertEquals(longValues, afterSort); assertEquals(longValues, afterSort);
} }

View File

@ -8,6 +8,7 @@ import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner; import org.powermock.modules.junit4.PowerMockRunner;
import test.java.utils.MockUtils;
import test.java.utils.RandomData; import test.java.utils.RandomData;
import test.java.utils.TestInit; import test.java.utils.TestInit;
@ -47,7 +48,7 @@ public class HtmlStructureTest {
@Test @Test
public void createSessionsTabContent() throws Exception { public void createSessionsTabContent() throws Exception {
List<Session> allSessions = sessions.values().stream().flatMap(Collection::stream).collect(Collectors.toList()); List<Session> allSessions = sessions.values().stream().flatMap(Collection::stream).collect(Collectors.toList());
String[] sessionsTab = HtmlStructure.createSessionsTabContent(sessions, allSessions); String[] sessionsTab = HtmlStructure.createSessionsTabContentInspectPage(sessions, allSessions, MockUtils.getPlayerUUID());
int opened = StringUtils.countMatches(sessionsTab[0], "<div"); int opened = StringUtils.countMatches(sessionsTab[0], "<div");
int closed = StringUtils.countMatches(sessionsTab[0], "</div"); int closed = StringUtils.countMatches(sessionsTab[0], "</div");

View File

@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.djrapitops</groupId> <groupId>com.djrapitops</groupId>
<artifactId>PlanPluginBridge</artifactId> <artifactId>PlanPluginBridge</artifactId>
<version>4.0.0</version> <version>4.0.3</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<repositories> <repositories>
<repository> <repository>

View File

@ -13,6 +13,8 @@ import com.djrapitops.pluginbridge.plan.superbvote.SuperbVoteHook;
import com.djrapitops.pluginbridge.plan.towny.TownyHook; import com.djrapitops.pluginbridge.plan.towny.TownyHook;
import com.djrapitops.pluginbridge.plan.vault.VaultHook; import com.djrapitops.pluginbridge.plan.vault.VaultHook;
import com.djrapitops.pluginbridge.plan.viaversion.ViaVersionHook; import com.djrapitops.pluginbridge.plan.viaversion.ViaVersionHook;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Settings;
import main.java.com.djrapitops.plan.data.additional.HookHandler; import main.java.com.djrapitops.plan.data.additional.HookHandler;
/** /**
@ -56,7 +58,10 @@ public class Bridge {
for (Hook hook : hooks) { for (Hook hook : hooks) {
try { try {
hook.hook(); hook.hook();
} catch (Exception | NoClassDefFoundError ignore) { } catch (Exception | NoClassDefFoundError e) {
if (Settings.DEV_MODE.isTrue()) {
Log.toLog("PluginBridge", e);
}
} }
} }
} }

View File

@ -21,6 +21,10 @@ public abstract class Hook {
protected HookHandler hookHandler; protected HookHandler hookHandler;
private Hook() {
throw new IllegalStateException();
}
/** /**
* Class constructor. * Class constructor.
* <p> * <p>
@ -45,8 +49,9 @@ public abstract class Hook {
/** /**
* Constructor to set enabled to false. * Constructor to set enabled to false.
*/ */
public Hook() { public Hook(HookHandler hookHandler) {
enabled = false; enabled = false;
this.hookHandler = hookHandler;
} }
protected void addPluginDataSource(PluginData pluginData) { protected void addPluginDataSource(PluginData pluginData) {

View File

@ -25,7 +25,7 @@ public class LiteBansHook extends Hook {
*/ */
@SuppressWarnings("ResultOfMethodCallIgnored") @SuppressWarnings("ResultOfMethodCallIgnored")
public LiteBansHook(HookHandler hookH) { public LiteBansHook(HookHandler hookH) {
super(); super(hookH);
try { try {
Database.get(); Database.get();
enabled = true; enabled = true;