Skip to content

Commit

Permalink
fix(adventure): use timer for phase lock
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed Jun 21, 2021
1 parent b527e0e commit af73653
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 19 deletions.
2 changes: 1 addition & 1 deletion packages/plugin-adventure/src/luck.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ namespace Luck {
.usage(showLotteryUsage)
.action(async ({ session, options }) => {
const { user } = session
if (Phase.metaMap[session.userId]) return '当前处于剧情模式中,无法抽卡。'
if (Phase.userSessionMap[session.user.id]) return '当前处于剧情模式中,无法抽卡。'
if (user.progress) return '检测到你有未完成的剧情,请尝试输入“继续当前剧情”。'

if (checkTimer('lottery', user, minInterval * 60 * 1000)) {
Expand Down
44 changes: 26 additions & 18 deletions packages/plugin-adventure/src/phase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,24 +38,24 @@ export namespace Phase {
export const phaseMap: Record<string, Adventurer.Infer<Phase>> = { '': mainPhase }
export const salePlots: Record<string, ReadonlyUser.Infer<string, Shopper.Field>> = {}

export const metaMap: Record<number, Session<User.Field>> = {}
export const groupStates: Record<number, number> = {}
export const userSessionMap: Record<string, [Session<Adventurer.Field>, NodeJS.Timer]> = {}
export const channelUserMap: Record<string, [string, NodeJS.Timer]> = {}
export const activeUsers = new Set<string>()

export function getBadEndingCount(user: Pick<User, 'endings'>) {
return Object.keys(user.endings).filter(id => badEndings.has(id)).length
}

export function checkStates(session: Session<'id'>, active = false) {
// check group state
const groupState = groupStates[session.groupId]
if (session.subtype === 'group' && groupState && groupState !== session.userId) {
// check channel state
const userState = channelUserMap[session.cid]
if (session.subtype === 'group' && userState && userState[0] !== session.user.id) {
return '同一个群内只能同时进行一处剧情,请尝试私聊或稍后重试。'
}

// check user state
const _meta = metaMap[session.userId]
if (_meta && !(active && _meta.channelId === session.channelId && activeUsers.has(session.user.id))) {
const sessionState = userSessionMap[session.user.id]
if (sessionState && !(active && sessionState[0].cid === session.cid && activeUsers.has(session.user.id))) {
return '同一用户只能同时进行一处剧情。'
}
}
Expand Down Expand Up @@ -344,20 +344,28 @@ export namespace Phase {
logger.debug('%s phase finish', session.userId)
}

export async function start(session: Session<Adventurer.Field>) {
metaMap[session.userId] = session
if (session.subtype === 'group') {
groupStates[session.groupId] = session.userId
function setState<V>(map: Record<string, [V, NodeJS.Timer]>, key: string, value: V) {
const current = map[key]
if (current) clearTimeout(current[1])
const timer = setTimeout(() => this.map.delete(key), Time.hour)
const entry = map[key] = [value, timer]
return () => {
if (map[key] !== entry) return
clearTimeout(entry[1])
delete map[key]
}
}

export async function start(session: Session<Adventurer.Field>) {
const disposeUser = setState(userSessionMap, session.user.id, session)
const disposeChannel = setState(channelUserMap, session.cid, session.user.id)
try {
await plot(session)
} catch (error) {
new Logger('cosmos').warn(error)
}
delete metaMap[session.userId]
if (session.subtype === 'group') {
delete groupStates[session.groupId]
}
disposeUser()
disposeChannel()
}

function findEndings(names: string[]) {
Expand Down Expand Up @@ -482,7 +490,7 @@ export namespace Phase {
ctx.command('adv/skip [-- command:text]', '跳过剧情')
.shortcut('跳过剧情')
.shortcut('跳过当前剧情')
.userFields(['phases', 'progress'])
.userFields(['phases', 'progress', 'id'])
.useRest()
.usage('这个指令用于跳过剧情的主体部分,并不会略去结算文字。当进入下一段剧情时需要再次跳过。未读过的剧情无法跳过。')
.action(async ({ session, next, options }) => {
Expand All @@ -493,7 +501,7 @@ export namespace Phase {
return
}
if (session._skipAll) return
if (!(session = metaMap[session.userId])) return
if (!(session = userSessionMap[session.user.id]?.[0])) return
if (session._skipCurrent || !session._canSkip) return
session.cancelQueued()
session._skipCurrent = true
Expand Down Expand Up @@ -558,7 +566,7 @@ export namespace Phase {
return start(session)
} else {
if (!item || session._skipAll) return
const next = !metaMap[session.userId] && getValue(mainPhase.items[item], user)
const next = !userSessionMap[session.user.id] && getValue(mainPhase.items[item], user)
if (next) {
return `物品“${item}”当前不可用,请尝试输入“继续当前剧情”。`
} else {
Expand Down

0 comments on commit af73653

Please sign in to comment.