Skip to content

Commit

Permalink
Merge remote-tracking branch 'neoforged/1.21.x' into ui
Browse files Browse the repository at this point in the history
  • Loading branch information
HenryLoenwind committed Jul 1, 2024
2 parents daaac9c + 001f9ff commit 68adcce
Show file tree
Hide file tree
Showing 8 changed files with 348 additions and 13 deletions.
Original file line number Diff line number Diff line change
@@ -1,14 +1,60 @@
--- a/net/minecraft/client/resources/language/ClientLanguage.java
+++ b/net/minecraft/client/resources/language/ClientLanguage.java
@@ -34,6 +_,7 @@
@@ -22,36 +_,50 @@
public class ClientLanguage extends Language {
private static final Logger LOGGER = LogUtils.getLogger();
private final Map<String, String> storage;
+ private final Map<String, net.minecraft.network.chat.Component> componentStorage;
private final boolean defaultRightToLeft;

+ @Deprecated
private ClientLanguage(Map<String, String> p_118914_, boolean p_118915_) {
+ this(p_118914_, p_118915_, Map.of());
+ }
+
+ private ClientLanguage(Map<String, String> p_118914_, boolean p_118915_, Map<String, net.minecraft.network.chat.Component> componentStorage) {
this.storage = p_118914_;
this.defaultRightToLeft = p_118915_;
+ this.componentStorage = componentStorage;
}

public static ClientLanguage loadFrom(ResourceManager p_265765_, List<String> p_265743_, boolean p_265470_) {
Map<String, String> map = Maps.newHashMap();
+ Map<String, net.minecraft.network.chat.Component> componentMap = Maps.newHashMap();

for (String s : p_265743_) {
String s1 = String.format(Locale.ROOT, "lang/%s.json", s);
+ map.putAll(net.neoforged.fml.i18n.I18nManager.loadTranslations(s));

for (String s2 : p_265765_.getNamespaces()) {
try {
@@ -76,5 +_,10 @@
ResourceLocation resourcelocation = ResourceLocation.fromNamespaceAndPath(s2, s1);
- appendFrom(s, p_265765_.getResourceStack(resourcelocation), map);
+ appendFrom(s, p_265765_.getResourceStack(resourcelocation), map, componentMap);
} catch (Exception exception) {
LOGGER.warn("Skipped language file: {}:{} ({})", s2, s1, exception.toString());
}
}
}

- return new ClientLanguage(ImmutableMap.copyOf(map), p_265470_);
+ return new ClientLanguage(ImmutableMap.copyOf(map), p_265470_, ImmutableMap.copyOf(componentMap));
}

+ @Deprecated
private static void appendFrom(String p_235036_, List<Resource> p_235037_, Map<String, String> p_235038_) {
+ appendFrom(p_235036_, p_235037_, p_235038_, new java.util.HashMap<>());
+ }
+
+ private static void appendFrom(String p_235036_, List<Resource> p_235037_, Map<String, String> p_235038_, Map<String, net.minecraft.network.chat.Component> componentMap) {
for (Resource resource : p_235037_) {
try (InputStream inputstream = resource.open()) {
- Language.loadFromJson(inputstream, p_235038_::put);
+ Language.loadFromJson(inputstream, p_235038_::put, componentMap::put);
} catch (IOException ioexception) {
LOGGER.warn("Failed to load translations for {} from pack {}", p_235036_, resource.sourcePackId(), ioexception);
}
@@ -76,5 +_,15 @@
@Override
public FormattedCharSequence getVisualOrder(FormattedText p_118925_) {
return FormattedBidiReorder.reorder(p_118925_, this.defaultRightToLeft);
Expand All @@ -17,5 +63,10 @@
+ @Override
+ public Map<String, String> getLanguageData() {
+ return storage;
+ }
+
+ @Override
+ public @org.jetbrains.annotations.Nullable net.minecraft.network.chat.Component getComponent(String key) {
+ return componentStorage.get(key);
}
}
62 changes: 55 additions & 7 deletions patches/net/minecraft/locale/Language.java.patch
Original file line number Diff line number Diff line change
@@ -1,34 +1,82 @@
--- a/net/minecraft/locale/Language.java
+++ b/net/minecraft/locale/Language.java
@@ -37,7 +_,8 @@
@@ -36,8 +_,10 @@
private static Language loadDefault() {
Builder<String, String> builder = ImmutableMap.builder();
BiConsumer<String, String> biconsumer = builder::put;
parseTranslations(biconsumer, "/assets/minecraft/lang/en_us.json");
- parseTranslations(biconsumer, "/assets/minecraft/lang/en_us.json");
- final Map<String, String> map = builder.build();
+ Map<String, net.minecraft.network.chat.Component> componentMap = new java.util.HashMap<>();
+ parseTranslations(biconsumer, componentMap::put, "/assets/minecraft/lang/en_us.json");
+ final Map<String, String> map = new java.util.HashMap<>(builder.build());
+ net.neoforged.neoforge.server.LanguageHook.captureLanguageMap(map);
+ net.neoforged.neoforge.server.LanguageHook.captureLanguageMap(map, componentMap);
return new Language() {
@Override
public String getOrDefault(String p_128127_, String p_265421_) {
@@ -64,6 +_,11 @@
@@ -64,21 +_,51 @@
)
.isPresent();
}
+
+ @Override
+ public Map<String, String> getLanguageData() {
+ return map;
+ }
+
+ @Override
+ public @org.jetbrains.annotations.Nullable net.minecraft.network.chat.Component getComponent(String key) {
+ return componentMap.get(key);
+ }
};
}

@@ -91,6 +_,9 @@
+ @Deprecated
private static void parseTranslations(BiConsumer<String, String> p_282031_, String p_283638_) {
+ parseTranslations(p_282031_, (key, value) -> {}, p_283638_);
+ }
+
+ private static void parseTranslations(BiConsumer<String, String> p_282031_, BiConsumer<String, net.minecraft.network.chat.Component> componentConsumer, String p_283638_) {
try (InputStream inputstream = Language.class.getResourceAsStream(p_283638_)) {
- loadFromJson(inputstream, p_282031_);
+ loadFromJson(inputstream, p_282031_, componentConsumer);
} catch (JsonParseException | IOException ioexception) {
LOGGER.error("Couldn't read strings from {}", p_283638_, ioexception);
}
}

public static void loadFromJson(InputStream p_128109_, BiConsumer<String, String> p_128110_) {
+ loadFromJson(p_128109_, p_128110_, (key, value) -> {});
+ }
+
+ public static void loadFromJson(InputStream p_128109_, BiConsumer<String, String> p_128110_, BiConsumer<String, net.minecraft.network.chat.Component> componentConsumer) {
JsonObject jsonobject = GSON.fromJson(new InputStreamReader(p_128109_, StandardCharsets.UTF_8), JsonObject.class);

for (Entry<String, JsonElement> entry : jsonobject.entrySet()) {
+ if (entry.getValue().isJsonArray()) {
+ var component = net.minecraft.network.chat.ComponentSerialization.CODEC
+ .parse(com.mojang.serialization.JsonOps.INSTANCE, entry.getValue())
+ .getOrThrow(msg -> new com.google.gson.JsonParseException("Error parsing translation for " + entry.getKey() + ": " + msg));
+
+ p_128110_.accept(entry.getKey(), component.getString());
+ componentConsumer.accept(entry.getKey(), component);
+
+ continue;
+ }
+
String s = UNSUPPORTED_FORMAT_PATTERN.matcher(GsonHelper.convertToString(entry.getValue(), entry.getKey())).replaceAll("%$1s");
p_128110_.accept(entry.getKey(), s);
}
@@ -90,6 +_,13 @@

public static void inject(Language p_128115_) {
instance = p_128115_;
}
+ }
+
+ // FORGE START
+ public Map<String, String> getLanguageData() { return ImmutableMap.of(); }
+
+ public @org.jetbrains.annotations.Nullable net.minecraft.network.chat.Component getComponent(String key) {
+ return null;
}

public String getOrDefault(String p_128111_) {
return this.getOrDefault(p_128111_, p_128111_);
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
--- a/net/minecraft/network/chat/ComponentSerialization.java
+++ b/net/minecraft/network/chat/ComponentSerialization.java
@@ -104,7 +_,7 @@

private static Codec<Component> createCodec(Codec<Component> p_304554_) {
ComponentContents.Type<?>[] type = new ComponentContents.Type[]{
- PlainTextContents.TYPE, TranslatableContents.TYPE, KeybindContents.TYPE, ScoreContents.TYPE, SelectorContents.TYPE, NbtContents.TYPE
+ PlainTextContents.TYPE, TranslatableContents.TYPE, KeybindContents.TYPE, ScoreContents.TYPE, SelectorContents.TYPE, NbtContents.TYPE, net.neoforged.neoforge.common.util.InsertingContents.TYPE
};
MapCodec<ComponentContents> mapcodec = createLegacyComponentMatcher(type, ComponentContents.Type::codec, ComponentContents::type, "type");
Codec<Component> codec = RecordCodecBuilder.create(
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,63 @@
+ }
}

@Override
@@ -92,6 +_,13 @@
Language language = Language.getInstance();
if (language != this.decomposedWith) {
this.decomposedWith = language;
+
+ Component langComponent = language.getComponent(this.key);
+ if (langComponent != null) {
+ this.decomposedParts = ImmutableList.of(langComponent);
+ return;
+ }
+
String s = this.fallback != null ? language.getOrDefault(this.key, this.fallback) : language.getOrDefault(this.key);

try {
@@ -170,6 +_,12 @@
public <T> Optional<T> visit(FormattedText.StyledContentConsumer<T> p_237521_, Style p_237522_) {
this.decompose();

+ if (!net.neoforged.neoforge.common.util.InsertingContents.pushTranslation(this)) {
+ // Reference cycle.
+ return Optional.empty();
+ }
+
+ try {
for (FormattedText formattedtext : this.decomposedParts) {
Optional<T> optional = formattedtext.visit(p_237521_, p_237522_);
if (optional.isPresent()) {
@@ -178,12 +_,21 @@
}

return Optional.empty();
+ } finally {
+ net.neoforged.neoforge.common.util.InsertingContents.popTranslation();
+ }
}

@Override
public <T> Optional<T> visit(FormattedText.ContentConsumer<T> p_237519_) {
this.decompose();

+ if (!net.neoforged.neoforge.common.util.InsertingContents.pushTranslation(this)) {
+ // Reference cycle.
+ return Optional.empty();
+ }
+
+ try {
for (FormattedText formattedtext : this.decomposedParts) {
Optional<T> optional = formattedtext.visit(p_237519_);
if (optional.isPresent()) {
@@ -192,6 +_,9 @@
}

return Optional.empty();
+ } finally {
+ net.neoforged.neoforge.common.util.InsertingContents.popTranslation();
+ }
}

@Override
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* Copyright (c) NeoForged and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/

package net.neoforged.neoforge.common.util;

import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Optional;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.ComponentContents;
import net.minecraft.network.chat.FormattedText;
import net.minecraft.network.chat.Style;
import net.minecraft.network.chat.contents.TranslatableContents;
import net.minecraft.util.ExtraCodecs;
import org.jetbrains.annotations.ApiStatus;

@ApiStatus.Internal
public record InsertingContents(int index) implements ComponentContents {
public static final MapCodec<InsertingContents> CODEC = RecordCodecBuilder.mapCodec(i -> i.group(
ExtraCodecs.NON_NEGATIVE_INT.fieldOf("index").forGetter(InsertingContents::index))
.apply(i, InsertingContents::new));

public static final ComponentContents.Type<InsertingContents> TYPE = new ComponentContents.Type<>(CODEC, "neoforge:inserting");

private static final ThreadLocal<Deque<TranslatableContents>> TRANSLATION_STACK = ThreadLocal.withInitial(ArrayDeque::new);

@ApiStatus.Internal
public static boolean pushTranslation(TranslatableContents contents) {
for (TranslatableContents other : TRANSLATION_STACK.get()) {
if (contents == other) {
return false;
}
}

TRANSLATION_STACK.get().push(contents);
return true;
}

@ApiStatus.Internal
public static void popTranslation() {
TRANSLATION_STACK.get().pop();
}

@Override
public <T> Optional<T> visit(FormattedText.ContentConsumer<T> visitor) {
var translation = TRANSLATION_STACK.get().peek();

if (translation == null || translation.getArgs().length <= index)
return visitor.accept("%" + (index + 1) + "$s");

Object arg = translation.getArgs()[index];

if (arg instanceof Component component) {
return component.visit(visitor);
} else {
return visitor.accept(arg.toString());
}
}

@Override
public <T> Optional<T> visit(FormattedText.StyledContentConsumer<T> visitor, Style style) {
var translation = TRANSLATION_STACK.get().peek();

if (translation == null || translation.getArgs().length <= index)
return visitor.accept(style, "%" + (index + 1) + "$s");

Object arg = translation.getArgs()[index];

if (arg instanceof Component component) {
return component.visit(visitor, style);
} else {
return visitor.accept(style, arg.toString());
}
}

@Override
public Type<?> type() {
return TYPE;
}
}
17 changes: 13 additions & 4 deletions src/main/java/net/neoforged/neoforge/server/LanguageHook.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import java.util.Locale;
import java.util.Map;
import net.minecraft.locale.Language;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.packs.PackType;
Expand All @@ -29,13 +30,19 @@
public class LanguageHook {
private static final Logger LOGGER = LogManager.getLogger();
private static Map<String, String> defaultLanguageTable = new HashMap<>();
private static Map<String, Component> defaultLanguageComponentTable = new HashMap<>();
private static Map<String, String> modTable = new HashMap<>();
private static Map<String, Component> modComponentTable = new HashMap<>();

public static void captureLanguageMap(Map<String, String> table) {
public static void captureLanguageMap(Map<String, String> table, Map<String, Component> componentTable) {
defaultLanguageTable = table;
defaultLanguageComponentTable = componentTable;
if (!modTable.isEmpty()) {
defaultLanguageTable.putAll(modTable);
}
if (!modComponentTable.isEmpty()) {
defaultLanguageComponentTable.putAll(modComponentTable);
}
}

private static void loadLanguage(String langName, MinecraftServer server) {
Expand All @@ -55,7 +62,7 @@ private static void loadLanguage(String langName, MinecraftServer server) {
ResourceLocation langResource = ResourceLocation.fromNamespaceAndPath(namespace, langFile);
for (Resource resource : clientResources.getResourceStack(langResource)) {
try (InputStream stream = resource.open()) {
Language.loadFromJson(stream, (key, value) -> modTable.put(key, value));
Language.loadFromJson(stream, (key, value) -> modTable.put(key, value), (key, value) -> modComponentTable.put(key, value));
}
}
loaded++;
Expand All @@ -72,14 +79,14 @@ public static void loadBuiltinLanguages() {

try (InputStream input = classLoader.getResourceAsStream("assets/minecraft/lang/en_us.json")) {
assert input != null;
Language.loadFromJson(input, (key, value) -> modTable.put(key, value));
Language.loadFromJson(input, (key, value) -> modTable.put(key, value), (key, value) -> modComponentTable.put(key, value));
} catch (Exception exception) {
LOGGER.warn("Failed to load built-in language file for Minecraft", exception);
}

try (InputStream input = classLoader.getResourceAsStream("assets/neoforge/lang/en_us.json")) {
assert input != null;
Language.loadFromJson(input, (key, value) -> modTable.put(key, value));
Language.loadFromJson(input, (key, value) -> modTable.put(key, value), (key, value) -> modComponentTable.put(key, value));
} catch (Exception exception) {
LOGGER.warn("Failed to load built-in language file for NeoForge", exception);
}
Expand All @@ -92,8 +99,10 @@ public static void loadBuiltinLanguages() {

static void loadModLanguages(MinecraftServer server) {
modTable = new HashMap<>(5000);
modComponentTable = new HashMap<>();
loadLanguage("en_us", server);
defaultLanguageTable.putAll(modTable);
defaultLanguageComponentTable.putAll(modComponentTable);
I18nManager.injectTranslations(modTable);
}
}
Loading

0 comments on commit 68adcce

Please sign in to comment.