fix(client): fail fast on boot/frontend fallbacks (P4)
- MapService load failure is no longer swallowed. - Character creation fails on unknown selected class instead of ?? 1. - No prefilled 'Wanderer'/'password' credentials; empty account name is an error; unknown MCP class id throws instead of ?? 'so'. - CommandMapper no longer sends BeltUse with fabricated itemId slot+1.
This commit is contained in:
parent
7db8c3c9b8
commit
3d20dc9c77
|
|
@ -253,8 +253,9 @@ export function createInitialFlowState(initialRoster: RosterCharacter[] = []): B
|
||||||
stageTicks: 0,
|
stageTicks: 0,
|
||||||
globalTick: 0,
|
globalTick: 0,
|
||||||
|
|
||||||
accountName: 'Wanderer',
|
// No prefilled credentials: the user (or a configured bot) must type them.
|
||||||
accountPassword: 'password',
|
accountName: '',
|
||||||
|
accountPassword: '',
|
||||||
loginError: null,
|
loginError: null,
|
||||||
|
|
||||||
campfireClasses,
|
campfireClasses,
|
||||||
|
|
@ -338,7 +339,8 @@ export function cancelConnecting(state: BnetFlowState): void {
|
||||||
export function submitBattleNetLogin(state: BnetFlowState): boolean {
|
export function submitBattleNetLogin(state: BnetFlowState): boolean {
|
||||||
if (state.stage !== 'bnet_login') return false
|
if (state.stage !== 'bnet_login') return false
|
||||||
if (!state.accountName.trim()) {
|
if (!state.accountName.trim()) {
|
||||||
state.accountName = 'Wanderer'
|
state.loginError = 'Account name required'
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
state.loginError = null
|
state.loginError = null
|
||||||
state.stageTicks = 0
|
state.stageTicks = 0
|
||||||
|
|
@ -589,7 +591,8 @@ export function charSummaryToRosterCharacter(summary: {
|
||||||
readonly hardcore: boolean
|
readonly hardcore: boolean
|
||||||
readonly ladder: boolean
|
readonly ladder: boolean
|
||||||
}): RosterCharacter {
|
}): RosterCharacter {
|
||||||
const classId = CHAR_CLASS_ID_TO_CAMPFIRE[summary.charClass] ?? 'so'
|
const classId = CHAR_CLASS_ID_TO_CAMPFIRE[summary.charClass]
|
||||||
|
if (!classId) throw new Error(`MCP character "${summary.name}" has unknown class id ${summary.charClass}`)
|
||||||
const spec = CAMPFIRE_CLASS_SPECS[classId]
|
const spec = CAMPFIRE_CLASS_SPECS[classId]
|
||||||
return {
|
return {
|
||||||
id: `${spec.heroToken}-${summary.name}`,
|
id: `${spec.heroToken}-${summary.name}`,
|
||||||
|
|
|
||||||
|
|
@ -634,18 +634,9 @@ export class CommandMapper {
|
||||||
if (event.key === '1' || event.key === '2' || event.key === '3' || event.key === '4') {
|
if (event.key === '1' || event.key === '2' || event.key === '3' || event.key === '4') {
|
||||||
const slotIndex = Number(event.key) - 1
|
const slotIndex = Number(event.key) - 1
|
||||||
event.preventDefault?.()
|
event.preventDefault?.()
|
||||||
if (this.hudModel) {
|
// BeltUse needs the real server item id of the potion, which only HudModel (ClientWorld) knows.
|
||||||
this.hudModel.useBeltSlot(slotIndex, Boolean(event.shiftKey))
|
if (!this.hudModel) return false
|
||||||
} else {
|
this.hudModel.useBeltSlot(slotIndex, Boolean(event.shiftKey))
|
||||||
this.dispatchRateLimited(
|
|
||||||
{
|
|
||||||
type: 'BeltUse',
|
|
||||||
itemId: slotIndex + 1,
|
|
||||||
shift: Boolean(event.shiftKey),
|
|
||||||
},
|
|
||||||
nowMs,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -193,11 +193,12 @@ async function bootPlayApp(): Promise<PlayAppController> {
|
||||||
})
|
})
|
||||||
await hudManager.load('/ui')
|
await hudManager.load('/ui')
|
||||||
|
|
||||||
let mapService: MapService | null = null
|
// Fail fast: without the packed act tiles there is no 1.13c map (automap, collision, picking).
|
||||||
|
let mapService: MapService
|
||||||
try {
|
try {
|
||||||
mapService = await MapService.fromPackedUrl('/act-packs/tiles')
|
mapService = await MapService.fromPackedUrl('/act-packs/tiles')
|
||||||
} catch {
|
} catch (err) {
|
||||||
mapService = null
|
throw new Error(`MapService: failed to load /act-packs/tiles: ${err instanceof Error ? err.message : String(err)}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kick off asynchronous GPU atlas preloading for WebGL2 world rendering
|
// Kick off asynchronous GPU atlas preloading for WebGL2 world rendering
|
||||||
|
|
@ -468,9 +469,11 @@ async function bootPlayApp(): Promise<PlayAppController> {
|
||||||
dz: 5,
|
dz: 5,
|
||||||
as: 6,
|
as: 6,
|
||||||
}
|
}
|
||||||
|
const classId = st.selectedClass === null ? undefined : classMap[st.selectedClass]
|
||||||
|
if (classId === undefined) throw new Error(`Unknown selected class ${String(st.selectedClass)}`)
|
||||||
const chars = await session.createCharacter({
|
const chars = await session.createCharacter({
|
||||||
name,
|
name,
|
||||||
classId: classMap[st.selectedClass] ?? 1,
|
classId,
|
||||||
hardcore: st.isHardcore,
|
hardcore: st.isHardcore,
|
||||||
expansion: st.isExpansion,
|
expansion: st.isExpansion,
|
||||||
ladder: st.isLadder,
|
ladder: st.isLadder,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue