|
| 1 | +<script> |
| 2 | + import { onMount, onDestroy } from 'svelte' |
| 3 | + import LoadingScreen from './components/LoadingScreen.svelte' |
| 4 | + import { progress, audio, config } from './stores.js' |
| 5 | +
|
| 6 | + onMount(() => { |
| 7 | + const cfg = window.CONFIG || getDevConfig() |
| 8 | + config.set(cfg) |
| 9 | +
|
| 10 | + // Apply theme colors as CSS custom properties |
| 11 | + const colors = cfg.Theme?.colors |
| 12 | + if (colors) { |
| 13 | + const root = document.documentElement |
| 14 | + if (colors.accent) root.style.setProperty('--accent', colors.accent) |
| 15 | + if (colors.accentRGB) root.style.setProperty('--accent-rgb', colors.accentRGB) |
| 16 | + if (colors.secondary) root.style.setProperty('--tech', colors.secondary) |
| 17 | + if (colors.secondaryRGB) root.style.setProperty('--tech-rgb', colors.secondaryRGB) |
| 18 | + if (colors.success) root.style.setProperty('--success', colors.success) |
| 19 | + if (colors.warning) root.style.setProperty('--warning', colors.warning) |
| 20 | + if (colors.danger) root.style.setProperty('--danger', colors.danger) |
| 21 | + } |
| 22 | +
|
| 23 | + // Apply font family |
| 24 | + if (cfg.Layout?.fontFamily) { |
| 25 | + document.documentElement.style.setProperty('--fontFamily', cfg.Layout.fontFamily) |
| 26 | + } |
| 27 | +
|
| 28 | + // Allow skip |
| 29 | + let skipEnabled = false |
| 30 | + if (cfg.General?.allowSkip) { |
| 31 | + const key = (cfg.General.skipKeyBinding || 'ENTER').toUpperCase() |
| 32 | + const onKey = (e) => { |
| 33 | + if (e.key.toUpperCase() === key || e.code.toUpperCase() === key) { |
| 34 | + skipEnabled = true |
| 35 | + document.removeEventListener('keydown', onKey) |
| 36 | + const screen = document.querySelector('.loading-screen') |
| 37 | + if (screen) { |
| 38 | + screen.style.transition = 'opacity 0.5s ease-out' |
| 39 | + screen.style.opacity = '0' |
| 40 | + } |
| 41 | + } |
| 42 | + } |
| 43 | + document.addEventListener('keydown', onKey) |
| 44 | + } |
| 45 | +
|
| 46 | + // Simulated progress |
| 47 | + let simTimer = null |
| 48 | + let realProgress = 0 |
| 49 | +
|
| 50 | + if (cfg.Progress?.simulateProgress) { |
| 51 | + const duration = cfg.Progress.minDuration || 8000 |
| 52 | + const checkpoints = cfg.Progress.checkpoints || [ |
| 53 | + { label: 'Initializing...', progress: 15 }, |
| 54 | + { label: 'Loading Resources...', progress: 35 }, |
| 55 | + { label: 'Connecting...', progress: 55 }, |
| 56 | + { label: 'Syncing Data...', progress: 75 }, |
| 57 | + { label: 'Almost There...', progress: 90 }, |
| 58 | + ] |
| 59 | +
|
| 60 | + let cpIndex = 0 |
| 61 | + const interval = duration / (checkpoints.length + 1) |
| 62 | +
|
| 63 | + simTimer = setInterval(() => { |
| 64 | + if (cpIndex < checkpoints.length) { |
| 65 | + const cp = checkpoints[cpIndex] |
| 66 | + if (realProgress < cp.progress) { |
| 67 | + progress.update(cp.progress) |
| 68 | + progress.setLabel(cp.label) |
| 69 | + } |
| 70 | + cpIndex++ |
| 71 | + } else { |
| 72 | + clearInterval(simTimer) |
| 73 | + } |
| 74 | + }, interval) |
| 75 | + } |
| 76 | +
|
| 77 | + window.addEventListener('message', (event) => { |
| 78 | + let item = event.data |
| 79 | + if (!item) return |
| 80 | +
|
| 81 | + if (typeof item === 'string') { |
| 82 | + try { item = JSON.parse(item) } catch (e) { return } |
| 83 | + } |
| 84 | +
|
| 85 | + if (item.eventName === 'loadProgress') { |
| 86 | + const fraction = item.loadFraction ?? 0 |
| 87 | + const pct = Math.round(fraction * 100) |
| 88 | + realProgress = pct |
| 89 | + progress.update(pct) |
| 90 | +
|
| 91 | + if (pct >= 100) { |
| 92 | + progress.setLabel('Ready!') |
| 93 | + if (simTimer) clearInterval(simTimer) |
| 94 | + } else if (pct >= 75) { |
| 95 | + progress.setLabel('Almost there...') |
| 96 | + } else if (pct >= 50) { |
| 97 | + progress.setLabel('Loading resources...') |
| 98 | + } else if (pct >= 25) { |
| 99 | + progress.setLabel('Connecting...') |
| 100 | + } else if (pct > 0) { |
| 101 | + progress.setLabel('Initializing...') |
| 102 | + } |
| 103 | + } |
| 104 | +
|
| 105 | + if (item.eventName === 'startInitFunctionOrder') { |
| 106 | + progress.setLabel('Loading game...') |
| 107 | + } |
| 108 | +
|
| 109 | + if (item.type === 'shutdown') { |
| 110 | + if (simTimer) clearInterval(simTimer) |
| 111 | + const fadeMs = cfg.General?.audioFadeOut ?? 1000 |
| 112 | + audio.stop() |
| 113 | + const screen = document.querySelector('.loading-screen') |
| 114 | + if (screen) { |
| 115 | + screen.style.transition = `opacity ${fadeMs}ms ease-out` |
| 116 | + screen.style.opacity = '0' |
| 117 | + } |
| 118 | + } |
| 119 | + }) |
| 120 | +
|
| 121 | + return () => { |
| 122 | + if (simTimer) clearInterval(simTimer) |
| 123 | + } |
| 124 | + }) |
| 125 | +
|
| 126 | + onDestroy(() => { |
| 127 | + audio.stop() |
| 128 | + }) |
| 129 | +
|
| 130 | + function getDevConfig() { |
| 131 | + return { |
| 132 | + General: { |
| 133 | + enableAudio: false, |
| 134 | + audioVolume: 0.5, |
| 135 | + audioFadeOut: 1000, |
| 136 | + enableVideo: false, |
| 137 | + loopVideo: true, |
| 138 | + allowSkip: false, |
| 139 | + skipKeyBinding: 'ENTER', |
| 140 | + }, |
| 141 | + Theme: { |
| 142 | + colors: { |
| 143 | + accent: '#ff6b35', |
| 144 | + accentRGB: '255, 107, 53', |
| 145 | + secondary: '#00d4ff', |
| 146 | + secondaryRGB: '0, 212, 255', |
| 147 | + success: '#06d6a0', |
| 148 | + warning: '#ffd700', |
| 149 | + danger: '#ef476f', |
| 150 | + }, |
| 151 | + branding: { |
| 152 | + enabled: true, |
| 153 | + icon: { |
| 154 | + show: true, |
| 155 | + url: 'https://cmap.lol/icon.svg', |
| 156 | + size: 120, |
| 157 | + showGlow: true, |
| 158 | + }, |
| 159 | + title: 'Your Server Name', |
| 160 | + subtitle: 'Loading...', |
| 161 | + }, |
| 162 | + }, |
| 163 | + Content: { |
| 164 | + loadingText: 'Initializing Server', |
| 165 | + loadingDescription: 'Please wait while we get things ready...', |
| 166 | + cards: [ |
| 167 | + { |
| 168 | + title: 'Welcome', |
| 169 | + icon: 'wrench', |
| 170 | + description: 'Welcome to our server!', |
| 171 | + bgColor: 'rgba(255, 107, 53, 0.1)', |
| 172 | + borderColor: 'rgba(255, 107, 53, 0.3)', |
| 173 | + }, |
| 174 | + { |
| 175 | + title: 'Features', |
| 176 | + icon: 'tools', |
| 177 | + description: 'Tons of custom content', |
| 178 | + bgColor: 'rgba(0, 212, 255, 0.1)', |
| 179 | + borderColor: 'rgba(0, 212, 255, 0.3)', |
| 180 | + }, |
| 181 | + { |
| 182 | + title: 'Community', |
| 183 | + icon: 'person', |
| 184 | + description: 'Join our growing community', |
| 185 | + bgColor: 'rgba(6, 214, 160, 0.1)', |
| 186 | + borderColor: 'rgba(6, 214, 160, 0.3)', |
| 187 | + }, |
| 188 | + ], |
| 189 | + tips: [ |
| 190 | + 'Explore the city and discover hidden locations', |
| 191 | + 'Join our Discord for updates and support', |
| 192 | + 'Check out the controls in the settings menu', |
| 193 | + 'Report bugs to help us improve', |
| 194 | + ], |
| 195 | + }, |
| 196 | + Media: { |
| 197 | + backgroundVideo: '', |
| 198 | + backgroundImage: '', |
| 199 | + audioFile: '', |
| 200 | + audioPlaylist: [], |
| 201 | + }, |
| 202 | + Progress: { |
| 203 | + showProgressBar: true, |
| 204 | + progressColor: '#ff6b35', |
| 205 | + simulateProgress: true, |
| 206 | + minDuration: 5000, |
| 207 | + checkpoints: [ |
| 208 | + { label: 'Initializing Core', progress: 10 }, |
| 209 | + { label: 'Loading Resources', progress: 25 }, |
| 210 | + { label: 'Connecting to Server', progress: 50 }, |
| 211 | + { label: 'Syncing Data', progress: 75 }, |
| 212 | + { label: 'Finalizing Setup', progress: 90 }, |
| 213 | + ], |
| 214 | + }, |
| 215 | + Tabs: { |
| 216 | + enabled: false, |
| 217 | + tabs: [], |
| 218 | + }, |
| 219 | + Layout: { |
| 220 | + fontFamily: 'Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif', |
| 221 | + }, |
| 222 | + } |
| 223 | + } |
| 224 | +</script> |
| 225 | +
|
| 226 | +<LoadingScreen /> |
| 227 | +
|
| 228 | +<style> |
| 229 | + :global(body) { |
| 230 | + margin: 0; |
| 231 | + padding: 0; |
| 232 | + overflow: hidden; |
| 233 | + } |
| 234 | +
|
| 235 | + :global(#app) { |
| 236 | + width: 100%; |
| 237 | + height: 100%; |
| 238 | + } |
| 239 | +</style> |
0 commit comments