mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-09-22 10:43:57 -04:00
世界管理新增删除世界功能 (#4263)
Co-authored-by: 3gf8jv4dv <3gf8jv4dv@gmail.com> Co-authored-by: Glavo <zjx001202@gmail.com>
This commit is contained in:
parent
f594abc37d
commit
7c024473d6
@ -147,7 +147,7 @@ public final class WorldBackupsPage extends ListPageBase<WorldBackupsPage.Backup
|
||||
WorldBackupsPage.this.getItems().sort(Comparator.naturalOrder());
|
||||
Controllers.dialog(i18n("world.backup.create.success", result.getKey()), null, MessageDialogPane.MessageType.INFO);
|
||||
} else if (exception instanceof WorldLockedException) {
|
||||
Controllers.dialog(i18n("world.backup.create.locked"), null, MessageDialogPane.MessageType.WARNING);
|
||||
Controllers.dialog(i18n("world.locked.failed"), null, MessageDialogPane.MessageType.WARNING);
|
||||
} else {
|
||||
LOG.warning("Failed to create backup", exception);
|
||||
Controllers.dialog(i18n("world.backup.create.failed", StringUtils.getStackTrace(exception)), null, MessageDialogPane.MessageType.WARNING);
|
||||
|
@ -21,9 +21,14 @@ import javafx.scene.control.Control;
|
||||
import javafx.scene.control.Skin;
|
||||
import javafx.stage.FileChooser;
|
||||
import org.jackhuang.hmcl.game.World;
|
||||
import org.jackhuang.hmcl.game.WorldLockedException;
|
||||
import org.jackhuang.hmcl.task.Schedulers;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
import org.jackhuang.hmcl.ui.Controllers;
|
||||
import org.jackhuang.hmcl.ui.FXUtils;
|
||||
import org.jackhuang.hmcl.ui.construct.MessageDialogPane.MessageType;
|
||||
import org.jackhuang.hmcl.ui.wizard.SinglePageWizardProvider;
|
||||
import org.jackhuang.hmcl.util.StringUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
@ -33,10 +38,12 @@ import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||
public final class WorldListItem extends Control {
|
||||
private final World world;
|
||||
private final Path backupsDir;
|
||||
private final WorldListPage parent;
|
||||
|
||||
public WorldListItem(World world, Path backupsDir) {
|
||||
public WorldListItem(WorldListPage parent, World world, Path backupsDir) {
|
||||
this.world = world;
|
||||
this.backupsDir = backupsDir;
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -61,6 +68,24 @@ public final class WorldListItem extends Control {
|
||||
Controllers.getDecorator().startWizard(new SinglePageWizardProvider(controller -> new WorldExportPage(world, file.toPath(), controller::onFinish)));
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
Controllers.confirm(
|
||||
i18n("button.remove.confirm"),
|
||||
i18n("world.delete"),
|
||||
() -> Task.runAsync(world::delete)
|
||||
.whenComplete(Schedulers.javafx(), (result, exception) -> {
|
||||
if (exception == null) {
|
||||
parent.remove(this);
|
||||
} else if (exception instanceof WorldLockedException) {
|
||||
Controllers.dialog(i18n("world.locked.failed"), null, MessageType.WARNING);
|
||||
} else {
|
||||
Controllers.dialog(i18n("world.delete.failed", StringUtils.getStackTrace(exception)), null, MessageType.WARNING);
|
||||
}
|
||||
}).start(),
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
public void reveal() {
|
||||
FXUtils.openFolder(world.getFile().toFile());
|
||||
}
|
||||
|
@ -136,6 +136,7 @@ public final class WorldListItemSkin extends SkinBase<WorldListItem> {
|
||||
popupMenu.getContent().addAll(
|
||||
new MenuSeparator(),
|
||||
new IconedMenuItem(SVG.OUTPUT, i18n("world.export"), item::export, popup),
|
||||
new IconedMenuItem(SVG.DELETE, i18n("world.delete"), item::delete, popup),
|
||||
new IconedMenuItem(SVG.FOLDER_OPEN, i18n("folder.world"), item::reveal, popup));
|
||||
|
||||
JFXPopup.PopupVPosition vPosition = determineOptimalPopupPosition(root, popup);
|
||||
|
@ -39,8 +39,8 @@ import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.jackhuang.hmcl.util.logging.Logger.LOG;
|
||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||
import static org.jackhuang.hmcl.util.logging.Logger.LOG;
|
||||
|
||||
public final class WorldListPage extends ListPageBase<WorldListItem> implements VersionPage.VersionLoadable {
|
||||
private final BooleanProperty showAll = new SimpleBooleanProperty(this, "showAll", false);
|
||||
@ -61,7 +61,7 @@ public final class WorldListPage extends ListPageBase<WorldListItem> implements
|
||||
if (worlds != null)
|
||||
itemsProperty().setAll(worlds.stream()
|
||||
.filter(world -> isShowAll() || world.getGameVersion() == null || world.getGameVersion().equals(gameVersion))
|
||||
.map(world -> new WorldListItem(world, backupsDir)).collect(Collectors.toList()));
|
||||
.map(world -> new WorldListItem(this, world, backupsDir)).toList());
|
||||
});
|
||||
}
|
||||
|
||||
@ -79,6 +79,10 @@ public final class WorldListPage extends ListPageBase<WorldListItem> implements
|
||||
refresh();
|
||||
}
|
||||
|
||||
public void remove(WorldListItem item) {
|
||||
itemsProperty().remove(item);
|
||||
}
|
||||
|
||||
public void refresh() {
|
||||
if (profile == null || id == null)
|
||||
return;
|
||||
@ -94,8 +98,10 @@ public final class WorldListPage extends ListPageBase<WorldListItem> implements
|
||||
worlds = result;
|
||||
setLoading(false);
|
||||
if (exception == null) {
|
||||
itemsProperty().setAll(result.stream().filter(world -> isShowAll() || world.getGameVersion() == null || world.getGameVersion().equals(gameVersion))
|
||||
.map(world -> new WorldListItem(world, backupsDir)).collect(Collectors.toList()));
|
||||
itemsProperty().setAll(result.stream()
|
||||
.filter(world -> isShowAll() || world.getGameVersion() == null || world.getGameVersion().equals(gameVersion))
|
||||
.map(world -> new WorldListItem(this, world, backupsDir))
|
||||
.collect(Collectors.toList()));
|
||||
} else {
|
||||
LOG.warning("Failed to load world list page", exception);
|
||||
}
|
||||
@ -125,7 +131,7 @@ public final class WorldListPage extends ListPageBase<WorldListItem> implements
|
||||
Controllers.prompt(i18n("world.name.enter"), (name, resolve, reject) -> {
|
||||
Task.runAsync(() -> world.install(savesDir, name))
|
||||
.whenComplete(Schedulers.javafx(), () -> {
|
||||
itemsProperty().add(new WorldListItem(new World(savesDir.resolve(name)), backupsDir));
|
||||
itemsProperty().add(new WorldListItem(this, new World(savesDir.resolve(name)), backupsDir));
|
||||
resolve.run();
|
||||
}, e -> {
|
||||
if (e instanceof FileAlreadyExistsException)
|
||||
|
@ -1113,7 +1113,6 @@ world.add=Add World
|
||||
world.backup=World Backup
|
||||
world.backup.create.new_one=Create New Backup
|
||||
world.backup.create.failed=Failed to create backup.\n%s
|
||||
world.backup.create.locked=The world is currently in use. Please close the game and try again.
|
||||
world.backup.create.success=Successfully created a new backup: %s
|
||||
world.backup.delete=Delete this backup
|
||||
world.backup.processing=Backing up ...
|
||||
@ -1124,6 +1123,8 @@ world.chunkbase.stronghold=Stronghold
|
||||
world.chunkbase.nether_fortress=Nether Fortress
|
||||
world.datapack=Datapacks
|
||||
world.datetime=Last played on %s
|
||||
world.delete=Delete the World
|
||||
world.delete.failed=Failed to delete world.\n%s
|
||||
world.download=Download World
|
||||
world.download.title=Download World - %1s
|
||||
world.export=Export the World
|
||||
@ -1167,6 +1168,7 @@ world.info.random_seed=Seed
|
||||
world.info.time=Game Time
|
||||
world.info.time.format=%s days
|
||||
world.locked=In use
|
||||
world.locked.failed=The world is currently in use. Please close the game and try again.
|
||||
world.manage=Worlds
|
||||
world.manage.button=World Management
|
||||
world.manage.title=World - %s
|
||||
|
@ -1113,7 +1113,6 @@ world.add=Añadir mundo
|
||||
world.backup=Copia de seguridad
|
||||
world.backup.create.new_one=Crear uno nuevo
|
||||
world.backup.create.failed=No se ha podido crear la copia de seguridad.\n%s
|
||||
world.backup.create.locked=El mundo está actualmente en uso. Por favor, cierra el juego e inténtalo de nuevo.
|
||||
world.backup.create.success=Creada con éxito una nueva copia de seguridad: %s
|
||||
world.backup.delete=Eliminar esta copia de seguridad
|
||||
world.backup.processing=Creando nueva copia de seguridad ...
|
||||
@ -1124,6 +1123,8 @@ world.chunkbase.stronghold=Fortaleza
|
||||
world.chunkbase.nether_fortress=Fortaleza del Nether
|
||||
world.datapack=Paquetes de datos
|
||||
world.datetime=Jugado por última vez en %s
|
||||
world.delete=Eliminar este mundo
|
||||
world.delete.failed=No se pudo eliminar el mundo.\n%s
|
||||
world.download=Descargar Mundo
|
||||
world.download.title=Descargar mundo - %1s
|
||||
world.export=Exportar el mundo
|
||||
@ -1166,6 +1167,7 @@ world.info.random_seed=Semilla
|
||||
world.info.time=Tiempo de juego
|
||||
world.info.time.format=%s días
|
||||
world.locked=En uso
|
||||
world.locked.failed=El mundo está actualmente en uso. Por favor, cierra el juego e inténtalo de nuevo.
|
||||
world.manage=Mundos
|
||||
world.manage.button=Administrar
|
||||
world.manage.title=Mundo - %s
|
||||
|
@ -705,6 +705,8 @@ world=マップ
|
||||
world.add=マップを追加(.zip)
|
||||
world.datapack=データパックの管理
|
||||
world.datetime=最終ゲーム時刻:%s
|
||||
world.delete=このマップを削除
|
||||
world.delete.failed=マップの削除に失敗しました\n%s
|
||||
world.download=ダウンロード
|
||||
world.export=このマップをエクスポートする
|
||||
world.export.title=保存する場所を選択してください
|
||||
|
@ -929,6 +929,8 @@ world.chunkbase.stronghold=要塞輿圖
|
||||
world.chunkbase.nether_fortress=焱界府輿圖
|
||||
world.datapack=司錄囊
|
||||
world.datetime=前戲之時辰: %s
|
||||
world.delete=刪斯生界
|
||||
world.delete.failed=刪斯生界未成\n%s
|
||||
world.download=引生界
|
||||
world.download.title=引生界 - %1s
|
||||
world.export=錄出生界
|
||||
|
@ -1112,7 +1112,6 @@ world.add=Добавить мир
|
||||
world.backup=Резервный мир
|
||||
world.backup.create.new_one=Создать новый
|
||||
world.backup.create.failed=Не удалось создать резервную копию.\n%s
|
||||
world.backup.create.locked=В настоящее время мир находится в эксплуатации. Закройте игру и попробуйте снова.
|
||||
world.backup.create.success=Успешно создано новое резервное копирование: %s
|
||||
world.backup.delete=Удалить эту резервную копию
|
||||
world.backup.processing=Создание новой резервной копии ...
|
||||
@ -1121,6 +1120,8 @@ world.chunkbase.end_city=Город Края
|
||||
world.chunkbase.seed_map=Предпросмотр генерации мира
|
||||
world.chunkbase.stronghold=Крепость
|
||||
world.chunkbase.nether_fortress=Крепость Нижнего мира
|
||||
world.delete=Удалить этот мир
|
||||
world.delete.failed=Не удалось удалить мир.\n%s
|
||||
world.datapack=Наборы данных
|
||||
world.datetime=Последний запуск игры %s
|
||||
world.download=Скачать мир
|
||||
@ -1165,6 +1166,7 @@ world.info.random_seed=Ключ генератора мира
|
||||
world.info.time=Время игры
|
||||
world.info.time.format=%s дн.
|
||||
world.locked=В эксплуатации
|
||||
world.locked.failed=В настоящее время мир находится в эксплуатации. Закройте игру и попробуйте снова.
|
||||
world.manage=Миры
|
||||
world.manage.button=Управлять
|
||||
world.manage.title=Мир - %s
|
||||
|
@ -1053,7 +1053,6 @@ world.add=Додати світ
|
||||
world.backup=Резервне копіювання світу
|
||||
world.backup.create.new_one=Створити нову резервну копію
|
||||
world.backup.create.failed=Не вдалося створити резервну копію. \n%s
|
||||
world.backup.create.locked=Світ наразі використовується. Закрийте гру та спробуйте знову.
|
||||
world.backup.create.success=Успішно створено нову резервну копію: %s
|
||||
world.backup.delete=Видалити цю резервну копію
|
||||
world.backup.processing=Резервне копіювання ...
|
||||
@ -1064,6 +1063,8 @@ world.chunkbase.stronghold=Фортеця
|
||||
world.chunkbase.nether_fortress=Форт Незеру
|
||||
world.datapack=Datapacks
|
||||
world.datetime=Останній раз грали %s
|
||||
world.delete=Видалити цей світ
|
||||
world.delete.failed=Не вдалося видалити світ.\n%s
|
||||
world.download=Завантажити світ
|
||||
world.download.title=Завантажити світ - %1s
|
||||
world.export=Експортувати світ
|
||||
@ -1107,6 +1108,7 @@ world.info.random_seed=Насіння
|
||||
world.info.time=Час гри
|
||||
world.info.time.format=%s днів
|
||||
world.locked=Використовується
|
||||
world.locked.failed=Світ наразі використовується. Закрийте гру та спробуйте знову.
|
||||
world.manage=Світи
|
||||
world.manage.button=Керування світами
|
||||
world.manage.title=Світ - %s
|
||||
|
@ -910,7 +910,6 @@ world.add=新增世界
|
||||
world.backup=世界備份
|
||||
world.backup.create.new_one=建立新備份
|
||||
world.backup.create.failed=建立備份失敗。\n%s
|
||||
world.backup.create.locked=該世界正在使用中,請關閉遊戲後重試。
|
||||
world.backup.create.success=成功建立新備份:%s
|
||||
world.backup.delete=刪除此備份
|
||||
world.backup.processing=正在備份中……
|
||||
@ -921,6 +920,8 @@ world.chunkbase.stronghold=要塞地圖
|
||||
world.chunkbase.nether_fortress=地獄要塞地圖
|
||||
world.datapack=資料包管理
|
||||
world.datetime=上一次遊戲時間: %s
|
||||
world.delete=刪除此世界
|
||||
world.delete.failed=刪除世界失敗。\n%s
|
||||
world.download=下載世界
|
||||
world.download.title=世界下載 - %1s
|
||||
world.export=匯出此世界
|
||||
@ -963,6 +964,7 @@ world.info.random_seed=種子碼
|
||||
world.info.time=遊戲內時間
|
||||
world.info.time.format=%s 天
|
||||
world.locked=使用中
|
||||
world.locked.failed=該世界正在使用中,請關閉遊戲後重試。
|
||||
world.game_version=遊戲版本
|
||||
world.manage=世界管理
|
||||
world.manage.button=世界管理
|
||||
|
@ -920,7 +920,6 @@ world.add=添加世界
|
||||
world.backup=备份管理
|
||||
world.backup.create.new_one=创建新备份
|
||||
world.backup.create.failed=创建备份失败。\n%s
|
||||
world.backup.create.locked=该世界正在使用中,请关闭游戏后重试。
|
||||
world.backup.create.success=成功创建新备份:%s
|
||||
world.backup.delete=删除此备份
|
||||
world.backup.processing=正在备份中……
|
||||
@ -931,6 +930,8 @@ world.chunkbase.stronghold=要塞地图
|
||||
world.chunkbase.nether_fortress=下界要塞地图
|
||||
world.datapack=数据包管理
|
||||
world.datetime=上一次游戏时间: %s
|
||||
world.delete=删除此世界
|
||||
world.delete.failed=删除世界失败。\n%s
|
||||
world.download=下载世界
|
||||
world.download.title=世界下载 - %1s
|
||||
world.export=导出此世界
|
||||
@ -974,6 +975,7 @@ world.info.random_seed=种子
|
||||
world.info.time=游戏内时间
|
||||
world.info.time.format=%s 天
|
||||
world.locked=使用中
|
||||
world.locked.failed=该世界正在使用中,请关闭游戏后重试。
|
||||
world.manage=世界管理
|
||||
world.manage.button=世界管理
|
||||
world.manage.title=世界管理 - %s
|
||||
|
@ -275,6 +275,13 @@ public final class World {
|
||||
}
|
||||
}
|
||||
|
||||
public void delete() throws IOException {
|
||||
if (isLocked()) {
|
||||
throw new WorldLockedException("The world " + getFile() + " has been locked");
|
||||
}
|
||||
FileUtils.deleteDirectory(file);
|
||||
}
|
||||
|
||||
public CompoundTag readLevelDat() throws IOException {
|
||||
if (!Files.isDirectory(file))
|
||||
throw new IOException("Not a valid world directory");
|
||||
|
Loading…
x
Reference in New Issue
Block a user