Skip to content

Commit

Permalink
feat: 迁移关卡模块到新版api
Browse files Browse the repository at this point in the history
  • Loading branch information
median-dxz committed Jul 8, 2024
1 parent 2799020 commit b5b4553
Show file tree
Hide file tree
Showing 89 changed files with 1,133 additions and 977 deletions.
50 changes: 25 additions & 25 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
// 以下信息仅在 >= 1.0 版本内显示,后续 1.0 版本发布后(应为第一个可用的稳定版)将删除并重新开始记录 changelog
// 为什么要删掉?一个是因为乱;一个是后面肯定会用上更好的 changelog 管理工具(changeset 预定)而不是手动编辑;最重要的一点:changelog 一般是供开发者了解功能变更,从而帮助版本的迁移。但是前面这会根本没有人用,自然不用关心这些问题...

当前更新内容 模组安装与管理(2024.6)
当前更新内容 模组安装与管理 & 关卡功能重构(2024.7)

- [ ] 关卡配置与mod配置UI
- [ ] 调度界面, 删除全部已完成
- [ ] 收星星上限出错出错处理
- [ ] 更新vip签到(flash商城?)
- [ ] 全屏与刷新按钮
- [ ] 关卡添加与结束的snackbar
- [ ] rotating算子基于内部计数器而不是round
- [ ] 命名空间的脆弱性
- [ ] core v1.0.0

- [ ] https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html#the-configdir-template-variable-for-configuration-files
- [ ] 升级sdk的ts版本
Expand All @@ -10,30 +20,25 @@
- [ ] 需要一次性提供 Launcher Api 版本,Core 版本和自身版本
- [ ] launcher api 版本和 launcher 版本之间的关系?
- [ ] 同步server launcher mod-type的版本,保持统一
- [x] 统一签到模组(`sign`)到关卡, 将无战斗纯发包的也视为关卡的一种
- [x] 可能需要重新设计关卡的整体接口
- [ ] 顺便解决关卡进度指示器的问题
- [ ] 战斗日志保存
- [ ] script 通过语法树进行高级反混淆, 暂定主要目标是升级 async/await
- [ ] 后端日志管理
- [ ] rotating
- [ ] 配置管理
- [ ] 预置功能管理
- [x] 一键收星星
- [ ] 内置模组在更新时的处理
- [ ] 日任掉线
- [ ] 自定义背景(各种意义上?)
- [x] 控制中心:自动治疗开关
- [ ] QuickAccess 重做,移入主界面底部
- [ ] ctOverride
- [ ] 日常新增:功勋任务
- [ ] spt 扫荡
- [ ] 作战实验室 六界扫荡 星际迷航 神兽
- [ ] 常用配置查询
- [ ] 精灵养成模组,每天自动养成指定精灵
- [ ] 自动消耗积分
- [ ] 指定一个列表,自动选择没有达到指标的精灵进行养成
- [ ] launcher 语法高亮模块
- [ ] launcher 语法高亮模块 hljs
- [ ] launcher 轻量配置编辑器模块,日志显示模块
- [ ] launcher 和 server 的 logger 模块
- [ ] 调度界面, 删除全部已完成
- [ ] 模组加载时的出错处理
- [ ] 教程的 cc 共享协议
- [ ] 删除博客功能
Expand All @@ -42,30 +47,26 @@
- [ ] 由后端支持的更新 dist 文件夹进行软件更新
- [ ] dc 群组
- [ ] yo 工作区脚手架构建
- [ ] 引入 changeset
- [ ] 引入 changeset + 发版
- [ ] 优化自动构建脚本
- [ ] 搜索功能
- [ ] sdk/预设/例子/模组发布转移到单独的仓库
- [ ] store逻辑复用优化
- [ ] 拆分优化调度器list
- [ ] pick函数
- [ ] 优化内置日志输出,信息输出,封装组件
- [ ] tarui/electron 打包项目
- [ ] 控件拖动
- [ ] 当前面板路径
- [ ] 进入对战超时
- [ ] 更新vip签到
- [ ] 日任掉线
- [ ] 更换名片精灵页面的重复
- [ ] 全屏与刷新按钮
- [ ] 收星星上限出错出错处理
- [ ] 收星星上限逻辑
- [ ] coverage文件夹换位置
- [ ] 对等依赖<->dts定义(例如注册查询表)(可参考:next模块定义,mui对样式引擎的定义依赖)
- [ ] 模组定义新增标志位,表明不支持热重载
- [ ] 取消对http-proxy-middleware的依赖
- [ ] PanelTable是不是直接useMemo就行了,奇怪的cacheReturn hook
- [ ] 错误边界

# Core 当前版本 v1.0.0-rc.5
# Core 当前版本 v1.0.0-rc.6

- [x] 精简 api 界面, 删除不必要的导出
- [x] 删除不常用的子包导出
Expand All @@ -88,20 +89,20 @@
- [x] 日志模块重写,输出 object 而不是消息,可以子 logger 化
- [ ] 查询关卡获取的因子数量
- [x] 启用单元测试
- [ ] 对于 CoreLoad 的注册 hook, 提供标志位来进行功能的打开,关闭
- [ ] 同时公开 hook 数组, 以便登录器层可以开关特定功能
- [ ] 解耦登录器/后端特定逻辑, 分离非核心功能, 部分移动到登录器下的`features`包下, 由登录器提供扩展定义, 部分合并到`engine`
- [ ] script 解密
- [ ] 对战显血
- [ ] 自动关弹窗
- [ ] logFilter

# Core 1.1.0

- [ ] 查询魂印激活放到 SEAPet 中
- [x] LevelRunner使用事件流
- [ ] 完善 pet 缓存逻辑
- [ ] 同时优化第五和魂印的检测逻辑
- [ ] 集成测试作为单独的包,移出 core
- [x] 对于 CoreLoad 的注册 hook, 提供标志位来进行功能的打开,关闭
- [x] 同时公开 hook 数组, 以便登录器层可以开关特定功能
- [x] 集成测试作为单独的包,移出 core

# Core v1.1.0

# 低优先级

Expand All @@ -111,7 +112,6 @@
- [x] 根组件渲染提前到 Core.init
- [ ] jsx 外部化, import-map 共享 react
- [ ] cookie issue
- [ ] 更换 store 库(不用 context)
- [ ] 在三个加载资源处都显示 总加载文件数 当前文件名 当前已下载大小/当前文件大小
- [ ] 考虑如何使`Strategy`添加更简单的 fallback 支持(可能添加一个字段?)
- [ ] 例如`true`代表 fallback 到自动, 否则链式依次 fallback
Expand Down
27 changes: 14 additions & 13 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,18 @@ export default tsEslint.config(
'@typescript-eslint/dot-notation': ['error', { allowIndexSignaturePropertyAccess: true }],
'@typescript-eslint/array-type': ['error', { default: 'array-simple' }],
'@typescript-eslint/no-unnecessary-condition': ['error', { allowConstantLoopConditions: true }],
'@typescript-eslint/no-invalid-void-type': ['error', { allowAsThisParameter: true }]
'@typescript-eslint/no-invalid-void-type': ['error', { allowAsThisParameter: true }],
'@typescript-eslint/no-confusing-void-expression': [
'error',
{ ignoreArrowShorthand: true, ignoreVoidOperator: true }
],
'@typescript-eslint/no-misused-promises': [
'error',
{
checksVoidReturn: false
}
],
'@typescript-eslint/no-extraneous-class': 'off'
}
},
{
Expand Down Expand Up @@ -107,7 +118,8 @@ export default tsEslint.config(
// @ts-expect-error
rules: {
...reactHooks.configs.recommended.rules,
'react-refresh/only-export-components': 'warn'
'react-refresh/only-export-components': 'warn',
'@typescript-eslint/no-unsafe-assignment': 'warn' // swr 当前版本解构出的 error 只能推导出 any
}
},
// @sea/server
Expand All @@ -117,17 +129,6 @@ export default tsEslint.config(
globals: {
...globals.node
}
},
rules: {
'@typescript-eslint/no-misused-promises': [
'error',
{
checksVoidReturn: {
arguments: false,
attributes: false
}
}
]
}
},
{
Expand Down
8 changes: 2 additions & 6 deletions packages/core/battle/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,7 @@ export default () => {
context.triggerLock?.(isWin);
manager.clear();
})
.catch((err: unknown) => {
console.error(err);
});
.catch((err: unknown) => console.error(err));
}
});

Expand All @@ -73,7 +71,5 @@ export default () => {
return [fi, si] as const;
});

SEAEventSource.socket(CommandID.NOTE_USE_SKILL, 'receive').on((data) => {
cachedRoundInfo.update([...data]);
});
SEAEventSource.socket(CommandID.NOTE_USE_SKILL, 'receive').on((data) => cachedRoundInfo.update([...data]));
};
52 changes: 32 additions & 20 deletions packages/core/battle/level/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Subject, tap } from 'rxjs';
import { delay } from '../../common/utils.js';
import { engine } from '../../internal/index.js';
import { spet } from '../../pet-helper/index.js';
Expand All @@ -14,6 +15,10 @@ class LevelManager {
private runner: LevelRunner | null = null;
lock: Promise<void> | null = null;

update$ = new Subject<void>();
nextAction$ = new Subject<string>();
log$ = new Subject<string>();

get running() {
return this.runner != null;
}
Expand All @@ -29,18 +34,16 @@ class LevelManager {
try {
await this.lock;
} catch (e) {
throw new Error(`关卡运行失败: ${e as string}`);
} finally {
this.lock = null;
manager.clear();
// pass
}
}

run(runner: LevelRunner) {
if (this.running) throw new Error('你必须先停止当前Runner的运行!');

this.runner = runner;
const { logger } = runner;
const log$ = new Subject<string>();
const subscription = log$.pipe(tap(runner.logger)).subscribe(this.log$);

const lockFn = async () => {
const autoCureState = await engine.autoCureState();
Expand All @@ -53,19 +56,19 @@ class LevelManager {

const { strategy, pets, beforeBattle } = levelBattle;

logger('准备对战');
log$.next('准备对战');
await engine.switchBag(pets);

void engine.toggleAutoCure(false);
engine.cureAllPet();

await delay(100);

logger('执行beforeBattle');
log$.next('执行beforeBattle');
await beforeBattle?.();
await spet(pets[0]).default();

logger('进入对战');
log$.next('进入对战');
try {
if (!this.runner) throw new Error('关卡已停止运行');

Expand All @@ -74,28 +77,30 @@ class LevelManager {
void runner.actions['battle'].call(runner);
}, strategy);

logger('对战完成');
log$.next('对战完成');
} catch (error) {
this.runner = null;
logger(`接管对战失败: ${error as string}`);
log$.next(`接管对战失败: ${error as string}`);
}

manager.clear();
};

while (this.runner) {
logger('更新关卡信息');
await runner.update();
this.update$.next();
log$.next('更新关卡信息');

const nextAction = runner.next();
logger(`next action: ${nextAction}`);
this.nextAction$.next(nextAction);
log$.next(`next action: ${nextAction}`);

switch (nextAction) {
case LevelAction.BATTLE:
await battle();
break;
case LevelAction.STOP:
if (runner.actions['stop']) {
await runner.actions['stop'].call(runner);
}
await runner.actions['stop']?.call(runner);
this.runner = null;
break;
default:
Expand All @@ -104,17 +109,24 @@ class LevelManager {
}
await delay(100);
}
logger('正在停止关卡');
log$.next('正在停止关卡');
// 恢复自动治疗状态
await engine.toggleAutoCure(autoCureState);
engine.cureAllPet();
await delay(200);

logger('关卡完成');
this.lock = this.runner = null;
};

this.lock = lockFn();
this.lock = lockFn()
.catch((err: unknown) => {
log$.next(`关卡运行失败: ${err as string}`);
throw err;
})
.finally(() => {
log$.next('关卡运行结束');
subscription.unsubscribe();
this.lock = this.runner = null;
manager.clear();
});
}
}

Expand Down
4 changes: 2 additions & 2 deletions packages/core/battle/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ function getCurRoundInfo() {
id: FighterModelFactory.playerMode.info.petID,
name: FighterModelFactory.playerMode.info.petName,
hp: {
gain: roundInfo[0].hp.gain,
gain: 0,
remain: FighterModelFactory.playerMode.info.hp,
max: FighterModelFactory.playerMode.info.maxHP
},
Expand All @@ -51,7 +51,7 @@ function getCurRoundInfo() {
id: FighterModelFactory.enemyMode.info.petID,
name: FighterModelFactory.enemyMode.info.petName,
hp: {
gain: roundInfo[1].hp.gain,
gain: 0,
remain: FighterModelFactory.enemyMode.info.hp,
max: FighterModelFactory.enemyMode.info.maxHP
},
Expand Down
2 changes: 1 addition & 1 deletion packages/core/common/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export class HookedSymbol {
export function delay(time: number): Promise<void> {
return new Promise((resolver) => setTimeout(resolver, time));
}
/** 去抖 所有小于指定间隔的调用只会响应最后一个 */
/** 去抖 所有小于指定间隔的调用只会在最后一个超时后响应 */
export function debounce<F extends AnyFunction>(func: F, time: number) {
let timer: number | undefined;
return function (this: unknown, ...args: Parameters<F>) {
Expand Down
9 changes: 6 additions & 3 deletions packages/core/event-source/EventSource.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { take, type Observable, type Subscription } from 'rxjs';
import type { Observable, Subscription } from 'rxjs';
import { take } from 'rxjs';
import { fromEvent } from './source-builder/fromEvent.js';
import { fromEventPattern } from './source-builder/fromEventPattern.js';
import { fromGameModule } from './source-builder/fromGameModule.js';
import { fromHook } from './source-builder/fromHook.js';
import { fromLevelManager } from './source-builder/fromLevelManager.js';
import { fromEgret } from './source-builder/fromNative.js';
import { fromSocket } from './source-builder/fromSocket.js';

Expand All @@ -16,8 +18,8 @@ export class SEAEventSource<T> {
private subscriptions = new Map<number, Subscription>();
private subscriptionId = 0;

constructor(EventSource$: Observable<T>) {
this._source$ = EventSource$;
constructor(eventSource$: Observable<T>) {
this._source$ = eventSource$;
}

on(handler: (data: T) => void) {
Expand Down Expand Up @@ -45,4 +47,5 @@ export class SEAEventSource<T> {
static readonly hook = fromHook;
static readonly egret = fromEgret;
static readonly socket = fromSocket;
static readonly levelManger = fromLevelManager;
}
20 changes: 20 additions & 0 deletions packages/core/event-source/source-builder/fromLevelManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { levelManager } from '../../battle/index.js';
import { SEAEventSource } from '../EventSource.js';

type LevelManagerEvents = 'update' | 'nextAction' | 'log';

export function fromLevelManager(event: 'update'): SEAEventSource<void>;
export function fromLevelManager(event: 'nextAction' | 'log'): SEAEventSource<string>;

export function fromLevelManager(event: LevelManagerEvents) {
switch (event) {
case 'update':
return new SEAEventSource(levelManager.update$);
case 'nextAction':
return new SEAEventSource(levelManager.nextAction$);
case 'log':
return new SEAEventSource(levelManager.log$);
default:
throw new Error(`Invalid type ${event as string}, type could only be 'update'`);
}
}
Loading

0 comments on commit b5b4553

Please sign in to comment.