├── .gitignore ├── README.md ├── game-server ├── .vscode │ └── launch.json ├── app.ts ├── app │ ├── base │ │ └── SingleBase.ts │ ├── dao │ │ ├── DaoManager.ts │ │ ├── controller │ │ │ ├── DaoAbsController.ts │ │ │ └── user │ │ │ │ └── DaoUserAccountInfo.ts │ │ ├── logger │ │ │ └── DaoLogger.ts │ │ └── module │ │ │ ├── DaoExecute.ts │ │ │ ├── DaoResult.ts │ │ │ └── user │ │ │ └── DbUserAccountInfo.ts │ ├── define │ │ ├── DefDaoTable.ts │ │ └── DefServerType.ts │ ├── protocol │ │ ├── AppProtocol.ts │ │ └── ProConnect.ts │ ├── redis │ │ ├── RedisManager.ts │ │ ├── controller │ │ │ └── RedisAbsController.ts │ │ └── logger │ │ │ └── RedisLogger.ts │ ├── servers │ │ └── connector │ │ │ ├── controller │ │ │ └── ConnectVerifyController.ts │ │ │ ├── handler │ │ │ └── ConnectHandler.ts │ │ │ ├── logger │ │ │ └── ConnectLogger.ts │ │ │ └── remote │ │ │ └── ConnectRemoter.ts │ └── utils │ │ ├── CryptoUtil.ts │ │ └── DateTimeUtil.ts ├── config │ ├── adminServer.ts │ ├── adminUser.ts │ ├── clientProtos.ts │ ├── dictionary.ts │ ├── log4js.ts │ ├── master.ts │ ├── mysql.ts │ ├── redis.ts │ ├── serverProtos.ts │ └── servers.ts ├── package-lock.json ├── package.json ├── preload.ts └── tsconfig.json ├── npm-install.bat ├── npm-install.sh ├── readme.md ├── shared ├── server.crt └── server.key └── web-server ├── app.js ├── bin ├── component.bat └── component.sh ├── package.json └── public ├── css └── base.css ├── image ├── logo.png └── sp.png ├── index.html └── js └── lib ├── build └── build.js ├── component.json └── local └── boot ├── component.json └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | game-server/node_modules 2 | game-server/dist -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # guide -------------------------------------------------------------------------------- /game-server/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // 使用 IntelliSense 了解相关属性。 3 | // 悬停以查看现有属性的描述。 4 | // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "request": "launch", 10 | "name": "LaunchMaster", 11 | "autoAttachChildProcesses": true, 12 | "program": "${workspaceFolder}/dist/app.js", 13 | "outFiles": [ 14 | "${workspaceFolder}/**/*.js" 15 | ] 16 | }, 17 | { 18 | "type": "node", 19 | "request": "attach", 20 | "name": "Attach to Connector", 21 | "address": "127.0.0.1", 22 | "port": 10001, 23 | "localRoot": "${workspaceFolder}", 24 | "remoteRoot": "${workspaceFolder}" 25 | } 26 | 27 | ] 28 | } -------------------------------------------------------------------------------- /game-server/app.ts: -------------------------------------------------------------------------------- 1 | import { pinus } from 'pinus'; 2 | import { preload } from './preload'; 3 | import _pinus = require('pinus'); 4 | import RedisManager from './app/redis/RedisManager'; 5 | import DaoManager from './app/dao/DaoManager'; 6 | 7 | const filePath = (_pinus as any).FILEPATH; 8 | filePath.MASTER = '/config/master'; 9 | filePath.SERVER = '/config/servers'; 10 | filePath.CRON = '/config/crons'; 11 | filePath.LOG = '/config/log4js'; 12 | filePath.SERVER_PROTOS = '/config/serverProtos'; 13 | filePath.CLIENT_PROTOS = '/config/clientProtos'; 14 | filePath.MASTER_HA = '/config/masterha'; 15 | filePath.LIFECYCLE = '/lifecycle'; 16 | filePath.SERVER_DIR = '/app/servers/'; 17 | filePath.CONFIG_DIR = '/config'; 18 | 19 | const adminfilePath = _pinus.DEFAULT_ADMIN_PATH; 20 | adminfilePath.ADMIN_FILENAME = 'adminUser'; 21 | adminfilePath.ADMIN_USER = 'config/adminUser'; 22 | /** 23 | * 替换全局Promise 24 | * 自动解析sourcemap 25 | * 捕获全局错误 26 | */ 27 | preload(); 28 | 29 | /** 30 | * Init app for client. 31 | */ 32 | let app = pinus.createApp(); 33 | app.set('name', 'guide'); 34 | 35 | // app configuration 36 | app.configure('production|development', 'connector', function () { 37 | app.set('connectorConfig', 38 | { 39 | connector: pinus.connectors.hybridconnector, 40 | heartbeat: 3, 41 | useDict: true, 42 | useProtobuf: true 43 | }); 44 | }); 45 | 46 | //redis配置 47 | app.loadConfig('redis',app.getBase() + '/config/redis'); 48 | //mysql配置 49 | app.loadConfig('mysql',app.getBase() + '/config/mysql') 50 | 51 | app.configure('production|development', "master|connector", function () { 52 | //redis管理初始化 53 | new RedisManager(app); 54 | //mysql管理初始化 55 | new DaoManager(app); 56 | }); 57 | 58 | // start app 59 | app.start(); 60 | 61 | -------------------------------------------------------------------------------- /game-server/app/base/SingleBase.ts: -------------------------------------------------------------------------------- 1 | export abstract class SingleBase{ 2 | protected static mInstance:SingleBase = null; 3 | protected static instance(C:new() => T):T{ 4 | if(this.mInstance === null){ 5 | this.mInstance = new C(); 6 | } 7 | return this.mInstance; 8 | } 9 | 10 | public constructor(){ 11 | if(SingleBase.mInstance !== null){ 12 | throw '实例已创建,不允许再次创建'; 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /game-server/app/dao/DaoManager.ts: -------------------------------------------------------------------------------- 1 | import { Application } from "pinus"; 2 | import DaoAbsController from "./controller/DaoAbsController"; 3 | import { DaoUserAccountInfo } from "./controller/user/DaoUserAccountInfo"; 4 | import { DbUserAccountInfo } from "./module/user/DbUserAccountInfo"; 5 | var mysql = require('mysql'); 6 | 7 | export default class DaoManager{ 8 | private mPool:any = null; 9 | 10 | public constructor(app){ 11 | this.init(app); 12 | } 13 | 14 | public init(app:Application){ 15 | let mysqlConfig = app.get('mysql'); 16 | this.mPool = mysql.createPool({ 17 | host: mysqlConfig.host, 18 | user: mysqlConfig.user, 19 | password: mysqlConfig.password, 20 | database: mysqlConfig.database, 21 | port: mysqlConfig.port || '3306', 22 | charset : 'utf8mb4', 23 | }); 24 | DaoAbsController.init(this.mPool); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /game-server/app/dao/controller/DaoAbsController.ts: -------------------------------------------------------------------------------- 1 | import { DaoExecute } from "../module/DaoExecute"; 2 | import { DaoResult } from "../module/DaoResult"; 3 | import { DaoLogger } from "../logger/DaoLogger"; 4 | 5 | export default abstract class DaoAbsController { 6 | protected static mPool: any = null; 7 | 8 | public static init(pool) { 9 | this.mPool = pool; 10 | } 11 | 12 | public static async execute(fun:(execute:DaoExecute)=>Promise>):Promise> { 13 | try { 14 | let exe = new DaoExecute(this.mPool); 15 | let connect = await exe.startConnection(); 16 | if(connect == false){ 17 | return DaoResult.fail('get connection fail'); 18 | } 19 | let result = await fun(exe); 20 | await exe.stopConnection(); 21 | return result; 22 | } catch (error) { 23 | DaoLogger.error(error); 24 | return DaoResult.fail('dao error',error); 25 | } 26 | } 27 | 28 | public static async executeTransaction(fun:(execute:DaoExecute)=>Promise>):Promise> { 29 | let exe:DaoExecute = null; 30 | try { 31 | exe = new DaoExecute(this.mPool); 32 | let connect = await exe.startConnection(); 33 | if(connect == false){ 34 | return DaoResult.fail('get connection fail'); 35 | } 36 | let isOk = await exe.beginTransaction(); 37 | if(isOk == false){ 38 | return DaoResult.fail('db Transaction fail'); 39 | } 40 | let result = await fun(exe); 41 | isOk = false; 42 | if(result && result.isSucceed){ 43 | isOk = await exe.commit(); 44 | } 45 | if(!isOk){ 46 | await exe.rollback(); 47 | } 48 | await exe.stopConnection(); 49 | return result; 50 | } catch (error) { 51 | if(exe && exe.isTransaction()){ 52 | await exe.rollback(); 53 | } 54 | DaoLogger.error(error); 55 | return DaoResult.fail('dao error',error); 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /game-server/app/dao/controller/user/DaoUserAccountInfo.ts: -------------------------------------------------------------------------------- 1 | import DaoAbsController from "../DaoAbsController"; 2 | import { DaoExecute } from "../../module/DaoExecute"; 3 | import { DaoResult } from "../../module/DaoResult"; 4 | import { DbUserAccountInfo } from "../../module/user/DbUserAccountInfo"; 5 | import { DefDaoTable } from "../../../define/DefDaoTable"; 6 | 7 | export class DaoUserAccountInfo extends DaoAbsController{ 8 | /** 9 | * 注册 10 | * @param arg 11 | */ 12 | public static async register(arg:DbUserAccountInfo):Promise>{ 13 | return await this.execute(async (exe:DaoExecute):Promise>=>{ 14 | let sql = exe.format('insert into %s(permission,robot,account,password,nickname,gender,head_url,login_date,login_ip,register_date,register_ip) ' 15 | + 'values(?,?,?,?,?,?,?,?,?,?,?)',DefDaoTable.USER_ACCOUNT_INFO); 16 | let param = [arg.permission,arg.robot,arg.account,arg.password,arg.nickname,arg.gender,arg.head_url,arg.login_date,arg.login_ip,arg.register_date,arg.register_ip]; 17 | let res = await exe.insert(sql,param); 18 | if(res.affectedRows<=0){ 19 | return DaoResult.fail('注册失败'); 20 | } 21 | sql = exe.format('select * from %s where uid=?',DefDaoTable.USER_ACCOUNT_INFO); 22 | param = [res.insertId]; 23 | let user = await exe.select(sql,param); 24 | if(user.length <= 0){ 25 | return DaoResult.fail('注册失败'); 26 | } 27 | return DaoResult.succeed(user[0]); 28 | }); 29 | } 30 | /** 31 | * 登录 32 | * @param account 33 | * @param password 34 | */ 35 | public static async login(account:string,password:string):Promise>{ 36 | return await this.execute(async (exe:DaoExecute):Promise>=>{ 37 | let sql = exe.format('select * from %s where account=? and password=?',DefDaoTable.USER_ACCOUNT_INFO); 38 | let param = [account,password]; 39 | let res = await exe.select(sql,param); 40 | if(res.length <= 0){ 41 | return DaoResult.fail('账号或密码错误'); 42 | } 43 | return DaoResult.succeed(res[0]); 44 | }); 45 | } 46 | /** 47 | * 查询用户信息 48 | * @param uid 49 | */ 50 | public static async queryAccountInfo(uid:number):Promise>{ 51 | return await this.execute(async (exe:DaoExecute):Promise>=>{ 52 | let sql = exe.format('select * from %s where uid=? ',DefDaoTable.USER_ACCOUNT_INFO); 53 | let param = [uid]; 54 | let res = await exe.select(sql,param); 55 | if(res.length <= 0){ 56 | return DaoResult.fail('操作失败'); 57 | } 58 | return DaoResult.succeed(res[0]); 59 | }); 60 | } 61 | /** 62 | * 更新用户信息 63 | * @param uid 64 | * @param data 65 | */ 66 | public static async updateAccountInfo(uid:number,data:{[key:string]:any}):Promise>{ 67 | return await this.execute(async (exe:DaoExecute):Promise>=>{ 68 | let sql = exe.format('update %s set ? where uid=?',DefDaoTable.USER_ACCOUNT_INFO); 69 | let param = [data,uid]; 70 | let res = await exe.update(sql,param); 71 | if(res.affectedRows <= 0){ 72 | return DaoResult.fail('操作失败'); 73 | } 74 | return DaoResult.succeed(true); 75 | }); 76 | } 77 | } -------------------------------------------------------------------------------- /game-server/app/dao/logger/DaoLogger.ts: -------------------------------------------------------------------------------- 1 | import { getLogger } from 'pinus-logger'; 2 | import * as path from 'path'; 3 | let logger = getLogger('dao', path.basename(__filename)); 4 | 5 | export class DaoLogger{ 6 | 7 | public static trace(message: any, ...args: any[]): void{ 8 | logger.trace(message,args); 9 | } 10 | 11 | public static debug(message: any, ...args: any[]): void{ 12 | logger.debug(message,args); 13 | } 14 | 15 | public static info(message: any, ...args: any[]): void{ 16 | logger.info(message,args); 17 | } 18 | 19 | public static warn(message: any, ...args: any[]): void{ 20 | logger.warn(message,args); 21 | } 22 | 23 | public static error(message: any, ...args: any[]): void{ 24 | logger.error(message,args); 25 | } 26 | 27 | public static fatal(message: any, ...args: any[]): void{ 28 | logger.fatal(message,args); 29 | } 30 | } -------------------------------------------------------------------------------- /game-server/app/dao/module/DaoExecute.ts: -------------------------------------------------------------------------------- 1 | let util = require('util'); 2 | export class DaoPack { 3 | fieldCount: number; 4 | affectedRows: number; 5 | insertId: number; 6 | serverStatus: number; 7 | warningCount: number; 8 | message: string; 9 | protocol41: boolean; 10 | changedRows: number 11 | } 12 | 13 | export class DaoExecute { 14 | private mPool: any = null; 15 | private mConn: any = null; 16 | private mIsTransaction: boolean = false; 17 | public constructor(pool: any) { 18 | this.mPool = pool; 19 | } 20 | 21 | public async startConnection(): Promise { 22 | return new Promise((resolve, reject) => { 23 | if (this.mPool == null) { 24 | reject('pool is null'); 25 | return; 26 | } 27 | this.mPool.getConnection((err, conn) => { 28 | if (err) { 29 | reject(err); 30 | } else { 31 | this.mConn = conn; 32 | resolve(true); 33 | } 34 | }); 35 | }); 36 | } 37 | 38 | public isTransaction(): boolean { 39 | return this.mIsTransaction; 40 | } 41 | 42 | public async beginTransaction(): Promise { 43 | return new Promise((resolve, reject) => { 44 | this.mConn.beginTransaction((err) => { 45 | if (err) { 46 | reject(err); 47 | } else { 48 | this.mIsTransaction = true; 49 | resolve(true); 50 | } 51 | }); 52 | }) 53 | } 54 | 55 | public async commit(): Promise { 56 | return new Promise((resolve, reject) => { 57 | this.mConn.commit((err, info) => { 58 | if (err) { 59 | reject(err); 60 | } else { 61 | resolve(true); 62 | } 63 | }); 64 | }); 65 | } 66 | 67 | public async rollback(): Promise { 68 | return new Promise((resolve, reject) => { 69 | this.mConn.rollback((a, b) => { 70 | resolve(true); 71 | }); 72 | }); 73 | } 74 | 75 | public async stopConnection(): Promise { 76 | if (this.mConn) { 77 | this.mConn.release(); 78 | return true; 79 | } 80 | return false 81 | } 82 | 83 | protected async query(sql: string, params?: Array): Promise { 84 | return new Promise((resolve, reject) => { 85 | this.mConn.query(sql, params || [], (err, res) => { 86 | if (err) { 87 | reject(err); 88 | } else { 89 | resolve(res); 90 | } 91 | }); 92 | }); 93 | } 94 | 95 | public format(format:string,...arg:any):string{ 96 | return util.format(format,arg); 97 | } 98 | 99 | public async select(sql: string, params?: Array): Promise> { 100 | return await this.query(sql, params); 101 | } 102 | public async update(sql: string, params?: Array): Promise { 103 | return await this.query(sql, params); 104 | } 105 | public async insert(sql: string, params?: Array): Promise { 106 | return await this.query(sql, params); 107 | } 108 | public async delete(sql: string, params?: Array): Promise { 109 | return await this.query(sql, params); 110 | } 111 | } -------------------------------------------------------------------------------- /game-server/app/dao/module/DaoResult.ts: -------------------------------------------------------------------------------- 1 | 2 | export class DaoResult{ 3 | public isSucceed:boolean = false; 4 | public data:T = null; 5 | public describe:string = ''; 6 | public error:any = null; 7 | public static succeed(result:T):DaoResult{ 8 | let obj = new DaoResult(); 9 | obj.isSucceed = true; 10 | obj.data = result; 11 | return obj; 12 | } 13 | public static fail(describe:string,err?:any):DaoResult{ 14 | let obj = new DaoResult(); 15 | obj.isSucceed = false; 16 | obj.describe = describe; 17 | obj.error = err; 18 | return obj; 19 | } 20 | } -------------------------------------------------------------------------------- /game-server/app/dao/module/user/DbUserAccountInfo.ts: -------------------------------------------------------------------------------- 1 | 2 | export class DbUserAccountInfo{ 3 | public uid:number = 0; 4 | public permission:number = 0; 5 | public robot:number = 0; 6 | public account:string = ''; 7 | public password:string = ''; 8 | public nickname:string = ''; 9 | public gender:number = 0; 10 | public head_url:string = ''; 11 | public login_date:string = ''; 12 | public login_ip:string = ''; 13 | public register_date:string = ''; 14 | public register_ip:string = ''; 15 | } -------------------------------------------------------------------------------- /game-server/app/define/DefDaoTable.ts: -------------------------------------------------------------------------------- 1 | 2 | export enum DefDaoTable{ 3 | USER_ACCOUNT_INFO = 'user_account_info', //账号信息表 4 | } -------------------------------------------------------------------------------- /game-server/app/define/DefServerType.ts: -------------------------------------------------------------------------------- 1 | 2 | export enum DefServerType{ 3 | CONNECTOR = 'connector', 4 | } -------------------------------------------------------------------------------- /game-server/app/protocol/AppProtocol.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | /** 4 | * 请求结果返回码 5 | */ 6 | export enum ProResultCode { 7 | CODE_NULL = 0, //未定义 8 | CODE_SUCCEED = 200, //请求成功 9 | CODE_FAIL = 500, //请求失败 10 | } 11 | 12 | /** 13 | * 初始化接口 14 | */ 15 | export interface IProInitializer { 16 | /** 17 | * 子类必须实现该方法对所有类成员变量初始化 18 | * number初始化为0 19 | * string初始化为'' 20 | * T 初始化为new T (T为对象) 21 | * Array 初始化为 [new T] (T为对象或基本数据类型) 22 | */ 23 | initialization():void; 24 | } 25 | 26 | /** 27 | * 所有请求数据的基类 28 | */ 29 | export abstract class ProRequest implements IProInitializer { 30 | constructor() { 31 | this.initialization(); 32 | } 33 | /** 34 | * 子类必须实现该方法对所有类成员变量初始化 35 | * number初始化为0 36 | * string初始化为'' 37 | * T 初始化为new T (T为对象) 38 | * Array 初始化为 [new T] (T为对象或基本数据类型) 39 | */ 40 | public abstract initialization():void; 41 | } 42 | /** 43 | * 所有请求结果的基类 44 | */ 45 | export abstract class ProResult implements IProInitializer { 46 | public code: ProResultCode = ProResultCode.CODE_NULL; 47 | public describe: string = ''; 48 | constructor() { 49 | this.initialization(); 50 | } 51 | /** 52 | * 子类必须实现该方法对所有类成员变量初始化 53 | * number初始化为0, 54 | * string初始化为'', 55 | * T 初始化为new T (T为对象), 56 | * Array 初始化为 [new T] (T为对象或基本数据类型), 57 | */ 58 | public abstract initialization():void; 59 | } 60 | 61 | export class AppProtocol { 62 | /** 63 | * 构造请求结果 64 | * @param C 65 | * @param sussced 66 | * @param des 67 | */ 68 | public static result(C: new () => T, sussced: boolean, des?: string): T { 69 | let res = new C; 70 | res.code = sussced ? ProResultCode.CODE_SUCCEED : ProResultCode.CODE_FAIL; 71 | if (des !== undefined) { 72 | res.describe = des; 73 | } 74 | return res; 75 | } 76 | /** 77 | * 构造请求 78 | * @param C 79 | */ 80 | public static request(C: new () => T): T { 81 | return new C; 82 | } 83 | 84 | /** 85 | * 将客户端发来的消息转换为对应的对象 86 | * @param arg 转换的对象 87 | * @param msg 消息对象 88 | */ 89 | public static convert(arg:T, msg: any): T { 90 | if (typeof arg !== 'object') return null; 91 | if (typeof msg !== 'object') return null; 92 | if (Array.isArray(arg)) { 93 | let arry = this.copyArray(arg,msg); 94 | if(arry == null) return null; 95 | arg = arry; 96 | return arg; 97 | } 98 | for (let name in arg) { 99 | if (msg.hasOwnProperty(name)) { 100 | //属性成员是否是数组 101 | if (Array.isArray(arg[name])) { 102 | let arry = this.copyArray(arg[name],msg[name]) 103 | if(arry == null) return null; 104 | arg[name] = arry; 105 | //属性成员是否是object 106 | } else if (typeof arg[name] === 'object') { 107 | arg[name] = this.convert(arg[name], msg[name]); 108 | if (arg[name] === null) return null;//转换对象失败 109 | } else { 110 | if (typeof arg[name] !== typeof msg[name]) return null;//数据类型校验 111 | arg[name] = msg[name]; 112 | } 113 | } 114 | //客户端消息缺少属性 115 | else if (!(arg[name] instanceof Function)) { 116 | return null; 117 | } 118 | } 119 | return arg; 120 | } 121 | 122 | protected static copyArray(arg, msg) { 123 | if (Array.isArray(msg) === false) return null;//客户端数据不是数组 124 | let argArry = >(arg); 125 | let msgArry = >msg; 126 | if (argArry.length <= 0) return null;//数组定义必须初始化添加一个元素 127 | let arry = []; 128 | if (typeof argArry[0] == 'object') { 129 | for (let i = 0; i < msgArry.length; i++) { 130 | let item = this.clone(argArry[0]); 131 | item = this.convert(item, msgArry[i]); 132 | if (item === null) return null;//转换对象失败 133 | arry.push(item); 134 | } 135 | } else { 136 | for (let i = 0; i < msgArry.length; i++) { 137 | if (typeof argArry[0] !== typeof msgArry[i]) return null;//数据类型校验 138 | arry.push(msgArry[i]); 139 | } 140 | } 141 | return arry; 142 | } 143 | 144 | protected static clone(obj: any) { 145 | if (typeof obj !== 'object') throw "克隆必须是对象"; 146 | let temp = null; 147 | if (obj instanceof Array) { 148 | temp = obj.concat(); 149 | } else if (obj instanceof Function) { 150 | //函数是共享的是无所谓的,js也没有什么办法可以在定义后再修改函数内容 151 | temp = obj; 152 | } else { 153 | temp = new Object(); 154 | for (let item in obj) { 155 | let val = obj[item]; 156 | temp[item] = typeof val == 'object' ? this.clone(val) : val; //这里也没有判断是否为函数,因为对于函数,我们将它和一般值一样处理 157 | } 158 | } 159 | return temp; 160 | } 161 | /** 162 | * 将source和dest相同的字段复制给dest 163 | * @param dest 164 | * @param source 165 | */ 166 | public static copy(dest:object,source:object){ 167 | for (const key in dest) { 168 | if (source.hasOwnProperty(key)) { 169 | dest[key] = source[key]; 170 | } 171 | } 172 | } 173 | } -------------------------------------------------------------------------------- /game-server/app/protocol/ProConnect.ts: -------------------------------------------------------------------------------- 1 | import { ProRequest, ProResult } from "./AppProtocol"; 2 | 3 | export namespace ProConnect{ 4 | export namespace Login{ 5 | export const RPC_REQUEST_ID = 'connector.ConnectHandler.onLogin'; 6 | export class Request extends ProRequest{ 7 | public account:string; 8 | public password:string; 9 | public initialization(){ 10 | this.account = ''; 11 | this.password = ''; 12 | } 13 | } 14 | export class Result extends ProResult{ 15 | public uid:number; 16 | public permission:number; 17 | public account:string; 18 | public password:string; 19 | public nickname:string; 20 | public gender:number; 21 | public head_url:string; 22 | public initialization(){ 23 | this.uid = 0; 24 | this.permission = 0; 25 | this.account = ''; 26 | this.password = ''; 27 | this.nickname = ''; 28 | this.gender = 0; 29 | this.head_url = ''; 30 | } 31 | } 32 | } 33 | 34 | export namespace Register{ 35 | export const RPC_REQUEST_ID = 'connector.ConnectHandler.onRegister'; 36 | export class Request extends ProRequest{ 37 | public account:string; 38 | public password:string; 39 | public nickname:string; 40 | public gender:number; 41 | public head_url:string; 42 | public initialization(){ 43 | this.account = ''; 44 | this.password = ''; 45 | this.nickname = ''; 46 | this.gender = 0; 47 | this.head_url = ''; 48 | } 49 | } 50 | export class Result extends ProResult{ 51 | public uid:number; 52 | public permission:number; 53 | public account:string; 54 | public password:string; 55 | public nickname:string; 56 | public gender:number; 57 | public head_url:string; 58 | public initialization(){ 59 | this.uid = 0; 60 | this.permission = 0; 61 | this.account = ''; 62 | this.password = ''; 63 | this.nickname = ''; 64 | this.gender = 0; 65 | this.head_url = ''; 66 | } 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /game-server/app/redis/RedisManager.ts: -------------------------------------------------------------------------------- 1 | import { Application } from "pinus"; 2 | import { RedisLogger } from "./logger/RedisLogger"; 3 | import { RedisAbsController } from "./controller/RedisAbsController"; 4 | let redis = require('redis'); 5 | let Redlock = require('redlock'); 6 | export default class RedisManager{ 7 | private mApp:Application = null; 8 | private mClient:any; 9 | private mRedlock:any; 10 | public constructor(app){ 11 | this.init(app); 12 | } 13 | 14 | public init(app:Application){ 15 | this.mApp = app; 16 | let redisConfig = app.get('redis'); 17 | this.mClient = redis.createClient(redisConfig.port,redisConfig.host); 18 | 19 | this.mClient.on("error",this.onRedisError.bind(this)) 20 | 21 | //清除数据 22 | if(this.mApp.isMaster()){ 23 | this.mClient.flushall(); 24 | } 25 | 26 | //创建Redis锁 27 | this.mRedlock = new Redlock(// you should have one client for each independent redis node 28 | // or cluster 29 | [this.mClient], 30 | { 31 | // the expected clock drift; for more details 32 | // see http://redis.io/topics/distlock 33 | driftFactor: 0.01, // time in ms 34 | // the max number of times Redlock will attempt 35 | // to lock a resource before erroring 36 | retryCount: 10, 37 | // the time in ms between attempts 38 | retryDelay: 200, // time in ms 39 | // the max time in ms randomly added to retries 40 | // to improve performance under high contention 41 | // see https://www.awsarchitectureblog.com/2015/03/backoff.html 42 | retryJitter: 200 // time in ms 43 | } 44 | ); 45 | 46 | this.mRedlock.on('clientError', function(err) { 47 | RedisLogger.error('A redis error has occurred:', err); 48 | }); 49 | 50 | RedisAbsController.init(this.mClient,this.mRedlock); 51 | } 52 | 53 | public onRedisError(error){ 54 | RedisLogger.error(error); 55 | } 56 | } -------------------------------------------------------------------------------- /game-server/app/redis/controller/RedisAbsController.ts: -------------------------------------------------------------------------------- 1 | import { RedisLogger } from "../logger/RedisLogger"; 2 | 3 | export abstract class RedisAbsController{ 4 | protected static mClient:any = null; 5 | protected static mRedlock:any = null; 6 | 7 | public static init(client,redlock){ 8 | RedisAbsController.mClient = client; 9 | RedisAbsController.mRedlock = redlock; 10 | } 11 | 12 | /** 13 | * 设置键值超时时间 14 | * @param key 15 | * @param ttl 秒 16 | */ 17 | public static async expire(key:string|number,ttl:number):Promise{ 18 | try{ 19 | this.mClient.expire(key,ttl); 20 | }catch(err){ 21 | RedisLogger.error(err); 22 | } 23 | } 24 | 25 | /** 26 | * hash,添加或更新 27 | * @param name 28 | * @param key 29 | * @param value 30 | */ 31 | protected static async hset(name:string,key:string|number,value:any):Promise{ 32 | return new Promise( (resolve, reject) => { 33 | try { 34 | this.mClient.hset(name,key,JSON.stringify(value),(err, res) =>{ 35 | if(err){ 36 | reject(err); 37 | }else{ 38 | resolve(JSON.parse(res)); 39 | } 40 | }); 41 | } catch (error) { 42 | reject(error); 43 | } 44 | }); 45 | } 46 | /** 47 | * hash,获取值 48 | * @param name 49 | * @param key 50 | */ 51 | protected static async hget(name:string,key:string|number):Promise{ 52 | return new Promise( (resolve, reject) => { 53 | try { 54 | this.mClient.hget(name,key,(err, res) =>{ 55 | if(err){ 56 | reject(err); 57 | }else{ 58 | resolve(JSON.parse(res)); 59 | } 60 | }); 61 | } catch (error) { 62 | reject(error); 63 | } 64 | }); 65 | } 66 | /** 67 | * hash,删除 68 | * @param name 69 | * @param key 70 | * @returns 返回删除数目 71 | */ 72 | protected static async hdel(name:string,key:string|number):Promise{ 73 | return new Promise( (resolve, reject) => { 74 | try { 75 | this.mClient.hdel(name,key,(err, res) =>{ 76 | if(err){ 77 | reject(err); 78 | }else{ 79 | resolve(res); 80 | } 81 | }); 82 | } catch (error) { 83 | reject(error); 84 | } 85 | }); 86 | } 87 | /** 88 | * hash,key是否存在 89 | * @param name 90 | * @param key 91 | * @returns 返回存在数目 92 | */ 93 | protected static async hexists(name:string,key:string|number):Promise{ 94 | return new Promise( (resolve, reject) => { 95 | try { 96 | this.mClient.hexists(name,key,(err, res) =>{ 97 | if(err){ 98 | reject(err); 99 | }else{ 100 | resolve(res); 101 | } 102 | }); 103 | } catch (error) { 104 | reject(error); 105 | } 106 | }); 107 | } 108 | /** 109 | * hash,获取所有key 110 | * @param name 111 | * @returns 返回key列表 112 | */ 113 | protected static async hkeys(name:string):Promise{ 114 | return new Promise( (resolve, reject) => { 115 | try { 116 | this.mClient.hkeys(name,(err, res) =>{ 117 | if(err){ 118 | reject(err); 119 | }else{ 120 | resolve(res); 121 | } 122 | }); 123 | } catch (error) { 124 | reject(error); 125 | } 126 | }); 127 | } 128 | /** 129 | * 130 | * @param name 131 | */ 132 | protected static async hvals(name:string):Promise{ 133 | return new Promise( (resolve, reject) => { 134 | try { 135 | this.mClient.hvals(name,(err, res) =>{ 136 | if(err){ 137 | reject(err); 138 | }else{ 139 | resolve(res); 140 | } 141 | }); 142 | } catch (error) { 143 | reject(error); 144 | } 145 | }); 146 | } 147 | } -------------------------------------------------------------------------------- /game-server/app/redis/logger/RedisLogger.ts: -------------------------------------------------------------------------------- 1 | import { getLogger } from 'pinus-logger'; 2 | import * as path from 'path'; 3 | let logger = getLogger('redis', path.basename(__filename)); 4 | 5 | export class RedisLogger{ 6 | 7 | public static trace(message: any, ...args: any[]): void{ 8 | logger.trace(message,args); 9 | } 10 | 11 | public static debug(message: any, ...args: any[]): void{ 12 | logger.debug(message,args); 13 | } 14 | 15 | public static info(message: any, ...args: any[]): void{ 16 | logger.info(message,args); 17 | } 18 | 19 | public static warn(message: any, ...args: any[]): void{ 20 | logger.warn(message,args); 21 | } 22 | 23 | public static error(message: any, ...args: any[]): void{ 24 | logger.error(message,args); 25 | } 26 | 27 | public static fatal(message: any, ...args: any[]): void{ 28 | logger.fatal(message,args); 29 | } 30 | } -------------------------------------------------------------------------------- /game-server/app/servers/connector/controller/ConnectVerifyController.ts: -------------------------------------------------------------------------------- 1 | import { Application, ChannelService, FrontendSession } from "pinus"; 2 | import { SingleBase } from "../../../base/SingleBase"; 3 | import { DaoUserAccountInfo } from "../../../dao/controller/user/DaoUserAccountInfo"; 4 | import { DbUserAccountInfo } from "../../../dao/module/user/DbUserAccountInfo"; 5 | import { AppProtocol } from "../../../protocol/AppProtocol"; 6 | import { ProConnect } from "../../../protocol/ProConnect"; 7 | 8 | export default class ConnectVerifyController extends SingleBase{ 9 | private mApp:Application = null; 10 | private mChannelService:ChannelService = null; 11 | 12 | public static getInstance():ConnectVerifyController{ 13 | return this.instance(ConnectVerifyController); 14 | } 15 | 16 | public setApplication(app:Application){ 17 | this.mApp = app; 18 | this.mChannelService = app.get('channelService'); 19 | } 20 | 21 | public async onLogin(session:FrontendSession,req:ProConnect.Login.Request):Promise{ 22 | let dbResult = await DaoUserAccountInfo.login(req.account,req.password); 23 | if(dbResult.isSucceed == false){ 24 | return AppProtocol.result(ProConnect.Login.Result,false,dbResult.describe); 25 | } 26 | let res = AppProtocol.result(ProConnect.Login.Result,true); 27 | AppProtocol.copy(res,dbResult.data); 28 | return AppProtocol.result(ProConnect.Login.Result,true); 29 | } 30 | 31 | public async onRegister(session:FrontendSession,req:ProConnect.Register.Request):Promise{ 32 | let data = new DbUserAccountInfo; 33 | data.account = req.account; 34 | data.password = req.password; 35 | data.nickname = req.nickname; 36 | data.gender = req.gender; 37 | data.head_url = req.head_url; 38 | let dbResult = await DaoUserAccountInfo.register(data); 39 | if(dbResult.isSucceed == false){ 40 | return AppProtocol.result(ProConnect.Register.Result,false,dbResult.describe); 41 | } 42 | let res = AppProtocol.result(ProConnect.Register.Result,true); 43 | AppProtocol.copy(res,dbResult.data); 44 | return AppProtocol.result(ProConnect.Register.Result,true); 45 | } 46 | } -------------------------------------------------------------------------------- /game-server/app/servers/connector/handler/ConnectHandler.ts: -------------------------------------------------------------------------------- 1 | import { Application, FrontendSession } from 'pinus'; 2 | import { DefServerType } from '../../../define/DefServerType'; 3 | import { AppProtocol } from '../../../protocol/AppProtocol'; 4 | import { ProConnect } from '../../../protocol/ProConnect'; 5 | import ConnectVerifyController from '../controller/ConnectVerifyController'; 6 | import { ConnectLogger } from '../logger/ConnectLogger'; 7 | 8 | export default function (app: Application) { 9 | return new ConnectHandler(app); 10 | } 11 | 12 | export class ConnectHandler { 13 | constructor(private app: Application) { 14 | if(app.getServerType() == DefServerType.CONNECTOR){ 15 | ConnectVerifyController.getInstance().setApplication(app); 16 | } 17 | } 18 | async onLogin(msg: any, session: FrontendSession) { 19 | try { 20 | let req = AppProtocol.convert(new ProConnect.Login.Request,msg); 21 | if(req == null){ 22 | return AppProtocol.result(ProConnect.Login.Result,false,'请求参数错误'); 23 | } 24 | return await ConnectVerifyController.getInstance().onLogin(session,req); 25 | } catch (error) { 26 | ConnectLogger.error(error); 27 | } 28 | return AppProtocol.result(ProConnect.Login.Result,false,'请求失败'); 29 | } 30 | 31 | async onRegister(msg: any, session: FrontendSession) { 32 | try { 33 | let req = AppProtocol.convert(new ProConnect.Register.Request,msg); 34 | if(req == null){ 35 | return AppProtocol.result(ProConnect.Register.Result,false,'请求参数错误'); 36 | } 37 | return await ConnectVerifyController.getInstance().onRegister(session,req); 38 | } catch (error) { 39 | ConnectLogger.error(error); 40 | } 41 | return AppProtocol.result(ProConnect.Register.Result,false,'请求失败'); 42 | } 43 | 44 | 45 | } -------------------------------------------------------------------------------- /game-server/app/servers/connector/logger/ConnectLogger.ts: -------------------------------------------------------------------------------- 1 | import { getLogger } from 'pinus-logger'; 2 | import * as path from 'path'; 3 | let logger = getLogger('connector', path.basename(__filename)); 4 | 5 | export class ConnectLogger{ 6 | 7 | public static trace(message: any, ...args: any[]): void{ 8 | logger.trace(message,args); 9 | } 10 | 11 | public static debug(message: any, ...args: any[]): void{ 12 | logger.debug(message,args); 13 | } 14 | 15 | public static info(message: any, ...args: any[]): void{ 16 | logger.info(message,args); 17 | } 18 | 19 | public static warn(message: any, ...args: any[]): void{ 20 | logger.warn(message,args); 21 | } 22 | 23 | public static error(message: any, ...args: any[]): void{ 24 | logger.error(message,args); 25 | } 26 | 27 | public static fatal(message: any, ...args: any[]): void{ 28 | logger.fatal(message,args); 29 | } 30 | } -------------------------------------------------------------------------------- /game-server/app/servers/connector/remote/ConnectRemoter.ts: -------------------------------------------------------------------------------- 1 | import {Application, RemoterClass, FrontendSession} from 'pinus'; 2 | 3 | export default function (app: Application) { 4 | return new ConnectRemoter(app); 5 | } 6 | 7 | // UserRpc的命名空间自动合并 8 | declare global { 9 | interface UserRpc { 10 | connector: { 11 | // 一次性定义一个类自动合并到UserRpc中 12 | remoter: RemoterClass; 13 | }; 14 | } 15 | } 16 | 17 | 18 | export class ConnectRemoter { 19 | constructor(private app: Application) { 20 | 21 | } 22 | 23 | /** 24 | * 25 | * @param username 26 | * @param password 27 | */ 28 | public async auth(username: string , password: string) { 29 | return true; 30 | } 31 | 32 | // 私有方法不会加入到RPC提示里 33 | private async privateMethod(testarg:string,arg2:number){ 34 | 35 | } 36 | } -------------------------------------------------------------------------------- /game-server/app/utils/CryptoUtil.ts: -------------------------------------------------------------------------------- 1 | const crypto = require('crypto'); 2 | export class CryptoUtil { 3 | //加密密钥 4 | private static readonly ENCRYPT_KEY = '23yOjdk098dj'; 5 | /** 6 | * 获取MD5值 7 | * @param str 8 | */ 9 | public static md5(str: string): string { 10 | const hash = crypto.createHash('md5'); 11 | hash.update(str); 12 | const md5str = hash.digest('hex'); 13 | return md5str; 14 | } 15 | /** 16 | * AES加密 17 | * @param data 18 | */ 19 | public static aesEncrypt(data: string): string { 20 | const cipher = crypto.createCipher('aes-256-cbc', CryptoUtil.ENCRYPT_KEY); 21 | var crypted = cipher.update(data, 'utf8', 'base64'); 22 | crypted += cipher.final('base64'); 23 | return crypted; 24 | } 25 | /** 26 | * AES解密 27 | * @param encrypted 28 | */ 29 | public static aesDecrypt(encrypted: string): string { 30 | const decipher = crypto.createDecipher('aes-256-cbc', CryptoUtil.ENCRYPT_KEY); 31 | var decrypted = decipher.update(encrypted, 'base64', 'utf8'); 32 | decrypted += decipher.final('utf8'); 33 | return decrypted; 34 | } 35 | } -------------------------------------------------------------------------------- /game-server/app/utils/DateTimeUtil.ts: -------------------------------------------------------------------------------- 1 | import moment = require("moment"); 2 | 3 | export default class DateTimeUtil{ 4 | 5 | /** 6 | * 格式化时间 7 | * @param date 8 | * @param format “YYYY-MM-DD HH:mm:ss” 9 | */ 10 | public static format(date:Date,format:string):string 11 | public static format(millisecond:number,format:string):string 12 | public static format(arg:any,format:string):string{ 13 | return moment(arg).format(format); 14 | } 15 | /** 16 | * 获取指定时间的当天起始时间戳 17 | * @param date 18 | * @returns 毫秒时间戳 19 | */ 20 | public static startOfDate(date:Date):number 21 | public static startOfDate(millisecond:number):number 22 | public static startOfDate(arg:any):number{ 23 | return moment(arg).startOf('date').valueOf(); 24 | } 25 | 26 | /** 27 | * 获取指定时间的当天结束时间戳 28 | * @param date 29 | * @returns 毫秒时间戳 30 | */ 31 | public static endOfDate(date:Date):number 32 | public static endOfDate(millisecond:number):number 33 | public static endOfDate(arg:any):number{ 34 | return moment(arg).endOf('date').valueOf(); 35 | } 36 | } -------------------------------------------------------------------------------- /game-server/config/adminServer.ts: -------------------------------------------------------------------------------- 1 | module.exports = [ 2 | { 3 | "type": "connector", 4 | "token": "agarxhqb98rpajloaxn34ga8xrunpagkjwlaw3ruxnpaagl36w4rxn" 5 | }, 6 | ]; -------------------------------------------------------------------------------- /game-server/config/adminUser.ts: -------------------------------------------------------------------------------- 1 | module.exports = [ 2 | { 3 | "id": "user-1", 4 | "username": "admin", 5 | "password": "admin", 6 | "level": 1 7 | }, 8 | 9 | { 10 | "id": "user-2", 11 | "username": "monitor", 12 | "password": "monitor", 13 | "level": 2 14 | }, 15 | 16 | { 17 | "id": "user-3", 18 | "username": "test", 19 | "password": "test", 20 | "level": 2 21 | } 22 | ]; -------------------------------------------------------------------------------- /game-server/config/clientProtos.ts: -------------------------------------------------------------------------------- 1 | module.exports = {} -------------------------------------------------------------------------------- /game-server/config/dictionary.ts: -------------------------------------------------------------------------------- 1 | module.exports = {} -------------------------------------------------------------------------------- /game-server/config/log4js.ts: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "appenders": { 3 | "console": { 4 | "type": "console" 5 | }, 6 | "con-log": { 7 | "type": "file", 8 | "filename": "${opts:base}/logs/con-log-${opts:serverId}.log", 9 | "pattern": "connector", 10 | "maxLogSize": 1048576, 11 | "layout": { 12 | "type": "basic" 13 | }, 14 | "backups": 5 15 | }, 16 | "rpc-log": { 17 | "type": "file", 18 | "filename": "${opts:base}/logs/rpc-log-${opts:serverId}.log", 19 | "maxLogSize": 1048576, 20 | "layout": { 21 | "type": "basic" 22 | }, 23 | "backups": 5 24 | }, 25 | "forward-log": { 26 | "type": "file", 27 | "filename": "${opts:base}/logs/forward-log-${opts:serverId}.log", 28 | "maxLogSize": 1048576, 29 | "layout": { 30 | "type": "basic" 31 | }, 32 | "backups": 5 33 | }, 34 | "rpc-debug": { 35 | "type": "file", 36 | "filename": "${opts:base}/logs/rpc-debug-${opts:serverId}.log", 37 | "maxLogSize": 1048576, 38 | "layout": { 39 | "type": "basic" 40 | }, 41 | "backups": 5 42 | }, 43 | "crash-log": { 44 | "type": "file", 45 | "filename": "${opts:base}/logs/crash.log", 46 | "maxLogSize": 1048576, 47 | "layout": { 48 | "type": "basic" 49 | }, 50 | "backups": 5 51 | }, 52 | "admin-log": { 53 | "type": "file", 54 | "filename": "${opts:base}/logs/admin.log", 55 | "maxLogSize": 1048576, 56 | "layout": { 57 | "type": "basic" 58 | }, 59 | "backups": 5 60 | }, 61 | "pinus": { 62 | "type": "file", 63 | "filename": "${opts:base}/logs/pinus-${opts:serverId}.log", 64 | "maxLogSize": 1048576, 65 | "layout": { 66 | "type": "basic" 67 | }, 68 | "backups": 5 69 | }, 70 | "pinus-admin": { 71 | "type": "file", 72 | "filename": "${opts:base}/logs/pinus-admin.log", 73 | "maxLogSize": 1048576, 74 | "layout": { 75 | "type": "basic" 76 | }, 77 | "backups": 5 78 | }, 79 | "pinus-rpc": { 80 | "type": "file", 81 | "filename": "${opts:base}/logs/pinus-rpc-${opts:serverId}.log", 82 | "maxLogSize": 1048576, 83 | "layout": { 84 | "type": "basic" 85 | }, 86 | "backups": 5 87 | } 88 | }, 89 | "categories": { 90 | "default": { 91 | "appenders": [ 92 | "console", 93 | "pinus" 94 | ], 95 | "level": "debug" 96 | }, 97 | "con-log": { 98 | "appenders": [ 99 | "con-log" 100 | ], 101 | "level": "debug" 102 | }, 103 | "rpc-log": { 104 | "appenders": [ 105 | "rpc-log" 106 | ], 107 | "level": "debug" 108 | }, 109 | "forward-log": { 110 | "appenders": [ 111 | "forward-log" 112 | ], 113 | "level": "debug" 114 | }, 115 | "rpc-debug": { 116 | "appenders": [ 117 | "rpc-debug" 118 | ], 119 | "level": "debug" 120 | }, 121 | "crash-log": { 122 | "appenders": [ 123 | "crash-log" 124 | ], 125 | "level": "debug" 126 | }, 127 | "admin-log": { 128 | "appenders": [ 129 | "admin-log" 130 | ], 131 | "level": "debug" 132 | }, 133 | "pinus-admin": { 134 | "appenders": [ 135 | "pinus-admin" 136 | ], 137 | "level": "debug" 138 | }, 139 | "pinus-rpc": { 140 | "appenders": [ 141 | "pinus-rpc" 142 | ], 143 | "level": "debug" 144 | } 145 | }, 146 | "prefix": "${opts:serverId} ", 147 | "replaceConsole": true, 148 | "lineDebug": false, 149 | "errorStack": true 150 | } -------------------------------------------------------------------------------- /game-server/config/master.ts: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "development": { 3 | "id": "master-server-1", "host": "127.0.0.1", "port": 3005 4 | }, 5 | "production": { 6 | "id": "master-server-1", "host": "127.0.0.1", "port": 3005 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /game-server/config/mysql.ts: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "development": 3 | { 4 | "host": "127.0.0.1", 5 | "database": "guide", 6 | "user": "root", 7 | "password": "" 8 | }, 9 | "production": 10 | { 11 | "host": "127.0.0.1", 12 | "database": "guide", 13 | "user": "root", 14 | "password": "" 15 | } 16 | }; -------------------------------------------------------------------------------- /game-server/config/redis.ts: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "development": 3 | { 4 | "host": "127.0.0.1", 5 | "port": "6379" 6 | }, 7 | "production": 8 | { 9 | "host": "127.0.0.1", 10 | "port": "6379" 11 | } 12 | }; -------------------------------------------------------------------------------- /game-server/config/serverProtos.ts: -------------------------------------------------------------------------------- 1 | module.exports = {} -------------------------------------------------------------------------------- /game-server/config/servers.ts: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "development": { 3 | "connector": [ 4 | { "id": "connector-server-1", "host": "127.0.0.1", "port": 3150, "clientHost": "127.0.0.1", "clientPort": 3010, "frontend": true, "args": " --inspect=10001" } 5 | ] 6 | }, 7 | "production": { 8 | "connector": [ 9 | { "id": "connector-server-1", "host": "127.0.0.1", "port": 3150, "clientHost": "127.0.0.1", "clientPort": 3010, "frontend": true, "args": " --inspect=10002" } 10 | ] 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /game-server/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "guide", 3 | "version": "0.0.1", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@babel/code-frame": { 8 | "version": "7.10.4", 9 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", 10 | "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", 11 | "dev": true, 12 | "requires": { 13 | "@babel/highlight": "^7.10.4" 14 | } 15 | }, 16 | "@babel/helper-validator-identifier": { 17 | "version": "7.10.4", 18 | "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", 19 | "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", 20 | "dev": true 21 | }, 22 | "@babel/highlight": { 23 | "version": "7.10.4", 24 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", 25 | "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", 26 | "dev": true, 27 | "requires": { 28 | "@babel/helper-validator-identifier": "^7.10.4", 29 | "chalk": "^2.0.0", 30 | "js-tokens": "^4.0.0" 31 | } 32 | }, 33 | "@types/bluebird": { 34 | "version": "3.5.33", 35 | "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.33.tgz", 36 | "integrity": "sha512-ndEo1xvnYeHxm7I/5sF6tBvnsA4Tdi3zj1keRKRs12SP+2ye2A27NDJ1B6PqkfMbGAcT+mqQVqbZRIrhfOp5PQ==" 37 | }, 38 | "@types/engine.io": { 39 | "version": "3.1.4", 40 | "resolved": "https://registry.npmjs.org/@types/engine.io/-/engine.io-3.1.4.tgz", 41 | "integrity": "sha512-98rXVukLD6/ozrQ2O80NAlWDGA4INg+tqsEReWJldqyi2fulC9V7Use/n28SWgROXKm6003ycWV4gZHoF8GA6w==", 42 | "requires": { 43 | "@types/node": "*" 44 | } 45 | }, 46 | "@types/node": { 47 | "version": "8.10.54", 48 | "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.54.tgz", 49 | "integrity": "sha512-kaYyLYf6ICn6/isAyD4K1MyWWd5Q3JgH6bnMN089LUx88+s4W8GvK9Q6JMBVu5vsFFp7pMdSxdKmlBXwH/VFRg==" 50 | }, 51 | "@types/socket.io": { 52 | "version": "2.1.11", 53 | "resolved": "https://registry.npmjs.org/@types/socket.io/-/socket.io-2.1.11.tgz", 54 | "integrity": "sha512-bVprmqPhJMLb9ZCm8g0Xy8kwBFRbnanOWSxzWkDkkIwxTvud5tKMfAJymXX6LQbizUKCS1yima7JM4BeLqjNqA==", 55 | "requires": { 56 | "@types/engine.io": "*", 57 | "@types/node": "*" 58 | } 59 | }, 60 | "accepts": { 61 | "version": "1.3.7", 62 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", 63 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", 64 | "requires": { 65 | "mime-types": "~2.1.24", 66 | "negotiator": "0.6.2" 67 | } 68 | }, 69 | "after": { 70 | "version": "0.8.2", 71 | "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", 72 | "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=" 73 | }, 74 | "ansi-styles": { 75 | "version": "3.2.1", 76 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 77 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 78 | "dev": true, 79 | "requires": { 80 | "color-convert": "^1.9.0" 81 | } 82 | }, 83 | "any-promise": { 84 | "version": "1.3.0", 85 | "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", 86 | "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" 87 | }, 88 | "argparse": { 89 | "version": "1.0.10", 90 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 91 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 92 | "dev": true, 93 | "requires": { 94 | "sprintf-js": "~1.0.2" 95 | } 96 | }, 97 | "arraybuffer.slice": { 98 | "version": "0.0.7", 99 | "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", 100 | "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==" 101 | }, 102 | "async": { 103 | "version": "3.2.0", 104 | "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", 105 | "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==" 106 | }, 107 | "async-limiter": { 108 | "version": "1.0.1", 109 | "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", 110 | "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" 111 | }, 112 | "backo2": { 113 | "version": "1.0.2", 114 | "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", 115 | "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=" 116 | }, 117 | "balanced-match": { 118 | "version": "1.0.0", 119 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 120 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 121 | "dev": true 122 | }, 123 | "base64-arraybuffer": { 124 | "version": "0.1.4", 125 | "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz", 126 | "integrity": "sha1-mBjHngWbE1X5fgQooBfIOOkLqBI=" 127 | }, 128 | "base64-js": { 129 | "version": "1.5.1", 130 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", 131 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" 132 | }, 133 | "base64id": { 134 | "version": "2.0.0", 135 | "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", 136 | "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==" 137 | }, 138 | "bearcat-buffer": { 139 | "version": "0.1.1", 140 | "resolved": "https://registry.npmjs.org/bearcat-buffer/-/bearcat-buffer-0.1.1.tgz", 141 | "integrity": "sha1-K7nJ/KYY0HRQHnN8fycY9ijOcSY=" 142 | }, 143 | "better-assert": { 144 | "version": "1.0.2", 145 | "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", 146 | "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", 147 | "requires": { 148 | "callsite": "1.0.0" 149 | } 150 | }, 151 | "bignumber.js": { 152 | "version": "9.0.0", 153 | "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", 154 | "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==" 155 | }, 156 | "bl": { 157 | "version": "4.0.3", 158 | "resolved": "https://registry.npmjs.org/bl/-/bl-4.0.3.tgz", 159 | "integrity": "sha512-fs4G6/Hu4/EE+F75J8DuN/0IpQqNjAdC7aEQv7Qt8MHGUH7Ckv2MwTEEeN9QehD0pfIDkMI1bkHYkKy7xHyKIg==", 160 | "requires": { 161 | "buffer": "^5.5.0", 162 | "inherits": "^2.0.4", 163 | "readable-stream": "^3.4.0" 164 | }, 165 | "dependencies": { 166 | "readable-stream": { 167 | "version": "3.6.0", 168 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", 169 | "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", 170 | "requires": { 171 | "inherits": "^2.0.3", 172 | "string_decoder": "^1.1.1", 173 | "util-deprecate": "^1.0.1" 174 | } 175 | } 176 | } 177 | }, 178 | "blob": { 179 | "version": "0.0.5", 180 | "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", 181 | "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==" 182 | }, 183 | "bluebird": { 184 | "version": "3.7.2", 185 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", 186 | "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" 187 | }, 188 | "brace-expansion": { 189 | "version": "1.1.11", 190 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 191 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 192 | "dev": true, 193 | "requires": { 194 | "balanced-match": "^1.0.0", 195 | "concat-map": "0.0.1" 196 | } 197 | }, 198 | "buffer": { 199 | "version": "5.7.1", 200 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", 201 | "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", 202 | "requires": { 203 | "base64-js": "^1.3.1", 204 | "ieee754": "^1.1.13" 205 | } 206 | }, 207 | "buffer-from": { 208 | "version": "1.1.1", 209 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", 210 | "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" 211 | }, 212 | "builtin-modules": { 213 | "version": "1.1.1", 214 | "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", 215 | "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", 216 | "dev": true 217 | }, 218 | "callsite": { 219 | "version": "1.0.0", 220 | "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", 221 | "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=" 222 | }, 223 | "chalk": { 224 | "version": "2.4.2", 225 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 226 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 227 | "dev": true, 228 | "requires": { 229 | "ansi-styles": "^3.2.1", 230 | "escape-string-regexp": "^1.0.5", 231 | "supports-color": "^5.3.0" 232 | } 233 | }, 234 | "cliff": { 235 | "version": "0.1.10", 236 | "resolved": "https://registry.npmjs.org/cliff/-/cliff-0.1.10.tgz", 237 | "integrity": "sha1-U74z6p9ZvshWCe4wCsQgdgPlIBM=", 238 | "requires": { 239 | "colors": "~1.0.3", 240 | "eyes": "~0.1.8", 241 | "winston": "0.8.x" 242 | } 243 | }, 244 | "color-convert": { 245 | "version": "1.9.3", 246 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 247 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 248 | "dev": true, 249 | "requires": { 250 | "color-name": "1.1.3" 251 | } 252 | }, 253 | "color-name": { 254 | "version": "1.1.3", 255 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 256 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", 257 | "dev": true 258 | }, 259 | "colors": { 260 | "version": "1.0.3", 261 | "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", 262 | "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" 263 | }, 264 | "commander": { 265 | "version": "3.0.2", 266 | "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz", 267 | "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==" 268 | }, 269 | "component-bind": { 270 | "version": "1.0.0", 271 | "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", 272 | "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=" 273 | }, 274 | "component-emitter": { 275 | "version": "1.2.1", 276 | "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", 277 | "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" 278 | }, 279 | "component-inherit": { 280 | "version": "0.0.3", 281 | "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", 282 | "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=" 283 | }, 284 | "concat-map": { 285 | "version": "0.0.1", 286 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 287 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 288 | "dev": true 289 | }, 290 | "cookie": { 291 | "version": "0.3.1", 292 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", 293 | "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" 294 | }, 295 | "core-util-is": { 296 | "version": "1.0.2", 297 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 298 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 299 | }, 300 | "crc": { 301 | "version": "3.8.0", 302 | "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", 303 | "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", 304 | "requires": { 305 | "buffer": "^5.1.0" 306 | } 307 | }, 308 | "crypto": { 309 | "version": "1.0.1", 310 | "resolved": "https://registry.npmjs.org/crypto/-/crypto-1.0.1.tgz", 311 | "integrity": "sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig==" 312 | }, 313 | "cycle": { 314 | "version": "1.0.3", 315 | "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", 316 | "integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI=" 317 | }, 318 | "date-format": { 319 | "version": "3.0.0", 320 | "resolved": "https://registry.npmjs.org/date-format/-/date-format-3.0.0.tgz", 321 | "integrity": "sha512-eyTcpKOcamdhWJXj56DpQMo1ylSQpcGtGKXcU0Tb97+K56/CF5amAqqqNj0+KvA0iw2ynxtHWFsPDSClCxe48w==" 322 | }, 323 | "debug": { 324 | "version": "4.2.0", 325 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", 326 | "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", 327 | "requires": { 328 | "ms": "2.1.2" 329 | } 330 | }, 331 | "denque": { 332 | "version": "1.4.1", 333 | "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", 334 | "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==" 335 | }, 336 | "diff": { 337 | "version": "4.0.2", 338 | "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", 339 | "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", 340 | "dev": true 341 | }, 342 | "duplexify": { 343 | "version": "3.7.1", 344 | "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", 345 | "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", 346 | "requires": { 347 | "end-of-stream": "^1.0.0", 348 | "inherits": "^2.0.1", 349 | "readable-stream": "^2.0.0", 350 | "stream-shift": "^1.0.0" 351 | } 352 | }, 353 | "end-of-stream": { 354 | "version": "1.4.4", 355 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", 356 | "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", 357 | "requires": { 358 | "once": "^1.4.0" 359 | } 360 | }, 361 | "engine.io": { 362 | "version": "3.4.2", 363 | "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.4.2.tgz", 364 | "integrity": "sha512-b4Q85dFkGw+TqgytGPrGgACRUhsdKc9S9ErRAXpPGy/CXKs4tYoHDkvIRdsseAF7NjfVwjRFIn6KTnbw7LwJZg==", 365 | "requires": { 366 | "accepts": "~1.3.4", 367 | "base64id": "2.0.0", 368 | "cookie": "0.3.1", 369 | "debug": "~4.1.0", 370 | "engine.io-parser": "~2.2.0", 371 | "ws": "^7.1.2" 372 | }, 373 | "dependencies": { 374 | "debug": { 375 | "version": "4.1.1", 376 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", 377 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", 378 | "requires": { 379 | "ms": "^2.1.1" 380 | } 381 | } 382 | } 383 | }, 384 | "engine.io-client": { 385 | "version": "3.4.4", 386 | "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.4.4.tgz", 387 | "integrity": "sha512-iU4CRr38Fecj8HoZEnFtm2EiKGbYZcPn3cHxqNGl/tmdWRf60KhK+9vE0JeSjgnlS/0oynEfLgKbT9ALpim0sQ==", 388 | "requires": { 389 | "component-emitter": "~1.3.0", 390 | "component-inherit": "0.0.3", 391 | "debug": "~3.1.0", 392 | "engine.io-parser": "~2.2.0", 393 | "has-cors": "1.1.0", 394 | "indexof": "0.0.1", 395 | "parseqs": "0.0.6", 396 | "parseuri": "0.0.6", 397 | "ws": "~6.1.0", 398 | "xmlhttprequest-ssl": "~1.5.4", 399 | "yeast": "0.1.2" 400 | }, 401 | "dependencies": { 402 | "component-emitter": { 403 | "version": "1.3.0", 404 | "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", 405 | "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" 406 | }, 407 | "debug": { 408 | "version": "3.1.0", 409 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 410 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 411 | "requires": { 412 | "ms": "2.0.0" 413 | } 414 | }, 415 | "ms": { 416 | "version": "2.0.0", 417 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 418 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 419 | }, 420 | "parseqs": { 421 | "version": "0.0.6", 422 | "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz", 423 | "integrity": "sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w==" 424 | }, 425 | "parseuri": { 426 | "version": "0.0.6", 427 | "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz", 428 | "integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow==" 429 | }, 430 | "ws": { 431 | "version": "6.1.4", 432 | "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz", 433 | "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==", 434 | "requires": { 435 | "async-limiter": "~1.0.0" 436 | } 437 | } 438 | } 439 | }, 440 | "engine.io-parser": { 441 | "version": "2.2.1", 442 | "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.2.1.tgz", 443 | "integrity": "sha512-x+dN/fBH8Ro8TFwJ+rkB2AmuVw9Yu2mockR/p3W8f8YtExwFgDvBDi0GWyb4ZLkpahtDGZgtr3zLovanJghPqg==", 444 | "requires": { 445 | "after": "0.8.2", 446 | "arraybuffer.slice": "~0.0.7", 447 | "base64-arraybuffer": "0.1.4", 448 | "blob": "0.0.5", 449 | "has-binary2": "~1.0.2" 450 | } 451 | }, 452 | "escape-string-regexp": { 453 | "version": "1.0.5", 454 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 455 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 456 | "dev": true 457 | }, 458 | "esprima": { 459 | "version": "4.0.1", 460 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 461 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 462 | "dev": true 463 | }, 464 | "eyes": { 465 | "version": "0.1.8", 466 | "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", 467 | "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=" 468 | }, 469 | "flatted": { 470 | "version": "2.0.2", 471 | "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", 472 | "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==" 473 | }, 474 | "fs-extra": { 475 | "version": "8.1.0", 476 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", 477 | "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", 478 | "requires": { 479 | "graceful-fs": "^4.2.0", 480 | "jsonfile": "^4.0.0", 481 | "universalify": "^0.1.0" 482 | } 483 | }, 484 | "fs.realpath": { 485 | "version": "1.0.0", 486 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 487 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 488 | "dev": true 489 | }, 490 | "function-bind": { 491 | "version": "1.1.1", 492 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 493 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", 494 | "dev": true 495 | }, 496 | "glob": { 497 | "version": "7.1.6", 498 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", 499 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", 500 | "dev": true, 501 | "requires": { 502 | "fs.realpath": "^1.0.0", 503 | "inflight": "^1.0.4", 504 | "inherits": "2", 505 | "minimatch": "^3.0.4", 506 | "once": "^1.3.0", 507 | "path-is-absolute": "^1.0.0" 508 | } 509 | }, 510 | "graceful-fs": { 511 | "version": "4.2.4", 512 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", 513 | "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" 514 | }, 515 | "has": { 516 | "version": "1.0.3", 517 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 518 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 519 | "dev": true, 520 | "requires": { 521 | "function-bind": "^1.1.1" 522 | } 523 | }, 524 | "has-binary2": { 525 | "version": "1.0.3", 526 | "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", 527 | "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", 528 | "requires": { 529 | "isarray": "2.0.1" 530 | }, 531 | "dependencies": { 532 | "isarray": { 533 | "version": "2.0.1", 534 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", 535 | "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" 536 | } 537 | } 538 | }, 539 | "has-cors": { 540 | "version": "1.1.0", 541 | "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", 542 | "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=" 543 | }, 544 | "has-flag": { 545 | "version": "3.0.0", 546 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 547 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 548 | "dev": true 549 | }, 550 | "ieee754": { 551 | "version": "1.2.1", 552 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", 553 | "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" 554 | }, 555 | "indexof": { 556 | "version": "0.0.1", 557 | "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", 558 | "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" 559 | }, 560 | "inflight": { 561 | "version": "1.0.6", 562 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 563 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 564 | "dev": true, 565 | "requires": { 566 | "once": "^1.3.0", 567 | "wrappy": "1" 568 | } 569 | }, 570 | "inherits": { 571 | "version": "2.0.4", 572 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 573 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 574 | }, 575 | "is-core-module": { 576 | "version": "2.1.0", 577 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.1.0.tgz", 578 | "integrity": "sha512-YcV7BgVMRFRua2FqQzKtTDMz8iCuLEyGKjr70q8Zm1yy2qKcurbFEd79PAdHV77oL3NrAaOVQIbMmiHQCHB7ZA==", 579 | "dev": true, 580 | "requires": { 581 | "has": "^1.0.3" 582 | } 583 | }, 584 | "isarray": { 585 | "version": "1.0.0", 586 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 587 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 588 | }, 589 | "isstream": { 590 | "version": "0.1.2", 591 | "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", 592 | "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" 593 | }, 594 | "js-tokens": { 595 | "version": "4.0.0", 596 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 597 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", 598 | "dev": true 599 | }, 600 | "js-yaml": { 601 | "version": "3.14.0", 602 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", 603 | "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", 604 | "dev": true, 605 | "requires": { 606 | "argparse": "^1.0.7", 607 | "esprima": "^4.0.0" 608 | } 609 | }, 610 | "jsonfile": { 611 | "version": "4.0.0", 612 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", 613 | "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", 614 | "requires": { 615 | "graceful-fs": "^4.1.6" 616 | } 617 | }, 618 | "log4js": { 619 | "version": "6.3.0", 620 | "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.3.0.tgz", 621 | "integrity": "sha512-Mc8jNuSFImQUIateBFwdOQcmC6Q5maU0VVvdC2R6XMb66/VnT+7WS4D/0EeNMZu1YODmJe5NIn2XftCzEocUgw==", 622 | "requires": { 623 | "date-format": "^3.0.0", 624 | "debug": "^4.1.1", 625 | "flatted": "^2.0.1", 626 | "rfdc": "^1.1.4", 627 | "streamroller": "^2.2.4" 628 | } 629 | }, 630 | "mime-db": { 631 | "version": "1.44.0", 632 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", 633 | "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" 634 | }, 635 | "mime-types": { 636 | "version": "2.1.27", 637 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", 638 | "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", 639 | "requires": { 640 | "mime-db": "1.44.0" 641 | } 642 | }, 643 | "minimatch": { 644 | "version": "3.0.4", 645 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 646 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 647 | "dev": true, 648 | "requires": { 649 | "brace-expansion": "^1.1.7" 650 | } 651 | }, 652 | "minimist": { 653 | "version": "1.2.5", 654 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 655 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" 656 | }, 657 | "mkdirp": { 658 | "version": "0.5.5", 659 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", 660 | "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", 661 | "requires": { 662 | "minimist": "^1.2.5" 663 | } 664 | }, 665 | "moment": { 666 | "version": "2.29.1", 667 | "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", 668 | "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" 669 | }, 670 | "mqtt-connection": { 671 | "version": "4.0.0", 672 | "resolved": "https://registry.npmjs.org/mqtt-connection/-/mqtt-connection-4.0.0.tgz", 673 | "integrity": "sha512-hkgQ2DjScc7ShVga4IEyxKum+rUXCGxoSiiG1DacrGZ9lz0TNzGEybaIScexCNBnt8fepBbfnXa6t0yr/69vjw==", 674 | "requires": { 675 | "duplexify": "^3.5.1", 676 | "inherits": "^2.0.3", 677 | "mqtt-packet": "^6.0.0", 678 | "safe-buffer": "^5.1.1", 679 | "through2": "^2.0.1" 680 | } 681 | }, 682 | "mqtt-packet": { 683 | "version": "6.6.0", 684 | "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.6.0.tgz", 685 | "integrity": "sha512-LvghnKMFC70hKWMVykmhJarlO5e7lT3t9s9A2qPCUx+lazL3Mq55U+eCV0eLi7/nRRQYvEUWo/2tTo89EjnCJQ==", 686 | "requires": { 687 | "bl": "^4.0.2", 688 | "debug": "^4.1.1", 689 | "process-nextick-args": "^2.0.1" 690 | } 691 | }, 692 | "ms": { 693 | "version": "2.1.2", 694 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 695 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 696 | }, 697 | "mysql": { 698 | "version": "2.18.1", 699 | "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz", 700 | "integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==", 701 | "requires": { 702 | "bignumber.js": "9.0.0", 703 | "readable-stream": "2.3.7", 704 | "safe-buffer": "5.1.2", 705 | "sqlstring": "2.3.1" 706 | }, 707 | "dependencies": { 708 | "safe-buffer": { 709 | "version": "5.1.2", 710 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 711 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 712 | } 713 | } 714 | }, 715 | "mz": { 716 | "version": "2.7.0", 717 | "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", 718 | "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", 719 | "requires": { 720 | "any-promise": "^1.0.0", 721 | "object-assign": "^4.0.1", 722 | "thenify-all": "^1.0.0" 723 | } 724 | }, 725 | "negotiator": { 726 | "version": "0.6.2", 727 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", 728 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" 729 | }, 730 | "node-bignumber": { 731 | "version": "1.2.1", 732 | "resolved": "https://registry.npmjs.org/node-bignumber/-/node-bignumber-1.2.1.tgz", 733 | "integrity": "sha1-JmyVUzUoOFOfZhyS5YYxvpeRfqU=" 734 | }, 735 | "object-assign": { 736 | "version": "4.1.1", 737 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 738 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 739 | }, 740 | "object-component": { 741 | "version": "0.0.3", 742 | "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", 743 | "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=" 744 | }, 745 | "once": { 746 | "version": "1.4.0", 747 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 748 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 749 | "requires": { 750 | "wrappy": "1" 751 | } 752 | }, 753 | "parseqs": { 754 | "version": "0.0.5", 755 | "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", 756 | "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", 757 | "requires": { 758 | "better-assert": "~1.0.0" 759 | } 760 | }, 761 | "parseuri": { 762 | "version": "0.0.5", 763 | "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", 764 | "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", 765 | "requires": { 766 | "better-assert": "~1.0.0" 767 | } 768 | }, 769 | "path-is-absolute": { 770 | "version": "1.0.1", 771 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 772 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 773 | "dev": true 774 | }, 775 | "path-parse": { 776 | "version": "1.0.6", 777 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", 778 | "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", 779 | "dev": true 780 | }, 781 | "pinus": { 782 | "version": "1.4.10", 783 | "resolved": "https://registry.npmjs.org/pinus/-/pinus-1.4.10.tgz", 784 | "integrity": "sha512-g0RYi5hFqSvigKbQlITK9JxcYEL0WtVd0wcXv5JOeqSw+rHfpbqoWDK+nMaVx6d69kknP6wvVtz/r0zPBfFp8w==", 785 | "requires": { 786 | "@types/socket.io": "^2.1.6", 787 | "async": "^3.0.0", 788 | "cliff": "^0.1.10", 789 | "commander": "^3.0.0", 790 | "crc": "^3.5.0", 791 | "eyes": "^0.1.8", 792 | "mkdirp": "^0.5.1", 793 | "mqtt-connection": "^4.0.0", 794 | "node-bignumber": "^1.2.1", 795 | "pinus-admin": "^1.4.10", 796 | "pinus-loader": "^1.4.10", 797 | "pinus-logger": "^1.4.10", 798 | "pinus-protobuf": "^1.4.10", 799 | "pinus-protocol": "^1.4.10", 800 | "pinus-rpc": "^1.4.10", 801 | "pinus-scheduler": "^1.4.10", 802 | "seq-queue": "^0.0.5", 803 | "socket.io": "^2.3.0", 804 | "ws": "^7.0.0" 805 | } 806 | }, 807 | "pinus-admin": { 808 | "version": "1.4.10", 809 | "resolved": "https://registry.npmjs.org/pinus-admin/-/pinus-admin-1.4.10.tgz", 810 | "integrity": "sha512-0SIPe5rUQcKyVmsWpNFvMw4C7qzeQDCGkv2rDrmW03Mrrqi1WgGjIEeUH4UAGBH64H3y0BQ2prnX/hTQ97rsrw==", 811 | "requires": { 812 | "mqtt-connection": "^3.2.0", 813 | "pinus-logger": "^1.4.10", 814 | "pinus-monitor": "^1.4.10", 815 | "pinus-scheduler": "^1.4.10", 816 | "read-last-lines": "^1.3.0" 817 | }, 818 | "dependencies": { 819 | "bl": { 820 | "version": "1.2.3", 821 | "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", 822 | "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", 823 | "requires": { 824 | "readable-stream": "^2.3.5", 825 | "safe-buffer": "^5.1.1" 826 | } 827 | }, 828 | "mqtt-connection": { 829 | "version": "3.2.0", 830 | "resolved": "https://registry.npmjs.org/mqtt-connection/-/mqtt-connection-3.2.0.tgz", 831 | "integrity": "sha512-br1n12OegkGfkseOHYby2LggkQy9qtgVKo8kg64acd89/Pc+vzcEA2PzmLd/kNo5K08YuJTVo2GYmymhY8NDIw==", 832 | "requires": { 833 | "duplexify": "^3.5.1", 834 | "inherits": "^2.0.3", 835 | "mqtt-packet": "^5.4.0", 836 | "safe-buffer": "^5.1.1", 837 | "through2": "^2.0.1" 838 | } 839 | }, 840 | "mqtt-packet": { 841 | "version": "5.6.1", 842 | "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-5.6.1.tgz", 843 | "integrity": "sha512-eaF9rO2uFrIYEHomJxziuKTDkbWW5psLBaIGCazQSKqYsTaB3n4SpvJ1PexKaDBiPnMLPIFWBIiTYT3IfEJfww==", 844 | "requires": { 845 | "bl": "^1.2.1", 846 | "inherits": "^2.0.3", 847 | "process-nextick-args": "^2.0.0", 848 | "safe-buffer": "^5.1.0" 849 | } 850 | } 851 | } 852 | }, 853 | "pinus-loader": { 854 | "version": "1.4.10", 855 | "resolved": "https://registry.npmjs.org/pinus-loader/-/pinus-loader-1.4.10.tgz", 856 | "integrity": "sha512-5EzEXP1y6sb+jKrDLQ10hyl8MGZDzg5eo+sPALAaGIKCcUIPyAFIBALXO/+l/efaNEDAJoWSCCFeDYe+HFrchg==", 857 | "requires": { 858 | "reflect-metadata": "0.1.13" 859 | } 860 | }, 861 | "pinus-logger": { 862 | "version": "1.4.10", 863 | "resolved": "https://registry.npmjs.org/pinus-logger/-/pinus-logger-1.4.10.tgz", 864 | "integrity": "sha512-qKQw4YwvWttUJX6/18lneJupZfmgc092d+marA66BfSgPOyXvn/jB+IYQMuNzsGqN2KgF+T083QPmZioIXdTLA==", 865 | "requires": { 866 | "log4js": "^6.0.0" 867 | } 868 | }, 869 | "pinus-monitor": { 870 | "version": "1.4.10", 871 | "resolved": "https://registry.npmjs.org/pinus-monitor/-/pinus-monitor-1.4.10.tgz", 872 | "integrity": "sha512-Dh067SgVeM+h0FWQQg2FQ6vrcVbfYNA2ne7uTjHQ4Rt1ggbfS1H4ZDvWpt6tkQznBElpdSJqfqcOLeZ+LGY9HQ==" 873 | }, 874 | "pinus-protobuf": { 875 | "version": "1.4.10", 876 | "resolved": "https://registry.npmjs.org/pinus-protobuf/-/pinus-protobuf-1.4.10.tgz", 877 | "integrity": "sha512-GL+N0++p6vx0sgRUsUl0UOn7DnTjykvEC7kQlAyrPUIXDNyLjE60Pr7hLVYw6qzMLy8tekPAB5p+Eb/UuuogTg==" 878 | }, 879 | "pinus-protocol": { 880 | "version": "1.4.10", 881 | "resolved": "https://registry.npmjs.org/pinus-protocol/-/pinus-protocol-1.4.10.tgz", 882 | "integrity": "sha512-c4SGfCadtAJsD/1k+CfyZHi+Ev4B/JaahIJYo1MZwd72Bj/+wZJFL3ntBvecpxVGZ9YQKjxrZS6G9dCrZvLEKg==" 883 | }, 884 | "pinus-rpc": { 885 | "version": "1.4.10", 886 | "resolved": "https://registry.npmjs.org/pinus-rpc/-/pinus-rpc-1.4.10.tgz", 887 | "integrity": "sha512-n67eP9kAsv+6PIFeEGaSMk0jkOJkQ5DTHzld5PP1LaM691LatsaPmgQJ/aBBxIeNLyPMp5uVuUP51KJ1b6qlTg==", 888 | "requires": { 889 | "async": "^3.0.0", 890 | "bearcat-buffer": "^0.1.x", 891 | "bluebird": "^3.5.1", 892 | "crc": "^0.2.1", 893 | "mqtt-connection": "^3.2.0", 894 | "pinus-loader": "^1.4.10", 895 | "pinus-logger": "^1.4.10", 896 | "socket.io": "^2.3.0", 897 | "source-map-support": "^0.5.0", 898 | "stream-pkg": "0.0.5", 899 | "uuid": "^3.1.0", 900 | "ws": "^7.0.0" 901 | }, 902 | "dependencies": { 903 | "bl": { 904 | "version": "1.2.3", 905 | "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", 906 | "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", 907 | "requires": { 908 | "readable-stream": "^2.3.5", 909 | "safe-buffer": "^5.1.1" 910 | } 911 | }, 912 | "crc": { 913 | "version": "0.2.1", 914 | "resolved": "https://registry.npmjs.org/crc/-/crc-0.2.1.tgz", 915 | "integrity": "sha1-sfER/Dq7m4PTopGmggz26MfvMtc=" 916 | }, 917 | "mqtt-connection": { 918 | "version": "3.2.0", 919 | "resolved": "https://registry.npmjs.org/mqtt-connection/-/mqtt-connection-3.2.0.tgz", 920 | "integrity": "sha512-br1n12OegkGfkseOHYby2LggkQy9qtgVKo8kg64acd89/Pc+vzcEA2PzmLd/kNo5K08YuJTVo2GYmymhY8NDIw==", 921 | "requires": { 922 | "duplexify": "^3.5.1", 923 | "inherits": "^2.0.3", 924 | "mqtt-packet": "^5.4.0", 925 | "safe-buffer": "^5.1.1", 926 | "through2": "^2.0.1" 927 | } 928 | }, 929 | "mqtt-packet": { 930 | "version": "5.6.1", 931 | "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-5.6.1.tgz", 932 | "integrity": "sha512-eaF9rO2uFrIYEHomJxziuKTDkbWW5psLBaIGCazQSKqYsTaB3n4SpvJ1PexKaDBiPnMLPIFWBIiTYT3IfEJfww==", 933 | "requires": { 934 | "bl": "^1.2.1", 935 | "inherits": "^2.0.3", 936 | "process-nextick-args": "^2.0.0", 937 | "safe-buffer": "^5.1.0" 938 | } 939 | } 940 | } 941 | }, 942 | "pinus-scheduler": { 943 | "version": "1.4.10", 944 | "resolved": "https://registry.npmjs.org/pinus-scheduler/-/pinus-scheduler-1.4.10.tgz", 945 | "integrity": "sha512-iqc9TV+rKMkQabCa+jI1Y/jP75lGUGU8QNwjtg3R6KdTV+pVx+NBfcYgMh/+zkJayzshK8XgqJII/GAT9qbDFA==", 946 | "requires": { 947 | "pinus-logger": "^1.4.10" 948 | } 949 | }, 950 | "pkginfo": { 951 | "version": "0.3.1", 952 | "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.1.tgz", 953 | "integrity": "sha1-Wyn2qB9wcXFC4J52W76rl7T4HiE=" 954 | }, 955 | "process-nextick-args": { 956 | "version": "2.0.1", 957 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", 958 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" 959 | }, 960 | "read-last-lines": { 961 | "version": "1.7.2", 962 | "resolved": "https://registry.npmjs.org/read-last-lines/-/read-last-lines-1.7.2.tgz", 963 | "integrity": "sha512-K0yUvTYAYn6qpyLJufaJ7yC6BeL23qpgZ8SKM7/fA1R1rHotCDxB/zDp9i1I2JHvexWBW6/35jkt07iiIKKp4g==", 964 | "requires": { 965 | "mz": "^2.7.0" 966 | } 967 | }, 968 | "readable-stream": { 969 | "version": "2.3.7", 970 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", 971 | "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", 972 | "requires": { 973 | "core-util-is": "~1.0.0", 974 | "inherits": "~2.0.3", 975 | "isarray": "~1.0.0", 976 | "process-nextick-args": "~2.0.0", 977 | "safe-buffer": "~5.1.1", 978 | "string_decoder": "~1.1.1", 979 | "util-deprecate": "~1.0.1" 980 | }, 981 | "dependencies": { 982 | "safe-buffer": { 983 | "version": "5.1.2", 984 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 985 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 986 | } 987 | } 988 | }, 989 | "redis": { 990 | "version": "3.0.2", 991 | "resolved": "https://registry.npmjs.org/redis/-/redis-3.0.2.tgz", 992 | "integrity": "sha512-PNhLCrjU6vKVuMOyFu7oSP296mwBkcE6lrAjruBYG5LgdSqtRBoVQIylrMyVZD/lkF24RSNNatzvYag6HRBHjQ==", 993 | "requires": { 994 | "denque": "^1.4.1", 995 | "redis-commands": "^1.5.0", 996 | "redis-errors": "^1.2.0", 997 | "redis-parser": "^3.0.0" 998 | } 999 | }, 1000 | "redis-commands": { 1001 | "version": "1.6.0", 1002 | "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.6.0.tgz", 1003 | "integrity": "sha512-2jnZ0IkjZxvguITjFTrGiLyzQZcTvaw8DAaCXxZq/dsHXz7KfMQ3OUJy7Tz9vnRtZRVz6VRCPDvruvU8Ts44wQ==" 1004 | }, 1005 | "redis-errors": { 1006 | "version": "1.2.0", 1007 | "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", 1008 | "integrity": "sha1-62LSrbFeTq9GEMBK/hUpOEJQq60=" 1009 | }, 1010 | "redis-parser": { 1011 | "version": "3.0.0", 1012 | "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", 1013 | "integrity": "sha1-tm2CjNyv5rS4pCin3vTGvKwxyLQ=", 1014 | "requires": { 1015 | "redis-errors": "^1.0.0" 1016 | } 1017 | }, 1018 | "redlock": { 1019 | "version": "4.2.0", 1020 | "resolved": "https://registry.npmjs.org/redlock/-/redlock-4.2.0.tgz", 1021 | "integrity": "sha512-j+oQlG+dOwcetUt2WJWttu4CZVeRzUrcVcISFmEmfyuwCVSJ93rDT7YSgg7H7rnxwoRyk/jU46kycVka5tW7jA==", 1022 | "requires": { 1023 | "bluebird": "^3.7.2" 1024 | } 1025 | }, 1026 | "reflect-metadata": { 1027 | "version": "0.1.13", 1028 | "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", 1029 | "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" 1030 | }, 1031 | "resolve": { 1032 | "version": "1.19.0", 1033 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", 1034 | "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", 1035 | "dev": true, 1036 | "requires": { 1037 | "is-core-module": "^2.1.0", 1038 | "path-parse": "^1.0.6" 1039 | } 1040 | }, 1041 | "rfdc": { 1042 | "version": "1.1.4", 1043 | "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.4.tgz", 1044 | "integrity": "sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug==" 1045 | }, 1046 | "safe-buffer": { 1047 | "version": "5.2.1", 1048 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 1049 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 1050 | }, 1051 | "semver": { 1052 | "version": "5.7.1", 1053 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 1054 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", 1055 | "dev": true 1056 | }, 1057 | "seq-queue": { 1058 | "version": "0.0.5", 1059 | "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", 1060 | "integrity": "sha1-1WgS4cAXpuTnw+Ojeh2m143TyT4=" 1061 | }, 1062 | "socket.io": { 1063 | "version": "2.3.0", 1064 | "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.3.0.tgz", 1065 | "integrity": "sha512-2A892lrj0GcgR/9Qk81EaY2gYhCBxurV0PfmmESO6p27QPrUK1J3zdns+5QPqvUYK2q657nSj0guoIil9+7eFg==", 1066 | "requires": { 1067 | "debug": "~4.1.0", 1068 | "engine.io": "~3.4.0", 1069 | "has-binary2": "~1.0.2", 1070 | "socket.io-adapter": "~1.1.0", 1071 | "socket.io-client": "2.3.0", 1072 | "socket.io-parser": "~3.4.0" 1073 | }, 1074 | "dependencies": { 1075 | "debug": { 1076 | "version": "4.1.1", 1077 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", 1078 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", 1079 | "requires": { 1080 | "ms": "^2.1.1" 1081 | } 1082 | } 1083 | } 1084 | }, 1085 | "socket.io-adapter": { 1086 | "version": "1.1.2", 1087 | "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz", 1088 | "integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g==" 1089 | }, 1090 | "socket.io-client": { 1091 | "version": "2.3.0", 1092 | "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.3.0.tgz", 1093 | "integrity": "sha512-cEQQf24gET3rfhxZ2jJ5xzAOo/xhZwK+mOqtGRg5IowZsMgwvHwnf/mCRapAAkadhM26y+iydgwsXGObBB5ZdA==", 1094 | "requires": { 1095 | "backo2": "1.0.2", 1096 | "base64-arraybuffer": "0.1.5", 1097 | "component-bind": "1.0.0", 1098 | "component-emitter": "1.2.1", 1099 | "debug": "~4.1.0", 1100 | "engine.io-client": "~3.4.0", 1101 | "has-binary2": "~1.0.2", 1102 | "has-cors": "1.1.0", 1103 | "indexof": "0.0.1", 1104 | "object-component": "0.0.3", 1105 | "parseqs": "0.0.5", 1106 | "parseuri": "0.0.5", 1107 | "socket.io-parser": "~3.3.0", 1108 | "to-array": "0.1.4" 1109 | }, 1110 | "dependencies": { 1111 | "base64-arraybuffer": { 1112 | "version": "0.1.5", 1113 | "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", 1114 | "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=" 1115 | }, 1116 | "debug": { 1117 | "version": "4.1.1", 1118 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", 1119 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", 1120 | "requires": { 1121 | "ms": "^2.1.1" 1122 | } 1123 | }, 1124 | "isarray": { 1125 | "version": "2.0.1", 1126 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", 1127 | "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" 1128 | }, 1129 | "socket.io-parser": { 1130 | "version": "3.3.1", 1131 | "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.1.tgz", 1132 | "integrity": "sha512-1QLvVAe8dTz+mKmZ07Swxt+LAo4Y1ff50rlyoEx00TQmDFVQYPfcqGvIDJLGaBdhdNCecXtyKpD+EgKGcmmbuQ==", 1133 | "requires": { 1134 | "component-emitter": "~1.3.0", 1135 | "debug": "~3.1.0", 1136 | "isarray": "2.0.1" 1137 | }, 1138 | "dependencies": { 1139 | "component-emitter": { 1140 | "version": "1.3.0", 1141 | "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", 1142 | "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" 1143 | }, 1144 | "debug": { 1145 | "version": "3.1.0", 1146 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 1147 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 1148 | "requires": { 1149 | "ms": "2.0.0" 1150 | } 1151 | }, 1152 | "ms": { 1153 | "version": "2.0.0", 1154 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1155 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 1156 | } 1157 | } 1158 | } 1159 | } 1160 | }, 1161 | "socket.io-parser": { 1162 | "version": "3.4.1", 1163 | "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.4.1.tgz", 1164 | "integrity": "sha512-11hMgzL+WCLWf1uFtHSNvliI++tcRUWdoeYuwIl+Axvwy9z2gQM+7nJyN3STj1tLj5JyIUH8/gpDGxzAlDdi0A==", 1165 | "requires": { 1166 | "component-emitter": "1.2.1", 1167 | "debug": "~4.1.0", 1168 | "isarray": "2.0.1" 1169 | }, 1170 | "dependencies": { 1171 | "debug": { 1172 | "version": "4.1.1", 1173 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", 1174 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", 1175 | "requires": { 1176 | "ms": "^2.1.1" 1177 | } 1178 | }, 1179 | "isarray": { 1180 | "version": "2.0.1", 1181 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", 1182 | "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" 1183 | } 1184 | } 1185 | }, 1186 | "source-map": { 1187 | "version": "0.6.1", 1188 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 1189 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" 1190 | }, 1191 | "source-map-support": { 1192 | "version": "0.5.19", 1193 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", 1194 | "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", 1195 | "requires": { 1196 | "buffer-from": "^1.0.0", 1197 | "source-map": "^0.6.0" 1198 | } 1199 | }, 1200 | "sprintf-js": { 1201 | "version": "1.0.3", 1202 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 1203 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", 1204 | "dev": true 1205 | }, 1206 | "sqlstring": { 1207 | "version": "2.3.1", 1208 | "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", 1209 | "integrity": "sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A=" 1210 | }, 1211 | "stack-trace": { 1212 | "version": "0.0.10", 1213 | "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", 1214 | "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" 1215 | }, 1216 | "stream-pkg": { 1217 | "version": "0.0.5", 1218 | "resolved": "https://registry.npmjs.org/stream-pkg/-/stream-pkg-0.0.5.tgz", 1219 | "integrity": "sha1-kx/TMuLomR8GBEKUNBYL1qSC82U=" 1220 | }, 1221 | "stream-shift": { 1222 | "version": "1.0.1", 1223 | "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", 1224 | "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" 1225 | }, 1226 | "streamroller": { 1227 | "version": "2.2.4", 1228 | "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-2.2.4.tgz", 1229 | "integrity": "sha512-OG79qm3AujAM9ImoqgWEY1xG4HX+Lw+yY6qZj9R1K2mhF5bEmQ849wvrb+4vt4jLMLzwXttJlQbOdPOQVRv7DQ==", 1230 | "requires": { 1231 | "date-format": "^2.1.0", 1232 | "debug": "^4.1.1", 1233 | "fs-extra": "^8.1.0" 1234 | }, 1235 | "dependencies": { 1236 | "date-format": { 1237 | "version": "2.1.0", 1238 | "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz", 1239 | "integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==" 1240 | } 1241 | } 1242 | }, 1243 | "string_decoder": { 1244 | "version": "1.1.1", 1245 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 1246 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 1247 | "requires": { 1248 | "safe-buffer": "~5.1.0" 1249 | }, 1250 | "dependencies": { 1251 | "safe-buffer": { 1252 | "version": "5.1.2", 1253 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1254 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 1255 | } 1256 | } 1257 | }, 1258 | "supports-color": { 1259 | "version": "5.5.0", 1260 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 1261 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 1262 | "dev": true, 1263 | "requires": { 1264 | "has-flag": "^3.0.0" 1265 | } 1266 | }, 1267 | "thenify": { 1268 | "version": "3.3.1", 1269 | "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", 1270 | "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", 1271 | "requires": { 1272 | "any-promise": "^1.0.0" 1273 | } 1274 | }, 1275 | "thenify-all": { 1276 | "version": "1.6.0", 1277 | "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", 1278 | "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=", 1279 | "requires": { 1280 | "thenify": ">= 3.1.0 < 4" 1281 | } 1282 | }, 1283 | "through2": { 1284 | "version": "2.0.5", 1285 | "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", 1286 | "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", 1287 | "requires": { 1288 | "readable-stream": "~2.3.6", 1289 | "xtend": "~4.0.1" 1290 | } 1291 | }, 1292 | "to-array": { 1293 | "version": "0.1.4", 1294 | "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", 1295 | "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=" 1296 | }, 1297 | "tslib": { 1298 | "version": "1.14.1", 1299 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", 1300 | "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", 1301 | "dev": true 1302 | }, 1303 | "tslint": { 1304 | "version": "5.20.1", 1305 | "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.20.1.tgz", 1306 | "integrity": "sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==", 1307 | "dev": true, 1308 | "requires": { 1309 | "@babel/code-frame": "^7.0.0", 1310 | "builtin-modules": "^1.1.1", 1311 | "chalk": "^2.3.0", 1312 | "commander": "^2.12.1", 1313 | "diff": "^4.0.1", 1314 | "glob": "^7.1.1", 1315 | "js-yaml": "^3.13.1", 1316 | "minimatch": "^3.0.4", 1317 | "mkdirp": "^0.5.1", 1318 | "resolve": "^1.3.2", 1319 | "semver": "^5.3.0", 1320 | "tslib": "^1.8.0", 1321 | "tsutils": "^2.29.0" 1322 | }, 1323 | "dependencies": { 1324 | "commander": { 1325 | "version": "2.20.3", 1326 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", 1327 | "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", 1328 | "dev": true 1329 | } 1330 | } 1331 | }, 1332 | "tsutils": { 1333 | "version": "2.29.0", 1334 | "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", 1335 | "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", 1336 | "dev": true, 1337 | "requires": { 1338 | "tslib": "^1.8.1" 1339 | } 1340 | }, 1341 | "typescript": { 1342 | "version": "3.7.3", 1343 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.3.tgz", 1344 | "integrity": "sha512-Mcr/Qk7hXqFBXMN7p7Lusj1ktCBydylfQM/FZCk5glCNQJrCUKPkMHdo9R0MTFWsC/4kPFvDS0fDPvukfCkFsw==", 1345 | "dev": true 1346 | }, 1347 | "universalify": { 1348 | "version": "0.1.2", 1349 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", 1350 | "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" 1351 | }, 1352 | "util-deprecate": { 1353 | "version": "1.0.2", 1354 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1355 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 1356 | }, 1357 | "uuid": { 1358 | "version": "3.4.0", 1359 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", 1360 | "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" 1361 | }, 1362 | "winston": { 1363 | "version": "0.8.3", 1364 | "resolved": "https://registry.npmjs.org/winston/-/winston-0.8.3.tgz", 1365 | "integrity": "sha1-ZLar9M0Brcrv1QCTk7HY6L7BnbA=", 1366 | "requires": { 1367 | "async": "0.2.x", 1368 | "colors": "0.6.x", 1369 | "cycle": "1.0.x", 1370 | "eyes": "0.1.x", 1371 | "isstream": "0.1.x", 1372 | "pkginfo": "0.3.x", 1373 | "stack-trace": "0.0.x" 1374 | }, 1375 | "dependencies": { 1376 | "async": { 1377 | "version": "0.2.10", 1378 | "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", 1379 | "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=" 1380 | }, 1381 | "colors": { 1382 | "version": "0.6.2", 1383 | "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", 1384 | "integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=" 1385 | } 1386 | } 1387 | }, 1388 | "wrappy": { 1389 | "version": "1.0.2", 1390 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1391 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" 1392 | }, 1393 | "ws": { 1394 | "version": "7.4.0", 1395 | "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.0.tgz", 1396 | "integrity": "sha512-kyFwXuV/5ymf+IXhS6f0+eAFvydbaBW3zjpT6hUdAh/hbVjTIB5EHBGi0bPoCLSK2wcuz3BrEkB9LrYv1Nm4NQ==" 1397 | }, 1398 | "xmlhttprequest-ssl": { 1399 | "version": "1.5.5", 1400 | "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", 1401 | "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=" 1402 | }, 1403 | "xtend": { 1404 | "version": "4.0.2", 1405 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", 1406 | "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" 1407 | }, 1408 | "yeast": { 1409 | "version": "0.1.2", 1410 | "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", 1411 | "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=" 1412 | } 1413 | } 1414 | } 1415 | -------------------------------------------------------------------------------- /game-server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "guide", 3 | "version": "0.0.1", 4 | "private": false, 5 | "bin": { 6 | "$": "./dist/bin/app.js" 7 | }, 8 | "main": "./dist/app", 9 | "scripts": { 10 | "start": "npm run build && cd dist && node app", 11 | "build": "node_modules/.bin/tsc" 12 | }, 13 | "dependencies": { 14 | "@types/bluebird": "^3.5.19", 15 | "@types/node": "8.10.54", 16 | "bluebird": "^3.5.1", 17 | "crypto": "^1.0.1", 18 | "moment": "^2.29.1", 19 | "mysql": "^2.18.1", 20 | "pinus": "1.4.10", 21 | "redis": "^3.0.2", 22 | "redlock": "^4.2.0", 23 | "reflect-metadata": "^0.1.10", 24 | "source-map-support": "^0.5.0" 25 | }, 26 | "devDependencies": { 27 | "tslint": "5.20.1", 28 | "typescript": "3.7.3" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /game-server/preload.ts: -------------------------------------------------------------------------------- 1 | import { Promise } from 'bluebird'; 2 | // 支持注解 3 | import 'reflect-metadata'; 4 | import { pinus } from 'pinus'; 5 | 6 | /** 7 | * 替换全局Promise 8 | * 自动解析sourcemap 9 | * 捕获全局错误 10 | */ 11 | export function preload() { 12 | // 使用bluebird输出完整的promise调用链 13 | global.Promise = Promise; 14 | // 开启长堆栈 15 | Promise.config({ 16 | // Enable warnings 17 | warnings: true, 18 | // Enable long stack traces 19 | longStackTraces: true, 20 | // Enable cancellation 21 | cancellation: true, 22 | // Enable monitoring 23 | monitoring: true 24 | }); 25 | 26 | // 自动解析ts的sourcemap 27 | require('source-map-support').install({ 28 | handleUncaughtExceptions: false 29 | }); 30 | 31 | // 捕获普通异常 32 | process.on('uncaughtException', function (err) { 33 | console.error(pinus.app.getServerId(), 'uncaughtException Caught exception: ', err); 34 | }); 35 | 36 | // 捕获async异常 37 | process.on('unhandledRejection', (reason: any, p) => { 38 | console.error(pinus.app.getServerId(), 'Caught Unhandled Rejection at:', p, 'reason:', reason); 39 | }); 40 | } 41 | -------------------------------------------------------------------------------- /game-server/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | // types option has been previously configured 4 | "types": [ 5 | // add node as an option 6 | "node" 7 | ], 8 | "module": "commonjs", //指定生成哪个模块系统代码 9 | "target": "es2017", 10 | "lib": [ 11 | "es2015", 12 | "es2016", 13 | "es2017", 14 | "esnext.asynciterable" 15 | ], 16 | "noImplicitAny": false, //在表达式和声明上有隐含的'any'类型时报错。 17 | "noImplicitThis": false, 18 | "inlineSourceMap": true, 19 | 20 | 21 | "rootDirs": ["."], //仅用来控制输出的目录结构--outDir。 22 | "outDir":"./dist", //重定向输出目录。 23 | "experimentalDecorators":true, 24 | "emitDecoratorMetadata": true, 25 | "moduleResolution": "node", 26 | "watch":false //在监视模式下运行编译器。会监视输出文件,在它们改变时重新编译。 27 | }, 28 | "include":[ 29 | "./**/*.ts" 30 | ], 31 | "exclude": [ 32 | "./dist/**/*.*" 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /npm-install.bat: -------------------------------------------------------------------------------- 1 | ::npm-install.bat 2 | @echo off 3 | ::install web server dependencies && game server dependencies 4 | cd web-server && npm install -d && cd .. && cd game-server && npm install -d -------------------------------------------------------------------------------- /npm-install.sh: -------------------------------------------------------------------------------- 1 | cd ./game-server && npm install -d 2 | echo '============ game-server npm installed ============' 3 | cd .. 4 | cd ./web-server && npm install -d 5 | echo '============ web-server npm installed ============' 6 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | 这是pinus的简单示例工程,包含: 2 | 1、game-server,游戏服务器 3 | 2、web-server,网页客户端的服务 4 | 5 | 启动方法: 6 | 1、执行npm-install.bat或npm-install.sh 7 | 2、编译游戏服 8 | cd game-server 9 | npm run build 10 | 2、启动游戏服 11 | cd dist 12 | node app 13 | 显示“all servers startup in xxx ms”即表示启动成功 14 | 15 | 3、启动网页服务器 16 | cd web-server 17 | node app 18 | 显示“Please log on http://127.0.0.1:3001/index.html”即表示启动成功 19 | 20 | 4、进入客户端网页 21 | 浏览器输入 22 | http://127.0.0.1:3001/index.html 23 | 点击“Test Game Server”,如返回“game server is ok.”即表示连接游戏服务器返回成功 24 | 25 | 26 | 调试游戏服务器的方法: 27 | 1、安装vscode 28 | 2、在game-server目录启动vscode 29 | 3、按照正常流程启动游戏服 30 | 4、在“调试”界面,选择Attach To Connector或Attach To Master 31 | 5、按F5把调试器挂上去,然后就可以断点调试了。 -------------------------------------------------------------------------------- /shared/server.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICSzCCAbQCCQCQVN8rD6MylDANBgkqhkiG9w0BAQUFADBqMQswCQYDVQQGEwJD 3 | TjERMA8GA1UECAwIemhlamlhbmcxETAPBgNVBAcMCGhhbmd6aG91MRAwDgYDVQQK 4 | DAdOZXRFYXNlMQ8wDQYDVQQLDAZwb21lbG8xEjAQBgNVBAMMCWxvY2FsaG9zdDAe 5 | Fw0xNDA0MjIwNjEwMDJaFw0xNDA1MjIwNjEwMDJaMGoxCzAJBgNVBAYTAkNOMREw 6 | DwYDVQQIDAh6aGVqaWFuZzERMA8GA1UEBwwIaGFuZ3pob3UxEDAOBgNVBAoMB05l 7 | dEVhc2UxDzANBgNVBAsMBnBvbWVsbzESMBAGA1UEAwwJbG9jYWxob3N0MIGfMA0G 8 | CSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMPe8oscKpTlQFZRrpbWmSO1UE+H65nq50 9 | l5+ptOVPMK3wgEj+YRyGWhBjugj9teVmLXY9ImWdZkBlvdAiQj7/S/1MxRbRtwEF 10 | GRE5ul/X1M6I+F0UyTGYA1Mo0jIlQaBDXAAyDujCWi+qlyZ28efNDUlO2KBY1H4r 11 | Xobm9hoEFQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAMIuL8KqEEtjbfL/tR2+5dQ5 12 | 958gtDtA62L7bMosl4hmuzdyWADu3IcKSaXAESLhIuIClt2Pwc14iFf9qRyB/cjY 13 | 4kLgwDGhK5EJw1kQS+Hs9NNSGxJTXUkoms3kEdRGy4hrZpTheJJNaKuv3oXrdvYQ 14 | 85yoc/P5OnJapB3huYL9 15 | -----END CERTIFICATE----- -------------------------------------------------------------------------------- /shared/server.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIICWwIBAAKBgQDMPe8oscKpTlQFZRrpbWmSO1UE+H65nq50l5+ptOVPMK3wgEj+ 3 | YRyGWhBjugj9teVmLXY9ImWdZkBlvdAiQj7/S/1MxRbRtwEFGRE5ul/X1M6I+F0U 4 | yTGYA1Mo0jIlQaBDXAAyDujCWi+qlyZ28efNDUlO2KBY1H4rXobm9hoEFQIDAQAB 5 | AoGAXhaeCUIyqeoynLWh+yzzOHFqzjpnrr0iIwYCgJycEqobRzLh7YXxLRdqe3al 6 | U7Oq9TI2SR2CcEs9mWEi89VOzVvfu+4zRlvJLMzNjG8ncdvzmzWR288ORq6qmYVU 7 | 3KAEz/tbNaQMLrD43hkIb9BrSIb/cnwekl3pANo9dwytU5UCQQD4V6vTyzs/ob21 8 | +fO98tFkPtoHbt43S/1kDBSUyh6WWbS1KIQgtUSr2P5Ddtl6/vD3DW+XHCAhxyfV 9 | vuDvaP/fAkEA0oomFfmlpvzYejYNKPOz2PR+M0oRFVwn7lYyNwbRtUK1JYOMHwJ/ 10 | 3gwQEgAcYEkvgRlsxX0T5vHNmoR3U3OqiwJAIWkiG9devDvVWxMqoKZ3V0ZBbPiU 11 | etoFWB1r82yR2uZssmamCAR7HaeO5aKqtapw3rv3BFxrUkAJ8u7AMlVs/wJAVnpm 12 | MGqNjyyWIoSnHSYUvk2WtKx8neBvimcfUxja9HAFBfaljGszaFpeE3a2MRp+h7GQ 13 | ywGYNikmAYzdkoqVBwJAcOm/6u863pD2xA1mSFnmm3TulAMBfCULLdcY40w9m38b 14 | D89R1ISEy//N1fWa4KTsM0GpVOowEyluc53XNRUghw== 15 | -----END RSA PRIVATE KEY----- -------------------------------------------------------------------------------- /web-server/app.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var app = express(); 3 | 4 | app.use(express.methodOverride()); 5 | app.use(express.bodyParser()); 6 | app.use(app.router); 7 | app.set('view engine', 'jade'); 8 | app.set('views', __dirname + '/public'); 9 | app.set('view options', {layout: false}); 10 | app.set('basepath',__dirname + '/public'); 11 | 12 | let env = app.get('env'); 13 | if(env=="development"){ 14 | app.use(express.static(__dirname + '/public')); 15 | app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); 16 | } 17 | if(env == "production"){ 18 | var oneYear = 31557600000; 19 | app.use(express.static(__dirname + '/public', { maxAge: oneYear })); 20 | app.use(express.errorHandler()); 21 | } 22 | 23 | console.log("Web server has started.\nPlease log on http://127.0.0.1:3001/index.html"); 24 | 25 | app.listen(3001); 26 | -------------------------------------------------------------------------------- /web-server/bin/component.bat: -------------------------------------------------------------------------------- 1 | cd public/js/lib && component install -f && component build -v -------------------------------------------------------------------------------- /web-server/bin/component.sh: -------------------------------------------------------------------------------- 1 | cd public/js/lib && component install -f && component build -v -------------------------------------------------------------------------------- /web-server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "guide", 3 | "version": "0.0.1", 4 | "private": false, 5 | "dependencies": { 6 | "express": "3.4.8" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /web-server/public/css/base.css: -------------------------------------------------------------------------------- 1 | .g-doc { 2 | width: 1000px; 3 | margin: 0 auto; 4 | text-align: left; 5 | line-height: 18px; 6 | font-size: 12px; 7 | color: #555; 8 | font-family: arial; 9 | } 10 | 11 | .g-banner { 12 | position: relative; 13 | width: 1000px; 14 | height: 90px; 15 | margin: 0 auto; 16 | } 17 | 18 | .g-banner .logo { 19 | position: absolute; 20 | left: 20px; 21 | top: 13px; 22 | width: 153px; 23 | height: 60px; 24 | z-index: 101; 25 | } 26 | 27 | .g-banner .logo .img { 28 | width: 153px; 29 | height: 60px; 30 | background: url(../image/logo.png) no-repeat 0 0; 31 | } 32 | 33 | .g-background { 34 | height: 350px; 35 | background: url(../image/sp.png) no-repeat 326px 0; 36 | } 37 | 38 | .g-content { 39 | padding: 150px; 40 | width: 800px; 41 | margin-left: 50px; 42 | font-size: 50pt; 43 | font-style: italic; 44 | } 45 | 46 | .g-link { 47 | height: 100px; 48 | margin-top: 30px; 49 | margin-left: 300px; 50 | font-size: 15pt; 51 | } 52 | 53 | .g-button { 54 | margin-top: 10px; 55 | text-align: center; 56 | } 57 | 58 | a:link { 59 | color: #006699; 60 | text-decoration: none; 61 | } 62 | 63 | a:visited { 64 | color: #006699; 65 | text-decoration: none; 66 | } 67 | 68 | a:hover { 69 | color: #FF0000; 70 | text-decoration: underline; 71 | } 72 | 73 | a:active { 74 | color: #006699; 75 | text-decoration: underline; 76 | } 77 | -------------------------------------------------------------------------------- /web-server/public/image/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/verketh/guide/2be050fb52805e31fcf35ae7e58b07b0277f4678/web-server/public/image/logo.png -------------------------------------------------------------------------------- /web-server/public/image/sp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/verketh/guide/2be050fb52805e31fcf35ae7e58b07b0277f4678/web-server/public/image/sp.png -------------------------------------------------------------------------------- /web-server/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Pinus 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 19 | 35 | 36 | 37 |
38 |
39 | 42 |
43 |
44 |
45 | Welcome to Pinus 46 |
47 |
48 | 52 |
53 | 54 |
55 |
56 | 57 | 58 | -------------------------------------------------------------------------------- /web-server/public/js/lib/build/build.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | /** 4 | * hasOwnProperty. 5 | */ 6 | 7 | var has = Object.prototype.hasOwnProperty; 8 | 9 | /* Refer to https://github.com/componentjs/require/blob/master/lib/require.js */ 10 | /** 11 | * Require the given path. 12 | * 13 | * @param {String} path 14 | * @return {Object} exports 15 | * @api public 16 | */ 17 | 18 | function require(path, parent, orig) { 19 | var resolved = require.resolve(path); 20 | 21 | // lookup failed 22 | if (null == resolved) { 23 | orig = orig || path; 24 | parent = parent || 'root'; 25 | var err = new Error('Failed to require "' + orig + '" from "' + parent + '"'); 26 | err.path = orig; 27 | err.parent = parent; 28 | err.require = true; 29 | throw err; 30 | } 31 | 32 | var module = require.modules[resolved]; 33 | 34 | // perform real require() 35 | // by invoking the module's 36 | // registered function 37 | if (!module.exports) { 38 | module.exports = {}; 39 | module.client = module.component = true; 40 | module.call(this, module.exports, require.relative(resolved), module); 41 | } 42 | 43 | return module.exports; 44 | } 45 | 46 | /** 47 | * Registered modules. 48 | */ 49 | 50 | require.modules = {}; 51 | 52 | /** 53 | * Registered aliases. 54 | */ 55 | 56 | require.aliases = {}; 57 | 58 | /** 59 | * Resolve `path`. 60 | * 61 | * Lookup: 62 | * 63 | * - PATH/index.js 64 | * - PATH.js 65 | * - PATH 66 | * 67 | * @param {String} path 68 | * @return {String} path or null 69 | * @api private 70 | */ 71 | 72 | require.resolve = function(path) { 73 | if (path.charAt(0) === '/') path = path.slice(1); 74 | var index = path + '/index.js'; 75 | 76 | var paths = [ 77 | path, 78 | path + '.js', 79 | path + '.json', 80 | path + '/index.js', 81 | path + '/index.json' 82 | ]; 83 | 84 | for (var i = 0; i < paths.length; i++) { 85 | var path = paths[i]; 86 | if (has.call(require.modules, path)) return path; 87 | } 88 | 89 | if (has.call(require.aliases, index)) { 90 | return require.aliases[index]; 91 | } 92 | }; 93 | 94 | /** 95 | * Normalize `path` relative to the current path. 96 | * 97 | * @param {String} curr 98 | * @param {String} path 99 | * @return {String} 100 | * @api private 101 | */ 102 | 103 | require.normalize = function(curr, path) { 104 | var segs = []; 105 | 106 | if ('.' != path.charAt(0)) return path; 107 | 108 | curr = curr.split('/'); 109 | path = path.split('/'); 110 | 111 | for (var i = 0; i < path.length; ++i) { 112 | if ('..' == path[i]) { 113 | curr.pop(); 114 | } else if ('.' != path[i] && '' != path[i]) { 115 | segs.push(path[i]); 116 | } 117 | } 118 | 119 | return curr.concat(segs).join('/'); 120 | }; 121 | 122 | /** 123 | * Register module at `path` with callback `definition`. 124 | * 125 | * @param {String} path 126 | * @param {Function} definition 127 | * @api private 128 | */ 129 | 130 | require.register = function(path, definition) { 131 | require.modules[path] = definition; 132 | }; 133 | 134 | /** 135 | * Alias a module definition. 136 | * 137 | * @param {String} from 138 | * @param {String} to 139 | * @api private 140 | */ 141 | 142 | require.alias = function(from, to) { 143 | if (!has.call(require.modules, from)) { 144 | throw new Error('Failed to alias "' + from + '", it does not exist'); 145 | } 146 | require.aliases[to] = from; 147 | }; 148 | 149 | /** 150 | * Return a require function relative to the `parent` path. 151 | * 152 | * @param {String} parent 153 | * @return {Function} 154 | * @api private 155 | */ 156 | 157 | require.relative = function(parent) { 158 | var p = require.normalize(parent, '..'); 159 | 160 | /** 161 | * lastIndexOf helper. 162 | */ 163 | 164 | function lastIndexOf(arr, obj) { 165 | var i = arr.length; 166 | while (i--) { 167 | if (arr[i] === obj) return i; 168 | } 169 | return -1; 170 | } 171 | 172 | /** 173 | * The relative require() itself. 174 | */ 175 | 176 | function localRequire(path) { 177 | var resolved = localRequire.resolve(path); 178 | return require(resolved, parent, path); 179 | } 180 | 181 | /** 182 | * Resolve relative to the parent. 183 | */ 184 | 185 | localRequire.resolve = function(path) { 186 | var c = path.charAt(0); 187 | if ('/' == c) return path.slice(1); 188 | if ('.' == c) return require.normalize(p, path); 189 | 190 | // resolve deps by returning 191 | // the dep in the nearest "deps" 192 | // directory 193 | var segs = parent.split('/'); 194 | var i = lastIndexOf(segs, 'deps') + 1; 195 | if (!i) i = 0; 196 | path = segs.slice(0, i + 1).join('/') + '/deps/' + path; 197 | return path; 198 | }; 199 | 200 | /** 201 | * Check if module is defined at `path`. 202 | */ 203 | 204 | localRequire.exists = function(path) { 205 | return has.call(require.modules, localRequire.resolve(path)); 206 | }; 207 | 208 | return localRequire; 209 | }; 210 | require.register("component-indexof/index.js", function(exports, require, module){ 211 | 212 | var indexOf = [].indexOf; 213 | 214 | module.exports = function(arr, obj){ 215 | if (indexOf) return arr.indexOf(obj); 216 | for (var i = 0; i < arr.length; ++i) { 217 | if (arr[i] === obj) return i; 218 | } 219 | return -1; 220 | }; 221 | }); 222 | require.register("component-emitter/index.js", function(exports, require, module){ 223 | 224 | /** 225 | * Module dependencies. 226 | */ 227 | 228 | var index = require('indexof'); 229 | 230 | /** 231 | * Expose `Emitter`. 232 | */ 233 | 234 | module.exports = Emitter; 235 | 236 | /** 237 | * Initialize a new `Emitter`. 238 | * 239 | * @api public 240 | */ 241 | 242 | function Emitter(obj) { 243 | if (obj) return mixin(obj); 244 | }; 245 | 246 | /** 247 | * Mixin the emitter properties. 248 | * 249 | * @param {Object} obj 250 | * @return {Object} 251 | * @api private 252 | */ 253 | 254 | function mixin(obj) { 255 | for (var key in Emitter.prototype) { 256 | obj[key] = Emitter.prototype[key]; 257 | } 258 | return obj; 259 | } 260 | 261 | /** 262 | * Listen on the given `event` with `fn`. 263 | * 264 | * @param {String} event 265 | * @param {Function} fn 266 | * @return {Emitter} 267 | * @api public 268 | */ 269 | 270 | Emitter.prototype.on = function(event, fn){ 271 | this._callbacks = this._callbacks || {}; 272 | (this._callbacks[event] = this._callbacks[event] || []) 273 | .push(fn); 274 | return this; 275 | }; 276 | 277 | /** 278 | * Adds an `event` listener that will be invoked a single 279 | * time then automatically removed. 280 | * 281 | * @param {String} event 282 | * @param {Function} fn 283 | * @return {Emitter} 284 | * @api public 285 | */ 286 | 287 | Emitter.prototype.once = function(event, fn){ 288 | var self = this; 289 | this._callbacks = this._callbacks || {}; 290 | 291 | function on() { 292 | self.off(event, on); 293 | fn.apply(this, arguments); 294 | } 295 | 296 | fn._off = on; 297 | this.on(event, on); 298 | return this; 299 | }; 300 | 301 | /** 302 | * Remove the given callback for `event` or all 303 | * registered callbacks. 304 | * 305 | * @param {String} event 306 | * @param {Function} fn 307 | * @return {Emitter} 308 | * @api public 309 | */ 310 | 311 | Emitter.prototype.off = 312 | Emitter.prototype.removeListener = 313 | Emitter.prototype.removeAllListeners = function(event, fn){ 314 | this._callbacks = this._callbacks || {}; 315 | 316 | // all 317 | if (0 == arguments.length) { 318 | this._callbacks = {}; 319 | return this; 320 | } 321 | 322 | // specific event 323 | var callbacks = this._callbacks[event]; 324 | if (!callbacks) return this; 325 | 326 | // remove all handlers 327 | if (1 == arguments.length) { 328 | delete this._callbacks[event]; 329 | return this; 330 | } 331 | 332 | // remove specific handler 333 | var i = index(callbacks, fn._off || fn); 334 | if (~i) callbacks.splice(i, 1); 335 | return this; 336 | }; 337 | 338 | /** 339 | * Emit `event` with the given args. 340 | * 341 | * @param {String} event 342 | * @param {Mixed} ... 343 | * @return {Emitter} 344 | */ 345 | 346 | Emitter.prototype.emit = function(event){ 347 | this._callbacks = this._callbacks || {}; 348 | var args = [].slice.call(arguments, 1) 349 | , callbacks = this._callbacks[event]; 350 | 351 | if (callbacks) { 352 | callbacks = callbacks.slice(0); 353 | for (var i = 0, len = callbacks.length; i < len; ++i) { 354 | callbacks[i].apply(this, args); 355 | } 356 | } 357 | 358 | return this; 359 | }; 360 | 361 | /** 362 | * Return array of callbacks for `event`. 363 | * 364 | * @param {String} event 365 | * @return {Array} 366 | * @api public 367 | */ 368 | 369 | Emitter.prototype.listeners = function(event){ 370 | this._callbacks = this._callbacks || {}; 371 | return this._callbacks[event] || []; 372 | }; 373 | 374 | /** 375 | * Check if this emitter has `event` handlers. 376 | * 377 | * @param {String} event 378 | * @return {Boolean} 379 | * @api public 380 | */ 381 | 382 | Emitter.prototype.hasListeners = function(event){ 383 | return !! this.listeners(event).length; 384 | }; 385 | 386 | }); 387 | require.register("node-pinus-pinus-protocol/lib/protocol.js", function(exports, require, module){ 388 | (function (exports, ByteArray, global) { 389 | var Protocol = exports; 390 | 391 | var PKG_HEAD_BYTES = 4; 392 | var MSG_FLAG_BYTES = 1; 393 | var MSG_ROUTE_CODE_BYTES = 2; 394 | var MSG_ID_MAX_BYTES = 5; 395 | var MSG_ROUTE_LEN_BYTES = 1; 396 | 397 | var MSG_ROUTE_CODE_MAX = 0xffff; 398 | 399 | var MSG_COMPRESS_ROUTE_MASK = 0x1; 400 | var MSG_TYPE_MASK = 0x7; 401 | 402 | var Package = Protocol.Package = {}; 403 | var Message = Protocol.Message = {}; 404 | 405 | Package.TYPE_HANDSHAKE = 1; 406 | Package.TYPE_HANDSHAKE_ACK = 2; 407 | Package.TYPE_HEARTBEAT = 3; 408 | Package.TYPE_DATA = 4; 409 | Package.TYPE_KICK = 5; 410 | 411 | Message.TYPE_REQUEST = 0; 412 | Message.TYPE_NOTIFY = 1; 413 | Message.TYPE_RESPONSE = 2; 414 | Message.TYPE_PUSH = 3; 415 | 416 | /** 417 | * pomele client encode 418 | * id message id; 419 | * route message route 420 | * msg message body 421 | * socketio current support string 422 | */ 423 | Protocol.strencode = function(str) { 424 | var byteArray = new ByteArray(str.length * 3); 425 | var offset = 0; 426 | for(var i = 0; i < str.length; i++){ 427 | var charCode = str.charCodeAt(i); 428 | var codes = null; 429 | if(charCode <= 0x7f){ 430 | codes = [charCode]; 431 | }else if(charCode <= 0x7ff){ 432 | codes = [0xc0|(charCode>>6), 0x80|(charCode & 0x3f)]; 433 | }else{ 434 | codes = [0xe0|(charCode>>12), 0x80|((charCode & 0xfc0)>>6), 0x80|(charCode & 0x3f)]; 435 | } 436 | for(var j = 0; j < codes.length; j++){ 437 | byteArray[offset] = codes[j]; 438 | ++offset; 439 | } 440 | } 441 | var _buffer = new ByteArray(offset); 442 | copyArray(_buffer, 0, byteArray, 0, offset); 443 | return _buffer; 444 | }; 445 | 446 | /** 447 | * client decode 448 | * msg String data 449 | * return Message Object 450 | */ 451 | Protocol.strdecode = function(buffer) { 452 | var bytes = new ByteArray(buffer); 453 | var array = []; 454 | var offset = 0; 455 | var charCode = 0; 456 | var end = bytes.length; 457 | while(offset < end){ 458 | if(bytes[offset] < 128){ 459 | charCode = bytes[offset]; 460 | offset += 1; 461 | }else if(bytes[offset] < 224){ 462 | charCode = ((bytes[offset] & 0x3f)<<6) + (bytes[offset+1] & 0x3f); 463 | offset += 2; 464 | }else{ 465 | charCode = ((bytes[offset] & 0x0f)<<12) + ((bytes[offset+1] & 0x3f)<<6) + (bytes[offset+2] & 0x3f); 466 | offset += 3; 467 | } 468 | array.push(charCode); 469 | } 470 | var res = ''; 471 | var chunk = 8 * 1024; 472 | var i; 473 | for (i = 0; i < array.length / chunk; i++) { 474 | res += String.fromCharCode.apply(null, array.slice(i * chunk, (i + 1) * chunk)); 475 | } 476 | res += String.fromCharCode.apply(null, array.slice(i * chunk)); 477 | return res; 478 | }; 479 | 480 | /** 481 | * Package protocol encode. 482 | * 483 | * Pinus package format: 484 | * +------+-------------+------------------+ 485 | * | type | body length | body | 486 | * +------+-------------+------------------+ 487 | * 488 | * Head: 4bytes 489 | * 0: package type, 490 | * 1 - handshake, 491 | * 2 - handshake ack, 492 | * 3 - heartbeat, 493 | * 4 - data 494 | * 5 - kick 495 | * 1 - 3: big-endian body length 496 | * Body: body length bytes 497 | * 498 | * @param {Number} type package type 499 | * @param {ByteArray} body body content in bytes 500 | * @return {ByteArray} new byte array that contains encode result 501 | */ 502 | Package.encode = function(type, body){ 503 | var length = body ? body.length : 0; 504 | var buffer = new ByteArray(PKG_HEAD_BYTES + length); 505 | var index = 0; 506 | buffer[index++] = type & 0xff; 507 | buffer[index++] = (length >> 16) & 0xff; 508 | buffer[index++] = (length >> 8) & 0xff; 509 | buffer[index++] = length & 0xff; 510 | if(body) { 511 | copyArray(buffer, index, body, 0, length); 512 | } 513 | return buffer; 514 | }; 515 | 516 | /** 517 | * Package protocol decode. 518 | * See encode for package format. 519 | * 520 | * @param {ByteArray} buffer byte array containing package content 521 | * @return {Object} {type: package type, buffer: body byte array} 522 | */ 523 | Package.decode = function(buffer){ 524 | var bytes = new ByteArray(buffer); 525 | var type = bytes[0]; 526 | var index = 1; 527 | var length = ((bytes[index++]) << 16 | (bytes[index++]) << 8 | bytes[index++]) >>> 0; 528 | var body = length ? new ByteArray(length) : null; 529 | copyArray(body, 0, bytes, PKG_HEAD_BYTES, length); 530 | return {'type': type, 'body': body}; 531 | }; 532 | 533 | /** 534 | * Message protocol encode. 535 | * 536 | * @param {Number} id message id 537 | * @param {Number} type message type 538 | * @param {Number} compressRoute whether compress route 539 | * @param {Number|String} route route code or route string 540 | * @param {Buffer} msg message body bytes 541 | * @return {Buffer} encode result 542 | */ 543 | Message.encode = function(id, type, compressRoute, route, msg){ 544 | // caculate message max length 545 | var idBytes = msgHasId(type) ? caculateMsgIdBytes(id) : 0; 546 | var msgLen = MSG_FLAG_BYTES + idBytes; 547 | 548 | if(msgHasRoute(type)) { 549 | if(compressRoute) { 550 | if(typeof route !== 'number'){ 551 | throw new Error('error flag for number route!'); 552 | } 553 | msgLen += MSG_ROUTE_CODE_BYTES; 554 | } else { 555 | msgLen += MSG_ROUTE_LEN_BYTES; 556 | if(route) { 557 | route = Protocol.strencode(route); 558 | if(route.length>255) { 559 | throw new Error('route maxlength is overflow'); 560 | } 561 | msgLen += route.length; 562 | } 563 | } 564 | } 565 | 566 | if(msg) { 567 | msgLen += msg.length; 568 | } 569 | 570 | var buffer = new ByteArray(msgLen); 571 | var offset = 0; 572 | 573 | // add flag 574 | offset = encodeMsgFlag(type, compressRoute, buffer, offset); 575 | 576 | // add message id 577 | if(msgHasId(type)) { 578 | offset = encodeMsgId(id, idBytes, buffer, offset); 579 | } 580 | 581 | // add route 582 | if(msgHasRoute(type)) { 583 | offset = encodeMsgRoute(compressRoute, route, buffer, offset); 584 | } 585 | 586 | // add body 587 | if(msg) { 588 | offset = encodeMsgBody(msg, buffer, offset); 589 | } 590 | 591 | return buffer; 592 | }; 593 | 594 | /** 595 | * Message protocol decode. 596 | * 597 | * @param {Buffer|Uint8Array} buffer message bytes 598 | * @return {Object} message object 599 | */ 600 | Message.decode = function(buffer) { 601 | var bytes = new ByteArray(buffer); 602 | var bytesLen = bytes.length || bytes.byteLength; 603 | var offset = 0; 604 | var id = 0; 605 | var route = null; 606 | 607 | // parse flag 608 | var flag = bytes[offset++]; 609 | var compressRoute = flag & MSG_COMPRESS_ROUTE_MASK; 610 | var type = (flag >> 1) & MSG_TYPE_MASK; 611 | 612 | // parse id 613 | if(msgHasId(type)) { 614 | var byte = bytes[offset++]; 615 | id = byte & 0x7f; 616 | while(byte & 0x80) { 617 | id <<= 7; 618 | byte = bytes[offset++]; 619 | id |= byte & 0x7f; 620 | } 621 | } 622 | 623 | // parse route 624 | if(msgHasRoute(type)) { 625 | if(compressRoute) { 626 | route = (bytes[offset++]) << 8 | bytes[offset++]; 627 | } else { 628 | var routeLen = bytes[offset++]; 629 | if(routeLen) { 630 | route = new ByteArray(routeLen); 631 | copyArray(route, 0, bytes, offset, routeLen); 632 | route = Protocol.strdecode(route); 633 | } else { 634 | route = ''; 635 | } 636 | offset += routeLen; 637 | } 638 | } 639 | 640 | // parse body 641 | var bodyLen = bytesLen - offset; 642 | var body = new ByteArray(bodyLen); 643 | 644 | copyArray(body, 0, bytes, offset, bodyLen); 645 | 646 | return {'id': id, 'type': type, 'compressRoute': compressRoute, 647 | 'route': route, 'body': body}; 648 | }; 649 | 650 | var copyArray = function(dest, doffset, src, soffset, length) { 651 | if('function' === typeof src.copy) { 652 | // Buffer 653 | src.copy(dest, doffset, soffset, soffset + length); 654 | } else { 655 | // Uint8Array 656 | for(var index=0; index>= 7; 676 | } while(id > 0); 677 | return len; 678 | }; 679 | 680 | var encodeMsgFlag = function(type, compressRoute, buffer, offset) { 681 | if(type !== Message.TYPE_REQUEST && type !== Message.TYPE_NOTIFY && 682 | type !== Message.TYPE_RESPONSE && type !== Message.TYPE_PUSH) { 683 | throw new Error('unkonw message type: ' + type); 684 | } 685 | 686 | buffer[offset] = (type << 1) | (compressRoute ? 1 : 0); 687 | 688 | return offset + MSG_FLAG_BYTES; 689 | }; 690 | 691 | var encodeMsgId = function(id, idBytes, buffer, offset) { 692 | var index = offset + idBytes - 1; 693 | buffer[index--] = id & 0x7f; 694 | while(index >= offset) { 695 | id >>= 7; 696 | buffer[index--] = id & 0x7f | 0x80; 697 | } 698 | return offset + idBytes; 699 | }; 700 | 701 | var encodeMsgRoute = function(compressRoute, route, buffer, offset) { 702 | if (compressRoute) { 703 | if(route > MSG_ROUTE_CODE_MAX){ 704 | throw new Error('route number is overflow'); 705 | } 706 | 707 | buffer[offset++] = (route >> 8) & 0xff; 708 | buffer[offset++] = route & 0xff; 709 | } else { 710 | if(route) { 711 | buffer[offset++] = route.length & 0xff; 712 | copyArray(buffer, offset, route, 0, route.length); 713 | offset += route.length; 714 | } else { 715 | buffer[offset++] = 0; 716 | } 717 | } 718 | 719 | return offset; 720 | }; 721 | 722 | var encodeMsgBody = function(msg, buffer, offset) { 723 | copyArray(buffer, offset, msg, 0, msg.length); 724 | return offset + msg.length; 725 | }; 726 | 727 | module.exports = Protocol; 728 | })('object' === typeof module ? module.exports : (this.Protocol = {}),'object' === typeof module ? Buffer : Uint8Array, this); 729 | 730 | }); 731 | require.register("pinusnode-pinus-protobuf/lib/client/protobuf.js", function(exports, require, module){ 732 | /* ProtocolBuffer client 0.1.0*/ 733 | 734 | /** 735 | * pinus-protobuf 736 | * @author 737 | */ 738 | 739 | /** 740 | * Protocol buffer root 741 | * In browser, it will be window.protbuf 742 | */ 743 | (function (exports, global){ 744 | var Protobuf = exports; 745 | 746 | Protobuf.init = function(opts){ 747 | //On the serverside, use serverProtos to encode messages send to client 748 | Protobuf.encoder.init(opts.encoderProtos); 749 | 750 | //On the serverside, user clientProtos to decode messages receive from clients 751 | Protobuf.decoder.init(opts.decoderProtos); 752 | }; 753 | 754 | Protobuf.encode = function(key, msg){ 755 | return Protobuf.encoder.encode(key, msg); 756 | }; 757 | 758 | Protobuf.decode = function(key, msg){ 759 | return Protobuf.decoder.decode(key, msg); 760 | }; 761 | 762 | // exports to support for components 763 | module.exports = Protobuf; 764 | })('object' === typeof module ? module.exports : (this.protobuf = {}), this); 765 | 766 | /** 767 | * constants 768 | */ 769 | (function (exports, global){ 770 | var constants = exports.constants = {}; 771 | 772 | constants.TYPES = { 773 | uInt32 : 0, 774 | sInt32 : 0, 775 | int32 : 0, 776 | double : 1, 777 | string : 2, 778 | message : 2, 779 | float : 5 780 | }; 781 | 782 | })('undefined' !== typeof protobuf ? protobuf : module.exports, this); 783 | 784 | /** 785 | * util module 786 | */ 787 | (function (exports, global){ 788 | 789 | var Util = exports.util = {}; 790 | 791 | Util.isSimpleType = function(type){ 792 | return ( type === 'uInt32' || 793 | type === 'sInt32' || 794 | type === 'int32' || 795 | type === 'uInt64' || 796 | type === 'sInt64' || 797 | type === 'float' || 798 | type === 'double' ); 799 | }; 800 | 801 | })('undefined' !== typeof protobuf ? protobuf : module.exports, this); 802 | 803 | /** 804 | * codec module 805 | */ 806 | (function (exports, global){ 807 | 808 | var Codec = exports.codec = {}; 809 | 810 | var buffer = new ArrayBuffer(8); 811 | var float32Array = new Float32Array(buffer); 812 | var float64Array = new Float64Array(buffer); 813 | var uInt8Array = new Uint8Array(buffer); 814 | 815 | Codec.encodeUInt32 = function(n){ 816 | var n = parseInt(n); 817 | if(isNaN(n) || n < 0){ 818 | return null; 819 | } 820 | 821 | var result = []; 822 | do{ 823 | var tmp = n % 128; 824 | var next = Math.floor(n/128); 825 | 826 | if(next !== 0){ 827 | tmp = tmp + 128; 828 | } 829 | result.push(tmp); 830 | n = next; 831 | }while(n !== 0); 832 | 833 | return result; 834 | }; 835 | 836 | Codec.encodeSInt32 = function(n){ 837 | var n = parseInt(n); 838 | if(isNaN(n)){ 839 | return null; 840 | } 841 | n = n<0?(Math.abs(n)*2-1):n*2; 842 | 843 | return Codec.encodeUInt32(n); 844 | }; 845 | 846 | Codec.decodeUInt32 = function(bytes){ 847 | var n = 0; 848 | 849 | for(var i = 0; i < bytes.length; i++){ 850 | var m = parseInt(bytes[i]); 851 | n = n + ((m & 0x7f) * Math.pow(2,(7*i))); 852 | if(m < 128){ 853 | return n; 854 | } 855 | } 856 | 857 | return n; 858 | }; 859 | 860 | 861 | Codec.decodeSInt32 = function(bytes){ 862 | var n = this.decodeUInt32(bytes); 863 | var flag = ((n%2) === 1)?-1:1; 864 | 865 | n = ((n%2 + n)/2)*flag; 866 | 867 | return n; 868 | }; 869 | 870 | Codec.encodeFloat = function(float){ 871 | float32Array[0] = float; 872 | return uInt8Array; 873 | }; 874 | 875 | Codec.decodeFloat = function(bytes, offset){ 876 | if(!bytes || bytes.length < (offset +4)){ 877 | return null; 878 | } 879 | 880 | for(var i = 0; i < 4; i++){ 881 | uInt8Array[i] = bytes[offset + i]; 882 | } 883 | 884 | return float32Array[0]; 885 | }; 886 | 887 | Codec.encodeDouble = function(double){ 888 | float64Array[0] = double; 889 | return uInt8Array.subarray(0, 8); 890 | }; 891 | 892 | Codec.decodeDouble = function(bytes, offset){ 893 | if(!bytes || bytes.length < (8 + offset)){ 894 | return null; 895 | } 896 | 897 | for(var i = 0; i < 8; i++){ 898 | uInt8Array[i] = bytes[offset + i]; 899 | } 900 | 901 | return float64Array[0]; 902 | }; 903 | 904 | Codec.encodeStr = function(bytes, offset, str){ 905 | for(var i = 0; i < str.length; i++){ 906 | var code = str.charCodeAt(i); 907 | var codes = encode2UTF8(code); 908 | 909 | for(var j = 0; j < codes.length; j++){ 910 | bytes[offset] = codes[j]; 911 | offset++; 912 | } 913 | } 914 | 915 | return offset; 916 | }; 917 | 918 | /** 919 | * Decode string from utf8 bytes 920 | */ 921 | Codec.decodeStr = function(bytes, offset, length){ 922 | var array = []; 923 | var end = offset + length; 924 | 925 | while(offset < end){ 926 | var code = 0; 927 | 928 | if(bytes[offset] < 128){ 929 | code = bytes[offset]; 930 | 931 | offset += 1; 932 | }else if(bytes[offset] < 224){ 933 | code = ((bytes[offset] & 0x3f)<<6) + (bytes[offset+1] & 0x3f); 934 | offset += 2; 935 | }else{ 936 | code = ((bytes[offset] & 0x0f)<<12) + ((bytes[offset+1] & 0x3f)<<6) + (bytes[offset+2] & 0x3f); 937 | offset += 3; 938 | } 939 | 940 | array.push(code); 941 | 942 | } 943 | 944 | var str = ''; 945 | for(var i = 0; i < array.length;){ 946 | str += String.fromCharCode.apply(null, array.slice(i, i + 10000)); 947 | i += 10000; 948 | } 949 | 950 | return str; 951 | }; 952 | 953 | /** 954 | * Return the byte length of the str use utf8 955 | */ 956 | Codec.byteLength = function(str){ 957 | if(typeof(str) !== 'string'){ 958 | return -1; 959 | } 960 | 961 | var length = 0; 962 | 963 | for(var i = 0; i < str.length; i++){ 964 | var code = str.charCodeAt(i); 965 | length += codeLength(code); 966 | } 967 | 968 | return length; 969 | }; 970 | 971 | /** 972 | * Encode a unicode16 char code to utf8 bytes 973 | */ 974 | function encode2UTF8(charCode){ 975 | if(charCode <= 0x7f){ 976 | return [charCode]; 977 | }else if(charCode <= 0x7ff){ 978 | return [0xc0|(charCode>>6), 0x80|(charCode & 0x3f)]; 979 | }else{ 980 | return [0xe0|(charCode>>12), 0x80|((charCode & 0xfc0)>>6), 0x80|(charCode & 0x3f)]; 981 | } 982 | } 983 | 984 | function codeLength(code){ 985 | if(code <= 0x7f){ 986 | return 1; 987 | }else if(code <= 0x7ff){ 988 | return 2; 989 | }else{ 990 | return 3; 991 | } 992 | } 993 | })('undefined' !== typeof protobuf ? protobuf : module.exports, this); 994 | 995 | /** 996 | * encoder module 997 | */ 998 | (function (exports, global){ 999 | 1000 | var protobuf = exports; 1001 | var MsgEncoder = exports.encoder = {}; 1002 | 1003 | var codec = protobuf.codec; 1004 | var constant = protobuf.constants; 1005 | var util = protobuf.util; 1006 | 1007 | MsgEncoder.init = function(protos){ 1008 | this.protos = protos || {}; 1009 | }; 1010 | 1011 | MsgEncoder.encode = function(route, msg){ 1012 | //Get protos from protos map use the route as key 1013 | var protos = this.protos[route]; 1014 | 1015 | //Check msg 1016 | if(!checkMsg(msg, protos)){ 1017 | return null; 1018 | } 1019 | 1020 | //Set the length of the buffer 2 times bigger to prevent overflow 1021 | var length = codec.byteLength(JSON.stringify(msg)); 1022 | 1023 | //Init buffer and offset 1024 | var buffer = new ArrayBuffer(length); 1025 | var uInt8Array = new Uint8Array(buffer); 1026 | var offset = 0; 1027 | 1028 | if(!!protos){ 1029 | offset = encodeMsg(uInt8Array, offset, protos, msg); 1030 | if(offset > 0){ 1031 | return uInt8Array.subarray(0, offset); 1032 | } 1033 | } 1034 | 1035 | return null; 1036 | }; 1037 | 1038 | /** 1039 | * Check if the msg follow the defination in the protos 1040 | */ 1041 | function checkMsg(msg, protos){ 1042 | if(!protos){ 1043 | return false; 1044 | } 1045 | 1046 | for(var name in protos){ 1047 | var proto = protos[name]; 1048 | 1049 | //All required element must exist 1050 | switch(proto.option){ 1051 | case 'required' : 1052 | if(typeof(msg[name]) === 'undefined'){ 1053 | return false; 1054 | } 1055 | case 'optional' : 1056 | if(typeof(msg[name]) !== 'undefined'){ 1057 | if(!!protos.__messages[proto.type]){ 1058 | checkMsg(msg[name], protos.__messages[proto.type]); 1059 | } 1060 | } 1061 | break; 1062 | case 'repeated' : 1063 | //Check nest message in repeated elements 1064 | if(!!msg[name] && !!protos.__messages[proto.type]){ 1065 | for(var i = 0; i < msg[name].length; i++){ 1066 | if(!checkMsg(msg[name][i], protos.__messages[proto.type])){ 1067 | return false; 1068 | } 1069 | } 1070 | } 1071 | break; 1072 | } 1073 | } 1074 | 1075 | return true; 1076 | } 1077 | 1078 | function encodeMsg(buffer, offset, protos, msg){ 1079 | for(var name in msg){ 1080 | if(!!protos[name]){ 1081 | var proto = protos[name]; 1082 | 1083 | switch(proto.option){ 1084 | case 'required' : 1085 | case 'optional' : 1086 | offset = writeBytes(buffer, offset, encodeTag(proto.type, proto.tag)); 1087 | offset = encodeProp(msg[name], proto.type, offset, buffer, protos); 1088 | break; 1089 | case 'repeated' : 1090 | if(msg[name].length > 0){ 1091 | offset = encodeArray(msg[name], proto, offset, buffer, protos); 1092 | } 1093 | break; 1094 | } 1095 | } 1096 | } 1097 | 1098 | return offset; 1099 | } 1100 | 1101 | function encodeProp(value, type, offset, buffer, protos){ 1102 | switch(type){ 1103 | case 'uInt32': 1104 | offset = writeBytes(buffer, offset, codec.encodeUInt32(value)); 1105 | break; 1106 | case 'int32' : 1107 | case 'sInt32': 1108 | offset = writeBytes(buffer, offset, codec.encodeSInt32(value)); 1109 | break; 1110 | case 'float': 1111 | writeBytes(buffer, offset, codec.encodeFloat(value)); 1112 | offset += 4; 1113 | break; 1114 | case 'double': 1115 | writeBytes(buffer, offset, codec.encodeDouble(value)); 1116 | offset += 8; 1117 | break; 1118 | case 'string': 1119 | var length = codec.byteLength(value); 1120 | 1121 | //Encode length 1122 | offset = writeBytes(buffer, offset, codec.encodeUInt32(length)); 1123 | //write string 1124 | codec.encodeStr(buffer, offset, value); 1125 | offset += length; 1126 | break; 1127 | default : 1128 | if(!!protos.__messages[type]){ 1129 | //Use a tmp buffer to build an internal msg 1130 | var tmpBuffer = new ArrayBuffer(codec.byteLength(JSON.stringify(value))); 1131 | var length = 0; 1132 | 1133 | length = encodeMsg(tmpBuffer, length, protos.__messages[type], value); 1134 | //Encode length 1135 | offset = writeBytes(buffer, offset, codec.encodeUInt32(length)); 1136 | //contact the object 1137 | for(var i = 0; i < length; i++){ 1138 | buffer[offset] = tmpBuffer[i]; 1139 | offset++; 1140 | } 1141 | } 1142 | break; 1143 | } 1144 | 1145 | return offset; 1146 | } 1147 | 1148 | /** 1149 | * Encode reapeated properties, simple msg and object are decode differented 1150 | */ 1151 | function encodeArray(array, proto, offset, buffer, protos){ 1152 | var i = 0; 1153 | 1154 | if(util.isSimpleType(proto.type)){ 1155 | offset = writeBytes(buffer, offset, encodeTag(proto.type, proto.tag)); 1156 | offset = writeBytes(buffer, offset, codec.encodeUInt32(array.length)); 1157 | for(i = 0; i < array.length; i++){ 1158 | offset = encodeProp(array[i], proto.type, offset, buffer); 1159 | } 1160 | }else{ 1161 | for(i = 0; i < array.length; i++){ 1162 | offset = writeBytes(buffer, offset, encodeTag(proto.type, proto.tag)); 1163 | offset = encodeProp(array[i], proto.type, offset, buffer, protos); 1164 | } 1165 | } 1166 | 1167 | return offset; 1168 | } 1169 | 1170 | function writeBytes(buffer, offset, bytes){ 1171 | for(var i = 0; i < bytes.length; i++, offset++){ 1172 | buffer[offset] = bytes[i]; 1173 | } 1174 | 1175 | return offset; 1176 | } 1177 | 1178 | function encodeTag(type, tag){ 1179 | var value = constant.TYPES[type]||2; 1180 | return codec.encodeUInt32((tag<<3)|value); 1181 | } 1182 | })('undefined' !== typeof protobuf ? protobuf : module.exports, this); 1183 | 1184 | /** 1185 | * decoder module 1186 | */ 1187 | (function (exports, global){ 1188 | var protobuf = exports; 1189 | var MsgDecoder = exports.decoder = {}; 1190 | 1191 | var codec = protobuf.codec; 1192 | var util = protobuf.util; 1193 | 1194 | var buffer; 1195 | var offset = 0; 1196 | 1197 | MsgDecoder.init = function(protos){ 1198 | this.protos = protos || {}; 1199 | }; 1200 | 1201 | MsgDecoder.setProtos = function(protos){ 1202 | if(!!protos){ 1203 | this.protos = protos; 1204 | } 1205 | }; 1206 | 1207 | MsgDecoder.decode = function(route, buf){ 1208 | var protos = this.protos[route]; 1209 | 1210 | buffer = buf; 1211 | offset = 0; 1212 | 1213 | if(!!protos){ 1214 | return decodeMsg({}, protos, buffer.length); 1215 | } 1216 | 1217 | return null; 1218 | }; 1219 | 1220 | function decodeMsg(msg, protos, length){ 1221 | while(offset>3 1259 | }; 1260 | } 1261 | 1262 | /** 1263 | * Get tag head without move the offset 1264 | */ 1265 | function peekHead(){ 1266 | var tag = codec.decodeUInt32(peekBytes()); 1267 | 1268 | return { 1269 | type : tag&0x7, 1270 | tag : tag>>3 1271 | }; 1272 | } 1273 | 1274 | function decodeProp(type, protos){ 1275 | switch(type){ 1276 | case 'uInt32': 1277 | return codec.decodeUInt32(getBytes()); 1278 | case 'int32' : 1279 | case 'sInt32' : 1280 | return codec.decodeSInt32(getBytes()); 1281 | case 'float' : 1282 | var float = codec.decodeFloat(buffer, offset); 1283 | offset += 4; 1284 | return float; 1285 | case 'double' : 1286 | var double = codec.decodeDouble(buffer, offset); 1287 | offset += 8; 1288 | return double; 1289 | case 'string' : 1290 | var length = codec.decodeUInt32(getBytes()); 1291 | 1292 | var str = codec.decodeStr(buffer, offset, length); 1293 | offset += length; 1294 | 1295 | return str; 1296 | default : 1297 | if(!!protos && !!protos.__messages[type]){ 1298 | var length = codec.decodeUInt32(getBytes()); 1299 | var msg = {}; 1300 | decodeMsg(msg, protos.__messages[type], offset+length); 1301 | return msg; 1302 | } 1303 | break; 1304 | } 1305 | } 1306 | 1307 | function decodeArray(array, type, protos){ 1308 | if(util.isSimpleType(type)){ 1309 | var length = codec.decodeUInt32(getBytes()); 1310 | 1311 | for(var i = 0; i < length; i++){ 1312 | array.push(decodeProp(type)); 1313 | } 1314 | }else{ 1315 | array.push(decodeProp(type, protos)); 1316 | } 1317 | } 1318 | 1319 | function getBytes(flag){ 1320 | var bytes = []; 1321 | var pos = offset; 1322 | flag = flag || false; 1323 | 1324 | var b; 1325 | 1326 | do{ 1327 | b = buffer[pos]; 1328 | bytes.push(b); 1329 | pos++; 1330 | }while(b >= 128); 1331 | 1332 | if(!flag){ 1333 | offset = pos; 1334 | } 1335 | return bytes; 1336 | } 1337 | 1338 | function peekBytes(){ 1339 | return getBytes(true); 1340 | } 1341 | 1342 | })('undefined' !== typeof protobuf ? protobuf : module.exports, this); 1343 | 1344 | 1345 | }); 1346 | require.register("pinusnode-pinus-jsclient-websocket/lib/pinus-client.js", function(exports, require, module){ 1347 | (function() { 1348 | var JS_WS_CLIENT_TYPE = 'js-websocket'; 1349 | var JS_WS_CLIENT_VERSION = '0.0.1'; 1350 | 1351 | var Protocol = window.Protocol; 1352 | var Package = Protocol.Package; 1353 | var Message = Protocol.Message; 1354 | var EventEmitter = window.EventEmitter; 1355 | 1356 | var RES_OK = 200; 1357 | var RES_FAIL = 500; 1358 | var RES_OLD_CLIENT = 501; 1359 | 1360 | if (typeof Object.create !== 'function') { 1361 | Object.create = function (o) { 1362 | function F() {} 1363 | F.prototype = o; 1364 | return new F(); 1365 | }; 1366 | } 1367 | 1368 | var root = window; 1369 | var pinus = Object.create(EventEmitter.prototype); // object extend from object 1370 | root.pinus = pinus; 1371 | var socket = null; 1372 | var reqId = 0; 1373 | var callbacks = {}; 1374 | var handlers = {}; 1375 | //Map from request id to route 1376 | var routeMap = {}; 1377 | 1378 | var heartbeatInterval = 0; 1379 | var heartbeatTimeout = 0; 1380 | var nextHeartbeatTimeout = 0; 1381 | var gapThreshold = 100; // heartbeat gap threashold 1382 | var heartbeatId = null; 1383 | var heartbeatTimeoutId = null; 1384 | 1385 | var handshakeCallback = null; 1386 | 1387 | var handshakeBuffer = { 1388 | 'sys': { 1389 | type: JS_WS_CLIENT_TYPE, 1390 | version: JS_WS_CLIENT_VERSION 1391 | }, 1392 | 'user': { 1393 | } 1394 | }; 1395 | 1396 | var initCallback = null; 1397 | 1398 | pinus.init = function(params, cb){ 1399 | initCallback = cb; 1400 | var host = params.host; 1401 | var port = params.port; 1402 | 1403 | var url = 'ws://' + host; 1404 | if(port) { 1405 | url += ':' + port; 1406 | } 1407 | 1408 | handshakeBuffer.user = params.user; 1409 | handshakeCallback = params.handshakeCallback; 1410 | initWebSocket(url, cb); 1411 | }; 1412 | 1413 | var initWebSocket = function(url,cb) { 1414 | console.log('connect to ' + url); 1415 | var onopen = function(event){ 1416 | var obj = Package.encode(Package.TYPE_HANDSHAKE, Protocol.strencode(JSON.stringify(handshakeBuffer))); 1417 | send(obj); 1418 | }; 1419 | var onmessage = function(event) { 1420 | processPackage(Package.decode(event.data), cb); 1421 | // new package arrived, update the heartbeat timeout 1422 | if(heartbeatTimeout) { 1423 | nextHeartbeatTimeout = Date.now() + heartbeatTimeout; 1424 | } 1425 | }; 1426 | var onerror = function(event) { 1427 | pinus.emit('io-error', event); 1428 | console.error('socket error: ', event); 1429 | }; 1430 | var onclose = function(event){ 1431 | pinus.emit('close',event); 1432 | console.error('socket close: ', event); 1433 | }; 1434 | socket = new WebSocket(url); 1435 | socket.binaryType = 'arraybuffer'; 1436 | socket.onopen = onopen; 1437 | socket.onmessage = onmessage; 1438 | socket.onerror = onerror; 1439 | socket.onclose = onclose; 1440 | }; 1441 | 1442 | pinus.disconnect = function() { 1443 | if(socket) { 1444 | if(socket.disconnect) socket.disconnect(); 1445 | if(socket.close) socket.close(); 1446 | console.log('disconnect'); 1447 | socket = null; 1448 | } 1449 | 1450 | if(heartbeatId) { 1451 | clearTimeout(heartbeatId); 1452 | heartbeatId = null; 1453 | } 1454 | if(heartbeatTimeoutId) { 1455 | clearTimeout(heartbeatTimeoutId); 1456 | heartbeatTimeoutId = null; 1457 | } 1458 | }; 1459 | 1460 | pinus.request = function(route, msg, cb) { 1461 | if(arguments.length === 2 && typeof msg === 'function') { 1462 | cb = msg; 1463 | msg = {}; 1464 | } else { 1465 | msg = msg || {}; 1466 | } 1467 | route = route || msg.route; 1468 | if(!route) { 1469 | return; 1470 | } 1471 | 1472 | reqId++; 1473 | sendMessage(reqId, route, msg); 1474 | 1475 | callbacks[reqId] = cb; 1476 | routeMap[reqId] = route; 1477 | }; 1478 | 1479 | pinus.notify = function(route, msg) { 1480 | msg = msg || {}; 1481 | sendMessage(0, route, msg); 1482 | }; 1483 | 1484 | var sendMessage = function(reqId, route, msg) { 1485 | var type = reqId ? Message.TYPE_REQUEST : Message.TYPE_NOTIFY; 1486 | 1487 | //compress message by protobuf 1488 | var protos = !!pinus.data.protos?pinus.data.protos.client:{}; 1489 | if(!!protos[route]){ 1490 | msg = protobuf.encode(route, msg); 1491 | }else{ 1492 | msg = Protocol.strencode(JSON.stringify(msg)); 1493 | } 1494 | 1495 | 1496 | var compressRoute = 0; 1497 | if(pinus.dict && pinus.dict[route]){ 1498 | route = pinus.dict[route]; 1499 | compressRoute = 1; 1500 | } 1501 | 1502 | msg = Message.encode(reqId, type, compressRoute, route, msg); 1503 | var packet = Package.encode(Package.TYPE_DATA, msg); 1504 | send(packet); 1505 | }; 1506 | 1507 | var send = function(packet){ 1508 | socket.send(packet.buffer); 1509 | }; 1510 | 1511 | 1512 | var handler = {}; 1513 | 1514 | var heartbeat = function(data) { 1515 | if(!heartbeatInterval) { 1516 | // no heartbeat 1517 | return; 1518 | } 1519 | 1520 | var obj = Package.encode(Package.TYPE_HEARTBEAT); 1521 | if(heartbeatTimeoutId) { 1522 | clearTimeout(heartbeatTimeoutId); 1523 | heartbeatTimeoutId = null; 1524 | } 1525 | 1526 | if(heartbeatId) { 1527 | // already in a heartbeat interval 1528 | return; 1529 | } 1530 | 1531 | heartbeatId = setTimeout(function() { 1532 | heartbeatId = null; 1533 | send(obj); 1534 | 1535 | nextHeartbeatTimeout = Date.now() + heartbeatTimeout; 1536 | heartbeatTimeoutId = setTimeout(heartbeatTimeoutCb, heartbeatTimeout); 1537 | }, heartbeatInterval); 1538 | }; 1539 | 1540 | var heartbeatTimeoutCb = function() { 1541 | var gap = nextHeartbeatTimeout - Date.now(); 1542 | if(gap > gapThreshold) { 1543 | heartbeatTimeoutId = setTimeout(heartbeatTimeoutCb, gap); 1544 | } else { 1545 | console.error('server heartbeat timeout'); 1546 | pinus.emit('heartbeat timeout'); 1547 | pinus.disconnect(); 1548 | } 1549 | }; 1550 | 1551 | var handshake = function(data){ 1552 | data = JSON.parse(Protocol.strdecode(data)); 1553 | if(data.code === RES_OLD_CLIENT) { 1554 | pinus.emit('error', 'client version not fullfill'); 1555 | return; 1556 | } 1557 | 1558 | if(data.code !== RES_OK) { 1559 | pinus.emit('error', 'handshake fail'); 1560 | return; 1561 | } 1562 | 1563 | handshakeInit(data); 1564 | 1565 | var obj = Package.encode(Package.TYPE_HANDSHAKE_ACK); 1566 | send(obj); 1567 | if(initCallback) { 1568 | initCallback(socket); 1569 | initCallback = null; 1570 | } 1571 | }; 1572 | 1573 | var onData = function(data){ 1574 | //probuff decode 1575 | var msg = Message.decode(data); 1576 | 1577 | if(msg.id > 0){ 1578 | msg.route = routeMap[msg.id]; 1579 | delete routeMap[msg.id]; 1580 | if(!msg.route){ 1581 | return; 1582 | } 1583 | } 1584 | 1585 | msg.body = deCompose(msg); 1586 | 1587 | processMessage(pinus, msg); 1588 | }; 1589 | 1590 | var onKick = function(data) { 1591 | pinus.emit('onKick'); 1592 | }; 1593 | 1594 | handlers[Package.TYPE_HANDSHAKE] = handshake; 1595 | handlers[Package.TYPE_HEARTBEAT] = heartbeat; 1596 | handlers[Package.TYPE_DATA] = onData; 1597 | handlers[Package.TYPE_KICK] = onKick; 1598 | 1599 | var processPackage = function(msg) { 1600 | handlers[msg.type](msg.body); 1601 | }; 1602 | 1603 | var processMessage = function(pinus, msg) { 1604 | if(!msg.id) { 1605 | // server push message 1606 | pinus.emit(msg.route, msg.body); 1607 | return; 1608 | } 1609 | 1610 | //if have a id then find the callback function with the request 1611 | var cb = callbacks[msg.id]; 1612 | 1613 | delete callbacks[msg.id]; 1614 | if(typeof cb !== 'function') { 1615 | return; 1616 | } 1617 | 1618 | cb(msg.body); 1619 | return; 1620 | }; 1621 | 1622 | var processMessageBatch = function(pinus, msgs) { 1623 | for(var i=0, l=msgs.length; i