selection fonctionnelle
This commit is contained in:
parent
db052845c6
commit
4cf1aca7e4
2 changed files with 90 additions and 3 deletions
|
|
@ -267,11 +267,26 @@
|
||||||
|
|
||||||
connectAndJoin();
|
connectAndJoin();
|
||||||
|
|
||||||
// Start button handler (host)
|
// Start button handler (host) — ensure custom deck is applied before starting
|
||||||
document.getElementById('startBtn').addEventListener('click', ()=>{
|
document.getElementById('startBtn').addEventListener('click', ()=>{
|
||||||
if(!socket) return;
|
if(!socket) return;
|
||||||
|
// If custom draw is enabled and host selected cards, send the deck first
|
||||||
|
try{
|
||||||
|
if(customDrawToggleEl && customDrawToggleEl.checked && selectedCards.size && myPlayerId && roomHostId && myPlayerId === roomHostId){
|
||||||
|
socket.emit('room:deck:set', { roomId, selected: Array.from(selectedCards) }, (deckResp)=>{
|
||||||
|
if(deckResp && deckResp.error){ showToast(deckResp.message || deckResp.error, { background: 'rgba(200,60,60,0.95)' }); return; }
|
||||||
|
// now start the game
|
||||||
|
socket.emit('game:start', { roomId }, (resp)=>{
|
||||||
|
if(resp && resp.error){ log('start error', resp); showToast(resp.error || resp.message || 'Erreur', { background: 'rgba(200,60,60,0.95)' }); return; }
|
||||||
|
log('game:start acknowledged');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}catch(_){ }
|
||||||
|
// fallback: start immediately
|
||||||
socket.emit('game:start', { roomId }, (resp)=>{
|
socket.emit('game:start', { roomId }, (resp)=>{
|
||||||
if(resp && resp.error){ log('start error', resp); showToast(resp.error || resp.message || 'Erreur', { background: 'rgba(200,60,60,0.95)' }); return; }
|
if(resp && resp.error){ log('start error', resp); showToast(resp.error || resp.message || 'Erreur', { background: 'rgba(200,60,60,0.95)' }); return; }
|
||||||
log('game:start acknowledged');
|
log('game:start acknowledged');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -311,6 +326,26 @@
|
||||||
const checked = !!customDrawToggleEl.checked;
|
const checked = !!customDrawToggleEl.checked;
|
||||||
log('custom-draw toggled (minimal)', { checked });
|
log('custom-draw toggled (minimal)', { checked });
|
||||||
if(customCardsSection) customCardsSection.style.display = checked ? 'block' : 'none';
|
if(customCardsSection) customCardsSection.style.display = checked ? 'block' : 'none';
|
||||||
|
// When toggling the checkbox, inform server: if unchecked, clear custom deck on server so default deck is used.
|
||||||
|
try{
|
||||||
|
if(socket && socket.connected && myPlayerId && roomHostId && myPlayerId === roomHostId){
|
||||||
|
if(!checked){
|
||||||
|
// inform server to revert to default deck
|
||||||
|
socket.emit('room:deck:set', { roomId, selected: [] }, (resp)=>{
|
||||||
|
if(resp && resp.error) showToast(resp.message || resp.error, { background: 'rgba(200,60,60,0.95)' });
|
||||||
|
else showToast('Pioche personnalisée désactivée — pioche par défaut restaurée', { background: 'rgba(40,160,40,0.95)' });
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// if checked and we already have a selection, push it to server
|
||||||
|
if(selectedCards.size){
|
||||||
|
socket.emit('room:deck:set', { roomId, selected: Array.from(selectedCards) }, (resp)=>{
|
||||||
|
if(resp && resp.error) showToast(resp.message || resp.error, { background: 'rgba(200,60,60,0.95)' });
|
||||||
|
else showToast('Pioche personnalisée activée', { background: 'rgba(40,160,40,0.95)' });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}catch(_){ }
|
||||||
if(checked){
|
if(checked){
|
||||||
// fetch card list and render simple names
|
// fetch card list and render simple names
|
||||||
if(customCardsContainer){
|
if(customCardsContainer){
|
||||||
|
|
@ -379,6 +414,15 @@
|
||||||
selectMark.style.display = 'flex';
|
selectMark.style.display = 'flex';
|
||||||
}
|
}
|
||||||
saveSelection();
|
saveSelection();
|
||||||
|
// if we're the host and connected AND custom-draw is enabled, update the server's custom deck selection
|
||||||
|
try{
|
||||||
|
if(socket && socket.connected && myPlayerId && roomHostId && myPlayerId === roomHostId && customDrawToggleEl && customDrawToggleEl.checked){
|
||||||
|
socket.emit('room:deck:set', { roomId, selected: Array.from(selectedCards) }, (resp)=>{
|
||||||
|
if(resp && resp.error){ showToast(resp.message || resp.error, { background: 'rgba(200,60,60,0.95)' }); }
|
||||||
|
else { showToast('Pioche personnalisée mise à jour', { background: 'rgba(40,160,40,0.95)' }); }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}catch(_){ }
|
||||||
});
|
});
|
||||||
|
|
||||||
grid.appendChild(cardEl);
|
grid.appendChild(cardEl);
|
||||||
|
|
@ -400,6 +444,15 @@
|
||||||
else { selectedCards.delete(id); el.classList.remove('selected'); if(mark) mark.style.display = 'none'; }
|
else { selectedCards.delete(id); el.classList.remove('selected'); if(mark) mark.style.display = 'none'; }
|
||||||
});
|
});
|
||||||
saveSelection();
|
saveSelection();
|
||||||
|
// send selection to server if host AND custom-draw enabled
|
||||||
|
try{
|
||||||
|
if(socket && socket.connected && myPlayerId && roomHostId && myPlayerId === roomHostId && customDrawToggleEl && customDrawToggleEl.checked){
|
||||||
|
socket.emit('room:deck:set', { roomId, selected: Array.from(selectedCards) }, (resp)=>{
|
||||||
|
if(resp && resp.error) showToast(resp.message || resp.error, { background: 'rgba(200,60,60,0.95)' });
|
||||||
|
else showToast('Pioche personnalisée mise à jour', { background: 'rgba(40,160,40,0.95)' });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}catch(_){ }
|
||||||
}
|
}
|
||||||
if(customSelectAllBtn) customSelectAllBtn.addEventListener('click', (e)=>{ e.preventDefault(); setAllVisible(true); });
|
if(customSelectAllBtn) customSelectAllBtn.addEventListener('click', (e)=>{ e.preventDefault(); setAllVisible(true); });
|
||||||
if(customDeselectAllBtn) customDeselectAllBtn.addEventListener('click', (e)=>{ e.preventDefault(); setAllVisible(false); });
|
if(customDeselectAllBtn) customDeselectAllBtn.addEventListener('click', (e)=>{ e.preventDefault(); setAllVisible(false); });
|
||||||
|
|
|
||||||
36
server.js
36
server.js
|
|
@ -303,7 +303,9 @@ function buildDefaultDeck(){
|
||||||
let ascii = normalized;
|
let ascii = normalized;
|
||||||
try{ ascii = ascii.normalize('NFD').replace(/\p{Diacritic}/gu, ''); }catch(e){ /* ignore if normalize unsupported */ }
|
try{ ascii = ascii.normalize('NFD').replace(/\p{Diacritic}/gu, ''); }catch(e){ /* ignore if normalize unsupported */ }
|
||||||
const cardId = ascii.replace(/[^a-z0-9]+/gi,'_').toLowerCase();
|
const cardId = ascii.replace(/[^a-z0-9]+/gi,'_').toLowerCase();
|
||||||
return { id: uuidv4().slice(0,8), cardId, title: cap(normalized), description: desc };
|
// Use deterministic id equal to the slug so clients and server agree on identifiers across requests
|
||||||
|
const id = cardId;
|
||||||
|
return { id, cardId, title: cap(normalized), description: desc };
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1251,6 +1253,38 @@ io.on('connection', (socket) => {
|
||||||
cb && cb({ ok: true });
|
cb && cb({ ok: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Host can set a custom deck for the room (selected list of card ids). Only host may change it.
|
||||||
|
socket.on('room:deck:set', ({ roomId, selected }, cb) => {
|
||||||
|
const room = rooms.get(roomId);
|
||||||
|
if(!room) return cb && cb({ error: 'room not found', message: "Aucune salle trouvée." });
|
||||||
|
const sender = socket.data.playerId;
|
||||||
|
if(!sender) return cb && cb({ error: 'not joined', message: "Vous n'avez pas rejoint la salle." });
|
||||||
|
if(room.hostId !== sender) return cb && cb({ error: 'only host can set deck', message: "Seul l'hôte peut définir la pioche." });
|
||||||
|
try{
|
||||||
|
// selected is expected to be an array of card identifiers (either id or cardId)
|
||||||
|
const sel = Array.isArray(selected) ? selected : [];
|
||||||
|
// Build a lookup from the canonical default deck and current room deck
|
||||||
|
const master = buildDefaultDeck();
|
||||||
|
const pool = (room.deck && Array.isArray(room.deck) && room.deck.length) ? room.deck.concat(master) : master;
|
||||||
|
const byId = {};
|
||||||
|
pool.forEach(c => { if(c && c.id) byId[c.id] = c; if(c && c.cardId) byId[c.cardId] = c; });
|
||||||
|
// Map selected ids to card objects, preserving order. If a selected id is unknown, ignore it.
|
||||||
|
const newDeck = [];
|
||||||
|
sel.forEach(sid => { const c = byId[sid]; if(c) newDeck.push(Object.assign({}, c)); });
|
||||||
|
if(newDeck.length === 0){
|
||||||
|
// empty selection -> revert to default deck
|
||||||
|
room.deck = buildDefaultDeck();
|
||||||
|
} else {
|
||||||
|
room.deck = newDeck;
|
||||||
|
}
|
||||||
|
// reset discard and hands so the new deck applies for the upcoming game
|
||||||
|
room.discard = room.discard || [];
|
||||||
|
// inform players
|
||||||
|
sendRoomUpdate(room);
|
||||||
|
return cb && cb({ ok: true, deckCount: room.deck.length });
|
||||||
|
}catch(err){ console.error('room:deck:set error', err); return cb && cb({ error: 'server_error' }); }
|
||||||
|
});
|
||||||
|
|
||||||
socket.on('disconnect', () => {
|
socket.on('disconnect', () => {
|
||||||
const roomId = socket.data.roomId;
|
const roomId = socket.data.roomId;
|
||||||
if (!roomId) return;
|
if (!roomId) return;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue