FlorianMichael 2023-07-10 04:19:32 +02:00
parent 36c3a2cd53
commit 32bb6c00e5
No known key found for this signature in database
GPG Key ID: C2FB87E71C425126
10 changed files with 595849 additions and 183 deletions

View File

@ -30,6 +30,7 @@ import de.florianmichael.viafabricplus.definition.classic.protocol.CustomClassic
import de.florianmichael.viafabricplus.definition.FontCacheFix; import de.florianmichael.viafabricplus.definition.FontCacheFix;
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.ItemReleaseVersionMappings; import de.florianmichael.viafabricplus.mappings.ItemReleaseVersionMappings;
import de.florianmichael.viafabricplus.mappings.PackFormatsMappings; import de.florianmichael.viafabricplus.mappings.PackFormatsMappings;
import de.florianmichael.viafabricplus.protocolhack.ProtocolHack; import de.florianmichael.viafabricplus.protocolhack.ProtocolHack;
@ -76,6 +77,7 @@ public class ViaFabricPlus {
// Fixes which requires to be loaded pre // Fixes which requires to be loaded pre
ChatLengthCalculation.create(); ChatLengthCalculation.create();
CharacterMappings.load();
FontCacheFix.init(); FontCacheFix.init();
// Protocol Translator // Protocol Translator

View File

@ -55,29 +55,11 @@ public class FontCacheFix {
public enum BuiltinEmptyGlyph1_12_2 implements Glyph { public enum BuiltinEmptyGlyph1_12_2 implements Glyph {
VERY_MISSING(() -> BuiltinEmptyGlyph1_12_2.createRectImage((x, y) -> x == 0 || x + 1 == 5 || y == 0 || y + 1 == 8 ? -1 : 0)); VERY_MISSING;
final NativeImage image;
BuiltinEmptyGlyph1_12_2(Supplier<NativeImage> imageSupplier) {
this.image = imageSupplier.get();
}
private static NativeImage createRectImage(BuiltinEmptyGlyph1_12_2.ColorSupplier colorSupplier) {
final NativeImage nativeImage = new NativeImage(NativeImage.Format.RGBA, 5, 8, false);
for (int y = 0; y < 8; ++y) {
for (int x = 0; x < 5; ++x) {
nativeImage.setColor(x, y, colorSupplier.getColor(x, y));
}
}
nativeImage.untrack();
return nativeImage;
}
@Override @Override
public float getAdvance() { public float getAdvance() {
return this.image.getWidth() + 1; return 1;
} }
@Override @Override
@ -86,12 +68,12 @@ public class FontCacheFix {
@Override @Override
public int getWidth() { public int getWidth() {
return BuiltinEmptyGlyph1_12_2.this.image.getWidth(); return 0;
} }
@Override @Override
public int getHeight() { public int getHeight() {
return BuiltinEmptyGlyph1_12_2.this.image.getHeight(); return 0;
} }
@Override @Override
@ -101,7 +83,6 @@ public class FontCacheFix {
@Override @Override
public void upload(int x, int y) { public void upload(int x, int y) {
BuiltinEmptyGlyph1_12_2.this.image.upload(0, x, y, false);
} }
@Override @Override
@ -110,11 +91,5 @@ public class FontCacheFix {
} }
}); });
} }
@FunctionalInterface
interface ColorSupplier {
int getColor(int x, int y);
}
} }
} }

View File

@ -0,0 +1,115 @@
/*
* This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus
* Copyright (C) 2021-2023 FlorianMichael/EnZaXD and 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 <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft;
import de.florianmichael.viafabricplus.definition.FontCacheFix;
import de.florianmichael.viafabricplus.injection.access.IFontStorage;
import de.florianmichael.viafabricplus.mappings.CharacterMappings;
import de.florianmichael.viafabricplus.protocolhack.ProtocolHack;
import net.minecraft.client.font.*;
import net.minecraft.client.font.Font;
import net.minecraft.util.Identifier;
import net.raphimc.vialoader.util.VersionEnum;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@Mixin(FontStorage.class)
public abstract class MixinFontStorage implements IFontStorage {
@Shadow protected abstract GlyphRenderer getGlyphRenderer(RenderableGlyph c);
@Shadow @Final private GlyphContainer<GlyphRenderer> glyphRendererCache;
@Shadow @Final private GlyphContainer<FontStorage.GlyphPair> glyphCache;
@Shadow private GlyphRenderer blankGlyphRenderer;
@Shadow @Final private Identifier id;
@Unique
private Map<String, List<Integer>> forbiddenCharacters;
@Unique
private boolean obfuscation;
@Inject(method = "setFonts", at = @At("HEAD"))
public void trackForbiddenCharacters(List<Font> fonts, CallbackInfo ci) {
forbiddenCharacters = CharacterMappings.getForbiddenCharactersForID(this.id);
}
@Unique
private boolean isForbiddenCharacter(final Font font, final int codePoint) {
try {
return forbiddenCharacters.get(font.getClass().getSimpleName()).contains(codePoint);
} catch (Exception ignored) {
return false;
}
}
@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) {
if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_19_4) && this.id.getNamespace().equals("minecraft")) {
if (isForbiddenCharacter(font, codePoint)) cir.setReturnValue(FontStorage.GlyphPair.MISSING);
if (FontCacheFix.shouldReplaceFontRenderer() && cir.getReturnValue() == FontStorage.GlyphPair.MISSING) {
cir.setReturnValue(new FontStorage.GlyphPair(FontCacheFix.BuiltinEmptyGlyph1_12_2.VERY_MISSING, FontCacheFix.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)
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 (isForbiddenCharacter(font, codePoint)) cir.setReturnValue(this.blankGlyphRenderer);
if (FontCacheFix.shouldReplaceFontRenderer() && cir.getReturnValue() == this.blankGlyphRenderer) {
cir.setReturnValue(FontCacheFix.BuiltinEmptyGlyph1_12_2.VERY_MISSING.bake(this::getGlyphRenderer));
}
}
}
/*
Minecraft uses all characters that exist for obfuscation mode, even those that no longer exist in the selected target version,
so we must not make the fix in case it is executed from an obfuscated text, because otherwise the obfuscation would have missing characters
*/
@Inject(method = "getObfuscatedGlyphRenderer", at = @At("HEAD"))
public void trackObfuscationState(Glyph glyph, CallbackInfoReturnable<GlyphRenderer> cir) {
obfuscation = true;
}
@Inject(method = "getGlyphRenderer(I)Lnet/minecraft/client/font/GlyphRenderer;", at = @At("RETURN"))
public void revertObfuscationState(int codePoint, CallbackInfoReturnable<GlyphRenderer> cir) {
obfuscation = false;
}
@Override
public void viafabricplus_clearCaches() {
this.glyphRendererCache.clear();
this.glyphCache.clear();
}
}

View File

@ -1,36 +0,0 @@
/*
* This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus
* Copyright (C) 2021-2023 FlorianMichael/EnZaXD and 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 <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.font;
import de.florianmichael.viafabricplus.definition.FontCacheFix;
import net.minecraft.client.font.BuiltinEmptyGlyph;
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.CallbackInfoReturnable;
@Mixin(BuiltinEmptyGlyph.class)
public class MixinBuiltinEmptyGlyph {
@Inject(method = "getAdvance", at = @At("HEAD"), cancellable = true)
public void resetAdvance(CallbackInfoReturnable<Float> cir) {
if (FontCacheFix.shouldReplaceFontRenderer()) {
cir.setReturnValue(0F);
}
}
}

View File

@ -1,35 +0,0 @@
/*
* This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus
* Copyright (C) 2021-2023 FlorianMichael/EnZaXD and 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 <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.font;
import de.florianmichael.viafabricplus.definition.FontCacheFix;
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.CallbackInfoReturnable;
@Mixin(targets = "net/minecraft/client/font/BuiltinEmptyGlyph$1")
public class MixinBuiltinEmptyGlyph_1 {
@Inject(method = {"getWidth", "getHeight"}, at = @At("HEAD"), cancellable = true)
public void resetDimension(CallbackInfoReturnable<Integer> cir) {
if (FontCacheFix.shouldReplaceFontRenderer()) {
cir.setReturnValue(0);
}
}
}

View File

@ -1,80 +0,0 @@
/*
* This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus
* Copyright (C) 2021-2023 FlorianMichael/EnZaXD and 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 <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft.font;
import de.florianmichael.viafabricplus.definition.FontCacheFix;
import de.florianmichael.viafabricplus.injection.access.IFontStorage;
import net.minecraft.client.font.Font;
import net.minecraft.client.font.FontStorage;
import net.minecraft.client.font.GlyphRenderer;
import net.minecraft.client.font.RenderableGlyph;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.List;
@Mixin(FontStorage.class)
public abstract class MixinFontStorage implements IFontStorage {
@Shadow protected abstract GlyphRenderer getGlyphRenderer(RenderableGlyph c);
@Shadow @Final private List<Font> fonts;
@Shadow public abstract void setFonts(List<Font> fonts);
@Unique
private GlyphRenderer unknownGlyphRenderer;
@Unique
private List<Font> viafabricplus_fontCache;
@Inject(method = "setFonts", at = @At("HEAD"))
public void cacheFonts(List<Font> fonts, CallbackInfo ci) {
if (viafabricplus_fontCache == fonts) return;
viafabricplus_fontCache = fonts;
}
@Inject(method = "setFonts", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/font/BuiltinEmptyGlyph;bake(Ljava/util/function/Function;)Lnet/minecraft/client/font/GlyphRenderer;", ordinal = 0, shift = At.Shift.AFTER))
public void injectSetFonts(List<Font> fonts, CallbackInfo ci) {
this.unknownGlyphRenderer = FontCacheFix.BuiltinEmptyGlyph1_12_2.VERY_MISSING.bake(this::getGlyphRenderer);
}
@Inject(method = "getRectangleRenderer", at = @At("HEAD"), cancellable = true)
public void setCustomRenderer(CallbackInfoReturnable<GlyphRenderer> cir) {
if (FontCacheFix.shouldReplaceFontRenderer()) {
cir.setReturnValue(this.unknownGlyphRenderer);
}
}
@Override
public void viafabricplus_clearCaches() {
if (fonts != null) {
fonts.clear();
if (viafabricplus_fontCache != null) {
setFonts(viafabricplus_fontCache);
}
}
}
}

View File

@ -0,0 +1,52 @@
/*
* This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus
* Copyright (C) 2021-2023 FlorianMichael/EnZaXD and 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 <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.mappings;
import com.google.gson.*;
import de.florianmichael.viafabricplus.ViaFabricPlus;
import net.minecraft.util.Identifier;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class CharacterMappings {
public static Map<String, Map<String, List<Integer>>> forbiddenCharacters1_19_4To1_20 = new HashMap<>();
public static void load() {
final JsonObject file = ViaFabricPlus.GSON.fromJson(new InputStreamReader(CharacterMappings.class.getResourceAsStream("/assets/viafabricplus/characters1_19_4To1_20.txt")), JsonObject.class);
for (Map.Entry<String, JsonElement> layer1 : file.entrySet()) { // missing / uniform / bitmap
final Map<String, List<Integer>> typeStorage = new HashMap<>();
for (Map.Entry<String, JsonElement> layer2 : layer1.getValue().getAsJsonObject().entrySet()) { // blank / space / unicode
final List<Integer> type2Storage = new ArrayList<>();
for (JsonElement element : layer2.getValue().getAsJsonArray()) { // data
type2Storage.add(element.getAsInt());
}
typeStorage.put(layer2.getKey(), type2Storage);
}
forbiddenCharacters1_19_4To1_20.put(layer1.getKey(), typeStorage);
}
}
public static Map<String, List<Integer>> getForbiddenCharactersForID(final Identifier id) {
if (!forbiddenCharacters1_19_4To1_20.containsKey(id.toString())) return new HashMap<>();
return forbiddenCharacters1_19_4To1_20.get(id.toString());
}
}

File diff suppressed because it is too large Load Diff

View File

@ -11,7 +11,10 @@ accessible field net/minecraft/client/font/FontManager fontStorages Ljava/util/M
accessible field net/minecraft/network/ClientConnection EPOLL_CLIENT_IO_GROUP Lnet/minecraft/util/Lazy; accessible field net/minecraft/network/ClientConnection EPOLL_CLIENT_IO_GROUP Lnet/minecraft/util/Lazy;
accessible field net/minecraft/network/ClientConnection LOCAL_CLIENT_IO_GROUP Lnet/minecraft/util/Lazy; accessible field net/minecraft/network/ClientConnection LOCAL_CLIENT_IO_GROUP Lnet/minecraft/util/Lazy;
accessible field net/minecraft/client/gui/screen/GameMenuScreen exitButton Lnet/minecraft/client/gui/widget/ButtonWidget; accessible field net/minecraft/client/gui/screen/GameMenuScreen exitButton Lnet/minecraft/client/gui/widget/ButtonWidget;
accessible field net/minecraft/client/font/FontStorage$GlyphPair MISSING Lnet/minecraft/client/font/FontStorage$GlyphPair;
accessible method net/minecraft/screen/GenericContainerScreenHandler <init> (Lnet/minecraft/screen/ScreenHandlerType;ILnet/minecraft/entity/player/PlayerInventory;I)V accessible method net/minecraft/screen/GenericContainerScreenHandler <init> (Lnet/minecraft/screen/ScreenHandlerType;ILnet/minecraft/entity/player/PlayerInventory;I)V
accessible method net/minecraft/client/font/FontStorage$GlyphPair <init> (Lnet/minecraft/client/font/Glyph;Lnet/minecraft/client/font/Glyph;)V
accessible class net/minecraft/client/gui/screen/GameModeSelectionScreen$GameModeSelection accessible class net/minecraft/client/gui/screen/GameModeSelectionScreen$GameModeSelection
accessible class net/minecraft/client/font/FontStorage$GlyphPair

View File

@ -86,9 +86,7 @@
"fixes.minecraft.entity.MixinSquidEntity", "fixes.minecraft.entity.MixinSquidEntity",
"fixes.minecraft.entity.MixinVexEntity", "fixes.minecraft.entity.MixinVexEntity",
"fixes.minecraft.entity.MixinWolfEntity", "fixes.minecraft.entity.MixinWolfEntity",
"fixes.minecraft.font.MixinBuiltinEmptyGlyph", "fixes.minecraft.MixinFontStorage",
"fixes.minecraft.font.MixinBuiltinEmptyGlyph_1",
"fixes.minecraft.font.MixinFontStorage",
"fixes.minecraft.input.MixinKeyboard", "fixes.minecraft.input.MixinKeyboard",
"fixes.minecraft.input.MixinKeyboardInput", "fixes.minecraft.input.MixinKeyboardInput",
"fixes.minecraft.input.MixinMouse", "fixes.minecraft.input.MixinMouse",