Settings rework and encapsulation (#1330)

* Settings rework and encapsulation

* Settings overhaul 3

Move everything in the new system to a new API package

Require rules using the new system to specify descriptions in their translation files

Implement temporary system on top of current translations to allow that to work properly

* Fix getRules fallback

* Final touches to settings refactor

* Mention that set shouldn't throw and remove comment

* Change translation keys to unify with translation PR

* Deprecate printAllRulesToLog to allow using any PrintStream

* Remove restriction of CarpetRules being Comparable

And fix overreaction in a deprecation message

* Bring back user input to rule observers

* Make Validator deprecation warning not spam on use

* Remove unneeded abstract methods in CarpetRule already inherited from CarpetRule

They literally do nothing, don't even force them to be implemented, and may be confusing as to why they're there or as if they are needed to be implemented

* Fix legacy SettingsManager field not being assigned correctly

* Finish fixing conflicts from future merge

* Actually fix remaining conflicts from future merge (missing imports)

* Import the newer rule in SettingsManager

* Refactor Validators

* Don't spam deprecation warnings on custom managers

* Get out the var

* Fix missing warning in old rule observers

* Update src/main/java/carpet/api/settings/Rule.java

* Remove `@ApiStatus.Experimental` annotations

* Fix incorrect `@deprecated` javadoc tags

By removing them given the class is deprecated anyway and else there's too much noise

* Add missing static import

* Remove TypedField and use a regular field

I liked that class tbh, but it's true that it wasn't really needed

* Move `field` assignment out of for removal

* Fix not following contract of `type()` returning boxed value

Previously handled by TypedField

* Fix few incorrect translation keys

* Remove resaving of comments when saving config files

Comments ignoring is still a thing when reading, so `locked` configs for example will keep comments

* Condense rule load messages in one

* Only print loaded settings message when at least one setting was changed

* Fix legacy validator detector

* Tweak and add more context to response to invalid values

* Fix strict validator not actually erroring on invalid input
This commit is contained in:
altrisi authored and GitHub committed 2022-06-27 13:12:15 +02:00
1 parent f5a92ebb8e
commit 0a972d6c56
44 files changed
+2687 -1616

No files matched your search

+66 -30
View File
@@ -10,33 +10,38 @@ import org.apache.commons.io.IOUtils;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import net.minecraft.commands.CommandSourceStack;
public class Translations
{
private static Map<String, String> translationMap;
private static Map<String, String> translationMap = Collections.emptyMap();
public static String tr(String key)
{
return translationMap == null ? key : translationMap.getOrDefault(key, key);
return translationMap.getOrDefault(key, key);
}
public static String trOrNull(String key)
{
return translationMap.get(key);
}
public static String tr(String key, String str)
{
return translationMap == null ? str : translationMap.getOrDefault(key, str);
return translationMap.getOrDefault(key, str);
}
public static boolean hasTranslations()
{
return translationMap != null;
return !translationMap.isEmpty();
}
public static boolean hasTranslation(String key)
{
return translationMap != null && translationMap.containsKey(key);
return translationMap.containsKey(key);
}
public static Map<String, String> getTranslationFromResourcePath(String path)
@@ -45,44 +50,59 @@ public class Translations
try
{
dataJSON = IOUtils.toString(
Objects.requireNonNull(Translations.class.getClassLoader().getResourceAsStream(String.format("assets/carpet/lang/%s.json", CarpetSettings.language))),
Objects.requireNonNull(Translations.class.getClassLoader().getResourceAsStream(path)),
StandardCharsets.UTF_8);
} catch (NullPointerException | IOException e) {
return null;
return Map.of();
}
Gson gson = new GsonBuilder().enableComplexMapKeySerialization().create();
Gson gson = new GsonBuilder().setLenient().create();
return gson.fromJson(dataJSON, new TypeToken<Map<String, String>>() {}.getType());
}
public static void updateLanguage(CommandSourceStack source)
public static void updateLanguage()
{
if (CarpetSettings.language.equalsIgnoreCase("none"))
{
translationMap = null;
return;
}
Map<String, String> translations = new HashMap<>();
Map<String, String> trans = getTranslationFromResourcePath(String.format("assets/carpet/lang/%s.json", CarpetSettings.language));
if (trans != null) trans.forEach(translations::put);
translations.putAll(getTranslationFromResourcePath(String.format("assets/carpet/lang/%s.json", CarpetSettings.language)));
for (CarpetExtension ext : CarpetServer.extensions)
{
Map<String, String> extMappings = ext.canHasTranslations(CarpetSettings.language);
if (extMappings != null)
{
extMappings.forEach((key, value) ->
{
if (!translations.containsKey(key)) translations.put(key, value);
});
if (extMappings == null) continue; // would be nice to get rid of this, but too many extensions return null where they don't know they do
boolean warned = false;
for (var entry : extMappings.entrySet()) {
var key = entry.getKey();
// Migrate the old format
if (!key.startsWith("carpet.")) {
if (key.startsWith("rule.")) {
// default to carpet's settings manager. Custom managers are really uncommon and the known ones don't provide translations anyway
key = TranslationKeys.BASE_RULE_NAMESPACE.formatted("carpet") + key.substring(5);
} else if (key.startsWith("category.")) {
key = TranslationKeys.CATEGORY_PATTERN.formatted("carpet", key.substring(9));
}
if (!warned && key != entry.getKey()) {
CarpetSettings.LOG.warn("""
Found outdated translation keys in extension '%s'!
These won't be supported in a later Carpet version!
Carpet will now try to map them to the correct keys in a best-effort basis""".formatted(ext.getClass().getName()));
warned = true;
}
}
translations.putIfAbsent(key, entry.getValue());
}
}
translations.entrySet().removeIf(e -> e.getKey().startsWith("//"));
if (translations.isEmpty())
{
translationMap = null;
return;
}
translations.keySet().removeIf(e -> {
if (e.startsWith("//")) {
CarpetSettings.LOG.warn("""
Found translation key starting with // while preparing translations!
Doing this is deprecated and may cause issues in later versions! Consider settings GSON to "lenient" mode and
using regular comments instead!
Translation key is '%s'""".formatted(e));
return true;
} else
return false;
});
// Remove after deprecated settings api is removed
addFallbacksTo(translations);
translationMap = translations;
}
@@ -91,4 +111,20 @@ public class Translations
// will put some validations for availble languages at some point
return true;
}
// fallbacks for old rules that don't define rule descriptions or stuff in language files yet
// to be removed when old settings system is removed and translation refactor is finished
private static final Map<String, String> FALLBACKS = new HashMap<>();
/**
* @deprecated if you compile against this method I'll steal your kneecaps
*/
@Deprecated(forRemoval = true)
public static void registerFallbackTranslation(String key, String description) {
FALLBACKS.put(key, description);
}
private static void addFallbacksTo(Map<String, String> translationMap) {
FALLBACKS.forEach(translationMap::putIfAbsent);
}
}