feat: calendrier impérial et conversions calendaires
- calendrier impérial : fenêtre compacte (260px), affichage date - commande /cal, auto-ouverture paramétrable dans les settings - socket calendarSync : mise à jour temps réel pour les joueurs - config MJ : année, jour (label live), heure:minute, planète - boutons +1 jour et +1 heure (report 24h→jour, 365→1) - conversions : Solomani, Vilani, Zhodani (Olympiade), Aslan, K'Kree, Hiver - formules wiki.travellerrpg.com/Date_Conversion, section repliable - fix: renderChatInput /cal trop large → exact match - fix: fenêtre refermable (onClose nullifie la référence) - fix: socket joueur lit data direct au lieu de readCalendar()
This commit is contained in:
@@ -0,0 +1,208 @@
|
||||
import { CalendarApp } from './CalendarApp.js';
|
||||
import { CalendarConfigDialog } from './CalendarConfigDialog.js';
|
||||
import { getDefaultCalendar } from './calendarDate.js';
|
||||
|
||||
const MODULE_ID = 'mgt2-compendium-amiral-denisov';
|
||||
const ChatLogV2 = foundry.applications.sidebar.tabs.ChatLog;
|
||||
|
||||
let _calendarApp = null;
|
||||
|
||||
function readCalendar() {
|
||||
return {
|
||||
year: game.settings.get(MODULE_ID, 'calendarYear'),
|
||||
day: game.settings.get(MODULE_ID, 'calendarDay'),
|
||||
hour: game.settings.get(MODULE_ID, 'calendarHour'),
|
||||
minute: game.settings.get(MODULE_ID, 'calendarMinute'),
|
||||
planet: game.settings.get(MODULE_ID, 'calendarPlanet'),
|
||||
};
|
||||
}
|
||||
|
||||
async function writeCalendar(data) {
|
||||
await game.settings.set(MODULE_ID, 'calendarYear', data.year);
|
||||
await game.settings.set(MODULE_ID, 'calendarDay', data.day);
|
||||
await game.settings.set(MODULE_ID, 'calendarHour', data.hour);
|
||||
await game.settings.set(MODULE_ID, 'calendarMinute', data.minute);
|
||||
await game.settings.set(MODULE_ID, 'calendarPlanet', data.planet);
|
||||
}
|
||||
|
||||
function applyCalendar(data) {
|
||||
if (_calendarApp) {
|
||||
_calendarApp.updateDisplay(data);
|
||||
}
|
||||
}
|
||||
|
||||
async function broadcastCalendar(data) {
|
||||
if (!game.socket?.emit) return;
|
||||
game.socket.emit(`module.${MODULE_ID}`, {
|
||||
_type: 'calendarSync',
|
||||
...data,
|
||||
});
|
||||
}
|
||||
|
||||
function openCalendarApp() {
|
||||
if (_calendarApp) {
|
||||
_calendarApp.bringToTop();
|
||||
return;
|
||||
}
|
||||
const data = readCalendar();
|
||||
_calendarApp = new CalendarApp({
|
||||
onConfig: () => openCalendarConfig(),
|
||||
onClose: () => { _calendarApp = null; },
|
||||
});
|
||||
_calendarApp.updateDisplay(data);
|
||||
_calendarApp.render({ force: true });
|
||||
}
|
||||
|
||||
function openCalendarConfig() {
|
||||
const data = readCalendar();
|
||||
const dialog = new CalendarConfigDialog({
|
||||
data,
|
||||
onApply: async (newData) => {
|
||||
await writeCalendar(newData);
|
||||
applyCalendar(newData);
|
||||
broadcastCalendar(newData);
|
||||
dialog.close();
|
||||
},
|
||||
});
|
||||
dialog.render({ force: true });
|
||||
}
|
||||
|
||||
function registerCalCommand() {
|
||||
if (!ChatLogV2?.CHAT_COMMANDS) return;
|
||||
ChatLogV2.CHAT_COMMANDS.cal = {
|
||||
rgx: /^\/cal(?:\s+(.*))?$/i,
|
||||
fn: () => {
|
||||
openCalendarApp();
|
||||
return false;
|
||||
},
|
||||
};
|
||||
console.log(`${MODULE_ID} | Commande /cal enregistrée via ChatLog.CHAT_COMMANDS`);
|
||||
}
|
||||
|
||||
Hooks.once('init', () => {
|
||||
const def = getDefaultCalendar();
|
||||
|
||||
game.settings.register(MODULE_ID, 'calendarYear', {
|
||||
name: 'Année impériale',
|
||||
scope: 'world',
|
||||
config: false,
|
||||
type: Number,
|
||||
default: def.year,
|
||||
});
|
||||
game.settings.register(MODULE_ID, 'calendarDay', {
|
||||
name: 'Jour impérial (1-365)',
|
||||
scope: 'world',
|
||||
config: false,
|
||||
type: Number,
|
||||
default: def.day,
|
||||
});
|
||||
game.settings.register(MODULE_ID, 'calendarHour', {
|
||||
name: 'Heure locale',
|
||||
scope: 'world',
|
||||
config: false,
|
||||
type: Number,
|
||||
default: def.hour,
|
||||
});
|
||||
game.settings.register(MODULE_ID, 'calendarMinute', {
|
||||
name: 'Minute locale',
|
||||
scope: 'world',
|
||||
config: false,
|
||||
type: Number,
|
||||
default: def.minute,
|
||||
});
|
||||
game.settings.register(MODULE_ID, 'calendarPlanet', {
|
||||
name: 'Planète',
|
||||
scope: 'world',
|
||||
config: false,
|
||||
type: String,
|
||||
default: def.planet,
|
||||
});
|
||||
game.settings.register(MODULE_ID, 'calendarAutoOpen', {
|
||||
name: 'Calendrier impérial : auto-ouverture',
|
||||
hint: 'Ouvre automatiquement la fenêtre du calendrier au démarrage',
|
||||
scope: 'world',
|
||||
config: true,
|
||||
type: Boolean,
|
||||
default: true,
|
||||
});
|
||||
|
||||
const loadTemplatesFn = foundry.applications?.handlebars?.loadTemplates || loadTemplates;
|
||||
if (loadTemplatesFn) {
|
||||
loadTemplatesFn([
|
||||
`modules/${MODULE_ID}/templates/calendar-app.hbs`,
|
||||
`modules/${MODULE_ID}/templates/calendar-config.hbs`,
|
||||
]);
|
||||
}
|
||||
|
||||
registerCalCommand();
|
||||
console.log(`${MODULE_ID} | Calendrier impérial initialisé`);
|
||||
});
|
||||
|
||||
Hooks.once('ready', () => {
|
||||
game.socket.on(`module.${MODULE_ID}`, (data) => {
|
||||
if (game.user?.isGM) return;
|
||||
if (data?._type !== 'calendarSync') return;
|
||||
if (!_calendarApp) {
|
||||
const { year, day, hour, minute, planet } = data;
|
||||
_calendarApp = new CalendarApp({
|
||||
onClose: () => { _calendarApp = null; },
|
||||
});
|
||||
_calendarApp.updateDisplay({ year, day, hour, minute, planet });
|
||||
_calendarApp.render({ force: true });
|
||||
return;
|
||||
}
|
||||
_calendarApp.updateDisplay(data);
|
||||
});
|
||||
|
||||
if (game.settings.get(MODULE_ID, 'calendarAutoOpen')) {
|
||||
openCalendarApp();
|
||||
}
|
||||
});
|
||||
|
||||
Hooks.on('preCreateChatMessage', (message, data, options) => {
|
||||
const content = message.content?.trim()?.toLowerCase();
|
||||
if (content === '/cal' || content?.startsWith('/cal ')) {
|
||||
openCalendarApp();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
Hooks.on('chatMessage', (...args) => {
|
||||
let message;
|
||||
if (args[0]?.content !== undefined) {
|
||||
message = args[0].content;
|
||||
} else if (typeof args[1] === 'string') {
|
||||
message = args[1];
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
const trimmed = message?.trim()?.toLowerCase();
|
||||
if (trimmed === '/cal' || trimmed?.startsWith('/cal ')) {
|
||||
openCalendarApp();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
Hooks.on('renderChatInput', (app, html, data) => {
|
||||
let input;
|
||||
if (html?.element) {
|
||||
input = $(html.element).find('textarea[name="content"]');
|
||||
} else if (html?.find) {
|
||||
input = html.find('textarea[name="content"]');
|
||||
} else {
|
||||
input = $(html).find('textarea[name="content"]');
|
||||
}
|
||||
if (input.data('mgt2-cal-listener')) return;
|
||||
input.data('mgt2-cal-listener', true);
|
||||
input.on('keydown', (event) => {
|
||||
if (event.key === 'Enter' && !event.shiftKey) {
|
||||
const content = input.val()?.trim();
|
||||
if (content === '/cal' || content?.startsWith('/cal ')) {
|
||||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
openCalendarApp();
|
||||
input.val('');
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user