From f468476627658d4bb5dd10b9bd553ba95db57322 Mon Sep 17 00:00:00 2001 From: Kyle Kemp Date: Wed, 20 Sep 2023 11:40:48 -0500 Subject: [PATCH] fix(api): rework lots of internal getters to guarantee existence rather than check in every subfunction --- .../achievements/achievements.service.ts | 11 ++- .../modules/aggregator/aggregator.service.ts | 2 - server/src/modules/content/content.service.ts | 97 +++++++++++++------ .../src/modules/crafting/crafting.service.ts | 13 ++- .../discoveries/discoveries.controller.ts | 11 +-- .../discoveries/discoveries.service.ts | 41 +++----- server/src/modules/fight/fight.service.ts | 17 +--- .../src/modules/gameplay/gameplay.service.ts | 24 +---- server/src/modules/gameplay/item.service.ts | 38 +------- server/src/modules/gameplay/npc.service.ts | 9 -- server/src/modules/gameplay/travel.service.ts | 17 +--- server/src/modules/gameplay/wave.service.ts | 7 -- .../modules/inventory/inventory.service.ts | 37 ++++--- .../modules/lottery/buyinlottery.service.ts | 2 - .../modules/lottery/dailylottery.service.ts | 2 - .../src/modules/lottery/lottery.controller.ts | 2 +- server/src/modules/market/market.service.ts | 25 ----- server/src/modules/player/npc.service.ts | 4 +- .../src/modules/player/player.controller.ts | 22 +---- server/src/modules/player/player.service.ts | 32 +++--- server/src/modules/stats/stats.service.ts | 18 ++-- 21 files changed, 158 insertions(+), 273 deletions(-) diff --git a/server/src/modules/achievements/achievements.service.ts b/server/src/modules/achievements/achievements.service.ts index 6f342f4..c30fd8a 100644 --- a/server/src/modules/achievements/achievements.service.ts +++ b/server/src/modules/achievements/achievements.service.ts @@ -13,7 +13,16 @@ export class AchievementsService { private readonly achievements: EntityRepository, ) {} - async getAchievementsForUser( + async getAchievementsForUser(userId: string): Promise { + const achievements = await this.getOrCreateAchievementsForUser(userId); + if (!achievements) { + throw new BadRequestException(`achievements id ${userId} not found.`); + } + + return achievements; + } + + private async getOrCreateAchievementsForUser( userId: string, ): Promise { const dbAchievements = await this.achievements.findOne({ userId }); diff --git a/server/src/modules/aggregator/aggregator.service.ts b/server/src/modules/aggregator/aggregator.service.ts index 2094fd5..8b19eae 100644 --- a/server/src/modules/aggregator/aggregator.service.ts +++ b/server/src/modules/aggregator/aggregator.service.ts @@ -115,7 +115,6 @@ export class AggregatorService { }): Promise { const { userId, amount } = event; const player = await this.playerService.getPlayerForUser(userId); - if (!player) return; const playerPatches = await getPatchesAfterPropChanges( player, @@ -140,7 +139,6 @@ export class AggregatorService { const { userId, amount } = event; const player = await this.playerService.getPlayerForUser(userId); - if (!player) return; const playerPatches = await getPatchesAfterPropChanges( player, diff --git a/server/src/modules/content/content.service.ts b/server/src/modules/content/content.service.ts index edc0822..305ca09 100644 --- a/server/src/modules/content/content.service.ts +++ b/server/src/modules/content/content.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@nestjs/common'; +import { Injectable, NotFoundException } from '@nestjs/common'; import { ICollectible, @@ -112,78 +112,115 @@ export class ContentService { } public allLocations(): ILocation[] { - return Object.values(this.locations); + return Object.values(this.locations ?? {}); } - public getLocation(location: string): ILocation | undefined { - return this.locations[location]; + public getLocation(location: string): ILocation { + const locationRef = this.locations[location]; + if (!location) + throw new NotFoundException(`Location ${location} not found!`); + + return locationRef; } public allJobs(): IJob[] { - return Object.values(this.jobs); + return Object.values(this.jobs ?? {}); } - public getJob(job: string): IJob | undefined { - return this.jobs[job]; + public getJob(job: string): IJob { + const jobRef = this.jobs[job]; + if (!jobRef) throw new NotFoundException(`Job ${job} not found!`); + + return jobRef; } public allCollectibles(): ICollectible[] { - return Object.values(this.collectibles); + return Object.values(this.collectibles ?? {}); } public allResources(): IResource[] { - return Object.values(this.resources); + return Object.values(this.resources ?? {}); } - public getResource(resourceId: string): IResource | undefined { - return this.resources[resourceId]; + public getResource(resourceId: string): IResource { + const resourceRef = this.resources[resourceId]; + if (!resourceRef) + throw new NotFoundException(`Resource ${resourceId} not found!`); + + return resourceRef; } - public getCollectible(collectibleId: string): ICollectible | undefined { - return this.collectibles[collectibleId]; + public getCollectible(collectibleId: string): ICollectible { + const collectibleRef = this.collectibles[collectibleId]; + if (!collectibleRef) + throw new NotFoundException(`Collectible ${collectibleId} not found!`); + + return collectibleRef; } public allEquipment(): IEquipment[] { - return Object.values(this.equipment); + return Object.values(this.equipment ?? {}); } - public getEquipment(equipmentId: string): IEquipment | undefined { - return this.equipment[equipmentId]; + public getEquipment(equipmentId: string): IEquipment { + const equipmentRef = this.equipment[equipmentId]; + if (!equipmentRef) + throw new NotFoundException(`Equipment ${equipmentId} not found!`); + + return equipmentRef; } - public getItem(item: string): IItem | undefined { + public getItem(item: string): IItem { return this.equipment[item] || this.collectibles[item]; } - public getRecipe(item: string): IRecipe | undefined { - return this.recipes[item]; + public getRecipe(item: string): IRecipe { + const recipeRef = this.recipes[item]; + if (!recipeRef) throw new NotFoundException(`Recipe ${item} not found!`); + + return recipeRef; } public allFormations(): IMonsterFormation[] { - return Object.values(this.formations); + return Object.values(this.formations ?? {}); } - public getFormation(formation: string): IMonsterFormation | undefined { - return this.formations[formation]; + public getFormation(formation: string): IMonsterFormation { + const formationRef = this.formations[formation]; + if (!formationRef) + throw new NotFoundException(`Formation ${formation} not found!`); + + return formationRef; } - public getMonster(monster: string): IMonster | undefined { - return this.monsters[monster]; + public getMonster(monster: string): IMonster { + const monsterRef = this.monsters[monster]; + if (!monsterRef) + throw new NotFoundException(`Monster ${monster} not found!`); + + return monsterRef; } public allAbilities(): ICombatAbility[] { - return Object.values(this.abilities); + return Object.values(this.abilities ?? {}); } - public getAbility(ability: string): ICombatAbility | undefined { - return this.abilities[ability]; + public getAbility(ability: string): ICombatAbility { + const abilityRef = this.abilities[ability]; + if (!abilityRef) + throw new NotFoundException(`Ability ${ability} not found!`); + + return abilityRef; } public allNPCs(): ILocationNPC[] { - return Object.values(this.npcs); + return Object.values(this.npcs ?? {}); } - public getNPC(npc: string): ILocationNPC | undefined { - return this.npcs[npc]; + public getNPC(npc: string): ILocationNPC { + const npcRef = this.npcs[npc]; + if (!npcRef) throw new NotFoundException(`NPC ${npc} not found!`); + + return npcRef; } } diff --git a/server/src/modules/crafting/crafting.service.ts b/server/src/modules/crafting/crafting.service.ts index 5511001..f1ec9de 100644 --- a/server/src/modules/crafting/crafting.service.ts +++ b/server/src/modules/crafting/crafting.service.ts @@ -14,7 +14,18 @@ export class CraftingService { private readonly crafting: EntityRepository, ) {} - async getCraftingForUser(userId: string): Promise { + async getCraftingForUser(userId: string): Promise { + const crafting = await this.getOrCreateCraftingForUser(userId); + if (!crafting) { + throw new BadRequestException(`crafting id ${userId} not found.`); + } + + return crafting; + } + + private async getOrCreateCraftingForUser( + userId: string, + ): Promise { const dbCrafting = await this.crafting.findOne({ userId }); if (!dbCrafting) { return await this.createCraftingForUser(userId); diff --git a/server/src/modules/discoveries/discoveries.controller.ts b/server/src/modules/discoveries/discoveries.controller.ts index 864e23f..1faea09 100644 --- a/server/src/modules/discoveries/discoveries.controller.ts +++ b/server/src/modules/discoveries/discoveries.controller.ts @@ -1,13 +1,6 @@ import { UserResponse } from '@interfaces'; import { DiscoveriesService } from '@modules/discoveries/discoveries.service'; -import { - Body, - Controller, - Get, - NotFoundException, - Post, - UseGuards, -} from '@nestjs/common'; +import { Body, Controller, Get, Post, UseGuards } from '@nestjs/common'; import { ApiBearerAuth, ApiOperation } from '@nestjs/swagger'; import { User } from '../../utils/user.decorator'; import { JwtAuthGuard } from '../auth/jwt.guard'; @@ -24,8 +17,6 @@ export class DiscoveriesController { const discoveries = await this.discoveriesService.getDiscoveriesForUser( user.userId, ); - if (!discoveries) - throw new NotFoundException(`User ${user.userId} not found`); return { discoveries }; } diff --git a/server/src/modules/discoveries/discoveries.service.ts b/server/src/modules/discoveries/discoveries.service.ts index 2b0354f..03f32dc 100644 --- a/server/src/modules/discoveries/discoveries.service.ts +++ b/server/src/modules/discoveries/discoveries.service.ts @@ -30,7 +30,16 @@ export class DiscoveriesService { private readonly events: EventEmitter2, ) {} - async getDiscoveriesForUser( + async getDiscoveriesForUser(userId: string): Promise { + const discoveries = await this.getOrCreateDiscoveriesForUser(userId); + if (!discoveries) { + throw new BadRequestException(`discoveries id ${userId} not found.`); + } + + return discoveries; + } + + private async getOrCreateDiscoveriesForUser( userId: string, ): Promise { const dbDiscoveries = await this.discoveries.findOne({ userId }); @@ -117,20 +126,13 @@ export class DiscoveriesService { instanceId: string, ): Promise { const discoveries = await this.getDiscoveriesForUser(userId); - if (!discoveries) throw new NotFoundException(`User ${userId} not found`); const item = await this.inventoryService.getInventoryItemForUser( userId, instanceId, ); - if (!item) - throw new NotFoundException(`Collectible item ${instanceId} not found`); - const itemDefinition = await this.contentService.getCollectible( - item.itemId, - ); - if (!itemDefinition) - throw new NotFoundException(`Item definition ${item.itemId} not found`); + const itemDefinition = this.contentService.getCollectible(item.itemId); await this.inventoryService.removeInventoryItemForUser(userId, instanceId); @@ -168,16 +170,13 @@ export class DiscoveriesService { instanceId: string, ): Promise { const discoveries = await this.getDiscoveriesForUser(userId); - if (!discoveries) throw new NotFoundException(`User ${userId} not found`); const item = await this.inventoryService.getInventoryItemForUser( userId, instanceId, ); - if (!item) - throw new NotFoundException(`Equipment item ${instanceId} not found`); - const itemDefinition = await this.contentService.getEquipment(item.itemId); + const itemDefinition = this.contentService.getEquipment(item.itemId); if (!itemDefinition) { await this.inventoryService.removeInventoryItemForUser( userId, @@ -221,10 +220,8 @@ export class DiscoveriesService { async discoverMonster(userId: string, monsterId: string): Promise { const discoveries = await this.getDiscoveriesForUser(userId); - if (!discoveries) throw new NotFoundException(`User ${userId} not found`); - const monster = await this.contentService.getMonster(monsterId); - if (!monster) throw new NotFoundException(`Monster ${monsterId} not found`); + const monster = this.contentService.getMonster(monsterId); this.logger.verbose(`Discovered monster ${monster.name} for ${userId}.`); @@ -238,8 +235,6 @@ export class DiscoveriesService { async claimUniqueCollectibleReward(userId: string): Promise { const discoveries = await this.getDiscoveriesForUser(userId); - if (!discoveries) - throw new NotFoundException(`Discoveries ${userId} not found`); const totalTimesClaimed = discoveries.uniqueCollectibleClaims ?? 0; const totalCollectiblesFound = sum(Object.keys(discoveries.collectibles)); @@ -279,8 +274,6 @@ export class DiscoveriesService { async claimTotalCollectibleReward(userId: string): Promise { const discoveries = await this.getDiscoveriesForUser(userId); - if (!discoveries) - throw new NotFoundException(`Discoveries ${userId} not found`); const totalTimesClaimed = discoveries.totalCollectibleClaims ?? 0; const totalCollectiblesFound = sum(Object.values(discoveries.collectibles)); @@ -320,8 +313,6 @@ export class DiscoveriesService { async claimUniqueEquipmentReward(userId: string): Promise { const discoveries = await this.getDiscoveriesForUser(userId); - if (!discoveries) - throw new NotFoundException(`Discoveries ${userId} not found`); const totalTimesClaimed = discoveries.uniqueEquipmentClaims ?? 0; const totalItemsFound = sum(Object.keys(discoveries.items)); @@ -361,8 +352,6 @@ export class DiscoveriesService { async claimTotalEquipmentReward(userId: string): Promise { const discoveries = await this.getDiscoveriesForUser(userId); - if (!discoveries) - throw new NotFoundException(`Discoveries ${userId} not found`); const totalTimesClaimed = discoveries.totalEquipmentClaims ?? 0; const totalItemsFound = sum(Object.values(discoveries.items)); @@ -402,8 +391,6 @@ export class DiscoveriesService { async claimUniqueMonsterReward(userId: string): Promise { const discoveries = await this.getDiscoveriesForUser(userId); - if (!discoveries) - throw new NotFoundException(`Discoveries ${userId} not found`); const totalTimesClaimed = discoveries.uniqueMonsterClaims ?? 0; const totalItemsFound = sum(Object.keys(discoveries.monsters)); @@ -443,8 +430,6 @@ export class DiscoveriesService { async claimTotalMonsterReward(userId: string): Promise { const discoveries = await this.getDiscoveriesForUser(userId); - if (!discoveries) - throw new NotFoundException(`Discoveries ${userId} not found`); const totalTimesClaimed = discoveries.totalMonsterClaims ?? 0; const totalItemsFound = sum(Object.values(discoveries.monsters)); diff --git a/server/src/modules/fight/fight.service.ts b/server/src/modules/fight/fight.service.ts index 5ca6f72..e2a3593 100644 --- a/server/src/modules/fight/fight.service.ts +++ b/server/src/modules/fight/fight.service.ts @@ -136,8 +136,6 @@ export class FightService { const inventory = await this.inventoryService.getInventoryForUser( player.userId, ); - if (!inventory) - throw new NotFoundException(`Inventory ${player.userId} not found`); const totalStats = await this.playerService.getTotalStats(player); const totalResistances = await this.playerService.getTotalResistances( @@ -276,8 +274,6 @@ export class FightService { await Promise.all( fight.involvedPlayers.map(async (playerId) => { const player = await this.playerService.getPlayerForUser(playerId); - if (!player) - throw new NotFoundException(`Player ${playerId} not found`); if (player.action?.action === 'fight') { this.playerService.setPlayerAction(player, undefined); @@ -360,9 +356,7 @@ export class FightService { random(0, 100) <= randomDropPossibility.chance ) { randomDrop = this.contentService.getItem(randomDropPossibility.item); - if (randomDrop) { - addStatusMessage(fight, 'Fight', `You found "${randomDrop.name}"!`); - } + addStatusMessage(fight, 'Fight', `You found "${randomDrop.name}"!`); } if (isWin && fight.defenders.length > 0) { @@ -381,14 +375,10 @@ export class FightService { await Promise.all( fight.involvedPlayers.map(async (playerId) => { const player = await this.playerService.getPlayerForUser(playerId); - if (!player) - throw new NotFoundException(`Player ${playerId} not found`); const discoveries = await this.discoveriesService.getDiscoveriesForUser( player.userId, ); - if (!discoveries) - throw new NotFoundException(`Discoveries ${playerId} not found`); if (fight.defenders.length > 0 && fight.attackers.length > 0) { await this.statsService.incrementStat( @@ -563,7 +553,6 @@ export class FightService { throw new BadRequestException('It is not your turn.'); const action = this.contentService.getAbility(actionId); - if (!action) throw new NotFoundException(`Action ${actionId} not found`); const character = getCharacterFromFightForUserId(fight, userId); if (!character) @@ -720,7 +709,6 @@ export class FightService { return this.setAndTakeNextTurn(fight); const monsterRef = this.contentService.getMonster(characterRef.monsterId); - if (!monsterRef) return this.setAndTakeNextTurn(fight); const abilities = monsterRef.abilities; if (abilities.length === 0) { @@ -741,7 +729,6 @@ export class FightService { if (!ability) return this.setAndTakeNextTurn(fight); const abilityRef = this.contentService.getAbility(ability.ability); - if (!abilityRef) return this.setAndTakeNextTurn(fight); const targetParams = getTargetsForAIAbility( fight, @@ -883,8 +870,6 @@ export class FightService { await Promise.all( fight.involvedPlayers.map(async (playerId) => { const player = await this.playerService.getPlayerForUser(playerId); - if (!player) - throw new NotFoundException(`Player ${playerId} not found`); this.emit(playerId, { fight, diff --git a/server/src/modules/gameplay/gameplay.service.ts b/server/src/modules/gameplay/gameplay.service.ts index e013042..c31cd35 100644 --- a/server/src/modules/gameplay/gameplay.service.ts +++ b/server/src/modules/gameplay/gameplay.service.ts @@ -9,11 +9,7 @@ import { FightService } from '@modules/fight/fight.service'; import { Player } from '@modules/player/player.schema'; import { PlayerService } from '@modules/player/player.service'; import { StatsService } from '@modules/stats/stats.service'; -import { - ForbiddenException, - Injectable, - NotFoundException, -} from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { EventEmitter2 } from '@nestjs/event-emitter'; import { getPatchesAfterPropChanges } from '@utils/patches'; import { userError, userSuccessObject } from '@utils/usernotifications'; @@ -50,7 +46,6 @@ export class GameplayService { async explore(userId: string): Promise { const player = await this.playerService.getPlayerForUser(userId); - if (!player) throw new NotFoundException(`Player ${userId} not found`); const fight = await this.fights.getFightForUser(userId); if (fight) return userError('You cannot explore while in a fight!'); @@ -66,16 +61,9 @@ export class GameplayService { userId, ); - if (!discoveries) - throw new NotFoundException(`Discoveries ${userId} not found`); - - let foundLocation: ILocation | undefined; - - foundLocation = this.contentService.getLocation(player.location.current); - - if (!foundLocation) { - foundLocation = this.contentService.getLocation('Mork'); - } + const foundLocation: ILocation = this.contentService.getLocation( + player.location.current, + ); if (!foundLocation) return { player: [], discoveries: [] }; @@ -262,21 +250,17 @@ export class GameplayService { async startFight(userId: string): Promise { const player = await this.playerService.getPlayerForUser(userId); - if (!player) throw new NotFoundException(`Player ${userId} not found`); const existingFight = await this.fights.getFightForUser(userId); if (existingFight) return userError('You are already in a fight!'); const formationId = player.action?.actionData.formation.itemId; const formation = this.contentService.getFormation(formationId); - if (!formation) - throw new NotFoundException(`Formation ${formationId} not found`); const fight = await this.fights.createPvEFightForSinglePlayer( player, formation, ); - if (!fight) throw new ForbiddenException('Fight not created'); this.analyticsService.sendDesignEvent( userId, diff --git a/server/src/modules/gameplay/item.service.ts b/server/src/modules/gameplay/item.service.ts index 66ed193..16a7d13 100644 --- a/server/src/modules/gameplay/item.service.ts +++ b/server/src/modules/gameplay/item.service.ts @@ -46,11 +46,8 @@ export class ItemService { async takeItem(userId: string): Promise { const player = await this.playerService.getPlayerForUser(userId); - if (!player) throw new NotFoundException(`Player ${userId} not found`); const inventory = await this.inventoryService.getInventoryForUser(userId); - if (!inventory) - throw new NotFoundException(`Inventory ${userId} not found`); const isResource = player.action?.action === 'resource'; @@ -118,18 +115,13 @@ export class ItemService { if (!instanceId) throw new NotFoundException('Item instance not found!'); const player = await this.playerService.getPlayerForUser(userId); - if (!player) throw new NotFoundException(`Player ${userId} not found`); const itemRef = await this.inventoryService.getInventoryItemForUser( userId, instanceId, ); - if (!itemRef) - throw new NotFoundException(`Inventory item ${instanceId} not found`); const item = this.contentService.getItem(itemRef.itemId); - if (!item) - throw new NotFoundException(`Item ref ${itemRef.itemId} not found`); const coinsGained = itemValue(item); await this.inventoryService.removeInventoryItemForUser(userId, instanceId); @@ -176,11 +168,8 @@ export class ItemService { instanceId: string, ): Promise { const player = await this.playerService.getPlayerForUser(userId); - if (!player) throw new NotFoundException(`Player ${userId} not found`); const inventory = await this.inventoryService.getInventoryForUser(userId); - if (!inventory) - throw new NotFoundException(`Inventory ${userId} not found`); const fight = await this.fights.getFightForUser(userId); if (fight) return userError('You cannot equip items while in a fight.'); @@ -189,15 +178,9 @@ export class ItemService { userId, instanceId, ); - if (!item) - throw new NotFoundException(`Inventory item ${instanceId} not found.`); - const itemRef = await this.contentService.getItem(item.itemId); - if (!itemRef) - throw new NotFoundException(`Item ref ${item.itemId} not found`); - - const job = await this.contentService.getJob(player.job); - if (!job) throw new NotFoundException(`Job ${player.job} not found.`); + const itemRef = this.contentService.getItem(item.itemId); + const job = this.contentService.getJob(player.job); if ( !job.armorSlots[itemRef.type] && @@ -261,19 +244,13 @@ export class ItemService { instanceId: string, ): Promise { const inventory = await this.inventoryService.getInventoryForUser(userId); - if (!inventory) - throw new NotFoundException(`Inventory ${userId} not found`); const item = await this.inventoryService.getInventoryItemForUser( userId, instanceId, ); - if (!item) - throw new NotFoundException(`Equipped item ${instanceId} not found.`); const itemRef = this.contentService.getItem(item.itemId); - if (!itemRef) - throw new NotFoundException(`Item ref ${item.itemId} not found`); item.isInUse = false; @@ -297,17 +274,12 @@ export class ItemService { async craftItem(userId: string, itemId: string): Promise { const crafting = await this.craftingService.getCraftingForUser(userId); - if (!crafting) throw new NotFoundException(`Crafting ${userId} not found.`); const inventory = await this.inventoryService.getInventoryForUser(userId); - if (!inventory) - throw new NotFoundException(`Inventory ${userId} not found`); const recipe = this.contentService.getRecipe(itemId); - if (!recipe) throw new NotFoundException(`Recipe ${itemId} not found.`); const item = this.contentService.getItem(itemId); - if (!item) throw new NotFoundException(`Craft item ${itemId} not found.`); if (crafting.currentlyCrafting) return userError('You are already crafting an item.'); @@ -377,25 +349,19 @@ export class ItemService { async takeCraftedItem(userId: string): Promise { const crafting = await this.craftingService.getCraftingForUser(userId); - if (!crafting) throw new NotFoundException(`Crafting ${userId} not found.`); const inventory = await this.inventoryService.getInventoryForUser(userId); - if (!inventory) - throw new NotFoundException(`Inventory ${userId} not found`); const craftItem = crafting.currentlyCrafting; if (!craftItem) throw new NotFoundException('Currently crafting item not found.'); const recipe = this.contentService.getRecipe(craftItem); - if (!recipe) throw new NotFoundException(`Recipe ${craftItem} not found.`); if (Date.now() < crafting.currentlyCraftingDoneAt) return userError('Crafting not done yet.'); const item = this.contentService.getItem(craftItem); - if (!item) - throw new NotFoundException(`Crafted ${craftItem} item not found.`); if ( item.type !== 'resource' && diff --git a/server/src/modules/gameplay/npc.service.ts b/server/src/modules/gameplay/npc.service.ts index 9694ec4..eec1d95 100644 --- a/server/src/modules/gameplay/npc.service.ts +++ b/server/src/modules/gameplay/npc.service.ts @@ -27,13 +27,10 @@ export class NpcService { async changeClass(userId: string): Promise { const player = await this.playerService.getPlayerForUser(userId); - if (!player) throw new NotFoundException(`Player ${userId} not found`); const inventory = await this.inventoryService.getInventoryForUser( player.userId, ); - if (!inventory) - throw new NotFoundException(`Inventory ${userId} not found`); const newJob = player.action?.actionData.newJob; if (!newJob) throw new NotFoundException(`New job ${newJob} not found.`); @@ -76,7 +73,6 @@ export class NpcService { async buyPortrait(userId: string): Promise { const player = await this.playerService.getPlayerForUser(userId); - if (!player) throw new NotFoundException(`Player ${userId} not found`); const { unlockSprite, unlockCost } = player.action?.actionData.npc.properties; @@ -87,8 +83,6 @@ export class NpcService { const discoveries = await this.discoveriesService.getDiscoveriesForUser( userId, ); - if (!discoveries) - throw new NotFoundException(`Discoveries ${userId} not found.`); const playerPatches = await getPatchesAfterPropChanges( player, @@ -116,7 +110,6 @@ export class NpcService { async buyBackground(userId: string): Promise { const player = await this.playerService.getPlayerForUser(userId); - if (!player) throw new NotFoundException(`Player ${userId} not found`); const { unlockBackground, unlockCost } = player.action?.actionData.npc.properties; @@ -127,8 +120,6 @@ export class NpcService { const discoveries = await this.discoveriesService.getDiscoveriesForUser( userId, ); - if (!discoveries) - throw new NotFoundException(`Discoveries ${userId} not found.`); const playerPatches = await getPatchesAfterPropChanges( player, diff --git a/server/src/modules/gameplay/travel.service.ts b/server/src/modules/gameplay/travel.service.ts index df741eb..5fb048b 100644 --- a/server/src/modules/gameplay/travel.service.ts +++ b/server/src/modules/gameplay/travel.service.ts @@ -6,11 +6,7 @@ import { DiscoveriesService } from '@modules/discoveries/discoveries.service'; import { Player } from '@modules/player/player.schema'; import { PlayerService } from '@modules/player/player.service'; import { StatsService } from '@modules/stats/stats.service'; -import { - ForbiddenException, - Injectable, - NotFoundException, -} from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { EventEmitter2 } from '@nestjs/event-emitter'; import { getPatchesAfterPropChanges } from '@utils/patches'; import { userError } from '@utils/usernotifications'; @@ -34,7 +30,6 @@ export class TravelService { locationName: string, ): Promise { const player = await this.playerService.getPlayerForUser(userId); - if (!player) throw new NotFoundException(`Player ${userId} not found`); if (player.location.goingTo === locationName) return userError(`You are already walking to ${locationName}!`); @@ -46,12 +41,7 @@ export class TravelService { userId, ); - if (!discoveries) - throw new NotFoundException(`Discoveries ${userId} not found.`); - const location = this.contentService.getLocation(locationName); - if (!location) - throw new NotFoundException(`Location ${locationName} does not exist!`); if (player.level < location.level) return userError('You are not high enough level to go here!'); @@ -85,7 +75,6 @@ export class TravelService { locationName: string, ): Promise { const player = await this.playerService.getPlayerForUser(userId); - if (!player) throw new NotFoundException(`Player ${userId} not found`); if (player.location.current === locationName) return userError('You are already here!'); @@ -96,12 +85,8 @@ export class TravelService { const discoveries = await this.discoveriesService.getDiscoveriesForUser( userId, ); - if (!discoveries) - throw new NotFoundException(`Discoveries ${userId} not found.`); const location = this.contentService.getLocation(locationName); - if (!location) - throw new ForbiddenException(`Location ${locationName} does not exist!`); if (player.level < location.level) return userError('You are not high enough level to go here!'); diff --git a/server/src/modules/gameplay/wave.service.ts b/server/src/modules/gameplay/wave.service.ts index 65f583c..354cecd 100644 --- a/server/src/modules/gameplay/wave.service.ts +++ b/server/src/modules/gameplay/wave.service.ts @@ -28,7 +28,6 @@ export class WaveService { async waveToPlayerFromExplore(userId: string): Promise { const player = await this.playerService.getPlayerForUser(userId); - if (!player) throw new NotFoundException(`Player ${userId} not found`); if (!player.action) throw new ForbiddenException('Player has no action'); @@ -40,7 +39,6 @@ export class WaveService { notificationId: string, ): Promise { const player = await this.playerService.getPlayerForUser(userId); - if (!player) throw new NotFoundException(`Player ${userId} not found`); const notification = await this.notificationService.getNotificationForUser( userId, @@ -70,11 +68,6 @@ export class WaveService { const { targetUserId, isWaveBack } = action?.urlData ?? {}; const otherPlayer = await this.playerService.getPlayerForUser(targetUserId); - if (!otherPlayer) - throw new NotFoundException(`Target player ${targetUserId} not found`); - - const stats = await this.statsService.getStatsForUser(targetUserId); - if (!stats) throw new NotFoundException(`Stats ${targetUserId} not found`); // tell the user they waved const playerPatches = await getPatchesAfterPropChanges( diff --git a/server/src/modules/inventory/inventory.service.ts b/server/src/modules/inventory/inventory.service.ts index 5246c5a..b5d2893 100644 --- a/server/src/modules/inventory/inventory.service.ts +++ b/server/src/modules/inventory/inventory.service.ts @@ -27,7 +27,18 @@ export class InventoryService { private readonly contentService: ContentService, ) {} - async getInventoryForUser(userId: string): Promise { + async getInventoryForUser(userId: string): Promise { + const inventory = await this.getOrCreateInventoryForUser(userId); + if (!inventory) { + throw new BadRequestException(`inventory id ${userId} not found.`); + } + + return inventory; + } + + private async getOrCreateInventoryForUser( + userId: string, + ): Promise { const dbInventory = await this.inventory.findOne({ userId }); if (!dbInventory) { return await this.createInventoryForUser(userId); @@ -64,8 +75,11 @@ export class InventoryService { async getInventoryItemForUser( userId: string, instanceId: string, - ): Promise { - return this.inventoryItems.findOne({ userId, instanceId }); + ): Promise { + const item = await this.inventoryItems.findOne({ userId, instanceId }); + if (!item) throw new NotFoundException(`Item ${instanceId} not found.`); + + return item; } async removeInventoryItemForUser( @@ -73,7 +87,6 @@ export class InventoryService { instanceId: string, ): Promise { const item = await this.getInventoryItemForUser(userId, instanceId); - if (!item) return; this.logger.verbose( `Removing item ${item.itemId} (${instanceId}) from ${userId}.`, @@ -86,13 +99,9 @@ export class InventoryService { instanceId: string, ): Promise>> { const item = await this.getInventoryItemForUser(userId, instanceId); - if (!item) - throw new NotFoundException(`Inventory item ${instanceId} not found.`); const itemRef = this.contentService.getEquipment(item.itemId); - if (!itemRef) return {}; - - return itemRef.stats; + return itemRef.stats ?? {}; } async isInventoryFull(userId: string): Promise { @@ -106,7 +115,6 @@ export class InventoryService { async acquireItem(userId: string, itemId: string) { const itemRef = this.contentService.getItem(itemId); - if (!itemRef) throw new NotFoundException(`Item ref ${itemId} not found.`); if (itemRef.type === 'resource') { await this.acquireResource(userId, itemId, 1); @@ -126,14 +134,11 @@ export class InventoryService { async hasResource(userId: string, resourceId: string, amount: number) { const inventory = await this.getInventoryForUser(userId); - if (!inventory) return; - return inventory.resources[resourceId] >= amount; } async updateEquippedItem(userId: string, slot: ItemSlot, item: IEquipment) { const inventory = await this.getInventoryForUser(userId); - if (!inventory) return; inventory.equippedItems = { ...inventory.equippedItems, @@ -158,11 +163,8 @@ export class InventoryService { async acquireResource(userId: string, itemId: string, quantity = 1) { const inventory = await this.getInventoryForUser(userId); - if (!inventory) return; const itemRef = this.contentService.getItem(itemId); - if (!itemRef) - throw new BadRequestException(`Item ref ${itemId} not found.`); if (itemRef.type !== 'resource') { await this.acquireItem(userId, itemId); @@ -194,7 +196,6 @@ export class InventoryService { async removeResource(userId: string, itemId: string, quantity = 1) { const inventory = await this.getInventoryForUser(userId); - if (!inventory) return; this.logger.verbose( `Removing resource x${quantity} ${itemId} for ${userId}.`, @@ -206,8 +207,6 @@ export class InventoryService { userId: string, ): Promise> { const inventory = await this.getInventoryForUser(userId); - if (!inventory) - throw new NotFoundException(`Inventory ${userId} not found`); return inventory.equippedItems; } diff --git a/server/src/modules/lottery/buyinlottery.service.ts b/server/src/modules/lottery/buyinlottery.service.ts index 218ef77..8c5c1fb 100644 --- a/server/src/modules/lottery/buyinlottery.service.ts +++ b/server/src/modules/lottery/buyinlottery.service.ts @@ -101,7 +101,6 @@ export class BuyInLotteryService implements OnModuleInit { if (todayTicket.claimed) return userError('Ticket already claimed'); const player = await this.playerService.getPlayerForUser(userId); - if (!player) throw new NotFoundError(`User ${userId} not found`); if ( !this.playerHelper.hasCoins(player, this.constants.buyinLotteryTicketCost) @@ -175,7 +174,6 @@ export class BuyInLotteryService implements OnModuleInit { return userError('Todays ticket was already claimed.'); const player = await this.playerService.getPlayerForUser(userId); - if (!player) throw new NotFoundError(`User ${userId} not found`); const total = await this.ticketValueSum(); diff --git a/server/src/modules/lottery/dailylottery.service.ts b/server/src/modules/lottery/dailylottery.service.ts index a116043..a43c2ec 100644 --- a/server/src/modules/lottery/dailylottery.service.ts +++ b/server/src/modules/lottery/dailylottery.service.ts @@ -1,5 +1,4 @@ import { UserResponse } from '@interfaces'; -import { NotFoundError } from '@mikro-orm/core'; import { EntityManager } from '@mikro-orm/mongodb'; import { ConstantsService } from '@modules/content/constants.service'; import { PlayerHelperService } from '@modules/content/playerhelper.service'; @@ -124,7 +123,6 @@ export class DailyLotteryService implements OnModuleInit { if (!record) return userError('You are not the winner for today'); const player = await this.playerService.getPlayerForUser(userId); - if (!player) throw new NotFoundError(`Player ${userId} not found`); const rewardScale = await this.numPlayersOnlineInLastWeek(); diff --git a/server/src/modules/lottery/lottery.controller.ts b/server/src/modules/lottery/lottery.controller.ts index dd4b17f..dcb15e6 100644 --- a/server/src/modules/lottery/lottery.controller.ts +++ b/server/src/modules/lottery/lottery.controller.ts @@ -33,7 +33,7 @@ export class LotteryController { @UseGuards(JwtAuthGuard) @ApiOperation({ summary: 'Get my buyin tickets total value' }) @Get('buyin/value') - async jackpotValue(@User() user): Promise { + async jackpotValue(): Promise { return this.buyinLotteryService.ticketValueSum(); } diff --git a/server/src/modules/market/market.service.ts b/server/src/modules/market/market.service.ts index 64f8bbd..1385966 100644 --- a/server/src/modules/market/market.service.ts +++ b/server/src/modules/market/market.service.ts @@ -55,7 +55,6 @@ export class MarketService { quantity = 1, ): Promise { const player = await this.playerService.getPlayerForUser(userId); - if (!player) throw new NotFoundException(`Player ${userId} not found`); const user = await this.userService.findUserById(userId); if (!user) throw new NotFoundException(`User ${userId} not found`); @@ -73,8 +72,6 @@ export class MarketService { instanceId, ); - if (!inventoryItem) - throw new NotFoundException(`Inventory item ${instanceId} not found.`); if (inventoryItem.isInUse) throw new BadRequestException(`Item ${instanceId} is in use already`); @@ -111,10 +108,6 @@ export class MarketService { const playerLocation = this.contentService.getLocation( player.location.current, ); - if (!playerLocation) - throw new NotFoundException( - `Location ${player.location.current} not found`, - ); const taxRate = playerLocation.baseStats.taxRate ?? 5; const tax = Math.floor(validPrice * (taxRate / 100)); @@ -309,7 +302,6 @@ export class MarketService { return userError('The market currently owes you no coins.'); const player = await this.playerService.getPlayerForUser(userId); - if (!player) throw new NotFoundException(`Player ${userId} not found`); const playerPatches = await getPatchesAfterPropChanges( player, @@ -345,21 +337,12 @@ export class MarketService { if (listing.isSold) return userError(`That item has already sold!`); const player = await this.playerService.getPlayerForUser(userId); - if (!player) throw new NotFoundException(`Player ${userId} not found`); const user = await this.userService.findUserById(userId); if (!user) throw new NotFoundException(`User ${userId} not found`); const isResource = this.contentService.getResource(listing.itemId); - const itemRef = this.contentService.getItem(listing.itemId); - if (!itemRef && !isResource) - throw new NotFoundException(`Item ref ${listing.itemId} not found`); - - const inventory = await this.inventoryService.getInventoryForUser(userId); - if (!inventory) - throw new NotFoundException(`Inventory ${userId} not found`); - if (!this.playerHelper.hasCoins(player, listing.price)) return userError('Not enough coins'); @@ -427,7 +410,6 @@ export class MarketService { price: number, ): Promise { const player = await this.playerService.getPlayerForUser(userId); - if (!player) throw new NotFoundException(`Player ${userId} not found`); const user = await this.userService.findUserById(userId); if (!user) throw new NotFoundException(`User ${userId} not found`); @@ -455,10 +437,6 @@ export class MarketService { const playerLocation = this.contentService.getLocation( player.location.current, ); - if (!playerLocation) - throw new NotFoundException( - `Location ${player.location.current} not found`, - ); const taxRate = playerLocation.baseStats.taxRate ?? 5; const tax = Math.max(1, Math.floor(validPrice * (taxRate / 100))); @@ -497,9 +475,6 @@ export class MarketService { } async unlistItem(userId: string, listingId: string): Promise { - const player = await this.playerService.getPlayerForUser(userId); - if (!player) throw new NotFoundException(`Player ${userId} not found`); - const user = await this.userService.findUserById(userId); if (!user) throw new NotFoundException(`User ${userId} not found`); diff --git a/server/src/modules/player/npc.service.ts b/server/src/modules/player/npc.service.ts index 2018dc9..29fd62e 100644 --- a/server/src/modules/player/npc.service.ts +++ b/server/src/modules/player/npc.service.ts @@ -39,7 +39,7 @@ export class NpcService { const discoveries = await this.discoveriesService.getDiscoveriesForUser( player.userId, ); - if (!discoveries) return undefined; + if (discoveries.portraits[npc.properties.unlockSprite]) return undefined; return { @@ -61,7 +61,7 @@ export class NpcService { const discoveries = await this.discoveriesService.getDiscoveriesForUser( player.userId, ); - if (!discoveries) return undefined; + if (discoveries.backgrounds[npc.properties.unlockBackground]) return undefined; diff --git a/server/src/modules/player/player.controller.ts b/server/src/modules/player/player.controller.ts index 5195e8a..72bdd88 100644 --- a/server/src/modules/player/player.controller.ts +++ b/server/src/modules/player/player.controller.ts @@ -3,15 +3,7 @@ import { JwtAuthGuard } from '@modules/auth/jwt.guard'; import { DiscoveriesService } from '@modules/discoveries/discoveries.service'; import { Player } from '@modules/player/player.schema'; import { PlayerService } from '@modules/player/player.service'; -import { - Body, - Controller, - Get, - NotFoundException, - Param, - Patch, - UseGuards, -} from '@nestjs/common'; +import { Body, Controller, Get, Param, Patch, UseGuards } from '@nestjs/common'; import { ApiBearerAuth, ApiOperation } from '@nestjs/swagger'; import { User } from '@utils/user.decorator'; import { userError } from '@utils/usernotifications'; @@ -67,12 +59,6 @@ export class PlayerController { user.userId, ); - if (!discoveries) { - throw new NotFoundException( - `Discoveries ${user.userId} not found for this user.`, - ); - } - // Check if the portrait is unlocked if (!discoveries.portraits[portraitId.toString()]) { return userError(`Portrait ${portraitId} is not unlocked.`); @@ -95,12 +81,6 @@ export class PlayerController { user.userId, ); - if (!discoveries) { - throw new NotFoundException( - `Discoveries ${user.userId} not found for this user.`, - ); - } - // Check if the portrait is unlocked if (backgroundId !== -1 && !discoveries.backgrounds[backgroundId]) { return userError(`Background ${backgroundId} is not unlocked.`); diff --git a/server/src/modules/player/player.service.ts b/server/src/modules/player/player.service.ts index 0d732be..cc93e39 100644 --- a/server/src/modules/player/player.service.ts +++ b/server/src/modules/player/player.service.ts @@ -19,11 +19,7 @@ import { InventoryService } from '@modules/inventory/inventory.service'; import { NpcService } from '@modules/player/npc.service'; import { Player } from '@modules/player/player.schema'; import { WaveDBService } from '@modules/wave/wavedb.service'; -import { - BadRequestException, - Injectable, - NotFoundException, -} from '@nestjs/common'; +import { BadRequestException, Injectable } from '@nestjs/common'; import { EventEmitter2 } from '@nestjs/event-emitter'; import { getPatchesAfterPropChanges } from '@utils/patches'; import { userError, userSuccessObject } from '@utils/usernotifications'; @@ -47,7 +43,18 @@ export class PlayerService { private readonly waveDBService: WaveDBService, ) {} - async getPlayerForUser(userId: string): Promise { + async getPlayerForUser(userId: string): Promise { + const player = await this.getOrCreatePlayerForUser(userId); + if (!player) { + throw new BadRequestException(`player id ${userId} not found.`); + } + + return player; + } + + private async getOrCreatePlayerForUser( + userId: string, + ): Promise { const dbPlayer = await this.players.findOne({ userId }); if (!dbPlayer) { return await this.createPlayerForUser(userId); @@ -79,7 +86,6 @@ export class PlayerService { async getPlayerProfile(userId: string): Promise | undefined> { const player = await this.getPlayerForUser(userId); - if (!player) throw new NotFoundException(`Player ${userId} not found`); return pick(player, [ 'userId', @@ -97,7 +103,6 @@ export class PlayerService { portrait: number, ): Promise { const player = await this.getPlayerForUser(userId); - if (!player) throw new NotFoundException(`Player ${userId} not found`); const playerPatches = await getPatchesAfterPropChanges( player, @@ -121,7 +126,6 @@ export class PlayerService { background: number, ): Promise { const player = await this.getPlayerForUser(userId); - if (!player) throw new NotFoundException(`Player ${userId} not found`); const playerPatches = await getPatchesAfterPropChanges( player, @@ -145,7 +149,6 @@ export class PlayerService { shortBio: string, ): Promise { const player = await this.getPlayerForUser(userId); - if (!player) throw new NotFoundException(`Player ${userId} not found`); shortBio = this.contentService.censor.cleanProfanityIsh( shortBio.substring(0, 30).trim(), @@ -175,7 +178,6 @@ export class PlayerService { longBio: string, ): Promise { const player = await this.getPlayerForUser(userId); - if (!player) throw new NotFoundException(`Player ${userId} not found`); longBio = this.contentService.censor.cleanProfanityIsh( longBio.substring(0, 500).trim(), @@ -204,13 +206,10 @@ export class PlayerService { slot: number, ): Promise { const player = await this.getPlayerForUser(userId); - if (!player) throw new NotFoundException(`Player ${userId} not found`); const discoveries = await this.discoveriesService.getDiscoveriesForUser( userId, ); - if (!discoveries) - throw new NotFoundException(`Discoveries ${userId} not found`); if (itemId && !discoveries.collectibles[itemId]) return userError('You have not discovered this collectible!'); @@ -258,13 +257,10 @@ export class PlayerService { slot: number, ): Promise { const player = await this.getPlayerForUser(userId); - if (!player) throw new NotFoundException(`Player ${userId} not found`); const discoveries = await this.discoveriesService.getDiscoveriesForUser( userId, ); - if (!discoveries) - throw new NotFoundException(`Discoveries ${userId} not found`); if (itemId && !discoveries.items[itemId]) return userError('You have not discovered this item!'); @@ -530,7 +526,6 @@ export class PlayerService { // get job stats const job = this.contentService.getJob(player.job); - if (!job) return base; Object.keys(job.statGainsPerLevel).forEach((stat) => { base[stat as Stat] += job.statGainsPerLevel[stat as Stat] * player.level; @@ -579,7 +574,6 @@ export class PlayerService { if (!randomNPCForLocation) return; const npcData = this.contentService.getNPC(randomNPCForLocation.name); - if (!npcData) return; const action = await this.npcService.getActionForNPC( player, diff --git a/server/src/modules/stats/stats.service.ts b/server/src/modules/stats/stats.service.ts index 64f9b18..7cb1860 100644 --- a/server/src/modules/stats/stats.service.ts +++ b/server/src/modules/stats/stats.service.ts @@ -24,7 +24,18 @@ export class StatsService { private readonly userService: UserService, ) {} - async getStatsForUser(userId: string): Promise { + async getStatsForUser(userId: string): Promise { + const stats = await this.getOrCreateStatsForUser(userId); + if (!stats) { + throw new BadRequestException(`stats id ${userId} not found.`); + } + + return stats; + } + + private async getOrCreateStatsForUser( + userId: string, + ): Promise { const dbStats = await this.stats.findOne({ userId }); if (!dbStats) { return await this.createStatsForUser(userId); @@ -58,7 +69,6 @@ export class StatsService { userId: string, ): Promise> { const stats = await this.getStatsForUser(userId); - if (!stats) throw new NotFoundException(`Stats ${userId} not found`); return leaderboardQueries.map((query) => ({ name: query.singleUserName, @@ -68,7 +78,6 @@ export class StatsService { async incrementStat(userId: string, stat: TrackedStat, byValue = 1) { const stats = await this.getStatsForUser(userId); - if (!stats) throw new NotFoundException(`Stats ${userId} not found`); this.logger.verbose( `Incrementing stat ${stat} by ${byValue} for user ${userId}`, @@ -83,7 +92,6 @@ export class StatsService { @OnEvent('sync.player') async syncPlayer(player: Player): Promise { const stats = await this.getStatsForUser(player.userId); - if (!stats) throw new NotFoundException(`Stats ${player.userId} not found`); const user = await this.userService.findUserById(player.userId); if (!user) throw new NotFoundException(`User ${player.userId} not found`); @@ -104,8 +112,6 @@ export class StatsService { @OnEvent('sync.discoveries') async syncDiscoveries(discoveries: Discoveries): Promise { const stats = await this.getStatsForUser(discoveries.userId); - if (!stats) - throw new NotFoundException(`Stats ${discoveries.userId} not found`); stats.discoveries = { locations: Object.keys(discoveries.locations || {}).length,