mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2025-01-07 00:48:24 +01:00
New Branch 'html' as a html Diff tool. Initial version 4.1.7
This commit is contained in:
parent
f07b8fa17f
commit
5483075f77
File diff suppressed because one or more lines are too long
Binary file not shown.
Before Width: | Height: | Size: 106 KiB |
File diff suppressed because one or more lines are too long
Binary file not shown.
Before Width: | Height: | Size: 82 KiB |
@ -1,171 +0,0 @@
|
||||
/*
|
||||
* Player Analytics Bukkit plugin for monitoring server activity.
|
||||
* Copyright (C) 2017 Risto Lahtela / Rsl1122
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the Plan License. (licence.yml)
|
||||
* Modified software can only be redistributed if allowed in the licence.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the License
|
||||
* along with this program.
|
||||
* If not it should be visible on the distribution page.
|
||||
* Or here
|
||||
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/licence.yml
|
||||
*/
|
||||
package com.djrapitops.plan;
|
||||
|
||||
import com.djrapitops.plan.api.exceptions.EnableException;
|
||||
import com.djrapitops.plan.command.PlanCommand;
|
||||
import com.djrapitops.plan.system.BukkitSystem;
|
||||
import com.djrapitops.plan.system.processing.importing.ImporterManager;
|
||||
import com.djrapitops.plan.system.processing.importing.importers.OfflinePlayerImporter;
|
||||
import com.djrapitops.plan.system.settings.locale.Locale;
|
||||
import com.djrapitops.plan.system.settings.locale.Msg;
|
||||
import com.djrapitops.plan.system.settings.theme.PlanColorScheme;
|
||||
import com.djrapitops.plan.utilities.metrics.BStats;
|
||||
import com.djrapitops.plugin.BukkitPlugin;
|
||||
import com.djrapitops.plugin.StaticHolder;
|
||||
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 org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Main class for Bukkit that manages the plugin.
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class Plan extends BukkitPlugin implements PlanPlugin {
|
||||
|
||||
private BukkitSystem system;
|
||||
|
||||
/**
|
||||
* Used to get the plugin-instance singleton.
|
||||
*
|
||||
* @return this object.
|
||||
*/
|
||||
public static Plan getInstance() {
|
||||
return (Plan) StaticHolder.getInstance(Plan.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* OnEnable method.
|
||||
* <p>
|
||||
* - Enables the plugin's subsystems.
|
||||
*/
|
||||
@Override
|
||||
public void onEnable() {
|
||||
super.onEnable();
|
||||
try {
|
||||
Benchmark.start("Enable");
|
||||
system = new BukkitSystem(this);
|
||||
system.enable();
|
||||
|
||||
ImporterManager.registerImporter(new OfflinePlayerImporter());
|
||||
|
||||
BStats bStats = new BStats(this);
|
||||
bStats.registerMetrics();
|
||||
|
||||
Log.debug("Verbose debug messages are enabled.");
|
||||
Benchmark.stop("Enable", "Enable");
|
||||
Log.logDebug("Enable");
|
||||
Log.info(Locale.get(Msg.ENABLED).toString());
|
||||
} 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 /plan reload");
|
||||
onDisable();
|
||||
} catch (Exception e) {
|
||||
Logger.getGlobal().log(Level.SEVERE, this.getClass().getSimpleName() + "-v" + getVersion(), e);
|
||||
Log.error("Plugin Failed to Initialize Correctly. If this issue is caused by config settings you can use /plan reload");
|
||||
Log.error("This error should be reported at https://github.com/Rsl1122/Plan-PlayerAnalytics/issues");
|
||||
onDisable();
|
||||
}
|
||||
registerCommand("plan", new PlanCommand(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ColorScheme getColorScheme() {
|
||||
return PlanColorScheme.create();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the plugin.
|
||||
*/
|
||||
@Override
|
||||
public void onDisable() {
|
||||
system.disable();
|
||||
|
||||
Log.info(Locale.get(Msg.DISABLED).toString());
|
||||
Benchmark.pluginDisabled(Plan.class);
|
||||
DebugLog.pluginDisabled(Plan.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return getDescription().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReload() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReloading() {
|
||||
return reloading;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Deprecated due to use of APF Config
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public void reloadConfig() {
|
||||
throw new IllegalStateException("This method should be used on this plugin. Use onReload() instead");
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Deprecated due to use of APF Config
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public FileConfiguration getConfig() {
|
||||
throw new IllegalStateException("This method should be used on this plugin. Use getMainConfig() instead");
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Deprecated due to use of APF Config
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public void saveConfig() {
|
||||
throw new IllegalStateException("This method should be used on this plugin. Use getMainConfig().save() instead");
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Deprecated due to use of APF Config
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public void saveDefaultConfig() {
|
||||
throw new IllegalStateException("This method should be used on this plugin.");
|
||||
}
|
||||
|
||||
public BukkitSystem getSystem() {
|
||||
return system;
|
||||
}
|
||||
}
|
@ -1,98 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan;
|
||||
|
||||
import com.djrapitops.plan.api.exceptions.EnableException;
|
||||
import com.djrapitops.plan.command.PlanBungeeCommand;
|
||||
import com.djrapitops.plan.system.BungeeSystem;
|
||||
import com.djrapitops.plan.system.settings.locale.Locale;
|
||||
import com.djrapitops.plan.system.settings.locale.Msg;
|
||||
import com.djrapitops.plan.system.settings.theme.PlanColorScheme;
|
||||
import com.djrapitops.plugin.BungeePlugin;
|
||||
import com.djrapitops.plugin.StaticHolder;
|
||||
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 java.io.InputStream;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Bungee Main class.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class PlanBungee extends BungeePlugin implements PlanPlugin {
|
||||
|
||||
private BungeeSystem system;
|
||||
|
||||
public static PlanBungee getInstance() {
|
||||
return (PlanBungee) StaticHolder.getInstance(PlanBungee.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
super.onEnable();
|
||||
try {
|
||||
system = new BungeeSystem(this);
|
||||
system.enable();
|
||||
|
||||
Log.info(Locale.get(Msg.ENABLED).toString());
|
||||
} 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 /planbungee reload");
|
||||
onDisable();
|
||||
} catch (Exception e) {
|
||||
Logger.getGlobal().log(Level.SEVERE, this.getClass().getSimpleName() + "-v" + getVersion(), e);
|
||||
Log.error("Plugin Failed to Initialize Correctly. If this issue is caused by config settings you can use /planbungee reload");
|
||||
Log.error("This error should be reported at https://github.com/Rsl1122/Plan-PlayerAnalytics/issues");
|
||||
onDisable();
|
||||
}
|
||||
registerCommand("planbungee", new PlanBungeeCommand(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
system.disable();
|
||||
|
||||
Log.info(Locale.get(Msg.DISABLED).toString());
|
||||
Benchmark.pluginDisabled(PlanBungee.class);
|
||||
DebugLog.pluginDisabled(PlanBungee.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return super.getDescription().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReload() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getResource(String resource) {
|
||||
return getResourceAsStream(resource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ColorScheme getColorScheme() {
|
||||
return PlanColorScheme.create();
|
||||
}
|
||||
|
||||
public BungeeSystem getSystem() {
|
||||
return system;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReloading() {
|
||||
return reloading;
|
||||
}
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan;
|
||||
|
||||
import com.djrapitops.plugin.IPlugin;
|
||||
import com.djrapitops.plugin.api.Check;
|
||||
import com.djrapitops.plugin.settings.ColorScheme;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* Abstraction interface for both Plan and PlanBungee.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public interface PlanPlugin extends IPlugin {
|
||||
static PlanPlugin getInstance() {
|
||||
boolean bukkitAvailable = Check.isBukkitAvailable();
|
||||
boolean bungeeAvailable = Check.isBungeeAvailable();
|
||||
if (bukkitAvailable) {
|
||||
try {
|
||||
Plan instance = Plan.getInstance();
|
||||
if (instance != null) {
|
||||
return instance;
|
||||
}
|
||||
} catch (IllegalStateException ignored) {
|
||||
}
|
||||
}
|
||||
if (bungeeAvailable) {
|
||||
try {
|
||||
PlanBungee instance = PlanBungee.getInstance();
|
||||
if (instance != null) {
|
||||
return instance;
|
||||
}
|
||||
} catch (IllegalStateException ignored) {
|
||||
}
|
||||
}
|
||||
throw new IllegalAccessError("Plugin instance not available");
|
||||
}
|
||||
|
||||
@Override
|
||||
File getDataFolder();
|
||||
|
||||
InputStream getResource(String resource);
|
||||
|
||||
ColorScheme getColorScheme();
|
||||
|
||||
@Override
|
||||
boolean isReloading();
|
||||
}
|
@ -1,111 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan;
|
||||
|
||||
import com.djrapitops.plan.api.exceptions.database.DBException;
|
||||
import com.djrapitops.plan.api.exceptions.database.DBInitException;
|
||||
import com.djrapitops.plan.data.Actions;
|
||||
import com.djrapitops.plan.data.container.Action;
|
||||
import com.djrapitops.plan.data.container.Session;
|
||||
import com.djrapitops.plan.system.cache.CacheSystem;
|
||||
import com.djrapitops.plan.system.cache.DataCache;
|
||||
import com.djrapitops.plan.system.cache.SessionCache;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plan.utilities.MiscUtils;
|
||||
import com.djrapitops.plugin.StaticHolder;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Thread that is run when JVM shuts down.
|
||||
* <p>
|
||||
* Saves active sessions to the Database (PlayerQuitEvent is not called)
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class ShutdownHook extends Thread {
|
||||
|
||||
private static boolean activated = false;
|
||||
|
||||
private static boolean isActivated() {
|
||||
return activated;
|
||||
}
|
||||
|
||||
private static void activate(ShutdownHook hook) {
|
||||
activated = true;
|
||||
Runtime.getRuntime().addShutdownHook(hook);
|
||||
}
|
||||
|
||||
public void register() {
|
||||
if (isActivated()) {
|
||||
return;
|
||||
}
|
||||
activate(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Log.debug("Shutdown hook triggered.");
|
||||
|
||||
Database db = null;
|
||||
try {
|
||||
Map<UUID, Session> activeSessions = SessionCache.getActiveSessions();
|
||||
long now = MiscUtils.getTime();
|
||||
db = Database.getActive();
|
||||
if (!db.isOpen()) {
|
||||
db.init();
|
||||
}
|
||||
|
||||
saveFirstSessionInformation(db, now);
|
||||
saveActiveSessions(db, activeSessions, now);
|
||||
} catch (IllegalStateException ignored) {
|
||||
/* Database is not initialized */
|
||||
} catch (DBInitException e) {
|
||||
Log.toLog(this.getClass(), e);
|
||||
} finally {
|
||||
if (db != null) {
|
||||
try {
|
||||
db.close();
|
||||
} catch (DBException e) {
|
||||
Log.toLog(this.getClass(), e);
|
||||
}
|
||||
}
|
||||
StaticHolder.unRegister(Plan.class);
|
||||
}
|
||||
}
|
||||
|
||||
private void saveFirstSessionInformation(Database db, long now) {
|
||||
DataCache dataCache = CacheSystem.getInstance().getDataCache();
|
||||
for (Map.Entry<UUID, Integer> entry : dataCache.getFirstSessionMsgCounts().entrySet()) {
|
||||
try {
|
||||
UUID uuid = entry.getKey();
|
||||
int messagesSent = entry.getValue();
|
||||
db.save().action(uuid, new Action(now, Actions.FIRST_LOGOUT, "Messages sent: " + messagesSent));
|
||||
} catch (DBException e) {
|
||||
Log.toLog(this.getClass(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void saveActiveSessions(Database db, Map<UUID, Session> activeSessions, long now) {
|
||||
for (Map.Entry<UUID, Session> entry : activeSessions.entrySet()) {
|
||||
UUID uuid = entry.getKey();
|
||||
Session session = entry.getValue();
|
||||
long sessionEnd = session.getSessionEnd();
|
||||
if (sessionEnd == -1) {
|
||||
session.endSession(now);
|
||||
}
|
||||
try {
|
||||
Log.debug("Shutdown: Saving a session: " + session.getSessionStart());
|
||||
db.save().session(uuid, session);
|
||||
} catch (DBException e) {
|
||||
Log.toLog(this.getClass(), e);
|
||||
}
|
||||
}
|
||||
activeSessions.clear();
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.api;
|
||||
|
||||
import com.djrapitops.plan.data.plugin.PluginData;
|
||||
import com.djrapitops.plan.system.BukkitSystem;
|
||||
import com.djrapitops.plan.system.database.databases.operation.FetchOperations;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* PlanAPI extension for Bukkit
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class BukkitAPI extends CommonAPI {
|
||||
|
||||
private final BukkitSystem bukkitSystem;
|
||||
|
||||
public BukkitAPI(BukkitSystem bukkitSystem) {
|
||||
this.bukkitSystem = bukkitSystem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPluginDataSource(PluginData pluginData) {
|
||||
bukkitSystem.getHookHandler().addPluginDataSource(pluginData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlayerName(UUID uuid) {
|
||||
return bukkitSystem.getCacheSystem().getDataCache().getName(uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchOperations fetchFromPlanDB() {
|
||||
return bukkitSystem.getDatabaseSystem().getActiveDatabase().fetch();
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.api;
|
||||
|
||||
import com.djrapitops.plan.data.plugin.PluginData;
|
||||
import com.djrapitops.plan.system.BungeeSystem;
|
||||
import com.djrapitops.plan.system.database.databases.operation.FetchOperations;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* PlanAPI extension for Bungee.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class BungeeAPI extends CommonAPI {
|
||||
|
||||
private final BungeeSystem bungeeSystem;
|
||||
|
||||
public BungeeAPI(BungeeSystem bungeeSystem) {
|
||||
this.bungeeSystem = bungeeSystem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPluginDataSource(PluginData pluginData) {
|
||||
bungeeSystem.getHookHandler().addPluginDataSource(pluginData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlayerName(UUID uuid) {
|
||||
return bungeeSystem.getCacheSystem().getDataCache().getName(uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchOperations fetchFromPlanDB() {
|
||||
return bungeeSystem.getDatabaseSystem().getActiveDatabase().fetch();
|
||||
}
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.api;
|
||||
|
||||
import com.djrapitops.plan.api.exceptions.database.DBException;
|
||||
import com.djrapitops.plan.utilities.uuid.UUIDUtility;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* PlanAPI extension for all implementations.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public abstract class CommonAPI implements PlanAPI {
|
||||
|
||||
@Override
|
||||
public String getPlayerInspectPageLink(UUID uuid) {
|
||||
return getPlayerInspectPageLink(getPlayerName(uuid));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlayerInspectPageLink(String playerName) {
|
||||
return "../player/" + playerName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID playerNameToUUID(String playerName) {
|
||||
return UUIDUtility.getUUIDOf(playerName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<UUID, String> getKnownPlayerNames() {
|
||||
try {
|
||||
return fetchFromPlanDB().getPlayerNames();
|
||||
} catch (DBException e) {
|
||||
Log.toLog(this.getClass(), e);
|
||||
return new HashMap<>();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.api;
|
||||
|
||||
import com.djrapitops.plan.data.plugin.PluginData;
|
||||
import com.djrapitops.plan.system.PlanSystem;
|
||||
import com.djrapitops.plan.system.database.databases.operation.FetchOperations;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Interface for PlanAPI methods.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public interface PlanAPI {
|
||||
|
||||
static PlanAPI getInstance() {
|
||||
return PlanSystem.getInstance().getPlanAPI();
|
||||
}
|
||||
|
||||
void addPluginDataSource(PluginData pluginData);
|
||||
|
||||
String getPlayerInspectPageLink(UUID uuid);
|
||||
|
||||
String getPlayerInspectPageLink(String playerName);
|
||||
|
||||
String getPlayerName(UUID uuid);
|
||||
|
||||
UUID playerNameToUUID(String playerName);
|
||||
|
||||
Map<UUID, String> getKnownPlayerNames();
|
||||
|
||||
FetchOperations fetchFromPlanDB();
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.api.exceptions;
|
||||
|
||||
/**
|
||||
* Thrown when something goes wrong with Plan initialization.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class EnableException extends Exception {
|
||||
|
||||
public EnableException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public EnableException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.api.exceptions;
|
||||
|
||||
/**
|
||||
* Exception thrown when Page encounters an Exception.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class ParseException extends Exception {
|
||||
|
||||
public ParseException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
package com.djrapitops.plan.api.exceptions;
|
||||
|
||||
public class PassEncryptException extends Exception {
|
||||
|
||||
public PassEncryptException(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
public PassEncryptException(String s, Throwable throwable) {
|
||||
super(s, throwable);
|
||||
}
|
||||
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.api.exceptions;
|
||||
|
||||
import com.djrapitops.plan.api.exceptions.connection.WebException;
|
||||
import com.djrapitops.plan.system.webserver.auth.FailReason;
|
||||
|
||||
/**
|
||||
* Thrown when WebUser can not be authorized (WebServer).
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class WebUserAuthException extends WebException {
|
||||
|
||||
private final FailReason failReason;
|
||||
|
||||
public WebUserAuthException(FailReason failReason) {
|
||||
super(failReason.getReason());
|
||||
this.failReason = failReason;
|
||||
}
|
||||
|
||||
public WebUserAuthException(FailReason failReason, String additionalInfo) {
|
||||
super(failReason.getReason() + ": " + additionalInfo);
|
||||
this.failReason = failReason;
|
||||
}
|
||||
|
||||
public WebUserAuthException(Throwable cause) {
|
||||
super(FailReason.ERROR.getReason(), cause);
|
||||
this.failReason = FailReason.ERROR;
|
||||
}
|
||||
|
||||
public FailReason getFailReason() {
|
||||
return failReason;
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.api.exceptions.connection;
|
||||
|
||||
/**
|
||||
* Thrown when connection is returned 401 Bad Request.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class BadRequestException extends WebException {
|
||||
|
||||
public BadRequestException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.api.exceptions.connection;
|
||||
|
||||
/**
|
||||
* Thrown when Connection fails to connect to an address.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class ConnectionFailException extends WebException {
|
||||
|
||||
public ConnectionFailException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public ConnectionFailException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.api.exceptions.connection;
|
||||
|
||||
/**
|
||||
* Thrown when Connection gets a 403 response.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class ForbiddenException extends WebFailException {
|
||||
public ForbiddenException(String url) {
|
||||
super("Forbidden: " + url);
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.api.exceptions.connection;
|
||||
|
||||
/**
|
||||
* Thrown when InfoRequest can not connect to the other server.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class GatewayException extends WebException {
|
||||
|
||||
public GatewayException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public GatewayException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public GatewayException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.api.exceptions.connection;
|
||||
|
||||
/**
|
||||
* Thrown when Connection returns 500.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class InternalErrorException extends WebFailException {
|
||||
public InternalErrorException() {
|
||||
super("Internal Error occurred on receiving server");
|
||||
}
|
||||
|
||||
public InternalErrorException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.api.exceptions.connection;
|
||||
|
||||
/**
|
||||
* Thrown when ConnectionSystem can not find any servers to send request to.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class NoServersException extends WebException {
|
||||
|
||||
public NoServersException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public NoServersException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public NoServersException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.api.exceptions.connection;
|
||||
|
||||
/**
|
||||
* Thrown when Connection returns 404, when page is not found.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class NotFoundException extends WebFailException {
|
||||
public NotFoundException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.api.exceptions.connection;
|
||||
|
||||
import com.djrapitops.plan.api.exceptions.database.DBException;
|
||||
|
||||
/**
|
||||
* Thrown when DBException occurs during InfoRequest#placeIntoDatabase.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class TransferDatabaseException extends WebException {
|
||||
|
||||
public TransferDatabaseException(DBException cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.api.exceptions.connection;
|
||||
|
||||
/**
|
||||
* Thrown when Connection gets a 412 response due to ServerUUID not being in the database.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class UnauthorizedServerException extends WebFailException {
|
||||
|
||||
public UnauthorizedServerException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public UnauthorizedServerException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public UnauthorizedServerException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.api.exceptions.connection;
|
||||
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
|
||||
/**
|
||||
* Exception thrown when calling Database#transfer and Database implementation doesn't support it.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class UnsupportedTransferDatabaseException extends WebException {
|
||||
|
||||
public UnsupportedTransferDatabaseException(Database db) {
|
||||
super(db.getName() + " does not support Transfer operations!");
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.api.exceptions.connection;
|
||||
|
||||
/**
|
||||
* Thrown when Connection POST-request fails, general Exception.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class WebException extends Exception {
|
||||
|
||||
public WebException() {
|
||||
}
|
||||
|
||||
public WebException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public WebException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public WebException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.api.exceptions.connection;
|
||||
|
||||
/**
|
||||
* Group of WebExceptions that can be considered a failed connection state on some occasions.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class WebFailException extends WebException {
|
||||
|
||||
public WebFailException() {
|
||||
}
|
||||
|
||||
public WebFailException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public WebFailException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public WebFailException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.api.exceptions.database;
|
||||
|
||||
/**
|
||||
* Thrown when something goes wrong with the Database, generic exception.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class DBException extends Exception {
|
||||
|
||||
public DBException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public DBException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public DBException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.api.exceptions.database;
|
||||
|
||||
/**
|
||||
* Thrown when something goes wrong with {@code Database#init}.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class DBInitException extends FatalDBException {
|
||||
|
||||
public DBInitException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public DBInitException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public DBInitException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
package com.djrapitops.plan.api.exceptions.database;
|
||||
|
||||
public class DBNoDataException extends DBException {
|
||||
|
||||
public DBNoDataException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public DBNoDataException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public DBNoDataException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
package com.djrapitops.plan.api.exceptions.database;
|
||||
|
||||
public class FatalDBException extends DBException {
|
||||
|
||||
public FatalDBException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public FatalDBException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public FatalDBException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
package com.djrapitops.plan.command;
|
||||
|
||||
import com.djrapitops.plan.PlanBungee;
|
||||
import com.djrapitops.plan.command.commands.*;
|
||||
import com.djrapitops.plan.command.commands.manage.ManageConDebugCommand;
|
||||
import com.djrapitops.plan.system.settings.Permissions;
|
||||
import com.djrapitops.plan.system.settings.locale.Locale;
|
||||
import com.djrapitops.plan.system.settings.locale.Msg;
|
||||
import com.djrapitops.plugin.command.CommandType;
|
||||
import com.djrapitops.plugin.command.TreeCommand;
|
||||
import com.djrapitops.plugin.command.defaultcmds.StatusCommand;
|
||||
|
||||
/**
|
||||
* 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, Permissions.MANAGE.getPermission(), "", "planbungee");
|
||||
super.setDefaultCommand("help");
|
||||
super.setColorScheme(plugin.getColorScheme());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] addHelp() {
|
||||
return Locale.get(Msg.CMD_HELP_PLAN).toArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCommands() {
|
||||
add(
|
||||
new ReloadCommand(plugin),
|
||||
new StatusCommand<>(plugin, Permissions.MANAGE.getPermission(), plugin.getColorScheme()),
|
||||
new ListCommand(),
|
||||
new BungeeSetupToggleCommand()
|
||||
);
|
||||
RegisterCommand registerCommand = new RegisterCommand();
|
||||
add(
|
||||
registerCommand,
|
||||
new WebUserCommand(plugin, registerCommand),
|
||||
new NetworkCommand(),
|
||||
new ListServersCommand(plugin),
|
||||
new ManageConDebugCommand()
|
||||
);
|
||||
}
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
package com.djrapitops.plan.command;
|
||||
|
||||
import com.djrapitops.plan.Plan;
|
||||
import com.djrapitops.plan.command.commands.*;
|
||||
import com.djrapitops.plan.system.settings.Permissions;
|
||||
import com.djrapitops.plan.system.settings.Settings;
|
||||
import com.djrapitops.plan.system.settings.locale.Locale;
|
||||
import com.djrapitops.plan.system.settings.locale.Msg;
|
||||
import com.djrapitops.plugin.command.CommandType;
|
||||
import com.djrapitops.plugin.command.TreeCommand;
|
||||
import com.djrapitops.plugin.command.defaultcmds.StatusCommand;
|
||||
|
||||
/**
|
||||
* 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 PlanCommand extends TreeCommand<Plan> {
|
||||
|
||||
public PlanCommand(Plan plugin) {
|
||||
super(plugin, "plan", CommandType.CONSOLE, "", "", "plan");
|
||||
super.setDefaultCommand("inspect");
|
||||
super.setColorScheme(plugin.getColorScheme());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] addHelp() {
|
||||
return Locale.get(Msg.CMD_HELP_PLAN).toArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCommands() {
|
||||
add(
|
||||
new InspectCommand(),
|
||||
new QInspectCommand(plugin),
|
||||
new AnalyzeCommand(),
|
||||
new SearchCommand(),
|
||||
new InfoCommand(plugin),
|
||||
new ReloadCommand(plugin),
|
||||
new ManageCommand(plugin),
|
||||
new StatusCommand<>(plugin, Permissions.MANAGE.getPermission(), plugin.getColorScheme()),
|
||||
new ListCommand()
|
||||
);
|
||||
RegisterCommand registerCommand = new RegisterCommand();
|
||||
add(
|
||||
registerCommand,
|
||||
new WebUserCommand(plugin, registerCommand),
|
||||
new NetworkCommand(),
|
||||
new ListServersCommand(plugin));
|
||||
|
||||
if (Settings.DEV_MODE.isTrue()) {
|
||||
add(new DevCommand());
|
||||
}
|
||||
}
|
||||
}
|
@ -1,121 +0,0 @@
|
||||
package com.djrapitops.plan.command.commands;
|
||||
|
||||
import com.djrapitops.plan.api.exceptions.connection.WebException;
|
||||
import com.djrapitops.plan.api.exceptions.database.DBException;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plan.system.info.InfoSystem;
|
||||
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.processing.Processor;
|
||||
import com.djrapitops.plan.system.settings.Permissions;
|
||||
import com.djrapitops.plan.system.settings.locale.Locale;
|
||||
import com.djrapitops.plan.system.settings.locale.Msg;
|
||||
import com.djrapitops.plan.system.webserver.WebServerSystem;
|
||||
import com.djrapitops.plan.utilities.analysis.Analysis;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
import com.djrapitops.plugin.command.CommandType;
|
||||
import com.djrapitops.plugin.command.CommandUtils;
|
||||
import com.djrapitops.plugin.command.ISender;
|
||||
import com.djrapitops.plugin.command.SubCommand;
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* This SubCommand is used to run the analysis and access the /server link.
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class AnalyzeCommand extends SubCommand {
|
||||
|
||||
public AnalyzeCommand() {
|
||||
super("analyze, analyse, analysis, a",
|
||||
CommandType.CONSOLE,
|
||||
Permissions.ANALYZE.getPermission(),
|
||||
Locale.get(Msg.CMD_USG_ANALYZE).parse(),
|
||||
"[ServerName or ID]");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] addHelp() {
|
||||
return Locale.get(Msg.CMD_HELP_ANALYZE).toArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(ISender sender, String commandLabel, String[] args) {
|
||||
sender.sendMessage(Locale.get(Msg.CMD_INFO_FETCH_DATA).toString());
|
||||
|
||||
Processor.queue(() -> {
|
||||
try {
|
||||
Server server = getServer(args).orElseGet(ServerInfo::getServer);
|
||||
UUID serverUUID = server.getUuid();
|
||||
if (!ServerInfo.getServerUUID().equals(serverUUID) || !Analysis.isAnalysisBeingRun()) {
|
||||
InfoSystem.getInstance().generateAnalysisPage(serverUUID);
|
||||
}
|
||||
sendWebUserNotificationIfNecessary(sender);
|
||||
sendLink(server, sender);
|
||||
} catch (DBException | WebException e) {
|
||||
// TODO Exception handling
|
||||
sender.sendMessage(ChatColor.RED + " Error occurred: " + e.toString());
|
||||
Log.toLog(this.getClass(), e);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
private void sendLink(Server server, ISender sender) {
|
||||
String target = "/server/" + server.getName();
|
||||
String url = ConnectionSystem.getAddress() + target;
|
||||
String message = Locale.get(Msg.CMD_INFO_LINK).toString();
|
||||
sender.sendMessage(Locale.get(Msg.CMD_HEADER_ANALYZE).toString());
|
||||
// Link
|
||||
boolean console = !CommandUtils.isPlayer(sender);
|
||||
if (console) {
|
||||
sender.sendMessage(message + url);
|
||||
} else {
|
||||
sender.sendMessage(message);
|
||||
sender.sendLink(" ", Locale.get(Msg.CMD_INFO_CLICK_ME).toString(), url);
|
||||
}
|
||||
sender.sendMessage(Locale.get(Msg.CMD_CONSTANT_FOOTER).toString());
|
||||
}
|
||||
|
||||
private void sendWebUserNotificationIfNecessary(ISender sender) throws DBException {
|
||||
if (WebServerSystem.getInstance().getWebServer().isAuthRequired() && CommandUtils.isPlayer(sender)) {
|
||||
|
||||
boolean senderHasWebUser = Database.getActive().check().doesWebUserExists(sender.getName());
|
||||
if (!senderHasWebUser) {
|
||||
sender.sendMessage(ChatColor.YELLOW + "[Plan] You might not have a web user, use /plan register <password>");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Optional<Server> getServer(String[] args) throws DBException {
|
||||
if (args.length >= 1 && ConnectionSystem.getInstance().isServerAvailable()) {
|
||||
Map<UUID, Server> bukkitServers = Database.getActive().fetch().getBukkitServers();
|
||||
String serverIdentifier = getGivenIdentifier(args);
|
||||
for (Map.Entry<UUID, Server> entry : bukkitServers.entrySet()) {
|
||||
Server server = entry.getValue();
|
||||
|
||||
if (Integer.toString(server.getId()).equals(serverIdentifier)
|
||||
|| server.getName().equalsIgnoreCase(serverIdentifier)) {
|
||||
return Optional.of(server);
|
||||
}
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private String getGivenIdentifier(String[] args) {
|
||||
StringBuilder idBuilder = new StringBuilder(args[0]);
|
||||
if (args.length > 1) {
|
||||
for (int i = 1; i < args.length; i++) {
|
||||
idBuilder.append(" ").append(args[i]);
|
||||
}
|
||||
}
|
||||
return idBuilder.toString();
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.command.commands;
|
||||
|
||||
import com.djrapitops.plan.system.info.connection.ConnectionSystem;
|
||||
import com.djrapitops.plan.system.settings.Permissions;
|
||||
import com.djrapitops.plugin.command.CommandType;
|
||||
import com.djrapitops.plugin.command.ISender;
|
||||
import com.djrapitops.plugin.command.SubCommand;
|
||||
|
||||
/**
|
||||
* Command for Toggling whether or not BungeeCord accepts set up requests.
|
||||
*
|
||||
* This was added as a security measure against unwanted MySQL snooping.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class BungeeSetupToggleCommand extends SubCommand {
|
||||
|
||||
public BungeeSetupToggleCommand() {
|
||||
super("setup", CommandType.ALL, Permissions.MANAGE.getPermission(), "Toggle Setup mode for Bungee");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(ISender sender, String s, String[] strings) {
|
||||
boolean setupAllowed = ConnectionSystem.isSetupAllowed();
|
||||
ConnectionSystem connectionSystem = ConnectionSystem.getInstance();
|
||||
|
||||
if (setupAllowed) {
|
||||
connectionSystem.setSetupAllowed(false);
|
||||
} else {
|
||||
connectionSystem.setSetupAllowed(true);
|
||||
}
|
||||
String msg = !setupAllowed ? "§aSet-up is now Allowed" : "§cSet-up is now Forbidden";
|
||||
sender.sendMessage(msg);
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.command.commands;
|
||||
|
||||
import com.djrapitops.plan.system.info.connection.ConnectionSystem;
|
||||
import com.djrapitops.plan.system.settings.locale.Locale;
|
||||
import com.djrapitops.plan.system.settings.locale.Msg;
|
||||
import com.djrapitops.plan.utilities.Condition;
|
||||
import com.djrapitops.plugin.command.CommandType;
|
||||
import com.djrapitops.plugin.command.ISender;
|
||||
import com.djrapitops.plugin.command.SubCommand;
|
||||
|
||||
/**
|
||||
* Command used for testing functions that are too difficult to unit test.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class DevCommand extends SubCommand {
|
||||
|
||||
public DevCommand() {
|
||||
super("dev", CommandType.PLAYER_OR_ARGS, "plan.*", "Test Plugin functions not testable with unit tests.", "<feature to test>");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(ISender sender, String cmd, String[] args) {
|
||||
if (!Condition.isTrue(args.length >= 1, Locale.get(Msg.CMD_FAIL_REQ_ONE_ARG).toString(), sender)) {
|
||||
return true;
|
||||
}
|
||||
String feature = args[0];
|
||||
switch (feature) {
|
||||
case "connection":
|
||||
if (!Condition.isTrue(args.length >= 2, Locale.get(Msg.CMD_FAIL_REQ_ONE_ARG).toString(), sender)) {
|
||||
break;
|
||||
}
|
||||
sender.sendMessage("[Plan] No implementation.");
|
||||
break;
|
||||
case "web":
|
||||
ConnectionSystem connectionSystem = ConnectionSystem.getInstance();
|
||||
String accessAddress = connectionSystem.getMainAddress();
|
||||
sender.sendMessage((connectionSystem.isServerAvailable())
|
||||
? "Bungee: " + accessAddress : "Local: " + accessAddress);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
package com.djrapitops.plan.command.commands;
|
||||
|
||||
import com.djrapitops.plan.Plan;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plan.system.settings.Permissions;
|
||||
import com.djrapitops.plan.system.settings.locale.Locale;
|
||||
import com.djrapitops.plan.system.settings.locale.Msg;
|
||||
import com.djrapitops.plan.system.update.VersionCheckSystem;
|
||||
import com.djrapitops.plugin.command.CommandType;
|
||||
import com.djrapitops.plugin.command.ISender;
|
||||
import com.djrapitops.plugin.command.SubCommand;
|
||||
import com.djrapitops.plugin.settings.ColorScheme;
|
||||
|
||||
/**
|
||||
* This SubCommand is used to view the version and the database type in use.
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class InfoCommand extends SubCommand {
|
||||
|
||||
private final Plan plugin;
|
||||
|
||||
public InfoCommand(Plan plugin) {
|
||||
super("info",
|
||||
CommandType.CONSOLE,
|
||||
Permissions.INFO.getPermission(),
|
||||
Locale.get(Msg.CMD_USG_INFO).toString());
|
||||
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(ISender sender, String commandLabel, String[] args) {
|
||||
ColorScheme cs = plugin.getColorScheme();
|
||||
String mColor = cs.getMainColor();
|
||||
String sColor = cs.getSecondaryColor();
|
||||
String tColor = cs.getTertiaryColor();
|
||||
String ball = Locale.get(Msg.CMD_CONSTANT_LIST_BALL).toString();
|
||||
|
||||
String upToDate = VersionCheckSystem.isNewVersionAvailable() ? "Update Available" : "Up to date";
|
||||
String[] messages = {
|
||||
Locale.get(Msg.CMD_HEADER_INFO).toString(),
|
||||
ball + mColor + " Version: " + sColor + plugin.getDescription().getVersion(),
|
||||
ball + mColor + " Up to date: " + sColor + upToDate,
|
||||
ball + mColor + " Active Database: " + tColor + Database.getActive().getConfigName(),
|
||||
Locale.get(Msg.CMD_CONSTANT_FOOTER).toString()
|
||||
};
|
||||
sender.sendMessage(messages);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -1,88 +0,0 @@
|
||||
package com.djrapitops.plan.command.commands;
|
||||
|
||||
import com.djrapitops.plan.api.exceptions.database.DBException;
|
||||
import com.djrapitops.plan.api.exceptions.database.FatalDBException;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plan.system.processing.processors.info.InspectCacheRequestProcessor;
|
||||
import com.djrapitops.plan.system.settings.Permissions;
|
||||
import com.djrapitops.plan.system.settings.locale.Locale;
|
||||
import com.djrapitops.plan.system.settings.locale.Msg;
|
||||
import com.djrapitops.plan.system.webserver.WebServer;
|
||||
import com.djrapitops.plan.utilities.Condition;
|
||||
import com.djrapitops.plan.utilities.MiscUtils;
|
||||
import com.djrapitops.plan.utilities.uuid.UUIDUtility;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
import com.djrapitops.plugin.command.CommandType;
|
||||
import com.djrapitops.plugin.command.CommandUtils;
|
||||
import com.djrapitops.plugin.command.ISender;
|
||||
import com.djrapitops.plugin.command.SubCommand;
|
||||
import com.djrapitops.plugin.task.AbsRunnable;
|
||||
import com.djrapitops.plugin.task.RunnableFactory;
|
||||
import com.djrapitops.plugin.utilities.Verify;
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* This command is used to refresh Inspect page and display link.
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class InspectCommand extends SubCommand {
|
||||
|
||||
public InspectCommand() {
|
||||
super("inspect",
|
||||
CommandType.PLAYER_OR_ARGS,
|
||||
Permissions.INSPECT.getPermission(),
|
||||
Locale.get(Msg.CMD_USG_INSPECT).toString(),
|
||||
"<player>");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] addHelp() {
|
||||
return Locale.get(Msg.CMD_HELP_INSPECT).toArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(ISender sender, String commandLabel, String[] args) {
|
||||
String playerName = MiscUtils.getPlayerName(args, sender);
|
||||
|
||||
runInspectTask(playerName, sender);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void runInspectTask(String playerName, ISender sender) {
|
||||
RunnableFactory.createNew(new AbsRunnable("InspectTask") {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Database activeDB = Database.getActive();
|
||||
UUID uuid = UUIDUtility.getUUIDOf(playerName);
|
||||
if (!Condition.isTrue(Verify.notNull(uuid), Locale.get(Msg.CMD_FAIL_USERNAME_NOT_VALID).toString(), sender)) {
|
||||
return;
|
||||
}
|
||||
if (!Condition.isTrue(activeDB.check().isPlayerRegistered(uuid), Locale.get(Msg.CMD_FAIL_USERNAME_NOT_KNOWN).toString(), sender)) {
|
||||
return;
|
||||
}
|
||||
if (CommandUtils.isPlayer(sender) && WebServer.getInstance().isAuthRequired()) {
|
||||
boolean senderHasWebUser = activeDB.check().doesWebUserExists(sender.getName());
|
||||
|
||||
if (!senderHasWebUser) {
|
||||
sender.sendMessage(ChatColor.YELLOW + "[Plan] You might not have a web user, use /plan register <password>");
|
||||
}
|
||||
}
|
||||
new InspectCacheRequestProcessor(uuid, sender, playerName).queue();
|
||||
} catch (FatalDBException ex) {
|
||||
Log.toLog(this.getClass(), ex);
|
||||
sender.sendMessage(ChatColor.RED + "Fatal database exception occurred: " + ex.getMessage());
|
||||
} catch (DBException ex) {
|
||||
Log.toLog(this.getClass(), ex);
|
||||
sender.sendMessage(ChatColor.YELLOW + "Non-Fatal database exception occurred: " + ex.getMessage());
|
||||
} finally {
|
||||
this.cancel();
|
||||
}
|
||||
}
|
||||
}).runTaskAsynchronously();
|
||||
}
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
package com.djrapitops.plan.command.commands;
|
||||
|
||||
import com.djrapitops.plan.system.info.connection.ConnectionSystem;
|
||||
import com.djrapitops.plan.system.settings.Permissions;
|
||||
import com.djrapitops.plan.system.settings.locale.Locale;
|
||||
import com.djrapitops.plan.system.settings.locale.Msg;
|
||||
import com.djrapitops.plugin.command.CommandType;
|
||||
import com.djrapitops.plugin.command.CommandUtils;
|
||||
import com.djrapitops.plugin.command.ISender;
|
||||
import com.djrapitops.plugin.command.SubCommand;
|
||||
|
||||
/**
|
||||
* Command used to display url to the player list page.
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @since 3.5.2
|
||||
*/
|
||||
public class ListCommand extends SubCommand {
|
||||
|
||||
public ListCommand() {
|
||||
super("list, pl, playerlist, players", CommandType.CONSOLE, Permissions.INSPECT_OTHER.getPermission(), Locale.get(Msg.CMD_USG_LIST).toString(), "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] addHelp() {
|
||||
return Locale.get(Msg.CMD_HELP_LIST).toArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(ISender sender, String commandLabel, String[] args) {
|
||||
|
||||
sendListMsg(sender);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void sendListMsg(ISender sender) {
|
||||
sender.sendMessage(Locale.get(Msg.CMD_CONSTANT_FOOTER).parse());
|
||||
|
||||
// Link
|
||||
String url = ConnectionSystem.getAddress() + "/players/";
|
||||
String message = Locale.get(Msg.CMD_INFO_LINK).toString();
|
||||
boolean console = !CommandUtils.isPlayer(sender);
|
||||
if (console) {
|
||||
sender.sendMessage(message + url);
|
||||
} else {
|
||||
sender.sendMessage(message);
|
||||
sender.sendLink(" ", Locale.get(Msg.CMD_INFO_CLICK_ME).toString(), url);
|
||||
}
|
||||
sender.sendMessage(Locale.get(Msg.CMD_CONSTANT_FOOTER).toString());
|
||||
}
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
package com.djrapitops.plan.command.commands;
|
||||
|
||||
import com.djrapitops.plan.PlanPlugin;
|
||||
import com.djrapitops.plan.api.exceptions.database.DBException;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plan.system.info.server.Server;
|
||||
import com.djrapitops.plan.system.settings.Permissions;
|
||||
import com.djrapitops.plan.system.settings.locale.Locale;
|
||||
import com.djrapitops.plan.system.settings.locale.Msg;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
import com.djrapitops.plugin.command.CommandType;
|
||||
import com.djrapitops.plugin.command.ISender;
|
||||
import com.djrapitops.plugin.command.SubCommand;
|
||||
import com.djrapitops.plugin.settings.ColorScheme;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This SubCommand is used to list all servers found in the database.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class ListServersCommand extends SubCommand {
|
||||
|
||||
private final PlanPlugin plugin;
|
||||
|
||||
public ListServersCommand(PlanPlugin plugin) {
|
||||
super("servers, serverlist, listservers, sl",
|
||||
CommandType.CONSOLE,
|
||||
Permissions.MANAGE.getPermission(),
|
||||
"List servers in the network");
|
||||
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(ISender sender, String commandLabel, String[] args) {
|
||||
ColorScheme colorScheme = plugin.getColorScheme();
|
||||
String mCol = colorScheme.getMainColor();
|
||||
String sCol = colorScheme.getSecondaryColor();
|
||||
String tCol = colorScheme.getTertiaryColor();
|
||||
try {
|
||||
sender.sendMessage(Locale.get(Msg.CMD_CONSTANT_FOOTER).toString() + mCol + " Servers");
|
||||
List<Server> servers = Database.getActive().fetch().getServers();
|
||||
for (Server server : servers) {
|
||||
sender.sendMessage(" " + tCol + server.getId() + sCol + " : " + server.getName() + " : " + server.getWebAddress());
|
||||
}
|
||||
sender.sendMessage(Locale.get(Msg.CMD_CONSTANT_FOOTER).toString());
|
||||
} catch (DBException e) {
|
||||
sender.sendMessage("§cDatabase Exception occurred.");
|
||||
Log.toLog(this.getClass(), e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
package com.djrapitops.plan.command.commands;
|
||||
|
||||
import com.djrapitops.plan.Plan;
|
||||
import com.djrapitops.plan.command.commands.manage.*;
|
||||
import com.djrapitops.plan.system.settings.Permissions;
|
||||
import com.djrapitops.plan.system.settings.locale.Locale;
|
||||
import com.djrapitops.plan.system.settings.locale.Msg;
|
||||
import com.djrapitops.plugin.command.CommandType;
|
||||
import com.djrapitops.plugin.command.TreeCommand;
|
||||
|
||||
/**
|
||||
* This SubCommand is used to manage the the plugin's database and components.
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @since 2.3.0
|
||||
*/
|
||||
public class ManageCommand extends TreeCommand<Plan> {
|
||||
|
||||
public ManageCommand(Plan plugin) {
|
||||
super(plugin, "manage,m", CommandType.CONSOLE, Permissions.MANAGE.getPermission(), Locale.get(Msg.CMD_USG_MANAGE).toString(), "plan m");
|
||||
super.setColorScheme(plugin.getColorScheme());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] addHelp() {
|
||||
return Locale.get(Msg.CMD_HELP_MANAGE).toArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCommands() {
|
||||
add(
|
||||
new ManageMoveCommand(),
|
||||
new ManageHotswapCommand(plugin),
|
||||
new ManageBackupCommand(),
|
||||
new ManageRestoreCommand(plugin),
|
||||
new ManageImportCommand(),
|
||||
new ManageRemoveCommand(),
|
||||
new ManageClearCommand(plugin),
|
||||
new ManageSetupCommand(),
|
||||
new ManageDisableCommand(),
|
||||
new ManageConDebugCommand()
|
||||
);
|
||||
}
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
package com.djrapitops.plan.command.commands;
|
||||
|
||||
import com.djrapitops.plan.system.info.connection.ConnectionSystem;
|
||||
import com.djrapitops.plan.system.settings.Permissions;
|
||||
import com.djrapitops.plan.system.settings.locale.Locale;
|
||||
import com.djrapitops.plan.system.settings.locale.Msg;
|
||||
import com.djrapitops.plugin.command.CommandType;
|
||||
import com.djrapitops.plugin.command.CommandUtils;
|
||||
import com.djrapitops.plugin.command.ISender;
|
||||
import com.djrapitops.plugin.command.SubCommand;
|
||||
|
||||
/**
|
||||
* Command used to display url to the network page.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class NetworkCommand extends SubCommand {
|
||||
|
||||
public NetworkCommand() {
|
||||
super("network, n, netw",
|
||||
CommandType.CONSOLE,
|
||||
Permissions.ANALYZE.getPermission(),
|
||||
"Get the link to the network page");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(ISender sender, String commandLabel, String[] args) {
|
||||
sendNetworkMsg(sender);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void sendNetworkMsg(ISender sender) {
|
||||
sender.sendMessage(Locale.get(Msg.CMD_CONSTANT_FOOTER).parse());
|
||||
|
||||
// Link
|
||||
String url = ConnectionSystem.getAddress() + "/network/";
|
||||
String message = Locale.get(Msg.CMD_INFO_LINK).toString();
|
||||
boolean console = !CommandUtils.isPlayer(sender);
|
||||
if (console) {
|
||||
sender.sendMessage(message + url);
|
||||
} else {
|
||||
sender.sendMessage(message);
|
||||
sender.sendLink(" ", Locale.get(Msg.CMD_INFO_CLICK_ME).toString(), url);
|
||||
}
|
||||
sender.sendMessage(Locale.get(Msg.CMD_CONSTANT_FOOTER).toString());
|
||||
}
|
||||
}
|
@ -1,122 +0,0 @@
|
||||
package com.djrapitops.plan.command.commands;
|
||||
|
||||
import com.djrapitops.plan.PlanPlugin;
|
||||
import com.djrapitops.plan.api.exceptions.database.DBException;
|
||||
import com.djrapitops.plan.data.PlayerProfile;
|
||||
import com.djrapitops.plan.data.calculation.ActivityIndex;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plan.system.settings.Permissions;
|
||||
import com.djrapitops.plan.system.settings.locale.Locale;
|
||||
import com.djrapitops.plan.system.settings.locale.Msg;
|
||||
import com.djrapitops.plan.utilities.Condition;
|
||||
import com.djrapitops.plan.utilities.FormatUtils;
|
||||
import com.djrapitops.plan.utilities.MiscUtils;
|
||||
import com.djrapitops.plan.utilities.uuid.UUIDUtility;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
import com.djrapitops.plugin.command.CommandType;
|
||||
import com.djrapitops.plugin.command.ISender;
|
||||
import com.djrapitops.plugin.command.SubCommand;
|
||||
import com.djrapitops.plugin.settings.ColorScheme;
|
||||
import com.djrapitops.plugin.settings.DefaultMessages;
|
||||
import com.djrapitops.plugin.task.AbsRunnable;
|
||||
import com.djrapitops.plugin.task.RunnableFactory;
|
||||
import com.djrapitops.plugin.utilities.Verify;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* This command is used to cache UserInfo to InspectCache and display the link.
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class QInspectCommand extends SubCommand {
|
||||
|
||||
private final PlanPlugin plugin;
|
||||
|
||||
/**
|
||||
* Class Constructor.
|
||||
*
|
||||
* @param plugin Current instance of Plan
|
||||
*/
|
||||
public QInspectCommand(PlanPlugin plugin) {
|
||||
super("qinspect",
|
||||
CommandType.PLAYER_OR_ARGS,
|
||||
Permissions.QUICK_INSPECT.getPermission(),
|
||||
Locale.get(Msg.CMD_USG_QINSPECT).toString(),
|
||||
"<player>");
|
||||
|
||||
this.plugin = plugin;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] addHelp() {
|
||||
return Locale.get(Msg.CMD_HELP_QINSPECT).toArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(ISender sender, String commandLabel, String[] args) {
|
||||
String playerName = MiscUtils.getPlayerName(args, sender, Permissions.QUICK_INSPECT_OTHER);
|
||||
|
||||
runInspectTask(playerName, sender);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void runInspectTask(String playerName, ISender sender) {
|
||||
RunnableFactory.createNew(new AbsRunnable("InspectTask") {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
UUID uuid = UUIDUtility.getUUIDOf(playerName);
|
||||
if (!Condition.isTrue(Verify.notNull(uuid), Locale.get(Msg.CMD_FAIL_USERNAME_NOT_VALID).toString(), sender)) {
|
||||
return;
|
||||
}
|
||||
Database database = Database.getActive();
|
||||
if (!Condition.isTrue(database.check().isPlayerRegistered(uuid), Locale.get(Msg.CMD_FAIL_USERNAME_NOT_KNOWN).toString(), sender)) {
|
||||
return;
|
||||
}
|
||||
|
||||
PlayerProfile playerProfile = database.fetch().getPlayerProfile(uuid);
|
||||
|
||||
sendMsgs(sender, playerProfile);
|
||||
|
||||
} catch (DBException ex) {
|
||||
Log.toLog(this.getClass(), ex);
|
||||
} finally {
|
||||
this.cancel();
|
||||
}
|
||||
}
|
||||
}).runTaskAsynchronously();
|
||||
}
|
||||
|
||||
private void sendMsgs(ISender sender, PlayerProfile profile) {
|
||||
long now = MiscUtils.getTime();
|
||||
|
||||
ColorScheme colorScheme = plugin.getColorScheme();
|
||||
|
||||
String colM = colorScheme.getMainColor();
|
||||
String colS = colorScheme.getSecondaryColor();
|
||||
String colT = colorScheme.getTertiaryColor();
|
||||
|
||||
String ball = DefaultMessages.BALL.parse();
|
||||
|
||||
sender.sendMessage(Locale.get(Msg.CMD_HEADER_INSPECT).toString() + ": " + colT + profile.getName());
|
||||
|
||||
ActivityIndex activityIndex = profile.getActivityIndex(now);
|
||||
|
||||
sender.sendMessage(colT + ball + " " + colM + " Activity Index: " + colS + activityIndex.getFormattedValue() + " | " + activityIndex.getColor());
|
||||
sender.sendMessage(colT + ball + " " + colM + " Registered: " + colS + FormatUtils.formatTimeStampYear(profile.getRegistered()));
|
||||
sender.sendMessage(colT + ball + " " + colM + " Last Seen: " + colS + FormatUtils.formatTimeStampYear(profile.getLastSeen()));
|
||||
sender.sendMessage(colT + ball + " " + colM + " Logged in from: " + colS + profile.getMostRecentGeoInfo().getGeolocation());
|
||||
sender.sendMessage(colT + ball + " " + colM + " Playtime: " + colS + FormatUtils.formatTimeAmount(profile.getTotalPlaytime()));
|
||||
sender.sendMessage(colT + ball + " " + colM + " Longest Session: " + colS + FormatUtils.formatTimeAmount(profile.getLongestSession(0, now)));
|
||||
sender.sendMessage(colT + ball + " " + colM + " Times Kicked: " + colS + profile.getTimesKicked());
|
||||
sender.sendMessage("");
|
||||
sender.sendMessage(colT + ball + " " + colM + " Player Kills : " + colS + profile.getPlayerKills().count());
|
||||
sender.sendMessage(colT + ball + " " + colM + " Mob Kills : " + colS + profile.getMobKillCount());
|
||||
sender.sendMessage(colT + ball + " " + colM + " Deaths : " + colS + profile.getDeathCount());
|
||||
|
||||
sender.sendMessage(Locale.get(Msg.CMD_CONSTANT_FOOTER).toString());
|
||||
}
|
||||
}
|
@ -1,142 +0,0 @@
|
||||
package com.djrapitops.plan.command.commands;
|
||||
|
||||
import com.djrapitops.plan.data.WebUser;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plan.system.settings.Permissions;
|
||||
import com.djrapitops.plan.system.settings.locale.Locale;
|
||||
import com.djrapitops.plan.system.settings.locale.Msg;
|
||||
import com.djrapitops.plan.utilities.Condition;
|
||||
import com.djrapitops.plan.utilities.PassEncryptUtil;
|
||||
import com.djrapitops.plugin.api.Check;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
import com.djrapitops.plugin.command.CommandType;
|
||||
import com.djrapitops.plugin.command.CommandUtils;
|
||||
import com.djrapitops.plugin.command.ISender;
|
||||
import com.djrapitops.plugin.command.SubCommand;
|
||||
import com.djrapitops.plugin.task.AbsRunnable;
|
||||
import com.djrapitops.plugin.task.RunnableFactory;
|
||||
|
||||
/**
|
||||
* Command for registering web users.
|
||||
* <p>
|
||||
* Registers a new WebUser to the database.
|
||||
* <p>
|
||||
* No permission required for self registration. (Super constructor string is empty).
|
||||
* {@code Permissions.MANAGE_WEB} required for registering other users.
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @since 3.5.2
|
||||
*/
|
||||
public class RegisterCommand extends SubCommand {
|
||||
|
||||
public RegisterCommand() {
|
||||
super("register",
|
||||
CommandType.PLAYER_OR_ARGS,
|
||||
"", // No Permission Requirement
|
||||
Locale.get(Msg.CMD_USG_WEB_REGISTER).toString(),
|
||||
"<password> [name] [access lvl]");
|
||||
if (Check.isBukkitAvailable()) {
|
||||
setupFilter();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] addHelp() {
|
||||
return Locale.get(Msg.CMD_HELP_WEB_REGISTER).toArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(ISender sender, String commandLabel, String[] args) {
|
||||
String notEnoughArgsMsg = Locale.get(Msg.CMD_FAIL_REQ_ARGS).parse("(3) " + super.getArguments());
|
||||
String hashErrorMsg = "§cPassword hash error.";
|
||||
String permLvlErrorMsg = "§cIncorrect perm level, not a number: ";
|
||||
try {
|
||||
if (CommandUtils.isPlayer(sender)) {
|
||||
Log.info(sender.getName() + " issued WebUser register command.");
|
||||
playerRegister(args, sender);
|
||||
} else {
|
||||
consoleRegister(args, sender, notEnoughArgsMsg);
|
||||
}
|
||||
} catch (PassEncryptUtil.CannotPerformOperationException e) {
|
||||
Log.toLog(this.getClass().getSimpleName(), e);
|
||||
sender.sendMessage(hashErrorMsg);
|
||||
} catch (NumberFormatException e) {
|
||||
sender.sendMessage(permLvlErrorMsg + args[2]);
|
||||
} catch (Exception e) {
|
||||
Log.toLog(this.getClass().getSimpleName(), e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void consoleRegister(String[] args, ISender sender, String notEnoughArgsMsg) throws PassEncryptUtil.CannotPerformOperationException {
|
||||
if (Condition.isTrue(args.length >= 3, notEnoughArgsMsg, sender)) {
|
||||
int permLevel;
|
||||
permLevel = Integer.parseInt(args[2]);
|
||||
String passHash = PassEncryptUtil.createHash(args[0]);
|
||||
registerUser(new WebUser(args[1], passHash, permLevel), sender);
|
||||
}
|
||||
}
|
||||
|
||||
private void playerRegister(String[] args, ISender sender) throws PassEncryptUtil.CannotPerformOperationException {
|
||||
final String notEnoughArgsMsg = Locale.get(Msg.CMD_FAIL_REQ_ARGS).parse("(1 or 3) " + super.getArguments());
|
||||
boolean registerSenderAsUser = args.length == 1;
|
||||
if (registerSenderAsUser) {
|
||||
String user = sender.getName();
|
||||
String pass = PassEncryptUtil.createHash(args[0]);
|
||||
int permLvl = getPermissionLevel(sender);
|
||||
registerUser(new WebUser(user, pass, permLvl), sender);
|
||||
} else if (sender.hasPermission(Permissions.MANAGE_WEB.getPermission())) {
|
||||
consoleRegister(args, sender, notEnoughArgsMsg);
|
||||
} else {
|
||||
sender.sendMessage(Locale.get(Msg.CMD_FAIL_NO_PERMISSION).parse());
|
||||
}
|
||||
}
|
||||
|
||||
private int getPermissionLevel(ISender sender) {
|
||||
final String permAnalyze = Permissions.ANALYZE.getPerm();
|
||||
final String permInspectOther = Permissions.INSPECT_OTHER.getPerm();
|
||||
final String permInspect = Permissions.INSPECT.getPerm();
|
||||
if (sender.hasPermission(permAnalyze)) {
|
||||
return 0;
|
||||
}
|
||||
if (sender.hasPermission(permInspectOther)) {
|
||||
return 1;
|
||||
}
|
||||
if (sender.hasPermission(permInspect)) {
|
||||
return 2;
|
||||
}
|
||||
return 100;
|
||||
}
|
||||
|
||||
private void registerUser(WebUser webUser, ISender sender) {
|
||||
RunnableFactory.createNew(new AbsRunnable("Register WebUser Task") {
|
||||
@Override
|
||||
public void run() {
|
||||
final String existsMsg = "§cUser Already Exists!";
|
||||
final String userName = webUser.getName();
|
||||
final String successMsg = "§aAdded a new user (" + userName + ") successfully!";
|
||||
try {
|
||||
Database database = Database.getActive();
|
||||
boolean userExists = database.check().doesWebUserExists(userName);
|
||||
if (!Condition.isTrue(!userExists, existsMsg, sender)) {
|
||||
return;
|
||||
}
|
||||
database.save().webUser(webUser);
|
||||
sender.sendMessage(successMsg);
|
||||
Log.info("Registered new user: " + userName + " Perm level: " + webUser.getPermLevel());
|
||||
} catch (Exception e) {
|
||||
Log.toLog(this.getClass(), e);
|
||||
} finally {
|
||||
this.cancel();
|
||||
}
|
||||
}
|
||||
}).runTaskAsynchronously();
|
||||
}
|
||||
|
||||
/**
|
||||
* Setups the command console output filter
|
||||
*/
|
||||
private void setupFilter() {
|
||||
new RegisterCommandFilter().registerFilter();
|
||||
}
|
||||
}
|
@ -1,84 +0,0 @@
|
||||
package com.djrapitops.plan.command.commands;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Marker;
|
||||
import org.apache.logging.log4j.core.LogEvent;
|
||||
import org.apache.logging.log4j.core.Logger;
|
||||
import org.apache.logging.log4j.core.filter.AbstractFilter;
|
||||
import org.apache.logging.log4j.message.Message;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Filters out WebUser registration command logs.
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @since 3.5.2
|
||||
*/
|
||||
public class RegisterCommandFilter extends AbstractFilter {
|
||||
|
||||
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
|
||||
public Result filter(LogEvent event) {
|
||||
if (event == null) {
|
||||
return Result.NEUTRAL;
|
||||
}
|
||||
|
||||
return validateMessage(event.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result filter(Logger logger, Level level, Marker marker, Message msg, Throwable t) {
|
||||
return validateMessage(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result filter(Logger logger, Level level, Marker marker, String msg, Object... params) {
|
||||
return validateMessage(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result filter(Logger logger, Level level, Marker marker, Object msg, Throwable t) {
|
||||
if (msg == null) {
|
||||
return Result.NEUTRAL;
|
||||
}
|
||||
|
||||
return validateMessage(msg.toString());
|
||||
}
|
||||
|
||||
private Result validateMessage(Message message) {
|
||||
if (message == null) {
|
||||
return Result.NEUTRAL;
|
||||
}
|
||||
|
||||
return validateMessage(message.getFormattedMessage());
|
||||
}
|
||||
|
||||
private Result validateMessage(String message) {
|
||||
if (message == null) {
|
||||
return Result.NEUTRAL;
|
||||
}
|
||||
|
||||
return commandShouldBeCensored(message)
|
||||
? Result.DENY
|
||||
: Result.NEUTRAL;
|
||||
}
|
||||
|
||||
private boolean commandShouldBeCensored(String message) {
|
||||
return message != null
|
||||
&& (message.toLowerCase().contains("issued server command:")
|
||||
&& shouldBeCensored(message));
|
||||
}
|
||||
|
||||
private boolean shouldBeCensored(String message) {
|
||||
return message != null && censoredCommands.stream().anyMatch(message::contains);
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
package com.djrapitops.plan.command.commands;
|
||||
|
||||
import com.djrapitops.plan.PlanPlugin;
|
||||
import com.djrapitops.plan.system.settings.Permissions;
|
||||
import com.djrapitops.plan.system.settings.locale.Locale;
|
||||
import com.djrapitops.plan.system.settings.locale.Msg;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
import com.djrapitops.plugin.command.CommandType;
|
||||
import com.djrapitops.plugin.command.ISender;
|
||||
import com.djrapitops.plugin.command.SubCommand;
|
||||
|
||||
/**
|
||||
* This SubCommand is used to reload the plugin.
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class ReloadCommand extends SubCommand {
|
||||
|
||||
private final PlanPlugin plugin;
|
||||
|
||||
public ReloadCommand(PlanPlugin plugin) {
|
||||
super("reload",
|
||||
CommandType.CONSOLE,
|
||||
Permissions.MANAGE.getPermission(),
|
||||
Locale.get(Msg.CMD_USG_RELOAD).toString());
|
||||
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(ISender sender, String commandLabel, String[] args) {
|
||||
try {
|
||||
plugin.reloadPlugin(true);
|
||||
} catch (Exception e) {
|
||||
Log.toLog(this.getClass(), e);
|
||||
sender.sendMessage("§cSomething went wrong during reload of the plugin, a restart is recommended.");
|
||||
}
|
||||
sender.sendMessage(Locale.get(Msg.CMD_INFO_RELOAD_COMPLETE).toString());
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
package com.djrapitops.plan.command.commands;
|
||||
|
||||
import com.djrapitops.plan.system.settings.Permissions;
|
||||
import com.djrapitops.plan.system.settings.locale.Locale;
|
||||
import com.djrapitops.plan.system.settings.locale.Msg;
|
||||
import com.djrapitops.plan.utilities.Condition;
|
||||
import com.djrapitops.plan.utilities.MiscUtils;
|
||||
import com.djrapitops.plugin.command.CommandType;
|
||||
import com.djrapitops.plugin.command.ISender;
|
||||
import com.djrapitops.plugin.command.SubCommand;
|
||||
import com.djrapitops.plugin.task.AbsRunnable;
|
||||
import com.djrapitops.plugin.task.RunnableFactory;
|
||||
import com.djrapitops.plugin.utilities.FormatUtils;
|
||||
import com.djrapitops.plugin.utilities.Verify;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This SubCommand is used to search for a user.
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class SearchCommand extends SubCommand {
|
||||
|
||||
public SearchCommand() {
|
||||
super("search",
|
||||
CommandType.PLAYER_OR_ARGS,
|
||||
Permissions.SEARCH.getPermission(),
|
||||
Locale.get(Msg.CMD_USG_SEARCH).toString(),
|
||||
"<part of playername>");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] addHelp() {
|
||||
return Locale.get(Msg.CMD_HELP_SEARCH).toArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(ISender sender, String commandLabel, String[] args) {
|
||||
if (!Condition.isTrue(args.length >= 1, Locale.get(Msg.CMD_FAIL_REQ_ONE_ARG).toString(), sender)) {
|
||||
return true;
|
||||
}
|
||||
sender.sendMessage(Locale.get(Msg.CMD_INFO_SEARCHING).toString());
|
||||
|
||||
runSearchTask(args, sender);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void runSearchTask(String[] args, ISender sender) {
|
||||
RunnableFactory.createNew(new AbsRunnable("SearchTask: " + Arrays.toString(args)) {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
List<String> names = MiscUtils.getMatchingPlayerNames(args[0]);
|
||||
|
||||
boolean empty = Verify.isEmpty(names);
|
||||
|
||||
sender.sendMessage(Locale.get(Msg.CMD_HEADER_SEARCH) + args[0] + " (" + (empty ? 0 : names.size()) + ")");
|
||||
// Results
|
||||
if (empty) {
|
||||
sender.sendMessage(Locale.get(Msg.CMD_INFO_NO_RESULTS).parse(Arrays.toString(args)));
|
||||
} else {
|
||||
sender.sendMessage(Locale.get(Msg.CMD_INFO_RESULTS).toString() + FormatUtils.collectionToStringNoBrackets(names));
|
||||
}
|
||||
|
||||
sender.sendMessage(Locale.get(Msg.CMD_CONSTANT_FOOTER).toString());
|
||||
} finally {
|
||||
this.cancel();
|
||||
}
|
||||
}
|
||||
}).runTaskAsynchronously();
|
||||
}
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
package com.djrapitops.plan.command.commands;
|
||||
|
||||
import com.djrapitops.plan.Plan;
|
||||
import com.djrapitops.plan.PlanBungee;
|
||||
import com.djrapitops.plan.PlanPlugin;
|
||||
import com.djrapitops.plan.command.commands.webuser.WebCheckCommand;
|
||||
import com.djrapitops.plan.command.commands.webuser.WebDeleteCommand;
|
||||
import com.djrapitops.plan.command.commands.webuser.WebLevelCommand;
|
||||
import com.djrapitops.plan.command.commands.webuser.WebListUsersCommand;
|
||||
import com.djrapitops.plan.system.settings.Permissions;
|
||||
import com.djrapitops.plan.system.settings.locale.Locale;
|
||||
import com.djrapitops.plan.system.settings.locale.Msg;
|
||||
import com.djrapitops.plugin.command.CommandType;
|
||||
import com.djrapitops.plugin.command.TreeCommand;
|
||||
|
||||
/**
|
||||
* Web subcommand used to manage Web users.
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @since 3.5.2
|
||||
*/
|
||||
public class WebUserCommand extends TreeCommand<PlanPlugin> {
|
||||
|
||||
public WebUserCommand(Plan plugin, RegisterCommand register) {
|
||||
super(plugin, "webuser, web",
|
||||
CommandType.CONSOLE,
|
||||
Permissions.MANAGE_WEB.getPerm(),
|
||||
Locale.get(Msg.CMD_USG_WEB).toString(),
|
||||
"plan web");
|
||||
super.setColorScheme(plugin.getColorScheme());
|
||||
add(register);
|
||||
}
|
||||
|
||||
public WebUserCommand(PlanBungee plugin, RegisterCommand register) {
|
||||
super(plugin, "webuser, web",
|
||||
CommandType.CONSOLE,
|
||||
Permissions.MANAGE_WEB.getPerm(),
|
||||
Locale.get(Msg.CMD_USG_WEB).toString(),
|
||||
"planbungee web");
|
||||
add(register);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] addHelp() {
|
||||
return Locale.get(Msg.CMD_HELP_WEB).toArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCommands() {
|
||||
add(
|
||||
new WebLevelCommand(plugin),
|
||||
new WebListUsersCommand(plugin),
|
||||
new WebCheckCommand(),
|
||||
new WebDeleteCommand()
|
||||
);
|
||||
}
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
package com.djrapitops.plan.command.commands.manage;
|
||||
|
||||
import com.djrapitops.plan.api.exceptions.database.DBInitException;
|
||||
import com.djrapitops.plan.system.database.DBSystem;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plan.system.settings.Permissions;
|
||||
import com.djrapitops.plan.system.settings.locale.Locale;
|
||||
import com.djrapitops.plan.system.settings.locale.Msg;
|
||||
import com.djrapitops.plan.utilities.Condition;
|
||||
import com.djrapitops.plan.utilities.ManageUtils;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
import com.djrapitops.plugin.command.CommandType;
|
||||
import com.djrapitops.plugin.command.ISender;
|
||||
import com.djrapitops.plugin.command.SubCommand;
|
||||
import com.djrapitops.plugin.task.AbsRunnable;
|
||||
import com.djrapitops.plugin.task.RunnableFactory;
|
||||
import com.djrapitops.plugin.utilities.Verify;
|
||||
|
||||
/**
|
||||
* This manage subcommand is used to backup a database to a .db file.
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @since 2.3.0
|
||||
*/
|
||||
public class ManageBackupCommand extends SubCommand {
|
||||
|
||||
public ManageBackupCommand() {
|
||||
super("backup",
|
||||
CommandType.CONSOLE,
|
||||
Permissions.MANAGE.getPermission(),
|
||||
Locale.get(Msg.CMD_USG_MANAGE_BACKUP).toString(),
|
||||
"<DB>");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(ISender sender, String commandLabel, String[] args) {
|
||||
try {
|
||||
|
||||
if (!Condition.isTrue(args.length >= 1, Locale.get(Msg.CMD_FAIL_REQ_ARGS).parse(this.getArguments()), sender)) {
|
||||
return true;
|
||||
}
|
||||
String dbName = args[0].toLowerCase();
|
||||
boolean isCorrectDB = "sqlite".equals(dbName) || "mysql".equals(dbName);
|
||||
if (!Condition.isTrue(isCorrectDB, Locale.get(Msg.MANAGE_FAIL_INCORRECT_DB) + dbName, sender)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final Database database = DBSystem.getActiveDatabaseByName(dbName);
|
||||
|
||||
// If DB is null return
|
||||
if (!Condition.isTrue(Verify.notNull(database), Locale.get(Msg.MANAGE_FAIL_FAULTY_DB).toString(), sender)) {
|
||||
Log.error(dbName + " was null!");
|
||||
return true;
|
||||
}
|
||||
Log.debug("Backup", "Start");
|
||||
runBackupTask(sender, args, database);
|
||||
} catch (DBInitException | NullPointerException e) {
|
||||
sender.sendMessage(Locale.get(Msg.MANAGE_FAIL_FAULTY_DB).toString());
|
||||
} finally {
|
||||
Log.logDebug("Backup");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void runBackupTask(ISender sender, String[] args, final Database database) {
|
||||
RunnableFactory.createNew(new AbsRunnable("BackupTask") {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_START).parse());
|
||||
ManageUtils.backup(args[0], database);
|
||||
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_COPY_SUCCESS).toString());
|
||||
} catch (Exception e) {
|
||||
Log.toLog(this.getClass(), e);
|
||||
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_FAIL).toString());
|
||||
} finally {
|
||||
this.cancel();
|
||||
}
|
||||
}
|
||||
}).runTaskAsynchronously();
|
||||
}
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
package com.djrapitops.plan.command.commands.manage;
|
||||
|
||||
import com.djrapitops.plan.Plan;
|
||||
import com.djrapitops.plan.api.exceptions.database.DBException;
|
||||
import com.djrapitops.plan.api.exceptions.database.DBInitException;
|
||||
import com.djrapitops.plan.api.exceptions.database.FatalDBException;
|
||||
import com.djrapitops.plan.data.container.Session;
|
||||
import com.djrapitops.plan.system.cache.SessionCache;
|
||||
import com.djrapitops.plan.system.database.DBSystem;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plan.system.settings.Permissions;
|
||||
import com.djrapitops.plan.system.settings.locale.Locale;
|
||||
import com.djrapitops.plan.system.settings.locale.Msg;
|
||||
import com.djrapitops.plan.utilities.Condition;
|
||||
import com.djrapitops.plan.utilities.MiscUtils;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
import com.djrapitops.plugin.command.CommandType;
|
||||
import com.djrapitops.plugin.command.ISender;
|
||||
import com.djrapitops.plugin.command.SubCommand;
|
||||
import com.djrapitops.plugin.task.AbsRunnable;
|
||||
import com.djrapitops.plugin.task.RunnableFactory;
|
||||
import com.djrapitops.plugin.utilities.Verify;
|
||||
|
||||
/**
|
||||
* This manage SubCommand is used to clear a database of all data.
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @since 2.3.0
|
||||
*/
|
||||
public class ManageClearCommand extends SubCommand {
|
||||
|
||||
private final Plan plugin;
|
||||
|
||||
public ManageClearCommand(Plan plugin) {
|
||||
super("clear",
|
||||
CommandType.PLAYER_OR_ARGS,
|
||||
Permissions.MANAGE.getPermission(),
|
||||
Locale.get(Msg.CMD_USG_MANAGE_CLEAR).toString(),
|
||||
"<DB> [-a]");
|
||||
|
||||
this.plugin = plugin;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] addHelp() {
|
||||
return Locale.get(Msg.CMD_HELP_MANAGE_CLEAR).toArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(ISender sender, String commandLabel, String[] args) {
|
||||
if (!Condition.isTrue(args.length >= 1, Locale.get(Msg.CMD_FAIL_REQ_ONE_ARG).toString(), sender)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
String dbName = args[0].toLowerCase();
|
||||
boolean isCorrectDB = "sqlite".equals(dbName) || "mysql".equals(dbName);
|
||||
|
||||
if (!Condition.isTrue(isCorrectDB, Locale.get(Msg.MANAGE_FAIL_INCORRECT_DB) + dbName, sender)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!Condition.isTrue(Verify.contains("-a", args), Locale.get(Msg.MANAGE_FAIL_CONFIRM).parse(Locale.get(Msg.MANAGE_NOTIFY_REMOVE).parse(args[0])), sender)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
Database database = DBSystem.getActiveDatabaseByName(dbName);
|
||||
runClearTask(sender, database);
|
||||
} catch (DBInitException e) {
|
||||
sender.sendMessage(Locale.get(Msg.MANAGE_FAIL_FAULTY_DB).toString());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void runClearTask(ISender sender, Database database) {
|
||||
RunnableFactory.createNew(new AbsRunnable("DBClearTask") {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_START).parse());
|
||||
|
||||
database.remove().everything();
|
||||
|
||||
long now = MiscUtils.getTime();
|
||||
SessionCache.clear();
|
||||
plugin.getServer().getOnlinePlayers().forEach(
|
||||
player -> SessionCache.getInstance().cacheSession(player.getUniqueId(),
|
||||
new Session(now, player.getWorld().getName(), player.getGameMode().name()))
|
||||
);
|
||||
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_CLEAR_SUCCESS).toString());
|
||||
} catch (FatalDBException e) {
|
||||
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_FAIL).toString()
|
||||
+ " Error was fatal, so all information may not have been removed.");
|
||||
Log.toLog(this.getClass(), e);
|
||||
} catch (DBException e) {
|
||||
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_FAIL).toString());
|
||||
Log.toLog(this.getClass(), e);
|
||||
} finally {
|
||||
this.cancel();
|
||||
}
|
||||
}
|
||||
}).runTaskAsynchronously();
|
||||
}
|
||||
}
|
@ -1,127 +0,0 @@
|
||||
package com.djrapitops.plan.command.commands.manage;
|
||||
|
||||
import com.djrapitops.plan.PlanPlugin;
|
||||
import com.djrapitops.plan.api.exceptions.connection.*;
|
||||
import com.djrapitops.plan.api.exceptions.database.DBException;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plan.system.info.InfoSystem;
|
||||
import com.djrapitops.plan.system.info.request.CheckConnectionRequest;
|
||||
import com.djrapitops.plan.system.info.server.Server;
|
||||
import com.djrapitops.plan.system.info.server.ServerInfo;
|
||||
import com.djrapitops.plan.system.processing.Processor;
|
||||
import com.djrapitops.plan.system.settings.Permissions;
|
||||
import com.djrapitops.plan.system.settings.locale.Locale;
|
||||
import com.djrapitops.plan.system.settings.locale.Msg;
|
||||
import com.djrapitops.plan.system.webserver.WebServerSystem;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
import com.djrapitops.plugin.command.CommandType;
|
||||
import com.djrapitops.plugin.command.ISender;
|
||||
import com.djrapitops.plugin.command.SubCommand;
|
||||
import com.djrapitops.plugin.settings.ColorScheme;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* This manage SubCommand is used to request settings from Bungee so that connection can be established.
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @since 2.3.0
|
||||
*/
|
||||
public class ManageConDebugCommand extends SubCommand {
|
||||
|
||||
private final ColorScheme cs;
|
||||
|
||||
public ManageConDebugCommand() {
|
||||
super("con",
|
||||
CommandType.ALL,
|
||||
Permissions.MANAGE.getPermission(),
|
||||
"Debug Bukkit-Bungee Connections",
|
||||
"");
|
||||
|
||||
cs = PlanPlugin.getInstance().getColorScheme();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] addHelp() {
|
||||
return Locale.get(Msg.CMD_HELP_MANAGE_HOTSWAP).toArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(ISender sender, String commandLabel, String[] args) {
|
||||
if (!WebServerSystem.isWebServerEnabled()) {
|
||||
sender.sendMessage("§cWebServer is not enabled on this server.");
|
||||
return true;
|
||||
}
|
||||
|
||||
Processor.queue(() -> {
|
||||
testServers(sender);
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void testServers(ISender sender) {
|
||||
try {
|
||||
List<Server> servers = Database.getActive().fetch().getServers();
|
||||
|
||||
String accessAddress = WebServerSystem.getInstance().getWebServer().getAccessAddress();
|
||||
UUID thisServer = ServerInfo.getServerUUID();
|
||||
for (Server server : servers) {
|
||||
if (thisServer.equals(server.getUuid())) {
|
||||
continue;
|
||||
}
|
||||
testServer(sender, accessAddress, server);
|
||||
}
|
||||
|
||||
} catch (DBException e) {
|
||||
Log.toLog(this.getClass().getName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void testServer(ISender sender, String accessAddress, Server server) {
|
||||
String address = server.getWebAddress().toLowerCase();
|
||||
boolean usingHttps = address.startsWith("https");
|
||||
boolean local = address.contains("localhost")
|
||||
|| address.startsWith("https://:")
|
||||
|| address.startsWith("http://:")
|
||||
|| address.contains("127.0.0.1");
|
||||
|
||||
try {
|
||||
|
||||
InfoSystem.getInstance().getConnectionSystem().sendInfoRequest(new CheckConnectionRequest(accessAddress), server);
|
||||
sender.sendMessage(getMsgFor(address, usingHttps, local, true, true));
|
||||
|
||||
} catch (ForbiddenException | BadRequestException | InternalErrorException e) {
|
||||
sender.sendMessage(getMsgFor(address, usingHttps, local, false, false));
|
||||
sender.sendMessage("§eOdd Exception: " + e.getClass().getSimpleName());
|
||||
} catch (UnauthorizedServerException e) {
|
||||
sender.sendMessage(getMsgFor(address, usingHttps, local, true, false));
|
||||
sender.sendMessage("§eFail reason: Unauthorized. Server might be using different database.");
|
||||
} catch (ConnectionFailException e) {
|
||||
sender.sendMessage(getMsgFor(address, usingHttps, local, false, false));
|
||||
sender.sendMessage("§eFail reason: " + e.getCause().getClass().getSimpleName() + " " + e.getCause().getMessage());
|
||||
if (!local) {
|
||||
sender.sendMessage("§eNon-local address, check that port is open");
|
||||
}
|
||||
} catch (GatewayException e) {
|
||||
sender.sendMessage(getMsgFor(address, usingHttps, local, true, false));
|
||||
} catch (NotFoundException e) {
|
||||
sender.sendMessage(getMsgFor(address, usingHttps, local, false, false));
|
||||
sender.sendMessage("§eFail reason: Older Plan version on receiving server");
|
||||
} catch (WebException e) {
|
||||
sender.sendMessage(getMsgFor(address, usingHttps, local, false, false));
|
||||
sender.sendMessage("§eOdd Exception: " + e.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
private String getMsgFor(String address, boolean usingHttps, boolean local, boolean successTo, boolean successFrom) {
|
||||
String tCol = cs.getTertiaryColor();
|
||||
String sCol = cs.getSecondaryColor();
|
||||
return tCol + address + sCol + ": "
|
||||
+ (usingHttps ? "HTTPS" : "HTTP") + " : "
|
||||
+ (local ? "Local" : "External") + " : "
|
||||
+ "To:" + (successTo ? "§aOK" : "§cFail") + sCol + " : "
|
||||
+ "From:" + (successFrom ? "§aOK" : "§cFail");
|
||||
}
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
package com.djrapitops.plan.command.commands.manage;
|
||||
|
||||
import com.djrapitops.plan.system.listeners.bukkit.PlayerOnlineListener;
|
||||
import com.djrapitops.plan.system.settings.Permissions;
|
||||
import com.djrapitops.plan.system.settings.locale.Locale;
|
||||
import com.djrapitops.plan.system.settings.locale.Msg;
|
||||
import com.djrapitops.plan.utilities.Condition;
|
||||
import com.djrapitops.plugin.command.CommandType;
|
||||
import com.djrapitops.plugin.command.ISender;
|
||||
import com.djrapitops.plugin.command.SubCommand;
|
||||
|
||||
/**
|
||||
* This manage SubCommand is used to disable some features of the plugin temporarily.
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @since 4.0.4
|
||||
*/
|
||||
public class ManageDisableCommand extends SubCommand {
|
||||
/**
|
||||
* Class Constructor.
|
||||
*/
|
||||
public ManageDisableCommand() {
|
||||
super("disable",
|
||||
CommandType.PLAYER_OR_ARGS,
|
||||
Permissions.MANAGE.getPermission(),
|
||||
"Used to disable some features of the Plugin temporarily",
|
||||
"<feature>");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(ISender sender, String commandLabel, String[] args) {
|
||||
if (!Condition.isTrue(args.length >= 1, Locale.get(Msg.CMD_FAIL_REQ_ARGS).parse(this.getArguments()), sender)) {
|
||||
return true;
|
||||
}
|
||||
switch (args[0].toLowerCase()) {
|
||||
case "kickcount":
|
||||
PlayerOnlineListener.setCountKicks(false);
|
||||
sender.sendMessage("§aDisabled Kick Counting temporarily until next plugin reload.");
|
||||
break;
|
||||
default:
|
||||
sender.sendMessage("§eDefine a feature to disable! (currently supports only kickCount)");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,84 +0,0 @@
|
||||
package com.djrapitops.plan.command.commands.manage;
|
||||
|
||||
import com.djrapitops.plan.Plan;
|
||||
import com.djrapitops.plan.system.database.DBSystem;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plan.system.settings.Permissions;
|
||||
import com.djrapitops.plan.system.settings.Settings;
|
||||
import com.djrapitops.plan.system.settings.locale.Locale;
|
||||
import com.djrapitops.plan.system.settings.locale.Msg;
|
||||
import com.djrapitops.plan.utilities.Condition;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
import com.djrapitops.plugin.command.CommandType;
|
||||
import com.djrapitops.plugin.command.ISender;
|
||||
import com.djrapitops.plugin.command.SubCommand;
|
||||
import com.djrapitops.plugin.utilities.Verify;
|
||||
|
||||
/**
|
||||
* This manage SubCommand is used to swap to a different database and reload the
|
||||
* plugin if the connection to the new database can be established.
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @since 2.3.0
|
||||
*/
|
||||
public class ManageHotswapCommand extends SubCommand {
|
||||
|
||||
private final Plan plugin;
|
||||
|
||||
public ManageHotswapCommand(Plan plugin) {
|
||||
super("hotswap",
|
||||
CommandType.PLAYER_OR_ARGS,
|
||||
Permissions.MANAGE.getPermission(),
|
||||
Locale.get(Msg.CMD_USG_MANAGE_HOTSWAP).toString(),
|
||||
"<DB>");
|
||||
|
||||
this.plugin = plugin;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] addHelp() {
|
||||
return Locale.get(Msg.CMD_HELP_MANAGE_HOTSWAP).toArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(ISender sender, String commandLabel, String[] args) {
|
||||
if (!Condition.isTrue(args.length >= 1, Locale.get(Msg.CMD_FAIL_REQ_ONE_ARG).toString(), sender)) {
|
||||
return true;
|
||||
}
|
||||
String dbName = args[0].toLowerCase();
|
||||
boolean isCorrectDB = "sqlite".equals(dbName) || "mysql".equals(dbName);
|
||||
|
||||
if (!Condition.isTrue(isCorrectDB, Locale.get(Msg.MANAGE_FAIL_INCORRECT_DB) + dbName, sender)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Condition.isTrue(dbName.equals(Database.getActive().getConfigName()), Locale.get(Msg.MANAGE_FAIL_SAME_DB).toString(), sender)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
final Database database = DBSystem.getActiveDatabaseByName(dbName);
|
||||
|
||||
// If DB is null return
|
||||
if (!Condition.isTrue(Verify.notNull(database), Locale.get(Msg.MANAGE_FAIL_FAULTY_DB).toString(), sender)) {
|
||||
Log.error(dbName + " was null!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!database.isOpen()) {
|
||||
return true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.toLog(this.getClass(), e);
|
||||
sender.sendMessage(Locale.get(Msg.MANAGE_FAIL_FAULTY_DB).toString());
|
||||
return true;
|
||||
}
|
||||
|
||||
Settings.DB_TYPE.set(dbName);
|
||||
|
||||
Settings.save();
|
||||
plugin.reloadPlugin(true);
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
package com.djrapitops.plan.command.commands.manage;
|
||||
|
||||
import com.djrapitops.plan.system.processing.importing.ImporterManager;
|
||||
import com.djrapitops.plan.system.settings.Permissions;
|
||||
import com.djrapitops.plan.system.settings.locale.Locale;
|
||||
import com.djrapitops.plan.system.settings.locale.Msg;
|
||||
import com.djrapitops.plan.utilities.Condition;
|
||||
import com.djrapitops.plugin.command.CommandType;
|
||||
import com.djrapitops.plugin.command.ISender;
|
||||
import com.djrapitops.plugin.command.SubCommand;
|
||||
import com.djrapitops.plugin.task.AbsRunnable;
|
||||
import com.djrapitops.plugin.task.RunnableFactory;
|
||||
|
||||
/**
|
||||
* This manage SubCommand is used to import data from 3rd party plugins.
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @since 2.3.0
|
||||
*/
|
||||
public class ManageImportCommand extends SubCommand {
|
||||
|
||||
public ManageImportCommand() {
|
||||
super("import",
|
||||
CommandType.CONSOLE,
|
||||
Permissions.MANAGE.getPermission(),
|
||||
Locale.get(Msg.CMD_USG_MANAGE_IMPORT).toString(),
|
||||
"<plugin>/list [import args]");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] addHelp() {
|
||||
return Locale.get(Msg.CMD_HELP_MANAGE_IMPORT).toArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(ISender sender, String commandLabel, String[] args) {
|
||||
if (!Condition.isTrue(args.length >= 1, Locale.get(Msg.CMD_FAIL_REQ_ONE_ARG) + " " + this.getArguments(), sender)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
runImport("offlineimporter");
|
||||
return true;
|
||||
}
|
||||
|
||||
private void runImport(String importer) {
|
||||
RunnableFactory.createNew("Import", new AbsRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
ImporterManager.getImporter(importer).processImport();
|
||||
} finally {
|
||||
this.cancel();
|
||||
}
|
||||
}
|
||||
}).runTaskAsynchronously();
|
||||
}
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
package com.djrapitops.plan.command.commands.manage;
|
||||
|
||||
import com.djrapitops.plan.system.database.DBSystem;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plan.system.settings.Permissions;
|
||||
import com.djrapitops.plan.system.settings.locale.Locale;
|
||||
import com.djrapitops.plan.system.settings.locale.Msg;
|
||||
import com.djrapitops.plan.utilities.Condition;
|
||||
import com.djrapitops.plan.utilities.ManageUtils;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
import com.djrapitops.plugin.command.CommandType;
|
||||
import com.djrapitops.plugin.command.ISender;
|
||||
import com.djrapitops.plugin.command.SubCommand;
|
||||
import com.djrapitops.plugin.task.AbsRunnable;
|
||||
import com.djrapitops.plugin.task.RunnableFactory;
|
||||
import com.djrapitops.plugin.utilities.Verify;
|
||||
|
||||
/**
|
||||
* This manage SubCommand is used to move all data from one database to another.
|
||||
* <p>
|
||||
* Destination database will be cleared.
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @since 2.3.0
|
||||
*/
|
||||
public class ManageMoveCommand extends SubCommand {
|
||||
|
||||
public ManageMoveCommand() {
|
||||
super("move",
|
||||
CommandType.PLAYER_OR_ARGS,
|
||||
Permissions.MANAGE.getPermission(),
|
||||
Locale.get(Msg.CMD_USG_MANAGE_MOVE).toString(),
|
||||
"<fromDB> <toDB> [-a]");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(ISender sender, String commandLabel, String[] args) {
|
||||
if (!Condition.isTrue(args.length >= 2, Locale.get(Msg.CMD_FAIL_REQ_ARGS).parse(this.getArguments()), sender)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
String fromDB = args[0].toLowerCase();
|
||||
boolean isCorrectDB = "sqlite".equals(fromDB) || "mysql".equals(fromDB);
|
||||
|
||||
if (!Condition.isTrue(isCorrectDB, Locale.get(Msg.MANAGE_FAIL_INCORRECT_DB) + fromDB, sender)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
String toDB = args[1].toLowerCase();
|
||||
isCorrectDB = "sqlite".equals(toDB) || "mysql".equals(toDB);
|
||||
|
||||
if (!Condition.isTrue(isCorrectDB, Locale.get(Msg.MANAGE_FAIL_INCORRECT_DB) + toDB, sender)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!Condition.isTrue(!Verify.equalsIgnoreCase(fromDB, toDB), Locale.get(Msg.MANAGE_FAIL_SAME_DB).toString(), sender)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!Condition.isTrue(Verify.contains("-a", args), Locale.get(Msg.MANAGE_FAIL_CONFIRM).parse(Locale.get(Msg.MANAGE_NOTIFY_REMOVE).parse(args[1])), sender)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
final Database fromDatabase = DBSystem.getActiveDatabaseByName(fromDB);
|
||||
final Database toDatabase = DBSystem.getActiveDatabaseByName(toDB);
|
||||
|
||||
runMoveTask(fromDatabase, toDatabase, sender);
|
||||
} catch (Exception e) {
|
||||
sender.sendMessage(Locale.get(Msg.MANAGE_FAIL_FAULTY_DB).toString());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void runMoveTask(final Database fromDatabase, final Database toDatabase, ISender sender) {
|
||||
RunnableFactory.createNew(new AbsRunnable("DBMoveTask") {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_START).parse());
|
||||
|
||||
ManageUtils.clearAndCopy(toDatabase, fromDatabase);
|
||||
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_MOVE_SUCCESS).toString());
|
||||
boolean movedToCurrentDatabase = Verify.equalsIgnoreCase(toDatabase.getConfigName(), Database.getActive().getConfigName());
|
||||
Condition.isTrue(!movedToCurrentDatabase, Locale.get(Msg.MANAGE_INFO_CONFIG_REMINDER).toString(), sender);
|
||||
} catch (Exception e) {
|
||||
Log.toLog(this.getClass(), e);
|
||||
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_FAIL).toString());
|
||||
} finally {
|
||||
this.cancel();
|
||||
}
|
||||
}
|
||||
}).runTaskAsynchronously();
|
||||
}
|
||||
}
|
@ -1,101 +0,0 @@
|
||||
package com.djrapitops.plan.command.commands.manage;
|
||||
|
||||
import com.djrapitops.plan.api.exceptions.database.DBException;
|
||||
import com.djrapitops.plan.data.container.Session;
|
||||
import com.djrapitops.plan.system.cache.SessionCache;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plan.system.settings.Permissions;
|
||||
import com.djrapitops.plan.system.settings.locale.Locale;
|
||||
import com.djrapitops.plan.system.settings.locale.Msg;
|
||||
import com.djrapitops.plan.utilities.Condition;
|
||||
import com.djrapitops.plan.utilities.MiscUtils;
|
||||
import com.djrapitops.plan.utilities.uuid.UUIDUtility;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
import com.djrapitops.plugin.command.CommandType;
|
||||
import com.djrapitops.plugin.command.ISender;
|
||||
import com.djrapitops.plugin.command.SubCommand;
|
||||
import com.djrapitops.plugin.task.AbsRunnable;
|
||||
import com.djrapitops.plugin.task.RunnableFactory;
|
||||
import com.djrapitops.plugin.utilities.Verify;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.bukkit.Bukkit.getPlayer;
|
||||
|
||||
/**
|
||||
* This manage subcommand is used to remove a single player's data from the
|
||||
* database.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class ManageRemoveCommand extends SubCommand {
|
||||
|
||||
public ManageRemoveCommand() {
|
||||
super("remove",
|
||||
CommandType.PLAYER_OR_ARGS,
|
||||
Permissions.MANAGE.getPermission(),
|
||||
Locale.get(Msg.CMD_USG_MANAGE_REMOVE).toString(),
|
||||
"<player> [-a]");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] addHelp() {
|
||||
return Locale.get(Msg.CMD_HELP_MANAGE_REMOVE).toArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(ISender sender, String commandLabel, String[] args) {
|
||||
if (!Condition.isTrue(args.length >= 1, Locale.get(Msg.CMD_FAIL_REQ_ONE_ARG).toString(), sender)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
String playerName = MiscUtils.getPlayerName(args, sender, Permissions.MANAGE);
|
||||
|
||||
runRemoveTask(playerName, sender, args);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void runRemoveTask(String playerName, ISender sender, String[] args) {
|
||||
RunnableFactory.createNew(new AbsRunnable("DBRemoveTask " + playerName) {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
UUID uuid = UUIDUtility.getUUIDOf(playerName);
|
||||
String message = Locale.get(Msg.CMD_FAIL_USERNAME_NOT_VALID).toString();
|
||||
|
||||
if (!Condition.isTrue(Verify.notNull(uuid), message, sender)) {
|
||||
return;
|
||||
}
|
||||
|
||||
message = Locale.get(Msg.CMD_FAIL_USERNAME_NOT_KNOWN).toString();
|
||||
Database database = Database.getActive();
|
||||
if (!Condition.isTrue(database.check().isPlayerRegistered(uuid), message, sender)) {
|
||||
return;
|
||||
}
|
||||
|
||||
message = Locale.get(Msg.MANAGE_FAIL_CONFIRM).parse(Locale.get(Msg.MANAGE_NOTIFY_REMOVE).parse(Database.getActive().getConfigName()));
|
||||
if (!Condition.isTrue(Verify.contains("-a", args), message, sender)) {
|
||||
return;
|
||||
}
|
||||
|
||||
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_START).parse());
|
||||
|
||||
database.remove().player(uuid);
|
||||
|
||||
Player player = getPlayer(uuid);
|
||||
if (player != null) {
|
||||
SessionCache.getActiveSessions().remove(uuid);
|
||||
SessionCache.getInstance().cacheSession(uuid, new Session(MiscUtils.getTime(), player.getWorld().getName(), player.getGameMode().name()));
|
||||
}
|
||||
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_REMOVE_SUCCESS).parse(playerName, Database.getActive().getConfigName()));
|
||||
} catch (DBException e) {
|
||||
Log.toLog(this.getClass(), e);
|
||||
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_FAIL).toString());
|
||||
} finally {
|
||||
this.cancel();
|
||||
}
|
||||
}
|
||||
}).runTaskAsynchronously();
|
||||
}
|
||||
}
|
@ -1,103 +0,0 @@
|
||||
package com.djrapitops.plan.command.commands.manage;
|
||||
|
||||
import com.djrapitops.plan.Plan;
|
||||
import com.djrapitops.plan.system.database.DBSystem;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plan.system.database.databases.sql.SQLiteDB;
|
||||
import com.djrapitops.plan.system.settings.Permissions;
|
||||
import com.djrapitops.plan.system.settings.locale.Locale;
|
||||
import com.djrapitops.plan.system.settings.locale.Msg;
|
||||
import com.djrapitops.plan.utilities.Condition;
|
||||
import com.djrapitops.plan.utilities.ManageUtils;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
import com.djrapitops.plugin.command.CommandType;
|
||||
import com.djrapitops.plugin.command.ISender;
|
||||
import com.djrapitops.plugin.command.SubCommand;
|
||||
import com.djrapitops.plugin.task.AbsRunnable;
|
||||
import com.djrapitops.plugin.task.RunnableFactory;
|
||||
import com.djrapitops.plugin.utilities.Verify;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* This manage SubCommand is used to restore a backup.db file in the
|
||||
* /plugins/Plan folder.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class ManageRestoreCommand extends SubCommand {
|
||||
|
||||
private final Plan plugin;
|
||||
|
||||
public ManageRestoreCommand(Plan plugin) {
|
||||
super("restore",
|
||||
CommandType.CONSOLE,
|
||||
Permissions.MANAGE.getPermission(),
|
||||
Locale.get(Msg.CMD_USG_MANAGE_RESTORE).toString(),
|
||||
"<Filename.db> <dbTo> [-a]");
|
||||
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(ISender sender, String commandLabel, String[] args) {
|
||||
if (!Condition.isTrue(args.length >= 2, Locale.get(Msg.CMD_FAIL_REQ_ARGS).parse(this.getArguments()), sender)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
String db = args[1].toLowerCase();
|
||||
boolean isCorrectDB = "sqlite".equals(db) || "mysql".equals(db);
|
||||
|
||||
if (!Condition.isTrue(isCorrectDB, Locale.get(Msg.MANAGE_FAIL_INCORRECT_DB) + db, sender)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!Condition.isTrue(Verify.contains("-a", args), Locale.get(Msg.MANAGE_FAIL_CONFIRM).parse(Locale.get(Msg.MANAGE_NOTIFY_REWRITE).parse(args[1])), sender)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
final Database database = DBSystem.getActiveDatabaseByName(db);
|
||||
|
||||
runRestoreTask(args, sender, database);
|
||||
} catch (Exception e) {
|
||||
sender.sendMessage(Locale.get(Msg.MANAGE_FAIL_FAULTY_DB).toString());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void runRestoreTask(String[] args, ISender sender, final Database database) {
|
||||
RunnableFactory.createNew(new AbsRunnable("RestoreTask") {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
String backupDBName = args[0];
|
||||
boolean containsDBFileExtension = backupDBName.endsWith(".db");
|
||||
|
||||
File backupDBFile = new File(plugin.getDataFolder(), backupDBName + (containsDBFileExtension ? "" : ".db"));
|
||||
if (!Condition.isTrue(Verify.exists(backupDBFile), Locale.get(Msg.MANAGE_FAIL_FILE_NOT_FOUND) + " " + args[0], sender)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (containsDBFileExtension) {
|
||||
backupDBName = backupDBName.substring(0, backupDBName.length() - 3);
|
||||
}
|
||||
|
||||
SQLiteDB backupDB = new SQLiteDB(backupDBName);
|
||||
backupDB.init();
|
||||
|
||||
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_START).parse());
|
||||
|
||||
ManageUtils.clearAndCopy(database, backupDB);
|
||||
|
||||
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_COPY_SUCCESS).toString());
|
||||
} catch (Exception e) {
|
||||
Log.toLog(this.getClass(), e);
|
||||
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_FAIL).toString());
|
||||
} finally {
|
||||
this.cancel();
|
||||
}
|
||||
}
|
||||
}).runTaskAsynchronously();
|
||||
}
|
||||
}
|
@ -1,88 +0,0 @@
|
||||
package com.djrapitops.plan.command.commands.manage;
|
||||
|
||||
import com.djrapitops.plan.api.exceptions.connection.*;
|
||||
import com.djrapitops.plan.system.info.InfoSystem;
|
||||
import com.djrapitops.plan.system.processing.Processor;
|
||||
import com.djrapitops.plan.system.settings.Permissions;
|
||||
import com.djrapitops.plan.system.settings.Settings;
|
||||
import com.djrapitops.plan.system.settings.locale.Locale;
|
||||
import com.djrapitops.plan.system.settings.locale.Msg;
|
||||
import com.djrapitops.plan.system.webserver.WebServerSystem;
|
||||
import com.djrapitops.plan.utilities.Condition;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
import com.djrapitops.plugin.command.CommandType;
|
||||
import com.djrapitops.plugin.command.ISender;
|
||||
import com.djrapitops.plugin.command.SubCommand;
|
||||
|
||||
/**
|
||||
* This manage SubCommand is used to request settings from Bungee so that connection can be established.
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @since 2.3.0
|
||||
*/
|
||||
public class ManageSetupCommand extends SubCommand {
|
||||
|
||||
public ManageSetupCommand() {
|
||||
super("setup",
|
||||
CommandType.PLAYER_OR_ARGS,
|
||||
Permissions.MANAGE.getPermission(),
|
||||
"Set-Up Bungee WebServer connection",
|
||||
"<Bungee WebServer address>");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] addHelp() {
|
||||
return Locale.get(Msg.CMD_HELP_MANAGE_HOTSWAP).toArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(ISender sender, String commandLabel, String[] args) {
|
||||
if (!Condition.isTrue(args.length >= 1, Locale.get(Msg.CMD_FAIL_REQ_ONE_ARG).toString(), sender)) {
|
||||
return true;
|
||||
}
|
||||
if (!WebServerSystem.isWebServerEnabled()) {
|
||||
sender.sendMessage("§cWebServer is not enabled on this server! Make sure it enables on boot!");
|
||||
return true;
|
||||
}
|
||||
String address = args[0].toLowerCase();
|
||||
if (!address.startsWith("http") || address.endsWith("://")) {
|
||||
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("/")) {
|
||||
address = address.substring(0, address.length() - 1);
|
||||
}
|
||||
|
||||
requestSetup(sender, address);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void requestSetup(ISender sender, String address) {
|
||||
Processor.queue(() -> {
|
||||
try {
|
||||
Settings.BUNGEE_OVERRIDE_STANDALONE_MODE.set(false);
|
||||
Settings.BUNGEE_COPY_CONFIG.set(true);
|
||||
|
||||
InfoSystem.getInstance().requestSetUp(address);
|
||||
|
||||
sender.sendMessage("§aConnection successful, Plan may restart in a few seconds..");
|
||||
} catch (ForbiddenException e) {
|
||||
sender.sendMessage("§eConnection succeeded, but Bungee has set-up mode disabled - use '/planbungee setup' to enable it.");
|
||||
} catch (BadRequestException e) {
|
||||
sender.sendMessage("§eConnection succeeded, but Receiving server was a Bukkit server. Use Bungee address instead.");
|
||||
} catch (UnauthorizedServerException e) {
|
||||
sender.sendMessage("§eConnection succeeded, but Receiving server didn't authorize this server. Contact Discord for support");
|
||||
} catch (ConnectionFailException e) {
|
||||
sender.sendMessage("§eConnection failed: " + e.getMessage());
|
||||
} catch (InternalErrorException e) {
|
||||
sender.sendMessage("§eConnection succeeded. " + e.getMessage() + ", check possible ErrorLog on receiving server's debug page.");
|
||||
} catch (GatewayException e) {
|
||||
sender.sendMessage("§eConnection succeeded, but Bungee failed to connect to this server. Use Connection debug commands for more.");
|
||||
} catch (WebException e) {
|
||||
Log.toLog(this.getClass(), e);
|
||||
sender.sendMessage("§cConnection to Bungee WebServer failed: More info in the error log.");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
package com.djrapitops.plan.command.commands.webuser;
|
||||
|
||||
import com.djrapitops.plan.data.WebUser;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plan.system.settings.Permissions;
|
||||
import com.djrapitops.plan.system.settings.locale.Locale;
|
||||
import com.djrapitops.plan.system.settings.locale.Msg;
|
||||
import com.djrapitops.plan.utilities.Condition;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
import com.djrapitops.plugin.command.CommandType;
|
||||
import com.djrapitops.plugin.command.ISender;
|
||||
import com.djrapitops.plugin.command.SubCommand;
|
||||
import com.djrapitops.plugin.task.AbsRunnable;
|
||||
import com.djrapitops.plugin.task.RunnableFactory;
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
/**
|
||||
* Subcommand for checking WebUser permission level.
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @since 3.5.2
|
||||
*/
|
||||
public class WebCheckCommand extends SubCommand {
|
||||
|
||||
public WebCheckCommand() {
|
||||
super("check",
|
||||
CommandType.PLAYER_OR_ARGS,
|
||||
Permissions.MANAGE_WEB.getPerm(),
|
||||
Locale.get(Msg.CMD_USG_WEB_CHECK).toString(),
|
||||
"<username>");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(ISender sender, String commandLabel, String[] args) {
|
||||
if (!Condition.isTrue(args.length >= 1, Locale.get(Msg.CMD_FAIL_REQ_ONE_ARG).parse() + " <username>", sender)) {
|
||||
return true;
|
||||
}
|
||||
Database database = Database.getActive();
|
||||
String user = args[0];
|
||||
|
||||
RunnableFactory.createNew(new AbsRunnable("Webuser Check Task: " + user) {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
if (!Condition.isTrue(database.check().doesWebUserExists(user), ChatColor.RED + "[Plan] User Doesn't exist.", sender)) {
|
||||
return;
|
||||
}
|
||||
WebUser info = database.fetch().getWebUser(user);
|
||||
sender.sendMessage(info.getName() + ": Permission level: " + info.getPermLevel());
|
||||
} catch (Exception ex) {
|
||||
Log.toLog(this.getClass(), ex);
|
||||
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_FAIL).parse());
|
||||
} finally {
|
||||
this.cancel();
|
||||
}
|
||||
}
|
||||
}).runTaskAsynchronously();
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
package com.djrapitops.plan.command.commands.webuser;
|
||||
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plan.system.settings.Permissions;
|
||||
import com.djrapitops.plan.system.settings.locale.Locale;
|
||||
import com.djrapitops.plan.system.settings.locale.Msg;
|
||||
import com.djrapitops.plan.utilities.Condition;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
import com.djrapitops.plugin.command.CommandType;
|
||||
import com.djrapitops.plugin.command.ISender;
|
||||
import com.djrapitops.plugin.command.SubCommand;
|
||||
import com.djrapitops.plugin.task.AbsRunnable;
|
||||
import com.djrapitops.plugin.task.RunnableFactory;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
|
||||
/**
|
||||
* Subcommand for deleting a WebUser.
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @since 3.5.2
|
||||
*/
|
||||
public class WebDeleteCommand extends SubCommand {
|
||||
|
||||
public WebDeleteCommand() {
|
||||
super("delete, remove",
|
||||
CommandType.PLAYER_OR_ARGS,
|
||||
Permissions.MANAGE_WEB.getPerm(),
|
||||
Locale.get(Msg.CMD_USG_WEB_DELETE).toString(),
|
||||
"<username>");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(ISender sender, String commandLabel, String[] args) {
|
||||
if (!Condition.isTrue(args.length >= 1, Locale.get(Msg.CMD_FAIL_REQ_ONE_ARG).parse() + " <username>", sender)) {
|
||||
return true;
|
||||
}
|
||||
Database database = Database.getActive();
|
||||
String user = args[0];
|
||||
|
||||
RunnableFactory.createNew(new AbsRunnable("Webuser Delete Task: " + user) {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
if (!Condition.isTrue(database.check().doesWebUserExists(user), ChatColor.RED + "[Plan] User Doesn't exist.", sender)) {
|
||||
return;
|
||||
}
|
||||
database.remove().webUser(user);
|
||||
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_SUCCESS).parse());
|
||||
} catch (Exception ex) {
|
||||
Log.toLog(this.getClass(), ex);
|
||||
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_FAIL).parse());
|
||||
} finally {
|
||||
this.cancel();
|
||||
}
|
||||
}
|
||||
}).runTaskAsynchronously();
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
package com.djrapitops.plan.command.commands.webuser;
|
||||
|
||||
import com.djrapitops.plan.PlanPlugin;
|
||||
import com.djrapitops.plan.system.settings.Permissions;
|
||||
import com.djrapitops.plan.system.settings.locale.Locale;
|
||||
import com.djrapitops.plan.system.settings.locale.Msg;
|
||||
import com.djrapitops.plugin.command.CommandType;
|
||||
import com.djrapitops.plugin.command.ISender;
|
||||
import com.djrapitops.plugin.command.SubCommand;
|
||||
import com.djrapitops.plugin.settings.ColorScheme;
|
||||
|
||||
/**
|
||||
* Subcommand for info about permission levels.
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @since 3.5.2
|
||||
*/
|
||||
public class WebLevelCommand extends SubCommand {
|
||||
|
||||
private final PlanPlugin plugin;
|
||||
|
||||
public WebLevelCommand(PlanPlugin plugin) {
|
||||
super("level",
|
||||
CommandType.CONSOLE,
|
||||
Permissions.MANAGE_WEB.getPerm(),
|
||||
Locale.get(Msg.CMD_USG_WEB_LEVEL).toString());
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(ISender sender, String commandLabel, String[] args) {
|
||||
ColorScheme cs = plugin.getColorScheme();
|
||||
String sCol = cs.getSecondaryColor();
|
||||
String cmdBall = Locale.get(Msg.CMD_CONSTANT_LIST_BALL).parse();
|
||||
String cmdFooter = Locale.get(Msg.CMD_CONSTANT_FOOTER).parse();
|
||||
|
||||
String[] messages = new String[]{
|
||||
cmdFooter,
|
||||
cmdBall + sCol + "0: Access all pages",
|
||||
cmdBall + sCol + "1: Access '/players' and all inspect pages",
|
||||
cmdBall + sCol + "2: Access inspect page with the same username as the webuser",
|
||||
cmdBall + sCol + "3+: No permissions",
|
||||
cmdFooter
|
||||
};
|
||||
|
||||
sender.sendMessage(messages);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
package com.djrapitops.plan.command.commands.webuser;
|
||||
|
||||
import com.djrapitops.plan.PlanPlugin;
|
||||
import com.djrapitops.plan.data.WebUser;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plan.system.settings.Permissions;
|
||||
import com.djrapitops.plan.system.settings.locale.Locale;
|
||||
import com.djrapitops.plan.system.settings.locale.Msg;
|
||||
import com.djrapitops.plan.utilities.comparators.WebUserComparator;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
import com.djrapitops.plugin.command.CommandType;
|
||||
import com.djrapitops.plugin.command.ISender;
|
||||
import com.djrapitops.plugin.command.SubCommand;
|
||||
import com.djrapitops.plugin.settings.ColorScheme;
|
||||
import com.djrapitops.plugin.task.AbsRunnable;
|
||||
import com.djrapitops.plugin.task.RunnableFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Subcommand for checking WebUser list.
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @since 3.5.2
|
||||
*/
|
||||
public class WebListUsersCommand extends SubCommand {
|
||||
|
||||
private final PlanPlugin plugin;
|
||||
|
||||
public WebListUsersCommand(PlanPlugin plugin) {
|
||||
super("list", CommandType.CONSOLE, Permissions.MANAGE_WEB.getPerm(), "List registered web users & permission levels.");
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(ISender sender, String commandLabel, String[] args) {
|
||||
RunnableFactory.createNew(new AbsRunnable("Webuser List Task") {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
ColorScheme cs = plugin.getColorScheme();
|
||||
String mCol = cs.getMainColor();
|
||||
List<WebUser> users = Database.getActive().fetch().getWebUsers();
|
||||
users.sort(new WebUserComparator());
|
||||
sender.sendMessage(Locale.get(Msg.CMD_CONSTANT_FOOTER).parse() + mCol + " WebUsers (" + users.size() + ")");
|
||||
for (WebUser user : users) {
|
||||
sender.sendMessage(" " + user.getPermLevel() + " : " + user.getName());
|
||||
}
|
||||
sender.sendMessage(Locale.get(Msg.CMD_CONSTANT_FOOTER).parse());
|
||||
} catch (Exception ex) {
|
||||
Log.toLog(this.getClass(), ex);
|
||||
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_FAIL).parse());
|
||||
} finally {
|
||||
this.cancel();
|
||||
}
|
||||
}
|
||||
}).runTaskAsynchronously();
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.data;
|
||||
|
||||
import org.apache.commons.lang3.text.WordUtils;
|
||||
|
||||
/**
|
||||
* IDs of various actions
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public enum Actions {
|
||||
UNKNOWN(-1),
|
||||
FIRST_SESSION(1),
|
||||
FIRST_LOGOUT(2),
|
||||
NEW_NICKNAME(3),
|
||||
KILLED(-2), // Not stored in ActionsTable.
|
||||
;
|
||||
|
||||
private final int id;
|
||||
|
||||
Actions(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public static Actions getById(int id) {
|
||||
for (Actions a : values()) {
|
||||
if (a.getId() == id) {
|
||||
return a;
|
||||
}
|
||||
}
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return WordUtils.capitalizeFully(name(), '_').replace('_', ' ');
|
||||
}
|
||||
}
|
@ -1,522 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.data;
|
||||
|
||||
import com.djrapitops.plan.data.calculation.ActivityIndex;
|
||||
import com.djrapitops.plan.data.container.Action;
|
||||
import com.djrapitops.plan.data.container.GeoInfo;
|
||||
import com.djrapitops.plan.data.container.PlayerKill;
|
||||
import com.djrapitops.plan.data.container.Session;
|
||||
import com.djrapitops.plan.data.time.WorldTimes;
|
||||
import com.djrapitops.plan.system.info.server.ServerInfo;
|
||||
import com.djrapitops.plan.utilities.MiscUtils;
|
||||
import com.djrapitops.plan.utilities.comparators.ActionComparator;
|
||||
import com.djrapitops.plan.utilities.comparators.GeoInfoComparator;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Data container object for a single player.
|
||||
* <p>
|
||||
* Created to streamline analysis and to make it easier to understand.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class PlayerProfile implements OfflinePlayer {
|
||||
|
||||
// Identification
|
||||
private final UUID uuid;
|
||||
private final String name;
|
||||
|
||||
// Basic information
|
||||
private final long registered;
|
||||
private Map<UUID, Long> registeredMap;
|
||||
private Set<UUID> bannedOnServers;
|
||||
private Set<UUID> oppedOnServers;
|
||||
private int timesKicked;
|
||||
|
||||
// Activity related information
|
||||
private Map<UUID, List<Session>> sessions;
|
||||
private List<Action> actions;
|
||||
private Map<UUID, WorldTimes> worldTimesMap;
|
||||
|
||||
// Extra information
|
||||
private Map<UUID, List<String>> nicknames;
|
||||
private List<GeoInfo> geoInformation;
|
||||
|
||||
// Plugin data
|
||||
private Map<String, String> pluginReplaceMap;
|
||||
|
||||
// Value that requires lot of processing
|
||||
private Map<Long, ActivityIndex> activityIndexCache;
|
||||
|
||||
public PlayerProfile(UUID uuid, String name, long registered) {
|
||||
this.uuid = uuid;
|
||||
this.name = name;
|
||||
this.registered = registered;
|
||||
registeredMap = new HashMap<>();
|
||||
|
||||
bannedOnServers = new HashSet<>();
|
||||
oppedOnServers = new HashSet<>();
|
||||
|
||||
sessions = new HashMap<>();
|
||||
actions = new ArrayList<>();
|
||||
worldTimesMap = new HashMap<>();
|
||||
|
||||
nicknames = new HashMap<>();
|
||||
geoInformation = new ArrayList<>();
|
||||
|
||||
pluginReplaceMap = new HashMap<>();
|
||||
activityIndexCache = new HashMap<>();
|
||||
}
|
||||
|
||||
public static long getPlaytime(Stream<Session> s) {
|
||||
return s.mapToLong(Session::getLength).sum();
|
||||
}
|
||||
|
||||
public static long getLongestSession(Stream<Session> s) {
|
||||
OptionalLong longestSession = s.mapToLong(Session::getLength).max();
|
||||
if (longestSession.isPresent()) {
|
||||
return longestSession.getAsLong();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static long getSessionMedian(Stream<Session> s) {
|
||||
List<Long> sessionLenghts = s.map(Session::getLength)
|
||||
.sorted()
|
||||
.collect(Collectors.toList());
|
||||
if (sessionLenghts.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
return sessionLenghts.get(sessionLenghts.size() / 2);
|
||||
}
|
||||
|
||||
public static long getSessionAverage(Stream<Session> s) {
|
||||
OptionalDouble average = s.map(Session::getLength)
|
||||
.mapToLong(i -> i)
|
||||
.average();
|
||||
if (average.isPresent()) {
|
||||
return (long) average.getAsDouble();
|
||||
}
|
||||
return 0L;
|
||||
}
|
||||
|
||||
public static Stream<PlayerKill> getPlayerKills(Stream<Session> s) {
|
||||
return s.map(Session::getPlayerKills)
|
||||
.flatMap(Collection::stream);
|
||||
}
|
||||
|
||||
public static long getDeathCount(Stream<Session> s) {
|
||||
return s.mapToLong(Session::getDeaths)
|
||||
.sum();
|
||||
}
|
||||
|
||||
public static long getMobKillCount(Stream<Session> s) {
|
||||
return s.mapToLong(Session::getMobKills)
|
||||
.sum();
|
||||
}
|
||||
|
||||
// Calculating Getters
|
||||
public ActivityIndex getActivityIndex(long date) {
|
||||
return activityIndexCache.computeIfAbsent(date, dateValue -> new ActivityIndex(this, dateValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the total world times of the player.
|
||||
*
|
||||
* @return returns the WorldTimes in the "null" key of the map.
|
||||
*/
|
||||
public WorldTimes getWorldTimes() {
|
||||
return worldTimesMap.getOrDefault(null, new WorldTimes(new HashMap<>()));
|
||||
}
|
||||
|
||||
public void setWorldTimes(Map<UUID, WorldTimes> worldTimes) {
|
||||
worldTimesMap.putAll(worldTimes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get world times per server for this player.
|
||||
*
|
||||
* @return a copy of the WorldTimes Map without the "null" key.
|
||||
*/
|
||||
public Map<UUID, WorldTimes> getWorldTimesPerServer() {
|
||||
Map<UUID, WorldTimes> map = new HashMap<>(worldTimesMap);
|
||||
map.remove(null);
|
||||
return map;
|
||||
}
|
||||
|
||||
public UUID getFavoriteServer() {
|
||||
long max = 0L;
|
||||
UUID maxServer = null;
|
||||
for (Map.Entry<UUID, WorldTimes> entry : getWorldTimesPerServer().entrySet()) {
|
||||
long playTime = entry.getValue().getTotal();
|
||||
if (playTime > max) {
|
||||
max = playTime;
|
||||
maxServer = entry.getKey();
|
||||
}
|
||||
}
|
||||
return maxServer;
|
||||
}
|
||||
|
||||
public long getLastSeen() {
|
||||
return getLastSeen(getAllSessions());
|
||||
}
|
||||
|
||||
public long getLastSeen(UUID serverUUID) {
|
||||
return getLastSeen(getSessions(serverUUID).stream());
|
||||
}
|
||||
|
||||
public long getLastSeen(Stream<Session> s) {
|
||||
OptionalLong max = s.mapToLong(session -> Math.max(session.getSessionStart(), session.getSessionEnd())).max();
|
||||
if (max.isPresent()) {
|
||||
return max.getAsLong();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public long getTotalPlaytime() {
|
||||
return getPlaytime(-1, MiscUtils.getTime() + 1L);
|
||||
}
|
||||
|
||||
public long getPlaytime(long after, long before) {
|
||||
return getPlaytime(getSessions(after, before));
|
||||
}
|
||||
|
||||
public long getPlaytime(UUID serverUUID) {
|
||||
return getPlaytime(getSessions(serverUUID).stream());
|
||||
}
|
||||
|
||||
public long getLongestSession() {
|
||||
return getLongestSession(-1, MiscUtils.getTime() + 1L);
|
||||
}
|
||||
|
||||
public long getLongestSession(int after, long before) {
|
||||
return getLongestSession(getSessions(after, before));
|
||||
}
|
||||
|
||||
public long getLongestSession(UUID serverUUID) {
|
||||
return getLongestSession(getSessions(serverUUID).stream());
|
||||
}
|
||||
|
||||
public long getSessionMedian() {
|
||||
return getSessionMedian(-1, MiscUtils.getTime() + 1L);
|
||||
}
|
||||
|
||||
public long getSessionMedian(int after, long before) {
|
||||
return getSessionMedian(getSessions(after, before));
|
||||
}
|
||||
|
||||
public long getSessionMedian(UUID serverUUID) {
|
||||
return getSessionMedian(getSessions(serverUUID).stream());
|
||||
}
|
||||
|
||||
// Special Getters
|
||||
|
||||
public long getSessionAverage() {
|
||||
return getSessionAverage(-1, MiscUtils.getTime() + 1L);
|
||||
}
|
||||
|
||||
public long getSessionAverage(int after, long before) {
|
||||
return getSessionAverage(getSessions(after, before));
|
||||
}
|
||||
|
||||
public long getSessionAverage(UUID serverUUID) {
|
||||
return getSessionAverage(getSessions(serverUUID).stream());
|
||||
}
|
||||
|
||||
public boolean playedBetween(long after, long before) {
|
||||
return getSessions(after, before).findFirst().isPresent();
|
||||
}
|
||||
|
||||
public Stream<Session> getAllSessions() {
|
||||
return sessions.values().stream().flatMap(Collection::stream);
|
||||
}
|
||||
|
||||
public Stream<Session> getSessions(long after, long before) {
|
||||
return getAllSessions()
|
||||
.filter(session -> session.getSessionStart() >= after && session.getSessionStart() <= before);
|
||||
}
|
||||
|
||||
public GeoInfo getMostRecentGeoInfo() {
|
||||
if (geoInformation.isEmpty()) {
|
||||
return new GeoInfo("-", "Not Known", MiscUtils.getTime());
|
||||
}
|
||||
geoInformation.sort(new GeoInfoComparator());
|
||||
return geoInformation.get(0);
|
||||
}
|
||||
|
||||
public List<Action> getAllActions() {
|
||||
List<Action> actions = new ArrayList<>(this.actions);
|
||||
getPlayerKills().map(PlayerKill::convertToAction).forEach(actions::add);
|
||||
actions.sort(new ActionComparator());
|
||||
return actions;
|
||||
}
|
||||
|
||||
public Stream<PlayerKill> getPlayerKills() {
|
||||
return getPlayerKills(getAllSessions());
|
||||
}
|
||||
|
||||
public Stream<PlayerKill> getPlayerKills(UUID serverUUID) {
|
||||
return getPlayerKills(getSessions(serverUUID).stream());
|
||||
}
|
||||
|
||||
public long getPlayerKillCount() {
|
||||
return getPlayerKills().count();
|
||||
}
|
||||
|
||||
public long getPlayerKillCount(UUID serverUUID) {
|
||||
return getPlayerKills(serverUUID).count();
|
||||
}
|
||||
|
||||
public long getDeathCount() {
|
||||
return getDeathCount(getAllSessions());
|
||||
}
|
||||
|
||||
public long getDeathCount(UUID serverUUID) {
|
||||
return getDeathCount(getSessions(serverUUID).stream());
|
||||
}
|
||||
|
||||
public long getMobKillCount() {
|
||||
return getMobKillCount(getAllSessions());
|
||||
}
|
||||
|
||||
public long getMobKillCount(UUID serverUUID) {
|
||||
return getMobKillCount(getSessions(serverUUID).stream());
|
||||
}
|
||||
|
||||
public long getSessionCount() {
|
||||
return getAllSessions().count();
|
||||
}
|
||||
|
||||
public long getSessionCount(UUID serverUUID) {
|
||||
return getSessions(serverUUID).size();
|
||||
}
|
||||
|
||||
// Setters & Adders
|
||||
|
||||
public long getRegistered(UUID serverUUID) {
|
||||
return registeredMap.getOrDefault(serverUUID, -1L);
|
||||
}
|
||||
|
||||
public void bannedOnServer(UUID serverUUID) {
|
||||
bannedOnServers.add(serverUUID);
|
||||
}
|
||||
|
||||
public void oppedOnServer(UUID serverUUID) {
|
||||
oppedOnServers.add(serverUUID);
|
||||
}
|
||||
|
||||
public void bannedOnServer(Collection<UUID> serverUUIDs) {
|
||||
bannedOnServers.addAll(serverUUIDs);
|
||||
}
|
||||
|
||||
public void oppedOnServer(Collection<UUID> serverUUIDs) {
|
||||
oppedOnServers.addAll(serverUUIDs);
|
||||
}
|
||||
|
||||
public void setSessions(UUID serverUUID, List<Session> sessions) {
|
||||
this.sessions.put(serverUUID, sessions);
|
||||
}
|
||||
|
||||
public void addActiveSession(Session activeSession) {
|
||||
UUID serverUUID = ServerInfo.getServerUUID();
|
||||
List<Session> sessions = getSessions(serverUUID);
|
||||
sessions.add(activeSession);
|
||||
this.sessions.put(serverUUID, sessions);
|
||||
}
|
||||
|
||||
public List<Session> getSessions(UUID serverUUID) {
|
||||
return this.sessions.getOrDefault(serverUUID, new ArrayList<>());
|
||||
}
|
||||
|
||||
public void addReplaceValue(String placeholder, Serializable value) {
|
||||
pluginReplaceMap.put(placeholder, value.toString());
|
||||
}
|
||||
|
||||
public void setWorldTimes(UUID serverUUID, WorldTimes worldTimes) {
|
||||
worldTimesMap.put(serverUUID, worldTimes);
|
||||
}
|
||||
|
||||
public void setTotalWorldTimes(WorldTimes worldTimes) {
|
||||
worldTimesMap.put(null, worldTimes);
|
||||
}
|
||||
|
||||
public void setRegistered(UUID serverUUID, long registered) {
|
||||
registeredMap.put(serverUUID, registered);
|
||||
}
|
||||
|
||||
public int getTimesKicked() {
|
||||
return timesKicked;
|
||||
}
|
||||
|
||||
// Default Setters
|
||||
|
||||
public void setTimesKicked(int timesKicked) {
|
||||
this.timesKicked = timesKicked;
|
||||
}
|
||||
|
||||
public Map<UUID, List<String>> getNicknames() {
|
||||
return nicknames;
|
||||
}
|
||||
|
||||
public void setNicknames(Map<UUID, List<String>> nicknames) {
|
||||
this.nicknames = nicknames;
|
||||
}
|
||||
|
||||
public List<GeoInfo> getGeoInformation() {
|
||||
return geoInformation;
|
||||
}
|
||||
|
||||
// Default Getters
|
||||
|
||||
public void setGeoInformation(List<GeoInfo> geoInformation) {
|
||||
this.geoInformation = geoInformation;
|
||||
}
|
||||
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public long getRegistered() {
|
||||
return registered;
|
||||
}
|
||||
|
||||
public Set<UUID> getBannedOnServers() {
|
||||
return bannedOnServers;
|
||||
}
|
||||
|
||||
public Set<UUID> getOppedOnServers() {
|
||||
return oppedOnServers;
|
||||
}
|
||||
|
||||
public Map<UUID, List<Session>> getSessions() {
|
||||
return sessions;
|
||||
}
|
||||
|
||||
public void setSessions(Map<UUID, List<Session>> sessions) {
|
||||
this.sessions.putAll(sessions);
|
||||
}
|
||||
|
||||
public List<Action> getActions() {
|
||||
return actions;
|
||||
}
|
||||
|
||||
public void setActions(List<Action> actions) {
|
||||
this.actions = actions;
|
||||
}
|
||||
|
||||
public Map<String, String> getPluginReplaceMap() {
|
||||
return pluginReplaceMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the WorldTimes map.
|
||||
*
|
||||
* @return Map that contains WorldTimes for each server and a total in the "null" key.
|
||||
*/
|
||||
public Map<UUID, WorldTimes> getWorldTimesMap() {
|
||||
return worldTimesMap;
|
||||
}
|
||||
|
||||
// OfflinePlayer methods for possible PluginData analysis
|
||||
|
||||
@Override
|
||||
public boolean isOnline() {
|
||||
Player p = getPlayer();
|
||||
return p != null && p.isOnline();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUniqueId() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBanned() {
|
||||
return bannedOnServers.size() != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWhitelisted() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWhitelisted(boolean b) {
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return Bukkit.getPlayer(uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getFirstPlayed() {
|
||||
return registered;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastPlayed() {
|
||||
return getLastSeen(ServerInfo.getServerUUID());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPlayedBefore() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getBedSpawnLocation() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> serialize() {
|
||||
return new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOp() {
|
||||
return oppedOnServers.contains(ServerInfo.getServerUUID());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOp(boolean b) {
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
public void calculateWorldTimesPerServer() {
|
||||
if (worldTimesMap.containsKey(ServerInfo.getServerUUID())) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Map.Entry<UUID, List<Session>> entry : sessions.entrySet()) {
|
||||
UUID serverUUID = entry.getKey();
|
||||
List<Session> sessions = entry.getValue();
|
||||
|
||||
WorldTimes times = worldTimesMap.getOrDefault(serverUUID, new WorldTimes(new HashMap<>()));
|
||||
for (Session session : sessions) {
|
||||
WorldTimes worldTimes = session.getWorldTimes();
|
||||
times.add(worldTimes);
|
||||
}
|
||||
worldTimesMap.put(serverUUID, times);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,391 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.data;
|
||||
|
||||
import com.djrapitops.plan.data.container.GeoInfo;
|
||||
import com.djrapitops.plan.data.container.PlayerKill;
|
||||
import com.djrapitops.plan.data.container.Session;
|
||||
import com.djrapitops.plan.data.container.TPS;
|
||||
import com.djrapitops.plan.data.time.WorldTimes;
|
||||
import com.djrapitops.plan.system.settings.Settings;
|
||||
import com.djrapitops.plan.utilities.analysis.AnalysisUtils;
|
||||
import com.djrapitops.plan.utilities.analysis.MathUtils;
|
||||
import com.djrapitops.plan.utilities.comparators.PlayerProfileLastPlayedComparator;
|
||||
import com.djrapitops.plan.utilities.comparators.TPSComparator;
|
||||
import com.djrapitops.plan.utilities.html.tables.PlayersTableCreator;
|
||||
import com.djrapitops.plugin.api.TimeAmount;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Data class for streamlining Analysis data.
|
||||
* <p>
|
||||
* Most of the methods are not the most efficient when multiple of them are used.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class ServerProfile {
|
||||
|
||||
private final UUID serverUUID;
|
||||
|
||||
// Database information
|
||||
private List<PlayerProfile> players;
|
||||
private List<TPS> tps;
|
||||
private Map<String, Integer> commandUsage;
|
||||
|
||||
// Information calculated with SQL
|
||||
private WorldTimes serverWorldtimes;
|
||||
private long lastPeakDate;
|
||||
private int lastPeakPlayers;
|
||||
private long allTimePeak;
|
||||
private int allTimePeakPlayers;
|
||||
|
||||
// Calculated once
|
||||
private Map<UUID, PlayerProfile> playerMap;
|
||||
|
||||
public ServerProfile(UUID serverUUID) {
|
||||
this.serverUUID = serverUUID;
|
||||
players = new ArrayList<>();
|
||||
tps = new ArrayList<>();
|
||||
commandUsage = new HashMap<>();
|
||||
|
||||
allTimePeak = -1;
|
||||
allTimePeakPlayers = -1;
|
||||
lastPeakDate = -1;
|
||||
lastPeakPlayers = -1;
|
||||
}
|
||||
|
||||
public static long getLowSpikeCount(List<TPS> tpsData) {
|
||||
int mediumThreshold = Settings.THEME_GRAPH_TPS_THRESHOLD_MED.getNumber();
|
||||
|
||||
boolean wasLow = false;
|
||||
long spikeCount = 0L;
|
||||
|
||||
for (TPS tpsObj : tpsData) {
|
||||
double tps = tpsObj.getTicksPerSecond();
|
||||
if (tps < mediumThreshold) {
|
||||
if (!wasLow) {
|
||||
spikeCount++;
|
||||
wasLow = true;
|
||||
}
|
||||
} else {
|
||||
wasLow = false;
|
||||
}
|
||||
}
|
||||
|
||||
return spikeCount;
|
||||
}
|
||||
|
||||
public static List<PlayerKill> getPlayerKills(List<Session> s) {
|
||||
List<PlayerKill> kills = new ArrayList<>();
|
||||
for (Session session : s) {
|
||||
kills.addAll(session.getPlayerKills());
|
||||
}
|
||||
return kills;
|
||||
}
|
||||
|
||||
public static long getMobKillCount(List<Session> s) {
|
||||
long total = 0;
|
||||
for (Session session : s) {
|
||||
total += session.getMobKills();
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
public static long getDeathCount(List<Session> s) {
|
||||
long total = 0;
|
||||
for (Session session : s) {
|
||||
total += session.getDeaths();
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
public static long serverDownTime(List<TPS> tpsData) {
|
||||
long lastDate = -1;
|
||||
long downTime = 0;
|
||||
for (TPS tps : tpsData) {
|
||||
long date = tps.getDate();
|
||||
if (lastDate == -1) {
|
||||
lastDate = date;
|
||||
continue;
|
||||
}
|
||||
|
||||
long diff = date - lastDate;
|
||||
if (diff > TimeAmount.MINUTE.ms() * 3L) {
|
||||
downTime += diff;
|
||||
}
|
||||
lastDate = date;
|
||||
}
|
||||
|
||||
return downTime;
|
||||
}
|
||||
|
||||
public static long serverIdleTime(List<TPS> tpsData) {
|
||||
long lastDate = -1;
|
||||
int lastPlayers = 0;
|
||||
long idleTime = 0;
|
||||
for (TPS tps : tpsData) {
|
||||
long date = tps.getDate();
|
||||
int players = tps.getPlayers();
|
||||
if (lastDate == -1) {
|
||||
lastDate = date;
|
||||
lastPlayers = players;
|
||||
continue;
|
||||
}
|
||||
|
||||
long diff = date - lastDate;
|
||||
if (lastPlayers == 0 && players == 0) {
|
||||
idleTime += diff;
|
||||
}
|
||||
|
||||
lastDate = date;
|
||||
lastPlayers = players;
|
||||
}
|
||||
|
||||
return idleTime;
|
||||
}
|
||||
|
||||
public static double aboveLowThreshold(List<TPS> tpsData) {
|
||||
if (tpsData.isEmpty()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int threshold = Settings.THEME_GRAPH_TPS_THRESHOLD_MED.getNumber();
|
||||
|
||||
long count = 0;
|
||||
for (TPS tps : tpsData) {
|
||||
if (tps.getTicksPerSecond() >= threshold) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count * 1.0 / tpsData.size();
|
||||
}
|
||||
|
||||
public List<PlayerProfile> getPlayers() {
|
||||
return players;
|
||||
}
|
||||
|
||||
public void setPlayers(List<PlayerProfile> players) {
|
||||
this.players = players;
|
||||
}
|
||||
|
||||
public List<TPS> getTps() {
|
||||
return tps;
|
||||
}
|
||||
|
||||
public void setTps(List<TPS> tps) {
|
||||
this.tps = tps;
|
||||
}
|
||||
|
||||
public Map<String, Integer> getCommandUsage() {
|
||||
return commandUsage;
|
||||
}
|
||||
|
||||
public void setCommandUsage(Map<String, Integer> commandUsage) {
|
||||
this.commandUsage = commandUsage;
|
||||
}
|
||||
|
||||
public double getAverageTPS(long after, long before) {
|
||||
OptionalDouble average = getTPSData(after, before)
|
||||
.mapToDouble(TPS::getTicksPerSecond)
|
||||
.average();
|
||||
if (average.isPresent()) {
|
||||
return average.getAsDouble();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public double getAverageCPU(long after, long before) {
|
||||
OptionalDouble average = getTPSData(after, before)
|
||||
.mapToDouble(TPS::getCPUUsage)
|
||||
.filter(num -> num >= 0)
|
||||
.average();
|
||||
if (average.isPresent()) {
|
||||
return average.getAsDouble();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public double getAverageRAM(long after, long before) {
|
||||
OptionalDouble average = getTPSData(after, before)
|
||||
.mapToDouble(TPS::getUsedMemory)
|
||||
.average();
|
||||
if (average.isPresent()) {
|
||||
return average.getAsDouble();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public double getAverageEntities(long after, long before) {
|
||||
OptionalDouble average = getTPSData(after, before)
|
||||
.mapToDouble(TPS::getEntityCount)
|
||||
.average();
|
||||
if (average.isPresent()) {
|
||||
return average.getAsDouble();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public double getAverageChunks(long after, long before) {
|
||||
OptionalDouble average = getTPSData(after, before)
|
||||
.mapToDouble(TPS::getChunksLoaded)
|
||||
.average();
|
||||
if (average.isPresent()) {
|
||||
return average.getAsDouble();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public long getNewPlayers(long after, long before) {
|
||||
return getPlayersWhoRegistered(after, before).count();
|
||||
}
|
||||
|
||||
public long getUniquePlayers(long after, long before) {
|
||||
return getPlayersWhoPlayedBetween(after, before).count();
|
||||
}
|
||||
|
||||
public double getNewPlayersPerDay(long after, long before) {
|
||||
long days = AnalysisUtils.getNumberOfDaysBetween(after, before);
|
||||
long newPlayers = getNewPlayers(after, before);
|
||||
return days == 0 ? newPlayers : newPlayers * 1.0 / days;
|
||||
}
|
||||
|
||||
public Stream<PlayerProfile> getPlayersWhoPlayedBetween(long after, long before) {
|
||||
return players.stream()
|
||||
.filter(player -> player.playedBetween(after, before));
|
||||
}
|
||||
|
||||
public Stream<PlayerProfile> getPlayersWhoRegistered(long after, long before) {
|
||||
return players.stream()
|
||||
.filter(player -> player.getRegistered() >= after && player.getRegistered() <= before);
|
||||
}
|
||||
|
||||
public Stream<TPS> getTPSData(long after, long before) {
|
||||
return tps.stream().filter(tps -> tps.getDate() >= after && tps.getDate() <= before);
|
||||
}
|
||||
|
||||
public String createPlayersTableBody() {
|
||||
players.sort(new PlayerProfileLastPlayedComparator());
|
||||
return PlayersTableCreator.createTable(players);
|
||||
}
|
||||
|
||||
public List<String> getGeoLocations() {
|
||||
return players.stream()
|
||||
.map(PlayerProfile::getMostRecentGeoInfo)
|
||||
.map(GeoInfo::getGeolocation)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
// Default setters & getters
|
||||
|
||||
public long getTotalPlaytime() {
|
||||
return serverWorldtimes.getTotal();
|
||||
}
|
||||
|
||||
public long getAveragePlayTime() {
|
||||
return MathUtils.averageLong(getTotalPlaytime(), getPlayerCount());
|
||||
}
|
||||
|
||||
public long getPlayerCount() {
|
||||
return players.size();
|
||||
}
|
||||
|
||||
public Map<UUID, List<Session>> getSessions() {
|
||||
return players.stream().collect(Collectors.toMap(PlayerProfile::getUuid, p -> p.getSessions(serverUUID)));
|
||||
}
|
||||
|
||||
public List<Session> getAllSessions() {
|
||||
return players.stream().map(p -> p.getSessions(serverUUID)).flatMap(Collection::stream).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public WorldTimes getServerWorldtimes() {
|
||||
return serverWorldtimes;
|
||||
}
|
||||
|
||||
public void setServerWorldtimes(WorldTimes serverWorldtimes) {
|
||||
this.serverWorldtimes = serverWorldtimes;
|
||||
}
|
||||
|
||||
public long getLastPeakDate() {
|
||||
return lastPeakDate;
|
||||
}
|
||||
|
||||
public void setLastPeakDate(long lastPeakDate) {
|
||||
this.lastPeakDate = lastPeakDate;
|
||||
}
|
||||
|
||||
public int getLastPeakPlayers() {
|
||||
return lastPeakPlayers;
|
||||
}
|
||||
|
||||
public void setLastPeakPlayers(int lastPeakPlayers) {
|
||||
this.lastPeakPlayers = lastPeakPlayers;
|
||||
}
|
||||
|
||||
public long getAllTimePeak() {
|
||||
return allTimePeak;
|
||||
}
|
||||
|
||||
public void setAllTimePeak(long allTimePeak) {
|
||||
this.allTimePeak = allTimePeak;
|
||||
}
|
||||
|
||||
public int getAllTimePeakPlayers() {
|
||||
return allTimePeakPlayers;
|
||||
}
|
||||
|
||||
public void setAllTimePeakPlayers(int allTimePeakPlayers) {
|
||||
this.allTimePeakPlayers = allTimePeakPlayers;
|
||||
}
|
||||
|
||||
public Stream<PlayerProfile> getOps() {
|
||||
return players.stream().filter(PlayerProfile::isOp);
|
||||
}
|
||||
|
||||
public Set<UUID> getUuids() {
|
||||
Set<UUID> uuids = new HashSet<>();
|
||||
for (PlayerProfile player : players) {
|
||||
uuids.add(player.getUuid());
|
||||
}
|
||||
return uuids;
|
||||
}
|
||||
|
||||
public long serverDownTime(long after, long before) {
|
||||
return serverDownTime(getTPSData(after, before)
|
||||
.sorted(new TPSComparator())
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
public long serverIdleTime(long after, long before) {
|
||||
return serverIdleTime(getTPSData(after, before)
|
||||
.sorted(new TPSComparator())
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
public PlayerProfile getPlayer(UUID uuid) {
|
||||
if (playerMap == null) {
|
||||
playerMap = players.stream().collect(Collectors.toMap(PlayerProfile::getUuid, Function.identity()));
|
||||
}
|
||||
|
||||
return playerMap.get(uuid);
|
||||
}
|
||||
|
||||
public void addActiveSessions(Map<UUID, Session> activeSessions) {
|
||||
for (Map.Entry<UUID, Session> entry : activeSessions.entrySet()) {
|
||||
UUID uuid = entry.getKey();
|
||||
Session session = entry.getValue();
|
||||
session.setSessionID((int) session.getSessionStart());
|
||||
|
||||
PlayerProfile player = getPlayer(uuid);
|
||||
if (player != null) {
|
||||
player.addActiveSession(session);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
package com.djrapitops.plan.data;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Object containing webserver security user information.
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @since 3.5.2
|
||||
*/
|
||||
public class WebUser {
|
||||
|
||||
private final String user;
|
||||
private final String saltedPassHash;
|
||||
private final int permLevel;
|
||||
|
||||
public WebUser(String user, String saltedPassHash, int permLevel) {
|
||||
this.user = user;
|
||||
this.saltedPassHash = saltedPassHash;
|
||||
this.permLevel = permLevel;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public String getSaltedPassHash() {
|
||||
return saltedPassHash;
|
||||
}
|
||||
|
||||
public int getPermLevel() {
|
||||
return permLevel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
WebUser webUser = (WebUser) o;
|
||||
return permLevel == webUser.permLevel &&
|
||||
Objects.equals(user, webUser.user) &&
|
||||
Objects.equals(saltedPassHash, webUser.saltedPassHash);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(user, saltedPassHash, permLevel);
|
||||
}
|
||||
}
|
@ -1,133 +0,0 @@
|
||||
package com.djrapitops.plan.data.calculation;
|
||||
|
||||
import com.djrapitops.plan.data.PlayerProfile;
|
||||
import com.djrapitops.plan.data.container.Session;
|
||||
import com.djrapitops.plan.system.settings.Settings;
|
||||
import com.djrapitops.plan.utilities.FormatUtils;
|
||||
import com.djrapitops.plugin.api.TimeAmount;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ActivityIndex {
|
||||
|
||||
private final double value;
|
||||
|
||||
public ActivityIndex(PlayerProfile player, long date) {
|
||||
value = calculate(player, date);
|
||||
}
|
||||
|
||||
public static String[] getGroups() {
|
||||
return new String[]{"Very Active", "Active", "Regular", "Irregular", "Inactive"};
|
||||
}
|
||||
|
||||
private long loadSetting(long value) {
|
||||
return value <= 0 ? 1 : value;
|
||||
}
|
||||
|
||||
private int loadSetting(int value) {
|
||||
return value <= 0 ? 1 : value;
|
||||
}
|
||||
|
||||
private double calculate(PlayerProfile player, long date) {
|
||||
long week = TimeAmount.WEEK.ms();
|
||||
long weekAgo = date - week;
|
||||
long twoWeeksAgo = date - 2L * week;
|
||||
long threeWeeksAgo = date - 3L * week;
|
||||
|
||||
long activePlayThreshold = loadSetting(Settings.ACTIVE_PLAY_THRESHOLD.getNumber() * TimeAmount.MINUTE.ms());
|
||||
int activeLoginThreshold = loadSetting(Settings.ACTIVE_LOGIN_THRESHOLD.getNumber());
|
||||
|
||||
List<Session> sessionsWeek = player.getSessions(weekAgo, date).collect(Collectors.toList());
|
||||
List<Session> sessionsWeek2 = player.getSessions(twoWeeksAgo, weekAgo).collect(Collectors.toList());
|
||||
List<Session> sessionsWeek3 = player.getSessions(threeWeeksAgo, twoWeeksAgo).collect(Collectors.toList());
|
||||
|
||||
// Playtime per week multipliers, max out to avoid too high values.
|
||||
double max = 4.0;
|
||||
|
||||
long playtimeWeek = PlayerProfile.getPlaytime(sessionsWeek.stream());
|
||||
double weekPlay = (playtimeWeek * 1.0 / activePlayThreshold);
|
||||
if (weekPlay > max) {
|
||||
weekPlay = max;
|
||||
}
|
||||
long playtimeWeek2 = PlayerProfile.getPlaytime(sessionsWeek2.stream());
|
||||
double week2Play = (playtimeWeek2 * 1.0 / activePlayThreshold);
|
||||
if (week2Play > max) {
|
||||
week2Play = max;
|
||||
}
|
||||
long playtimeWeek3 = PlayerProfile.getPlaytime(sessionsWeek3.stream());
|
||||
double week3Play = (playtimeWeek3 * 1.0 / activePlayThreshold);
|
||||
if (week3Play > max) {
|
||||
week3Play = max;
|
||||
}
|
||||
|
||||
double playtimeMultiplier = 1.0;
|
||||
if (playtimeWeek + playtimeWeek2 + playtimeWeek3 > activePlayThreshold * 3.0) {
|
||||
playtimeMultiplier = 1.25;
|
||||
}
|
||||
|
||||
// Reduce the harshness for new players and players who have had a vacation
|
||||
if (weekPlay > 1 && week3Play > 1 && week2Play == 0.0) {
|
||||
week2Play = 0.5;
|
||||
}
|
||||
if (weekPlay > 1 && week2Play == 0.0) {
|
||||
week2Play = 0.6;
|
||||
}
|
||||
if (weekPlay > 1 && week3Play == 0.0) {
|
||||
week3Play = 0.75;
|
||||
}
|
||||
|
||||
double playAvg = (weekPlay + week2Play + week3Play) / 3.0;
|
||||
|
||||
double weekLogin = sessionsWeek.size() >= activeLoginThreshold ? 1.0 : 0.5;
|
||||
double week2Login = sessionsWeek2.size() >= activeLoginThreshold ? 1.0 : 0.5;
|
||||
double week3Login = sessionsWeek3.size() >= activeLoginThreshold ? 1.0 : 0.5;
|
||||
|
||||
double loginMultiplier = 1.0;
|
||||
double loginTotal = weekLogin + week2Login + week3Login;
|
||||
double loginAvg = loginTotal / 3.0;
|
||||
|
||||
if (loginTotal <= 2.0) {
|
||||
// Reduce index for players that have not logged in the threshold amount for 2 weeks
|
||||
loginMultiplier = 0.75;
|
||||
}
|
||||
|
||||
return playAvg * loginAvg * loginMultiplier * playtimeMultiplier;
|
||||
}
|
||||
|
||||
public double getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public String getFormattedValue() {
|
||||
return FormatUtils.cutDecimals(value);
|
||||
}
|
||||
|
||||
public String getGroup() {
|
||||
if (value >= 3.5) {
|
||||
return "Very Active";
|
||||
} else if (value >= 1.75) {
|
||||
return "Active";
|
||||
} else if (value >= 1.0) {
|
||||
return "Regular";
|
||||
} else if (value >= 0.5) {
|
||||
return "Irregular";
|
||||
} else {
|
||||
return "Inactive";
|
||||
}
|
||||
}
|
||||
|
||||
public String getColor() {
|
||||
if (value >= 3.5) {
|
||||
return "green";
|
||||
} else if (value >= 1.75) {
|
||||
return "green";
|
||||
} else if (value >= 1.0) {
|
||||
return "lime";
|
||||
} else if (value >= 0.5) {
|
||||
return "amber";
|
||||
} else {
|
||||
return "blue-gray";
|
||||
}
|
||||
}
|
||||
}
|
@ -1,370 +0,0 @@
|
||||
package com.djrapitops.plan.data.calculation;
|
||||
|
||||
import com.djrapitops.plan.PlanPlugin;
|
||||
import com.djrapitops.plan.data.PlayerProfile;
|
||||
import com.djrapitops.plan.data.ServerProfile;
|
||||
import com.djrapitops.plan.data.container.Session;
|
||||
import com.djrapitops.plan.data.container.StickyData;
|
||||
import com.djrapitops.plan.data.container.TPS;
|
||||
import com.djrapitops.plan.data.element.AnalysisContainer;
|
||||
import com.djrapitops.plan.data.plugin.PluginData;
|
||||
import com.djrapitops.plan.data.time.WorldTimes;
|
||||
import com.djrapitops.plan.system.info.server.ServerInfo;
|
||||
import com.djrapitops.plan.system.info.server.ServerProperties;
|
||||
import com.djrapitops.plan.system.settings.Settings;
|
||||
import com.djrapitops.plan.system.settings.theme.Theme;
|
||||
import com.djrapitops.plan.system.settings.theme.ThemeVal;
|
||||
import com.djrapitops.plan.utilities.FormatUtils;
|
||||
import com.djrapitops.plan.utilities.MiscUtils;
|
||||
import com.djrapitops.plan.utilities.analysis.AnalysisUtils;
|
||||
import com.djrapitops.plan.utilities.analysis.MathUtils;
|
||||
import com.djrapitops.plan.utilities.comparators.SessionStartComparator;
|
||||
import com.djrapitops.plan.utilities.html.Html;
|
||||
import com.djrapitops.plan.utilities.html.graphs.ActivityStackGraph;
|
||||
import com.djrapitops.plan.utilities.html.graphs.PunchCardGraph;
|
||||
import com.djrapitops.plan.utilities.html.graphs.WorldMap;
|
||||
import com.djrapitops.plan.utilities.html.graphs.line.*;
|
||||
import com.djrapitops.plan.utilities.html.graphs.pie.ActivityPie;
|
||||
import com.djrapitops.plan.utilities.html.graphs.pie.WorldPie;
|
||||
import com.djrapitops.plan.utilities.html.structure.AnalysisPluginsTabContentCreator;
|
||||
import com.djrapitops.plan.utilities.html.structure.SessionTabStructureCreator;
|
||||
import com.djrapitops.plan.utilities.html.tables.CommandUseTable;
|
||||
import com.djrapitops.plan.utilities.html.tables.SessionsTableCreator;
|
||||
import com.djrapitops.plugin.api.TimeAmount;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Big container object for Data.
|
||||
* <p>
|
||||
* Contains parts that can be analysed. Each part has their own purpose.
|
||||
* <p>
|
||||
* Parts contain variables that can be added to. These variables are then
|
||||
* analysed using the analysis method.
|
||||
* <p>
|
||||
* After being analysed the ReplaceMap can be retrieved for replacing
|
||||
* placeholders on the server.html file.
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @since 3.5.2
|
||||
*/
|
||||
public class AnalysisData extends RawData {
|
||||
|
||||
private long refreshDate;
|
||||
|
||||
private Map<String, Long> analyzedValues;
|
||||
private Set<StickyData> stickyMonthData;
|
||||
private List<PlayerProfile> players;
|
||||
|
||||
public AnalysisData() {
|
||||
analyzedValues = new HashMap<>();
|
||||
stickyMonthData = new HashSet<>();
|
||||
}
|
||||
|
||||
public void parsePluginsSection(Map<PluginData, AnalysisContainer> containers) {
|
||||
String[] navAndTabs = AnalysisPluginsTabContentCreator.createContent(containers);
|
||||
addValue("navPluginsTabs", navAndTabs[0]);
|
||||
addValue("tabsPlugins", navAndTabs[1]);
|
||||
}
|
||||
|
||||
private void addConstants() {
|
||||
addValue("version", PlanPlugin.getInstance().getVersion());
|
||||
addValue("worldPieColors", Theme.getValue(ThemeVal.GRAPH_WORLD_PIE));
|
||||
addValue("gmPieColors", Theme.getValue(ThemeVal.GRAPH_GM_PIE));
|
||||
addValue("serverName", Settings.SERVER_NAME.toString().replaceAll("[^a-zA-Z0-9_\\s]", "_"));
|
||||
addValue("timeZone", MiscUtils.getTimeZoneOffsetHours());
|
||||
addValue("refresh", FormatUtils.formatTimeStampClock(refreshDate));
|
||||
|
||||
addValue("activityPieColors", Theme.getValue(ThemeVal.GRAPH_ACTIVITY_PIE));
|
||||
addValue("playersGraphColor", Theme.getValue(ThemeVal.GRAPH_PLAYERS_ONLINE));
|
||||
addValue("tpsHighColor", Theme.getValue(ThemeVal.GRAPH_TPS_HIGH));
|
||||
addValue("tpsMediumColor", Theme.getValue(ThemeVal.GRAPH_TPS_MED));
|
||||
addValue("tpsLowColor", Theme.getValue(ThemeVal.GRAPH_TPS_LOW));
|
||||
addValue("worldMapColLow", Theme.getValue(ThemeVal.WORLD_MAP_LOW));
|
||||
addValue("worldMapColHigh", Theme.getValue(ThemeVal.WORLD_MAP_HIGH));
|
||||
addValue("tpsMedium", Settings.THEME_GRAPH_TPS_THRESHOLD_MED.getNumber());
|
||||
addValue("tpsHigh", Settings.THEME_GRAPH_TPS_THRESHOLD_HIGH.getNumber());
|
||||
|
||||
ServerProperties serverProperties = ServerInfo.getServerProperties();
|
||||
addValue("playersMax", serverProperties.getMaxPlayers());
|
||||
addValue("playersOnline", serverProperties.getOnlinePlayers());
|
||||
}
|
||||
|
||||
public void analyze(ServerProfile profile) {
|
||||
long now = MiscUtils.getTime();
|
||||
refreshDate = now;
|
||||
long dayAgo = now - TimeAmount.DAY.ms();
|
||||
long weekAgo = now - TimeAmount.WEEK.ms();
|
||||
long monthAgo = now - TimeAmount.MONTH.ms();
|
||||
|
||||
addConstants();
|
||||
|
||||
got("now", now);
|
||||
got("dayAgo", dayAgo);
|
||||
got("weekAgo", weekAgo);
|
||||
got("monthAgo", monthAgo);
|
||||
|
||||
Map<UUID, List<Session>> sessions = profile.getSessions();
|
||||
List<Session> allSessions = profile.getAllSessions();
|
||||
allSessions.sort(new SessionStartComparator());
|
||||
|
||||
players = profile.getPlayers();
|
||||
List<PlayerProfile> ops = profile.getOps().collect(Collectors.toList());
|
||||
long playersTotal = got("playersTotal", players.size());
|
||||
|
||||
List<TPS> tpsData = profile.getTPSData(0, now).collect(Collectors.toList());
|
||||
List<TPS> tpsDataDay = profile.getTPSData(dayAgo, now).collect(Collectors.toList());
|
||||
List<TPS> tpsDataWeek = profile.getTPSData(weekAgo, now).collect(Collectors.toList());
|
||||
List<TPS> tpsDataMonth = profile.getTPSData(monthAgo, now).collect(Collectors.toList());
|
||||
|
||||
List<String> geoLocations = profile.getGeoLocations();
|
||||
Map<String, Integer> commandUsage = profile.getCommandUsage();
|
||||
|
||||
directProfileVariables(profile);
|
||||
performanceTab(tpsData, tpsDataDay, tpsDataWeek, tpsDataMonth);
|
||||
sessionData(monthAgo, sessions, allSessions);
|
||||
onlineActivityNumbers(profile, sessions, players);
|
||||
geolocationsTab(geoLocations);
|
||||
commandUsage(commandUsage);
|
||||
|
||||
addValue("ops", ops.size());
|
||||
addValue("playersTotal", playersTotal);
|
||||
|
||||
healthTab(now, players, tpsDataMonth);
|
||||
|
||||
long totalPlaytime = profile.getTotalPlaytime();
|
||||
addValue("playtimeTotal", playersTotal != 0 ? FormatUtils.formatTimeAmount(totalPlaytime) : "No Players");
|
||||
addValue("playtimeAverage", playersTotal != 0 ? FormatUtils.formatTimeAmount(MathUtils.averageLong(totalPlaytime, playersTotal)) : "-");
|
||||
}
|
||||
|
||||
private void healthTab(long now, List<PlayerProfile> players, List<TPS> tpsDataMonth) {
|
||||
TreeMap<Long, Map<String, Set<UUID>>> activityData = AnalysisUtils.turnToActivityDataMap(now, players);
|
||||
|
||||
Map<String, Set<UUID>> activityNow = activityData.getOrDefault(now, new HashMap<>());
|
||||
|
||||
ActivityStackGraph activityStackGraph = new ActivityStackGraph(activityData);
|
||||
String activityPieSeries = new ActivityPie(activityNow).toHighChartsSeries();
|
||||
|
||||
addValue("activityStackCategories", activityStackGraph.toHighChartsLabels());
|
||||
addValue("activityStackSeries", activityStackGraph.toHighChartsSeries());
|
||||
addValue("activityPieSeries", activityPieSeries);
|
||||
|
||||
Set<UUID> veryActiveNow = activityNow.getOrDefault("Very Active", new HashSet<>());
|
||||
Set<UUID> activeNow = activityNow.getOrDefault("Active", new HashSet<>());
|
||||
Set<UUID> regularNow = activityNow.getOrDefault("Regular", new HashSet<>());
|
||||
|
||||
addValue("playersRegular", (veryActiveNow.size() + activeNow.size() + regularNow.size()));
|
||||
|
||||
HealthNotes healthNotes = new HealthNotes(this, activityData, tpsDataMonth, now);
|
||||
healthNotes.analyzeHealth();
|
||||
|
||||
addValue("healthNotes", healthNotes.parse());
|
||||
addValue("healthIndex", healthNotes.getServerHealth());
|
||||
}
|
||||
|
||||
private void commandUsage(Map<String, Integer> commandUsage) {
|
||||
addValue("commandUniqueCount", String.valueOf(commandUsage.size()));
|
||||
addValue("commandCount", MathUtils.sumInt(commandUsage.values().stream().map(i -> (int) i)));
|
||||
addValue("tableBodyCommands", new CommandUseTable(commandUsage).parseBody());
|
||||
}
|
||||
|
||||
private void geolocationsTab(List<String> geoLocations) {
|
||||
addValue("geoMapSeries", new WorldMap(geoLocations).toHighChartsSeries());
|
||||
}
|
||||
|
||||
private void onlineActivityNumbers(ServerProfile profile, Map<UUID, List<Session>> sessions, List<PlayerProfile> players) {
|
||||
long now = value("now");
|
||||
long dayAgo = value("dayAgo");
|
||||
long weekAgo = value("weekAgo");
|
||||
long monthAgo = value("monthAgo");
|
||||
|
||||
List<PlayerProfile> newDay = profile.getPlayersWhoRegistered(dayAgo, now).collect(Collectors.toList());
|
||||
List<PlayerProfile> newWeek = profile.getPlayersWhoRegistered(weekAgo, now).collect(Collectors.toList());
|
||||
List<PlayerProfile> newMonth = profile.getPlayersWhoRegistered(monthAgo, now).collect(Collectors.toList());
|
||||
List<PlayerProfile> uniqueDay = profile.getPlayersWhoPlayedBetween(dayAgo, now).collect(Collectors.toList());
|
||||
List<PlayerProfile> uniqueWeek = profile.getPlayersWhoPlayedBetween(weekAgo, now).collect(Collectors.toList());
|
||||
List<PlayerProfile> uniqueMonth = profile.getPlayersWhoPlayedBetween(monthAgo, now).collect(Collectors.toList());
|
||||
|
||||
int uniqD = uniqueDay.size();
|
||||
int uniqW = uniqueWeek.size();
|
||||
int uniqM = uniqueMonth.size();
|
||||
long newD = got("newD", newDay.size());
|
||||
long newW = got("newW", newWeek.size());
|
||||
long newM = got("newM", newMonth.size());
|
||||
long playersTotal = value("playersTotal");
|
||||
|
||||
addValue("playersDay", uniqD);
|
||||
addValue("playersWeek", uniqW);
|
||||
addValue("playersMonth", uniqM);
|
||||
addValue("playersNewDay", newD);
|
||||
addValue("playersNewWeek", newW);
|
||||
addValue("playersNewMonth", newM);
|
||||
|
||||
addValue("playersAverage", AnalysisUtils.getUniqueJoinsPerDay(sessions, -1));
|
||||
addValue("playersAverageDay", AnalysisUtils.getUniqueJoinsPerDay(sessions, dayAgo));
|
||||
addValue("playersAverageWeek", AnalysisUtils.getUniqueJoinsPerDay(sessions, weekAgo));
|
||||
addValue("playersAverageMonth", AnalysisUtils.getUniqueJoinsPerDay(sessions, monthAgo));
|
||||
addValue("playersNewAverage", AnalysisUtils.getNewUsersPerDay(toRegistered(players), -1, playersTotal));
|
||||
addValue("playersNewAverageDay", AnalysisUtils.getNewUsersPerDay(toRegistered(newDay), -1, newD));
|
||||
addValue("playersNewAverageWeek", AnalysisUtils.getNewUsersPerDay(toRegistered(newWeek), -1, newW));
|
||||
addValue("playersNewAverageMonth", AnalysisUtils.getNewUsersPerDay(toRegistered(newMonth), -1, newM));
|
||||
|
||||
stickiness(now, weekAgo, monthAgo, newDay, newWeek, newMonth);
|
||||
}
|
||||
|
||||
private void stickiness(long now, long weekAgo, long monthAgo,
|
||||
List<PlayerProfile> newDay, List<PlayerProfile> newWeek, List<PlayerProfile> newMonth) {
|
||||
long newD = value("newD");
|
||||
long newW = value("newW");
|
||||
long newM = value("newM");
|
||||
|
||||
long fourDaysAgo = now - TimeAmount.DAY.ms() * 4L;
|
||||
long twoWeeksAgo = now - TimeAmount.WEEK.ms() * 2L;
|
||||
|
||||
List<PlayerProfile> playersStuckPerMonth = newMonth.stream()
|
||||
.filter(p -> p.playedBetween(monthAgo, twoWeeksAgo) && p.playedBetween(twoWeeksAgo, now))
|
||||
.collect(Collectors.toList());
|
||||
List<PlayerProfile> playersStuckPerWeek = newWeek.stream()
|
||||
.filter(p -> p.playedBetween(weekAgo, fourDaysAgo) && p.playedBetween(fourDaysAgo, now))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
int stuckPerM = playersStuckPerMonth.size();
|
||||
int stuckPerW = playersStuckPerWeek.size();
|
||||
got("stuckPerM", stuckPerM);
|
||||
got("stuckPerW", stuckPerW);
|
||||
|
||||
addValue("playersStuckMonth", stuckPerM);
|
||||
addValue("playersStuckWeek", stuckPerW);
|
||||
addValue("playersStuckPercMonth", newM != 0 ? FormatUtils.cutDecimals(MathUtils.averageDouble(stuckPerM, newM) * 100.0) + "%" : "-");
|
||||
addValue("playersStuckPercWeek", newW != 0 ? FormatUtils.cutDecimals(MathUtils.averageDouble(stuckPerW, newW) * 100.0) + "%" : "-");
|
||||
|
||||
stuckPerDay(newDay, newMonth, newD, playersStuckPerMonth, playersStuckPerWeek);
|
||||
}
|
||||
|
||||
private void stuckPerDay(List<PlayerProfile> newDay, List<PlayerProfile> newMonth, long newD, List<PlayerProfile> playersStuckPerMonth, List<PlayerProfile> playersStuckPerWeek) {
|
||||
if (newD != 0) {
|
||||
// New Players
|
||||
stickyMonthData = newMonth.stream().map(StickyData::new).distinct().collect(Collectors.toSet());
|
||||
Set<StickyData> stickyW = playersStuckPerMonth.stream().map(StickyData::new).distinct().collect(Collectors.toSet());
|
||||
// New Players who stayed
|
||||
Set<StickyData> stickyStuckM = newMonth.stream().map(StickyData::new).distinct().collect(Collectors.toSet());
|
||||
Set<StickyData> stickyStuckW = playersStuckPerWeek.stream().map(StickyData::new).distinct().collect(Collectors.toSet());
|
||||
|
||||
int stuckPerD = 0;
|
||||
for (PlayerProfile playerProfile : newDay) {
|
||||
double probability = AnalysisUtils.calculateProbabilityOfStaying(
|
||||
stickyMonthData, stickyW, stickyStuckM, stickyStuckW, playerProfile
|
||||
);
|
||||
if (probability >= 0.5) {
|
||||
stuckPerD++;
|
||||
}
|
||||
}
|
||||
addValue("playersStuckDay", stuckPerD);
|
||||
addValue("playersStuckPercDay", FormatUtils.cutDecimals(MathUtils.averageDouble(stuckPerD, newD) * 100.0) + "%");
|
||||
} else {
|
||||
addValue("playersStuckDay", 0);
|
||||
addValue("playersStuckPercDay", "-");
|
||||
}
|
||||
}
|
||||
|
||||
private List<Long> toRegistered(List<PlayerProfile> players) {
|
||||
return players.stream().map(PlayerProfile::getRegistered).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private void sessionData(long monthAgo, Map<UUID, List<Session>> sessions, List<Session> allSessions) {
|
||||
List<Session> sessionsMonth = allSessions.stream()
|
||||
.filter(s -> s.getSessionStart() >= monthAgo)
|
||||
.collect(Collectors.toList());
|
||||
String[] tables = SessionsTableCreator.createTable(sessions, allSessions);
|
||||
String[] sessionContent = SessionTabStructureCreator.createStructure(sessions, allSessions);
|
||||
|
||||
addValue("sessionCount", allSessions.size());
|
||||
addValue("accordionSessions", sessionContent[0]);
|
||||
addValue("sessionTabGraphViewFunctions", sessionContent[1]);
|
||||
addValue("tableBodySessions", tables[0]);
|
||||
addValue("listRecentLogins", tables[1]);
|
||||
addValue("sessionAverage", FormatUtils.formatTimeAmount(MathUtils.averageLong(allSessions.stream().map(Session::getLength))));
|
||||
addValue("punchCardSeries", new PunchCardGraph(sessionsMonth).toHighChartsSeries());
|
||||
|
||||
addValue("deaths", ServerProfile.getDeathCount(allSessions));
|
||||
addValue("mobKillCount", ServerProfile.getMobKillCount(allSessions));
|
||||
addValue("killCount", ServerProfile.getPlayerKills(allSessions).size());
|
||||
}
|
||||
|
||||
private void directProfileVariables(ServerProfile profile) {
|
||||
WorldTimes worldTimes = profile.getServerWorldtimes();
|
||||
long allTimePeak = profile.getAllTimePeak();
|
||||
long lastPeak = profile.getLastPeakDate();
|
||||
|
||||
String playersTableBody = profile.createPlayersTableBody();
|
||||
addValue("tablePlayerlist", Settings.PLAYERTABLE_FOOTER.isTrue() ?
|
||||
Html.TABLE_PLAYERS_FOOTER.parse(playersTableBody)
|
||||
: Html.TABLE_PLAYERS.parse(playersTableBody));
|
||||
addValue("worldTotal", FormatUtils.formatTimeAmount(worldTimes.getTotal()));
|
||||
WorldPie worldPie = new WorldPie(worldTimes);
|
||||
addValue("worldSeries", worldPie.toHighChartsSeries());
|
||||
addValue("gmSeries", worldPie.toHighChartsDrilldown());
|
||||
addValue("lastPeakTime", lastPeak != -1 ? FormatUtils.formatTimeStampYear(lastPeak) : "No Data");
|
||||
addValue("playersLastPeak", lastPeak != -1 ? profile.getLastPeakPlayers() : "-");
|
||||
addValue("bestPeakTime", allTimePeak != -1 ? FormatUtils.formatTimeStampYear(allTimePeak) : "No Data");
|
||||
addValue("playersBestPeak", allTimePeak != -1 ? profile.getAllTimePeakPlayers() : "-");
|
||||
}
|
||||
|
||||
private void performanceTab(List<TPS> tpsData, List<TPS> tpsDataDay, List<TPS> tpsDataWeek, List<TPS> tpsDataMonth) {
|
||||
got("tpsSpikeMonth", ServerProfile.getLowSpikeCount(tpsDataMonth));
|
||||
got("tpsSpikeWeek", ServerProfile.getLowSpikeCount(tpsDataWeek));
|
||||
got("tpsSpikeDay", ServerProfile.getLowSpikeCount(tpsDataDay));
|
||||
addValue("tpsSpikeMonth", value("tpsSpikeMonth"));
|
||||
addValue("tpsSpikeWeek", value("tpsSpikeWeek"));
|
||||
addValue("tpsSpikeDay", value("tpsSpikeDay"));
|
||||
|
||||
addValue("playersOnlineSeries", new OnlineActivityGraph(tpsData).toHighChartsSeries());
|
||||
addValue("tpsSeries", new TPSGraph(tpsData).toHighChartsSeries());
|
||||
addValue("cpuSeries", new CPUGraph(tpsData).toHighChartsSeries());
|
||||
addValue("ramSeries", new RamGraph(tpsData).toHighChartsSeries());
|
||||
addValue("entitySeries", new EntityGraph(tpsData).toHighChartsSeries());
|
||||
addValue("chunkSeries", new ChunkGraph(tpsData).toHighChartsSeries());
|
||||
|
||||
double averageCPUMonth = MathUtils.averageDouble(tpsDataMonth.stream().map(TPS::getCPUUsage).filter(i -> i != 0));
|
||||
double averageCPUWeek = MathUtils.averageDouble(tpsDataWeek.stream().map(TPS::getCPUUsage).filter(i -> i != 0));
|
||||
double averageCPUDay = MathUtils.averageDouble(tpsDataDay.stream().map(TPS::getCPUUsage).filter(i -> i != 0));
|
||||
|
||||
addValue("tpsAverageMonth", FormatUtils.cutDecimals(MathUtils.averageDouble(tpsDataMonth.stream().map(TPS::getTicksPerSecond))));
|
||||
addValue("tpsAverageWeek", FormatUtils.cutDecimals(MathUtils.averageDouble(tpsDataWeek.stream().map(TPS::getTicksPerSecond))));
|
||||
addValue("tpsAverageDay", FormatUtils.cutDecimals(MathUtils.averageDouble(tpsDataDay.stream().map(TPS::getTicksPerSecond))));
|
||||
|
||||
addValue("cpuAverageMonth", averageCPUMonth >= 0 ? FormatUtils.cutDecimals(averageCPUMonth) + "%" : "Unavailable");
|
||||
addValue("cpuAverageWeek", averageCPUWeek >= 0 ? FormatUtils.cutDecimals(averageCPUWeek) + "%" : "Unavailable");
|
||||
addValue("cpuAverageDay", averageCPUDay >= 0 ? FormatUtils.cutDecimals(averageCPUDay) + "%" : "Unavailable");
|
||||
|
||||
addValue("ramAverageMonth", FormatUtils.cutDecimals(MathUtils.averageLong(tpsDataMonth.stream().map(TPS::getUsedMemory).filter(i -> i != 0))));
|
||||
addValue("ramAverageWeek", FormatUtils.cutDecimals(MathUtils.averageLong(tpsDataWeek.stream().map(TPS::getUsedMemory).filter(i -> i != 0))));
|
||||
addValue("ramAverageDay", FormatUtils.cutDecimals(MathUtils.averageLong(tpsDataDay.stream().map(TPS::getUsedMemory).filter(i -> i != 0))));
|
||||
|
||||
addValue("entityAverageMonth", FormatUtils.cutDecimals(MathUtils.averageInt(tpsDataMonth.stream().map(TPS::getEntityCount).filter(i -> i != 0))));
|
||||
addValue("entityAverageWeek", FormatUtils.cutDecimals(MathUtils.averageInt(tpsDataWeek.stream().map(TPS::getEntityCount).filter(i -> i != 0))));
|
||||
addValue("entityAverageDay", FormatUtils.cutDecimals(MathUtils.averageInt(tpsDataDay.stream().map(TPS::getEntityCount).filter(i -> i != 0))));
|
||||
|
||||
addValue("chunkAverageMonth", FormatUtils.cutDecimals(MathUtils.averageInt(tpsDataMonth.stream().map(TPS::getChunksLoaded).filter(i -> i != 0))));
|
||||
addValue("chunkAverageWeek", FormatUtils.cutDecimals(MathUtils.averageInt(tpsDataWeek.stream().map(TPS::getChunksLoaded).filter(i -> i != 0))));
|
||||
addValue("chunkAverageDay", FormatUtils.cutDecimals(MathUtils.averageInt(tpsDataDay.stream().map(TPS::getChunksLoaded).filter(i -> i != 0))));
|
||||
}
|
||||
|
||||
private long got(String key, long v) {
|
||||
analyzedValues.put(key, v);
|
||||
return v;
|
||||
}
|
||||
|
||||
public long value(String key) {
|
||||
return analyzedValues.getOrDefault(key, 0L);
|
||||
}
|
||||
|
||||
public Set<StickyData> getStickyMonthData() {
|
||||
return stickyMonthData;
|
||||
}
|
||||
|
||||
public List<PlayerProfile> getPlayers() {
|
||||
return players;
|
||||
}
|
||||
}
|
@ -1,250 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.data.calculation;
|
||||
|
||||
import com.djrapitops.plan.data.PlayerProfile;
|
||||
import com.djrapitops.plan.data.ServerProfile;
|
||||
import com.djrapitops.plan.data.container.StickyData;
|
||||
import com.djrapitops.plan.data.container.TPS;
|
||||
import com.djrapitops.plan.system.settings.Settings;
|
||||
import com.djrapitops.plan.utilities.FormatUtils;
|
||||
import com.djrapitops.plan.utilities.analysis.MathUtils;
|
||||
import com.djrapitops.plan.utilities.html.Html;
|
||||
import com.djrapitops.plugin.api.TimeAmount;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Class in charge of Server health analysis.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class HealthNotes {
|
||||
|
||||
private final List<String> notes;
|
||||
private final AnalysisData analysisData;
|
||||
private final SortedMap<Long, Map<String, Set<UUID>>> activityData;
|
||||
private final List<TPS> tpsDataMonth;
|
||||
private final long now;
|
||||
private final long fourWeeksAgo;
|
||||
private double serverHealth;
|
||||
|
||||
public HealthNotes(AnalysisData analysisData, SortedMap<Long, Map<String, Set<UUID>>> activityData, List<TPS> tpsDataMonth, long now) {
|
||||
this.notes = new ArrayList<>();
|
||||
serverHealth = 100.0;
|
||||
|
||||
this.analysisData = analysisData;
|
||||
this.activityData = activityData;
|
||||
this.tpsDataMonth = tpsDataMonth;
|
||||
this.now = now;
|
||||
this.fourWeeksAgo = now - TimeAmount.WEEK.ms() * 4L;
|
||||
}
|
||||
|
||||
public void analyzeHealth() {
|
||||
activityChangeNote();
|
||||
newPlayerNote();
|
||||
activePlayerPlaytimeChange();
|
||||
lowPerformance();
|
||||
}
|
||||
|
||||
public String parse() {
|
||||
StringBuilder healthNoteBuilder = new StringBuilder();
|
||||
for (String healthNote : notes) {
|
||||
healthNoteBuilder.append(healthNote);
|
||||
}
|
||||
return healthNoteBuilder.toString();
|
||||
}
|
||||
|
||||
public double getServerHealth() {
|
||||
return serverHealth;
|
||||
}
|
||||
|
||||
private void activityChangeNote() {
|
||||
Map<String, Set<UUID>> activityNow = activityData.getOrDefault(now, new HashMap<>());
|
||||
Set<UUID> veryActiveNow = activityNow.getOrDefault("Very Active", new HashSet<>());
|
||||
Set<UUID> activeNow = activityNow.getOrDefault("Active", new HashSet<>());
|
||||
Set<UUID> regularNow = activityNow.getOrDefault("Regular", new HashSet<>());
|
||||
|
||||
Map<String, Set<UUID>> activityFourWAgo = activityData.getOrDefault(fourWeeksAgo, new HashMap<>());
|
||||
Set<UUID> veryActiveFWAG = activityFourWAgo.getOrDefault("Very Active", new HashSet<>());
|
||||
Set<UUID> activeFWAG = activityFourWAgo.getOrDefault("Active", new HashSet<>());
|
||||
Set<UUID> regularFWAG = activityFourWAgo.getOrDefault("Regular", new HashSet<>());
|
||||
|
||||
Set<UUID> regularRemainCompareSet = new HashSet<>(regularFWAG);
|
||||
regularRemainCompareSet.addAll(activeFWAG);
|
||||
regularRemainCompareSet.addAll(veryActiveFWAG);
|
||||
|
||||
int activeFWAGNum = regularRemainCompareSet.size();
|
||||
regularRemainCompareSet.removeAll(regularNow);
|
||||
regularRemainCompareSet.removeAll(activeNow);
|
||||
regularRemainCompareSet.removeAll(veryActiveNow);
|
||||
int notRegularAnymore = regularRemainCompareSet.size();
|
||||
int remain = activeFWAGNum - notRegularAnymore;
|
||||
double percRemain = remain * 100.0 / activeFWAGNum;
|
||||
|
||||
int newActive = getNewActive(veryActiveNow, activeNow, regularNow, veryActiveFWAG, activeFWAG, regularFWAG);
|
||||
|
||||
int change = newActive - notRegularAnymore;
|
||||
|
||||
String remainNote = "";
|
||||
if (activeFWAGNum != 0) {
|
||||
remainNote = " ";
|
||||
if (percRemain > 50) {
|
||||
remainNote += Html.GREEN_THUMB.parse();
|
||||
} else if (percRemain > 20) {
|
||||
remainNote += Html.YELLOW_FLAG.parse();
|
||||
} else {
|
||||
remainNote += Html.RED_WARN.parse();
|
||||
serverHealth -= 2.5;
|
||||
}
|
||||
|
||||
remainNote += " " + FormatUtils.cutDecimals(percRemain) + "% of regular players have remained active ("
|
||||
+ remain + "/" + activeFWAGNum + ")";
|
||||
}
|
||||
if (change > 0) {
|
||||
notes.add(
|
||||
"<p>" + Html.GREEN_THUMB.parse() + " Number of regular players has increased (+" + change + ")<br>" +
|
||||
remainNote + "</p>");
|
||||
} else if (change == 0) {
|
||||
notes.add(
|
||||
"<p>" + Html.GREEN_THUMB.parse() + " Number of regular players has stayed the same (+" + change + ")<br>" +
|
||||
remainNote + "</p>");
|
||||
} else if (change > -20) {
|
||||
notes.add(
|
||||
"<p>" + Html.YELLOW_FLAG.parse() + " Number of regular players has decreased (" + change + ")<br>" +
|
||||
remainNote + "</p>");
|
||||
serverHealth -= 5;
|
||||
} else {
|
||||
notes.add(
|
||||
"<p>" + Html.RED_WARN.parse() + " Number of regular players has decreased (" + change + ")<br>" +
|
||||
remainNote + "</p>");
|
||||
serverHealth -= 10;
|
||||
}
|
||||
}
|
||||
|
||||
private void newPlayerNote() {
|
||||
double avgOnlineOnRegister = MathUtils.averageInt(analysisData.getStickyMonthData().stream().map(StickyData::getOnlineOnJoin));
|
||||
if (avgOnlineOnRegister >= 1) {
|
||||
notes.add("<p>" + Html.GREEN_THUMB.parse() + " New Players have players to play with when they join ("
|
||||
+ FormatUtils.cutDecimals(avgOnlineOnRegister) + " on average)</p>");
|
||||
} else {
|
||||
notes.add("<p>" + Html.YELLOW_FLAG.parse() + " New Players may not have players to play with when they join ("
|
||||
+ FormatUtils.cutDecimals(avgOnlineOnRegister) + " on average)</p>");
|
||||
serverHealth -= 5;
|
||||
}
|
||||
|
||||
long newM = analysisData.value("newM");
|
||||
long stuckPerM = analysisData.value("stuckPerM");
|
||||
|
||||
if (newM != 0) {
|
||||
double stuckPerc = MathUtils.averageDouble(stuckPerM, newM) * 100;
|
||||
if (stuckPerc >= 25) {
|
||||
notes.add("<p>" + Html.GREEN_THUMB.parse() + " " + FormatUtils.cutDecimals(stuckPerc)
|
||||
+ "% of new players have stuck around (" + stuckPerM + "/" + newM + ")</p>");
|
||||
} else {
|
||||
notes.add("<p>" + Html.YELLOW_FLAG.parse() + " " + FormatUtils.cutDecimals(stuckPerc)
|
||||
+ "% of new players have stuck around (" + stuckPerM + "/" + newM + ")</p>");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void activePlayerPlaytimeChange() {
|
||||
List<PlayerProfile> currentActivePlayers = analysisData.getPlayers().stream()
|
||||
.filter(player -> player.getActivityIndex(now).getValue() >= 1.75)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
long twoWeeksAgo = now - TimeAmount.WEEK.ms() * 2L;
|
||||
|
||||
long totalFourToTwoWeeks = 0;
|
||||
long totalLastTwoWeeks = 0;
|
||||
for (PlayerProfile activePlayer : currentActivePlayers) {
|
||||
totalFourToTwoWeeks += activePlayer.getPlaytime(analysisData.value("monthAgo"), twoWeeksAgo);
|
||||
totalLastTwoWeeks += activePlayer.getPlaytime(twoWeeksAgo, now);
|
||||
}
|
||||
int currentlyActive = currentActivePlayers.size();
|
||||
if (currentlyActive != 0) {
|
||||
long avgFourToTwoWeeks = MathUtils.averageLong(totalFourToTwoWeeks, currentlyActive);
|
||||
long avgLastTwoWeeks = MathUtils.averageLong(totalLastTwoWeeks, currentlyActive);
|
||||
String avgLastTwoWeeksString = FormatUtils.formatTimeAmount(avgLastTwoWeeks);
|
||||
String avgFourToTwoWeeksString = FormatUtils.formatTimeAmount(avgFourToTwoWeeks);
|
||||
if (avgFourToTwoWeeks >= avgLastTwoWeeks) {
|
||||
notes.add("<p>" + Html.GREEN_THUMB.parse() + " Active players seem to have things to do (Played "
|
||||
+ avgLastTwoWeeksString + " vs " + avgFourToTwoWeeksString
|
||||
+ ", last two weeks vs weeks 2-4)</p>");
|
||||
} else if (avgFourToTwoWeeks - avgLastTwoWeeks > TimeAmount.HOUR.ms() * 2L) {
|
||||
notes.add("<p>" + Html.RED_WARN.parse() + " Active players might be running out of things to do (Played "
|
||||
+ avgLastTwoWeeksString + " vs " + avgFourToTwoWeeksString
|
||||
+ ", last two weeks vs weeks 2-4)</p>");
|
||||
serverHealth -= 5;
|
||||
} else {
|
||||
notes.add("<p>" + Html.YELLOW_FLAG.parse() + " Active players might be running out of things to do (Played "
|
||||
+ avgLastTwoWeeksString + " vs " + avgFourToTwoWeeksString
|
||||
+ ", last two weeks vs weeks 2-4)</p>");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void lowPerformance() {
|
||||
long serverDownTime = ServerProfile.serverDownTime(tpsDataMonth);
|
||||
double aboveThreshold = ServerProfile.aboveLowThreshold(tpsDataMonth);
|
||||
long tpsSpikeMonth = analysisData.value("tpsSpikeMonth");
|
||||
|
||||
String avgLowThresholdString = " ";
|
||||
if (aboveThreshold >= 0.96) {
|
||||
avgLowThresholdString += Html.GREEN_THUMB.parse();
|
||||
} else if (aboveThreshold >= 0.9) {
|
||||
avgLowThresholdString += Html.YELLOW_FLAG.parse();
|
||||
serverHealth *= 0.9;
|
||||
} else {
|
||||
avgLowThresholdString += Html.RED_WARN.parse();
|
||||
serverHealth *= 0.6;
|
||||
}
|
||||
avgLowThresholdString += " Average TPS was above Low Threshold "
|
||||
+ FormatUtils.cutDecimals(aboveThreshold * 100.0) + "% of the time";
|
||||
|
||||
if (tpsSpikeMonth <= 5) {
|
||||
notes.add("<p>" + Html.GREEN_THUMB.parse()
|
||||
+ " Average TPS dropped below Low Threshold (" + Settings.THEME_GRAPH_TPS_THRESHOLD_MED.getNumber() + ")" +
|
||||
" " + tpsSpikeMonth + " times<br>" +
|
||||
avgLowThresholdString + "</p>");
|
||||
} else if (tpsSpikeMonth <= 25) {
|
||||
notes.add("<p>" + Html.YELLOW_FLAG.parse()
|
||||
+ " Average TPS dropped below Low Threshold (" + Settings.THEME_GRAPH_TPS_THRESHOLD_MED.getNumber() + ")" +
|
||||
" " + tpsSpikeMonth + " times<br>" +
|
||||
avgLowThresholdString + "</p>");
|
||||
serverHealth *= 0.95;
|
||||
} else {
|
||||
notes.add("<p>" + Html.RED_WARN.parse()
|
||||
+ " Average TPS dropped below Low Threshold (" + Settings.THEME_GRAPH_TPS_THRESHOLD_MED.getNumber() + ")" +
|
||||
" " + tpsSpikeMonth + " times<br>" +
|
||||
avgLowThresholdString + "</p>");
|
||||
serverHealth *= 0.8;
|
||||
}
|
||||
|
||||
if (serverDownTime <= TimeAmount.DAY.ms()) {
|
||||
notes.add("<p>" + Html.GREEN_THUMB.parse() + " Total Server downtime (No Data) was "
|
||||
+ FormatUtils.formatTimeAmount(serverDownTime) + "</p>");
|
||||
} else if (serverDownTime <= TimeAmount.WEEK.ms()) {
|
||||
notes.add("<p>" + Html.YELLOW_FLAG.parse() + " Total Server downtime (No Data) was "
|
||||
+ FormatUtils.formatTimeAmount(serverDownTime) + "</p>");
|
||||
serverHealth *= (TimeAmount.WEEK.ms() - serverDownTime) * 1.0 / TimeAmount.WEEK.ms();
|
||||
} else {
|
||||
notes.add("<p>" + Html.RED_WARN.parse() + " Total Server downtime (No Data) was "
|
||||
+ FormatUtils.formatTimeAmount(serverDownTime) + "</p>");
|
||||
serverHealth *= (TimeAmount.MONTH.ms() - serverDownTime) * 1.0 / TimeAmount.MONTH.ms();
|
||||
}
|
||||
}
|
||||
|
||||
private int getNewActive(Set<UUID> veryActiveNow, Set<UUID> activeNow, Set<UUID> regularNow, Set<UUID> veryActiveFWAG, Set<UUID> activeFWAG, Set<UUID> regularFWAG) {
|
||||
Set<UUID> regularNewCompareSet = new HashSet<>(regularNow);
|
||||
regularNewCompareSet.addAll(activeNow);
|
||||
regularNewCompareSet.addAll(veryActiveNow);
|
||||
regularNewCompareSet.removeAll(regularFWAG);
|
||||
regularNewCompareSet.removeAll(activeFWAG);
|
||||
regularNewCompareSet.removeAll(veryActiveFWAG);
|
||||
return regularNewCompareSet.size();
|
||||
}
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
package com.djrapitops.plan.data.calculation;
|
||||
|
||||
import com.djrapitops.plugin.utilities.Verify;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Extending objects should represent, add together and analyse data.
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @since 3.5.2
|
||||
*/
|
||||
public abstract class RawData {
|
||||
|
||||
private final Map<String, Serializable> replaceMap;
|
||||
|
||||
/**
|
||||
* Only used by subclasses.
|
||||
*/
|
||||
public RawData() {
|
||||
replaceMap = new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds values from an existing replaceMap.
|
||||
*
|
||||
* @param values Map that contains place-holders.
|
||||
*/
|
||||
public void addValues(Map<String, Serializable> values) {
|
||||
Verify.nullCheck(values);
|
||||
replaceMap.putAll(values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a placeholder to the replaceMap.
|
||||
*
|
||||
* @param placeholder placeholder, without prefix and suffix
|
||||
* @param value Any value the placeholder should be replaced with.
|
||||
*/
|
||||
public void addValue(String placeholder, Serializable value) {
|
||||
replaceMap.put(placeholder, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to get the placeholders and values.
|
||||
*
|
||||
* @return Map containing the placeholders and values.
|
||||
*/
|
||||
public Map<String, Serializable> getReplaceMap() {
|
||||
return replaceMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to get the value for a placeholder without the placeholder prefix and suffix.
|
||||
*
|
||||
* @param key placeholder name without ${ and }
|
||||
* @return Value the placeholder should be replaced with or null.
|
||||
*/
|
||||
public Serializable get(String key) {
|
||||
return replaceMap.get(key);
|
||||
}
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.data.container;
|
||||
|
||||
import com.djrapitops.plan.data.Actions;
|
||||
import com.djrapitops.plan.utilities.FormatUtils;
|
||||
import com.djrapitops.plan.utilities.html.Html;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Class that represents an action made by a player.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class Action {
|
||||
private final long date;
|
||||
private final Actions doneAction;
|
||||
private final String additionalInfo;
|
||||
private int serverID;
|
||||
|
||||
public Action(long date, Actions doneAction, String additionalInfo) {
|
||||
this.date = date;
|
||||
this.doneAction = doneAction;
|
||||
this.additionalInfo = additionalInfo;
|
||||
}
|
||||
|
||||
public Action(long date, Actions doneAction, String additionalInfo, int serverID) {
|
||||
this.date = date;
|
||||
this.doneAction = doneAction;
|
||||
this.additionalInfo = additionalInfo;
|
||||
this.serverID = serverID;
|
||||
}
|
||||
|
||||
public long getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public Actions getDoneAction() {
|
||||
return doneAction;
|
||||
}
|
||||
|
||||
public String getAdditionalInfo() {
|
||||
return additionalInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can only be used on Action classes returned by the ActionsTable.
|
||||
*
|
||||
* @return ID of the server the action occurred on.
|
||||
*/
|
||||
public int getServerID() {
|
||||
return serverID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Action action = (Action) o;
|
||||
return date == action.date &&
|
||||
serverID == action.serverID &&
|
||||
doneAction == action.doneAction &&
|
||||
Objects.equals(additionalInfo, action.additionalInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(date, doneAction, additionalInfo, serverID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Html.TABLELINE_3.parse(FormatUtils.formatTimeStampYear(date), doneAction.toString(), additionalInfo);
|
||||
}
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.data.container;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
/**
|
||||
* Data class that contains information about IP and Geolocation.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class GeoInfo {
|
||||
|
||||
private final String ip;
|
||||
private final String geolocation;
|
||||
private final long lastUsed;
|
||||
|
||||
public GeoInfo(String ip, String geolocation, long lastUsed) {
|
||||
this.ip = ip;
|
||||
this.geolocation = geolocation;
|
||||
this.lastUsed = lastUsed;
|
||||
}
|
||||
|
||||
public String getIp() {
|
||||
return ip;
|
||||
}
|
||||
|
||||
public String getGeolocation() {
|
||||
return geolocation;
|
||||
}
|
||||
|
||||
public long getLastUsed() {
|
||||
return lastUsed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
GeoInfo geoInfo = (GeoInfo) o;
|
||||
return Objects.equal(ip, geoInfo.ip) &&
|
||||
Objects.equal(geolocation, geoInfo.geolocation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(ip, geolocation);
|
||||
}
|
||||
}
|
@ -1,88 +0,0 @@
|
||||
package com.djrapitops.plan.data.container;
|
||||
|
||||
import com.djrapitops.plan.data.Actions;
|
||||
import com.djrapitops.plan.system.cache.DataCache;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* This class is used to store data about a player kill inside the UserInfo
|
||||
* object.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class PlayerKill {
|
||||
|
||||
private final UUID victim;
|
||||
private final long time;
|
||||
private final String weapon;
|
||||
|
||||
/**
|
||||
* Creates a PlayerKill object with given parameters.
|
||||
*
|
||||
* @param victim UUID of the victim.
|
||||
* @param weapon Weapon used.
|
||||
* @param time Epoch millisecond at which the kill occurred.
|
||||
*/
|
||||
public PlayerKill(UUID victim, String weapon, long time) {
|
||||
this.victim = victim;
|
||||
this.weapon = weapon;
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the victim's UUID.
|
||||
*
|
||||
* @return UUID of the victim.
|
||||
*/
|
||||
public UUID getVictim() {
|
||||
return victim;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Epoch millisecond the kill occurred.
|
||||
*
|
||||
* @return long in ms.
|
||||
*/
|
||||
public long getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Weapon used as string.
|
||||
*
|
||||
* @return For example DIAMOND_SWORD
|
||||
*/
|
||||
public String getWeapon() {
|
||||
return weapon;
|
||||
}
|
||||
|
||||
public Action convertToAction() {
|
||||
String name = DataCache.getInstance().getName(victim);
|
||||
return new Action(time, Actions.KILLED, name + " with " + weapon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
PlayerKill that = (PlayerKill) o;
|
||||
return time == that.time &&
|
||||
Objects.equals(victim, that.victim) &&
|
||||
Objects.equals(weapon, that.weapon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(victim, time, weapon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PlayerKill{" +
|
||||
"victim=" + victim + ", " +
|
||||
"time=" + time + ", " +
|
||||
"weapon='" + weapon + "'}";
|
||||
}
|
||||
}
|
@ -1,205 +0,0 @@
|
||||
package com.djrapitops.plan.data.container;
|
||||
|
||||
import com.djrapitops.plan.data.time.WorldTimes;
|
||||
import com.djrapitops.plan.utilities.MiscUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Object for storing various information about a player's play session.
|
||||
* <p>
|
||||
* Includes:
|
||||
* <ul>
|
||||
* <li>World and GameMode playtimes</li>
|
||||
* <li>Player and Mob kills</li>
|
||||
* <li>Deaths</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* Following data can be derived from Sessions in the database (Between any time span):
|
||||
* <ul>
|
||||
* <li>Playtime</li>
|
||||
* <li>LoginTimes</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class Session {
|
||||
|
||||
private final long sessionStart;
|
||||
private Integer sessionID;
|
||||
private WorldTimes worldTimes;
|
||||
private long sessionEnd;
|
||||
private List<PlayerKill> playerKills;
|
||||
private int mobKills;
|
||||
private int deaths;
|
||||
|
||||
/**
|
||||
* Creates a new session with given start and end of -1.
|
||||
*
|
||||
* @param sessionStart Epoch millisecond the session was started.
|
||||
*/
|
||||
public Session(long sessionStart, String world, String gm) {
|
||||
this.worldTimes = new WorldTimes(world, gm);
|
||||
this.sessionStart = sessionStart;
|
||||
this.sessionEnd = -1;
|
||||
playerKills = new ArrayList<>();
|
||||
mobKills = 0;
|
||||
deaths = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-Creates a session data object for viewing.
|
||||
*
|
||||
* @param sessionStart Epoch millisecond the session was started.
|
||||
* @param sessionEnd Epoch millisecond the session ended.
|
||||
*/
|
||||
public Session(int id, long sessionStart, long sessionEnd, int mobKills, int deaths) {
|
||||
this.sessionID = id;
|
||||
this.sessionStart = sessionStart;
|
||||
this.sessionEnd = sessionEnd;
|
||||
this.worldTimes = new WorldTimes(new HashMap<>());
|
||||
this.playerKills = new ArrayList<>();
|
||||
this.mobKills = mobKills;
|
||||
this.deaths = deaths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends the session with given end point.
|
||||
* <p>
|
||||
* (Changes the end to the parameter.).
|
||||
*
|
||||
* @param endOfSession Epoch millisecond the session ended.
|
||||
*/
|
||||
public void endSession(long endOfSession) {
|
||||
sessionEnd = endOfSession;
|
||||
worldTimes.updateState(endOfSession);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates WorldTimes state.
|
||||
*
|
||||
* @param world World Name the player has moved to
|
||||
* @param gm GameMode the player is in.
|
||||
* @param time Epoch ms of the event.
|
||||
*/
|
||||
public void changeState(String world, String gm, long time) {
|
||||
worldTimes.updateState(world, gm, time);
|
||||
}
|
||||
|
||||
public void playerKilled(PlayerKill kill) {
|
||||
playerKills.add(kill);
|
||||
}
|
||||
|
||||
public void mobKilled() {
|
||||
mobKills++;
|
||||
}
|
||||
|
||||
public void died() {
|
||||
deaths++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the length of the session in milliseconds.
|
||||
*
|
||||
* @return Long in ms.
|
||||
*/
|
||||
public long getLength() {
|
||||
if (sessionEnd == -1) {
|
||||
return MiscUtils.getTime() - sessionStart;
|
||||
}
|
||||
return sessionEnd - sessionStart;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the start of the session.
|
||||
*
|
||||
* @return Epoch millisecond the session started.
|
||||
*/
|
||||
public long getSessionStart() {
|
||||
return sessionStart;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the end of the session.
|
||||
*
|
||||
* @return Epoch millisecond the session ended.
|
||||
*/
|
||||
public long getSessionEnd() {
|
||||
return sessionEnd;
|
||||
}
|
||||
|
||||
public WorldTimes getWorldTimes() {
|
||||
return worldTimes;
|
||||
}
|
||||
|
||||
public void setWorldTimes(WorldTimes worldTimes) {
|
||||
this.worldTimes = worldTimes;
|
||||
}
|
||||
|
||||
public List<PlayerKill> getPlayerKills() {
|
||||
return playerKills;
|
||||
}
|
||||
|
||||
public void setPlayerKills(List<PlayerKill> playerKills) {
|
||||
this.playerKills = playerKills;
|
||||
}
|
||||
|
||||
public int getMobKills() {
|
||||
return mobKills;
|
||||
}
|
||||
|
||||
public int getDeaths() {
|
||||
return deaths;
|
||||
}
|
||||
|
||||
public boolean isFetchedFromDB() {
|
||||
return sessionID != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to get the ID of the session in the Database.
|
||||
*
|
||||
* @return ID if present.
|
||||
* @throws NullPointerException if Session was not fetched from DB. Condition using {@code isFetchedFromDB}
|
||||
*/
|
||||
public int getSessionID() {
|
||||
return sessionID != null ? sessionID : -1;
|
||||
}
|
||||
|
||||
public void setSessionID(int sessionID) {
|
||||
this.sessionID = sessionID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Session session = (Session) o;
|
||||
return sessionStart == session.sessionStart &&
|
||||
sessionEnd == session.sessionEnd &&
|
||||
mobKills == session.mobKills &&
|
||||
deaths == session.deaths &&
|
||||
Objects.equals(worldTimes, session.worldTimes) &&
|
||||
Objects.equals(playerKills, session.playerKills);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(sessionStart, sessionID, worldTimes, sessionEnd, playerKills, mobKills, deaths);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Session{" +
|
||||
"sessionStart=" + sessionStart + ", " +
|
||||
"sessionID=" + sessionID + ", " +
|
||||
"worldTimes=" + worldTimes + ", " +
|
||||
"sessionEnd=" + sessionEnd + ", " +
|
||||
"playerKills=" + playerKills + ", " +
|
||||
"mobKills=" + mobKills + ", " +
|
||||
"deaths=" + deaths + '}';
|
||||
}
|
||||
}
|
@ -1,94 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.data.container;
|
||||
|
||||
import com.djrapitops.plan.data.Actions;
|
||||
import com.djrapitops.plan.data.PlayerProfile;
|
||||
import com.djrapitops.plugin.api.TimeAmount;
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class StickyData {
|
||||
private final double activityIndex;
|
||||
private Integer messagesSent;
|
||||
private Integer onlineOnJoin;
|
||||
|
||||
public StickyData(PlayerProfile player) {
|
||||
activityIndex = player.getActivityIndex(player.getRegistered() + TimeAmount.DAY.ms()).getValue();
|
||||
loadActionVariables(player.getActions());
|
||||
}
|
||||
|
||||
private void loadActionVariables(List<Action> actions) {
|
||||
for (Action action : actions) {
|
||||
try {
|
||||
if (messagesSent == null && action.getDoneAction() == Actions.FIRST_LOGOUT) {
|
||||
messagesSent = loadSentMessages(action);
|
||||
}
|
||||
if (onlineOnJoin == null && action.getDoneAction() == Actions.FIRST_SESSION) {
|
||||
onlineOnJoin = loadOnlineOnJoin(action);
|
||||
}
|
||||
} catch (IllegalArgumentException ignore) {
|
||||
/* continue */
|
||||
}
|
||||
}
|
||||
setDefaultValuesIfNull();
|
||||
}
|
||||
|
||||
private void setDefaultValuesIfNull() {
|
||||
if (messagesSent == null) {
|
||||
messagesSent = 0;
|
||||
}
|
||||
if (onlineOnJoin == null) {
|
||||
onlineOnJoin = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private int loadOnlineOnJoin(Action action) {
|
||||
String additionalInfo = action.getAdditionalInfo();
|
||||
String[] split = additionalInfo.split(" ");
|
||||
if (split.length == 3) {
|
||||
return Integer.parseInt(split[1]);
|
||||
}
|
||||
throw new IllegalArgumentException("Improper Action");
|
||||
}
|
||||
|
||||
private int loadSentMessages(Action action) {
|
||||
String additionalInfo = action.getAdditionalInfo();
|
||||
String[] split = additionalInfo.split(": ");
|
||||
if (split.length == 2) {
|
||||
return Integer.parseInt(split[1]);
|
||||
}
|
||||
throw new IllegalArgumentException("Improper Action");
|
||||
}
|
||||
|
||||
public double distance(StickyData data) {
|
||||
double num = 0;
|
||||
num += Math.abs(data.activityIndex - activityIndex) * 2.0;
|
||||
num += Math.abs(data.onlineOnJoin - onlineOnJoin) / 10.0;
|
||||
num += Math.abs(data.messagesSent - messagesSent) / 10.0;
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
StickyData that = (StickyData) o;
|
||||
return Double.compare(that.activityIndex, activityIndex) == 0 &&
|
||||
Objects.equal(messagesSent, that.messagesSent) &&
|
||||
Objects.equal(onlineOnJoin, that.onlineOnJoin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(activityIndex, messagesSent, onlineOnJoin);
|
||||
}
|
||||
|
||||
public int getOnlineOnJoin() {
|
||||
return onlineOnJoin;
|
||||
}
|
||||
}
|
@ -1,140 +0,0 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package com.djrapitops.plan.data.container;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Class containing single datapoint of TPS / Players online / CPU Usage / Used Memory / Entity Count / Chunks loaded.
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @since 3.5.0
|
||||
*/
|
||||
public class TPS {
|
||||
|
||||
private final long date;
|
||||
private final double ticksPerSecond;
|
||||
private final int players;
|
||||
private final double cpuUsage;
|
||||
private final long usedMemory;
|
||||
private final int entityCount;
|
||||
private final int chunksLoaded;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param date time of the TPS calculation.
|
||||
* @param ticksPerSecond average ticksPerSecond for the last minute.
|
||||
* @param players players for the minute.
|
||||
* @param cpuUsage CPU usage for the minute
|
||||
* @param usedMemory used memory at the time of fetching
|
||||
* @param entityCount amount of entities at the time of fetching
|
||||
* @param chunksLoaded amount of chunks loaded at the time of fetching
|
||||
*/
|
||||
public TPS(long date, double ticksPerSecond, int players, double cpuUsage, long usedMemory, int entityCount, int chunksLoaded) {
|
||||
this.date = date;
|
||||
this.ticksPerSecond = ticksPerSecond;
|
||||
this.players = players;
|
||||
this.cpuUsage = cpuUsage;
|
||||
this.usedMemory = usedMemory;
|
||||
this.entityCount = entityCount;
|
||||
this.chunksLoaded = chunksLoaded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the time of the average calculation.
|
||||
*
|
||||
* @return epoch ms.
|
||||
*/
|
||||
public long getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the average ticksPerSecond for the minute.
|
||||
*
|
||||
* @return 0-20 double
|
||||
*/
|
||||
public double getTicksPerSecond() {
|
||||
return ticksPerSecond;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the player for the time, when the data was fetched.
|
||||
*
|
||||
* @return Players online.
|
||||
*/
|
||||
public int getPlayers() {
|
||||
return players;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the average CPU Usage for the minute
|
||||
*
|
||||
* @return 0-100 double
|
||||
*/
|
||||
public double getCPUUsage() {
|
||||
return cpuUsage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the used memory for the time, when the data was fetched.
|
||||
*
|
||||
* @return Used Memory in Megabyte
|
||||
*/
|
||||
public long getUsedMemory() {
|
||||
return usedMemory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the amount of entities for the time, when the data was fetched
|
||||
*
|
||||
* @return Amount of entities
|
||||
*/
|
||||
public int getEntityCount() {
|
||||
return entityCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the amount of chunks loaded for the time, when the data was fetched
|
||||
*
|
||||
* @return Amount of chunks loaded
|
||||
*/
|
||||
public int getChunksLoaded() {
|
||||
return chunksLoaded;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
TPS tps = (TPS) o;
|
||||
return date == tps.date &&
|
||||
Double.compare(tps.ticksPerSecond, ticksPerSecond) == 0 &&
|
||||
players == tps.players &&
|
||||
Double.compare(tps.cpuUsage, cpuUsage) == 0 &&
|
||||
usedMemory == tps.usedMemory &&
|
||||
entityCount == tps.entityCount &&
|
||||
chunksLoaded == tps.chunksLoaded;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(date, ticksPerSecond, players, cpuUsage, usedMemory, entityCount, chunksLoaded);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TPS{" +
|
||||
"date=" + date + ", " +
|
||||
"ticksPerSecond=" + ticksPerSecond + ", " +
|
||||
"players=" + players + ", " +
|
||||
"cpuUsage=" + cpuUsage + ", " +
|
||||
"usedMemory=" + usedMemory + ", " +
|
||||
"entityCount=" + entityCount + ", " +
|
||||
"chunksLoaded=" + chunksLoaded + '}';
|
||||
}
|
||||
}
|
@ -1,90 +0,0 @@
|
||||
package com.djrapitops.plan.data.container;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Used for storing information of players after it has been fetched.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class UserInfo {
|
||||
|
||||
private final UUID uuid;
|
||||
private String name;
|
||||
private long registered;
|
||||
private long lastSeen;
|
||||
private boolean banned;
|
||||
private boolean opped;
|
||||
|
||||
public UserInfo(UUID uuid) {
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
public UserInfo(UUID uuid, String name, long registered, boolean opped, boolean banned) {
|
||||
this.uuid = uuid;
|
||||
this.name = name;
|
||||
this.registered = registered;
|
||||
this.opped = opped;
|
||||
this.banned = banned;
|
||||
lastSeen = 0L;
|
||||
}
|
||||
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public long getRegistered() {
|
||||
return registered;
|
||||
}
|
||||
|
||||
public long getLastSeen() {
|
||||
return lastSeen;
|
||||
}
|
||||
|
||||
public void setLastSeen(long lastSeen) {
|
||||
this.lastSeen = lastSeen;
|
||||
}
|
||||
|
||||
public boolean isBanned() {
|
||||
return banned;
|
||||
}
|
||||
|
||||
public boolean isOpped() {
|
||||
return opped;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
UserInfo userInfo = (UserInfo) o;
|
||||
return registered == userInfo.registered &&
|
||||
lastSeen == userInfo.lastSeen &&
|
||||
banned == userInfo.banned &&
|
||||
opped == userInfo.opped &&
|
||||
Objects.equals(uuid, userInfo.uuid) &&
|
||||
Objects.equals(name, userInfo.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(uuid, name, registered, lastSeen, banned, opped);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "UserInfo{" +
|
||||
"uuid=" + uuid +
|
||||
", name='" + name + '\'' +
|
||||
", registered=" + registered +
|
||||
", lastSeen=" + lastSeen +
|
||||
", banned=" + banned +
|
||||
", opped=" + opped +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -1,97 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.data.container.builders;
|
||||
|
||||
import com.djrapitops.plan.data.container.TPS;
|
||||
|
||||
/**
|
||||
* Builder for TPS to make it easier to manage.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class TPSBuilder {
|
||||
|
||||
protected long date = 0;
|
||||
protected double ticksPerSecond = -1;
|
||||
protected int players = -1;
|
||||
protected double cpuUsage = -1;
|
||||
protected long usedMemory = -1;
|
||||
protected int entityCount = -1;
|
||||
protected int chunksLoaded = -1;
|
||||
|
||||
/**
|
||||
* Hides constructor.
|
||||
*/
|
||||
private TPSBuilder() {
|
||||
}
|
||||
|
||||
public static TPSBuilder.Date get() {
|
||||
return new TPSBuilder.Chunks();
|
||||
}
|
||||
|
||||
public TPS toTPS() {
|
||||
return new TPS(date, ticksPerSecond, players, cpuUsage, usedMemory, entityCount, chunksLoaded);
|
||||
}
|
||||
|
||||
public static class Date extends TPSBuilder {
|
||||
|
||||
public Ticks date(long date) {
|
||||
this.date = date;
|
||||
return (Ticks) this;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Ticks extends Date {
|
||||
|
||||
public Players tps(double tps) {
|
||||
ticksPerSecond = tps;
|
||||
return (Players) this;
|
||||
}
|
||||
|
||||
public Players skipTPS() {
|
||||
return (Players) this;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Players extends Ticks {
|
||||
|
||||
public CPU playersOnline(int online) {
|
||||
players = online;
|
||||
return (CPU) this;
|
||||
}
|
||||
}
|
||||
|
||||
public static class CPU extends Players {
|
||||
|
||||
public Memory usedCPU(double cpu) {
|
||||
cpuUsage = cpu;
|
||||
return (Memory) this;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Memory extends CPU {
|
||||
|
||||
public Entities usedMemory(long ram) {
|
||||
usedMemory = ram;
|
||||
return (Entities) this;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Entities extends Memory {
|
||||
|
||||
public Chunks entities(int count) {
|
||||
entityCount = count;
|
||||
return (Chunks) this;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Chunks extends Entities {
|
||||
|
||||
public TPSBuilder chunksLoaded(int chunksLoaded) {
|
||||
this.chunksLoaded = chunksLoaded;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.data.element;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Container used to parse data for Analysis page.
|
||||
* <p>
|
||||
* Similar to InspectContainer, but can contain data for each player for a bigger Player data table.
|
||||
* <p>
|
||||
* Can contain values: addValue("Total Examples", 1) parses into ("Total Examples: 1")
|
||||
* Html: addHtml(key, "{@code <html>}") parses into ("{@code <html>}")
|
||||
* Tables: addTable(key, TableContainer) parses into ("{@code <table>...</table}")
|
||||
* Player Data for a big table: {@code addTableData("header", Map<UUID, value>)} parses a new column to Plugin data player table.
|
||||
* <p>
|
||||
* Has methods for adding icons to Strings:
|
||||
* getWithIcon("text", "cube") parses into {@code "<i class=\"fa fa-cube\"></i> text"}
|
||||
* getWithColoredIcon("text", "cube", "light-green") parses into {@code "<i class=\"col-light-green fa fa-cube\"></i> text"}
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @see TableContainer
|
||||
* @see InspectContainer
|
||||
* @since 4.1.0
|
||||
*/
|
||||
public final class AnalysisContainer extends InspectContainer {
|
||||
|
||||
private TreeMap<String, Map<UUID, ? extends Serializable>> playerTableValues;
|
||||
|
||||
public AnalysisContainer() {
|
||||
playerTableValues = new TreeMap<>();
|
||||
}
|
||||
|
||||
public TreeMap<String, Map<UUID, ? extends Serializable>> getPlayerTableValues() {
|
||||
return playerTableValues;
|
||||
}
|
||||
|
||||
public void addPlayerTableValues(String columnName, Map<UUID, ? extends Serializable> values) {
|
||||
playerTableValues.put(columnName, values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return playerTableValues.isEmpty() && super.isEmpty();
|
||||
}
|
||||
|
||||
public boolean hasPlayerTableValues() {
|
||||
return !playerTableValues.isEmpty();
|
||||
}
|
||||
}
|
@ -1,88 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.data.element;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* Container used to parse data for Inspect page.
|
||||
* <p>
|
||||
* Can contain values: addValue("Total Examples", 1) parses into ("Total Examples: 1")
|
||||
* Html: addHtml(key, "{@code <html>}") parses into ("{@code <html>}")
|
||||
* Tables: addTable(key, TableContainer) parses into ("{@code <table>...</table}")
|
||||
* <p>
|
||||
* Has methods for adding icons to Strings:
|
||||
* getWithIcon("text", "cube") parses into {@code "<i class=\"fa fa-cube\"></i> text"}
|
||||
* getWithColoredIcon("text", "cube", "light-green") parses into {@code "<i class=\"col-light-green fa fa-cube\"></i> text"}
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @see TableContainer
|
||||
* @since 4.1.0
|
||||
*/
|
||||
public class InspectContainer {
|
||||
|
||||
protected TreeMap<String, String> values;
|
||||
protected TreeMap<String, String> html;
|
||||
protected TreeMap<String, TableContainer> tables;
|
||||
|
||||
public InspectContainer() {
|
||||
values = new TreeMap<>();
|
||||
html = new TreeMap<>();
|
||||
tables = new TreeMap<>();
|
||||
}
|
||||
|
||||
public final void addValue(String label, Serializable value) {
|
||||
values.put(label, value.toString());
|
||||
}
|
||||
|
||||
public final void addHtml(String key, String html) {
|
||||
this.html.put(key, html);
|
||||
}
|
||||
|
||||
public final void addTable(String key, TableContainer table) {
|
||||
tables.put(key, table);
|
||||
}
|
||||
|
||||
public final String parseHtml() {
|
||||
StringBuilder html = new StringBuilder();
|
||||
|
||||
if (!values.isEmpty()) {
|
||||
html.append("<div class=\"body\">");
|
||||
for (Map.Entry<String, String> entry : values.entrySet()) {
|
||||
html.append("<p>").append(entry.getKey()).append(": ").append(entry.getValue()).append("</p>");
|
||||
}
|
||||
html.append("</div>");
|
||||
}
|
||||
|
||||
for (Map.Entry<String, String> entry : this.html.entrySet()) {
|
||||
html.append(entry.getValue());
|
||||
}
|
||||
|
||||
for (Map.Entry<String, TableContainer> entry : tables.entrySet()) {
|
||||
html.append(entry.getValue().parseHtml());
|
||||
}
|
||||
|
||||
return html.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if InspectContainer has only values, and not HTML or Tables.
|
||||
*
|
||||
* @return true/false
|
||||
*/
|
||||
public final boolean hasOnlyValues() {
|
||||
return html.isEmpty() && tables.isEmpty();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return values.isEmpty() && html.isEmpty() && tables.isEmpty();
|
||||
}
|
||||
|
||||
public final boolean hasValues() {
|
||||
return !values.isEmpty();
|
||||
}
|
||||
}
|
@ -1,107 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.data.element;
|
||||
|
||||
import com.djrapitops.plan.utilities.FormatUtils;
|
||||
import com.djrapitops.plan.utilities.html.Html;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Container used for parsing Html tables.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class TableContainer {
|
||||
|
||||
private final String[] header;
|
||||
private List<Serializable[]> values;
|
||||
|
||||
private boolean jqueryDatatable;
|
||||
|
||||
private String color;
|
||||
|
||||
/**
|
||||
* Constructor, call with super(...).
|
||||
*
|
||||
* @param header Required: example {@code new TableContainer("1st", "2nd"} parses into {@code <thead><tr><th>1st</th><th>2nd</th></tr></thead}.
|
||||
*/
|
||||
public TableContainer(String... header) {
|
||||
this.header = header;
|
||||
values = new ArrayList<>();
|
||||
}
|
||||
|
||||
public TableContainer(boolean players, String... header) {
|
||||
this.header = FormatUtils.mergeArrays(new String[]{Html.FONT_AWESOME_ICON.parse("user") + " Player"}, header);
|
||||
values = new ArrayList<>();
|
||||
}
|
||||
|
||||
public final void addRow(Serializable... values) {
|
||||
this.values.add(values);
|
||||
}
|
||||
|
||||
public final String parseHtml() {
|
||||
return getTableHeader() +
|
||||
parseHeader() +
|
||||
parseBody() +
|
||||
"</table>";
|
||||
}
|
||||
|
||||
public final String parseBody() {
|
||||
StringBuilder body = new StringBuilder();
|
||||
|
||||
if (values.isEmpty()) {
|
||||
addRow("No Data");
|
||||
}
|
||||
for (Serializable[] row : values) {
|
||||
int maxIndex = row.length - 1;
|
||||
body.append("<tr>");
|
||||
for (int i = 0; i < header.length; i++) {
|
||||
body.append("<td>");
|
||||
if (i > maxIndex) {
|
||||
body.append("-");
|
||||
} else {
|
||||
body.append(row[i]);
|
||||
}
|
||||
body.append("</td>");
|
||||
}
|
||||
body.append("</tr>");
|
||||
}
|
||||
|
||||
return Html.TABLE_BODY.parse(body.toString());
|
||||
}
|
||||
|
||||
public final void setColor(String color) {
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public final String parseHeader() {
|
||||
StringBuilder header = new StringBuilder("<thead" + (color != null ? " class=\"bg-" + color + "\"" : "") + "><tr>");
|
||||
for (String title : this.header) {
|
||||
header.append("<th>").append(title).append("</th>");
|
||||
}
|
||||
header.append("</tr></thead>");
|
||||
return header.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make use of JQuery Datatables plugin.
|
||||
* <p>
|
||||
* If this is called, result of {@code parseHtml()} should be wrapped with {@code Html.PANEL.parse(Html.PANEL_BODY.parse(result))}
|
||||
*/
|
||||
public void useJqueryDataTables() {
|
||||
this.jqueryDatatable = true;
|
||||
}
|
||||
|
||||
private String getTableHeader() {
|
||||
if (jqueryDatatable) {
|
||||
return "<div class=\"table-responsive\">" + Html.TABLE_JQUERY.parse() + "</div>";
|
||||
} else {
|
||||
return Html.TABLE_SCROLL.parse();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.data.plugin;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Interface for PluginData objects that affect Ban state of players.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public interface BanData {
|
||||
|
||||
boolean isBanned(UUID uuid);
|
||||
|
||||
/**
|
||||
* Method that should return only banned players of the given UUIDs.
|
||||
*
|
||||
* @param uuids UUIDs to filter.
|
||||
* @return UUIDs from the collection uuids that are banned.
|
||||
*/
|
||||
Collection<UUID> filterBanned(Collection<UUID> uuids);
|
||||
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.data.plugin;
|
||||
|
||||
/**
|
||||
* Enum class for PluginData to estimate the required width of the contained items.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public enum ContainerSize {
|
||||
THIRD,
|
||||
TWO_THIRDS,
|
||||
WHOLE,
|
||||
TAB
|
||||
}
|
@ -1,108 +0,0 @@
|
||||
package com.djrapitops.plan.data.plugin;
|
||||
|
||||
import com.djrapitops.plan.Plan;
|
||||
import com.djrapitops.plan.data.element.InspectContainer;
|
||||
import com.djrapitops.plan.system.PlanSystem;
|
||||
import com.djrapitops.plan.system.SubSystem;
|
||||
import com.djrapitops.plugin.StaticHolder;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
import com.djrapitops.plugin.utilities.Verify;
|
||||
import com.djrapitops.pluginbridge.plan.Bridge;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Class responsible for hooking to other plugins and managing the %plugins%
|
||||
* placeholder on Analysis and Inspect pages.
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @since 2.6.0
|
||||
*/
|
||||
public class HookHandler implements SubSystem {
|
||||
|
||||
private final List<PluginData> additionalDataSources;
|
||||
private PluginsConfigSection configHandler;
|
||||
|
||||
public HookHandler() {
|
||||
additionalDataSources = new ArrayList<>();
|
||||
}
|
||||
|
||||
public static HookHandler getInstance() {
|
||||
HookHandler hookHandler = PlanSystem.getInstance().getHookHandler();
|
||||
Verify.nullCheck(hookHandler, () -> new IllegalStateException("Plugin Hooks were not initialized."));
|
||||
return hookHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
configHandler = new PluginsConfigSection();
|
||||
try {
|
||||
Bridge.hook(this);
|
||||
} catch (Exception e) {
|
||||
Log.toLog(this.getClass(), e);
|
||||
Log.error("Plan Plugin Bridge not included in the plugin jar.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disable() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new PluginData source to the list.
|
||||
* <p>
|
||||
* The plugin data will appear on Analysis and/or Inspect pages depending on
|
||||
* how the extending object is set up.
|
||||
* <p>
|
||||
* Refer to documentation on GitHub for more information.
|
||||
*
|
||||
* @param dataSource an object extending the PluginData class.
|
||||
*/
|
||||
public void addPluginDataSource(PluginData dataSource) {
|
||||
if (dataSource == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
StaticHolder.saveInstance(dataSource.getClass(), Plan.class);
|
||||
if (!configHandler.hasSection(dataSource)) {
|
||||
configHandler.createSection(dataSource);
|
||||
}
|
||||
if (configHandler.isEnabled(dataSource)) {
|
||||
Log.debug("Registered a new datasource: " + dataSource.getSourcePlugin());
|
||||
additionalDataSources.add(dataSource);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.toLog(this.getClass(), e);
|
||||
Log.error("Attempting to register PluginDataSource caused an exception.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to get all PluginData objects currently registered.
|
||||
*
|
||||
* @return List of PluginData objects.
|
||||
*/
|
||||
public List<PluginData> getAdditionalDataSources() {
|
||||
return additionalDataSources;
|
||||
}
|
||||
|
||||
public Map<PluginData, InspectContainer> getInspectContainersFor(UUID uuid) {
|
||||
List<PluginData> plugins = getAdditionalDataSources();
|
||||
Map<PluginData, InspectContainer> containers = new HashMap<>();
|
||||
for (PluginData pluginData : plugins) {
|
||||
InspectContainer inspectContainer = new InspectContainer();
|
||||
try {
|
||||
InspectContainer container = pluginData.getPlayerData(uuid, inspectContainer);
|
||||
if (container != null && !container.isEmpty()) {
|
||||
containers.put(pluginData, container);
|
||||
}
|
||||
} catch (Exception | NoClassDefFoundError | NoSuchFieldError | NoSuchMethodError e) {
|
||||
String sourcePlugin = pluginData.getSourcePlugin();
|
||||
Log.error("PluginData caused exception: " + sourcePlugin);
|
||||
Log.toLog(this.getClass().getName() + " " + sourcePlugin, e);
|
||||
}
|
||||
}
|
||||
return containers;
|
||||
}
|
||||
}
|
@ -1,80 +0,0 @@
|
||||
package com.djrapitops.plan.data.plugin;
|
||||
|
||||
import com.djrapitops.plan.data.element.AnalysisContainer;
|
||||
import com.djrapitops.plan.data.element.InspectContainer;
|
||||
import com.djrapitops.plan.utilities.html.Html;
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* This is an abstract class that can be used to add data from a plugin to the
|
||||
* "Plugins"-sections of Analysis and Inspect pages.
|
||||
* <p>
|
||||
* API-section of documentation has examples on the usage of this class and how
|
||||
* to register objects extending this class.
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @since 4.1.0
|
||||
*/
|
||||
public abstract class PluginData {
|
||||
|
||||
private final ContainerSize size;
|
||||
private final String sourcePlugin;
|
||||
|
||||
private String pluginIcon;
|
||||
private String iconColor;
|
||||
|
||||
public PluginData(ContainerSize size, String sourcePlugin) {
|
||||
this.size = size;
|
||||
this.sourcePlugin = sourcePlugin;
|
||||
}
|
||||
|
||||
public abstract InspectContainer getPlayerData(UUID uuid, InspectContainer fillThis) throws Exception;
|
||||
|
||||
public abstract AnalysisContainer getServerData(Collection<UUID> uuids, AnalysisContainer fillThis) throws Exception;
|
||||
|
||||
protected final void setPluginIcon(String pluginIcon) {
|
||||
this.pluginIcon = pluginIcon;
|
||||
}
|
||||
|
||||
protected final void setIconColor(String iconColor) {
|
||||
this.iconColor = iconColor;
|
||||
}
|
||||
|
||||
public final String parsePluginIcon() {
|
||||
return pluginIcon != null ? Html.FA_COLORED_ICON.parse((iconColor != null ? iconColor : "black"), pluginIcon) : Html.FONT_AWESOME_ICON.parse("cube");
|
||||
}
|
||||
|
||||
public final ContainerSize getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public final String getSourcePlugin() {
|
||||
return sourcePlugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
PluginData that = (PluginData) o;
|
||||
return size == that.size &&
|
||||
Objects.equal(sourcePlugin, that.sourcePlugin) &&
|
||||
Objects.equal(pluginIcon, that.pluginIcon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
return Objects.hashCode(size, sourcePlugin, pluginIcon);
|
||||
}
|
||||
|
||||
public final String getWithIcon(String text, String icon) {
|
||||
return getWithIcon(text, icon, "");
|
||||
}
|
||||
|
||||
public final String getWithIcon(String text, String icon, String color) {
|
||||
return Html.FA_COLORED_ICON.parse(color, icon) + " " + text;
|
||||
}
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
package com.djrapitops.plan.data.plugin;
|
||||
|
||||
import com.djrapitops.plan.system.settings.config.ConfigSystem;
|
||||
import com.djrapitops.plugin.api.config.ConfigNode;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Class responsible for generating and generating settings for PluginData
|
||||
* objects to the config.
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @since 3.5.0
|
||||
*/
|
||||
public class PluginsConfigSection {
|
||||
|
||||
public boolean hasSection(PluginData dataSource) {
|
||||
ConfigNode section = getPluginsSection();
|
||||
String pluginName = dataSource.getSourcePlugin();
|
||||
return section.getChildren().containsKey(pluginName)
|
||||
&& section.getConfigNode(pluginName).getChildren().containsKey("Enabled");
|
||||
}
|
||||
|
||||
private ConfigNode getPluginsSection() {
|
||||
return ConfigSystem.getConfig().getConfigNode("Plugins");
|
||||
}
|
||||
|
||||
public void createSection(PluginData dataSource) {
|
||||
ConfigNode section = getPluginsSection();
|
||||
String pluginName = dataSource.getSourcePlugin();
|
||||
|
||||
section.set(pluginName + ".Enabled", true);
|
||||
try {
|
||||
section.sort();
|
||||
section.save();
|
||||
} catch (IOException e) {
|
||||
Log.toLog(this.getClass(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEnabled(PluginData dataSource) {
|
||||
ConfigNode section = getPluginsSection();
|
||||
|
||||
String pluginName = dataSource.getSourcePlugin();
|
||||
return section.getBoolean(pluginName + ".Enabled");
|
||||
}
|
||||
}
|
@ -1,81 +0,0 @@
|
||||
package com.djrapitops.plan.data.time;
|
||||
|
||||
import com.djrapitops.plugin.utilities.Verify;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* TimeKeeper class that tracks the time spent in each GameMode based on Playtime.
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @since 3.6.0
|
||||
*/
|
||||
public class GMTimes extends TimeKeeper {
|
||||
|
||||
private static final String SURVIVAL = "SURVIVAL";
|
||||
private static final String CREATIVE = "CREATIVE";
|
||||
private static final String ADVENTURE = "ADVENTURE";
|
||||
private static final String SPECTATOR = "SPECTATOR";
|
||||
|
||||
public GMTimes(Map<String, Long> times, String lastState, long lastStateChange) {
|
||||
super(times, lastState, lastStateChange);
|
||||
}
|
||||
|
||||
public GMTimes(String lastState, long lastStateChange) {
|
||||
super(lastState, lastStateChange);
|
||||
}
|
||||
|
||||
public GMTimes(String lastState) {
|
||||
super(lastState);
|
||||
}
|
||||
|
||||
public GMTimes(Map<String, Long> times) {
|
||||
super(times);
|
||||
}
|
||||
|
||||
public GMTimes() {
|
||||
super();
|
||||
}
|
||||
|
||||
public static String[] getGMKeyArray() {
|
||||
return new String[]{SURVIVAL, CREATIVE, ADVENTURE, SPECTATOR};
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets times for all 4 gamemodes.
|
||||
* <p>
|
||||
* Give 1 - 4 parameters.
|
||||
* times starts from Survival, ends in Spectator.
|
||||
* <p>
|
||||
* Given too few parameters (Under 4, rest are set as 0L)
|
||||
* Extra parameters are ignored (Over 4)
|
||||
*
|
||||
* @param times 1-4 time parameters.
|
||||
* @throws IllegalArgumentException If any parameter is null.
|
||||
*/
|
||||
public void setAllGMTimes(long... times) {
|
||||
Verify.nullCheck(times);
|
||||
String[] gms = getGMKeyArray();
|
||||
int size = times.length;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (i >= size) {
|
||||
setTime(gms[i], 0L);
|
||||
} else {
|
||||
setTime(gms[i], times[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void resetTimes(long time) {
|
||||
resetState(SURVIVAL, time);
|
||||
resetState(CREATIVE);
|
||||
resetState(ADVENTURE);
|
||||
resetState(SPECTATOR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getState() {
|
||||
String state = super.getState();
|
||||
return state != null ? state : SURVIVAL;
|
||||
}
|
||||
}
|
@ -1,160 +0,0 @@
|
||||
package com.djrapitops.plan.data.time;
|
||||
|
||||
import com.djrapitops.plugin.utilities.Verify;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Abstract class for keeping track of time spent in each state.
|
||||
*/
|
||||
public abstract class TimeKeeper {
|
||||
/**
|
||||
* Keeps time of states.
|
||||
*/
|
||||
protected Map<String, Long> times;
|
||||
/**
|
||||
* Last State seen in
|
||||
*/
|
||||
protected String state;
|
||||
/**
|
||||
* Relates to Playtime Milliseconds.
|
||||
*/
|
||||
protected long lastStateChange;
|
||||
|
||||
public TimeKeeper(Map<String, Long> times, String lastState, long lastStateChange) {
|
||||
this.times = times;
|
||||
this.state = lastState;
|
||||
this.lastStateChange = lastStateChange;
|
||||
}
|
||||
|
||||
public TimeKeeper(String lastState, long lastStateChange) {
|
||||
this(new HashMap<>(), lastState, lastStateChange);
|
||||
}
|
||||
|
||||
public TimeKeeper(String lastState) {
|
||||
this(new HashMap<>(), lastState, 0L);
|
||||
}
|
||||
|
||||
public TimeKeeper(Map<String, Long> times) {
|
||||
this(times, null, 0);
|
||||
}
|
||||
|
||||
public TimeKeeper() {
|
||||
this(new HashMap<>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a specific time for a state.
|
||||
*
|
||||
* @param state State to set
|
||||
* @param time Time in ms the state has been active for
|
||||
* @throws IllegalArgumentException If given state is null
|
||||
*/
|
||||
public void setTime(String state, long time) {
|
||||
times.put(Verify.nullCheck(state), time);
|
||||
}
|
||||
|
||||
public void renameState(String state, String renameTo) {
|
||||
Verify.nullCheck(state, renameTo);
|
||||
Long time = times.get(state);
|
||||
if (time != null) {
|
||||
times.put(renameTo, time);
|
||||
times.remove(state);
|
||||
if (state.equals(this.state)) {
|
||||
this.state = renameTo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds time to the last state while updating the status of other parameters.
|
||||
*
|
||||
* @param newState New State seen in.
|
||||
* @param playTime Current Playtime.
|
||||
* @throws IllegalArgumentException If newState is null.
|
||||
*/
|
||||
public void changeState(String newState, long playTime) {
|
||||
Verify.nullCheck(newState);
|
||||
if (state == null) {
|
||||
state = newState;
|
||||
}
|
||||
Long currentTime = times.getOrDefault(state, 0L);
|
||||
long diff = playTime - lastStateChange;
|
||||
times.put(state, currentTime + Math.abs(diff));
|
||||
state = newState;
|
||||
lastStateChange = playTime;
|
||||
}
|
||||
|
||||
protected void resetState(String state) {
|
||||
times.remove(Verify.nullCheck(state));
|
||||
}
|
||||
|
||||
protected void resetState(String state, long time) {
|
||||
if (time > 0) {
|
||||
times.put(Verify.nullCheck(state), time);
|
||||
lastStateChange = time;
|
||||
this.state = state;
|
||||
} else {
|
||||
resetState(state);
|
||||
}
|
||||
}
|
||||
|
||||
public long getTime(String state) {
|
||||
return times.getOrDefault(state, 0L);
|
||||
}
|
||||
|
||||
public void addTime(String state, long time) {
|
||||
times.put(state, times.getOrDefault(state, 0L) + time);
|
||||
}
|
||||
|
||||
public long getTotal() {
|
||||
return times.values().stream().mapToLong(i -> i).sum();
|
||||
}
|
||||
|
||||
public Map<String, Long> getTimes() {
|
||||
return times;
|
||||
}
|
||||
|
||||
public void setTimes(Map<String, Long> times) {
|
||||
this.times = times;
|
||||
}
|
||||
|
||||
public String getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
public void setState(String state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public long getLastStateChange() {
|
||||
return lastStateChange;
|
||||
}
|
||||
|
||||
public void setLastStateChange(long lastStateChange) {
|
||||
this.lastStateChange = lastStateChange;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
TimeKeeper that = (TimeKeeper) o;
|
||||
return lastStateChange == that.lastStateChange &&
|
||||
Objects.equals(times, that.times) &&
|
||||
Objects.equals(state, that.state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(times, state, lastStateChange);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TimeKeeper{" + "times=" + times +
|
||||
", state='" + state + "', lastStateChange=" + lastStateChange + '}';
|
||||
}
|
||||
}
|
@ -1,175 +0,0 @@
|
||||
package com.djrapitops.plan.data.time;
|
||||
|
||||
import com.djrapitops.plan.utilities.MiscUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Class that tracks the time spent in each World based on GMTimes.
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public class WorldTimes {
|
||||
|
||||
private final Map<String, GMTimes> worldTimes;
|
||||
private String currentWorld;
|
||||
private String currentGamemode;
|
||||
|
||||
/**
|
||||
* Creates a new Empty WorldTimes object.
|
||||
*
|
||||
* @param startingWorld World to start the calculations at.
|
||||
* @param startingGM GameMode to start the calculations at.
|
||||
*/
|
||||
public WorldTimes(String startingWorld, String startingGM) {
|
||||
worldTimes = new HashMap<>();
|
||||
currentWorld = startingWorld;
|
||||
currentGamemode = startingGM;
|
||||
addWorld(startingWorld, startingGM, MiscUtils.getTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-Creates an existing WorldTimes object for viewing.
|
||||
*
|
||||
* @param times Map of each World's GMTimes object.
|
||||
*/
|
||||
public WorldTimes(Map<String, GMTimes> times) {
|
||||
worldTimes = times;
|
||||
}
|
||||
|
||||
private void addWorld(String worldName, String gameMode, long changeTime) {
|
||||
worldTimes.put(worldName, new GMTimes(gameMode, changeTime));
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the state at the end of the session.
|
||||
* Does not change world or GameMode.
|
||||
*
|
||||
* @param changeTime epoch ms session ended.
|
||||
*/
|
||||
public void updateState(long changeTime) {
|
||||
updateState(currentWorld, currentGamemode, changeTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the time status to match the new state.
|
||||
*
|
||||
* @param worldName World name of the world swapped to.
|
||||
* @param gameMode GameMode name of the gm swapped to.
|
||||
* @param changeTime Epoch ms the change occurred.
|
||||
*/
|
||||
public void updateState(String worldName, String gameMode, long changeTime) {
|
||||
GMTimes currentGMTimes = worldTimes.get(currentWorld);
|
||||
if (worldName.equals(currentWorld)) {
|
||||
currentGMTimes.changeState(gameMode, changeTime);
|
||||
} else {
|
||||
GMTimes newGMTimes = worldTimes.get(worldName);
|
||||
if (newGMTimes == null) {
|
||||
addWorld(worldName, gameMode, currentGMTimes.getLastStateChange());
|
||||
}
|
||||
currentGMTimes.changeState(currentGamemode, changeTime);
|
||||
}
|
||||
|
||||
for (GMTimes gmTimes : worldTimes.values()) {
|
||||
gmTimes.setLastStateChange(changeTime);
|
||||
}
|
||||
|
||||
currentWorld = worldName;
|
||||
currentGamemode = gameMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to get a total playtime of a world.
|
||||
*
|
||||
* @param world World name being checked.
|
||||
* @return total milliseconds spent in a world.
|
||||
*/
|
||||
public long getWorldPlaytime(String world) {
|
||||
GMTimes gmTimes = worldTimes.get(world);
|
||||
return gmTimes != null ? gmTimes.getTotal() : 0;
|
||||
}
|
||||
|
||||
public long getTotal() {
|
||||
return worldTimes.values().stream()
|
||||
.mapToLong(GMTimes::getTotal)
|
||||
.sum();
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for Quick access to time of each GameMode.
|
||||
* <p>
|
||||
* Should not be used for changing state,
|
||||
* because if player has not played in the world,
|
||||
* an empty GMTimes is given, with 0 as playtime
|
||||
*
|
||||
* @param world World name being checked.
|
||||
* @return GMTimes object with play times of each GameMode.
|
||||
*/
|
||||
public GMTimes getGMTimes(String world) {
|
||||
return worldTimes.getOrDefault(world, new GMTimes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to get the Map for saving.
|
||||
*
|
||||
* @return Current time map.
|
||||
*/
|
||||
public Map<String, GMTimes> getWorldTimes() {
|
||||
return worldTimes;
|
||||
}
|
||||
|
||||
public void setGMTimesForWorld(String world, GMTimes gmTimes) {
|
||||
worldTimes.put(world, gmTimes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
WorldTimes that = (WorldTimes) o;
|
||||
return Objects.equals(worldTimes, that.worldTimes) &&
|
||||
Objects.equals(currentWorld, that.currentWorld) &&
|
||||
Objects.equals(currentGamemode, that.currentGamemode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(worldTimes, currentWorld, currentGamemode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder b = new StringBuilder("WorldTimes (Current: " + currentWorld + "){\n");
|
||||
|
||||
for (Map.Entry<String, GMTimes> entry : worldTimes.entrySet()) {
|
||||
GMTimes value = entry.getValue();
|
||||
b.append("World '").append(entry.getKey()).append("':\n")
|
||||
.append(" Total: ").append(value.getTotal()).append("\n")
|
||||
.append(" ").append(value.toString()).append("\n");
|
||||
}
|
||||
|
||||
b.append("}");
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
public String getCurrentWorld() {
|
||||
return currentWorld;
|
||||
}
|
||||
|
||||
public void add(WorldTimes toAdd) {
|
||||
Map<String, GMTimes> times = toAdd.getWorldTimes();
|
||||
for (Map.Entry<String, GMTimes> entry : times.entrySet()) {
|
||||
String worldName = entry.getKey();
|
||||
GMTimes gmTimes = entry.getValue();
|
||||
|
||||
GMTimes currentGMTimes = getGMTimes(worldName);
|
||||
for (String gm : GMTimes.getGMKeyArray()) {
|
||||
currentGMTimes.addTime(gm, gmTimes.getTime(gm));
|
||||
}
|
||||
worldTimes.put(worldName, currentGMTimes);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.system;
|
||||
|
||||
import com.djrapitops.plan.Plan;
|
||||
import com.djrapitops.plan.ShutdownHook;
|
||||
import com.djrapitops.plan.api.BukkitAPI;
|
||||
import com.djrapitops.plan.api.exceptions.EnableException;
|
||||
import com.djrapitops.plan.data.plugin.HookHandler;
|
||||
import com.djrapitops.plan.system.database.BukkitDBSystem;
|
||||
import com.djrapitops.plan.system.file.FileSystem;
|
||||
import com.djrapitops.plan.system.info.BukkitInfoSystem;
|
||||
import com.djrapitops.plan.system.info.server.BukkitServerInfo;
|
||||
import com.djrapitops.plan.system.listeners.BukkitListenerSystem;
|
||||
import com.djrapitops.plan.system.settings.PlanErrorManager;
|
||||
import com.djrapitops.plan.system.settings.config.BukkitConfigSystem;
|
||||
import com.djrapitops.plan.system.settings.network.NetworkSettings;
|
||||
import com.djrapitops.plan.system.tasks.BukkitTaskSystem;
|
||||
import com.djrapitops.plan.system.update.VersionCheckSystem;
|
||||
import com.djrapitops.plugin.StaticHolder;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
|
||||
/**
|
||||
* Represents PlanSystem for Plan.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class BukkitSystem extends PlanSystem {
|
||||
|
||||
public BukkitSystem(Plan plugin) {
|
||||
testSystem = this;
|
||||
|
||||
Log.setErrorManager(new PlanErrorManager());
|
||||
|
||||
versionCheckSystem = new VersionCheckSystem(plugin.getVersion());
|
||||
fileSystem = new FileSystem(plugin);
|
||||
configSystem = new BukkitConfigSystem();
|
||||
databaseSystem = new BukkitDBSystem();
|
||||
listenerSystem = new BukkitListenerSystem(plugin);
|
||||
taskSystem = new BukkitTaskSystem(plugin);
|
||||
|
||||
infoSystem = new BukkitInfoSystem();
|
||||
serverInfo = new BukkitServerInfo(plugin);
|
||||
|
||||
hookHandler = new HookHandler();
|
||||
planAPI = new BukkitAPI(this);
|
||||
|
||||
StaticHolder.saveInstance(ShutdownHook.class, plugin.getClass());
|
||||
new ShutdownHook().register();
|
||||
}
|
||||
|
||||
public static BukkitSystem getInstance() {
|
||||
return Plan.getInstance().getSystem();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() throws EnableException {
|
||||
super.enable();
|
||||
NetworkSettings.loadSettingsFromDB();
|
||||
}
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.system;
|
||||
|
||||
import com.djrapitops.plan.PlanBungee;
|
||||
import com.djrapitops.plan.api.BungeeAPI;
|
||||
import com.djrapitops.plan.api.exceptions.EnableException;
|
||||
import com.djrapitops.plan.data.plugin.HookHandler;
|
||||
import com.djrapitops.plan.system.database.BungeeDBSystem;
|
||||
import com.djrapitops.plan.system.database.DBSystem;
|
||||
import com.djrapitops.plan.system.file.FileSystem;
|
||||
import com.djrapitops.plan.system.info.BungeeInfoSystem;
|
||||
import com.djrapitops.plan.system.info.server.BungeeServerInfo;
|
||||
import com.djrapitops.plan.system.listeners.BungeeListenerSystem;
|
||||
import com.djrapitops.plan.system.settings.PlanErrorManager;
|
||||
import com.djrapitops.plan.system.settings.config.BungeeConfigSystem;
|
||||
import com.djrapitops.plan.system.settings.network.NetworkSettings;
|
||||
import com.djrapitops.plan.system.tasks.BungeeTaskSystem;
|
||||
import com.djrapitops.plan.system.update.VersionCheckSystem;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
|
||||
/**
|
||||
* Represents PlanSystem for PlanBungee.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class BungeeSystem extends PlanSystem {
|
||||
|
||||
public BungeeSystem(PlanBungee plugin) {
|
||||
testSystem = this;
|
||||
|
||||
Log.setErrorManager(new PlanErrorManager());
|
||||
|
||||
versionCheckSystem = new VersionCheckSystem(plugin.getVersion());
|
||||
fileSystem = new FileSystem(plugin);
|
||||
configSystem = new BungeeConfigSystem();
|
||||
databaseSystem = new BungeeDBSystem();
|
||||
listenerSystem = new BungeeListenerSystem(plugin);
|
||||
taskSystem = new BungeeTaskSystem(plugin);
|
||||
|
||||
infoSystem = new BungeeInfoSystem();
|
||||
serverInfo = new BungeeServerInfo(plugin);
|
||||
|
||||
hookHandler = new HookHandler();
|
||||
planAPI = new BungeeAPI(this);
|
||||
}
|
||||
|
||||
public static BungeeSystem getInstance() {
|
||||
return PlanBungee.getInstance().getSystem();
|
||||
}
|
||||
|
||||
public void setDatabaseSystem(DBSystem dbSystem) {
|
||||
this.databaseSystem = dbSystem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() throws EnableException {
|
||||
super.enable();
|
||||
NetworkSettings.placeSettingsToDB();
|
||||
}
|
||||
}
|
@ -1,196 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.system;
|
||||
|
||||
import com.djrapitops.plan.api.PlanAPI;
|
||||
import com.djrapitops.plan.api.exceptions.EnableException;
|
||||
import com.djrapitops.plan.data.plugin.HookHandler;
|
||||
import com.djrapitops.plan.system.cache.CacheSystem;
|
||||
import com.djrapitops.plan.system.database.DBSystem;
|
||||
import com.djrapitops.plan.system.file.FileSystem;
|
||||
import com.djrapitops.plan.system.info.InfoSystem;
|
||||
import com.djrapitops.plan.system.info.server.ServerInfo;
|
||||
import com.djrapitops.plan.system.listeners.ListenerSystem;
|
||||
import com.djrapitops.plan.system.processing.ProcessingQueue;
|
||||
import com.djrapitops.plan.system.settings.config.ConfigSystem;
|
||||
import com.djrapitops.plan.system.tasks.TaskSystem;
|
||||
import com.djrapitops.plan.system.update.VersionCheckSystem;
|
||||
import com.djrapitops.plan.system.webserver.WebServerSystem;
|
||||
import com.djrapitops.plugin.api.Check;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
import com.djrapitops.plugin.utilities.Verify;
|
||||
|
||||
/**
|
||||
* PlanSystem contains everything Plan needs to run.
|
||||
* <p>
|
||||
* This is an abstraction layer on top of Plugin instances so that tests can be run with less mocks.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public abstract class PlanSystem implements SubSystem {
|
||||
|
||||
protected static PlanSystem testSystem;
|
||||
|
||||
// Initialized in this class
|
||||
protected final ProcessingQueue processingQueue;
|
||||
protected final WebServerSystem webServerSystem;
|
||||
protected final CacheSystem cacheSystem;
|
||||
|
||||
// These need to be initialized in the sub class.
|
||||
protected VersionCheckSystem versionCheckSystem;
|
||||
protected FileSystem fileSystem;
|
||||
protected ConfigSystem configSystem;
|
||||
protected DBSystem databaseSystem;
|
||||
protected InfoSystem infoSystem;
|
||||
|
||||
protected ListenerSystem listenerSystem;
|
||||
protected TaskSystem taskSystem;
|
||||
protected ServerInfo serverInfo;
|
||||
|
||||
protected HookHandler hookHandler;
|
||||
|
||||
// Not a SubSystem.
|
||||
protected PlanAPI planAPI;
|
||||
|
||||
public PlanSystem() {
|
||||
processingQueue = new ProcessingQueue();
|
||||
webServerSystem = new WebServerSystem();
|
||||
cacheSystem = new CacheSystem(this);
|
||||
}
|
||||
|
||||
public static PlanSystem getInstance() {
|
||||
boolean bukkitAvailable = Check.isBukkitAvailable();
|
||||
boolean bungeeAvailable = Check.isBungeeAvailable();
|
||||
if (bukkitAvailable && bungeeAvailable) {
|
||||
return testSystem;
|
||||
} else if (bungeeAvailable) {
|
||||
return BungeeSystem.getInstance();
|
||||
} else if (bukkitAvailable) {
|
||||
return BukkitSystem.getInstance();
|
||||
}
|
||||
throw new IllegalAccessError("PlanSystem is not available on this platform.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() throws EnableException {
|
||||
checkSubSystemInitialization();
|
||||
|
||||
SubSystem[] systems = new SubSystem[]{
|
||||
versionCheckSystem,
|
||||
fileSystem,
|
||||
configSystem,
|
||||
databaseSystem,
|
||||
webServerSystem,
|
||||
processingQueue,
|
||||
serverInfo,
|
||||
infoSystem,
|
||||
cacheSystem,
|
||||
listenerSystem,
|
||||
taskSystem,
|
||||
hookHandler
|
||||
};
|
||||
for (SubSystem system : systems) {
|
||||
system.enable();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disable() {
|
||||
SubSystem[] systems = new SubSystem[]{
|
||||
taskSystem,
|
||||
hookHandler,
|
||||
cacheSystem,
|
||||
listenerSystem,
|
||||
processingQueue,
|
||||
databaseSystem,
|
||||
webServerSystem,
|
||||
infoSystem,
|
||||
serverInfo,
|
||||
configSystem,
|
||||
fileSystem,
|
||||
versionCheckSystem
|
||||
};
|
||||
for (SubSystem system : systems) {
|
||||
try {
|
||||
if (system != null) {
|
||||
system.disable();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.toLog(this.getClass(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkSubSystemInitialization() throws EnableException {
|
||||
try {
|
||||
Verify.nullCheck(versionCheckSystem, () -> new IllegalStateException("Version Check system was not initialized."));
|
||||
Verify.nullCheck(fileSystem, () -> new IllegalStateException("File system was not initialized."));
|
||||
Verify.nullCheck(configSystem, () -> new IllegalStateException("Config system was not initialized."));
|
||||
Verify.nullCheck(databaseSystem, () -> new IllegalStateException("Database system was not initialized."));
|
||||
Verify.nullCheck(infoSystem, () -> new IllegalStateException("Info system was not initialized."));
|
||||
Verify.nullCheck(serverInfo, () -> new IllegalStateException("ServerInfo was not initialized."));
|
||||
Verify.nullCheck(listenerSystem, () -> new IllegalStateException("Listener system was not initialized."));
|
||||
Verify.nullCheck(taskSystem, () -> new IllegalStateException("Task system was not initialized."));
|
||||
Verify.nullCheck(hookHandler, () -> new IllegalStateException("Plugin Hooks were not initialized."));
|
||||
Verify.nullCheck(planAPI, () -> new IllegalStateException("Plan API was not initialized."));
|
||||
} catch (Exception e) {
|
||||
throw new EnableException("One of the subsystems is not initialized on enable for " + this.getClass().getSimpleName() + ": " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// Accessor methods.
|
||||
|
||||
public ProcessingQueue getProcessingQueue() {
|
||||
return processingQueue;
|
||||
}
|
||||
|
||||
public VersionCheckSystem getVersionCheckSystem() {
|
||||
return versionCheckSystem;
|
||||
}
|
||||
|
||||
public ConfigSystem getConfigSystem() {
|
||||
return configSystem;
|
||||
}
|
||||
|
||||
public FileSystem getFileSystem() {
|
||||
return fileSystem;
|
||||
}
|
||||
|
||||
public DBSystem getDatabaseSystem() {
|
||||
return databaseSystem;
|
||||
}
|
||||
|
||||
public ListenerSystem getListenerSystem() {
|
||||
return listenerSystem;
|
||||
}
|
||||
|
||||
public TaskSystem getTaskSystem() {
|
||||
return taskSystem;
|
||||
}
|
||||
|
||||
public WebServerSystem getWebServerSystem() {
|
||||
return webServerSystem;
|
||||
}
|
||||
|
||||
public ServerInfo getServerInfo() {
|
||||
return serverInfo;
|
||||
}
|
||||
|
||||
public CacheSystem getCacheSystem() {
|
||||
return cacheSystem;
|
||||
}
|
||||
|
||||
public InfoSystem getInfoSystem() {
|
||||
return infoSystem;
|
||||
}
|
||||
|
||||
public HookHandler getHookHandler() {
|
||||
return hookHandler;
|
||||
}
|
||||
|
||||
public PlanAPI getPlanAPI() {
|
||||
return planAPI;
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.system;
|
||||
|
||||
import com.djrapitops.plan.api.exceptions.EnableException;
|
||||
|
||||
/**
|
||||
* Represents a system that can be enabled and disabled.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public interface SubSystem {
|
||||
|
||||
/**
|
||||
* Performs enable actions for the subsystem.
|
||||
*
|
||||
* @throws EnableException If an error occurred during enable and it is fatal to the subsystem.
|
||||
*/
|
||||
void enable() throws EnableException;
|
||||
|
||||
/**
|
||||
* Performs disable actions for the subsystem
|
||||
*/
|
||||
void disable();
|
||||
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.system.cache;
|
||||
|
||||
import com.djrapitops.plan.api.exceptions.EnableException;
|
||||
import com.djrapitops.plan.system.PlanSystem;
|
||||
import com.djrapitops.plan.system.SubSystem;
|
||||
import com.djrapitops.plugin.utilities.Verify;
|
||||
|
||||
/**
|
||||
* System that holds data caches of the plugin.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class CacheSystem implements SubSystem {
|
||||
|
||||
private final DataCache dataCache;
|
||||
private final GeolocationCache geolocationCache;
|
||||
|
||||
public CacheSystem(PlanSystem system) {
|
||||
dataCache = new DataCache(system);
|
||||
geolocationCache = new GeolocationCache();
|
||||
}
|
||||
|
||||
public static CacheSystem getInstance() {
|
||||
CacheSystem cacheSystem = PlanSystem.getInstance().getCacheSystem();
|
||||
Verify.nullCheck(cacheSystem, () -> new IllegalStateException("Cache System was not initialized."));
|
||||
return cacheSystem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() throws EnableException {
|
||||
dataCache.enable();
|
||||
geolocationCache.enable();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disable() {
|
||||
geolocationCache.clearCache();
|
||||
}
|
||||
|
||||
public DataCache getDataCache() {
|
||||
return dataCache;
|
||||
}
|
||||
|
||||
public GeolocationCache getGeolocationCache() {
|
||||
return geolocationCache;
|
||||
}
|
||||
}
|
@ -1,135 +0,0 @@
|
||||
package com.djrapitops.plan.system.cache;
|
||||
|
||||
import com.djrapitops.plan.api.exceptions.database.DBException;
|
||||
import com.djrapitops.plan.system.PlanSystem;
|
||||
import com.djrapitops.plan.system.SubSystem;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
import com.djrapitops.plugin.utilities.Verify;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* This Class contains the Cache.
|
||||
* <p>
|
||||
* Contains:
|
||||
* <ul>
|
||||
* <li>PlayerName cache, used for reducing database calls on chat events</li>
|
||||
* <li>DisplayName cache, used for reducing database calls on chat events</li>
|
||||
* <li>FirstSession MessageCount Map, used for tracking first session and message count on that session.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public class DataCache extends SessionCache implements SubSystem {
|
||||
|
||||
private Database db;
|
||||
private final Map<UUID, String> playerNames;
|
||||
private final Map<String, UUID> uuids;
|
||||
private final Map<UUID, String> displayNames;
|
||||
|
||||
public DataCache(PlanSystem system) {
|
||||
super(system);
|
||||
|
||||
playerNames = new HashMap<>();
|
||||
displayNames = new HashMap<>();
|
||||
uuids = new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
db = system.getDatabaseSystem().getActiveDatabase();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disable() {
|
||||
}
|
||||
|
||||
public static DataCache getInstance() {
|
||||
DataCache dataCache = CacheSystem.getInstance().getDataCache();
|
||||
Verify.nullCheck(dataCache, () -> new IllegalStateException("Data Cache was not initialized."));
|
||||
return dataCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to update PlayerName and DisplayName caches.
|
||||
*
|
||||
* @param uuid UUID of the player.
|
||||
* @param playerName Name of the player.
|
||||
* @param displayName DisplayName of the player.
|
||||
*/
|
||||
public void updateNames(UUID uuid, String playerName, String displayName) {
|
||||
if (playerName != null) {
|
||||
playerNames.put(uuid, playerName);
|
||||
uuids.put(playerName, uuid);
|
||||
}
|
||||
if (displayName != null) {
|
||||
displayNames.put(uuid, displayName);
|
||||
}
|
||||
}
|
||||
|
||||
public void cacheSavedNames() {
|
||||
try {
|
||||
Map<UUID, String> playerNames = db.fetch().getPlayerNames();
|
||||
this.playerNames.putAll(playerNames);
|
||||
for (Map.Entry<UUID, String> entry : playerNames.entrySet()) {
|
||||
uuids.put(entry.getValue(), entry.getKey());
|
||||
}
|
||||
} catch (DBException e) {
|
||||
Log.toLog(this.getClass(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to get the player name in the cache.
|
||||
*
|
||||
* @param uuid UUID of the player.
|
||||
* @return name or null if not cached.
|
||||
*/
|
||||
public String getName(UUID uuid) {
|
||||
String name = playerNames.get(uuid);
|
||||
if (name == null) {
|
||||
try {
|
||||
name = db.fetch().getPlayerName(uuid);
|
||||
playerNames.put(uuid, name);
|
||||
} catch (DBException e) {
|
||||
Log.toLog(this.getClass(), e);
|
||||
name = "Error occurred";
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to get the player display name in the cache.
|
||||
* <p>
|
||||
* If not cached, one from the database will be cached.
|
||||
*
|
||||
* @param uuid UUID of the player.
|
||||
* @return latest displayName or null if none are saved.
|
||||
*/
|
||||
public String getDisplayName(UUID uuid) {
|
||||
String cached = displayNames.get(uuid);
|
||||
if (cached == null) {
|
||||
List<String> nicknames;
|
||||
try {
|
||||
nicknames = db.fetch().getNicknames(uuid);
|
||||
if (!nicknames.isEmpty()) {
|
||||
return nicknames.get(nicknames.size() - 1);
|
||||
}
|
||||
} catch (DBException e) {
|
||||
Log.toLog(this.getClass(), e);
|
||||
}
|
||||
}
|
||||
return cached;
|
||||
}
|
||||
|
||||
public Set<UUID> getUuids() {
|
||||
return playerNames.keySet();
|
||||
}
|
||||
|
||||
public UUID getUUIDof(String playerName) {
|
||||
return uuids.get(playerName);
|
||||
}
|
||||
}
|
@ -1,169 +0,0 @@
|
||||
package com.djrapitops.plan.system.cache;
|
||||
|
||||
import com.djrapitops.plan.api.exceptions.EnableException;
|
||||
import com.djrapitops.plan.system.SubSystem;
|
||||
import com.djrapitops.plan.system.file.FileSystem;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
import com.djrapitops.plugin.utilities.Verify;
|
||||
import com.google.common.cache.Cache;
|
||||
import com.maxmind.geoip2.DatabaseReader;
|
||||
import com.maxmind.geoip2.exception.GeoIp2Exception;
|
||||
import com.maxmind.geoip2.model.CountryResponse;
|
||||
import com.maxmind.geoip2.record.Country;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.URL;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.channels.Channels;
|
||||
import java.nio.channels.ReadableByteChannel;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
/**
|
||||
* This class contains the geolocation cache.
|
||||
* <p>
|
||||
* It caches all IPs with their matching country.
|
||||
* <p>
|
||||
* This cache uses the Google Guava {@link Cache}.
|
||||
*
|
||||
* @author Fuzzlemann
|
||||
* @since 3.5.5
|
||||
*/
|
||||
public class GeolocationCache implements SubSystem {
|
||||
|
||||
private final Map<String, String> geolocationCache;
|
||||
private File geolocationDB;
|
||||
|
||||
public GeolocationCache() {
|
||||
geolocationCache = new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() throws EnableException {
|
||||
geolocationDB = new File(FileSystem.getDataFolder(), "GeoIP.dat");
|
||||
try {
|
||||
GeolocationCache.checkDB();
|
||||
} catch (UnknownHostException e) {
|
||||
Log.error("Plan Requires internet access on first run to download GeoLite2 Geolocation database.");
|
||||
} catch (IOException e) {
|
||||
throw new EnableException("Something went wrong saving the downloaded GeoLite2 Geolocation database", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disable() {
|
||||
}
|
||||
|
||||
private static GeolocationCache getInstance() {
|
||||
GeolocationCache geolocationCache = CacheSystem.getInstance().getGeolocationCache();
|
||||
Verify.nullCheck(geolocationCache, () -> new IllegalStateException("GeolocationCache was not initialized."));
|
||||
return geolocationCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the country in full length (e.g. United States) from the IP Address.
|
||||
* <p>
|
||||
* This method uses the {@code geolocationCache}, every first access is getting cached and then retrieved later.
|
||||
*
|
||||
* @param ipAddress The IP Address from which the country is retrieved
|
||||
* @return The name of the country in full length.
|
||||
* <p>
|
||||
* An exception from that rule is when the country is unknown or the retrieval of the country failed in any way,
|
||||
* if that happens, "Not Known" will be returned.
|
||||
* @see #getUnCachedCountry(String)
|
||||
*/
|
||||
public static String getCountry(String ipAddress) {
|
||||
String country = getCachedCountry(ipAddress);
|
||||
|
||||
if (country != null) {
|
||||
return country;
|
||||
} else {
|
||||
country = getUnCachedCountry(ipAddress);
|
||||
getInstance().geolocationCache.put(ipAddress, country);
|
||||
|
||||
return country;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the country in full length (e.g. United States) from the IP Address.
|
||||
* <p>
|
||||
* This product includes GeoLite2 data created by MaxMind, available from
|
||||
* <a href="http://www.maxmind.com">http://www.maxmind.com</a>.
|
||||
*
|
||||
* @param ipAddress The IP Address from which the country is retrieved
|
||||
* @return The name of the country in full length.
|
||||
* <p>
|
||||
* An exception from that rule is when the country is unknown or the retrieval of the country failed in any way,
|
||||
* if that happens, "Not Known" will be returned.
|
||||
* @see <a href="http://maxmind.com">http://maxmind.com</a>
|
||||
* @see #getCountry(String)
|
||||
*/
|
||||
private static String getUnCachedCountry(String ipAddress) {
|
||||
if ("127.0.0.1".equals(ipAddress)) {
|
||||
return "Local Machine";
|
||||
}
|
||||
try {
|
||||
checkDB();
|
||||
|
||||
try (DatabaseReader reader = new DatabaseReader.Builder(getInstance().geolocationDB).build()) {
|
||||
InetAddress inetAddress = InetAddress.getByName(ipAddress);
|
||||
|
||||
CountryResponse response = reader.country(inetAddress);
|
||||
Country country = response.getCountry();
|
||||
|
||||
return country.getName();
|
||||
}
|
||||
|
||||
} catch (IOException | GeoIp2Exception e) {
|
||||
return "Not Known";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the DB exists, if not, it downloads it
|
||||
*
|
||||
* @throws IOException when an error at download or saving the DB happens
|
||||
*/
|
||||
public static void checkDB() throws IOException {
|
||||
if (getInstance().geolocationDB.exists()) {
|
||||
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(getInstance().geolocationDB.getAbsoluteFile())) {
|
||||
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cached country
|
||||
*
|
||||
* @param ipAddress The IP Address which is retrieved out of the cache
|
||||
* @return The cached country, {@code null} if the country is not cached
|
||||
*/
|
||||
private static String getCachedCountry(String ipAddress) {
|
||||
return getInstance().geolocationCache.get(ipAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the IP Address is cached
|
||||
*
|
||||
* @param ipAddress The IP Address which is checked
|
||||
* @return true if the IP Address is cached
|
||||
*/
|
||||
public static boolean isCached(String ipAddress) {
|
||||
return getInstance().geolocationCache.containsKey(ipAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the cache
|
||||
*/
|
||||
public void clearCache() {
|
||||
geolocationCache.clear();
|
||||
}
|
||||
}
|
@ -1,135 +0,0 @@
|
||||
package com.djrapitops.plan.system.cache;
|
||||
|
||||
import com.djrapitops.plan.api.exceptions.database.DBException;
|
||||
import com.djrapitops.plan.data.container.Session;
|
||||
import com.djrapitops.plan.system.PlanSystem;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plan.system.info.connection.WebExceptionLogger;
|
||||
import com.djrapitops.plan.system.processing.Processor;
|
||||
import com.djrapitops.plan.utilities.MiscUtils;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
import com.djrapitops.plugin.utilities.Verify;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* This class is used to store active sessions of players in memory.
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public class SessionCache {
|
||||
|
||||
private static final Map<UUID, Integer> firstSessionInformation = new HashMap<>();
|
||||
private static final Map<UUID, Session> activeSessions = new HashMap<>();
|
||||
protected final PlanSystem system;
|
||||
|
||||
public SessionCache(PlanSystem system) {
|
||||
this.system = system;
|
||||
}
|
||||
|
||||
public static SessionCache getInstance() {
|
||||
DataCache dataCache = CacheSystem.getInstance().getDataCache();
|
||||
Verify.nullCheck(dataCache, () -> new IllegalStateException("Data Cache was not initialized."));
|
||||
return dataCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to get the Map of active sessions.
|
||||
* <p>
|
||||
* Used for testing.
|
||||
*
|
||||
* @return key:value UUID:Session
|
||||
*/
|
||||
public static Map<UUID, Session> getActiveSessions() {
|
||||
return activeSessions;
|
||||
}
|
||||
|
||||
public static void clear() {
|
||||
activeSessions.clear();
|
||||
}
|
||||
|
||||
public void cacheSession(UUID uuid, Session session) {
|
||||
activeSessions.put(uuid, session);
|
||||
Processor.queue(() -> WebExceptionLogger.logIfOccurs(this.getClass(), () ->
|
||||
system.getInfoSystem().generateAndCachePlayerPage(uuid))
|
||||
);
|
||||
}
|
||||
|
||||
public void endSession(UUID uuid, long time) {
|
||||
try {
|
||||
Session session = activeSessions.get(uuid);
|
||||
if (session == null) {
|
||||
return;
|
||||
}
|
||||
session.endSession(time);
|
||||
Database.getActive().save().session(uuid, session);
|
||||
} catch (DBException e) {
|
||||
Log.toLog(this.getClass(), e);
|
||||
} finally {
|
||||
activeSessions.remove(uuid);
|
||||
|
||||
WebExceptionLogger.logIfOccurs(this.getClass(), () -> system.getInfoSystem().generateAndCachePlayerPage(uuid));
|
||||
}
|
||||
}
|
||||
|
||||
public static void refreshActiveSessionsState() {
|
||||
for (Session session : activeSessions.values()) {
|
||||
session.getWorldTimes().updateState(MiscUtils.getTime());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to get the Session of the player in the sessionCache.
|
||||
*
|
||||
* @param uuid UUID of the player.
|
||||
* @return Session or null if not cached.
|
||||
*/
|
||||
public static Optional<Session> getCachedSession(UUID uuid) {
|
||||
Session session = activeSessions.get(uuid);
|
||||
if (session != null) {
|
||||
return Optional.of(session);
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for marking first Session Actions to be saved.
|
||||
*
|
||||
* @param uuid UUID of the new player.
|
||||
*/
|
||||
public void markFirstSession(UUID uuid) {
|
||||
firstSessionInformation.put(uuid, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Condition if a session is player's first session on the server.
|
||||
*
|
||||
* @param uuid UUID of the player
|
||||
* @return true / false
|
||||
*/
|
||||
public boolean isFirstSession(UUID uuid) {
|
||||
return firstSessionInformation.containsKey(uuid);
|
||||
}
|
||||
|
||||
public void endFirstSessionActionTracking(UUID uuid) {
|
||||
firstSessionInformation.remove(uuid);
|
||||
}
|
||||
|
||||
public void firstSessionMessageSent(UUID uuid) {
|
||||
Integer msgCount = firstSessionInformation.getOrDefault(uuid, 0);
|
||||
msgCount++;
|
||||
firstSessionInformation.put(uuid, msgCount);
|
||||
}
|
||||
|
||||
public int getFirstSessionMsgCount(UUID uuid) {
|
||||
return firstSessionInformation.getOrDefault(uuid, 0);
|
||||
}
|
||||
|
||||
public Map<UUID, Integer> getFirstSessionMsgCounts() {
|
||||
return firstSessionInformation;
|
||||
}
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.system.database;
|
||||
|
||||
import com.djrapitops.plan.api.exceptions.database.DBInitException;
|
||||
import com.djrapitops.plan.system.database.databases.sql.MySQLDB;
|
||||
import com.djrapitops.plan.system.database.databases.sql.SQLiteDB;
|
||||
import com.djrapitops.plan.system.settings.Settings;
|
||||
|
||||
/**
|
||||
* Bukkit Database system that initializes SQLite and MySQL database objects.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class BukkitDBSystem extends DBSystem {
|
||||
|
||||
@Override
|
||||
protected void initDatabase() throws DBInitException {
|
||||
databases.add(new MySQLDB());
|
||||
databases.add(new SQLiteDB());
|
||||
|
||||
String dbType = Settings.DB_TYPE.toString().toLowerCase().trim();
|
||||
db = getActiveDatabaseByName(dbType);
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
/*
|
||||
* 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 com.djrapitops.plan.system.database;
|
||||
|
||||
import com.djrapitops.plan.api.exceptions.database.DBInitException;
|
||||
import com.djrapitops.plan.system.database.databases.sql.MySQLDB;
|
||||
|
||||
/**
|
||||
* Bungee Database system that initializes MySQL object.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class BungeeDBSystem extends DBSystem {
|
||||
|
||||
@Override
|
||||
protected void initDatabase() throws DBInitException {
|
||||
db = new MySQLDB();
|
||||
databases.add(db);
|
||||
db.init();
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user