diff options
-rw-r--r-- | api/logic/CMakeLists.txt | 5 | ||||
-rw-r--r-- | api/logic/Usable.h | 58 | ||||
-rw-r--r-- | api/logic/launch/LaunchStep.h | 2 | ||||
-rw-r--r-- | api/logic/launch/LaunchTask.cpp | 20 | ||||
-rw-r--r-- | api/logic/launch/LaunchTask.h | 3 | ||||
-rw-r--r-- | api/logic/minecraft/MinecraftInstance.cpp | 2 | ||||
-rw-r--r-- | api/logic/minecraft/auth/AuthSession.h | 3 | ||||
-rw-r--r-- | api/logic/minecraft/auth/MojangAccount.cpp | 22 | ||||
-rw-r--r-- | api/logic/minecraft/auth/MojangAccount.h | 11 | ||||
-rw-r--r-- | api/logic/minecraft/launch/ClaimAccount.cpp | 24 | ||||
-rw-r--r-- | api/logic/minecraft/launch/ClaimAccount.h | 35 | ||||
-rw-r--r-- | application/MainWindow.cpp | 7 | ||||
-rw-r--r-- | application/dialogs/ProfileSelectDialog.cpp | 7 |
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); |