const MODULE_ID = 'mgt2-compendium-amiral-denisov'; const { ApplicationV2, HandlebarsApplicationMixin } = foundry.applications.api; let _playerDialog = null; class PlayerMapDialog extends HandlebarsApplicationMixin(ApplicationV2) { static DEFAULT_OPTIONS = { id: 'mgt2-sector-map-player', classes: ['mgt2-sector-map'], position: { width: 960, height: 720 }, window: { icon: 'fas fa-map', resizable: true }, }; static PARTS = { main: { template: `modules/${MODULE_ID}/templates/player-map.hbs`, }, }; constructor(url, sector) { super(); this._mapUrl = url; this._sectorLabel = sector ? `Secteur ${sector}` : 'Carte stellaire'; } get title() { return this._sectorLabel; } async _prepareContext() { return { url: this._mapUrl }; } updateMap(url) { this._mapUrl = url; const iframe = this.element?.querySelector('iframe'); if (iframe) iframe.src = url; } } function buildMapUrl(sector, subsector, mapHex, mapCenter, mapScale) { const base = 'https://travellermap.com'; if (!sector) return `${base}/?style=mongoose&hideui=1`; if (subsector) { let url = `${base}/?sector=${encodeURIComponent(sector)}&subsector=${encodeURIComponent(subsector)}&style=mongoose&hideui=1`; if (mapCenter && mapScale) url += `¢er=${mapCenter}&scale=${mapScale}`; return url; } let url = `${base}/?sector=${encodeURIComponent(sector)}&style=mongoose&hideui=1`; if (mapHex) { url += `&hex=${mapHex}&scale=512`; } else if (mapCenter && mapScale) { url += `¢er=${mapCenter}&scale=${mapScale}`; } return url; } Hooks.once('ready', () => { console.log(`${MODULE_ID} | sectorSocket pret`); game.socket.on(`module.${MODULE_ID}`, (data) => { if (game.user?.isGM) return; if (data?._type === 'sectorMapSync') { try { const url = buildMapUrl(data.sector, data.subsector, data.mapHex, data.mapCenter, data.mapScale); if (_playerDialog) { _playerDialog.updateMap(url); _playerDialog.bringToTop?.(); console.log(`${MODULE_ID} | Carte mise a jour`); return; } _playerDialog = new PlayerMapDialog(url, data.sector); _playerDialog.render({ force: true }).then(() => { console.log(`${MODULE_ID} | Dialog affiche`); }).catch(err => { console.error(`${MODULE_ID} | Erreur render:`, err); }); } catch (err) { console.error(`${MODULE_ID} | Erreur:`, err); } return; } if (data?._type === 'canvasSync') { try { const { x, y, scale } = data; console.log(`${MODULE_ID} | Canvas sync recu:`, x, y, scale); canvas.animatePan({ x, y, scale, duration: 0 }); } catch (err) { console.error(`${MODULE_ID} | Erreur canvas sync:`, err); } return; } if (data?._type === 'closeImagePopout') { try { let closed = 0; document.querySelectorAll('.image-popout, [class*="image-popout"], [id*="image-popout"]').forEach(el => { el.remove(); closed++; }); console.log(`${MODULE_ID} | ${closed} portrait(s) fermé(s)`); } catch (err) { console.error(`${MODULE_ID} | Erreur close portraits:`, err); } return; } }); });