[4.0.0] Merge pull request #269 from Rsl1122/4.0.0-BungeeCord-Support

4.0.0 bungeecord support
This commit is contained in:
Rsl1122 2017-10-01 21:48:06 +03:00 committed by GitHub
commit da64b1bae8
436 changed files with 21406 additions and 16508 deletions

6
.gitignore vendored
View File

@ -12,4 +12,8 @@
/Filetool/nbproject/private/
/Filetool/build/
/PlanPluginBridge/target/
/MakroS/nbproject/private/
/MakroS/nbproject/private/
*.xml
Plan/Plan.iml
Plan/.sonar/.sonar_lock
Plan/.sonar/report-task.txt

View File

@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.djrapitops</groupId>
<artifactId>Plan</artifactId>
<version>3.6.3</version>
<version>4.0.0</version>
<build>
<sourceDirectory>${basedir}/src</sourceDirectory>
<testSourceDirectory>${basedir}/test</testSourceDirectory>
@ -14,10 +14,26 @@
<directory>${basedir}/src/main/resources</directory>
<includes>
<include>*.keystore</include>
<include>*.js</include>
<include>*.css</include>
<include>*.yml</include>
<include>*.html</include>
<include>*.txt</include>
</includes>
<excludes>
<exclude>licence.yml</exclude>
</excludes>
</resource>
<resource>
<targetPath>.</targetPath>
<directory>${basedir}/src/main/resources/html</directory>
<includes>
<include>*.html</include>
</includes>
</resource>
<resource>
<targetPath>.</targetPath>
<directory>${basedir}/src/main/resources/js</directory>
<includes>
<include>*.js</include>
</includes>
</resource>
</resources>
@ -43,6 +59,7 @@
</execution>
</executions>
<configuration>
<minimizeJar>true</minimizeJar>
<artifactSet>
<excludes>
<exclude>org.powermock:*</exclude>
@ -52,7 +69,8 @@
<exclude>xpp3:*</exclude>
<exclude>org.objenesis:*</exclude>
<exclude>cglib:*</exclude>
<exclude>org.*:*</exclude>
<exclude>org.bukkit:*</exclude>
<exclude>org.mockito:*</exclude>
<exclude>org.easymock:*</exclude>
<exclude>junit:*</exclude>
</excludes>
@ -95,12 +113,8 @@
</build>
<repositories>
<repository>
<id>plan-repo</id>
<url>http://repo.fuzzlemann.de/artifactory/libs-release/</url>
</repository>
<repository>
<id>plan-snapshot-repo</id>
<url>http://repo.fuzzlemann.de/artifactory/libs-snapshot/</url>
<id>bungeecord-repo</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</repository>
</repositories>
<dependencies>
@ -110,6 +124,34 @@
<version>1.12-R0.1-20170725.202533-1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>1.12-SNAPSHOT</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<artifactId>bungeecord-chat</artifactId>
<groupId>net.md-5</groupId>
</exclusion>
<exclusion>
<artifactId>bungeecord-config</artifactId>
<groupId>net.md-5</groupId>
</exclusion>
<exclusion>
<artifactId>bungeecord-event</artifactId>
<groupId>net.md-5</groupId>
</exclusion>
<exclusion>
<artifactId>bungeecord-protocol</artifactId>
<groupId>net.md-5</groupId>
</exclusion>
<exclusion>
<artifactId>guava</artifactId>
<groupId>com.google.guava</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock</artifactId>

View File

@ -1,138 +0,0 @@
ENABLED <> Player Analytics aktiviert.
DISABLED <> Player Analytics deaktiviert.
RELOAD_COMPLETE <> §a[Plan] Reload abgeschlossen.
CACHE_SAVE <> Daten im Cache werden gespeichert...
CACHE_ADD <> REPLACE0 wurde zum Cache hinzugefügt.
CACHE_REMOVE <> REPLACE0 wurde aus dem Cache gelöscht.
CONFIG_HEADER <> Plan Config | Mehr Informationen auf https://www.spigotmc.org/wiki/plan-configuration/
DB_INIT <> Datenbank Initialisierung...
WEBSERVER_INIT <> Initialisiere Webserver...
WEBSERVER_CLOSE <> Webserver wird heruntergefahren...
WEBSERVER_RUNNING <> Webserver läuft auf PORT REPLACE0
DB_CONNECTION_FAIL <> REPLACE0-Datenbank Verbindung fehlgeschlagen: REPLACE1
DB_ESTABLISHED <> REPLACE0-Datenbank Verbindung hergestellt.
DB_TYPE_DOES_NOT_EXIST <> Dieser Datenbank Typ existiert nicht.
DB_FAILURE_DISABLE <> Datenbank Initialisierung fehlgeschlagen, deaktiviere Plan.
NOTIFY_EMPTY_IP <> §e[Plan] IP in server.properties ist leer & Alternative ServerIP wird nicht benutzt, fehlerhafte Links werden ausgegeben!
VERSION_NEW_AVAILABLE <> Eine neue Version (REPLACE0) ist verfügbar auf https://www.spigotmc.org/resources/plan-player-analytics.32536/
VERSION_LATEST <> Du benutzt die neueste Version.
VERSION_CHECK_ERROR <> Versionen konnten nicht abgeglichen werden.
VERSION_FAIL <> Die neueste Versionsnummer konnte nicht abgerufen werden.
USERNAME_NOT_VALID <> §c[Plan] Dieser Spieler existiert nicht.
USERNAME_NOT_SEEN <> §c[Plan] Dieser Spieler war noch nie auf diesem Server.
USERNAME_NOT_KNOWN <> §c[Plan] Der Spielername konnte in der Datenbank nicht gefunden werden.
GRABBING_DATA_MESSAGE <> Ȥ2 Hole Daten ins Cache...
DEM_UNKNOWN <> Nicht bekannt
NOT_IN_TOWN <> Nicht in einem Dorf
NOT_IN_FAC <> Nicht in einer Faction
COMMAND_TIMEOUT <> §c[Plan] REPLACE0 Befehl ausgetimed! Der Error befindest sich vermutlich in der Serverkonsole.
ANALYSIS_START <> Analyse | Beginne die Analyse der Spieler Daten...
ANALYSIS_BOOT_NOTIFY <> Analyse | Boot Analyse in 30 Sekunden...
ANALYSIS_BOOT <> Analyse | Starte Boot Analyse...
ANALYSIS_FETCH_PLAYERS <> Analyse | Suche nach verfügbaren Spieler...
ANALYSIS_FETCH_DATA <> Analyse | Hole Daten...
ANALYSIS_FAIL_NO_PLAYERS <> Analyse | Analyse fehlgeschlagen, keine bekannten Spieler.
ANALYSIS_FAIL_NO_DATA <> Analyse | Analyse fehlgeschlagen, keine Daten in der Datenbank.
ANALYSIS_BEGIN_ANALYSIS <> Analyse | Daten geholt, beginne mit der Analyse der Daten...
ANALYSIS_COMPLETE <> Analyse | Analyse vollständig.
DATA_CORRUPTION_WARN <> Einige Daten könnten beschädigt sein: REPLACE0
ERROR_NO_DATA_VIEW <> §eWebserver deaktiviert aber Alternative IP/PlanLite wird nicht benutzt, Daten können nicht angezeigt werden!
ERROR_WEBSERVER_OFF_ANALYSIS <> §e[Plan] Dieser Befehl kann nur benutzt werden wenn der Webserver auf diesem Server läuft...
ERROR_WEBSERVER_OFF_INSPECT <> §e[Plan] Dieser Befehl kann nur benutzt werden wenn Webserver/Planlite auf dem Server aktiviert ist.
MANAGE_ERROR_INCORRECT_PLUGIN <> §c[Plan] Plugin nicht unterstützt:
MANAGE_PROCESS_START <> Ȥ7 Verarbeite Daten...
MANAGE_ERROR_PLUGIN_NOT_ENABLED <> §c[Plan] Plugin ist nicht aktiviert:
MANAGE_ERROR_INCORRECT_DB <> §c[Plan] Falsche Datenbank! (SQlite/MySQL wird unterstützt):
MANAGE_ERROR_SAME_DB <> §c[Plan] Kann nicht zur selben Datenbank bewegen!
MANAGE_DATABASE_FAILURE <> §c[Plan] Eine der Datenbanken wurde nicht richtig initialisiert.
MANAGE_DB_CONFIG_REMINDER <> §e[Plan] Vergiss nicht zur neuen Datenbank zu wechseln und das Plugin neu zu laden
MANAGE_ERROR_NO_PLAYERS <> §c[Plan] Datenbank hat keine Spieler Daten!
MANAGE_ERROR_BACKUP_FILE_NOT_FOUND <> §c[Plan] Sicherheitskopie existiert nicht!
MANAGE_MOVE_SUCCESS <> §a[Plan] Alle Daten wurden erfolgreich verschoben!
MANAGE_COPY_SUCCESS <> §a[Plan] Alle Daten wurden erfolgreich kopiert!
MANAGE_PROCESS_FAIL <> §c[Plan] Irgendwas lief schief während die Daten verarbeitet wurden!
MANAGE_CLEAR_SUCCESS <> §a[Plan] Alle Daten wurden erfolgreich gesäubert!
MANAGE_REMOVE_SUCCESS <> §f» §2Daten von §fREPLACE0§2 wurden aus dieser Datenbank entfernt §fREPLACE1§2.
MANAGE_IMPORTING <> §f» §2 Importiere Daten...
MANAGE_SUCCESS <> §f» §2 Erfolgreich!
CMD_ANALYZE_HEADER <> §f»§2 Player Analytics - Analyse Ergebnisse
CMD_INSPECT_HEADER <> §f»§2 Player Analytics - Überprüfe die Ergebnisse:
CMD_INFO_HEADER <> §f»§2 Player Analytics - Info
CMD_INFO_VERSION <> §7 •§2§2 Version: §7REPLACE0
CMD_SEARCH_HEADER <> §f»§2 Player Analytics - Suchergebnisse für:
CMD_HELP_HEADER <> §f»§2 Player Analytics - Hilfe
CMD_MANAGE_HELP_HEADER <> §f»§2 Player Analytics - Management Hilfe
CMD_MANAGE_STATUS_HEADER <> §f»§2 Player Analytics - Datenbank Status
CMD_MANAGE_STATUS_ACTIVE_DB <> §7 •§2§2 Aktive Datenbank: §7REPLACE0
CMD_CLICK_ME <> Klick Mich
CMD_LINK <> §7 •§2 Link: §f
CMD_RESULTS_AVAILABLE <> §7 Die Ergebnisse werden für §fREPLACE0§7 Minuten erreichbar sein.
CMD_NO_RESULTS <> §7 •§2 Keine Ergebnisse für §7REPLACE0§2.
CMD_MATCH <> §7 Übereinstimmender Spieler: §f
CMD_USG_ANALYZE <> Zeige die Server Analyse
CMD_USG_HELP <> Zeige die Befehlsliste.
CMD_USG_INFO <> Zeige die Version von Plan
CMD_USG_INSPECT <> Prüfe Spieler Daten
CMD_USG_MANAGE <> Datenbank Management Befehl
CMD_USG_MANAGE_BACKUP <> Erstelle eine Sicherheitskopie der Datenbank als .db Datei
CMD_USG_MANAGE_RESTORE <> Stelle eine Sicherheitskopie einer Datenbank aus einer Datei wieder her.
CMD_USG_MANAGE_MOVE <> Kopiere Daten von einer Datenbank zur anderen & überschreibe die Werte
CMD_USG_MANAGE_COMBINE <> Kopiere Daten von einer Datenbank zur anderen & kombiniere die Werte
CMD_USG_MANAGE_IMPORT <> Importiere Daten von unterstützten Plugins zur aktiven Datenbank.
CMD_USG_MANAGE_CLEAR <> Leere Daten aus einer Datenbank
CMD_USG_MANAGE_REMOVE <> Entferne die Spieler Daten aus der aktiven Datenbank.
CMD_USG_MANAGE_STATUS <> Überprüfe den Status der aktiven Datenbank.
CMD_USG_MANAGE_HELP <> Zeige die Management Hilfe.
CMD_USG_MANAGE_HOTSWAP <> Wechsle zu einer anderen Datenbank & starte das Plugin neu
CMD_USG_RELOAD <> Lade die Plugin Konfiguration neu und & speichere die Daten aus dem Cache
CMD_USG_SEARCH <> Suche nach einem Spieler
ARG_SEARCH <> <Teil des Spielernamens>
ARG_PLAYER <> <Spieler>
ARG_RESTORE <> <Dateiname.db> <dbTo> [-a]
ARG_IMPORT <> <Plugin> [-a]
ARG_MOVE <> <vonDB> <nachDB> [-a]
USE_RESTORE <> Nutze /plan manage restore <Dateiname.db> <dbTo> [-a]
USE_MANAGE <> Nutze /plan manage für Hilfe
USE_PLAN <> Nutze /plan für Hilfe
USE_MOVE <> Nutze /plan manage move <vonDB> <nachDB> [-a]
USE_COMBINE <> Nutze /plan manage combine <vonDB> <nachDB> [-a]
USE_IMPORT <> Nutze /plan manage import <Plugin> [-a]
WARN_REWRITE <> Daten in REPLACE0-Datenbank werden neu geschrieben!
WARN_OVERWRITE <> Daten in REPLACE0-Datenbank werden überschrieben!
WARN_OVERWRITE_SOME <> Einige Daten in REPLACE0-Datenbank werden überschrieben!
WARN_REMOVE <> Daten in REPLACE0-Datenbank werden entfernt!
COMMAND_SENDER_NOT_PLAYER <> §c[Plan] Dieser Befehl kann nur als Spieler benutzt werden.
COMMAND_REQUIRES_ARGUMENTS <> §c[Plan] Dieser Befehl erfordert Argumente. REPLACE0
COMMAND_ADD_CONFIRMATION_ARGUMENT <> §c[Plan] Füge -a hinzu um den Befehl zu bestätigen! REPLACE0
COMMAND_REQUIRES_ARGUMENTS_ONE <> §c[Plan] Der Befehl benötigt ein Argument.
COMMAND_NO_PERMISSION <> §c[Plan] Du hast nicht die benötigte Berechtigung.
<<<<<<HTML>>>>>>
WARN_INACCURATE <> <div class="warn">Daten könnten ungenau sein, der Spieler hat sich erst registriert.</div>
BANNED <> | <span class="darkred">Gesperrt</span>
OPERATOR <> , Operator (Op)
ONLINE <> | <span class="darkgreen">Online</span>
OFFLINE <> | <span class="darkred">Offline</span>
ACTIVE <> | Spieler ist aktiv
INACTIVE <> | Spieler ist inaktiv
ERROR_LIST <> Error beim erstellen der Liste</p>
HIDDEN <> Versteckt (config)
FACTION_NOT_FOUND <> Faction nicht gefunden
FACTION_NO_LEADER <> Kein Anführer
FACTION_NO_FACTIONS <> Keine Factions
WARPS <> <br/>Warps: REPLACE0
ACHIEVEMENTS <> <br/>Errungenschaften: REPLACE0/REPLACE1
JAILED <> | Eingesperrt
MUTED <> | Stummgeschaltet
VOTES <> <br/>Hat REPLACE0 mal gevoted
FACTION <> <br/>Faction: REPLACE0 | Power: REPLACE1/REPLACE2
TOWN <> <br/>Dorf: REPLACE0
TOWN_NO_TOWNS <> Keine Dörfer
GRAPH_BANNED <> Gesperrt
GRAPH_UNKNOWN <> Unbekannt
GRAPH_INACTIVE <> Inaktiv
GRAPH_ACTIVE <> Aktiv
TABLE_SESSIONS_START <> <table class="sortable table"><thead><tr><th>Session Started</th><th>Session Ended</th><th>Session Length</th></tr></thead><tbody>
TABLE_FACTIONS_START <> <table class="sortable table"><thead><tr><th>Faction</th><th>Power</th><th>Land</th><th>Leader</th></tr></thead><tbody>
TABLE_TOWNS_START <> <table class="sortable table"><thead><tr><th>Town</th><th>Residents</th><th>Land</th><th>Mayor</th></tr></thead><tbody>
ERROR_TABLE_2 <> <tr><td><b>No data</b></td><td>No data</td></tr>
SESSIONDATA_NONE <> Keine Session Daten verfügbar

View File

@ -1,138 +0,0 @@
ENABLED <> Player Analytics Enabled.
DISABLED <> Player Analytics Disabled.
RELOAD_COMPLETE <> <20>a[Plan] Reload complete.
CACHE_SAVE <> Saving cached data..
CACHE_ADD <> Added REPLACE0 to Cache.
CACHE_REMOVE <> Cleared REPLACE0 from Cache.
CONFIG_HEADER <> Plan Config | More info at https://www.spigotmc.org/wiki/plan-configuration/
DB_INIT <> Database init..
WEBSERVER_INIT <> Initializing Webserver..
WEBSERVER_CLOSE <> Shutting down Webserver..
WEBSERVER_RUNNING <> Webserver running on PORT REPLACE0
DB_CONNECTION_FAIL <> REPLACE0-Database Connection failed: REPLACE1
DB_ESTABLISHED <> REPLACE0-database connection established.
DB_TYPE_DOES_NOT_EXIST <> That database type doesn't exist.
DB_FAILURE_DISABLE <> Database initialization has failed, disabling Plan.
NOTIFY_EMPTY_IP <> <20>e[Plan] IP in server.properties is empty & AlternativeServerIP is not used, incorrect links will be given!
VERSION_NEW_AVAILABLE <> New Version (REPLACE0) is available at https://www.spigotmc.org/resources/plan-player-analytics.32536/
VERSION_LATEST <> You're running the latest version
VERSION_CHECK_ERROR <> Failed to compare versions.
VERSION_FAIL <> Failed to get newest version number.
USERNAME_NOT_VALID <> <20>c[Plan] This Player doesn't exist.
USERNAME_NOT_SEEN <> <20>c[Plan] This Player has not played on this server.
USERNAME_NOT_KNOWN <> <20>c[Plan] Player not found from the database.
GRABBING_DATA_MESSAGE <> <20><>2 Fetching data to cache..
DEM_UNKNOWN <> Not Known
NOT_IN_TOWN <> Not in a town
NOT_IN_FAC <> Not in a faction
COMMAND_TIMEOUT <> <20>c[Plan] REPLACE0 Command timed out! Error most likely on console.
ANALYSIS_START <> Analysis | Beginning analysis of user data..
ANALYSIS_BOOT_NOTIFY <> Analysis | Boot analysis in 30 seconds..
ANALYSIS_BOOT <> Analysis | Starting Boot Analysis..
ANALYSIS_FETCH_PLAYERS <> Analysis | Checking for available players..
ANALYSIS_FETCH_DATA <> Analysis | Fetching Data..
ANALYSIS_FAIL_NO_PLAYERS <> Analysis | Analysis failed, no known players.
ANALYSIS_FAIL_NO_DATA <> Analysis | Analysis failed, no data in the database.
ANALYSIS_BEGIN_ANALYSIS <> Analysis | Data Fetched, beginning Analysis of data..
ANALYSIS_COMPLETE <> Analysis | Analysis Complete.
DATA_CORRUPTION_WARN <> Some data might be corrupted: REPLACE0
ERROR_NO_DATA_VIEW <> <20>eWebserver disabled but Alternative IP/PlanLite not used, no way to view data!
ERROR_WEBSERVER_OFF_ANALYSIS <> <20>e[Plan] This command can be only used if the webserver is running on this server.
ERROR_WEBSERVER_OFF_INSPECT <> <20>e[Plan] This command can be only used if webserver/planlite is enabled on this server.
MANAGE_ERROR_INCORRECT_PLUGIN <> <20>c[Plan] Plugin not supported:
MANAGE_PROCESS_START <> <20><>7 Processing data..
MANAGE_ERROR_PLUGIN_NOT_ENABLED <> <20>c[Plan] Plugin is not enabled:
MANAGE_ERROR_INCORRECT_DB <> <20>c[Plan] Incorrect database! (sqlite/mysql accepted):
MANAGE_ERROR_SAME_DB <> <20>c[Plan] Can't move to the same database!
MANAGE_DATABASE_FAILURE <> <20>c[Plan] One of the databases was not initialized properly.
MANAGE_DB_CONFIG_REMINDER <> <20>e[Plan] Remember to swap to the new database and reload plugin
MANAGE_ERROR_NO_PLAYERS <> <20>c[Plan] Database has no player data!
MANAGE_ERROR_BACKUP_FILE_NOT_FOUND <> <20>c[Plan] Backup file doesn't exist!
MANAGE_MOVE_SUCCESS <> <20>a[Plan] All data moved successfully!
MANAGE_COPY_SUCCESS <> <20>a[Plan] All data copied successfully!
MANAGE_PROCESS_FAIL <> <20>c[Plan] Something went wrong while processing the data!
MANAGE_CLEAR_SUCCESS <> <20>a[Plan] All data cleared successfully!
MANAGE_REMOVE_SUCCESS <> <20>f<EFBFBD> <20>2Data of <20>fREPLACE0<45>2 was removed from Database <20>fREPLACE1<45>2.
MANAGE_IMPORTING <> <20>f<EFBFBD> <20>2 Importing Data..
MANAGE_SUCCESS <> <20>f<EFBFBD> <20>2 Success!
CMD_ANALYZE_HEADER <> <20>f<EFBFBD><66>2 Player Analytics - Analysis results
CMD_INSPECT_HEADER <> <20>f<EFBFBD><66>2 Player Analytics - Inspect results:
CMD_INFO_HEADER <> <20>f<EFBFBD><66>2 Player Analytics - Info
CMD_INFO_VERSION <> <20>7 <20><>2<EFBFBD>2 Version: <20>7REPLACE0
CMD_SEARCH_HEADER <> <20>f<EFBFBD><66>2 Player Analytics - Search results for:
CMD_HELP_HEADER <> <20>f<EFBFBD><66>2 Player Analytics - Help
CMD_MANAGE_HELP_HEADER <> <20>f<EFBFBD><66>2 Player Analytics - Managment Help
CMD_MANAGE_STATUS_HEADER <> <20>f<EFBFBD><66>2 Player Analytics - Database status
CMD_MANAGE_STATUS_ACTIVE_DB <> <20>7 <20><>2<EFBFBD>2 Active Database: <20>7REPLACE0
CMD_CLICK_ME <> Click Me
CMD_LINK <> <20>7 <20><>2 Link: <20>f
CMD_RESULTS_AVAILABLE <> <20>7 Results will be available for <20>fREPLACE0<45>7 minutes.
CMD_NO_RESULTS <> <20>7 <20><>2 No results for <20>7REPLACE0<45>2.
CMD_MATCH <> <20>7 Matching player: <20>f
CMD_USG_ANALYZE <> View the Server Analysis
CMD_USG_HELP <> Show command list.
CMD_USG_INFO <> View Version of Plan
CMD_USG_INSPECT <> Inspect Player's Data
CMD_USG_MANAGE <> Database management command
CMD_USG_MANAGE_BACKUP <> Backup a database to .db file
CMD_USG_MANAGE_RESTORE <> Restore a database from a backup file
CMD_USG_MANAGE_MOVE <> Copy data from one database to another & overwrite values
CMD_USG_MANAGE_COMBINE <> Copy data from one database to another & combine values
CMD_USG_MANAGE_IMPORT <> Import Data from supported plugins to Active Database.
CMD_USG_MANAGE_CLEAR <> Clear data from one database
CMD_USG_MANAGE_REMOVE <> Remove players's data from the Active Database.
CMD_USG_MANAGE_STATUS <> Check the status of the Active Database.
CMD_USG_MANAGE_HELP <> Show management help.
CMD_USG_MANAGE_HOTSWAP <> Hotswap to another database & restart the plugin
CMD_USG_RELOAD <> Reload plugin config & save cached data
CMD_USG_SEARCH <> Search for player
ARG_SEARCH <> <part of playername>
ARG_PLAYER <> <player>
ARG_RESTORE <> <Filename.db> <dbTo> [-a]
ARG_IMPORT <> <plugin> [-a]
ARG_MOVE <> <fromDB> <toDB> [-a]
USE_RESTORE <> Use /plan manage restore <Filename.db> <dbTo> [-a]
USE_MANAGE <> Use /plan manage for help
USE_PLAN <> Use /plan for help
USE_MOVE <> Use /plan manage move <fromDB> <toDB> [-a]
USE_COMBINE <> Use /plan manage combine <fromDB> <toDB> [-a]
USE_IMPORT <> Use /plan manage import <plugin> [-a]
WARN_REWRITE <> Data in REPLACE0-database will be rewritten!
WARN_OVERWRITE <> Data in REPLACE0-database will be overwritten!
WARN_OVERWRITE_SOME <> Some data in REPLACE0-database will be overwritten!
WARN_REMOVE <> Data in REPLACE0-database will be removed!
COMMAND_SENDER_NOT_PLAYER <> <20>c[Plan] This command can be only used as a player.
COMMAND_REQUIRES_ARGUMENTS <> <20>c[Plan] Command requires arguments. REPLACE0
COMMAND_ADD_CONFIRMATION_ARGUMENT <> <20>c[Plan] Add -a to confirm execution! REPLACE0
COMMAND_REQUIRES_ARGUMENTS_ONE <> <20>c[Plan] Command requires one argument.
COMMAND_NO_PERMISSION <> <20>c[Plan] You do not have the required permission.
<<<<<<HTML>>>>>>
WARN_INACCURATE <> <div class="warn">Data might be inaccurate, player has just registered.</div>
BANNED <> | <span class="darkred">Banned</span>
OPERATOR <> , Operator (Op)
ONLINE <> | <span class="darkgreen">Online</span>
OFFLINE <> | <span class="darkred">Offline</span>
ACTIVE <> | Player is Active
INACTIVE <> | Player is inactive
ERROR_LIST <> Error Creating List</p>
HIDDEN <> Hidden (config)
FACTION_NOT_FOUND <> Faction not found
FACTION_NO_LEADER <> No leader
FACTION_NO_FACTIONS <> No Factions
WARPS <> <br/>Warps: REPLACE0
ACHIEVEMENTS <> <br/>Achievements: REPLACE0/REPLACE1
JAILED <> | Jailed
MUTED <> | Muted
VOTES <> <br/>Has voted REPLACE0times
FACTION <> <br/>Faction: REPLACE0 | Power: REPLACE1/REPLACE2
TOWN <> <br/>Town: REPLACE0
TOWN_NO_TOWNS <> No Towns
GRAPH_BANNED <> Banned
GRAPH_UNKNOWN <> Unknown
GRAPH_INACTIVE <> Inactive
GRAPH_ACTIVE <> Active
TABLE_SESSIONS_START <> <table class="sortable table"><thead><tr><th>Session Started</th><th>Session Ended</th><th>Session Length</th></tr></thead><tbody>
TABLE_FACTIONS_START <> <table class="sortable table"><thead><tr><th>Faction</th><th>Power</th><th>Land</th><th>Leader</th></tr></thead><tbody>
TABLE_TOWNS_START <> <table class="sortable table"><thead><tr><th>Town</th><th>Residents</th><th>Land</th><th>Mayor</th></tr></thead><tbody>
ERROR_TABLE_2 <> <tr><td><b>No data</b></td><td>No data</td></tr>
SESSIONDATA_NONE <> No Session Data available

View File

@ -1,138 +0,0 @@
ENABLED <> Player Analytics Käynnistetty.
DISABLED <> Player Analytics Sammutettu.
RELOAD_COMPLETE <> §a[Plan] Reload suoritettu.
CACHE_SAVE <> Tallennetaan välimuistin tietoja..
CACHE_ADD <> REPLACE0 lisätty välimuistiin.
CACHE_REMOVE <> REPLACE0 poistettu välimuistista.
CONFIG_HEADER <> Plan Config | More info at https://www.spigotmc.org/wiki/plan-configuration/
DB_INIT <> Tietokannan käynnistys..
WEBSERVER_INIT <> WebServerin käynnistys..
WEBSERVER_CLOSE <> Suljetaan WebServer..
WEBSERVER_RUNNING <> Webserver puörii PORTILLA REPLACE0
DB_CONNECTION_FAIL <> REPLACE0-Tietokantayhteys ei onnistunut: REPLACE1
DB_ESTABLISHED <> REPLACE0-yhteys luotu.
DB_TYPE_DOES_NOT_EXIST <> Tietokantatyyppiä ei tueta.
DB_FAILURE_DISABLE <> Tietokannan käynnistys epäonnistui, suljetaan Plan.
NOTIFY_EMPTY_IP <> §e[Plan] IP server.properties-tiedostossa on tyhjä & AlternativeServerIP-asetusta ei käytetä, plugin antaa virheellisiä linkkejä!
VERSION_NEW_AVAILABLE <> Uusi versio (REPLACE0) on saatavilla: https://www.spigotmc.org/resources/plan-player-analytics.32536/
VERSION_LATEST <> Käytät viimeisintä versiota
VERSION_CHECK_ERROR <> Virhe vertaillessa versioita.
VERSION_FAIL <> Virhe haettaessa versionumeroa.
USERNAME_NOT_VALID <> §c[Plan] Pelaajaa ei ole olemassa.
USERNAME_NOT_SEEN <> §c[Plan] Pelaaja ei ole pelannut tällä serverillä.
USERNAME_NOT_KNOWN <> §c[Plan] Pelaajaa ei löytynyt tietokannasta.
GRABBING_DATA_MESSAGE <> »§2 Haetaan tietoja välimuistiin..
DEM_UNKNOWN <> Ei tiedossa
NOT_IN_TOWN <> Ei kylässä
NOT_IN_FAC <> Ei killassa
COMMAND_TIMEOUT <> §c[Plan] REPLACE0 Komennon aikakatkaisu. Virhe tod.näk. konsolissa
ANALYSIS_START <> Analysis | Aloitetaan analyysi..
ANALYSIS_BOOT_NOTIFY <> Analysis | Käynnistyksen yhteinen analyysi 30 sekunnin kuluttua..
ANALYSIS_BOOT <> Analysis | Aloitetaan käynnistyksen yhteinen analyysi..
ANALYSIS_FETCH_PLAYERS <> Analysis | Tarkistetaan saatavilla olevia pelaajia..
ANALYSIS_FETCH_DATA <> Analysis | Haetaan dataa..
ANALYSIS_FAIL_NO_PLAYERS <> Analysis | Analyysi epäonnistui, ei pelaajia.
ANALYSIS_FAIL_NO_DATA <> Analysis | Analyysi epäonnistui, ei tietoa tietokannassa.
ANALYSIS_BEGIN_ANALYSIS <> Analysis | Tieto haettu, aloitetaan tiedon työstäminen..
ANALYSIS_COMPLETE <> Analysis | Analyysi valmis.
DATA_CORRUPTION_WARN <> Jonkun data voi olla korruptoitunut: REPLACE0
ERROR_NO_DATA_VIEW <> §eWebserver on poissa käytössä eikä Alternative IP ole käytössä, no way to view data!
ERROR_WEBSERVER_OFF_ANALYSIS <> §e[Plan] Tätä komentoa voi käyttää vain jos Webserver pyörii serverillä.
ERROR_WEBSERVER_OFF_INSPECT <> §e[Plan] Tätä komentoa voi käyttää vain jos Webserver pyörii serverillä.
MANAGE_ERROR_INCORRECT_PLUGIN <> §c[Plan] Pluginia ei tueta:
MANAGE_PROCESS_START <> Ȥ7 Prosessoidaan tietoa..
MANAGE_ERROR_PLUGIN_NOT_ENABLED <> §c[Plan] Plugin ei ole käynnissä:
MANAGE_ERROR_INCORRECT_DB <> §c[Plan] Väärä tietokanta! (sqlite/mysql hyväksytään):
MANAGE_ERROR_SAME_DB <> §c[Plan] Et voi siirtää tietoa samaan tietokantaan!
MANAGE_DATABASE_FAILURE <> §c[Plan] Toinen tietokannoista ei käynnistynyt kunnolla.
MANAGE_DB_CONFIG_REMINDER <> §e[Plan] Muista vaihtaa uuteen tietokantaan ja ladata Plan uudelleen.
MANAGE_ERROR_NO_PLAYERS <> §c[Plan] Tietokannassa ei ole tietoa!
MANAGE_ERROR_BACKUP_FILE_NOT_FOUND <> §c[Plan] Varmuuskopio-tiedostoa ei ole olemassa!
MANAGE_MOVE_SUCCESS <> §a[Plan] Kaikki tieto siirretty onnistuneesti!
MANAGE_COPY_SUCCESS <> §a[Plan] Kaikki tieto kopioitu onnistuneesti!
MANAGE_PROCESS_FAIL <> §c[Plan] Jokin meni pieleen työstäessä tietoa!
MANAGE_CLEAR_SUCCESS <> §a[Plan] Kaikki tieto poistettu onnistuneesti!
MANAGE_REMOVE_SUCCESS <> §f» §2§fREPLACE0n§2 tiedot poistettiin §fREPLACE1§2-tietokannasta.
MANAGE_IMPORTING <> §f» §2 Tuodaan tietoa..
MANAGE_SUCCESS <> §f» §2 Onnistui!
CMD_ANALYZE_HEADER <> §f»§2 Player Analytics - Analyysin tulokset
CMD_INSPECT_HEADER <> §f»§2 Player Analytics - Inspect tulokset:
CMD_INFO_HEADER <> §f»§2 Player Analytics - Info
CMD_INFO_VERSION <> §7 •§2§2 Versio: §7REPLACE0
CMD_SEARCH_HEADER <> §f»§2 Player Analytics - Haun tulokset:
CMD_HELP_HEADER <> §f»§2 Player Analytics - Apua
CMD_MANAGE_HELP_HEADER <> §f»§2 Player Analytics - Managment-komennon apu
CMD_MANAGE_STATUS_HEADER <> §f»§2 Player Analytics - Tietokannan tila
CMD_MANAGE_STATUS_ACTIVE_DB <> §7 •§2§2 Aktiivinen tietokanta: §7REPLACE0
CMD_CLICK_ME <> Klikkaa minua!
CMD_LINK <> §7 •§2 Linkki: §f
CMD_RESULTS_AVAILABLE <> §7 Tulokset saatavilla §fREPLACE0§7 minuuttia.
CMD_NO_RESULTS <> §7 •§2 Ei tuloksia §7REPLACE0§2.
CMD_MATCH <> §7 Vastaava pelaaja: §f
CMD_USG_ANALYZE <> Tarkastele analyysia
CMD_USG_HELP <> Tarkastele komentoja.
CMD_USG_INFO <> Tarkasta Plan-versio
CMD_USG_INSPECT <> Tarkastele pelaajan tietoja
CMD_USG_MANAGE <> Tietokannan hallinta komento
CMD_USG_MANAGE_BACKUP <> Varmuuskopioi tietokanta .db-tiedostoon
CMD_USG_MANAGE_RESTORE <> Palauta varmuuskopio tiedostosta
CMD_USG_MANAGE_MOVE <> Kopioi tiedot yhdestä tietokannasta toiseen ja korvaa edelliset arvot
CMD_USG_MANAGE_COMBINE <> Kopioi tiedot yhdestä tietokannasta toiseen ja yhdistä arvot
CMD_USG_MANAGE_IMPORT <> Tuo dataa tuetuista plugineista aktiiviseen tietokantaan
CMD_USG_MANAGE_CLEAR <> Tyhjennä tiedot tietokannasta
CMD_USG_MANAGE_REMOVE <> Poista pelaajan tiedot aktiivisesta tietokannasta.
CMD_USG_MANAGE_STATUS <> Tarkista aktiivisen tietokannan tila.
CMD_USG_MANAGE_HELP <> Näytä manage-komennon apu.
CMD_USG_MANAGE_HOTSWAP <> Vaihda tietokantaa ja lataa Plan uudelleen
CMD_USG_RELOAD <> Lataa Plan-config ja tallenna välimuisti
CMD_USG_SEARCH <> Etsi pelaajaa
ARG_SEARCH <> <nimen osa>
ARG_PLAYER <> <pelaaja>
ARG_RESTORE <> <Tiedostonimi.db> <tietokantaanDB> [-a]
ARG_IMPORT <> <plugin> [-a]
ARG_MOVE <> <tietokannastaDB> <tietokantaanDB> [-a]
USE_RESTORE <> Käytä /plan manage restore <Tiedostonimi.db> <tietokantaanDB> [-a]
USE_MANAGE <> Käytä /plan nähdäksesi apu
USE_PLAN <> Käytä /plan nähdäksesi apu
USE_MOVE <> Käytä /plan manage move <tietokannastaDB> <tietokantaanDB> [-a]
USE_COMBINE <> Käytä /plan manage combine <tietokannastaDB> <tietokantaanDB> [-a]
USE_IMPORT <> Käytä /plan manage import <plugin> [-a]
WARN_REWRITE <> Tiedot REPLACE0-tietokannassa uudelleenkirjoitetaan!
WARN_OVERWRITE <> Tiedot REPLACE0-tietokannassa ylikirjoitetaan!
WARN_OVERWRITE_SOME <> Osa tiedoista REPLACE0-tietokannassa ylikirjoitetaan!
WARN_REMOVE <> Tiedot REPLACE0-tietokannasta poistetaan!
COMMAND_SENDER_NOT_PLAYER <> §c[Plan] Tätä komentoa voi käyttää vain pelaaja.
COMMAND_REQUIRES_ARGUMENTS <> §c[Plan] Komento tarvii argumentteja. REPLACE0
COMMAND_ADD_CONFIRMATION_ARGUMENT <> §c[Plan] Lisää -a vahvistaaksesi komennon ajo! REPLACE0
COMMAND_REQUIRES_ARGUMENTS_ONE <> §c[Plan] Komento tarvii yhden argumentin.
COMMAND_NO_PERMISSION <> §c[Plan] Ei oo lupaa!
<<<<<<HTML>>>>>>
WARN_INACCURATE <> <div class="warn">Tiedot voivat olla epätarkkoja, pelaaja rekisteröityi juuri.</div>
BANNED <> | <span class="darkred">Pannassa</span>
OPERATOR <> , Operaattori (Op)
ONLINE <> | <span class="darkgreen">Online</span>
OFFLINE <> | <span class="darkred">Offline</span>
ACTIVE <> | Pelaaja on aktiivinen
INACTIVE <> | Pelaaja on inaktiivinen
ERROR_LIST <> Virhe luodessa listaa</p>
HIDDEN <> Piilotettu (config)
FACTION_NOT_FOUND <> Kiltaa ei löytynyt
FACTION_NO_LEADER <> Ei johtajaa
FACTION_NO_FACTIONS <> Ei kiltoja
WARPS <> <br/>Warpit: REPLACE0
ACHIEVEMENTS <> <br/>Achievementit: REPLACE0/REPLACE1
JAILED <> | Vankilassa
MUTED <> | Mutetettu
VOTES <> <br/>On äänestänyt REPLACE0kertaa
FACTION <> <br/>Kilta: REPLACE0 | Voima: REPLACE1/REPLACE2
TOWN <> <br/>Kylä: REPLACE0
TOWN_NO_TOWNS <> Ei kyliä
GRAPH_BANNED <> Pannassa
GRAPH_UNKNOWN <> Ei tiedossa
GRAPH_INACTIVE <> Inaktiivi
GRAPH_ACTIVE <> Aktiivinen
TABLE_SESSIONS_START <> <table class="sortable table"><thead><tr><th>Sessio alkoi</th><th>Sessio loppui</th><th>Session pituus</th></tr></thead><tbody>
TABLE_FACTIONS_START <> <table class="sortable table"><thead><tr><th>Kilta</th><th>Voima</th><th>Maa</th><th>Johtaja</th></tr></thead><tbody>
TABLE_TOWNS_START <> <table class="sortable table"><thead><tr><th>Kylä</th><th>Asukkaita</th><th>Maa</th><th>Pormestari</th></tr></thead><tbody>
ERROR_TABLE_2 <> <tr><td><b>Ei dataa</b></td><td>Ei dataa</td></tr>
SESSIONDATA_NONE <> Ei sessio dataa saatavilla

View File

@ -4,41 +4,76 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.djrapitops</groupId>
<artifactId>Plan</artifactId>
<version>3.7.0</version>
<version>4.0.0</version>
<packaging>jar</packaging>
<repositories>
<repository>
<id>plan-repo</id>
<url>http://repo.fuzzlemann.de/artifactory/libs-release/</url>
</repository>
<repository>
<id>plan-snapshot-repo</id>
<url>http://repo.fuzzlemann.de/artifactory/libs-snapshot/</url>
<id>bungeecord-repo</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</repository>
</repositories>
<dependencies>
<!-- PaperSpigot 1.12 built with Buildtools for Database classes.-->
<!-- PaperSpigot 1.12 -->
<dependency>
<groupId>com.destroystokyo.paper</groupId>
<artifactId>paper</artifactId>
<version>1.12-R0.1-20170725.202533-1</version>
<scope>provided</scope>
</dependency>
<!-- Framework for easier plugin development-->
<!-- BungeeCord -->
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>1.12-SNAPSHOT</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.6</version>
<scope>compile</scope>
</dependency>
<!-- Geo IP -->
<dependency>
<groupId>com.maxmind.geoip2</groupId>
<artifactId>geoip2</artifactId>
<version>2.9.0</version>
</dependency>
<!-- Framework for easier plugin development -->
<dependency>
<groupId>com.djrapitops</groupId>
<artifactId>abstract-plugin-framework</artifactId>
<version>2.0.4</version>
<version>2.0.5</version>
<scope>compile</scope>
</dependency>
<!-- SoftDepended Plugins-->
<!-- Connection Pool -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.1.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.4.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
<scope>compile</scope>
</dependency>
<!-- SoftDepended Plugins -->
<dependency>
<groupId>com.djrapitops</groupId>
<artifactId>PlanPluginBridge</artifactId>
<version>3.7.0</version>
<version>4.0.0</version>
<scope>compile</scope>
</dependency>
<!-- -->
<!-- Testing -->
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock</artifactId>
@ -107,10 +142,26 @@
<directory>${basedir}/src/main/resources</directory>
<includes>
<include>*.keystore</include>
<include>*.js</include>
<include>*.css</include>
<include>*.yml</include>
<include>*.html</include>
<include>*.txt</include>
</includes>
<excludes>
<exclude>licence.yml</exclude>
</excludes>
</resource>
<resource>
<targetPath>.</targetPath>
<directory>${basedir}/src/main/resources/html</directory>
<includes>
<include>*.html</include>
</includes>
</resource>
<resource>
<targetPath>.</targetPath>
<directory>${basedir}/src/main/resources/js</directory>
<includes>
<include>*.js</include>
</includes>
</resource>
</resources>
@ -136,6 +187,7 @@
</execution>
</executions>
<configuration>
<minimizeJar>true</minimizeJar>
<artifactSet>
<excludes>
<exclude>org.powermock:*</exclude>
@ -145,7 +197,8 @@
<exclude>xpp3:*</exclude>
<exclude>org.objenesis:*</exclude>
<exclude>cglib:*</exclude>
<exclude>org.*:*</exclude>
<exclude>org.bukkit:*</exclude>
<exclude>org.mockito:*</exclude>
<exclude>org.easymock:*</exclude>
<exclude>junit:*</exclude>
</excludes>

View File

@ -1,6 +1,7 @@
package main.java.com.djrapitops.plan;
import com.djrapitops.plugin.utilities.log.DebugInfo;
import com.djrapitops.plugin.utilities.log.PluginLog;
import main.java.com.djrapitops.plan.utilities.MiscUtils;
import java.util.Collection;
@ -28,7 +29,7 @@ public class Log {
* @param message "Message" will show up as [INFO][Plan]: Message
*/
public static void info(String message) {
Plan.getInstance().getPluginLogger().info(message);
getPluginLogger().info(message);
}
/**
@ -37,7 +38,7 @@ public class Log {
* @param message Message to send.
*/
public static void infoColor(String message) {
Plan.getInstance().getPluginLogger().infoColor(message);
getPluginLogger().infoColor(message);
}
/**
@ -46,7 +47,7 @@ public class Log {
* @param message "Message" will show up as [ERROR][Plan]: Message
*/
public static void error(String message) {
Plan.getInstance().getPluginLogger().error(message);
getPluginLogger().error(message);
}
/**
@ -55,7 +56,7 @@ public class Log {
* @param message "Message" will show up as [INFO][Plan]: [DEBUG] Message
*/
public static void debug(String message) {
Plan.getInstance().getPluginLogger().debug(message);
getPluginLogger().debug(message);
}
@ -77,7 +78,6 @@ public class Log {
* @param messages All messages to add to the debug log.
* @return full debug complex so far.
*/
@SafeVarargs
public static DebugInfo debug(String task, String... messages) {
DebugInfo debug = getDebug(task);
long time = MiscUtils.getTime();
@ -94,7 +94,7 @@ public class Log {
* @return full debug complex so far.
*/
public static DebugInfo getDebug(String task) {
return Plan.getInstance().getPluginLogger().getDebug(task);
return getPluginLogger().getDebug(task);
}
/**
@ -120,19 +120,45 @@ public class Log {
* Logs trace of caught Exception to Errors.txt and notifies on console.
*
* @param source Class name the exception was caught in.
* @param e Throwable, eg NullPointerException
* @param e {@code Throwable}, eg NullPointerException
*/
public static void toLog(String source, Throwable e) {
Plan.getInstance().getPluginLogger().toLog(source, e);
getPluginLogger().toLog(source, e);
}
/**
* Logs multiple caught Errors to Errors.txt.
*
* @param source Class name the exception was caught in.
* @param e Collection of Throwables, eg NullPointerException
* @param e Collection of {@code Throwable}, eg NullPointerException
*/
public static void toLog(String source, Collection<Throwable> e) {
Plan.getInstance().getPluginLogger().toLog(source, e);
}
private static PluginLog getPluginLogger() {
return MiscUtils.getIPlan().getPluginLogger();
}
public static void logStackTrace(Throwable e) {
error(e.toString());
for (StackTraceElement stackTraceElement : e.getStackTrace()) {
error(" " + stackTraceElement);
}
Throwable cause = e.getCause();
if (cause != null) {
logCause(cause);
}
}
private static void logCause(Throwable e) {
error("caused by: " + e.toString());
for (StackTraceElement stackTraceElement : e.getStackTrace()) {
error(" " + stackTraceElement);
}
Throwable cause = e.getCause();
if (cause != null) {
logCause(cause);
}
}
}

View File

@ -24,33 +24,41 @@ import com.djrapitops.plugin.api.TimeAmount;
import com.djrapitops.plugin.settings.ColorScheme;
import com.djrapitops.plugin.task.AbsRunnable;
import com.djrapitops.plugin.task.ITask;
import com.djrapitops.plugin.task.RunnableFactory;
import com.djrapitops.plugin.utilities.Verify;
import main.java.com.djrapitops.plan.api.API;
import main.java.com.djrapitops.plan.api.IPlan;
import main.java.com.djrapitops.plan.api.exceptions.DatabaseInitException;
import main.java.com.djrapitops.plan.command.PlanCommand;
import main.java.com.djrapitops.plan.command.commands.RegisterCommandFilter;
import main.java.com.djrapitops.plan.data.additional.HookHandler;
import main.java.com.djrapitops.plan.data.cache.AnalysisCacheHandler;
import main.java.com.djrapitops.plan.data.cache.DataCacheHandler;
import main.java.com.djrapitops.plan.data.cache.InspectCacheHandler;
import main.java.com.djrapitops.plan.data.cache.PageCacheHandler;
import main.java.com.djrapitops.plan.data.listeners.*;
import main.java.com.djrapitops.plan.database.Database;
import main.java.com.djrapitops.plan.database.databases.MySQLDB;
import main.java.com.djrapitops.plan.database.databases.SQLiteDB;
import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg;
import main.java.com.djrapitops.plan.ui.webserver.WebServer;
import main.java.com.djrapitops.plan.systems.cache.DataCache;
import main.java.com.djrapitops.plan.systems.cache.GeolocationCache;
import main.java.com.djrapitops.plan.systems.info.BukkitInformationManager;
import main.java.com.djrapitops.plan.systems.info.ImporterManager;
import main.java.com.djrapitops.plan.systems.info.InformationManager;
import main.java.com.djrapitops.plan.systems.info.pluginchannel.BukkitPluginChannelListener;
import main.java.com.djrapitops.plan.systems.info.server.BukkitServerInfoManager;
import main.java.com.djrapitops.plan.systems.listeners.*;
import main.java.com.djrapitops.plan.systems.processing.Processor;
import main.java.com.djrapitops.plan.systems.processing.importing.importers.OfflinePlayerImporter;
import main.java.com.djrapitops.plan.systems.queue.ProcessingQueue;
import main.java.com.djrapitops.plan.systems.tasks.TPSCountTimer;
import main.java.com.djrapitops.plan.systems.webserver.PageCache;
import main.java.com.djrapitops.plan.systems.webserver.WebServer;
import main.java.com.djrapitops.plan.utilities.Benchmark;
import main.java.com.djrapitops.plan.utilities.Check;
import main.java.com.djrapitops.plan.utilities.MiscUtils;
import main.java.com.djrapitops.plan.utilities.metrics.BStats;
import org.apache.logging.log4j.LogManager;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.UUID;
/**
* Main class for Bukkit that manages the plugin.
@ -61,21 +69,23 @@ import java.util.concurrent.ScheduledExecutorService;
* @author Rsl1122
* @since 1.0.0
*/
public class Plan extends BukkitPlugin<Plan> {
public class Plan extends BukkitPlugin<Plan> implements IPlan {
private API api;
private DataCacheHandler handler;
private InspectCacheHandler inspectCache;
private AnalysisCacheHandler analysisCache;
private ProcessingQueue processingQueue;
private HookHandler hookHandler; // Manages 3rd party data sources
private Database db;
private Set<Database> databases;
private WebServer uiServer;
private WebServer webServer;
private BukkitInformationManager infoManager;
private BukkitServerInfoManager serverInfoManager;
private ServerVariableHolder serverVariableHolder;
private TPSCountTimer tpsCountTimer;
private int bootAnalysisTaskID = -1;
/**
@ -103,6 +113,14 @@ public class Plan extends BukkitPlugin<Plan> {
return (Plan) getPluginInstance(Plan.class);
}
public static UUID getServerUUID() {
return getInstance().getServerUuid();
}
public UUID getServerUuid() {
return serverInfoManager.getServerUUID();
}
/**
* OnEnable method.
* <p>
@ -124,7 +142,8 @@ public class Plan extends BukkitPlugin<Plan> {
Benchmark.start("Enable");
// Initialize Locale
GeolocationCache.checkDB();
new Locale(this).loadLocale();
Benchmark.start("Reading server variables");
@ -133,72 +152,46 @@ public class Plan extends BukkitPlugin<Plan> {
Benchmark.start("Copy default config");
getConfig().options().copyDefaults(true);
getConfig().options().header("Plan Config | More info at https://www.spigotmc.org/wiki/plan-configuration/");
getConfig().options().header("Plan Config | More info at https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/documentation/Configuration.md");
saveConfig();
Benchmark.stop("Enable", "Copy default config");
Benchmark.start("Init Database");
Log.info(Locale.get(Msg.ENABLE_DB_INIT).toString());
if (Check.errorIfFalse(initDatabase(), Locale.get(Msg.ENABLE_DB_FAIL_DISABLE_INFO).toString())) {
Log.info(Locale.get(Msg.ENABLE_DB_INFO).parse(db.getConfigName()));
} else {
disablePlugin();
return;
}
initDatabase();
Benchmark.stop("Enable", "Init Database");
Benchmark.start("Init DataCache");
this.handler = new DataCacheHandler(this);
this.inspectCache = new InspectCacheHandler(this);
this.analysisCache = new AnalysisCacheHandler(this);
Benchmark.stop("Enable", "Init DataCache");
Benchmark.start("WebServer Initialization");
webServer = new WebServer(this);
processingQueue = new ProcessingQueue();
serverInfoManager = new BukkitServerInfoManager(this);
infoManager = new BukkitInformationManager(this);
webServer.initServer();
if (!webServer.isEnabled()) {
Log.error("WebServer was not successfully initialized.");
}
Benchmark.stop("Enable", "WebServer Initialization");
super.getRunnableFactory().createNew(new TPSCountTimer(this)).runTaskTimer(1000, TimeAmount.SECOND.ticks());
registerListeners();
registerTasks();
this.api = new API(this);
Benchmark.start("Handle Reload");
handler.handleReload();
Benchmark.stop("Enable", "Handle Reload");
Benchmark.start("Analysis refresh task registration");
// Analysis refresh settings
boolean bootAnalysisIsEnabled = Settings.ANALYSIS_REFRESH_ON_ENABLE.isTrue();
int analysisRefreshMinutes = Settings.ANALYSIS_AUTO_REFRESH.getNumber();
boolean analysisRefreshTaskIsEnabled = analysisRefreshMinutes > 0;
// Analysis refresh tasks
if (bootAnalysisIsEnabled) {
startBootAnalysisTask();
}
if (analysisRefreshTaskIsEnabled) {
startAnalysisRefreshTask(analysisRefreshMinutes);
}
Benchmark.stop("Enable", "Analysis refresh task registration");
Benchmark.start("WebServer Initialization");
// Data view settings
boolean webserverIsEnabled = Settings.WEBSERVER_ENABLED.isTrue();
boolean usingBungeeWebServer = infoManager.isUsingAnotherWebServer();
boolean usingAlternativeIP = Settings.SHOW_ALTERNATIVE_IP.isTrue();
boolean usingAlternativeUI = Settings.USE_ALTERNATIVE_UI.isTrue();
boolean hasDataViewCapability = usingAlternativeIP || usingAlternativeUI || webserverIsEnabled;
uiServer = new WebServer(this);
if (webserverIsEnabled) {
uiServer.initServer();
if (!uiServer.isEnabled()) {
Log.error("WebServer was not successfully initialized.");
}
setupFilter();
} else if (!hasDataViewCapability) {
Log.infoColor(Locale.get(Msg.ENABLE_NOTIFY_NO_DATA_VIEW).toString());
}
if (!usingAlternativeIP && serverVariableHolder.getIp().isEmpty()) {
Log.infoColor(Locale.get(Msg.ENABLE_NOTIFY_EMPTY_IP).toString());
}
Benchmark.stop("Enable", "WebServer Initialization");
if (usingBungeeWebServer && usingAlternativeIP) {
// TODO Move to Locale
Log.info("Make sure that the alternative IP points to Bungee Server: " + Settings.ALTERNATIVE_IP.toString());
}
registerCommand(new PlanCommand(this));
@ -206,20 +199,78 @@ public class Plan extends BukkitPlugin<Plan> {
hookHandler = new HookHandler(this);
Benchmark.stop("Enable", "Hook to 3rd party plugins");
ImporterManager.registerImporter(new OfflinePlayerImporter());
// if (Settings.BUNGEE_OVERRIDE_STANDALONE_MODE.isFalse()) {
// registerPluginChannelListener();
// }
BStats bStats = new BStats(this);
bStats.registerMetrics();
Log.debug("Verbose debug messages are enabled.");
Log.logDebug("Enable", Benchmark.stop("Enable", "Enable"));
Log.info(Locale.get(Msg.ENABLED).toString());
new ShutdownHook(this);
} catch (Exception e) {
Log.error("Plugin Failed to Initialize Correctly.");
Log.toLog(this.getClass().getName(), e);
Log.logStackTrace(e);
disablePlugin();
}
}
private final void initColorScheme() {
private void registerPluginChannelListener() {
Bukkit.getMessenger().registerOutgoingPluginChannel(this, "BungeeCord");
Bukkit.getMessenger().registerIncomingPluginChannel(this, "Plan", new BukkitPluginChannelListener(this));
}
private void registerTasks() {
RunnableFactory runnableFactory = getRunnableFactory();
String bootAnalysisMsg = Locale.get(Msg.ENABLE_BOOT_ANALYSIS_INFO).toString();
String bootAnalysisRunMsg = Locale.get(Msg.ENABLE_BOOT_ANALYSIS_RUN_INFO).toString();
Benchmark.start("Task Registration");
tpsCountTimer = new TPSCountTimer(this);
runnableFactory.createNew(tpsCountTimer).runTaskTimer(1000, TimeAmount.SECOND.ticks());
// Analysis refresh settings
int analysisRefreshMinutes = Settings.ANALYSIS_AUTO_REFRESH.getNumber();
boolean analysisRefreshTaskIsEnabled = analysisRefreshMinutes > 0;
long analysisPeriod = analysisRefreshMinutes * TimeAmount.MINUTE.ticks();
Log.info(bootAnalysisMsg);
ITask bootAnalysisTask = runnableFactory.createNew("BootAnalysisTask", new AbsRunnable() {
@Override
public void run() {
Log.info(bootAnalysisRunMsg);
infoManager.refreshAnalysis(getServerUUID());
this.cancel();
}
}).runTaskLaterAsynchronously(30 * TimeAmount.SECOND.ticks());
bootAnalysisTaskID = bootAnalysisTask.getTaskId();
if (analysisRefreshTaskIsEnabled) {
runnableFactory.createNew("PeriodicalAnalysisTask", new AbsRunnable() {
@Override
public void run() {
infoManager.refreshAnalysis(getServerUUID());
}
}).runTaskTimerAsynchronously(analysisPeriod, analysisPeriod);
}
runnableFactory.createNew("PeriodicNetworkBoxRefreshTask", new AbsRunnable() {
@Override
public void run() {
infoManager.updateNetworkPageContent();
}
}).runTaskTimerAsynchronously(TimeAmount.SECOND.ticks(), TimeAmount.MINUTE.ticks() * 5L);
Benchmark.stop("Enable", "Task Registration");
}
private void initColorScheme() {
try {
ChatColor mainColor = ChatColor.getByChar(Settings.COLOR_MAIN.toString().charAt(1));
ChatColor secColor = ChatColor.getByChar(Settings.COLOR_SEC.toString().charAt(1));
@ -233,63 +284,44 @@ public class Plan extends BukkitPlugin<Plan> {
/**
* Disables the plugin.
* <p>
* Stops the webserver, cancels all tasks and saves cache to the database.
*/
@Override
public void onDisable() {
//Clears the page cache
PageCacheHandler.clearCache();
PageCache.clearCache();
// Stop the UI Server
if (uiServer != null) {
uiServer.stop();
if (webServer != null) {
webServer.stop();
}
// Processes unprocessed processors
if (processingQueue != null) {
List<Processor> processors = processingQueue.stopAndReturnLeftovers();
Log.info("Processing unprocessed processors. (" + processors.size() + ")"); // TODO Move to Locale
for (Processor processor : processors) {
processor.process();
}
}
getServer().getScheduler().cancelTasks(this);
if (Verify.notNull(handler, db)) {
Benchmark.start("Disable: DataCache Save");
// Saves the DataCache to the database without Bukkit's Schedulers.
Log.info(Locale.get(Msg.DISABLE_CACHE_SAVE).toString());
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.execute(() -> {
handler.saveCacheOnDisable();
taskStatus().cancelAllKnownTasks();
Benchmark.stop("Disable: DataCache Save");
});
scheduler.shutdown(); // Schedules the save to shutdown after it has ran the execute method.
if (Verify.notNull(infoManager, db)) {
taskStatus().cancelAllKnownTasks();
}
getPluginLogger().endAllDebugs();
Log.info(Locale.get(Msg.DISABLED).toString());
// Locale.unload();
}
private void registerListeners() {
Benchmark.start("Register Listeners");
registerListener(new PlanPlayerListener(this));
boolean chatListenerIsEnabled = Check.isTrue(Settings.GATHERCHAT.isTrue(), Locale.get(Msg.ENABLE_NOTIFY_DISABLED_CHATLISTENER).toString());
boolean commandListenerIsEnabled = Check.isTrue(Settings.GATHERCOMMANDS.isTrue(), Locale.get(Msg.ENABLE_NOTIFY_DISABLED_COMMANDLISTENER).toString());
boolean deathListenerIsEnabled = Check.isTrue(Settings.GATHERKILLS.isTrue(), Locale.get(Msg.ENABLE_NOTIFY_DISABLED_DEATHLISTENER).toString());
if (chatListenerIsEnabled) {
registerListener(new PlanChatListener(this));
}
registerListener(new PlanChatListener(this));
registerListener(new PlanGamemodeChangeListener(this));
registerListener(new PlanWorldChangeListener(this));
if (commandListenerIsEnabled) {
registerListener(new PlanCommandPreprocessListener(this));
}
if (deathListenerIsEnabled) {
registerListener(new PlanDeathEventListener(this));
}
registerListener(new PlanCommandPreprocessListener(this));
registerListener(new PlanDeathEventListener(this));
Benchmark.stop("Enable", "Register Listeners");
}
@ -300,7 +332,7 @@ public class Plan extends BukkitPlugin<Plan> {
*
* @return true if init was successful, false if not.
*/
public boolean initDatabase() {
private void initDatabase() throws DatabaseInitException {
databases = new HashSet<>();
databases.add(new MySQLDB(this));
databases.add(new SQLiteDB(this));
@ -315,85 +347,20 @@ public class Plan extends BukkitPlugin<Plan> {
}
}
if (!Verify.notNull(db)) {
Log.info(Locale.get(Msg.ENABLE_FAIL_WRONG_DB).toString() + " " + dbType);
return false;
if (db == null) {
throw new DatabaseInitException(Locale.get(Msg.ENABLE_FAIL_WRONG_DB).toString() + " " + dbType);
}
return Check.errorIfFalse(db.init(), Locale.get(Msg.ENABLE_DB_FAIL_DISABLE_INFO).toString());
}
private void startAnalysisRefreshTask(int everyXMinutes) {
Benchmark.start("Schedule PeriodicAnalysisTask");
if (everyXMinutes <= 0) {
return;
}
getRunnableFactory().createNew("PeriodicalAnalysisTask", new AbsRunnable() {
@Override
public void run() {
Log.debug("Running PeriodicalAnalysisTask");
if (!analysisCache.isCached() || MiscUtils.getTime() - analysisCache.getData().getRefreshDate() > TimeAmount.MINUTE.ms()) {
analysisCache.updateCache();
}
}
}).runTaskTimerAsynchronously(everyXMinutes * TimeAmount.MINUTE.ticks(), everyXMinutes * TimeAmount.MINUTE.ticks());
Benchmark.stop("Schedule PeriodicAnalysisTask");
}
private void startBootAnalysisTask() {
Benchmark.start("Schedule boot analysis task");
String bootAnalysisMsg = Locale.get(Msg.ENABLE_BOOT_ANALYSIS_INFO).toString();
String bootAnalysisRunMsg = Locale.get(Msg.ENABLE_BOOT_ANALYSIS_RUN_INFO).toString();
Log.info(bootAnalysisMsg);
ITask bootAnalysisTask = getRunnableFactory().createNew("BootAnalysisTask", new AbsRunnable() {
@Override
public void run() {
Log.debug("Running BootAnalysisTask");
Log.info(bootAnalysisRunMsg);
analysisCache.updateCache();
this.cancel();
}
}).runTaskLaterAsynchronously(30 * TimeAmount.SECOND.ticks());
bootAnalysisTaskID = bootAnalysisTask.getTaskId();
Benchmark.stop("Enable", "Schedule boot analysis task");
}
/**
* Setups the command console output filter
*/
private void setupFilter() {
org.apache.logging.log4j.core.Logger logger = (org.apache.logging.log4j.core.Logger) LogManager.getRootLogger();
logger.addFilter(new RegisterCommandFilter());
}
/**
* Used to access AnalysisCache.
*
* @return Current instance of the AnalysisCacheHandler
*/
public AnalysisCacheHandler getAnalysisCache() {
return analysisCache;
}
/**
* Used to access InspectCache.
*
* @return Current instance of the InspectCacheHandler
*/
public InspectCacheHandler getInspectCache() {
return inspectCache;
db.init();
}
/**
* Used to access Cache.
*
* @return Current instance of the DataCacheHandler
* @return Current instance of the DataCache
*/
public DataCacheHandler getHandler() {
return handler;
public DataCache getDataCache() {
return getInfoManager().getDataCache();
}
/**
@ -406,12 +373,12 @@ public class Plan extends BukkitPlugin<Plan> {
}
/**
* Used to access Webserver.
* Used to access WebServer.
*
* @return the Webserver
* @return the WebServer
*/
public WebServer getUiServer() {
return uiServer;
public WebServer getWebServer() {
return webServer;
}
/**
@ -453,4 +420,41 @@ public class Plan extends BukkitPlugin<Plan> {
public ServerVariableHolder getVariable() {
return serverVariableHolder;
}
/**
* Used to get the object storing server info
*
* @return BukkitServerInfoManager
* @see BukkitServerInfoManager
*/
public BukkitServerInfoManager getServerInfoManager() {
return serverInfoManager;
}
public ProcessingQueue getProcessingQueue() {
return processingQueue;
}
public TPSCountTimer getTpsCountTimer() {
return tpsCountTimer;
}
public void addToProcessQueue(Processor... processors) {
for (Processor processor : processors) {
if (processor == null) {
continue;
}
processingQueue.addToQueue(processor);
}
}
public InformationManager getInfoManager() {
return infoManager;
}
public void restart() {
onDisable();
reloadConfig();
onEnable();
}
}

View File

@ -0,0 +1,190 @@
/*
* Licence is provided in the jar as license.yml also here:
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
*/
package main.java.com.djrapitops.plan;
import com.djrapitops.plugin.BungeePlugin;
import com.djrapitops.plugin.settings.ColorScheme;
import com.djrapitops.plugin.task.AbsRunnable;
import main.java.com.djrapitops.plan.api.IPlan;
import main.java.com.djrapitops.plan.api.exceptions.DatabaseInitException;
import main.java.com.djrapitops.plan.command.commands.ReloadCommand;
import main.java.com.djrapitops.plan.database.Database;
import main.java.com.djrapitops.plan.database.databases.MySQLDB;
import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg;
import main.java.com.djrapitops.plan.systems.info.BungeeInformationManager;
import main.java.com.djrapitops.plan.systems.info.InformationManager;
import main.java.com.djrapitops.plan.systems.info.server.BungeeServerInfoManager;
import main.java.com.djrapitops.plan.systems.listeners.BungeePlayerListener;
import main.java.com.djrapitops.plan.systems.processing.Processor;
import main.java.com.djrapitops.plan.systems.queue.ProcessingQueue;
import main.java.com.djrapitops.plan.systems.webserver.WebServer;
import main.java.com.djrapitops.plan.utilities.Benchmark;
import net.md_5.bungee.api.ChatColor;
import java.io.InputStream;
import java.util.List;
import java.util.UUID;
/**
* Bungee Main class.
*
* @author Rsl1122
*/
public class PlanBungee extends BungeePlugin<PlanBungee> implements IPlan {
private WebServer webServer;
private Database db;
private BungeeServerInfoManager serverInfoManager;
private BungeeInformationManager infoManager;
private ServerVariableHolder variableHolder;
private ProcessingQueue processingQueue;
@Override
public void onEnable() {
try {
super.setInstance(this);
super.copyDefaultConfig("Plan Config | More info at https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/documentation/Configuration.md");
super.setDebugMode(Settings.DEBUG.toString());
super.getPluginLogger().setFolder(getDataFolder());
super.setColorScheme(new ColorScheme(ChatColor.GREEN, ChatColor.GRAY, ChatColor.WHITE));
super.setLogPrefix("[Plan]");
super.setUpdateCheckUrl("https://raw.githubusercontent.com/Rsl1122/Plan-PlayerAnalytics/master/Plan/src/main/resources/plugin.yml");
super.setUpdateUrl("https://www.spigotmc.org/resources/plan-player-analytics.32536/");
super.onEnableDefaultTasks();
variableHolder = new ServerVariableHolder(getProxy());
new Locale(this).loadLocale();
Log.info(Locale.get(Msg.ENABLE_DB_INIT).toString());
initDatabase();
registerCommand(new ReloadCommand(this));
String ip = variableHolder.getIp();
if ("0.0.0.0".equals(ip)) {
Log.error("IP setting still 0.0.0.0 - Configure AlternativeIP/IP that connects to the Proxy server.");
Log.info("Player Analytics partially enabled (Use /planbungee to reload config)");
return;
}
Benchmark.start("WebServer Initialization");
webServer = new WebServer(this);
serverInfoManager = new BungeeServerInfoManager(this);
infoManager = new BungeeInformationManager(this);
webServer.initServer();
if (!webServer.isEnabled()) {
Log.error("WebServer was not successfully initialized.");
disablePlugin();
return;
}
getRunnableFactory().createNew("Enable Bukkit Connection Task", new AbsRunnable() {
@Override
public void run() {
infoManager.attemptConnection();
infoManager.sendConfigSettings();
}
}).runTaskAsynchronously();
// getProxy().registerChannel("Plan");
// registerListener(new BungeePluginChannelListener(this));
processingQueue = new ProcessingQueue();
registerListener(new BungeePlayerListener(this));
Benchmark.stop("Enable", "WebServer Initialization");
Log.info(Locale.get(Msg.ENABLED).toString());
} catch (Exception e) {
Log.error("Plugin Failed to Initialize Correctly.");
Log.logStackTrace(e);
disablePlugin();
}
}
public static PlanBungee getInstance() {
return getInstance(PlanBungee.class);
}
@Override
public void onDisable() {
if (processingQueue != null) {
List<Processor> processors = processingQueue.stopAndReturnLeftovers();
Log.info("Processing unprocessed processors. (" + processors.size() + ")");
for (Processor processor : processors) {
processor.process();
}
}
Log.info(Locale.get(Msg.DISABLED).toString());
}
private void initDatabase() throws DatabaseInitException {
db = new MySQLDB(this);
db.init();
}
@Override
public Database getDB() {
return db;
}
public BungeeServerInfoManager getServerInfoManager() {
return serverInfoManager;
}
@Override
public InformationManager getInfoManager() {
return infoManager;
}
@Override
public WebServer getWebServer() {
return webServer;
}
@Override
public ProcessingQueue getProcessingQueue() {
return processingQueue;
}
@Override
public void addToProcessQueue(Processor... processors) {
for (Processor processor : processors) {
processingQueue.addToQueue(processor);
}
}
@Override
public InputStream getResource(String resource) {
return getResourceAsStream(resource);
}
@Override
public ServerVariableHolder getVariable() {
return variableHolder;
}
public static UUID getServerUUID() {
return getInstance().getServerUuid();
}
public UUID getServerUuid() {
return serverInfoManager.getServerUUID();
}
@Override
public void restart() {
onDisable();
onEnable();
}
}

View File

@ -0,0 +1,167 @@
/*
* Licence is provided in the jar as license.yml also here:
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
*/
package main.java.com.djrapitops.plan;
import com.djrapitops.plugin.config.IConfig;
import com.djrapitops.plugin.config.fileconfig.IFileConfig;
import com.djrapitops.plugin.utilities.Verify;
import org.bukkit.configuration.file.FileConfiguration;
import java.io.IOException;
import java.util.Map;
import java.util.UUID;
/**
* Bungee Config manager for Server Settings such as:
* - WebServer Port
* - ServerName
* - Theme Base
*
* @author Rsl1122
*/
public class ServerSpecificSettings {
public void addOriginalBukkitSettings(PlanBungee plugin, UUID serverUUID, Map<String, Object> settings) {
try {
IConfig iConfig = plugin.getIConfig();
IFileConfig config = iConfig.getConfig();
if (!Verify.isEmpty(config.getString("Servers." + serverUUID + ".ServerName"))) {
return;
}
for (Map.Entry<String, Object> entry : settings.entrySet()) {
config.set("Servers." + serverUUID + "." + entry.getKey(), entry.getValue());
}
iConfig.save();
} catch (IOException e) {
Log.toLog(this.getClass().getName(), e);
}
}
public static void updateSettings(Plan plugin, Map<String, String> settings) {
Log.debug("Checking new settings..");
FileConfiguration config = plugin.getConfig();
boolean changedSomething = false;
for (Map.Entry<String, String> setting : settings.entrySet()) {
try {
String path = setting.getKey();
if ("sender".equals(path)) {
continue;
}
String stringValue = setting.getValue();
Object value = getValue(stringValue);
String currentValue = config.get(path).toString();
if (stringValue.equals(currentValue)) {
continue;
}
config.set(path, value);
Log.debug(" " + path + ": " + value);
} catch (NullPointerException e) {
}
changedSomething = true;
}
if (changedSomething) {
plugin.saveConfig();
Log.info("----------------------------------");
Log.info("The Received Bungee Settings changed the config values, restarting Plan..");
Log.info("----------------------------------");
plugin.restart();
} else {
Log.debug("Settings up to date");
}
}
private static Object getValue(String value) {
try {
return Integer.parseInt(value);
} catch (Exception ignored) {
}
if ("true".equalsIgnoreCase(value)) {
return true;
} else if ("false".equalsIgnoreCase(value)) {
return false;
}
return value;
}
private String getPath(UUID serverUUID, Settings setting) {
String path = "Servers." + serverUUID;
switch (setting) {
case WEBSERVER_PORT:
path += ".WebServerPort";
break;
case SERVER_NAME:
path += ".ServerName";
break;
case THEME_BASE:
path += ".ThemeBase";
break;
default:
break;
}
return path;
}
public Object get(UUID serverUUID, Settings setting) {
try {
IFileConfig config = PlanBungee.getInstance().getIConfig().getConfig();
String path = getPath(serverUUID, setting);
String value = config.getString(path);
try {
return Boolean.parseBoolean(value);
} catch (Exception e) {
if (Verify.isEmpty(value)) {
return config.getInt(value);
}
return value;
}
} catch (IOException e) {
Log.toLog(this.getClass().getName(), e);
}
return null;
}
public boolean getBoolean(UUID serverUUID, Settings setting) {
try {
IFileConfig config = PlanBungee.getInstance().getIConfig().getConfig();
String path = getPath(serverUUID, setting);
return config.getBoolean(path);
} catch (IOException e) {
Log.toLog(this.getClass().getName(), e);
}
return false;
}
public String getString(UUID serverUUID, Settings setting) {
try {
IFileConfig config = PlanBungee.getInstance().getIConfig().getConfig();
String path = getPath(serverUUID, setting);
return config.getString(path);
} catch (IOException e) {
Log.toLog(this.getClass().getName(), e);
}
return null;
}
public Integer getInt(UUID serverUUID, Settings setting) {
try {
IFileConfig config = PlanBungee.getInstance().getIConfig().getConfig();
String path = getPath(serverUUID, setting);
return config.getInt(path);
} catch (IOException e) {
Log.toLog(this.getClass().getName(), e);
}
return null;
}
public void set(UUID serverUUID, Settings setting, Object value) throws IOException {
IConfig iConfig = PlanBungee.getInstance().getIConfig();
IFileConfig config = iConfig.getConfig();
String path = getPath(serverUUID, setting);
config.set(path, value);
iConfig.save();
}
}

View File

@ -1,5 +1,6 @@
package main.java.com.djrapitops.plan;
import net.md_5.bungee.api.ProxyServer;
import org.bukkit.Server;
/**
@ -11,7 +12,12 @@ import org.bukkit.Server;
*/
public class ServerVariableHolder {
private final String name;
private final int port;
private final String version;
private final String implVersion;
private final String ip;
private final int maxPlayers;
private final boolean usingPaper;
/**
@ -21,10 +27,32 @@ public class ServerVariableHolder {
*/
public ServerVariableHolder(Server server) {
ip = server.getIp();
name = server.getName();
port = server.getPort();
version = server.getVersion();
implVersion = server.getBukkitVersion();
String serverName = server.getName();
usingPaper = serverName.equals("Paper")
|| serverName.equals("TacoSpigot"); //Fork of Paper
maxPlayers = server.getMaxPlayers();
usingPaper = name.equals("Paper")
|| name.equals("TacoSpigot"); //Fork of Paper
}
/**
* Constructor, grabs the variables.
*
* @param server instance the plugin is running on.
*/
public ServerVariableHolder(ProxyServer server) {
ip = Settings.BUNGEE_IP.toString();
name = "BungeeCord";
port = -1;
version = server.getVersion();
implVersion = server.getVersion();
maxPlayers = server.getConfig().getPlayerLimit();
usingPaper = false;
}
/**
@ -44,4 +72,24 @@ public class ServerVariableHolder {
public boolean isUsingPaper() {
return usingPaper;
}
public String getName() {
return name;
}
public int getPort() {
return port;
}
public String getVersion() {
return version;
}
public String getImplVersion() {
return implVersion;
}
public int getMaxPlayers() {
return maxPlayers;
}
}

View File

@ -1,5 +1,10 @@
package main.java.com.djrapitops.plan;
import com.djrapitops.plugin.config.fileconfig.BukkitFileConfig;
import com.djrapitops.plugin.config.fileconfig.IFileConfig;
import com.djrapitops.plugin.utilities.Compatibility;
import java.io.IOException;
import java.util.List;
/**
@ -10,86 +15,92 @@ import java.util.List;
* @since 2.3.2
*/
public enum Settings {
// Boolean
WEBSERVER_ENABLED("Settings.WebServer.Enabled"),
ANALYSIS_REFRESH_ON_ENABLE("Settings.Cache.AnalysisCache.RefreshAnalysisCacheOnEnable"),
ANALYSIS_LOG_TO_CONSOLE("Settings.Analysis.LogProgressOnConsole"),
ANALYSIS_LOG_FINISHED("Settings.Analysis.NotifyWhenFinished"),
ANALYSIS_EXPORT("Settings.Analysis.Export.Enabled"),
SHOW_ALTERNATIVE_IP("Settings.WebServer.ShowAlternativeServerIP"),
USE_ALTERNATIVE_UI("Settings.UseTextUI"),
GATHERCHAT("Settings.Data.ChatListener"),
GATHERKILLS("Settings.Data.GatherKillData"),
GATHERCOMMANDS("Settings.Data.GatherCommandUsage"),
DO_NOT_LOG_UNKNOWN_COMMANDS("Customization.Data.DoNotLogUnknownCommands"),
COMBINE_COMMAND_ALIASES_TO_MAIN_COMMAND("Customization.Data.CombineCommandAliasesToMainCommand"),
SECURITY_IP_UUID("Settings.WebServer.Security.DisplayIPsAndUUIDs"),
PLAYERLIST_SHOW_IMAGES("Customization.SmallHeadImagesOnAnalysisPlayerlist"),
WRITE_NEW_LOCALE("Settings.WriteNewLocaleFileOnStart"),
// Boolean
BUNGEE_COPY_CONFIG("Plugin.Bungee-Override.CopyBungeeConfig"),
BUNGEE_OVERRIDE_STANDALONE_MODE("Plugin.Bungee-Override.StandaloneMode"),
ANALYSIS_EXPORT("Analysis.Export.Enabled"),
SHOW_ALTERNATIVE_IP("Commands.AlternativeIP.Enabled"),
LOG_UNKNOWN_COMMANDS("Data.Commands.LogUnknownCommands"),
COMBINE_COMMAND_ALIASES("Data.Commands.CombineCommandAliases"),
WRITE_NEW_LOCALE("Plugin.WriteNewLocaleFileOnStart"),
DEV_MODE("Plugin.Dev"),
// Integer
ANALYSIS_MINUTES_FOR_ACTIVE("Settings.Analysis.MinutesPlayedUntilConsidiredActive"),
SAVE_CACHE_MIN("Settings.Cache.DataCache.SaveEveryXMinutes"),
CLEAR_INSPECT_CACHE("Settings.Cache.InspectCache.ClearFromInspectCacheAfterXMinutes"),
CLEAR_CACHE_X_SAVES("Settings.Cache.DataCache.ClearCacheEveryXSaves"),
WEBSERVER_PORT("Settings.WebServer.Port"),
ANALYSIS_AUTO_REFRESH("Settings.Cache.AnalysisCache.RefreshEveryXMinutes"),
PROCESS_GET_LIMIT("Settings.Cache.Processing.GetLimit"),
PROCESS_SAVE_LIMIT("Settings.Cache.Processing.SaveLimit"),
PROCESS_CLEAR_LIMIT("Settings.Cache.Processing.ClearLimit"),
TPS_GRAPH_HIGH("Customization.Colors.HTML.TPSGraph.TPSHigh"),
TPS_GRAPH_MED("Customization.Colors.HTML.TPSGraph.TPSMedium"),
WEBSERVER_PORT("WebServer.Port"),
DB_PORT("Database.MySQL.Port"),
ANALYSIS_AUTO_REFRESH("Analysis.AutoRefreshPeriod"),
// String
DEBUG("Settings.Debug"),
ALTERNATIVE_IP("Settings.WebServer.AlternativeIP"),
DB_TYPE("database.type"),
DEM_TRIGGERS("Customization.DemographicsTriggers.Trigger"),
DEM_FEMALE("Customization.DemographicsTriggers.Female"),
DEM_MALE("Customization.DemographicsTriggers.Male"),
DEM_IGNORE("Customization.DemographicsTriggers.IgnoreWhen"),
LOCALE("Settings.Locale"),
WEBSERVER_IP("Settings.WebServer.InternalIP"),
ANALYSIS_EXPORT_PATH("Settings.Analysis.Export.DestinationFolder"),
WEBSERVER_CERTIFICATE_PATH("Settings.WebServer.Security.Certificate.KeyStorePath"),
WEBSERVER_CERTIFICATE_KEYPASS("Settings.WebServer.Security.Certificate.KeyPass"),
WEBSERVER_CERTIFICATE_STOREPASS("Settings.WebServer.Security.Certificate.StorePass"),
WEBSERVER_CERTIFICATE_ALIAS("Settings.WebServer.Security.Certificate.Alias"),
LINK_PROTOCOL("Settings.WebServer.ExternalWebServerLinkProtocol"),
DEBUG("Plugin.Debug"),
ALTERNATIVE_IP("Commands.AlternativeIP.Link"),
DB_TYPE("Database.Type"),
DB_HOST("Database.MySQL.Host"),
DB_USER("Database.MySQL.User"),
DB_PASS("Database.MySQL.Password"),
DB_DATABASE("Database.MySQL.Database"),
LOCALE("Plugin.Locale"),
WEBSERVER_IP("WebServer.InternalIP"),
ANALYSIS_EXPORT_PATH("Analysis.Export.DestinationFolder"),
WEBSERVER_CERTIFICATE_PATH("WebServer.Security.SSL-Certificate.KeyStorePath"),
WEBSERVER_CERTIFICATE_KEYPASS("WebServer.Security.SSL-Certificate.KeyPass"),
WEBSERVER_CERTIFICATE_STOREPASS("WebServer.Security.SSL-Certificate.StorePass"),
WEBSERVER_CERTIFICATE_ALIAS("WebServer.Security.SSL-Certificate.Alias"),
EXTERNAL_WEBSERVER_LINK_PROTOCOL("Analysis.Export.ExternalWebServerLinkProtocol"),
//
SERVER_NAME("Customization.ServerName"),
SERVER_NAME("Server.ServerName"),
//
FORMAT_YEAR("Customization.Formats.TimeAmount.Year"),
FORMAT_YEARS("Customization.Formats.TimeAmount.Years"),
FORMAT_DAY("Customization.Formats.TimeAmount.Day"),
FORMAT_DAYS("Customization.Formats.TimeAmount.Days"),
FORMAT_HOURS("Customization.Formats.TimeAmount.Hours"),
FORMAT_MINUTES("Customization.Formats.TimeAmount.Minutes"),
FORMAT_SECONDS("Customization.Formats.TimeAmount.Seconds"),
FORMAT_DECIMALS("Customization.Formats.DecimalPoints"),
FORMAT_YEAR("Customization.Formatting.TimeAmount.Year"),
FORMAT_YEARS("Customization.Formatting.TimeAmount.Years"),
FORMAT_MONTH("Customization.Formatting.TimeAmount.Month"),
FORMAT_MONTHS("Customization.Formatting.TimeAmount.Months"),
FORMAT_DAY("Customization.Formatting.TimeAmount.Day"),
FORMAT_DAYS("Customization.Formatting.TimeAmount.Days"),
FORMAT_HOURS("Customization.Formatting.TimeAmount.Hours"),
FORMAT_MINUTES("Customization.Formatting.TimeAmount.Minutes"),
FORMAT_SECONDS("Customization.Formatting.TimeAmount.Seconds"),
FORMAT_DECIMALS("Customization.Formatting.DecimalPoints"),
//
COLOR_MAIN("Customization.Colors.Commands.Main"),
COLOR_SEC("Customization.Colors.Commands.Secondary"),
COLOR_TER("Customization.Colors.Commands.Highlight"),
COLOR_MAIN("Commands.Colors.Main"),
COLOR_SEC("Commands.Colors.Secondary"),
COLOR_TER("Commands.Colors.Highlight"),
//
HCOLOR_MAIN("Customization.Colors.HTML.UI.Main"),
HCOLOR_MAIN_DARK("Customization.Colors.HTML.UI.MainDark"),
HCOLOR_SEC("Customization.Colors.HTML.UI.Secondary"),
HCOLOR_TER("Customization.Colors.HTML.UI.Tertiary"),
HCOLOR_TER_DARK("Customization.Colors.HTML.UI.TertiaryDark"),
HCOLOR_TPS_HIGH("Customization.Colors.HTML.TPSGraph.TPSHighCol"),
HCOLOR_TPS_MED("Customization.Colors.HTML.TPSGraph.TPSMediumCol"),
HCOLOR_TPS_LOW("Customization.Colors.HTML.TPSGraph.TPSLowCol"),
HCOLOR_ACT_ONL("Customization.Colors.HTML.ActivityGraph.OnlinePlayers"),
HCOLOR_ACTP_ACT("Customization.Colors.HTML.ActivityPie.Active"),
HCOLOR_ACTP_BAN("Customization.Colors.HTML.ActivityPie.Banned"),
HCOLOR_ACTP_INA("Customization.Colors.HTML.ActivityPie.Inactive"),
HCOLOR_ACTP_JON("Customization.Colors.HTML.ActivityPie.JoinedOnce"),
HCOLOR_GMP_0("Customization.Colors.HTML.GamemodePie.Survival"),
HCOLOR_GMP_1("Customization.Colors.HTML.GamemodePie.Creative"),
HCOLOR_GMP_2("Customization.Colors.HTML.GamemodePie.Adventure"),
HCOLOR_GMP_3("Customization.Colors.HTML.GamemodePie.Spectator"),
THEME_BASE("Theme.Base"),
THEME_FONT_STYLESHEET("Theme.Font.FontStyleSheet"),
THEME_FONT_FAMILY("Theme.Font.FontFamily"),
THEME_FONT_COLOR_DARK("Theme.Font.Color.Dark"),
THEME_FONT_COLOR_LIGHT("Theme.Font.Color.Light"),
THEME_COLOR_MAIN("Theme.Colors.Main"),
THEME_COLOR_MAIN_DARK("Theme.Colors.Main-Dark"),
THEME_COLOR_SECONDARY("Theme.Colors.Secondary"),
THEME_COLOR_SECONDARY_DARK("Theme.Colors.Secondary-Dark"),
THEME_COLOR_TERTIARY("Theme.Colors.Tertiary"),
THEME_COLOR_BACKGROUND("Theme.Colors.Background"),
THEME_COLOR_TABLE_DARK("Theme.Colors.Table-Dark"),
THEME_COLOR_TABLE_LIGHT("Theme.Colors.Table-Light"),
THEME_GRAPH_PUNCHCARD("Theme.Graphs.PunchCard"),
THEME_GRAPH_PLAYERS_ONLINE("Theme.Graphs.PlayersOnline"),
THEME_GRAPH_TPS_THRESHOLD_HIGH("Theme.Graphs.TPS.High-Threshold"),
THEME_GRAPH_TPS_THRESHOLD_MED("Theme.Graphs.TPS.Medium-Threshold"),
THEME_GRAPH_TPS_HIGH("Theme.Graphs.TPS.High"),
THEME_GRAPH_TPS_MED("Theme.Graphs.TPS.Medium"),
THEME_GRAPH_TPS_LOW("Theme.Graphs.TPS.Low"),
THEME_GRAPH_CPU("Theme.Graphs.CPU"),
THEME_GRAPH_RAM("Theme.Graphs.RAM"),
THEME_GRAPH_CHUNKS("Theme.Graphs.Chunks"),
THEME_GRAPH_ENTITIES("Theme.Graphs.Entities"),
THEME_GRAPH_WORLD_PIE("Theme.Graphs.WorldPie"),
THEME_GRAPH_GM_PIE("Theme.Graphs.GMDrilldown"),
THEME_GRAPH_ACTIVITY_PIE("Theme.Graphs.ActivityPie"),
THEME_GRAPH_SERVER_PREF_PIE("Theme.Graphs.ServerPreferencePie"),
// StringList
HIDE_FACTIONS("Customization.Plugins.Factions.HideFactions"),
HIDE_TOWNS("Customization.Plugins.Towny.HideTowns");
HIDE_FACTIONS("Plugins.Factions.HideFactions"),
HIDE_TOWNS("Plugins.Towny.HideTowns"),
//
// Bungee
BUNGEE_IP("Server.IP"),
BUNGEE_NETWROK_NAME("Network.Name");
private static final ServerSpecificSettings serverSpecificSettings = new ServerSpecificSettings();
private final String configPath;
private Boolean value;
@ -107,7 +118,11 @@ public enum Settings {
if (value != null) {
return value;
}
return Plan.getInstance().getConfig().getBoolean(configPath);
return getConfig().getBoolean(configPath);
}
public boolean isFalse() {
return !isTrue();
}
public void setValue(Boolean value) {
@ -121,7 +136,7 @@ public enum Settings {
*/
@Override
public String toString() {
return Plan.getInstance().getConfig().getString(configPath);
return getConfig().getString(configPath);
}
/**
@ -130,11 +145,11 @@ public enum Settings {
* @return Integer value of the config setting
*/
public int getNumber() {
return Plan.getInstance().getConfig().getInt(configPath);
return getConfig().getInt(configPath);
}
public List<String> getStringList() {
return Plan.getInstance().getConfig().getStringList(configPath);
return getConfig().getStringList(configPath);
}
/**
@ -146,4 +161,24 @@ public enum Settings {
public String getPath() {
return configPath;
}
private IFileConfig getConfig() {
try {
if (Compatibility.isBukkitAvailable()) {
return new BukkitFileConfig(Plan.getInstance().getConfig());
} else {
return PlanBungee.getInstance().getIConfig().getConfig();
}
} catch (IOException e) {
throw new IllegalStateException("Config could not be loaded.", e);
}
}
public static ServerSpecificSettings serverSpecific() {
if (!Compatibility.isBungeeAvailable()) {
throw new IllegalStateException("Not supposed to call this method on Bukkit");
}
return serverSpecificSettings;
}
}

View File

@ -0,0 +1,98 @@
/*
* Licence is provided in the jar as license.yml also here:
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
*/
package main.java.com.djrapitops.plan;
import main.java.com.djrapitops.plan.api.exceptions.DatabaseInitException;
import main.java.com.djrapitops.plan.data.Action;
import main.java.com.djrapitops.plan.data.Session;
import main.java.com.djrapitops.plan.database.databases.SQLDB;
import main.java.com.djrapitops.plan.database.tables.Actions;
import main.java.com.djrapitops.plan.database.tables.SessionsTable;
import main.java.com.djrapitops.plan.systems.cache.DataCache;
import main.java.com.djrapitops.plan.utilities.MiscUtils;
import java.sql.SQLException;
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 active = false;
private static DataCache dataCache;
private static SQLDB db;
public ShutdownHook(Plan plugin) {
if (!active) {
Runtime.getRuntime().addShutdownHook(this);
}
active = true;
db = (SQLDB) plugin.getDB();
dataCache = plugin.getDataCache();
}
@Override
public void run() {
try {
Map<UUID, Session> activeSessions = dataCache.getActiveSessions();
long now = MiscUtils.getTime();
if (db == null) {
return;
}
if (!db.isOpen()) {
db.init();
}
saveFirstSessionInformation(now);
saveActiveSessions(activeSessions, now);
} catch (DatabaseInitException e) {
Log.toLog(this.getClass().getName(), e);
} finally {
if (db != null) {
try {
db.close();
} catch (SQLException e) {
Log.toLog(this.getClass().getName(), e);
}
}
db = null;
dataCache = null;
}
}
private void saveFirstSessionInformation(long now) {
try {
for (Map.Entry<UUID, Integer> entry : dataCache.getFirstSessionMsgCounts().entrySet()) {
UUID uuid = entry.getKey();
int messagesSent = entry.getValue();
db.getActionsTable().insertAction(uuid, new Action(now, Actions.FIRST_LOGOUT, "Messages sent: " + messagesSent));
}
} catch (SQLException e) {
Log.toLog(this.getClass().getName(), e);
}
}
private void saveActiveSessions(Map<UUID, Session> activeSessions, long now) {
SessionsTable sessionsTable = db.getSessionsTable();
for (Map.Entry<UUID, Session> entry : activeSessions.entrySet()) {
UUID uuid = entry.getKey();
Session session = entry.getValue();
session.endSession(now);
try {
sessionsTable.saveSession(uuid, session);
} catch (SQLException e) {
Log.toLog(this.getClass().getName(), e);
}
}
activeSessions.clear();
}
}

View File

@ -5,26 +5,17 @@ import com.djrapitops.plugin.utilities.player.Fetch;
import com.djrapitops.plugin.utilities.player.IOfflinePlayer;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.AnalysisData;
import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.data.additional.AnalysisType;
import main.java.com.djrapitops.plan.data.additional.PluginData;
import main.java.com.djrapitops.plan.data.cache.DBCallableProcessor;
import main.java.com.djrapitops.plan.data.handling.info.HandlingInfo;
import main.java.com.djrapitops.plan.ui.html.DataRequestHandler;
import main.java.com.djrapitops.plan.ui.webserver.WebServer;
import main.java.com.djrapitops.plan.utilities.HtmlUtils;
import main.java.com.djrapitops.plan.systems.info.BukkitInformationManager;
import main.java.com.djrapitops.plan.utilities.uuid.UUIDUtility;
import java.sql.SQLException;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* This class contains the API methods.
* This class contains the API methods for Bukkit version of the plugin.
* <p>
* Methods can be called from Asynchronous task and are thread safe unless
* otherwise stated.
@ -36,8 +27,6 @@ import java.util.stream.Collectors;
* @author Rsl1122
* @see PluginData
* @see AnalysisType
* @see DBCallableProcessor
* @see HandlingInfo
* @since 2.0.0
*/
public class API {
@ -80,7 +69,7 @@ public class API {
}
/**
* Used to get the link to InspectPage of a player.
* Used to get a relative link to InspectPage of a player.
* <p>
* This method is useful if you have a table and want to link to the inspect
* page.
@ -89,79 +78,46 @@ public class API {
* {@code <a href="Link">PlayerName</a>}
*
* @param name Name of the player
* @return ip:port/security/player/PlayerName
* @return ./player/PlayerName
*/
public String getPlayerInspectPageLink(String name) {
return HtmlUtils.getInspectUrlWithProtocol(name);
return "../player/" + name;
}
/**
* Schedule a UserData object to be fetched from the database or cache if
* the player is online.
* <p>
* The data will not be cached if it is not already cached.
*
* @param uuid UUID of the player.
* @param processor Object implementing DBCallableProcessor, which
* process (UserData data) method will be called.
*/
public void scheduleForGet(UUID uuid, DBCallableProcessor processor) {
plugin.getHandler().getUserDataForProcessing(processor, uuid, false);
}
/**
* Schedule a HandlingInfo object to be processed.
* <p>
* UserData associated with the UUID of the HandlingInfo object will be
* cached.
*
* @param info object that extends HandlingInfo.
*/
public void scheduleEventHandlingInfo(HandlingInfo info) {
plugin.getHandler().addToPool(info);
}
/**
* Used to cache a UserData object.
* <p>
* If data is already cached it will be overridden.
*
* @param data UserData object. Will be placed to the data.getUuid() key in
* the cache.
*/
public void placeDataToCache(UserData data) {
plugin.getHandler().cache(data);
}
/**
* Used to save the cached data to the database.
* <p>
* Should be only called from an Asynchronous thread.
*/
public void saveCachedData() {
plugin.getHandler().saveCachedUserData();
}
/**
* Check if the UserData is cached to the InspectCache.
* Check if Players's Inspect page is cached to pagecache.
*
* @param uuid UUID of the player.
* @return true/false
* @deprecated use {@code isPlayerHtmlCached}
*/
@Deprecated
public boolean isPlayersDataInspectCached(UUID uuid) {
return plugin.getInspectCache().isCached(uuid);
return isPlayerHtmlCached(uuid);
}
public boolean isPlayerHtmlCached(UUID uuid) {
return plugin.getInfoManager().isCached(uuid);
}
/**
* Cache the UserData to InspectCache.
* <p>
* Uses cache if data is cached or database if not. Call from an Asynchronous
* thread.
* Cache Players's Inspect page to the PageCache of the WebServer.
*
* @param uuid UUID of the player.
* @deprecated use {@code cachePlayerHtml}
*/
@Deprecated
public void cacheUserDataToInspectCache(UUID uuid) {
cachePlayerHtml(uuid);
}
/**
* Cache Players's Inspect page to the PageCache of the WebServer.
*
* @param uuid UUID of the player.
*/
public void cacheUserDataToInspectCache(UUID uuid) {
plugin.getInspectCache().cache(uuid);
public void cachePlayerHtml(UUID uuid) {
plugin.getInfoManager().cachePlayer(uuid);
}
/**
@ -173,12 +129,7 @@ public class API {
* @return player.html with all placeholders replaced.
*/
public String getPlayerHtmlAsString(UUID uuid) {
WebServer server = plugin.getUiServer();
if (Verify.notNull(server)) {
return server.getDataReqHandler().getInspectHtml(uuid);
}
DataRequestHandler reqH = new DataRequestHandler(plugin);
return reqH.getInspectHtml(uuid);
return plugin.getInfoManager().getPlayerHtml(uuid);
}
/**
@ -187,17 +138,14 @@ public class API {
* @return true/false
*/
public boolean isAnalysisCached() {
return plugin.getAnalysisCache().isCached();
return plugin.getInfoManager().isAnalysisCached(Plan.getServerUUID());
}
/**
* Run's the analysis with the current data in the cache and fetches rest
* from the database.
* <p>
* Starts a new Asynchronous task to run the analysis.
* Run the analysis.
*/
public void updateAnalysisCache() {
plugin.getAnalysisCache().updateCache();
plugin.getInfoManager().refreshAnalysis(plugin.getServerUuid());
}
/**
@ -205,15 +153,10 @@ public class API {
* <p>
* Check if the data is cached to AnalysisCache before calling this.
*
* @return analysis.html with all placeholders replaced.
* @return server.html with all placeholders replaced.
*/
public String getAnalysisHtmlAsString() {
WebServer server = plugin.getUiServer();
if (Verify.notNull(server)) {
return server.getDataReqHandler().getAnalysisHtml();
}
DataRequestHandler reqH = new DataRequestHandler(plugin);
return reqH.getAnalysisHtml();
return plugin.getInfoManager().getAnalysisHtml();
}
/**
@ -225,22 +168,26 @@ public class API {
* @see AnalysisData
*/
public AnalysisData getAnalysisDataFromCache() {
return plugin.getAnalysisCache().getData();
return ((BukkitInformationManager) plugin.getInfoManager()).getAnalysisData();
}
/**
* Used to get the PlayerName of a player who has played on the server.
* Should be called from an Async thread.
*
* @param uuid UUID of the player.
* @return PlayerName, eg "Rsl1122"
* @throws IllegalArgumentException If uuid is null.
* @throws IllegalStateException If the player has not played on the server
* before.
* @throws IllegalStateException If the player has not played on the server before.
*/
public String getPlayerName(UUID uuid) {
public String getPlayerName(UUID uuid) throws SQLException {
Verify.nullCheck(uuid);
String playerName = plugin.getDB().getUsersTable().getPlayerName(uuid);
if (playerName != null) {
return playerName;
}
IOfflinePlayer offlinePlayer = Fetch.getIOfflinePlayer(uuid);
if (Verify.notNull(offlinePlayer)) {
if (offlinePlayer != null) {
return offlinePlayer.getName();
}
throw new IllegalStateException("Player has not played on this server before.");
@ -286,49 +233,4 @@ public class API {
public Collection<UUID> getSavedUUIDs() throws SQLException {
return plugin.getDB().getSavedUUIDs();
}
/**
* Get the saved UserData in the database for a collection of UUIDs.
* <p>
* Will not contain data for UUIDs not found in the database.
* <p>
* Should be called from async thread.
*
* @param uuids Collection of UUIDs that can be found in the database.
* @return List of all Data in the database.
* @throws SQLException If database error occurs.
* @since 3.4.2
*/
public List<UserData> getUserDataOfUsers(Collection<UUID> uuids) throws SQLException {
return plugin.getDB().getUserDataForUUIDS(uuids);
}
/**
* Get the cached UserData objects in the InspectCache.
* <p>
* This can be used with PluginData objects safely to get the data for all
* users in Plan database, because all data is InspectCached before analysis
* begins.
*
* @return List of all Data in the InspectCache.
* @since 3.5.0
*/
public List<UserData> getInspectCachedUserData() {
return plugin.getInspectCache().getCachedUserData();
}
/**
* Get the cached UserData objects in the InspectCache in a Map form.
* <p>
* This can be used with PluginData objects safely to get the data for all
* users in Plan database, because all data is InspectCached before analysis
* begins.
*
* @return Map of all Data in the InspectCache with UUID of the player as
* the key.
* @since 3.5.0
*/
public Map<UUID, UserData> getInspectCachedUserDataMap() {
return getInspectCachedUserData().stream().collect(Collectors.toMap(UserData::getUuid, Function.identity()));
}
}

View File

@ -0,0 +1,48 @@
/*
* Licence is provided in the jar as license.yml also here:
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
*/
package main.java.com.djrapitops.plan.api;
import com.djrapitops.plugin.IPlugin;
import com.djrapitops.plugin.config.IConfig;
import main.java.com.djrapitops.plan.ServerVariableHolder;
import main.java.com.djrapitops.plan.database.Database;
import main.java.com.djrapitops.plan.systems.info.InformationManager;
import main.java.com.djrapitops.plan.systems.processing.Processor;
import main.java.com.djrapitops.plan.systems.queue.ProcessingQueue;
import main.java.com.djrapitops.plan.systems.webserver.WebServer;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;
/**
* Abstraction interface for both Plan and PlanBungee.
*
* @author Rsl1122
*/
public interface IPlan extends IPlugin {
Database getDB();
ServerVariableHolder getVariable();
UUID getServerUuid();
InformationManager getInfoManager();
WebServer getWebServer();
File getDataFolder();
ProcessingQueue getProcessingQueue();
void addToProcessQueue(Processor... processors);
InputStream getResource(String resource);
IConfig getIConfig() throws IOException;
void restart();
}

View File

@ -0,0 +1,21 @@
/*
* Licence is provided in the jar as license.yml also here:
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
*/
package main.java.com.djrapitops.plan.api.exceptions;
/**
* Thrown when something goes wrong with creating tables with Table#createTable.
*
* @author Rsl1122
*/
public class DBCreateTableException extends DatabaseInitException {
public DBCreateTableException(String tableName, String message, Throwable cause) {
super(tableName + ": " + message, cause);
}
public DBCreateTableException(Throwable cause) {
super(cause);
}
}

View File

@ -0,0 +1,25 @@
/*
* Licence is provided in the jar as license.yml also here:
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
*/
package main.java.com.djrapitops.plan.api.exceptions;
/**
* Thrown when something goes wrong in the database, generic exception.
*
* @author Rsl1122
*/
public class DatabaseException extends Exception {
public DatabaseException(String message, Throwable cause) {
super(message, cause);
}
public DatabaseException(Throwable cause) {
super(cause);
}
public DatabaseException(String message) {
super(message);
}
}

View File

@ -0,0 +1,25 @@
/*
* Licence is provided in the jar as license.yml also here:
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
*/
package main.java.com.djrapitops.plan.api.exceptions;
/**
* Thrown when something goes wrong with Database#init.
*
* @author Rsl1122
*/
public class DatabaseInitException extends DatabaseException {
public DatabaseInitException(String message, Throwable cause) {
super(message, cause);
}
public DatabaseInitException(Throwable cause) {
super(cause);
}
public DatabaseInitException(String message) {
super(message);
}
}

View File

@ -0,0 +1,17 @@
/*
* Licence is provided in the jar as license.yml also here:
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
*/
package main.java.com.djrapitops.plan.api.exceptions;
/**
* Exception thrown when Html page parsing fails.
*
* @author Rsl1122
*/
public class ParseException extends Exception {
public ParseException(Throwable cause) {
super(cause);
}
}

View File

@ -0,0 +1,21 @@
/*
* Licence is provided in the jar as license.yml also here:
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
*/
package main.java.com.djrapitops.plan.api.exceptions;
/**
* Thrown when something goes wrong with Plan initialization.
*
* @author Rsl1122
*/
public class PlanEnableException extends Exception {
public PlanEnableException(String message, Throwable cause) {
super(message, cause);
}
public PlanEnableException(String message) {
super(message);
}
}

View File

@ -0,0 +1,21 @@
/*
* Licence is provided in the jar as license.yml also here:
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
*/
package main.java.com.djrapitops.plan.api.exceptions;
/**
* Thrown when WebAPI fails to connect.
*
* @author Rsl1122
*/
public class WebAPIConnectionFailException extends WebAPIException {
public WebAPIConnectionFailException(String message, Throwable cause) {
super(message, cause);
}
public WebAPIConnectionFailException(Throwable cause) {
super(cause);
}
}

View File

@ -0,0 +1,28 @@
/*
* Licence is provided in the jar as license.yml also here:
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
*/
package main.java.com.djrapitops.plan.api.exceptions;
/**
* Thrown when web api post request fails.
*
* @author Rsl1122
*/
public class WebAPIException extends Exception {
public WebAPIException() {
}
public WebAPIException(String message) {
super(message);
}
public WebAPIException(String message, Throwable cause) {
super(message, cause);
}
public WebAPIException(Throwable cause) {
super(cause);
}
}

View File

@ -0,0 +1,16 @@
/*
* Licence is provided in the jar as license.yml also here:
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
*/
package main.java.com.djrapitops.plan.api.exceptions;
/**
* Thrown when WebAPI gets a 403 response.
*
* @author Rsl1122
*/
public class WebAPIForbiddenException extends WebAPIException {
public WebAPIForbiddenException(String url) {
super("Forbidden: " + url);
}
}

View File

@ -0,0 +1,16 @@
/*
* Licence is provided in the jar as license.yml also here:
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
*/
package main.java.com.djrapitops.plan.api.exceptions;
/**
* Thrown when WebAPI returns 404, usually when response is supposed to be false.
*
* @author Rsl1122
*/
public class WebAPINotFoundException extends WebAPIException {
public WebAPINotFoundException() {
super("Not Found");
}
}

View File

@ -0,0 +1,27 @@
/*
* Licence is provided in the jar as license.yml also here:
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
*/
package main.java.com.djrapitops.plan.api.exceptions;
/**
* Thrown when WebUser can not be authorized (WebServer).
*
* @author Rsl1122
*/
public class WebUserAuthException extends Exception {
public WebUserAuthException() {
}
public WebUserAuthException(String message) {
super(message);
}
public WebUserAuthException(String message, Throwable cause) {
super(message, cause);
}
public WebUserAuthException(Throwable cause) {
super(cause);
}
}

View File

@ -2,7 +2,6 @@ package main.java.com.djrapitops.plan.command;
import com.djrapitops.plugin.utilities.Verify;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.Settings;
import java.util.UUID;
@ -21,18 +20,6 @@ public class ConditionUtils {
throw new IllegalStateException("Utility class");
}
/**
* Check if the plugin can display the data.
*
* @return true/false
*/
public static boolean pluginHasViewCapability() {
final boolean usingAlternativeIP = Settings.SHOW_ALTERNATIVE_IP.isTrue();
final boolean webserverIsOn = Settings.WEBSERVER_ENABLED.isTrue();
final boolean usingTextUI = Settings.USE_ALTERNATIVE_UI.isTrue();
return webserverIsOn || usingAlternativeIP || usingTextUI;
}
/**
* Check if the player has played.
*

View File

@ -5,6 +5,7 @@ import com.djrapitops.plugin.command.TreeCommand;
import com.djrapitops.plugin.command.defaultcmds.StatusCommand;
import main.java.com.djrapitops.plan.Permissions;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.Settings;
import main.java.com.djrapitops.plan.command.commands.*;
import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg;
@ -39,20 +40,21 @@ public class PlanCommand extends TreeCommand<Plan> {
@Override
public void addCommands() {
commands.add(new InspectCommand(plugin));
commands.add(new QuickInspectCommand(plugin));
commands.add(new AnalyzeCommand(plugin));
commands.add(new QuickAnalyzeCommand(plugin));
commands.add(new SearchCommand(plugin));
commands.add(new InfoCommand(plugin));
commands.add(new ReloadCommand(plugin));
commands.add(new ManageCommand(plugin));
commands.add(new StatusCommand<>(plugin, Permissions.MANAGE.getPermission()));
commands.add(new ListCommand());
RegisterCommand registerCommand = new RegisterCommand(plugin);
commands.add(registerCommand);
commands.add(new WebUserCommand(plugin, registerCommand));
commands.add(new NetworkCommand(plugin));
commands.add(new ListServersCommand(plugin));
if (plugin.getUiServer().isEnabled()) {
commands.add(new ListCommand());
RegisterCommand registerCommand = new RegisterCommand(plugin);
commands.add(registerCommand);
commands.add(new WebUserCommand(plugin, registerCommand));
if (Settings.DEV_MODE.isTrue()) {
commands.add(new DevCommand(plugin));
}
}
}

View File

@ -1,25 +1,26 @@
package main.java.com.djrapitops.plan.command.commands;
import com.djrapitops.plugin.api.TimeAmount;
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.utilities.Verify;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Permissions;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.Settings;
import main.java.com.djrapitops.plan.command.ConditionUtils;
import main.java.com.djrapitops.plan.data.cache.AnalysisCacheHandler;
import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg;
import main.java.com.djrapitops.plan.ui.text.TextUI;
import main.java.com.djrapitops.plan.utilities.Check;
import main.java.com.djrapitops.plan.utilities.HtmlUtils;
import main.java.com.djrapitops.plan.utilities.MiscUtils;
import main.java.com.djrapitops.plan.systems.info.InformationManager;
import main.java.com.djrapitops.plan.systems.info.server.ServerInfo;
import org.bukkit.ChatColor;
import java.sql.SQLException;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
/**
* This subcommand is used to run the analysis and access the /server link.
*
@ -29,7 +30,7 @@ import org.bukkit.ChatColor;
public class AnalyzeCommand extends SubCommand {
private final Plan plugin;
private final AnalysisCacheHandler analysisCache;
private final InformationManager infoManager;
/**
* Subcommand Constructor.
@ -40,9 +41,36 @@ public class AnalyzeCommand extends SubCommand {
super("analyze, analyse, analysis, a",
CommandType.CONSOLE,
Permissions.ANALYZE.getPermission(),
Locale.get(Msg.CMD_USG_ANALYZE).parse());
Locale.get(Msg.CMD_USG_ANALYZE).parse(),
"[ServerName or ID]");
this.plugin = plugin;
analysisCache = plugin.getAnalysisCache();
infoManager = plugin.getInfoManager();
}
public static void sendAnalysisMessage(Collection<ISender> senders, UUID serverUUID) throws SQLException {
if (Verify.isEmpty(senders)) {
return;
}
Plan plugin = Plan.getInstance();
Optional<String> serverName = plugin.getDB().getServerTable().getServerName(serverUUID);
if (serverName.isPresent()) {
String target = "/server/" + serverName.get();
String url = plugin.getInfoManager().getLinkTo(target);
String message = Locale.get(Msg.CMD_INFO_LINK).toString();
for (ISender sender : senders) {
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());
}
}
}
@Override
@ -52,17 +80,36 @@ public class AnalyzeCommand extends SubCommand {
@Override
public boolean onCommand(ISender sender, String commandLabel, String[] args) {
if (!Check.isTrue(ConditionUtils.pluginHasViewCapability(), Locale.get(Msg.CMD_FAIL_NO_DATA_VIEW).toString(), sender)) {
return true;
// TODO Write a command for listing servers.
UUID serverUUID = Plan.getServerUUID();
if (args.length >= 1 && plugin.getInfoManager().isUsingAnotherWebServer()) {
try {
List<ServerInfo> bukkitServers = plugin.getDB().getServerTable().getBukkitServers();
Optional<ServerInfo> server = bukkitServers.stream().filter(info -> {
StringBuilder idBuilder = new StringBuilder(args[0]);
if (args.length > 1) {
for (int i = 1; i < args.length; i++) {
idBuilder.append(" ").append(args[i]);
}
}
String serverIdentifier = idBuilder.toString();
return Integer.toString(info.getId()).equals(serverIdentifier) || info.getName().equalsIgnoreCase(serverIdentifier);
}).findFirst();
if (server.isPresent()) {
serverUUID = server.get().getUuid();
}
} catch (SQLException e) {
Log.toLog(this.getClass().getName(), e);
return true;
}
}
if (!Check.isTrue(analysisCache.isAnalysisEnabled(), Locale.get(Msg.CMD_INFO_ANALYSIS_TEMP_DISABLE).toString(), sender)
&& !analysisCache.isCached()) {
return true;
}
updateCache(sender, serverUUID);
sender.sendMessage(Locale.get(Msg.CMD_INFO_FETCH_DATA).toString());
if (plugin.getUiServer().isAuthRequired() && CommandUtils.isPlayer(sender)) {
if (plugin.getInfoManager().isAuthRequired() && CommandUtils.isPlayer(sender)) {
plugin.getRunnableFactory().createNew(new AbsRunnable("WebUser exist check task") {
@Override
public void run() {
@ -79,68 +126,15 @@ public class AnalyzeCommand extends SubCommand {
}
}).runTaskAsynchronously();
}
updateCache(sender);
return true;
}
private void updateCache(ISender sender) {
if (!analysisCache.isCached() || MiscUtils.getTime() - analysisCache.getData().getRefreshDate() > TimeAmount.MINUTE.ms()) {
int bootAnID = plugin.getBootAnalysisTaskID();
if (bootAnID != -1) {
plugin.getServer().getScheduler().cancelTask(bootAnID);
}
analysisCache.addNotification(sender);
analysisCache.updateCache();
} else {
analysisCache.sendAnalysisMessage(sender);
private void updateCache(ISender sender, UUID serverUUID) {
int bootAnID = plugin.getBootAnalysisTaskID();
if (bootAnID != -1) {
plugin.getServer().getScheduler().cancelTask(bootAnID);
}
}
private void runMessageSenderTask(ISender sender) {
plugin.getRunnableFactory().createNew("AnalysisMessageSenderTask", new AbsRunnable() {
private int timesRun = 0;
@Override
public void run() {
timesRun++;
if (analysisCache.isCached() && (!analysisCache.isAnalysisBeingRun() || !analysisCache.isAnalysisEnabled())) {
sendAnalysisMessage(sender);
this.cancel();
return;
}
if (timesRun > 10) {
Log.debug("Command Timeout Message, Analysis.");
sender.sendMessage(Locale.get(Msg.CMD_FAIL_TIMEOUT).parse("Analysis"));
this.cancel();
}
}
}).runTaskTimer(TimeAmount.SECOND.ticks(), 5 * TimeAmount.SECOND.ticks());
}
/**
* Used to send the message after /plan analysis.
* <p>
* Final because
*
* @param sender Command sender.
*/
private void sendAnalysisMessage(ISender sender) {
boolean textUI = Settings.USE_ALTERNATIVE_UI.isTrue();
sender.sendMessage(Locale.get(Msg.CMD_HEADER_ANALYZE).toString());
if (textUI) {
sender.sendMessage(TextUI.getAnalysisMessages());
} else {
// Link
String url = HtmlUtils.getServerAnalysisUrlWithProtocol();
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());
infoManager.addAnalysisNotification(sender, serverUUID);
infoManager.refreshAnalysis(serverUUID);
}
}

View File

@ -0,0 +1,86 @@
/*
* Licence is provided in the jar as license.yml also here:
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
*/
package main.java.com.djrapitops.plan.command.commands;
import com.djrapitops.plugin.command.CommandType;
import com.djrapitops.plugin.command.ISender;
import com.djrapitops.plugin.command.SubCommand;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.api.exceptions.WebAPIException;
import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg;
import main.java.com.djrapitops.plan.systems.webserver.webapi.WebAPI;
import main.java.com.djrapitops.plan.systems.webserver.webapi.bukkit.InspectWebAPI;
import main.java.com.djrapitops.plan.utilities.Check;
import java.util.Optional;
import java.util.UUID;
/**
* Command used for testing functions that are too difficult to unit test.
*
* @author Rsl1122
*/
public class DevCommand extends SubCommand {
private final Plan plugin;
public DevCommand(Plan plugin) {
super("dev", CommandType.CONSOLE_WITH_ARGUMENTS, "plan.*", "Test Plugin functions not testable with unit tests.", "<feature to test>");
this.plugin = plugin;
}
@Override
public boolean onCommand(ISender sender, String cmd, String[] args) {
if (!Check.isTrue(args.length >= 1, Locale.get(Msg.CMD_FAIL_REQ_ONE_ARG).toString(), sender)) {
return true;
}
String feature = args[0];
switch (feature) {
case "webapi":
if (!Check.isTrue(args.length >= 2, Locale.get(Msg.CMD_FAIL_REQ_ONE_ARG).toString(), sender)) {
break;
}
if (!webapi(args[1] + "webapi", args.length >= 3)) {
sender.sendMessage("[Plan] No such API / Exception occurred.");
}
break;
case "web":
Optional<String> bungeeConnectionAddress = plugin.getServerInfoManager().getBungeeConnectionAddress();
String accessAddress = plugin.getWebServer().getAccessAddress();
sender.sendMessage((plugin.getInfoManager().isUsingAnotherWebServer() && bungeeConnectionAddress.isPresent())
? "Bungee: " + bungeeConnectionAddress.get() : "Local: " + accessAddress);
break;
default:
break;
}
return true;
}
private boolean webapi(String method, boolean connectToBungee) {
WebAPI api = plugin.getWebServer().getWebAPI().getAPI(method);
if (api == null) {
return false;
}
try {
String address = plugin.getWebServer().getAccessAddress();
if (connectToBungee) {
Optional<String> bungeeConnectionAddress = plugin.getServerInfoManager().getBungeeConnectionAddress();
if (bungeeConnectionAddress.isPresent()) {
address = bungeeConnectionAddress.get();
}
}
if (api instanceof InspectWebAPI) {
((InspectWebAPI) api).sendRequest(address, UUID.randomUUID());
} else {
api.sendRequest(address);
}
return true;
} catch (WebAPIException e) {
e.printStackTrace();
}
return false;
}
}

View File

@ -1,6 +1,5 @@
package main.java.com.djrapitops.plan.command.commands;
import com.djrapitops.plugin.api.TimeAmount;
import com.djrapitops.plugin.command.CommandType;
import com.djrapitops.plugin.command.CommandUtils;
import com.djrapitops.plugin.command.ISender;
@ -10,14 +9,11 @@ import com.djrapitops.plugin.utilities.Verify;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Permissions;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.Settings;
import main.java.com.djrapitops.plan.command.ConditionUtils;
import main.java.com.djrapitops.plan.data.cache.InspectCacheHandler;
import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg;
import main.java.com.djrapitops.plan.ui.text.TextUI;
import main.java.com.djrapitops.plan.systems.processing.info.InspectCacheRequestProcessor;
import main.java.com.djrapitops.plan.utilities.Check;
import main.java.com.djrapitops.plan.utilities.HtmlUtils;
import main.java.com.djrapitops.plan.utilities.MiscUtils;
import main.java.com.djrapitops.plan.utilities.uuid.UUIDUtility;
import org.bukkit.ChatColor;
@ -26,7 +22,7 @@ import java.sql.SQLException;
import java.util.UUID;
/**
* This command is used to cache UserData to InspectCache and display the link.
* This command is used to cache UserInfo to InspectCache and display the link.
*
* @author Rsl1122
* @since 1.0.0
@ -34,7 +30,6 @@ import java.util.UUID;
public class InspectCommand extends SubCommand {
private final Plan plugin;
private final InspectCacheHandler inspectCache;
/**
* Class Constructor.
@ -49,7 +44,6 @@ public class InspectCommand extends SubCommand {
"<player>");
this.plugin = plugin;
inspectCache = plugin.getInspectCache();
}
@ -60,10 +54,6 @@ public class InspectCommand extends SubCommand {
@Override
public boolean onCommand(ISender sender, String commandLabel, String[] args) {
if (!Check.isTrue(ConditionUtils.pluginHasViewCapability(), Locale.get(Msg.CMD_FAIL_NO_DATA_VIEW).toString(), sender)) {
return true;
}
String playerName = MiscUtils.getPlayerName(args, sender);
runInspectTask(playerName, sender);
@ -85,15 +75,14 @@ public class InspectCommand extends SubCommand {
if (!Check.isTrue(plugin.getDB().wasSeenBefore(uuid), Locale.get(Msg.CMD_FAIL_USERNAME_NOT_KNOWN).toString(), sender)) {
return;
}
sender.sendMessage(Locale.get(Msg.CMD_INFO_FETCH_DATA).toString());
if (CommandUtils.isPlayer(sender) && plugin.getUiServer().isAuthRequired()) {
if (CommandUtils.isPlayer(sender) && plugin.getWebServer().isAuthRequired()) {
boolean senderHasWebUser = plugin.getDB().getSecurityTable().userExists(sender.getName());
if (!senderHasWebUser) {
sender.sendMessage(ChatColor.YELLOW + "[Plan] You might not have a web user, use /plan register <password>");
}
}
inspectCache.cache(uuid);
runMessageSenderTask(uuid, sender, playerName);
plugin.addToProcessQueue(new InspectCacheRequestProcessor(uuid, sender, playerName));
} catch (SQLException ex) {
Log.toLog(this.getClass().getName(), ex);
} finally {
@ -102,50 +91,4 @@ public class InspectCommand extends SubCommand {
}
}).runTaskAsynchronously();
}
private void runMessageSenderTask(UUID uuid, ISender sender, String playerName) {
plugin.getRunnableFactory().createNew(new AbsRunnable("InspectMessageSenderTask") {
private int timesrun = 0;
@Override
public void run() {
timesrun++;
if (inspectCache.isCached(uuid)) {
sendInspectMsg(sender, playerName, uuid);
this.cancel();
return;
}
if (timesrun > 10) {
Log.debug("Command Timeout Message, Inspect.");
sender.sendMessage(Locale.get(Msg.CMD_FAIL_TIMEOUT).parse("Inspect"));
this.cancel();
}
}
}).runTaskTimer(TimeAmount.SECOND.ticks(), 5 * TimeAmount.SECOND.ticks());
}
private void sendInspectMsg(ISender sender, String playerName, UUID uuid) {
boolean usingTextUI = Settings.USE_ALTERNATIVE_UI.isTrue();
sender.sendMessage(Locale.get(Msg.CMD_HEADER_INSPECT) + playerName);
if (usingTextUI) {
sender.sendMessage(TextUI.getInspectMessages(uuid));
} else {
// Link
String url = HtmlUtils.getInspectUrlWithProtocol(playerName);
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());
}
}

View File

@ -5,11 +5,9 @@ import com.djrapitops.plugin.command.CommandUtils;
import com.djrapitops.plugin.command.ISender;
import com.djrapitops.plugin.command.SubCommand;
import main.java.com.djrapitops.plan.Permissions;
import main.java.com.djrapitops.plan.command.ConditionUtils;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg;
import main.java.com.djrapitops.plan.utilities.Check;
import main.java.com.djrapitops.plan.utilities.HtmlUtils;
/**
* Command used to display link to the player list webpage.
@ -36,9 +34,6 @@ public class ListCommand extends SubCommand {
@Override
public boolean onCommand(ISender sender, String commandLabel, String[] args) {
if (!Check.isTrue(ConditionUtils.pluginHasViewCapability(), Locale.get(Msg.CMD_FAIL_NO_DATA_VIEW) + "", sender)) {
return true;
}
sendListMsg(sender);
return true;
@ -48,7 +43,7 @@ public class ListCommand extends SubCommand {
sender.sendMessage(Locale.get(Msg.CMD_CONSTANT_FOOTER).parse());
// Link
String url = HtmlUtils.getServerAnalysisUrlWithProtocol().replace("server", "players");
String url = Plan.getInstance().getInfoManager().getLinkTo("/players");
String message = Locale.get(Msg.CMD_INFO_LINK).toString();
boolean console = !CommandUtils.isPlayer(sender);
if (console) {

View File

@ -0,0 +1,61 @@
package main.java.com.djrapitops.plan.command.commands;
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 main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Permissions;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.api.IPlan;
import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg;
import java.sql.SQLException;
import java.util.Map;
/**
* This subcommand is used to reload the plugin.
*
* @author Rsl1122
* @since 2.0.0
*/
public class ListServersCommand extends SubCommand {
private final IPlan plugin;
/**
* Subcommand constructor.
*
* @param plugin Current instance of Plan
*/
public ListServersCommand(Plan plugin) {
super("servers, serverlist, listservers, sl",
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) {
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");
Map<Integer, String> serverNames = plugin.getDB().getServerTable().getServerNames();
for (Map.Entry<Integer, String> entry : serverNames.entrySet()) {
sender.sendMessage(" " + tCol + entry.getKey() + sCol + " : " + entry.getValue());
}
sender.sendMessage(Locale.get(Msg.CMD_CONSTANT_FOOTER).toString());
} catch (SQLException e) {
sender.sendMessage("§cSQLException occurred.");
Log.toLog(this.getClass().getName(), e);
}
return true;
}
}

View File

@ -35,14 +35,14 @@ public class ManageCommand extends TreeCommand<Plan> {
@Override
public void addCommands() {
// commands.add(new ManageMoveCommand(plugin));
commands.add(new ManageMoveCommand(plugin));
commands.add(new ManageHotswapCommand(plugin));
// commands.add(new ManageBackupCommand(plugin));
// commands.add(new ManageRestoreCommand(plugin));
commands.add(new ManageBackupCommand(plugin));
commands.add(new ManageRestoreCommand(plugin));
commands.add(new ManageImportCommand(plugin));
commands.add(new ManageRemoveCommand(plugin));
// commands.add(new ManageCleanCommand(plugin));
commands.add(new ManageClearCommand(plugin));
commands.add(new ManageDumpCommand(plugin));
commands.add(new ManageSetupCommand(plugin));
}
}

View File

@ -0,0 +1,57 @@
package main.java.com.djrapitops.plan.command.commands;
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 main.java.com.djrapitops.plan.Permissions;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg;
/**
* Command used to display link to the player list webpage.
* <p>
* Subcommand is not registered if Webserver is not enabled.
*
* @author Rsl1122
* @since 3.5.2
*/
public class NetworkCommand extends SubCommand {
private final Plan plugin;
/**
* Class Constructor.
*/
public NetworkCommand(Plan plugin) {
super("network, n, netw", CommandType.CONSOLE, Permissions.ANALYZE.getPermission(), Locale.get(Msg.CMD_USG_LIST).toString(), "");
this.plugin = plugin;
}
@Override
public boolean onCommand(ISender sender, String commandLabel, String[] args) {
if (plugin.getInfoManager().isUsingAnotherWebServer()) {
sender.sendMessage("§cNot using Bungee WebServer!");
return true;
}
sendNetworkMsg(sender);
return true;
}
private void sendNetworkMsg(ISender sender) {
sender.sendMessage(Locale.get(Msg.CMD_CONSTANT_FOOTER).parse());
// Link
String url = Plan.getInstance().getInfoManager().getLinkTo("/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());
}
}

View File

@ -1,98 +0,0 @@
package main.java.com.djrapitops.plan.command.commands;
import com.djrapitops.plugin.api.TimeAmount;
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 main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Permissions;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.command.ConditionUtils;
import main.java.com.djrapitops.plan.data.cache.AnalysisCacheHandler;
import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg;
import main.java.com.djrapitops.plan.ui.text.TextUI;
import main.java.com.djrapitops.plan.utilities.Check;
import main.java.com.djrapitops.plan.utilities.MiscUtils;
/**
* This subcommand is used to run the analysis and to view some of the data in
* game.
*
* @author Rsl1122
* @since 3.0.0
*/
public class QuickAnalyzeCommand extends SubCommand {
private final Plan plugin;
private final AnalysisCacheHandler analysisCache;
/**
* Subcommand Constructor.
*
* @param plugin Current instance of Plan
*/
public QuickAnalyzeCommand(Plan plugin) {
super("qanalyze, qanalyse, qanalysis, qa",
CommandType.CONSOLE,
Permissions.QUICK_ANALYZE.getPermission(),
Locale.get(Msg.CMD_USG_QANALYZE).parse());
this.plugin = plugin;
analysisCache = plugin.getAnalysisCache();
}
@Override
public String[] addHelp() {
return Locale.get(Msg.CMD_HELP_PLAN).toArray();
}
@Override
public boolean onCommand(ISender sender, String commandLabel, String[] args) {
if (!Check.isTrue(ConditionUtils.pluginHasViewCapability(), Locale.get(Msg.CMD_FAIL_NO_DATA_VIEW).toString(), sender)) {
return true;
}
if (!Check.isTrue(analysisCache.isAnalysisEnabled(), Locale.get(Msg.CMD_INFO_ANALYSIS_TEMP_DISABLE).toString(), sender)
&& !analysisCache.isCached()) {
return true;
}
updateCache();
runMessageSenderTask(sender);
return true;
}
private void updateCache() {
if (!analysisCache.isCached() || MiscUtils.getTime() - analysisCache.getData().getRefreshDate() > TimeAmount.MINUTE.ms()) {
int bootAnID = plugin.getBootAnalysisTaskID();
if (bootAnID != -1) {
plugin.getServer().getScheduler().cancelTask(bootAnID);
}
analysisCache.updateCache();
}
}
private void runMessageSenderTask(ISender sender) {
plugin.getRunnableFactory().createNew(new AbsRunnable("QanalysisMessageSenderTask") {
private int timesRun = 0;
@Override
public void run() {
timesRun++;
if (analysisCache.isCached() && (!analysisCache.isAnalysisBeingRun() || !analysisCache.isAnalysisEnabled())) {
sender.sendMessage(Locale.get(Msg.CMD_HEADER_ANALYZE) + "");
sender.sendMessage(TextUI.getAnalysisMessages());
sender.sendMessage(Locale.get(Msg.CMD_CONSTANT_FOOTER) + "");
this.cancel();
}
if (timesRun > 10) {
Log.debug("Command Timeout Message, QuickAnalyze.");
sender.sendMessage(Locale.get(Msg.CMD_FAIL_TIMEOUT).parse("Analysis"));
this.cancel();
}
}
}).runTaskTimer(TimeAmount.SECOND.ticks(), 5 * TimeAmount.SECOND.ticks());
}
}

View File

@ -1,105 +0,0 @@
package main.java.com.djrapitops.plan.command.commands;
import com.djrapitops.plugin.api.TimeAmount;
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.utilities.Verify;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Permissions;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.command.ConditionUtils;
import main.java.com.djrapitops.plan.data.cache.InspectCacheHandler;
import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg;
import main.java.com.djrapitops.plan.ui.text.TextUI;
import main.java.com.djrapitops.plan.utilities.Check;
import main.java.com.djrapitops.plan.utilities.MiscUtils;
import main.java.com.djrapitops.plan.utilities.uuid.UUIDUtility;
import java.util.UUID;
/**
* This command is used to cache UserData to InspectCache and to view some of
* the data in game.
*
* @author Rsl1122
* @since 3.0.0
*/
public class QuickInspectCommand extends SubCommand {
private final Plan plugin;
private final InspectCacheHandler inspectCache;
/**
* Class Constructor.
*
* @param plugin Current instance of Plan
*/
public QuickInspectCommand(Plan plugin) {
super("qinspect, qi",
CommandType.CONSOLE_WITH_ARGUMENTS,
Permissions.QUICK_INSPECT.getPermission(),
Locale.get(Msg.CMD_USG_QINSPECT).toString(), "<player>");
this.plugin = plugin;
inspectCache = plugin.getInspectCache();
}
@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);
plugin.getRunnableFactory().createNew(new AbsRunnable("QinspectTask") {
@Override
public void run() {
try {
UUID uuid = UUIDUtility.getUUIDOf(playerName);
if (!Check.isTrue(Verify.notNull(uuid), Locale.get(Msg.CMD_FAIL_USERNAME_NOT_VALID).toString(), sender)) {
return;
}
if (!Check.isTrue(ConditionUtils.playerHasPlayed(uuid), Locale.get(Msg.CMD_FAIL_USERNAME_NOT_SEEN).toString(), sender)) {
return;
}
if (!Check.isTrue(plugin.getDB().wasSeenBefore(uuid), Locale.get(Msg.CMD_FAIL_USERNAME_NOT_KNOWN).toString(), sender)) {
return;
}
sender.sendMessage(Locale.get(Msg.CMD_INFO_FETCH_DATA).toString());
inspectCache.cache(uuid);
runMessageSenderTask(uuid, sender, playerName);
} finally {
this.cancel();
}
}
}).runTaskAsynchronously();
return true;
}
private void runMessageSenderTask(UUID uuid, ISender sender, String playerName) {
plugin.getRunnableFactory().createNew(new AbsRunnable("QinspectMessageSenderTask") {
private int timesrun = 0;
@Override
public void run() {
timesrun++;
if (inspectCache.isCached(uuid)) {
sender.sendMessage(Locale.get(Msg.CMD_HEADER_INSPECT) + playerName);
sender.sendMessage(TextUI.getInspectMessages(uuid));
sender.sendMessage(Locale.get(Msg.CMD_CONSTANT_FOOTER) + "");
this.cancel();
}
if (timesrun > 10) {
Log.debug("Command Timeout Message, QuickInspect.");
sender.sendMessage(Locale.get(Msg.CMD_FAIL_TIMEOUT).parse("Qinspect"));
this.cancel();
}
}
}).runTaskTimer(TimeAmount.SECOND.ticks(), 5 * TimeAmount.SECOND.ticks());
}
}

View File

@ -14,7 +14,8 @@ import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg;
import main.java.com.djrapitops.plan.utilities.Check;
import main.java.com.djrapitops.plan.utilities.PassEncryptUtil;
import org.bukkit.ChatColor;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.Logger;
/**
* Command for registering web users.
@ -39,7 +40,7 @@ public class RegisterCommand extends SubCommand {
Locale.get(Msg.CMD_USG_WEB_REGISTER).toString(),
"<password> [name] [access lvl]");
this.plugin = plugin;
setupFilter();
}
@Override
@ -50,8 +51,8 @@ public class RegisterCommand extends SubCommand {
@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 = ChatColor.RED + "Password hash error.";
String permLvlErrorMsg = ChatColor.RED + "Incorrect perm level, not a number: ";
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.");
@ -114,9 +115,9 @@ public class RegisterCommand extends SubCommand {
plugin.getRunnableFactory().createNew(new AbsRunnable("Register WebUser Task") {
@Override
public void run() {
final String existsMsg = ChatColor.RED + "User Already Exists!";
final String existsMsg = "§cUser Already Exists!";
final String userName = webUser.getName();
final String successMsg = ChatColor.GREEN + "Added a new user (" + userName + ") successfully!";
final String successMsg = "§aAdded a new user (" + userName + ") successfully!";
try {
SecurityTable securityTable = plugin.getDB().getSecurityTable();
boolean userExists = securityTable.userExists(userName);
@ -134,4 +135,12 @@ public class RegisterCommand extends SubCommand {
}
}).runTaskAsynchronously();
}
/**
* Setups the command console output filter
*/
private void setupFilter() {
Logger logger = (Logger) LogManager.getRootLogger();
logger.addFilter(new RegisterCommandFilter());
}
}

View File

@ -5,6 +5,8 @@ import com.djrapitops.plugin.command.ISender;
import com.djrapitops.plugin.command.SubCommand;
import main.java.com.djrapitops.plan.Permissions;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.PlanBungee;
import main.java.com.djrapitops.plan.api.IPlan;
import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg;
@ -16,7 +18,7 @@ import main.java.com.djrapitops.plan.locale.Msg;
*/
public class ReloadCommand extends SubCommand {
private final Plan plugin;
private final IPlan plugin;
/**
* Subcommand constructor.
@ -32,11 +34,18 @@ public class ReloadCommand extends SubCommand {
this.plugin = plugin;
}
public ReloadCommand(PlanBungee plugin) {
super("planbungee",
CommandType.CONSOLE,
Permissions.MANAGE.getPermission(),
Locale.get(Msg.CMD_USG_RELOAD).toString());
this.plugin = plugin;
}
@Override
public boolean onCommand(ISender sender, String commandLabel, String[] args) {
plugin.onDisable();
plugin.reloadConfig();
plugin.onEnable();
plugin.restart();
sender.sendMessage(Locale.get(Msg.CMD_INFO_RELOAD_COMPLETE).toString());
return true;
}

View File

@ -5,6 +5,7 @@ import com.djrapitops.plugin.command.ISender;
import com.djrapitops.plugin.command.SubCommand;
import com.djrapitops.plugin.task.AbsRunnable;
import com.djrapitops.plugin.utilities.FormattingUtils;
import com.djrapitops.plugin.utilities.Verify;
import main.java.com.djrapitops.plan.Permissions;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.locale.Locale;
@ -62,9 +63,12 @@ public class SearchCommand extends SubCommand {
public void run() {
try {
List<String> names = MiscUtils.getMatchingPlayerNames(args[0]);
sender.sendMessage(Locale.get(Msg.CMD_HEADER_SEARCH) + args[0] + " (" + names.size() + ")");
boolean empty = Verify.isEmpty(names);
sender.sendMessage(Locale.get(Msg.CMD_HEADER_SEARCH) + args[0] + " (" + (empty ? 0 : names.size()) + ")");
// Results
if (names.isEmpty()) {
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() + FormattingUtils.collectionToStringNoBrackets(names));

View File

@ -8,6 +8,7 @@ import com.djrapitops.plugin.utilities.Verify;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Permissions;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.api.exceptions.DatabaseInitException;
import main.java.com.djrapitops.plan.database.Database;
import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg;
@ -42,12 +43,13 @@ public class ManageBackupCommand extends SubCommand {
@Override
public boolean onCommand(ISender sender, String commandLabel, String[] args) {
try {
if (!Check.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 (Check.isTrue(isCorrectDB, Locale.get(Msg.MANAGE_FAIL_INCORRECT_DB) + dbName, sender)) {
if (!Check.isTrue(isCorrectDB, Locale.get(Msg.MANAGE_FAIL_INCORRECT_DB) + dbName, sender)) {
return true;
}
@ -58,10 +60,12 @@ public class ManageBackupCommand extends SubCommand {
Log.error(dbName + " was null!");
return true;
}
Log.debug("Backup", "Start");
runBackupTask(sender, args, database);
} catch (NullPointerException e) {
} catch (DatabaseInitException | NullPointerException e) {
sender.sendMessage(Locale.get(Msg.MANAGE_FAIL_FAULTY_DB).toString());
} finally {
Log.logDebug("Backup");
}
return true;
}
@ -72,11 +76,8 @@ public class ManageBackupCommand extends SubCommand {
public void run() {
try {
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_START).parse());
if (ManageUtils.backup(args[0], database)) {
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_COPY_SUCCESS).toString());
} else {
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_FAIL).toString());
}
ManageUtils.backup(args[0], database);
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_COPY_SUCCESS).toString());
} catch (Exception e) {
Log.toLog(this.getClass().getName() + " " + getTaskName(), e);
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_FAIL).toString());

View File

@ -1,78 +0,0 @@
package main.java.com.djrapitops.plan.command.commands.manage;
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.utilities.Verify;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Permissions;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.database.Database;
import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg;
import main.java.com.djrapitops.plan.utilities.Check;
import main.java.com.djrapitops.plan.utilities.ManageUtils;
/**
* This manage subcommand is used to clear a database of all data.
*
* @author Rsl1122
* @since 2.3.0
*/
public class ManageCleanCommand extends SubCommand {
private final Plan plugin;
/**
* Class Constructor.
*
* @param plugin Current instance of Plan
*/
public ManageCleanCommand(Plan plugin) {
super("clean",
CommandType.CONSOLE_WITH_ARGUMENTS,
Permissions.MANAGE.getPermission(),
Locale.get(Msg.CMD_USG_MANAGE_CLEAN).toString(),
"<DB>");
this.plugin = plugin;
}
@Override
public boolean onCommand(ISender sender, String commandLabel, String[] args) {
if (!Check.isTrue(args.length != 0, 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 (!Check.isTrue(isCorrectDB, Locale.get(Msg.MANAGE_FAIL_INCORRECT_DB) + dbName, sender)) {
return true;
}
final Database database = ManageUtils.getDB(plugin, dbName);
// If DB is null return
if (!Check.isTrue(Verify.notNull(database), Locale.get(Msg.MANAGE_FAIL_FAULTY_DB).toString(), sender)) {
Log.error(dbName + " was null!");
return true;
}
runCleanTask(sender, database);
return true;
}
private void runCleanTask(ISender sender, final Database database) {
plugin.getRunnableFactory().createNew(new AbsRunnable("DBCleanTask") {
@Override
public void run() {
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_START).parse());
database.clean();
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_SUCCESS).toString());
this.cancel();
}
}).runTaskAsynchronously();
}
}

View File

@ -8,11 +8,17 @@ import com.djrapitops.plugin.utilities.Verify;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Permissions;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.api.exceptions.DatabaseInitException;
import main.java.com.djrapitops.plan.data.Session;
import main.java.com.djrapitops.plan.database.Database;
import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg;
import main.java.com.djrapitops.plan.systems.cache.DataCache;
import main.java.com.djrapitops.plan.utilities.Check;
import main.java.com.djrapitops.plan.utilities.ManageUtils;
import main.java.com.djrapitops.plan.utilities.MiscUtils;
import java.sql.SQLException;
/**
* This manage subcommand is used to clear a database of all data.
@ -62,31 +68,35 @@ public class ManageClearCommand extends SubCommand {
return true;
}
final Database database = ManageUtils.getDB(plugin, dbName);
// If DB is null return
if (!Check.isTrue(Verify.notNull(database), Locale.get(Msg.MANAGE_FAIL_FAULTY_DB).toString(), sender)) {
Log.error(dbName + " was null!");
return true;
try {
Database database = ManageUtils.getDB(plugin, dbName);
runClearTask(sender, database);
} catch (DatabaseInitException e) {
sender.sendMessage(Locale.get(Msg.MANAGE_FAIL_FAULTY_DB).toString());
}
runClearTask(sender, database);
return true;
}
private void runClearTask(ISender sender, final Database database) {
private void runClearTask(ISender sender, Database database) {
plugin.getRunnableFactory().createNew(new AbsRunnable("DBClearTask") {
@Override
public void run() {
try {
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_START).parse());
if (database.removeAllData()) {
plugin.getHandler().getDataCache().clear();
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_CLEAR_SUCCESS).toString());
} else {
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_FAIL).toString());
}
database.removeAllData();
DataCache dataCache = plugin.getDataCache();
long now = MiscUtils.getTime();
dataCache.getActiveSessions().clear();
plugin.getServer().getOnlinePlayers().forEach(
player -> dataCache.cacheSession(player.getUniqueId(),
new Session(now, player.getWorld().getName(), player.getGameMode().name()))
);
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_CLEAR_SUCCESS).toString());
} catch (SQLException e) {
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_FAIL).toString());
Log.toLog(this.getClass().getSimpleName() + "/" + this.getTaskName(), e);
} finally {
this.cancel();
}

View File

@ -61,15 +61,18 @@ public class ManageHotswapCommand extends SubCommand {
return true;
}
final Database database = ManageUtils.getDB(plugin, dbName);
// If DB is null return
if (!Check.isTrue(Verify.notNull(database), Locale.get(Msg.MANAGE_FAIL_FAULTY_DB).toString(), sender)) {
Log.error(dbName + " was null!");
return true;
}
try {
final Database database = ManageUtils.getDB(plugin, dbName);
// If DB is null return
if (!Check.isTrue(Verify.notNull(database), Locale.get(Msg.MANAGE_FAIL_FAULTY_DB).toString(), sender)) {
Log.error(dbName + " was null!");
return true;
}
assert database != null;
database.getVersion(); //Test db connection
} catch (Exception e) {
Log.toLog(this.getClass().getName(), e);

View File

@ -4,21 +4,15 @@ 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.utilities.FormattingUtils;
import com.djrapitops.plugin.utilities.player.Fetch;
import com.djrapitops.plugin.utilities.player.IOfflinePlayer;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Permissions;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.handling.importing.ImportUtils;
import main.java.com.djrapitops.plan.data.handling.importing.Importer;
import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg;
import main.java.com.djrapitops.plan.systems.info.ImporterManager;
import main.java.com.djrapitops.plan.utilities.Check;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
import java.sql.SQLException;
/**
* This manage subcommand is used to import data from 3rd party plugins.
@ -59,51 +53,22 @@ public class ManageImportCommand extends SubCommand {
return true;
}
String importFromPlugin = args[0].toLowerCase();
Map<String, Importer> importPlugins = ImportUtils.getImporters();
if (importFromPlugin.equals("list")) {
list(importPlugins, sender);
return true;
}
if (!Check.isTrue(importPlugins.keySet().contains(importFromPlugin), Locale.get(Msg.MANAGE_FAIL_INCORRECT_PLUGIN) + importFromPlugin, sender)) {
return true;
}
if (!Check.isTrue(ImportUtils.isPluginEnabled(importFromPlugin), Locale.get(Msg.MANAGE_FAIL_PLUGIN_NOT_ENABLED) + importFromPlugin, sender)) {
return true;
}
String[] importArguments = FormattingUtils.removeFirstArgument(args);
final Importer importer = importPlugins.get(importFromPlugin);
runImportTask(sender, importer, importArguments);
runImport("offlineimporter");
return true;
}
private void runImportTask(ISender sender, final Importer importer, String... importArguments) {
plugin.getRunnableFactory().createNew(new AbsRunnable("ImportTask") {
private void runImport(String importer) {
plugin.getRunnableFactory().createNew("Import", new AbsRunnable() {
@Override
public void run() {
try {
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_IMPORT).toString());
List<UUID> uuids = Fetch.getIOfflinePlayers().stream().map(IOfflinePlayer::getUniqueId).collect(Collectors.toList());
if (importer.importData(uuids, importArguments)) {
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_SUCCESS).toString());
} else {
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_FAIL).toString());
}
ImporterManager.getImporter(importer).processImport();
} catch (SQLException e) {
Log.toLog(this.getClass().getName(), e);
} finally {
this.cancel();
}
}
}).runTaskAsynchronously();
}
private void list(Map<String, Importer> importers, ISender sender) {
sender.sendMessage(Locale.get(Msg.CMD_CONSTANT_FOOTER).parse());
importers.forEach((string, importer) -> sender.sendMessage(Locale.get(Msg.CMD_CONSTANT_LIST_BALL) + " " + string + ": " + importer.getInfo()));
sender.sendMessage(Locale.get(Msg.CMD_CONSTANT_FOOTER).parse());
}
}

View File

@ -14,9 +14,6 @@ import main.java.com.djrapitops.plan.locale.Msg;
import main.java.com.djrapitops.plan.utilities.Check;
import main.java.com.djrapitops.plan.utilities.ManageUtils;
import java.util.Collection;
import java.util.UUID;
/**
* This manage subcommand is used to move all data from one database to another.
* <p>
@ -72,21 +69,14 @@ public class ManageMoveCommand extends SubCommand {
return true;
}
final Database fromDatabase = ManageUtils.getDB(plugin, fromDB);
try {
final Database fromDatabase = ManageUtils.getDB(plugin, fromDB);
final Database toDatabase = ManageUtils.getDB(plugin, toDB);
if (!Check.isTrue(Verify.notNull(fromDatabase), Locale.get(Msg.MANAGE_FAIL_FAULTY_DB).toString(), sender)) {
Log.error(fromDB + " was null!");
return true;
runMoveTask(fromDatabase, toDatabase, sender);
} catch (Exception e) {
sender.sendMessage(Locale.get(Msg.MANAGE_FAIL_FAULTY_DB).toString());
}
final Database toDatabase = ManageUtils.getDB(plugin, toDB);
if (!Check.isTrue(Verify.notNull(toDatabase), Locale.get(Msg.MANAGE_FAIL_FAULTY_DB).toString(), sender)) {
Log.error(toDB + " was null!");
return true;
}
runMoveTask(fromDatabase, toDatabase, sender);
return true;
}
@ -95,21 +85,12 @@ public class ManageMoveCommand extends SubCommand {
@Override
public void run() {
try {
final Collection<UUID> uuids = ManageUtils.getUUIDS(fromDatabase);
if (Check.isTrue(Verify.isEmpty(uuids), Locale.get(Msg.MANAGE_FAIL_NO_PLAYERS) + " (" + fromDatabase.getName() + ")", sender)) {
return;
}
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_START).parse());
if (ManageUtils.clearAndCopy(toDatabase, fromDatabase)) {
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_MOVE_SUCCESS).toString());
boolean movedToCurrentDatabase = Verify.equalsIgnoreCase(toDatabase.getConfigName(), plugin.getDB().getConfigName());
Check.isTrue(!movedToCurrentDatabase, Locale.get(Msg.MANAGE_INFO_CONFIG_REMINDER).toString(), sender);
} else {
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_FAIL).toString());
}
ManageUtils.clearAndCopy(toDatabase, fromDatabase);
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_MOVE_SUCCESS).toString());
boolean movedToCurrentDatabase = Verify.equalsIgnoreCase(toDatabase.getConfigName(), plugin.getDB().getConfigName());
Check.isTrue(!movedToCurrentDatabase, Locale.get(Msg.MANAGE_INFO_CONFIG_REMINDER).toString(), sender);
} catch (Exception e) {
Log.toLog(this.getClass().getName() + " " + getTaskName(), e);
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_FAIL).toString());

View File

@ -8,15 +8,20 @@ import com.djrapitops.plugin.utilities.Verify;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Permissions;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.Session;
import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg;
import main.java.com.djrapitops.plan.systems.cache.DataCache;
import main.java.com.djrapitops.plan.utilities.Check;
import main.java.com.djrapitops.plan.utilities.MiscUtils;
import main.java.com.djrapitops.plan.utilities.uuid.UUIDUtility;
import org.bukkit.entity.Player;
import java.sql.SQLException;
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.
@ -84,12 +89,14 @@ public class ManageRemoveCommand extends SubCommand {
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_START).parse());
try {
plugin.getHandler().getDataCache().remove(uuid);
if (plugin.getDB().removeAccount(uuid.toString())) {
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_REMOVE_SUCCESS).parse(playerName, plugin.getDB().getConfigName()));
} else {
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_FAIL).toString());
}
plugin.getDB().removeAccount(uuid);
DataCache dataCache = plugin.getDataCache();
Player player = getPlayer(uuid);
dataCache.getActiveSessions().remove(uuid);
dataCache.cacheSession(uuid, new Session(MiscUtils.getTime(), player.getWorld().getName(), player.getGameMode().name()));
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_REMOVE_SUCCESS).parse(playerName, plugin.getDB().getConfigName()));
} catch (SQLException e) {
Log.toLog(this.getClass().getName(), e);
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_FAIL).toString());

View File

@ -16,8 +16,6 @@ import main.java.com.djrapitops.plan.utilities.Check;
import main.java.com.djrapitops.plan.utilities.ManageUtils;
import java.io.File;
import java.util.Collection;
import java.util.UUID;
/**
* This manage subcommand is used to restore a backup.db file in the
@ -61,14 +59,13 @@ public class ManageRestoreCommand extends SubCommand {
return true;
}
final Database database = ManageUtils.getDB(plugin, db);
try {
final Database database = ManageUtils.getDB(plugin, db);
if (!Check.isTrue(Verify.notNull(database), Locale.get(Msg.MANAGE_FAIL_FAULTY_DB).toString(), sender)) {
Log.error(db + " was null!");
return true;
runRestoreTask(args, sender, database);
} catch (Exception e) {
sender.sendMessage(Locale.get(Msg.MANAGE_FAIL_FAULTY_DB).toString());
}
runRestoreTask(args, sender, database);
return true;
}
@ -90,27 +87,16 @@ public class ManageRestoreCommand extends SubCommand {
}
SQLiteDB backupDB = new SQLiteDB(plugin, backupDBName);
if (!backupDB.init()) {
sender.sendMessage(Locale.get(Msg.MANAGE_FAIL_FAULTY_DB).toString());
return;
}
backupDB.init();
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_START).parse());
final Collection<UUID> uuids = ManageUtils.getUUIDS(backupDB);
if (!Check.isTrue(!Verify.isEmpty(uuids), Locale.get(Msg.MANAGE_FAIL_NO_PLAYERS) + " (" + backupDBName + ")", sender)) {
return;
ManageUtils.clearAndCopy(database, backupDB);
if (database.getConfigName().equals(plugin.getDB().getConfigName())) {
// plugin.getDataCache().getCommandUseFromDb();
}
if (ManageUtils.clearAndCopy(database, backupDB)) {
if (database.getConfigName().equals(plugin.getDB().getConfigName())) {
plugin.getHandler().getCommandUseFromDb();
}
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_COPY_SUCCESS).toString());
} else {
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_FAIL).toString());
}
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_COPY_SUCCESS).toString());
} catch (Exception e) {
Log.toLog(this.getClass().getName() + " " + getTaskName(), e);
sender.sendMessage(Locale.get(Msg.MANAGE_INFO_FAIL).toString());

View File

@ -0,0 +1,64 @@
package main.java.com.djrapitops.plan.command.commands.manage;
import com.djrapitops.plugin.command.CommandType;
import com.djrapitops.plugin.command.ISender;
import com.djrapitops.plugin.command.SubCommand;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Permissions;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.api.exceptions.WebAPIException;
import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg;
import main.java.com.djrapitops.plan.systems.webserver.webapi.bungee.RequestSetupWebAPI;
import main.java.com.djrapitops.plan.systems.webserver.webapi.universal.PingWebAPI;
import main.java.com.djrapitops.plan.utilities.Check;
/**
* 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 ManageSetupCommand extends SubCommand {
private final Plan plugin;
/**
* Class Constructor.
*
* @param plugin Current instance of Plan
*/
public ManageSetupCommand(Plan plugin) {
super("setup",
CommandType.CONSOLE_WITH_ARGUMENTS,
Permissions.MANAGE.getPermission(),
"Set-Up Bungee WebServer connection",
"<Bungee WebServer address>");
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 (!Check.isTrue(args.length >= 1, Locale.get(Msg.CMD_FAIL_REQ_ONE_ARG).toString(), sender)) {
return true;
}
String address = args[0].toLowerCase();
try {
plugin.getWebServer().getWebAPI().getAPI(PingWebAPI.class).sendRequest(address);
plugin.getWebServer().getWebAPI().getAPI(RequestSetupWebAPI.class).sendRequest(address);
sender.sendMessage("§aConnection successful, Plan may restart in a few seconds.");
} catch (WebAPIException e) {
Log.toLog(this.getClass().getName(), e);
sender.sendMessage("§cConnection to Bungee WebServer failed: More info on console");
}
return true;
}
}

View File

@ -0,0 +1,78 @@
/*
* Licence is provided in the jar as license.yml also here:
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
*/
package main.java.com.djrapitops.plan.data;
import main.java.com.djrapitops.plan.database.tables.Actions;
import main.java.com.djrapitops.plan.utilities.FormatUtils;
import main.java.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);
}
}

View File

@ -4,8 +4,8 @@ import com.djrapitops.plugin.utilities.Verify;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.data.analysis.*;
import main.java.com.djrapitops.plan.utilities.Benchmark;
import main.java.com.djrapitops.plan.utilities.HtmlUtils;
import main.java.com.djrapitops.plan.utilities.MiscUtils;
import main.java.com.djrapitops.plan.utilities.html.HtmlUtils;
import java.io.Serializable;
import java.util.Arrays;
@ -21,7 +21,7 @@ import java.util.Map;
* analysed using the analysis method.
* <p>
* After being analysed the ReplaceMap can be retrieved for replacing
* placeholders on the analysis.html file.
* placeholders on the server.html file.
*
* @author Rsl1122
* @since 3.5.2
@ -30,7 +30,6 @@ public class AnalysisData extends RawData {
private final ActivityPart activityPart;
private final CommandUsagePart commandUsagePart;
private final GamemodePart gamemodePart;
private final GeolocationPart geolocationPart;
private final JoinInfoPart joinInfoPart;
private final KillPart killPart;
@ -44,16 +43,15 @@ public class AnalysisData extends RawData {
private Map<String, Serializable> additionalDataReplaceMap;
private String playersTable;
public AnalysisData(Map<String, Integer> commandUsage, List<TPS> tpsData) {
commandUsagePart = new CommandUsagePart(commandUsage);
public AnalysisData() {
commandUsagePart = new CommandUsagePart();
geolocationPart = new GeolocationPart();
joinInfoPart = new JoinInfoPart();
playerCountPart = new PlayerCountPart();
playtimePart = new PlaytimePart(playerCountPart);
killPart = new KillPart(playerCountPart);
gamemodePart = new GamemodePart();
tpsPart = new TPSPart(tpsData);
activityPart = new ActivityPart(joinInfoPart, tpsPart);
playtimePart = new PlaytimePart();
killPart = new KillPart(joinInfoPart);
tpsPart = new TPSPart();
activityPart = new ActivityPart(playerCountPart, joinInfoPart, tpsPart);
worldPart = new WorldPart();
}
@ -65,10 +63,6 @@ public class AnalysisData extends RawData {
return commandUsagePart;
}
public GamemodePart getGamemodePart() {
return gamemodePart;
}
public GeolocationPart getGeolocationPart() {
return geolocationPart;
}
@ -98,9 +92,9 @@ public class AnalysisData extends RawData {
}
public List<RawData> getAllParts() {
return Arrays.asList(activityPart, commandUsagePart, gamemodePart,
geolocationPart, joinInfoPart, killPart,
playerCountPart, playtimePart, tpsPart, worldPart);
return Arrays.asList(activityPart, commandUsagePart, geolocationPart,
joinInfoPart, killPart, playerCountPart, playtimePart, tpsPart,
worldPart);
}
public String getPlanVersion() {
@ -137,7 +131,7 @@ public class AnalysisData extends RawData {
Verify.nullCheck(pluginsTabLayout);
Verify.nullCheck(planVersion);
addValue("sortabletable", playersTable);
addValue("tableBodyPlayerList", playersTable);
addValue("version", planVersion);
final List<RawData> parts = getAllParts();
@ -157,8 +151,7 @@ public class AnalysisData extends RawData {
}
public String replacePluginsTabLayout() {
String replacedOnce = HtmlUtils.replacePlaceholders(pluginsTabLayout, additionalDataReplaceMap);
return HtmlUtils.replacePlaceholders(replacedOnce, additionalDataReplaceMap);
return HtmlUtils.replacePlaceholders(pluginsTabLayout, additionalDataReplaceMap);
}
public long getRefreshDate() {

View File

@ -1,104 +0,0 @@
package main.java.com.djrapitops.plan.data;
import java.util.Objects;
import java.util.UUID;
/**
* This class is used to store data about a player kill inside the UserData
* object.
*
* @author Rsl1122
*/
public class KillData {
private final UUID victim;
private int victimUserID;
private final long date;
private final String weapon;
/**
* Creates a KillData object with given parameters.
*
* @param victim UUID of the victim.
* @param victimID ID of the victim, get from the database.
* @param weapon Weapon used.
* @param date Epoch millisecond at which the kill occurred.
*/
public KillData(UUID victim, int victimID, String weapon, long date) {
this.victim = victim;
this.weapon = weapon;
victimUserID = victimID;
this.date = date;
}
/**
* 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 getDate() {
return date;
}
/**
* Get the Weapon used as string.
*
* @return For example DIAMOND_SWORD
*/
public String getWeapon() {
return weapon;
}
/**
* Get the UserID of the victim, found from the database.
*
* @return For example: 6
*/
public int getVictimUserID() {
return victimUserID;
}
@Override
public String toString() {
return "{victim:" + victim + "|victimUserID:" + victimUserID + "|date:" + date + "|weapon:" + weapon + '}';
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final KillData other = (KillData) obj;
return this.date == other.date
&& Objects.equals(this.weapon, other.weapon)
&& Objects.equals(this.victim, other.victim);
}
@Override
public int hashCode() {
int hash = 3;
hash = 89 * hash + Objects.hashCode(this.victim);
hash = 89 * hash + (int) (this.date ^ (this.date >>> 32));
hash = 89 * hash + Objects.hashCode(this.weapon);
return hash;
}
public void setVictimUserID(int victimUserID) {
this.victimUserID = victimUserID;
}
}

View File

@ -0,0 +1,90 @@
package main.java.com.djrapitops.plan.data;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.database.tables.Actions;
import org.apache.commons.lang3.builder.ToStringBuilder;
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 = Plan.getInstance().getDataCache().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 new ToStringBuilder(this)
.append("victim", victim)
.append("time", time)
.append("weapon", weapon)
.toString();
}
}

View File

@ -0,0 +1,215 @@
package main.java.com.djrapitops.plan.data;
import main.java.com.djrapitops.plan.data.time.WorldTimes;
import org.apache.commons.lang3.builder.ToStringBuilder;
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 & GameMode playtimes</li>
* <li>Player & 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;
}
/**
* Starts a new Session.
*
* @param time Time the session started.
* @param world World the session started in.
* @param gm GameMode the session started in.
* @return a new Session object.
*/
public static Session start(long time, String world, String gm) {
return new Session(time, world, gm);
}
/**
* 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() {
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. Check using {@code isFetchedFromDB}
*/
public int getSessionID() {
return sessionID;
}
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 new ToStringBuilder(this)
.append("sessionStart", sessionStart)
.append("sessionID", sessionID)
.append("worldTimes", worldTimes)
.append("sessionEnd", sessionEnd)
.append("playerKills", playerKills)
.append("mobKills", mobKills)
.append("deaths", deaths)
.toString();
}
}

View File

@ -1,119 +0,0 @@
package main.java.com.djrapitops.plan.data;
/**
* This class is used for storing start and end of a play session inside UserData
* object.
*
* @author Rsl1122
*/
public class SessionData {
private final long sessionStart;
private long sessionEnd;
/**
* Creates a new session with given start and end of -1.
*
* @param sessionStart Epoch millisecond the session was started.
*/
public SessionData(long sessionStart) {
this.sessionStart = sessionStart;
this.sessionEnd = -1;
}
/**
* Creates a new session with given start and end.
*
* @param sessionStart Epoch millisecond the session was started.
* @param sessionEnd Epoch millisecond the session ended.
*/
public SessionData(long sessionStart, long sessionEnd) {
this.sessionStart = sessionStart;
this.sessionEnd = sessionEnd;
}
/**
* Constructor for copying the object.
*
* @param s SessionData to copy.
*/
public SessionData(SessionData s) {
this.sessionStart = s.getSessionStart();
this.sessionEnd = s.getSessionEnd();
}
/**
* 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;
}
/**
* 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;
}
/**
* Get the length of the session in milliseconds.
*
* @return Long in ms.
*/
public long getLength() {
return sessionEnd - sessionStart;
}
@Override
public String toString() {
return "s:" + sessionStart + " e:" + sessionEnd;
}
/**
* Check if the session start was before the end.
*
* @return Is the length positive?
*/
public boolean isValid() {
return sessionStart <= sessionEnd;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final SessionData other = (SessionData) obj;
return this.sessionStart == other.sessionStart && this.sessionEnd == other.sessionEnd;
}
@Override
public int hashCode() {
int hash = 3;
hash = 97 * hash + (int) (this.sessionStart ^ (this.sessionStart >>> 32));
hash = 97 * hash + (int) (this.sessionEnd ^ (this.sessionEnd >>> 32));
return hash;
}
}

View File

@ -5,6 +5,10 @@
*/
package main.java.com.djrapitops.plan.data;
import org.apache.commons.lang3.builder.ToStringBuilder;
import java.util.Objects;
/**
* Class containing single datapoint of TPS / Players online / CPU Usage / Used Memory / Entity Count / Chunks loaded.
*
@ -24,13 +28,13 @@ public class TPS {
/**
* 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
* @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;
@ -106,37 +110,34 @@ public class TPS {
}
@Override
public int hashCode() {
int hash = 3;
hash = 97 * hash + (int) (this.date ^ (this.date >>> 32));
hash = 97 * hash + (int) (Double.doubleToLongBits(this.ticksPerSecond) ^ (Double.doubleToLongBits(this.ticksPerSecond) >>> 32));
hash = 97 * hash + this.players;
return hash;
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 boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final TPS other = (TPS) obj;
return date == other.date
&& Double.compare(this.ticksPerSecond, other.ticksPerSecond) == 0
&& this.players == other.players
&& Double.compare(cpuUsage, other.cpuUsage) == 0;
public int hashCode() {
return Objects.hash(date, ticksPerSecond, players, cpuUsage, usedMemory, entityCount, chunksLoaded);
}
@Override
public String toString() {
return "TPS{" + date + "|" + ticksPerSecond + "|" + players + "|" + cpuUsage + "}";
return new ToStringBuilder(this)
.append("date", date)
.append("ticksPerSecond", ticksPerSecond)
.append("players", players)
.append("cpuUsage", cpuUsage)
.append("usedMemory", usedMemory)
.append("entityCount", entityCount)
.append("chunksLoaded", chunksLoaded)
.toString();
}
}

View File

@ -1,758 +0,0 @@
package main.java.com.djrapitops.plan.data;
import com.djrapitops.plugin.utilities.Verify;
import com.djrapitops.plugin.utilities.player.IOfflinePlayer;
import com.djrapitops.plugin.utilities.player.IPlayer;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.data.time.GMTimes;
import main.java.com.djrapitops.plan.data.time.WorldTimes;
import java.net.InetAddress;
import java.util.*;
import java.util.stream.Collectors;
/**
* This class is used for storing information about a player during runtime.
*
* @author Rsl1122
*/
public class UserData {
private final List<SessionData> sessions;
private int accessing;
private boolean clearAfterSave;
private UUID uuid;
private String name;
private Set<String> nicknames;
private String lastNick;
private String geolocation;
private Set<InetAddress> ips;
private int loginTimes;
private int timesKicked;
private boolean isOp;
private boolean isBanned;
private boolean isOnline;
private int mobKills;
private List<KillData> playerKills;
private int deaths;
private long registered;
private long lastPlayed;
private long playTime;
private GMTimes gmTimes;
private WorldTimes worldTimes;
/**
* Creates a new UserData object with given values and default values.
* <p>
* Some variables are left uninitialized: isBanned, lastPlayed, playTime,
* loginTimes, timesKicked, lastGmSwapTime, mobKills, deaths, lastWorldSwapTime, lastWorld
* <p>
* These variables need to be set with setters.
* <p>
* All Collections are left empty: locations, nicknames, ips, sessions,
* playerKills. Because nicknames is empty, lastNick is an empty string.
* <p>
* gmTimes Map will contain 4 '0L' values: SURVIVAL, CREATIVE,
* ADVENTURE, SPECTATOR
* worldTimes Map is left empty.
*
* @param uuid UUID of the player
* @param reg Epoch millisecond the player registered.
* @param op Is the player op? (true/false)
* @param name Name of the player.
* @param online Is the player online?
*/
public UserData(UUID uuid, long reg, boolean op, String gm, String name, boolean online) {
accessing = 0;
this.gmTimes = new GMTimes(gm);
this.worldTimes = new WorldTimes();
this.uuid = uuid;
this.name = name;
lastNick = "";
nicknames = new HashSet<>();
ips = new HashSet<>();
geolocation = "Not Known";
isOp = op;
isOnline = online;
registered = reg;
sessions = new ArrayList<>();
playerKills = new ArrayList<>();
}
/**
* Creates a new UserData object with the variables inside a Player object.
* <p>
* Some variables are left uninitialized: lastPlayed, playTime, loginTimes,
* timesKicked, lastGmSwapTime, mobKills, deaths and currentSession.
* <p>
* These variables need to be set with setters.
* <p>
* All Collections are left empty: locations, nicknames, ips, sessions,
* playerKills. Because nicknames is empty, lastNick is an empty string.
* <p>
* gmTimes HashMap will contain 4 '0L' values: SURVIVAL, CREATIVE,
* ADVENTURE, SPECTATOR
*
* @param player IPlayer object.
*/
public UserData(IPlayer player) {
this(player.getUuid(), player.getFirstPlayed(), player.isOp(), player.getGamemode().name(), player.getName(), player.isOnline());
try {
isBanned = player.isBanned();
} catch (Exception e) {
Log.error("Error getting ban date from Bukkit files. " + uuid.toString());
Log.toLog(this.getClass().getName(), e);
isBanned = false;
}
}
/**
* Creates a new UserData object with the variables inside a OfflinePlayer
* object.
* <p>
* Some variables are left uninitialized: location, lastPlayed, playTime,
* loginTimes, timesKicked, lastGmSwapTime, mobKills, deaths and
* currentSession.
* <p>
* These variables need to be set with setters.
* <p>
* All Collections are left empty: locations, nicknames, ips, sessions,
* playerKills. Because nicknames is empty, lastNick is an empty string.
* <p>
* gmTimes HashMap will contain 4 '0L' values: SURVIVAL, CREATIVE,
* ADVENTURE, SPECTATOR
* <p>
* lastGM will be set as SURVIVAL
*
* @param player IOfflinePlayer object.
*/
public UserData(IOfflinePlayer player) {
this(player.getUniqueId(), player.getFirstPlayed(), player.isOp(), "SURVIVAL", player.getName(), player.isOnline());
try {
isBanned = player.isBanned();
} catch (Exception e) {
Log.error("Error getting ban date from Bukkit files. " + uuid.toString());
Log.toLog(this.getClass().getName(), e);
isBanned = false;
}
}
/**
* Creates a new UserData object with copied values.
*
* @param data UserData to copy into the new object.
*/
public UserData(UserData data) {
this.accessing = 0;
this.uuid = data.getUuid();
this.ips = new HashSet<>();
ips.addAll(data.getIps());
this.nicknames = new HashSet<>();
nicknames.addAll(data.getNicknames());
this.lastNick = data.getLastNick();
this.registered = data.getRegistered();
this.lastPlayed = data.getLastPlayed();
this.playTime = data.getPlayTime();
this.loginTimes = data.getLoginTimes();
this.timesKicked = data.getTimesKicked();
this.gmTimes = data.getGmTimes();
this.worldTimes = data.getWorldTimes();
this.isOp = data.isOp();
this.isBanned = data.isBanned();
this.geolocation = data.getGeolocation();
this.mobKills = data.getMobKills();
this.playerKills = data.getPlayerKills();
this.deaths = data.getDeaths();
this.name = data.getName();
this.isOnline = data.isOnline();
this.sessions = new ArrayList<>();
sessions.addAll(data.getSessions());
}
@Override
public String toString() {
try {
return "{" + "accessing:" + accessing + "|uuid:" + uuid + "|ips:" + ips + "|nicknames:" + nicknames + "|lastNick:" + lastNick + "|registered:" + registered + "|lastPlayed:" + lastPlayed + "|playTime:" + playTime + "|loginTimes:" + loginTimes + "|timesKicked:" + timesKicked + "|gm:" + gmTimes + "|world:" + worldTimes + "|isOp:" + isOp + "|isBanned:" + isBanned + "|geolocation:" + geolocation + "|mobKills:" + mobKills + "|playerKills:" + playerKills + "|deaths:" + deaths + "|name:" + name + "|isOnline:" + isOnline + "|sessions:" + sessions + '}';
} catch (Exception e) {
return "UserData: Error on toString:" + e;
}
}
/**
* Adds an to the ips Set if it is not null or the set doesn't contain it.
*
* @param ip InetAddress of the player.
*/
public void addIpAddress(InetAddress ip) {
if (Verify.notNull(ip)) {
ips.add(ip);
}
}
/**
* Adds multiple ips to the ips set if they're not null.
*
* @param addIps a Collection of InetAddresses the player has logged from.
*/
public void addIpAddresses(Collection<InetAddress> addIps) {
if (addIps.isEmpty()) {
return;
}
ips.addAll(addIps.stream().filter(Verify::notNull).collect(Collectors.toList()));
}
/**
* Adds a nickname to the nicknames Set.
* <p>
* null or empty values filtered.
* <p>
* lastNick will be set as the given parameter, if accepted.
*
* @param nick Displayname of the player.
* @return was lastNick updated?
*/
public boolean addNickname(String nick) {
if (!Verify.isEmpty(nick)) {
boolean isNew = !nicknames.contains(nick);
nicknames.add(nick);
if (isNew) {
lastNick = nick;
}
return isNew;
}
return false;
}
/**
* Adds nicknames to the nicknames Set.
* <p>
* null or empty values filtered.
*
* @param addNicks Collection of nicknames.
*/
public void addNicknames(Collection<String> addNicks) {
nicknames.addAll(addNicks.stream().filter(nick -> !Verify.isEmpty(nick)).collect(Collectors.toList()));
}
/**
* Adds a new SessionData to the sessions list.
* <p>
* null and invalid sessions filtered.
*
* @param session SessionData object
*/
public void addSession(SessionData session) {
if (Verify.notNull(session) && session.isValid()) {
sessions.add(session);
}
}
/**
* Adds SessionData objects to the sessions list.
* <p>
* null and invalid sessions filtered.
*
* @param sessions Collection of SessionData objects.
*/
public void addSessions(Collection<SessionData> sessions) {
Collection<SessionData> filteredSessions = sessions.stream()
.filter(Verify::notNull)
.filter(SessionData::isValid)
.collect(Collectors.toList());
this.sessions.addAll(filteredSessions);
}
/**
* Changes the value of isBanned.
*
* @param isBanned Is the player banned?
*/
public void updateBanned(boolean isBanned) {
this.isBanned = isBanned;
}
/**
* Checks whether or not the UserData object is accessed by different save
* processes.
*
* @return true if accessed.
*/
public boolean isAccessed() {
return accessing > 0;
}
/**
* Accesses the UserData object to protect it from being cleared.
*/
public void access() {
accessing++;
}
/**
* Stops accessing the object so that it can now be cleared.
*/
public void stopAccessing() {
accessing--;
}
/**
* Used to get the UUID of the player.
*
* @return UUID.
*/
public UUID getUuid() {
return uuid;
}
/**
* Set the UUID.
*
* @param uuid UUID
*/
public void setUuid(UUID uuid) {
this.uuid = uuid;
}
/**
* Get the InetAddress Set.
*
* @return a HashSet of ips.
*/
public Set<InetAddress> getIps() {
return ips;
}
/**
* Set the ips set.
*
* @param ips ips of the user.
*/
public void setIps(Set<InetAddress> ips) {
if (Verify.notNull(ips)) {
this.ips = ips;
}
}
/**
* Get the nickname String Set.
*
* @return a HashSet of Strings.
*/
public Set<String> getNicknames() {
return nicknames;
}
/**
* Set the nicknames set.
*
* @param nicknames nicknames of the user.
*/
public void setNicknames(Set<String> nicknames) {
if (Verify.notNull(nicknames)) {
this.nicknames = nicknames;
}
}
/**
* Get the Epoch millisecond the player registered.
*
* @return long in ms.
*/
public long getRegistered() {
return registered;
}
/**
* Set the time the user was registered.
*
* @param registered Epoch millisecond of register time.
*/
public void setRegistered(long registered) {
this.registered = registered;
}
/**
* Get the Epoch millisecond the player was last seen.
* <p>
* NOT INITIALIZED BY CONSTRUCTORS. Value is updated periodically by cache
* if the player is online.
*
* @return long in ms.
*/
public long getLastPlayed() {
return lastPlayed;
}
/**
* Set the time the user was last seen.
* <p>
* Affects playtime calculation, playtime should be updated before updating
* this value.
*
* @param lastPlayed Epoch millisecond of last seen moment.
*/
public void setLastPlayed(long lastPlayed) {
this.lastPlayed = lastPlayed;
}
/**
* Get the playtime in milliseconds.
* <p>
* NOT INITIALIZED BY CONSTRUCTORS. Value is updated periodically by cache
* if the player is online.
*
* @return time in ms.
*/
public long getPlayTime() {
return playTime;
}
/**
* Set the time the user has been playing.
*
* @param playTime Time in ms.
*/
public void setPlayTime(long playTime) {
this.playTime = playTime;
}
/**
* Get how many times the player has logged in.
* <p>
* NOT INITIALIZED BY CONSTRUCTORS.
*
* @return 0 to Integer.MAX
*/
public int getLoginTimes() {
return loginTimes;
}
/**
* Set how many times the user has logged in.
* <p>
* No check for input.
*
* @param loginTimes 0 to Int.MAX
*/
public void setLoginTimes(int loginTimes) {
this.loginTimes = loginTimes;
}
/**
* Get how many times the player has been kicked.
* <p>
* NOT INITIALIZED BY CONSTRUCTORS.
*
* @return 0 to Integer.MAX
*/
public int getTimesKicked() {
return timesKicked;
}
/**
* Set how many times the user has been kicked.
* <p>
* No check for input.
*
* @param timesKicked 0 to Int.MAX
*/
public void setTimesKicked(int timesKicked) {
this.timesKicked = timesKicked;
}
/**
* Get the GMTimes object.
*
* @return TimeKeeper object with possible keys of SURVIVAL, CREATIVE, ADVENTURE, SPECTATOR
*/
public GMTimes getGmTimes() {
return gmTimes;
}
/**
* Set the GM Times object containing playtime in each gamemode.
*
* @param gmTimes GM Times object
*/
public void setGmTimes(GMTimes gmTimes) {
if (Verify.notNull(gmTimes)) {
this.gmTimes = gmTimes;
}
}
public void setGmTimes(Map<String, Long> times) {
if (Verify.notNull(times)) {
for (Map.Entry<String, Long> entry : times.entrySet()) {
gmTimes.setTime(entry.getKey(), entry.getValue());
}
}
}
/**
* Is the user Operator?
*
* @return opped?
*/
public boolean isOp() {
return isOp;
}
/**
* Is the user Banned?
*
* @return banned?
*/
public boolean isBanned() {
return isBanned;
}
/**
* Set the banned value.
*
* @param isBanned true/false
*/
public void setBanned(boolean isBanned) {
this.isBanned = isBanned;
}
/**
* Get the username of the player.
*
* @return username.
*/
public String getName() {
return name;
}
/**
* Set the username of the user.
*
* @param name username.
*/
public void setName(String name) {
this.name = name;
}
/**
* Set whether or not player is op.
*
* @param isOp operator?
*/
public void setIsOp(boolean isOp) {
this.isOp = isOp;
}
/**
* Is the player online?
*
* @return true if data is cached to datacache, false if not.
*/
public boolean isOnline() {
return isOnline;
}
/**
* Set the online value.
*
* @param isOnline true/false
*/
public void setOnline(boolean isOnline) {
this.isOnline = isOnline;
}
/**
* Get how many mob kills the player has.
*
* @return 0 to Int.MAX
*/
public int getMobKills() {
return mobKills;
}
/**
* Get how many mob kills the player has.
*
* @param mobKills 0 to Int.MAX
*/
public void setMobKills(int mobKills) {
this.mobKills = mobKills;
}
/**
* Get the player kills list.
*
* @return playerkills list.
*/
public List<KillData> getPlayerKills() {
return playerKills;
}
/**
* Set the playerkills list.
*
* @param playerKills list of players kills.
*/
public void setPlayerKills(List<KillData> playerKills) {
if (Verify.notNull(playerKills)) {
this.playerKills = playerKills;
}
}
/**
* Add a Killdata to player's kills list.
*
* @param kill KillData representing a player kill.
*/
public void addPlayerKill(KillData kill) {
playerKills.add(kill);
}
/**
* Get how many times the player has died.
*
* @return 0 to Int.MAX
*/
public int getDeaths() {
return deaths;
}
/**
* Set how many times the player has died.
*
* @param deaths 0 to Int.MAX
*/
public void setDeaths(int deaths) {
this.deaths = deaths;
}
/**
* Get the sessions of a player.
*
* @return a list of SessionData.
*/
public List<SessionData> getSessions() {
return sessions;
}
/**
* Get the last nickname the user has set.
* <p>
* Set when using addNickname(String)
*
* @return last nickname used.
*/
public String getLastNick() {
return lastNick;
}
/**
* Set the last nickname the user has set.
* <p>
* Also set when using addNickname(String)
*
* @param lastNick last nickname used.
*/
public void setLastNick(String lastNick) {
this.lastNick = lastNick;
}
public WorldTimes getWorldTimes() {
return worldTimes;
}
public void setWorldTimes(WorldTimes worldTimes) {
this.worldTimes = worldTimes;
}
/**
* Check whether or not the object should be cleared from cache after it has
* been saved.
*
* @return true/false
*/
public boolean shouldClearAfterSave() {
return clearAfterSave;
}
/**
* Set whether or not the object should be cleared from cache after it has
* been saved.
*
* @param clearAfterSave true/false
*/
public void setClearAfterSave(boolean clearAfterSave) {
this.clearAfterSave = clearAfterSave;
}
public String getGeolocation() {
return geolocation;
}
public void setGeolocation(String geolocation) {
this.geolocation = geolocation;
}
@Override
public int hashCode() {
int result = sessions.hashCode();
result = 31 * result + accessing;
result = 31 * result + (clearAfterSave ? 1 : 0);
result = 31 * result + uuid.hashCode();
result = 31 * result + ips.hashCode();
result = 31 * result + nicknames.hashCode();
result = 31 * result + lastNick.hashCode();
result = 31 * result + (int) (registered ^ (registered >>> 32));
result = 31 * result + (int) (lastPlayed ^ (lastPlayed >>> 32));
result = 31 * result + (int) (playTime ^ (playTime >>> 32));
result = 31 * result + loginTimes;
result = 31 * result + timesKicked;
result = 31 * result + gmTimes.hashCode();
result = 31 * result + worldTimes.hashCode();
result = 31 * result + (isOp ? 1 : 0);
result = 31 * result + (isBanned ? 1 : 0);
result = 31 * result + geolocation.hashCode();
result = 31 * result + mobKills;
result = 31 * result + playerKills.hashCode();
result = 31 * result + deaths;
result = 31 * result + name.hashCode();
result = 31 * result + (isOnline ? 1 : 0);
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final UserData other = (UserData) obj;
return this.registered == other.registered
&& this.playTime == other.playTime
&& this.loginTimes == other.loginTimes
&& this.timesKicked == other.timesKicked
&& this.mobKills == other.mobKills
&& this.deaths == other.deaths
&& Objects.equals(this.lastNick, other.lastNick)
&& Objects.equals(this.name, other.name)
&& Objects.equals(this.uuid, other.uuid)
&& Objects.equals(this.ips, other.ips)
&& Objects.equals(this.nicknames, other.nicknames)
&& Objects.equals(this.gmTimes, other.gmTimes)
&& Objects.equals(this.worldTimes, other.worldTimes)
&& Objects.equals(this.playerKills, other.playerKills)
&& Objects.equals(this.sessions, other.sessions);
}
}

View File

@ -0,0 +1,101 @@
package main.java.com.djrapitops.plan.data;
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;
}
public UUID getUuid() {
return uuid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getRegistered() {
return registered;
}
public void setRegistered(long registered) {
this.registered = registered;
}
public long getLastSeen() {
return lastSeen;
}
public void setLastSeen(long lastSeen) {
this.lastSeen = lastSeen;
}
public boolean isBanned() {
return banned;
}
public void setBanned(boolean banned) {
this.banned = 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 +
'}';
}
}

View File

@ -1,5 +1,7 @@
package main.java.com.djrapitops.plan.data;
import java.util.Objects;
/**
* Object containing webserver security user information.
*
@ -34,19 +36,14 @@ public class WebUser {
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
&& user.equals(webUser.user)
&& saltedPassHash.equals(webUser.saltedPassHash);
return permLevel == webUser.permLevel &&
Objects.equals(user, webUser.user) &&
Objects.equals(saltedPassHash, webUser.saltedPassHash);
}
@Override
public int hashCode() {
int result = user.hashCode();
result = 31 * result + saltedPassHash.hashCode();
result = 31 * result + permLevel;
return result;
return Objects.hash(user, saltedPassHash, permLevel);
}
}

View File

@ -20,56 +20,56 @@ public enum AnalysisType {
* <p>
* -1 values will be disregarded from the calculation (size will not grow).
*/
INT_AVG("avgInt_", "Average "),
INT_AVG("_avgInt", "Average "),
/**
* Used when the getValue() method returns a long and average should be
* calculated.
* <p>
* -1 values will be disregarded from the calculation (size will not grow).
*/
LONG_AVG("avgLong_", "Average "),
LONG_AVG("_avgLong", "Average "),
/**
* Used when the getValue() method returns double and average should be
* calculated.
* <p>
* -1 values will be disregarded from the calculation (size will not grow).
*/
DOUBLE_AVG("avgDouble_", "Average "),
DOUBLE_AVG("_avgDouble", "Average "),
/**
* Used when the getValue() method returns an integer and total should be
* calculated.
* <p>
* -1 values will be disregarded from the calculation (size will not grow).
*/
INT_TOTAL("totalInt_", "Total "),
INT_TOTAL("_totalInt", "Total "),
/**
* Used when the getValue() method returns a long and total should be
* calculated.
* <p>
* -1 values will be disregarded from the calculation (size will not grow).
*/
LONG_TOTAL("totalLong_", "Total "),
LONG_TOTAL("_totalLong", "Total "),
/**
* Used when the getValue() method returns a double and total should be
* calculated.
* <p>
* -1 values will be disregarded from the calculation (size will not grow).
*/
DOUBLE_TOTAL("totalDouble_", "Total "),
DOUBLE_TOTAL("_totalDouble", "Total "),
/**
* Used when the getValue() method returns an amount of milliseconds as long
* and average should be calculated.
* <p>
* -1 values will be disregarded from the calculation (size will not grow).
*/
LONG_TIME_MS_AVG("avgTimeMs_", "Average "),
LONG_TIME_MS_AVG("_avgTimeMs", "Average "),
/**
* Used when the getValue() method returns an amount of milliseconds as long
* and total should be calculated.
* <p>
* -1 values will be disregarded from the calculation (size will not grow).
*/
LONG_TIME_MS_TOTAL("totalTimeMs_"),
LONG_TIME_MS_TOTAL("_totalTimeMs"),
/**
* Used when the getValue() method returns an Epoch Millisecond as long and
* average of differences between the millisecond and current millisecond
@ -81,18 +81,18 @@ public enum AnalysisType {
* <p>
* -1 values will be disregarded from the calculation (size will not grow).
*/
LONG_EPOCH_MS_MINUS_NOW_AVG("avgEpochMsMinusNow_", "Average "),
LONG_EPOCH_MS_MINUS_NOW_AVG("_avgEpochMsMinusNow", "Average "),
/**
* Used to calculate %-true for the returned boolean values of getValue().
*/
BOOLEAN_PERCENTAGE("perchBool_", "Percentage "),
BOOLEAN_PERCENTAGE("_perchBool", "Percentage "),
/**
* Used to calculate number of true values for the returned boolean values
* of getValue().
* <p>
* Will be presented as "n / total".
*/
BOOLEAN_TOTAL("totalBool_"),
BOOLEAN_TOTAL("_totalBool"),
/**
* Used to add html tags to the plugins tab.
* <p>

View File

@ -3,7 +3,7 @@ package main.java.com.djrapitops.plan.data.additional;
import com.djrapitops.pluginbridge.plan.Bridge;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.utilities.HtmlUtils;
import org.apache.commons.lang3.StringUtils;
import java.io.Serializable;
import java.util.*;
@ -53,7 +53,7 @@ public class HookHandler {
configHandler.createSection(dataSource);
}
if (configHandler.isEnabled(dataSource)) {
Log.debug("Registered a new datasource: " + dataSource.getPlaceholder("").replace("%", ""));
Log.debug("Registered a new datasource: " + StringUtils.remove(dataSource.getPlaceholder(), '%'));
additionalDataSources.add(dataSource);
}
} catch (Exception e) {
@ -71,32 +71,6 @@ public class HookHandler {
return additionalDataSources;
}
/**
* Used to get the Layout with PluginData placeholders to replace %plugins%
* placeholder on analysis.html.
*
* @return html, getPluginsTabLayout-method
* @see HtmlUtils
*/
public String getPluginsTabLayoutForAnalysis() {
List<String> pluginNames = getPluginNamesAnalysis();
Map<String, List<String>> placeholders = getPlaceholdersAnalysis();
return HtmlUtils.getPluginsTabLayout(pluginNames, placeholders);
}
/**
* Used to get the Layout with PluginData placeholders to replace %plugins%
* placeholder on player.html.
*
* @return html, getPluginsTabLayout-method
* @see HtmlUtils
*/
public String getPluginsTabLayoutForInspect() {
List<String> pluginNames = getPluginNamesInspect();
Map<String, List<String>> placeholders = getPlaceholdersInspect();
return HtmlUtils.getPluginsTabLayout(pluginNames, placeholders);
}
private List<String> getPluginNamesAnalysis() {
List<String> pluginNames = additionalDataSources.stream()
.filter(source -> !source.getAnalysisTypes().isEmpty())
@ -117,39 +91,6 @@ public class HookHandler {
return pluginNames;
}
private Map<String, List<String>> getPlaceholdersAnalysis() {
Map<String, List<String>> placeholders = new HashMap<>();
for (PluginData source : additionalDataSources) {
List<AnalysisType> analysisTypes = source.getAnalysisTypes();
if (analysisTypes.isEmpty()) {
continue;
}
String pluginName = source.getSourcePlugin();
if (!placeholders.containsKey(pluginName)) {
placeholders.put(pluginName, new ArrayList<>());
}
for (AnalysisType t : analysisTypes) {
placeholders.get(pluginName).add(source.getPlaceholder(t.getPlaceholderModifier()));
}
}
return placeholders;
}
private Map<String, List<String>> getPlaceholdersInspect() {
Map<String, List<String>> placeholders = new HashMap<>();
for (PluginData source : additionalDataSources) {
if (source.analysisOnly()) {
continue;
}
String pluginName = source.getSourcePlugin();
if (!placeholders.containsKey(pluginName)) {
placeholders.put(pluginName, new ArrayList<>());
}
placeholders.get(pluginName).add(source.getPlaceholder(""));
}
return placeholders;
}
/**
* Used to get the replaceMap for inspect page.
*
@ -163,9 +104,9 @@ public class HookHandler {
continue;
}
try {
addReplace.put(source.getPlaceholder(""), source.getHtmlReplaceValue("", uuid));
addReplace.put(source.getPlaceholderName(), source.getHtmlReplaceValue("", uuid));
} catch (Exception e) {
addReplace.put(source.getPlaceholder(""), "Error occurred: " + e);
addReplace.put(source.getPlaceholderName(), "Error occurred: " + e);
Log.error("PluginDataSource caused an exception: " + source.getSourcePlugin());
Log.toLog("PluginDataSource " + source.getSourcePlugin(), e);
}

View File

@ -27,12 +27,12 @@ public class PluginConfigSectionHandler {
}
ConfigurationSection pluginSection = section.getConfigurationSection(pluginName);
return pluginSection.contains(dataSource.getPlaceholder(""));
return pluginSection.contains(dataSource.getPlaceholder());
}
private ConfigurationSection getPluginsSection() {
FileConfiguration config = plan.getConfig();
return config.getConfigurationSection("Customization.Plugins");
return config.getConfigurationSection("Plugins");
}
public void createSection(PluginData dataSource) {
@ -44,7 +44,7 @@ public class PluginConfigSectionHandler {
section.addDefault(pluginName + ".Data." + source, true);
FileConfiguration config = plan.getConfig();
config.set("Customization.Plugins", section);
config.set("Plugins", section);
plan.saveConfig();
}

View File

@ -1,6 +1,8 @@
package main.java.com.djrapitops.plan.data.additional;
import main.java.com.djrapitops.plan.ui.html.Html;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.utilities.html.Html;
import org.apache.commons.lang3.builder.ToStringBuilder;
import java.io.Serializable;
import java.util.*;
@ -139,7 +141,8 @@ public abstract class PluginData {
* @see AnalysisType
*/
public final String parseContainer(String modifier, String contents) {
return "<div class=\"plugin-data\">" + (icon.isEmpty() ? "<br>" : Html.FONT_AWESOME_ICON.parse(icon)) + " " + modifier + prefix + contents + suffix + "</div>";
boolean html = analysisTypes.contains(AnalysisType.HTML);
return "<div class=\"plugin-data\">" + (html ? "" : "<p>") + (icon.isEmpty() ? "" : Html.FONT_AWESOME_ICON.parse(icon)) + " " + modifier + prefix + contents + suffix + (html ? "" : "</p>") + "</div>";
}
/**
@ -150,11 +153,41 @@ public abstract class PluginData {
*
* @param modifier Modifier determined by AnalysisType's
* placeholderModifier-variable.
* @return for example "%StepCounter_stepsTaken_total%"
* @return for example "${StepCounter_stepsTaken_total}"
* @see AnalysisType
*/
public final String getPlaceholder(String modifier) {
return "%" + sourcePlugin + "_" + placeholder + modifier + "%";
return "${" + getPlaceholderName(modifier) + "}";
}
/**
* Used to get the placeholder without the modifier.
*
* @return for example "${StepCounter_stepsTaken}"
* @see #getPlaceholder(String)
*/
public final String getPlaceholder() {
return "${" + getPlaceholderName() + "}";
}
/**
* Used to get the placeholder name with modifier.
*
* @return for example "StepCounter_stepsTaken_modifier"
* @see #getPlaceholder(String)
*/
public final String getPlaceholderName(String modifier) {
return getPlaceholderName() + modifier;
}
/**
* Used to get the placeholder name.
*
* @return for example "StepCounter_stepsTaken"
* @see #getPlaceholder(String)
*/
public final String getPlaceholderName() {
return sourcePlugin + "_" + placeholder;
}
/**
@ -279,40 +312,43 @@ public abstract class PluginData {
&& analysisTypes.contains(AnalysisType.BOOLEAN_TOTAL);
}
/**
* If a PluginData object has same placeholder, sourcePlugin and
* analysisTypes, it is considered equal.
*
* @param obj Another Object.
* @return Is current object equal to given object.
*/
@Override
public final boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final PluginData other = (PluginData) obj;
return this.analysisOnly == other.analysisOnly
&& Objects.equals(this.placeholder, other.placeholder)
&& Objects.equals(this.sourcePlugin, other.sourcePlugin)
&& Objects.equals(this.analysisTypes, other.analysisTypes);
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PluginData that = (PluginData) o;
return analysisOnly == that.analysisOnly &&
Objects.equals(analysisTypes, that.analysisTypes) &&
Objects.equals(placeholder, that.placeholder) &&
Objects.equals(sourcePlugin, that.sourcePlugin) &&
Objects.equals(icon, that.icon) &&
Objects.equals(prefix, that.prefix) &&
Objects.equals(suffix, that.suffix);
}
@Override
public final int hashCode() {
int hash = 5;
hash = 47 * hash + Objects.hashCode(this.placeholder);
hash = 47 * hash + Objects.hashCode(this.sourcePlugin);
hash = 47 * hash + (this.analysisOnly ? 1 : 0);
hash = 47 * hash + Objects.hashCode(this.prefix);
hash = 47 * hash + Objects.hashCode(this.suffix);
hash = 47 * hash + Objects.hashCode(this.analysisTypes);
return hash;
public int hashCode() {
return Objects.hash(analysisTypes, placeholder, sourcePlugin, analysisOnly, icon, prefix, suffix);
}
@Override
public String toString() {
return new ToStringBuilder(this)
.append("analysisTypes", analysisTypes)
.append("placeholder", placeholder)
.append("sourcePlugin", sourcePlugin)
.append("analysisOnly", analysisOnly)
.append("icon", icon)
.append("prefix", prefix)
.append("suffix", suffix)
.toString();
}
protected Set<UUID> getUUIDsBeingAnalyzed() {
return Plan.getInstance().getDataCache().getUuids();
}
protected String getNameOf(UUID uuid) {
return Plan.getInstance().getDataCache().getName(uuid);
}
}

View File

@ -3,17 +3,15 @@ package main.java.com.djrapitops.plan.data.analysis;
import com.djrapitops.plugin.api.TimeAmount;
import com.djrapitops.plugin.utilities.Verify;
import main.java.com.djrapitops.plan.Settings;
import main.java.com.djrapitops.plan.data.SessionData;
import main.java.com.djrapitops.plan.data.Session;
import main.java.com.djrapitops.plan.data.TPS;
import main.java.com.djrapitops.plan.ui.html.RecentPlayersButtonsCreator;
import main.java.com.djrapitops.plan.ui.html.graphs.PlayerActivityGraphCreator;
import main.java.com.djrapitops.plan.ui.html.graphs.PunchCardGraphCreator;
import main.java.com.djrapitops.plan.ui.html.graphs.SessionLengthDistributionGraphCreator;
import main.java.com.djrapitops.plan.systems.webserver.theme.Colors;
import main.java.com.djrapitops.plan.utilities.FormatUtils;
import main.java.com.djrapitops.plan.utilities.HtmlUtils;
import main.java.com.djrapitops.plan.utilities.MiscUtils;
import main.java.com.djrapitops.plan.utilities.analysis.AnalysisUtils;
import main.java.com.djrapitops.plan.utilities.analysis.MathUtils;
import main.java.com.djrapitops.plan.utilities.html.graphs.PlayerActivityGraphCreator;
import main.java.com.djrapitops.plan.utilities.html.graphs.PunchCardGraphCreator;
import java.util.*;
import java.util.stream.Collectors;
@ -21,23 +19,28 @@ import java.util.stream.Collectors;
/**
* Part responsible for all Player Activity related analysis.
* <p>
* Online Graphs, Player-base pie-chart, Recent Players and Session
* visualisation.
* <p>
* Placeholder values can be retrieved using the get method.
* <p>
* Contains following place-holders: recentlogins, sessionaverage,
* datapunchcard, datasessiondistribution, labelssessiondistribution,
* datascatterday, datascatterweek, datascattermonth, playersonlinecolor,
* playersgraphfill, activecol, inactivecol, joinleavecol, bannedcol,
* activitycolors, labelsactivity, dataaactivity, active, inactive, joinleaver,
* banned
* Contains following placeholders after analyzed:
* ${active} - (Number)
* ${inactive} - (Number)
* ${joinLeaver} - (Number)
* ${banned} - (Number)
* ${activityColors} - Color array
* ${playersGraphColor} - Color
* <p>
* ${playersOnlineSeries} - Data for HighCharts
* ${sessionLengthSeries} - Data for HighCharts
* ${punchCardSeries} - Data for HighCharts
* <p>
* ${sessionAverage} - Formatted Time amount
*
* @author Rsl1122
* @since 3.5.2
*/
public class ActivityPart extends RawData {
private final PlayerCountPart playerCount;
private final JoinInfoPart joins;
private final TPSPart tpsPart;
private final Set<UUID> bans;
@ -47,7 +50,8 @@ public class ActivityPart extends RawData {
private List<String> recentPlayers;
private List<UUID> recentPlayersUUIDs;
public ActivityPart(JoinInfoPart joins, TPSPart tps) {
public ActivityPart(PlayerCountPart playerCount, JoinInfoPart joins, TPSPart tps) {
this.playerCount = playerCount;
this.joins = joins;
tpsPart = tps;
bans = new HashSet<>();
@ -61,76 +65,82 @@ public class ActivityPart extends RawData {
Verify.nullCheck(recentPlayers);
Verify.nullCheck(recentPlayersUUIDs);
addValue("recentlogins", RecentPlayersButtonsCreator.createRecentLoginsButtons(recentPlayers, 15));
activityPiechart();
playerActivityGraphs();
final List<SessionData> sessions = joins.getAllSessions();
final List<Session> sessions = joins.getAllSessions();
List<Long> lengths = AnalysisUtils.transformSessionDataToLengths(sessions);
long averageLength = MathUtils.averageLong(lengths);
addValue("sessionaverage", FormatUtils.formatTimeAmount(averageLength));
addValue("sessionAverage", FormatUtils.formatTimeAmount(averageLength));
List<SessionData> sessionsMonth = sessions.stream()
List<Session> sessionsMonth = sessions.stream()
.filter(s -> s.getSessionStart() > MiscUtils.getTime() - TimeAmount.MONTH.ms())
.collect(Collectors.toList());
addValue("punchcardseries", PunchCardGraphCreator.createDataSeries(sessionsMonth));
addValue("sessionlengthseries", SessionLengthDistributionGraphCreator.createDataSeries(lengths));
addValue("punchCardSeries", PunchCardGraphCreator.createDataSeries(sessionsMonth));
}
private void playerActivityGraphs() {
List<TPS> tpsData = tpsPart.getTpsData();
addValue("playersonlineseries", PlayerActivityGraphCreator.buildSeriesDataString(tpsData));
addValue("%playersgraphcolor%", Settings.HCOLOR_ACT_ONL.toString());
addValue("playersOnlineSeries", PlayerActivityGraphCreator.buildSeriesDataString(tpsData));
addValue("playersGraphColor", Colors.PLAYERS_ONLINE.getColor());
}
private void activityPiechart() {
calculateActivityAmounts();
int[] counts = new int[]{active.size(), inactive.size(), joinedOnce.size(), bans.size()};
final String colAct = Settings.HCOLOR_ACTP_ACT.toString();
final String colIna = Settings.HCOLOR_ACTP_INA.toString();
final String colJoi = Settings.HCOLOR_ACTP_JON.toString();
final String colBan = Settings.HCOLOR_ACTP_BAN.toString();
addValue("%activecol%", colAct);
addValue("%inactivecol%", colIna);
addValue("%joinleavecol%", colJoi);
addValue("%bancol%", colBan);
String activityColors = HtmlUtils.separateWithQuotes(
"#" + colAct, "#" + colIna, "#" + colJoi, "#" + colBan
);
addValue("%activitycolors%", activityColors);
addValue("activityPieColors", Settings.THEME_GRAPH_ACTIVITY_PIE.toString());
addValue("playersActive", counts[0]);
addValue("active", counts[0]);
addValue("inactive", counts[1]);
addValue("joinLeaver", counts[2]);
addValue("banned", counts[3]);
}
String activityLabels = "[" + HtmlUtils.separateWithQuotes(
"Active", "Inactive", "Unknown", "Banned") + "]";
addValue("%labelsactivity%", activityLabels);
private void calculateActivityAmounts() {
Map<UUID, List<Session>> allSessions = joins.getSessions();
for (UUID uuid : playerCount.getUuids()) {
if (bans.contains(uuid)) {
continue;
}
List<Session> sessions = allSessions.getOrDefault(uuid, new ArrayList<>());
long lastSeen = AnalysisUtils.getLastSeen(sessions);
long playtime = AnalysisUtils.getTotalPlaytime(sessions);
int sessionCount = sessions.size();
if (sessionCount <= 1) {
addJoinedOnce(uuid);
continue;
}
boolean isActive = AnalysisUtils.isActive(MiscUtils.getTime(), lastSeen, playtime, sessionCount);
if (isActive) {
addActive(uuid);
} else {
addInActive(uuid);
}
}
}
addValue("activitydata", Arrays.toString(counts));
addValue("%active%", counts[0]);
addValue("%inactive%", counts[1]);
addValue("%joinleaver%", counts[2]);
addValue("%banned%", counts[3]);
public void addBans(Collection<UUID> uuids) {
bans.addAll(uuids);
}
public void addBan(UUID uuid) {
Verify.nullCheck(uuid);
bans.add(uuid);
bans.add(Verify.nullCheck(uuid));
}
public void addActive(UUID uuid) {
Verify.nullCheck(uuid);
active.add(uuid);
active.add(Verify.nullCheck(uuid));
}
public void addInActive(UUID uuid) {
Verify.nullCheck(uuid);
inactive.add(uuid);
inactive.add(Verify.nullCheck(uuid));
}
public void addJoinedOnce(UUID uuid) {
Verify.nullCheck(uuid);
joinedOnce.add(uuid);
joinedOnce.add(Verify.nullCheck(uuid));
}
public Map<Long, Integer> getPlayersOnline() {

View File

@ -5,37 +5,47 @@
*/
package main.java.com.djrapitops.plan.data.analysis;
import main.java.com.djrapitops.plan.ui.html.tables.CommandUseTableCreator;
import main.java.com.djrapitops.plan.utilities.HtmlUtils;
import main.java.com.djrapitops.plan.utilities.html.HtmlUtils;
import main.java.com.djrapitops.plan.utilities.html.tables.CommandUseTableCreator;
import java.util.HashMap;
import java.util.Map;
/**
* Part responsible for all CommandUsage related analysis.
* <p>
* Command Usage Table.
* <p>
* Placeholder values can be retrieved using the get method.
* <p>
* Contains following place-holders: uniquecommands, totalcommands, commanduse
* Contains following placeholders after analyzed:
* ${commandCount} - (Number)
* ${commandUniqueCount} - (Number)
* ${tableBodyCommands} - Table body for CommandUsage table.
*
* @author Rsl1122
* @since 3.5.2
*/
public class CommandUsagePart extends RawData {
private final Map<String, Integer> commandUsage;
private Map<String, Integer> commandUsage;
public CommandUsagePart(Map<String, Integer> commandUsage) {
this.commandUsage = commandUsage;
public CommandUsagePart() {
this.commandUsage = new HashMap<>();
}
@Override
public void analyse() {
addValue("uniquecommands", String.valueOf(getUniqueCommands()));
addValue("totalcommands", String.valueOf(getCommandTotal()));
String commandUsageTable = CommandUseTableCreator.createSortedCommandUseTable(commandUsage);
addValue("commanduse", HtmlUtils.removeXSS(commandUsageTable));
addValue("commandUniqueCount", String.valueOf(getUniqueCommands()));
addValue("commandCount", String.valueOf(getCommandTotal()));
String commandUsageTable = CommandUseTableCreator.createTable(commandUsage);
addValue("tableBodyCommands", HtmlUtils.removeXSS(commandUsageTable));
}
public void setCommandUsage(Map<String, Integer> commandUsage) {
this.commandUsage = commandUsage;
}
public void addCommands(Map<String, Integer> commandUsage) {
this.commandUsage.putAll(commandUsage);
}
public int getUniqueCommands() {

View File

@ -1,151 +0,0 @@
package main.java.com.djrapitops.plan.data.analysis;
import com.djrapitops.plugin.utilities.Verify;
import main.java.com.djrapitops.plan.Settings;
import main.java.com.djrapitops.plan.utilities.FormatUtils;
import main.java.com.djrapitops.plan.utilities.HtmlUtils;
import java.util.Arrays;
/**
* Part responsible for all Gamemode usage related analysis.
* <p>
* Gamemode Piechart, Percentages and Totals.
* <p>
* Placeholder values can be retrieved using the get method.
* <p>
* Contains following place-holders: gmtotal, gm0col-gm3col, gmcolors, gmlabels,
* gm0-gm3, gmdata, gm0total-gm3total
*
* @author Rsl1122
* @since 3.5.2
*/
public class GamemodePart extends RawData {
private long survivalTime;
private long creativeTime;
private long adventureTime;
private long spectatorTime;
public GamemodePart() {
survivalTime = 0;
creativeTime = 0;
adventureTime = 0;
spectatorTime = 0;
}
@Override
public void analyse() {
gamemodePiechart();
}
private void gamemodePiechart() {
long totalTime = survivalTime + creativeTime + adventureTime + spectatorTime;
addValue("gmtotal", FormatUtils.formatTimeAmount(totalTime));
double[] percentages = new double[]{
(survivalTime * 100.0) / totalTime,
(creativeTime * 100.0) / totalTime,
(adventureTime * 100.0) / totalTime,
(spectatorTime * 100.0) / totalTime
};
long[] times = new long[]{
survivalTime, creativeTime, adventureTime, spectatorTime
};
String col0 = Settings.HCOLOR_GMP_0.toString();
String col1 = Settings.HCOLOR_GMP_1.toString();
String col2 = Settings.HCOLOR_GMP_2.toString();
String col3 = Settings.HCOLOR_GMP_3.toString();
addValue("%gm0col%", col0);
addValue("%gm1col%", col1);
addValue("%gm2col%", col2);
addValue("%gm3col%", col3);
String gmColors = HtmlUtils.separateWithQuotes(
"#" + col0, "#" + col1, "#" + col2, "#" + col3
);
String gmLabels = "[" + HtmlUtils.separateWithQuotes(
"Survival", "Creative", "Adventure", "Spectator") + "]";
addValue("%gmcolors%", gmColors);
addValue("%gmlabels%", gmLabels);
// Adds Percentage indicators
for (int i = 0; i < percentages.length; i++) {
addValue("gm" + i, (int) (percentages[i]) + "%");
}
// Adds Value array for graph
addValue("gmdata", Arrays.toString(times));
// Adds formatted time amounts for each gamemode
for (int i = 0; i < times.length; i++) {
addValue("gm" + i + "total", FormatUtils.formatTimeAmount(times[i]));
}
}
/**
* Adds time to a gamemode.
* @param gm Name of Gamemode
* @param amount milliseconds to add
* @throws IllegalArgumentException if gm is null
*/
public void addTo(String gm, long amount) {
Verify.nullCheck(gm);
switch (gm) {
case "SURVIVAL":
addToSurvival(amount);
break;
case "CREATIVE":
addToCreative(amount);
break;
case "ADVENTURE":
addToAdventure(amount);
break;
case "SPECTATOR":
addToSpectator(amount);
break;
default:
break;
}
}
public void addToSurvival(long amount) {
if (amount > 0) {
survivalTime += amount;
}
}
public void addToCreative(long amount) {
if (amount > 0) {
creativeTime += amount;
}
}
public void addToAdventure(long amount) {
if (amount > 0) {
adventureTime += amount;
}
}
public void addToSpectator(long amount) {
if (amount > 0) {
spectatorTime += amount;
}
}
public long getSurvivalTime() {
return survivalTime;
}
public long getCreativeTime() {
return creativeTime;
}
public long getAdventureTime() {
return adventureTime;
}
public long getSpectatorTime() {
return spectatorTime;
}
}

View File

@ -1,30 +1,35 @@
package main.java.com.djrapitops.plan.data.analysis;
import main.java.com.djrapitops.plan.ui.html.graphs.WorldMapCreator;
import main.java.com.djrapitops.plan.utilities.html.graphs.WorldMapCreator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* Part responsible for all Geolocation related analysis.
* <p>
* Player location World Choropleth map.
* <p>
* Placeholder values can be retrieved using the get method.
* <p>
* Contains following place-holders: geomapz, geomapcountries, geomapcodes
* Contains following placeholders after analyzed:
* ${geoMapSeries}
*
* @author Rsl1122
* @since 3.5.2
*/
public class GeolocationPart extends RawData {
private final Map<UUID, String> mostCommonGeolocations;
private final Map<String, String> geoCodes;
private final Map<String, Integer> geoCodeCounts;
public GeolocationPart() {
geoCodes = new HashMap<>();
geoCodeCounts = new HashMap<>();
mostCommonGeolocations = new HashMap<>();
String[] countries = new String[]{"Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra", "Angola", "Anguilla", "Antigua and Barbuda", "Argentina", "Armenia", "Aruba", "Australia", "Austria", "Azerbaijan", "Bahamas, The", "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium", "Belize", "Benin", "Bermuda", "Bhutan", "Bolivia", "Bosnia and Herzegovina", "Botswana", "Brazil", "British Virgin Islands", "Brunei", "Bulgaria", "Burkina Faso", "Burma", "Burundi", "Cabo Verde", "Cambodia", "Cameroon", "Canada", "Cayman Islands", "Central African Republic", "Chad", "Chile", "China", "Colombia", "Comoros", "Congo, Democratic Republic of the", "Congo, Republic of the", "Cook Islands", "Costa Rica", "Cote d'Ivoire", "Croatia", "Cuba", "Curacao", "Cyprus", "Czech Republic", "Denmark", "Djibouti", "Dominica", "Dominican Republic", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea", "Estonia", "Ethiopia", "Falkland Islands (Islas Malvinas)", "Faroe Islands", "Fiji", "Finland", "France", "French Polynesia", "Gabon", "Gambia, The", "Georgia", "Germany", "Ghana", "Gibraltar", "Greece", "Greenland", "Grenada", "Guam", "Guatemala", "Guernsey", "Guinea-Bissau", "Guinea", "Guyana", "Haiti", "Honduras", "Hong Kong", "Hungary", "Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Isle of Man", "Israel", "Italy", "Jamaica", "Japan", "Jersey", "Jordan", "Kazakhstan", "Kenya", "Kiribati", "Korea, North", "Korea, South", "Kosovo", "Kuwait", "Kyrgyzstan", "Laos", "Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg", "Macau", "Macedonia", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands", "Mauritania", "Mauritius", "Mexico", "Micronesia, Federated States of", "Moldova", "Monaco", "Mongolia", "Montenegro", "Morocco", "Mozambique", "Namibia", "Nepal", "Netherlands", "New Caledonia", "New Zealand", "Nicaragua", "Nigeria", "Niger", "Niue", "Northern Mariana Islands", "Norway", "Oman", "Pakistan", "Palau", "Panama", "Papua New Guinea", "Paraguay", "Peru", "Philippines", "Poland", "Portugal", "Puerto Rico", "Qatar", "Romania", "Russia", "Rwanda", "Saint Kitts and Nevis", "Saint Lucia", "Saint Martin", "Saint Pierre and Miquelon", "Saint Vincent and the Grenadines", "Samoa", "San Marino", "Sao Tome and Principe", "Saudi Arabia", "Senegal", "Serbia", "Seychelles", "Sierra Leone", "Singapore", "Sint Maarten", "Slovakia", "Slovenia", "Solomon Islands", "Somalia", "South Africa", "South Sudan", "Spain", "Sri Lanka", "Sudan", "Suriname", "Swaziland", "Sweden", "Switzerland", "Syria", "Taiwan", "Tajikistan", "Tanzania", "Thailand", "Timor-Leste", "Togo", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey", "Turkmenistan", "Tuvalu", "Uganda", "Ukraine", "United Arab Emirates", "United Kingdom", "United States", "Uruguay", "Uzbekistan", "Vanuatu", "Venezuela", "Vietnam", "Virgin Islands", "West Bank", "Yemen", "Zambia", "Zimbabwe"};
String[] codes = new String[]{"AFG", "ALB", "DZA", "ASM", "AND", "AGO", "AIA", "ATG", "ARG", "ARM", "ABW", "AUS", "AUT", "AZE", "BHM", "BHR", "BGD", "BRB", "BLR", "BEL", "BLZ", "BEN", "BMU", "BTN", "BOL", "BIH", "BWA", "BRA", "VGB", "BRN", "BGR", "BFA", "MMR", "BDI", "CPV", "KHM", "CMR", "CAN", "CYM", "CAF", "TCD", "CHL", "CHN", "COL", "COM", "COD", "COG", "COK", "CRI", "CIV", "HRV", "CUB", "CUW", "CYP", "CZE", "DNK", "DJI", "DMA", "DOM", "ECU", "EGY", "SLV", "GNQ", "ERI", "EST", "ETH", "FLK", "FRO", "FJI", "FIN", "FRA", "PYF", "GAB", "GMB", "GEO", "DEU", "GHA", "GIB", "GRC", "GRL", "GRD", "GUM", "GTM", "GGY", "GNB", "GIN", "GUY", "HTI", "HND", "HKG", "HUN", "ISL", "IND", "IDN", "IRN", "IRQ", "IRL", "IMN", "ISR", "ITA", "JAM", "JPN", "JEY", "JOR", "KAZ", "KEN", "KIR", "KOR", "PRK", "KSV", "KWT", "KGZ", "LAO", "LVA", "LBN", "LSO", "LBR", "LBY", "LIE", "LTU", "LUX", "MAC", "MKD", "MDG", "MWI", "MYS", "MDV", "MLI", "MLT", "MHL", "MRT", "MUS", "MEX", "FSM", "MDA", "MCO", "MNG", "MNE", "MAR", "MOZ", "NAM", "NPL", "NLD", "NCL", "NZL", "NIC", "NGA", "NER", "NIU", "MNP", "NOR", "OMN", "PAK", "PLW", "PAN", "PNG", "PRY", "PER", "PHL", "POL", "PRT", "PRI", "QAT", "ROU", "RUS", "RWA", "KNA", "LCA", "MAF", "SPM", "VCT", "WSM", "SMR", "STP", "SAU", "SEN", "SRB", "SYC", "SLE", "SGP", "SXM", "SVK", "SVN", "SLB", "SOM", "ZAF", "SSD", "ESP", "LKA", "SDN", "SUR", "SWZ", "SWE", "CHE", "SYR", "TWN", "TJK", "TZA", "THA", "TLS", "TGO", "TON", "TTO", "TUN", "TUR", "TKM", "TUV", "UGA", "UKR", "ARE", "GBR", "USA", "URY", "UZB", "VUT", "VEN", "VNM", "VGB", "WBG", "YEM", "ZMB", "ZWE"};
@ -39,7 +44,7 @@ public class GeolocationPart extends RawData {
@Override
public void analyse() {
addValue("geomapseries", WorldMapCreator.createDataSeries(geoCodeCounts));
addValue("geoMapSeries", WorldMapCreator.createDataSeries(geoCodeCounts));
}
public void addGeolocation(String country) {
@ -48,4 +53,31 @@ public class GeolocationPart extends RawData {
geoCodeCounts.computeIfPresent(countryCode, (computedCountry, amount) -> amount + 1);
}
}
public void addGeoLocations(Map<UUID, List<String>> geolocations) {
for (Map.Entry<UUID, List<String>> entry : geolocations.entrySet()) {
String mostCommon = getMostCommon(entry.getValue());
mostCommonGeolocations.put(entry.getKey(), mostCommon);
addGeolocation(mostCommon);
}
}
private String getMostCommon(List<String> geoLocs) {
Map<String, Long> occurrences =
geoLocs.stream().collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
String mostCommon = "Not Known";
long count = -1;
for (Map.Entry<String, Long> entry : occurrences.entrySet()) {
Long value = entry.getValue();
if (value > count) {
mostCommon = entry.getKey();
count = value;
}
}
return mostCommon;
}
public Map<UUID, String> getMostCommonGeoLocations() {
return mostCommonGeolocations;
}
}

View File

@ -2,47 +2,68 @@ package main.java.com.djrapitops.plan.data.analysis;
import com.djrapitops.plugin.api.TimeAmount;
import com.djrapitops.plugin.utilities.Verify;
import main.java.com.djrapitops.plan.data.SessionData;
import main.java.com.djrapitops.plan.data.Session;
import main.java.com.djrapitops.plan.utilities.MiscUtils;
import main.java.com.djrapitops.plan.utilities.analysis.AnalysisUtils;
import main.java.com.djrapitops.plan.utilities.html.tables.SessionsTableCreator;
import java.util.*;
import java.util.stream.Collectors;
/**
* Part responsible for all Player login related analysis.
* <p>
* Unique per Day, Unique, New Players, Logins
* Part responsible for all Player player related analysis.
* <p>
* Placeholder values can be retrieved using the get method.
* <p>
* Contains following place-holders: totallogins, uniquejoinsday,
* uniquejoinsweek, uniquejoinsmonth, avguniquejoins, avguniquejoinsday,
* avguniquejoinsweek, avguniquejoinsmonth, npday, npweek, npmonth,
* npdataday, npdataweek, npdatamonth, newperday, newperdayday, newperdayweek, newperdaymonth
* Contains following placeholders after analyzed:
* ${playersAverage} - (Number)
* ${playersNewAverage} - (Number)
* <p>
* ${playersDay} - (Number)
* ${playersWeek} - (Number)
* ${playersMonth} - (Number)
* ${playersAverageDay} - (Number)
* ${playersAverageWeek} - (Number)
* ${playersAverageMonth} - (Number)
* ${playersNewDay} - (Number)
* ${playersNewWeek} - (Number)
* ${playersNewMonth} - (Number)
* ${playersNewAverageDay} - (Number)
* ${playersNewAverageWeek} - (Number)
* ${playersNewAverageMonth} - (Number)
*
* @author Rsl1122
* @since 3.5.2
*/
public class JoinInfoPart extends RawData {
private final Map<UUID, List<SessionData>> sessions;
private final List<Long> registered;
private final Map<UUID, Session> activeSessions;
private final Map<UUID, List<Session>> sessions;
private final Map<UUID, Long> registered;
private long loginTimes;
public JoinInfoPart() {
activeSessions = new HashMap<>();
sessions = new HashMap<>();
registered = new ArrayList<>();
registered = new HashMap<>();
loginTimes = 0;
}
@Override
public void analyse() {
addValue("totallogins", loginTimes);
newPlayers();
uniquePlayers();
uniquePlayersPerDay();
addValue("sessionCount", getAllSessions().size());
sessionTables();
}
private void sessionTables() {
String[] tables = SessionsTableCreator.createTables(this);
addValue("tableBodySessions", tables[0]);
addValue("tableBodyRecentLogins", tables[1]);
}
private void uniquePlayers() {
@ -50,9 +71,9 @@ public class JoinInfoPart extends RawData {
int uniqueWeek = AnalysisUtils.getUniqueJoins(sessions, TimeAmount.WEEK.ms());
int uniqueMonth = AnalysisUtils.getUniqueJoins(sessions, TimeAmount.MONTH.ms());
addValue("uniquejoinsday", uniqueDay);
addValue("uniquejoinsweek", uniqueWeek);
addValue("uniquejoinsmonth", uniqueMonth);
addValue("playersDay", uniqueDay);
addValue("playersWeek", uniqueWeek);
addValue("playersMonth", uniqueMonth);
}
private void uniquePlayersPerDay() {
@ -61,31 +82,32 @@ public class JoinInfoPart extends RawData {
int perDayWeek = AnalysisUtils.getUniqueJoinsPerDay(sessions, TimeAmount.WEEK.ms());
int perDayMonth = AnalysisUtils.getUniqueJoinsPerDay(sessions, TimeAmount.MONTH.ms());
addValue("avguniquejoins", perDay);
addValue("avguniquejoinsday", perDayDay);
addValue("avguniquejoinsweek", perDayWeek);
addValue("avguniquejoinsmonth", perDayMonth);
addValue("playersAverage", perDay);
addValue("playersAverageDay", perDayDay);
addValue("playersAverageWeek", perDayWeek);
addValue("playersAverageMonth", perDayMonth);
}
private void newPlayers() {
long now = MiscUtils.getTime();
long newDay = AnalysisUtils.getNewPlayers(registered, TimeAmount.DAY.ms(), now);
long newWeek = AnalysisUtils.getNewPlayers(registered, TimeAmount.WEEK.ms(), now);
long newMonth = AnalysisUtils.getNewPlayers(registered, TimeAmount.MONTH.ms(), now);
List<Long> registeredList = getRegisteredList();
long newDay = AnalysisUtils.getNewPlayers(registeredList, TimeAmount.DAY.ms(), now);
long newWeek = AnalysisUtils.getNewPlayers(registeredList, TimeAmount.WEEK.ms(), now);
long newMonth = AnalysisUtils.getNewPlayers(registeredList, TimeAmount.MONTH.ms(), now);
addValue("npday", newDay);
addValue("npweek", newWeek);
addValue("npmonth", newMonth);
addValue("playersNewDay", newDay);
addValue("playersNewWeek", newWeek);
addValue("playersNewMonth", newMonth);
long newPerDay = AnalysisUtils.getNewUsersPerDay(registered, -1);
long newPerDayDay = AnalysisUtils.getNewUsersPerDay(registered, TimeAmount.DAY.ms());
long newPerDayWeek = AnalysisUtils.getNewUsersPerDay(registered, TimeAmount.WEEK.ms());
long newPerDayMonth = AnalysisUtils.getNewUsersPerDay(registered, TimeAmount.MONTH.ms());
long newPerDay = AnalysisUtils.getNewUsersPerDay(registeredList, -1);
long newPerDayDay = AnalysisUtils.getNewUsersPerDay(registeredList, TimeAmount.DAY.ms());
long newPerDayWeek = AnalysisUtils.getNewUsersPerDay(registeredList, TimeAmount.WEEK.ms());
long newPerDayMonth = AnalysisUtils.getNewUsersPerDay(registeredList, TimeAmount.MONTH.ms());
addValue("newperday", newPerDay);
addValue("newperdayday", newPerDayDay);
addValue("newperdayweek", newPerDayWeek);
addValue("newperdaymonth", newPerDayMonth);
addValue("playersNewAverage", newPerDay);
addValue("playersNewAverageDay", newPerDayDay);
addValue("playersNewAverageWeek", newPerDayWeek);
addValue("playersNewAverageMonth", newPerDayMonth);
}
public void addToLoginTimes() {
@ -100,25 +122,43 @@ public class JoinInfoPart extends RawData {
return loginTimes;
}
public Map<UUID, List<SessionData>> getSessions() {
public Map<UUID, List<Session>> getSessions() {
return sessions;
}
public List<SessionData> getAllSessions() {
return MiscUtils.flatMap(sessions.values());
public List<Session> getAllSessions() {
List<Session> sessions = MiscUtils.flatMap(this.sessions.values());
sessions.addAll(activeSessions.values());
return sessions;
}
public void addRegistered(long registerDate) {
registered.add(registerDate);
public void addRegistered(UUID uuid, long registerDate) {
registered.put(uuid, registerDate);
}
public List<Long> getRegistered() {
public void addRegistered(Map<UUID, Long> registerDates) {
registered.putAll(registerDates);
}
public Map<UUID, Long> getRegistered() {
return registered;
}
public void addSessions(UUID uuid, List<SessionData> sessions) {
public List<Long> getRegisteredList() {
return new ArrayList<>(registered.values());
}
public void addSessions(Map<UUID, List<Session>> sessions) {
this.sessions.putAll(Verify.nullCheck(sessions));
}
public void addSessions(UUID uuid, List<Session> sessions) {
Verify.nullCheck(uuid);
Verify.nullCheck(sessions);
this.sessions.put(uuid, sessions.stream().distinct().collect(Collectors.toList()));
}
public void addActiveSessions(Map<UUID, Session> activeSessions) {
this.activeSessions.putAll(activeSessions);
}
}

View File

@ -1,11 +1,9 @@
package main.java.com.djrapitops.plan.data.analysis;
import com.djrapitops.plugin.utilities.Verify;
import main.java.com.djrapitops.plan.data.KillData;
import main.java.com.djrapitops.plan.utilities.MiscUtils;
import main.java.com.djrapitops.plan.utilities.analysis.MathUtils;
import main.java.com.djrapitops.plan.data.PlayerKill;
import main.java.com.djrapitops.plan.data.Session;
import java.util.HashMap;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@ -13,69 +11,48 @@ import java.util.UUID;
/**
* Part responsible for all Death related analysis.
* <p>
* Totals
* <p>
* Placeholder values can be retrieved using the get method.
* <p>
* Contains following place-holders: deaths, mobkills, playerkills, avgdeaths, avgmobkills, avgplayerkills
* Contains following placeholders after analyzed:
* ${killCount} - (Number)
* ${mobKillCount} - (Number)
* ${deathCount} - (Number)
*
* @author Rsl1122
* @since 3.5.2
*/
public class KillPart extends RawData {
private final PlayerCountPart playerCountPart;
private final Map<UUID, List<KillData>> playerKills;
private final JoinInfoPart joinInfoPart;
private long playerKills;
private long mobKills;
private long deaths;
public KillPart(PlayerCountPart playerCountPart) {
this.playerCountPart = playerCountPart;
playerKills = new HashMap<>();
public KillPart(JoinInfoPart joinInfoPart) {
this.joinInfoPart = joinInfoPart;
playerKills = 0;
mobKills = 0;
deaths = 0;
}
@Override
public void analyse() {
addValue("deaths", deaths);
addValue("mobkills", mobKills);
int playerKillAmount = getAllPlayerKills().size();
addValue("playerkills", playerKillAmount);
int playerCount = playerCountPart.getPlayerCount();
addValue("avgdeaths", MathUtils.averageLong(deaths, playerCount));
addValue("avgmobkills", MathUtils.averageLong(mobKills, playerCount));
addValue("avgplayerkills", MathUtils.averageLong(playerKillAmount, playerCount));
List<Session> sessions = joinInfoPart.getAllSessions();
deaths += sessions.stream().mapToLong(Session::getDeaths).sum();
mobKills += sessions.stream().mapToLong(Session::getMobKills).sum();
playerKills += sessions.stream().map(Session::getPlayerKills).mapToLong(Collection::size).sum();
addValue("deathCount", this.deaths);
addValue("mobKillCount", mobKills);
addValue("killCount", playerKills);
}
/**
* Adds kills to the dataset.
*
* @param uuid Player whose kills are being added
* @param kills all kills of a player
* @throws IllegalArgumentException if kills is null
*/
public void addKills(UUID uuid, List<KillData> kills) {
Verify.nullCheck(kills);
playerKills.put(uuid, kills);
}
public void addMobKills(long amount) {
mobKills += amount;
}
public void addDeaths(long amount) {
deaths += amount;
}
public Map<UUID, List<KillData>> getPlayerKills() {
public long getPlayerKills() {
return playerKills;
}
public List<KillData> getAllPlayerKills() {
return MiscUtils.flatMap(playerKills.values());
}
public long getMobKills() {
return mobKills;
}
@ -83,4 +60,8 @@ public class KillPart extends RawData {
public long getDeaths() {
return deaths;
}
public void addKills(Map<UUID, List<PlayerKill>> playerKills) {
this.playerKills += playerKills.values().stream().mapToLong(Collection::size).sum();
}
}

View File

@ -10,11 +10,10 @@ import java.util.UUID;
/**
* Part responsible for counting players.
* <p>
* Total player count, op count
* <p>
* Placeholder values can be retrieved using the get method.
* <p>
* Contains following place-holders: activitytotal, ops
* Contains following placeholders after analyzed:
* ${playersTotal}, ${ops}
*
* @author Rsl1122
* @since 3.5.2
@ -31,8 +30,8 @@ public class PlayerCountPart extends RawData {
@Override
public void analyse() {
addValue("activitytotal", uuids.size());
addValue("ops", ops.size());
addValue("playersTotal", uuids.size());
}
public void addPlayer(UUID uuid) {
@ -45,6 +44,11 @@ public class PlayerCountPart extends RawData {
this.uuids.addAll(uuids);
}
public void addOPs(Collection<UUID> uuids) {
Verify.nullCheck(uuids);
this.ops.addAll(uuids);
}
public void addOP(UUID uuid) {
Verify.nullCheck(uuid);
ops.add(uuid);

View File

@ -1,36 +1,54 @@
package main.java.com.djrapitops.plan.data.analysis;
import main.java.com.djrapitops.plan.utilities.FormatUtils;
import main.java.com.djrapitops.plan.utilities.analysis.MathUtils;
/**
* Part responsible for all Playtime related analysis.
* <p>
* Placeholder values can be retrieved using the get method.
* <p>
* Contains following place-holders: totalplaytime, avgplaytime
* Contains following placeholders after analyzed:
* ${playtimeTotal} - Formatted time amount
*
* @author Rsl1122
* @since 3.5.2
*/
public class PlaytimePart extends RawData {
private final PlayerCountPart playerCount;
private long totalPlaytime;
private long playtime30d;
private long playtime7d;
private long playtime24h;
public PlaytimePart(PlayerCountPart part) {
playerCount = part;
public PlaytimePart() {
totalPlaytime = 0;
}
@Override
public void analyse() {
addValue("totalplaytime", FormatUtils.formatTimeAmount(totalPlaytime));
final long averagePlaytime = MathUtils.averageLong(totalPlaytime, playerCount.getPlayerCount());
addValue("avgplaytime", FormatUtils.formatTimeAmount(averagePlaytime));
addValue("playtimeTotal", FormatUtils.formatTimeAmount(totalPlaytime));
addValue("playtimeMonth", FormatUtils.formatTimeAmount(playtime30d));
addValue("playtimeWeek", FormatUtils.formatTimeAmount(playtime7d));
addValue("playtimeDay", FormatUtils.formatTimeAmount(playtime24h));
}
public void addToPlaytime(long amount) {
totalPlaytime += amount;
}
public void setTotalPlaytime(long totalPlaytime) {
this.totalPlaytime = totalPlaytime;
}
public void setPlaytime30d(long playtime30d) {
this.playtime30d = playtime30d;
}
public void setPlaytime7d(long playtime7d) {
this.playtime7d = playtime7d;
}
public void setPlaytime24h(long playtime24h) {
this.playtime24h = playtime24h;
}
}

View File

@ -14,7 +14,7 @@ import java.util.Map;
*/
public abstract class RawData {
private final Map<String, String> replaceMap;
private final Map<String, Serializable> replaceMap;
/**
* Status info for call to analyzeData method.
@ -60,7 +60,7 @@ public abstract class RawData {
*
* @param values Map that contains place-holders.
*/
public void addValues(Map<String, String> values) {
public void addValues(Map<String, Serializable> values) {
Verify.nullCheck(values);
replaceMap.putAll(values);
}
@ -68,28 +68,11 @@ public abstract class RawData {
/**
* Adds a placeholder to the replaceMap.
*
* @param placeholder placeholder, with or without % signs.
* @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(addPlaceholderSigns(placeholder), value.toString());
}
private String addPlaceholderSigns(String placeholder) {
StringBuilder newPlaceholder = new StringBuilder();
if (placeholder.charAt(0) != '%') {
newPlaceholder.append("%");
}
newPlaceholder.append(placeholder);
int lastIndex = placeholder.length() - 1;
if (placeholder.charAt(lastIndex) != '%') {
newPlaceholder.append("%");
}
return newPlaceholder.toString();
replaceMap.put(placeholder, value);
}
/**
@ -97,17 +80,17 @@ public abstract class RawData {
*
* @return Map containing the placeholders and values.
*/
public Map<String, String> getReplaceMap() {
public Map<String, Serializable> getReplaceMap() {
return replaceMap;
}
/**
* Used to get the value for a placeholder with or without the % symbols.
* Used to get the value for a placeholder without the placeholder prefix and suffix.
*
* @param key placeholder with or without % symbols.
* @param key placeholder name without ${ and }
* @return Value the placeholder should be replaced with or null.
*/
public String get(String key) {
return replaceMap.get(addPlaceholderSigns(key));
public Serializable get(String key) {
return replaceMap.get(key);
}
}

View File

@ -1,28 +1,50 @@
package main.java.com.djrapitops.plan.data.analysis;
import com.djrapitops.plugin.api.TimeAmount;
import com.djrapitops.plugin.utilities.Verify;
import main.java.com.djrapitops.plan.Settings;
import main.java.com.djrapitops.plan.data.TPS;
import main.java.com.djrapitops.plan.ui.html.graphs.CPUGraphCreator;
import main.java.com.djrapitops.plan.ui.html.graphs.RamGraphCreator;
import main.java.com.djrapitops.plan.ui.html.graphs.TPSGraphCreator;
import main.java.com.djrapitops.plan.ui.html.graphs.WorldLoadGraphCreator;
import main.java.com.djrapitops.plan.systems.webserver.theme.Colors;
import main.java.com.djrapitops.plan.utilities.FormatUtils;
import main.java.com.djrapitops.plan.utilities.MiscUtils;
import main.java.com.djrapitops.plan.utilities.analysis.MathUtils;
import main.java.com.djrapitops.plan.utilities.html.graphs.CPUGraphCreator;
import main.java.com.djrapitops.plan.utilities.html.graphs.RamGraphCreator;
import main.java.com.djrapitops.plan.utilities.html.graphs.TPSGraphCreator;
import main.java.com.djrapitops.plan.utilities.html.graphs.WorldLoadGraphCreator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* Part responsible for all TPS related analysis.
* <p>
* Ticks Per Second Graphs
* <p>
* Placeholder values can be retrieved using the get method.
* <p>
* Contains following place-holders: tpsscatterday, tpsscatterweek, cpuscatterday, cpuscatterweek, averagetps(-week),
* averagetpsday, averagecpuday, averagecpuweek, averagememoryday, averagememoryweek, averageentitiesday, averageentitiesweek,
* averagechunksday, averagechunkweek, ramscatterday, ramscatterweek
* Contains following placeholders after being analyzed:
* ${tpsSeries} - HighCharts data
* ${cpuSeries} - HighCharts data
* ${ramSeries} - HighCharts data
* ${entitySeries} - HighCharts data
* ${chunkSeries} - HighCharts data
* <p>
* ${tpsAverageDay} - (Number)
* ${tpsAverageWeek} - (Number)
* ${cpuAverageDay} - (Number)%
* ${cpuAverageWeek} - (Number)%
* ${ramAverageDay} - (Number) MB
* ${ramAverageWeek} - (Number) MB
* ${entityAverageDay} - (Number)
* ${entityAverageWeek} - (Number)
* ${chunkAverageDay} - (Number)
* ${chunkAverageWeek} - (Number)
* <p>
* ${tpsMedium} - (Number) Color Threshold for Medium TPS
* ${tpsHigh} - (Number) Color Threshold for High TPS
* ${tpsLowColor} - Color of Low TPS
* ${tpsMediumColor} - Color of Low TPS
* ${tpsHighColor} - Color of Low TPS
*
* @author Rsl1122
* @since 3.5.2
@ -30,9 +52,11 @@ import java.util.List;
public class TPSPart extends RawData {
private final List<TPS> tpsData;
private TPS allTimePeak;
private TPS lastPeak;
public TPSPart(List<TPS> tpsData) {
this.tpsData = tpsData;
public TPSPart() {
this.tpsData = new ArrayList<>();
}
@Override
@ -41,18 +65,34 @@ public class TPSPart extends RawData {
List<TPS> week = TPSGraphCreator.filterTPS(tpsData, now - TimeAmount.WEEK.ms());
List<TPS> day = TPSGraphCreator.filterTPS(tpsData, now - TimeAmount.DAY.ms());
addValue("tpshighcol", "#"+ Settings.HCOLOR_TPS_HIGH);
addValue("tpsmediumcol", "#"+ Settings.HCOLOR_TPS_MED);
addValue("tpslowcol", "#"+ Settings.HCOLOR_TPS_LOW);
addValue("tpsmedium", Settings.TPS_GRAPH_MED.getNumber());
addValue("tpshigh", Settings.TPS_GRAPH_HIGH.getNumber());
tpsGraphOptions();
addValue("tpsseries", TPSGraphCreator.buildSeriesDataString(tpsData));
addValue("cpuseries", CPUGraphCreator.buildSeriesDataString(tpsData));
addValue("ramseries", RamGraphCreator.buildSeriesDataString(tpsData));
addValue("entityseries", WorldLoadGraphCreator.buildSeriesDataStringEntities(tpsData));
addValue("chunkseries", WorldLoadGraphCreator.buildSeriesDataStringChunks(tpsData));
chartData();
averages(week, day);
peaks();
}
private void peaks() {
if (lastPeak != null) {
addValue("lastPeakTime", FormatUtils.formatTimeStampYear(lastPeak.getDate()));
addValue("playersLastPeak", lastPeak.getPlayers());
} else {
addValue("lastPeakTime", "No Data");
addValue("playersLastPeak", "-");
}
if (allTimePeak != null) {
addValue("bestPeakTime", FormatUtils.formatTimeStampYear(allTimePeak.getDate()));
addValue("playersBestPeak", allTimePeak.getPlayers());
} else {
addValue("bestPeakTime", "No Data");
addValue("playersBestPeak", "-");
}
}
private void averages(List<TPS> week, List<TPS> day) {
double averageTPSWeek = MathUtils.averageDouble(week.stream().map(TPS::getTicksPerSecond));
double averageTPSDay = MathUtils.averageDouble(day.stream().map(TPS::getTicksPerSecond));
@ -68,24 +108,51 @@ public class TPSPart extends RawData {
double averageChunksLoadedWeek = MathUtils.averageInt(week.stream().map(TPS::getChunksLoaded).filter(i -> i != 0));
double averageChunksLoadedDay = MathUtils.averageInt(day.stream().map(TPS::getChunksLoaded).filter(i -> i != 0));
addValue("averagetps", FormatUtils.cutDecimals(averageTPSWeek)); //Staying for backwards compatibility
addValue("averagetpsweek", FormatUtils.cutDecimals(averageTPSWeek));
addValue("averagetpsday", FormatUtils.cutDecimals(averageTPSDay));
addValue("tpsAverageWeek", FormatUtils.cutDecimals(averageTPSWeek));
addValue("tpsAverageDay", FormatUtils.cutDecimals(averageTPSDay));
addValue("averagecpuweek", averageCPUWeek >= 0 ? FormatUtils.cutDecimals(averageCPUWeek) + "%" : "Unavailable");
addValue("averagecpuday", averageCPUDay >= 0 ? FormatUtils.cutDecimals(averageCPUDay) + "%" : "Unavailable");
addValue("cpuAverageWeek", averageCPUWeek >= 0 ? FormatUtils.cutDecimals(averageCPUWeek) + "%" : "Unavailable");
addValue("cpuAverageDay", averageCPUDay >= 0 ? FormatUtils.cutDecimals(averageCPUDay) + "%" : "Unavailable");
addValue("averagememoryweek", FormatUtils.cutDecimals(averageUsedMemoryWeek));
addValue("averagememoryday", FormatUtils.cutDecimals(averageUsedMemoryDay));
addValue("ramAverageWeek", FormatUtils.cutDecimals(averageUsedMemoryWeek));
addValue("ramAverageDay", FormatUtils.cutDecimals(averageUsedMemoryDay));
addValue("averageentitiesweek", FormatUtils.cutDecimals(averageEntityCountWeek));
addValue("averageentitiesday", FormatUtils.cutDecimals(averageEntityCountDay));
addValue("entityAverageWeek", FormatUtils.cutDecimals(averageEntityCountWeek));
addValue("entityAverageDay", FormatUtils.cutDecimals(averageEntityCountDay));
addValue("averagechunksweek", FormatUtils.cutDecimals(averageChunksLoadedWeek));
addValue("averagechunksday", FormatUtils.cutDecimals(averageChunksLoadedDay));
addValue("chunkAverageWeek", FormatUtils.cutDecimals(averageChunksLoadedWeek));
addValue("chunkAverageDay", FormatUtils.cutDecimals(averageChunksLoadedDay));
}
private void chartData() {
addValue("tpsSeries", TPSGraphCreator.buildSeriesDataString(tpsData));
addValue("cpuSeries", CPUGraphCreator.buildSeriesDataString(tpsData));
addValue("ramSeries", RamGraphCreator.buildSeriesDataString(tpsData));
addValue("entitySeries", WorldLoadGraphCreator.buildSeriesDataStringEntities(tpsData));
addValue("chunkSeries", WorldLoadGraphCreator.buildSeriesDataStringChunks(tpsData));
}
private void tpsGraphOptions() {
addValue("tpsHighColor", Colors.TPS_HIGH.getColor());
addValue("tpsMediumColor", Colors.TPS_MED.getColor());
addValue("tpsLowColor", Colors.TPS_LOW.getColor());
addValue("tpsMedium", Settings.THEME_GRAPH_TPS_THRESHOLD_MED.getNumber());
addValue("tpsHigh", Settings.THEME_GRAPH_TPS_THRESHOLD_HIGH.getNumber());
}
public List<TPS> getTpsData() {
return tpsData;
}
public void addTpsData(Collection<TPS> data) {
tpsData.addAll(Verify.nullCheck(data));
}
public void setAllTimePeak(TPS allTimePeak) {
this.allTimePeak = allTimePeak;
}
public void setLastPeak(TPS lastPeak) {
this.lastPeak = lastPeak;
}
}

View File

@ -1,11 +1,11 @@
package main.java.com.djrapitops.plan.data.analysis;
import main.java.com.djrapitops.plan.Settings;
import main.java.com.djrapitops.plan.data.time.WorldTimes;
import main.java.com.djrapitops.plan.ui.html.graphs.WorldPieCreator;
import main.java.com.djrapitops.plan.utilities.FormatUtils;
import main.java.com.djrapitops.plan.utilities.html.graphs.WorldPieCreator;
import java.util.HashMap;
import java.util.Map;
/**
* Part responsible for all World Playtime related analysis.
@ -14,28 +14,36 @@ import java.util.Map;
* <p>
* Placeholder values can be retrieved using the get method.
* <p>
* Contains following place-holders: worldtotal, worldseries
* Contains following placeholders after analyzed:
* ${worldTotal} - Total playtime for all worlds
* ${worldSeries} - Data for HighCharts
*
* @author Rsl1122
* @since 3.6.0
*/
public class WorldPart extends RawData {
private final Map<String, Long> worldTimes;
private WorldTimes worldTimes;
public WorldPart() {
worldTimes = new HashMap<>();
worldTimes = new WorldTimes(new HashMap<>());
}
@Override
protected void analyse() {
WorldTimes t = new WorldTimes(worldTimes);
addValue("worldtotal", FormatUtils.formatTimeAmount(t.getTotal()));
addValue("worldseries", WorldPieCreator.createSeriesData(worldTimes));
addValue("worldTotal", FormatUtils.formatTimeAmount(worldTimes.getTotal()));
String[] seriesData = WorldPieCreator.createSeriesData(worldTimes);
addValue("worldSeries", seriesData[0]);
addValue("gmSeries", seriesData[1]);
addValue("worldPieColors", Settings.THEME_GRAPH_WORLD_PIE.toString());
addValue("gmPieColors", Settings.THEME_GRAPH_GM_PIE.toString());
}
public void addToWorld(String worldName, long playTime) {
Long value = worldTimes.getOrDefault(worldName, 0L);
worldTimes.put(worldName, value + playTime);
public WorldTimes getWorldTimes() {
return worldTimes;
}
public void setWorldTimes(WorldTimes worldTimes) {
this.worldTimes = worldTimes;
}
}

View File

@ -1,138 +0,0 @@
package main.java.com.djrapitops.plan.data.cache;
import com.djrapitops.plugin.command.CommandUtils;
import com.djrapitops.plugin.command.ISender;
import com.djrapitops.plugin.utilities.player.IPlayer;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.Settings;
import main.java.com.djrapitops.plan.data.AnalysisData;
import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg;
import main.java.com.djrapitops.plan.ui.text.TextUI;
import main.java.com.djrapitops.plan.utilities.HtmlUtils;
import main.java.com.djrapitops.plan.utilities.analysis.Analysis;
import org.bukkit.entity.Player;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
/**
* This class is used to store the most recent AnalysisData object and to run
* Analysis.
*
* @author Rsl1122
* @since 2.0.0
*/
public class AnalysisCacheHandler {
private final Plan plugin;
private final Analysis analysis;
private AnalysisData cache;
private boolean analysisEnabled;
private Set<UUID> notifyWhenCached;
/**
* Class Constructor.
* <p>
* Initializes Analysis
*
* @param plugin Current instance of Plan
*/
public AnalysisCacheHandler(Plan plugin) {
this.plugin = plugin;
analysis = new Analysis(plugin);
analysisEnabled = true;
notifyWhenCached = new HashSet<>();
}
/**
* Runs analysis, cache method is called after analysis is complete.
*/
public void updateCache() {
analysis.runAnalysis(this);
}
/**
* Saves the new analysis data to cache.
*
* @param data AnalysisData generated by Analysis.analyze
*/
public void cache(AnalysisData data) {
cache = data;
for (UUID uuid : notifyWhenCached) {
Optional<IPlayer> player = plugin.fetch().getPlayer(uuid);
if (player.isPresent()) {
sendAnalysisMessage(player.get());
}
}
notifyWhenCached.clear();
}
public void sendAnalysisMessage(ISender sender) {
boolean textUI = Settings.USE_ALTERNATIVE_UI.isTrue();
sender.sendMessage(Locale.get(Msg.CMD_HEADER_ANALYZE).toString());
if (textUI) {
sender.sendMessage(TextUI.getAnalysisMessages());
} else {
// Link
String url = HtmlUtils.getServerAnalysisUrlWithProtocol();
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());
}
/**
* Returns the cached AnalysisData.
*
* @return null if not cached
*/
public AnalysisData getData() {
return cache;
}
/**
* Check if the AnalysisData has been cached.
*
* @return true if there is data in the cache.
*/
public boolean isCached() {
return cache != null;
}
/**
* @return if currently an analysis is being run
*/
public boolean isAnalysisBeingRun() {
return analysis.isAnalysisBeingRun();
}
public boolean isAnalysisEnabled() {
return analysisEnabled;
}
public void disableAnalysisTemporarily() {
analysisEnabled = false;
analysis.setTaskId(-2);
}
public void enableAnalysis() {
analysis.setTaskId(-1);
analysisEnabled = true;
}
public void addNotification(ISender sender) {
if (CommandUtils.isPlayer(sender)) {
notifyWhenCached.add(((Player) sender.getSender()).getUniqueId());
}
}
}

View File

@ -1,25 +0,0 @@
package main.java.com.djrapitops.plan.data.cache;
import main.java.com.djrapitops.plan.data.UserData;
/**
* This interface can be extended with anything as the process method and
* given to the Database.
* <p>
* The process method will be called with the UserData object fetched from the
* database.
*
* @author Rsl1122
* @since 2.6.0
*/
public interface DBCallableProcessor {
/**
* Method used to do multiple things to UserData objects such as Caching,
* changing properties etc.
*
* @param data UserData object given to the DBCallableProcessor by the
* method it was given as parameter to.
*/
void process(UserData data);
}

View File

@ -1,550 +0,0 @@
package main.java.com.djrapitops.plan.data.cache;
import com.djrapitops.plugin.task.AbsRunnable;
import com.djrapitops.plugin.utilities.player.IPlayer;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.Settings;
import main.java.com.djrapitops.plan.data.TPS;
import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.data.cache.queue.DataCacheClearQueue;
import main.java.com.djrapitops.plan.data.cache.queue.DataCacheGetQueue;
import main.java.com.djrapitops.plan.data.cache.queue.DataCacheProcessQueue;
import main.java.com.djrapitops.plan.data.cache.queue.DataCacheSaveQueue;
import main.java.com.djrapitops.plan.data.handling.info.HandlingInfo;
import main.java.com.djrapitops.plan.data.handling.info.LogoutInfo;
import main.java.com.djrapitops.plan.data.handling.info.ReloadInfo;
import main.java.com.djrapitops.plan.database.Database;
import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg;
import main.java.com.djrapitops.plan.utilities.Benchmark;
import main.java.com.djrapitops.plan.utilities.MiscUtils;
import main.java.com.djrapitops.plan.utilities.NewPlayerCreator;
import main.java.com.djrapitops.plan.utilities.analysis.MathUtils;
import main.java.com.djrapitops.plan.utilities.comparators.HandlingInfoTimeComparator;
import org.bukkit.entity.Player;
import java.sql.SQLException;
import java.util.*;
/**
* This Class contains the Cache.
* <p>
* This class is the main processing class that initialises Save, Clear, Process
* and Get queue and Starts the asynchronous save task.
* <p>
* It is used to store command use, locations, active sessions and UserData
* objects in memory.
* <p>
* Its methods can be used to access all the data it stores and to clear them.
*
* @author Rsl1122
* @since 2.0.0
*/
public class DataCacheHandler extends SessionCache {
// Cache
private final Map<UUID, UserData> dataCache;
// Plan
private final Plan plugin;
private final Database db;
//Cache
private Map<String, Integer> commandUse;
private List<List<TPS>> unsavedTPSHistory;
// Queues
private DataCacheSaveQueue saveTask;
private DataCacheClearQueue clearTask;
private DataCacheProcessQueue processTask;
private DataCacheGetQueue getTask;
// Variables
private boolean periodicTaskIsSaving = false;
/**
* Class Constructor.
* <p>
* Gets the Database from the plugin. Starts the queues. Registers
* Asynchronous Periodic Save Task
*
* @param plugin Current instance of Plan
*/
public DataCacheHandler(Plan plugin) {
super(); // Initializes Session & Location cache.
this.plugin = plugin;
db = plugin.getDB();
dataCache = new HashMap<>();
startQueues();
commandUse = new HashMap<>();
if (!getCommandUseFromDb()) {
Log.error(Locale.get(Msg.ENABLE_DB_FAIL_DISABLE_INFO).toString());
plugin.disablePlugin();
return;
}
unsavedTPSHistory = new ArrayList<>();
startAsyncPeriodicSaveTask();
}
/**
* Used to get the initial commandUse Map from the database.
*
* @return Was the fetch successful?
*/
public boolean getCommandUseFromDb() {
try {
commandUse = db.getCommandUse();
return true;
} catch (Exception e) {
Log.toLog(this.getClass().getName(), e);
}
return false;
}
/**
* Used to start all processing Queue Threads.
*/
public void startQueues() {
getTask = new DataCacheGetQueue(plugin);
processTask = new DataCacheProcessQueue(this);
clearTask = new DataCacheClearQueue(this);
saveTask = new DataCacheSaveQueue(plugin, this);
}
/**
* Used to start the Asynchronous Save Task.
*
* @throws IllegalArgumentException BukkitRunnable was given wrong
* parameters.
* @throws IllegalStateException BukkitScheduler is in a wrong state.
*/
public void startAsyncPeriodicSaveTask() {
int minutes = Settings.SAVE_CACHE_MIN.getNumber();
if (minutes <= 0) {
minutes = 5;
}
final int clearAfterXsaves;
int configValue = Settings.CLEAR_CACHE_X_SAVES.getNumber();
if (configValue <= 1) {
clearAfterXsaves = 2;
} else {
clearAfterXsaves = configValue;
}
DataCacheHandler handler = this;
plugin.getRunnableFactory().createNew(new AbsRunnable("PeriodicCacheSaveTask") {
private int timesSaved = 0;
@Override
public void run() {
if (periodicTaskIsSaving) {
return;
}
try {
periodicTaskIsSaving = true;
Log.debug("Database", "Periodic Cache Save: " + dataCache.size());
handler.saveHandlerDataToCache();
handler.saveCachedUserData();
if (timesSaved % clearAfterXsaves == 0) {
handler.clearCache();
}
saveCommandUse();
saveUnsavedTPSHistory();
timesSaved++;
} catch (Exception e) {
Log.toLog(this.getClass().getName() + "(" + this.getName() + ")", e);
} finally {
periodicTaskIsSaving = false;
}
}
}).runTaskTimerAsynchronously(60L * 20L * minutes, 60L * 20L * minutes);
}
/**
* Uses Database or Cache to retrieve the UserData of a matching player.
* <p>
* Caches the data to the Cache if cache-parameter is true.
*
* @param processor DBCallableProcessor Object used to process the data
* after it was retrieved
* @param uuid Player's UUID
* @param cache Whether or not the UserData will be Cached in this instance
* of DataCacheHandler after it has been fetched (if not already fetched)
*/
public void getUserDataForProcessing(DBCallableProcessor processor, UUID uuid, boolean cache) {
UserData uData = dataCache.get(uuid);
if (uData == null) {
if (cache) {
DBCallableProcessor cacher = this::cache;
getTask.scheduleForGet(uuid, cacher, processor);
} else {
getTask.scheduleForGet(uuid, processor);
}
} else {
processor.process(uData);
}
}
/**
* Used to Cache a UserData object to the Cache.
* <p>
* If a object already exists it will be replaced.
*
* @param data UserData object with the UUID inside used as key.
*/
public void cache(UserData data) {
data.setOnline(true);
dataCache.put(data.getUuid(), data);
Log.debug("Added " + data.getUuid().toString() + " to Cache.");
}
/**
* Uses Database or Cache to retrieve the UserData of a matching player.
* <p>
* Always Caches the data after retrieval (unless already cached)
*
* @param processor DBCallableProcessor Object used to process the data
* after it was retrieved
* @param uuid Player's UUID
*/
public void getUserDataForProcessing(DBCallableProcessor processor, UUID uuid) {
getUserDataForProcessing(processor, uuid, true);
}
/**
* Saves all UserData in the cache to Database.
* <p>
* Should only be called from Async thread
*/
public void saveCachedUserData() {
Set<UserData> data = new HashSet<>();
data.addAll(dataCache.values());
try {
db.saveMultipleUserData(data);
} catch (SQLException ex) {
Log.toLog(this.getClass().getName(), ex);
}
}
/**
* Used to add event HandlingInfo to the processTask's pool.
* <p>
* Given HandlingInfo object's process method will be called.
*
* @param i Object that extends HandlingInfo.
*/
public void addToPool(HandlingInfo i) {
if (i == null) {
return;
}
processTask.addToPool(i);
}
/**
* Saves all data in the cache to Database and closes the database down.
* <p>
* Stops all tasks.
* <p>
* If processTask has unprocessed information, it will be processed.
*/
public void saveCacheOnDisable() {
long time = MiscUtils.getTime();
Benchmark.start("Cache: SaveOnDisable");
saveTask.stop();
getTask.stop();
clearTask.stop();
List<HandlingInfo> toProcess = processTask.stopAndReturnLeftovers();
Benchmark.start("Cache: ProcessOnlineHandlingInfo");
Log.debug("ToProcess size: " + toProcess.size() + " DataCache size: " + dataCache.keySet().size());
List<IPlayer> onlinePlayers = plugin.fetch().getOnlinePlayers();
Log.debug("Online: " + onlinePlayers.size());
for (IPlayer p : onlinePlayers) {
UUID uuid = p.getUuid();
endSession(uuid);
String worldName = ((Player) p.getWrappedPlayerClass()).getWorld().getName();
toProcess.add(new LogoutInfo(uuid, time, p.isBanned(), p.getGamemode().name(), getSession(uuid), worldName));
}
Log.debug("ToProcess size_AFTER: " + toProcess.size() + " DataCache size: " + dataCache.keySet().size());
toProcess.sort(new HandlingInfoTimeComparator());
processUnprocessedHandlingInfo(toProcess);
Benchmark.stop("Cache: ProcessOnlineHandlingInfo");
List<UserData> data = new ArrayList<>();
data.addAll(dataCache.values());
Log.debug("SAVING, DataCache size: " + dataCache.keySet().size());
try {
db.saveCommandUse(commandUse);
} catch (SQLException e) {
Log.toLog(this.getClass().getName(), e);
}
try {
db.saveMultipleUserData(data);
} catch (SQLException e) {
Log.toLog(this.getClass().getName(), e);
}
saveUnsavedTPSHistory();
try {
db.close();
} catch (SQLException e) {
Log.toLog(this.getClass().getName(), e);
}
Benchmark.stop("Cache: SaveOnDisable");
}
private void processUnprocessedHandlingInfo(List<HandlingInfo> toProcess) {
Log.debug("PROCESS: " + toProcess.size());
for (HandlingInfo i : toProcess) {
UserData uData = dataCache.get(i.getUuid());
if (uData == null) {
DBCallableProcessor p = i::process;
getUserDataForProcessing(p, i.getUuid());
} else {
i.process(uData);
}
}
}
/**
* Saves the cached data of matching Player if it is in the cache.
*
* @param uuid Player's UUID
*/
public void saveCachedData(UUID uuid) {
DBCallableProcessor saveProcessor = data -> {
data.access();
data.setClearAfterSave(true);
saveTask.scheduleForSave(data);
};
getUserDataForProcessing(saveProcessor, uuid);
}
/**
* Saves the cached CommandUse.
* <p>
* Should be only called from an Asynchronous Thread.
*/
public void saveCommandUse() {
try {
db.saveCommandUse(new HashMap<>(commandUse));
} catch (SQLException | NullPointerException e) {
Log.toLog(this.getClass().getName(), e);
}
}
public void saveUnsavedTPSHistory() {
List<TPS> averages = calculateAverageTpsForEachMinute();
if (averages.isEmpty()) {
return;
}
try {
Log.debug("Database", "Periodic TPS Save: " + averages.size());
db.getTpsTable().saveTPSData(averages);
} catch (SQLException ex) {
Log.toLog(this.getClass().getName(), ex);
}
}
private List<TPS> calculateAverageTpsForEachMinute() {
final List<TPS> averages = new ArrayList<>();
if (unsavedTPSHistory.isEmpty()) {
return new ArrayList<>();
}
List<List<TPS>> copy = new ArrayList<>(unsavedTPSHistory);
for (List<TPS> history : copy) {
final long lastDate = history.get(history.size() - 1).getDate();
final double averageTPS = MathUtils.round(MathUtils.averageDouble(history.stream().map(TPS::getTicksPerSecond)));
final int averagePlayersOnline = (int) MathUtils.averageInt(history.stream().map(TPS::getPlayers));
final double averageCPUUsage = MathUtils.round(MathUtils.averageDouble(history.stream().map(TPS::getCPUUsage)));
final long averageUsedMemory = MathUtils.averageLong(history.stream().map(TPS::getUsedMemory));
final int averageEntityCount = (int) MathUtils.averageInt(history.stream().map(TPS::getEntityCount));
final int averageChunksLoaded = (int) MathUtils.averageInt(history.stream().map(TPS::getChunksLoaded));
averages.add(new TPS(lastDate, averageTPS, averagePlayersOnline, averageCPUUsage, averageUsedMemory, averageEntityCount, averageChunksLoaded));
}
unsavedTPSHistory.removeAll(copy);
return averages;
}
/**
* Refreshes the calculations for all online players with ReloadInfo.
*/
public void saveHandlerDataToCache() {
final List<IPlayer> onlinePlayers = plugin.fetch().getOnlinePlayers();
onlinePlayers.forEach(p -> saveHandlerDataToCache(p, false));
}
private void saveHandlerDataToCache(IPlayer p, boolean pool) {
long time = MiscUtils.getTime();
UUID uuid = p.getUuid();
String worldName = ((Player) p.getWrappedPlayerClass()).getWorld().getName();
ReloadInfo info = new ReloadInfo(uuid, time, p.getAddress().getAddress(), p.isBanned(), p.getDisplayName(), p.getGamemode().name(), worldName);
if (!pool) {
UserData data = dataCache.get(uuid);
if (data != null) {
info.process(data);
return;
}
}
addToPool(info);
}
/**
* Schedules all UserData from the Cache to be cleared.
*/
public void clearCache() {
clearTask.scheduleForClear(dataCache.keySet());
}
/**
* Clears the matching UserData from the Cache if they're not online.
*
* @param uuid Player's UUID
*/
public void clearFromCache(UUID uuid) {
if (plugin.fetch().isOnline(uuid)) {
UserData data = dataCache.get(uuid);
if (data != null) {
data.setClearAfterSave(false);
}
} else {
dataCache.remove(uuid);
Log.debug("Cleared " + uuid.toString() + " from Cache.");
}
}
/**
* Schedules a matching UserData object to be cleared from the cache.
*
* @param uuid Player's UUID.
*/
public void scheduldeForClear(UUID uuid) {
clearTask.scheduleForClear(uuid);
}
/**
* Check whether or not the UserData object is being accessed by save or
* process tasks.
*
* @param uuid Player's UUID
* @return true/false
*/
public boolean isDataAccessed(UUID uuid) {
UserData userData = dataCache.get(uuid);
if (userData == null) {
return false;
}
boolean isAccessed = (userData.isAccessed()) || saveTask.containsUUID(uuid) || processTask.containsUUID(uuid);
if (isAccessed) {
userData.setClearAfterSave(false);
}
return isAccessed;
}
/**
* Creates a new UserData instance and saves it to the Database.
*
* @param player Player the new UserData is created for
*/
public void newPlayer(IPlayer player) {
newPlayer(NewPlayerCreator.createNewPlayer(player));
}
/**
* Schedules a new player's data to be saved to the Database.
*
* @param data UserData object to schedule for save.
*/
public void newPlayer(UserData data) {
saveTask.scheduleNewPlayer(data);
cache(data);
}
/**
* Used to get the contents of the cache.
*
* @return The Map containing all Cached UserData
*/
public Map<UUID, UserData> getDataCache() {
return dataCache;
}
/**
* Used to get the cached commandUse.
*
* @return Map with key:value - "/command":4
*/
public Map<String, Integer> getCommandUse() {
return commandUse;
}
/**
* If /reload is run this treats every online player as a new login.
* <p>
* Calls all the methods that are ran when PlayerJoinEvent is fired
*/
public void handleReload() {
plugin.getRunnableFactory().createNew(new AbsRunnable("ReloadCacheUpdateTask") {
@Override
public void run() {
final List<IPlayer> onlinePlayers = plugin.fetch().getOnlinePlayers();
for (IPlayer player : onlinePlayers) {
UUID uuid = player.getUuid();
boolean isNewPlayer = !db.wasSeenBefore(uuid);
if (isNewPlayer) {
newPlayer(player);
}
startSession(uuid);
saveHandlerDataToCache(player, true);
}
this.cancel();
}
}).runTaskAsynchronously();
}
/**
* Used to handle a command's execution.
*
* @param command "/command"
*/
public void handleCommand(String command) {
int amount = commandUse.getOrDefault(command, 0);
commandUse.put(command, amount + 1);
}
/**
* @return The SaveTask
*/
public DataCacheSaveQueue getSaveTask() {
return saveTask;
}
/**
* @return The ClearTask
*/
public DataCacheClearQueue getClearTask() {
return clearTask;
}
/**
* @return The ProcessTask
*/
public DataCacheProcessQueue getProcessTask() {
return processTask;
}
/**
* @return The GetTask
*/
public DataCacheGetQueue getGetTask() {
return getTask;
}
public void addTPSLastMinute(List<TPS> history) {
// Copy the contents to avoid reference, thus making the whole calculation pointless.
unsavedTPSHistory.add(new ArrayList<>(history));
}
}

View File

@ -1,129 +0,0 @@
package main.java.com.djrapitops.plan.data.cache;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.database.Database;
import main.java.com.djrapitops.plan.ui.webserver.response.InspectPageResponse;
import main.java.com.djrapitops.plan.utilities.HtmlUtils;
import main.java.com.djrapitops.plan.utilities.MiscUtils;
import main.java.com.djrapitops.plan.utilities.analysis.ExportUtility;
import java.io.FileNotFoundException;
import java.sql.SQLException;
import java.util.*;
/**
* This class stores UserData objects used for displaying the Html pages.
*
* @author Rsl1122
* @since 2.0.0
*/
public class InspectCacheHandler {
private final DataCacheHandler handler;
private final Map<UUID, UserData> cache;
private final Map<UUID, Long> cacheTimes;
/**
* Class constructor.
*
* @param plugin Current instance of Plan.class
*/
public InspectCacheHandler(Plan plugin) {
this.handler = plugin.getHandler();
this.cache = new HashMap<>();
cacheTimes = new HashMap<>();
}
/**
* Caches the UserData object to InspectCache.
* <p>
* If the Userdata is cached in DataCache it will be used. Otherwise the Get
* Queue will handle the DBCallableProcessor.
*
* @param uuid UUID of the player.
*/
public void cache(UUID uuid) {
DBCallableProcessor cacher = data -> {
cache.put(uuid, new UserData(data));
cacheTimes.put(uuid, MiscUtils.getTime());
PageCacheHandler.cachePage("inspectPage: " + uuid.toString(), () -> new InspectPageResponse(Plan.getInstance().getUiServer().getDataReqHandler(), uuid));
try {
ExportUtility.writeInspectHtml(data, ExportUtility.getPlayersFolder(ExportUtility.getFolder()), HtmlUtils.getStringFromResource("player.html"));
} catch (FileNotFoundException e) {
Log.toLog(this.getClass().getName(), e);
}
};
handler.getUserDataForProcessing(cacher, uuid, false);
}
/**
* Used to cache all UserData to the InspectCache from the cache and
* provided database.
*
* @param db Database to cache from if data is not in the cache.
* @throws SQLException If Database is not properly enabled
*/
public void cacheAllUserData(Database db) throws SQLException {
Set<UUID> cachedUserData = handler.getDataCache().keySet();
for (UUID uuid : cachedUserData) {
cache(uuid);
}
Set<UUID> savedUUIDs = new HashSet<>();
try {
savedUUIDs = db.getUsersTable().getSavedUUIDs();
} catch (SQLException ex) {
Log.toLog(this.getClass().getName(), ex);
}
savedUUIDs.removeAll(cachedUserData);
List<UserData> userDataForUUIDS = db.getUserDataForUUIDS(savedUUIDs);
long time = MiscUtils.getTime();
for (UserData uData : userDataForUUIDS) {
UUID uuid = uData.getUuid();
cache.put(uuid, new UserData(uData));
cacheTimes.put(uuid, time);
}
}
/**
* Checks the cache for UserData matching UUID.
*
* @param uuid UUID of the Player
* @return UserData that matches the player, null if not cached.
*/
public UserData getFromCache(UUID uuid) {
return cache.get(uuid);
}
/**
* Returns the Epoch millisecond the data was cached to the inspect cache.
*
* @param uuid UUID of the player.
* @return -1 when not cached or Epoch millisecond.
*/
public long getCacheTime(UUID uuid) {
return cacheTimes.getOrDefault(uuid, -1L);
}
/**
* Check if the data of a player is in the inspect cache.
*
* @param uuid UUID of player.
* @return true if cached.
*/
public boolean isCached(UUID uuid) {
return cache.containsKey(uuid);
}
/**
* Used to get all cached userdata objects.
*
* @return List of cached userdata objects.
*/
public List<UserData> getCachedUserData() {
return new ArrayList<>(cache.values());
}
}

View File

@ -1,84 +0,0 @@
package main.java.com.djrapitops.plan.data.cache;
import main.java.com.djrapitops.plan.data.SessionData;
import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.utilities.MiscUtils;
import java.util.HashMap;
import java.util.Map;
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 final HashMap<UUID, SessionData> activeSessions;
/**
* Class Constructor.
*/
public SessionCache() {
this.activeSessions = new HashMap<>();
}
/**
* Starts a session for a player at the current moment.
*
* @param uuid UUID of the player.
*/
public void startSession(UUID uuid) {
SessionData session = new SessionData(MiscUtils.getTime());
activeSessions.put(uuid, session);
}
/**
* Ends a session for a player at the current moment.
*
* @param uuid UUID of the player.
*/
public void endSession(UUID uuid) {
SessionData currentSession = activeSessions.get(uuid);
if (currentSession != null) {
currentSession.endSession(MiscUtils.getTime());
}
}
/**
* Used to get the SessionData of the player in the sessionCache.
*
* @param uuid UUID of the player.
* @return SessionData or null if not cached.
*/
public SessionData getSession(UUID uuid) {
return activeSessions.get(uuid);
}
/**
* Add a session to the UserData object if it is cached and has been ended.
*
* @param data UserData object a session should be added to.
*/
public void addSession(UserData data) {
UUID uuid = data.getUuid();
SessionData currentSession = activeSessions.get(uuid);
if (currentSession != null && currentSession.isValid() && !data.getSessions().contains(currentSession)) {
data.addSession(currentSession);
activeSessions.remove(uuid);
}
}
/**
* Used to get the Map of active sessions.
* <p>
* Used for testing.
*
* @return key:value UUID:SessionData
*/
public Map<UUID, SessionData> getActiveSessions() {
return activeSessions;
}
}

View File

@ -1,102 +0,0 @@
package main.java.com.djrapitops.plan.data.cache.queue;
import com.djrapitops.plugin.utilities.Verify;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Settings;
import main.java.com.djrapitops.plan.data.cache.DataCacheHandler;
import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg;
import java.util.Collection;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.stream.Collectors;
/**
* This Class contains the Clear Queue Thread, which is clearing data from the DataCache.
*
* @author Rsl1122
* @since 3.0.0
*/
public class DataCacheClearQueue extends Queue<UUID> {
/**
* Class constructor, starts the new Thread for clearing.
*
* @param handler current instance of DataCacheHandler.
*/
public DataCacheClearQueue(DataCacheHandler handler) {
super(new ArrayBlockingQueue<>(Settings.PROCESS_CLEAR_LIMIT.getNumber()));
setup = new ClearSetup(queue, handler);
setup.go();
}
/**
* Used to schedule UserData to be cleared from the cache.
*
* @param uuid UUID of the UserData object (Player's UUID)
*/
public void scheduleForClear(UUID uuid) {
queue.add(uuid);
}
/**
* Used to schedule multiple UserData objects to be cleared from the cache.
*
* @param uuids UUIDs of the UserData object (Players' UUIDs)
*/
public void scheduleForClear(Collection<UUID> uuids) {
if (Verify.isEmpty(uuids)) {
return;
}
try {
queue.addAll(uuids.stream().filter(Objects::nonNull).collect(Collectors.toList()));
} catch (IllegalStateException e) {
Log.error(Locale.get(Msg.RUN_WARN_QUEUE_SIZE).parse("Clear Queue", Settings.PROCESS_CLEAR_LIMIT.getNumber()));
}
}
}
class ClearConsumer extends Consumer<UUID> implements Runnable {
private DataCacheHandler handler;
ClearConsumer(BlockingQueue<UUID> q, DataCacheHandler handler) {
super(q, "ClearQueueConsumer");
this.handler = handler;
}
@Override
void consume(UUID uuid) {
if (!Verify.notNull(handler, uuid)) {
return;
}
try {
if (handler.isDataAccessed(uuid)) {
queue.add(uuid);
} else {
handler.clearFromCache(uuid);
}
// if online remove from clear list
} catch (Exception ex) {
Log.toLog(this.getClass().getName(), ex);
}
}
@Override
void clearVariables() {
if (handler != null) {
handler = null;
}
}
}
class ClearSetup extends Setup<UUID> {
ClearSetup(BlockingQueue<UUID> q, DataCacheHandler handler) {
super(new ClearConsumer(q, handler));
}
}

View File

@ -1,103 +0,0 @@
package main.java.com.djrapitops.plan.data.cache.queue;
import com.djrapitops.plugin.utilities.Verify;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.Settings;
import main.java.com.djrapitops.plan.data.cache.DBCallableProcessor;
import main.java.com.djrapitops.plan.database.Database;
import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg;
import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
/**
* This Class is starts the Get Queue Thread, that fetches data from DataCache.
*
* @author Rsl1122
* @since 3.0.0
*/
public class DataCacheGetQueue extends Queue<Map<UUID, List<DBCallableProcessor>>> {
/**
* Class constructor, starts the new Thread for fetching.
*
* @param plugin current instance of Plan
*/
public DataCacheGetQueue(Plan plugin) {
super(new ArrayBlockingQueue<>(Settings.PROCESS_GET_LIMIT.getNumber()));
setup = new GetSetup(queue, plugin.getDB());
setup.go();
}
/**
* Schedules UserData objects to be get for the given processors.
*
* @param uuid UUID of the player whose UserData object is fetched.
* @param processors Processors which process-method will be called after
* fetch is complete, with the UserData object.
*/
public void scheduleForGet(UUID uuid, DBCallableProcessor... processors) {
try {
Map<UUID, List<DBCallableProcessor>> map = new HashMap<>();
map.put(uuid, Arrays.asList(processors));
queue.add(map);
} catch (IllegalStateException e) {
Log.error(Locale.get(Msg.RUN_WARN_QUEUE_SIZE).parse("Get Queue", Settings.PROCESS_GET_LIMIT.getNumber()));
}
}
boolean containsUUIDtoBeCached(UUID uuid) {
return uuid != null && queue.stream()
.map(map -> map.get(uuid))
.filter(Objects::nonNull)
.anyMatch(list -> list.size() >= 2);
}
}
class GetConsumer extends Consumer<Map<UUID, List<DBCallableProcessor>>> {
private Database db;
GetConsumer(BlockingQueue<Map<UUID, List<DBCallableProcessor>>> q, Database db) {
super(q, "GetQueueConsumer");
this.db = db;
}
@Override
void consume(Map<UUID, List<DBCallableProcessor>> processors) {
if (!Verify.notNull(processors, db)) {
return;
}
try {
for (Map.Entry<UUID, List<DBCallableProcessor>> entrySet : processors.entrySet()) {
UUID uuid = entrySet.getKey();
List<DBCallableProcessor> processorsList = entrySet.getValue();
if (uuid == null || Verify.isEmpty(processorsList)) {
continue;
}
Log.debug("Database", uuid + ": Get, For:" + processorsList.size());
db.giveUserDataToProcessors(uuid, processorsList);
}
} catch (Exception ex) {
Log.toLog(this.getClass().getName(), ex);
}
}
@Override
void clearVariables() {
if (db != null) {
db = null;
}
}
}
class GetSetup extends Setup<Map<UUID, List<DBCallableProcessor>>> {
GetSetup(BlockingQueue<Map<UUID, List<DBCallableProcessor>>> q, Database db) {
super(new GetConsumer(q, db), new GetConsumer(q, db));
}
}

View File

@ -1,100 +0,0 @@
package main.java.com.djrapitops.plan.data.cache.queue;
import com.djrapitops.plugin.utilities.Verify;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.data.cache.DBCallableProcessor;
import main.java.com.djrapitops.plan.data.cache.DataCacheHandler;
import main.java.com.djrapitops.plan.data.handling.info.HandlingInfo;
import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
/**
* This Class is starts the Process Queue Thread, that processes HandlingInfo
* objects.
*
* @author Rsl1122
* @since 3.0.0
*/
public class DataCacheProcessQueue extends Queue<HandlingInfo> {
/**
* Class constructor, starts the new Thread for processing.
*
* @param handler current instance of DataCacheHandler.
*/
public DataCacheProcessQueue(DataCacheHandler handler) {
super(new ArrayBlockingQueue<>(20000));
setup = new ProcessSetup(queue, handler);
setup.go();
}
/**
* Used to add HandlingInfo object to be processed.
*
* @param info object that extends HandlingInfo.
*/
public void addToPool(HandlingInfo info) {
try {
queue.add(info);
} catch (IllegalStateException e) {
Log.toLog(this.getClass().getName(), e);
}
}
/**
* Check whether or not the queue contains a HandlingInfo object with the
* uuid.
*
* @param uuid UUID of the player.
* @return true/false
*/
public boolean containsUUID(UUID uuid) {
return uuid != null && queue.stream().anyMatch(info -> info.getUuid().equals(uuid));
}
}
class ProcessConsumer extends Consumer<HandlingInfo> {
private DataCacheHandler handler;
ProcessConsumer(BlockingQueue<HandlingInfo> q, DataCacheHandler h) {
super(q, "ProcessQueueConsumer");
handler = h;
}
@Override
void consume(HandlingInfo info) {
if (!Verify.notNull(handler, info)) {
return;
}
if (handler.getGetTask().containsUUIDtoBeCached(info.getUuid())) { // Wait for get queue.
queue.add(info);
return;
}
DBCallableProcessor p = data -> {
if (!info.process(data)) {
Log.error("Attempted to process data for wrong uuid: W:" + data.getUuid() + " | R:" + info.getUuid() + " Type:" + info.getType().name());
}
};
handler.getUserDataForProcessing(p, info.getUuid());
}
@Override
void clearVariables() {
if (handler != null) {
handler = null;
}
}
}
class ProcessSetup extends Setup<HandlingInfo> {
ProcessSetup(BlockingQueue<HandlingInfo> q, DataCacheHandler h) {
super(new ProcessConsumer(q, h), new ProcessConsumer(q, h));
}
}

View File

@ -1,124 +0,0 @@
package main.java.com.djrapitops.plan.data.cache.queue;
import com.djrapitops.plugin.utilities.Verify;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.Settings;
import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.data.cache.DataCacheHandler;
import main.java.com.djrapitops.plan.database.Database;
import main.java.com.djrapitops.plan.locale.Locale;
import main.java.com.djrapitops.plan.locale.Msg;
import java.sql.SQLException;
import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
/**
* This Class is starts the Save Queue Thread, that saves data to the Database.
*
* @author Rsl1122
* @since 3.0.0
*/
public class DataCacheSaveQueue extends Queue<UserData> {
/**
* Class constructor, starts the new Thread for saving.
*
* @param plugin current instance of Plan
* @param handler DataCacheHandler
*/
public DataCacheSaveQueue(Plan plugin, DataCacheHandler handler) {
super(new ArrayBlockingQueue<>(Settings.PROCESS_SAVE_LIMIT.getNumber()));
setup = new SaveSetup(queue, handler, plugin.getDB());
setup.go();
}
/**
* Schedule UserData object to be saved to the database.
*
* @param data UserData object.
*/
public void scheduleForSave(UserData data) {
try {
queue.add(data);
} catch (IllegalStateException e) {
Log.error(Locale.get(Msg.RUN_WARN_QUEUE_SIZE).parse("Save Queue", Settings.PROCESS_SAVE_LIMIT.getNumber()));
}
}
/**
* Schedule UserData object for a new player to be saved to the database.
*
* @param data UserData object.
*/
public void scheduleNewPlayer(UserData data) {
Log.debug(data.getUuid() + ": Scheduling new Player");
scheduleForSave(data);
}
/**
* Check whether or not the queue contains a UserData object with the uuid.
*
* @param uuid UUID of the player.
* @return true/false
*/
public boolean containsUUID(UUID uuid) {
return uuid != null && queue.stream().anyMatch(d -> d.getUuid().equals(uuid));
}
}
class SaveConsumer extends Consumer<UserData> {
private Database db;
private DataCacheHandler handler;
SaveConsumer(BlockingQueue<UserData> q, DataCacheHandler handler, Database db) {
super(q, "SaveQueueConsumer");
this.db = db;
this.handler = handler;
run = true;
}
@Override
void consume(UserData data) {
if (!Verify.notNull(handler, db, data)) {
return;
}
UUID uuid = data.getUuid();
if (handler.getProcessTask().containsUUID(uuid)) { // Wait for process queue.
queue.add(data);
return;
}
try {
db.saveUserData(data);
data.stopAccessing();
if (data.shouldClearAfterSave()) {
handler.getClearTask().scheduleForClear(uuid);
}
} catch (SQLException ex) {
Log.toLog(this.getClass().getName(), ex);
}
}
@Override
void clearVariables() {
if (db != null) {
db = null;
}
if (handler != null) {
handler = null;
}
}
}
class SaveSetup extends Setup<UserData> {
SaveSetup(BlockingQueue<UserData> q, DataCacheHandler handler, Database db) {
super(new SaveConsumer(q, handler, db), new SaveConsumer(q, handler, db));
}
}

View File

@ -1,31 +0,0 @@
package main.java.com.djrapitops.plan.data.handling;
import main.java.com.djrapitops.plan.data.UserData;
/**
* Class containing static methods for processing information contained in a
* ChatEvent.
*
* @author Rsl1122
* @since 3.0.0
*/
public class ChatHandling {
/**
* Constructor used to hide the public constructor
*/
private ChatHandling() {
throw new IllegalStateException("Utility class");
}
/**
* Processes the information of the Event and changes UserData object
* accordingly.
*
* @param data UserData of the player.
* @param nickname Nickname of the player during the event.
*/
public static void processChatInfo(UserData data, String nickname) {
data.addNickname(nickname);
}
}

View File

@ -1,69 +0,0 @@
package main.java.com.djrapitops.plan.data.handling;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.KillData;
import main.java.com.djrapitops.plan.data.UserData;
import org.apache.commons.lang3.text.WordUtils;
import org.bukkit.Material;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import java.sql.SQLException;
import java.util.UUID;
/**
* Class containing static methods for processing information contained in a
* DeathEvent when the killer is a player.
*
* @author Rsl1122
* @since 3.0.0
*/
public class KillHandling {
/**
* Utility Class, hides constructor.
*/
private KillHandling() {
throw new IllegalStateException("Utility Class.");
}
/**
* Processes the information of the Event and changes UserData object
* accordingly.
*
* @param data UserData of the player.
* @param time Epoch ms the event occurred.
* @param dead Mob or a Player the player killed.
* @param weaponName The name of the Weapon used.
*/
public static void processKillInfo(UserData data, long time, LivingEntity dead, String weaponName) {
Plan plugin = Plan.getInstance();
if (dead instanceof Player) {
Player deadPlayer = (Player) dead;
int victimID;
try {
UUID victimUUID = deadPlayer.getUniqueId();
victimID = plugin.getDB().getUsersTable().getUserId(victimUUID);
if (victimID == -1) {
return;
}
data.addPlayerKill(new KillData(victimUUID, victimID, weaponName, time));
} catch (SQLException e) {
Log.toLog("main.java.com.djrapitops.plan.KillHandling", e);
}
} else {
data.setMobKills(data.getMobKills() + 1);
}
}
/**
* Normalizes a material name
*
* @param material The material
* @return The normalized material name
*/
public static String normalizeMaterialName(Material material) {
return WordUtils.capitalizeFully(material.name(), '_').replace('_', ' ');
}
}

View File

@ -1,58 +0,0 @@
package main.java.com.djrapitops.plan.data.handling;
import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.data.cache.GeolocationCacheHandler;
import java.net.InetAddress;
/**
* Class containing static methods for processing information contained in a
* JoinEvent.
*
* @author Rsl1122
* @since 3.0.0
*/
public class LoginHandling {
/**
* Utility Class, hides constructor.
*/
private LoginHandling() {
throw new IllegalStateException("Utility Class.");
}
/**
* Processes the information of the Event and changes UserData object
* accordingly.
*
* @param data UserData of the player.
* @param time Epoch ms the event occurred.
* @param ip IP of the player
* @param banned Is the player banned
* @param nickname Nickname of the player
* @param loginTimes amount the loginTimes should be incremented with.
*/
public static void processLoginInfo(UserData data, long time, InetAddress ip, boolean banned, String nickname, int loginTimes) {
data.setLastPlayed(time);
data.updateBanned(banned);
data.setLoginTimes(data.getLoginTimes() + loginTimes);
data.addNickname(nickname);
data.addIpAddress(ip);
updateGeolocation(ip, data);
}
/**
* Updates the geolocation of the player.
* <p>
* Uses free service of freegeoip.net. 15000 requests can be sent per hour.
*
* @param ip InetAddress used for location.
* @param data UserData of the player.
* @see GeolocationCacheHandler
*/
public static void updateGeolocation(InetAddress ip, UserData data) {
String geoLocation = GeolocationCacheHandler.getCountry(ip.getHostAddress());
data.setGeolocation(geoLocation);
}
}

View File

@ -1,34 +0,0 @@
package main.java.com.djrapitops.plan.data.handling;
import main.java.com.djrapitops.plan.data.UserData;
/**
* Class containing static methods for processing information contained in a
* QuitEvent.
*
* @author Rsl1122
* @since 3.0.0
*/
public class LogoutHandling {
/**
* Constructor used to hide the public constructor
*/
private LogoutHandling() {
throw new IllegalStateException("Utility class");
}
/**
* Processes the information of the Event and changes UserData object
* accordingly.
*
* @param data UserData of the player.
* @param time Epoch ms the event occurred.
* @param banned Is the player banned?
*/
public static void processLogoutInfo(UserData data, long time, boolean banned) {
data.setPlayTime(data.getPlayTime() + (time - data.getLastPlayed()));
data.setLastPlayed(time);
data.updateBanned(banned);
}
}

View File

@ -1,32 +0,0 @@
package main.java.com.djrapitops.plan.data.handling;
import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.data.time.GMTimes;
import main.java.com.djrapitops.plan.data.time.WorldTimes;
public class PlaytimeHandling {
/**
* Constructor used to hide the public constructor
*/
private PlaytimeHandling() {
throw new IllegalStateException("Utility class");
}
public static void processPlaytimeDependentInfo(UserData data, long time, String gamemode, String worldName) {
long diff = time - data.getLastPlayed();
long playTime = data.getPlayTime() + diff;
data.setPlayTime(playTime);
data.setLastPlayed(time);
GMTimes gmTimes = data.getGmTimes();
if (gamemode != null) {
gmTimes.changeState(gamemode, playTime);
} else {
gmTimes.changeState(gmTimes.getState(), playTime);
}
WorldTimes worldTimes = data.getWorldTimes();
worldTimes.changeState(worldName, playTime);
}
}

View File

@ -1,53 +0,0 @@
package main.java.com.djrapitops.plan.data.handling.importing;
import com.djrapitops.pluginbridge.plan.importing.OnTimeImporter;
import main.java.com.djrapitops.plan.Log;
import java.util.HashMap;
import java.util.Map;
import static org.bukkit.Bukkit.getPluginManager;
/**
* This class is responsible for static utility methods used for importing.
*
* @author Rsl1122
* @since 3.2.0
*/
public class ImportUtils {
/**
* Constructor used to hide the public constructor
*/
private ImportUtils() {
throw new IllegalStateException("Utility class");
}
/**
* Checks if a plugin is enabled.
*
* @param pluginName Name of the plugin
* @return true/false
*/
public static boolean isPluginEnabled(String pluginName) {
return "offline".equals(pluginName) || getPluginManager().isPluginEnabled(pluginName);
}
/**
* Used to get all importers for different plugins.
*
* @return Map of importers with pluginname in lowercase as key.
*/
public static Map<String, Importer> getImporters() {
Map<String, Importer> importers = new HashMap<>();
try {
importers.put("ontime", new OnTimeImporter());
importers.put("offline", new OfflinePlayerImporter());
} catch (Exception e) {
Log.toLog("ImportUtils.getImporters", e);
Log.error("Plan Plugin Bridge not included in the plugin jar.");
}
return importers;
}
}

View File

@ -1,154 +0,0 @@
package main.java.com.djrapitops.plan.data.handling.importing;
import com.djrapitops.plugin.utilities.player.Fetch;
import com.djrapitops.plugin.utilities.player.IOfflinePlayer;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.data.cache.DataCacheHandler;
import main.java.com.djrapitops.plan.data.handling.info.HandlingInfo;
import main.java.com.djrapitops.plan.data.handling.info.InfoType;
import main.java.com.djrapitops.plan.database.Database;
import main.java.com.djrapitops.plan.utilities.Benchmark;
import main.java.com.djrapitops.plan.utilities.NewPlayerCreator;
import java.sql.SQLException;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
* Abstract class used for importing data from other plugins.
*
* @author Rsl1122
* @since 3.2.0
*/
public abstract class Importer {
private String info;
/**
* Constructor.
*/
public Importer() {
info = "No info specified";
}
/**
* Method used for the import.
* <p>
* Creates UserData for players that have not been saved to the database.
*
* @param uuids UUIDs to be imported
* @param args arguments for the import
* @return success
*/
public boolean importData(Collection<UUID> uuids, String... args) {
Plan plan = Plan.getInstance();
plan.getAnalysisCache().disableAnalysisTemporarily();
String processName = "Import, " + getClass().getSimpleName();
try {
DataCacheHandler handler = plan.getHandler();
Database db = plan.getDB();
Benchmark.start(processName);
Set<UUID> saved;
saved = db.getSavedUUIDs();
List<UUID> unSaved = new ArrayList<>(uuids);
unSaved.removeAll(saved);
int amount = unSaved.size();
String createUserObjects = "Creating " + amount + " new UserData objects";
Log.debug(processName, createUserObjects);
Map<UUID, IOfflinePlayer> offlinePlayers = Fetch.getIOfflinePlayers().stream().collect(Collectors.toMap(IOfflinePlayer::getUuid, Function.identity()));
Benchmark.start(createUserObjects);
List<UserData> newUsers = new ArrayList<>();
List<IOfflinePlayer> offlineP = unSaved
.stream()
.map(offlinePlayers::get)
.collect(Collectors.toList());
AtomicInteger currentUser = new AtomicInteger(0);
AtomicInteger currentPercent = new AtomicInteger(0);
int fivePercent = amount / 20;
//Using Set because of better Collection#contains() performance
Set<Integer> milestones = IntStream.rangeClosed(1, 20)
.mapToObj(i -> i * fivePercent)
.collect(Collectors.toSet());
offlineP.parallelStream()
.map(NewPlayerCreator::createNewOfflinePlayer)
.forEach(newPlayer -> {
newPlayer.setLastPlayed(newPlayer.getRegistered());
newUsers.add(newPlayer);
if (milestones.contains(currentUser.incrementAndGet())) {
Log.debug(processName, "Creating new UserData objects: " + currentPercent.addAndGet(5) + "%");
}
});
Benchmark.stop(processName, createUserObjects);
Log.debug(processName, "Save new UserData objects (" + amount + ")");
plan.getDB().saveMultipleUserData(newUsers);
for (UUID uuid : uuids) {
handler.addToPool(importData(uuid, args));
}
} catch (SQLException ex) {
Log.toLog(this.getClass().getName(), ex);
return false;
} finally {
plan.getAnalysisCache().enableAnalysis();
Log.logDebug(processName, Benchmark.stop(processName, processName));
}
return true;
}
/**
* Returns the info for import command.
*
* @return Information about the import options
* @since 3.5.0
*/
public final String getInfo() {
return info;
}
/**
* Set the info for import command.
*
* @param info Information about the import options
* @since 3.5.0
*/
public final void setInfo(String info) {
this.info = info;
}
/**
* Method used for getting the HandlingInfo object for the import data.
*
* @param uuid UUID of the player
* @param args Arguments for import
* @return HandlingInfo object that modifies the UserData so that the data
* is imported.
* @since 3.5.0
*/
public HandlingInfo importData(UUID uuid, String... args) {
return new HandlingInfo(uuid, InfoType.OTHER, 0) {
@Override
public boolean process(UserData uData) {
return true;
}
};
}
}

View File

@ -1,23 +0,0 @@
package main.java.com.djrapitops.plan.data.handling.importing;
import main.java.com.djrapitops.plan.data.handling.info.HandlingInfo;
import java.util.UUID;
/**
* Imports all players who have not joined since Plan was installed.
*
* @author Rsl1122
* @since 3.5.0
*/
public class OfflinePlayerImporter extends Importer {
public OfflinePlayerImporter() {
super.setInfo("Import all players who have not joined since Plan was installed.");
}
@Override
public HandlingInfo importData(UUID uuid, String... args) {
return null;
}
}

View File

@ -1,37 +0,0 @@
package main.java.com.djrapitops.plan.data.handling.info;
import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.data.handling.ChatHandling;
import java.util.UUID;
/**
* HandlingInfo Class for ChatEvent information.
*
* @author Rsl1122
* @since 3.0.0
*/
public class ChatInfo extends HandlingInfo {
private final String nickname;
/**
* Constructor.
*
* @param uuid UUID of the player.
* @param nickname Nickname of the player.
*/
public ChatInfo(UUID uuid, String nickname) {
super(uuid, InfoType.CHAT, 0L);
this.nickname = nickname;
}
@Override
public boolean process(UserData uData) {
if (!uData.getUuid().equals(uuid)) {
return false;
}
ChatHandling.processChatInfo(uData, nickname);
return true;
}
}

View File

@ -1,32 +0,0 @@
package main.java.com.djrapitops.plan.data.handling.info;
import main.java.com.djrapitops.plan.data.UserData;
import java.util.UUID;
/**
* HandlingInfo Class for DeathEvent information.
*
* @author Rsl1122
* @since 3.0.0
*/
public class DeathInfo extends HandlingInfo {
/**
* Constructor.
*
* @param uuid UUID of the dead player.
*/
public DeathInfo(UUID uuid) {
super(uuid, InfoType.DEATH, 0L);
}
@Override
public boolean process(UserData uData) {
if (!uData.getUuid().equals(uuid)) {
return false;
}
uData.setDeaths(uData.getDeaths() + 1);
return true;
}
}

View File

@ -1,70 +0,0 @@
package main.java.com.djrapitops.plan.data.handling.info;
import main.java.com.djrapitops.plan.data.UserData;
import java.util.UUID;
/**
* An abstract class for processing information about events and modifying
* UserData objects associated with the events.
*
* @author Rsl1122
* @since 3.0.0
*/
public abstract class HandlingInfo {
final UUID uuid;
final InfoType type;
final long time;
/**
* Super Constructor.
*
* @param uuid UUID of the player
* @param type InfoType enum of the event. Only used for debugging different
* types.
* @param time Epoch ms of the event.
*/
public HandlingInfo(UUID uuid, InfoType type, long time) {
this.uuid = uuid;
this.type = type;
this.time = time;
}
/**
* Get the UUID.
*
* @return UUID of the player associated with the event.
*/
public UUID getUuid() {
return uuid;
}
/**
* Get the InfoType.
*
* @return InfoType enum.
*/
public InfoType getType() {
return type;
}
/**
* Get the epoch ms the event occurred.
*
* @return long in ms.
*/
public long getTime() {
return time;
}
/**
* Process the info and modify the UserData object accordingly.
* <p>
* If the UUIDs don't match no change should occur.
*
* @param uData UserData object to modify.
* @return UUID of the UserData object and HandlingInfo match.
*/
public abstract boolean process(UserData uData);
}

View File

@ -1,54 +0,0 @@
package main.java.com.djrapitops.plan.data.handling.info;
/**
* Enum class for the types of HandlingInfo to be processed.
* <p>
* Type is only used for debugging.
* <p>
* OTHER should be used when
*
* @author Rsl1122
* @since 3.0.0
*/
public enum InfoType {
/**
*
*/
CHAT,
/**
*
*/
DEATH,
/**
*
*/
KILL,
/**
*
*/
GM,
/**
*
*/
LOGIN,
/**
*
*/
LOGOUT,
/**
*
*/
KICK,
/**
*
*/
RELOAD,
/**
* Used for events registered with the API.
*
* @since 3.1.1
*/
WORLD,
OTHER
}

View File

@ -1,33 +0,0 @@
package main.java.com.djrapitops.plan.data.handling.info;
import main.java.com.djrapitops.plan.data.UserData;
import java.util.UUID;
/**
* HandlingInfo Class for KickEvent information.
*
* @author Rsl1122
* @since 3.0.0
*/
public class KickInfo extends HandlingInfo {
/**
* Constructor.
*
* @param uuid UUID of the kicked player.
*/
public KickInfo(UUID uuid) {
super(uuid, InfoType.KICK, 0L);
}
@Override
public boolean process(UserData uData) {
if (!uData.getUuid().equals(uuid)) {
return false;
}
uData.setTimesKicked(uData.getTimesKicked() + 1);
return true;
}
}

View File

@ -1,43 +0,0 @@
package main.java.com.djrapitops.plan.data.handling.info;
import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.data.handling.KillHandling;
import org.bukkit.entity.LivingEntity;
import java.util.UUID;
/**
* HandlingInfo Class for DeathEvent information when the dead entity is a
* player.
*
* @author Rsl1122
* @since 3.0.0
*/
public class KillInfo extends HandlingInfo {
private final LivingEntity dead;
private final String weaponName;
/**
* Constructor.
*
* @param uuid UUID of the killer.
* @param time Epoch ms the event occurred.
* @param dead Dead entity (Mob or Player)
* @param weaponName Weapon used.
*/
public KillInfo(UUID uuid, long time, LivingEntity dead, String weaponName) {
super(uuid, InfoType.KILL, time);
this.dead = dead;
this.weaponName = weaponName;
}
@Override
public boolean process(UserData uData) {
if (!uData.getUuid().equals(uuid)) {
return false;
}
KillHandling.processKillInfo(uData, time, dead, weaponName);
return true;
}
}

View File

@ -1,73 +0,0 @@
package main.java.com.djrapitops.plan.data.handling.info;
import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.data.handling.LoginHandling;
import java.net.InetAddress;
import java.util.UUID;
/**
* HandlingInfo Class for JoinEvent information.
*
* @author Rsl1122
* @since 3.0.0
*/
public class LoginInfo extends HandlingInfo {
private final InetAddress ip;
private final boolean banned;
private final String nickname;
private final PlaytimeDependentInfo playtimeDependentInfo;
private final int loginTimes;
/**
* Constructor.
*
* @param uuid UUID of the player.
* @param time Epoch ms of the event.
* @param ip IP of the player
* @param banned Is the player banned?
* @param nickname Nickname of the player
* @param gm current gamemode of the player
* @param loginTimes number the loginTimes should be incremented with.
*/
public LoginInfo(UUID uuid, long time, InetAddress ip, boolean banned, String nickname, String gm, int loginTimes, String worldName) {
super(uuid, InfoType.LOGIN, time);
this.ip = ip;
this.banned = banned;
this.nickname = nickname;
this.playtimeDependentInfo = new PlaytimeDependentInfo(uuid, InfoType.OTHER, time, gm, worldName);
this.loginTimes = loginTimes;
}
/**
* Constructor for not incrementing the loginTimes.
* <p>
* This constructor is used only by ReloadInfo
*
* @param uuid UUID of the player.
* @param time Epoch ms of the event.
* @param ip IP of the player
* @param banned Is the player banned?
* @param nickname Nickname of the player
* @param gm current gamemode of the player
*/
public LoginInfo(UUID uuid, long time, InetAddress ip, boolean banned, String nickname, String gm, String worldName) {
super(uuid, InfoType.RELOAD, time);
this.ip = ip;
this.banned = banned;
this.nickname = nickname;
this.playtimeDependentInfo = new PlaytimeDependentInfo(uuid, InfoType.OTHER, time, gm, worldName);
this.loginTimes = 0;
}
@Override
public boolean process(UserData uData) {
if (!uData.getUuid().equals(uuid)) {
return false;
}
LoginHandling.processLoginInfo(uData, time, ip, banned, nickname, loginTimes);
playtimeDependentInfo.process(uData);
return true;
}
}

View File

@ -1,49 +0,0 @@
package main.java.com.djrapitops.plan.data.handling.info;
import main.java.com.djrapitops.plan.data.SessionData;
import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.data.handling.LogoutHandling;
import java.util.UUID;
/**
* HandlingInfo Class for QuitEvent information.
*
* @author Rsl1122
* @since 3.0.0
*/
public class LogoutInfo extends HandlingInfo {
private final boolean banned;
private final SessionData sData;
private final PlaytimeDependentInfo playtimeDependentInfo;
/**
* Constructor.
*
* @param uuid UUID of the player.
* @param time Epoch ms of the event.
* @param banned Is the player banned
* @param gm current gamemode of the player
* @param sData session that has been ended at the moment of the logout
* event.
*/
public LogoutInfo(UUID uuid, long time, boolean banned, String gm, SessionData sData, String worldName) {
super(uuid, InfoType.LOGOUT, time);
this.banned = banned;
this.sData = sData;
this.playtimeDependentInfo = new PlaytimeDependentInfo(uuid, InfoType.OTHER, time, gm, worldName);
}
@Override
public boolean process(UserData uData) {
if (!uData.getUuid().equals(uuid)) {
return false;
}
uData.addSession(sData);
LogoutHandling.processLogoutInfo(uData, time, banned);
playtimeDependentInfo.process(uData);
return true;
}
}

View File

@ -1,27 +0,0 @@
package main.java.com.djrapitops.plan.data.handling.info;
import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.data.handling.PlaytimeHandling;
import java.util.UUID;
public class PlaytimeDependentInfo extends HandlingInfo {
private final String gamemode;
private final String worldName;
public PlaytimeDependentInfo(UUID uuid, InfoType type, long time, String gm, String worldName) {
super(uuid, type, time);
this.worldName = worldName;
this.gamemode = gm;
}
@Override
public boolean process(UserData uData) {
if (!uuid.equals(uData.getUuid())) {
return false;
}
PlaytimeHandling.processPlaytimeDependentInfo(uData, time, gamemode, worldName);
return true;
}
}

View File

@ -1,27 +0,0 @@
package main.java.com.djrapitops.plan.data.handling.info;
import java.net.InetAddress;
import java.util.UUID;
/**
* HandlingInfo Class for refreshing data in the cache for online players.
*
* @author Rsl1122
* @since 3.0.0
*/
public class ReloadInfo extends LoginInfo {
/**
* Constructor.
*
* @param uuid UUID of the player.
* @param time Epoch ms of the event.
* @param ip IP of the player
* @param banned Is the player banned?
* @param nickname Nickname of the player
* @param gm current gamemode of the player
*/
public ReloadInfo(UUID uuid, long time, InetAddress ip, boolean banned, String nickname, String gm, String worldName) {
super(uuid, time, ip, banned, nickname, gm, worldName);
}
}

Some files were not shown because too many files have changed in this diff Show More