Skip to content

Commit

Permalink
new: let spectators use apm gpm etc
Browse files Browse the repository at this point in the history
  • Loading branch information
Geczy committed Sep 3, 2023
1 parent dcde748 commit 120da18
Show file tree
Hide file tree
Showing 29 changed files with 432 additions and 604 deletions.
10 changes: 5 additions & 5 deletions packages/dota/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
"pickup": "{{- heroName}} picked up the aegis!",
"snatched": "{{- heroName}} snatched the aegis {{emote}}"
},
"apm_one": "Live APM: {{count}} {{emote}}",
"apm_other": "Live APM: {{count}} {{emote}}",
"apm_one": "Live APM for {{- heroName}}: {{count}} {{emote}}",
"apm_other": "Live APM for {{- heroName}}: {{count}} {{emote}}",
"averageRank": "Average rank this game",
"betaFeature": "[beta feature]",
"betaTester": "$t(betaTester_on)",
Expand Down Expand Up @@ -52,8 +52,8 @@
"dota2pt": "Need pro build ideas for {{- heroName}}? Check here {{- url}}",
"dotabod": "I'm an open source bot made by {{author}}. More info: {{- url}}",
"gameNotFound": "Game was not found",
"gpm_zero": "Live GPM: {{num}}",
"gpm_other": "Live GPM: {{num}}. {{heroKills}} from hero kills, {{creepKills}} from creep kills.",
"gpm_zero": "Live GPM for {{- heroName}}: {{num}}",
"gpm_other": "Live GPM for {{- heroName}}: {{num}}. {{heroKills}} from hero kills, {{creepKills}} from creep kills.",
"heroItems": {
"empty": "(2m delay) No items found for {{- heroName}}",
"list": "(2m delay) {{- heroName}} has: {{- itemNames}}"
Expand Down Expand Up @@ -195,5 +195,5 @@
"commit": "Server running version {{version}}, here's what's missing compared to the latest version: {{- url}}",
"unknown": "Couldn't find the last git commit, here's the repo {{- url}}"
},
"xpm": "Live XPM: {{num}}"
"xpm": "Live XPM for {{- heroName}}: {{num}}"
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { t } from 'i18next'
import { DotaEvent, DotaEventTypes } from '../../../types.js'
import { GSIHandler } from '../../GSIHandler.js'
import { getAccountsFromMatch } from '../../lib/getAccountsFromMatch.js'
import { getHeroNameById } from '../../lib/heroes.js'
import { getHeroNameOrColor } from '../../lib/heroes.js'
import { isPlayingMatch } from '../../lib/isPlayingMatch.js'
import { say } from '../../say.js'
import eventHandler from '../EventHandler.js'
Expand All @@ -16,7 +16,7 @@ eventHandler.registerEvent(`event:${DotaEventTypes.AegisDenied}`, {

const { matchPlayers } = await getAccountsFromMatch({ gsi: dotaClient.client.gsi })

const heroName = getHeroNameById(matchPlayers[event.player_id]?.heroid ?? 0, event.player_id)
const heroName = getHeroNameOrColor(matchPlayers[event.player_id]?.heroid ?? 0, event.player_id)

const chattersEnabled = getValueOrDefault(DBSettings.chatter, dotaClient.client.settings)
const {
Expand Down
14 changes: 4 additions & 10 deletions packages/dota/src/dota/events/gsi-events/event.aegis_picked_up.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,14 @@ import { t } from 'i18next'
import RedisClient from '../../../db/RedisClient.js'
import { DotaEvent, DotaEventTypes } from '../../../types.js'
import { fmtMSS } from '../../../utils/index.js'
import { logger } from '../../../utils/logger.js'
import { GSIHandler } from '../../GSIHandler.js'
import { server } from '../../index.js'
import { getAccountsFromMatch } from '../../lib/getAccountsFromMatch.js'
import { getHeroNameById } from '../../lib/heroes.js'
import { getHeroNameOrColor } from '../../lib/heroes.js'
import { isPlayingMatch } from '../../lib/isPlayingMatch.js'
import { say } from '../../say.js'
import eventHandler from '../EventHandler.js'

const redisClient = RedisClient.getInstance()

export interface AegisRes {
expireS: number
playerId: number
Expand Down Expand Up @@ -71,7 +68,7 @@ eventHandler.registerEvent(`event:${DotaEventTypes.AegisPickedUp}`, {

const { matchPlayers } = await getAccountsFromMatch({ gsi: dotaClient.client.gsi })

const heroName = getHeroNameById(matchPlayers[event.player_id]?.heroid ?? 0, event.player_id)
const heroName = getHeroNameOrColor(matchPlayers[event.player_id]?.heroid ?? 0, event.player_id)

const res = {
expireS,
Expand All @@ -82,11 +79,8 @@ eventHandler.registerEvent(`event:${DotaEventTypes.AegisPickedUp}`, {
heroName,
}

try {
void redisClient.client.json.set(`${dotaClient.getToken()}:aegis`, '$', res)
} catch (e) {
logger.error('Error in aegis json set', { e })
}
const redisClient = RedisClient.getInstance()
await redisClient.client.json.set(`${dotaClient.getToken()}:aegis`, '$', res)

const chattersEnabled = getValueOrDefault(DBSettings.chatter, dotaClient.client.settings)
const {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { t } from 'i18next'
import { DotaEvent, DotaEventTypes } from '../../../types.js'
import { GSIHandler, redisClient } from '../../GSIHandler.js'
import { getAccountsFromMatch } from '../../lib/getAccountsFromMatch.js'
import { getHeroNameById } from '../../lib/heroes.js'
import { getHeroNameOrColor } from '../../lib/heroes.js'
import { isPlayingMatch } from '../../lib/isPlayingMatch.js'
import { say } from '../../say.js'
import eventHandler from '../EventHandler.js'
Expand Down Expand Up @@ -36,7 +36,7 @@ eventHandler.registerEvent(`event:${DotaEventTypes.BountyPickup}`, {
return

clearTimeout(dotaClient.bountyTimeout)
const heroName = getHeroNameById(matchPlayers[event.player_id]?.heroid, event.player_id)
const heroName = getHeroNameOrColor(matchPlayers[event.player_id]?.heroid, event.player_id)

dotaClient.bountyHeroNames.push(heroName)

Expand Down
50 changes: 20 additions & 30 deletions packages/dota/src/dota/events/gsi-events/event.roshan_killed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,12 @@ import { t } from 'i18next'
import RedisClient from '../../../db/RedisClient.js'
import { DotaEvent, DotaEventTypes } from '../../../types.js'
import { fmtMSS } from '../../../utils/index.js'
import { logger } from '../../../utils/logger.js'
import { GSIHandler } from '../../GSIHandler.js'
import { server } from '../../index.js'
import { isPlayingMatch } from '../../lib/isPlayingMatch.js'
import { say } from '../../say.js'
import eventHandler from '../EventHandler.js'

const redisClient = RedisClient.getInstance()

export interface RoshRes {
minS: number
maxS: number
Expand Down Expand Up @@ -80,7 +77,7 @@ export function emitRoshEvent(res: RoshRes, token: string) {
}

eventHandler.registerEvent(`event:${DotaEventTypes.RoshanKilled}`, {
handler: (dotaClient: GSIHandler, event: DotaEvent) => {
handler: async (dotaClient: GSIHandler, event: DotaEvent) => {
if (!isPlayingMatch(dotaClient.client.gsi)) return
if (!dotaClient.client.stream_online) return

Expand All @@ -106,35 +103,28 @@ eventHandler.registerEvent(`event:${DotaEventTypes.RoshanKilled}`, {
roshanKilled: { enabled: chatterEnabled },
} = getValueOrDefault(DBSettings.chatters, dotaClient.client.settings)

const redisClient = RedisClient.getInstance()
// TODO: move this to a redis handler
async function redisHandler() {
const redisJson = (await redisClient.client.json.get(
`${dotaClient.getToken()}:roshan`,
)) as RoshRes | null
const count = redisJson ? Number(redisJson.count) : 0
const res = {
minS,
maxS,
minTime: fmtMSS(minTime),
maxTime: fmtMSS(maxTime),
minDate,
maxDate,
count: count + 1,
}

await redisClient.client.json.set(`${dotaClient.getToken()}:roshan`, '$', res)

if (chattersEnabled && chatterEnabled) {
say(dotaClient.client, generateRoshanMessage(res, dotaClient.client.locale))
}

emitRoshEvent(res, dotaClient.getToken())
const redisJson = (await redisClient.client.json.get(
`${dotaClient.getToken()}:roshan`,
)) as RoshRes | null
const count = redisJson ? Number(redisJson.count) : 0
const res = {
minS,
maxS,
minTime: fmtMSS(minTime),
maxTime: fmtMSS(maxTime),
minDate,
maxDate,
count: count + 1,
}

try {
void redisHandler()
} catch (e) {
logger.error('Error in redisHandler', { e })
await redisClient.client.json.set(`${dotaClient.getToken()}:roshan`, '$', res)

if (chattersEnabled && chatterEnabled) {
say(dotaClient.client, generateRoshanMessage(res, dotaClient.client.locale))
}

emitRoshEvent(res, dotaClient.getToken())
},
})
6 changes: 3 additions & 3 deletions packages/dota/src/dota/events/gsi-events/event.tip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { t } from 'i18next'
import { DotaEvent, DotaEventTypes } from '../../../types.js'
import { GSIHandler, redisClient } from '../../GSIHandler.js'
import { getAccountsFromMatch } from '../../lib/getAccountsFromMatch.js'
import { getHeroNameById } from '../../lib/heroes.js'
import { getHeroNameOrColor } from '../../lib/heroes.js'
import { isPlayingMatch } from '../../lib/isPlayingMatch.js'
import { say } from '../../say.js'
import eventHandler from '../EventHandler.js'
Expand All @@ -23,7 +23,7 @@ eventHandler.registerEvent(`event:${DotaEventTypes.Tip}`, {

const { matchPlayers } = await getAccountsFromMatch({ gsi: dotaClient.client.gsi })

const heroName = getHeroNameById(
const heroName = getHeroNameOrColor(
matchPlayers[event.sender_player_id]?.heroid ?? 0,
event.sender_player_id,
)
Expand All @@ -39,7 +39,7 @@ eventHandler.registerEvent(`event:${DotaEventTypes.Tip}`, {
}

if (event.sender_player_id === playingHeroSlot) {
const toHero = getHeroNameById(
const toHero = getHeroNameOrColor(
matchPlayers[event.receiver_player_id]?.heroid ?? 0,
event.receiver_player_id,
)
Expand Down
35 changes: 12 additions & 23 deletions packages/dota/src/dota/events/gsi-events/hero.alive.ts
Original file line number Diff line number Diff line change
@@ -1,40 +1,29 @@
import RedisClient from '../../../db/RedisClient.js'
import { logger } from '../../../utils/logger.js'
import { GSIHandler } from '../../GSIHandler.js'
import { server } from '../../index.js'
import { isPlayingMatch } from '../../lib/isPlayingMatch.js'
import eventHandler from '../EventHandler.js'

const redisClient = RedisClient.getInstance()

eventHandler.registerEvent(`hero:alive`, {
handler: async (dotaClient: GSIHandler, alive: boolean) => {
if (!dotaClient.client.stream_online) return
if (!isPlayingMatch(dotaClient.client.gsi)) return

async function handler() {
const redisJson = (await redisClient.client.json.get(`${dotaClient.getToken()}:aegis`)) as any
const redisClient = RedisClient.getInstance()
const redisJson = (await redisClient.client.json.get(`${dotaClient.getToken()}:aegis`)) as any

// Case one, we had aegis, and we die with it. Triggers on an aegis death
const playingHeroSlot = Number(
await redisClient.client.get(`${dotaClient.getToken()}:playingHeroSlot`),
)
if (!alive && redisJson?.playerId === playingHeroSlot) {
try {
void redisClient.client.json.del(`${dotaClient.getToken()}:aegis`)
} catch (e) {
logger.error('Error in hero alive', { e })
}
server.io.to(dotaClient.getToken()).emit('aegis-picked-up', {})
// Case one, we had aegis, and we die with it. Triggers on an aegis death
const playingHeroSlot = Number(
await redisClient.client.get(`${dotaClient.getToken()}:playingHeroSlot`),
)

return
}
if (!(!alive && redisJson?.playerId === playingHeroSlot)) {
return
}

try {
void handler()
} catch (e) {
logger.error('Error in hero alive', { e })
}
await redisClient.client.json.del(`${dotaClient.getToken()}:aegis`)
server.io.to(dotaClient.getToken()).emit('aegis-picked-up', {})

return
},
})
31 changes: 11 additions & 20 deletions packages/dota/src/dota/events/gsi-events/player.kill_list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,24 @@ import { server } from '../../index.js'
import { isPlayingMatch } from '../../lib/isPlayingMatch.js'
import eventHandler from '../EventHandler.js'

const redisClient = RedisClient.getInstance()

// TODO: check kill list value
eventHandler.registerEvent(`player:kill_list`, {
handler: (dotaClient: GSIHandler, kill_list: Player['kill_list']) => {
handler: async (dotaClient: GSIHandler, kill_list: Player['kill_list']) => {
if (!dotaClient.client.stream_online) return
if (!isPlayingMatch(dotaClient.client.gsi)) return

async function handler() {
const redisJson = (await redisClient.client.json.get(`${dotaClient.getToken()}:aegis`)) as any
if (typeof redisJson?.playerId !== 'number') return
const redisClient = RedisClient.getInstance()
const redisJson = (await redisClient.client.json.get(`${dotaClient.getToken()}:aegis`)) as any
if (typeof redisJson?.playerId !== 'number') return

// Remove aegis icon from the player we just killed
if (Object.values(kill_list).includes(redisJson.playerId)) {
try {
void redisClient.client.json.del(`${dotaClient.getToken()}:aegis`)
} catch (e) {
logger.error('err redisClient aegis del', { e })
}
server.io.to(dotaClient.getToken()).emit('aegis-picked-up', {})
// Remove aegis icon from the player we just killed
if (Object.values(kill_list).includes(redisJson.playerId)) {
try {
void redisClient.client.json.del(`${dotaClient.getToken()}:aegis`)
} catch (e) {
logger.error('err redisClient aegis del', { e })
}
}

try {
void handler()
} catch (e) {
logger.error('err redisClient handler aegis del', { e })
server.io.to(dotaClient.getToken()).emit('aegis-picked-up', {})
}
},
})
3 changes: 1 addition & 2 deletions packages/dota/src/dota/lib/checkTreadToggle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ import RedisClient from '../../db/RedisClient.js'
import { GSIHandler } from '../GSIHandler.js'
import { findItem } from './findItem.js'

const redisClient = RedisClient.getInstance()

export async function calculateManaSaved(dotaClient: GSIHandler) {
const { treadsData } = dotaClient
const data = dotaClient.client.gsi
Expand All @@ -18,6 +16,7 @@ export async function calculateManaSaved(dotaClient: GSIHandler) {
const didToggleToInt = maxMana - prevMaxMana === 120
const didToggleOffInt = maxMana - prevMaxMana === -120

const redisClient = RedisClient.getInstance()
if (didToggleToInt) {
treadsData.manaAtLastToggle = data.hero.mana

Expand Down
5 changes: 3 additions & 2 deletions packages/dota/src/dota/lib/getAccountsFromMatch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { delayedGames } from '@dotabod/prisma/dist/mongo/index.js'

import MongoDBSingleton from '../../steam/MongoDBSingleton.js'
import { Packet } from '../../types.js'
import { getCurrentMatchPlayers } from './getCurrentMatchPlayers.js'
import { getSpectatorPlayers } from './getSpectatorPlayers.js'

export async function getAccountsFromMatch({
gsi,
Expand All @@ -16,8 +16,9 @@ export async function getAccountsFromMatch({
accountid: number
}[]
} = {}) {
const players = searchPlayers?.length ? searchPlayers : getCurrentMatchPlayers(gsi)
const players = searchPlayers?.length ? searchPlayers : getSpectatorPlayers(gsi)

// spectator account ids
if (Array.isArray(players) && players.length) {
return {
matchPlayers: players,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Packet } from '../../types.js'

export function getCurrentMatchPlayers(gsi?: Packet) {
export function getSpectatorPlayers(gsi?: Packet) {
let matchPlayers: { heroid: number; accountid: number; selected: boolean }[] = []
if (gsi?.hero?.team2 && gsi.hero.team3) {
matchPlayers = [
Expand Down
2 changes: 1 addition & 1 deletion packages/dota/src/dota/lib/heroes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -654,7 +654,7 @@ export const translatedColor = (color: string, lng: string) => {
}

export const heroColors = 'Blue,Teal,Purple,Yellow,Orange,Pink,Olive,Cyan,Green,Brown'.split(',')
export function getHeroNameById(id: number, index?: number) {
export function getHeroNameOrColor(id: number, index?: number) {
if (!id && typeof index === 'number') return heroColors[index]

const name = getHeroById(id)?.localized_name
Expand Down
3 changes: 1 addition & 2 deletions packages/dota/src/dota/lib/ranks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import { logger } from '../../utils/logger.js'
import { server } from '../index.js'
import { leaderRanks, ranks } from './consts.js'

const redisClient = RedisClient.getInstance()

export function rankTierToMmr(rankTier: string | number) {
if (!Number(rankTier)) {
return 0
Expand Down Expand Up @@ -51,6 +49,7 @@ export async function lookupLeaderRank(
const cacheKey = `${steam32Id}:medal`
let result

const redisClient = RedisClient.getInstance()
// Try to get the cached result first
const medalCache = await redisClient.client.json.get(cacheKey)
if (medalCache) {
Expand Down
Loading

0 comments on commit 120da18

Please sign in to comment.