fix: implement OverlayMap to store FallbackI18n without evaluating lower map early
This commit is contained in:
parent
4943127ecc
commit
2c66bc4146
|
@ -1,7 +1,7 @@
|
||||||
package io.gitlab.jfronny.respackopts.mixin;
|
package io.gitlab.jfronny.respackopts.mixin;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import io.gitlab.jfronny.respackopts.util.FallbackI18n;
|
import io.gitlab.jfronny.respackopts.util.FallbackI18n;
|
||||||
|
import io.gitlab.jfronny.respackopts.util.OverlayMap;
|
||||||
import net.minecraft.client.resource.language.LanguageManager;
|
import net.minecraft.client.resource.language.LanguageManager;
|
||||||
import net.minecraft.client.resource.language.TranslationStorage;
|
import net.minecraft.client.resource.language.TranslationStorage;
|
||||||
import net.minecraft.resource.ResourceManager;
|
import net.minecraft.resource.ResourceManager;
|
||||||
|
@ -18,8 +18,8 @@ public class LanguageManagerMixin {
|
||||||
@Inject(method = "reload(Lnet/minecraft/resource/ResourceManager;)V", at = @At("TAIL"), locals = LocalCapture.CAPTURE_FAILEXCEPTION)
|
@Inject(method = "reload(Lnet/minecraft/resource/ResourceManager;)V", at = @At("TAIL"), locals = LocalCapture.CAPTURE_FAILEXCEPTION)
|
||||||
private void rpo$appendTranslations(ResourceManager manager, CallbackInfo ci, List<String> list, boolean bl, TranslationStorage translationStorage) {
|
private void rpo$appendTranslations(ResourceManager manager, CallbackInfo ci, List<String> list, boolean bl, TranslationStorage translationStorage) {
|
||||||
TranslationStorageAccessor storage = (TranslationStorageAccessor) translationStorage;
|
TranslationStorageAccessor storage = (TranslationStorageAccessor) translationStorage;
|
||||||
Map<String, String> map = new HashMap<>(storage.getTranslations());
|
Map<String, String> map = new HashMap<>();
|
||||||
FallbackI18n.insertInto(map);
|
FallbackI18n.insertInto(map);
|
||||||
storage.setTranslations(ImmutableMap.copyOf(map));
|
storage.setTranslations(new OverlayMap<>(storage.getTranslations(), map));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,169 @@
|
||||||
|
package io.gitlab.jfronny.respackopts.util;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public final class OverlayMap<K, V> extends AbstractMap<K, V> {
|
||||||
|
private final Map<K, V> overlay;
|
||||||
|
private final Map<K, V> lower;
|
||||||
|
private final Set<K> masked = new HashSet<>();
|
||||||
|
|
||||||
|
public OverlayMap(Map<K, V> overlay, Map<K, V> lower) {
|
||||||
|
this.overlay = overlay;
|
||||||
|
this.lower = lower;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return overlay.size() + (int) lower.keySet().stream()
|
||||||
|
.filter(s -> !overlay.containsKey(s) && !masked.contains(s))
|
||||||
|
.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Stream<K> streamKeys() {
|
||||||
|
return Stream.concat(
|
||||||
|
overlay.keySet().stream(),
|
||||||
|
lower.keySet().stream()
|
||||||
|
.filter(s -> !overlay.containsKey(s) && !masked.contains(s))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return overlay.isEmpty() && (masked.size() >= lower.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsKey(Object key) {
|
||||||
|
return overlay.containsKey(key) || (lower.containsKey(key) && !masked.contains(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsValue(Object value) {
|
||||||
|
return overlay.containsValue(value) || lower.entrySet()
|
||||||
|
.stream()
|
||||||
|
.filter(s -> Objects.equals(s.getValue(), value))
|
||||||
|
.anyMatch(s -> !masked.contains(s.getKey()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V get(Object key) {
|
||||||
|
V result = overlay.get(key);
|
||||||
|
if (result == null && !masked.contains(key)) result = lower.get(key);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public V put(K key, V value) {
|
||||||
|
V result = overlay.put(key, value);
|
||||||
|
V low = lower.get(key);
|
||||||
|
if (low != null && masked.add(key) && result == null) {
|
||||||
|
result = low;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V remove(Object key) {
|
||||||
|
V result = overlay.remove(key);
|
||||||
|
V low = lower.get(key);
|
||||||
|
if (low != null && masked.add((K) key) && result == null) {
|
||||||
|
result = low;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
overlay.clear();
|
||||||
|
masked.addAll(lower.keySet());
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Set<Entry<K, V>> entrySet() {
|
||||||
|
return entrySet;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Set<Entry<K, V>> entrySet = new AbstractSet<>() {
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return OverlayMap.this.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return OverlayMap.this.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean contains(Object o) {
|
||||||
|
return o instanceof Map.Entry<?,?> e && Objects.equals(OverlayMap.this.get(e.getKey()), e.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean add(Entry<K, V> kvEntry) {
|
||||||
|
return OverlayMap.this.put(kvEntry.getKey(), kvEntry.getValue()) == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean remove(Object o) {
|
||||||
|
return o instanceof Map.Entry<?,?> e && OverlayMap.this.remove(e.getKey(), e.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
OverlayMap.this.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Iterator<Entry<K, V>> iterator() {
|
||||||
|
return new Iterator<>() {
|
||||||
|
private final Iterator<K> keys = OverlayMap.this.streamKeys().iterator();
|
||||||
|
private K previous = null;
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
return keys.hasNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Entry<K, V> next() {
|
||||||
|
previous = keys.next();
|
||||||
|
return new Entry<>() {
|
||||||
|
private final K currentK = previous;
|
||||||
|
private V currentV = OverlayMap.this.get(currentK);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public K getKey() {
|
||||||
|
return currentK;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V getValue() {
|
||||||
|
return currentV;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V setValue(V value) {
|
||||||
|
V result = OverlayMap.this.put(currentK, value);
|
||||||
|
currentV = value;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove() {
|
||||||
|
if (previous == null) throw new IllegalStateException();
|
||||||
|
OverlayMap.this.remove(previous);
|
||||||
|
previous = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in New Issue