Skip to content

Commit

Permalink
Merge branch 'Wurst-Imperium:master' into murder-mystery
Browse files Browse the repository at this point in the history
  • Loading branch information
BlueGradientHorizon authored Mar 2, 2024
2 parents 612a1f3 + 86f3ae8 commit a6b885e
Show file tree
Hide file tree
Showing 13 changed files with 232 additions and 38 deletions.
6 changes: 3 additions & 3 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ org.gradle.parallel=true
# https://www.curseforge.com/minecraft/mc-mods/fabric-api
minecraft_version=1.20.4
yarn_mappings=1.20.4+build.3
loader_version=0.15.6
loader_version=0.15.7

#Fabric api
fabric_version=0.95.4+1.20.4
fabric_version=0.96.4+1.20.4

# Mod Properties
mod_version = v7.41-MC1.20.4
mod_version = v7.41.1-MC1.20.4
maven_group = net.wurstclient
archives_base_name = Wurst-Client

Expand Down
20 changes: 16 additions & 4 deletions src/main/java/net/wurstclient/WurstClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
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;

Expand Down Expand Up @@ -57,7 +58,7 @@ public enum WurstClient
public static MinecraftClient MC;
public static IMinecraftClient IMC;

public static final String VERSION = "7.41";
public static final String VERSION = "7.41.1";
public static final String MC_VERSION = "1.20.4";

private WurstAnalytics analytics;
Expand Down Expand Up @@ -175,18 +176,29 @@ private Path createWurstFolder()
return wurstFolder;
}

public String translate(String key)
public String translate(String key, Object... args)
{
if(otfs.translationsOtf.getForceEnglish().isChecked())
return ILanguageManager.getEnglish().get(key);
{
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);
return I18n.translate(key, args);
}

public WurstAnalytics getAnalytics()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,15 @@ public AltManagerScreen(Screen prevScreen, AltManager altManager)
public void init()
{
listGui = new ListGui(client, this, altManager.getList());
WurstClient wurst = WurstClient.INSTANCE;

Exception folderException = altManager.getFolderException();
if(folderException != null && shouldAsk)
{
Text title =
Text.translatable("gui.wurst.altmanager.folder_error.title");
Text message = Text.translatable(
"gui.wurst.altmanager.folder_error.message", folderException);
Text title = Text.literal(
wurst.translate("gui.wurst.altmanager.folder_error.title"));
Text message = Text.literal(wurst.translate(
"gui.wurst.altmanager.folder_error.message", folderException));
Text buttonText = Text.translatable("gui.done");

// This just sets shouldAsk to false and closes the message.
Expand All @@ -105,9 +106,10 @@ public void init()

}else if(altManager.getList().isEmpty() && shouldAsk)
{
Text title = Text.translatable("gui.wurst.altmanager.empty.title");
Text message =
Text.translatable("gui.wurst.altmanager.empty.message");
Text title = Text
.literal(wurst.translate("gui.wurst.altmanager.empty.title"));
Text message = Text
.literal(wurst.translate("gui.wurst.altmanager.empty.message"));
BooleanConsumer callback = this::confirmGenerate;

ConfirmScreen screen = new ConfirmScreen(callback, title, message);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ private ClientPlayNetworkHandlerMixin(WurstClient wurst,
public void onOnServerMetadata(ServerMetadataS2CPacket packet,
CallbackInfo ci)
{
if(!WurstClient.INSTANCE.isEnabled())
WurstClient wurst = WurstClient.INSTANCE;
if(!wurst.isEnabled())
return;

// Remove Mojang's dishonest warning toast on safe servers
Expand All @@ -58,10 +59,10 @@ public void onOnServerMetadata(ServerMetadataS2CPacket packet,
}

// Add an honest warning toast on unsafe servers
MutableText title = Text.literal(ChatUtils.WURST_PREFIX).append(
Text.translatable("toast.wurst.nochatreports.unsafe_server.title"));
MutableText message = Text
.translatable("toast.wurst.nochatreports.unsafe_server.message");
MutableText title = Text.literal(ChatUtils.WURST_PREFIX
+ wurst.translate("toast.wurst.nochatreports.unsafe_server.title"));
MutableText message = Text.literal(
wurst.translate("toast.wurst.nochatreports.unsafe_server.message"));

SystemToast systemToast = SystemToast.create(client,
SystemToast.Type.UNSECURE_SERVER_WARNING, title, message);
Expand Down
57 changes: 57 additions & 0 deletions src/main/java/net/wurstclient/mixin/ControlsListWidgetMixin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* 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.client.MinecraftClient;
import net.minecraft.client.gui.screen.option.ControlsListWidget;
import net.minecraft.client.gui.widget.ElementListWidget;
import net.minecraft.client.gui.widget.EntryListWidget;
import net.minecraft.text.Text;
import net.minecraft.text.TranslatableTextContent;
import net.wurstclient.WurstClient;

@Mixin(ControlsListWidget.class)
public abstract class ControlsListWidgetMixin
extends ElementListWidget<ControlsListWidget.Entry>
{
public ControlsListWidgetMixin(WurstClient wurst, MinecraftClient client,
int width, int height, int y, int itemHeight)
{
super(client, width, height, y, itemHeight);
}

/**
* Prevents Wurst's zoom keybind from being added to the controls list.
*/
@WrapOperation(at = @At(value = "INVOKE",
target = "Lnet/minecraft/client/gui/screen/option/ControlsListWidget;addEntry(Lnet/minecraft/client/gui/widget/EntryListWidget$Entry;)I",
ordinal = 1),
method = "<init>(Lnet/minecraft/client/gui/screen/option/KeybindsScreen;Lnet/minecraft/client/MinecraftClient;)V")
private int dontAddZoomEntry(ControlsListWidget instance,
EntryListWidget.Entry<?> entry, Operation<Integer> original)
{
if(!(entry instanceof ControlsListWidget.KeyBindingEntry kbEntry))
return original.call(instance, entry);

Text name = kbEntry.bindingName;
if(name == null || !(name
.getContent() instanceof TranslatableTextContent trContent))
return original.call(instance, entry);

if(!"key.wurst.zoom".equals(trContent.getKey()))
return original.call(instance, entry);

return 0;
}
}
56 changes: 56 additions & 0 deletions src/main/java/net/wurstclient/mixin/KeybindTextContentMixin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* 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));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* 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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,13 @@ public final class ForcedChatReportsScreen extends Screen

public ForcedChatReportsScreen(Screen prevScreen)
{
super(Text.literal(ChatUtils.WURST_PREFIX).append(
Text.translatable("gui.wurst.nochatreports.unsafe_server.title")));
super(Text.literal(ChatUtils.WURST_PREFIX)
.append(Text.literal(WurstClient.INSTANCE
.translate("gui.wurst.nochatreports.unsafe_server.title"))));
this.prevScreen = prevScreen;

reason =
Text.translatable("gui.wurst.nochatreports.unsafe_server.message");
reason = Text.literal(WurstClient.INSTANCE
.translate("gui.wurst.nochatreports.unsafe_server.message"));

NoChatReportsOtf ncr = WurstClient.INSTANCE.getOtfs().noChatReportsOtf;
sigButtonMsg = () -> WurstClient.INSTANCE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ public final class NcrModRequiredScreen extends Screen

public NcrModRequiredScreen(Screen prevScreen)
{
super(Text.literal(ChatUtils.WURST_PREFIX).append(
Text.translatable("gui.wurst.nochatreports.ncr_mod_server.title")));
super(Text.literal(ChatUtils.WURST_PREFIX + WurstClient.INSTANCE
.translate("gui.wurst.nochatreports.ncr_mod_server.title")));
this.prevScreen = prevScreen;

reason =
Text.translatable("gui.wurst.nochatreports.ncr_mod_server.message");
reason = Text.literal(WurstClient.INSTANCE
.translate("gui.wurst.nochatreports.ncr_mod_server.message"));

OtfList otfs = WurstClient.INSTANCE.getOtfs();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import net.wurstclient.Category;
import net.wurstclient.DontBlock;
import net.wurstclient.SearchTags;
import net.wurstclient.WurstClient;
import net.wurstclient.events.UpdateListener;
import net.wurstclient.other_feature.OtherFeature;
import net.wurstclient.settings.CheckboxSetting;
Expand Down Expand Up @@ -81,15 +80,15 @@ private void onLoginStart(ClientLoginNetworkHandler handler,
public MessageIndicator modifyIndicator(Text message,
MessageSignatureData signature, MessageIndicator indicator)
{
if(!WurstClient.INSTANCE.isEnabled() || MC.isInSingleplayer())
if(!WURST.isEnabled() || MC.isInSingleplayer())
return indicator;

if(indicator != null || signature == null)
return indicator;

return new MessageIndicator(0xE84F58, Icon.CHAT_MODIFIED,
Text.literal(ChatUtils.WURST_PREFIX + "\u00a7cReportable\u00a7r - ")
.append(Text.translatable(
Text.literal(ChatUtils.WURST_PREFIX + "\u00a7cReportable\u00a7r - "
+ WURST.translate(
"description.wurst.nochatreports.message_is_reportable")),
"Reportable");
}
Expand All @@ -102,8 +101,7 @@ public boolean isEnabled()

public boolean isActive()
{
return isEnabled() && WurstClient.INSTANCE.isEnabled()
&& !MC.isInSingleplayer();
return isEnabled() && WURST.isEnabled() && !MC.isInSingleplayer();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,6 @@ public boolean isWorking()
return !failed;
}

public boolean isOtherVersion()
{
return server.protocolVersion != 47;
}

public String getServerIP()
{
return server.address;
Expand Down
Loading

0 comments on commit a6b885e

Please sign in to comment.