Files
ZYZ/game-server/app/services/role/checkMaterial.ts

196 lines
7.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { CURRENCY_TYPE, HANDLE_REWARD_TYPE, CURRENCY_BY_TYPE } from '../../consts';
import { RoleModel, RoleType } from '../../db/Role';
import { ItemModel, ItemType } from '../../db/Item';
import { ItemInter, RewardInter, } from '../../pubUtils/interface';
import { gameData } from '../../pubUtils/data';
import { sortItems } from './util';
export class CheckMeterial {
private roleId: string;
private itemsIndb: Map<number, number> = new Map(); // 玩家已有的东西
private notEnoughItems: Map<number, number> = new Map(); // 缺少的数量
private consumes: ItemInter[] = []; // 消耗,正向数
private canReplace: boolean = false; // 是否可以被通用的啥代替代替
private tempConsumes: ItemInter[] = [];
private goldId = CURRENCY_BY_TYPE.get(CURRENCY_TYPE.GOLD);
private coinId = CURRENCY_BY_TYPE.get(CURRENCY_TYPE.COIN);
constructor(roleId: string, role?: RoleType, items?: ItemType[]) {
this.roleId = roleId;
if(role) {
this.itemsIndb.set(this.goldId, role.gold);
this.itemsIndb.set(this.coinId, role.coin);
}
if(items && items.length) {
for(let {id, count} of items) {
this.itemsIndb.set(id, count);
}
}
}
private pushToNotEnoughItems(id: number, count: number) {
if(!this.notEnoughItems.has(id)) {
this.notEnoughItems.set(id, 0);
}
this.notEnoughItems.set(id, this.notEnoughItems.get(id) + count);
}
private getNotEnoughItems() {
let map = new Map<number, number>();
for(let [ id, count ] of this.notEnoughItems) {
map.set(id, count);
}
return map;
}
public async decrease(goods: {id: number, count: number}[]) {
this.tempConsumes.splice(0, this.tempConsumes.length);
this.notEnoughItems.clear();
let { items, gold, coin } = sortItems(goods, HANDLE_REWARD_TYPE.COST);
for(let { id, count} of items) {
console.log('#####', id, count)
let notEnoughCount = await this.decreaseItem(id, count);
console.log('##### notEnoughCount', id, notEnoughCount, this.canReplace)
if(notEnoughCount > 0) {
let isEnough = await this.checkReplaceItem(id, notEnoughCount);
if(isEnough) {
this.tempConsumes.push({ id, count: count - notEnoughCount });
} else {
return false;
}
}
}
if(gold.length > 0) {
let isEnough = await this.decreaseGold(gold);
if(!isEnough) return false;
}
if(coin.length > 0) {
let isEnough = await this.decreaseCoin(coin);
if(!isEnough) return false;
}
this.consumes.push(...this.tempConsumes);
return true;
}
public setCanReplace(canReplace: boolean) {
this.canReplace = canReplace;
}
private async decreaseItem(id: number, count: number) {
console.log('#### decreaseItem 1', id, count);
if(!this.itemsIndb.has(id)) {
let item = await ItemModel.findbyRoleAndGid(this.roleId, id);
console.log('#### decreaseItem', item);
if(!item) {
this.pushToNotEnoughItems(id, count);
return count;
}
this.itemsIndb.set(id, item.count);
}
if(this.itemsIndb.get(id) < count) {
let notEnoughCount = count - this.itemsIndb.get(id);
this.pushToNotEnoughItems(id, notEnoughCount);
this.itemsIndb.set(id, 0);
return notEnoughCount;
} else {
this.itemsIndb.set(id, this.itemsIndb.get(id) - count);
this.tempConsumes.push({ id, count });
return 0
}
}
private async checkReplaceItem(id: number, count: number) {
if(!this.canReplace) return false;
let relationGoodId = gameData.relationGoods.get(id);
if(!relationGoodId) return false;
if(relationGoodId == this.goldId) {
return await this.decreaseGold([{ count }]);
} else if (relationGoodId == this.coinId) {
return await this.decreaseCoin([count]);
} else {
let cnt = await this.decreaseItem(relationGoodId, count);
return cnt == 0
}
}
private async decreaseGold(gold: { count: number }[]) {
if(!this.itemsIndb.has(this.goldId)) {
let role = await RoleModel.findByRoleId(this.roleId, 'gold coin');
this.itemsIndb.set(this.goldId, role.gold);
this.itemsIndb.set(this.coinId, role.coin);
}
let goldCost = gold.reduce((pre, cur) => { return pre + cur.count }, 0);
if(this.itemsIndb.get(this.goldId) < goldCost) {
this.pushToNotEnoughItems(this.goldId, goldCost - this.itemsIndb.get(this.goldId));
this.itemsIndb.set(this.goldId, 0);
return false;
}
this.itemsIndb.set(this.goldId, this.itemsIndb.get(this.goldId) - goldCost);
this.tempConsumes.push({ id: this.goldId, count: goldCost });
return true
}
private async decreaseCoin(coin: number[]) {
if(!this.itemsIndb.has(this.coinId)) {
let role = await RoleModel.findByRoleId(this.roleId, 'gold coin');
this.itemsIndb.set(this.goldId, role.gold);
this.itemsIndb.set(this.coinId, role.coin);
}
let coinCost = coin.reduce((pre, cur) => pre + cur, 0);
if(this.itemsIndb.get(this.coinId) < coinCost) {
this.pushToNotEnoughItems(this.coinId, coinCost - this.itemsIndb.get(this.coinId));
this.itemsIndb.set(this.coinId, 0);
return false;
}
this.itemsIndb.set(this.coinId, this.itemsIndb.get(this.coinId) - coinCost);
this.tempConsumes.push({ id: this.coinId, count: coinCost });
return true;
}
private getMaterialEnough(materials: RewardInter[], notEnoughItems: Map<number, number>) {
let newMaterials: RewardInter[] = [];
for(let {id, count} of materials) {
if(notEnoughItems.has(id)) {
newMaterials.push({ id, count: count - notEnoughItems.get(id) });
} else {
newMaterials.push({ id, count });
}
}
return newMaterials;
}
// 检查地玉石是否可以合成
public async composeStone(id: number, count: number) {
let dicStone = gameData.stone.get(id);
if(!dicStone || dicStone.composeMaterial.length <= 0) return false; // 1阶石头不能再从下合成返回不行
let materials = dicStone.composeMaterial.map(cur => ({...cur, count: cur.count * count }));
let isEnough = await this.decrease(materials);
if(!isEnough) {
let notEnoughItems = this.getNotEnoughItems();
let newMaterials = this.getMaterialEnough(materials, notEnoughItems);
let isEnough = await this.decrease(newMaterials); // 消耗掉除了不足的部分以外的其他部分
if(!isEnough) return false;
let isAllOK = true; // 如果有石头不足向下补充isAllOK标识不足的都能补充上
for(let [id, count] of notEnoughItems) {
let isEnough = await this.composeStone(id, count);
if(!isEnough) {
isAllOK = false; break;
}
}
return isAllOK;
} else {
return true;
}
}
public getConsume() {
return this.consumes;
}
}