Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ $RECYCLE.BIN/

.gradle
build/
remappedSrc

# Ignore Gradle GUI config
gradle-app.setting
Expand Down
4 changes: 4 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ processResources {
}
}

loom {
accessWidenerPath = file("src/main/resources/moddetectionpreventer.accesswidener");
}

def targetJavaVersion = 17
tasks.withType(JavaCompile).configureEach {
it.options.encoding = "UTF-8"
Expand Down
8 changes: 4 additions & 4 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
org.gradle.jvmargs=-Xmx1G

minecraft_version=1.20.4
yarn_mappings=1.20.4+build.3
loader_version=0.15.7
minecraft_version=1.21.1
yarn_mappings=1.21.1+build.3
loader_version=0.16.9

mod_version = 1.2.0
mod_version = 2.0.1
archives_base_name = ModDetectionPreventer
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package me.wolfii.moddetectionpreventer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public final class ModDetectionPreventer {
private ModDetectionPreventer() { throw new UnsupportedOperationException("Consider this class abstract-final"); }

public static Logger LOGGER = LoggerFactory.getLogger("ModDetectionPreventer");


/// Called when the server tries to abuse the exploit.
public static void warnAccess(String action, String kind, String key) {
LOGGER.warn("{} incoming request for {} `{}`", action, kind, key);
}

}

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package me.wolfii.moddetectionpreventer.mixin.antidetection;

import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import me.wolfii.moddetectionpreventer.text.CombinedFilter;
import net.minecraft.client.gui.screen.ingame.AbstractSignEditScreen;
import net.minecraft.text.Text;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;

import java.util.function.Function;
import java.util.stream.Stream;


/// Catches incoming sign screens, filtering out components.
@Mixin(AbstractSignEditScreen.class)
class AbstractSignEditScreenMixin {

@WrapOperation(
method = "<init>(Lnet/minecraft/block/entity/SignBlockEntity;ZZLnet/minecraft/text/Text;)V",
at = @At(
value = "INVOKE",
target = "Ljava/util/stream/Stream;map(Ljava/util/function/Function;)Ljava/util/stream/Stream;"
)
)
private Stream<String> preventSignModDetection(Stream<Text> instance, Function<Text, String> function, Operation<Stream<String>> original) {
return original.call(
instance.map(CombinedFilter::filterComponents),
function
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package me.wolfii.moddetectionpreventer.mixin.antidetection;

import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import me.wolfii.moddetectionpreventer.text.CombinedFilter;
import net.minecraft.client.gui.screen.ingame.AnvilScreen;
import net.minecraft.text.Text;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;


/// Catches incoming anvil screens, filtering out components.
@Mixin(AnvilScreen.class)
class AnvilEditScreenMixin {

@WrapOperation(
method = "onSlotUpdate",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/text/Text;getString()Ljava/lang/String;"
)
)
private String preventAnvilItemNameChangeModDetection(Text instance, Operation<String> original) {
return original.call(CombinedFilter.filterComponents(instance));
}

@WrapOperation(
method = "onRenamed",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/text/Text;getString()Ljava/lang/String;"
)
)
private String preventAnvilItemNameCheckModDetection(Text instance, Operation<String> original) {
return original.call(CombinedFilter.filterComponents(instance));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package me.wolfii.moddetectionpreventer.mixin.antidetection;

import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import me.wolfii.moddetectionpreventer.text.CombinedFilter;
import net.minecraft.screen.AnvilScreenHandler;
import net.minecraft.text.Text;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;


/// Catches incoming anvil screens, filtering out components.
@Mixin(AnvilScreenHandler.class)
class AnvilScreenHandlerMixin {

@WrapOperation(
method = "updateResult",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/text/Text;getString()Ljava/lang/String;"
)
)
private String preventAnvilModDetection(Text instance, Operation<String> original) {
return original.call(CombinedFilter.filterComponents(instance));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package me.wolfii.moddetectionpreventer.mixin.datagetter;

import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import me.wolfii.moddetectionpreventer.ModDetectionPreventer;
import me.wolfii.moddetectionpreventer.text.KeybindFilter;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.option.GameOptions;
import net.minecraft.client.option.KeyBinding;
import net.minecraft.client.option.StickyKeyBinding;
import net.minecraft.client.util.InputUtil;
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;

import java.io.File;
import java.util.function.BooleanSupplier;


@Mixin(GameOptions.class)
class GameOptionsMixin {

/// When the vanilla keybindings start loading, reset the list of keybindings to pass through.
@Inject(
method = "<init>",
at = @At(
value = "INVOKE",
target = "Ljava/lang/Object;<init>()V",
shift = At.Shift.AFTER
)
)
private void resetAllowedKeys(MinecraftClient client, File optionsFile, CallbackInfo ci) {
KeybindFilter.unfilteredKeybindings.clear();
}

/// When the vanilla keybindings are initialised, keep a record of them.
@WrapOperation(
method = "<init>",
at = @At(
value = "NEW",
target = "(Ljava/lang/String;Lnet/minecraft/client/util/InputUtil$Type;ILjava/lang/String;)Lnet/minecraft/client/option/KeyBinding;"
)
)
private KeyBinding getAllowedKeys0(String translationKey, InputUtil.Type type, int code, String category, Operation<KeyBinding> original) {
KeyBinding keybinding = original.call(translationKey, type, code, category);
KeybindFilter.unfilteredKeybindings.put(translationKey, keybinding);
return keybinding;
}

/// When the vanilla keybindings are initialised, keep a record of them.
@WrapOperation(
method = "<init>",
at = @At(
value = "NEW",
target = "(Ljava/lang/String;ILjava/lang/String;)Lnet/minecraft/client/option/KeyBinding;"
)
)
private KeyBinding getAllowedKeys1(String translationKey, int code, String category, Operation<KeyBinding> original) {
KeyBinding keybinding = original.call(translationKey, code, category);
KeybindFilter.unfilteredKeybindings.put(translationKey, keybinding);
return keybinding;
}

/// When the vanilla keybindings are initialised, keep a record of them.
@WrapOperation(
method = "<init>",
at = @At(
value = "NEW",
target = "(Ljava/lang/String;ILjava/lang/String;Ljava/util/function/BooleanSupplier;)Lnet/minecraft/client/option/StickyKeyBinding;"
)
)
private StickyKeyBinding getAllowedKeys2(String translationKey, int code, String category, BooleanSupplier toggleGetter, Operation<StickyKeyBinding> original) {
StickyKeyBinding keybinding = original.call(translationKey, code, category, toggleGetter);
KeybindFilter.unfilteredKeybindings.put(translationKey, keybinding);
return keybinding;
}

}
Loading