UNPKG

17.4 kBJavaScriptView Raw
1/**
2 * bootstrap
3 */
4let httpProxy = require('http-proxy');
5let express = require('express');
6let EventEmitter = require('events').EventEmitter;
7EventEmitter.defaultMaxListeners = 0;
8
9//注入通用函数
10require('./util/mixin/base');
11
12// Uncaught exception handler
13process.on('uncaughtException', function(err) {
14 console.error(' Caught exceptio n: ' + err.stack);
15});
16
17let commonFunc = require('./util/commonFunc');
18let getAsnyc = require('./util/async')
19let cache = require('./util/cache')
20let formula = require('./util/formula')
21let Indicator = require('./util/Indicator')
22let updateMgr = require('./util/updateMgr')
23let Collection = require('./util/Collection')
24let config = require('./util/configInterface') //配置文件管理
25let {applyMixins, extendObj, clone} = require('./util/mixin/comm')
26let filelist = require('./util/filelist')
27let iniFile = require(`${process.cwd()}/gameconfig`);
28
29/**
30 * 门面对象
31 */
32class Facade
33{
34 /**
35 * 启动支持反向代理的静态门户网站
36 * @param {String} options.protocol 协议 http/https
37 * @param {Object} options.router 路由 {host: {target,}}
38 * @param {String} options.port 守护端口
39 */
40 static startProxy(options) {
41 // 新建一个代理 Proxy Server 对象
42 var proxy = httpProxy.createProxyServer({});
43 proxy.on('error', function (err, req, res) {
44 res.writeHead(500, {'Content-Type': 'text/plain'});
45 res.end('Something went wrong.');
46 });
47 // 在每次请求中,调用 proxy.web(req, res config) 方法进行请求分发
48 var server = (require(options.protocol||'http')).createServer(function(req, res) {
49 var host = req.headers.host, ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
50 if(options.router[host]) {
51 proxy.web(req, res, { target: options.router[host].target });
52 } else {
53 res.writeHead(200, {'Content-Type': 'text/plain'});
54 res.end('Welcome! visit [wallet.vallnet.cn] for wallet service and [crm.vallnet.cn] for crm service.');
55 }
56 });
57 server.listen(options.port);
58 }
59
60 /**
61 * 添加一个静态内容服务站
62 * @description 相比通过 facade.boot 传入 static 数组而言,该方法能灵活指定协议、地址和端口
63 *
64 * @param {*} protocol 协议 http / https
65 * @param {*} host 主机地址
66 * @param {*} port 主机端口
67 * @param {Object} route 路由设置
68 */
69 static addWebSite(protocol, host, port, route) {
70 let app = express();
71 if(Array.isArray(route)) {
72 route.map(rt => {
73 if(typeof rt.dir == 'string') {
74 app.use(rt.path, express.static(rt.dir));
75 } else if(typeof rt.dir == 'function') {
76 let router = express.Router();
77 router.request(path, async (req, res) => {
78 try {
79 res.send(await rt.dir(req.query));
80 } catch(e) {
81 res.end();
82 console.error(e);
83 }
84 });
85 app.use("/", router);
86 }
87 });
88 }
89
90 let httpObj = require(protocol);
91 let hrv = httpObj.createServer(app);
92 hrv.listen(port, host, () => {
93 console.log(`静态网站服务在 ${protocol}://${host}:${port} 上准备就绪`);
94 });
95 }
96
97 /**
98 * 系统主引导流程
99 * @param {*} options 启动参数数组
100 */
101 static async boot(options, startup) {
102 this.serverType = {};
103 this.serverTypeMapping = {};
104
105 //自动从指定目录载入系统定义和用户自定义的核心类
106 let corelist = filelist.mapPackagePath(`${__dirname}/./core`);
107 if(this.$addition) {
108 corelist = corelist.concat(filelist.mapPath('app/core'));
109 }
110 corelist.map(srv => {
111 let srvObj = require(srv.path);
112 this.serverType[srv.name.split('.')[0]] = srvObj; //节点类列表
113 srvObj.mapping.map(key => {
114 this.serverTypeMapping[key] = srvObj; //节点类映射列表,每个节点类可能映射多个条目
115 });
116 });
117
118 //主程序启动,提供包括Http、Socket、路由解析等服务
119 let core = this.FactoryOfCore(!!options?options.env:{});
120 extendObj(core.options, options);
121
122 if(this.$addition) { //加载用户自定义模块
123 await core.loadModel();
124 }
125
126 //将用户自定义表添加到自动加载列表中
127 if(options.loading) {
128 options.loading.map(table=>{
129 core.addLoadingModel(table);
130 });
131 }
132
133 let app = express();
134 //启用跨域访问
135 app.all('*',function (req, res, next) {
136 // 允许应用的跨域访问
137 res.header('Access-Control-Allow-Origin', '*');
138 res.header('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild');
139 res.header('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS');
140
141 if (req.method == 'OPTIONS') {
142 //让options请求快速返回
143 res.send(200);
144 } else {
145 next();
146 }
147 });
148
149 //region 添加POST模式下的body解析器
150 let bodyParser = require('body-parser');
151 app.use(bodyParser.urlencoded({extended: true}))
152 app.use(bodyParser.json());
153 //endregion
154
155 //载入持久化层数据,开放通讯服务端口,加载所有控制器相关的路由、中间件设定
156 await core.Start(app);
157
158 if(options.static) {
159 for(let [route, path] of options.static) {
160 if(typeof path == 'string') {
161 core.static(route, path);
162 } else if(typeof path == 'function') {
163 core.addRouter(route, path);
164 }
165 }
166 }
167
168 //下发404 必须在控制器路由、静态资源路由全部加载之后设定
169 app.use(function(req, res, next) {
170 res.status(404).send('Sorry cant find the path!');
171 });
172
173 //捕获并下发错误码 必须放在最后!
174 app.use(function(err, req, res, next) {
175 console.error(err.stack);
176 res.status(500).send('Something broke!');
177 });
178
179 if(typeof startup == 'function') {
180 await startup(core);
181 }
182
183 return core;
184 }
185
186 /**
187 * 创建核心类实例的类工厂
188 * @param {*} env 运行环境
189 * @returns {CoreOfBase}
190 */
191 static FactoryOfCore(env) {
192 let ret = null;
193 if(!!this.serverTypeMapping[env.serverType] && !!this.ini.servers[env.serverType] && !!this.ini.servers[env.serverType][env["serverId"]]) {
194 ret = new this.serverTypeMapping[env.serverType](this.tools.extend(
195 {serverType: env.serverType, serverId: env.serverId},
196 this.ini.servers["Index"][1],
197 this.ini.servers[env.serverType][env["serverId"]]
198 ));
199 } else {
200 throw new Error(`无法识别的服务器类型和编号 ${env.serverType}.${env.serverId}`);
201 }
202 return ret;
203 }
204
205 /**
206 * 读取加载附加自定义模块标志
207 */
208 static get addition() {
209 return this.$addition || false;
210 }
211 /**
212 * 设置加载附加自定义模块标志,链式操作
213 */
214 static set addition(val) {
215 this.$addition = val;
216 return this;
217 }
218
219 /**
220 * 建立关键字和核心类之间的映射关系,用于建立核心对象的类工厂中
221 * @param {Array} pair 形如[keyword, CoreClassName]的数组
222 *
223 * @note 核心类的静态mapping方法规定了服务器类型映射关系,但可以随时调用registerServer补充新的映射关系
224 */
225 static registerServer(pair) {
226 if(!!pair) { //带参数表示补录映射关系
227 this.serverTypeMapping[pair[0]] = pair[1];
228 }
229 }
230
231 /**
232 * 获取当前运行环境的节点对象
233 */
234 static get current(){
235 return this.$current;
236 }
237 /**
238 * 设置当前运行环境的节点对象
239 */
240 static set current(val){
241 this.$current = val;
242 return this.$current;
243 }
244
245 //region 内置的节点类
246 static get CoreOfBase() {
247 return require('./core/CoreOfBase');
248 }
249 static get CoreOfIndex() {
250 return require('./core/CoreOfIndex');
251 }
252 static get CoreOfLogic() {
253 return require('./core/CoreOfLogic');
254 }
255 //endregion
256
257 //region 可用于继承的基础类
258
259 /**
260 * 集合管理类
261 */
262 static get Collection(){
263 return Collection;
264 }
265
266 /**
267 * 基础控制器类
268 */
269 static get Control(){
270 return require('./util/baseCtl');
271 }
272 /**
273 * 基础服务类
274 */
275 static get Service(){
276 return require('./util/baseService');
277 }
278 /**
279 * 基础助手类
280 */
281 static get Assistant(){
282 return require('./model/baseAssistant');
283 }
284
285 /**
286 * 背包管理基础类
287 */
288 static get Assistants() {
289 return {
290 Pocket: require('./model/assistant/item'),
291 }
292 }
293
294 /**
295 * 指向原生基础实体类
296 */
297 static get BaseEntity(){
298 return require('./model/BaseEntity');
299 }
300
301 /**
302 * 指向原生基础用户类
303 */
304 static get BaseUserEntity() {
305 return require('./model/entity/BaseUserEntity');
306 }
307
308 /**
309 * 指向原生基础联盟类
310 */
311 static get BaseAllyObject() {
312 return require('./model/entity/BaseAllyObject');
313 }
314
315 /**
316 * 指向原生基础日志类
317 */
318 static get BaseLogEntity() {
319 return require('./model/entity/BuyLogEntity');
320 }
321
322 //endregion
323
324 /**
325 * 返回全部助手类
326 */
327 static get assistants() {
328 if(!this.$assistants){
329 this.$assistants = {};
330 filelist.mapPackagePath(`${__dirname}/./model/assistant`).map(mod=>{
331 let mid = mod.name.split('.')[0];
332 this.$assistants[mid] = require(mod.path);
333 });
334 if(this.$addition) {
335 filelist.mapPath('app/model/assistant').map(mod=>{
336 let mid = mod.name.split('.')[0];
337 this.$assistants[mid] = require(mod.path);
338 });
339 }
340 }
341 return this.$assistants;
342 }
343 /**
344 * 返回全部表映射类
345 */
346 static get models() {
347 if(!this.$models){
348 //载入全部ORM模块
349 this.$models = {};
350 filelist.mapPackagePath(`${__dirname}/./model/table`).map(mod=>{
351 let mid = mod.name.split('.')[0];
352 this.$models[mid] = require(mod.path)[mid];
353 });
354 if(this.$addition) {
355 filelist.mapPath('app/model/table').map(mod=>{
356 let mid = mod.name.split('.')[0];
357 this.$models[mid] = require(mod.path)[mid];
358 });
359 }
360 }
361 return this.$models;
362 }
363 /**
364 * 返回全部 ORM 映射类
365 */
366 static get entities(){
367 if(!this.$entities) {
368 this.$entities = {};
369
370 //载入原生Entity模块
371 filelist.mapPackagePath(`${__dirname}/./model/entity`).map(mod=>{
372 let mid = mod.name.split('.')[0];
373 this.$entities[mid] = require(mod.path);
374 });
375 //将 UserEntity AllyObject 也指向原生模块
376 this.$entities.UserEntity = require('./model/entity/BaseUserEntity'); //指向原生定义的角色类
377 this.$entities.AllyObject = require('./model/entity/BaseAllyObject'); //指向原生定义的联盟类
378
379 if(this.$addition) {
380 //载入用户自定义Entity模块,如果用户有重载 UserEntity AllyObject 则自动覆盖之前的设置
381 filelist.mapPath('app/model/entity').map(mod=>{
382 let mid = mod.name.split('.')[0];
383 this.$entities[mid] = require(mod.path);
384 });
385 }
386 }
387 return this.$entities;
388 }
389
390 /**
391 * 工具箱
392 */
393 static get tools() {
394 return {
395 mixin: applyMixins, //混合对象属性函数
396 extend: extendObj, //扩展对象函数
397 clone: clone, //深度复刻对象函数
398 Sequelize: require('sequelize'), //sequelize类
399 seqconn: require('./util/sequel'), //mysql连接器
400 maintain: require('./util/maintain'), //执行数据维护任务
401 formula: formula, //表达式计算
402 cache: cache, //缓存管理
403 Indicator: Indicator, //标志位管理
404 updateMgr: updateMgr, //定时刷新器
405 getAsnyc: getAsnyc,
406 Lock: require('./util/Lock')
407 };
408 }
409
410 /**
411 * 所有自动化执行类的列表
412 */
413 static get autoExec() {
414 if(!this.$autoExec){
415 this.$autoExec = {};
416 filelist.mapPackagePath(`${__dirname}/./util/autoExec`).map(mod=>{
417 let mid = mod.name.split('.')[0];
418 this.$autoExec[mid] = require(mod.path);
419 });
420 if(this.$addition) {
421 filelist.mapPath('app/util/autoExec').map(mod=>{
422 let mid = mod.name.split('.')[0];
423 this.$autoExec[mid] = require(mod.path);
424 });
425 }
426 }
427 return this.$autoExec;
428 }
429
430 /**
431 * 返回运行环境配置文件
432 */
433 static get ini(){
434 return iniFile;
435 }
436 /**
437 * 业务配置文件管理
438 */
439 static get config(){
440 return config;
441 }
442 /**
443 * 获取常用函数集
444 */
445 static get util(){
446 return commonFunc;
447 }
448 /**
449 * 获取常用枚举集
450 */
451 static get const(){
452 if(!this.$constList) {
453 //加载核心常量定义
454 this.$constList = require( './define/comm');
455 //加载扩展常量定义
456 for(let fl of filelist.mapPackagePath(`${__dirname}/./define`)){
457 let id = fl.name.split('.')[0];
458 if(id != 'comm'){
459 let n = require(fl.path);
460 extendObj(this.$constList, n);
461 }
462 }
463
464 if(this.$addition) {
465 //加载用户自定义常量定义
466 for(let fl of filelist.mapPath('app/define')){
467 let n = require(fl.path);
468 extendObj(this.$constList, n);
469 }
470 }
471
472 this.$constList.AddConditionType = (name, val) => {
473 this.$constList.em_Condition_Type[name] = val;
474 };
475 this.$constList.AddResType = (name, val) => {
476 this.$constList.ResType[name] = val;
477 };
478 }
479
480 return this.$constList;
481 }
482}
483
484class Util
485{
486 static get BonusObject() {
487 return require('./util/comm/BonusObject');
488 }
489
490 static get EffectManager() {
491 return require('./util/comm/EffectManager');
492 }
493
494 static get EffectObject() {
495 return require('./util/comm/EffectObject');
496 }
497
498 static get TollgateObject() {
499 return require('./util/tollgate/TollgateObject');
500 }
501
502 static get OperationInfo() {
503 return require('./util/tollgate/OperationInfo');
504 }
505
506 static get PotentialClientItem() {
507 return require('./util/potential/PetClientItem');
508 }
509
510 static get BattleManager() {
511 return require('./util/battle/BattleManager');
512 }
513
514 static get BaseBattleParam() {
515 let {BaseBattleParam} = require('./util/battle/util');
516 return BaseBattleParam;
517 }
518
519 static get BattleHero() {
520 let {BattleHero} = require('./util/battle/hero');
521 return BattleHero;
522 }
523
524 static get LargeNumberCalculator() {
525 return require('./util/comm/LargeNumberCalculator');
526 }
527
528 static get EventData() {
529 let {EventData} = require('./util/comm/EventData');
530 return EventData;
531 }
532}
533
534Facade.Util = Util;
535
536exports = module.exports = Facade;