diff --git a/src/main/java/de/florianmichael/viafabricplus/fixes/ClientsideFixes.java b/src/main/java/de/florianmichael/viafabricplus/fixes/ClientsideFixes.java index 9c8f5f78..8202aab7 100644 --- a/src/main/java/de/florianmichael/viafabricplus/fixes/ClientsideFixes.java +++ b/src/main/java/de/florianmichael/viafabricplus/fixes/ClientsideFixes.java @@ -19,9 +19,9 @@ package de.florianmichael.viafabricplus.fixes; +import com.mojang.blaze3d.systems.RenderSystem; import com.viaversion.viaversion.api.protocol.version.ProtocolVersion; -import de.florianmichael.viafabricplus.event.ChangeProtocolVersionCallback; -import de.florianmichael.viafabricplus.event.PostGameLoadCallback; +import de.florianmichael.viafabricplus.event.*; import de.florianmichael.viafabricplus.fixes.data.EntityDimensionDiff; import de.florianmichael.viafabricplus.fixes.data.ResourcePackHeaderDiff; import de.florianmichael.viafabricplus.fixes.versioned.EnchantmentAttributesEmulation1_20_6; @@ -31,16 +31,21 @@ import de.florianmichael.viafabricplus.fixes.versioned.visual.ArmorHudEmulation1 import de.florianmichael.viafabricplus.fixes.versioned.visual.FootStepParticle1_12_2; import de.florianmichael.viafabricplus.injection.access.IClientConnection; import de.florianmichael.viafabricplus.protocoltranslator.ProtocolTranslator; +import de.florianmichael.viafabricplus.protocoltranslator.util.LanguageUtil; import de.florianmichael.viafabricplus.settings.impl.BedrockSettings; +import de.florianmichael.viafabricplus.settings.impl.VisualSettings; import de.florianmichael.viafabricplus.util.DataCustomPayload; import net.minecraft.block.*; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.FontStorage; import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.client.network.ServerAddress; +import net.minecraft.client.option.SimpleOption; +import net.minecraft.client.resource.language.TranslationStorage; import net.minecraft.network.PacketByteBuf; import net.minecraft.network.RegistryByteBuf; import net.minecraft.registry.Registries; +import net.minecraft.util.Language; import net.raphimc.viaaprilfools.api.AprilFoolsProtocolVersion; import net.raphimc.viabedrock.api.BedrockProtocolVersion; import net.raphimc.viabedrock.protocol.data.ProtocolConstants; @@ -75,6 +80,12 @@ public class ClientsideFixes { */ public static int GLOBAL_TABLIST_INDEX = 0; + /** + * Older versions only had unicode font support for some languages and therefore servers are expecting the client + * to use a unicode font, not using it on older versions can cause issues with wrong dimensions in chat components. + */ + private static boolean forcingUnicodeFont = false; + static { // Register additional CPE features CPEAdditions.modifyMappings(); @@ -94,40 +105,45 @@ public class ClientsideFixes { }); // Reloads some clientside stuff when the protocol version changes - ChangeProtocolVersionCallback.EVENT.register((oldVersion, newVersion) -> MinecraftClient.getInstance().execute(() -> { - // Clear all font caches to enforce a reload of all fonts (this is needed because we change the font renderer behavior) - for (FontStorage storage : MinecraftClient.getInstance().fontManager.fontStorages.values()) { - storage.glyphRendererCache.clear(); - storage.glyphCache.clear(); - } + ChangeProtocolVersionCallback.EVENT.register((oldVersion, newVersion) -> { + MinecraftClient.getInstance().execute(() -> { + // Clear all font caches to enforce a reload of all fonts (this is needed because we change the font renderer behavior) + for (FontStorage storage : MinecraftClient.getInstance().fontManager.fontStorages.values()) { + storage.glyphRendererCache.clear(); + storage.glyphCache.clear(); + } - // Reloads all bounding boxes of the blocks that we changed - for (Block block : Registries.BLOCK) { - if (block instanceof AnvilBlock || block instanceof BedBlock || block instanceof BrewingStandBlock - || block instanceof CarpetBlock || block instanceof CauldronBlock || block instanceof ChestBlock - || block instanceof EnderChestBlock || block instanceof EndPortalBlock || block instanceof EndPortalFrameBlock - || block instanceof FarmlandBlock || block instanceof FenceBlock || block instanceof FenceGateBlock - || block instanceof HopperBlock || block instanceof LadderBlock || block instanceof LeavesBlock - || block instanceof LilyPadBlock || block instanceof PaneBlock || block instanceof PistonBlock - || block instanceof PistonHeadBlock || block instanceof SnowBlock || block instanceof WallBlock - || block instanceof CropBlock || block instanceof FlowerbedBlock - ) { - for (BlockState state : block.getStateManager().getStates()) { - state.initShapeCache(); + // Reloads all bounding boxes of the blocks that we changed + for (Block block : Registries.BLOCK) { + if (block instanceof AnvilBlock || block instanceof BedBlock || block instanceof BrewingStandBlock + || block instanceof CarpetBlock || block instanceof CauldronBlock || block instanceof ChestBlock + || block instanceof EnderChestBlock || block instanceof EndPortalBlock || block instanceof EndPortalFrameBlock + || block instanceof FarmlandBlock || block instanceof FenceBlock || block instanceof FenceGateBlock + || block instanceof HopperBlock || block instanceof LadderBlock || block instanceof LeavesBlock + || block instanceof LilyPadBlock || block instanceof PaneBlock || block instanceof PistonBlock + || block instanceof PistonHeadBlock || block instanceof SnowBlock || block instanceof WallBlock + || block instanceof CropBlock || block instanceof FlowerbedBlock + ) { + for (BlockState state : block.getStateManager().getStates()) { + state.initShapeCache(); + } } } - } - // Rebuilds the item selection screen grid - if (newVersion.olderThanOrEqualTo(LegacyProtocolVersion.c0_28toc0_30)) { - GridItemSelectionScreen.INSTANCE.itemGrid = null; - } + // Rebuilds the item selection screen grid + if (newVersion.olderThanOrEqualTo(LegacyProtocolVersion.c0_28toc0_30)) { + GridItemSelectionScreen.INSTANCE.itemGrid = null; + } - // Reload sound system when switching between 3D Shareware and normal versions - if (oldVersion.equals(AprilFoolsProtocolVersion.s3d_shareware) || newVersion.equals(AprilFoolsProtocolVersion.s3d_shareware)) { - MinecraftClient.getInstance().getSoundManager().reloadSounds(); - } - })); + // Reload sound system when switching between 3D Shareware and normal versions + if (oldVersion.equals(AprilFoolsProtocolVersion.s3d_shareware) || newVersion.equals(AprilFoolsProtocolVersion.s3d_shareware)) { + MinecraftClient.getInstance().getSoundManager().reloadSounds(); + } + }); + + // Runs its own code already inside the game thread + updateUnicodeFontOverride(newVersion); + }); // Register the footstep particle FootStepParticle1_12_2.init(); @@ -140,6 +156,21 @@ public class ClientsideFixes { // Calls the static block } + @ApiStatus.Internal + public static void updateUnicodeFontOverride(final ProtocolVersion version) { + final SimpleOption option = MinecraftClient.getInstance().options.getForceUnicodeFont(); + + if (VisualSettings.global().forceUnicodeFontForNonAsciiLanguages.isEnabled(version)) { + if (Language.getInstance() instanceof TranslationStorage storage) { + forcingUnicodeFont = LanguageUtil.isUnicodeFont1_12_2(storage.translations); + RenderSystem.recordRenderCall(() -> option.setValue(forcingUnicodeFont)); + } + } else if (forcingUnicodeFont) { + RenderSystem.recordRenderCall(() -> option.setValue(false)); + forcingUnicodeFont = false; + } + } + /** * Calculates the maximum chat length for the selected protocol version in {@link ProtocolTranslator#getTargetVersion()} * diff --git a/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinLanguageManager.java b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinLanguageManager.java new file mode 100644 index 00000000..0deeca79 --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/injection/mixin/fixes/minecraft/MixinLanguageManager.java @@ -0,0 +1,39 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2024 FlorianMichael/EnZaXD and RK_01/RaphiMC + * Copyright (C) 2023-2024 contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft; + +import de.florianmichael.viafabricplus.fixes.ClientsideFixes; +import de.florianmichael.viafabricplus.protocoltranslator.ProtocolTranslator; +import net.minecraft.client.resource.language.LanguageManager; +import net.minecraft.resource.ResourceManager; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(LanguageManager.class) +public abstract class MixinLanguageManager { + + @Inject(method = "reload", at = @At("RETURN")) + private void updateUnicodeFontOverride(ResourceManager manager, CallbackInfo ci) { + ClientsideFixes.updateUnicodeFontOverride(ProtocolTranslator.getTargetVersion()); + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/protocoltranslator/util/LanguageUtil.java b/src/main/java/de/florianmichael/viafabricplus/protocoltranslator/util/LanguageUtil.java new file mode 100644 index 00000000..26035475 --- /dev/null +++ b/src/main/java/de/florianmichael/viafabricplus/protocoltranslator/util/LanguageUtil.java @@ -0,0 +1,44 @@ +/* + * This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus + * Copyright (C) 2021-2024 FlorianMichael/EnZaXD and RK_01/RaphiMC + * Copyright (C) 2023-2024 contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package de.florianmichael.viafabricplus.protocoltranslator.util; + +import java.util.Map; + +public class LanguageUtil { + + private static final int NON_ASCII_THRESHOLD = 256; + + public static boolean isUnicodeFont1_12_2(final Map translations) { + int nonAsciiCharacters = 0; + int totalCharacters = 0; + + for (String value : translations.values()) { + totalCharacters += value.length(); + for (int i = 0; i < value.length(); ++i) { + if (value.charAt(i) >= NON_ASCII_THRESHOLD) { + nonAsciiCharacters++; + } + } + } + + return (float) nonAsciiCharacters / totalCharacters > 0.1; + } + +} diff --git a/src/main/java/de/florianmichael/viafabricplus/settings/impl/VisualSettings.java b/src/main/java/de/florianmichael/viafabricplus/settings/impl/VisualSettings.java index dc18c6a3..206ef936 100644 --- a/src/main/java/de/florianmichael/viafabricplus/settings/impl/VisualSettings.java +++ b/src/main/java/de/florianmichael/viafabricplus/settings/impl/VisualSettings.java @@ -56,6 +56,7 @@ public class VisualSettings extends SettingGroup { public final VersionedBooleanSetting replacePetrifiedOakSlab = new VersionedBooleanSetting(this, Text.translatable("visual_settings.viafabricplus.replace_petrified_oak_slab"), VersionRange.of(LegacyProtocolVersion.r1_3_1tor1_3_2, ProtocolVersion.v1_12_2)); public final VersionedBooleanSetting changeFontRendererBehaviour = new VersionedBooleanSetting(this, Text.translatable("visual_settings.viafabricplus.change_font_renderer_behaviour"), VersionRange.andOlder(ProtocolVersion.v1_12_2)); public final VersionedBooleanSetting hideFurnaceRecipeBook = new VersionedBooleanSetting(this, Text.translatable("visual_settings.viafabricplus.hide_furnace_recipe_book"), VersionRange.andOlder(ProtocolVersion.v1_12_2)); + public final VersionedBooleanSetting forceUnicodeFontForNonAsciiLanguages = new VersionedBooleanSetting(this, Text.translatable("visual_settings.viafabricplus.force_unicode_font_for_non_ascii_languages"), VersionRange.andOlder(ProtocolVersion.v1_12_2)); // 1.12 -> 1.11.1 public final VersionedBooleanSetting sidewaysBackwardsRunning = new VersionedBooleanSetting(this, Text.translatable("visual_settings.viafabricplus.sideways_backwards_walking"), VersionRange.andOlder(ProtocolVersion.v1_11_1)); @@ -91,6 +92,7 @@ public class VisualSettings extends SettingGroup { changeGameMenuScreenLayout.setValue(1); hideDownloadTerrainScreenTransitionEffects.setValue(VersionedBooleanSetting.DISABLED_INDEX); + forceUnicodeFontForNonAsciiLanguages.setValue(VersionedBooleanSetting.DISABLED_INDEX); } public static VisualSettings global() { diff --git a/src/main/resources/assets/viafabricplus/lang/de_de.json b/src/main/resources/assets/viafabricplus/lang/de_de.json index 5def53f9..30ecca15 100644 --- a/src/main/resources/assets/viafabricplus/lang/de_de.json +++ b/src/main/resources/assets/viafabricplus/lang/de_de.json @@ -100,6 +100,7 @@ "visual_settings.viafabricplus.hide_furnace_recipe_book": "Ofen-Rezeptbuch verstecken", "visual_settings.viafabricplus.hide_crafting_recipe_book": "Bastelrezeptbuch verstecken", "visual_settings.viafabricplus.hide_modern_jigsaw_screen_features": "Moderne Puzzle-Funktionen ausblenden", + "visual_settings.viafabricplus.force_unicode_font_for_non_ascii_languages": "Unicode-Schrift für nicht-ASCII-Sprachen erzwingen", "force_version.viafabricplus.title": "Version festlegen, mit der der Server gepingt/verbunden werden soll", diff --git a/src/main/resources/assets/viafabricplus/lang/en_us.json b/src/main/resources/assets/viafabricplus/lang/en_us.json index 4173d0ae..044d85d3 100644 --- a/src/main/resources/assets/viafabricplus/lang/en_us.json +++ b/src/main/resources/assets/viafabricplus/lang/en_us.json @@ -102,6 +102,7 @@ "visual_settings.viafabricplus.hide_furnace_recipe_book": "Hide furnace recipe book", "visual_settings.viafabricplus.hide_crafting_recipe_book": "Hide crafting recipe book", "visual_settings.viafabricplus.hide_modern_jigsaw_screen_features": "Hide modern Jigsaw screen features", + "visual_settings.viafabricplus.force_unicode_font_for_non_ascii_languages": "Force Unicode font for non-ASCII languages", "force_version.viafabricplus.title": "Please select the version with which the server should be pinged/connected", diff --git a/src/main/resources/viafabricplus.accesswidener b/src/main/resources/viafabricplus.accesswidener index 37307880..304fb50b 100644 --- a/src/main/resources/viafabricplus.accesswidener +++ b/src/main/resources/viafabricplus.accesswidener @@ -18,6 +18,7 @@ accessible field net/minecraft/client/gui/screen/world/WorldIcon UNKNOWN_SERVER_ accessible field net/minecraft/client/gui/widget/TexturedButtonWidget textures Lnet/minecraft/client/gui/screen/ButtonTextures; accessible field net/minecraft/client/gui/screen/option/ControlsListWidget$KeyBindingEntry RESET_TEXT Lnet/minecraft/text/Text; accessible field net/minecraft/client/gui/screen/multiplayer/SocialInteractionsScreen TITLE Lnet/minecraft/text/Text; +accessible field net/minecraft/client/resource/language/TranslationStorage translations Ljava/util/Map; accessible method net/minecraft/screen/GenericContainerScreenHandler (Lnet/minecraft/screen/ScreenHandlerType;ILnet/minecraft/entity/player/PlayerInventory;I)V accessible method net/minecraft/client/font/FontStorage$GlyphPair (Lnet/minecraft/client/font/Glyph;Lnet/minecraft/client/font/Glyph;)V diff --git a/src/main/resources/viafabricplus.mixins.json b/src/main/resources/viafabricplus.mixins.json index d7e4a9df..7aeff783 100644 --- a/src/main/resources/viafabricplus.mixins.json +++ b/src/main/resources/viafabricplus.mixins.json @@ -50,6 +50,7 @@ "fixes.minecraft.MixinGameRenderer", "fixes.minecraft.MixinKeyboard", "fixes.minecraft.MixinKeyboardInput", + "fixes.minecraft.MixinLanguageManager", "fixes.minecraft.MixinMinecraftClient", "fixes.minecraft.MixinMouse", "fixes.minecraft.MixinPlayerInventory",