First draft of player faces in the login dialog

This commit is contained in:
Sky 2013-10-19 06:40:46 +01:00
parent be2c7f4515
commit 681d36b232
7 changed files with 227 additions and 5 deletions

View File

@ -256,6 +256,8 @@ logic/net/HttpMetaCache.h
logic/net/HttpMetaCache.cpp logic/net/HttpMetaCache.cpp
logic/net/LoginTask.h logic/net/LoginTask.h
logic/net/LoginTask.cpp logic/net/LoginTask.cpp
logic/net/SkinDownload.h
logic/net/SkinDownload.cpp
# legacy instances # legacy instances
logic/LegacyInstance.h logic/LegacyInstance.h

View File

@ -294,6 +294,7 @@ void MultiMC::initHttpMetaCache()
m_metacache->addBase("versions", QDir("versions").absolutePath()); m_metacache->addBase("versions", QDir("versions").absolutePath());
m_metacache->addBase("libraries", QDir("libraries").absolutePath()); m_metacache->addBase("libraries", QDir("libraries").absolutePath());
m_metacache->addBase("minecraftforge", QDir("mods/minecraftforge").absolutePath()); m_metacache->addBase("minecraftforge", QDir("mods/minecraftforge").absolutePath());
m_metacache->addBase("skins", QDir("playerdata/skins").absolutePath());
m_metacache->Load(); m_metacache->Load();
} }

View File

@ -17,6 +17,13 @@
#include "ui_logindialog.h" #include "ui_logindialog.h"
#include "keyring.h" #include "keyring.h"
#include "gui/platform.h" #include "gui/platform.h"
#include "MultiMC.h"
#include <QFile>
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonParseError>
#include "logic/net/HttpMetaCache.h"
#include <logger/QsLog.h> #include <logger/QsLog.h>
LoginDialog::LoginDialog(QWidget *parent, const QString& loginErrMsg) : LoginDialog::LoginDialog(QWidget *parent, const QString& loginErrMsg) :
@ -51,6 +58,8 @@ LoginDialog::LoginDialog(QWidget *parent, const QString& loginErrMsg) :
arg(loginErrMsg)); arg(loginErrMsg));
} }
ui->lblFace->setVisible(false);
resize(minimumSizeHint()); resize(minimumSizeHint());
layout()->setSizeConstraint(QLayout::SetFixedSize); layout()->setSizeConstraint(QLayout::SetFixedSize);
Keyring * k = Keyring::instance(); Keyring * k = Keyring::instance();
@ -151,13 +160,54 @@ void LoginDialog::userTextChanged ( const QString& user )
blockToggles = true; blockToggles = true;
Keyring * k = Keyring::instance(); Keyring * k = Keyring::instance();
QStringList sl = k->getStoredAccounts("minecraft"); QStringList sl = k->getStoredAccounts("minecraft");
bool gotFace = false;
if(sl.contains(user)) if(sl.contains(user))
{ {
ui->rememberUsernameCheckbox->setChecked(true); ui->rememberUsernameCheckbox->setChecked(true);
QString passwd = k->getPassword("minecraft",user); QString passwd = k->getPassword("minecraft",user);
ui->rememberPasswordCheckbox->setChecked(!passwd.isEmpty()); ui->rememberPasswordCheckbox->setChecked(!passwd.isEmpty());
ui->passwordTextBox->setText(passwd); ui->passwordTextBox->setText(passwd);
QByteArray data;
{
auto filename = MMC->metacache()->resolveEntry("skins", "skins.json")->getFullPath();
QFile listFile(filename);
if(!listFile.open(QIODevice::ReadOnly))
return;
data = listFile.readAll();
} }
QJsonParseError jsonError;
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError);
QJsonObject root = jsonDoc.object();
QJsonObject mappings = root.value("mappings").toObject();
if(!mappings[user].isUndefined())
{
QJsonArray usernames = mappings.value(user).toArray();
if(!usernames.isEmpty())
{
QString mapped_username = usernames[0].toString();
if(!mapped_username.isEmpty())
{
QFile fskin(MMC->metacache()->resolveEntry("skins", mapped_username + ".png")->getFullPath());
if(fskin.exists())
{
QPixmap skin(MMC->metacache()->resolveEntry("skins", mapped_username + ".png")->getFullPath());
QPixmap face = skin.copy(8, 8, 8, 8).scaled(48, 48, Qt::KeepAspectRatio);
ui->lblFace->setPixmap(face);
gotFace = true;
}
}
}
}
}
if(gotFace) ui->lblFace->setVisible(true);
else ui->lblFace->setVisible(false);
blockToggles = false; blockToggles = false;
} }

View File

@ -23,10 +23,34 @@
</item> </item>
<item> <item>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="0" column="0"> <item row="0" column="4" rowspan="2">
<widget class="QLabel" name="usernameLabel"> <widget class="QLabel" name="lblFace">
<property name="minimumSize">
<size>
<width>48</width>
<height>48</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>48</width>
<height>48</height>
</size>
</property>
<property name="sizeIncrement">
<size>
<width>1</width>
<height>1</height>
</size>
</property>
<property name="text"> <property name="text">
<string>Username:</string> <string/>
</property>
<property name="pixmap">
<pixmap resource="../multimc.qrc">:/icons/instances/steve</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>
@ -37,6 +61,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="0">
<widget class="QLabel" name="usernameLabel">
<property name="text">
<string>Username:</string>
</property>
</widget>
</item>
<item row="1" column="0"> <item row="1" column="0">
<widget class="QLabel" name="passwordLabel"> <widget class="QLabel" name="passwordLabel">
<property name="text"> <property name="text">
@ -54,7 +85,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="2" rowspan="2"> <item row="0" column="5" rowspan="2">
<widget class="QPushButton" name="forgetButton"> <widget class="QPushButton" name="forgetButton">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum"> <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
@ -111,7 +142,9 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<resources/> <resources>
<include location="../multimc.qrc"/>
</resources>
<connections> <connections>
<connection> <connection>
<sender>loginButtonBox</sender> <sender>loginButtonBox</sender>

View File

@ -57,6 +57,8 @@
#include "logic/lists/JavaVersionList.h" #include "logic/lists/JavaVersionList.h"
#include "logic/net/LoginTask.h" #include "logic/net/LoginTask.h"
#include "logic/net/SkinDownload.h"
#include "logic/BaseInstance.h" #include "logic/BaseInstance.h"
#include "logic/InstanceFactory.h" #include "logic/InstanceFactory.h"
#include "logic/MinecraftProcess.h" #include "logic/MinecraftProcess.h"
@ -517,6 +519,42 @@ void MainWindow::onLoginComplete()
tDialog.exec(updateTask); tDialog.exec(updateTask);
delete updateTask; delete updateTask;
} }
auto download = new SkinDownload(m_activeLogin.player_name);
download->start();
auto filename = MMC->metacache()->resolveEntry("skins", "skins.json")->getFullPath();
QFile listFile(filename);
// Add skin mapping
QByteArray data;
{
if(!listFile.open(QIODevice::ReadWrite))
{
QLOG_ERROR() << "Failed to open/make skins list JSON";
return;
}
data = listFile.readAll();
}
QJsonParseError jsonError;
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError);
QJsonObject root = jsonDoc.object();
QJsonObject mappings = root.value("mappings").toObject();
QJsonArray usernames = mappings.value(m_activeLogin.username).toArray();
if(!usernames.contains(m_activeLogin.player_name))
{
usernames.prepend(m_activeLogin.player_name);
mappings[m_activeLogin.username] = usernames;
root["mappings"] = mappings;
jsonDoc.setObject(root);
// QJson hack - shouldn't have to clear the file every time a save happens
listFile.resize(0);
listFile.write(jsonDoc.toJson());
}
} }
void MainWindow::onGameUpdateComplete() void MainWindow::onGameUpdateComplete()

View File

@ -0,0 +1,60 @@
#include "MultiMC.h"
#include "SkinDownload.h"
#include "DownloadJob.h"
#include <pathutils.h>
#include <QImage>
#include <QPainter>
#include <QCryptographicHash>
#include <QFileInfo>
#include <QDateTime>
#include <logger/QsLog.h>
SkinDownload::SkinDownload(QString name)
{
m_name = name;
m_entry = MMC->metacache()->resolveEntry("skins", name + ".png");
m_entry->stale = true;
m_url = QUrl("http://skins.minecraft.net/MinecraftSkins/" + name + ".png");
}
void SkinDownload::start()
{
auto job = new DownloadJob("Player skin: " + m_name);
job->addCacheDownload(m_url, m_entry);
m_job.reset(job);
connect(m_job.get(), SIGNAL(started()), SLOT(downloadStarted()));
connect(m_job.get(), SIGNAL(progress(qint64, qint64)), SLOT(downloadProgress(qint64, qint64)));
connect(m_job.get(), SIGNAL(succeeded()), SLOT(downloadSucceeded()));
connect(m_job.get(), SIGNAL(failed()), SLOT(downloadFailed()));
m_job->start();
}
void SkinDownload::downloadStarted()
{
//QLOG_INFO() << "Started skin download for " << m_name << ".";
emit started();
}
void SkinDownload::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
{
emit progress(bytesReceived, bytesTotal);
}
void SkinDownload::downloadSucceeded()
{
//QLOG_INFO() << "Got skin for " << m_name << ", cropping.";
emit succeeded();
}
void SkinDownload::downloadFailed()
{
//QLOG_ERROR() << "Failed to download skin for: " << m_name;
emit failed();
}

38
logic/net/SkinDownload.h Normal file
View File

@ -0,0 +1,38 @@
#pragma once
#include "Download.h"
#include "HttpMetaCache.h"
#include "DownloadJob.h"
#include <QFile>
#include <QTemporaryFile>
class SkinDownload : public QObject
{
Q_OBJECT
public:
explicit SkinDownload(QString name);
QString m_name;
QUrl m_url;
MetaEntryPtr m_entry;
DownloadJobPtr m_job;
void start();
protected slots:
void downloadStarted();
void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
void downloadSucceeded();
void downloadFailed();
signals:
void started();
void progress(qint64 current, qint64 total);
void succeeded();
void failed();
protected:
};
typedef std::shared_ptr<SkinDownload> SkinDownloadPtr;