Skip to content

Commit

Permalink
Added AntiToS - Censor player-generated text sources according to a c…
Browse files Browse the repository at this point in the history
…ontent blacklist.
  • Loading branch information
0xTas committed Apr 10, 2024
1 parent e9e20c9 commit 01b80b5
Show file tree
Hide file tree
Showing 6 changed files with 275 additions and 6 deletions.
1 change: 1 addition & 0 deletions src/main/java/dev/stardust/Stardust.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public void onInitialize() {

Modules.get().add(new Honker());
Modules.get().add(new WaxAura());
Modules.get().add(new AntiToS());
Modules.get().add(new AutoDoors());
Modules.get().add(new BookTools());
Modules.get().add(new ChatSigns());
Expand Down
21 changes: 15 additions & 6 deletions src/main/java/dev/stardust/mixin/BookScreenMixin.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.util.ArrayList;
import dev.stardust.Stardust;
import net.minecraft.text.Text;
import dev.stardust.modules.AntiToS;
import dev.stardust.util.StardustUtil;
import dev.stardust.modules.BookTools;
import org.spongepowered.asm.mixin.Mixin;
Expand Down Expand Up @@ -31,7 +32,7 @@ public abstract class BookScreenMixin extends Screen {
@Shadow
private BookScreen.Contents contents;

// See BookTools.java
// See BookTools.java && AntiToS.java
protected BookScreenMixin(Text title) { super(title); }


Expand All @@ -49,7 +50,6 @@ private void deobfuscateBook(ButtonWidget btn) {
return;
}

Stardust.LOG.debug("[Stardust] Deobfuscated book contents.");
if (contents instanceof BookScreen.WrittenBookContents) {
List<String> pages = ((WrittenBookContentsAccessor) contents).getPages();
List<String> deobfuscatedPages = new java.util.ArrayList<>(List.of());
Expand Down Expand Up @@ -92,10 +92,20 @@ private void reobfuscateBook(ButtonWidget btn) {
private void mixinInit(CallbackInfo ci) {
if (!(this.contents instanceof BookScreen.WrittenBookContents)) return;

List<String> pages = ((WrittenBookContentsAccessor) this.contents).getPages();
AntiToS antiToS = Modules.get().get(AntiToS.class);
BookTools bookTools = Modules.get().get(BookTools.class);
if (bookTools.skipDeobfuscation()) return;

List<String> pages = ((WrittenBookContentsAccessor) this.contents).getPages();
if (antiToS.isActive() && antiToS.booksSetting.get()) {
List<String> filtered = new ArrayList<>();
for (String page : pages) {
if (antiToS.containsBlacklistedText(page)) {
filtered.add(antiToS.censorText(page));
} else filtered.add(page);
}
((WrittenBookContentsAccessor) this.contents).setPages(filtered);
this.cachedPageIndex = -1;
} else if (bookTools.skipDeobfuscation()) return;

this.deobfuscateButton = this.addDrawableChild(
ButtonWidget.builder(
Expand All @@ -107,7 +117,7 @@ private void mixinInit(CallbackInfo ci) {

this.deobfuscateButton.visible = pages.get(this.pageIndex).contains("§k");
if (pages.stream().anyMatch(page -> page.contains("§k"))) {
this.obfuscatedPages = pages;
this.obfuscatedPages = ((WrittenBookContentsAccessor) this.contents).getPages();
}
}

Expand All @@ -120,7 +130,6 @@ private void mixinUpdatePageButtons(CallbackInfo ci) {
if (bookTools.skipDeobfuscation()) return;

List<String> pages = ((WrittenBookContentsAccessor) contents).getPages();

this.deobfuscateButton.visible = pages.get(this.pageIndex).contains("§k");
}
}
29 changes: 29 additions & 0 deletions src/main/java/dev/stardust/mixin/ChatHudMixin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package dev.stardust.mixin;

import net.minecraft.text.Text;
import dev.stardust.modules.AntiToS;
import org.spongepowered.asm.mixin.Mixin;
import net.minecraft.client.gui.hud.ChatHud;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import meteordevelopment.meteorclient.systems.modules.Modules;


/**
* @author Tas [0xTas] <[email protected]>
**/
@Mixin(ChatHud.class)
public class ChatHudMixin {

// See AntiToS.java
@ModifyVariable(
method = "addMessage(Lnet/minecraft/text/Text;Lnet/minecraft/network/message/MessageSignatureData;ILnet/minecraft/client/gui/hud/MessageIndicator;Z)V",
at = @At("HEAD"),
argsOnly = true
)
private Text censorChatMessage(Text message) {
AntiToS antiToS = Modules.get().get(AntiToS.class);
if (!antiToS.isActive() || !antiToS.chatSetting.get()) return message;
return (antiToS.containsBlacklistedText(message.getString()) ? Text.of(antiToS.censorText(message.getString())) : message);
}
}
35 changes: 35 additions & 0 deletions src/main/java/dev/stardust/mixin/SignBlockEntityRendererMixin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package dev.stardust.mixin;

import java.util.Arrays;
import net.minecraft.text.Text;
import java.util.stream.Collectors;
import dev.stardust.modules.AntiToS;
import org.spongepowered.asm.mixin.Mixin;
import net.minecraft.block.entity.SignText;
import org.spongepowered.asm.mixin.injection.At;
import net.minecraft.block.entity.SignBlockEntity;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import meteordevelopment.meteorclient.systems.modules.Modules;
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
import net.minecraft.client.render.block.entity.SignBlockEntityRenderer;


/**
* @author Tas [0xTas] <[email protected]>
**/
@Mixin(SignBlockEntityRenderer.class)
public abstract class SignBlockEntityRendererMixin implements BlockEntityRenderer<SignBlockEntity> {

// See AntiToS.java
@ModifyVariable(method = "renderText", at = @At("HEAD"), argsOnly = true)
private SignText modifyRenderedText(SignText signText) {
AntiToS antiToS = Modules.get().get(AntiToS.class);
if (!antiToS.isActive() || !antiToS.signsSetting.get()) return signText;

String testText = Arrays.stream(signText.getMessages(false))
.map(Text::getString)
.collect(Collectors.joining(" "))
.trim();
return antiToS.containsBlacklistedText(testText) ? antiToS.familyFriendlySignText(signText) : signText;
}
}
193 changes: 193 additions & 0 deletions src/main/java/dev/stardust/modules/AntiToS.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
package dev.stardust.modules;

import java.io.File;
import java.util.HashSet;
import java.nio.file.Files;
import dev.stardust.Stardust;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import net.minecraft.text.Text;
import net.minecraft.util.DyeColor;
import dev.stardust.util.StardustUtil;
import net.minecraft.block.entity.SignText;
import net.fabricmc.loader.api.FabricLoader;
import meteordevelopment.meteorclient.settings.*;
import meteordevelopment.meteorclient.systems.modules.Module;


/**
* @author Tas [0xTas] <[email protected]>
**/
public class AntiToS extends Module {
public AntiToS() { super(Stardust.CATEGORY, "AntiToS", "Censor player-generated text sources according to a content blacklist."); }

private final String BLACKLIST_FILE = "meteor-client/anti-tos.txt";

private final SettingGroup sgSources = settings.createGroup("Source Settings");
private final SettingGroup sgBlacklist = settings.createGroup("Content Settings");

public enum SignMode {
Censor, Replace
}

public final Setting<Boolean> chatSetting = sgSources.add(
new BoolSetting.Builder()
.name("Chat Messages")
.description("Censor text in chat if it matches the content blacklist.")
.defaultValue(true)
.build()
);

public final Setting<Boolean> booksSetting = sgSources.add(
new BoolSetting.Builder()
.name("Book Text")
.description("Censor text in books if it matches the content blacklist.")
.defaultValue(true)
.build()
);

public final Setting<Boolean> signsSetting = sgSources.add(
new BoolSetting.Builder()
.name("Sign Text")
.description("Filter sign text according to the content blacklist.")
.defaultValue(true)
.build()
);
private final Setting<SignMode> signMode = sgSources.add(
new EnumSetting.Builder<SignMode>()
.name("Sign Mode")
.description("Censor or completely replace SignText that matches the filter.")
.defaultValue(SignMode.Censor)
.visible(signsSetting::get)
.build()
);
private final Setting<String> familyFriendlyLine1 = sgSources.add(
new StringSetting.Builder()
.name("Replacement Line 1")
.defaultValue("Original text")
.visible(() -> signsSetting.get() && signMode.get() == SignMode.Replace)
.build()
);
private final Setting<String> familyFriendlyLine2 = sgSources.add(
new StringSetting.Builder()
.name("Replacement Line 2")
.defaultValue("was replaced by")
.visible(() -> signsSetting.get() && signMode.get() == SignMode.Replace)
.build()
);
private final Setting<String> familyFriendlyLine3 = sgSources.add(
new StringSetting.Builder()
.name("Replacement Line 3")
.defaultValue("Stardust AntiToS")
.visible(() -> signsSetting.get() && signMode.get() == SignMode.Replace)
.build()
);
private final Setting<String> familyFriendlyLine4 = sgSources.add(
new StringSetting.Builder()
.name("Replacement Line 4")
.defaultValue("plz no ban ☺")
.visible(() -> signsSetting.get() && signMode.get() == SignMode.Replace)
.build()
);
private final Setting<DyeColor> familyFriendlyColor = sgSources.add(
new EnumSetting.Builder<DyeColor>()
.name("Replacement Color")
.description("Render replacement SignText with the selected dye color.")
.defaultValue(DyeColor.RED)
.visible(() -> signsSetting.get() && signMode.get() == SignMode.Replace)
.build()
);
private final Setting<Boolean> familyFriendlyGlowing = sgSources.add(
new BoolSetting.Builder()
.name("Replacement Glowing")
.description("Render replacement SignText with glowing text.")
.defaultValue(true)
.visible(() -> signsSetting.get() && signMode.get() == SignMode.Replace)
.build()
);

private final Setting<Boolean> openBlacklistFile = sgBlacklist.add(
new BoolSetting.Builder()
.name("Open Blacklist File")
.description("Open the anti-tos.txt file.")
.defaultValue(false)
.onChanged(it -> {
if (it) {
if (StardustUtil.checkOrCreateFile(mc, BLACKLIST_FILE)) StardustUtil.openFile(mc, BLACKLIST_FILE);
resetBlacklistFileSetting();
}
})
.build()
);

private final HashSet<String> blacklisted = new HashSet<>();

private void resetBlacklistFileSetting() { openBlacklistFile.set(false); }

private void initBlacklistText() {
File blackListFile = FabricLoader.getInstance().getGameDir().resolve(BLACKLIST_FILE).toFile();

try(Stream<String> lineStream = Files.lines(blackListFile.toPath())) {
blacklisted.addAll(lineStream.toList());
if (blacklisted.isEmpty()) {
mc.player.sendMessage(Text.of("§8<"+StardustUtil.rCC()+"§o✨§r§8> §7"+BLACKLIST_FILE+" §4was empty§7!"));
mc.player.sendMessage(Text.of("§8<"+StardustUtil.rCC()+"§o✨§r§8> §7Please write one blacklisted item for each line of the file."));
mc.player.sendMessage(Text.of("§8<"+StardustUtil.rCC()+"§o✨§r§8> §7Spaces and other punctuation will be treated literally."));
mc.player.sendMessage(Text.of("§8<"+StardustUtil.rCC()+"§o✨§r§8> §7You must toggle this setting or the module after updating the blacklist's contents."));
}
}catch (Exception err) {
Stardust.LOG.error("[Stardust] Failed to read from "+ blackListFile.getAbsolutePath() +"! - Why:\n"+err);
}
}

// See ChatHudMixin.java
// && BookScreenMixin.java
// && SignBlockEntityRendererMixin.java
public boolean containsBlacklistedText(String text) {
return blacklisted.stream().anyMatch(line -> text.trim().toLowerCase().contains(line.trim().toLowerCase()));
}

public String censorText(String text) {
for (String filter : blacklisted) {
text = text.replaceAll("(?i)"+ Pattern.quote(filter), "*".repeat(filter.length()));
}
return text;
}

public SignText familyFriendlySignText(SignText original) {
if (signMode.get() == SignMode.Censor) {
Text[] lines = {
Text.of(censorText(original.getMessage(0, false).getString())),
Text.of(censorText(original.getMessage(1, false).getString())),
Text.of(censorText(original.getMessage(2, false).getString())),
Text.of(censorText(original.getMessage(3, false).getString()))
};
return new SignText(lines, lines, original.getColor(), original.isGlowing());
} else {
Text[] lines = {
Text.of(familyFriendlyLine1.get()),
Text.of(familyFriendlyLine2.get()),
Text.of(familyFriendlyLine3.get()),
Text.of(familyFriendlyLine4.get())
};
return new SignText(lines, lines, familyFriendlyColor.get(), familyFriendlyGlowing.get());
}
}

@Override
public void onActivate() {
if (StardustUtil.checkOrCreateFile(mc, BLACKLIST_FILE)) initBlacklistText();
else {
toggle();
mc.player.sendMessage(Text.of(
"§8[§4Stardust§8] §4§lFailed to create anti-tos.txt in your meteor-client folder§8!"
));
mc.player.sendMessage(Text.of(
"§8[§4Stardust§8] §4§lThis issue is fatal§8§l. §4§lPlease check latest.log for more info§8§l."
));
}
}

@Override
public void onDeactivate() { blacklisted.clear(); }
}
2 changes: 2 additions & 0 deletions src/main/resources/stardust.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"package": "dev.stardust.mixin",
"compatibilityLevel": "JAVA_17",
"client": [
"ChatHudMixin",
"BookScreenMixin",
"DrawContextMixin",
"SoundSystemMixin",
Expand All @@ -22,6 +23,7 @@
"ElytraSoundInstanceMixin",
"WrittenBookContentsAccessor",
"AbstractSignEditScreenMixin",
"SignBlockEntityRendererMixin",
"AbstractSignEditScreenAccessor",
"ClientPlayerInteractionManagerMixin"
],
Expand Down

0 comments on commit 01b80b5

Please sign in to comment.