Skip to content

Commit

Permalink
Yggdrasil Login (#229)
Browse files Browse the repository at this point in the history
  • Loading branch information
hexadecimal233 authored Mar 4, 2023
1 parent 4fbc7e3 commit 9c8b2a1
Show file tree
Hide file tree
Showing 13 changed files with 519 additions and 5 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@
- `Random Teleport, Hit Chance, Random Delay` (Removed from Meteor in [8722e](https://github.com/MeteorDevelopment/meteor-client/commit/8722ef565afa02ca4b6d9710a20fc9fcfd97bf05))
- AimAssist
- `Fov filter`
- Alts
- `Yggdrasil Login`

## Commands
- `.center`
Expand Down
54 changes: 54 additions & 0 deletions src/main/java/anticope/rejects/mixin/MinecraftClientAccessor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package anticope.rejects.mixin;

import com.mojang.authlib.minecraft.MinecraftSessionService;
import com.mojang.authlib.minecraft.UserApiService;
import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.SocialInteractionsManager;
import net.minecraft.client.report.AbuseReportContext;
import net.minecraft.client.texture.PlayerSkinProvider;
import net.minecraft.client.util.ProfileKeys;
import net.minecraft.client.util.Session;
import net.minecraft.network.encryption.SignatureVerifier;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.gen.Accessor;

@Mixin(MinecraftClient.class)
public interface MinecraftClientAccessor {
@Mutable
@Accessor("session")
void setSession(Session session);

@Mutable
@Accessor("sessionService")
void setSessionService(MinecraftSessionService sessionService);

@Mutable
@Accessor("authenticationService")
void setAuthenticationService(YggdrasilAuthenticationService authenticationService);

@Mutable
@Accessor("servicesSignatureVerifier")
void setServicesSignatureVerifier(SignatureVerifier servicesSignatureVerifier);

@Mutable
@Accessor("skinProvider")
void setSkinProvider(PlayerSkinProvider skinProvider);

@Mutable
@Accessor("socialInteractionsManager")
void setSocialInteractionsManager(SocialInteractionsManager socialInteractionsManager);

@Mutable
@Accessor("userApiService")
void setUserApiService(UserApiService userApiService);

@Mutable
@Accessor("abuseReportContext")
void setAbuseReportContext(AbuseReportContext abuseReportContext);

@Mutable
@Accessor("profileKeys")
void setProfileKeys(ProfileKeys profileKeys);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package anticope.rejects.mixin;

import net.minecraft.client.texture.PlayerSkinProvider;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;

import java.io.File;

@Mixin(PlayerSkinProvider.class)
public interface PlayerSkinProviderAccessor {
@Accessor("skinCacheDir")
File getSkinCacheDir();
}
16 changes: 16 additions & 0 deletions src/main/java/anticope/rejects/mixin/meteor/AccountMixin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package anticope.rejects.mixin.meteor;

import anticope.rejects.utils.accounts.CustomYggdrasilAccount;
import meteordevelopment.meteorclient.systems.accounts.Account;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg;

@Mixin(value = Account.class, remap = false)
public class AccountMixin {
@ModifyArg(method = "toTag", at = @At(value = "INVOKE", target = "Lnet/minecraft/nbt/NbtCompound;putString(Ljava/lang/String;Ljava/lang/String;)V", ordinal = 0), index = 1)
private String putString(String key) {
if ((Object) this instanceof CustomYggdrasilAccount) return "Yggdrasil";
return key;
}
}
23 changes: 23 additions & 0 deletions src/main/java/anticope/rejects/mixin/meteor/AccountsMixin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package anticope.rejects.mixin.meteor;

import anticope.rejects.utils.accounts.CustomYggdrasilAccount;
import meteordevelopment.meteorclient.systems.accounts.Account;
import meteordevelopment.meteorclient.systems.accounts.Accounts;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtElement;
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 org.spongepowered.asm.mixin.injection.callback.LocalCapture;

@Mixin(value = Accounts.class, remap = false)
public class AccountsMixin {
@Inject(method = "lambda$fromTag$0", at = @At(value = "INVOKE", target = "Lnet/minecraft/nbt/NbtCompound;getString(Ljava/lang/String;)Ljava/lang/String;"), locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true)
private static void onFromTag(NbtElement tag1, CallbackInfoReturnable<Account<?>> cir, NbtCompound t) {
if (t.getString("type").equals("Yggdrasil")) {
Account<CustomYggdrasilAccount> account = new CustomYggdrasilAccount(null, null, null).fromTag(t);
if (account.fetchInfo()) cir.setReturnValue(account);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package anticope.rejects.mixin.meteor;

import anticope.rejects.utils.accounts.AddCustomYggdrasilAccountScreen;
import meteordevelopment.meteorclient.gui.GuiTheme;
import meteordevelopment.meteorclient.gui.WindowScreen;
import meteordevelopment.meteorclient.gui.screens.AccountsScreen;
import meteordevelopment.meteorclient.gui.widgets.WWidget;
import meteordevelopment.meteorclient.gui.widgets.containers.WContainer;
import meteordevelopment.meteorclient.gui.widgets.containers.WHorizontalList;
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.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;

import static meteordevelopment.meteorclient.MeteorClient.mc;

@Mixin(value = AccountsScreen.class, remap = false)
public abstract class AccountsScreenMixin extends WindowScreen {
public AccountsScreenMixin(GuiTheme theme, WWidget icon, String title) {
super(theme, icon, title);
}

@Shadow
protected abstract void addButton(WContainer c, String text, Runnable action);

@Inject(method = "initWidgets", at = @At(value = "INVOKE", target = "Lmeteordevelopment/meteorclient/gui/screens/AccountsScreen;addButton(Lmeteordevelopment/meteorclient/gui/widgets/containers/WContainer;Ljava/lang/String;Ljava/lang/Runnable;)V", ordinal = 0), locals = LocalCapture.CAPTURE_FAILHARD)
private void afterAddCrackedButton(CallbackInfo info, WHorizontalList l) {
addButton(l, "Yggdrasil", () -> mc.setScreen(new AddCustomYggdrasilAccountScreen(theme, (AccountsScreen) (Object) this)));
}
}
21 changes: 21 additions & 0 deletions src/main/java/anticope/rejects/mixin/meteor/WAccountMixin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package anticope.rejects.mixin.meteor;

import anticope.rejects.utils.accounts.CustomYggdrasilAccount;
import meteordevelopment.meteorclient.gui.widgets.WAccount;
import meteordevelopment.meteorclient.systems.accounts.Account;
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.ModifyArg;

@Mixin(value = WAccount.class, remap = false)
public class WAccountMixin {
@Shadow @Final private Account<?> account;

@ModifyArg(method = "init", at = @At(value = "INVOKE", target = "Lmeteordevelopment/meteorclient/gui/GuiTheme;label(Ljava/lang/String;)Lmeteordevelopment/meteorclient/gui/widgets/WLabel;",ordinal = 1))
private String accountName(String text) {
if (account instanceof CustomYggdrasilAccount) return "(Yggdrasil)";
return text;
}
}
45 changes: 45 additions & 0 deletions src/main/java/anticope/rejects/utils/accounts/AccountUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package anticope.rejects.utils.accounts;

import anticope.rejects.mixin.MinecraftClientAccessor;
import anticope.rejects.mixin.PlayerSkinProviderAccessor;
import com.mojang.authlib.exceptions.AuthenticationException;
import com.mojang.authlib.minecraft.MinecraftSessionService;
import com.mojang.authlib.minecraft.UserApiService;
import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
import net.minecraft.client.network.SocialInteractionsManager;
import net.minecraft.client.report.AbuseReportContext;
import net.minecraft.client.report.ReporterEnvironment;
import net.minecraft.client.texture.PlayerSkinProvider;
import net.minecraft.client.util.ProfileKeys;
import net.minecraft.client.util.Session;
import net.minecraft.network.encryption.SignatureVerifier;

import java.io.File;

import static meteordevelopment.meteorclient.MeteorClient.mc;

public class AccountUtils {
public static MinecraftSessionService applyLoginEnvironment(YggdrasilAuthenticationService authService, MinecraftSessionService sessService, Session session) {
File skinDir = ((PlayerSkinProviderAccessor) mc.getSkinProvider()).getSkinCacheDir();
((MinecraftClientAccessor) mc).setSession(session);
((MinecraftClientAccessor) mc).setAuthenticationService(authService);
((MinecraftClientAccessor) mc).setSessionService(sessService);
((MinecraftClientAccessor) mc).setServicesSignatureVerifier(SignatureVerifier.create(authService.getServicesKey()));
((MinecraftClientAccessor) mc).setSkinProvider(new PlayerSkinProvider(mc.getTextureManager(), skinDir, sessService));
UserApiService apiService = createUserApiService(authService, session);
((MinecraftClientAccessor) mc).setUserApiService(apiService);
((MinecraftClientAccessor) mc).setSocialInteractionsManager(new SocialInteractionsManager(mc, apiService));
((MinecraftClientAccessor) mc).setProfileKeys(ProfileKeys.create(apiService, session, mc.runDirectory.toPath()));
((MinecraftClientAccessor) mc).setAbuseReportContext(AbuseReportContext.create(ReporterEnvironment.ofIntegratedServer(), apiService));
return sessService;
}

public static UserApiService createUserApiService(YggdrasilAuthenticationService authService, Session session) {
try {
return authService.createUserApiService(session.getAccessToken());
} catch (AuthenticationException e) {
return UserApiService.OFFLINE;
}
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package anticope.rejects.utils.accounts;

import meteordevelopment.meteorclient.gui.GuiTheme;
import meteordevelopment.meteorclient.gui.screens.AccountsScreen;
import meteordevelopment.meteorclient.gui.screens.AddAccountScreen;
import meteordevelopment.meteorclient.gui.widgets.containers.WTable;
import meteordevelopment.meteorclient.gui.widgets.input.WTextBox;
import meteordevelopment.meteorclient.systems.accounts.Accounts;

public class AddCustomYggdrasilAccountScreen extends AddAccountScreen {
public AddCustomYggdrasilAccountScreen(GuiTheme theme, AccountsScreen parent) {
super(theme, "Add Yggdrasil Account", parent);
}

@Override
public void initWidgets() {
WTable t = add(theme.table()).widget();

// Email
t.add(theme.label("Username / Email: "));
WTextBox username = t.add(theme.textBox("")).minWidth(400).expandX().widget();
username.setFocused(true);
t.row();

// Password
t.add(theme.label("Password: "));
WTextBox password = t.add(theme.textBox("")).minWidth(400).expandX().widget();
t.row();

// Password
t.add(theme.label("Server: "));
WTextBox server = t.add(theme.textBox("")).minWidth(400).expandX().widget();
t.row();

// Add
add = t.add(theme.button("Add")).expandX().widget();
add.action = () -> {
CustomYggdrasilAccount account = new CustomYggdrasilAccount(username.get(), password.get(), server.get());
if (!username.get().isEmpty() && !password.get().isEmpty() && !Accounts.get().exists(account)) {
AccountsScreen.addAccount(this, parent, account);
}
};

enterAction = add.action;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package anticope.rejects.utils.accounts;

import com.mojang.authlib.exceptions.AuthenticationException;
import meteordevelopment.meteorclient.MeteorClient;
import meteordevelopment.meteorclient.mixin.MinecraftClientAccessor;
import meteordevelopment.meteorclient.systems.accounts.Account;
import meteordevelopment.meteorclient.systems.accounts.AccountType;
import meteordevelopment.meteorclient.utils.misc.NbtException;
import net.minecraft.client.util.Session;
import net.minecraft.nbt.NbtCompound;

import static meteordevelopment.meteorclient.MeteorClient.mc;

public class CustomYggdrasilAccount extends Account<CustomYggdrasilAccount> {
private String password, server;

public CustomYggdrasilAccount(String name, String password, String server) {
super(AccountType.Cracked, name);
this.password = password;
this.server = server;
}

@Override
public boolean fetchInfo() {
try {
Session session = CustomYggdrasilLogin.login(name, password, server);

cache.username = session.getUsername();
cache.uuid = session.getUuid();

return true;
} catch (AuthenticationException e) {
return false;
}
}

@Override
public boolean login() {
try {
Session session = CustomYggdrasilLogin.login(name, password, server);
CustomYggdrasilLogin.LocalYggdrasilAuthenticationService service = new CustomYggdrasilLogin.LocalYggdrasilAuthenticationService(((MinecraftClientAccessor) mc).getProxy(), server);
CustomYggdrasilLogin.applyYggdrasilAccount(service, session);
cache.username = session.getUsername();
cache.loadHead();
return true;
} catch (AuthenticationException e) {
if (e.getMessage().contains("Invalid username or password") || e.getMessage().contains("account migrated"))
MeteorClient.LOG.error("Wrong password.");
else MeteorClient.LOG.error("Failed to contact the authentication server.");
return false;
}
}

@Override
public NbtCompound toTag() {
NbtCompound tag = super.toTag();

tag.putString("password", password);
tag.putString("server", server);

return tag;
}

@Override
public CustomYggdrasilAccount fromTag(NbtCompound tag) {
super.fromTag(tag);
if (!tag.contains("password")) throw new NbtException();

password = tag.getString("password");
server = tag.getString("server");

return this;
}

@Override
public boolean equals(Object o) {
if (!(o instanceof CustomYggdrasilAccount)) return false;
return ((CustomYggdrasilAccount) o).name.equals(this.name);
}
}
Loading

0 comments on commit 9c8b2a1

Please sign in to comment.