├── .DS_Store ├── .gitignore ├── LICENSE ├── README.md ├── bin ├── .DS_Store ├── chat │ ├── .DS_Store │ ├── index.html │ ├── js │ │ ├── client.js │ │ ├── lib │ │ │ ├── jquery-1.8.0.min.js │ │ │ ├── mqantlib.js │ │ │ └── mqttws31.js │ │ └── pop.js │ └── style.css ├── conf │ └── server.json ├── console │ ├── index.html │ └── js │ │ ├── lib │ │ ├── jquery-1.8.0.min.js │ │ ├── mqantlib.js │ │ ├── mqttws31.js │ │ └── vue.js │ │ └── main.js └── hitball │ ├── assets │ ├── arrow.png │ ├── ball.png │ ├── coin.png │ ├── deadly.png │ ├── tilemaps │ │ ├── desert.json │ │ └── tmw_desert_spacing.png │ └── virtualjoystick │ │ └── skins │ │ ├── arcade-joystick.json │ │ ├── arcade-joystick.png │ │ ├── generic-joystick.json │ │ └── generic-joystick.png │ ├── index.html │ ├── js │ ├── lib │ │ ├── MyScaleManager.js │ │ ├── inherits.js │ │ ├── mqantlib.js │ │ ├── mqttws31.js │ │ ├── phaser-compat-2.4.js │ │ ├── phaser.min.js │ │ ├── phaser2.6.2.js │ │ └── phaser_plugins │ │ │ ├── AStar │ │ │ └── AStar.js │ │ │ ├── CSS3Filters │ │ │ └── CSS3Filters.js │ │ │ ├── ColorHarmony │ │ │ └── ColorHarmony.js │ │ │ ├── Juicy │ │ │ └── Juicy.js │ │ │ ├── KineticScrolling │ │ │ └── KineticScrolling.js │ │ │ ├── ProTracker │ │ │ └── ProTracker.js │ │ │ ├── README.md │ │ │ ├── SamplePlugin │ │ │ └── SamplePlugin.js │ │ │ ├── SaveCPU │ │ │ └── SaveCPU.js │ │ │ ├── ScreenShake │ │ │ └── ScreenShake.js │ │ │ ├── TilemapWalker │ │ │ └── TilemapWalker.js │ │ │ ├── VirtualJoystick │ │ │ └── VirtualJoystick.js │ │ │ ├── Webcam │ │ │ └── Webcam.js │ │ │ └── YM │ │ │ └── YM.js │ ├── main.js │ └── main.js.map │ ├── package.json │ └── webpack.config.js ├── client ├── __init__.py ├── caextract.pem └── mqtt_chat_client.py ├── clientlib ├── mqantlib.js └── paho-mqtt.js ├── example └── helloworld.go ├── go.mod ├── go.sum ├── robot ├── xaba │ ├── caextract.pem │ ├── manager.go │ └── work.go └── xaba_task.go ├── server ├── chat │ ├── RPCListener.go │ └── module.go ├── gate │ ├── CustomAgent.go │ └── module.go ├── helloworld │ └── module.go ├── hitball │ ├── base_room.go │ ├── base_table.go │ ├── module.go │ ├── objects │ │ ├── coins.go │ │ └── player.go │ ├── table.go │ └── table_test.go ├── login │ └── module.go ├── main.go ├── user │ ├── module.go │ └── module_test.go └── xaxb │ ├── action.go │ ├── fsm.go │ ├── logic.go │ ├── module.go │ ├── notify.go │ ├── objects │ └── player.go │ └── table.go ├── static ├── .DS_Store └── hitball │ ├── .DS_Store │ ├── assets │ ├── arrow.png │ ├── ball.png │ ├── coin.png │ ├── deadly.png │ ├── fonts │ │ ├── Skranji-Bold-40.fnt │ │ ├── Skranji-Bold-40.png │ │ ├── desyrel.fnt │ │ └── desyrel.png │ ├── img │ │ ├── bomb1-selected.png │ │ ├── bomb1.png │ │ ├── bomb2-selected.png │ │ ├── bomb2.png │ │ ├── bomb3-selected.png │ │ ├── bomb3.png │ │ ├── level-box.png │ │ ├── lvlcomplete.png │ │ ├── orange-btn.png │ │ ├── panel-650x400.png │ │ └── star2.png │ ├── kenney-theme │ │ ├── images │ │ │ ├── bg.png │ │ │ ├── btn-blue-bg-down.png │ │ │ ├── btn-blue-bg.png │ │ │ ├── btn-blue-corner-bl-down.png │ │ │ ├── btn-blue-corner-bl.png │ │ │ ├── btn-blue-corner-br-down.png │ │ │ ├── btn-blue-corner-br.png │ │ │ ├── btn-blue-corner-tl-down.png │ │ │ ├── btn-blue-corner-tl.png │ │ │ ├── btn-blue-corner-tr-down.png │ │ │ ├── btn-blue-corner-tr.png │ │ │ ├── btn-blue-line-b-down.png │ │ │ ├── btn-blue-line-b.png │ │ │ ├── btn-blue-line-l-down.png │ │ │ ├── btn-blue-line-l.png │ │ │ ├── btn-blue-line-r-down.png │ │ │ ├── btn-blue-line-r.png │ │ │ ├── btn-blue-line-t-down.png │ │ │ ├── btn-blue-line-t.png │ │ │ ├── btn-grey-bg-down.png │ │ │ ├── btn-grey-bg.png │ │ │ ├── btn-grey-corner-bl-down.png │ │ │ ├── btn-grey-corner-bl.png │ │ │ ├── btn-grey-corner-br-down.png │ │ │ ├── btn-grey-corner-br.png │ │ │ ├── btn-grey-corner-tl-down.png │ │ │ ├── btn-grey-corner-tl.png │ │ │ ├── btn-grey-corner-tr-down.png │ │ │ ├── btn-grey-corner-tr.png │ │ │ ├── btn-grey-line-b-down.png │ │ │ ├── btn-grey-line-b.png │ │ │ ├── btn-grey-line-l-down.png │ │ │ ├── btn-grey-line-l.png │ │ │ ├── btn-grey-line-r-down.png │ │ │ ├── btn-grey-line-r.png │ │ │ ├── btn-grey-line-t-down.png │ │ │ ├── btn-grey-line-t.png │ │ │ ├── chk-blue-checkmark.png │ │ │ ├── chk-grey-checkmark.png │ │ │ ├── chk-grey-corner.png │ │ │ ├── down-grey-slide-down.png │ │ │ ├── down-grey-slide.png │ │ │ ├── radio-blue-check.png │ │ │ ├── radio-grey-check.png │ │ │ ├── sld-grey-bg.png │ │ │ ├── sld-grey-corner.png │ │ │ ├── sld-grey-line.png │ │ │ ├── wnd-grey-bg.png │ │ │ ├── wnd-grey-corner.png │ │ │ └── wnd-grey-line.png │ │ ├── kenney-atlas.json │ │ ├── kenney-theme.json │ │ ├── kenney-theme.png │ │ └── theme.tps │ ├── metalworks-theme │ │ ├── feathers-metal-works-desktop-theme.png │ │ ├── images │ │ │ ├── bg-down.png │ │ │ ├── bg.png │ │ │ ├── btn-bg-down.png │ │ │ ├── btn-bg.png │ │ │ ├── btn-corner.png │ │ │ ├── btn-line.png │ │ │ ├── chk-checkmark.png │ │ │ ├── corner.png │ │ │ ├── darkcnt-corner.png │ │ │ ├── darkcnt-line.png │ │ │ ├── header-bg.png │ │ │ ├── line.png │ │ │ └── radio-checkmark.png │ │ └── metalworks-theme.json │ ├── tilemaps │ │ ├── desert.json │ │ └── tmw_desert_spacing.png │ └── virtualjoystick │ │ └── skins │ │ ├── arcade-joystick.json │ │ ├── arcade-joystick.png │ │ ├── generic-joystick.json │ │ └── generic-joystick.png │ ├── index.html │ ├── js │ ├── .DS_Store │ ├── lib │ │ ├── mqantlib.js │ │ ├── mqttws31.js │ │ ├── phaser.min.js │ │ ├── phaser2.6.2.js │ │ └── phaser_plugins │ │ │ ├── AStar │ │ │ └── AStar.js │ │ │ ├── CSS3Filters │ │ │ └── CSS3Filters.js │ │ │ ├── ColorHarmony │ │ │ └── ColorHarmony.js │ │ │ ├── Juicy │ │ │ └── Juicy.js │ │ │ ├── KineticScrolling │ │ │ └── KineticScrolling.js │ │ │ ├── ProTracker │ │ │ └── ProTracker.js │ │ │ ├── README.md │ │ │ ├── SamplePlugin │ │ │ └── SamplePlugin.js │ │ │ ├── SaveCPU │ │ │ └── SaveCPU.js │ │ │ ├── ScreenShake │ │ │ └── ScreenShake.js │ │ │ ├── TilemapWalker │ │ │ └── TilemapWalker.js │ │ │ ├── VirtualJoystick │ │ │ └── VirtualJoystick.js │ │ │ ├── Webcam │ │ │ └── Webcam.js │ │ │ └── YM │ │ │ └── YM.js │ ├── main.js │ └── main.js.map │ ├── package.json │ ├── src │ ├── .DS_Store │ ├── gui │ │ └── login.js │ ├── main.bak.js │ ├── main.js │ ├── maps │ │ ├── DesertMap.js │ │ └── GameMap.js │ ├── objects │ │ ├── Bullet.js │ │ ├── Coin.js │ │ ├── Enemy.js │ │ ├── Player.js │ │ └── Role.js │ ├── states │ │ ├── BootState.js │ │ └── PlayGameState.js │ └── utils │ │ ├── MyScaleManager.js │ │ ├── inherits.js │ │ └── list.js │ └── webpack.config.js └── webapp └── module.go /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | .idea 3 | bin/logs 4 | bin/sslkey 5 | bin/server 6 | bin/client 7 | #src/hitball 8 | #src/server/hitball 9 | src/gopkg.in 10 | src/github.com/quick-know-master 11 | pkg 12 | node_modules 13 | *.o 14 | *.a 15 | *.so 16 | *.iml 17 | projectFilesBackup 18 | 19 | # Folders 20 | _obj 21 | _test 22 | 23 | # Architecture specific extensions/prefixes 24 | *.[568vq] 25 | [568vq].out 26 | 27 | *.cgo1.go 28 | *.cgo2.c 29 | _cgo_defun.c 30 | _cgo_gotypes.go 31 | _cgo_export.* 32 | 33 | _testmain.go 34 | 35 | *.exe 36 | *.test 37 | *.prof 38 | 39 | server.conf.bat 40 | 41 | 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 快速使用 2 | 获取 mqantserver: 3 | 4 | git clone https://github.com/liangdas/mqantserver 5 | 6 | # mqant 2x开始支持分布式服务发现 7 | 8 | [请务必先查看2x跟1x版本差异](https://github.com/liangdas/mqant/wiki/mqant%E6%9C%8D%E5%8A%A1%E5%8F%91%E7%8E%B0%E6%A6%82%E8%BF%B0) 9 | 10 | ## 依赖组件 11 | 12 | 必须启动的组件有 13 | 14 | 1. consul 15 | 16 | consul agent --dev 17 | 18 | 2. nats 19 | 20 | gnats 21 | 22 | 23 | 24 | 25 | # 由社区提供的docker环境 26 | [mqant-docker](https://github.com/bjfumac/mqant-docker) 27 | 28 | # go.mod 用法 29 | 30 | mqantserver 只支持golang1.2版本以上的go.mod方式编译 31 | 32 | # 翻墙 33 | 34 | >golang.org/x/net 等库无法下载的问题 35 | 36 | export GOPROXY=https://goproxy.io 37 | 38 | 39 | ## 编译 mqantserver: 40 | 41 | go install server/main.go 42 | 43 | go build server/main.go 44 | 45 | 如果一切顺利,运行 main 你可以获得以下输出: 46 | 47 | > ./main --conf bin/conf/server.json --log bin/logs 48 | 49 | [release] mqant 1.0.0 starting up 50 | [debug ] RPCClient create success type(Gate) id(127.0.0.1:Gate) 51 | [debug ] RPCClient create success type(Login) id(127.0.0.1:Login) 52 | [debug ] RPCClient create success type(Chat) id(127.0.0.1:Chat) 53 | [release] MySelfHost 172.16.8.4 54 | [release] WS Listen :%!(EXTRA string=0.0.0.0:3653) 55 | [release] TCP Listen :%!(EXTRA string=0.0.0.0:3563) 56 | 57 | 敲击 Ctrl + C 关闭游戏服务器,服务器正常关闭输出: 58 | 59 | [debug ] RPCServer close success id(127.0.0.1:Chat) 60 | [debug ] RPCServer close success id(127.0.0.1:Login) 61 | [debug ] RPCServer close success id(127.0.0.1:Gate) 62 | [debug ] RPCClient close success type(Gate) id(127.0.0.1:Gate) 63 | [debug ] RPCClient close success type(Login) id(127.0.0.1:Login) 64 | [debug ] RPCClient close success type(Chat) id(127.0.0.1:Chat) 65 | [release] mqant closing down (signal: interrupt) 66 | 67 | # 更改web服务器文件访问本地路径 68 | 69 | bin/conf/server.conf 中 70 | 71 | "Webapp":[ 72 | { 73 | "Id":"Webapp001", 74 | "ProcessID":"development", 75 | "Settings":{ 76 | "StaticPath":"/work/go/mqantserver/bin" 77 | } 78 | } 79 | ], 80 | 其中StaticPath 更改为你本机上mqantserver bin的绝对路径 81 | 82 | # 访问网页版本客户端 83 | mqantserver已内置了一个web模块(源码在server/webapp),因此进程启动成功以后就可以访问了 84 | 85 | 访问地址为:http://127.0.0.1:8080/mqant/chat/index.html 86 | 87 | 小球碰撞游戏DEMO访问地址为:http://127.0.0.1:8080/mqant/hitball/index.html 88 | 89 | # 猜数字游戏 90 | 91 | 猜数字游戏无网页模块,而是实现了一个golang的后端机器人来模拟整个逻辑 92 | 93 | 机器人代码在src/robot下,需要依赖github.com/liangdas/armyant 94 | 95 | # Demo演示说明 96 | 97 | 1. 启动服务器 98 | 2. 启动网页客户端 (默认房间名,用户名) 99 | 3. 登陆成功后就可以聊天了 100 | 101 | # 分布式跟踪系统功能测试 102 | [Appdash,用Go实现的分布式系统跟踪神器](http://tonybai.com/2015/06/17/appdash-distributed-systems-tracing-in-go/) 103 | 104 | 客户端访问Chat/HD_JoinChat/{msgid}时后端将会收集访问信息,通过以下地址就可以看到了 105 | [访问地址 http://localhost:7700](http://localhost:7700) 106 | 107 | 示意图: 108 | ![示意图](https://github.com/liangdas/mqant/wiki/images/mqant_tracing.png) 109 | 110 | # 项目目录结构 111 | 112 | https://github.com/liangdas/mqantserver 仓库中包含了mqant框架,所用到的第三方库,聊天Demo服务端,聊天代码客户端代码 113 | 114 | bin 115 | |-conf/server.json 服务端配置文件 116 | |-public web客户端静态文件 117 | |-hitball 小球碰撞游戏DEMO客户端文件 118 | |-console 控制台web静态文件(还未完成) 119 | src 120 | |-client 121 | |-mqtt_chat_client.py 聊天客户端 Python版本 122 | |-webclient.go 聊天客户端网页版本 123 | |-hitball 小球碰撞游戏DEMO客户端源码 124 | |-server 聊天服务器Demo 125 | |-gate 网关模块 126 | |-chat 聊天模块 127 | |-login 登陆模块 128 | |-hitball 小球碰撞游戏模块 129 | |-tracing 分布式跟踪系统服务模块 130 | |-main.go 服务器启动入口 131 | 132 | 133 | # 客户端快速测试 134 | 如果你需要测试其他语言的mqtt客户端,可以使用mqant提供的测试接口来测试 135 | ### tcp mqtt : 136 | host: mqant.com 137 | port: 3563 138 | protocol=mqtt.MQTTv31 139 | tcp: tls/TLSv1 140 | 141 | 如果客户端需要ca证书可以使用下面这个网站提供的 142 | https://curl.haxx.se/docs/caextract.html 143 | 144 | ### websocket mqtt : 145 | host: ws://www.mqant.com:3653/mqant 146 | protocol=mqtt.MQTTv31 147 | 148 | ### 测试协议 149 | 150 | 1. 登陆接口 151 | 152 | 向服务器publish一条登陆消息 153 | 154 | topic: Login/HD_Login/{msgid} 155 | 156 | message: {"userName": "liangdas", "passWord": "Hello,anyone!"} 157 | 158 | 如果topic添加了msgid,则服务器会返回一条回复消息 159 | 160 | 2. 加入聊天室 161 | 162 | 向服务器publish一条登陆消息 163 | 164 | topic: Chat/HD_JoinChat/{msgid} 165 | 166 | message: {"roomName": "mqant"} 167 | 168 | 服务器会广播消息给所有聊天室成员 169 | 170 | topic: Chat/OnJoin 171 | 172 | message: {"users": [“liangdas”]} 173 | 174 | 3. 发送一条聊天 175 | 176 | 向服务器publish一条登陆消息 177 | 178 | topic: Chat/HD_Say/{msgid} 179 | 180 | message: {"roomName": "mqant","from":"liangdas","target":"*","content": "大家好!!"} 181 | 182 | 服务器会广播消息给所有聊天室成员 183 | 184 | topic: Chat/OnChat 185 | 186 | message: {"roomName": "mqant","from":"liangdas","target":"*","msg":"大家好!!"} -------------------------------------------------------------------------------- /bin/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/bin/.DS_Store -------------------------------------------------------------------------------- /bin/chat/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/bin/chat/.DS_Store -------------------------------------------------------------------------------- /bin/chat/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Chat Of mqant 8 | 9 | 10 | 12 | 13 | 16 | 19 | 22 | 25 | 26 | 27 | 28 |
29 |
30 |
31 | Chat Of mqant 32 |
33 | 34 | 35 | 38 | 39 | 40 | 44 | 45 | 48 | 49 |
36 | 37 |
41 | 43 |
46 | 47 |
50 |
51 |
52 |
53 |
54 |
55 |
56 | 76 | 77 |
78 |
79 |
80 |
81 | Close 82 |

83 | Tip 84 |

85 |
86 |
87 |
88 |
89 |
90 |
91 |

92 | No Tip Again 93 |

94 |
95 |
96 | 97 | 98 | -------------------------------------------------------------------------------- /bin/chat/js/lib/mqantlib.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * Created by liangdas on 17/2/25. 4 | * Email 1587790525@qq.com 5 | */ 6 | 7 | var hashmap = function () { 8 | } 9 | hashmap.prototype = { 10 | constructor: hashmap, 11 | add: function (k, v) { 12 | if (!this.hasOwnProperty(k)) { 13 | this[k] = v; 14 | } 15 | }, 16 | remove: function (k) { 17 | if (this.hasOwnProperty(k)) { 18 | delete this[k]; 19 | } 20 | }, 21 | update: function (k, v) { 22 | this[k] = v; 23 | }, 24 | has: function (k) { 25 | var type = typeof k; 26 | if (type === 'string' || type === 'number') { 27 | return this.hasOwnProperty(k); 28 | } else if (type === 'function' && this.some(k)) { 29 | return true; 30 | } 31 | return false; 32 | }, 33 | clear: function () { 34 | for (var k in this) { 35 | if (this.hasOwnProperty(k)) { 36 | delete this[k]; 37 | } 38 | } 39 | }, 40 | empty: function () { 41 | for (var k in this) { 42 | if (this.hasOwnProperty(k)) { 43 | return false; 44 | } 45 | } 46 | return true; 47 | }, 48 | each: function (fn) { 49 | for (var k in this) { 50 | if (this.hasOwnProperty(k)) { 51 | fn.call(this, this[k], k, this); 52 | } 53 | } 54 | }, 55 | map: function (fn) { 56 | var hash = new Hash; 57 | for (var k in this) { 58 | if (this.hasOwnProperty(k)) { 59 | hash.add(k, fn.call(this, this[k], k, this)); 60 | } 61 | } 62 | return hash; 63 | }, 64 | filter: function (fn) { 65 | var hash = new Hash; 66 | for (var k in this) { 67 | 68 | } 69 | }, 70 | join: function (split) { 71 | split = split !== undefined ? split : ','; 72 | var rst = []; 73 | this.each(function (v) { 74 | rst.push(v); 75 | }); 76 | return rst.join(split); 77 | }, 78 | every: function (fn) { 79 | for (var k in this) { 80 | if (this.hasOwnProperty(k)) { 81 | if (!fn.call(this, this[k], k, this)) { 82 | return false; 83 | } 84 | } 85 | } 86 | return true; 87 | }, 88 | some: function (fn) { 89 | for (var k in this) { 90 | if (this.hasOwnProperty(k)) { 91 | if (fn.call(this, this[k], k, this)) { 92 | return true; 93 | } 94 | } 95 | } 96 | return false; 97 | }, 98 | find: function (k) { 99 | var type = typeof k; 100 | if (type === 'string' || type === 'number' && this.has(k)) { 101 | return this[k]; 102 | } else if (type === 'function') { 103 | for (var _k in this) { 104 | if (this.hasOwnProperty(_k) && k.call(this, this[_k], _k, this)) { 105 | return this[_k]; 106 | } 107 | } 108 | } 109 | return null; 110 | } 111 | }; 112 | 113 | var mqant = function () { 114 | } 115 | mqant.prototype = { 116 | constructor: window.mqant, 117 | curr_id: 0, 118 | client:null, 119 | waiting_queue:new hashmap(), 120 | init:function(prop){ 121 | prop["onFailure"]=prop["onFailure"]||function () { 122 | console.log("onFailure"); 123 | } 124 | prop["onConnectionLost"]=prop["onConnectionLost"]||function (responseObject) { 125 | if (responseObject.errorCode !== 0) { 126 | console.log("onConnectionLost:" + responseObject.errorMessage); 127 | console.log("连接已断开"); 128 | } 129 | } 130 | prop["useSSL"]=prop["useSSL"]||false 131 | this.client = new Paho.MQTT.Client(prop["host"], prop["port"], prop["client_id"]); 132 | this.client.connect({ 133 | onSuccess: prop["onSuccess"], 134 | onFailure: prop["onFailure"], 135 | mqttVersion: 3, 136 | useSSL:prop["useSSL"], 137 | cleanSession: true, 138 | });//连接服务器并注册连接成功处理事件 139 | this.client.onConnectionLost =prop["onConnectionLost"] ;//注册连接断开处理事件 140 | this.client.onMessageArrived = onMessageArrived;//注册消息接收处理事件 141 | var self=this; 142 | function onMessageArrived(message) { 143 | var callback=self.waiting_queue.find(message.destinationName); 144 | if(typeof(callback)!="undefined"){ 145 | //有等待消息的callback 还缺一个信息超时的处理机制 146 | var h=message.destinationName.split("/") 147 | if(h.length>2){ 148 | //这个topic存在msgid 那么这个回调只使用一次 149 | self.waiting_queue.remove(message.destinationName) 150 | } 151 | callback(message); 152 | } 153 | } 154 | }, 155 | /** 156 | * 向服务器发送一条消息 157 | * @param topic 158 | * @param msg 159 | * @param callback 160 | */ 161 | request:function(topic,msg,callback){ 162 | this.curr_id=this.curr_id+1 163 | var topic=topic+"/"+this.curr_id; //给topic加一个msgid 这样服务器就会返回这次请求的结果,否则服务器不会返回结果 164 | var payload=JSON.stringify(msg); 165 | this.on(topic,callback); 166 | this.client.send(topic,payload ,1); 167 | }, 168 | /** 169 | * 向服务器发送一条消息,但不要求服务器返回结果 170 | * @param topic 171 | * @param msg 172 | */ 173 | requestNR:function(topic,msg){ 174 | var payload=JSON.stringify(msg); 175 | this.client.send(topic,payload ,1); 176 | }, 177 | /** 178 | * 监听指定类型的topic消息 179 | * @param topic 180 | * @param callback 181 | */ 182 | on:function(topic,callback){ 183 | //服务器不会返回结果 184 | this.waiting_queue.add(topic,callback); //添加这条消息到等待队列 185 | } 186 | } 187 | 188 | window.mqant=new mqant(); 189 | 190 | 191 | 192 | 193 | 194 | -------------------------------------------------------------------------------- /bin/chat/js/pop.js: -------------------------------------------------------------------------------- 1 |  (function($j) { 2 | $j.positionFixed = function(el) { 3 | $j(el).each(function() { 4 | new fixed(this) 5 | }) 6 | return el; 7 | } 8 | $j.fn.positionFixed = function() { 9 | return $j.positionFixed(this) 10 | } 11 | var fixed = $j.positionFixed.impl = function(el) { 12 | var o = this; 13 | o.sts = { 14 | target: $j(el).css('position', 'fixed'), 15 | container: $j(window) 16 | } 17 | o.sts.currentCss = { 18 | top: o.sts.target.css('top'), 19 | right: o.sts.target.css('right'), 20 | bottom: o.sts.target.css('bottom'), 21 | left: o.sts.target.css('left') 22 | } 23 | if (!o.ie6) return; 24 | o.bindEvent(); 25 | } 26 | $j.extend(fixed.prototype, { 27 | ie6: $.browser.msie && $.browser.version < 7.0, 28 | bindEvent: function() { 29 | var o = this; 30 | o.sts.target.css('position', 'absolute') 31 | o.overRelative().initBasePos(); 32 | o.sts.target.css(o.sts.basePos) 33 | o.sts.container.scroll(o.scrollEvent()).resize(o.resizeEvent()); 34 | o.setPos(); 35 | }, 36 | overRelative: function() { 37 | var o = this; 38 | var relative = o.sts.target.parents().filter(function() { 39 | if ($j(this).css('position') == 'relative') return this; 40 | }) 41 | if (relative.size() > 0) relative.after(o.sts.target) 42 | return o; 43 | }, 44 | initBasePos: function() { 45 | var o = this; 46 | o.sts.basePos = { 47 | top: o.sts.target.offset().top - (o.sts.currentCss.top == 'auto' ? o.sts.container.scrollTop() : 0), 48 | left: o.sts.target.offset().left - (o.sts.currentCss.left == 'auto' ? o.sts.container.scrollLeft() : 0) 49 | } 50 | return o; 51 | }, 52 | setPos: function() { 53 | var o = this; 54 | o.sts.target.css({ 55 | top: o.sts.container.scrollTop() + o.sts.basePos.top, 56 | left: o.sts.container.scrollLeft() + o.sts.basePos.left 57 | }) 58 | }, 59 | scrollEvent: function() { 60 | var o = this; 61 | return function() { 62 | o.setPos(); 63 | } 64 | }, 65 | resizeEvent: function() { 66 | var o = this; 67 | return function() { 68 | setTimeout(function() { 69 | o.sts.target.css(o.sts.currentCss) 70 | o.initBasePos(); 71 | o.setPos() 72 | }, 1) 73 | } 74 | } 75 | }) 76 | })(jQuery) 77 | 78 | jQuery(function($j) { 79 | $j('#footer').positionFixed() 80 | }) 81 | 82 | function Pop(title, intro) { 83 | this.title = title; 84 | this.intro = intro; 85 | this.apearTime = 1000; 86 | this.hideTime = 500; 87 | this.delay = 8000; 88 | this.addInfo(); 89 | this.showDiv(); 90 | this.closeDiv(); 91 | } 92 | Pop.prototype = { 93 | addInfo: function() { 94 | $("#popIntro").html(this.intro); 95 | }, 96 | showDiv: function(time) { 97 | if (!($.browser.msie && ($.browser.version == "6.0") && !$.support.style)) { 98 | $('#pop').slideDown(this.apearTime).delay(this.delay).fadeOut(400); 99 | } else { 100 | $('#pop').show(); 101 | jQuery(function($j) { 102 | $j('#pop').positionFixed() 103 | }) 104 | } 105 | }, 106 | closeDiv: function() { 107 | $("#popClose").click(function() { 108 | $('#pop').hide(); 109 | }); 110 | $("#popMore").click(function() { 111 | $('#pop').remove(); 112 | }); 113 | } 114 | } -------------------------------------------------------------------------------- /bin/chat/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 0; 3 | margin: 0; 4 | } 5 | 6 | body, #entry { 7 | background: #c5e8d6; 8 | color: #000000; 9 | } 10 | 11 | body, table { 12 | font-family: DejaVu Sans Mono, fixed; 13 | font-size: 14pt; 14 | line-height: 150%; 15 | } 16 | 17 | #loginView { 18 | width: 100%; 19 | font-size: 13pt; 20 | overflow: hidden; 21 | } 22 | 23 | #loginTitle { 24 | width: 100%; 25 | margin-top: 150px; 26 | font-size: 50pt; 27 | text-align: center; 28 | } 29 | 30 | #loginView input[type = "text"] { 31 | height: 30px; 32 | width: 270px; 33 | font-size: inherit; 34 | margin-left: 15px; 35 | } 36 | 37 | #loginView input[type = "button"] { 38 | height: 30px; 39 | width: 90px; 40 | font-size: inherit; 41 | } 42 | 43 | #loginView table { 44 | width: 100%; 45 | height: 100%; 46 | margin-top: 10%; 47 | } 48 | 49 | #loginView table tr { 50 | text-align: center; 51 | height: 50%; 52 | } 53 | 54 | #loginView table tr td { 55 | padding-top: 25px; 56 | } 57 | 58 | #loginError { 59 | text-align: center; 60 | font-size: 16pt; 61 | color: #ff0000; 62 | margin-top: 15px; 63 | } 64 | 65 | #chatHistory { 66 | padding-bottom: 5.1em; 67 | } 68 | 69 | #toolbar { 70 | position: fixed; 71 | width: 100%; 72 | bottom: 0; 73 | background: #007077; 74 | } 75 | 76 | #toolbar ul { 77 | margin: 0; 78 | padding: 5px 0 0 6px; 79 | height: 35px; 80 | list-style: none; 81 | } 82 | 83 | #toolbar li { 84 | display: block; 85 | float: left; 86 | margin: 0 2em 0 0; 87 | } 88 | 89 | #toolbar select { 90 | width: 100px; 91 | height: 30px; 92 | font-size: inherit; 93 | } 94 | 95 | #entry { 96 | width: 100%; 97 | font-size: inherit; 98 | padding: 1em; 99 | margin: 0; 100 | border-width: 0; 101 | outline-width: 0; 102 | clear: both; 103 | } 104 | 105 | .message { 106 | margin: 0.1em 0; 107 | } 108 | 109 | .message td { 110 | vertical-align: top; 111 | } 112 | 113 | .nick { 114 | font-weight: bold; 115 | padding: 0 1em 0 0.5em; 116 | } 117 | 118 | #pop { 119 | display: none; 120 | background: #fff; 121 | width: 260px; 122 | height: 152px; 123 | border: 1px solid #e0e0e0; 124 | font-size: 12px; 125 | font-family: DejaVu Sans Mono, fixed; 126 | position: fixed; 127 | right: 10px; 128 | bottom: 10px; 129 | } 130 | 131 | #popHead { 132 | line-height: 40px; 133 | background: #E74C65; 134 | border-bottom: 1px solid #e0e0e0; 135 | position: relative; 136 | font-size: 12px; 137 | padding: 0 0 0 10px; 138 | } 139 | 140 | #popHead h2 { 141 | font-size: 14px; 142 | color: #666; 143 | line-height: 40px; 144 | height: 32px; 145 | margin-top: -12px; 146 | } 147 | 148 | #popHead #popClose { 149 | position: absolute; 150 | right: 10px; 151 | top: 1px; 152 | } 153 | 154 | #popHead a#popClose:hover { 155 | color: #f00; 156 | cursor: pointer; 157 | } 158 | 159 | #popContent { 160 | padding: 20px 10px; 161 | } 162 | 163 | #popIntro { 164 | text-align: center; 165 | line-height: 160%; 166 | margin: 5px 0; 167 | color: #000; 168 | font-size: 12pt; 169 | } 170 | 171 | #popMore { 172 | text-align: right; 173 | border-top: 1px solid #ccc; 174 | line-height: 24px; 175 | padding-top: 5px; 176 | } 177 | 178 | #popMore:hover { 179 | color: #f00; 180 | cursor: pointer; 181 | } -------------------------------------------------------------------------------- /bin/conf/server.json: -------------------------------------------------------------------------------- 1 | { 2 | "Master":{ 3 | "Enable":false, 4 | "MasterType":"Master", 5 | "WebRoot":"/work/go/mqantserver/bin/console", 6 | "WebHost":"0.0.0.0:8686", 7 | "SSH":[ 8 | 9 | ], 10 | "Process":[ 11 | 12 | ] 13 | }, 14 | "Module":{ 15 | "Gate":[ 16 | { 17 | "Id":"Gate001", 18 | "ProcessID":"development", 19 | "Settings":{ 20 | "WSAddr": ":3653", 21 | "TCPAddr": ":3563", 22 | "MaxMsgLen": 4096, 23 | "HTTPTimeout": 10, 24 | "MaxConnNum" : 20000, 25 | "Tls" : false, 26 | "CertFile" : "/opt/go/mqantserver/sslkey/h5link.pem", 27 | "KeyFile" : "/opt/go/mqantserver/sslkey/h5link.key", 28 | "MinHBStorage" : 60 29 | } 30 | } 31 | ], 32 | "Master":[ 33 | { 34 | "Id":"Master001", 35 | "ProcessID":"development" 36 | } 37 | ], 38 | "HelloWorld":[ 39 | { 40 | "Id":"HelloWorld001", 41 | "ProcessID":"development" 42 | } 43 | ], 44 | "Login":[ 45 | { 46 | "Id":"Login001", 47 | "ProcessID":"development" 48 | } 49 | ], 50 | "Chat":[ 51 | { 52 | "Id":"Chat001", 53 | "ProcessID":"development" 54 | } 55 | ], 56 | "PyChat":[ 57 | { 58 | "Id":"PyChat001", 59 | "ProcessID":"development" 60 | } 61 | ], 62 | "Test":[ 63 | { 64 | "Id":"Test001", 65 | "ProcessID":"development" 66 | } 67 | ], 68 | "Hitball":[ 69 | { 70 | "Id":"Hitball001", 71 | "ProcessID":"development" 72 | } 73 | ], 74 | "XaXb":[ 75 | { 76 | "Id":"XaXb001", 77 | "ProcessID":"development", 78 | "Settings":{ 79 | "LevelPath": "static/tacit/assets/levels/level1.json" 80 | } 81 | } 82 | ], 83 | "Webapp":[ 84 | { 85 | "Id":"Webapp001", 86 | "ProcessID":"development", 87 | "Settings":{ 88 | "StaticPath":"/work/go/mqantserver/bin" 89 | } 90 | } 91 | ], 92 | "Tracing":[ 93 | { 94 | "Id":"Tracing001", 95 | "ProcessID":"development", 96 | "Settings":{ 97 | "StoreFile": "/tmp/appdash.gob", 98 | "URL": "http://localhost:7700", 99 | "CollectorAddr":":7701", 100 | "HTTPAddr": ":7700" 101 | } 102 | } 103 | 104 | ] 105 | }, 106 | "Mqtt":{ 107 | "WirteLoopChanNum": 10, 108 | "ReadPackLoop": 1, 109 | "ReadTimeout": 600, 110 | "WriteTimeout": 300 111 | }, 112 | "Rpc":{ 113 | "MaxCoroutine":10000, 114 | "RpcExpired": 1, 115 | "LogSuccess":false 116 | } 117 | } -------------------------------------------------------------------------------- /bin/console/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Console Of mqant 8 | 9 | 11 | 13 | 16 | 19 | 22 | 23 | 24 | 25 |
26 |
27 |
28 | Console Of mqant 29 |
30 |
31 | {{ message }} 32 |
33 | 34 |
35 | 36 |
37 | 38 | 39 | -------------------------------------------------------------------------------- /bin/console/js/lib/mqantlib.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * Created by liangdas on 17/2/25. 4 | * Email 1587790525@qq.com 5 | */ 6 | 7 | var hashmap = function () { 8 | } 9 | hashmap.prototype = { 10 | constructor: hashmap, 11 | add: function (k, v) { 12 | if (!this.hasOwnProperty(k)) { 13 | this[k] = v; 14 | } 15 | }, 16 | remove: function (k) { 17 | if (this.hasOwnProperty(k)) { 18 | delete this[k]; 19 | } 20 | }, 21 | update: function (k, v) { 22 | this[k] = v; 23 | }, 24 | has: function (k) { 25 | var type = typeof k; 26 | if (type === 'string' || type === 'number') { 27 | return this.hasOwnProperty(k); 28 | } else if (type === 'function' && this.some(k)) { 29 | return true; 30 | } 31 | return false; 32 | }, 33 | clear: function () { 34 | for (var k in this) { 35 | if (this.hasOwnProperty(k)) { 36 | delete this[k]; 37 | } 38 | } 39 | }, 40 | empty: function () { 41 | for (var k in this) { 42 | if (this.hasOwnProperty(k)) { 43 | return false; 44 | } 45 | } 46 | return true; 47 | }, 48 | each: function (fn) { 49 | for (var k in this) { 50 | if (this.hasOwnProperty(k)) { 51 | fn.call(this, this[k], k, this); 52 | } 53 | } 54 | }, 55 | map: function (fn) { 56 | var hash = new Hash; 57 | for (var k in this) { 58 | if (this.hasOwnProperty(k)) { 59 | hash.add(k, fn.call(this, this[k], k, this)); 60 | } 61 | } 62 | return hash; 63 | }, 64 | filter: function (fn) { 65 | var hash = new Hash; 66 | for (var k in this) { 67 | 68 | } 69 | }, 70 | join: function (split) { 71 | split = split !== undefined ? split : ','; 72 | var rst = []; 73 | this.each(function (v) { 74 | rst.push(v); 75 | }); 76 | return rst.join(split); 77 | }, 78 | every: function (fn) { 79 | for (var k in this) { 80 | if (this.hasOwnProperty(k)) { 81 | if (!fn.call(this, this[k], k, this)) { 82 | return false; 83 | } 84 | } 85 | } 86 | return true; 87 | }, 88 | some: function (fn) { 89 | for (var k in this) { 90 | if (this.hasOwnProperty(k)) { 91 | if (fn.call(this, this[k], k, this)) { 92 | return true; 93 | } 94 | } 95 | } 96 | return false; 97 | }, 98 | find: function (k) { 99 | var type = typeof k; 100 | if (type === 'string' || type === 'number' && this.has(k)) { 101 | return this[k]; 102 | } else if (type === 'function') { 103 | for (var _k in this) { 104 | if (this.hasOwnProperty(_k) && k.call(this, this[_k], _k, this)) { 105 | return this[_k]; 106 | } 107 | } 108 | } 109 | return null; 110 | } 111 | }; 112 | 113 | window.mqant = function () { 114 | } 115 | window.mqant.prototype = { 116 | constructor: window.mqant, 117 | curr_id: 0, 118 | client:null, 119 | waiting_queue:new hashmap(), 120 | init:function(prop){ 121 | prop["onFailure"]=prop["onFailure"]||function () { 122 | console.log("onFailure"); 123 | } 124 | prop["onConnectionLost"]=prop["onConnectionLost"]||function (responseObject) { 125 | if (responseObject.errorCode !== 0) { 126 | console.log("onConnectionLost:" + responseObject.errorMessage); 127 | console.log("连接已断开"); 128 | } 129 | } 130 | prop["useSSL"]=prop["useSSL"]||false 131 | this.client = new Paho.MQTT.Client(prop["host"], prop["port"], prop["client_id"]); 132 | this.client.connect({ 133 | onSuccess: prop["onSuccess"], 134 | onFailure: prop["onFailure"], 135 | mqttVersion: 3, 136 | useSSL:prop["useSSL"], 137 | cleanSession: true, 138 | });//连接服务器并注册连接成功处理事件 139 | this.client.onConnectionLost =prop["onConnectionLost"] ;//注册连接断开处理事件 140 | this.client.onMessageArrived = onMessageArrived;//注册消息接收处理事件 141 | var self=this 142 | function onMessageArrived(message) { 143 | var callback=self.waiting_queue.find(message.destinationName) 144 | if(callback!=null){ 145 | //有等待消息的callback 还缺一个信息超时的处理机制 146 | var h=message.destinationName.split("/") 147 | if(h.length>2){ 148 | //这个topic存在msgid 那么这个回调只使用一次 149 | self.waiting_queue.remove(message.destinationName) 150 | } 151 | callback(message) 152 | } 153 | } 154 | }, 155 | /** 156 | * 向服务器发送一条消息 157 | * @param topic 158 | * @param msg 159 | * @param callback 160 | */ 161 | request:function(topic,msg,callback){ 162 | this.curr_id=this.curr_id+1 163 | var topic=topic+"/"+this.curr_id //给topic加一个msgid 这样服务器就会返回这次请求的结果,否则服务器不会返回结果 164 | var payload=JSON.stringify(msg) 165 | this.on(topic,callback) 166 | this.client.send(topic,payload ,1); 167 | }, 168 | /** 169 | * 向服务器发送一条消息,但不要求服务器返回结果 170 | * @param topic 171 | * @param msg 172 | */ 173 | requestNR:function(topic,msg){ 174 | var payload=JSON.stringify(msg) 175 | this.client.send(topic,payload ,1); 176 | }, 177 | /** 178 | * 监听指定类型的topic消息 179 | * @param topic 180 | * @param callback 181 | */ 182 | on:function(topic,callback){ 183 | //服务器不会返回结果 184 | this.waiting_queue.add(topic,callback) //添加这条消息到等待队列 185 | } 186 | } 187 | 188 | 189 | 190 | 191 | 192 | -------------------------------------------------------------------------------- /bin/console/js/main.js: -------------------------------------------------------------------------------- 1 | var mqant=new window.mqant() 2 | 3 | $(document).ready(function() { 4 | var app = new Vue({ 5 | el: '#app', 6 | data: { 7 | message: 'Hello Vue!' 8 | } 9 | }) 10 | }); -------------------------------------------------------------------------------- /bin/hitball/assets/arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/bin/hitball/assets/arrow.png -------------------------------------------------------------------------------- /bin/hitball/assets/ball.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/bin/hitball/assets/ball.png -------------------------------------------------------------------------------- /bin/hitball/assets/coin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/bin/hitball/assets/coin.png -------------------------------------------------------------------------------- /bin/hitball/assets/deadly.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/bin/hitball/assets/deadly.png -------------------------------------------------------------------------------- /bin/hitball/assets/tilemaps/tmw_desert_spacing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/bin/hitball/assets/tilemaps/tmw_desert_spacing.png -------------------------------------------------------------------------------- /bin/hitball/assets/virtualjoystick/skins/arcade-joystick.json: -------------------------------------------------------------------------------- 1 | {"frames": [ 2 | 3 | { 4 | "filename": "base", 5 | "frame": {"x":2,"y":2,"w":280,"h":280}, 6 | "rotated": false, 7 | "trimmed": false, 8 | "spriteSourceSize": {"x":0,"y":0,"w":280,"h":280}, 9 | "sourceSize": {"w":280,"h":280} 10 | }, 11 | { 12 | "filename": "button1-down", 13 | "frame": {"x":2,"y":284,"w":132,"h":132}, 14 | "rotated": false, 15 | "trimmed": false, 16 | "spriteSourceSize": {"x":0,"y":0,"w":132,"h":132}, 17 | "sourceSize": {"w":132,"h":132} 18 | }, 19 | { 20 | "filename": "button1-up", 21 | "frame": {"x":136,"y":284,"w":132,"h":132}, 22 | "rotated": false, 23 | "trimmed": false, 24 | "spriteSourceSize": {"x":0,"y":0,"w":132,"h":132}, 25 | "sourceSize": {"w":132,"h":132} 26 | }, 27 | { 28 | "filename": "button2-down", 29 | "frame": {"x":270,"y":284,"w":132,"h":132}, 30 | "rotated": false, 31 | "trimmed": false, 32 | "spriteSourceSize": {"x":0,"y":0,"w":132,"h":132}, 33 | "sourceSize": {"w":132,"h":132} 34 | }, 35 | { 36 | "filename": "button2-up", 37 | "frame": {"x":284,"y":138,"w":132,"h":132}, 38 | "rotated": false, 39 | "trimmed": false, 40 | "spriteSourceSize": {"x":0,"y":0,"w":132,"h":132}, 41 | "sourceSize": {"w":132,"h":132} 42 | }, 43 | { 44 | "filename": "button3-down", 45 | "frame": {"x":418,"y":138,"w":132,"h":132}, 46 | "rotated": false, 47 | "trimmed": false, 48 | "spriteSourceSize": {"x":0,"y":0,"w":132,"h":132}, 49 | "sourceSize": {"w":132,"h":132} 50 | }, 51 | { 52 | "filename": "button3-up", 53 | "frame": {"x":404,"y":272,"w":132,"h":132}, 54 | "rotated": false, 55 | "trimmed": false, 56 | "spriteSourceSize": {"x":0,"y":0,"w":132,"h":132}, 57 | "sourceSize": {"w":132,"h":132} 58 | }, 59 | { 60 | "filename": "stick", 61 | "frame": {"x":404,"y":2,"w":134,"h":134}, 62 | "rotated": false, 63 | "trimmed": false, 64 | "spriteSourceSize": {"x":0,"y":0,"w":134,"h":134}, 65 | "sourceSize": {"w":134,"h":134} 66 | }], 67 | "meta": { 68 | "app": "http://www.codeandweb.com/texturepacker", 69 | "version": "1.0", 70 | "image": "arcade-joystick.png", 71 | "format": "RGBA8888", 72 | "size": {"w":552,"h":418}, 73 | "scale": "1", 74 | "smartupdate": "$TexturePacker:SmartUpdate:10346054b252ab14bb310a8d6bd547c8:95c6dd72d4153222351a2981c3dd9889:a263a0553fca6de61a66e4e620c067cc$" 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /bin/hitball/assets/virtualjoystick/skins/arcade-joystick.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/bin/hitball/assets/virtualjoystick/skins/arcade-joystick.png -------------------------------------------------------------------------------- /bin/hitball/assets/virtualjoystick/skins/generic-joystick.json: -------------------------------------------------------------------------------- 1 | {"frames": [ 2 | 3 | { 4 | "filename": "base", 5 | "frame": {"x":2,"y":2,"w":224,"h":224}, 6 | "rotated": false, 7 | "trimmed": false, 8 | "spriteSourceSize": {"x":0,"y":0,"w":224,"h":224}, 9 | "sourceSize": {"w":224,"h":224} 10 | }, 11 | { 12 | "filename": "button1-down", 13 | "frame": {"x":364,"y":2,"w":104,"h":104}, 14 | "rotated": false, 15 | "trimmed": false, 16 | "spriteSourceSize": {"x":0,"y":0,"w":104,"h":104}, 17 | "sourceSize": {"w":104,"h":104} 18 | }, 19 | { 20 | "filename": "button1-up", 21 | "frame": {"x":364,"y":108,"w":104,"h":104}, 22 | "rotated": false, 23 | "trimmed": false, 24 | "spriteSourceSize": {"x":0,"y":0,"w":104,"h":104}, 25 | "sourceSize": {"w":104,"h":104} 26 | }, 27 | { 28 | "filename": "button2-down", 29 | "frame": {"x":470,"y":2,"w":104,"h":104}, 30 | "rotated": false, 31 | "trimmed": false, 32 | "spriteSourceSize": {"x":0,"y":0,"w":104,"h":104}, 33 | "sourceSize": {"w":104,"h":104} 34 | }, 35 | { 36 | "filename": "button2-up", 37 | "frame": {"x":576,"y":2,"w":104,"h":104}, 38 | "rotated": false, 39 | "trimmed": false, 40 | "spriteSourceSize": {"x":0,"y":0,"w":104,"h":104}, 41 | "sourceSize": {"w":104,"h":104} 42 | }, 43 | { 44 | "filename": "button3-down", 45 | "frame": {"x":470,"y":108,"w":104,"h":104}, 46 | "rotated": false, 47 | "trimmed": false, 48 | "spriteSourceSize": {"x":0,"y":0,"w":104,"h":104}, 49 | "sourceSize": {"w":104,"h":104} 50 | }, 51 | { 52 | "filename": "button3-up", 53 | "frame": {"x":576,"y":108,"w":104,"h":104}, 54 | "rotated": false, 55 | "trimmed": false, 56 | "spriteSourceSize": {"x":0,"y":0,"w":104,"h":104}, 57 | "sourceSize": {"w":104,"h":104} 58 | }, 59 | { 60 | "filename": "stick", 61 | "frame": {"x":228,"y":2,"w":134,"h":134}, 62 | "rotated": false, 63 | "trimmed": false, 64 | "spriteSourceSize": {"x":0,"y":0,"w":134,"h":134}, 65 | "sourceSize": {"w":134,"h":134} 66 | }], 67 | "meta": { 68 | "app": "http://www.codeandweb.com/texturepacker", 69 | "version": "1.0", 70 | "image": "generic-joystick.png", 71 | "format": "RGBA8888", 72 | "size": {"w":682,"h":228}, 73 | "scale": "1", 74 | "smartupdate": "$TexturePacker:SmartUpdate:e9879c3113ba01e8301c41ff8a522461:27f6351bd7b0a375a2a8ff5a01af291c:39ee24d5067dbc6be070854b489a5e77$" 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /bin/hitball/assets/virtualjoystick/skins/generic-joystick.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/bin/hitball/assets/virtualjoystick/skins/generic-joystick.png -------------------------------------------------------------------------------- /bin/hitball/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 54 | 55 | 56 |
57 | 58 |
59 | 60 | -------------------------------------------------------------------------------- /bin/hitball/js/lib/inherits.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * Created by liangdas on 2016/12/6 0006. 4 | * Email :1587790525@qq.com 5 | * 这是一个 javascript 类继承函数, 6 | * 与以往的继承函数不同的是这个函数, 7 | * 可以直接从一个已存在的普通构造函数继承。 8 | */ 9 | var extend= function (superCtor, prop) { 10 | return function () { 11 | var fnTest = /xyz/.test(function () { 12 | xyz; 13 | }) ? /\b_super\b/ : /.*/; 14 | 15 | var _super = superCtor.prototype; 16 | //// The base Class implementation (does nothing) 17 | function baseClass() { 18 | if (baseClass.prototype.ctor) { 19 | baseClass.prototype.ctor.apply(this, Array.from(arguments)); 20 | } 21 | }; 22 | // 空函数F: 23 | var F = function F() {}; 24 | // 把F的原型指向Student.prototype: 25 | F.prototype = superCtor.prototype; 26 | //F.prototype = Object.create(superCtor.prototype); 27 | // 把PrimaryStudent的原型指向一个新的F对象,F对象的原型正好指向Student.prototype: 28 | baseClass.prototype = new F(); 29 | // 把PrimaryStudent原型的构造函数修复为PrimaryStudent: 30 | baseClass.prototype.constructor = baseClass; 31 | 32 | var prototype = baseClass.prototype; 33 | if (!_super.ctor) { 34 | _super.ctor = superCtor; 35 | } 36 | 37 | // Copy the properties over onto the new prototype 38 | for (var name in prop) { 39 | // Check if we're overwriting an existing function 40 | prototype[name] = typeof prop[name] == "function" && typeof _super[name] == "function" && fnTest.test(prop[name]) ? function (name, fn) { 41 | return function () { 42 | //var tmp_superclass = this.superclass; 43 | var tmp = this._super; 44 | // Add a new ._super() method that is the same method 45 | // but on the super-class 46 | this._super = _super[name]; 47 | //this.superclass=superCtor.bind(this); 48 | // The method only need to be bound temporarily, so we 49 | // remove it when we're done executing 50 | var ret = fn.apply(this, Array.from(arguments)); 51 | this._super = tmp; 52 | //this.superclass=tmp_superclass; 53 | return ret; 54 | }; 55 | }(name, prop[name]) : prop[name]; 56 | } 57 | return baseClass; 58 | }(); 59 | }; 60 | 61 | window.extend=extend; -------------------------------------------------------------------------------- /bin/hitball/js/lib/phaser_plugins/ColorHarmony/ColorHarmony.js: -------------------------------------------------------------------------------- 1 | /* jshint camelcase:false */ 2 | /** 3 | * A collection of methods useful for manipulating and comparing colors. 4 | * 5 | * @class Phaser.Plugin.ColorHarmony 6 | * @author Richard Davey 7 | * @copyright 2013 Photon Storm Ltd. 8 | * @license https://github.com/photonstorm/phaser/blob/master/license.txt MIT License 9 | */ 10 | 11 | Phaser.Plugins.ColorHarmony.prototype = { 12 | 13 | /** 14 | * Returns a Complementary Color Harmony for the given color. 15 | *

A complementary hue is one directly opposite the color given on the color wheel

16 | *

Value returned in 0xAARRGGBB format with Alpha set to 255.

17 | * 18 | * @method Phaser.Plugin.ColorHarmony#getComplementHarmony 19 | * @param {Number} color The color to base the harmony on. 20 | * @return {Number} 0xAARRGGBB format color value. 21 | */ 22 | getComplementHarmony: function (color) { 23 | 24 | var hsv = Phaser.Color.RGBtoHSV(color); 25 | var opposite = Phaser.Color.game.math.wrapValue(hsv.hue, 180, 359); 26 | return Phaser.Color.HSVtoRGB(opposite, 1.0, 1.0); 27 | 28 | }, 29 | 30 | /** 31 | * Returns an Analogous Color Harmony for the given color. 32 | *

An Analogous harmony are hues adjacent to each other on the color wheel

33 | *

Values returned in 0xAARRGGBB format with Alpha set to 255.

34 | * 35 | * @method Phaser.Plugin.ColorHarmony#getAnalogousHarmony 36 | * @param {Number} color The color to base the harmony on. 37 | * @param {Number} threshold Control how adjacent the colors will be (default +- 30 degrees) 38 | * @return {Object} Object containing 3 properties: color1 (the original color), color2 (the warmer analogous color) and color3 (the colder analogous color) 39 | */ 40 | getAnalogousHarmony: function (color, threshold) { 41 | if (typeof threshold === "undefined") { threshold = 30; } 42 | var hsv = Phaser.Color.RGBtoHSV(color); 43 | if(threshold > 359 || threshold < 0) { 44 | throw new Error("Color Warning: Invalid threshold given to getAnalogousHarmony()"); 45 | } 46 | var warmer = Phaser.Color.game.math.wrapValue(hsv.hue, 359 - threshold, 359); 47 | var colder = Phaser.Color.game.math.wrapValue(hsv.hue, threshold, 359); 48 | return { 49 | color1: color, 50 | color2: Phaser.Color.HSVtoRGB(warmer, 1.0, 1.0), 51 | color3: Phaser.Color.HSVtoRGB(colder, 1.0, 1.0), 52 | hue1: hsv.hue, 53 | hue2: warmer, 54 | hue3: colder 55 | }; 56 | }, 57 | 58 | /** 59 | * Returns an Split Complement Color Harmony for the given color. 60 | *

A Split Complement harmony are the two hues on either side of the color's Complement

61 | *

Values returned in 0xAARRGGBB format with Alpha set to 255.

62 | * 63 | * @method Phaser.Plugin.ColorHarmony#getSplitComplementHarmony 64 | * @param {Number} color The color to base the harmony on 65 | * @param {Number} threshold Control how adjacent the colors will be to the Complement (default +- 30 degrees) 66 | * @return {Object} An object containing 3 properties: color1 (the original color), color2 (the warmer analogous color) and color3 (the colder analogous color) 67 | */ 68 | getSplitComplementHarmony: function (color, threshold) { 69 | if (typeof threshold === "undefined") { threshold = 30; } 70 | var hsv = Phaser.Color.RGBtoHSV(color); 71 | if(threshold >= 359 || threshold <= 0) { 72 | throw new Error("Phaser.Color Warning: Invalid threshold given to getSplitComplementHarmony()"); 73 | } 74 | var opposite = Phaser.Color.game.math.wrapValue(hsv.hue, 180, 359); 75 | var warmer = Phaser.Color.game.math.wrapValue(hsv.hue, opposite - threshold, 359); 76 | var colder = Phaser.Color.game.math.wrapValue(hsv.hue, opposite + threshold, 359); 77 | return { 78 | color1: color, 79 | color2: Phaser.Color.HSVtoRGB(warmer, hsv.saturation, hsv.value), 80 | color3: Phaser.Color.HSVtoRGB(colder, hsv.saturation, hsv.value), 81 | hue1: hsv.hue, 82 | hue2: warmer, 83 | hue3: colder 84 | }; 85 | }, 86 | 87 | /** 88 | * Returns a Triadic Color Harmony for the given color. 89 | *

A Triadic harmony are 3 hues equidistant from each other on the color wheel

90 | *

Values returned in 0xAARRGGBB format with Alpha set to 255.

91 | * 92 | * @method Phaser.Plugin.ColorHarmony#getTriadicHarmony 93 | * @param {Number} color The color to base the harmony on. 94 | * @return {Object} An Object containing 3 properties: color1 (the original color), color2 and color3 (the equidistant colors) 95 | */ 96 | getTriadicHarmony: function (color) { 97 | var hsv = Phaser.Color.RGBtoHSV(color); 98 | var triadic1 = Phaser.Color.game.math.wrapValue(hsv.hue, 120, 359); 99 | var triadic2 = Phaser.Color.game.math.wrapValue(triadic1, 120, 359); 100 | return { 101 | color1: color, 102 | color2: Phaser.Color.HSVtoRGB(triadic1, 1.0, 1.0), 103 | color3: Phaser.Color.HSVtoRGB(triadic2, 1.0, 1.0) 104 | }; 105 | } 106 | 107 | }; 108 | -------------------------------------------------------------------------------- /bin/hitball/js/lib/phaser_plugins/README.md: -------------------------------------------------------------------------------- 1 | ![Phaser Logo](http://www.photonstorm.com/wp-content/uploads/2013/09/phaser_10_release.jpg) 2 | 3 | # Phaser Plugins 4 | 5 | This is the Phaser Plugins repository. 6 | 7 | If you're looking for the framework itself, please go here: https://github.com/photonstorm/phaser 8 | 9 | 10 | ## Contributing 11 | 12 | - If you find a bug in a Plugin then please report it on [GitHub Issues][issues] or our [Support Forum][forum]. 13 | 14 | - You can issue Pull Requests for new plugins or fixes to existing ones against the `master` branch. 15 | 16 | - If you have a Plugin request, or have written a game or demo that shows a Phaser Plugin in use, then please get in touch. We'd love to hear from you! Either post to our [forum][forum] or email: rich@photonstorm.com 17 | 18 | 19 | ## Bugs? 20 | 21 | Please add them to the [Issue Tracker][issues] with as much info as possible, especially source code demonstrating the issue. 22 | 23 | 24 | ## About Phaser 25 | 26 | Phaser is a fast, free and fun open source game framework for making desktop and mobile browser HTML5 games. It uses [Pixi.js](https://github.com/GoodBoyDigital/pixi.js/) internally for fast 2D Canvas and WebGL rendering. 27 | 28 | By Richard Davey, [Photon Storm](http://www.photonstorm.com) 29 | 30 | * View the [Official Website](http://phaser.io) 31 | * Follow on [Twitter](https://twitter.com/photonstorm) 32 | * Join the [Forum](http://www.html5gamedevs.com/forum/14-phaser/) 33 | * Source code for 300+ [Phaser Examples](https://github.com/photonstorm/phaser-examples) or [browse them online](http://examples.phaser.io) 34 | * Read the [documentation online](http://docs.phaser.io) 35 | * Join our [#phaserio IRC channel](http://www.html5gamedevs.com/topic/4470-official-phaserio-irc-channel-phaserio-on-freenode/) on freenode 36 | * Subscribe to the [Phaser Newsletter](https://confirmsubscription.com/h/r/369DE48E3E86AF1E) and we'll email you when new versions are released. 37 | 38 | 39 | ## License 40 | 41 | Phaser and all examples are released under the [MIT License](http://opensource.org/licenses/MIT). This does not include any assets (art, music, sounds). However it is up to the individual Plugin authors which license they release under, so please check for a `license.txt` file in the plugin folder. If one is not present you may assume the MIT License. 42 | 43 | [issues]: https://github.com/photonstorm/phaser-plugins/issues 44 | [contribute]: https://github.com/photonstorm/phaser/blob/master/CONTRIBUTING.md 45 | [phaser]: https://github.com/photonstorm/phaser-plugins 46 | [forum]: http://www.html5gamedevs.com/forum/14-phaser/ 47 | 48 | [![Analytics](https://ga-beacon.appspot.com/UA-44006568-2/phaser/index)](https://github.com/igrigorik/ga-beacon) 49 | -------------------------------------------------------------------------------- /bin/hitball/js/lib/phaser_plugins/SamplePlugin/SamplePlugin.js: -------------------------------------------------------------------------------- 1 | /** 2 | * A Sample Plugin demonstrating how to hook into the Phaser plugin system. 3 | * @class Phaser.Plugin.SamplePlugin 4 | */ 5 | Phaser.Plugin.SamplePlugin = function (game, parent) { 6 | 7 | Phaser.Plugin.call(this, game, parent); 8 | 9 | this.sprite = null; 10 | 11 | }; 12 | 13 | // Extends the Phaser.Plugin template, setting up values we need 14 | Phaser.Plugin.SamplePlugin.prototype = Object.create(Phaser.Plugin.prototype); 15 | Phaser.Plugin.SamplePlugin.prototype.constructor = Phaser.Plugin.SamplePlugin; 16 | 17 | /** 18 | * Add a Sprite reference to this Plugin. 19 | * All this plugin does is move the Sprite across the screen slowly. 20 | * @type {Phaser.Sprite} 21 | */ 22 | Phaser.Plugin.SamplePlugin.prototype.addSprite = function (sprite) { 23 | 24 | this.sprite = sprite; 25 | 26 | }; 27 | 28 | /** 29 | * This is run when the plugins update during the core game loop. 30 | */ 31 | Phaser.Plugin.SamplePlugin.prototype.update = function () { 32 | 33 | if (this.sprite) 34 | { 35 | this.sprite.x += 0.5; 36 | } 37 | 38 | }; 39 | -------------------------------------------------------------------------------- /bin/hitball/js/lib/phaser_plugins/ScreenShake/ScreenShake.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Plugin to make screen shake FX (makes number of short camera movements). 5 | * 6 | * Usage: 7 | * in main create function: 8 | * game.plugins.screenShake = game.plugins.add(Phaser.Plugin.ScreenShake); 9 | * 10 | * in function where need to call shake FX: 11 | * game.plugins.screenShake.setup({ //if need to replace default plugin settings 12 | * shakeX: true, 13 | * shakeY: false 14 | * }); 15 | * this.game.plugins.screenShake.shake(10); //pass shake count value 16 | * 17 | * 18 | * 19 | * @author Dmitry Maslov 20 | * @copyright 2014 Dmitry Maslov 21 | * @license http://choosealicense.com/licenses/mit 22 | * 23 | */ 24 | Phaser.Plugin.ScreenShake = function(game, parent){ 25 | Phaser.Plugin.call(this, game, parent); 26 | 27 | //settings by default 28 | this._settings = { 29 | shakesCount: 0, 30 | shakeX: true, 31 | shakeY: true, 32 | sensCoef: 0.5 33 | }; 34 | this.game.camera.bounds = null; 35 | 36 | /** 37 | * screen shake FX. 38 | */ 39 | this._moveCamera = function(){ 40 | if(this._settings.shakesCount > 0){ 41 | var sens = this._settings.shakesCount * this._settings.sensCoef; 42 | 43 | if(this._settings.shakesCount % 2){ 44 | this.game.camera.x += this._settings.shakeX ? sens : 0; 45 | this.game.camera.y += this._settings.shakeY ? sens : 0; 46 | } 47 | else{ 48 | this.game.camera.x -= this._settings.shakeX ? sens : 0; 49 | this.game.camera.y -= this._settings.shakeY ? sens : 0; 50 | } 51 | 52 | this._settings.shakesCount--; 53 | 54 | if(this._settings.shakesCount === 0){ 55 | this.game.camera.setPosition(0, 0); 56 | } 57 | } 58 | }; 59 | }; 60 | 61 | Phaser.Plugin.ScreenShake.prototype = Object.create(Phaser.Plugin.prototype); 62 | Phaser.Plugin.ScreenShake.prototype.constructor = Phaser.Plugin.ScreenShake; 63 | 64 | 65 | /** 66 | * Change default settings object values with passed object value. 67 | * 68 | * @method Phaser.Plugin.ScreenShake#setup 69 | * @param {object} [obj] - Passed object to merge 70 | */ 71 | Phaser.Plugin.ScreenShake.prototype.setup = function(obj){ 72 | this._settings = Phaser.Utils.extend(false, this._settings, obj); 73 | }; 74 | 75 | 76 | /** 77 | * Pass value of count shakes. 78 | * 79 | * @method Phaser.Plugin.ScreenShake#shake 80 | * @param {number} [count] - Value of count shakes 81 | */ 82 | Phaser.Plugin.ScreenShake.prototype.shake = function(count){ 83 | this._settings.shakesCount = count; 84 | }; 85 | 86 | Phaser.Plugin.ScreenShake.prototype.update = function(){ 87 | this._moveCamera(); 88 | }; 89 | -------------------------------------------------------------------------------- /bin/hitball/js/lib/phaser_plugins/Webcam/Webcam.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Provides access to the Webcam (if available) 3 | * @class Phaser.Plugin.Webcam 4 | */ 5 | Phaser.Plugin.Webcam = function (game, parent) { 6 | 7 | Phaser.Plugin.call(this, game, parent); 8 | 9 | if (!game.device.getUserMedia) 10 | { 11 | return false; 12 | } 13 | 14 | navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia; 15 | 16 | this.context = null; 17 | this.stream = null; 18 | 19 | this.video = document.createElement('video'); 20 | this.video.autoplay = true; 21 | 22 | this.onConnect = new Phaser.Signal(); 23 | this.onError = new Phaser.Signal(); 24 | 25 | }; 26 | 27 | Phaser.Plugin.Webcam.prototype = Object.create(Phaser.Plugin.prototype); 28 | Phaser.Plugin.Webcam.prototype.constructor = Phaser.Plugin.Webcam; 29 | 30 | Phaser.Plugin.Webcam.prototype.start = function (width, height, context) { 31 | 32 | // console.log('Webcam start', width, height); 33 | 34 | this.context = context; 35 | 36 | if (!this.stream) 37 | { 38 | navigator.getUserMedia( { video: { mandatory: { minWidth: width, minHeight: height } } }, this.connectCallback.bind(this), this.errorCallback.bind(this)); 39 | } 40 | 41 | }; 42 | 43 | Phaser.Plugin.Webcam.prototype.stop = function () { 44 | 45 | if (this.stream) 46 | { 47 | this.stream.stop(); 48 | this.stream = null; 49 | } 50 | 51 | }; 52 | 53 | Phaser.Plugin.Webcam.prototype.connectCallback = function (stream) { 54 | 55 | this.stream = stream; 56 | 57 | this.video.src = window.URL.createObjectURL(this.stream); 58 | 59 | this.onConnect.dispatch(this.video); 60 | 61 | }; 62 | 63 | Phaser.Plugin.Webcam.prototype.errorCallback = function (event) { 64 | 65 | this.onError.dispatch(event); 66 | 67 | }; 68 | 69 | Phaser.Plugin.Webcam.prototype.grab = function (context, x, y) { 70 | 71 | if (this.stream) 72 | { 73 | context.drawImage(this.video, x, y); 74 | } 75 | 76 | }; 77 | 78 | Phaser.Plugin.Webcam.prototype.update = function () { 79 | 80 | if (this.stream) 81 | { 82 | this.context.drawImage(this.video, 0, 0); 83 | } 84 | 85 | }; 86 | 87 | /** 88 | * @name Phaser.Plugin.Webcam#active 89 | * @property {boolean} active - Is this Webcam plugin capturing a video stream or not? 90 | * @readonly 91 | */ 92 | Object.defineProperty(Phaser.Plugin.Webcam.prototype, "active", { 93 | 94 | get: function() { 95 | return (this.stream); 96 | } 97 | 98 | }); 99 | -------------------------------------------------------------------------------- /bin/hitball/js/main.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"main.js","sources":["webpack:///main.js"],"mappings":"AAAA","sourceRoot":""} -------------------------------------------------------------------------------- /bin/hitball/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hitball", 3 | "version": "0.0.1", 4 | "private": false, 5 | "dependencies": { 6 | "babelify": "^6.1.0", 7 | "babel-preset-es2015": "^6.18.0" 8 | }, 9 | "scripts": { 10 | "webpack": "webpack" 11 | }, 12 | "devDependencies": { 13 | "babel-cli": "^6.22.1", 14 | "babel-core": "^6.22.1", 15 | "babel-loader": "^6.2.10", 16 | "babel-plugin-add-module-exports": "^0.2.1", 17 | "babel-polyfill": "^6.22.0", 18 | "babel-preset-es2015": "^6.22.0", 19 | "babel-preset-react": "^6.22.0", 20 | "babel-preset-stage-0": "^6.22.0", 21 | "babelify": "^6.4.0", 22 | "json-loader": "^0.5.4", 23 | "script-loader": "0.7.0", 24 | "webpack": "^1.14.0", 25 | "phaser":"2.6.2" 26 | }, 27 | "browserify": { 28 | "transform": [ 29 | [ 30 | "babelify", 31 | { 32 | "presets": [ 33 | "es2015" 34 | ] 35 | } 36 | ] 37 | ] 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /bin/hitball/webpack.config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * Created by liangdas on 17/1/20. 4 | * Email 1587790525@qq.com 5 | */ 6 | var path = require('path'); 7 | var webpack = require('webpack'); 8 | 9 | var phaserModule = path.join(__dirname, '/node_modules/phaser/'); 10 | var phaser = path.join(phaserModule, 'build/custom/phaser-split.js'), 11 | pixi = path.join(phaserModule, 'build/custom/pixi.js'), 12 | p2 = path.join(phaserModule, 'build/custom/p2.js'); 13 | module.exports = { 14 | devtool: 'eval-source-map',//配置生成Source Maps,选择合适的选项 15 | entry: __dirname + "/src/main.js",//已多次提及的唯一入口文件 16 | output: { 17 | path: __dirname + "/js",//打包后的文件存放的地方 18 | filename: "main.js"//打包后输出文件的文件名 19 | }, 20 | 21 | module: { 22 | loaders: [ 23 | { 24 | test: /\.json$/, 25 | loader: "json" 26 | }, 27 | { 28 | test: /\.js$/, 29 | exclude: /node_modules/, 30 | loader: 'babel',//在webpack的module部分的loaders里进行配置即可 31 | }, 32 | { test: /pixi.js/, loader: "script" } 33 | ] 34 | }, 35 | 36 | devServer: { 37 | contentBase: "./js", 38 | colors: true, 39 | historyApiFallback: true, 40 | inline: true 41 | }, 42 | resolve: { 43 | alias: { 44 | 'phaser': phaser, 45 | 'pixi.js': pixi, 46 | 'p2': p2, 47 | } 48 | } 49 | } 50 | 51 | -------------------------------------------------------------------------------- /client/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | ''' 3 | Created on 17/2/21. 4 | @author: love 5 | ''' -------------------------------------------------------------------------------- /client/mqtt_chat_client.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | ''' 3 | Created on 17/2/16. 4 | @author: love 5 | ''' 6 | import paho.mqtt.client as mqtt 7 | import json 8 | import ssl 9 | 10 | def on_connect(client, userdata, flags, rc): 11 | print("Connected with result code %d"%rc) 12 | client.publish("Login/HD_Login/1", json.dumps({"userName": user, "passWord": "Hello,anyone!"}),qos=0,retain=False) 13 | 14 | 15 | 16 | def on_message(client, userdata, msg): 17 | print ('---------------') 18 | print ("topic :"+msg.topic) 19 | print ("payload :"+msg.payload) 20 | client.subscribe([("chat",2),("aaa",2)]) 21 | client.unsubscribe(["chat"]) 22 | #client.publish("login/addUser", json.dumps({"user": user, "say": "Hello,anyone!"}),qos=2,retain=False) 23 | #print(msg.topic+":"+str(msg.payload.decode())) 24 | #print(msg.topic+":"+msg.payload.decode()) 25 | #payload = json.loads(msg.payload.decode()) 26 | #print(payload.get("user")+":"+payload.get("say")) 27 | def mylog(self,userdata,level, buf): 28 | print buf 29 | 30 | if __name__ == '__main__': 31 | client = mqtt.Client(protocol=mqtt.MQTTv31) 32 | client.username_pw_set("admin", "password") # 必须设置,否则会返回「Connected with result code 4」 33 | client.on_connect = on_connect 34 | client.on_message = on_message 35 | #链接测试服务器 需要用tls请求 python tls功能比较弱。 36 | # 需要一个证书,这里使用的这个网站提供的证书https://curl.haxx.se/docs/caextract.html 37 | HOST = "mqant.com" 38 | # client.tls_set(ca_certs="caextract.pem", certfile=None, keyfile=None, cert_reqs=ssl.CERT_REQUIRED, 39 | # tls_version=ssl.PROTOCOL_TLSv1, ciphers=None) 40 | client.connect(HOST, 3563, 60) 41 | #client.loop_forever() 42 | 43 | user = raw_input("请输入用户名:") 44 | client.user_data_set(user) 45 | 46 | client.loop_start() 47 | 48 | while True: 49 | s = raw_input("请先输入'join'加入房间,然后输入任意聊天字符:\n") 50 | if s: 51 | if s=="join": 52 | client.publish("Chat/HD_JoinChat/2", json.dumps({"roomName": "mqant"}),qos=0,retain=False) 53 | elif s=="start": 54 | client.publish("Master/HD_Start_Process/2", json.dumps({"ProcessID": "001"}),qos=0,retain=False) 55 | elif s=="stop": 56 | client.publish("Master/HD_Stop_Process/2", json.dumps({"ProcessID": "001"}),qos=0,retain=False) 57 | else: 58 | client.publish("Chat/HD_Say/2", json.dumps({"roomName": "mqant","from":user,"target":"*","content": s}),qos=0,retain=False) -------------------------------------------------------------------------------- /example/helloworld.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 mqantserver Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | package main 15 | 16 | import ( 17 | "fmt" 18 | MQTT "github.com/eclipse/paho.mqtt.golang" 19 | "github.com/liangdas/armyant/work" 20 | ) 21 | 22 | func main() { 23 | this := new(work.MqttWork) 24 | opts := this.GetDefaultOptions("ws://127.0.0.1:3653") 25 | opts.SetConnectionLostHandler(func(client MQTT.Client, err error) { 26 | fmt.Println("连接断开", err.Error()) 27 | }) 28 | opts.SetOnConnectHandler(func(client MQTT.Client) { 29 | fmt.Println("连接成功") 30 | }) 31 | err := this.Connect(opts) 32 | if err != nil { 33 | fmt.Println(err.Error()) 34 | } 35 | 36 | //访问HelloWorld001模块的HD_Say函数 37 | msg, err := this.Request("HelloWorld/HD_Say", []byte(`{"say":"我是梁大帅"}`)) 38 | if err != nil { 39 | fmt.Println(err.Error()) 40 | } 41 | fmt.Println(fmt.Sprintf("topic :%s body :%s", msg.Topic(), string(msg.Payload()))) 42 | } 43 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/liangdas/mqantserver 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/eclipse/paho.mqtt.golang v1.2.0 7 | github.com/gorilla/mux v1.7.3 8 | github.com/liangdas/armyant v0.0.0-20181120080818-50ccc5936868 9 | github.com/liangdas/mqant v1.2.0 10 | github.com/liangdas/mqant-modules v1.1.2 11 | github.com/nats-io/nats.go v1.9.1 12 | github.com/pkg/errors v0.8.1 13 | github.com/yireyun/go-queue v0.0.0-20180809062148-5e6897360dac 14 | ) 15 | -------------------------------------------------------------------------------- /robot/xaba/manager.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 hey Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | package xaba_task 15 | 16 | import ( 17 | "github.com/liangdas/armyant/task" 18 | "io" 19 | "os" 20 | ) 21 | 22 | type Manager struct { 23 | // Writer is where results will be written. If nil, results are written to stdout. 24 | Writer io.Writer 25 | } 26 | 27 | func (this *Manager) writer() io.Writer { 28 | if this.Writer == nil { 29 | return os.Stdout 30 | } 31 | return this.Writer 32 | } 33 | func (this *Manager) Finish(task task.Task) { 34 | //total := time.Now().Sub(task.Start) 35 | } 36 | func (this *Manager) CreateWork() task.Work { 37 | return NewWork(this) 38 | } 39 | 40 | // Run makes all the requests, prints the summary. It blocks until 41 | // all work is done. 42 | func NewManager(t task.Task) task.WorkManager { 43 | // append hey's user agent 44 | this := new(Manager) 45 | return this 46 | } 47 | -------------------------------------------------------------------------------- /robot/xaba/work.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 hey Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | package xaba_task 15 | 16 | import ( 17 | "crypto/tls" 18 | "crypto/x509" 19 | "encoding/json" 20 | "fmt" 21 | MQTT "github.com/eclipse/paho.mqtt.golang" 22 | "github.com/liangdas/armyant/task" 23 | "github.com/liangdas/armyant/work" 24 | "github.com/liangdas/mqant/utils" 25 | "io/ioutil" 26 | "time" 27 | ) 28 | 29 | func NewWork(manager *Manager) *Work { 30 | this := new(Work) 31 | this.manager = manager 32 | //opts:=this.GetDefaultOptions("tls://127.0.0.1:3563") 33 | //opts := this.GetDefaultOptions("tcp://127.0.0.1:3563") 34 | opts := this.GetDefaultOptions("ws://127.0.0.1:3653") 35 | opts.SetConnectionLostHandler(func(client MQTT.Client, err error) { 36 | fmt.Println("ConnectionLost", err.Error()) 37 | }) 38 | opts.SetOnConnectHandler(func(client MQTT.Client) { 39 | fmt.Println("OnConnectHandler") 40 | }) 41 | // load root ca 42 | // 需要一个证书,这里使用的这个网站提供的证书https://curl.haxx.se/docs/caextract.html 43 | caData, err := ioutil.ReadFile("/work/go/gopath/src/github.com/liangdas/armyant/mqtt_task/caextract.pem") 44 | if err != nil { 45 | fmt.Println(err.Error()) 46 | } 47 | pool := x509.NewCertPool() 48 | pool.AppendCertsFromPEM(caData) 49 | 50 | config := &tls.Config{ 51 | RootCAs: pool, 52 | InsecureSkipVerify: true, 53 | } 54 | opts.SetTLSConfig(config) 55 | err = this.Connect(opts) 56 | if err != nil { 57 | fmt.Println(err.Error()) 58 | } 59 | 60 | this.On("XaXb/OnEnter", func(client MQTT.Client, msg MQTT.Message) { 61 | //服务端主动下发玩家加入事件 62 | fmt.Println(msg.Topic(), string(msg.Payload())) 63 | }) 64 | this.On("XaXb/Exit", func(client MQTT.Client, msg MQTT.Message) { 65 | fmt.Println(msg.Topic(), string(msg.Payload())) 66 | this.GetClient().Disconnect(25) 67 | }) 68 | this.On("XaXb/OnStop", func(client MQTT.Client, msg MQTT.Message) { 69 | fmt.Println(msg.Topic(), string(msg.Payload())) 70 | this.GetClient().Disconnect(25) 71 | }) 72 | this.On("XaXb/OnSync", func(client MQTT.Client, msg MQTT.Message) { 73 | fmt.Println(msg.Topic(), string(msg.Payload())) 74 | }) 75 | this.On("XaXb/Idle", func(client MQTT.Client, msg MQTT.Message) { 76 | fmt.Println(msg.Topic(), string(msg.Payload())) 77 | }) 78 | this.On("XaXb/Betting", func(client MQTT.Client, msg MQTT.Message) { 79 | //服务端通知可以押注了 80 | fmt.Println(msg.Topic(), string(msg.Payload())) 81 | time.Sleep(time.Millisecond * time.Duration(utils.RandInt64(100, 1000))) 82 | //开始押注 83 | msg, err = this.Request("XaXb/HD_Stake", []byte(fmt.Sprintf(`{"Target":%d}`, utils.RandInt64(0, 10)))) 84 | if err != nil { 85 | fmt.Println(err.Error()) 86 | return 87 | } 88 | //押注完成 89 | fmt.Println(msg.Topic(), string(msg.Payload())) 90 | }) 91 | this.On("XaXb/Opening", func(client MQTT.Client, msg MQTT.Message) { 92 | fmt.Println(msg.Topic(), string(msg.Payload())) 93 | }) 94 | this.On("XaXb/Settlement", func(client MQTT.Client, msg MQTT.Message) { 95 | fmt.Println(msg.Topic(), string(msg.Payload())) 96 | }) 97 | return this 98 | } 99 | 100 | /** 101 | Work 代表一个协程内具体执行任务工作者 102 | */ 103 | type Work struct { 104 | work.MqttWork 105 | manager *Manager 106 | } 107 | 108 | func (this *Work) UnmarshalResult(payload []byte) map[string]interface{} { 109 | rmsg := map[string]interface{}{} 110 | json.Unmarshal(payload, &rmsg) 111 | return rmsg["Result"].(map[string]interface{}) 112 | } 113 | 114 | /** 115 | 每一次请求都会调用该函数,在该函数内实现具体请求操作 116 | 117 | task:=task.Task{ 118 | N:1000, //一共请求次数,会被平均分配给每一个并发协程 119 | C:100, //并发数 120 | //QPS:10, //每一个并发平均每秒请求次数(限流) 不填代表不限流 121 | } 122 | 123 | N/C 可计算出每一个Work(协程) RunWorker将要调用的次数 124 | */ 125 | func (this *Work) RunWorker(t task.Task) { 126 | //登陆 127 | //s := `{"phone":"1880000000", "password":"123456"}` 128 | //msg,err:=this.Request("User/HD_LoginWithPassword",[]byte(s)) 129 | //if err!=nil{ 130 | // return 131 | //} 132 | //fmt.Println(msg.Topic(),string(msg.Payload())) 133 | 134 | //for { 135 | // msg, err := this.Request("XaXb/HD_Hello", []byte(`{"gameName":"xaxb"}`)) 136 | // if err != nil { 137 | // return 138 | // } 139 | // 140 | // if !strings.Contains(string(msg.Payload()),"success"){ 141 | // fmt.Println(string(msg.Payload())) 142 | // } 143 | // //this.RequestNR("XaXb/HD_Hello", []byte(`{"gameName":"xaxb"}`)) 144 | // time.Sleep(time.Millisecond*1000) 145 | //} 146 | //申请牌桌 147 | msg, err := this.Request("XaXb/HD_GetUsableTable", []byte(`{"gameName":"xaxb"}`)) 148 | if err != nil { 149 | return 150 | } 151 | 152 | fmt.Println(msg.Topic(), string(msg.Payload())) 153 | //进入牌桌 154 | BigRoomId := this.UnmarshalResult(msg.Payload())["BigRoomId"].(string) 155 | msg, err = this.Request("XaXb/HD_Enter", []byte(fmt.Sprintf(`{"BigRoomId":"%s"}`, BigRoomId))) 156 | if err != nil { 157 | return 158 | } 159 | fmt.Println(msg.Topic(), string(msg.Payload())) 160 | //坐下 161 | msg, err = this.Request("XaXb/HD_SitDown", []byte(fmt.Sprintf(`{"BigRoomId":"%s"}`, BigRoomId))) 162 | if err != nil { 163 | return 164 | } 165 | fmt.Println(msg.Topic(), string(msg.Payload())) 166 | 167 | } 168 | func (this *Work) Init(t task.Task) { 169 | 170 | } 171 | func (this *Work) Close(t task.Task) { 172 | this.GetClient().Disconnect(0) 173 | } 174 | -------------------------------------------------------------------------------- /robot/xaba_task.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 hey Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | package main 15 | 16 | import ( 17 | "fmt" 18 | "github.com/liangdas/armyant/task" 19 | "github.com/liangdas/mqantserver/robot/xaba" 20 | "os" 21 | "os/signal" 22 | ) 23 | 24 | func main() { 25 | 26 | task := task.LoopTask{ 27 | C: 100, //并发数 两人1桌 建立两张桌子 28 | } 29 | manager := xaba_task.NewManager(task) 30 | fmt.Println("开始压测请等待") 31 | task.Run(manager) 32 | c := make(chan os.Signal, 1) 33 | signal.Notify(c, os.Interrupt) 34 | <-c 35 | task.Stop() 36 | os.Exit(1) 37 | } 38 | -------------------------------------------------------------------------------- /server/chat/RPCListener.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 mqantserver Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | package chat 15 | 16 | import ( 17 | "fmt" 18 | "github.com/liangdas/mqant/gate" 19 | "github.com/liangdas/mqant/log" 20 | "github.com/liangdas/mqant/module" 21 | "github.com/liangdas/mqant/rpc" 22 | "github.com/liangdas/mqant/rpc/pb" 23 | "github.com/liangdas/mqant/rpc/util" 24 | "github.com/pkg/errors" 25 | ) 26 | 27 | type Listener struct { 28 | module module.RPCModule 29 | } 30 | 31 | func (l *Listener) BeforeHandle(fn string, callInfo *mqrpc.CallInfo) error { 32 | //放行 33 | for i, Type := range callInfo.RpcInfo.ArgsType { 34 | v, err := argsutil.Bytes2Args(l.module.GetApp(), Type, callInfo.RpcInfo.Args[i]) 35 | if err != nil { 36 | log.Error("BeforeHandle %v", err) 37 | continue 38 | } 39 | switch v2 := v.(type) { //多选语句switch 40 | case gate.Session: 41 | //尝试加载Span 42 | if v2 != nil { 43 | if v2 == nil { 44 | return fmt.Errorf("session 不能为nil") 45 | } 46 | if v2.GetUserId() == "" { 47 | return fmt.Errorf("必须先登录账号") 48 | } 49 | } 50 | } 51 | } 52 | 53 | return nil 54 | } 55 | func (l *Listener) NoFoundFunction(fn string) (*mqrpc.FunctionInfo, error) { 56 | return nil, errors.Errorf("Remote function(%s) not found", fn) 57 | } 58 | func (l *Listener) OnTimeOut(fn string, Expired int64) { 59 | log.Error("请求(%s)超时了!", fn) 60 | } 61 | func (l *Listener) OnError(fn string, callInfo *mqrpc.CallInfo, err error) { 62 | log.Error("请求(%s)出现异常 error(%s)!", fn, err.Error()) 63 | } 64 | 65 | /** 66 | fn 方法名 67 | params 参数 68 | result 执行结果 69 | exec_time 方法执行时间 单位为 Nano 纳秒 1000000纳秒等于1毫秒 70 | */ 71 | func (l *Listener) OnComplete(fn string, callInfo *mqrpc.CallInfo, result *rpcpb.ResultInfo, exec_time int64) { 72 | log.Info("请求(%s) 执行时间为:[%d 微妙]!", fn, exec_time/1000) 73 | } 74 | -------------------------------------------------------------------------------- /server/chat/module.go: -------------------------------------------------------------------------------- 1 | /** 2 | 一定要记得在confin.json配置这个模块的参数,否则无法使用 3 | */ 4 | package chat 5 | 6 | import ( 7 | "encoding/json" 8 | "github.com/liangdas/mqant/conf" 9 | "github.com/liangdas/mqant/gate" 10 | "github.com/liangdas/mqant/log" 11 | "github.com/liangdas/mqant/module" 12 | "github.com/liangdas/mqant/module/base" 13 | "time" 14 | ) 15 | 16 | var Module = func() module.Module { 17 | chat := new(Chat) 18 | return chat 19 | } 20 | 21 | type Chat struct { 22 | basemodule.BaseModule 23 | listener *Listener 24 | chats map[string]map[string]gate.Session 25 | } 26 | 27 | func (m *Chat) GetType() string { 28 | //很关键,需要与配置文件中的Module配置对应 29 | return "Chat" 30 | } 31 | func (m *Chat) Version() string { 32 | //可以在监控时了解代码版本 33 | return "1.0.0" 34 | } 35 | func (m *Chat) OnInit(app module.App, settings *conf.ModuleSettings) { 36 | //初始化模块 37 | m.BaseModule.OnInit(m, app, settings) 38 | 39 | m.chats = map[string]map[string]gate.Session{} 40 | //注册一个rpc事件监听器,可以用来统计rpc调用的异常,执行时长等状态 41 | m.listener = new(Listener) 42 | m.listener.module = m 43 | m.SetListener(m.listener) 44 | //注册远程调用的函数 45 | m.GetServer().RegisterGO("HD_JoinChat", m.joinChat) //我们约定所有对客户端的请求都以Handler_开头 46 | m.GetServer().RegisterGO("HD_Say", m.say) //我们约定所有对客户端的请求都以Handler_开头 47 | 48 | } 49 | 50 | func (m *Chat) Run(closeSig chan bool) { 51 | //运行模块 52 | } 53 | 54 | func (m *Chat) OnDestroy() { 55 | //注销模块 56 | //一定别忘了BaseModule.OnDestroy() 57 | m.BaseModule.OnDestroy() 58 | } 59 | 60 | func (m *Chat) joinChat(session gate.Session, msg map[string]interface{}) (result map[string]interface{}, err string) { 61 | if msg["roomName"] == "" { 62 | err = "roomName cannot be nil" 63 | return 64 | } 65 | log.TInfo(session, "session %v", session.GetSettings()) 66 | if session.GetUserId() == "" { 67 | err = "Not Logined" 68 | return 69 | } 70 | time.Sleep(time.Millisecond * 10) 71 | roomName := msg["roomName"].(string) 72 | r, e := m.RpcInvoke("Login", "track", session) 73 | 74 | log.TInfo(session, "演示模块间RPC调用 :", r, e) 75 | 76 | userList := m.chats[roomName] 77 | if userList == nil { 78 | //添加一个新的房间 79 | userList = map[string]gate.Session{session.GetUserId(): session} 80 | m.chats[roomName] = userList 81 | } else { 82 | //user:=userList[session.Userid] 83 | //if user!=nil{ 84 | //已经加入过这个聊天室了 不过这里还是替换一下session 因此用户可能是重连的 85 | //err="Already in this chat room" 86 | //userList[session.Userid]=session 87 | //return 88 | //} 89 | //添加这个用户进入聊天室 90 | userList[session.GetUserId()] = session 91 | } 92 | 93 | rmsg := map[string]interface{}{} 94 | rmsg["roomName"] = roomName 95 | rmsg["user"] = session.GetUserId() 96 | b, _ := json.Marshal(rmsg) 97 | 98 | userL := make([]string, len(userList)) 99 | //广播添加用户信息到该房间的所有用户 100 | i := 0 101 | for _, user := range userList { 102 | if user.GetUserId() != session.GetUserId() { 103 | //给其他用户发送消息 104 | err := user.Send("Chat/OnJoin", b) 105 | if err != "" { 106 | //信息没有发送成功 107 | m.onLeave(roomName, user.GetUserId()) 108 | } 109 | } 110 | userL[i] = user.GetUserId() 111 | i++ 112 | 113 | } 114 | result = map[string]interface{}{ 115 | "users": userL, 116 | } 117 | return 118 | } 119 | 120 | func (m *Chat) say(session gate.Session, msg map[string]interface{}) (result map[string]string, err string) { 121 | if msg["roomName"] == nil || msg["content"] == nil { 122 | err = "roomName or say cannot be nil" 123 | return 124 | } 125 | if session.GetUserId() == "" { 126 | err = "Not Logined" 127 | return 128 | } 129 | roomName := msg["roomName"].(string) 130 | //from:=msg["from"].(string) 131 | target := msg["target"].(string) 132 | content := msg["content"].(string) 133 | userList := m.chats[roomName] 134 | if userList == nil { 135 | err = "No room" 136 | return 137 | } else { 138 | user := userList[session.GetUserId()] 139 | if user == nil { 140 | err = "You haven't been in the room yet" 141 | return 142 | } 143 | rmsg := map[string]string{} 144 | rmsg["roomName"] = roomName 145 | rmsg["from"] = session.GetUserId() 146 | rmsg["target"] = target 147 | rmsg["msg"] = content 148 | b, _ := json.Marshal(rmsg) 149 | if target == "*" { 150 | //广播添加用户信息到该房间的所有用户 151 | for _, user := range userList { 152 | err := user.Send("Chat/OnChat", b) 153 | if err != "" { 154 | //信息没有发送成功 155 | m.onLeave(roomName, user.GetUserId()) 156 | } 157 | } 158 | } else { 159 | user := userList[target] 160 | if user == nil { 161 | err = "This user haven't been in the room yet" 162 | return 163 | } 164 | e := user.Send("Chat/OnChat", b) 165 | if e != "" { 166 | //信息没有发送成功 167 | m.onLeave(roomName, user.GetUserId()) 168 | err = "The user has left the room" 169 | return 170 | } 171 | } 172 | 173 | } 174 | result = map[string]string{ 175 | "say": "say success", 176 | } 177 | return 178 | } 179 | 180 | /** 181 | 用户 断开连接 广播离线消息 182 | */ 183 | func (m *Chat) onLeave(roomName string, Userid string) { 184 | userList := m.chats[roomName] 185 | if userList == nil { 186 | return 187 | } 188 | delete(userList, Userid) //从列表中删除 189 | rmsg := map[string]string{} 190 | rmsg["roomName"] = roomName 191 | rmsg["user"] = Userid 192 | b, _ := json.Marshal(rmsg) 193 | for _, user := range userList { 194 | user.SendNR("Chat/OnLeave", b) 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /server/gate/CustomAgent.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 loolgame Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | //与客户端通信的自定义粘包示例,需要mqant v1.6.4版本以上才能运行 15 | //该示例只用于简单的演示,并没有实现具体的粘包协议 16 | package mgate 17 | 18 | import ( 19 | "bufio" 20 | "github.com/liangdas/mqant/gate" 21 | "github.com/liangdas/mqant/log" 22 | "github.com/liangdas/mqant/module" 23 | "github.com/liangdas/mqant/network" 24 | "time" 25 | ) 26 | 27 | func NewAgent(module module.RPCModule) *CustomAgent { 28 | a := &CustomAgent{ 29 | module: module, 30 | } 31 | return a 32 | } 33 | 34 | type CustomAgent struct { 35 | gate.Agent 36 | module module.RPCModule 37 | session gate.Session 38 | conn network.Conn 39 | r *bufio.Reader 40 | w *bufio.Writer 41 | gate gate.Gate 42 | rev_num int64 43 | send_num int64 44 | last_storage_heartbeat_data_time time.Duration //上一次发送存储心跳时间 45 | isclose bool 46 | } 47 | 48 | func (this *CustomAgent) OnInit(gate gate.Gate, conn network.Conn) error { 49 | log.Info("CustomAgent", "OnInit") 50 | this.conn = conn 51 | this.gate = gate 52 | this.r = bufio.NewReader(conn) 53 | this.w = bufio.NewWriter(conn) 54 | this.isclose = false 55 | this.rev_num = 0 56 | this.send_num = 0 57 | return nil 58 | } 59 | 60 | /** 61 | 给客户端发送消息 62 | */ 63 | func (this *CustomAgent) WriteMsg(topic string, body []byte) error { 64 | this.send_num++ 65 | //粘包完成后调下面的语句发送数据 66 | //this.w.Write() 67 | return nil 68 | } 69 | 70 | func (this *CustomAgent) Run() (err error) { 71 | log.Info("CustomAgent", "开始读数据了") 72 | 73 | this.session, err = this.gate.NewSessionByMap(map[string]interface{}{ 74 | "Sessionid": "生成一个随机数", 75 | "Network": this.conn.RemoteAddr().Network(), 76 | "IP": this.conn.RemoteAddr().String(), 77 | "Serverid": this.module.GetServerId(), 78 | "Settings": make(map[string]string), 79 | }) 80 | 81 | //这里可以循环读取客户端的数据 82 | 83 | //这个函数返回后连接就会被关闭 84 | return nil 85 | } 86 | 87 | /** 88 | 接收到一个数据包 89 | */ 90 | func (this *CustomAgent) OnRecover(topic string, msg []byte) { 91 | //通过解析的数据得到 92 | moduleType := "" 93 | _func := "" 94 | 95 | //如果要对这个请求进行分布式跟踪调试,就执行下面这行语句 96 | //a.session.CreateRootSpan("gate") 97 | 98 | //然后请求后端模块,第一个参数为session 99 | result, e := this.module.RpcInvoke(moduleType, _func, this.session, msg) 100 | log.Info("result", result) 101 | log.Info("error", e) 102 | 103 | //回复客户端 104 | this.WriteMsg(topic, []byte("请求成功了谢谢")) 105 | 106 | this.heartbeat() 107 | } 108 | 109 | func (this *CustomAgent) heartbeat() { 110 | //自定义网关需要你自己设计心跳协议 111 | if this.GetSession().GetUserId() != "" { 112 | //这个链接已经绑定Userid 113 | interval := int64(this.last_storage_heartbeat_data_time) + int64(this.gate.Options().Heartbeat) //单位纳秒 114 | if interval < time.Now().UnixNano() { 115 | //如果用户信息存储心跳包的时长已经大于一秒 116 | if this.gate.GetStorageHandler() != nil { 117 | this.gate.GetStorageHandler().Heartbeat(this.GetSession()) 118 | this.last_storage_heartbeat_data_time = time.Duration(time.Now().UnixNano()) 119 | } 120 | } 121 | } 122 | } 123 | 124 | func (this *CustomAgent) Close() { 125 | log.Info("CustomAgent", "主动断开连接") 126 | this.conn.Close() 127 | } 128 | func (this *CustomAgent) OnClose() error { 129 | this.isclose = true 130 | log.Info("CustomAgent", "连接断开事件") 131 | //这个一定要调用,不然gate可能注销不了,造成内存溢出 132 | this.gate.GetAgentLearner().DisConnect(this) //发送连接断开的事件 133 | return nil 134 | } 135 | func (this *CustomAgent) Destroy() { 136 | this.conn.Destroy() 137 | } 138 | func (this *CustomAgent) RevNum() int64 { 139 | return this.rev_num 140 | } 141 | func (this *CustomAgent) SendNum() int64 { 142 | return this.send_num 143 | } 144 | func (this *CustomAgent) IsClosed() bool { 145 | return this.isclose 146 | } 147 | func (this *CustomAgent) GetSession() gate.Session { 148 | return this.session 149 | } 150 | -------------------------------------------------------------------------------- /server/gate/module.go: -------------------------------------------------------------------------------- 1 | /** 2 | 一定要记得在confin.json配置这个模块的参数,否则无法使用 3 | */ 4 | package mgate 5 | 6 | import ( 7 | "fmt" 8 | "github.com/liangdas/mqant/conf" 9 | "github.com/liangdas/mqant/gate" 10 | "github.com/liangdas/mqant/gate/base" 11 | "github.com/liangdas/mqant/log" 12 | "github.com/liangdas/mqant/module" 13 | "time" 14 | ) 15 | 16 | var Module = func() module.Module { 17 | gate := new(Gate) 18 | return gate 19 | } 20 | 21 | type Gate struct { 22 | basegate.Gate //继承 23 | } 24 | 25 | func (this *Gate) GetType() string { 26 | //很关键,需要与配置文件中的Module配置对应 27 | return "Gate" 28 | } 29 | func (this *Gate) Version() string { 30 | //可以在监控时了解代码版本 31 | return "1.0.0" 32 | } 33 | 34 | //与客户端通信的自定义粘包示例,需要mqant v1.6.4版本以上才能运行 35 | //该示例只用于简单的演示,并没有实现具体的粘包协议 36 | //去掉下面方法的注释就能启用这个自定义的粘包处理了,但也会造成demo都无法正常通行,因为demo都是用的mqtt粘包协议 37 | //func (this *Gate)CreateAgent() gate.Agent{ 38 | // agent:= NewAgent(this) 39 | // return agent 40 | //} 41 | 42 | func (this *Gate) OnInit(app module.App, settings *conf.ModuleSettings) { 43 | //注意这里一定要用 gate.Gate 而不是 module.BaseModule 44 | this.Gate.OnInit(this, app, settings, gate.Heartbeat(time.Second*10)) 45 | 46 | //与客户端通信的自定义粘包示例,需要mqant v1.6.4版本以上才能运行 47 | //该示例只用于简单的演示,并没有实现具体的粘包协议 48 | //去掉下面一行的注释就能启用这个自定义的粘包处理了,但也会造成demo都无法正常通行,因为demo都是用的mqtt粘包协议 49 | //gate.Gate.SetCreateAgent(gate.CreateAgent) 50 | 51 | this.Gate.SetSessionLearner(this) 52 | this.Gate.SetStorageHandler(this) //设置持久化处理器 53 | } 54 | 55 | //当连接建立 并且MQTT协议握手成功 56 | func (this *Gate) Connect(session gate.Session) { 57 | //log.Info("客户端建立了链接") 58 | } 59 | 60 | //当连接关闭 或者客户端主动发送MQTT DisConnect命令 ,这个函数中Session无法再继续后续的设置操作,只能读取部分配置内容了 61 | func (this *Gate) DisConnect(session gate.Session) { 62 | //log.Info("客户端断开了链接") 63 | } 64 | 65 | /** 66 | 是否需要对本次客户端请求进行跟踪 67 | */ 68 | func (gate *Gate) OnRequestTracing(session gate.Session, topic string, msg []byte) bool { 69 | if session.GetUserId() == "" { 70 | //没有登陆的用户不跟踪 71 | return false 72 | } 73 | //if session.GetUserid()!="liangdas"{ 74 | // //userId 不等于liangdas 的请求不跟踪 75 | // return false 76 | //} 77 | return true 78 | } 79 | 80 | /** 81 | 存储用户的Session信息 82 | Session Bind Userid以后每次设置 settings都会调用一次Storage 83 | */ 84 | func (gate *Gate) Storage(session gate.Session) (err error) { 85 | log.Info("需要处理对Session的持久化") 86 | return nil 87 | } 88 | 89 | /** 90 | 强制删除Session信息 91 | */ 92 | func (gate *Gate) Delete(session gate.Session) (err error) { 93 | log.Info("需要删除Session持久化数据") 94 | return nil 95 | } 96 | 97 | /** 98 | 获取用户Session信息 99 | 用户登录以后会调用Query获取最新信息 100 | */ 101 | func (gate *Gate) Query(Userid string) ([]byte, error) { 102 | log.Info("查询Session持久化数据") 103 | return nil, fmt.Errorf("no redis") 104 | } 105 | 106 | /** 107 | 用户心跳,一般用户在线时60s发送一次 108 | 可以用来延长Session信息过期时间 109 | */ 110 | func (gate *Gate) Heartbeat(session gate.Session) { 111 | log.Info("用户在线的心跳包") 112 | } 113 | -------------------------------------------------------------------------------- /server/helloworld/module.go: -------------------------------------------------------------------------------- 1 | /** 2 | 一定要记得在confin.json配置这个模块的参数,否则无法使用 3 | */ 4 | package helloworld 5 | 6 | import ( 7 | "fmt" 8 | "github.com/liangdas/mqant/conf" 9 | "github.com/liangdas/mqant/gate" 10 | "github.com/liangdas/mqant/module" 11 | "github.com/liangdas/mqant/module/base" 12 | ) 13 | 14 | var Module = func() module.Module { 15 | this := new(HellWorld) 16 | return this 17 | } 18 | 19 | type HellWorld struct { 20 | basemodule.BaseModule 21 | } 22 | 23 | func (m *HellWorld) GetType() string { 24 | //很关键,需要与配置文件中的Module配置对应 25 | return "HelloWorld" 26 | } 27 | func (m *HellWorld) Version() string { 28 | //可以在监控时了解代码版本 29 | return "1.0.0" 30 | } 31 | func (m *HellWorld) OnInit(app module.App, settings *conf.ModuleSettings) { 32 | m.BaseModule.OnInit(m, app, settings) 33 | 34 | m.GetServer().RegisterGO("HD_Say", m.say) //我们约定所有对客户端的请求都以HD_开头 35 | } 36 | 37 | func (m *HellWorld) Run(closeSig chan bool) { 38 | 39 | } 40 | 41 | func (m *HellWorld) OnDestroy() { 42 | //一定别忘了关闭RPC 43 | m.GetServer().OnDestroy() 44 | } 45 | func (m *HellWorld) say(session gate.Session, msg map[string]interface{}) (result string, err string) { 46 | if msg["say"] == nil { 47 | result = "say cannot be nil" 48 | return 49 | } 50 | say := msg["say"].(string) 51 | return fmt.Sprintf("you say : %s", say), "" 52 | } 53 | -------------------------------------------------------------------------------- /server/hitball/base_room.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 loolgame Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | package hitball 15 | 16 | import ( 17 | "fmt" 18 | "github.com/liangdas/mqant/module" 19 | "sync" 20 | ) 21 | 22 | type Room struct { 23 | module module.Module 24 | lock *sync.RWMutex 25 | tables map[int]*Table 26 | index int 27 | max int 28 | } 29 | 30 | func NewRoom(module module.Module) *Room { 31 | room := &Room{ 32 | module: module, 33 | lock: new(sync.RWMutex), 34 | tables: map[int]*Table{}, 35 | index: 0, 36 | max: 0, 37 | } 38 | return room 39 | } 40 | 41 | func (self *Room) create(module module.Module) *Table { 42 | self.lock.Lock() 43 | self.index++ 44 | table := NewTable(module, self.index) 45 | self.tables[self.index] = table 46 | self.lock.Unlock() 47 | return table 48 | } 49 | 50 | func (self *Room) GetTable(tableId int) *Table { 51 | if table, ok := self.tables[tableId]; ok { 52 | return table 53 | } 54 | return nil 55 | } 56 | 57 | func (self *Room) GetEmptyTable() (*Table, error) { 58 | for _, table := range self.tables { 59 | if table.Empty() { 60 | return table, nil 61 | } 62 | } 63 | //没有找到已创建的空房间,新创建一个 64 | table := self.create(self.module) 65 | if table == nil { 66 | return nil, fmt.Errorf("fail create table") 67 | } 68 | return table, nil 69 | } 70 | -------------------------------------------------------------------------------- /server/hitball/base_table.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 loolgame Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | package hitball 15 | 16 | import ( 17 | "fmt" 18 | "github.com/liangdas/mqant/log" 19 | "github.com/yireyun/go-queue" 20 | "reflect" 21 | "runtime" 22 | "sync" 23 | ) 24 | 25 | type QueueMsg struct { 26 | Func string 27 | Params []interface{} 28 | } 29 | type QueueReceive interface { 30 | Receive(msg *QueueMsg, index int) 31 | } 32 | type BaseTable struct { 33 | functions map[string]interface{} 34 | receive QueueReceive 35 | queue0 *queue.EsQueue 36 | queue1 *queue.EsQueue 37 | current_w_queue int //当前写的队列 38 | lock *sync.RWMutex 39 | } 40 | 41 | func (self *BaseTable) Init() { 42 | self.functions = map[string]interface{}{} 43 | self.queue0 = queue.NewQueue(256) 44 | self.queue1 = queue.NewQueue(256) 45 | self.current_w_queue = 0 46 | self.lock = new(sync.RWMutex) 47 | } 48 | func (self *BaseTable) SetReceive(receive QueueReceive) { 49 | self.receive = receive 50 | } 51 | func (self *BaseTable) Register(id string, f interface{}) { 52 | 53 | if _, ok := self.functions[id]; ok { 54 | panic(fmt.Sprintf("function id %v: already registered", id)) 55 | } 56 | 57 | self.functions[id] = f 58 | } 59 | 60 | /** 61 | 协成安全,任意协成可调用 62 | */ 63 | func (self *BaseTable) PutQueue(_func string, params ...interface{}) error { 64 | ok, quantity := self.wqueue().Put(&QueueMsg{ 65 | Func: _func, 66 | Params: params, 67 | }) 68 | if !ok { 69 | return fmt.Errorf("Put Fail, quantity:%v\n", quantity) 70 | } else { 71 | return nil 72 | } 73 | 74 | } 75 | 76 | /** 77 | 切换并且返回读的队列 78 | */ 79 | func (self *BaseTable) switchqueue() *queue.EsQueue { 80 | self.lock.Lock() 81 | if self.current_w_queue == 0 { 82 | self.current_w_queue = 1 83 | self.lock.Unlock() 84 | return self.queue0 85 | } else { 86 | self.current_w_queue = 0 87 | self.lock.Unlock() 88 | return self.queue1 89 | } 90 | 91 | } 92 | func (self *BaseTable) wqueue() *queue.EsQueue { 93 | self.lock.Lock() 94 | if self.current_w_queue == 0 { 95 | self.lock.Unlock() 96 | return self.queue0 97 | } else { 98 | self.lock.Unlock() 99 | return self.queue1 100 | } 101 | 102 | } 103 | 104 | /** 105 | 【每帧调用】执行队列中的所有事件 106 | */ 107 | func (self *BaseTable) ExecuteEvent(arge interface{}) { 108 | ok := true 109 | queue := self.switchqueue() 110 | index := 0 111 | for ok { 112 | val, _ok, _ := queue.Get() 113 | index++ 114 | if _ok { 115 | if self.receive != nil { 116 | self.receive.Receive(val.(*QueueMsg), index) 117 | } else { 118 | msg := val.(*QueueMsg) 119 | function, ok := self.functions[msg.Func] 120 | if !ok { 121 | fmt.Println(fmt.Sprintf("Remote function(%s) not found", msg.Func)) 122 | continue 123 | } 124 | f := reflect.ValueOf(function) 125 | in := make([]reflect.Value, len(msg.Params)) 126 | for k, _ := range in { 127 | in[k] = reflect.ValueOf(msg.Params[k]) 128 | } 129 | _runFunc := func() { 130 | defer func() { 131 | if r := recover(); r != nil { 132 | var rn = "" 133 | switch r.(type) { 134 | 135 | case string: 136 | rn = r.(string) 137 | case error: 138 | rn = r.(error).Error() 139 | } 140 | buf := make([]byte, 1024) 141 | l := runtime.Stack(buf, false) 142 | errstr := string(buf[:l]) 143 | log.Error("table qeueu event(%s) exec fail error:%s \n ----Stack----\n %s", msg.Func, rn, errstr) 144 | } 145 | }() 146 | f.Call(in) 147 | } 148 | _runFunc() 149 | } 150 | } 151 | ok = _ok 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /server/hitball/module.go: -------------------------------------------------------------------------------- 1 | /** 2 | 一定要记得在confin.json配置这个模块的参数,否则无法使用 3 | */ 4 | package hitball 5 | 6 | import ( 7 | "encoding/json" 8 | "github.com/liangdas/mqant/conf" 9 | "github.com/liangdas/mqant/gate" 10 | "github.com/liangdas/mqant/log" 11 | "github.com/liangdas/mqant/module" 12 | "github.com/liangdas/mqant/module/base" 13 | "math/rand" 14 | "time" 15 | ) 16 | 17 | var Module = func() module.Module { 18 | gate := new(Hitball) 19 | return gate 20 | } 21 | 22 | type Hitball struct { 23 | basemodule.BaseModule 24 | room *Room 25 | proTime int64 26 | table *Table 27 | } 28 | 29 | //生成随机字符串 30 | func GetRandomString(lenght int) string { 31 | str := "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" 32 | bytes := []byte(str) 33 | result := []byte{} 34 | r := rand.New(rand.NewSource(time.Now().UnixNano())) 35 | for i := 0; i < lenght; i++ { 36 | result = append(result, bytes[r.Intn(len(bytes))]) 37 | } 38 | return string(result) 39 | } 40 | func (self *Hitball) GetType() string { 41 | //很关键,需要与配置文件中的Module配置对应 42 | return "Hitball" 43 | } 44 | func (self *Hitball) Version() string { 45 | //可以在监控时了解代码版本 46 | return "1.0.0" 47 | } 48 | func (self *Hitball) OnInit(app module.App, settings *conf.ModuleSettings) { 49 | self.BaseModule.OnInit(self, app, settings) 50 | self.room = NewRoom(self) 51 | self.table, _ = self.room.GetEmptyTable() 52 | //self.SetListener(new(chat.Listener)) 53 | self.GetServer().RegisterGO("HD_Move", self.move) 54 | self.GetServer().RegisterGO("HD_Join", self.join) 55 | self.GetServer().RegisterGO("HD_Fire", self.fire) 56 | self.GetServer().RegisterGO("HD_EatCoin", self.eatCoin) 57 | } 58 | 59 | func (self *Hitball) Run(closeSig chan bool) { 60 | self.table.Start() 61 | } 62 | 63 | func (self *Hitball) OnDestroy() { 64 | //一定别忘了关闭RPC 65 | self.GetServer().OnDestroy() 66 | } 67 | 68 | func (self *Hitball) join(session gate.Session, msg map[string]interface{}) (result string, err string) { 69 | if session.GetUserId() == "" { 70 | session.Bind(GetRandomString(8)) 71 | //return "","no login" 72 | } 73 | erro := self.table.PutQueue("Join", session) 74 | if erro != nil { 75 | return "", erro.Error() 76 | } 77 | return "success", "" 78 | } 79 | 80 | func (self *Hitball) fire(session gate.Session, msg map[string]interface{}) (result string, err string) { 81 | if msg["Angle"] == nil || msg["Power"] == nil || msg["X"] == nil || msg["Y"] == nil { 82 | err = "Angle , Power X ,Y cannot be nil" 83 | return 84 | } 85 | Angle := msg["Angle"].(float64) 86 | Power := msg["Power"].(float64) 87 | X := msg["X"].(float64) 88 | Y := msg["Y"].(float64) 89 | erro := self.table.PutQueue("Fire", session, float64(X), float64(Y), float64(Angle), float64(Power)) 90 | if erro != nil { 91 | return "", erro.Error() 92 | } 93 | return "success", "" 94 | } 95 | 96 | func (self *Hitball) eatCoin(session gate.Session, msg map[string]interface{}) (result string, err string) { 97 | if msg["Id"] == nil { 98 | err = "Id cannot be nil" 99 | return 100 | } 101 | Id := int(msg["Id"].(float64)) 102 | erro := self.table.PutQueue("EatCoins", session, Id) 103 | if erro != nil { 104 | return "", erro.Error() 105 | } 106 | return "success", "" 107 | } 108 | 109 | func (self *Hitball) move(session gate.Session, msg map[string]interface{}) (result string, err string) { 110 | if msg["war"] == nil || msg["wid"] == nil || msg["x"] == nil || msg["y"] == nil { 111 | err = "war , wid ,x ,y cannot be nil" 112 | return 113 | } 114 | //log.Debug("exct time %d", (time.Now().UnixNano()-self.proTime)/1000000) 115 | //self.proTime = time.Now().UnixNano() 116 | //war := msg["war"].(string) 117 | //wid := msg["wid"].(string) 118 | x := msg["x"].(float64) 119 | y := msg["y"].(float64) 120 | //passWord:=msg["passWord"].(string) 121 | roles := []map[string]float64{ 122 | map[string]float64{ 123 | "x": x, 124 | "y": y, 125 | }, 126 | } 127 | re := map[string]interface{}{} 128 | re["roles"] = roles 129 | b, _ := json.Marshal(re) 130 | e := session.SendNR("Hitball/OnMove", b) 131 | if e != "" { 132 | log.Error(e) 133 | } 134 | //log.Debug(fmt.Sprintf("move success x:%v,y:%v", x, y)) 135 | return "success", "" 136 | } 137 | -------------------------------------------------------------------------------- /server/hitball/objects/coins.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 loolgame Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | package objects 15 | 16 | type Coins struct { 17 | Id int 18 | X float64 19 | Y float64 20 | Wid int 21 | Type int 22 | } 23 | -------------------------------------------------------------------------------- /server/hitball/objects/player.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 loolgame Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | package objects 15 | 16 | import ( 17 | "github.com/liangdas/mqant/gate" 18 | "math" 19 | "time" 20 | ) 21 | 22 | type Player struct { 23 | Session gate.Session 24 | Rid string //角色ID userid 25 | SitDown bool //是否已坐下 ,如果网络断开会设置为false,当网络连接成功以后需要重新坐下 26 | NetBroken int64 //网络中断时间,超过60秒就踢出房间或者做其他处理 单位/秒 27 | LastRequestDate int64 //玩家最后一次请求时间 单位纳秒 28 | X float64 29 | Y float64 30 | Wid int 31 | XSpeed float64 32 | YSpeed float64 33 | RotateDirection int // rotate direction: 1-clockwise, 2-counterclockwise 34 | BallRadius float64 35 | Angle float64 36 | Power float64 37 | 38 | RotateSpeed int 39 | DegToRad float64 40 | MinPower float64 41 | MaxPower float64 42 | } 43 | 44 | /** 45 | 玩家主动发请求时间 46 | */ 47 | func (self *Player) OnRequest(session gate.Session) { 48 | self.Session = session 49 | self.LastRequestDate = time.Now().UnixNano() 50 | } 51 | 52 | func (self *Player) OnSitDown() { 53 | self.SitDown = true 54 | } 55 | 56 | func (self *Player) OnSitUp() { 57 | self.SitDown = false 58 | } 59 | 60 | func (self *Player) OnNetBroken() { 61 | self.NetBroken = time.Now().Unix() 62 | } 63 | 64 | func (self *Player) Move(friction float64) { 65 | self.X = self.X + self.XSpeed 66 | self.Y = self.Y + self.YSpeed 67 | // reduce ball speed using friction 速度递减 68 | self.XSpeed *= friction 69 | self.YSpeed *= friction 70 | } 71 | 72 | func (self *Player) Rotate() { 73 | self.Angle += float64(self.RotateSpeed * self.RotateDirection) 74 | } 75 | func (self *Player) Fire(X float64, Y float64, angle float64, power float64) { 76 | //发射 77 | self.XSpeed += math.Cos(angle*self.DegToRad) * power / 20 78 | self.YSpeed += math.Sin(angle*self.DegToRad) * power / 20 79 | self.Power = self.MinPower 80 | //self.Angle=angle //这里不同步客户端发过来的角速度 81 | self.X = X 82 | self.Y = Y 83 | self.Power = power 84 | self.RotateDirection *= -1 85 | } 86 | -------------------------------------------------------------------------------- /server/hitball/table_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 loolgame Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | package hitball 15 | 16 | import ( 17 | "fmt" 18 | "runtime" 19 | "testing" 20 | "time" 21 | ) 22 | 23 | func TestTable(t *testing.T) { 24 | stoped := false 25 | table := NewTable() 26 | index := 0 27 | runtime.GOMAXPROCS(runtime.NumCPU()) 28 | go func() { 29 | //这里设置为22ms但实际上每次循环大概是23-25ms左右,根据机器定,客户端设置的帧为40 30 | tick := time.NewTicker(22 * time.Millisecond) 31 | for !stoped { 32 | select { 33 | case <-tick.C: 34 | table.Update(nil) 35 | } 36 | } 37 | }() 38 | go func() { 39 | //这里设置为22ms但实际上每次循环大概是23-25ms左右,根据机器定,客户端设置的帧为40 40 | tick := time.NewTicker(6 * time.Millisecond) 41 | for index <= 5000 { 42 | select { 43 | case <-tick.C: 44 | err := table.PutQueue("EatCoins", "127.0.0.1", 1) 45 | if err != nil { 46 | fmt.Println("PutQueue", err.Error()) 47 | } 48 | index++ 49 | } 50 | } 51 | fmt.Println("PutQueue end 1") 52 | }() 53 | go func() { 54 | //这里设置为22ms但实际上每次循环大概是23-25ms左右,根据机器定,客户端设置的帧为40 55 | tick := time.NewTicker(6 * time.Millisecond) 56 | for index <= 5000 { 57 | select { 58 | case <-tick.C: 59 | err := table.PutQueue("Fire", "127.0.0.1", float64(30), float64(45), float64(23), float64(43)) 60 | if err != nil { 61 | fmt.Println("PutQueue", err.Error()) 62 | } 63 | index++ 64 | } 65 | } 66 | fmt.Println("PutQueue end 2") 67 | }() 68 | for index <= 5000 { 69 | 70 | } 71 | stoped = true 72 | time.Sleep(1 * time.Second) 73 | 74 | } 75 | -------------------------------------------------------------------------------- /server/login/module.go: -------------------------------------------------------------------------------- 1 | /** 2 | 一定要记得在confin.json配置这个模块的参数,否则无法使用 3 | */ 4 | package login 5 | 6 | import ( 7 | "fmt" 8 | "github.com/liangdas/mqant/conf" 9 | "github.com/liangdas/mqant/gate" 10 | "github.com/liangdas/mqant/log" 11 | "github.com/liangdas/mqant/module" 12 | "github.com/liangdas/mqant/module/base" 13 | "math/rand" 14 | "time" 15 | ) 16 | 17 | var Module = func() module.Module { 18 | gate := new(Login) 19 | return gate 20 | } 21 | 22 | type Login struct { 23 | basemodule.BaseModule 24 | } 25 | 26 | func (m *Login) GetType() string { 27 | //很关键,需要与配置文件中的Module配置对应 28 | return "Login" 29 | } 30 | func (m *Login) Version() string { 31 | //可以在监控时了解代码版本 32 | return "1.0.0" 33 | } 34 | func (m *Login) OnInit(app module.App, settings *conf.ModuleSettings) { 35 | m.BaseModule.OnInit(m, app, settings) 36 | 37 | m.GetServer().RegisterGO("HD_Login", m.login) //我们约定所有对客户端的请求都以Handler_开头 38 | m.GetServer().RegisterGO("track", m.track) //演示后台模块间的rpc调用 39 | m.GetServer().RegisterGO("track2", m.track2) //演示后台模块间的rpc调用 40 | m.GetServer().RegisterGO("track3", m.track3) //演示后台模块间的rpc调用 41 | m.GetServer().Register("HD_Robot", m.robot) 42 | m.GetServer().RegisterGO("HD_Robot_GO", m.robot) //我们约定所有对客户端的请求都以Handler_开头 43 | } 44 | 45 | func (m *Login) Run(closeSig chan bool) { 46 | } 47 | 48 | func (m *Login) OnDestroy() { 49 | //一定别忘了关闭RPC 50 | m.GetServer().OnDestroy() 51 | } 52 | func (m *Login) robot(session gate.Session, msg map[string]interface{}) (result string, err string) { 53 | //time.Sleep(1) 54 | return "sss", "" 55 | } 56 | func (m *Login) login(session gate.Session, msg map[string]interface{}) (result string, err string) { 57 | if msg["userName"] == nil || msg["passWord"] == nil { 58 | result = "userName or passWord cannot be nil" 59 | return 60 | } 61 | userName := msg["userName"].(string) 62 | err = session.Bind(userName) 63 | if err != "" { 64 | return 65 | } 66 | session.Set("login", "true") 67 | session.Push() //推送到网关 68 | return fmt.Sprintf("login success %s", userName), "" 69 | } 70 | 71 | func (m *Login) track(session gate.Session) (result string, err string) { 72 | //演示后台模块间的rpc调用 73 | time.Sleep(time.Millisecond * 10) 74 | log.TInfo(session, "Login %v", "track1") 75 | m.RpcInvoke("Login", "track2", session) 76 | return fmt.Sprintf("My is Login Module %s"), "" 77 | } 78 | 79 | func (m *Login) track2(session gate.Session) (result string, err string) { 80 | //演示后台模块间的rpc调用 81 | time.Sleep(time.Millisecond * 10) 82 | log.TInfo(session, "Login %v", "track2") 83 | r := rand.Intn(100) 84 | if r > 30 { 85 | m.RpcInvoke("Login", "track3", session) 86 | } 87 | 88 | return fmt.Sprintf("My is Login Module"), "" 89 | } 90 | func (m *Login) track3(session gate.Session) (result string, err string) { 91 | //演示后台模块间的rpc调用 92 | time.Sleep(time.Millisecond * 10) 93 | log.TInfo(session, "Login %v", "track3") 94 | return fmt.Sprintf("My is Login Module"), "" 95 | } 96 | -------------------------------------------------------------------------------- /server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/liangdas/mqant" 5 | "github.com/liangdas/mqant/gate" 6 | "github.com/liangdas/mqant/module/modules" 7 | "github.com/nats-io/nats.go" 8 | 9 | //"github.com/liangdas/mqant-modules/tracing" 10 | "fmt" 11 | "github.com/liangdas/mqant/module" 12 | "github.com/liangdas/mqant/registry" 13 | "github.com/liangdas/mqant/selector" 14 | "github.com/liangdas/mqantserver/server/chat" 15 | "github.com/liangdas/mqantserver/server/gate" 16 | "github.com/liangdas/mqantserver/server/helloworld" 17 | "github.com/liangdas/mqantserver/server/hitball" 18 | "github.com/liangdas/mqantserver/server/login" 19 | "github.com/liangdas/mqantserver/server/user" 20 | "github.com/liangdas/mqantserver/server/xaxb" 21 | "github.com/liangdas/mqantserver/webapp" 22 | "math/rand" 23 | "net/http" 24 | _ "net/http/pprof" 25 | "sync" 26 | ) 27 | 28 | func main() { 29 | go func() { 30 | http.ListenAndServe("0.0.0.0:6060", nil) 31 | }() 32 | rs := registry.DefaultRegistry //etcdv3.NewRegistry() 33 | nc, err := nats.Connect(nats.DefaultURL, nats.MaxReconnects(10000)) 34 | if err != nil { 35 | 36 | } 37 | app := mqant.CreateApp( 38 | module.Debug(true),//只有是在调试模式下才会在控制台打印日志, 非调试模式下只在日志文件中输出日志 39 | module.Nats(nc), 40 | module.Registry(rs), 41 | module.SetJudgeGuest(func(session gate.Session) bool { 42 | if session.GetUserId()==""{ 43 | return true 44 | }else{ 45 | return false 46 | } 47 | }), 48 | ) 49 | app.Options().Selector.Init(selector.SetStrategy(func(services []*registry.Service) selector.Next { 50 | var nodes []*registry.Node 51 | 52 | // Filter the nodes for datacenter 53 | for _, service := range services { 54 | for _, node := range service.Nodes { 55 | nodes = append(nodes, node) 56 | //if node.Metadata["type"] == "helloworld" { 57 | // nodes = append(nodes, node) 58 | //} 59 | } 60 | } 61 | 62 | var mtx sync.Mutex 63 | //log.Info("services[0] $v",services[0].Nodes[0]) 64 | return func() (*registry.Node, error) { 65 | mtx.Lock() 66 | defer mtx.Unlock() 67 | if len(nodes) == 0 { 68 | return nil, fmt.Errorf("no node") 69 | } 70 | index := rand.Intn(int(len(nodes))) 71 | return nodes[index], nil 72 | } 73 | })) 74 | //app.Route("Chat",ChatRoute) 75 | app.Run( //只有是在调试模式下才会在控制台打印日志, 非调试模式下只在日志文件中输出日志 76 | modules.MasterModule(), 77 | hitball.Module(), 78 | mgate.Module(), //这是默认网关模块,是必须的支持 TCP,websocket,MQTT协议 79 | helloworld.Module(), 80 | login.Module(), //这是用户登录验证模块 81 | chat.Module(), 82 | user.Module(), 83 | webapp.Module(), 84 | xaxb.Module(), 85 | //tracing.Module(), //很多初学者不会改文件路径,先移除了 86 | ) //这是聊天模块 87 | 88 | } 89 | -------------------------------------------------------------------------------- /server/user/module.go: -------------------------------------------------------------------------------- 1 | /** 2 | 一定要记得在confin.json配置这个模块的参数,否则无法使用 3 | */ 4 | package user 5 | 6 | import ( 7 | "fmt" 8 | "github.com/liangdas/mqant/conf" 9 | "github.com/liangdas/mqant/module" 10 | "github.com/liangdas/mqant/module/base" 11 | ) 12 | 13 | var Module = func() module.Module { 14 | user := new(User) 15 | return user 16 | } 17 | 18 | type User struct { 19 | basemodule.BaseModule 20 | } 21 | 22 | func (self *User) GetType() string { 23 | //很关键,需要与配置文件中的Module配置对应 24 | return "User" 25 | } 26 | func (self *User) Version() string { 27 | //可以在监控时了解代码版本 28 | return "1.0.0" 29 | } 30 | func (self *User) OnInit(app module.App, settings *conf.ModuleSettings) { 31 | self.BaseModule.OnInit(self, app, settings) 32 | 33 | self.GetServer().RegisterGO("mongodb", self.mongodb) //演示后台模块间的rpc调用 34 | } 35 | 36 | func (self *User) Run(closeSig chan bool) { 37 | } 38 | 39 | func (self *User) OnDestroy() { 40 | //一定别忘了关闭RPC 41 | self.GetServer().OnDestroy() 42 | } 43 | 44 | func (self *User) mongodb() (rpc_result string, rpc_err string) { 45 | 46 | return fmt.Sprintf("My is Login Module"), "" 47 | } 48 | -------------------------------------------------------------------------------- /server/user/module_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 loolgame Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | package user 15 | 16 | import "testing" 17 | 18 | func TestUser_mongodb(t *testing.T) { 19 | user := new(User) 20 | r, err := user.mongodb() 21 | if err != "" { 22 | t.Errorf(err) 23 | } else { 24 | t.Log(r) 25 | } 26 | } 27 | 28 | //性能测试 29 | func BenchmarkUser_mongodb(b *testing.B) { 30 | user := new(User) 31 | for i := 0; i < b.N; i++ { 32 | user.mongodb() 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /server/xaxb/action.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 loolgame Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | package xaxb 15 | 16 | import ( 17 | "encoding/json" 18 | "fmt" 19 | "github.com/liangdas/mqant-modules/room" 20 | "github.com/liangdas/mqant/gate" 21 | "github.com/liangdas/mqantserver/server/xaxb/objects" 22 | ) 23 | 24 | func (self *Table) SitDown(session gate.Session) error { 25 | playerImp := self.GetBindPlayer(session) 26 | if playerImp != nil { 27 | player := playerImp.(*objects.Player) 28 | player.OnRequest(session) 29 | player.OnSitDown() 30 | return nil 31 | } 32 | return nil 33 | } 34 | func (self *Table) StartGame(session gate.Session) error { 35 | playerImp := self.GetBindPlayer(session) 36 | if playerImp != nil { 37 | player := playerImp.(*objects.Player) 38 | player.OnRequest(session) 39 | player.OnSitDown() 40 | if self.State() == room.Active { 41 | 42 | } else if self.State() == room.Initialized { 43 | self.Start() 44 | } else if self.State() == room.Paused { 45 | self.Resume() 46 | } 47 | return nil 48 | } 49 | return nil 50 | } 51 | 52 | func (self *Table) PauseGame(session gate.Session) error { 53 | playerImp := self.GetBindPlayer(session) 54 | if playerImp != nil { 55 | player := playerImp.(*objects.Player) 56 | player.OnRequest(session) 57 | player.OnSitDown() 58 | self.Pause() 59 | return nil 60 | } 61 | return nil 62 | } 63 | 64 | /** 65 | 玩家加入场景 66 | */ 67 | func (self *Table) Join(session gate.Session) error { 68 | self.writelock.Lock() 69 | defer self.writelock.Unlock() 70 | player := self.GetBindPlayer(session) 71 | if player != nil { 72 | playerImp := player.(*objects.Player) 73 | playerImp.OnRequest(session) 74 | 75 | //回复当前状态 76 | result := map[string]interface{}{ 77 | "State": self.State(), 78 | "Rid": player.Session().GetUserId(), 79 | "SeatIndex": playerImp.SeatIndex, 80 | } 81 | b, _ := json.Marshal(result) 82 | session.Send("XaXb/OnEnter", b) 83 | 84 | return nil 85 | } 86 | var indexSeat int = -1 87 | for i, player := range self.seats { 88 | if !player.Bind() { 89 | indexSeat = i 90 | player.OnBind(session) 91 | self.NotifyJoin(player) //广播给所有其他玩家 92 | 93 | result := map[string]interface{}{ 94 | "State": self.State(), 95 | "Rid": player.Session().GetUserId(), 96 | "SeatIndex": indexSeat, 97 | } 98 | b, _ := json.Marshal(result) 99 | session.Send("XaXb/OnEnter", b) 100 | break 101 | } 102 | } 103 | 104 | if indexSeat == -1 { 105 | //没有位置了,加入到观众列表 106 | //for e := self.viewer.Front(); e != nil; e = e.Next() { 107 | // if e.Value.(gate.Session).GetUserid()==session.GetUserid(){ 108 | // return nil 109 | // } 110 | //} 111 | //self.viewer.PushBack(session) 112 | // 113 | //result:=map[string]interface{}{ 114 | // "Rid":"", 115 | // "SeatIndex":indexSeat, 116 | //} 117 | //b, _ := json.Marshal(result) 118 | //session.Send("Shoot/OnEnter", b) 119 | return fmt.Errorf("房间已满,无法加入游戏") 120 | } 121 | return nil 122 | } 123 | 124 | /** 125 | 玩家押注 126 | */ 127 | func (self *Table) Stake(session gate.Session, target int64) error { 128 | playerImp := self.GetBindPlayer(session) 129 | if playerImp != nil { 130 | player := playerImp.(*objects.Player) 131 | player.OnRequest(session) 132 | player.OnSitDown() 133 | player.Target = target 134 | player.Stake = true 135 | player.Coin -= 500 136 | return nil 137 | } 138 | return nil 139 | } 140 | -------------------------------------------------------------------------------- /server/xaxb/fsm.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 loolgame Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // fsm.go 15 | package xaxb 16 | 17 | import ( 18 | "fmt" 19 | "sync" 20 | ) 21 | 22 | type FSMState string // 状态 23 | type FSMEvent string // 事件 24 | type FSMHandler func() FSMState // 处理方法,并返回新的状态 25 | 26 | // 有限状态机 27 | type FSM struct { 28 | mu sync.Mutex // 排他锁 29 | state FSMState // 当前状态 30 | handlers map[FSMState]map[FSMEvent]FSMHandler // 处理地图集,每一个状态都可以出发有限个事件,执行有限个处理 31 | } 32 | 33 | // 获取当前状态 34 | func (f *FSM) getState() FSMState { 35 | return f.state 36 | } 37 | 38 | // 设置当前状态 39 | func (f *FSM) setState(newState FSMState) { 40 | f.state = newState 41 | } 42 | 43 | // 某状态添加事件处理方法 44 | func (f *FSM) AddHandler(state FSMState, event FSMEvent, handler FSMHandler) *FSM { 45 | if _, ok := f.handlers[state]; !ok { 46 | f.handlers[state] = make(map[FSMEvent]FSMHandler) 47 | } 48 | if _, ok := f.handlers[state][event]; ok { 49 | fmt.Printf("[警告] 状态(%s)事件(%s)已定义过", state, event) 50 | } 51 | f.handlers[state][event] = handler 52 | return f 53 | } 54 | 55 | // 事件处理 56 | func (f *FSM) Call(event FSMEvent) FSMState { 57 | f.mu.Lock() 58 | defer f.mu.Unlock() 59 | events := f.handlers[f.getState()] 60 | if events == nil { 61 | return f.getState() 62 | } 63 | if fn, ok := events[event]; ok { 64 | oldState := f.getState() 65 | f.setState(fn()) 66 | newState := f.getState() 67 | fmt.Println("状态从 [", oldState, "] 变成 [", newState, "]") 68 | } 69 | return f.getState() 70 | } 71 | 72 | // 实例化FSM 73 | func NewFSM(initState FSMState) *FSM { 74 | return &FSM{ 75 | state: initState, 76 | handlers: make(map[FSMState]map[FSMEvent]FSMHandler), 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /server/xaxb/logic.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 loolgame Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | package xaxb 15 | 16 | import ( 17 | "fmt" 18 | "github.com/liangdas/mqant/utils" 19 | "github.com/liangdas/mqantserver/server/xaxb/objects" 20 | "math" 21 | ) 22 | 23 | var ( 24 | VoidPeriod = FSMState("空档期") 25 | IdlePeriod = FSMState("空闲期") 26 | BettingPeriod = FSMState("押注期") 27 | OpeningPeriod = FSMState("开奖期") 28 | SettlementPeriod = FSMState("结算期") 29 | VoidPeriodEvent = FSMEvent("进入空档期") 30 | IdlePeriodEvent = FSMEvent("进入空闲期") 31 | BettingPeriodEvent = FSMEvent("进入押注期") 32 | OpeningPeriodEvent = FSMEvent("进入开奖期") 33 | SettlementPeriodEvent = FSMEvent("进入结算期") 34 | ) 35 | 36 | func (this *Table) InitFsm() { 37 | this.fsm = *NewFSM(VoidPeriod) 38 | this.VoidPeriodHandler = FSMHandler(func() FSMState { 39 | fmt.Println("已进入空档期") 40 | return VoidPeriod 41 | }) 42 | this.IdlePeriodHandler = FSMHandler(func() FSMState { 43 | fmt.Println("已进入空闲期") 44 | this.step1 = this.current_frame 45 | this.NotifyIdle() 46 | 47 | for _, seat := range this.GetSeats() { 48 | player := seat.(*objects.Player) 49 | if player.Bind() { 50 | if player.Coin <= 0 { 51 | player.Session().Send("XaXb/Exit", []byte(`{"Info":"金币不足你被强制离开房间"}`)) 52 | player.OnUnBind() //踢下线 53 | } 54 | } 55 | } 56 | 57 | return IdlePeriod 58 | }) 59 | this.BettingPeriodHandler = FSMHandler(func() FSMState { 60 | fmt.Println("已进入押注期") 61 | this.step2 = this.current_frame 62 | this.NotifyBetting() 63 | return BettingPeriod 64 | }) 65 | this.OpeningPeriodHandler = FSMHandler(func() FSMState { 66 | fmt.Println("已进入开奖期") 67 | this.step3 = this.current_frame 68 | this.NotifyOpening() 69 | return OpeningPeriod 70 | }) 71 | this.SettlementPeriodHandler = FSMHandler(func() FSMState { 72 | fmt.Println("已进入结算期") 73 | var mixWeight int64 = math.MaxInt64 74 | var winer *objects.Player = nil 75 | Result := utils.RandInt64(0, 10) 76 | for _, seat := range this.GetSeats() { 77 | player := seat.(*objects.Player) 78 | if player.Stake { 79 | player.Weight = int64(math.Abs(float64(player.Target - Result))) 80 | if mixWeight > player.Weight { 81 | mixWeight = player.Weight 82 | winer = player 83 | } 84 | } 85 | } 86 | if winer != nil { 87 | winer.Coin += 800 88 | } 89 | 90 | this.step4 = this.current_frame 91 | this.NotifySettlement(Result) 92 | return SettlementPeriod 93 | }) 94 | 95 | this.fsm.AddHandler(IdlePeriod, VoidPeriodEvent, this.VoidPeriodHandler) 96 | this.fsm.AddHandler(SettlementPeriod, VoidPeriodEvent, this.VoidPeriodHandler) 97 | this.fsm.AddHandler(BettingPeriod, VoidPeriodEvent, this.VoidPeriodHandler) 98 | this.fsm.AddHandler(OpeningPeriod, VoidPeriodEvent, this.VoidPeriodHandler) 99 | 100 | this.fsm.AddHandler(VoidPeriod, IdlePeriodEvent, this.IdlePeriodHandler) 101 | this.fsm.AddHandler(SettlementPeriod, IdlePeriodEvent, this.IdlePeriodHandler) 102 | 103 | this.fsm.AddHandler(IdlePeriod, BettingPeriodEvent, this.BettingPeriodHandler) 104 | this.fsm.AddHandler(BettingPeriod, OpeningPeriodEvent, this.OpeningPeriodHandler) 105 | this.fsm.AddHandler(OpeningPeriod, SettlementPeriodEvent, this.SettlementPeriodHandler) 106 | } 107 | 108 | /** 109 | 进入空闲期 110 | */ 111 | func (this *Table) StateSwitch() { 112 | switch this.fsm.getState() { 113 | case VoidPeriod: 114 | 115 | case IdlePeriod: 116 | if (this.current_frame - this.step1) > 5 { 117 | this.fsm.Call(BettingPeriodEvent) 118 | } else { 119 | //this.NotifyAxes() 120 | } 121 | case BettingPeriod: 122 | if (this.current_frame - this.step2) > 20 { 123 | this.fsm.Call(OpeningPeriodEvent) 124 | } else { 125 | ready := true 126 | for _, seat := range this.GetSeats() { 127 | player := seat.(*objects.Player) 128 | if player.SitDown() && !player.Stake { 129 | ready = false 130 | } 131 | } 132 | if ready { 133 | //都押注了直接开奖 134 | this.fsm.Call(OpeningPeriodEvent) 135 | } 136 | } 137 | case OpeningPeriod: 138 | if (this.current_frame - this.step3) > 5 { 139 | this.fsm.Call(SettlementPeriodEvent) 140 | } else { 141 | //this.NotifyAxes() 142 | } 143 | case SettlementPeriod: 144 | if (this.current_frame - this.step4) > 5 { 145 | this.fsm.Call(IdlePeriodEvent) 146 | } else { 147 | //this.NotifyAxes() 148 | } 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /server/xaxb/notify.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 loolgame Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | package xaxb 15 | 16 | import ( 17 | "encoding/json" 18 | "github.com/liangdas/mqantserver/server/xaxb/objects" 19 | ) 20 | 21 | /** 22 | 定期刷新所有玩家的位置 23 | */ 24 | func (self *Table) NotifyAxes() { 25 | seats := []map[string]interface{}{} 26 | for _, player := range self.seats { 27 | if player.Bind() { 28 | seats = append(seats, player.SerializableMap()) 29 | } 30 | } 31 | b, _ := json.Marshal(map[string]interface{}{ 32 | "State": self.State(), 33 | "StateGame": self.fsm.getState(), 34 | "Seats": seats, 35 | }) 36 | self.NotifyCallBackMsg("XaXb/OnSync", b) 37 | } 38 | 39 | /** 40 | 通知所有玩家有新玩家加入 41 | */ 42 | func (self *Table) NotifyJoin(player *objects.Player) { 43 | b, _ := json.Marshal(player.SerializableMap()) 44 | self.NotifyCallBackMsg("XaXb/OnEnter", b) 45 | } 46 | 47 | /** 48 | 通知所有玩家开始游戏了 49 | */ 50 | func (self *Table) NotifyResume() { 51 | b, _ := json.Marshal(self.getSeatsMap()) 52 | self.NotifyCallBackMsg("XaXb/OnResume", b) 53 | } 54 | 55 | /** 56 | 通知所有玩家开始游戏了 57 | */ 58 | func (self *Table) NotifyPause() { 59 | b, _ := json.Marshal(self.getSeatsMap()) 60 | self.NotifyCallBackMsg("XaXb/OnPause", b) 61 | } 62 | 63 | /** 64 | 通知所有玩家开始游戏了 65 | */ 66 | func (self *Table) NotifyStop() { 67 | b, _ := json.Marshal(self.getSeatsMap()) 68 | self.NotifyCallBackMsg("XaXb/OnStop", b) 69 | } 70 | 71 | /** 72 | 通知所有玩家进入空闲期了 73 | */ 74 | func (self *Table) NotifyIdle() { 75 | b, _ := json.Marshal(map[string]interface{}{ 76 | "Coin": 500, 77 | }) 78 | self.NotifyCallBackMsg("XaXb/Idle", b) 79 | } 80 | 81 | /** 82 | 通知所有玩家开始押注了 83 | */ 84 | func (self *Table) NotifyBetting() { 85 | b, _ := json.Marshal(map[string]interface{}{ 86 | "Coin": 500, 87 | }) 88 | self.NotifyCallBackMsg("XaXb/Betting", b) 89 | } 90 | 91 | /** 92 | 通知所有玩家开始开奖了 93 | */ 94 | func (self *Table) NotifyOpening() { 95 | b, _ := json.Marshal(map[string]interface{}{ 96 | "Coin": 500, 97 | }) 98 | self.NotifyCallBackMsg("XaXb/Opening", b) 99 | } 100 | 101 | /** 102 | 通知所有玩家开奖结果出来了 103 | */ 104 | func (self *Table) NotifySettlement(Result int64) { 105 | seats := []map[string]interface{}{} 106 | for _, player := range self.seats { 107 | if player.Bind() { 108 | seats = append(seats, player.SerializableMap()) 109 | } 110 | } 111 | b, _ := json.Marshal(map[string]interface{}{ 112 | "Result": Result, 113 | "Seats": seats, 114 | }) 115 | self.NotifyCallBackMsg("XaXb/Settlement", b) 116 | } 117 | -------------------------------------------------------------------------------- /server/xaxb/objects/player.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 loolgame Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | package objects 15 | 16 | import ( 17 | "encoding/json" 18 | "github.com/liangdas/mqant-modules/room" 19 | ) 20 | 21 | type Player struct { 22 | room.BasePlayerImp 23 | SeatIndex int 24 | Coin int //金币数量 25 | timeToMove int64 26 | Target int64 //押注目标 27 | Stake bool //是否已押注 28 | Weight int64 //计算后权重 29 | } 30 | 31 | func NewPlayer(SeatIndex int) *Player { 32 | this := new(Player) 33 | this.SeatIndex = SeatIndex 34 | this.Coin = 1000 35 | return this 36 | } 37 | 38 | func (this *Player) Serializable() ([]byte, error) { 39 | 40 | return json.Marshal(this.SerializableMap()) 41 | } 42 | 43 | func (this *Player) SerializableMap() map[string]interface{} { 44 | rid := "" 45 | if this.Session() != nil { 46 | rid = this.Session().GetUserId() 47 | } 48 | return map[string]interface{}{ 49 | "SeatIndex": this.SeatIndex, 50 | "Rid": rid, 51 | "Coin": this.Coin, 52 | "Stake": this.Stake, 53 | "Target": this.Target, 54 | "Weight": this.Weight, 55 | "SitDown": this.SitDown(), 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /static/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/.DS_Store -------------------------------------------------------------------------------- /static/hitball/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/.DS_Store -------------------------------------------------------------------------------- /static/hitball/assets/arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/arrow.png -------------------------------------------------------------------------------- /static/hitball/assets/ball.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/ball.png -------------------------------------------------------------------------------- /static/hitball/assets/coin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/coin.png -------------------------------------------------------------------------------- /static/hitball/assets/deadly.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/deadly.png -------------------------------------------------------------------------------- /static/hitball/assets/fonts/Skranji-Bold-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/fonts/Skranji-Bold-40.png -------------------------------------------------------------------------------- /static/hitball/assets/fonts/desyrel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/fonts/desyrel.png -------------------------------------------------------------------------------- /static/hitball/assets/img/bomb1-selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/img/bomb1-selected.png -------------------------------------------------------------------------------- /static/hitball/assets/img/bomb1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/img/bomb1.png -------------------------------------------------------------------------------- /static/hitball/assets/img/bomb2-selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/img/bomb2-selected.png -------------------------------------------------------------------------------- /static/hitball/assets/img/bomb2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/img/bomb2.png -------------------------------------------------------------------------------- /static/hitball/assets/img/bomb3-selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/img/bomb3-selected.png -------------------------------------------------------------------------------- /static/hitball/assets/img/bomb3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/img/bomb3.png -------------------------------------------------------------------------------- /static/hitball/assets/img/level-box.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/img/level-box.png -------------------------------------------------------------------------------- /static/hitball/assets/img/lvlcomplete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/img/lvlcomplete.png -------------------------------------------------------------------------------- /static/hitball/assets/img/orange-btn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/img/orange-btn.png -------------------------------------------------------------------------------- /static/hitball/assets/img/panel-650x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/img/panel-650x400.png -------------------------------------------------------------------------------- /static/hitball/assets/img/star2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/img/star2.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/bg.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/btn-blue-bg-down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/btn-blue-bg-down.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/btn-blue-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/btn-blue-bg.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/btn-blue-corner-bl-down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/btn-blue-corner-bl-down.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/btn-blue-corner-bl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/btn-blue-corner-bl.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/btn-blue-corner-br-down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/btn-blue-corner-br-down.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/btn-blue-corner-br.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/btn-blue-corner-br.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/btn-blue-corner-tl-down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/btn-blue-corner-tl-down.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/btn-blue-corner-tl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/btn-blue-corner-tl.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/btn-blue-corner-tr-down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/btn-blue-corner-tr-down.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/btn-blue-corner-tr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/btn-blue-corner-tr.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/btn-blue-line-b-down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/btn-blue-line-b-down.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/btn-blue-line-b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/btn-blue-line-b.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/btn-blue-line-l-down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/btn-blue-line-l-down.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/btn-blue-line-l.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/btn-blue-line-l.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/btn-blue-line-r-down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/btn-blue-line-r-down.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/btn-blue-line-r.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/btn-blue-line-r.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/btn-blue-line-t-down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/btn-blue-line-t-down.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/btn-blue-line-t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/btn-blue-line-t.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/btn-grey-bg-down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/btn-grey-bg-down.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/btn-grey-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/btn-grey-bg.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/btn-grey-corner-bl-down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/btn-grey-corner-bl-down.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/btn-grey-corner-bl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/btn-grey-corner-bl.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/btn-grey-corner-br-down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/btn-grey-corner-br-down.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/btn-grey-corner-br.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/btn-grey-corner-br.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/btn-grey-corner-tl-down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/btn-grey-corner-tl-down.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/btn-grey-corner-tl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/btn-grey-corner-tl.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/btn-grey-corner-tr-down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/btn-grey-corner-tr-down.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/btn-grey-corner-tr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/btn-grey-corner-tr.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/btn-grey-line-b-down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/btn-grey-line-b-down.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/btn-grey-line-b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/btn-grey-line-b.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/btn-grey-line-l-down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/btn-grey-line-l-down.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/btn-grey-line-l.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/btn-grey-line-l.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/btn-grey-line-r-down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/btn-grey-line-r-down.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/btn-grey-line-r.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/btn-grey-line-r.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/btn-grey-line-t-down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/btn-grey-line-t-down.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/btn-grey-line-t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/btn-grey-line-t.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/chk-blue-checkmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/chk-blue-checkmark.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/chk-grey-checkmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/chk-grey-checkmark.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/chk-grey-corner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/chk-grey-corner.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/down-grey-slide-down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/down-grey-slide-down.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/down-grey-slide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/down-grey-slide.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/radio-blue-check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/radio-blue-check.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/radio-grey-check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/radio-grey-check.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/sld-grey-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/sld-grey-bg.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/sld-grey-corner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/sld-grey-corner.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/sld-grey-line.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/sld-grey-line.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/wnd-grey-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/wnd-grey-bg.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/wnd-grey-corner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/wnd-grey-corner.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/images/wnd-grey-line.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/images/wnd-grey-line.png -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/kenney-theme.json: -------------------------------------------------------------------------------- 1 | { 2 | "__config__": { 3 | "name": "kenney", 4 | "resources": [ 5 | "./kenney-atlas.json", 6 | "../fonts/desyrel.fnt", 7 | "../fonts/Skranji-Bold-40.fnt" 8 | ] 9 | }, 10 | 11 | "default": { 12 | "scale": 0.5, 13 | "bg": "wnd-grey-bg.png", 14 | "padding" : 2, 15 | "bgPadding": 6, 16 | "corner": "wnd-grey-corner.png", 17 | "line": "wnd-grey-line.png", 18 | "font": { 19 | "size": "20px", 20 | "family": "Arial", 21 | "color": "black" 22 | } 23 | }, 24 | "Dialog": { 25 | "bgPadding": 5, 26 | "bg": "wnd-grey-bg.png", 27 | "corner": "wnd-grey-corner.png", 28 | "line": "wnd-grey-line.png" 29 | }, 30 | "Label_": { 31 | "bgPadding": 0, 32 | "bg": "", 33 | "corner": " ", 34 | "line": " " 35 | }, 36 | "Layout": { 37 | "bgPadding": 1, 38 | "bg": "", 39 | "corner": " ", 40 | "line": " " 41 | }, 42 | "blueheader": { 43 | "bgPadding": 6, 44 | "bg": "btn-blue-bg-down.png", 45 | "font": { 46 | "size": "20px", 47 | "family": "Arial", 48 | "color": "white" 49 | }, 50 | "corner-tl": { "default": "btn-blue-corner-tl-down.png" }, 51 | "corner-tr": { "default": "btn-blue-corner-tr-down.png" }, 52 | "corner-bl": { "default": "btn-blue-corner-bl-down.png" }, 53 | "corner-br": { "default": "btn-blue-corner-br-down.png" }, 54 | "line-t": { "default": "btn-blue-line-t-down.png" }, 55 | "line-r": { "default": "btn-blue-line-r-down.png" }, 56 | "line-b": { "default": "btn-blue-line-b-down.png" }, 57 | "line-l": { "default": "btn-blue-line-l-down.png" } 58 | }, 59 | "List": { 60 | "bg": "sld-grey-bg.png", 61 | "bgPadding": 5, 62 | "corner": "sld-grey-corner.png", 63 | "line": "sld-grey-line.png" 64 | }, 65 | "Button": { 66 | "bgPadding": 6, 67 | "bg": "btn-grey-bg.png", 68 | "corner-tl": { "default": "btn-grey-corner-tl.png" }, 69 | "corner-tr": { "default": "btn-grey-corner-tr.png" }, 70 | "corner-bl": { "default": "btn-grey-corner-bl.png", "down": "btn-grey-corner-bl-down.png" }, 71 | "corner-br": { "default": "btn-grey-corner-br.png", "down": "btn-grey-corner-br-down.png" }, 72 | "line-t": { "default": "btn-grey-line-t.png" }, 73 | "line-r": { "default": "btn-grey-line-r.png" }, 74 | "line-b": { "default": "btn-grey-line-b.png", "down": "btn-grey-line-b-down.png" }, 75 | "line-l": { "default": "btn-grey-line-l.png" } 76 | }, 77 | "bluebutton": { 78 | "bgPadding": 6, 79 | "bg": "btn-blue-bg.png", 80 | "corner-tl": { "default": "btn-blue-corner-tl.png" }, 81 | "corner-tr": { "default": "btn-blue-corner-tr.png" }, 82 | "corner-bl": { "default": "btn-blue-corner-bl.png", "down": "btn-blue-corner-bl-down.png" }, 83 | "corner-br": { "default": "btn-blue-corner-br.png", "down": "btn-blue-corner-br-down.png" }, 84 | "line-t": { "default": "btn-blue-line-t.png" }, 85 | "line-r": { "default": "btn-blue-line-r.png" }, 86 | "line-b": { "default": "btn-blue-line-b.png", "down": "btn-blue-line-b-down.png" }, 87 | "line-l": { "default": "btn-blue-line-l.png" } 88 | }, 89 | 90 | "Slider": { 91 | "bgPadding": 0, 92 | "bg": "sld-grey-bg.png", 93 | "corner": "sld-grey-corner.png", 94 | "line": "sld-grey-line.png" 95 | }, 96 | "Slide": { 97 | "image": { "default": "down-grey-slide.png", "down": "down-grey-slide-down.png" } 98 | }, 99 | "Checkbox": { 100 | "bgPadding": 6, 101 | "bg": "wnd-grey-bg.png", 102 | "corner": "wnd-grey-corner.png", 103 | "line": "wnd-grey-line.png", 104 | "checkmark": "chk-grey-checkmark.png", 105 | "font": { 106 | "color": "green" 107 | } 108 | }, 109 | "Radio": { 110 | "bgPadding": 6, 111 | "bg": "wnd-grey-bg.png", 112 | "corner": "wnd-grey-corner.png", 113 | "line": "wnd-grey-line.png", 114 | "checkmark": "radio-grey-check.png" 115 | } 116 | } -------------------------------------------------------------------------------- /static/hitball/assets/kenney-theme/kenney-theme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/kenney-theme/kenney-theme.png -------------------------------------------------------------------------------- /static/hitball/assets/metalworks-theme/feathers-metal-works-desktop-theme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/metalworks-theme/feathers-metal-works-desktop-theme.png -------------------------------------------------------------------------------- /static/hitball/assets/metalworks-theme/images/bg-down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/metalworks-theme/images/bg-down.png -------------------------------------------------------------------------------- /static/hitball/assets/metalworks-theme/images/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/metalworks-theme/images/bg.png -------------------------------------------------------------------------------- /static/hitball/assets/metalworks-theme/images/btn-bg-down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/metalworks-theme/images/btn-bg-down.png -------------------------------------------------------------------------------- /static/hitball/assets/metalworks-theme/images/btn-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/metalworks-theme/images/btn-bg.png -------------------------------------------------------------------------------- /static/hitball/assets/metalworks-theme/images/btn-corner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/metalworks-theme/images/btn-corner.png -------------------------------------------------------------------------------- /static/hitball/assets/metalworks-theme/images/btn-line.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/metalworks-theme/images/btn-line.png -------------------------------------------------------------------------------- /static/hitball/assets/metalworks-theme/images/chk-checkmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/metalworks-theme/images/chk-checkmark.png -------------------------------------------------------------------------------- /static/hitball/assets/metalworks-theme/images/corner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/metalworks-theme/images/corner.png -------------------------------------------------------------------------------- /static/hitball/assets/metalworks-theme/images/darkcnt-corner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/metalworks-theme/images/darkcnt-corner.png -------------------------------------------------------------------------------- /static/hitball/assets/metalworks-theme/images/darkcnt-line.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/metalworks-theme/images/darkcnt-line.png -------------------------------------------------------------------------------- /static/hitball/assets/metalworks-theme/images/header-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/metalworks-theme/images/header-bg.png -------------------------------------------------------------------------------- /static/hitball/assets/metalworks-theme/images/line.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/metalworks-theme/images/line.png -------------------------------------------------------------------------------- /static/hitball/assets/metalworks-theme/images/radio-checkmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/metalworks-theme/images/radio-checkmark.png -------------------------------------------------------------------------------- /static/hitball/assets/metalworks-theme/metalworks-theme.json: -------------------------------------------------------------------------------- 1 | { 2 | "__config__": { 3 | "name": "metalworks", 4 | "resources": [ 5 | "./images/header-bg.png", 6 | "./images/bg.png", 7 | "./images/bg-down.png", 8 | "./images/btn-bg.png", 9 | "./images/btn-bg-down.png", 10 | "./images/btn-corner.png", 11 | "./images/btn-line.png", 12 | "./images/darkcnt-corner.png", 13 | "./images/darkcnt-line.png", 14 | "./images/corner.png", 15 | "./images/line.png", 16 | "./images/chk-checkmark.png", 17 | "./images/radio-checkmark.png", 18 | "../fonts/desyrel.fnt", 19 | "../fonts/Skranji-Bold-40.fnt" 20 | ] 21 | }, 22 | 23 | "default": { 24 | "scale": 1, 25 | "padding": 2, 26 | "bg": { "default": "./images/bg.png", "down": "./images/bg-down.png" }, 27 | "bgPadding": 1, 28 | "corner": "./images/corner.png", 29 | "line": "./images/line.png", 30 | "font": { 31 | "size": "20px", 32 | "family": "Arial", 33 | "color": "black" 34 | } 35 | }, 36 | "Header": { 37 | "bg": "./images/header-bg.png", 38 | "bgTiling": "x", 39 | "bgPadding": 0, 40 | "corner": "", 41 | "line": "", 42 | "font": { 43 | "color": "white" 44 | } 45 | }, 46 | 47 | "Button": { 48 | "bg": { "default": "./images/btn-bg.png", "down": "./images/btn-bg-down.png" }, 49 | "bgTiling": "x", 50 | "bgPadding": 2, 51 | "corner": "./images/btn-corner.png", 52 | "line": "./images/btn-line.png", 53 | "font": { 54 | "size": "20px", 55 | "family": "Arial", 56 | "color": "black" 57 | } 58 | }, 59 | "List": { 60 | "bg": "./images/darkcnt-line.png", 61 | "corner": "./images/darkcnt-corner.png", 62 | "line": "./images/darkcnt-line.png" 63 | 64 | }, 65 | "hListItem": { 66 | "bg": { "default": "./images/btn-bg.png", "down": "./images/btn-bg-down.png" }, 67 | "bgTiling": "x", 68 | "bgPadding": 2, 69 | "corner": "", 70 | "line": "./images/btn-line.png", 71 | "font": { 72 | "size": "20px", 73 | "family": "Arial", 74 | "color": "black" 75 | } 76 | }, 77 | "Slider": { 78 | "bg": "./images/darkcnt-line.png", 79 | "corner": "./images/darkcnt-corner.png", 80 | "line": "./images/darkcnt-line.png" 81 | }, 82 | "Slide": { 83 | "bg": { "default": "./images/btn-bg.png", "down": "./images/btn-bg-down.png" }, 84 | "bgTiling": "x", 85 | "bgPadding": 2, 86 | "corner": "./images/btn-corner.png", 87 | "line": "./images/btn-line.png" 88 | }, 89 | "Checkbox": { 90 | "bg": "./images/darkcnt-line.png", 91 | "corner": "./images/darkcnt-corner.png", 92 | "line": "./images/darkcnt-line.png", 93 | "checkmark": "./images/chk-checkmark.png" 94 | }, 95 | "Radio": { 96 | "bg": "./images/darkcnt-line.png", 97 | "corner": "./images/darkcnt-corner.png", 98 | "line": "./images/darkcnt-line.png", 99 | "checkmark": "./images/radio-checkmark.png" 100 | } 101 | 102 | } -------------------------------------------------------------------------------- /static/hitball/assets/tilemaps/tmw_desert_spacing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/tilemaps/tmw_desert_spacing.png -------------------------------------------------------------------------------- /static/hitball/assets/virtualjoystick/skins/arcade-joystick.json: -------------------------------------------------------------------------------- 1 | {"frames": [ 2 | 3 | { 4 | "filename": "base", 5 | "frame": {"x":2,"y":2,"w":280,"h":280}, 6 | "rotated": false, 7 | "trimmed": false, 8 | "spriteSourceSize": {"x":0,"y":0,"w":280,"h":280}, 9 | "sourceSize": {"w":280,"h":280} 10 | }, 11 | { 12 | "filename": "button1-down", 13 | "frame": {"x":2,"y":284,"w":132,"h":132}, 14 | "rotated": false, 15 | "trimmed": false, 16 | "spriteSourceSize": {"x":0,"y":0,"w":132,"h":132}, 17 | "sourceSize": {"w":132,"h":132} 18 | }, 19 | { 20 | "filename": "button1-up", 21 | "frame": {"x":136,"y":284,"w":132,"h":132}, 22 | "rotated": false, 23 | "trimmed": false, 24 | "spriteSourceSize": {"x":0,"y":0,"w":132,"h":132}, 25 | "sourceSize": {"w":132,"h":132} 26 | }, 27 | { 28 | "filename": "button2-down", 29 | "frame": {"x":270,"y":284,"w":132,"h":132}, 30 | "rotated": false, 31 | "trimmed": false, 32 | "spriteSourceSize": {"x":0,"y":0,"w":132,"h":132}, 33 | "sourceSize": {"w":132,"h":132} 34 | }, 35 | { 36 | "filename": "button2-up", 37 | "frame": {"x":284,"y":138,"w":132,"h":132}, 38 | "rotated": false, 39 | "trimmed": false, 40 | "spriteSourceSize": {"x":0,"y":0,"w":132,"h":132}, 41 | "sourceSize": {"w":132,"h":132} 42 | }, 43 | { 44 | "filename": "button3-down", 45 | "frame": {"x":418,"y":138,"w":132,"h":132}, 46 | "rotated": false, 47 | "trimmed": false, 48 | "spriteSourceSize": {"x":0,"y":0,"w":132,"h":132}, 49 | "sourceSize": {"w":132,"h":132} 50 | }, 51 | { 52 | "filename": "button3-up", 53 | "frame": {"x":404,"y":272,"w":132,"h":132}, 54 | "rotated": false, 55 | "trimmed": false, 56 | "spriteSourceSize": {"x":0,"y":0,"w":132,"h":132}, 57 | "sourceSize": {"w":132,"h":132} 58 | }, 59 | { 60 | "filename": "stick", 61 | "frame": {"x":404,"y":2,"w":134,"h":134}, 62 | "rotated": false, 63 | "trimmed": false, 64 | "spriteSourceSize": {"x":0,"y":0,"w":134,"h":134}, 65 | "sourceSize": {"w":134,"h":134} 66 | }], 67 | "meta": { 68 | "app": "http://www.codeandweb.com/texturepacker", 69 | "version": "1.0", 70 | "image": "arcade-joystick.png", 71 | "format": "RGBA8888", 72 | "size": {"w":552,"h":418}, 73 | "scale": "1", 74 | "smartupdate": "$TexturePacker:SmartUpdate:10346054b252ab14bb310a8d6bd547c8:95c6dd72d4153222351a2981c3dd9889:a263a0553fca6de61a66e4e620c067cc$" 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /static/hitball/assets/virtualjoystick/skins/arcade-joystick.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/virtualjoystick/skins/arcade-joystick.png -------------------------------------------------------------------------------- /static/hitball/assets/virtualjoystick/skins/generic-joystick.json: -------------------------------------------------------------------------------- 1 | {"frames": [ 2 | 3 | { 4 | "filename": "base", 5 | "frame": {"x":2,"y":2,"w":224,"h":224}, 6 | "rotated": false, 7 | "trimmed": false, 8 | "spriteSourceSize": {"x":0,"y":0,"w":224,"h":224}, 9 | "sourceSize": {"w":224,"h":224} 10 | }, 11 | { 12 | "filename": "button1-down", 13 | "frame": {"x":364,"y":2,"w":104,"h":104}, 14 | "rotated": false, 15 | "trimmed": false, 16 | "spriteSourceSize": {"x":0,"y":0,"w":104,"h":104}, 17 | "sourceSize": {"w":104,"h":104} 18 | }, 19 | { 20 | "filename": "button1-up", 21 | "frame": {"x":364,"y":108,"w":104,"h":104}, 22 | "rotated": false, 23 | "trimmed": false, 24 | "spriteSourceSize": {"x":0,"y":0,"w":104,"h":104}, 25 | "sourceSize": {"w":104,"h":104} 26 | }, 27 | { 28 | "filename": "button2-down", 29 | "frame": {"x":470,"y":2,"w":104,"h":104}, 30 | "rotated": false, 31 | "trimmed": false, 32 | "spriteSourceSize": {"x":0,"y":0,"w":104,"h":104}, 33 | "sourceSize": {"w":104,"h":104} 34 | }, 35 | { 36 | "filename": "button2-up", 37 | "frame": {"x":576,"y":2,"w":104,"h":104}, 38 | "rotated": false, 39 | "trimmed": false, 40 | "spriteSourceSize": {"x":0,"y":0,"w":104,"h":104}, 41 | "sourceSize": {"w":104,"h":104} 42 | }, 43 | { 44 | "filename": "button3-down", 45 | "frame": {"x":470,"y":108,"w":104,"h":104}, 46 | "rotated": false, 47 | "trimmed": false, 48 | "spriteSourceSize": {"x":0,"y":0,"w":104,"h":104}, 49 | "sourceSize": {"w":104,"h":104} 50 | }, 51 | { 52 | "filename": "button3-up", 53 | "frame": {"x":576,"y":108,"w":104,"h":104}, 54 | "rotated": false, 55 | "trimmed": false, 56 | "spriteSourceSize": {"x":0,"y":0,"w":104,"h":104}, 57 | "sourceSize": {"w":104,"h":104} 58 | }, 59 | { 60 | "filename": "stick", 61 | "frame": {"x":228,"y":2,"w":134,"h":134}, 62 | "rotated": false, 63 | "trimmed": false, 64 | "spriteSourceSize": {"x":0,"y":0,"w":134,"h":134}, 65 | "sourceSize": {"w":134,"h":134} 66 | }], 67 | "meta": { 68 | "app": "http://www.codeandweb.com/texturepacker", 69 | "version": "1.0", 70 | "image": "generic-joystick.png", 71 | "format": "RGBA8888", 72 | "size": {"w":682,"h":228}, 73 | "scale": "1", 74 | "smartupdate": "$TexturePacker:SmartUpdate:e9879c3113ba01e8301c41ff8a522461:27f6351bd7b0a375a2a8ff5a01af291c:39ee24d5067dbc6be070854b489a5e77$" 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /static/hitball/assets/virtualjoystick/skins/generic-joystick.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/assets/virtualjoystick/skins/generic-joystick.png -------------------------------------------------------------------------------- /static/hitball/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 64 | 65 | 66 |
67 | 68 |
69 | 70 | -------------------------------------------------------------------------------- /static/hitball/js/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/js/.DS_Store -------------------------------------------------------------------------------- /static/hitball/js/lib/phaser_plugins/ColorHarmony/ColorHarmony.js: -------------------------------------------------------------------------------- 1 | /* jshint camelcase:false */ 2 | /** 3 | * A collection of methods useful for manipulating and comparing colors. 4 | * 5 | * @class Phaser.Plugin.ColorHarmony 6 | * @author Richard Davey 7 | * @copyright 2013 Photon Storm Ltd. 8 | * @license https://github.com/photonstorm/phaser/blob/master/license.txt MIT License 9 | */ 10 | 11 | Phaser.Plugins.ColorHarmony.prototype = { 12 | 13 | /** 14 | * Returns a Complementary Color Harmony for the given color. 15 | *

A complementary hue is one directly opposite the color given on the color wheel

16 | *

Value returned in 0xAARRGGBB format with Alpha set to 255.

17 | * 18 | * @method Phaser.Plugin.ColorHarmony#getComplementHarmony 19 | * @param {Number} color The color to base the harmony on. 20 | * @return {Number} 0xAARRGGBB format color value. 21 | */ 22 | getComplementHarmony: function (color) { 23 | 24 | var hsv = Phaser.Color.RGBtoHSV(color); 25 | var opposite = Phaser.Color.game.math.wrapValue(hsv.hue, 180, 359); 26 | return Phaser.Color.HSVtoRGB(opposite, 1.0, 1.0); 27 | 28 | }, 29 | 30 | /** 31 | * Returns an Analogous Color Harmony for the given color. 32 | *

An Analogous harmony are hues adjacent to each other on the color wheel

33 | *

Values returned in 0xAARRGGBB format with Alpha set to 255.

34 | * 35 | * @method Phaser.Plugin.ColorHarmony#getAnalogousHarmony 36 | * @param {Number} color The color to base the harmony on. 37 | * @param {Number} threshold Control how adjacent the colors will be (default +- 30 degrees) 38 | * @return {Object} Object containing 3 properties: color1 (the original color), color2 (the warmer analogous color) and color3 (the colder analogous color) 39 | */ 40 | getAnalogousHarmony: function (color, threshold) { 41 | if (typeof threshold === "undefined") { threshold = 30; } 42 | var hsv = Phaser.Color.RGBtoHSV(color); 43 | if(threshold > 359 || threshold < 0) { 44 | throw new Error("Color Warning: Invalid threshold given to getAnalogousHarmony()"); 45 | } 46 | var warmer = Phaser.Color.game.math.wrapValue(hsv.hue, 359 - threshold, 359); 47 | var colder = Phaser.Color.game.math.wrapValue(hsv.hue, threshold, 359); 48 | return { 49 | color1: color, 50 | color2: Phaser.Color.HSVtoRGB(warmer, 1.0, 1.0), 51 | color3: Phaser.Color.HSVtoRGB(colder, 1.0, 1.0), 52 | hue1: hsv.hue, 53 | hue2: warmer, 54 | hue3: colder 55 | }; 56 | }, 57 | 58 | /** 59 | * Returns an Split Complement Color Harmony for the given color. 60 | *

A Split Complement harmony are the two hues on either side of the color's Complement

61 | *

Values returned in 0xAARRGGBB format with Alpha set to 255.

62 | * 63 | * @method Phaser.Plugin.ColorHarmony#getSplitComplementHarmony 64 | * @param {Number} color The color to base the harmony on 65 | * @param {Number} threshold Control how adjacent the colors will be to the Complement (default +- 30 degrees) 66 | * @return {Object} An object containing 3 properties: color1 (the original color), color2 (the warmer analogous color) and color3 (the colder analogous color) 67 | */ 68 | getSplitComplementHarmony: function (color, threshold) { 69 | if (typeof threshold === "undefined") { threshold = 30; } 70 | var hsv = Phaser.Color.RGBtoHSV(color); 71 | if(threshold >= 359 || threshold <= 0) { 72 | throw new Error("Phaser.Color Warning: Invalid threshold given to getSplitComplementHarmony()"); 73 | } 74 | var opposite = Phaser.Color.game.math.wrapValue(hsv.hue, 180, 359); 75 | var warmer = Phaser.Color.game.math.wrapValue(hsv.hue, opposite - threshold, 359); 76 | var colder = Phaser.Color.game.math.wrapValue(hsv.hue, opposite + threshold, 359); 77 | return { 78 | color1: color, 79 | color2: Phaser.Color.HSVtoRGB(warmer, hsv.saturation, hsv.value), 80 | color3: Phaser.Color.HSVtoRGB(colder, hsv.saturation, hsv.value), 81 | hue1: hsv.hue, 82 | hue2: warmer, 83 | hue3: colder 84 | }; 85 | }, 86 | 87 | /** 88 | * Returns a Triadic Color Harmony for the given color. 89 | *

A Triadic harmony are 3 hues equidistant from each other on the color wheel

90 | *

Values returned in 0xAARRGGBB format with Alpha set to 255.

91 | * 92 | * @method Phaser.Plugin.ColorHarmony#getTriadicHarmony 93 | * @param {Number} color The color to base the harmony on. 94 | * @return {Object} An Object containing 3 properties: color1 (the original color), color2 and color3 (the equidistant colors) 95 | */ 96 | getTriadicHarmony: function (color) { 97 | var hsv = Phaser.Color.RGBtoHSV(color); 98 | var triadic1 = Phaser.Color.game.math.wrapValue(hsv.hue, 120, 359); 99 | var triadic2 = Phaser.Color.game.math.wrapValue(triadic1, 120, 359); 100 | return { 101 | color1: color, 102 | color2: Phaser.Color.HSVtoRGB(triadic1, 1.0, 1.0), 103 | color3: Phaser.Color.HSVtoRGB(triadic2, 1.0, 1.0) 104 | }; 105 | } 106 | 107 | }; 108 | -------------------------------------------------------------------------------- /static/hitball/js/lib/phaser_plugins/README.md: -------------------------------------------------------------------------------- 1 | ![Phaser Logo](http://www.photonstorm.com/wp-content/uploads/2013/09/phaser_10_release.jpg) 2 | 3 | # Phaser Plugins 4 | 5 | This is the Phaser Plugins repository. 6 | 7 | If you're looking for the framework itself, please go here: https://github.com/photonstorm/phaser 8 | 9 | 10 | ## Contributing 11 | 12 | - If you find a bug in a Plugin then please report it on [GitHub Issues][issues] or our [Support Forum][forum]. 13 | 14 | - You can issue Pull Requests for new plugins or fixes to existing ones against the `master` branch. 15 | 16 | - If you have a Plugin request, or have written a game or demo that shows a Phaser Plugin in use, then please get in touch. We'd love to hear from you! Either post to our [forum][forum] or email: rich@photonstorm.com 17 | 18 | 19 | ## Bugs? 20 | 21 | Please add them to the [Issue Tracker][issues] with as much info as possible, especially source code demonstrating the issue. 22 | 23 | 24 | ## About Phaser 25 | 26 | Phaser is a fast, free and fun open source game framework for making desktop and mobile browser HTML5 games. It uses [Pixi.js](https://github.com/GoodBoyDigital/pixi.js/) internally for fast 2D Canvas and WebGL rendering. 27 | 28 | By Richard Davey, [Photon Storm](http://www.photonstorm.com) 29 | 30 | * View the [Official Website](http://phaser.io) 31 | * Follow on [Twitter](https://twitter.com/photonstorm) 32 | * Join the [Forum](http://www.html5gamedevs.com/forum/14-phaser/) 33 | * Source code for 300+ [Phaser Examples](https://github.com/photonstorm/phaser-examples) or [browse them online](http://examples.phaser.io) 34 | * Read the [documentation online](http://docs.phaser.io) 35 | * Join our [#phaserio IRC channel](http://www.html5gamedevs.com/topic/4470-official-phaserio-irc-channel-phaserio-on-freenode/) on freenode 36 | * Subscribe to the [Phaser Newsletter](https://confirmsubscription.com/h/r/369DE48E3E86AF1E) and we'll email you when new versions are released. 37 | 38 | 39 | ## License 40 | 41 | Phaser and all examples are released under the [MIT License](http://opensource.org/licenses/MIT). This does not include any assets (art, music, sounds). However it is up to the individual Plugin authors which license they release under, so please check for a `license.txt` file in the plugin folder. If one is not present you may assume the MIT License. 42 | 43 | [issues]: https://github.com/photonstorm/phaser-plugins/issues 44 | [contribute]: https://github.com/photonstorm/phaser/blob/master/CONTRIBUTING.md 45 | [phaser]: https://github.com/photonstorm/phaser-plugins 46 | [forum]: http://www.html5gamedevs.com/forum/14-phaser/ 47 | 48 | [![Analytics](https://ga-beacon.appspot.com/UA-44006568-2/phaser/index)](https://github.com/igrigorik/ga-beacon) 49 | -------------------------------------------------------------------------------- /static/hitball/js/lib/phaser_plugins/SamplePlugin/SamplePlugin.js: -------------------------------------------------------------------------------- 1 | /** 2 | * A Sample Plugin demonstrating how to hook into the Phaser plugin system. 3 | * @class Phaser.Plugin.SamplePlugin 4 | */ 5 | Phaser.Plugin.SamplePlugin = function (game, parent) { 6 | 7 | Phaser.Plugin.call(this, game, parent); 8 | 9 | this.sprite = null; 10 | 11 | }; 12 | 13 | // Extends the Phaser.Plugin template, setting up values we need 14 | Phaser.Plugin.SamplePlugin.prototype = Object.create(Phaser.Plugin.prototype); 15 | Phaser.Plugin.SamplePlugin.prototype.constructor = Phaser.Plugin.SamplePlugin; 16 | 17 | /** 18 | * Add a Sprite reference to this Plugin. 19 | * All this plugin does is move the Sprite across the screen slowly. 20 | * @type {Phaser.Sprite} 21 | */ 22 | Phaser.Plugin.SamplePlugin.prototype.addSprite = function (sprite) { 23 | 24 | this.sprite = sprite; 25 | 26 | }; 27 | 28 | /** 29 | * This is run when the plugins update during the core game loop. 30 | */ 31 | Phaser.Plugin.SamplePlugin.prototype.update = function () { 32 | 33 | if (this.sprite) 34 | { 35 | this.sprite.x += 0.5; 36 | } 37 | 38 | }; 39 | -------------------------------------------------------------------------------- /static/hitball/js/lib/phaser_plugins/ScreenShake/ScreenShake.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Plugin to make screen shake FX (makes number of short camera movements). 5 | * 6 | * Usage: 7 | * in main create function: 8 | * game.plugins.screenShake = game.plugins.add(Phaser.Plugin.ScreenShake); 9 | * 10 | * in function where need to call shake FX: 11 | * game.plugins.screenShake.setup({ //if need to replace default plugin settings 12 | * shakeX: true, 13 | * shakeY: false 14 | * }); 15 | * this.game.plugins.screenShake.shake(10); //pass shake count value 16 | * 17 | * 18 | * 19 | * @author Dmitry Maslov 20 | * @copyright 2014 Dmitry Maslov 21 | * @license http://choosealicense.com/licenses/mit 22 | * 23 | */ 24 | Phaser.Plugin.ScreenShake = function(game, parent){ 25 | Phaser.Plugin.call(this, game, parent); 26 | 27 | //settings by default 28 | this._settings = { 29 | shakesCount: 0, 30 | shakeX: true, 31 | shakeY: true, 32 | sensCoef: 0.5 33 | }; 34 | this.game.camera.bounds = null; 35 | 36 | /** 37 | * screen shake FX. 38 | */ 39 | this._moveCamera = function(){ 40 | if(this._settings.shakesCount > 0){ 41 | var sens = this._settings.shakesCount * this._settings.sensCoef; 42 | 43 | if(this._settings.shakesCount % 2){ 44 | this.game.camera.x += this._settings.shakeX ? sens : 0; 45 | this.game.camera.y += this._settings.shakeY ? sens : 0; 46 | } 47 | else{ 48 | this.game.camera.x -= this._settings.shakeX ? sens : 0; 49 | this.game.camera.y -= this._settings.shakeY ? sens : 0; 50 | } 51 | 52 | this._settings.shakesCount--; 53 | 54 | if(this._settings.shakesCount === 0){ 55 | this.game.camera.setPosition(0, 0); 56 | } 57 | } 58 | }; 59 | }; 60 | 61 | Phaser.Plugin.ScreenShake.prototype = Object.create(Phaser.Plugin.prototype); 62 | Phaser.Plugin.ScreenShake.prototype.constructor = Phaser.Plugin.ScreenShake; 63 | 64 | 65 | /** 66 | * Change default settings object values with passed object value. 67 | * 68 | * @method Phaser.Plugin.ScreenShake#setup 69 | * @param {object} [obj] - Passed object to merge 70 | */ 71 | Phaser.Plugin.ScreenShake.prototype.setup = function(obj){ 72 | this._settings = Phaser.Utils.extend(false, this._settings, obj); 73 | }; 74 | 75 | 76 | /** 77 | * Pass value of count shakes. 78 | * 79 | * @method Phaser.Plugin.ScreenShake#shake 80 | * @param {number} [count] - Value of count shakes 81 | */ 82 | Phaser.Plugin.ScreenShake.prototype.shake = function(count){ 83 | this._settings.shakesCount = count; 84 | }; 85 | 86 | Phaser.Plugin.ScreenShake.prototype.update = function(){ 87 | this._moveCamera(); 88 | }; 89 | -------------------------------------------------------------------------------- /static/hitball/js/lib/phaser_plugins/Webcam/Webcam.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Provides access to the Webcam (if available) 3 | * @class Phaser.Plugin.Webcam 4 | */ 5 | Phaser.Plugin.Webcam = function (game, parent) { 6 | 7 | Phaser.Plugin.call(this, game, parent); 8 | 9 | if (!game.device.getUserMedia) 10 | { 11 | return false; 12 | } 13 | 14 | navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia; 15 | 16 | this.context = null; 17 | this.stream = null; 18 | 19 | this.video = document.createElement('video'); 20 | this.video.autoplay = true; 21 | 22 | this.onConnect = new Phaser.Signal(); 23 | this.onError = new Phaser.Signal(); 24 | 25 | }; 26 | 27 | Phaser.Plugin.Webcam.prototype = Object.create(Phaser.Plugin.prototype); 28 | Phaser.Plugin.Webcam.prototype.constructor = Phaser.Plugin.Webcam; 29 | 30 | Phaser.Plugin.Webcam.prototype.start = function (width, height, context) { 31 | 32 | // console.log('Webcam start', width, height); 33 | 34 | this.context = context; 35 | 36 | if (!this.stream) 37 | { 38 | navigator.getUserMedia( { video: { mandatory: { minWidth: width, minHeight: height } } }, this.connectCallback.bind(this), this.errorCallback.bind(this)); 39 | } 40 | 41 | }; 42 | 43 | Phaser.Plugin.Webcam.prototype.stop = function () { 44 | 45 | if (this.stream) 46 | { 47 | this.stream.stop(); 48 | this.stream = null; 49 | } 50 | 51 | }; 52 | 53 | Phaser.Plugin.Webcam.prototype.connectCallback = function (stream) { 54 | 55 | this.stream = stream; 56 | 57 | this.video.src = window.URL.createObjectURL(this.stream); 58 | 59 | this.onConnect.dispatch(this.video); 60 | 61 | }; 62 | 63 | Phaser.Plugin.Webcam.prototype.errorCallback = function (event) { 64 | 65 | this.onError.dispatch(event); 66 | 67 | }; 68 | 69 | Phaser.Plugin.Webcam.prototype.grab = function (context, x, y) { 70 | 71 | if (this.stream) 72 | { 73 | context.drawImage(this.video, x, y); 74 | } 75 | 76 | }; 77 | 78 | Phaser.Plugin.Webcam.prototype.update = function () { 79 | 80 | if (this.stream) 81 | { 82 | this.context.drawImage(this.video, 0, 0); 83 | } 84 | 85 | }; 86 | 87 | /** 88 | * @name Phaser.Plugin.Webcam#active 89 | * @property {boolean} active - Is this Webcam plugin capturing a video stream or not? 90 | * @readonly 91 | */ 92 | Object.defineProperty(Phaser.Plugin.Webcam.prototype, "active", { 93 | 94 | get: function() { 95 | return (this.stream); 96 | } 97 | 98 | }); 99 | -------------------------------------------------------------------------------- /static/hitball/js/main.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"main.js","sources":["webpack:///main.js"],"mappings":"AAAA","sourceRoot":""} -------------------------------------------------------------------------------- /static/hitball/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hitball", 3 | "version": "0.0.1", 4 | "private": false, 5 | "dependencies": { 6 | "babelify": "^6.1.0", 7 | "babel-preset-es2015": "^6.18.0" 8 | }, 9 | "scripts": { 10 | "webpack": "webpack" 11 | }, 12 | "devDependencies": { 13 | "babel-cli": "^6.22.1", 14 | "babel-core": "^6.22.1", 15 | "babel-loader": "^6.2.10", 16 | "babel-plugin-add-module-exports": "^0.2.1", 17 | "babel-polyfill": "^6.22.0", 18 | "babel-preset-es2015": "^6.22.0", 19 | "babel-preset-react": "^6.22.0", 20 | "babel-preset-stage-0": "^6.22.0", 21 | "babelify": "^6.4.0", 22 | "json-loader": "^0.5.4", 23 | "script-loader": "0.7.0", 24 | "webpack": "^1.14.0", 25 | "phaser":"2.6.2" 26 | }, 27 | "browserify": { 28 | "transform": [ 29 | [ 30 | "babelify", 31 | { 32 | "presets": [ 33 | "es2015" 34 | ] 35 | } 36 | ] 37 | ] 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /static/hitball/src/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liangdas/mqantserver/ce26905143af7f25b29efbdf729955d813ab7a94/static/hitball/src/.DS_Store -------------------------------------------------------------------------------- /static/hitball/src/gui/login.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Created by liangdas on 16/12/19. 5 | * Email 1587790525@qq.com 6 | */ 7 | module.exports ={ 8 | id: 'myWindow', 9 | 10 | component: 'Window', 11 | 12 | padding: 4, 13 | 14 | //component position relative to parent 15 | position: { x: 10, y: 10 }, 16 | 17 | width: 500, 18 | height: 500, 19 | 20 | layout: [1, 5], 21 | children: [null, { 22 | id: 'username', 23 | text: 'liangdas', 24 | component: 'Input', 25 | position: 'center', 26 | width: 300, 27 | height: 50 28 | }, { 29 | id: 'passwd', 30 | text: '123456', 31 | component: 'Input', 32 | position: 'center', 33 | width: 300, 34 | height: 50 35 | }, { 36 | id: 'warName', 37 | text: 'ys', 38 | component: 'Input', 39 | position: 'center', 40 | width: 300, 41 | height: 50 42 | }, { 43 | id: 'btn1', 44 | text: 'Get Text Value', 45 | component: 'Button', 46 | position: 'center', 47 | width: 200, 48 | height: 100 49 | }] 50 | }; -------------------------------------------------------------------------------- /static/hitball/src/main.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var extend = require('./utils/inherits.js'); 3 | var MyScaleManager = require('./utils/MyScaleManager.js'); 4 | var BootState = require('./states/BootState.js'); 5 | var test=extend(function(){},{ 6 | ctor:function(){ 7 | alert("test"); 8 | } 9 | }) 10 | /** 11 | * Created by liangdas on 2016/12/6 0006. 12 | * Email :1587790525@qq.com 13 | */ 14 | window.onload = function () { 15 | var gameDiv = document.getElementById("game"); 16 | Phaser.myScaleManager = new MyScaleManager(gameDiv); 17 | var width=800; 18 | var scale = screen.width / screen.height; 19 | if (scale > 1) { 20 | scale = 1 / scale; 21 | } 22 | var game = new Phaser.Game(width, width * scale, Phaser.AUTO, gameDiv); 23 | Phaser.myScaleManager.boot(); 24 | game.state.add('BootState', BootState, true); 25 | }; 26 | 27 | -------------------------------------------------------------------------------- /static/hitball/src/maps/DesertMap.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Created by liangdas on 2016/12/6 0006. 5 | * Email :1587790525@qq.com 6 | */ 7 | var extend = require('../utils/inherits.js'); 8 | var GameMap = require('./GameMap.js'); 9 | module.exports = extend(GameMap, { 10 | ctor: function ctor(game, key, tileWidth, tileHeight, width, height) { 11 | this._super.call(this, game, "desert"); 12 | this.addTilesetImage('Desert', 'tiles'); 13 | 14 | //设置瓦片地图中哪些索引可以碰撞检测 15 | //只要瓦片设置了mesh属性的都是需要检测碰撞的 16 | //碰撞检测的规则可以参考README.md 17 | var setCollisions = []; 18 | for (var key in this.tilesets[0].tileProperties) { 19 | var tile = this.tilesets[0].tileProperties[key]; 20 | if ("mesh" in tile) { 21 | setCollisions.push(parseInt(key) + 1); //墙的坐标是从 1开始的 22 | } 23 | } 24 | this.setCollision(setCollisions, true); //墙 25 | this.setTileIndexCallback(setCollisions, this.hitTile, this, "Ground"); 26 | }, 27 | //有物体撞击指定的tile了 28 | hitTile: function hitTile(sprite, tile) { 29 | if ("mesh" in tile.properties) { 30 | if (tile.properties.mesh - sprite.tileVolume > 0) { 31 | //可以通过 32 | return false; 33 | } 34 | //无法通过 判断碰撞的精灵类型 35 | return true; //返回 true 精灵无法穿过 返回 false 精灵可以穿过 36 | } else { 37 | //透明的可以直接穿过 38 | return false; 39 | } 40 | } 41 | }); -------------------------------------------------------------------------------- /static/hitball/src/maps/GameMap.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | /** 4 | * Created by love on 16/12/9. 5 | */ 6 | var extend = require('../utils/inherits.js'); 7 | module.exports = extend(Phaser.Tilemap, {}); -------------------------------------------------------------------------------- /static/hitball/src/objects/Bullet.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * Created by liangdas on 2016/12/6 0006. 4 | * Email :1587790525@qq.com 5 | */ 6 | 7 | var Bullet = extend(GameRole, { 8 | ctor: function ctor(game, x, y, key, frame, group, properties) { 9 | properties = properties || {}; 10 | this.roleType = "bullet"; 11 | this.bulletType = null; 12 | this._super(game, x, y, key, frame); 13 | game.physics.arcade.enable(this); 14 | this.speed = properties.speed || 200; 15 | this.tileVolume = 1; //体积与瓦片地图判断是否可以通过 16 | //this.lifespan = 200; //能发射的长度 17 | this.checkWorldBounds = true; 18 | this.outOfBoundsKill = true; 19 | 20 | this.exists = false; 21 | this.visible = false; 22 | this.events.onOutOfBounds.add(this.resetBullet, this); 23 | 24 | if (group) { 25 | group.add(this); 26 | } 27 | }, 28 | // 如果子弹飞出屏幕 就调用这个回调 29 | resetBullet: function resetBullet(bullet) { 30 | bullet.kill(); 31 | }, 32 | //重置 位置 角度 转动(0 3.12) 速度 重力 33 | rebirth: function rebirth(x, y, angle, rotation, gx, gy) { 34 | gx = gx || 0; 35 | gy = gy || 0; 36 | this.reset(x, y); 37 | this.scale.set(1); 38 | //this.lifespan = 200; //能发射的长度 39 | this.rotation = rotation; //设置子弹的角度 40 | this.game.physics.arcade.velocityFromAngle(angle, this.speed, this.body.velocity); 41 | this.angle = angle; 42 | this.body.gravity.set(gx, gy); 43 | }, 44 | hit: function hit() { 45 | this.explode(); 46 | this.dead(); 47 | }, 48 | //爆炸效果 49 | explode: function explode() { 50 | var boom = this.game.add.sprite(this.x, this.y, 'explode', 0); 51 | boom.anchor.setTo(0.5, 0.5); 52 | boom.width = 40; //设置对象比例 53 | boom.height = 40; 54 | var anim = boom.animations.add('boom', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], 20); 55 | anim.play(); 56 | anim.onComplete.add(function () { 57 | boom.destroy(); 58 | }); 59 | } 60 | }); 61 | 62 | var BulletFactory = function BulletFactory() {}; 63 | BulletFactory.prototype = { 64 | bulletTypes: ["bullet0", "bullet2", "bullet9", "bullet10"], 65 | createBullet: function createBullet(bulletType, game, group, properties) { 66 | bulletType = bulletType || this.randomBullet(); 67 | var bullet = null; 68 | if (bulletType === "bullet0") { 69 | var b = new Bullet0(game, group, properties); 70 | b.name = 'bullet'; 71 | bullet = b; 72 | } else if (bulletType === "bullet2") { 73 | var b = new Bullet2(game, group, properties); 74 | b.name = 'bullet'; 75 | bullet = b; 76 | } else if (bulletType === "bullet9") { 77 | var b = new Bullet9(game, group, properties); 78 | b.name = 'bullet'; 79 | bullet = b; 80 | } else if (bulletType === "bullet10") { 81 | var b = new Bullet10(game, group, properties); 82 | b.name = 'bullet'; 83 | bullet = b; 84 | } 85 | return bullet; 86 | }, 87 | randomBullet: function randomBullet() { 88 | var bulletIndex = Math.floor(Math.random() * (this.bulletTypes.length - 1)); 89 | var bulletType = this.bulletTypes[bulletIndex]; 90 | return bulletType; 91 | } 92 | }; 93 | 94 | var Bullet0 = extend(Bullet, { 95 | ctor: function ctor(game, group, properties) { 96 | this._super.call(this, game, 0, 0, "bullet0", null, group, properties); 97 | this.bulletType = "bullet0"; 98 | } 99 | }); 100 | 101 | var Bullet2 = extend(Bullet, { 102 | ctor: function ctor(game, group, properties) { 103 | this._super.call(this, game, 0, 0, "bullet2", null, group, properties); 104 | this.bulletType = "bullet2"; 105 | } 106 | }); 107 | var Bullet9 = extend(Bullet, { 108 | ctor: function ctor(game, group, properties) { 109 | this._super.call(this, game, 0, 0, "bullet9", null, group, properties); 110 | this.bulletType = "bullet9"; 111 | } 112 | }); 113 | var Bullet10 = extend(Bullet, { 114 | ctor: function ctor(game, group, properties) { 115 | this._super.call(this, game, 0, 0, "bullet10", null, group, properties); 116 | this.bulletType = "bullet10"; 117 | } 118 | }); -------------------------------------------------------------------------------- /static/hitball/src/objects/Coin.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | /** 4 | * Created by liangdas on 2016/12/6 0006. 5 | * Email :1587790525@qq.com 6 | */ 7 | var extend = require('../utils/inherits.js'); 8 | var GameRole = require('./Role.js'); 9 | module.exports = extend(GameRole, { 10 | ctor: function ctor(game, x, y, group, properties) { 11 | this.roleType = "enemy"; 12 | properties = properties || {}; 13 | this._super(game, x, y, "coin", null, properties); 14 | this.game = game; 15 | this.speed = properties.speed || 50; 16 | 17 | this.nextFire = 0; //下一次发射子弹的时间 18 | this.fireRate = 50; //发射速率 50ms 19 | this.tileVolume = 3; //体积与瓦片地图判断是否可以通过 20 | this.game.physics.arcade.enable(this); 21 | this.anchor.x = 0.5; 22 | this.anchor.y = 0.5; 23 | this.anchor.setTo(0.5, 0.5); 24 | this.checkWorldBounds = true; 25 | this.outOfBoundsKill = true; 26 | this.body.collideWorldBounds = true; //与世界边境进行物理检测 27 | this.inputEnabled = true; 28 | this.input.useHandCursor = true; //当鼠标移动到其上面时显示小手 29 | //this.input.enableDrag(); //可以拖动 30 | if (group) { 31 | group.add(this); 32 | } 33 | }, 34 | move: function move() { 35 | 36 | }, 37 | rebirth: function rebirth(x, y) { 38 | this.reset(x, y); 39 | } 40 | }); -------------------------------------------------------------------------------- /static/hitball/src/objects/Enemy.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | /** 4 | * Created by liangdas on 2016/12/6 0006. 5 | * Email :1587790525@qq.com 6 | */ 7 | var extend = require('../utils/inherits.js'); 8 | var Player = require('./Player.js'); 9 | module.exports = extend(Player, { 10 | ctor: function ctor(game, x, y, group, properties) { 11 | this.roleType = "deadly"; 12 | properties = properties || {}; 13 | this._super(game, x, y, "deadly", null, properties); 14 | } 15 | }); -------------------------------------------------------------------------------- /static/hitball/src/objects/Player.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | /** 4 | * Created by liangdas on 2016/12/6 0006. 5 | * Email :1587790525@qq.com 6 | */ 7 | var extend = require('../utils/inherits.js'); 8 | var GameRole = require('./Role.js'); 9 | var mqant=window.mqant 10 | module.exports = extend(GameRole, { 11 | ctor: function ctor(game, x, y, group, properties) { 12 | this.roleType = "hero"; 13 | properties = properties || {}; 14 | this.game = game; 15 | this.arrows = properties.arrowsGroup; //视觉观察组 16 | this.rotateDirection = 1; // rotate direction: 1-clockwise, 2-counterclockwise 17 | this.rotateSpeed = 3; // arrow rotation speed 18 | this.friction = 0.99; // friction affects ball speed 速度递减因子 19 | this.arrow; // rotating arrow 20 | this.minPower = 50; // minimum power applied to ball 21 | this.maxPower = properties.maxPower || 200; // maximum power applied to ball 22 | this.power=this.minPower; //力量 23 | this.ballRadius=10; //周长 24 | this.degToRad=0.0174532925; // degrees-radians conversion 25 | this._super(this.game, x, y, "ball", null, properties); 26 | this.xSpeed = 0; 27 | this.ySpeed = 0; 28 | this.game.physics.arcade.enable(this); 29 | this.anchor.setTo(0.5, 0.5); 30 | this.checkWorldBounds = true; 31 | this.outOfBoundsKill = true; 32 | this.body.collideWorldBounds = true; //与世界边境进行物理检测 33 | this.inputEnabled = true; 34 | this.input.useHandCursor = true; //当鼠标移动到其上面时显示小手 35 | this.powering=false; 36 | //this.input.enableDrag(); //可以拖动 37 | if (group) { 38 | group.add(this); 39 | } 40 | }, 41 | dead: function () { 42 | if(this.alive){ 43 | this._super(); 44 | this.arrow.kill(); 45 | } 46 | }, 47 | getArrow: function getArrow() { 48 | if (this.arrow == null) { 49 | var arrow = this.arrows.getFirstExists(false); 50 | if (arrow) { 51 | this.arrow = arrow; 52 | this.arrow.reset(this.x, this.y); 53 | } else { 54 | //设置一个观察器 55 | this.arrow = this.game.add.sprite(this.game.world.centerX,this.game.world.centerY,"arrow"); 56 | this.arrow.anchor.x = -1; 57 | this.arrow.anchor.y = 0.5; 58 | } 59 | } 60 | return this.arrow; 61 | }, 62 | Power:function (){ 63 | this.power++; 64 | this.power = Math.min(this.power,this.maxPower) 65 | this.powering=true; 66 | }, 67 | Fire: function () { 68 | //发射 69 | //this.xSpeed += Math.cos(this.getArrow().angle*this.degToRad)*this.power/20; 70 | //this.ySpeed += Math.sin(this.getArrow().angle*this.degToRad)*this.power/20; 71 | this.power = this.minPower; 72 | mqant.requestNR("Hitball/HD_Fire",{ 73 | "Rid": "001", 74 | "Angle": this.getArrow().angle, 75 | "Power": this.power, 76 | "X": this.x, 77 | "Y": this.y, 78 | }); 79 | this.rotateDirection*=-1; 80 | this.powering=false; 81 | }, 82 | Rotate: function () { 83 | this.getArrow().angle+=this.rotateSpeed*this.rotateDirection; 84 | }, 85 | OnMove:function(player){ 86 | this.x=player.X; 87 | this.y=player.Y; 88 | this.xSpeed=player.XSpeed; 89 | this.ySpeed=player.YSpeed; 90 | this.power=player.Power; 91 | this.rotateDirection=player.RotateDirection 92 | this.getArrow().x=this.x; 93 | this.getArrow().y=this.y; 94 | if(!this.powering){ 95 | this.angle=player.Angle 96 | this.getArrow().angle=player.Angle 97 | } 98 | }, 99 | OnRotate:function(player){ 100 | this.angle=player.Angle 101 | this.getArrow().angle=player.Angle 102 | }, 103 | Move: function () { 104 | this.x=this.x+this.xSpeed; 105 | this.y=this.y+this.ySpeed; 106 | // reduce ball speed using friction 速度递减 107 | this.xSpeed*=this.friction; 108 | this.ySpeed*=this.friction; 109 | // update arrow position 更新选择箭头 110 | this.getArrow().x=this.x; 111 | this.getArrow().y=this.y; 112 | //var self=this; 113 | //向服务器汇报 114 | //mqant.requestNR("Hitball/HD_Move",{ 115 | // "wid": "1", 116 | // "war": "001", 117 | // "x":x, 118 | // "y":y 119 | //}); 120 | } 121 | }); -------------------------------------------------------------------------------- /static/hitball/src/objects/Role.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * Created by liangdas on 2016/12/6 0006. 4 | * Email :1587790525@qq.com 5 | */ 6 | var extend = require('../utils/inherits.js'); 7 | module.exports = extend(Phaser.Sprite, { 8 | //ctor 可以省略 省略以后会继续执行其父构造函数 如 this._super.apply(this,arguments); 9 | ctor: function ctor(game, x, y, key, frame, properties) { 10 | properties = properties || {}; 11 | this._super(game, x, y, key, frame); 12 | this.rid = properties.rid; //系统角色 13 | this.wid = properties.wid; //战场中的角色ID 14 | }, 15 | dead: function dead() { 16 | if(this.alive){ 17 | this.kill(); 18 | } 19 | } 20 | }); -------------------------------------------------------------------------------- /static/hitball/src/states/BootState.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var PlayGameState = require('./PlayGameState.js'); 3 | var guiLogin = require('../gui/login.js'); 4 | var mqant=window.mqant 5 | module.exports = { 6 | preload: function preload() { 7 | "use strict"; 8 | this.game.load.image('loading', 'assets/ball.png'); 9 | this.game.load.tilemap('desert', 'assets/tilemaps/desert.json', null, Phaser.Tilemap.TILED_JSON); 10 | this.game.load.image('tiles', 'assets/tilemaps/tmw_desert_spacing.png'); 11 | }, 12 | create: function create() { 13 | var self=this; 14 | var preloadSprite = this.game.add.sprite(34, game.height / 2, 'loading'); 15 | this.game.load.setPreloadSprite(preloadSprite); 16 | //this.game.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL; 17 | this.game.scale.scaleMode = Phaser.ScaleManager.RESIZE; 18 | this.game.scale.setUserScale(Phaser.myScaleManager.hScale, Phaser.myScaleManager.vScale, Phaser.myScaleManager.hTrim, Phaser.myScaleManager.vTrim); 19 | var useSSL = 'https:' == document.location.protocol ? true : false; 20 | try{ 21 | mqant.init({ 22 | host: window.location.hostname, 23 | port: 3653, 24 | client_id: "111", 25 | useSSL:useSSL, 26 | onSuccess:function() { 27 | //alert("游戏链接成功!"); 28 | mqant.requestNR("Hitball/HD_Join",{ 29 | "Rid": "001", 30 | }); 31 | 32 | mqant.on('Hitball/OnEnter', function(data) { 33 | var message=JSON.parse(data.payloadString); 34 | var player=message.Player; 35 | var coins=message.Coins; 36 | var Rid=message.Rid; 37 | try{ 38 | self.game.state.add('PlayGameState', new PlayGameState(Rid,player,coins), false); 39 | self.game.state.start('PlayGameState'); 40 | }catch(e) { 41 | alert(e); 42 | } 43 | }); 44 | }, 45 | onConnectionLost:function(code,reason) { 46 | console.log(code) 47 | alert("链接断开了:"+code); 48 | } 49 | }); 50 | }catch (e){ 51 | alert(e); 52 | } 53 | } 54 | }; 55 | -------------------------------------------------------------------------------- /static/hitball/src/utils/inherits.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * Created by liangdas on 2016/12/6 0006. 4 | * Email :1587790525@qq.com 5 | * 这是一个 javascript 类继承函数, 6 | * 与以往的继承函数不同的是这个函数, 7 | * 可以直接从一个已存在的普通构造函数继承。 8 | */ 9 | function object(o){ 10 | function W(){ 11 | } 12 | W.prototype=o; 13 | return new W(); 14 | } 15 | function inheritPrototype(SubType,SuperType){ 16 | var prototype; 17 | if(typeof Object.create==='function'){ 18 | prototype=Object.create(SuperType.prototype); 19 | }else{ 20 | prototype=object.create(SuperType.prototype); 21 | } 22 | prototype.constructor=SubType; 23 | SubType.prototype=prototype; 24 | } 25 | module.exports = function (superCtor, prop) { 26 | return function () { 27 | var fnTest = /xyz/.test(function () { 28 | xyz; 29 | }) ? /\b_super\b/ : /.*/; 30 | 31 | var _super = superCtor.prototype; 32 | //// The base Class implementation (does nothing) 33 | function baseClass() { 34 | if (typeof baseClass.prototype.ctor==="undefined") { 35 | }else{ 36 | var args = new Array() 37 | for(var k in arguments){ 38 | args.push(arguments[k]); 39 | } 40 | baseClass.prototype.ctor.apply(this, args); 41 | } 42 | }; 43 | // 空函数F: 44 | //var F = function F() {}; 45 | //// 把F的原型指向Student.prototype: 46 | //F.prototype = superCtor.prototype; 47 | ////F.prototype = Object.create(superCtor.prototype); 48 | //// 把PrimaryStudent的原型指向一个新的F对象,F对象的原型正好指向Student.prototype: 49 | //baseClass.prototype = new F(); 50 | //// 把PrimaryStudent原型的构造函数修复为PrimaryStudent: 51 | //baseClass.prototype.constructor = baseClass; 52 | inheritPrototype(baseClass,superCtor); 53 | var prototype = baseClass.prototype; 54 | if(typeof (_super)==="undefined"){ 55 | 56 | }else{ 57 | //_super["ctor"]="ss"; 58 | if (typeof (_super["ctor"])==="undefined") { 59 | _super["ctor"] = superCtor; 60 | } 61 | } 62 | 63 | // Copy the properties over onto the new prototype 64 | for (var name in prop) { 65 | // Check if we're overwriting an existing function 66 | prototype[name] = typeof prop[name] == "function" && typeof _super[name] == "function" && fnTest.test(prop[name]) ? function (name, fn) { 67 | return function () { 68 | //var tmp_superclass = this.superclass; 69 | var tmp = this._super; 70 | // Add a new ._super() method that is the same method 71 | // but on the super-class 72 | this._super = _super[name]; 73 | //this.superclass=superCtor.bind(this); 74 | // The method only need to be bound temporarily, so we 75 | // remove it when we're done executing 76 | var args = new Array() 77 | for(var k in arguments){ 78 | args.push(arguments[k]); 79 | } 80 | var ret = fn.apply(this,args); 81 | this._super = tmp; 82 | //this.superclass=tmp_superclass; 83 | return ret; 84 | }; 85 | }(name, prop[name]) : prop[name]; 86 | } 87 | return baseClass; 88 | }(); 89 | }; 90 | -------------------------------------------------------------------------------- /static/hitball/src/utils/list.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | /** 4 | * Created by love on 16/12/11. 5 | */ 6 | /** 7 | * js实现list 8 | * 9 | */ 10 | module.exports =function List() { 11 | this.value = []; 12 | 13 | /* 添加 */ 14 | this.add = function (obj) { 15 | return this.value.push(obj); 16 | }; 17 | 18 | /* 大小 */ 19 | this.size = function () { 20 | return this.value.length; 21 | }; 22 | 23 | /* 返回指定索引的值 */ 24 | this.get = function (index) { 25 | return this.value[index]; 26 | }; 27 | 28 | /* 删除指定索引的值 */ 29 | this.remove = function (index) { 30 | this.value.splice(index, 1); 31 | return this.value; 32 | }; 33 | 34 | /* 删除全部值 */ 35 | this.removeAll = function () { 36 | return this.value = []; 37 | }; 38 | 39 | /* 是否包含某个对象 */ 40 | this.constains = function (obj) { 41 | for (var i in this.value) { 42 | if (obj == this.value[i]) { 43 | return true; 44 | } else { 45 | continue; 46 | } 47 | } 48 | return false; 49 | }; 50 | 51 | /* 是否包含某个对象 */ 52 | this.getAll = function () { 53 | var allInfos = ''; 54 | for (var i in this.value) { 55 | if (i != value.length - 1) { 56 | allInfos += this.value[i] + ","; 57 | } else { 58 | allInfos += this.value[i]; 59 | } 60 | } 61 | alert(allInfos); 62 | return allInfos += this.value[i] + ",";; 63 | }; 64 | } 65 | /* 66 | * MAP对象,实现MAP功能 67 | * 68 | * 接口: 69 | * size() 获取MAP元素个数 70 | * isEmpty() 判断MAP是否为空 71 | * clear() 删除MAP所有元素 72 | * put(key, value) 向MAP中增加元素(key, value) 73 | * remove(key) 删除指定KEY的元素,成功返回True,失败返回False 74 | * get(key) 获取指定KEY的元素值VALUE,失败返回NULL 75 | * element(index) 获取指定索引的元素(使用element.key,element.value获取KEY和VALUE),失败返回NULL 76 | * containsKey(key) 判断MAP中是否含有指定KEY的元素 77 | * containsValue(value) 判断MAP中是否含有指定VALUE的元素 78 | * values() 获取MAP中所有VALUE的数组(ARRAY) 79 | * keys() 获取MAP中所有KEY的数组(ARRAY) 80 | * 81 | * 例子: 82 | * var map = new Map(); 83 | * 84 | * map.put("key", "value"); 85 | * var val = map.get("key") 86 | * …… 87 | * 88 | */ 89 | function Map() { 90 | this.elements = new Array(); 91 | 92 | //获取MAP元素个数 93 | this.size = function () { 94 | return this.elements.length; 95 | }; 96 | 97 | //判断MAP是否为空 98 | this.isEmpty = function () { 99 | return this.elements.length < 1; 100 | }; 101 | 102 | //删除MAP所有元素 103 | this.clear = function () { 104 | this.elements = new Array(); 105 | }; 106 | 107 | //向MAP中增加元素(key, value) 108 | this.put = function (_key, _value) { 109 | this.elements.push({ 110 | key: _key, 111 | value: _value 112 | }); 113 | }; 114 | 115 | //删除指定KEY的元素,成功返回True,失败返回False 116 | this.remove = function (_key) { 117 | var bln = false; 118 | try { 119 | for (var i = 0; i < this.elements.length; i++) { 120 | if (this.elements[i].key == _key) { 121 | this.elements.splice(i, 1); 122 | return true; 123 | } 124 | } 125 | } catch (e) { 126 | bln = false; 127 | } 128 | return bln; 129 | }; 130 | 131 | //获取指定KEY的元素值VALUE,失败返回NULL 132 | this.get = function (_key) { 133 | try { 134 | for (var i = 0; i < this.elements.length; i++) { 135 | if (this.elements[i].key == _key) { 136 | return this.elements[i].value; 137 | } 138 | } 139 | } catch (e) { 140 | return null; 141 | } 142 | }; 143 | 144 | //获取指定索引的元素(使用element.key,element.value获取KEY和VALUE),失败返回NULL 145 | this.element = function (_index) { 146 | if (_index < 0 || _index >= this.elements.length) { 147 | return null; 148 | } 149 | return this.elements[_index]; 150 | }; 151 | 152 | //判断MAP中是否含有指定KEY的元素 153 | this.containsKey = function (_key) { 154 | var bln = false; 155 | try { 156 | for (var i = 0; i < this.elements.length; i++) { 157 | if (this.elements[i].key == _key) { 158 | bln = true; 159 | } 160 | } 161 | } catch (e) { 162 | bln = false; 163 | } 164 | return bln; 165 | }; 166 | 167 | //判断MAP中是否含有指定VALUE的元素 168 | this.containsValue = function (_value) { 169 | var bln = false; 170 | try { 171 | for (var i = 0; i < this.elements.length; i++) { 172 | if (this.elements[i].value == _value) { 173 | bln = true; 174 | } 175 | } 176 | } catch (e) { 177 | bln = false; 178 | } 179 | return bln; 180 | }; 181 | 182 | //获取MAP中所有VALUE的数组(ARRAY) 183 | this.values = function () { 184 | var arr = new Array(); 185 | for (var i = 0; i < this.elements.length; i++) { 186 | arr.push(this.elements[i].value); 187 | } 188 | return arr; 189 | }; 190 | 191 | //获取MAP中所有KEY的数组(ARRAY) 192 | this.keys = function () { 193 | var arr = new Array(); 194 | for (var i = 0; i < this.elements.length; i++) { 195 | arr.push(this.elements[i].key); 196 | } 197 | return arr; 198 | }; 199 | } -------------------------------------------------------------------------------- /static/hitball/webpack.config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * Created by liangdas on 17/1/20. 4 | * Email 1587790525@qq.com 5 | */ 6 | var path = require('path'); 7 | var webpack = require('webpack'); 8 | var phaserModule = path.join(__dirname, '/node_modules/phaser/'); 9 | var phaser = path.join(phaserModule, 'build/custom/phaser-split.js'), 10 | pixi = path.join(phaserModule, 'build/custom/pixi.js'), 11 | p2 = path.join(phaserModule, 'build/custom/p2.js'); 12 | module.exports = { 13 | //devtool: 'eval-source-map',//配置生成Source Maps,选择合适的选项 14 | devtool:"cheap-module-source-map", 15 | entry: __dirname + "/src/main.js",//已多次提及的唯一入口文件 16 | output: { 17 | path: __dirname + "/../../bin/hitball/js",//打包后的文件存放的地方 18 | filename: "main.js"//打包后输出文件的文件名 19 | }, 20 | 21 | module: { 22 | loaders: [ 23 | { 24 | test: /\.json$/, 25 | loader: "json" 26 | }, 27 | { 28 | test: /\.js$/, 29 | exclude: /node_modules/, 30 | loader: 'babel',//在webpack的module部分的loaders里进行配置即可 31 | }, 32 | { test: /pixi.js/, loader: "script" } 33 | ] 34 | }, 35 | 36 | devServer: { 37 | contentBase: "./js", 38 | colors: true, 39 | historyApiFallback: true, 40 | inline: true 41 | }, 42 | resolve: { 43 | alias: { 44 | 'phaser': phaser, 45 | 'pixi.js': pixi, 46 | 'p2': p2, 47 | } 48 | }, 49 | plugins: [ 50 | //这个使用uglifyJs压缩你的js代码 51 | new webpack.optimize.UglifyJsPlugin({ 52 | mangle: { 53 | except: ['$super','_super','ctor', '$', 'exports', 'require'] 54 | //以上变量‘$super’, ‘$’, ‘exports’ or ‘require’,不会被混淆 55 | }, 56 | minimize: true, 57 | compress: { 58 | warnings: false 59 | } 60 | }), 61 | ] 62 | } 63 | 64 | -------------------------------------------------------------------------------- /webapp/module.go: -------------------------------------------------------------------------------- 1 | /** 2 | 一定要记得在confin.json配置这个模块的参数,否则无法使用 3 | */ 4 | package webapp 5 | 6 | import ( 7 | "encoding/json" 8 | "github.com/gorilla/mux" 9 | "github.com/liangdas/mqant/conf" 10 | "github.com/liangdas/mqant/log" 11 | "github.com/liangdas/mqant/module" 12 | "github.com/liangdas/mqant/module/base" 13 | "net" 14 | "net/http" 15 | "time" 16 | ) 17 | 18 | var Module = func() *Web { 19 | web := new(Web) 20 | return web 21 | } 22 | 23 | type Web struct { 24 | basemodule.BaseModule 25 | } 26 | 27 | func (self *Web) GetType() string { 28 | //很关键,需要与配置文件中的Module配置对应 29 | return "Webapp" 30 | } 31 | func (self *Web) Version() string { 32 | //可以在监控时了解代码版本 33 | return "1.0.0" 34 | } 35 | func (self *Web) OnInit(app module.App, settings *conf.ModuleSettings) { 36 | self.BaseModule.OnInit(self, app, settings) 37 | } 38 | 39 | func loggingHandler(next http.Handler) http.Handler { 40 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 41 | start := time.Now() 42 | next.ServeHTTP(w, r) 43 | //[26/Oct/2017:19:07:04 +0800]`-`"GET /g/c HTTP/1.1"`"curl/7.51.0"`502`[127.0.0.1]`-`"-"`0.006`166`-`-`127.0.0.1:8030`-`0.000`xd 44 | log.Info("%s %s %s [%s] in %v", r.Method, r.URL.Path, r.Proto, r.RemoteAddr, time.Since(start)) 45 | }) 46 | } 47 | func Statushandler(w http.ResponseWriter, r *http.Request) { 48 | json.NewEncoder(w).Encode(map[string]string{ 49 | "status": "success", 50 | }) 51 | } 52 | func (self *Web) Run(closeSig chan bool) { 53 | //这里如果出现异常请检查8080端口是否已经被占用 54 | l, err := net.Listen("tcp", ":8080") 55 | if err != nil { 56 | log.Error("webapp server error", err.Error()) 57 | return 58 | } 59 | go func() { 60 | log.Info("webapp server Listen : %s", ":8080") 61 | root := mux.NewRouter() 62 | status := root.PathPrefix("/status") 63 | status.HandlerFunc(Statushandler) 64 | 65 | static := root.PathPrefix("/mqant/") 66 | static.Handler(http.StripPrefix("/mqant/", http.FileServer(http.Dir(self.GetModuleSettings().Settings["StaticPath"].(string))))) 67 | //r.Handle("/static",static) 68 | ServeMux := http.NewServeMux() 69 | ServeMux.Handle("/", root) 70 | http.Serve(l, loggingHandler(ServeMux)) 71 | }() 72 | <-closeSig 73 | log.Info("webapp server Shutting down...") 74 | l.Close() 75 | } 76 | 77 | func (self *Web) OnDestroy() { 78 | //一定别忘了关闭RPC 79 | self.GetServer().OnDestroy() 80 | } 81 | --------------------------------------------------------------------------------