HJ_Server/src/global.ts
2023-12-22 14:33:49 +08:00

266 lines
8.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import EventEmitter from 'events';
import { existsSync, readdirSync, readFileSync, writeFileSync } from 'fs';
import { parse } from 'json5';
import * as mathjs from 'mathjs';
import { join, resolve } from 'path';
import { argv, env } from 'process';
import { HttpServer, WsClient, WsServer } from 'tsrpc';
import { ServiceType as ServiceTypeCross } from './cross/protocols/serviceProto';
import { MyEvent } from './event';
import { addListener, gEventType } from './globalListener';
import localConfig from './localConfig';
import { ServiceType as ServiceTypeHttp } from './monopoly/protocols/serviceProto';
import { SchedulerManage } from './public/scheduler/scheduler';
import { _mongodb } from './setMongodb';
import { redisJsonFun } from './setRedis';
import { ResGetList } from './shared/protocols/pay/PtlGetList';
import { ServiceType as ServiceTypeWs } from './shared/protocols/serviceProto';
import { PublicShared } from './shared/public/public';
import { clusterRunOnce } from './clusterUtils';
import * as ramda from 'ramda'
import Redis from 'ioredis';
declare global {
var G: _G & Partial<{
/**仅类型映射 */
otherBuff: any;
}>;
var mathJs: typeof mathjs;
var R
type k_v<T> = { [k: string]: T; };
type atn = { a: string, t: string | number | any, n: number; colour?: number; shiwuBuff?: any; };
/**类型过滤 */
type FilterConditionally<Source, Condition> = Pick<
Source,
{
[K in keyof Source]: Source[K] extends Condition ? K : never
}[keyof Source]
>;
interface Array<T> {
/**数组随机取值 */
random(): T;
/**取一个数组在当前数组中的交集 */
intersection(other: T[]): T[];
/**取一个数组在当前数组中的差集 */
difference(other: T[]): T[];
/**数组是否存在重复元素 */
isDuplication(): boolean;
/**打乱数组 */
shuffle(): this;
}
interface Uint8Array {
/**是否已经加密 */
encrypt: boolean;
}
}
class _G {
/**游戏配置 */
gc: Partial<_gcType> = {};
/**服务启动时命令行参数解析 */
argv: {
/**服务器类型 */
serverType: 'msg' | 'cross',
/**服务器日志模式 error | debug*/
logModel: string;
} = {
serverType: 'msg',
logModel: 'error'
};
/**当前时间对象 */
date: Date;
/**当前时间戳 */
time: number;
// /**serverType==msg时记录所有玩家的uid, 剔除全局变量转移到redis */
// uids?: string[];
/**服务器配置 */
config: Partial<typeof localConfig> & k_v<any> = {};
/**当serverType==msg时才会启动的http */
http?: HttpServer<ServiceTypeHttp>;
/**当serverType!=cross时才会启动的ws */
server?: WsServer<ServiceTypeWs>;
/**当serverType==cross时才会启动的ws */
serverCross?: WsServer<ServiceTypeCross>;
/**当serverType==msg时才会启动的跨服连接 */
clientCross?: WsClient<ServiceTypeCross>;
/**redis连接对象 */
redis: redisJsonFun;
/**ioredis连接对象 */
ioredis: Redis;
/**mongodb连接对象 */
mongodb: _mongodb;
/**crossmongodb连接对象 */
crossmongodb: _mongodb;
// mongodbClient: any;
/**所有玩家的充值记录 */
allPlayerPayLog: k_v<ResGetList['list']> = {};
private event = new EventEmitter();
/**映射开服时间 */
get openTime() {
return this.config.openTime;
}
get getEvent(): new (...args: any) => {
on(type: any, callback: any, caller?: any): any;
once(type: any, callback: any): any;
off(type: any, callback: any, caller?: any): void;
emit(type: any, ...args: any[]): void;
debug(): any;
removeAllListeners(type?:any):void;
} {
return MyEvent as any;
}
constructor(argArr: string[]) {
let configJson = existsSync(resolve(__dirname, 'config.json')) ? JSON.parse(readFileSync(resolve(__dirname, 'config.json'), 'utf-8')) : {};
for (let index = 0; index < argArr.length; index++) {
let arg = argArr[index];
if (arg == '-serverType') {
this.argv.serverType = argArr[index + 1] as any;
} else if (arg == '-logModel') {
this.argv.logModel = argArr[index + 1];
}
}
Object.assign(localConfig, configJson);
this.config = localConfig;
if (env.SERVER_ID) {
this.config.serverId = ~~env.SERVER_ID;
}
this.initGc();
}
on<T extends keyof gEventType>(event: T, callback: gEventType[T]) {
return this.event.on(event, (...args)=>{
try{
callback.call(this, ...args);
}catch(e){
console.error(e)
}
});
}
once<T extends keyof gEventType>(event: T, callback: gEventType[T]) {
return this.event.once(event, callback);
}
emit<T extends keyof gEventType>(event: T, ...args: Parameters<gEventType[T]>) {
return this.event.emit(event, ...args);
}
/**加载json */
initGc() {
let jsonPath = join(__dirname, 'json');
readdirSync(jsonPath).forEach(file => {
if (file.endsWith('.json5')) {
let json = parse(readFileSync(join(jsonPath, file), 'utf-8'));
this.gc[file.split('.')[0]] = json;
} else if(file.endsWith('.json')) {
let json = JSON.parse(readFileSync(join(jsonPath, file), 'utf-8'));
this.gc[file.split('.')[0]] = json;
}
});
}
/**更新时间 每秒刷新 */
updateTime() {
if (G.config.debug && G.config.time) {
try {
let conf = JSON.parse(readFileSync(resolve(__dirname, 'config.json'), 'utf-8'));
this.date = new Date(conf.time);
this.date = new Date(this.date.getTime() + 1000);
this.time = Math.round(this.date.getTime() / 1000);
conf.time = this.date.format('YYYY-MM-DD hh:mm:ss');
// writeFileSync(resolve(__dirname, 'config.json'), JSON.stringify(conf, null, 2));
} catch (error) {
}
} else {
// let date = new Date();
// let time = date.getTime();
// let offset = date.getTimezoneOffset() / 60 + this.config.utc;
// this.date = new Date(time + offset * 3600 * 1000);
this.date = new Date();
this.time = Math.round(this.date.getTime() / 1000);
}
}
/**检查redis路径是否首字符为数字 */
formatRedisKey(key: string) {
let firstStr = key.toString().substring(0, 1);
if (!isNaN(Number(firstStr))) return '_' + key;
return key;
}
/**改写开区时间(外部请求 games/open 改写)*/
set openTime(_opentine) {
try {
let conf = JSON.parse(readFileSync(resolve(__dirname, 'config.json'), 'utf-8'));
G.date = new Date(_opentine);
G.date = new Date(this.date.getTime() + 1000);
conf.openTime = this.date.format('YYYY-MM-DD hh:mm:ss');
// this.openTime = this.date.format('YYYY-MM-DD hh:mm:ss'); // 外部调用时直接改写了,不然会无限重复调用
this.config.openTime = this.date.format('YYYY-MM-DD hh:mm:ss')
// writeFileSync(resolve(__dirname, 'config.json'), JSON.stringify(conf, null, 2));
} catch (error) {
}
}
sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
}
export function ctor() {
globalThis.mathJs = mathjs;
globalThis.G = new _G(argv);
G.updateTime();
globalThis.R = ramda
}
Array.prototype.random = function (this: Array<any>) {
return this[PublicShared.randomNum(0, this.length)];
};
Array.prototype.intersection = function (this: Array<any>, other: Array<any>) {
let a = new Set(this);
let b = new Set(other);
return Array.from(new Set([...a].filter(x => b.has(x))));
};
Array.prototype.difference = function (this: Array<any>, other: Array<any>) {
let a = new Set(this);
let b = new Set(other);
return Array.from(new Set([...a].filter(x => !b.has(x))));
};
Array.prototype.isDuplication = function (this: Array<any>) {
return this.length != [...new Set(this)].length;
};
Array.prototype.shuffle = function (this: Array<any>) {
this.forEach((v, k) => {
let _k = 0 | (Math.random() * (k + 1));
var tmp = this[k];
this[k] = this[_k];
this[_k] = tmp;
});
return this;
}