mm_os 4.3.7 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +101 -504
- package/index.js +26 -19
- package/lib/loader.js +787 -0
- package/lib/os.js +369 -0
- package/package.json +55 -84
- package/LICENSE +0 -21
- package/README_EN.md +0 -505
- package/adapter/adapter.js +0 -484
- package/adapter/custom_persistence.js +0 -661
- package/adapter/mqtt.js +0 -254
- package/adapter/socket.js +0 -244
- package/adapter/web.js +0 -92
- package/adapter/websocket.js +0 -43
- package/ai.js +0 -130
- package/com/api/README.md +0 -3
- package/com/api/com.json +0 -5
- package/com/api/config.tpl.json +0 -41
- package/com/api/drive.js +0 -732
- package/com/api/index.js +0 -201
- package/com/api/oauth.js +0 -200
- package/com/api/script.tpl.js +0 -32
- package/com/cmd/README.md +0 -11
- package/com/cmd/com.json +0 -5
- package/com/cmd/config.tpl.json +0 -48
- package/com/cmd/drive.js +0 -176
- package/com/cmd/index.js +0 -287
- package/com/cmd/job/config.json +0 -66
- package/com/cmd/job/index.js +0 -241
- package/com/cmd/job/test.js +0 -188
- package/com/cmd/msg.json +0 -48
- package/com/cmd/script.tpl.js +0 -12
- package/com/db/README.md +0 -3
- package/com/db/com.json +0 -5
- package/com/db/drive.js +0 -2206
- package/com/db/index.js +0 -241
- package/com/event/README.md +0 -4
- package/com/event/com.json +0 -5
- package/com/event/config.tpl.json +0 -20
- package/com/event/drive.js +0 -61
- package/com/event/index.js +0 -438
- package/com/event/script.tpl.js +0 -23
- package/com/mqtt/README.md +0 -47
- package/com/mqtt/com.json +0 -5
- package/com/mqtt/config.tpl.json +0 -42
- package/com/mqtt/drive.js +0 -704
- package/com/mqtt/index.js +0 -1052
- package/com/mqtt/index.test.js +0 -503
- package/com/mqtt/script.tpl.js +0 -719
- package/com/nav/README.md +0 -2
- package/com/nav/com.json +0 -5
- package/com/nav/config.tpl.json +0 -84
- package/com/nav/drive.js +0 -702
- package/com/nav/index.js +0 -228
- package/com/nav/tpl/admin_pc/page_channel.vue +0 -305
- package/com/nav/tpl/admin_pc/page_config.vue +0 -280
- package/com/nav/tpl/admin_pc/page_config_form.vue +0 -194
- package/com/nav/tpl/admin_pc/page_default.vue +0 -247
- package/com/nav/tpl/admin_pc/page_form.vue +0 -180
- package/com/nav/tpl/admin_pc/page_lang.vue +0 -264
- package/com/nav/tpl/admin_pc/page_nav.vue +0 -321
- package/com/nav/tpl/admin_pc/page_table.vue +0 -296
- package/com/nav/tpl/admin_pc/page_type.vue +0 -321
- package/com/nav/tpl/admin_pc/page_view.vue +0 -124
- package/com/nav/tpl/dev_pc/page_channel.vue +0 -253
- package/com/nav/tpl/dev_pc/page_config.vue +0 -253
- package/com/nav/tpl/dev_pc/page_default.vue +0 -247
- package/com/nav/tpl/dev_pc/page_form.vue +0 -162
- package/com/nav/tpl/dev_pc/page_nav.vue +0 -253
- package/com/nav/tpl/dev_pc/page_table.vue +0 -247
- package/com/nav/tpl/dev_pc/page_type.vue +0 -313
- package/com/nav/tpl/home_pc/page_channel.vue +0 -234
- package/com/nav/tpl/home_pc/page_default.vue +0 -234
- package/com/nav/tpl/home_pc/page_form.vue +0 -137
- package/com/nav/tpl/home_pc/page_list.vue +0 -234
- package/com/nav/tpl/home_pc/page_nav.vue +0 -221
- package/com/nav/tpl/home_pc/page_type.vue +0 -234
- package/com/nav/tpl/home_pc/page_view.vue +0 -125
- package/com/nav/tpl/home_phone/page_channel.vue +0 -234
- package/com/nav/tpl/home_phone/page_default.vue +0 -234
- package/com/nav/tpl/home_phone/page_form.vue +0 -137
- package/com/nav/tpl/home_phone/page_list.vue +0 -234
- package/com/nav/tpl/home_phone/page_nav.vue +0 -237
- package/com/nav/tpl/home_phone/page_type.vue +0 -234
- package/com/nav/tpl/home_phone/page_view.vue +0 -125
- package/com/nav/viewmodel.js +0 -446
- package/com/param/README.md +0 -2
- package/com/param/com.json +0 -5
- package/com/param/config.tpl.json +0 -136
- package/com/param/drive.js +0 -502
- package/com/param/index.js +0 -158
- package/com/param/script.tpl.js +0 -12
- package/com/pendant/README.md +0 -3
- package/com/pendant/com.json +0 -5
- package/com/pendant/config.tpl.json +0 -32
- package/com/pendant/drive.js +0 -204
- package/com/pendant/index.js +0 -467
- package/com/pendant/pendant.html +0 -16
- package/com/pendant/script.tpl.js +0 -18
- package/com/socket/README.md +0 -47
- package/com/socket/com.json +0 -5
- package/com/socket/config.tpl.json +0 -12
- package/com/socket/drive.js +0 -679
- package/com/socket/index.js +0 -402
- package/com/socket/script.tpl.js +0 -41
- package/com/sql/README.md +0 -3
- package/com/sql/com.json +0 -5
- package/com/sql/config.tpl.json +0 -74
- package/com/sql/drive.js +0 -1328
- package/com/sql/index.js +0 -152
- package/com/sql/script.tpl.js +0 -47
- package/com/static/README.md +0 -2
- package/com/static/com.json +0 -5
- package/com/static/config.tpl.json +0 -24
- package/com/static/drive.js +0 -194
- package/com/static/index.js +0 -237
- package/com/static/script.tpl.js +0 -28
- package/com/task/README.md +0 -3
- package/com/task/com.json +0 -5
- package/com/task/config.tpl.json +0 -24
- package/com/task/drive.js +0 -428
- package/com/task/index.js +0 -159
- package/com/task/script.tpl.js +0 -40
- package/com/template/com.json +0 -5
- package/com/template/config.tpl.json +0 -16
- package/com/template/drive.js +0 -81
- package/com/template/index.js +0 -141
- package/com.js +0 -237
- package/common/README.md +0 -2
- package/common/middleware/web_after/index.js +0 -26
- package/common/middleware/web_after/middleware.json +0 -9
- package/common/middleware/web_base/index.js +0 -113
- package/common/middleware/web_base/middleware.json +0 -19
- package/common/middleware/web_before/index.js +0 -33
- package/common/middleware/web_before/middleware.json +0 -9
- package/common/middleware/web_cors/index.js +0 -87
- package/common/middleware/web_cors/middleware.json +0 -24
- package/common/middleware/web_error/index.js +0 -131
- package/common/middleware/web_error/middleware.json +0 -19
- package/common/middleware/web_ip/index.js +0 -15
- package/common/middleware/web_ip/middleware.json +0 -14
- package/common/middleware/web_logger/index.js +0 -156
- package/common/middleware/web_logger/middleware.json +0 -14
- package/common/middleware/web_main/index.js +0 -26
- package/common/middleware/web_main/middleware.json +0 -9
- package/common/middleware/web_static/index.js +0 -73
- package/common/middleware/web_static/middleware.json +0 -54
- package/common/middleware/web_waf/index.js +0 -395
- package/common/middleware/web_waf/middleware.json +0 -13
- package/core/app/config.tpl.json +0 -67
- package/core/app/index.js +0 -711
- package/core/app/script.tpl.js +0 -52
- package/core/channel/index.js +0 -899
- package/core/channel/matcher.js +0 -585
- package/core/com/config.tpl.json +0 -16
- package/core/com/index.js +0 -77
- package/core/com/script.tpl.js +0 -5
- package/core/component/component.js +0 -42
- package/core/component/config.tpl.json +0 -63
- package/core/component/index.js +0 -273
- package/core/component/script.tpl.js +0 -19
- package/core/controller/config.tpl.json +0 -14
- package/core/controller/index.js +0 -371
- package/core/controller/script.tpl.js +0 -27
- package/core/factory/config.tpl.json +0 -14
- package/core/factory/entity.js +0 -275
- package/core/factory/index.js +0 -241
- package/core/factory/script.tpl.js +0 -16
- package/core/game/bat/index.js +0 -137
- package/core/game/bat/world.js +0 -622
- package/core/game/config.tpl.json +0 -16
- package/core/game/entity_admin.js +0 -230
- package/core/game/index.js +0 -186
- package/core/handler/config.tpl.json +0 -22
- package/core/handler/index.js +0 -181
- package/core/handler/script.tpl.js +0 -23
- package/core/logic/config.tpl.json +0 -14
- package/core/logic/index.js +0 -59
- package/core/logic/script.tpl.js +0 -19
- package/core/middleware/config.tpl.json +0 -16
- package/core/middleware/index.js +0 -117
- package/core/middleware/script.tpl.js +0 -37
- package/core/mod/config.tpl.json +0 -22
- package/core/mod/index.js +0 -136
- package/core/mod/script.tpl.js +0 -34
- package/core/model/config.tpl.json +0 -219
- package/core/model/index.js +0 -272
- package/core/model/model.js +0 -27
- package/core/model/script.tpl.js +0 -20
- package/core/notifier/config.tpl.json +0 -14
- package/core/notifier/index.js +0 -77
- package/core/notifier/script.tpl.js +0 -20
- package/core/plugin/config.tpl.json +0 -36
- package/core/plugin/index.js +0 -267
- package/core/plugin/script.tpl.js +0 -51
- package/core/pusher/config.tpl.json +0 -14
- package/core/pusher/index.js +0 -158
- package/core/pusher/script.tpl.js +0 -20
- package/core/room/bat/index.js +0 -170
- package/core/room/bat/room.js +0 -524
- package/core/room/config.tpl.json +0 -20
- package/core/room/index.js +0 -249
- package/core/room/room.js +0 -61
- package/core/scene/config.tpl.json +0 -14
- package/core/scene/index.js +0 -467
- package/core/scene/loop.js +0 -1306
- package/core/scene/map.js +0 -28
- package/core/scene/script.tpl.js +0 -22
- package/core/sender/config.tpl.json +0 -14
- package/core/sender/index.js +0 -79
- package/core/sender/script.tpl.js +0 -20
- package/core/service/config.tpl.json +0 -14
- package/core/service/index.js +0 -100
- package/core/service/script.tpl.js +0 -25
- package/core/store/config.tpl.json +0 -26
- package/core/store/index.js +0 -1794
- package/core/store/script.tpl.js +0 -22
- package/core/system/config.tpl.json +0 -18
- package/core/system/index.js +0 -312
- package/core/system/script.tpl.js +0 -77
- package/core/view/config.tpl.json +0 -14
- package/core/view/index.js +0 -91
- package/core/view/script.tpl.js +0 -20
- package/core/zone/bat/index.js +0 -744
- package/core/zone/config.tpl.json +0 -54
- package/core/zone/index.js +0 -655
- package/core/zone/script.tpl.js +0 -10
- package/core/zone/zone_bat.js +0 -136
- package/core//345/237/272/347/261/273/346/250/241/345/235/227/346/270/205/345/215/225.md +0 -24
- package/os.js +0 -53
- package/server.js +0 -602
- package/ulits/id_gen.js +0 -134
- package/ulits/word.js +0 -206
package/core/channel/index.js
DELETED
|
@@ -1,899 +0,0 @@
|
|
|
1
|
-
const {
|
|
2
|
-
Drive
|
|
3
|
-
} = require('mm_machine');
|
|
4
|
-
const {
|
|
5
|
-
RoomAdmin
|
|
6
|
-
} = require('../room/index.js');
|
|
7
|
-
const {
|
|
8
|
-
Matcher
|
|
9
|
-
} = require('./matcher.js');
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* 游戏频道 - 平行世界管理器
|
|
13
|
-
* 负责管理频道的创建、销毁、玩家隔离和频道间通信
|
|
14
|
-
*/
|
|
15
|
-
class Channel extends Drive {
|
|
16
|
-
static config = {
|
|
17
|
-
'name': 'default',
|
|
18
|
-
'title': '默认频道',
|
|
19
|
-
'min_level': 0,
|
|
20
|
-
'max_level': 1000,
|
|
21
|
-
'max_players': 5000,
|
|
22
|
-
'type': 'normal',
|
|
23
|
-
'load_threshold': 0.8,
|
|
24
|
-
'main': '',
|
|
25
|
-
'match': {
|
|
26
|
-
'wait_time': 120000,
|
|
27
|
-
'lv_range_init': 5,
|
|
28
|
-
'lv_range_max': 20,
|
|
29
|
-
'lv_expand_int': 10000,
|
|
30
|
-
'interval': 1000
|
|
31
|
-
}
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* 构造函数
|
|
36
|
-
* @param {object} config 配置参数
|
|
37
|
-
*/
|
|
38
|
-
constructor(config) {
|
|
39
|
-
super({ ...Channel.config, ...config });
|
|
40
|
-
|
|
41
|
-
// 游戏世界集合
|
|
42
|
-
this.worlds = new Map();
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* 预置
|
|
48
|
-
*/
|
|
49
|
-
Channel.prototype._preset = function () {
|
|
50
|
-
this.channel_id = 0;
|
|
51
|
-
this.status = 1;
|
|
52
|
-
this.stats = {
|
|
53
|
-
player: 0,
|
|
54
|
-
room: 0,
|
|
55
|
-
world: 0,
|
|
56
|
-
message: 0,
|
|
57
|
-
last_update: Date.now()
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
this._monitorTimer = null;
|
|
61
|
-
|
|
62
|
-
this.roomAdmin = null;
|
|
63
|
-
this.matcher = null;
|
|
64
|
-
|
|
65
|
-
// 主世界ID
|
|
66
|
-
this._main_world_id = '';
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* 获取模板目录
|
|
71
|
-
* @returns {string} 模板目录
|
|
72
|
-
*/
|
|
73
|
-
Channel.prototype.getTplDir = function () {
|
|
74
|
-
return __dirname;
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* 初始化核心
|
|
79
|
-
* @param {object} zone 分区对象
|
|
80
|
-
* @param {object} eventer 事件管理器
|
|
81
|
-
* @param {object} logger 日志管理器
|
|
82
|
-
*/
|
|
83
|
-
Channel.prototype._initCore = async function (zone, eventer, logger) {
|
|
84
|
-
if (!zone) {
|
|
85
|
-
throw new TypeError('分区对象不能为空');
|
|
86
|
-
}
|
|
87
|
-
else {
|
|
88
|
-
this.getZone = function () {
|
|
89
|
-
return zone;
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
if (logger) {
|
|
94
|
-
this.setLogger(logger);
|
|
95
|
-
}
|
|
96
|
-
if (eventer) {
|
|
97
|
-
this.getEventer = function () {
|
|
98
|
-
return eventer;
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
await this._initManager();
|
|
103
|
-
await this._loadSources();
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* 加载世界
|
|
108
|
-
* @returns {Promise<void>}
|
|
109
|
-
*/
|
|
110
|
-
Channel.prototype._loadWorlds = async function () {
|
|
111
|
-
// 通过事件方式加载已创建的世界数据,避免直接操作数据库
|
|
112
|
-
var worlds = await this.emitWait('world_load', {
|
|
113
|
-
zone_name: this.getZone().config.name,
|
|
114
|
-
channel_id: this.channel_id
|
|
115
|
-
});
|
|
116
|
-
if (worlds && worlds.length > 0) {
|
|
117
|
-
// 遍历世界列表,创建世界对象
|
|
118
|
-
for (var i = 0; i < worlds.length; i++) {
|
|
119
|
-
var info = worlds[i];
|
|
120
|
-
await this.createWorld(info, info.world_id);
|
|
121
|
-
}
|
|
122
|
-
this.log('info', `加载世界成功,共 ${worlds.length} 个`);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// 加载所有游戏世界
|
|
126
|
-
var promises = [];
|
|
127
|
-
for (var o of this.worlds.values()) {
|
|
128
|
-
promises.push(o.do('load'));
|
|
129
|
-
}
|
|
130
|
-
await Promise.all(promises);
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* 初始化房间管理器
|
|
135
|
-
*/
|
|
136
|
-
Channel.prototype._initRoomAdmin = async function () {
|
|
137
|
-
this.roomAdmin = new RoomAdmin();
|
|
138
|
-
await this.roomAdmin.do('init', this);
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* 初始化匹配器
|
|
143
|
-
*/
|
|
144
|
-
Channel.prototype._initMatcher = async function () {
|
|
145
|
-
this.matcher = new Matcher(this.config.match, this);
|
|
146
|
-
await this.matcher.do('init', this);
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* 初始化管理器
|
|
151
|
-
*/
|
|
152
|
-
Channel.prototype._initManager = async function () {
|
|
153
|
-
// var dir = this.getDir().dirname().dirname();
|
|
154
|
-
// var game = new Manager({
|
|
155
|
-
// name: 'game',
|
|
156
|
-
// title: '游戏',
|
|
157
|
-
// filename: 'game.json',
|
|
158
|
-
// tpl_dir: `../game/`.fullname(__dirname),
|
|
159
|
-
// base_dir: '',
|
|
160
|
-
// // base_dir: `../../common/${name}/`.fullname(__dirname),
|
|
161
|
-
// dir: `./game`.fullname(dir)
|
|
162
|
-
// }, this, this.game, Game);
|
|
163
|
-
// await game.do('init');
|
|
164
|
-
// this.manager.game = game;
|
|
165
|
-
};
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* 获取游戏管理器目录
|
|
169
|
-
* @returns {string} 游戏管理器目录
|
|
170
|
-
*/
|
|
171
|
-
Channel.prototype.getDir = function () {
|
|
172
|
-
return this.getZone().getDir();
|
|
173
|
-
};
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* 加载资源
|
|
177
|
-
*/
|
|
178
|
-
Channel.prototype._loadSources = async function () {
|
|
179
|
-
await this.manager.game.runAll('load');
|
|
180
|
-
};
|
|
181
|
-
|
|
182
|
-
/**
|
|
183
|
-
* 设置主世界ID
|
|
184
|
-
* @param {string} world_id 主世界ID
|
|
185
|
-
*/
|
|
186
|
-
Channel.prototype.setMainWorld = function (world_id) {
|
|
187
|
-
this._main_world_id = world_id;
|
|
188
|
-
};
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* 初始化资源
|
|
192
|
-
*/
|
|
193
|
-
Channel.prototype._initSources = async function () {
|
|
194
|
-
await this.manager.game.runAll('init', this, this.getEventer(), this.getLogger());
|
|
195
|
-
};
|
|
196
|
-
|
|
197
|
-
/**
|
|
198
|
-
* 加载游戏房间
|
|
199
|
-
* @returns {Promise<void>}
|
|
200
|
-
*/
|
|
201
|
-
Channel.prototype._loadRooms = async function () {
|
|
202
|
-
// 通过事件方式加载已创建的房间数据,避免直接操作数据库
|
|
203
|
-
var rooms = await this.emitWait('room_load', {
|
|
204
|
-
zone_name: this.getZone().config.name,
|
|
205
|
-
channel_id: this.channel_id
|
|
206
|
-
});
|
|
207
|
-
if (rooms && rooms.length > 0) {
|
|
208
|
-
// 遍历房间列表,创建房间对象
|
|
209
|
-
for (var i = 0; i < rooms.length; i++) {
|
|
210
|
-
var info = rooms[i];
|
|
211
|
-
var room = await this.roomAdmin.create(info, info.owner);
|
|
212
|
-
// 恢复房间原有ID
|
|
213
|
-
if (info.room_id) {
|
|
214
|
-
this.roomAdmin._rooms.delete(room.room_id);
|
|
215
|
-
room.room_id = info.room_id;
|
|
216
|
-
this.roomAdmin._rooms.set(room.room_id, room);
|
|
217
|
-
}
|
|
218
|
-
// 恢复房间状态
|
|
219
|
-
if (info.state) {
|
|
220
|
-
room.state = info.state;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
this.log('info', `加载房间成功,共 ${rooms.length} 个`);
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
// 加载所有游戏房间
|
|
227
|
-
var promises = [];
|
|
228
|
-
for (var o of this.rooms.values()) {
|
|
229
|
-
promises.push(o.do('load'));
|
|
230
|
-
}
|
|
231
|
-
await Promise.all(promises);
|
|
232
|
-
};
|
|
233
|
-
|
|
234
|
-
/**
|
|
235
|
-
* 启动核心
|
|
236
|
-
*/
|
|
237
|
-
Channel.prototype._startCore = async function () {
|
|
238
|
-
await this._initSources();
|
|
239
|
-
|
|
240
|
-
await this._loadWorlds();
|
|
241
|
-
|
|
242
|
-
await this._initRoomAdmin();
|
|
243
|
-
|
|
244
|
-
await this._loadRooms();
|
|
245
|
-
|
|
246
|
-
await this._initMatcher();
|
|
247
|
-
|
|
248
|
-
await this.manager.game.runAll('start');
|
|
249
|
-
await this.matcher.do('start');
|
|
250
|
-
this._startMonitor();
|
|
251
|
-
await this._startWorlds();
|
|
252
|
-
};
|
|
253
|
-
|
|
254
|
-
/**
|
|
255
|
-
* 启动游戏世界
|
|
256
|
-
*/
|
|
257
|
-
Channel.prototype._startWorlds = async function () {
|
|
258
|
-
var promises = [];
|
|
259
|
-
for (let o of this.worlds.values()) {
|
|
260
|
-
promises.push(o.do('start'));
|
|
261
|
-
}
|
|
262
|
-
await Promise.all(promises);
|
|
263
|
-
};
|
|
264
|
-
|
|
265
|
-
/**
|
|
266
|
-
* 初始化默认房间
|
|
267
|
-
*/
|
|
268
|
-
Channel.prototype._initRooms = async function () {
|
|
269
|
-
var promises = [];
|
|
270
|
-
for (let o of this.rooms.values()) {
|
|
271
|
-
promises.push(o.do('init', this, this.getEventer(), this.getLogger()));
|
|
272
|
-
}
|
|
273
|
-
await Promise.all(promises);
|
|
274
|
-
};
|
|
275
|
-
|
|
276
|
-
/**
|
|
277
|
-
* 启动频道监控
|
|
278
|
-
*/
|
|
279
|
-
Channel.prototype._startMonitor = function () {
|
|
280
|
-
this._monitorTimer = setInterval(() => {
|
|
281
|
-
this._updateStatus();
|
|
282
|
-
}, 30000);
|
|
283
|
-
};
|
|
284
|
-
|
|
285
|
-
/**
|
|
286
|
-
* 更新频道状态
|
|
287
|
-
*/
|
|
288
|
-
Channel.prototype._updateStatus = function () {
|
|
289
|
-
var player = this.player_ids.size;
|
|
290
|
-
var max_players = this.config.max_players;
|
|
291
|
-
var load_ratio = player / max_players;
|
|
292
|
-
|
|
293
|
-
if (load_ratio >= 1) {
|
|
294
|
-
this.status = 3;
|
|
295
|
-
} else if (load_ratio >= this.config.load_threshold) {
|
|
296
|
-
this.status = 2;
|
|
297
|
-
} else {
|
|
298
|
-
this.status = 1;
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
this.stats.player = player;
|
|
302
|
-
this.stats.room = this.rooms.size;
|
|
303
|
-
this.stats.world = this.worlds.size;
|
|
304
|
-
this.stats.last_update = Date.now();
|
|
305
|
-
};
|
|
306
|
-
|
|
307
|
-
/**
|
|
308
|
-
* 玩家进入频道
|
|
309
|
-
* @param {string} player_id 玩家ID
|
|
310
|
-
* @returns {object} 世界对象
|
|
311
|
-
*/
|
|
312
|
-
Channel.prototype.enter = function (player_id) {
|
|
313
|
-
if (!player_id) {
|
|
314
|
-
throw new TypeError('玩家ID不能为空');
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
if (this.player_ids.has(player_id)) {
|
|
318
|
-
throw new Error('玩家已在当前频道中');
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
var player = this.getZone().getPlayer(player_id);
|
|
322
|
-
if (!player) {
|
|
323
|
-
throw new Error(`玩家 ${player_id} 不存在`);
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
var {
|
|
327
|
-
min_level,
|
|
328
|
-
max_level,
|
|
329
|
-
status,
|
|
330
|
-
max_players
|
|
331
|
-
} = this.config;
|
|
332
|
-
|
|
333
|
-
this._validateStatus(status);
|
|
334
|
-
this._validateQualify(player, min_level, max_level, max_players);
|
|
335
|
-
|
|
336
|
-
try {
|
|
337
|
-
this.player_ids.set(player_id, true);
|
|
338
|
-
|
|
339
|
-
this.emitEvent('player_enter_channel', {
|
|
340
|
-
channel_id: this.config.name,
|
|
341
|
-
player_id: player_id,
|
|
342
|
-
player_level: player.level,
|
|
343
|
-
timestamp: Date.now()
|
|
344
|
-
});
|
|
345
|
-
|
|
346
|
-
let world = this.enterMainWorld(player_id);
|
|
347
|
-
return world;
|
|
348
|
-
} catch (error) {
|
|
349
|
-
this.player_ids.delete(player_id);
|
|
350
|
-
throw error;
|
|
351
|
-
}
|
|
352
|
-
};
|
|
353
|
-
|
|
354
|
-
/**
|
|
355
|
-
* 验证频道状态
|
|
356
|
-
* @param {number} status 频道状态
|
|
357
|
-
*/
|
|
358
|
-
Channel.prototype._validateStatus = function (status) {
|
|
359
|
-
if (status === 0) {
|
|
360
|
-
throw new Error('频道已关闭,无法进入');
|
|
361
|
-
}
|
|
362
|
-
if (status === 2) {
|
|
363
|
-
throw new Error('频道维护中,暂时无法进入');
|
|
364
|
-
}
|
|
365
|
-
if (status === 3) {
|
|
366
|
-
throw new Error('频道爆满,请稍后再试');
|
|
367
|
-
}
|
|
368
|
-
};
|
|
369
|
-
|
|
370
|
-
/**
|
|
371
|
-
* 检查玩家是否在频道中
|
|
372
|
-
* @param {string} player_id 玩家ID
|
|
373
|
-
* @returns {boolean} 是否在频道中
|
|
374
|
-
*/
|
|
375
|
-
Channel.prototype._hasPlayer = function (player_id) {
|
|
376
|
-
return this.player_ids.has(player_id);
|
|
377
|
-
};
|
|
378
|
-
|
|
379
|
-
/**
|
|
380
|
-
* 验证玩家资格
|
|
381
|
-
* @param {object} player 玩家对象
|
|
382
|
-
* @param {number} min_level 最低等级
|
|
383
|
-
* @param {number} max_level 最高等级
|
|
384
|
-
* @param {number} max_players 最大玩家数
|
|
385
|
-
*/
|
|
386
|
-
Channel.prototype._validateQualify = function (player, min_level, max_level, max_players) {
|
|
387
|
-
if (player.level < min_level || player.level > max_level) {
|
|
388
|
-
var msg = `境界不符,无法进入此频道(要求等级:${min_level}-${max_level})`;
|
|
389
|
-
throw new Error(msg);
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
if (this.player_ids.size >= max_players) {
|
|
393
|
-
throw new Error('频道人数已达上限,无法进入');
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
if (this._hasPlayer(player.player_id)) {
|
|
397
|
-
throw new Error('玩家已在当前频道中');
|
|
398
|
-
}
|
|
399
|
-
};
|
|
400
|
-
|
|
401
|
-
/**
|
|
402
|
-
* 获取默认房间
|
|
403
|
-
* @param {string} player_id 玩家ID
|
|
404
|
-
* @returns {object} 房间对象
|
|
405
|
-
*/
|
|
406
|
-
Channel.prototype.getDefaultRoom = async function (player_id) {
|
|
407
|
-
var player = this.getPlayer(player_id);
|
|
408
|
-
|
|
409
|
-
var room_name = player.returning ? 'main_room' : 'cultivation_area';
|
|
410
|
-
var room = this.rooms.get(room_name);
|
|
411
|
-
|
|
412
|
-
if (!room) {
|
|
413
|
-
throw new Error(`默认房间 ${room_name} 不存在`);
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
return room;
|
|
417
|
-
};
|
|
418
|
-
|
|
419
|
-
/**
|
|
420
|
-
* 玩家退出频道
|
|
421
|
-
* @param {string} player_id 玩家ID
|
|
422
|
-
* @returns {boolean} 是否成功退出
|
|
423
|
-
*/
|
|
424
|
-
Channel.prototype.leave = async function (player_id) {
|
|
425
|
-
if (!player_id) {
|
|
426
|
-
throw new TypeError('玩家ID不能为空');
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
if (!this.player_ids.has(player_id)) {
|
|
430
|
-
throw new Error('玩家不在当前频道中');
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
this.player_ids.delete(player_id);
|
|
434
|
-
|
|
435
|
-
this.emitEvent('player_leave_channel', {
|
|
436
|
-
channel_id: this.config.name,
|
|
437
|
-
player_id: player_id,
|
|
438
|
-
timestamp: Date.now()
|
|
439
|
-
});
|
|
440
|
-
return true;
|
|
441
|
-
};
|
|
442
|
-
|
|
443
|
-
/**
|
|
444
|
-
* 强制踢出玩家
|
|
445
|
-
* @param {string} player_id 玩家ID
|
|
446
|
-
* @param {string} reason 踢出原因
|
|
447
|
-
* @returns {boolean} 是否成功踢出
|
|
448
|
-
*/
|
|
449
|
-
Channel.prototype.kickPlayer = async function (player_id, reason = '系统维护') {
|
|
450
|
-
if (!player_id) {
|
|
451
|
-
throw new TypeError('玩家ID不能为空');
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
if (!this.player_ids.has(player_id)) {
|
|
455
|
-
throw new Error('玩家不在当前频道中');
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
this.player_ids.delete(player_id);
|
|
459
|
-
|
|
460
|
-
this.emitEvent('player_kicked_channel', {
|
|
461
|
-
channel_id: this.config.name,
|
|
462
|
-
player_id: player_id,
|
|
463
|
-
reason: reason,
|
|
464
|
-
timestamp: Date.now()
|
|
465
|
-
});
|
|
466
|
-
return true;
|
|
467
|
-
};
|
|
468
|
-
|
|
469
|
-
/**
|
|
470
|
-
* 获取玩家对象
|
|
471
|
-
* @param {string} player_id 玩家ID
|
|
472
|
-
* @returns {object} 玩家对象
|
|
473
|
-
*/
|
|
474
|
-
Channel.prototype.getPlayer = function (player_id) {
|
|
475
|
-
if (!player_id) {
|
|
476
|
-
throw new TypeError('玩家ID不能为空');
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
return this.getZone().getPlayer(player_id);
|
|
480
|
-
};
|
|
481
|
-
|
|
482
|
-
/**
|
|
483
|
-
* 获取所有玩家对象
|
|
484
|
-
* @returns {Array} 玩家对象列表
|
|
485
|
-
*/
|
|
486
|
-
Channel.prototype.getAllPlayers = function () {
|
|
487
|
-
var players = [];
|
|
488
|
-
for (var player_id of this.player_ids.keys()) {
|
|
489
|
-
var player = this.getPlayer(player_id);
|
|
490
|
-
players.push(player);
|
|
491
|
-
}
|
|
492
|
-
return players;
|
|
493
|
-
};
|
|
494
|
-
|
|
495
|
-
/**
|
|
496
|
-
* 创建房间
|
|
497
|
-
* @param {string} name 房间名称
|
|
498
|
-
* @param {string} player_id 玩家ID
|
|
499
|
-
* @returns {object} 创建的房间对象
|
|
500
|
-
*/
|
|
501
|
-
Channel.prototype.createRoom = async function (name, player_id) {
|
|
502
|
-
if (!name) {
|
|
503
|
-
throw new TypeError('房间名称不能为空');
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
if (!player_id) {
|
|
507
|
-
throw new TypeError('玩家ID不能为空');
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
var player = this.getPlayer(player_id);
|
|
511
|
-
if (!player) {
|
|
512
|
-
throw new Error(`玩家 ${player_id} 不存在`);
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
let config = {
|
|
516
|
-
name,
|
|
517
|
-
'min_level': player.level,
|
|
518
|
-
'max_level': player.level + 100
|
|
519
|
-
};
|
|
520
|
-
|
|
521
|
-
var room = await this.roomAdmin.create(config, player_id);
|
|
522
|
-
return room;
|
|
523
|
-
};
|
|
524
|
-
|
|
525
|
-
/**
|
|
526
|
-
* 销毁房间
|
|
527
|
-
* @param {string} room_id 房间ID
|
|
528
|
-
* @returns {boolean} 是否成功销毁
|
|
529
|
-
*/
|
|
530
|
-
Channel.prototype.destroyRoom = async function (room_id) {
|
|
531
|
-
if (!room_id) {
|
|
532
|
-
throw new TypeError('房间ID不能为空');
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
this.roomAdmin.del(room_id);
|
|
536
|
-
return true;
|
|
537
|
-
};
|
|
538
|
-
|
|
539
|
-
/**
|
|
540
|
-
* 玩家进入房间
|
|
541
|
-
* @param {string} room_id 房间ID
|
|
542
|
-
* @param {string} player_id 玩家ID
|
|
543
|
-
*/
|
|
544
|
-
Channel.prototype.enterRoom = function (room_id, player_id) {
|
|
545
|
-
this.roomAdmin.enter(room_id, player_id);
|
|
546
|
-
};
|
|
547
|
-
|
|
548
|
-
/**
|
|
549
|
-
* 玩家退出房间
|
|
550
|
-
* @param {string} room_id 房间ID
|
|
551
|
-
* @param {string} player_id 玩家ID
|
|
552
|
-
*/
|
|
553
|
-
Channel.prototype.leaveRoom = function (room_id, player_id) {
|
|
554
|
-
this.roomAdmin.leave(room_id, player_id);
|
|
555
|
-
};
|
|
556
|
-
|
|
557
|
-
/**
|
|
558
|
-
* 获取房间列表
|
|
559
|
-
* @returns {Array} 房间列表
|
|
560
|
-
*/
|
|
561
|
-
Channel.prototype.getRoomList = function () {
|
|
562
|
-
return this.roomAdmin.getList();
|
|
563
|
-
};
|
|
564
|
-
|
|
565
|
-
/**
|
|
566
|
-
* 玩家开始实时匹配
|
|
567
|
-
* @param {string} player_id 玩家ID
|
|
568
|
-
* @param {object} options 匹配选项
|
|
569
|
-
* @returns {object} 匹配状态
|
|
570
|
-
*/
|
|
571
|
-
Channel.prototype.startQuickMatch = function (player_id, options = {}) {
|
|
572
|
-
if (typeof player_id !== 'string') {
|
|
573
|
-
throw new TypeError('玩家ID必须是字符串');
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
var mode = options.mode || 'rank';
|
|
577
|
-
var format = options.format || '5v5';
|
|
578
|
-
var team_members = options.team_members || [player_id];
|
|
579
|
-
var team_size = team_members.length;
|
|
580
|
-
|
|
581
|
-
if (team_size > this._getMaxTeamSize(format)) {
|
|
582
|
-
throw new Error(`队伍人数超过限制: ${team_size}`);
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
for (var i = 0; i < team_members.length; i++) {
|
|
586
|
-
if (this.matcher.has(team_members[i])) {
|
|
587
|
-
throw new Error(`玩家 ${team_members[i]} 已在匹配池中`);
|
|
588
|
-
}
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
this.matcher.join(player_id, {
|
|
592
|
-
mode: mode,
|
|
593
|
-
format: format,
|
|
594
|
-
team_size: team_size,
|
|
595
|
-
team_members: team_members
|
|
596
|
-
});
|
|
597
|
-
|
|
598
|
-
return this.matcher.getMatchStatus(player_id);
|
|
599
|
-
};
|
|
600
|
-
|
|
601
|
-
/**
|
|
602
|
-
* 玩家取消实时匹配
|
|
603
|
-
* @param {string} player_id 玩家ID
|
|
604
|
-
* @returns {boolean} 是否成功取消
|
|
605
|
-
*/
|
|
606
|
-
Channel.prototype.cancelQuickMatch = function (player_id) {
|
|
607
|
-
if (typeof player_id !== 'string') {
|
|
608
|
-
throw new TypeError('玩家ID必须是字符串');
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
return this.matcher.leave(player_id);
|
|
612
|
-
};
|
|
613
|
-
|
|
614
|
-
/**
|
|
615
|
-
* 获取实时匹配状态
|
|
616
|
-
* @param {string} player_id 玩家ID
|
|
617
|
-
* @returns {object|null} 匹配状态
|
|
618
|
-
*/
|
|
619
|
-
Channel.prototype.getQuickMatchStatus = function (player_id) {
|
|
620
|
-
return this.matcher.getMatchStatus(player_id);
|
|
621
|
-
};
|
|
622
|
-
|
|
623
|
-
/**
|
|
624
|
-
* 获取匹配统计信息
|
|
625
|
-
* @returns {object} 统计信息
|
|
626
|
-
*/
|
|
627
|
-
Channel.prototype.getMatchStats = function () {
|
|
628
|
-
return {
|
|
629
|
-
waiting_count: this.matcher.getTotalWaiting(),
|
|
630
|
-
room_count: this.roomAdmin.getCount()
|
|
631
|
-
};
|
|
632
|
-
};
|
|
633
|
-
|
|
634
|
-
/**
|
|
635
|
-
* 获取最大队伍人数
|
|
636
|
-
* @param {string} format 比赛格式
|
|
637
|
-
* @returns {number} 最大队伍人数
|
|
638
|
-
*/
|
|
639
|
-
Channel.prototype._getMaxTeamSize = function (format) {
|
|
640
|
-
var sizes = {
|
|
641
|
-
'1v1': 1,
|
|
642
|
-
'3v3': 3,
|
|
643
|
-
'5v5': 5
|
|
644
|
-
};
|
|
645
|
-
return sizes[format] || 5;
|
|
646
|
-
};
|
|
647
|
-
|
|
648
|
-
/**
|
|
649
|
-
* 广播频道消息
|
|
650
|
-
* @param {object} data 广播数据
|
|
651
|
-
* @param {string} data_type 数据类型
|
|
652
|
-
* @returns {boolean} 是否广播成功
|
|
653
|
-
*/
|
|
654
|
-
Channel.prototype.broadcast = async function (data, data_type) {
|
|
655
|
-
if (!data) {
|
|
656
|
-
throw new TypeError('数据不能为空');
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
if (!data_type || typeof data_type !== 'string') {
|
|
660
|
-
throw new TypeError('数据类型必须是有效字符串');
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
// 触发广播事件,由业务层处理具体的广播逻辑
|
|
664
|
-
this.emitEvent('channel_broadcast', {
|
|
665
|
-
channel_id: this.config.name,
|
|
666
|
-
data: data,
|
|
667
|
-
data_type: data_type,
|
|
668
|
-
timestamp: Date.now()
|
|
669
|
-
});
|
|
670
|
-
|
|
671
|
-
return true;
|
|
672
|
-
};
|
|
673
|
-
|
|
674
|
-
/**
|
|
675
|
-
* 发送频道消息
|
|
676
|
-
* @param {string} player_id 发送者ID
|
|
677
|
-
* @param {string} content 消息内容
|
|
678
|
-
* @returns {boolean} 是否发送成功
|
|
679
|
-
*/
|
|
680
|
-
Channel.prototype.sendMessage = async function (player_id, content) {
|
|
681
|
-
if (!player_id) {
|
|
682
|
-
throw new TypeError('发送者ID不能为空');
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
if (!content || typeof content !== 'string') {
|
|
686
|
-
throw new TypeError('消息内容必须是有效字符串');
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
if (!this.player_ids.has(player_id)) {
|
|
690
|
-
throw new Error('发送者不在当前频道中');
|
|
691
|
-
}
|
|
692
|
-
|
|
693
|
-
var player = this.getPlayer(player_id);
|
|
694
|
-
|
|
695
|
-
var msg = {
|
|
696
|
-
sender_id: player_id,
|
|
697
|
-
sender_name: player.name || player_id,
|
|
698
|
-
content: content,
|
|
699
|
-
msg_type: 'text',
|
|
700
|
-
msg_group: 'channel',
|
|
701
|
-
timestamp: Date.now(),
|
|
702
|
-
channel_id: this.config.name
|
|
703
|
-
};
|
|
704
|
-
|
|
705
|
-
// 触发消息发送事件,由业务层处理具体的发送逻辑
|
|
706
|
-
this.emitEvent('channel_message_send', msg);
|
|
707
|
-
|
|
708
|
-
return true;
|
|
709
|
-
};
|
|
710
|
-
|
|
711
|
-
/**
|
|
712
|
-
* 公共数据传输方法
|
|
713
|
-
* @param {string} sender_id 发送者ID
|
|
714
|
-
* @param {object} data 传输数据
|
|
715
|
-
* @param {string} data_type 数据类型
|
|
716
|
-
* @returns {object} 传输结果
|
|
717
|
-
*/
|
|
718
|
-
Channel.prototype.send = async function (sender_id, data, data_type) {
|
|
719
|
-
// 触发数据发送事件,由业务层处理具体的发送逻辑
|
|
720
|
-
this.emitEvent('channel_data_send', {
|
|
721
|
-
channel_id: this.config.name,
|
|
722
|
-
sender_id: sender_id,
|
|
723
|
-
data: data,
|
|
724
|
-
data_type: data_type,
|
|
725
|
-
timestamp: Date.now()
|
|
726
|
-
});
|
|
727
|
-
|
|
728
|
-
// 返回默认结果
|
|
729
|
-
return {
|
|
730
|
-
players: this.player_ids.size,
|
|
731
|
-
success: 0,
|
|
732
|
-
fail: 0,
|
|
733
|
-
failed_players: []
|
|
734
|
-
};
|
|
735
|
-
};
|
|
736
|
-
|
|
737
|
-
/**
|
|
738
|
-
* 获取频道统计信息
|
|
739
|
-
* @returns {object} 统计信息
|
|
740
|
-
*/
|
|
741
|
-
Channel.prototype.getStats = function () {
|
|
742
|
-
return {
|
|
743
|
-
...this.stats,
|
|
744
|
-
channel_name: this.config.name,
|
|
745
|
-
channel_status: this.status,
|
|
746
|
-
channel_type: this.config.type,
|
|
747
|
-
current_time: Date.now()
|
|
748
|
-
};
|
|
749
|
-
};
|
|
750
|
-
|
|
751
|
-
/**
|
|
752
|
-
* 切换频道状态
|
|
753
|
-
* @param {number} new_status 新状态
|
|
754
|
-
* @returns {boolean} 是否切换成功
|
|
755
|
-
*/
|
|
756
|
-
Channel.prototype.switchStatus = function (new_status) {
|
|
757
|
-
if (typeof new_status !== 'number' || new_status < 0 || new_status > 3) {
|
|
758
|
-
throw new TypeError('频道状态必须是0-3之间的数字');
|
|
759
|
-
}
|
|
760
|
-
|
|
761
|
-
var old_status = this.status;
|
|
762
|
-
this.status = new_status;
|
|
763
|
-
|
|
764
|
-
this.emitEvent('channel_status_changed', {
|
|
765
|
-
channel_id: this.config.name,
|
|
766
|
-
old_status: old_status,
|
|
767
|
-
new_status: new_status,
|
|
768
|
-
timestamp: Date.now()
|
|
769
|
-
});
|
|
770
|
-
|
|
771
|
-
this.log('info', `频道 ${this.channel_id} 状态切换: ${old_status} -> ${new_status}`);
|
|
772
|
-
return true;
|
|
773
|
-
};
|
|
774
|
-
|
|
775
|
-
/**
|
|
776
|
-
* 销毁频道
|
|
777
|
-
* @returns {boolean} 是否销毁成功
|
|
778
|
-
*/
|
|
779
|
-
Channel.prototype.destroy = async function () {
|
|
780
|
-
if (this._monitorTimer) {
|
|
781
|
-
clearInterval(this._monitorTimer);
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
for (var player_id of this.player_ids.keys()) {
|
|
785
|
-
await this.kickPlayer(player_id, '频道关闭');
|
|
786
|
-
}
|
|
787
|
-
|
|
788
|
-
// 保存所有房间数据
|
|
789
|
-
await this._saveRooms();
|
|
790
|
-
|
|
791
|
-
for (var world_name of this.worlds.keys()) {
|
|
792
|
-
await this.destroyWorld(world_name);
|
|
793
|
-
}
|
|
794
|
-
|
|
795
|
-
for (var room_name of this.rooms.keys()) {
|
|
796
|
-
await this.destroyRoom(room_name);
|
|
797
|
-
}
|
|
798
|
-
|
|
799
|
-
if (this.matcher) {
|
|
800
|
-
this.matcher.stop();
|
|
801
|
-
}
|
|
802
|
-
|
|
803
|
-
if (this.roomAdmin) {
|
|
804
|
-
this.roomAdmin.destroy();
|
|
805
|
-
}
|
|
806
|
-
|
|
807
|
-
this.emitEvent('channel_destroyed', {
|
|
808
|
-
channel_id: this.channel_id,
|
|
809
|
-
timestamp: Date.now()
|
|
810
|
-
});
|
|
811
|
-
return true;
|
|
812
|
-
};
|
|
813
|
-
|
|
814
|
-
/**
|
|
815
|
-
* 保存所有房间数据
|
|
816
|
-
* @returns {Promise<void>}
|
|
817
|
-
*/
|
|
818
|
-
Channel.prototype._saveRooms = async function () {
|
|
819
|
-
try {
|
|
820
|
-
var promises = [];
|
|
821
|
-
for (var room of this.roomAdmin._rooms.values()) {
|
|
822
|
-
promises.push(room.do('save'));
|
|
823
|
-
}
|
|
824
|
-
await Promise.all(promises);
|
|
825
|
-
this.log('info', `保存所有房间数据成功,共 ${this.roomAdmin._rooms.size} 个`);
|
|
826
|
-
} catch (error) {
|
|
827
|
-
this.log('error', `保存房间数据失败: `, error);
|
|
828
|
-
}
|
|
829
|
-
};
|
|
830
|
-
|
|
831
|
-
/**
|
|
832
|
-
* 获取频道玩家数量
|
|
833
|
-
* @returns {number} 玩家数量
|
|
834
|
-
*/
|
|
835
|
-
Channel.prototype.getPlayerNum = function () {
|
|
836
|
-
return this.player_ids.size;
|
|
837
|
-
};
|
|
838
|
-
|
|
839
|
-
/**
|
|
840
|
-
* 进入主世界
|
|
841
|
-
* @param {string} player_id 玩家ID
|
|
842
|
-
*/
|
|
843
|
-
Channel.prototype.enterMainWorld = function (player_id) {
|
|
844
|
-
this.enterWorld(player_id, this._main_world_id);
|
|
845
|
-
};
|
|
846
|
-
|
|
847
|
-
/**
|
|
848
|
-
* 进入世界
|
|
849
|
-
* @param {string} player_id 玩家ID
|
|
850
|
-
* @param {string} world_id 世界ID
|
|
851
|
-
* @returns {object} 世界对象
|
|
852
|
-
*/
|
|
853
|
-
Channel.prototype.enterWorld = function (player_id, world_id) {
|
|
854
|
-
let world = this.getWorldById(world_id);
|
|
855
|
-
if (!world) {
|
|
856
|
-
throw new Error(`世界 ${world_id} 不存在`);
|
|
857
|
-
}
|
|
858
|
-
world.enter(player_id);
|
|
859
|
-
return world;
|
|
860
|
-
};
|
|
861
|
-
|
|
862
|
-
/**
|
|
863
|
-
* 根据世界ID获取世界对象
|
|
864
|
-
* @param {string} world_id 世界ID
|
|
865
|
-
* @returns {object|null} 世界对象
|
|
866
|
-
*/
|
|
867
|
-
Channel.prototype.getWorldById = function (world_id) {
|
|
868
|
-
return this.worlds.get(world_id);
|
|
869
|
-
};
|
|
870
|
-
|
|
871
|
-
/**
|
|
872
|
-
* 根据世界名称获取世界对象
|
|
873
|
-
* @param {string} name 世界名称
|
|
874
|
-
* @returns {object|null} 世界对象
|
|
875
|
-
*/
|
|
876
|
-
Channel.prototype.getWorldByName = function (name) {
|
|
877
|
-
for (let world of this.worlds.values()) {
|
|
878
|
-
if (world.config.name === name) {
|
|
879
|
-
return world;
|
|
880
|
-
}
|
|
881
|
-
}
|
|
882
|
-
return null;
|
|
883
|
-
};
|
|
884
|
-
|
|
885
|
-
/**
|
|
886
|
-
* 创建游戏世界
|
|
887
|
-
* @param {object} config 世界配置
|
|
888
|
-
* @param {string} world_id 世界ID
|
|
889
|
-
* @returns {object} 世界对象
|
|
890
|
-
*/
|
|
891
|
-
Channel.prototype.createWorld = async function (config, world_id) {
|
|
892
|
-
// let game = this.game[config.type];
|
|
893
|
-
// if (!game) {
|
|
894
|
-
// throw new Error(`游戏类型 ${config.type} 不存在`);
|
|
895
|
-
// }
|
|
896
|
-
// return await game.createWorld(config, world_id);
|
|
897
|
-
};
|
|
898
|
-
|
|
899
|
-
exports.Channel = Channel;
|