From 2240140136b9dfc0faeb1d29edf037609f9e8c9c Mon Sep 17 00:00:00 2001 From: mat Date: Sat, 30 Apr 2022 00:20:49 -0500 Subject: revamp skills api --- src/cleaners/skyblock/member.ts | 14 +++++---- src/cleaners/skyblock/skills.ts | 66 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 67 insertions(+), 13 deletions(-) (limited to 'src/cleaners/skyblock') diff --git a/src/cleaners/skyblock/member.ts b/src/cleaners/skyblock/member.ts index 57462ed..6b2f452 100644 --- a/src/cleaners/skyblock/member.ts +++ b/src/cleaners/skyblock/member.ts @@ -10,7 +10,7 @@ import { CleanMinion, cleanMinions } from './minions.js' import { cleanSlayers, SlayerData } from './slayers.js' import { AccountCustomization } from '../../database.js' import { cleanVisitedZones, Zone } from './zones.js' -import { cleanSkills, Skill } from './skills.js' +import { cleanSkills, Skills } from './skills.js' import * as cached from '../../hypixelCached.js' import typedHypixelApi from 'typed-hypixel-api' import { cleanPets, PetsData } from './pets.js' @@ -37,7 +37,7 @@ export interface CleanMember extends CleanBasicMember { fairySouls: FairySouls inventories?: Inventories objectives: Objective[] - skills: Skill[] + skills: Skills zones: Zone[] collections: Collection[] slayers: SlayerData @@ -50,7 +50,7 @@ export interface CleanMember extends CleanBasicMember { } export async function cleanSkyBlockProfileMemberResponseBasic(member: typedHypixelApi.SkyBlockProfileMember & { uuid: string }): Promise { - const player = await cached.fetchPlayer(member.uuid) + const player = await cached.fetchPlayer(member.uuid, false) if (!player) return null return { uuid: member.uuid, @@ -64,7 +64,7 @@ export async function cleanSkyBlockProfileMemberResponseBasic(member: typedHypix /** Cleans up a member (from skyblock/profile) */ export async function cleanSkyBlockProfileMemberResponse(member: typedHypixelApi.SkyBlockProfileMember & { uuid: string }, profileId?: string, included: Included[] | undefined = undefined): Promise { const inventoriesIncluded = included === undefined || included.includes('inventories') - const player = await cached.fetchPlayer(member.uuid) + const player = await cached.fetchPlayer(member.uuid, true) if (!player) return null const fairySouls = await cleanFairySouls(member) @@ -74,7 +74,7 @@ export async function cleanSkyBlockProfileMemberResponse(member: typedHypixelApi const coopInvitationPromise = cleanCoopInvitation(member, member.uuid) const minionsPromise = cleanMinions(member) - const skillsPromise = cleanSkills(member) + const skillsPromise = cleanSkills(member, player) const zonesPromise = cleanVisitedZones(member) const petsPromise = cleanPets(member) const harpPromise = cleanHarp(member) @@ -100,7 +100,9 @@ export async function cleanSkyBlockProfileMemberResponse(member: typedHypixelApi fairySouls: fairySouls, inventories: inventoriesPromise ? await inventoriesPromise : undefined, objectives: cleanObjectives(member), + skills: await skillsPromise, + zones: await zonesPromise, collections: cleanCollections(member), slayers: cleanSlayers(member), @@ -126,7 +128,7 @@ export interface CleanMemberProfilePlayer extends CleanPlayer { fairySouls: FairySouls inventories?: Inventories objectives: Objective[] - skills: Skill[] + skills: Skills zones: Zone[] collections: Collection[] slayers: SlayerData diff --git a/src/cleaners/skyblock/skills.ts b/src/cleaners/skyblock/skills.ts index d035a96..8d0f16d 100644 --- a/src/cleaners/skyblock/skills.ts +++ b/src/cleaners/skyblock/skills.ts @@ -2,9 +2,10 @@ import typedHypixelApi from 'typed-hypixel-api' import { fetchSkills } from '../../constants.js' import { levelFromXpTable } from '../../util.js' import * as constants from '../../constants.js' +import { CleanFullPlayer } from '../player.js' export interface Skill { - name: string + id: string xp: number level: number @@ -14,6 +15,16 @@ export interface Skill { levelXpRequired: number } +export interface Skills { + list: Skill[] + /** + * Whether the player has their skills API enabled. If this is off, that + * means the data doesn't include xp and is per-player. You should show a + * warning to the user. + */ + apiEnabled: boolean +} + // the highest level you can have in each skill // numbers taken from https://hypixel-skyblock.fandom.com/wiki/Skills const skillsMaxLevel: { [key: string]: number } = { @@ -137,7 +148,39 @@ export function levelForSkillXp(xp: number, maxLevel: number) { return levelFromXpTable(xp, xpTable) } -export async function cleanSkills(data: typedHypixelApi.SkyBlockProfileMember): Promise { +function skillFromLevel(id: string, level: number): Skill { + const maxLevel = skillsMaxLevel[id] ?? skillsDefaultMaxLevel + const xpTable = (maxLevel <= 25 ? skillXpTableEasier : skillXpTable).slice(0, maxLevel) + const xp = level > 0 ? xpTable[level - 1] ?? 0 : 0 + + return { + id, + level, + levelXp: 0, + levelXpRequired: xpTable[level], + maxLevel: maxLevel, + xp + } +} + +function skillsFromSkyBlockAchievements(achievements: CleanFullPlayer['achievements']['skyblock']): Skills { + return { + apiEnabled: false, + list: [ + skillFromLevel('fishing', achievements['angler']), + skillFromLevel('enchanting', achievements['augmentation']), + skillFromLevel('combat', achievements['combat']), + skillFromLevel('alchemy', achievements['concoctor']), + skillFromLevel('taming', achievements['domesticator']), + skillFromLevel('dungeoneering', achievements['dungeoneer']), + skillFromLevel('mining', achievements['excavator']), + skillFromLevel('foraging', achievements['gatherer']), + skillFromLevel('farming', achievements['harvester']) + ] + } +} + +export async function cleanSkills(data: typedHypixelApi.SkyBlockProfileMember, player: CleanFullPlayer): Promise { const allSkillNames = await fetchSkills() const skills: Skill[] = [] @@ -168,7 +211,7 @@ export async function cleanSkills(data: typedHypixelApi.SkyBlockProfileMember): const skillLevelXpRequired = xpTable[skillLevel] - previousLevelXp skills.push({ - name: skillName, + id: skillName, xp: skillXp, level: skillLevel, maxLevel: skillMaxLevel, @@ -178,16 +221,22 @@ export async function cleanSkills(data: typedHypixelApi.SkyBlockProfileMember): } } + // if the player has no skills but has kills, we can assume they have the skills api off + // (we check kills to know whether the profile is actually used, this is kinda arbitrary) + if (skills.length === 0 && Object.keys(data.stats).includes('kills')) { + return skillsFromSkyBlockAchievements(player.achievements.skyblock) + } + constants.addSkills(skillNamesFound) // add missing skills - const missingSkillNames = allSkillNames.filter(skillName => !skills.some(skill => skill.name === skillName)) + const missingSkillNames = allSkillNames.filter(skillName => !skills.some(skill => skill.id === skillName)) for (const skillName of missingSkillNames) { const skillMaxLevel = skillsMaxLevel[skillName] ?? skillsDefaultMaxLevel const xpTable = (skillMaxLevel <= 25 ? skillXpTableEasier : skillXpTable).slice(0, skillMaxLevel) skills.push({ - name: skillName, + id: skillName, xp: 0, level: 0, maxLevel: skillMaxLevel, @@ -197,7 +246,10 @@ export async function cleanSkills(data: typedHypixelApi.SkyBlockProfileMember): } // sort skills by name - skills.sort((a, b) => a.name.localeCompare(b.name)) + skills.sort((a, b) => a.id.localeCompare(b.id)) - return skills + return { + apiEnabled: true, + list: skills, + } } -- cgit