mirror of
https://github.com/AntiCope/meteor-rejects.git
synced 2025-09-06 12:25:49 +00:00
Yggdrasil Login (#229)
This commit is contained in:
@@ -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`
|
||||
|
@@ -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);
|
||||
}
|
@@ -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();
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@@ -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)));
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -0,0 +1,176 @@
|
||||
// Credit to https://github.com/IAFEnvoy/AccountSwitcher
|
||||
|
||||
package anticope.rejects.utils.accounts;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.gson.*;
|
||||
import com.mojang.authlib.Environment;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.exceptions.AuthenticationException;
|
||||
import com.mojang.authlib.minecraft.InsecureTextureException;
|
||||
import com.mojang.authlib.minecraft.MinecraftProfileTexture;
|
||||
import com.mojang.authlib.minecraft.MinecraftSessionService;
|
||||
import com.mojang.authlib.properties.Property;
|
||||
import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
|
||||
import com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService;
|
||||
import com.mojang.authlib.yggdrasil.response.MinecraftTexturesPayload;
|
||||
import com.mojang.util.UUIDTypeAdapter;
|
||||
import meteordevelopment.meteorclient.utils.network.Http;
|
||||
import net.minecraft.client.util.Session;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.net.Proxy;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PublicKey;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.util.*;
|
||||
|
||||
public class CustomYggdrasilLogin {
|
||||
public static Session login(String name, String password, String server) throws AuthenticationException {
|
||||
try {
|
||||
String url = server + "/authserver/authenticate";
|
||||
JsonObject agent = new JsonObject();
|
||||
agent.addProperty("name", "Minecraft");
|
||||
agent.addProperty("version", 1);
|
||||
|
||||
JsonObject root = new JsonObject();
|
||||
root.add("agent", agent);
|
||||
root.addProperty("username", name);
|
||||
root.addProperty("password", password);
|
||||
|
||||
String data = Http.post(url).bodyJson(root).sendString();
|
||||
JsonObject json = JsonParser.parseString(data).getAsJsonObject();
|
||||
if (json.has("error")) {
|
||||
throw new AuthenticationException(json.get("errorMessage").getAsString());
|
||||
}
|
||||
String token = json.get("accessToken").getAsString();
|
||||
String uuid = json.get("selectedProfile").getAsJsonObject().get("id").getAsString();
|
||||
String username = json.get("selectedProfile").getAsJsonObject().get("name").getAsString();
|
||||
return new Session(username, uuid, token, Optional.empty(), Optional.empty(), Session.AccountType.MOJANG);
|
||||
} catch (Exception e) {
|
||||
throw new AuthenticationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void applyYggdrasilAccount(LocalYggdrasilAuthenticationService authService, Session session) {
|
||||
MinecraftSessionService service = new LocalYggdrasilMinecraftSessionService(authService, authService.server);
|
||||
AccountUtils.applyLoginEnvironment(authService, service, session);
|
||||
}
|
||||
|
||||
public static class LocalYggdrasilApi implements Environment {
|
||||
private final String url;
|
||||
|
||||
public LocalYggdrasilApi(String serverUrl) {
|
||||
this.url = serverUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthHost() {
|
||||
return url + "/authserver";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccountsHost() {
|
||||
return url + "/api";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSessionHost() {
|
||||
return url + "/sessionserver";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServicesHost() {
|
||||
return url + "/minecraftservices";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Custom-Yggdrasil";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asString() {
|
||||
return new StringJoiner(", ", "", "")
|
||||
.add("authHost='" + getAuthHost() + "'")
|
||||
.add("accountsHost='" + getAccountsHost() + "'")
|
||||
.add("sessionHost='" + getSessionHost() + "'")
|
||||
.add("servicesHost='" + getServicesHost() + "'")
|
||||
.add("name='" + getName() + "'")
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public static class LocalYggdrasilMinecraftSessionService extends YggdrasilMinecraftSessionService {
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
private final PublicKey publicKey;
|
||||
private final Gson gson = new GsonBuilder().registerTypeAdapter(UUID.class, new UUIDTypeAdapter()).create();
|
||||
|
||||
public LocalYggdrasilMinecraftSessionService(YggdrasilAuthenticationService service, String serverUrl) {
|
||||
super(service, new LocalYggdrasilApi(serverUrl));
|
||||
String data = Http.get(serverUrl).sendString();
|
||||
JsonObject json = JsonParser.parseString(data).getAsJsonObject();
|
||||
this.publicKey = getPublicKey(json.get("signaturePublickey").getAsString());
|
||||
}
|
||||
|
||||
private static PublicKey getPublicKey(String key) {
|
||||
key = key.replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLIC KEY-----", "");
|
||||
try {
|
||||
byte[] byteKey = Base64.getDecoder().decode(key.replace("\n", ""));
|
||||
X509EncodedKeySpec spec = new X509EncodedKeySpec(byteKey);
|
||||
KeyFactory factory = KeyFactory.getInstance("RSA");
|
||||
return factory.generatePublic(spec);
|
||||
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<MinecraftProfileTexture.Type, MinecraftProfileTexture> getTextures(final GameProfile profile, final boolean requireSecure) {
|
||||
final Property textureProperty = Iterables.getFirst(profile.getProperties().get("textures"), null);
|
||||
|
||||
if (textureProperty == null)
|
||||
return new HashMap<>();
|
||||
|
||||
if (requireSecure) {
|
||||
if (!textureProperty.hasSignature()) {
|
||||
LOGGER.error("Signature is missing from textures payload");
|
||||
throw new InsecureTextureException("Signature is missing from textures payload");
|
||||
}
|
||||
if (!textureProperty.isSignatureValid(publicKey)) {
|
||||
LOGGER.error("Textures payload has been tampered with (signature invalid)");
|
||||
throw new InsecureTextureException("Textures payload has been tampered with (signature invalid)");
|
||||
}
|
||||
}
|
||||
|
||||
final MinecraftTexturesPayload result;
|
||||
try {
|
||||
final String json = new String(org.apache.commons.codec.binary.Base64.decodeBase64(textureProperty.getValue()), StandardCharsets.UTF_8);
|
||||
result = gson.fromJson(json, MinecraftTexturesPayload.class);
|
||||
} catch (final JsonParseException e) {
|
||||
LOGGER.error("Could not decode textures payload", e);
|
||||
return new HashMap<>();
|
||||
}
|
||||
|
||||
if (result == null || result.getTextures() == null)
|
||||
return new HashMap<>();
|
||||
|
||||
return result.getTextures();
|
||||
}
|
||||
}
|
||||
|
||||
public static class LocalYggdrasilAuthenticationService extends YggdrasilAuthenticationService {
|
||||
public final String server;
|
||||
|
||||
public LocalYggdrasilAuthenticationService(Proxy proxy, String server) {
|
||||
super(proxy, new LocalYggdrasilApi(server));
|
||||
this.server = server;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -3,18 +3,22 @@
|
||||
"package": "anticope.rejects.mixin.meteor",
|
||||
"compatibilityLevel": "JAVA_16",
|
||||
"client": [
|
||||
"AccountMixin",
|
||||
"AccountsMixin",
|
||||
"AccountsScreenMixin",
|
||||
"ConfigTabMixin",
|
||||
"DefaultSettingsWidgetFactoryMixin",
|
||||
"FontUtilsMixin",
|
||||
"GuiRendererAccessor",
|
||||
"HttpMixin",
|
||||
"ModuleMixin",
|
||||
"ModulesMixin",
|
||||
"FontUtilsMixin",
|
||||
"DefaultSettingsWidgetFactoryMixin",
|
||||
"modules.FlightMixin",
|
||||
"modules.NoRenderAccessor",
|
||||
"WAccountMixin",
|
||||
"modules.AimAssistMixin",
|
||||
"modules.AutoSignMixin",
|
||||
"modules.FlightMixin",
|
||||
"modules.InventoryTweaksMixin",
|
||||
"modules.KillAuraMixin",
|
||||
"modules.AimAssistMixin"
|
||||
"modules.NoRenderAccessor"
|
||||
]
|
||||
}
|
||||
|
@@ -12,9 +12,11 @@
|
||||
"GameRendererMixin",
|
||||
"LivingEntityMixin",
|
||||
"LivingEntityRendererMixin",
|
||||
"MinecraftClientAccessor",
|
||||
"MultiplayerScreenAccessor",
|
||||
"MultiplayerScreenMixin",
|
||||
"PlayerMoveC2SPacketAccessor",
|
||||
"PlayerSkinProviderAccessor",
|
||||
"ServerListAccessor",
|
||||
"StructureVoidBlockMixin",
|
||||
"TexturedRenderLayersMixin",
|
||||
|
Reference in New Issue
Block a user