Code cleanup

This commit is contained in:
FlorianMichael 2023-07-10 11:24:01 +02:00
parent 32bb6c00e5
commit 2209040e47
No known key found for this signature in database
GPG Key ID: C2FB87E71C425126
16 changed files with 38 additions and 50 deletions

View File

@ -27,7 +27,7 @@ import de.florianmichael.viafabricplus.definition.ChatLengthCalculation;
import de.florianmichael.viafabricplus.definition.bedrock.BedrockAccountHandler; import de.florianmichael.viafabricplus.definition.bedrock.BedrockAccountHandler;
import de.florianmichael.viafabricplus.definition.classic.ClassiCubeAccountHandler; import de.florianmichael.viafabricplus.definition.classic.ClassiCubeAccountHandler;
import de.florianmichael.viafabricplus.definition.classic.protocol.CustomClassicProtocolExtensions; import de.florianmichael.viafabricplus.definition.classic.protocol.CustomClassicProtocolExtensions;
import de.florianmichael.viafabricplus.definition.FontCacheFix; import de.florianmichael.viafabricplus.definition.FontRenderer1_12_2;
import de.florianmichael.viafabricplus.definition.ArmorPointCalculation; import de.florianmichael.viafabricplus.definition.ArmorPointCalculation;
import de.florianmichael.viafabricplus.information.InformationSystem; import de.florianmichael.viafabricplus.information.InformationSystem;
import de.florianmichael.viafabricplus.mappings.CharacterMappings; import de.florianmichael.viafabricplus.mappings.CharacterMappings;
@ -78,7 +78,7 @@ public class ViaFabricPlus {
// Fixes which requires to be loaded pre // Fixes which requires to be loaded pre
ChatLengthCalculation.create(); ChatLengthCalculation.create();
CharacterMappings.load(); CharacterMappings.load();
FontCacheFix.init(); FontRenderer1_12_2.init();
// Protocol Translator // Protocol Translator
ProtocolHack.init(); ProtocolHack.init();

View File

@ -26,7 +26,6 @@ public class ExperimentalSettings extends SettingGroup {
public final BooleanSetting fixChunkBorders = new BooleanSetting(this, Text.translatable("experimental.viafabricplus.chunkborderfix"), true); public final BooleanSetting fixChunkBorders = new BooleanSetting(this, Text.translatable("experimental.viafabricplus.chunkborderfix"), true);
public final BooleanSetting waterMovementEdgeDetection = new BooleanSetting(this, Text.translatable("experimental.viafabricplus.watermovement"), true); public final BooleanSetting waterMovementEdgeDetection = new BooleanSetting(this, Text.translatable("experimental.viafabricplus.watermovement"), true);
public final BooleanSetting fixFontCache = new BooleanSetting(this, Text.translatable("experimental.viafabricplus.fontcachefix"), true);
public ExperimentalSettings() { public ExperimentalSettings() {
super(Text.translatable("settings.viafabricplus.experimental")); super(Text.translatable("settings.viafabricplus.experimental"));

View File

@ -18,12 +18,9 @@
package de.florianmichael.viafabricplus.base.settings.groups; package de.florianmichael.viafabricplus.base.settings.groups;
import net.raphimc.vialoader.util.VersionEnum; import net.raphimc.vialoader.util.VersionEnum;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import de.florianmichael.viafabricplus.base.settings.base.SettingGroup; import de.florianmichael.viafabricplus.base.settings.base.SettingGroup;
import de.florianmichael.viafabricplus.base.settings.type_impl.ProtocolSyncBooleanSetting; import de.florianmichael.viafabricplus.base.settings.type_impl.ProtocolSyncBooleanSetting;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.raphimc.vialoader.util.VersionEnum;
import net.raphimc.vialegacy.api.LegacyProtocolVersion;
import net.raphimc.vialoader.util.VersionRange; import net.raphimc.vialoader.util.VersionRange;
public class VisualSettings extends SettingGroup { public class VisualSettings extends SettingGroup {
@ -40,6 +37,7 @@ public class VisualSettings extends SettingGroup {
// 1.13 -> 1.12.2 // 1.13 -> 1.12.2
public final ProtocolSyncBooleanSetting replacePetrifiedOakSlab = new ProtocolSyncBooleanSetting(this, Text.translatable("visual.viafabricplus.stoneslab"), new VersionRange(VersionEnum.r1_12_2, VersionEnum.r1_3_1tor1_3_2)); public final ProtocolSyncBooleanSetting replacePetrifiedOakSlab = new ProtocolSyncBooleanSetting(this, Text.translatable("visual.viafabricplus.stoneslab"), new VersionRange(VersionEnum.r1_12_2, VersionEnum.r1_3_1tor1_3_2));
public final ProtocolSyncBooleanSetting changeFontRendererBehaviour = new ProtocolSyncBooleanSetting(this, Text.translatable("visual.viafabricplus.fontrendererbehaviour"), VersionRange.andOlder(VersionEnum.r1_12_2));
// 1.9 -> 1.8.x // 1.9 -> 1.8.x
public final ProtocolSyncBooleanSetting emulateArmorHud = new ProtocolSyncBooleanSetting(this, Text.translatable("visual.viafabricplus.armor"), VersionRange.andOlder(VersionEnum.r1_8)); public final ProtocolSyncBooleanSetting emulateArmorHud = new ProtocolSyncBooleanSetting(this, Text.translatable("visual.viafabricplus.armor"), VersionRange.andOlder(VersionEnum.r1_8));

View File

@ -18,39 +18,31 @@
package de.florianmichael.viafabricplus.definition; package de.florianmichael.viafabricplus.definition;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import net.raphimc.vialoader.util.VersionEnum; import de.florianmichael.viafabricplus.base.settings.groups.VisualSettings;
import de.florianmichael.viafabricplus.base.event.ChangeProtocolVersionCallback; import de.florianmichael.viafabricplus.base.event.ChangeProtocolVersionCallback;
import de.florianmichael.viafabricplus.injection.access.IFontStorage; import de.florianmichael.viafabricplus.injection.access.IFontStorage;
import de.florianmichael.viafabricplus.base.settings.groups.ExperimentalSettings;
import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.Glyph; import net.minecraft.client.font.Glyph;
import net.minecraft.client.font.GlyphRenderer; import net.minecraft.client.font.GlyphRenderer;
import net.minecraft.client.font.RenderableGlyph; import net.minecraft.client.font.RenderableGlyph;
import net.minecraft.client.texture.NativeImage;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Supplier;
public class FontCacheFix { public class FontRenderer1_12_2 {
public final static boolean DASH_LOADER = FabricLoader.getInstance().isModLoaded("dashloader"); public final static boolean DASH_LOADER = FabricLoader.getInstance().isModLoaded("dashloader");
private static VersionEnum protocolVersion;
public static void init() { public static void init() {
if (DASH_LOADER) return; if (DASH_LOADER) return;
ChangeProtocolVersionCallback.EVENT.register(protocolVersion -> { ChangeProtocolVersionCallback.EVENT.register(protocolVersion ->
FontCacheFix.protocolVersion = protocolVersion; MinecraftClient.getInstance().fontManager.fontStorages.values().forEach(fontStorage ->
RenderSystem.recordRenderCall(() -> ((IFontStorage) fontStorage).viafabricplus_clearCaches())));
MinecraftClient.getInstance().fontManager.fontStorages.values().forEach(fontStorage -> RenderSystem.recordRenderCall(() -> ((IFontStorage) fontStorage).viafabricplus_clearCaches()));
});
} }
public static boolean shouldReplaceFontRenderer() { public static boolean shouldReplaceFontRenderer() {
if (DASH_LOADER || protocolVersion == null) return false; if (DASH_LOADER) return false;
return VisualSettings.INSTANCE.changeFontRendererBehaviour.isEnabled();
return ExperimentalSettings.INSTANCE.fixFontCache.getValue() && protocolVersion.isOlderThanOrEqualTo(VersionEnum.r1_12_2);
} }
public enum BuiltinEmptyGlyph1_12_2 implements Glyph { public enum BuiltinEmptyGlyph1_12_2 implements Glyph {

View File

@ -17,7 +17,7 @@
*/ */
package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft; package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft;
import de.florianmichael.viafabricplus.definition.FontCacheFix; import de.florianmichael.viafabricplus.definition.FontRenderer1_12_2;
import de.florianmichael.viafabricplus.injection.access.IFontStorage; import de.florianmichael.viafabricplus.injection.access.IFontStorage;
import de.florianmichael.viafabricplus.mappings.CharacterMappings; import de.florianmichael.viafabricplus.mappings.CharacterMappings;
import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; import de.florianmichael.viafabricplus.protocolhack.ProtocolHack;
@ -51,43 +51,50 @@ public abstract class MixinFontStorage implements IFontStorage {
@Shadow @Final private Identifier id; @Shadow @Final private Identifier id;
@Unique @Unique
private Map<String, List<Integer>> forbiddenCharacters; private Map<String, List<Integer>> viafabricplus_forbiddenCharacters;
@Unique @Unique
private boolean obfuscation; private boolean viafabricplus_obfuscation;
@Inject(method = "setFonts", at = @At("HEAD")) @Inject(method = "setFonts", at = @At("HEAD"))
public void trackForbiddenCharacters(List<Font> fonts, CallbackInfo ci) { public void trackForbiddenCharacters(List<Font> fonts, CallbackInfo ci) {
forbiddenCharacters = CharacterMappings.getForbiddenCharactersForID(this.id); viafabricplus_forbiddenCharacters = CharacterMappings.getForbiddenCharactersForID(this.id);
} }
@Unique @Unique
private boolean isForbiddenCharacter(final Font font, final int codePoint) { private boolean viafabricplus_isForbiddenCharacter(final Font font, final int codePoint) {
try { String fontName = null;
return forbiddenCharacters.get(font.getClass().getSimpleName()).contains(codePoint); if (font instanceof BitmapFont) {
} catch (Exception ignored) { fontName = "BitmapFont";
return false; } else if (font instanceof BlankFont) {
fontName = "BlankFont";
} else if (font instanceof SpaceFont) {
fontName = "SpaceFont";
} else if (font instanceof UnihexFont) {
fontName = "UnihexFont";
} }
if (fontName == null) return false;
return viafabricplus_forbiddenCharacters.get(fontName).contains(codePoint);
} }
@Inject(method = "findGlyph", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/font/Font;getGlyph(I)Lnet/minecraft/client/font/Glyph;"), locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true) @Inject(method = "findGlyph", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/font/Font;getGlyph(I)Lnet/minecraft/client/font/Glyph;"), locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true)
public void injectFindGlyph(int codePoint, CallbackInfoReturnable<FontStorage.GlyphPair> cir, Glyph glyph, Iterator var3, Font font) { public void injectFindGlyph(int codePoint, CallbackInfoReturnable<FontStorage.GlyphPair> cir, Glyph glyph, Iterator var3, Font font) {
if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_19_4) && this.id.getNamespace().equals("minecraft")) { if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_19_4) && this.id.getNamespace().equals("minecraft")) {
if (isForbiddenCharacter(font, codePoint)) cir.setReturnValue(FontStorage.GlyphPair.MISSING); if (viafabricplus_isForbiddenCharacter(font, codePoint)) cir.setReturnValue(FontStorage.GlyphPair.MISSING);
if (FontCacheFix.shouldReplaceFontRenderer() && cir.getReturnValue() == FontStorage.GlyphPair.MISSING) { if (FontRenderer1_12_2.shouldReplaceFontRenderer() && cir.getReturnValue() == FontStorage.GlyphPair.MISSING) {
cir.setReturnValue(new FontStorage.GlyphPair(FontCacheFix.BuiltinEmptyGlyph1_12_2.VERY_MISSING, FontCacheFix.BuiltinEmptyGlyph1_12_2.VERY_MISSING)); cir.setReturnValue(new FontStorage.GlyphPair(FontRenderer1_12_2.BuiltinEmptyGlyph1_12_2.VERY_MISSING, FontRenderer1_12_2.BuiltinEmptyGlyph1_12_2.VERY_MISSING));
} }
} }
} }
@Inject(method = "findGlyphRenderer", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/font/Font;getGlyph(I)Lnet/minecraft/client/font/Glyph;"), locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true) @Inject(method = "findGlyphRenderer", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/font/Font;getGlyph(I)Lnet/minecraft/client/font/Glyph;"), locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true)
public void injectFindGlyphRenderer(int codePoint, CallbackInfoReturnable<GlyphRenderer> cir, Iterator var2, Font font) { public void injectFindGlyphRenderer(int codePoint, CallbackInfoReturnable<GlyphRenderer> cir, Iterator var2, Font font) {
if (!obfuscation && ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_19_4) && this.id.getNamespace().equals("minecraft")) { if (!viafabricplus_obfuscation && ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_19_4) && this.id.getNamespace().equals("minecraft")) {
if (isForbiddenCharacter(font, codePoint)) cir.setReturnValue(this.blankGlyphRenderer); if (viafabricplus_isForbiddenCharacter(font, codePoint)) cir.setReturnValue(this.blankGlyphRenderer);
if (FontCacheFix.shouldReplaceFontRenderer() && cir.getReturnValue() == this.blankGlyphRenderer) { if (FontRenderer1_12_2.shouldReplaceFontRenderer() && cir.getReturnValue() == this.blankGlyphRenderer) {
cir.setReturnValue(FontCacheFix.BuiltinEmptyGlyph1_12_2.VERY_MISSING.bake(this::getGlyphRenderer)); cir.setReturnValue(FontRenderer1_12_2.BuiltinEmptyGlyph1_12_2.VERY_MISSING.bake(this::getGlyphRenderer));
} }
} }
} }
@ -99,12 +106,12 @@ public abstract class MixinFontStorage implements IFontStorage {
@Inject(method = "getObfuscatedGlyphRenderer", at = @At("HEAD")) @Inject(method = "getObfuscatedGlyphRenderer", at = @At("HEAD"))
public void trackObfuscationState(Glyph glyph, CallbackInfoReturnable<GlyphRenderer> cir) { public void trackObfuscationState(Glyph glyph, CallbackInfoReturnable<GlyphRenderer> cir) {
obfuscation = true; viafabricplus_obfuscation = true;
} }
@Inject(method = "getGlyphRenderer(I)Lnet/minecraft/client/font/GlyphRenderer;", at = @At("RETURN")) @Inject(method = "getGlyphRenderer(I)Lnet/minecraft/client/font/GlyphRenderer;", at = @At("RETURN"))
public void revertObfuscationState(int codePoint, CallbackInfoReturnable<GlyphRenderer> cir) { public void revertObfuscationState(int codePoint, CallbackInfoReturnable<GlyphRenderer> cir) {
obfuscation = false; viafabricplus_obfuscation = false;
} }
@Override @Override

View File

@ -31,7 +31,7 @@ public class CharacterMappings {
public static Map<String, Map<String, List<Integer>>> forbiddenCharacters1_19_4To1_20 = new HashMap<>(); public static Map<String, Map<String, List<Integer>>> forbiddenCharacters1_19_4To1_20 = new HashMap<>();
public static void load() { public static void load() {
final JsonObject file = ViaFabricPlus.GSON.fromJson(new InputStreamReader(CharacterMappings.class.getResourceAsStream("/assets/viafabricplus/characters1_19_4To1_20.txt")), JsonObject.class); final JsonObject file = ViaFabricPlus.GSON.fromJson(new InputStreamReader(CharacterMappings.class.getResourceAsStream("/assets/viafabricplus/characters1_19_4To1_20.json")), JsonObject.class);
for (Map.Entry<String, JsonElement> layer1 : file.entrySet()) { // missing / uniform / bitmap for (Map.Entry<String, JsonElement> layer1 : file.entrySet()) { // missing / uniform / bitmap
final Map<String, List<Integer>> typeStorage = new HashMap<>(); final Map<String, List<Integer>> typeStorage = new HashMap<>();
for (Map.Entry<String, JsonElement> layer2 : layer1.getValue().getAsJsonObject().entrySet()) { // blank / space / unicode for (Map.Entry<String, JsonElement> layer2 : layer1.getValue().getAsJsonObject().entrySet()) { // blank / space / unicode

View File

@ -37,7 +37,6 @@
"experimental.viafabricplus.chunkborderfix": "Fix Chunk borders", "experimental.viafabricplus.chunkborderfix": "Fix Chunk borders",
"experimental.viafabricplus.watermovement": "Water movement edge detection", "experimental.viafabricplus.watermovement": "Water movement edge detection",
"experimental.viafabricplus.fontcachefix": "Fix Font Cache",
"debug.viafabricplus.sequence": "Disable sequencing", "debug.viafabricplus.sequence": "Disable sequencing",
"debug.viafabricplus.merchant": "Smooth out merchant screens", "debug.viafabricplus.merchant": "Smooth out merchant screens",
@ -70,6 +69,7 @@
"visual.viafabricplus.classic": "Replace creative inventory", "visual.viafabricplus.classic": "Replace creative inventory",
"visual.viafabricplus.walkanimation": "Old walking animation", "visual.viafabricplus.walkanimation": "Old walking animation",
"visual.viafabricplus.sodium": "Fix Sodium Chunk renderer", "visual.viafabricplus.sodium": "Fix Sodium Chunk renderer",
"visual.viafabricplus.fontrendererbehaviour": "Change Font renderer behaviour",
"bedrocklogin.viafabricplus.text": "Your browser should have opened.\nPlease enter the following Code: %s\nClosing this screen will cancel the process!", "bedrocklogin.viafabricplus.text": "Your browser should have opened.\nPlease enter the following Code: %s\nClosing this screen will cancel the process!",
"bedrocklogin.viafabricplus.error": "An error has occurred! See the latest.log for more information,\nplease report the bug at: \nhttps://github.com/ViaVersion/ViaFabricPlus/issues", "bedrocklogin.viafabricplus.error": "An error has occurred! See the latest.log for more information,\nplease report the bug at: \nhttps://github.com/ViaVersion/ViaFabricPlus/issues",

View File

@ -24,7 +24,6 @@
"experimental.viafabricplus.chunkborderfix": "Korjaa chunk-rajat", "experimental.viafabricplus.chunkborderfix": "Korjaa chunk-rajat",
"experimental.viafabricplus.watermovement": "Vesi-liikkeen reunan havaitseminen", "experimental.viafabricplus.watermovement": "Vesi-liikkeen reunan havaitseminen",
"experimental.viafabricplus.fontcachefix": "Korjaa fontti-välimuisti",
"debug.viafabricplus.sequence": "Poista jaksotuksen käyttö", "debug.viafabricplus.sequence": "Poista jaksotuksen käyttö",
"debug.viafabricplus.merchant": "Pehmennä kauppias-näyttöjä", "debug.viafabricplus.merchant": "Pehmennä kauppias-näyttöjä",

View File

@ -23,7 +23,6 @@
"experimental.viafabricplus.chunkborderfix": "Réparer les bordures de Chunk", "experimental.viafabricplus.chunkborderfix": "Réparer les bordures de Chunk",
"experimental.viafabricplus.watermovement": "Détection des bords du mouvement de l'eau", "experimental.viafabricplus.watermovement": "Détection des bords du mouvement de l'eau",
"experimental.viafabricplus.fontcachefix": "Correction du cache de polices",
"debug.viafabricplus.sequence": "Désactiver le séquençage", "debug.viafabricplus.sequence": "Désactiver le séquençage",
"debug.viafabricplus.merchant": "Lisser les écrans des marchands", "debug.viafabricplus.merchant": "Lisser les écrans des marchands",

View File

@ -23,7 +23,6 @@
"experimental.viafabricplus.chunkborderfix": "Chunk határok megjavítása", "experimental.viafabricplus.chunkborderfix": "Chunk határok megjavítása",
"experimental.viafabricplus.watermovement": "Vízalatti mozgás szél érzékelés", "experimental.viafabricplus.watermovement": "Vízalatti mozgás szél érzékelés",
"experimental.viafabricplus.fontcachefix": "Betűtípus gyorsítótár megjavítása",
"debug.viafabricplus.sequence": "Szekvenálás kikapcsolása", "debug.viafabricplus.sequence": "Szekvenálás kikapcsolása",
"debug.viafabricplus.merchant": "Kereskedelmi képernyő kisimítása", "debug.viafabricplus.merchant": "Kereskedelmi képernyő kisimítása",

View File

@ -37,7 +37,6 @@
"experimental.viafabricplus.chunkborderfix": "Napraw granice chunków", "experimental.viafabricplus.chunkborderfix": "Napraw granice chunków",
"experimental.viafabricplus.watermovement": "Wykrywanie krawędzi ruchu wody", "experimental.viafabricplus.watermovement": "Wykrywanie krawędzi ruchu wody",
"experimental.viafabricplus.fontcachefix": "Napraw pamięć tymczasową czcionek",
"debug.viafabricplus.sequence": "Wyłącz sekwencjonowanie", "debug.viafabricplus.sequence": "Wyłącz sekwencjonowanie",
"debug.viafabricplus.merchant": "Wygładź ekrany kupców", "debug.viafabricplus.merchant": "Wygładź ekrany kupców",

View File

@ -30,7 +30,6 @@
"experimental.viafabricplus.chunkborderfix": "Исправлять границы чанков", "experimental.viafabricplus.chunkborderfix": "Исправлять границы чанков",
"experimental.viafabricplus.watermovement": "Проверять уровень воды для прыжка", "experimental.viafabricplus.watermovement": "Проверять уровень воды для прыжка",
"experimental.viafabricplus.fontcachefix": "Исправить кэширование шрифтов",
"debug.viafabricplus.sequence": "Отключить последовательность", "debug.viafabricplus.sequence": "Отключить последовательность",
"debug.viafabricplus.merchant": "Ускорить интерфейс старых жителей", "debug.viafabricplus.merchant": "Ускорить интерфейс старых жителей",

View File

@ -33,7 +33,6 @@
"experimental.viafabricplus.chunkborderfix": "Полагодити границі чанків", "experimental.viafabricplus.chunkborderfix": "Полагодити границі чанків",
"experimental.viafabricplus.watermovement": "Виявлення краю руху води", "experimental.viafabricplus.watermovement": "Виявлення краю руху води",
"experimental.viafabricplus.fontcachefix": "Полагодити кеш шрифтів",
"debug.viafabricplus.sequence": "Вимкнути послідовності", "debug.viafabricplus.sequence": "Вимкнути послідовності",
"debug.viafabricplus.merchant": "Згладити екрани крамарів", "debug.viafabricplus.merchant": "Згладити екрани крамарів",

View File

@ -33,7 +33,6 @@
"experimental.viafabricplus.chunkborderfix": "修复区块边界", "experimental.viafabricplus.chunkborderfix": "修复区块边界",
"experimental.viafabricplus.watermovement": "水中移动边缘检测", "experimental.viafabricplus.watermovement": "水中移动边缘检测",
"experimental.viafabricplus.fontcachefix": "修复字体缓存",
"debug.viafabricplus.sequence": "禁用排序", "debug.viafabricplus.sequence": "禁用排序",
"debug.viafabricplus.merchant": "平滑商人屏幕", "debug.viafabricplus.merchant": "平滑商人屏幕",

View File

@ -33,7 +33,6 @@
"experimental.viafabricplus.chunkborderfix": "修復區塊邊界", "experimental.viafabricplus.chunkborderfix": "修復區塊邊界",
"experimental.viafabricplus.watermovement": "Water movement edge detection/\u00a78水中移動邊緣偵測\u00a7r", "experimental.viafabricplus.watermovement": "Water movement edge detection/\u00a78水中移動邊緣偵測\u00a7r",
"experimental.viafabricplus.fontcachefix": "修復字體緩存",
"debug.viafabricplus.sequence": "Disable sequencing/\u00a78禁用排序\u00a7r", "debug.viafabricplus.sequence": "Disable sequencing/\u00a78禁用排序\u00a7r",
"debug.viafabricplus.merchant": "Smooth out merchant screens/\u00a78平滑螢幕\u00a7r", "debug.viafabricplus.merchant": "Smooth out merchant screens/\u00a78平滑螢幕\u00a7r",