// ==================== ENTRY POINT ==================== import { state } from './core/state.js'; import { initCanvas } from './core/canvas.js'; import { SERVER_URL } from './config.js'; import { initSocket } from './multiplayer/socket.js'; import { loadSound, playSound } from './audio/sound-engine.js'; import { BLOCKS } from './data/blocks.js'; import { ITEMS } from './data/items.js'; import { TOOLS } from './data/tools.js'; import { SMELTING_RECIPES } from './data/recipes.js'; import { initTextures, tex, itemTex } from './render/textures.js'; import { getBlock, setBlock, removeBlock } from './world/world-storage.js'; import { genColumn, surfaceGyAt, ensureGenAroundCamera, regenerateVisibleChunks } from './world/generation.js'; import { initDB, loadGame, applySave, saveGame } from './game/save.js'; import { loop } from './game/loop.js'; import { initChat } from './ui/chat.js'; import { initFurnace } from './ui/furnace.js'; import { initMinimap } from './ui/minimap.js'; import { initSaveControls, updateSaveButtonVisibility } from './ui/save-controls.js'; import { initMarket } from './ui/market.js'; import { initRespawn } from './ui/respawn.js'; import { initShare } from './ui/share.js'; import { initControls } from './input/controls.js'; import { initMouseHandlers } from './input/mouse-handler.js'; import { initModes } from './game/modes.js'; import { initVoice } from './multiplayer/voice-chat.js'; import { rebuildHotbar } from './ui/hotbar.js'; import { toggleCraft, closeCraft, toggleInventory, closeInventory } from './ui/craft.js'; import { renderCraft } from './ui/craft.js'; // ==================== 1) CONFIG — parse URL/getName ==================== const urlParams = new URLSearchParams(window.location.search); state.SERVER_URL = SERVER_URL; state.TELEGRAM_BOT_USERNAME = 'Grechkacraft_bot'; state.TELEGRAM_APP_SHORT_NAME = 'minegrechka'; // Player name state.playerName = localStorage.getItem('minegrechka_playerName') || null; if (!state.playerName) { state.playerName = prompt('Введите ваше имя для игры:') || 'Игрок'; localStorage.setItem('minegrechka_playerName', state.playerName); console.log('Player name set:', state.playerName); } // World ID from URL or generate new console.log('Current URL:', window.location.href); const worldParam = urlParams.get('world'); console.log('world param:', worldParam); state.worldId = (worldParam && worldParam.trim() !== '') ? worldParam : null; console.log('worldId after params:', state.worldId, 'type:', typeof state.worldId); if (!state.worldId) { state.worldId = Math.random().toString(36).substring(2, 10); console.log('Generated worldId:', state.worldId); try { const newUrl = new URL(window.location.href); newUrl.searchParams.set('world', state.worldId); const newUrlString = newUrl.toString(); console.log('New URL to set:', newUrlString); if (typeof window.history !== 'undefined' && typeof window.history.replaceState === 'function') { window.history.replaceState(null, '', newUrlString); console.log('URL after replaceState:', window.location.href); } else { console.error('History API not supported!'); } } catch (e) { console.error('Error updating URL:', e); } console.log('Generated new worldId for browser:', state.worldId); } console.log('Final worldId:', state.worldId, 'Player name:', state.playerName); // ==================== 2) CANVAS — init from canvas module ==================== initCanvas(); // ==================== 3) STATE — set DOM refs ==================== state.hpEl = document.getElementById('hp'); state.foodEl = document.getElementById('food'); state.sxEl = document.getElementById('sx'); state.syEl = document.getElementById('sy'); state.todEl = document.getElementById('tod'); state.worldIdEl = document.getElementById('worldId'); state.playerCountEl = document.getElementById('playerCount'); state.deathEl = document.getElementById('death'); state.hotbarEl = document.getElementById('hotbar'); state.craftPanel = document.getElementById('craftPanel'); state.recipesEl = document.getElementById('recipes'); state.inventoryPanel = document.getElementById('inventoryPanel'); state.inventoryGrid = document.getElementById('inventoryGrid'); state.marketPanel = document.getElementById('marketPanel'); state.marketContent = document.getElementById('marketContent'); state.tradePanel = document.getElementById('tradePanel'); state.tradeContent = document.getElementById('tradeContent'); state.multiplayerStatus = document.getElementById('multiplayerStatus'); // ==================== 4) TEXTURES — initTextures() ==================== initTextures(); state.tex = tex; state.itemTex = itemTex; // ==================== 5) AUDIO — sounds already loaded by sound-engine.js module init ==================== // (sound-engine.js loads all sounds at module init time) // ==================== 6) CRAFT/INVENTORY BUTTONS ==================== const craftBtn = document.getElementById('craftBtn'); const invToggle = document.getElementById('invToggle'); const craftClose = document.getElementById('craftClose'); const inventoryClose = document.getElementById('inventoryClose'); if (craftBtn) craftBtn.onclick = () => toggleCraft(); if (craftClose) craftClose.onclick = () => closeCraft(); if (invToggle) invToggle.onclick = () => toggleInventory(); if (inventoryClose) inventoryClose.onclick = () => closeInventory(); // ==================== 7) CONTROLS — initControls ==================== initControls(); // ==================== 8) MOUSE — initMouseHandlers ==================== initMouseHandlers(); // ==================== 9) UI MODULES — init all UI ==================== initChat(); initFurnace(); initMinimap(); initSaveControls(); initMarket(); initRespawn(); initShare(); initModes(); // ==================== 10) SOCKET — initSocket ==================== initSocket(); // ==================== 11) VOICE — initVoice ==================== initVoice(); // ==================== 12) SAVE — loadGame, applySave ==================== rebuildHotbar(); initDB().then(async () => { const loadedSave = await loadGame(); if (loadedSave) { await applySave(loadedSave); console.log('Загружено сохранение, HP:', state.player.hp); if (state.player.hp <= 0) { console.log('WARNING: HP <= 0 после загрузки, возрождаемся'); state.player.hp = 100; state.player.hunger = 100; state.player.o2 = 100; state.player.x = state.spawnPoint.x; state.player.y = state.spawnPoint.y; state.player.vx = state.player.vy = 0; state.player.invuln = 0; state.player.fallStartY = state.player.y; } } else { console.log('Сохранение не найдено, начинаем новую игру'); state.player.hp = 100; state.player.hunger = 100; state.player.o2 = 100; state.player.vx = state.player.vy = 0; state.player.invuln = 0; // старт — на поверхности const startGX = 6; for (let dx = -3; dx <= 3; dx++) genColumn(startGX + dx); const surfaceY = surfaceGyAt(startGX); let safeGY = surfaceY - 1; const aboveBlock = getBlock(startGX, surfaceY - 1); if (aboveBlock && aboveBlock.t === 'water') { for (let gy = state.SEA_GY - 1; gy >= 0; gy--) { const b = getBlock(startGX, gy); if (!b || b.dead || b.t === 'air' || b.t === 'water') continue; safeGY = gy - 1; break; } } state.player.y = safeGY * state.TILE; state.player.x = startGX * state.TILE; state.player.fallStartY = state.player.y; state.spawnPoint.x = state.player.x; state.spawnPoint.y = state.player.y; console.log('Новая игра: startGX=', startGX, 'surfaceY=', surfaceY, 'player.y=', state.player.y); // Генерируем карту вокруг стартовой позиции for (let gx = startGX - 50; gx <= startGX + 50; gx++) { genColumn(gx); } } // Автосейв при скрытии страницы document.addEventListener('visibilitychange', () => { if (document.hidden) { saveGame(); } }); // Автосейв перед закрытием страницы window.addEventListener('beforeunload', () => { saveGame(); }); }).catch(err => { console.error('Ошибка инициализации:', err); const startGX = 6; genColumn(startGX); state.player.y = (surfaceGyAt(startGX) - 1) * state.TILE; state.player.fallStartY = state.player.y; for (let gx = startGX - 50; gx <= startGX + 50; gx++) { genColumn(gx); } }); // ==================== 13) LOOP — startLoop ==================== requestAnimationFrame(loop);