Story 3.2 done
This commit is contained in:
@@ -22,11 +22,15 @@ import { StateStore } from './src/core/StateStore.js';
|
||||
import { SocketHandler } from './src/core/SocketHandler.js';
|
||||
import { VisibilityManager } from './src/core/VisibilityManager.js';
|
||||
import { ScryingPoolController } from './src/core/ScryingPoolController.js';
|
||||
import { ScenePresetManager } from './src/core/ScenePresetManager.js';
|
||||
import { AVTileAdapter } from './src/ui/shared/AVTileAdapter.js';
|
||||
import { RoleRenderer } from './src/ui/RoleRenderer.js';
|
||||
import { VisibilityBadge } from './src/ui/player/VisibilityBadge.js';
|
||||
import { NotificationBus } from './src/notifications/NotificationBus.js';
|
||||
import { DirectorsBoard } from './src/ui/gm/DirectorsBoard.js';
|
||||
import { ConfirmationBar } from './src/ui/gm/ConfirmationBar.js';
|
||||
import { StripOverlayLayer } from './src/ui/shared/StripOverlayLayer.js';
|
||||
import { SOCKET_EVENTS } from './src/contracts/socket-message.js';
|
||||
|
||||
// Module-level references — constructed in init hook, used across hooks
|
||||
let adapter;
|
||||
@@ -34,11 +38,14 @@ let stateStore;
|
||||
let socketHandler;
|
||||
let visibilityManager;
|
||||
let scryingPoolController;
|
||||
let scenePresetManager;
|
||||
let avTileAdapter;
|
||||
let roleRenderer;
|
||||
let visibilityBadge;
|
||||
let notificationBus;
|
||||
let directorsBoard;
|
||||
let stripOverlayLayer;
|
||||
let confirmationBar;
|
||||
/** @type {boolean} Flag to prevent duplicate scene control button addition */
|
||||
let directorsBoardButtonAdded = false;
|
||||
|
||||
@@ -89,7 +96,18 @@ Hooks.once("init", () => {
|
||||
default: "all",
|
||||
});
|
||||
|
||||
// Story 3.2: Global auto-apply enable/disable setting
|
||||
adapter.settings.register("autoApplyEnabled", {
|
||||
scope: "world",
|
||||
config: true,
|
||||
type: Boolean,
|
||||
default: true,
|
||||
name: "Enable Scene Preset Auto-Apply",
|
||||
hint: "When enabled, scenes with configured presets will automatically apply them on activation",
|
||||
});
|
||||
|
||||
// Construct data layer — constructors are side-effect-free
|
||||
// Note: ScenePresetManager is constructed in 'ready' hook after visibilityManager is available
|
||||
stateStore = new StateStore(adapter.settings);
|
||||
socketHandler = new SocketHandler(adapter.socket, adapter.hooks);
|
||||
|
||||
@@ -164,6 +182,27 @@ Hooks.once("ready", () => {
|
||||
// Wire core managers — construct both before setReady so handler can reference both
|
||||
visibilityManager = new VisibilityManager(stateStore, adapter);
|
||||
scryingPoolController = new ScryingPoolController(stateStore, socketHandler, adapter);
|
||||
|
||||
// Story 3.2: Re-construct ScenePresetManager with visibilityManager for auto-apply
|
||||
scenePresetManager = new ScenePresetManager(adapter, stateStore, socketHandler, visibilityManager);
|
||||
|
||||
// Story 3.2: Create StripOverlayLayer (shared infrastructure for UI components)
|
||||
stripOverlayLayer = new StripOverlayLayer(adapter);
|
||||
stripOverlayLayer.init();
|
||||
|
||||
// Story 3.2: Create ConfirmationBar for preset apply feedback
|
||||
confirmationBar = new ConfirmationBar(adapter, visibilityManager, socketHandler, stripOverlayLayer);
|
||||
confirmationBar.init();
|
||||
|
||||
// Story 3.2: Register updateScene hook for auto-apply
|
||||
adapter.hooks.on('updateScene', (scene) => {
|
||||
if (adapter.users.isGM()) {
|
||||
scenePresetManager.onSceneActivate(scene);
|
||||
}
|
||||
});
|
||||
|
||||
// Story 3.1: Initialize ScenePresetManager to load presets from current scene
|
||||
scenePresetManager.init();
|
||||
|
||||
// Set up composite handler for SocketHandler timeout callbacks
|
||||
// This allows cleanup of ScryingPoolController._pendingOps when onRevert fires
|
||||
@@ -194,9 +233,34 @@ Hooks.once("ready", () => {
|
||||
// Story 2.1: NotificationBus — runs for all clients (GM and players)
|
||||
notificationBus = new NotificationBus(adapter);
|
||||
notificationBus.init();
|
||||
// Story 3.1: Register socket listener for preset apply echo (all clients receive)
|
||||
// Note: In Foundry, socket messages are automatically broadcast to all clients.
|
||||
// The GM emits PRESET_APPLIED, and all clients (including GM) receive it.
|
||||
// We skip processing on the GM since they already applied it locally.
|
||||
adapter.socket.on(SOCKET_EVENTS.PRESET_APPLIED, async (payload) => {
|
||||
try {
|
||||
// Validate payload
|
||||
if (!payload || typeof payload !== 'object' || typeof payload.presetName !== 'string') {
|
||||
console.warn('[ScryingPool] Invalid PRESET_APPLIED payload:', payload);
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip on GM — they already applied the preset locally
|
||||
if (adapter.users.isGM()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Load the preset on this client (emitSocket: false to prevent loop)
|
||||
await scenePresetManager.load(payload.presetName, { emitSocket: false });
|
||||
} catch (err) {
|
||||
console.error('[ScryingPool] Failed to handle PRESET_APPLIED:', err);
|
||||
}
|
||||
});
|
||||
|
||||
// Story 2.2: DirectorsBoard (lazy, GM only)
|
||||
// Story 3.1: Pass scenePresetManager for preset save/load functionality
|
||||
if (adapter.users.isGM()) {
|
||||
directorsBoard = new DirectorsBoard(stateStore, scryingPoolController, adapter);
|
||||
directorsBoard = new DirectorsBoard(stateStore, scryingPoolController, adapter, scenePresetManager);
|
||||
directorsBoard.init();
|
||||
}
|
||||
} catch (err) {
|
||||
|
||||
Reference in New Issue
Block a user