merge: resolve conflicts, keep working game.js

This commit is contained in:
root 2026-05-27 04:55:00 +00:00
commit 2a5f65d393
11 changed files with 6592 additions and 319 deletions

View File

@ -4,6 +4,7 @@ COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY index.html /usr/share/nginx/html/index.html
COPY style.css /usr/share/nginx/html/style.css
COPY game.js /usr/share/nginx/html/game.js
COPY src/ /usr/share/nginx/html/src/
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

1899
game.js

File diff suppressed because it is too large Load Diff

4568
game.js.bak.v23 Normal file

File diff suppressed because it is too large Load Diff

97
index-new.html Normal file
View File

@ -0,0 +1,97 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>GrechkaCraft: Multiplayer</title>
<!-- Socket.io Client (loaded as regular script, provides window.io) -->
<script src="https://cdn.socket.io/4.7.4/socket.io.min.js"></script>
<link rel="stylesheet" href="style.css?v=5">
</head>
<body>
<div id="game">
<canvas id="c"></canvas>
<div class="ui">
<div id="stats">
<div class="row">❤️ <span id="hp">100</span> &nbsp; 🍗 <span id="food">100</span></div>
<div class="row">🫁 <span id="o2">100</span></div>
<div class="row">📍 X:<span id="sx">0</span> Y:<span id="sy">0</span></div>
<div class="row">🕒 <span id="tod">День</span></div>
<div class="row">🌐 <span id="worldId" style="cursor:pointer; text-decoration:underline;" title="Нажмите, чтобы скопировать ссылку">default</span></div>
<div class="row" id="multiplayerStatus" style="display:none;">👥 <span id="playerCount">0</span></div>
</div>
<div id="modeBtn" class="rbtn pe">⛏️</div>
<div id="saveBtn" class="rbtn pe">💾</div>
<div id="craftBtn" class="rbtn pe">🔨</div>
<div id="resetBtn" class="rbtn pe">🔄</div>
<div id="chatToggle" class="rbtn pe">💬</div>
<div id="invToggle" class="rbtn pe">📦</div>
<div id="mapToggle" class="rbtn pe">🗺️</div>
<div id="hotbar" class="pe"></div>
</div>
<!-- Миникарта -->
<div id="minimapWrap" style="display:none;position:absolute;left:10px;top:120px;z-index:200;pointer-events:auto;">
<canvas id="minimap" width="200" height="120" style="border:2px solid rgba(255,255,255,0.7);border-radius:8px;background:rgba(0,0,0,0.8);"></canvas>
</div>
<!-- Печь -->
<div id="furnacePanel" class="panel" style="display:none;">
<div class="panel-header">
<span>🔥 Печь</span>
<span id="furnaceClose" class="close" style="cursor:pointer;"></span>
</div>
<div id="furnaceContent" style="padding:8px;"></div>
</div>
<div id="controls">
<div id="left" class="btn pe">⬅️</div>
<div id="jump" class="btn pe">⬆️</div>
<div id="down" class="btn pe">⬇️</div>
<div id="right" class="btn pe">➡️</div>
</div>
<div id="craftPanel" class="panel" style="display:none;">
<div class="panel-header">
<span>Крафт</span>
<span id="craftClose" class="close" style="cursor:pointer;"></span>
</div>
<div id="recipes"></div>
</div>
<div id="inventoryPanel" class="panel" style="display:none;">
<div class="panel-header">
<span>Инвентарь</span>
<span id="inventoryClose" class="close" style="cursor:pointer;"></span>
</div>
<div id="inventoryGrid"></div>
</div>
<div id="chatPanel" class="panel" style="display:none;">
<div class="panel-header">
<span>Чат</span>
<span id="chatClose" class="close" style="cursor:pointer;"></span>
</div>
<div id="chatMessages"></div>
<div class="chat-input">
<input type="text" id="chatInput" placeholder="Введите сообщение...">
<button id="chatSend">Отправить</button>
</div>
</div>
<div id="death" class="death-screen" style="display:none;">
<div class="death-content">
<h1>💀 Вы погибли!</h1>
<button id="respawnBtn" class="respawn-btn">Возродиться</button>
</div>
</div>
</div>
<script type="module" src="src/main.js?v=9"></script>
</body>
</html>

97
index-old.html Normal file
View File

@ -0,0 +1,97 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>GrechkaCraft: Multiplayer</title>
<!-- Socket.io Client -->
<script src="https://cdn.socket.io/4.7.4/socket.io.min.js"></script>
<link rel="stylesheet" href="style.css?v=5">
</head>
<body>
<div id="game">
<canvas id="c"></canvas>
<div class="ui">
<div id="stats">
<div class="row">❤️ <span id="hp">100</span> &nbsp; 🍗 <span id="food">100</span></div>
<div class="row">🫁 <span id="o2">100</span></div>
<div class="row">📍 X:<span id="sx">0</span> Y:<span id="sy">0</span></div>
<div class="row">🕒 <span id="tod">День</span></div>
<div class="row">🌐 <span id="worldId" style="cursor:pointer; text-decoration:underline;" title="Нажмите, чтобы скопировать ссылку">default</span></div>
<div class="row" id="multiplayerStatus" style="display:none;">👥 <span id="playerCount">0</span></div>
</div>
<div id="modeBtn" class="rbtn pe">⛏️</div>
<div id="saveBtn" class="rbtn pe">💾</div>
<div id="craftBtn" class="rbtn pe">🔨</div>
<div id="resetBtn" class="rbtn pe">🔄</div>
<div id="chatToggle" class="rbtn pe">💬</div>
<div id="invToggle" class="rbtn pe">📦</div>
<div id="mapToggle" class="rbtn pe">🗺️</div>
<div id="hotbar" class="pe"></div>
</div>
<!-- Миникарта -->
<div id="minimapWrap" style="display:none;position:absolute;left:10px;top:120px;z-index:200;pointer-events:auto;">
<canvas id="minimap" width="200" height="120" style="border:2px solid rgba(255,255,255,0.7);border-radius:8px;background:rgba(0,0,0,0.8);"></canvas>
</div>
<!-- Печь -->
<div id="furnacePanel" class="panel" style="display:none;">
<div class="panel-header">
<span>🔥 Печь</span>
<span id="furnaceClose" class="close" style="cursor:pointer;"></span>
</div>
<div id="furnaceContent" style="padding:8px;"></div>
</div>
<div id="controls">
<div id="left" class="btn pe">⬅️</div>
<div id="jump" class="btn pe">⬆️</div>
<div id="down" class="btn pe">⬇️</div>
<div id="right" class="btn pe">➡️</div>
</div>
<div id="craftPanel" class="panel" style="display:none;">
<div class="panel-header">
<span>Крафт</span>
<span id="craftClose" class="close" style="cursor:pointer;"></span>
</div>
<div id="recipes"></div>
</div>
<div id="inventoryPanel" class="panel" style="display:none;">
<div class="panel-header">
<span>Инвентарь</span>
<span id="inventoryClose" class="close" style="cursor:pointer;"></span>
</div>
<div id="inventoryGrid"></div>
</div>
<div id="chatPanel" class="panel" style="display:none;">
<div class="panel-header">
<span>Чат</span>
<span id="chatClose" class="close" style="cursor:pointer;"></span>
</div>
<div id="chatMessages"></div>
<div class="chat-input">
<input type="text" id="chatInput" placeholder="Введите сообщение...">
<button id="chatSend">Отправить</button>
</div>
</div>
<div id="death" class="death-screen" style="display:none;">
<div class="death-content">
<h1>💀 Вы погибли!</h1>
<button id="respawnBtn" class="respawn-btn">Возродиться</button>
</div>
</div>
</div>
<script src="game.js?v=8"></script>
</body>
</html>

View File

@ -6,7 +6,7 @@
<title>GrechkaCraft: Multiplayer</title>
<!-- Socket.io Client -->
<script src="https://cdn.socket.io/4.7.4/socket.io.min.js"></script>
<link rel="stylesheet" href="style.css?v=5">
<link rel="stylesheet" href="style.css?v=6">
</head>
<body>
@ -20,6 +20,7 @@
<div class="row">📍 X:<span id="sx">0</span> Y:<span id="sy">0</span></div>
<div class="row">🕒 <span id="tod">День</span></div>
<div class="row">🌐 <span id="worldId" style="cursor:pointer; text-decoration:underline;" title="Нажмите, чтобы скопировать ссылку">default</span></div>
<div class="row">⭐ Lv.<span id="xplevel">1</span> | XP: <span id="xpbar">0/50</span></div>
<div class="row" id="multiplayerStatus" style="display:none;">👥 <span id="playerCount">0</span></div>
</div>
@ -35,7 +36,7 @@
</div>
<!-- Миникарта -->
<div id="minimapWrap" style="display:none;position:absolute;left:10px;top:120px;z-index:200;pointer-events:auto;">
<div id="minimapWrap" style="display:none;position:absolute;left:190px;top:10px;z-index:200;pointer-events:auto;">
<canvas id="minimap" width="200" height="120" style="border:2px solid rgba(255,255,255,0.7);border-radius:8px;background:rgba(0,0,0,0.8);"></canvas>
</div>
@ -92,6 +93,6 @@
</div>
</div>
<script src="game.js?v=8"></script>
<script src="game.js?v=24"></script>
</body>
</html>

View File

@ -3,10 +3,15 @@ server {
root /usr/share/nginx/html;
index index.html;
location ~* \.(js|css)$ {
# CORS for ES modules
add_header Access-Control-Allow-Origin *;
location ~* \.(js|mjs|css)$ {
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
add_header Access-Control-Allow-Origin *;
expires 0;
default_type application/javascript;
}
location / {

View File

@ -3,7 +3,7 @@ import { state } from '../core/state.js';
import { BLOCKS } from '../data/blocks.js';
import { playSound } from '../audio/sound-engine.js';
import { getBlock } from '../world/world-storage.js';
import { updateWaterPhysics } from '../world/water.js';
import { updateWaterPhysics } from '../physics/water.js';
import { updateWaterFlag } from '../physics/water-detect.js';
import { resolveY, resolveX } from '../physics/collision.js';
import { calculateDamage } from '../entities/player.js';

View File

@ -25,7 +25,7 @@ import { initVoice } from './multiplayer/voice-chat.js';
import { resolveY, resolveX } from './physics/collision.js';
import { calculateDamage } from './entities/player.js';
import { updateWaterFlag } from './physics/water-detect.js';
import { updateWaterPhysics } from './world/water.js';
import { updateWaterPhysics } from './physics/water.js';
import { explodeAt, activateTNT } from './world/tnt.js';
import { useTool } from './data/tools.js';
import { rebuildHotbar } from './ui/hotbar.js';

View File

@ -91,3 +91,16 @@ body.touch-device #hotbar {
#death { display:none; position:absolute; inset:0; background: rgba(60,0,0,0.88);
z-index:200; color:#fff; pointer-events:auto; align-items:center; justify-content:center; flex-direction:column; gap:12px; }
#death button { padding:12px 18px; font-size:18px; font-weight:900; border:none; border-radius:12px; cursor:pointer; }
/* Panel header + close button fix */
.panel-header { display:flex; justify-content:space-between; align-items:center; color:#fff; font-weight:900; font-size:18px; margin-bottom:12px; padding-bottom:8px; border-bottom:1px solid rgba(255,255,255,0.15); }
.panel-header .close { background:#c0392b; border:none; color:#fff; font-weight:900; padding:8px 12px; border-radius:10px; cursor:pointer; font-size:16px; min-width:36px; text-align:center; flex-shrink:0; margin-left:12px; }
/* Custom modal (alerts/confirms) */
.custom-modal-overlay { position:absolute; inset:0; background:rgba(0,0,0,0.7); z-index:9999; display:flex; align-items:center; justify-content:center; }
.custom-modal-box { background:#1a1a2e; border:2px solid #e74c3c; border-radius:16px; padding:24px 32px; color:#fff; font-size:16px; font-weight:700; text-align:center; max-width:320px; box-shadow:0 8px 32px rgba(0,0,0,0.5); }
.custom-modal-box .modal-btns { display:flex; gap:10px; justify-content:center; margin-top:16px; }
.custom-modal-box button { font-weight:900; padding:10px 20px; border-radius:10px; font-size:15px; cursor:pointer; border:none; color:#fff; }
.custom-modal-box .btn-yes { background:#e74c3c; }
.custom-modal-box .btn-no { background:#555; }
.custom-modal-box .btn-ok { background:#2ecc71; }

70
voice-test.html Normal file
View File

@ -0,0 +1,70 @@
<!DOCTYPE html>
<html><head><title>Voice Test</title></head><body>
<h1>Voice Capture Test</h1>
<button id="btn" style="padding:20px;font-size:24px;background:#2ecc71;color:#fff;border:none;border-radius:12px;cursor:pointer;">Start Mic</button>
<div id="log" style="font-family:monospace;white-space:pre;margin-top:20px;"></div>
<script src="https://cdn.socket.io/4.7.4/socket.io.min.js"></script>
<script>
const log = document.getElementById('log');
function addLog(msg) { log.textContent += msg + '\n'; console.log(msg); }
let voiceStream, audioCtx, voiceProcessor, voiceSocket;
let debugCount = 0;
document.getElementById('btn').onclick = async () => {
try {
addLog('1. Requesting mic...');
voiceStream = await navigator.mediaDevices.getUserMedia({ audio: { echoCancellation: true, noiseSuppression: true } });
addLog('2. Got stream: ' + voiceStream.getTracks().map(t => t.label + ' ' + t.readyState).join(', '));
audioCtx = new AudioContext({ sampleRate: 24000 });
if (audioCtx.state === 'suspended') await audioCtx.resume();
addLog('3. AudioContext: state=' + audioCtx.state + ' sampleRate=' + audioCtx.sampleRate);
const source = audioCtx.createMediaStreamSource(voiceStream);
voiceProcessor = audioCtx.createScriptProcessor(2048, 1, 1);
addLog('4. ScriptProcessor created');
voiceProcessor.onaudioprocess = (e) => {
debugCount++;
const pcm = e.inputBuffer.getChannelData(0);
const maxVal = Math.max(...Array.from(pcm).map(Math.abs));
if (debugCount <= 10) addLog('5. onaudioprocess #' + debugCount + ' samples=' + pcm.length + ' max=' + maxVal.toFixed(4));
if (!voiceSocket || !voiceSocket.connected) return;
const int16 = new Int16Array(pcm.length);
for (let i = 0; i < pcm.length; i++) {
const s = Math.max(-1, Math.min(1, pcm[i]));
int16[i] = s < 0 ? s * 0x8000 : s * 0x7FFF;
}
voiceSocket.emit('voice_data', int16.buffer);
};
const silentGain = audioCtx.createGain();
silentGain.gain.value = 0;
source.connect(voiceProcessor);
voiceProcessor.connect(silentGain);
silentGain.connect(audioCtx.destination);
addLog('6. Audio chain connected: source→processor→gain(0)→destination');
addLog('7. Connecting to voice server...');
voiceSocket = io('https://voicegrech.mkn8n.ru', { transports: ['websocket'] });
voiceSocket.on('connect', () => {
addLog('8. Socket connected: ' + voiceSocket.id);
voiceSocket.emit('voice_join', { world_id: 'test', x: 0, y: 0, name: 'Tester' });
addLog('9. Sent voice_join. Speak into mic — watch onaudioprocess logs above!');
});
voiceSocket.on('connect_error', (err) => addLog('ERROR: ' + err.message));
voiceSocket.on('voice_in', (payload) => {
addLog('VOICE_IN from ' + payload.meta.name + ' vol=' + payload.volume + ' bytes=' + payload.data.byteLength);
});
document.getElementById('btn').textContent = 'Listening...';
document.getElementById('btn').style.background = '#e74c3c';
} catch(e) {
addLog('ERROR: ' + e.message + '\n' + e.stack);
}
};
</script>
</body></html>