171 lines
5.2 KiB
TypeScript
171 lines
5.2 KiB
TypeScript
/**
|
|
* Lighting Presets Plugin (`plugins/lighting-presets/index.ts` — Issue #715).
|
|
*
|
|
* Isolates the non-1.13c manual lighting preset selector (`noon`, `dusk`, `night`,
|
|
* `torch`, `cold`, `fullbright`) outside core `src/`. When disabled, `PluginHost`
|
|
* releases the capability claim and strictly enforces 1.13c native level lighting (`auto`).
|
|
*/
|
|
|
|
import {
|
|
CLIENT_LIGHTING_PRESET_ORDER,
|
|
LIGHTING_PRESETS,
|
|
VALID_LIGHTING_PRESETS,
|
|
type ClientLightingPreset,
|
|
type D2WebPlugin,
|
|
type PluginContext,
|
|
type PluginInstance,
|
|
type PluginStatus,
|
|
type PluginToolbarSelectOption,
|
|
} from '../../src/client/plugin-host/api.ts'
|
|
|
|
const LIGHTING_SELECT_OPTIONS: readonly PluginToolbarSelectOption[] =
|
|
CLIENT_LIGHTING_PRESET_ORDER.map((presetId) => {
|
|
const cfg = LIGHTING_PRESETS[presetId]
|
|
return {
|
|
value: presetId,
|
|
label: {
|
|
zh: cfg.labelZh,
|
|
en: cfg.labelEn,
|
|
},
|
|
}
|
|
})
|
|
|
|
function isLightingPreset(value: unknown): value is ClientLightingPreset {
|
|
return (
|
|
typeof value === 'string' &&
|
|
(VALID_LIGHTING_PRESETS as readonly string[]).includes(value)
|
|
)
|
|
}
|
|
|
|
export interface LightingPresetsPluginInstance extends PluginInstance {
|
|
getPreset(): ClientLightingPreset
|
|
setPreset(preset: ClientLightingPreset): void
|
|
}
|
|
|
|
export function createLightingPresetsPlugin(): D2WebPlugin {
|
|
return {
|
|
id: 'lighting-presets',
|
|
name: {
|
|
zh: '光照预设切换',
|
|
en: 'Lighting Presets',
|
|
},
|
|
description: {
|
|
zh: '非 1.13c 增强:允许手动切换全局环境光与火把照明预设(正午/黄昏/黑夜/火把/寒光/全亮)。关闭插件后严格恢复 1.13c 原版关卡环境光(自动)。',
|
|
en: 'Non-1.13c enhancement: manually override ambient RGB and player torch radius (Noon, Dusk, Night, Torch, Cold, Fullbright). When disabled, strictly enforces 1.13c level lighting (Auto).',
|
|
},
|
|
defaultEnabled: true,
|
|
settings: [
|
|
{
|
|
kind: 'select',
|
|
key: 'preset',
|
|
label: {
|
|
zh: '光照模式',
|
|
en: 'Lighting Mode',
|
|
},
|
|
default: 'auto',
|
|
options: LIGHTING_SELECT_OPTIONS,
|
|
},
|
|
{
|
|
kind: 'boolean',
|
|
key: 'showToolbarShortcut',
|
|
label: {
|
|
zh: '在工具栏显示快捷下拉框',
|
|
en: 'Show selector in toolbar',
|
|
},
|
|
default: true,
|
|
},
|
|
],
|
|
activate(ctx: PluginContext): LightingPresetsPluginInstance {
|
|
const storedSetting = ctx.settings.get('preset')
|
|
const initialPreset: ClientLightingPreset = isLightingPreset(storedSetting)
|
|
? storedSetting
|
|
: 'auto'
|
|
|
|
ctx.client.setLightingPreset(initialPreset)
|
|
|
|
const unsubClient = ctx.client.subscribeLightingPreset((clientPreset) => {
|
|
if (ctx.settings.get('preset') !== clientPreset) {
|
|
ctx.settings.set('preset', clientPreset)
|
|
}
|
|
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: 'preset',
|
|
selectDomId: 'd2-toolbar-lighting-select',
|
|
label: {
|
|
zh: '光照',
|
|
en: 'Lighting',
|
|
},
|
|
options: LIGHTING_SELECT_OPTIONS,
|
|
getValue: () => {
|
|
const raw = ctx.settings.get('preset')
|
|
return isLightingPreset(raw) ? raw : 'auto'
|
|
},
|
|
onChange: (value: string) => {
|
|
if (!isLightingPreset(value)) {
|
|
throw new Error(`Invalid lighting preset: ${value}`)
|
|
}
|
|
ctx.settings.set('preset', value)
|
|
},
|
|
})
|
|
} else if (!show && removeToolbarSelect) {
|
|
removeToolbarSelect()
|
|
removeToolbarSelect = null
|
|
}
|
|
}
|
|
|
|
syncToolbarShortcut()
|
|
|
|
const unsubSettings = ctx.settings.subscribe((key) => {
|
|
if (key === 'preset') {
|
|
const next = ctx.settings.get('preset')
|
|
if (isLightingPreset(next)) {
|
|
ctx.client.setLightingPreset(next)
|
|
ctx.notifyStatusChanged()
|
|
}
|
|
} else if (key === 'showToolbarShortcut') {
|
|
syncToolbarShortcut()
|
|
}
|
|
})
|
|
|
|
const getStatus = (): PluginStatus => {
|
|
const preset = ctx.client.getLightingPreset()
|
|
const cfg = LIGHTING_PRESETS[preset]
|
|
return {
|
|
level: 'ok',
|
|
text: {
|
|
zh: `当前:${cfg.labelZh}`,
|
|
en: `Preset: ${cfg.labelEn}`,
|
|
},
|
|
}
|
|
}
|
|
|
|
return {
|
|
getPreset: () => ctx.client.getLightingPreset(),
|
|
setPreset: (preset: ClientLightingPreset) => {
|
|
if (!isLightingPreset(preset)) {
|
|
throw new Error(`Invalid lighting preset: ${String(preset)}`)
|
|
}
|
|
ctx.settings.set('preset', preset)
|
|
},
|
|
getStatus,
|
|
deactivate(): void {
|
|
unsubClient()
|
|
unsubSettings()
|
|
if (removeToolbarSelect) {
|
|
removeToolbarSelect()
|
|
removeToolbarSelect = null
|
|
}
|
|
},
|
|
}
|
|
},
|
|
}
|
|
}
|
|
|
|
export const lightingPresetsPlugin: D2WebPlugin = createLightingPresetsPlugin()
|