1
0
mirror of https://github.com/SKCraft/Launcher.git synced 2025-01-05 19:09:03 +01:00

Fix persistence, download & persist avatar locally

This commit is contained in:
Henry Le Grys 2021-02-08 20:38:49 +00:00
parent b6252863da
commit 18a99b338e
10 changed files with 78 additions and 27 deletions

View File

@ -42,4 +42,9 @@ subprojects {
options.addStringOption('Xdoclint:none', '-quiet')
}
}
tasks.withType(JavaExec) {
workingDir = new File(rootDir, "run/")
workingDir.mkdirs()
}
}

View File

@ -5,7 +5,9 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.skcraft.launcher.dialog.component.ListListenerReducer;
import com.skcraft.launcher.persistence.Scrambled;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.apache.commons.lang.RandomStringUtils;
import javax.swing.*;
@ -17,7 +19,9 @@ import java.util.List;
* Persisted account list
*/
@Scrambled("ACCOUNT_LIST_NOT_SECURITY!")
@Data
@Getter
@Setter
@ToString
@JsonIgnoreProperties(ignoreUnknown = true)
public class NewAccountList implements ListModel<SavedSession> {
private List<SavedSession> accounts = Lists.newArrayList();

View File

@ -62,6 +62,11 @@ public class OfflineSession implements Session {
return UserType.LEGACY;
}
@Override
public String getAvatarImage() {
return null;
}
@Override
public boolean isOnline() {
return false;

View File

@ -1,9 +1,12 @@
package com.skcraft.launcher.auth;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import org.apache.commons.lang.builder.HashCodeBuilder;
import java.util.Base64;
/**
* Represents a session saved to disk.
*/
@ -15,6 +18,12 @@ public class SavedSession {
private String username;
private String accessToken;
private String refreshToken;
private String avatarImage;
@JsonIgnore
public byte[] getAvatarBytes() {
return Base64.getDecoder().decode(avatarImage);
}
@Override
public boolean equals(Object o) {

View File

@ -64,6 +64,13 @@ public interface Session {
*/
UserType getUserType();
/**
* Get the user's avatar
*
* @return User's avatar as a base64 string.
*/
String getAvatarImage();
/**
* Return true if the user is in an online session.
*
@ -82,6 +89,7 @@ public interface Session {
savedSession.setUsername(getName());
savedSession.setUuid(getUuid());
savedSession.setAccessToken(getAccessToken());
savedSession.setAvatarImage(getAvatarImage());
return savedSession;
}

View File

@ -0,0 +1,22 @@
package com.skcraft.launcher.auth;
import com.skcraft.launcher.util.HttpRequest;
import java.io.IOException;
import java.util.Base64;
import static com.skcraft.launcher.util.HttpRequest.url;
public class VisageSkinService {
public static String fetchSkinHead(String uuid) throws IOException, InterruptedException {
String skinUrl = String.format("https://visage.surgeplay.com/face/32/%s.png", uuid);
byte[] skinBytes = HttpRequest.get(url(skinUrl))
.execute()
.expectResponseCode(200)
.returnContent()
.asBytes();
return Base64.getEncoder().encodeToString(skinBytes);
}
}

View File

@ -9,7 +9,7 @@ package com.skcraft.launcher.auth;
import com.fasterxml.jackson.annotation.*;
import com.skcraft.launcher.util.HttpRequest;
import lombok.Data;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.ToString;
import lombok.extern.java.Log;
@ -22,27 +22,17 @@ import java.util.Map;
* Creates authenticated sessions using the Mojang Yggdrasil login protocol.
*/
@Log
@RequiredArgsConstructor
public class YggdrasilLoginService implements LoginService {
private final URL authUrl;
private final String clientId;
/**
* Create a new login service with the given authentication URL.
*
* @param authUrl the authentication URL
* @param clientId
*/
public YggdrasilLoginService(@NonNull URL authUrl, String clientId) {
this.authUrl = authUrl;
this.clientId = clientId;
}
public Session login(String agent, String id, String password)
throws IOException, InterruptedException, AuthenticationException {
AuthenticatePayload payload = new AuthenticatePayload(new Agent(agent), id, password, clientId);
return call(this.authUrl, payload);
return call(this.authUrl, payload, null);
}
@Override
@ -50,10 +40,10 @@ public class YggdrasilLoginService implements LoginService {
throws IOException, InterruptedException, AuthenticationException {
RefreshPayload payload = new RefreshPayload(savedSession.getAccessToken(), clientId);
return call(new URL(this.authUrl, "/refresh"), payload);
return call(new URL(this.authUrl, "/refresh"), payload, savedSession);
}
private Session call(URL url, Object payload)
private Session call(URL url, Object payload, SavedSession previous)
throws IOException, InterruptedException, AuthenticationException {
HttpRequest req = HttpRequest
.post(url)
@ -66,8 +56,15 @@ public class YggdrasilLoginService implements LoginService {
throw new AuthenticationException(error.getErrorMessage(), error.getErrorMessage());
} else {
AuthenticateResponse response = req.returnContent().asJson(AuthenticateResponse.class);
Profile profile = response.getSelectedProfile();
return response.getSelectedProfile();
if (previous == null || previous.getAvatarImage() == null) {
profile.setAvatarImage(VisageSkinService.fetchSkinHead(profile.getUuid()));
} else {
profile.setAvatarImage(previous.getAvatarImage());
}
return profile;
}
}
@ -117,6 +114,7 @@ public class YggdrasilLoginService implements LoginService {
@JsonProperty("id") private String uuid;
private String name;
private boolean legacy;
private String avatarImage;
@JsonIgnore private final Map<String, String> userProperties = Collections.emptyMap();
@JsonBackReference private AuthenticateResponse response;

View File

@ -17,16 +17,13 @@ import lombok.RequiredArgsConstructor;
import javax.swing.*;
import java.awt.*;
import java.net.URL;
import java.util.concurrent.Callable;
import static com.skcraft.launcher.util.HttpRequest.url;
public class AccountSelectDialog extends JDialog {
private final JList<SavedSession> accountList;
private final JButton loginButton = new JButton(SharedLocale.tr("login.login"));
private final JButton cancelButton = new JButton(SharedLocale.tr("button.cancel"));
private final JButton addAccountButton = new JButton(SharedLocale.tr("accounts.addNew"));
private final JButton addAccountButton = new JButton(SharedLocale.tr("accounts.addMojang"));
private final LinedBoxPanel buttonsPanel = new LinedBoxPanel(true);
private final Launcher launcher;
@ -82,6 +79,7 @@ public class AccountSelectDialog extends JDialog {
if (newSession != null) {
launcher.getAccounts().add(newSession.toSavedSession());
setResult(newSession);
}
});
}
@ -117,7 +115,6 @@ public class AccountSelectDialog extends JDialog {
Futures.addCallback(future, new FutureCallback<Session>() {
@Override
public void onSuccess(Session result) {
// session.setAccessToken(result.getAccessToken());
setResult(result);
}
@ -161,9 +158,11 @@ public class AccountSelectDialog extends JDialog {
@Override
public Component getListCellRendererComponent(JList<? extends SavedSession> list, SavedSession value, int index, boolean isSelected, boolean cellHasFocus) {
setText(value.getUsername());
URL avatarUrl = url("https://visage.surgeplay.com/face/24/" + value.getUuid() + ".png");
setIcon(new ImageIcon(avatarUrl));
if (value.getAvatarImage() != null) {
setIcon(new ImageIcon(value.getAvatarBytes()));
} else {
setIcon(SwingHelper.createIcon(Launcher.class, "default_skin.png", 32, 32));
}
if (isSelected) {
setOpaque(true);

Binary file not shown.

After

Width:  |  Height:  |  Size: 484 B

View File

@ -89,7 +89,8 @@ launcher.updatePendingHint=(pending update)
accounts.title=Select the account to play with
accounts.refreshingStatus=Refreshing login session...
accounts.addNew=Add a new account...
accounts.addMojang=Log in via Mojang
accounts.addMicrosoft=Log in via Microsoft
login.rememberId=Remember my account in the list
login.rememberPassword=Remember my password