├── .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 | 
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 |
50 |
51 |
52 |
53 |
54 |
55 |
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 | 
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 | [](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 | 
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 | [](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 |
--------------------------------------------------------------------------------