[3.6.0] Merge pull request #200 from Rsl1122/3.6.0

Main Pull Request for 3.6.0
This commit is contained in:
Rsl1122 2017-08-01 08:49:35 +03:00 committed by GitHub
commit 2335b00c46
244 changed files with 7398 additions and 5876 deletions

View File

@ -1,13 +1,13 @@
<component name="libraryTable"> <component name="libraryTable">
<library name="Maven: com.djrapitops:abstract-plugin-framework:2.0.0"> <library name="Maven: com.djrapitops:abstract-plugin-framework:2.0.1">
<CLASSES> <CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/com/djrapitops/abstract-plugin-framework/2.0.0/abstract-plugin-framework-2.0.0.jar!/" /> <root url="jar://$MAVEN_REPOSITORY$/com/djrapitops/abstract-plugin-framework/2.0.1/abstract-plugin-framework-2.0.1.jar!/" />
</CLASSES> </CLASSES>
<JAVADOC> <JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/com/djrapitops/abstract-plugin-framework/2.0.0/abstract-plugin-framework-2.0.0-javadoc.jar!/" /> <root url="jar://$MAVEN_REPOSITORY$/com/djrapitops/abstract-plugin-framework/2.0.1/abstract-plugin-framework-2.0.1-javadoc.jar!/" />
</JAVADOC> </JAVADOC>
<SOURCES> <SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/com/djrapitops/abstract-plugin-framework/2.0.0/abstract-plugin-framework-2.0.0-sources.jar!/" /> <root url="jar://$MAVEN_REPOSITORY$/com/djrapitops/abstract-plugin-framework/2.0.1/abstract-plugin-framework-2.0.1-sources.jar!/" />
</SOURCES> </SOURCES>
</library> </library>
</component> </component>

View File

@ -0,0 +1,13 @@
<component name="libraryTable">
<library name="Maven: com.destroystokyo.paper:paper:1.12-R0.1-SNAPSHOT">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/com/destroystokyo/paper/paper/1.12-R0.1-SNAPSHOT/paper-1.12-R0.1-20170725.202533-1.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/com/destroystokyo/paper/paper/1.12-R0.1-SNAPSHOT/paper-1.12-R0.1-20170725.202533-1-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/com/destroystokyo/paper/paper/1.12-R0.1-SNAPSHOT/paper-1.12-R0.1-20170725.202533-1-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@ -0,0 +1,14 @@
<component name="libraryTable">
<library name="Maven: com.djrapitops:PlanPluginBridge:3.6.0">
<CLASSES>
<root url="jar://$PROJECT_DIR$/../PlanPluginBridge/PlanPluginBridge-3.6.0.jar!/" />
<root url="file://$PROJECT_DIR$/../PlanPluginBridge" />
<root url="file://$PROJECT_DIR$/../PlanPluginBridge" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="file://$PROJECT_DIR$/../PlanPluginBridge/src/main/java" />
</SOURCES>
<jarDirectory url="file://$PROJECT_DIR$/../PlanPluginBridge" recursive="false" />
</library>
</component>

View File

@ -0,0 +1,13 @@
<component name="libraryTable">
<library name="Maven: com.djrapitops:abstract-plugin-framework:2.0.1">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/com/djrapitops/abstract-plugin-framework/2.0.1/abstract-plugin-framework-2.0.1.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/com/djrapitops/abstract-plugin-framework/2.0.1/abstract-plugin-framework-2.0.1-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/com/djrapitops/abstract-plugin-framework/2.0.1/abstract-plugin-framework-2.0.1-sources.jar!/" />
</SOURCES>
</library>
</component>

349
Plan/.idea/sonarIssues.xml Normal file
View File

@ -0,0 +1,349 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="issues">
<option name="index">
<map>
<entry key="/Dummy.txt">
<value>
<set />
</value>
</entry>
<entry key="/a.dummy">
<value>
<set />
</value>
</entry>
<entry key="/fragment.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/pom.xml">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/Plan.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/Settings.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/data/AnalysisData.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/data/TimeKeeper.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/data/TimeKeepingObject.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/data/UserData.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/data/analysis/WorldPart.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/data/cache/DataCacheHandler.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/data/handling/GamemodeHandling.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/data/handling/KillHandling.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/data/handling/LoginHandling.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/data/handling/PlaytimeHandling.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/data/handling/WorldTimeHandling.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/data/handling/info/GamemodeInfo.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/data/handling/info/InfoType.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/data/handling/info/LoginInfo.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/data/handling/info/LogoutInfo.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/data/handling/info/PlaytimeDependentInfo.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/data/handling/info/ReloadInfo.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/data/handling/info/WorldInfo.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/data/listeners/PlanGamemodeChangeListener.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/data/listeners/PlanPlayerListener.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/data/listeners/PlanWorldChangeListener.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/data/time/GMTimes.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/data/time/TimeKeeper.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/data/time/WorldTimes.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/database/Database.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/database/databases/SQLDB.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/database/tables/CommandUseTable.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/database/tables/GMTimesTable.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/database/tables/NicknamesTable.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/database/tables/SessionsTable.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/database/tables/TPSTable.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/database/tables/Table.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/database/tables/UsersTable.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/database/tables/WorldTable.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/database/tables/WorldTimesTable.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/ui/html/graphs/WorldPieCreator.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/utilities/NewPlayerCreator.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/utilities/PlaceholderUtils.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/utilities/analysis/Analysis.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/utilities/comparators/SessionDataComparator.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/java/com/djrapitops/plan/utilities/metrics/BStats.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/resources/analysis.html">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/resources/config.yml">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/main/resources/player.html">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/test/java/main/java/com/djrapitops/plan/data/UserDataTest.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/test/java/main/java/com/djrapitops/plan/data/handling/GamemodeHandlingTest.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/test/java/main/java/com/djrapitops/plan/data/handling/KillHandlingTest.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/test/java/main/java/com/djrapitops/plan/data/handling/info/ChatInfoTest.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/test/java/main/java/com/djrapitops/plan/data/handling/info/DeathInfoTest.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/test/java/main/java/com/djrapitops/plan/data/handling/info/GamemodeInfoTest.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/test/java/main/java/com/djrapitops/plan/data/handling/info/InfoUuidCorrectionTest.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/test/java/main/java/com/djrapitops/plan/data/handling/info/KillInfoTest.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/test/java/main/java/com/djrapitops/plan/data/handling/info/LoginInfoTest.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/test/java/main/java/com/djrapitops/plan/data/handling/info/LogoutInfoTest.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/test/java/main/java/com/djrapitops/plan/data/handling/info/ReloadInfoTest.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/test/java/main/java/com/djrapitops/plan/data/time/GMTimesTest.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/test/java/main/java/com/djrapitops/plan/database/DatabaseTest.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/test/java/main/java/com/djrapitops/plan/utilities/ManageUtilsTest.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/test/java/main/java/com/djrapitops/plan/utilities/NewPlayerCreatorTest.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/test/java/main/java/com/djrapitops/plan/utilities/comparators/ComparatorTest.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/test/java/main/java/com/djrapitops/plan/utilities/comparators/HandlingInfoTimeComparatorTest.java">
<value>
<set />
</value>
</entry>
<entry key="$PROJECT_DIR$/src/test/java/utils/MockUtils.java">
<value>
<set />
</value>
</entry>
</map>
</option>
</component>
</project>

124
Plan/.idea/uiDesigner.xml Normal file
View File

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.3//EN" "http://www.puppycrawl.com/dtds/configuration_1_3.dtd"> <!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
"http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
<module name='Checker'> <module name='Checker'>
<!-- asetetaan kieliasetukset englanniksi. --> <!-- asetetaan kieliasetukset englanniksi. -->
@ -8,15 +9,15 @@
<module name='TreeWalker'> <module name='TreeWalker'>
<property name='tabWidth' value='4' /> <property name='tabWidth' value='4'/>
<!-- Block Checks --> <!-- Block Checks -->
<module name='EmptyBlock' /> <module name='EmptyBlock'/>
<module name='LeftCurly' /> <module name='LeftCurly'/>
<module name='NeedBraces' /> <module name='NeedBraces'/>
<module name='RightCurly' /> <module name='RightCurly'/>
<module name='AvoidNestedBlocks' /> <module name='AvoidNestedBlocks'/>
<module name="NestedIfDepth"> <module name="NestedIfDepth">
<property name="max" value="2"/> <property name="max" value="2"/>
</module> </module>
@ -26,50 +27,50 @@
<module name="NestedTryDepth"/> <module name="NestedTryDepth"/>
<!-- Miscellaneous --> <!-- Miscellaneous -->
<module name='Indentation' /> <module name='Indentation'/>
<module name="OneStatementPerLine"/> <module name="OneStatementPerLine"/>
<!--- Naming Conventions --> <!--- Naming Conventions -->
<module name='ClassTypeParameterName' /> <module name='ClassTypeParameterName'/>
<module name='ConstantName' /> <module name='ConstantName'/>
<module name='LocalFinalVariableName' /> <module name='LocalFinalVariableName'/>
<module name='LocalVariableName' /> <module name='LocalVariableName'/>
<module name='MemberName' /> <module name='MemberName'/>
<module name='MethodName' /> <module name='MethodName'/>
<module name='MethodTypeParameterName' /> <module name='MethodTypeParameterName'/>
<module name='PackageName'> <module name='PackageName'>
<property name='format' value='^[a-z]+(\.[a-z][a-z0-9]*)*$' /> <property name='format' value='^[a-z]+(\.[a-z][a-z0-9]*)*$'/>
</module> </module>
<module name='ParameterName' /> <module name='ParameterName'/>
<module name='StaticVariableName' /> <module name='StaticVariableName'/>
<module name='TypeName' /> <module name='TypeName'/>
<!-- Whitespace --> <!-- Whitespace -->
<module name='GenericWhitespace' /> <module name='GenericWhitespace'/>
<module name='EmptyForInitializerPad' /> <module name='EmptyForInitializerPad'/>
<module name='EmptyForIteratorPad' /> <module name='EmptyForIteratorPad'/>
<module name='MethodParamPad' /> <module name='MethodParamPad'/>
<module name='NoWhitespaceAfter'> <module name='NoWhitespaceAfter'>
<property name='tokens' value='BNOT, DEC, DOT, INC, LNOT, UNARY_MINUS, UNARY_PLUS' /> <property name='tokens' value='BNOT, DEC, DOT, INC, LNOT, UNARY_MINUS, UNARY_PLUS'/>
</module> </module>
<module name='NoWhitespaceBefore'> <module name='NoWhitespaceBefore'>
<property name='tokens' value='SEMI, DOT, POST_DEC, POST_INC' /> <property name='tokens' value='SEMI, DOT, POST_DEC, POST_INC'/>
<property name='allowLineBreaks' value='true' /> <property name='allowLineBreaks' value='true'/>
</module> </module>
<module name='ParenPad' /> <module name='ParenPad'/>
<module name='TypecastParenPad' /> <module name='TypecastParenPad'/>
<module name='WhitespaceAfter' /> <module name='WhitespaceAfter'/>
<module name='WhitespaceAround'> <module name='WhitespaceAround'>
<property name='allowEmptyConstructors' value='true' /> <property name='allowEmptyConstructors' value='true'/>
<property name='allowEmptyMethods' value='true' /> <property name='allowEmptyMethods' value='true'/>
</module> </module>
<!-- Javadoc --> <!-- Javadoc -->
@ -91,7 +92,7 @@
<!-- File Length --> <!-- File Length -->
<module name='FileLength'> <module name='FileLength'>
<property name='max' value='2000' /> <property name='max' value='2000'/>
</module> </module>
</module> </module>

View File

@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.djrapitops</groupId> <groupId>com.djrapitops</groupId>
<artifactId>Plan</artifactId> <artifactId>Plan</artifactId>
<version>3.5.4</version> <version>3.5.5</version>
<build> <build>
<sourceDirectory>${basedir}/src</sourceDirectory> <sourceDirectory>${basedir}/src</sourceDirectory>
<defaultGoal>clean package install</defaultGoal> <defaultGoal>clean package install</defaultGoal>
@ -100,15 +100,19 @@
</build> </build>
<repositories> <repositories>
<repository> <repository>
<id>spigot-repo</id> <id>plan-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url> <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>
</repository> </repository>
</repositories> </repositories>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.spigotmc</groupId> <groupId>com.destroystokyo.paper</groupId>
<artifactId>spigot</artifactId> <artifactId>paper</artifactId>
<version>1.12-R0.1-SNAPSHOT</version> <version>1.12-R0.1-20170725.202533-1</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -1,6 +1,6 @@
ENABLED <> Player Analytics Enabled. ENABLED <> Player Analytics Enabled.
DISABLED <> Player Analytics Disabled. DISABLED <> Player Analytics Disabled.
RELOAD_COMPLETE <> §a[Plan] Reload complete. RELOAD_COMPLETE <> <EFBFBD>a[Plan] Reload complete.
CACHE_SAVE <> Saving cached data.. CACHE_SAVE <> Saving cached data..
CACHE_ADD <> Added REPLACE0 to Cache. CACHE_ADD <> Added REPLACE0 to Cache.
CACHE_REMOVE <> Cleared REPLACE0 from Cache. CACHE_REMOVE <> Cleared REPLACE0 from Cache.
@ -13,19 +13,19 @@ DB_CONNECTION_FAIL <> REPLACE0-Database Connection failed: REPLACE1
DB_ESTABLISHED <> REPLACE0-database connection established. DB_ESTABLISHED <> REPLACE0-database connection established.
DB_TYPE_DOES_NOT_EXIST <> That database type doesn't exist. DB_TYPE_DOES_NOT_EXIST <> That database type doesn't exist.
DB_FAILURE_DISABLE <> Database initialization has failed, disabling Plan. DB_FAILURE_DISABLE <> Database initialization has failed, disabling Plan.
NOTIFY_EMPTY_IP <> §e[Plan] IP in server.properties is empty & AlternativeServerIP is not used, incorrect links will be given! NOTIFY_EMPTY_IP <> <EFBFBD>e[Plan] IP in server.properties is empty & AlternativeServerIP is not used, incorrect links will be given!
VERSION_NEW_AVAILABLE <> New Version (REPLACE0) is availible at https://www.spigotmc.org/resources/plan-player-analytics.32536/ 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_LATEST <> You're running the latest version
VERSION_CHECK_ERROR <> Failed to compare versions. VERSION_CHECK_ERROR <> Failed to compare versions.
VERSION_FAIL <> Failed to get newest version number. VERSION_FAIL <> Failed to get newest version number.
USERNAME_NOT_VALID <> §c[Plan] This Player doesn't exist. USERNAME_NOT_VALID <> <EFBFBD>c[Plan] This Player doesn't exist.
USERNAME_NOT_SEEN <> §c[Plan] This Player has not played on this server. USERNAME_NOT_SEEN <> <EFBFBD>c[Plan] This Player has not played on this server.
USERNAME_NOT_KNOWN <> §c[Plan] Player not found from the database. USERNAME_NOT_KNOWN <> <EFBFBD>c[Plan] Player not found from the database.
GRABBING_DATA_MESSAGE <> Ȥ2 Fetching data to cache.. GRABBING_DATA_MESSAGE <> <EFBFBD><EFBFBD>2 Fetching data to cache..
DEM_UNKNOWN <> Not Known DEM_UNKNOWN <> Not Known
NOT_IN_TOWN <> Not in a town NOT_IN_TOWN <> Not in a town
NOT_IN_FAC <> Not in a faction NOT_IN_FAC <> Not in a faction
COMMAND_TIMEOUT <> §c[Plan] REPLACE0 Command timed out! Error most likely on console. COMMAND_TIMEOUT <> <EFBFBD>c[Plan] REPLACE0 Command timed out! Error most likely on console.
ANALYSIS_START <> Analysis | Beginning analysis of user data.. ANALYSIS_START <> Analysis | Beginning analysis of user data..
ANALYSIS_BOOT_NOTIFY <> Analysis | Boot analysis in 30 seconds.. ANALYSIS_BOOT_NOTIFY <> Analysis | Boot analysis in 30 seconds..
ANALYSIS_BOOT <> Analysis | Starting Boot Analysis.. ANALYSIS_BOOT <> Analysis | Starting Boot Analysis..
@ -36,44 +36,44 @@ ANALYSIS_FAIL_NO_DATA <> Analysis | Analysis failed, no data in the database.
ANALYSIS_BEGIN_ANALYSIS <> Analysis | Data Fetched, beginning Analysis of data.. ANALYSIS_BEGIN_ANALYSIS <> Analysis | Data Fetched, beginning Analysis of data..
ANALYSIS_COMPLETE <> Analysis | Analysis Complete. ANALYSIS_COMPLETE <> Analysis | Analysis Complete.
DATA_CORRUPTION_WARN <> Some data might be corrupted: REPLACE0 DATA_CORRUPTION_WARN <> Some data might be corrupted: REPLACE0
ERROR_NO_DATA_VIEW <> §eWebserver disabled but Alternative IP/PlanLite not used, no way to view data! ERROR_NO_DATA_VIEW <> <EFBFBD>eWebserver disabled but Alternative IP/PlanLite not used, no way to view data!
ERROR_WEBSERVER_OFF_ANALYSIS <> §e[Plan] This command can be only used if the webserver is running on this server. ERROR_WEBSERVER_OFF_ANALYSIS <> <EFBFBD>e[Plan] This command can be only used if the webserver is running on this server.
ERROR_WEBSERVER_OFF_INSPECT <> §e[Plan] This command can be only used if webserver/planlite is enabled on this server. ERROR_WEBSERVER_OFF_INSPECT <> <EFBFBD>e[Plan] This command can be only used if webserver/planlite is enabled on this server.
MANAGE_ERROR_INCORRECT_PLUGIN <> §c[Plan] Plugin not supported: MANAGE_ERROR_INCORRECT_PLUGIN <> <EFBFBD>c[Plan] Plugin not supported:
MANAGE_PROCESS_START <> Ȥ7 Processing data.. MANAGE_PROCESS_START <> <EFBFBD><EFBFBD>7 Processing data..
MANAGE_ERROR_PLUGIN_NOT_ENABLED <> §c[Plan] Plugin is not enabled: MANAGE_ERROR_PLUGIN_NOT_ENABLED <> <EFBFBD>c[Plan] Plugin is not enabled:
MANAGE_ERROR_INCORRECT_DB <> §c[Plan] Incorrect database! (sqlite/mysql accepted): MANAGE_ERROR_INCORRECT_DB <> <EFBFBD>c[Plan] Incorrect database! (sqlite/mysql accepted):
MANAGE_ERROR_SAME_DB <> §c[Plan] Can't move to the same database! MANAGE_ERROR_SAME_DB <> <EFBFBD>c[Plan] Can't move to the same database!
MANAGE_DATABASE_FAILURE <> §c[Plan] One of the databases was not initialized properly. MANAGE_DATABASE_FAILURE <> <EFBFBD>c[Plan] One of the databases was not initialized properly.
MANAGE_DB_CONFIG_REMINDER <> §e[Plan] Remember to swap to the new database and reload plugin MANAGE_DB_CONFIG_REMINDER <> <EFBFBD>e[Plan] Remember to swap to the new database and reload plugin
MANAGE_ERROR_NO_PLAYERS <> §c[Plan] Database has no player data! MANAGE_ERROR_NO_PLAYERS <> <EFBFBD>c[Plan] Database has no player data!
MANAGE_ERROR_BACKUP_FILE_NOT_FOUND <> §c[Plan] Backup file doesn't exist! MANAGE_ERROR_BACKUP_FILE_NOT_FOUND <> <EFBFBD>c[Plan] Backup file doesn't exist!
MANAGE_MOVE_SUCCESS <> §a[Plan] All data moved successfully! MANAGE_MOVE_SUCCESS <> <EFBFBD>a[Plan] All data moved successfully!
MANAGE_COPY_SUCCESS <> §a[Plan] All data copied successfully! MANAGE_COPY_SUCCESS <> <EFBFBD>a[Plan] All data copied successfully!
MANAGE_PROCESS_FAIL <> §c[Plan] Something went wrong while processing the data! MANAGE_PROCESS_FAIL <> <EFBFBD>c[Plan] Something went wrong while processing the data!
MANAGE_CLEAR_SUCCESS <> §a[Plan] All data cleared successfully! MANAGE_CLEAR_SUCCESS <> <EFBFBD>a[Plan] All data cleared successfully!
MANAGE_REMOVE_SUCCESS <> §f» §2Data of §fREPLACE0§2 was removed from Database §fREPLACE1§2. MANAGE_REMOVE_SUCCESS <> <EFBFBD>f<EFBFBD> <20>2Data of <20>fREPLACE0<45>2 was removed from Database <20>fREPLACE1<45>2.
MANAGE_IMPORTING <> §f» §2 Importing Data.. MANAGE_IMPORTING <> <EFBFBD>f<EFBFBD> <20>2 Importing Data..
MANAGE_SUCCESS <> §f» §2 Success! MANAGE_SUCCESS <> <EFBFBD>f<EFBFBD> <20>2 Success!
CMD_ANALYZE_HEADER <> §f»§2 Player Analytics - Analysis results CMD_ANALYZE_HEADER <> <EFBFBD>f<EFBFBD><EFBFBD>2 Player Analytics - Analysis results
CMD_INSPECT_HEADER <> §f»§2 Player Analytics - Inspect results: CMD_INSPECT_HEADER <> <EFBFBD>f<EFBFBD><EFBFBD>2 Player Analytics - Inspect results:
CMD_INFO_HEADER <> §f»§2 Player Analytics - Info CMD_INFO_HEADER <> <EFBFBD>f<EFBFBD><EFBFBD>2 Player Analytics - Info
CMD_INFO_VERSION <> §7 •§2§2 Version: §7REPLACE0 CMD_INFO_VERSION <> <EFBFBD>7 <20><>2<EFBFBD>2 Version: <20>7REPLACE0
CMD_SEARCH_HEADER <> §f»§2 Player Analytics - Search results for: CMD_SEARCH_HEADER <> <EFBFBD>f<EFBFBD><EFBFBD>2 Player Analytics - Search results for:
CMD_HELP_HEADER <> §f»§2 Player Analytics - Help CMD_HELP_HEADER <> <EFBFBD>f<EFBFBD><EFBFBD>2 Player Analytics - Help
CMD_MANAGE_HELP_HEADER <> §f»§2 Player Analytics - Managment Help CMD_MANAGE_HELP_HEADER <> <EFBFBD>f<EFBFBD><EFBFBD>2 Player Analytics - Managment Help
CMD_MANAGE_STATUS_HEADER <> §f»§2 Player Analytics - Database status CMD_MANAGE_STATUS_HEADER <> <EFBFBD>f<EFBFBD><EFBFBD>2 Player Analytics - Database status
CMD_MANAGE_STATUS_ACTIVE_DB <> §7 •§2§2 Active Database: §7REPLACE0 CMD_MANAGE_STATUS_ACTIVE_DB <> <EFBFBD>7 <20><>2<EFBFBD>2 Active Database: <20>7REPLACE0
CMD_CLICK_ME <> Click Me CMD_CLICK_ME <> Click Me
CMD_LINK <> §7 •§2 Link: §f CMD_LINK <> <EFBFBD>7 <20><>2 Link: <20>f
CMD_RESULTS_AVAILABLE <> §7 Results will be available for §fREPLACE0§7 minutes. CMD_RESULTS_AVAILABLE <> <EFBFBD>7 Results will be available for <20>fREPLACE0<45>7 minutes.
CMD_NO_RESULTS <> §7 •§2 No results for §7REPLACE0§2. CMD_NO_RESULTS <> <EFBFBD>7 <20><>2 No results for <20>7REPLACE0<45>2.
CMD_MATCH <> §7 Matching player: §f CMD_MATCH <> <EFBFBD>7 Matching player: <20>f
CMD_USG_ANALYZE <> View the Server Analysis CMD_USG_ANALYZE <> View the Server Analysis
CMD_USG_HELP <> Show command list. CMD_USG_HELP <> Show command list.
CMD_USG_INFO <> View Version of Plan CMD_USG_INFO <> View Version of Plan
CMD_USG_INSPECT <> Inspect Player's Data CMD_USG_INSPECT <> Inspect Player's Data
CMD_USG_MANAGE <> Database managment command CMD_USG_MANAGE <> Database management command
CMD_USG_MANAGE_BACKUP <> Backup a database to .db file CMD_USG_MANAGE_BACKUP <> Backup a database to .db file
CMD_USG_MANAGE_RESTORE <> Restore a database from a backup 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_MOVE <> Copy data from one database to another & overwrite values
@ -82,7 +82,7 @@ CMD_USG_MANAGE_IMPORT <> Import Data from supported plugins to Active Database.
CMD_USG_MANAGE_CLEAR <> Clear data from one 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_REMOVE <> Remove players's data from the Active Database.
CMD_USG_MANAGE_STATUS <> Check the status of the Active Database. CMD_USG_MANAGE_STATUS <> Check the status of the Active Database.
CMD_USG_MANAGE_HELP <> Show managment help. CMD_USG_MANAGE_HELP <> Show management help.
CMD_USG_MANAGE_HOTSWAP <> Hotswap to another database & restart the plugin CMD_USG_MANAGE_HOTSWAP <> Hotswap to another database & restart the plugin
CMD_USG_RELOAD <> Reload plugin config & save cached data CMD_USG_RELOAD <> Reload plugin config & save cached data
CMD_USG_SEARCH <> Search for player CMD_USG_SEARCH <> Search for player
@ -101,11 +101,11 @@ WARN_REWRITE <> Data in REPLACE0-database will be rewritten!
WARN_OVERWRITE <> Data in REPLACE0-database will be overwritten! WARN_OVERWRITE <> Data in REPLACE0-database will be overwritten!
WARN_OVERWRITE_SOME <> Some 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! WARN_REMOVE <> Data in REPLACE0-database will be removed!
COMMAND_SENDER_NOT_PLAYER <> §c[Plan] This command can be only used as a player. COMMAND_SENDER_NOT_PLAYER <> <EFBFBD>c[Plan] This command can be only used as a player.
COMMAND_REQUIRES_ARGUMENTS <> §c[Plan] Command requires arguments. REPLACE0 COMMAND_REQUIRES_ARGUMENTS <> <EFBFBD>c[Plan] Command requires arguments. REPLACE0
COMMAND_ADD_CONFIRMATION_ARGUMENT <> §c[Plan] Add -a to confirm execution! REPLACE0 COMMAND_ADD_CONFIRMATION_ARGUMENT <> <EFBFBD>c[Plan] Add -a to confirm execution! REPLACE0
COMMAND_REQUIRES_ARGUMENTS_ONE <> §c[Plan] Command requires one argument. COMMAND_REQUIRES_ARGUMENTS_ONE <> <EFBFBD>c[Plan] Command requires one argument.
COMMAND_NO_PERMISSION <> §c[Plan] You do not have the required permmission. COMMAND_NO_PERMISSION <> <EFBFBD>c[Plan] You do not have the required permission.
<<<<<<HTML>>>>>> <<<<<<HTML>>>>>>
WARN_INACCURATE <> <div class="warn">Data might be inaccurate, player has just registered.</div> WARN_INACCURATE <> <div class="warn">Data might be inaccurate, player has just registered.</div>
BANNED <> | <span class="darkred">Banned</span> BANNED <> | <span class="darkred">Banned</span>

View File

@ -46,7 +46,9 @@
<goal>org.codehaus.mojo:exec-maven-plugin:1.2.1:exec</goal> <goal>org.codehaus.mojo:exec-maven-plugin:1.2.1:exec</goal>
</goals> </goals>
<properties> <properties>
<exec.args>-Xdebug -Xrunjdwp:transport=dt_socket,server=n,address=${jpda.address} -classpath %classpath com.djrapitops.nmplayer.NMPlayer</exec.args> <exec.args>-Xdebug -Xrunjdwp:transport=dt_socket,server=n,address=${jpda.address} -classpath %classpath
com.djrapitops.nmplayer.NMPlayer
</exec.args>
<exec.executable>java</exec.executable> <exec.executable>java</exec.executable>
<jpda.listen>true</jpda.listen> <jpda.listen>true</jpda.listen>
</properties> </properties>

View File

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.djrapitops</groupId> <groupId>com.djrapitops</groupId>
<artifactId>Plan</artifactId> <artifactId>Plan</artifactId>
<version>3.5.5</version> <version>3.6.0</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<repositories> <repositories>
<repository> <repository>
@ -28,14 +28,14 @@
<dependency> <dependency>
<groupId>com.djrapitops</groupId> <groupId>com.djrapitops</groupId>
<artifactId>abstract-plugin-framework</artifactId> <artifactId>abstract-plugin-framework</artifactId>
<version>2.0.0</version> <version>2.0.1</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<!-- SoftDepended Plugins--> <!-- SoftDepended Plugins-->
<dependency> <dependency>
<groupId>com.djrapitops</groupId> <groupId>com.djrapitops</groupId>
<artifactId>PlanPluginBridge</artifactId> <artifactId>PlanPluginBridge</artifactId>
<version>3.5.0</version> <version>3.6.0</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<!-- --> <!-- -->
@ -105,6 +105,8 @@
<targetPath>.</targetPath> <targetPath>.</targetPath>
<directory>${basedir}/src/main/resources</directory> <directory>${basedir}/src/main/resources</directory>
<includes> <includes>
<include>*.keystore</include>
<include>*.js</include>
<include>*.yml</include> <include>*.yml</include>
<include>*.html</include> <include>*.html</include>
</includes> </includes>
@ -198,5 +200,6 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target> <maven.compiler.target>1.8</maven.compiler.target>
<sonar.language>java</sonar.language>
</properties> </properties>
</project> </project>

View File

@ -4,7 +4,7 @@ import java.util.Collection;
/** /**
* This class manages the messages going to the Console Logger. * This class manages the messages going to the Console Logger.
* * <p>
* Methods of Abstract Plugin Framework log utility are used. * Methods of Abstract Plugin Framework log utility are used.
* *
* @author Rsl1122 * @author Rsl1122
@ -12,6 +12,13 @@ import java.util.Collection;
*/ */
public class Log { public class Log {
/**
* Constructor used to hide the public constructor
*/
private Log() {
throw new IllegalStateException("Utility Class");
}
/** /**
* Logs the message to the console as INFO. * Logs the message to the console as INFO.
* *

View File

@ -44,7 +44,7 @@ public enum Permissions {
/** /**
* Returns the permission node in plugin.yml. * Returns the permission node in plugin.yml.
* * <p>
* Same as getPermission. * Same as getPermission.
* *
* @return permission node eg. plan.inspect * @return permission node eg. plan.inspect

View File

@ -1,12 +1,13 @@
package main.java.com.djrapitops.plan; package main.java.com.djrapitops.plan;
import org.bukkit.ChatColor;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Scanner; import java.util.Scanner;
import org.bukkit.ChatColor;
/** /**
* Phrase contains every message that is used in placeholders or commands. The * Phrase contains every message that is used in placeholders or commands. The
@ -21,7 +22,7 @@ public enum Phrase {
PREFIX("[Plan] "), PREFIX("[Plan] "),
ENABLED("Player Analytics Enabled."), ENABLED("Player Analytics Enabled."),
DISABLED("Player Analytics Disabled."), DISABLED("Player Analytics Disabled."),
RELOAD_COMPLETE(ChatColor.GREEN + "" + PREFIX + "Reload complete."), RELOAD_COMPLETE(ChatColor.GREEN.toString() + PREFIX + "Reload complete."),
CACHE_SAVE("Saving cached data.."), CACHE_SAVE("Saving cached data.."),
CACHE_ADD("Added REPLACE0 to Cache."), CACHE_ADD("Added REPLACE0 to Cache."),
CACHE_REMOVE("Cleared REPLACE0 from Cache."), CACHE_REMOVE("Cleared REPLACE0 from Cache."),
@ -34,7 +35,7 @@ public enum Phrase {
DB_ESTABLISHED(REPLACE0 + "-database connection established."), DB_ESTABLISHED(REPLACE0 + "-database connection established."),
DB_TYPE_DOES_NOT_EXIST("That database type doesn't exist."), DB_TYPE_DOES_NOT_EXIST("That database type doesn't exist."),
DB_FAILURE_DISABLE("Database initialization has failed, disabling Plan."), DB_FAILURE_DISABLE("Database initialization has failed, disabling Plan."),
NOTIFY_EMPTY_IP(ChatColor.YELLOW + "" + PREFIX + "IP in server.properties is empty & AlternativeServerIP is not used, incorrect links will be given!"), NOTIFY_EMPTY_IP(ChatColor.YELLOW.toString() + PREFIX + "IP in server.properties is empty & AlternativeServerIP is not used, incorrect links will be given!"),
NOTIFY_DISABLED_CHATLISTENER(ChatColor.YELLOW + "Chat listener disabled, nickname info inaccurate."), NOTIFY_DISABLED_CHATLISTENER(ChatColor.YELLOW + "Chat listener disabled, nickname info inaccurate."),
NOTIFY_DISABLED_GMLISTENER(ChatColor.YELLOW + "Gamemode change listener disabled, Gm times info inaccurate."), NOTIFY_DISABLED_GMLISTENER(ChatColor.YELLOW + "Gamemode change listener disabled, Gm times info inaccurate."),
NOTIFY_DISABLED_COMMANDLISTENER(ChatColor.YELLOW + "Command usage listener disabled."), NOTIFY_DISABLED_COMMANDLISTENER(ChatColor.YELLOW + "Command usage listener disabled."),
@ -44,14 +45,14 @@ public enum Phrase {
CACHE_GETTASK_DISABLED("Attempted to schedule data grab after task was shut down."), CACHE_GETTASK_DISABLED("Attempted to schedule data grab after task was shut down."),
CACHE_CLEARTASK_DISABLED("Attempted to schedule data for clear after task was shut down."), CACHE_CLEARTASK_DISABLED("Attempted to schedule data for clear after task was shut down."),
// //
VERSION_NEW_AVAILABLE("New Version (" + REPLACE0 + ") is availible at https://www.spigotmc.org/resources/plan-player-analytics.32536/"), 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_LATEST("You're running the latest version"),
VERSION_CHECK_ERROR("Failed to compare versions."), VERSION_CHECK_ERROR("Failed to compare versions."),
VERSION_FAIL("Failed to get newest version number."), VERSION_FAIL("Failed to get newest version number."),
// //
USERNAME_NOT_VALID(ChatColor.RED + "" + PREFIX + "This Player doesn't exist."), USERNAME_NOT_VALID(ChatColor.RED.toString() + PREFIX + "This Player doesn't exist."),
USERNAME_NOT_SEEN(ChatColor.RED + "" + PREFIX + "This Player has not played on this server."), USERNAME_NOT_SEEN(ChatColor.RED.toString() + PREFIX + "This Player has not played on this server."),
USERNAME_NOT_KNOWN(ChatColor.RED + "" + PREFIX + "Player not found from the database."), USERNAME_NOT_KNOWN(ChatColor.RED.toString() + PREFIX + "Player not found from the database."),
// //
COLOR_MAIN(ChatColor.getByChar(Settings.COLOR_MAIN.toString().charAt(1))), COLOR_MAIN(ChatColor.getByChar(Settings.COLOR_MAIN.toString().charAt(1))),
COLOR_SEC(ChatColor.getByChar(Settings.COLOR_SEC.toString().charAt(1))), COLOR_SEC(ChatColor.getByChar(Settings.COLOR_SEC.toString().charAt(1))),
@ -59,14 +60,14 @@ public enum Phrase {
// //
ARROWS_RIGHT("»"), ARROWS_RIGHT("»"),
BALL(""), BALL(""),
GRABBING_DATA_MESSAGE(COLOR_TER + "" + ARROWS_RIGHT + COLOR_MAIN.color() + " Fetching data to cache.."), GRABBING_DATA_MESSAGE(COLOR_TER.toString() + ARROWS_RIGHT + COLOR_MAIN.color() + " Fetching data to cache.."),
// //
DEM_UNKNOWN("Not Known"), DEM_UNKNOWN("Not Known"),
NOT_IN_TOWN("Not in a town"), NOT_IN_TOWN("Not in a town"),
NOT_IN_FAC("Not in a faction"), NOT_IN_FAC("Not in a faction"),
// //
ANALYSIS("Analysis | "), ANALYSIS("Analysis | "),
COMMAND_TIMEOUT(ChatColor.RED + "" + PREFIX + "REPLACE0 Command timed out! Check '/plan status' & console."), COMMAND_TIMEOUT(ChatColor.RED.toString() + PREFIX + "REPLACE0 Command timed out! Check '/plan status' & console."),
ANALYSIS_START(ANALYSIS + "Beginning analysis of user data.."), ANALYSIS_START(ANALYSIS + "Beginning analysis of user data.."),
ANALYSIS_BOOT_NOTIFY(ANALYSIS + "Boot analysis in 30 seconds.."), ANALYSIS_BOOT_NOTIFY(ANALYSIS + "Boot analysis in 30 seconds.."),
ANALYSIS_BOOT(ANALYSIS + "Starting Boot Analysis.."), ANALYSIS_BOOT(ANALYSIS + "Starting Boot Analysis.."),
@ -82,45 +83,45 @@ public enum Phrase {
ERROR_CONSOLE_PLAYER("This point of code should not be accessable on console. Inform author: " + REPLACE0 + " Console: REPLACE1"), ERROR_CONSOLE_PLAYER("This point of code should not be accessable on console. Inform author: " + REPLACE0 + " Console: REPLACE1"),
ERROR_NO_DATA_VIEW(ChatColor.YELLOW + "Webserver disabled but Alternative IP/PlanLite not used, no way to view data!"), ERROR_NO_DATA_VIEW(ChatColor.YELLOW + "Webserver disabled but Alternative IP/PlanLite not used, no way to view data!"),
ERROR_WEBSERVER_OFF_ANALYSIS(ChatColor.YELLOW + "" + PREFIX + "This command can be only used if the webserver is running on this server."), ERROR_WEBSERVER_OFF_ANALYSIS(ChatColor.YELLOW + "" + PREFIX + "This command can be only used if the webserver is running on this server."),
ERROR_WEBSERVER_OFF_INSPECT(ChatColor.YELLOW + "" + PREFIX + "This command can be only used if webserver/planlite is enabled on this server."), ERROR_WEBSERVER_OFF_INSPECT(ChatColor.YELLOW + "" + PREFIX + "This command can be only used if webserver is enabled on this server."),
ERROR_LOGGED("Caught " + REPLACE0 + ". It has been logged to the Errors.txt"), ERROR_LOGGED("Caught " + REPLACE0 + ". It has been logged to the Errors.txt"),
ERROR_SESSIONDATA_INITIALIZATION("Player's session was initialized in a wrong way! (" + REPLACE0 + ")"), ERROR_SESSIONDATA_INITIALIZATION("Player's session was initialized in a wrong way! (" + REPLACE0 + ")"),
ERROR_ANALYSIS_FETCH_FAIL("Failed to fetch data for Analysis, Exception occurred."), ERROR_ANALYSIS_FETCH_FAIL("Failed to fetch data for Analysis, Exception occurred."),
ERROR_ANALYSIS_DISABLED_TEMPORARILY(ChatColor.YELLOW + "Analysis has been temporarily disabled due to expensive task, use /plan status for info."), ERROR_ANALYSIS_DISABLED_TEMPORARILY(ChatColor.YELLOW + "Analysis has been temporarily disabled due to expensive task, use /plan status for info."),
// //
CMD_FOOTER(COLOR_TER.color() + "" + ARROWS_RIGHT), CMD_FOOTER(COLOR_TER.color().toString() + ARROWS_RIGHT),
MANAGE_ERROR_INCORRECT_PLUGIN(ChatColor.RED + "" + PREFIX + "Plugin not supported: "), MANAGE_ERROR_INCORRECT_PLUGIN(ChatColor.RED.toString() + PREFIX + "Plugin not supported: "),
MANAGE_PROCESS_START(ARROWS_RIGHT + "" + COLOR_SEC.color() + " Processing data.."), MANAGE_PROCESS_START(ARROWS_RIGHT.toString() + COLOR_SEC.color() + " Processing data.."),
MANAGE_ERROR_PLUGIN_NOT_ENABLED(ChatColor.RED + "" + PREFIX + "Plugin is not enabled: "), MANAGE_ERROR_PLUGIN_NOT_ENABLED(ChatColor.RED.toString() + PREFIX + "Plugin is not enabled: "),
MANAGE_ERROR_INCORRECT_DB(ChatColor.RED + "" + PREFIX + "Incorrect database! (sqlite/mysql accepted): "), MANAGE_ERROR_INCORRECT_DB(ChatColor.RED.toString() + PREFIX + "Incorrect database! (sqlite/mysql accepted): "),
MANAGE_ERROR_SAME_DB(ChatColor.RED + "" + PREFIX + "Can't move to the same database!"), MANAGE_ERROR_SAME_DB(ChatColor.RED.toString() + PREFIX + "Can't move to the same database!"),
MANAGE_DATABASE_FAILURE(ChatColor.RED + "" + PREFIX + "One of the databases was not initialized properly."), MANAGE_DATABASE_FAILURE(ChatColor.RED.toString() + PREFIX + "One of the databases was not initialized properly."),
MANAGE_DB_CONFIG_REMINDER(ChatColor.YELLOW + "" + PREFIX + "Remember to swap to the new database and reload plugin"), MANAGE_DB_CONFIG_REMINDER(ChatColor.YELLOW.toString() + PREFIX + "Remember to swap to the new database and reload plugin"),
MANAGE_ERROR_NO_PLAYERS(ChatColor.RED + "" + PREFIX + "Database has no player data!"), MANAGE_ERROR_NO_PLAYERS(ChatColor.RED.toString() + PREFIX + "Database has no player data!"),
MANAGE_ERROR_BACKUP_FILE_NOT_FOUND(ChatColor.RED + "" + PREFIX + "Backup file doesn't exist!"), MANAGE_ERROR_BACKUP_FILE_NOT_FOUND(ChatColor.RED.toString() + PREFIX + "Backup file doesn't exist!"),
MANAGE_MOVE_SUCCESS(ChatColor.GREEN + "" + PREFIX + "All data moved successfully!"), MANAGE_MOVE_SUCCESS(ChatColor.GREEN.toString() + PREFIX + "All data moved successfully!"),
MANAGE_COPY_SUCCESS(ChatColor.GREEN + "" + PREFIX + "All data copied successfully!"), MANAGE_COPY_SUCCESS(ChatColor.GREEN.toString() + PREFIX + "All data copied successfully!"),
MANAGE_PROCESS_FAIL(ChatColor.RED + "" + PREFIX + "Something went wrong while processing the data!"), MANAGE_PROCESS_FAIL(ChatColor.RED.toString() + PREFIX + "Something went wrong while processing the data!"),
MANAGE_CLEAR_SUCCESS(ChatColor.GREEN + "" + PREFIX + "All data cleared successfully!"), MANAGE_CLEAR_SUCCESS(ChatColor.GREEN.toString() + PREFIX + "All data cleared successfully!"),
MANAGE_REMOVE_SUCCESS(CMD_FOOTER + " " + COLOR_MAIN.color() + "Data of " + COLOR_TER.color() + "REPLACE0" + COLOR_MAIN.color() + " was removed from Database " + COLOR_TER.color() + "REPLACE1" + COLOR_MAIN.color() + "."), MANAGE_REMOVE_SUCCESS(CMD_FOOTER + " " + COLOR_MAIN.color() + "Data of " + COLOR_TER.color() + "REPLACE0" + COLOR_MAIN.color() + " was removed from Database " + COLOR_TER.color() + "REPLACE1" + COLOR_MAIN.color() + "."),
MANAGE_IMPORTING(CMD_FOOTER + " " + COLOR_MAIN.color() + " Importing Data.."), MANAGE_IMPORTING(CMD_FOOTER + " " + COLOR_MAIN.color() + " Importing Data.."),
MANAGE_SUCCESS(CMD_FOOTER + " " + COLOR_MAIN.color() + " Success!"), MANAGE_SUCCESS(CMD_FOOTER + " " + COLOR_MAIN.color() + " Success!"),
// //
CMD_BALL(COLOR_SEC.color() + " " + Phrase.BALL.toString() + COLOR_MAIN.color()), CMD_BALL(COLOR_SEC.color() + " " + Phrase.BALL.toString() + COLOR_MAIN.color()),
CMD_ANALYZE_HEADER(CMD_FOOTER + "" + COLOR_MAIN.color() + " Player Analytics - Analysis results"), CMD_ANALYZE_HEADER(CMD_FOOTER.toString() + COLOR_MAIN.color() + " Player Analytics - Analysis results"),
CMD_INSPECT_HEADER(CMD_FOOTER + "" + COLOR_MAIN.color() + " Player Analytics - Inspect results: "), CMD_INSPECT_HEADER(CMD_FOOTER.toString() + COLOR_MAIN.color() + " Player Analytics - Inspect results: "),
CMD_INFO_HEADER(CMD_FOOTER + "" + COLOR_MAIN.color() + " Player Analytics - Info"), CMD_INFO_HEADER(CMD_FOOTER.toString() + COLOR_MAIN.color() + " Player Analytics - Info"),
CMD_INFO_VERSION(CMD_BALL + "" + COLOR_MAIN.color() + " Version: " + COLOR_SEC.color() + REPLACE0), CMD_INFO_VERSION(CMD_BALL.toString() + COLOR_MAIN.color() + " Version: " + COLOR_SEC.color() + REPLACE0),
CMD_SEARCH_HEADER(CMD_FOOTER + "" + COLOR_MAIN.color() + " Player Analytics - Search results for: "), CMD_SEARCH_HEADER(CMD_FOOTER.toString() + COLOR_MAIN.color() + " Player Analytics - Search results for: "),
CMD_SEARCH_SEARCHING(CMD_FOOTER + "" + COLOR_MAIN.color() + " Searching.."), CMD_SEARCH_SEARCHING(CMD_FOOTER.toString() + COLOR_MAIN.color() + " Searching.."),
CMD_HELP_HEADER(CMD_FOOTER + "" + COLOR_MAIN.color() + " Player Analytics - Help"), CMD_HELP_HEADER(CMD_FOOTER.toString() + COLOR_MAIN.color() + " Player Analytics - Help"),
CMD_MANAGE_HELP_HEADER(CMD_FOOTER + "" + COLOR_MAIN.color() + " Player Analytics - Managment Help"), CMD_MANAGE_HELP_HEADER(CMD_FOOTER.toString() + COLOR_MAIN.color() + " Player Analytics - Managment Help"),
CMD_MANAGE_STATUS_HEADER(CMD_FOOTER + "" + COLOR_MAIN.color() + " Player Analytics - Database status"), CMD_MANAGE_STATUS_HEADER(CMD_FOOTER.toString() + COLOR_MAIN.color() + " Player Analytics - Database status"),
CMD_MANAGE_STATUS_ACTIVE_DB(CMD_BALL + "" + COLOR_MAIN.color() + " Active Database: " + COLOR_SEC.color() + "REPLACE0"), CMD_MANAGE_STATUS_ACTIVE_DB(CMD_BALL.toString() + COLOR_MAIN.color() + " Active Database: " + COLOR_SEC.color() + "REPLACE0"),
CMD_MANAGE_STATUS_QUEUE_SAVE(CMD_BALL + "" + COLOR_MAIN.color() + " Save Queue Size: " + COLOR_SEC.color() + "REPLACE0/" + Settings.PROCESS_SAVE_LIMIT.getNumber()), CMD_MANAGE_STATUS_QUEUE_SAVE(CMD_BALL.toString() + COLOR_MAIN.color() + " Save Queue Size: " + COLOR_SEC.color() + "REPLACE0/" + Settings.PROCESS_SAVE_LIMIT.getNumber()),
CMD_MANAGE_STATUS_QUEUE_GET(CMD_BALL + "" + COLOR_MAIN.color() + " Get Queue Size: " + COLOR_SEC.color() + "REPLACE0/" + Settings.PROCESS_GET_LIMIT.getNumber()), CMD_MANAGE_STATUS_QUEUE_GET(CMD_BALL.toString() + COLOR_MAIN.color() + " Get Queue Size: " + COLOR_SEC.color() + "REPLACE0/" + Settings.PROCESS_GET_LIMIT.getNumber()),
CMD_MANAGE_STATUS_QUEUE_CLEAR(CMD_BALL + "" + COLOR_MAIN.color() + " Clear Queue Size: " + COLOR_SEC.color() + "REPLACE0/" + Settings.PROCESS_CLEAR_LIMIT.getNumber()), CMD_MANAGE_STATUS_QUEUE_CLEAR(CMD_BALL.toString() + COLOR_MAIN.color() + " Clear Queue Size: " + COLOR_SEC.color() + "REPLACE0/" + Settings.PROCESS_CLEAR_LIMIT.getNumber()),
CMD_MANAGE_STATUS_QUEUE_PROCESS(CMD_BALL + "" + COLOR_MAIN.color() + " Process Queue Size: " + COLOR_SEC.color() + "REPLACE0/20000"), CMD_MANAGE_STATUS_QUEUE_PROCESS(CMD_BALL.toString() + COLOR_MAIN.color() + " Process Queue Size: " + COLOR_SEC.color() + "REPLACE0/20000"),
CMD_CLICK_ME("Click Me"), CMD_CLICK_ME("Click Me"),
CMD_LINK(COLOR_SEC.color() + " " + BALL + COLOR_MAIN.color() + " Link: " + COLOR_TER.color()), CMD_LINK(COLOR_SEC.color() + " " + BALL + COLOR_MAIN.color() + " Link: " + COLOR_TER.color()),
CMD_PASS_PLANLITE("UNUSED"), CMD_PASS_PLANLITE("UNUSED"),
@ -134,7 +135,7 @@ public enum Phrase {
CMD_USG_INFO("View Version of Plan"), CMD_USG_INFO("View Version of Plan"),
CMD_USG_INSPECT("Inspect Player's Data"), CMD_USG_INSPECT("Inspect Player's Data"),
CMD_USG_QINSPECT("QuickInspect Player's Data"), CMD_USG_QINSPECT("QuickInspect Player's Data"),
CMD_USG_MANAGE("Database managment command"), CMD_USG_MANAGE("Database management command"),
CMD_USG_MANAGE_BACKUP("Backup a database to .db file"), CMD_USG_MANAGE_BACKUP("Backup a database to .db file"),
CMD_USG_MANAGE_RESTORE("Restore a database from a backup 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_MOVE("Copy data from one database to another & overwrite values"),
@ -144,7 +145,7 @@ public enum Phrase {
CMD_USG_MANAGE_CLEAN("Clear incorrect data from the database"), CMD_USG_MANAGE_CLEAN("Clear incorrect data from the database"),
CMD_USG_MANAGE_REMOVE("Remove players's data from the Active 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_STATUS("Check the status of the Active Database."),
CMD_USG_MANAGE_HELP("Show managment help."), CMD_USG_MANAGE_HELP("Show management help."),
CMD_USG_MANAGE_HOTSWAP("Hotswap to another database & restart the plugin"), CMD_USG_MANAGE_HOTSWAP("Hotswap to another database & restart the plugin"),
CMD_USG_RELOAD("Reload plugin config & save cached data"), CMD_USG_RELOAD("Reload plugin config & save cached data"),
CMD_USG_SEARCH("Search for player"), CMD_USG_SEARCH("Search for player"),
@ -167,11 +168,11 @@ public enum Phrase {
WARN_OVERWRITE_SOME("Some 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!"), WARN_REMOVE("Data in REPLACE0-database will be removed!"),
// //
COMMAND_SENDER_NOT_PLAYER(ChatColor.RED + "" + PREFIX + "This command can be only used as a player."), COMMAND_SENDER_NOT_PLAYER(ChatColor.RED.toString() + PREFIX + "This command can be only used as a player."),
COMMAND_REQUIRES_ARGUMENTS(ChatColor.RED + "" + PREFIX + "Command requires arguments. REPLACE0"), COMMAND_REQUIRES_ARGUMENTS(ChatColor.RED.toString() + PREFIX + "Command requires arguments. REPLACE0"),
COMMAND_ADD_CONFIRMATION_ARGUMENT(ChatColor.RED + "" + PREFIX + "Add -a to confirm execution! REPLACE0"), COMMAND_ADD_CONFIRMATION_ARGUMENT(ChatColor.RED.toString() + PREFIX + "Add -a to confirm execution! REPLACE0"),
COMMAND_REQUIRES_ARGUMENTS_ONE(ChatColor.RED + "" + PREFIX + "Command requires one argument."), COMMAND_REQUIRES_ARGUMENTS_ONE(ChatColor.RED.toString() + PREFIX + "Command requires one argument."),
COMMAND_NO_PERMISSION(ChatColor.RED + "" + PREFIX + "You do not have the required permmission."), COMMAND_NO_PERMISSION(ChatColor.RED.toString() + PREFIX + "You do not have the required permission."),
ERROR_TOO_SMALL_QUEUE("Queue size is too small! (REPLACE0), change the setting to a higher number! (Currently REPLACE1)"); ERROR_TOO_SMALL_QUEUE("Queue size is too small! (REPLACE0), change the setting to a higher number! (Currently REPLACE1)");
private String text; private String text;
@ -187,6 +188,32 @@ public enum Phrase {
this.text = ""; this.text = "";
} }
static void loadLocale(File localeFile) {
try (Scanner localeScanner = new Scanner(localeFile, "UTF-8")) {
List<String> localeRows = new ArrayList<>();
while (localeScanner.hasNextLine()) {
String line = localeScanner.nextLine();
if (!line.isEmpty()) {
if ("<<<<<<HTML>>>>>>".equals(line)) {
break;
}
localeRows.add(line);
}
}
for (String localeRow : localeRows) {
try {
String[] split = localeRow.split(" <> ");
Phrase.valueOf(split[0]).setText(split[1]);
} catch (IllegalArgumentException e) {
Log.error("There is a miswritten line in locale on line " + localeRows.indexOf(localeRow));
}
}
} catch (IOException e) {
Log.error("Error at Locale Scanning: " + e.getCause());
}
}
@Override @Override
public String toString() { public String toString() {
return text; return text;
@ -241,30 +268,4 @@ public enum Phrase {
public void setColor(char colorCode) { public void setColor(char colorCode) {
this.color = ChatColor.getByChar(colorCode); this.color = ChatColor.getByChar(colorCode);
} }
static void loadLocale(File localeFile) {
try {
Scanner localeScanner = new Scanner(localeFile, "UTF-8");
List<String> localeRows = new ArrayList<>();
while (localeScanner.hasNextLine()) {
String line = localeScanner.nextLine();
if (!line.isEmpty()) {
if ("<<<<<<HTML>>>>>>".equals(line)) {
break;
}
localeRows.add(line);
}
}
for (String localeRow : localeRows) {
try {
String[] split = localeRow.split(" <> ");
Phrase.valueOf(split[0]).setText(split[1]);
} catch (IllegalArgumentException e) {
Log.error("There is a miswritten line in locale on line " + localeRows.indexOf(localeRow));
}
}
} catch (IOException e) {
}
}
} }

View File

@ -32,27 +32,30 @@ 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.AnalysisCacheHandler;
import main.java.com.djrapitops.plan.data.cache.DataCacheHandler; 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.InspectCacheHandler;
import main.java.com.djrapitops.plan.data.cache.PageCacheHandler;
import main.java.com.djrapitops.plan.data.listeners.*; import main.java.com.djrapitops.plan.data.listeners.*;
import main.java.com.djrapitops.plan.database.Database; import main.java.com.djrapitops.plan.database.Database;
import main.java.com.djrapitops.plan.database.databases.MySQLDB; import main.java.com.djrapitops.plan.database.databases.MySQLDB;
import main.java.com.djrapitops.plan.database.databases.SQLiteDB; import main.java.com.djrapitops.plan.database.databases.SQLiteDB;
import main.java.com.djrapitops.plan.ui.html.Html; import main.java.com.djrapitops.plan.ui.html.Html;
import main.java.com.djrapitops.plan.ui.webserver.WebSocketServer; import main.java.com.djrapitops.plan.ui.webserver.WebServer;
import main.java.com.djrapitops.plan.utilities.Benchmark; import main.java.com.djrapitops.plan.utilities.Benchmark;
import main.java.com.djrapitops.plan.utilities.Check; import main.java.com.djrapitops.plan.utilities.Check;
import main.java.com.djrapitops.plan.utilities.MiscUtils; import main.java.com.djrapitops.plan.utilities.MiscUtils;
import main.java.com.djrapitops.plan.utilities.metrics.BStats; import main.java.com.djrapitops.plan.utilities.metrics.BStats;
import org.bukkit.Bukkit; import org.apache.logging.log4j.LogManager;
import java.io.*; import java.io.*;
import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
/** /**
* Main class for Bukkit that manages the plugin. * Main class for Bukkit that manages the plugin.
* * <p>
* Everything can be accessed through this class. Use Plan.getInstance() to get * Everything can be accessed through this class. Use Plan.getInstance() to get
* the initialised instance of Plan. * the initialised instance of Plan.
* *
@ -71,14 +74,38 @@ public class Plan extends BukkitPlugin<Plan> {
private Database db; private Database db;
private HashSet<Database> databases; private HashSet<Database> databases;
private WebSocketServer uiServer; private WebServer uiServer;
private ServerVariableHolder serverVariableHolder; private ServerVariableHolder serverVariableHolder;
private int bootAnalysisTaskID = -1; private int bootAnalysisTaskID = -1;
/** /**
* OnEnable method. * Used to get the PlanAPI. @see API
* *
* @return API of the current instance of Plan.
* @throws IllegalStateException If onEnable method has not been called on
* Plan and the instance is null.
*/
public static API getPlanAPI() throws IllegalStateException {
Plan instance = getInstance();
if (instance == null) {
throw new IllegalStateException("Plugin not enabled properly, Singleton instance is null.");
}
return instance.api;
}
/**
* Used to get the plugin-instance singleton.
*
* @return this object.
*/
public static Plan getInstance() {
return (Plan) getPluginInstance(Plan.class);
}
/**
* OnEnable method.
* <p>
* - Enables the plugin's subsystems. * - Enables the plugin's subsystems.
*/ */
@Override @Override
@ -103,13 +130,13 @@ public class Plan extends BukkitPlugin<Plan> {
Benchmark.start("Enable: Copy default config"); Benchmark.start("Enable: Copy default config");
getConfig().options().copyDefaults(true); getConfig().options().copyDefaults(true);
getConfig().options().header(Phrase.CONFIG_HEADER + ""); getConfig().options().header(Phrase.CONFIG_HEADER.toString());
saveConfig(); saveConfig();
Benchmark.stop("Enable: Copy default config"); Benchmark.stop("Enable: Copy default config");
Benchmark.start("Enable: Init Database"); Benchmark.start("Enable: Init Database");
Log.info(Phrase.DB_INIT + ""); Log.info(Phrase.DB_INIT.toString());
if (Check.isTrue_Error(initDatabase(), Phrase.DB_FAILURE_DISABLE.toString())) { if (Check.ErrorIfFalse(initDatabase(), Phrase.DB_FAILURE_DISABLE.toString())) {
Log.info(Phrase.DB_ESTABLISHED.parse(db.getConfigName())); Log.info(Phrase.DB_ESTABLISHED.parse(db.getConfigName()));
} else { } else {
disablePlugin(); disablePlugin();
@ -154,15 +181,19 @@ public class Plan extends BukkitPlugin<Plan> {
boolean hasDataViewCapability = usingAlternativeIP || usingAlternativeUI || webserverIsEnabled; boolean hasDataViewCapability = usingAlternativeIP || usingAlternativeUI || webserverIsEnabled;
if (webserverIsEnabled) { if (webserverIsEnabled) {
uiServer = new WebSocketServer(this); uiServer = new WebServer(this);
uiServer.initServer(); uiServer.initServer();
// Prevent passwords showing up on console.
Bukkit.getLogger().setFilter(new RegisterCommandFilter()); if (!uiServer.isEnabled()) {
Log.error("WebServer was not successfully initialized.");
}
setupFilter();
} else if (!hasDataViewCapability) { } else if (!hasDataViewCapability) {
Log.infoColor(Phrase.ERROR_NO_DATA_VIEW + ""); Log.infoColor(Phrase.ERROR_NO_DATA_VIEW.toString());
} }
if (!usingAlternativeIP && serverVariableHolder.getIp().isEmpty()) { if (!usingAlternativeIP && serverVariableHolder.getIp().isEmpty()) {
Log.infoColor(Phrase.NOTIFY_EMPTY_IP + ""); Log.infoColor(Phrase.NOTIFY_EMPTY_IP.toString());
} }
Benchmark.stop("Enable: WebServer Initialization"); Benchmark.stop("Enable: WebServer Initialization");
@ -176,64 +207,73 @@ public class Plan extends BukkitPlugin<Plan> {
bStats.registerMetrics(); bStats.registerMetrics();
Log.debug("Verbose debug messages are enabled."); Log.debug("Verbose debug messages are enabled.");
Log.info(Phrase.ENABLED + ""); Log.info(Phrase.ENABLED.toString());
processStatus().finishExecution("Enable"); processStatus().finishExecution("Enable");
} }
/** /**
* Disables the plugin. * Disables the plugin.
* * <p>
* Stops the webserver, cancels all tasks and saves cache to the database. * Stops the webserver, cancels all tasks and saves cache to the database.
*/ */
@Override @Override
public void onDisable() { public void onDisable() {
//Clears the page cache
PageCacheHandler.clearCache();
// Stop the UI Server // Stop the UI Server
if (uiServer != null) { if (uiServer != null) {
uiServer.stop(); uiServer.stop();
} }
getServer().getScheduler().cancelTasks(this); getServer().getScheduler().cancelTasks(this);
if (Verify.notNull(handler, db)) { if (Verify.notNull(handler, db)) {
Benchmark.start("Disable: DataCache Save"); Benchmark.start("Disable: DataCache Save");
// Saves the DataCache to the database without Bukkit's Schedulers. // Saves the DataCache to the database without Bukkit's Schedulers.
Log.info(Phrase.CACHE_SAVE + ""); Log.info(Phrase.CACHE_SAVE.toString());
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.execute(() -> { scheduler.execute(() -> {
handler.saveCacheOnDisable(); handler.saveCacheOnDisable();
taskStatus().cancelAllKnownTasks(); taskStatus().cancelAllKnownTasks();
Benchmark.stop("Disable: DataCache Save"); Benchmark.stop("Disable: DataCache Save");
}); });
scheduler.shutdown(); // Schedules the save to shutdown after it has ran the execute method.
scheduler.shutdown(); // Schedules the save to shutdown after it has ran the execute method.
} }
Log.info(Phrase.DISABLED + "");
Log.info(Phrase.DISABLED.toString());
} }
private void registerListeners() { private void registerListeners() {
Benchmark.start("Enable: Register Listeners"); Benchmark.start("Enable: Register Listeners");
registerListener(new PlanPlayerListener(this)); registerListener(new PlanPlayerListener(this));
boolean chatListenerIsEnabled = Check.isTrue(Settings.GATHERCHAT.isTrue(), Phrase.NOTIFY_DISABLED_CHATLISTENER + ""); boolean chatListenerIsEnabled = Check.isTrue(Settings.GATHERCHAT.isTrue(), Phrase.NOTIFY_DISABLED_CHATLISTENER.toString());
boolean gamemodeChangeListenerIsEnabled = Check.isTrue(Settings.GATHERGMTIMES.isTrue(), Phrase.NOTIFY_DISABLED_GMLISTENER + ""); boolean commandListenerIsEnabled = Check.isTrue(Settings.GATHERCOMMANDS.isTrue(), Phrase.NOTIFY_DISABLED_COMMANDLISTENER.toString());
boolean commandListenerIsEnabled = Check.isTrue(Settings.GATHERCOMMANDS.isTrue(), Phrase.NOTIFY_DISABLED_COMMANDLISTENER + ""); boolean deathListenerIsEnabled = Check.isTrue(Settings.GATHERKILLS.isTrue(), Phrase.NOTIFY_DISABLED_DEATHLISTENER.toString());
boolean deathListenerIsEnabled = Check.isTrue(Settings.GATHERKILLS.isTrue(), Phrase.NOTIFY_DISABLED_DEATHLISTENER + "");
if (chatListenerIsEnabled) { if (chatListenerIsEnabled) {
registerListener(new PlanChatListener(this)); registerListener(new PlanChatListener(this));
} }
if (gamemodeChangeListenerIsEnabled) {
registerListener(new PlanGamemodeChangeListener(this)); registerListener(new PlanGamemodeChangeListener(this));
} registerListener(new PlanWorldChangeListener(this));
if (commandListenerIsEnabled) { if (commandListenerIsEnabled) {
registerListener(new PlanCommandPreprocessListener(this)); registerListener(new PlanCommandPreprocessListener(this));
} }
if (deathListenerIsEnabled) { if (deathListenerIsEnabled) {
registerListener(new PlanDeathEventListener(this)); registerListener(new PlanDeathEventListener(this));
} }
Benchmark.stop("Enable: Register Listeners"); Benchmark.stop("Enable: Register Listeners");
} }
/** /**
* Initializes the database according to settings in the config. * Initializes the database according to settings in the config.
* * <p>
* If database connection can not be established plugin is disabled. * If database connection can not be established plugin is disabled.
* *
* @return true if init was successful, false if not. * @return true if init was successful, false if not.
@ -243,7 +283,7 @@ public class Plan extends BukkitPlugin<Plan> {
databases.add(new MySQLDB(this)); databases.add(new MySQLDB(this));
databases.add(new SQLiteDB(this)); databases.add(new SQLiteDB(this));
String dbType = (Settings.DB_TYPE + "").toLowerCase().trim(); String dbType = Settings.DB_TYPE.toString().toLowerCase().trim();
for (Database database : databases) { for (Database database : databases) {
String databaseType = database.getConfigName().toLowerCase().trim(); String databaseType = database.getConfigName().toLowerCase().trim();
@ -253,11 +293,13 @@ public class Plan extends BukkitPlugin<Plan> {
break; break;
} }
} }
if (!Verify.notNull(db)) { if (!Verify.notNull(db)) {
Log.info(Phrase.DB_TYPE_DOES_NOT_EXIST.toString() + " " + dbType); Log.info(Phrase.DB_TYPE_DOES_NOT_EXIST.toString() + " " + dbType);
return false; return false;
} }
return Check.isTrue_Error(db.init(), Phrase.DB_FAILURE_DISABLE.toString());
return Check.ErrorIfFalse(db.init(), Phrase.DB_FAILURE_DISABLE.toString());
} }
private void startAnalysisRefreshTask(int everyXMinutes) throws IllegalStateException { private void startAnalysisRefreshTask(int everyXMinutes) throws IllegalStateException {
@ -269,9 +311,7 @@ public class Plan extends BukkitPlugin<Plan> {
@Override @Override
public void run() { public void run() {
Log.debug("Running PeriodicalAnalysisTask"); Log.debug("Running PeriodicalAnalysisTask");
if (!analysisCache.isCached()) { if (!analysisCache.isCached() || MiscUtils.getTime() - analysisCache.getData().getRefreshDate() > TimeAmount.MINUTE.ms()) {
analysisCache.updateCache();
} else if (MiscUtils.getTime() - analysisCache.getData().getRefreshDate() > TimeAmount.MINUTE.ms()) {
analysisCache.updateCache(); analysisCache.updateCache();
} }
} }
@ -300,10 +340,14 @@ public class Plan extends BukkitPlugin<Plan> {
*/ */
public void writeNewLocaleFile() { public void writeNewLocaleFile() {
File genLocale = new File(getDataFolder(), "locale_EN.txt"); File genLocale = new File(getDataFolder(), "locale_EN.txt");
try { try (
genLocale.createNewFile();
FileWriter fw = new FileWriter(genLocale, true); FileWriter fw = new FileWriter(genLocale, true);
PrintWriter pw = new PrintWriter(fw); PrintWriter pw = new PrintWriter(fw)
) {
if (genLocale.createNewFile()) {
Log.debug(genLocale.getAbsoluteFile() + " created");
}
for (Phrase p : Phrase.values()) { for (Phrase p : Phrase.values()) {
pw.println(p.name() + " <> " + p.parse()); pw.println(p.name() + " <> " + p.parse());
pw.flush(); pw.flush();
@ -319,41 +363,83 @@ public class Plan extends BukkitPlugin<Plan> {
} }
private void initLocale() { private void initLocale() {
String defaultLocale = "Default: EN";
String locale = Settings.LOCALE.toString().toUpperCase(); String locale = Settings.LOCALE.toString().toUpperCase();
Benchmark.start("Enable: Initializing locale"); Benchmark.start("Enable: Initializing locale");
File localeFile = new File(getDataFolder(), "locale.txt"); File localeFile = new File(getDataFolder(), "locale.txt");
boolean skipLoc = false;
String usingLocale = ""; String usingLocale;
if (localeFile.exists()) { if (localeFile.exists()) {
Phrase.loadLocale(localeFile); Phrase.loadLocale(localeFile);
Html.loadLocale(localeFile); Html.loadLocale(localeFile);
skipLoc = true;
usingLocale = "locale.txt"; stopInitLocale(defaultLocale);
return;
} }
if (!locale.equals("DEFAULT")) {
if (locale.equals("DEFAULT")) {
stopInitLocale(defaultLocale);
return;
}
String urlString = "https://raw.githubusercontent.com/Rsl1122/Plan-PlayerAnalytics/master/Plan/localization/locale_" + locale + ".txt";
URL localeURL;
try { try {
if (!skipLoc) { localeURL = new URL(urlString);
URL localeURL = new URL("https://raw.githubusercontent.com/Rsl1122/Plan-PlayerAnalytics/master/Plan/localization/locale_" + locale + ".txt"); } catch (MalformedURLException e) {
InputStream inputStream = localeURL.openStream(); Log.error("Error at parsing \"" + urlString + "\" to an URL"); //Shouldn't ever happen
OutputStream outputStream = new FileOutputStream(localeFile);
stopInitLocale(defaultLocale);
return;
}
try (InputStream inputStream = localeURL.openStream();
OutputStream outputStream = new FileOutputStream(localeFile)) {
int read; int read;
byte[] bytes = new byte[1024]; byte[] bytes = new byte[1024];
while ((read = inputStream.read(bytes)) != -1) { while ((read = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, read); outputStream.write(bytes, 0, read);
} }
Phrase.loadLocale(localeFile); Phrase.loadLocale(localeFile);
Html.loadLocale(localeFile); Html.loadLocale(localeFile);
usingLocale = locale; usingLocale = locale;
localeFile.delete();
if (localeFile.delete()) {
Log.debug(localeFile.getAbsoluteFile() + " (Locale File) deleted");
} }
stopInitLocale(usingLocale);
} catch (FileNotFoundException ex) { } catch (FileNotFoundException ex) {
Log.error("Attempted using locale that doesn't exist."); Log.error("Attempted using locale that doesn't exist.");
usingLocale = "Default: EN";
stopInitLocale(defaultLocale);
} catch (IOException e) { } catch (IOException e) {
Log.error("Error at loading locale from GitHub, using default locale.");
stopInitLocale(defaultLocale);
} }
} else {
usingLocale = "Default: EN";
} }
/**
* 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());
}
/**
* Stops initializing the locale
*
* @param usingLocale The locale that's used
* @implNote Removes clutter in the method
*/
private void stopInitLocale(String usingLocale) {
Benchmark.stop("Enable: Initializing locale"); Benchmark.stop("Enable: Initializing locale");
Log.info("Using locale: " + usingLocale); Log.info("Using locale: " + usingLocale);
} }
@ -399,7 +485,7 @@ public class Plan extends BukkitPlugin<Plan> {
* *
* @return the Webserver * @return the Webserver
*/ */
public WebSocketServer getUiServer() { public WebServer getUiServer() {
return uiServer; return uiServer;
} }
@ -414,12 +500,12 @@ public class Plan extends BukkitPlugin<Plan> {
/** /**
* Used to get all possible database objects. * Used to get all possible database objects.
* * <p>
* #init() might need to be called in order for the object to function. * #init() might need to be called in order for the object to function.
* *
* @return Set containing the SqLite and MySQL objects. * @return Set containing the SqLite and MySQL objects.
*/ */
public HashSet<Database> getDatabases() { public Set<Database> getDatabases() {
return databases; return databases;
} }
@ -446,35 +532,11 @@ public class Plan extends BukkitPlugin<Plan> {
/** /**
* Old method for getting the API. * Old method for getting the API.
* *
* @deprecated Use Plan.getPlanAPI() (static method) instead.
* @return the Plan API. * @return the Plan API.
* @deprecated Use Plan.getPlanAPI() (static method) instead.
*/ */
@Deprecated @Deprecated
public API getAPI() { public API getAPI() {
return api; return api;
} }
/**
* Used to get the PlanAPI. @see API
*
* @return API of the current instance of Plan.
* @throws IllegalStateException If onEnable method has not been called on
* Plan and the instance is null.
*/
public static API getPlanAPI() throws IllegalStateException {
Plan instance = getInstance();
if (instance == null) {
throw new IllegalStateException("Plugin not enabled properly, Singleton instance is null.");
}
return instance.api;
}
/**
* Used to get the plugin-instance singleton.
*
* @return this object.
*/
public static Plan getInstance() {
return (Plan) getPluginInstance(Plan.class);
}
} }

View File

@ -11,7 +11,6 @@ import org.bukkit.Server;
*/ */
public class ServerVariableHolder { public class ServerVariableHolder {
private final int maxPlayers;
private final String ip; private final String ip;
private final boolean usingPaper; private final boolean usingPaper;
@ -21,18 +20,11 @@ public class ServerVariableHolder {
* @param server instance the plugin is running on. * @param server instance the plugin is running on.
*/ */
public ServerVariableHolder(Server server) { public ServerVariableHolder(Server server) {
maxPlayers = server.getMaxPlayers();
ip = server.getIp(); ip = server.getIp();
usingPaper = server.getName().equals("Paper");
}
/** String serverName = server.getName();
* Maximum amount of players defined in server.properties. usingPaper = serverName.equals("Paper")
* || serverName.equals("TacoSpigot"); //Fork of Paper
* @return number.
*/
public int getMaxPlayers() {
return maxPlayers;
} }
/** /**

View File

@ -15,18 +15,15 @@ public enum Settings {
ANALYSIS_REFRESH_ON_ENABLE("Settings.Cache.AnalysisCache.RefreshAnalysisCacheOnEnable"), ANALYSIS_REFRESH_ON_ENABLE("Settings.Cache.AnalysisCache.RefreshAnalysisCacheOnEnable"),
ANALYSIS_LOG_TO_CONSOLE("Settings.Analysis.LogProgressOnConsole"), ANALYSIS_LOG_TO_CONSOLE("Settings.Analysis.LogProgressOnConsole"),
ANALYSIS_LOG_FINISHED("Settings.Analysis.NotifyWhenFinished"), ANALYSIS_LOG_FINISHED("Settings.Analysis.NotifyWhenFinished"),
ANALYSIS_REMOVE_OUTLIERS("Settings.Analysis.RemoveOutliersFromVisualization"),
ANALYSIS_EXPORT("Settings.Analysis.Export.Enabled"), ANALYSIS_EXPORT("Settings.Analysis.Export.Enabled"),
SHOW_ALTERNATIVE_IP("Settings.WebServer.ShowAlternativeServerIP"), SHOW_ALTERNATIVE_IP("Settings.WebServer.ShowAlternativeServerIP"),
USE_ALTERNATIVE_UI("Settings.UseTextUI"), USE_ALTERNATIVE_UI("Settings.UseTextUI"),
GATHERCHAT("Settings.Data.ChatListener"), GATHERCHAT("Settings.Data.ChatListener"),
GATHERKILLS("Settings.Data.GatherKillData"), GATHERKILLS("Settings.Data.GatherKillData"),
GATHERGMTIMES("Settings.Data.GamemodeChangeListener"),
GATHERCOMMANDS("Settings.Data.GatherCommandUsage"), GATHERCOMMANDS("Settings.Data.GatherCommandUsage"),
DO_NOT_LOG_UNKNOWN_COMMANDS("Customization.Data.DoNotLogUnknownCommands"), DO_NOT_LOG_UNKNOWN_COMMANDS("Customization.Data.DoNotLogUnknownCommands"),
COMBINE_COMMAND_ALIASES_TO_MAIN_COMMAND("Customization.Data.CombineCommandAliasesToMainCommand"), COMBINE_COMMAND_ALIASES_TO_MAIN_COMMAND("Customization.Data.CombineCommandAliasesToMainCommand"),
SECURITY_IP_UUID("Settings.WebServer.Security.DisplayIPsAndUUIDs"), SECURITY_IP_UUID("Settings.WebServer.Security.DisplayIPsAndUUIDs"),
GRAPH_PLAYERS_USEMAXPLAYERS_SCALE("Customization.Graphs.PlayersOnlineGraph.UseMaxPlayersAsScale"),
PLAYERLIST_SHOW_IMAGES("Customization.SmallHeadImagesOnAnalysisPlayerlist"), PLAYERLIST_SHOW_IMAGES("Customization.SmallHeadImagesOnAnalysisPlayerlist"),
// Integer // Integer
ANALYSIS_MINUTES_FOR_ACTIVE("Settings.Analysis.MinutesPlayedUntilConsidiredActive"), ANALYSIS_MINUTES_FOR_ACTIVE("Settings.Analysis.MinutesPlayedUntilConsidiredActive"),
@ -49,7 +46,11 @@ public enum Settings {
LOCALE("Settings.Locale"), LOCALE("Settings.Locale"),
WEBSERVER_IP("Settings.WebServer.InternalIP"), WEBSERVER_IP("Settings.WebServer.InternalIP"),
ANALYSIS_EXPORT_PATH("Settings.Analysis.Export.DestinationFolder"), ANALYSIS_EXPORT_PATH("Settings.Analysis.Export.DestinationFolder"),
LINK_PROTOCOL("Settings.WebServer.LinkProtocol"), 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"),
// //
SERVER_NAME("Customization.ServerName"), SERVER_NAME("Customization.ServerName"),
// //
@ -72,7 +73,6 @@ public enum Settings {
HCOLOR_TER("Customization.Colors.HTML.UI.Tertiary"), HCOLOR_TER("Customization.Colors.HTML.UI.Tertiary"),
HCOLOR_TER_DARK("Customization.Colors.HTML.UI.TertiaryDark"), HCOLOR_TER_DARK("Customization.Colors.HTML.UI.TertiaryDark"),
HCOLOR_ACT_ONL("Customization.Colors.HTML.ActivityGraph.OnlinePlayers"), HCOLOR_ACT_ONL("Customization.Colors.HTML.ActivityGraph.OnlinePlayers"),
HCOLOR_ACT_ONL_FILL("Customization.Colors.HTML.ActivityGraph.OnlinePlayersFill"),
HCOLOR_ACTP_ACT("Customization.Colors.HTML.ActivityPie.Active"), HCOLOR_ACTP_ACT("Customization.Colors.HTML.ActivityPie.Active"),
HCOLOR_ACTP_BAN("Customization.Colors.HTML.ActivityPie.Banned"), HCOLOR_ACTP_BAN("Customization.Colors.HTML.ActivityPie.Banned"),
HCOLOR_ACTP_INA("Customization.Colors.HTML.ActivityPie.Inactive"), HCOLOR_ACTP_INA("Customization.Colors.HTML.ActivityPie.Inactive"),

View File

@ -12,7 +12,7 @@ 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.cache.DBCallableProcessor;
import main.java.com.djrapitops.plan.data.handling.info.HandlingInfo; 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.html.DataRequestHandler;
import main.java.com.djrapitops.plan.ui.webserver.WebSocketServer; import main.java.com.djrapitops.plan.ui.webserver.WebServer;
import main.java.com.djrapitops.plan.utilities.HtmlUtils; import main.java.com.djrapitops.plan.utilities.HtmlUtils;
import java.sql.SQLException; import java.sql.SQLException;
@ -25,20 +25,20 @@ import java.util.stream.Collectors;
/** /**
* This class contains the API methods. * This class contains the API methods.
* * <p>
* Methods can be called from Asynchronous task and are thread safe unless * Methods can be called from Asynchronous task and are thread safe unless
* otherwise stated. * otherwise stated.
* * <p>
* Use Plan.getPlanAPI() to get the API. * Use Plan.getPlanAPI() to get the API.
* * <p>
* More information about API methods can be found on GitHub. * More information about API methods can be found on GitHub.
* *
* @author Rsl1122 * @author Rsl1122
* @since 2.0.0
* @see PluginData * @see PluginData
* @see AnalysisType * @see AnalysisType
* @see DBCallableProcessor * @see DBCallableProcessor
* @see HandlingInfo * @see HandlingInfo
* @since 2.0.0
*/ */
public class API { public class API {
@ -65,7 +65,7 @@ public class API {
/** /**
* Add a source of plugin data to the Plugins tab on Analysis and/or Inspect * Add a source of plugin data to the Plugins tab on Analysis and/or Inspect
* page. * page.
* * <p>
* Refer to documentation on GitHub or Javadoc of PluginData to set-up a * Refer to documentation on GitHub or Javadoc of PluginData to set-up a
* data source that extends PluginData correctly. * data source that extends PluginData correctly.
* *
@ -81,15 +81,15 @@ public class API {
/** /**
* Used to get the link to InspectPage of a player. * Used to get the link to InspectPage of a player.
* * <p>
* This method is useful if you have a table and want to link to the inspect * This method is useful if you have a table and want to link to the inspect
* page. * page.
* <p>
* Html.LINK.parse("Link", "PlayerName") can be used to get a link
* {@code <a href="Link">PlayerName</a>}
* *
* Html.LINK.parse("Link", "Playername") can be used to get a link * @param name Name of the player
* {@code <a href="Link">Playername</a>} * @return ip:port/security/player/PlayerName
*
* @param name Playername of the player
* @return ip:port/security/player/Playername
*/ */
public String getPlayerInspectPageLink(String name) { public String getPlayerInspectPageLink(String name) {
return HtmlUtils.getInspectUrlWithProtocol(name); return HtmlUtils.getInspectUrlWithProtocol(name);
@ -98,7 +98,7 @@ public class API {
/** /**
* Schedule a UserData object to be fetched from the database or cache if * Schedule a UserData object to be fetched from the database or cache if
* the player is online. * the player is online.
* * <p>
* The data will not be cached if it is not already cached. * The data will not be cached if it is not already cached.
* *
* @param uuid UUID of the player. * @param uuid UUID of the player.
@ -111,7 +111,7 @@ public class API {
/** /**
* Schedule a HandlingInfo object to be processed. * Schedule a HandlingInfo object to be processed.
* * <p>
* UserData associated with the UUID of the HandlingInfo object will be * UserData associated with the UUID of the HandlingInfo object will be
* cached. * cached.
* *
@ -123,7 +123,7 @@ public class API {
/** /**
* Used to cache a UserData object. * Used to cache a UserData object.
* * <p>
* If data is already cached it will be overridden. * If data is already cached it will be overridden.
* *
* @param data UserData object. Will be placed to the data.getUuid() key in * @param data UserData object. Will be placed to the data.getUuid() key in
@ -135,7 +135,7 @@ public class API {
/** /**
* Used to save the cached data to the database. * Used to save the cached data to the database.
* * <p>
* Should be only called from an Asynchronous thread. * Should be only called from an Asynchronous thread.
*/ */
public void saveCachedData() { public void saveCachedData() {
@ -154,7 +154,7 @@ public class API {
/** /**
* Cache the UserData to InspectCache. * Cache the UserData to InspectCache.
* * <p>
* Uses cache if data is cached or database if not. Call from an Asynchronous * Uses cache if data is cached or database if not. Call from an Asynchronous
* thread. * thread.
* *
@ -166,14 +166,14 @@ public class API {
/** /**
* Used to get the full Html of the Inspect page as a string. * Used to get the full Html of the Inspect page as a string.
* * <p>
* Check if the data is cached to InspectCache before calling this. * Check if the data is cached to InspectCache before calling this.
* *
* @param uuid UUID of the player. * @param uuid UUID of the player.
* @return player.html with all placeholders replaced. * @return player.html with all placeholders replaced.
*/ */
public String getPlayerHtmlAsString(UUID uuid) { public String getPlayerHtmlAsString(UUID uuid) {
WebSocketServer server = plugin.getUiServer(); WebServer server = plugin.getUiServer();
if (Verify.notNull(server)) { if (Verify.notNull(server)) {
return server.getDataReqHandler().getInspectHtml(uuid); return server.getDataReqHandler().getInspectHtml(uuid);
} }
@ -193,7 +193,7 @@ public class API {
/** /**
* Run's the analysis with the current data in the cache and fetches rest * Run's the analysis with the current data in the cache and fetches rest
* from the database. * from the database.
* * <p>
* Starts a new Asynchronous task to run the analysis. * Starts a new Asynchronous task to run the analysis.
*/ */
public void updateAnalysisCache() { public void updateAnalysisCache() {
@ -202,13 +202,13 @@ public class API {
/** /**
* Used to get the full HTML of the Analysis page as a string. * Used to get the full HTML of the Analysis page as a string.
* * <p>
* Check if the data is cached to AnalysisCache before calling this. * Check if the data is cached to AnalysisCache before calling this.
* *
* @return analysis.html with all placeholders replaced. * @return analysis.html with all placeholders replaced.
*/ */
public String getAnalysisHtmlAsString() { public String getAnalysisHtmlAsString() {
WebSocketServer server = plugin.getUiServer(); WebServer server = plugin.getUiServer();
if (Verify.notNull(server)) { if (Verify.notNull(server)) {
return server.getDataReqHandler().getAnalysisHtml(); return server.getDataReqHandler().getAnalysisHtml();
} }
@ -218,7 +218,7 @@ public class API {
/** /**
* Used to get the AnalysisData object. * Used to get the AnalysisData object.
* * <p>
* Check if the data is cached to AnalysisCache before calling this. * Check if the data is cached to AnalysisCache before calling this.
* *
* @return AnalysisData object. * @return AnalysisData object.
@ -229,10 +229,10 @@ public class API {
} }
/** /**
* Used to get the playerName of a player who has played on the server. * Used to get the PlayerName of a player who has played on the server.
* *
* @param uuid UUID of the player. * @param uuid UUID of the player.
* @return Playername, eg "Rsl1122" * @return PlayerName, eg "Rsl1122"
* @throws IllegalArgumentException If uuid is null. * @throws IllegalArgumentException If uuid is null.
* @throws IllegalStateException If the player has not played on the server * @throws IllegalStateException If the player has not played on the server
* before. * before.
@ -253,13 +253,13 @@ public class API {
* @return UUID of the Player * @return UUID of the Player
* @throws Exception if player's name is not registered at Mojang * @throws Exception if player's name is not registered at Mojang
*/ */
public UUID playerNameToUUID(String playerName) throws Exception { public UUID PlayerNameToUUID(String playerName) throws Exception {
return UUIDFetcher.getUUIDOf(playerName); return UUIDFetcher.getUUIDOf(playerName);
} }
/** /**
* Get the saved UUIDs in the database. * Get the saved UUIDs in the database.
* * <p>
* Should be called from async thread. * Should be called from async thread.
* *
* @return Collection of UUIDs that can be found in the database. * @return Collection of UUIDs that can be found in the database.
@ -272,9 +272,9 @@ public class API {
/** /**
* Get the saved UserData in the database for a collection of UUIDs. * Get the saved UserData in the database for a collection of UUIDs.
* * <p>
* Will not contain data for UUIDs not found in the database. * Will not contain data for UUIDs not found in the database.
* * <p>
* Should be called from async thread. * Should be called from async thread.
* *
* @param uuids Collection of UUIDs that can be found in the database. * @param uuids Collection of UUIDs that can be found in the database.
@ -288,7 +288,7 @@ public class API {
/** /**
* Get the cached UserData objects in the InspectCache. * Get the cached UserData objects in the InspectCache.
* * <p>
* This can be used with PluginData objects safely to get the data for all * 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 * users in Plan database, because all data is InspectCached before analysis
* begins. * begins.
@ -302,7 +302,7 @@ public class API {
/** /**
* Get the cached UserData objects in the InspectCache in a Map form. * 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 * 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 * users in Plan database, because all data is InspectCached before analysis
* begins. * begins.

View File

@ -14,6 +14,13 @@ import java.util.UUID;
*/ */
public class ConditionUtils { public class ConditionUtils {
/**
* Constructor used to hide the public constructor
*/
private ConditionUtils() {
throw new IllegalStateException("Utility class");
}
/** /**
* Check if the plugin can display the data. * Check if the plugin can display the data.
* *

View File

@ -3,13 +3,14 @@ package main.java.com.djrapitops.plan.command;
import com.djrapitops.plugin.command.CommandType; import com.djrapitops.plugin.command.CommandType;
import com.djrapitops.plugin.command.TreeCommand; import com.djrapitops.plugin.command.TreeCommand;
import com.djrapitops.plugin.command.defaultcmds.StatusCommand; import com.djrapitops.plugin.command.defaultcmds.StatusCommand;
import com.djrapitops.plugin.settings.ColorScheme;
import main.java.com.djrapitops.plan.Permissions; import main.java.com.djrapitops.plan.Permissions;
import main.java.com.djrapitops.plan.Plan; import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.command.commands.*; import main.java.com.djrapitops.plan.command.commands.*;
/** /**
* TreeCommand for the /plan command, and all subcommands. * TreeCommand for the /plan command, and all subcommands.
* * <p>
* Uses the Abstract Plugin Framework for easier command management. * Uses the Abstract Plugin Framework for easier command management.
* *
* @author Rsl1122 * @author Rsl1122
@ -19,7 +20,7 @@ public class PlanCommand extends TreeCommand<Plan> {
/** /**
* CommandExecutor class Constructor. * CommandExecutor class Constructor.
* * <p>
* Initializes Subcommands * Initializes Subcommands
* *
* @param plugin Current instance of Plan * @param plugin Current instance of Plan
@ -27,6 +28,24 @@ public class PlanCommand extends TreeCommand<Plan> {
public PlanCommand(Plan plugin) { public PlanCommand(Plan plugin) {
super(plugin, "plan", CommandType.CONSOLE, "", "", "plan"); super(plugin, "plan", CommandType.CONSOLE, "", "", "plan");
super.setDefaultCommand("inspect"); super.setDefaultCommand("inspect");
setHelp(plugin);
}
private void setHelp(Plan plugin) {
ColorScheme colorScheme = plugin.getColorScheme();
String mCol = colorScheme.getMainColor();
String sCol = colorScheme.getSecondaryColor();
String tCol = colorScheme.getTertiaryColor();
String[] help = new String[]{
mCol + "/plan - Main Command",
tCol + " Used to access all SubCommands & help",
sCol + " /plan - List subcommands",
sCol + " /plan <subcommand> ? - in depth help"
};
setInDepthHelp(help);
} }
@Override @Override

View File

@ -5,21 +5,16 @@ import com.djrapitops.plugin.command.CommandType;
import com.djrapitops.plugin.command.CommandUtils; import com.djrapitops.plugin.command.CommandUtils;
import com.djrapitops.plugin.command.ISender; import com.djrapitops.plugin.command.ISender;
import com.djrapitops.plugin.command.SubCommand; import com.djrapitops.plugin.command.SubCommand;
import com.djrapitops.plugin.settings.ColorScheme;
import com.djrapitops.plugin.task.AbsRunnable; import com.djrapitops.plugin.task.AbsRunnable;
import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.*;
import main.java.com.djrapitops.plan.Permissions;
import main.java.com.djrapitops.plan.Phrase;
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.command.ConditionUtils;
import main.java.com.djrapitops.plan.data.cache.AnalysisCacheHandler; import main.java.com.djrapitops.plan.data.cache.AnalysisCacheHandler;
import main.java.com.djrapitops.plan.ui.text.TextUI; import main.java.com.djrapitops.plan.ui.text.TextUI;
import main.java.com.djrapitops.plan.utilities.Check; import main.java.com.djrapitops.plan.utilities.Check;
import main.java.com.djrapitops.plan.utilities.HtmlUtils; import main.java.com.djrapitops.plan.utilities.HtmlUtils;
import main.java.com.djrapitops.plan.utilities.MiscUtils; import main.java.com.djrapitops.plan.utilities.MiscUtils;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.command.CommandException;
/** /**
* This subcommand is used to run the analysis and access the /server link. * This subcommand is used to run the analysis and access the /server link.
@ -38,9 +33,27 @@ public class AnalyzeCommand extends SubCommand {
* @param plugin Current instance of Plan * @param plugin Current instance of Plan
*/ */
public AnalyzeCommand(Plan plugin) { public AnalyzeCommand(Plan plugin) {
super("analyze, analyse, analysis", CommandType.CONSOLE, Permissions.ANALYZE.getPermission(), Phrase.CMD_USG_ANALYZE.parse()); super("analyze, analyse, analysis, a", CommandType.CONSOLE, Permissions.ANALYZE.getPermission(), Phrase.CMD_USG_ANALYZE.parse());
this.plugin = plugin; this.plugin = plugin;
analysisCache = plugin.getAnalysisCache(); analysisCache = plugin.getAnalysisCache();
setHelp(plugin);
}
private void setHelp(Plan plugin) {
ColorScheme colorScheme = plugin.getColorScheme();
String mCol = colorScheme.getMainColor();
String sCol = colorScheme.getSecondaryColor();
String tCol = colorScheme.getTertiaryColor();
String[] help = new String[]{
mCol + "Analysis Command",
tCol + " Used to Refresh analysis cache & Access the result page",
sCol + " /plan status can be used to check status of analysis while it is running.",
sCol + " Aliases: analyze, analyse, analysis, a"
};
setInDepthHelp(help);
} }
@Override @Override
@ -48,13 +61,14 @@ public class AnalyzeCommand extends SubCommand {
if (!Check.isTrue(ConditionUtils.pluginHasViewCapability(), Phrase.ERROR_WEBSERVER_OFF_ANALYSIS.toString(), sender)) { if (!Check.isTrue(ConditionUtils.pluginHasViewCapability(), Phrase.ERROR_WEBSERVER_OFF_ANALYSIS.toString(), sender)) {
return true; return true;
} }
if (!Check.isTrue(analysisCache.isAnalysisEnabled(), Phrase.ERROR_ANALYSIS_DISABLED_TEMPORARILY.toString(), sender)) {
if (!analysisCache.isCached()) { if (!Check.isTrue(analysisCache.isAnalysisEnabled(), Phrase.ERROR_ANALYSIS_DISABLED_TEMPORARILY.toString(), sender)
&& !analysisCache.isCached()) {
return true; return true;
} }
}
sender.sendMessage(Phrase.GRABBING_DATA_MESSAGE + ""); sender.sendMessage(Phrase.GRABBING_DATA_MESSAGE + "");
if (plugin.getUiServer().isAuthRequired()) {
plugin.getRunnableFactory().createNew(new AbsRunnable("WebUser exist check task") { plugin.getRunnableFactory().createNew(new AbsRunnable("WebUser exist check task") {
@Override @Override
public void run() { public void run() {
@ -72,6 +86,7 @@ public class AnalyzeCommand extends SubCommand {
} }
} }
}).runTaskAsynchronously(); }).runTaskAsynchronously();
}
updateCache(); updateCache();
runMessageSenderTask(sender); runMessageSenderTask(sender);
return true; return true;
@ -110,7 +125,7 @@ public class AnalyzeCommand extends SubCommand {
/** /**
* Used to send the message after /plan analysis. * Used to send the message after /plan analysis.
* * <p>
* Final because * Final because
* *
* @param sender Command sender. * @param sender Command sender.
@ -129,17 +144,9 @@ public class AnalyzeCommand extends SubCommand {
sender.sendMessage(message + url); sender.sendMessage(message + url);
} else { } else {
sender.sendMessage(message); sender.sendMessage(message);
sendLink(sender, url); sender.sendLink(" ", Phrase.CMD_CLICK_ME.toString(), url);
} }
} }
sender.sendMessage(Phrase.CMD_FOOTER + ""); sender.sendMessage(Phrase.CMD_FOOTER.toString());
}
@Deprecated // TODO Will be rewritten to the RslPlugin abstractions in the future.
private void sendLink(ISender sender, String url) throws CommandException {
plugin.getServer().dispatchCommand(
Bukkit.getConsoleSender(),
"tellraw " + sender.getName() + " [\"\",{\"text\":\"" + Phrase.CMD_CLICK_ME + "\",\"underlined\":true,"
+ "\"clickEvent\":{\"action\":\"open_url\",\"value\":\"" + url + "\"}}]");
} }
} }

View File

@ -5,6 +5,7 @@ import com.djrapitops.plugin.command.CommandType;
import com.djrapitops.plugin.command.CommandUtils; import com.djrapitops.plugin.command.CommandUtils;
import com.djrapitops.plugin.command.ISender; import com.djrapitops.plugin.command.ISender;
import com.djrapitops.plugin.command.SubCommand; import com.djrapitops.plugin.command.SubCommand;
import com.djrapitops.plugin.settings.ColorScheme;
import com.djrapitops.plugin.task.AbsRunnable; import com.djrapitops.plugin.task.AbsRunnable;
import com.djrapitops.plugin.utilities.Verify; import com.djrapitops.plugin.utilities.Verify;
import main.java.com.djrapitops.plan.*; import main.java.com.djrapitops.plan.*;
@ -15,9 +16,7 @@ import main.java.com.djrapitops.plan.utilities.Check;
import main.java.com.djrapitops.plan.utilities.HtmlUtils; import main.java.com.djrapitops.plan.utilities.HtmlUtils;
import main.java.com.djrapitops.plan.utilities.MiscUtils; import main.java.com.djrapitops.plan.utilities.MiscUtils;
import main.java.com.djrapitops.plan.utilities.uuid.UUIDUtility; import main.java.com.djrapitops.plan.utilities.uuid.UUIDUtility;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.command.CommandException;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.UUID; import java.util.UUID;
@ -43,6 +42,24 @@ public class InspectCommand extends SubCommand {
this.plugin = plugin; this.plugin = plugin;
inspectCache = plugin.getInspectCache(); inspectCache = plugin.getInspectCache();
setHelp(plugin);
}
private void setHelp(Plan plugin) {
ColorScheme colorScheme = plugin.getColorScheme();
String mCol = colorScheme.getMainColor();
String sCol = colorScheme.getSecondaryColor();
String tCol = colorScheme.getTertiaryColor();
String[] help = new String[]{
mCol + "Inspect command",
tCol + " Used to get a link to User's inspect page.",
sCol + " Own inspect page can be accessed with /plan inspect",
sCol + " Alias: /plan <name>"
};
super.setInDepthHelp(help);
} }
@Override @Override
@ -72,8 +89,8 @@ public class InspectCommand extends SubCommand {
if (!Check.isTrue(plugin.getDB().wasSeenBefore(uuid), Phrase.USERNAME_NOT_KNOWN.toString(), sender)) { if (!Check.isTrue(plugin.getDB().wasSeenBefore(uuid), Phrase.USERNAME_NOT_KNOWN.toString(), sender)) {
return; return;
} }
sender.sendMessage(Phrase.GRABBING_DATA_MESSAGE + ""); sender.sendMessage(Phrase.GRABBING_DATA_MESSAGE.toString());
if (CommandUtils.isPlayer(sender)) { if (CommandUtils.isPlayer(sender) && plugin.getUiServer().isAuthRequired()) {
boolean senderHasWebUser = plugin.getDB().getSecurityTable().userExists(sender.getName()); boolean senderHasWebUser = plugin.getDB().getSecurityTable().userExists(sender.getName());
if (!senderHasWebUser) { if (!senderHasWebUser) {
sender.sendMessage(ChatColor.YELLOW + "[Plan] You might not have a web user, use /plan register <password>"); sender.sendMessage(ChatColor.YELLOW + "[Plan] You might not have a web user, use /plan register <password>");
@ -123,24 +140,16 @@ public class InspectCommand extends SubCommand {
} else { } else {
// Link // Link
String url = HtmlUtils.getInspectUrlWithProtocol(playerName); String url = HtmlUtils.getInspectUrlWithProtocol(playerName);
String message = Phrase.CMD_LINK + ""; String message = Phrase.CMD_LINK.toString();
boolean console = !CommandUtils.isPlayer(sender); boolean console = !CommandUtils.isPlayer(sender);
if (console) { if (console) {
sender.sendMessage(message + url); sender.sendMessage(message + url);
} else { } else {
sender.sendMessage(message); sender.sendMessage(message);
sendLink(sender, url); sender.sendLink(" ", Phrase.CMD_CLICK_ME.toString(), url);
} }
} }
sender.sendMessage(Phrase.CMD_FOOTER + ""); sender.sendMessage(Phrase.CMD_FOOTER.toString());
}
@Deprecated // TODO Will be rewritten to the RslPlugin abstractions in the future.
private void sendLink(ISender sender, String url) throws CommandException {
plugin.getServer().dispatchCommand(
Bukkit.getConsoleSender(),
"tellraw " + sender.getName() + " [\"\",{\"text\":\"" + Phrase.CMD_CLICK_ME + "\",\"underlined\":true,"
+ "\"clickEvent\":{\"action\":\"open_url\",\"value\":\"" + url + "\"}}]");
} }
} }

View File

@ -4,18 +4,17 @@ import com.djrapitops.plugin.command.CommandType;
import com.djrapitops.plugin.command.CommandUtils; import com.djrapitops.plugin.command.CommandUtils;
import com.djrapitops.plugin.command.ISender; import com.djrapitops.plugin.command.ISender;
import com.djrapitops.plugin.command.SubCommand; import com.djrapitops.plugin.command.SubCommand;
import com.djrapitops.plugin.settings.ColorScheme;
import main.java.com.djrapitops.plan.Permissions; import main.java.com.djrapitops.plan.Permissions;
import main.java.com.djrapitops.plan.Phrase; import main.java.com.djrapitops.plan.Phrase;
import main.java.com.djrapitops.plan.Plan; import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.command.ConditionUtils; import main.java.com.djrapitops.plan.command.ConditionUtils;
import main.java.com.djrapitops.plan.utilities.Check; import main.java.com.djrapitops.plan.utilities.Check;
import main.java.com.djrapitops.plan.utilities.HtmlUtils; import main.java.com.djrapitops.plan.utilities.HtmlUtils;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandException;
/** /**
* Command used to display link to the player list webpage. * Command used to display link to the player list webpage.
* * <p>
* Subcommand is not registered if Webserver is not enabled. * Subcommand is not registered if Webserver is not enabled.
* *
* @author Rsl1122 * @author Rsl1122
@ -23,17 +22,32 @@ import org.bukkit.command.CommandException;
*/ */
public class ListCommand extends SubCommand { public class ListCommand extends SubCommand {
private final Plan plugin;
/** /**
* Class Constructor. * Class Constructor.
* *
* @param plugin Current instance of Plan * @param plugin Current instance of Plan
*/ */
public ListCommand(Plan plugin) { public ListCommand(Plan plugin) {
super("list", CommandType.CONSOLE, Permissions.INSPECT_OTHER.getPermission(), "List to all cached players", ""); super("list, pl", CommandType.CONSOLE, Permissions.INSPECT_OTHER.getPermission(), "List to all cached players", "");
this.plugin = plugin; setHelp(plugin);
}
private void setHelp(Plan plugin) {
ColorScheme colorScheme = plugin.getColorScheme();
String mCol = colorScheme.getMainColor();
String sCol = colorScheme.getSecondaryColor();
String tCol = colorScheme.getTertiaryColor();
String[] help = new String[]{
mCol + "List command",
tCol + " Used to get a link to players page.",
sCol + " Players page contains links to all cached inspect pages.",
sCol + " Alias: /plan pl"
};
setInDepthHelp(help);
} }
@Override @Override
@ -50,22 +64,14 @@ public class ListCommand extends SubCommand {
// Link // Link
String url = HtmlUtils.getServerAnalysisUrlWithProtocol().replace("server", "players"); String url = HtmlUtils.getServerAnalysisUrlWithProtocol().replace("server", "players");
String message = Phrase.CMD_LINK + ""; String message = Phrase.CMD_LINK.toString();
boolean console = !CommandUtils.isPlayer(sender); boolean console = !CommandUtils.isPlayer(sender);
if (console) { if (console) {
sender.sendMessage(message + url); sender.sendMessage(message + url);
} else { } else {
sender.sendMessage(message); sender.sendMessage(message);
sendLink(sender, url); sender.sendLink(" ", Phrase.CMD_CLICK_ME.toString(), url);
} }
sender.sendMessage(Phrase.CMD_FOOTER + ""); sender.sendMessage(Phrase.CMD_FOOTER.toString());
}
@Deprecated // TODO Will be rewritten to the RslPlugin abstractions in the future.
private void sendLink(ISender sender, String url) throws CommandException {
plugin.getServer().dispatchCommand(
Bukkit.getConsoleSender(),
"tellraw " + sender.getName() + " [\"\",{\"text\":\"" + Phrase.CMD_CLICK_ME + "\",\"underlined\":true,"
+ "\"clickEvent\":{\"action\":\"open_url\",\"value\":\"" + url + "\"}}]");
} }
} }

View File

@ -2,6 +2,7 @@ package main.java.com.djrapitops.plan.command.commands;
import com.djrapitops.plugin.command.CommandType; import com.djrapitops.plugin.command.CommandType;
import com.djrapitops.plugin.command.TreeCommand; import com.djrapitops.plugin.command.TreeCommand;
import com.djrapitops.plugin.settings.ColorScheme;
import main.java.com.djrapitops.plan.Permissions; import main.java.com.djrapitops.plan.Permissions;
import main.java.com.djrapitops.plan.Phrase; import main.java.com.djrapitops.plan.Phrase;
import main.java.com.djrapitops.plan.Plan; import main.java.com.djrapitops.plan.Plan;
@ -9,7 +10,7 @@ import main.java.com.djrapitops.plan.command.commands.manage.*;
/** /**
* This command is used to manage the database of the plugin. * This command is used to manage the database of the plugin.
* * <p>
* No arguments will run ManageHelpCommand. Contains subcommands. * No arguments will run ManageHelpCommand. Contains subcommands.
* *
* @author Rsl1122 * @author Rsl1122
@ -24,6 +25,25 @@ public class ManageCommand extends TreeCommand<Plan> {
*/ */
public ManageCommand(Plan plugin) { public ManageCommand(Plan plugin) {
super(plugin, "manage,m", CommandType.CONSOLE, Permissions.MANAGE.getPermission(), Phrase.CMD_USG_MANAGE + "", "plan m"); super(plugin, "manage,m", CommandType.CONSOLE, Permissions.MANAGE.getPermission(), Phrase.CMD_USG_MANAGE + "", "plan m");
setHelp(plugin);
}
private void setHelp(Plan plugin) {
ColorScheme colorScheme = plugin.getColorScheme();
String mCol = colorScheme.getMainColor();
String sCol = colorScheme.getSecondaryColor();
String tCol = colorScheme.getTertiaryColor();
String[] help = new String[]{
mCol + "Manage command",
tCol + " Used to Manage Database of the plugin.",
sCol + " Alias: /plan m",
sCol + " /plan m - List subcommands",
sCol + " /plan m <subcommand> ? - in depth help"
};
setInDepthHelp(help);
} }
@Override @Override

View File

@ -4,6 +4,7 @@ import com.djrapitops.plugin.api.TimeAmount;
import com.djrapitops.plugin.command.CommandType; import com.djrapitops.plugin.command.CommandType;
import com.djrapitops.plugin.command.ISender; import com.djrapitops.plugin.command.ISender;
import com.djrapitops.plugin.command.SubCommand; import com.djrapitops.plugin.command.SubCommand;
import com.djrapitops.plugin.settings.ColorScheme;
import com.djrapitops.plugin.task.AbsRunnable; import com.djrapitops.plugin.task.AbsRunnable;
import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Permissions; import main.java.com.djrapitops.plan.Permissions;
@ -33,21 +34,39 @@ public class QuickAnalyzeCommand extends SubCommand {
* @param plugin Current instance of Plan * @param plugin Current instance of Plan
*/ */
public QuickAnalyzeCommand(Plan plugin) { public QuickAnalyzeCommand(Plan plugin) {
super("qanalyze, qanalyse, qanalysis", CommandType.CONSOLE, Permissions.QUICK_ANALYZE.getPermission(), Phrase.CMD_USG_QANALYZE.parse()); super("qanalyze, qanalyse, qanalysis, qa", CommandType.CONSOLE, Permissions.QUICK_ANALYZE.getPermission(), Phrase.CMD_USG_QANALYZE.parse());
this.plugin = plugin; this.plugin = plugin;
analysisCache = plugin.getAnalysisCache(); analysisCache = plugin.getAnalysisCache();
setHelp(plugin);
}
private void setHelp(Plan plugin) {
ColorScheme colorScheme = plugin.getColorScheme();
String mCol = colorScheme.getMainColor();
String sCol = colorScheme.getSecondaryColor();
String tCol = colorScheme.getTertiaryColor();
String[] help = new String[]{
mCol + "Quick Analysis command",
tCol + " Used to get in game info about analysis.",
sCol + " Has less info than full Analysis web page.",
sCol + " Aliases: qanalyze, ganalyse, qanalysis, qa"
};
setInDepthHelp(help);
} }
@Override @Override
public boolean onCommand(ISender sender, String commandLabel, String[] args) { public boolean onCommand(ISender sender, String commandLabel, String[] args) {
if (!Check.isTrue(ConditionUtils.pluginHasViewCapability(), Phrase.ERROR_WEBSERVER_OFF_ANALYSIS + "", sender)) { if (!Check.isTrue(ConditionUtils.pluginHasViewCapability(), Phrase.ERROR_WEBSERVER_OFF_ANALYSIS.toString(), sender)) {
return true; return true;
} }
if (!Check.isTrue(analysisCache.isAnalysisEnabled(), Phrase.ERROR_ANALYSIS_DISABLED_TEMPORARILY + "", sender)) { if (!Check.isTrue(analysisCache.isAnalysisEnabled(), Phrase.ERROR_ANALYSIS_DISABLED_TEMPORARILY.toString(), sender)
if (!analysisCache.isCached()) { && !analysisCache.isCached()) {
return true; return true;
} }
}
updateCache(); updateCache();
runMessageSenderTask(sender); runMessageSenderTask(sender);

View File

@ -4,9 +4,9 @@ import com.djrapitops.plugin.api.TimeAmount;
import com.djrapitops.plugin.command.CommandType; import com.djrapitops.plugin.command.CommandType;
import com.djrapitops.plugin.command.ISender; import com.djrapitops.plugin.command.ISender;
import com.djrapitops.plugin.command.SubCommand; import com.djrapitops.plugin.command.SubCommand;
import com.djrapitops.plugin.settings.ColorScheme;
import com.djrapitops.plugin.task.AbsRunnable; import com.djrapitops.plugin.task.AbsRunnable;
import com.djrapitops.plugin.utilities.Verify; import com.djrapitops.plugin.utilities.Verify;
import java.util.UUID;
import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Permissions; import main.java.com.djrapitops.plan.Permissions;
import main.java.com.djrapitops.plan.Phrase; import main.java.com.djrapitops.plan.Phrase;
@ -18,6 +18,8 @@ import main.java.com.djrapitops.plan.utilities.Check;
import main.java.com.djrapitops.plan.utilities.MiscUtils; import main.java.com.djrapitops.plan.utilities.MiscUtils;
import main.java.com.djrapitops.plan.utilities.uuid.UUIDUtility; 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 * This command is used to cache UserData to InspectCache and to view some of
* the data in game. * the data in game.
@ -36,10 +38,28 @@ public class QuickInspectCommand extends SubCommand {
* @param plugin Current instance of Plan * @param plugin Current instance of Plan
*/ */
public QuickInspectCommand(Plan plugin) { public QuickInspectCommand(Plan plugin) {
super("qinspect", CommandType.CONSOLE_WITH_ARGUMENTS, Permissions.QUICK_INSPECT.getPermission(), Phrase.CMD_USG_QINSPECT + "", Phrase.ARG_PLAYER + ""); super("qinspect, qi", CommandType.CONSOLE_WITH_ARGUMENTS, Permissions.QUICK_INSPECT.getPermission(), Phrase.CMD_USG_QINSPECT + "", Phrase.ARG_PLAYER + "");
this.plugin = plugin; this.plugin = plugin;
inspectCache = plugin.getInspectCache(); inspectCache = plugin.getInspectCache();
setHelp(plugin);
}
private void setHelp(Plan plugin) {
ColorScheme colorScheme = plugin.getColorScheme();
String mCol = colorScheme.getMainColor();
String sCol = colorScheme.getSecondaryColor();
String tCol = colorScheme.getTertiaryColor();
String[] help = new String[]{
mCol + "Quick Inspect command",
tCol + " Used to get some inspect info in game.",
sCol + " Has less info than full Inspect web page.",
sCol + " Alias: /plan qi"
};
setInDepthHelp(help);
} }
@Override @Override

View File

@ -4,6 +4,7 @@ import com.djrapitops.plugin.command.CommandType;
import com.djrapitops.plugin.command.CommandUtils; import com.djrapitops.plugin.command.CommandUtils;
import com.djrapitops.plugin.command.ISender; import com.djrapitops.plugin.command.ISender;
import com.djrapitops.plugin.command.SubCommand; import com.djrapitops.plugin.command.SubCommand;
import com.djrapitops.plugin.settings.ColorScheme;
import com.djrapitops.plugin.task.AbsRunnable; import com.djrapitops.plugin.task.AbsRunnable;
import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Permissions; import main.java.com.djrapitops.plan.Permissions;
@ -17,11 +18,11 @@ import org.bukkit.ChatColor;
/** /**
* Command for registering web users. * Command for registering web users.
* * <p>
* Registers a new webuser to the database. * Registers a new webuser to the database.
* * <p>
* No permission required for self registration. (Constructor string is empty) * No permission required for self registration. (Constructor string is empty)
* * <p>
* plan.webmanage required for registering other users. * plan.webmanage required for registering other users.
* *
* @author Rsl1122 * @author Rsl1122
@ -34,6 +35,24 @@ public class RegisterCommand extends SubCommand {
public RegisterCommand(Plan plugin) { public RegisterCommand(Plan plugin) {
super("register", CommandType.CONSOLE_WITH_ARGUMENTS, "", "Register a user for the webserver", "<password> [name] [access lvl]"); super("register", CommandType.CONSOLE_WITH_ARGUMENTS, "", "Register a user for the webserver", "<password> [name] [access lvl]");
this.plugin = plugin; this.plugin = plugin;
setHelp(plugin);
}
private void setHelp(Plan plugin) {
ColorScheme colorScheme = plugin.getColorScheme();
String mCol = colorScheme.getMainColor();
String sCol = colorScheme.getSecondaryColor();
String tCol = colorScheme.getTertiaryColor();
String[] help = new String[]{
mCol + "Web Register command",
tCol + " Used to register a new user for the webserver.",
sCol + " Registering a user for another player requires " + Permissions.MANAGE_WEB.getPerm() + " permission.",
sCol + " Passwords are hashed with PBKDF2 (64,000 iterations of SHA1) using a cryptographically-random salt."
};
setInDepthHelp(help);
} }
@Override @Override

View File

@ -1,7 +1,14 @@
package main.java.com.djrapitops.plan.command.commands; package main.java.com.djrapitops.plan.command.commands;
import java.util.logging.Filter; import com.google.common.collect.ImmutableSet;
import java.util.logging.LogRecord; import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.Logger;
import org.apache.logging.log4j.core.filter.AbstractFilter;
import org.apache.logging.log4j.message.Message;
import java.util.Set;
/** /**
* Filters out WebUser registration command logs. * Filters out WebUser registration command logs.
@ -9,15 +16,58 @@ import java.util.logging.LogRecord;
* @author Rsl1122 * @author Rsl1122
* @since 3.5.2 * @since 3.5.2
*/ */
public class RegisterCommandFilter implements Filter { public class RegisterCommandFilter extends AbstractFilter {
private final Set<String> censoredCommands = ImmutableSet.of("/plan web register", "/plan webuser register", "/plan register");
@Override @Override
public boolean isLoggable(LogRecord record) { public Result filter(LogEvent event) {
String message = record.getMessage(); if (event == null) {
boolean block = message.contains("command: /plan register") return Result.NEUTRAL;
|| message.contains("command: /plan web register")
|| message.contains("command: /plan webuser register");
return !block;
} }
return validateMessage(event.getMessage());
}
@Override
public Result filter(Logger logger, Level level, Marker marker, Message msg, Throwable t) {
return validateMessage(msg);
}
@Override
public Result filter(Logger logger, Level level, Marker marker, String msg, Object... params) {
return validateMessage(msg);
}
@Override
public Result filter(Logger logger, Level level, Marker marker, Object msg, Throwable t) {
if (msg == null) {
return Result.NEUTRAL;
}
return validateMessage(msg.toString());
}
private Result validateMessage(Message message) {
if (message == null) {
return Result.NEUTRAL;
}
return validateMessage(message.getFormattedMessage());
}
private Result validateMessage(String message) {
return isSensibleCommand(message)
? Result.DENY
: Result.NEUTRAL;
}
private boolean isSensibleCommand(String message) {
message = message.toLowerCase();
return message.contains("issued server command:") && isSensible(message);
}
private boolean isSensible(String message) {
return censoredCommands.stream().anyMatch(message::contains);
}
} }

View File

@ -23,7 +23,7 @@ public class ReloadCommand extends SubCommand {
* @param plugin Current instance of Plan * @param plugin Current instance of Plan
*/ */
public ReloadCommand(Plan plugin) { public ReloadCommand(Plan plugin) {
super("reload", CommandType.CONSOLE, Permissions.MANAGE.getPermission(), Phrase.CMD_USG_RELOAD + ""); super("reload", CommandType.CONSOLE, Permissions.MANAGE.getPermission(), Phrase.CMD_USG_RELOAD.toString());
this.plugin = plugin; this.plugin = plugin;
} }
@ -33,7 +33,7 @@ public class ReloadCommand extends SubCommand {
plugin.onDisable(); plugin.onDisable();
plugin.reloadConfig(); plugin.reloadConfig();
plugin.onEnable(); plugin.onEnable();
sender.sendMessage(Phrase.RELOAD_COMPLETE + ""); sender.sendMessage(Phrase.RELOAD_COMPLETE.toString());
return true; return true;
} }

View File

@ -3,16 +3,18 @@ package main.java.com.djrapitops.plan.command.commands;
import com.djrapitops.plugin.command.CommandType; import com.djrapitops.plugin.command.CommandType;
import com.djrapitops.plugin.command.ISender; import com.djrapitops.plugin.command.ISender;
import com.djrapitops.plugin.command.SubCommand; import com.djrapitops.plugin.command.SubCommand;
import com.djrapitops.plugin.settings.ColorScheme;
import com.djrapitops.plugin.task.AbsRunnable; import com.djrapitops.plugin.task.AbsRunnable;
import com.djrapitops.plugin.utilities.FormattingUtils; import com.djrapitops.plugin.utilities.FormattingUtils;
import java.util.Arrays;
import java.util.List;
import main.java.com.djrapitops.plan.Permissions; import main.java.com.djrapitops.plan.Permissions;
import main.java.com.djrapitops.plan.Phrase; import main.java.com.djrapitops.plan.Phrase;
import main.java.com.djrapitops.plan.Plan; import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.utilities.Check; import main.java.com.djrapitops.plan.utilities.Check;
import main.java.com.djrapitops.plan.utilities.MiscUtils; import main.java.com.djrapitops.plan.utilities.MiscUtils;
import java.util.Arrays;
import java.util.List;
/** /**
* This subcommand is used to search for a user, and to view all matches' data. * This subcommand is used to search for a user, and to view all matches' data.
* *
@ -29,8 +31,25 @@ public class SearchCommand extends SubCommand {
* @param plugin Current instance of Plan * @param plugin Current instance of Plan
*/ */
public SearchCommand(Plan plugin) { public SearchCommand(Plan plugin) {
super("search", CommandType.CONSOLE_WITH_ARGUMENTS, Permissions.SEARCH.getPermission(), Phrase.CMD_USG_SEARCH + "", Phrase.ARG_SEARCH + ""); super("search", CommandType.CONSOLE_WITH_ARGUMENTS, Permissions.SEARCH.getPermission(), Phrase.CMD_USG_SEARCH.toString(), Phrase.ARG_SEARCH.toString());
this.plugin = plugin; this.plugin = plugin;
setHelp(plugin);
}
private void setHelp(Plan plugin) {
ColorScheme colorScheme = plugin.getColorScheme();
String mCol = colorScheme.getMainColor();
String sCol = colorScheme.getSecondaryColor();
String tCol = colorScheme.getTertiaryColor();
String[] help = new String[]{
mCol + "Search command",
tCol + " Used to get a list of Player names that match the given argument.",
sCol + " Example: /plan search 123 - Finds all users with 123 in their name."
};
setInDepthHelp(help);
} }
@Override @Override
@ -38,7 +57,7 @@ public class SearchCommand extends SubCommand {
if (!Check.isTrue(args.length >= 1, Phrase.COMMAND_REQUIRES_ARGUMENTS_ONE.toString(), sender)) { if (!Check.isTrue(args.length >= 1, Phrase.COMMAND_REQUIRES_ARGUMENTS_ONE.toString(), sender)) {
return true; return true;
} }
sender.sendMessage(Phrase.CMD_SEARCH_SEARCHING + ""); sender.sendMessage(Phrase.CMD_SEARCH_SEARCHING.toString());
runSearchTask(args, sender); runSearchTask(args, sender);
return true; return true;
@ -55,9 +74,10 @@ public class SearchCommand extends SubCommand {
if (names.isEmpty()) { if (names.isEmpty()) {
sender.sendMessage(Phrase.CMD_NO_RESULTS.parse(Arrays.toString(args))); sender.sendMessage(Phrase.CMD_NO_RESULTS.parse(Arrays.toString(args)));
} else { } else {
sender.sendMessage(Phrase.CMD_MATCH + "" + FormattingUtils.collectionToStringNoBrackets(names)); sender.sendMessage(Phrase.CMD_MATCH.toString() + FormattingUtils.collectionToStringNoBrackets(names));
} }
sender.sendMessage(Phrase.CMD_FOOTER + "");
sender.sendMessage(Phrase.CMD_FOOTER.toString());
} finally { } finally {
this.cancel(); this.cancel();
} }

View File

@ -2,6 +2,7 @@ package main.java.com.djrapitops.plan.command.commands;
import com.djrapitops.plugin.command.CommandType; import com.djrapitops.plugin.command.CommandType;
import com.djrapitops.plugin.command.TreeCommand; import com.djrapitops.plugin.command.TreeCommand;
import com.djrapitops.plugin.settings.ColorScheme;
import main.java.com.djrapitops.plan.Permissions; import main.java.com.djrapitops.plan.Permissions;
import main.java.com.djrapitops.plan.Plan; import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.command.commands.webuser.WebCheckCommand; import main.java.com.djrapitops.plan.command.commands.webuser.WebCheckCommand;
@ -20,6 +21,27 @@ public class WebUserCommand extends TreeCommand<Plan> {
public WebUserCommand(Plan plugin, RegisterCommand register) { public WebUserCommand(Plan plugin, RegisterCommand register) {
super(plugin, "webuser, web", CommandType.CONSOLE, Permissions.MANAGE_WEB.getPerm(), "Manage Webusers", "plan web"); super(plugin, "webuser, web", CommandType.CONSOLE, Permissions.MANAGE_WEB.getPerm(), "Manage Webusers", "plan web");
commands.add(register); commands.add(register);
setHelp(plugin);
}
private void setHelp(Plan plugin) {
ColorScheme colorScheme = plugin.getColorScheme();
String mCol = colorScheme.getMainColor();
String sCol = colorScheme.getSecondaryColor();
String tCol = colorScheme.getTertiaryColor();
String[] help = new String[]{
mCol + "Web User Manage command",
tCol + " Used to manage web users of the plugin",
sCol + " Users have a permission level:",
tCol + " 0 - Access to all pages",
tCol + " 1 - Access to /players & all inspect pages",
tCol + " 2 - Access to own inspect page",
sCol + " Alias: /plan web"
};
setInDepthHelp(help);
} }
@Override @Override

View File

@ -39,6 +39,7 @@ public class ManageCleanCommand extends SubCommand {
if (!Check.isTrue(args.length != 0, Phrase.COMMAND_REQUIRES_ARGUMENTS_ONE.toString(), sender)) { if (!Check.isTrue(args.length != 0, Phrase.COMMAND_REQUIRES_ARGUMENTS_ONE.toString(), sender)) {
return true; return true;
} }
String dbName = args[0].toLowerCase(); String dbName = args[0].toLowerCase();
boolean isCorrectDB = "sqlite".equals(dbName) || "mysql".equals(dbName); boolean isCorrectDB = "sqlite".equals(dbName) || "mysql".equals(dbName);

View File

@ -3,6 +3,7 @@ package main.java.com.djrapitops.plan.command.commands.manage;
import com.djrapitops.plugin.command.CommandType; import com.djrapitops.plugin.command.CommandType;
import com.djrapitops.plugin.command.ISender; import com.djrapitops.plugin.command.ISender;
import com.djrapitops.plugin.command.SubCommand; import com.djrapitops.plugin.command.SubCommand;
import com.djrapitops.plugin.settings.ColorScheme;
import com.djrapitops.plugin.task.AbsRunnable; import com.djrapitops.plugin.task.AbsRunnable;
import com.djrapitops.plugin.utilities.Verify; import com.djrapitops.plugin.utilities.Verify;
import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.Log;
@ -32,11 +33,29 @@ public class ManageClearCommand extends SubCommand {
super("clear", CommandType.CONSOLE_WITH_ARGUMENTS, Permissions.MANAGE.getPermission(), Phrase.CMD_USG_MANAGE_CLEAR + "", "<DB> [-a]"); super("clear", CommandType.CONSOLE_WITH_ARGUMENTS, Permissions.MANAGE.getPermission(), Phrase.CMD_USG_MANAGE_CLEAR + "", "<DB> [-a]");
this.plugin = plugin; this.plugin = plugin;
setHelp(plugin);
}
private void setHelp(Plan plugin) {
ColorScheme colorScheme = plugin.getColorScheme();
String mCol = colorScheme.getMainColor();
String sCol = colorScheme.getSecondaryColor();
String tCol = colorScheme.getTertiaryColor();
String[] help = new String[]{
mCol + "Manage Clear command",
tCol + " Used to delete ALL data in the active database.",
sCol + " Plugin should be reloaded after successful clear.",
sCol + " Alias: /plan pl"
};
setInDepthHelp(help);
} }
@Override @Override
public boolean onCommand(ISender sender, String commandLabel, String[] args) { public boolean onCommand(ISender sender, String commandLabel, String[] args) {
if (!Check.isTrue(args.length >= 1, Phrase.COMMAND_REQUIRES_ARGUMENTS_ONE + "", sender)) { if (!Check.isTrue(args.length >= 1, Phrase.COMMAND_REQUIRES_ARGUMENTS_ONE.toString(), sender)) {
return true; return true;
} }
@ -54,7 +73,7 @@ public class ManageClearCommand extends SubCommand {
final Database database = ManageUtils.getDB(plugin, dbName); final Database database = ManageUtils.getDB(plugin, dbName);
// If DB is null return // If DB is null return
if (!Check.isTrue(Verify.notNull(database), Phrase.MANAGE_DATABASE_FAILURE + "", sender)) { if (!Check.isTrue(Verify.notNull(database), Phrase.MANAGE_DATABASE_FAILURE.toString(), sender)) {
Log.error(dbName + " was null!"); Log.error(dbName + " was null!");
return true; return true;
} }
@ -71,6 +90,7 @@ public class ManageClearCommand extends SubCommand {
sender.sendMessage(Phrase.MANAGE_PROCESS_START.parse()); sender.sendMessage(Phrase.MANAGE_PROCESS_START.parse());
if (database.removeAllData()) { if (database.removeAllData()) {
plugin.getHandler().getDataCache().clear();
sender.sendMessage(Phrase.MANAGE_CLEAR_SUCCESS.toString()); sender.sendMessage(Phrase.MANAGE_CLEAR_SUCCESS.toString());
} else { } else {
sender.sendMessage(Phrase.MANAGE_PROCESS_FAIL.toString()); sender.sendMessage(Phrase.MANAGE_PROCESS_FAIL.toString());

View File

@ -3,6 +3,7 @@ package main.java.com.djrapitops.plan.command.commands.manage;
import com.djrapitops.plugin.command.CommandType; import com.djrapitops.plugin.command.CommandType;
import com.djrapitops.plugin.command.ISender; import com.djrapitops.plugin.command.ISender;
import com.djrapitops.plugin.command.SubCommand; import com.djrapitops.plugin.command.SubCommand;
import com.djrapitops.plugin.settings.ColorScheme;
import com.djrapitops.plugin.utilities.Verify; import com.djrapitops.plugin.utilities.Verify;
import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Permissions; import main.java.com.djrapitops.plan.Permissions;
@ -32,6 +33,23 @@ public class ManageHotswapCommand extends SubCommand {
super("hotswap", CommandType.CONSOLE_WITH_ARGUMENTS, Permissions.MANAGE.getPermission(), Phrase.CMD_USG_MANAGE_HOTSWAP.toString(), "<DB>"); super("hotswap", CommandType.CONSOLE_WITH_ARGUMENTS, Permissions.MANAGE.getPermission(), Phrase.CMD_USG_MANAGE_HOTSWAP.toString(), "<DB>");
this.plugin = plugin; this.plugin = plugin;
setHelp(plugin);
}
private void setHelp(Plan plugin) {
ColorScheme colorScheme = plugin.getColorScheme();
String mCol = colorScheme.getMainColor();
String sCol = colorScheme.getSecondaryColor();
String tCol = colorScheme.getTertiaryColor();
String[] help = new String[]{
mCol + "Manage Hotswap command",
tCol + " Used to change database in use on the fly.",
sCol + " Does not change database if connection fails"
};
setInDepthHelp(help);
} }
@Override @Override
@ -46,7 +64,7 @@ public class ManageHotswapCommand extends SubCommand {
return true; return true;
} }
if (Check.isTrue(dbName.equals(plugin.getDB().getConfigName()), Phrase.MANAGE_ERROR_SAME_DB + "", sender)) { if (Check.isTrue(dbName.equals(plugin.getDB().getConfigName()), Phrase.MANAGE_ERROR_SAME_DB.toString(), sender)) {
return true; return true;
} }

View File

@ -3,6 +3,7 @@ package main.java.com.djrapitops.plan.command.commands.manage;
import com.djrapitops.plugin.command.CommandType; import com.djrapitops.plugin.command.CommandType;
import com.djrapitops.plugin.command.ISender; import com.djrapitops.plugin.command.ISender;
import com.djrapitops.plugin.command.SubCommand; import com.djrapitops.plugin.command.SubCommand;
import com.djrapitops.plugin.settings.ColorScheme;
import com.djrapitops.plugin.task.AbsRunnable; import com.djrapitops.plugin.task.AbsRunnable;
import com.djrapitops.plugin.utilities.FormattingUtils; import com.djrapitops.plugin.utilities.FormattingUtils;
import com.djrapitops.plugin.utilities.player.Fetch; import com.djrapitops.plugin.utilities.player.Fetch;
@ -21,7 +22,7 @@ import java.util.stream.Collectors;
/** /**
* This manage subcommand is used to import data from 3rd party plugins. * This manage subcommand is used to import data from 3rd party plugins.
* * <p>
* Supported plugins (v3.0.0) : OnTime * Supported plugins (v3.0.0) : OnTime
* *
* @author Rsl1122 * @author Rsl1122
@ -39,6 +40,24 @@ public class ManageImportCommand extends SubCommand {
public ManageImportCommand(Plan plugin) { public ManageImportCommand(Plan plugin) {
super("import", CommandType.CONSOLE, Permissions.MANAGE.getPermission(), Phrase.CMD_USG_MANAGE_IMPORT.toString(), Phrase.ARG_IMPORT.toString()); super("import", CommandType.CONSOLE, Permissions.MANAGE.getPermission(), Phrase.CMD_USG_MANAGE_IMPORT.toString(), Phrase.ARG_IMPORT.toString());
this.plugin = plugin; this.plugin = plugin;
setHelp(plugin);
}
private void setHelp(Plan plugin) {
ColorScheme colorScheme = plugin.getColorScheme();
String mCol = colorScheme.getMainColor();
String sCol = colorScheme.getSecondaryColor();
String tCol = colorScheme.getTertiaryColor();
String[] help = new String[]{
mCol + "Manage Import command",
tCol + " Used to import data from other sources",
sCol + " Analysis will be disabled during import.",
sCol + " If a lot of users are not in the database, saving may take a long time."
};
setInDepthHelp(help);
} }
@Override @Override
@ -58,6 +77,7 @@ public class ManageImportCommand extends SubCommand {
if (!Check.isTrue(importPlugins.keySet().contains(importFromPlugin), Phrase.MANAGE_ERROR_INCORRECT_PLUGIN + importFromPlugin, sender)) { if (!Check.isTrue(importPlugins.keySet().contains(importFromPlugin), Phrase.MANAGE_ERROR_INCORRECT_PLUGIN + importFromPlugin, sender)) {
return true; return true;
} }
if (!Check.isTrue(ImportUtils.isPluginEnabled(importFromPlugin), Phrase.MANAGE_ERROR_PLUGIN_NOT_ENABLED + importFromPlugin, sender)) { if (!Check.isTrue(ImportUtils.isPluginEnabled(importFromPlugin), Phrase.MANAGE_ERROR_PLUGIN_NOT_ENABLED + importFromPlugin, sender)) {
return true; return true;
} }

View File

@ -18,7 +18,7 @@ import java.util.UUID;
/** /**
* This manage subcommand is used to move all data from one database to another. * This manage subcommand is used to move all data from one database to another.
* * <p>
* Destination database will be cleared. * Destination database will be cleared.
* *
* @author Rsl1122 * @author Rsl1122
@ -58,9 +58,11 @@ public class ManageMoveCommand extends SubCommand {
if (!Check.isTrue(isCorrectDB, Phrase.MANAGE_ERROR_INCORRECT_DB + toDB, sender)) { if (!Check.isTrue(isCorrectDB, Phrase.MANAGE_ERROR_INCORRECT_DB + toDB, sender)) {
return true; return true;
} }
if (!Check.isTrue(!Verify.equalsIgnoreCase(fromDB, toDB), Phrase.MANAGE_ERROR_SAME_DB.toString(), sender)) { if (!Check.isTrue(!Verify.equalsIgnoreCase(fromDB, toDB), Phrase.MANAGE_ERROR_SAME_DB.toString(), sender)) {
return true; return true;
} }
if (!Check.isTrue(Verify.contains("-a", args), Phrase.COMMAND_ADD_CONFIRMATION_ARGUMENT.parse(Phrase.WARN_REMOVE.parse(args[1])), sender)) { if (!Check.isTrue(Verify.contains("-a", args), Phrase.COMMAND_ADD_CONFIRMATION_ARGUMENT.parse(Phrase.WARN_REMOVE.parse(args[1])), sender)) {
return true; return true;
} }
@ -92,9 +94,11 @@ public class ManageMoveCommand extends SubCommand {
if (Check.isTrue(Verify.isEmpty(uuids), Phrase.MANAGE_ERROR_NO_PLAYERS + " (" + fromDatabase.getName() + ")", sender)) { if (Check.isTrue(Verify.isEmpty(uuids), Phrase.MANAGE_ERROR_NO_PLAYERS + " (" + fromDatabase.getName() + ")", sender)) {
return; return;
} }
sender.sendMessage(Phrase.MANAGE_PROCESS_START.parse()); sender.sendMessage(Phrase.MANAGE_PROCESS_START.parse());
if (ManageUtils.clearAndCopy(toDatabase, fromDatabase, uuids)) { if (ManageUtils.clearAndCopy(toDatabase, fromDatabase, uuids)) {
sender.sendMessage(Phrase.MANAGE_MOVE_SUCCESS + ""); sender.sendMessage(Phrase.MANAGE_MOVE_SUCCESS.toString());
boolean movedToCurrentDatabase = Verify.equalsIgnoreCase(toDatabase.getConfigName(), plugin.getDB().getConfigName()); boolean movedToCurrentDatabase = Verify.equalsIgnoreCase(toDatabase.getConfigName(), plugin.getDB().getConfigName());
Check.isTrue(!movedToCurrentDatabase, Phrase.MANAGE_DB_CONFIG_REMINDER.toString(), sender); Check.isTrue(!movedToCurrentDatabase, Phrase.MANAGE_DB_CONFIG_REMINDER.toString(), sender);

View File

@ -3,6 +3,7 @@ package main.java.com.djrapitops.plan.command.commands.manage;
import com.djrapitops.plugin.command.CommandType; import com.djrapitops.plugin.command.CommandType;
import com.djrapitops.plugin.command.ISender; import com.djrapitops.plugin.command.ISender;
import com.djrapitops.plugin.command.SubCommand; import com.djrapitops.plugin.command.SubCommand;
import com.djrapitops.plugin.settings.ColorScheme;
import com.djrapitops.plugin.task.AbsRunnable; import com.djrapitops.plugin.task.AbsRunnable;
import com.djrapitops.plugin.utilities.Verify; import com.djrapitops.plugin.utilities.Verify;
import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.Log;
@ -35,6 +36,21 @@ public class ManageRemoveCommand extends SubCommand {
super("remove", CommandType.CONSOLE_WITH_ARGUMENTS, Permissions.MANAGE.getPermission(), Phrase.CMD_USG_MANAGE_REMOVE.toString(), Phrase.ARG_PLAYER + " [-a]"); super("remove", CommandType.CONSOLE_WITH_ARGUMENTS, Permissions.MANAGE.getPermission(), Phrase.CMD_USG_MANAGE_REMOVE.toString(), Phrase.ARG_PLAYER + " [-a]");
this.plugin = plugin; this.plugin = plugin;
setHelp(plugin);
}
private void setHelp(Plan plugin) {
ColorScheme colorScheme = plugin.getColorScheme();
String mCol = colorScheme.getMainColor();
String tCol = colorScheme.getTertiaryColor();
String[] help = new String[]{
mCol + "Manage Remove command",
tCol + " Used to Remove user's data from the active database."
};
setInDepthHelp(help);
} }
@Override @Override
@ -56,13 +72,16 @@ public class ManageRemoveCommand extends SubCommand {
try { try {
UUID uuid = UUIDUtility.getUUIDOf(playerName); UUID uuid = UUIDUtility.getUUIDOf(playerName);
String message = Phrase.USERNAME_NOT_VALID.toString(); String message = Phrase.USERNAME_NOT_VALID.toString();
if (!Check.isTrue(Verify.notNull(uuid), message, sender)) { if (!Check.isTrue(Verify.notNull(uuid), message, sender)) {
return; return;
} }
message = Phrase.USERNAME_NOT_KNOWN.toString(); message = Phrase.USERNAME_NOT_KNOWN.toString();
if (!Check.isTrue(plugin.getDB().wasSeenBefore(uuid), message, sender)) { if (!Check.isTrue(plugin.getDB().wasSeenBefore(uuid), message, sender)) {
return; return;
} }
message = Phrase.COMMAND_ADD_CONFIRMATION_ARGUMENT.parse(Phrase.WARN_REMOVE.parse(plugin.getDB().getConfigName())); message = Phrase.COMMAND_ADD_CONFIRMATION_ARGUMENT.parse(Phrase.WARN_REMOVE.parse(plugin.getDB().getConfigName()));
if (!Check.isTrue(Verify.contains("-a", args), message, sender)) { if (!Check.isTrue(Verify.contains("-a", args), message, sender)) {
return; return;

View File

@ -44,12 +44,14 @@ public class ManageRestoreCommand extends SubCommand {
if (!Check.isTrue(args.length >= 2, Phrase.COMMAND_REQUIRES_ARGUMENTS.parse(Phrase.USE_RESTORE.toString()), sender)) { if (!Check.isTrue(args.length >= 2, Phrase.COMMAND_REQUIRES_ARGUMENTS.parse(Phrase.USE_RESTORE.toString()), sender)) {
return true; return true;
} }
String db = args[1].toLowerCase(); String db = args[1].toLowerCase();
boolean isCorrectDB = "sqlite".equals(db) || "mysql".equals(db); boolean isCorrectDB = "sqlite".equals(db) || "mysql".equals(db);
if (!Check.isTrue(isCorrectDB, Phrase.MANAGE_ERROR_INCORRECT_DB + db, sender)) { if (!Check.isTrue(isCorrectDB, Phrase.MANAGE_ERROR_INCORRECT_DB + db, sender)) {
return true; return true;
} }
if (!Check.isTrue(Verify.contains("-a", args), Phrase.COMMAND_ADD_CONFIRMATION_ARGUMENT.parse(Phrase.WARN_REWRITE.parse(args[1])), sender)) { if (!Check.isTrue(Verify.contains("-a", args), Phrase.COMMAND_ADD_CONFIRMATION_ARGUMENT.parse(Phrase.WARN_REWRITE.parse(args[1])), sender)) {
return true; return true;
} }
@ -71,7 +73,7 @@ public class ManageRestoreCommand extends SubCommand {
public void run() { public void run() {
try { try {
String backupDBName = args[0]; String backupDBName = args[0];
boolean containsDBFileExtension = backupDBName.contains(".db"); boolean containsDBFileExtension = backupDBName.endsWith(".db");
File backupDBFile = new File(plugin.getDataFolder(), backupDBName + (containsDBFileExtension ? "" : ".db")); File backupDBFile = new File(plugin.getDataFolder(), backupDBName + (containsDBFileExtension ? "" : ".db"));
if (!Check.isTrue(Verify.exists(backupDBFile), Phrase.MANAGE_ERROR_BACKUP_FILE_NOT_FOUND + " " + args[0], sender)) { if (!Check.isTrue(Verify.exists(backupDBFile), Phrase.MANAGE_ERROR_BACKUP_FILE_NOT_FOUND + " " + args[0], sender)) {
@ -79,22 +81,27 @@ public class ManageRestoreCommand extends SubCommand {
} }
if (containsDBFileExtension) { if (containsDBFileExtension) {
backupDBName = backupDBName.replace(".db", ""); backupDBName = backupDBName.substring(0, backupDBName.length() - 3);
} }
SQLiteDB backupDB = new SQLiteDB(plugin, backupDBName); SQLiteDB backupDB = new SQLiteDB(plugin, backupDBName);
if (!backupDB.init()) { if (!backupDB.init()) {
sender.sendMessage(Phrase.MANAGE_DATABASE_FAILURE.toString()); sender.sendMessage(Phrase.MANAGE_DATABASE_FAILURE.toString());
return; return;
} }
sender.sendMessage(Phrase.MANAGE_PROCESS_START.parse()); sender.sendMessage(Phrase.MANAGE_PROCESS_START.parse());
final Collection<UUID> uuids = ManageUtils.getUUIDS(backupDB); final Collection<UUID> uuids = ManageUtils.getUUIDS(backupDB);
if (!Check.isTrue(!Verify.isEmpty(uuids), Phrase.MANAGE_ERROR_NO_PLAYERS + " (" + backupDBName + ")", sender)) { if (!Check.isTrue(!Verify.isEmpty(uuids), Phrase.MANAGE_ERROR_NO_PLAYERS + " (" + backupDBName + ")", sender)) {
return; return;
} }
if (ManageUtils.clearAndCopy(database, backupDB, uuids)) { if (ManageUtils.clearAndCopy(database, backupDB, uuids)) {
if (database.getConfigName().equals(plugin.getDB().getConfigName())) { if (database.getConfigName().equals(plugin.getDB().getConfigName())) {
plugin.getHandler().getCommandUseFromDb(); plugin.getHandler().getCommandUseFromDb();
} }
sender.sendMessage(Phrase.MANAGE_COPY_SUCCESS.toString()); sender.sendMessage(Phrase.MANAGE_COPY_SUCCESS.toString());
} else { } else {
sender.sendMessage(Phrase.MANAGE_PROCESS_FAIL.toString()); sender.sendMessage(Phrase.MANAGE_PROCESS_FAIL.toString());

View File

@ -32,10 +32,10 @@ public class ManageStatusCommand extends SubCommand {
String[] messages = new String[]{ String[] messages = new String[]{
Phrase.CMD_MANAGE_STATUS_HEADER.toString(), Phrase.CMD_MANAGE_STATUS_HEADER.toString(),
Phrase.CMD_MANAGE_STATUS_ACTIVE_DB.parse(plugin.getDB().getConfigName()), Phrase.CMD_MANAGE_STATUS_ACTIVE_DB.parse(plugin.getDB().getConfigName()),
Phrase.CMD_MANAGE_STATUS_QUEUE_PROCESS.parse("" + plugin.getHandler().getProcessTask().size()), Phrase.CMD_MANAGE_STATUS_QUEUE_PROCESS.parse(String.valueOf(plugin.getHandler().getProcessTask().size())),
Phrase.CMD_MANAGE_STATUS_QUEUE_SAVE.parse("" + plugin.getHandler().getSaveTask().size()), Phrase.CMD_MANAGE_STATUS_QUEUE_SAVE.parse(String.valueOf(plugin.getHandler().getSaveTask().size())),
Phrase.CMD_MANAGE_STATUS_QUEUE_GET.parse("" + plugin.getHandler().getGetTask().size()), Phrase.CMD_MANAGE_STATUS_QUEUE_GET.parse(String.valueOf(plugin.getHandler().getGetTask().size())),
Phrase.CMD_MANAGE_STATUS_QUEUE_CLEAR.parse("" + plugin.getHandler().getClearTask().size()), Phrase.CMD_MANAGE_STATUS_QUEUE_CLEAR.parse(String.valueOf(plugin.getHandler().getClearTask().size())),
Phrase.CMD_FOOTER.toString() Phrase.CMD_FOOTER.toString()
}; };

View File

@ -37,7 +37,6 @@ public class WebListUsersCommand extends SubCommand {
try { try {
ColorScheme cs = plugin.getColorScheme(); ColorScheme cs = plugin.getColorScheme();
String mCol = cs.getMainColor(); String mCol = cs.getMainColor();
String sCol = cs.getSecondaryColor();
List<WebUser> users = plugin.getDB().getSecurityTable().getUsers(); List<WebUser> users = plugin.getDB().getSecurityTable().getUsers();
users.sort(new WebUserComparator()); users.sort(new WebUserComparator());
sender.sendMessage(Phrase.CMD_FOOTER.parse() + mCol + " WebUsers (" + users.size() + ")"); sender.sendMessage(Phrase.CMD_FOOTER.parse() + mCol + " WebUsers (" + users.size() + ")");

View File

@ -13,27 +13,19 @@ import java.util.Map;
/** /**
* Big container object for Data. * Big container object for Data.
* * <p>
* Contains parts that can be analysed. Each part has their own purpose. * Contains parts that can be analysed. Each part has their own purpose.
* * <p>
* Parts contain variables that can be added to. These variables are then * Parts contain variables that can be added to. These variables are then
* analysed using the analysis method. * analysed using the analysis method.
* * <p>
* After being analysed the ReplaceMap can be retrieved for replacing * After being analysed the ReplaceMap can be retrieved for replacing
* placeholders on the analysis.html file. * placeholders on the analysis.html file.
* *
* @author Rsl1122 * @author Rsl1122
* @since 3.5.2 * @since 3.5.2
*/ */
public class AnalysisData extends RawData<AnalysisData> { public class AnalysisData extends RawData {
private long refreshDate;
private String planVersion;
private String pluginsTabLayout;
private Map<String, String> additionalDataReplaceMap;
private String playersTable;
private final ActivityPart activityPart; private final ActivityPart activityPart;
private final CommandUsagePart commandUsagePart; private final CommandUsagePart commandUsagePart;
@ -44,6 +36,12 @@ public class AnalysisData extends RawData<AnalysisData> {
private final PlayerCountPart playerCountPart; private final PlayerCountPart playerCountPart;
private final PlaytimePart playtimePart; private final PlaytimePart playtimePart;
private final TPSPart tpsPart; private final TPSPart tpsPart;
private final WorldPart worldPart;
private long refreshDate;
private String planVersion;
private String pluginsTabLayout;
private Map<String, String> additionalDataReplaceMap;
private String playersTable;
public AnalysisData(Map<String, Integer> commandUsage, List<TPS> tpsData) { public AnalysisData(Map<String, Integer> commandUsage, List<TPS> tpsData) {
commandUsagePart = new CommandUsagePart(commandUsage); commandUsagePart = new CommandUsagePart(commandUsage);
@ -55,6 +53,7 @@ public class AnalysisData extends RawData<AnalysisData> {
gamemodePart = new GamemodePart(); gamemodePart = new GamemodePart();
tpsPart = new TPSPart(tpsData); tpsPart = new TPSPart(tpsData);
activityPart = new ActivityPart(joinInfoPart, tpsPart); activityPart = new ActivityPart(joinInfoPart, tpsPart);
worldPart = new WorldPart();
} }
public ActivityPart getActivityPart() { public ActivityPart getActivityPart() {
@ -93,12 +92,14 @@ public class AnalysisData extends RawData<AnalysisData> {
return tpsPart; return tpsPart;
} }
public WorldPart getWorldPart() {
return worldPart;
}
public List<RawData> getAllParts() { public List<RawData> getAllParts() {
return Arrays.asList(new RawData[]{ return Arrays.asList(activityPart, commandUsagePart, gamemodePart,
activityPart, commandUsagePart, gamemodePart,
geolocationPart, joinInfoPart, killPart, geolocationPart, joinInfoPart, killPart,
playerCountPart, playtimePart, tpsPart playerCountPart, playtimePart, tpsPart, worldPart);
});
} }
public String getPlanVersion() { public String getPlanVersion() {
@ -125,10 +126,6 @@ public class AnalysisData extends RawData<AnalysisData> {
this.additionalDataReplaceMap = additionalDataReplaceMap; this.additionalDataReplaceMap = additionalDataReplaceMap;
} }
public void setRefreshDate(long refreshDate) {
this.refreshDate = refreshDate;
}
public void setPlayersTable(String playersTable) { public void setPlayersTable(String playersTable) {
this.playersTable = playersTable; this.playersTable = playersTable;
} }
@ -143,7 +140,7 @@ public class AnalysisData extends RawData<AnalysisData> {
addValue("version", planVersion); addValue("version", planVersion);
final List<RawData> parts = getAllParts(); final List<RawData> parts = getAllParts();
parts.forEach((part) -> { parts.forEach(part -> {
try { try {
Benchmark.start("Analysis Phase: " + part.getClass().getSimpleName()); Benchmark.start("Analysis Phase: " + part.getClass().getSimpleName());
part.analyseData(); part.analyseData();
@ -166,4 +163,8 @@ public class AnalysisData extends RawData<AnalysisData> {
public long getRefreshDate() { public long getRefreshDate() {
return refreshDate; return refreshDate;
} }
public void setRefreshDate(long refreshDate) {
this.refreshDate = refreshDate;
}
} }

View File

@ -1,7 +1,7 @@
package main.java.com.djrapitops.plan.data; package main.java.com.djrapitops.plan.data;
/** /**
* This class is used for storing start and end of a playsession inside UserData * This class is used for storing start and end of a play session inside UserData
* object. * object.
* *
* @author Rsl1122 * @author Rsl1122
@ -44,7 +44,7 @@ public class SessionData {
/** /**
* Ends the session with given end point. * Ends the session with given end point.
* * <p>
* (Changes the end to the parameter.). * (Changes the end to the parameter.).
* *
* @param endOfSession Epoch millisecond the session ended. * @param endOfSession Epoch millisecond the session ended.

View File

@ -6,7 +6,7 @@
package main.java.com.djrapitops.plan.data; package main.java.com.djrapitops.plan.data;
/** /**
* Class containing single datapoint of TPS/players online. * Class containing single datapoint of TPS / Players online / CPU Usage / Used Memory / Entity Count / Chunks loaded.
* *
* @author Rsl1122 * @author Rsl1122
* @since 3.5.0 * @since 3.5.0
@ -17,20 +17,29 @@ public class TPS {
private final double tps; private final double tps;
private final int players; private final int players;
private final double cpuUsage; private final double cpuUsage;
private final long usedMemory;
private final int entityCount;
private final int chunksLoaded;
/** /**
* Constructor. * Constructor.
* *
* @param date time of the average calculation. * @param date time of the TPS calculation.
* @param tps average tps for the last minute. * @param tps average tps for the last minute.
* @param players average players for the last minute. * @param players players for the minute.
* @param cpuUsage average CPU usage for the last 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 tps, int players, double cpuUsage) { public TPS(long date, double tps, int players, double cpuUsage, long usedMemory, int entityCount, int chunksLoaded) {
this.date = date; this.date = date;
this.tps = tps; this.tps = tps;
this.players = players; this.players = players;
this.cpuUsage = cpuUsage; this.cpuUsage = cpuUsage;
this.usedMemory = usedMemory;
this.entityCount = entityCount;
this.chunksLoaded = chunksLoaded;
} }
/** /**
@ -52,7 +61,7 @@ public class TPS {
} }
/** /**
* Get the average players for the minute. * Get the player for the time, when the data was fetched.
* *
* @return Players online. * @return Players online.
*/ */
@ -61,14 +70,41 @@ public class TPS {
} }
/** /**
* Get the average CPU Usage for the minute. * Get the average CPU Usage for the minute
* *
* @return 0-20 double * @return 0-100 double
*/ */
public double getCPUUsage() { public double getCPUUsage() {
return cpuUsage; return cpuUsage;
} }
/**
* Get the used memory for the time, when the data was fetched.
*
* @return Used Memory in Megabyte
*/
public long getUsedMemory() {
return usedMemory;
}
/**
* Get the amount of entities for the time, when the data was fetched
*
* @return Amount of entities
*/
public int getEntityCount() {
return entityCount;
}
/**
* Get the amount of chunks loaded for the time, when the data was fetched
*
* @return Amount of chunks loaded
*/
public int getChunksLoaded() {
return chunksLoaded;
}
@Override @Override
public int hashCode() { public int hashCode() {
int hash = 3; int hash = 3;
@ -83,17 +119,20 @@ public class TPS {
if (this == obj) { if (this == obj) {
return true; return true;
} }
if (obj == null) { if (obj == null) {
return false; return false;
} }
if (getClass() != obj.getClass()) { if (getClass() != obj.getClass()) {
return false; return false;
} }
final TPS other = (TPS) obj; final TPS other = (TPS) obj;
return this.date == other.date return date == other.date
&& Double.doubleToLongBits(this.tps) == Double.doubleToLongBits(other.tps) && Double.compare(this.tps, other.tps) == 0
&& this.players == other.players && this.players == other.players
&& this.cpuUsage == other.cpuUsage; && Double.compare(cpuUsage, other.cpuUsage) == 0;
} }
@Override @Override

View File

@ -4,6 +4,8 @@ import com.djrapitops.plugin.utilities.Verify;
import com.djrapitops.plugin.utilities.player.IOfflinePlayer; import com.djrapitops.plugin.utilities.player.IOfflinePlayer;
import com.djrapitops.plugin.utilities.player.IPlayer; import com.djrapitops.plugin.utilities.player.IPlayer;
import main.java.com.djrapitops.plan.Log; 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.net.InetAddress;
import java.util.*; import java.util.*;
@ -20,85 +22,85 @@ public class UserData {
private boolean clearAfterSave; private boolean clearAfterSave;
private UUID uuid; private UUID uuid;
private Set<InetAddress> ips; private String name;
private Set<String> nicknames; private Set<String> nicknames;
private String lastNick; private String lastNick;
private long registered; private String geolocation;
private long lastPlayed; private Set<InetAddress> ips;
private long playTime;
private int loginTimes; private int loginTimes;
private int timesKicked; private int timesKicked;
private long lastGmSwapTime;
private String lastGamemode;
private Map<String, Long> gmTimes;
private boolean isOp; private boolean isOp;
private boolean isBanned; private boolean isBanned;
private String geolocation; private boolean isOnline;
private int mobKills; private int mobKills;
private List<KillData> playerKills; private List<KillData> playerKills;
private int deaths; private int deaths;
private String name; private long registered;
private boolean isOnline; private long lastPlayed;
private long playTime;
private GMTimes gmTimes;
private WorldTimes worldTimes;
private SessionData currentSession;
private final List<SessionData> sessions; private final List<SessionData> sessions;
/** /**
* Creates a new UserData object with given values and default values. * Creates a new UserData object with given values and default values.
* * <p>
* Some variables are left uninitialized: isBanned, lastPlayed, playTime, * Some variables are left uninitialized: isBanned, lastPlayed, playTime,
* loginTimes, timesKicked, lastGmSwapTime, mobKills, deaths and * loginTimes, timesKicked, lastGmSwapTime, mobKills, deaths, lastWorldSwapTime, lastWorld
* currentSession. * <p>
*
* These variables need to be set with setters. * These variables need to be set with setters.
* * <p>
* All Collections are left empty: locations, nicknames, ips, sessions, * All Collections are left empty: locations, nicknames, ips, sessions,
* playerKills. Because nicknames is empty, lastNick is an empty string. * playerKills. Because nicknames is empty, lastNick is an empty string.
* * <p>
* gmTimes HashMap will contain 4 '0L' values: SURVIVAL, CREATIVE, * gmTimes Map will contain 4 '0L' values: SURVIVAL, CREATIVE,
* ADVENTURE, SPECTATOR * ADVENTURE, SPECTATOR
* worldTimes Map is left empty.
* *
* @param uuid UUID of the player * @param uuid UUID of the player
* @param reg Epoch millisecond the player registered. * @param reg Epoch millisecond the player registered.
* @param op Is the player op? (true/false) * @param op Is the player op? (true/false)
* @param lastGM last GameMode the player was seen in.
* @param name Name of the player. * @param name Name of the player.
* @param online Is the player online? * @param online Is the player online?
*/ */
public UserData(UUID uuid, long reg, boolean op, String lastGM, String name, boolean online) { public UserData(UUID uuid, long reg, boolean op, String gm, String name, boolean online) {
accessing = 0; accessing = 0;
this.gmTimes = new GMTimes(gm);
this.worldTimes = new WorldTimes();
this.uuid = uuid; this.uuid = uuid;
registered = reg; this.name = name;
isOp = op; lastNick = "";
nicknames = new HashSet<>(); nicknames = new HashSet<>();
ips = new HashSet<>(); ips = new HashSet<>();
gmTimes = new HashMap<>();
String[] gms = new String[]{"SURVIVAL", "CREATIVE", "ADVENTURE", "SPECTATOR"};
for (String gm : gms) {
gmTimes.put(gm, 0L);
}
lastGamemode = lastGM;
geolocation = "Not Known"; geolocation = "Not Known";
this.name = name;
isOp = op;
isOnline = online; isOnline = online;
registered = reg;
sessions = new ArrayList<>(); sessions = new ArrayList<>();
lastNick = "";
playerKills = new ArrayList<>(); playerKills = new ArrayList<>();
} }
/** /**
* Creates a new UserData object with the variables inside a Player object. * Creates a new UserData object with the variables inside a Player object.
* * <p>
* Some variables are left uninitialized: lastPlayed, playTime, loginTimes, * Some variables are left uninitialized: lastPlayed, playTime, loginTimes,
* timesKicked, lastGmSwapTime, mobKills, deaths and currentSession. * timesKicked, lastGmSwapTime, mobKills, deaths and currentSession.
* * <p>
* These variables need to be set with setters. * These variables need to be set with setters.
* * <p>
* All Collections are left empty: locations, nicknames, ips, sessions, * All Collections are left empty: locations, nicknames, ips, sessions,
* playerKills. Because nicknames is empty, lastNick is an empty string. * playerKills. Because nicknames is empty, lastNick is an empty string.
* * <p>
* gmTimes HashMap will contain 4 '0L' values: SURVIVAL, CREATIVE, * gmTimes HashMap will contain 4 '0L' values: SURVIVAL, CREATIVE,
* ADVENTURE, SPECTATOR * ADVENTURE, SPECTATOR
* *
@ -118,19 +120,19 @@ public class UserData {
/** /**
* Creates a new UserData object with the variables inside a OfflinePlayer * Creates a new UserData object with the variables inside a OfflinePlayer
* object. * object.
* * <p>
* Some variables are left uninitialized: location, lastPlayed, playTime, * Some variables are left uninitialized: location, lastPlayed, playTime,
* loginTimes, timesKicked, lastGmSwapTime, mobKills, deaths and * loginTimes, timesKicked, lastGmSwapTime, mobKills, deaths and
* currentSession. * currentSession.
* * <p>
* These variables need to be set with setters. * These variables need to be set with setters.
* * <p>
* All Collections are left empty: locations, nicknames, ips, sessions, * All Collections are left empty: locations, nicknames, ips, sessions,
* playerKills. Because nicknames is empty, lastNick is an empty string. * playerKills. Because nicknames is empty, lastNick is an empty string.
* * <p>
* gmTimes HashMap will contain 4 '0L' values: SURVIVAL, CREATIVE, * gmTimes HashMap will contain 4 '0L' values: SURVIVAL, CREATIVE,
* ADVENTURE, SPECTATOR * ADVENTURE, SPECTATOR
* * <p>
* lastGM will be set as SURVIVAL * lastGM will be set as SURVIVAL
* *
* @param player IOfflinePlayer object. * @param player IOfflinePlayer object.
@ -164,10 +166,8 @@ public class UserData {
this.playTime = data.getPlayTime(); this.playTime = data.getPlayTime();
this.loginTimes = data.getLoginTimes(); this.loginTimes = data.getLoginTimes();
this.timesKicked = data.getTimesKicked(); this.timesKicked = data.getTimesKicked();
this.lastGmSwapTime = data.getLastGmSwapTime(); this.gmTimes = data.getGmTimes();
this.lastGamemode = data.getLastGamemode(); this.worldTimes = data.getWorldTimes();
this.gmTimes = new HashMap<>();
gmTimes.putAll(data.getGmTimes());
this.isOp = data.isOp(); this.isOp = data.isOp();
this.isBanned = data.isBanned(); this.isBanned = data.isBanned();
this.geolocation = data.getGeolocation(); this.geolocation = data.getGeolocation();
@ -183,12 +183,22 @@ public class UserData {
@Override @Override
public String toString() { public String toString() {
try { try {
return "{" + "accessing:" + accessing + "|uuid:" + uuid + "|ips:" + ips + "|nicknames:" + nicknames + "|lastNick:" + lastNick + "|registered:" + registered + "|lastPlayed:" + lastPlayed + "|playTime:" + playTime + "|loginTimes:" + loginTimes + "|timesKicked:" + timesKicked + "|lastGmSwapTime:" + lastGmSwapTime + "|lastGamemode:" + lastGamemode + "|gmTimes:" + gmTimes + "|isOp:" + isOp + "|isBanned:" + isBanned + "|geolocation:" + geolocation + "|mobKills:" + mobKills + "|playerKills:" + playerKills + "|deaths:" + deaths + "|name:" + name + "|isOnline:" + isOnline + "|currentSession:" + currentSession + "|sessions:" + sessions + '}'; 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 (Throwable e) { } catch (Exception e) {
return "UserData: Error on toString:" + e; return "UserData: Error on toString:" + e;
} }
} }
@Deprecated
public String getLastGamemode() {
return gmTimes.getState();
}
@Deprecated
public long getLastGmSwapTime() {
return gmTimes.getLastStateChange();
}
/** /**
* Adds an to the ips Set if it is not null or the set doesn't contain it. * Adds an to the ips Set if it is not null or the set doesn't contain it.
* *
@ -215,9 +225,9 @@ public class UserData {
/** /**
* Adds a nickname to the nicknames Set. * Adds a nickname to the nicknames Set.
* * <p>
* null or empty values filtered. * null or empty values filtered.
* * <p>
* lastNick will be set as the given parameter, if accepted. * lastNick will be set as the given parameter, if accepted.
* *
* @param nick Displayname of the player. * @param nick Displayname of the player.
@ -237,7 +247,7 @@ public class UserData {
/** /**
* Adds nicknames to the nicknames Set. * Adds nicknames to the nicknames Set.
* * <p>
* null or empty values filtered. * null or empty values filtered.
* *
* @param addNicks Collection of nicknames. * @param addNicks Collection of nicknames.
@ -246,40 +256,9 @@ public class UserData {
nicknames.addAll(addNicks.stream().filter(nick -> !Verify.isEmpty(nick)).collect(Collectors.toList())); nicknames.addAll(addNicks.stream().filter(nick -> !Verify.isEmpty(nick)).collect(Collectors.toList()));
} }
/**
* Set a specific GameMode's millisecond value.
*
* @param gm Name of Gamemode.
* @param time Milliseconds spent in the gamemode.
*/
public void setGMTime(String gm, long time) {
if (!Verify.notNull(gmTimes)) {
gmTimes = new HashMap<>();
}
if (Verify.notNull(gm)) {
gmTimes.put(gm, time);
}
}
/**
* Set every GameMode's millisecond value.
*
* @param survivalTime ms spent in SURVIVAL
* @param creativeTime ms spent in CREATIVE
* @param adventureTime ms spent in ADVENTURE
* @param spectatorTime ms spent in SPECTATOR
*/
public void setAllGMTimes(long survivalTime, long creativeTime, long adventureTime, long spectatorTime) {
gmTimes.clear();
gmTimes.put("SURVIVAL", survivalTime);
gmTimes.put("CREATIVE", creativeTime);
gmTimes.put("ADVENTURE", adventureTime);
gmTimes.put("SPECTATOR", spectatorTime);
}
/** /**
* Adds a new SessionData to the sessions list. * Adds a new SessionData to the sessions list.
* * <p>
* null and invalid sessions filtered. * null and invalid sessions filtered.
* *
* @param session SessionData object * @param session SessionData object
@ -292,7 +271,7 @@ public class UserData {
/** /**
* Adds SessionData objects to the sessions list. * Adds SessionData objects to the sessions list.
* * <p>
* null and invalid sessions filtered. * null and invalid sessions filtered.
* *
* @param sessions Collection of SessionData objects. * @param sessions Collection of SessionData objects.
@ -305,28 +284,6 @@ public class UserData {
this.sessions.addAll(filteredSessions); this.sessions.addAll(filteredSessions);
} }
/**
* Sets the current session.
*
* Currently unused.
*
* @param session SessionData object, no restrictions.
*/
public void setCurrentSession(SessionData session) {
currentSession = session;
}
/**
* Gets the current session.
*
* Currently unused.
*
* @return SessionData object with a recent start.
*/
public SessionData getCurrentSession() {
return currentSession;
}
/** /**
* Changes the value of isBanned. * Changes the value of isBanned.
* *
@ -369,6 +326,15 @@ public class UserData {
return uuid; return uuid;
} }
/**
* Set the UUID.
*
* @param uuid UUID
*/
public void setUuid(UUID uuid) {
this.uuid = uuid;
}
/** /**
* Get the InetAddress Set. * Get the InetAddress Set.
* *
@ -378,6 +344,17 @@ public class UserData {
return ips; 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. * Get the nickname String Set.
* *
@ -387,6 +364,17 @@ public class UserData {
return nicknames; 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. * Get the Epoch millisecond the player registered.
* *
@ -397,8 +385,17 @@ public class UserData {
} }
/** /**
* Get the Epoch millisecond the player was last seen. * 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 * NOT INITIALIZED BY CONSTRUCTORS. Value is updated periodically by cache
* if the player is online. * if the player is online.
* *
@ -409,8 +406,20 @@ public class UserData {
} }
/** /**
* Get the playtime in milliseconds. * 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 * NOT INITIALIZED BY CONSTRUCTORS. Value is updated periodically by cache
* if the player is online. * if the player is online.
* *
@ -421,8 +430,17 @@ public class UserData {
} }
/** /**
* Get how many times the player has logged in. * 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. * NOT INITIALIZED BY CONSTRUCTORS.
* *
* @return 0 to Integer.MAX * @return 0 to Integer.MAX
@ -432,8 +450,19 @@ public class UserData {
} }
/** /**
* Get how many times the player has been kicked. * 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. * NOT INITIALIZED BY CONSTRUCTORS.
* *
* @return 0 to Integer.MAX * @return 0 to Integer.MAX
@ -443,36 +472,42 @@ public class UserData {
} }
/** /**
* Get the GMTimes Map. * Set how many times the user has been kicked.
* <p>
* No check for input.
* *
* @return a GameMode map with 4 keys: SURVIVAL, CREATIVE, ADVENTURE, * @param timesKicked 0 to Int.MAX
* SPECTATOR.
*/ */
public Map<String, Long> getGmTimes() { public void setTimesKicked(int timesKicked) {
if (gmTimes == null) { this.timesKicked = timesKicked;
gmTimes = new HashMap<>();
} }
/**
* Get the GMTimes object.
*
* @return TimeKeeper object with possible keys of SURVIVAL, CREATIVE, ADVENTURE, SPECTATOR
*/
public GMTimes getGmTimes() {
return gmTimes; return gmTimes;
} }
/** /**
* Get the last time a Gamemode time was updated. * Set the GM Times object containing playtime in each gamemode.
* *
* @return Epoch millisecond of last GM Time update. * @param gmTimes GM Times object
*/ */
public long getLastGmSwapTime() { public void setGmTimes(GMTimes gmTimes) {
return lastGmSwapTime; if (Verify.notNull(gmTimes)) {
this.gmTimes = gmTimes;
}
} }
/** public void setGmTimes(Map<String, Long> times) {
* Get the last Gamemode that the user was seen in. if (Verify.notNull(times)) {
* for (Map.Entry<String, Long> entry : times.entrySet()) {
* When player changes to SURVIVAL this is set to SURVIVAL. gmTimes.setTime(entry.getKey(), entry.getValue());
* }
* @return Gamemode. }
*/
public String getLastGamemode() {
return lastGamemode;
} }
/** /**
@ -493,6 +528,15 @@ public class UserData {
return 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. * Get the username of the player.
* *
@ -502,132 +546,6 @@ public class UserData {
return name; return name;
} }
/**
* Set the UUID.
*
* @param uuid UUID
*/
public void setUuid(UUID uuid) {
this.uuid = uuid;
}
/**
* Set the ips set.
*
* @param ips ips of the user.
*/
public void setIps(Set<InetAddress> ips) {
if (Verify.notNull(ips)) {
this.ips = ips;
}
}
/**
* Set the nicknames set.
*
* @param nicknames nicknames of the user.
*/
public void setNicknames(Set<String> nicknames) {
if (Verify.notNull(nicknames)) {
this.nicknames = nicknames;
}
}
/**
* Set the time the user was registered.
*
* @param registered Epoch millisecond of register time.
*/
public void setRegistered(long registered) {
this.registered = registered;
}
/**
* Set the time the user was last seen.
*
* 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;
}
/**
* Set the time the user has been playing.
*
* @param playTime Time in ms.
*/
public void setPlayTime(long playTime) {
this.playTime = playTime;
}
/**
* Set how many times the user has logged in.
*
* No check for input.
*
* @param loginTimes 0 to Int.MAX
*/
public void setLoginTimes(int loginTimes) {
this.loginTimes = loginTimes;
}
/**
* Set how many times the user has been kicked.
*
* No check for input.
*
* @param timesKicked 0 to Int.MAX
*/
public void setTimesKicked(int timesKicked) {
this.timesKicked = timesKicked;
}
/**
* Set the GM Times map containing playtime in each gamemode.
*
* @param gmTimes Map containing SURVIVAL, CREATIVE, ADVENTURE and SPECTATOR
* (After 1.8) keys.
*/
public void setGmTimes(Map<String, Long> gmTimes) {
if (Verify.notNull(gmTimes)) {
this.gmTimes = gmTimes;
}
}
/**
* Set the last time a Gamemode time was updated.
*
* @param lastGmSwapTime Epoch millisecond a gm time was updated.
*/
public void setLastGmSwapTime(long lastGmSwapTime) {
this.lastGmSwapTime = lastGmSwapTime;
}
/**
* Set the last gamemode the user was seen in.
*
* @param lastGamemode gamemode.
*/
public void setLastGamemode(String lastGamemode) {
this.lastGamemode = lastGamemode;
}
/**
* Set whether or not player is op.
*
* @param isOp operator?
*/
public void setIsOp(boolean isOp) {
this.isOp = isOp;
}
public void setGeolocation(String geolocation) {
this.geolocation = geolocation;
}
/** /**
* Set the username of the user. * Set the username of the user.
* *
@ -637,6 +555,15 @@ public class UserData {
this.name = 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? * Is the player online?
* *
@ -646,6 +573,15 @@ public class UserData {
return 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. * Get how many mob kills the player has.
* *
@ -722,7 +658,7 @@ public class UserData {
/** /**
* Get the last nickname the user has set. * Get the last nickname the user has set.
* * <p>
* Set when using addNickname(String) * Set when using addNickname(String)
* *
* @return last nickname used. * @return last nickname used.
@ -733,7 +669,7 @@ public class UserData {
/** /**
* Set the last nickname the user has set. * Set the last nickname the user has set.
* * <p>
* Also set when using addNickname(String) * Also set when using addNickname(String)
* *
* @param lastNick last nickname used. * @param lastNick last nickname used.
@ -742,39 +678,13 @@ public class UserData {
this.lastNick = lastNick; this.lastNick = lastNick;
} }
@Override
public boolean equals(Object obj) { public WorldTimes getWorldTimes() {
if (this == obj) { return worldTimes;
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
} }
final UserData other = (UserData) obj; public void setWorldTimes(WorldTimes worldTimes) {
// if (this.lastPlayed != other.lastPlayed) { this.worldTimes = worldTimes;
// return false;
// }
return this.registered == other.registered
&& this.playTime == other.playTime
&& this.loginTimes == other.loginTimes
&& this.timesKicked == other.timesKicked
&& this.lastGmSwapTime == other.lastGmSwapTime
&& 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.lastGamemode, other.lastGamemode)
&& Objects.equals(this.gmTimes, other.gmTimes)
&& Objects.equals(this.playerKills, other.playerKills)
&& Objects.equals(this.sessions, other.sessions);
} }
/** /**
@ -797,25 +707,69 @@ public class UserData {
this.clearAfterSave = clearAfterSave; this.clearAfterSave = clearAfterSave;
} }
/**
* Set the banned value.
*
* @param isBanned true/false
*/
public void setBanned(boolean isBanned) {
this.isBanned = isBanned;
}
/**
* Set the online value.
*
* @param isOnline true/false
*/
public void setOnline(boolean isOnline) {
this.isOnline = isOnline;
}
public String getGeolocation() { public String getGeolocation() {
return geolocation; 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

@ -3,10 +3,10 @@ package main.java.com.djrapitops.plan.data.additional;
/** /**
* This class contains Enum values for different types of Analysis that can be * This class contains Enum values for different types of Analysis that can be
* performed on values of PluginData. * performed on values of PluginData.
* * <p>
* The enum determines what should be done to the return value of * The enum determines what should be done to the return value of
* PluginData.getValue() method when the analysis is run. * PluginData.getValue() method when the analysis is run.
* * <p>
* Refer to the documentation on GitHub for additional information. * Refer to the documentation on GitHub for additional information.
* *
* @author Rsl1122 * @author Rsl1122
@ -17,56 +17,56 @@ public enum AnalysisType {
/** /**
* Used when the getValue() method returns an integer and average should be * Used when the getValue() method returns an integer and average should be
* calculated. * calculated.
* * <p>
* -1 values will be disregarded from the calculation (size will not grow). * -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 * Used when the getValue() method returns a long and average should be
* calculated. * calculated.
* * <p>
* -1 values will be disregarded from the calculation (size will not grow). * -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 * Used when the getValue() method returns double and average should be
* calculated. * calculated.
* * <p>
* -1 values will be disregarded from the calculation (size will not grow). * -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 * Used when the getValue() method returns an integer and total should be
* calculated. * calculated.
* * <p>
* -1 values will be disregarded from the calculation (size will not grow). * -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 * Used when the getValue() method returns a long and total should be
* calculated. * calculated.
* * <p>
* -1 values will be disregarded from the calculation (size will not grow). * -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 * Used when the getValue() method returns a double and total should be
* calculated. * calculated.
* * <p>
* -1 values will be disregarded from the calculation (size will not grow). * -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 * Used when the getValue() method returns an amount of milliseconds as long
* and average should be calculated. * and average should be calculated.
* * <p>
* -1 values will be disregarded from the calculation (size will not grow). * -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 * Used when the getValue() method returns an amount of milliseconds as long
* and total should be calculated. * and total should be calculated.
* * <p>
* -1 values will be disregarded from the calculation (size will not grow). * -1 values will be disregarded from the calculation (size will not grow).
*/ */
LONG_TIME_MS_TOTAL("totalTimeMs_"), LONG_TIME_MS_TOTAL("totalTimeMs_"),
@ -74,11 +74,11 @@ public enum AnalysisType {
* Used when the getValue() method returns an Epoch Millisecond as long and * Used when the getValue() method returns an Epoch Millisecond as long and
* average of differences between the millisecond and current millisecond * average of differences between the millisecond and current millisecond
* should be calculated. * should be calculated.
* * <p>
* For example if a player has dropped a Foo on epoch ms 1494486504000 and * For example if a player has dropped a Foo on epoch ms 1494486504000 and
* that was 5s (5000ms) ago. Now you want to calculate the average * that was 5s (5000ms) ago. Now you want to calculate the average
* time-since for all players. Then you use this one. * time-since for all players. Then you use this one.
* * <p>
* -1 values will be disregarded from the calculation (size will not grow). * -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 "),
@ -89,13 +89,13 @@ public enum AnalysisType {
/** /**
* Used to calculate number of true values for the returned boolean values * Used to calculate number of true values for the returned boolean values
* of getValue(). * of getValue().
* * <p>
* Will be presented as "n / total". * Will be presented as "n / total".
*/ */
BOOLEAN_TOTAL("totalBool_"), BOOLEAN_TOTAL("totalBool_"),
/** /**
* Used to add html tags to the plugins tab. * Used to add html tags to the plugins tab.
* * <p>
* Can be used to add Tables, Images (for example maps) and other html * Can be used to add Tables, Images (for example maps) and other html
* elements. * elements.
*/ */
@ -121,7 +121,7 @@ public enum AnalysisType {
/** /**
* Used to get the modifier for the Prefix of the value. * Used to get the modifier for the Prefix of the value.
* * <p>
* For example: "Average Votes" when INT_AVG is used and Prefix is set as * For example: "Average Votes" when INT_AVG is used and Prefix is set as
* "Votes". * "Votes".
* *

View File

@ -30,7 +30,7 @@ public class HookHandler {
configHandler = new PluginConfigSectionHandler(plugin); configHandler = new PluginConfigSectionHandler(plugin);
try { try {
Bridge.hook(this); Bridge.hook(this);
} catch (Throwable e) { } catch (Exception e) {
Log.toLog(this.getClass().getName(), e); Log.toLog(this.getClass().getName(), e);
Log.error("Plan Plugin Bridge not included in the plugin jar."); Log.error("Plan Plugin Bridge not included in the plugin jar.");
} }
@ -38,10 +38,10 @@ public class HookHandler {
/** /**
* Adds a new PluginData source to the list. * Adds a new PluginData source to the list.
* * <p>
* The plugin data will appear on Analysis and/or Inspect pages depending on * The plugin data will appear on Analysis and/or Inspect pages depending on
* how the extending object is set up. * how the extending object is set up.
* * <p>
* Refer to documentation on GitHub for more information. * Refer to documentation on GitHub for more information.
* *
* @param dataSource an object extending the PluginData class. * @param dataSource an object extending the PluginData class.

View File

@ -8,7 +8,7 @@ import java.util.*;
/** /**
* This is an abstract class that can be used to add data from a plugin to the * This is an abstract class that can be used to add data from a plugin to the
* "Plugins"-tab of Analysis and Inspect pages. * "Plugins"-tab of Analysis and Inspect pages.
* * <p>
* API-section of documentation has examples on the usage of this class and how * API-section of documentation has examples on the usage of this class and how
* to register objects extending this class. * to register objects extending this class.
* *
@ -17,65 +17,59 @@ import java.util.*;
*/ */
public abstract class PluginData { public abstract class PluginData {
/**
* A list containing the AnalysisType enums that determine what should be
* done with the data on the analysis page.
*/
protected final List<AnalysisType> analysisTypes;
/** /**
* Placeholder string, for example "stepsTaken". This will be used when * Placeholder string, for example "stepsTaken". This will be used when
* building the structure of the Plugins tab. * building the structure of the Plugins tab.
* * <p>
* The complete placeholder also includes the plugin name and if analysis is * The complete placeholder also includes the plugin name and if analysis is
* run, a modifier. * run, a modifier.
* * <p>
* Second parameter of any super constructor. * Second parameter of any super constructor.
*/ */
protected String placeholder; protected String placeholder;
/** /**
* Name of the plugin the data is coming from. * Name of the plugin the data is coming from.
* * <p>
* All sources of data with the same sourcePlugin will be placed in the same * All sources of data with the same sourcePlugin will be placed in the same
* "box" in the "Plugins" tab. * "box" in the "Plugins" tab.
* * <p>
* A box has a max height of 600px, and higher than that will add a * A box has a max height of 600px, and higher than that will add a
* scrollbar. * scrollbar.
* * <p>
* First parameter of any super constructor. * First parameter of any super constructor.
*/ */
protected String sourcePlugin; protected String sourcePlugin;
/** /**
* Determines if the datapoint should only be used for the analysis page. * Determines if the datapoint should only be used for the analysis page.
* * <p>
* If set to false, the datapoint will be added to the inspect page as well. * If set to false, the datapoint will be added to the inspect page as well.
*/ */
protected boolean analysisOnly; protected boolean analysisOnly;
/** /**
* Font Awesome icon name. * Font Awesome icon name.
* * <p>
* http://fontawesome.io/icons/ * http://fontawesome.io/icons/
*/ */
protected String icon; protected String icon;
/** /**
* Prefix shown before the data, for example "Steps taken: ". * Prefix shown before the data, for example "Steps taken: ".
*/ */
protected String prefix; protected String prefix;
/** /**
* Suffix shown after the data, for example " steps". * Suffix shown after the data, for example " steps".
*/ */
protected String suffix; protected String suffix;
/**
* A list containing the AnalysisType enums that determine what should be
* done with the data on the analysis page.
*/
protected final List<AnalysisType> analysisTypes;
/** /**
* Main constructor. * Main constructor.
* * <p>
* Defaults analysisOnly to true. * Defaults analysisOnly to true.
* * <p>
* Defaults icon, prefix and suffix to "". * Defaults icon, prefix and suffix to "".
* *
* @param sourcePlugin Name of the plugin the data is coming from * @param sourcePlugin Name of the plugin the data is coming from
@ -107,7 +101,7 @@ public abstract class PluginData {
/** /**
* Constructor for Inspect-page only data point. * Constructor for Inspect-page only data point.
* * <p>
* analysisOnly will be set to false. * analysisOnly will be set to false.
* *
* @param sourcePlugin Name of the plugin the data is coming from * @param sourcePlugin Name of the plugin the data is coming from
@ -120,7 +114,7 @@ public abstract class PluginData {
/** /**
* Returns the list of AnalysisTypes. * Returns the list of AnalysisTypes.
* * <p>
* Used by Analysis * Used by Analysis
* *
* @return a list. * @return a list.
@ -132,7 +126,7 @@ public abstract class PluginData {
/** /**
* This method should be used with the return values of * This method should be used with the return values of
* getHtmlReplaceValue(String, UUID). * getHtmlReplaceValue(String, UUID).
* * <p>
* It will add the div, icon, modifier, prefix and suffix to the value. * It will add the div, icon, modifier, prefix and suffix to the value.
* Modifier is for example, if calculating AnalysisType.INT_AVG "Average ", * Modifier is for example, if calculating AnalysisType.INT_AVG "Average ",
* it is a text that helps user understand that a calculation has been made. * it is a text that helps user understand that a calculation has been made.
@ -150,7 +144,7 @@ public abstract class PluginData {
/** /**
* Used to get the full placeholder. * Used to get the full placeholder.
* * <p>
* Used to avoid conflicts with existing placeholders and placeholders of * Used to avoid conflicts with existing placeholders and placeholders of
* other plugins. * other plugins.
* *
@ -174,13 +168,13 @@ public abstract class PluginData {
/** /**
* Used to get the string for the html page. * Used to get the string for the html page.
* * <p>
* parseContainer(modifierPrefix, value); should be used for all return * parseContainer(modifierPrefix, value); should be used for all return
* values so that div, icon, prefix and suffix are added. * values so that div, icon, prefix and suffix are added.
* * <p>
* This method is used when AnalysisType.HTML is set, or while getting the * This method is used when AnalysisType.HTML is set, or while getting the
* value for the inspect page. * value for the inspect page.
* * <p>
* When using AnalysisType.HTML a random UUID is given, so it should be * When using AnalysisType.HTML a random UUID is given, so it should be
* disregarded. modifierPrefix is empty in that case. * disregarded. modifierPrefix is empty in that case.
* *
@ -196,10 +190,10 @@ public abstract class PluginData {
* Used to get the value for analysis. The return value is determined by * Used to get the value for analysis. The return value is determined by
* AnalysisType you have specified. If the AnalysisType's name has a BOOLEAN * AnalysisType you have specified. If the AnalysisType's name has a BOOLEAN
* in it, Analysis will expect boolean values etc. * in it, Analysis will expect boolean values etc.
* * <p>
* If the Type and return value mismatch, exception is thrown and the result * If the Type and return value mismatch, exception is thrown and the result
* on the analysis page will say that error occurred as the value. * on the analysis page will say that error occurred as the value.
* * <p>
* If a player has no value a -1 should be returned in the case of a Number. * If a player has no value a -1 should be returned in the case of a Number.
* -1 is excluded from the Average calculation's size and total. * -1 is excluded from the Average calculation's size and total.
* *
@ -209,24 +203,6 @@ public abstract class PluginData {
*/ */
public abstract Serializable getValue(UUID uuid); public abstract Serializable getValue(UUID uuid);
/**
* Used to set the prefix.
*
* @param prefix for example "Steps Taken: " or a Html start tag.
*/
public final void setPrefix(String prefix) {
this.prefix = prefix;
}
/**
* Used to set the suffix.
*
* @param suffix for example " steps" or a html end tag.
*/
public final void setSuffix(String suffix) {
this.suffix = suffix;
}
/** /**
* Used to set the Font Awesome icon. * Used to set the Font Awesome icon.
* *
@ -238,7 +214,7 @@ public abstract class PluginData {
/** /**
* Used to set the analysisOnly parameter. * Used to set the analysisOnly parameter.
* * <p>
* true: only used for Analysis page false: used for both if AnalysisTypes * true: only used for Analysis page false: used for both if AnalysisTypes
* specified, if no AnalysisTypes are specified only used for Inspect page. * specified, if no AnalysisTypes are specified only used for Inspect page.
* *
@ -266,6 +242,15 @@ public abstract class PluginData {
return prefix; return prefix;
} }
/**
* Used to set the prefix.
*
* @param prefix for example "Steps Taken: " or a Html start tag.
*/
public final void setPrefix(String prefix) {
this.prefix = prefix;
}
/** /**
* Used to get the suffix. * Used to get the suffix.
* *
@ -275,6 +260,15 @@ public abstract class PluginData {
return suffix; return suffix;
} }
/**
* Used to set the suffix.
*
* @param suffix for example " steps" or a html end tag.
*/
public final void setSuffix(String suffix) {
this.suffix = suffix;
}
/** /**
* If a PluginData object has same placeholder, sourcePlugin and * If a PluginData object has same placeholder, sourcePlugin and
* analysisTypes, it is considered equal. * analysisTypes, it is considered equal.

View File

@ -2,13 +2,6 @@ package main.java.com.djrapitops.plan.data.analysis;
import com.djrapitops.plugin.api.TimeAmount; import com.djrapitops.plugin.api.TimeAmount;
import com.djrapitops.plugin.utilities.Verify; import com.djrapitops.plugin.utilities.Verify;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import main.java.com.djrapitops.plan.Settings; import main.java.com.djrapitops.plan.Settings;
import main.java.com.djrapitops.plan.data.SessionData; import main.java.com.djrapitops.plan.data.SessionData;
import main.java.com.djrapitops.plan.data.TPS; import main.java.com.djrapitops.plan.data.TPS;
@ -19,17 +12,21 @@ 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.ui.html.graphs.SessionLengthDistributionGraphCreator;
import main.java.com.djrapitops.plan.utilities.FormatUtils; import main.java.com.djrapitops.plan.utilities.FormatUtils;
import main.java.com.djrapitops.plan.utilities.HtmlUtils; 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.AnalysisUtils;
import main.java.com.djrapitops.plan.utilities.analysis.MathUtils; import main.java.com.djrapitops.plan.utilities.analysis.MathUtils;
import java.util.*;
import java.util.stream.Collectors;
/** /**
* Part responsible for all Player Activity related analysis. * Part responsible for all Player Activity related analysis.
* * <p>
* Online Graphs, Player-base pie-chart, Recent Players and Session * Online Graphs, Player-base pie-chart, Recent Players and Session
* visualisation. * visualisation.
* * <p>
* Placeholder values can be retrieved using the get method. * Placeholder values can be retrieved using the get method.
* * <p>
* Contains following place-holders: recentlogins, sessionaverage, * Contains following place-holders: recentlogins, sessionaverage,
* datapunchcard, datasessiondistribution, labelssessiondistribution, * datapunchcard, datasessiondistribution, labelssessiondistribution,
* datascatterday, datascatterweek, datascattermonth, playersonlinecolor, * datascatterday, datascatterweek, datascattermonth, playersonlinecolor,
@ -40,18 +37,16 @@ import main.java.com.djrapitops.plan.utilities.analysis.MathUtils;
* @author Rsl1122 * @author Rsl1122
* @since 3.5.2 * @since 3.5.2
*/ */
public class ActivityPart extends RawData<ActivityPart> { public class ActivityPart extends RawData {
private final JoinInfoPart joins; private final JoinInfoPart joins;
private final TPSPart tpsPart; private final TPSPart tpsPart;
private List<String> recentPlayers;
private List<UUID> recentPlayersUUIDs;
private final Set<UUID> bans; private final Set<UUID> bans;
private final Set<UUID> active; private final Set<UUID> active;
private final Set<UUID> inactive; private final Set<UUID> inactive;
private final Set<UUID> joinedOnce; private final Set<UUID> joinedOnce;
private List<String> recentPlayers;
private List<UUID> recentPlayersUUIDs;
public ActivityPart(JoinInfoPart joins, TPSPart tps) { public ActivityPart(JoinInfoPart joins, TPSPart tps) {
this.joins = joins; this.joins = joins;
@ -75,38 +70,29 @@ public class ActivityPart extends RawData<ActivityPart> {
final List<SessionData> sessions = joins.getAllSessions(); final List<SessionData> sessions = joins.getAllSessions();
long averageLength = MathUtils.averageLong(AnalysisUtils.transformSessionDataToLengths(sessions)); List<Long> lengths = AnalysisUtils.transformSessionDataToLengths(sessions);
long averageLength = MathUtils.averageLong(lengths);
addValue("sessionaverage", FormatUtils.formatTimeAmount(averageLength)); addValue("sessionaverage", FormatUtils.formatTimeAmount(averageLength));
String punchCardArray = PunchCardGraphCreator.generateDataArray(sessions); List<SessionData> sessionsMonth = sessions.stream()
addValue("datapunchcard", punchCardArray); .filter(s -> s.getSessionStart() > MiscUtils.getTime() - TimeAmount.MONTH.ms())
.collect(Collectors.toList());
String[] sessionDistribution = SessionLengthDistributionGraphCreator.generateDataArraySessions(sessions); addValue("punchcardseries", PunchCardGraphCreator.createDataSeries(sessionsMonth));
addValue("datasessiondistribution", sessionDistribution[0]); addValue("sessionlengthseries", SessionLengthDistributionGraphCreator.createDataSeries(lengths));
addValue("labelssessiondistribution", sessionDistribution[1]);
} }
private void playerActivityGraphs() { private void playerActivityGraphs() {
List<TPS> tpsData = tpsPart.getTpsData(); List<TPS> tpsData = tpsPart.getTpsData();
addValue("playersonlineseries", PlayerActivityGraphCreator.buildSeriesDataString(tpsData));
String dayScatter = PlayerActivityGraphCreator.buildScatterDataString(tpsData, TimeAmount.DAY.ms()); addValue("%playersgraphcolor%", Settings.HCOLOR_ACT_ONL.toString());
String weekScatter = PlayerActivityGraphCreator.buildScatterDataString(tpsData, TimeAmount.WEEK.ms());
String monthScatter = PlayerActivityGraphCreator.buildScatterDataString(tpsData, TimeAmount.MONTH.ms());
addValue("datascatterday", dayScatter);
addValue("datascatterweek", weekScatter);
addValue("datascattermonth", monthScatter);
addValue("%playersgraphcolor%", Settings.HCOLOR_ACT_ONL + "");
addValue("%playersgraphfill%", Settings.HCOLOR_ACT_ONL_FILL + "");
} }
private void activityPiechart() { private void activityPiechart() {
int[] counts = new int[]{active.size(), inactive.size(), joinedOnce.size(), bans.size()}; int[] counts = new int[]{active.size(), inactive.size(), joinedOnce.size(), bans.size()};
final String colAct = Settings.HCOLOR_ACTP_ACT + ""; final String colAct = Settings.HCOLOR_ACTP_ACT.toString();
final String colIna = Settings.HCOLOR_ACTP_INA + ""; final String colIna = Settings.HCOLOR_ACTP_INA.toString();
final String colJoi = Settings.HCOLOR_ACTP_JON + ""; final String colJoi = Settings.HCOLOR_ACTP_JON.toString();
final String colBan = Settings.HCOLOR_ACTP_BAN + ""; final String colBan = Settings.HCOLOR_ACTP_BAN.toString();
addValue("%activecol%", colAct); addValue("%activecol%", colAct);
addValue("%inactivecol%", colIna); addValue("%inactivecol%", colIna);
@ -149,14 +135,6 @@ public class ActivityPart extends RawData<ActivityPart> {
joinedOnce.add(uuid); joinedOnce.add(uuid);
} }
public void setRecentPlayers(List<String> recentPlayers) {
this.recentPlayers = recentPlayers;
}
public void setRecentPlayersUUIDs(List<UUID> recentPlayersUUIDs) {
this.recentPlayersUUIDs = recentPlayersUUIDs;
}
public Map<Long, Integer> getPlayersOnline() { public Map<Long, Integer> getPlayersOnline() {
return tpsPart.getTpsData().stream().collect(Collectors.toMap(TPS::getDate, TPS::getPlayers)); return tpsPart.getTpsData().stream().collect(Collectors.toMap(TPS::getDate, TPS::getPlayers));
} }
@ -165,10 +143,18 @@ public class ActivityPart extends RawData<ActivityPart> {
return recentPlayers; return recentPlayers;
} }
public void setRecentPlayers(List<String> recentPlayers) {
this.recentPlayers = recentPlayers;
}
public List<UUID> getRecentPlayersUUIDs() { public List<UUID> getRecentPlayersUUIDs() {
return recentPlayersUUIDs; return recentPlayersUUIDs;
} }
public void setRecentPlayersUUIDs(List<UUID> recentPlayersUUIDs) {
this.recentPlayersUUIDs = recentPlayersUUIDs;
}
public Set<UUID> getBans() { public Set<UUID> getBans() {
return bans; return bans;
} }

View File

@ -5,23 +5,24 @@
*/ */
package main.java.com.djrapitops.plan.data.analysis; package main.java.com.djrapitops.plan.data.analysis;
import java.util.Map;
import main.java.com.djrapitops.plan.ui.html.tables.CommandUseTableCreator; 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.HtmlUtils;
import java.util.Map;
/** /**
* Part responsible for all CommandUsage related analysis. * Part responsible for all CommandUsage related analysis.
* * <p>
* Command Usage Table. * Command Usage Table.
* * <p>
* Placeholder values can be retrieved using the get method. * Placeholder values can be retrieved using the get method.
* * <p>
* Contains following place-holders: uniquecommands, totalcommands, commanduse * Contains following place-holders: uniquecommands, totalcommands, commanduse
* *
* @author Rsl1122 * @author Rsl1122
* @since 3.5.2 * @since 3.5.2
*/ */
public class CommandUsagePart extends RawData<CommandUsagePart> { public class CommandUsagePart extends RawData {
private final Map<String, Integer> commandUsage; private final Map<String, Integer> commandUsage;
@ -31,8 +32,8 @@ public class CommandUsagePart extends RawData<CommandUsagePart> {
@Override @Override
public void analyse() { public void analyse() {
addValue("uniquecommands", getUniqueCommands() + ""); addValue("uniquecommands", String.valueOf(getUniqueCommands()));
addValue("totalcommands", getCommandTotal() + ""); addValue("totalcommands", String.valueOf(getCommandTotal()));
String commandUsageTable = CommandUseTableCreator.createSortedCommandUseTable(commandUsage); String commandUsageTable = CommandUseTableCreator.createSortedCommandUseTable(commandUsage);
addValue("commanduse", HtmlUtils.removeXSS(commandUsageTable)); addValue("commanduse", HtmlUtils.removeXSS(commandUsageTable));
} }

View File

@ -9,18 +9,18 @@ import java.util.Arrays;
/** /**
* Part responsible for all Gamemode usage related analysis. * Part responsible for all Gamemode usage related analysis.
* * <p>
* Gamemode Piechart, Percentages and Totals. * Gamemode Piechart, Percentages and Totals.
* * <p>
* Placeholder values can be retrieved using the get method. * Placeholder values can be retrieved using the get method.
* * <p>
* Contains following place-holders: gmtotal, gm0col-gm3col, gmcolors, gmlabels, * Contains following place-holders: gmtotal, gm0col-gm3col, gmcolors, gmlabels,
* gm0-gm3, gmdata, gm0total-gm3total * gm0-gm3, gmdata, gm0total-gm3total
* *
* @author Rsl1122 * @author Rsl1122
* @since 3.5.2 * @since 3.5.2
*/ */
public class GamemodePart extends RawData<GamemodePart> { public class GamemodePart extends RawData {
private long survivalTime; private long survivalTime;
private long creativeTime; private long creativeTime;
@ -53,10 +53,10 @@ public class GamemodePart extends RawData<GamemodePart> {
long[] times = new long[]{ long[] times = new long[]{
survivalTime, creativeTime, adventureTime, spectatorTime survivalTime, creativeTime, adventureTime, spectatorTime
}; };
String col0 = Settings.HCOLOR_GMP_0 + ""; String col0 = Settings.HCOLOR_GMP_0.toString();
String col1 = Settings.HCOLOR_GMP_1 + ""; String col1 = Settings.HCOLOR_GMP_1.toString();
String col2 = Settings.HCOLOR_GMP_2 + ""; String col2 = Settings.HCOLOR_GMP_2.toString();
String col3 = Settings.HCOLOR_GMP_3 + ""; String col3 = Settings.HCOLOR_GMP_3.toString();
addValue("%gm0col%", col0); addValue("%gm0col%", col0);
addValue("%gm1col%", col1); addValue("%gm1col%", col1);

View File

@ -1,79 +1,51 @@
package main.java.com.djrapitops.plan.data.analysis; package main.java.com.djrapitops.plan.data.analysis;
import main.java.com.djrapitops.plan.ui.html.graphs.WorldMapCreator;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
/** /**
* Part responsible for all Geolocation related analysis. * Part responsible for all Geolocation related analysis.
* * <p>
* Player location World Chloropleth map. * Player location World Choropleth map.
* * <p>
* Placeholder values can be retrieved using the get method. * Placeholder values can be retrieved using the get method.
* * <p>
* Contains following place-holders: geomapz, geomapcountries, geomapcodes * Contains following place-holders: geomapz, geomapcountries, geomapcodes
* *
* @author Rsl1122 * @author Rsl1122
* @since 3.5.2 * @since 3.5.2
*/ */
public class GeolocationPart extends RawData<GeolocationPart> { public class GeolocationPart extends RawData {
private final Map<String, Integer> geolocations;
private final Map<String, String> geoCodes; private final Map<String, String> geoCodes;
private final Map<String, Integer> geoCodeCounts;
public GeolocationPart() { public GeolocationPart() {
geolocations = new HashMap<>();
geoCodes = new HashMap<>(); geoCodes = new HashMap<>();
geoCodeCounts = 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[] 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"}; 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"};
for (int i = 0; i < countries.length; i++) { for (int i = 0; i < countries.length; i++) {
String country = countries[i]; String country = countries[i];
geolocations.put(country, 0); String countryCode = codes[i];
geoCodes.put(country, codes[i]);
geoCodes.put(country, countryCode);
geoCodeCounts.put(countryCode, 0);
} }
} }
@Override @Override
public void analyse() { public void analyse() {
cloroplethMapValues(); addValue("geomapseries", WorldMapCreator.createDataSeries(geoCodeCounts));
} }
private void cloroplethMapValues() { public void addGeolocation(String country) {
StringBuilder locations = new StringBuilder(); String countryCode = geoCodes.get(country);
StringBuilder z = new StringBuilder(); if (countryCode != null) {
StringBuilder text = new StringBuilder(); geoCodeCounts.computeIfPresent(countryCode, (computedCountry, amount) -> amount + 1);
locations.append("[");
z.append("[");
text.append("[");
int i = 0;
int size = geolocations.size();
for (String c : geolocations.keySet()) {
locations.append("\"").append(c).append("\"");
z.append("\"").append(geolocations.get(c)).append("\"");
text.append("\"");
String code = geoCodes.get(c);
if (code != null) {
text.append(code);
} else {
text.append("UNK");
}
text.append("\"");
if (i < size - 1) {
locations.append(",");
z.append(",");
text.append(",");
} }
} }
locations.append("]");
z.append("]");
text.append("]");
addValue("geomapz", z.toString());
addValue("geomapcountries", locations.toString());
addValue("geomapcodes", text.toString());
}
public void addGeoloc(String country) {
geolocations.computeIfPresent(country, (computedCountry, amount) -> amount + 1);
}
} }

View File

@ -11,19 +11,20 @@ import java.util.stream.Collectors;
/** /**
* Part responsible for all Player login related analysis. * Part responsible for all Player login related analysis.
* * <p>
* Unique per Day, Unique, New Players, Logins * Unique per Day, Unique, New Players, Logins
* * <p>
* Placeholder values can be retrieved using the get method. * Placeholder values can be retrieved using the get method.
* * <p>
* Contains following place-holders: totallogins, uniquejoinsday, * Contains following place-holders: totallogins, uniquejoinsday,
* uniquejoinsweek, uniquejoinsmonth, avguniquejoins, avguniquejoinsday, * uniquejoinsweek, uniquejoinsmonth, avguniquejoins, avguniquejoinsday,
* avguniquejoinsweek, avguniquejoinsmonth, npday, npweek, npmonth * avguniquejoinsweek, avguniquejoinsmonth, npday, npweek, npmonth,
* npdataday, npdataweek, npdatamonth, newperday, newperdayday, newperdayweek, newperdaymonth
* *
* @author Rsl1122 * @author Rsl1122
* @since 3.5.2 * @since 3.5.2
*/ */
public class JoinInfoPart extends RawData<JoinInfoPart> { public class JoinInfoPart extends RawData {
private final Map<UUID, List<SessionData>> sessions; private final Map<UUID, List<SessionData>> sessions;
private final List<Long> registered; private final List<Long> registered;
@ -67,13 +68,24 @@ public class JoinInfoPart extends RawData<JoinInfoPart> {
} }
private void newPlayers() { private void newPlayers() {
int newDay = AnalysisUtils.getNewPlayers(registered, TimeAmount.DAY.ms(), MiscUtils.getTime()); long now = MiscUtils.getTime();
int newWeek = AnalysisUtils.getNewPlayers(registered, TimeAmount.WEEK.ms(), MiscUtils.getTime()); long newDay = AnalysisUtils.getNewPlayers(registered, TimeAmount.DAY.ms(), now);
int newMonth = AnalysisUtils.getNewPlayers(registered, TimeAmount.MONTH.ms(), MiscUtils.getTime()); long newWeek = AnalysisUtils.getNewPlayers(registered, TimeAmount.WEEK.ms(), now);
long newMonth = AnalysisUtils.getNewPlayers(registered, TimeAmount.MONTH.ms(), now);
addValue("npday", newDay); addValue("npday", newDay);
addValue("npweek", newWeek); addValue("npweek", newWeek);
addValue("npmonth", newMonth); addValue("npmonth", 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());
addValue("newperday", newPerDay);
addValue("newperdayday", newPerDayDay);
addValue("newperdayweek", newPerDayWeek);
addValue("newperdaymonth", newPerDayMonth);
} }
public void addToLoginTimes() { public void addToLoginTimes() {

View File

@ -3,6 +3,7 @@ package main.java.com.djrapitops.plan.data.analysis;
import com.djrapitops.plugin.utilities.Verify; import com.djrapitops.plugin.utilities.Verify;
import main.java.com.djrapitops.plan.data.KillData; import main.java.com.djrapitops.plan.data.KillData;
import main.java.com.djrapitops.plan.utilities.MiscUtils; import main.java.com.djrapitops.plan.utilities.MiscUtils;
import main.java.com.djrapitops.plan.utilities.analysis.MathUtils;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -11,19 +12,19 @@ import java.util.UUID;
/** /**
* Part responsible for all Death related analysis. * Part responsible for all Death related analysis.
* * <p>
* Totals * Totals
* * <p>
* Placeholder values can be retrieved using the get method. * Placeholder values can be retrieved using the get method.
* * <p>
* Contains following place-holders: deaths, mobkills, playerkilss * Contains following place-holders: deaths, mobkills, playerkills, avgdeaths, avgmobkills, avgplayerkills
* *
* @author Rsl1122 * @author Rsl1122
* @since 3.5.2 * @since 3.5.2
*/ */
public class KillPart extends RawData<KillPart> { public class KillPart extends RawData {
private final PlayerCountPart playerCount; // TODO Averages private final PlayerCountPart playerCount;
private final Map<UUID, List<KillData>> playerKills; private final Map<UUID, List<KillData>> playerKills;
private long mobKills; private long mobKills;
private long deaths; private long deaths;
@ -39,7 +40,12 @@ public class KillPart extends RawData<KillPart> {
public void analyse() { public void analyse() {
addValue("deaths", deaths); addValue("deaths", deaths);
addValue("mobkills", mobKills); addValue("mobkills", mobKills);
addValue("playerkills", getAllPlayerKills().size()); int playerKillAmount = getAllPlayerKills().size();
addValue("playerkills", playerKillAmount);
int playerCount = this.playerCount.getPlayerCount();
addValue("avgdeaths", MathUtils.averageLong(deaths, playerCount));
addValue("avgmobkills", MathUtils.averageLong(mobKills, playerCount));
addValue("avgplayerkills", MathUtils.averageLong(playerKillAmount, playerCount));
} }
public void addKills(UUID uuid, List<KillData> kills) throws IllegalArgumentException { public void addKills(UUID uuid, List<KillData> kills) throws IllegalArgumentException {

View File

@ -1,6 +1,7 @@
package main.java.com.djrapitops.plan.data.analysis; package main.java.com.djrapitops.plan.data.analysis;
import com.djrapitops.plugin.utilities.Verify; import com.djrapitops.plugin.utilities.Verify;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
@ -8,17 +9,17 @@ import java.util.UUID;
/** /**
* Part responsible for counting players. * Part responsible for counting players.
* * <p>
* Total player count, op count * Total player count, op count
* * <p>
* Placeholder values can be retrieved using the get method. * Placeholder values can be retrieved using the get method.
* * <p>
* Contains following place-holders: activitytotal, ops * Contains following place-holders: activitytotal, ops
* *
* @author Rsl1122 * @author Rsl1122
* @since 3.5.2 * @since 3.5.2
*/ */
public class PlayerCountPart extends RawData<PlayerCountPart> { public class PlayerCountPart extends RawData {
private final Set<UUID> uuids; private final Set<UUID> uuids;
private final Set<UUID> ops; private final Set<UUID> ops;

View File

@ -5,18 +5,18 @@ import main.java.com.djrapitops.plan.utilities.analysis.MathUtils;
/** /**
* Part responsible for all Playtime related analysis. * Part responsible for all Playtime related analysis.
* * <p>
* Placeholder values can be retrieved using the get method. * Placeholder values can be retrieved using the get method.
* * <p>
* Contains following place-holders: totalplaytime, avgplaytime * Contains following place-holders: totalplaytime, avgplaytime
* *
* @author Rsl1122 * @author Rsl1122
* @since 3.5.2 * @since 3.5.2
*/ */
public class PlaytimePart extends RawData<PlaytimePart> { public class PlaytimePart extends RawData {
private long totalPlaytime;
private final PlayerCountPart playerCount; private final PlayerCountPart playerCount;
private long totalPlaytime;
public PlaytimePart(PlayerCountPart part) { public PlaytimePart(PlayerCountPart part) {
playerCount = part; playerCount = part;

View File

@ -1,6 +1,7 @@
package main.java.com.djrapitops.plan.data.analysis; package main.java.com.djrapitops.plan.data.analysis;
import com.djrapitops.plugin.utilities.Verify; import com.djrapitops.plugin.utilities.Verify;
import java.io.Serializable; import java.io.Serializable;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -9,10 +10,9 @@ import java.util.Map;
* Extending objects should represent, add together and analyse data. * Extending objects should represent, add together and analyse data.
* *
* @author Rsl1122 * @author Rsl1122
* @param <T> The extending class, return value for get method.
* @since 3.5.2 * @since 3.5.2
*/ */
public abstract class RawData<T extends RawData> { public abstract class RawData {
private final Map<String, String> replaceMap; private final Map<String, String> replaceMap;
@ -40,7 +40,7 @@ public abstract class RawData<T extends RawData> {
/** /**
* Analyses the data added together. * Analyses the data added together.
* * <p>
* Places place-holders to the replace map. * Places place-holders to the replace map.
*/ */
public void analyseData() { public void analyseData() {
@ -50,7 +50,7 @@ public abstract class RawData<T extends RawData> {
/** /**
* Subclasses should analyse the data added together. * Subclasses should analyse the data added together.
* * <p>
* Place-holders should be added to the replace map. * Place-holders should be added to the replace map.
*/ */
protected abstract void analyse(); protected abstract void analyse();
@ -78,10 +78,10 @@ public abstract class RawData<T extends RawData> {
private String addPlaceholderSigns(String placeholder) { private String addPlaceholderSigns(String placeholder) {
if (placeholder.charAt(0) != '%') { if (placeholder.charAt(0) != '%') {
placeholder = '%' + placeholder; placeholder = "%" + placeholder;
} }
if (placeholder.charAt(placeholder.length() - 1) != '%') { if (placeholder.charAt(placeholder.length() - 1) != '%') {
placeholder += '%'; placeholder += "%";
} }
return placeholder; return placeholder;
} }

View File

@ -3,7 +3,9 @@ package main.java.com.djrapitops.plan.data.analysis;
import com.djrapitops.plugin.api.TimeAmount; import com.djrapitops.plugin.api.TimeAmount;
import main.java.com.djrapitops.plan.data.TPS; 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.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.TPSGraphCreator;
import main.java.com.djrapitops.plan.ui.html.graphs.WorldLoadGraphCreator;
import main.java.com.djrapitops.plan.utilities.FormatUtils; import main.java.com.djrapitops.plan.utilities.FormatUtils;
import main.java.com.djrapitops.plan.utilities.MiscUtils; import main.java.com.djrapitops.plan.utilities.MiscUtils;
import main.java.com.djrapitops.plan.utilities.analysis.MathUtils; import main.java.com.djrapitops.plan.utilities.analysis.MathUtils;
@ -12,18 +14,19 @@ import java.util.List;
/** /**
* Part responsible for all TPS related analysis. * Part responsible for all TPS related analysis.
* * <p>
* Ticks Per Second Graphs * Ticks Per Second Graphs
* * <p>
* Placeholder values can be retrieved using the get method. * Placeholder values can be retrieved using the get method.
* * <p>
* Contains following place-holders: tpsscatterday, tpsscatterweek, cpuscatterday, cpuscatterweek, averagetps, * Contains following place-holders: tpsscatterday, tpsscatterweek, cpuscatterday, cpuscatterweek, averagetps(-week),
* averagetpsday * averagetpsday, averagecpuday, averagecpuweek, averagememoryday, averagememoryweek, averageentitiesday, averageentitiesweek,
* averagechunksday, averagechunkweek, ramscatterday, ramscatterweek
* *
* @author Rsl1122 * @author Rsl1122
* @since 3.5.2 * @since 3.5.2
*/ */
public class TPSPart extends RawData<TPSPart> { public class TPSPart extends RawData {
private final List<TPS> tpsData; private final List<TPS> tpsData;
@ -37,22 +40,43 @@ public class TPSPart extends RawData<TPSPart> {
List<TPS> week = TPSGraphCreator.filterTPS(tpsData, now - TimeAmount.WEEK.ms()); List<TPS> week = TPSGraphCreator.filterTPS(tpsData, now - TimeAmount.WEEK.ms());
List<TPS> day = TPSGraphCreator.filterTPS(tpsData, now - TimeAmount.DAY.ms()); List<TPS> day = TPSGraphCreator.filterTPS(tpsData, now - TimeAmount.DAY.ms());
String tpsScatterDay = TPSGraphCreator.buildScatterDataStringTPS(day, TimeAmount.DAY.ms());
String tpsScatterWeek = TPSGraphCreator.buildScatterDataStringTPS(week, TimeAmount.WEEK.ms());
String cpuScatterDay = CPUGraphCreator.buildScatterDataString(day, TimeAmount.DAY.ms());
String cpuScatterWeek = CPUGraphCreator.buildScatterDataString(week, TimeAmount.WEEK.ms());
addValue("tpsscatterday", tpsScatterDay); addValue("tpsseries", TPSGraphCreator.buildSeriesDataString(tpsData));
addValue("tpsscatterweek", tpsScatterWeek); addValue("cpuseries", CPUGraphCreator.buildSeriesDataString(tpsData));
addValue("ramseries", RamGraphCreator.buildSeriesDataString(tpsData));
addValue("entityseries", WorldLoadGraphCreator.buildSeriesDataStringEntities(tpsData));
addValue("chunkseries", WorldLoadGraphCreator.buildSeriesDataStringChunks(tpsData));
addValue("cpuscatterday", cpuScatterDay); double averageTPSWeek = MathUtils.averageDouble(week.stream().map(TPS::getTps));
addValue("cpuscatterweek", cpuScatterWeek); double averageTPSDay = MathUtils.averageDouble(day.stream().map(TPS::getTps));
double averageTPSweek = MathUtils.averageDouble(week.stream().map(TPS::getTps)); double averageCPUWeek = MathUtils.averageDouble(week.stream().map(TPS::getCPUUsage).filter(i -> i != 0));
double averageTPSday = MathUtils.averageDouble(day.stream().map(TPS::getTps)); double averageCPUDay = MathUtils.averageDouble(day.stream().map(TPS::getCPUUsage).filter(i -> i != 0));
addValue("averagetps", FormatUtils.cutDecimals(averageTPSweek)); long averageUsedMemoryWeek = MathUtils.averageLong(week.stream().map(TPS::getUsedMemory).filter(i -> i != 0));
addValue("averagetpsday", FormatUtils.cutDecimals(averageTPSday)); long averageUsedMemoryDay = MathUtils.averageLong(day.stream().map(TPS::getUsedMemory).filter(i -> i != 0));
double averageEntityCountWeek = MathUtils.averageInt(week.stream().map(TPS::getEntityCount).filter(i -> i != 0));
double averageEntityCountDay = MathUtils.averageInt(day.stream().map(TPS::getEntityCount).filter(i -> i != 0));
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("averagecpuweek", averageCPUWeek >= 0 ? FormatUtils.cutDecimals(averageCPUWeek) + "%" : "Unavailable");
addValue("averagecpuday", averageCPUDay >= 0 ? FormatUtils.cutDecimals(averageCPUDay) + "%" : "Unavailable");
addValue("averagememoryweek", FormatUtils.cutDecimals(averageUsedMemoryWeek));
addValue("averagememoryday", FormatUtils.cutDecimals(averageUsedMemoryDay));
addValue("averageentitiesweek", FormatUtils.cutDecimals(averageEntityCountWeek));
addValue("averageentitiesday", FormatUtils.cutDecimals(averageEntityCountDay));
addValue("averagechunksweek", FormatUtils.cutDecimals(averageChunksLoadedWeek));
addValue("averagechunksday", FormatUtils.cutDecimals(averageChunksLoadedDay));
} }
public List<TPS> getTpsData() { public List<TPS> getTpsData() {

View File

@ -0,0 +1,41 @@
package main.java.com.djrapitops.plan.data.analysis;
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 java.util.HashMap;
import java.util.Map;
/**
* Part responsible for all World Playtime related analysis.
* <p>
* World times Pie
* <p>
* Placeholder values can be retrieved using the get method.
* <p>
* Contains following place-holders: worldtotal, worldseries
*
* @author Rsl1122
* @since 3.6.0
*/
public class WorldPart extends RawData {
private final Map<String, Long> worldTimes;
public WorldPart() {
worldTimes = new HashMap<>();
}
@Override
protected void analyse() {
WorldTimes t = new WorldTimes(worldTimes);
addValue("worldtotal", FormatUtils.formatTimeAmount(t.getTotal()));
addValue("worldseries", WorldPieCreator.createSeriesData(worldTimes));
}
public void addToWorld(String worldName, long playTime) {
Long value = worldTimes.getOrDefault(worldName, 0L);
worldTimes.put(worldName, value + playTime);
}
}

View File

@ -13,13 +13,13 @@ import main.java.com.djrapitops.plan.utilities.analysis.Analysis;
*/ */
public class AnalysisCacheHandler { public class AnalysisCacheHandler {
private AnalysisData cache;
private final Analysis analysis; private final Analysis analysis;
private AnalysisData cache;
private boolean analysisEnabled; private boolean analysisEnabled;
/** /**
* Class Constructor. * Class Constructor.
* * <p>
* Initializes Analysis * Initializes Analysis
* *
* @param plugin Current instance of Plan * @param plugin Current instance of Plan
@ -64,7 +64,6 @@ public class AnalysisCacheHandler {
} }
/** /**
*
* @return * @return
*/ */
public boolean isAnalysisBeingRun() { public boolean isAnalysisBeingRun() {

View File

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

View File

@ -21,19 +21,20 @@ import main.java.com.djrapitops.plan.utilities.MiscUtils;
import main.java.com.djrapitops.plan.utilities.NewPlayerCreator; import main.java.com.djrapitops.plan.utilities.NewPlayerCreator;
import main.java.com.djrapitops.plan.utilities.analysis.MathUtils; import main.java.com.djrapitops.plan.utilities.analysis.MathUtils;
import main.java.com.djrapitops.plan.utilities.comparators.HandlingInfoTimeComparator; import main.java.com.djrapitops.plan.utilities.comparators.HandlingInfoTimeComparator;
import org.bukkit.entity.Player;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.*; import java.util.*;
/** /**
* This Class contains the Cache. * This Class contains the Cache.
* * <p>
* This class is the main processing class that initialises Save, Clear, Process * This class is the main processing class that initialises Save, Clear, Process
* and Get queue and Starts the asynchronous save task. * and Get queue and Starts the asynchronous save task.
* * <p>
* It is used to store command use, locations, active sessions and UserData * It is used to store command use, locations, active sessions and UserData
* objects in memory. * objects in memory.
* * <p>
* Its methods can be used to access all the data it stores and to clear them. * Its methods can be used to access all the data it stores and to clear them.
* *
* @author Rsl1122 * @author Rsl1122
@ -42,14 +43,16 @@ import java.util.*;
public class DataCacheHandler extends SessionCache { public class DataCacheHandler extends SessionCache {
// Cache // Cache
private final HashMap<UUID, UserData> dataCache; private final Map<UUID, UserData> dataCache;
private Map<String, Integer> commandUse;
private List<List<TPS>> unsavedTPSHistory;
// Plan // Plan
private final Plan plugin; private final Plan plugin;
private final Database db; private final Database db;
//Cache
private Map<String, Integer> commandUse;
private List<List<TPS>> unsavedTPSHistory;
// Queues // Queues
private DataCacheSaveQueue saveTask; private DataCacheSaveQueue saveTask;
private DataCacheClearQueue clearTask; private DataCacheClearQueue clearTask;
@ -61,7 +64,7 @@ public class DataCacheHandler extends SessionCache {
/** /**
* Class Constructor. * Class Constructor.
* * <p>
* Gets the Database from the plugin. Starts the queues. Registers * Gets the Database from the plugin. Starts the queues. Registers
* Asynchronous Periodic Save Task * Asynchronous Periodic Save Task
* *
@ -160,7 +163,7 @@ public class DataCacheHandler extends SessionCache {
/** /**
* Uses Database or Cache to retrieve the UserData of a matching player. * Uses Database or Cache to retrieve the UserData of a matching player.
* * <p>
* Caches the data to the Cache if cache-parameter is true. * Caches the data to the Cache if cache-parameter is true.
* *
* @param processor DBCallableProcessor Object used to process the data * @param processor DBCallableProcessor Object used to process the data
@ -174,12 +177,7 @@ public class DataCacheHandler extends SessionCache {
UserData uData = dataCache.get(uuid); UserData uData = dataCache.get(uuid);
if (uData == null) { if (uData == null) {
if (cache) { if (cache) {
DBCallableProcessor cacher = new DBCallableProcessor() { DBCallableProcessor cacher = this::cache;
@Override
public void process(UserData data) {
cache(data);
}
};
getTask.scheduleForGet(uuid, cacher, processor); getTask.scheduleForGet(uuid, cacher, processor);
} else { } else {
getTask.scheduleForGet(uuid, processor); getTask.scheduleForGet(uuid, processor);
@ -191,7 +189,7 @@ public class DataCacheHandler extends SessionCache {
/** /**
* Used to Cache a UserData object to the Cache. * Used to Cache a UserData object to the Cache.
* * <p>
* If a object already exists it will be replaced. * If a object already exists it will be replaced.
* *
* @param data UserData object with the UUID inside used as key. * @param data UserData object with the UUID inside used as key.
@ -204,7 +202,7 @@ public class DataCacheHandler extends SessionCache {
/** /**
* Uses Database or Cache to retrieve the UserData of a matching player. * Uses Database or Cache to retrieve the UserData of a matching player.
* * <p>
* Always Caches the data after retrieval (unless already cached) * Always Caches the data after retrieval (unless already cached)
* *
* @param processor DBCallableProcessor Object used to process the data * @param processor DBCallableProcessor Object used to process the data
@ -217,9 +215,7 @@ public class DataCacheHandler extends SessionCache {
/** /**
* Saves all UserData in the cache to Database. * Saves all UserData in the cache to Database.
* * <p>
* ATTENTION: TODO - Doesn't save the Locations in the locationCache.
*
* Should only be called from Async thread * Should only be called from Async thread
*/ */
public void saveCachedUserData() { public void saveCachedUserData() {
@ -234,7 +230,7 @@ public class DataCacheHandler extends SessionCache {
/** /**
* Used to add event HandlingInfo to the processTask's pool. * Used to add event HandlingInfo to the processTask's pool.
* * <p>
* Given HandlingInfo object's process method will be called. * Given HandlingInfo object's process method will be called.
* *
* @param i Object that extends HandlingInfo. * @param i Object that extends HandlingInfo.
@ -249,9 +245,9 @@ public class DataCacheHandler extends SessionCache {
/** /**
* Saves all data in the cache to Database and closes the database down. * Saves all data in the cache to Database and closes the database down.
* * <p>
* Stops all tasks. * Stops all tasks.
* * <p>
* If processTask has unprocessed information, it will be processed. * If processTask has unprocessed information, it will be processed.
*/ */
public void saveCacheOnDisable() { public void saveCacheOnDisable() {
@ -268,7 +264,8 @@ public class DataCacheHandler extends SessionCache {
for (IPlayer p : onlinePlayers) { for (IPlayer p : onlinePlayers) {
UUID uuid = p.getUuid(); UUID uuid = p.getUuid();
endSession(uuid); endSession(uuid);
toProcess.add(new LogoutInfo(uuid, time, p.isBanned(), p.getGamemode(), getSession(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()); Log.debug("ToProcess size_AFTER: " + toProcess.size() + " DataCache size: " + dataCache.keySet().size());
toProcess.sort(new HandlingInfoTimeComparator()); toProcess.sort(new HandlingInfoTimeComparator());
@ -301,12 +298,7 @@ public class DataCacheHandler extends SessionCache {
for (HandlingInfo i : toProcess) { for (HandlingInfo i : toProcess) {
UserData uData = dataCache.get(i.getUuid()); UserData uData = dataCache.get(i.getUuid());
if (uData == null) { if (uData == null) {
DBCallableProcessor p = new DBCallableProcessor() { DBCallableProcessor p = i::process;
@Override
public void process(UserData data) {
i.process(data);
}
};
getUserDataForProcessing(p, i.getUuid()); getUserDataForProcessing(p, i.getUuid());
} else { } else {
i.process(uData); i.process(uData);
@ -321,20 +313,17 @@ public class DataCacheHandler extends SessionCache {
*/ */
public void saveCachedData(UUID uuid) { public void saveCachedData(UUID uuid) {
Log.debug(uuid + ": SaveCachedData"); Log.debug(uuid + ": SaveCachedData");
DBCallableProcessor saveProcessor = new DBCallableProcessor() { DBCallableProcessor saveProcessor = data -> {
@Override
public void process(UserData data) {
data.access(); data.access();
data.setClearAfterSave(true); data.setClearAfterSave(true);
saveTask.scheduleForSave(data); saveTask.scheduleForSave(data);
}
}; };
getUserDataForProcessing(saveProcessor, uuid); getUserDataForProcessing(saveProcessor, uuid);
} }
/** /**
* Saves the cached CommandUse. * Saves the cached CommandUse.
* * <p>
* Should be only called from an Asynchronous Thread. * Should be only called from an Asynchronous Thread.
*/ */
public void saveCommandUse() { public void saveCommandUse() {
@ -366,11 +355,14 @@ public class DataCacheHandler extends SessionCache {
for (List<TPS> history : copy) { for (List<TPS> history : copy) {
final long lastDate = history.get(history.size() - 1).getDate(); final long lastDate = history.get(history.size() - 1).getDate();
final double averageTPS = MathUtils.averageDouble(history.stream().map(TPS::getTps)); final double averageTPS = MathUtils.round(MathUtils.averageDouble(history.stream().map(TPS::getTps)));
final int averagePlayersOnline = (int) MathUtils.averageInt(history.stream().map(TPS::getPlayers)); final int averagePlayersOnline = (int) MathUtils.averageInt(history.stream().map(TPS::getPlayers));
final double averageCPUUsage = MathUtils.averageDouble(history.stream().map(TPS::getCPUUsage)); 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)); averages.add(new TPS(lastDate, averageTPS, averagePlayersOnline, averageCPUUsage, averageUsedMemory, averageEntityCount, averageChunksLoaded));
} }
unsavedTPSHistory.removeAll(copy); unsavedTPSHistory.removeAll(copy);
return averages; return averages;
@ -381,13 +373,14 @@ public class DataCacheHandler extends SessionCache {
*/ */
public void saveHandlerDataToCache() { public void saveHandlerDataToCache() {
final List<IPlayer> onlinePlayers = plugin.fetch().getOnlinePlayers(); final List<IPlayer> onlinePlayers = plugin.fetch().getOnlinePlayers();
onlinePlayers.forEach((p) -> saveHandlerDataToCache(p, false)); onlinePlayers.forEach(p -> saveHandlerDataToCache(p, false));
} }
private void saveHandlerDataToCache(IPlayer player, boolean pool) { private void saveHandlerDataToCache(IPlayer p, boolean pool) {
long time = MiscUtils.getTime(); long time = MiscUtils.getTime();
UUID uuid = player.getUuid(); UUID uuid = p.getUuid();
ReloadInfo info = new ReloadInfo(uuid, time, player.getAddress().getAddress(), player.isBanned(), player.getDisplayName(), player.getGamemode()); 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) { if (!pool) {
UserData data = dataCache.get(uuid); UserData data = dataCache.get(uuid);
if (data != null) { if (data != null) {
@ -474,9 +467,9 @@ public class DataCacheHandler extends SessionCache {
/** /**
* Used to get the contents of the cache. * Used to get the contents of the cache.
* *
* @return The HashMap containing all Cached UserData * @return The Map containing all Cached UserData
*/ */
public HashMap<UUID, UserData> getDataCache() { public Map<UUID, UserData> getDataCache() {
return dataCache; return dataCache;
} }
@ -491,7 +484,7 @@ public class DataCacheHandler extends SessionCache {
/** /**
* If /reload is run this treats every online player as a new login. * 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 * Calls all the methods that are ran when PlayerJoinEvent is fired
*/ */
public void handleReload() { public void handleReload() {
@ -525,7 +518,6 @@ public class DataCacheHandler extends SessionCache {
} }
/** /**
*
* @return * @return
*/ */
public DataCacheSaveQueue getSaveTask() { public DataCacheSaveQueue getSaveTask() {
@ -533,7 +525,6 @@ public class DataCacheHandler extends SessionCache {
} }
/** /**
*
* @return * @return
*/ */
public DataCacheClearQueue getClearTask() { public DataCacheClearQueue getClearTask() {
@ -541,7 +532,6 @@ public class DataCacheHandler extends SessionCache {
} }
/** /**
*
* @return * @return
*/ */
public DataCacheProcessQueue getProcessTask() { public DataCacheProcessQueue getProcessTask() {
@ -549,7 +539,6 @@ public class DataCacheHandler extends SessionCache {
} }
/** /**
*
* @return * @return
*/ */
public DataCacheGetQueue getGetTask() { public DataCacheGetQueue getGetTask() {

View File

@ -7,6 +7,7 @@ import main.java.com.djrapitops.plan.utilities.Benchmark;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.util.Map; import java.util.Map;
@ -21,6 +22,14 @@ import java.util.Map;
* @since 3.5.5 * @since 3.5.5
*/ */
public class GeolocationCacheHandler { public class GeolocationCacheHandler {
/**
* Constructor used to hide the public constructor
*/
private GeolocationCacheHandler() {
throw new IllegalStateException("Utility class");
}
private static final Cache<String, String> geolocationCache = CacheBuilder.newBuilder() private static final Cache<String, String> geolocationCache = CacheBuilder.newBuilder()
.maximumSize(10000) .maximumSize(10000)
.build(); .build();
@ -71,12 +80,20 @@ public class GeolocationCacheHandler {
*/ */
private static String getUncachedCountry(String ipAddress) { private static String getUncachedCountry(String ipAddress) {
Benchmark.start("getUncachedCountry"); Benchmark.start("getUncachedCountry");
URL url;
String urlString = "http://freegeoip.net/csv/" + ipAddress;
try { try {
URL url = new URL("http://freegeoip.net/csv/" + ipAddress); url = new URL(urlString);
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream())); } catch (MalformedURLException e) {
Log.error("The URL \"" + urlString + "\" couldn't be converted to URL: " + e.getCause()); //Shouldn't ever happen
return "Not Known";
}
try (BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()))) {
String resultLine = in.readLine(); String resultLine = in.readLine();
Log.debug(resultLine); Log.debug("Result for country request for " + ipAddress + ": " + resultLine);
in.close();
String[] results = resultLine.split(","); String[] results = resultLine.split(",");
String result = results[2]; String result = results[2];
@ -87,7 +104,5 @@ public class GeolocationCacheHandler {
} finally { } finally {
Benchmark.stop("getUncachedCountry"); Benchmark.stop("getUncachedCountry");
} }
} }
} }

View File

@ -4,6 +4,7 @@ import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Plan; import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.UserData; import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.database.Database; 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.MiscUtils; import main.java.com.djrapitops.plan.utilities.MiscUtils;
import main.java.com.djrapitops.plan.utilities.analysis.ExportUtility; import main.java.com.djrapitops.plan.utilities.analysis.ExportUtility;
@ -36,7 +37,7 @@ public class InspectCacheHandler {
/** /**
* Caches the UserData object to InspectCache. * Caches the UserData object to InspectCache.
* * <p>
* If the Userdata is cached in DataCache it will be used. Otherwise the Get * If the Userdata is cached in DataCache it will be used. Otherwise the Get
* Queue will handle the DBCallableProcessor. * Queue will handle the DBCallableProcessor.
* *
@ -48,6 +49,7 @@ public class InspectCacheHandler {
public void process(UserData data) { public void process(UserData data) {
cache.put(uuid, new UserData(data)); cache.put(uuid, new UserData(data));
cacheTimes.put(uuid, MiscUtils.getTime()); cacheTimes.put(uuid, MiscUtils.getTime());
PageCacheHandler.cachePage("inspectPage: " + uuid.toString(), () -> new InspectPageResponse(Plan.getInstance().getUiServer().getDataReqHandler(), uuid));
try { try {
ExportUtility.writeInspectHtml(data, ExportUtility.getPlayersFolder(ExportUtility.getFolder())); ExportUtility.writeInspectHtml(data, ExportUtility.getPlayersFolder(ExportUtility.getFolder()));
} catch (IOException ex) { } catch (IOException ex) {

View File

@ -0,0 +1,76 @@
package main.java.com.djrapitops.plan.data.cache;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import main.java.com.djrapitops.plan.ui.webserver.response.Response;
/**
* This class contains the page cache.
* <p>
* It caches all Responses with their matching identifiers.
* This reduces CPU cycles and the time to wait for loading the pages.
* This is especially useful in situations where multiple clients are accessing the server.
* <p>
* This cache uses the Google Guava {@link Cache}.
*
* @author Fuzzlemann
* @since 3.6.0
*/
public class PageCacheHandler {
/**
* Constructor used to hide the public constructor
*/
private PageCacheHandler() {
throw new IllegalStateException("Utility class");
}
private static final Cache<String, Response> pageCache = CacheBuilder.newBuilder()
.build();
/**
* Loads the page from the page cache.
* <p>
* If the {@link Response} isn't cached, {@link PageLoader#createResponse()} in the {@code loader}
* is called to create the Response.
* <p>
* If the Response is created, it's automatically cached.
*
* @param identifier The identifier of the page
* @param loader The {@link PageLoader} (How should it load the page if it's not cached)
* @return The Response that was cached or created by the {@link PageLoader loader}
*/
public static Response loadPage(String identifier, PageLoader loader) {
Response response = pageCache.getIfPresent(identifier);
if (response != null) {
return response;
}
response = loader.createResponse();
pageCache.put(identifier, response);
return response;
}
/**
* Puts the page into the page cache.
* <p>
* If the cache already inherits that {@code identifier}, it's renewed.
*
* @param identifier The identifier of the page
* @param loader The {@link PageLoader} (How it should load the page)
*/
public static void cachePage(String identifier, PageLoader loader) {
Response response = loader.createResponse();
pageCache.put(identifier, response);
}
/**
* Clears the cache from all its contents.
*/
public static void clearCache() {
pageCache.asMap().clear();
}
}

View File

@ -0,0 +1,15 @@
package main.java.com.djrapitops.plan.data.cache;
import main.java.com.djrapitops.plan.ui.webserver.response.Response;
/**
* This interface is used for providing the method to load the page.
*
* @author Fuzzlemann
* @since 3.6.0
*/
public interface PageLoader {
Response createResponse();
}

View File

@ -1,13 +1,14 @@
package main.java.com.djrapitops.plan.data.cache; package main.java.com.djrapitops.plan.data.cache;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.data.SessionData; import main.java.com.djrapitops.plan.data.SessionData;
import main.java.com.djrapitops.plan.data.UserData; import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.utilities.MiscUtils; 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. * This class is used to store active sessions of players in memory.
* *
@ -54,7 +55,7 @@ public class SessionCache {
/** /**
* Used to get the SessionData of the player in the sessionCache. * Used to get the SessionData of the player in the sessionCache.
* *
* @param uuid UUId of the player. * @param uuid UUID of the player.
* @return SessionData or null if not cached. * @return SessionData or null if not cached.
*/ */
public SessionData getSession(UUID uuid) { public SessionData getSession(UUID uuid) {
@ -78,7 +79,7 @@ public class SessionCache {
/** /**
* Used to get the Map of active sessions. * Used to get the Map of active sessions.
* * <p>
* Used for testing. * Used for testing.
* *
* @return key:value UUID:SessionData * @return key:value UUID:SessionData

View File

@ -1,18 +1,20 @@
package main.java.com.djrapitops.plan.data.cache.queue; package main.java.com.djrapitops.plan.data.cache.queue;
import com.djrapitops.plugin.task.AbsRunnable; import com.djrapitops.plugin.task.AbsRunnable;
import main.java.com.djrapitops.plan.Log;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
/** /**
* Abstract class representing a queue consumer. * Abstract class representing a queue consumer.
* *
* @author Rsl1122
* @param <T> * @param <T>
* @author Rsl1122
*/ */
public abstract class Consumer<T> extends AbsRunnable { public abstract class Consumer<T> extends AbsRunnable {
boolean run;
final BlockingQueue<T> queue; final BlockingQueue<T> queue;
boolean run;
/** /**
* Constructor, defines queue. * Constructor, defines queue.
@ -33,6 +35,8 @@ public abstract class Consumer<T> extends AbsRunnable {
consume(queue.take()); consume(queue.take());
} }
} catch (InterruptedException ex) { } catch (InterruptedException ex) {
Log.error("Consumer interrupted: " + ex.getCause());
Thread.currentThread().interrupt();
} }
} }

View File

@ -45,12 +45,12 @@ public class DataCacheGetQueue extends Queue<Map<UUID, List<DBCallableProcessor>
map.put(uuid, Arrays.asList(processors)); map.put(uuid, Arrays.asList(processors));
queue.add(map); queue.add(map);
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
Log.error(Phrase.ERROR_TOO_SMALL_QUEUE.parse("Get Queue", Settings.PROCESS_GET_LIMIT.getNumber() + "")); Log.error(Phrase.ERROR_TOO_SMALL_QUEUE.parse("Get Queue", String.valueOf(Settings.PROCESS_GET_LIMIT.getNumber())));
} }
} }
public boolean containsUUIDtoBeCached(UUID uuid) { public boolean containsUUIDtoBeCached(UUID uuid) {
return uuid != null && new ArrayList<>(queue).stream().anyMatch((map) -> (map.get(uuid) != null && map.get(uuid).size() >= 2)); return uuid != null && new ArrayList<>(queue).stream().anyMatch(map -> (map.get(uuid) != null && map.get(uuid).size() >= 2));
} }
} }
@ -68,12 +68,17 @@ class GetConsumer extends Consumer<Map<UUID, List<DBCallableProcessor>>> {
if (db == null) { if (db == null) {
return; return;
} }
try { try {
for (UUID uuid : processors.keySet()) { for (Map.Entry<UUID, List<DBCallableProcessor>> entrySet : processors.entrySet()) {
UUID uuid = entrySet.getKey();
if (uuid == null) { if (uuid == null) {
continue; continue;
} }
List<DBCallableProcessor> processorsList = processors.get(uuid);
List<DBCallableProcessor> processorsList = entrySet.getValue();
if (processorsList != null) { if (processorsList != null) {
Log.debug(uuid + ": Get, For:" + processorsList.size()); Log.debug(uuid + ": Get, For:" + processorsList.size());
try { try {

View File

@ -1,12 +1,10 @@
package main.java.com.djrapitops.plan.data.cache.queue; package main.java.com.djrapitops.plan.data.cache.queue;
import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.data.cache.DBCallableProcessor; 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.cache.DataCacheHandler;
import main.java.com.djrapitops.plan.data.handling.info.HandlingInfo; import main.java.com.djrapitops.plan.data.handling.info.HandlingInfo;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ArrayBlockingQueue;
@ -27,7 +25,7 @@ public class DataCacheProcessQueue extends Queue<HandlingInfo> {
* @param handler current instance of DataCacheHandler. * @param handler current instance of DataCacheHandler.
*/ */
public DataCacheProcessQueue(DataCacheHandler handler) { public DataCacheProcessQueue(DataCacheHandler handler) {
super(new ArrayBlockingQueue(20000)); super(new ArrayBlockingQueue<>(20000));
setup = new ProcessSetup(queue, handler); setup = new ProcessSetup(queue, handler);
setup.go(); setup.go();
} }
@ -66,7 +64,7 @@ public class DataCacheProcessQueue extends Queue<HandlingInfo> {
* @return true/false * @return true/false
*/ */
public boolean containsUUID(UUID uuid) { public boolean containsUUID(UUID uuid) {
return uuid != null && new ArrayList<>(queue).stream().anyMatch(info -> info.getUuid().equals(uuid)); return uuid != null && queue.stream().anyMatch(info -> info.getUuid().equals(uuid));
} }
} }
@ -74,7 +72,7 @@ class ProcessConsumer extends Consumer<HandlingInfo> {
private DataCacheHandler handler; private DataCacheHandler handler;
ProcessConsumer(BlockingQueue q, DataCacheHandler h) { ProcessConsumer(BlockingQueue<HandlingInfo> q, DataCacheHandler h) {
super(q, "ProcessQueueConsumer"); super(q, "ProcessQueueConsumer");
handler = h; handler = h;
} }
@ -84,19 +82,19 @@ class ProcessConsumer extends Consumer<HandlingInfo> {
if (handler == null) { if (handler == null) {
return; return;
} }
if (handler.getGetTask().containsUUIDtoBeCached(info.getUuid())) { // Wait for get queue. if (handler.getGetTask().containsUUIDtoBeCached(info.getUuid())) { // Wait for get queue.
queue.add(info); queue.add(info);
return; return;
} }
Log.debug(info.getUuid() + ": Processing type: " + info.getType().name()); Log.debug(info.getUuid() + ": Processing type: " + info.getType().name());
DBCallableProcessor p = new DBCallableProcessor() { DBCallableProcessor p = data -> {
@Override
public void process(UserData data) {
if (!info.process(data)) { if (!info.process(data)) {
Log.error("Attempted to process data for wrong uuid: W:" + data.getUuid() + " | R:" + info.getUuid() + " Type:" + info.getType().name()); Log.error("Attempted to process data for wrong uuid: W:" + data.getUuid() + " | R:" + info.getUuid() + " Type:" + info.getType().name());
} }
}
}; };
handler.getUserDataForProcessing(p, info.getUuid()); handler.getUserDataForProcessing(p, info.getUuid());
} }

View File

@ -9,7 +9,6 @@ import main.java.com.djrapitops.plan.data.cache.DataCacheHandler;
import main.java.com.djrapitops.plan.database.Database; import main.java.com.djrapitops.plan.database.Database;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ArrayBlockingQueue;
@ -31,7 +30,7 @@ public class DataCacheSaveQueue extends Queue<UserData> {
* @param handler DataCacheHandler * @param handler DataCacheHandler
*/ */
public DataCacheSaveQueue(Plan plugin, DataCacheHandler handler) { public DataCacheSaveQueue(Plan plugin, DataCacheHandler handler) {
super(new ArrayBlockingQueue(Settings.PROCESS_SAVE_LIMIT.getNumber())); super(new ArrayBlockingQueue<>(Settings.PROCESS_SAVE_LIMIT.getNumber()));
setup = new SaveSetup(queue, handler, plugin.getDB()); setup = new SaveSetup(queue, handler, plugin.getDB());
setup.go(); setup.go();
} }
@ -85,7 +84,7 @@ public class DataCacheSaveQueue extends Queue<UserData> {
* @return true/false * @return true/false
*/ */
public boolean containsUUID(UUID uuid) { public boolean containsUUID(UUID uuid) {
return uuid != null && new ArrayList<>(queue).stream().anyMatch(d -> d.getUuid().equals(uuid)); return uuid != null && queue.stream().anyMatch(d -> d.getUuid().equals(uuid));
} }
} }
@ -94,7 +93,7 @@ class SaveConsumer extends Consumer<UserData> {
private Database db; private Database db;
private DataCacheHandler handler; private DataCacheHandler handler;
SaveConsumer(BlockingQueue q, DataCacheHandler handler, Database db) { SaveConsumer(BlockingQueue<UserData> q, DataCacheHandler handler, Database db) {
super(q, "SaveQueueConsumer"); super(q, "SaveQueueConsumer");
this.db = db; this.db = db;
this.handler = handler; this.handler = handler;
@ -106,23 +105,23 @@ class SaveConsumer extends Consumer<UserData> {
if (db == null) { if (db == null) {
return; return;
} }
UUID uuid = data.getUuid(); UUID uuid = data.getUuid();
if (handler.getProcessTask().containsUUID(uuid)) { // Wait for process queue. if (handler.getProcessTask().containsUUID(uuid)) { // Wait for process queue.
queue.add(data); queue.add(data);
return; return;
} }
Log.debug(uuid + ": Saving: " + uuid); Log.debug(uuid + ": Saving: " + uuid);
try { try {
db.saveUserData(data); db.saveUserData(data);
data.stopAccessing(); data.stopAccessing();
Log.debug(uuid + ": Saved!"); Log.debug(uuid + ": Saved!");
if (data.shouldClearAfterSave()) { if (data.shouldClearAfterSave()
if (handler != null) { && handler != null) {
handler.getClearTask().scheduleForClear(uuid); handler.getClearTask().scheduleForClear(uuid);
} }
}
} catch (SQLException ex) { } catch (SQLException ex) {
// queue.add(data);
Log.toLog(this.getClass().getName(), ex); Log.toLog(this.getClass().getName(), ex);
} }
} }
@ -132,6 +131,7 @@ class SaveConsumer extends Consumer<UserData> {
if (db != null) { if (db != null) {
db = null; db = null;
} }
if (handler != null) { if (handler != null) {
handler = null; handler = null;
} }

View File

@ -7,8 +7,8 @@ import java.util.concurrent.BlockingQueue;
/** /**
* Abstract implementation of a Queue. * Abstract implementation of a Queue.
* *
* @author Rsl1122
* @param <T> Object this queue consumes * @param <T> Object this queue consumes
* @author Rsl1122
*/ */
public abstract class Queue<T> { public abstract class Queue<T> {

View File

@ -5,8 +5,8 @@ import main.java.com.djrapitops.plan.Plan;
/** /**
* Abstract representation of a queue setup. * Abstract representation of a queue setup.
* *
* @author Rsl1122
* @param <T> Object this queue consumes. * @param <T> Object this queue consumes.
* @author Rsl1122
*/ */
public abstract class Setup<T> { public abstract class Setup<T> {

View File

@ -11,15 +11,21 @@ import main.java.com.djrapitops.plan.data.UserData;
*/ */
public class ChatHandling { 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 * Processes the information of the Event and changes UserData object
* accordingly. * accordingly.
* *
* @param data UserData of the player. * @param data UserData of the player.
* @param nickname Nickname of the player during the event. * @param nickname Nickname of the player during the event.
* @param msg Message sent by the player.
*/ */
public static void processChatInfo(UserData data, String nickname, String msg) { public static void processChatInfo(UserData data, String nickname) {
data.addNickname(nickname); data.addNickname(nickname);
} }
} }

View File

@ -1,46 +0,0 @@
package main.java.com.djrapitops.plan.data.handling;
import com.djrapitops.plugin.utilities.player.Gamemode;
import main.java.com.djrapitops.plan.data.UserData;
import java.util.Map;
/**
* Class containing static methods for processing information contained in a
* GamemodeChangeEvent.
*
* @author Rsl1122
* @since 3.0.0
*/
public class GamemodeHandling {
/**
* 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 newGM The Gamemode the player changed to.
*/
public static void processGamemodeInfo(UserData data, long time, Gamemode newGM) {
if (newGM == null) {
return;
}
final String newGamemode = newGM.name();
String lastGamemode = data.getLastGamemode();
if (lastGamemode == null) {
data.setLastGamemode(newGamemode);
}
lastGamemode = data.getLastGamemode();
Map<String, Long> times = data.getGmTimes();
long currentGMTime = times.getOrDefault(lastGamemode, 0L);
data.setPlayTime(data.getPlayTime() + (time - data.getLastPlayed()));
data.setLastPlayed(time);
long lastSwap = data.getLastGmSwapTime();
long playtime = data.getPlayTime();
data.setGMTime(lastGamemode, currentGMTime + (playtime - lastSwap));
data.setLastGmSwapTime(playtime);
data.setLastGamemode(newGamemode);
}
}

View File

@ -1,7 +1,5 @@
package main.java.com.djrapitops.plan.data.handling; package main.java.com.djrapitops.plan.data.handling;
import java.sql.SQLException;
import java.util.UUID;
import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Plan; import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.KillData; import main.java.com.djrapitops.plan.data.KillData;
@ -9,6 +7,9 @@ import main.java.com.djrapitops.plan.data.UserData;
import org.bukkit.entity.LivingEntity; import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.sql.SQLException;
import java.util.UUID;
/** /**
* Class containing static methods for processing information contained in a * Class containing static methods for processing information contained in a
* DeathEvent when the killer is a player. * DeathEvent when the killer is a player.
@ -18,6 +19,13 @@ import org.bukkit.entity.Player;
*/ */
public class KillHandling { public class KillHandling {
/**
* Utility Class, hides constructor.
*/
private KillHandling() {
throw new IllegalStateException("Utility Class.");
}
/** /**
* Processes the information of the Event and changes UserData object * Processes the information of the Event and changes UserData object
* accordingly. * accordingly.
@ -34,7 +42,7 @@ public class KillHandling {
int victimID; int victimID;
try { try {
UUID victimUUID = deadPlayer.getUniqueId(); UUID victimUUID = deadPlayer.getUniqueId();
victimID = plugin.getDB().getUsersTable().getUserId(victimUUID + ""); victimID = plugin.getDB().getUsersTable().getUserId(victimUUID);
if (victimID == -1) { if (victimID == -1) {
return; return;
} }

View File

@ -14,6 +14,13 @@ import java.net.InetAddress;
*/ */
public class LoginHandling { public class LoginHandling {
/**
* Utility Class, hides constructor.
*/
private LoginHandling() {
throw new IllegalStateException("Utility Class.");
}
/** /**
* Processes the information of the Event and changes UserData object * Processes the information of the Event and changes UserData object
* accordingly. * accordingly.
@ -36,7 +43,7 @@ public class LoginHandling {
/** /**
* Updates the geolocation of the player. * Updates the geolocation of the player.
* * <p>
* Uses free service of freegeoip.net. 15000 requests can be sent per hour. * Uses free service of freegeoip.net. 15000 requests can be sent per hour.
* *
* @param ip InetAddress used for location. * @param ip InetAddress used for location.

View File

@ -0,0 +1,25 @@
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 {
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,9 +1,11 @@
package main.java.com.djrapitops.plan.data.handling.importing; package main.java.com.djrapitops.plan.data.handling.importing;
import com.djrapitops.pluginbridge.plan.importing.OnTimeImporter; import com.djrapitops.pluginbridge.plan.importing.OnTimeImporter;
import main.java.com.djrapitops.plan.Log;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import main.java.com.djrapitops.plan.Log;
import static org.bukkit.Bukkit.getPluginManager; import static org.bukkit.Bukkit.getPluginManager;
/** /**
@ -34,7 +36,7 @@ public class ImportUtils {
try { try {
importers.put("ontime", new OnTimeImporter()); importers.put("ontime", new OnTimeImporter());
importers.put("offline", new OfflinePlayerImporter()); importers.put("offline", new OfflinePlayerImporter());
} catch (Throwable e) { } catch (Exception e) {
Log.toLog("ImportUtils.getImporters", e); Log.toLog("ImportUtils.getImporters", e);
Log.error("Plan Plugin Bridge not included in the plugin jar."); Log.error("Plan Plugin Bridge not included in the plugin jar.");
} }

View File

@ -2,15 +2,6 @@ package main.java.com.djrapitops.plan.data.handling.importing;
import com.djrapitops.plugin.utilities.player.Fetch; import com.djrapitops.plugin.utilities.player.Fetch;
import com.djrapitops.plugin.utilities.player.IOfflinePlayer; import com.djrapitops.plugin.utilities.player.IOfflinePlayer;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.function.Function;
import java.util.stream.Collectors;
import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Plan; import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.UserData; import main.java.com.djrapitops.plan.data.UserData;
@ -21,6 +12,11 @@ import main.java.com.djrapitops.plan.database.Database;
import main.java.com.djrapitops.plan.utilities.Benchmark; import main.java.com.djrapitops.plan.utilities.Benchmark;
import main.java.com.djrapitops.plan.utilities.NewPlayerCreator; import main.java.com.djrapitops.plan.utilities.NewPlayerCreator;
import java.sql.SQLException;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/** /**
* Abstract class used for importing data from other plugins. * Abstract class used for importing data from other plugins.
* *
@ -52,7 +48,7 @@ public abstract class Importer {
/** /**
* Method used for the import. * Method used for the import.
* * <p>
* Creates UserData for players that have not been saved to the database. * Creates UserData for players that have not been saved to the database.
* *
* @param uuids UUIDs to be imported * @param uuids UUIDs to be imported

View File

@ -1,8 +1,9 @@
package main.java.com.djrapitops.plan.data.handling.importing; package main.java.com.djrapitops.plan.data.handling.importing;
import java.util.UUID;
import main.java.com.djrapitops.plan.data.handling.info.HandlingInfo; 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. * Imports all players who have not joined since Plan was installed.
* *

View File

@ -14,19 +14,16 @@ import java.util.UUID;
public class ChatInfo extends HandlingInfo { public class ChatInfo extends HandlingInfo {
private final String nickname; private final String nickname;
private final String message;
/** /**
* Constructor. * Constructor.
* *
* @param uuid UUID of the player. * @param uuid UUID of the player.
* @param nickname Nickname of the player. * @param nickname Nickname of the player.
* @param message Message the player sent.
*/ */
public ChatInfo(UUID uuid, String nickname, String message) { public ChatInfo(UUID uuid, String nickname) {
super(uuid, InfoType.CHAT, 0L); super(uuid, InfoType.CHAT, 0L);
this.nickname = nickname; this.nickname = nickname;
this.message = message;
} }
@Override @Override
@ -34,7 +31,7 @@ public class ChatInfo extends HandlingInfo {
if (!uData.getUuid().equals(uuid)) { if (!uData.getUuid().equals(uuid)) {
return false; return false;
} }
ChatHandling.processChatInfo(uData, nickname, message); ChatHandling.processChatInfo(uData, nickname);
return true; return true;
} }
} }

View File

@ -1,8 +1,9 @@
package main.java.com.djrapitops.plan.data.handling.info; package main.java.com.djrapitops.plan.data.handling.info;
import java.util.UUID;
import main.java.com.djrapitops.plan.data.UserData; import main.java.com.djrapitops.plan.data.UserData;
import java.util.UUID;
/** /**
* HandlingInfo Class for DeathEvent information. * HandlingInfo Class for DeathEvent information.
* *

View File

@ -1,41 +0,0 @@
package main.java.com.djrapitops.plan.data.handling.info;
import com.djrapitops.plugin.utilities.player.Gamemode;
import java.util.UUID;
import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.data.handling.GamemodeHandling;
/**
* HandlingInfo Class for GamemodeChangeEvent information.
*
* @author Rsl1122
* @since 3.0.0
*/
public class GamemodeInfo extends HandlingInfo {
private final Gamemode currentGamemode;
/**
* Constructor.
*
* @param uuid UUID of the player.
* @param time Epoch ms of the event.
* @param gm Gamemode the player changed to.
*/
public GamemodeInfo(UUID uuid, long time, Gamemode gm) {
super(uuid, InfoType.GM, time);
currentGamemode = gm;
}
@Override
public boolean process(UserData uData) {
if (currentGamemode == null) {
return false;
}
if (!uData.getUuid().equals(uuid)) {
return false;
}
GamemodeHandling.processGamemodeInfo(uData, time, currentGamemode);
return true;
}
}

View File

@ -60,7 +60,7 @@ public abstract class HandlingInfo {
/** /**
* Process the info and modify the UserData object accordingly. * Process the info and modify the UserData object accordingly.
* * <p>
* If the UUIDs don't match no change should occur. * If the UUIDs don't match no change should occur.
* *
* @param uData UserData object to modify. * @param uData UserData object to modify.

View File

@ -2,9 +2,9 @@ package main.java.com.djrapitops.plan.data.handling.info;
/** /**
* Enum class for the types of HandlingInfo to be processed. * Enum class for the types of HandlingInfo to be processed.
* * <p>
* Type is only used for debugging. * Type is only used for debugging.
* * <p>
* OTHER should be used when * OTHER should be used when
* *
* @author Rsl1122 * @author Rsl1122
@ -49,5 +49,6 @@ public enum InfoType {
* *
* @since 3.1.1 * @since 3.1.1
*/ */
WORLD,
OTHER OTHER
} }

View File

@ -1,8 +1,9 @@
package main.java.com.djrapitops.plan.data.handling.info; package main.java.com.djrapitops.plan.data.handling.info;
import java.util.UUID;
import main.java.com.djrapitops.plan.data.UserData; import main.java.com.djrapitops.plan.data.UserData;
import java.util.UUID;
/** /**
* HandlingInfo Class for KickEvent information. * HandlingInfo Class for KickEvent information.
* *

View File

@ -1,6 +1,5 @@
package main.java.com.djrapitops.plan.data.handling.info; package main.java.com.djrapitops.plan.data.handling.info;
import com.djrapitops.plugin.utilities.player.Gamemode;
import main.java.com.djrapitops.plan.data.UserData; import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.data.handling.LoginHandling; import main.java.com.djrapitops.plan.data.handling.LoginHandling;
@ -18,7 +17,7 @@ public class LoginInfo extends HandlingInfo {
private final InetAddress ip; private final InetAddress ip;
private final boolean banned; private final boolean banned;
private final String nickname; private final String nickname;
private final GamemodeInfo gmInfo; private final PlaytimeDependentInfo playtimeDependentInfo;
private final int loginTimes; private final int loginTimes;
/** /**
@ -32,17 +31,19 @@ public class LoginInfo extends HandlingInfo {
* @param gm current gamemode of the player * @param gm current gamemode of the player
* @param loginTimes number the loginTimes should be incremented with. * @param loginTimes number the loginTimes should be incremented with.
*/ */
public LoginInfo(UUID uuid, long time, InetAddress ip, boolean banned, String nickname, Gamemode gm, int loginTimes) { public LoginInfo(UUID uuid, long time, InetAddress ip, boolean banned, String nickname, String gm, int loginTimes, String worldName) {
super(uuid, InfoType.LOGIN, time); super(uuid, InfoType.LOGIN, time);
this.ip = ip; this.ip = ip;
this.banned = banned; this.banned = banned;
this.nickname = nickname; this.nickname = nickname;
this.gmInfo = new GamemodeInfo(uuid, time, gm); this.playtimeDependentInfo = new PlaytimeDependentInfo(uuid, InfoType.OTHER, time, gm, worldName);
this.loginTimes = loginTimes; this.loginTimes = loginTimes;
} }
/** /**
* Constructor for not incrementing the loginTimes. * Constructor for not incrementing the loginTimes.
* <p>
* This constructor is used only by ReloadInfo
* *
* @param uuid UUID of the player. * @param uuid UUID of the player.
* @param time Epoch ms of the event. * @param time Epoch ms of the event.
@ -51,8 +52,13 @@ public class LoginInfo extends HandlingInfo {
* @param nickname Nickname of the player * @param nickname Nickname of the player
* @param gm current gamemode of the player * @param gm current gamemode of the player
*/ */
public LoginInfo(UUID uuid, long time, InetAddress ip, boolean banned, String nickname, Gamemode gm) { public LoginInfo(UUID uuid, long time, InetAddress ip, boolean banned, String nickname, String gm, String worldName) {
this(uuid, time, ip, banned, nickname, gm, 0); 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 @Override
@ -61,7 +67,7 @@ public class LoginInfo extends HandlingInfo {
return false; return false;
} }
LoginHandling.processLoginInfo(uData, time, ip, banned, nickname, loginTimes); LoginHandling.processLoginInfo(uData, time, ip, banned, nickname, loginTimes);
gmInfo.process(uData); playtimeDependentInfo.process(uData);
return true; return true;
} }
} }

View File

@ -1,6 +1,5 @@
package main.java.com.djrapitops.plan.data.handling.info; package main.java.com.djrapitops.plan.data.handling.info;
import com.djrapitops.plugin.utilities.player.Gamemode;
import main.java.com.djrapitops.plan.data.SessionData; import main.java.com.djrapitops.plan.data.SessionData;
import main.java.com.djrapitops.plan.data.UserData; import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.data.handling.LogoutHandling; import main.java.com.djrapitops.plan.data.handling.LogoutHandling;
@ -17,7 +16,7 @@ public class LogoutInfo extends HandlingInfo {
private final boolean banned; private final boolean banned;
private final SessionData sData; private final SessionData sData;
private final GamemodeInfo gmInfo; private final PlaytimeDependentInfo playtimeDependentInfo;
/** /**
* Constructor. * Constructor.
@ -29,11 +28,11 @@ public class LogoutInfo extends HandlingInfo {
* @param sData session that has been ended at the moment of the logout * @param sData session that has been ended at the moment of the logout
* event. * event.
*/ */
public LogoutInfo(UUID uuid, long time, boolean banned, Gamemode gm, SessionData sData) { public LogoutInfo(UUID uuid, long time, boolean banned, String gm, SessionData sData, String worldName) {
super(uuid, InfoType.LOGOUT, time); super(uuid, InfoType.LOGOUT, time);
this.banned = banned; this.banned = banned;
this.sData = sData; this.sData = sData;
this.gmInfo = new GamemodeInfo(uuid, time, gm); this.playtimeDependentInfo = new PlaytimeDependentInfo(uuid, InfoType.OTHER, time, gm, worldName);
} }
@Override @Override
@ -43,7 +42,7 @@ public class LogoutInfo extends HandlingInfo {
} }
uData.addSession(sData); uData.addSession(sData);
LogoutHandling.processLogoutInfo(uData, time, banned); LogoutHandling.processLogoutInfo(uData, time, banned);
gmInfo.process(uData); playtimeDependentInfo.process(uData);
return true; return true;
} }

View File

@ -0,0 +1,27 @@
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,9 +1,5 @@
package main.java.com.djrapitops.plan.data.handling.info; package main.java.com.djrapitops.plan.data.handling.info;
import com.djrapitops.plugin.utilities.player.Gamemode;
import main.java.com.djrapitops.plan.data.UserData;
import main.java.com.djrapitops.plan.data.handling.LoginHandling;
import java.net.InetAddress; import java.net.InetAddress;
import java.util.UUID; import java.util.UUID;
@ -13,12 +9,7 @@ import java.util.UUID;
* @author Rsl1122 * @author Rsl1122
* @since 3.0.0 * @since 3.0.0
*/ */
public class ReloadInfo extends HandlingInfo { public class ReloadInfo extends LoginInfo {
private final InetAddress ip;
private final boolean banned;
private final String nickname;
private final GamemodeInfo gmInfo;
/** /**
* Constructor. * Constructor.
@ -30,26 +21,7 @@ public class ReloadInfo extends HandlingInfo {
* @param nickname Nickname of the player * @param nickname Nickname of the player
* @param gm current gamemode of the player * @param gm current gamemode of the player
*/ */
public ReloadInfo(UUID uuid, long time, InetAddress ip, boolean banned, String nickname, Gamemode gm) { public ReloadInfo(UUID uuid, long time, InetAddress ip, boolean banned, String nickname, String gm, String worldName) {
super(uuid, InfoType.RELOAD, time); super(uuid, time, ip, banned, nickname, gm, worldName);
this.ip = ip;
this.banned = banned;
this.nickname = nickname;
gmInfo = new GamemodeInfo(uuid, time, gm);
} }
@Override
public boolean process(UserData uData) {
if (!uData.getUuid().equals(uuid)) {
return false;
}
uData.setPlayTime(uData.getPlayTime() + (time - uData.getLastPlayed()));
uData.setLastPlayed(time);
uData.updateBanned(banned);
uData.addIpAddress(ip);
uData.addNickname(nickname);
LoginHandling.updateGeolocation(ip, uData);
return gmInfo.process(uData);
}
} }

View File

@ -37,7 +37,8 @@ public class PlanChatListener implements Listener {
if (event.isCancelled()) { if (event.isCancelled()) {
return; return;
} }
Player p = event.getPlayer(); Player p = event.getPlayer();
handler.addToPool(new ChatInfo(p.getUniqueId(), p.getDisplayName(), event.getMessage())); handler.addToPool(new ChatInfo(p.getUniqueId(), p.getDisplayName()));
} }
} }

View File

@ -49,14 +49,14 @@ public class PlanCommandPreprocessListener implements Listener {
boolean combineCommandAliasesToMainCommand = Settings.COMBINE_COMMAND_ALIASES_TO_MAIN_COMMAND.isTrue(); boolean combineCommandAliasesToMainCommand = Settings.COMBINE_COMMAND_ALIASES_TO_MAIN_COMMAND.isTrue();
if (doNotLogUnknownCommands || combineCommandAliasesToMainCommand) { if (doNotLogUnknownCommands || combineCommandAliasesToMainCommand) {
Command command = plugin.getServer().getPluginCommand(commandName); Command command = plugin.getServer().getPluginCommand(commandName.substring(1, commandName.length()));
if (command == null) { if (command == null) {
if (doNotLogUnknownCommands) { if (doNotLogUnknownCommands) {
Log.debug("Ignored command, command is unknown"); Log.debug("Ignored command, command is unknown");
return; return;
} }
} else if (combineCommandAliasesToMainCommand) { } else if (combineCommandAliasesToMainCommand) {
commandName = command.getName(); commandName = "/" + command.getName();
} }
} }
@ -66,6 +66,7 @@ public class PlanCommandPreprocessListener implements Listener {
Log.debug("Ignored command, player had ignore permission."); Log.debug("Ignored command, player had ignore permission.");
return; return;
} }
handler.handleCommand(commandName); handler.handleCommand(commandName);
} }
} }

View File

@ -6,11 +6,12 @@ import main.java.com.djrapitops.plan.data.handling.info.DeathInfo;
import main.java.com.djrapitops.plan.data.handling.info.KillInfo; import main.java.com.djrapitops.plan.data.handling.info.KillInfo;
import main.java.com.djrapitops.plan.utilities.MiscUtils; import main.java.com.djrapitops.plan.utilities.MiscUtils;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.LivingEntity; import org.bukkit.entity.*;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityDeathEvent; import org.bukkit.event.entity.EntityDeathEvent;
/** /**
@ -41,23 +42,51 @@ public class PlanDeathEventListener implements Listener {
public void onDeath(EntityDeathEvent event) { public void onDeath(EntityDeathEvent event) {
long time = MiscUtils.getTime(); long time = MiscUtils.getTime();
LivingEntity dead = event.getEntity(); LivingEntity dead = event.getEntity();
Player killer = dead.getKiller();
boolean killerIsPlayer = killer != null;
if (killerIsPlayer) {
Material itemInHand;
try {
itemInHand = killer.getInventory().getItemInMainHand().getType();
} catch (Throwable e) {
try {
itemInHand = killer.getInventory().getItemInHand().getType(); // Support for non dual wielding versions.
} catch (Throwable e2) {
itemInHand = Material.AIR;
}
}
handler.addToPool(new KillInfo(killer.getUniqueId(), time, dead, itemInHand.name()));
}
if (dead instanceof Player) { if (dead instanceof Player) {
handler.addToPool(new DeathInfo(dead.getUniqueId())); handler.addToPool(new DeathInfo(dead.getUniqueId()));
} }
EntityDamageEvent entityDamageEvent = dead.getLastDamageCause();
if (!(entityDamageEvent instanceof EntityDamageByEntityEvent)) {
return;
}
EntityDamageByEntityEvent entityDamageByEntityEvent = (EntityDamageByEntityEvent) entityDamageEvent;
Entity killerEntity = entityDamageByEntityEvent.getDamager();
if (killerEntity instanceof Player) {
Player killer = (Player) killerEntity;
Material itemInHand;
try {
itemInHand = killer.getInventory().getItemInMainHand().getType();
} catch (Exception e) {
try {
itemInHand = killer.getInventory().getItemInHand().getType(); // Support for non dual wielding versions.
} catch (Exception e2) {
itemInHand = Material.AIR;
}
}
handler.addToPool(new KillInfo(killer.getUniqueId(), time, dead, itemInHand.name()));
return;
}
if (killerEntity instanceof Wolf) {
Wolf wolf = (Wolf) killerEntity;
if (!wolf.isTamed()) {
return;
}
AnimalTamer owner = wolf.getOwner();
if (!(owner instanceof Player)) {
return;
}
handler.addToPool(new KillInfo(owner.getUniqueId(), time, dead, "Wolf"));
}
} }
} }

View File

@ -1,9 +1,9 @@
package main.java.com.djrapitops.plan.data.listeners; package main.java.com.djrapitops.plan.data.listeners;
import com.djrapitops.plugin.utilities.player.Gamemode;
import main.java.com.djrapitops.plan.Plan; import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.cache.DataCacheHandler; import main.java.com.djrapitops.plan.data.cache.DataCacheHandler;
import main.java.com.djrapitops.plan.data.handling.info.GamemodeInfo; import main.java.com.djrapitops.plan.data.handling.info.InfoType;
import main.java.com.djrapitops.plan.data.handling.info.PlaytimeDependentInfo;
import main.java.com.djrapitops.plan.utilities.MiscUtils; import main.java.com.djrapitops.plan.utilities.MiscUtils;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
@ -11,6 +11,8 @@ import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerGameModeChangeEvent; import org.bukkit.event.player.PlayerGameModeChangeEvent;
import java.util.UUID;
/** /**
* Event Listener for PlayerGameModeChangeEvents. * Event Listener for PlayerGameModeChangeEvents.
* *
@ -41,6 +43,8 @@ public class PlanGamemodeChangeListener implements Listener {
return; return;
} }
Player p = event.getPlayer(); Player p = event.getPlayer();
handler.addToPool(new GamemodeInfo(p.getUniqueId(), MiscUtils.getTime(), Gamemode.wrap(event.getNewGameMode()))); UUID uuid = p.getUniqueId();
long time = MiscUtils.getTime();
handler.addToPool(new PlaytimeDependentInfo(uuid, InfoType.GM, time, event.getNewGameMode().name(), p.getWorld().getName()));
} }
} }

View File

@ -1,8 +1,9 @@
package main.java.com.djrapitops.plan.data.listeners; package main.java.com.djrapitops.plan.data.listeners;
import com.djrapitops.plugin.task.AbsRunnable; import com.djrapitops.plugin.task.AbsRunnable;
import com.djrapitops.plugin.utilities.player.Fetch;
import com.djrapitops.plugin.utilities.player.Gamemode; import com.djrapitops.plugin.utilities.player.Gamemode;
import com.djrapitops.plugin.utilities.player.bukkit.BukkitPlayer; import com.djrapitops.plugin.utilities.player.IPlayer;
import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Plan; import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.UserData; import main.java.com.djrapitops.plan.data.UserData;
@ -20,12 +21,14 @@ import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerKickEvent; import org.bukkit.event.player.PlayerKickEvent;
import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.player.PlayerQuitEvent;
import java.net.InetAddress;
import java.util.UUID; import java.util.UUID;
/** /**
* Event Listener for PlayerJoin, PlayerQuit and PlayerKickEvents. * Event Listener for PlayerJoin, PlayerQuit and PlayerKickEvents.
* *
* @author Rsl1122 * @author Rsl1122
* @since 2.0.0
*/ */
public class PlanPlayerListener implements Listener { public class PlanPlayerListener implements Listener {
@ -34,9 +37,8 @@ public class PlanPlayerListener implements Listener {
/** /**
* Class Constructor. * Class Constructor.
* * <p>
* Copies the references to multiple handlers from Current instance of * Copies the references to multiple handlers from Current instance of handler.
* handler.
* *
* @param plugin Current instance of Plan * @param plugin Current instance of Plan
*/ */
@ -47,42 +49,57 @@ public class PlanPlayerListener implements Listener {
/** /**
* PlayerJoinEvent Listener. * PlayerJoinEvent Listener.
* * <p>
* If player is a new player, creates a new data in the database for the * If player is a new player, creates new data for the player.
* player. Retrieves the UserData, updates and then saves it to the Cache. * <p>
* Adds a LoginInfo to the processingQueue if the user is not new.
* *
* @param event The Fired event. * @param event The Fired event.
*/ */
@EventHandler(priority = EventPriority.MONITOR) @EventHandler(priority = EventPriority.MONITOR)
public void onPlayerLogin(PlayerJoinEvent event) { public void onPlayerLogin(PlayerJoinEvent event) {
Player player = event.getPlayer(); Player player = event.getPlayer();
IPlayer iPlayer = Fetch.wrapBukkit(player);
plugin.getNotificationCenter().checkNotifications(iPlayer);
UUID uuid = player.getUniqueId(); UUID uuid = player.getUniqueId();
handler.startSession(uuid); handler.startSession(uuid);
Log.debug(uuid + ": PlayerJoinEvent"); Log.debug(uuid + ": PlayerJoinEvent");
plugin.getRunnableFactory().createNew(new AbsRunnable("NewPlayerCheckTask") { plugin.getRunnableFactory().createNew(new AbsRunnable("NewPlayerCheckTask") {
@Override @Override
public void run() { public void run() {
LoginInfo loginInfo = new LoginInfo(uuid, MiscUtils.getTime(), player.getAddress().getAddress(), player.isBanned(), player.getDisplayName(), Gamemode.wrap(player.getGameMode()), 1); long time = MiscUtils.getTime();
InetAddress ip = player.getAddress().getAddress();
boolean banned = player.isBanned();
String displayName = player.getDisplayName();
String gm = player.getGameMode().name();
String worldName = player.getWorld().getName();
LoginInfo loginInfo = new LoginInfo(uuid, time, ip, banned, displayName, gm, 1, worldName);
boolean isNewPlayer = !plugin.getDB().wasSeenBefore(uuid); boolean isNewPlayer = !plugin.getDB().wasSeenBefore(uuid);
if (isNewPlayer) { if (isNewPlayer) {
UserData newUserData = NewPlayerCreator.createNewPlayer(BukkitPlayer.wrap(player)); UserData newUserData = NewPlayerCreator.createNewPlayer(iPlayer);
loginInfo.process(newUserData); loginInfo.process(newUserData);
handler.newPlayer(newUserData); handler.newPlayer(newUserData);
} else { } else {
handler.addToPool(loginInfo); handler.addToPool(loginInfo);
} }
Log.debug(uuid + ": PlayerJoinEvent_AsyncTask_END, New:" + isNewPlayer); Log.debug(uuid + ": PlayerJoinEvent_AsyncTask_END, New:" + isNewPlayer);
this.cancel(); this.cancel();
} }
}).runTaskAsynchronously(); }).runTaskAsynchronously();
Log.debug(uuid + ": PlayerJoinEvent_END"); Log.debug(uuid + ": PlayerJoinEvent_END");
} }
/** /**
* PlayerQuitEvent Listener. * PlayerQuitEvent Listener.
* * <p>
* Retrieves the current UserData for the Player, updates it, saves the data * Adds a LogoutInfo to the processing Queue.
* to Database and clears it from cache.
* *
* @param event Fired event * @param event Fired event
*/ */
@ -92,15 +109,20 @@ public class PlanPlayerListener implements Listener {
UUID uuid = player.getUniqueId(); UUID uuid = player.getUniqueId();
handler.endSession(uuid); handler.endSession(uuid);
Log.debug(uuid + ": PlayerQuitEvent"); Log.debug(uuid + ": PlayerQuitEvent");
handler.addToPool(new LogoutInfo(uuid, MiscUtils.getTime(), player.isBanned(), Gamemode.wrap(player.getGameMode()), handler.getSession(uuid))); long time = MiscUtils.getTime();
boolean banned = player.isBanned();
Gamemode gm = Gamemode.wrap(player.getGameMode());
String worldName = player.getWorld().getName();
handler.addToPool(new LogoutInfo(uuid, time, banned, gm.name(), handler.getSession(uuid), worldName));
handler.saveCachedData(uuid); handler.saveCachedData(uuid);
Log.debug(uuid + ": PlayerQuitEvent_END"); Log.debug(uuid + ": PlayerQuitEvent_END");
} }
/** /**
* PlayerKickEvent Listener. * PlayerKickEvent Listener.
* * <p>
* Updates current playerdata and saves it to the Database. * Adds a KickInfo & LogoutInfo to the processing Queue.
* *
* @param event Fired event * @param event Fired event
*/ */
@ -113,7 +135,12 @@ public class PlanPlayerListener implements Listener {
UUID uuid = player.getUniqueId(); UUID uuid = player.getUniqueId();
handler.endSession(uuid); handler.endSession(uuid);
Log.debug(uuid + ": PlayerKickEvent"); Log.debug(uuid + ": PlayerKickEvent");
handler.addToPool(new LogoutInfo(uuid, MiscUtils.getTime(), player.isBanned(), Gamemode.wrap(player.getGameMode()), handler.getSession(uuid))); long time = MiscUtils.getTime();
boolean banned = player.isBanned();
Gamemode gm = Gamemode.wrap(player.getGameMode());
String worldName = player.getWorld().getName();
handler.addToPool(new LogoutInfo(uuid, time, banned, gm.name(), handler.getSession(uuid), worldName));
handler.addToPool(new KickInfo(uuid)); handler.addToPool(new KickInfo(uuid));
handler.saveCachedData(uuid); handler.saveCachedData(uuid);
Log.debug(uuid + ": PlayerKickEvent_END"); Log.debug(uuid + ": PlayerKickEvent_END");

View File

@ -0,0 +1,35 @@
package main.java.com.djrapitops.plan.data.listeners;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.cache.DataCacheHandler;
import main.java.com.djrapitops.plan.data.handling.info.InfoType;
import main.java.com.djrapitops.plan.data.handling.info.PlaytimeDependentInfo;
import main.java.com.djrapitops.plan.utilities.MiscUtils;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerChangedWorldEvent;
import java.util.UUID;
public class PlanWorldChangeListener implements Listener {
private final DataCacheHandler handler;
public PlanWorldChangeListener(Plan plugin) {
this.handler = plugin.getHandler();
}
@EventHandler(priority = EventPriority.MONITOR)
public void onWorldChange(PlayerChangedWorldEvent event) {
Player p = event.getPlayer();
String previousWorld = event.getFrom().getName();
String worldName = p.getWorld().getName();
if (previousWorld.equals(worldName)) {
return;
}
UUID uuid = p.getUniqueId();
long time = MiscUtils.getTime();
handler.addToPool(new PlaytimeDependentInfo(uuid, InfoType.WORLD, time, p.getGameMode().name(), p.getWorld().getName()));
}
}

View File

@ -8,6 +8,7 @@ import main.java.com.djrapitops.plan.data.TPS;
import main.java.com.djrapitops.plan.data.cache.DataCacheHandler; import main.java.com.djrapitops.plan.data.cache.DataCacheHandler;
import main.java.com.djrapitops.plan.utilities.MiscUtils; import main.java.com.djrapitops.plan.utilities.MiscUtils;
import main.java.com.djrapitops.plan.utilities.analysis.MathUtils; import main.java.com.djrapitops.plan.utilities.analysis.MathUtils;
import org.bukkit.World;
import java.lang.management.ManagementFactory; import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean; import java.lang.management.OperatingSystemMXBean;
@ -21,10 +22,10 @@ import java.util.List;
*/ */
public class TPSCountTimer extends AbsRunnable { public class TPSCountTimer extends AbsRunnable {
private long lastCheckNano;
private final Plan plugin; private final Plan plugin;
private final DataCacheHandler handler; private final DataCacheHandler handler;
private final List<TPS> history; private final List<TPS> history;
private long lastCheckNano;
public TPSCountTimer(Plan plugin) { public TPSCountTimer(Plan plugin) {
super("TPSCountTimer"); super("TPSCountTimer");
@ -67,20 +68,57 @@ public class TPSCountTimer extends AbsRunnable {
OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean(); OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean();
int availableProcessors = operatingSystemMXBean.getAvailableProcessors(); int availableProcessors = operatingSystemMXBean.getAvailableProcessors();
double averageCPUUsage = MathUtils.round(operatingSystemMXBean.getSystemLoadAverage() / availableProcessors * 100.0); double averageCPUUsage = MathUtils.round(operatingSystemMXBean.getSystemLoadAverage() / availableProcessors * 100.0);
if (averageCPUUsage < 0) { // If Unavailable, getSystemLoadAverage() returns -1
if (averageCPUUsage < 0) { // If unavailable, getSystemLoadAverage() returns -1
averageCPUUsage = -1; averageCPUUsage = -1;
} }
Runtime runtime = Runtime.getRuntime();
long totalMemory = runtime.totalMemory();
long usedMemory = (totalMemory - runtime.freeMemory()) / 1000000;
int playersOnline = plugin.getServer().getOnlinePlayers().size(); int playersOnline = plugin.getServer().getOnlinePlayers().size();
int loadedChunks = getLoadedChunks();
int entityCount;
if (plugin.getVariable().isUsingPaper()) { if (plugin.getVariable().isUsingPaper()) {
return getTPSPaper(now, averageCPUUsage, playersOnline); entityCount = getEntityCountPaper();
return getTPSPaper(now, averageCPUUsage, usedMemory, entityCount, loadedChunks, playersOnline);
} else { } else {
entityCount = getEntityCount();
diff -= TimeAmount.MILLISECOND.ns() * 40L; // 40ms removed because the run appears to take 40-50ms, screwing the tps. diff -= TimeAmount.MILLISECOND.ns() * 40L; // 40ms removed because the run appears to take 40-50ms, screwing the tps.
return getTPS(diff, now, averageCPUUsage, playersOnline); return getTPS(diff, now, averageCPUUsage, usedMemory, entityCount, loadedChunks, playersOnline);
} }
} }
/**
* Gets the TPS for Spigot / Bukkit
*
* @param diff The difference between the last run and this run
* @param now The time right now
* @param cpuUsage The usage of the CPU
* @param playersOnline The amount of players that are online
* @return the TPS
*/
private TPS getTPS(long diff, long now, double cpuUsage, long usedMemory, int entityCount, int chunksLoaded, int playersOnline) {
if (diff < TimeAmount.SECOND.ns()) { // No tick count above 20
diff = TimeAmount.SECOND.ns();
}
long twentySeconds = 20L * TimeAmount.SECOND.ns();
while (diff > twentySeconds) {
history.add(new TPS(now, 0, playersOnline, cpuUsage, usedMemory, entityCount, chunksLoaded));
diff -= twentySeconds;
}
double tpsN = twentySeconds * 1.0 / diff;
return new TPS(now, tpsN, playersOnline, cpuUsage, usedMemory, entityCount, chunksLoaded);
}
/** /**
* Gets the TPS for Paper * Gets the TPS for Paper
* *
@ -89,7 +127,7 @@ public class TPSCountTimer extends AbsRunnable {
* @param playersOnline The amount of players that are online * @param playersOnline The amount of players that are online
* @return the TPS * @return the TPS
*/ */
private TPS getTPSPaper(long now, double cpuUsage, int playersOnline) { private TPS getTPSPaper(long now, double cpuUsage, long usedMemory, int entityCount, int chunksLoaded, int playersOnline) {
double tps = plugin.getServer().getTPS()[0]; double tps = plugin.getServer().getTPS()[0];
if (tps > 20) { if (tps > 20) {
@ -98,31 +136,33 @@ public class TPSCountTimer extends AbsRunnable {
tps = MathUtils.round(tps); tps = MathUtils.round(tps);
return new TPS(now, tps, playersOnline, cpuUsage); return new TPS(now, tps, playersOnline, cpuUsage, usedMemory, entityCount, chunksLoaded);
} }
/** /**
* Gets the TPS for a Spigot / Bukkit * Gets the amount of loaded chunks
* *
* @param diff The difference between the last run and this run * @return amount of loaded chunks
* @param now The time right now
* @param cpuUsage The usage of the CPU
* @param playersOnline The amount of players that are online
* @return the TPS
*/ */
private TPS getTPS(long diff, long now, double cpuUsage, int playersOnline) { private int getLoadedChunks() {
if (diff < TimeAmount.SECOND.ns()) { // No tick count above 20 return plugin.getServer().getWorlds().stream().mapToInt(world -> world.getLoadedChunks().length).sum();
diff = TimeAmount.SECOND.ns();
} }
long twentySeconds = 20L * TimeAmount.SECOND.ns(); /**
while (diff > twentySeconds) { * Gets the amount of entities on the server for Bukkit / Spigot
history.add(new TPS(now, 0, playersOnline, cpuUsage)); *
diff -= twentySeconds; * @return amount of entities
*/
private int getEntityCount() {
return plugin.getServer().getWorlds().stream().mapToInt(world -> world.getEntities().size()).sum();
} }
double tpsN = twentySeconds / diff; /**
* Gets the amount of entities on the server for Paper
return new TPS(now, tpsN, playersOnline, cpuUsage); *
* @return amount of entities
*/
private int getEntityCountPaper() {
return plugin.getServer().getWorlds().stream().mapToInt(World::getEntityCount).sum();
} }
} }

View File

@ -0,0 +1,73 @@
package main.java.com.djrapitops.plan.data.time;
import com.djrapitops.plugin.utilities.Verify;
import main.java.com.djrapitops.plan.database.tables.GMTimesTable;
import java.util.Map;
/**
* TimeKeeper class that tracks the time spent in each GameMode based on Playtime.
*
* @author Rsl1122
* @since 3.6.0
*/
public class GMTimes extends TimeKeeper {
public GMTimes(Map<String, Long> times, String lastState, long lastStateChange) {
super(times, lastState, lastStateChange);
}
public GMTimes(String lastState, long lastStateChange) {
super(lastState, lastStateChange);
}
public GMTimes(String lastState) {
super(lastState);
}
public GMTimes(Map<String, Long> times) {
super(times);
}
public GMTimes() {
super();
}
/**
* Sets times for all 4 gamemodes.
* <p>
* Give 1 - 4 parameters.
* times starts from Survival, ends in Spectator.
* <p>
* Given too few parameters (Under 4, rest are set as 0L)
* Extra parameters are ignored (Over 4)
*
* @param times 1-4 time parameters.
* @throws IllegalArgumentException If any parameter is null.
*/
public void setAllGMTimes(long... times) throws IllegalArgumentException {
Verify.nullCheck(times);
String[] gms = GMTimesTable.getGMKeyArray();
int size = times.length;
for (int i = 0; i < 4; i++) {
if (i >= size) {
setTime(gms[i], 0L);
} else {
setTime(gms[i], times[i]);
}
}
}
public void resetTimes(long playtime) {
resetState("SURVIVAL", playtime);
resetState("CREATIVE");
resetState("ADVENTURE");
resetState("SPECTATOR");
}
@Override
public String getState() {
String state = super.getState();
return state != null ? state : "SURVIVAL";
}
}

View File

@ -0,0 +1,162 @@
package main.java.com.djrapitops.plan.data.time;
import com.djrapitops.plugin.utilities.Verify;
import java.util.HashMap;
import java.util.Map;
/**
* Abstract class for keeping track of time spent in each state.
*/
public abstract class TimeKeeper {
/**
* Keeps time of states.
*/
protected Map<String, Long> times;
/**
* Last State seen in
*/
protected String state;
/**
* Relates to Playtime Milliseconds.
*/
protected long lastStateChange;
public TimeKeeper(Map<String, Long> times, String lastState, long lastStateChange) {
this.times = times;
this.state = lastState;
this.lastStateChange = lastStateChange;
}
public TimeKeeper(String lastState, long lastStateChange) {
this(new HashMap<>(), lastState, lastStateChange);
}
public TimeKeeper(String lastState) {
this(new HashMap<>(), lastState, 0L);
}
public TimeKeeper(Map<String, Long> times) {
this(times, null, 0);
}
public TimeKeeper() {
this(new HashMap<>());
}
public void setTime(String state, long time) throws IllegalArgumentException {
times.put(Verify.nullCheck(state), time);
}
public void renameState(String state, String renameTo) {
Verify.nullCheck(state, renameTo);
Long time = times.get(state);
if (time != null) {
times.put(renameTo, time);
times.remove(state);
if (state.equals(this.state)) {
this.state = renameTo;
}
}
}
/**
* Adds time to the last state while updating the status of other parameters.
*
* @param newState New State seen in.
* @param playTime Current Playtime.
* @throws IllegalArgumentException If new state is null.
* @throws IllegalStateException If lastStateChange time is higher than playtime.
*/
public void changeState(String newState, long playTime) throws IllegalArgumentException, IllegalStateException {
Verify.nullCheck(newState);
if (playTime < lastStateChange) {
throw new IllegalStateException("Given Playtime is lower than last status change time: " + playTime + " / " + lastStateChange);
}
if (state == null) {
state = newState;
}
Long currentTime = times.get(state);
if (currentTime == null) {
currentTime = 0L;
}
long diff = playTime - lastStateChange;
times.put(state, currentTime + diff);
state = newState;
lastStateChange = playTime;
}
protected void resetState(String state) {
times.remove(Verify.nullCheck(state));
}
protected void resetState(String state, long time) {
if (time > 0) {
times.put(Verify.nullCheck(state), time);
lastStateChange = time;
this.state = state;
} else {
resetState(state);
}
}
public long getTime(String state) {
Long time = times.get(state);
return time != null ? time : 0L;
}
public long getTotal() {
return times.values().stream().mapToLong(i -> i).sum();
}
public void setTimes(Map<String, Long> times) {
this.times = times;
}
public Map<String, Long> getTimes() {
return times;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TimeKeeper that = (TimeKeeper) o;
if (lastStateChange != that.lastStateChange) return false;
if (times != null ? !times.equals(that.times) : that.times != null) return false;
return state != null ? state.equals(that.state) : that.state == null;
}
@Override
public int hashCode() {
int result = times != null ? times.hashCode() : 0;
result = 31 * result + (state != null ? state.hashCode() : 0);
result = 31 * result + (int) (lastStateChange ^ (lastStateChange >>> 32));
return result;
}
public void setState(String state) {
this.state = state;
}
public void setLastStateChange(long lastStateChange) {
this.lastStateChange = lastStateChange;
}
public String getState() {
return state;
}
public long getLastStateChange() {
return lastStateChange;
}
@Override
public String toString() {
return "times:" + times +
",state:" + state +
",lastStateChange:" + lastStateChange;
}
}

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