From 1119f6c3cf421da2f2db92873efae8135c76b678 Mon Sep 17 00:00:00 2001 From: HsiangNianian Date: Fri, 16 Jan 2026 18:38:47 +0800 Subject: feat: enhance Java version management for Minecraft versions Added functionality to determine and validate the required Java version for Minecraft versions, including checks for compatibility with older versions. Implemented event emissions for version installation and deletion, and updated the UI to reflect Java version requirements and installation status. Improved version metadata handling and added support for deleting versions. --- ui/src/stores/game.svelte.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'ui/src/stores/game.svelte.ts') diff --git a/ui/src/stores/game.svelte.ts b/ui/src/stores/game.svelte.ts index 28b2db5..ca5dc2b 100644 --- a/ui/src/stores/game.svelte.ts +++ b/ui/src/stores/game.svelte.ts @@ -14,10 +14,8 @@ export class GameState { async loadVersions() { try { this.versions = await invoke("get_versions"); - if (this.versions.length > 0) { - const latest = this.versions.find((v) => v.type === "release"); - this.selectedVersion = latest ? latest.id : this.versions[0].id; - } + // Don't auto-select version here - let BottomBar handle version selection + // based on installed versions only } catch (e) { console.error("Failed to fetch versions:", e); uiState.setStatus("Error fetching versions: " + e); -- cgit v1.2.3-70-g09d2 From 3c13c14dea03c6b91716fb0f1578deb12fcf9756 Mon Sep 17 00:00:00 2001 From: HsiangNianian Date: Fri, 16 Jan 2026 20:20:05 +0800 Subject: feat: implement instance management functionality Added a new InstancesState class to manage game instances, including loading, creating, deleting, updating, and duplicating instances. Integrated instance selection into the game launch process, ensuring an active instance is selected before starting a game. Updated the types to include instance-related data structures. --- ui/src/stores/game.svelte.ts | 14 ++++- ui/src/stores/instances.svelte.ts | 109 ++++++++++++++++++++++++++++++++++++++ ui/src/types/index.ts | 17 +++++- 3 files changed, 137 insertions(+), 3 deletions(-) create mode 100644 ui/src/stores/instances.svelte.ts (limited to 'ui/src/stores/game.svelte.ts') diff --git a/ui/src/stores/game.svelte.ts b/ui/src/stores/game.svelte.ts index ca5dc2b..3efcf71 100644 --- a/ui/src/stores/game.svelte.ts +++ b/ui/src/stores/game.svelte.ts @@ -2,6 +2,7 @@ import { invoke } from "@tauri-apps/api/core"; import type { Version } from "../types"; import { uiState } from "./ui.svelte"; import { authState } from "./auth.svelte"; +import { instancesState } from "./instances.svelte"; export class GameState { versions = $state([]); @@ -34,10 +35,19 @@ export class GameState { return; } + if (!instancesState.activeInstanceId) { + alert("Please select an instance first!"); + uiState.setView("instances"); + return; + } + uiState.setStatus("Preparing to launch " + this.selectedVersion + "..."); - console.log("Invoking start_game for version:", this.selectedVersion); + console.log("Invoking start_game for version:", this.selectedVersion, "instance:", instancesState.activeInstanceId); try { - const msg = await invoke("start_game", { versionId: this.selectedVersion }); + const msg = await invoke("start_game", { + instanceId: instancesState.activeInstanceId, + versionId: this.selectedVersion, + }); console.log("Response:", msg); uiState.setStatus(msg); } catch (e) { diff --git a/ui/src/stores/instances.svelte.ts b/ui/src/stores/instances.svelte.ts new file mode 100644 index 0000000..f4ac4e9 --- /dev/null +++ b/ui/src/stores/instances.svelte.ts @@ -0,0 +1,109 @@ +import { invoke } from "@tauri-apps/api/core"; +import type { Instance } from "../types"; +import { uiState } from "./ui.svelte"; + +export class InstancesState { + instances = $state([]); + activeInstanceId = $state(null); + get activeInstance(): Instance | null { + if (!this.activeInstanceId) return null; + return this.instances.find((i) => i.id === this.activeInstanceId) || null; + } + + async loadInstances() { + try { + this.instances = await invoke("list_instances"); + const active = await invoke("get_active_instance"); + if (active) { + this.activeInstanceId = active.id; + } else if (this.instances.length > 0) { + // If no active instance but instances exist, set the first one as active + await this.setActiveInstance(this.instances[0].id); + } + } catch (e) { + console.error("Failed to load instances:", e); + uiState.setStatus("Error loading instances: " + e); + } + } + + async createInstance(name: string): Promise { + try { + const instance = await invoke("create_instance", { name }); + await this.loadInstances(); + uiState.setStatus(`Instance "${name}" created successfully`); + return instance; + } catch (e) { + console.error("Failed to create instance:", e); + uiState.setStatus("Error creating instance: " + e); + return null; + } + } + + async deleteInstance(id: string) { + try { + await invoke("delete_instance", { instanceId: id }); + await this.loadInstances(); + // If deleted instance was active, set another as active + if (this.activeInstanceId === id) { + if (this.instances.length > 0) { + await this.setActiveInstance(this.instances[0].id); + } else { + this.activeInstanceId = null; + } + } + uiState.setStatus("Instance deleted successfully"); + } catch (e) { + console.error("Failed to delete instance:", e); + uiState.setStatus("Error deleting instance: " + e); + } + } + + async updateInstance(instance: Instance) { + try { + await invoke("update_instance", { instance }); + await this.loadInstances(); + uiState.setStatus("Instance updated successfully"); + } catch (e) { + console.error("Failed to update instance:", e); + uiState.setStatus("Error updating instance: " + e); + } + } + + async setActiveInstance(id: string) { + try { + await invoke("set_active_instance", { instanceId: id }); + this.activeInstanceId = id; + uiState.setStatus("Active instance changed"); + } catch (e) { + console.error("Failed to set active instance:", e); + uiState.setStatus("Error setting active instance: " + e); + } + } + + async duplicateInstance(id: string, newName: string): Promise { + try { + const instance = await invoke("duplicate_instance", { + instanceId: id, + newName, + }); + await this.loadInstances(); + uiState.setStatus(`Instance duplicated as "${newName}"`); + return instance; + } catch (e) { + console.error("Failed to duplicate instance:", e); + uiState.setStatus("Error duplicating instance: " + e); + return null; + } + } + + async getInstance(id: string): Promise { + try { + return await invoke("get_instance", { instanceId: id }); + } catch (e) { + console.error("Failed to get instance:", e); + return null; + } + } +} + +export const instancesState = new InstancesState(); diff --git a/ui/src/types/index.ts b/ui/src/types/index.ts index 9a4da2b..a5b336e 100644 --- a/ui/src/types/index.ts +++ b/ui/src/types/index.ts @@ -1,4 +1,4 @@ -export type ViewType = "home" | "versions" | "settings" | "guide"; +export type ViewType = "home" | "versions" | "settings" | "guide" | "instances"; export interface Version { id: string; @@ -187,3 +187,18 @@ export interface InstalledForgeVersion { // ==================== Mod Loader Type ==================== export type ModLoaderType = "vanilla" | "fabric" | "forge"; + +// ==================== Instance Types ==================== + +export interface Instance { + id: string; + name: string; + game_dir: string; + version_id?: string; + created_at: number; + last_played?: number; + icon_path?: string; + notes?: string; + mod_loader?: string; + mod_loader_version?: string; +} -- cgit v1.2.3-70-g09d2 From e6de034475c8cdaef4a65d04dad7c626805d2ffc Mon Sep 17 00:00:00 2001 From: HsiangNianian <44714368+HsiangNianian@users.noreply.github.com> Date: Fri, 16 Jan 2026 12:56:47 +0000 Subject: style: auto format and lint fix [skip ci] --- ui/src/stores/game.svelte.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'ui/src/stores/game.svelte.ts') diff --git a/ui/src/stores/game.svelte.ts b/ui/src/stores/game.svelte.ts index 3efcf71..1e4119f 100644 --- a/ui/src/stores/game.svelte.ts +++ b/ui/src/stores/game.svelte.ts @@ -42,7 +42,12 @@ export class GameState { } uiState.setStatus("Preparing to launch " + this.selectedVersion + "..."); - console.log("Invoking start_game for version:", this.selectedVersion, "instance:", instancesState.activeInstanceId); + console.log( + "Invoking start_game for version:", + this.selectedVersion, + "instance:", + instancesState.activeInstanceId, + ); try { const msg = await invoke("start_game", { instanceId: instancesState.activeInstanceId, -- cgit v1.2.3-70-g09d2