mirror of
https://github.com/WiIIiam278/HuskSync.git
synced 2026-01-04 15:31:37 +00:00
feat: add /husksync dump status dumping, close #460
This commit is contained in:
@@ -34,12 +34,14 @@ import net.william278.husksync.data.Identifier;
|
||||
import net.william278.husksync.data.SerializerRegistry;
|
||||
import net.william278.husksync.database.Database;
|
||||
import net.william278.husksync.event.EventDispatcher;
|
||||
import net.william278.husksync.listener.LockedHandler;
|
||||
import net.william278.husksync.migrator.Migrator;
|
||||
import net.william278.husksync.redis.RedisManager;
|
||||
import net.william278.husksync.sync.DataSyncer;
|
||||
import net.william278.husksync.user.ConsoleUser;
|
||||
import net.william278.husksync.user.OnlineUser;
|
||||
import net.william278.husksync.util.CompatibilityChecker;
|
||||
import net.william278.husksync.util.DumpProvider;
|
||||
import net.william278.husksync.util.LegacyConverter;
|
||||
import net.william278.husksync.util.Task;
|
||||
import net.william278.uniform.Uniform;
|
||||
@@ -54,7 +56,7 @@ import java.util.logging.Level;
|
||||
* Abstract implementation of the HuskSync plugin.
|
||||
*/
|
||||
public interface HuskSync extends Task.Supplier, EventDispatcher, ConfigProvider, SerializerRegistry,
|
||||
CompatibilityChecker {
|
||||
CompatibilityChecker, DumpProvider {
|
||||
|
||||
int SPIGOT_RESOURCE_ID = 97144;
|
||||
|
||||
@@ -302,6 +304,9 @@ public interface HuskSync extends Task.Supplier, EventDispatcher, ConfigProvider
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
LockedHandler getLockedHandler();
|
||||
|
||||
/**
|
||||
* Get the set of UUIDs of "locked players", for which events will be canceled.
|
||||
* </p>
|
||||
@@ -340,12 +345,12 @@ public interface HuskSync extends Task.Supplier, EventDispatcher, ConfigProvider
|
||||
private static final String FORMAT = """
|
||||
HuskSync has failed to load! The plugin will not be enabled and no data will be synchronized.
|
||||
Please make sure the plugin has been setup correctly (https://william278.net/docs/husksync/setup):
|
||||
|
||||
|
||||
1) Make sure you've entered your MySQL, MariaDB or MongoDB database details correctly in config.yml
|
||||
2) Make sure your Redis server details are also correct in config.yml
|
||||
3) Make sure your config is up-to-date (https://william278.net/docs/husksync/config-file)
|
||||
4) Check the error below for more details
|
||||
|
||||
|
||||
Caused by: %s""";
|
||||
|
||||
public FailedToLoadException(@NotNull String message) {
|
||||
|
||||
@@ -24,9 +24,10 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import de.themoep.minedown.adventure.MineDown;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.JoinConfiguration;
|
||||
import net.kyori.adventure.text.event.HoverEvent;
|
||||
import net.kyori.adventure.text.event.ClickEvent;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.format.TextColor;
|
||||
import net.kyori.adventure.text.format.TextDecoration;
|
||||
import net.william278.desertwell.about.AboutMenu;
|
||||
import net.william278.desertwell.util.UpdateChecker;
|
||||
import net.william278.husksync.HuskSync;
|
||||
@@ -35,18 +36,17 @@ import net.william278.husksync.database.Database;
|
||||
import net.william278.husksync.migrator.Migrator;
|
||||
import net.william278.husksync.user.CommandUser;
|
||||
import net.william278.husksync.util.LegacyConverter;
|
||||
import net.william278.husksync.util.StatusLine;
|
||||
import net.william278.uniform.BaseCommand;
|
||||
import net.william278.uniform.CommandProvider;
|
||||
import net.william278.uniform.Permission;
|
||||
import net.william278.uniform.element.ArgumentElement;
|
||||
import org.apache.commons.text.WordUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -98,6 +98,7 @@ public class HuskSyncCommand extends PluginCommand {
|
||||
command.setDefaultExecutor((ctx) -> about(command, ctx));
|
||||
command.addSubCommand("about", (sub) -> sub.setDefaultExecutor((ctx) -> about(command, ctx)));
|
||||
command.addSubCommand("status", needsOp("status"), status());
|
||||
command.addSubCommand("dump", needsOp("dump"), dump());
|
||||
command.addSubCommand("reload", needsOp("reload"), reload());
|
||||
command.addSubCommand("update", needsOp("update"), update());
|
||||
command.addSubCommand("forceupgrade", forceUpgrade());
|
||||
@@ -120,6 +121,26 @@ public class HuskSyncCommand extends PluginCommand {
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private CommandProvider dump() {
|
||||
return (sub) -> {
|
||||
sub.setDefaultExecutor((ctx) -> {
|
||||
final CommandUser user = user(sub, ctx);
|
||||
plugin.getLocales().getLocale("system_dump_confirm").ifPresent(user::sendMessage);
|
||||
});
|
||||
sub.addSubCommand("confirm", (con) -> con.setDefaultExecutor((ctx) -> {
|
||||
final CommandUser user = user(sub, ctx);
|
||||
plugin.getLocales().getLocale("system_dump_started").ifPresent(user::sendMessage);
|
||||
plugin.runAsync(() -> {
|
||||
final String url = plugin.createDump(user);
|
||||
plugin.getLocales().getLocale("system_dump_ready").ifPresent(user::sendMessage);
|
||||
user.sendMessage(Component.text(url).clickEvent(ClickEvent.openUrl(url))
|
||||
.decorate(TextDecoration.UNDERLINED).color(NamedTextColor.GRAY));
|
||||
});
|
||||
}));
|
||||
};
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private CommandProvider reload() {
|
||||
return (sub) -> sub.setDefaultExecutor((ctx) -> {
|
||||
@@ -234,86 +255,4 @@ public class HuskSyncCommand extends PluginCommand {
|
||||
});
|
||||
}
|
||||
|
||||
private enum StatusLine {
|
||||
PLUGIN_VERSION(plugin -> Component.text("v" + plugin.getPluginVersion().toStringWithoutMetadata())
|
||||
.appendSpace().append(plugin.getPluginVersion().getMetadata().isBlank() ? Component.empty()
|
||||
: Component.text("(build " + plugin.getPluginVersion().getMetadata() + ")"))),
|
||||
SERVER_VERSION(plugin -> Component.text(plugin.getServerVersion())),
|
||||
LANGUAGE(plugin -> Component.text(plugin.getSettings().getLanguage())),
|
||||
MINECRAFT_VERSION(plugin -> Component.text(plugin.getMinecraftVersion().toString())),
|
||||
JAVA_VERSION(plugin -> Component.text(System.getProperty("java.version"))),
|
||||
JAVA_VENDOR(plugin -> Component.text(System.getProperty("java.vendor"))),
|
||||
SERVER_NAME(plugin -> Component.text(plugin.getServerName())),
|
||||
CLUSTER_ID(plugin -> Component.text(plugin.getSettings().getClusterId().isBlank() ? "None" : plugin.getSettings().getClusterId())),
|
||||
SYNC_MODE(plugin -> Component.text(WordUtils.capitalizeFully(
|
||||
plugin.getSettings().getSynchronization().getMode().toString()
|
||||
))),
|
||||
DELAY_LATENCY(plugin -> Component.text(
|
||||
plugin.getSettings().getSynchronization().getNetworkLatencyMilliseconds() + "ms"
|
||||
)),
|
||||
DATABASE_TYPE(plugin ->
|
||||
Component.text(plugin.getSettings().getDatabase().getType().getDisplayName() +
|
||||
(plugin.getSettings().getDatabase().getType() == Database.Type.MONGO ?
|
||||
(plugin.getSettings().getDatabase().getMongoSettings().isUsingAtlas() ? " Atlas" : "") : ""))
|
||||
),
|
||||
IS_DATABASE_LOCAL(plugin -> getLocalhostBoolean(plugin.getSettings().getDatabase().getCredentials().getHost())),
|
||||
USING_REDIS_SENTINEL(plugin -> getBoolean(
|
||||
!plugin.getSettings().getRedis().getSentinel().getMaster().isBlank()
|
||||
)),
|
||||
USING_REDIS_PASSWORD(plugin -> getBoolean(
|
||||
!plugin.getSettings().getRedis().getCredentials().getPassword().isBlank()
|
||||
)),
|
||||
REDIS_USING_SSL(plugin -> getBoolean(
|
||||
plugin.getSettings().getRedis().getCredentials().isUseSsl()
|
||||
)),
|
||||
IS_REDIS_LOCAL(plugin -> getLocalhostBoolean(
|
||||
plugin.getSettings().getRedis().getCredentials().getHost()
|
||||
)),
|
||||
DATA_TYPES(plugin -> Component.join(
|
||||
JoinConfiguration.commas(true),
|
||||
plugin.getRegisteredDataTypes().stream().map(i -> Component.textOfChildren(Component.text(i.toString())
|
||||
.appendSpace().append(Component.text(i.isEnabled() ? '✔' : '❌')))
|
||||
.color(i.isEnabled() ? NamedTextColor.GREEN : NamedTextColor.RED)
|
||||
.hoverEvent(HoverEvent.showText(
|
||||
Component.text(i.isEnabled() ? "Enabled" : "Disabled")
|
||||
.append(Component.newline())
|
||||
.append(Component.text("Dependencies: %s".formatted(i.getDependencies()
|
||||
.isEmpty() ? "(None)" : i.getDependencies().stream()
|
||||
.map(d -> "%s (%s)".formatted(
|
||||
d.getKey().value(), d.isRequired() ? "Required" : "Optional"
|
||||
)).collect(Collectors.joining(", ")))
|
||||
).color(NamedTextColor.GRAY))
|
||||
))).toList()
|
||||
));
|
||||
|
||||
private final Function<HuskSync, Component> supplier;
|
||||
|
||||
StatusLine(@NotNull Function<HuskSync, Component> supplier) {
|
||||
this.supplier = supplier;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Component get(@NotNull HuskSync plugin) {
|
||||
return Component
|
||||
.text("•").appendSpace()
|
||||
.append(Component.text(
|
||||
WordUtils.capitalizeFully(name().replaceAll("_", " ")),
|
||||
TextColor.color(0x848484)
|
||||
))
|
||||
.append(Component.text(':')).append(Component.space().color(NamedTextColor.WHITE))
|
||||
.append(supplier.apply(plugin));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Component getBoolean(boolean value) {
|
||||
return Component.text(value ? "Yes" : "No", value ? NamedTextColor.GREEN : NamedTextColor.RED);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Component getLocalhostBoolean(@NotNull String value) {
|
||||
return getBoolean(value.equals("127.0.0.1") || value.equals("0.0.0.0")
|
||||
|| value.equals("localhost") || value.equals("::1"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ import net.william278.husksync.redis.RedisKeyType;
|
||||
import net.william278.husksync.redis.RedisManager;
|
||||
import net.william278.husksync.user.CommandUser;
|
||||
import net.william278.husksync.user.User;
|
||||
import net.william278.husksync.util.DataDumper;
|
||||
import net.william278.husksync.util.UserDataDumper;
|
||||
import net.william278.husksync.util.DataSnapshotList;
|
||||
import net.william278.husksync.util.DataSnapshotOverview;
|
||||
import net.william278.uniform.BaseCommand;
|
||||
@@ -185,7 +185,7 @@ public class UserDataCommand extends PluginCommand {
|
||||
|
||||
// Dump the data
|
||||
final DataSnapshot.Packed userData = data.get();
|
||||
final DataDumper dumper = DataDumper.create(userData, user, plugin);
|
||||
final UserDataDumper dumper = UserDataDumper.create(userData, user, plugin);
|
||||
try {
|
||||
plugin.getLocales().getLocale("data_dumped", userData.getShortId(), user.getUsername(),
|
||||
(type == DumpType.WEB ? dumper.toWeb() : dumper.toFile()))
|
||||
|
||||
@@ -412,6 +412,33 @@ public class RedisManager extends JedisPubSub {
|
||||
}
|
||||
}
|
||||
|
||||
@Blocking
|
||||
public String getStatusDump() {
|
||||
try (Jedis jedis = jedisPool.getResource()) {
|
||||
return jedis.info();
|
||||
}
|
||||
}
|
||||
|
||||
@Blocking
|
||||
public long getLatency() {
|
||||
final long startTime = System.currentTimeMillis();
|
||||
try (Jedis jedis = jedisPool.getResource()) {
|
||||
jedis.ping();
|
||||
return startTime - System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
|
||||
@Blocking
|
||||
public String getVersion() {
|
||||
final String info = getStatusDump();
|
||||
for (String line : info.split("\n")) {
|
||||
if (line.startsWith("redis_version:")) {
|
||||
return line.split(":")[1];
|
||||
}
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
@Blocking
|
||||
public void terminate() {
|
||||
enabled = false;
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
|
||||
package net.william278.husksync.user;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.UUID;
|
||||
@@ -26,39 +29,18 @@ import java.util.UUID;
|
||||
/**
|
||||
* Represents a user who has their data synchronized by HuskSync
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(exclude = {"name"})
|
||||
public class User {
|
||||
|
||||
private final UUID uuid;
|
||||
private final String name;
|
||||
|
||||
private final String username;
|
||||
|
||||
public User(@NotNull UUID uuid, @NotNull String username) {
|
||||
this.username = username;
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user's unique account ID
|
||||
*/
|
||||
@NotNull
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user's username
|
||||
*/
|
||||
@NotNull
|
||||
@Deprecated(since = "3.7.4")
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
if (object instanceof User other) {
|
||||
return this.getUuid().equals(other.getUuid());
|
||||
}
|
||||
return super.equals(object);
|
||||
return name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* This file is part of HuskSync, licensed under the Apache License 2.0.
|
||||
*
|
||||
* Copyright (c) William278 <will27528@gmail.com>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.william278.husksync.util;
|
||||
|
||||
import net.william278.husksync.HuskSync;
|
||||
import net.william278.husksync.user.CommandUser;
|
||||
import net.william278.husksync.user.OnlineUser;
|
||||
import net.william278.toilet.DumpOptions;
|
||||
import net.william278.toilet.Toilet;
|
||||
import net.william278.toilet.dump.*;
|
||||
import org.jetbrains.annotations.Blocking;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import static net.william278.toilet.DumpOptions.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public interface DumpProvider {
|
||||
|
||||
@NotNull String BYTEBIN_URL = "https://bytebin.lucko.me";
|
||||
@NotNull String VIEWER_URL = "https://william278.net/dump";
|
||||
|
||||
@NotNull
|
||||
Toilet getToilet();
|
||||
|
||||
@NotNull
|
||||
@Blocking
|
||||
default String createDump(@NotNull CommandUser u) {
|
||||
return getToilet().dump(getPluginStatus(), u instanceof OnlineUser o
|
||||
? new DumpUser(o.getName(), o.getUuid()) : null,
|
||||
getRedisInfo()).toString();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
default DumpOptions getDumpOptions() {
|
||||
return builder()
|
||||
.bytebinUrl(BYTEBIN_URL)
|
||||
.viewerUrl(VIEWER_URL)
|
||||
.projectMeta(ProjectMeta.builder()
|
||||
.id("husksync")
|
||||
.name("HuskSync")
|
||||
.version(getPlugin().getPluginVersion().toString())
|
||||
.md5("unknown")
|
||||
.author("William278")
|
||||
.sourceCode("https://github.com/WiIIiam278/HuskSync")
|
||||
.website("https://william278.net/project/husksync")
|
||||
.support("https://discord.gg/tVYhJfyDWG")
|
||||
.build())
|
||||
.fileInclusionRules(List.of(
|
||||
FileInclusionRule.configFile("config.yml", "Config File"),
|
||||
FileInclusionRule.configFile(getMessagesFile(), "Locales File")
|
||||
))
|
||||
.compatibilityRules(List.of(
|
||||
getCompatibilityWarning("CombatLogX", "Combat loggers require additional" +
|
||||
"configuration for use with HuskSync. Check https://william278.net/docs/husksync/event-priorities"),
|
||||
getIncompatibleNotice("UltimateAutoRestart", "Restart plugins are not" +
|
||||
"compatible with HuskSync as they affect the way the server shuts down, preventing data" +
|
||||
"from saving correctly during a restart. Check https://william278.net/docs/husksync/troubleshooting")
|
||||
))
|
||||
.build();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Blocking
|
||||
private PluginStatus getPluginStatus() {
|
||||
return PluginStatus.builder()
|
||||
.blocks(List.of(getSystemStatus(), getRegisteredDataTypes()))
|
||||
.build();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Blocking
|
||||
private PluginStatus.MapStatusBlock getSystemStatus() {
|
||||
return new PluginStatus.MapStatusBlock(
|
||||
Map.ofEntries(
|
||||
Map.entry("Language", StatusLine.LANGUAGE.getValue(getPlugin())),
|
||||
Map.entry("Database Type", StatusLine.DATABASE_TYPE.getValue(getPlugin())),
|
||||
Map.entry("Database Local", StatusLine.IS_DATABASE_LOCAL.getValue(getPlugin())),
|
||||
Map.entry("Locked User Handler", StatusLine.LOCKED_USER_HANDLER.getValue(getPlugin())),
|
||||
Map.entry("Server Name", StatusLine.SERVER_NAME.getValue(getPlugin())),
|
||||
Map.entry("Redis Version", StatusLine.REDIS_VERSION.getValue(getPlugin())),
|
||||
Map.entry("Redis Latency", StatusLine.REDIS_LATENCY.getValue(getPlugin())),
|
||||
Map.entry("Redis Sentinel", StatusLine.USING_REDIS_SENTINEL.getValue(getPlugin())),
|
||||
Map.entry("Redis Password", StatusLine.USING_REDIS_PASSWORD.getValue(getPlugin())),
|
||||
Map.entry("Redis SSL", StatusLine.REDIS_USING_SSL.getValue(getPlugin())),
|
||||
Map.entry("Redis Local", StatusLine.IS_REDIS_LOCAL.getValue(getPlugin()))
|
||||
),
|
||||
"Plugin Status", "fa6-solid:wrench"
|
||||
);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Blocking
|
||||
private PluginStatus.MapStatusBlock getRegisteredDataTypes() {
|
||||
return new PluginStatus.MapStatusBlock(
|
||||
getPlugin().getRegisteredDataTypes().stream().collect(Collectors.toMap(
|
||||
i -> i.getKey().asMinimalString(),
|
||||
i -> i.isEnabled() ? "✅ Enabled" : "❌ Disabled",
|
||||
(a, b) -> a)
|
||||
),
|
||||
"Registered Data Types", "carbon:data-blob"
|
||||
);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Blocking
|
||||
private ExtraFile getRedisInfo() {
|
||||
return new ExtraFile(
|
||||
"redis-status", "Redis Status", "devicon-plain:redis",
|
||||
getPlugin().getRedisManager().getStatusDump(),
|
||||
"markdown"
|
||||
);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
private CompatibilityRule getCompatibilityWarning(@NotNull String plugin, @NotNull String description) {
|
||||
return CompatibilityRule.builder()
|
||||
.labelToApply(new PluginInfo.Label("Warning", "#fcba03", description))
|
||||
.resourceName(plugin).build();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
private CompatibilityRule getIncompatibleNotice(@NotNull String plugin, @NotNull String description) {
|
||||
return CompatibilityRule.builder()
|
||||
.labelToApply(new PluginInfo.Label("Incompatible", "#ff3300", description))
|
||||
.resourceName(plugin).build();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String getMessagesFile() {
|
||||
return "messages-%s.yml".formatted(getPlugin().getSettings().getLanguage());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
HuskSync getPlugin();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* This file is part of HuskSync, licensed under the Apache License 2.0.
|
||||
*
|
||||
* Copyright (c) William278 <will27528@gmail.com>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.william278.husksync.util;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.JoinConfiguration;
|
||||
import net.kyori.adventure.text.event.HoverEvent;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.format.TextColor;
|
||||
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||
import net.william278.husksync.HuskSync;
|
||||
import net.william278.husksync.database.Database;
|
||||
import org.apache.commons.text.WordUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public enum StatusLine {
|
||||
PLUGIN_VERSION(plugin -> Component.text("v" + plugin.getPluginVersion().toStringWithoutMetadata())
|
||||
.appendSpace().append(plugin.getPluginVersion().getMetadata().isBlank() ? Component.empty()
|
||||
: Component.text("(build " + plugin.getPluginVersion().getMetadata() + ")"))),
|
||||
SERVER_VERSION(plugin -> Component.text(plugin.getServerVersion())),
|
||||
LANGUAGE(plugin -> Component.text(plugin.getSettings().getLanguage())),
|
||||
MINECRAFT_VERSION(plugin -> Component.text(plugin.getMinecraftVersion().toString())),
|
||||
JAVA_VERSION(plugin -> Component.text(System.getProperty("java.version"))),
|
||||
JAVA_VENDOR(plugin -> Component.text(System.getProperty("java.vendor"))),
|
||||
SERVER_NAME(plugin -> Component.text(plugin.getServerName())),
|
||||
CLUSTER_ID(plugin -> Component.text(plugin.getSettings().getClusterId().isBlank() ? "None" : plugin.getSettings().getClusterId())),
|
||||
SYNC_MODE(plugin -> Component.text(WordUtils.capitalizeFully(
|
||||
plugin.getSettings().getSynchronization().getMode().toString()
|
||||
))),
|
||||
DELAY_LATENCY(plugin -> Component.text(
|
||||
plugin.getSettings().getSynchronization().getNetworkLatencyMilliseconds() + "ms"
|
||||
)),
|
||||
DATABASE_TYPE(plugin ->
|
||||
Component.text(plugin.getSettings().getDatabase().getType().getDisplayName() +
|
||||
(plugin.getSettings().getDatabase().getType() == Database.Type.MONGO ?
|
||||
(plugin.getSettings().getDatabase().getMongoSettings().isUsingAtlas() ? " Atlas" : "") : ""))
|
||||
),
|
||||
IS_DATABASE_LOCAL(plugin -> getLocalhostBoolean(plugin.getSettings().getDatabase().getCredentials().getHost())),
|
||||
REDIS_VERSION(plugin -> Component.text(plugin.getRedisManager().getVersion())),
|
||||
USING_REDIS_SENTINEL(plugin -> getBoolean(
|
||||
!plugin.getSettings().getRedis().getSentinel().getMaster().isBlank()
|
||||
)),
|
||||
USING_REDIS_PASSWORD(plugin -> getBoolean(
|
||||
!plugin.getSettings().getRedis().getCredentials().getPassword().isBlank()
|
||||
)),
|
||||
REDIS_USING_SSL(plugin -> getBoolean(
|
||||
plugin.getSettings().getRedis().getCredentials().isUseSsl()
|
||||
)),
|
||||
REDIS_LATENCY(plugin -> Component.text("%sms".formatted(plugin.getRedisManager().getLatency()))),
|
||||
IS_REDIS_LOCAL(plugin -> getLocalhostBoolean(
|
||||
plugin.getSettings().getRedis().getCredentials().getHost()
|
||||
)),
|
||||
LOCKED_USER_HANDLER(plugin -> Component.text(plugin.getLockedHandler().getClass().getSimpleName())),
|
||||
DATA_TYPES(plugin -> Component.join(
|
||||
JoinConfiguration.commas(true),
|
||||
plugin.getRegisteredDataTypes().stream().map(i -> Component.textOfChildren(Component.text(i.toString())
|
||||
.appendSpace().append(Component.text(i.isEnabled() ? '✔' : '❌')))
|
||||
.color(i.isEnabled() ? NamedTextColor.GREEN : NamedTextColor.RED)
|
||||
.hoverEvent(HoverEvent.showText(
|
||||
Component.text(i.isEnabled() ? "Enabled" : "Disabled")
|
||||
.append(Component.newline())
|
||||
.append(Component.text("Dependencies: %s".formatted(i.getDependencies()
|
||||
.isEmpty() ? "(None)" : i.getDependencies().stream()
|
||||
.map(d -> "%s (%s)".formatted(
|
||||
d.getKey().value(), d.isRequired() ? "Required" : "Optional"
|
||||
)).collect(Collectors.joining(", ")))
|
||||
).color(NamedTextColor.GRAY))
|
||||
))).toList()
|
||||
));
|
||||
|
||||
private final Function<HuskSync, Component> supplier;
|
||||
|
||||
StatusLine(@NotNull Function<HuskSync, Component> supplier) {
|
||||
this.supplier = supplier;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Component get(@NotNull HuskSync plugin) {
|
||||
return Component
|
||||
.text("•").appendSpace()
|
||||
.append(Component.text(
|
||||
WordUtils.capitalizeFully(name().replaceAll("_", " ")),
|
||||
TextColor.color(0x848484)
|
||||
))
|
||||
.append(Component.text(':')).append(Component.space().color(NamedTextColor.WHITE))
|
||||
.append(supplier.apply(plugin));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getValue(@NotNull HuskSync plugin) {
|
||||
return PlainTextComponentSerializer.plainText().serialize(supplier.apply(plugin));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Component getBoolean(boolean value) {
|
||||
return Component.text(value ? "Yes" : "No", value ? NamedTextColor.GREEN : NamedTextColor.RED);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Component getLocalhostBoolean(@NotNull String value) {
|
||||
return getBoolean(value.equals("127.0.0.1") || value.equals("0.0.0.0")
|
||||
|| value.equals("localhost") || value.equals("::1"));
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,7 @@ import java.util.logging.Level;
|
||||
/**
|
||||
* Utility class for dumping {@link DataSnapshot}s to a file or as a paste on the web
|
||||
*/
|
||||
public class DataDumper {
|
||||
public class UserDataDumper {
|
||||
|
||||
private static final String LOGS_SITE_ENDPOINT = "https://api.mclo.gs/1/log";
|
||||
|
||||
@@ -50,23 +50,23 @@ public class DataDumper {
|
||||
private final DataSnapshot.Packed snapshot;
|
||||
private final User user;
|
||||
|
||||
private DataDumper(@NotNull DataSnapshot.Packed snapshot, @NotNull User user, @NotNull HuskSync implementor) {
|
||||
private UserDataDumper(@NotNull DataSnapshot.Packed snapshot, @NotNull User user, @NotNull HuskSync implementor) {
|
||||
this.snapshot = snapshot;
|
||||
this.user = user;
|
||||
this.plugin = implementor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link DataDumper} of the given {@link DataSnapshot}
|
||||
* Create a {@link UserDataDumper} of the given {@link DataSnapshot}
|
||||
*
|
||||
* @param dataSnapshot The {@link DataSnapshot} to dump
|
||||
* @param user The {@link User} whose data is being dumped
|
||||
* @param plugin The implementing {@link HuskSync} plugin
|
||||
* @return A {@link DataDumper} for the given {@link DataSnapshot}
|
||||
* @return A {@link UserDataDumper} for the given {@link DataSnapshot}
|
||||
*/
|
||||
public static DataDumper create(@NotNull DataSnapshot.Packed dataSnapshot,
|
||||
@NotNull User user, @NotNull HuskSync plugin) {
|
||||
return new DataDumper(dataSnapshot, user, plugin);
|
||||
public static UserDataDumper create(@NotNull DataSnapshot.Packed dataSnapshot,
|
||||
@NotNull User user, @NotNull HuskSync plugin) {
|
||||
return new UserDataDumper(dataSnapshot, user, plugin);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -179,11 +179,11 @@ public class DataDumper {
|
||||
@NotNull
|
||||
private String getFileName() {
|
||||
return new StringJoiner("_")
|
||||
.add(user.getUsername())
|
||||
.add(snapshot.getTimestamp().format(DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm-ss")))
|
||||
.add(snapshot.getSaveCause().name().toLowerCase(Locale.ENGLISH))
|
||||
.add(snapshot.getShortId())
|
||||
+ ".json";
|
||||
.add(user.getUsername())
|
||||
.add(snapshot.getTimestamp().format(DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm-ss")))
|
||||
.add(snapshot.getSaveCause().name().toLowerCase(Locale.ENGLISH))
|
||||
.add(snapshot.getShortId())
|
||||
+ ".json";
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user