From 3a6ae78bc64e91dcebd1360b449c551cdbbbcdab Mon Sep 17 00:00:00 2001 From: Ice Yeti <101294194+IceYetiWins@users.noreply.github.com> Date: Sun, 31 May 2026 13:48:31 -0400 Subject: [PATCH] all worlds list will now join correct instance for each world --- launcher/minecraft/MultiWorldList.cpp | 77 +++++++++++++++------------ launcher/minecraft/MultiWorldList.h | 13 +++-- launcher/ui/MainWindow.cpp | 9 ++-- launcher/ui/MultiWorldListPage.cpp | 18 +++---- launcher/ui/MultiWorldListPage.h | 5 +- 5 files changed, 66 insertions(+), 56 deletions(-) diff --git a/launcher/minecraft/MultiWorldList.cpp b/launcher/minecraft/MultiWorldList.cpp index 258768c18..c43f84054 100644 --- a/launcher/minecraft/MultiWorldList.cpp +++ b/launcher/minecraft/MultiWorldList.cpp @@ -46,7 +46,9 @@ #include #include -MultiWorldList::MultiWorldList(const QList& dirs, QList instances) : QAbstractListModel(), m_instances(instances) +#include "MinecraftInstance.h" + +MultiWorldList::MultiWorldList(const QList& dirs, const QList& instances) : QAbstractListModel(), m_instances(instances) { for (QString dir : dirs) { m_dirs.append(dir); @@ -105,9 +107,10 @@ bool MultiWorldList::update() if (!isValid()) return false; - QList newWorlds; + QList newWorlds; - for (QDir dir : m_dirs) { + for (BaseInstance* inst : m_instances) { + QDir dir = dynamic_cast(inst)->worldDir(); dir.refresh(); auto folderContents = dir.entryInfoList(); // if there are any untracked files... @@ -117,7 +120,7 @@ bool MultiWorldList::update() World w(entry); if (w.isValid()) { - newWorlds.append(w); + newWorlds.append(InstanceWorld(w, inst)); } } } @@ -134,16 +137,24 @@ void MultiWorldList::directoryChanged(QString) update(); } -bool MultiWorldList::isValid() //account for all directories +bool MultiWorldList::isValid() { - return m_dirs[0].exists() && m_dirs[0].isReadable(); + bool valid = true; + + for (const QDir& dir : m_dirs) { + if (!(dir.exists() && dir.isReadable())) { + valid = false; + } + } + + return valid; } QList MultiWorldList::instDirPaths() const { QList dirList; - for (BaseInstance* instance : m_instances) { + for (BaseInstance* instance : m_instances) { //use m_dirs??? iy dirList.append(QFileInfo(instance->instanceRoot()).absoluteFilePath()); } @@ -154,7 +165,7 @@ bool MultiWorldList::deleteWorld(int index) { if (index >= m_worlds.size() || index < 0) return false; - World& m = m_worlds[index]; + World& m = m_worlds[index].world; if (m.destroy()) { beginRemoveRows(QModelIndex(), index, index); m_worlds.removeAt(index); @@ -168,7 +179,7 @@ bool MultiWorldList::deleteWorld(int index) bool MultiWorldList::deleteWorlds(int first, int last) { for (int i = first; i <= last; i++) { - World& m = m_worlds[i]; + World& m = m_worlds[i].world; m.destroy(); } beginRemoveRows(QModelIndex(), first, last); @@ -182,7 +193,7 @@ bool MultiWorldList::resetIcon(int row) { if (row >= m_worlds.size() || row < 0) return false; - World& m = m_worlds[row]; + World& m = m_worlds[row].world; if (m.resetIcon()) { QModelIndex modelIndex = index(row, NameColumn); emit dataChanged(modelIndex, modelIndex, { MultiWorldList::IconFileRole }); @@ -209,29 +220,29 @@ QVariant MultiWorldList::data(const QModelIndex& index, int role) const QLocale locale; - auto& world = m_worlds[row]; + auto& instanceWorld = m_worlds[row]; switch (role) { case Qt::DisplayRole: switch (column) { case NameColumn: - return world.name(); + return instanceWorld.world.name(); case GameModeColumn: - return world.gameType().toTranslatedString(); + return instanceWorld.world.gameType().toTranslatedString(); case LastPlayedColumn: - return world.lastPlayed(); + return instanceWorld.world.lastPlayed(); case SizeColumn: - return locale.formattedDataSize(world.bytes()); + return locale.formattedDataSize(instanceWorld.world.bytes()); case InfoColumn: for (QString path : instDirPaths()) { //use canonical paths instead of for loops? iy - if (world.isSymLinkUnder(path)) { + if (instanceWorld.world.isSymLinkUnder(path)) { return tr("This world is symbolically linked from elsewhere."); } } - if (world.isMoreThanOneHardLink()) { + if (instanceWorld.world.isMoreThanOneHardLink()) { return tr("\nThis world is hard linked elsewhere."); } return ""; @@ -241,44 +252,44 @@ QVariant MultiWorldList::data(const QModelIndex& index, int role) const case Qt::UserRole: if (column == SizeColumn) - return QVariant::fromValue(world.bytes()); + return QVariant::fromValue(instanceWorld.world.bytes()); return data(index, Qt::DisplayRole); case Qt::ToolTipRole: { if (column == InfoColumn) { for (QString path : instDirPaths()) { //use canonical paths instead of for loops? iy - if (world.isSymLinkUnder(path)) { + if (instanceWorld.world.isSymLinkUnder(path)) { return tr("Warning: This world is symbolically linked from elsewhere. Editing it will also change the original." "\nCanonical Path: %1") - .arg(world.canonicalFilePath()); + .arg(instanceWorld.world.canonicalFilePath()); } } - if (world.isMoreThanOneHardLink()) { + if (instanceWorld.world.isMoreThanOneHardLink()) { return tr("Warning: This world is hard linked elsewhere. Editing it will also change the original."); } } - return world.folderName(); + return instanceWorld.world.folderName(); } case ObjectRole: { - return QVariant::fromValue((void*)&world); + return QVariant::fromValue((void*)&instanceWorld); } case FolderRole: { - return QDir::toNativeSeparators(QDir(world.canonicalFilePath()).absoluteFilePath(world.folderName())); //test if canonical file path works iy + return QDir::toNativeSeparators(QDir(instanceWorld.world.canonicalFilePath()).absoluteFilePath(instanceWorld.world.folderName())); //test if canonical file path works iy } case SeedRole: { - return QVariant::fromValue(world.seed()); + return QVariant::fromValue(instanceWorld.world.seed()); } case NameRole: { - return world.name(); + return instanceWorld.world.name(); } case LastPlayedRole: { - return world.lastPlayed(); + return instanceWorld.world.lastPlayed(); } case SizeRole: { - return QVariant::fromValue(world.bytes()); + return QVariant::fromValue(instanceWorld.world.bytes()); } case IconFileRole: { - return world.iconFile(); + return instanceWorld.world.iconFile(); } default: return QVariant(); @@ -345,7 +356,7 @@ QMimeData* MultiWorldList::mimeData(const QModelIndexList& indexes) const if (row < 0 || row >= this->m_worlds.size()) continue; - const World& world = m_worlds[row]; + const World& world = m_worlds[row].world; if (!world.isValid() || !world.isOnFS()) continue; @@ -446,7 +457,7 @@ int64_t MultiWorldList::calculateWorldSize(const QFileInfo& file) void MultiWorldList::loadWorldsAsync() { for (int i = 0; i < m_worlds.size(); ++i) { - auto file = m_worlds.at(i).container(); + auto file = m_worlds.at(i).world.container(); int row = i; QThreadPool::globalInstance()->start([this, file, row]() mutable { auto size = calculateWorldSize(file); @@ -454,8 +465,8 @@ void MultiWorldList::loadWorldsAsync() QMetaObject::invokeMethod( this, [this, size, row, file]() { - if (row < m_worlds.size() && m_worlds[row].container() == file) { - m_worlds[row].setSize(size); + if (row < m_worlds.size() && m_worlds[row].world.container() == file) { + m_worlds[row].world.setSize(size); // Notify views QModelIndex modelIndex = index(row, SizeColumn); diff --git a/launcher/minecraft/MultiWorldList.h b/launcher/minecraft/MultiWorldList.h index 1e0a7e60e..147f5e8f8 100644 --- a/launcher/minecraft/MultiWorldList.h +++ b/launcher/minecraft/MultiWorldList.h @@ -25,6 +25,11 @@ class QFileSystemWatcher; +struct InstanceWorld { + World world; + BaseInstance* instance; +}; + class MultiWorldList : public QAbstractListModel { Q_OBJECT public: @@ -32,7 +37,7 @@ class MultiWorldList : public QAbstractListModel { enum Roles { ObjectRole = Qt::UserRole + 1, FolderRole, SeedRole, NameRole, GameModeRole, LastPlayedRole, SizeRole, IconFileRole }; - MultiWorldList(const QList& dirs, QList instances); + MultiWorldList(const QList& dirs, const QList& instances); virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; @@ -42,7 +47,7 @@ class MultiWorldList : public QAbstractListModel { size_t size() const { return m_worlds.size(); }; bool empty() const { return size() == 0; } - World& operator[](size_t index) { return m_worlds[index]; } + World& operator[](size_t index) { return m_worlds[index].world; } /// Reloads the mod list and returns true if the list changed. virtual bool update(); @@ -83,7 +88,7 @@ class MultiWorldList : public QAbstractListModel { QList instDirPaths() const; - const QList& allWorlds() const { return m_worlds; } + const QList& allWorlds() const { return m_worlds; } private slots: void directoryChanged(QString path); @@ -97,5 +102,5 @@ class MultiWorldList : public QAbstractListModel { QFileSystemWatcher* m_watcher; bool m_isWatching; QList m_dirs; - QList m_worlds; + QList m_worlds; }; diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 42611ab88..8fd3ee8aa 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -339,7 +339,6 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWi // Create the all worlds widget { QList allInstances = APPLICATION->instances()->getAllInstances(); - qDebug() << "iy initially" << allInstances.length(); QList dirs; for (BaseInstance* inst : allInstances) { dirs.append(dynamic_cast(inst)->worldDir()); @@ -347,7 +346,7 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWi allWorlds = new MultiWorldList(dirs, allInstances); allWorlds->update(); - allWorldsPage = new MultiWorldListPage(dynamic_cast(allInstances[0]), allWorlds); //shouldnt be only one instance iy + allWorldsPage = new MultiWorldListPage(allWorlds); ui->horizontalLayout->addWidget(allWorldsPage); } @@ -945,10 +944,7 @@ void MainWindow::addInstance(const QString& url, const QMap& e instanceFromInstanceTask(creationTask); } - //clean this up iy - fix ghosting issue and only joining one world despite which one you click - QList allInstances = APPLICATION->instances()->getAllInstances(); - qDebug() << "iy finally " << allInstances.length(); QList dirs; for (BaseInstance* inst : allInstances) { dirs.append(dynamic_cast(inst)->worldDir()); @@ -956,8 +952,9 @@ void MainWindow::addInstance(const QString& url, const QMap& e allWorlds = new MultiWorldList(dirs, allInstances); allWorlds->update(); - auto newAllWorldsPage = new MultiWorldListPage(dynamic_cast(allInstances[0]), allWorlds); //shouldnt be only one instance iy + auto newAllWorldsPage = new MultiWorldListPage(allWorlds); ui->horizontalLayout->replaceWidget(allWorldsPage, newAllWorldsPage); + delete allWorldsPage; allWorldsPage = newAllWorldsPage; } diff --git a/launcher/ui/MultiWorldListPage.cpp b/launcher/ui/MultiWorldListPage.cpp index 16dc6a5c5..3075bf840 100644 --- a/launcher/ui/MultiWorldListPage.cpp +++ b/launcher/ui/MultiWorldListPage.cpp @@ -86,14 +86,14 @@ class MultiWorldListProxyModel : public QSortFilterProxyModel { } }; -MultiWorldListPage::MultiWorldListPage(MinecraftInstance* inst, MultiWorldList* worlds, QWidget* parent) //require all instances instead of just one iy - : QMainWindow(parent), m_inst(inst), ui(new Ui::MultiWorldListPage), m_worlds(worlds) +MultiWorldListPage::MultiWorldListPage(MultiWorldList* worlds, QWidget* parent) + : QMainWindow(parent), ui(new Ui::MultiWorldListPage), m_worlds(worlds) { ui->setupUi(this); ui->toolBar->insertSpacer(ui->actionRefresh); - MultiWorldListProxyModel* proxy = new MultiWorldListProxyModel(this); + auto* proxy = new MultiWorldListProxyModel(this); proxy->setSortCaseSensitivity(Qt::CaseInsensitive); proxy->setSourceModel(m_worlds); proxy->setSortRole(Qt::UserRole); @@ -195,7 +195,7 @@ void MultiWorldListPage::on_actionRemove_triggered() tr("You are about to delete \"%1\".\n" "The world may be gone forever (A LONG TIME).\n\n" "Are you sure?") - .arg(m_worlds->allWorlds().at(proxiedIndex.row()).name()), + .arg(m_worlds->allWorlds().at(proxiedIndex.row()).world.name()), QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ->exec(); @@ -237,9 +237,9 @@ void MultiWorldListPage::on_actionData_Packs_triggered() GenericPageProvider provider(dialog->windowTitle()); bool isIndexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool(); - m_datapackModel.reset(new DataPackFolderModel(folder, m_inst, isIndexed, true)); + m_datapackModel.reset(new DataPackFolderModel(folder, m_worlds->allWorlds()[0].instance, isIndexed, true)); //don't use instance 0 iy - provider.addPageCreator([this] { return new DataPackPage(m_inst, m_datapackModel.get(), this); }); + provider.addPageCreator([this] { return new DataPackPage(m_worlds->allWorlds()[0].instance, m_datapackModel.get(), this); }); //no instance 0 iy auto layout = new QVBoxLayout(dialog); @@ -402,7 +402,7 @@ void MultiWorldListPage::on_actionAdd_triggered() bool MultiWorldListPage::isWorldSafe(QModelIndex) { - return !m_inst->isRunning(); + return !m_worlds->allWorlds()[0].instance->isRunning(); //don't use instance 0 iy } bool MultiWorldListPage::worldSafetyNagQuestion(const QString& actionType) @@ -471,8 +471,8 @@ void MultiWorldListPage::on_actionJoin_triggered() return; } auto worldVariant = m_worlds->data(index, MultiWorldList::ObjectRole); - auto world = (World*)worldVariant.value(); - APPLICATION->launch(m_inst, LaunchMode::Normal, std::make_shared(MinecraftTarget::parse(world->folderName(), true))); + auto world = (InstanceWorld*)worldVariant.value(); + APPLICATION->launch(world->instance, LaunchMode::Normal, std::make_shared(MinecraftTarget::parse(world->world.folderName(), true))); } #include "MultiWorldListPage.moc" diff --git a/launcher/ui/MultiWorldListPage.h b/launcher/ui/MultiWorldListPage.h index 91cc088cf..5531017a7 100644 --- a/launcher/ui/MultiWorldListPage.h +++ b/launcher/ui/MultiWorldListPage.h @@ -52,7 +52,7 @@ class MultiWorldListPage : public QMainWindow, public BasePage { Q_OBJECT public: - explicit MultiWorldListPage(MinecraftInstance* inst, MultiWorldList* worlds, QWidget* parent = 0); + explicit MultiWorldListPage(MultiWorldList* worlds, QWidget* parent = 0); virtual ~MultiWorldListPage(); virtual QString displayName() const override { return tr("Worlds"); } @@ -70,9 +70,6 @@ class MultiWorldListPage : public QMainWindow, public BasePage { bool worldListFilter(QKeyEvent* ev); QMenu* createPopupMenu() override; - protected: - MinecraftInstance* m_inst; - private: QModelIndex getSelectedWorld(); bool isWorldSafe(QModelIndex index);