From b9c00e334bc0c5307ca9228d3fe5e8476b0d7e43 Mon Sep 17 00:00:00 2001 From: Sw3ys Date: Tue, 30 Jun 2026 12:53:52 +0100 Subject: [PATCH 1/5] Create MixinYggdrasilUserApiService to remove restrictions This mixin modifies the YggdrasilUserApiService to remove chat and multiplayer restrictions by injecting custom user properties. It ensures that all instances of the service return permissive properties regardless of how they are created. --- .../mixins/MixinYggdrasilUserApiService.java | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 Fabric/src/main/java/com/aizistral/nochatrestrictions/mixins/MixinYggdrasilUserApiService.java diff --git a/Fabric/src/main/java/com/aizistral/nochatrestrictions/mixins/MixinYggdrasilUserApiService.java b/Fabric/src/main/java/com/aizistral/nochatrestrictions/mixins/MixinYggdrasilUserApiService.java new file mode 100644 index 0000000..6c968b3 --- /dev/null +++ b/Fabric/src/main/java/com/aizistral/nochatrestrictions/mixins/MixinYggdrasilUserApiService.java @@ -0,0 +1,51 @@ +package com.aizistral.nochatrestrictions.mixins; + +import java.util.Map; +import java.util.concurrent.Executor; + +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; + +import com.google.common.collect.ImmutableSet; +import com.mojang.authlib.minecraft.TelemetrySession; +import com.mojang.authlib.minecraft.UserApiService.UserFlag; +import com.mojang.authlib.minecraft.UserApiService.UserProperties; +import com.mojang.authlib.yggdrasil.YggdrasilUserApiService; + +/** + * Applies the chat/multiplayer restriction removal directly on the concrete + * service class instead of wrapping it once at {@code Minecraft.createUserApiService}. + * + * In-game account switchers (e.g. IAS) build a brand new {@link YggdrasilUserApiService} + * and swap it onto the Minecraft instance without going through the original wrapping + * path, which is why restrictions used to come back after switching accounts. By hooking + * the service class itself, every instance the game ever uses returns permissive + * properties, regardless of who created it or when. + */ +@Mixin(value = YggdrasilUserApiService.class, remap = false) +public class MixinYggdrasilUserApiService { + private static final UserProperties FORCED_PROPERTIES; + + static { + ImmutableSet.Builder flags = ImmutableSet.builder(); + + flags.add(UserFlag.CHAT_ALLOWED); // always let the player access chat + flags.add(UserFlag.SERVERS_ALLOWED); // always let the player open multiplayer menu + flags.add(UserFlag.REALMS_ALLOWED); // always let the player open Realms menu + + FORCED_PROPERTIES = new UserProperties(flags.build(), Map.of()); + } + + @Inject(method = "fetchProperties", at = @At("RETURN"), cancellable = true) + private void onFetchProperties(CallbackInfoReturnable info) { + info.setReturnValue(FORCED_PROPERTIES); + } + + @Inject(method = "newTelemetrySession", at = @At("HEAD"), cancellable = true) + private void onNewTelemetrySession(Executor executor, CallbackInfoReturnable info) { + info.setReturnValue(TelemetrySession.DISABLED); + } + +} From 2633a417206e17c92f491abd5387a19fad918112 Mon Sep 17 00:00:00 2001 From: Sw3ys Date: Tue, 30 Jun 2026 12:54:31 +0100 Subject: [PATCH 2/5] Add MixinYggdrasilUserApiService to client mixins --- Fabric/src/main/resources/nochatrestrictions.mixins.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Fabric/src/main/resources/nochatrestrictions.mixins.json b/Fabric/src/main/resources/nochatrestrictions.mixins.json index fca6bc9..9b967be 100644 --- a/Fabric/src/main/resources/nochatrestrictions.mixins.json +++ b/Fabric/src/main/resources/nochatrestrictions.mixins.json @@ -5,7 +5,8 @@ "minVersion": "0.8", "mixins": [], "client": [ - "MixinMinecraft" + "MixinMinecraft", + "MixinYggdrasilUserApiService" ], "injectors": { "defaultRequire": 1 @@ -13,4 +14,4 @@ "overwrites": { "requireAnnotations": true } -} \ No newline at end of file +} From fdfad28b976423ad6ff3fe22aa3580f3c5513df8 Mon Sep 17 00:00:00 2001 From: Aizistral Date: Wed, 19 Aug 2026 14:59:41 +0200 Subject: [PATCH 3/5] Revert "Add MixinYggdrasilUserApiService to client mixins" This reverts commit 2633a417206e17c92f491abd5387a19fad918112. --- Fabric/src/main/resources/nochatrestrictions.mixins.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Fabric/src/main/resources/nochatrestrictions.mixins.json b/Fabric/src/main/resources/nochatrestrictions.mixins.json index 9b967be..fca6bc9 100644 --- a/Fabric/src/main/resources/nochatrestrictions.mixins.json +++ b/Fabric/src/main/resources/nochatrestrictions.mixins.json @@ -5,8 +5,7 @@ "minVersion": "0.8", "mixins": [], "client": [ - "MixinMinecraft", - "MixinYggdrasilUserApiService" + "MixinMinecraft" ], "injectors": { "defaultRequire": 1 @@ -14,4 +13,4 @@ "overwrites": { "requireAnnotations": true } -} +} \ No newline at end of file From d7794faa43af2f31b2a9412e9c3f2ff927d6001c Mon Sep 17 00:00:00 2001 From: Aizistral Date: Wed, 19 Aug 2026 14:59:44 +0200 Subject: [PATCH 4/5] Revert "Create MixinYggdrasilUserApiService to remove restrictions" This reverts commit b9c00e334bc0c5307ca9228d3fe5e8476b0d7e43. --- .../mixins/MixinYggdrasilUserApiService.java | 51 ------------------- 1 file changed, 51 deletions(-) delete mode 100644 Fabric/src/main/java/com/aizistral/nochatrestrictions/mixins/MixinYggdrasilUserApiService.java diff --git a/Fabric/src/main/java/com/aizistral/nochatrestrictions/mixins/MixinYggdrasilUserApiService.java b/Fabric/src/main/java/com/aizistral/nochatrestrictions/mixins/MixinYggdrasilUserApiService.java deleted file mode 100644 index 6c968b3..0000000 --- a/Fabric/src/main/java/com/aizistral/nochatrestrictions/mixins/MixinYggdrasilUserApiService.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.aizistral.nochatrestrictions.mixins; - -import java.util.Map; -import java.util.concurrent.Executor; - -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; - -import com.google.common.collect.ImmutableSet; -import com.mojang.authlib.minecraft.TelemetrySession; -import com.mojang.authlib.minecraft.UserApiService.UserFlag; -import com.mojang.authlib.minecraft.UserApiService.UserProperties; -import com.mojang.authlib.yggdrasil.YggdrasilUserApiService; - -/** - * Applies the chat/multiplayer restriction removal directly on the concrete - * service class instead of wrapping it once at {@code Minecraft.createUserApiService}. - * - * In-game account switchers (e.g. IAS) build a brand new {@link YggdrasilUserApiService} - * and swap it onto the Minecraft instance without going through the original wrapping - * path, which is why restrictions used to come back after switching accounts. By hooking - * the service class itself, every instance the game ever uses returns permissive - * properties, regardless of who created it or when. - */ -@Mixin(value = YggdrasilUserApiService.class, remap = false) -public class MixinYggdrasilUserApiService { - private static final UserProperties FORCED_PROPERTIES; - - static { - ImmutableSet.Builder flags = ImmutableSet.builder(); - - flags.add(UserFlag.CHAT_ALLOWED); // always let the player access chat - flags.add(UserFlag.SERVERS_ALLOWED); // always let the player open multiplayer menu - flags.add(UserFlag.REALMS_ALLOWED); // always let the player open Realms menu - - FORCED_PROPERTIES = new UserProperties(flags.build(), Map.of()); - } - - @Inject(method = "fetchProperties", at = @At("RETURN"), cancellable = true) - private void onFetchProperties(CallbackInfoReturnable info) { - info.setReturnValue(FORCED_PROPERTIES); - } - - @Inject(method = "newTelemetrySession", at = @At("HEAD"), cancellable = true) - private void onNewTelemetrySession(Executor executor, CallbackInfoReturnable info) { - info.setReturnValue(TelemetrySession.DISABLED); - } - -} From 93df85c836c904b71614e586b42c65a743e39132 Mon Sep 17 00:00:00 2001 From: Aizistral Date: Wed, 19 Aug 2026 15:01:03 +0200 Subject: [PATCH 5/5] Apply shared patch for all modloaders --- .../core/WrappedUserApiService.java | 79 ------------------- .../mixins/MixinMinecraft.java | 18 +---- .../mixins/MixinYggdrasilUserApiService.java | 54 +++++++++++++ .../resources/nochatrestrictions.mixins.json | 3 +- .../core/WrappedUserApiService.java | 79 ------------------- .../mixins/MixinMinecraft.java | 18 +---- .../mixins/MixinYggdrasilUserApiService.java | 54 +++++++++++++ .../resources/nochatrestrictions.mixins.json | 3 +- .../core/WrappedUserApiService.java | 79 ------------------- .../mixins/MixinMinecraft.java | 18 +---- .../mixins/MixinYggdrasilUserApiService.java | 54 +++++++++++++ .../resources/nochatrestrictions.mixins.json | 3 +- 12 files changed, 177 insertions(+), 285 deletions(-) delete mode 100644 Fabric/src/main/java/com/aizistral/nochatrestrictions/core/WrappedUserApiService.java create mode 100644 Fabric/src/main/java/com/aizistral/nochatrestrictions/mixins/MixinYggdrasilUserApiService.java delete mode 100644 Forge/src/main/java/com/aizistral/nochatrestrictions/core/WrappedUserApiService.java create mode 100644 Forge/src/main/java/com/aizistral/nochatrestrictions/mixins/MixinYggdrasilUserApiService.java delete mode 100644 NeoForge/src/main/java/com/aizistral/nochatrestrictions/core/WrappedUserApiService.java create mode 100644 NeoForge/src/main/java/com/aizistral/nochatrestrictions/mixins/MixinYggdrasilUserApiService.java diff --git a/Fabric/src/main/java/com/aizistral/nochatrestrictions/core/WrappedUserApiService.java b/Fabric/src/main/java/com/aizistral/nochatrestrictions/core/WrappedUserApiService.java deleted file mode 100644 index e3e367d..0000000 --- a/Fabric/src/main/java/com/aizistral/nochatrestrictions/core/WrappedUserApiService.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.aizistral.nochatrestrictions.core; - -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.Executor; - -import com.google.common.collect.ImmutableSet; -import com.mojang.authlib.minecraft.TelemetrySession; -import com.mojang.authlib.minecraft.UserApiService; -import com.mojang.authlib.minecraft.report.AbuseReportLimits; -import com.mojang.authlib.yggdrasil.request.AbuseReportRequest; -import com.mojang.authlib.yggdrasil.response.KeyPairResponse; - -public class WrappedUserApiService implements UserApiService { - private static final UserProperties FORCED_PROPERTIES; - - static { - ImmutableSet.Builder flags = ImmutableSet.builder(); - - flags.add(UserFlag.CHAT_ALLOWED); // always let the player access chat - flags.add(UserFlag.SERVERS_ALLOWED); // always let the player open multiplayer menu - flags.add(UserFlag.REALMS_ALLOWED); // always let the player open Realms menu - // flags.add(UserFlag.TELEMETRY_ENABLED); // not adding this for obvious reasons - // flags.add(UserFlag.OPTIONAL_TELEMETRY_AVAILABLE); // thanks but no thanks - // flags.add(UserFlag.PROFANITY_FILTER_ENABLED) // not adding this one either - - FORCED_PROPERTIES = new UserProperties(flags.build(), Map.of()); - } - - private final UserApiService service; - - public WrappedUserApiService(UserApiService service) { - this.service = service; - } - - @Override - public UserProperties fetchProperties() { - return FORCED_PROPERTIES; - } - - @Override - public boolean isBlockedPlayer(UUID playerID) { - return this.service.isBlockedPlayer(playerID); - } - - @Override - public void refreshBlockList() { - this.service.refreshBlockList(); - } - - @Override - public TelemetrySession newTelemetrySession(Executor executor) { - return TelemetrySession.DISABLED; - } - - // Methods below primarily concern chat reporting. Not doing anything with them - // here as that's out of scope for this mod, it's more of a No Chat Reports thing - - @Override - public KeyPairResponse getKeyPair() { - return this.service.getKeyPair(); - } - - @Override - public void reportAbuse(AbuseReportRequest request) { - this.service.reportAbuse(request); - } - - @Override - public boolean canSendReports() { - return this.service.canSendReports(); - } - - @Override - public AbuseReportLimits getAbuseReportLimits() { - return this.service.getAbuseReportLimits(); - } - -} diff --git a/Fabric/src/main/java/com/aizistral/nochatrestrictions/mixins/MixinMinecraft.java b/Fabric/src/main/java/com/aizistral/nochatrestrictions/mixins/MixinMinecraft.java index eb2cebe..5e9761a 100644 --- a/Fabric/src/main/java/com/aizistral/nochatrestrictions/mixins/MixinMinecraft.java +++ b/Fabric/src/main/java/com/aizistral/nochatrestrictions/mixins/MixinMinecraft.java @@ -5,26 +5,14 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import com.aizistral.nochatrestrictions.core.NCRCore; -import com.aizistral.nochatrestrictions.core.WrappedUserApiService; -import com.mojang.authlib.minecraft.UserApiService; -import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; - import net.minecraft.client.Minecraft; -import net.minecraft.client.main.GameConfig; @Mixin(Minecraft.class) public class MixinMinecraft { - @Inject(method = { "m_193585_", "createUserApiService" }, at = @At("RETURN"), cancellable = true) - public void onCreateUserApi(YggdrasilAuthenticationService authService, GameConfig gameConfig, - CallbackInfoReturnable info) { - UserApiService returnedService = info.getReturnValue(); - assert returnedService != null; - info.setReturnValue(new WrappedUserApiService(returnedService)); - - NCRCore.LOGGER.info("Successfully supplanted UserApiService with a wrapped version."); - } + // Removal of multiplayer/chat/telemetry restrictions is handled in + // MixinYggdrasilUserApiService, so that it keeps working after in-game + // account switchers (e.g. IAS) replace the UserApiService instance. @Inject(method = { "m_294837_", "isNameBanned" }, at = @At("HEAD"), cancellable = true) public void onCheckNameBan(CallbackInfoReturnable info) { diff --git a/Fabric/src/main/java/com/aizistral/nochatrestrictions/mixins/MixinYggdrasilUserApiService.java b/Fabric/src/main/java/com/aizistral/nochatrestrictions/mixins/MixinYggdrasilUserApiService.java new file mode 100644 index 0000000..eda55bd --- /dev/null +++ b/Fabric/src/main/java/com/aizistral/nochatrestrictions/mixins/MixinYggdrasilUserApiService.java @@ -0,0 +1,54 @@ +package com.aizistral.nochatrestrictions.mixins; + +import java.util.Map; +import java.util.concurrent.Executor; + +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; + +import com.google.common.collect.ImmutableSet; +import com.mojang.authlib.minecraft.TelemetrySession; +import com.mojang.authlib.minecraft.UserApiService.UserFlag; +import com.mojang.authlib.minecraft.UserApiService.UserProperties; +import com.mojang.authlib.yggdrasil.YggdrasilUserApiService; + +/** + * Applies the chat/multiplayer restriction removal directly on the concrete + * service class instead of wrapping it once at {@code Minecraft.createUserApiService}. + * + * In-game account switchers (e.g. IAS) build a brand new {@link YggdrasilUserApiService} + * and swap it onto the Minecraft instance without going through the original wrapping + * path, which is why restrictions used to come back after switching accounts. By hooking + * the service class itself, every instance the game ever uses returns permissive + * properties, regardless of who created it or when. + */ +@Mixin(value = YggdrasilUserApiService.class, remap = false) +public class MixinYggdrasilUserApiService { + private static final UserProperties FORCED_PROPERTIES; + + static { + ImmutableSet.Builder flags = ImmutableSet.builder(); + + flags.add(UserFlag.CHAT_ALLOWED); // always let the player access chat + flags.add(UserFlag.SERVERS_ALLOWED); // always let the player open multiplayer menu + flags.add(UserFlag.REALMS_ALLOWED); // always let the player open Realms menu + // flags.add(UserFlag.TELEMETRY_ENABLED); // not adding this for obvious reasons + // flags.add(UserFlag.OPTIONAL_TELEMETRY_AVAILABLE); // thanks but no thanks + // flags.add(UserFlag.PROFANITY_FILTER_ENABLED) // not adding this one either + + FORCED_PROPERTIES = new UserProperties(flags.build(), Map.of()); + } + + @Inject(method = "fetchProperties", at = @At("RETURN"), cancellable = true) + private void onFetchProperties(CallbackInfoReturnable info) { + info.setReturnValue(FORCED_PROPERTIES); + } + + @Inject(method = "newTelemetrySession", at = @At("HEAD"), cancellable = true) + private void onNewTelemetrySession(Executor executor, CallbackInfoReturnable info) { + info.setReturnValue(TelemetrySession.DISABLED); + } + +} diff --git a/Fabric/src/main/resources/nochatrestrictions.mixins.json b/Fabric/src/main/resources/nochatrestrictions.mixins.json index fca6bc9..1e741e9 100644 --- a/Fabric/src/main/resources/nochatrestrictions.mixins.json +++ b/Fabric/src/main/resources/nochatrestrictions.mixins.json @@ -5,7 +5,8 @@ "minVersion": "0.8", "mixins": [], "client": [ - "MixinMinecraft" + "MixinMinecraft", + "MixinYggdrasilUserApiService" ], "injectors": { "defaultRequire": 1 diff --git a/Forge/src/main/java/com/aizistral/nochatrestrictions/core/WrappedUserApiService.java b/Forge/src/main/java/com/aizistral/nochatrestrictions/core/WrappedUserApiService.java deleted file mode 100644 index e3e367d..0000000 --- a/Forge/src/main/java/com/aizistral/nochatrestrictions/core/WrappedUserApiService.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.aizistral.nochatrestrictions.core; - -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.Executor; - -import com.google.common.collect.ImmutableSet; -import com.mojang.authlib.minecraft.TelemetrySession; -import com.mojang.authlib.minecraft.UserApiService; -import com.mojang.authlib.minecraft.report.AbuseReportLimits; -import com.mojang.authlib.yggdrasil.request.AbuseReportRequest; -import com.mojang.authlib.yggdrasil.response.KeyPairResponse; - -public class WrappedUserApiService implements UserApiService { - private static final UserProperties FORCED_PROPERTIES; - - static { - ImmutableSet.Builder flags = ImmutableSet.builder(); - - flags.add(UserFlag.CHAT_ALLOWED); // always let the player access chat - flags.add(UserFlag.SERVERS_ALLOWED); // always let the player open multiplayer menu - flags.add(UserFlag.REALMS_ALLOWED); // always let the player open Realms menu - // flags.add(UserFlag.TELEMETRY_ENABLED); // not adding this for obvious reasons - // flags.add(UserFlag.OPTIONAL_TELEMETRY_AVAILABLE); // thanks but no thanks - // flags.add(UserFlag.PROFANITY_FILTER_ENABLED) // not adding this one either - - FORCED_PROPERTIES = new UserProperties(flags.build(), Map.of()); - } - - private final UserApiService service; - - public WrappedUserApiService(UserApiService service) { - this.service = service; - } - - @Override - public UserProperties fetchProperties() { - return FORCED_PROPERTIES; - } - - @Override - public boolean isBlockedPlayer(UUID playerID) { - return this.service.isBlockedPlayer(playerID); - } - - @Override - public void refreshBlockList() { - this.service.refreshBlockList(); - } - - @Override - public TelemetrySession newTelemetrySession(Executor executor) { - return TelemetrySession.DISABLED; - } - - // Methods below primarily concern chat reporting. Not doing anything with them - // here as that's out of scope for this mod, it's more of a No Chat Reports thing - - @Override - public KeyPairResponse getKeyPair() { - return this.service.getKeyPair(); - } - - @Override - public void reportAbuse(AbuseReportRequest request) { - this.service.reportAbuse(request); - } - - @Override - public boolean canSendReports() { - return this.service.canSendReports(); - } - - @Override - public AbuseReportLimits getAbuseReportLimits() { - return this.service.getAbuseReportLimits(); - } - -} diff --git a/Forge/src/main/java/com/aizistral/nochatrestrictions/mixins/MixinMinecraft.java b/Forge/src/main/java/com/aizistral/nochatrestrictions/mixins/MixinMinecraft.java index e470410..ffc0934 100644 --- a/Forge/src/main/java/com/aizistral/nochatrestrictions/mixins/MixinMinecraft.java +++ b/Forge/src/main/java/com/aizistral/nochatrestrictions/mixins/MixinMinecraft.java @@ -5,26 +5,14 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import com.aizistral.nochatrestrictions.core.NCRCore; -import com.aizistral.nochatrestrictions.core.WrappedUserApiService; -import com.mojang.authlib.minecraft.UserApiService; -import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; - import net.minecraft.client.Minecraft; -import net.minecraft.client.main.GameConfig; @Mixin(value = Minecraft.class, remap = false) public class MixinMinecraft { - @Inject(method = { "m_193585_", "createUserApiService" }, at = @At("RETURN"), cancellable = true) - public void onCreateUserApi(YggdrasilAuthenticationService authService, GameConfig gameConfig, - CallbackInfoReturnable info) { - UserApiService returnedService = info.getReturnValue(); - assert returnedService != null; - info.setReturnValue(new WrappedUserApiService(returnedService)); - - NCRCore.LOGGER.info("Successfully supplanted UserApiService with a wrapped version."); - } + // Removal of multiplayer/chat/telemetry restrictions is handled in + // MixinYggdrasilUserApiService, so that it keeps working after in-game + // account switchers (e.g. IAS) replace the UserApiService instance. @Inject(method = { "m_294837_", "isNameBanned" }, at = @At("HEAD"), cancellable = true) public void onCheckNameBan(CallbackInfoReturnable info) { diff --git a/Forge/src/main/java/com/aizistral/nochatrestrictions/mixins/MixinYggdrasilUserApiService.java b/Forge/src/main/java/com/aizistral/nochatrestrictions/mixins/MixinYggdrasilUserApiService.java new file mode 100644 index 0000000..eda55bd --- /dev/null +++ b/Forge/src/main/java/com/aizistral/nochatrestrictions/mixins/MixinYggdrasilUserApiService.java @@ -0,0 +1,54 @@ +package com.aizistral.nochatrestrictions.mixins; + +import java.util.Map; +import java.util.concurrent.Executor; + +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; + +import com.google.common.collect.ImmutableSet; +import com.mojang.authlib.minecraft.TelemetrySession; +import com.mojang.authlib.minecraft.UserApiService.UserFlag; +import com.mojang.authlib.minecraft.UserApiService.UserProperties; +import com.mojang.authlib.yggdrasil.YggdrasilUserApiService; + +/** + * Applies the chat/multiplayer restriction removal directly on the concrete + * service class instead of wrapping it once at {@code Minecraft.createUserApiService}. + * + * In-game account switchers (e.g. IAS) build a brand new {@link YggdrasilUserApiService} + * and swap it onto the Minecraft instance without going through the original wrapping + * path, which is why restrictions used to come back after switching accounts. By hooking + * the service class itself, every instance the game ever uses returns permissive + * properties, regardless of who created it or when. + */ +@Mixin(value = YggdrasilUserApiService.class, remap = false) +public class MixinYggdrasilUserApiService { + private static final UserProperties FORCED_PROPERTIES; + + static { + ImmutableSet.Builder flags = ImmutableSet.builder(); + + flags.add(UserFlag.CHAT_ALLOWED); // always let the player access chat + flags.add(UserFlag.SERVERS_ALLOWED); // always let the player open multiplayer menu + flags.add(UserFlag.REALMS_ALLOWED); // always let the player open Realms menu + // flags.add(UserFlag.TELEMETRY_ENABLED); // not adding this for obvious reasons + // flags.add(UserFlag.OPTIONAL_TELEMETRY_AVAILABLE); // thanks but no thanks + // flags.add(UserFlag.PROFANITY_FILTER_ENABLED) // not adding this one either + + FORCED_PROPERTIES = new UserProperties(flags.build(), Map.of()); + } + + @Inject(method = "fetchProperties", at = @At("RETURN"), cancellable = true) + private void onFetchProperties(CallbackInfoReturnable info) { + info.setReturnValue(FORCED_PROPERTIES); + } + + @Inject(method = "newTelemetrySession", at = @At("HEAD"), cancellable = true) + private void onNewTelemetrySession(Executor executor, CallbackInfoReturnable info) { + info.setReturnValue(TelemetrySession.DISABLED); + } + +} diff --git a/Forge/src/main/resources/nochatrestrictions.mixins.json b/Forge/src/main/resources/nochatrestrictions.mixins.json index c9e96c5..c74587e 100644 --- a/Forge/src/main/resources/nochatrestrictions.mixins.json +++ b/Forge/src/main/resources/nochatrestrictions.mixins.json @@ -5,7 +5,8 @@ "refmap": "nochatrestrictions.refmap.json", "mixins": [], "client": [ - "MixinMinecraft" + "MixinMinecraft", + "MixinYggdrasilUserApiService" ], "injectors": { "defaultRequire": 1 diff --git a/NeoForge/src/main/java/com/aizistral/nochatrestrictions/core/WrappedUserApiService.java b/NeoForge/src/main/java/com/aizistral/nochatrestrictions/core/WrappedUserApiService.java deleted file mode 100644 index e3e367d..0000000 --- a/NeoForge/src/main/java/com/aizistral/nochatrestrictions/core/WrappedUserApiService.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.aizistral.nochatrestrictions.core; - -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.Executor; - -import com.google.common.collect.ImmutableSet; -import com.mojang.authlib.minecraft.TelemetrySession; -import com.mojang.authlib.minecraft.UserApiService; -import com.mojang.authlib.minecraft.report.AbuseReportLimits; -import com.mojang.authlib.yggdrasil.request.AbuseReportRequest; -import com.mojang.authlib.yggdrasil.response.KeyPairResponse; - -public class WrappedUserApiService implements UserApiService { - private static final UserProperties FORCED_PROPERTIES; - - static { - ImmutableSet.Builder flags = ImmutableSet.builder(); - - flags.add(UserFlag.CHAT_ALLOWED); // always let the player access chat - flags.add(UserFlag.SERVERS_ALLOWED); // always let the player open multiplayer menu - flags.add(UserFlag.REALMS_ALLOWED); // always let the player open Realms menu - // flags.add(UserFlag.TELEMETRY_ENABLED); // not adding this for obvious reasons - // flags.add(UserFlag.OPTIONAL_TELEMETRY_AVAILABLE); // thanks but no thanks - // flags.add(UserFlag.PROFANITY_FILTER_ENABLED) // not adding this one either - - FORCED_PROPERTIES = new UserProperties(flags.build(), Map.of()); - } - - private final UserApiService service; - - public WrappedUserApiService(UserApiService service) { - this.service = service; - } - - @Override - public UserProperties fetchProperties() { - return FORCED_PROPERTIES; - } - - @Override - public boolean isBlockedPlayer(UUID playerID) { - return this.service.isBlockedPlayer(playerID); - } - - @Override - public void refreshBlockList() { - this.service.refreshBlockList(); - } - - @Override - public TelemetrySession newTelemetrySession(Executor executor) { - return TelemetrySession.DISABLED; - } - - // Methods below primarily concern chat reporting. Not doing anything with them - // here as that's out of scope for this mod, it's more of a No Chat Reports thing - - @Override - public KeyPairResponse getKeyPair() { - return this.service.getKeyPair(); - } - - @Override - public void reportAbuse(AbuseReportRequest request) { - this.service.reportAbuse(request); - } - - @Override - public boolean canSendReports() { - return this.service.canSendReports(); - } - - @Override - public AbuseReportLimits getAbuseReportLimits() { - return this.service.getAbuseReportLimits(); - } - -} diff --git a/NeoForge/src/main/java/com/aizistral/nochatrestrictions/mixins/MixinMinecraft.java b/NeoForge/src/main/java/com/aizistral/nochatrestrictions/mixins/MixinMinecraft.java index eb2cebe..5e9761a 100644 --- a/NeoForge/src/main/java/com/aizistral/nochatrestrictions/mixins/MixinMinecraft.java +++ b/NeoForge/src/main/java/com/aizistral/nochatrestrictions/mixins/MixinMinecraft.java @@ -5,26 +5,14 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import com.aizistral.nochatrestrictions.core.NCRCore; -import com.aizistral.nochatrestrictions.core.WrappedUserApiService; -import com.mojang.authlib.minecraft.UserApiService; -import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; - import net.minecraft.client.Minecraft; -import net.minecraft.client.main.GameConfig; @Mixin(Minecraft.class) public class MixinMinecraft { - @Inject(method = { "m_193585_", "createUserApiService" }, at = @At("RETURN"), cancellable = true) - public void onCreateUserApi(YggdrasilAuthenticationService authService, GameConfig gameConfig, - CallbackInfoReturnable info) { - UserApiService returnedService = info.getReturnValue(); - assert returnedService != null; - info.setReturnValue(new WrappedUserApiService(returnedService)); - - NCRCore.LOGGER.info("Successfully supplanted UserApiService with a wrapped version."); - } + // Removal of multiplayer/chat/telemetry restrictions is handled in + // MixinYggdrasilUserApiService, so that it keeps working after in-game + // account switchers (e.g. IAS) replace the UserApiService instance. @Inject(method = { "m_294837_", "isNameBanned" }, at = @At("HEAD"), cancellable = true) public void onCheckNameBan(CallbackInfoReturnable info) { diff --git a/NeoForge/src/main/java/com/aizistral/nochatrestrictions/mixins/MixinYggdrasilUserApiService.java b/NeoForge/src/main/java/com/aizistral/nochatrestrictions/mixins/MixinYggdrasilUserApiService.java new file mode 100644 index 0000000..eda55bd --- /dev/null +++ b/NeoForge/src/main/java/com/aizistral/nochatrestrictions/mixins/MixinYggdrasilUserApiService.java @@ -0,0 +1,54 @@ +package com.aizistral.nochatrestrictions.mixins; + +import java.util.Map; +import java.util.concurrent.Executor; + +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; + +import com.google.common.collect.ImmutableSet; +import com.mojang.authlib.minecraft.TelemetrySession; +import com.mojang.authlib.minecraft.UserApiService.UserFlag; +import com.mojang.authlib.minecraft.UserApiService.UserProperties; +import com.mojang.authlib.yggdrasil.YggdrasilUserApiService; + +/** + * Applies the chat/multiplayer restriction removal directly on the concrete + * service class instead of wrapping it once at {@code Minecraft.createUserApiService}. + * + * In-game account switchers (e.g. IAS) build a brand new {@link YggdrasilUserApiService} + * and swap it onto the Minecraft instance without going through the original wrapping + * path, which is why restrictions used to come back after switching accounts. By hooking + * the service class itself, every instance the game ever uses returns permissive + * properties, regardless of who created it or when. + */ +@Mixin(value = YggdrasilUserApiService.class, remap = false) +public class MixinYggdrasilUserApiService { + private static final UserProperties FORCED_PROPERTIES; + + static { + ImmutableSet.Builder flags = ImmutableSet.builder(); + + flags.add(UserFlag.CHAT_ALLOWED); // always let the player access chat + flags.add(UserFlag.SERVERS_ALLOWED); // always let the player open multiplayer menu + flags.add(UserFlag.REALMS_ALLOWED); // always let the player open Realms menu + // flags.add(UserFlag.TELEMETRY_ENABLED); // not adding this for obvious reasons + // flags.add(UserFlag.OPTIONAL_TELEMETRY_AVAILABLE); // thanks but no thanks + // flags.add(UserFlag.PROFANITY_FILTER_ENABLED) // not adding this one either + + FORCED_PROPERTIES = new UserProperties(flags.build(), Map.of()); + } + + @Inject(method = "fetchProperties", at = @At("RETURN"), cancellable = true) + private void onFetchProperties(CallbackInfoReturnable info) { + info.setReturnValue(FORCED_PROPERTIES); + } + + @Inject(method = "newTelemetrySession", at = @At("HEAD"), cancellable = true) + private void onNewTelemetrySession(Executor executor, CallbackInfoReturnable info) { + info.setReturnValue(TelemetrySession.DISABLED); + } + +} diff --git a/NeoForge/src/main/resources/nochatrestrictions.mixins.json b/NeoForge/src/main/resources/nochatrestrictions.mixins.json index 8cdf752..c6f2888 100644 --- a/NeoForge/src/main/resources/nochatrestrictions.mixins.json +++ b/NeoForge/src/main/resources/nochatrestrictions.mixins.json @@ -6,7 +6,8 @@ "refmap": "nochatrestrictions.refmap.json", "mixins": [], "client": [ - "MixinMinecraft" + "MixinMinecraft", + "MixinYggdrasilUserApiService" ], "injectors": { "defaultRequire": 1