Apply shared patch for all modloaders

This commit is contained in:
Aizistral
2026-08-19 15:01:03 +02:00
parent d7794faa43
commit 93df85c836
12 changed files with 177 additions and 285 deletions
@@ -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<UserFlag> 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();
}
}
@@ -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<UserApiService> 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<Boolean> info) {
@@ -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<UserFlag> 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<UserProperties> info) {
info.setReturnValue(FORCED_PROPERTIES);
}
@Inject(method = "newTelemetrySession", at = @At("HEAD"), cancellable = true)
private void onNewTelemetrySession(Executor executor, CallbackInfoReturnable<TelemetrySession> info) {
info.setReturnValue(TelemetrySession.DISABLED);
}
}
@@ -5,7 +5,8 @@
"minVersion": "0.8",
"mixins": [],
"client": [
"MixinMinecraft"
"MixinMinecraft",
"MixinYggdrasilUserApiService"
],
"injectors": {
"defaultRequire": 1
@@ -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<UserFlag> 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();
}
}
@@ -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<UserApiService> 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<Boolean> info) {
@@ -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<UserFlag> 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<UserProperties> info) {
info.setReturnValue(FORCED_PROPERTIES);
}
@Inject(method = "newTelemetrySession", at = @At("HEAD"), cancellable = true)
private void onNewTelemetrySession(Executor executor, CallbackInfoReturnable<TelemetrySession> info) {
info.setReturnValue(TelemetrySession.DISABLED);
}
}
@@ -5,7 +5,8 @@
"refmap": "nochatrestrictions.refmap.json",
"mixins": [],
"client": [
"MixinMinecraft"
"MixinMinecraft",
"MixinYggdrasilUserApiService"
],
"injectors": {
"defaultRequire": 1
@@ -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<UserFlag> 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();
}
}
@@ -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<UserApiService> 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<Boolean> info) {
@@ -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<UserFlag> 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<UserProperties> info) {
info.setReturnValue(FORCED_PROPERTIES);
}
@Inject(method = "newTelemetrySession", at = @At("HEAD"), cancellable = true)
private void onNewTelemetrySession(Executor executor, CallbackInfoReturnable<TelemetrySession> info) {
info.setReturnValue(TelemetrySession.DISABLED);
}
}
@@ -6,7 +6,8 @@
"refmap": "nochatrestrictions.refmap.json",
"mixins": [],
"client": [
"MixinMinecraft"
"MixinMinecraft",
"MixinYggdrasilUserApiService"
],
"injectors": {
"defaultRequire": 1