HumanBreak/src/core/main/setting.ts

166 lines
4.9 KiB
TypeScript
Raw Normal View History

2023-08-02 23:25:14 +08:00
import { EmitableEvent, EventEmitter } from '../common/eventEmitter';
2023-08-02 23:17:10 +08:00
type MotaSettingType = boolean | number | MotaSetting;
interface MotaSettingItem<T extends MotaSettingType = MotaSettingType> {
name: string;
value: T;
defaults?: boolean | number;
step?: number;
display?: (value: T) => string;
2023-08-02 23:27:57 +08:00
special?: string;
2023-08-02 23:17:10 +08:00
}
2023-08-02 23:25:14 +08:00
interface SettingEvent extends EmitableEvent {
valueChange: <T extends boolean | number>(
key: string,
newValue: T,
oldValue: T
) => void;
}
class MotaSetting extends EventEmitter<SettingEvent> {
2023-08-02 23:17:10 +08:00
private list: Record<string, MotaSettingItem> = {};
/**
*
*/
2023-08-02 23:27:57 +08:00
markSpecial(key: string, sp: string) {
const setting = this.getSettingBy(key.split('.'));
setting.special = sp;
2023-08-02 23:17:10 +08:00
return this;
}
/**
*
* @param key
* @param value
*/
register(key: string, name: string, value: number, step?: number): this;
/**
*
* @param key
* @param value
*/
register(key: string, name: string, value: boolean | MotaSetting): this;
register(
key: string,
name: string,
value: MotaSettingType,
step: number = 1
) {
const setting: MotaSettingItem = {
name,
value
};
if (!(value instanceof MotaSetting)) setting.defaults = value;
if (typeof value === 'number') setting.step = step;
this.list[key] = setting;
return this;
}
/**
*
* @param key
*/
getSetting(key: string): Readonly<MotaSettingItem | null> {
const list = key.split('.');
return this.getSettingBy(list);
}
/**
*
* @param key
* @param value
*/
setValue(key: string, value: boolean | number) {
const setting = this.getSettingBy(key.split('.'));
if (typeof setting.value !== typeof value) {
throw new Error(
`Setting type mismatch on setting '${key}'.` +
`Expected: ${typeof setting.value}. Recieve: ${typeof value}`
);
}
2023-08-02 23:25:14 +08:00
const old = setting.value as boolean | number;
2023-08-02 23:17:10 +08:00
setting.value = value;
2023-08-02 23:27:57 +08:00
this.emit('valueChange', key, old, value);
2023-08-02 23:17:10 +08:00
}
/**
*
* @param key
* @param value
*/
addValue(key: string, value: number) {
const setting = this.getSettingBy(key.split('.'));
if (typeof setting.value !== 'number') {
throw new Error(
`Cannot execute addValue method on a non-number setting.` +
`Type expected: number. See: ${typeof setting.value}`
);
}
2023-08-02 23:25:14 +08:00
const old = setting.value as boolean | number;
2023-08-02 23:17:10 +08:00
setting.value += value;
2023-08-02 23:27:57 +08:00
this.emit('valueChange', key, old, value);
2023-08-02 23:17:10 +08:00
}
/**
*
* @param key
* @param func
*/
setDisplayFunc(key: string, func: (value: MotaSettingType) => string) {
const setting = this.getSettingBy(key.split('.'));
setting.display = func;
}
private getSettingBy(list: string[]) {
let now: MotaSetting = this;
for (let i = 0; i < list.length - 1; i++) {
const item = now.list[list[i]];
if (!(item instanceof MotaSetting)) {
throw new Error(
`Cannot get setting. The parent isn't a MotaSetting instance.` +
`Key: '${list.join('.')}'. Reading: '${list[i]}'`
);
}
now = item;
}
return now.list[list.at(-1)!] ?? null;
}
}
export const mainSetting = new MotaSetting();
// ----- 游戏的所有设置项
mainSetting
.register(
'screen',
'显示设置',
new MotaSetting()
.register('fullscreen', '全屏游戏', false)
.register('halo', '光环显示', true)
.register('frag', '打怪特效', true)
.register('itemDetail', '宝石血瓶显伤', true)
.register('transition', '界面动画', false)
.register('antiAlias', '抗锯齿', false)
.register('autoScale', '自动放缩', true)
.register('fontSize', '字体大小', 16, 1)
)
.register(
'action',
'操作设置',
new MotaSetting()
.register('autoSkill', '自动切换技能', true)
.register('fixed', '定点查看', true)
2023-08-02 23:27:57 +08:00
.register('hotkey', '快捷键', false)
.markSpecial('hotkey', 'hotkey')
2023-08-02 23:17:10 +08:00
)
.register(
'utils',
'功能设置',
new MotaSetting().register('betterLoad', '优化加载', true)
);