summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/logic/CMakeLists.txt5
-rw-r--r--api/logic/Usable.h58
-rw-r--r--api/logic/launch/LaunchStep.h2
-rw-r--r--api/logic/launch/LaunchTask.cpp20
-rw-r--r--api/logic/launch/LaunchTask.h3
-rw-r--r--api/logic/minecraft/MinecraftInstance.cpp2
-rw-r--r--api/logic/minecraft/auth/AuthSession.h3
-rw-r--r--api/logic/minecraft/auth/MojangAccount.cpp22
-rw-r--r--api/logic/minecraft/auth/MojangAccount.h11
-rw-r--r--api/logic/minecraft/launch/ClaimAccount.cpp24
-rw-r--r--api/logic/minecraft/launch/ClaimAccount.h35
-rw-r--r--application/MainWindow.cpp7
-rw-r--r--application/dialogs/ProfileSelectDialog.cpp7
13 files changed, 194 insertions, 5 deletions
diff --git a/api/logic/CMakeLists.txt b/api/logic/CMakeLists.txt
index 6d0f78f9..1af3bb71 100644
--- a/api/logic/CMakeLists.txt
+++ b/api/logic/CMakeLists.txt
@@ -32,6 +32,9 @@ set(CORE_SOURCES
MMCStrings.h
MMCStrings.cpp
+ # Use tracking separate from memory management
+ Usable.h
+
# Prefix tree where node names are strings between separators
SeparatorPrefixTree.h
@@ -219,6 +222,8 @@ set(MINECRAFT_SOURCES
minecraft/onesix/update/FoldersTask.h
minecraft/onesix/update/LibrariesTask.cpp
minecraft/onesix/update/LibrariesTask.h
+ minecraft/launch/ClaimAccount.cpp
+ minecraft/launch/ClaimAccount.h
minecraft/launch/CreateServerResourcePacksFolder.cpp
minecraft/launch/CreateServerResourcePacksFolder.h
minecraft/launch/ModMinecraftJar.cpp
diff --git a/api/logic/Usable.h b/api/logic/Usable.h
new file mode 100644
index 00000000..1168be4d
--- /dev/null
+++ b/api/logic/Usable.h
@@ -0,0 +1,58 @@
+#pragma once
+
+#include <cstddef>
+#include <memory>
+
+class Usable;
+
+/**
+ * Base class for things that can be used by multiple other things and we want to track the use count.
+ *
+ * @see UseLock
+ */
+class Usable
+{
+ friend class UseLock;
+public:
+ std::size_t useCount()
+ {
+ return m_useCount;
+ }
+ bool isInUse()
+ {
+ return m_useCount > 0;
+ }
+protected:
+ virtual void decrementUses()
+ {
+ m_useCount--;
+ }
+ virtual void incrementUses()
+ {
+ m_useCount++;
+ }
+private:
+ std::size_t m_useCount = 0;
+};
+
+/**
+ * Lock class to use for keeping track of uses of other things derived from Usable
+ *
+ * @see Usable
+ */
+class UseLock
+{
+public:
+ UseLock(std::shared_ptr<Usable> usable)
+ : m_usable(usable)
+ {
+ // this doesn't use shared pointer use count, because that wouldn't be correct. this count is separate.
+ m_usable->incrementUses();
+ }
+ ~UseLock()
+ {
+ m_usable->decrementUses();
+ }
+private:
+ std::shared_ptr<Usable> m_usable;
+};
diff --git a/api/logic/launch/LaunchStep.h b/api/logic/launch/LaunchStep.h
index ea472c0d..4df4673c 100644
--- a/api/logic/launch/LaunchStep.h
+++ b/api/logic/launch/LaunchStep.h
@@ -42,6 +42,8 @@ signals:
public slots:
virtual void proceed() {};
+ // called in the opposite order than the Task launch(), used to clean up or otherwise undo things after the launch ends
+ virtual void finalize() {};
protected: /* data */
LaunchTask *m_parent;
diff --git a/api/logic/launch/LaunchTask.cpp b/api/logic/launch/LaunchTask.cpp
index a006e519..8b9da398 100644
--- a/api/logic/launch/LaunchTask.cpp
+++ b/api/logic/launch/LaunchTask.cpp
@@ -88,7 +88,7 @@ void LaunchTask::onStepFinished()
// end?
if(currentStep == m_steps.size() - 1)
{
- emitSucceeded();
+ finalizeSteps(true, QString());
}
else
{
@@ -99,7 +99,23 @@ void LaunchTask::onStepFinished()
}
else
{
- emitFailed(step->failReason());
+ finalizeSteps(false, step->failReason());
+ }
+}
+
+void LaunchTask::finalizeSteps(bool successful, const QString& error)
+{
+ for(auto step = currentStep; step >= 0; step--)
+ {
+ m_steps[step]->finalize();
+ }
+ if(successful)
+ {
+ emitSucceeded();
+ }
+ else
+ {
+ emitFailed(error);
}
}
diff --git a/api/logic/launch/LaunchTask.h b/api/logic/launch/LaunchTask.h
index f2fb3a2c..981e25cf 100644
--- a/api/logic/launch/LaunchTask.h
+++ b/api/logic/launch/LaunchTask.h
@@ -109,6 +109,9 @@ public slots:
void onStepFinished();
void onProgressReportingRequested();
+private: /*methods */
+ void finalizeSteps(bool successful, const QString & error);
+
protected: /* data */
InstancePtr m_instance;
shared_qobject_ptr<LogModel> m_logModel;
diff --git a/api/logic/minecraft/MinecraftInstance.cpp b/api/logic/minecraft/MinecraftInstance.cpp
index f0d47733..f36e40ed 100644
--- a/api/logic/minecraft/MinecraftInstance.cpp
+++ b/api/logic/minecraft/MinecraftInstance.cpp
@@ -19,6 +19,7 @@
#include "launch/steps/TextPrint.h"
#include "minecraft/launch/LauncherPartLaunch.h"
#include "minecraft/launch/ModMinecraftJar.h"
+#include "minecraft/launch/ClaimAccount.h"
#include "java/launch/CheckJava.h"
#include <icons/IIconList.h>
@@ -425,6 +426,7 @@ std::shared_ptr<LaunchTask> MinecraftInstance::createLaunchTask(AuthSessionPtr s
// if we aren't in offline mode,.
if(session->status != AuthSession::PlayableOffline)
{
+ process->appendStep(std::make_shared<ClaimAccount>(pptr, session));
process->appendStep(std::make_shared<Update>(pptr));
}
diff --git a/api/logic/minecraft/auth/AuthSession.h b/api/logic/minecraft/auth/AuthSession.h
index dede90a9..d2f66db8 100644
--- a/api/logic/minecraft/auth/AuthSession.h
+++ b/api/logic/minecraft/auth/AuthSession.h
@@ -6,6 +6,8 @@
#include "multimc_logic_export.h"
+class MojangAccount;
+
struct User
{
QString id;
@@ -46,6 +48,7 @@ struct MULTIMC_LOGIC_EXPORT AuthSession
bool auth_server_online = false;
// Did the user request online mode?
bool wants_online = true;
+ std::shared_ptr<MojangAccount> m_accountPtr;
};
typedef std::shared_ptr<AuthSession> AuthSessionPtr;
diff --git a/api/logic/minecraft/auth/MojangAccount.cpp b/api/logic/minecraft/auth/MojangAccount.cpp
index 69a24c09..2b073aac 100644
--- a/api/logic/minecraft/auth/MojangAccount.cpp
+++ b/api/logic/minecraft/auth/MojangAccount.cpp
@@ -275,4 +275,26 @@ void MojangAccount::fillSession(AuthSessionPtr session)
session->session = "-";
}
session->u = user();
+ session->m_accountPtr = shared_from_this();
+}
+
+void MojangAccount::decrementUses()
+{
+ Usable::decrementUses();
+ if(!isInUse())
+ {
+ emit changed();
+ qWarning() << "Account" << m_username << "is no longer in use.";
+ }
+}
+
+void MojangAccount::incrementUses()
+{
+ bool wasInUse = isInUse();
+ Usable::incrementUses();
+ if(!wasInUse)
+ {
+ emit changed();
+ qWarning() << "Account" << m_username << "is now in use.";
+ }
}
diff --git a/api/logic/minecraft/auth/MojangAccount.h b/api/logic/minecraft/auth/MojangAccount.h
index 2de0c19c..4902ec11 100644
--- a/api/logic/minecraft/auth/MojangAccount.h
+++ b/api/logic/minecraft/auth/MojangAccount.h
@@ -24,6 +24,7 @@
#include <memory>
#include "AuthSession.h"
+#include "Usable.h"
#include "multimc_logic_export.h"
@@ -60,7 +61,10 @@ enum AccountStatus
* Said information may include things such as that account's username, client token, and access
* token if the user chose to stay logged in.
*/
-class MULTIMC_LOGIC_EXPORT MojangAccount : public QObject
+class MULTIMC_LOGIC_EXPORT MojangAccount :
+ public QObject,
+ public Usable,
+ public std::enable_shared_from_this<MojangAccount>
{
Q_OBJECT
public: /* construction */
@@ -157,6 +161,11 @@ protected: /* variables */
// current task we are executing here
std::shared_ptr<YggdrasilTask> m_currentTask;
+protected: /* methods */
+
+ void incrementUses() override;
+ void decrementUses() override;
+
private
slots:
void authSucceeded();
diff --git a/api/logic/minecraft/launch/ClaimAccount.cpp b/api/logic/minecraft/launch/ClaimAccount.cpp
new file mode 100644
index 00000000..71670b4f
--- /dev/null
+++ b/api/logic/minecraft/launch/ClaimAccount.cpp
@@ -0,0 +1,24 @@
+#include "ClaimAccount.h"
+#include <launch/LaunchTask.h>
+
+ClaimAccount::ClaimAccount(LaunchTask* parent, AuthSessionPtr session): LaunchStep(parent)
+{
+ if(session->status == AuthSession::Status::PlayableOnline)
+ {
+ m_account = session->m_accountPtr;
+ }
+}
+
+void ClaimAccount::executeTask()
+{
+ if(m_account)
+ {
+ lock.reset(new UseLock(m_account));
+ emitSucceeded();
+ }
+}
+
+void ClaimAccount::finalize()
+{
+ lock.reset();
+}
diff --git a/api/logic/minecraft/launch/ClaimAccount.h b/api/logic/minecraft/launch/ClaimAccount.h
new file mode 100644
index 00000000..fa5039af
--- /dev/null
+++ b/api/logic/minecraft/launch/ClaimAccount.h
@@ -0,0 +1,35 @@
+/* Copyright 2013-2016 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <launch/LaunchStep.h>
+#include <minecraft/auth/MojangAccount.h>
+
+class ClaimAccount: public LaunchStep
+{
+ Q_OBJECT
+public:
+ explicit ClaimAccount(LaunchTask *parent, AuthSessionPtr session);
+ void executeTask() override;
+ void finalize() override;
+ bool canAbort() const override
+ {
+ return false;
+ }
+private:
+ std::unique_ptr<UseLock> lock;
+ MojangAccountPtr m_account;
+};
diff --git a/application/MainWindow.cpp b/application/MainWindow.cpp
index 70a0fbf1..5ef32804 100644
--- a/application/MainWindow.cpp
+++ b/application/MainWindow.cpp
@@ -726,7 +726,12 @@ void MainWindow::repopulateAccountsMenu()
MojangAccountPtr account = accounts->at(i);
for (auto profile : account->profiles())
{
- QAction *action = new QAction(profile.name, this);
+ auto profileLabel = profile.name;
+ if(account->isInUse())
+ {
+ profileLabel += tr(" (in use)");
+ }
+ QAction *action = new QAction(profileLabel, this);
action->setData(account->username());
action->setCheckable(true);
if (active_username == account->username())
diff --git a/application/dialogs/ProfileSelectDialog.cpp b/application/dialogs/ProfileSelectDialog.cpp
index 5c42bc7b..1bd8d06a 100644
--- a/application/dialogs/ProfileSelectDialog.cpp
+++ b/application/dialogs/ProfileSelectDialog.cpp
@@ -50,8 +50,13 @@ ProfileSelectDialog::ProfileSelectDialog(const QString &message, int flags, QWid
MojangAccountPtr account = m_accounts->at(i);
for (auto profile : account->profiles())
{
+ auto profileLabel = profile.name;
+ if(account->isInUse())
+ {
+ profileLabel += tr(" (in use)");
+ }
auto item = new QTreeWidgetItem(view);
- item->setText(0, profile.name);
+ item->setText(0, profileLabel);
item->setIcon(0, SkinUtils::getFaceFromCache(profile.id));
item->setData(0, MojangAccountList::PointerRole, QVariant::fromValue(account));
items.append(item);