mirror of
https://github.com/lucko/LuckPerms.git
synced 2025-09-01 18:32:33 +02:00
Automatically install translation bundles
This commit is contained in:
@@ -310,6 +310,9 @@ log-notify: true
|
||||
log-notify-filtered-descriptions:
|
||||
# - "parent add example"
|
||||
|
||||
# If LuckPerms should automatically install translation bundles and periodically update them.
|
||||
auto-install-translations: true
|
||||
|
||||
# Defines the options for prefix and suffix stacking.
|
||||
#
|
||||
# - The feature allows you to display multiple prefixes or suffixes alongside a players username in
|
||||
|
@@ -318,6 +318,9 @@ log-notify: true
|
||||
log-notify-filtered-descriptions:
|
||||
# - "parent add example"
|
||||
|
||||
# If LuckPerms should automatically install translation bundles and periodically update them.
|
||||
auto-install-translations: true
|
||||
|
||||
# Defines the options for prefix and suffix stacking.
|
||||
#
|
||||
# - The feature allows you to display multiple prefixes or suffixes alongside a players username in
|
||||
|
@@ -25,9 +25,6 @@
|
||||
|
||||
package me.lucko.luckperms.common.commands.misc;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import me.lucko.luckperms.common.command.CommandResult;
|
||||
import me.lucko.luckperms.common.command.abstraction.SingleCommand;
|
||||
import me.lucko.luckperms.common.command.access.CommandPermission;
|
||||
@@ -36,36 +33,19 @@ import me.lucko.luckperms.common.command.utils.ArgumentList;
|
||||
import me.lucko.luckperms.common.http.UnsuccessfulRequestException;
|
||||
import me.lucko.luckperms.common.locale.Message;
|
||||
import me.lucko.luckperms.common.locale.TranslationManager;
|
||||
import me.lucko.luckperms.common.locale.TranslationRepository.LanguageInfo;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.util.MoreFiles;
|
||||
import me.lucko.luckperms.common.util.Predicates;
|
||||
import me.lucko.luckperms.common.util.gson.GsonProvider;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.ResponseBody;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class TranslationsCommand extends SingleCommand {
|
||||
private static final String TRANSLATIONS_INFO_ENDPOINT = "https://metadata.luckperms.net/data/translations";
|
||||
private static final String TRANSLATIONS_DOWNLOAD_ENDPOINT = "https://metadata.luckperms.net/translation/";
|
||||
|
||||
public TranslationsCommand() {
|
||||
super(CommandSpec.TRANSLATIONS, "Translations", CommandPermission.TRANSLATIONS, Predicates.notInRange(0, 1));
|
||||
@@ -77,7 +57,7 @@ public class TranslationsCommand extends SingleCommand {
|
||||
|
||||
List<LanguageInfo> availableTranslations;
|
||||
try {
|
||||
availableTranslations = getAvailableTranslations(plugin);
|
||||
availableTranslations = plugin.getTranslationRepository().getAvailableLanguages();
|
||||
} catch (IOException | UnsuccessfulRequestException e) {
|
||||
Message.TRANSLATIONS_SEARCHING_ERROR.send(sender);
|
||||
plugin.getLogger().warn("Unable to obtain a list of available translations", e);
|
||||
@@ -86,10 +66,7 @@ public class TranslationsCommand extends SingleCommand {
|
||||
|
||||
if (args.size() >= 1 && args.get(0).equalsIgnoreCase("install")) {
|
||||
Message.TRANSLATIONS_INSTALLING.send(sender);
|
||||
|
||||
downloadTranslations(plugin, availableTranslations, sender);
|
||||
plugin.getTranslationManager().reload();
|
||||
|
||||
plugin.getTranslationRepository().downloadAndInstallTranslations(availableTranslations, sender, true);
|
||||
Message.TRANSLATIONS_INSTALL_COMPLETE.send(sender);
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
@@ -98,109 +75,11 @@ public class TranslationsCommand extends SingleCommand {
|
||||
|
||||
Message.AVAILABLE_TRANSLATIONS_HEADER.send(sender);
|
||||
for (LanguageInfo language : availableTranslations) {
|
||||
Message.AVAILABLE_TRANSLATIONS_ENTRY.send(sender, language.locale.toString(), localeDisplayName(language.locale), language.progress, language.contributors);
|
||||
Message.AVAILABLE_TRANSLATIONS_ENTRY.send(sender, language.locale().toString(), TranslationManager.localeDisplayName(language.locale()), language.progress(), language.contributors());
|
||||
}
|
||||
sender.sendMessage(Message.prefixed(Component.empty()));
|
||||
Message.TRANSLATIONS_DOWNLOAD_PROMPT.send(sender, label);
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
|
||||
private static void downloadTranslations(LuckPermsPlugin plugin, List<LanguageInfo> languages, Sender sender) {
|
||||
try {
|
||||
MoreFiles.createDirectoriesIfNotExists(plugin.getTranslationManager().getTranslationsDirectory());
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
for (LanguageInfo language : languages) {
|
||||
Message.TRANSLATIONS_INSTALLING_SPECIFIC.send(sender, language.locale.toString());
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.header("User-Agent", plugin.getBytebin().getUserAgent())
|
||||
.url(TRANSLATIONS_DOWNLOAD_ENDPOINT + language.id)
|
||||
.build();
|
||||
|
||||
Path file = plugin.getTranslationManager().getTranslationsDirectory().resolve(language.locale.toString() + ".properties");
|
||||
|
||||
try (Response response = plugin.getBytebin().makeHttpRequest(request)) {
|
||||
try (ResponseBody responseBody = response.body()) {
|
||||
if (responseBody == null) {
|
||||
throw new RuntimeException("No response");
|
||||
}
|
||||
|
||||
try (InputStream inputStream = responseBody.byteStream()) {
|
||||
Files.copy(inputStream, file, StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
}
|
||||
} catch (UnsuccessfulRequestException | IOException e) {
|
||||
Message.TRANSLATIONS_DOWNLOAD_ERROR.send(sender, language.locale.toString());
|
||||
plugin.getLogger().warn("Unable to download translations", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static List<LanguageInfo> getAvailableTranslations(LuckPermsPlugin plugin) throws IOException, UnsuccessfulRequestException {
|
||||
Request request = new Request.Builder()
|
||||
.header("User-Agent", plugin.getBytebin().getUserAgent())
|
||||
.url(TRANSLATIONS_INFO_ENDPOINT)
|
||||
.build();
|
||||
|
||||
JsonObject jsonResponse;
|
||||
try (Response response = plugin.getBytebin().makeHttpRequest(request)) {
|
||||
try (ResponseBody responseBody = response.body()) {
|
||||
if (responseBody == null) {
|
||||
throw new RuntimeException("No response");
|
||||
}
|
||||
|
||||
try (InputStream inputStream = responseBody.byteStream()) {
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
|
||||
jsonResponse = GsonProvider.normal().fromJson(reader, JsonObject.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<LanguageInfo> languages = new ArrayList<>();
|
||||
for (Map.Entry<String, JsonElement> language : jsonResponse.get("languages").getAsJsonObject().entrySet()) {
|
||||
languages.add(new LanguageInfo(language.getKey(), language.getValue().getAsJsonObject()));
|
||||
}
|
||||
languages.removeIf(language -> language.progress <= 0);
|
||||
return languages;
|
||||
}
|
||||
|
||||
private static String localeDisplayName(Locale locale) {
|
||||
if (locale.getLanguage().equals("zh")) {
|
||||
if (locale.getCountry().equals("CN")) {
|
||||
return "简体中文"; // Chinese (Simplified)
|
||||
} else if (locale.getCountry().equals("TW")) {
|
||||
return "繁體中文"; // Chinese (Traditional)
|
||||
}
|
||||
return locale.getDisplayCountry(locale) + locale.getDisplayLanguage(locale);
|
||||
}
|
||||
|
||||
if (locale.getLanguage().equals("en") && locale.getCountry().equals("PT")) {
|
||||
return "Pirate";
|
||||
}
|
||||
|
||||
return locale.getDisplayLanguage(locale);
|
||||
}
|
||||
|
||||
private static final class LanguageInfo {
|
||||
private final String id;
|
||||
private final String name;
|
||||
private final Locale locale;
|
||||
private final int progress;
|
||||
private final List<String> contributors;
|
||||
|
||||
LanguageInfo(String id, JsonObject data) {
|
||||
this.id = id;
|
||||
this.name = data.get("name").getAsString();
|
||||
this.locale = Objects.requireNonNull(TranslationManager.parseLocale(data.get("localeTag").getAsString()));
|
||||
this.progress = data.get("progress").getAsInt();
|
||||
this.contributors = new ArrayList<>();
|
||||
for (JsonElement contributor : data.get("contributors").getAsJsonArray()) {
|
||||
this.contributors.add(contributor.getAsJsonObject().get("name").getAsString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -416,6 +416,11 @@ public final class ConfigKeys {
|
||||
.collect(ImmutableCollectors.toList());
|
||||
});
|
||||
|
||||
/**
|
||||
* If LuckPerms should automatically install translation bundles and periodically update them.
|
||||
*/
|
||||
public static final ConfigKey<Boolean> AUTO_INSTALL_TRANSLATIONS = notReloadable(booleanKey("auto-install-translations", true));
|
||||
|
||||
/**
|
||||
* If auto op is enabled. Only used by the Bukkit platform.
|
||||
*/
|
||||
|
@@ -159,7 +159,6 @@ public class TranslationManager {
|
||||
}
|
||||
|
||||
this.registry.registerAll(locale, bundle, false);
|
||||
this.plugin.getLogger().info("Registered additional translations for " + locale.toString());
|
||||
this.installed.add(locale);
|
||||
return Maps.immutableEntry(locale, bundle);
|
||||
}
|
||||
@@ -186,4 +185,21 @@ public class TranslationManager {
|
||||
return locale == null ? null : Translator.parseLocale(locale);
|
||||
}
|
||||
|
||||
public static String localeDisplayName(Locale locale) {
|
||||
if (locale.getLanguage().equals("zh")) {
|
||||
if (locale.getCountry().equals("CN")) {
|
||||
return "简体中文"; // Chinese (Simplified)
|
||||
} else if (locale.getCountry().equals("TW")) {
|
||||
return "繁體中文"; // Chinese (Traditional)
|
||||
}
|
||||
return locale.getDisplayCountry(locale) + locale.getDisplayLanguage(locale);
|
||||
}
|
||||
|
||||
if (locale.getLanguage().equals("en") && locale.getCountry().equals("PT")) {
|
||||
return "Pirate";
|
||||
}
|
||||
|
||||
return locale.getDisplayLanguage(locale);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,329 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.locale;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
|
||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||
import me.lucko.luckperms.common.http.UnsuccessfulRequestException;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.util.MoreFiles;
|
||||
import me.lucko.luckperms.common.util.gson.GsonProvider;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.ResponseBody;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.Closeable;
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class TranslationRepository {
|
||||
private static final String TRANSLATIONS_INFO_ENDPOINT = "https://metadata.luckperms.net/data/translations";
|
||||
private static final String TRANSLATIONS_DOWNLOAD_ENDPOINT = "https://metadata.luckperms.net/translation/";
|
||||
private static final long MAX_BUNDLE_SIZE = 1048576L; // 1mb
|
||||
private static final long CACHE_MAX_AGE = TimeUnit.DAYS.toMillis(1);
|
||||
|
||||
private final LuckPermsPlugin plugin;
|
||||
|
||||
public TranslationRepository(LuckPermsPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of available languages.
|
||||
*
|
||||
* @return a list of languages
|
||||
* @throws IOException if an i/o error occurs
|
||||
* @throws UnsuccessfulRequestException if the http request fails
|
||||
*/
|
||||
public List<LanguageInfo> getAvailableLanguages() throws IOException, UnsuccessfulRequestException {
|
||||
return getTranslationsMetadata().languages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules a refresh of the current translations if necessary.
|
||||
*/
|
||||
public void scheduleRefresh() {
|
||||
if (!this.plugin.getConfiguration().get(ConfigKeys.AUTO_INSTALL_TRANSLATIONS)) {
|
||||
return; // skip
|
||||
}
|
||||
|
||||
this.plugin.getBootstrap().getScheduler().executeAsync(() -> {
|
||||
try {
|
||||
refresh();
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void refresh() throws Exception {
|
||||
Path translationsDirectory = this.plugin.getTranslationManager().getTranslationsDirectory();
|
||||
try {
|
||||
MoreFiles.createDirectoriesIfNotExists(translationsDirectory);
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
long lastRefresh = 0L;
|
||||
|
||||
Path repoStatusFile = translationsDirectory.resolve("repository.json");
|
||||
if (Files.exists(repoStatusFile)) {
|
||||
try (BufferedReader reader = Files.newBufferedReader(repoStatusFile, StandardCharsets.UTF_8)) {
|
||||
JsonObject status = GsonProvider.normal().fromJson(reader, JsonObject.class);
|
||||
if (status.has("lastRefresh")) {
|
||||
lastRefresh = status.get("lastRefresh").getAsLong();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
long timeSinceLastRefresh = System.currentTimeMillis() - lastRefresh;
|
||||
if (timeSinceLastRefresh <= CACHE_MAX_AGE) {
|
||||
return;
|
||||
}
|
||||
|
||||
MetadataResponse metadata = getTranslationsMetadata();
|
||||
|
||||
if (timeSinceLastRefresh <= metadata.cacheMaxAge) {
|
||||
return;
|
||||
}
|
||||
|
||||
// perform a refresh!
|
||||
downloadAndInstallTranslations(metadata.languages, null, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Downloads and installs translations for the given languages.
|
||||
*
|
||||
* @param languages the languages to install translations for
|
||||
* @param sender the sender to report progress to
|
||||
* @param updateStatus if the status file should be updated
|
||||
*/
|
||||
public void downloadAndInstallTranslations(List<LanguageInfo> languages, @Nullable Sender sender, boolean updateStatus) {
|
||||
TranslationManager manager = this.plugin.getTranslationManager();
|
||||
Path translationsDirectory = manager.getTranslationsDirectory();
|
||||
|
||||
try {
|
||||
MoreFiles.createDirectoriesIfNotExists(translationsDirectory);
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
for (LanguageInfo language : languages) {
|
||||
if (sender != null) {
|
||||
Message.TRANSLATIONS_INSTALLING_SPECIFIC.send(sender, language.locale().toString());
|
||||
}
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.header("User-Agent", this.plugin.getBytebin().getUserAgent())
|
||||
.url(TRANSLATIONS_DOWNLOAD_ENDPOINT + language.id())
|
||||
.build();
|
||||
|
||||
Path file = translationsDirectory.resolve(language.locale().toString() + ".properties");
|
||||
|
||||
try (Response response = this.plugin.getBytebin().makeHttpRequest(request)) {
|
||||
try (ResponseBody responseBody = response.body()) {
|
||||
if (responseBody == null) {
|
||||
throw new IOException("No response");
|
||||
}
|
||||
|
||||
try (InputStream inputStream = new LimitedInputStream(responseBody.byteStream(), MAX_BUNDLE_SIZE)) {
|
||||
Files.copy(inputStream, file, StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
}
|
||||
} catch (UnsuccessfulRequestException | IOException e) {
|
||||
if (sender != null) {
|
||||
Message.TRANSLATIONS_DOWNLOAD_ERROR.send(sender, language.locale().toString());
|
||||
this.plugin.getLogger().warn("Unable to download translations", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (updateStatus) {
|
||||
// update status file
|
||||
Path repoStatusFile = translationsDirectory.resolve("repository.json");
|
||||
try (BufferedWriter writer = Files.newBufferedWriter(repoStatusFile, StandardCharsets.UTF_8)) {
|
||||
JsonObject status = new JsonObject();
|
||||
status.add("lastRefresh", new JsonPrimitive(System.currentTimeMillis()));
|
||||
GsonProvider.prettyPrinting().toJson(status, writer);
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
this.plugin.getTranslationManager().reload();
|
||||
}
|
||||
|
||||
private MetadataResponse getTranslationsMetadata() throws IOException, UnsuccessfulRequestException {
|
||||
Request request = new Request.Builder()
|
||||
.header("User-Agent", this.plugin.getBytebin().getUserAgent())
|
||||
.url(TRANSLATIONS_INFO_ENDPOINT)
|
||||
.build();
|
||||
|
||||
JsonObject jsonResponse;
|
||||
try (Response response = this.plugin.getBytebin().makeHttpRequest(request)) {
|
||||
try (ResponseBody responseBody = response.body()) {
|
||||
if (responseBody == null) {
|
||||
throw new RuntimeException("No response");
|
||||
}
|
||||
|
||||
try (InputStream inputStream = new LimitedInputStream(responseBody.byteStream(), MAX_BUNDLE_SIZE)) {
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
|
||||
jsonResponse = GsonProvider.normal().fromJson(reader, JsonObject.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<LanguageInfo> languages = new ArrayList<>();
|
||||
for (Map.Entry<String, JsonElement> language : jsonResponse.get("languages").getAsJsonObject().entrySet()) {
|
||||
languages.add(new LanguageInfo(language.getKey(), language.getValue().getAsJsonObject()));
|
||||
}
|
||||
languages.removeIf(language -> language.progress() <= 0);
|
||||
|
||||
if (languages.size() >= 100) {
|
||||
// just a precaution: if more than 100 languages have been
|
||||
// returned then the metadata server is doing something silly
|
||||
throw new IOException("More than 100 languages - cancelling download");
|
||||
}
|
||||
|
||||
long cacheMaxAge = jsonResponse.get("cacheMaxAge").getAsLong();
|
||||
|
||||
return new MetadataResponse(cacheMaxAge, languages);
|
||||
}
|
||||
|
||||
private static final class MetadataResponse {
|
||||
private final long cacheMaxAge;
|
||||
private final List<LanguageInfo> languages;
|
||||
|
||||
MetadataResponse(long cacheMaxAge, List<LanguageInfo> languages) {
|
||||
this.cacheMaxAge = cacheMaxAge;
|
||||
this.languages = languages;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class LanguageInfo {
|
||||
private final String id;
|
||||
private final String name;
|
||||
private final Locale locale;
|
||||
private final int progress;
|
||||
private final List<String> contributors;
|
||||
|
||||
LanguageInfo(String id, JsonObject data) {
|
||||
this.id = id;
|
||||
this.name = data.get("name").getAsString();
|
||||
this.locale = Objects.requireNonNull(TranslationManager.parseLocale(data.get("localeTag").getAsString()));
|
||||
this.progress = data.get("progress").getAsInt();
|
||||
this.contributors = new ArrayList<>();
|
||||
for (JsonElement contributor : data.get("contributors").getAsJsonArray()) {
|
||||
this.contributors.add(contributor.getAsJsonObject().get("name").getAsString());
|
||||
}
|
||||
}
|
||||
|
||||
public String id() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public Locale locale() {
|
||||
return this.locale;
|
||||
}
|
||||
|
||||
public int progress() {
|
||||
return this.progress;
|
||||
}
|
||||
|
||||
public List<String> contributors() {
|
||||
return this.contributors;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class LimitedInputStream extends FilterInputStream implements Closeable {
|
||||
private final long limit;
|
||||
private long count;
|
||||
|
||||
public LimitedInputStream(InputStream inputStream, long limit) {
|
||||
super(inputStream);
|
||||
this.limit = limit;
|
||||
}
|
||||
|
||||
private void checkLimit() throws IOException {
|
||||
if (this.count > this.limit) {
|
||||
throw new IOException("Limit exceeded");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
int res = super.read();
|
||||
if (res != -1) {
|
||||
this.count++;
|
||||
checkLimit();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b, int off, int len) throws IOException {
|
||||
int res = super.read(b, off, len);
|
||||
if (res > 0) {
|
||||
this.count += res;
|
||||
checkLimit();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
super.close();
|
||||
}
|
||||
}
|
||||
}
|
@@ -43,6 +43,7 @@ import me.lucko.luckperms.common.http.BytebinClient;
|
||||
import me.lucko.luckperms.common.inheritance.InheritanceGraphFactory;
|
||||
import me.lucko.luckperms.common.locale.Message;
|
||||
import me.lucko.luckperms.common.locale.TranslationManager;
|
||||
import me.lucko.luckperms.common.locale.TranslationRepository;
|
||||
import me.lucko.luckperms.common.messaging.InternalMessagingService;
|
||||
import me.lucko.luckperms.common.messaging.MessagingFactory;
|
||||
import me.lucko.luckperms.common.plugin.logging.PluginLogger;
|
||||
@@ -79,6 +80,7 @@ public abstract class AbstractLuckPermsPlugin implements LuckPermsPlugin {
|
||||
private LogDispatcher logDispatcher;
|
||||
private LuckPermsConfiguration configuration;
|
||||
private BytebinClient bytebin;
|
||||
private TranslationRepository translationRepository;
|
||||
private FileWatcher fileWatcher = null;
|
||||
private Storage storage;
|
||||
private InternalMessagingService messagingService = null;
|
||||
@@ -124,6 +126,10 @@ public abstract class AbstractLuckPermsPlugin implements LuckPermsPlugin {
|
||||
|
||||
this.bytebin = new BytebinClient(httpClient, getConfiguration().get(ConfigKeys.BYTEBIN_URL), "luckperms");
|
||||
|
||||
// init translation repo and update bundle files
|
||||
this.translationRepository = new TranslationRepository(this);
|
||||
this.translationRepository.scheduleRefresh();
|
||||
|
||||
// now the configuration is loaded, we can create a storage factory and load initial dependencies
|
||||
StorageFactory storageFactory = new StorageFactory(this);
|
||||
Set<StorageType> storageTypes = storageFactory.getRequiredTypes();
|
||||
@@ -320,6 +326,11 @@ public abstract class AbstractLuckPermsPlugin implements LuckPermsPlugin {
|
||||
return this.bytebin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TranslationRepository getTranslationRepository() {
|
||||
return this.translationRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<FileWatcher> getFileWatcher() {
|
||||
return Optional.ofNullable(this.fileWatcher);
|
||||
|
@@ -38,6 +38,7 @@ import me.lucko.luckperms.common.extension.SimpleExtensionManager;
|
||||
import me.lucko.luckperms.common.http.BytebinClient;
|
||||
import me.lucko.luckperms.common.inheritance.InheritanceGraphFactory;
|
||||
import me.lucko.luckperms.common.locale.TranslationManager;
|
||||
import me.lucko.luckperms.common.locale.TranslationRepository;
|
||||
import me.lucko.luckperms.common.messaging.InternalMessagingService;
|
||||
import me.lucko.luckperms.common.model.Group;
|
||||
import me.lucko.luckperms.common.model.Track;
|
||||
@@ -175,6 +176,13 @@ public interface LuckPermsPlugin {
|
||||
*/
|
||||
TranslationManager getTranslationManager();
|
||||
|
||||
/**
|
||||
* Gets the translation repository
|
||||
*
|
||||
* @return the translation repository
|
||||
*/
|
||||
TranslationRepository getTranslationRepository();
|
||||
|
||||
/**
|
||||
* Gets the dependency manager for the plugin
|
||||
*
|
||||
|
@@ -305,6 +305,9 @@ log-notify: true
|
||||
log-notify-filtered-descriptions:
|
||||
# - "parent add example"
|
||||
|
||||
# If LuckPerms should automatically install translation bundles and periodically update them.
|
||||
auto-install-translations: true
|
||||
|
||||
# Defines the options for prefix and suffix stacking.
|
||||
#
|
||||
# - The feature allows you to display multiple prefixes or suffixes alongside a players username in
|
||||
|
@@ -315,6 +315,9 @@ log-notify-filtered-descriptions = [
|
||||
# "parent add example"
|
||||
]
|
||||
|
||||
# If LuckPerms should automatically install translation bundles and periodically update them.
|
||||
auto-install-translations = true
|
||||
|
||||
# Defines the options for prefix and suffix stacking.
|
||||
#
|
||||
# - The feature allows you to display multiple prefixes or suffixes alongside a players username in
|
||||
|
@@ -309,6 +309,9 @@ log-notify: true
|
||||
log-notify-filtered-descriptions:
|
||||
# - "parent add example"
|
||||
|
||||
# If LuckPerms should automatically install translation bundles and periodically update them.
|
||||
auto-install-translations: true
|
||||
|
||||
# Defines the options for prefix and suffix stacking.
|
||||
#
|
||||
# - The feature allows you to display multiple prefixes or suffixes alongside a players username in
|
||||
|
Reference in New Issue
Block a user