This commit is contained in:
DESKTOP-15R5JU0\legu 2023-11-17 12:02:12 +08:00
parent 24d8c75e21
commit 97e070ea81
1071 changed files with 507956 additions and 0 deletions

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
/node_modules
/.idea
/.vscode
/dist
/doc

11
.mocharc.js Normal file
View File

@ -0,0 +1,11 @@
module.exports = {
require: [
'ts-node/register',
],
timeout: 999999,
exit: false,
spec: [
'./test/**/*.test.ts'
],
'preserve-symlinks': true
}

14
Dockerfile Normal file
View File

@ -0,0 +1,14 @@
FROM node:18-alpine
ENV Param sid=0
ADD ./dist ./app
WORKDIR /app
RUN apk add tzdata
RUN npm config set registry http://registry.npm.taobao.org/ && npm install pm2@5.2.2 -g
CMD cd /app && sh zoeninfo.sh "Asia/Tokyo" && pm2-runtime start js_pm2.config.js -- ${Param}

44
frame.md Normal file
View File

@ -0,0 +1,44 @@
## **src**
###### api_o2s
* o2s -> ***任意端与服务端通信代码***
* s2s -> ***服务端与服务端通信代码***
###### api_s2c -> ***与客户端的业务逻辑交互代码***
###### gameJson -> ***服务端的json配置文件***
###### json -> ***与客户端的共享json配置文件,初次svn拉取项目记得svn切换至../../cehua/json***
###### module -> ***mongodb与redis的数据模型***
###### monopoly -> ***服务端使用类型文件***
###### public -> ***服务端使用函数***
###### shared -> ***客户端与服务端共享的类型文件以及函数***
###### encrypt.ts -> ***数据加解密***
###### extends.ts -> ***扩展npm安装的包***
###### global.ts -> ***全局变量定义***
###### index.ts -> ***启动脚本***
###### jsonType.ts -> ***json配置文件类型提示***
###### lng.ts -> ***语言包***
###### localConfig.ts -> ***本地服务端配置***
###### scheduler.ts -> ***定时器***
###### setHttp.ts -> ***创建、初始化 http服务***
###### setMongodb.ts -> ***初始化mongodb***
###### setRedis.ts -> ***初始化redis***
###### setWs.ts -> ***创建、初始化 websocket服务***

61
js_docker_dev.js Normal file
View File

@ -0,0 +1,61 @@
/**
* 执行脚本环境要求
* 1. aliyun cli
* 2. docker
*/
const { execSync } = require('child_process');
const { argv, platform } = require('process');
const imageName = argv[2];
const tag = argv[3];
const url = 'staging-legolas-registry.ap-northeast-1.cr.aliyuncs.com';
const repositories = `${url}/blacklagoon/heijiaoserver`;
function executeCommand(command) {
try {
const outPut = execSync(command, { stdio: 'inherit' });
return outPut?.toString() || '';
} catch (error) {
console.error(`Command execution failed: ${command}`)
console.error(error.message);
process.exit();
}
}
function buildImage() {
console.log('构建镜像');
if (platform == 'linux') executeCommand(`npm run build_docker_linux`);
else if (platform == 'win32') executeCommand(`npm run build_docker_win`)
executeCommand(`docker build -t ${imageName} .`);
}
function dockerLogin() {
console.log('登陆镜像仓库');
const region = 'ap-northeast-1';
const instanceId = 'cri-fe5eqsg73zl4vd4m';
const version = '2018-12-01';
const command = `aliyun cr GetAuthorizationToken --profile dev --region ${region} --InstanceId ${instanceId} --version ${version} --force`;
const output = execSync(command, { encoding: 'utf8' });
const result = JSON.parse(output);
const password = result.AuthorizationToken.replace(/"/g, '');
executeCommand(`docker login --username=cr_temp_user --password=${password} ${url}`)
}
function dockerTag() {
console.log('标记镜像');
executeCommand(`docker tag ${imageName} ${repositories}:${tag}`);
}
function dockerPush() {
console.log('推送镜像');
executeCommand(`docker push ${repositories}:${tag}`);
}
if (!imageName) return console.error('imageName is null');
if (!tag) return console.error('tag is null');
buildImage();
dockerLogin();
dockerTag();
dockerPush();

61
js_docker_prod.js Normal file
View File

@ -0,0 +1,61 @@
/**
* 执行脚本环境要求
* 1. aliyun cli
* 2. docker
*/
const { execSync } = require('child_process');
const { argv, platform } = require('process');
const imageName = argv[2];
const tag = argv[3];
const url = 'production-legolas-registry.ap-northeast-1.cr.aliyuncs.com';
const repositories = `${url}/blacklagoon/heijiao-server`;
function executeCommand(command) {
try {
const outPut = execSync(command, { stdio: 'inherit' });
return outPut?.toString() || '';
} catch (error) {
console.error(`Command execution failed: ${command}`)
console.error(error.message);
process.exit();
}
}
function buildImage() {
console.log('构建镜像');
if (platform == 'linux') executeCommand(`npm run build_docker_linux`);
else if (platform == 'win32') executeCommand(`npm run build_docker_win`)
executeCommand(`docker build -t ${imageName} .`);
}
function dockerLogin() {
console.log('登陆镜像仓库');
const region = 'ap-northeast-1';
const instanceId = 'cri-azy285s79zw3ti5v';
const version = '2018-12-01';
const command = `aliyun cr GetAuthorizationToken --profile prod --region ${region} --InstanceId ${instanceId} --version ${version} --force`;
const output = execSync(command, { encoding: 'utf8' });
const result = JSON.parse(output);
const password = result.AuthorizationToken.replace(/"/g, '');
executeCommand(`docker login --username=cr_temp_user --password=${password} ${url}`)
}
function dockerTag() {
console.log('标记镜像');
executeCommand(`docker tag ${imageName} ${repositories}:${tag}`);
}
function dockerPush() {
console.log('推送镜像');
executeCommand(`docker push ${repositories}:${tag}`);
}
if (!imageName) return console.error('imageName is null');
if (!tag) return console.error('tag is null');
buildImage();
dockerLogin();
dockerTag();
dockerPush();

20
js_jsonType.js Normal file
View File

@ -0,0 +1,20 @@
var fs = require('fs');
var path = require('path');
var shell = require('child_process');
shell.execSync(`svn up ${path.join(__dirname, '../cehua')}`);
shell.exec(`node ${path.join(__dirname, '../cehua/_creatJsonType.js')} ${path.join(__dirname, 'src/gamejson')}`, (err, stdout, stderr) => {
if (stdout) {
fs.writeFileSync('src/jsonType.ts', stdout + `
declare global {
type _gcType = gcType;
}
export function initGcType () {
}
`);
}
});

85
js_pm2.config.js Normal file
View File

@ -0,0 +1,85 @@
const fs = require('fs');
const os = require('os');
const path = require('path');
const {env} = require('process');
const request = require('sync-request');
console.log('服务端环境变量 ', env.SERVER_ID, env.SERVER_TYPE);
if (env.SERVER_ID) {
let type = env.SERVER_TYPE || 'game';
let url = `http://server-tool:7456/server/getConfig?sid=${env.SERVER_ID}&type=${type}`
console.log('拉取服务端启动配置文件', url);
let res = request('GET', url, {
headers: {
'content-type': 'application/json'
}
});
const body = JSON.parse(res.body.toString());
if (body) {
fs.writeFileSync('config.json', JSON.stringify(body, null, 2));
console.log('服务端配置: ', body);
} else {
console.log('拉取失败');
}
}
//读取服务配置
const config = fs.existsSync(path.resolve(__dirname, 'config.json')) ? JSON.parse(fs.readFileSync(path.resolve(__dirname, 'config.json'), 'utf-8')) : {};
const dis = config.serverId != undefined ? config.serverId : '0';
const localApps = [
{
// 应用程序名称
name: 'heijiao_msg_s' + dis,
// 执行文件
script: 'index.js',
// 应用程序所在的目录
cwd: './',
//集群实例数量0表示根据cpu核心数自动控制
instances: 8,
// 传递给脚本的参数
args: '-serverType msg',
// 是否启用监控模式默认是false。如果设置成true当应用程序变动时pm2会自动重载。这里也可以设置你要监控的文件。
watch: false,
// 不用监听的文件
ignore_watch: [
'logs'
],
// 自定义应用程序的错误日志文件(错误日志文件)
error_file: './logs/errMsg.log',
// 自定义应用程序日志文件(正常日志文件)
out_file: './logs/outMsg.log',
// 指定日志文件的时间格式
log_date_format: 'YYYY-MM-DD HH:mm:ss',
}
];
const crossApps = [
{
// 应用程序名称
name: 'heijiao_cross_s' + dis,
// 执行文件
script: 'index.js',
// 应用程序所在的目录
cwd: './',
// 传递给脚本的参数
args: '-serverType cross',
// 是否启用监控模式默认是false。如果设置成true当应用程序变动时pm2会自动重载。这里也可以设置你要监控的文件。
watch: false,
// 不用监听的文件
ignore_watch: [
'logs'
],
// 自定义应用程序的错误日志文件(错误日志文件)
error_file: './logs/errCross.log',
// 自定义应用程序日志文件(正常日志文件)
out_file: './logs/outCross.log',
// 指定日志文件的时间格式
log_date_format: 'YYYY-MM-DD HH:mm:ss',
}
]
module.exports = {
apps: config.type == 'cross' ? crossApps : localApps
}

128
js_uploadDoc.js Normal file
View File

@ -0,0 +1,128 @@
const fs = require('fs');
const ftp = require('ftp');
const path = require('path');
const client = new ftp();
function changeMD(url) {
var str = ''
if (url.indexOf('s2c') != -1) {
str = `
## [返回上一级](README.md)
## 目录
`
} else if (url.indexOf('s2o') != -1) {
str = `
## [返回上一级](README.md)
## 通用说明
- 所有请求方法均为 \`POST\`
- 所有请求均需加入以下 Header :
- \`Content-Type: application/json\`
- 调用api的格式为:
- \`url: http://{ip}:{port}{path}\`
- \`body: 对应api的请求类型\`
- \`加密方式: 联系该项目的后端获取\`
- 返回值统一为:
- 请求参数校验不成功返回
- \`data error 字符串\`
- 请求参数校验成功:
{
/**请求是否成功 */
isSucc: boolean;
/**请求的返回值 对应调用api的响应值*/
res?: any;
/**请求返回的错误信息*/
err?: any;
}
- 以向玩家发送邮件为例:
![发送邮件代码示例](../../img/heijiao_http_api_send.png)
![发送邮件代码示例](../../img/heijiao_http_api_send_over.png)
## 目录
`
}
let file = fs.readFileSync(url, 'utf-8');
file = file.replace(/^# TSRPC API 接口文档(.|\n)*^## 目录/gm, str);
fs.writeFileSync(url, file);
}
changeMD('doc/s2c/tsapi.md');
changeMD('doc/s2o/tsapi.md');
client.on('ready', async () => {
console.log('ftp client is ready');
await cd('document/serverDoc/doc/heijiao');
let { err, files } = await list();
console.log(files);
for (let file of files) {
await del(file.name)
}
await put('doc/s2c/tsapi.md', 's2c.md');
await put('doc/s2o/tsapi.md', 's2o.md');
client.destroy();
});
client.on('close', () => {
console.log('ftp client has close')
});
client.on('end', () => {
console.log('ftp client has end')
});
client.on('error', (err) => {
console.log('ftp client has an error : ' + JSON.stringify(err))
});
client.connect({
host: '10.0.1.20',
port: '21',
user: 'administrator',
password: 'a123456789.',
keepalive: 1000
});
//列出目标目录
async function list() {
return new Promise((resolve, reject) => {
client.list((err, files) => {
resolve({ err: err, files: files });
})
});
}
//切换目录
async function cd(dirPath) {
return new Promise(res => {
client.cwd(dirPath, (err, dir) => {
res({ err: err, dir: dir })
})
});
}
//删除
async function del(path) {
return new Promise(res => {
client.rmdir(path, (err, dir) => {
res({ err: err, dir: dir })
})
});
}
//将文件上传到ftp目标地址
async function put(currentFile, targetFilePath) {
const rs = fs.createReadStream(currentFile);
return new Promise((resolve, reject) => {
client.put(rs, targetFilePath, (err) => {
resolve({ err: err });
})
});
}

8076
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

49
package.json Normal file
View File

@ -0,0 +1,49 @@
{
"name": "server-.",
"description": "黑礁",
"version": "0.1.0",
"main": "index.js",
"private": true,
"scripts": {
"dev": "tsrpc-cli dev",
"build": "tsrpc-cli build && copy js_pm2.config.js dist && copy zoeninfo.sh dist && mkdir dist\\json && xcopy src\\json dist\\json /e ",
"build_win": "tsrpc-cli build && copy js_pm2.config.js dist && copy zoeninfo.sh dist && mkdir dist\\json && xcopy src\\json dist\\json /e ",
"build_linux": "tsrpc-cli build && cp js_pm2.config.js dist && cp zoeninfo.sh dist && cp src/json/ -a dist ",
"build_docker_win": "npm run build_win && cd dist && npm i --omit=dev",
"build_docker_linux": "npm run build_linux && cd dist && npm i --omit=dev",
"doc": "tsrpc-cli doc && node js_uploadDoc.js",
"test": "mocha test/**/*.test.ts",
"proto": "tsrpc-cli proto",
"sync": "tsrpc-cli sync",
"api": "tsrpc-cli api",
"capi": "npm run proto && npm run api && npm run doc"
},
"devDependencies": {
"@types/crypto-js": "^4.1.1",
"@types/json5": "^2.2.0",
"@types/mathjs": "^9.4.2",
"@types/mocha": "^8.2.3",
"@types/mongodb": "^4.0.7",
"@types/node": "^15.14.9",
"@types/redis": "^4.0.11",
"ftp": "^0.3.10",
"mocha": "^9.2.2",
"onchange": "^7.1.0",
"ts-node": "^10.9.1",
"tsrpc-cli": "^2.4.5",
"typescript": "^4.8.4"
},
"dependencies": {
"axios": "^1.4.0",
"crypto-js": "^4.1.1",
"express": "^4.18.2",
"json5": "^2.2.3",
"mathjs": "^11.4.0",
"mongodb": "^4.11.0",
"redis": "^4.3.1",
"shelljs": "^0.8.5",
"sync-request": "^6.1.0",
"tsrpc": "^3.4.12",
"xlsx": "^0.18.5"
}
}

View File

@ -0,0 +1,21 @@
import { ApiCall } from "tsrpc";
import { ReqFindEnemy, ResFindEnemy } from "../../cross/protocols/clsl/PtlFindEnemy";
import { formatNpcData } from '../../shared/fightControl/fightFun';
export default async function (call: ApiCall<ReqFindEnemy, ResFindEnemy>) {
let my = await G.mongodb.collection('clslCrossUser').findOne({ uid: call.req.uid });
let starConf = getStarConf(my.allStar);
let others = await G.mongodb.collection('clslCrossUser').find({ uid: { $nin: [call.req.uid] } }).toArray();
let enemy = others.random();
call.succ({
allStar: enemy?.allStar || my.allStar,
info: enemy?.info || formatNpcData(starConf.npc)
});
}
const endConf = Object.values(G.gc.clsl_dan).slice(-1)[0];
function getStarConf(star = 0) {
return G.gc.clsl_dan[star] || endConf;
}

View File

@ -0,0 +1,14 @@
import { ApiCall } from "tsrpc";
import { ReqLog, ResLog } from "../../cross/protocols/clsl/PtlLog";
import { FightFun } from '../../public/fight';
export default async function (call: ApiCall<ReqLog, ResLog>) {
if (call.req.result) {
FightFun.saveLog(call.req.uid, 'clsl', call.req.result);
call.succ({});
} else {
call.succ({
logs: await FightFun.readLog(call.req.uid, 'clsl')
});
}
}

View File

@ -0,0 +1,7 @@
import { ApiCall } from "tsrpc";
import { ReqRank, ResRank } from "../../cross/protocols/clsl/PtlRank";
import { Rank } from '../../public/rank/rank';
export default async function (call: ApiCall<ReqRank, ResRank>) {
call.succ(await Rank.list.clslCross.getRankList(call.req.gud.uid, call.req.gud));
}

View File

@ -0,0 +1,10 @@
import { ApiCall } from "tsrpc";
import { ReqRankUids, ResRankUids } from "../../cross/protocols/clsl/PtlRankUids";
import { Rank } from '../../public/rank/rank';
export default async function (call: ApiCall<ReqRankUids, ResRankUids>) {
let rankList = await Rank.list.clslCross.getRankListAll()
call.succ({
uids: rankList.map(li => li.player.uid)
});
}

View File

@ -0,0 +1,23 @@
import { ApiCall } from "tsrpc";
import { ReqUpLoad, ResUpLoad } from "../../cross/protocols/clsl/PtlUpLoad";
import { Rank } from '../../public/rank/rank';
export default async function (call: ApiCall<ReqUpLoad, ResUpLoad>) {
let { allStar, uid, ...ops } = call.req;
let a = await G.mongodb.collection('clslCrossUser').findOneAndUpdate(
{ uid: uid },
{
$inc: { allStar: allStar || 0 },
$set: ops
},
{ upsert: true }
);
if (allStar != undefined && ops.info) {
Rank.list.clslCross.addNew({
player: a.value.info.player,
valArr: [(await G.mongodb.collection('clslCrossUser').findOne({ uid: uid })).allStar]
});
}
}

View File

@ -0,0 +1,43 @@
import { ApiCall } from "tsrpc";
import { ReqGetEnemy, ResGetEnemy } from "../../../cross/protocols/hbzb/jfs/PtlGetEnemy";
import { Rank } from '../../../public/rank/rank';
import { formatNpcData } from '../../../shared/fightControl/fightFun';
import { PublicShared } from "../../../shared/public/public";
export default async function (call: ApiCall<ReqGetEnemy, ResGetEnemy>) {
// TODO
let allPlayers = Rank.list.hbzbCross.allPlayer;
let user = allPlayers[call.req.uid];
if (!user) return call.succ({ enemy: [] });
let conf = call.req.auto ? G.gc.hbzb.jfsMatchingAuto : G.gc.hbzb.jfsMatchingHand;
let rang = conf.map(val => {
return [PublicShared.eval(val.min, { zhanli: user.data.player.power }), PublicShared.eval(val.max, { zhanli: user.data.player.power })] as [number, number];
});
let min = rang.slice(-1)[0][0];
let max = rang[0][1];
let players = Object.values(allPlayers).filter(p => {
return p.data.player.power >= min && p.data.player.power <= max && p.data.player.uid != call.req.uid;
});
let select: string[] = [];
let enemy = rang.map((r, index) => {
let es = players.filter(p => p.data.player.power >= r[0] && p.data.player.power <= r[1] && !select.includes(p.data.player.uid));
if (es.length > 0) {
let { uid, ...ops } = es.random();
select.push(uid);
return ops;
} else {
return {
data: getNpc(user.data.player.lv, index),
jifen: 1000
};
}
});
call.succ({ enemy: enemy });
}
function getNpc(lv: number, index: number) {
let rang = G.gc.hbzb.jfsRefreshNpcId.find(v => lv >= v.lvs[0] && lv <= v.lvs[1]);
return formatNpcData(rang.npcs[index].random());
}

View File

@ -0,0 +1,7 @@
import { ApiCall } from "tsrpc";
import { ReqGetLog, ResGetLog } from "../../../cross/protocols/hbzb/jfs/PtlGetLog";
import { FightFun } from '../../../public/fight';
export default async function (call: ApiCall<ReqGetLog, ResGetLog>) {
call.succ(await FightFun.readLog(call.req.uid, 'hbzbJfs'));
}

View File

@ -0,0 +1,9 @@
import { ApiCall } from "tsrpc";
import { ReqGetRankList, ResGetRankList } from "../../../cross/protocols/hbzb/jfs/PtlGetRankList";
import { Rank } from '../../../public/rank/rank';
export default async function (call: ApiCall<ReqGetRankList, ResGetRankList>) {
let rankList = await Rank.list.hbzbCross.getRankListAll()
// TODO
call.succ({ rankList: rankList, jifen: Rank.list.hbzbCross.allPlayer[call.req.uid]?.jifen || 1000 });
}

View File

@ -0,0 +1,7 @@
import { ApiCall } from "tsrpc";
import { ReqGetUser, ResGetUser } from "../../../cross/protocols/hbzb/jfs/PtlGetUser";
export default async function (call: ApiCall<ReqGetUser, ResGetUser>) {
// TODO
call.error('API Not Implemented');
}

View File

@ -0,0 +1,31 @@
import {ApiCall} from "tsrpc";
import {ReqGetEnemy, ResGetEnemy} from "../../../cross/protocols/hbzb/zbs/PtlGetEnemy";
import {Rank} from '../../../public/rank/rank';
export default async function (call: ApiCall<ReqGetEnemy, ResGetEnemy>) {
let list = await Rank.list.hbzbZbsCross.getRankListAll();
let enemys = list.slice(0, 10);
let myRank = list.findIndex(e => e.player.uid == call.req.uid);
if (myRank > 8) {
if (myRank == 9) enemys.push(list.slice(10, 5).random());
else if (myRank == 10) enemys.push(list.slice(11, 5).random());
else {
let two = list.slice(10, myRank - 10).shuffle();
enemys.push(...two.slice(0, 2));
enemys.push(list.slice(myRank + 1, 5).random());
}
}
call.succ({
enemy: enemys.map((e, i) => ({
data: {
player: e.player,
roles: e.roles
},
rank: i
})),
rank: myRank
});
}

View File

@ -0,0 +1,7 @@
import { ApiCall } from "tsrpc";
import { ReqGetLog, ResGetLog } from "../../../cross/protocols/hbzb/zbs/PtlGetLog";
import { FightFun } from '../../../public/fight';
export default async function (call: ApiCall<ReqGetLog, ResGetLog>) {
call.succ(await FightFun.readLog(call.req.uid, 'hbzbZbs'));
}

View File

@ -0,0 +1,8 @@
import { ApiCall } from "tsrpc";
import { ReqGetRankList, ResGetRankList } from "../../../cross/protocols/hbzb/zbs/PtlGetRankList";
import { Rank } from '../../../public/rank/rank';
export default async function (call: ApiCall<ReqGetRankList, ResGetRankList>) {
let rankList = await Rank.list.hbzbZbsCross.getRankListAll();
call.succ({ rankList: rankList });
}

View File

@ -0,0 +1,8 @@
import { ApiCall } from "tsrpc";
import { ReqGetStatus, ResGetStatus } from "../../../cross/protocols/hbzb/zbs/PtlGetStatus";
import { Rank } from '../../../public/rank/rank';
export default async function (call: ApiCall<ReqGetStatus, ResGetStatus>) {
let rank = await Rank.list.hbzbZbsCross.getRankSortByOne(call.req.uid)
call.succ({ status: rank});
}

View File

@ -0,0 +1,13 @@
import { ApiCall } from "tsrpc";
import { ReqSendJjcTop, ResSendJjcTop } from "../../../cross/protocols/hbzb/zbs/PtlSendJjcTop";
import { Rank } from '../../../public/rank/rank';
export default async function (call: ApiCall<ReqSendJjcTop, ResSendJjcTop>) {
// Rank.list.hbzbZbsCross.list.push(...call.req.tops);
for (let index = 0; index < call.req.tops.length; index++) {
const element = call.req.tops[index];
element["valArr"] = [0];
Rank.list.hbzbZbsCross.addNew(element)
};
}

View File

@ -0,0 +1,7 @@
import { ApiCall } from "tsrpc";
import { ReqApply, ResApply } from "../../cross/protocols/kbzz/PtlApply";
export default async function (call: ApiCall<ReqApply, ResApply>) {
G.mongodb.collection('kbzzApplyUser').updateOne({ uid: call.req.info.player.uid }, { $set: { info: call.req.info } }, { upsert: true });
call.succ({});
}

View File

@ -0,0 +1,12 @@
import { ApiCall } from "tsrpc";
import { ReqGetUser, ResGetUser } from "../../cross/protocols/kbzz/PtlGetUser";
export default async function (call: ApiCall<ReqGetUser, ResGetUser>) {
let dbData = await G.mongodb.collection('kbzzGroupUser').findOne({ uid: call.req.uid });
call.succ({
group: dbData.group,
troop: dbData.troop
});
}

View File

@ -0,0 +1,17 @@
import { ApiCall } from "tsrpc";
import { ReqGroupRank, ResGroupRank } from "../../cross/protocols/kbzz/PtlGroupRank";
export default async function (call: ApiCall<ReqGroupRank, ResGroupRank>) {
// TODO
let db = await G.mongodb.collection('kbzzGroupTroop').find({ group: call.req.group }).toArray();
call.succ({
rank: db.map(d => {
return {
troop: d.troop,
score: d.score
};
}),
log: (await G.mongodb.collection('kbzzGroupLog').findOne({ group: call.req.group }))?.log || []
});
}

View File

@ -0,0 +1,17 @@
import { ApiCall } from "tsrpc";
import { ReqRank, ResRank } from "../../cross/protocols/kbzz/PtlRank";
import { RankKbzz } from '../../public/rank/rank_kbzz';
export default async function (call: ApiCall<ReqRank, ResRank>) {
let _cunzai = await G.mongodb.collection('kbzzGroupTroop').findOne({})
if (!_cunzai) {
return call.error('', { code: -1, message: '功能未开放' })
}
let db = await G.mongodb.collection('kbzzGroupUser').findOne({ uid: call.req.uid });
let group = db?.group || 0;
let rank = await RankKbzz.groupList[group].getRankList(call.req.uid);
call.succ({
...rank
});
}

View File

@ -0,0 +1,19 @@
import { ApiCall } from "tsrpc";
import { ReqRefresh, ResRefresh } from "../../cross/protocols/kbzz/PtlRefresh";
export default async function (call: ApiCall<ReqRefresh, ResRefresh>) {
let enemys = await G.mongodb.collection('kbzzGroupUser').find({ group: call.req.group, troop: { $nin: [call.req.troop] } }).toArray();
enemys.sort(() => Math.random() - .5);
let arr = enemys.slice(0, G.gc.kbzz.refreshEnemyNum).map(e => {
return {
info: e.info,
troop: e.troop,
result: null
};
});
call.succ({
enemy: arr
});
}

View File

@ -0,0 +1,12 @@
import { ApiCall } from "tsrpc";
import { ReqState, ResState } from "../../cross/protocols/kbzz/PtlState";
export default async function (call: ApiCall<ReqState, ResState>) {
let num = await G.mongodb.collection(call.req.type == 'apply' ? 'kbzzApplyUser' : 'kbzzGroupUser').countDocuments();
call.succ({
num: num,
succ: call.req.type == 'apply' ? num >= G.gc.kbzz.groupNum : num >= 1
});
}

View File

@ -0,0 +1,44 @@
import { ApiCall } from "tsrpc";
import { ReqUpUser, ResUpUser } from "../../cross/protocols/kbzz/PtlUpUser";
import { RankKbzz } from '../../public/rank/rank_kbzz';
export default async function (call: ApiCall<ReqUpUser, ResUpUser>) {
G.mongodb.collection('kbzzGroupUser').updateOne(
{ uid: call.req.uid },
{
$inc: { score: call.req.addScore },
$set: call.req.info == null ? {} : { info: call.req.info }
}
);
G.mongodb.collection('kbzzGroupTroop').updateOne(
{ group: call.req.group, troop: call.req.troop },
{
$inc: { score: call.req.addScore }
}
);
G.mongodb.collection('kbzzGroupLog').updateOne(
{ group: call.req.group },
{
$push: {
log: {
$each: [call.req.log],
$slice: -50
}
}
},
{ upsert: true }
);
if (call.req.info != null) {
RankKbzz.groupList[call.req.group].addNew({
...call.req.info,
valArr: [call.req.allScore]
});
}
call.succ({});
}

View File

@ -0,0 +1,13 @@
import { ApiCall } from "tsrpc";
import { ReqBaoMing, ResBaoMing } from "../../cross/protocols/wzry/PtlBaoMing";
export default async function (call: ApiCall<ReqBaoMing, ResBaoMing>) {
let _setData = {
zkey: call.req.zkey,
data: call.req.data,
jifen: 0,
uid: call.req.data.player.uid
}
await G.mongodb.collection('wzry_user_cross').updateOne({ uid: call.req.data.player.uid }, { $set: _setData }, { upsert: true })
call.succ({ mydata: _setData });
}

View File

@ -0,0 +1,9 @@
import { ApiCall } from "tsrpc";
import { ReqDldRefre, ResDldRefre } from "../../cross/protocols/wzry/PtlDldRefre";
export default async function (call: ApiCall<ReqDldRefre, ResDldRefre>) {
let others = await G.mongodb.collection('wzry_fight').find({ uid: { $nin: [call.req.uid] } }).toArray();
let enemy = others.random();
call.succ({ info: enemy.data })
}

View File

@ -0,0 +1,15 @@
import { ApiCall } from "tsrpc";
import { ReqRank, ResRank } from "../../cross/protocols/wzry/PtlRank";
import { ChatFun } from "../../public/chat";
import { EmailFun } from "../../public/email";
import { FightFun } from "../../public/fight";
import { Rank } from '../../public/rank/rank';
import { SchedulerWzryDlDstart, wzrygroup } from "../../public/scheduler/scheduler_wzry";
import { WangZheRongYaofun } from "../../public/wzry";
import { PublicShared } from "../../shared/public/public";
export default async function (call: ApiCall<ReqRank, ResRank>) {
let _r = await Rank.list.wzryCross.getRankList(call.req.gud.uid, call.req.gud)
call.succ(_r);
}

View File

@ -0,0 +1,24 @@
import { ApiCall } from "tsrpc";
import { ReqSetWzFight, ResSetWzFight } from "../../cross/protocols/wzry/PtlSetWzFight";
import { Rank } from "../../public/rank/rank";
export default async function (call: ApiCall<ReqSetWzFight, ResSetWzFight>) {
let _setData = {
zkey: call.req.zkey,
data: call.req.data,
jifen: call.req.jifen,
uid: call.req.data.player.uid
}
await G.mongodb.collection('wzry_fight').updateOne({ uid: call.req.data.player.uid }, { $set: _setData })
// 有积分数据更新积分
if (_setData.jifen) {
let data = {
valArr: [_setData.jifen],
..._setData.data
}
Rank.list.wzryCross.addNew(data)
}
let rank = await Rank.list.wzryCross.getPlayerRank(call.req.data.player.uid) || -1
call.succ({ mydata: _setData, rank: rank });
}

View File

@ -0,0 +1,23 @@
import { ApiCall } from "tsrpc";
import { ReqUpdateFight, ResUpdateFight } from "../../cross/protocols/wzry/PtlUpdateFight";
export default async function (call: ApiCall<ReqUpdateFight, ResUpdateFight>) {
if (call.req.setdata) {
await G.mongodb.collection('wzry_fight').updateOne({ uid: call.req.uid }, { $set: call.req.setdata })
}
if (call.req.isjingcai) {
await G.mongodb.collection('crosskv').updateOne({ type: "wzryallnum" }, { $inc: { num: call.req.isjingcai } }, { upsert: true })
}
// 设置删除跨服邮件的标识符,标识已经被拉倒本服生效
if (call.req?.isdelemail?.isdel) {
let _list = []
for (let index = 0; index < call.req.isdelemail.email.length; index++) {
const element = call.req.isdelemail.email[index];
_list.push(G.mongodb.conversionId(element))
}
await G.mongodb.collection('email').updateMany({ _id: { $in: _list } }, {$set: { isdel: 1 }})
}
call.succ({})
}

View File

@ -0,0 +1,45 @@
import { ApiCall } from "tsrpc";
import { ReqWzFightData, ResWzFightData } from "../../cross/protocols/wzry/PtlWzFightData";
import { Rank } from "../../public/rank/rank";
import { PublicShared } from "../../shared/public/public";
export default async function (call: ApiCall<ReqWzFightData, ResWzFightData>) {
// 王者参与数据
let changeInfo: ResWzFightData = {}
if (call.req.iswzfight) {
let _myFight = await G.mongodb.collection('wzry_fight').findOne({ uid: call.req.uid })
if (_myFight && Object.keys(_myFight).length > 0) {
if (_myFight?._id) delete _myFight._id
_myFight['rank'] = await Rank.list.wzryCross.getPlayerRank(call.req.uid) || -1
changeInfo['info'] = _myFight
}
}
// 王者之巅本期数据
if (call.req.iswzzd) {
let zkey = PublicShared.getToWeek()
let _wzzd = await G.mongodb.collection('wzrywiner').findOne({ zkey: zkey })
if (_wzzd && _wzzd._id) delete _wzzd._id
changeInfo['wzzd'] = _wzzd
}
if (call.req.isdel) {
// 删除本期数据
await G.mongodb.collection('wzry_fight').deleteMany({})
await G.mongodb.collection('crosskv').deleteMany({ type: 'wzryallnum' })
await G.mongodb.collection('wzry_user_cross').deleteMany({})
await G.mongodb.collection('wzry_fight_log').deleteMany({})
await Rank.list.wzryCross.clear()
}
// 跨服邮件
if (call.req.isemail) {
let _crossEmail = await G.mongodb.collection('email').find({ isdel: { $exists: false } }).toArray()
_crossEmail.forEach(email => {
email._id.toString()
})
changeInfo['crossEmail'] = _crossEmail
}
call.succ(changeInfo)
}

View File

@ -0,0 +1,7 @@
import { ApiCall } from "tsrpc";
import { ReqWzFightGroup, ResWzFightGroup } from "../../cross/protocols/wzry/PtlWzFightGroup";
export default async function (call: ApiCall<ReqWzFightGroup, ResWzFightGroup>) {
let _myFight = await G.mongodb.collection('wzry_fight').find({ ...call.req.where }).toArray()
call.succ({ info: _myFight })
}

View File

@ -0,0 +1,8 @@
import { ApiCall } from "tsrpc";
import { ReqWzzd, ResWzzd } from "../../cross/protocols/wzry/PtlWzzd";
export default async function (call: ApiCall<ReqWzzd, ResWzzd>) {
let _where = call.req?.where ? call.req.where : {}
let wzzdlist = await G.mongodb.collection('wzrywiner').find(_where).toArray()
call.succ({ wzzdlist: wzzdlist });
}

View File

@ -0,0 +1,11 @@
import { ApiCall } from "tsrpc";
import { ReqcatFightLog, RescatFightLog } from "../../cross/protocols/wzry/PtlcatFightLog";
export default async function (call: ApiCall<ReqcatFightLog, RescatFightLog>) {
let result = await G.mongodb.collection('wzry_fight_log').findOne({ _id: G.mongodb.conversionId(call.req.fid) });
if (!result) {
return call.errorCode(-1);
}
delete result._id;
call.succ({ result: result });
}

View File

@ -0,0 +1,9 @@
import { ApiCall } from "tsrpc";
import { ReqgetJingCai, ResgetJingCai } from "../../cross/protocols/wzry/PtlgetJingCai";
export default async function (call: ApiCall<ReqgetJingCai, ResgetJingCai>) {
let num = (await G.mongodb.collection('crosskv').findOne({ type: 'wzryallnum' }))?.num || 0
call.succ({
num: num
})
}

View File

@ -0,0 +1,22 @@
import { ApiCall } from "tsrpc";
import { ReqAddHuoDong, ResAddHuoDong } from "../monopoly/protocols/PtlAddHuoDong";
import { HuoDongFun } from "../public/huodongfun";
import { PublicShared } from "../shared/public/public";
export default async function (call: ApiCall<ReqAddHuoDong, ResAddHuoDong>) {
let _hd = call.req
if (_hd["ttype"] == 0) {
if (_hd["stime"] == -1) { // 永久活动
_hd["stime"] = 0
_hd["rtime"] = 0
_hd["etime"] = 0
_hd["showtime"] = "永久"
} else { // 不是永久活动,直接使用传输时间;检测显示时间
let _st = PublicShared.fmtTime(_hd["stime"])
let _rt = PublicShared.fmtTime(_hd["rtime"])
_hd["showtime"] = _st + " - " + _rt
}
}
call.succ({ insertId: await HuoDongFun.addHuoDong(_hd) });
}

View File

@ -0,0 +1,13 @@
import { ApiCall } from "tsrpc";
import { ReqCatAllhd, ResCatAllhd } from "../monopoly/protocols/PtlCatAllhd";
import { HuoDongFun } from "../public/huodongfun";
export default async function (call: ApiCall<ReqCatAllhd, ResCatAllhd>) {
let _where = call.req.where
let _w = {}
if (_where && Object.keys(_where).length > 0) {
_w = _where
}
let _hdList = await HuoDongFun.catAllHD(_w)
call.succ({ hdlist: _hdList });
}

View File

@ -0,0 +1,8 @@
import { ApiCall } from "tsrpc";
import { ReqDelHuoDong, ResDelHuoDong } from "../monopoly/protocols/PtlDelHuoDong";
import { HuoDongFun } from "../public/huodongfun";
export default async function (call: ApiCall<ReqDelHuoDong, ResDelHuoDong>) {
await HuoDongFun.delHD(call.req.hdid)
call.succ({ status: "success" });
}

7
src/api_o2s/ApiEmail.ts Normal file
View File

@ -0,0 +1,7 @@
import { ApiCall } from "tsrpc";
import { ReqEmail, ResEmail } from "../monopoly/protocols/PtlEmail";
import { EmailFun } from '../public/email';
export default async function (call: ApiCall<ReqEmail, ResEmail>) {
call.succ({ insertId: await EmailFun.addEmail(call.req) });
}

19
src/api_o2s/ApiGetLog.ts Normal file
View File

@ -0,0 +1,19 @@
import { existsSync, readFileSync, readdirSync } from 'fs';
import { dirname, join } from 'path';
import { ApiCall } from "tsrpc";
import { ReqGetLog, ResGetLog } from "../monopoly/protocols/PtlGetLog";
export default async function (call: ApiCall<ReqGetLog, ResGetLog>) {
let logStr = '';
let dir = join(dirname(require.main.filename), 'logs');
if (existsSync(dir)) {
let files = readdirSync(dir);
files.forEach(file => {
logStr += file + ':\n';
logStr += readFileSync(join(dir, file), 'utf-8') + '\n';
});
}
call.succ(logStr);
}

37
src/api_o2s/Apihealthz.ts Normal file
View File

@ -0,0 +1,37 @@
import { ApiCall } from "tsrpc";
import { Reqhealthz, Reshealthz } from "../monopoly/protocols/Ptlhealthz";
export default async function (call: ApiCall<Reqhealthz, Reshealthz>) {
let _chkMDB = await G.mongodb.indexInformation("user")
let _chkRedis = await G.redis.chkRedis()
let _dateTime = new Date();
let _newTime = _dateTime.format('YYYY-MM-DDTHH:MM+01:00');
// 构造返回值
let _data: Reshealthz = {
code: 0,
data: {
dependencies: []
}
}
let _names = ["mongodb", "redis"]
for (let index = 0; index < [_chkMDB, _chkRedis].length; index++) {
const element = [_chkMDB, _chkRedis][index];
let _tmp = {
dependency: _names[index],
status: (_names[index] == "mongodb" ? _chkMDB : _chkRedis) ? 0 : 102,
reason: '',
severity: _names[index] == "mongodb" ? "critical" : "warning",
lastcheck: _newTime
}
_data.code = _tmp.status
_data.data.dependencies.push(_tmp)
}
call.succ(_data);
}

View File

@ -0,0 +1,14 @@
import { ApiCall } from "tsrpc";
import { Reqdeploy, Resdeploy } from "../../monopoly/protocols/games/Ptldeploy";
import { initStarupFun } from "../../starup";
export default async function (call: ApiCall<Reqdeploy, Resdeploy>) {
try{
initStarupFun.initStart()
}catch(err){
call.succ({message:err.toString(), code:-1})
}
// 区服初始化
call.succ({ message: "success", code: 0 });
}

View File

@ -0,0 +1,17 @@
import { ApiCall } from "tsrpc";
import { Reqmetrics, Resmetrics } from "../../monopoly/protocols/games/Ptlmetrics";
export default async function (call: ApiCall<Reqmetrics, Resmetrics>) {
// 当前区服付费人数
let now_paid_user_num = await G.mongodb.collection('payLog').countDocuments({})
// 当前区服在线人数
let now_login_user_num = await G.mongodb.collection('user').countDocuments({ newonlinetime: { $gte: G.time - 90, $lte: G.time + 30 } })
// 当前区服注册人数
let now_register_user_num = await G.mongodb.collection('user').countDocuments({})
call.succ({
now_paid_user_num: now_paid_user_num,
now_login_user_num: now_login_user_num,
now_register_user_num: now_register_user_num
});
}

View File

@ -0,0 +1,127 @@
import { ApiCall } from "tsrpc";
import { GongGaoBan_info, Reqnotification, Resnotification } from "../../monopoly/protocols/games/Ptlnotification";
import { ChatFun } from "../../public/chat";
import { EmailFun } from "../../public/email";
import { NotifiCationFun } from "../../public/notification";
import { ServerToolFun } from "../../public/servertooltcp";
export default async function (call: ApiCall<Reqnotification, Resnotification>) {
let template = call.req.template
let action = call.req.action
if (template == "server_mail") { // 全服邮件
if (action == "offline") { // publish 发布全服邮件/个人邮件/公告板/跑马灯 offline 下线全服邮件/公告板/跑马灯
// 根据g123 唯一id 删除邮件
await G.mongodb.collection('email').deleteMany({ "g123log.id": { $in: call.req.data } });
} else {
let _prize = await NotifiCationFun.getFmtPrize(call.req.data.assets)
let _mails = call.req.data.mail
for (let indexMail = 0; indexMail < _mails.length; indexMail++) {
const elementMail = _mails[indexMail];
EmailFun.addQuanFuEmail({
uid: "system",
type: 'gm',
title: elementMail.header,
content: elementMail.content,
prize: _prize,
contentInsertArr: [],
createTime: call.req.data?.startTime || G.time,
g123log: { id: call.req.data.id }
})
}
}
} else if (template == "player_mail") { // 个人邮件
let _playerIds = call.req.data.playerIds
for (let index = 0; index < _playerIds.length; index++) {
const element = _playerIds[index];
// 邮件内容
let _prize = await NotifiCationFun.getFmtPrize(call.req.data.assets)
let _mails = call.req.data.mail
for (let indexMail = 0; indexMail < _mails.length; indexMail++) {
const elementMail = _mails[indexMail];
EmailFun.addEmail({
uid: element,
type: 'gm',
title: elementMail.header,
content: elementMail.content,
prize: _prize,
contentInsertArr: [],
createTime: call.req.data?.sendTime || G.time,
g123log: { id: call.req.data.id }
})
}
}
} else if (template == "news_ticker") { // 跑马灯
if (action == "offline") { // 删除跑马灯
ChatFun.newMsg({
type: 'local',
msg: "",
time: G.time,
sender: 'system',
otherData: {
pmd: false,
args: [],
ids: call.req.data
}
})
} else {
let newsTicker = call.req.data.newsTicker
for (let index = 0; index < newsTicker.length; index++) {
const element = newsTicker[index];
ChatFun.newMsg({
type: 'local',
msg: element.content,
time: call.req.data.startTime,
sender: 'system',
otherData: {
pmd: true,
args: [],
interval: call.req.data.interval, // 播放间隔单位分钟为0时仅播放frequency次
frequency: call.req.data.frequency, // 每回播放频次,单位条数
id: call.req.data.id // G123生成的告知唯一ID
}
})
}
}
} else if (template == "bulletin") { // 游戏公告板(登录游戏之前的公告)
if (action == "offline") { // 删除公告
ServerToolFun.postServer("server/delGongGao", { "gonggao": call.req.data })
} else {
let _gongGao: GongGaoBan_info[] = []
let bulletin = call.req.data.bulletin
let levelMin = call.req.data.levelMin
let levelMax = call.req.data.levelMax
let stime = call.req.data.startTime
let etime = call.req.data.endTime
for (let index = 0; index < bulletin.length; index++) {
const element = bulletin[index];
let _tmp: GongGaoBan_info = {
content: element.content,
title: element.header,
stime: stime,
etime: etime,
sort: "0", // 写入的时候会复写
otherData: {
levelMin: levelMin,
levelMax: levelMax,
id: call.req.data.id,
serverIds: call.req.data.serverIds
}
}
_gongGao.push(_tmp)
}
ServerToolFun.postServer("server/setGongGao", { "gonggao": _gongGao })
}
}
call.succ({ message: "success", code: 0 });
}

View File

@ -0,0 +1,50 @@
import {ApiCall} from "tsrpc";
import {Reqopen, Resopen} from "../../monopoly/protocols/games/Ptlopen";
import {env} from "process";
import request from "sync-request";
import fs from "fs";
import {initStarupFun} from "../../starup";
export default async function (call: ApiCall<Reqopen, Resopen>) {
// 设置开区时间
let _opentine = call.req.opentime
let _dateTime = new Date(_opentine);
_dateTime = new Date(_dateTime.getTime());
G.openTime = _dateTime.format('YYYY-MM-DD hh:mm:ss')
await setConfig()
call.succ({
code: 0,
message: G.openTime
});
initStarupFun.initStart()
if(call.req.utc){
console.log('---------------开始修改时区shell脚本---------------')
const shell = require('shelljs');
shell.exec(`sh /app/zoeninfo.sh ${call.req.utc}`)
}
}
async function setConfig(){
let type = env.SERVER_TYPE || 'game';
let url = `http://server-tool:7456/server/getConfig?sid=${env.SERVER_ID}&type=${type}`
console.log('拉取服务端启动配置文件', url);
let res = await request('GET', url, {
headers: {
'content-type': 'application/json'
}
});
const body = JSON.parse(res.body.toString());
if (body) {
await fs.writeFileSync('/app/config.json', JSON.stringify(body, null, 2));
console.log('服务端配置: ', body);
} else {
console.log('拉取失败');
}
}

View File

@ -0,0 +1,40 @@
import { ApiCall } from "tsrpc";
import { rankOpenfun } from "../../api_s2c/rank/ApiOpen";
import { Reqranking, Resranking } from "../../monopoly/protocols/games/Ptlranking";
import { NotifiCationFun } from "../../public/notification";
import { PayFun } from "../../public/pay";
export default async function (call: ApiCall<Reqranking, Resranking>) {
// 设置开区时间
let _num = call.req.skip ? 999 : call.req.num
let _rankType = call.req.rankid
// 无此玩家 随便取一个玩家
let gud = await G.mongodb.collection('user').findOne({});
if (!gud) {
return call.error('', { code: 1002, message: globalThis.lng.wuciwanjia });
}
let rescall = PayFun.getCall(gud);
// 排行榜数据
let _rankData = await rankOpenfun(rescall, [_rankType])
// 排行
let _renkList = _rankData[_rankType]["rankList"]
let _resData = []
for (let index = 0; index < _renkList.length; index++) {
const element = _renkList[index];
let _tmp: Resranking["data"][0] = {
ranking: index + 1,
id: element.player.uid,
name: element.player.name,
rankkingValue: (element.valArr ? element.valArr[0] : await NotifiCationFun.getFmtRankVal(_rankType, element)).toString()
}
_resData.push(_tmp)
}
call.succ({
code: 0,
message: globalThis.lng.huoqupaihang,
data: _resData
});
}

View File

@ -0,0 +1,27 @@
import {ApiCall} from "tsrpc";
import {Reqpopup, Respopup} from "../../monopoly/protocols/gift/Ptlpopup";
export default async function (call: ApiCall<Reqpopup, Respopup>) {
// 给用户推送礼包的逻辑实现
let popup_info = call.req
// todo 开发去实现
console.log("收到礼包推送", popup_info)
let user = G.server.uid_connections[popup_info.game_user_id]
let giftLog: any = {...popup_info}
if (user) {
giftLog = {
...popup_info,
showTime: G.time,
endTime: G.time + popup_info.duration
}
G.server.sendMsgByUid(popup_info.game_user_id, 'msg_s2c/SendGift', giftLog)
}
G.mongodb.collection('giftLog').updateOne({popup_id: giftLog.popup_id}, {$set: giftLog}, {upsert: true});
call.succ({})
}

9
src/api_o2s/gm/ApiPay.ts Normal file
View File

@ -0,0 +1,9 @@
import {ApiCall} from "tsrpc";
import {ReqPay, ResPay} from "../../monopoly/protocols/gm/PtlPay";
import {PayFun} from "../../public/pay";
export default async function (call: ApiCall<ReqPay, ResPay>) {
await PayFun.pay(call.req.uid, call.req.payId, call.req.payArgs, call.req.type);
call.succ({});
}

View File

@ -0,0 +1,7 @@
import {ApiCall} from "tsrpc";
import {ReqSendPrize, ResSendPrize} from "../../monopoly/protocols/gm/PtlSendPrize";
export default async function (call: ApiCall<ReqSendPrize, ResSendPrize>) {
}

View File

@ -0,0 +1,61 @@
import { ApiCall } from "tsrpc";
import { g123_response_hdinfo_details, g123_response_hdinfo_details_accountingData, g123_response_hdinfo_details_taowa, Reqdetails, Resdetails } from "../../monopoly/protocols/hdinfo/Ptldetails";
import { HuoDongFun } from "../../public/huodongfun";
import { PayFun } from "../../public/pay";
export default async function (call: ApiCall<Reqdetails, Resdetails>) {
let _where = call.req.uid ? { uid: call.req.uid } : {}
// 无玩家 随便取一个玩家
let gud = await G.mongodb.collection('user').findOne(_where);
if (!gud) {
return call.error('', { code: 1002, message: globalThis.lng.wuciwanjia });
}
let rescall = PayFun.getCall(gud);
// 构造返回值
let _data: g123_response_hdinfo_details[] = []
// 目前游戏只有游戏 5 符合查询要求
// @ts-ignore
let _hds = await HuoDongFun.gethdList(rescall, 5)
for (let index = 0; index < _hds.length; index++) {
const element = _hds[index];
let _dbType: `leijichongzhi${number}` = `leijichongzhi${element.hdid}`
let _users = await G.mongodb.cEvent(_dbType).find({ type: _dbType }).toArray();
let accountingData: g123_response_hdinfo_details_accountingData[] = []
for (let index = 0; index < _users.length; index++) {
const elementUser = _users[index];
let _tmp = {
ranking: index,
participantId: elementUser.uid,
value: await (await PayFun.getPayDaysAllPayNum(elementUser.uid, element.stime, element.rtime)).toString()
}
accountingData.push(_tmp)
}
// 排序
accountingData = accountingData.sort((b, a) => Number(a.value) - Number(b.value))
accountingData.forEach((ele, index) => {
ele.ranking = index + 1
})
let _pushiTmp: g123_response_hdinfo_details_taowa[] = []
_pushiTmp.push({
eventId: element.hdid.toString(),
eventName: element.name,
serverId: G.config.serverId,
accountingTime: element.rtime * 1000,
accountingData: accountingData
})
_data.push({
total: index + 1,
elemengts: _pushiTmp
})
}
call.succ({ status: 0, message: "success", data: _data });
}

View File

@ -0,0 +1,17 @@
import { ApiCall } from "tsrpc";
import { Reqrename, Resrename } from "../../monopoly/protocols/union/Ptlrename";
import { GongHuiFun } from "../../public/gonghui/gonghui";
import { GHManage } from "../../public/gonghui/manage";
export default async function (call: ApiCall<Reqrename, Resrename>) {
let _newName = call.req.guildName;
await GongHuiFun.checkSetArgs({ name: _newName });
let _GH = await GHManage.getGH(call.req.guildId);
if (!_GH) {
call.error('', { status: 1001, message: globalThis.lng.wucigonghui });
}
_GH.updateSetting({ name: _newName });
call.succ({ status: 0, message: "success" });
}

View File

@ -0,0 +1,36 @@
import { ApiCall } from "tsrpc";
import { Reqdata, Resdata } from "../../monopoly/protocols/user/Ptldata";
import { PayFun } from "../../public/pay";
import { PlayerFun } from "../../public/player";
export default async function (call: ApiCall<Reqdata, Resdata>) {
let uid = call.req.data.playerId
let upData = call.req.data.playerData
// 无此玩家
let getgud = await G.mongodb.collection('user').findOne({ uid: uid });
if (!getgud) {
return call.error('', { code: 1002, message: globalThis.lng.wuciwanjia });
}
// 无法修改的数据
let falseData = ["name", "uid", "bindUid"]
// 需要修改的数据key
let _tmp = Object.keys(upData)
let _setData = {}
for (let index = 0; index < _tmp.length; index++) {
const element = _tmp[index];
if (upData[element] == getgud[element] || falseData.indexOf(element) != -1) {
continue
}
_setData[element] = upData[element]
}
if (Object.keys(_setData).length > 0) {
let renamecall = PayFun.getCall(getgud);
await PlayerFun.addAttr(renamecall, _setData);
G.server.sendMsgByUid(uid, 'msg_s2c/PlayerChange', _setData)
}
call.succ({ message: "玩家导入数据成功", code: 0 });
}

View File

@ -0,0 +1,15 @@
import { ApiCall } from "tsrpc";
import { Reqgetdata, Resgetdata } from "../../monopoly/protocols/user/Ptlgetdata";
export default async function (call: ApiCall<Reqgetdata, Resgetdata>) {
let uid = call.req.user_id;
// 无此玩家
let getgud = await G.mongodb.collection('user').findOne({ uid: uid });
if (!getgud) {
return call.error('', { code: 1002, message: globalThis.lng.wuciwanjia });
}
let { _id, ...gud } = getgud;
call.succ({ message: "导出玩家数据成功", code: 0, data: gud });
}

View File

@ -0,0 +1,32 @@
import { ApiCall } from "tsrpc";
import { Reqrename, Resrename } from "../../monopoly/protocols/user/Ptlrename";
import { PlayerFun } from "../../public/player";
import { PayFun } from "../../public/pay";
export default async function (call: ApiCall<Reqrename, Resrename>) {
let uid = call.req.data.playerId
let _name = call.req.data.nickname
// 名称已被使用
let _user = await G.mongodb.collection('user').findOne({ "name": _name });
if (_user) {
return call.error('', { code: 1001, message: globalThis.lng.nameyicunzai });
}
// g123 后台修改不限次数,不扣资源
// let num = call.conn.gud.changeNameNum || 0;
// let need = G.gc.common.usercom.changename[num] || G.gc.common.usercom.changename.slice(-1)[0];
// 无此玩家
let gud = await G.mongodb.collection('user').findOne({ uid: uid });
if (!gud) {
return call.error('', { code: 1002, message: globalThis.lng.wuciwanjia });
}
let rescall = PayFun.getCall(gud);
await PlayerFun.addAttr(rescall, { name: _name });
G.server.sendMsgByUid(uid, 'msg_s2c/PlayerChange', { name: _name })
call.succ({ message: "玩家昵称更新成功", code: 0 });
G.emit('PLAYER_CHANGE_NAME', gud, _name);
}

127
src/api_s2c/ApiBingo.ts Normal file
View File

@ -0,0 +1,127 @@
import { ApiCall } from "tsrpc";
import { HeroFun } from '../public/hero';
import { PlayerFun } from '../public/player';
import { defaultUserAppend, UserFun } from '../public/user';
import { ReqBingo, ResBingo } from "../shared/protocols/PtlBingo";
export default async function (call: ApiCall<ReqBingo, ResBingo>) {
// TODO
if (G.config.debug == false) return call.succ('fail');
let shell = call.req.split(' ');
if (shell[0] == 'all') {
if (shell[1] == 'item') {
if (isNaN(parseInt(shell[2]))) return call.error(`请输入正确的数量`);
await PlayerFun.addItem(call, Object.keys(G.gc.item).map((v, index) => {
return {
a: 'item',
t: v,
n: parseInt(shell[2]),
};
}));
} else if (shell[1] == 'hero') {
if (isNaN(parseInt(shell[2]))) return call.error(`请输入正确的数量`);
await PlayerFun.addHero(call, Object.keys(G.gc.hero).map(v => {
return {
a: 'item',
t: v,
n: parseInt(shell[2]),
};
}));
} else if (shell[1] == 'equip') {
if (isNaN(parseInt(shell[2]))) return call.error(`请输入正确的数量`);
await PlayerFun.addEquip(call, Object.keys(G.gc.equip).map(v => {
return {
a: 'equip',
t: v,
n: parseInt(shell[2]),
};
}));
} else if (shell[1] == 'shiwu') {
if (isNaN(parseInt(shell[2]))) return call.error(`请输入正确的数量`);
if (isNaN(parseInt(shell[3]))) return call.error(`请输入正确的品质`);
await PlayerFun.addShiwu(call, Object.keys(G.gc.shiwu).map(v => {
return {
a: 'shiwu',
t: v,
n: parseInt(shell[2]),
colour: parseInt(shell[3])
};
}));
} else if (shell[1] == 'peijian') {
if (isNaN(parseInt(shell[2]))) return call.error(`请输入正确的数量`);
await PlayerFun.addPeijian(call, Object.keys(G.gc.peijian).map(v => {
return {
a: 'peijian',
t: v,
n: parseInt(shell[2]),
};
}));
}
} else if (shell[0] == 'item') {
if (!G.gc.item[shell[1]]) return call.error(`道具id不存在${shell[1]}`);
if (isNaN(parseInt(shell[2]))) return call.error(`请输入正确的数量`);
await PlayerFun.addItem(call, [{ a: 'item', t: shell[1], n: parseInt(shell[2]) }]);
} else if (shell[0] == 'hero') {
if (!G.gc.hero[shell[1]]) return call.error(`英雄id不存在${shell[1]}`);
if (isNaN(parseInt(shell[2]))) return call.error(`请输入正确的数量`);
await PlayerFun.addHero(call, [{ a: 'item', t: shell[1], n: parseInt(shell[2]) }]);
} else if (shell[0] == 'equip') {
if (!G.gc.equip[shell[1]]) return call.error(`装备id不存在${shell[1]}`);
if (isNaN(parseInt(shell[2]))) return call.error(`请输入正确的数量`);
await PlayerFun.addEquip(call, [{ a: 'equip', t: shell[1], n: parseInt(shell[2]) }]);
} else if (shell[0] == 'shiwu') {
if (!G.gc.shiwu[shell[1]]) return call.error(`饰物id不存在${shell[1]}`);
if (isNaN(parseInt(shell[2]))) return call.error(`请输入正确的数量`);
if (isNaN(parseInt(shell[3]))) return call.error(`请输入正确的品质`);
await PlayerFun.addShiwu(call, [{ a: 'shiwu', t: shell[1], n: parseInt(shell[2]), colour: parseInt(shell[3]) }]);
} else if (shell[0] == 'peijian') {
if (!G.gc.peijian[shell[1]]) return call.error(`配件id不存在${shell[1]}`);
if (isNaN(parseInt(shell[2]))) return call.error(`请输入正确的数量`);
await PlayerFun.addPeijian(call, [{ a: 'peijian', t: shell[1], n: parseInt(shell[2]) }]);
} else if (shell[0] == 'attr') {
if (G.gc.attr[shell[1]] == undefined) return call.error(`道具id不存在${shell[1]}`);
if (isNaN(parseInt(shell[2]))) return call.error(`请输入正确的数量`);
await PlayerFun.addAttr(call, [{ a: 'attr', t: shell[1], n: parseInt(shell[2]) }]);
} else if (shell.length == 2) {
let gud = Object.assign(UserFun.create(''), defaultUserAppend);
if (gud[shell[0]] != undefined) {
let obj = {};
if (typeof gud[shell[0]] == 'string') {
obj[shell[0]] = shell[1];
} else if (typeof gud[shell[0]] == 'number' && !isNaN(parseInt(shell[1]))) {
obj[shell[0]] = parseInt(shell[1]);
} else {
return;
}
await PlayerFun.addAttr(call, obj);
}
} else if (shell[0] == 'heroMaxLv') {
let heros = await G.redis.get('hero', call.uid);
for (let [_id, hero] of Object.entries(heros)) {
await HeroFun.changeHeroAttr(call, hero, { lv: Object.keys(G.gc.playerLv).length * 3, jieji: Object.keys(G.gc.herogrow[hero.heroId]).length - 1 });
}
}
call.succ('succ');
}

View File

@ -0,0 +1,41 @@
import { ApiCall } from "tsrpc";
import { FightFun } from '../public/fight';
import { joinFightData } from '../shared/fightControl/fightType';
import { ReqFightTest, ResFightTest } from "../shared/protocols/PtlFightTest";
import { HeroShared } from '../shared/public/hero';
import { PublicShared } from '../shared/public/public';
export default async function (call: ApiCall<ReqFightTest, ResFightTest>) {
let joins: joinFightData[] = [];
let pd = await FightFun.getPlayerFightData(call.uid);
call.req.roles.forEach((d, i) => {
let player = call.req.player?.[i] || { ...pd, fightHeros: d.map(d => d.hero.heroId.toString()) };
let a: any[] = d.map((hd, index) => {
let buff = HeroShared.getHeroBasicAttr({ ...hd.hero, lv: hd.hero.lv || 1, jieji: hd.hero.jieji || 0 }, player, index + 1);
let hero = {
attr: buff,
...hd.hero
};
PublicShared.mergeProperty(hero.attr, hd.attr);
hero.attr.maxHp = hero.attr.hp;
return hero;
});
joins.push({
player: JSON.parse(JSON.stringify(player)),
roles: Object.fromEntries(a.map((h, p) => [p + 1, h]))
});
});
let res = FightFun.fight(joins);
call.succ({
result: res
});
}

139
src/api_s2c/ApiSyncBtn.ts Normal file
View File

@ -0,0 +1,139 @@
import {ApiCall} from "tsrpc";
import {EventFun} from '../public/event/event';
import {PayFun} from '../public/pay';
import {ReqSyncBtn, ResSyncBtn, syncBtnKeys} from "../shared/protocols/PtlSyncBtn";
import {PublicShared} from '../shared/public/public';
const defaultKeys: syncBtnKeys[] = [
'huobanzhaomu', 'yibaichou', 'shouchong',
'dayjijin', 'dengjijijin', 'guanqiajijin', 'tianshujijin',
'zhanling',
'xianshilibao',
'xianshizhaomu',
'G123Gift'
// 'kaifukuanghuan',
// 'qiridenglu',
// 'leijichongzhi', 'xinshoulibao', 'jierihuodong', 'yuedujijin', 'zixuanlibao', 'diaoluoduihuan', 'chuanshuozhilu',
// 'yangchengmubiao'
];
export default async function (call: ApiCall<ReqSyncBtn, ResSyncBtn>) {
let change: ResSyncBtn = {};
let keys = call.req.length < 1 ? defaultKeys : call.req;
let data = await G.mongodb.collection('syncBtns').findOne({uid: call.uid});
if (!data) data = {} as any;
for (let key of keys) {
switch (key) {
case 'huobanzhaomu':
case 'yibaichou':
case 'shouchong':
//领完消失
if (!data[key]) {
data[key] = {active: true};
change[key] = data[key];
}
break;
case 'dayjijin':
case 'dengjijijin':
case 'guanqiajijin':
case 'tianshujijin':
//领完消失
if (!PublicShared.getEventIsOpen(G.gc.eventOpen[key], call.conn.gud)) {
data[key] = {active: false};
} else {
if (!data[key]) {
data[key] = {active: true};
change[key] = data[key];
}
}
break;
case 'zhanling':
//30天一轮循环不管奖励。常驻活动
if (!PublicShared.getEventIsOpen(G.gc.zhanling.eventOpen, call.conn.gud)) {
data[key] = {active: false};
} else {
let zls = await G.mongodb.collection('scheduler').findOne({type: 'zhanling'});
if (!data[key] || data[key].round != zls.round) {
let lastRunTime = zls && zls.lastRunTime? zls.lastRunTime : G.time
let round = zls && zls.lastRunTime? zls.round : 1
data[key] = {active: true, sTime: lastRunTime, round: round};
change[key] = data[key];
PayFun.setPayLog(call.uid, {payId: G.gc.zhanling.payId, val: []});
G.mongodb.cEvent('zhanling').findOne({uid: call.uid, type: 'zhanling'}).then(data => {
//新一轮战令 不管玩家多久没上线 只补发玩家上一轮没有领取的奖励
data && EventFun.reissueZhanLingPrize(data, call.conn.gud);
G.mongodb.cEvent('zhanling').updateOne(
{uid: call.uid, type: 'zhanling'},
{
$set: {
lv: 1,
exp: 0,
rec: {},
isPay: false,
taskRec: [],
refreshTime: G.time
}
},
{upsert: true}
);
});
}
}
break;
case 'xianshilibao':
// 到时间消失
if (!data.xianshilibao) {
data.xianshilibao = change.xianshilibao = {pays: []};
} else {
change.xianshilibao = data.xianshilibao;
data.xianshilibao.pays = data.xianshilibao.pays.filter(p => {
return p.eTime > G.time;
});
}
break;
case 'xianshizhaomu':
// 不确定
if (G.time < PublicShared.getToDayZeroTime(G.openTime) + G.gc.xianshizhaomu.time.slice(-1)[0]) {
data[key] = {active: false};
} else {
data[key] = {active: false};
}
break;
case 'G123Gift':
data[key] = {active: false, giftInfo:[]};
let giftList = await G.mongodb.collection('giftLog').find({
game_user_id: call.uid,
$or: [{endTime: {$gte: G.time}}, {endTime: {$exists: false}}]
}).toArray();
if (giftList.length>0) {
data[key] = {active: true, giftInfo: giftList.filter(i=>(i.buyNumber||0)<i.purchaseLimitAmount)};
}
for (let item of giftList){
if (item && !item.endTime) {
G.mongodb.collection('giftLog').updateOne({_id: item._id}, {
$set: {
showTime: G.time,
endTime: G.time + item.duration
}
}, {upsert: true});
}
}
break
default:
data[key] = {active: true};
break;
}
}
if (Object.keys(change).length > 0) {
G.mongodb.collection('syncBtns').updateOne({uid: call.uid}, {$set: change}, {upsert: true});
}
call.succ(Object.fromEntries(keys.map(key => [key, data[key]])));
}

12
src/api_s2c/ApiTest.ts Normal file
View File

@ -0,0 +1,12 @@
import { ApiCall } from "tsrpc";
import { PlayerFun } from '../public/player';
import { ReqTest, ResTest } from "../shared/protocols/PtlTest";
export default async function (call: ApiCall<ReqTest, ResTest>) {
// TODO
// if (G.config.debug == false) return call.succ({});
await PlayerFun.sendPrize(call, G.gc.playerdata.data);
call.succ({});
// PayFun.pay(call.uid, 'zuanshi_1', G.gc.pay['zuanshi_1'].prize);
// call.succ({});
}

View File

@ -0,0 +1,15 @@
import { ApiCall } from "tsrpc";
import { ReqDelPrivate, ResDelPrivate } from "../../shared/protocols/chat/PtlDelPrivate";
export default async function (call: ApiCall<ReqDelPrivate, ResDelPrivate>) {
G.redis.get('chatPrivate', call.uid).then(v => {
if (v?.includes(call.req.privateId)) {
G.redis.arrPop('chatPrivate', call.uid, v.findIndex(id => id == call.req.privateId));
}
});
G.mongodb.collection('chat').deleteOne({ type: call.req.privateId });
call.succ({});
}

View File

@ -0,0 +1,23 @@
import { ApiCall } from "tsrpc";
import { ChatFun } from '../../public/chat';
import { ReqGetList, ResGetList } from "../../shared/protocols/chat/PtlGetList";
import { PublicShared } from "../../shared/public/public";
export default async function (call: ApiCall<ReqGetList, ResGetList>) {
let publicList = await G.mongodb.collection('chat').find({ type: { $in: ['cross', 'local', `guild${call.conn.gud.ghId || ''}`] } }).toArray();
let _guildList = publicList.find(l => l.type.indexOf('guild') != -1)?.list || []
let list = {
cross: publicList.find(l => l.type == 'cross')?.list || [],
local: publicList.find(l => l.type == 'local')?.list || [],
guild: _guildList.filter(l => { return PublicShared.getToDayZeroTime(G.time) < l.time }),
private: await ChatFun.getPrivateList(call.uid)
};
// 删除过期帮助
if (_guildList.length != list.guild.length) {
G.mongodb.collection('chat').updateOne({ type: 'guild' + call.conn.gud.ghId }, { $set: { list: list.guild } });
}
call.succ(list);
}

View File

@ -0,0 +1,84 @@
import { ApiCall } from "tsrpc";
import { PayFun } from '../../public/pay';
import { PlayerFun } from '../../public/player';
import { ReqHelp, ResHelp } from "../../shared/protocols/chat/PtlHelp";
import { PublicShared } from '../../shared/public/public';
export default async function (call: ApiCall<ReqHelp, ResHelp>) {
call.req.helps = call.req.helps.filter(h => {
return G.time >= PublicShared.getToDayZeroTime(h.cTime) && call.uid != h.uid;
});
// 'chat list is null'
if (call.req.helps.length < 1) return call.error('', { code: -1, message: globalThis.lng.chat_1 });
let chatList = await G.mongodb.collection('chat').findOne({ type: 'guild' + call.conn.gud.ghId });
if (!chatList || chatList.list.length < 1) return call.error('', { code: -2, message: globalThis.lng.chat_1 });
let list = [];
let _isQz: 0 | 1 = 0
chatList.list.remove(v => {
// 只需要移除过期的即可 (不是当天的就是过期)
if (PublicShared.getToDayZeroTime(v.time) == PublicShared.getToDayZeroTime(G.time)) {
// 帮助次数不够
_isQz = (v.sender.uid == call.uid && v.otherData.myhelpless >= call.req.helps.length) && _isQz == 0 ? 1 : _isQz
list.push(v);
return true;
} else return false;
});
if (_isQz == 0) {
// '请先求助或帮助次数不够'
return call.error('', { code: -3, message: globalThis.lng.chat_2 });
}
// 新增条件,移除本玩家
let listFilter = list.filter(li => li.otherData.helpUis.length < G.gc.shili_com.resHelp[li.otherData.helpIndex].num && !li.otherData.helpUis.includes(call.uid)
&& (li.sender.uid != call.uid));
if (listFilter.length < 1) return call.error('', { code: -4, message: 'chat list is null' });
let prize = [];
let change = [];
let need = [];
for (let index = 0; index < call.req.helps.length; index++) {
const element = call.req.helps[index];
for (let index = 0; index < list.length; index++) {
const li = list[index];
// 扣除帮助次数
if (li.sender.uid == call.uid) {
let _lessNum = li.otherData.myhelpless - 1
li.otherData.myhelpless = _lessNum < 0 ? 0 : _lessNum
}
// 修改被帮玩家数据 及 发奖
if (li.sender.uid == element.uid) {
change.push({
uid: li.sender.uid,
cTime: li.time,
pushUid: call.uid,
});
li.otherData.helpUis.push(call.uid);
if (G.gc.shili_com.resHelp[li.otherData.helpIndex] <= li.otherData.helpUis.length) {
PlayerFun.sendPrize(PayFun.getCall(await G.redis.get('user', li.sender.uid)), [G.gc.shili_com.resHelp[li.otherData.helpIndex].need]);
}
prize.push(...PublicShared.randomDropGroup(G.gc.shili_com.resHelp[li.otherData.helpIndex].helpPrizeDrop));
}
}
}
// 新改帮助无消耗
// need = PublicShared.mergePrize(need);
// await PlayerFun.checkNeedIsMeet(call, need);
// await PlayerFun.cutNeed(call, need);
prize = PublicShared.mergePrize(prize);
await PlayerFun.sendPrize(call, prize);
G.server.broadcastClusterMsg('msg_s2c/ChatHelp', { change: change }, {ghId:call.conn.gud.ghId});
G.mongodb.collection('chat').updateOne({ type: 'guild' + call.conn.gud.ghId }, { $set: { list: list } });
call.succ({
prize: prize
});
}

View File

@ -0,0 +1,39 @@
import { ApiCall } from "tsrpc";
import { ChatFun } from '../../public/chat';
import { FriendManage } from '../../public/friend/manage';
import { ReqPrivate, ResPrivate } from "../../shared/protocols/chat/PtlPrivate";
import { MsgPrivate } from '../../shared/protocols/msg_s2c/MsgPrivate';
export default async function (call: ApiCall<ReqPrivate, ResPrivate>) {
let my = await FriendManage.getFriend(call.uid);
if (!my.data.friendList.includes(call.req.uid)) return call.errorCode(-1);
let privateId = [call.uid, call.req.uid].sort().join('&');
ChatFun.writePrivateId(call.uid, privateId);
ChatFun.writePrivateId(call.req.uid, privateId);
let recipient = await G.mongodb.collection('user').findOne({ uid: call.req.uid });
let msg: MsgPrivate = {
msg: call.req.msg,
time: G.time,
sender: call.conn.gud,
privateId: privateId,
otherData: {
uids: [call.req.uid, call.uid]
},
recipient: recipient
};
G.mongodb.collection('chat').updateOne(
{ type: privateId },
{ $push: { list: msg } },
{ upsert: true }
);
G.server.sendMsgByUid(call.uid, 'msg_s2c/Private', msg);
G.server.sendMsgByUid(call.req.uid, 'msg_s2c/Private', msg);
call.succ({});
}

View File

@ -0,0 +1,39 @@
import { ApiCall, WsClientStatus } from "tsrpc";
import { ActionLog } from '../../public/actionLog/actionLog';
import { ChatFun } from '../../public/chat';
import { ReqSend, ResSend } from "../../shared/protocols/chat/PtlSend";
export default async function (call: ApiCall<ReqSend, ResSend>) {
let data = call.req;
if (data.msg.length < 1 || data.msg.length > 30) return call.error('', { code: -1 });
if (data.otherData?.helpIndex != undefined) {
let num = await ActionLog.getDayLog(call.uid, 'resHelp');
if (num > 0) return call.errorCode(-2);
ActionLog.addDayLog(call.uid, { key: 'resHelp', val: 1 });
data.otherData.helpUis = [];
// 我助力别人次数 初始10
data.otherData.myhelpless = 10;
}
let gud = call.conn.gud;
let sendData = {
...data,
time: G.time,
sender: gud
};
if (sendData.type == 'guild' && !gud.ghId) return call.error('', { code: -3, message: globalThis.lng.chat_3 });
if (sendData.type == 'cross' && G.clientCross?.status == WsClientStatus.Opened) {
G.clientCross.sendMsg('msg_cross/CrossChat', sendData);
call.succ({});
return;
}
ChatFun.newMsg(sendData);
call.succ({});
}

View File

@ -0,0 +1,28 @@
import { ApiCall } from "tsrpc";
import { PlayerFun } from '../../public/player';
import { ReqBuyGift, ResBuyGift } from "../../shared/protocols/chongzhi/PtlBuyGift";
export default async function (call: ApiCall<ReqBuyGift, ResBuyGift>) {
if (call.req.vip > call.conn.gud.vip) return call.error(globalThis.lng.chongzhi_1);
if (!G.gc.chongzhi.tequan[call.req.vip] || !G.gc.chongzhi.tequan[call.req.vip].gift) return call.error(globalThis.lng.chongzhi_2);
let data = await G.mongodb.cPlayerInfo('chongzhi').findOne({ uid: call.uid, type: 'chongzhi' });
let buyNum = data?.giftBy?.[call.req.vip];
let need = G.gc.chongzhi.tequan[call.req.vip].gift.need.map(v => { return { ...v, n: v.n * G.gc.chongzhi.tequan[call.req.vip].gift.sale / 10 }; });
if (buyNum >= G.gc.chongzhi.tequan[call.req.vip].gift.buyNum) return call.error(globalThis.lng.chongzhi_3);
await PlayerFun.checkNeedIsMeet(call, need);
await PlayerFun.cutNeed(call, need);
await PlayerFun.sendPrize(call, G.gc.chongzhi.tequan[call.req.vip].gift.prize);
G.mongodb.cPlayerInfo('chongzhi').updateOne(
{ uid: call.uid, type: 'chongzhi' },
{ $inc: G.mongodb.createTreeObj({ key: 'giftBy', k: call.req.vip.toString(), val: 1 }) },
{ upsert: true }
);
call.succ({
prize: G.gc.chongzhi.tequan[call.req.vip].gift.prize
});
}

View File

@ -0,0 +1,14 @@
import { ApiCall } from "tsrpc";
import { PayFun } from '../../public/pay';
import { ReqOpen, ResOpen } from "../../shared/protocols/chongzhi/PtlOpen";
export default async function (call: ApiCall<ReqOpen, ResOpen>) {
let data = await G.mongodb.cPlayerInfo('chongzhi').findOne({ uid: call.uid, type: 'chongzhi' });
let logs = await PayFun.getPayLog(call.uid);
call.succ({
payNum: Object.fromEntries(G.gc.chongzhi.payCom.map(pay => pay.payId).map(payId => [payId, logs?.[payId]?.length || 0])),
giftBuy: data?.giftBy || {},
});
}

View File

@ -0,0 +1,24 @@
import { ApiCall } from "tsrpc";
import { PlayerFun } from '../../public/player';
import { ReqBuyNum, ResBuyNum } from "../../shared/protocols/conglinshoulie/PtlBuyNum";
import { HongDianChange } from "../hongdian/fun";
import { clslDb } from './ApiOpen';
export default async function (call: ApiCall<ReqBuyNum, ResBuyNum>) {
let db = await clslDb().findOne({ uid: call.uid, type: 'clsl' });
let buyNum = db?.buyFightNum || 0;
let hasNum = G.gc.clsl_com.vipBuyFightNum[call.conn.gud.vip];
if (buyNum >= hasNum) return call.errorCode(-1);
let _need = [G.gc.clsl_com.buyFightNumNeed[buyNum]]
await PlayerFun.checkNeedIsMeet(call, _need);
await PlayerFun.cutNeed(call, _need);
clslDb().updateOne({ uid: call.uid, type: 'clsl' }, { $inc: { buyFightNum: 1 } });
HongDianChange.sendChangeKey(call.uid, ['clslhd'])
call.succ({});
}

View File

@ -0,0 +1,40 @@
import { ApiCall } from "tsrpc";
import { FightFun } from '../../public/fight';
import { PlayerFun } from '../../public/player';
import { ReqFind, ResFind } from "../../shared/protocols/conglinshoulie/PtlFind";
import { PublicShared } from '../../shared/public/public';
import { addStar, clslDb } from './ApiOpen';
export default async function (call: ApiCall<ReqFind, ResFind>) {
let weekZeroTime = PublicShared.getToWeekMondayZeroTime();
if (G.time < weekZeroTime + G.gc.clsl_com.fightTime[0] || G.time > weekZeroTime + G.gc.clsl_com.fightTime[1]) return call.errorCode(-1);
let db = await clslDb().findOne({ uid: call.uid, type: 'clsl' });
let curStar = db?.allStar || 0;
let useNum = db?.useFightNum || 0;
let buyNum = db?.buyFightNum || 0;
let starConf = G.gc.clsl_dan[curStar] || Object.values(G.gc.clsl_dan).slice(-1)[0];
if (useNum >= buyNum + G.gc.clsl_com.fightNum) return call.errorCode(-2);
let my = await call.conn.getDefaultFightData();
let other = (await G.clientCross.callApi('clsl/FindEnemy', { uid: call.uid })).res;
let result = FightFun.fight([my, other.info]);
if ((result.winSide != 0 && starConf.failCut) || result.winSide == 0) {
addStar(call, result.winSide == 0 ? 1 : -starConf.failCut, my);
}
result.winSide == 0 && clslDb().updateOne({ uid: call.uid, type: 'clsl' }, { $inc: { fightWinNum: 1 } });
clslDb().updateOne({ uid: call.uid, type: 'clsl' }, { $inc: { useFightNum: 1 } });
await PlayerFun.sendPrize(call, starConf.fightPrize);
G.clientCross?.callApi('clsl/Log', { uid: call.uid, result: result });
G.clientCross?.callApi('clsl/Log', { uid: other.info.player.uid, result: result });
call.succ({
enemy: other,
result: result
});
}

View File

@ -0,0 +1,6 @@
import { ApiCall } from "tsrpc";
import { ReqGetLog, ResGetLog } from "../../shared/protocols/conglinshoulie/PtlGetLog";
export default async function (call: ApiCall<ReqGetLog, ResGetLog>) {
call.succ((await G.clientCross.callApi('clsl/Log', { uid: call.uid })).res?.logs || []);
}

View File

@ -0,0 +1,47 @@
import { OptionalId, WithId } from 'mongodb';
import { ApiCall } from "tsrpc";
import { CollectionPlayerInfo } from '../../module/collection_palyerInfo';
import { joinFightData } from '../../shared/fightControl/fightType';
import { ReqOpen, ResOpen } from "../../shared/protocols/conglinshoulie/PtlOpen";
import { PublicShared } from '../../shared/public/public';
export default async function (call: ApiCall<ReqOpen, ResOpen>) {
let db = await clslDb().findOne({ uid: call.uid, type: 'clsl' });
let { _id, uid, type, ...ops } = db || {} as WithId<OptionalId<CollectionPlayerInfo<"clsl">>>;
if (!db || ops?.refreshTime < PublicShared.getToDayZeroTime()) {
let change: Partial<typeof ops> = {
refreshTime: G.time,
useFightNum: 0,
recWinPrize: [],
fightWinNum: 0,
buyFightNum: 0
};
Object.assign(ops, change);
clslDb().updateOne({ uid: call.uid, type: 'clsl' }, { $set: change }, { upsert: true });
call.conn.getDefaultFightData().then(v => {
G.clientCross.callApi('clsl/UpLoad', { uid: call.uid, info: v });
});
}
call.succ({
allStar: ops?.allStar || 0,
buyFightNum: ops?.buyFightNum || 0,
useFightNum: ops?.useFightNum || 0,
fightWinNum: ops?.fightWinNum || 0,
recWinPrize: ops?.recWinPrize || []
});
}
export function clslDb() {
return G.mongodb.cPlayerInfo('clsl');
}
export async function addStar(call: ApiCall, star: number, info?: joinFightData) {
clslDb().updateOne({ uid: call.uid, type: 'clsl' }, { $inc: { allStar: star } }, { upsert: true });
G.clientCross.callApi('clsl/UpLoad', { uid: call.uid, allStar: star, info: info || await call.conn.getDefaultFightData() });
}

View File

@ -0,0 +1,23 @@
import { ApiCall } from "tsrpc";
import { PlayerFun } from '../../public/player';
import { ReqRec, ResRec } from "../../shared/protocols/conglinshoulie/PtlRec";
import { HongDianChange } from "../hongdian/fun";
import { addStar, clslDb } from './ApiOpen';
export default async function (call: ApiCall<ReqRec, ResRec>) {
let conf = G.gc.clsl_com.fightWinPrize[call.req.index];
if (!conf) return call.errorCode(-1);
let db = await clslDb().findOne({ uid: call.uid, type: 'clsl' });
if ((db?.fightWinNum || 0) < conf.total || db?.recWinPrize?.includes(call.req.index)) return call.errorCode(-2);
await PlayerFun.sendPrize(call, conf.prize);
addStar(call, conf.star);
clslDb().updateOne({ uid: call.uid, type: 'clsl' }, { $push: { recWinPrize: call.req.index } });
HongDianChange.sendChangeKey(call.uid, ['clslhd'])
call.succ({});
}

View File

@ -0,0 +1,6 @@
import { ApiCall } from "tsrpc";
import { ReqOpen, ResOpen } from "../../shared/protocols/dixiaheishi/PtlOpen";
export default async function (call: ApiCall<ReqOpen, ResOpen>) {
call.error(globalThis.lng.dixiaheishi_3);
}

View File

@ -0,0 +1,31 @@
import { ApiCall } from "tsrpc";
import { DxltFun } from '../../public/dxlt';
import { PlayerFun } from '../../public/player';
import { ReqBuy, ResBuy } from "../../shared/protocols/dixialeitai/PtlBuy";
import { ResOpen } from '../../shared/protocols/dixialeitai/PtlOpen';
import { HongDianChange } from "../hongdian/fun";
export default async function (call: ApiCall<ReqBuy, ResBuy>) {
let change: Partial<ResOpen> = {};
let data = await DxltFun.getData(call);
let shopItem = data.shop[call.req.id];
if (!shopItem) return call.error(globalThis.lng.dixialeitai_1);
if (shopItem.useBuyNum >= shopItem.buyNum) return call.error(globalThis.lng.dixialeitai_1);
shopItem.useBuyNum++;
change.shop = data.shop;
await PlayerFun.checkNeedIsMeet(call, shopItem.need);
await PlayerFun.sendPrize(call, shopItem.prize);
await PlayerFun.cutNeed(call, shopItem.need);
await DxltFun.changeData(call, change);
HongDianChange.sendChangeKey(call.uid, ['dxlthd']);
call.succ({
change: change,
prize: shopItem.prize
});
}

View File

@ -0,0 +1,94 @@
import { ApiCall } from "tsrpc";
import { DxltFun } from '../../public/dxlt';
import { FightFun } from '../../public/fight';
import { PlayerFun } from '../../public/player';
import { formatNpcData } from '../../shared/fightControl/fightFun';
import { roleDataType } from '../../shared/fightControl/fightType';
import { ReqFight, ResFight } from "../../shared/protocols/dixialeitai/PtlFight";
import { ResOpen } from '../../shared/protocols/dixialeitai/PtlOpen';
import { HongDianChange } from "../hongdian/fun";
export default async function (call: ApiCall<ReqFight, ResFight>) {
let change: Partial<ResOpen> = {};
let data = await DxltFun.getData(call);
if (data.killBoss >= G.gc.dxlt_com.dayFightLayer) return call.error(globalThis.lng.dixialeitai_2);
if (G.gc.dxlt_layer[data.curLayer].type != 1) return call.error(globalThis.lng.dixialeitai_3);
if (data.over) return call.error(globalThis.lng.dixialeitai_4);
if (!data.heros[call.req]) return call.error(globalThis.lng.dixialeitai_5);
if (data.heros[call.req].attr.hp <= 0) return call.error(globalThis.lng.dixialeitai_6);
let hero: roleDataType = JSON.parse(JSON.stringify(data.heros[call.req]));
Object.assign(hero.attr, DxltFun.getBuff(data));
let npc = formatNpcData(G.gc.dxlt_layer[data.curLayer].npcId);
Object.entries(data.enemyState).forEach(role => {
Object.assign(npc.roles[role[0]].attr, role[1]);
});
const result = FightFun.fight(
[
{
player: call.conn.gud,
roles: Object.fromEntries([hero].map(hero => [1, hero]))
},
npc
],
30,
'pve'
);
let _role = result.fightData[0].roles[1];
Object.assign(data.heros[call.req].attr, { hp: _role.attr.hp, maxHp: _role.attr.maxHp });
change.heros = data.heros;
change.enemyState = {};
let prize: atn[] = [];
if (result.winSide == 0) {
DxltFun.saodan(data, 1);
change.over = true;
change.item = data.item;
change.buff = data.buff;
if (data.saodang.mibaoNum) {
change.mibao = (data.mibao || 0) + data.saodang.mibaoNum;
}
if (G.gc.dxlt_layer[data.curLayer].isBoss) {
change.killBoss = (data.killBoss || 0) + 1;
}
prize.push(...G.gc.dxlt_layer[data.curLayer].price);
if (data.saodang.prize) {
prize.push(...data.saodang.prize);
}
if (data.saodang.shop) {
DxltFun.changeShop(data, change);
}
DxltFun.passLayerChange(data, change);
} else {
Object.entries(result.fightData[1].roles).forEach(role => {
change.enemyState[role[0]] = { hp: role[1].attr.hp, maxHp: role[1].attr.maxHp };
});
}
if (prize.length > 0) {
await PlayerFun.sendPrize(call, prize);
}
await DxltFun.changeData(call, change);
HongDianChange.sendChangeKey(call.uid, ['dxlthd']);
call.succ({
change: change,
result: result,
fightPrize: data.saodang || {},
prize: prize
});
}

View File

@ -0,0 +1,30 @@
import { ApiCall } from "tsrpc";
import { DxltFun } from '../../public/dxlt';
import { ReqNext, ResNext } from "../../shared/protocols/dixialeitai/PtlNext";
import { ResOpen } from '../../shared/protocols/dixialeitai/PtlOpen';
import { HongDianChange } from "../hongdian/fun";
export default async function (call: ApiCall<ReqNext, ResNext>) {
let change: Partial<ResOpen> = {};
let data = await DxltFun.getData(call);
if (!G.gc.dxlt_layer[data.curLayer + 1]) return call.error(globalThis.lng.dixialeitai_7);
change.curLayer = data.curLayer += 1;
if (G.gc.dxlt_layer[change.curLayer].type == 2) {
DxltFun.passLayerChange(data, change);
DxltFun.changeShop(data, change);
change.over = true;
} else {
change.over = false;
}
await DxltFun.changeData(call, change);
HongDianChange.sendChangeKey(call.uid, ['dxlthd'])
call.succ({
change: change
});
}

View File

@ -0,0 +1,47 @@
import { ApiCall } from "tsrpc";
import { DxltFun } from '../../public/dxlt';
import { ReqOpen, ResOpen } from "../../shared/protocols/dixialeitai/PtlOpen";
import { PublicShared } from '../../shared/public/public';
import { HongDianChange } from "../hongdian/fun";
export default async function (call: ApiCall<ReqOpen, ResOpen>) {
let collection = await G.mongodb.collection('dxlt').findOne({ uid: call.uid });
if (!collection) return call.error('', { code: 2 });
let { _id, uid, ...data } = collection;
if (Object.keys(data).length == 2) {//说明第一次进入游戏
data.buff = {};
data.item = {};
data.over = false;
data.curLayer = 1;
data.maxLayer = 0;
data.curMaxLayer = 0;
data.toDayLayer = 0;
data.recordLayer = 0;
data.mibao = 0;
data.enemyState = {};
data.killPrizeRec = [];
data.passPrizeRec = [];
data.shop = {};
data.killBoss = 0;
call.succ(data);
} else if (PublicShared.getToDayZeroTime() >= PublicShared.getToDayZeroTime(data.resetTime) + 2 * 24 * 3600) {//每两天重置
data.item = {};
data.buff = {};
data.toDayLayer = 0;
data.enemyState = {};
data.killPrizeRec = [];
data.shop = {};
data.killBoss = 0;
DxltFun.backLayer(data);
call.error('', { code: 2 });
HongDianChange.sendChangeKey(call.uid, ['dxlthd']);
} else {
call.succ(data);
}
G.redis.set('dxlt', call.uid, data);
G.mongodb.collection('dxlt').updateOne({ uid: call.uid }, { $set: { ...data } });
}

View File

@ -0,0 +1,27 @@
import { ApiCall } from "tsrpc";
import { DxltFun } from '../../public/dxlt';
import { PlayerFun } from '../../public/player';
import { ResOpen } from '../../shared/protocols/dixialeitai/PtlOpen';
import { ReqRecMiBao, ResRecMiBao } from "../../shared/protocols/dixialeitai/PtlRecMiBao";
import { HongDianChange } from "../hongdian/fun";
export default async function (call: ApiCall<ReqRecMiBao, ResRecMiBao>) {
let change: Partial<ResOpen> = {};
let data = await DxltFun.getData(call);
if (!G.gc.dxlt_mb[call.req.id]) return call.error(globalThis.lng.dixialeitai_5);
if (data.mibao < G.gc.dxlt_com.getPrizeByMiBaoNum) return call.error(globalThis.lng.dixialeitai_8);
change.mibao = (data.mibao - G.gc.dxlt_com.getPrizeByMiBaoNum);
await PlayerFun.sendPrize(call, G.gc.dxlt_mb[call.req.id].mibao);
await DxltFun.changeData(call, change);
HongDianChange.sendChangeKey(call.uid, ['dxlthd']);
call.succ({
change: change,
prize: G.gc.dxlt_mb[call.req.id].mibao
});
}

View File

@ -0,0 +1,32 @@
import { ApiCall } from "tsrpc";
import { DxltFun } from '../../public/dxlt';
import { PlayerFun } from '../../public/player';
import { ResOpen } from '../../shared/protocols/dixialeitai/PtlOpen';
import { ReqRecPrize, ResRecPrize } from "../../shared/protocols/dixialeitai/PtlRecPrize";
import { HongDianChange } from "../hongdian/fun";
export default async function (call: ApiCall<ReqRecPrize, ResRecPrize>) {
let change: Partial<ResOpen> = {};
let data = await DxltFun.getData(call);
let val = call.req.type == 'killPrizeRec' ? (data.killBoss || 0) : data.maxLayer;
let conf = call.req.type == 'killPrizeRec' ? G.gc.dxlt_com.killPrize : G.gc.dxlt_com.passPrize;
if (!conf[call.req.index]) return call.error(globalThis.lng.dixialeitai_5);
if (data[call.req.type].includes(call.req.index)) return call.error(globalThis.lng.dixialeitai_9);
if (val < conf[call.req.index].need) return call.error(globalThis.lng.dixialeitai_10);
data[call.req.type].push(call.req.index);
change[call.req.type] = data[call.req.type];
await PlayerFun.sendPrize(call, conf[call.req.index].prize);
await DxltFun.changeData(call, change);
HongDianChange.sendChangeKey(call.uid, ['dxlthd']);
call.succ({
change: change,
prize: conf[call.req.index].prize
});
}

View File

@ -0,0 +1,30 @@
import { ApiCall } from "tsrpc";
import { HeroFun } from '../../public/hero';
import { ReqSetDef, ResSetDef } from "../../shared/protocols/dixialeitai/PtlSetDef";
export default async function (call: ApiCall<ReqSetDef, ResSetDef>) {
let arr = call.req;
if (arr.isDuplication()) return call.error(globalThis.lng.dixialeitai_5);
if (arr.length < G.gc.dxlt_com.heroNum[0] || arr.length > G.gc.dxlt_com.heroNum[1]) return call.error(globalThis.lng.dixialeitai_5);
let heros = await HeroFun.getHeros(call, arr);
if (heros.filter(hero => hero != null).length < arr.length) return call.error(globalThis.lng.dixialeitai_5);
await G.mongodb.collection('dxlt').updateOne(
{
uid: call.uid
},
{
$set: {
resetTime: G.time,
heros: (await call.conn.getDefaultFightData(Object.fromEntries(arr.map((_id, pos) => [pos + 1, _id])))).roles
}
},
{
upsert: true
}
);
call.succ({});
}

View File

@ -0,0 +1,70 @@
import { ApiCall } from "tsrpc";
import { DxltFun } from '../../public/dxlt';
import { PlayerFun } from '../../public/player';
import { ResOpen } from '../../shared/protocols/dixialeitai/PtlOpen';
import { ReqUseItem, ResUseItem } from "../../shared/protocols/dixialeitai/PtlUseItem";
import { HongDianChange } from "../hongdian/fun";
export default async function (call: ApiCall<ReqUseItem, ResUseItem>) {
let args = call.req;
let change: Partial<ResOpen> = {};
let data = await DxltFun.getData(call);
let item = data.item;
let conf = G.gc.dxlt_com.fightPrize.item[args.id];
let prize: atn[] = [];
if (!item[args.id]) return call.error(globalThis.lng.dixialeitai_11);
if (args.id == '1' && !data.heros[args.pos]) return call.error(globalThis.lng.dixialeitai_5);
if (args.id == '2' && data.killBoss >= G.gc.dxlt_com.dayFightLayer) return call.error(globalThis.lng.dixialeitai_2);
if (args.id == '2' && G.gc.dxlt_layer[data.curLayer].type != 1) return call.error(globalThis.lng.dixialeitai_12);
if (args.id == '2' && data.over) return call.error(globalThis.lng.dixialeitai_12);
item[args.id]--;
switch (args.id) {
case '1':
data.heros[args.pos].attr.hp += data.heros[args.pos].attr.maxHp * conf.val;
if (data.heros[args.pos].attr.hp > data.heros[args.pos].attr.maxHp) data.heros[args.pos].attr.hp = data.heros[args.pos].attr.maxHp;
change.heros = data.heros;
break;
case '2':
DxltFun.saodan(data, 1);
change.over = true;
change.buff = data.buff;
if (data.saodang.mibaoNum) {
change.mibao += data.saodang.mibaoNum;
}
if (G.gc.dxlt_layer[data.curLayer].isBoss) {
change.killBoss = (data.killBoss || 0) + 1;
}
prize.push(...G.gc.dxlt_layer[data.curLayer].price);
if (data.saodang.prize) {
prize.push(...data.saodang.prize);
}
if (data.saodang.shop) {
DxltFun.changeShop(data, change);
}
DxltFun.passLayerChange(data, change);
break;
case '3':
DxltFun.changeShop(data, change);
break;
}
change.item = data.item;
prize.length > 0 && await PlayerFun.sendPrize(call, prize);
await DxltFun.changeData(call, change);
HongDianChange.sendChangeKey(call.uid, ['dxlthd']);
call.succ({
change: change,
fightPrize: data.saodang || {},
prize: prize
});
}

View File

@ -0,0 +1,11 @@
import { ApiCall } from "tsrpc";
import { DiXiaQianZhuangFun } from "../../public/dixiaqianzhuang";
import { ReqOpen, ResOpen } from "../../shared/protocols/dixiaqianzhuang/PtlOpen";
export default async function (call: ApiCall<ReqOpen, ResOpen>) {
let result = await DiXiaQianZhuangFun.getMyData(call)
call.succ({
num: result
});
}

View File

@ -0,0 +1,109 @@
import { OptionalId, UpdateFilter } from 'mongodb';
import { ApiCall } from "tsrpc";
import { CollectionPlayerInfo } from '../../module/collection_palyerInfo';
import { PlayerFun } from '../../public/player';
import { ReqQf, ResQf } from "../../shared/protocols/dixiaqianzhuang/PtlQf";
import { ResOpen } from '../../shared/protocols/dixiaqianzhuang/PtlOpen';
import { DiXiaQianZhuangFun } from '../../public/dixiaqianzhuang';
import { HongDianChange } from '../hongdian/fun';
export default async function (call: ApiCall<ReqQf, ResQf>) {
let need: atn[];
let prize: atn[];
let _num = await DiXiaQianZhuangFun.getMyData(call)
let update: UpdateFilter<OptionalId<CollectionPlayerInfo<"dixiaqianzhuang">>>;
let changeData: Partial<ResOpen>;
let _rbj = {} // 返回的暴击次数
let _needNum: number = 0
let _jinbi: number = 0
let isnum: number = 0 // 实际次数
if (call.req.type == 1) {
let _myNeed = await DiXiaQianZhuangFun.getNumNeed(call, _num + 1)
// vip 条件不足
if (_myNeed.needvip > call.conn.gud.vip) {
return call.error('', { code: -1, message: globalThis.lng.dixaiqianzhuang_1 })
}
if (_myNeed.need) {
_needNum = _myNeed.need
}
let _bj = await DiXiaQianZhuangFun.getBj()
_jinbi += _myNeed.jinbi * _bj
_rbj[_bj.toString()] = 1
isnum = 1
} else if (call.req.type == 10) {
for (let index = 1; index <= call.req.type; index++) {
let _myNeed = await DiXiaQianZhuangFun.getNumNeed(call, _num + index)
if (_myNeed.needvip > call.conn.gud.vip) {
break
}
isnum += 1
if (_myNeed.need) {
_needNum += _myNeed.need
}
let _bj = await DiXiaQianZhuangFun.getBj()
// console.log("第 {} 次暴击 {} 倍数", index, _bj)
if (_myNeed.jinbi) {
_jinbi += _myNeed.jinbi * _bj
}
// 返回的暴击次数
if (_rbj[_bj]) {
_rbj[_bj] += 1
} else {
_rbj[_bj] = 1
}
}
// 一次次数都没有
if (isnum == 0) {
return call.error('', { code: -2, message: globalThis.lng.dixaiqianzhuang_1 })
}
}
// 更新数据的数据
update = {
$set: { time: G.time, num: isnum + _num }
};
if (_needNum) {
need = [{ "a": "attr", "t": "rmbmoney", "n": _needNum }]
let meet = await PlayerFun.checkNeedByArgs(call, need[0]);
need = [meet.atn];
}
prize = [{ "a": "attr", "t": "jinbi", "n": _jinbi }]
// 设置数据
G.mongodb.collection('playerInfo', 'dixiaqianzhuang').updateOne(
{
uid: call.uid,
type: 'dixiaqianzhuang'
},
{
...update
},
{
upsert: true
}
);
// 扣除奖励和发奖
need && await PlayerFun.cutNeed(call, need);
await PlayerFun.sendPrize(call, prize);
changeData = {
num: _num + isnum
};
HongDianChange.sendChangeKey(call.uid, ['dixiaqianzhuanghd', 'taskhd', 'huodonghd'])
call.succ({
prize: prize,
changeData: changeData,
bj: _rbj
});
}

View File

@ -0,0 +1,20 @@
import { ApiCall } from "tsrpc";
import { EmailFun } from '../../public/email';
import { PlayerFun } from '../../public/player';
import { ReqAllReceive, ResAllReceive } from "../../shared/protocols/email/PtlAllReceive";
export default async function (call: ApiCall<ReqAllReceive, ResAllReceive>) {
let emailList = (await EmailFun.getAllEmail(call.uid, true)).filter(email => (email.type == 'system' && email.prizeData?.isGet == false && email.prizeData?.prize?.length > 0)
|| (email.type == 'system' && email.uid == "system" && (email?.prizelist?.indexOf(call.uid) == -1 && call.conn.gud && call.conn.gud.cTime <= email.createTime)));
if (emailList.length < 1) return call.error(globalThis.lng.email_1);
let prizeList = emailList.map(email => email.prizeData.prize).reduce((a, b) => a.concat(b));
let sendPrize = await PlayerFun.sendPrize(call, prizeList);
call.succ({
prize: sendPrize,
change: EmailFun.receiveEmail(call.uid, emailList.map(email => email._id))
});
}

View File

@ -0,0 +1,13 @@
import { ApiCall } from "tsrpc";
import { EmailFun } from '../../public/email';
import { ReqAllRemove, ResAllRemove } from "../../shared/protocols/email/PtlAllRemove";
export default async function (call: ApiCall<ReqAllRemove, ResAllRemove>) {
// TODO
let emailList = (await EmailFun.getAllEmail(call.uid, true)).filter(email => (email.type == 'system' && (!email.prizeData || email.prizeData?.isGet == true || !email.prizeData.prize || email.prizeData.prize.length < 1
|| (email?.dellist?.indexOf(call.uid) == -1 && call.conn.gud && call.conn.gud.cTime <= email.createTime))));
if (emailList.length < 1) return call.error(globalThis.lng.email_2);
call.succ(EmailFun.removeEmail(call.uid, emailList.map(email => email._id)));
}

View File

@ -0,0 +1,10 @@
import { ApiCall } from "tsrpc";
import { EmailFun } from '../../public/email';
import { ReqOpen, ResOpen } from "../../shared/protocols/email/PtlOpen";
export default async function (call: ApiCall<ReqOpen, ResOpen>) {
let list = await EmailFun.getAllEmail(call.uid);
let obj: ResOpen = {};
list.forEach(e => obj[e._id] = e);
call.succ(obj);
}

View File

@ -0,0 +1,9 @@
import { ApiCall } from "tsrpc";
import { EmailFun } from '../../public/email';
import { ReqRead, ResRead } from "../../shared/protocols/email/PtlRead";
export default async function (call: ApiCall<ReqRead, ResRead>) {
// 修改状态为已读
await EmailFun.readEmail(call.uid, call.req._id);
call.succ([]);
}

View File

@ -0,0 +1,20 @@
import { ApiCall } from "tsrpc";
import { EmailFun } from '../../public/email';
import { PlayerFun } from '../../public/player';
import { ReqReceive, ResReceive } from "../../shared/protocols/email/PtlReceive";
export default async function (call: ApiCall<ReqReceive, ResReceive>) {
let email = await EmailFun.getEmail(call.uid, call.req._id);
if (!email) return call.error(globalThis.lng.email_3);
if (!email.prizeData || (email.prizeData.prize && email.prizeData.prize.length < 1)) return call.error(globalThis.lng.email_5);
if (email.prizeData.isGet) return call.error(globalThis.lng.email_4);
let prize = await PlayerFun.sendPrize(call, email.prizeData.prize);
call.succ({
prize: prize,
change: EmailFun.receiveEmail(call.uid, call.req._id)
});
}

View File

@ -0,0 +1,12 @@
import { ApiCall } from "tsrpc";
import { EmailFun } from '../../public/email';
import { ReqRemove, ResRemove } from "../../shared/protocols/email/PtlRemove";
export default async function (call: ApiCall<ReqRemove, ResRemove>) {
let email = await EmailFun.getEmail(call.uid, call.req._id);
if (!email) return call.error(globalThis.lng.email_3);
if (email.prizeData?.isGet == false && email.prizeData?.prize?.length > 0) return call.error(globalThis.lng.email_6);
call.succ(EmailFun.removeEmail(call.uid, call.req._id));
}

View File

@ -0,0 +1,48 @@
import { ApiCall } from "tsrpc";
import { EquipFun } from '../../public/equip';
import { HeroFun } from '../../public/hero';
import { PlayerFun } from '../../public/player';
import { ReqAdjustment, ResAdjustment } from "../../shared/protocols/equip/PtlAdjustment";
import { EquipShared } from '../../shared/public/equip';
import { PublicShared } from '../../shared/public/public';
export default async function (call: ApiCall<ReqAdjustment, ResAdjustment>) {
let equip = await EquipFun.getEquip(call, call.req.equipId);
if (!equip) return call.error('', { code: 0 });
let curLv = equip.adjustment || 0;
if (!G.gc.equipAdjusting[curLv + 1]) return call.error('', { code: -1 });
let addLv = 0;
let allNeed: atn[] = [];
for (let i = 1; i <= call.req.num; i++) {
let conf = G.gc.equipAdjusting[curLv + i];
if (!conf) break;
let isMeet = await PlayerFun.checkNeedIsMeet(call, PublicShared.mergePrize(allNeed.concat(conf.need)), false);
if (!isMeet.isOk) {
if (addLv == 0) {
return call.error('', { code: -104, atn: isMeet.atn });
} else {
break;
}
}
addLv++;
allNeed.push(...conf.need);
}
await PlayerFun.cutNeed(call, allNeed);
await EquipFun.changeEquipAttr(call, equip, { adjustment: curLv + addLv });
if (equip.wearaId) {
let hero = await HeroFun.getHero(call, equip.wearaId);
if (hero) {
let wearData = hero.equip || {};
wearData[G.gc.equip[equip.equipId].type] = EquipShared.fmtEquip(equip);
await HeroFun.changeHeroAttr(call, hero, { equip: wearData });
}
}
call.succ({});
}

View File

@ -0,0 +1,37 @@
import { ApiCall } from "tsrpc";
import { RedisCollections2 } from '../../module/redis';
import { ReqGetList, ResGetList } from "../../shared/protocols/equip/PtlGetList";
export default async function (call: ApiCall<ReqGetList, ResGetList>) {
let list: ResGetList['list'] = {};
let kvList: k_v<RedisCollections2['equip']> = {};
let arrList = await G.mongodb.collection('equip').find({ uid: call.uid }).toArray();
let equipCon = G.gc.equip
let color = {}
let maxequiplv = 0
arrList.forEach(v => {
let d = G.mongodb.conversionIdObj(v);
kvList[G.formatRedisKey(d._id)] = d;
list[d._id] = d;
if (v.lv > maxequiplv) maxequiplv = v.lv
if (!color[equipCon[v.equipId].colour]) color[equipCon[v.equipId].colour] = 0
color[equipCon[v.equipId].colour] += 1
});
// 记录玩家最大等级,注册任务用
await G.mongodb.collection('playerInfo', 'usertasklog').updateOne({ uid: call.conn.uid, type: 'usertasklog' },
{ $set: { maxequiplv: maxequiplv, equipcolor: color } }, { upsert: true })
G.redis.set('equip', call.uid, kvList);
let recLshd = await G.mongodb.collection('playerInfo', 'lshd_equip').findOne({ uid: call.conn.uid, type: 'lshd_equip' });
let { uid, _id, type, ...equips } = (recLshd || {});
call.conn.lshd.equip = equips || {};
call.succ({
list: list,
lshd: equips || {}
});
}

View File

@ -0,0 +1,52 @@
import { ApiCall } from "tsrpc";
import { Wjjl } from '../../module/collection_wjjl';
import { EquipFun } from '../../public/equip';
import { HeroFun } from '../../public/hero';
import { PlayerFun } from '../../public/player';
import { ReqLvUp, ResLvUp } from "../../shared/protocols/equip/PtlLvUp";
import { ServiceType } from '../../shared/protocols/serviceProto';
import { EquipShared } from '../../shared/public/equip';
import { PublicShared } from '../../shared/public/public';
import { HongDianChange } from "../hongdian/fun";
export default async function (call: ApiCall<ReqLvUp, ResLvUp, ServiceType>) {
let equip = await EquipFun.getEquip(call, call.req.equipId);
if (!equip) return call.error(globalThis.lng.equip_1);
if (equip.lv >= call.conn.gud.lv * 2) return call.error(globalThis.lng.equip_2);
let addLv = 0;
let allNeed: atn[] = [];
for (let i = 1; i <= call.req.upLv; i++) {
if (equip.lv + i > call.conn.gud.lv * 2) break;
let need = EquipShared.getEquipLvUpNeed({ lv: equip.lv + i });
let isMeet = await PlayerFun.checkNeedIsMeet(call, PublicShared.mergePrize(allNeed.concat(need)), false);
if (!isMeet.isOk) {
if (addLv == 0) {
return call.error('', { code: -104, atn: isMeet.atn });
} else {
break;
}
}
addLv++;
allNeed = allNeed.concat(need);
}
await PlayerFun.cutNeed(call, allNeed);
await EquipFun.changeEquipAttr(call, equip, { lv: equip.lv + addLv });
Wjjl.setVal(call.uid, 'equip_qh_lv', equip.lv);
if (equip.wearaId) {
let hero = await HeroFun.getHero(call, equip.wearaId);
if (hero) {
let wearData = hero.equip || {};
wearData[G.gc.equip[equip.equipId].type] = EquipShared.fmtEquip(equip);
await HeroFun.changeHeroAttr(call, hero, { equip: wearData });
}
}
HongDianChange.sendChangeKey(call.uid, ['taskhd', 'huodonghd']);
call.succ({ lv: equip.lv, addlv: addLv });
}

View File

@ -0,0 +1,68 @@
import { ApiCall } from "tsrpc";
import { Wjjl } from '../../module/collection_wjjl';
import { EquipFun } from '../../public/equip';
import { HeroFun } from '../../public/hero';
import { PlayerFun } from '../../public/player';
import { ReqOneKeyLvUp, ResOneKeyLvUp } from "../../shared/protocols/equip/PtlOneKeyLvUp";
import { ServiceType } from '../../shared/protocols/serviceProto';
import { EquipShared } from '../../shared/public/equip';
import { PublicShared } from '../../shared/public/public';
import { HongDianChange } from "../hongdian/fun";
export default async function (call: ApiCall<ReqOneKeyLvUp, ResOneKeyLvUp, ServiceType>) {
let hero = await HeroFun.getHero(call, call.req.heroId);
if (!hero) return call.errorCode(-4);
if (hero.lv < G.gc.herocom.equipOpenLv) return call.errorCode(0);
if (Object.values(hero.equip || {}).filter(v => v != '').length < 1) return call.errorCode(-1);
// let res = EquipShared.getQuickLvUpNeed(hero.equip, call.conn.gud.lv)
// let {posLvUp, allNeed, log} = res
let allNeed:atn[] = [];
let posLvUp = {};
// 获取装备数量
let _equip = {}
Object.keys(hero.equip).forEach( x => {
if(hero.equip[x]) _equip[x] = EquipShared.getFmtEquipLvUp(x, hero.equip)
})
for (let i = 1; i <= 10 * Object.keys(_equip).length; i++) {
let meet: boolean[] = [];
// 排序,取等级最低的装备升级
let _sortPos = Object.keys(_equip).sort((a, b) => _equip[a] - _equip[b])
const pos = _sortPos[0]
// const pos = _sortPos[index];
if (!hero.equip[pos]) continue;
let equipLv = _equip[pos]
if (equipLv + 1 > call.conn.gud.lv * 2) continue;
let need:atn[] = EquipShared.getEquipLvUpNeed({ lv: equipLv + 1 });
let countNeed = PublicShared.mergePrize(allNeed.concat(need));
if ((await PlayerFun.checkNeedIsMeet(call, countNeed, false)).isOk == false) {
continue;
}
meet.push(true);
allNeed = allNeed.concat(need);
if (!posLvUp[pos]) posLvUp[pos] = 0;
posLvUp[pos]++;
_equip[pos]++;
if (!meet.includes(true)) break;
}
if (allNeed.length < 1) return call.errorCode(-104);
await PlayerFun.cutNeed(call, allNeed);
let log = {};
for (let pos in posLvUp) {
let equip = EquipShared.fmtEquip(hero.equip[pos]);
let _lv = equip.lv + posLvUp[pos];
await EquipFun.changeEquipAttr(call, equip, { lv: _lv });
hero.equip[pos] = EquipShared.fmtEquip(equip);
Wjjl.setVal(call.uid, 'equip_qh_lv', _lv);
log[pos] = _lv;
}
await HeroFun.changeHeroAttr(call, hero, { equip: hero.equip });
HongDianChange.sendChangeKey(call.uid, ['taskhd', 'huodonghd']);
call.succ({ posLvUp: posLvUp, log: log, allNeed});
}

View File

@ -0,0 +1,22 @@
import { ApiCall } from "tsrpc";
import { EquipFun } from '../../public/equip';
import { HeroFun } from '../../public/hero';
import { ReqOneKeyTakeOff, ResOneKeyTakeOff } from "../../shared/protocols/equip/PtlOneKeyTakeOff";
import { EquipShared } from '../../shared/public/equip';
export default async function (call: ApiCall<ReqOneKeyTakeOff, ResOneKeyTakeOff>) {
let hero = await HeroFun.getHero(call, call.req.h_id);
if (!hero) return call.errorCode(-1);
let obj = hero.equip || {};
let equips = Object.values(obj).filter(s => !!s).map(s => EquipShared.fmtEquip(s));
if (equips.length > 0) {
for (let equip of equips) {
await EquipFun.changeEquipAttr(call, equip, { wearaId: '' }, false);
}
await HeroFun.changeHeroAttr(call, hero, { equip: {} });
}
call.succ({});
}

View File

@ -0,0 +1,58 @@
import { ApiCall } from "tsrpc";
import { EquipFun } from '../../public/equip';
import { HeroFun } from '../../public/hero';
import { ReqOneKeyWear, ResOneKeyWear } from "../../shared/protocols/equip/PtlOneKeyWear";
import { ServiceType } from '../../shared/protocols/serviceProto';
import { EquipShared } from '../../shared/public/equip';
export default async function (call: ApiCall<ReqOneKeyWear, ResOneKeyWear, ServiceType>) {
let hero = await HeroFun.getHero(call, call.req.heroId);
if (!hero) return call.error(globalThis.lng.equip_3);
if (hero.lv < G.gc.herocom.equipOpenLv) return call.error(`英雄${G.gc.herocom.equipOpenLv}级开启`);
let wearNum = 0;
let wearData = hero.equip || {};
let equipList = await G.redis.get('equip', call.conn.uid) || {};
let allEquip = Object.values(equipList);
let heroIds = Object.values(call.conn.gud.heroPos).filter(i=>!!i)
for (let pos = 1; pos < 5; pos++) {
let posEquip = wearData[pos] || '';
let curEquip = EquipShared.fmtEquip(posEquip);
let curEquipConf = G.gc.equip[curEquip.equipId];
let wearEquip = allEquip.filter(e => {
let conf = G.gc.equip[e.equipId];
if (!posEquip) {
return (!e.wearaId || !heroIds.includes(e.wearaId)) && conf.type == pos;
} else {
return (!e.wearaId || !heroIds.includes(e.wearaId)) && conf.type == pos && (
conf.colour > curEquipConf.colour
|| (conf.colour > curEquipConf.colour && e.lv > curEquip.lv)
|| (conf.colour > curEquipConf.colour && e.lv > curEquip.lv && e.star > curEquip.star));
}
}).sort((a, b) => {
if (G.gc.equip[a.equipId].colour != G.gc.equip[b.equipId].colour) {
return G.gc.equip[b.equipId].colour - G.gc.equip[a.equipId].colour;
} else if (a.lv != b.lv) {
return b.lv - a.lv;
} else {
return b.star - a.star;
}
})[0];
if (!wearEquip) continue;
if (posEquip) {
await EquipFun.changeEquipAttr(call, equipList[G.formatRedisKey(EquipShared.fmtEquip(posEquip)._id)], { wearaId: '' }, false);
}
await EquipFun.changeEquipAttr(call, wearEquip, { wearaId: hero._id });
wearNum++;
wearData[pos] = EquipShared.fmtEquip(wearEquip);
}
if (wearNum > 0) {
await HeroFun.changeHeroAttr(call, hero, { equip: wearData });
}
call.succ({});
}

Some files were not shown because too many files have changed in this diff Show More