document.addEventListener('DOMContentLoaded', () => { // State let currentStep = 1; let selectedDevice = null; let selectedEdition = 'java'; const totalSteps = 4; // Elements const prevBtn = document.getElementById('btn-prev'); const nextBtn = document.getElementById('btn-next'); // Updated selector for new sidebar structure const stepIndicators = document.querySelectorAll('.progress-step'); const stepContents = document.querySelectorAll('.step-content'); const conventionContent = document.getElementById('convention-content'); if (!conventionContent) { console.error('Critical Error: Element #convention-content not found in DOM'); return; } const agreeCheckbox = document.getElementById('agree-checkbox'); const deviceCards = document.querySelectorAll('.device-card'); const recommendationSection = document.getElementById('launcher-recommendation'); const recommendationContent = document.getElementById('recommendation-content'); const tutorialContent = document.getElementById('tutorial-content'); const step4Buttons = document.getElementById('step4-buttons'); const mainWizardActions = document.querySelector('.wizard-actions'); const editionSelector = document.getElementById('edition-selector'); const editionBtns = document.querySelectorAll('.edition-btn'); console.log('DOM Elements loaded. Step contents found:', stepContents.length); // Fallback if marked is not loading correctly if (typeof marked === 'undefined') { console.warn("Marked not defined globally, checking for window.marked"); if (window.marked) { console.log("Found window.marked"); // Assign to local variable if needed or just use window.marked } } // --- Step 1: Convention Loading --- console.log('Fetching convention from data/convention.md ...'); fetch('data/convention.md') .then(response => { console.log('Response status:', response.status); if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`); return response.text(); }) .then(markdown => { console.log('Convention loaded, length:', markdown.length); let parser = null; if (typeof marked !== 'undefined') { if (typeof marked.parse === 'function') parser = marked.parse; else if (typeof marked === 'function') parser = marked; } else if (window.marked) { if (typeof window.marked.parse === 'function') parser = window.marked.parse; else if (typeof window.marked === 'function') parser = window.marked; } if (parser) { try { const result = parser(markdown); if (result instanceof Promise) { result.then(html => conventionContent.innerHTML = html); } else { conventionContent.innerHTML = result; } } catch (e) { console.error('Parse error:', e); conventionContent.innerHTML = '
' + markdown + ''; } } else { console.error('No markdown parser found'); conventionContent.innerHTML = '
' + markdown + ''; } }) .catch(error => { console.error('Convention fetch error:', error); conventionContent.innerHTML = `
无法加载公约内容: ${error.message}
`; }); // --- Navigation Logic --- function updateWizard() { console.log('UpdateWizard called, step:', currentStep); // Update Indicators stepIndicators.forEach(indicator => { const step = parseInt(indicator.dataset.step); if (step === currentStep) { indicator.classList.add('active'); indicator.classList.remove('completed'); // Scroll into view on mobile if (window.innerWidth <= 800) { indicator.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' }); } } else if (step < currentStep) { indicator.classList.add('completed'); indicator.classList.remove('active'); } else { indicator.classList.remove('active', 'completed'); } }); // Update Progress Bar Fill const progressFill = document.getElementById('progress-fill'); if (progressFill) { const progress = ((currentStep - 1) / (totalSteps - 1)) * 100; progressFill.style.width = `${progress}%`; } // Update Content visibility with Animation timeout stepContents.forEach(content => { if (content.id === `step-${currentStep}`) { content.classList.add('active'); // Optional: ensure display block if handled by CSS alone or JS } else { content.classList.remove('active'); } }); // Buttons State updateButtons(); } function updateButtons() { // Prev Button if (prevBtn) prevBtn.disabled = currentStep === 1; // Next Button logic if (currentStep === 1) { // Step 1: Checkbox required if (nextBtn) nextBtn.disabled = !agreeCheckbox.checked; } else if (currentStep === 2) { // Step 2: Device selection required if (nextBtn) nextBtn.disabled = !selectedDevice; } else { if (nextBtn) nextBtn.disabled = false; } // Step 4 special buttons visibility if (currentStep === totalSteps) { if (nextBtn) nextBtn.style.display = 'none'; if (step4Buttons) step4Buttons.classList.remove('hidden'); } else { if (nextBtn) nextBtn.style.display = 'inline-flex'; if (step4Buttons) step4Buttons.classList.add('hidden'); } } if (prevBtn) { prevBtn.addEventListener('click', () => { if (currentStep > 1) { currentStep--; updateWizard(); } }); } if (nextBtn) { nextBtn.addEventListener('click', () => { if (currentStep < totalSteps) { if (currentStep === 2) { renderTutorial(); // Generate step 3 content before showing // Also scroll to top for better ux window.scrollTo({ top: 0, behavior: 'smooth' }); } currentStep++; updateWizard(); window.scrollTo({ top: 0, behavior: 'smooth' }); } }); } // Step 1 Checkbox if (agreeCheckbox) { agreeCheckbox.addEventListener('change', updateButtons); } // --- Step 2: Device Selection --- const deviceData = { pc: { title: "电脑版 (Java Edition)", recommendations: [ { name: "PCL2", icon: "fas fa-cube", desc: "界面精美,功能强大的现代化启动器(仅Win)", url: "https://afdian.net/p/0164034c016c11ebafcb52540025c377", primary: true }, { name: "HMCL", icon: "fas fa-horse-head", desc: "历史悠久,跨平台支持好 (Win/Mac/Linux)", url: "https://hmcl.huangyuhui.net/", primary: false } ], note: "推荐使用 PCL2 或 HMCL,均支持极大改善游戏体验。" }, ios: { title: "iOS 设备", recommendations: [ { name: "PojavLauncher", icon: "fab fa-app-store-ios", desc: "iOS 上运行 Java 版的唯一选择", url: "https://apps.apple.com/us/app/pojavlauncher/id6443526546", primary: true } ], note: "需要 iOS 14.0 或更高版本。若未越狱,请保持 JIT 开启以获得最佳性能(部分版本可能需要)。" }, android: { title: "安卓设备", recommendations: [ { name: "FCL 启动器", icon: "fab fa-android", desc: "基于 FoldCraft 的高性能启动器", url: "https://github.com/FoldCraftLauncher/FoldCraftLauncher/releases", primary: true }, { name: "PojavLauncher", icon: "fas fa-gamepad", desc: "经典的移动端 Java 版启动器", url: "https://play.google.com/store/apps/details?id=net.kdt.pojavlaunch", primary: false } ], note: "建议设备拥有至少 4GB 运存以流畅运行 1.21 版本。" } }; const bedrockDeviceData = { pc: { title: "电脑版 (Bedrock Edition)", recommendations: [ { name: "Minecraft 基岩版", icon: "fas fa-cube", desc: "从 Microsoft Store 获取 Minecraft(需 Windows 10/11)", url: "https://www.xbox.com/games/store/minecraft/9NBLGGH2JHXJ", primary: true } ], note: "基岩版通过 Microsoft Store 购买,使用 Xbox / Microsoft 账号登录即可游玩。" }, ios: { title: "iOS 基岩版", recommendations: [ { name: "Minecraft", icon: "fas fa-cube", desc: "从 App Store 购买并下载 Minecraft", url: "https://apps.apple.com/app/minecraft/id479516143", primary: true } ], note: "基岩版是 iOS 上的原生 Minecraft,性能最佳、操作体验最好。" }, android: { title: "安卓基岩版", recommendations: [ { name: "Minecraft", icon: "fas fa-cube", desc: "从 Google Play 购买并下载 Minecraft", url: "https://play.google.com/store/apps/details?id=com.mojang.minecraftpe", primary: true } ], note: "基岩版是安卓上的原生 Minecraft,性能最佳、操作体验最好。" } }; deviceCards.forEach(card => { card.addEventListener('click', () => { // UI Update deviceCards.forEach(c => c.classList.remove('selected')); card.classList.add('selected'); const deviceType = card.dataset.device; selectedDevice = deviceType; selectedEdition = 'java'; // Show edition selector and reset to Java if (editionSelector) { editionSelector.classList.remove('hidden'); editionBtns.forEach(btn => { btn.classList.toggle('active', btn.dataset.edition === 'java'); }); } // Show Recommendation showRecommendation(deviceType); // Re-enable next button updateButtons(); }); }); // Edition toggle handlers editionBtns.forEach(btn => { btn.addEventListener('click', () => { editionBtns.forEach(b => b.classList.remove('active')); btn.classList.add('active'); selectedEdition = btn.dataset.edition; if (selectedDevice) { showRecommendation(selectedDevice); } }); }); function showRecommendation(device) { const data = selectedEdition === 'bedrock' ? bedrockDeviceData[device] : deviceData[device]; if (!data) return; if (recommendationSection) { recommendationSection.classList.remove('hidden'); // Little fade-in effect recommendationSection.style.opacity = '0'; setTimeout(() => recommendationSection.style.opacity = '1', 50); } let cardsHtml = data.recommendations.map(req => `${req.desc}
${data.note}
mcpure.lunadeer.cn
mcpure.lunadeer.cn
mcpure.lunadeer.cn
mcbe.lunadeer.cn
15337
mcbe.lunadeer.cn
15337
mcbe.lunadeer.cn
15337
${step.desc}