diff --git a/packages/api-client/src/modules/archon/servers/v0.ts b/packages/api-client/src/modules/archon/servers/v0.ts index 8dee490de6..694ddd2147 100644 --- a/packages/api-client/src/modules/archon/servers/v0.ts +++ b/packages/api-client/src/modules/archon/servers/v0.ts @@ -97,19 +97,6 @@ export class ArchonServersV0Module extends AbstractModule { }) } - /** - * Send a power action to a server (Start, Stop, Restart, Kill) - * POST /modrinth/v0/servers/:id/power - */ - public async power(serverId: string, action: Archon.Servers.v0.PowerAction): Promise { - await this.client.request(`/servers/${serverId}/power`, { - api: 'archon', - method: 'POST', - version: 'modrinth/v0', - body: { action }, - }) - } - /** * Reinstall a server with a new loader or modpack * POST /modrinth/v0/servers/:id/reinstall diff --git a/packages/api-client/src/modules/archon/servers/v1.ts b/packages/api-client/src/modules/archon/servers/v1.ts index 2abf6fd58c..36100a7005 100644 --- a/packages/api-client/src/modules/archon/servers/v1.ts +++ b/packages/api-client/src/modules/archon/servers/v1.ts @@ -91,6 +91,23 @@ export class ArchonServersV1Module extends AbstractModule { }) } + /** + * Run a power action for a specific world + * POST /v1/servers/:id/worlds/:wid/power + */ + public async powerWorld( + serverId: string, + worldId: string, + request: Archon.Servers.v1.WorldPowerActionRequest, + ): Promise { + await this.client.request(`/servers/${serverId}/worlds/${worldId}/power`, { + api: 'archon', + version: 1, + method: 'POST', + body: request, + }) + } + /** * Reset a world to onboarding * POST /v1/servers/:id/worlds/:wid/onboard diff --git a/packages/api-client/src/modules/archon/types.ts b/packages/api-client/src/modules/archon/types.ts index 39bd4a8073..da6627a705 100644 --- a/packages/api-client/src/modules/archon/types.ts +++ b/packages/api-client/src/modules/archon/types.ts @@ -681,8 +681,6 @@ export namespace Archon { token: string // JWT token for filesystem access } - export type PowerAction = 'Start' | 'Stop' | 'Restart' | 'Kill' - export type ReinstallLoaderRequest = { loader: string loader_version?: string @@ -715,6 +713,13 @@ export namespace Archon { } export namespace v1 { + export type WorldPowerAction = 'start' | 'stop' | 'restart' | 'kill' + + export type WorldPowerActionRequest = { + action: WorldPowerAction + shutdown_strategy?: string | null + } + export type ServerFull = { id: string name: string diff --git a/packages/ui/src/components/servers/SaveBanner.vue b/packages/ui/src/components/servers/SaveBanner.vue index afc753fe51..fdb613c9a4 100644 --- a/packages/ui/src/components/servers/SaveBanner.vue +++ b/packages/ui/src/components/servers/SaveBanner.vue @@ -14,7 +14,7 @@ - @@ -43,7 +43,7 @@ const props = defineProps<{ const client = injectModrinthClient() -const { powerState } = injectModrinthServerContext() +const { powerState, worldId } = injectModrinthServerContext() const isStopped = computed(() => powerState.value === 'stopped' || powerState.value === 'crashed') @@ -63,6 +63,9 @@ const saveAndPower = async () => { } catch { return } - await client.archon.servers_v0.power(props.serverId, isStopped.value ? 'Start' : 'Restart') + if (!worldId.value) return + await client.archon.servers_v1.powerWorld(props.serverId, worldId.value, { + action: isStopped.value ? 'start' : 'restart', + }) } diff --git a/packages/ui/src/components/servers/server-header/WorldManageHeader.vue b/packages/ui/src/components/servers/server-header/ServerInstanceManageHeader.vue similarity index 99% rename from packages/ui/src/components/servers/server-header/WorldManageHeader.vue rename to packages/ui/src/components/servers/server-header/ServerInstanceManageHeader.vue index 7d2e3342bf..aede4b8c76 100644 --- a/packages/ui/src/components/servers/server-header/WorldManageHeader.vue +++ b/packages/ui/src/components/servers/server-header/ServerInstanceManageHeader.vue @@ -76,7 +76,7 @@ const props = withDefaults( loader: null, loaderVersion: null, lastActive: null, - fallbackName: 'World', + fallbackName: 'Instance', headerClass: '', actions: () => [], }, diff --git a/packages/ui/src/components/servers/server-header/index.ts b/packages/ui/src/components/servers/server-header/index.ts index dcbaebc210..8c63dc8038 100644 --- a/packages/ui/src/components/servers/server-header/index.ts +++ b/packages/ui/src/components/servers/server-header/index.ts @@ -1,3 +1,3 @@ export { default as PanelServerActionButton } from './PanelServerActionButton.vue' export { default as ServerManageHeader } from './ServerManageHeader.vue' -export { default as WorldManageHeader } from './WorldManageHeader.vue' +export { default as ServerInstanceManageHeader } from './ServerInstanceManageHeader.vue' diff --git a/packages/ui/src/components/servers/server-header/use-server-power-action.ts b/packages/ui/src/components/servers/server-header/use-server-power-action.ts index 05fdfb5073..edd06d7d5f 100644 --- a/packages/ui/src/components/servers/server-header/use-server-power-action.ts +++ b/packages/ui/src/components/servers/server-header/use-server-power-action.ts @@ -9,12 +9,19 @@ import { injectNotificationManager, } from '#ui/providers' -export type PowerAction = Archon.Servers.v0.PowerAction +export type PowerAction = 'Start' | 'Stop' | 'Restart' | 'Kill' + +const powerActionMap = { + Start: 'start', + Stop: 'stop', + Restart: 'restart', + Kill: 'kill', +} as const satisfies Record export function useServerPowerAction(options?: { disabled?: Ref }) { const { formatMessage } = useVIntl() const client = injectModrinthClient() - const { serverId, server, powerState, isSyncingContent, busyReasons } = + const { serverId, worldId, server, powerState, isSyncingContent, busyReasons } = injectModrinthServerContext() const { addNotification } = injectNotificationManager() const { canUsePowerActions, permissionDeniedMessage } = useServerPermissions() @@ -46,16 +53,18 @@ export function useServerPowerAction(options?: { disabled?: Ref }) { const busyTooltip = computed(() => { if (!canUsePowerActions.value) return permissionDeniedMessage.value + if (!worldId.value) return 'Your server instance is loading' if (isStarting.value) return 'Your server is starting' return busyReasons.value.length > 0 ? formatMessage(busyReasons.value[0].reason) : undefined }) const canTakeAction = computed( - () => !isTransitioning.value && !isBlockedByPropsBusyOrPermission.value, + () => !!worldId.value && !isTransitioning.value && !isBlockedByPropsBusyOrPermission.value, ) const canKill = computed( () => + !!worldId.value && !isBlockedByPropsBusyOrPermission.value && (isStopping.value || isRunning.value || isStarting.value), ) @@ -72,9 +81,13 @@ export function useServerPowerAction(options?: { disabled?: Ref }) { } }) - async function sendPowerAction(action: PowerAction) { + async function sendPowerAction(action: PowerAction, targetWorldId = worldId.value) { + if (!targetWorldId) return + try { - await client.archon.servers_v0.power(serverId, action) + await client.archon.servers_v1.powerWorld(serverId, targetWorldId, { + action: powerActionMap[action], + }) } catch (error) { console.error(`Error performing ${action} on server:`, error) addNotification({ @@ -85,13 +98,13 @@ export function useServerPowerAction(options?: { disabled?: Ref }) { } } - function initiateAction(action: PowerAction) { + function initiateAction(action: PowerAction, targetWorldId = worldId.value) { if (action === 'Kill') { if (!canKill.value) return } else { if (!canTakeAction.value) return } - void sendPowerAction(action) + void sendPowerAction(action, targetWorldId) } function handlePrimaryAction() { diff --git a/packages/ui/src/layouts/wrapped/hosting/manage/[id]/instances/[instance-id]/files.vue b/packages/ui/src/layouts/wrapped/hosting/manage/[id]/instances/[instance-id]/files.vue index 6ba1e9cf92..3759614d67 100644 --- a/packages/ui/src/layouts/wrapped/hosting/manage/[id]/instances/[instance-id]/files.vue +++ b/packages/ui/src/layouts/wrapped/hosting/manage/[id]/instances/[instance-id]/files.vue @@ -389,8 +389,8 @@ onMounted(async () => { // Restart async function restartServer() { - if (!canUsePowerActions.value) return - await client.archon.servers_v0.power(serverId, 'Restart') + if (!canUsePowerActions.value || !worldId.value) return + await client.archon.servers_v1.powerWorld(serverId, worldId.value, { action: 'restart' }) } function getSessionUploadFilename(fileName: string) { diff --git a/packages/ui/src/layouts/wrapped/hosting/manage/[id]/instances/[instance-id]/index.vue b/packages/ui/src/layouts/wrapped/hosting/manage/[id]/instances/[instance-id]/index.vue index a23e2757a4..58d734ff76 100644 --- a/packages/ui/src/layouts/wrapped/hosting/manage/[id]/instances/[instance-id]/index.vue +++ b/packages/ui/src/layouts/wrapped/hosting/manage/[id]/instances/[instance-id]/index.vue @@ -1,6 +1,6 @@