/** * MGT2 – Commandes /sector et /subsector * * Ouvre l'application interactive SectorMapApp (IFRAME Traveller Map). * Compatible Foundry VTT v13 et v14 */ import { SectorMapApp } from './SectorMapApp.js'; const MODULE_ID = 'mgt2-compendium-amiral-denisov'; const ChatLogV2 = foundry.applications?.sidebar?.tabs?.ChatLog; let _pendingHandle = false; /* ───── Fonctions partagées ───── */ async function openMap(sector, subsector) { const app = new SectorMapApp(sector, subsector); await app.render({ force: true }); } async function handleSectorCommand(sector, subsector) { if (_pendingHandle) return; _pendingHandle = true; try { if (!sector?.trim()) { ui.notifications.warn('Usage : /sector (ex: /sector "Spinward Marches")'); return; } if (!game.user?.isGM) { ui.notifications.error('Seul le MJ peut utiliser cette commande'); return; } await openMap(sector.trim()); } catch (err) { console.error(`${MODULE_ID} | Erreur /sector :`, err); ui.notifications.error(`Erreur : ${err.message}`); } finally { _pendingHandle = false; } } async function handleSubsectorCommand(raw) { if (_pendingHandle) return; _pendingHandle = true; try { const parts = raw?.trim().split(/\s+/); if (!parts || parts.length < 2) { ui.notifications.warn('Usage : /subsector (ex: /subsector "Spinward Marches" C)'); return; } const sub = parts.pop(); const sector = parts.join(' '); if (!sector || !sub) { ui.notifications.warn('Usage : /subsector '); return; } if (!game.user?.isGM) { ui.notifications.error('Seul le MJ peut utiliser cette commande'); return; } await openMap(sector.trim(), sub.trim()); } catch (err) { console.error(`${MODULE_ID} | Erreur /subsector :`, err); ui.notifications.error(`Erreur : ${err.message}`); } finally { _pendingHandle = false; } } /* ───── Commande /sector ───── */ if (ChatLogV2?.CHAT_COMMANDS) { ChatLogV2.CHAT_COMMANDS['sector'] = { rgx: /^\/sector(?:\s+(.*))?$/i, fn: function() { const raw = arguments[1]?.[1]?.trim?.(); if (raw) { handleSectorCommand(raw); return false; } return true; }, }; console.log(`${MODULE_ID} | Commande /sector enregistrée`); ChatLogV2.CHAT_COMMANDS['subsector'] = { rgx: /^\/subsector(?:\s+(.*))?$/i, fn: function() { const raw = arguments[1]?.[1]?.trim?.(); if (raw) { handleSubsectorCommand(raw); return false; } return true; }, }; console.log(`${MODULE_ID} | Commande /subsector enregistrée`); } /* ───── Hooks de secours (v13 / fallback v14) ───── */ Hooks.on('preCreateChatMessage', (message, data, options) => { const c = message.content?.trim(); let m = c?.match(/^\/sector(?:\s+(.*))?$/i); if (m) { handleSectorCommand(m[1]?.trim()); return false; } m = c?.match(/^\/subsector(?:\s+(.*))?$/i); if (m) { handleSubsectorCommand(m[1]?.trim()); return false; } }); /* ───── Socket (synchronisation MJ → joueurs) ───── */ Hooks.once('ready', () => { game.socket.on(`module.${MODULE_ID}`, (data) => { if (data?.type !== 'sectorMapSync') return; if (game.user?.isGM) return; openMap(data.sector, data.subsector); }); }); Hooks.on('chatMessage', (...args) => { let msg; if (args[0]?.content !== undefined) msg = args[0].content; else if (typeof args[1] === 'string') msg = args[1]; else return; let m = msg?.trim()?.match(/^\/sector(?:\s+(.*))?$/i); if (m) { handleSectorCommand(m[1]?.trim()); return false; } m = msg?.trim()?.match(/^\/subsector(?:\s+(.*))?$/i); if (m) { handleSubsectorCommand(m[1]?.trim()); return false; } });