Files
mgt2-compendium-amiral-denisov/scripts/sector.js
T
2026-06-02 00:16:08 +02:00

209 lines
5.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* MGT2 Commandes /sector et /subsector
*
* Ouvre l'application interactive SectorMapApp (IFRAME Traveller Map).
* Compatible Foundry VTT v13 et v14
*/
import { SectorMapApp } from './SectorMapApp.js';
import { postWorldCardToChat } from './worldCard.js';
import { CommerceDialog } from './CommerceDialog.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 (!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 handleSystemCommand(sector, hex) {
if (!sector || !hex) {
ui.notifications.warn('Usage : /system <secteur> <hex> (ex: /system "Spinward Marches" 1910)');
return;
}
await postWorldCardToChat(sector, hex);
}
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 <secteur> <sous-secteur> (ex: /subsector "Spinward Marches" C)');
return;
}
const sub = parts.pop();
const sector = parts.join(' ');
if (!sector || !sub) {
ui.notifications.warn('Usage : /subsector <secteur> <sous-secteur>');
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?.();
handleSectorCommand(raw || undefined);
return false;
},
};
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`);
ChatLogV2.CHAT_COMMANDS['system'] = {
rgx: /^\/system\s+(.+?)\s+(\d{4})\s*$/i,
fn: function() {
const sector = arguments[1]?.[1]?.trim?.();
const hex = arguments[1]?.[2]?.trim?.();
if (sector && hex) {
handleSystemCommand(sector, hex);
return false;
}
return true;
},
};
console.log(`${MODULE_ID} | Commande /system 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;
}
m = c?.match(/^\/system\s+(.+?)\s+(\d{4})\s*$/i);
if (m) {
handleSystemCommand(m[1]?.trim(), m[2]?.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);
});
// Clics sur les liens de monde dans les journals de trajet
document.addEventListener('click', (event) => {
const link = event.target.closest('.mgt2-world-link');
if (!link) return;
event.preventDefault();
const sector = link.dataset.sector;
const hex = link.dataset.hex;
if (sector && hex) {
handleSystemCommand(sector, hex);
}
});
// Clics sur le bouton Commerce dans les cartes de monde
document.addEventListener('click', (event) => {
const btn = event.target.closest('.mgt2-world-commerce');
if (!btn) return;
event.preventDefault();
const uwp = btn.dataset.uwp;
const zone = btn.dataset.zone;
const name = btn.dataset.name;
const sector = btn.dataset.sector;
const hex = btn.dataset.hex;
if (uwp) {
const existing = Object.values(ui.windows).find(w => w.id === 'mgt2-commerce');
if (existing) { existing.bringToTop(); return; }
const dialog = new CommerceDialog({
defaultWorld: { uwp, zone, name, sector, hex },
initialTab: 'trade',
});
dialog.render({ force: true });
}
});
});
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;
}
m = msg?.trim()?.match(/^\/system\s+(.+?)\s+(\d{4})\s*$/i);
if (m) {
handleSystemCommand(m[1]?.trim(), m[2]?.trim());
return false;
}
});