mirror of
https://github.com/Wurst-Imperium/Wurst7.git
synced 2024-09-20 01:12:13 +02:00
Stop using Mojang's translation system entirely
Fixes JustAlittleWolf/ModDetectionPreventer#6 Sorry for breaking all open translation PRs with this commit, but it's necessary for security reasons. Anything in the lang folder can potentially be read by servers, so the files had to be moved.
This commit is contained in:
parent
5987308569
commit
f8a096c0fb
@ -11,17 +11,10 @@ import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.IllegalFormatException;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.option.KeyBinding;
|
||||
import net.minecraft.client.resource.language.I18n;
|
||||
import net.minecraft.client.util.InputUtil;
|
||||
import net.wurstclient.altmanager.AltManager;
|
||||
import net.wurstclient.altmanager.Encryption;
|
||||
import net.wurstclient.analytics.WurstAnalytics;
|
||||
@ -41,7 +34,6 @@ import net.wurstclient.hack.HackList;
|
||||
import net.wurstclient.hud.IngameHUD;
|
||||
import net.wurstclient.keybinds.KeybindList;
|
||||
import net.wurstclient.keybinds.KeybindProcessor;
|
||||
import net.wurstclient.mixinterface.ILanguageManager;
|
||||
import net.wurstclient.mixinterface.IMinecraftClient;
|
||||
import net.wurstclient.navigator.Navigator;
|
||||
import net.wurstclient.other_feature.OtfList;
|
||||
@ -76,6 +68,7 @@ public enum WurstClient
|
||||
private IngameHUD hud;
|
||||
private RotationFaker rotationFaker;
|
||||
private FriendsList friends;
|
||||
private WurstTranslator translator;
|
||||
|
||||
private boolean enabled = true;
|
||||
private static boolean guiInitialized;
|
||||
@ -83,8 +76,6 @@ public enum WurstClient
|
||||
private ProblematicResourcePackDetector problematicPackDetector;
|
||||
private Path wurstFolder;
|
||||
|
||||
private KeyBinding zoomKey;
|
||||
|
||||
public void initialize()
|
||||
{
|
||||
System.out.println("Starting Wurst Client...");
|
||||
@ -126,6 +117,8 @@ public enum WurstClient
|
||||
friends = new FriendsList(friendsFile);
|
||||
friends.load();
|
||||
|
||||
translator = new WurstTranslator();
|
||||
|
||||
cmdProcessor = new CmdProcessor(cmds);
|
||||
eventManager.add(ChatOutputListener.class, cmdProcessor);
|
||||
|
||||
@ -150,10 +143,6 @@ public enum WurstClient
|
||||
Path encFolder = Encryption.chooseEncryptionFolder();
|
||||
altManager = new AltManager(altsFile, encFolder);
|
||||
|
||||
zoomKey = new KeyBinding("key.wurst.zoom", InputUtil.Type.KEYSYM,
|
||||
GLFW.GLFW_KEY_V, KeyBinding.MISC_CATEGORY);
|
||||
KeyBindingHelper.registerKeyBinding(zoomKey);
|
||||
|
||||
analytics.trackPageView("/mc" + MC_VERSION + "/v" + VERSION,
|
||||
"Wurst " + VERSION + " MC" + MC_VERSION);
|
||||
}
|
||||
@ -178,27 +167,7 @@ public enum WurstClient
|
||||
|
||||
public String translate(String key, Object... args)
|
||||
{
|
||||
if(otfs.translationsOtf.getForceEnglish().isChecked())
|
||||
{
|
||||
String string = ILanguageManager.getEnglish().get(key);
|
||||
|
||||
try
|
||||
{
|
||||
return String.format(string, args);
|
||||
|
||||
}catch(IllegalFormatException e)
|
||||
{
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
// This extra check is necessary because I18n.translate() doesn't
|
||||
// always return the key when the translation is missing. If the key
|
||||
// contains a '%', it will return "Format Error: key" instead.
|
||||
if(!I18n.hasTranslation(key))
|
||||
return key;
|
||||
|
||||
return I18n.translate(key, args);
|
||||
return translator.translate(key, args);
|
||||
}
|
||||
|
||||
public WurstAnalytics getAnalytics()
|
||||
@ -314,6 +283,11 @@ public enum WurstClient
|
||||
return friends;
|
||||
}
|
||||
|
||||
public WurstTranslator getTranslator()
|
||||
{
|
||||
return translator;
|
||||
}
|
||||
|
||||
public boolean isEnabled()
|
||||
{
|
||||
return enabled;
|
||||
@ -345,11 +319,6 @@ public enum WurstClient
|
||||
return wurstFolder;
|
||||
}
|
||||
|
||||
public KeyBinding getZoomKey()
|
||||
{
|
||||
return zoomKey;
|
||||
}
|
||||
|
||||
public AltManager getAltManager()
|
||||
{
|
||||
return altManager;
|
||||
|
183
src/main/java/net/wurstclient/WurstTranslator.java
Normal file
183
src/main/java/net/wurstclient/WurstTranslator.java
Normal file
@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2024 Wurst-Imperium and contributors.
|
||||
*
|
||||
* This source code is subject to the terms of the GNU General Public
|
||||
* License, version 3. If a copy of the GPL was not distributed with this
|
||||
* file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt
|
||||
*/
|
||||
package net.wurstclient;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.IllegalFormatException;
|
||||
import java.util.List;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.resource.language.I18n;
|
||||
import net.minecraft.client.resource.language.TranslationStorage;
|
||||
import net.minecraft.resource.Resource;
|
||||
import net.minecraft.resource.ResourceManager;
|
||||
import net.minecraft.resource.SynchronousResourceReloader;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.Language;
|
||||
|
||||
public class WurstTranslator implements SynchronousResourceReloader
|
||||
{
|
||||
private final WurstClient wurst = WurstClient.INSTANCE;
|
||||
private TranslationStorage mcEnglish;
|
||||
|
||||
private final HashMap<String, String> englishOnlyStrings = new HashMap<>();
|
||||
private final HashMap<String, String> currentLangStrings = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void reload(ResourceManager manager)
|
||||
{
|
||||
mcEnglish = TranslationStorage.load(manager,
|
||||
Lists.newArrayList("en_us"), false);
|
||||
|
||||
currentLangStrings.clear();
|
||||
loadTranslations(manager, getCurrentLangCodes(),
|
||||
currentLangStrings::put);
|
||||
|
||||
englishOnlyStrings.clear();
|
||||
loadTranslations(manager, List.of("en_us"), englishOnlyStrings::put);
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates the given key with the given args into the current language,
|
||||
* or into English if the "Force English" setting is enabled. Both Wurst and
|
||||
* vanilla translations are supported.
|
||||
*/
|
||||
public String translate(String key, Object... args)
|
||||
{
|
||||
// Forced English
|
||||
if(isForcedEnglish())
|
||||
return translateEnglish(key, args);
|
||||
|
||||
// Wurst translation
|
||||
String string = currentLangStrings.get(key);
|
||||
if(string != null)
|
||||
try
|
||||
{
|
||||
return String.format(string, args);
|
||||
|
||||
}catch(IllegalFormatException e)
|
||||
{
|
||||
return key;
|
||||
}
|
||||
|
||||
// Vanilla translation
|
||||
return translateMc(key, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates the given key with the given args into English, regardless of
|
||||
* the current language. Both Wurst and vanilla translations are supported.
|
||||
*/
|
||||
public String translateEnglish(String key, Object... args)
|
||||
{
|
||||
String string = englishOnlyStrings.get(key);
|
||||
if(string == null)
|
||||
string = mcEnglish.get(key);
|
||||
|
||||
try
|
||||
{
|
||||
return String.format(string, args);
|
||||
|
||||
}catch(IllegalFormatException e)
|
||||
{
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates the given key with the given args into the current language,
|
||||
* or into English if the "Force English" setting is enabled, using only
|
||||
* Minecraft's own translations.
|
||||
*
|
||||
* @apiNote This method differs from
|
||||
* {@link I18n#translate(String, Object...)} in that it does not
|
||||
* return "Format error" if the key contains a percent sign.
|
||||
*/
|
||||
public String translateMc(String key, Object... args)
|
||||
{
|
||||
if(I18n.hasTranslation(key))
|
||||
return I18n.translate(key, args);
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates the given key with the given args into English, regardless of
|
||||
* the current language, using only Minecraft's own translations.
|
||||
*
|
||||
* @apiNote This method differs from
|
||||
* {@link I18n#translate(String, Object...)} in that it does not
|
||||
* return "Format error" if the key contains a percent sign.
|
||||
*/
|
||||
public String translateMcEnglish(String key, Object... args)
|
||||
{
|
||||
try
|
||||
{
|
||||
return String.format(mcEnglish.get(key), args);
|
||||
|
||||
}catch(IllegalFormatException e)
|
||||
{
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isForcedEnglish()
|
||||
{
|
||||
return wurst.getOtfs().translationsOtf.getForceEnglish().isChecked();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a translation storage for Minecraft's English strings, regardless
|
||||
* of the current language. Does not include any of Wurst's translations.
|
||||
*/
|
||||
public TranslationStorage getMcEnglish()
|
||||
{
|
||||
return mcEnglish;
|
||||
}
|
||||
|
||||
private ArrayList<String> getCurrentLangCodes()
|
||||
{
|
||||
String mainLangCode =
|
||||
MinecraftClient.getInstance().getLanguageManager().getLanguage();
|
||||
|
||||
ArrayList<String> langCodes = new ArrayList<>();
|
||||
langCodes.add("en_us");
|
||||
if(!"en_us".equals(mainLangCode))
|
||||
langCodes.add(mainLangCode);
|
||||
|
||||
return langCodes;
|
||||
}
|
||||
|
||||
private void loadTranslations(ResourceManager manager,
|
||||
Iterable<String> langCodes, BiConsumer<String, String> entryConsumer)
|
||||
{
|
||||
for(String langCode : langCodes)
|
||||
{
|
||||
String langFilePath = "translations/" + langCode + ".json";
|
||||
Identifier langId = Identifier.of("wurst", langFilePath);
|
||||
|
||||
for(Resource resource : manager.getAllResources(langId))
|
||||
try(InputStream stream = resource.getInputStream())
|
||||
{
|
||||
Language.load(stream, entryConsumer);
|
||||
|
||||
}catch(IOException e)
|
||||
{
|
||||
System.out.println("Failed to load translations for "
|
||||
+ langCode + " from pack " + resource.getPackId());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -10,7 +10,6 @@ package net.wurstclient.hacks.autolibrarian;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import net.minecraft.client.resource.language.TranslationStorage;
|
||||
import net.minecraft.enchantment.Enchantment;
|
||||
import net.minecraft.registry.DynamicRegistryManager;
|
||||
import net.minecraft.registry.Registry;
|
||||
@ -21,7 +20,7 @@ import net.minecraft.text.Text;
|
||||
import net.minecraft.text.TranslatableTextContent;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.wurstclient.WurstClient;
|
||||
import net.wurstclient.mixinterface.ILanguageManager;
|
||||
import net.wurstclient.WurstTranslator;
|
||||
|
||||
public record BookOffer(String id, int level, int price)
|
||||
implements Comparable<BookOffer>
|
||||
@ -53,28 +52,27 @@ public record BookOffer(String id, int level, int price)
|
||||
{
|
||||
Text description = getEnchantment().description();
|
||||
if(description.getContent() instanceof TranslatableTextContent tr)
|
||||
{
|
||||
TranslationStorage english = ILanguageManager.getEnglish();
|
||||
return english.get(tr.getKey());
|
||||
}
|
||||
return WurstClient.INSTANCE.getTranslator()
|
||||
.translateMcEnglish(tr.getKey());
|
||||
|
||||
return description.getString();
|
||||
}
|
||||
|
||||
public String getEnchantmentNameWithLevel()
|
||||
{
|
||||
TranslationStorage english = ILanguageManager.getEnglish();
|
||||
WurstTranslator translator = WurstClient.INSTANCE.getTranslator();
|
||||
Enchantment enchantment = getEnchantment();
|
||||
String name;
|
||||
|
||||
if(enchantment.description()
|
||||
.getContent() instanceof TranslatableTextContent tr)
|
||||
name = english.get(tr.getKey());
|
||||
name = translator.translateMcEnglish(tr.getKey());
|
||||
else
|
||||
name = enchantment.description().getString();
|
||||
|
||||
if(enchantment.getMaxLevel() > 1)
|
||||
name += " " + english.get("enchantment.level." + level);
|
||||
name += " "
|
||||
+ translator.translateMcEnglish("enchantment.level." + level);
|
||||
|
||||
return name;
|
||||
}
|
||||
|
@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2024 Wurst-Imperium and contributors.
|
||||
*
|
||||
* This source code is subject to the terms of the GNU General Public
|
||||
* License, version 3. If a copy of the GPL was not distributed with this
|
||||
* file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt
|
||||
*/
|
||||
package net.wurstclient.mixin;
|
||||
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import net.minecraft.text.KeybindTextContent;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.text.TextContent;
|
||||
|
||||
@Mixin(KeybindTextContent.class)
|
||||
public abstract class KeybindTextContentMixin implements TextContent
|
||||
{
|
||||
@Shadow
|
||||
@Final
|
||||
private String key;
|
||||
|
||||
/**
|
||||
* Ensures that any chat messages, written books, signs, etc. cannot resolve
|
||||
* Wurst-related keybinds.
|
||||
*
|
||||
* <p>
|
||||
* Fixes at least one security vulnerability affecting Minecraft 1.20 and
|
||||
* later versions, where the server can detect the presence of Wurst by
|
||||
* abusing Minecraft's sign editing feature. When a player edits a sign, any
|
||||
* translated text and keybind text components on that sign are resolved by
|
||||
* the client and sent back to the server as plain text. This allows the
|
||||
* server to detect the presence of non-vanilla keybinds, such as Wurst's
|
||||
* zoom keybind.
|
||||
*
|
||||
* <p>
|
||||
* It is likely that similar vulnerabilities exist or will exist in other
|
||||
* parts of the game, such as chat messages and written books. Mojang has a
|
||||
* long history of failing to properly secure their text component system
|
||||
* (see BookHack, OP-Sign, BookDupe). Therefore it's best to cut off this
|
||||
* entire attack vector at the source.
|
||||
*/
|
||||
@Inject(at = @At("RETURN"),
|
||||
method = "getTranslated()Lnet/minecraft/text/Text;",
|
||||
cancellable = true)
|
||||
private void onGetTranslated(CallbackInfoReturnable<Text> cir)
|
||||
{
|
||||
if(key != null && key.contains("wurst"))
|
||||
cir.setReturnValue(Text.literal(key));
|
||||
}
|
||||
}
|
@ -12,31 +12,21 @@ import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import net.minecraft.client.resource.language.LanguageManager;
|
||||
import net.minecraft.client.resource.language.TranslationStorage;
|
||||
import net.minecraft.resource.ResourceManager;
|
||||
import net.minecraft.resource.SynchronousResourceReloader;
|
||||
import net.wurstclient.mixinterface.ILanguageManager;
|
||||
import net.wurstclient.WurstClient;
|
||||
|
||||
@Mixin(LanguageManager.class)
|
||||
public abstract class LanguageManagerMixin
|
||||
implements SynchronousResourceReloader, ILanguageManager
|
||||
implements SynchronousResourceReloader
|
||||
{
|
||||
private TranslationStorage wurstEnglish;
|
||||
|
||||
@Inject(at = @At("HEAD"),
|
||||
method = "reload(Lnet/minecraft/resource/ResourceManager;)V")
|
||||
private void onReload(ResourceManager manager, CallbackInfo ci)
|
||||
{
|
||||
wurstEnglish = TranslationStorage.load(manager,
|
||||
Lists.newArrayList("en_us"), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TranslationStorage wurst_getEnglish()
|
||||
{
|
||||
return wurstEnglish;
|
||||
// Using a mixin for this because WurstClient.initialize() runs too
|
||||
// early to call ResourceManager.registerReloader()
|
||||
WurstClient.INSTANCE.getTranslator().reload(manager);
|
||||
}
|
||||
}
|
||||
|
@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2024 Wurst-Imperium and contributors.
|
||||
*
|
||||
* This source code is subject to the terms of the GNU General Public
|
||||
* License, version 3. If a copy of the GPL was not distributed with this
|
||||
* file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt
|
||||
*/
|
||||
package net.wurstclient.mixin;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
|
||||
import net.minecraft.text.TextContent;
|
||||
import net.minecraft.text.TranslatableTextContent;
|
||||
import net.minecraft.util.Language;
|
||||
|
||||
@Mixin(TranslatableTextContent.class)
|
||||
public abstract class TranslatableTextContentMixin implements TextContent
|
||||
{
|
||||
/**
|
||||
* Ensures that any chat messages, written books, signs, etc. cannot resolve
|
||||
* Wurst-related translation keys.
|
||||
*
|
||||
* <p>
|
||||
* Fixes at least one security vulnerability affecting Minecraft 1.20 and
|
||||
* later versions, where the server can detect the presence of Wurst by
|
||||
* abusing Minecraft's sign editing feature. When a player edits a sign, any
|
||||
* translated text and keybind text components on that sign are resolved by
|
||||
* the client and sent back to the server as plain text. This allows the
|
||||
* server to detect the presence of non-vanilla translation keys.
|
||||
*
|
||||
* <p>
|
||||
* It is likely that similar vulnerabilities exist or will exist in other
|
||||
* parts of the game, such as chat messages and written books. Mojang has a
|
||||
* long history of failing to properly secure their text component system
|
||||
* (see BookHack, OP-Sign, BookDupe). Therefore it's best to cut off this
|
||||
* entire attack vector at the source.
|
||||
*/
|
||||
@WrapOperation(at = @At(value = "INVOKE",
|
||||
target = "Lnet/minecraft/util/Language;get(Ljava/lang/String;)Ljava/lang/String;",
|
||||
ordinal = 0), method = "updateTranslations()V")
|
||||
private String translate(Language instance, String key,
|
||||
Operation<String> original)
|
||||
{
|
||||
if(key != null && key.contains("wurst"))
|
||||
return key;
|
||||
|
||||
return original.call(instance, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as above, but for translatable text components with a fallback.
|
||||
*/
|
||||
@WrapOperation(at = @At(value = "INVOKE",
|
||||
target = "Lnet/minecraft/util/Language;get(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
|
||||
ordinal = 0), method = "updateTranslations()V")
|
||||
private String translateWithFallback(Language instance, String key,
|
||||
String fallback, Operation<String> original)
|
||||
{
|
||||
if(key != null && key.contains("wurst"))
|
||||
return fallback;
|
||||
|
||||
return original.call(instance, key, fallback);
|
||||
}
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2024 Wurst-Imperium and contributors.
|
||||
*
|
||||
* This source code is subject to the terms of the GNU General Public
|
||||
* License, version 3. If a copy of the GPL was not distributed with this
|
||||
* file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt
|
||||
*/
|
||||
package net.wurstclient.mixinterface;
|
||||
|
||||
import net.minecraft.client.resource.language.TranslationStorage;
|
||||
import net.wurstclient.WurstClient;
|
||||
|
||||
public interface ILanguageManager
|
||||
{
|
||||
public TranslationStorage wurst_getEnglish();
|
||||
|
||||
public static TranslationStorage getEnglish()
|
||||
{
|
||||
return ((ILanguageManager)WurstClient.MC.getLanguageManager())
|
||||
.wurst_getEnglish();
|
||||
}
|
||||
}
|
@ -11,8 +11,6 @@ import net.minecraft.client.gui.DrawContext;
|
||||
import net.minecraft.client.gui.Drawable;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.widget.ButtonWidget;
|
||||
import net.minecraft.client.option.KeyBinding;
|
||||
import net.minecraft.client.util.InputUtil;
|
||||
import net.minecraft.text.Text;
|
||||
import net.wurstclient.WurstClient;
|
||||
import net.wurstclient.other_features.ZoomOtf;
|
||||
@ -22,7 +20,6 @@ import net.wurstclient.settings.SliderSetting;
|
||||
public class ZoomManagerScreen extends Screen implements PressAKeyCallback
|
||||
{
|
||||
private Screen prevScreen;
|
||||
private ButtonWidget keyButton;
|
||||
private ButtonWidget scrollButton;
|
||||
|
||||
public ZoomManagerScreen(Screen par1GuiScreen)
|
||||
@ -38,15 +35,16 @@ public class ZoomManagerScreen extends Screen implements PressAKeyCallback
|
||||
ZoomOtf zoom = wurst.getOtfs().zoomOtf;
|
||||
SliderSetting level = zoom.getLevelSetting();
|
||||
CheckboxSetting scroll = zoom.getScrollSetting();
|
||||
Text zoomKeyName = wurst.getZoomKey().getBoundKeyLocalizedText();
|
||||
|
||||
addDrawableChild(ButtonWidget
|
||||
.builder(Text.literal("Back"), b -> client.setScreen(prevScreen))
|
||||
.dimensions(width / 2 - 100, height / 4 + 144 - 16, 200, 20)
|
||||
.build());
|
||||
|
||||
addDrawableChild(keyButton = ButtonWidget
|
||||
.builder(Text.literal("Zoom Key: ").append(zoomKeyName),
|
||||
addDrawableChild(ButtonWidget
|
||||
.builder(
|
||||
Text.literal("Zoom Key: ")
|
||||
.append(zoom.getTranslatedKeybindName()),
|
||||
b -> client.setScreen(new PressAKeyScreen(this)))
|
||||
.dimensions(width / 2 - 79, height / 4 + 24 - 16, 158, 20).build());
|
||||
|
||||
@ -115,10 +113,8 @@ public class ZoomManagerScreen extends Screen implements PressAKeyCallback
|
||||
@Override
|
||||
public void setKey(String key)
|
||||
{
|
||||
WurstClient.INSTANCE.getZoomKey()
|
||||
.setBoundKey(InputUtil.fromTranslationKey(key));
|
||||
client.options.write();
|
||||
KeyBinding.updateKeysByCode();
|
||||
keyButton.setMessage(Text.literal("Zoom Key: " + key));
|
||||
WurstClient.INSTANCE.getOtfs().zoomOtf.setBoundKey(key);
|
||||
// Button text updates automatically because going back to this screen
|
||||
// calls init(). Might be different in older MC versions.
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,8 @@
|
||||
package net.wurstclient.other_features;
|
||||
|
||||
import net.minecraft.client.option.SimpleOption;
|
||||
import net.minecraft.client.util.InputUtil;
|
||||
import net.minecraft.text.Text;
|
||||
import net.wurstclient.DontBlock;
|
||||
import net.wurstclient.SearchTags;
|
||||
import net.wurstclient.events.MouseScrollListener;
|
||||
@ -15,6 +17,7 @@ import net.wurstclient.other_feature.OtherFeature;
|
||||
import net.wurstclient.settings.CheckboxSetting;
|
||||
import net.wurstclient.settings.SliderSetting;
|
||||
import net.wurstclient.settings.SliderSetting.ValueDisplay;
|
||||
import net.wurstclient.settings.TextFieldSetting;
|
||||
import net.wurstclient.util.MathUtils;
|
||||
|
||||
@SearchTags({"telescope", "optifine"})
|
||||
@ -25,10 +28,16 @@ public final class ZoomOtf extends OtherFeature implements MouseScrollListener
|
||||
50, 0.1, ValueDisplay.DECIMAL.withSuffix("x"));
|
||||
|
||||
private final CheckboxSetting scroll = new CheckboxSetting(
|
||||
"Use mouse wheel",
|
||||
"If enabled, you can use the mouse wheel while zooming to zoom in even further.",
|
||||
"Use mouse wheel", "If enabled, you can use the mouse wheel while"
|
||||
+ " zooming to zoom in even further.",
|
||||
true);
|
||||
|
||||
private final TextFieldSetting keybind = new TextFieldSetting("Keybind",
|
||||
"Determines the zoom keybind.\n\n"
|
||||
+ "Instead of editing this value manually, you should go to Wurst"
|
||||
+ " Options -> Zoom and set it there.",
|
||||
"key.keyboard.v", this::isValidKeybind);
|
||||
|
||||
private Double currentLevel;
|
||||
private Double defaultMouseSensitivity;
|
||||
|
||||
@ -39,6 +48,7 @@ public final class ZoomOtf extends OtherFeature implements MouseScrollListener
|
||||
+ "Go to Wurst Options -> Zoom to change this keybind.");
|
||||
addSetting(level);
|
||||
addSetting(scroll);
|
||||
addSetting(keybind);
|
||||
EVENTS.add(MouseScrollListener.class, this);
|
||||
}
|
||||
|
||||
@ -50,7 +60,7 @@ public final class ZoomOtf extends OtherFeature implements MouseScrollListener
|
||||
if(currentLevel == null)
|
||||
currentLevel = level.getValue();
|
||||
|
||||
if(!WURST.getZoomKey().isPressed())
|
||||
if(!isZoomKeyPressed())
|
||||
{
|
||||
currentLevel = level.getValue();
|
||||
|
||||
@ -78,7 +88,7 @@ public final class ZoomOtf extends OtherFeature implements MouseScrollListener
|
||||
@Override
|
||||
public void onMouseScroll(double amount)
|
||||
{
|
||||
if(!WURST.getZoomKey().isPressed() || !scroll.isChecked())
|
||||
if(!isZoomKeyPressed() || !scroll.isChecked())
|
||||
return;
|
||||
|
||||
if(currentLevel == null)
|
||||
@ -95,7 +105,36 @@ public final class ZoomOtf extends OtherFeature implements MouseScrollListener
|
||||
|
||||
public boolean shouldPreventHotbarScrolling()
|
||||
{
|
||||
return WURST.getZoomKey().isPressed() && scroll.isChecked();
|
||||
return isZoomKeyPressed() && scroll.isChecked();
|
||||
}
|
||||
|
||||
public Text getTranslatedKeybindName()
|
||||
{
|
||||
return InputUtil.fromTranslationKey(keybind.getValue())
|
||||
.getLocalizedText();
|
||||
}
|
||||
|
||||
public void setBoundKey(String translationKey)
|
||||
{
|
||||
keybind.setValue(translationKey);
|
||||
}
|
||||
|
||||
private boolean isZoomKeyPressed()
|
||||
{
|
||||
return InputUtil.isKeyPressed(MC.getWindow().getHandle(),
|
||||
InputUtil.fromTranslationKey(keybind.getValue()).getCode());
|
||||
}
|
||||
|
||||
private boolean isValidKeybind(String keybind)
|
||||
{
|
||||
try
|
||||
{
|
||||
return InputUtil.fromTranslationKey(keybind) != null;
|
||||
|
||||
}catch(IllegalArgumentException e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public SliderSetting getLevelSetting()
|
||||
|
@ -40,7 +40,6 @@
|
||||
"IngameHudMixin",
|
||||
"InGameOverlayRendererMixin",
|
||||
"KeyBindingMixin",
|
||||
"KeybindTextContentMixin",
|
||||
"KeyboardMixin",
|
||||
"LanguageManagerMixin",
|
||||
"LivingEntityRendererMixin",
|
||||
@ -63,7 +62,6 @@
|
||||
"TelemetryManagerMixin",
|
||||
"TextVisitFactoryMixin",
|
||||
"TitleScreenMixin",
|
||||
"TranslatableTextContentMixin",
|
||||
"WorldMixin",
|
||||
"WorldRendererMixin"
|
||||
],
|
||||
|
Loading…
Reference in New Issue
Block a user