fix: support concurrent game windows and prepare beta12 GitHub releases
This commit is contained in:
1 parent
91f483b960
commit
1cf67602d8
33 files changed
+681
-293
No files matched your search
@@ -0,0 +1,38 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import { test } from 'node:test'
|
||||
import { isInstanceLaunching, launchOnce } from './instance-launch-state.ts'
|
||||
|
||||
test('launches different instances concurrently and coalesces repeated pending clicks', async () => {
|
||||
let finishA!: (value: string) => void
|
||||
let starts = 0
|
||||
const first = launchOnce('a', () => {
|
||||
starts++
|
||||
return new Promise<string>((resolve) => {
|
||||
finishA = resolve
|
||||
})
|
||||
})
|
||||
assert.equal(
|
||||
launchOnce('a', async () => 'unexpected duplicate'),
|
||||
first,
|
||||
)
|
||||
assert.equal(isInstanceLaunching('a'), true)
|
||||
assert.equal(isInstanceLaunching('b'), false)
|
||||
assert.equal(await launchOnce('b', async () => 'b started'), 'b started')
|
||||
assert.equal(isInstanceLaunching('a'), true)
|
||||
finishA('a started')
|
||||
assert.equal(await first, 'a started')
|
||||
assert.equal(starts, 1)
|
||||
assert.equal(isInstanceLaunching('a'), false)
|
||||
assert.equal(await launchOnce('a', async () => 'second window'), 'second window')
|
||||
})
|
||||
|
||||
test('failed launch releases only its own pending state and can retry', async () => {
|
||||
await assert.rejects(
|
||||
launchOnce('failed', async () => {
|
||||
throw new Error('launch failed')
|
||||
}),
|
||||
/launch failed/,
|
||||
)
|
||||
assert.equal(isInstanceLaunching('failed'), false)
|
||||
assert.equal(await launchOnce('failed', async () => 'retry'), 'retry')
|
||||
})
|
||||
@@ -0,0 +1,20 @@
|
||||
import { reactive } from 'vue'
|
||||
|
||||
const pending = reactive(new Map<string, Promise<unknown>>())
|
||||
|
||||
export function isInstanceLaunching(instanceId: string) {
|
||||
return pending.has(instanceId)
|
||||
}
|
||||
|
||||
/** Coalesce repeated clicks for one launch without blocking other instances. */
|
||||
export function launchOnce<T>(instanceId: string, launch: () => Promise<T>): Promise<T> {
|
||||
const existing = pending.get(instanceId)
|
||||
if (existing) return existing as Promise<T>
|
||||
const task = Promise.resolve()
|
||||
.then(launch)
|
||||
.finally(() => {
|
||||
pending.delete(instanceId)
|
||||
})
|
||||
pending.set(instanceId, task)
|
||||
return task
|
||||
}
|
||||
@@ -19,6 +19,7 @@ import type { GcContext, ResolvedGcStrategyId } from '@/helpers/gc/types'
|
||||
import { setLastGcLaunchReport } from '@/helpers/gc-notice'
|
||||
import { getInstanceMode, prepareHostedSession } from '@/helpers/hosted-packs'
|
||||
import { prepareInstancePlayer } from '@/helpers/instance-player'
|
||||
import { launchOnce } from '@/helpers/instance-launch-state'
|
||||
import { AUTO_GC_PRESET_ARG } from '@/helpers/java-arguments'
|
||||
import { get_jre, get_memory_status } from '@/helpers/jre.js'
|
||||
import { get as getSettings } from '@/helpers/settings'
|
||||
@@ -1071,12 +1072,19 @@ export async function resolveGcLaunchIntent(
|
||||
|
||||
// Run Minecraft using an instance
|
||||
// Returns the process metadata plus an optional GC fallback report.
|
||||
export async function run(
|
||||
export function run(
|
||||
instanceId: string,
|
||||
serverAddress: string | null = null,
|
||||
): Promise<InstanceRunResult> {
|
||||
return launchOnce(instanceId, () => launchInstance(instanceId, serverAddress))
|
||||
}
|
||||
|
||||
async function launchInstance(
|
||||
instanceId: string,
|
||||
serverAddress: string | null,
|
||||
): Promise<InstanceRunResult> {
|
||||
await prepareInstancePlayer(instanceId)
|
||||
if (await getInstanceMode(instanceId) === 'starlight') await prepareHostedSession()
|
||||
if ((await getInstanceMode(instanceId)) === 'starlight') await prepareHostedSession()
|
||||
const { args, gcIntent } = await resolveGcLaunchIntent(instanceId)
|
||||
const result = await invoke<InstanceRunResult>('plugin:instance|instance_run', {
|
||||
instanceId,
|
||||
|
||||
Reference in new issue
Block a user