From 24b6669c7d1211f1bfcbb17bcb6352639dace8d1 Mon Sep 17 00:00:00 2001 From: Risto Lahtela <24460436+Rsl1122@users.noreply.github.com> Date: Tue, 17 Nov 2020 17:41:12 +0200 Subject: [PATCH 01/20] DataService implementation from another branch --- .../java/com/djrapitops/plan/DataService.java | 76 ++++++++ .../java/com/djrapitops/plan/DataSvc.java | 180 ++++++++++++++++++ .../modules/SystemObjectProvidingModule.java | 8 + 3 files changed, 264 insertions(+) create mode 100644 Plan/common/src/main/java/com/djrapitops/plan/DataService.java create mode 100644 Plan/common/src/main/java/com/djrapitops/plan/DataSvc.java diff --git a/Plan/common/src/main/java/com/djrapitops/plan/DataService.java b/Plan/common/src/main/java/com/djrapitops/plan/DataService.java new file mode 100644 index 000000000..b799d05b7 --- /dev/null +++ b/Plan/common/src/main/java/com/djrapitops/plan/DataService.java @@ -0,0 +1,76 @@ +/* + * This file is part of Player Analytics (Plan). + * + * Plan is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License v3 as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Plan is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Plan. If not, see . + */ +package com.djrapitops.plan; + +import java.util.Optional; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; + +/** + * Service for sourcing, mapping and consuming data. + *

+ * The service is in charge of two data flows: + * - push, given to consumers + * - pull, obtained from sources + *

+ * The mappers facilitate a one way type transformation if needed. + *

+ * The interface is very abstract about how data is obtained, + * but here are my general ideas of where the abstraction is coming from. + * - push cause one or multiple consumers to modify stored data + * - pull cause one or multiple suppliers to fetch stored data + * - mappers are stateless type transformers in memory + *

+ * Example use-case: + * - PlayerJoinEvent -> mapped to a generic event + * - that generic event is then consumed and mapped until the data is in a database. + *

+ * - Some kind of data is wanted to place on a web page + * - It is requested and the suppliers and mappers give the wanted type of data. + *

+ * Further research needed: + * - Can this limited type system represent types of data that need parameters + * (such as differentiate between two servers data) + */ +public interface DataService { + + DataService push(Class type, M data); + + Optional pull(Class type); + + Optional pull(Class type, P parameter); + + B mapTo(Class toType, A from); + + default Optional pull(Class type, Class

parameterType) { + return pull(type, () -> pull(parameterType).orElse(null)); + } + + default Optional pull(Class type, Supplier

parameter) { + return pull(type, parameter.get()); + } + + DataService registerMapper(Class typeA, Class typeB, Function mapper); + + DataService registerConsumer(Class type, Consumer consumer); + + DataService registerSupplier(Class type, Supplier supplier); + + DataService registerSupplier(Class type, Class

parameterType, Function supplierWithParameter); + +} diff --git a/Plan/common/src/main/java/com/djrapitops/plan/DataSvc.java b/Plan/common/src/main/java/com/djrapitops/plan/DataSvc.java new file mode 100644 index 000000000..8ca95957b --- /dev/null +++ b/Plan/common/src/main/java/com/djrapitops/plan/DataSvc.java @@ -0,0 +1,180 @@ +/* + * This file is part of Player Analytics (Plan). + * + * Plan is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License v3 as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Plan is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Plan. If not, see . + */ +package com.djrapitops.plan; + +import javax.inject.Inject; +import javax.inject.Singleton; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; + +@Singleton +public class DataSvc implements DataService { + + private final MultiHashMap mappers; + private final MultiHashMap mappersReverse; + private final Map suppliers; + private final Map suppliersWithParameter; + private final MultiHashMap consumers; + + @Inject + public DataSvc() { + mappers = new MultiHashMap<>(); + mappersReverse = new MultiHashMap<>(); + suppliers = new ConcurrentHashMap<>(); + suppliersWithParameter = new ConcurrentHashMap<>(); + consumers = new MultiHashMap<>(); + } + + @Override + public DataService push(Class type, A data) { + if (data == null) return this; + List mappers = this.mappers.get(type); + for (Mapper mapper : mappers) { + push(mapper.typeB, mapper.func.apply(data)); + } + List consumers = this.consumers.get(type); + for (Consumer consumer : consumers) { + consumer.accept(data); + } + if (mappers.isEmpty() && consumers.isEmpty()) { + System.out.println("WARN: Nothing consumed " + type); + } + return this; + } + + @Override + public Optional pull(Class type) { + Supplier present = this.suppliers.get(type); + if (present != null) return Optional.ofNullable((A) present.get()); + + List mappers = this.mappersReverse.get(type); + for (Mapper mapper : mappers) { + Optional found = pull(mapper.typeA) + .map(data -> mapper.func.apply(data)); + if (found.isPresent()) return found; + } + + System.out.println("WARN: Nothing supplied " + type); + return Optional.empty(); + } + + @Override + public B mapTo(Class toType, A from) { + List mappers = this.mappers.get(from.getClass()); + for (Mapper mapper : mappers) { + if (mapper.typeB.equals(toType)) { + return toType.cast(mapper.func.apply(from)); + } + } + // TODO Figure out type mapping resolution when it needs more than one mapping + System.out.println("WARN: No mapper for " + from.getClass() + " -> " + toType); + return null; + } + + @Override + public DataService registerMapper(Class typeA, Class typeB, Function mapper) { + Mapper asWrapper = new Mapper<>(typeA, typeB, mapper); + // TODO Prevent two mappers for same 2 types with a data structure + mappers.putOne(typeA, asWrapper); + mappersReverse.putOne(typeB, asWrapper); + return this; + } + + @Override + public DataService registerConsumer(Class type, Consumer consumer) { + consumers.putOne(type, consumer); + return this; + } + + @Override + public DataService registerSupplier(Class type, Supplier supplier) { + suppliers.put(type, supplier); + return this; + } + + @Override + public Optional pull(Class type, P parameter) { + if (parameter == null) return Optional.empty(); + Function function = suppliersWithParameter.get(new ClassPair<>(type, parameter.getClass())); + return function != null ? Optional.of(function.apply(parameter)) : Optional.empty(); + } + + @Override + public DataService registerSupplier(Class type, Class

parameterType, Function supplierWithParameter) { + suppliersWithParameter.put(new ClassPair<>(type, parameterType), supplierWithParameter); + return this; + } + + private static class ClassPair { + final Class a; + final Class b; + + public ClassPair(Class a, Class b) { + this.a = a; + this.b = b; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ClassPair classPair = (ClassPair) o; + return a.equals(classPair.a) && + b.equals(classPair.b); + } + + @Override + public int hashCode() { + return Objects.hash(a, b); + } + } + + private static class KeyValuePair { + final K key; + final V value; + + public KeyValuePair(K key, V value) { + this.key = key; + this.value = value; + } + } + + private static class MultiHashMap extends ConcurrentHashMap> { + + void putOne(A key, B value) { + List values = getOrDefault(key, new ArrayList<>()); + values.add(value); + put(key, values); + } + + } + + private static class Mapper { + Class typeA; + Class typeB; + Function func; + + public Mapper(Class typeA, Class typeB, Function func) { + this.typeA = typeA; + this.typeB = typeB; + this.func = func; + } + } +} diff --git a/Plan/common/src/main/java/com/djrapitops/plan/modules/SystemObjectProvidingModule.java b/Plan/common/src/main/java/com/djrapitops/plan/modules/SystemObjectProvidingModule.java index af4c80db0..9701a3bc2 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/modules/SystemObjectProvidingModule.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/modules/SystemObjectProvidingModule.java @@ -16,6 +16,8 @@ */ package com.djrapitops.plan.modules; +import com.djrapitops.plan.DataService; +import com.djrapitops.plan.DataSvc; import com.djrapitops.plan.PlanPlugin; import com.djrapitops.plan.settings.config.ExtensionSettings; import com.djrapitops.plan.settings.config.PlanConfig; @@ -78,4 +80,10 @@ public class SystemObjectProvidingModule { return errorLogger; } + @Provides + @Singleton + DataService provideDataService(DataSvc dataService) { + return dataService; + } + } \ No newline at end of file From 35ca5a8560493db229e7f5d269fbbb59a7b16974 Mon Sep 17 00:00:00 2001 From: Risto Lahtela <24460436+Rsl1122@users.noreply.github.com> Date: Tue, 17 Nov 2020 18:11:38 +0200 Subject: [PATCH 02/20] Add possibility to query directly via service --- .../java/com/djrapitops/plan/DataService.java | 4 ++++ .../main/java/com/djrapitops/plan/DataSvc.java | 16 +++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/Plan/common/src/main/java/com/djrapitops/plan/DataService.java b/Plan/common/src/main/java/com/djrapitops/plan/DataService.java index b799d05b7..c00d54dbf 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/DataService.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/DataService.java @@ -16,6 +16,8 @@ */ package com.djrapitops.plan; +import com.djrapitops.plan.storage.database.queries.Query; + import java.util.Optional; import java.util.function.Consumer; import java.util.function.Function; @@ -73,4 +75,6 @@ public interface DataService { DataService registerSupplier(Class type, Class

parameterType, Function supplierWithParameter); + DataService registerDBSupplier(Class type, Class

parameterType, Function> supplierWithParameter); + } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/DataSvc.java b/Plan/common/src/main/java/com/djrapitops/plan/DataSvc.java index 8ca95957b..cc27379f7 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/DataSvc.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/DataSvc.java @@ -16,6 +16,10 @@ */ package com.djrapitops.plan; +import com.djrapitops.plan.storage.database.DBSystem; +import com.djrapitops.plan.storage.database.queries.Query; +import dagger.Lazy; + import javax.inject.Inject; import javax.inject.Singleton; import java.util.*; @@ -33,8 +37,13 @@ public class DataSvc implements DataService { private final Map suppliersWithParameter; private final MultiHashMap consumers; + private final Lazy dbSystem; + @Inject - public DataSvc() { + public DataSvc( + Lazy dbSystem + ) { + this.dbSystem = dbSystem; mappers = new MultiHashMap<>(); mappersReverse = new MultiHashMap<>(); suppliers = new ConcurrentHashMap<>(); @@ -122,6 +131,11 @@ public class DataSvc implements DataService { return this; } + @Override + public DataService registerDBSupplier(Class type, Class

parameterType, Function> queryVisitor) { + return registerSupplier(type, parameterType, parameter -> dbSystem.get().getDatabase().query(queryVisitor.apply(parameter))); + } + private static class ClassPair { final Class a; final Class b; From d402b1c8329b2010762218e9736dbe0a6df3e5b4 Mon Sep 17 00:00:00 2001 From: Risto Lahtela <24460436+Rsl1122@users.noreply.github.com> Date: Thu, 19 Nov 2020 16:10:18 +0200 Subject: [PATCH 03/20] Refactored table html rendering classes away from TableContainer TableContainer is deprecated and this has been on the todo list for a while --- .../delivery/rendering/html/icon/Color.java | 6 ++ .../html/structure/DynamicHtmlTable.java | 90 ++++++++++++++++++ .../rendering/html/structure/HtmlTable.java | 74 +++++++++++++++ .../structure/HtmlTableWithColoredHeader.java | 94 +++++++++++++++++++ .../rendering/pages/PlayerPluginTab.java | 2 +- .../rendering/pages/ServerPluginTabs.java | 2 +- .../results/ExtensionTableData.java | 44 +-------- .../html/structure/HtmlTableTest.java | 79 ++++++++++++++++ .../queries/ExtensionsDatabaseTest.java | 41 ++++---- 9 files changed, 370 insertions(+), 62 deletions(-) create mode 100644 Plan/common/src/main/java/com/djrapitops/plan/delivery/rendering/html/structure/DynamicHtmlTable.java create mode 100644 Plan/common/src/main/java/com/djrapitops/plan/delivery/rendering/html/structure/HtmlTable.java create mode 100644 Plan/common/src/main/java/com/djrapitops/plan/delivery/rendering/html/structure/HtmlTableWithColoredHeader.java create mode 100644 Plan/common/src/test/java/com/djrapitops/plan/delivery/rendering/html/structure/HtmlTableTest.java diff --git a/Plan/common/src/main/java/com/djrapitops/plan/delivery/rendering/html/icon/Color.java b/Plan/common/src/main/java/com/djrapitops/plan/delivery/rendering/html/icon/Color.java index 83e37b48a..dbf9bb3a6 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/delivery/rendering/html/icon/Color.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/delivery/rendering/html/icon/Color.java @@ -16,6 +16,8 @@ */ package com.djrapitops.plan.delivery.rendering.html.icon; +import org.apache.commons.lang3.StringUtils; + import java.util.Optional; public enum Color { @@ -61,4 +63,8 @@ public enum Color { public String getHtmlClass() { return htmlClass; } + + public String getBackgroundColorClass() { + return StringUtils.replace(htmlClass, "col-", "bg-"); + } } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/delivery/rendering/html/structure/DynamicHtmlTable.java b/Plan/common/src/main/java/com/djrapitops/plan/delivery/rendering/html/structure/DynamicHtmlTable.java new file mode 100644 index 000000000..462f6a3ac --- /dev/null +++ b/Plan/common/src/main/java/com/djrapitops/plan/delivery/rendering/html/structure/DynamicHtmlTable.java @@ -0,0 +1,90 @@ +/* + * This file is part of Player Analytics (Plan). + * + * Plan is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License v3 as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Plan is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Plan. If not, see . + */ +package com.djrapitops.plan.delivery.rendering.html.structure; + +import com.djrapitops.plan.extension.table.Table; + +import java.util.List; + +public class DynamicHtmlTable implements HtmlTable { + private final Header[] headers; + private final List rows; + + public DynamicHtmlTable(Header[] headers, List rows) { + this.headers = headers; + this.rows = rows; + } + + public DynamicHtmlTable(Table table) { + this(HtmlTable.mapToHeaders(table), table.getRows()); + } + + @Override + public String toHtml() { + return "

" + + "" + + buildTableHeader() + + buildTableBody() + + "
" + + "
"; + } + + private String buildTableHeader() { + StringBuilder builtHeader = new StringBuilder(""); + for (Header header : headers) { + builtHeader.append("") + .append(header.getIcon().toHtml()) + .append(' ') + .append(header.getText()) + .append(""); + } + builtHeader.append(""); + return builtHeader.toString(); + } + + private String buildTableBody() { + StringBuilder builtBody = new StringBuilder(); + builtBody.append(""); + if (rows.isEmpty()) { + appendRow(builtBody, "No Data"); + } + for (Object[] row : rows) { + appendRow(builtBody, row); + } + return builtBody.append("").toString(); + } + + private void appendRow(StringBuilder builtBody, Object... row) { + int headerLength = row.length - 1; + builtBody.append(""); + for (int i = 0; i < headers.length; i++) { + try { + if (i > headerLength) { + builtBody.append("-"); + } else { + builtBody.append(""); + Object value = row[i]; + builtBody.append(value != null ? value : '-'); + } + builtBody.append(""); + } catch (ClassCastException | ArrayIndexOutOfBoundsException e) { + throw new IllegalStateException("Invalid formatter given at index " + i + ": " + e.getMessage(), e); + } + } + builtBody.append(""); + } +} diff --git a/Plan/common/src/main/java/com/djrapitops/plan/delivery/rendering/html/structure/HtmlTable.java b/Plan/common/src/main/java/com/djrapitops/plan/delivery/rendering/html/structure/HtmlTable.java new file mode 100644 index 000000000..6c3e719e7 --- /dev/null +++ b/Plan/common/src/main/java/com/djrapitops/plan/delivery/rendering/html/structure/HtmlTable.java @@ -0,0 +1,74 @@ +/* + * This file is part of Player Analytics (Plan). + * + * Plan is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License v3 as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Plan is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Plan. If not, see . + */ +package com.djrapitops.plan.delivery.rendering.html.structure; + +import com.djrapitops.plan.delivery.rendering.html.icon.Color; +import com.djrapitops.plan.delivery.rendering.html.icon.Icon; +import com.djrapitops.plan.extension.table.Table; + +import java.util.ArrayList; + +public interface HtmlTable { + + static HtmlTable fromExtensionTable(Table table, com.djrapitops.plan.extension.icon.Color tableColor) { + return fromExtensionTable(table, Color.getByName(tableColor.name()).orElse(Color.NONE)); + } + + static HtmlTable fromExtensionTable(Table table, Color tableColor) { + if (table.getRows().size() > 50) { + return new DynamicHtmlTable(table); + } else { + return new HtmlTableWithColoredHeader(table, tableColor); + } + } + + static Header[] mapToHeaders(Table table) { + ArrayList
headers = new ArrayList<>(); + + com.djrapitops.plan.extension.icon.Icon[] icons = table.getIcons(); + String[] columns = table.getColumns(); + for (int i = 0; i < columns.length; i++) { + String column = columns[i]; + if (column == null) { + break; + } + headers.add(new Header(Icon.fromExtensionIcon(icons[i]), column)); + } + + return headers.toArray(new Header[0]); + } + + String toHtml(); + + class Header { + private final Icon icon; + private final String text; + + public Header(Icon icon, String text) { + this.icon = icon; + this.text = text; + } + + public Icon getIcon() { + return icon; + } + + public String getText() { + return text; + } + } +} diff --git a/Plan/common/src/main/java/com/djrapitops/plan/delivery/rendering/html/structure/HtmlTableWithColoredHeader.java b/Plan/common/src/main/java/com/djrapitops/plan/delivery/rendering/html/structure/HtmlTableWithColoredHeader.java new file mode 100644 index 000000000..350f41ad1 --- /dev/null +++ b/Plan/common/src/main/java/com/djrapitops/plan/delivery/rendering/html/structure/HtmlTableWithColoredHeader.java @@ -0,0 +1,94 @@ +/* + * This file is part of Player Analytics (Plan). + * + * Plan is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License v3 as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Plan is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Plan. If not, see . + */ +package com.djrapitops.plan.delivery.rendering.html.structure; + +import com.djrapitops.plan.delivery.rendering.html.icon.Color; +import com.djrapitops.plan.extension.table.Table; + +import java.util.List; + +public class HtmlTableWithColoredHeader implements HtmlTable { + private final Header[] headers; + private final Color headerColor; + private final List rows; + + public HtmlTableWithColoredHeader(Header[] headers, Color headerColor, List rows) { + this.headers = headers; + this.headerColor = headerColor; + this.rows = rows; + } + + public HtmlTableWithColoredHeader(Table table, Color headerColor) { + this(HtmlTable.mapToHeaders(table), headerColor, table.getRows()); + } + + @Override + public String toHtml() { + return "
" + + "" + + buildTableHeader() + + buildTableBody() + + "
" + + "
"; + } + + private String buildTableHeader() { + StringBuilder builtHeader = new StringBuilder(""); + for (Header header : headers) { + builtHeader.append("") + .append(header.getIcon().toHtml()) + .append(' ') + .append(header.getText()) + .append(""); + } + builtHeader.append(""); + return builtHeader.toString(); + } + + private String buildTableBody() { + StringBuilder builtBody = new StringBuilder(); + builtBody.append(""); + if (rows.isEmpty()) { + appendRow(builtBody, "No Data"); + } + for (Object[] row : rows) { + appendRow(builtBody, row); + } + return builtBody.append("").toString(); + } + + private void appendRow(StringBuilder builtBody, Object... row) { + int headerLength = row.length - 1; + builtBody.append(""); + for (int i = 0; i < headers.length; i++) { + try { + if (i > headerLength) { + builtBody.append("-"); + } else { + builtBody.append(""); + Object value = row[i]; + builtBody.append(value != null ? value : '-'); + } + builtBody.append(""); + } catch (ClassCastException | ArrayIndexOutOfBoundsException e) { + throw new IllegalStateException("Invalid formatter given at index " + i + ": " + e.getMessage(), e); + } + } + builtBody.append(""); + } + +} diff --git a/Plan/common/src/main/java/com/djrapitops/plan/delivery/rendering/pages/PlayerPluginTab.java b/Plan/common/src/main/java/com/djrapitops/plan/delivery/rendering/pages/PlayerPluginTab.java index ee09b7ecb..90e84c298 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/delivery/rendering/pages/PlayerPluginTab.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/delivery/rendering/pages/PlayerPluginTab.java @@ -185,7 +185,7 @@ public class PlayerPluginTab implements Comparable { if (tableData.isWideTable()) { hasWideTable = true; } - builder.append(tableData.getHtmlTable().buildHtml()); + builder.append(tableData.getHtmlTable().toHtml()); } return builder.toString(); } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/delivery/rendering/pages/ServerPluginTabs.java b/Plan/common/src/main/java/com/djrapitops/plan/delivery/rendering/pages/ServerPluginTabs.java index 9a8ee1e60..c2400a28b 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/delivery/rendering/pages/ServerPluginTabs.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/delivery/rendering/pages/ServerPluginTabs.java @@ -207,7 +207,7 @@ public class ServerPluginTabs { private String buildTablesHtml(ExtensionTabData tabData) { StringBuilder builder = new StringBuilder(); for (ExtensionTableData tableData : tabData.getTableData()) { - builder.append(tableData.getHtmlTable().buildHtml()); + builder.append(tableData.getHtmlTable().toHtml()); } return builder.toString(); } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/results/ExtensionTableData.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/results/ExtensionTableData.java index e7c442dcb..a1ac54c9f 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/results/ExtensionTableData.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/results/ExtensionTableData.java @@ -16,15 +16,10 @@ */ package com.djrapitops.plan.extension.implementation.results; -import com.djrapitops.plan.data.element.TableContainer; +import com.djrapitops.plan.delivery.rendering.html.structure.HtmlTable; import com.djrapitops.plan.extension.icon.Color; -import com.djrapitops.plan.extension.icon.Icon; import com.djrapitops.plan.extension.table.Table; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; import java.util.Objects; /** @@ -44,41 +39,8 @@ public class ExtensionTableData implements Comparable { this.tableColor = tableColor; } - public TableContainer getHtmlTable() { - String[] columns = table.getColumns(); - Icon[] icons = table.getIcons(); - List rows = table.getRows(); - - String[] header = buildHeader(columns, icons); - - TableContainer htmlTable = new TableContainer(header); - if (rows.size() > 50) { - htmlTable.useJqueryDataTables(); // Use a jQuery data table since there are a lot of rows. - } else { - String colorName = com.djrapitops.plan.delivery.rendering.html.icon.Color.getByName(tableColor.name()).orElse(com.djrapitops.plan.delivery.rendering.html.icon.Color.NONE).getHtmlClass() - .replace("col-", ""); // TODO after PluginData deprecation, change this thing - htmlTable.setColor(colorName); - } - - for (Object[] row : rows) { - htmlTable.addRow(Arrays.stream(row).map(value -> value != null ? value.toString() : null).toArray(Serializable[]::new)); - } - - return htmlTable; - } - - private String[] buildHeader(String[] columns, Icon[] icons) { - ArrayList header = new ArrayList<>(); - - for (int i = 0; i < columns.length; i++) { - String column = columns[i]; - if (column == null) { - break; - } - header.add(com.djrapitops.plan.delivery.rendering.html.icon.Icon.fromExtensionIcon(icons[i]).toHtml() + ' ' + column); - } - - return header.toArray(new String[0]); + public HtmlTable getHtmlTable() { + return HtmlTable.fromExtensionTable(table, tableColor); } @Override diff --git a/Plan/common/src/test/java/com/djrapitops/plan/delivery/rendering/html/structure/HtmlTableTest.java b/Plan/common/src/test/java/com/djrapitops/plan/delivery/rendering/html/structure/HtmlTableTest.java new file mode 100644 index 000000000..fd69ba906 --- /dev/null +++ b/Plan/common/src/test/java/com/djrapitops/plan/delivery/rendering/html/structure/HtmlTableTest.java @@ -0,0 +1,79 @@ +/* + * This file is part of Player Analytics (Plan). + * + * Plan is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License v3 as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Plan is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Plan. If not, see . + */ +package com.djrapitops.plan.delivery.rendering.html.structure; + +import com.djrapitops.plan.extension.icon.Color; +import com.djrapitops.plan.extension.icon.Icon; +import com.djrapitops.plan.extension.table.Table; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * Sanity tests for the functionality of refactored html table rendering code. + */ +class HtmlTableTest { + + @Test + void coloredTableProducesSameHtmlAsOldCode() { + // Produced by old code + String expected = "
Col 1 Col 2 Col 3
12three
"; + + Icon icon = Icon.called("test").build(); + String result = HtmlTable.fromExtensionTable(Table.builder() + .columnOne("Col 1", icon) + .columnTwo("Col 2", icon) + .columnThree("Col 3", icon) + .addRow("1", 2, "three") + .build(), Color.AMBER).toHtml(); + assertEquals(expected, result); + } + + @Test + void coloredTableProducesSameHtmlAsOldCodeWhenEmpty() { + // Produced by old code + String expected = "
Col 1 Col 2 Col 3
No Data--
"; + + Icon icon = Icon.called("test").build(); + String result = HtmlTable.fromExtensionTable(Table.builder() + .columnOne("Col 1", icon) + .columnTwo("Col 2", icon) + .columnThree("Col 3", icon) + .build(), Color.AMBER).toHtml(); + assertEquals(expected, result); + } + + @Test + void dynamicTableProducesSameHtmlAsOldCode() { + // Produced by old code + String expected = "
Col 1 Col 2 Col 3
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
12three
"; + + Icon icon = Icon.called("test").build(); + Table.Factory buildingTable = Table.builder() + .columnOne("Col 1", icon) + .columnTwo("Col 2", icon) + .columnThree("Col 3", icon); + + for (int i = 0; i < 60; i++) { + buildingTable.addRow("1", 2, "three"); + } + + String result = HtmlTable.fromExtensionTable(buildingTable.build(), Color.AMBER).toHtml(); + assertEquals(expected, result); + } + +} \ No newline at end of file diff --git a/Plan/common/src/test/java/com/djrapitops/plan/storage/database/queries/ExtensionsDatabaseTest.java b/Plan/common/src/test/java/com/djrapitops/plan/storage/database/queries/ExtensionsDatabaseTest.java index 40fe64db8..1f84e8dbf 100644 --- a/Plan/common/src/test/java/com/djrapitops/plan/storage/database/queries/ExtensionsDatabaseTest.java +++ b/Plan/common/src/test/java/com/djrapitops/plan/storage/database/queries/ExtensionsDatabaseTest.java @@ -16,7 +16,7 @@ */ package com.djrapitops.plan.storage.database.queries; -import com.djrapitops.plan.data.element.TableContainer; +import com.djrapitops.plan.delivery.rendering.html.structure.HtmlTable; import com.djrapitops.plan.extension.CallEvents; import com.djrapitops.plan.extension.DataExtension; import com.djrapitops.plan.extension.ExtensionService; @@ -176,8 +176,9 @@ public interface ExtensionsDatabaseTest extends DatabaseTestPreparer { List tableData = tabData.getTableData(); assertEquals(1, tableData.size()); - TableContainer table = tableData.get(0).getHtmlTable(); - assertEquals("Group1", table.parseBody()); + HtmlTable table = tableData.get(0).getHtmlTable(); + String result = table.toHtml(); + assertTrue(result.contains("Group1"), result); } @Test @@ -305,15 +306,16 @@ public interface ExtensionsDatabaseTest extends DatabaseTestPreparer { assertEquals(1, tableData.size()); ExtensionTableData table = tableData.get(0); - TableContainer expected = new TableContainer( - " first", - " second", - " third" - ); - expected.setColor("amber"); - expected.addRow("value", 3, 0.5, 400L); + HtmlTable expected = HtmlTable.fromExtensionTable( + Table.builder() + .columnOne("first", Icon.called("gavel").build()) + .columnTwo("second", Icon.called("what").build()) + .columnThree("third", Icon.called("question").build()) + .addRow("value", 3, 0.5, 400L) + .build(), + com.djrapitops.plan.delivery.rendering.html.icon.Color.AMBER); - assertEquals(expected.buildHtml(), table.getHtmlTable().buildHtml()); + assertEquals(expected.toHtml(), table.getHtmlTable().toHtml()); } @Test @@ -338,15 +340,16 @@ public interface ExtensionsDatabaseTest extends DatabaseTestPreparer { assertEquals(1, tableData.size()); ExtensionTableData table = tableData.get(0); - TableContainer expected = new TableContainer( - " first", - " second", - " third" - ); - expected.setColor("amber"); - expected.addRow("value", 3, 0.5, 400L); + HtmlTable expected = HtmlTable.fromExtensionTable( + Table.builder() + .columnOne("first", Icon.called("gavel").build()) + .columnTwo("second", Icon.called("what").build()) + .columnThree("third", Icon.called("question").build()) + .addRow("value", 3, 0.5, 400L) + .build(), + com.djrapitops.plan.delivery.rendering.html.icon.Color.AMBER); - assertEquals(expected.buildHtml(), table.getHtmlTable().buildHtml()); + assertEquals(expected.toHtml(), table.getHtmlTable().toHtml()); } @PluginInfo(name = "ConditionalExtension") From 6292ef5f4d07482aad862ae18f99d85fe1060698 Mon Sep 17 00:00:00 2001 From: Risto Lahtela <24460436+Rsl1122@users.noreply.github.com> Date: Thu, 19 Nov 2020 16:34:52 +0200 Subject: [PATCH 04/20] Extracted TestSettings utility --- .../com/djrapitops/plan/BukkitSystemTest.java | 12 +-- .../plan/settings/ConfigSettingKeyTest.java | 86 ++--------------- .../config/changes/ConfigUpdaterTest.java | 60 ++++++------ .../src/test/java/utilities/TestSettings.java | 95 +++++++++++++++++++ .../com/djrapitops/plan/NukkitSystemTest.java | 6 +- .../com/djrapitops/plan/SpongeSystemTest.java | 6 +- 6 files changed, 139 insertions(+), 126 deletions(-) create mode 100644 Plan/common/src/test/java/utilities/TestSettings.java diff --git a/Plan/bukkit/src/test/java/com/djrapitops/plan/BukkitSystemTest.java b/Plan/bukkit/src/test/java/com/djrapitops/plan/BukkitSystemTest.java index 27e0f7d18..123ad7e08 100644 --- a/Plan/bukkit/src/test/java/com/djrapitops/plan/BukkitSystemTest.java +++ b/Plan/bukkit/src/test/java/com/djrapitops/plan/BukkitSystemTest.java @@ -16,19 +16,16 @@ */ package com.djrapitops.plan; -import com.djrapitops.plan.exceptions.EnableException; -import com.djrapitops.plan.settings.ConfigSettingKeyTest; import com.djrapitops.plan.settings.config.PlanConfig; import com.djrapitops.plan.settings.config.paths.WebserverSettings; -import com.djrapitops.plan.settings.config.paths.key.Setting; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import utilities.RandomData; +import utilities.TestSettings; import utilities.mocks.BukkitMockComponent; import java.nio.file.Path; -import java.util.Collection; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -51,7 +48,7 @@ class BukkitSystemTest { } @Test - void bukkitSystemEnables() throws EnableException { + void bukkitSystemEnables() { try { system.enable(); assertTrue(system.isEnabled()); @@ -61,13 +58,12 @@ class BukkitSystemTest { } @Test - void bukkitSystemHasDefaultConfigValuesAfterEnable() throws EnableException, IllegalAccessException { + void bukkitSystemHasDefaultConfigValuesAfterEnable() throws IllegalAccessException { try { system.enable(); PlanConfig config = system.getConfigSystem().getConfig(); - Collection serverSettings = ConfigSettingKeyTest.getServerSettings(); - ConfigSettingKeyTest.assertValidDefaultValuesForAllSettings(config, serverSettings); + TestSettings.assertValidDefaultValuesForAllSettings(config, TestSettings.getServerSettings()); } finally { system.disable(); } diff --git a/Plan/common/src/test/java/com/djrapitops/plan/settings/ConfigSettingKeyTest.java b/Plan/common/src/test/java/com/djrapitops/plan/settings/ConfigSettingKeyTest.java index f64804dfd..1d77b190d 100644 --- a/Plan/common/src/test/java/com/djrapitops/plan/settings/ConfigSettingKeyTest.java +++ b/Plan/common/src/test/java/com/djrapitops/plan/settings/ConfigSettingKeyTest.java @@ -17,35 +17,25 @@ package com.djrapitops.plan.settings; import com.djrapitops.plan.settings.config.PlanConfig; -import com.djrapitops.plan.settings.config.paths.*; -import com.djrapitops.plan.settings.config.paths.key.Setting; import com.djrapitops.plugin.logging.console.TestPluginLogger; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; -import utilities.FieldFetcher; import utilities.TestResources; +import utilities.TestSettings; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Optional; - -import static org.junit.jupiter.api.Assertions.assertTrue; /** * Test to check that configs contain all values required to run the plugin. - *

- * TODO Move public utility methods to an utility to make this class package private * * @author Rsl1122 */ -public class ConfigSettingKeyTest { +class ConfigSettingKeyTest { public static Path temporaryFolder; @@ -54,82 +44,18 @@ public class ConfigSettingKeyTest { temporaryFolder = tempDir; } - public static void assertValidDefaultValuesForAllSettings(PlanConfig config, Iterable settings) { - List fails = new ArrayList<>(); - for (Setting setting : settings) { - checkSettingForFailures(config, setting).ifPresent(fails::add); - } - assertTrue(fails.isEmpty(), fails::toString); - } - - private static Optional checkSettingForFailures(PlanConfig config, Setting setting) { - try { - if (!config.contains(setting.getPath())) { - return Optional.of("Did not contain " + setting.getPath()); - } else { - config.get(setting); - return Optional.empty(); - } - } catch (IllegalStateException validationFailed) { - return Optional.of(validationFailed.getMessage()); - } - } - - public static Collection getServerSettings() throws IllegalAccessException { - List settings = new ArrayList<>(); - for (Class settingKeyClass : new Class[]{ - DatabaseSettings.class, - DataGatheringSettings.class, - DisplaySettings.class, - ExportSettings.class, - FormatSettings.class, - PluginSettings.class, - TimeSettings.class, - WebserverSettings.class - }) { - settings.addAll(FieldFetcher.getPublicStaticFields(settingKeyClass, Setting.class)); - } - return settings; - } - - public static Collection getProxySettings() throws IllegalAccessException { - List settings = new ArrayList<>(); - for (Class settingKeyClass : new Class[]{ - DatabaseSettings.class, - DisplaySettings.class, - ExportSettings.class, - FormatSettings.class, - PluginSettings.class, - ProxySettings.class, - TimeSettings.class, - WebserverSettings.class - }) { - settings.addAll(FieldFetcher.getPublicStaticFields(settingKeyClass, Setting.class)); - } - // Server settings contained in the key classes, remove - settings.remove(PluginSettings.SERVER_NAME); - settings.remove(PluginSettings.PROXY_COPY_CONFIG); - settings.remove(DatabaseSettings.TYPE); - settings.remove(DisplaySettings.WORLD_ALIASES); - settings.remove(DatabaseSettings.H2_USER); - settings.remove(DatabaseSettings.H2_PASS); - return settings; - } - @Test @DisplayName("config.yml has valid default values") void serverConfigHasValidDefaultValues() throws IOException, IllegalAccessException { - PlanConfig planConfig = createConfig("config.yml"); - Collection settings = getServerSettings(); - assertValidDefaultValuesForAllSettings(planConfig, settings); + PlanConfig config = createConfig("config.yml"); + TestSettings.assertValidDefaultValuesForAllSettings(config, TestSettings.getServerSettings()); } @Test @DisplayName("bungeeconfig.yml has valid default values") void proxyConfigHasValidDefaultValues() throws IOException, IllegalAccessException { - PlanConfig planConfig = createConfig("bungeeconfig.yml"); - Collection settings = getProxySettings(); - assertValidDefaultValuesForAllSettings(planConfig, settings); + PlanConfig config = createConfig("bungeeconfig.yml"); + TestSettings.assertValidDefaultValuesForAllSettings(config, TestSettings.getProxySettings()); } private PlanConfig createConfig(String copyDefaultSettingsFrom) throws IOException { diff --git a/Plan/common/src/test/java/com/djrapitops/plan/settings/config/changes/ConfigUpdaterTest.java b/Plan/common/src/test/java/com/djrapitops/plan/settings/config/changes/ConfigUpdaterTest.java index 0a85bd685..5cba78350 100644 --- a/Plan/common/src/test/java/com/djrapitops/plan/settings/config/changes/ConfigUpdaterTest.java +++ b/Plan/common/src/test/java/com/djrapitops/plan/settings/config/changes/ConfigUpdaterTest.java @@ -16,10 +16,8 @@ */ package com.djrapitops.plan.settings.config.changes; -import com.djrapitops.plan.settings.ConfigSettingKeyTest; import com.djrapitops.plan.settings.config.ConfigReader; import com.djrapitops.plan.settings.config.PlanConfig; -import com.djrapitops.plan.settings.config.paths.key.Setting; import com.djrapitops.plan.utilities.logging.ErrorLogger; import com.djrapitops.plugin.logging.console.PluginLogger; import com.djrapitops.plugin.logging.console.TestPluginLogger; @@ -29,6 +27,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import org.mockito.Mockito; import utilities.TestResources; +import utilities.TestSettings; import java.io.File; import java.io.IOException; @@ -36,7 +35,6 @@ import java.net.URISyntaxException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; -import java.util.Collection; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -87,77 +85,75 @@ class ConfigUpdaterTest { @Test void serverConfigIsPatchedCorrectly() throws IOException, IllegalAccessException { - Path config = tempDir.resolve("oldconfig.yml"); - Files.copy(oldConfig.toPath(), config, StandardCopyOption.REPLACE_EXISTING); + Path configPath = tempDir.resolve("oldconfig.yml"); + Files.copy(oldConfig.toPath(), configPath, StandardCopyOption.REPLACE_EXISTING); - PlanConfig planConfig = new PlanConfig(config.toFile(), null, null, new TestPluginLogger()); + PlanConfig config = new PlanConfig(configPath.toFile(), null, null, new TestPluginLogger()); - UNDER_TEST.applyConfigUpdate(planConfig); + UNDER_TEST.applyConfigUpdate(config); // Ensure that added settings are present - copyMissingFrom(planConfig, newConfig); + copyMissingFrom(config, newConfig); - Collection settings = ConfigSettingKeyTest.getServerSettings(); - ConfigSettingKeyTest.assertValidDefaultValuesForAllSettings(planConfig, settings); + TestSettings.assertValidDefaultValuesForAllSettings(config, TestSettings.getServerSettings()); } @Test void proxyConfigIsPatchedCorrectly() throws IOException, IllegalAccessException { - Path config = tempDir.resolve("oldconfig.yml"); - Files.copy(oldBungeeConfig.toPath(), config, StandardCopyOption.REPLACE_EXISTING); + Path configPath = tempDir.resolve("oldconfig.yml"); + Files.copy(oldBungeeConfig.toPath(), configPath, StandardCopyOption.REPLACE_EXISTING); - PlanConfig planConfig = new PlanConfig(config.toFile(), null, null, new TestPluginLogger()); + PlanConfig config = new PlanConfig(configPath.toFile(), null, null, new TestPluginLogger()); - UNDER_TEST.applyConfigUpdate(planConfig); + UNDER_TEST.applyConfigUpdate(config); // Ensure that added settings are present - copyMissingFrom(planConfig, newBungeeConfig); + copyMissingFrom(config, newBungeeConfig); - Collection settings = ConfigSettingKeyTest.getProxySettings(); - ConfigSettingKeyTest.assertValidDefaultValuesForAllSettings(planConfig, settings); + TestSettings.assertValidDefaultValuesForAllSettings(config, TestSettings.getProxySettings()); } - private void copyMissingFrom(PlanConfig planConfig, Path newBungeeConfig) throws IOException { + private void copyMissingFrom(PlanConfig config, Path newBungeeConfig) throws IOException { try (ConfigReader reader = new ConfigReader(newBungeeConfig)) { - planConfig.copyMissing(reader.read()); + config.copyMissing(reader.read()); } } @Test void serverMoveChangesDoNotLeaveNewEmptyValues() throws IOException { - Path config = tempDir.resolve("oldconfig.yml"); - Files.copy(oldConfig.toPath(), config, StandardCopyOption.REPLACE_EXISTING); + Path configPath = tempDir.resolve("oldconfig.yml"); + Files.copy(oldConfig.toPath(), configPath, StandardCopyOption.REPLACE_EXISTING); - PlanConfig planConfig = new PlanConfig(config.toFile(), null, null, new TestPluginLogger()); + PlanConfig config = new PlanConfig(configPath.toFile(), null, null, new TestPluginLogger()); ConfigChange[] changes = UNDER_TEST.configEnhancementPatch(); - assertMoveChangesAreAppliedProperly(planConfig, changes); + assertMoveChangesAreAppliedProperly(config, changes); } @Test void proxyMoveChangesDoNotLeaveNewEmptyValues() throws IOException { - Path config = tempDir.resolve("oldconfig.yml"); - Files.copy(oldBungeeConfig.toPath(), config, StandardCopyOption.REPLACE_EXISTING); + Path configPath = tempDir.resolve("oldconfig.yml"); + Files.copy(oldBungeeConfig.toPath(), configPath, StandardCopyOption.REPLACE_EXISTING); - PlanConfig planConfig = new PlanConfig(config.toFile(), null, null, new TestPluginLogger()); + PlanConfig config = new PlanConfig(configPath.toFile(), null, null, new TestPluginLogger()); ConfigChange[] changes = UNDER_TEST.configEnhancementPatch(); - assertMoveChangesAreAppliedProperly(planConfig, changes); + assertMoveChangesAreAppliedProperly(config, changes); } - private void assertMoveChangesAreAppliedProperly(PlanConfig planConfig, ConfigChange[] changes) { + private void assertMoveChangesAreAppliedProperly(PlanConfig config, ConfigChange[] changes) { for (ConfigChange change : changes) { - if (change.hasBeenApplied(planConfig)) { + if (change.hasBeenApplied(config)) { continue; } if (change instanceof ConfigChange.Moved) { ConfigChange.Moved move = (ConfigChange.Moved) change; - String expected = planConfig.getString(move.oldPath); + String expected = config.getString(move.oldPath); - move.apply(planConfig); + move.apply(config); - assertEquals(expected, planConfig.getString(move.newPath)); + assertEquals(expected, config.getString(move.newPath)); } } } diff --git a/Plan/common/src/test/java/utilities/TestSettings.java b/Plan/common/src/test/java/utilities/TestSettings.java new file mode 100644 index 000000000..e2e14d7ad --- /dev/null +++ b/Plan/common/src/test/java/utilities/TestSettings.java @@ -0,0 +1,95 @@ +/* + * This file is part of Player Analytics (Plan). + * + * Plan is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License v3 as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Plan is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Plan. If not, see . + */ +package utilities; + +import com.djrapitops.plan.settings.config.PlanConfig; +import com.djrapitops.plan.settings.config.paths.*; +import com.djrapitops.plan.settings.config.paths.key.Setting; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * Utility for testing that configs contain all appropriate values. + */ +public class TestSettings { + public static void assertValidDefaultValuesForAllSettings(PlanConfig config, Iterable settings) { + List fails = new ArrayList<>(); + for (Setting setting : settings) { + checkSettingForFailures(config, setting).ifPresent(fails::add); + } + assertTrue(fails.isEmpty(), fails::toString); + } + + private static Optional checkSettingForFailures(PlanConfig config, Setting setting) { + try { + if (!config.contains(setting.getPath())) { + return Optional.of("Did not contain " + setting.getPath()); + } else { + config.get(setting); + return Optional.empty(); + } + } catch (IllegalStateException validationFailed) { + return Optional.of(validationFailed.getMessage()); + } + } + + public static Collection getServerSettings() throws IllegalAccessException { + List settings = new ArrayList<>(); + for (Class settingKeyClass : new Class[]{ + DatabaseSettings.class, + DataGatheringSettings.class, + DisplaySettings.class, + ExportSettings.class, + FormatSettings.class, + PluginSettings.class, + TimeSettings.class, + WebserverSettings.class + }) { + settings.addAll(FieldFetcher.getPublicStaticFields(settingKeyClass, Setting.class)); + } + return settings; + } + + public static Collection getProxySettings() throws IllegalAccessException { + List settings = new ArrayList<>(); + for (Class settingKeyClass : new Class[]{ + DatabaseSettings.class, + DisplaySettings.class, + ExportSettings.class, + FormatSettings.class, + PluginSettings.class, + ProxySettings.class, + TimeSettings.class, + WebserverSettings.class + }) { + settings.addAll(FieldFetcher.getPublicStaticFields(settingKeyClass, Setting.class)); + } + // Server settings contained in the key classes, remove + settings.remove(PluginSettings.SERVER_NAME); + settings.remove(PluginSettings.PROXY_COPY_CONFIG); + settings.remove(DatabaseSettings.TYPE); + settings.remove(DisplaySettings.WORLD_ALIASES); + settings.remove(DatabaseSettings.H2_USER); + settings.remove(DatabaseSettings.H2_PASS); + return settings; + } +} diff --git a/Plan/nukkit/src/test/java/com/djrapitops/plan/NukkitSystemTest.java b/Plan/nukkit/src/test/java/com/djrapitops/plan/NukkitSystemTest.java index 75c472146..ddfa9fd72 100644 --- a/Plan/nukkit/src/test/java/com/djrapitops/plan/NukkitSystemTest.java +++ b/Plan/nukkit/src/test/java/com/djrapitops/plan/NukkitSystemTest.java @@ -17,7 +17,6 @@ package com.djrapitops.plan; import com.djrapitops.plan.exceptions.EnableException; -import com.djrapitops.plan.settings.ConfigSettingKeyTest; import com.djrapitops.plan.settings.config.PlanConfig; import com.djrapitops.plan.settings.config.paths.WebserverSettings; import com.djrapitops.plan.settings.config.paths.key.Setting; @@ -25,6 +24,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import utilities.RandomData; +import utilities.TestSettings; import utilities.mocks.NukkitMockComponent; import java.nio.file.Path; @@ -65,8 +65,8 @@ class NukkitSystemTest { system.enable(); PlanConfig config = system.getConfigSystem().getConfig(); - Collection serverSettings = ConfigSettingKeyTest.getServerSettings(); - ConfigSettingKeyTest.assertValidDefaultValuesForAllSettings(config, serverSettings); + Collection serverSettings = TestSettings.getServerSettings(); + TestSettings.assertValidDefaultValuesForAllSettings(config, serverSettings); } finally { system.disable(); } diff --git a/Plan/sponge/src/test/java/com/djrapitops/plan/SpongeSystemTest.java b/Plan/sponge/src/test/java/com/djrapitops/plan/SpongeSystemTest.java index 93b33678a..ef9fcf1c1 100644 --- a/Plan/sponge/src/test/java/com/djrapitops/plan/SpongeSystemTest.java +++ b/Plan/sponge/src/test/java/com/djrapitops/plan/SpongeSystemTest.java @@ -17,7 +17,6 @@ package com.djrapitops.plan; import com.djrapitops.plan.exceptions.EnableException; -import com.djrapitops.plan.settings.ConfigSettingKeyTest; import com.djrapitops.plan.settings.config.PlanConfig; import com.djrapitops.plan.settings.config.paths.WebserverSettings; import com.djrapitops.plan.settings.config.paths.key.Setting; @@ -25,6 +24,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import utilities.RandomData; +import utilities.TestSettings; import utilities.mocks.SpongeMockComponent; import java.nio.file.Path; @@ -67,8 +67,8 @@ class SpongeSystemTest { system.enable(); PlanConfig config = system.getConfigSystem().getConfig(); - Collection serverSettings = ConfigSettingKeyTest.getServerSettings(); - ConfigSettingKeyTest.assertValidDefaultValuesForAllSettings(config, serverSettings); + Collection serverSettings = TestSettings.getServerSettings(); + TestSettings.assertValidDefaultValuesForAllSettings(config, serverSettings); } finally { system.disable(); } From a6a606494d78da006f45c949f795fdee9b5c5dca Mon Sep 17 00:00:00 2001 From: Risto Lahtela <24460436+Rsl1122@users.noreply.github.com> Date: Thu, 19 Nov 2020 16:50:15 +0200 Subject: [PATCH 05/20] PlayerKill now supports killer UUID --- .../domain/mutators/PlayerKillMutator.java | 2 +- .../plan/gathering/domain/PlayerKill.java | 31 ++++++++++--------- .../player/PlayerKillProcessor.java | 2 +- .../database/queries/objects/KillQueries.java | 15 ++++++--- .../queries/objects/SessionQueries.java | 4 ++- .../plan/gathering/domain/PlayerKillTest.java | 8 ++--- .../plan/gathering/domain/SessionTest.java | 4 +-- .../importing/data/ImportBuilderTest.java | 6 ++-- .../src/test/java/utilities/RandomData.java | 8 ++--- .../src/test/java/utilities/TestData.java | 4 +-- 10 files changed, 48 insertions(+), 36 deletions(-) diff --git a/Plan/common/src/main/java/com/djrapitops/plan/delivery/domain/mutators/PlayerKillMutator.java b/Plan/common/src/main/java/com/djrapitops/plan/delivery/domain/mutators/PlayerKillMutator.java index df76a9d41..94b4d011e 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/delivery/domain/mutators/PlayerKillMutator.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/delivery/domain/mutators/PlayerKillMutator.java @@ -47,7 +47,7 @@ public class PlayerKillMutator { Map killMap = new HashMap<>(); killMap.put("date", formatters.secondLong().apply(kill.getDate())); killMap.put("victim", kill.getVictimName().orElse(kill.getVictim().toString())); - killMap.put("killer", kill.getKillerName().orElse("Missing UUID")); // TODO Kills should support killer UUID + killMap.put("killer", kill.getKillerName().orElse(kill.getKiller().toString())); killMap.put("weapon", kill.getWeapon()); return killMap; } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/gathering/domain/PlayerKill.java b/Plan/common/src/main/java/com/djrapitops/plan/gathering/domain/PlayerKill.java index 919dee670..cce0b4b34 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/gathering/domain/PlayerKill.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/gathering/domain/PlayerKill.java @@ -23,13 +23,13 @@ import java.util.Optional; import java.util.UUID; /** - * This class is used to store data about a player kill inside the UserInfo - * object. + * Represents a player vs player kill. * * @author Rsl1122 */ public class PlayerKill implements DateHolder { + private final UUID killer; private final UUID victim; private final String weapon; private final long date; @@ -40,31 +40,32 @@ public class PlayerKill implements DateHolder { /** * Creates a PlayerKill object with given parameters. * + * @param killer UUID of the killer. * @param victim UUID of the victim. * @param weapon Weapon used. * @param date Epoch millisecond at which the kill occurred. */ - public PlayerKill(UUID victim, String weapon, long date) { + public PlayerKill(UUID killer, UUID victim, String weapon, long date) { + this.killer = killer; this.victim = victim; this.weapon = weapon; this.date = date; } - public PlayerKill(UUID victim, String weapon, long date, String victimName) { - this(victim, weapon, date); + public PlayerKill(UUID killer, UUID victim, String weapon, long date, String victimName) { + this(killer, victim, weapon, date); this.victimName = victimName; } - public PlayerKill(UUID victim, String weapon, long date, String victimName, String killerName) { - this(victim, weapon, date, victimName); + public PlayerKill(UUID killer, UUID victim, String weapon, long date, String victimName, String killerName) { + this(killer, victim, weapon, date, victimName); this.killerName = killerName; } - /** - * Get the victim's UUID. - * - * @return UUID of the victim. - */ + public UUID getKiller() { + return killer; + } + public UUID getVictim() { return victim; } @@ -97,25 +98,27 @@ public class PlayerKill implements DateHolder { if (o == null || getClass() != o.getClass()) return false; PlayerKill that = (PlayerKill) o; return date == that.date && + Objects.equals(killer, that.killer) && Objects.equals(victim, that.victim) && Objects.equals(weapon, that.weapon); } @Override public int hashCode() { - return Objects.hash(victim, date, weapon); + return Objects.hash(killer, victim, date, weapon); } @Override public String toString() { return "PlayerKill{" + + "killer=" + killer + ", " + "victim=" + victim + ", " + "date=" + date + ", " + "weapon='" + weapon + "'}"; } public boolean isSelfKill() { - return getVictimName().map(v -> v.equals(killerName)).orElse(false); + return killer.equals(victim); } public boolean isNotSelfKill() { diff --git a/Plan/common/src/main/java/com/djrapitops/plan/processing/processors/player/PlayerKillProcessor.java b/Plan/common/src/main/java/com/djrapitops/plan/processing/processors/player/PlayerKillProcessor.java index 2b832e963..5c9d83207 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/processing/processors/player/PlayerKillProcessor.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/processing/processors/player/PlayerKillProcessor.java @@ -62,6 +62,6 @@ public class PlayerKillProcessor implements CriticalRunnable { } Session session = cachedSession.get(); - session.playerKilled(new PlayerKill(victim, weaponName, time)); + session.playerKilled(new PlayerKill(killer, victim, weaponName, time)); } } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/queries/objects/KillQueries.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/queries/objects/KillQueries.java index d436f2608..19a364722 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/queries/objects/KillQueries.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/queries/objects/KillQueries.java @@ -46,7 +46,9 @@ public class KillQueries { } public static Query> fetchPlayerKillsOnServer(UUID serverUUID, int limit) { - String sql = SELECT + KillsTable.VICTIM_UUID + ", " + + String sql = SELECT + + KillsTable.KILLER_UUID + ", " + + KillsTable.VICTIM_UUID + ", " + "v." + UsersTable.USER_NAME + " as victim_name, " + "k." + UsersTable.USER_NAME + " as killer_name," + KillsTable.DATE + ", " + @@ -76,7 +78,9 @@ public class KillQueries { } public static Query> fetchPlayerKillsOfPlayer(UUID playerUUID) { - String sql = SELECT + KillsTable.VICTIM_UUID + ", " + + String sql = SELECT + + KillsTable.KILLER_UUID + ", " + + KillsTable.VICTIM_UUID + ", " + "v." + UsersTable.USER_NAME + " as victim_name, " + "k." + UsersTable.USER_NAME + " as killer_name," + KillsTable.DATE + ", " + @@ -105,7 +109,9 @@ public class KillQueries { } public static Query> fetchPlayerDeathsOfPlayer(UUID playerUUID) { - String sql = SELECT + KillsTable.VICTIM_UUID + ", " + + String sql = SELECT + + KillsTable.KILLER_UUID + ", " + + KillsTable.VICTIM_UUID + ", " + "v." + UsersTable.USER_NAME + " as victim_name, " + "k." + UsersTable.USER_NAME + " as killer_name," + KillsTable.DATE + ", " + @@ -137,10 +143,11 @@ public class KillQueries { String victimName = set.getString("victim_name"); String killerName = set.getString("killer_name"); if (victimName != null && killerName != null) { + UUID killer = UUID.fromString(set.getString(KillsTable.KILLER_UUID)); UUID victim = UUID.fromString(set.getString(KillsTable.VICTIM_UUID)); long date = set.getLong(KillsTable.DATE); String weapon = set.getString(KillsTable.WEAPON); - return Optional.of(new PlayerKill(victim, weapon, date, victimName, killerName)); + return Optional.of(new PlayerKill(killer, victim, weapon, date, victimName, killerName)); } return Optional.empty(); } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/queries/objects/SessionQueries.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/queries/objects/SessionQueries.java index 50bd18035..eea629544 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/queries/objects/SessionQueries.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/queries/objects/SessionQueries.java @@ -67,6 +67,7 @@ public class SessionQueries { WorldTimesTable.ADVENTURE + ',' + WorldTimesTable.SPECTATOR + ',' + WorldTable.NAME + ',' + + KillsTable.KILLER_UUID + ',' + KillsTable.VICTIM_UUID + ',' + "v." + UsersTable.USER_NAME + " as victim_name, " + KillsTable.DATE + ',' + @@ -193,11 +194,12 @@ public class SessionQueries { String victimName = set.getString("victim_name"); if (victimName != null) { + UUID killer = UUID.fromString(set.getString(KillsTable.KILLER_UUID)); UUID victim = UUID.fromString(set.getString(KillsTable.VICTIM_UUID)); long date = set.getLong(KillsTable.DATE); String weapon = set.getString(KillsTable.WEAPON); List playerKills = session.getPlayerKills(); - PlayerKill newKill = new PlayerKill(victim, weapon, date, victimName); + PlayerKill newKill = new PlayerKill(killer, victim, weapon, date, victimName); if (!playerKills.contains(newKill)) { playerKills.add(newKill); } diff --git a/Plan/common/src/test/java/com/djrapitops/plan/gathering/domain/PlayerKillTest.java b/Plan/common/src/test/java/com/djrapitops/plan/gathering/domain/PlayerKillTest.java index 8cc98b29c..f7a9bb1da 100644 --- a/Plan/common/src/test/java/com/djrapitops/plan/gathering/domain/PlayerKillTest.java +++ b/Plan/common/src/test/java/com/djrapitops/plan/gathering/domain/PlayerKillTest.java @@ -31,9 +31,9 @@ import static org.junit.jupiter.api.Assertions.assertFalse; */ class PlayerKillTest { - private String weapon = RandomData.randomString(10); - private UUID testUUID = UUID.randomUUID(); - private PlayerKill underTest = new PlayerKill(testUUID, weapon, 100L); + private final String weapon = RandomData.randomString(10); + private final UUID testUUID = UUID.randomUUID(); + private final PlayerKill underTest = new PlayerKill(testUUID, testUUID, weapon, 100L); @Test void victimUUIDIsReturned() { @@ -58,7 +58,7 @@ class PlayerKillTest { @Test void victimFound() { String expectedName = "Test Victim"; - PlayerKill underTest = new PlayerKill(testUUID, weapon, 100L, expectedName); + PlayerKill underTest = new PlayerKill(testUUID, testUUID, weapon, 100L, expectedName); assertEquals("Test Victim", underTest.getVictimName().orElse("Unknown")); } } diff --git a/Plan/common/src/test/java/com/djrapitops/plan/gathering/domain/SessionTest.java b/Plan/common/src/test/java/com/djrapitops/plan/gathering/domain/SessionTest.java index 2afb68f5a..59698341f 100644 --- a/Plan/common/src/test/java/com/djrapitops/plan/gathering/domain/SessionTest.java +++ b/Plan/common/src/test/java/com/djrapitops/plan/gathering/domain/SessionTest.java @@ -68,7 +68,7 @@ class SessionTest { List before = beforeOptional.get(); assertTrue(before.isEmpty()); - session.playerKilled(new PlayerKill(TestConstants.PLAYER_TWO_UUID, "Weapon", System.currentTimeMillis())); + session.playerKilled(new PlayerKill(TestConstants.PLAYER_ONE_UUID, TestConstants.PLAYER_TWO_UUID, "Weapon", System.currentTimeMillis())); Optional> afterOptional = session.getValue(SessionKeys.PLAYER_KILLS); assertTrue(afterOptional.isPresent()); @@ -82,7 +82,7 @@ class SessionTest { void killsAreAdded2() { Session session = new Session(null, serverUUID, System.currentTimeMillis(), "", ""); - session.playerKilled(new PlayerKill(TestConstants.PLAYER_TWO_UUID, "Weapon", System.currentTimeMillis())); + session.playerKilled(new PlayerKill(TestConstants.PLAYER_ONE_UUID, TestConstants.PLAYER_TWO_UUID, "Weapon", System.currentTimeMillis())); Optional> afterOptional = session.getValue(SessionKeys.PLAYER_KILLS); assertTrue(afterOptional.isPresent()); diff --git a/Plan/common/src/test/java/com/djrapitops/plan/gathering/importing/data/ImportBuilderTest.java b/Plan/common/src/test/java/com/djrapitops/plan/gathering/importing/data/ImportBuilderTest.java index f9e546380..9e8ea7d1d 100644 --- a/Plan/common/src/test/java/com/djrapitops/plan/gathering/importing/data/ImportBuilderTest.java +++ b/Plan/common/src/test/java/com/djrapitops/plan/gathering/importing/data/ImportBuilderTest.java @@ -38,8 +38,8 @@ import static org.junit.jupiter.api.Assertions.*; */ class ImportBuilderTest { - private int randomInt = RandomData.randomInt(0, 10); - private String randomString = RandomData.randomString(randomInt); + private final int randomInt = RandomData.randomInt(0, 10); + private final String randomString = RandomData.randomString(randomInt); @Test void emptyServerBuilderInitializesCollections() { @@ -100,7 +100,7 @@ class ImportBuilderTest { UserImportData.UserImportDataBuilder builder = UserImportData.builder(TestConstants.SERVER_UUID); UUID uuid = UUID.randomUUID(); - PlayerKill playerKill = new PlayerKill(uuid, randomString, 1); + PlayerKill playerKill = new PlayerKill(uuid, uuid, randomString, 1); GMTimes gmTimes = new GMTimes(randomString, randomInt); UserImportData data = builder.uuid(uuid) diff --git a/Plan/common/src/test/java/utilities/RandomData.java b/Plan/common/src/test/java/utilities/RandomData.java index 77bd2aa90..8469ca045 100644 --- a/Plan/common/src/test/java/utilities/RandomData.java +++ b/Plan/common/src/test/java/utilities/RandomData.java @@ -109,7 +109,7 @@ public class RandomData { session.endSession(RandomData.randomTimeAfter(session.getDate())); session.setWorldTimes(RandomData.randomWorldTimes(worlds)); if (uuids.length >= 2) { - session.setPlayerKills(RandomData.randomKills(pickAtRandom(Arrays.copyOfRange(uuids, 1, uuids.length)))); + session.setPlayerKills(RandomData.randomKills(uuids[0], pickAtRandom(Arrays.copyOfRange(uuids, 1, uuids.length)))); } return session; } @@ -122,7 +122,7 @@ public class RandomData { Session session = new Session(uuids[0], serverUUID, RandomData.randomTime(), pickAtRandom(worlds), randomGameMode()); session.setWorldTimes(RandomData.randomWorldTimes(worlds)); if (uuids.length >= 2) { - session.setPlayerKills(RandomData.randomKills(pickAtRandom(Arrays.copyOfRange(uuids, 1, uuids.length)))); + session.setPlayerKills(RandomData.randomKills(uuids[0], pickAtRandom(Arrays.copyOfRange(uuids, 1, uuids.length)))); } return session; } @@ -151,11 +151,11 @@ public class RandomData { return new WorldTimes(times); } - public static List randomKills(UUID... victimUUIDs) { + public static List randomKills(UUID killer, UUID... victimUUIDs) { if (victimUUIDs == null || victimUUIDs.length == 1 && victimUUIDs[0] == null) return Collections.emptyList(); return pickMultiple(randomInt(3, 15), () -> new PlayerKill( - pickAtRandom(victimUUIDs), + killer, pickAtRandom(victimUUIDs), randomString(randomInt(10, KillsTable.WEAPON_COLUMN_LENGTH)), randomTime() )); diff --git a/Plan/common/src/test/java/utilities/TestData.java b/Plan/common/src/test/java/utilities/TestData.java index 354ebf3dd..ffb244576 100644 --- a/Plan/common/src/test/java/utilities/TestData.java +++ b/Plan/common/src/test/java/utilities/TestData.java @@ -78,8 +78,8 @@ public class TestData { Session sessionOne = new Session(uuid, serverUUID, playerFirstJoin, serverWorldNames[0], gms[0]); UUID otherUUID = uuid.equals(playerUUID) ? player2UUID : playerUUID; - sessionOne.playerKilled(new PlayerKill(otherUUID, "Iron Sword", 1234750L)); - sessionOne.playerKilled(new PlayerKill(otherUUID, "Gold Sword", 1234800L)); + sessionOne.playerKilled(new PlayerKill(uuid, otherUUID, "Iron Sword", 1234750L)); + sessionOne.playerKilled(new PlayerKill(uuid, otherUUID, "Gold Sword", 1234800L)); sessionOne.endSession(1235000L); // Length 500ms sessions.add(sessionOne); From 68ce65b4d5ed51d159e0f8af4faf280911f29db5 Mon Sep 17 00:00:00 2001 From: Risto Lahtela <24460436+Rsl1122@users.noreply.github.com> Date: Thu, 19 Nov 2020 17:05:44 +0200 Subject: [PATCH 06/20] Moved some abstraction of ImporterSystem to Dagger Removes 2 unnecessary classes --- .../importing/BukkitImportSystem.java | 45 ------------------- .../plan/modules/bukkit/BukkitPlanModule.java | 7 +++ .../bukkit/BukkitSuperClassBindingModule.java | 5 --- .../importing/EmptyImportSystem.java | 39 ---------------- .../gathering/importing/ImportSystem.java | 20 +++++---- .../modules/ProxySuperClassBindingModule.java | 5 --- .../modules/SystemObjectProvidingModule.java | 10 +++++ .../utilities/dagger/PlanPluginModule.java | 5 --- .../nukkit/NukkitSuperClassBindingModule.java | 5 --- .../sponge/SpongeSuperClassBindingModule.java | 5 --- 10 files changed, 29 insertions(+), 117 deletions(-) delete mode 100644 Plan/bukkit/src/main/java/com/djrapitops/plan/gathering/importing/BukkitImportSystem.java delete mode 100644 Plan/common/src/main/java/com/djrapitops/plan/gathering/importing/EmptyImportSystem.java diff --git a/Plan/bukkit/src/main/java/com/djrapitops/plan/gathering/importing/BukkitImportSystem.java b/Plan/bukkit/src/main/java/com/djrapitops/plan/gathering/importing/BukkitImportSystem.java deleted file mode 100644 index 8affb2525..000000000 --- a/Plan/bukkit/src/main/java/com/djrapitops/plan/gathering/importing/BukkitImportSystem.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * This file is part of Player Analytics (Plan). - * - * Plan is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License v3 as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Plan is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Plan. If not, see . - */ -package com.djrapitops.plan.gathering.importing; - -import com.djrapitops.plan.gathering.importing.importers.OfflinePlayerImporter; - -import javax.inject.Inject; -import javax.inject.Singleton; - -/** - * ImportSystem implementation for Bukkit. - * - * @author Rsl1122 - */ -@Singleton -public class BukkitImportSystem extends ImportSystem { - - private final OfflinePlayerImporter offlinePlayerImporter; - - @Inject - public BukkitImportSystem( - OfflinePlayerImporter offlinePlayerImporter - ) { - this.offlinePlayerImporter = offlinePlayerImporter; - } - - @Override - void registerImporters() { - registerImporter(offlinePlayerImporter); - } -} \ No newline at end of file diff --git a/Plan/bukkit/src/main/java/com/djrapitops/plan/modules/bukkit/BukkitPlanModule.java b/Plan/bukkit/src/main/java/com/djrapitops/plan/modules/bukkit/BukkitPlanModule.java index 29b447418..7143b0105 100644 --- a/Plan/bukkit/src/main/java/com/djrapitops/plan/modules/bukkit/BukkitPlanModule.java +++ b/Plan/bukkit/src/main/java/com/djrapitops/plan/modules/bukkit/BukkitPlanModule.java @@ -18,8 +18,11 @@ package com.djrapitops.plan.modules.bukkit; import com.djrapitops.plan.Plan; import com.djrapitops.plan.PlanPlugin; +import com.djrapitops.plan.gathering.importing.importers.Importer; +import com.djrapitops.plan.gathering.importing.importers.OfflinePlayerImporter; import dagger.Binds; import dagger.Module; +import dagger.multibindings.IntoSet; /** * Dagger module for binding Plan instance. @@ -31,4 +34,8 @@ public interface BukkitPlanModule { @Binds PlanPlugin bindPlanPlugin(Plan plugin); + + @Binds + @IntoSet + Importer bindOfflinePlayerImporter(OfflinePlayerImporter importer); } \ No newline at end of file diff --git a/Plan/bukkit/src/main/java/com/djrapitops/plan/modules/bukkit/BukkitSuperClassBindingModule.java b/Plan/bukkit/src/main/java/com/djrapitops/plan/modules/bukkit/BukkitSuperClassBindingModule.java index 722d8cb08..152833228 100644 --- a/Plan/bukkit/src/main/java/com/djrapitops/plan/modules/bukkit/BukkitSuperClassBindingModule.java +++ b/Plan/bukkit/src/main/java/com/djrapitops/plan/modules/bukkit/BukkitSuperClassBindingModule.java @@ -22,8 +22,6 @@ import com.djrapitops.plan.TaskSystem; import com.djrapitops.plan.gathering.BukkitSensor; import com.djrapitops.plan.gathering.ServerSensor; import com.djrapitops.plan.gathering.ServerShutdownSave; -import com.djrapitops.plan.gathering.importing.BukkitImportSystem; -import com.djrapitops.plan.gathering.importing.ImportSystem; import com.djrapitops.plan.gathering.listeners.BukkitListenerSystem; import com.djrapitops.plan.gathering.listeners.ListenerSystem; import com.djrapitops.plan.identification.ServerInfo; @@ -59,9 +57,6 @@ public interface BukkitSuperClassBindingModule { @Binds ListenerSystem bindListenerSystem(BukkitListenerSystem listenerSystem); - @Binds - ImportSystem bindImportSystem(BukkitImportSystem importSystem); - @Binds ServerShutdownSave bindServerShutdownSave(BukkitServerShutdownSave shutdownSave); diff --git a/Plan/common/src/main/java/com/djrapitops/plan/gathering/importing/EmptyImportSystem.java b/Plan/common/src/main/java/com/djrapitops/plan/gathering/importing/EmptyImportSystem.java deleted file mode 100644 index 8f2595010..000000000 --- a/Plan/common/src/main/java/com/djrapitops/plan/gathering/importing/EmptyImportSystem.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * This file is part of Player Analytics (Plan). - * - * Plan is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License v3 as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Plan is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Plan. If not, see . - */ -package com.djrapitops.plan.gathering.importing; - -import javax.inject.Inject; -import javax.inject.Singleton; - -/** - * Placeholder for a ImportSystem. - * - * @author Rsl1122 - */ -@Singleton -public class EmptyImportSystem extends ImportSystem { - - @Inject - public EmptyImportSystem() { - // Inject constructor required for dagger - } - - @Override - void registerImporters() { - // No importers to register. - } -} \ No newline at end of file diff --git a/Plan/common/src/main/java/com/djrapitops/plan/gathering/importing/ImportSystem.java b/Plan/common/src/main/java/com/djrapitops/plan/gathering/importing/ImportSystem.java index 56403e50e..63ffee6f3 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/gathering/importing/ImportSystem.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/gathering/importing/ImportSystem.java @@ -20,30 +20,34 @@ import com.djrapitops.plan.SubSystem; import com.djrapitops.plan.gathering.importing.importers.Importer; import com.djrapitops.plugin.utilities.Verify; +import javax.inject.Inject; +import javax.inject.Singleton; import java.util.*; /** * Abstract representation of an ImportSystem. - *

- * TODO it is possible to remove the abstract part of this class by binding Importers to a Map with Dagger * * @author Rsl1122 */ -public abstract class ImportSystem implements SubSystem { +@Singleton +public class ImportSystem implements SubSystem { protected final Map importers; - protected ImportSystem() { - importers = new HashMap<>(); + @Inject + protected ImportSystem(Set importers) { + this.importers = new HashMap<>(); + for (Importer importer : importers) { + this.importers.put(importer.getName(), importer); + } + } @Override public void enable() { - registerImporters(); + // Nothing to do } - abstract void registerImporters(); - public void registerImporter(Importer importer) { Verify.nullCheck(importer, () -> new IllegalArgumentException("Importer cannot be null")); diff --git a/Plan/common/src/main/java/com/djrapitops/plan/modules/ProxySuperClassBindingModule.java b/Plan/common/src/main/java/com/djrapitops/plan/modules/ProxySuperClassBindingModule.java index d203865b2..ca5831311 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/modules/ProxySuperClassBindingModule.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/modules/ProxySuperClassBindingModule.java @@ -17,8 +17,6 @@ package com.djrapitops.plan.modules; import com.djrapitops.plan.gathering.ServerSensor; -import com.djrapitops.plan.gathering.importing.EmptyImportSystem; -import com.djrapitops.plan.gathering.importing.ImportSystem; import com.djrapitops.plan.settings.ConfigSystem; import com.djrapitops.plan.settings.ProxyConfigSystem; import com.djrapitops.plan.storage.database.DBSystem; @@ -40,9 +38,6 @@ public interface ProxySuperClassBindingModule { @Binds ConfigSystem bindConfigSystem(ProxyConfigSystem configSystem); - @Binds - ImportSystem bindImportSystem(EmptyImportSystem emptyImportSystem); - @Binds ServerSensor bindServerSensor(ServerSensor sensor); diff --git a/Plan/common/src/main/java/com/djrapitops/plan/modules/SystemObjectProvidingModule.java b/Plan/common/src/main/java/com/djrapitops/plan/modules/SystemObjectProvidingModule.java index 9701a3bc2..2bc9faef4 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/modules/SystemObjectProvidingModule.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/modules/SystemObjectProvidingModule.java @@ -19,6 +19,7 @@ package com.djrapitops.plan.modules; import com.djrapitops.plan.DataService; import com.djrapitops.plan.DataSvc; import com.djrapitops.plan.PlanPlugin; +import com.djrapitops.plan.gathering.importing.importers.Importer; import com.djrapitops.plan.settings.config.ExtensionSettings; import com.djrapitops.plan.settings.config.PlanConfig; import com.djrapitops.plan.settings.locale.Locale; @@ -28,10 +29,13 @@ import com.djrapitops.plan.utilities.logging.ErrorLogger; import com.djrapitops.plan.utilities.logging.PluginErrorLogger; import dagger.Module; import dagger.Provides; +import dagger.multibindings.ElementsIntoSet; import javax.inject.Named; import javax.inject.Singleton; import java.io.File; +import java.util.HashSet; +import java.util.Set; import java.util.function.Predicate; /** @@ -42,6 +46,12 @@ import java.util.function.Predicate; @Module public class SystemObjectProvidingModule { + @Provides + @ElementsIntoSet + Set emptyImporterSet() { + return new HashSet<>(); + } + @Provides @Singleton Locale provideLocale(LocaleSystem localeSystem) { diff --git a/Plan/common/src/test/java/utilities/dagger/PlanPluginModule.java b/Plan/common/src/test/java/utilities/dagger/PlanPluginModule.java index 64750ebe7..6d3bc6d58 100644 --- a/Plan/common/src/test/java/utilities/dagger/PlanPluginModule.java +++ b/Plan/common/src/test/java/utilities/dagger/PlanPluginModule.java @@ -16,8 +16,6 @@ */ package utilities.dagger; -import com.djrapitops.plan.gathering.importing.EmptyImportSystem; -import com.djrapitops.plan.gathering.importing.ImportSystem; import com.djrapitops.plan.identification.ServerInfo; import com.djrapitops.plan.identification.ServerServerInfo; import com.djrapitops.plan.settings.BukkitConfigSystem; @@ -33,9 +31,6 @@ import dagger.Module; @Module public interface PlanPluginModule { - @Binds - ImportSystem bindImportSystem(EmptyImportSystem emptyImportSystem); - @Binds ConfigSystem bindBukkitConfigSystem(BukkitConfigSystem bukkitConfigSystem); diff --git a/Plan/nukkit/src/main/java/com/djrapitops/plan/modules/nukkit/NukkitSuperClassBindingModule.java b/Plan/nukkit/src/main/java/com/djrapitops/plan/modules/nukkit/NukkitSuperClassBindingModule.java index 271fc312f..1dcacb2b6 100644 --- a/Plan/nukkit/src/main/java/com/djrapitops/plan/modules/nukkit/NukkitSuperClassBindingModule.java +++ b/Plan/nukkit/src/main/java/com/djrapitops/plan/modules/nukkit/NukkitSuperClassBindingModule.java @@ -23,8 +23,6 @@ import com.djrapitops.plan.TaskSystem; import com.djrapitops.plan.gathering.NukkitSensor; import com.djrapitops.plan.gathering.ServerSensor; import com.djrapitops.plan.gathering.ServerShutdownSave; -import com.djrapitops.plan.gathering.importing.EmptyImportSystem; -import com.djrapitops.plan.gathering.importing.ImportSystem; import com.djrapitops.plan.gathering.listeners.ListenerSystem; import com.djrapitops.plan.gathering.listeners.NukkitListenerSystem; import com.djrapitops.plan.identification.ServerInfo; @@ -59,9 +57,6 @@ public interface NukkitSuperClassBindingModule { @Binds ListenerSystem bindListenerSystem(NukkitListenerSystem listenerSystem); - @Binds - ImportSystem bindImportSystem(EmptyImportSystem emptyImportSystem); - @Binds ServerShutdownSave bindServerShutdownSave(NukkitServerShutdownSave shutdownSave); diff --git a/Plan/sponge/src/main/java/com/djrapitops/plan/modules/sponge/SpongeSuperClassBindingModule.java b/Plan/sponge/src/main/java/com/djrapitops/plan/modules/sponge/SpongeSuperClassBindingModule.java index c30f79842..79e438484 100644 --- a/Plan/sponge/src/main/java/com/djrapitops/plan/modules/sponge/SpongeSuperClassBindingModule.java +++ b/Plan/sponge/src/main/java/com/djrapitops/plan/modules/sponge/SpongeSuperClassBindingModule.java @@ -22,8 +22,6 @@ import com.djrapitops.plan.TaskSystem; import com.djrapitops.plan.gathering.ServerSensor; import com.djrapitops.plan.gathering.ServerShutdownSave; import com.djrapitops.plan.gathering.SpongeSensor; -import com.djrapitops.plan.gathering.importing.EmptyImportSystem; -import com.djrapitops.plan.gathering.importing.ImportSystem; import com.djrapitops.plan.gathering.listeners.ListenerSystem; import com.djrapitops.plan.gathering.listeners.SpongeListenerSystem; import com.djrapitops.plan.identification.ServerInfo; @@ -64,9 +62,6 @@ public interface SpongeSuperClassBindingModule { @Binds ListenerSystem bindListenerSystem(SpongeListenerSystem listenerSystem); - @Binds - ImportSystem bindImportSystem(EmptyImportSystem emptyImportSystem); - @Binds ServerShutdownSave bindServerShutdownSave(SpongeServerShutdownSave shutdownSave); From c8fb39ada5c34c8626a44f01616bbb43c63063b1 Mon Sep 17 00:00:00 2001 From: Risto Lahtela <24460436+Rsl1122@users.noreply.github.com> Date: Thu, 19 Nov 2020 18:16:11 +0200 Subject: [PATCH 07/20] Replaced TaskSystem implementations with dagger modules - Removes the need for duplicate code in 5 places in charge of registering the tasks for different platforms, as all the delays were the same too. Affects issues: - Close #1387 --- .../com/djrapitops/plan/BukkitTaskSystem.java | 154 ------------------ .../main/java/com/djrapitops/plan/Plan.java | 15 +- .../djrapitops/plan/PlanBukkitComponent.java | 4 +- .../gathering/timed/BukkitPingCounter.java | 32 +++- .../bukkit/BukkitSuperClassBindingModule.java | 5 - .../plan/modules/bukkit/BukkitTaskModule.java | 77 +++++++++ .../com/djrapitops/plan/BungeeTaskSystem.java | 129 --------------- .../java/com/djrapitops/plan/PlanBungee.java | 1 + .../djrapitops/plan/PlanBungeeComponent.java | 8 +- .../gathering/timed/BungeePingCounter.java | 20 ++- .../bungee/BungeeSuperClassBindingModule.java | 5 - .../plan/modules/bungee/BungeeTaskModule.java | 71 ++++++++ .../java/com/djrapitops/plan/PlanPlugin.java | 4 + .../java/com/djrapitops/plan/TaskSystem.java | 37 +++-- .../plan/delivery/export/ExportScheduler.java | 14 +- .../delivery/webserver/cache/JSONCache.java | 12 +- ...k.java => ExtensionServerDataUpdater.java} | 23 ++- .../plan/gathering/ShutdownHook.java | 21 +++ .../gathering/timed/SystemUsageBuffer.java | 23 ++- .../plan/gathering/timed/TPSCounter.java | 14 +- .../network/ServerSettingsManager.java | 11 +- .../plan/settings/upkeep/ConfigStoreTask.java | 14 +- .../upkeep/NetworkConfigStoreTask.java | 19 ++- .../plan/storage/upkeep/DBCleanTask.java | 14 +- .../storage/upkeep/LogsFolderCleanTask.java | 12 +- .../dagger/PluginSuperClassBindingModule.java | 21 ++- .../com/djrapitops/plan/NukkitTaskSystem.java | 151 ----------------- .../java/com/djrapitops/plan/PlanNukkit.java | 17 +- .../djrapitops/plan/PlanNukkitComponent.java | 4 +- .../gathering/timed/NukkitPingCounter.java | 19 ++- .../nukkit/NukkitSuperClassBindingModule.java | 5 - .../plan/modules/nukkit/NukkitTaskModule.java | 77 +++++++++ .../java/com/djrapitops/plan/PlanSponge.java | 18 +- .../djrapitops/plan/PlanSpongeComponent.java | 4 +- .../com/djrapitops/plan/SpongeTaskSystem.java | 149 ----------------- .../gathering/timed/SpongePingCounter.java | 19 ++- .../sponge/SpongeSuperClassBindingModule.java | 5 - .../plan/modules/sponge/SpongeTaskModule.java | 77 +++++++++ .../com/djrapitops/plan/PlanVelocity.java | 3 +- .../plan/PlanVelocityComponent.java | 8 +- .../djrapitops/plan/VelocityTaskSystem.java | 128 --------------- .../gathering/timed/VelocityPingCounter.java | 15 +- .../VelocitySuperClassBindingModule.java | 5 - .../modules/velocity/VelocityTaskModule.java | 71 ++++++++ 44 files changed, 704 insertions(+), 831 deletions(-) delete mode 100644 Plan/bukkit/src/main/java/com/djrapitops/plan/BukkitTaskSystem.java create mode 100644 Plan/bukkit/src/main/java/com/djrapitops/plan/modules/bukkit/BukkitTaskModule.java delete mode 100644 Plan/bungeecord/src/main/java/com/djrapitops/plan/BungeeTaskSystem.java create mode 100644 Plan/bungeecord/src/main/java/com/djrapitops/plan/modules/bungee/BungeeTaskModule.java rename Plan/common/src/main/java/com/djrapitops/plan/extension/{ExtensionServerMethodCallerTask.java => ExtensionServerDataUpdater.java} (56%) delete mode 100644 Plan/nukkit/src/main/java/com/djrapitops/plan/NukkitTaskSystem.java create mode 100644 Plan/nukkit/src/main/java/com/djrapitops/plan/modules/nukkit/NukkitTaskModule.java delete mode 100644 Plan/sponge/src/main/java/com/djrapitops/plan/SpongeTaskSystem.java create mode 100644 Plan/sponge/src/main/java/com/djrapitops/plan/modules/sponge/SpongeTaskModule.java delete mode 100644 Plan/velocity/src/main/java/com/djrapitops/plan/VelocityTaskSystem.java create mode 100644 Plan/velocity/src/main/java/com/djrapitops/plan/modules/velocity/VelocityTaskModule.java diff --git a/Plan/bukkit/src/main/java/com/djrapitops/plan/BukkitTaskSystem.java b/Plan/bukkit/src/main/java/com/djrapitops/plan/BukkitTaskSystem.java deleted file mode 100644 index 7a53499eb..000000000 --- a/Plan/bukkit/src/main/java/com/djrapitops/plan/BukkitTaskSystem.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * This file is part of Player Analytics (Plan). - * - * Plan is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License v3 as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Plan is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Plan. If not, see . - */ -package com.djrapitops.plan; - -import com.djrapitops.plan.delivery.webserver.cache.JSONCache; -import com.djrapitops.plan.extension.ExtensionServerMethodCallerTask; -import com.djrapitops.plan.gathering.ShutdownHook; -import com.djrapitops.plan.gathering.timed.BukkitPingCounter; -import com.djrapitops.plan.gathering.timed.ServerTPSCounter; -import com.djrapitops.plan.gathering.timed.SystemUsageBuffer; -import com.djrapitops.plan.gathering.timed.TPSCounter; -import com.djrapitops.plan.settings.config.PlanConfig; -import com.djrapitops.plan.settings.config.paths.DataGatheringSettings; -import com.djrapitops.plan.settings.config.paths.TimeSettings; -import com.djrapitops.plan.settings.upkeep.ConfigStoreTask; -import com.djrapitops.plan.storage.upkeep.DBCleanTask; -import com.djrapitops.plan.storage.upkeep.LogsFolderCleanTask; -import com.djrapitops.plugin.api.TimeAmount; -import com.djrapitops.plugin.task.RunnableFactory; -import org.bukkit.Bukkit; -import org.bukkit.World; - -import javax.inject.Inject; -import javax.inject.Singleton; -import java.util.concurrent.TimeUnit; - -/** - * TaskSystem responsible for registering tasks for Bukkit. - * - * @author Rsl1122 - */ -@Singleton -public class BukkitTaskSystem extends TaskSystem { - - private final Plan plugin; - private final PlanConfig config; - private final ShutdownHook shutdownHook; - private final JSONCache.CleanTask jsonCacheCleanTask; - private final LogsFolderCleanTask logsFolderCleanTask; - private final BukkitPingCounter pingCounter; - private final ConfigStoreTask configStoreTask; - private final DBCleanTask dbCleanTask; - private final ExtensionServerMethodCallerTask extensionServerMethodCallerTask; - private final TPSCounter tpsCounter; - private final SystemUsageBuffer.RamAndCpuTask ramAndCpuTask; - private final SystemUsageBuffer.DiskTask diskTask; - - @Inject - public BukkitTaskSystem( - Plan plugin, - PlanConfig config, - ShutdownHook shutdownHook, - RunnableFactory runnableFactory, - - ServerTPSCounter tpsCounter, - BukkitPingCounter pingCounter, - ExtensionServerMethodCallerTask extensionServerMethodCallerTask, - - LogsFolderCleanTask logsFolderCleanTask, - ConfigStoreTask configStoreTask, - DBCleanTask dbCleanTask, - JSONCache.CleanTask jsonCacheCleanTask, - SystemUsageBuffer.RamAndCpuTask ramAndCpuTask, - SystemUsageBuffer.DiskTask diskTask - ) { - super(runnableFactory); - this.plugin = plugin; - this.config = config; - this.shutdownHook = shutdownHook; - this.jsonCacheCleanTask = jsonCacheCleanTask; - - this.tpsCounter = tpsCounter; - this.pingCounter = pingCounter; - this.extensionServerMethodCallerTask = extensionServerMethodCallerTask; - - this.logsFolderCleanTask = logsFolderCleanTask; - this.configStoreTask = configStoreTask; - this.dbCleanTask = dbCleanTask; - this.ramAndCpuTask = ramAndCpuTask; - this.diskTask = diskTask; - } - - @Override - public void enable() { - registerTPSCounter(); - registerPingCounter(); - registerExtensionDataGatheringTask(); - registerUpkeepTasks(); - - shutdownHook.register(); - } - - private void registerUpkeepTasks() { - // +40 ticks / 2 seconds so that update check task runs first. - long storeDelay = TimeAmount.toTicks(config.get(TimeSettings.CONFIG_UPDATE_INTERVAL), TimeUnit.MILLISECONDS) + 40; - registerTask(configStoreTask).runTaskLaterAsynchronously(storeDelay); - registerTask(logsFolderCleanTask).runTaskLaterAsynchronously(TimeAmount.toTicks(30L, TimeUnit.SECONDS)); - registerTask(dbCleanTask).runTaskTimerAsynchronously( - TimeAmount.toTicks(20, TimeUnit.SECONDS), - TimeAmount.toTicks(config.get(TimeSettings.CLEAN_DATABASE_PERIOD), TimeUnit.MILLISECONDS) - ); - long minute = TimeAmount.toTicks(1, TimeUnit.MINUTES); - registerTask(jsonCacheCleanTask).runTaskTimerAsynchronously(minute, minute); - } - - private void registerTPSCounter() { - long halfSecondTicks = TimeAmount.toTicks(500L, TimeUnit.MILLISECONDS); - long secondTicks = TimeAmount.toTicks(1L, TimeUnit.SECONDS); - long minuteTicks = TimeAmount.toTicks(1L, TimeUnit.MINUTES); - registerTask(tpsCounter).runTaskTimer(minuteTicks, secondTicks); - registerTask(ramAndCpuTask).runTaskTimerAsynchronously(minuteTicks - halfSecondTicks, secondTicks); - registerTask(diskTask).runTaskTimerAsynchronously(50L * secondTicks, minuteTicks); - } - - private void registerPingCounter() { - try { - Long pingDelay = config.get(TimeSettings.PING_SERVER_ENABLE_DELAY); - if (pingDelay < TimeUnit.HOURS.toMillis(1L) && config.isTrue(DataGatheringSettings.PING)) { - plugin.registerListener(pingCounter); - long startDelay = TimeAmount.toTicks(pingDelay, TimeUnit.MILLISECONDS); - registerTask(pingCounter).runTaskTimer(startDelay, 40L); - } - } catch (ExceptionInInitializerError | NoClassDefFoundError ignore) { - // Running CraftBukkit - } - } - - private void registerExtensionDataGatheringTask() { - long extensionRefreshPeriod = TimeAmount.toTicks(config.get(TimeSettings.EXTENSION_DATA_REFRESH_PERIOD), TimeUnit.MILLISECONDS); - registerTask(extensionServerMethodCallerTask).runTaskTimerAsynchronously( - TimeAmount.toTicks(30, TimeUnit.SECONDS), extensionRefreshPeriod - ); - } - - @Override - public void disable() { - super.disable(); - Bukkit.getScheduler().cancelTasks(plugin); - } -} diff --git a/Plan/bukkit/src/main/java/com/djrapitops/plan/Plan.java b/Plan/bukkit/src/main/java/com/djrapitops/plan/Plan.java index fad7789b6..eb8466a16 100644 --- a/Plan/bukkit/src/main/java/com/djrapitops/plan/Plan.java +++ b/Plan/bukkit/src/main/java/com/djrapitops/plan/Plan.java @@ -120,16 +120,19 @@ public class Plan extends BukkitPlugin implements PlanPlugin { */ @Override public void onDisable() { - if (serverShutdownSave != null) { - serverShutdownSave.performSave(); - } - if (system != null) { - system.disable(); - } + if (serverShutdownSave != null) serverShutdownSave.performSave(); + cancelAllTasks(); + if (system != null) system.disable(); logger.info(locale != null ? locale.getString(PluginLang.DISABLED) : PluginLang.DISABLED.getDefault()); } + @Override + public void cancelAllTasks() { + runnableFactory.cancelAllKnownTasks(); + Bukkit.getScheduler().cancelTasks(this); + } + @Override public String getVersion() { return getDescription().getVersion(); diff --git a/Plan/bukkit/src/main/java/com/djrapitops/plan/PlanBukkitComponent.java b/Plan/bukkit/src/main/java/com/djrapitops/plan/PlanBukkitComponent.java index e512a762d..e9a063d3c 100644 --- a/Plan/bukkit/src/main/java/com/djrapitops/plan/PlanBukkitComponent.java +++ b/Plan/bukkit/src/main/java/com/djrapitops/plan/PlanBukkitComponent.java @@ -26,6 +26,7 @@ import com.djrapitops.plan.modules.SystemObjectProvidingModule; import com.djrapitops.plan.modules.bukkit.BukkitPlanModule; import com.djrapitops.plan.modules.bukkit.BukkitServerPropertiesModule; import com.djrapitops.plan.modules.bukkit.BukkitSuperClassBindingModule; +import com.djrapitops.plan.modules.bukkit.BukkitTaskModule; import dagger.BindsInstance; import dagger.Component; @@ -45,7 +46,8 @@ import javax.inject.Singleton; ServerCommandModule.class, BukkitServerPropertiesModule.class, - BukkitSuperClassBindingModule.class + BukkitSuperClassBindingModule.class, + BukkitTaskModule.class }) public interface PlanBukkitComponent { diff --git a/Plan/bukkit/src/main/java/com/djrapitops/plan/gathering/timed/BukkitPingCounter.java b/Plan/bukkit/src/main/java/com/djrapitops/plan/gathering/timed/BukkitPingCounter.java index e7b81dec8..1c0f04152 100644 --- a/Plan/bukkit/src/main/java/com/djrapitops/plan/gathering/timed/BukkitPingCounter.java +++ b/Plan/bukkit/src/main/java/com/djrapitops/plan/gathering/timed/BukkitPingCounter.java @@ -23,9 +23,12 @@ */ package com.djrapitops.plan.gathering.timed; +import com.djrapitops.plan.Plan; +import com.djrapitops.plan.TaskSystem; import com.djrapitops.plan.delivery.domain.DateObj; import com.djrapitops.plan.identification.ServerInfo; import com.djrapitops.plan.settings.config.PlanConfig; +import com.djrapitops.plan.settings.config.paths.DataGatheringSettings; import com.djrapitops.plan.settings.config.paths.TimeSettings; import com.djrapitops.plan.storage.database.DBSystem; import com.djrapitops.plan.storage.database.transactions.events.PingStoreTransaction; @@ -60,7 +63,7 @@ import java.util.logging.Logger; * @author games647 */ @Singleton -public class BukkitPingCounter extends AbsRunnable implements Listener { +public class BukkitPingCounter extends TaskSystem.Task implements Listener { //the server is pinging the client every 40 Ticks (2 sec) - so check it then //https://github.com/bergerkiller/CraftSource/blob/master/net.minecraft.server/PlayerConnection.java#L178 @@ -70,13 +73,23 @@ public class BukkitPingCounter extends AbsRunnable implements Listener { private static MethodHandle PING_FIELD; private static MethodHandle GET_HANDLE_METHOD; + private final Map>> playerHistory; + + private final Plan plugin; + private final PlanConfig config; + private final DBSystem dbSystem; + private final ServerInfo serverInfo; + private final RunnableFactory runnableFactory; + @Inject public BukkitPingCounter( + Plan plugin, PlanConfig config, DBSystem dbSystem, ServerInfo serverInfo, RunnableFactory runnableFactory ) { + this.plugin = plugin; BukkitPingCounter.loadPingMethodDetails(); this.config = config; this.dbSystem = dbSystem; @@ -85,12 +98,6 @@ public class BukkitPingCounter extends AbsRunnable implements Listener { playerHistory = new HashMap<>(); } - private final Map>> playerHistory; - - private final PlanConfig config; - private final DBSystem dbSystem; - private final ServerInfo serverInfo; - private final RunnableFactory runnableFactory; private static void loadPingMethodDetails() { PING_METHOD_AVAILABLE = isPingMethodAvailable(); @@ -135,6 +142,17 @@ public class BukkitPingCounter extends AbsRunnable implements Listener { } } + @Override + public void register(RunnableFactory runnableFactory) { + Long startDelay = config.get(TimeSettings.PING_SERVER_ENABLE_DELAY); + if (startDelay < TimeUnit.HOURS.toMillis(1L) && config.isTrue(DataGatheringSettings.PING)) { + plugin.registerListener(this); + long delay = TimeAmount.toTicks(startDelay, TimeUnit.MILLISECONDS); + long period = 40L; + runnableFactory.create(null, this).runTaskTimer(delay, period); + } + } + @Override public void run() { long time = System.currentTimeMillis(); diff --git a/Plan/bukkit/src/main/java/com/djrapitops/plan/modules/bukkit/BukkitSuperClassBindingModule.java b/Plan/bukkit/src/main/java/com/djrapitops/plan/modules/bukkit/BukkitSuperClassBindingModule.java index 152833228..f6e9cba8e 100644 --- a/Plan/bukkit/src/main/java/com/djrapitops/plan/modules/bukkit/BukkitSuperClassBindingModule.java +++ b/Plan/bukkit/src/main/java/com/djrapitops/plan/modules/bukkit/BukkitSuperClassBindingModule.java @@ -17,8 +17,6 @@ package com.djrapitops.plan.modules.bukkit; import com.djrapitops.plan.BukkitServerShutdownSave; -import com.djrapitops.plan.BukkitTaskSystem; -import com.djrapitops.plan.TaskSystem; import com.djrapitops.plan.gathering.BukkitSensor; import com.djrapitops.plan.gathering.ServerSensor; import com.djrapitops.plan.gathering.ServerShutdownSave; @@ -51,9 +49,6 @@ public interface BukkitSuperClassBindingModule { @Binds ConfigSystem bindConfigSystem(BukkitConfigSystem configSystem); - @Binds - TaskSystem bindTaskSystem(BukkitTaskSystem taskSystem); - @Binds ListenerSystem bindListenerSystem(BukkitListenerSystem listenerSystem); diff --git a/Plan/bukkit/src/main/java/com/djrapitops/plan/modules/bukkit/BukkitTaskModule.java b/Plan/bukkit/src/main/java/com/djrapitops/plan/modules/bukkit/BukkitTaskModule.java new file mode 100644 index 000000000..cbcd6b9e4 --- /dev/null +++ b/Plan/bukkit/src/main/java/com/djrapitops/plan/modules/bukkit/BukkitTaskModule.java @@ -0,0 +1,77 @@ +/* + * This file is part of Player Analytics (Plan). + * + * Plan is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License v3 as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Plan is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Plan. If not, see . + */ +package com.djrapitops.plan.modules.bukkit; + +import com.djrapitops.plan.TaskSystem; +import com.djrapitops.plan.delivery.webserver.cache.JSONCache; +import com.djrapitops.plan.extension.ExtensionServerDataUpdater; +import com.djrapitops.plan.gathering.ShutdownHook; +import com.djrapitops.plan.gathering.timed.BukkitPingCounter; +import com.djrapitops.plan.gathering.timed.ServerTPSCounter; +import com.djrapitops.plan.gathering.timed.SystemUsageBuffer; +import com.djrapitops.plan.settings.upkeep.ConfigStoreTask; +import com.djrapitops.plan.storage.upkeep.DBCleanTask; +import com.djrapitops.plan.storage.upkeep.LogsFolderCleanTask; +import dagger.Binds; +import dagger.Module; +import dagger.multibindings.IntoSet; +import org.bukkit.World; + +@Module +public interface BukkitTaskModule { + + @Binds + @IntoSet + TaskSystem.Task bindTPSCounter(ServerTPSCounter tpsCounter); + + @Binds + @IntoSet + TaskSystem.Task bindPingCounter(BukkitPingCounter pingCounter); + + @Binds + @IntoSet + TaskSystem.Task bindExtensionServerDataUpdater(ExtensionServerDataUpdater extensionServerDataUpdater); + + @Binds + @IntoSet + TaskSystem.Task bindLogCleanTask(LogsFolderCleanTask logsFolderCleanTask); + + @Binds + @IntoSet + TaskSystem.Task bindConfigStoreTask(ConfigStoreTask configStoreTask); + + @Binds + @IntoSet + TaskSystem.Task bindDBCleanTask(DBCleanTask cleanTask); + + @Binds + @IntoSet + TaskSystem.Task bindJSONCacheCleanTask(JSONCache.CleanTask cleanTask); + + @Binds + @IntoSet + TaskSystem.Task bindRamAndCpuTask(SystemUsageBuffer.RamAndCpuTask ramAndCpuTask); + + @Binds + @IntoSet + TaskSystem.Task bindDiskTask(SystemUsageBuffer.DiskTask diskTask); + + @Binds + @IntoSet + TaskSystem.Task bindShutdownHookRegistration(ShutdownHook.Registrar registrar); + +} diff --git a/Plan/bungeecord/src/main/java/com/djrapitops/plan/BungeeTaskSystem.java b/Plan/bungeecord/src/main/java/com/djrapitops/plan/BungeeTaskSystem.java deleted file mode 100644 index fae823ddc..000000000 --- a/Plan/bungeecord/src/main/java/com/djrapitops/plan/BungeeTaskSystem.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * This file is part of Player Analytics (Plan). - * - * Plan is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License v3 as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Plan is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Plan. If not, see . - */ -package com.djrapitops.plan; - -import com.djrapitops.plan.delivery.webserver.cache.JSONCache; -import com.djrapitops.plan.extension.ExtensionServerMethodCallerTask; -import com.djrapitops.plan.gathering.timed.BungeePingCounter; -import com.djrapitops.plan.gathering.timed.ProxyTPSCounter; -import com.djrapitops.plan.gathering.timed.SystemUsageBuffer; -import com.djrapitops.plan.gathering.timed.TPSCounter; -import com.djrapitops.plan.settings.config.PlanConfig; -import com.djrapitops.plan.settings.config.paths.DataGatheringSettings; -import com.djrapitops.plan.settings.config.paths.TimeSettings; -import com.djrapitops.plan.settings.upkeep.NetworkConfigStoreTask; -import com.djrapitops.plan.storage.upkeep.DBCleanTask; -import com.djrapitops.plan.storage.upkeep.LogsFolderCleanTask; -import com.djrapitops.plugin.api.TimeAmount; -import com.djrapitops.plugin.task.RunnableFactory; - -import javax.inject.Inject; -import javax.inject.Singleton; -import java.util.concurrent.TimeUnit; - -/** - * TaskSystem responsible for registering tasks for Bungee. - * - * @author Rsl1122 - */ -@Singleton -public class BungeeTaskSystem extends TaskSystem { - - private final PlanBungee plugin; - private final PlanConfig config; - private final TPSCounter tpsCounter; - private final BungeePingCounter pingCounter; - private final LogsFolderCleanTask logsFolderCleanTask; - private final NetworkConfigStoreTask networkConfigStoreTask; - private final DBCleanTask dbCleanTask; - private final JSONCache.CleanTask jsonCacheCleanTask; - private final ExtensionServerMethodCallerTask extensionServerMethodCallerTask; - private final SystemUsageBuffer.RamAndCpuTask ramAndCpuTask; - private final SystemUsageBuffer.DiskTask diskTask; - - @Inject - public BungeeTaskSystem( - PlanBungee plugin, - PlanConfig config, - RunnableFactory runnableFactory, - ProxyTPSCounter tpsCounter, - BungeePingCounter pingCounter, - LogsFolderCleanTask logsFolderCleanTask, - NetworkConfigStoreTask networkConfigStoreTask, - DBCleanTask dbCleanTask, - JSONCache.CleanTask jsonCacheCleanTask, - ExtensionServerMethodCallerTask extensionServerMethodCallerTask, - SystemUsageBuffer.RamAndCpuTask ramAndCpuTask, - SystemUsageBuffer.DiskTask diskTask - ) { - super(runnableFactory); - this.plugin = plugin; - this.config = config; - this.tpsCounter = tpsCounter; - - this.pingCounter = pingCounter; - this.logsFolderCleanTask = logsFolderCleanTask; - this.networkConfigStoreTask = networkConfigStoreTask; - this.dbCleanTask = dbCleanTask; - this.jsonCacheCleanTask = jsonCacheCleanTask; - this.extensionServerMethodCallerTask = extensionServerMethodCallerTask; - this.ramAndCpuTask = ramAndCpuTask; - this.diskTask = diskTask; - } - - @Override - public void enable() { - registerTasks(); - } - - private void registerTPSCounter() { - long halfSecondTicks = TimeAmount.toTicks(500L, TimeUnit.MILLISECONDS); - long secondTicks = TimeAmount.toTicks(1L, TimeUnit.SECONDS); - long minuteTicks = TimeAmount.toTicks(1L, TimeUnit.MINUTES); - registerTask(tpsCounter).runTaskTimer(minuteTicks, secondTicks); - registerTask(ramAndCpuTask).runTaskTimerAsynchronously(minuteTicks - halfSecondTicks, secondTicks); - registerTask(diskTask).runTaskTimerAsynchronously(50L * secondTicks, minuteTicks); - } - - private void registerTasks() { - registerTPSCounter(); - registerTask(logsFolderCleanTask).runTaskLaterAsynchronously(TimeAmount.toTicks(30L, TimeUnit.SECONDS)); - - Long pingDelay = config.get(TimeSettings.PING_SERVER_ENABLE_DELAY); - if (pingDelay < TimeUnit.HOURS.toMillis(1L) && config.isTrue(DataGatheringSettings.PING)) { - plugin.registerListener(pingCounter); - long startDelay = TimeAmount.toTicks(pingDelay, TimeUnit.MILLISECONDS); - registerTask(pingCounter).runTaskTimer(startDelay, 40L); - } - - // +40 ticks / 2 seconds so that update check task runs first. - long storeDelay = TimeAmount.toTicks(config.get(TimeSettings.CONFIG_UPDATE_INTERVAL), TimeUnit.MILLISECONDS) + 40; - registerTask(networkConfigStoreTask).runTaskLaterAsynchronously(storeDelay); - - registerTask(dbCleanTask).runTaskTimerAsynchronously( - TimeAmount.toTicks(20, TimeUnit.SECONDS), - TimeAmount.toTicks(config.get(TimeSettings.CLEAN_DATABASE_PERIOD), TimeUnit.MILLISECONDS) - ); - long minute = TimeAmount.toTicks(1, TimeUnit.MINUTES); - registerTask(jsonCacheCleanTask).runTaskTimerAsynchronously(minute, minute); - - long extensionRefreshPeriod = TimeAmount.toTicks(config.get(TimeSettings.EXTENSION_DATA_REFRESH_PERIOD), TimeUnit.MILLISECONDS); - registerTask(extensionServerMethodCallerTask).runTaskTimerAsynchronously( - TimeAmount.toTicks(30, TimeUnit.SECONDS), extensionRefreshPeriod - ); - } -} diff --git a/Plan/bungeecord/src/main/java/com/djrapitops/plan/PlanBungee.java b/Plan/bungeecord/src/main/java/com/djrapitops/plan/PlanBungee.java index 9f253422d..b410ea640 100644 --- a/Plan/bungeecord/src/main/java/com/djrapitops/plan/PlanBungee.java +++ b/Plan/bungeecord/src/main/java/com/djrapitops/plan/PlanBungee.java @@ -74,6 +74,7 @@ public class PlanBungee extends BungeePlugin implements PlanPlugin { @Override public void onDisable() { + cancelAllTasks(); if (system != null) system.disable(); logger.info(locale.getString(PluginLang.DISABLED)); diff --git a/Plan/bungeecord/src/main/java/com/djrapitops/plan/PlanBungeeComponent.java b/Plan/bungeecord/src/main/java/com/djrapitops/plan/PlanBungeeComponent.java index 81223dffb..e736870b6 100644 --- a/Plan/bungeecord/src/main/java/com/djrapitops/plan/PlanBungeeComponent.java +++ b/Plan/bungeecord/src/main/java/com/djrapitops/plan/PlanBungeeComponent.java @@ -21,10 +21,7 @@ import com.djrapitops.plan.modules.APFModule; import com.djrapitops.plan.modules.PlaceholderModule; import com.djrapitops.plan.modules.ProxySuperClassBindingModule; import com.djrapitops.plan.modules.SystemObjectProvidingModule; -import com.djrapitops.plan.modules.bungee.BungeeCommandModule; -import com.djrapitops.plan.modules.bungee.BungeePlanModule; -import com.djrapitops.plan.modules.bungee.BungeeServerPropertiesModule; -import com.djrapitops.plan.modules.bungee.BungeeSuperClassBindingModule; +import com.djrapitops.plan.modules.bungee.*; import dagger.BindsInstance; import dagger.Component; @@ -45,7 +42,8 @@ import javax.inject.Singleton; ProxySuperClassBindingModule.class, BungeeSuperClassBindingModule.class, - BungeeServerPropertiesModule.class + BungeeServerPropertiesModule.class, + BungeeTaskModule.class }) public interface PlanBungeeComponent { diff --git a/Plan/bungeecord/src/main/java/com/djrapitops/plan/gathering/timed/BungeePingCounter.java b/Plan/bungeecord/src/main/java/com/djrapitops/plan/gathering/timed/BungeePingCounter.java index d0d23c9d1..6507cf404 100644 --- a/Plan/bungeecord/src/main/java/com/djrapitops/plan/gathering/timed/BungeePingCounter.java +++ b/Plan/bungeecord/src/main/java/com/djrapitops/plan/gathering/timed/BungeePingCounter.java @@ -23,9 +23,12 @@ */ package com.djrapitops.plan.gathering.timed; +import com.djrapitops.plan.PlanBungee; +import com.djrapitops.plan.TaskSystem; import com.djrapitops.plan.delivery.domain.DateObj; import com.djrapitops.plan.identification.ServerInfo; import com.djrapitops.plan.settings.config.PlanConfig; +import com.djrapitops.plan.settings.config.paths.DataGatheringSettings; import com.djrapitops.plan.settings.config.paths.TimeSettings; import com.djrapitops.plan.storage.database.DBSystem; import com.djrapitops.plan.storage.database.transactions.events.PingStoreTransaction; @@ -50,10 +53,11 @@ import java.util.concurrent.TimeUnit; * @author BrainStone */ @Singleton -public class BungeePingCounter extends AbsRunnable implements Listener { +public class BungeePingCounter extends TaskSystem.Task implements Listener { private final Map>> playerHistory; + private final PlanBungee plugin; private final PlanConfig config; private final DBSystem dbSystem; private final ServerInfo serverInfo; @@ -61,11 +65,13 @@ public class BungeePingCounter extends AbsRunnable implements Listener { @Inject public BungeePingCounter( + PlanBungee plugin, PlanConfig config, DBSystem dbSystem, ServerInfo serverInfo, RunnableFactory runnableFactory ) { + this.plugin = plugin; this.config = config; this.dbSystem = dbSystem; this.serverInfo = serverInfo; @@ -102,6 +108,18 @@ public class BungeePingCounter extends AbsRunnable implements Listener { } } + @Override + public void register(RunnableFactory runnableFactory) { + Long startDelay = config.get(TimeSettings.PING_SERVER_ENABLE_DELAY); + if (startDelay < TimeUnit.HOURS.toMillis(1L) && config.isTrue(DataGatheringSettings.PING)) { + plugin.registerListener(this); + + long delay = TimeAmount.toTicks(startDelay, TimeUnit.MILLISECONDS); + long period = 40L; + runnableFactory.create(null, this).runTaskTimerAsynchronously(delay, period); + } + } + public void addPlayer(ProxiedPlayer player) { playerHistory.put(player.getUniqueId(), new ArrayList<>()); } diff --git a/Plan/bungeecord/src/main/java/com/djrapitops/plan/modules/bungee/BungeeSuperClassBindingModule.java b/Plan/bungeecord/src/main/java/com/djrapitops/plan/modules/bungee/BungeeSuperClassBindingModule.java index cd5071cbf..e8cac77df 100644 --- a/Plan/bungeecord/src/main/java/com/djrapitops/plan/modules/bungee/BungeeSuperClassBindingModule.java +++ b/Plan/bungeecord/src/main/java/com/djrapitops/plan/modules/bungee/BungeeSuperClassBindingModule.java @@ -16,8 +16,6 @@ */ package com.djrapitops.plan.modules.bungee; -import com.djrapitops.plan.BungeeTaskSystem; -import com.djrapitops.plan.TaskSystem; import com.djrapitops.plan.gathering.BungeeSensor; import com.djrapitops.plan.gathering.ServerSensor; import com.djrapitops.plan.gathering.listeners.BungeeListenerSystem; @@ -38,9 +36,6 @@ public interface BungeeSuperClassBindingModule { @Binds ServerInfo bindServerInfo(BungeeServerInfo serverInfo); - @Binds - TaskSystem bindTaskSystem(BungeeTaskSystem taskSystem); - @Binds ListenerSystem bindListenerSystem(BungeeListenerSystem listenerSystem); diff --git a/Plan/bungeecord/src/main/java/com/djrapitops/plan/modules/bungee/BungeeTaskModule.java b/Plan/bungeecord/src/main/java/com/djrapitops/plan/modules/bungee/BungeeTaskModule.java new file mode 100644 index 000000000..7bdc64d03 --- /dev/null +++ b/Plan/bungeecord/src/main/java/com/djrapitops/plan/modules/bungee/BungeeTaskModule.java @@ -0,0 +1,71 @@ +/* + * This file is part of Player Analytics (Plan). + * + * Plan is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License v3 as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Plan is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Plan. If not, see . + */ +package com.djrapitops.plan.modules.bungee; + +import com.djrapitops.plan.TaskSystem; +import com.djrapitops.plan.delivery.webserver.cache.JSONCache; +import com.djrapitops.plan.extension.ExtensionServerDataUpdater; +import com.djrapitops.plan.gathering.timed.BungeePingCounter; +import com.djrapitops.plan.gathering.timed.ProxyTPSCounter; +import com.djrapitops.plan.gathering.timed.SystemUsageBuffer; +import com.djrapitops.plan.settings.upkeep.NetworkConfigStoreTask; +import com.djrapitops.plan.storage.upkeep.DBCleanTask; +import com.djrapitops.plan.storage.upkeep.LogsFolderCleanTask; +import dagger.Binds; +import dagger.Module; +import dagger.multibindings.IntoSet; + +@Module +public interface BungeeTaskModule { + + @Binds + @IntoSet + TaskSystem.Task bindTPSCounter(ProxyTPSCounter counter); + + @Binds + @IntoSet + TaskSystem.Task bindPingCounter(BungeePingCounter counter); + + @Binds + @IntoSet + TaskSystem.Task bindNetworkConfigStoreTask(NetworkConfigStoreTask configStoreTask); + + @Binds + @IntoSet + TaskSystem.Task bindExtensionServerDataUpdater(ExtensionServerDataUpdater extensionServerDataUpdater); + + @Binds + @IntoSet + TaskSystem.Task bindLogCleanTask(LogsFolderCleanTask logsFolderCleanTask); + + @Binds + @IntoSet + TaskSystem.Task bindDBCleanTask(DBCleanTask cleanTask); + + @Binds + @IntoSet + TaskSystem.Task bindJSONCacheCleanTask(JSONCache.CleanTask cleanTask); + + @Binds + @IntoSet + TaskSystem.Task bindRamAndCpuTask(SystemUsageBuffer.RamAndCpuTask ramAndCpuTask); + + @Binds + @IntoSet + TaskSystem.Task bindDiskTask(SystemUsageBuffer.DiskTask diskTask); + +} diff --git a/Plan/common/src/main/java/com/djrapitops/plan/PlanPlugin.java b/Plan/common/src/main/java/com/djrapitops/plan/PlanPlugin.java index 33e65d06e..a619104f1 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/PlanPlugin.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/PlanPlugin.java @@ -47,4 +47,8 @@ public interface PlanPlugin extends IPlugin { } void registerCommand(Subcommand command); + + default void cancelAllTasks() { + getRunnableFactory().cancelAllKnownTasks(); + } } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/TaskSystem.java b/Plan/common/src/main/java/com/djrapitops/plan/TaskSystem.java index cf062df15..6853e34b2 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/TaskSystem.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/TaskSystem.java @@ -17,31 +17,36 @@ package com.djrapitops.plan; import com.djrapitops.plugin.task.AbsRunnable; -import com.djrapitops.plugin.task.PluginRunnable; import com.djrapitops.plugin.task.RunnableFactory; +import javax.inject.Inject; +import javax.inject.Singleton; +import java.util.Set; + /** - * TaskSystem that registers tasks that were previously registered inside Plugin classes. - * - * Subclasses register actual tasks. + * TaskSystem that registers tasks for the plugin. + * See platform specific [Platform]TaskModule classes for what Tasks are registered. * * @author Rsl1122 */ -public abstract class TaskSystem implements SubSystem { +@Singleton +public class TaskSystem implements SubSystem { - protected final RunnableFactory runnableFactory; + private final RunnableFactory runnableFactory; + private final Set tasks; - protected TaskSystem(RunnableFactory runnableFactory) { + @Inject + public TaskSystem( + RunnableFactory runnableFactory, + Set tasks + ) { this.runnableFactory = runnableFactory; + this.tasks = tasks; } - protected PluginRunnable registerTask(AbsRunnable runnable) { - String taskName = runnable.getClass().getSimpleName(); - return registerTask(taskName, runnable); - } - - public PluginRunnable registerTask(String name, AbsRunnable runnable) { - return runnableFactory.create(name, runnable); + @Override + public void enable() { + for (Task task : tasks) task.register(runnableFactory); } @Override @@ -49,4 +54,8 @@ public abstract class TaskSystem implements SubSystem { runnableFactory.cancelAllKnownTasks(); } + public static abstract class Task extends AbsRunnable { + public abstract void register(RunnableFactory runnableFactory); + } + } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/delivery/export/ExportScheduler.java b/Plan/common/src/main/java/com/djrapitops/plan/delivery/export/ExportScheduler.java index 8fbbb3652..137f5f2f2 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/delivery/export/ExportScheduler.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/delivery/export/ExportScheduler.java @@ -16,7 +16,6 @@ */ package com.djrapitops.plan.delivery.export; -import com.djrapitops.plan.TaskSystem; import com.djrapitops.plan.identification.Server; import com.djrapitops.plan.settings.config.PlanConfig; import com.djrapitops.plan.settings.config.paths.ExportSettings; @@ -24,6 +23,7 @@ import com.djrapitops.plan.storage.database.DBSystem; import com.djrapitops.plan.storage.database.queries.objects.ServerQueries; import com.djrapitops.plan.utilities.logging.ErrorLogger; import com.djrapitops.plugin.api.TimeAmount; +import com.djrapitops.plugin.task.RunnableFactory; import javax.inject.Inject; import javax.inject.Singleton; @@ -41,8 +41,8 @@ public class ExportScheduler { private final PlanConfig config; private final DBSystem dbSystem; - private final TaskSystem taskSystem; + private final RunnableFactory runnableFactory; private final Exporter exporter; private final ErrorLogger errorLogger; @@ -50,13 +50,13 @@ public class ExportScheduler { public ExportScheduler( PlanConfig config, DBSystem dbSystem, - TaskSystem taskSystem, + RunnableFactory runnableFactory, Exporter exporter, ErrorLogger errorLogger ) { this.config = config; this.dbSystem = dbSystem; - this.taskSystem = taskSystem; + this.runnableFactory = runnableFactory; this.exporter = exporter; this.errorLogger = errorLogger; } @@ -68,7 +68,7 @@ public class ExportScheduler { private void schedulePlayersPageExport() { long period = TimeAmount.toTicks(config.get(ExportSettings.EXPORT_PERIOD), TimeUnit.MILLISECONDS); - taskSystem.registerTask("Players page export", + runnableFactory.create("Players page export", new ExportTask(exporter, Exporter::exportPlayersPage, errorLogger) ).runTaskTimerAsynchronously(0L, period); } @@ -84,14 +84,14 @@ public class ExportScheduler { long offset = period / serverCount; Optional proxy = servers.stream().filter(Server::isProxy).findFirst(); - proxy.ifPresent(mainServer -> taskSystem.registerTask("Network export", + proxy.ifPresent(mainServer -> runnableFactory.create("Network export", new ExportTask(exporter, same -> same.exportServerPage(mainServer), errorLogger)) .runTaskTimerAsynchronously(0L, period) ); int offsetMultiplier = proxy.isPresent() ? 1 : 0; // Delay first server export if on a network. for (Server server : servers) { - taskSystem.registerTask("Server export", + runnableFactory.create("Server export", new ExportTask(exporter, same -> { same.exportServerPage(server); same.exportServerJSON(server); diff --git a/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/cache/JSONCache.java b/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/cache/JSONCache.java index 077629b90..2c1683785 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/cache/JSONCache.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/cache/JSONCache.java @@ -16,11 +16,13 @@ */ package com.djrapitops.plan.delivery.webserver.cache; +import com.djrapitops.plan.TaskSystem; import com.djrapitops.plan.delivery.web.resolver.MimeType; import com.djrapitops.plan.delivery.web.resolver.Response; import com.djrapitops.plan.delivery.webserver.resolver.json.RootJSONResolver; import com.djrapitops.plan.storage.file.ResourceCache; -import com.djrapitops.plugin.task.AbsRunnable; +import com.djrapitops.plugin.api.TimeAmount; +import com.djrapitops.plugin.task.RunnableFactory; import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; import org.apache.commons.lang3.StringUtils; @@ -141,7 +143,7 @@ public class JSONCache { } @Singleton - public static class CleanTask extends AbsRunnable { + public static class CleanTask extends TaskSystem.Task { @Inject public CleanTask() { @@ -153,5 +155,11 @@ public class JSONCache { cleanUp(); ResourceCache.cleanUp(); } + + @Override + public void register(RunnableFactory runnableFactory) { + long minute = TimeAmount.toTicks(1, TimeUnit.MINUTES); + runnableFactory.create(null, this).runTaskTimerAsynchronously(minute, minute); + } } } \ No newline at end of file diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/ExtensionServerMethodCallerTask.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/ExtensionServerDataUpdater.java similarity index 56% rename from Plan/common/src/main/java/com/djrapitops/plan/extension/ExtensionServerMethodCallerTask.java rename to Plan/common/src/main/java/com/djrapitops/plan/extension/ExtensionServerDataUpdater.java index ea75f8779..dc8f0f461 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/extension/ExtensionServerMethodCallerTask.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/extension/ExtensionServerDataUpdater.java @@ -16,10 +16,15 @@ */ package com.djrapitops.plan.extension; -import com.djrapitops.plugin.task.AbsRunnable; +import com.djrapitops.plan.TaskSystem; +import com.djrapitops.plan.settings.config.PlanConfig; +import com.djrapitops.plan.settings.config.paths.TimeSettings; +import com.djrapitops.plugin.api.TimeAmount; +import com.djrapitops.plugin.task.RunnableFactory; import javax.inject.Inject; import javax.inject.Singleton; +import java.util.concurrent.TimeUnit; /** * Task for updating {@link DataExtension} server values periodically. @@ -27,17 +32,29 @@ import javax.inject.Singleton; * @author Rsl1122 */ @Singleton -public class ExtensionServerMethodCallerTask extends AbsRunnable { +public class ExtensionServerDataUpdater extends TaskSystem.Task { private final ExtensionSvc service; + private final PlanConfig config; @Inject - public ExtensionServerMethodCallerTask(ExtensionSvc service) { + public ExtensionServerDataUpdater( + ExtensionSvc service, + PlanConfig config + ) { this.service = service; + this.config = config; } @Override public void run() { service.updateServerValues(CallEvents.SERVER_PERIODICAL); } + + @Override + public void register(RunnableFactory runnableFactory) { + long period = TimeAmount.toTicks(config.get(TimeSettings.EXTENSION_DATA_REFRESH_PERIOD), TimeUnit.MILLISECONDS); + long delay = TimeAmount.toTicks(30, TimeUnit.SECONDS); + runnableFactory.create(null, this).runTaskTimerAsynchronously(delay, period); + } } \ No newline at end of file diff --git a/Plan/common/src/main/java/com/djrapitops/plan/gathering/ShutdownHook.java b/Plan/common/src/main/java/com/djrapitops/plan/gathering/ShutdownHook.java index e7a53865a..97656382b 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/gathering/ShutdownHook.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/gathering/ShutdownHook.java @@ -16,6 +16,9 @@ */ package com.djrapitops.plan.gathering; +import com.djrapitops.plan.TaskSystem; +import com.djrapitops.plugin.task.RunnableFactory; + import javax.inject.Inject; import javax.inject.Singleton; import java.util.concurrent.ExecutionException; @@ -78,4 +81,22 @@ public class ShutdownHook extends Thread { Logger.getGlobal().log(Level.SEVERE, "Plan failed to save sessions on JVM shutdown.", e); } } + + @Singleton + public static class Registrar extends TaskSystem.Task { + private final ShutdownHook shutdownHook; + + @Inject + public Registrar(ShutdownHook shutdownHook) {this.shutdownHook = shutdownHook;} + + @Override + public void run() { + shutdownHook.register(); + } + + @Override + public void register(RunnableFactory runnableFactory) { + runnableFactory.create(null, this).runTaskAsynchronously(); + } + } } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/gathering/timed/SystemUsageBuffer.java b/Plan/common/src/main/java/com/djrapitops/plan/gathering/timed/SystemUsageBuffer.java index 0454600a8..2b20d4bc2 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/gathering/timed/SystemUsageBuffer.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/gathering/timed/SystemUsageBuffer.java @@ -16,17 +16,20 @@ */ package com.djrapitops.plan.gathering.timed; +import com.djrapitops.plan.TaskSystem; import com.djrapitops.plan.gathering.SystemUsage; import com.djrapitops.plan.settings.config.PlanConfig; import com.djrapitops.plan.settings.config.paths.DataGatheringSettings; import com.djrapitops.plan.utilities.logging.ErrorContext; import com.djrapitops.plan.utilities.logging.ErrorLogger; +import com.djrapitops.plugin.api.TimeAmount; import com.djrapitops.plugin.logging.L; import com.djrapitops.plugin.logging.console.PluginLogger; -import com.djrapitops.plugin.task.AbsRunnable; +import com.djrapitops.plugin.task.RunnableFactory; import javax.inject.Inject; import javax.inject.Singleton; +import java.util.concurrent.TimeUnit; /** * Task for performing system resource usage checks asynchronously @@ -64,7 +67,7 @@ public class SystemUsageBuffer { } @Singleton - public static class RamAndCpuTask extends AbsRunnable { + public static class RamAndCpuTask extends TaskSystem.Task { private final SystemUsageBuffer buffer; private final PluginLogger logger; @@ -84,10 +87,17 @@ public class SystemUsageBuffer { cancel(); } } + + @Override + public void register(RunnableFactory runnableFactory) { + long delay = TimeAmount.toTicks(1, TimeUnit.MINUTES) - TimeAmount.toTicks(500, TimeUnit.MILLISECONDS); + long period = TimeAmount.toTicks(1, TimeUnit.SECONDS); + runnableFactory.create(null, this).runTaskTimerAsynchronously(delay, period); + } } @Singleton - public static class DiskTask extends AbsRunnable { + public static class DiskTask extends TaskSystem.Task { private final PlanConfig config; private final SystemUsageBuffer buffer; private final PluginLogger logger; @@ -121,6 +131,13 @@ public class SystemUsageBuffer { cancel(); } } + + @Override + public void register(RunnableFactory runnableFactory) { + long delay = TimeAmount.toTicks(50, TimeUnit.SECONDS); + long period = TimeAmount.toTicks(1, TimeUnit.SECONDS); + runnableFactory.create(null, this).runTaskTimerAsynchronously(delay, period); + } } } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/gathering/timed/TPSCounter.java b/Plan/common/src/main/java/com/djrapitops/plan/gathering/timed/TPSCounter.java index 068e35a8d..1fb5189d4 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/gathering/timed/TPSCounter.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/gathering/timed/TPSCounter.java @@ -16,18 +16,22 @@ */ package com.djrapitops.plan.gathering.timed; +import com.djrapitops.plan.TaskSystem; import com.djrapitops.plan.utilities.logging.ErrorContext; import com.djrapitops.plan.utilities.logging.ErrorLogger; +import com.djrapitops.plugin.api.TimeAmount; import com.djrapitops.plugin.logging.L; import com.djrapitops.plugin.logging.console.PluginLogger; -import com.djrapitops.plugin.task.AbsRunnable; +import com.djrapitops.plugin.task.RunnableFactory; + +import java.util.concurrent.TimeUnit; /** * Class responsible for calculating TPS every second. * * @author Rsl1122 */ -public abstract class TPSCounter extends AbsRunnable { +public abstract class TPSCounter extends TaskSystem.Task { protected final PluginLogger logger; protected final ErrorLogger errorLogger; @@ -51,6 +55,12 @@ public abstract class TPSCounter extends AbsRunnable { } } + public void register(RunnableFactory runnableFactory) { + long delay = TimeAmount.toTicks(1L, TimeUnit.MINUTES); + long period = TimeAmount.toTicks(1L, TimeUnit.SECONDS); + runnableFactory.create(null, this).runTaskTimer(delay, period); + } + public abstract void pulse(); } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/settings/network/ServerSettingsManager.java b/Plan/common/src/main/java/com/djrapitops/plan/settings/network/ServerSettingsManager.java index 46f6481c9..5d10542dd 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/settings/network/ServerSettingsManager.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/settings/network/ServerSettingsManager.java @@ -17,7 +17,6 @@ package com.djrapitops.plan.settings.network; import com.djrapitops.plan.SubSystem; -import com.djrapitops.plan.TaskSystem; import com.djrapitops.plan.identification.ServerInfo; import com.djrapitops.plan.settings.config.Config; import com.djrapitops.plan.settings.config.ConfigReader; @@ -35,6 +34,7 @@ import com.djrapitops.plan.utilities.logging.ErrorLogger; import com.djrapitops.plugin.api.TimeAmount; import com.djrapitops.plugin.logging.console.PluginLogger; import com.djrapitops.plugin.task.AbsRunnable; +import com.djrapitops.plugin.task.RunnableFactory; import javax.inject.Inject; import javax.inject.Singleton; @@ -62,8 +62,8 @@ public class ServerSettingsManager implements SubSystem { private final PlanConfig config; private final DBSystem dbSystem; private final ServerInfo serverInfo; - private final TaskSystem taskSystem; private final ErrorLogger errorLogger; + private final RunnableFactory runnableFactory; private final PluginLogger logger; private FileWatcher watcher; @@ -73,7 +73,7 @@ public class ServerSettingsManager implements SubSystem { PlanConfig config, DBSystem dbSystem, ServerInfo serverInfo, - TaskSystem taskSystem, + RunnableFactory runnableFactory, PluginLogger logger, ErrorLogger errorLogger ) { @@ -81,7 +81,7 @@ public class ServerSettingsManager implements SubSystem { this.config = config; this.dbSystem = dbSystem; this.serverInfo = serverInfo; - this.taskSystem = taskSystem; + this.runnableFactory = runnableFactory; this.logger = logger; this.errorLogger = errorLogger; } @@ -125,7 +125,8 @@ public class ServerSettingsManager implements SubSystem { private void scheduleDBCheckTask() { long checkPeriod = TimeAmount.toTicks(config.get(TimeSettings.CONFIG_UPDATE_INTERVAL), TimeUnit.MILLISECONDS); - taskSystem.registerTask("Config Update DB Checker", new AbsRunnable() { + + runnableFactory.create("Config Update DB Checker", new AbsRunnable() { @Override public void run() { checkDBForNewConfigSettings(dbSystem.getDatabase()); diff --git a/Plan/common/src/main/java/com/djrapitops/plan/settings/upkeep/ConfigStoreTask.java b/Plan/common/src/main/java/com/djrapitops/plan/settings/upkeep/ConfigStoreTask.java index b3876d89a..2afe1159d 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/settings/upkeep/ConfigStoreTask.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/settings/upkeep/ConfigStoreTask.java @@ -16,16 +16,20 @@ */ package com.djrapitops.plan.settings.upkeep; +import com.djrapitops.plan.TaskSystem; import com.djrapitops.plan.identification.ServerInfo; import com.djrapitops.plan.settings.config.PlanConfig; +import com.djrapitops.plan.settings.config.paths.TimeSettings; import com.djrapitops.plan.storage.database.DBSystem; import com.djrapitops.plan.storage.database.transactions.StoreConfigTransaction; import com.djrapitops.plan.storage.file.PlanFiles; +import com.djrapitops.plugin.api.TimeAmount; import com.djrapitops.plugin.logging.console.PluginLogger; -import com.djrapitops.plugin.task.AbsRunnable; +import com.djrapitops.plugin.task.RunnableFactory; import javax.inject.Inject; import javax.inject.Singleton; +import java.util.concurrent.TimeUnit; /** * Task that stores a server config in the database on boot. @@ -33,7 +37,7 @@ import javax.inject.Singleton; * @author Rsl1122 */ @Singleton -public class ConfigStoreTask extends AbsRunnable { +public class ConfigStoreTask extends TaskSystem.Task { private final PlanFiles files; private final PlanConfig config; @@ -63,4 +67,10 @@ public class ConfigStoreTask extends AbsRunnable { logger.debug("Config Store Task - Config in db now up to date."); cancel(); } + + @Override + public void register(RunnableFactory runnableFactory) { + long delay = TimeAmount.toTicks(config.get(TimeSettings.CONFIG_UPDATE_INTERVAL), TimeUnit.MILLISECONDS) + 40; + runnableFactory.create(null, this).runTaskLaterAsynchronously(delay); + } } \ No newline at end of file diff --git a/Plan/common/src/main/java/com/djrapitops/plan/settings/upkeep/NetworkConfigStoreTask.java b/Plan/common/src/main/java/com/djrapitops/plan/settings/upkeep/NetworkConfigStoreTask.java index 30aa6dafc..f864c2b19 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/settings/upkeep/NetworkConfigStoreTask.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/settings/upkeep/NetworkConfigStoreTask.java @@ -16,13 +16,18 @@ */ package com.djrapitops.plan.settings.upkeep; +import com.djrapitops.plan.TaskSystem; +import com.djrapitops.plan.settings.config.PlanConfig; +import com.djrapitops.plan.settings.config.paths.TimeSettings; import com.djrapitops.plan.settings.network.NetworkSettingManager; -import com.djrapitops.plugin.task.AbsRunnable; +import com.djrapitops.plugin.api.TimeAmount; +import com.djrapitops.plugin.task.RunnableFactory; import javax.inject.Inject; import javax.inject.Singleton; import java.io.File; import java.util.UUID; +import java.util.concurrent.TimeUnit; /** * Task on networks that stores server configs in /plugins/Plan/serverConfiguration in database on boot. @@ -30,14 +35,17 @@ import java.util.UUID; * @author Rsl1122 */ @Singleton -public class NetworkConfigStoreTask extends AbsRunnable { +public class NetworkConfigStoreTask extends TaskSystem.Task { private final NetworkSettingManager networkSettingManager; + private final PlanConfig config; @Inject public NetworkConfigStoreTask( + PlanConfig config, NetworkSettingManager networkSettingManager ) { + this.config = config; this.networkSettingManager = networkSettingManager; } @@ -47,6 +55,13 @@ public class NetworkConfigStoreTask extends AbsRunnable { cancel(); } + @Override + public void register(RunnableFactory runnableFactory) { + long delay = TimeAmount.toTicks(config.get(TimeSettings.CONFIG_UPDATE_INTERVAL), TimeUnit.MILLISECONDS) + 40; + + runnableFactory.create(null, this).runTaskLaterAsynchronously(delay); + } + private void updateDBConfigs() { File[] configFiles = networkSettingManager.getConfigFiles(); diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/upkeep/DBCleanTask.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/upkeep/DBCleanTask.java index f7f3fc6ec..9ad6b818a 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/upkeep/DBCleanTask.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/upkeep/DBCleanTask.java @@ -16,6 +16,7 @@ */ package com.djrapitops.plan.storage.upkeep; +import com.djrapitops.plan.TaskSystem; import com.djrapitops.plan.exceptions.database.DBOpException; import com.djrapitops.plan.extension.implementation.storage.transactions.results.RemoveUnsatisfiedConditionalPlayerResultsTransaction; import com.djrapitops.plan.extension.implementation.storage.transactions.results.RemoveUnsatisfiedConditionalServerResultsTransaction; @@ -35,9 +36,10 @@ import com.djrapitops.plan.storage.database.transactions.init.RemoveDuplicateUse import com.djrapitops.plan.storage.database.transactions.init.RemoveOldExtensionsTransaction; import com.djrapitops.plan.storage.database.transactions.init.RemoveOldSampledDataTransaction; import com.djrapitops.plan.utilities.logging.ErrorLogger; +import com.djrapitops.plugin.api.TimeAmount; import com.djrapitops.plugin.logging.L; import com.djrapitops.plugin.logging.console.PluginLogger; -import com.djrapitops.plugin.task.AbsRunnable; +import com.djrapitops.plugin.task.RunnableFactory; import javax.inject.Inject; import javax.inject.Singleton; @@ -47,6 +49,7 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import java.util.UUID; +import java.util.concurrent.TimeUnit; import static com.djrapitops.plan.storage.database.sql.building.Sql.*; @@ -56,7 +59,7 @@ import static com.djrapitops.plan.storage.database.sql.building.Sql.*; * @author Rsl1122 */ @Singleton -public class DBCleanTask extends AbsRunnable { +public class DBCleanTask extends TaskSystem.Task { private final Locale locale; private final DBSystem dbSystem; @@ -120,6 +123,13 @@ public class DBCleanTask extends AbsRunnable { } } + @Override + public void register(RunnableFactory runnableFactory) { + long delay = TimeAmount.toTicks(20, TimeUnit.SECONDS); + long period = TimeAmount.toTicks(config.get(TimeSettings.CLEAN_DATABASE_PERIOD), TimeUnit.MILLISECONDS); + runnableFactory.create(null, this).runTaskTimerAsynchronously(delay, period); + } + // VisibleForTesting public int cleanOldPlayers(Database database) { long now = System.currentTimeMillis(); diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/upkeep/LogsFolderCleanTask.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/upkeep/LogsFolderCleanTask.java index 38d061f31..bc3fe2ab5 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/upkeep/LogsFolderCleanTask.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/upkeep/LogsFolderCleanTask.java @@ -16,11 +16,13 @@ */ package com.djrapitops.plan.storage.upkeep; +import com.djrapitops.plan.TaskSystem; import com.djrapitops.plan.settings.config.PlanConfig; import com.djrapitops.plan.settings.config.paths.PluginSettings; import com.djrapitops.plan.storage.file.PlanFiles; +import com.djrapitops.plugin.api.TimeAmount; import com.djrapitops.plugin.logging.console.PluginLogger; -import com.djrapitops.plugin.task.AbsRunnable; +import com.djrapitops.plugin.task.RunnableFactory; import javax.inject.Inject; import javax.inject.Singleton; @@ -36,7 +38,7 @@ import java.util.concurrent.TimeUnit; * @author Rsl1122 */ @Singleton -public class LogsFolderCleanTask extends AbsRunnable { +public class LogsFolderCleanTask extends TaskSystem.Task { private final File folder; private final PlanConfig config; @@ -71,6 +73,12 @@ public class LogsFolderCleanTask extends AbsRunnable { } } + @Override + public void register(RunnableFactory runnableFactory) { + long delay = TimeAmount.toTicks(30L, TimeUnit.SECONDS); + runnableFactory.create(null, this).runTaskLaterAsynchronously(delay); + } + private void cleanFolder() { long now = System.currentTimeMillis(); for (File file : Objects.requireNonNull(folder.listFiles())) { diff --git a/Plan/common/src/test/java/utilities/dagger/PluginSuperClassBindingModule.java b/Plan/common/src/test/java/utilities/dagger/PluginSuperClassBindingModule.java index 6550154ee..0dd1b22b0 100644 --- a/Plan/common/src/test/java/utilities/dagger/PluginSuperClassBindingModule.java +++ b/Plan/common/src/test/java/utilities/dagger/PluginSuperClassBindingModule.java @@ -19,16 +19,19 @@ package utilities.dagger; import com.djrapitops.plan.PlanPlugin; import com.djrapitops.plan.TaskSystem; import com.djrapitops.plan.gathering.ServerSensor; +import com.djrapitops.plan.gathering.importing.importers.Importer; import com.djrapitops.plan.gathering.listeners.ListenerSystem; import com.djrapitops.plan.processing.Processing; -import com.djrapitops.plugin.task.RunnableFactory; import dagger.Module; import dagger.Provides; +import dagger.multibindings.ElementsIntoSet; import org.mockito.Mockito; import utilities.mocks.TestProcessing; import javax.inject.Named; import javax.inject.Singleton; +import java.util.HashSet; +import java.util.Set; import static org.mockito.Mockito.when; @@ -41,13 +44,15 @@ import static org.mockito.Mockito.when; public class PluginSuperClassBindingModule { @Provides - @Singleton - TaskSystem provideTaskSystem(RunnableFactory runnableFactory) { - return new TaskSystem(runnableFactory) { - @Override - public void enable() { - } - }; + @ElementsIntoSet + Set provideEmptyImporterSet() { + return new HashSet<>(); + } + + @Provides + @ElementsIntoSet + Set provideEmptyTaskSet() { + return new HashSet<>(); } @Provides diff --git a/Plan/nukkit/src/main/java/com/djrapitops/plan/NukkitTaskSystem.java b/Plan/nukkit/src/main/java/com/djrapitops/plan/NukkitTaskSystem.java deleted file mode 100644 index 35333eea4..000000000 --- a/Plan/nukkit/src/main/java/com/djrapitops/plan/NukkitTaskSystem.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * This file is part of Player Analytics (Plan). - * - * Plan is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License v3 as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Plan is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Plan. If not, see . - */ -package com.djrapitops.plan; - -import cn.nukkit.Server; -import cn.nukkit.level.Level; -import com.djrapitops.plan.delivery.webserver.cache.JSONCache; -import com.djrapitops.plan.extension.ExtensionServerMethodCallerTask; -import com.djrapitops.plan.gathering.ShutdownHook; -import com.djrapitops.plan.gathering.timed.NukkitPingCounter; -import com.djrapitops.plan.gathering.timed.ServerTPSCounter; -import com.djrapitops.plan.gathering.timed.SystemUsageBuffer; -import com.djrapitops.plan.gathering.timed.TPSCounter; -import com.djrapitops.plan.settings.config.PlanConfig; -import com.djrapitops.plan.settings.config.paths.DataGatheringSettings; -import com.djrapitops.plan.settings.config.paths.TimeSettings; -import com.djrapitops.plan.settings.upkeep.ConfigStoreTask; -import com.djrapitops.plan.storage.upkeep.DBCleanTask; -import com.djrapitops.plan.storage.upkeep.LogsFolderCleanTask; -import com.djrapitops.plugin.api.TimeAmount; -import com.djrapitops.plugin.task.RunnableFactory; - -import javax.inject.Inject; -import javax.inject.Singleton; -import java.util.Optional; -import java.util.concurrent.TimeUnit; - -/** - * TaskSystem responsible for registering tasks for Nukkit. - * - * @author Rsl1122 - */ -@Singleton -public class NukkitTaskSystem extends TaskSystem { - - private final PlanNukkit plugin; - private final PlanConfig config; - private final ShutdownHook shutdownHook; - private final JSONCache.CleanTask jsonCacheCleanTask; - private final LogsFolderCleanTask logsFolderCleanTask; - private final TPSCounter tpsCounter; - private final NukkitPingCounter pingCounter; - private final ConfigStoreTask configStoreTask; - private final DBCleanTask dbCleanTask; - private final SystemUsageBuffer.RamAndCpuTask ramAndCpuTask; - private final SystemUsageBuffer.DiskTask diskTask; - private final ExtensionServerMethodCallerTask extensionServerMethodCallerTask; - - @Inject - public NukkitTaskSystem( - PlanNukkit plugin, - PlanConfig config, - ShutdownHook shutdownHook, - RunnableFactory runnableFactory, - - ServerTPSCounter tpsCounter, - NukkitPingCounter pingCounter, - ExtensionServerMethodCallerTask extensionServerMethodCallerTask, - - LogsFolderCleanTask logsFolderCleanTask, - ConfigStoreTask configStoreTask, - DBCleanTask dbCleanTask, - JSONCache.CleanTask jsonCacheCleanTask, - SystemUsageBuffer.RamAndCpuTask ramAndCpuTask, - SystemUsageBuffer.DiskTask diskTask - ) { - super(runnableFactory); - this.plugin = plugin; - this.config = config; - this.shutdownHook = shutdownHook; - this.jsonCacheCleanTask = jsonCacheCleanTask; - - this.tpsCounter = tpsCounter; - this.pingCounter = pingCounter; - this.extensionServerMethodCallerTask = extensionServerMethodCallerTask; - - this.logsFolderCleanTask = logsFolderCleanTask; - this.configStoreTask = configStoreTask; - this.dbCleanTask = dbCleanTask; - this.ramAndCpuTask = ramAndCpuTask; - this.diskTask = diskTask; - } - - @Override - public void enable() { - registerTPSCounter(); - registerPingCounter(); - registerExtensionDataGatheringTask(); - registerUpkeepTasks(); - - shutdownHook.register(); - } - - private void registerUpkeepTasks() { - // +40 ticks / 2 seconds so that update check task runs first. - long storeDelay = TimeAmount.toTicks(config.get(TimeSettings.CONFIG_UPDATE_INTERVAL), TimeUnit.MILLISECONDS) + 40; - registerTask(configStoreTask).runTaskLaterAsynchronously(storeDelay); - registerTask(logsFolderCleanTask).runTaskLaterAsynchronously(TimeAmount.toTicks(30L, TimeUnit.SECONDS)); - registerTask(dbCleanTask).runTaskTimerAsynchronously( - TimeAmount.toTicks(20, TimeUnit.SECONDS), - TimeAmount.toTicks(config.get(TimeSettings.CLEAN_DATABASE_PERIOD), TimeUnit.MILLISECONDS) - ); - long minute = TimeAmount.toTicks(1, TimeUnit.MINUTES); - registerTask(jsonCacheCleanTask).runTaskTimerAsynchronously(minute, minute); - } - - private void registerTPSCounter() { - long halfSecondTicks = TimeAmount.toTicks(500L, TimeUnit.MILLISECONDS); - long secondTicks = TimeAmount.toTicks(1L, TimeUnit.SECONDS); - long minuteTicks = TimeAmount.toTicks(1L, TimeUnit.MINUTES); - registerTask(tpsCounter).runTaskTimer(minuteTicks, secondTicks); - registerTask(ramAndCpuTask).runTaskTimerAsynchronously(minuteTicks - halfSecondTicks, secondTicks); - registerTask(diskTask).runTaskTimerAsynchronously(50L * secondTicks, minuteTicks); - } - - private void registerPingCounter() { - Long pingDelay = config.get(TimeSettings.PING_SERVER_ENABLE_DELAY); - if (pingDelay < TimeUnit.HOURS.toMillis(1L) && config.isTrue(DataGatheringSettings.PING)) { - plugin.registerListener(pingCounter); - long startDelay = TimeAmount.toTicks(pingDelay, TimeUnit.MILLISECONDS); - registerTask(pingCounter).runTaskTimer(startDelay, 40L); - } - } - - private void registerExtensionDataGatheringTask() { - long extensionRefreshPeriod = TimeAmount.toTicks(config.get(TimeSettings.EXTENSION_DATA_REFRESH_PERIOD), TimeUnit.MILLISECONDS); - registerTask(extensionServerMethodCallerTask).runTaskTimerAsynchronously( - TimeAmount.toTicks(30, TimeUnit.SECONDS), extensionRefreshPeriod - ); - } - - @Override - public void disable() { - super.disable(); - Optional.ofNullable(Server.getInstance().getScheduler()).ifPresent(scheduler -> scheduler.cancelTask(plugin)); - } -} diff --git a/Plan/nukkit/src/main/java/com/djrapitops/plan/PlanNukkit.java b/Plan/nukkit/src/main/java/com/djrapitops/plan/PlanNukkit.java index 1736a3b00..c800c789f 100644 --- a/Plan/nukkit/src/main/java/com/djrapitops/plan/PlanNukkit.java +++ b/Plan/nukkit/src/main/java/com/djrapitops/plan/PlanNukkit.java @@ -17,6 +17,7 @@ package com.djrapitops.plan; import cn.nukkit.Player; +import cn.nukkit.Server; import cn.nukkit.command.Command; import cn.nukkit.command.CommandSender; import com.djrapitops.plan.addons.placeholderapi.NukkitPlaceholderRegistrar; @@ -36,6 +37,7 @@ import com.djrapitops.plugin.task.AbsRunnable; import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import java.util.Optional; import java.util.logging.Level; import java.util.logging.Logger; @@ -98,16 +100,19 @@ public class PlanNukkit extends NukkitPlugin implements PlanPlugin { */ @Override public void onDisable() { - if (serverShutdownSave != null) { - serverShutdownSave.performSave(); - } - if (system != null) { - system.disable(); - } + if (serverShutdownSave != null) serverShutdownSave.performSave(); + cancelAllTasks(); + if (system != null) system.disable(); logger.info(locale != null ? locale.getString(PluginLang.DISABLED) : PluginLang.DISABLED.getDefault()); } + @Override + public void cancelAllTasks() { + runnableFactory.cancelAllKnownTasks(); + Optional.ofNullable(Server.getInstance().getScheduler()).ifPresent(scheduler -> scheduler.cancelTask(this)); + } + @Override public boolean onCommand(CommandSender actualSender, Command actualCommand, String label, String[] args) { String name = actualCommand.getName(); diff --git a/Plan/nukkit/src/main/java/com/djrapitops/plan/PlanNukkitComponent.java b/Plan/nukkit/src/main/java/com/djrapitops/plan/PlanNukkitComponent.java index c41c7ad14..47ffcab1f 100644 --- a/Plan/nukkit/src/main/java/com/djrapitops/plan/PlanNukkitComponent.java +++ b/Plan/nukkit/src/main/java/com/djrapitops/plan/PlanNukkitComponent.java @@ -26,6 +26,7 @@ import com.djrapitops.plan.modules.SystemObjectProvidingModule; import com.djrapitops.plan.modules.nukkit.NukkitPlanModule; import com.djrapitops.plan.modules.nukkit.NukkitServerPropertiesModule; import com.djrapitops.plan.modules.nukkit.NukkitSuperClassBindingModule; +import com.djrapitops.plan.modules.nukkit.NukkitTaskModule; import dagger.BindsInstance; import dagger.Component; @@ -45,7 +46,8 @@ import javax.inject.Singleton; ServerCommandModule.class, NukkitServerPropertiesModule.class, - NukkitSuperClassBindingModule.class + NukkitSuperClassBindingModule.class, + NukkitTaskModule.class }) public interface PlanNukkitComponent { diff --git a/Plan/nukkit/src/main/java/com/djrapitops/plan/gathering/timed/NukkitPingCounter.java b/Plan/nukkit/src/main/java/com/djrapitops/plan/gathering/timed/NukkitPingCounter.java index 9354a319f..6f8bf7d21 100644 --- a/Plan/nukkit/src/main/java/com/djrapitops/plan/gathering/timed/NukkitPingCounter.java +++ b/Plan/nukkit/src/main/java/com/djrapitops/plan/gathering/timed/NukkitPingCounter.java @@ -29,9 +29,12 @@ import cn.nukkit.event.EventHandler; import cn.nukkit.event.Listener; import cn.nukkit.event.player.PlayerJoinEvent; import cn.nukkit.event.player.PlayerQuitEvent; +import com.djrapitops.plan.PlanNukkit; +import com.djrapitops.plan.TaskSystem; import com.djrapitops.plan.delivery.domain.DateObj; import com.djrapitops.plan.identification.ServerInfo; import com.djrapitops.plan.settings.config.PlanConfig; +import com.djrapitops.plan.settings.config.paths.DataGatheringSettings; import com.djrapitops.plan.settings.config.paths.TimeSettings; import com.djrapitops.plan.storage.database.DBSystem; import com.djrapitops.plan.storage.database.transactions.events.PingStoreTransaction; @@ -53,10 +56,11 @@ import java.util.concurrent.TimeUnit; * @author games647 */ @Singleton -public class NukkitPingCounter extends AbsRunnable implements Listener { +public class NukkitPingCounter extends TaskSystem.Task implements Listener { private final Map>> playerHistory; + private final PlanNukkit plugin; private final PlanConfig config; private final DBSystem dbSystem; private final ServerInfo serverInfo; @@ -64,11 +68,13 @@ public class NukkitPingCounter extends AbsRunnable implements Listener { @Inject public NukkitPingCounter( + PlanNukkit plugin, PlanConfig config, DBSystem dbSystem, ServerInfo serverInfo, RunnableFactory runnableFactory ) { + this.plugin = plugin; this.config = config; this.dbSystem = dbSystem; this.serverInfo = serverInfo; @@ -105,6 +111,17 @@ public class NukkitPingCounter extends AbsRunnable implements Listener { } } + @Override + public void register(RunnableFactory runnableFactory) { + Long enableDelay = config.get(TimeSettings.PING_SERVER_ENABLE_DELAY); + if (enableDelay < TimeUnit.HOURS.toMillis(1L) && config.isTrue(DataGatheringSettings.PING)) { + plugin.registerListener(this); + long delay = TimeAmount.toTicks(enableDelay, TimeUnit.MILLISECONDS); + long period = 40L; + runnableFactory.create(null, this).runTaskTimer(delay, period); + } + } + public void addPlayer(Player player) { playerHistory.put(player.getUniqueId(), new ArrayList<>()); } diff --git a/Plan/nukkit/src/main/java/com/djrapitops/plan/modules/nukkit/NukkitSuperClassBindingModule.java b/Plan/nukkit/src/main/java/com/djrapitops/plan/modules/nukkit/NukkitSuperClassBindingModule.java index 1dcacb2b6..8cd0a899e 100644 --- a/Plan/nukkit/src/main/java/com/djrapitops/plan/modules/nukkit/NukkitSuperClassBindingModule.java +++ b/Plan/nukkit/src/main/java/com/djrapitops/plan/modules/nukkit/NukkitSuperClassBindingModule.java @@ -18,8 +18,6 @@ package com.djrapitops.plan.modules.nukkit; import cn.nukkit.level.Level; import com.djrapitops.plan.NukkitServerShutdownSave; -import com.djrapitops.plan.NukkitTaskSystem; -import com.djrapitops.plan.TaskSystem; import com.djrapitops.plan.gathering.NukkitSensor; import com.djrapitops.plan.gathering.ServerSensor; import com.djrapitops.plan.gathering.ServerShutdownSave; @@ -51,9 +49,6 @@ public interface NukkitSuperClassBindingModule { @Binds ConfigSystem bindConfigSystem(NukkitConfigSystem configSystem); - @Binds - TaskSystem bindTaskSystem(NukkitTaskSystem taskSystem); - @Binds ListenerSystem bindListenerSystem(NukkitListenerSystem listenerSystem); diff --git a/Plan/nukkit/src/main/java/com/djrapitops/plan/modules/nukkit/NukkitTaskModule.java b/Plan/nukkit/src/main/java/com/djrapitops/plan/modules/nukkit/NukkitTaskModule.java new file mode 100644 index 000000000..bfb50a7eb --- /dev/null +++ b/Plan/nukkit/src/main/java/com/djrapitops/plan/modules/nukkit/NukkitTaskModule.java @@ -0,0 +1,77 @@ +/* + * This file is part of Player Analytics (Plan). + * + * Plan is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License v3 as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Plan is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Plan. If not, see . + */ +package com.djrapitops.plan.modules.nukkit; + +import cn.nukkit.level.Level; +import com.djrapitops.plan.TaskSystem; +import com.djrapitops.plan.delivery.webserver.cache.JSONCache; +import com.djrapitops.plan.extension.ExtensionServerDataUpdater; +import com.djrapitops.plan.gathering.ShutdownHook; +import com.djrapitops.plan.gathering.timed.NukkitPingCounter; +import com.djrapitops.plan.gathering.timed.ServerTPSCounter; +import com.djrapitops.plan.gathering.timed.SystemUsageBuffer; +import com.djrapitops.plan.settings.upkeep.ConfigStoreTask; +import com.djrapitops.plan.storage.upkeep.DBCleanTask; +import com.djrapitops.plan.storage.upkeep.LogsFolderCleanTask; +import dagger.Binds; +import dagger.Module; +import dagger.multibindings.IntoSet; + +@Module +public interface NukkitTaskModule { + + @Binds + @IntoSet + TaskSystem.Task bindTPSCounter(ServerTPSCounter tpsCounter); + + @Binds + @IntoSet + TaskSystem.Task bindPingCounter(NukkitPingCounter pingCounter); + + @Binds + @IntoSet + TaskSystem.Task bindExtensionServerDataUpdater(ExtensionServerDataUpdater extensionServerDataUpdater); + + @Binds + @IntoSet + TaskSystem.Task bindLogCleanTask(LogsFolderCleanTask logsFolderCleanTask); + + @Binds + @IntoSet + TaskSystem.Task bindConfigStoreTask(ConfigStoreTask configStoreTask); + + @Binds + @IntoSet + TaskSystem.Task bindDBCleanTask(DBCleanTask cleanTask); + + @Binds + @IntoSet + TaskSystem.Task bindJSONCacheCleanTask(JSONCache.CleanTask cleanTask); + + @Binds + @IntoSet + TaskSystem.Task bindRamAndCpuTask(SystemUsageBuffer.RamAndCpuTask ramAndCpuTask); + + @Binds + @IntoSet + TaskSystem.Task bindDiskTask(SystemUsageBuffer.DiskTask diskTask); + + @Binds + @IntoSet + TaskSystem.Task bindShutdownHookRegistration(ShutdownHook.Registrar registrar); + +} diff --git a/Plan/sponge/src/main/java/com/djrapitops/plan/PlanSponge.java b/Plan/sponge/src/main/java/com/djrapitops/plan/PlanSponge.java index bdcb5224f..4fc0ed5e2 100644 --- a/Plan/sponge/src/main/java/com/djrapitops/plan/PlanSponge.java +++ b/Plan/sponge/src/main/java/com/djrapitops/plan/PlanSponge.java @@ -38,6 +38,7 @@ import org.spongepowered.api.event.game.state.GameStartedServerEvent; import org.spongepowered.api.event.game.state.GameStoppingServerEvent; import org.spongepowered.api.plugin.Dependency; import org.spongepowered.api.plugin.Plugin; +import org.spongepowered.api.scheduler.Task; import java.io.File; import java.io.InputStream; @@ -123,16 +124,21 @@ public class PlanSponge extends SpongePlugin implements PlanPlugin { @Override public void onDisable() { - if (serverShutdownSave != null) { - serverShutdownSave.performSave(); - } - if (system != null) { - system.disable(); - } + if (serverShutdownSave != null) serverShutdownSave.performSave(); + cancelAllTasks(); + if (system != null) system.disable(); logger.info(locale.getString(PluginLang.DISABLED)); } + @Override + public void cancelAllTasks() { + runnableFactory.cancelAllKnownTasks(); + for (Task task : Sponge.getScheduler().getScheduledTasks(this)) { + task.cancel(); + } + } + @Override public InputStream getResource(String resource) { return getClass().getResourceAsStream("/" + resource); diff --git a/Plan/sponge/src/main/java/com/djrapitops/plan/PlanSpongeComponent.java b/Plan/sponge/src/main/java/com/djrapitops/plan/PlanSpongeComponent.java index e77d898fb..02bfc6cee 100644 --- a/Plan/sponge/src/main/java/com/djrapitops/plan/PlanSpongeComponent.java +++ b/Plan/sponge/src/main/java/com/djrapitops/plan/PlanSpongeComponent.java @@ -25,6 +25,7 @@ import com.djrapitops.plan.modules.SystemObjectProvidingModule; import com.djrapitops.plan.modules.sponge.SpongePlanModule; import com.djrapitops.plan.modules.sponge.SpongeServerPropertiesModule; import com.djrapitops.plan.modules.sponge.SpongeSuperClassBindingModule; +import com.djrapitops.plan.modules.sponge.SpongeTaskModule; import dagger.BindsInstance; import dagger.Component; @@ -44,7 +45,8 @@ import javax.inject.Singleton; ServerCommandModule.class, SpongeSuperClassBindingModule.class, - SpongeServerPropertiesModule.class + SpongeServerPropertiesModule.class, + SpongeTaskModule.class }) public interface PlanSpongeComponent { diff --git a/Plan/sponge/src/main/java/com/djrapitops/plan/SpongeTaskSystem.java b/Plan/sponge/src/main/java/com/djrapitops/plan/SpongeTaskSystem.java deleted file mode 100644 index 340bb3e41..000000000 --- a/Plan/sponge/src/main/java/com/djrapitops/plan/SpongeTaskSystem.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * This file is part of Player Analytics (Plan). - * - * Plan is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License v3 as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Plan is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Plan. If not, see . - */ -package com.djrapitops.plan; - -import com.djrapitops.plan.delivery.webserver.cache.JSONCache; -import com.djrapitops.plan.extension.ExtensionServerMethodCallerTask; -import com.djrapitops.plan.gathering.ShutdownHook; -import com.djrapitops.plan.gathering.timed.ServerTPSCounter; -import com.djrapitops.plan.gathering.timed.SpongePingCounter; -import com.djrapitops.plan.gathering.timed.SystemUsageBuffer; -import com.djrapitops.plan.gathering.timed.TPSCounter; -import com.djrapitops.plan.settings.config.PlanConfig; -import com.djrapitops.plan.settings.config.paths.DataGatheringSettings; -import com.djrapitops.plan.settings.config.paths.TimeSettings; -import com.djrapitops.plan.settings.upkeep.ConfigStoreTask; -import com.djrapitops.plan.storage.upkeep.DBCleanTask; -import com.djrapitops.plan.storage.upkeep.LogsFolderCleanTask; -import com.djrapitops.plugin.api.TimeAmount; -import com.djrapitops.plugin.task.RunnableFactory; -import org.spongepowered.api.Sponge; -import org.spongepowered.api.scheduler.Task; -import org.spongepowered.api.world.World; - -import javax.inject.Inject; -import javax.inject.Singleton; -import java.util.concurrent.TimeUnit; - -@Singleton -public class SpongeTaskSystem extends TaskSystem { - - private final PlanSponge plugin; - private final PlanConfig config; - private final ShutdownHook shutdownHook; - private final TPSCounter tpsCounter; - private final JSONCache.CleanTask jsonCacheCleanTask; - private final SystemUsageBuffer.RamAndCpuTask ramAndCpuTask; - private final SystemUsageBuffer.DiskTask diskTask; - private final SpongePingCounter pingCounter; - private final LogsFolderCleanTask logsFolderCleanTask; - private final ConfigStoreTask configStoreTask; - private final DBCleanTask dbCleanTask; - private final ExtensionServerMethodCallerTask extensionServerMethodCallerTask; - - @Inject - public SpongeTaskSystem( - PlanSponge plugin, - PlanConfig config, - ShutdownHook shutdownHook, - RunnableFactory runnableFactory, - - ServerTPSCounter tpsCounter, - SpongePingCounter pingCounter, - ExtensionServerMethodCallerTask extensionServerMethodCallerTask, - - LogsFolderCleanTask logsFolderCleanTask, - ConfigStoreTask configStoreTask, - DBCleanTask dbCleanTask, - JSONCache.CleanTask jsonCacheCleanTask, - SystemUsageBuffer.RamAndCpuTask ramAndCpuTask, - SystemUsageBuffer.DiskTask diskTask - ) { - super(runnableFactory); - this.plugin = plugin; - this.config = config; - this.shutdownHook = shutdownHook; - - this.tpsCounter = tpsCounter; - this.pingCounter = pingCounter; - this.extensionServerMethodCallerTask = extensionServerMethodCallerTask; - - this.logsFolderCleanTask = logsFolderCleanTask; - this.configStoreTask = configStoreTask; - this.dbCleanTask = dbCleanTask; - this.jsonCacheCleanTask = jsonCacheCleanTask; - - this.ramAndCpuTask = ramAndCpuTask; - this.diskTask = diskTask; - } - - @Override - public void enable() { - registerTPSCounter(); - registerPingCounter(); - registerExtensionDataGatheringTask(); - registerUpkeepTasks(); - - shutdownHook.register(); - } - - private void registerUpkeepTasks() { - // +40 ticks / 2 seconds so that update check task runs first. - long storeDelay = TimeAmount.toTicks(config.get(TimeSettings.CONFIG_UPDATE_INTERVAL), TimeUnit.MILLISECONDS) + 40; - registerTask(configStoreTask).runTaskLaterAsynchronously(storeDelay); - registerTask(logsFolderCleanTask).runTaskLaterAsynchronously(TimeAmount.toTicks(30L, TimeUnit.SECONDS)); - registerTask(dbCleanTask).runTaskTimerAsynchronously( - TimeAmount.toTicks(20, TimeUnit.SECONDS), - TimeAmount.toTicks(config.get(TimeSettings.CLEAN_DATABASE_PERIOD), TimeUnit.MILLISECONDS) - ); - long minute = TimeAmount.toTicks(1, TimeUnit.MINUTES); - registerTask(jsonCacheCleanTask).runTaskTimerAsynchronously(minute, minute); - } - - private void registerTPSCounter() { - long halfSecondTicks = TimeAmount.toTicks(500L, TimeUnit.MILLISECONDS); - long secondTicks = TimeAmount.toTicks(1L, TimeUnit.SECONDS); - long minuteTicks = TimeAmount.toTicks(1L, TimeUnit.MINUTES); - registerTask(tpsCounter).runTaskTimer(minuteTicks, secondTicks); - registerTask(ramAndCpuTask).runTaskTimerAsynchronously(minuteTicks - halfSecondTicks, secondTicks); - registerTask(diskTask).runTaskTimerAsynchronously(50L * secondTicks, minuteTicks); - } - - private void registerPingCounter() { - Long pingDelay = config.get(TimeSettings.PING_SERVER_ENABLE_DELAY); - if (pingDelay < TimeUnit.HOURS.toMillis(1L) && config.isTrue(DataGatheringSettings.PING)) { - plugin.registerListener(pingCounter); - long startDelay = TimeAmount.toTicks(pingDelay, TimeUnit.MILLISECONDS); - registerTask(pingCounter).runTaskTimer(startDelay, 40L); - } - } - - private void registerExtensionDataGatheringTask() { - long extensionRefreshPeriod = TimeAmount.toTicks(config.get(TimeSettings.EXTENSION_DATA_REFRESH_PERIOD), TimeUnit.MILLISECONDS); - registerTask(extensionServerMethodCallerTask).runTaskTimerAsynchronously( - TimeAmount.toTicks(30, TimeUnit.SECONDS), extensionRefreshPeriod - ); - } - - @Override - public void disable() { - super.disable(); - for (Task task : Sponge.getScheduler().getScheduledTasks(plugin)) { - task.cancel(); - } - } -} diff --git a/Plan/sponge/src/main/java/com/djrapitops/plan/gathering/timed/SpongePingCounter.java b/Plan/sponge/src/main/java/com/djrapitops/plan/gathering/timed/SpongePingCounter.java index 752966128..730d76abf 100644 --- a/Plan/sponge/src/main/java/com/djrapitops/plan/gathering/timed/SpongePingCounter.java +++ b/Plan/sponge/src/main/java/com/djrapitops/plan/gathering/timed/SpongePingCounter.java @@ -23,9 +23,12 @@ */ package com.djrapitops.plan.gathering.timed; +import com.djrapitops.plan.PlanSponge; +import com.djrapitops.plan.TaskSystem; import com.djrapitops.plan.delivery.domain.DateObj; import com.djrapitops.plan.identification.ServerInfo; import com.djrapitops.plan.settings.config.PlanConfig; +import com.djrapitops.plan.settings.config.paths.DataGatheringSettings; import com.djrapitops.plan.settings.config.paths.TimeSettings; import com.djrapitops.plan.storage.database.DBSystem; import com.djrapitops.plan.storage.database.transactions.events.PingStoreTransaction; @@ -46,10 +49,11 @@ import java.util.concurrent.TimeUnit; * * @author BrainStone */ -public class SpongePingCounter extends AbsRunnable { +public class SpongePingCounter extends TaskSystem.Task { private final Map>> playerHistory; + private final PlanSponge plugin; private final PlanConfig config; private final DBSystem dbSystem; private final ServerInfo serverInfo; @@ -57,11 +61,13 @@ public class SpongePingCounter extends AbsRunnable { @Inject public SpongePingCounter( + PlanSponge plugin, PlanConfig config, DBSystem dbSystem, ServerInfo serverInfo, RunnableFactory runnableFactory ) { + this.plugin = plugin; this.config = config; this.dbSystem = dbSystem; this.serverInfo = serverInfo; @@ -98,6 +104,17 @@ public class SpongePingCounter extends AbsRunnable { } } + @Override + public void register(RunnableFactory runnableFactory) { + Long startDelay = config.get(TimeSettings.PING_SERVER_ENABLE_DELAY); + if (startDelay < TimeUnit.HOURS.toMillis(1L) && config.isTrue(DataGatheringSettings.PING)) { + plugin.registerListener(this); + long delay = TimeAmount.toTicks(startDelay, TimeUnit.MILLISECONDS); + long period = 40L; + runnableFactory.create(null, this).runTaskTimer(delay, period); + } + } + public void addPlayer(Player player) { playerHistory.put(player.getUniqueId(), new ArrayList<>()); } diff --git a/Plan/sponge/src/main/java/com/djrapitops/plan/modules/sponge/SpongeSuperClassBindingModule.java b/Plan/sponge/src/main/java/com/djrapitops/plan/modules/sponge/SpongeSuperClassBindingModule.java index 79e438484..68b6e76fd 100644 --- a/Plan/sponge/src/main/java/com/djrapitops/plan/modules/sponge/SpongeSuperClassBindingModule.java +++ b/Plan/sponge/src/main/java/com/djrapitops/plan/modules/sponge/SpongeSuperClassBindingModule.java @@ -17,8 +17,6 @@ package com.djrapitops.plan.modules.sponge; import com.djrapitops.plan.SpongeServerShutdownSave; -import com.djrapitops.plan.SpongeTaskSystem; -import com.djrapitops.plan.TaskSystem; import com.djrapitops.plan.gathering.ServerSensor; import com.djrapitops.plan.gathering.ServerShutdownSave; import com.djrapitops.plan.gathering.SpongeSensor; @@ -56,9 +54,6 @@ public interface SpongeSuperClassBindingModule { @Binds ConfigSystem bindConfigSystem(SpongeConfigSystem configSystem); - @Binds - TaskSystem bindTaskSystem(SpongeTaskSystem taskSystem); - @Binds ListenerSystem bindListenerSystem(SpongeListenerSystem listenerSystem); diff --git a/Plan/sponge/src/main/java/com/djrapitops/plan/modules/sponge/SpongeTaskModule.java b/Plan/sponge/src/main/java/com/djrapitops/plan/modules/sponge/SpongeTaskModule.java new file mode 100644 index 000000000..71421e32e --- /dev/null +++ b/Plan/sponge/src/main/java/com/djrapitops/plan/modules/sponge/SpongeTaskModule.java @@ -0,0 +1,77 @@ +/* + * This file is part of Player Analytics (Plan). + * + * Plan is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License v3 as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Plan is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Plan. If not, see . + */ +package com.djrapitops.plan.modules.sponge; + +import com.djrapitops.plan.TaskSystem; +import com.djrapitops.plan.delivery.webserver.cache.JSONCache; +import com.djrapitops.plan.extension.ExtensionServerDataUpdater; +import com.djrapitops.plan.gathering.ShutdownHook; +import com.djrapitops.plan.gathering.timed.ServerTPSCounter; +import com.djrapitops.plan.gathering.timed.SpongePingCounter; +import com.djrapitops.plan.gathering.timed.SystemUsageBuffer; +import com.djrapitops.plan.settings.upkeep.ConfigStoreTask; +import com.djrapitops.plan.storage.upkeep.DBCleanTask; +import com.djrapitops.plan.storage.upkeep.LogsFolderCleanTask; +import dagger.Binds; +import dagger.Module; +import dagger.multibindings.IntoSet; +import org.spongepowered.api.world.World; + +@Module +public interface SpongeTaskModule { + + @Binds + @IntoSet + TaskSystem.Task bindTPSCounter(ServerTPSCounter tpsCounter); + + @Binds + @IntoSet + TaskSystem.Task bindPingCounter(SpongePingCounter pingCounter); + + @Binds + @IntoSet + TaskSystem.Task bindExtensionServerDataUpdater(ExtensionServerDataUpdater extensionServerDataUpdater); + + @Binds + @IntoSet + TaskSystem.Task bindLogCleanTask(LogsFolderCleanTask logsFolderCleanTask); + + @Binds + @IntoSet + TaskSystem.Task bindConfigStoreTask(ConfigStoreTask configStoreTask); + + @Binds + @IntoSet + TaskSystem.Task bindDBCleanTask(DBCleanTask cleanTask); + + @Binds + @IntoSet + TaskSystem.Task bindJSONCacheCleanTask(JSONCache.CleanTask cleanTask); + + @Binds + @IntoSet + TaskSystem.Task bindRamAndCpuTask(SystemUsageBuffer.RamAndCpuTask ramAndCpuTask); + + @Binds + @IntoSet + TaskSystem.Task bindDiskTask(SystemUsageBuffer.DiskTask diskTask); + + @Binds + @IntoSet + TaskSystem.Task bindShutdownHookRegistration(ShutdownHook.Registrar registrar); + +} diff --git a/Plan/velocity/src/main/java/com/djrapitops/plan/PlanVelocity.java b/Plan/velocity/src/main/java/com/djrapitops/plan/PlanVelocity.java index 1c63fa70d..0df7f707d 100644 --- a/Plan/velocity/src/main/java/com/djrapitops/plan/PlanVelocity.java +++ b/Plan/velocity/src/main/java/com/djrapitops/plan/PlanVelocity.java @@ -102,7 +102,8 @@ public class PlanVelocity extends VelocityPlugin implements PlanPlugin { @Override public void onDisable() { - system.disable(); + cancelAllTasks(); + if (system != null) system.disable(); logger.info(locale.getString(PluginLang.DISABLED)); } diff --git a/Plan/velocity/src/main/java/com/djrapitops/plan/PlanVelocityComponent.java b/Plan/velocity/src/main/java/com/djrapitops/plan/PlanVelocityComponent.java index 2358a2217..f66871f97 100644 --- a/Plan/velocity/src/main/java/com/djrapitops/plan/PlanVelocityComponent.java +++ b/Plan/velocity/src/main/java/com/djrapitops/plan/PlanVelocityComponent.java @@ -21,10 +21,7 @@ import com.djrapitops.plan.modules.APFModule; import com.djrapitops.plan.modules.PlaceholderModule; import com.djrapitops.plan.modules.ProxySuperClassBindingModule; import com.djrapitops.plan.modules.SystemObjectProvidingModule; -import com.djrapitops.plan.modules.velocity.VelocityCommandModule; -import com.djrapitops.plan.modules.velocity.VelocityPlanModule; -import com.djrapitops.plan.modules.velocity.VelocityServerPropertiesModule; -import com.djrapitops.plan.modules.velocity.VelocitySuperClassBindingModule; +import com.djrapitops.plan.modules.velocity.*; import dagger.BindsInstance; import dagger.Component; @@ -45,7 +42,8 @@ import javax.inject.Singleton; ProxySuperClassBindingModule.class, VelocitySuperClassBindingModule.class, - VelocityServerPropertiesModule.class + VelocityServerPropertiesModule.class, + VelocityTaskModule.class }) public interface PlanVelocityComponent { diff --git a/Plan/velocity/src/main/java/com/djrapitops/plan/VelocityTaskSystem.java b/Plan/velocity/src/main/java/com/djrapitops/plan/VelocityTaskSystem.java deleted file mode 100644 index 35d65c287..000000000 --- a/Plan/velocity/src/main/java/com/djrapitops/plan/VelocityTaskSystem.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * This file is part of Player Analytics (Plan). - * - * Plan is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License v3 as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Plan is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Plan. If not, see . - */ -package com.djrapitops.plan; - -import com.djrapitops.plan.delivery.webserver.cache.JSONCache; -import com.djrapitops.plan.extension.ExtensionServerMethodCallerTask; -import com.djrapitops.plan.gathering.timed.ProxyTPSCounter; -import com.djrapitops.plan.gathering.timed.SystemUsageBuffer; -import com.djrapitops.plan.gathering.timed.TPSCounter; -import com.djrapitops.plan.gathering.timed.VelocityPingCounter; -import com.djrapitops.plan.settings.config.PlanConfig; -import com.djrapitops.plan.settings.config.paths.DataGatheringSettings; -import com.djrapitops.plan.settings.config.paths.TimeSettings; -import com.djrapitops.plan.settings.upkeep.NetworkConfigStoreTask; -import com.djrapitops.plan.storage.upkeep.DBCleanTask; -import com.djrapitops.plan.storage.upkeep.LogsFolderCleanTask; -import com.djrapitops.plugin.api.TimeAmount; -import com.djrapitops.plugin.task.RunnableFactory; - -import javax.inject.Inject; -import javax.inject.Singleton; -import java.util.concurrent.TimeUnit; - -/** - * TaskSystem responsible for registering tasks for Velocity. - * - * @author Rsl1122 - */ -@Singleton -public class VelocityTaskSystem extends TaskSystem { - - private final PlanVelocity plugin; - private final PlanConfig config; - private final TPSCounter tpsCounter; - private final VelocityPingCounter pingCounter; - private final LogsFolderCleanTask logsFolderCleanTask; - private final NetworkConfigStoreTask networkConfigStoreTask; - private final DBCleanTask dbCleanTask; - private final JSONCache.CleanTask jsonCacheCleanTask; - private final ExtensionServerMethodCallerTask extensionServerMethodCallerTask; - private final SystemUsageBuffer.RamAndCpuTask ramAndCpuTask; - private final SystemUsageBuffer.DiskTask diskTask; - - @Inject - public VelocityTaskSystem( - PlanVelocity plugin, - PlanConfig config, - RunnableFactory runnableFactory, - ProxyTPSCounter tpsCounter, - VelocityPingCounter pingCounter, - LogsFolderCleanTask logsFolderCleanTask, - NetworkConfigStoreTask networkConfigStoreTask, - DBCleanTask dbCleanTask, - JSONCache.CleanTask jsonCacheCleanTask, - ExtensionServerMethodCallerTask extensionServerMethodCallerTask, - SystemUsageBuffer.RamAndCpuTask ramAndCpuTask, - SystemUsageBuffer.DiskTask diskTask - ) { - super(runnableFactory); - this.plugin = plugin; - this.config = config; - this.tpsCounter = tpsCounter; - this.pingCounter = pingCounter; - this.logsFolderCleanTask = logsFolderCleanTask; - this.networkConfigStoreTask = networkConfigStoreTask; - this.dbCleanTask = dbCleanTask; - this.jsonCacheCleanTask = jsonCacheCleanTask; - this.extensionServerMethodCallerTask = extensionServerMethodCallerTask; - this.ramAndCpuTask = ramAndCpuTask; - this.diskTask = diskTask; - } - - @Override - public void enable() { - registerTasks(); - } - - private void registerTPSCounter() { - long halfSecondTicks = TimeAmount.toTicks(500L, TimeUnit.MILLISECONDS); - long secondTicks = TimeAmount.toTicks(1L, TimeUnit.SECONDS); - long minuteTicks = TimeAmount.toTicks(1L, TimeUnit.MINUTES); - registerTask(tpsCounter).runTaskTimer(minuteTicks, secondTicks); - registerTask(ramAndCpuTask).runTaskTimerAsynchronously(minuteTicks - halfSecondTicks, secondTicks); - registerTask(diskTask).runTaskTimerAsynchronously(50L * secondTicks, minuteTicks); - } - - private void registerTasks() { - registerTPSCounter(); - registerTask(logsFolderCleanTask).runTaskLaterAsynchronously(TimeAmount.toTicks(30L, TimeUnit.SECONDS)); - - Long pingDelay = config.get(TimeSettings.PING_SERVER_ENABLE_DELAY); - if (pingDelay < TimeUnit.HOURS.toMillis(1L) && config.isTrue(DataGatheringSettings.PING)) { - plugin.registerListener(pingCounter); - long startDelay = TimeAmount.toTicks(pingDelay, TimeUnit.MILLISECONDS); - registerTask(pingCounter).runTaskTimer(startDelay, 40L); - } - - // +40 ticks / 2 seconds so that update check task runs first. - long storeDelay = TimeAmount.toTicks(config.get(TimeSettings.CONFIG_UPDATE_INTERVAL), TimeUnit.MILLISECONDS) + 40; - registerTask(networkConfigStoreTask).runTaskLaterAsynchronously(storeDelay); - - registerTask(dbCleanTask).runTaskTimerAsynchronously( - TimeAmount.toTicks(20, TimeUnit.SECONDS), - TimeAmount.toTicks(config.get(TimeSettings.CLEAN_DATABASE_PERIOD), TimeUnit.MILLISECONDS) - ); - long minute = TimeAmount.toTicks(1, TimeUnit.MINUTES); - registerTask(jsonCacheCleanTask).runTaskTimerAsynchronously(minute, minute); - - long extensionRefreshPeriod = TimeAmount.toTicks(config.get(TimeSettings.EXTENSION_DATA_REFRESH_PERIOD), TimeUnit.MILLISECONDS); - registerTask(extensionServerMethodCallerTask).runTaskTimerAsynchronously( - TimeAmount.toTicks(30, TimeUnit.SECONDS), extensionRefreshPeriod - ); - } -} diff --git a/Plan/velocity/src/main/java/com/djrapitops/plan/gathering/timed/VelocityPingCounter.java b/Plan/velocity/src/main/java/com/djrapitops/plan/gathering/timed/VelocityPingCounter.java index d8f1113ea..82251f394 100644 --- a/Plan/velocity/src/main/java/com/djrapitops/plan/gathering/timed/VelocityPingCounter.java +++ b/Plan/velocity/src/main/java/com/djrapitops/plan/gathering/timed/VelocityPingCounter.java @@ -24,9 +24,11 @@ package com.djrapitops.plan.gathering.timed; import com.djrapitops.plan.PlanVelocity; +import com.djrapitops.plan.TaskSystem; import com.djrapitops.plan.delivery.domain.DateObj; import com.djrapitops.plan.identification.ServerInfo; import com.djrapitops.plan.settings.config.PlanConfig; +import com.djrapitops.plan.settings.config.paths.DataGatheringSettings; import com.djrapitops.plan.settings.config.paths.TimeSettings; import com.djrapitops.plan.storage.database.DBSystem; import com.djrapitops.plan.storage.database.transactions.events.PingStoreTransaction; @@ -51,7 +53,7 @@ import java.util.concurrent.TimeUnit; * @author MicleBrick */ @Singleton -public class VelocityPingCounter extends AbsRunnable { +public class VelocityPingCounter extends TaskSystem.Task { final Map>> playerHistory; @@ -106,6 +108,17 @@ public class VelocityPingCounter extends AbsRunnable { } } + @Override + public void register(RunnableFactory runnableFactory) { + Long startDelay = config.get(TimeSettings.PING_SERVER_ENABLE_DELAY); + if (startDelay < TimeUnit.HOURS.toMillis(1L) && config.isTrue(DataGatheringSettings.PING)) { + plugin.registerListener(this); + long delay = TimeAmount.toTicks(startDelay, TimeUnit.MILLISECONDS); + long period = 40L; + runnableFactory.create(null, this).runTaskTimer(delay, period); + } + } + void addPlayer(Player player) { playerHistory.put(player.getUniqueId(), new ArrayList<>()); } diff --git a/Plan/velocity/src/main/java/com/djrapitops/plan/modules/velocity/VelocitySuperClassBindingModule.java b/Plan/velocity/src/main/java/com/djrapitops/plan/modules/velocity/VelocitySuperClassBindingModule.java index 31d8d5dad..c541b33f0 100644 --- a/Plan/velocity/src/main/java/com/djrapitops/plan/modules/velocity/VelocitySuperClassBindingModule.java +++ b/Plan/velocity/src/main/java/com/djrapitops/plan/modules/velocity/VelocitySuperClassBindingModule.java @@ -16,8 +16,6 @@ */ package com.djrapitops.plan.modules.velocity; -import com.djrapitops.plan.TaskSystem; -import com.djrapitops.plan.VelocityTaskSystem; import com.djrapitops.plan.gathering.ServerSensor; import com.djrapitops.plan.gathering.VelocitySensor; import com.djrapitops.plan.gathering.listeners.ListenerSystem; @@ -38,9 +36,6 @@ public interface VelocitySuperClassBindingModule { @Binds ServerInfo bindServerInfo(VelocityServerInfo serverInfo); - @Binds - TaskSystem bindTaskSystem(VelocityTaskSystem taskSystem); - @Binds ListenerSystem bindListenerSystem(VelocityListenerSystem listenerSystem); diff --git a/Plan/velocity/src/main/java/com/djrapitops/plan/modules/velocity/VelocityTaskModule.java b/Plan/velocity/src/main/java/com/djrapitops/plan/modules/velocity/VelocityTaskModule.java new file mode 100644 index 000000000..1a92939a4 --- /dev/null +++ b/Plan/velocity/src/main/java/com/djrapitops/plan/modules/velocity/VelocityTaskModule.java @@ -0,0 +1,71 @@ +/* + * This file is part of Player Analytics (Plan). + * + * Plan is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License v3 as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Plan is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Plan. If not, see . + */ +package com.djrapitops.plan.modules.velocity; + +import com.djrapitops.plan.TaskSystem; +import com.djrapitops.plan.delivery.webserver.cache.JSONCache; +import com.djrapitops.plan.extension.ExtensionServerDataUpdater; +import com.djrapitops.plan.gathering.timed.ProxyTPSCounter; +import com.djrapitops.plan.gathering.timed.SystemUsageBuffer; +import com.djrapitops.plan.gathering.timed.VelocityPingCounter; +import com.djrapitops.plan.settings.upkeep.NetworkConfigStoreTask; +import com.djrapitops.plan.storage.upkeep.DBCleanTask; +import com.djrapitops.plan.storage.upkeep.LogsFolderCleanTask; +import dagger.Binds; +import dagger.Module; +import dagger.multibindings.IntoSet; + +@Module +public interface VelocityTaskModule { + + @Binds + @IntoSet + TaskSystem.Task bindTPSCounter(ProxyTPSCounter counter); + + @Binds + @IntoSet + TaskSystem.Task bindPingCounter(VelocityPingCounter counter); + + @Binds + @IntoSet + TaskSystem.Task bindNetworkConfigStoreTask(NetworkConfigStoreTask configStoreTask); + + @Binds + @IntoSet + TaskSystem.Task bindExtensionServerDataUpdater(ExtensionServerDataUpdater extensionServerDataUpdater); + + @Binds + @IntoSet + TaskSystem.Task bindLogCleanTask(LogsFolderCleanTask logsFolderCleanTask); + + @Binds + @IntoSet + TaskSystem.Task bindDBCleanTask(DBCleanTask cleanTask); + + @Binds + @IntoSet + TaskSystem.Task bindJSONCacheCleanTask(JSONCache.CleanTask cleanTask); + + @Binds + @IntoSet + TaskSystem.Task bindRamAndCpuTask(SystemUsageBuffer.RamAndCpuTask ramAndCpuTask); + + @Binds + @IntoSet + TaskSystem.Task bindDiskTask(SystemUsageBuffer.DiskTask diskTask); + +} From 3ce068e332d9a144868df1d03e1d229d7082a73c Mon Sep 17 00:00:00 2001 From: Risto Lahtela <24460436+Rsl1122@users.noreply.github.com> Date: Fri, 20 Nov 2020 21:18:26 +0200 Subject: [PATCH 08/20] Removed unused WebUserComparator --- .../commands/RemoveWebUserTransaction.java | 3 +- .../comparators/WebUserComparator.java | 35 ------------------- 2 files changed, 1 insertion(+), 37 deletions(-) delete mode 100644 Plan/common/src/main/java/com/djrapitops/plan/utilities/comparators/WebUserComparator.java diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/commands/RemoveWebUserTransaction.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/commands/RemoveWebUserTransaction.java index a7af7c1c8..29a0735e3 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/commands/RemoveWebUserTransaction.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/commands/RemoveWebUserTransaction.java @@ -16,7 +16,6 @@ */ package com.djrapitops.plan.storage.database.transactions.commands; -import com.djrapitops.plan.delivery.domain.WebUser; import com.djrapitops.plan.delivery.webserver.auth.ActiveCookieStore; import com.djrapitops.plan.storage.database.queries.objects.WebUserQueries; import com.djrapitops.plan.storage.database.sql.tables.SecurityTable; @@ -30,7 +29,7 @@ import static com.djrapitops.plan.storage.database.sql.building.Sql.DELETE_FROM; import static com.djrapitops.plan.storage.database.sql.building.Sql.WHERE; /** - * Transaction to remove a Plan {@link WebUser} from the database. + * Transaction to remove a Plan {@link com.djrapitops.plan.delivery.domain.auth.User} from the database. * * @author Rsl1122 */ diff --git a/Plan/common/src/main/java/com/djrapitops/plan/utilities/comparators/WebUserComparator.java b/Plan/common/src/main/java/com/djrapitops/plan/utilities/comparators/WebUserComparator.java deleted file mode 100644 index 856274b15..000000000 --- a/Plan/common/src/main/java/com/djrapitops/plan/utilities/comparators/WebUserComparator.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * This file is part of Player Analytics (Plan). - * - * Plan is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License v3 as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Plan is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Plan. If not, see . - */ -package com.djrapitops.plan.utilities.comparators; - -import com.djrapitops.plan.delivery.domain.WebUser; - -import java.util.Comparator; - -/** - * Orders WebUsers in descending order by permission level. - * - * @author Rsl1122 - */ -public class WebUserComparator implements Comparator { - - @Override - public int compare(WebUser o1, WebUser o2) { - return Integer.compare(o2.getPermLevel(), o1.getPermLevel()); - } - -} From 49868ee590ef0cd1a144e2de333a91e437ee1045 Mon Sep 17 00:00:00 2001 From: Risto Lahtela <24460436+Rsl1122@users.noreply.github.com> Date: Fri, 1 Jan 2021 10:22:50 +0200 Subject: [PATCH 09/20] Added SQLite support for Nukkit Affects issues: - Close #1472 --- Plan/build.gradle | 3 ++- Plan/common/build.gradle | 1 + .../com/djrapitops/plan/settings/NukkitConfigSystem.java | 8 -------- .../java/com/djrapitops/plan/storage/database/H2DB.java | 4 +++- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/Plan/build.gradle b/Plan/build.gradle index 8e3d56f4d..1c0d5493f 100644 --- a/Plan/build.gradle +++ b/Plan/build.gradle @@ -84,6 +84,7 @@ subprojects { ext.caffeineVersion = "2.8.0" ext.h2Version = "1.4.199" ext.mysqlVersion = "8.0.22" + ext.sqliteVersion = "3.34.0" ext.hikariVersion = "3.4.5" ext.slf4jVersion = "1.7.30" ext.geoIpVersion = "2.15.0" @@ -140,7 +141,7 @@ subprojects { testCompile "com.jayway.awaitility:awaitility:1.7.0" // Awaitility (Concurrent wait conditions) // Testing dependencies required by Plan - testCompile "org.xerial:sqlite-jdbc:3.34.0" // SQLite + testCompile "org.xerial:sqlite-jdbc:$sqliteVersion" // SQLite testCompile "mysql:mysql-connector-java:$mysqlVersion" // MySQL } diff --git a/Plan/common/build.gradle b/Plan/common/build.gradle index 0cb11f3c9..21cad48e7 100644 --- a/Plan/common/build.gradle +++ b/Plan/common/build.gradle @@ -10,6 +10,7 @@ dependencies { compile "com.github.ben-manes.caffeine:caffeine:$caffeineVersion" compile "com.h2database:h2:$h2Version" compile "mysql:mysql-connector-java:$mysqlVersion" + compile "org.xerial:sqlite-jdbc:$sqliteVersion" compile "com.zaxxer:HikariCP:$hikariVersion" compile "org.slf4j:slf4j-nop:$slf4jVersion" compile "org.slf4j:slf4j-api:$slf4jVersion" diff --git a/Plan/common/src/main/java/com/djrapitops/plan/settings/NukkitConfigSystem.java b/Plan/common/src/main/java/com/djrapitops/plan/settings/NukkitConfigSystem.java index 75a15d9f6..26810afb1 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/settings/NukkitConfigSystem.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/settings/NukkitConfigSystem.java @@ -19,7 +19,6 @@ package com.djrapitops.plan.settings; import com.djrapitops.plan.settings.config.ConfigReader; import com.djrapitops.plan.settings.config.PlanConfig; import com.djrapitops.plan.settings.config.changes.ConfigUpdater; -import com.djrapitops.plan.settings.config.paths.DatabaseSettings; import com.djrapitops.plan.settings.config.paths.PluginSettings; import com.djrapitops.plan.settings.network.ServerSettingsManager; import com.djrapitops.plan.settings.theme.Theme; @@ -43,7 +42,6 @@ public class NukkitConfigSystem extends ConfigSystem { private final ConfigUpdater configUpdater; private final ServerSettingsManager serverSettingsManager; - private boolean firstInstall; @Inject public NukkitConfigSystem( @@ -62,7 +60,6 @@ public class NukkitConfigSystem extends ConfigSystem { @Override public void enable() { - firstInstall = !files.getConfigFile().exists(); super.enable(); if (config.isTrue(PluginSettings.PROXY_COPY_CONFIG)) { serverSettingsManager.enable(); @@ -81,10 +78,5 @@ public class NukkitConfigSystem extends ConfigSystem { try (ConfigReader reader = new ConfigReader(files.getResourceFromJar("config.yml").asInputStream())) { config.copyMissing(reader.read()); } - String dbType = config.get(DatabaseSettings.TYPE); - if ("sqlite".equalsIgnoreCase(dbType)) { - if (!firstInstall) logger.warn("'SQLite' is not supported on Nukkit, switching to 'H2'."); - config.set(DatabaseSettings.TYPE, "H2"); - } } } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/H2DB.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/H2DB.java index a0414894c..e626e8092 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/H2DB.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/H2DB.java @@ -99,8 +99,10 @@ public class H2DB extends SQLDB { private void startConnectionPingTask() { stopConnectionPingTask(); - logger.warn("H2 database is going to be deprecated in version 5.2. It is recommended to move to MySQL or SQLite when possible."); + logger.warn("! ! ! ---------- ! ! !"); + logger.warn("H2 database is DEPRECATED and WILL STOP WORKING in version 5.4 - It is recommended to move to MySQL or SQLite when possible."); logger.warn("See https://github.com/plan-player-analytics/Plan/issues/1472 for details"); + logger.warn("! ! ! ---------- ! ! !"); try { // Maintains Connection. connectionPingTask = runnableFactory.create("DBConnectionPingTask " + getType().getName(), From 7f8fd7d235ac3a26c6d1d6e1e3aab9ae5926443f Mon Sep 17 00:00:00 2001 From: Risto Lahtela <24460436+Rsl1122@users.noreply.github.com> Date: Fri, 1 Jan 2021 10:24:10 +0200 Subject: [PATCH 10/20] Bump version to 5.2 --- Plan/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Plan/build.gradle b/Plan/build.gradle index 1c0d5493f..c5df377e9 100644 --- a/Plan/build.gradle +++ b/Plan/build.gradle @@ -33,10 +33,10 @@ allprojects { wrapper.gradleVersion = "6.2.1" group "com.djrapitops" - version "5.1-SNAPSHOT" + version "5.2-SNAPSHOT" ext.majorVersion = '5' - ext.minorVersion = '1' + ext.minorVersion = '2' ext.buildVersion = buildVersion ext.fullVersion = project.ext.majorVersion + '.' + project.ext.minorVersion + ' build ' + project.ext.buildVersion From 9b692480dac00c74dc78941bc9bac6c52eb706f4 Mon Sep 17 00:00:00 2001 From: Risto Lahtela <24460436+Rsl1122@users.noreply.github.com> Date: Fri, 1 Jan 2021 11:26:07 +0200 Subject: [PATCH 11/20] Patch proxy server detection - Added a field is_proxy to plan_servers - Patch to populate the new field - Field is set to true when proxy enables to fix any broken data - Allows any name for a proxy - Updated server save queries - Changed isProxy method in Server.java to match the change - Changed query for fetching the proxy server Affects issues: - Close #1678 --- .../plan/identification/BungeeServerInfo.java | 4 +- .../plan/identification/Server.java | 12 +++- .../storage/ServerFileLoader.java | 4 +- .../plan/storage/database/SQLDB.java | 3 +- .../database/queries/LargeStoreQueries.java | 12 ++-- .../queries/objects/ServerQueries.java | 36 ++++++++++-- .../database/sql/tables/ServerTable.java | 7 ++- .../StoreServerInformationTransaction.java | 6 +- .../patches/ServerIsProxyPatch.java | 56 +++++++++++++++++++ .../database/queries/ServerQueriesTest.java | 1 + .../identification/VelocityServerInfo.java | 6 +- 11 files changed, 123 insertions(+), 24 deletions(-) create mode 100644 Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/ServerIsProxyPatch.java diff --git a/Plan/bungeecord/src/main/java/com/djrapitops/plan/identification/BungeeServerInfo.java b/Plan/bungeecord/src/main/java/com/djrapitops/plan/identification/BungeeServerInfo.java index 15737d19b..5751d2fdc 100644 --- a/Plan/bungeecord/src/main/java/com/djrapitops/plan/identification/BungeeServerInfo.java +++ b/Plan/bungeecord/src/main/java/com/djrapitops/plan/identification/BungeeServerInfo.java @@ -67,6 +67,8 @@ public class BungeeServerInfo extends ServerInfo { this.server = fromFile.load(null).orElseGet(() -> fromDatabase.load(null) .orElseGet(this::registerServer)); + this.server.setProxy(true); // Ensure isProxy if loaded from file + processing.submitNonCritical(this::updateStorage); } @@ -112,6 +114,6 @@ public class BungeeServerInfo extends ServerInfo { private Server createServerObject() { UUID serverUUID = generateNewUUID(); String accessAddress = addresses.getAccessAddress().orElseThrow(() -> new EnableException("Velocity can not have '0.0.0.0' or '' as an address. Set up 'Server.IP' setting.")); - return new Server(-1, serverUUID, "BungeeCord", accessAddress); + return new Server(-1, serverUUID, "BungeeCord", accessAddress, true); } } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/identification/Server.java b/Plan/common/src/main/java/com/djrapitops/plan/identification/Server.java index dc0760266..f656fbb26 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/identification/Server.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/identification/Server.java @@ -30,16 +30,18 @@ public class Server implements Comparable { private Integer id; private String name; private String webAddress; + private boolean proxy; public Server(UUID uuid, String name, String webAddress) { - this(null, uuid, name, webAddress); + this(null, uuid, name, webAddress, false); } - public Server(Integer id, UUID uuid, String name, String webAddress) { + public Server(Integer id, UUID uuid, String name, String webAddress, boolean proxy) { this.id = id; this.uuid = uuid; this.name = name; this.webAddress = webAddress; + this.proxy = proxy; } public Optional getId() { @@ -105,7 +107,11 @@ public class Server implements Comparable { } public boolean isProxy() { - return "BungeeCord".equals(name); + return proxy; + } + + public void setProxy(boolean proxy) { + this.proxy = proxy; } public boolean isNotProxy() { diff --git a/Plan/common/src/main/java/com/djrapitops/plan/identification/storage/ServerFileLoader.java b/Plan/common/src/main/java/com/djrapitops/plan/identification/storage/ServerFileLoader.java index c515675da..2f048849d 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/identification/storage/ServerFileLoader.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/identification/storage/ServerFileLoader.java @@ -72,10 +72,10 @@ public class ServerFileLoader extends Config implements ServerLoader { UUID serverUUID = UUID.fromString(serverUUIDString); String name = config.getNode(PluginSettings.SERVER_NAME.getPath()) .map(ConfigNode::getString) - .orElse("BungeeCord"); + .orElse("Proxy"); String address = getString("Server.Web_address"); - return Optional.of(new Server(id, serverUUID, name, address)); + return Optional.of(new Server(id, serverUUID, name, address, false)); } catch (IOException e) { throw new EnableException("Failed to read ServerInfoFile.yml: " + e.getMessage()); } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/SQLDB.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/SQLDB.java index f2509d95b..8152ef900 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/SQLDB.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/SQLDB.java @@ -173,7 +173,8 @@ public abstract class SQLDB extends AbstractDatabase { new BadNukkitRegisterValuePatch(), new LinkedToSecurityTablePatch(), new LinkUsersToPlayersSecurityTablePatch(), - new LitebansTableHeaderPatch() + new LitebansTableHeaderPatch(), + new ServerIsProxyPatch() }; } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/queries/LargeStoreQueries.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/queries/LargeStoreQueries.java index 8c960ec8c..9378901c5 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/queries/LargeStoreQueries.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/queries/LargeStoreQueries.java @@ -151,19 +151,17 @@ public class LargeStoreQueries { return new ExecBatchStatement(ServerTable.INSERT_STATEMENT) { @Override public void prepare(PreparedStatement statement) throws SQLException { - for (Server info : servers) { - UUID uuid = info.getUuid(); - String name = info.getName(); - String webAddress = info.getWebAddress(); - + for (Server server : servers) { + UUID uuid = server.getUuid(); if (uuid == null) { continue; } statement.setString(1, uuid.toString()); - statement.setString(2, name); - statement.setString(3, webAddress); + statement.setString(2, server.getName()); + statement.setString(3, server.getWebAddress()); statement.setBoolean(4, true); + statement.setBoolean(5, server.isProxy()); statement.addBatch(); } } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/queries/objects/ServerQueries.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/queries/objects/ServerQueries.java index 58b731e8a..d8b6f5cb2 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/queries/objects/ServerQueries.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/queries/objects/ServerQueries.java @@ -65,7 +65,9 @@ public class ServerQueries { set.getInt(ServerTable.SERVER_ID), serverUUID, set.getString(ServerTable.NAME), - set.getString(ServerTable.WEB_ADDRESS))); + set.getString(ServerTable.WEB_ADDRESS), + set.getBoolean(ServerTable.PROXY) + )); } return servers; } @@ -106,7 +108,8 @@ public class ServerQueries { set.getInt(ServerTable.SERVER_ID), UUID.fromString(set.getString(ServerTable.SERVER_UUID)), set.getString(ServerTable.NAME), - set.getString(ServerTable.WEB_ADDRESS) + set.getString(ServerTable.WEB_ADDRESS), + set.getBoolean(ServerTable.PROXY) )); } return Optional.empty(); @@ -115,7 +118,31 @@ public class ServerQueries { } public static Query> fetchProxyServerInformation() { - return db -> db.query(fetchServerMatchingIdentifier("BungeeCord")); + String sql = SELECT + '*' + FROM + ServerTable.TABLE_NAME + + WHERE + ServerTable.INSTALLED + "=?" + + AND + ServerTable.PROXY + "=?" + + " LIMIT 1"; + return new QueryStatement>(sql) { + @Override + public void prepare(PreparedStatement statement) throws SQLException { + statement.setBoolean(1, true); + statement.setBoolean(2, true); + } + + @Override + public Optional processResults(ResultSet set) throws SQLException { + if (set.next()) { + return Optional.of(new Server( + set.getInt(ServerTable.SERVER_ID), + UUID.fromString(set.getString(ServerTable.SERVER_UUID)), + set.getString(ServerTable.NAME), + set.getString(ServerTable.WEB_ADDRESS), + set.getBoolean(ServerTable.PROXY) + )); + } + return Optional.empty(); + } + }; } public static Query> fetchServerNames() { @@ -165,7 +192,8 @@ public class ServerQueries { set.getInt(ServerTable.SERVER_ID), UUID.fromString(set.getString(ServerTable.SERVER_UUID)), set.getString(ServerTable.NAME), - set.getString(ServerTable.WEB_ADDRESS) + set.getString(ServerTable.WEB_ADDRESS), + set.getBoolean(ServerTable.PROXY) )); } return matches; diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/sql/tables/ServerTable.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/sql/tables/ServerTable.java index cdfbd0e7c..bbd64aeff 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/sql/tables/ServerTable.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/sql/tables/ServerTable.java @@ -40,18 +40,20 @@ public class ServerTable { public static final String NAME = "name"; public static final String WEB_ADDRESS = "web_address"; public static final String INSTALLED = "is_installed"; + public static final String PROXY = "is_proxy"; @Deprecated public static final String MAX_PLAYERS = "max_players"; public static final String INSERT_STATEMENT = Insert.values(TABLE_NAME, SERVER_UUID, NAME, - WEB_ADDRESS, INSTALLED); + WEB_ADDRESS, INSTALLED, PROXY); public static final String UPDATE_STATEMENT = Update.values(TABLE_NAME, SERVER_UUID, NAME, WEB_ADDRESS, - INSTALLED) + INSTALLED, + PROXY) .where(SERVER_UUID + "=?") .toString(); @@ -71,6 +73,7 @@ public class ServerTable { .column(NAME, Sql.varchar(100)) .column(WEB_ADDRESS, Sql.varchar(100)) .column(INSTALLED, Sql.BOOL).notNull().defaultValue(true) + .column(PROXY, Sql.BOOL).notNull().defaultValue(false) .column(MAX_PLAYERS, Sql.INT).notNull().defaultValue("-1") .toString(); } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/StoreServerInformationTransaction.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/StoreServerInformationTransaction.java index 3bf1e3129..4ea284de4 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/StoreServerInformationTransaction.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/StoreServerInformationTransaction.java @@ -25,7 +25,7 @@ import static com.djrapitops.plan.storage.database.sql.tables.ServerTable.INSERT import static com.djrapitops.plan.storage.database.sql.tables.ServerTable.UPDATE_STATEMENT; /** - * Transaction for keeping Plan Server serverrmation up to date in the database. + * Transaction for keeping Plan Server information up to date in the database. * * @author Rsl1122 */ @@ -53,7 +53,8 @@ public class StoreServerInformationTransaction extends Transaction { statement.setString(2, server.getName()); statement.setString(3, server.getWebAddress()); statement.setBoolean(4, true); - statement.setString(5, serverUUIDString); + statement.setBoolean(5, server.isProxy()); + statement.setString(6, serverUUIDString); } }; } @@ -66,6 +67,7 @@ public class StoreServerInformationTransaction extends Transaction { statement.setString(2, server.getName()); statement.setString(3, server.getWebAddress()); statement.setBoolean(4, true); + statement.setBoolean(5, server.isProxy()); } }; } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/ServerIsProxyPatch.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/ServerIsProxyPatch.java new file mode 100644 index 000000000..3f0392231 --- /dev/null +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/ServerIsProxyPatch.java @@ -0,0 +1,56 @@ +/* + * This file is part of Player Analytics (Plan). + * + * Plan is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License v3 as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Plan is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Plan. If not, see . + */ +package com.djrapitops.plan.storage.database.transactions.patches; + +import com.djrapitops.plan.storage.database.sql.building.Sql; +import com.djrapitops.plan.storage.database.sql.tables.ServerTable; +import com.djrapitops.plan.storage.database.transactions.ExecStatement; + +import java.sql.PreparedStatement; +import java.sql.SQLException; + +import static com.djrapitops.plan.storage.database.sql.building.Sql.WHERE; + +/** + * Adds a is_proxy field to remove technical debt assuming name field "BungeeCord" being the proxy. + *

+ * See https://github.com/plan-player-analytics/Plan/issues/1678 for more details + * + * @author Rsl1122 + */ +public class ServerIsProxyPatch extends Patch { + + @Override + public boolean hasBeenApplied() { + return hasColumn(ServerTable.TABLE_NAME, ServerTable.PROXY); + } + + @Override + protected void applyPatch() { + addColumn(ServerTable.TABLE_NAME, ServerTable.PROXY + ' ' + Sql.BOOL + " DEFAULT 0"); + + String populateFieldSql = "UPDATE " + ServerTable.TABLE_NAME + " SET " + ServerTable.PROXY + "=?" + + WHERE + ServerTable.NAME + "=?"; + execute(new ExecStatement(populateFieldSql) { + @Override + public void prepare(PreparedStatement statement) throws SQLException { + statement.setBoolean(1, true); + statement.setString(2, "BungeeCord"); + } + }); + } +} diff --git a/Plan/common/src/test/java/com/djrapitops/plan/storage/database/queries/ServerQueriesTest.java b/Plan/common/src/test/java/com/djrapitops/plan/storage/database/queries/ServerQueriesTest.java index 123cd3337..2b97ca0b0 100644 --- a/Plan/common/src/test/java/com/djrapitops/plan/storage/database/queries/ServerQueriesTest.java +++ b/Plan/common/src/test/java/com/djrapitops/plan/storage/database/queries/ServerQueriesTest.java @@ -57,6 +57,7 @@ public interface ServerQueriesTest extends DatabaseTestPreparer { UUID bungeeUUID = UUID.randomUUID(); Server bungeeCord = new Server(bungeeUUID, "BungeeCord", "Random:1234"); + bungeeCord.setProxy(true); db().executeTransaction(new StoreServerInformationTransaction(bungeeCord)); forcePersistenceCheck(); diff --git a/Plan/velocity/src/main/java/com/djrapitops/plan/identification/VelocityServerInfo.java b/Plan/velocity/src/main/java/com/djrapitops/plan/identification/VelocityServerInfo.java index e8c7b4ef7..9b6f2c041 100644 --- a/Plan/velocity/src/main/java/com/djrapitops/plan/identification/VelocityServerInfo.java +++ b/Plan/velocity/src/main/java/com/djrapitops/plan/identification/VelocityServerInfo.java @@ -66,6 +66,8 @@ public class VelocityServerInfo extends ServerInfo { this.server = fromFile.load(null).orElseGet(() -> fromDatabase.load(null) .orElseGet(this::registerServer)); + this.server.setProxy(true); // Ensure isProxy if loaded from file + processing.submitNonCritical(this::updateStorage); } @@ -108,7 +110,7 @@ public class VelocityServerInfo extends ServerInfo { private Server createServerObject() { UUID serverUUID = generateNewUUID(); String accessAddress = addresses.getAccessAddress().orElseThrow(() -> new EnableException("Velocity can not have '0.0.0.0' or '' as an address. Set up 'Server.IP' setting.")); - // TODO Rework to allow Velocity as a name - return new Server(-1, serverUUID, "BungeeCord", accessAddress); + + return new Server(-1, serverUUID, "Velocity", accessAddress, true); } } From 47633cad37f2e7d8008df90caec389a78a4e94e1 Mon Sep 17 00:00:00 2001 From: Risto Lahtela <24460436+Rsl1122@users.noreply.github.com> Date: Fri, 1 Jan 2021 11:31:40 +0200 Subject: [PATCH 12/20] Updated javadoc for database Patches --- .../patches/CommandUsageTableRemovalPatch.java | 2 ++ .../transactions/patches/DeleteIPsPatch.java | 2 ++ .../transactions/patches/DiskUsagePatch.java | 5 +++++ .../patches/ExtensionTableRowValueLengthPatch.java | 5 +++++ .../transactions/patches/GeoInfoLastUsedPatch.java | 5 +++++ .../patches/GeoInfoOptimizationPatch.java | 5 +++++ .../transactions/patches/KillsOptimizationPatch.java | 7 +++++++ .../transactions/patches/KillsServerIDPatch.java | 8 ++++++++ .../LinkUsersToPlayersSecurityTablePatch.java | 6 ++++++ .../patches/LinkedToSecurityTablePatch.java | 8 ++++++++ .../transactions/patches/NicknameLastSeenPatch.java | 7 +++++++ .../patches/NicknamesOptimizationPatch.java | 7 +++++++ .../transactions/patches/PingOptimizationPatch.java | 5 +++++ .../patches/RegisterDateMinimizationPatch.java | 9 +++++++++ .../transactions/patches/SessionAFKTimePatch.java | 5 +++++ .../patches/SessionsOptimizationPatch.java | 7 +++++++ .../patches/TransferTableRemovalPatch.java | 7 +++++++ .../patches/UserInfoOptimizationPatch.java | 5 +++++ .../transactions/patches/Version10Patch.java | 12 ++++++++++++ .../patches/VersionTableRemovalPatch.java | 5 +++++ .../patches/WorldTimesOptimizationPatch.java | 7 +++++++ .../transactions/patches/WorldTimesSeverIDPatch.java | 6 ++++++ .../patches/WorldsOptimizationPatch.java | 7 +++++++ .../transactions/patches/WorldsServerIDPatch.java | 6 ++++++ 24 files changed, 148 insertions(+) diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/CommandUsageTableRemovalPatch.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/CommandUsageTableRemovalPatch.java index fb7688156..598bd4800 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/CommandUsageTableRemovalPatch.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/CommandUsageTableRemovalPatch.java @@ -18,6 +18,8 @@ package com.djrapitops.plan.storage.database.transactions.patches; /** * Patch that removes plan_commandusages table. + *

+ * See https://github.com/plan-player-analytics/Plan/issues/1240 for more details * * @author Rsl1122 */ diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/DeleteIPsPatch.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/DeleteIPsPatch.java index 914455227..fb1dba128 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/DeleteIPsPatch.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/DeleteIPsPatch.java @@ -26,6 +26,8 @@ import static com.djrapitops.plan.storage.database.sql.building.Sql.*; /** * Patch that replaces plan_ips with plan_geolocations table. + *

+ * Prepares Plan to be GDPR compliant through the easiest to make change. * * @author Rsl1122 */ diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/DiskUsagePatch.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/DiskUsagePatch.java index 7136d3594..63220549b 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/DiskUsagePatch.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/DiskUsagePatch.java @@ -18,6 +18,11 @@ package com.djrapitops.plan.storage.database.transactions.patches; import com.djrapitops.plan.storage.database.sql.tables.TPSTable; +/** + * Adds disk usage information to tps table. + * + * @author Rsl1122 + */ public class DiskUsagePatch extends Patch { @Override diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/ExtensionTableRowValueLengthPatch.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/ExtensionTableRowValueLengthPatch.java index 20a2053af..589bd8a11 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/ExtensionTableRowValueLengthPatch.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/ExtensionTableRowValueLengthPatch.java @@ -23,6 +23,11 @@ import com.djrapitops.plan.storage.database.sql.building.Sql; import com.djrapitops.plan.storage.database.sql.tables.ExtensionPlayerTableValueTable; import com.djrapitops.plan.storage.database.sql.tables.ExtensionServerTableValueTable; +/** + * Increases the length of Strings in extension tables to 250 to avoid cutoffs and exceptions. + * + * @author Rsl1122 + */ public class ExtensionTableRowValueLengthPatch extends Patch { private final String playerTable; diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/GeoInfoLastUsedPatch.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/GeoInfoLastUsedPatch.java index 5e605de1f..9237ea7d2 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/GeoInfoLastUsedPatch.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/GeoInfoLastUsedPatch.java @@ -18,6 +18,11 @@ package com.djrapitops.plan.storage.database.transactions.patches; import com.djrapitops.plan.storage.database.sql.tables.GeoInfoTable; +/** + * Adds last_used field to the geolocation table. + * + * @author Rsl1122 + */ public class GeoInfoLastUsedPatch extends Patch { @Override diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/GeoInfoOptimizationPatch.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/GeoInfoOptimizationPatch.java index 00c2cb0f7..876b3e52e 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/GeoInfoOptimizationPatch.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/GeoInfoOptimizationPatch.java @@ -20,6 +20,11 @@ import com.djrapitops.plan.storage.database.sql.tables.GeoInfoTable; import static com.djrapitops.plan.storage.database.sql.building.Sql.*; +/** + * Replaces user_id foreign keys with user_uuid fields in geolocation table. + * + * @author Rsl1122 + */ public class GeoInfoOptimizationPatch extends Patch { private final String tempTableName; diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/KillsOptimizationPatch.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/KillsOptimizationPatch.java index e99880f98..8e47a026e 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/KillsOptimizationPatch.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/KillsOptimizationPatch.java @@ -21,6 +21,13 @@ import com.djrapitops.plan.storage.database.sql.tables.KillsTable; import static com.djrapitops.plan.storage.database.sql.building.Sql.FROM; +/** + * Replaces killer_id, victim_id and server_id foreign keys with respective uuid fields in kills table. + *

+ * This was to "reduce the amount of joins when querying sessions". + * + * @author Rsl1122 + */ public class KillsOptimizationPatch extends Patch { private final String tempTableName; diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/KillsServerIDPatch.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/KillsServerIDPatch.java index 7fd556136..836b4df3f 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/KillsServerIDPatch.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/KillsServerIDPatch.java @@ -24,6 +24,14 @@ import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.Map; +/** + * Adds server_id field to kills table. + *

+ * The field is populated by querying the session table for server ids. + * + * @author Rsl1122 + * @see KillsOptimizationPatch for removal of this field later + */ public class KillsServerIDPatch extends Patch { @Override diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/LinkUsersToPlayersSecurityTablePatch.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/LinkUsersToPlayersSecurityTablePatch.java index f6bf20cc5..2ee06df20 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/LinkUsersToPlayersSecurityTablePatch.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/LinkUsersToPlayersSecurityTablePatch.java @@ -31,6 +31,12 @@ import java.util.Map; import static com.djrapitops.plan.storage.database.sql.building.Sql.*; +/** + * Populates new linked_to_uuid field with the uuid of a username (same as minecraft name) or 'console'. + * + * @author Rsl1122 + * @see LinkedToSecurityTablePatch for addition of the field. + */ public class LinkUsersToPlayersSecurityTablePatch extends Patch { @Override diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/LinkedToSecurityTablePatch.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/LinkedToSecurityTablePatch.java index 5c32cd9db..b82f37781 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/LinkedToSecurityTablePatch.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/LinkedToSecurityTablePatch.java @@ -19,6 +19,14 @@ package com.djrapitops.plan.storage.database.transactions.patches; import com.djrapitops.plan.storage.database.sql.building.Sql; import com.djrapitops.plan.storage.database.sql.tables.SecurityTable; +/** + * Adds linked_to_uuid field to plan_security table that stores web users. + *

+ * This patch allows web users to have a username other than the minecraft username. + * + * @author Rsl1122 + * @see LinkUsersToPlayersSecurityTablePatch for the patch that populates the field afterwards. + */ public class LinkedToSecurityTablePatch extends Patch { @Override diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/NicknameLastSeenPatch.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/NicknameLastSeenPatch.java index 9cb0b6e40..727c32004 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/NicknameLastSeenPatch.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/NicknameLastSeenPatch.java @@ -35,6 +35,13 @@ import java.util.UUID; import static com.djrapitops.plan.storage.database.sql.building.Sql.AND; import static com.djrapitops.plan.storage.database.sql.building.Sql.WHERE; +/** + * Adds last_seen to nickname table by populating it with the data in actions table, and removes the actions table. + *

+ * Actions table contained nickname change events and change to "last seen" saved space on the interface. + * + * @author Rsl1122 + */ public class NicknameLastSeenPatch extends Patch { @Override diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/NicknamesOptimizationPatch.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/NicknamesOptimizationPatch.java index 7b7694522..576df014c 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/NicknamesOptimizationPatch.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/NicknamesOptimizationPatch.java @@ -21,6 +21,13 @@ import com.djrapitops.plan.storage.database.sql.tables.NicknamesTable; import static com.djrapitops.plan.storage.database.sql.building.Sql.FROM; +/** + * Replaces user_id and server_id foreign keys with respective uuid fields in nickname table. + *

+ * This was to "reduce the amount of joins when querying sessions". + * + * @author Rsl1122 + */ public class NicknamesOptimizationPatch extends Patch { private final String tempTableName; diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/PingOptimizationPatch.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/PingOptimizationPatch.java index d2e0a5051..2bed7af7b 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/PingOptimizationPatch.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/PingOptimizationPatch.java @@ -21,6 +21,11 @@ import com.djrapitops.plan.storage.database.sql.tables.PingTable; import static com.djrapitops.plan.storage.database.sql.building.Sql.FROM; +/** + * Replaces user_id and server_id foreign keys with respective uuid fields in ping table. + * + * @author Rsl1122 + */ public class PingOptimizationPatch extends Patch { private final String tempTableName; diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/RegisterDateMinimizationPatch.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/RegisterDateMinimizationPatch.java index 0e2993437..d2f519696 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/RegisterDateMinimizationPatch.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/RegisterDateMinimizationPatch.java @@ -31,6 +31,15 @@ import java.util.UUID; import static com.djrapitops.plan.storage.database.sql.building.Sql.*; +/** + * Changes register dates on networks to the smallest number found in the database. + *

+ * Proxy servers do not store player register date information, so Game servers can hold earlier + * join date than the first session Plan sees. This patch changes the register date in + * plan_users if a smaller register date in plan_user_info is found. + * + * @author Rsl1122 + */ public class RegisterDateMinimizationPatch extends Patch { private Map registerDates; diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/SessionAFKTimePatch.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/SessionAFKTimePatch.java index d46280a3f..a2bdeeab9 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/SessionAFKTimePatch.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/SessionAFKTimePatch.java @@ -18,6 +18,11 @@ package com.djrapitops.plan.storage.database.transactions.patches; import com.djrapitops.plan.storage.database.sql.tables.SessionsTable; +/** + * Adds afk_time field to sessions table. + * + * @author Rsl1122 + */ public class SessionAFKTimePatch extends Patch { @Override diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/SessionsOptimizationPatch.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/SessionsOptimizationPatch.java index 5ac9d857a..b621c8153 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/SessionsOptimizationPatch.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/SessionsOptimizationPatch.java @@ -21,6 +21,13 @@ import com.djrapitops.plan.storage.database.sql.tables.SessionsTable; import static com.djrapitops.plan.storage.database.sql.building.Sql.FROM; +/** + * Replaces user_id and server_id foreign keys with respective uuid fields in sessions table. + *

+ * This was to "reduce the amount of joins when querying sessions". + * + * @author Rsl1122 + */ public class SessionsOptimizationPatch extends Patch { private final String tempTableName; diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/TransferTableRemovalPatch.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/TransferTableRemovalPatch.java index 8fad3d5f5..df789dee8 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/TransferTableRemovalPatch.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/TransferTableRemovalPatch.java @@ -16,6 +16,13 @@ */ package com.djrapitops.plan.storage.database.transactions.patches; +/** + * Removes plan_transfer table, used for transferring html in the database. + *

+ * The idea turned out to use a lot of disk space and improper use of a database. + * + * @author Rsl1122 + */ public class TransferTableRemovalPatch extends Patch { @Override diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/UserInfoOptimizationPatch.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/UserInfoOptimizationPatch.java index 99da74d4d..985734745 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/UserInfoOptimizationPatch.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/UserInfoOptimizationPatch.java @@ -21,6 +21,11 @@ import com.djrapitops.plan.storage.database.sql.tables.UserInfoTable; import static com.djrapitops.plan.storage.database.sql.building.Sql.FROM; +/** + * Replaces user_id and server_id foreign keys with respective uuid fields in user info table. + * + * @author Rsl1122 + */ public class UserInfoOptimizationPatch extends Patch { private final String tempTableName; diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/Version10Patch.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/Version10Patch.java index 8f6e5b661..38ee6b47e 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/Version10Patch.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/Version10Patch.java @@ -24,6 +24,18 @@ import java.util.Optional; import static com.djrapitops.plan.storage.database.sql.building.Sql.FROM; +/** + * Table schema change patch for version 4.0.0 to support BungeeCord servers. + *

+ * This patch makes the database compatible with further changes to the schema, + * bugs in this patch are possible, as the patch is untested against new schema. + *

+ * Version 10 comes from "schema version" that was in use in the database to version changes + * before Patch system was implemented. + * + * @author Rsl1122 + * @see VersionTableRemovalPatch for Patch that removes the schema versions + */ public class Version10Patch extends Patch { private Integer serverID; diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/VersionTableRemovalPatch.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/VersionTableRemovalPatch.java index 34d18a32d..d34770e02 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/VersionTableRemovalPatch.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/VersionTableRemovalPatch.java @@ -16,6 +16,11 @@ */ package com.djrapitops.plan.storage.database.transactions.patches; +/** + * Removes the table schema versioning table. + * + * @author Rsl1122 + */ public class VersionTableRemovalPatch extends Patch { @Override diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/WorldTimesOptimizationPatch.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/WorldTimesOptimizationPatch.java index 5798ecb8e..288edb47f 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/WorldTimesOptimizationPatch.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/WorldTimesOptimizationPatch.java @@ -21,6 +21,13 @@ import com.djrapitops.plan.storage.database.sql.tables.WorldTimesTable; import static com.djrapitops.plan.storage.database.sql.building.Sql.FROM; +/** + * Replaces server_id foreign keys with server_uuid field in world times table. + *

+ * This was to "reduce the amount of joins when querying sessions". + * + * @author Rsl1122 + */ public class WorldTimesOptimizationPatch extends Patch { private final String tempTableName; diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/WorldTimesSeverIDPatch.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/WorldTimesSeverIDPatch.java index 1e32822e8..56fc21332 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/WorldTimesSeverIDPatch.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/WorldTimesSeverIDPatch.java @@ -26,6 +26,12 @@ import java.util.Map; import static com.djrapitops.plan.storage.database.sql.building.Sql.WHERE; +/** + * Adds server_id field to world times table. + * + * @author Rsl1122 + * @see WorldTimesOptimizationPatch for removal of this field later + */ public class WorldTimesSeverIDPatch extends Patch { @Override diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/WorldsOptimizationPatch.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/WorldsOptimizationPatch.java index 055dd407d..d6b3c9429 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/WorldsOptimizationPatch.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/WorldsOptimizationPatch.java @@ -21,6 +21,13 @@ import com.djrapitops.plan.storage.database.sql.tables.WorldTable; import static com.djrapitops.plan.storage.database.sql.building.Sql.FROM; +/** + * Replaces server_id foreign keys with server_uuid field in world table. + *

+ * This was to "reduce the amount of joins when querying sessions". + * + * @author Rsl1122 + */ public class WorldsOptimizationPatch extends Patch { private final String tempTableName; diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/WorldsServerIDPatch.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/WorldsServerIDPatch.java index 7922a9bed..dc1561e0c 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/WorldsServerIDPatch.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/patches/WorldsServerIDPatch.java @@ -34,6 +34,12 @@ import java.util.stream.Collectors; import static com.djrapitops.plan.storage.database.sql.building.Sql.*; +/** + * Adds server_id field to worlds table. + * + * @author Rsl1122 + * @see WorldsOptimizationPatch for removal of the field. + */ public class WorldsServerIDPatch extends Patch { @Override From 5401aef681e2d475ebbfbc4cdd142bf888885e12 Mon Sep 17 00:00:00 2001 From: Risto Lahtela <24460436+Rsl1122@users.noreply.github.com> Date: Fri, 1 Jan 2021 11:33:46 +0200 Subject: [PATCH 13/20] Fixed [object Object] showing when Kill has unknown victim uuid Improper use of Optional in Map#put Affects issues - Close #1675 --- .../plan/delivery/domain/mutators/SessionsMutator.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Plan/common/src/main/java/com/djrapitops/plan/delivery/domain/mutators/SessionsMutator.java b/Plan/common/src/main/java/com/djrapitops/plan/delivery/domain/mutators/SessionsMutator.java index 27506fbca..9ad9f09e0 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/delivery/domain/mutators/SessionsMutator.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/delivery/domain/mutators/SessionsMutator.java @@ -288,8 +288,8 @@ public class SessionsMutator { kill -> { Map killMap = new HashMap<>(); killMap.put("date", formatters.secondLong().apply(kill.getDate())); - killMap.put("victim", kill.getVictimName()); - killMap.put("killer", sessionMap.get("player_name")); + killMap.put("victim", kill.getVictimName().orElse(kill.getVictim().toString())); + killMap.put("killer", playerName); killMap.put("weapon", kill.getWeapon()); return killMap; } From 306e30e21fb32f6ae7c3caa71efa796fd6a8dd00 Mon Sep 17 00:00:00 2001 From: Risto Lahtela <24460436+Rsl1122@users.noreply.github.com> Date: Fri, 1 Jan 2021 11:50:47 +0200 Subject: [PATCH 14/20] Made MySQL launch options regex more lenient Affects issues: - Fixed #1661 --- .../main/java/com/djrapitops/plan/storage/database/MySQLDB.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/MySQLDB.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/MySQLDB.java index 566230d55..371673749 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/MySQLDB.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/MySQLDB.java @@ -94,7 +94,7 @@ public class MySQLDB extends SQLDB { String database = config.get(DatabaseSettings.MYSQL_DATABASE); String launchOptions = config.get(DatabaseSettings.MYSQL_LAUNCH_OPTIONS); // REGEX: match "?", match "word=word&" *-times, match "word=word" - if (launchOptions.isEmpty() || !launchOptions.matches("\\?((\\w*=\\w*)&)*(\\w*=\\w*)")) { + if (launchOptions.isEmpty() || !launchOptions.matches("\\?(((\\w|[-])+=.+)&)*((\\w|[-])+=.+)")) { launchOptions = "?rewriteBatchedStatements=true&useSSL=false"; logger.error(locale.getString(PluginLang.DB_MYSQL_LAUNCH_OPTIONS_FAIL, launchOptions)); } From b894656d6614daa001af1eea3557b7c0853bfe77 Mon Sep 17 00:00:00 2001 From: Risto Lahtela <24460436+Rsl1122@users.noreply.github.com> Date: Sun, 3 Jan 2021 12:05:14 +0200 Subject: [PATCH 15/20] Add instructions to "No servers" Affects issues - Close #1644 --- .../java/com/djrapitops/plan/settings/locale/lang/JSLang.java | 1 + .../src/main/resources/assets/plan/web/js/network-values.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Plan/common/src/main/java/com/djrapitops/plan/settings/locale/lang/JSLang.java b/Plan/common/src/main/java/com/djrapitops/plan/settings/locale/lang/JSLang.java index 223083f68..18b516cea 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/settings/locale/lang/JSLang.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/settings/locale/lang/JSLang.java @@ -25,6 +25,7 @@ public enum JSLang implements Lang { TEXT_PREDICTED_RETENTION("This value is a prediction based on previous players"), TEXT_NO_SERVERS("No servers found in the database"), + TEXT_SERVER_INSTRUCTIONS("It appears that Plan is not installed on any game servers or not connected to the same database. See wiki for Network tutorial."), TEXT_NO_SERVER("No server to display online activity for"), LABEL_REGISTERED_PLAYERS("Registered Players"), LINK_SERVER_ANALYSIS("Server Analysis"), diff --git a/Plan/common/src/main/resources/assets/plan/web/js/network-values.js b/Plan/common/src/main/resources/assets/plan/web/js/network-values.js index 9cdbf52b5..489ee6b95 100644 --- a/Plan/common/src/main/resources/assets/plan/web/js/network-values.js +++ b/Plan/common/src/main/resources/assets/plan/web/js/network-values.js @@ -237,7 +237,7 @@ function loadservers(servers, error) { if (!servers || !servers.length) { $('#data_server_list').replaceWith( - `

No servers found in the database.

` + `

No servers found in the database.

It appears that Plan is not installed on any game servers or not connected to the same database. See wiki for Network tutorial.

` ); $('#quick_view_players_online').text(`No server to display online activity for.`); return; From 16641995746be1b493e0653412bc444a1317ebe0 Mon Sep 17 00:00:00 2001 From: Risto Lahtela <24460436+Rsl1122@users.noreply.github.com> Date: Sun, 3 Jan 2021 12:27:49 +0200 Subject: [PATCH 16/20] Extension Table now handles Optionals Updated mcMMO Extension to R1.2 Affects issues: - Fixed #1643 --- Plan/api/build.gradle | 3 +- .../plan/extension/table/Table.java | 15 ++++- .../plan/extension/table/TableTest.java | 61 +++++++++++++++++++ Plan/extensions/build.gradle | 2 +- 4 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 Plan/api/src/test/java/com/djrapitops/plan/extension/table/TableTest.java diff --git a/Plan/api/build.gradle b/Plan/api/build.gradle index c1fd3ccef..eef225ec8 100644 --- a/Plan/api/build.gradle +++ b/Plan/api/build.gradle @@ -3,7 +3,8 @@ plugins { } dependencies { - compileOnly group: 'org.apache.commons', name: 'commons-lang3', version: '3.11' + compileOnly "org.apache.commons:commons-text:$commonsTextVersion" + testCompile "org.apache.commons:commons-text:$commonsTextVersion" compileOnly "com.google.code.gson:gson:$gsonVersion" } diff --git a/Plan/api/src/main/java/com/djrapitops/plan/extension/table/Table.java b/Plan/api/src/main/java/com/djrapitops/plan/extension/table/Table.java index c8a1a6a72..7c263cc31 100644 --- a/Plan/api/src/main/java/com/djrapitops/plan/extension/table/Table.java +++ b/Plan/api/src/main/java/com/djrapitops/plan/extension/table/Table.java @@ -22,8 +22,9 @@ import com.djrapitops.plan.extension.icon.Icon; import org.apache.commons.lang3.StringUtils; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; +import java.util.Objects; +import java.util.Optional; /** * Object for giving Plan table data. @@ -186,7 +187,17 @@ public final class Table { return this; // Ignore row when all values are null or no values are present. } - building.rows.add(Arrays.copyOf(values, 5)); + Object[] row = new Object[5]; + + for (int i = 0; i < Math.min(values.length, 5); i++) { + Object value = values[i]; + if (value instanceof Optional) { + value = ((Optional) value).map(Objects::toString).orElse("-"); + } + row[i] = value; + } + + building.rows.add(row); return this; } diff --git a/Plan/api/src/test/java/com/djrapitops/plan/extension/table/TableTest.java b/Plan/api/src/test/java/com/djrapitops/plan/extension/table/TableTest.java new file mode 100644 index 000000000..01455d8b8 --- /dev/null +++ b/Plan/api/src/test/java/com/djrapitops/plan/extension/table/TableTest.java @@ -0,0 +1,61 @@ +/* + * This file is part of Player Analytics (Plan). + * + * Plan is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License v3 as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Plan is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Plan. If not, see . + */ +package com.djrapitops.plan.extension.table; + +import com.djrapitops.plan.extension.icon.Icon; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; + +class TableTest { + + @Test + void tableWithVaryingRowLengthsHasNoErrors() { + Table.Factory table = Table.builder() + .columnOne("", Icon.called("").build()) + .columnTwo("", Icon.called("").build()) + .columnThree("", Icon.called("").build()) + .columnFour("", Icon.called("").build()) + .columnFive("", Icon.called("").build()); + + table.addRow(); + table.addRow("a"); + table.addRow("a", "b"); + table.addRow("a"); + table.addRow("a", "b", "c", "d", "e", "f"); + table.addRow("a", "b", "c", "d"); + + List expected = Arrays.asList( + new Object[]{"a", null, null, null, null}, + new Object[]{"a", "b", null, null, null}, + new Object[]{"a", null, null, null, null}, + new Object[]{"a", "b", "c", "d", "e"}, + new Object[]{"a", "b", "c", "d", null} + ); + List result = table.build().getRows(); + + for (int i = 0; i < expected.size(); i++) { + assertArrayEquals(expected.get(i), result.get(i)); + } + assertEquals(expected.size(), result.size()); + } + +} \ No newline at end of file diff --git a/Plan/extensions/build.gradle b/Plan/extensions/build.gradle index 0bf6cc7bf..32851d1b1 100644 --- a/Plan/extensions/build.gradle +++ b/Plan/extensions/build.gradle @@ -21,7 +21,7 @@ dependencies { compile 'com.djrapitops:Extension-Jobs:4.13.1-R0.1' compile 'com.djrapitops:Extension-Litebans:0.3.2-R0.1' compile 'com.djrapitops:Extension-LuckPerms:5.0-R0.2' - compile 'com.djrapitops:Extension-McMMO:2.1.149-R1.1' + compile 'com.djrapitops:Extension-McMMO:2.1.149-R1.2' compile 'com.djrapitops:Extension-MinigamesLib:1.14.17-R0.2' compile 'com.djrapitops:Extension-Nucleus:1.14.0-R0.1' compile 'com.djrapitops:Extension-nuVotifier:2.3.4-R0.3' From 7eb194e13f3ed8f33ca4e1fc5b1a5bf303ab5f38 Mon Sep 17 00:00:00 2001 From: Risto Lahtela <24460436+Rsl1122@users.noreply.github.com> Date: Sun, 3 Jan 2021 12:48:36 +0200 Subject: [PATCH 17/20] Distributed clean task evenly across servers Affects issues: - Fixed #1641 --- .../queries/objects/ServerQueries.java | 32 +++++++++++++++++++ .../plan/storage/upkeep/DBCleanTask.java | 26 +++++++++++++-- 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/queries/objects/ServerQueries.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/queries/objects/ServerQueries.java index d8b6f5cb2..d887396b9 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/queries/objects/ServerQueries.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/queries/objects/ServerQueries.java @@ -200,4 +200,36 @@ public class ServerQueries { } }; } + + public static Query fetchServerCount() { + String sql = SELECT + "COUNT(1) as c" + FROM + ServerTable.TABLE_NAME + + WHERE + ServerTable.INSTALLED + "=?"; + return new QueryStatement(sql) { + @Override + public void prepare(PreparedStatement statement) throws SQLException { + statement.setBoolean(1, true); + } + + @Override + public Integer processResults(ResultSet set) throws SQLException { + return set.next() ? set.getInt("c") : 1; + } + }; + } + + public static Query fetchBiggestServerID() { + String sql = SELECT + "MAX(" + ServerTable.SERVER_ID + ") as max_id" + FROM + ServerTable.TABLE_NAME + + WHERE + ServerTable.INSTALLED + "=?"; + return new QueryStatement(sql) { + @Override + public void prepare(PreparedStatement statement) throws SQLException { + statement.setBoolean(1, true); + } + + @Override + public Integer processResults(ResultSet set) throws SQLException { + return set.next() ? set.getInt("max_id") : 1; + } + }; + } } \ No newline at end of file diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/upkeep/DBCleanTask.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/upkeep/DBCleanTask.java index 9ad6b818a..a37a655cd 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/upkeep/DBCleanTask.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/upkeep/DBCleanTask.java @@ -30,6 +30,7 @@ import com.djrapitops.plan.storage.database.DBSystem; import com.djrapitops.plan.storage.database.Database; import com.djrapitops.plan.storage.database.queries.Query; import com.djrapitops.plan.storage.database.queries.QueryStatement; +import com.djrapitops.plan.storage.database.queries.objects.ServerQueries; import com.djrapitops.plan.storage.database.sql.tables.SessionsTable; import com.djrapitops.plan.storage.database.transactions.commands.RemovePlayerTransaction; import com.djrapitops.plan.storage.database.transactions.init.RemoveDuplicateUserInfoTransaction; @@ -39,6 +40,7 @@ import com.djrapitops.plan.utilities.logging.ErrorLogger; import com.djrapitops.plugin.api.TimeAmount; import com.djrapitops.plugin.logging.L; import com.djrapitops.plugin.logging.console.PluginLogger; +import com.djrapitops.plugin.task.AbsRunnable; import com.djrapitops.plugin.task.RunnableFactory; import javax.inject.Inject; @@ -100,6 +102,7 @@ public class DBCleanTask extends TaskSystem.Task { Database database = dbSystem.getDatabase(); try { if (database.getState() != Database.State.CLOSED) { + database.executeTransaction(new RemoveOldSampledDataTransaction( serverInfo.getServerUUID(), config.get(TimeSettings.DELETE_TPS_DATA_AFTER), @@ -125,9 +128,26 @@ public class DBCleanTask extends TaskSystem.Task { @Override public void register(RunnableFactory runnableFactory) { - long delay = TimeAmount.toTicks(20, TimeUnit.SECONDS); - long period = TimeAmount.toTicks(config.get(TimeSettings.CLEAN_DATABASE_PERIOD), TimeUnit.MILLISECONDS); - runnableFactory.create(null, this).runTaskTimerAsynchronously(delay, period); + // Secondary task for registration due to database queries. + runnableFactory.create(null, new AbsRunnable() { + @Override + public void run() { + // Distribute clean task evenly between multiple servers. + // see https://github.com/plan-player-analytics/Plan/issues/1641 for why + Integer biggestId = dbSystem.getDatabase().query(ServerQueries.fetchBiggestServerID()); + Integer id = serverInfo.getServer().getId().orElse(1); + + double distributor = id * 1.0 / biggestId; // 0 < distributor <= 1 + long distributingOverTime = config.get(TimeSettings.CLEAN_DATABASE_PERIOD); + + // -40 seconds to start first at 20 seconds if only one server is present. + long startAfter = (long) (distributor * distributingOverTime) - 40L; + + long delay = TimeAmount.toTicks(startAfter, TimeUnit.MILLISECONDS); + long period = TimeAmount.toTicks(config.get(TimeSettings.CLEAN_DATABASE_PERIOD), TimeUnit.MILLISECONDS); + runnableFactory.create(null, this).runTaskTimerAsynchronously(delay, period); + } + }).runTaskAsynchronously(); } // VisibleForTesting From 558e132b6e0e8620827e640b77fa9fcce8b9ee06 Mon Sep 17 00:00:00 2001 From: Risto Lahtela <24460436+Rsl1122@users.noreply.github.com> Date: Sun, 3 Jan 2021 12:51:06 +0200 Subject: [PATCH 18/20] Replace theme colors in color-selector.js when exported Affects issues: - Fixed #1666 --- .../djrapitops/plan/delivery/export/NetworkPageExporter.java | 2 +- .../com/djrapitops/plan/delivery/export/PlayerPageExporter.java | 2 +- .../djrapitops/plan/delivery/export/PlayersPageExporter.java | 2 +- .../com/djrapitops/plan/delivery/export/ServerPageExporter.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Plan/common/src/main/java/com/djrapitops/plan/delivery/export/NetworkPageExporter.java b/Plan/common/src/main/java/com/djrapitops/plan/delivery/export/NetworkPageExporter.java index 2135ed547..7ab9affe5 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/delivery/export/NetworkPageExporter.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/delivery/export/NetworkPageExporter.java @@ -215,7 +215,7 @@ public class NetworkPageExporter extends FileExporter { () -> files.getResourceFromJar("web/" + resourceName).asWebResource()); Path to = toDirectory.resolve(resourceName); - if (resourceName.endsWith(".css")) { + if (resourceName.endsWith(".css") || resourceName.endsWith("color-selector.js")) { export(to, theme.replaceThemeColors(resource.asString())); } else if ("js/network-values.js".equalsIgnoreCase(resourceName) || "js/sessionAccordion.js".equalsIgnoreCase(resourceName)) { String relativePlayerLink = toRelativePathFromRoot("player"); diff --git a/Plan/common/src/main/java/com/djrapitops/plan/delivery/export/PlayerPageExporter.java b/Plan/common/src/main/java/com/djrapitops/plan/delivery/export/PlayerPageExporter.java index 12b2051e0..b78397995 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/delivery/export/PlayerPageExporter.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/delivery/export/PlayerPageExporter.java @@ -191,7 +191,7 @@ public class PlayerPageExporter extends FileExporter { () -> files.getResourceFromJar("web/" + resourceName).asWebResource()); Path to = toDirectory.resolve(resourceName); - if (resourceName.endsWith(".css")) { + if (resourceName.endsWith(".css") || resourceName.endsWith("color-selector.js")) { export(to, theme.replaceThemeColors(resource.asString())); } else if (Resource.isTextResource(resourceName)) { export(to, resource.asString()); diff --git a/Plan/common/src/main/java/com/djrapitops/plan/delivery/export/PlayersPageExporter.java b/Plan/common/src/main/java/com/djrapitops/plan/delivery/export/PlayersPageExporter.java index 49ecc1fb2..af47eb6b3 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/delivery/export/PlayersPageExporter.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/delivery/export/PlayersPageExporter.java @@ -164,7 +164,7 @@ public class PlayersPageExporter extends FileExporter { () -> files.getResourceFromJar("web/" + resourceName).asWebResource()); Path to = toDirectory.resolve(resourceName); - if (resourceName.endsWith(".css")) { + if (resourceName.endsWith(".css") || resourceName.endsWith("color-selector.js")) { export(to, theme.replaceThemeColors(resource.asString())); } else if (Resource.isTextResource(resourceName)) { export(to, resource.asString()); diff --git a/Plan/common/src/main/java/com/djrapitops/plan/delivery/export/ServerPageExporter.java b/Plan/common/src/main/java/com/djrapitops/plan/delivery/export/ServerPageExporter.java index 91fd4262d..d9cf723f0 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/delivery/export/ServerPageExporter.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/delivery/export/ServerPageExporter.java @@ -234,7 +234,7 @@ public class ServerPageExporter extends FileExporter { () -> files.getResourceFromJar("web/" + resourceName).asWebResource()); Path to = toDirectory.resolve(resourceName); - if (resourceName.endsWith(".css")) { + if (resourceName.endsWith(".css") || resourceName.endsWith("color-selector.js")) { export(to, theme.replaceThemeColors(resource.asString())); } else if (Resource.isTextResource(resourceName)) { export(to, resource.asString()); From 36011b5ff982f9691ba80d8c681f43538e3ba344 Mon Sep 17 00:00:00 2001 From: Risto Lahtela <24460436+Rsl1122@users.noreply.github.com> Date: Sun, 3 Jan 2021 12:53:38 +0200 Subject: [PATCH 19/20] Fix /plan m hotswap -> /plan db hotswap --- .../com/djrapitops/plan/settings/locale/lang/CommandLang.java | 2 +- Plan/common/src/main/resources/assets/plan/locale/locale_CN.txt | 2 +- Plan/common/src/main/resources/assets/plan/locale/locale_CS.txt | 2 +- Plan/common/src/main/resources/assets/plan/locale/locale_DE.txt | 2 +- Plan/common/src/main/resources/assets/plan/locale/locale_EN.txt | 2 +- Plan/common/src/main/resources/assets/plan/locale/locale_ES.txt | 2 +- Plan/common/src/main/resources/assets/plan/locale/locale_FI.txt | 2 +- Plan/common/src/main/resources/assets/plan/locale/locale_FR.txt | 2 +- Plan/common/src/main/resources/assets/plan/locale/locale_IT.txt | 2 +- Plan/common/src/main/resources/assets/plan/locale/locale_JA.txt | 2 +- Plan/common/src/main/resources/assets/plan/locale/locale_KO.txt | 2 +- .../src/main/resources/assets/plan/locale/locale_PT_BR.txt | 2 +- Plan/common/src/main/resources/assets/plan/locale/locale_RU.txt | 2 +- Plan/common/src/main/resources/assets/plan/locale/locale_TR.txt | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Plan/common/src/main/java/com/djrapitops/plan/settings/locale/lang/CommandLang.java b/Plan/common/src/main/java/com/djrapitops/plan/settings/locale/lang/CommandLang.java index d96b5adde..7daf82de5 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/settings/locale/lang/CommandLang.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/settings/locale/lang/CommandLang.java @@ -115,7 +115,7 @@ public enum CommandLang implements Lang { RELOAD_COMPLETE("Cmd Info - Reload Complete", "§aReload Complete"), RELOAD_FAILED("Cmd Info - Reload Failed", "§cSomething went wrong during reload of the plugin, a restart is recommended."), NO_ADDRESS_NOTIFY("Cmd Notify - No Address", "§eNo address was available - using localhost as fallback. Set up 'Alternative_IP' settings."), - HOTSWAP_REMINDER("Manage - Remind HotSwap", "§eRemember to swap to the new database (/plan m hotswap ${0}) & reload the plugin."), + HOTSWAP_REMINDER("Manage - Remind HotSwap", "§eRemember to swap to the new database (/plan db hotswap ${0}) & reload the plugin."), PROGRESS_START("Manage - Start", "> §2Processing data.."), PROGRESS("Manage - Progress", "${0} / ${1} processed.."), PROGRESS_SUCCESS("Manage - Success", "> §aSuccess!"), diff --git a/Plan/common/src/main/resources/assets/plan/locale/locale_CN.txt b/Plan/common/src/main/resources/assets/plan/locale/locale_CN.txt index d01551183..67484544a 100644 --- a/Plan/common/src/main/resources/assets/plan/locale/locale_CN.txt +++ b/Plan/common/src/main/resources/assets/plan/locale/locale_CN.txt @@ -398,7 +398,7 @@ Manage - Fail Same server || 无法将服务器标记为 Manage - Fail, Confirmation || > §c[数据统计] 请添加 -a 以确认执行!${0} Manage - List Importers || 导入器: Manage - Progress || ${0} / ${1} processed.. -Manage - Remind HotSwap || §e[数据统计] 请切换至新数据库并重载插件(/plan m hotswap ${0}) +Manage - Remind HotSwap || §e[数据统计] 请切换至新数据库并重载插件(/plan db hotswap ${0}) Manage - Start || »§7 正在处理数据... Manage - Success || §f» §2 成功! Negative || 否 diff --git a/Plan/common/src/main/resources/assets/plan/locale/locale_CS.txt b/Plan/common/src/main/resources/assets/plan/locale/locale_CS.txt index d7858b1b4..1f4060061 100644 --- a/Plan/common/src/main/resources/assets/plan/locale/locale_CS.txt +++ b/Plan/common/src/main/resources/assets/plan/locale/locale_CS.txt @@ -398,7 +398,7 @@ Manage - Fail Same server || Nelze označit tento server j Manage - Fail, Confirmation || > §cPřidejte '-a' argument k potvrzení provedení: ${0} Manage - List Importers || Importery: Manage - Progress || ${0} / ${1} zpracovávání.. -Manage - Remind HotSwap || §eNezapomeňte přehodit na novou databázi (/plan m hotswap ${0}) & reload pluginu. +Manage - Remind HotSwap || §eNezapomeňte přehodit na novou databázi (/plan db hotswap ${0}) & reload pluginu. Manage - Start || > §2Zpracovávám data.. Manage - Success || > §aÚspěch! Negative || Ne diff --git a/Plan/common/src/main/resources/assets/plan/locale/locale_DE.txt b/Plan/common/src/main/resources/assets/plan/locale/locale_DE.txt index 886db8853..df78932b5 100644 --- a/Plan/common/src/main/resources/assets/plan/locale/locale_DE.txt +++ b/Plan/common/src/main/resources/assets/plan/locale/locale_DE.txt @@ -398,7 +398,7 @@ Manage - Fail Same server || Server kann nicht als uninsta Manage - Fail, Confirmation || > §cFüge '-a' zum Befehl hinzu um die Ausführung zu bestätigen: ${0} Manage - List Importers || Importer: Manage - Progress || ${0} / ${1} processed.. -Manage - Remind HotSwap || §eDenk dran, zur neuen Datenbank zu wechseln (/plan m hotswap ${0}) und um das Plugin neu zu laden. +Manage - Remind HotSwap || §eDenk dran, zur neuen Datenbank zu wechseln (/plan db hotswap ${0}) und um das Plugin neu zu laden. Manage - Start || > §2Verarbeite Daten... Manage - Success || > §aErfolgreich! Negative || Nein diff --git a/Plan/common/src/main/resources/assets/plan/locale/locale_EN.txt b/Plan/common/src/main/resources/assets/plan/locale/locale_EN.txt index f3810c246..be306dc98 100644 --- a/Plan/common/src/main/resources/assets/plan/locale/locale_EN.txt +++ b/Plan/common/src/main/resources/assets/plan/locale/locale_EN.txt @@ -398,7 +398,7 @@ Manage - Fail Same server || Can not mark this server as u Manage - Fail, Confirmation || > §cAdd '-a' argument to confirm execution: ${0} Manage - List Importers || Importers: Manage - Progress || ${0} / ${1} processed.. -Manage - Remind HotSwap || §eRemember to swap to the new database (/plan m hotswap ${0}) & reload the plugin. +Manage - Remind HotSwap || §eRemember to swap to the new database (/plan db hotswap ${0}) & reload the plugin. Manage - Start || > §2Processing data.. Manage - Success || > §aSuccess! Negative || No diff --git a/Plan/common/src/main/resources/assets/plan/locale/locale_ES.txt b/Plan/common/src/main/resources/assets/plan/locale/locale_ES.txt index dc8f5b785..d97bcdfc4 100644 --- a/Plan/common/src/main/resources/assets/plan/locale/locale_ES.txt +++ b/Plan/common/src/main/resources/assets/plan/locale/locale_ES.txt @@ -398,7 +398,7 @@ Manage - Fail Same server || No se ha podido marcar el ser Manage - Fail, Confirmation || > §cAñade el argumento '-a' para confirmar la ejecución: ${0} Manage - List Importers || Importadores: Manage - Progress || ${0} / ${1} processed.. -Manage - Remind HotSwap || §eRecuerda cambiarte a la nueva base de datos (/plan m hotswap ${0}) & recarga el plugin. +Manage - Remind HotSwap || §eRecuerda cambiarte a la nueva base de datos (/plan db hotswap ${0}) & recarga el plugin. Manage - Start || > §2Procesando datos.. Manage - Success || > §a¡Éxito! Negative || No diff --git a/Plan/common/src/main/resources/assets/plan/locale/locale_FI.txt b/Plan/common/src/main/resources/assets/plan/locale/locale_FI.txt index 302f4a1c3..827fc9df5 100644 --- a/Plan/common/src/main/resources/assets/plan/locale/locale_FI.txt +++ b/Plan/common/src/main/resources/assets/plan/locale/locale_FI.txt @@ -398,7 +398,7 @@ Manage - Fail Same server || Ei voi merkitä tätä palvel Manage - Fail, Confirmation || > §cLisää '-a' vahvistaaksesi: ${0} Manage - List Importers || Tuojat: Manage - Progress || ${0} / ${1} processed.. -Manage - Remind HotSwap || §eMuista vaihtaa tietokantaa (/plan m hotswap ${0}) & käynnistä Plan uudelleen. +Manage - Remind HotSwap || §eMuista vaihtaa tietokantaa (/plan db hotswap ${0}) & käynnistä Plan uudelleen. Manage - Start || > §2Prosessoidaan tietoa.. Manage - Success || > §aOnnistui! Negative || Ei diff --git a/Plan/common/src/main/resources/assets/plan/locale/locale_FR.txt b/Plan/common/src/main/resources/assets/plan/locale/locale_FR.txt index 821f1103e..8aafd2354 100644 --- a/Plan/common/src/main/resources/assets/plan/locale/locale_FR.txt +++ b/Plan/common/src/main/resources/assets/plan/locale/locale_FR.txt @@ -398,7 +398,7 @@ Manage - Fail Same server || Impossible de marquer ce serv Manage - Fail, Confirmation || > §cAjoutez l'argmenter '-a' afin de confirmer l'éxécution : ${0} Manage - List Importers || Importateurs : Manage - Progress || ${0} / ${1} processed.. -Manage - Remind HotSwap || §eN'oubliez pas de passer à la nouvelle base de données (/plan m hotswap ${0}) & de recharger Plan. +Manage - Remind HotSwap || §eN'oubliez pas de passer à la nouvelle base de données (/plan db hotswap ${0}) & de recharger Plan. Manage - Start || > §2Traitement des données... Manage - Success || > §aSuccès ! Negative || Non diff --git a/Plan/common/src/main/resources/assets/plan/locale/locale_IT.txt b/Plan/common/src/main/resources/assets/plan/locale/locale_IT.txt index bd6cc143e..5ed04b2c6 100644 --- a/Plan/common/src/main/resources/assets/plan/locale/locale_IT.txt +++ b/Plan/common/src/main/resources/assets/plan/locale/locale_IT.txt @@ -398,7 +398,7 @@ Manage - Fail Same server || Impossibile rimuovere questo Manage - Fail, Confirmation || > §cAggiungi l'argomento '-a' per confermare l'esecuzione: ${0} Manage - List Importers || Importatori: Manage - Progress || ${0} / ${1} processed.. -Manage - Remind HotSwap || §eRircorda di cambiare il nuovo database (/plan m hotswap ${0}) e ricaricare il plugin. +Manage - Remind HotSwap || §eRircorda di cambiare il nuovo database (/plan db hotswap ${0}) e ricaricare il plugin. Manage - Start || > §2Processando i dati.. Manage - Success || > §aCompletato! Negative || No diff --git a/Plan/common/src/main/resources/assets/plan/locale/locale_JA.txt b/Plan/common/src/main/resources/assets/plan/locale/locale_JA.txt index ab5cbe5ea..3a2572419 100644 --- a/Plan/common/src/main/resources/assets/plan/locale/locale_JA.txt +++ b/Plan/common/src/main/resources/assets/plan/locale/locale_JA.txt @@ -398,7 +398,7 @@ Manage - Fail Same server || このサーバーをアン Manage - Fail, Confirmation || > §c実行を確認するために引数「-a」を追加します: ${0} Manage - List Importers || インポーター: Manage - Progress || ${0} / ${1} を処理中.. -Manage - Remind HotSwap || §e新しいデータベースに交換することを忘れないで下さい(/plan m hotswap ${0})。そして、プラグインをリロードして下さい +Manage - Remind HotSwap || §e新しいデータベースに交換することを忘れないで下さい(/plan db hotswap ${0})。そして、プラグインをリロードして下さい Manage - Start || > §2データを処理中です.. Manage - Success || > §a成功しました! Negative || ない diff --git a/Plan/common/src/main/resources/assets/plan/locale/locale_KO.txt b/Plan/common/src/main/resources/assets/plan/locale/locale_KO.txt index b0125025e..456ceffd1 100644 --- a/Plan/common/src/main/resources/assets/plan/locale/locale_KO.txt +++ b/Plan/common/src/main/resources/assets/plan/locale/locale_KO.txt @@ -399,7 +399,7 @@ Manage - Fail Same server || 이 서버를 제거된 것 Manage - Fail, Confirmation || > §cAdd '-a' argument to confirm execution: ${0} Manage - List Importers || Importers: Manage - Progress || ${0} / ${1} 처리 중.. -Manage - Remind HotSwap || §e새 데이터베이스 (/plan m hotswap ${0})로 교체하고 플러그인을 다시 로드해야합니다. +Manage - Remind HotSwap || §e새 데이터베이스 (/plan db hotswap ${0})로 교체하고 플러그인을 다시 로드해야합니다. Manage - Start || > §2데이터 처리 중.. Manage - Success || > §a성공! Negative || 아니오 diff --git a/Plan/common/src/main/resources/assets/plan/locale/locale_PT_BR.txt b/Plan/common/src/main/resources/assets/plan/locale/locale_PT_BR.txt index 7d6b011fd..ffd326570 100644 --- a/Plan/common/src/main/resources/assets/plan/locale/locale_PT_BR.txt +++ b/Plan/common/src/main/resources/assets/plan/locale/locale_PT_BR.txt @@ -398,7 +398,7 @@ Manage - Fail Same server || Can not mark this server as u Manage - Fail, Confirmation || > §cAdicione o argumento '-a' para confirmar a execução: ${0} Manage - List Importers || Importadores: Manage - Progress || ${0} / ${1} processed.. -Manage - Remind HotSwap || §eLembre-se de trocar para o novo banco de dados (/plan m hotswap ${0}) & reinicie o plugin. +Manage - Remind HotSwap || §eLembre-se de trocar para o novo banco de dados (/plan db hotswap ${0}) & reinicie o plugin. Manage - Start || > §2Processando dados.. Manage - Success || > §aSucesso! Negative || Não diff --git a/Plan/common/src/main/resources/assets/plan/locale/locale_RU.txt b/Plan/common/src/main/resources/assets/plan/locale/locale_RU.txt index c8bc71ae0..4eea9d02b 100644 --- a/Plan/common/src/main/resources/assets/plan/locale/locale_RU.txt +++ b/Plan/common/src/main/resources/assets/plan/locale/locale_RU.txt @@ -398,7 +398,7 @@ Manage - Fail Same server || Невозможно поме Manage - Fail, Confirmation || > §cДобавьте аргумент '-a' для подтверждения выполнения: ${0} Manage - List Importers || Импортеры: Manage - Progress || ${0} / ${1} processed.. -Manage - Remind HotSwap || §eНе забудьте поменять на новую базу данных (/plan m hotswap ${0}) и перезагрузить плагин. +Manage - Remind HotSwap || §eНе забудьте поменять на новую базу данных (/plan db hotswap ${0}) и перезагрузить плагин. Manage - Start || > §2Обработка данных.. Manage - Success || > §aУспех! Negative || Нет diff --git a/Plan/common/src/main/resources/assets/plan/locale/locale_TR.txt b/Plan/common/src/main/resources/assets/plan/locale/locale_TR.txt index 3f4380a22..951e35733 100644 --- a/Plan/common/src/main/resources/assets/plan/locale/locale_TR.txt +++ b/Plan/common/src/main/resources/assets/plan/locale/locale_TR.txt @@ -398,7 +398,7 @@ Manage - Fail Same server || Can not mark this server as u Manage - Fail, Confirmation || > §cKomutu onaylamak için '-a' komuta ekle: ${0} Manage - List Importers || Importers: Manage - Progress || ${0} / ${1} processed.. -Manage - Remind HotSwap || §eRemember to swap to the new database (/plan m hotswap ${0}) & reload the plugin. +Manage - Remind HotSwap || §eRemember to swap to the new database (/plan db hotswap ${0}) & reload the plugin. Manage - Start || > §2Veri işleniyor.. Manage - Success || > §aBaşarılı! Negative || Hayır From f9d1794e79bdbd880bbd50d5ebf0786e75b120b4 Mon Sep 17 00:00:00 2001 From: Risto Lahtela <24460436+Rsl1122@users.noreply.github.com> Date: Tue, 5 Jan 2021 11:59:55 +0200 Subject: [PATCH 20/20] Fixed javadoc errors --- .../com/djrapitops/plan/commands/use/BukkitPartBuilder.java | 2 +- Plan/common/src/main/java/com/djrapitops/plan/DataService.java | 2 +- .../com/djrapitops/plan/commands/use/ConsoleChatFormatter.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Plan/bukkit/src/main/java/com/djrapitops/plan/commands/use/BukkitPartBuilder.java b/Plan/bukkit/src/main/java/com/djrapitops/plan/commands/use/BukkitPartBuilder.java index 896292ca4..2206868c5 100644 --- a/Plan/bukkit/src/main/java/com/djrapitops/plan/commands/use/BukkitPartBuilder.java +++ b/Plan/bukkit/src/main/java/com/djrapitops/plan/commands/use/BukkitPartBuilder.java @@ -52,7 +52,7 @@ class BukkitPartBuilder implements MessageBuilder { try { nextPart.part.appendLegacy(text); } catch (NoSuchMethodError oldVersion) { // not supported in 1.8 - nextPart.part.append(ChatColor.translateAlternateColorCodes('§', text)); + nextPart.part.append(ChatColor.translateAlternateColorCodes('\u00a7', text)); } return nextPart; } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/DataService.java b/Plan/common/src/main/java/com/djrapitops/plan/DataService.java index c00d54dbf..10637e52c 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/DataService.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/DataService.java @@ -39,7 +39,7 @@ import java.util.function.Supplier; * - mappers are stateless type transformers in memory *

* Example use-case: - * - PlayerJoinEvent -> mapped to a generic event + * - PlayerJoinEvent is mapped to a generic event * - that generic event is then consumed and mapped until the data is in a database. *

* - Some kind of data is wanted to place on a web page diff --git a/Plan/common/src/main/java/com/djrapitops/plan/commands/use/ConsoleChatFormatter.java b/Plan/common/src/main/java/com/djrapitops/plan/commands/use/ConsoleChatFormatter.java index 91706b16c..2acf5115c 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/commands/use/ConsoleChatFormatter.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/commands/use/ConsoleChatFormatter.java @@ -22,6 +22,6 @@ public class ConsoleChatFormatter extends ChatFormatter { @Override public int getWidth(String part) { - return part.length() - (StringUtils.countMatches(part, '§') * 2); + return part.length() - (StringUtils.countMatches(part, '\u00a7') * 2); } }