refactor(09-3): align main/statusBar/toolbar to props.state (D-11/D-13)

- main.tsx: add MainSceneProps extends IUIPropsBase + props decl; mainMapRenderer/mainMapExtension/flags/9x getFinalAttribute/addHook -> props.state; thread state={props.state} to LeftStatusBar/RightStatusBar; D-13 TODOs (3); keep state/using/mainUIController
- statusBar.tsx: StatusBarProps base + IUIPropsBase + 'state' prop; client.materials -> p.state.materials; thread state to MixedToolbar
- toolbar.tsx: ToolbarProps/ReplayingProps base + IUIPropsBase + 'state' prop; client.materials -> props.state.materials; thread state to child toolbars
This commit is contained in:
unanmed 2026-10-09 17:17:31 +08:00
parent d1f167ce6f
commit 699b0b09a0
3 changed files with 57 additions and 29 deletions

View File

@ -7,7 +7,7 @@ import {
// import { WeatherController } from '../weather';
import { defineComponent, onUnmounted, reactive, ref } from 'vue';
import { Textbox, TextboxProps, Tip } from '@user/client-base';
import { GameUI } from '@motajs/system';
import { GameUI, SetupComponentOptions } from '@motajs/system';
import {
ENABLE_RIGHT_STATUS_BAR,
MAIN_HEIGHT,
@ -29,10 +29,17 @@ import { state } from '@user/data-state';
import { mainUIController } from './controller';
import { isNil } from 'lodash-es';
import { using } from '../render/renderer';
import { client } from '../core';
import { IUIPropsBase } from './types';
const MainScene = defineComponent(() => {
const { mainMapRenderer, mainMapExtension } = client;
interface MainSceneProps extends IUIPropsBase {}
const mainSceneProps = {
props: ['controller', 'instance', 'state']
} satisfies SetupComponentOptions<MainSceneProps>;
const MainScene = defineComponent<MainSceneProps>(props => {
const mainMapRenderer = props.state.mainMapRenderer;
const mainMapExtension = props.state.mainMapExtension;
//#region 基本定义
@ -95,19 +102,23 @@ const MainScene = defineComponent(() => {
//#region 状态更新
const updateStatus = () => {
if (!core.status || !core.status.hero || !core.status.floorId) return;
const flags = client.flags;
// TODO: flags 更新未接(当前无监听系统)
const flags = props.state.flags;
hideStatus.value = flags.getFieldValueDefaults('hideStatusBar', false);
const hero = core.status.hero;
leftStatus.atk = client.hero.attribute.getFinalAttribute('atk');
leftStatus.hp = client.hero.attribute.getFinalAttribute('hp');
leftStatus.hpmax = client.hero.attribute.getFinalAttribute('hpmax');
leftStatus.mana = client.hero.attribute.getFinalAttribute('mana');
leftStatus.manamax = client.hero.attribute.getFinalAttribute('manamax');
leftStatus.def = client.hero.attribute.getFinalAttribute('def');
leftStatus.mdef = client.hero.attribute.getFinalAttribute('mdef');
leftStatus.money = client.hero.attribute.getFinalAttribute('money');
leftStatus.exp = client.hero.attribute.getFinalAttribute('exp');
leftStatus.atk = props.state.hero.attribute.getFinalAttribute('atk');
leftStatus.hp = props.state.hero.attribute.getFinalAttribute('hp');
leftStatus.hpmax =
props.state.hero.attribute.getFinalAttribute('hpmax');
leftStatus.mana = props.state.hero.attribute.getFinalAttribute('mana');
leftStatus.manamax =
props.state.hero.attribute.getFinalAttribute('manamax');
leftStatus.def = props.state.hero.attribute.getFinalAttribute('def');
leftStatus.mdef = props.state.hero.attribute.getFinalAttribute('mdef');
leftStatus.money =
props.state.hero.attribute.getFinalAttribute('money');
leftStatus.exp = props.state.hero.attribute.getFinalAttribute('exp');
leftStatus.up = core.getNextLvUpNeed() ?? 0;
leftStatus.yellowKey = core.itemCount('yellowKey');
leftStatus.blueKey = core.itemCount('blueKey');
@ -116,6 +127,7 @@ const MainScene = defineComponent(() => {
leftStatus.pickaxe = core.itemCount('pickaxe');
leftStatus.bomb = core.itemCount('bomb');
leftStatus.centerFly = core.itemCount('centerFly');
// TODO: flags 更新未接(当前无监听系统)
leftStatus.poison = flags.getFieldValueDefaults('poison', true);
leftStatus.weak = flags.getFieldValueDefaults('weak', true);
leftStatus.curse = flags.getFieldValueDefaults('curse', true);
@ -129,6 +141,7 @@ const MainScene = defineComponent(() => {
replayStatus.played = totalList.length - toReplay.length;
replayStatus.total = totalList.length;
// TODO: flags 更新未接(当前无监听系统)
rightStatus.exampleHard = flags.getFieldValueDefaults('hard', 0);
};
@ -138,7 +151,7 @@ const MainScene = defineComponent(() => {
};
// 监听状态栏更新事件
const attributeHook = client.hero.attribute.addHook({
const attributeHook = props.state.hero.attribute.addHook({
onUpdateAttribute: () => {
updateStatus();
updateDataFallback();
@ -229,6 +242,7 @@ const MainScene = defineComponent(() => {
loc={[0, 0, STATUS_BAR_WIDTH, STATUS_BAR_HEIGHT]}
status={leftStatus}
hidden={hideStatus.value}
state={props.state}
></LeftStatusBar>
<g-line
line={[STATUS_BAR_WIDTH, 0, STATUS_BAR_WIDTH, MAIN_HEIGHT]}
@ -275,6 +289,7 @@ const MainScene = defineComponent(() => {
loc={[RIGHT_STATUS_POS, 0, STATUS_BAR_WIDTH, STATUS_BAR_HEIGHT]}
status={rightStatus}
hidden={hideStatus.value && ENABLE_RIGHT_STATUS_BAR}
state={props.state}
></RightStatusBar>
<container
loc={[0, 0, MAIN_WIDTH, MAIN_HEIGHT]}
@ -307,6 +322,6 @@ const MainScene = defineComponent(() => {
/>
</container>
);
});
}, mainSceneProps);
export const MainSceneUI = new GameUI('main-scene', MainScene);

View File

@ -12,7 +12,7 @@ import {
STATUS_BAR_WIDTH
} from '../shared';
import { DefaultProps } from '@motajs/render-vue';
import { client } from '../core';
import { IUIPropsBase } from './types';
export interface ILeftHeroStatus {
/** 楼层 id */
@ -93,14 +93,14 @@ interface KeyLikeInfo {
readonly items: KeyLikeItem[];
}
interface StatusBarProps<T> extends DefaultProps {
interface StatusBarProps<T> extends DefaultProps, IUIPropsBase {
loc: ElementLocator;
status: T;
hidden: boolean;
}
const statusBarProps = {
props: ['loc', 'status', 'hidden']
props: ['loc', 'status', 'hidden', 'state']
} satisfies SetupComponentOptions<StatusBarProps<unknown>>;
export const LeftStatusBar = defineComponent<StatusBarProps<ILeftHeroStatus>>(
@ -116,7 +116,7 @@ export const LeftStatusBar = defineComponent<StatusBarProps<ILeftHeroStatus>>(
/** 状态属性的开始纵坐标 */
const STATUS_Y = TITLE_HEIGHT + STATUS_PAD;
const materials = client.materials;
const materials = p.state.materials;
// 可以换成 materials.getImageByAlias('xxx.png') 来使用全塔属性注册的图片
const hpIcon = materials.getImageByAlias('icon-hp');
@ -450,6 +450,7 @@ export const LeftStatusBar = defineComponent<StatusBarProps<ILeftHeroStatus>>(
<MixedToolbar
loc={[0, MAIN_HEIGHT - 113, STATUS_BAR_WIDTH, 113]}
status={s.replay}
state={p.state}
/>
</container>
);

View File

@ -25,9 +25,9 @@ import { MAIN_HEIGHT, FULL_LOC, POP_BOX_WIDTH, CENTER_LOC } from '../shared';
import { openReplay, openSettings } from './settings';
import { openViewMap } from './viewmap';
import { DefaultProps } from '@motajs/render-vue';
import { client } from '../core';
import { IUIPropsBase } from './types';
interface ToolbarProps extends DefaultProps {
interface ToolbarProps extends DefaultProps, IUIPropsBase {
loc?: ElementLocator;
}
@ -36,7 +36,7 @@ type ToolbarEmits = {
};
const toolbarProps = {
props: ['loc'],
props: ['loc', 'state'],
emits: ['numpad']
} satisfies SetupComponentOptions<
ToolbarProps,
@ -74,7 +74,7 @@ export const PlayingToolbar = defineComponent<
ToolbarEmits,
keyof ToolbarEmits
>((props, { emit }) => {
const materials = client.materials;
const materials = props.state.materials;
const bookIcon = materials.getImageByAlias('icon-book');
const flyIcon = materials.getImageByAlias('icon-fly');
const toolIcon = materials.getImageByAlias('icon-toolbox');
@ -166,13 +166,13 @@ export interface ReplayingProps extends ToolbarProps {
}
const replayingProps = {
props: ['status', 'loc']
props: ['status', 'loc', 'state']
} satisfies SetupComponentOptions<ReplayingProps>;
export const ReplayingToolbar = defineComponent<ReplayingProps>(props => {
const status = props.status;
const materials = client.materials;
const materials = props.state.materials;
const bookIcon = materials.getImageByAlias('icon-book');
const saveIcon = materials.getImageByAlias('icon-save');
const font1 = Font.defaults({ size: 16 });
@ -394,10 +394,22 @@ export const MixedToolbar = defineComponent<ReplayingProps>(props => {
return () =>
inNumpad.value ? (
<NumpadToolbar loc={props.loc} onNumpad={onNumpad} />
<NumpadToolbar
loc={props.loc}
onNumpad={onNumpad}
state={props.state}
/>
) : props.status.replaying ? (
<ReplayingToolbar loc={props.loc} status={props.status} />
<ReplayingToolbar
loc={props.loc}
status={props.status}
state={props.state}
/>
) : (
<PlayingToolbar loc={props.loc} onNumpad={onNumpad} />
<PlayingToolbar
loc={props.loc}
onNumpad={onNumpad}
state={props.state}
/>
);
}, replayingProps);