9
0
mirror of https://github.com/WiIIiam278/HuskSync.git synced 2025-12-19 14:59:21 +00:00

feat: add /husksync dump status dumping, close #460

This commit is contained in:
William278
2025-03-06 14:36:33 +00:00
parent 8b7e891ab6
commit b108d38598
30 changed files with 444 additions and 131 deletions

View File

@@ -10,6 +10,7 @@ dependencies {
implementation 'net.william278.uniform:uniform-bukkit:1.3.1' implementation 'net.william278.uniform:uniform-bukkit:1.3.1'
implementation 'net.william278.uniform:uniform-paper:1.3.1' implementation 'net.william278.uniform:uniform-paper:1.3.1'
implementation 'net.william278.toilet:toilet-bukkit:1.0.12'
implementation 'net.william278:mpdbdataconverter:1.0.1' implementation 'net.william278:mpdbdataconverter:1.0.1'
implementation 'net.william278:hsldataconverter:1.0' implementation 'net.william278:hsldataconverter:1.0'
implementation 'net.william278:mapdataapi:2.0' implementation 'net.william278:mapdataapi:2.0'
@@ -72,6 +73,7 @@ shadowJar {
relocate 'com.zaxxer', 'net.william278.husksync.libraries' relocate 'com.zaxxer', 'net.william278.husksync.libraries'
relocate 'de.exlll', 'net.william278.husksync.libraries' relocate 'de.exlll', 'net.william278.husksync.libraries'
relocate 'net.william278.uniform', 'net.william278.husksync.libraries.uniform' relocate 'net.william278.uniform', 'net.william278.husksync.libraries.uniform'
relocate 'net.william278.toilet', 'net.william278.husksync.libraries.toilet'
relocate 'net.william278.desertwell', 'net.william278.husksync.libraries.desertwell' relocate 'net.william278.desertwell', 'net.william278.husksync.libraries.desertwell'
relocate 'net.william278.paginedown', 'net.william278.husksync.libraries.paginedown' relocate 'net.william278.paginedown', 'net.william278.husksync.libraries.paginedown'
relocate 'net.william278.mapdataapi', 'net.william278.husksync.libraries.mapdataapi' relocate 'net.william278.mapdataapi', 'net.william278.husksync.libraries.mapdataapi'

View File

@@ -47,6 +47,7 @@ import net.william278.husksync.database.PostgresDatabase;
import net.william278.husksync.event.BukkitEventDispatcher; import net.william278.husksync.event.BukkitEventDispatcher;
import net.william278.husksync.hook.PlanHook; import net.william278.husksync.hook.PlanHook;
import net.william278.husksync.listener.BukkitEventListener; import net.william278.husksync.listener.BukkitEventListener;
import net.william278.husksync.listener.LockedHandler;
import net.william278.husksync.migrator.LegacyMigrator; import net.william278.husksync.migrator.LegacyMigrator;
import net.william278.husksync.migrator.Migrator; import net.william278.husksync.migrator.Migrator;
import net.william278.husksync.migrator.MpdbMigrator; import net.william278.husksync.migrator.MpdbMigrator;
@@ -58,6 +59,8 @@ import net.william278.husksync.util.BukkitLegacyConverter;
import net.william278.husksync.util.BukkitMapPersister; import net.william278.husksync.util.BukkitMapPersister;
import net.william278.husksync.util.BukkitTask; import net.william278.husksync.util.BukkitTask;
import net.william278.husksync.util.LegacyConverter; import net.william278.husksync.util.LegacyConverter;
import net.william278.toilet.BukkitToilet;
import net.william278.toilet.Toilet;
import net.william278.uniform.Uniform; import net.william278.uniform.Uniform;
import net.william278.uniform.bukkit.BukkitUniform; import net.william278.uniform.bukkit.BukkitUniform;
import org.bstats.bukkit.Metrics; import org.bstats.bukkit.Metrics;
@@ -100,6 +103,7 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync, BukkitTask.S
private boolean disabling; private boolean disabling;
private Gson gson; private Gson gson;
private AudienceProvider audiences; private AudienceProvider audiences;
private Toilet toilet;
private MorePaperLib paperLib; private MorePaperLib paperLib;
private Database database; private Database database;
private RedisManager redisManager; private RedisManager redisManager;
@@ -139,6 +143,7 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync, BukkitTask.S
@Override @Override
public void onEnable() { public void onEnable() {
this.audiences = BukkitAudiences.create(this); this.audiences = BukkitAudiences.create(this);
this.toilet = BukkitToilet.create(getDumpOptions());
// Check compatibility // Check compatibility
checkCompatibility(); checkCompatibility();
@@ -366,6 +371,12 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync, BukkitTask.S
return Optional.of(legacyConverter); return Optional.of(legacyConverter);
} }
@Override
@NotNull
public LockedHandler getLockedHandler() {
return eventListener.getLockedHandler();
}
@NotNull @NotNull
public GracefulScheduling getScheduler() { public GracefulScheduling getScheduler() {
return paperLib.scheduling(); return paperLib.scheduling();

View File

@@ -19,6 +19,7 @@
package net.william278.husksync.listener; package net.william278.husksync.listener;
import lombok.Getter;
import net.william278.husksync.BukkitHuskSync; import net.william278.husksync.BukkitHuskSync;
import net.william278.husksync.data.BukkitData; import net.william278.husksync.data.BukkitData;
import net.william278.husksync.user.BukkitUser; import net.william278.husksync.user.BukkitUser;
@@ -36,6 +37,7 @@ import org.jetbrains.annotations.NotNull;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Getter
public class BukkitEventListener extends EventListener implements BukkitJoinEventListener, BukkitQuitEventListener, public class BukkitEventListener extends EventListener implements BukkitJoinEventListener, BukkitQuitEventListener,
BukkitDeathEventListener, Listener { BukkitDeathEventListener, Listener {

View File

@@ -16,12 +16,15 @@ dependencies {
exclude module: 'slf4j-api' exclude module: 'slf4j-api'
} }
compileOnlyApi 'net.william278.toilet:toilet-common:1.0.12'
compileOnly 'net.william278.uniform:uniform-common:1.3.1' compileOnly 'net.william278.uniform:uniform-common:1.3.1'
compileOnly 'com.mojang:brigadier:1.1.8' compileOnly 'com.mojang:brigadier:1.1.8'
compileOnly 'org.projectlombok:lombok:1.18.36' compileOnly 'org.projectlombok:lombok:1.18.36'
compileOnly 'org.jetbrains:annotations:26.0.2' compileOnly 'org.jetbrains:annotations:26.0.2'
compileOnly 'net.kyori:adventure-api:4.18.0' compileOnly 'net.kyori:adventure-api:4.19.0'
compileOnly 'net.kyori:adventure-platform-api:4.3.4' compileOnly 'net.kyori:adventure-platform-api:4.3.4'
compileOnly "net.kyori:adventure-text-serializer-plain:4.19.0"
compileOnly 'com.google.guava:guava:33.4.0-jre' compileOnly 'com.google.guava:guava:33.4.0-jre'
compileOnly 'com.github.plan-player-analytics:Plan:5.5.2272' compileOnly 'com.github.plan-player-analytics:Plan:5.5.2272'
compileOnly "redis.clients:jedis:$jedis_version" compileOnly "redis.clients:jedis:$jedis_version"

View File

@@ -34,12 +34,14 @@ import net.william278.husksync.data.Identifier;
import net.william278.husksync.data.SerializerRegistry; import net.william278.husksync.data.SerializerRegistry;
import net.william278.husksync.database.Database; import net.william278.husksync.database.Database;
import net.william278.husksync.event.EventDispatcher; import net.william278.husksync.event.EventDispatcher;
import net.william278.husksync.listener.LockedHandler;
import net.william278.husksync.migrator.Migrator; import net.william278.husksync.migrator.Migrator;
import net.william278.husksync.redis.RedisManager; import net.william278.husksync.redis.RedisManager;
import net.william278.husksync.sync.DataSyncer; import net.william278.husksync.sync.DataSyncer;
import net.william278.husksync.user.ConsoleUser; import net.william278.husksync.user.ConsoleUser;
import net.william278.husksync.user.OnlineUser; import net.william278.husksync.user.OnlineUser;
import net.william278.husksync.util.CompatibilityChecker; import net.william278.husksync.util.CompatibilityChecker;
import net.william278.husksync.util.DumpProvider;
import net.william278.husksync.util.LegacyConverter; import net.william278.husksync.util.LegacyConverter;
import net.william278.husksync.util.Task; import net.william278.husksync.util.Task;
import net.william278.uniform.Uniform; import net.william278.uniform.Uniform;
@@ -54,7 +56,7 @@ import java.util.logging.Level;
* Abstract implementation of the HuskSync plugin. * Abstract implementation of the HuskSync plugin.
*/ */
public interface HuskSync extends Task.Supplier, EventDispatcher, ConfigProvider, SerializerRegistry, public interface HuskSync extends Task.Supplier, EventDispatcher, ConfigProvider, SerializerRegistry,
CompatibilityChecker { CompatibilityChecker, DumpProvider {
int SPIGOT_RESOURCE_ID = 97144; 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. * Get the set of UUIDs of "locked players", for which events will be canceled.
* </p> * </p>
@@ -340,12 +345,12 @@ public interface HuskSync extends Task.Supplier, EventDispatcher, ConfigProvider
private static final String FORMAT = """ private static final String FORMAT = """
HuskSync has failed to load! The plugin will not be enabled and no data will be synchronized. 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): 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 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 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) 3) Make sure your config is up-to-date (https://william278.net/docs/husksync/config-file)
4) Check the error below for more details 4) Check the error below for more details
Caused by: %s"""; Caused by: %s""";
public FailedToLoadException(@NotNull String message) { public FailedToLoadException(@NotNull String message) {

View File

@@ -24,9 +24,10 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException;
import de.themoep.minedown.adventure.MineDown; import de.themoep.minedown.adventure.MineDown;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.JoinConfiguration; 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.NamedTextColor;
import net.kyori.adventure.text.format.TextColor; import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.format.TextDecoration;
import net.william278.desertwell.about.AboutMenu; import net.william278.desertwell.about.AboutMenu;
import net.william278.desertwell.util.UpdateChecker; import net.william278.desertwell.util.UpdateChecker;
import net.william278.husksync.HuskSync; 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.migrator.Migrator;
import net.william278.husksync.user.CommandUser; import net.william278.husksync.user.CommandUser;
import net.william278.husksync.util.LegacyConverter; import net.william278.husksync.util.LegacyConverter;
import net.william278.husksync.util.StatusLine;
import net.william278.uniform.BaseCommand; import net.william278.uniform.BaseCommand;
import net.william278.uniform.CommandProvider; import net.william278.uniform.CommandProvider;
import net.william278.uniform.Permission; import net.william278.uniform.Permission;
import net.william278.uniform.element.ArgumentElement; import net.william278.uniform.element.ArgumentElement;
import org.apache.commons.text.WordUtils;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.time.OffsetDateTime; import java.time.OffsetDateTime;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.function.Function;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -98,6 +98,7 @@ public class HuskSyncCommand extends PluginCommand {
command.setDefaultExecutor((ctx) -> about(command, ctx)); command.setDefaultExecutor((ctx) -> about(command, ctx));
command.addSubCommand("about", (sub) -> sub.setDefaultExecutor((ctx) -> about(command, ctx))); command.addSubCommand("about", (sub) -> sub.setDefaultExecutor((ctx) -> about(command, ctx)));
command.addSubCommand("status", needsOp("status"), status()); command.addSubCommand("status", needsOp("status"), status());
command.addSubCommand("dump", needsOp("dump"), dump());
command.addSubCommand("reload", needsOp("reload"), reload()); command.addSubCommand("reload", needsOp("reload"), reload());
command.addSubCommand("update", needsOp("update"), update()); command.addSubCommand("update", needsOp("update"), update());
command.addSubCommand("forceupgrade", forceUpgrade()); 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 @NotNull
private CommandProvider reload() { private CommandProvider reload() {
return (sub) -> sub.setDefaultExecutor((ctx) -> { 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"));
}
}
} }

View File

@@ -26,7 +26,7 @@ import net.william278.husksync.redis.RedisKeyType;
import net.william278.husksync.redis.RedisManager; import net.william278.husksync.redis.RedisManager;
import net.william278.husksync.user.CommandUser; import net.william278.husksync.user.CommandUser;
import net.william278.husksync.user.User; 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.DataSnapshotList;
import net.william278.husksync.util.DataSnapshotOverview; import net.william278.husksync.util.DataSnapshotOverview;
import net.william278.uniform.BaseCommand; import net.william278.uniform.BaseCommand;
@@ -185,7 +185,7 @@ public class UserDataCommand extends PluginCommand {
// Dump the data // Dump the data
final DataSnapshot.Packed userData = data.get(); final DataSnapshot.Packed userData = data.get();
final DataDumper dumper = DataDumper.create(userData, user, plugin); final UserDataDumper dumper = UserDataDumper.create(userData, user, plugin);
try { try {
plugin.getLocales().getLocale("data_dumped", userData.getShortId(), user.getUsername(), plugin.getLocales().getLocale("data_dumped", userData.getShortId(), user.getUsername(),
(type == DumpType.WEB ? dumper.toWeb() : dumper.toFile())) (type == DumpType.WEB ? dumper.toWeb() : dumper.toFile()))

View File

@@ -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 @Blocking
public void terminate() { public void terminate() {
enabled = false; enabled = false;

View File

@@ -19,6 +19,9 @@
package net.william278.husksync.user; package net.william278.husksync.user;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.UUID; import java.util.UUID;
@@ -26,39 +29,18 @@ import java.util.UUID;
/** /**
* Represents a user who has their data synchronized by HuskSync * Represents a user who has their data synchronized by HuskSync
*/ */
@Getter
@AllArgsConstructor
@EqualsAndHashCode(exclude = {"name"})
public class User { public class User {
private final UUID uuid; 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 @NotNull
@Deprecated(since = "3.7.4")
public String getUsername() { public String getUsername() {
return username; return name;
}
@Override
public boolean equals(Object object) {
if (object instanceof User other) {
return this.getUuid().equals(other.getUuid());
}
return super.equals(object);
} }
} }

View File

@@ -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();
}

View File

@@ -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"));
}
}

View File

@@ -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 * 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"; 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 DataSnapshot.Packed snapshot;
private final User user; 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.snapshot = snapshot;
this.user = user; this.user = user;
this.plugin = implementor; 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 dataSnapshot The {@link DataSnapshot} to dump
* @param user The {@link User} whose data is being dumped * @param user The {@link User} whose data is being dumped
* @param plugin The implementing {@link HuskSync} plugin * @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, public static UserDataDumper create(@NotNull DataSnapshot.Packed dataSnapshot,
@NotNull User user, @NotNull HuskSync plugin) { @NotNull User user, @NotNull HuskSync plugin) {
return new DataDumper(dataSnapshot, user, plugin); return new UserDataDumper(dataSnapshot, user, plugin);
} }
/** /**
@@ -179,11 +179,11 @@ public class DataDumper {
@NotNull @NotNull
private String getFileName() { private String getFileName() {
return new StringJoiner("_") return new StringJoiner("_")
.add(user.getUsername()) .add(user.getUsername())
.add(snapshot.getTimestamp().format(DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm-ss"))) .add(snapshot.getTimestamp().format(DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm-ss")))
.add(snapshot.getSaveCause().name().toLowerCase(Locale.ENGLISH)) .add(snapshot.getSaveCause().name().toLowerCase(Locale.ENGLISH))
.add(snapshot.getShortId()) .add(snapshot.getShortId())
+ ".json"; + ".json";
} }
} }

View File

@@ -51,6 +51,9 @@ locales:
update_available: '[HuskSync](#ff7e5e bold) [| A new version of HuskSync is available: v%1% (running: v%2%).](#ff7e5e)' update_available: '[HuskSync](#ff7e5e bold) [| A new version of HuskSync is available: v%1% (running: v%2%).](#ff7e5e)'
reload_complete: '[HuskSync](#00fb9a bold) [| Презаредихме конфигурацията и файловете със съобщения.](#00fb9a)\n[⚠ Ensure config files are up-to-date on all servers!](#00fb9a)\n[A restart is needed for config changes to take effect.](#00fb9a italic)' reload_complete: '[HuskSync](#00fb9a bold) [| Презаредихме конфигурацията и файловете със съобщения.](#00fb9a)\n[⚠ Ensure config files are up-to-date on all servers!](#00fb9a)\n[A restart is needed for config changes to take effect.](#00fb9a italic)'
system_status_header: '[HuskSync](#00fb9a bold) [| System status report:](#00fb9a)' system_status_header: '[HuskSync](#00fb9a bold) [| System status report:](#00fb9a)'
system_dump_confirm: '[HuskSync](#00fb9a bold) [| Prepare a system dump? This will include:](#00fb9a)\n[• Your latest server logs and HuskSync config files](gray)\n[• Current plugin system status information](gray)\n[• Information about your Java & Minecraft server environment](gray)\n[• A list of other currently installed plugins](gray)\n[To confirm, use:](#00fb9a) [/husksync dump confirm](#00fb9a italic show_text=&7Click to prepare dump run_command=/husksync dump confirm)'
system_dump_started: '[HuskSync](#00fb9a bold) [| Preparing system status dump, please wait…](#00fb9a)'
system_dump_ready: '[HuskSync](#00fb9a bold) [| System status dump prepared! Click to view:](#00fb9a)'
error_invalid_syntax: '[Грешка:](#ff3300) [Неправилен синтаксис. Използвайте:](#ff7e5e) [%1%](#ff7e5e italic show_text=&#ff7e5e&Click to suggest suggest_command=%1%)' error_invalid_syntax: '[Грешка:](#ff3300) [Неправилен синтаксис. Използвайте:](#ff7e5e) [%1%](#ff7e5e italic show_text=&#ff7e5e&Click to suggest suggest_command=%1%)'
error_invalid_player: '[Грешка:](#ff3300) [Не можахме да открием играч с това име.](#ff7e5e)' error_invalid_player: '[Грешка:](#ff3300) [Не можахме да открием играч с това име.](#ff7e5e)'
error_invalid_data: '[Error:](#ff3300) [Failed to unpack user data as the snapshot is invalid or corrupt.](#ff7e5e) [(Details…)](gray show_text=&7⚠ %1%)' error_invalid_data: '[Error:](#ff3300) [Failed to unpack user data as the snapshot is invalid or corrupt.](#ff7e5e) [(Details…)](gray show_text=&7⚠ %1%)'

View File

@@ -51,6 +51,9 @@ locales:
up_to_date: '[HuskSync](#00fb9a bold) [| Du verwendest die neuste Version von HuskSync (v%1%).](#00fb9a)' up_to_date: '[HuskSync](#00fb9a bold) [| Du verwendest die neuste Version von HuskSync (v%1%).](#00fb9a)'
update_available: '[HuskSync](#ff7e5e bold) [| Eine neue Version von HuskSync ist verfügbar: v%1% (Aktuelle Version: v%2%).](#ff7e5e)' update_available: '[HuskSync](#ff7e5e bold) [| Eine neue Version von HuskSync ist verfügbar: v%1% (Aktuelle Version: v%2%).](#ff7e5e)'
system_status_header: '[HuskSync](#00fb9a bold) [| System status report:](#00fb9a)' system_status_header: '[HuskSync](#00fb9a bold) [| System status report:](#00fb9a)'
system_dump_confirm: '[HuskSync](#00fb9a bold) [| Prepare a system dump? This will include:](#00fb9a)\n[• Your latest server logs and HuskSync config files](gray)\n[• Current plugin system status information](gray)\n[• Information about your Java & Minecraft server environment](gray)\n[• A list of other currently installed plugins](gray)\n[To confirm, use:](#00fb9a) [/husksync dump confirm](#00fb9a italic show_text=&7Click to prepare dump run_command=/husksync dump confirm)'
system_dump_started: '[HuskSync](#00fb9a bold) [| Preparing system status dump, please wait…](#00fb9a)'
system_dump_ready: '[HuskSync](#00fb9a bold) [| System status dump prepared! Click to view:](#00fb9a)'
error_invalid_syntax: '[Fehler:](#ff3300) [Falsche Syntax. Nutze:](#ff7e5e) [%1%](#ff7e5e italic show_text=&#ff7e5e&Click to suggest suggest_command=%1%)' error_invalid_syntax: '[Fehler:](#ff3300) [Falsche Syntax. Nutze:](#ff7e5e) [%1%](#ff7e5e italic show_text=&#ff7e5e&Click to suggest suggest_command=%1%)'
error_invalid_player: '[Fehler:](#ff3300) [Es konnte kein Spieler mit diesem Namen gefunden werden.](#ff7e5e)' error_invalid_player: '[Fehler:](#ff3300) [Es konnte kein Spieler mit diesem Namen gefunden werden.](#ff7e5e)'
error_invalid_data: '[Error:](#ff3300) [Failed to unpack user data as the snapshot is invalid or corrupt.](#ff7e5e) [(Details…)](gray show_text=&7⚠ %1%)' error_invalid_data: '[Error:](#ff3300) [Failed to unpack user data as the snapshot is invalid or corrupt.](#ff7e5e) [(Details…)](gray show_text=&7⚠ %1%)'

View File

@@ -51,6 +51,9 @@ locales:
update_available: '[HuskSync](#ff7e5e bold) [| A new version of HuskSync is available: v%1% (running: v%2%).](#ff7e5e)' update_available: '[HuskSync](#ff7e5e bold) [| A new version of HuskSync is available: v%1% (running: v%2%).](#ff7e5e)'
reload_complete: '[HuskSync](#00fb9a bold) [| Reloaded config and message files.](#00fb9a)\n[⚠ Ensure config files are up-to-date on all servers!](#00fb9a)\n[A restart is needed for config changes to take effect.](#00fb9a italic)' reload_complete: '[HuskSync](#00fb9a bold) [| Reloaded config and message files.](#00fb9a)\n[⚠ Ensure config files are up-to-date on all servers!](#00fb9a)\n[A restart is needed for config changes to take effect.](#00fb9a italic)'
system_status_header: '[HuskSync](#00fb9a bold) [| System status report:](#00fb9a)' system_status_header: '[HuskSync](#00fb9a bold) [| System status report:](#00fb9a)'
system_dump_confirm: '[HuskSync](#00fb9a bold) [| Prepare a system dump? This will include:](#00fb9a)\n[• Your latest server logs and HuskSync config files](gray)\n[• Current plugin system status information](gray)\n[• Information about your Java & Minecraft server environment](gray)\n[• A list of other currently installed plugins](gray)\n[To confirm, use:](#00fb9a) [/husksync dump confirm](#00fb9a italic show_text=&7Click to prepare dump run_command=/husksync dump confirm)'
system_dump_started: '[HuskSync](#00fb9a bold) [| Preparing system status dump, please wait…](#00fb9a)'
system_dump_ready: '[HuskSync](#00fb9a bold) [| System status dump prepared! Click to view:](#00fb9a)'
error_invalid_syntax: '[Error:](#ff3300) [Incorrect syntax. Usage:](#ff7e5e) [%1%](#ff7e5e italic show_text=&#ff7e5e&Click to suggest suggest_command=%1%)' error_invalid_syntax: '[Error:](#ff3300) [Incorrect syntax. Usage:](#ff7e5e) [%1%](#ff7e5e italic show_text=&#ff7e5e&Click to suggest suggest_command=%1%)'
error_invalid_player: '[Error:](#ff3300) [Could not find a player by that name.](#ff7e5e)' error_invalid_player: '[Error:](#ff3300) [Could not find a player by that name.](#ff7e5e)'
error_invalid_data: '[Error:](#ff3300) [Failed to unpack user data as the snapshot is invalid or corrupt.](#ff7e5e) [(Details…)](gray show_text=&7⚠ %1%)' error_invalid_data: '[Error:](#ff3300) [Failed to unpack user data as the snapshot is invalid or corrupt.](#ff7e5e) [(Details…)](gray show_text=&7⚠ %1%)'

View File

@@ -51,6 +51,9 @@ locales:
update_available: '[HuskSync](#ff7e5e bold) [| A new version of HuskSync is available: v%1% (running: v%2%).](#ff7e5e)' update_available: '[HuskSync](#ff7e5e bold) [| A new version of HuskSync is available: v%1% (running: v%2%).](#ff7e5e)'
reload_complete: '[HuskSync](#00fb9a bold) [| Recargada la configuración y los archivos de lenguaje.](#00fb9a)\n[⚠ Ensure config files are up-to-date on all servers!](#00fb9a)\n[A restart is needed for config changes to take effect.](#00fb9a italic)' reload_complete: '[HuskSync](#00fb9a bold) [| Recargada la configuración y los archivos de lenguaje.](#00fb9a)\n[⚠ Ensure config files are up-to-date on all servers!](#00fb9a)\n[A restart is needed for config changes to take effect.](#00fb9a italic)'
system_status_header: '[HuskSync](#00fb9a bold) [| System status report:](#00fb9a)' system_status_header: '[HuskSync](#00fb9a bold) [| System status report:](#00fb9a)'
system_dump_confirm: '[HuskSync](#00fb9a bold) [| Prepare a system dump? This will include:](#00fb9a)\n[• Your latest server logs and HuskSync config files](gray)\n[• Current plugin system status information](gray)\n[• Information about your Java & Minecraft server environment](gray)\n[• A list of other currently installed plugins](gray)\n[To confirm, use:](#00fb9a) [/husksync dump confirm](#00fb9a italic show_text=&7Click to prepare dump run_command=/husksync dump confirm)'
system_dump_started: '[HuskSync](#00fb9a bold) [| Preparing system status dump, please wait…](#00fb9a)'
system_dump_ready: '[HuskSync](#00fb9a bold) [| System status dump prepared! Click to view:](#00fb9a)'
error_invalid_syntax: '[Error:](#ff3300) [Sintanxis incorrecta. Usa:](#ff7e5e) [%1%](#ff7e5e italic show_text=&#ff7e5e&Click to suggest suggest_command=%1%)' error_invalid_syntax: '[Error:](#ff3300) [Sintanxis incorrecta. Usa:](#ff7e5e) [%1%](#ff7e5e italic show_text=&#ff7e5e&Click to suggest suggest_command=%1%)'
error_invalid_player: '[Error:](#ff3300) [No se ha podido encontrar un jugador con ese nombre.](#ff7e5e)' error_invalid_player: '[Error:](#ff3300) [No se ha podido encontrar un jugador con ese nombre.](#ff7e5e)'
error_invalid_data: '[Error:](#ff3300) [Failed to unpack user data as the snapshot is invalid or corrupt.](#ff7e5e) [(Details…)](gray show_text=&7⚠ %1%)' error_invalid_data: '[Error:](#ff3300) [Failed to unpack user data as the snapshot is invalid or corrupt.](#ff7e5e) [(Details…)](gray show_text=&7⚠ %1%)'

View File

@@ -51,6 +51,9 @@ locales:
update_available: '[HuskSync](#ff7e5e bold) [| Une nouvelle version de HuskSync est disponible:v%1% (version actuelle: v%2%).](#ff7e5e)' update_available: '[HuskSync](#ff7e5e bold) [| Une nouvelle version de HuskSync est disponible:v%1% (version actuelle: v%2%).](#ff7e5e)'
reload_complete: '[HuskSync](#00fb9a bold) [| Config et messages rechargés.](#00fb9a)\n[⚠Assurez-vous que les fichiers de configuration sont à jour sur tous les serveurs!](#00fb9a)\n[Un redémarrage est nécessairepour que les modifications de configuration prennent effet.](#00fb9a italic)' reload_complete: '[HuskSync](#00fb9a bold) [| Config et messages rechargés.](#00fb9a)\n[⚠Assurez-vous que les fichiers de configuration sont à jour sur tous les serveurs!](#00fb9a)\n[Un redémarrage est nécessairepour que les modifications de configuration prennent effet.](#00fb9a italic)'
system_status_header: '[HuskSync](#00fb9a bold) [| Rapport d''état du système:](#00fb9a)' system_status_header: '[HuskSync](#00fb9a bold) [| Rapport d''état du système:](#00fb9a)'
system_dump_confirm: '[HuskSync](#00fb9a bold) [| Prepare a system dump? This will include:](#00fb9a)\n[• Your latest server logs and HuskSync config files](gray)\n[• Current plugin system status information](gray)\n[• Information about your Java & Minecraft server environment](gray)\n[• A list of other currently installed plugins](gray)\n[To confirm, use:](#00fb9a) [/husksync dump confirm](#00fb9a italic show_text=&7Click to prepare dump run_command=/husksync dump confirm)'
system_dump_started: '[HuskSync](#00fb9a bold) [| Preparing system status dump, please wait…](#00fb9a)'
system_dump_ready: '[HuskSync](#00fb9a bold) [| System status dump prepared! Click to view:](#00fb9a)'
error_invalid_syntax: '[Erreur:](#ff3300) [Syntaxe incorrecte. Utilisation:](#ff7e5e) [%1%](#ff7e5eitalic show_text=&#ff7e5e&Cliquez pour suggérer suggest_command=%1%)' error_invalid_syntax: '[Erreur:](#ff3300) [Syntaxe incorrecte. Utilisation:](#ff7e5e) [%1%](#ff7e5eitalic show_text=&#ff7e5e&Cliquez pour suggérer suggest_command=%1%)'
error_invalid_player: '[Erreur:](#ff3300) [Impossible de trouver un joueur avec ce nom.](#ff7e5e)' error_invalid_player: '[Erreur:](#ff3300) [Impossible de trouver un joueur avec ce nom.](#ff7e5e)'
error_invalid_data: '[Erreur:](#ff3300) [Impossible de déballer les données de l''instantané car elles sont invalides ou corrompues.](#ff7e5e) [(Détails…)](gray show_text=&7⚠ %1%)' error_invalid_data: '[Erreur:](#ff3300) [Impossible de déballer les données de l''instantané car elles sont invalides ou corrompues.](#ff7e5e) [(Détails…)](gray show_text=&7⚠ %1%)'

View File

@@ -51,6 +51,9 @@ locales:
update_available: '[HuskSync](#ff7e5e bold) [| Versi baru HuskSync tersedia: v%1% (menjalankan: v%2%).](#ff7e5e)' update_available: '[HuskSync](#ff7e5e bold) [| Versi baru HuskSync tersedia: v%1% (menjalankan: v%2%).](#ff7e5e)'
reload_complete: '[HuskSync](#00fb9a bold) [| Memuat ulang file konfigurasi dan pesan.](#00fb9a)\n[⚠ Pastikan file konfigurasi sudah diperbarui di semua server!](#00fb9a)\n[Diperlukan pengaktifan ulang agar perubahan konfigurasi dapat diterapkan.](#00fb9a italic)' reload_complete: '[HuskSync](#00fb9a bold) [| Memuat ulang file konfigurasi dan pesan.](#00fb9a)\n[⚠ Pastikan file konfigurasi sudah diperbarui di semua server!](#00fb9a)\n[Diperlukan pengaktifan ulang agar perubahan konfigurasi dapat diterapkan.](#00fb9a italic)'
system_status_header: '[HuskSync](#00fb9a bold) [| Laporan status sistem:](#00fb9a)' system_status_header: '[HuskSync](#00fb9a bold) [| Laporan status sistem:](#00fb9a)'
system_dump_confirm: '[HuskSync](#00fb9a bold) [| Prepare a system dump? This will include:](#00fb9a)\n[• Your latest server logs and HuskSync config files](gray)\n[• Current plugin system status information](gray)\n[• Information about your Java & Minecraft server environment](gray)\n[• A list of other currently installed plugins](gray)\n[To confirm, use:](#00fb9a) [/husksync dump confirm](#00fb9a italic show_text=&7Click to prepare dump run_command=/husksync dump confirm)'
system_dump_started: '[HuskSync](#00fb9a bold) [| Preparing system status dump, please wait…](#00fb9a)'
system_dump_ready: '[HuskSync](#00fb9a bold) [| System status dump prepared! Click to view:](#00fb9a)'
error_invalid_syntax: '[Kesalahan:](#ff3300) [Sintaks salah. Penggunaan:](#ff7e5e) [%1%](#ff7e5e italic show_text=&#ff7e5e&Klik untuk menyarankan suggest_command=%1%)' error_invalid_syntax: '[Kesalahan:](#ff3300) [Sintaks salah. Penggunaan:](#ff7e5e) [%1%](#ff7e5e italic show_text=&#ff7e5e&Klik untuk menyarankan suggest_command=%1%)'
error_invalid_player: '[Kesalahan:](#ff3300) [Tidak dapat menemukan pemain dengan nama tersebut.](#ff7e5e)' error_invalid_player: '[Kesalahan:](#ff3300) [Tidak dapat menemukan pemain dengan nama tersebut.](#ff7e5e)'
error_invalid_data: '[Error:](#ff3300) [Failed to unpack user data as the snapshot is invalid or corrupt.](#ff7e5e) [(Details…)](gray show_text=&7⚠ %1%)' error_invalid_data: '[Error:](#ff3300) [Failed to unpack user data as the snapshot is invalid or corrupt.](#ff7e5e) [(Details…)](gray show_text=&7⚠ %1%)'

View File

@@ -51,6 +51,9 @@ locales:
update_available: '[HuskSync](#ff7e5e bold) [| Disponibile una nuova versione: v%1% (running: v%2%).](#ff7e5e)' update_available: '[HuskSync](#ff7e5e bold) [| Disponibile una nuova versione: v%1% (running: v%2%).](#ff7e5e)'
reload_complete: '[HuskSync](#00fb9a bold) [| Configurazione e messaggi ricaricati.](#00fb9a)\n[⚠ Ensure config files are up-to-date on all servers!](#00fb9a)\n[A restart is needed for config changes to take effect.](#00fb9a italic)' reload_complete: '[HuskSync](#00fb9a bold) [| Configurazione e messaggi ricaricati.](#00fb9a)\n[⚠ Ensure config files are up-to-date on all servers!](#00fb9a)\n[A restart is needed for config changes to take effect.](#00fb9a italic)'
system_status_header: '[HuskSync](#00fb9a bold) [| System status report:](#00fb9a)' system_status_header: '[HuskSync](#00fb9a bold) [| System status report:](#00fb9a)'
system_dump_confirm: '[HuskSync](#00fb9a bold) [| Prepare a system dump? This will include:](#00fb9a)\n[• Your latest server logs and HuskSync config files](gray)\n[• Current plugin system status information](gray)\n[• Information about your Java & Minecraft server environment](gray)\n[• A list of other currently installed plugins](gray)\n[To confirm, use:](#00fb9a) [/husksync dump confirm](#00fb9a italic show_text=&7Click to prepare dump run_command=/husksync dump confirm)'
system_dump_started: '[HuskSync](#00fb9a bold) [| Preparing system status dump, please wait…](#00fb9a)'
system_dump_ready: '[HuskSync](#00fb9a bold) [| System status dump prepared! Click to view:](#00fb9a)'
error_invalid_syntax: '[Errore:](#ff3300) [Sintassi errata. Usa:](#ff7e5e) [%1%](#ff7e5e italic show_text=&#ff7e5e&Click to suggest suggest_command=%1%)' error_invalid_syntax: '[Errore:](#ff3300) [Sintassi errata. Usa:](#ff7e5e) [%1%](#ff7e5e italic show_text=&#ff7e5e&Click to suggest suggest_command=%1%)'
error_invalid_player: '[Errore:](#ff3300) [Impossibile trovare un giocatore con questo nome.](#ff7e5e)' error_invalid_player: '[Errore:](#ff3300) [Impossibile trovare un giocatore con questo nome.](#ff7e5e)'
error_invalid_data: '[Error:](#ff3300) [Failed to unpack user data as the snapshot is invalid or corrupt.](#ff7e5e) [(Details…)](gray show_text=&7⚠ %1%)' error_invalid_data: '[Error:](#ff3300) [Failed to unpack user data as the snapshot is invalid or corrupt.](#ff7e5e) [(Details…)](gray show_text=&7⚠ %1%)'

View File

@@ -51,6 +51,9 @@ locales:
update_available: '[HuskSync](#ff7e5e bold) [| HuskSyncの最新バージョンが更新されています: v%1% (実行中: v%2%).](#ff7e5e)' update_available: '[HuskSync](#ff7e5e bold) [| HuskSyncの最新バージョンが更新されています: v%1% (実行中: v%2%).](#ff7e5e)'
reload_complete: '[HuskSync](#00fb9a bold) [| 設定ファイルとメッセージファイルを再読み込みしました。](#00fb9a)\n[⚠ すべてのサーバーで設定ファイルが最新であることを確認してください!](#00fb9a)\n[設定の変更を有効にするには再起動が必要です。](#00fb9a italic)' reload_complete: '[HuskSync](#00fb9a bold) [| 設定ファイルとメッセージファイルを再読み込みしました。](#00fb9a)\n[⚠ すべてのサーバーで設定ファイルが最新であることを確認してください!](#00fb9a)\n[設定の変更を有効にするには再起動が必要です。](#00fb9a italic)'
system_status_header: '[HuskSync](#00fb9a bold) [| System status report:](#00fb9a)' system_status_header: '[HuskSync](#00fb9a bold) [| System status report:](#00fb9a)'
system_dump_confirm: '[HuskSync](#00fb9a bold) [| Prepare a system dump? This will include:](#00fb9a)\n[• Your latest server logs and HuskSync config files](gray)\n[• Current plugin system status information](gray)\n[• Information about your Java & Minecraft server environment](gray)\n[• A list of other currently installed plugins](gray)\n[To confirm, use:](#00fb9a) [/husksync dump confirm](#00fb9a italic show_text=&7Click to prepare dump run_command=/husksync dump confirm)'
system_dump_started: '[HuskSync](#00fb9a bold) [| Preparing system status dump, please wait…](#00fb9a)'
system_dump_ready: '[HuskSync](#00fb9a bold) [| System status dump prepared! Click to view:](#00fb9a)'
error_invalid_syntax: '[Error:](#ff3300) [構文が正しくありません。使用法:](#ff7e5e) [%1%](#ff7e5e italic show_text=&#ff7e5e&クリックでサジェスト suggest_command=%1%)' error_invalid_syntax: '[Error:](#ff3300) [構文が正しくありません。使用法:](#ff7e5e) [%1%](#ff7e5e italic show_text=&#ff7e5e&クリックでサジェスト suggest_command=%1%)'
error_invalid_player: '[Error:](#ff3300) [そのプレイヤーは見つかりませんでした](#ff7e5e)' error_invalid_player: '[Error:](#ff3300) [そのプレイヤーは見つかりませんでした](#ff7e5e)'
error_invalid_data: '[Error:](#ff3300) [Failed to unpack user data as the snapshot is invalid or corrupt.](#ff7e5e) [(Details…)](gray show_text=&7⚠ %1%)' error_invalid_data: '[Error:](#ff3300) [Failed to unpack user data as the snapshot is invalid or corrupt.](#ff7e5e) [(Details…)](gray show_text=&7⚠ %1%)'

View File

@@ -51,6 +51,9 @@ locales:
update_available: '[HuskSync](#ff7e5e bold) [| 새로운 버전의 HuskSync가 존재합니다: v%1% (현재 버전: v%2%).](#ff7e5e)' update_available: '[HuskSync](#ff7e5e bold) [| 새로운 버전의 HuskSync가 존재합니다: v%1% (현재 버전: v%2%).](#ff7e5e)'
reload_complete: '[HuskSync](#00fb9a bold) [| 콘피그와 메시지 파일을 다시 불러왔습니다.](#00fb9a)\n[⚠ 모든 서버의 컨피그 파일을 변경하였는지 확인하세요!](#00fb9a)\n[몇몇 설정은 재시작 후에 적용됩니다.](#00fb9a italic)' reload_complete: '[HuskSync](#00fb9a bold) [| 콘피그와 메시지 파일을 다시 불러왔습니다.](#00fb9a)\n[⚠ 모든 서버의 컨피그 파일을 변경하였는지 확인하세요!](#00fb9a)\n[몇몇 설정은 재시작 후에 적용됩니다.](#00fb9a italic)'
system_status_header: '[HuskSync](#00fb9a bold) [| System status report:](#00fb9a)' system_status_header: '[HuskSync](#00fb9a bold) [| System status report:](#00fb9a)'
system_dump_confirm: '[HuskSync](#00fb9a bold) [| Prepare a system dump? This will include:](#00fb9a)\n[• Your latest server logs and HuskSync config files](gray)\n[• Current plugin system status information](gray)\n[• Information about your Java & Minecraft server environment](gray)\n[• A list of other currently installed plugins](gray)\n[To confirm, use:](#00fb9a) [/husksync dump confirm](#00fb9a italic show_text=&7Click to prepare dump run_command=/husksync dump confirm)'
system_dump_started: '[HuskSync](#00fb9a bold) [| Preparing system status dump, please wait…](#00fb9a)'
system_dump_ready: '[HuskSync](#00fb9a bold) [| System status dump prepared! Click to view:](#00fb9a)'
error_invalid_syntax: '[오류:](#ff3300) [잘못된 사용법. 사용법:](#ff7e5e) [%1%](#ff7e5e italic show_text=&#ff7e5e&클릭하여 입력할 수 있습니다. suggest_command=%1%)' error_invalid_syntax: '[오류:](#ff3300) [잘못된 사용법. 사용법:](#ff7e5e) [%1%](#ff7e5e italic show_text=&#ff7e5e&클릭하여 입력할 수 있습니다. suggest_command=%1%)'
error_invalid_player: '[오류:](#ff3300) [해당 이름의 사용자를 찾을 수 없습니다.](#ff7e5e)' error_invalid_player: '[오류:](#ff3300) [해당 이름의 사용자를 찾을 수 없습니다.](#ff7e5e)'
error_invalid_data: '[Error:](#ff3300) [Failed to unpack user data as the snapshot is invalid or corrupt.](#ff7e5e) [(Details…)](gray show_text=&7⚠ %1%)' error_invalid_data: '[Error:](#ff3300) [Failed to unpack user data as the snapshot is invalid or corrupt.](#ff7e5e) [(Details…)](gray show_text=&7⚠ %1%)'

View File

@@ -51,6 +51,9 @@ locales:
update_available: '[HuskSync](#ff7e5e bold) [| Er is een nieuwe versie van HuskSync beschikbaar: v%1% (huidige versie: v%2%).](#ff7e5e)' update_available: '[HuskSync](#ff7e5e bold) [| Er is een nieuwe versie van HuskSync beschikbaar: v%1% (huidige versie: v%2%).](#ff7e5e)'
reload_complete: '[HuskSync](#00fb9a bold) [| Configuratie- en berichtbestanden opnieuw geladen.](#00fb9a)\n[⚠ Controleer of de configuratiebestanden up-to-date zijn op alle servers!](#00fb9a)\n[Een herstart is nodig voor de configuratiewijzigingen van kracht te laten worden.](#00fb9a italic)' reload_complete: '[HuskSync](#00fb9a bold) [| Configuratie- en berichtbestanden opnieuw geladen.](#00fb9a)\n[⚠ Controleer of de configuratiebestanden up-to-date zijn op alle servers!](#00fb9a)\n[Een herstart is nodig voor de configuratiewijzigingen van kracht te laten worden.](#00fb9a italic)'
system_status_header: '[HuskSync](#00fb9a bold) [| System status report:](#00fb9a)' system_status_header: '[HuskSync](#00fb9a bold) [| System status report:](#00fb9a)'
system_dump_confirm: '[HuskSync](#00fb9a bold) [| Prepare a system dump? This will include:](#00fb9a)\n[• Your latest server logs and HuskSync config files](gray)\n[• Current plugin system status information](gray)\n[• Information about your Java & Minecraft server environment](gray)\n[• A list of other currently installed plugins](gray)\n[To confirm, use:](#00fb9a) [/husksync dump confirm](#00fb9a italic show_text=&7Click to prepare dump run_command=/husksync dump confirm)'
system_dump_started: '[HuskSync](#00fb9a bold) [| Preparing system status dump, please wait…](#00fb9a)'
system_dump_ready: '[HuskSync](#00fb9a bold) [| System status dump prepared! Click to view:](#00fb9a)'
error_invalid_syntax: '[Error:](#ff3300) [Onjuiste syntaxis. Gebruik:](#ff7e5e) [%1%](#ff7e5e italic show_text=&#ff7e5e&Click to suggest suggest_command=%1%)' error_invalid_syntax: '[Error:](#ff3300) [Onjuiste syntaxis. Gebruik:](#ff7e5e) [%1%](#ff7e5e italic show_text=&#ff7e5e&Click to suggest suggest_command=%1%)'
error_invalid_player: '[Error:](#ff3300) [Kan geen speler met die naam vinden.](#ff7e5e)' error_invalid_player: '[Error:](#ff3300) [Kan geen speler met die naam vinden.](#ff7e5e)'
error_invalid_data: '[Error:](#ff3300) [Failed to unpack user data as the snapshot is invalid or corrupt.](#ff7e5e) [(Details…)](gray show_text=&7⚠ %1%)' error_invalid_data: '[Error:](#ff3300) [Failed to unpack user data as the snapshot is invalid or corrupt.](#ff7e5e) [(Details…)](gray show_text=&7⚠ %1%)'

View File

@@ -51,6 +51,9 @@ locales:
update_available: '[HuskSync](#ff7e5e bold) [| A new version of HuskSync is available: v%1% (running: v%2%).](#ff7e5e)' update_available: '[HuskSync](#ff7e5e bold) [| A new version of HuskSync is available: v%1% (running: v%2%).](#ff7e5e)'
reload_complete: '[HuskSync](#00fb9a bold) [| Arquivos de configuração e mensagens recarregados.](#00fb9a)\n[⚠ Ensure config files are up-to-date on all servers!](#00fb9a)\n[A restart is needed for config changes to take effect.](#00fb9a italic)' reload_complete: '[HuskSync](#00fb9a bold) [| Arquivos de configuração e mensagens recarregados.](#00fb9a)\n[⚠ Ensure config files are up-to-date on all servers!](#00fb9a)\n[A restart is needed for config changes to take effect.](#00fb9a italic)'
system_status_header: '[HuskSync](#00fb9a bold) [| System status report:](#00fb9a)' system_status_header: '[HuskSync](#00fb9a bold) [| System status report:](#00fb9a)'
system_dump_confirm: '[HuskSync](#00fb9a bold) [| Prepare a system dump? This will include:](#00fb9a)\n[• Your latest server logs and HuskSync config files](gray)\n[• Current plugin system status information](gray)\n[• Information about your Java & Minecraft server environment](gray)\n[• A list of other currently installed plugins](gray)\n[To confirm, use:](#00fb9a) [/husksync dump confirm](#00fb9a italic show_text=&7Click to prepare dump run_command=/husksync dump confirm)'
system_dump_started: '[HuskSync](#00fb9a bold) [| Preparing system status dump, please wait…](#00fb9a)'
system_dump_ready: '[HuskSync](#00fb9a bold) [| System status dump prepared! Click to view:](#00fb9a)'
error_invalid_syntax: '[Error:](#ff3300) [Sintaxe incorreta. Utilize:](#ff7e5e) [%1%](#ff7e5e italic show_text=&#ff7e5e&Click to suggest suggest_command=%1%)' error_invalid_syntax: '[Error:](#ff3300) [Sintaxe incorreta. Utilize:](#ff7e5e) [%1%](#ff7e5e italic show_text=&#ff7e5e&Click to suggest suggest_command=%1%)'
error_invalid_player: '[Error:](#ff3300) [Não foi possível encontrar um jogador com esse nome.](#ff7e5e)' error_invalid_player: '[Error:](#ff3300) [Não foi possível encontrar um jogador com esse nome.](#ff7e5e)'
error_invalid_data: '[Error:](#ff3300) [Failed to unpack user data as the snapshot is invalid or corrupt.](#ff7e5e) [(Details…)](gray show_text=&7⚠ %1%)' error_invalid_data: '[Error:](#ff3300) [Failed to unpack user data as the snapshot is invalid or corrupt.](#ff7e5e) [(Details…)](gray show_text=&7⚠ %1%)'

View File

@@ -51,6 +51,9 @@ locales:
update_available: '[HuskSync](#ff7e5e bold) [| Доступна новая версия HuskSync: v%1% (текущая: v%2%).](#ff7e5e)' update_available: '[HuskSync](#ff7e5e bold) [| Доступна новая версия HuskSync: v%1% (текущая: v%2%).](#ff7e5e)'
reload_complete: '[HuskSync](#00fb9a bold) [| Конфигурация и файлы локализации перезагружены.](#00fb9a)\n[⚠ Убедитесь, что файлы конфигурации обновлены на всех серверах!](#00fb9a)\n[Необходима перезагрузка для вступления изменений конфигурации в силу.](#00fb9a italic)' reload_complete: '[HuskSync](#00fb9a bold) [| Конфигурация и файлы локализации перезагружены.](#00fb9a)\n[⚠ Убедитесь, что файлы конфигурации обновлены на всех серверах!](#00fb9a)\n[Необходима перезагрузка для вступления изменений конфигурации в силу.](#00fb9a italic)'
system_status_header: '[HuskSync](#00fb9a bold) [| System status report:](#00fb9a)' system_status_header: '[HuskSync](#00fb9a bold) [| System status report:](#00fb9a)'
system_dump_confirm: '[HuskSync](#00fb9a bold) [| Prepare a system dump? This will include:](#00fb9a)\n[• Your latest server logs and HuskSync config files](gray)\n[• Current plugin system status information](gray)\n[• Information about your Java & Minecraft server environment](gray)\n[• A list of other currently installed plugins](gray)\n[To confirm, use:](#00fb9a) [/husksync dump confirm](#00fb9a italic show_text=&7Click to prepare dump run_command=/husksync dump confirm)'
system_dump_started: '[HuskSync](#00fb9a bold) [| Preparing system status dump, please wait…](#00fb9a)'
system_dump_ready: '[HuskSync](#00fb9a bold) [| System status dump prepared! Click to view:](#00fb9a)'
error_invalid_syntax: '[Ошибка:](#ff3300) [Неправильный синтаксис. Используйте:](#ff7e5e) [%1%](#ff7e5e italic show_text=&#ff7e5e&Click to suggest suggest_command=%1%)' error_invalid_syntax: '[Ошибка:](#ff3300) [Неправильный синтаксис. Используйте:](#ff7e5e) [%1%](#ff7e5e italic show_text=&#ff7e5e&Click to suggest suggest_command=%1%)'
error_invalid_player: '[Ошибка:](#ff3300) [Не удалось найти игрока с данным именем.](#ff7e5e)' error_invalid_player: '[Ошибка:](#ff3300) [Не удалось найти игрока с данным именем.](#ff7e5e)'
error_invalid_data: '[Error:](#ff3300) [Failed to unpack user data as the snapshot is invalid or corrupt.](#ff7e5e) [(Details…)](gray show_text=&7⚠ %1%)' error_invalid_data: '[Error:](#ff3300) [Failed to unpack user data as the snapshot is invalid or corrupt.](#ff7e5e) [(Details…)](gray show_text=&7⚠ %1%)'

View File

@@ -51,6 +51,9 @@ locales:
update_available: '[HuskSync](#ff7e5e bold) [| HuskSync\''in yeni bir sürümü mevcut: v%1% (kullanılan sürüm: v%2%).](#ff7e5e)' update_available: '[HuskSync](#ff7e5e bold) [| HuskSync\''in yeni bir sürümü mevcut: v%1% (kullanılan sürüm: v%2%).](#ff7e5e)'
reload_complete: '[HuskSync](#00fb9a bold) [| Yapılandırma ve mesaj dosyaları yeniden yüklendi.](#00fb9a)\n[⚠ Lütfen yapılandırma dosyalarının tüm sunucularda güncel olduğundan emin olun!](#00fb9a)\n[Yapılandırma değişikliklerinin etkili olabilmesi için bir yeniden başlatma gereklidir.](#00fb9a italic)' reload_complete: '[HuskSync](#00fb9a bold) [| Yapılandırma ve mesaj dosyaları yeniden yüklendi.](#00fb9a)\n[⚠ Lütfen yapılandırma dosyalarının tüm sunucularda güncel olduğundan emin olun!](#00fb9a)\n[Yapılandırma değişikliklerinin etkili olabilmesi için bir yeniden başlatma gereklidir.](#00fb9a italic)'
system_status_header: '[HuskSync](#00fb9a bold) [| Sistem durumu raporu:](#00fb9a)' system_status_header: '[HuskSync](#00fb9a bold) [| Sistem durumu raporu:](#00fb9a)'
system_dump_confirm: '[HuskSync](#00fb9a bold) [| Prepare a system dump? This will include:](#00fb9a)\n[• Your latest server logs and HuskSync config files](gray)\n[• Current plugin system status information](gray)\n[• Information about your Java & Minecraft server environment](gray)\n[• A list of other currently installed plugins](gray)\n[To confirm, use:](#00fb9a) [/husksync dump confirm](#00fb9a italic show_text=&7Click to prepare dump run_command=/husksync dump confirm)'
system_dump_started: '[HuskSync](#00fb9a bold) [| Preparing system status dump, please wait…](#00fb9a)'
system_dump_ready: '[HuskSync](#00fb9a bold) [| System status dump prepared! Click to view:](#00fb9a)'
error_invalid_syntax: '[Hata:](#ff3300) [Yanlış sözdizimi. Kullanım:](#ff7e5e) [%1%](#ff7e5e italic show_text=&#ff7e5e&Öneri için tıklayın Suggest_command=%1%)' error_invalid_syntax: '[Hata:](#ff3300) [Yanlış sözdizimi. Kullanım:](#ff7e5e) [%1%](#ff7e5e italic show_text=&#ff7e5e&Öneri için tıklayın Suggest_command=%1%)'
error_invalid_player: '[Hata:](#ff3300) [Bu isimde bir oyuncu bulunamadı.](#ff7e5e)' error_invalid_player: '[Hata:](#ff3300) [Bu isimde bir oyuncu bulunamadı.](#ff7e5e)'
error_invalid_data: '[Error:](#ff3300) [Failed to unpack user data as the snapshot is invalid or corrupt.](#ff7e5e) [(Details…)](gray show_text=&7⚠ %1%)' error_invalid_data: '[Error:](#ff3300) [Failed to unpack user data as the snapshot is invalid or corrupt.](#ff7e5e) [(Details…)](gray show_text=&7⚠ %1%)'

View File

@@ -51,6 +51,9 @@ locales:
update_available: '[HuskSync](#ff7e5e bold) [| A new version of HuskSync is available: v%1% (running: v%2%).](#ff7e5e)' update_available: '[HuskSync](#ff7e5e bold) [| A new version of HuskSync is available: v%1% (running: v%2%).](#ff7e5e)'
reload_complete: '[HuskSync](#00fb9a bold) [| Перезавантажено конфіґ та файли повідомлень.](#00fb9a)\n[⚠ Ensure config files are up-to-date on all servers!](#00fb9a)\n[A restart is needed for config changes to take effect.](#00fb9a italic)' reload_complete: '[HuskSync](#00fb9a bold) [| Перезавантажено конфіґ та файли повідомлень.](#00fb9a)\n[⚠ Ensure config files are up-to-date on all servers!](#00fb9a)\n[A restart is needed for config changes to take effect.](#00fb9a italic)'
system_status_header: '[HuskSync](#00fb9a bold) [| System status report:](#00fb9a)' system_status_header: '[HuskSync](#00fb9a bold) [| System status report:](#00fb9a)'
system_dump_confirm: '[HuskSync](#00fb9a bold) [| Prepare a system dump? This will include:](#00fb9a)\n[• Your latest server logs and HuskSync config files](gray)\n[• Current plugin system status information](gray)\n[• Information about your Java & Minecraft server environment](gray)\n[• A list of other currently installed plugins](gray)\n[To confirm, use:](#00fb9a) [/husksync dump confirm](#00fb9a italic show_text=&7Click to prepare dump run_command=/husksync dump confirm)'
system_dump_started: '[HuskSync](#00fb9a bold) [| Preparing system status dump, please wait…](#00fb9a)'
system_dump_ready: '[HuskSync](#00fb9a bold) [| System status dump prepared! Click to view:](#00fb9a)'
error_invalid_syntax: '[Помилка:](#ff3300) [Неправильний синтакс. Використання:](#ff7e5e) [%1%](#ff7e5e italic show_text=&#ff7e5e&Click to suggest suggest_command=%1%)' error_invalid_syntax: '[Помилка:](#ff3300) [Неправильний синтакс. Використання:](#ff7e5e) [%1%](#ff7e5e italic show_text=&#ff7e5e&Click to suggest suggest_command=%1%)'
error_invalid_player: '[Помилка:](#ff3300) [Гравця не знайдено](#ff7e5e)' error_invalid_player: '[Помилка:](#ff3300) [Гравця не знайдено](#ff7e5e)'
error_invalid_data: '[Error:](#ff3300) [Failed to unpack user data as the snapshot is invalid or corrupt.](#ff7e5e) [(Details…)](gray show_text=&7⚠ %1%)' error_invalid_data: '[Error:](#ff3300) [Failed to unpack user data as the snapshot is invalid or corrupt.](#ff7e5e) [(Details…)](gray show_text=&7⚠ %1%)'

View File

@@ -51,6 +51,9 @@ locales:
update_available: '[HuskSync](#ff7e5e bold) [| 检测到HuskSync有新版本可以更新了:v%1%(当前版本:v%2%).](#ff7e5e)' update_available: '[HuskSync](#ff7e5e bold) [| 检测到HuskSync有新版本可以更新了:v%1%(当前版本:v%2%).](#ff7e5e)'
reload_complete: '[HuskSync](#00fb9a bold) [| 重新加载配置和消息文件完成.](#00fb9a)\n[⚠ 确保在所有服务器上更新配置文件!](#00fb9a)\n[需要重新启动才能使配置更改生效.](#00fb9a italic)' reload_complete: '[HuskSync](#00fb9a bold) [| 重新加载配置和消息文件完成.](#00fb9a)\n[⚠ 确保在所有服务器上更新配置文件!](#00fb9a)\n[需要重新启动才能使配置更改生效.](#00fb9a italic)'
system_status_header: '[HuskSync](#00fb9a bold) [| 系统状态报告:](#00fb9a)' system_status_header: '[HuskSync](#00fb9a bold) [| 系统状态报告:](#00fb9a)'
system_dump_confirm: '[HuskSync](#00fb9a bold) [| Prepare a system dump? This will include:](#00fb9a)\n[• Your latest server logs and HuskSync config files](gray)\n[• Current plugin system status information](gray)\n[• Information about your Java & Minecraft server environment](gray)\n[• A list of other currently installed plugins](gray)\n[To confirm, use:](#00fb9a) [/husksync dump confirm](#00fb9a italic show_text=&7Click to prepare dump run_command=/husksync dump confirm)'
system_dump_started: '[HuskSync](#00fb9a bold) [| Preparing system status dump, please wait…](#00fb9a)'
system_dump_ready: '[HuskSync](#00fb9a bold) [| System status dump prepared! Click to view:](#00fb9a)'
error_invalid_syntax: '[错误:](#ff3300) [语法错误.用法:](#ff7e5e) [%1%](#ff7e5e italic show_text=&#ff7e5e&点击建议 suggest_command=%1%)' error_invalid_syntax: '[错误:](#ff3300) [语法错误.用法:](#ff7e5e) [%1%](#ff7e5e italic show_text=&#ff7e5e&点击建议 suggest_command=%1%)'
error_invalid_player: '[错误:](#ff3300) [找不到这个名称的玩家.](#ff7e5e)' error_invalid_player: '[错误:](#ff3300) [找不到这个名称的玩家.](#ff7e5e)'
error_invalid_data: '[错误:](#ff3300) [无法解压缩快照数据, 因为它无效或已损坏.](#ff7e5e) [(详情…)](gray show_text=&7⚠ %1%)' error_invalid_data: '[错误:](#ff3300) [无法解压缩快照数据, 因为它无效或已损坏.](#ff7e5e) [(详情…)](gray show_text=&7⚠ %1%)'

View File

@@ -51,6 +51,9 @@ locales:
update_available: '[HuskSync](#ff7e5e bold) [| 發現可用的新版本: v%1% (running: v%2%).](#ff7e5e)' update_available: '[HuskSync](#ff7e5e bold) [| 發現可用的新版本: v%1% (running: v%2%).](#ff7e5e)'
reload_complete: '[HuskSync](#00fb9a bold) [| 配置和語言文件已重新加載。](#00fb9a)\n[⚠ 確保所有伺服器上的配置文件都是最新的!](#00fb9a)\n[重啟後配置變更才會生效。](#00fb9a italic)' reload_complete: '[HuskSync](#00fb9a bold) [| 配置和語言文件已重新加載。](#00fb9a)\n[⚠ 確保所有伺服器上的配置文件都是最新的!](#00fb9a)\n[重啟後配置變更才會生效。](#00fb9a italic)'
system_status_header: '[HuskSync](#00fb9a bold) [| 系統狀態報告:](#00fb9a)' system_status_header: '[HuskSync](#00fb9a bold) [| 系統狀態報告:](#00fb9a)'
system_dump_confirm: '[HuskSync](#00fb9a bold) [| Prepare a system dump? This will include:](#00fb9a)\n[• Your latest server logs and HuskSync config files](gray)\n[• Current plugin system status information](gray)\n[• Information about your Java & Minecraft server environment](gray)\n[• A list of other currently installed plugins](gray)\n[To confirm, use:](#00fb9a) [/husksync dump confirm](#00fb9a italic show_text=&7Click to prepare dump run_command=/husksync dump confirm)'
system_dump_started: '[HuskSync](#00fb9a bold) [| Preparing system status dump, please wait…](#00fb9a)'
system_dump_ready: '[HuskSync](#00fb9a bold) [| System status dump prepared! Click to view:](#00fb9a)'
error_invalid_syntax: '[錯誤:](#ff3300) [語法不正確,用法:](#ff7e5e) [%1%](#ff7e5e italic show_text=&#ff7e5e&點擊建議 suggest_command=%1%)' error_invalid_syntax: '[錯誤:](#ff3300) [語法不正確,用法:](#ff7e5e) [%1%](#ff7e5e italic show_text=&#ff7e5e&點擊建議 suggest_command=%1%)'
error_invalid_player: '[錯誤:](#ff3300) [找不到這位玩家](#ff7e5e)' error_invalid_player: '[錯誤:](#ff3300) [找不到這位玩家](#ff7e5e)'
error_invalid_data: '[錯誤:](#ff3300) [無法解壓使用者資料,因為快照無效或已損壞。](#ff7e5e) [(詳細資訊…)](gray show_text=&7⚠ %1%)' error_invalid_data: '[錯誤:](#ff3300) [無法解壓使用者資料,因為快照無效或已損壞。](#ff7e5e) [(詳細資訊…)](gray show_text=&7⚠ %1%)'

View File

@@ -15,6 +15,7 @@ dependencies {
modImplementation include("me.lucko:fabric-permissions-api:${fabric_permissions_api_version}") modImplementation include("me.lucko:fabric-permissions-api:${fabric_permissions_api_version}")
modImplementation include("eu.pb4:sgui:${fabric_sgui_version}") modImplementation include("eu.pb4:sgui:${fabric_sgui_version}")
modImplementation include("net.william278.uniform:uniform-fabric:1.3.1+${project.name}") modImplementation include("net.william278.uniform:uniform-fabric:1.3.1+${project.name}")
modImplementation include("net.william278.toilet:toilet-fabric:1.0.12+${project.name}")
modImplementation "net.fabricmc.fabric-api:fabric-api:${fabric_api_version}" modImplementation "net.fabricmc.fabric-api:fabric-api:${fabric_api_version}"
implementation include('org.apache.commons:commons-pool2:2.12.1') implementation include('org.apache.commons:commons-pool2:2.12.1')

View File

@@ -56,6 +56,7 @@ import net.william278.husksync.event.ModLoadedCallback;
import net.william278.husksync.hook.PlanHook; import net.william278.husksync.hook.PlanHook;
import net.william278.husksync.listener.EventListener; import net.william278.husksync.listener.EventListener;
import net.william278.husksync.listener.FabricEventListener; import net.william278.husksync.listener.FabricEventListener;
import net.william278.husksync.listener.LockedHandler;
import net.william278.husksync.migrator.Migrator; import net.william278.husksync.migrator.Migrator;
import net.william278.husksync.redis.RedisManager; import net.william278.husksync.redis.RedisManager;
import net.william278.husksync.sync.DataSyncer; import net.william278.husksync.sync.DataSyncer;
@@ -64,6 +65,8 @@ import net.william278.husksync.user.FabricUser;
import net.william278.husksync.user.OnlineUser; import net.william278.husksync.user.OnlineUser;
import net.william278.husksync.util.FabricTask; import net.william278.husksync.util.FabricTask;
import net.william278.husksync.util.LegacyConverter; import net.william278.husksync.util.LegacyConverter;
import net.william278.toilet.Toilet;
import net.william278.toilet.fabric.FabricToilet;
import net.william278.uniform.Uniform; import net.william278.uniform.Uniform;
import net.william278.uniform.fabric.FabricUniform; import net.william278.uniform.fabric.FabricUniform;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -118,9 +121,10 @@ public class FabricHuskSync implements DedicatedServerModInitializer, HuskSync,
//#else //#else
//$$ private FabricServerAudiences audiences; //$$ private FabricServerAudiences audiences;
//#endif //#endif
private Toilet toilet;
private Database database; private Database database;
private RedisManager redisManager; private RedisManager redisManager;
private EventListener eventListener; private FabricEventListener eventListener;
private DataAdapter dataAdapter; private DataAdapter dataAdapter;
@Setter @Setter
private DataSyncer dataSyncer; private DataSyncer dataSyncer;
@@ -168,6 +172,7 @@ public class FabricHuskSync implements DedicatedServerModInitializer, HuskSync,
//#else //#else
//$$ this.audiences = FabricServerAudiences.of(minecraftServer); //$$ this.audiences = FabricServerAudiences.of(minecraftServer);
//#endif //#endif
this.toilet = FabricToilet.create(getDumpOptions(), minecraftServer);
// Check compatibility // Check compatibility
checkCompatibility(); checkCompatibility();
@@ -411,6 +416,12 @@ public class FabricHuskSync implements DedicatedServerModInitializer, HuskSync,
return Optional.empty(); return Optional.empty();
} }
@Override
@NotNull
public LockedHandler getLockedHandler() {
return eventListener;
}
@Override @Override
@NotNull @NotNull
public FabricHuskSync getPlugin() { public FabricHuskSync getPlugin() {