import type { ServerTypeId } from '@modrinth/server' import { invoke } from '@tauri-apps/api/core' import { listen } from '@tauri-apps/api/event' export interface ModpackInfoData { projectId: string versionId: string title: string iconUrl?: string } export interface ServerManifestData { id: string name: string serverType: ServerTypeId gameVersion: string loaderVersion?: string jarName?: string iconPath?: string modpack?: ModpackInfoData installState?: 'incomplete' | 'failed' | null installError?: string | null javaPath?: string memoryMb?: number jvmArgs: string[] createdAt: string lastStartedAt?: string lastExitCrashed: boolean } export interface ServerInfoData extends ServerManifestData { path: string running: boolean eulaExists: boolean eulaAccepted: boolean port: number | null } export type ServerExitReason = 'eula' export type ServerEventPayload = | { event: 'log'; line: string } | { event: 'console_output'; data: string } | { event: 'download_progress'; downloaded: number; total?: number } | { event: 'started' } | { event: 'stopped'; crashed: boolean; reason?: ServerExitReason } | { event: 'eula_required'; server_id: string; eula_text: string } export interface PortProcessInfoData { pid: number name?: string | null } export interface InstallModpackOptions { mrpackUrl: string mrpackSha1?: string jarUrl: string jarFilename: string jarSha1?: string modpackProjectId?: string modpackVersionId?: string modpackTitle?: string modpackIconUrl?: string } const command = (name: string) => `plugin:servers|${name}` export const servers = { list: () => invoke(command('servers_list')), get: (serverId: string) => invoke(command('servers_get'), { serverId }), create: (options: { name: string serverType: ServerTypeId gameVersion: string loaderVersion?: string javaPath?: string memoryMb?: number }) => invoke(command('servers_create'), options), updateSettings: ( serverId: string, options: { name?: string javaPath?: string memoryMb?: number jvmArgs?: string[] }, ) => invoke(command('servers_update_settings'), { serverId, ...options }), setIcon: (serverId: string, iconPath: string | null) => invoke(command('servers_set_icon'), { serverId, iconPath }), delete: (serverId: string) => invoke(command('servers_delete'), { serverId }), readFile: (serverId: string, file: string) => invoke(command('servers_read_file'), { serverId, file }), writeFile: (serverId: string, file: string, contents: string) => invoke(command('servers_write_file'), { serverId, file, contents }), downloadFile: (serverId: string, url: string, filename: string, expectedSha1?: string) => invoke(command('servers_download_file'), { serverId, url, filename, expectedSha1, }), installModpack: (serverId: string, options: InstallModpackOptions) => invoke(command('servers_install_modpack'), { serverId, ...options }), installForge: (serverId: string, mcVersion: string, build: string, javaPath?: string) => invoke(command('servers_install_forge'), { serverId, mcVersion, build, javaPath }), start: ( serverId: string, options?: { javaPath?: string; memoryMb?: number; jvmArgs?: string[] }, ) => invoke(command('servers_start'), { serverId, ...options }), sendCommand: (serverId: string, commandText: string) => invoke(command('servers_send_command'), { serverId, command: commandText }), sendConsoleInput: (serverId: string, data: Uint8Array) => invoke(command('servers_send_console_input'), { serverId, data: bytesToBase64(data), }), resizeConsole: (serverId: string, cols: number, rows: number) => invoke(command('servers_resize_console'), { serverId, cols, rows }), stop: (serverId: string) => invoke(command('servers_stop'), { serverId }), kill: (serverId: string) => invoke(command('servers_kill'), { serverId }), killPortProcess: (port: number) => invoke(command('servers_kill_port_process'), { port }), portProcess: (port: number) => invoke(command('servers_port_process'), { port }), getLogBuffer: (serverId: string) => invoke(command('servers_get_log_buffer'), { serverId }), clearLog: (serverId: string) => invoke(command('servers_clear_log'), { serverId }), } export function base64ToBytes(data: string): Uint8Array { return Uint8Array.from(atob(data), (character) => character.charCodeAt(0)) } function bytesToBase64(data: Uint8Array): string { let binary = '' for (const byte of data) binary += String.fromCharCode(byte) return btoa(binary) } export async function serverEventListener( callback: (serverId: string, payload: ServerEventPayload) => void, ): Promise<() => void> { const unlisten = await listen<{ serverId: string; event: string } & ServerEventPayload>( 'server', (event) => callback(event.payload.serverId, event.payload), ) return unlisten }