feat: WIP: Download Page
This commit is contained in:
@@ -44,6 +44,7 @@ import org.jackhuang.hmcl.ui.construct.MessageDialogPane.MessageType;
|
|||||||
import org.jackhuang.hmcl.ui.construct.PromptDialogPane;
|
import org.jackhuang.hmcl.ui.construct.PromptDialogPane;
|
||||||
import org.jackhuang.hmcl.ui.construct.TaskExecutorDialogPane;
|
import org.jackhuang.hmcl.ui.construct.TaskExecutorDialogPane;
|
||||||
import org.jackhuang.hmcl.ui.decorator.DecoratorController;
|
import org.jackhuang.hmcl.ui.decorator.DecoratorController;
|
||||||
|
import org.jackhuang.hmcl.ui.download.DownloadPage;
|
||||||
import org.jackhuang.hmcl.ui.download.ModpackInstallWizardProvider;
|
import org.jackhuang.hmcl.ui.download.ModpackInstallWizardProvider;
|
||||||
import org.jackhuang.hmcl.ui.main.LauncherSettingsPage;
|
import org.jackhuang.hmcl.ui.main.LauncherSettingsPage;
|
||||||
import org.jackhuang.hmcl.ui.main.RootPage;
|
import org.jackhuang.hmcl.ui.main.RootPage;
|
||||||
@@ -93,6 +94,7 @@ public final class Controllers {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
private static Lazy<DownloadPage> downloadPage = new Lazy<>(DownloadPage::new);
|
||||||
private static Lazy<AccountListPage> accountListPage = new Lazy<>(() -> {
|
private static Lazy<AccountListPage> accountListPage = new Lazy<>(() -> {
|
||||||
AccountListPage accountListPage = new AccountListPage();
|
AccountListPage accountListPage = new AccountListPage();
|
||||||
accountListPage.selectedAccountProperty().bindBidirectional(Accounts.selectedAccountProperty());
|
accountListPage.selectedAccountProperty().bindBidirectional(Accounts.selectedAccountProperty());
|
||||||
@@ -149,6 +151,11 @@ public final class Controllers {
|
|||||||
return accountListPage.get();
|
return accountListPage.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FXThread
|
||||||
|
public static DownloadPage getDownloadPage() {
|
||||||
|
return downloadPage.get();
|
||||||
|
}
|
||||||
|
|
||||||
// FXThread
|
// FXThread
|
||||||
public static DecoratorController getDecorator() {
|
public static DecoratorController getDecorator() {
|
||||||
return decorator;
|
return decorator;
|
||||||
|
|||||||
@@ -307,6 +307,12 @@ public final class SVG {
|
|||||||
fill, width, height);
|
fill, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Node textureBox(ObjectBinding<? extends Paint> fill, double width, double height) {
|
||||||
|
return createSVGPath(
|
||||||
|
"M20 2H4C2.9 2 2 2.9 2 4V20C2 21.11 2.9 22 4 22H20C21.11 22 22 21.11 22 20V4C22 2.9 21.11 2 20 2M4 6L6 4H10.9L4 10.9V6M4 13.7L13.7 4H18.6L4 18.6V13.7M20 18L18 20H13.1L20 13.1V18M20 10.3L10.3 20H5.4L20 5.4V10.3Z",
|
||||||
|
fill, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
public static Node gamepad(ObjectBinding<? extends Paint> fill, double width, double height) {
|
public static Node gamepad(ObjectBinding<? extends Paint> fill, double width, double height) {
|
||||||
return createSVGPath(
|
return createSVGPath(
|
||||||
"M6,9H8V11H10V13H8V15H6V13H4V11H6V9M18.5,9A1.5,1.5 0 0,1 20,10.5A1.5,1.5 0 0,1 18.5,12A1.5,1.5 0 0,1 17,10.5A1.5,1.5 0 0,1 18.5,9M15.5,12A1.5,1.5 0 0,1 17,13.5A1.5,1.5 0 0,1 15.5,15A1.5,1.5 0 0,1 14,13.5A1.5,1.5 0 0,1 15.5,12M17,5A7,7 0 0,1 24,12A7,7 0 0,1 17,19C15.04,19 13.27,18.2 12,16.9C10.73,18.2 8.96,19 7,19A7,7 0 0,1 0,12A7,7 0 0,1 7,5H17M7,7A5,5 0 0,0 2,12A5,5 0 0,0 7,17C8.64,17 10.09,16.21 11,15H13C13.91,16.21 15.36,17 17,17A5,5 0 0,0 22,12A5,5 0 0,0 17,7H7Z",
|
"M6,9H8V11H10V13H8V15H6V13H4V11H6V9M18.5,9A1.5,1.5 0 0,1 20,10.5A1.5,1.5 0 0,1 18.5,12A1.5,1.5 0 0,1 17,10.5A1.5,1.5 0 0,1 18.5,9M15.5,12A1.5,1.5 0 0,1 17,13.5A1.5,1.5 0 0,1 15.5,15A1.5,1.5 0 0,1 14,13.5A1.5,1.5 0 0,1 15.5,12M17,5A7,7 0 0,1 24,12A7,7 0 0,1 17,19C15.04,19 13.27,18.2 12,16.9C10.73,18.2 8.96,19 7,19A7,7 0 0,1 0,12A7,7 0 0,1 7,5H17M7,7A5,5 0 0,0 2,12A5,5 0 0,0 7,17C8.64,17 10.09,16.21 11,15H13C13.91,16.21 15.36,17 17,17A5,5 0 0,0 22,12A5,5 0 0,0 17,7H7Z",
|
||||||
|
|||||||
@@ -259,6 +259,10 @@ public interface TabControl {
|
|||||||
this.userData.set(userData);
|
this.userData.set(userData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isInitialized() {
|
||||||
|
return getNode() == null;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean initializeIfNeeded() {
|
public boolean initializeIfNeeded() {
|
||||||
if (getNode() == null) {
|
if (getNode() == null) {
|
||||||
if (getNodeSupplier() == null) {
|
if (getNodeSupplier() == null) {
|
||||||
|
|||||||
@@ -0,0 +1,153 @@
|
|||||||
|
/*
|
||||||
|
* Hello Minecraft! Launcher
|
||||||
|
* Copyright (C) 2021 huangyuhui <huanghongxun2008@126.com> and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.jackhuang.hmcl.ui.download;
|
||||||
|
|
||||||
|
import javafx.beans.property.ReadOnlyObjectProperty;
|
||||||
|
import javafx.beans.property.ReadOnlyObjectWrapper;
|
||||||
|
import javafx.scene.layout.BorderPane;
|
||||||
|
import org.jackhuang.hmcl.mod.curse.CurseAddon;
|
||||||
|
import org.jackhuang.hmcl.mod.curse.CurseModManager;
|
||||||
|
import org.jackhuang.hmcl.setting.Profile;
|
||||||
|
import org.jackhuang.hmcl.setting.Profiles;
|
||||||
|
import org.jackhuang.hmcl.task.FileDownloadTask;
|
||||||
|
import org.jackhuang.hmcl.task.Task;
|
||||||
|
import org.jackhuang.hmcl.task.TaskExecutor;
|
||||||
|
import org.jackhuang.hmcl.ui.Controllers;
|
||||||
|
import org.jackhuang.hmcl.ui.FXUtils;
|
||||||
|
import org.jackhuang.hmcl.ui.SVG;
|
||||||
|
import org.jackhuang.hmcl.ui.WeakListenerHolder;
|
||||||
|
import org.jackhuang.hmcl.ui.animation.ContainerAnimations;
|
||||||
|
import org.jackhuang.hmcl.ui.animation.TransitionPane;
|
||||||
|
import org.jackhuang.hmcl.ui.construct.AdvancedListBox;
|
||||||
|
import org.jackhuang.hmcl.ui.construct.TabHeader;
|
||||||
|
import org.jackhuang.hmcl.ui.construct.TaskExecutorDialogPane;
|
||||||
|
import org.jackhuang.hmcl.ui.decorator.DecoratorPage;
|
||||||
|
import org.jackhuang.hmcl.ui.versions.ModDownloadListPage;
|
||||||
|
import org.jackhuang.hmcl.ui.versions.VersionPage;
|
||||||
|
import org.jackhuang.hmcl.ui.versions.Versions;
|
||||||
|
import org.jackhuang.hmcl.util.io.NetworkUtils;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
import static org.jackhuang.hmcl.ui.FXUtils.runInFX;
|
||||||
|
import static org.jackhuang.hmcl.ui.versions.VersionPage.wrap;
|
||||||
|
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||||
|
|
||||||
|
public class DownloadPage extends BorderPane implements DecoratorPage {
|
||||||
|
private final ReadOnlyObjectWrapper<DecoratorPage.State> state = new ReadOnlyObjectWrapper<>(DecoratorPage.State.fromTitle(i18n("download"), 200));
|
||||||
|
private final TabHeader tab;
|
||||||
|
private final TabHeader.Tab<ModDownloadListPage> modTab = new TabHeader.Tab<>("modTab");
|
||||||
|
private final TabHeader.Tab<ModDownloadListPage> modpackTab = new TabHeader.Tab<>("modpackTab");
|
||||||
|
private final TabHeader.Tab<ModDownloadListPage> resourcePackTab = new TabHeader.Tab<>("resourcePackTab");
|
||||||
|
private final TransitionPane transitionPane = new TransitionPane();
|
||||||
|
|
||||||
|
private WeakListenerHolder listenerHolder;
|
||||||
|
|
||||||
|
public DownloadPage() {
|
||||||
|
modTab.setNodeSupplier(() -> new ModDownloadListPage(CurseModManager.SECTION_MODPACK, Versions::downloadModpackImpl));
|
||||||
|
modpackTab.setNodeSupplier(() -> new ModDownloadListPage(CurseModManager.SECTION_MOD, this::download));
|
||||||
|
resourcePackTab.setNodeSupplier(() -> new ModDownloadListPage(CurseModManager.SECTION_MOD, this::download));
|
||||||
|
tab = new TabHeader(modTab, modpackTab, resourcePackTab);
|
||||||
|
|
||||||
|
Profiles.registerVersionsListener(this::loadVersions);
|
||||||
|
|
||||||
|
tab.getSelectionModel().select(modTab);
|
||||||
|
FXUtils.onChangeAndOperate(tab.getSelectionModel().selectedItemProperty(), newValue -> {
|
||||||
|
if (newValue.initializeIfNeeded()) {
|
||||||
|
if (newValue.getNode() instanceof VersionPage.VersionLoadable) {
|
||||||
|
((VersionPage.VersionLoadable) newValue.getNode()).loadVersion(Profiles.getSelectedProfile(), Profiles.getSelectedVersion());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
transitionPane.setContent(newValue.getNode(), ContainerAnimations.FADE.getAnimationProducer());
|
||||||
|
});
|
||||||
|
|
||||||
|
{
|
||||||
|
AdvancedListBox sideBar = new AdvancedListBox()
|
||||||
|
.addNavigationDrawerItem(item -> {
|
||||||
|
item.setTitle(i18n("mods"));
|
||||||
|
item.setLeftGraphic(wrap(SVG.puzzle(null, 20, 20)));
|
||||||
|
item.activeProperty().bind(tab.getSelectionModel().selectedItemProperty().isEqualTo(modTab));
|
||||||
|
item.setOnAction(e -> tab.getSelectionModel().select(modTab));
|
||||||
|
})
|
||||||
|
.addNavigationDrawerItem(settingsItem -> {
|
||||||
|
settingsItem.setTitle(i18n("modpack"));
|
||||||
|
settingsItem.setLeftGraphic(wrap(SVG.pack(null, 20, 20)));
|
||||||
|
settingsItem.activeProperty().bind(tab.getSelectionModel().selectedItemProperty().isEqualTo(modpackTab));
|
||||||
|
settingsItem.setOnAction(e -> tab.getSelectionModel().select(modpackTab));
|
||||||
|
})
|
||||||
|
.addNavigationDrawerItem(item -> {
|
||||||
|
item.setTitle(i18n("resourcepack"));
|
||||||
|
item.setLeftGraphic(wrap(SVG.textureBox(null, 20, 20)));
|
||||||
|
item.activeProperty().bind(tab.getSelectionModel().selectedItemProperty().isEqualTo(resourcePackTab));
|
||||||
|
item.setOnAction(e -> tab.getSelectionModel().select(resourcePackTab));
|
||||||
|
});
|
||||||
|
FXUtils.setLimitWidth(sideBar, 200);
|
||||||
|
setLeft(sideBar);
|
||||||
|
}
|
||||||
|
|
||||||
|
setCenter(transitionPane);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void download(Profile profile, @Nullable String version, CurseAddon.LatestFile file) {
|
||||||
|
if (version == null) {
|
||||||
|
throw new InternalError();
|
||||||
|
}
|
||||||
|
|
||||||
|
Path dest = profile.getRepository().getRunDirectory(version).toPath().resolve("mods").resolve(file.getFileName());
|
||||||
|
|
||||||
|
TaskExecutorDialogPane downloadingPane = new TaskExecutorDialogPane(it -> {
|
||||||
|
});
|
||||||
|
|
||||||
|
TaskExecutor executor = Task.composeAsync(() -> {
|
||||||
|
FileDownloadTask task = new FileDownloadTask(NetworkUtils.toURL(file.getDownloadUrl()), dest.toFile());
|
||||||
|
task.setName(file.getDisplayName());
|
||||||
|
return task;
|
||||||
|
}).executor(false);
|
||||||
|
|
||||||
|
downloadingPane.setExecutor(executor, true);
|
||||||
|
Controllers.dialog(downloadingPane);
|
||||||
|
executor.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadVersions(Profile profile) {
|
||||||
|
WeakListenerHolder listenerHolder = new WeakListenerHolder();
|
||||||
|
runInFX(() -> {
|
||||||
|
if (profile == Profiles.getSelectedProfile()) {
|
||||||
|
profile.selectedVersionProperty().addListener(listenerHolder.weak((a, b, newValue) -> {
|
||||||
|
FXUtils.checkFxUserThread();
|
||||||
|
|
||||||
|
if (modTab.isInitialized()) {
|
||||||
|
modTab.getNode().loadVersion(profile, newValue);
|
||||||
|
}
|
||||||
|
if (modpackTab.isInitialized()) {
|
||||||
|
modpackTab.getNode().loadVersion(profile, newValue);
|
||||||
|
}
|
||||||
|
if (resourcePackTab.isInitialized()) {
|
||||||
|
resourcePackTab.getNode().loadVersion(profile, newValue);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ReadOnlyObjectProperty<State> stateProperty() {
|
||||||
|
return state.getReadOnlyProperty();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -167,6 +167,14 @@ public class RootPage extends DecoratorTabPage {
|
|||||||
gameItem.setTitle(i18n("version.manage"));
|
gameItem.setTitle(i18n("version.manage"));
|
||||||
gameItem.setOnAction(e -> Controllers.navigate(Controllers.getGameListPage()));
|
gameItem.setOnAction(e -> Controllers.navigate(Controllers.getGameListPage()));
|
||||||
|
|
||||||
|
// forth item in left sidebar
|
||||||
|
AdvancedListItem downloadItem = new AdvancedListItem();
|
||||||
|
downloadItem
|
||||||
|
.setLeftGraphic(AdvancedListItem.createImageView(newImage("/assets/img/chest.png")).getKey());
|
||||||
|
downloadItem.setActionButtonVisible(false);
|
||||||
|
downloadItem.setTitle(i18n("download"));
|
||||||
|
downloadItem.setOnAction(e -> Controllers.navigate(Controllers.getDownloadPage()));
|
||||||
|
|
||||||
// fifth item in left sidebar
|
// fifth item in left sidebar
|
||||||
AdvancedListItem launcherSettingsItem = new AdvancedListItem();
|
AdvancedListItem launcherSettingsItem = new AdvancedListItem();
|
||||||
launcherSettingsItem
|
launcherSettingsItem
|
||||||
@@ -182,6 +190,7 @@ public class RootPage extends DecoratorTabPage {
|
|||||||
.startCategory(i18n("version").toUpperCase())
|
.startCategory(i18n("version").toUpperCase())
|
||||||
.add(gameListItem)
|
.add(gameListItem)
|
||||||
.add(gameItem)
|
.add(gameItem)
|
||||||
|
.add(downloadItem)
|
||||||
.add(launcherSettingsItem);
|
.add(launcherSettingsItem);
|
||||||
|
|
||||||
// the root page, with the sidebar in left, navigator in center.
|
// the root page, with the sidebar in left, navigator in center.
|
||||||
|
|||||||
@@ -107,15 +107,15 @@ public class VersionPage extends Control implements DecoratorPage, ModDownloadPa
|
|||||||
setVersion(version, profile);
|
setVersion(version, profile);
|
||||||
preferredVersionName = version;
|
preferredVersionName = version;
|
||||||
|
|
||||||
if (versionSettingsTab.getNode() != null)
|
if (versionSettingsTab.isInitialized())
|
||||||
versionSettingsTab.getNode().loadVersion(profile, version);
|
versionSettingsTab.getNode().loadVersion(profile, version);
|
||||||
if (modListTab.getNode() != null)
|
if (modListTab.isInitialized())
|
||||||
modListTab.getNode().loadVersion(profile, version);
|
modListTab.getNode().loadVersion(profile, version);
|
||||||
if (curseModListTab.getNode() != null)
|
if (curseModListTab.isInitialized())
|
||||||
curseModListTab.getNode().loadVersion(profile, version);
|
curseModListTab.getNode().loadVersion(profile, version);
|
||||||
if (installerListTab.getNode() != null)
|
if (installerListTab.isInitialized())
|
||||||
installerListTab.getNode().loadVersion(profile, version);
|
installerListTab.getNode().loadVersion(profile, version);
|
||||||
if (worldListTab.getNode() != null)
|
if (worldListTab.isInitialized())
|
||||||
worldListTab.getNode().loadVersion(profile, version);
|
worldListTab.getNode().loadVersion(profile, version);
|
||||||
currentVersionUpgradable.set(profile.getRepository().isModpack(version));
|
currentVersionUpgradable.set(profile.getRepository().isModpack(version));
|
||||||
}
|
}
|
||||||
@@ -251,7 +251,7 @@ public class VersionPage extends Control implements DecoratorPage, ModDownloadPa
|
|||||||
|
|
||||||
AdvancedListItem modListItem = new AdvancedListItem();
|
AdvancedListItem modListItem = new AdvancedListItem();
|
||||||
modListItem.getStyleClass().add("navigation-drawer-item");
|
modListItem.getStyleClass().add("navigation-drawer-item");
|
||||||
modListItem.setTitle(i18n("mods"));
|
modListItem.setTitle(i18n("mods.manage"));
|
||||||
modListItem.setLeftGraphic(wrap(SVG.puzzle(null, 20, 20)));
|
modListItem.setLeftGraphic(wrap(SVG.puzzle(null, 20, 20)));
|
||||||
modListItem.setActionButtonVisible(false);
|
modListItem.setActionButtonVisible(false);
|
||||||
modListItem.activeProperty().bind(control.tab.getSelectionModel().selectedItemProperty().isEqualTo(control.modListTab));
|
modListItem.activeProperty().bind(control.tab.getSelectionModel().selectedItemProperty().isEqualTo(control.modListTab));
|
||||||
@@ -380,7 +380,7 @@ public class VersionPage extends Control implements DecoratorPage, ModDownloadPa
|
|||||||
return stackPane;
|
return stackPane;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface VersionLoadable {
|
public interface VersionLoadable {
|
||||||
void loadVersion(Profile profile, String version);
|
void loadVersion(Profile profile, String version);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -397,6 +397,7 @@ mods.disable=Disable
|
|||||||
mods.download=Mod Downloads
|
mods.download=Mod Downloads
|
||||||
mods.download.title=Mod Downloads - %1s
|
mods.download.title=Mod Downloads - %1s
|
||||||
mods.enable=Enable
|
mods.enable=Enable
|
||||||
|
mods.manage=Mods
|
||||||
mods.mcmod.page=MCWiki
|
mods.mcmod.page=MCWiki
|
||||||
mods.mcmod.search=Search in MCWiki
|
mods.mcmod.search=Search in MCWiki
|
||||||
mods.name=Name
|
mods.name=Name
|
||||||
@@ -443,6 +444,8 @@ profile.title=Game Directories
|
|||||||
profile.selected=Selected
|
profile.selected=Selected
|
||||||
profile.use_relative_path=Use relative path for game directory if possible
|
profile.use_relative_path=Use relative path for game directory if possible
|
||||||
|
|
||||||
|
resourcepack=Resource Pack
|
||||||
|
|
||||||
selector.choose=Choose
|
selector.choose=Choose
|
||||||
selector.choose_file=Select a file
|
selector.choose_file=Select a file
|
||||||
selector.custom=Custom
|
selector.custom=Custom
|
||||||
|
|||||||
@@ -296,13 +296,14 @@ modpack.wizard.step.initialization.save=選擇要匯出到的遊戲整合包位
|
|||||||
modpack.wizard.step.initialization.warning=在製作整合包前,請您確認您選擇的版本可以正常啟動,\n並保證您的 Minecraft 是正式版而非快照版,\n而且不應將不允許非官方途徑傳播的 Mod 模組、材質包等納入整合包。\n整合包會儲存您目前的下載來源設定
|
modpack.wizard.step.initialization.warning=在製作整合包前,請您確認您選擇的版本可以正常啟動,\n並保證您的 Minecraft 是正式版而非快照版,\n而且不應將不允許非官方途徑傳播的 Mod 模組、材質包等納入整合包。\n整合包會儲存您目前的下載來源設定
|
||||||
modpack.wizard.step.initialization.server=點選此處查看有關伺服器自動更新整合包的製作教學
|
modpack.wizard.step.initialization.server=點選此處查看有關伺服器自動更新整合包的製作教學
|
||||||
|
|
||||||
mods=模組管理
|
mods=模組
|
||||||
mods.add=新增模組
|
mods.add=新增模組
|
||||||
mods.add.failed=新增模組 %s 失敗。
|
mods.add.failed=新增模組 %s 失敗。
|
||||||
mods.add.success=成功新增模組 %s。
|
mods.add.success=成功新增模組 %s。
|
||||||
mods.choose_mod=選擇模組
|
mods.choose_mod=選擇模組
|
||||||
mods.enable=啟用
|
mods.enable=啟用
|
||||||
mods.disable=停用
|
mods.disable=停用
|
||||||
|
mods.mangage=模組管理
|
||||||
mods.name=名稱
|
mods.name=名稱
|
||||||
mods.not_modded=你需要先在自動安裝頁面安裝 Fabric、Forge 或 LiteLoader 才能進行模組管理。
|
mods.not_modded=你需要先在自動安裝頁面安裝 Fabric、Forge 或 LiteLoader 才能進行模組管理。
|
||||||
|
|
||||||
|
|||||||
@@ -389,7 +389,7 @@ modpack.wizard.step.initialization.save=选择要导出到的游戏整合包位
|
|||||||
modpack.wizard.step.initialization.warning=在制作整合包前,请您确认您选择的版本可以正常启动,\n并保证您的 Minecraft 是正式版而非快照版,\n而且不应当将不允许非官方途径传播的 Mod、材质包等纳入整合包。\n整合包会保存您目前的下载源设置
|
modpack.wizard.step.initialization.warning=在制作整合包前,请您确认您选择的版本可以正常启动,\n并保证您的 Minecraft 是正式版而非快照版,\n而且不应当将不允许非官方途径传播的 Mod、材质包等纳入整合包。\n整合包会保存您目前的下载源设置
|
||||||
modpack.wizard.step.initialization.server=点击此处查看有关服务器自动更新整合包的制作教程
|
modpack.wizard.step.initialization.server=点击此处查看有关服务器自动更新整合包的制作教程
|
||||||
|
|
||||||
mods=模组管理
|
mods=模组
|
||||||
mods.add=添加模组
|
mods.add=添加模组
|
||||||
mods.add.failed=添加模组 %s 失败。
|
mods.add.failed=添加模组 %s 失败。
|
||||||
mods.add.success=成功添加模组 %s。
|
mods.add.success=成功添加模组 %s。
|
||||||
@@ -399,6 +399,7 @@ mods.disable=禁用
|
|||||||
mods.download=模组下载
|
mods.download=模组下载
|
||||||
mods.download.title=模组下载 - %1s
|
mods.download.title=模组下载 - %1s
|
||||||
mods.enable=启用
|
mods.enable=启用
|
||||||
|
mods.manage=模组管理
|
||||||
mods.mcmod.page=MC 百科页面
|
mods.mcmod.page=MC 百科页面
|
||||||
mods.mcmod.search=MC 百科搜索
|
mods.mcmod.search=MC 百科搜索
|
||||||
mods.name=名称
|
mods.name=名称
|
||||||
@@ -445,6 +446,8 @@ profile.title=游戏目录
|
|||||||
profile.selected=已选中
|
profile.selected=已选中
|
||||||
profile.use_relative_path=若可能,游戏目录使用相对路径
|
profile.use_relative_path=若可能,游戏目录使用相对路径
|
||||||
|
|
||||||
|
resourcepack=资源包
|
||||||
|
|
||||||
search=搜索
|
search=搜索
|
||||||
search.sort=排序
|
search.sort=排序
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user