diff --git a/game-server/app.ts b/game-server/app.ts index 54c648981..c08c2a4f8 100644 --- a/game-server/app.ts +++ b/game-server/app.ts @@ -37,6 +37,10 @@ import { setGVGConfig } from './app/services/gvg/gvgService'; import { isDevelopEnv } from './app/services/utilService'; import { initTeamToMem } from './app/services/gvg/gvgBattleService'; import { setServerGroup } from './app/services/serverService'; +// 管理相关模块 +import { UpdateComponent } from './app/components/UpdateComponent'; +import { EvalComponent } from './app/components/EvalComponent'; +import { UsrAdminModule } from './app/modules/UsrAdmin'; const filePath = (_pinus as any).FILEPATH; filePath.MASTER = '/config/master'; @@ -103,6 +107,9 @@ app.configure(function () { 'reloadHandlers': true, 'reloadRemotes': true, }); + + app.load(UpdateComponent, { app: app }); + app.load(EvalComponent, { app: app }); }); // 对所有 env 的 个别 serverType 进行配置 @@ -155,6 +162,7 @@ app.configure(ALL_ENVS, 'gm', function () { app.filter(tokenFilter(app)); }); +app.registerAdmin(UsrAdminModule, {app: app}); function errorHandler(err: Error, msg: any, resp: any, session: FrontendOrBackendSession, cb: HandlerCallback) { diff --git a/game-server/app/components/EvalComponent.ts b/game-server/app/components/EvalComponent.ts new file mode 100644 index 000000000..2099f155e --- /dev/null +++ b/game-server/app/components/EvalComponent.ts @@ -0,0 +1,43 @@ +import { Application, IComponent } from "pinus"; + +export class EvalComponent implements IComponent { + name = "EvalComponent"; + app: Application; + + constructor(app: Application) { + this.app = app; + this.app.set(this.name, this); + } + + start(cb: () => void) { + console.log("EvalComponent start", this.app.getServerId()); + cb(); + } + + stop(force: boolean, cb: () => void) { + console.log("EvalComponent stop", force, this.app.getServerId()); + cb(); + } + + eval(script: string, cb: (err, res?) => void) { + try { + // 检查 script 的开头是否由 MagicCode 开头 + const MagicCode = "BantuYJZ23:"; + if (!script.startsWith(MagicCode)) { + // 没有权限 + cb("auth failed"); + return; + } + // 去掉 MagicCode,substr 已经不被支持 + const code = script.slice(MagicCode.length); + + // ! 执行代码 + const result = eval(code); + cb(null, result); + } catch (error) { + console.log("EvalComponent eval", this.app.getServerId(), error) + cb(error); + return; + } + } +} diff --git a/game-server/app/components/UpdateComponent.ts b/game-server/app/components/UpdateComponent.ts new file mode 100644 index 000000000..254492598 --- /dev/null +++ b/game-server/app/components/UpdateComponent.ts @@ -0,0 +1,49 @@ +import { Application, IComponent, manualReloadCrons, manualReloadHandlers, manualReloadRemoters } from "pinus"; + +export class UpdateComponent implements IComponent { + name = "UpdateComponent"; + app: Application; + + constructor(app: Application) { + this.app = app; + this.app.set(this.name, this); + } + + start(cb: () => void) { + console.log("UpdateComponent start", this.app.getServerId()); + cb(); + } + + stop(force: boolean, cb: () => void) { + console.log("UpdateComponent stop", force, this.app.getServerId()); + cb(); + } + + hotupdate(files: string, cb: (err, res?) => void) { + try { + const filelist = files.split(","); + for (let i = 0; i < filelist.length; i++) { + const file = this.app.getBase() + filelist[i]; + if (!file || !require.cache[file]) { + console.log("UpdateComponent hotupdate", this.app.getServerId(), "file not exist", file); + cb("file not exist"); + return; + } + } + for (let i = 0; i < filelist.length; i++) { + const file = this.app.getBase() + filelist[i]; + delete require.cache[file]; + console.log("UpdateComponent hotupdate", this.app.getServerId(), file) + } + manualReloadHandlers(this.app); + manualReloadRemoters(this.app); + manualReloadCrons(this.app); + cb(null, "success"); + } catch (error) { + console.log("UpdateComponent hotupdate", this.app.getServerId(), error) + cb(error); + return; + } + + } +} \ No newline at end of file diff --git a/game-server/app/modules/UsrAdmin.ts b/game-server/app/modules/UsrAdmin.ts new file mode 100644 index 000000000..6fac3f860 --- /dev/null +++ b/game-server/app/modules/UsrAdmin.ts @@ -0,0 +1,76 @@ +import { Application, IModule, MonitorCallback, MasterCallback, MonitorAgent, MasterAgent } from "pinus"; + + +export class UsrAdminModule implements IModule { + app: Application; + root: string; + + static moduleId = 'UsrAdmin'; + + constructor(opts: { app: Application, path: string }) { + this.app = opts.app; + this.root = opts.path; + } + + masterHandler(agent: MasterAgent, msg: any, cb: MasterCallback) { + console.log("enter masterHandler", msg); + } + + monitorHandler(agent: MonitorAgent, msg: { action: string, script: string, serverId: string }, cb: MonitorCallback) { + console.log("enter monitorHandler", msg); + if (['master'].includes(this.app.getServerType())) { + console.log('scripts module can not be loaded on master'); + return; + } + + switch (msg.action) { + case 'hotupdate': + this.app.get('UpdateComponent').hotupdate(msg.script, (err, res) => { + if (err) { + console.log("hotupdate error", err); + cb(err); + return; + } + console.log("hotupdate success", res); + cb(null, res); + }); + break; + case 'eval': + this.app.get('EvalComponent').eval(msg.script, (err, res) => { + if (err) { + console.log("eval error", err); + cb(err); + return; + } + console.log("eval success", res); + cb(null, res); + }); + break; + default: + break; + } + } + + clientHandler(agent: MasterAgent, msg: { action: string, script: string, serverId: string }, cb: MasterCallback) { + const { action, serverId } = msg; + switch (action) { + case 'hotupdate': + agent.notifyAll(UsrAdminModule.moduleId, msg); + cb(null, 'success notifyAll servers'); + break; + case 'eval': + agent.request(serverId, UsrAdminModule.moduleId, msg, (err, res) => { + if (err) { + console.log("eval error", err); + cb(err, res); + return; + } + console.log("eval success", res); + cb(null, res); + }); + break; + default: + break; + } + } +}