Merge branch 'feature/login'

Conflicts:
	game-server/app/servers/role/handler/heroHandler.ts
	game-server/app/services/redisService.ts
	shared/consts/index.ts
	shared/resource/jsons/dic_zyz_gk_main.json
This commit is contained in:
luying
2021-03-08 11:04:09 +08:00
79 changed files with 3766 additions and 2442 deletions

View File

@@ -62,7 +62,7 @@ app.configure(function() {
}
});
const redisClient = connectRedis(app.get('database').redis);
const redisClient = connectRedis(app.get('database').redis, app.get('database').redispw);
app.set('redis', redisClient);
redLockService.initRedlock(redisClient);
redlockCacheService.init();
@@ -78,7 +78,7 @@ app.configure(function() {
});
// app configuration
app.configure('production|development|alpha|dev', 'connector', function () {
app.configure('production|development|alpha|dev|isbn', 'connector', function () {
app.set('connectorConfig',
{
connector: pinus.connectors.hybridconnector,
@@ -103,7 +103,7 @@ app.configure('production|development|alpha|dev', 'connector', function () {
});
});
app.configure('production|development|alpha|dev', 'gate', function () {
app.configure('production|development|alpha|dev|isbn', 'gate', function () {
app.set('connectorConfig',
{
connector: pinus.connectors.hybridconnector,
@@ -111,7 +111,7 @@ app.configure('production|development|alpha|dev', 'gate', function () {
});
});
app.configure('production|development|alpha|dev', 'gm', function () {
app.configure('production|development|alpha|dev|isbn', 'gm', function () {
app.set('connectorConfig',
{
connector: pinus.connectors.hybridconnector,
@@ -120,7 +120,7 @@ app.configure('production|development|alpha|dev', 'gm', function () {
init();//将gm后台数据加载到gate服
});
app.configure('production|development|alpha|dev', 'systimer', function () {
app.configure('production|development|alpha|dev|isbn', 'systimer', function () {
app.set('connectorConfig',
{
connector: pinus.connectors.hybridconnector,
@@ -154,7 +154,7 @@ export function globalErrorHandler(err: Error, msg: any, resp: any,
}
// app configure
app.configure('production|development|alpha|dev', function () {
app.configure('production|development|alpha|dev|isbn', function () {
app.set(RESERVED.ERROR_HANDLER, errorHandler);
app.set(RESERVED.GLOBAL_ERROR_HANDLER, globalErrorHandler);
app.globalAfter((err: Error, routeRecord: RouteRecord, msg: any, session: FrontendOrBackendSession, resp: any, cb: HandlerCallback) => {

View File

@@ -55,7 +55,7 @@ export class EntryHandler {
await self.app.rpc.connector.connectorRemote.remoteLogin.toServer(connect.sid, role.roleId);
}
let serverName = this.app.getServerId();
await roleLogin(role.roleId, user.userCode, serverName); // 保存在线用户
await roleLogin(role.roleId, user.userCode, serverName, user.pkgName); // 保存在线用户
await session.abind(role.roleId);
session.set('uid', role.roleId);
session.set('roleId', role.roleId);

View File

@@ -138,7 +138,7 @@ export class EquipHandler {
hero.ePlace = ePlace;
await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.EQUIP_BASE);
await calPlayerCeAndSave(HERO_SYSTEM_TYPE.EQUIP_BASE, sid, roleId, hero, { ePlace });
const curHero = {
hid,
ePlace: strengthenArr
@@ -197,7 +197,7 @@ export class EquipHandler {
hero.ePlace = ePlace;
await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.EQUIP_BASE);
await calPlayerCeAndSave(HERO_SYSTEM_TYPE.EQUIP_BASE, sid, roleId, hero, { ePlace });
const curHero = {
hid,
ePlace: strengthenArr
@@ -261,7 +261,7 @@ export class EquipHandler {
let result = await handleCost(roleId, sid, cost);
if (!result) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH);
await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.EQUIP_BASE);
await calPlayerCeAndSave(HERO_SYSTEM_TYPE.EQUIP_BASE, sid, roleId, hero, { ePlace });
const curHero = {
hid,
@@ -381,7 +381,7 @@ export class EquipHandler {
// 更新战力
const hero = await HeroModel.findByHidAndRoleWithEquip(hid, roleId);
await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.RESTRENGTHEN, [ePlaceId, ...removeSeidList]);
await calPlayerCeAndSave(HERO_SYSTEM_TYPE.RESTRENGTHEN, sid, roleId, hero, {}, [ePlaceId, ...removeSeidList]);
return resResult(STATUS.SUCCESS,{curEquip});
@@ -448,7 +448,7 @@ export class EquipHandler {
} else if (type == 2) {
if (!equip.hid)
return resResult(STATUS.EQUIP_NOT_EQUIPED);
let curEquip = await takeOffEquipAndCalPlayerCe(roleId, sid, equip.seqId, hero, id)
let curEquip = await takeOffEquipAndCalPlayerCe(roleId, sid, hero, equip, id)
curEquips.push(curEquip);
}
return resResult(STATUS.SUCCESS, { curEquips: curEquips });
@@ -513,7 +513,7 @@ export class EquipHandler {
await addItems(roleId, roleName, sid, goods);
if (!!equip.hid) {
let hero = await HeroModel.findByHidAndRole(equip.hid, roleId);
await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.JEWEL_ON, [jewel, oldJewel]);
await calPlayerCeAndSave(HERO_SYSTEM_TYPE.JEWEL_ON, sid, roleId, hero, {}, [jewel, oldJewel]);
}
return resResult(STATUS.SUCCESS, { curEquip: { seqId: eid, holes: equip.holes } });
}
@@ -560,7 +560,7 @@ export class EquipHandler {
await addItems(roleId, roleName, sid, goods);
if (!!equip.hid) {
let hero = await HeroModel.findByHidAndRole(equip.hid, roleId);
await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.JEWEL_OFF, [jewel]);
await calPlayerCeAndSave(HERO_SYSTEM_TYPE.JEWEL_OFF, sid, roleId, hero, {}, [jewel]);
}
return resResult(STATUS.SUCCESS, { curEquip: { seqId: eid, holes: equip.holes } });
}
@@ -651,7 +651,7 @@ export class EquipHandler {
await EquipModel.updateEquipInfo(eid, { holes: equip.holes });
if (!!equip.hid) {
let hero = await HeroModel.findByHidAndRole(equip.hid, roleId);
await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.JEWEL_ON, [jewel, oldJewel]);
await calPlayerCeAndSave(HERO_SYSTEM_TYPE.JEWEL_ON, sid, roleId, hero, {}, [jewel, oldJewel]);
}
return resResult(STATUS.SUCCESS, { curEquip: { seqId: eid, holes: equip.holes } });
} else {

View File

@@ -681,12 +681,12 @@ export class FriendHandler {
if(heroList.length <= 0) return resResult(STATUS.HERO_NOT_FIND);
let list = new Array();
for(let {roleId, roleName, hid, hName, ce, lv, star, colorStar, quality, job, skins, ceAttr} of heroList) {
for(let {roleId, roleName, hid, hName, ce, lv, star, colorStar, quality, job, skins, attr: heroAttrs} of heroList) {
let curSkin = skins.find(cur => cur.enable);
let equips = await EquipModel.findListByHidAndRole(hisRoleId, hid, EQUIP_SELECT.HERO_DETAIL);
let attributes = getPlayerMainAttribute(ceAttr, role.globalCeAttr);
let attributes = getPlayerMainAttribute(heroAttrs, role.attr);
list.push({
roleId, roleName, hid, hName, ce, lv, star, colorStar, quality, job,

View File

@@ -1,9 +1,9 @@
import {Application, BackendSession, ChannelService} from 'pinus';
import { handleCost, addItems } from '../../../services/rewardService';
import { calPlayerCeAndSave } from '../../../services/playerCeService';
import { resResult, returnHeroCeRatio } from '../../../pubUtils/util';
import { calPlayerCeAndSave, calAllHeroCe } from '../../../services/playerCeService';
import { resResult, returnHeroCeRatio, deepCopy } from '../../../pubUtils/util';
import { STATUS } from '../../../consts/statusCode';
import {HeroModel} from '../../../db/Hero';
import { HeroModel, Connect } from '../../../db/Hero';
import {CURRENCY_BY_TYPE, CURRENCY_TYPE, CONSUME_TYPE, HERO_GROW_MAX, HERO_SYSTEM_TYPE, ITID, ABI_STAGE, HERO_CE_RATIO} from '../../../consts';
import { RoleModel } from '../../../db/Role';
import { ItemModel } from '../../../db/Item';
@@ -12,6 +12,8 @@ import { RewardInter } from '../../../pubUtils/interface';
import { getDropItems } from '../../../consts/constModules/itemConst'
import { getRoleOnlineInfo, getAllOnlineRoles } from '../../../services/redisService';
import { pushHeroQualityUpMsg } from '../../../services/chatService';
import { CeAttrDataRole, CeAttrData } from '../../../domain/roleField/attribute';
export default function(app: Application) {
return new HeroHandler(app);
}
@@ -81,8 +83,9 @@ export class HeroHandler {
let curHero = await HeroModel.createHero({
roleId, serverId, roleName, hid, hName, star, quality, job, skins:[{id: initialSkin, enable: true}]
});
await calPlayerCeAndSave(sid, roleId, [curHero], HERO_SYSTEM_TYPE.INIT);
return resResult(STATUS.SUCCESS, {curHero: returnHeroCeRatio(curHero)});
let hero = await calPlayerCeAndSave(HERO_SYSTEM_TYPE.INIT, sid, roleId, curHero, {});
await calAllHeroCe(HERO_SYSTEM_TYPE.ADD_SKIN, sid, roleId, {}, [initialSkin])
return resResult(STATUS.SUCCESS, {curHero: returnHeroCeRatio(hero)});
}
// 武将升级
@@ -138,12 +141,14 @@ export class HeroHandler {
let costResult = await handleCost(roleId, sid, material);
if(!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH);
hero.lv = playerLv > newLv?newLv: playerLv;
hero.exp = newExp;
let update = {
lv: playerLv > newLv?newLv: playerLv,
exp: newExp
}
let heros = await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.LVUP, [hid]);
hero = await calPlayerCeAndSave(HERO_SYSTEM_TYPE.LVUP, sid, roleId, hero, update);
const curHero = {
hid, lv : heros[0].lv, exp : heros[0].exp
hid, lv : hero.lv, exp : hero.exp
}
return resResult(STATUS.SUCCESS, { curHero });
@@ -178,16 +183,20 @@ export class HeroHandler {
if(!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH);
let isUpStar = oldStarStage + 1 == ABI_STAGE.END;
hero.star = isUpStar? oldStar + 1: oldStar;
hero.starStage = isUpStar? ABI_STAGE.START: oldStarStage + 1;
let heros = await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.STAR, [hid, isUpStar?1:0]);
let update = {
star: isUpStar? oldStar + 1: oldStar,
starStage: isUpStar? ABI_STAGE.START: oldStarStage + 1
}
hero = await calPlayerCeAndSave(HERO_SYSTEM_TYPE.STAR, sid, roleId, hero, update);
if(isUpStar) await calAllHeroCe(HERO_SYSTEM_TYPE.STAR, sid, roleId, {}, [hid, isUpStar?1:0]); // 升星可能影响到百家学院全局加成
const curHero = {
hid,
star : heros[0].star,
starStage : heros[0].starStage,
colorStar: heros[0].colorStar,
colorStarStage: heros[0].colorStarStage
star : hero.star,
starStage : hero.starStage,
colorStar: hero.colorStar,
colorStarStage: hero.colorStarStage
}
return resResult(STATUS.SUCCESS, {isUpStar, curHero});
}
@@ -226,11 +235,14 @@ export class HeroHandler {
let costResult = await handleCost(roleId, sid, [{id: pieceId, count: fragmentNum}]);
if(!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH);
hero.quality ++;
let heros = await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.QUALITY, [hid]);
hero = await calPlayerCeAndSave(HERO_SYSTEM_TYPE.QUALITY, sid, roleId, hero, {
quality: hero.quality + 1
});
await calAllHeroCe(HERO_SYSTEM_TYPE.QUALITY, sid, roleId, {}, [hid, 0]); // 升品可能影响到百家学院全局加成
const curHero = {
hid,
quality : heros[0].quality
quality : hero.quality
}
pushHeroQualityUpMsg(roleId, roleName, serverId, hero);
return resResult(STATUS.SUCCESS, {curHero});
@@ -273,16 +285,21 @@ export class HeroHandler {
let isWakeUp = oldColorStar == 0;
let isUpStar = isWakeUp || oldColorStarStage + 1 == ABI_STAGE.END;
hero.colorStar = isUpStar? oldColorStar + 1: oldColorStar;
hero.colorStarStage = isUpStar? ABI_STAGE.START: oldColorStarStage + 1;
let heros = await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.COLORSTAR, [hid, isUpStar?1:0, isWakeUp?1:0]);
let update = {
colorStar: isUpStar? oldColorStar + 1: oldColorStar,
colorStarStage: isUpStar? ABI_STAGE.START: oldColorStarStage + 1
}
hero = await calPlayerCeAndSave(HERO_SYSTEM_TYPE.COLORSTAR, sid, roleId, hero, update);
if(isUpStar) await calAllHeroCe(HERO_SYSTEM_TYPE.COLORSTAR, sid, roleId, {}, [hid, isUpStar?1:0]); // 升星可能影响到百家学院全局加成
const curHero = {
hid,
star : heros[0].star,
starStage : heros[0].starStage,
colorStar: heros[0].colorStar,
colorStarStage: heros[0].colorStarStage
star : hero.star,
starStage : hero.starStage,
colorStar: hero.colorStar,
colorStarStage: hero.colorStarStage
}
return resResult(STATUS.SUCCESS, {isUpStar, curHero});
}
@@ -293,26 +310,30 @@ export class HeroHandler {
let sid: string = session.get('sid');
let { hid } = msg;
let hero = await HeroModel.findByHidAndRole(hid, roleId);
if (!hero)
return resResult(STATUS.HERO_NOT_FIND);
let heroJob = gameData.job.get(hero.job);
if (hero.jobStage >= 6)
if (!hero) return resResult(STATUS.HERO_NOT_FIND);
let dicJob = gameData.job.get(hero.job);
if(!dicJob) return resResult(STATUS.DIC_DATA_NOT_FOUND);
if (hero.jobStage >= ABI_STAGE.END)
return resResult(STATUS.HERO_JOB_STAGE_REACH_MAX_STAGE);
if (hero.job >= getMaxGradeByjobClass(heroJob.job_class))
if (hero.job >= getMaxGradeByjobClass(dicJob.job_class))
return resResult(STATUS.HERO_JOB_REACH_MAX_STAGE);
let consume = new Array<RewardInter>();
if(heroJob.trainingConsume[hero.jobStage]) {
consume.push(heroJob.trainingConsume[hero.jobStage]);
if(dicJob.trainingConsume[hero.jobStage]) {
consume.push(dicJob.trainingConsume[hero.jobStage]);
}
let result = await handleCost(roleId, sid, consume);
if(!result) {
return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH);
}
hero.jobStage = hero.jobStage +1;
//重算战力并下发
let heros = await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.TRAIN);
return resResult(STATUS.SUCCESS, { curHero: {hid : heros[0].hid, job : heros[0].job, jobStage: heros[0].jobStage}});
hero = await calPlayerCeAndSave(HERO_SYSTEM_TYPE.TRAIN, sid, roleId, hero, {
jobStage: hero.jobStage + 1
});
return resResult(STATUS.SUCCESS, { curHero: {hid : hero.hid, job : hero.job, jobStage: hero.jobStage}});
}
//进阶
@@ -334,27 +355,30 @@ export class HeroHandler {
return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH);
}
let nextHeroJob = getJobByGradeAndClass(heroJob.job_class, heroJob.grade + 1);
hero.job = nextHeroJob.jobid;
hero.jobStage = 0;
//重算战力并下发
let heros = await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.STAGEUP, [curJob]);
return resResult(STATUS.SUCCESS, { curHero: {hid : heros[0].hid, job : heros[0].job, jobStage : heros[0].jobStage}});
let update = {
job: nextHeroJob.jobid,
jobStage: 0
}
hero = await calPlayerCeAndSave(HERO_SYSTEM_TYPE.STAGEUP, sid, roleId, hero, update);
return resResult(STATUS.SUCCESS, { curHero: {hid : hero.hid, job : hero.job, jobStage : hero.jobStage}});
}
//激活羁绊
async heroConectionActivate(msg: {shipId: number}, session: BackendSession) {
async heroConectionActivate(msg: { shipId: number }, session: BackendSession) {
let roleId: string = session.get('roleId');
let sid: string = session.get('sid');
let { shipId } = msg;
let shipHidAndLevel = gameData.friendShipHidAandIds.get(shipId);
if (!shipHidAndLevel)
return resResult(STATUS.HERO_CONECTION_IS_NOT_EXIT);
if (!shipHidAndLevel) return resResult(STATUS.HERO_CONECTION_IS_NOT_EXIT);
let hero = await HeroModel.findByHidAndRole(shipHidAndLevel.actorId, roleId);
if (!hero)
return resResult(STATUS.HERO_NOT_FIND);
if (!hero) return resResult(STATUS.HERO_NOT_FIND);
let heroConnections: Connect[] = deepCopy(hero.connections);
let flag = true;
let level = 1;
for (let conection of hero.connections) {
for (let conection of heroConnections) {
if (conection.shipId == shipId ) {
if (conection.level >= shipHidAndLevel.level) {
return resResult(STATUS.HERO_CONECTION_IS_MAX_LEVEL);
@@ -366,7 +390,7 @@ export class HeroHandler {
}
}
if (!!flag) {
hero.connections.push({shipId, level});
heroConnections.push({shipId, level});
}
let friendShip = getFriendShipById(shipId, level);
if (hero.star < friendShip.level)
@@ -386,8 +410,8 @@ export class HeroHandler {
return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH);
}
//重算战力并下发
let heros = await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.CONNECT, [shipId, level]);
return resResult(STATUS.SUCCESS, { curHero: {hid : heros[0].hid, connections : heros[0].connections}});
hero = await calPlayerCeAndSave(HERO_SYSTEM_TYPE.CONNECT, sid, roleId, hero, { connections: heroConnections }, [shipId]);
return resResult(STATUS.SUCCESS, { curHero: {hid : hero.hid, connections : hero.connections}});
}
//赠送(包括一键赠送)
@@ -445,8 +469,6 @@ export class HeroHandler {
}
let newLv = getFavourLvByExp(newExp);
hero.favour = newExp;
hero.favourLv = newLv;
let result = await handleCost(roleId, sid, material);
if(!result) {
@@ -454,11 +476,13 @@ export class HeroHandler {
}
//重算战力并下发
if (oldLv != hero.favourLv) {
await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.FAVOUR, [oldLv]);
await calPlayerCeAndSave(HERO_SYSTEM_TYPE.FAVOUR, sid, roleId, hero, {
favour: newExp, favourLv: newLv
}, [oldLv]);
} else {
await HeroModel.updateHeroInfo(roleId, hero.hid, hero);
}
return resResult(STATUS.SUCCESS, { curHero: {hid : hero.hid, favour : hero.favour, favourLv : hero.favourLv}});
return resResult(STATUS.SUCCESS, { curHero: { hid: hero.hid, favour: hero.favour, favourLv: hero.favourLv } });
}
//穿带时装
@@ -467,14 +491,15 @@ export class HeroHandler {
let sid: string = session.get('sid');
let { id } = msg;
let skinInfo = gameData.fashion.get(id);
if (!skinInfo)
return resResult(STATUS.HERO_SKIN_NOT_FIND);
if (!skinInfo) return resResult(STATUS.HERO_SKIN_NOT_FIND);
let hero = await HeroModel.findByHidAndRole(skinInfo.actorId, roleId);
if (!hero)
return resResult(STATUS.HERO_NOT_FIND);
if (!hero) return resResult(STATUS.HERO_NOT_FIND);
let heroSkins = deepCopy(hero.skins);
let result = false;
let lastSkinId: number;
for (let skin of hero.skins) {
for (let skin of heroSkins) {
if (skin.id == id) {
if (!!skin.enable) {
return resResult(STATUS.HERO_SKIN_IS_EQUIPED);
@@ -491,7 +516,7 @@ export class HeroHandler {
if (!result) {
return resResult(STATUS.HERO_SKIN_NOT_FIND);
}
await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.SKIN, [id, lastSkinId]);
await calPlayerCeAndSave(HERO_SYSTEM_TYPE.SKIN, sid, roleId, hero, { skins: heroSkins }, [id, lastSkinId]);
return resResult(STATUS.SUCCESS, {curHero: {hid : hero.hid, skins : hero.skins} });
}
}

View File

@@ -1,12 +1,12 @@
import { STATUS } from '../../../consts/statusCode';
import { RoleModel } from './../../../db/Role';
import { HeroModel } from '../../../db/Hero';
import { resResult, decodeIdCntArrayStr, parseGoodStr, reduceCe } from '../../../pubUtils/util';
import {Application, BackendSession} from 'pinus';
import { resResult, decodeIdCntArrayStr, parseGoodStr } from '../../../pubUtils/util';
import {Application, BackendSession, pinus} from 'pinus';
import { handleCost } from '../../../services/rewardService';
import { getTitle, getTeraph, gameData, getScollByStar, getFriendLvByExp } from '../../../pubUtils/data';
import { SCHOOL, SCROLL } from '../../../pubUtils/dicParam';
import { getTeraphAttr, getAtrrNameById } from '../../../consts/constModules/abilityConst'
import { getAtrrNameById } from '../../../consts/constModules/abilityConst'
import { findIndex } from 'underscore';
import { SclResultInter, SclPosInter } from '../../../pubUtils/interface';
import { SchoolModel } from '../../../db/School';
@@ -79,11 +79,12 @@ export class RoleHandler {
//爵位
async roleTitleLevelUp(msg: {}, session: BackendSession){
let roleId = session.get('roleId');
let role = await RoleModel.findByRoleId(roleId);
let oldCe = role.ce;
let sid: string = session.get('sid');
let title = ++role.title;
let titleInfo = getTitle(role.title);
let role = await RoleModel.findByRoleId(roleId);
let { title } = role;
let titleInfo = getTitle(title + 1);
if (!titleInfo)
return resResult(STATUS.DIC_DATA_NOT_FOUND)
if (titleInfo.lvLimited > role.lv)
@@ -92,44 +93,47 @@ export class RoleHandler {
let result = await handleCost(roleId, sid, consumes);
if (!result)
return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH);
await RoleModel.updateRoleInfo(roleId, { title });
let {ce} = await calAllHeroCe( sid, roleId, HERO_SYSTEM_TYPE.TITLE, [title]);
return resResult(STATUS.SUCCESS, { roleId, title });
let update = { title: title + 1 }
role = await calAllHeroCe(HERO_SYSTEM_TYPE.TITLE, sid, roleId, update);
return resResult(STATUS.SUCCESS, { roleId, title: role.title });
}
//神像强化
async roleTeraphStrengthen(msg: {id: number, count: number}, session: BackendSession){
let {id, count} = msg;
let roleId = session.get('roleId');
let role = await RoleModel.findByRoleId(roleId);
let sid: string = session.get('sid');
let index = findIndex(role.teraphs, {id});
let role = await RoleModel.findByRoleId(roleId);
let teraphs = role.teraphs;
let index = findIndex(teraphs, {id});
if (index < 0)
return resResult(STATUS.WRONG_PARMS);
let teraph = role.teraphs[index];
let teraphInfo = getTeraph(id, teraph.grade);
if (!teraphInfo)
return resResult(STATUS.DIC_DATA_NOT_FOUND)
let attrs = [];
for (let attrName in getTeraphAttr()) {
let attrNameMax = attrName+'Max';
if (teraph[attrName] < teraphInfo[attrNameMax]) {
attrs.push(attrName);
let teraph = teraphs[index];
let dicTeraph = getTeraph(id, teraph.grade);
if (!dicTeraph)
return resResult(STATUS.DIC_DATA_NOT_FOUND);
let attrs = new Array<number>(); // 可以强化的属性
dicTeraph.mainAttrMax.forEach(( max, id) => {
let attrName = getAtrrNameById(id);
if (teraph[attrName] < max) {
attrs.push(id);
}
}
});
if (!attrs.length)
return resResult(STATUS.ROLE_TERAPH_NOT_STRENGTHEN);
// 随机神像中的一条属性并检查道具是否足够
let {attr, consumes} = checkTeraphMaterialEnough(count, attrs, teraphInfo, teraph);
for (let key in attr) {
teraph[key] += attr[key];
role.globalCeAttr[key].fixUp += attr[key];
}
// 随机神像中的一条属性并检查道具是否足够以及更新teraph
let { consumes} = checkTeraphMaterialEnough(count, attrs, dicTeraph, teraph);
let result = await handleCost(roleId, sid, consumes);
if (!result)
return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH);
await RoleModel.updateRoleInfo(roleId, { teraphs: role.teraphs, globalCeAttr: role.globalCeAttr});
await calAllHeroCe( sid, roleId);
role = await calAllHeroCe(HERO_SYSTEM_TYPE.TERAPH, sid, roleId, { teraphs }, [id]);
return resResult(STATUS.SUCCESS, { roleId, teraphs: role.teraphs });
}
@@ -137,34 +141,37 @@ export class RoleHandler {
async roleTeraphQualityUp(msg: {id: number}, session: BackendSession){
let {id} = msg;
let roleId = session.get('roleId');
let role = await RoleModel.findByRoleId(roleId);
let sid: string = session.get('sid');
let index = findIndex(role.teraphs, {id});
let role = await RoleModel.findByRoleId(roleId);
let teraphs = role.teraphs;
let index = findIndex(teraphs, {id});
if (index < 0)
return resResult(STATUS.WRONG_PARMS);
let teraph = role.teraphs[index];
let teraph = teraphs[index];
let teraphInfo = getTeraph(id, teraph.grade);
if (!teraphInfo)
return resResult(STATUS.DIC_DATA_NOT_FOUND)
for (let attrName in getTeraphAttr()) {
if (teraph[attrName] != teraphInfo[attrName +'Max'])
for(let [attrId, val] of teraph.attr) {
if (val < teraphInfo.mainAttrMax.get(attrId))
return resResult(STATUS.ROLE_TERAPH_NOT_QUILITY);
teraph[attrName] = 0;
teraph.attr.set(attrId, 0);
}
teraph.grade++;
teraph.grade ++;
let nextTeraphInfo = getTeraph(id, teraph.grade)
if (!nextTeraphInfo)
return resResult(STATUS.DIC_DATA_NOT_FOUND)
return resResult(STATUS.DIC_DATA_NOT_FOUND);
let consumes = teraphInfo.upGradeMaterial;
let result = await handleCost(roleId, sid, consumes);
if (!result)
return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH);
for (let {id, number} of nextTeraphInfo.assiAttrValue) {
let attrName = getAtrrNameById(id);
role.globalCeAttr[attrName].ratioUp += number;
}
await RoleModel.updateRoleInfo(roleId, { teraphs: role.teraphs, globalCeAttr: role.globalCeAttr});
await calAllHeroCe(sid, roleId);
role = await calAllHeroCe(HERO_SYSTEM_TYPE.TERAPH_UP, sid, roleId, { teraphs }, [id]);
return resResult(STATUS.SUCCESS, { roleId, teraphs: role.teraphs });
}
@@ -246,7 +253,7 @@ export class RoleHandler {
}
await SchoolModel.updateBySclAndPos(roleId, schoolId, positionId, { hid, isOpen })
await calPlayerCeAndSave(sid, roleId, [], HERO_SYSTEM_TYPE.SCHOOL, [schoolId, hid, preHid]);
await calAllHeroCe(HERO_SYSTEM_TYPE.SCHOOL, sid, roleId, {}, [schoolId, hid, preHid]);
return resResult(STATUS.SUCCESS, {
schoolId, positionId, hid, preHid, isOpen
@@ -294,7 +301,7 @@ export class RoleHandler {
let { hid } = msg;
let curHero = await HeroModel.findByHidAndRole(hid, roleId, 'star colorStar quality scrollId scrollActive scrollStar scrollColorStar scrollQuality favour favourLv');
let curHero = await HeroModel.findByHidAndRole(hid, roleId, 'hid star colorStar quality scrollId scrollActive scrollStar scrollColorStar scrollQuality favour favourLv connections attr ce');
if (!curHero) return resResult(STATUS.HERO_NOT_FIND);
let dicHero = gameData.hero.get(hid);
@@ -334,12 +341,67 @@ export class RoleHandler {
let dicHeroScroll = getScollByStar(dicHero.quality, update.scrollStar, update.scrollQuality, update.scrollColorStar);
update.scrollId = dicHeroScroll?dicHeroScroll.id: 0;
curHero = await HeroModel.updateHeroInfo(roleId, hid, update, 'hid scrollActive scrollId scrollStar scrollColorStar scrollQuality favour favourLv');
await calPlayerCeAndSave(sid, roleId, [], HERO_SYSTEM_TYPE.SCROLL, [hid, favourLv]);
let hero = await calPlayerCeAndSave(HERO_SYSTEM_TYPE.SCROLL, sid, roleId, curHero, update); // 更新单个武将战力
calAllHeroCe(HERO_SYSTEM_TYPE.SCROLL, sid, roleId, {}, [hid]); // 全局增加战力
return resResult(STATUS.SUCCESS, {
curHero
curHero: {
hid: hero.hid,
scrollActive: hero.scrollActive,
scrollId: hero.scrollId,
scrollStar: hero.scrollStar,
scrollColorStar: hero.scrollColorStar,
scrollQuality: hero.scrollQuality,
favour: hero.favour,
favourLv: hero.favourLv,
}
});
}
async debugPlayerTime(msg: { type: number }, session: BackendSession) {
let { type } = msg;
let roleId = session.get('roleId');
let sid = session.get('sid');
if(type == 1) {
pinus.app.channelService.pushMessageByUids('onPlayTime', resResult(STATUS.SUCCESS, {
isGuest: true,
guestTime: 60 * 60, // 游客已体验时间
hasAuthenticated: false, // 是否进行过实名认证
isAdult: false, // 是否已成年
todayPlayTime: 60 * 60, // 今天已游戏时长
type: 1
} ), [{uid: roleId, sid: sid}]);
} else if (type == 2) {
pinus.app.channelService.pushMessageByUids('onPlayTime', resResult(STATUS.SUCCESS, {
isGuest: false,
guestTime: 0, // 游客已体验时间
hasAuthenticated: true, // 是否进行过实名认证
isAdult: false, // 是否已成年
todayPlayTime: 60 * 60, // 今天已游戏时长
type: 2
} ), [{uid: roleId, sid: sid}]);
} else if (type == 3) {
pinus.app.channelService.pushMessageByUids('onPlayTime', resResult(STATUS.SUCCESS, {
isGuest: false,
guestTime: 0, // 游客已体验时间
hasAuthenticated: true, // 是否进行过实名认证
isAdult: false, // 是否已成年
todayPlayTime: 3 * 60 * 60, // 今天已游戏时长
type: 3
} ), [{uid: roleId, sid: sid}]);
} else if (type == 4) {
pinus.app.channelService.pushMessageByUids('onPlayTime', resResult(STATUS.SUCCESS, {
isGuest: false,
guestTime: 0, // 游客已体验时间
hasAuthenticated: true, // 是否进行过实名认证
isAdult: false, // 是否已成年
todayPlayTime: 1.5 * 60 * 60, // 今天已游戏时长
type: 4
} ), [{uid: roleId, sid: sid}]);
}
return resResult(STATUS.SUCCESS);
}
}

View File

@@ -1,6 +1,6 @@
import { HeroModel } from './../db/Hero';
import { HangUpRecordModel } from './../db/HangUpRecord';
import { ChannelService, pinus } from 'pinus';
import { pinus } from 'pinus';
import { HANG_UP_CONSTS, TOWER_TASK_CONST, REDIS_KEY } from './../consts';
import { BattleRecordModel } from './../db/BattleRecord';
import { TowerRecordModel } from './../db/TowerRecord';

View File

@@ -1,4 +1,4 @@
import { mergeSameGoods } from '../pubUtils/util';
import { mergeSameGoods, deepCopy } from '../pubUtils/util';
import { EquipModel } from "../db/Equip";
import { HeroModel, EPlace, HeroType } from "../db/Hero";
import { getHeroJob, getGoodById, gameData, getJewelById, getHeroEquipByClassId } from "../pubUtils/data";
@@ -77,7 +77,7 @@ export async function changeEquip(roleId: string, sid: string, equip: EquipType,
return res;
}
} else if (!!hero) {//从穿戴装备的武将上卸下装备
await takeOffEquipAndCalPlayerCe(roleId, sid, seqId, hero, id);//卸下装备并重算战力
await takeOffEquipAndCalPlayerCe(roleId, sid, hero, equip, id);//卸下装备并重算战力
}
}
/**
@@ -88,15 +88,12 @@ export async function changeEquip(roleId: string, sid: string, equip: EquipType,
* @param hero
* @param id
*/
export async function takeOffEquipAndCalPlayerCe(roleId: string, sid: string, seqId: number, hero:HeroType, id: number ) {
let index = findIndex(hero.ePlace, { id });
if (index < 0)
return;
await EquipModel.updateEquipInfo(seqId, { hid: 0 });
hero.ePlace[index].equip = null;
export async function takeOffEquipAndCalPlayerCe(roleId: string, sid: string, hero:HeroType, equip: EquipType, id: number ) {
let args = calEquipSeids(hero);
await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.EQUIP, args);
return { seqId, hid: 0};
hero = await HeroModel.removeEquip(roleId, hero.hid, id, equip._id);
await calPlayerCeAndSave(HERO_SYSTEM_TYPE.EQUIP, sid, roleId, hero, {}, args);
return { seqId: equip.seqId, hid: 0};
}
/**
* 穿戴装备并重算战力
@@ -106,9 +103,10 @@ export async function takeOffEquipAndCalPlayerCe(roleId: string, sid: string, se
* @param equip
*/
export async function dressEquip(roleId: string, sid: string, hero:HeroType, equip: EquipType) {
hero = await HeroModel.addEquip(roleId, hero.hid, equip.ePlaceId, equip._id);
let args = calEquipSeids(hero);
await calPlayerCeAndSave(sid, roleId, [hero], HERO_SYSTEM_TYPE.EQUIP, args);
hero = await HeroModel.addEquip(roleId, hero.hid, equip.ePlaceId, equip._id);
await calPlayerCeAndSave(HERO_SYSTEM_TYPE.EQUIP, sid, roleId, hero, {}, args);
return { seqId: equip.seqId, hid: hero.hid };
}
/**

View File

@@ -3,9 +3,9 @@ import { ExpeditionPointModel } from '../db/ExpeditionPoint';
import Role, { RoleModel, RoleType } from '../db/Role';
import { PvpDefenseModel } from '../db/PvpDefense';
import { getWarJsons, getGamedata, getExpeditionById } from '../pubUtils/gamedata';
import { decodeStr, resResult, shouldRefresh } from '../pubUtils/util';
import { EXPEDITION_CONST, HERO_CE_RATIO, getAttrCeRatio } from '../consts';
import { getWarJsons, getGamedata } from '../pubUtils/gamedata';
import { decodeStr, shouldRefresh } from '../pubUtils/util';
import { EXPEDITION_CONST, HERO_CE_RATIO } from '../consts';
import { getAtrrNameById} from '../consts';
import { ExpeditionWarRecordModel } from '../db/ExpeditionWarRecord';
import { HeroType } from '../db/Hero';
@@ -75,7 +75,7 @@ export async function matchPlayers(roleId: string, scale: number, range: number,
let result = resultRange[index];
let {roleId, heroes, defCe } = result;
let role = <RoleType>result.role;
let { globalCeAttr } = role;
let { attr: roleAttrs } = role;
enemyObj.enemyFrom = 1;
enemyObj.enemyId = roleId;
@@ -87,9 +87,9 @@ export async function matchPlayers(roleId: string, scale: number, range: number,
let hero = heroes[heroIndex];
if(hero) {
let h = <HeroType>hero.hero;
let { star, lv, ceAttr } = h;
let { star, lv, attr: heroAttrs } = h;
let dicHero = gameData.hero.get(hero.actorId);
let newAttribute = getPlayerAttribute(ceAttr, globalCeAttr);
let newAttribute = getPlayerAttribute(heroAttrs, roleAttrs);
let heroInfo = {
actorId: hero.actorId,
actorName: dicHero.name,
@@ -127,10 +127,7 @@ export async function matchRobots(scale: number, myCe: number, robotCe: number,
const { attribute } = json;
let newAttribute = getRobotAttribute(attribute, myCe, robotCe, scale);
let ce = 0;
for(let attrName in newAttribute) {
ce += newAttribute[attrName] * getAttrCeRatio(attrName)||0;
}
let ce = newAttribute.calCelAndReduce();
enemyObj.enemies.push({...json, attribute: newAttribute, lv});
allCe += ce;
}
@@ -156,21 +153,6 @@ export async function getCEScaleAndRange(roleId: string, curDicExpedition: any)
return {scale, range, lv: role.lv}
}
// 远征表属性解码
export function decodeWarJsonAttribute(attribute: string) {
let arr = decodeStr('attribute', attribute);
// 初始化
let obj = {hp: 0, atk: 0, matk: 0, def: 0, mdef: 0, speed: 0, agi: 0, luk: 0, hit: 0, cri: 0, flee: 0, antCri: 0, damageIncrease: 0, damageDecrease: 0, defIngnore: 0, bloodSuck: 0}
for(let {id, value} of arr) {
let field = getAtrrNameById(id);
if(field) {
obj[field] = value;
}
}
return obj
}
// 远征累计点数获取
export async function getPointRewardStatus(roleId: string, role?: Role) {
if(!role) {

View File

@@ -7,22 +7,26 @@ import { STATUS } from '../consts/statusCode';
import { resResult, reduceCe } from '../pubUtils/util';
import { calPlayerCeAndSave as pubCalPlayerCeAndSave, reCalAllHeroCe } from '../pubUtils/playerCe';
import { HeroType } from '../db/Hero';
import Hero, { HeroType, HeroUpdate } from '../db/Hero';
import { defaultHeroes } from './pvpService';
import { RoleUpdate } from '../db/Role';
//修改并下发战力
export async function calPlayerCeAndSave(sid: string, roleId: string, heros: Array<HeroType>, type?: number, args?: Array<number>) {
let {role, pushHeros, topLineupCe} = await pubCalPlayerCeAndSave(roleId, heros, type, args);
export async function calPlayerCeAndSave(type: number, sid: string, roleId: string, originHero: HeroType, update: HeroUpdate, args?: Array<number>) {
let {role, pushHeros, topLineupCe, hero} = await pubCalPlayerCeAndSave(type, roleId, originHero, update, args);
console.log(JSON.stringify(pushHeros))
//下发战力
let uids = [{ uid: roleId, sid }];
pinus.app.get('channelService').pushMessageByUids('onPlayerCeUpdate', resResult(STATUS.SUCCESS, { ce: reduceCe(role.ce) , heros: pushHeros, topLineupCe: reduceCe(topLineupCe) }), uids);
defaultHeroes(role);
return heros;
return hero;
}
export async function calAllHeroCe(sid: string, roleId: string, type?:number, args?:Array<number>) {
let {ce, pushHeros, topLineupCe }= await reCalAllHeroCe(roleId, type, args);
let uids = [{ uid: roleId, sid }];
pinus.app.get('channelService').pushMessageByUids('onPlayerCeUpdate', resResult(STATUS.SUCCESS, { ce: reduceCe(ce), heros: pushHeros, topLineupCe: reduceCe(topLineupCe) }), uids);
return {ce: reduceCe(ce)};
export async function calAllHeroCe(type:number, sid: string, roleId: string, update: RoleUpdate, args?:Array<number>) {
let {role, ce, pushHeros, topLineupCe } = await reCalAllHeroCe(type, roleId, update, args);
if(pushHeros.length > 0) {
let uids = [{ uid: roleId, sid }];
pinus.app.get('channelService').pushMessageByUids('onPlayerCeUpdate', resResult(STATUS.SUCCESS, { ce: reduceCe(ce), heros: pushHeros, topLineupCe: reduceCe(topLineupCe) }), uids);
}
return role;
}

View File

@@ -5,7 +5,7 @@ import { PVP_HERO_POS, ROBOT_NAME, REDIS_KEY, PVP_CONST, HERO_CE_RATIO } from '.
import { setPvpDefResult } from '../services/timeTaskService';
import { dicPvpOpponent, DicPvpOpponent } from "../pubUtils/dictionary/DicPvpOpponent";
import { getRandomIndexByLen, genCode, getRandomByLen, shouldRefresh, reduceCe, getChineseName } from '../pubUtils/util';
import { oppPlayersInter, pvpEndParamInter, Attributes } from '../pubUtils/interface';
import { oppPlayersInter, pvpEndParamInter } from '../pubUtils/interface';
import { RankParam } from '../domain/rank';
import { gameData, getPLvByScore } from "../pubUtils/data";
import { PVP } from '../pubUtils/dicParam';
@@ -14,7 +14,7 @@ import { setRank, getMyRank, getFieldByRank } from './redisService';
import { nowSeconds, checkTodayTime } from '../pubUtils/timeUtil';
import { HeroesRecord } from '../db/PvpRecord';
import { HeroModel, HeroType } from '../db/Hero';
import { CeAttrNumber, CeAttr, CeAttrRole, MainAttrNumber } from '../domain/roleField/attribute';
import { MainAttrNumber, Attribute, CeAttrData, CeAttrDataRole } from '../domain/roleField/attribute';
import { PvpEnemies, PvpHeroInfo, PvpOtherHeroes } from '../domain/dbGeneral';
import { DicWarJson } from '../pubUtils/dictionary/DicWarJson';
import { findWhere, findIndex } from 'underscore';
@@ -213,7 +213,7 @@ async function generPlayerOppHis(pvpdefense: PvpDefenseType, mapWarJson: DicWarJ
let heroInfo = new PvpHeroInfo();
heroInfo.setHeroInfo(dbHero);
heroInfo.setOutIndex(h.order);
let attribute = getPlayerAttribute(dbHero.ceAttr, role.globalCeAttr);
let attribute = getPlayerAttribute(dbHero.attr, role.attr);
heroInfo.setAttribute(attribute);
let enemy = new PvpEnemies(warJson, heroInfo, hs?hs.score: 0);
heroes.push(enemy);
@@ -491,16 +491,13 @@ export async function findPvpDefAllByRoleId(roleId: string) {
* @param enemyCe 出兵表对手战力
* @param ratio 系数
*/
export function getRobotAttribute(attribute: Attributes, ce: number, enemyCe: number, ratio: number) {
export function getRobotAttribute(attribute: {id: number, val: number}[], ce: number, enemyCe: number, ratio: number) {
let newAttribute = new CeAttrNumber();
for(let attrName in newAttribute) {
newAttribute[attrName] = Math.floor(attribute[attrName] * ce / enemyCe * ratio);
}
newAttribute['speed'] = 0;
newAttribute['ap'] = 0;
let newAttribute = new Attribute();
newAttribute.setByWarJson(attribute, ce / enemyCe * ratio);
let attrJson = newAttribute.getReduceAttributes();
return newAttribute;
return attrJson;
}
/**
@@ -508,18 +505,12 @@ export function getRobotAttribute(attribute: Attributes, ce: number, enemyCe: nu
* @param ceAttr hero表的ceAttr
* @param globalCeAttr role表中的globalCeAttr
*/
export function getPlayerAttribute(ceAttr: CeAttr, globalCeAttr: CeAttrRole) {
let newAttribute = new CeAttrNumber();
for(let attrName in newAttribute) {
let { base, ratioUp, fixUp, equipUp } = ceAttr[attrName];
let { ratioUp: ratioUp2, fixUp: fixUp2 } = globalCeAttr[attrName];
let result = base * ( HERO_CE_RATIO + ratioUp + ratioUp2) + (fixUp + fixUp2 + equipUp) * HERO_CE_RATIO;
newAttribute[attrName] += reduceCe(result);
}
newAttribute['speed'] = 0;
newAttribute['ap'] = 0;
export function getPlayerAttribute(heroAttrs: CeAttrData[] = [], roleAttrs: CeAttrDataRole[] = []) {
let newAttribute = new Attribute();
newAttribute.setByDbData(roleAttrs, heroAttrs);
let attrJson = newAttribute.getReduceAttributes();
return newAttribute;
return attrJson;
}
/**
@@ -527,8 +518,8 @@ export function getPlayerAttribute(ceAttr: CeAttr, globalCeAttr: CeAttrRole) {
* @param ceAttr
* @param globalCeAttr
*/
export function getPlayerMainAttribute(ceAttr: CeAttr, globalCeAttr: CeAttrRole) {
let attribute = getPlayerAttribute(ceAttr, globalCeAttr);
export function getPlayerMainAttribute(heroAttrs: CeAttrData[], roleAttrs: CeAttrDataRole[]) {
let attribute = getPlayerAttribute(heroAttrs, roleAttrs);
let mainAttributes = new MainAttrNumber(attribute);
return mainAttributes;

View File

@@ -10,6 +10,7 @@ import { SystemConfigModel } from '../db/SystemConfig';
import { GuildRankParam, GuildLeader, RankParam } from '../domain/rank';
import { GuildModel } from '../db/Guild';
import { comBtlRanges } from '../pubUtils/gamedata';
import { stringify } from 'querystring';
/**
* 在服务重新启动时将信息存入redis
*/
@@ -366,8 +367,8 @@ export async function clearChannelServers() {
* @param userCode user表唯一字符串标识
* @param sid connector服的那个sid
*/
export async function roleLogin(roleId: string, userCode: string, sid: string) {
let param = { userCode, sid };
export async function roleLogin(roleId: string, userCode: string, sid: string, pkgName: string) {
let param = { userCode, sid, pkgName };
return await redisClient().hsetAsync(REDIS_KEY.ONLINE_USERS, roleId, JSON.stringify(param));
}
@@ -400,7 +401,8 @@ export async function getRoleOnlineInfo(roleId: string) {
return {
isOnline: true,
userCode: result.userCode,
sid: result.sid
sid: result.sid,
pkgName: result.pkgName
}
} catch(e) {
return { isOnline: false }
@@ -414,8 +416,20 @@ export async function getRoleOnlineInfo(roleId: string) {
* 获得所有在线的玩家
*/
export async function getAllOnlineRoles() {
const client: Redis.RedisClient = pinus.app.get('redis');
let allRoles = await redisClient().hgetallAsync(REDIS_KEY.ONLINE_USERS);
return allRoles;
let result = new Array<{roleId: string, userCode: string, sid: string, pkgName: string}>();
for(let roleId in allRoles) {
try{
let param = JSON.parse(allRoles[roleId]);
if(param) {
result.push({ roleId, userCode: param.userCode, sid: param.sid, pkgName: param.pkgName });
}
} catch(e) {
continue;
}
}
return result;
}
export async function resetPvpRanks() {

View File

@@ -9,7 +9,7 @@ interface UserCache {
var userCacheMap = new Map<string, UserCache>();
export function init() {
scheduleJob("0/5 * * * * *", clearDirtyData, {name:'clearDirtyData'});//每个5秒钟释放redis锁
scheduleJob('clearDirtyData', "0/5 * * * * *", clearDirtyData);//每个5秒钟释放redis锁
}
/**
* 释放锁

View File

@@ -156,7 +156,7 @@ export async function addItems(roleId: string, roleName: string, sid: string, go
}
}
if (!!skinInfos.length) {
calAllHeroCe(sid, roleId, HERO_SYSTEM_TYPE.ADD_SKIN, addSkinIds)
calAllHeroCe(HERO_SYSTEM_TYPE.ADD_SKIN, sid, roleId, {}, addSkinIds);
pinus.app.get('channelService').pushMessageByUids('onHeroSkinChange', resResult(STATUS.SUCCESS, {skinInfos}), uids);
}
return showItems;

View File

@@ -3,44 +3,47 @@ import { Channel } from 'pinus';
import { getRandNum, getRandomArr } from '../pubUtils/util';
import { TERAPH_RANDOM } from "../consts/consts";
import { indexOf } from 'underscore';
import { DicTeraph } from '../pubUtils/dictionary/DicTeraph';
import { Teraph } from '../db/Role';
const TERAPH_STRENGTHEN = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
/**
* 计算强化次数和消耗
* @param count 强化次数
* @param attrNames 可以强化的属性名字
* @param attrs 可以强化的属性名字
* @param teraphInfo 字典表对应的神像信息
* @param teraph
* @param teraph 数据库内单个神像信息
*/
export function checkTeraphMaterialEnough(count: number, attrNames:Array<any>, teraphInfo: any, teraph: any) {
let res = {};
export function checkTeraphMaterialEnough(count: number, attrs:number[], teraphInfo: DicTeraph, teraph: Teraph) {
let consumes = [];
let times = 0;
if (count < 10) {
for (let i = 0; i < count; i++) {
if (!attrNames.length) {
if (!attrs.length) {
break;
}
let num = getRandNum(TERAPH_RANDOM.MIN, TERAPH_RANDOM.MAX);
let arr = getRandomArr(attrNames, num)
let num = getRandNum(TERAPH_RANDOM.MIN, TERAPH_RANDOM.MAX); // 强化时随机增加 2-4 属性
let arr: number[] = getRandomArr(attrs, num); // 随机出的属性id
let critical = getRandNum(0, 100);//属性暴击率
let criEffect = 1;
let criEffect = 1; // 暴击效果
if (critical <= teraphInfo.criRate)
criEffect = teraphInfo.criEffect;
for (let attrName of arr) {
let attrNameMax = attrName+'Max';
res[attrName] = teraphInfo[attrName] * criEffect;
if (teraph[attrName] + res[attrName] > teraphInfo[attrNameMax]) {
res[attrName] = teraphInfo[attrNameMax] - teraph[attrName];
let attrIndex = indexOf(attrNames, attrName);
attrNames.splice(attrIndex, 1);
for (let attrId of arr) {
let val = teraph.attr.get(attrId); // 已有的强化值
val += teraphInfo.mainAttrUp.get(attrId) * criEffect;
let max = teraphInfo.mainAttrMax.get(attrId);
if(val > max) {
val = max;
let attrIndex = attrs.indexOf(attrId);
attrs.splice(attrIndex, 1);
}
teraph.attr.set(attrId, val);
}
times++;
}
} else if (count == 10){
let criticalArrTimes = getRandomArr(TERAPH_STRENGTHEN, 2);//10次中随机2次发生暴击
for (let item of TERAPH_STRENGTHEN) {
if (!attrNames.length) {
if (!attrs.length) {
break;
}
let criEffect = 1;
@@ -49,24 +52,27 @@ export function checkTeraphMaterialEnough(count: number, attrNames:Array<any>, t
criEffect = teraphInfo.criEffect;//本次是暴击 item 在 criticalArrTimes 中
}
let num = getRandNum(TERAPH_RANDOM.MIN, TERAPH_RANDOM.MAX);
let arr = getRandomArr(attrNames, num);
for (let attrName of arr) {
res[attrName] = (res[attrName]||0) + teraphInfo[attrName] * criEffect;
let attrNameMax = attrName+'Max';
if (teraph[attrName] + res[attrName] > teraphInfo[attrNameMax]) {
res[attrName] = teraphInfo[attrNameMax] - teraph[attrName];
let attrIndex = indexOf(attrNames, attrName);
attrNames.splice(attrIndex, 1);
let arr: number[] = getRandomArr(attrs, num);
for (let attrId of arr) {
let val = teraph.attr.get(attrId); // 已有的强化值
val += teraphInfo.mainAttrUp.get(attrId) * criEffect;
let max = teraphInfo.mainAttrMax.get(attrId);
if(val > max) {
val = max;
let attrIndex = attrs.indexOf(attrId);
attrs.splice(attrIndex, 1);
}
teraph.attr.set(attrId, val);
}
times++;
}
}
//计算消耗
for (let {id, count} of teraphInfo.upMaterial) {
consumes.push({ id, count: count*times});
consumes.push({ id, count: count * times});
}
return {attr: res, consumes};
return { consumes};
}
/**
*

View File

@@ -3,12 +3,12 @@ import { scheduleJob, Job } from 'node-schedule';
import { SystemConfigModel } from '../db/SystemConfig';
import PvpDefenseType,{ PvpDefenseModel } from '../db/PvpDefense';
import { PVP } from '../pubUtils/dicParam';
import { nowSeconds, getTodayZeroPoint } from '../pubUtils/timeUtil';
import { nowSeconds, getTodayZeroPoint, getAge } from '../pubUtils/timeUtil';
import { getPvpGkWarIds, getPvpRankRewards, getPvpHeroRewards, getResultMaxRank } from '../pubUtils/data';
import { deepCopy, getRandomArr, resResult } from '../pubUtils/util';
import { deepCopy, getRandomArr, resResult, shouldRefresh } from '../pubUtils/util';
import { getLvByScore } from './pvpService';
import { getMyRank, setRank, resetPvpRanks } from './redisService';
import { MAIL_TYPE, REDIS_KEY } from '../consts';
import { getMyRank, setRank, resetPvpRanks, getAllOnlineRoles } from './redisService';
import { MAIL_TYPE, REDIS_KEY, ADULT_AGE, GUEST_MAX_TIME, ADDICTION_PREVENTION_CODE } from '../consts';
import { RankParam } from '../domain/rank';
import { RoleModel } from '../db/Role';
import { MailModel, MailType } from '../db/Mail';
@@ -18,6 +18,8 @@ import { PvpSeasonResultModel } from '../db/PvpSeasonResult';
import { settleGuildWeekly } from './guildService';
import { STATUS } from '../consts/statusCode';
import { getMailContent, sendMail } from './mailService';
import { reportOnline } from '../pubUtils/httpUtil';
import User, { UserModel } from '../db/User';
const PER_SECOND = 1 * 1000;
const PER_DAY = 24 * 60 * 60;
const SETTLE_DIFF = 29 * 60;
@@ -34,7 +36,7 @@ export async function init() {
let seasonEndTime = 0;
let systemConfig = await SystemConfigModel.findSystemConfig();//系统全局参数表
if (!systemConfig) {
console.log('create season seasonNum = '+ systemConfig.seasonNum);
console.log('create season seasonNum = '+ systemConfig?.seasonNum);
let warIds = getPvpGkWarIds();
let warId = warIds[0];
seasonEndTime = PVP.PVP_SEASON_DAYS * PER_DAY + getTodayZeroPoint();
@@ -50,21 +52,27 @@ export async function init() {
}
}
let settleTime = (seasonEndTime - SETTLE_DIFF)* PER_SECOND;
seasonJobId = scheduleJob(settleTime, setPvpSeasonResult, { name: 'setPvpSeasonResult' });//设置实际赛季结算时间
seasonJobId = scheduleJob('setPvpSeasonResult', settleTime, setPvpSeasonSchdule);//设置实际赛季结算时间
seasonEndTimeJobId = scheduleJob(seasonEndTime* PER_SECOND, resetPvpRanks, { name: 'resetRank' });//由于24之后才展示结算之后的信息为保排行榜信息一致性设置实际重置排行榜的时间为12点
seasonEndTimeJobId = scheduleJob('resetRank', seasonEndTime * PER_SECOND, resetPvpRanks);//由于24之后才展示结算之后的信息为保排行榜信息一致性设置实际重置排行榜的时间为12点
warJobId = scheduleJob("0 0 0 * * 1", resetPvpWarId);//每周1零点重置地图
await resetPvpRanks();//服务器重启,重置排行榜的信息
// 周功勋结算任务
guildWeeklyJobId = scheduleJob('0 0 0 * * 1', settleGuildWeekly, { name: 'settleGuildWeekly' });
guildWeeklyJobId = scheduleJob('settleGuildWeekly', '0 0 0 * * 1', settleGuildWeekly);
scheduleJob('reportOnline', '0 0/5 * * * *', reportOnlineSchedule)
}
function setPvpSeasonSchdule() {
setPvpSeasonResult();
}
/**
* pvp定时任务赛季结算
* @param obj
*/
export async function setPvpSeasonResult(obj:{ name:string, notSetNext?: boolean, notPush?: boolean }) {
export async function setPvpSeasonResult(obj?:{ name:string, notSetNext?: boolean, notPush?: boolean }) {
console.log('exce setPvpSeasonResult'+ obj?.name);
let { seasonNum, seasonEndTime, oldSeasonEndTime } = await setNextPvpTime(obj?.notSetNext);//设置下个结算任务
let resultMaxRank = getResultMaxRank();//根据排行榜的奖励表获得最大排名挡位的最小值其余不在结算中结算的玩家按照最大排名挡位在登录或进入pvp时结算
@@ -214,8 +222,8 @@ async function setNextPvpTime(notSetNext: boolean) {
seasonEndTime = (PVP.PVP_SEASON_DAYS + 1) * PER_DAY + getTodayZeroPoint();
await SystemConfigModel.updateSeason(seasonEndTime, oldSeasonEndTime);
let settleTime = (seasonEndTime - SETTLE_DIFF)* PER_SECOND;
seasonJobId = scheduleJob(settleTime, setPvpSeasonResult, { name: 'setPvpSeasonResult' });
seasonEndTimeJobId = scheduleJob(seasonEndTime* PER_SECOND, resetPvpRanks, { name: 'resetRank' });
seasonJobId = scheduleJob('setPvpSeasonResult', settleTime, setPvpSeasonSchdule);
seasonEndTimeJobId = scheduleJob('resetRank', seasonEndTime* PER_SECOND, resetPvpRanks);
return { seasonEndTime, seasonNum: seasonNum + 1, oldSeasonEndTime };
}
@@ -254,6 +262,51 @@ export async function resetPvpSeasonTime(hour: number) {
}
let settleTime = (seasonEndTime - SETTLE_DIFF)* PER_SECOND;
console.log('settleTime = ' + settleTime)
seasonJobId = scheduleJob(settleTime, setPvpSeasonResult, { name: 'setPvpSeasonResult' });
seasonJobId = scheduleJob('setPvpSeasonResult', settleTime, setPvpSeasonSchdule);
return { seasonEndTime, seasonNum };
}
export async function reportOnlineSchedule() {
let allRoles = await getAllOnlineRoles();
console.log('reportOnlineSchedule all roles count: ', allRoles.length)
for(let { roleId, userCode, sid, pkgName } of allRoles) {
let result = await reportOnline(userCode, pkgName); // 连接sdk
if(!result || result.code == -1) continue;
let user = await UserModel.findUserByUserCode(userCode);
if(!user) continue;
let { reportTime = new Date(), lastLoginTime = new Date(), guestTime, isGuest, hasAuthenticated, birthday } = user;
let age = getAge(birthday);
let isAdult = age >= ADULT_AGE;
if(result.code != ADDICTION_PREVENTION_CODE.SUCCESS) { // 未成年人防沉迷
pinus.app.channelService.pushMessageByUids('onPlayTime', resResult(STATUS.SUCCESS, {
isGuest,
guestTime, // 游客已体验时间
hasAuthenticated, // 是否进行过实名认证
isAdult, // 是否已成年
todayPlayTime: result.total, // 今天已游戏时长
type: result.code
} ), [{uid: roleId, sid: sid}]);
} else {
let lastTime = lastLoginTime > reportTime? lastLoginTime.getTime(): reportTime.getTime();
let guestTimeInc = Math.floor((Date.now() - lastTime)/1000);
user = await UserModel.updatePlayTime(userCode, guestTimeInc, result.total); // 记录时间
guestTime = user.guestTime;
if (isGuest && guestTime > GUEST_MAX_TIME) {
pinus.app.channelService.pushMessageByUids('onPlayTime', resResult(STATUS.SUCCESS, {
isGuest,
guestTime, // 游客已体验时间
hasAuthenticated, // 是否进行过实名认证
isAdult, // 是否已成年
todayPlayTime: result.total, // 今天已游戏时长
type: ADDICTION_PREVENTION_CODE.GUEST,
} ), [{uid: roleId, sid: sid}]);
}
}
}
}

View File

@@ -7,7 +7,7 @@ function main (){
let env = args[0];
if(args[0] == 'stable') {
env = 'production';
}
}
let configObject = {
env: env

View File

@@ -1,19 +1,28 @@
module.exports = {
'development': {
'mongo': 'mongodb://127.0.0.1/zyz',
'redis': '127.0.0.1'
'redis': '127.0.0.1',
'redispw': 'zyz_2020'
},
'production': {
'mongo': 'mongodb://dbop:zyzdbopbantu@dds-8vbdb47c6fb58a541.mongodb.zhangbei.rds.aliyuncs.com:3717,dds-8vbdb47c6fb58a542.mongodb.zhangbei.rds.aliyuncs.com:3717/zyz?replicaSet=mgset-500808098',
'redis': 'r-8vb4i2kgl91886fkxd.redis.zhangbei.rds.aliyuncs.com'
'redis': 'r-8vb4i2kgl91886fkxd.redis.zhangbei.rds.aliyuncs.com',
'redispw': 'zyz_2020'
},
'alpha': {
'mongo': 'mongodb://dbop:zyzdbopbantu@dds-8vbdb47c6fb58a541.mongodb.zhangbei.rds.aliyuncs.com:3717,dds-8vbdb47c6fb58a542.mongodb.zhangbei.rds.aliyuncs.com:3717/zyz?replicaSet=mgset-500808098',
'redis': 'r-8vb4i2kgl91886fkxd.redis.zhangbei.rds.aliyuncs.com'
'redis': 'r-8vb4i2kgl91886fkxd.redis.zhangbei.rds.aliyuncs.com',
'redispw': 'zyz_2020'
},
'dev': {
'mongo': 'mongodb://dbop:zyzdbopbantu@dds-8vbdb47c6fb58a541.mongodb.zhangbei.rds.aliyuncs.com:3717,dds-8vbdb47c6fb58a542.mongodb.zhangbei.rds.aliyuncs.com:3717/zyz?replicaSet=mgset-500808098',
'redis': 'r-8vb4i2kgl91886fkxd.redis.zhangbei.rds.aliyuncs.com'
'redis': 'r-8vb4i2kgl91886fkxd.redis.zhangbei.rds.aliyuncs.com',
'redispw': 'zyz_2020'
},
'isbn': {
'mongo': 'mongodb://root:Bantus123@dds-8vb74337eab84d641.mongodb.zhangbei.rds.aliyuncs.com:3717,dds-8vb74337eab84d642.mongodb.zhangbei.rds.aliyuncs.com:3717/admin?replicaSet=mgset-504694158',
'redis': 'r-8vbekkbb3z8ru2ckuj.redis.zhangbei.rds.aliyuncs.com',
'redispw': 'zyz_isbn_2021'
}
};

View File

@@ -0,0 +1,170 @@
module.exports = {
'appenders': {
'console': {
'type': 'console'
},
'logger': {
'type': 'file',
'filename': '${opts:base}/logs/logger.log',
'pattern': 'connector',
'maxLogSize': 1048576,
'layout': {
'type': 'basic'
},
'backups': 5
},
'log': {
'type': 'file',
'filename': '${opts:base}/logs/log.log',
'pattern': 'connector',
'maxLogSize': 1048576,
'layout': {
'type': 'basic'
},
'backups': 5
},
'con-log': {
'type': 'file',
'filename': '${opts:base}/logs/con-log-${opts:serverId}.log',
'pattern': 'connector',
'maxLogSize': 1048576,
'layout': {
'type': 'basic'
},
'backups': 5
},
'rpc-log': {
'type': 'file',
'filename': '${opts:base}/logs/rpc-log-${opts:serverId}.log',
'maxLogSize': 1048576,
'layout': {
'type': 'basic'
},
'backups': 5
},
'forward-log': {
'type': 'file',
'filename': '${opts:base}/logs/forward-log-${opts:serverId}.log',
'maxLogSize': 1048576,
'layout': {
'type': 'basic'
},
'backups': 5
},
'rpc-debug': {
'type': 'file',
'filename': '${opts:base}/logs/rpc-debug-${opts:serverId}.log',
'maxLogSize': 1048576,
'layout': {
'type': 'basic'
},
'backups': 5
},
'crash-log': {
'type': 'file',
'filename': '${opts:base}/logs/crash.log',
'maxLogSize': 1048576,
'layout': {
'type': 'basic'
},
'backups': 5
},
'admin-log': {
'type': 'file',
'filename': '${opts:base}/logs/admin.log',
'maxLogSize': 1048576,
'layout': {
'type': 'basic'
},
'backups': 5
},
'pinus': {
'type': 'file',
'filename': '${opts:base}/logs/pinus-default.log',
'maxLogSize': 1048576,
'layout': {
'type': 'basic'
},
'backups': 5
},
'error': {
'type': 'file',
'filename': '${opts:base}/logs/error.log',
'maxLogSize': 1048576,
'layout': {
'type': 'basic'
},
'backups': 5
},
'pinus-admin': {
'type': 'file',
'filename': '${opts:base}/logs/pinus-admin.log',
'maxLogSize': 1048576,
'layout': {
'type': 'basic'
},
'backups': 5
},
'pinus-rpc': {
'type': 'file',
'filename': '${opts:base}/logs/pinus-rpc-${opts:serverId}.log',
'maxLogSize': 1048576,
'layout': {
'type': 'basic'
},
'backups': 5
}
},
'categories': {
'default': {
'appenders': ['console'],
'level': 'debug'
},
'pinus': {
'appenders': ['console', 'pinus'],
'level': 'debug'
},
'con-log': {
'appenders': ['console', 'log'],
'level': 'debug'
},
'rpc-log': {
'appenders': ['console', 'log'],
'level': 'debug'
},
'forward-log': {
'appenders': ['console', 'log'],
'level': 'debug'
},
'rpc-debug': {
'appenders': ['console', 'log'],
'level': 'debug'
},
'crash-log': {
'appenders': ['console', 'crash-log'],
'level': 'debug'
},
'admin-log': {
'appenders': ['console', 'log'],
'level': 'debug'
},
'pinus-admin': {
'appenders': ['console', 'log'],
'level': 'debug'
},
'pinus-rpc': {
'appenders': ['console', 'log'],
'level': 'debug'
},
'logger': {
'appenders': ['console', 'logger'],
'level': 'error'
}
},
'prefix': '${opts:serverId} ',
'replaceConsole': true,
'lineDebug': false,
'errorStack': true
};

View File

@@ -0,0 +1,134 @@
module.exports = {
'appenders': {
'console': {
'type': 'console'
},
'con-log': {
'type': 'file',
'filename': '${opts:base}/logs/con-log-${opts:serverId}.log',
'pattern': 'connector',
'maxLogSize': 1048576,
'layout': {
'type': 'basic'
},
'backups': 5
},
'rpc-log': {
'type': 'file',
'filename': '${opts:base}/logs/rpc-log-${opts:serverId}.log',
'maxLogSize': 1048576,
'layout': {
'type': 'basic'
},
'backups': 5
},
'forward-log': {
'type': 'file',
'filename': '${opts:base}/logs/forward-log-${opts:serverId}.log',
'maxLogSize': 1048576,
'layout': {
'type': 'basic'
},
'backups': 5
},
'rpc-debug': {
'type': 'file',
'filename': '${opts:base}/logs/rpc-debug-${opts:serverId}.log',
'maxLogSize': 1048576,
'layout': {
'type': 'basic'
},
'backups': 5
},
'crash-log': {
'type': 'file',
'filename': '${opts:base}/logs/crash.log',
'maxLogSize': 1048576,
'layout': {
'type': 'basic'
},
'backups': 5
},
'admin-log': {
'type': 'file',
'filename': '${opts:base}/logs/admin.log',
'maxLogSize': 1048576,
'layout': {
'type': 'basic'
},
'backups': 5
},
'pinus': {
'type': 'file',
'filename': '${opts:base}/logs/pinus-${opts:serverId}.log',
'maxLogSize': 1048576,
'layout': {
'type': 'basic'
},
'backups': 5
},
'pinus-admin': {
'type': 'file',
'filename': '${opts:base}/logs/pinus-admin.log',
'maxLogSize': 1048576,
'layout': {
'type': 'basic'
},
'backups': 5
},
'pinus-rpc': {
'type': 'file',
'filename': '${opts:base}/logs/pinus-rpc-${opts:serverId}.log',
'maxLogSize': 1048576,
'layout': {
'type': 'basic'
},
'backups': 5
}
},
'categories': {
'default': {
'appenders': ['console', 'pinus'],
'level': 'debug'
},
'con-log': {
'appenders': ['con-log'],
'level': 'debug'
},
'rpc-log': {
'appenders': ['rpc-log'],
'level': 'debug'
},
'forward-log': {
'appenders': ['forward-log'],
'level': 'debug'
},
'rpc-debug': {
'appenders': ['rpc-debug'],
'level': 'debug'
},
'crash-log': {
'appenders': ['crash-log'],
'level': 'debug'
},
'admin-log': {
'appenders': ['admin-log'],
'level': 'debug'
},
'pinus-admin': {
'appenders': ['pinus-admin'],
'level': 'debug'
},
'pinus-rpc': {
'appenders': ['pinus-rpc'],
'level': 'debug'
},
},
'prefix': '${opts:serverId} ',
'replaceConsole': true,
'lineDebug': false,
'errorStack': true
};

View File

@@ -18,5 +18,10 @@ module.exports = {
'id': 'master-server-1',
'host': '127.0.0.1',
'port': 3005
},
'isbn': {
'id': 'master-server-1',
'host': '127.0.0.1',
'port': 3005
}
};

View File

@@ -63,11 +63,11 @@ declare module 'redis' {
}
}
export function connectRedis(redisArr: string) {
export function connectRedis(redisArr: string, redisPw: string) {
// 创建 redis 连接
const oldRedisClient = Redis.createClient(6379, redisArr, {detect_buffers: true});
oldRedisClient.auth('zyz_2020', (err, reply) => {
oldRedisClient.auth(redisPw, (err, reply) => {
if (err) {
console.log('redis err', err);
} else {

View File

@@ -21,8 +21,9 @@ module.exports = {
"message Hero": {
'required uInt32 hid': 1,
'required uInt32 ce': 2,
'required sInt32 incHeroCe': 3,
},
'required uInt32 ce': 1,
'required sInt32 ce': 1,
'repeated Hero heros': 2,
'required uInt32 topLineupCe': 3
},

View File

@@ -145,5 +145,37 @@ module.exports = {
'systimer': [
{'id': 'systimer-server-1', 'host': '127.0.0.1', 'port': 6056, "args": " --inspect=9233"}
]
},
'isbn': {
'connector': [
{'id': 'connector-server-1', 'port': 4050, 'clientHost': 'zyz_isbn.trgame.cn', 'host': '127.0.0.1', 'clientPort': 3050, 'frontend': true},
{'id': 'connector-server-2', 'port': 4051, 'clientHost': 'zyz_isbn.trgame.cn', 'host': '127.0.0.1', 'clientPort': 3051, 'frontend': true},
{'id': 'connector-server-3', 'port': 4052, 'clientHost': 'zyz_isbn.trgame.cn', 'host': '127.0.0.1', 'clientPort': 3052, 'frontend': true}
],
'chat': [
{'id': 'chat-server-1', 'host': '127.0.0.1', 'port': 6050},
],
'role': [
{'id': 'role-server-1', 'host': '127.0.0.1', 'port': 6053}
],
'battle': [
{'id': 'battle-server-1', 'host': '127.0.0.1', 'port': 6054}
],
'gate': [
{'id': 'gate-server-1', 'host': '127.0.0.1', 'clientHost': 'zyz_isbn.trgame.cn', 'clientPort': 3014, 'frontend': true},
{
'id': 'gate-server-2',
'host': '127.0.0.1',
'clientHost': 'zyz_isbn.trgame.cn',
'clientPort': 3015,
'frontend': true
}
],
'gm': [
{'id': 'gm-server-1', 'host': '127.0.0.1', 'port': 6055}
],
'systimer': [
{'id': 'systimer-server-1', 'host': '127.0.0.1', 'port': 6056}
]
}
};

View File

@@ -41,5 +41,20 @@ module.exports = {
'gate': [
{'id': 'gate-server-1', 'host': '127.0.0.1', 'clientPort': 3014, 'frontend': true}
]
},
'isbn': {
'connector': [
{'id': 'connector-server-1', 'host': '127.0.0.1', 'port': 4050, 'clientPort': 3050, 'frontend': true},
{'id': 'connector-server-2', 'host': '127.0.0.1', 'port': 4051, 'clientPort': 3051, 'frontend': true},
{'id': 'connector-server-3', 'host': '127.0.0.1', 'port': 4052, 'clientPort': 3052, 'frontend': true}
],
'chat': [
{'id': 'chat-server-1', 'host': '127.0.0.1', 'port': 6050},
{'id': 'chat-server-2', 'host': '127.0.0.1', 'port': 6051},
{'id': 'chat-server-3', 'host': '39.100.68.60', 'port': 6052}
],
'gate': [
{'id': 'gate-server-1', 'host': '127.0.0.1', 'clientPort': 3014, 'frontend': true}
]
}
};

View File

@@ -67,6 +67,11 @@
"@types/node": "*"
}
},
"@types/caseless": {
"version": "0.12.2",
"resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz",
"integrity": "sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w=="
},
"@types/chai": {
"version": "4.2.14",
"resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.2.14.tgz",
@@ -121,6 +126,15 @@
"resolved": "https://registry.npm.taobao.org/@types/node/download/@types/node-8.10.54.tgz?cache=0&sync_timestamp=1595281257528&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fnode%2Fdownload%2F%40types%2Fnode-8.10.54.tgz",
"integrity": "sha1-HIjrJTrBIQ8aWHaVP7cPfMSShAI="
},
"@types/node-schedule": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/@types/node-schedule/-/node-schedule-1.3.1.tgz",
"integrity": "sha512-xAY/ZATrThUkMElSDfOk+5uXprCrV6c6GQ5gTw3U04qPS6NofE1dhOUW+yrOF2UyrUiAax/Zc4WtagrbPAN3Tw==",
"dev": true,
"requires": {
"@types/node": "*"
}
},
"@types/redis": {
"version": "2.8.25",
"resolved": "https://registry.npm.taobao.org/@types/redis/download/@types/redis-2.8.25.tgz",
@@ -129,6 +143,26 @@
"@types/node": "*"
}
},
"@types/request": {
"version": "2.48.5",
"resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.5.tgz",
"integrity": "sha512-/LO7xRVnL3DxJ1WkPGDQrp4VTV1reX9RkC85mJ+Qzykj2Bdw+mG15aAfDahc76HtknjzE16SX/Yddn6MxVbmGQ==",
"requires": {
"@types/caseless": "*",
"@types/node": "*",
"@types/tough-cookie": "*",
"form-data": "^2.5.0"
}
},
"@types/request-promise": {
"version": "4.1.47",
"resolved": "https://registry.npmjs.org/@types/request-promise/-/request-promise-4.1.47.tgz",
"integrity": "sha512-eRSZhAS8SMsrWOM8vbhxFGVZhTbWSJvaRKyufJTdIf4gscUouQvOBlfotPSPHbMR3S7kfkyKbhb1SWPmQdy3KQ==",
"requires": {
"@types/bluebird": "*",
"@types/request": "*"
}
},
"@types/socket.io": {
"version": "2.1.10",
"resolved": "https://registry.npm.taobao.org/@types/socket.io/download/@types/socket.io-2.1.10.tgz",
@@ -138,6 +172,11 @@
"@types/node": "*"
}
},
"@types/tough-cookie": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.0.tgz",
"integrity": "sha512-I99sngh224D0M7XgW1s120zxCt3VYQ3IQsuw3P3jbq5GG4yc79+ZjyKznyOGIQrflfylLgcfekeZW/vk0yng6A=="
},
"@types/underscore": {
"version": "1.10.24",
"resolved": "https://registry.npm.taobao.org/@types/underscore/download/@types/underscore-1.10.24.tgz",
@@ -256,6 +295,11 @@
"resolved": "https://registry.npm.taobao.org/async-limiter/download/async-limiter-1.0.1.tgz",
"integrity": "sha1-3TeelPDbgxCwgpH51kwyCXZmF/0="
},
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
},
"backo2": {
"version": "1.0.2",
"resolved": "https://registry.npm.taobao.org/backo2/download/backo2-1.0.2.tgz",
@@ -520,6 +564,14 @@
"resolved": "https://registry.npm.taobao.org/colors/download/colors-1.0.3.tgz",
"integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs="
},
"combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"requires": {
"delayed-stream": "~1.0.0"
}
},
"commander": {
"version": "3.0.2",
"resolved": "https://registry.npm.taobao.org/commander/download/commander-3.0.2.tgz?cache=0&sync_timestamp=1595168120323&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcommander%2Fdownload%2Fcommander-3.0.2.tgz",
@@ -639,6 +691,11 @@
"object-keys": "^1.0.12"
}
},
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
},
"delegates": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
@@ -817,6 +874,16 @@
"resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.3.tgz",
"integrity": "sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg=="
},
"form-data": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz",
"integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==",
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.6",
"mime-types": "^2.1.12"
}
},
"fs-extra": {
"version": "8.1.0",
"resolved": "https://registry.npm.taobao.org/fs-extra/download/fs-extra-8.1.0.tgz",
@@ -2177,6 +2244,16 @@
"resolved": "https://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-2.0.1.tgz",
"integrity": "sha1-eCDZsWEgzFXKmud5JoCufbptf+I="
},
"psl": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
"integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ=="
},
"punycode": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
},
"random-to": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/random-to/-/random-to-0.0.2.tgz",
@@ -2285,6 +2362,25 @@
"resolved": "https://registry.npm.taobao.org/regexp-clone/download/regexp-clone-1.0.0.tgz",
"integrity": "sha1-Ii25Z2IydwViYLmSYmNUoEzpv2M="
},
"request-promise": {
"version": "4.2.6",
"resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.6.tgz",
"integrity": "sha512-HCHI3DJJUakkOr8fNoCc73E5nU5bqITjOYFMDrKHYOXWXrgD/SBaC7LjwuPymUprRyuF06UK7hd/lMHkmUXglQ==",
"requires": {
"bluebird": "^3.5.0",
"request-promise-core": "1.1.4",
"stealthy-require": "^1.1.1",
"tough-cookie": "^2.3.3"
}
},
"request-promise-core": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz",
"integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==",
"requires": {
"lodash": "^4.17.19"
}
},
"require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npm.taobao.org/require-directory/download/require-directory-2.1.1.tgz",
@@ -2532,6 +2628,11 @@
"resolved": "https://registry.npm.taobao.org/stack-trace/download/stack-trace-0.0.10.tgz?cache=0&sync_timestamp=1575992264808&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstack-trace%2Fdownload%2Fstack-trace-0.0.10.tgz",
"integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA="
},
"stealthy-require": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz",
"integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks="
},
"stream-pkg": {
"version": "0.0.5",
"resolved": "https://registry.npm.taobao.org/stream-pkg/download/stream-pkg-0.0.5.tgz",
@@ -2676,6 +2777,15 @@
"is-number": "^7.0.0"
}
},
"tough-cookie": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
"integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
"requires": {
"psl": "^1.1.28",
"punycode": "^2.1.1"
}
},
"ts-node": {
"version": "8.10.2",
"resolved": "https://registry.npm.taobao.org/ts-node/download/ts-node-8.10.2.tgz?cache=0&sync_timestamp=1590685779800&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fts-node%2Fdownload%2Fts-node-8.10.2.tgz",

View File

@@ -24,6 +24,7 @@
"@types/mongoose": "^5.7.36",
"@types/node": "8.10.54",
"@types/redis": "^2.8.25",
"@types/request-promise": "^4.1.47",
"@types/underscore": "^1.10.24",
"bcrypt": "^5.0.0",
"bluebird": "^3.5.1",
@@ -46,10 +47,13 @@
"redis": "^3.0.2",
"redlock": "^4.2.0",
"reflect-metadata": "^0.1.10",
"request": "^2.88.2",
"request-promise": "^4.2.6",
"source-map-support": "^0.5.0",
"ts-node": "^8.2.0"
},
"devDependencies": {
"@types/node-schedule": "^1.3.1",
"tslint": "^5.9.1",
"typescript": "^3.9.7"
}

View File

@@ -2,8 +2,6 @@ import { Service } from 'egg';
import { addSkins, addBags, addEquips } from '@pubUtils/itemUtils';
import * as pubUtils from '@pubUtils/util';
import * as pubGamedata from '@pubUtils/gamedata'
import { HeroType } from '@db/Hero';
import { calPlayerCeAndSave } from '@pubUtils/playerCe';
import { BagInter, EquipInter } from '@pubUtils/interface';
const csprng = require('csprng');
@@ -47,10 +45,6 @@ export default class Utils extends Service {
return pubUtils.resResult(status, data, customMsg);
}
public calPlayerCeAndSave(roleId: string, heros: HeroType[], type: number, args: number[]) {
return calPlayerCeAndSave(roleId, heros, type, args)
}
public addSkins(roleId: string, id: number) {
return addSkins(roleId, id);
}

View File

@@ -26,7 +26,7 @@ import { ItemModel } from '@db/Item';
import { gameData, getHeroExpByLv } from '@pubUtils/data';
import { calPlayerCeAndSave, calculatetopLineup, calEquipSeids } from '@pubUtils/playerCe';
import { SchoolModel } from '@db/School';
import { CeAttrNumber } from '@domain/roleField/attribute';
import { Attribute } from '@domain/roleField/attribute';
import { smsModel } from '@db/Sms';
import { isString } from 'underscore';
import { FriendShipModel } from '@db/FriendShip';
@@ -267,7 +267,7 @@ export default class GMUsers extends Service {
try {
for(let heroInfo of heroInfos) {
let hero = await HeroModel.createHero(heroInfo);
await calPlayerCeAndSave(heroInfo.roleId, [hero], HERO_SYSTEM_TYPE.INIT);
await calPlayerCeAndSave(HERO_SYSTEM_TYPE.INIT, heroInfo.roleId, hero, {});
}
return ctx.service.utils.resResult(STATUS.SUCCESS, { uids });
} catch(e) {
@@ -436,22 +436,19 @@ export default class GMUsers extends Service {
if(!hero || !role) {
return ctx.service.utils.resResult(STATUS.GM_HERO_NOT_FOUND);
}
let { lv, ce, ceAttr } = hero;
let { globalCeAttr } = role;
let { lv, ce, attr: heroAttrs } = hero;
let { attr: roleAttrs } = role;
let dicHero = ctx.service.utils.getHeroById(hid);
let attribute = new CeAttrNumber();
for(let attrName in attribute) {
let { base, ratioUp, fixUp, equipUp } = ceAttr[attrName];
let { ratioUp: ratioUp2, fixUp: fixUp2 } = globalCeAttr[attrName];
attribute[attrName] += base * ( 1 + ratioUp + ratioUp2) + fixUp + fixUp2 + equipUp;
}
let attribute = new Attribute();
attribute.setByDbData(roleAttrs, heroAttrs);
let heroInfo = {
actorId: dicHero.heroId,
actorName: dicHero.name,
attribute: {...attribute, speed: 0, ap: 0}, lv,
attribute, lv,
ce
};
@@ -540,9 +537,9 @@ export default class GMUsers extends Service {
let hero = await HeroModel.findByHidAndRole(equip.hid, roleId);
let index = hero.ePlace.findIndex(cur => cur.id == equip.ePlaceId);
if (index < 0) continue;
hero.ePlace[index].equip = null;
let args = calEquipSeids(hero);
await calPlayerCeAndSave(roleId, [hero], HERO_SYSTEM_TYPE.EQUIP, args);
hero.ePlace[index].equip = null;
await calPlayerCeAndSave(HERO_SYSTEM_TYPE.EQUIP, roleId, hero, {}, args);
}
seqIds.push(seqId);
}
@@ -617,8 +614,7 @@ export default class GMUsers extends Service {
let hero = await HeroModel.findByHidAndRole(hid, roleId);
console.log(hid, roleId, !!hero);
if(!hero) continue;
hero.lv = hlv;
await calPlayerCeAndSave(roleId, [hero], HERO_SYSTEM_TYPE.LVUP, [hid]);
await calPlayerCeAndSave(HERO_SYSTEM_TYPE.LVUP, roleId, hero, {lv: hlv});
}
return ctx.service.utils.resResult(STATUS.SUCCESS);

View File

@@ -0,0 +1,55 @@
import { EggAppConfig, EggAppInfo, PowerPartial } from 'egg';
export default (appInfo: EggAppInfo) => {
const config = {} as PowerPartial<EggAppConfig>;
// override config from framework / plugin
// use for cookie sign key, should change to your own and keep security
config.keys = appInfo.name + '_1600244957952_7142';
// add your egg config in here
config.middleware = [];
config.cluster = {
listen: {
port: 7500
}
};
// add your special config in here
const bizConfig = {
sourceUrl: `https://github.com/eggjs/examples/tree/master/${appInfo.name}`,
};
config.mongoose = {
url: 'mongodb://root:Bantus123@dds-8vb74337eab84d641.mongodb.zhangbei.rds.aliyuncs.com:3717,dds-8vb74337eab84d642.mongodb.zhangbei.rds.aliyuncs.com:3717/admin?replicaSet=mgset-504694158', // 内网
options: { useNewUrlParser: true, useUnifiedTopology: true },
};
config.security = {
csrf: {
enable: false,
ignoreJSON: true
},
domainWhiteList: ['http://localhost:9000']
};
// 配置上传
config.multipart = {
fileSize: '50mb',
mode: 'stream',
fileExtensions: ['.zip', '.tar.gz'], // 扩展几种上传的文件格式
};
config.alinode = {
appid: '86043',
secret: '54ef0364995b0c4f2ab42150e29ad30df8327a3a',
error_log: [ '/root/logs/zyz/zyz-web.log', '/root/logs/zyz/common-error.log', '/root/logs/zyz/egg-agent.log' ],
packages: [ '/root/zyz/web-server/package.json' ],
};
// the return config will combines to EggAppConfig
return {
...config,
...bizConfig,
};
};

119
package-lock.json generated
View File

@@ -23,6 +23,11 @@
}
}
},
"@types/bluebird": {
"version": "3.5.33",
"resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.33.tgz",
"integrity": "sha512-ndEo1xvnYeHxm7I/5sF6tBvnsA4Tdi3zj1keRKRs12SP+2ye2A27NDJ1B6PqkfMbGAcT+mqQVqbZRIrhfOp5PQ=="
},
"@types/bson": {
"version": "4.0.2",
"resolved": "https://registry.npm.taobao.org/@types/bson/download/@types/bson-4.0.2.tgz",
@@ -31,6 +36,11 @@
"@types/node": "*"
}
},
"@types/caseless": {
"version": "0.12.2",
"resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz",
"integrity": "sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w=="
},
"@types/mongodb": {
"version": "3.5.27",
"resolved": "https://registry.npm.taobao.org/@types/mongodb/download/@types/mongodb-3.5.27.tgz?cache=0&sync_timestamp=1599138259359&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fmongodb%2Fdownload%2F%40types%2Fmongodb-3.5.27.tgz",
@@ -54,6 +64,31 @@
"resolved": "https://registry.npm.taobao.org/@types/node/download/@types/node-14.10.0.tgz?cache=0&sync_timestamp=1599757029267&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fnode%2Fdownload%2F%40types%2Fnode-14.10.0.tgz",
"integrity": "sha1-FYFd/4LI3DCCf2sShvhlkClFCVo="
},
"@types/request": {
"version": "2.48.5",
"resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.5.tgz",
"integrity": "sha512-/LO7xRVnL3DxJ1WkPGDQrp4VTV1reX9RkC85mJ+Qzykj2Bdw+mG15aAfDahc76HtknjzE16SX/Yddn6MxVbmGQ==",
"requires": {
"@types/caseless": "*",
"@types/node": "*",
"@types/tough-cookie": "*",
"form-data": "^2.5.0"
}
},
"@types/request-promise": {
"version": "4.1.47",
"resolved": "https://registry.npmjs.org/@types/request-promise/-/request-promise-4.1.47.tgz",
"integrity": "sha512-eRSZhAS8SMsrWOM8vbhxFGVZhTbWSJvaRKyufJTdIf4gscUouQvOBlfotPSPHbMR3S7kfkyKbhb1SWPmQdy3KQ==",
"requires": {
"@types/bluebird": "*",
"@types/request": "*"
}
},
"@types/tough-cookie": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.0.tgz",
"integrity": "sha512-I99sngh224D0M7XgW1s120zxCt3VYQ3IQsuw3P3jbq5GG4yc79+ZjyKznyOGIQrflfylLgcfekeZW/vk0yng6A=="
},
"abbrev": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
@@ -87,6 +122,11 @@
"es-abstract": "^1.17.0-next.1"
}
},
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
},
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
@@ -157,6 +197,14 @@
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
},
"combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"requires": {
"delayed-stream": "~1.0.0"
}
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -200,6 +248,11 @@
"object-keys": "^1.0.12"
}
},
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
},
"delegates": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
@@ -248,6 +301,16 @@
"resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.3.tgz",
"integrity": "sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg=="
},
"form-data": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz",
"integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==",
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.6",
"mime-types": "^2.1.12"
}
},
"fs-minipass": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz",
@@ -417,6 +480,19 @@
"integrity": "sha1-2HUWVdItOEaCdByXLyw9bfo+ZrU=",
"optional": true
},
"mime-db": {
"version": "1.46.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.46.0.tgz",
"integrity": "sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ=="
},
"mime-types": {
"version": "2.1.29",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.29.tgz",
"integrity": "sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ==",
"requires": {
"mime-db": "1.46.0"
}
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
@@ -714,6 +790,16 @@
"resolved": "https://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-2.0.1.tgz",
"integrity": "sha1-eCDZsWEgzFXKmud5JoCufbptf+I="
},
"psl": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
"integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ=="
},
"punycode": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
},
"random-to": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/random-to/-/random-to-0.0.2.tgz",
@@ -761,6 +847,25 @@
"resolved": "https://registry.npm.taobao.org/regexp-clone/download/regexp-clone-1.0.0.tgz",
"integrity": "sha1-Ii25Z2IydwViYLmSYmNUoEzpv2M="
},
"request-promise": {
"version": "4.2.6",
"resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.6.tgz",
"integrity": "sha512-HCHI3DJJUakkOr8fNoCc73E5nU5bqITjOYFMDrKHYOXWXrgD/SBaC7LjwuPymUprRyuF06UK7hd/lMHkmUXglQ==",
"requires": {
"bluebird": "^3.5.0",
"request-promise-core": "1.1.4",
"stealthy-require": "^1.1.1",
"tough-cookie": "^2.3.3"
}
},
"request-promise-core": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz",
"integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==",
"requires": {
"lodash": "^4.17.19"
}
},
"require_optional": {
"version": "1.0.1",
"resolved": "https://registry.npm.taobao.org/require_optional/download/require_optional-1.0.1.tgz",
@@ -841,6 +946,11 @@
"memory-pager": "^1.0.2"
}
},
"stealthy-require": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz",
"integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks="
},
"string-width": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
@@ -911,6 +1021,15 @@
"yallist": "^3.0.3"
}
},
"tough-cookie": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
"integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
"requires": {
"psl": "^1.1.28",
"punycode": "^2.1.1"
}
},
"tslib": {
"version": "2.0.1",
"resolved": "https://registry.npm.taobao.org/tslib/download/tslib-2.0.1.tgz?cache=0&sync_timestamp=1596751904317&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftslib%2Fdownload%2Ftslib-2.0.1.tgz",

View File

@@ -6,6 +6,7 @@
"dependencies": {
"@typegoose/typegoose": "^7.3.5",
"@types/mongoose": "^5.7.36",
"@types/request-promise": "^4.1.47",
"bcrypt": "^5.0.0",
"chinese-random-name": "^1.0.0",
"lodash": "^4.17.20",
@@ -14,6 +15,7 @@
"mongoose-lean-getters": "^0.1.2",
"mongoose-lean-virtuals": "^0.7.6",
"mongoose-transactions": "^1.1.4",
"request-promise": "^4.2.6",
"underscore": "^1.12.0"
},
"devDependencies": {},

View File

@@ -13,6 +13,8 @@ elif [ ${1} == 'alpha' ] ; then
destUrl="root@zyzalpha:/root/zyz/"
elif [ ${1} == 'dev' ] ; then
destUrl="root@zyzdev:/root/zyz/"
elif [ ${1} == 'isbn' ] ; then
destUrl="root@zyzisbn:/root/zyz/"
else
echo "需要一个参数指明服务器"
exit 1;

View File

@@ -4,9 +4,6 @@
* 属性 id
*/
import { JOB_TYPE } from "..";
export enum ABI_TYPE{
/**生命 */
ABI_HP = 1,
@@ -41,12 +38,33 @@ export enum ABI_TYPE{
ABI_DEF_IGNORE = 15,
/**吸血等级 */
ABI_BLOOD_SUCK = 16,
/**怒气 */
/**怒气恢复效果 */
ABI_AP = 17,
/**暴击伤害 */
ABI_DAMAGE_CRI = 18,
ABI_MAX,
}
// 主属性
export const ABI_TYPE_MAIN = [
ABI_TYPE.ABI_HP,
ABI_TYPE.ABI_ATK,
ABI_TYPE.ABI_DEF,
ABI_TYPE.ABI_MDEF
];
// 次级属性
export const ABI_TYPE_SUB = [
ABI_TYPE.ABI_HIT,
ABI_TYPE.ABI_CRI,
ABI_TYPE.ABI_FLEE,
ABI_TYPE.ABI_ANT_CRI,
ABI_TYPE.ABI_DAMAGE_INCREASE,
ABI_TYPE.ABI_DAMAGE_DECREASE,
ABI_TYPE.ABI_DEF_IGNORE,
ABI_TYPE.ABI_DAMAGE_CRI
];
export enum SEID_TYPE {
/**属性固定值加成(数值) */
@@ -63,39 +81,10 @@ export enum ABI_STAGE {
ATK = 2,
DEF = 3,
MDEF = 4,
AGI = 5,
LUK = 6,
END = 6
END = 4
}
export const ATTR = {}
//武将训练等级
export const HEROTARIN = {
1: "hp",
2: "atk",
3: "def",
4: "mdef",
5: "agi",
6: "luk"
};
//战力系数
export const CE_RATIO = {
"hp" : 1,
"atk" : 2,
"matk": 2,
"def": 2,
"mdef": 2,
"agi": 2,
"luk": 0,
"hit": 0,
"cri": 0,
"flee": 0,
"antCri": 0,
"damageIncrease": 0,
"damageDecrease": 0,
"defIngnore": 0,
"bloodSuck": 0,
};
export const HERO_ATTR = {
1: "hp", // 生命
@@ -114,44 +103,30 @@ export const HERO_ATTR = {
14: "damageDecrease", // 伤害减免等级
15: "defIngnore", // 忽视防御等级
16: "bloodSuck", // 吸血等级
17: "ap" // 怒气
17: "damageCri", // 暴击伤害
18: "ap" // 暴击伤害
};
export const JEWEL_ATTR = {
1: "hp",
2: "atk",
3: "def",
4: "mdef",
5: "agi",
6: "luk"
}
const BASE_ATTR = {
'hp' : 1 ,
'atk' : 2,
'def' : 3,
'mdef' : 4
}
export const ABI_TYPE_TO_STAGE = new Map<number, number | ((jobType: number) => number)>([
export const ABI_TYPE_TO_STAGE = new Map<number, number>([
[ABI_STAGE.HP, ABI_TYPE.ABI_HP],
[ABI_STAGE.ATK, (jobType:number) => { return jobType == JOB_TYPE.PHYSIC?ABI_TYPE.ABI_ATK: ABI_TYPE.ABI_MATK}],
[ABI_STAGE.ATK, ABI_TYPE.ABI_ATK],
[ABI_STAGE.DEF, ABI_TYPE.ABI_DEF],
[ABI_STAGE.MDEF, ABI_TYPE.ABI_MDEF],
[ABI_STAGE.AGI, ABI_TYPE.ABI_AGI],
[ABI_STAGE.LUK, ABI_TYPE.ABI_LUK]
[ABI_STAGE.MDEF, ABI_TYPE.ABI_MDEF]
]);
export function getAtrrNameById(attrId: number):string {
return HERO_ATTR[attrId];
};
export function getAttrCeRatio(attr: string):number {
return CE_RATIO[attr];
};
export function getAttrNameByJobStage(jobStage: number) {
return HEROTARIN[jobStage];
};
export function getTeraphAttr() {
return BASE_ATTR;
};
export enum CE_CONST {
FLEE_VALUE = 0.3, // 格挡价值
PUT_HIT = 50000, // 投放总命中
HIT_RATE_BASE = 0.75, // 命中率基础
HIT_RATE_MAX = 1, // 命中率上限
HIT_RATE_MIN = 0, // 命中率下限
PUT_ANT_CRI = 50000, // 投放总抗暴
CRI_RATE_BASE = 0.05, // 暴击率基础
CRI_RATE_MAX = 0.75, // 暴击率上限
CRI_RATE_MIN = 0.05, // 暴击率下限
CRI_VALUE_BASE = 1.5, // 暴击价值基础
}

View File

@@ -14,7 +14,3 @@ export const GOLD_COST_RATIO = {
"DAILY_REF_NUM": { "A": 50, "B": 0 }, // 每日购买次数花费
"DUNGRON_BUY_NUM": { "A": 0, "B": 50 } // 秘境购买次数花费
}
export const EXPRESSION = {
"CE": "1*hp+2*atk+2*matk+2*def+2*mdef+2*agi+2*luk+0*hit+0*cri+0*flee+0*antCri+0*damageIncrease+0*damageDecrease+0*defIngnore+0*bloodSuck"
}

View File

@@ -18,7 +18,9 @@ export const HERO_SYSTEM_TYPE = {
ADD_SKIN: 15,
SCHOOL: 16,
SCROLL: 17,
TITLE:18,
TITLE: 18,
TERAPH: 19,
TERAPH_UP: 20
};
// 武将上限
@@ -36,4 +38,6 @@ export const JOB_TYPE = {
}
// 武将战力放大系数
export const HERO_CE_RATIO = 100;
export const HERO_CE_RATIO = 100;
// 次级属性放大系数
export const HERO_SUB_ATTR_RATIO = 1000;

View File

@@ -0,0 +1,6 @@
export enum BANTU_VID_ADDR {
HOST = 'https://sdks.trgame.cn',
IDCARD = '/vid/idcard', // 实名认证
REPORT_ONLINE = '/addiction_prevention/report_online'
}
export const BANTU_VID_APP_KEY = '05c1c495369769e3c5d98426e9c8c2c0';

View File

@@ -7,7 +7,7 @@ export enum ROLE_SELECT {
// 显示申请需要的信息
SHOW_FRIEND_APPLY_LIST = 'roleId roleName ce headHid sHid lv title job quitTime vLv guildName friendCnt recFrdApplyCnt serverId userInfo.serverType',
HANDLE_APPLY = 'roleId friendCnt lv',
ATTR = 'globalCeAttr',
ATTR = 'attr',
GET_LV = 'lv',
GET_ROLE_ID = 'roleId',
GET_MY_SERVER = 'lv serverId userInfo.serverType',
@@ -15,8 +15,8 @@ export enum ROLE_SELECT {
};
export enum HERO_SELECT {
ENTRY = '-ceAttr',
HERO_DETAIL = 'roleId roleName hid hName ce lv star colorStar quality job skins ceAttr'
ENTRY = '-attr',
HERO_DETAIL = 'roleId roleName hid hName ce lv star colorStar quality job skins attr'
}
export enum EQUIP_SELECT {

View File

@@ -7,6 +7,10 @@ export const ENCRYPT_KEY = 'fiqaxijabbantusmprc234fj';
export const AUTH_SMS_CNT_PER_DAY = 8;
export const ADULT_AGE = 18;
export const GUEST_MAX_TIME = 60 * 60 * 100; // 游客体验时间
export const GUEST_DAY = 15; // 同一设备15天内不得重复体验游客模式
export const COUNTER = {
UID: { name: 'uid', def: 1 },
GMUID: { name: 'gmuid', def: 1 },
@@ -392,4 +396,17 @@ export enum BLOCK_OPEATE {
REMOVE_BLACK = 2,
REMOVE_AND_APPLY = 3,
REMOVE_FRIEND = 4
}
export enum TIME_FORMAT {
TYPE_SLASH = 1
}
export enum ADDICTION_PREVENTION_CODE {
FAIL = -1,
SUCCESS = 1, // 接口的返回
GUEST = 1, // 返回给客户端时,游客时间超时
CURFEW = 2, // 每日22时至次日8时,未成年禁止游戏
HOLIDAY = 3, // 法定节假日每日累计不得超过3小时
WORKDAY = 4, // 非法定节假日每日累计不得超过1.5小时
}

View File

@@ -7,5 +7,6 @@ export * from './constModules/sysConst';
export * from './constModules/guildConst';
export * from './constModules/selectConst';
export * from './constModules/chatConst';
export * from './constModules/httpConst';
export * from './statusCode';
export * from './dataName';

View File

@@ -17,6 +17,12 @@ export const STATUS = {
DUP_LOGIN: { code: 10006, simStr: '重复登录' },
NEW_SERVER_ERR: { code: 10007, simStr: '添加新服务器失败' },
SERVER_EXISTS: { code: 10008, simStr: '服务器已存在' },
PASSWORD_ERR: { code: 10009, simStr: '密码错误' },
PASSWORD_ILLEGEL: { code: 10010, simStr: '请输入密码' },
TEL_HAS_USED: { code: 10011, simStr: '该手机号已被使用' },
ACCOUNT_NOT_GUEST: { code: 10012, simStr: '该账号已绑定过' },
AUTHEN_FAIL: { code: 10013, simStr: '实名失败' },
TEL_LEN_ERR: { code: 10014, simStr: '手机长度错误' },
// 战斗相关状态 20000 - 29999
// 战斗通用 20000 - 20099
BATTLE_MISS_INFO: { code: 20001, simStr: '缺少关卡信息' },

View File

@@ -94,7 +94,7 @@ export default class Equip extends BaseModel {
return equip;
}
public static async putOn(hid: number, equipId: string, lean = true) {
public static async putOnOrOff(equipId: string, hid: number, lean = true) {
const equip: EquipType = await EquipModel.findOneAndUpdate({ _id: equipId }, { hid }, { new: true }).lean(lean);
return equip;
}

View File

@@ -2,27 +2,58 @@ import { APP_ID } from './../consts';
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, modelOptions } from '@typegoose/typegoose';
class ServerInfo {
export class ServerInfo {
@prop({ required: true })
id: number;
id: number; // 小区id
@prop({ required: true })
name: string;
name: string; // 小区区名
@prop({ required: true })
host: string;
groupId: number; // 大区id
@prop({ required: true })
groupName: string; // 大区区名
@prop({ required: true })
host: string; // pinus连接地址
@prop({ required: false })
port: number;
port: number; // pinus端口
@prop({ required: true })
status: number;
serverStatus: number; // 服务器状态
public get status() {
let now = new Date();
if( now > this.openTime) {
return this.serverStatus;
} else {
return 3; // 未开服
}
}
@prop({ required: true })
openTime: Date;
@prop({ required: true })
createTime: Date;
@prop({ required: true })
serverType: string;
constructor(id: number, name: string, groupId: number, groupName: string, host: string, port: number, serverStatus: number, serverType: string, openTime?: Date) {
this.id = id;
this.name = name;
this.groupId = groupId;
this.groupName = groupName;
this.host = host;
this.port = port;
this.serverStatus = serverStatus;
this.serverType = serverType;
this.openTime = openTime||new Date();
this.createTime = new Date();
}
}
/**
@@ -65,26 +96,23 @@ export default class Game extends BaseModel {
}
}
public static async getServerListByType(serverType: string) {
let game: GameType = await GameModel.findOne().lean();
public static async getServerList() {
let game: GameType = await GameModel.findOne().lean({ getter: true, virtuals: true });
if (!game) {
const serverInfo: ServerInfo = { id: 1, name: '常山少年', host: 'pinus_test.trgame.cn', port: 3014, status: 1, createTime: new Date(), serverType: 'official' };
const serverInfo = new ServerInfo(1, '常山少年', 1, '逍遥津', 'pinus_test.trgame.cn', 3014, 1, 'official');
const iconUrl = `https://download.tgamebox.cn/avatar/${APP_ID}/1.png`;
game = await GameModel.findOneAndUpdate(
{},
{ id: 1, name: '赵云传', nameEn: 'zyz', des: '牛逼的战棋', iconUrl, version: '0.0.1', versionCode: 1, $push: { serverList: serverInfo } },
{ upsert: true, new: true },
).lean();
).lean({ getter: true, virtuals: true });
}
console.log(serverType, game);
let serverList: Array<ServerInfo> = game ? game.serverList : [];
serverList = serverList.filter(item => { return item.serverType === serverType; });
console.log(serverType, serverList);
return serverList;
}
public static async newServer(serverId: number, serverType: string, name: string, host: string, port: number, status: number, lean = true) {
let serverInfo: ServerInfo = {id: serverId, name, host, port, status, createTime: new Date(), serverType};
let serverInfo = new ServerInfo(serverId, name, 1, '逍遥津', host, port, status, serverType);
let game: GameType = await GameModel.findOneAndUpdate({}, {$push: {serverList: serverInfo}}, {new: true}).lean(lean);
return game;
}

View File

@@ -1,9 +1,9 @@
import BaseModel from './BaseModel';
import { index, getModelForClass, mongoose, prop, DocumentType } from '@typegoose/typegoose';
import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose';
import { nowSeconds } from '../pubUtils/timeUtil';
import { MAIL_STATUS, MAIL_TYPE } from '../consts/constModules/mailConst';
import { findWhere } from 'underscore';
const { ObjectId } = mongoose.Types;
class RewardInter {
@prop({ required: true })
id: number;

View File

@@ -1,17 +1,32 @@
import BaseModel from './BaseModel';
import { CeAttr } from '../domain/roleField/attribute';
import { index, getModelForClass, prop, Ref, mongoose, DocumentType } from '@typegoose/typegoose';
import Equip, { } from './Equip';
import { CounterModel } from './Counter';
import { COUNTER, EQUIP_TYPE } from '../consts';
import { reduceCe } from '../pubUtils/util';
class CeAttrData {
@prop({ required: true })
id: number = 0;
@prop({ required: true })
base: number = 0;
@prop({ required: true })
ratioUp: number = 0;
@prop({ required: true })
fixUp: number = 0;
@prop({ required: true })
equipUp: number = 0;
constructor(id: number) {
this.id = id;
}
}
/**
* 英雄表
*/
class Connect {
export class Connect {
@prop({ required: true })
shipId: number;
@prop({ required: true })
@@ -51,31 +66,6 @@ function getInitialEplace() {
return ePlace;
}
interface heroUpdate {
exp?: number;
lv?: number;
ce?: number;
star?: number;
starStage?: number;
colorStar?: number;
colorStarStage?: number;
quality?: number;
job?:number;
jobStage?:number;
favour?:number;
favourLv?:number;
skins?: Skin[];
connections?: Connect[];
ePlace?:EPlace[];
_id?:number;
scrollActive?: boolean;
scrollId?: number;
scrollStar?: number;
scrollColorStar?: number;
scrollQuality?: number;
historyCe?: number;
}
@index({ roleId: 1, hid: 1 })
@index({ roleId: 1, seqId: 1 })
export default class Hero extends BaseModel {
@@ -102,8 +92,8 @@ export default class Hero extends BaseModel {
ce: number; // 武将战力
@prop({ required: true, default: 0 })
historyCe: number; // 武将历史最高战力
@prop({required: true, default: new CeAttr(), _id: false })
ceAttr: CeAttr; // 影响战力的属性
@prop({required: true, type: CeAttrData, default: [], _id: false })
attr: CeAttrData[]; // 影响战力的属性
@prop({ required: true, default: 1 })
star: number; // 星级
@@ -181,10 +171,21 @@ export default class Hero extends BaseModel {
public static async addEquip(roleId: string, hid: number, ePlaceId: number, equipId: string, lean = true) {
const hero: HeroType = await HeroModel.findOneAndUpdate(
{ roleId, hid, 'ePlace.id': ePlaceId },
{$set: {'ePlace.$.equip': equipId, 'ePlace.$.hid':hid, 'ePlace.$.ePlaceId':ePlaceId}},
{$set: { 'ePlace.$.equip': equipId }},
{new: true}).populate('ePlace.equip').lean(lean);
if (hero) {
await Equip.putOn(hero.hid, equipId);
await Equip.putOnOrOff( equipId, hero.hid );
}
return hero;
}
public static async removeEquip(roleId: string, hid: number, ePlaceId: number, equipId: string, lean = true) {
const hero: HeroType = await HeroModel.findOneAndUpdate(
{ roleId, hid, 'ePlace.id': ePlaceId },
{$set: {'ePlace.$.equip': null}},
{new: true}).populate('ePlace.equip').lean(lean);
if (hero) {
await Equip.putOnOrOff( equipId, 0 );
}
return hero;
}
@@ -238,7 +239,7 @@ export default class Hero extends BaseModel {
return result;
}
public static async updateHeroInfo(roleId: string, hid:number, heroUpdate:heroUpdate, select?: string, lean = true) {
public static async updateHeroInfo(roleId: string, hid:number, heroUpdate:HeroUpdate, select?: string, lean = true) {
delete heroUpdate._id;
let result: HeroType = await HeroModel.findOneAndUpdate({roleId, hid}, {$set:heroUpdate}, {new: true}).select(select).lean(lean);
return result;
@@ -270,3 +271,4 @@ export default class Hero extends BaseModel {
export const HeroModel = getModelForClass(Hero);
export interface HeroType extends Pick<DocumentType<Hero>, keyof Hero>{};
export type HeroUpdate = Partial<HeroType>; // 将所有字段变成可选项

View File

@@ -1,8 +1,8 @@
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, mongoose } from '@typegoose/typegoose';
import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose';
import { nowSeconds } from '../pubUtils/timeUtil';
import { MAIL_STATUS, MAIL_TYPE } from '../consts/constModules/mailConst';
const { ObjectId } = mongoose.Types;
class RewardInter {
@prop({ required: true })
id: number;

63
shared/db/Notice.ts Normal file
View File

@@ -0,0 +1,63 @@
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, modelOptions } from '@typegoose/typegoose';
import { formatTime } from '../pubUtils/timeUtil';
import { TIME_FORMAT } from '../consts'
/**
* 游戏字段接口
*/
@index({ id: 1 })
@modelOptions({schemaOptions: {id: false}})
export default class Notice extends BaseModel {
@prop({ required: true })
id: number; // 公告id
@prop({ required: true })
title: string; // 公告标题
@prop({ required: true })
tag: number; // 公告显示标签,在系统参数表中配了
@prop({ required: true })
type: number; // 类型 1-公告 2-活动
@prop({ required: true })
content: number; // 公告内容
@prop({ required: true })
timeStr: string; // 时间显示
@prop({ required: true })
startTime: Date; // 活动开始时间
@prop({ required: true })
endTime: Date; // 活动结束时间
public get time() {
let startTime = formatTime(this.startTime, TIME_FORMAT.TYPE_SLASH);
let endTime = formatTime(this.endTime, TIME_FORMAT.TYPE_SLASH);
return this.timeStr.replace(/%startTime/g, startTime).replace(/%endTime/g, endTime);
}
@prop({ required: true, select: false })
sort: number;
@prop({ required: true, select: false })
showStartTime: Date;
@prop({ required: true, select: false })
showEndTime: Date;
@prop({ required: true, select: false })
serverType: string; // 服务器类型
@prop({ required: true, select: false })
isEnable: boolean;
public static async getAllNotice(serverType: string) {
let curTime = new Date();
let notices: NoticeType[] = await NoticeModel.find({ showStartTime: { $lte: curTime }, showEndTime: { $gte: curTime }, isEnable: true, serverType })
.sort({ sort: -1, createTime: -1 })
.lean({ virtuals: true });
return notices;
}
}
export const NoticeModel = getModelForClass(Notice);
export interface NoticeType extends Pick<DocumentType<Notice>, keyof Notice>{
id: number;
};

View File

@@ -1,6 +1,5 @@
import { HANG_UP_CONSTS, ROLE_TERAPH, ROLE_SELECT } from './../consts';
import { HANG_UP_CONSTS, ROLE_TERAPH, ROLE_SELECT, ABI_TYPE } from './../consts';
import BaseModel from './BaseModel';
import { CeAttrRole } from '../domain/roleField/attribute';
import { index, getModelForClass, prop, DocumentType, Ref, mongoose } from '@typegoose/typegoose';
import User from './User';
import { shouldRefresh, reduceCe } from '../pubUtils/util';
@@ -8,6 +7,20 @@ import { initRoleAtrr } from '../pubUtils/playerCe';
import Hero,{} from '../db/Hero';
import { nowSeconds } from '../pubUtils/timeUtil';
// role表属性格式
export class CeAttrDataRole {
@prop({ required: true })
id: number = 0;
@prop({ required: true })
ratioUp: number = 0;
@prop({ required: true })
fixUp: number = 0;
constructor(id: number) {
this.id = id;
}
}
class TopHero {
@prop({ required: true })
hid: number; // 武将id
@@ -41,37 +54,47 @@ export class WarStar {
star: number; // 星级
}
class Teraph{
export class Teraph{
@prop({ required: true, default: 1 })
id: number; // 神像的id
@prop({ required: true, default: 1 })
grade: number; // 等级
grade: number = 1; // 等级
@prop({ required: true, default: 0 })
hp: number;
hp: number = 0;
@prop({ required: true, default: 0 })
atk: number;
atk: number = 0;
@prop({ required: true, default: 0 })
def: number;
def: number = 0;
@prop({ required: true, default: 0 })
mdef: number;
@prop({ required: true, default: 0 })
agi: number;
@prop({ required: true, default: 0 })
luk: number;
mdef: number = 0;
constructor(id: number) {
this.id = id;
}
public get attr() {
let map = new Map<number, number>();
map.set(ABI_TYPE.ABI_HP, this.hp);
map.set(ABI_TYPE.ABI_ATK, this.atk);
map.set(ABI_TYPE.ABI_DEF, this.def);
map.set(ABI_TYPE.ABI_MDEF, this.mdef);
return map
}
public set attr(value: Map<number, number>) {
value.forEach((val, id) => {
if(id == ABI_TYPE.ABI_HP) this.hp = val;
if(id == ABI_TYPE.ABI_ATK) this.atk = val;
if(id == ABI_TYPE.ABI_DEF) this.def = val;
if(id == ABI_TYPE.ABI_MDEF) this.mdef = val;
});
}
}
// 初始化
function getInitialTeraph() {
let teraphs = new Array<Teraph>();
for(let i = ROLE_TERAPH.START; i <= ROLE_TERAPH.END; i++) {
let p = new Teraph();
p.id = i;
p.grade = 1;
p.hp = 0;
p.atk = 0;
p.def = 0;
p.mdef = 0;
p.agi = 0;
p.luk = 0;
let p = new Teraph(i);
teraphs.push(p);
}
return teraphs;
@@ -114,8 +137,8 @@ export default class Role extends BaseModel {
lv: number; // 主公等级
@prop({ required: true, default: 0, set: (val: number) => val, get: (val: number) => reduceCe(val) })
ce: number; // 总战力
@prop({ required: true, default: new CeAttrRole(), _id: false })
globalCeAttr: CeAttrRole; // 总战力
@prop({ required: true, type: CeAttrDataRole, default: [], _id: false })
attr: CeAttrDataRole[]; // 总战力
@prop({ required: true, default: 0, set: (val: number) => val, get: (val: number) => reduceCe(val) })
topLineupCe: number; // 最强x人战力
@prop({ required: true, type: TopHero, default: [], _id: false })
@@ -227,7 +250,7 @@ export default class Role extends BaseModel {
@prop({ required: true, default: 0 })
updatedMailAt: number;
public static async findAllByUid(uid: number, lean = true) {
const role: RoleType[] = await RoleModel.find({ 'userInfo.uid': uid }).select('roleId roleName serverId').lean(lean);
const role: RoleType[] = await RoleModel.find({ 'userInfo.uid': uid }).select('roleId roleName serverId headHid sHid lv updatedAt').lean(lean);
return role;
}
@@ -242,8 +265,8 @@ export default class Role extends BaseModel {
* @param select 选取字段,来自 selectConst/ROLE
* @param getters 是否使用get方法如ce使用了自动缩小1w倍
*/
public static async findByRoleId(roleId: string, select?: string, getters = false) {
const role: RoleType = await RoleModel.findOne({ roleId }).select(select).lean({getters});
public static async findByRoleId(roleId: string, select?: string, getters = false, virtuals = true) {
const role: RoleType = await RoleModel.findOne({ roleId }).select(select).lean({getters, virtuals});
return role;
}
@@ -252,9 +275,8 @@ export default class Role extends BaseModel {
if (!user) return null;
const doc = new RoleModel();
const update = Object.assign(doc.toJSON(), roleInfo, { userInfo: user, serverType: user.serverType, serverId });
initRoleAtrr(update);
const role: RoleType = await RoleModel.findOneAndUpdate({ 'userInfo.uid': uid, serverId }, update, { upsert: true, new: true }).lean(lean);
initRoleAtrr(role);
return role;
}
@@ -427,7 +449,7 @@ export default class Role extends BaseModel {
return recs
}
public static async updateRoleInfo(roleId: string, roleUpdate:roleUpdate, lean = true) {
public static async updateRoleInfo(roleId: string, roleUpdate:RoleUpdate, lean = true) {
delete roleUpdate._id;
let result: RoleType = await RoleModel.findOneAndUpdate({roleId}, {$set:roleUpdate}, {new: true}).lean(lean);
return result;
@@ -519,4 +541,4 @@ export default class Role extends BaseModel {
export const RoleModel = getModelForClass(Role);
export interface RoleType extends Pick<DocumentType<Role>, keyof Role>{};
type roleUpdate = Partial<RoleType>; // 将所有字段变成可选项
export type RoleUpdate = Partial<RoleType>; // 将所有字段变成可选项

View File

@@ -3,6 +3,8 @@ import { CounterModel } from './Counter';
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose';
import { genCode } from '../pubUtils/util';
const bcrypt = require('bcrypt');
const SALT_WORK_FACTOR = 5
/**
* 用户字段接口
@@ -24,16 +26,42 @@ export default class User extends BaseModel {
token: string;
@prop({ required: true })
tel: string;
tel: string; // 账号
@prop({ required: true, default: '' })
telHash: string;
@prop({ required: true })
password: string;
@prop({ required: true })
salt: string;
@prop({ required: true, default: '' })
channelId: string;
// 游客相关
@prop({ required: false, default: false })
isGuest: boolean; // 是否是游客
@prop({ required: false })
guestId: string;
guestId: string; // 游客id
@prop({ required: false, default: 0 })
guestTime: number; // 游客体验时间
// 防沉迷相关
@prop({ required: false, default: false })
hasAuthenticated: boolean; // 是否是已认证
@prop({ required: false })
birthday: string; // 生日年月
@prop({ required: false })
pi: string; // 已通过实名认证用户唯一标识
@prop({ required: false, default: 0 })
todayPlayTime: number; // 今日游戏时间
@prop({ required: false })
reportTime: Date; // 汇报时间
@prop({ required: false, default: false })
hasSetPw: boolean; // 是否设置过密码
// 最后登录 IP
@prop({ required: false })
@@ -52,6 +80,9 @@ export default class User extends BaseModel {
unionId: string; // 用户标识
}];
@prop({ required: true, type: String, default: [], _id: false })
device: string[];
@prop({ required: true, default: 'com.bantu.zyz' })
pkgName: string;
@@ -67,23 +98,77 @@ export default class User extends BaseModel {
@prop({ required: true, default: 0 })
auth: number;
public static async updateToken(tel: string, token: string, platform: string, pkgName: string, serverType: string, lean = true) {
let user: UserType = await UserModel.findOne({ tel }).lean();
public static async createUser(isGuest: boolean, tel: string, token: string, platform: string, pkgName: string, serverType: string, deviceId: string, guestTime?: number) {
const curTime: Date = new Date();
const uid = await CounterModel.getNewCounter(COUNTER.UID);
const userCode = genCode(8);
const doc = new UserModel();
let update = {};
if (!user) {
const uid = await CounterModel.getNewCounter(COUNTER.UID);
const userCode = genCode(8);
const doc = new UserModel();
update = Object.assign(update, { platform, pkgName, serverType, createTime: curTime, uid, userCode, username: `用户${uid}` }, doc.toJSON());
}
update = Object.assign(update, { token, lastLoginTime: curTime });
user = await UserModel.findOneAndUpdate({ tel }, update, { upsert: true, new: true }).lean(lean);
update = Object.assign(update, doc.toJSON(), { platform, pkgName, serverType, createTime: curTime, uid, userCode, username: `用户${uid}`, isGuest, token, lastLoginTime: curTime, guestTime });
if(isGuest) update["guestId"] = tel;
delete update["device"];
const user: UserType = await UserModel.findOneAndUpdate({ tel }, { $set: update, $addToSet: {device: deviceId}}, { upsert: true, new: true }).lean();
return user;
}
public static async getLastDeviceGuest(deviceId: string) {
const user: UserType = await UserModel.findOne({ device: { $elemMatch: { $eq: deviceId } }, isGuest: true }).sort({createTime: -1}).lean();
return user;
}
public static async updateToken(tel: string, token: string, deviceId: string, lean = true) {
const curTime: Date = new Date();
let user = await UserModel.findOneAndUpdate({ tel }, { $set: { token, lastLoginTime: curTime }, $addToSet: {device: deviceId}}, { new: true }).lean(lean);
return user;
}
public static async createOrUpdate(isGuest: boolean, tel: string, token: string, platform: string, pkgName: string, serverType: string, deviceId: string) {
let user: UserType = await UserModel.findOne({ tel }).lean();
if (!user) {
user = await UserModel.createUser(isGuest, tel, token, platform, pkgName, serverType, deviceId);
} else {
user = await UserModel.updateToken(tel, token, deviceId);
}
return user;
}
private static async encryptPass(password: string, salt?: string) {
if (!salt) {
salt = await bcrypt.genSalt(SALT_WORK_FACTOR);
}
let npassword = await bcrypt.hash(password, salt);
return { npassword, salt };
}
public static async setPass(uid: number, password: string, lean = true) {
let r = await this.encryptPass(password);
const user: UserType = await UserModel.findOneAndUpdate({ uid }, { $set: { password: r.npassword, salt: r.salt, hasSetPw: true }}, {new: true}).lean(lean);
return user;
}
public static async bindTel(uid: number, tel: string, lean = true) {
const user: UserType = await UserModel.findOneAndUpdate({ uid, isGuest: true }, { $set: { tel, isGuest: false }}, {new: true}).lean(lean);
return user;
}
public static async checkPass(tel: string, password: string, token: string, deviceId: string, lean = true) {
const user: UserType = await UserModel.findOne({ tel }).select('salt').lean();
if (user) {
const curTime: Date = new Date();
let { salt } = user;
let { npassword } = await this.encryptPass(password, salt);
const checkUser: UserType = await UserModel.findOneAndUpdate({ tel, password: npassword }, { $set: { token, lastLoginTime: curTime }, $addToSet: {device: deviceId}}, { new: true }).lean(lean);
return checkUser;
} else {
return null
}
}
public static async findUserByToken(token: string, lean = true) {
const user: UserType = await UserModel.findOne({ token }).select('uid token serverType auth userCode').lean(lean);
const user: UserType = await UserModel.findOne({ token }).select('uid token serverType auth tel userCode pkgName').lean(lean);
return user;
}
@@ -93,7 +178,7 @@ export default class User extends BaseModel {
}
public static async findUserByTel(tel: string, lean = true) {
const user: UserType = await UserModel.findOne({ tel }).select('uid tel').lean(lean);
const user: UserType = await UserModel.findOne({ tel }).select('uid tel hasSetPw').lean(lean);
return user;
}
@@ -102,8 +187,18 @@ export default class User extends BaseModel {
return user;
}
public static async findUserByUserCode(userCode: string, lean = true) {
const user: UserType = await UserModel.findOne({ userCode }).lean(lean);
return user;
}
public static async addAuth(uid: number, auth: number, lean = true) {
const user: UserType = await UserModel.findOneAndUpdate({ uid }, { auth }).select('uid tel').lean(lean);
const user: UserType = await UserModel.findOneAndUpdate({ uid }, { auth }, {new: true}).select('uid tel').lean(lean);
return user;
}
public static async authentication(uid: number, birthday: string, pi: string, lean = true) {
const user: UserType = await UserModel.findOneAndUpdate({ uid }, { hasAuthenticated: true, birthday, pi }, {new: true}).lean(lean);
return user;
}
@@ -117,8 +212,15 @@ export default class User extends BaseModel {
const user: UserType[] = await UserModel.find(searchObj).select('uid tel username serverType auth').lean(lean);
return user;
}
public static async updatePlayTime(userCode: string, guestTimeInc: number, todayPlayTime: number, lean = true) {
const user: UserType = await UserModel.findOneAndUpdate({ userCode }, { $inc: { guestTime: guestTimeInc }, $set: { todayPlayTime, reportTime: new Date() }}, { new: true }).lean(lean);
return user;
}
}
export const UserModel = getModelForClass(User);
export interface UserType extends Pick<DocumentType<User>, keyof User>{};

View File

@@ -1,7 +1,7 @@
import { prop } from '@typegoose/typegoose';
import { DicWarJson } from '../pubUtils/dictionary/DicWarJson';
import { HeroType } from '../db/Hero';
import { CeAttrNumber } from './roleField/attribute';
import { Attribute } from './roleField/attribute';
// 从玩家数据中覆盖warjson的部分字段
export class PvpHeroInfo {
@@ -27,7 +27,7 @@ export class PvpHeroInfo {
quality?: number = 0; // 品质
@prop({ required: true, _id: false })
attribute?: CeAttrNumber; // 属性
attribute?: Attribute; // 属性
setHeroInfo(hero: HeroType) {
this.actorId = hero.hid;
@@ -46,7 +46,7 @@ export class PvpHeroInfo {
this.quality = quality;
}
setAttribute(attribute: CeAttrNumber) {
setAttribute(attribute: Attribute) {
this.attribute = attribute;
}

View File

@@ -0,0 +1,69 @@
import { ServerInfo } from '../../db/Game';
import { RoleType } from '../../db/Role';
import { getSeconds } from '../../pubUtils/timeUtil';
export class ServerParam {
id: number; // 区号
serverStr: string; // 显示的区号 S1
name: string; // 区名
host: string; // pinus地址
port: number; // pinus端口
status: number; // 状态
openTime: number; // 开服时间
serverType: string; // 分区类型 官服 测试服 开发服
constructor(server: ServerInfo) {
this.id = server.id;
this.serverStr = `S${this.id}`;
this.name = server.name;
this.host = server.host;
this.port = server.port;
this.status = server.status;
this.openTime = getSeconds(server.openTime);
this.serverType = server.serverType;
}
}
export class GroupParam {
groupId: number; // 大区号
groupName: string; // 大区名
groupStr: string; // 大区内小区编号 S1-S10
servers: ServerParam[]; // 区
constructor(server: ServerInfo) {
this.groupId = server.groupId;
this.groupName = server.groupName;
this.groupStr = `S${server.id}-S${server.id + 9}`;
this.servers = new Array<ServerParam>();
}
public pushServer(server: ServerInfo) {
let srv = new ServerParam(server);
this.servers.push(srv);
}
}
export class ServerParamWithRole extends ServerParam {
groupId: number; // 大区号
groupName: string; // 大区名
roleId: string; // 玩家账号
roleName: string; // 玩家名
headHid: number; // 头像
sHid: number; // 形象
lv: number; // 等级
updatedAt: Date;
constructor(role: RoleType, server: ServerInfo) {
super(server);
this.groupId = server.groupId;
this.groupName = server.groupName;
this.roleId = role.roleId;
this.roleName = role.roleName;
this.headHid = role.headHid;
this.sHid = role.sHid;
this.lv = role.lv;
this.updatedAt = role.updatedAt;
}
}

View File

@@ -1,7 +1,11 @@
import { prop } from '@typegoose/typegoose';
import { HERO_CE_RATIO, getAtrrNameById, CE_CONST, HERO_SUB_ATTR_RATIO } from '../../consts';
import { reduceCe } from '../../pubUtils/util';
// hero表内属性基础格式
export class CeAttrData {
@prop({ required: true })
id: number = 0;
@prop({ required: true })
base: number = 0;
@prop({ required: true })
@@ -10,134 +14,175 @@ export class CeAttrData {
fixUp: number = 0;
@prop({ required: true })
equipUp: number = 0;
}
// hero表全属性
export class CeAttr {
@prop({ required: false, _id: false })
hp?: CeAttrData = new CeAttrData();
@prop({ required: false, _id: false })
atk?: CeAttrData = new CeAttrData();
@prop({ required: false, _id: false })
matk?: CeAttrData = new CeAttrData();
@prop({ required: false, _id: false })
def?: CeAttrData = new CeAttrData();
@prop({ required: false, _id: false })
mdef?: CeAttrData = new CeAttrData();
@prop({ required: false, _id: false })
agi?: CeAttrData = new CeAttrData();
@prop({ required: false, _id: false })
luk?: CeAttrData = new CeAttrData();
@prop({ required: false, _id: false })
hit?: CeAttrData = new CeAttrData();
@prop({ required: false, _id: false })
cri?: CeAttrData = new CeAttrData();
@prop({ required: false, _id: false })
flee?: CeAttrData = new CeAttrData();
@prop({ required: false, _id: false })
antCri?: CeAttrData = new CeAttrData();
@prop({ required: false, _id: false })
damageIncrease?: CeAttrData = new CeAttrData();
@prop({ required: false, _id: false })
damageDecrease?: CeAttrData = new CeAttrData();
@prop({ required: false, _id: false })
defIngnore?: CeAttrData = new CeAttrData();
@prop({ required: false, _id: false })
bloodSuck?: CeAttrData = new CeAttrData();
constructor(id: number) {
this.id = id;
}
}
// role表属性格式
export class CeAttrDataRole {
@prop({ required: true })
id: number = 0;
@prop({ required: true })
ratioUp: number = 0;
@prop({ required: true })
fixUp: number = 0;
}
// role表全属性
export class CeAttrRole {
@prop({ required: false, _id: false })
hp?: CeAttrDataRole = new CeAttrDataRole();
@prop({ required: false, _id: false })
atk?: CeAttrDataRole = new CeAttrDataRole();
@prop({ required: false, _id: false })
matk?: CeAttrDataRole = new CeAttrDataRole();
@prop({ required: false, _id: false })
def?: CeAttrDataRole = new CeAttrDataRole();
@prop({ required: false, _id: false })
mdef?: CeAttrDataRole = new CeAttrDataRole();
@prop({ required: false, _id: false })
agi?: CeAttrDataRole = new CeAttrDataRole();
@prop({ required: false, _id: false })
luk?: CeAttrDataRole = new CeAttrDataRole();
@prop({ required: false, _id: false })
hit?: CeAttrDataRole = new CeAttrDataRole();
@prop({ required: false, _id: false })
cri?: CeAttrDataRole = new CeAttrDataRole();
@prop({ required: false, _id: false })
flee?: CeAttrDataRole = new CeAttrDataRole();
@prop({ required: false, _id: false })
antCri?: CeAttrDataRole = new CeAttrDataRole();
@prop({ required: false, _id: false })
damageIncrease?: CeAttrDataRole = new CeAttrDataRole();
@prop({ required: false, _id: false })
damageDecrease?: CeAttrDataRole = new CeAttrDataRole();
@prop({ required: false, _id: false })
defIngnore?: CeAttrDataRole = new CeAttrDataRole();
@prop({ required: false, _id: false })
bloodSuck?: CeAttrDataRole = new CeAttrDataRole();
}
// 所有属性使用数字格式
export class CeAttrNumber {
@prop({ required: false })
hp?: number = 0;
@prop({ required: false })
atk?: number = 0;
@prop({ required: false })
matk?: number = 0;
@prop({ required: false })
def?: number = 0;
@prop({ required: false })
mdef?: number = 0;
@prop({ required: false })
agi?: number = 0;
@prop({ required: false })
luk?: number = 0;
@prop({ required: false })
hit?: number = 0;
@prop({ required: false })
cri?: number = 0;
@prop({ required: false })
flee?: number = 0;
@prop({ required: false })
antCri?: number = 0;
@prop({ required: false })
damageIncrease?: number = 0;
@prop({ required: false })
damageDecrease?: number = 0;
@prop({ required: false })
defIngnore?: number = 0;
@prop({ required: false })
bloodSuck?: number = 0;
constructor(id: number) {
this.id = id;
}
}
// 主属性
export class MainAttrNumber {
hp: number = 0;
atk: number = 0;
matk: number = 0;
def: number = 0;
mdef: number = 0;
agi: number = 0;
luk: number = 0;
constructor(attr: CeAttrNumber) {
constructor(attr: Attribute) {
if(attr.hp) this.hp = attr.hp;
if(attr.atk) this.atk = attr.atk;
if(attr.def) this.def = attr.def;
if(attr.mdef) this.mdef = attr.mdef;
if(attr.agi) this.agi = attr.agi;
if(attr.luk) this.luk = attr.luk;
}
}
export class Attribute {
@prop({ required: false })
hp: number = 0;
@prop({ required: false })
atk: number = 0;
@prop({ required: false })
def: number = 0;
@prop({ required: false })
mdef: number = 0;
@prop({ required: false })
speed: number = 0;
@prop({ required: false })
hit: number = 0;
@prop({ required: false })
cri: number = 0;
@prop({ required: false })
flee: number = 0;
@prop({ required: false })
antCri: number = 0;
@prop({ required: false })
damageIncrease: number = 0;
@prop({ required: false })
damageDecrease: number = 0;
@prop({ required: false })
defIngnore: number = 0;
@prop({ required: false })
bloodSuck: number = 0;
@prop({ required: false })
ap: number = 0;
@prop({ required: false })
damageCri: number = 0;
setByDbData(roleAttrs: CeAttrDataRole[], heroAttrs: CeAttrData[]) {
for(let { id, fixUp: roleFix, ratioUp: roleRatio } of roleAttrs) {
let attrName = getAtrrNameById(id);
let heroAttr = heroAttrs.find(heroAttr => heroAttr.id == id);
if(heroAttr) {
let { fixUp: heroFix, base: heroBase, ratioUp: heroRatio, equipUp: heroEquip } = heroAttr;
let value = this.calAttrValue(roleFix, roleRatio, heroBase, heroFix, heroRatio, heroEquip);
if(attrName in this) this[attrName] = value;
} else {
let value = this.calAttrValue(roleFix, roleRatio, 0, 0, 0, 0);
if(attrName in this) this[attrName] = value;
}
}
for(let { id, base: heroBase, fixUp: heroFix, ratioUp: heroRatio, equipUp: heroEquip } of heroAttrs) {
let attrName = getAtrrNameById(id);
let roleAttr = roleAttrs.find(roleAttr => roleAttr.id == id);
if(!roleAttr) {
let value = this.calAttrValue(0, 0, heroBase, heroFix, heroRatio, heroEquip);
if(attrName in this) this[attrName] = value;
}
}
}
setByWarJson( attributes: {id: number, val: number}[], ratio: number = 1) {
for(let {id, val} of attributes) {
let attrName = getAtrrNameById(id);
if(attrName in this) this[attrName] = Math.floor(val * ratio * HERO_CE_RATIO * HERO_CE_RATIO);
}
}
private calAttrValue(roleFix: number = 0, roleRatio: number = 0, heroBase: number = 0, heroFix: number = 0, heroRatio: number = 0, heroEquip: number = 0) {
return (heroFix + heroEquip + roleFix) * HERO_CE_RATIO + heroBase * ( HERO_CE_RATIO + heroRatio + roleRatio );
}
private getRealSubAttr() {
return {
hit: this.hit / HERO_SUB_ATTR_RATIO / HERO_CE_RATIO / HERO_CE_RATIO,
cri: this.cri / HERO_SUB_ATTR_RATIO / HERO_CE_RATIO / HERO_CE_RATIO,
flee: this.flee / HERO_SUB_ATTR_RATIO / HERO_CE_RATIO / HERO_CE_RATIO,
antCri: this.antCri / HERO_SUB_ATTR_RATIO / HERO_CE_RATIO / HERO_CE_RATIO,
damageIncrease: this.damageIncrease / HERO_SUB_ATTR_RATIO / HERO_CE_RATIO / HERO_CE_RATIO,
damageDecrease: this.damageDecrease / HERO_SUB_ATTR_RATIO / HERO_CE_RATIO / HERO_CE_RATIO,
defIngnore: this.defIngnore / HERO_SUB_ATTR_RATIO / HERO_CE_RATIO / HERO_CE_RATIO,
damageCri: this.damageCri / HERO_SUB_ATTR_RATIO / HERO_CE_RATIO / HERO_CE_RATIO
}
}
private getRealMainAttr() {
return {
hp: this.hp / HERO_CE_RATIO / HERO_CE_RATIO,
atk: this.atk / HERO_CE_RATIO / HERO_CE_RATIO,
def: this.def / HERO_CE_RATIO / HERO_CE_RATIO,
mdef: this.mdef / HERO_CE_RATIO / HERO_CE_RATIO
}
}
public getReduceAttributes() {
let newAttr = new Attribute();
newAttr.hp = reduceCe(this.hp);
newAttr.atk = reduceCe(this.atk);
newAttr.def = reduceCe(this.def);
newAttr.mdef = reduceCe(this.mdef);
newAttr.speed = reduceCe(this.speed);
newAttr.hit = reduceCe(this.hit);
newAttr.cri = reduceCe(this.cri);
newAttr.flee = reduceCe(this.flee);
newAttr.antCri = reduceCe(this.antCri);
newAttr.damageIncrease = reduceCe(this.damageIncrease);
newAttr.damageDecrease = reduceCe(this.damageDecrease);
newAttr.defIngnore = reduceCe(this.defIngnore);
newAttr.bloodSuck = reduceCe(this.bloodSuck);
newAttr.ap = reduceCe(this.ap);
newAttr.damageCri = reduceCe(this.damageCri);
return newAttr;
}
// 战力计算
public calCe() {
let { hp, atk, def, mdef } = this.getRealMainAttr();
let { cri, flee, damageIncrease, damageDecrease, damageCri } = this.getRealSubAttr();
let putHit = CE_CONST.PUT_HIT / HERO_SUB_ATTR_RATIO;
let putAntCri = CE_CONST.PUT_ANT_CRI / HERO_SUB_ATTR_RATIO;
let hitRate = CE_CONST.HIT_RATE_BASE + putHit/2 - flee; // 命中率
if(hitRate > CE_CONST.HIT_RATE_MAX) hitRate = CE_CONST.HIT_RATE_MAX;
if(hitRate < CE_CONST.HIT_RATE_MIN) hitRate = CE_CONST.HIT_RATE_MIN;
let fleeRate = 1 - hitRate; // 格挡率
let criRate = CE_CONST.CRI_RATE_BASE + cri - putAntCri/2;
if(criRate > CE_CONST.CRI_RATE_MAX) criRate = CE_CONST.CRI_RATE_MAX;
if(criRate < CE_CONST.CRI_RATE_MIN) criRate = CE_CONST.CRI_RATE_MIN;
let criValue = CE_CONST.CRI_VALUE_BASE + damageCri;
let validHp = hp + (def + mdef) * 0.5 / ((1 - fleeRate * CE_CONST.FLEE_VALUE) * (1 - damageDecrease)); // 有效生命
let validAtk = atk * hitRate * ( 1 + criRate * criValue) * ( 1 + damageIncrease); // 有效输出
let ce = Math.floor(validHp * validAtk * HERO_CE_RATIO * HERO_CE_RATIO);
return ce > 0? ce: 1;
}
public calCelAndReduce() {
return Math.floor(this.calCe() / HERO_CE_RATIO / HERO_CE_RATIO);
}
}

View File

@@ -35,7 +35,6 @@ import { dicTeraph } from './dictionary/DicTeraph';
import { dicSchool } from './dictionary/DicSchool';
import { dicSchoolRate } from './dictionary/DicSchoolRate';
import { dicHeroScroll, preHeroScroll } from './dictionary/DicHeroScroll';
import { ABI_TYPE_TO_STAGE } from "../consts";
import { dicPvpOpponent } from './dictionary/DicPvpOpponent';
import { dicPvpTeamLevel } from './dictionary/DicPvpTeamLevel';
import { dicPvpRefreshConsume, maxPvpRefreshCnt } from './dictionary/DicPvpRefreshConsume';
@@ -58,6 +57,7 @@ import { dicArmyBossRank } from '../pubUtils/dictionary/DicArmyBossRank';
import { dicArmyDonate } from '../pubUtils/dictionary/DicArmyDonateBoxReward';
import { dicRoleFriend } from "./dictionary/DicRoleFriend";
import { dicRoleFriendLv } from "./dictionary/DicRoleFriendLv";
import { Attribute } from "../domain/roleField/attribute";
export const gameData = {
blurprtCompose: dicBlueprtCompose,
@@ -213,7 +213,11 @@ export function getBossHpByWarId(warId: number) {
warInfo.forEach(hero => {
let { attribute, dataId, relation, actorId } = hero;
if (relation === 2) {
const hp = attribute.hp||0;
let newAttr = new Attribute();
newAttr.setByWarJson(attribute, 1);
let attrJson = newAttr.getReduceAttributes();
const hp = attrJson.hp||0;
if (hp > 0) {
bossHpArr.push({dataId, hp, actorId});
bossHpSum += hp;
@@ -300,17 +304,6 @@ export function getScollByStar(quality: number, star: number, curQuality: number
return heroScroll;
}
// 根据存在升星表等的stage字段的id对应17维id
export function getFieldByStage(stage: number, jobid: number) {
let targetAttrId = ABI_TYPE_TO_STAGE.get(stage);
if(typeof targetAttrId === 'number') {
return targetAttrId
} else {
const dicJob = gameData.job.get(jobid);
return targetAttrId(dicJob.type);
}
}
export function getSuit(id: number) {
const suitInfo = gameData.suit.get(id);
return suitInfo;
@@ -420,7 +413,7 @@ export function getArmyWishPoolBaseByLv(lv: number) {
export function getFriendLvByExp(exp: number) {
let resultLv = 1;
for(let [lv, {sum}] of gameData.roleFriendLv) {
for(let [lv, {sum}] of gameData.roleFriendLv.entries()) {
resultLv = lv;
if(exp < sum) break;
}

View File

@@ -152,12 +152,10 @@ function parseAbility(json) {
let map = new Map<number, number>();
map.set(ABI_TYPE.ABI_HP, json.hp||0);
map.set(ABI_TYPE.ABI_ATK, json.atk||0);
map.set(ABI_TYPE.ABI_MATK, json.matk||0);
map.set(ABI_TYPE.ABI_DEF, json.def||0);
map.set(ABI_TYPE.ABI_MDEF, json.mdef||0);
map.set(ABI_TYPE.ABI_AGI, json.agi||0);
map.set(ABI_TYPE.ABI_LUK, json.luk||0);
map.set(ABI_TYPE.ABI_SPEED, json.speed||0);
map.set(ABI_TYPE.ABI_DAMAGE_INCREASE, json.damageIncrease||0);
map.set(ABI_TYPE.ABI_DAMAGE_DECREASE, json.damageDecrease||0);
return map
}
@@ -165,12 +163,10 @@ function parseAbilityUp(json) {
let map = new Map<number, number>();
map.set(ABI_TYPE.ABI_HP, json.hp_up||0);
map.set(ABI_TYPE.ABI_ATK, json.atk_up||0);
map.set(ABI_TYPE.ABI_MATK, json.matk_up||0);
map.set(ABI_TYPE.ABI_DEF, json.def_up||0);
map.set(ABI_TYPE.ABI_MDEF, json.mdef_up||0);
map.set(ABI_TYPE.ABI_AGI, json.agi_up||0);
map.set(ABI_TYPE.ABI_LUK, json.luk_up||0);
map.set(ABI_TYPE.ABI_SPEED, json.speed_up||0);
map.set(ABI_TYPE.ABI_DAMAGE_INCREASE, json.damageIncrease_up||0);
map.set(ABI_TYPE.ABI_DAMAGE_DECREASE, json.damageDecrease_up||0);
return map
}

View File

@@ -46,12 +46,8 @@ function parseBaseAbilityArr(json) {
let map = new Map<number, number>();
map.set(ABI_TYPE.ABI_HP, json.hp||0);
map.set(ABI_TYPE.ABI_ATK, json.atk||0);
map.set(ABI_TYPE.ABI_MATK, json.matk||0);
map.set(ABI_TYPE.ABI_DEF, json.def||0);
map.set(ABI_TYPE.ABI_MDEF, json.mdef||0);
map.set(ABI_TYPE.ABI_AGI, json.agi||0);
map.set(ABI_TYPE.ABI_LUK, json.luk||0);
map.set(ABI_TYPE.ABI_SPEED, json.speed||0);
return map
}
@@ -59,11 +55,7 @@ function parseBaseAbilityUpArr(json) {
let map = new Map<number, number>();
map.set(ABI_TYPE.ABI_HP, json.hp_up||0);
map.set(ABI_TYPE.ABI_ATK, json.atk_up||0);
map.set(ABI_TYPE.ABI_MATK, json.matk_up||0);
map.set(ABI_TYPE.ABI_DEF, json.def_up||0);
map.set(ABI_TYPE.ABI_MDEF, json.mdef_up||0);
map.set(ABI_TYPE.ABI_AGI, json.agi_up||0);
map.set(ABI_TYPE.ABI_LUK, json.luk_up||0);
map.set(ABI_TYPE.ABI_SPEED, json.speed_up||0);
return map
}

View File

@@ -41,7 +41,5 @@ function parseCeAttr(elem) {
ceAttr.set(ABI_STAGE.ATK, elem.atk);
ceAttr.set(ABI_STAGE.DEF, elem.def);
ceAttr.set(ABI_STAGE.MDEF, elem.mdef);
ceAttr.set(ABI_STAGE.AGI, elem.agi);
ceAttr.set(ABI_STAGE.LUK, elem.luk);
return ceAttr;
}

View File

@@ -36,7 +36,6 @@ function parseCeAttr(elem) {
ceAttr.set(ABI_STAGE.ATK, elem.atk_up);
ceAttr.set(ABI_STAGE.DEF, elem.def_up);
ceAttr.set(ABI_STAGE.MDEF, elem.mdef_up);
ceAttr.set(ABI_STAGE.AGI, elem.agi_up);
ceAttr.set(ABI_STAGE.LUK, elem.luk_up);
return ceAttr;
}
}
arr = undefined;

View File

@@ -40,7 +40,5 @@ function parseCeAttr(elem) {
ceAttr.set(ABI_STAGE.ATK, elem.atk_up);
ceAttr.set(ABI_STAGE.DEF, elem.def_up);
ceAttr.set(ABI_STAGE.MDEF, elem.mdef_up);
ceAttr.set(ABI_STAGE.AGI, elem.agi_up);
ceAttr.set(ABI_STAGE.LUK, elem.luk_up);
return ceAttr;
}

View File

@@ -1,6 +1,6 @@
// 兵种表
import {readJsonFile, parseNumberList, parseGoodStr} from '../util'
import { FILENAME } from '../../consts'
import { FILENAME, ABI_STAGE } from '../../consts'
import { RewardInter } from '../interface';
const _ = require('lodash');
@@ -23,18 +23,8 @@ export interface DicJob {
readonly trainingConsume: Array<RewardInter>;
// 升阶消耗
readonly upGradeConsume: Array<RewardInter>;
// 生命训练提升
readonly hp: number;
// 攻击力训练提升
readonly atk: number;
// 防御力训练提升
readonly def: number;
// 策防训练提升
readonly mdef: number;
// 敏捷训练提升
readonly agi: number;
// 幸运训练提升
readonly luk: number;
// 每阶升级属性
readonly ceAttr: Map<number, number>
}
@@ -42,7 +32,7 @@ const str = readJsonFile(FILENAME.DIC_JOB);
let arr = JSON.parse(str);
type KeysEnum<T> = { [P in keyof Required<T>]: true };
const DicJobKeys: KeysEnum<DicJob> = {jobid: true, name: true, grade: true, unlockLevel: true, job_class: true, type: true, seid: true,trainingConsume: true, upGradeConsume: true, hp: true, atk: true, def: true, mdef: true, agi: true, luk: true};
const DicJobKeys: KeysEnum<DicJob> = {jobid: true, name: true, grade: true, unlockLevel: true, job_class: true, type: true, seid: true,trainingConsume: true, upGradeConsume: true, ceAttr: true};
export const dicJob = new Map<number, DicJob>();
export const jobClassMaxGrades = new Map<number, {grade:number, jobid:number}>();
@@ -52,6 +42,7 @@ arr.forEach(o => {
o.seid = parseNumberList(o.seid);
o.trainingConsume = parseGoodStr(o.trainingConsume);
o.upGradeConsume = parseGoodStr(o.upGradeConsume);
o.ceAttr = parseCeAttr(o);
dicJob.set(o.jobid, _.pick(o, Object.keys(DicJobKeys)));
let jobClass = jobClassMaxGrades.get(o.job_class);
if (!!jobClass && jobClass.grade < o.grade) {
@@ -61,4 +52,13 @@ arr.forEach(o => {
});
function parseCeAttr(elem) {
let ceAttr = new Map<number, number>();
ceAttr.set(ABI_STAGE.HP, elem.hp);
ceAttr.set(ABI_STAGE.ATK, elem.atk);
ceAttr.set(ABI_STAGE.DEF, elem.def);
ceAttr.set(ABI_STAGE.MDEF, elem.mdef);
return ceAttr;
}
arr = undefined;

View File

@@ -1,6 +1,7 @@
// 物品表
import { decodeArrayListStr, readJsonFile, parseGoodStr } from '../util'
import { FILENAME} from '../../consts'
import { FILENAME, ABI_TYPE} from '../../consts'
import { RewardInter } from '../interface';
const _ = require('lodash');
export interface SpecialMaterial {
@@ -13,25 +14,16 @@ export interface DicTeraph {
readonly id: number;
readonly index: number;
readonly grade: number;
readonly hpMax: number;
readonly atkMax: number;
readonly defMax: number;
readonly mdefMax: number;
readonly agiMax: number;
readonly lukMax: number;
readonly hp;
readonly atk;
readonly def;
readonly mdef;
readonly agi;
readonly luk;
readonly criRate;
readonly criEffect;
readonly upMaterial:Array<{id: number, number: number}>;
readonly mainAttrMax: Map<number, number>; // 最大强化加成 id => value 18围内的id
readonly mainAttrUp: Map<number, number>; // 每次强化加成 id => value 18围内的id
readonly criRate: number;
readonly criEffect: number;
readonly upMaterial:Array<RewardInter>;
readonly assiAttrValue:Array<{id: number, number: number}>;
readonly upGradeMaterial:Array<{id: number, number: number}>;
readonly assiAttrValue:Map<number, number>; // 次级属性
readonly upGradeMaterial:Array<RewardInter>;
}
const str = readJsonFile(FILENAME.DIC_TERAPH);
@@ -42,18 +34,8 @@ const DicTeraphKeys: KeysEnum<DicTeraph> = {
id: true,
index: true,
grade: true,
hpMax: true,
atkMax: true,
defMax: true,
mdefMax: true,
agiMax: true,
lukMax: true,
hp: true,
atk: true,
def: true,
mdef: true,
agi: true,
luk: true,
mainAttrMax: true,
mainAttrUp: true,
criRate: true,
criEffect: true,
upMaterial: true,
@@ -65,26 +47,40 @@ arr.forEach(o => {
o.assiAttrValue = parseAttr(o.assiAttrValue);
o.upGradeMaterial = parseGoodStr(o.upGradeMaterial);
o.upMaterial = parseGoodStr(o.upMaterial);
o.hp = o.hpUp;
o.atk = o.atkUp;
o.def = o.defUp;
o.mdef = o.mdefUp;
o.agi = o.agiUp;
o.luk = o.lukUp;
o.mainAttrMax = parseMainAttrMax(o);
o.mainAttrUp = parseMainAttrUp(o);
dicTeraph.set(o.index + '_' + o.grade, _.pick(o, Object.keys(DicTeraphKeys)));
});
arr = undefined;
function parseAttr(str: string) {
let result = new Array<{id: number, number: number}>();
let result = new Map<number, number>();
if(!str) return result;
let decodeArr = decodeArrayListStr(str);
for(let [id, number] of decodeArr) {
if(isNaN(parseInt(id)) || isNaN(parseInt(number))) {
throw new Error('data table format wrong');
}
result.push({id: parseInt(id), number: parseInt(number)});
result.set(parseInt(id), parseInt(number));
}
return result
}
function parseMainAttrMax(elem) {
let result = new Map<number, number>();
result.set(ABI_TYPE.ABI_HP, elem.hpMax);
result.set(ABI_TYPE.ABI_ATK, elem.atkMax);
result.set(ABI_TYPE.ABI_DEF, elem.defMax);
result.set(ABI_TYPE.ABI_MDEF, elem.mdefMax);
return result
}
function parseMainAttrUp(elem) {
let result = new Map<number, number>();
result.set(ABI_TYPE.ABI_HP, elem.hpUp);
result.set(ABI_TYPE.ABI_ATK, elem.atkUp);
result.set(ABI_TYPE.ABI_DEF, elem.defUp);
result.set(ABI_TYPE.ABI_MDEF, elem.mdefUp);
return result
}

View File

@@ -1,6 +1,6 @@
// 物品表
import { decodeArrayListStr, readJsonFile, parseGoodStr } from '../util'
import { FILENAME} from '../../consts'
import { FILENAME, ABI_TYPE} from '../../consts'
const _ = require('lodash');
export interface SpecialMaterial {
@@ -9,15 +9,10 @@ export interface SpecialMaterial {
}
export interface DicTitle {
// 等级
readonly id: number;
readonly hp: number;
readonly atk: number;
readonly def: number;
readonly mdef: number;
readonly agi: number;
readonly luk: number;
readonly assiAttrValue: Array<{id: number, number: number}>;
// 等级
readonly mainAttrValue: Map<number, number>; // id => value 这里的值是上一级的基础上增加的值
readonly assiAttrValue: Map<number, number>; // id => value
// 等级现在
readonly lvLimited: number;
// 升级消耗
@@ -30,18 +25,14 @@ let arr = JSON.parse(str);
type KeysEnum<T> = { [P in keyof Required<T>]: true };
const DicTitleKeys: KeysEnum<DicTitle> = {
id: true,
hp: true,
atk: true,
def: true,
mdef: true,
agi: true,
luk: true,
mainAttrValue: true,
assiAttrValue: true,
lvLimited: true,
material: true
}
export const dicTitle = new Map<number, DicTitle>();
arr.forEach(o => {
o.mainAttrValue = parseMainAttr(o);
o.assiAttrValue = parseAttr(o.assiAttrValue);
o.material = parseGoodStr(o.material);
dicTitle.set(o.id, _.pick(o, Object.keys(DicTitleKeys)));
@@ -50,14 +41,23 @@ arr.forEach(o => {
arr = undefined;
function parseAttr(str: string) {
let result = new Array<{id: number, number: number}>();
let result = new Map<number, number>();
if(!str) return result;
let decodeArr = decodeArrayListStr(str);
for(let [id, number] of decodeArr) {
if(isNaN(parseInt(id)) || isNaN(parseInt(number))) {
for(let [id, value] of decodeArr) {
if(isNaN(parseInt(id)) || isNaN(parseInt(value))) {
throw new Error('data table format wrong');
}
result.push({id: parseInt(id), number: parseInt(number)});
result.set(parseInt(id), parseInt(value));
}
return result
}
function parseMainAttr(elem) {
let result = new Map<number, number>();
result.set(ABI_TYPE.ABI_HP, elem.hp);
result.set(ABI_TYPE.ABI_ATK, elem.atk);
result.set(ABI_TYPE.ABI_DEF, elem.def);
result.set(ABI_TYPE.ABI_MDEF, elem.mdef);
return result;
}

View File

@@ -1,8 +1,5 @@
// 关卡表
import {decodeArrayListStr, readWarJsonFileList} from '../util'
import { ABI_TYPE } from '../../consts';
import { Attributes } from '../interface';
export interface DicWarJson {
@@ -33,7 +30,7 @@ export interface DicWarJson {
// 角色使用的AI类型
readonly initial_ai: number;
// 属性
readonly attribute: Attributes;
readonly attribute: {id: number, val: number}[];
// 武将技能
readonly skill: string;
// 武将被动技能
@@ -63,55 +60,15 @@ readWarJsonFileList().forEach(str => {
dicWarJson.set(warid, warjson);
})
function parseAttribute(str: string) {
let attribute: Attributes = {};
if(!str) return attribute;
let arr = decodeArrayListStr(str);
for(let [id, value] of arr) {
if(isNaN(parseInt(id)) || isNaN(parseInt(value))) {
export function parseAttribute(str: string) {
let result = new Array<{ id: number, val: number }>();
if (!str) return result;
let decodeArr = decodeArrayListStr(str);
for (let [id, val] of decodeArr) {
if (isNaN(parseInt(id)) || isNaN(parseInt(val))) {
throw new Error('data table format wrong');
}
let _id = parseInt(id), _value = parseInt(value);
switch(_id) {
case ABI_TYPE.ABI_HP:
attribute.hp = _value; break;
case ABI_TYPE.ABI_ATK:
attribute.atk = _value; break;
case ABI_TYPE.ABI_MATK:
attribute.matk = _value; break;
case ABI_TYPE.ABI_DEF:
attribute.def = _value; break;
case ABI_TYPE.ABI_MDEF:
attribute.mdef = _value; break;
case ABI_TYPE.ABI_AGI:
attribute.agi = _value; break;
case ABI_TYPE.ABI_LUK:
attribute.luk = _value; break;
case ABI_TYPE.ABI_SPEED:
attribute.speed = _value; break;
case ABI_TYPE.ABI_HIT:
attribute.hit = _value; break;
case ABI_TYPE.ABI_CRI:
attribute.cri = _value; break;
case ABI_TYPE.ABI_FLEE:
attribute.flee = _value; break;
case ABI_TYPE.ABI_ANT_CRI:
attribute.antCri = _value; break;
case ABI_TYPE.ABI_DAMAGE_INCREASE:
attribute.damageIncrease = _value; break;
case ABI_TYPE.ABI_DAMAGE_DECREASE:
attribute.damageDecrease = _value; break;
case ABI_TYPE.ABI_DEF_IGNORE:
attribute.defIngnore = _value; break;
case ABI_TYPE.ABI_BLOOD_SUCK:
attribute.bloodSuck = _value; break;
case ABI_TYPE.ABI_AP:
attribute.ap = _value; break;
default:
break;
}
result.push({ id: parseInt(id), val: parseInt(val) });
}
return attribute
}
return result
}

View File

@@ -373,8 +373,6 @@ function parseHeroStar() {
ceAttr.set(ABI_STAGE.ATK, elem.atk_up);
ceAttr.set(ABI_STAGE.DEF, elem.def_up);
ceAttr.set(ABI_STAGE.MDEF, elem.mdef_up);
ceAttr.set(ABI_STAGE.AGI, elem.agi_up);
ceAttr.set(ABI_STAGE.LUK, elem.luk_up);
heroStarList.set(`${elem.quality}_${elem.star}`,{ceAttr, ...elem});
}
@@ -392,8 +390,6 @@ function parseHeroWake() {
ceAttr.set(ABI_STAGE.ATK, elem.atk_up);
ceAttr.set(ABI_STAGE.DEF, elem.def_up);
ceAttr.set(ABI_STAGE.MDEF, elem.mdef_up);
ceAttr.set(ABI_STAGE.AGI, elem.agi_up);
ceAttr.set(ABI_STAGE.LUK, elem.luk_up);
heroWakeList.set(`${elem.quality}_${elem.star}`,{ceAttr, ...elem});
}

103
shared/pubUtils/httpUtil.ts Normal file
View File

@@ -0,0 +1,103 @@
import * as request from "request-promise";
import * as crypto from 'crypto'
import { BANTU_VID_ADDR, BANTU_VID_APP_KEY } from '../consts';
/**
* 在线报告
* @param userCode 账号
* @param packageName 包名
*/
export async function reportOnline ( userCode: string, packageName: string) {
if(!packageName || packageName==''){
packageName = 'com.bantu.nfsg'
}
let result = await vidHttpRequest(BANTU_VID_ADDR.REPORT_ONLINE, {
account: userCode,
package: packageName
});
if(result && result.code !== 1) {
console.error(result.msg);
}
return result;
}
/**
* 实名认证
* @param name 真实姓名
* @param idNum 身份证号
* @param userCode 账号
* @param packageName 包名
*/
export async function authenticate (name: string, idNum: string, userCode: string, packageName: string) {
if(!packageName || packageName==''){
packageName = 'com.bantu.nfsg'
}
let result = await vidHttpRequest(BANTU_VID_ADDR.IDCARD, {
account: userCode,
cardno: idNum,
name,
appkey: BANTU_VID_APP_KEY,
package: packageName
});
if(result && result.code !== 1) {
console.error(result.msg);
}
return result && result.code == 1;
}
export async function vidHttpRequest(addr: string, body: any) {
body['sign'] = getObjSign(body);
console.log('body: ', JSON.stringify(body))
let options = {
url: BANTU_VID_ADDR.HOST + addr,
method: 'POST',
body:body,
json: true
}
try {
let res = await request(options);
let check = checkSign(res);
if(!check) return false;
console.log('*****request result*****');
console.log(JSON.stringify(res));
return res;
} catch(e) {
console.error(e);
return false
}
}
export function md5Vid (str: string) {
str = 'vId' + str;
return crypto.createHash('md5').update(str, 'utf8').digest("hex");
};
export function getObjSign (obj: any) {
const str = [];
Object.keys(obj).sort().forEach((key) => {
if (key == 'sign') {
} else {
str.push(key + '=' + obj[key]);
}
});
if (str.length == 0) {
console.error('check obj', obj);
}
var strs = str.join('');
return md5Vid(strs);
}
export async function checkSign (obj: any) {
if (getObjSign(obj) === obj.sign) {
return true;
}
console.warn('correct sign:', getObjSign(obj), obj.sign);
return false;
}

View File

@@ -1,31 +1,12 @@
// 一些通用的interface定义
import { Attribute } from "../domain/roleField/attribute";
export interface RewardInter {
id: number;
count: number;
}
export interface Attributes {
hp?: number;
atk?: number;
matk?: number;
def?: number;
mdef?: number;
agi?: number;
luk?: number;
speed?: number;
hit?: number;
cri?: number;
flee?: number;
antCri?: number;
damageIncrease?: number;
damageDecrease?: number;
defIngnore?: number;
bloodSuck?: number;
ap?: number;
}
export interface EquipInter {
id: number;
name: string;
@@ -82,7 +63,7 @@ export interface oppHeroesDefenseInter {
lv: number; // 等级
hide: number; // 是否隐藏
initial_ai: number; // ai类型
attribute: Attributes;
attribute: Attribute;
star: number; // 星级
skill: string|number; // 技能
seid: string; // 技能

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +1,4 @@
import { TIME_FORMAT } from '@consts';
const PER_SECOND = 1 * 1000;
const PER_DAY = 24 * 60 * 60;
@@ -93,4 +94,39 @@ export function getTodayZeroDate() {
date.setMinutes(0);
date.setSeconds(0);
return date;
}
export function getAge(birthday: string) {
let d = new Date(birthday + ' 00:00:00');
let _year = d.getFullYear();
let _month = d.getMonth() + 1;
let _day = d.getDate();
let age = 0;
let now = new Date();
let year = now.getFullYear();
let month = now.getMonth() + 1;
let day = now.getDate();
if (year >= _year && month >= _month && day >= _day) {
age = year - _year;
}else{
age = year - _year - 1;
}
return age
}
export function formatTime(d: Date, type: number) {
let year = d.getFullYear();
let month = d.getMonth() + 1;
let day = d.getDate();
let yearStr = year.toString();
let monthStr = month.toString();
let dayStr = day.toString();
if(type == TIME_FORMAT.TYPE_SLASH) {
if(day < 10) dayStr = '0' + dayStr;
if(month < 10) monthStr = '0' + monthStr;
return `${yearStr}/${monthStr}/${dayStr}`;
}
}

View File

@@ -751,7 +751,7 @@
"heroInUI": "1&1001|1&1004",
"detailUIBg": "2_1",
"recommendedPower": 10031,
"previousGk": 129,
"previousGk": 201,
"relatedEliteGk": 0,
"movePoint": 95
},
@@ -779,7 +779,7 @@
"heroInUI": "1&1001|1&1004",
"detailUIBg": "2_1",
"recommendedPower": 10032,
"previousGk": 130,
"previousGk": 202,
"relatedEliteGk": 0,
"movePoint": 97
},
@@ -807,7 +807,7 @@
"heroInUI": "1&1001|1&1004|2&312",
"detailUIBg": "2_1",
"recommendedPower": 10033,
"previousGk": 0,
"previousGk": 203,
"relatedEliteGk": 9204,
"movePoint": 100
},
@@ -835,7 +835,7 @@
"heroInUI": "1&1001|1&1004",
"detailUIBg": "2_2",
"recommendedPower": 10034,
"previousGk": 0,
"previousGk": 204,
"relatedEliteGk": 0,
"movePoint": 103
},
@@ -863,7 +863,7 @@
"heroInUI": "1&1001|1&1004",
"detailUIBg": "2_2",
"recommendedPower": 10035,
"previousGk": 0,
"previousGk": 205,
"relatedEliteGk": 0,
"movePoint": 109
},
@@ -891,7 +891,7 @@
"heroInUI": "1&1001|1&1004",
"detailUIBg": "2_2",
"recommendedPower": 10036,
"previousGk": 0,
"previousGk": 206,
"relatedEliteGk": 0,
"movePoint": 112
},
@@ -919,7 +919,7 @@
"heroInUI": "1&1001|1&1004|2&312",
"detailUIBg": "2_2",
"recommendedPower": 10037,
"previousGk": 0,
"previousGk": 207,
"relatedEliteGk": 9208,
"movePoint": 116
},
@@ -947,7 +947,7 @@
"heroInUI": "1&1001",
"detailUIBg": "2_3",
"recommendedPower": 10038,
"previousGk": 0,
"previousGk": 208,
"relatedEliteGk": 0,
"movePoint": 118
},
@@ -975,7 +975,7 @@
"heroInUI": "1&1001|1&1004",
"detailUIBg": "2_3",
"recommendedPower": 10039,
"previousGk": 0,
"previousGk": 209,
"relatedEliteGk": 0,
"movePoint": 120
},
@@ -1003,7 +1003,7 @@
"heroInUI": "1&1001|1&1004",
"detailUIBg": "2_3",
"recommendedPower": 10040,
"previousGk": 0,
"previousGk": 210,
"relatedEliteGk": 0,
"movePoint": 122
},
@@ -1031,7 +1031,7 @@
"heroInUI": "1&1001|1&1004|2&312",
"detailUIBg": "2_3",
"recommendedPower": 10041,
"previousGk": 0,
"previousGk": 211,
"relatedEliteGk": 9212,
"movePoint": 124
},
@@ -1059,7 +1059,7 @@
"heroInUI": "1&1001|1&1004",
"detailUIBg": "2_4",
"recommendedPower": 10042,
"previousGk": 0,
"previousGk": 212,
"relatedEliteGk": 0,
"movePoint": 126
},
@@ -1087,7 +1087,7 @@
"heroInUI": "1&1001|1&1004",
"detailUIBg": "2_4",
"recommendedPower": 10043,
"previousGk": 0,
"previousGk": 213,
"relatedEliteGk": 0,
"movePoint": 128
},
@@ -1115,7 +1115,7 @@
"heroInUI": "1&1001|1&1004",
"detailUIBg": "2_4",
"recommendedPower": 10044,
"previousGk": 0,
"previousGk": 214,
"relatedEliteGk": 0,
"movePoint": 130
},
@@ -1143,7 +1143,7 @@
"heroInUI": "1&1001|1&1004|2&312",
"detailUIBg": "2_4",
"recommendedPower": 10045,
"previousGk": 0,
"previousGk": 215,
"relatedEliteGk": 9216,
"movePoint": 133
},
@@ -1171,7 +1171,7 @@
"heroInUI": "1&1001",
"detailUIBg": "2_5",
"recommendedPower": 10046,
"previousGk": 0,
"previousGk": 216,
"relatedEliteGk": 0,
"movePoint": 135
},
@@ -1199,7 +1199,7 @@
"heroInUI": "1&1001|1&1004",
"detailUIBg": "2_5",
"recommendedPower": 10047,
"previousGk": 0,
"previousGk": 217,
"relatedEliteGk": 0,
"movePoint": 137
},
@@ -1227,7 +1227,7 @@
"heroInUI": "1&1001|1&1004",
"detailUIBg": "2_5",
"recommendedPower": 10048,
"previousGk": 0,
"previousGk": 218,
"relatedEliteGk": 0,
"movePoint": 139
},
@@ -1255,7 +1255,7 @@
"heroInUI": "1&1001|1&1004|2&312",
"detailUIBg": "2_5",
"recommendedPower": 10049,
"previousGk": 0,
"previousGk": 219,
"relatedEliteGk": 9220,
"movePoint": 141
},
@@ -1283,7 +1283,7 @@
"heroInUI": "1&1001|1&1004",
"detailUIBg": "2_6",
"recommendedPower": 10050,
"previousGk": 0,
"previousGk": 220,
"relatedEliteGk": 0,
"movePoint": 143
},
@@ -1311,7 +1311,7 @@
"heroInUI": "1&1001|1&1004",
"detailUIBg": "2_6",
"recommendedPower": 10051,
"previousGk": 0,
"previousGk": 221,
"relatedEliteGk": 0,
"movePoint": 146
},
@@ -1339,7 +1339,7 @@
"heroInUI": "1&1001|1&1004",
"detailUIBg": "2_6",
"recommendedPower": 10052,
"previousGk": 0,
"previousGk": 222,
"relatedEliteGk": 0,
"movePoint": 148
},
@@ -1367,7 +1367,7 @@
"heroInUI": "1&1001|1&1004|2&312",
"detailUIBg": "2_6",
"recommendedPower": 10053,
"previousGk": 0,
"previousGk": 223,
"relatedEliteGk": 9224,
"movePoint": 150
},
@@ -1395,7 +1395,7 @@
"heroInUI": "1&1001",
"detailUIBg": "3_1",
"recommendedPower": 10054,
"previousGk": 0,
"previousGk": 224,
"relatedEliteGk": 0,
"movePoint": 155
},
@@ -1423,7 +1423,7 @@
"heroInUI": "1&1001|1&1004",
"detailUIBg": "3_1",
"recommendedPower": 10055,
"previousGk": 0,
"previousGk": 301,
"relatedEliteGk": 0,
"movePoint": 159
},
@@ -1451,7 +1451,7 @@
"heroInUI": "1&1001|1&1004",
"detailUIBg": "3_1",
"recommendedPower": 10056,
"previousGk": 0,
"previousGk": 302,
"relatedEliteGk": 0,
"movePoint": 162
},
@@ -1479,7 +1479,7 @@
"heroInUI": "1&1001|1&1004|2&312",
"detailUIBg": "3_1",
"recommendedPower": 10057,
"previousGk": 0,
"previousGk": 303,
"relatedEliteGk": 9304,
"movePoint": 166
},
@@ -1507,7 +1507,7 @@
"heroInUI": "1&1001|1&1004",
"detailUIBg": "3_2",
"recommendedPower": 10058,
"previousGk": 0,
"previousGk": 304,
"relatedEliteGk": 0,
"movePoint": 169
},
@@ -1535,7 +1535,7 @@
"heroInUI": "1&1001|1&1004",
"detailUIBg": "3_2",
"recommendedPower": 10059,
"previousGk": 0,
"previousGk": 305,
"relatedEliteGk": 0,
"movePoint": 173
},
@@ -1563,7 +1563,7 @@
"heroInUI": "1&1001|1&1004",
"detailUIBg": "3_2",
"recommendedPower": 10060,
"previousGk": 0,
"previousGk": 306,
"relatedEliteGk": 0,
"movePoint": 176
},
@@ -1591,7 +1591,7 @@
"heroInUI": "1&1001|1&1004|2&312",
"detailUIBg": "3_2",
"recommendedPower": 10061,
"previousGk": 0,
"previousGk": 307,
"relatedEliteGk": 9308,
"movePoint": 180
},
@@ -1619,7 +1619,7 @@
"heroInUI": "1&1001",
"detailUIBg": "3_3",
"recommendedPower": 10062,
"previousGk": 0,
"previousGk": 308,
"relatedEliteGk": 0,
"movePoint": 184
},
@@ -1647,7 +1647,7 @@
"heroInUI": "1&1001|1&1004",
"detailUIBg": "3_3",
"recommendedPower": 10063,
"previousGk": 0,
"previousGk": 309,
"relatedEliteGk": 0,
"movePoint": 186
},
@@ -1675,7 +1675,7 @@
"heroInUI": "1&1001|1&1004",
"detailUIBg": "3_3",
"recommendedPower": 10064,
"previousGk": 0,
"previousGk": 310,
"relatedEliteGk": 0,
"movePoint": 188
},
@@ -1703,7 +1703,7 @@
"heroInUI": "1&1001|1&1004|2&312",
"detailUIBg": "3_3",
"recommendedPower": 10065,
"previousGk": 0,
"previousGk": 311,
"relatedEliteGk": 9312,
"movePoint": 190
},
@@ -1731,7 +1731,7 @@
"heroInUI": "1&1001|1&1004",
"detailUIBg": "3_4",
"recommendedPower": 10066,
"previousGk": 0,
"previousGk": 312,
"relatedEliteGk": 0,
"movePoint": 195
},
@@ -1759,7 +1759,7 @@
"heroInUI": "1&1001|1&1004",
"detailUIBg": "3_4",
"recommendedPower": 10067,
"previousGk": 0,
"previousGk": 313,
"relatedEliteGk": 0,
"movePoint": 197
},
@@ -1787,7 +1787,7 @@
"heroInUI": "1&1001|1&1004",
"detailUIBg": "3_4",
"recommendedPower": 10068,
"previousGk": 0,
"previousGk": 314,
"relatedEliteGk": 0,
"movePoint": 201
},
@@ -1815,7 +1815,7 @@
"heroInUI": "1&1001|1&1004|2&312",
"detailUIBg": "3_4",
"recommendedPower": 10069,
"previousGk": 0,
"previousGk": 315,
"relatedEliteGk": 9316,
"movePoint": 204
},
@@ -1843,7 +1843,7 @@
"heroInUI": "1&1001",
"detailUIBg": "3_5",
"recommendedPower": 10070,
"previousGk": 0,
"previousGk": 316,
"relatedEliteGk": 0,
"movePoint": 209
},
@@ -1871,7 +1871,7 @@
"heroInUI": "1&1001|1&1004",
"detailUIBg": "3_5",
"recommendedPower": 10071,
"previousGk": 0,
"previousGk": 317,
"relatedEliteGk": 0,
"movePoint": 212
},
@@ -1899,7 +1899,7 @@
"heroInUI": "1&1001|1&1004",
"detailUIBg": "3_5",
"recommendedPower": 10072,
"previousGk": 0,
"previousGk": 318,
"relatedEliteGk": 0,
"movePoint": 215
},
@@ -1927,7 +1927,7 @@
"heroInUI": "1&1001|1&1004|2&312",
"detailUIBg": "3_5",
"recommendedPower": 10073,
"previousGk": 0,
"previousGk": 319,
"relatedEliteGk": 9320,
"movePoint": 218
},
@@ -1955,7 +1955,7 @@
"heroInUI": "1&1001|1&1004",
"detailUIBg": "3_6",
"recommendedPower": 10074,
"previousGk": 0,
"previousGk": 320,
"relatedEliteGk": 0,
"movePoint": 221
},
@@ -1983,7 +1983,7 @@
"heroInUI": "1&1001|1&1004",
"detailUIBg": "3_6",
"recommendedPower": 10075,
"previousGk": 0,
"previousGk": 321,
"relatedEliteGk": 0,
"movePoint": 223
},
@@ -2011,7 +2011,7 @@
"heroInUI": "1&1001|1&1004",
"detailUIBg": "3_6",
"recommendedPower": 10076,
"previousGk": 0,
"previousGk": 322,
"relatedEliteGk": 0,
"movePoint": 225
},
@@ -2039,7 +2039,7 @@
"heroInUI": "1&1001|1&1004|2&312",
"detailUIBg": "3_6",
"recommendedPower": 10077,
"previousGk": 0,
"previousGk": 323,
"relatedEliteGk": 9324,
"movePoint": 227
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,13 @@
import { Controller } from 'egg';
export default class AccountController extends Controller {
public async deviceLogin() {
const { ctx } = this;
const { token, isGuest, deviceId, platform, pkgName, serverType } = ctx.request.body;
ctx.body = await ctx.service.auth.deviceLogin(isGuest, token, deviceId, platform, pkgName, serverType);
}
public async getSms() {
const { ctx } = this;
const { tel } = ctx.request.body;
@@ -9,8 +16,20 @@ export default class AccountController extends Controller {
public async smsLogin() {
const { ctx } = this;
const { tel, code, platform, pkgName, serverType } = ctx.request.body;
ctx.body = await ctx.service.auth.smsLogin(tel, code, platform, pkgName, serverType);
const { tel, code, platform, pkgName, serverType, deviceId } = ctx.request.body;
ctx.body = await ctx.service.auth.smsLogin(tel, deviceId, code, platform, pkgName, serverType);
}
public async setPassword() {
const { ctx } = this;
const { password } = ctx.request.body;
ctx.body = await ctx.service.auth.setPassword(password);
}
public async pwLogin() {
const { ctx } = this;
const { tel, deviceId, password } = ctx.request.body;
ctx.body = await ctx.service.auth.pwLogin(tel, deviceId, password);
}
public async checkRole() {
@@ -24,4 +43,16 @@ export default class AccountController extends Controller {
const { serverId, roleName } = ctx.request.body;
ctx.body = await ctx.service.auth.createRole(serverId, roleName);
}
public async bind() {
const { ctx } = this;
const { tel, code } = ctx.request.body;
ctx.body = await ctx.service.auth.bind(tel, code);
}
public async authentication() {
const { ctx } = this;
const { name, idNum } = ctx.request.body;
ctx.body = await ctx.service.auth.authentication(name, idNum);
}
}

View File

@@ -1,39 +1,89 @@
import { STATUS } from '@consts';
import { GameModel } from '@db/Game';
import { Controller } from 'egg';
import { RoleModel } from '@db/Role';
import { NoticeModel } from '@db/Notice';
import { ServerParamWithRole, GroupParam } from '../domain/gameField/serverlist';
export default class GameController extends Controller {
public async getServerList() {
const { ctx } = this;
let serverList: Array<any> = [];
let { serverType, auth } = ctx;
if (auth === 1) {
serverList = await GameModel.getAllServerList();
} else if (!auth) {
serverList = await GameModel.getServerListByType(serverType);
}
if (serverList && serverList.length > 0) {
ctx.body = ctx.service.utils.resResult(STATUS.SUCCESS, { serverList });
} else {
ctx.body = ctx.service.utils.resResult(STATUS.SERVER_NOT_FOUND);
}
}
public async newServer() {
const { ctx } = this;
const { serverId, serverType, name, host, port, status } = ctx.request.body;
const serverList = await GameModel.getAllServerList();
for (let { id, host: preHost, port: prePort } of serverList) {
if (preHost === host && prePort === port && id === serverId) {
ctx.body = ctx.service.utils.resResult(STATUS.SERVER_EXISTS);
return;
}
public async getServerList() {
const { ctx } = this;
let { serverType, auth, uid } = ctx;
let serverList = new Array<GroupParam>();
let loginServerList = new Array<ServerParamWithRole>();
let allServers = await GameModel.getServerList();
let roles = await RoleModel.findAllByUid(uid);
allServers.sort((a, b) => {
return b.id - a.id;
});
for(let server of allServers) {
if(auth === 1 || (!auth && server.serverType == serverType)) {
server['serverStr'] = `S${server.id}`;
let curGroup = serverList.find(cur => cur.groupId == server.groupId);
if(!curGroup) {
curGroup = new GroupParam(server);
serverList.push(curGroup);
}
curGroup.pushServer(server);
let role = roles.find(role => role.serverId == server.id);
if(!!role) {
let curLoginInfo = new ServerParamWithRole(role, server);
loginServerList.push(curLoginInfo);
}
}
}
loginServerList.sort((a, b) => { return b.updatedAt.getTime() - a.updatedAt.getTime()});
if (serverList && serverList.length > 0) {
ctx.body = ctx.service.utils.resResult(STATUS.SUCCESS, { serverList, loginServerList });
} else {
ctx.body = ctx.service.utils.resResult(STATUS.SERVER_NOT_FOUND);
}
return
}
const gameInfo = await GameModel.newServer(serverId, serverType, name, host, port, status);
if (gameInfo) {
ctx.body = ctx.service.utils.resResult(STATUS.SUCCESS, { gameInfo });
} else {
ctx.body = ctx.service.utils.resResult(STATUS.NEW_SERVER_ERR);
public async newServer() {
const { ctx } = this;
const { serverId, serverType, name, host, port, status } = ctx.request.body;
const serverList = await GameModel.getAllServerList();
for (let { id, host: preHost, port: prePort } of serverList) {
if (preHost === host && prePort === port && id === serverId) {
ctx.body = ctx.service.utils.resResult(STATUS.SERVER_EXISTS);
return;
}
}
const gameInfo = await GameModel.newServer(serverId, serverType, name, host, port, status);
if (gameInfo) {
ctx.body = ctx.service.utils.resResult(STATUS.SUCCESS, { gameInfo });
} else {
ctx.body = ctx.service.utils.resResult(STATUS.NEW_SERVER_ERR);
}
return
}
}
public async getnotice() {
const { ctx } = this;
let { serverType } = ctx;
console.log(serverType);
let notice = await NoticeModel.getAllNotice(serverType);
let result = notice.map(cur => {
let {id, title, tag, type, content, time} = cur;
return {
id, title, tag, type, content, time
}
})
ctx.body = ctx.service.utils.resResult(STATUS.SUCCESS, { notice: result });
return
}
}

View File

@@ -43,7 +43,7 @@ module.exports = options => {
await next();
const resBody = ctx.body;
console.log('return value:', resBody);
console.log('return value:', JSON.stringify(resBody));
if (isJSON(resBody)) {
ctx.body = { result: aesEncrypt(JSON.stringify(resBody), ENCRYPT_KEY, ENCRYPT_IV) };
} else {

View File

@@ -17,6 +17,8 @@ module.exports = () => {
ctx.uid = user.uid;
ctx.serverType = user.serverType;
ctx.auth = user.auth;
ctx.userCode = user.userCode;
ctx.pkgName = user.pkgName;
await next();
};
};

View File

@@ -5,9 +5,15 @@ export default (app: Application) => {
const tokenParser = app.middleware.tokenParser();
router.get('/dev', controller.home.dev);
router.get('/', controller.home.index);
router.post('/user/devicelogin', controller.account.deviceLogin);
router.post('/user/getsms', controller.account.getSms);
router.post('/user/smslogin', controller.account.smsLogin);
router.post('/user/setpassword', tokenParser, controller.account.setPassword);
router.post('/user/pwlogin', controller.account.pwLogin);
router.post('/user/checkrole', tokenParser, controller.account.checkRole);
router.post('/user/createrole', tokenParser, controller.account.createRole);
router.post('/user/bind', tokenParser, controller.account.bind);
router.post('/user/authentication', tokenParser, controller.account.authentication);
router.post('/game/getserverlist', tokenParser, controller.game.getServerList);
router.post('/game/getnotice', tokenParser, controller.game.getnotice);
};

View File

@@ -1,185 +1,389 @@
import { COUNTER, HERO_SYSTEM_TYPE, DEFAULT_LV, DEFAULT_ITEMS, ITID, DEFAULT_GOLD, DEFAULT_HERO_LV, DEFAULT_EQUIPS, DEFAULT_COIN } from '@consts';
import { COUNTER, HERO_SYSTEM_TYPE, DEFAULT_LV, DEFAULT_ITEMS, ITID, DEFAULT_GOLD, DEFAULT_HERO_LV, DEFAULT_EQUIPS, DEFAULT_COIN, ADULT_AGE, GUEST_MAX_TIME, GUEST_DAY } from '@consts';
import { DEFAULT_HEROES } from '@consts';
import { HeroModel } from '@db/Hero';
import { RoleModel } from '@db/Role';
import { UserModel } from '@db/User';
import { UserModel, UserType } from '@db/User';
import { STATUS } from '@consts';
import { smsModel } from '@db/Sms';
import { Service } from 'egg';
import Counter from '@db/Counter';
import { getHeroInfoById } from 'app/pubUtils/gamedata';
import { calPlayerCeAndSave } from 'app/pubUtils/playerCe';
import { calPlayerCeAndSave, reCalAllHeroCe } from 'app/pubUtils/playerCe';
import { getExpByLv, getHeroExpByLv, gameData } from 'app/pubUtils/data';
import { isString } from 'underscore';
import { getAge } from 'app/pubUtils/timeUtil';
import { shouldRefresh, resResult } from 'app/pubUtils/util';
import { authenticate } from 'app/pubUtils/httpUtil';
/**
* Test Service
*/
export default class Auth extends Service {
public checkTelNo(telNo) {
if (!isString(telNo)) {
return { status: 1, data: '参数类型错误' };
}
if (telNo.length !== 11) {
return { status: 1, data: '手机号长度错误' };
}
return { status: 0, data: '手机号合法' };
}
/**
* 设备免密登录
* @param telNo - 用户手机号
*/
async sendSmsCodeByGuodu(tel, code) {
const ctx = this.ctx;
const url = `http://221.179.172.68:8000/QxtSms/QxtFirewall?OperID=bantu3&OperPass=c8XcTffG&DesMobile=${tel}&Content=${encodeURIComponent(`【同人游戏】验证码${code},您正在登录赵云传,若非本人操作,请勿泄露`)}&Content_Code=1`;
const result = await ctx.curl(url, {
method: 'GET',
});
return result.data;
}
public async deviceLogin(isGuest: boolean, token: string, deviceId: string, platform: string, pkgName: string, serverType: string) {
const ctx = this.ctx;
testLimit(sms, interval) {
if (sms.updateTime.getTime() > Date.now() - interval) {
return true;
}
return false;
}
let user = await UserModel.findUserByToken(token);
let loginType = 1;
/**
* 用户获取手机验证码
* @param telNo - 用户手机号
*/
if (!user) {
if(isGuest) {
const tel = ctx.service.utils.genCode(10);
const token = ctx.service.utils.generateStr(256);
let lastGuest = await UserModel.getLastDeviceGuest(deviceId);
let { guestTime, createdAt } = lastGuest;
if(shouldRefresh(createdAt, new Date(), 0, GUEST_DAY)) {
guestTime = 0;
}
if(guestTime > GUEST_MAX_TIME) {
loginType = 3;
return this.ctx.service.utils.resResult(STATUS.SUCCESS, {
canLogin: true,
loginType
});
} else {
public async getSms(tel: string) {
user = await UserModel.createUser(isGuest, tel, token, platform, pkgName, serverType, deviceId, guestTime);
let param = this.getReturnParam(user);
const telVerify = this.checkTelNo(tel);
if (telVerify.status !== 0) {
return telVerify;
}
const sms = await smsModel.findByTel(tel, false);
if (sms) {
if (await sms.timeLimit(10000)) {
return this.ctx.service.utils.resResult(STATUS.SMS_IN_60S);
}
if (await sms.cntLimit(8)) {
return this.ctx.service.utils.resResult(STATUS.SMS_CNT_LIMIT);
}
}
return this.ctx.service.utils.resResult(STATUS.SUCCESS, {
canLogin: true,
loginType,
...param
});
}
let code = '';
if (sms && (!sms.used || sms.isFixed)) {
code = sms.code;
} else {
code = this.ctx.service.utils.generateNum(6);
}
const smsResult = await this.sendSmsCodeByGuodu(tel, code);
console.log(smsResult);
await smsModel.updateByTel(tel, code, false, new Date(), sms?.hasSendToday() ? sms.countToday + 1 : 1);
return this.ctx.service.utils.resResult(STATUS.SUCCESS);
}
/**
* 用户获取到手机验证码之后发送验证登录请求
* @param tel 登录手机号
* @param code 登录验证码
* @param platform 平台
* @param pkgName 包名
* @param serverType 服务器类型
*/
public async smsLogin(tel: string, code: string, platform: string, pkgName: string, serverType: string) {
const ctx = this.ctx;
// 参数检查
const telVerify = this.checkTelNo(tel);
if (telVerify.status !== 0) {
return telVerify;
}
// ! 测试阶段允许客户端不传验证码,此时不做验证码验证,直接注册或登录账号
// TODO 上线前改掉或仅保留在测试服
if (code !== '') {
if (!isString(code) || code.length !== 6) {
return ctx.service.utils.resResult(STATUS.WRONG_PARMS);
}
// 手机验证码核验
const smsValid: boolean = await smsModel.validateSms(tel, code);
if (!smsValid) {
const sms = await smsModel.findByTel(tel);
if(sms && sms.isFixed) { // 固定手机号登录
if (sms.code !== code) {
return ctx.service.utils.resResult(STATUS.SMS_INVALID);
}
} else {
return this.ctx.service.utils.resResult(STATUS.SUCCESS, {
canLogin: false
});
}
} else {
return ctx.service.utils.resResult(STATUS.SMS_INVALID);
const token = ctx.service.utils.generateStr(256);
user = await UserModel.updateToken(user.tel, token, deviceId);
let param = this.getReturnParam(user);
if(param.isGuest && param.guestTime > GUEST_MAX_TIME) {
loginType = 2;
}
let canLogin = true;
if(!user.isGuest && !user.hasSetPw) canLogin = false;
return this.ctx.service.utils.resResult(STATUS.SUCCESS, {
canLogin, // 未设置密码等于未创建账号
loginType,
...param
});
}
}
}
// 用户注册登录
const token = ctx.service.utils.generateStr(256);
const user = await UserModel.updateToken(tel, token, platform, pkgName, serverType);
return ctx.service.utils.resResult(STATUS.SUCCESS, { token, userCode: user?.userCode });
}
public async checkRole(serverId: number) {
const ctx = this.ctx;
const { uid } = ctx;
const role = await RoleModel.findByUid(uid, serverId);
if (role) {
return ctx.service.utils.resResult(STATUS.SUCCESS, { roleId: role.roleId });
private getReturnParam(user: UserType) {
let age = getAge(user.birthday);
let isAdult = age >= ADULT_AGE;
let todayPlayTime = user.todayPlayTime;
if(shouldRefresh(user.reportTime, new Date(), 0)) {
todayPlayTime = 0;
}
return {
tel: user.tel,
isGuest: !!user.isGuest,
guestTime: user.guestTime, // 游客已体验时间
hasAuthenticated: !!user.hasAuthenticated, // 是否进行过实名认证
isAdult, // 是否已成年
todayPlayTime, // 今天已游戏时长
hasSetPw: user.hasSetPw, // 是否设置了密码
token: user.token, // 用户token
userCode: user.userCode // 用户标识
}
}
return ctx.service.utils.resResult(STATUS.ROLE_NOT_FOUND);
}
public async createRole(serverId: number, roleName: string) {
console.log('enter Auth createRole');
const ctx = this.ctx;
const { uid } = ctx;
const roleId = ctx.service.utils.genCode(10);
const code = ctx.service.utils.genCode(6);
const seqId = await Counter.getNewCounter(COUNTER.ROLE) || -1;
const role = await RoleModel.createRole(uid, serverId, { roleId, code, roleName, seqId, lv: DEFAULT_LV, exp: (getExpByLv(DEFAULT_LV - 1)||{sum:0}).sum||0 });
if (role) {
for (let hid of DEFAULT_HEROES) {
let hero = await HeroModel.findByHidAndRole(hid, roleId);
if(hero) {
continue;
public checkTelNo(telNo) {
if (!isString(telNo)) {
return { status: 1, resResult: resResult(STATUS.WRONG_PARMS) };
}
let dicHero = getHeroInfoById(hid);
if(!dicHero) {
break;
if (telNo.length !== 11) {
return { status: 1, resResult: resResult(STATUS.TEL_LEN_ERR) };
}
let {quality, initialStars: star, jobid: job, name: hName, initialSkin} = dicHero;
return { status: 0 };
}
hero = await HeroModel.createHero({
roleId, roleName: role.roleName, hid, hName, star, quality, job, serverId: role.serverId,
skins:[{id: initialSkin, enable: true}], lv: DEFAULT_HERO_LV, exp: getHeroExpByLv(DEFAULT_HERO_LV - 1)||0
async sendSmsCodeByGuodu(tel, code) {
const ctx = this.ctx;
const url = `http://221.179.172.68:8000/QxtSms/QxtFirewall?OperID=bantu3&OperPass=c8XcTffG&DesMobile=${tel}&Content=${encodeURIComponent(`【同人游戏】验证码${code},您正在登录赵云传,若非本人操作,请勿泄露`)}&Content_Code=1`;
const result = await ctx.curl(url, {
method: 'GET',
});
await calPlayerCeAndSave(roleId, [hero], HERO_SYSTEM_TYPE.INIT);
}
for(let {id, count} of DEFAULT_ITEMS) {
let dicGoods = gameData.goods.get(id);
if(!dicGoods) continue;
let itidObj = ITID.get(dicGoods.itid);
if(!itidObj) continue;
await ctx.service.utils.addBags(roleId, role.roleName, {id, itemName: dicGoods.name, count, type: itidObj.type, hid: 0});
}
for(let {id, count} of DEFAULT_EQUIPS) {
for(let j = 0; j < count; j++) {
let dicGoods = gameData.goods.get(id);
if(!dicGoods) continue;
await ctx.service.utils.addEquips(roleId, role.roleName, {id, ...dicGoods, hid: 0});
}
}
await RoleModel.addGoldFree(roleId, DEFAULT_GOLD);
await RoleModel.addCoin(roleId, DEFAULT_COIN);
return ctx.service.utils.resResult(STATUS.SUCCESS, { roleId: role.roleId });
return result.data;
}
testLimit(sms, interval) {
if (sms.updateTime.getTime() > Date.now() - interval) {
return true;
}
return false;
}
/**
* 用户获取手机验证码
* @param telNo - 用户手机号
*/
public async getSms(tel: string) {
const telVerify = this.checkTelNo(tel);
if (telVerify.status !== 0) {
return telVerify.resResult;
}
const sms = await smsModel.findByTel(tel, false);
if (sms) {
if (await sms.timeLimit(10000)) {
return this.ctx.service.utils.resResult(STATUS.SMS_IN_60S);
}
if (await sms.cntLimit(8)) {
return this.ctx.service.utils.resResult(STATUS.SMS_CNT_LIMIT);
}
}
let code = '';
if (sms && (!sms.used || sms.isFixed)) {
code = sms.code;
} else {
code = this.ctx.service.utils.generateNum(6);
}
const smsResult = await this.sendSmsCodeByGuodu(tel, code);
console.log(smsResult);
await smsModel.updateByTel(tel, code, false, new Date(), sms?.hasSendToday() ? sms.countToday + 1 : 1);
let user = await UserModel.findUserByTel(tel);
return this.ctx.service.utils.resResult(STATUS.SUCCESS, {
hasAccount: !!user && !!user.hasSetPw
});
}
/**
* 用户获取到手机验证码之后发送验证登录请求
* @param tel 登录手机号
* @param code 登录验证码
* @param platform 平台
* @param pkgName 包名
* @param serverType 服务器类型
*/
public async smsLogin(tel: string, deviceId: string, code: string, platform: string, pkgName: string, serverType: string) {
const ctx = this.ctx;
// 参数检查
const telVerify = this.checkTelNo(tel);
if (telVerify.status !== 0) {
return telVerify.resResult;
}
// ! 测试阶段允许客户端不传验证码,此时不做验证码验证,直接注册或登录账号
// TODO 上线前改掉或仅保留在测试服
if (code !== '') {
if (!isString(code) || code.length !== 6) {
return ctx.service.utils.resResult(STATUS.WRONG_PARMS);
}
// 手机验证码核验
const smsValid: boolean = await smsModel.validateSms(tel, code);
if (!smsValid) {
const sms = await smsModel.findByTel(tel);
if (sms && sms.isFixed) { // 固定手机号登录
if (sms.code !== code) {
return ctx.service.utils.resResult(STATUS.SMS_INVALID);
}
} else {
return ctx.service.utils.resResult(STATUS.SMS_INVALID);
}
}
}
// 用户注册登录
const token = ctx.service.utils.generateStr(256);
const user = await UserModel.createOrUpdate(false, tel, token, platform, pkgName, serverType, deviceId);
let param = this.getReturnParam(user);
return ctx.service.utils.resResult(STATUS.SUCCESS, param);
}
/**
* 设置密码
* @param password 密码
*/
public async setPassword(password: string) {
const { ctx } = this;
const { uid } = ctx;
if(!password) return ctx.service.utils.resResult(STATUS.PASSWORD_ILLEGEL);
let user = await UserModel.setPass(uid, password);
if (user) {
let param = this.getReturnParam(user);
return ctx.service.utils.resResult(STATUS.SUCCESS, param);
} else {
return ctx.service.utils.resResult(STATUS.INTERNAL_ERR);
}
}
/**
* 密码登录
* @param tel 登录手机号
* @param code 登录验证码
* @param platform 平台
* @param pkgName 包名
* @param serverType 服务器类型
*/
public async pwLogin(tel: string, deviceId: string, pw: string) {
const ctx = this.ctx;
// 参数检查
const telVerify = this.checkTelNo(tel);
if (telVerify.status !== 0) {
return telVerify.resResult;
}
// 用户注册登录
const token = ctx.service.utils.generateStr(256);
const user = await UserModel.checkPass(tel, pw, token, deviceId);
if(!user) return ctx.service.utils.resResult(STATUS.PASSWORD_ERR);
let param = this.getReturnParam(user);
return ctx.service.utils.resResult(STATUS.SUCCESS, { ...param });
}
public async checkRole(serverId: number) {
const ctx = this.ctx;
const { uid } = ctx;
const role = await RoleModel.findByUid(uid, serverId);
if (role) {
return ctx.service.utils.resResult(STATUS.SUCCESS, { roleId: role.roleId });
}
return ctx.service.utils.resResult(STATUS.ROLE_NOT_FOUND);
}
public async createRole(serverId: number, roleName: string) {
console.log('enter Auth createRole');
const ctx = this.ctx;
const { uid } = ctx;
const roleId = ctx.service.utils.genCode(10);
const code = ctx.service.utils.genCode(6);
const seqId = await Counter.getNewCounter(COUNTER.ROLE) || -1;
const role = await RoleModel.createRole(uid, serverId, { roleId, code, roleName, seqId, lv: DEFAULT_LV, exp: (getExpByLv(DEFAULT_LV - 1) || { sum: 0 }).sum || 0 });
if (role) {
let skinIds = new Array<number>();
for (let hid of DEFAULT_HEROES) {
let hero = await HeroModel.findByHidAndRole(hid, roleId);
if (hero) {
continue;
}
let dicHero = getHeroInfoById(hid);
if (!dicHero) {
break;
}
let { quality, initialStars: star, jobid: job, name: hName, initialSkin } = dicHero;
hero = await HeroModel.createHero({
roleId, roleName: role.roleName, hid, hName, star, quality, job, serverId: role.serverId,
skins: [{ id: initialSkin, enable: true }], lv: DEFAULT_HERO_LV, exp: getHeroExpByLv(DEFAULT_HERO_LV - 1) || 0
});
skinIds.push(initialSkin);
await calPlayerCeAndSave(HERO_SYSTEM_TYPE.INIT, roleId, hero, {});
}
await reCalAllHeroCe(HERO_SYSTEM_TYPE.ADD_SKIN, roleId, {}, skinIds)
for (let { id, count } of DEFAULT_ITEMS) {
let dicGoods = gameData.goods.get(id);
if (!dicGoods) continue;
let itidObj = ITID.get(dicGoods.itid);
if (!itidObj) continue;
await ctx.service.utils.addBags(roleId, role.roleName, { id, itemName: dicGoods.name, count, type: itidObj.type, hid: 0 });
}
for (let { id, count } of DEFAULT_EQUIPS) {
for (let j = 0; j < count; j++) {
let dicGoods = gameData.goods.get(id);
if (!dicGoods) continue;
await ctx.service.utils.addEquips(roleId, role.roleName, { id, ...dicGoods, hid: 0 });
}
}
await RoleModel.addGoldFree(roleId, DEFAULT_GOLD);
await RoleModel.addCoin(roleId, DEFAULT_COIN);
return ctx.service.utils.resResult(STATUS.SUCCESS, { roleId: role.roleId });
}
return ctx.service.utils.resResult(STATUS.ROLE_NOT_FOUND);
}
/**
* 绑定账号
* @param tel 手机号
* @param code 验证码
*/
public async bind(tel: string, code: string) {
const ctx = this.ctx;
// 参数检查
const telVerify = this.checkTelNo(tel);
if (telVerify.status !== 0) {
return telVerify.resResult;
}
if (!isString(code) || code.length !== 6) {
return ctx.service.utils.resResult(STATUS.WRONG_PARMS);
}
// 手机验证码核验
const smsValid: boolean = await smsModel.validateSms(tel, code);
if (!smsValid) {
const sms = await smsModel.findByTel(tel);
if (sms && sms.isFixed) { // 固定手机号登录
if (sms.code !== code) {
return ctx.service.utils.resResult(STATUS.SMS_INVALID);
}
} else {
return ctx.service.utils.resResult(STATUS.SMS_INVALID);
}
}
let telUser = await UserModel.findUserByTel(tel);
if(telUser && telUser.uid != ctx.uid) {
return ctx.service.utils.resResult(STATUS.TEL_HAS_USED);
}
let user = await UserModel.bindTel(ctx.uid, tel);
if(!user) return ctx.service.utils.resResult(STATUS.ACCOUNT_NOT_GUEST);
let param = this.getReturnParam(user);
return ctx.service.utils.resResult(STATUS.SUCCESS, param);
}
/**
* 实名认证
* @param password 密码
*/
public async authentication(name: string, idNum: string) {
const ctx = this.ctx;
// TODO 接SDK
console.log(name, idNum);
let result = await authenticate(name, idNum, ctx.userCode, ctx.pkgName);
if(!result) return ctx.service.utils.resResult(STATUS.AUTHEN_FAIL);
let birthday = this.getBirthdayByIdCard(idNum);
let user = await UserModel.authentication(ctx.uid, birthday, '');
let param = this.getReturnParam(user);
return ctx.service.utils.resResult(STATUS.SUCCESS, param);
}
private getBirthdayByIdCard(idNum: string) {
let year = idNum.slice(6,10);
let month = idNum.slice(10,12);
let date = idNum.slice(12,14);
return `${year}-${month}-${date}`;
}
return ctx.service.utils.resResult(STATUS.ROLE_NOT_FOUND);
}
}

View File

@@ -1,7 +1,5 @@
import { Service } from 'egg';
import { resResult as pubResult } from '../pubUtils/util';
import { calPlayerCeAndSave } from 'app/pubUtils/playerCe';
import { HeroType } from '@db/Hero';
import { addSkins, addBags, addEquips } from 'app/pubUtils/itemUtils';
import { BagInter, EquipInter } from 'app/pubUtils/interface';
const csprng = require('csprng');
@@ -44,10 +42,6 @@ export default class Utils extends Service {
return pubResult(status, data, customMsg);
}
public calPlayerCeAndSave(roleId: string, heros: HeroType[], type: number, args: number[]) {
return calPlayerCeAndSave(roleId, heros, type, args)
}
public addSkins(roleId: string, id: number) {
return addSkins(roleId, id);
}

View File

@@ -0,0 +1,59 @@
import { EggAppConfig, EggAppInfo, PowerPartial } from 'egg';
const path = require('path');
export default (appInfo: EggAppInfo) => {
const config = {} as PowerPartial<EggAppConfig>;
// override config from framework / plugin
// use for cookie sign key, should change to your own and keep security
config.keys = appInfo.name + '_1597499383757_3508';
config.security = {
csrf: {
enable: false,
},
domainWhiteList: [ '*' ],
};
config.cors = {
origin: '*', // 匹配规则 域名+端口 *则为全匹配
allowMethods: 'GET,HEAD,PUT,POST,DELETE,PATCH',
};
// add your egg config in here
config.middleware = [ 'parmsDecode' ];
config.mongoose = {
url: 'mongodb://root:Bantus123@dds-8vb74337eab84d641.mongodb.zhangbei.rds.aliyuncs.com:3717,dds-8vb74337eab84d642.mongodb.zhangbei.rds.aliyuncs.com:3717/admin?replicaSet=mgset-504694158', // 内网
options: { useNewUrlParser: true, useUnifiedTopology: true },
};
config.alinode = {
appid: '86043',
secret: '54ef0364995b0c4f2ab42150e29ad30df8327a3a',
error_log: [ '/root/logs/zyz/zyz-web.log', '/root/logs/zyz/common-error.log', '/root/logs/zyz/egg-agent.log' ],
packages: [ '/root/zyz/web-server/package.json' ],
};
config.view = {
root: path.join(appInfo.baseDir, '/app/public'),
defaultViewEngine: 'nunjucks',
mapping: {
'.html': 'nunjucks' //左边写成.html后缀会自动渲染.html文件
},
};
config.static = {
prefix: '/',
dir: path.join(appInfo.baseDir, '/app/public'),
};
// add your special config in here
const bizConfig = {
sourceUrl: `https://github.com/eggjs/examples/tree/master/${appInfo.name}`,
};
// the return config will combines to EggAppConfig
return {
...config,
...bizConfig,
};
};

View File

@@ -269,6 +269,12 @@
}
}
},
"@types/bluebird": {
"version": "3.5.33",
"resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.33.tgz",
"integrity": "sha512-ndEo1xvnYeHxm7I/5sF6tBvnsA4Tdi3zj1keRKRs12SP+2ye2A27NDJ1B6PqkfMbGAcT+mqQVqbZRIrhfOp5PQ==",
"dev": true
},
"@types/body-parser": {
"version": "1.19.0",
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz",
@@ -285,6 +291,12 @@
}
}
},
"@types/caseless": {
"version": "0.12.2",
"resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz",
"integrity": "sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w==",
"dev": true
},
"@types/color-name": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
@@ -544,6 +556,28 @@
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz",
"integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA=="
},
"@types/request": {
"version": "2.48.5",
"resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.5.tgz",
"integrity": "sha512-/LO7xRVnL3DxJ1WkPGDQrp4VTV1reX9RkC85mJ+Qzykj2Bdw+mG15aAfDahc76HtknjzE16SX/Yddn6MxVbmGQ==",
"dev": true,
"requires": {
"@types/caseless": "*",
"@types/node": "*",
"@types/tough-cookie": "*",
"form-data": "^2.5.0"
}
},
"@types/request-promise": {
"version": "4.1.47",
"resolved": "https://registry.npmjs.org/@types/request-promise/-/request-promise-4.1.47.tgz",
"integrity": "sha512-eRSZhAS8SMsrWOM8vbhxFGVZhTbWSJvaRKyufJTdIf4gscUouQvOBlfotPSPHbMR3S7kfkyKbhb1SWPmQdy3KQ==",
"dev": true,
"requires": {
"@types/bluebird": "*",
"@types/request": "*"
}
},
"@types/serve-static": {
"version": "1.13.5",
"resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.5.tgz",
@@ -572,6 +606,12 @@
"@types/superagent": "*"
}
},
"@types/tough-cookie": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.0.tgz",
"integrity": "sha512-I99sngh224D0M7XgW1s120zxCt3VYQ3IQsuw3P3jbq5GG4yc79+ZjyKznyOGIQrflfylLgcfekeZW/vk0yng6A==",
"dev": true
},
"@types/yargs": {
"version": "12.0.18",
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-12.0.18.tgz",

View File

@@ -20,7 +20,8 @@
"autod": "autod",
"lint": "eslint . --ext .ts",
"clean": "ets clean",
"local": "cross-env EGG_SERVER_ENV=local npm run dev"
"local": "cross-env EGG_SERVER_ENV=local npm run dev",
"isbn": "cross-env EGG_SERVER_ENV=isbn npm run dev"
},
"dependencies": {
"cross-env": "^7.0.3",
@@ -37,6 +38,7 @@
"devDependencies": {
"@types/mocha": "^2.2.40",
"@types/node": "^7.0.12",
"@types/request-promise": "^4.1.47",
"@types/supertest": "^2.0.0",
"autod": "^3.0.1",
"autod-egg": "^1.1.0",