mirror of
https://github.com/WiIIiam278/HuskSync.git
synced 2025-12-22 16:19:20 +00:00
Compare commits
58 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2aa33b2f2c | ||
|
|
972fee1bc7 | ||
|
|
efe34977b5 | ||
|
|
02ed9687ee | ||
|
|
08889a1739 | ||
|
|
9cf6d1eab6 | ||
|
|
33c2eb2237 | ||
|
|
299586aa86 | ||
|
|
05c988f2c7 | ||
|
|
8e0ad76968 | ||
|
|
4db162e78f | ||
|
|
272bc1278a | ||
|
|
35fdcf7106 | ||
|
|
48e087a3d7 | ||
|
|
ca000197e4 | ||
|
|
a6bab88cee | ||
|
|
f0c64df439 | ||
|
|
ac5ab56717 | ||
|
|
c2025350ba | ||
|
|
4c2bb5c6df | ||
|
|
fb069296e1 | ||
|
|
22eedc8522 | ||
|
|
664c8c3352 | ||
|
|
e7e6f9cfa7 | ||
|
|
5ec0f1b098 | ||
|
|
8fad075357 | ||
|
|
83e27cca83 | ||
|
|
729230a646 | ||
|
|
029407613f | ||
|
|
3d6ff7c30b | ||
|
|
5833ce955f | ||
|
|
b3a5091828 | ||
|
|
693209ff00 | ||
|
|
5d1bd7c3a9 | ||
|
|
7b8c75dbeb | ||
|
|
b7a30bd6e9 | ||
|
|
2daf5fedef | ||
|
|
5fd40915d0 | ||
|
|
c49700e9ec | ||
|
|
0f35331441 | ||
|
|
0153e14ce5 | ||
|
|
419434bdca | ||
|
|
f1be4d2d88 | ||
|
|
c973dc5f05 | ||
|
|
b530941687 | ||
|
|
c09fde4c36 | ||
|
|
8d3beab145 | ||
|
|
cdf666bde6 | ||
|
|
350528e394 | ||
|
|
a1d3e5fddc | ||
|
|
e096e58c45 | ||
|
|
75eafe57e2 | ||
|
|
0005392cd3 | ||
|
|
93913ca4ef | ||
|
|
aa09639e55 | ||
|
|
b205643fdd | ||
|
|
6fc827dedf | ||
|
|
b8aa1d9701 |
21
.github/dependabot.yml
vendored
21
.github/dependabot.yml
vendored
@@ -1,7 +1,22 @@
|
||||
# Dependabot configuration file for GitHub
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "gradle" # See documentation for possible values
|
||||
directory: "/" # Location of package manifests
|
||||
# CI workflow action updates
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "weekly"
|
||||
commit-message:
|
||||
prefix: "ci"
|
||||
|
||||
# Gradle package updates
|
||||
- package-ecosystem: "gradle"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
commit-message:
|
||||
prefix: "deps"
|
||||
ignore:
|
||||
- dependency-name: 'org.spigotmc:spigot-api'
|
||||
- dependency-name: 'org.papermc:paper-api'
|
||||
1
.github/funding.yml
vendored
1
.github/funding.yml
vendored
@@ -1,3 +1,4 @@
|
||||
# Funding metadata for GitHub
|
||||
|
||||
github: WiIIiam278
|
||||
custom: https://buymeacoff.ee/william278
|
||||
29
.github/workflows/ci.yml
vendored
29
.github/workflows/ci.yml
vendored
@@ -1,4 +1,3 @@
|
||||
# Builds, tests the project with Gradle
|
||||
name: CI Tests
|
||||
|
||||
on:
|
||||
@@ -17,21 +16,29 @@ jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v3
|
||||
- name: 'Checkout for CI 🛎️'
|
||||
uses: actions/checkout@v4
|
||||
- name: 'Set up JDK 17 📦'
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'temurin'
|
||||
- name: Build with Gradle
|
||||
- name: 'Build with Gradle 🏗️'
|
||||
uses: gradle/gradle-build-action@v2
|
||||
with:
|
||||
arguments: build test publish
|
||||
env:
|
||||
SNAPSHOTS_MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
|
||||
SNAPSHOTS_MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
|
||||
- name: Publish Test Report
|
||||
uses: mikepenz/action-junit-report@v3
|
||||
if: success() || failure() # always run even if the previous step fails
|
||||
SNAPSHOTS_MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
|
||||
SNAPSHOTS_MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
|
||||
- name: 'Publish Test Report 📊'
|
||||
uses: mikepenz/action-junit-report@v4
|
||||
if: success() || failure() # Continue on failure
|
||||
with:
|
||||
report_paths: '**/build/test-results/test/TEST-*.xml'
|
||||
report_paths: '**/build/test-results/test/TEST-*.xml'
|
||||
- name: 'Fetch Version Name 📝'
|
||||
run: |
|
||||
echo "::set-output name=VERSION_NAME::$(${{github.workspace}}/gradlew properties --no-daemon --console=plain -q | grep "^version:" | awk '{printf $2}')"
|
||||
id: fetch-version
|
||||
- name: Get Version
|
||||
run: |
|
||||
echo "version_name=${{steps.fetch-version.outputs.VERSION_NAME}}" >> $GITHUB_ENV
|
||||
18
.github/workflows/pr_tests.yml
vendored
18
.github/workflows/pr_tests.yml
vendored
@@ -1,4 +1,3 @@
|
||||
# Carry out tests on pull requests
|
||||
name: PR Tests
|
||||
|
||||
on:
|
||||
@@ -7,18 +6,25 @@ on:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
checks: write
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v3
|
||||
- name: 'Checkout for CI 🛎'
|
||||
uses: actions/checkout@v4
|
||||
- name: 'Set up JDK 17 📦'
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'temurin'
|
||||
- name: Test Pull Request
|
||||
- name: 'Build with Gradle 🏗️'
|
||||
uses: gradle/gradle-build-action@v2
|
||||
with:
|
||||
arguments: test
|
||||
arguments: test
|
||||
- name: 'Publish Test Report 📊'
|
||||
uses: mikepenz/action-junit-report@v4
|
||||
if: success() || failure() # Continue on failure
|
||||
with:
|
||||
report_paths: '**/build/test-results/test/TEST-*.xml'
|
||||
18
.github/workflows/release.yml
vendored
18
.github/workflows/release.yml
vendored
@@ -1,9 +1,8 @@
|
||||
# Builds, tests and publishes to maven when a release is published
|
||||
name: Release Tests
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [ published ]
|
||||
types: [ 'published' ]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -13,21 +12,22 @@ jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v3
|
||||
- name: 'Checkout for CI 🛎️'
|
||||
uses: actions/checkout@v4
|
||||
- name: 'Set up JDK 17 📦'
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'temurin'
|
||||
- name: Build with Gradle
|
||||
- name: 'Build with Gradle 🏗️'
|
||||
uses: gradle/gradle-build-action@v2
|
||||
with:
|
||||
arguments: build test publish
|
||||
env:
|
||||
RELEASES_MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
|
||||
RELEASES_MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
|
||||
- name: Publish Test Report
|
||||
uses: mikepenz/action-junit-report@v3
|
||||
if: success() || failure() # always run even if the previous step fails
|
||||
- name: 'Publish Test Report 📊'
|
||||
uses: mikepenz/action-junit-report@v4
|
||||
if: success() || failure() # Continue on failure
|
||||
with:
|
||||
report_paths: '**/build/test-results/test/TEST-*.xml'
|
||||
7
.github/workflows/update_docs.yml
vendored
7
.github/workflows/update_docs.yml
vendored
@@ -1,4 +1,3 @@
|
||||
# Update the GitHub Wiki documentation when a push is made to docs/
|
||||
name: Update Docs
|
||||
|
||||
on:
|
||||
@@ -17,9 +16,9 @@ jobs:
|
||||
deploy-wiki:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: 'Checkout Code'
|
||||
uses: actions/checkout@v3
|
||||
- name: 'Push Changes to Wiki'
|
||||
- name: 'Checkout for CI 🛎️'
|
||||
uses: actions/checkout@v4
|
||||
- name: 'Push Docs to Github Wiki 📄️'
|
||||
uses: Andrew-Chen-Wang/github-wiki-action@v3
|
||||
env:
|
||||
WIKI_DIR: 'docs/'
|
||||
|
||||
16
README.md
16
README.md
@@ -3,10 +3,10 @@
|
||||
<img src="images/banner.png" alt="HuskSync" />
|
||||
<a href="https://github.com/WiIIiam278/HuskSync/actions/workflows/ci.yml">
|
||||
<img src="https://img.shields.io/github/actions/workflow/status/WiIIiam278/HuskSync/ci.yml?branch=master&logo=github"/>
|
||||
</a>
|
||||
<a href="https://jitpack.io/#net.william278/HuskSync">
|
||||
<img src="https://img.shields.io/jitpack/version/net.william278/HuskSync?color=%2300fb9a&label=api&logo=gradle" />
|
||||
</a>
|
||||
</a>
|
||||
<a href="https://repo.william278.net/#/releases/net/william278/husksync/">
|
||||
<img src="https://repo.william278.net/api/badge/latest/releases/net/william278/husksync?color=00fb9a&name=Maven&prefix=v" />
|
||||
</a>
|
||||
<a href="https://discord.gg/tVYhJfyDWG">
|
||||
<img src="https://img.shields.io/discord/818135932103557162.svg?label=&logo=discord&logoColor=fff&color=7389D8&labelColor=6A7EC2" />
|
||||
</a>
|
||||
@@ -66,17 +66,17 @@ HuskSync is licensed under the Apache 2.0 license.
|
||||
Contributions to the project are welcome—feel free to open a pull request with new features, improvements and/or fixes!
|
||||
|
||||
### Support
|
||||
Due to its complexity, official support for HuskSync is provided through a paid model. This means that support is only available to users who have purchased a license to the plugin from Spigot, Polymart, or Craftaro and have provided proof of purchase. Please join our Discord server if you have done so and need help!
|
||||
Due to its complexity, official binaries and customer support for HuskSync is provided through a paid model. This means that support is only available to users who have purchased a license to the plugin from Spigot, Polymart, Craftaro, or BuiltByBit and have provided proof of purchase. Please join our Discord server if you have done so and need help!
|
||||
|
||||
### Translations
|
||||
Translations of the plugin locales are welcome to help make the plugin more accessible. Please submit a pull request with your translations as a `.yml` file.
|
||||
|
||||
- [Locales Directory](https://github.com/WiIIiam278/HuskSync/tree/master/common/src/main/resources/languages)
|
||||
- [English Locales](https://github.com/WiIIiam278/HuskSync/tree/master/common/src/main/resources/languages/en-gb.yml)
|
||||
- [Locales Directory](https://github.com/WiIIiam278/HuskSync/tree/master/common/src/main/resources/locales)
|
||||
- [English Locales](https://github.com/WiIIiam278/HuskSync/tree/master/common/src/main/resources/locales/en-gb.yml)
|
||||
|
||||
## Links
|
||||
- [Docs](https://william278.net/docs/husksync/) — Read the plugin documentation!
|
||||
- [Spigot](https://www.spigotmc.org/resources/husksync.97144/) — View the Spigot resource page (Also: [Polymart](https://polymart.org/resource/husksync.1634), [Craftaro](https://craftaro.com/marketplace/product/husksync.758))
|
||||
- [Spigot](https://www.spigotmc.org/resources/husksync.97144/) — View the Spigot resource page (Also: [Polymart](https://polymart.org/resource/husksync.1634), [Craftaro](https://craftaro.com/marketplace/product/husksync.758), [BuiltByBit](https://builtbybit.com/resources/husksync.34956/))
|
||||
- [Issues](https://github.com/WiIIiam278/HuskSync/issues) — File a bug report or feature request
|
||||
- [Discord](https://discord.gg/tVYhJfyDWG) — Get help, ask questions (Purchase required)
|
||||
- [bStats](https://bstats.org/plugin/bukkit/HuskSync%20-%20Bukkit/13140) — View plugin metrics
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
plugins {
|
||||
id 'com.github.johnrengelman.shadow' version '8.1.1'
|
||||
id 'org.cadixdev.licenser' version '0.6.1' apply false
|
||||
id 'org.ajoberstar.grgit' version '5.2.0'
|
||||
id 'org.ajoberstar.grgit' version '5.2.1'
|
||||
id 'maven-publish'
|
||||
id 'java'
|
||||
}
|
||||
@@ -48,9 +48,9 @@ allprojects {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.10.0'
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter-params:5.10.0'
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.10.0'
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.10.1'
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter-params:5.10.1'
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.10.1'
|
||||
}
|
||||
|
||||
test {
|
||||
|
||||
@@ -8,16 +8,16 @@ dependencies {
|
||||
implementation 'net.william278:andjam:1.0.2'
|
||||
implementation 'me.lucko:commodore:2.2'
|
||||
implementation 'net.kyori:adventure-platform-bukkit:4.3.1'
|
||||
implementation 'dev.triumphteam:triumph-gui:3.1.6'
|
||||
implementation 'dev.triumphteam:triumph-gui:3.1.7'
|
||||
implementation 'space.arim.morepaperlib:morepaperlib:0.4.3'
|
||||
implementation 'de.tr7zw:item-nbt-api:2.12.0'
|
||||
implementation 'de.tr7zw:item-nbt-api:2.12.2'
|
||||
|
||||
compileOnly 'org.spigotmc:spigot-api:1.16.5-R0.1-SNAPSHOT'
|
||||
compileOnly 'commons-io:commons-io:2.14.0'
|
||||
compileOnly 'org.json:json:20230618'
|
||||
compileOnly 'commons-io:commons-io:2.15.1'
|
||||
compileOnly 'org.json:json:20231013'
|
||||
compileOnly 'de.themoep:minedown-adventure:1.7.2-SNAPSHOT'
|
||||
compileOnly 'dev.dejvokep:boosted-yaml:1.3.1'
|
||||
compileOnly 'com.zaxxer:HikariCP:5.0.1'
|
||||
compileOnly 'com.zaxxer:HikariCP:5.1.0'
|
||||
compileOnly 'net.william278:DesertWell:2.0.4'
|
||||
compileOnly 'net.william278:annotaml:2.0.7'
|
||||
compileOnly 'net.william278:AdvancementAPI:97a9583413'
|
||||
@@ -36,7 +36,6 @@ shadowJar {
|
||||
relocate 'org.json', 'net.william278.husksync.libraries.json'
|
||||
relocate 'com.fatboyindustrial', 'net.william278.husksync.libraries'
|
||||
relocate 'de.themoep', 'net.william278.husksync.libraries'
|
||||
relocate 'net.kyori', 'net.william278.husksync.libraries'
|
||||
relocate 'org.jetbrains', 'net.william278.husksync.libraries'
|
||||
relocate 'org.intellij', 'net.william278.husksync.libraries'
|
||||
relocate 'com.zaxxer', 'net.william278.husksync.libraries'
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
package net.william278.husksync;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import net.kyori.adventure.platform.AudienceProvider;
|
||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
||||
import net.william278.desertwell.util.Version;
|
||||
import net.william278.husksync.adapter.DataAdapter;
|
||||
@@ -46,7 +47,6 @@ import net.william278.husksync.migrator.MpdbMigrator;
|
||||
import net.william278.husksync.redis.RedisManager;
|
||||
import net.william278.husksync.sync.DataSyncer;
|
||||
import net.william278.husksync.user.BukkitUser;
|
||||
import net.william278.husksync.user.ConsoleUser;
|
||||
import net.william278.husksync.user.OnlineUser;
|
||||
import net.william278.husksync.util.BukkitLegacyConverter;
|
||||
import net.william278.husksync.util.BukkitMapPersister;
|
||||
@@ -346,12 +346,6 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync, BukkitTask.S
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ConsoleUser getConsole() {
|
||||
return new ConsoleUser(audiences.console());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Version getPluginVersion() {
|
||||
@@ -415,7 +409,7 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync, BukkitTask.S
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public BukkitAudiences getAudiences() {
|
||||
public AudienceProvider getAudiences() {
|
||||
return audiences;
|
||||
}
|
||||
|
||||
|
||||
@@ -593,54 +593,54 @@ public abstract class BukkitData implements Data {
|
||||
@NotNull
|
||||
public static BukkitData.Statistics from(@NotNull StatisticsMap stats) {
|
||||
return new BukkitData.Statistics(
|
||||
stats.genericStats().entrySet().stream()
|
||||
.flatMap(entry -> {
|
||||
Statistic statistic = matchStatistic(entry.getKey());
|
||||
return statistic != null ? Stream.of(new AbstractMap.SimpleEntry<>(statistic, entry.getValue())) : Stream.empty();
|
||||
})
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)),
|
||||
stats.blockStats().entrySet().stream()
|
||||
.flatMap(entry -> {
|
||||
Statistic statistic = matchStatistic(entry.getKey());
|
||||
return statistic != null ? Stream.of(new AbstractMap.SimpleEntry<>(statistic, entry.getValue())) : Stream.empty();
|
||||
})
|
||||
.collect(Collectors.toMap(
|
||||
Map.Entry::getKey,
|
||||
entry -> entry.getValue().entrySet().stream()
|
||||
.flatMap(blockEntry -> {
|
||||
Material material = Material.matchMaterial(blockEntry.getKey());
|
||||
return material != null ? Stream.of(new AbstractMap.SimpleEntry<>(material, blockEntry.getValue())) : Stream.empty();
|
||||
stats.genericStats().entrySet().stream()
|
||||
.flatMap(entry -> {
|
||||
Statistic statistic = matchStatistic(entry.getKey());
|
||||
return statistic != null ? Stream.of(new AbstractMap.SimpleEntry<>(statistic, entry.getValue())) : Stream.empty();
|
||||
})
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))
|
||||
)),
|
||||
stats.itemStats().entrySet().stream()
|
||||
.flatMap(entry -> {
|
||||
Statistic statistic = matchStatistic(entry.getKey());
|
||||
return statistic != null ? Stream.of(new AbstractMap.SimpleEntry<>(statistic, entry.getValue())) : Stream.empty();
|
||||
})
|
||||
.collect(Collectors.toMap(
|
||||
Map.Entry::getKey,
|
||||
entry -> entry.getValue().entrySet().stream()
|
||||
.flatMap(itemEntry -> {
|
||||
Material material = Material.matchMaterial(itemEntry.getKey());
|
||||
return material != null ? Stream.of(new AbstractMap.SimpleEntry<>(material, itemEntry.getValue())) : Stream.empty();
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)),
|
||||
stats.blockStats().entrySet().stream()
|
||||
.flatMap(entry -> {
|
||||
Statistic statistic = matchStatistic(entry.getKey());
|
||||
return statistic != null ? Stream.of(new AbstractMap.SimpleEntry<>(statistic, entry.getValue())) : Stream.empty();
|
||||
})
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))
|
||||
)),
|
||||
stats.entityStats().entrySet().stream()
|
||||
.flatMap(entry -> {
|
||||
Statistic statistic = matchStatistic(entry.getKey());
|
||||
return statistic != null ? Stream.of(new AbstractMap.SimpleEntry<>(statistic, entry.getValue())) : Stream.empty();
|
||||
})
|
||||
.collect(Collectors.toMap(
|
||||
Map.Entry::getKey,
|
||||
entry -> entry.getValue().entrySet().stream()
|
||||
.flatMap(itemEntry -> {
|
||||
EntityType entityType = matchEntityType(itemEntry.getKey());
|
||||
return entityType != null ? Stream.of(new AbstractMap.SimpleEntry<>(entityType, itemEntry.getValue())) : Stream.empty();
|
||||
.collect(Collectors.toMap(
|
||||
Map.Entry::getKey,
|
||||
entry -> entry.getValue().entrySet().stream()
|
||||
.flatMap(blockEntry -> {
|
||||
Material material = Material.matchMaterial(blockEntry.getKey());
|
||||
return material != null ? Stream.of(new AbstractMap.SimpleEntry<>(material, blockEntry.getValue())) : Stream.empty();
|
||||
})
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))
|
||||
)),
|
||||
stats.itemStats().entrySet().stream()
|
||||
.flatMap(entry -> {
|
||||
Statistic statistic = matchStatistic(entry.getKey());
|
||||
return statistic != null ? Stream.of(new AbstractMap.SimpleEntry<>(statistic, entry.getValue())) : Stream.empty();
|
||||
})
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))
|
||||
))
|
||||
.collect(Collectors.toMap(
|
||||
Map.Entry::getKey,
|
||||
entry -> entry.getValue().entrySet().stream()
|
||||
.flatMap(itemEntry -> {
|
||||
Material material = Material.matchMaterial(itemEntry.getKey());
|
||||
return material != null ? Stream.of(new AbstractMap.SimpleEntry<>(material, itemEntry.getValue())) : Stream.empty();
|
||||
})
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))
|
||||
)),
|
||||
stats.entityStats().entrySet().stream()
|
||||
.flatMap(entry -> {
|
||||
Statistic statistic = matchStatistic(entry.getKey());
|
||||
return statistic != null ? Stream.of(new AbstractMap.SimpleEntry<>(statistic, entry.getValue())) : Stream.empty();
|
||||
})
|
||||
.collect(Collectors.toMap(
|
||||
Map.Entry::getKey,
|
||||
entry -> entry.getValue().entrySet().stream()
|
||||
.flatMap(itemEntry -> {
|
||||
EntityType entityType = matchEntityType(itemEntry.getKey());
|
||||
return entityType != null ? Stream.of(new AbstractMap.SimpleEntry<>(entityType, itemEntry.getValue())) : Stream.empty();
|
||||
})
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -822,10 +822,9 @@ public abstract class BukkitData implements Data {
|
||||
|
||||
@NotNull
|
||||
public static BukkitData.Health adapt(@NotNull Player player) {
|
||||
final double maxHealth = getMaxHealth(player);
|
||||
return from(
|
||||
Math.min(player.getHealth(), maxHealth),
|
||||
maxHealth,
|
||||
player.getHealth(),
|
||||
getMaxHealth(player),
|
||||
player.isHealthScaled() ? player.getHealthScale() : 0d
|
||||
);
|
||||
}
|
||||
@@ -834,64 +833,65 @@ public abstract class BukkitData implements Data {
|
||||
public void apply(@NotNull BukkitUser user, @NotNull BukkitHuskSync plugin) throws IllegalStateException {
|
||||
final Player player = user.getPlayer();
|
||||
|
||||
// Set base max health
|
||||
final AttributeInstance maxHealthAttribute = Objects.requireNonNull(
|
||||
player.getAttribute(Attribute.GENERIC_MAX_HEALTH), "Max health attribute was null"
|
||||
);
|
||||
double currentMaxHealth = maxHealthAttribute.getBaseValue();
|
||||
if (plugin.getSettings().doSynchronizeMaxHealth() && maxHealth != 0d) {
|
||||
maxHealthAttribute.setBaseValue(maxHealth);
|
||||
currentMaxHealth = maxHealth;
|
||||
// Set max health
|
||||
final AttributeInstance maxHealth = getMaxHealthAttribute(player);
|
||||
try {
|
||||
if (plugin.getSettings().doSynchronizeMaxHealth() && this.maxHealth != 0) {
|
||||
maxHealth.setBaseValue(this.maxHealth);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
plugin.log(Level.WARNING, String.format("Failed setting the max health of %s to %s",
|
||||
player.getName(), this.maxHealth), e);
|
||||
}
|
||||
|
||||
// Set health
|
||||
final double currentHealth = player.getHealth();
|
||||
if (health != currentHealth) {
|
||||
final double healthToSet = currentHealth > currentMaxHealth ? currentMaxHealth : health;
|
||||
try {
|
||||
player.setHealth(Math.min(healthToSet, currentMaxHealth));
|
||||
} catch (IllegalArgumentException e) {
|
||||
plugin.log(Level.WARNING, "Failed to set player health", e);
|
||||
}
|
||||
try {
|
||||
final double health = player.getHealth();
|
||||
player.setHealth(Math.min(health, maxHealth.getBaseValue()));
|
||||
} catch (Throwable e) {
|
||||
plugin.log(Level.WARNING, String.format("Failed setting the health of %s to %s",
|
||||
player.getName(), this.maxHealth), e);
|
||||
}
|
||||
|
||||
// Set health scale
|
||||
try {
|
||||
if (healthScale != 0d) {
|
||||
player.setHealthScale(healthScale);
|
||||
if (this.healthScale != 0d) {
|
||||
player.setHealthScaled(true);
|
||||
player.setHealthScale(this.healthScale);
|
||||
} else {
|
||||
player.setHealthScale(maxHealth);
|
||||
player.setHealthScaled(false);
|
||||
player.setHealthScale(this.maxHealth);
|
||||
}
|
||||
player.setHealthScaled(healthScale != 0D);
|
||||
} catch (IllegalArgumentException e) {
|
||||
plugin.log(Level.WARNING, "Failed to set player health scale", e);
|
||||
} catch (Throwable e) {
|
||||
plugin.log(Level.WARNING, String.format("Failed setting the health scale of %s to %s",
|
||||
player.getName(), this.healthScale), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Player}'s maximum health, minus any health boost effects
|
||||
*
|
||||
* @param player The {@link Player} to get the maximum health of
|
||||
* @return The {@link Player}'s max health
|
||||
*/
|
||||
// Returns the max health of a player, accounting for health boost potion effects
|
||||
private static double getMaxHealth(@NotNull Player player) {
|
||||
double maxHealth = Objects.requireNonNull(
|
||||
player.getAttribute(Attribute.GENERIC_MAX_HEALTH), "Max health attribute was null"
|
||||
).getBaseValue();
|
||||
// Get the base value of the attribute (ignore armor, items that give health boosts, etc.)
|
||||
double maxHealth = getMaxHealthAttribute(player).getBaseValue();
|
||||
|
||||
// If the player has additional health bonuses from synchronized potion effects,
|
||||
// subtract these from this number as they are synchronized separately
|
||||
// Subtract health boost potion effects from stored max health
|
||||
if (player.hasPotionEffect(PotionEffectType.HEALTH_BOOST) && maxHealth > 20d) {
|
||||
final PotionEffect healthBoost = Objects.requireNonNull(
|
||||
player.getPotionEffect(PotionEffectType.HEALTH_BOOST), "Health boost effect was null"
|
||||
);
|
||||
final double boostEffect = 4 * (healthBoost.getAmplifier() + 1);
|
||||
maxHealth -= boostEffect;
|
||||
maxHealth -= (4 * (healthBoost.getAmplifier() + 1));
|
||||
}
|
||||
|
||||
return maxHealth;
|
||||
}
|
||||
|
||||
// Returns the max health attribute of a player
|
||||
@NotNull
|
||||
private static AttributeInstance getMaxHealthAttribute(@NotNull Player player) {
|
||||
return Objects.requireNonNull(
|
||||
player.getAttribute(Attribute.GENERIC_MAX_HEALTH), "Max health attribute was null"
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getHealth() {
|
||||
return health;
|
||||
@@ -1093,7 +1093,7 @@ public abstract class BukkitData implements Data {
|
||||
final Player player = user.getPlayer();
|
||||
player.setGameMode(org.bukkit.GameMode.valueOf(gameMode));
|
||||
player.setAllowFlight(allowFlight);
|
||||
player.setFlying(isFlying);
|
||||
player.setFlying(allowFlight && isFlying);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -23,7 +23,6 @@ import de.themoep.minedown.adventure.MineDown;
|
||||
import dev.triumphteam.gui.builder.gui.StorageBuilder;
|
||||
import dev.triumphteam.gui.guis.Gui;
|
||||
import dev.triumphteam.gui.guis.StorageGui;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.roxeez.advancement.display.FrameType;
|
||||
import net.william278.andjam.Toast;
|
||||
import net.william278.husksync.BukkitHuskSync;
|
||||
@@ -77,12 +76,6 @@ public class BukkitUser extends OnlineUser implements BukkitUserDataHolder {
|
||||
return player == null || !player.isOnline();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Audience getAudience() {
|
||||
return ((BukkitHuskSync) plugin).getAudiences().player(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendToast(@NotNull MineDown title, @NotNull MineDown description,
|
||||
@NotNull String iconMaterial, @NotNull String backgroundType) {
|
||||
|
||||
@@ -211,7 +211,8 @@ public interface BukkitMapPersister {
|
||||
}
|
||||
|
||||
// Create a new map view renderer with the map data color at each pixel
|
||||
view.getRenderers().clear();
|
||||
// use view.removeRenderer() to remove all this maps renderers
|
||||
view.getRenderers().forEach(view::removeRenderer);
|
||||
view.addRenderer(new PersistentMapRenderer(canvasData));
|
||||
view.setLocked(true);
|
||||
view.setScale(MapView.Scale.NORMAL);
|
||||
@@ -306,6 +307,10 @@ public interface BukkitMapPersister {
|
||||
|
||||
// Set the map banners and markers
|
||||
final MapCursorCollection cursors = canvas.getCursors();
|
||||
while (cursors.size() > 0) {
|
||||
cursors.removeCursor(cursors.getCursor(0));
|
||||
}
|
||||
|
||||
canvasData.getBanners().forEach(banner -> cursors.addCursor(createBannerCursor(banner)));
|
||||
canvas.setCursors(cursors);
|
||||
}
|
||||
@@ -316,7 +321,7 @@ public interface BukkitMapPersister {
|
||||
return new MapCursor(
|
||||
(byte) banner.getPosition().getX(),
|
||||
(byte) banner.getPosition().getZ(),
|
||||
(byte) 0,
|
||||
(byte) 8, // Always rotate banners upright
|
||||
switch (banner.getColor().toLowerCase(Locale.ENGLISH)) {
|
||||
case "white" -> MapCursor.Type.BANNER_WHITE;
|
||||
case "orange" -> MapCursor.Type.BANNER_ORANGE;
|
||||
@@ -412,12 +417,13 @@ public interface BukkitMapPersister {
|
||||
@NotNull
|
||||
private MapData extractMapData() {
|
||||
final List<MapBanner> banners = new ArrayList<>();
|
||||
final String BANNER_PREFIX = "banner_";
|
||||
for (int i = 0; i < getCursors().size(); i++) {
|
||||
final MapCursor cursor = getCursors().getCursor(i);
|
||||
final String type = cursor.getType().name().toLowerCase(Locale.ENGLISH);
|
||||
if (type.startsWith("banner_")) {
|
||||
if (type.startsWith(BANNER_PREFIX)) {
|
||||
banners.add(new MapBanner(
|
||||
type.replaceAll("banner_", ""),
|
||||
type.replaceAll(BANNER_PREFIX, ""),
|
||||
cursor.getCaption() == null ? "" : cursor.getCaption(),
|
||||
cursor.getX(),
|
||||
mapView.getWorld() != null ? mapView.getWorld().getSeaLevel() : 128,
|
||||
|
||||
@@ -3,22 +3,23 @@ plugins {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api 'commons-io:commons-io:2.14.0'
|
||||
api 'org.apache.commons:commons-text:1.10.0'
|
||||
api 'commons-io:commons-io:2.15.1'
|
||||
api 'org.apache.commons:commons-text:1.11.0'
|
||||
api 'de.themoep:minedown-adventure:1.7.2-SNAPSHOT'
|
||||
api 'net.kyori:adventure-api:4.14.0'
|
||||
api 'org.json:json:20230618'
|
||||
api 'org.json:json:20231013'
|
||||
api 'com.google.code.gson:gson:2.10.1'
|
||||
api 'com.fatboyindustrial.gson-javatime-serialisers:gson-javatime-serialisers:1.1.2'
|
||||
api 'dev.dejvokep:boosted-yaml:1.3.1'
|
||||
api 'net.william278:annotaml:2.0.7'
|
||||
api 'net.william278:DesertWell:2.0.4'
|
||||
api 'net.william278:PagineDown:1.1'
|
||||
api('com.zaxxer:HikariCP:5.0.1') {
|
||||
api('com.zaxxer:HikariCP:5.1.0') {
|
||||
exclude module: 'slf4j-api'
|
||||
}
|
||||
|
||||
compileOnly 'org.jetbrains:annotations:24.0.1'
|
||||
compileOnly 'net.kyori:adventure-api:4.15.0'
|
||||
compileOnly 'net.kyori:adventure-platform-api:4.3.1'
|
||||
compileOnly 'org.jetbrains:annotations:24.1.0'
|
||||
compileOnly 'com.github.plan-player-analytics:Plan:5.5.2272'
|
||||
compileOnly "redis.clients:jedis:$jedis_version"
|
||||
compileOnly "com.mysql:mysql-connector-j:$mysql_driver_version"
|
||||
@@ -29,5 +30,5 @@ dependencies {
|
||||
testImplementation "redis.clients:jedis:$jedis_version"
|
||||
testImplementation "org.xerial.snappy:snappy-java:$snappy_version"
|
||||
testCompileOnly 'dev.dejvokep:boosted-yaml:1.3.1'
|
||||
testCompileOnly 'org.jetbrains:annotations:24.0.1'
|
||||
testCompileOnly 'org.jetbrains:annotations:24.1.0'
|
||||
}
|
||||
@@ -22,6 +22,8 @@ package net.william278.husksync;
|
||||
import com.fatboyindustrial.gsonjavatime.Converters;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.platform.AudienceProvider;
|
||||
import net.william278.annotaml.Annotaml;
|
||||
import net.william278.desertwell.util.ThrowingConsumer;
|
||||
import net.william278.desertwell.util.UpdateChecker;
|
||||
@@ -48,6 +50,7 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
|
||||
@@ -245,17 +248,46 @@ public interface HuskSync extends Task.Supplier, EventDispatcher {
|
||||
*/
|
||||
default void debug(@NotNull String message, @NotNull Throwable... throwable) {
|
||||
if (getSettings().doDebugLogging()) {
|
||||
log(Level.INFO, String.format("[DEBUG] %s", message), throwable);
|
||||
log(Level.INFO, getDebugString(message), throwable);
|
||||
}
|
||||
}
|
||||
|
||||
// Get the debug log message format
|
||||
@NotNull
|
||||
private String getDebugString(@NotNull String message) {
|
||||
return String.format("[DEBUG] [%s] %s", new SimpleDateFormat("mm:ss.SSS").format(new Date()), message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the console user
|
||||
* Get the {@link AudienceProvider} instance
|
||||
*
|
||||
* @return the {@link ConsoleUser}
|
||||
* @return the {@link AudienceProvider} instance
|
||||
* @since 1.0
|
||||
*/
|
||||
@NotNull
|
||||
ConsoleUser getConsole();
|
||||
AudienceProvider getAudiences();
|
||||
|
||||
/**
|
||||
* Get the {@link Audience} instance for the given {@link OnlineUser}
|
||||
*
|
||||
* @param user the {@link OnlineUser} to get the {@link Audience} for
|
||||
* @return the {@link Audience} instance
|
||||
*/
|
||||
@NotNull
|
||||
default Audience getAudience(@NotNull UUID user) {
|
||||
return getAudiences().player(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link ConsoleUser} instance
|
||||
*
|
||||
* @return the {@link ConsoleUser} instance
|
||||
* @since 1.0
|
||||
*/
|
||||
@NotNull
|
||||
default ConsoleUser getConsole() {
|
||||
return new ConsoleUser(getAudiences());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the plugin version
|
||||
|
||||
@@ -72,7 +72,8 @@ public class HuskSyncCommand extends Command implements TabProvider {
|
||||
AboutMenu.Credit.of("Ghost-chu").description("Simplified Chinese (zh-cn)"),
|
||||
AboutMenu.Credit.of("DJelly4K").description("Simplified Chinese (zh-cn)"),
|
||||
AboutMenu.Credit.of("Thourgard").description("Ukrainian (uk-ua)"),
|
||||
AboutMenu.Credit.of("xF3d3").description("Italian (it-it)"))
|
||||
AboutMenu.Credit.of("xF3d3").description("Italian (it-it)"),
|
||||
AboutMenu.Credit.of("cada3141").description("Korean (ko-kr)"))
|
||||
.buttons(
|
||||
AboutMenu.Link.of("https://william278.net/docs/husksync").text("Documentation").icon("⛏"),
|
||||
AboutMenu.Link.of("https://github.com/WiIIiam278/HuskSync/issues").text("Issues").icon("❌").color(TextColor.color(0xff9f0f)),
|
||||
|
||||
@@ -134,12 +134,23 @@ public class Settings {
|
||||
@YamlKey("redis.use_ssl")
|
||||
private boolean redisUseSsl = false;
|
||||
|
||||
@YamlComment("If you're using Redis Sentinel, specify the master set name. If you don't know what this is, don't change anything here.")
|
||||
@YamlKey("redis.sentinel.master")
|
||||
private String redisSentinelMaster = "";
|
||||
|
||||
@YamlComment("List of host:port pairs")
|
||||
@YamlKey("redis.sentinel.nodes")
|
||||
private List<String> redisSentinelNodes = new ArrayList<>();
|
||||
|
||||
@YamlKey("redis.sentinel.password")
|
||||
private String redisSentinelPassword = "";
|
||||
|
||||
|
||||
// Synchronization settings
|
||||
@YamlComment("The mode of data synchronization to use (DELAY or LOCKSTEP). DELAY should be fine for most networks."
|
||||
@YamlComment("The data synchronization mode to use (LOCKSTEP or DELAY). LOCKSTEP is recommended for most networks."
|
||||
+ " Docs: https://william278.net/docs/husksync/sync-modes")
|
||||
@YamlKey("synchronization.mode")
|
||||
private DataSyncer.Mode syncMode = DataSyncer.Mode.DELAY;
|
||||
private DataSyncer.Mode syncMode = DataSyncer.Mode.LOCKSTEP;
|
||||
|
||||
@YamlComment("The number of data snapshot backups that should be kept at once per user")
|
||||
@YamlKey("synchronization.max_user_data_snapshots")
|
||||
@@ -324,6 +335,21 @@ public class Settings {
|
||||
return redisUseSsl;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getRedisSentinelMaster() {
|
||||
return redisSentinelMaster;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<String> getRedisSentinelNodes() {
|
||||
return redisSentinelNodes;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getRedisSentinelPassword() {
|
||||
return redisSentinelPassword;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public DataSyncer.Mode getSyncMode() {
|
||||
return syncMode;
|
||||
|
||||
@@ -503,7 +503,10 @@ public class DataSnapshot {
|
||||
@NotNull
|
||||
public Builder timestamp(@NotNull OffsetDateTime timestamp) {
|
||||
if (timestamp.isAfter(OffsetDateTime.now())) {
|
||||
throw new IllegalArgumentException("Data snapshots cannot have a timestamp set in the future");
|
||||
throw new IllegalArgumentException("Data snapshots cannot have a timestamp set in the future! "
|
||||
+ "Make sure your database server time matches the server time.\n"
|
||||
+ "Current game server timestamp: " + OffsetDateTime.now() + " / "
|
||||
+ "Snapshot timestamp: " + timestamp);
|
||||
}
|
||||
this.timestamp = timestamp;
|
||||
return this;
|
||||
@@ -822,6 +825,11 @@ public class DataSnapshot {
|
||||
.replaceAll("_", " "), 18);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getLocale(@NotNull HuskSync plugin) {
|
||||
return plugin.getLocales().getRawLocale("save_cause_" + name().toLowerCase())
|
||||
.orElse(getDisplayName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -65,7 +65,7 @@ public abstract class EventListener {
|
||||
return;
|
||||
}
|
||||
plugin.lockPlayer(user.getUuid());
|
||||
plugin.runAsync(() -> plugin.getDataSyncer().saveUserData(user));
|
||||
plugin.getDataSyncer().saveUserData(user);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,15 +24,13 @@ import org.jetbrains.annotations.NotNull;
|
||||
import java.util.Locale;
|
||||
|
||||
public enum RedisKeyType {
|
||||
DATA_UPDATE(10),
|
||||
SERVER_SWITCH(10),
|
||||
DATA_CHECKOUT(60 * 60 * 24 * 7 * 52);
|
||||
|
||||
private final int timeToLive;
|
||||
LATEST_SNAPSHOT,
|
||||
SERVER_SWITCH,
|
||||
DATA_CHECKOUT;
|
||||
|
||||
RedisKeyType(int timeToLive) {
|
||||
this.timeToLive = timeToLive;
|
||||
}
|
||||
public static final int TTL_1_YEAR = 60 * 60 * 24 * 7 * 52; // 1 year
|
||||
public static final int TTL_10_SECONDS = 10; // 10 seconds
|
||||
|
||||
@NotNull
|
||||
public String getKeyPrefix(@NotNull String clusterId) {
|
||||
@@ -44,8 +42,4 @@ public enum RedisKeyType {
|
||||
);
|
||||
}
|
||||
|
||||
public int getTimeToLive() {
|
||||
return timeToLive;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,14 +24,11 @@ import net.william278.husksync.data.DataSnapshot;
|
||||
import net.william278.husksync.user.User;
|
||||
import org.jetbrains.annotations.Blocking;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import redis.clients.jedis.Jedis;
|
||||
import redis.clients.jedis.JedisPool;
|
||||
import redis.clients.jedis.JedisPoolConfig;
|
||||
import redis.clients.jedis.JedisPubSub;
|
||||
import redis.clients.jedis.*;
|
||||
import redis.clients.jedis.exceptions.JedisException;
|
||||
import redis.clients.jedis.util.Pool;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@@ -39,7 +36,7 @@ import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
|
||||
/**
|
||||
* Manages the connection to the Redis server, handling the caching of user data
|
||||
* Manages the connection to Redis, handling the caching of user data
|
||||
*/
|
||||
public class RedisManager extends JedisPubSub {
|
||||
|
||||
@@ -47,7 +44,7 @@ public class RedisManager extends JedisPubSub {
|
||||
|
||||
private final HuskSync plugin;
|
||||
private final String clusterId;
|
||||
private JedisPool jedisPool;
|
||||
private Pool<Jedis> jedisPool;
|
||||
private final Map<UUID, CompletableFuture<Optional<DataSnapshot.Packed>>> pendingRequests;
|
||||
|
||||
public RedisManager(@NotNull HuskSync plugin) {
|
||||
@@ -57,7 +54,7 @@ public class RedisManager extends JedisPubSub {
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the redis connection pool
|
||||
* Initialize Redis connection pool
|
||||
*/
|
||||
@Blocking
|
||||
public void initialize() throws IllegalStateException {
|
||||
@@ -71,15 +68,22 @@ public class RedisManager extends JedisPubSub {
|
||||
config.setMaxIdle(0);
|
||||
config.setTestOnBorrow(true);
|
||||
config.setTestOnReturn(true);
|
||||
this.jedisPool = password.isEmpty()
|
||||
? new JedisPool(config, host, port, 0, useSSL)
|
||||
: new JedisPool(config, host, port, 0, password, useSSL);
|
||||
Set<String> redisSentinelNodes = new HashSet<>(plugin.getSettings().getRedisSentinelNodes());
|
||||
if (redisSentinelNodes.isEmpty()) {
|
||||
this.jedisPool = password.isEmpty()
|
||||
? new JedisPool(config, host, port, 0, useSSL)
|
||||
: new JedisPool(config, host, port, 0, password, useSSL);
|
||||
} else {
|
||||
String sentinelPassword = plugin.getSettings().getRedisSentinelPassword();
|
||||
String redisSentinelMaster = plugin.getSettings().getRedisSentinelMaster();
|
||||
this.jedisPool = new JedisSentinelPool(redisSentinelMaster, redisSentinelNodes, password.isEmpty() ? null : password, sentinelPassword.isEmpty() ? null : sentinelPassword);
|
||||
}
|
||||
|
||||
// Ping the server to check the connection
|
||||
try {
|
||||
jedisPool.getResource().ping();
|
||||
} catch (JedisException e) {
|
||||
throw new IllegalStateException("Failed to establish connection with the Redis server. "
|
||||
throw new IllegalStateException("Failed to establish connection with Redis. "
|
||||
+ "Please check the supplied credentials in the config file", e);
|
||||
}
|
||||
|
||||
@@ -175,23 +179,23 @@ public class RedisManager extends JedisPubSub {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a user's data to the Redis server
|
||||
* Set a user's data to Redis
|
||||
*
|
||||
* @param user the user to set data for
|
||||
* @param data the user's data to set
|
||||
* @param user the user to set data for
|
||||
* @param data the user's data to set
|
||||
* @param timeToLive The time to cache the data for
|
||||
*/
|
||||
@Blocking
|
||||
public void setUserData(@NotNull User user, @NotNull DataSnapshot.Packed data) {
|
||||
public void setUserData(@NotNull User user, @NotNull DataSnapshot.Packed data, int timeToLive) {
|
||||
try (Jedis jedis = jedisPool.getResource()) {
|
||||
jedis.setex(
|
||||
getKey(RedisKeyType.DATA_UPDATE, user.getUuid(), clusterId),
|
||||
RedisKeyType.DATA_UPDATE.getTimeToLive(),
|
||||
getKey(RedisKeyType.LATEST_SNAPSHOT, user.getUuid(), clusterId),
|
||||
timeToLive,
|
||||
data.asBytes(plugin)
|
||||
);
|
||||
plugin.debug(String.format("[%s] Set %s key to redis at: %s", user.getUsername(),
|
||||
RedisKeyType.DATA_UPDATE.name(), new SimpleDateFormat("mm:ss.SSS").format(new Date())));
|
||||
plugin.debug(String.format("[%s] Set %s key on Redis", user.getUsername(), RedisKeyType.LATEST_SNAPSHOT));
|
||||
} catch (Throwable e) {
|
||||
plugin.log(Level.SEVERE, "An exception occurred setting a user's server switch", e);
|
||||
plugin.log(Level.SEVERE, "An exception occurred setting user data on Redis", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,11 +210,10 @@ public class RedisManager extends JedisPubSub {
|
||||
} else {
|
||||
jedis.del(getKey(RedisKeyType.DATA_CHECKOUT, user.getUuid(), clusterId));
|
||||
}
|
||||
plugin.debug(String.format("[%s] %s %s key to redis at: %s",
|
||||
checkedOut ? "set" : "removed", user.getUsername(), RedisKeyType.DATA_CHECKOUT.name(),
|
||||
new SimpleDateFormat("mm:ss.SSS").format(new Date())));
|
||||
plugin.debug(String.format("[%s] %s %s key to/from Redis", user.getUsername(),
|
||||
checkedOut ? "Set" : "Removed", RedisKeyType.DATA_CHECKOUT));
|
||||
} catch (Throwable e) {
|
||||
plugin.log(Level.SEVERE, "An exception occurred setting a user's server switch", e);
|
||||
plugin.log(Level.SEVERE, "An exception occurred setting checkout to", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,17 +223,16 @@ public class RedisManager extends JedisPubSub {
|
||||
final byte[] key = getKey(RedisKeyType.DATA_CHECKOUT, user.getUuid(), clusterId);
|
||||
final byte[] readData = jedis.get(key);
|
||||
if (readData != null) {
|
||||
plugin.debug("[" + user.getUsername() + "] Successfully read "
|
||||
+ RedisKeyType.DATA_CHECKOUT.name() + " key from redis at: " +
|
||||
new SimpleDateFormat("mm:ss.SSS").format(new Date()));
|
||||
return Optional.of(new String(readData, StandardCharsets.UTF_8));
|
||||
final String checkoutServer = new String(readData, StandardCharsets.UTF_8);
|
||||
plugin.debug(String.format("[%s] Waiting for %s %s key to be unset on Redis",
|
||||
user.getUsername(), checkoutServer, RedisKeyType.DATA_CHECKOUT));
|
||||
return Optional.of(checkoutServer);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
plugin.log(Level.SEVERE, "An exception occurred fetching a user's checkout key from redis", e);
|
||||
plugin.log(Level.SEVERE, "An exception occurred getting a user's checkout key from Redis", e);
|
||||
}
|
||||
plugin.debug("[" + user.getUsername() + "] Could not read " +
|
||||
RedisKeyType.DATA_CHECKOUT.name() + " key from redis at: " +
|
||||
new SimpleDateFormat("mm:ss.SSS").format(new Date()));
|
||||
plugin.debug(String.format("[%s] %s key not set on Redis", user.getUsername(),
|
||||
RedisKeyType.DATA_CHECKOUT));
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@@ -240,7 +242,7 @@ public class RedisManager extends JedisPubSub {
|
||||
try (Jedis jedis = jedisPool.getResource()) {
|
||||
final Set<String> keys = jedis.keys(keyFormat);
|
||||
if (keys == null) {
|
||||
plugin.log(Level.WARNING, "Checkout key set returned null from jedis during clearing");
|
||||
plugin.log(Level.WARNING, "Checkout key returned null from Redis during clearing");
|
||||
return;
|
||||
}
|
||||
for (String key : keys) {
|
||||
@@ -249,12 +251,12 @@ public class RedisManager extends JedisPubSub {
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
plugin.log(Level.SEVERE, "An exception occurred clearing users checked out on this server", e);
|
||||
plugin.log(Level.SEVERE, "An exception occurred clearing this server's checkout keys on Redis", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a user's server switch to the Redis server
|
||||
* Set a user's server switch to Redis
|
||||
*
|
||||
* @param user the user to set the server switch for
|
||||
*/
|
||||
@@ -263,17 +265,18 @@ public class RedisManager extends JedisPubSub {
|
||||
try (Jedis jedis = jedisPool.getResource()) {
|
||||
jedis.setex(
|
||||
getKey(RedisKeyType.SERVER_SWITCH, user.getUuid(), clusterId),
|
||||
RedisKeyType.SERVER_SWITCH.getTimeToLive(), new byte[0]
|
||||
RedisKeyType.TTL_10_SECONDS,
|
||||
new byte[0]
|
||||
);
|
||||
plugin.debug(String.format("[%s] Set %s key to redis at: %s", user.getUsername(),
|
||||
RedisKeyType.SERVER_SWITCH.name(), new SimpleDateFormat("mm:ss.SSS").format(new Date())));
|
||||
plugin.debug(String.format("[%s] Set %s key to Redis",
|
||||
user.getUsername(), RedisKeyType.SERVER_SWITCH));
|
||||
} catch (Throwable e) {
|
||||
plugin.log(Level.SEVERE, "An exception occurred setting a user's server switch", e);
|
||||
plugin.log(Level.SEVERE, "An exception occurred setting a user's server switch key from Redis", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a user's data from the Redis server and consume the key if found
|
||||
* Fetch a user's data from Redis and consume the key if found
|
||||
*
|
||||
* @param user The user to fetch data for
|
||||
* @return The user's data, if it's present on the database. Otherwise, an empty optional.
|
||||
@@ -281,17 +284,15 @@ public class RedisManager extends JedisPubSub {
|
||||
@Blocking
|
||||
public Optional<DataSnapshot.Packed> getUserData(@NotNull User user) {
|
||||
try (Jedis jedis = jedisPool.getResource()) {
|
||||
final byte[] key = getKey(RedisKeyType.DATA_UPDATE, user.getUuid(), clusterId);
|
||||
final byte[] key = getKey(RedisKeyType.LATEST_SNAPSHOT, user.getUuid(), clusterId);
|
||||
final byte[] dataByteArray = jedis.get(key);
|
||||
if (dataByteArray == null) {
|
||||
plugin.debug("[" + user.getUsername() + "] Could not read " +
|
||||
RedisKeyType.DATA_UPDATE.name() + " key from redis at: " +
|
||||
new SimpleDateFormat("mm:ss.SSS").format(new Date()));
|
||||
plugin.debug(String.format("[%s] Waiting for %s key from Redis",
|
||||
user.getUsername(), RedisKeyType.LATEST_SNAPSHOT));
|
||||
return Optional.empty();
|
||||
}
|
||||
plugin.debug("[" + user.getUsername() + "] Successfully read "
|
||||
+ RedisKeyType.DATA_UPDATE.name() + " key from redis at: " +
|
||||
new SimpleDateFormat("mm:ss.SSS").format(new Date()));
|
||||
plugin.debug(String.format("[%s] Read %s key from Redis",
|
||||
user.getUsername(), RedisKeyType.LATEST_SNAPSHOT));
|
||||
|
||||
// Consume the key (delete from redis)
|
||||
jedis.del(key);
|
||||
@@ -299,7 +300,7 @@ public class RedisManager extends JedisPubSub {
|
||||
// Use Snappy to decompress the json
|
||||
return Optional.of(DataSnapshot.deserialize(plugin, dataByteArray));
|
||||
} catch (Throwable e) {
|
||||
plugin.log(Level.SEVERE, "An exception occurred fetching a user's data from redis", e);
|
||||
plugin.log(Level.SEVERE, "An exception occurred getting a user's data from Redis", e);
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
@@ -310,20 +311,18 @@ public class RedisManager extends JedisPubSub {
|
||||
final byte[] key = getKey(RedisKeyType.SERVER_SWITCH, user.getUuid(), clusterId);
|
||||
final byte[] readData = jedis.get(key);
|
||||
if (readData == null) {
|
||||
plugin.debug("[" + user.getUsername() + "] Could not read " +
|
||||
RedisKeyType.SERVER_SWITCH.name() + " key from redis at: " +
|
||||
new SimpleDateFormat("mm:ss.SSS").format(new Date()));
|
||||
plugin.debug(String.format("[%s] Waiting for %s key from Redis",
|
||||
user.getUsername(), RedisKeyType.SERVER_SWITCH));
|
||||
return false;
|
||||
}
|
||||
plugin.debug("[" + user.getUsername() + "] Successfully read "
|
||||
+ RedisKeyType.SERVER_SWITCH.name() + " key from redis at: " +
|
||||
new SimpleDateFormat("mm:ss.SSS").format(new Date()));
|
||||
plugin.debug(String.format("[%s] Read %s key from Redis",
|
||||
user.getUsername(), RedisKeyType.SERVER_SWITCH));
|
||||
|
||||
// Consume the key (delete from redis)
|
||||
jedis.del(key);
|
||||
return true;
|
||||
} catch (Throwable e) {
|
||||
plugin.log(Level.SEVERE, "An exception occurred fetching a user's server switch from redis", e);
|
||||
plugin.log(Level.SEVERE, "An exception occurred getting a user's server switch from Redis", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,6 +114,8 @@ public abstract class DataSyncer {
|
||||
}
|
||||
if (plugin.isDisabling() || timesRun.getAndIncrement() > maxListenAttempts) {
|
||||
task.get().cancel();
|
||||
plugin.debug(String.format("[%s] Redis timed out after %s attempts; setting from database",
|
||||
user.getUsername(), timesRun.get()));
|
||||
setUserFromDatabase(user);
|
||||
return;
|
||||
}
|
||||
@@ -132,8 +134,8 @@ public abstract class DataSyncer {
|
||||
* @since 3.1
|
||||
*/
|
||||
public enum Mode {
|
||||
DELAY(DelayDataSyncer::new),
|
||||
LOCKSTEP(LockstepDataSyncer::new);
|
||||
LOCKSTEP(LockstepDataSyncer::new),
|
||||
DELAY(DelayDataSyncer::new);
|
||||
|
||||
private final Function<HuskSync, ? extends DataSyncer> supplier;
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ package net.william278.husksync.sync;
|
||||
|
||||
import net.william278.husksync.HuskSync;
|
||||
import net.william278.husksync.data.DataSnapshot;
|
||||
import net.william278.husksync.redis.RedisKeyType;
|
||||
import net.william278.husksync.user.OnlineUser;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -61,7 +62,7 @@ public class DelayDataSyncer extends DataSyncer {
|
||||
plugin.runAsync(() -> {
|
||||
plugin.getRedisManager().setUserServerSwitch(user);
|
||||
final DataSnapshot.Packed data = user.createSnapshot(DataSnapshot.SaveCause.DISCONNECT);
|
||||
plugin.getRedisManager().setUserData(user, data);
|
||||
plugin.getRedisManager().setUserData(user, data, RedisKeyType.TTL_10_SECONDS);
|
||||
plugin.getDatabase().addSnapshot(user, data);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ package net.william278.husksync.sync;
|
||||
|
||||
import net.william278.husksync.HuskSync;
|
||||
import net.william278.husksync.data.DataSnapshot;
|
||||
import net.william278.husksync.redis.RedisKeyType;
|
||||
import net.william278.husksync.user.OnlineUser;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -60,7 +61,7 @@ public class LockstepDataSyncer extends DataSyncer {
|
||||
public void saveUserData(@NotNull OnlineUser user) {
|
||||
plugin.runAsync(() -> {
|
||||
final DataSnapshot.Packed data = user.createSnapshot(DataSnapshot.SaveCause.DISCONNECT);
|
||||
plugin.getRedisManager().setUserData(user, data);
|
||||
plugin.getRedisManager().setUserData(user, data, RedisKeyType.TTL_1_YEAR);
|
||||
plugin.getRedisManager().setUserCheckedOut(user, false);
|
||||
plugin.getDatabase().addSnapshot(user, data);
|
||||
});
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
package net.william278.husksync.user;
|
||||
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.platform.AudienceProvider;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public final class ConsoleUser implements CommandUser {
|
||||
@@ -27,8 +28,8 @@ public final class ConsoleUser implements CommandUser {
|
||||
@NotNull
|
||||
private final Audience audience;
|
||||
|
||||
public ConsoleUser(@NotNull Audience console) {
|
||||
this.audience = console;
|
||||
public ConsoleUser(@NotNull AudienceProvider audiences) {
|
||||
this.audience = audiences.console();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -50,13 +50,11 @@ public abstract class OnlineUser extends User implements CommandUser, UserDataHo
|
||||
*/
|
||||
public abstract boolean isOffline();
|
||||
|
||||
/**
|
||||
* Get the player's adventure {@link Audience}
|
||||
*
|
||||
* @return the player's {@link Audience}
|
||||
*/
|
||||
@NotNull
|
||||
public abstract Audience getAudience();
|
||||
@Override
|
||||
public Audience getAudience() {
|
||||
return getPlugin().getAudience(getUuid());
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message to this player
|
||||
@@ -131,6 +129,9 @@ public abstract class OnlineUser extends User implements CommandUser, UserDataHo
|
||||
public void applySnapshot(@NotNull DataSnapshot.Packed snapshot, @NotNull DataSnapshot.UpdateCause cause) {
|
||||
getPlugin().fireEvent(getPlugin().getPreSyncEvent(this, snapshot), (event) -> {
|
||||
if (!isOffline()) {
|
||||
getPlugin().debug(String.format("Applying snapshot (%s) to %s (cause: %s)",
|
||||
snapshot.getShortId(), getUsername(), cause
|
||||
));
|
||||
UserDataHolder.super.applySnapshot(
|
||||
event.getData(), (succeeded) -> completeSync(succeeded, cause, getPlugin())
|
||||
);
|
||||
|
||||
@@ -56,7 +56,7 @@ public class DataSnapshotList {
|
||||
.ofPattern("dd/MM/yyyy, HH:mm")),
|
||||
snapshot.getTimestamp().format(DateTimeFormatter
|
||||
.ofPattern("MMM dd yyyy, HH:mm:ss.SSS")),
|
||||
snapshot.getSaveCause().getDisplayName(),
|
||||
snapshot.getSaveCause().getLocale(plugin),
|
||||
String.format("%.2fKiB", snapshot.getFileSize(plugin) / 1024f))
|
||||
.orElse("• " + snapshot.getId())).toList(),
|
||||
plugin.getLocales().getBaseChatList(6)
|
||||
|
||||
@@ -68,7 +68,7 @@ public class DataSnapshotOverview {
|
||||
locales.getLocale("data_manager_pinned")
|
||||
.ifPresent(user::sendMessage);
|
||||
}
|
||||
locales.getLocale("data_manager_cause", snapshot.getSaveCause().getDisplayName())
|
||||
locales.getLocale("data_manager_cause", snapshot.getSaveCause().getLocale(plugin))
|
||||
.ifPresent(user::sendMessage);
|
||||
locales.getLocale("data_manager_server", snapshot.getServerName())
|
||||
.ifPresent(user::sendMessage);
|
||||
|
||||
@@ -11,7 +11,7 @@ data_manager_title: '[Преглеждане потребителският сн
|
||||
data_manager_timestamp: '[⌚ %1%](#ffc43b-#f5c962 show_text=&7Клеймо на Версията:\n&8Когато данните са били запазени)'
|
||||
data_manager_pinned: '[※ Закачен снапшот](#d8ff2b show_text=&7Закачен:\n&8Снапшота на този потребител няма да бъде автоматично завъртан.)'
|
||||
data_manager_cause: '[⚑ %1%](#23a825-#36f539 show_text=&7Причина на Запазване:\n&8Какво е накарало данните да бъдат запазени)'
|
||||
data_manager_server: '[Ⓢ %1%](#ff87b3-#f5538e show_text=&7Server:\n&8Name of the server the data was saved on)'
|
||||
data_manager_server: '[☁ %1%](#ff87b3-#f5538e show_text=&7Server:\n&8Name of the server the data was saved on)'
|
||||
data_manager_size: '[⏏ %1%](color=#62a9f5-#7ab8fa show_text=&7Snapshot size:\n&8Estimated file size of the snapshot (in KiB))\n'
|
||||
data_manger_status: '[%1%](red)[/](gray)[%2%](red)[×](gray)[❤](red show_text=&7Точки кръв) [%3%](yellow)[×](gray)[🍖](yellow show_text=&7Точки глад) [ʟᴠ](green)[.](gray)[%4%](green show_text=&7Ниво опит) [🏹 %5%](dark_aqua show_text=&7Режим на игра)'
|
||||
data_manager_advancements_statistics: '[⭐ Напредъци: %1%](color=#ffc43b-#f5c962 show_text=&7Напредъци, в които имате прогрес:\n&8%2%) [⌛ Изиграно Време: %3%ʜʀs](color=#62a9f5-#7ab8fa show_text=&7Изиграно време в играта\n&8⚠ Базирано на статистики от играта)\n'
|
||||
@@ -34,6 +34,17 @@ list_page_jumper_button: '[%1%](show_text=&7Jump to page %1% run_command=%2% %1%
|
||||
list_page_jumper_current_page: '[%1%](#00fb9a)'
|
||||
list_page_jumper_separator: ' '
|
||||
list_page_jumper_group_separator: '…'
|
||||
save_cause_disconnect: 'disconnect'
|
||||
save_cause_world_save: 'world save'
|
||||
save_cause_death: 'death'
|
||||
save_cause_server_shutdown: 'server shutdown'
|
||||
save_cause_inventory_command: 'inventory command'
|
||||
save_cause_enderchest_command: 'enderchest command'
|
||||
save_cause_backup_restore: 'backup restore'
|
||||
save_cause_api: 'API'
|
||||
save_cause_mpdb_migration: 'MPDB migration'
|
||||
save_cause_legacy_migration: 'legacy migration'
|
||||
save_cause_converted_from_v2: 'converted from v2'
|
||||
up_to_date: '[HuskSync](#00fb9a bold) [| You are running the latest version of HuskSync (v%1%).](#00fb9a)'
|
||||
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)'
|
||||
|
||||
@@ -6,13 +6,13 @@ inventory_viewer_opened: '[Du siehst den Schnappschuss des Inventares von](#00fb
|
||||
ender_chest_viewer_opened: '[Du siehst den Schnappschuss der Endertruhe von](#00fb9a) [%1%](#00fb9a bold) [von ⌚ %2%](#00fb9a)'
|
||||
data_update_complete: '[🔔 Deine Daten wurden aktualisiert!](#00fb9a)'
|
||||
data_update_failed: '[🔔 Ein Fehler ist beim Aktualisieren deiner Daten aufgetreten! Bitte kontaktiere einen Administrator.](#ff7e5e)'
|
||||
user_registration_complete: '[⭐ User registration complete!](#00fb9a)'
|
||||
user_registration_complete: '[⭐ Benutzer-Registrierung abgeschlossen!](#00fb9a)'
|
||||
data_manager_title: '[Du siehst den Nutzerdaten-Schnappschuss](#00fb9a) [%1%](#00fb9a show_text=&7Versions-UUID:\n&8%2%) [für %3%](#00fb9a bold show_text=&7Spieler-UUID:\n&8%4%)[:](#00fb9a)'
|
||||
data_manager_timestamp: '[⌚ %1%](#ffc43b-#f5c962 show_text=&7Versions-Zeitstempel:\n&8Zeitpunkt der Speicherung der Daten)'
|
||||
data_manager_pinned: '[※ Schnappschuss angeheftet](#d8ff2b show_text=&7Angeheftet:\n&8Dieser Nutzerdaten-Schnappschuss wird nicht automatisch rotiert.)'
|
||||
data_manager_cause: '[⚑ %1%](#23a825-#36f539 show_text=&7Speicherungsgrund:\n&8Der Grund für das Speichern der Daten)'
|
||||
data_manager_server: '[Ⓢ %1%](#ff87b3-#f5538e show_text=&7Server:\n&8Name of the server the data was saved on)'
|
||||
data_manager_size: '[⏏ %1%](color=#62a9f5-#7ab8fa show_text=&7Snapshot size:\n&8Estimated file size of the snapshot (in KiB))\n'
|
||||
data_manager_server: '[☁ %1%](#ff87b3-#f5538e show_text=&7Server:\n&8Name des Servers, auf dem die Daten gespeichert wurden)'
|
||||
data_manager_size: '[⏏ %1%](color=#62a9f5-#7ab8fa show_text=&7Schnappschuss-Größe:\n&8Geschätzte Dateigröße des Schnappschusses (in KiB))\n'
|
||||
data_manger_status: '[%1%](red)[/](gray)[%2%](red)[×](gray)[❤](red show_text=&7Lebenspunkte) [%3%](yellow)[×](gray)[🍖](yellow show_text=&7Hungerpunkte) [ʟᴠ](green)[.](gray)[%4%](green show_text=&7XP-Level) [🏹 %5%](dark_aqua show_text=&7Spielmodus)'
|
||||
data_manager_advancements_statistics: '[⭐ Erfolge: %1%](color=#ffc43b-#f5c962 show_text=&7Erfolge in denen du Fortschritt gemacht hast:\n&8%2%) [⌛ Spielzeit: %3%ʜʀs](color=#62a9f5-#7ab8fa show_text=&7Deine verbrachte Zeit im Spiel\n&8⚠ Basierend auf Spielstatistiken)\n'
|
||||
data_manager_item_buttons: '[Sehen:](gray) [[🪣 Inventar…]](color=#a17b5f-#f5b98c show_text=&7Klicke zum Ansehen run_command=/inventory %1% %2%) [[⌀ Endertruhe…]](#b649c4-#d254ff show_text=&7Klicke zum Ansehen run_command=/enderchest %1% %2%)'
|
||||
@@ -20,7 +20,7 @@ data_manager_management_buttons: '[Verwalten:](gray) [[❌ Löschen…]](#ff3300
|
||||
data_manager_system_buttons: '[System:](gray) [[⏷ Daten-Dump…]](dark_gray show_text=&7Klicke, um diesen rohen Nutzerdaten-Schnappschuss in eine Datei zu speichern.\n&8Daten-Dumps können unter ~/plugins/HuskSync/dumps/ gefunden werden. run_command=/husksync:userdata dump %1% %2% file) [[☂ Web-Dump…]](dark_gray show_text=&7Klicke, um diesen rohen Nutzerdaten-Schnappschuss auf den mc-logs Service hochzuladen.\n&8Du erhältst dann eine URL, die die Daten enthält. run_command=/husksync:userdata dump %1% %2% web)'
|
||||
data_manager_advancements_preview_remaining: 'und %1% weitere…'
|
||||
data_list_title: '[Nutzerdaten-Schnappschüsse von %1%:](#00fb9a) [(%2%-%3% von](#00fb9a) [%4%](#00fb9a bold)[)](#00fb9a)\n'
|
||||
data_list_item: '[%1%](gray show_text=&7User Data Snapshot for %2%&8⚡ %4% run_command=/userdata view %2% %3%) [%5%](#d8ff2b show_text=&7Pinned:\n&8Pinned snapshots won''t be automatically rotated. run_command=/userdata view %2% %3%) [%6%](color=#ffc43b-#f5c962 show_text=&7Version timestamp:&7\n&8When the data was saved\n&8%7% run_command=/userdata view %2% %3%) [⚑ %8%](#23a825-#36f539 show_text=&7Save cause:\n&8What caused the data to be saved run_command=/userdata view %2% %3%) [⏏ %9%](color=#62a9f5-#7ab8fa show_text=&7Snapshot size:&7\n&8Estimated file size of the snapshot (in KiB) run_command=/userdata view %2% %3%)'
|
||||
data_list_item: '[%1%](gray show_text=&7Nutzerdaten-Schnappschuss für %2%&8⚡ %4% run_command=/userdata view %2% %3%) [%5%](#d8ff2b show_text=&7Angeheftet:\n&8Angeheftete Schnappschüsse werden nicht automatisch rotiert. run_command=/userdata view %2% %3%) [%6%](color=#ffc43b-#f5c962 show_text=&7Versions-Zeitstempel:&7\n&8Zeitpunkt der Speicherung der Daten\n&8%7% run_command=/userdata view %2% %3%) [⚑ %8%](#23a825-#36f539 show_text=&7Speicherungsgrund:\n&8Grund für das Speichern der Daten run_command=/userdata view %2% %3%) [⏏ %9%](color=#62a9f5-#7ab8fa show_text=&7Schnappschuss-Größe:&7\n&8Geschätzte Dateigröße des Schnappschusses (in KiB) run_command=/userdata view %2% %3%)'
|
||||
data_deleted: '[❌ Nutzerdaten-Schnappschuss erfolgreich gelöscht](#00fb9a) [%1%](#00fb9a show_text=&7Version UUID:\n&8%2%) [für](#00fb9a) [%3%.](#00fb9a show_text=&7Player UUID:\n&8%4%)'
|
||||
data_restored: '[⏪ Erfgreich wiederhergestellt](#00fb9a) [Aktuelle Nutzerdaten des Schnappschusses von %1%](#00fb9a show_text=&7Spieler-UUID:\n&8%2%) [%3%.](#00fb9a show_text=&7Versions-UUID:\n&8%4%)'
|
||||
data_pinned: '[※ Nutzerdaten-Schnappschuss erfolgreich angepinnt](#00fb9a) [%1%](#00fb9a show_text=&7Versions-UUID:\n&8%2%) [für](#00fb9a) [%3%.](#00fb9a show_text=&7Spieler-UUID:\n&8%4%)'
|
||||
@@ -34,9 +34,20 @@ list_page_jumper_button: '[%1%](show_text=&7Springe zu Seite %1% run_command=%2%
|
||||
list_page_jumper_current_page: '[%1%](#00fb9a)'
|
||||
list_page_jumper_separator: ' '
|
||||
list_page_jumper_group_separator: '…'
|
||||
reload_complete: '[HuskSync](#00fb9a bold) [| Die Konfigurations- und Sprachdateien wurden neu geladen.](#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)'
|
||||
up_to_date: '[HuskSync](#00fb9a bold) [| You are running the latest version of HuskSync (v%1%).](#00fb9a)'
|
||||
update_available: '[HuskSync](#ff7e5e bold) [| A new version of HuskSync is available: v%1% (running: v%2%).](#ff7e5e)'
|
||||
save_cause_disconnect: 'Server verlassen'
|
||||
save_cause_world_save: 'Welt gespeichert'
|
||||
save_cause_death: 'Tod'
|
||||
save_cause_server_shutdown: 'Server gestoppt'
|
||||
save_cause_inventory_command: 'Inventar Befehl'
|
||||
save_cause_enderchest_command: 'Enderchest Befehl'
|
||||
save_cause_backup_restore: 'Backup wiederhergestellt'
|
||||
save_cause_api: 'API'
|
||||
save_cause_mpdb_migration: 'MPDB Migration'
|
||||
save_cause_legacy_migration: 'Legacy Migration'
|
||||
save_cause_converted_from_v2: 'Import von v2'
|
||||
reload_complete: '[HuskSync](#00fb9a bold) [| Die Konfigurations- und Sprachdateien wurden neu geladen.](#00fb9a)\n[⚠ Stelle sicher, dass die Konfigurationsdateien auf allen Servern aktuell sind!](#00fb9a)\n[Ein Neustart wird benötigt, damit Konfigurations-Änderungen wirkbar werden.](#00fb9a italic)'
|
||||
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)'
|
||||
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_no_permission: '[Fehler:](#ff3300) [Du hast nicht die benötigten Berechtigungen um diesen Befehl auszuführen](#ff7e5e)'
|
||||
@@ -44,7 +55,7 @@ error_console_command_only: '[Fehler:](#ff3300) [Dieser Befehl kann nur über di
|
||||
error_in_game_command_only: 'Fehler: Dieser Befehl kann nur im Spiel genutzt werden.'
|
||||
error_no_data_to_display: '[Fehler:](#ff3300) [Es konnten keine Nutzerdaten zum Anzeigen gefunden werden.](#ff7e5e)'
|
||||
error_invalid_version_uuid: '[Fehler:](#ff3300) [Es konnten keine Nutzerdaten für diese Versions-UUID gefunden werden.](#ff7e5e)'
|
||||
husksync_command_description: 'Manage the HuskSync plugin'
|
||||
userdata_command_description: 'View, manage & restore player userdata'
|
||||
inventory_command_description: 'View & edit a player''s inventory'
|
||||
enderchest_command_description: 'View & edit a player''s Ender Chest'
|
||||
husksync_command_description: 'Das HuskSync-Plugin verwalten'
|
||||
userdata_command_description: 'Nutzerdaten eines Spielers anzeigen, verwalten und wiederherstellen'
|
||||
inventory_command_description: 'Inventar eines Spielers ansehen und bearbeiten'
|
||||
enderchest_command_description: 'Endertruhe eines Spielers ansehen und bearbeiten'
|
||||
|
||||
@@ -11,7 +11,7 @@ data_manager_title: '[Viewing user data snapshot](#00fb9a) [%1%](#00fb9a show_te
|
||||
data_manager_timestamp: '[⌚ %1%](#ffc43b-#f5c962 show_text=&7Version timestamp:\n&8When the data was saved)'
|
||||
data_manager_pinned: '[※ Snapshot pinned](#d8ff2b show_text=&7Pinned:\n&8This user data snapshot won''t be automatically rotated.)'
|
||||
data_manager_cause: '[⚑ %1%](#23a825-#36f539 show_text=&7Save cause:\n&8What caused the data to be saved)'
|
||||
data_manager_server: '[Ⓢ %1%](#ff87b3-#f5538e show_text=&7Server:\n&8Name of the server the data was saved on)'
|
||||
data_manager_server: '[☁ %1%](#ff87b3-#f5538e show_text=&7Server:\n&8Name of the server the data was saved on)'
|
||||
data_manager_size: '[⏏ %1%](color=#62a9f5-#7ab8fa show_text=&7Snapshot size:\n&8Estimated file size of the snapshot (in KiB))\n'
|
||||
data_manger_status: '[%1%](red)[/](gray)[%2%](red)[×](gray)[❤](red show_text=&7Health points) [%3%](yellow)[×](gray)[🍖](yellow show_text=&7Hunger points) [ʟᴠ](green)[.](gray)[%4%](green show_text=&7XP level) [🏹 %5%](dark_aqua show_text=&7Game mode)'
|
||||
data_manager_advancements_statistics: '[⭐ Advancements: %1%](color=#ffc43b-#f5c962 show_text=&7Advancements you have progress in:\n&8%2%) [⌛ Play Time: %3%ʜʀs](color=#62a9f5-#7ab8fa show_text=&7In-game play time\n&8⚠ Based on in-game statistics)\n'
|
||||
@@ -34,6 +34,17 @@ list_page_jumper_button: '[%1%](show_text=&7Jump to page %1% run_command=%2% %1%
|
||||
list_page_jumper_current_page: '[%1%](#00fb9a)'
|
||||
list_page_jumper_separator: ' '
|
||||
list_page_jumper_group_separator: '…'
|
||||
save_cause_disconnect: 'disconnect'
|
||||
save_cause_world_save: 'world save'
|
||||
save_cause_death: 'death'
|
||||
save_cause_server_shutdown: 'server shutdown'
|
||||
save_cause_inventory_command: 'inventory command'
|
||||
save_cause_enderchest_command: 'enderchest command'
|
||||
save_cause_backup_restore: 'backup restore'
|
||||
save_cause_api: 'API'
|
||||
save_cause_mpdb_migration: 'MPDB migration'
|
||||
save_cause_legacy_migration: 'legacy migration'
|
||||
save_cause_converted_from_v2: 'converted from v2'
|
||||
up_to_date: '[HuskSync](#00fb9a bold) [| You are running the latest version of HuskSync (v%1%).](#00fb9a)'
|
||||
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)'
|
||||
|
||||
@@ -11,7 +11,7 @@ data_manager_title: '[Viendo una snapshot sobre la informacion del jugador](#00f
|
||||
data_manager_timestamp: '[⌚ %1%](#ffc43b-#f5c962 show_text=&7Version del registro:\n&8Cuando los datos se han guardado)'
|
||||
data_manager_pinned: '[※ Snapshot anclada](#d8ff2b show_text=&Anclado:\n&8La informacion de este jugador no se rotará automaticamente.)'
|
||||
data_manager_cause: '[⚑ %1%](#23a825-#36f539 show_text=&7Motivo del guardado:\n&8Lo que ha causado que se guarde)'
|
||||
data_manager_server: '[Ⓢ %1%](#ff87b3-#f5538e show_text=&7Server:\n&8Name of the server the data was saved on)'
|
||||
data_manager_server: '[☁ %1%](#ff87b3-#f5538e show_text=&7Server:\n&8Name of the server the data was saved on)'
|
||||
data_manager_size: '[⏏ %1%](color=#62a9f5-#7ab8fa show_text=&7Snapshot size:\n&8Estimated file size of the snapshot (in KiB))\n'
|
||||
data_manger_status: '[%1%](red)[/](gray)[%2%](red)[×](gray)[❤](red show_text=&7Puntos de vida) [%3%](yellow)[×](gray)[🍖](yellow show_text=&7Puntos de hambre) [ʟᴠ](green)[.](gray)[%4%](green show_text=&7Nivel de exp) [🏹 %5%](dark_aqua show_text=&7Gamemode)'
|
||||
data_manager_advancements_statistics: '[⭐ Logros: %1%](color=#ffc43b-#f5c962 show_text=&7Logros que has conseguido:\n&8%2%) [⌛ Tiempo de juego: %3%ʜʀs](color=#62a9f5-#7ab8fa show_text=&7In-game play time\n&8⚠ Based on in-game statistics)\n'
|
||||
@@ -34,6 +34,17 @@ list_page_jumper_button: '[%1%](show_text=&7Jump to page %1% run_command=%2% %1%
|
||||
list_page_jumper_current_page: '[%1%](#00fb9a)'
|
||||
list_page_jumper_separator: ' '
|
||||
list_page_jumper_group_separator: '…'
|
||||
save_cause_disconnect: 'disconnect'
|
||||
save_cause_world_save: 'world save'
|
||||
save_cause_death: 'death'
|
||||
save_cause_server_shutdown: 'server shutdown'
|
||||
save_cause_inventory_command: 'inventory command'
|
||||
save_cause_enderchest_command: 'enderchest command'
|
||||
save_cause_backup_restore: 'backup restore'
|
||||
save_cause_api: 'API'
|
||||
save_cause_mpdb_migration: 'MPDB migration'
|
||||
save_cause_legacy_migration: 'legacy migration'
|
||||
save_cause_converted_from_v2: 'converted from v2'
|
||||
up_to_date: '[HuskSync](#00fb9a bold) [| You are running the latest version of HuskSync (v%1%).](#00fb9a)'
|
||||
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)'
|
||||
|
||||
@@ -11,7 +11,7 @@ data_manager_title: '[Stai vedendo l''istantanea](#00fb9a) [%1%](#00fb9a show_te
|
||||
data_manager_timestamp: '[⌚ %1%](#ffc43b-#f5c962 show_text=&7:\n&8Quando i dati sono stati salvati)'
|
||||
data_manager_pinned: '[※ Istantanea fissata](#d8ff2b show_text=&7Pinned:\n&8Quest''istantanea non sarà cancellata automaticamente.)'
|
||||
data_manager_cause: '[⚑ %1%](#23a825-#36f539 show_text=&7Causa di salvataggio:\n&8Cosa ha causato il salvataggio dei dati)'
|
||||
data_manager_server: '[Ⓢ %1%](#ff87b3-#f5538e show_text=&7Server:\n&8Name of the server the data was saved on)'
|
||||
data_manager_server: '[☁ %1%](#ff87b3-#f5538e show_text=&7Server:\n&8Name of the server the data was saved on)'
|
||||
data_manager_size: '[⏏ %1%](color=#62a9f5-#7ab8fa show_text=&7Peso dell''istantanea:\n&8Peso stimato del file (in KiB))\n'
|
||||
data_manger_status: '[%1%](red)[/](gray)[%2%](red)[×](gray)[❤](red show_text=&7Vita) [%3%](yellow)[×](gray)[🍖](yellow show_text=&7Fame) [ʟᴠ](green)[.](gray)[%4%](green show_text=&7Livello di XP) [🏹 %5%](dark_aqua show_text=&7Modalità di gioco)'
|
||||
data_manager_advancements_statistics: '[⭐ Progressi: %1%](color=#ffc43b-#f5c962 show_text=&7Progressi compiuti in:\n&8%2%) [⌛ Tempo di gioco: %3%ʜʀs](color=#62a9f5-#7ab8fa show_text=&7Tempo di gioco\n&8⚠ Basato sulle statistiche di gioco)\n'
|
||||
@@ -34,6 +34,17 @@ list_page_jumper_button: '[%1%](show_text=&7Vai alla pagina %1% run_command=%2%
|
||||
list_page_jumper_current_page: '[%1%](#00fb9a)'
|
||||
list_page_jumper_separator: ' '
|
||||
list_page_jumper_group_separator: '…'
|
||||
save_cause_disconnect: 'disconnect'
|
||||
save_cause_world_save: 'world save'
|
||||
save_cause_death: 'death'
|
||||
save_cause_server_shutdown: 'server shutdown'
|
||||
save_cause_inventory_command: 'inventory command'
|
||||
save_cause_enderchest_command: 'enderchest command'
|
||||
save_cause_backup_restore: 'backup restore'
|
||||
save_cause_api: 'API'
|
||||
save_cause_mpdb_migration: 'MPDB migration'
|
||||
save_cause_legacy_migration: 'legacy migration'
|
||||
save_cause_converted_from_v2: 'converted from v2'
|
||||
up_to_date: '[HuskSync](#00fb9a bold) [| Il plugin è all''ultima versione disponibile (v%1%).](#00fb9a)'
|
||||
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)'
|
||||
|
||||
@@ -11,7 +11,7 @@ data_manager_title: '[%3%](#00fb9a bold show_text=&7プレイヤーUUID:\n&8%4%)
|
||||
data_manager_timestamp: '[⌚ %1%](#ffc43b-#f5c962 show_text=&7バージョンタイムスタンプ:\n&8データの保存時期)'
|
||||
data_manager_pinned: '[※ ピン留めされたスナップショット](#d8ff2b show_text=&7ピン留め:\n&8このユーザーデータのスナップショットは自動的にローテーションされません。)'
|
||||
data_manager_cause: '[⚑ %1%](#23a825-#36f539 show_text=&7保存理由:\n&8データが保存された理由)'
|
||||
data_manager_server: '[Ⓢ %1%](#ff87b3-#f5538e show_text=&7Server:\n&8Name of the server the data was saved on)'
|
||||
data_manager_server: '[☁ %1%](#ff87b3-#f5538e show_text=&7Server:\n&8Name of the server the data was saved on)'
|
||||
data_manager_size: '[⏏ %1%](color=#62a9f5-#7ab8fa show_text=&7スナップショットサイズ:\n&8スナップショットの推定ファイルサイズ(単位:KiB))\n'
|
||||
data_manger_status: '[%1%](red)[/](gray)[%2%](red)[×](gray)[❤](red show_text=&7体力) [%3%](yellow)[×](gray)[🍖](yellow show_text=&7空腹度) [ʟᴠ](green)[.](gray)[%4%](green show_text=&7経験値レベル) [🏹 %5%](dark_aqua show_text=&7ゲームモード)'
|
||||
data_manager_advancements_statistics: '[⭐ 進捗: %1%](color=#ffc43b-#f5c962 show_text=&7達成した進捗:\n&8%2%) [⌛ プレイ時間: %3%ʜʀs](color=#62a9f5-#7ab8fa show_text=&7ゲーム内のプレイ時間\n&8⚠ ゲーム内の統計に基づく)\n'
|
||||
@@ -34,6 +34,17 @@ list_page_jumper_button: '[%1%](show_text=&7%1% ページ目へ run_command=%2%
|
||||
list_page_jumper_current_page: '[%1%](#00fb9a)'
|
||||
list_page_jumper_separator: ' '
|
||||
list_page_jumper_group_separator: '…'
|
||||
save_cause_disconnect: 'disconnect'
|
||||
save_cause_world_save: 'world save'
|
||||
save_cause_death: 'death'
|
||||
save_cause_server_shutdown: 'server shutdown'
|
||||
save_cause_inventory_command: 'inventory command'
|
||||
save_cause_enderchest_command: 'enderchest command'
|
||||
save_cause_backup_restore: 'backup restore'
|
||||
save_cause_api: 'API'
|
||||
save_cause_mpdb_migration: 'MPDB migration'
|
||||
save_cause_legacy_migration: 'legacy migration'
|
||||
save_cause_converted_from_v2: 'converted from v2'
|
||||
up_to_date: '[HuskSync](#00fb9a bold) [| HuskSyncの最新バージョンを実行しています(v%1%).](#00fb9a)'
|
||||
update_available: '[HuskSync](#ff7e5e bold) [| HuskSyncの最新バージョンが更新されています: v%1% (実行中: v%2%).](#ff7e5e)'
|
||||
reload_complete: '[HuskSync](#00fb9a bold) [| 設定ファイルとメッセージファイルを再読み込みしました。](#00fb9a)\n[⚠ すべてのサーバーで設定ファイルが最新であることを確認してください!](#00fb9a)\n[設定の変更を有効にするには再起動が必要です。](#00fb9a italic)'
|
||||
|
||||
61
common/src/main/resources/locales/ko-kr.yml
Normal file
61
common/src/main/resources/locales/ko-kr.yml
Normal file
@@ -0,0 +1,61 @@
|
||||
synchronization_complete: '[⏵ 데이터 연동됨!](#00fb9a)'
|
||||
synchronization_failed: '[⏵ 데이터 연동에 실패하였습니다! 관리자에게 문의해 주세요.](#ff7e5e)'
|
||||
inventory_viewer_menu_title: '&0%1%님의 인벤토리'
|
||||
ender_chest_viewer_menu_title: '&0%1%님의 엔더상자'
|
||||
inventory_viewer_opened: '[%1%](#00fb9a bold)[님의 ⌚ %2%의 인벤토리를 엽니다](#00fb9a)'
|
||||
ender_chest_viewer_opened: '[%1%](#00fb9a bold)[님의 ⌚ %2%의 엔더상자를 엽니다](#00fb9a)'
|
||||
data_update_complete: '[🔔 당신의 데이터가 업데이트 되었습니다!](#00fb9a)'
|
||||
data_update_failed: '[🔔 데이터 업데이트에 실패하였습니다! 관리자에게 문의해 주세요.](#ff7e5e)'
|
||||
user_registration_complete: '[⭐ 유저 등록이 완료되었습니다!](#00fb9a)'
|
||||
data_manager_title: '[%3%](#00fb9a bold show_text=&7플레이어 UUID:\n&8%4%)[님의 ](#00fb9a) [%1%](#00fb9a show_text=&7버전 UUID:\n&8%2%) [데이터 스냅샷을 표시합니다](#00fb9a)[:](#00fb9a)'
|
||||
data_manager_timestamp: '[⌚ %1%](#ffc43b-#f5c962 show_text=&7저장 시각:\n&8데이터가 저장된 시각)'
|
||||
data_manager_pinned: '[※ 스냅샷 고정됨](#d8ff2b show_text=&7고정됨:\n&8이 유저의 데이터 스냅샷은 자동으로 갱신되지 않습니다.)'
|
||||
data_manager_cause: '[⚑ %1%](#23a825-#36f539 show_text=&7저장 사유:\n&8데이터가 저장된 사유입니다.)'
|
||||
data_manager_server: '[☁ %1%](#ff87b3-#f5538e show_text=&7서버:\n&8데이터 저장이 이루어진 서버입니다.)'
|
||||
data_manager_size: '[⏏ %1%](color=#62a9f5-#7ab8fa show_text=&7스냅샷 크기:\n&8스냅샷 파일의 대략적인 크기입니다. (단위 KiB))\n'
|
||||
data_manger_status: '[%1%](red)[/](gray)[%2%](red)[×](gray)[❤](red show_text=&7체력) [%3%](yellow)[×](gray)[🍖](yellow show_text=&7허기) [ʟᴠ](green)[.](gray)[%4%](green show_text=&7경험치 레벨) [🏹 %5%](dark_aqua show_text=&7게임 모드)'
|
||||
data_manager_advancements_statistics: '[⭐ 도전 과제: %1%](color=#ffc43b-#f5c962 show_text=&7진행한 도전 과제:\n&8%2%) [⌛ 플레이 타임: %3%ʜʀs](color=#62a9f5-#7ab8fa show_text=&7인게임 플레이 시간\n&8⚠ 인게임 통계에 기반합니다.)\n'
|
||||
data_manager_item_buttons: '[보기:](gray) [[🪣 인벤토리…]](color=#a17b5f-#f5b98c show_text=&7클릭하여 확인 run_command=/inventory %1% %2%) [[⌀ 엔더상자…]](#b649c4-#d254ff show_text=&7클릭하여 확인 run_command=/enderchest %1% %2%)'
|
||||
data_manager_management_buttons: '[관리:](gray) [[❌ 삭제…]](#ff3300 show_text=&7클릭하여 이 유저 스냅샷 데이터를 삭제\n&8이 기능은 현재 유저의 인벤토리 데이터에는 영향을 미치지 않습니다.\n&#ff3300&⚠ 이 작업은 되돌릴 수 없습니다! suggest_command=/husksync:userdata delete %1% %2%) [[⏪ 복구…]](#00fb9a show_text=&7클릭하여 유저 데이터 복구\n&8유저의 데이터가 이 스냅샷의 데이터로 변경됩니다.\n&#ff3300&⚠ %1%님의 현재 데이터에 덧씌워 집니다! suggest_command=/husksync:userdata restore %1% %2%) [[※ 고정/고정 해제…]](#d8ff2b show_text=&7클릭하여 유저 데이터를 고정 또는 고정 해제\n&8고정된 스냅샷은 자동적으로 갱신되지 않습니다. run_command=/userdata pin %1% %2%)'
|
||||
data_manager_system_buttons: '[시스템:](gray) [[⏷ 파일 덤프…]](dark_gray show_text=&7클릭하여 이 유저 데이터 스냅샷을 덤프하기\n&8데이터 덤프 파일은 ~/plugins/HuskSync/dumps/ 에서 찾을 수 있습니다. run_command=/husksync:userdata dump %1% %2% file) [[☂ 웹 덤프…]](dark_gray show_text=&7클릭하여 유저 데이터 스냅샷을 mc-log 서비스에 덤프하기\n&8데이터를 포함한 URL이 제공됩니다. run_command=/husksync:userdata dump %1% %2% web)'
|
||||
data_manager_advancements_preview_remaining: '외 %1%개...'
|
||||
data_list_title: '[%1%님의 유저 데이터 스냅샷 목록:](#00fb9a) [(%2%-%3% 중](#00fb9a) [%4%](#00fb9a bold)[)](#00fb9a)\n'
|
||||
data_list_item: '[%1%](gray show_text=&7%2%&7님의 유저 데이터 스냅샷&8⚡ %4% run_command=/userdata view %2% %3%) [%5%](#d8ff2b show_text=&7고정됨:\n&8고정된 스냅샷은 자동적으로 갱신되지 않습니다. run_command=/userdata view %2% %3%) [%6%](color=#ffc43b-#f5c962 show_text=&7저장 시각:&7\n&8데이터가 저장된 시각입니다.\n&8%7% run_command=/userdata view %2% %3%) [⚑ %8%](#23a825-#36f539 show_text=&7저장 사유:\n&8데이터가 저장된 사유입니다. run_command=/userdata view %2% %3%) [⏏ %9%](color=#62a9f5-#7ab8fa show_text=&7스냅샷 크기:&7\n&8스냅샷 파일의 대략적인 크기입니다. (단위 KiB) run_command=/userdata view %2% %3%)'
|
||||
data_deleted: '[❌ 성공적으로](#00fb9a) [%3%](#00fb9a show_text=&7플레이어 UUID:\n&8%4%) [님의 유저 데이터 스냅샷](#00fb9a) [%1%](#00fb9a show_text=&7버전 UUID:\n&8%2%)[을 삭제하였습니다.](#00fb9a)'
|
||||
data_restored: '[⏪ 성공적으로 복구되었습니다.](#00fb9a) [%1%](#00fb9a show_text=&7플레이어 UUID:\n&8%2%)[님의 현재 유저 데이터 스냅샷이](#00fb9a) [%3%](#00fb9a show_text=&7버전 UUID:\n&8%4%)[으로 변경되었습니다.](#00fb9a)'
|
||||
data_pinned: '[※ 성공적으로](#00fb9a) [%3%](#00fb9a show_text=&7플레이어 UUID:\n&8%4%)[님의 유저 데이터 스냅샷](#00fb9a) [%1%](#00fb9a show_text=&7버전 UUID:\n&8%2%)[을 고정하였습니다.](#00fb9a)'
|
||||
data_unpinned: '[※ 성공적으로](#00fb9a) [%3%](#00fb9a show_text=&7플레이어 UUID:\n&8%4%) [님의 유저 데이터 스냅샷](#00fb9a) [%1%](#00fb9a show_text=&7버전 UUID:\n&8%2%)[을 고정 해제하였습니다.](#00fb9a)'
|
||||
data_dumped: '[☂ 성공적으로 %2%님의 유저 데이터 스냅샷 %1%를 다음으로 덤프하였습니다:](#00fb9a) &7%3%'
|
||||
list_footer: '\n%1%[페이지](#00fb9a) [%2%](#00fb9a)/[%3%](#00fb9a)%4% %5%'
|
||||
list_previous_page_button: '[◀](white show_text=&7이전 페이지 보기 run_command=%2% %1%) '
|
||||
list_next_page_button: ' [▶](white show_text=&7다음 페이지 보기 run_command=%2% %1%)'
|
||||
list_page_jumpers: '(%1%)'
|
||||
list_page_jumper_button: '[%1%](show_text=&7%1% 페이지 보기 run_command=%2% %1%)'
|
||||
list_page_jumper_current_page: '[%1%](#00fb9a)'
|
||||
list_page_jumper_separator: ' '
|
||||
list_page_jumper_group_separator: '…'
|
||||
save_cause_disconnect: 'disconnect'
|
||||
save_cause_world_save: 'world save'
|
||||
save_cause_death: 'death'
|
||||
save_cause_server_shutdown: 'server shutdown'
|
||||
save_cause_inventory_command: 'inventory command'
|
||||
save_cause_enderchest_command: 'enderchest command'
|
||||
save_cause_backup_restore: 'backup restore'
|
||||
save_cause_api: 'API'
|
||||
save_cause_mpdb_migration: 'MPDB migration'
|
||||
save_cause_legacy_migration: 'legacy migration'
|
||||
save_cause_converted_from_v2: 'converted from v2'
|
||||
up_to_date: '[HuskSync](#00fb9a bold) [| 가장 최신 버전의 HuskSync를 실행 중입니다 (v%1%).](#00fb9a)'
|
||||
update_available: '[HuskSync](#ff7e5e bold) [| 새로운 버전의 HuskSync가 존재합니다: v%1% (현재 버전: v%2%).](#ff7e5e)'
|
||||
reload_complete: '[HuskSync](#00fb9a bold) [| 콘피그와 메시지 파일을 다시 불러왔습니다.](#00fb9a)\n[⚠ 모든 서버의 컨피그 파일을 변경하였는지 확인하세요!](#00fb9a)\n[몇몇 설정은 재시작 후에 적용됩니다.](#00fb9a italic)'
|
||||
error_invalid_syntax: '[오류:](#ff3300) [잘못된 사용법. 사용법:](#ff7e5e) [%1%](#ff7e5e italic show_text=&#ff7e5e&클릭하여 입력할 수 있습니다. suggest_command=%1%)'
|
||||
error_invalid_player: '[오류:](#ff3300) [해당 이름의 사용자를 찾을 수 없습니다.](#ff7e5e)'
|
||||
error_no_permission: '[오류:](#ff3300) [해당 명령어를 사용할 권한이 없습니다.](#ff7e5e)'
|
||||
error_console_command_only: '[오류:](#ff3300) [해당 명령어는 콘솔을 통해서만 사용할 수 있습니다.](#ff7e5e)'
|
||||
error_in_game_command_only: '오류: 해당 명령어는 게임 내부에서만 사용할 수 있습니다.'
|
||||
error_no_data_to_display: '[오류:](#ff3300) [표시할 유저 데이터를 찾을 수 없습니다.](#ff7e5e)'
|
||||
error_invalid_version_uuid: '[오류:](#ff3300) [해당 버전 UUID의 유저 데이터 스냅샷을 찾을 수 없습니다.](#ff7e5e)'
|
||||
husksync_command_description: 'HuskSync 플러그인을 관리합니다.'
|
||||
userdata_command_description: '확인, 관리 또는 복구합니다.'
|
||||
inventory_command_description: '플레이어의 인벤토리를 열람 또는 편집합니다.'
|
||||
enderchest_command_description: '플레이어의 엔더상자를 열람 또는 편집합니다.'
|
||||
@@ -11,7 +11,7 @@ data_manager_title: '[Momentopname van gebruikersgegevens bekijken](#00fb9a) [%1
|
||||
data_manager_timestamp: '[⌚ %1%](#ffc43b-#f5c962 show_text=&7Versie tijdmarkering:\n&8Toen de gegevens werden opgeslagen)'
|
||||
data_manager_pinned: '[※ Momentopname vastgezet](#d8ff2b show_text=&7Vastgezet:\n&8Deze momentopname van gebruikersgegevens wordt niet automatisch gerouleerd.)'
|
||||
data_manager_cause: '[⚑ %1%](#23a825-#36f539 show_text=&7Reden opslaan:\n&8Waarom de data is opgeslagen)'
|
||||
data_manager_server: '[Ⓢ %1%](#ff87b3-#f5538e show_text=&7Server:\n&8Name of the server the data was saved on)'
|
||||
data_manager_server: '[☁ %1%](#ff87b3-#f5538e show_text=&7Server:\n&8Name of the server the data was saved on)'
|
||||
data_manager_size: '[⏏ %1%](color=#62a9f5-#7ab8fa show_text=&7Grootte van momentopname:\n&8Geschatte bestandsgrootte van de momentopname (in KiB))\n'
|
||||
data_manger_status: '[%1%](red)[/](gray)[%2%](red)[×](gray)[❤](red show_text=&7Gezondheids punten) [%3%](yellow)[×](gray)[🍖](yellow show_text=&7Honger punten) [ʟᴠ](green)[.](gray)[%4%](green show_text=&7XP level) [🏹 %5%](dark_aqua show_text=&7Speltype)'
|
||||
data_manager_advancements_statistics: '[⭐ Advancements: %1%](color=#ffc43b-#f5c962 show_text=&7Advancements waarin je voortgang hebt:\n&8%2%) [⌛ Speeltijd: %3%uren](color=#62a9f5-#7ab8fa show_text=&7In-game speeltijd\n&8⚠ Gebaseerd op in-game statistieken)\n'
|
||||
@@ -34,6 +34,17 @@ list_page_jumper_button: '[%1%](show_text=&7Ga naar pagina %1% run_command=%2% %
|
||||
list_page_jumper_current_page: '[%1%](#00fb9a)'
|
||||
list_page_jumper_separator: ' '
|
||||
list_page_jumper_group_separator: '…'
|
||||
save_cause_disconnect: 'disconnect'
|
||||
save_cause_world_save: 'world save'
|
||||
save_cause_death: 'death'
|
||||
save_cause_server_shutdown: 'server shutdown'
|
||||
save_cause_inventory_command: 'inventory command'
|
||||
save_cause_enderchest_command: 'enderchest command'
|
||||
save_cause_backup_restore: 'backup restore'
|
||||
save_cause_api: 'API'
|
||||
save_cause_mpdb_migration: 'MPDB migration'
|
||||
save_cause_legacy_migration: 'legacy migration'
|
||||
save_cause_converted_from_v2: 'converted from v2'
|
||||
up_to_date: '[HuskSync](#00fb9a bold) [| Je gebruikt de nieuwste versie van HuskSync (v%1%).](#00fb9a)'
|
||||
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)'
|
||||
|
||||
@@ -11,7 +11,7 @@ data_manager_title: '[Visualizando snapshot dos dados do usuário](#00fb9a) [%1%
|
||||
data_manager_timestamp: '[⌚ %1%](#ffc43b-#f5c962 show_text=&7Version timestamp:\n&8Quando os dados foram salvos)'
|
||||
data_manager_pinned: '[※ Snapshot marcada](#d8ff2b show_text=&7Marcada:\n&8Essa snapshot de dados do usuário não será girada automaticamente.)'
|
||||
data_manager_cause: '[⚑ %1%](#23a825-#36f539 show_text=&7Causa do salvamento:\n&8O motivo para que os dados fossem salvos)'
|
||||
data_manager_server: '[Ⓢ %1%](#ff87b3-#f5538e show_text=&7Server:\n&8Name of the server the data was saved on)'
|
||||
data_manager_server: '[☁ %1%](#ff87b3-#f5538e show_text=&7Server:\n&8Name of the server the data was saved on)'
|
||||
data_manager_size: '[⏏ %1%](color=#62a9f5-#7ab8fa show_text=&7Snapshot size:\n&8Estimated file size of the snapshot (in KiB))\n'
|
||||
data_manger_status: '[%1%](red)[/](gray)[%2%](red)[×](gray)[❤](red show_text=&7Pontos de Vida) [%3%](yellow)[×](gray)[🍖](yellow show_text=&7Pontos de vida) [ʟᴠ](green)[.](gray)[%4%](green show_text=&7XP level) [🏹 %5%](dark_aqua show_text=&7Game mode)'
|
||||
data_manager_advancements_statistics: '[⭐ Progressos: %1%](color=#ffc43b-#f5c962 show_text=&7Progressos que você tem realizado em:\n&8%2%) [⌛ Tempo de jogo: %3%ʜʀs](color=#62a9f5-#7ab8fa show_text=&7Tempo de jogo dentro do jogo\n&8⚠ Com base em estatísticas dentro do jogo)\n'
|
||||
@@ -34,6 +34,17 @@ list_page_jumper_button: '[%1%](show_text=&7Jump to page %1% run_command=%2% %1%
|
||||
list_page_jumper_current_page: '[%1%](#00fb9a)'
|
||||
list_page_jumper_separator: ' '
|
||||
list_page_jumper_group_separator: '…'
|
||||
save_cause_disconnect: 'disconnect'
|
||||
save_cause_world_save: 'world save'
|
||||
save_cause_death: 'death'
|
||||
save_cause_server_shutdown: 'server shutdown'
|
||||
save_cause_inventory_command: 'inventory command'
|
||||
save_cause_enderchest_command: 'enderchest command'
|
||||
save_cause_backup_restore: 'backup restore'
|
||||
save_cause_api: 'API'
|
||||
save_cause_mpdb_migration: 'MPDB migration'
|
||||
save_cause_legacy_migration: 'legacy migration'
|
||||
save_cause_converted_from_v2: 'converted from v2'
|
||||
up_to_date: '[HuskSync](#00fb9a bold) [| You are running the latest version of HuskSync (v%1%).](#00fb9a)'
|
||||
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)'
|
||||
|
||||
61
common/src/main/resources/locales/ru-ru.yml
Normal file
61
common/src/main/resources/locales/ru-ru.yml
Normal file
@@ -0,0 +1,61 @@
|
||||
synchronization_complete: '[⏵ Данные синхронизированы!](#00fb9a)'
|
||||
synchronization_failed: '[⏵ Не удалось синхронизировать данные! Пожалуйста, обратитесь к администратору.](#ff7e5e)'
|
||||
inventory_viewer_menu_title: '&0Инвентарь %1%'
|
||||
ender_chest_viewer_menu_title: '&0Эндер-сундук %1%'
|
||||
inventory_viewer_opened: '[Просмотр снимка инвентаря](#00fb9a) [%1%](#00fb9a bold) [во время ⌚ %2%](#00fb9a)'
|
||||
ender_chest_viewer_opened: '[Просмотр снимка эндер-сундука](#00fb9a) [%1%](#00fb9a bold) [во время ⌚ %2%](#00fb9a)'
|
||||
data_update_complete: '[🔔 Ваши данные обновлены!](#00fb9a)'
|
||||
data_update_failed: '[🔔 Не удалось обновить ваши данные! Пожалуйста, обратитесь к администратору.](#ff7e5e)'
|
||||
user_registration_complete: '[⭐ Регистрация пользователя завершена!](#00fb9a)'
|
||||
data_manager_title: '[Просмотр снимка данных](#00fb9a) [%1%](#00fb9a show_text=&7UUID снимка:\n&8%2%) [пользователя](#00fb9a) [%3%](#00fb9a bold show_text=&7UUID игрока:\n&8%4%)[:](#00fb9a)'
|
||||
data_manager_timestamp: '[⌚ %1%](#ffc43b-#f5c962 show_text=&7Время:\n&8Когда данные были сохранены)'
|
||||
data_manager_pinned: '[※ Снимок закреплен](#d8ff2b show_text=&7Закреплен:\n&8Этот снимок данных пользователя не будет автоматически применено.)'
|
||||
data_manager_cause: '[⚑ %1%](#23a825-#36f539 show_text=&7Причина сохранения:\n&8Что привело к сохранению данных)'
|
||||
data_manager_server: '[☁ %1%](#ff87b3-#f5538e show_text=&7Сервер:\n&8Название сервера где данные были сохранены)'
|
||||
data_manager_size: '[⏏ %1%](color=#62a9f5-#7ab8fa show_text=&7Размер:\n&8Предполагаемый размер снимка (в килобайтах))\n'
|
||||
data_manger_status: '[%1%](red)[/](gray)[%2%](red)[×](gray)[❤](red show_text=&7Здоровье) [%3%](yellow)[×](gray)[🍖](yellow show_text=&7Голод) [ʟᴠ](green)[.](gray)[%4%](green show_text=&7Уровень опыта) [🏹 %5%](dark_aqua show_text=&7Игровой режим)'
|
||||
data_manager_advancements_statistics: '[⭐ Достижения: %1%](color=#ffc43b-#f5c962 show_text=&7Полученные вами достижения:\n&8%2%) [⌛ Отыгранное время: %3%ʜʀs](color=#62a9f5-#7ab8fa show_text=&7Сколько времени вы отыграли\n&8⚠ Строится по внутреигровой статистике)\n'
|
||||
data_manager_item_buttons: '[Просмотр:](gray) [[🪣 Инвентарь…]](color=#a17b5f-#f5b98c show_text=&7Нажмите для просмотра run_command=/inventory %1% %2%) [[⌀ Эндер-сундук…]](#b649c4-#d254ff show_text=&7Нажмите для просмотра run_command=/enderchest %1% %2%)'
|
||||
data_manager_management_buttons: '[Управление:](gray) [[❌ Удалить…]](#ff3300 show_text=&7Нажмите для удаления этого снимка данных пользователя\n&8Не влияет на текущие данные пользователя.\n&#ff3300&⚠ Необратимое действие! suggest_command=/husksync:userdata delete %1% %2%) [[⏪ Восстановить…]](#00fb9a show_text=&7Нажмите для восстановления данных пользователя\n&8Это восстановит данные пользователя до этого снимка.\n&#ff3300&⚠ Текущие данные %1% будут перезаписаны! suggest_command=/husksync:userdata restore %1% %2%) [[※ Закрепить/Открепить…]](#d8ff2b show_text=&7Нажмите для закрепления или открепления снимка данных пользователя\n&8Закрепленные снимки данных не удаляются автоматически. run_command=/userdata pin %1% %2%)'
|
||||
data_manager_system_buttons: '[Система:](gray) [[⏷ Дамп в файл…]](dark_gray show_text=&7Нажмите для дампа исходного снимка данных пользователя в файл\n&8Файлы дампов данных находятся в ~/plugins/HuskSync/dumps/ run_command=/husksync:userdata dump %1% %2% file) [[☂ Выгрузить дамп…]](dark_gray show_text=&7Нажмите для дампа исходного снимка данных пользователя с помощью сервиса mc-logs\n&8Вы получите ссылку с дампом данных. run_command=/husksync:userdata dump %1% %2% web)'
|
||||
data_manager_advancements_preview_remaining: 'и еще %1%…'
|
||||
data_list_title: '[Снимки данных %1%:](#00fb9a) [(%2%-%3% из](#00fb9a) [%4%](#00fb9a bold)[)](#00fb9a)\n'
|
||||
data_list_item: '[%1%](gray show_text=&7Снимок данных %4% пользователя %2%&8⚡ run_command=/userdata view %2% %3%) [%5%](#d8ff2b show_text=&7Закреплен:\n&8Закрепленные снимки данных не удаляются автоматически run_command=/userdata view %2% %3%) [%6%](color=#ffc43b-#f5c962 show_text=&7Время:&7\n&8Когда данные были сохранены\n&8%7% run_command=/userdata view %2% %3%) [⚑ %8%](#23a825-#36f539 show_text=&7Причина сохранения:\n&8Что привело к сохранению данных run_command=/userdata view %2% %3%) [⏏ %9%](color=#62a9f5-#7ab8fa show_text=&7Размер:&7\n&8Предполагаемый размер снимка (в килобайтах) run_command=/userdata view %2% %3%)'
|
||||
data_deleted: '[❌ Снимок данных](#00fb9a) [%1%](#00fb9a show_text=&7UUID снимка:\n&8%2%) [пользователя](#00fb9a) [%3%](#00fb9a show_text=&7UUID игрока:\n&8%4%) [удален.](#00fb9a)'
|
||||
data_restored: '[⏪ Данные пользователя](#00fb9a) [%1%](#00fb9a show_text=&7UUID игрока:\n&8%2%) [из снимка](#00fb9a) [%3%](#00fb9a show_text=&7UUID снимка:\n&8%4%) [успешно восстановлены.](#00fb9a)'
|
||||
data_pinned: '[※ Снимок данных](#00fb9a) [%1%](#00fb9a show_text=&7UUID снимка:\n&8%2%) [пользователя](#00fb9a) [%3%](#00fb9a show_text=&7UUID игрока:\n&8%4%) [успешно закреплен.](#00fb9a)'
|
||||
data_unpinned: '[※ Снимок данных](#00fb9a) [%1%](#00fb9a show_text=&7UUID снимка:\n&8%2%) [пользователя](#00fb9a) [%3%](#00fb9a show_text=&7UUID пользователя:\n&8%4%) [успешно откреплен.](#00fb9a)'
|
||||
data_dumped: '[☂ Дамп снимка данных %1% пользователя %2% успешно выгружен:](#00fb9a) &7%3%'
|
||||
list_footer: '\n%1%[Страница](#00fb9a) [%2%](#00fb9a)/[%3%](#00fb9a)%4% %5%\n'
|
||||
list_previous_page_button: '[◀](white show_text=&7Просмотр предыдущей страницы run_command=%2% %1%) '
|
||||
list_next_page_button: ' [▶](white show_text=&7Просмотр следующей страницы run_command=%2% %1%)'
|
||||
list_page_jumpers: '(%1%)'
|
||||
list_page_jumper_button: '[%1%](show_text=&7Перейти на страницу %1% run_command=%2% %1%)'
|
||||
list_page_jumper_current_page: '[%1%](#00fb9a)'
|
||||
list_page_jumper_separator: ' '
|
||||
list_page_jumper_group_separator: '…'
|
||||
save_cause_disconnect: 'отключение с сервера'
|
||||
save_cause_world_save: 'сохранение мира'
|
||||
save_cause_death: 'смерть'
|
||||
save_cause_server_shutdown: 'отключение сервера'
|
||||
save_cause_inventory_command: 'команда inventory'
|
||||
save_cause_enderchest_command: 'команда enderchest'
|
||||
save_cause_backup_restore: 'восстановление из снимка'
|
||||
save_cause_api: 'API'
|
||||
save_cause_mpdb_migration: 'миграция из MPDB'
|
||||
save_cause_legacy_migration: 'миграция с legacy'
|
||||
save_cause_converted_from_v2: 'конвертация с v2'
|
||||
up_to_date: '[HuskSync](#00fb9a bold) [| Вы используете последнюю версию HuskSync (v%1%).](#00fb9a)'
|
||||
update_available: '[HuskSync](#ff7e5e bold) [| Доступна новая версия HuskSync: v%1% (текущая: v%2%).](#ff7e5e)'
|
||||
reload_complete: '[HuskSync](#00fb9a bold) [| Конфигурация и файлы локализации перезагружены.](#00fb9a)\n[⚠ Убедитесь, что файлы конфигурации обновлены на всех серверах!](#00fb9a)\n[Необходима перезагрузка для вступления изменений конфигурации в силу.](#00fb9a italic)'
|
||||
error_invalid_syntax: '[Ошибка:](#ff3300) [Неправильный синтаксис. Используйте:](#ff7e5e) [%1%](#ff7e5e italic show_text=&#ff7e5e&Click to suggest suggest_command=%1%)'
|
||||
error_invalid_player: '[Ошибка:](#ff3300) [Не удалось найти игрока с данным именем.](#ff7e5e)'
|
||||
error_no_permission: '[Ошибка:](#ff3300) [У вас недостаточно прав для выполнения данной команды.](#ff7e5e)'
|
||||
error_console_command_only: '[Ошибка:](#ff3300) [Данная команда может быть выполнена только из консоли.](#ff7e5e)'
|
||||
error_in_game_command_only: 'Ошибка: Данная команда может быть выполнена только в игре.'
|
||||
error_no_data_to_display: '[Ошибка:](#ff3300) [Не удалось найти никаких пользовательских данных для отображения.](#ff7e5e)'
|
||||
error_invalid_version_uuid: '[Ошибка:](#ff3300) [Не удалось найти никаких пользовательских данных с этим UUID снимка.](#ff7e5e)'
|
||||
husksync_command_description: 'Управление плагином HuskSync'
|
||||
userdata_command_description: 'Просмотр, редактирование и восстановление пользовательских данных игрока'
|
||||
inventory_command_description: 'Просмотр и редактирование инвентаря игрока'
|
||||
enderchest_command_description: 'Просмотр и редактирование эндер-сундука игрока'
|
||||
61
common/src/main/resources/locales/tr-tr.yml
Normal file
61
common/src/main/resources/locales/tr-tr.yml
Normal file
@@ -0,0 +1,61 @@
|
||||
synchronization_complete: '[⏵ Veri senkronize edildi!](#00fb9a)'
|
||||
synchronization_failed: '[⏵ Veriler senkronize edilemedi! Lütfen bir yönetici ile iletişime geçin.](#ff7e5e)'
|
||||
inventory_viewer_menu_title: '&0%1%''ın Envanteri'
|
||||
ender_chest_viewer_menu_title: '&0%1%''ın Ender Sandığı'
|
||||
inventory_viewer_opened: '[Görüntülenen anlık](#00fb9a) [%1%](#00fb9a bold)[''ın envanteri ⌚ %2% tarihine kadar](#00fb9a)'
|
||||
ender_chest_viewer_opened: '[Görüntülenen anlık](#00fb9a) [%1%](#00fb9a bold)[''ın Ender Sandığı ⌚ %2% tarihine kadar](#00fb9a)'
|
||||
data_update_complete: '[🔔 Verileriniz güncellendi!](#00fb9a)'
|
||||
data_update_failed: '[🔔 Verileriniz güncellenirken bir hata oluştu! Lütfen bir yönetici ile iletişime geçin.](#ff7e5e)'
|
||||
user_registration_complete: '[⭐ Kullanıcı kaydı tamamlandı!](#00fb9a)'
|
||||
data_manager_title: '[Kullanıcı veri anlık görünümü](#00fb9a) [%1%](#00fb9a show_text=&7Versiyon UUID:\n&8%2%) [için](#00fb9a) [%3%](#00fb9a bold show_text=&7Oyuncu UUID:\n&8%4%)[:](#00fb9a)'
|
||||
data_manager_timestamp: '[⌚ %1%](#ffc43b-#f5c962 show_text=&7Versiyon zaman damgası:\n&8Verinin ne zaman kaydedildiği)'
|
||||
data_manager_pinned: '[※ Anlık sabitlendi](#d8ff2b show_text=&7Sabitlendi:\n&8Bu kullanıcı veri anlığı otomatik olarak döndürülmeyecek.)'
|
||||
data_manager_cause: '[⚑ %1%](#23a825-#36f539 show_text=&7Kaydetme sebebi:\n&8Verinin kaydedilme nedeni)'
|
||||
data_manager_server: '[☁ %1%](#ff87b3-#f5538e show_text=&7Sunucu:\n&8Verinin kaydedildiği sunucu adı)'
|
||||
data_manager_size: '[⏏ %1%](color=#62a9f5-#7ab8fa show_text=&7Anlık boyutu:\n&8Anlının tahmini dosya boyutu (KiB cinsinden))\n'
|
||||
data_manger_status: '[%1%](red)[/](gray)[%2%](red)[×](gray)[❤](red show_text=&7Can puanı) [%3%](yellow)[×](gray)[🍖](yellow show_text=&7Açlık puanı) [ʟᴠ](green)[.](gray)[%4%](green show_text=&7XP seviyesi) [🏹 %5%](dark_aqua show_text=&7Oyun modu)'
|
||||
data_manager_advancements_statistics: '[⭐ Gelişmeler: %1%](color=#ffc43b-#f5c962 show_text=&7Gelişmelerdeki ilerlemeniz:\n&8%2%) [⌛ Oynama Süresi: %3%s](color=#62a9f5-#7ab8fa show_text=&7Oyunda geçen süre\n&8⚠ Oyun içi istatistiklere dayanır)\n'
|
||||
data_manager_item_buttons: '[Görünüm:](gray) [[🪣 Envanter…]](color=#a17b5f-#f5b98c show_text=&7Görüntülemek için tıklayın run_command=/inventory %1% %2%) [[⌀ Ender Sandığı…]](#b649c4-#d254ff show_text=&7Görüntülemek için tıklayın run_command=/enderchest %1% %2%)'
|
||||
data_manager_management_buttons: '[Yönet:](gray) [[❌ Sil…]](#ff3300 show_text=&7Bu kullanıcı veri anlığını silmek için tıklayın.\n&8Bu, kullanıcının mevcut verilerini etkilemez.\n&#ff3300&⚠ Geri alınamaz! suggest_command=/husksync:userdata delete %1% %2%) [[⏪ Geri Yükle…]](#00fb9a show_text=&7Bu kullanıcı verisini geri yüklemek için tıklayın.\n&8Bu, kullanıcının verisini bu anlığa ayarlar.\n&#ff3300&⚠ %1%''nın mevcut verisi üzerine yazılacak! suggest_command=/husksync:userdata restore %1% %2%) [[※ Sabitle/Çöz…]](#d8ff2b show_text=&7Bu kullanıcı veri anlığını sabitlemek veya çözmek için tıklayın\n&8Sabitlenmiş anlıklar otomatik olarak döndürülmez run_command=/userdata pin %1% %2%)'
|
||||
data_manager_system_buttons: '[Sistem:](gray) [[⏷ Dosya Dök…]](dark_gray show_text=&7Bu ham kullanıcı veri anlığını bir dosyaya dökmek için tıklayın.\n&8Veri dökümleri ~/plugins/HuskSync/dumps/ klasöründe bulunabilir. run_command=/husksync:userdata dump %1% %2% file) [[☂ Web Dök…]](dark_gray show_text=&7Bu ham kullanıcı veri anlığını mc-logs servisine dökme için tıklayın\n&8Verileri içeren bir URL ile sağlanacaksınız. run_command=/husksync:userdata dump %1% %2% web)'
|
||||
data_manager_advancements_preview_remaining: 've %1% daha fazla…'
|
||||
data_list_title: '[%1%''ın kullanıcı veri anlıkları:](#00fb9a) [(%2%-%3% /](#00fb9a) [%4%](#00fb9a bold)[)](#00fb9a)\n'
|
||||
data_list_item: '[%1%](gray show_text=&7Oyuncu Veri Anlığı %2% için %3%&8⚡ %4% run_command=/userdata view %2% %3%) [%5%](#d8ff2b show_text=&7Sabitlendi:\n&8Sabitlenmiş anlıklar otomatik olarak döndürülmez. run_command=/userdata view %2% %3%) [%6%](color=#ffc43b-#f5c962 show_text=&7Versiyon zaman damgası:&7\n&8Verinin ne zaman kaydedildiği\n&8%7% run_command=/userdata view %2% %3%) [⚑ %8%](#23a825-#36f539 show_text=&7Kaydetme sebebi:\n&8Verinin kaydedilme nedeni run_command=/userdata view %2% %3%) [⏏ %9%](color=#62a9f5-#7ab8fa show_text=&7Anlık boyutu:&7\n&8Anlının tahmini dosya boyutu (KiB cinsinden) run_command=/userdata view %2% %3%)'
|
||||
data_deleted: '[❌ Kullanıcı veri anlığı başarıyla silindi](#00fb9a) [%1%](#00fb9a show_text=&7Versiyon UUID:\n&8%2%) [için](#00fb9a) [%3%.](#00fb9a show_text=&7Oyuncu UUID:\n&8%4%)'
|
||||
data_restored: '[⏪ Başarıyla geri yüklendi](#00fb9a) [%1%](#00fb9a show_text=&7Oyuncu UUID:\n&8%2%)[''ın mevcut kullanıcı verisi anlığından](#00fb9a) [%3%.](#00fb9a show_text=&7Versiyon UUID:\n&8%4%)'
|
||||
data_pinned: '[※ Kullanıcı veri anlığı başarıyla sabitlendi](#00fb9a) [%1%](#00fb9a show_text=&7Versiyon UUID:\n&8%2%) [için](#00fb9a) [%3%.](#00fb9a show_text=&7Oyuncu UUID:\n&8%4%)'
|
||||
data_unpinned: '[※ Kullanıcı veri anlığı başarıyla çözüldü](#00fb9a) [%1%](#00fb9a show_text=&7Versiyon UUID:\n&8%2%) [için](#00fb9a) [%3%.](#00fb9a show_text=&7Oyuncu UUID:\n&8%4%)'
|
||||
data_dumped: '[☂ Kullanıcı veri anlığı başarıyla döküldü %1% için %2%:](#00fb9a) &7%3%'
|
||||
list_footer: '\n%1%[Sayfa](#00fb9a) [%2%](#00fb9a)/[%3%](#00fb9a)%4% %5%'
|
||||
list_previous_page_button: '[◀](white show_text=&7Önceki sayfayı görüntüle run_command=%2% %1%) '
|
||||
list_next_page_button: ' [▶](white show_text=&7Sonraki sayfayı görüntüle run_command=%2% %1%)'
|
||||
list_page_jumpers: '(%1%)'
|
||||
list_page_jumper_button: '[%1%](show_text=&7Sayfaya git %1% run_command=%2% %1%)'
|
||||
list_page_jumper_current_page: '[%1%](#00fb9a)'
|
||||
list_page_jumper_separator: ' '
|
||||
list_page_jumper_group_separator: '…'
|
||||
save_cause_disconnect: 'disconnect'
|
||||
save_cause_world_save: 'world save'
|
||||
save_cause_death: 'death'
|
||||
save_cause_server_shutdown: 'server shutdown'
|
||||
save_cause_inventory_command: 'inventory command'
|
||||
save_cause_enderchest_command: 'enderchest command'
|
||||
save_cause_backup_restore: 'backup restore'
|
||||
save_cause_api: 'API'
|
||||
save_cause_mpdb_migration: 'MPDB migration'
|
||||
save_cause_legacy_migration: 'legacy migration'
|
||||
save_cause_converted_from_v2: 'converted from v2'
|
||||
up_to_date: '[HuskSync](#00fb9a bold) [| HuskSync\''in en son sürümünü kullanıyorsunuz (v%1%).](#00fb9a)'
|
||||
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)'
|
||||
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_no_permission: '[Hata:](#ff3300) [Bu komutu gerçekleştirmek için izniniz yok](#ff7e5e)'
|
||||
error_console_command_only: '[Hata:](#ff3300) [Bu komut yalnızca konsoldan çalıştırılabilir](#ff7e5e)'
|
||||
error_in_game_command_only: 'Hata: Bu komut yalnızca oyun içinde kullanılabilir.'
|
||||
error_no_data_to_display: '[Hata:](#ff3300) [Görüntülenecek kullanıcı verisi bulunamadı.](#ff7e5e)'
|
||||
error_invalid_version_uuid: '[Hata:](#ff3300) [Bu sürüm UUID''si için kullanıcı verisi bulunamadı.](#ff7e5e)'
|
||||
husksync_command_description: 'HuskSync eklentisini yönet'
|
||||
userdata_command_description: 'Oyuncu verilerini görüntüle, yönet ve geri yükle'
|
||||
inventory_command_description: 'Oyuncunun envanterini görüntüle ve düzenle'
|
||||
enderchest_command_description: 'Oyuncunun Ender Chest''ini görüntüle ve düzenle'
|
||||
@@ -11,7 +11,7 @@ data_manager_title: '[Viewing user data snapshot](#00fb9a) [%1%](#00fb9a show_te
|
||||
data_manager_timestamp: '[⌚ %1%](#ffc43b-#f5c962 show_text=&7Version timestamp:\n&8When the data was saved)'
|
||||
data_manager_pinned: '[※ Snapshot pinned](#d8ff2b show_text=&7Pinned:\n&8This user data snapshot won''t be automatically rotated.)'
|
||||
data_manager_cause: '[⚑ %1%](#23a825-#36f539 show_text=&7Save cause:\n&8What caused the data to be saved)'
|
||||
data_manager_server: '[Ⓢ %1%](#ff87b3-#f5538e show_text=&7Server:\n&8Name of the server the data was saved on)'
|
||||
data_manager_server: '[☁ %1%](#ff87b3-#f5538e show_text=&7Server:\n&8Name of the server the data was saved on)'
|
||||
data_manager_size: '[⏏ %1%](color=#62a9f5-#7ab8fa show_text=&7Snapshot size:\n&8Estimated file size of the snapshot (in KiB))\n'
|
||||
data_manger_status: '[%1%](red)[/](gray)[%2%](red)[×](gray)[❤](red show_text=&7Health points) [%3%](yellow)[×](gray)[🍖](yellow show_text=&7Hunger points) [ʟᴠ](green)[.](gray)[%4%](green show_text=&7XP level) [🏹 %5%](dark_aqua show_text=&7Game mode)'
|
||||
data_manager_advancements_statistics: '[⭐ Advancements: %1%](color=#ffc43b-#f5c962 show_text=&7Advancements you have progress in:\n&8%2%) [⌛ Play Time: %3%ʜʀs](color=#62a9f5-#7ab8fa show_text=&7In-game play time\n&8⚠ Based on in-game statistics)\n'
|
||||
@@ -34,6 +34,17 @@ list_page_jumper_button: '[%1%](show_text=&7Jump to page %1% run_command=%2% %1%
|
||||
list_page_jumper_current_page: '[%1%](#00fb9a)'
|
||||
list_page_jumper_separator: ' '
|
||||
list_page_jumper_group_separator: '…'
|
||||
save_cause_disconnect: 'disconnect'
|
||||
save_cause_world_save: 'world save'
|
||||
save_cause_death: 'death'
|
||||
save_cause_server_shutdown: 'server shutdown'
|
||||
save_cause_inventory_command: 'inventory command'
|
||||
save_cause_enderchest_command: 'enderchest command'
|
||||
save_cause_backup_restore: 'backup restore'
|
||||
save_cause_api: 'API'
|
||||
save_cause_mpdb_migration: 'MPDB migration'
|
||||
save_cause_legacy_migration: 'legacy migration'
|
||||
save_cause_converted_from_v2: 'converted from v2'
|
||||
up_to_date: '[HuskSync](#00fb9a bold) [| You are running the latest version of HuskSync (v%1%).](#00fb9a)'
|
||||
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)'
|
||||
|
||||
@@ -6,45 +6,56 @@ inventory_viewer_opened: '[正在查看玩家](#00fb9a) [%1%](#00fb9a bold) [于
|
||||
ender_chest_viewer_opened: '[正在查看玩家](#00fb9a) [%1%](#00fb9a bold) [于 ⌚ %2% 的末影箱备份](#00fb9a)'
|
||||
data_update_complete: '[🔔 你的用户数据已更新!](#00fb9a)'
|
||||
data_update_failed: '[🔔 无法更新你的用户数据! 请联系管理员.](#ff7e5e)'
|
||||
user_registration_complete: '[⭐ User registration complete!](#00fb9a)'
|
||||
user_registration_complete: '[⭐ 用户注册完成!](#00fb9a)'
|
||||
data_manager_title: '[正在查看玩家](#00fb9a) [%3%](#00fb9a bold show_text=&7玩家 UUID:\n&8%4%) [的数据备份](#00fb9a) [%1%](#00fb9a show_text=&7备份版本 UUID:\n&8%2%) [:](#00fb9a)'
|
||||
data_manager_timestamp: '[⌚ %1%](#ffc43b-#f5c962 show_text=&7备份时间:\n&7何时保存了此数据)'
|
||||
data_manager_pinned: '[※ 置顶备份](#d8ff2b show_text=&7置顶:\n&8此数据备份不会按照备份时间自动排序.)'
|
||||
data_manager_cause: '[⚑ %1%](#23a825-#36f539 show_text=&7备份原因:\n&7为何保存了此数据)'
|
||||
data_manager_server: '[Ⓢ %1%](#ff87b3-#f5538e show_text=&7Server:\n&8Name of the server the data was saved on)'
|
||||
data_manager_size: '[⏏ %1%](color=#62a9f5-#7ab8fa show_text=&7Snapshot size:\n&8Estimated file size of the snapshot (in KiB))\n'
|
||||
data_manager_server: '[☁ %1%](#ff87b3-#f5538e show_text=&7服务器:\n&8保存数据的服务器的名称)'
|
||||
data_manager_size: '[⏏ %1%](color=#62a9f5-#7ab8fa show_text=&7快照大小:\n&8快照的估计文件大小(以KiB为单位))\n'
|
||||
data_manger_status: '[%1%](red)[/](gray)[%2%](red)[×](gray)[❤](red show_text=&7血量) [%3%](yellow)[×](gray)[🍖](yellow show_text=&7饱食度) [ʟᴠ](green)[.](gray)[%4%](green show_text=&7经验等级) [🏹 %5%](dark_aqua show_text=&7游戏模式)'
|
||||
data_manager_advancements_statistics: '[⭐ 成就: %1%](color=#ffc43b-#f5c962 show_text=&7%2%) [⌛ 游玩时间: %3%ʜʀs](color=#62a9f5-#7ab8fa show_text=&7⚠ 基于游戏内的统计)\n'
|
||||
data_manager_item_buttons: '[View:](gray) [[🪣 背包…]](color=#a17b5f-#f5b98c show_text=&7点击查看 run_command=/inventory %1% %2%) [[⌀ 末影箱…]](#b649c4-#d254ff show_text=&7点击查看 run_command=/enderchest %1% %2%)'
|
||||
data_manager_management_buttons: '[Manage:](gray) [[❌ 删除…]](#ff3300 show_text=&7点击删除此数据备份.\n这不会影响玩家当前的数据.\n&#ff3300&⚠ 此操作不可撤销! suggest_command=/husksync:userdata delete %1% %2%) [[⏪ 恢复…]](#00fb9a show_text=&7点击让玩家恢复到此数据备份.\n这将会使玩家的数据恢复到这个备份.\n&#ff3300&⚠ %1% 当前的用户数据会被备份数据所覆盖! suggest_command=/husksync:userdata restore %1% %2%) [[※ Pin/Unpin…]](#d8ff2b show_text=&7Click to pin or unpin this user data snapshot\n&8Pinned snapshots won''t be automatically rotated run_command=/userdata pin %1% %2%)'
|
||||
data_manager_system_buttons: '[System:](gray) [[⏷ File Dump…]](dark_gray show_text=&7Click to dump this raw user data snapshot to a file.\n&8Data dumps can be found in ~/plugins/HuskSync/dumps/ run_command=/husksync:userdata dump %1% %2% file) [[☂ Web Dump…]](dark_gray show_text=&7Click to dump this raw user data snapshot to the mc-logs service\n&8You will be provided with a URL containing the data. run_command=/husksync:userdata dump %1% %2% web)'
|
||||
data_manager_management_buttons: '[Manage:](gray) [[❌ 删除…]](#ff3300 show_text=&7点击删除此数据备份.\n这不会影响玩家当前的数据.\n&#ff3300&⚠ 此操作不可撤销! suggest_command=/husksync:userdata delete %1% %2%) [[⏪ 恢复…]](#00fb9a show_text=&7点击让玩家恢复到此数据备份.\n这将会使玩家的数据恢复到这个备份.\n&#ff3300&⚠ %1% 当前的用户数据会被备份数据所覆盖! suggest_command=/husksync:userdata restore %1% %2%) [[※ 固定/取消固定…]](#d8ff2b show_text=&7单击可固定或取消固定此用户数据快照\n&8固定的快照不会自动重载 run_command=/userdata pin %1% %2%)'
|
||||
data_manager_system_buttons: '[System:](gray) [[⏷ 文件储存…]](dark_gray show_text=&7单击将此原始用户数据快照储存到文件.\n&8数据储存可以在 ~/plugins/HuskSync/dumps/ 中找到 run_command=/husksync:userdata dump %1% %2% file) [[☂ Web 储存…]](dark_gray show_text=&7单击将此原始用户数据快照转储到mc日志服务\n&8您将获得包含数据的URL. run_command=/husksync:userdata dump %1% %2% web)'
|
||||
data_manager_advancements_preview_remaining: '还有 %1% …'
|
||||
data_list_title: '[%1%''s user data snapshots:](#00fb9a) [(%2%-%3% of](#00fb9a) [%4%](#00fb9a bold)[)](#00fb9a)\n'
|
||||
data_list_item: '[%1%](gray show_text=&7User Data Snapshot for %2%&8⚡ %4% run_command=/userdata view %2% %3%) [%5%](#d8ff2b show_text=&7Pinned:\n&8Pinned snapshots won''t be automatically rotated. run_command=/userdata view %2% %3%) [%6%](color=#ffc43b-#f5c962 show_text=&7Version timestamp:&7\n&8When the data was saved\n&8%7% run_command=/userdata view %2% %3%) [⚑ %8%](#23a825-#36f539 show_text=&7Save cause:\n&8What caused the data to be saved run_command=/userdata view %2% %3%) [⏏ %9%](color=#62a9f5-#7ab8fa show_text=&7Snapshot size:&7\n&8Estimated file size of the snapshot (in KiB) run_command=/userdata view %2% %3%)'
|
||||
data_list_title: '[%1%的用户数据快照:](#00fb9a) [(%2%-%3% of](#00fb9a) [%4%](#00fb9a bold)[)](#00fb9a)\n'
|
||||
data_list_item: '[%1%](gray show_text=&7的用户数据快照 %2%&8⚡ %4% run_command=/userdata view %2% %3%) [%5%](#d8ff2b show_text=&7固定:\n&8固定的快照不会自动加载. run_command=/userdata view %2% %3%) [%6%](color=#ffc43b-#f5c962 show_text=&7版本时间戳:&7\n&8保存数据时\n&8%7% run_command=/userdata view %2% %3%) [⚑ %8%](#23a825-#36f539 show_text=&7保存原因:\n&8是什么导致数据被保存 run_command=/userdata view %2% %3%) [⏏ %9%](color=#62a9f5-#7ab8fa show_text=&7快照大小:&7\n&8快照的估计文件大小(以KiB为单位) run_command=/userdata view %2% %3%)'
|
||||
data_deleted: '[❌ 成功删除玩家](#00fb9a) [%3%](#00fb9a show_text=&7玩家 UUID:\n&7%4%) [的数据备份](#00fb9a) [%1%.](#00fb9a show_text=&7备份版本 UUID:\n&7%2%)'
|
||||
data_restored: '[⏪ 成功恢复玩家](#00fb9a) [%1%](#00fb9a show_text=&7玩家 UUID:\n&7%2%)[的数据备份](#00fb9a) [%3%.](#00fb9a show_text=&7备份版本 UUID:\n&7%4%)'
|
||||
data_pinned: '[※ 成功置顶玩家](#00fb9a) [%3%](#00fb9a show_text=&7玩家 UUID:\n&8%4%) [的数据备份](#00fb9a) [%1%.](#00fb9a show_text=&7备份版本 UUID:\n&8%2%)'
|
||||
data_unpinned: '[※ 成功取消置顶玩家](#00fb9a) [%3%](#00fb9a show_text=&7玩家 UUID:\n&8%4%) [的数据备份](#00fb9a) [%1%.](#00fb9a show_text=&7备份版本 UUID:\n&8%2%)'
|
||||
data_dumped: '[☂ Successfully dumped the user data snapshot %1% for %2% to:](#00fb9a) &7%3%'
|
||||
data_dumped: '[☂ 已成功将 %1% 的用户数据快照 %2% 转储到:](#00fb9a) &7%3%'
|
||||
list_footer: '\n%1%[Page](#00fb9a) [%2%](#00fb9a)/[%3%](#00fb9a)%4% %5%'
|
||||
list_previous_page_button: '[◀](white show_text=&7View previous page run_command=%2% %1%) '
|
||||
list_next_page_button: ' [▶](white show_text=&7View next page run_command=%2% %1%)'
|
||||
list_previous_page_button: '[◀](white show_text=&7查看上一页 run_command=%2% %1%) '
|
||||
list_next_page_button: ' [▶](white show_text=&7查看下一页 run_command=%2% %1%)'
|
||||
list_page_jumpers: '(%1%)'
|
||||
list_page_jumper_button: '[%1%](show_text=&7Jump to page %1% run_command=%2% %1%)'
|
||||
list_page_jumper_button: '[%1%](show_text=&7跳转到页面 %1% run_command=%2% %1%)'
|
||||
list_page_jumper_current_page: '[%1%](#00fb9a)'
|
||||
list_page_jumper_separator: ' '
|
||||
list_page_jumper_group_separator: '…'
|
||||
save_cause_disconnect: 'disconnect'
|
||||
save_cause_world_save: 'world save'
|
||||
save_cause_death: 'death'
|
||||
save_cause_server_shutdown: 'server shutdown'
|
||||
save_cause_inventory_command: 'inventory command'
|
||||
save_cause_enderchest_command: 'enderchest command'
|
||||
save_cause_backup_restore: 'backup restore'
|
||||
save_cause_api: 'API'
|
||||
save_cause_mpdb_migration: 'MPDB migration'
|
||||
save_cause_legacy_migration: 'legacy migration'
|
||||
save_cause_converted_from_v2: 'converted from v2'
|
||||
up_to_date: '[HuskSync](#00fb9a bold) [| 你正在使用最新版本的HuskSync (v%1%)](#00fb9a)'
|
||||
update_available: '[HuskSync](#ff7e5e bold) [| 一个新版本的HuskSync已经可以更新: v%1% (当前: 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)'
|
||||
error_invalid_syntax: ':](#ff3300) [格式错误, 使用方法:](#ff7e5e) [%1%](#ff7e5e italic show_text=&#ff7e5e&Click to suggest suggest_command=%1%)'
|
||||
reload_complete: '[HuskSync](#00fb9a bold) [| 插件配置和语言文件已重载.](#00fb9a)\n[⚠ 确保所有服务器上的配置文件都是最新的!](#00fb9a)\n[需要重新启动配置更改才能生效.](#00fb9a italic)'
|
||||
error_invalid_syntax: ':](#ff3300) [格式错误, 使用方法:](#ff7e5e) [%1%](#ff7e5e italic show_text=&#ff7e5e&点击建议 suggest_command=%1%)'
|
||||
error_invalid_player: '[错误:](#ff3300) [无法找到目标玩家.](#ff7e5e)'
|
||||
error_no_permission: '[错误:](#ff3300) [你没有执行此指令的权限](#ff7e5e)'
|
||||
error_console_command_only: '[错误:](#ff3300) [该指令只能在控制台运行](#ff7e5e)'
|
||||
error_in_game_command_only: 'Error: 该指令只能在游戏内运行.'
|
||||
error_no_data_to_display: '[错误:](#ff3300) [无法找到用户数据显示.](#ff7e5e)'
|
||||
error_invalid_version_uuid: '[错误:](#ff3300) [无法找到该备份的 UUID .](#ff7e5e)'
|
||||
husksync_command_description: 'Manage the HuskSync plugin'
|
||||
userdata_command_description: 'View, manage & restore player userdata'
|
||||
inventory_command_description: 'View & edit a player''s inventory'
|
||||
enderchest_command_description: 'View & edit a player''s Ender Chest'
|
||||
husksync_command_description: '管理HuskSync插件'
|
||||
userdata_command_description: '查看、管理和恢复玩家用户数据'
|
||||
inventory_command_description: '查看和编辑玩家的背包'
|
||||
enderchest_command_description: '查看和编辑玩家的末影箱'
|
||||
|
||||
@@ -11,7 +11,7 @@ data_manager_title: '[查看](#00fb9a) [%3%](#00fb9a bold show_text=&7玩家 UUI
|
||||
data_manager_timestamp: '[⌚ %1%](#ffc43b-#f5c962 show_text=&7快照時間:\n&8何時保存的資料)'
|
||||
data_manager_pinned: '[※ 被標記的快照](#d8ff2b show_text=&7標記:\n&8此快照資料不會自動輪換更新)'
|
||||
data_manager_cause: '[⚑ %1%](#23a825-#36f539 show_text=&7保存原因:\n&8保存此快照的原因)'
|
||||
data_manager_server: '[Ⓢ %1%](#ff87b3-#f5538e show_text=&7Server:\n&8Name of the server the data was saved on)'
|
||||
data_manager_server: '[☁ %1%](#ff87b3-#f5538e show_text=&7Server:\n&8Name of the server the data was saved on)'
|
||||
data_manager_size: '[⏏ %1%](color=#62a9f5-#7ab8fa show_text=&7Snapshot size:\n&8Estimated file size of the snapshot (in KiB))\n'
|
||||
data_manger_status: '[%1%](red)[/](gray)[%2%](red)[×](gray)[❤](red show_text=&7血量) [%3%](yellow)[×](gray)[🍖](yellow show_text=&7飽食度) [ʟᴠ](green)[.](gray)[%4%](green show_text=&7經驗等級) [🏹 %5%](dark_aqua show_text=&7遊戲模式)'
|
||||
data_manager_advancements_statistics: '[⭐ 成就: %1%](color=#ffc43b-#f5c962 show_text=&7已獲得的成就:\n&8%2%) [⌛ 遊戲時間: %3%ʜʀs](color=#62a9f5-#7ab8fa show_text=&7遊戲內的遊玩時間\n&8⚠ 根據遊戲內統計)\n'
|
||||
@@ -34,6 +34,17 @@ list_page_jumper_button: '[%1%](show_text=&7跳至第 %1% 頁 run_command=%2% %1
|
||||
list_page_jumper_current_page: '[%1%](#00fb9a)'
|
||||
list_page_jumper_separator: ' '
|
||||
list_page_jumper_group_separator: '…'
|
||||
save_cause_disconnect: 'disconnect'
|
||||
save_cause_world_save: 'world save'
|
||||
save_cause_death: 'death'
|
||||
save_cause_server_shutdown: 'server shutdown'
|
||||
save_cause_inventory_command: 'inventory command'
|
||||
save_cause_enderchest_command: 'enderchest command'
|
||||
save_cause_backup_restore: 'backup restore'
|
||||
save_cause_api: 'API'
|
||||
save_cause_mpdb_migration: 'MPDB migration'
|
||||
save_cause_legacy_migration: 'legacy migration'
|
||||
save_cause_converted_from_v2: 'converted from v2'
|
||||
up_to_date: '[HuskSync](#00fb9a bold) [| 您運行的是最新版本的 HuskSync (v%1%).](#00fb9a)'
|
||||
update_available: '[HuskSync](#ff7e5e bold) [| 發現可用的新版本: 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)'
|
||||
|
||||
@@ -60,8 +60,8 @@ redis:
|
||||
password: ''
|
||||
use_ssl: false
|
||||
synchronization:
|
||||
# The mode of data synchronization to use (DELAY or LOCKSTEP). DELAY should be fine for most networks. Docs: https://william278.net/docs/husksync/sync-modes
|
||||
mode: DELAY
|
||||
# The data synchronization mode to use (LOCKSTEP or DELAY). LOCKSTEP is recommended for most networks. Docs: https://william278.net/docs/husksync/sync-modes
|
||||
mode: LOCKSTEP
|
||||
# The number of data snapshot backups that should be kept at once per user
|
||||
max_user_data_snapshots: 16
|
||||
# Number of hours between new snapshots being saved as backups (Use "0" to backup all snapshots)
|
||||
|
||||
@@ -12,6 +12,7 @@ If you'd like to have a look at an example of a data extension for HuskSync that
|
||||
2. [Extending the BukkitSerializer Class](#2-extending-the-bukkitserializer-class)
|
||||
3. [Identifiers and registering our Serializer](#3-identifiers--registering-our-serializer)
|
||||
4. [Setting and Getting our Data to/from a User](#4-setting-and-getting-our-data-tofrom-a-user)
|
||||
1. [Persisting custom data on the DataSaveEvent](#41-persisting-custom-data-on-the-datasaveevent)
|
||||
|
||||
## 1. Extending the BukkitData Class
|
||||
* HuskSync provides a `Data` interface that you must implement that will represent your custom data.
|
||||
@@ -130,4 +131,14 @@ huskSyncAPI.getUser(player).setData(LOGIN_PARTICLES_ID, loginParticleData);
|
||||
|
||||
// Get our data from a player
|
||||
LoginParticleData loginParticleData = (LoginParticleData) huskSyncAPI.getUser(player).getData(LOGIN_PARTICLES_ID);
|
||||
```
|
||||
```
|
||||
|
||||
### 4.1 Persisting custom data on the DataSaveEvent
|
||||
Add an EventListener to the `DataSaveEvent` and use the `#editData` consumer method to apply custom data during standard DataSaves. This will persist data to users any time the data save routine executes (on user logout, server shutdownm, world save, etc).
|
||||
|
||||
```java
|
||||
@EventHandler
|
||||
public void onDataSave(BukkitDataSaveEvent event) {
|
||||
event.editData((unpacked) -> unpacked.setData(LOGIN_PARTICLES_ID, new LoginParticleData("FIREWORKS_SPARK", 10)));
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
This guide will walk you through how to migrate from MySQLPlayerDataBridge (MPDB) to HuskSync v2.x.
|
||||
This guide will walk you through how to migrate from MySQLPlayerDataBridge (MPDB) to HuskSync v3.x.
|
||||
|
||||
> **Warning:** Please note that due to MPDB changes, HuskSync only supports migrating from MySQLPlayerDataBridge `<= v4.9.2`. Support for newer versions will be added in the future.
|
||||
|
||||
@@ -6,13 +6,13 @@ This guide will walk you through how to migrate from MySQLPlayerDataBridge (MPDB
|
||||
- Spigot servers with MySQLPlayerDataBridge *still installed*
|
||||
|
||||
## Migration Instructions
|
||||
### 1. Install HuskSync v2.x on all Spigot servers
|
||||
### 1. Install HuskSync v3.x on all Spigot servers
|
||||
- Download, then install HuskSync on all your servers. Don't uninstall MySQLPlayerDataBridge yet.
|
||||
- Follow the setup instructions [here](Setup).
|
||||
- Follow the setup instructions [here](setup).
|
||||
- Start your servers again when done.
|
||||
|
||||
### 2. Configure the migrator
|
||||
- With your servers back on and correctly configured to run HuskSync v2.x, ensure nobody is online.
|
||||
- With your servers back on and correctly configured to run HuskSync v3.x, ensure nobody is online.
|
||||
- Use the console on one of your Spigot servers to enter: `husksync migrate mpdb`. If the MPDB migrator is not available, ensure MySQLPlayerDataBridge is still installed.
|
||||
- Adjust the migration setting as needed using the following command: `husksync migrate mpdb set <setting> <value>`.
|
||||
- Note that migration will be carried out *from* the database you specify with the settings in console *to* the database configured in `config.yml`.
|
||||
@@ -27,4 +27,4 @@ This guide will walk you through how to migrate from MySQLPlayerDataBridge (MPDB
|
||||
|
||||
### 5. Ensure the migration was successful
|
||||
- Verify that the migration was successful by logging in and using the `/userdata list <username>` command to see if the data was imported with the `mpdb_migration` saveCause.
|
||||
- You can delete the old tables in the database if you want. Be careful to make sure you delete the correct ones.
|
||||
- You can delete the old tables in the database if you want. Be careful to make sure you delete the correct ones.
|
||||
|
||||
@@ -3,8 +3,8 @@ HuskSync offers two built-in **synchronization modes** that utilise Redis and My
|
||||

|
||||
|
||||
## Available Modes
|
||||
* The `DELAY` sync mode is the default sync mode, that use the `network_latency_miliseconds` value to apply a delay before listening to Redis data
|
||||
* The `LOCKSTEP` sync mode uses a data checkout system to ensure that all servers are in sync regardless of network latency or tick rate fluctuations. This mode was introduced in HuskSync v3.1
|
||||
* The `LOCKSTEP` sync mode is the default sync mode. It uses a data checkout system to ensure that all servers are in sync regardless of network latency or tick rate fluctuations. This mode was introduced in HuskSync v3.1
|
||||
* The `DELAY` sync mode uses the `network_latency_miliseconds` value to apply a delay before listening to Redis data
|
||||
|
||||
You can change which sync mode you are using by editing the `sync_mode` setting under `synchronization` in `config.yml`.
|
||||
|
||||
@@ -15,11 +15,22 @@ You can change which sync mode you are using by editing the `sync_mode` setting
|
||||
|
||||
```yaml
|
||||
synchronization:
|
||||
# The mode of data synchronization to use (DELAY or LOCKSTEP). DELAY should be fine for most networks. Docs: https://william278.net/docs/husksync/sync-modes
|
||||
mode: DELAY
|
||||
# The data synchronization mode to use (LOCKSTEP or DELAY). LOCKSTEP is recommended for most networks. Docs: https://william278.net/docs/husksync/sync-modes
|
||||
mode: LOCKSTEP
|
||||
```
|
||||
</details>
|
||||
|
||||
## Lockstep
|
||||
The `LOCKSTEP` sync mode works as described below:
|
||||
* When a user connects to a server, the server will continuously asynchronously check if a `DATA_CHECKOUT` key is present.
|
||||
* If, or when, the key is not present, the plugin will set a new `DATA_CHECKOUT` key.
|
||||
* After this, the plugin will check Redis for the presence of a `DATA_UPDATE` key.
|
||||
* If a `DATA_UPDATE` key is present, the user's data will be set from the snapshot deserialized from Redis contained within that key.
|
||||
* Otherwise, their data will be pulled from the database.
|
||||
* When a user disconnects from a server, their data is serialized and set to Redis with a `DATA_UPDATE` key. After this key has been set, the user's current `DATA_CHECKOUT` key will be removed from Redis.
|
||||
|
||||
Additionally, note that `DATA_CHECKOUT` keys are set with the server ID of the server which "checked out" the data (taken from the `server.yml` config file). On both shutdown and startup, the plugin will clear all `DATA_CHECKOUT` keys for the current server ID (to prevent stale keys in the event of a server crash for instance)
|
||||
|
||||
## Delay
|
||||
The `DELAY` sync mode works as described below:
|
||||
* When a user disconnects from a server, a `SERVER_SWITCH` key is immediately set on Redis, followed by a `DATA_UPDATE` key which contains the user's packed and serialized Data Snapshot.
|
||||
@@ -31,15 +42,4 @@ The `DELAY` sync mode works as described below:
|
||||
|
||||
`DELAY` has been the default sync mode since HuskSync v2.0. In HuskSync v3.1, `LOCKSTEP` was introduced. Since the delay mode has been tested and deployed for the longest, it is still the default, though note this may change in the future.
|
||||
|
||||
However, if your network has a fluctuating tick rate or significant latency (especially if you have servers on different hardware/locations), you may wish to use `LOCKSTEP` instead for a more reliable sync system.
|
||||
|
||||
## Lockstep
|
||||
The `LOCKSTEP` sync mode works as described below:
|
||||
* When a user connects to a server, the server will continuously asynchronously check if a `DATA_CHECKOUT` key is present.
|
||||
* If, or when, the key is not present, the plugin will set a new `DATA_CHECKOUT` key.
|
||||
* After this, the plugin will check Redis for the presence of a `DATA_UPDATE` key.
|
||||
* If a `DATA_UPDATE` key is present, the user's data will be set from the snapshot deserialized from Redis contained within that key.
|
||||
* Otherwise, their data will be pulled from the database.
|
||||
* When a user disconnects from a server, their data is serialized and set to Redis with a `DATA_UPDATE` key. After this key has been set, the user's current `DATA_CHECKOUT` key will be removed from Redis.
|
||||
|
||||
Additionally, note that `DATA_CHECKOUT` keys are set with the server ID of the server which "checked out" the data (taken from the `server.yml` config file). On both shutdown and startup, the plugin will clear all `DATA_CHECKOUT` keys for the current server ID (to prevent stale keys in the event of a server crash for instance)
|
||||
However, if your network has a fluctuating tick rate or significant latency (especially if you have servers on different hardware/locations), you may wish to use `LOCKSTEP` instead for a more reliable sync system.
|
||||
@@ -28,4 +28,5 @@
|
||||
* 🚰 [Spigot](https://www.spigotmc.org/resources/husksync.97144/)
|
||||
* 🛒 [Polymart](https://polymart.org/resource/husksync.1634)
|
||||
* ⚒️ [Craftaro](https://craftaro.com/marketplace/product/husksync.758)
|
||||
* 💬 [Discord Support](https://discord.gg/tVYhJfyDWG)
|
||||
* 🛒 [BuiltByBit](https://craftaro.com/marketplace/product/husksync.758)
|
||||
* 💬 [Discord Support](https://discord.gg/tVYhJfyDWG)
|
||||
|
||||
@@ -3,11 +3,11 @@ org.gradle.jvmargs='-Dfile.encoding=UTF-8'
|
||||
org.gradle.daemon=true
|
||||
javaVersion=16
|
||||
|
||||
plugin_version=3.1
|
||||
plugin_version=3.2
|
||||
plugin_archive=husksync
|
||||
plugin_description=A modern, cross-server player data synchronization system
|
||||
|
||||
jedis_version=5.0.0
|
||||
mysql_driver_version=8.1.0
|
||||
mariadb_driver_version=3.2.0
|
||||
snappy_version=1.1.10.3
|
||||
jedis_version=5.1.0
|
||||
mysql_driver_version=8.2.0
|
||||
mariadb_driver_version=3.3.2
|
||||
snappy_version=1.1.10.5
|
||||
|
||||
@@ -17,7 +17,6 @@ shadowJar {
|
||||
relocate 'org.json', 'net.william278.husksync.libraries.json'
|
||||
relocate 'com.fatboyindustrial', 'net.william278.husksync.libraries'
|
||||
relocate 'de.themoep', 'net.william278.husksync.libraries'
|
||||
relocate 'net.kyori', 'net.william278.husksync.libraries'
|
||||
relocate 'org.jetbrains', 'net.william278.husksync.libraries'
|
||||
relocate 'org.intellij', 'net.william278.husksync.libraries'
|
||||
relocate 'com.zaxxer', 'net.william278.husksync.libraries'
|
||||
|
||||
@@ -19,10 +19,14 @@
|
||||
|
||||
package net.william278.husksync;
|
||||
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.william278.husksync.listener.BukkitEventListener;
|
||||
import net.william278.husksync.listener.PaperEventListener;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class PaperHuskSync extends BukkitHuskSync {
|
||||
|
||||
@@ -32,4 +36,11 @@ public class PaperHuskSync extends BukkitHuskSync {
|
||||
return new PaperEventListener(this);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Audience getAudience(@NotNull UUID user) {
|
||||
final Player player = getServer().getPlayer(user);
|
||||
return player == null || !player.isOnline() ? Audience.empty() : player;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,4 +4,4 @@ colorama==0.4.6
|
||||
idna==3.4
|
||||
requests==2.31.0
|
||||
tqdm==4.66.1
|
||||
urllib3==2.0.6
|
||||
urllib3==2.0.7
|
||||
|
||||
@@ -13,7 +13,7 @@ from tqdm import tqdm
|
||||
class Parameters:
|
||||
root_dir = './servers/'
|
||||
proxy_version = "1.20"
|
||||
minecraft_version = '1.20.2'
|
||||
minecraft_version = '1.20.4'
|
||||
eula_agreement = 'true'
|
||||
|
||||
backend_names = ['alpha', 'beta']
|
||||
|
||||
Reference in New Issue
Block a user