finish unlock hero
This commit is contained in:
parent
dd5c51c722
commit
c4c3ba8ac1
23
docs/api.md
23
docs/api.md
@ -244,8 +244,7 @@
|
||||
|
||||
| 字段 | 说明 |
|
||||
| -------- | -------------------------------------- |
|
||||
| moneyid |代币的item id |
|
||||
| count |试用数量 |
|
||||
| count |使用数量 |
|
||||
|
||||
3. Response: JSON
|
||||
|
||||
@ -258,7 +257,25 @@
|
||||
```
|
||||
|
||||
### 11. 将专属英雄碎片转化成经验
|
||||
1. Method: POST
|
||||
2. URI: /api/:accountid/hero/toexp/:heroid
|
||||
|
||||
| 字段 | 说明 |
|
||||
| -------- | -------------------------------------- |
|
||||
| accountid | 帐号id |
|
||||
| heroid | 英雄id |
|
||||
|
||||
|
||||
|
||||
3. Response: JSON
|
||||
|
||||
```json
|
||||
{
|
||||
exp: 1022, // 当前经验值
|
||||
exp_POST: 100, // 本次获得的经验
|
||||
level: 1 // 当前等级
|
||||
}
|
||||
```
|
||||
|
||||
## 三. 服务端接口列表
|
||||
|
||||
@ -277,3 +294,5 @@
|
||||
```
|
||||
|
||||
|
||||
|
||||
```
|
@ -1,18 +1,15 @@
|
||||
import BaseController from "../common/base.controller";
|
||||
import {role, router} from "../decorators/router";
|
||||
import {Account} from "../models/Account";
|
||||
import {User} from "../models/User";
|
||||
import {ZError} from "../common/ZError";
|
||||
import {Hero} from "../models/subdoc/Hero";
|
||||
import {Card} from "../models/subdoc/Card";
|
||||
import {CardGroup} from "../models/CardGroup";
|
||||
import {MoneyTypeConst} from "../constants/MoneyTypeConst";
|
||||
|
||||
export default class AccountController extends BaseController {
|
||||
@role('anon')
|
||||
@router('post /api/:accountid/uinfo')
|
||||
async info(req: any) {
|
||||
let {accountid} = req.params;
|
||||
let account = (await Account.findOrCreate({_id: accountid})).doc;
|
||||
let account = (await User.findOrCreate({_id: accountid})).doc;
|
||||
let result: any = {accountid: account.id};
|
||||
if (account.locked) {
|
||||
throw new ZError(4, 'account locked');
|
||||
@ -63,69 +60,5 @@ export default class AccountController extends BaseController {
|
||||
return result;
|
||||
}
|
||||
|
||||
@router('post /api/:accountid/heros')
|
||||
async herolist(req: any) {
|
||||
let account = req.user;
|
||||
let heros: any[] = [];
|
||||
for(let [key, hero] of account.heros) {
|
||||
heros.push({
|
||||
heroid: hero.heroid,
|
||||
owned: true,
|
||||
usetype: 0,
|
||||
level: hero.level,
|
||||
exp: hero.exp,
|
||||
free: hero.free,
|
||||
free_expire: 0
|
||||
});
|
||||
}
|
||||
//TODO:: 添加限免英雄和免费英雄
|
||||
return heros;
|
||||
}
|
||||
|
||||
@router('post /api/:accountid/hero/unlock/:heroid')
|
||||
async unlockHero(req: any) {
|
||||
let account = req.user;
|
||||
let {heroid, type} = req.params;
|
||||
if (!heroid) {
|
||||
throw new ZError(101, '未指定heroid');
|
||||
}
|
||||
if (account.heros.has(heroid + '')) {
|
||||
if (!account.heros.get(heroid + '').free) {
|
||||
throw new ZError(102, '你已经解锁了该英雄');
|
||||
}
|
||||
}
|
||||
let money0 = MoneyTypeConst.getHeroShard(heroid);
|
||||
let money1 = MoneyTypeConst.HERO_SHARD;
|
||||
let count0 = account.moneys.has(money0) ? account.moneys.get(money0) : 0;
|
||||
let count1 = account.moneys.has(money1) ? account.moneys.get(money1) : 0;
|
||||
// TODO:: 根据配置获取解锁英雄需要的碎片数量
|
||||
let needCount = 30;
|
||||
if (count0 + count1 < needCount) {
|
||||
throw new ZError(102, '碎片数量不足');
|
||||
}
|
||||
if (count0 > 0) {
|
||||
let rest = needCount - count0;
|
||||
if (rest >= 0) {
|
||||
needCount = rest;
|
||||
account.moneys.set(money0, 0);
|
||||
} else {
|
||||
needCount = 0;
|
||||
account.moneys.set(money0, Math.abs(rest));
|
||||
}
|
||||
}
|
||||
// 上面已经过滤了 count0 + count1 > needcount, 所以这里不需要判断碎片是否足够
|
||||
if (needCount > 0) {
|
||||
count1 = count1 - needCount;
|
||||
account.moneys.set(money1, count1);
|
||||
}
|
||||
let hero = new Hero();
|
||||
hero.heroid = heroid;
|
||||
hero.free = false;
|
||||
hero.level = 1;
|
||||
hero.exp = 0;
|
||||
account.heros.set(heroid + '', hero);
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
70
src/controllers/HeroController.ts
Normal file
70
src/controllers/HeroController.ts
Normal file
@ -0,0 +1,70 @@
|
||||
import BaseController from "../common/base.controller";
|
||||
import {router} from "../decorators/router";
|
||||
import {ZError} from "../common/ZError";
|
||||
import {MoneyTypeConst} from "../constants/MoneyTypeConst";
|
||||
import {Hero} from "../models/subdoc/Hero";
|
||||
import {User} from "../models/User";
|
||||
|
||||
export default class HeroController extends BaseController {
|
||||
@router('post /api/:accountid/heros')
|
||||
async herolist(req: any) {
|
||||
let account = req.user;
|
||||
let heros: any[] = [];
|
||||
for(let [key, hero] of account.heros) {
|
||||
heros.push({
|
||||
heroid: hero.heroid,
|
||||
owned: true,
|
||||
usetype: 0,
|
||||
level: hero.level,
|
||||
exp: hero.exp,
|
||||
free: hero.free,
|
||||
free_expire: 0
|
||||
});
|
||||
}
|
||||
//TODO:: 添加限免英雄和免费英雄
|
||||
return heros;
|
||||
}
|
||||
|
||||
@router('post /api/:accountid/hero/unlock/:heroid')
|
||||
async unlockHero(req: any) {
|
||||
let account = req.user;
|
||||
let {heroid, type} = req.params;
|
||||
if (!heroid) {
|
||||
throw new ZError(101, '未指定heroid');
|
||||
}
|
||||
try {
|
||||
if (!type) {
|
||||
let hero = await account.unlockHero(heroid);
|
||||
await account.save();
|
||||
return hero;
|
||||
} else {
|
||||
let hero = await account.tryHero(heroid);
|
||||
await account.save();
|
||||
return hero;
|
||||
}
|
||||
} catch (err) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@router('post /api/:accountid/hero/update/:heroid')
|
||||
async updateHero(req: any) {
|
||||
let account = req.user;
|
||||
let {heroid, count} = req.params;
|
||||
if (!heroid) {
|
||||
throw new ZError(101, '未指定heroid');
|
||||
}
|
||||
if (!account.heros.has(heroid + '')) {
|
||||
throw new ZError(102, '你未解锁该英雄');
|
||||
}
|
||||
}
|
||||
|
||||
@router('post /api/:accountid/hero/toexp/:heroid')
|
||||
async shardToExp(req: any) {
|
||||
let account = req.user;
|
||||
let {heroid} = req.params;
|
||||
|
||||
}
|
||||
}
|
@ -1,91 +0,0 @@
|
||||
import {
|
||||
prop,
|
||||
getModelForClass,
|
||||
modelOptions,
|
||||
index,
|
||||
plugin,
|
||||
mongoose
|
||||
} from '@typegoose/typegoose';
|
||||
import {dbconn} from '../decorators/dbconn';
|
||||
// @ts-ignore
|
||||
import findOrCreate from 'mongoose-findorcreate';
|
||||
import {
|
||||
Base,
|
||||
FindOrCreate,
|
||||
TimeStamps
|
||||
} from "@typegoose/typegoose/lib/defaultClasses";
|
||||
import {Card} from "./subdoc/Card";
|
||||
import {Hero} from "./subdoc/Hero";
|
||||
|
||||
interface AccountClass extends Base<string>, TimeStamps {}
|
||||
@dbconn()
|
||||
// @index({ _id: 1}, { unique: true })
|
||||
@plugin(findOrCreate)
|
||||
@modelOptions({schemaOptions:
|
||||
{collection: "account", timestamps: true}
|
||||
})
|
||||
class AccountClass extends FindOrCreate{
|
||||
@prop()
|
||||
public _id: string;
|
||||
|
||||
@prop({default: false})
|
||||
public locked: boolean;
|
||||
@prop()
|
||||
public lockedtime?: number;
|
||||
|
||||
@prop()
|
||||
public comment?: string;
|
||||
@prop()
|
||||
public lastLogin?: Date;
|
||||
/**
|
||||
* 已获得卡牌信息
|
||||
*/
|
||||
@prop({ type: () => [Number] })
|
||||
public cards: number[];
|
||||
/**
|
||||
* 已解锁英雄信息
|
||||
*/
|
||||
@prop({ type: Hero, default: new Map() })
|
||||
public heros: Map<string, Hero>;
|
||||
/**
|
||||
* 货币信息
|
||||
* coin: 金币
|
||||
* diamond: 钻石
|
||||
* hero_shard: 通用英雄碎片
|
||||
* hero_exp: 通用英雄经验
|
||||
* hero_shard_heroid: 英雄专用碎片
|
||||
* hero_exp_heroid: 英雄专用经验
|
||||
* card_scroll: 抽卡卷轴
|
||||
*/
|
||||
@prop({ type: Number, default: new Map() })
|
||||
public moneys: Map<string, number>;
|
||||
|
||||
|
||||
/**
|
||||
* 匹配: 胜利场数, 失败场数, 平局场数, 掉线场数
|
||||
*/
|
||||
@prop({type: Number, default: [0,0,0,0]})
|
||||
public normal_stat: number[];
|
||||
/**
|
||||
* 当前赛季: 胜利场数, 失败场数, 平局场数, 掉线场数
|
||||
*/
|
||||
@prop({type: Number, default: [0,0,0,0]})
|
||||
public season_stat: number[];
|
||||
|
||||
/**
|
||||
* 所有未定义的信息, 供扩展
|
||||
*/
|
||||
@prop({type: mongoose.Schema.Types.Mixed})
|
||||
public extinfo: any;
|
||||
|
||||
public toJson() {
|
||||
return {
|
||||
accountid: this._id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export const Account = getModelForClass(AccountClass,
|
||||
// @ts-ignore
|
||||
{existingConnection: AccountClass['db']});
|
146
src/models/User.ts
Normal file
146
src/models/User.ts
Normal file
@ -0,0 +1,146 @@
|
||||
import {
|
||||
prop,
|
||||
getModelForClass,
|
||||
modelOptions,
|
||||
index,
|
||||
plugin,
|
||||
mongoose
|
||||
} from '@typegoose/typegoose';
|
||||
import {dbconn} from '../decorators/dbconn';
|
||||
// @ts-ignore
|
||||
import findOrCreate from 'mongoose-findorcreate';
|
||||
import {
|
||||
Base,
|
||||
FindOrCreate,
|
||||
TimeStamps
|
||||
} from "@typegoose/typegoose/lib/defaultClasses";
|
||||
import {Card} from "./subdoc/Card";
|
||||
import {Hero} from "./subdoc/Hero";
|
||||
import {ZError} from "../common/ZError";
|
||||
import {MoneyTypeConst} from "../constants/MoneyTypeConst";
|
||||
|
||||
interface AccountClass extends Base<string>, TimeStamps {}
|
||||
@dbconn()
|
||||
// @index({ _id: 1}, { unique: true })
|
||||
@plugin(findOrCreate)
|
||||
@modelOptions({schemaOptions:
|
||||
{collection: "account", timestamps: true}
|
||||
})
|
||||
class UserClass extends FindOrCreate{
|
||||
@prop()
|
||||
public _id: string;
|
||||
|
||||
@prop({default: false})
|
||||
public locked: boolean;
|
||||
@prop()
|
||||
public lockedtime?: number;
|
||||
|
||||
@prop()
|
||||
public comment?: string;
|
||||
@prop()
|
||||
public lastLogin?: Date;
|
||||
/**
|
||||
* 已获得卡牌信息
|
||||
*/
|
||||
@prop({ type: () => [Number] })
|
||||
public cards: number[];
|
||||
/**
|
||||
* 已解锁英雄信息
|
||||
*/
|
||||
@prop({ type: Hero, default: new Map() })
|
||||
public heros: Map<string, Hero>;
|
||||
/**
|
||||
* 货币信息
|
||||
* coin: 金币
|
||||
* diamond: 钻石
|
||||
* hero_shard: 通用英雄碎片
|
||||
* hero_exp: 通用英雄经验
|
||||
* hero_shard_heroid: 英雄专用碎片
|
||||
* hero_exp_heroid: 英雄专用经验
|
||||
* card_scroll: 抽卡卷轴
|
||||
*/
|
||||
@prop({ type: Number, default: new Map() })
|
||||
public moneys: Map<string, number>;
|
||||
|
||||
|
||||
/**
|
||||
* 匹配: 胜利场数, 失败场数, 平局场数, 掉线场数
|
||||
*/
|
||||
@prop({type: Number, default: [0,0,0,0]})
|
||||
public normal_stat: number[];
|
||||
/**
|
||||
* 当前赛季: 胜利场数, 失败场数, 平局场数, 掉线场数
|
||||
*/
|
||||
@prop({type: Number, default: [0,0,0,0]})
|
||||
public season_stat: number[];
|
||||
|
||||
/**
|
||||
* 所有未定义的信息, 供扩展
|
||||
*/
|
||||
@prop({type: mongoose.Schema.Types.Mixed})
|
||||
public extinfo: any;
|
||||
|
||||
public toJson() {
|
||||
return {
|
||||
accountid: this._id,
|
||||
}
|
||||
}
|
||||
|
||||
public async unlockHero(heroid: number) {
|
||||
if (this.heros.has(heroid + '')) {
|
||||
if (!this.heros.get(heroid + '').free) {
|
||||
throw new ZError(102, '你已经解锁了该英雄');
|
||||
}
|
||||
}
|
||||
let money0 = MoneyTypeConst.getHeroShard(heroid);
|
||||
let money1 = MoneyTypeConst.HERO_SHARD;
|
||||
let count0 = this.moneys.has(money0) ? this.moneys.get(money0) : 0;
|
||||
let count1 = this.moneys.has(money1) ? this.moneys.get(money1) : 0;
|
||||
// TODO:: 根据配置获取解锁英雄需要的碎片数量
|
||||
let needCount = 30;
|
||||
if (count0 + count1 < needCount) {
|
||||
throw new ZError(102, '碎片数量不足');
|
||||
}
|
||||
if (count0 > 0) {
|
||||
let rest = needCount - count0;
|
||||
if (rest >= 0) {
|
||||
needCount = rest;
|
||||
this.moneys.set(money0, 0);
|
||||
} else {
|
||||
needCount = 0;
|
||||
this.moneys.set(money0, Math.abs(rest));
|
||||
}
|
||||
}
|
||||
// 上面已经过滤了 count0 + count1 > needcount, 所以这里不需要判断碎片是否足够
|
||||
if (needCount > 0) {
|
||||
count1 = count1 - needCount;
|
||||
this.moneys.set(money1, count1);
|
||||
}
|
||||
let hero = new Hero();
|
||||
hero.heroid = heroid;
|
||||
hero.free = false;
|
||||
hero.level = 1;
|
||||
hero.exp = 0;
|
||||
this.heros.set(heroid + '', hero);
|
||||
return hero;
|
||||
}
|
||||
|
||||
public async tryHero(heroid: number) {
|
||||
if (this.heros.has(heroid + '')) {
|
||||
throw new ZError(102, '你已经解锁了该英雄');
|
||||
}
|
||||
//TODO:: 根据配置查看该英雄是否可使用
|
||||
let hero = new Hero();
|
||||
hero.heroid = heroid;
|
||||
hero.free = true;
|
||||
hero.level = 1;
|
||||
hero.exp = 0;
|
||||
this.heros.set(heroid+'', hero);
|
||||
return hero;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export const User = getModelForClass(UserClass,
|
||||
// @ts-ignore
|
||||
{existingConnection: UserClass['db']});
|
@ -4,7 +4,7 @@ import {
|
||||
FastifyRequest,
|
||||
} from 'fastify';
|
||||
import fastifyPlugin from 'fastify-plugin';
|
||||
import {Account} from '../models/Account';
|
||||
import {User} from '../models/User';
|
||||
import {ZError} from "../common/ZError";
|
||||
|
||||
declare module 'fastify' {
|
||||
@ -41,7 +41,7 @@ const apiAuthPlugin: FastifyPluginAsync = async function(
|
||||
// if (!data || !data.id) {
|
||||
// return reply.send({code: 10, msg: 'need login'});
|
||||
// }
|
||||
let account = await Account.findById(accountid);
|
||||
let account = await User.findById(accountid);
|
||||
if (!account) {
|
||||
return reply.send({code: 5, msg: 'account not found'});
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user