diff --git a/.github/workflows/build-single-file.yml b/.github/workflows/build-single-file.yml
index 93b1b77f..5f9800db 100644
--- a/.github/workflows/build-single-file.yml
+++ b/.github/workflows/build-single-file.yml
@@ -23,6 +23,8 @@ jobs:
- name: Build single-file version - minecraft.html
run: pnpm build-single-file && mv dist/single/index.html minecraft.html
+ env:
+ LOCAL_CONFIG_FILE: config.mcraft-only.json
- name: Upload artifact
uses: actions/upload-artifact@v4
diff --git a/.github/workflows/build-zip.yml b/.github/workflows/build-zip.yml
index cc472476..76ca65ca 100644
--- a/.github/workflows/build-zip.yml
+++ b/.github/workflows/build-zip.yml
@@ -23,6 +23,8 @@ jobs:
- name: Build project
run: pnpm build
+ env:
+ LOCAL_CONFIG_FILE: config.mcraft-only.json
- name: Bundle server.js
run: |
diff --git a/.github/workflows/next-deploy.yml b/.github/workflows/next-deploy.yml
index 99172bf7..75b39f6c 100644
--- a/.github/workflows/next-deploy.yml
+++ b/.github/workflows/next-deploy.yml
@@ -36,6 +36,7 @@ jobs:
run: vercel build --token=${{ secrets.VERCEL_TOKEN }}
env:
CONFIG_JSON_SOURCE: BUNDLED
+ LOCAL_CONFIG_FILE: config.mcraft-only.json
- name: Copy playground files
run: |
mkdir -p .vercel/output/static/playground
diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml
index f243a395..89fd6698 100644
--- a/.github/workflows/preview.yml
+++ b/.github/workflows/preview.yml
@@ -78,6 +78,7 @@ jobs:
run: vercel build --token=${{ secrets.VERCEL_TOKEN }}
env:
CONFIG_JSON_SOURCE: BUNDLED
+ LOCAL_CONFIG_FILE: config.mcraft-only.json
- name: Copy playground files
run: |
mkdir -p .vercel/output/static/playground
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 76322cb5..cbf52251 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -34,6 +34,7 @@ jobs:
- run: vercel build --token=${{ secrets.VERCEL_TOKEN }} --prod
env:
CONFIG_JSON_SOURCE: BUNDLED
+ LOCAL_CONFIG_FILE: config.mcraft-only.json
- name: Copy playground files
run: |
mkdir -p .vercel/output/static/playground
diff --git a/config.mcraft-only.json b/config.mcraft-only.json
new file mode 100644
index 00000000..51b6eee6
--- /dev/null
+++ b/config.mcraft-only.json
@@ -0,0 +1,3 @@
+{
+ "alwaysReconnectButton": true
+}
diff --git a/renderer/viewer/three/threeJsSound.ts b/renderer/viewer/three/threeJsSound.ts
index 627cabf8..46aefda9 100644
--- a/renderer/viewer/three/threeJsSound.ts
+++ b/renderer/viewer/three/threeJsSound.ts
@@ -39,7 +39,9 @@ export class ThreeJsSound implements SoundSystem {
sound.position.set(position.x, position.y, position.z)
sound.onEnded = () => {
this.worldRenderer.scene.remove(sound)
- sound.disconnect()
+ if (sound.source) {
+ sound.disconnect()
+ }
this.activeSounds.delete(sound)
audioLoader.manager.itemEnd(path)
}
@@ -51,7 +53,9 @@ export class ThreeJsSound implements SoundSystem {
// Stop and clean up all active sounds
for (const sound of this.activeSounds) {
sound.stop()
- sound.disconnect()
+ if (sound.source) {
+ sound.disconnect()
+ }
}
// Remove and cleanup audio listener
diff --git a/rsbuild.config.ts b/rsbuild.config.ts
index 8bcbd75d..5014bdf9 100644
--- a/rsbuild.config.ts
+++ b/rsbuild.config.ts
@@ -1,3 +1,4 @@
+///
import { defineConfig, mergeRsbuildConfig, RsbuildPluginAPI } from '@rsbuild/core'
import { pluginReact } from '@rsbuild/plugin-react'
import { pluginTypedCSSModules } from '@rsbuild/plugin-typed-css-modules'
@@ -48,7 +49,7 @@ if (fs.existsSync('./assets/release.json')) {
const configJson = JSON.parse(fs.readFileSync('./config.json', 'utf8'))
try {
- Object.assign(configJson, JSON.parse(fs.readFileSync('./config.local.json', 'utf8')))
+ Object.assign(configJson, JSON.parse(fs.readFileSync(process.env.LOCAL_CONFIG_FILE || './config.local.json', 'utf8')))
} catch (err) {}
if (dev) {
configJson.defaultProxy = ':8080'
@@ -198,7 +199,7 @@ const appConfig = defineConfig({
}
if (configSource === 'REMOTE') {
- fs.writeFileSync('./dist/config.json', JSON.stringify(configJson), 'utf8')
+ fs.writeFileSync('./dist/config.json', JSON.stringify(configJson, undefined, 2), 'utf8')
}
if (fs.existsSync('./generated/sounds.js')) {
fs.copyFileSync('./generated/sounds.js', './dist/sounds.js')
diff --git a/src/appConfig.ts b/src/appConfig.ts
index 0805c448..b8c1e219 100644
--- a/src/appConfig.ts
+++ b/src/appConfig.ts
@@ -55,6 +55,7 @@ export type AppConfig = {
showModsButton?: boolean
defaultUsername?: string
skinTexturesProxy?: string
+ alwaysReconnectButton?: boolean
}
export const loadAppConfig = (appConfig: AppConfig) => {
diff --git a/src/env.d.ts b/src/env.d.ts
new file mode 100644
index 00000000..4cb5bafd
--- /dev/null
+++ b/src/env.d.ts
@@ -0,0 +1,30 @@
+declare namespace NodeJS {
+ interface ProcessEnv {
+ // Build configuration
+ NODE_ENV: 'development' | 'production'
+ SINGLE_FILE_BUILD?: string
+ DISABLE_SERVICE_WORKER?: string
+ CONFIG_JSON_SOURCE?: 'BUNDLED' | 'REMOTE'
+ LOCAL_CONFIG_FILE?: string
+ BUILD_VERSION?: string
+
+ // GitHub and Vercel related
+ GITHUB_REPOSITORY?: string
+ VERCEL_GIT_REPO_OWNER?: string
+ VERCEL_GIT_REPO_SLUG?: string
+
+ // UI and Features
+ MAIN_MENU_LINKS?: string
+ ENABLE_COOKIE_STORAGE?: string
+ COOKIE_STORAGE_PREFIX?: string
+
+ // Release information
+ RELEASE_TAG?: string
+ RELEASE_LINK?: string
+ RELEASE_CHANGELOG?: string
+
+ // Other configurations
+ DEPS_VERSIONS?: string
+ INLINED_APP_CONFIG?: string
+ }
+}
diff --git a/src/react/PauseScreen.tsx b/src/react/PauseScreen.tsx
index 22e00ded..4bdd2974 100644
--- a/src/react/PauseScreen.tsx
+++ b/src/react/PauseScreen.tsx
@@ -163,6 +163,7 @@ export default () => {
const { noConnection } = useSnapshot(gameAdditionalState)
const { active: packetsReplaceActive, hasRecordedPackets: packetsReplaceHasRecordedPackets } = useSnapshot(packetsRecordingState)
const { displayRecordButton: displayPacketsButtons } = useSnapshot(options)
+ const { appConfig } = useSnapshot(miscUiState)
const handlePointerLockChange = () => {
if (!pointerLock.hasPointerLock && activeModalStack.length === 0) {
@@ -293,7 +294,7 @@ export default () => {
{fsState.inMemorySave && !fsState.syncFs && !fsState.isReadonly ? 'Save & Quit' : 'Disconnect & Reset'}
>}
- {noConnection && (
+ {(noConnection || appConfig?.alwaysReconnectButton) && (