diablo2-web/plugins/automap-reveal/index.ts

179 lines
5.2 KiB
TypeScript

/**
* Automap Reveal Plugin (`plugins/automap-reveal/index.ts` — Issue #714).
*
* Isolates the non-1.13c full-level (`level`) and full-act (`act`) automap reveal
* enhancement outside core `src/`. When disabled, `PluginHost` releases the capability
* claim and strictly enforces 1.13c fog-of-war (`automapReveal = 'off'`).
*/
import {
VALID_AUTOMAP_REVEAL_MODES,
type AutomapRevealMode,
type D2WebPlugin,
type LocalizedText,
type PluginContext,
type PluginInstance,
type PluginStatus,
type PluginToolbarSelectOption,
} from '../../src/client/plugin-host/api.ts'
const AUTOMAP_MODE_LABELS: Readonly<Record<AutomapRevealMode, LocalizedText>> = {
off: {
zh: '关闭',
en: 'Off',
},
level: {
zh: '本层全开',
en: 'Current Level',
},
act: {
zh: '整幕全开',
en: 'Full Act',
},
}
const AUTOMAP_SELECT_OPTIONS: readonly PluginToolbarSelectOption[] =
VALID_AUTOMAP_REVEAL_MODES.map((mode) => ({
value: mode,
label: AUTOMAP_MODE_LABELS[mode],
}))
function isAutomapRevealMode(value: unknown): value is AutomapRevealMode {
return (
typeof value === 'string' &&
(VALID_AUTOMAP_REVEAL_MODES as readonly string[]).includes(value)
)
}
export interface AutomapRevealPluginInstance extends PluginInstance {
getMode(): AutomapRevealMode
setMode(mode: AutomapRevealMode): void
}
export function createAutomapRevealPlugin(): D2WebPlugin {
return {
id: 'automap-reveal',
name: {
zh: '小地图全图透视',
en: 'Automap Reveal',
},
description: {
zh: '非 1.13c 增强:支持一键揭开本层或整幕全部小地图房间与传送点标记。关闭插件后严格恢复 1.13c 原版战争迷雾(仅显示服务端已探索区域)。',
en: 'Non-1.13c enhancement: reveals all rooms and warp markers for the current level or entire Act. When disabled, strictly enforces 1.13c server-driven fog of war.',
},
defaultEnabled: true,
settings: [
{
kind: 'select',
key: 'mode',
label: {
zh: '透视范围',
en: 'Reveal Scope',
},
default: 'off',
options: AUTOMAP_SELECT_OPTIONS,
},
{
kind: 'boolean',
key: 'showToolbarShortcut',
label: {
zh: '在工具栏显示快捷下拉框',
en: 'Show selector in toolbar',
},
default: true,
},
],
activate(ctx: PluginContext): AutomapRevealPluginInstance {
const storedSetting = ctx.settings.get('mode')
const initialMode: AutomapRevealMode = isAutomapRevealMode(storedSetting)
? storedSetting
: 'off'
ctx.client.setAutomapReveal(initialMode)
const unsubClient = ctx.client.subscribeAutomapReveal((clientMode) => {
if (ctx.settings.get('mode') !== clientMode) {
ctx.settings.set('mode', clientMode)
}
ctx.notifyStatusChanged()
})
let removeToolbarSelect: (() => void) | null = null
const syncToolbarShortcut = (): void => {
const show = ctx.settings.get('showToolbarShortcut') === true
if (show && !removeToolbarSelect) {
removeToolbarSelect = ctx.toolbar.addSelect({
id: 'mode',
selectDomId: 'd2-toolbar-automap-select',
label: {
zh: '小地图',
en: 'Automap',
},
options: AUTOMAP_SELECT_OPTIONS,
getValue: () => {
const raw = ctx.settings.get('mode')
return isAutomapRevealMode(raw) ? raw : 'off'
},
onChange: (value: string) => {
if (!isAutomapRevealMode(value)) {
throw new Error(`Invalid automap reveal mode: ${value}`)
}
ctx.settings.set('mode', value)
},
})
} else if (!show && removeToolbarSelect) {
removeToolbarSelect()
removeToolbarSelect = null
}
}
syncToolbarShortcut()
const unsubSettings = ctx.settings.subscribe((key) => {
if (key === 'mode') {
const next = ctx.settings.get('mode')
if (isAutomapRevealMode(next)) {
ctx.client.setAutomapReveal(next)
ctx.notifyStatusChanged()
}
} else if (key === 'showToolbarShortcut') {
syncToolbarShortcut()
}
})
const getStatus = (): PluginStatus => {
const mode = ctx.client.getAutomapReveal()
const label = AUTOMAP_MODE_LABELS[mode]
return {
level: 'ok',
text: {
zh: `当前:${label.zh}`,
en: `Mode: ${label.en}`,
},
}
}
return {
getMode: () => ctx.client.getAutomapReveal(),
setMode: (mode: AutomapRevealMode) => {
if (!isAutomapRevealMode(mode)) {
throw new Error(`Invalid automap reveal mode: ${String(mode)}`)
}
ctx.settings.set('mode', mode)
},
getStatus,
deactivate(): void {
unsubClient()
unsubSettings()
if (removeToolbarSelect) {
removeToolbarSelect()
removeToolbarSelect = null
}
},
}
},
}
}
export const automapRevealPlugin: D2WebPlugin = createAutomapRevealPlugin()