@@ -97,10 +97,8 @@ public final class LauncherHelper {
|
||||
try {
|
||||
variables.set("account", account.logIn());
|
||||
} catch (ServerDisconnectException e) {
|
||||
if (account.canPlayOffline())
|
||||
variables.set("account", account.playOffline());
|
||||
else
|
||||
throw e;
|
||||
variables.set("account",
|
||||
account.playOffline().orElseThrow(() -> e));
|
||||
}
|
||||
} catch (AuthenticationException e) {
|
||||
variables.set("account", DialogController.logIn(account));
|
||||
|
||||
@@ -20,6 +20,7 @@ package org.jackhuang.hmcl.auth;
|
||||
import org.jackhuang.hmcl.util.ToStringBuilder;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
@@ -29,37 +30,38 @@ import java.util.UUID;
|
||||
public abstract class Account {
|
||||
|
||||
/**
|
||||
* @return the account name (mostly email)
|
||||
* @return the name of the account who owns the character
|
||||
*/
|
||||
public abstract String getUsername();
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the character name
|
||||
*/
|
||||
public abstract String getCharacter();
|
||||
|
||||
/**
|
||||
* @return the UUID
|
||||
* @return the character UUID
|
||||
*/
|
||||
public abstract UUID getUUID();
|
||||
|
||||
/**
|
||||
* log in.
|
||||
* @return the specific player's info.
|
||||
* @throws AuthenticationException if server error occurred.
|
||||
* Login with stored credentials.
|
||||
*
|
||||
* @throws ServerDisconnectException if an network error has occurred, in which case password login won't be tried.
|
||||
* @throws AuthenticationException if an error has occurred. If it's not a {@link ServerDisconnectException}, password login will be tried.
|
||||
*/
|
||||
public abstract AuthInfo logIn() throws AuthenticationException;
|
||||
public abstract AuthInfo logIn() throws ServerDisconnectException, AuthenticationException;
|
||||
|
||||
/**
|
||||
* Login with specified password.
|
||||
*/
|
||||
public abstract AuthInfo logInWithPassword(String password) throws AuthenticationException;
|
||||
|
||||
public abstract boolean canPlayOffline();
|
||||
|
||||
/**
|
||||
* Play offline.
|
||||
* @return the specific offline player's info.
|
||||
*/
|
||||
public abstract AuthInfo playOffline();
|
||||
public abstract Optional<AuthInfo> playOffline();
|
||||
|
||||
public abstract Map<Object, Object> toStorage();
|
||||
|
||||
|
||||
@@ -20,23 +20,24 @@ package org.jackhuang.hmcl.auth;
|
||||
import org.jackhuang.hmcl.auth.yggdrasil.GameProfile;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Select character by name.
|
||||
*/
|
||||
public class SpecificCharacterSelector implements CharacterSelector {
|
||||
private final String id;
|
||||
private UUID uuid;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param id character's name.
|
||||
* @param uuid character's uuid.
|
||||
*/
|
||||
public SpecificCharacterSelector(String id) {
|
||||
this.id = id;
|
||||
public SpecificCharacterSelector(UUID uuid) {
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GameProfile select(Account account, List<GameProfile> names) throws NoSelectedCharacterException {
|
||||
return names.stream().filter(profile -> profile.getName().equals(id)).findAny().orElseThrow(() -> new NoSelectedCharacterException(account));
|
||||
return names.stream().filter(profile -> profile.getId().equals(uuid)).findAny().orElseThrow(() -> new NoSelectedCharacterException(account));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.jackhuang.hmcl.util.NetworkUtils;
|
||||
|
||||
import java.util.Base64;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
@@ -39,8 +40,8 @@ public class AuthlibInjectorAccount extends YggdrasilAccount {
|
||||
private final String serverBaseURL;
|
||||
private final ExceptionalSupplier<String, ?> injectorJarPath;
|
||||
|
||||
protected AuthlibInjectorAccount(YggdrasilService service, String serverBaseURL, ExceptionalSupplier<String, ?> injectorJarPath, String username, String character, YggdrasilSession session) {
|
||||
super(service, username, character, session);
|
||||
protected AuthlibInjectorAccount(YggdrasilService service, String serverBaseURL, ExceptionalSupplier<String, ?> injectorJarPath, String username, UUID characterUUID, YggdrasilSession session) {
|
||||
super(service, username, characterUUID, session);
|
||||
|
||||
this.injectorJarPath = injectorJarPath;
|
||||
this.serverBaseURL = serverBaseURL;
|
||||
@@ -66,11 +67,10 @@ public class AuthlibInjectorAccount extends YggdrasilAccount {
|
||||
try {
|
||||
thread.join();
|
||||
|
||||
String arg = "-javaagent:" + injectorJarPath.get() + "=" + serverBaseURL;
|
||||
Arguments arguments = Arguments.addJVMArguments(null, arg);
|
||||
Arguments arguments = new Arguments().addJVMArguments("-javaagent:" + injectorJarPath.get() + "=" + serverBaseURL);
|
||||
|
||||
if (flag.get())
|
||||
arguments = Arguments.addJVMArguments(arguments, "-Dorg.to2mbn.authlibinjector.config.prefetched=" + new String(Base64.getEncoder().encode(getTask.getResult().getBytes()), UTF_8));
|
||||
arguments = arguments.addJVMArguments("-Dorg.to2mbn.authlibinjector.config.prefetched=" + new String(Base64.getEncoder().encode(getTask.getResult().getBytes()), UTF_8));
|
||||
|
||||
return info.withArguments(arguments);
|
||||
} catch (Exception e) {
|
||||
|
||||
@@ -42,14 +42,14 @@ public class AuthlibInjectorAccountFactory extends AccountFactory<AuthlibInjecto
|
||||
Objects.requireNonNull(storage);
|
||||
Objects.requireNonNull(proxy);
|
||||
|
||||
YggdrasilSession session = YggdrasilSession.fromStorage(storage);
|
||||
|
||||
String username = tryCast(storage.get("username"), String.class)
|
||||
.orElseThrow(() -> new IllegalArgumentException("storage does not have username"));
|
||||
String character = tryCast(storage.get("character"), String.class)
|
||||
.orElseThrow(() -> new IllegalArgumentException("storage does not have selected character name."));
|
||||
String apiRoot = tryCast(storage.get("serverBaseURL"), String.class)
|
||||
.orElseThrow(() -> new IllegalArgumentException("storage does not have API root."));
|
||||
|
||||
return new AuthlibInjectorAccount(new YggdrasilService(new AuthlibInjectorProvider(apiRoot), proxy),
|
||||
apiRoot, injectorJarPathSupplier, username, character, YggdrasilSession.fromStorage(storage));
|
||||
apiRoot, injectorJarPathSupplier, username, session.getSelectedProfile().getId(), session);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.jackhuang.hmcl.util.UUIDTypeAdapter;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.jackhuang.hmcl.util.Lang.mapOf;
|
||||
@@ -80,13 +81,8 @@ public class OfflineAccount extends Account {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPlayOffline() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthInfo playOffline() {
|
||||
throw new IllegalStateException();
|
||||
public Optional<AuthInfo> playOffline() {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -33,13 +33,13 @@ public class YggdrasilAccount extends Account {
|
||||
private final YggdrasilService service;
|
||||
private boolean isOnline = false;
|
||||
private YggdrasilSession session;
|
||||
private String character;
|
||||
private UUID characterUUID;
|
||||
|
||||
protected YggdrasilAccount(YggdrasilService service, String username, String character, YggdrasilSession session) {
|
||||
protected YggdrasilAccount(YggdrasilService service, String username, UUID characterUUID, YggdrasilSession session) {
|
||||
this.service = service;
|
||||
this.username = username;
|
||||
this.session = session;
|
||||
this.character = character;
|
||||
this.characterUUID = characterUUID;
|
||||
|
||||
if (session == null || session.getSelectedProfile() == null || StringUtils.isBlank(session.getAccessToken()))
|
||||
this.session = null;
|
||||
@@ -67,14 +67,14 @@ public class YggdrasilAccount extends Account {
|
||||
public AuthInfo logIn() throws AuthenticationException {
|
||||
if (!canPlayOnline()) {
|
||||
logInWithToken();
|
||||
selectProfile(new SpecificCharacterSelector(character));
|
||||
selectProfile(new SpecificCharacterSelector(characterUUID));
|
||||
}
|
||||
return session.toAuthInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final AuthInfo logInWithPassword(String password) throws AuthenticationException {
|
||||
return logInWithPassword(password, new SpecificCharacterSelector(character));
|
||||
return logInWithPassword(password, new SpecificCharacterSelector(characterUUID));
|
||||
}
|
||||
|
||||
protected AuthInfo logInWithPassword(String password, CharacterSelector selector) throws AuthenticationException {
|
||||
@@ -91,7 +91,7 @@ public class YggdrasilAccount extends Account {
|
||||
session = service.refresh(session.getAccessToken(), session.getClientToken(), selector.select(this, Arrays.asList(session.getAvailableProfiles())));
|
||||
}
|
||||
|
||||
character = session.getSelectedProfile().getName();
|
||||
characterUUID = session.getSelectedProfile().getId();
|
||||
}
|
||||
|
||||
private void logInWithToken() throws AuthenticationException {
|
||||
@@ -103,27 +103,21 @@ public class YggdrasilAccount extends Account {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPlayOffline() {
|
||||
return isLoggedIn() && session.getSelectedProfile() != null && !canPlayOnline();
|
||||
}
|
||||
public Optional<AuthInfo> playOffline() {
|
||||
if (isLoggedIn() && session.getSelectedProfile() != null && !canPlayOnline())
|
||||
return Optional.of(session.toAuthInfo());
|
||||
|
||||
@Override
|
||||
public AuthInfo playOffline() {
|
||||
if (!canPlayOffline())
|
||||
throw new IllegalStateException("Current account " + this + " cannot play offline.");
|
||||
|
||||
return session.toAuthInfo();
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Object, Object> toStorage() {
|
||||
if (session == null)
|
||||
throw new IllegalStateException("No session is specified");
|
||||
|
||||
HashMap<Object, Object> storage = new HashMap<>();
|
||||
|
||||
storage.put("username", getUsername());
|
||||
storage.put("character", character);
|
||||
if (session != null)
|
||||
storage.putAll(session.toStorage());
|
||||
|
||||
storage.putAll(session.toStorage());
|
||||
return storage;
|
||||
}
|
||||
|
||||
|
||||
@@ -58,12 +58,12 @@ public class YggdrasilAccountFactory extends AccountFactory<YggdrasilAccount> {
|
||||
Objects.requireNonNull(storage);
|
||||
Objects.requireNonNull(proxy);
|
||||
|
||||
YggdrasilSession session = YggdrasilSession.fromStorage(storage);
|
||||
|
||||
String username = tryCast(storage.get("username"), String.class)
|
||||
.orElseThrow(() -> new IllegalArgumentException("storage does not have username"));
|
||||
String character = tryCast(storage.get("character"), String.class)
|
||||
.orElseThrow(() -> new IllegalArgumentException("storage does not have selected character name."));
|
||||
|
||||
return new YggdrasilAccount(new YggdrasilService(provider, proxy), username, character, YggdrasilSession.fromStorage(storage));
|
||||
return new YggdrasilAccount(new YggdrasilService(provider, proxy), username, session.getSelectedProfile().getId(), session);
|
||||
}
|
||||
|
||||
public static String randomToken() {
|
||||
|
||||
@@ -54,28 +54,22 @@ public final class Arguments {
|
||||
return jvm == null ? Collections.emptyList() : Collections.unmodifiableList(jvm);
|
||||
}
|
||||
|
||||
public static Arguments addGameArguments(Arguments arguments, String... gameArguments) {
|
||||
return addGameArguments(arguments, Arrays.asList(gameArguments));
|
||||
public Arguments addGameArguments(String... gameArguments) {
|
||||
return addGameArguments(Arrays.asList(gameArguments));
|
||||
}
|
||||
|
||||
public static Arguments addGameArguments(Arguments arguments, List<String> gameArguments) {
|
||||
public Arguments addGameArguments(List<String> gameArguments) {
|
||||
List<Argument> list = gameArguments.stream().map(StringArgument::new).collect(Collectors.toList());
|
||||
if (arguments == null)
|
||||
return new Arguments(list, null);
|
||||
else
|
||||
return new Arguments(Lang.merge(arguments.getGame(), list), arguments.getJvm());
|
||||
return new Arguments(Lang.merge(getGame(), list), getJvm());
|
||||
}
|
||||
|
||||
public static Arguments addJVMArguments(Arguments arguments, String... jvmArguments) {
|
||||
return addJVMArguments(arguments, Arrays.asList(jvmArguments));
|
||||
public Arguments addJVMArguments(String... jvmArguments) {
|
||||
return addJVMArguments(Arrays.asList(jvmArguments));
|
||||
}
|
||||
|
||||
public static Arguments addJVMArguments(Arguments arguments, List<String> jvmArguments) {
|
||||
public Arguments addJVMArguments(List<String> jvmArguments) {
|
||||
List<Argument> list = jvmArguments.stream().map(StringArgument::new).collect(Collectors.toList());
|
||||
if (arguments == null)
|
||||
return new Arguments(null, list);
|
||||
else
|
||||
return new Arguments(arguments.getGame(), Lang.merge(arguments.getJvm(), list));
|
||||
return new Arguments(getGame(), Lang.merge(getJvm(), list));
|
||||
}
|
||||
|
||||
public static Arguments merge(Arguments a, Arguments b) {
|
||||
|
||||
@@ -109,7 +109,7 @@ public final class MultiMCModpackInstallTask extends Task {
|
||||
version = version
|
||||
.setLibraries(Lang.merge(version.getLibraries(), patch.getLibraries()))
|
||||
.setMainClass(patch.getMainClass())
|
||||
.setArguments(Arguments.addGameArguments(version.getArguments().orElse(null), newArguments));
|
||||
.setArguments(version.getArguments().orElseGet(Arguments::new).addGameArguments(newArguments));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user