Game Files | Electric Cherry
{#if $page.url.searchParams.has('returnTo')}{/if} {#if error}{/if} {#if notice}

{notice}

{/if} {#if !canManage}

Administrators upload game files. Active hosts prepare verified copies automatically.

{/if} {#if canManage && showUpload}

{phase === 'published' ? `${gameTitle(game, true)} files uploaded` : uploadId ? `Continue ${gameTitle(game, true)} upload` : `Upload ${gameTitle(game, true)} game folder`}

Select your complete {gameName(game)} game folder, including its installed DLC. Once verified, this upload becomes the latest files and hosts download it automatically. Running servers keep using their existing files.

{#if uploadError}{/if}
{#if phase !== 'verifying' && phase !== 'published'}

{uploadId ? 'To resume, file names, sizes, and modification dates must match the original upload.' : 'Choose the game directory itself. Its top-level folder name is removed once; all files and subfolders inside it keep their paths.'}

{/if} {#if folder}
{folder.name}{folder.files.length.toLocaleString()} files · {formatGameBytes( folder.size )}
Preview folder paths
    {#each folder.files.slice(0, 8) as file}
  • {file.path}
  • {/each}
{#if folder.files.length > 8}

And {(folder.files.length - 8).toLocaleString()} more files.

{/if}
{/if} {#if phase !== 'idle'}
{phase === 'preparing' ? 'Preparing upload…' : phase === 'uploading' ? 'Uploading game files' : phase === 'verifying' ? 'Verifying files…' : phase === 'published' ? 'Ready · host downloads are automatic' : 'Upload paused'}{completedFiles.toLocaleString()} / {totalFiles.toLocaleString()} files

{formatGameBytes(progressBytes)} / {formatGameBytes(totalBytes)} saved or transferring

{#if currentPath}

{currentPath}

{/if} {#if phase === 'verifying'}

The controller checks every file before making this upload available to hosts. Verification continues if you leave this page.

{:else if phase === 'paused'}

Saved chunks are kept on the controller. Resume this upload to check the saved progress and retry.

{/if}
{/if}
{#if transferring} {:else if phase !== 'verifying' && phase !== 'published'}{/if} {#if phase === 'idle' || phase === 'uploading'}Keep this page open while files transfer. Interrupted uploads can be resumed below.{/if}
{/if} {#if !loaded}

Loading game files…

{/if} {#each libraries as library (library.game)} {@const latest = library.versions.find((item) => item.id === library.latestVersionId)} {@const unfinished = library.versions.filter((item) => item.state !== 'ready')} {@const history = library.versions.filter( (item) => item.state === 'ready' && item.id !== library.latestVersionId )}

{gameName(library.game)}

{#if latest}

{formatGameBytes(latest.sizeBytes)} · {latest.fileCount.toLocaleString()} files

{/if}
{#if canManage}{/if}
{#if latest}
Latest verified upload cache.status === 'failed') ? 'danger' : latest.caches.length && latest.caches.every((cache) => cache.status === 'ready') ? 'online' : 'neutral'} >{latest.caches.length ? `${latest.caches.filter((cache) => cache.status === 'ready').length} / ${latest.caches.length} host copies ready` : 'No hosts'}
{:else}

Upload the complete {gameName(library.game)} game folder once. Hosts will download and verify it automatically as part of setup.

{/if} {#if unfinished.length}

Unfinished uploads

{#each unfinished as item (item.id)} {@const browserUpload = !item.sourceHostId}

Started · {formatGameBytes( item.sizeBytes )} · {item.fileCount.toLocaleString()} files

{item.state === 'failed' ? 'Failed' : browserUpload ? item.id === uploadId && phase === 'verifying' ? 'Verifying' : 'Uploading' : 'Importing'}
{#if item.error}

{item.error}

{/if} {#if browserUpload}

Resume with the original unchanged folder. The latest files stay available while this upload completes.

{#if canManage}
{/if} {:else if item.state === 'importing'}

The existing host import continues independently. It is reconciled when the host reconnects.

{/if}
{/each}
{/if} {#if latest || history.length}
Details
{#if latest}

Uploaded

{@render uploadDetails(latest)}{@render downloadControls(latest)}{/if} {#if history.length}
Previous uploads ({history.length})

Old host copies are removed once no instances use them. Controller files are removed after all host copies are gone; upload history is kept.

{#each history as item (item.id)}

Uploaded

{#if item.filesRemoved}

Files removed from controller · upload history retained

{:else if item.filesRemoving}

Removing unused controller files · upload history retained

{/if}

{formatGameBytes(item.sizeBytes)} · {item.fileCount.toLocaleString()} files

{@render uploadDetails(item)}
Host copies{@render downloadControls(item)}
{/each}
{/if}
{/if}
{/each}
{#snippet uploadDetails(item: OverviewLibrary['versions'][number])}
Upload details
Upload ID
{item.id}
Manifest SHA256
{item.manifestSha256 ?? 'Available after verification'}
Uploaded from
{!item.sourceHostId ? 'Game folder in browser' : `${hostName(item.sourceHostId)} / ${item.sourceVolume}`}
View complete file manifest
{/snippet} {#snippet downloadControls(item: OverviewLibrary['versions'][number])} {#if canManage && !item.filesRemoved && !item.filesRemoving}
Advanced: download or verify these files

Retry a download or prepare a previous upload on a host. The latest files are downloaded automatically.

{/if} {/snippet}