mm_os 3.3.1 → 4.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.
Files changed (380) hide show
  1. package/LICENSE +21 -201
  2. package/README.md +491 -99
  3. package/README_EN.md +498 -0
  4. package/adapter/adapter.js +431 -0
  5. package/adapter/custom_persistence.js +660 -0
  6. package/adapter/mqtt.js +273 -0
  7. package/adapter/socket.js +113 -0
  8. package/adapter/web.js +67 -0
  9. package/adapter/websocket.js +146 -0
  10. package/com/api/com.json +5 -0
  11. package/{core/com → com}/api/config.tpl.json +8 -8
  12. package/com/api/drive.js +708 -0
  13. package/com/api/index.js +198 -0
  14. package/com/api/oauth.js +200 -0
  15. package/com/api/script.tpl.js +32 -0
  16. package/com/cmd/README.md +11 -0
  17. package/com/cmd/com.json +5 -0
  18. package/com/cmd/config.tpl.json +122 -0
  19. package/com/cmd/drive.js +1548 -0
  20. package/com/cmd/index.js +1066 -0
  21. package/com/cmd/msg.json +48 -0
  22. package/com/cmd/nlp.js +525 -0
  23. package/com/cmd/script.tpl.js +32 -0
  24. package/com/db/com.json +5 -0
  25. package/com/db/drive.js +1999 -0
  26. package/com/db/index.js +242 -0
  27. package/{core/com → com}/event/README.md +4 -4
  28. package/com/event/com.json +5 -0
  29. package/{core/com → com}/event/config.tpl.json +18 -18
  30. package/com/event/drive.js +59 -0
  31. package/com/event/index.js +409 -0
  32. package/com/event/script.tpl.js +23 -0
  33. package/com/mqtt/com.json +5 -0
  34. package/{core/com → com}/mqtt/config.tpl.json +3 -5
  35. package/com/mqtt/drive.js +676 -0
  36. package/com/mqtt/index.js +822 -0
  37. package/com/mqtt/mm_mqtt.js +425 -0
  38. package/com/mqtt/script.tpl.js +723 -0
  39. package/com/nav/com.json +5 -0
  40. package/com/nav/config.tpl.json +84 -0
  41. package/com/nav/drive.js +702 -0
  42. package/com/nav/index.js +231 -0
  43. package/{core/com → com}/nav/tpl/admin_pc/page_config.vue +280 -280
  44. package/{core/com → com}/nav/tpl/admin_pc/page_config_form.vue +194 -194
  45. package/com/nav/tpl/admin_pc/page_form.vue +180 -0
  46. package/com/nav/tpl/admin_pc/page_view.vue +124 -0
  47. package/com/nav/tpl/dev_pc/page_default.vue +247 -0
  48. package/com/nav/tpl/dev_pc/page_type.vue +313 -0
  49. package/com/nav/tpl/home_pc/page_default.vue +234 -0
  50. package/com/nav/tpl/home_pc/page_form.vue +137 -0
  51. package/com/nav/tpl/home_pc/page_list.vue +234 -0
  52. package/com/nav/tpl/home_pc/page_nav.vue +221 -0
  53. package/com/nav/tpl/home_pc/page_type.vue +234 -0
  54. package/com/nav/tpl/home_pc/page_view.vue +125 -0
  55. package/com/nav/tpl/home_phone/page_channel.vue +234 -0
  56. package/com/nav/tpl/home_phone/page_default.vue +234 -0
  57. package/com/nav/tpl/home_phone/page_form.vue +137 -0
  58. package/com/nav/tpl/home_phone/page_nav.vue +237 -0
  59. package/com/nav/tpl/home_phone/page_type.vue +234 -0
  60. package/com/nav/tpl/home_phone/page_view.vue +125 -0
  61. package/com/nav/viewmodel.js +446 -0
  62. package/com/param/com.json +5 -0
  63. package/{core/com → com}/param/config.tpl.json +7 -1
  64. package/com/param/drive.js +502 -0
  65. package/com/param/index.js +155 -0
  66. package/com/param/script.tpl.js +12 -0
  67. package/com/pendant/com.json +5 -0
  68. package/{core/com/component → com/pendant}/config.tpl.json +15 -13
  69. package/com/pendant/drive.js +204 -0
  70. package/com/pendant/index.js +441 -0
  71. package/com/pendant/pendant.html +16 -0
  72. package/com/pendant/script.tpl.js +18 -0
  73. package/com/socket/com.json +5 -0
  74. package/com/socket/config.tpl.json +12 -0
  75. package/com/socket/drive.js +651 -0
  76. package/com/socket/index.js +351 -0
  77. package/com/socket/script.tpl.js +41 -0
  78. package/com/sql/com.json +5 -0
  79. package/{core/com → com}/sql/config.tpl.json +13 -9
  80. package/com/sql/drive.js +1259 -0
  81. package/com/sql/index.js +150 -0
  82. package/com/sql/script.tpl.js +47 -0
  83. package/com/static/com.json +5 -0
  84. package/{core/com → com}/static/config.tpl.json +10 -6
  85. package/com/static/drive.js +194 -0
  86. package/com/static/index.js +226 -0
  87. package/com/static/script.tpl.js +28 -0
  88. package/com/task/com.json +5 -0
  89. package/{core/com → com}/task/config.tpl.json +4 -6
  90. package/com/task/drive.js +405 -0
  91. package/com/task/index.js +148 -0
  92. package/com/task/script.tpl.js +37 -0
  93. package/com/template/com.json +5 -0
  94. package/com/template/config.tpl.json +16 -0
  95. package/com/template/drive.js +80 -0
  96. package/com/template/index.js +141 -0
  97. package/com.js +156 -0
  98. package/common/README.md +2 -0
  99. package/common/handler/msg/handler.json +22 -0
  100. package/common/handler/msg/index.js +23 -0
  101. package/common/handler/player/handler.json +22 -0
  102. package/common/handler/player/index.js +287 -0
  103. package/common/handler/user/handler.json +22 -0
  104. package/common/handler/user/index.js +23 -0
  105. package/common/middleware/web_after/index.js +29 -0
  106. package/common/middleware/web_after/middleware.json +9 -0
  107. package/common/middleware/web_base/index.js +113 -0
  108. package/common/middleware/web_base/middleware.json +19 -0
  109. package/common/middleware/web_before/index.js +33 -0
  110. package/common/middleware/web_before/middleware.json +9 -0
  111. package/common/middleware/web_cors/index.js +87 -0
  112. package/common/middleware/web_cors/middleware.json +24 -0
  113. package/common/middleware/web_error/index.js +119 -0
  114. package/common/middleware/web_error/middleware.json +18 -0
  115. package/common/middleware/web_ip/index.js +15 -0
  116. package/common/middleware/web_ip/middleware.json +14 -0
  117. package/common/middleware/web_logger/index.js +156 -0
  118. package/common/middleware/web_logger/middleware.json +14 -0
  119. package/common/middleware/web_main/index.js +24 -0
  120. package/common/middleware/web_main/middleware.json +9 -0
  121. package/common/middleware/web_static/index.js +73 -0
  122. package/common/middleware/web_static/middleware.json +54 -0
  123. package/common/middleware/web_waf/index.js +385 -0
  124. package/common/middleware/web_waf/middleware.json +13 -0
  125. package/common/model/msg/index.js +88 -0
  126. package/common/model/msg/model.json +401 -0
  127. package/common/model/player/index.js +63 -0
  128. package/common/model/player/model.json +185 -0
  129. package/common/model/user/index.js +11 -0
  130. package/common/model/user/model.json +219 -0
  131. package/core/app/config.tpl.json +67 -0
  132. package/core/app/index.js +632 -0
  133. package/core/app/script.tpl.js +52 -0
  134. package/core/channel/index.js +899 -0
  135. package/core/channel/matcher.js +585 -0
  136. package/core/com/config.tpl.json +16 -0
  137. package/core/com/index.js +74 -0
  138. package/core/com/script.tpl.js +5 -0
  139. package/core/component/component.js +42 -0
  140. package/core/component/config.tpl.json +63 -0
  141. package/core/component/index.js +273 -0
  142. package/core/component/script.tpl.js +19 -0
  143. package/core/controller/config.tpl.json +14 -0
  144. package/core/controller/index.js +373 -0
  145. package/core/controller/script.tpl.js +27 -0
  146. package/core/factory/config.tpl.json +14 -0
  147. package/core/factory/entity.js +275 -0
  148. package/core/factory/index.js +241 -0
  149. package/core/factory/script.tpl.js +16 -0
  150. package/core/game/bat/index.js +137 -0
  151. package/core/game/bat/world.js +622 -0
  152. package/core/game/config.tpl.json +16 -0
  153. package/core/game/entity_admin.js +230 -0
  154. package/core/game/index.js +186 -0
  155. package/core/handler/config.tpl.json +22 -0
  156. package/core/handler/index.js +181 -0
  157. package/core/handler/script.tpl.js +23 -0
  158. package/core/logic/config.tpl.json +14 -0
  159. package/core/logic/index.js +59 -0
  160. package/core/logic/script.tpl.js +19 -0
  161. package/core/middleware/config.tpl.json +16 -0
  162. package/core/middleware/index.js +125 -0
  163. package/core/middleware/script.tpl.js +37 -0
  164. package/core/mod/config.tpl.json +22 -0
  165. package/core/mod/index.js +130 -0
  166. package/core/mod/script.tpl.js +34 -0
  167. package/core/model/config.tpl.json +219 -0
  168. package/core/model/index.js +272 -0
  169. package/core/model/model.js +27 -0
  170. package/core/model/script.tpl.js +20 -0
  171. package/core/notifier/config.tpl.json +14 -0
  172. package/core/notifier/index.js +77 -0
  173. package/core/notifier/script.tpl.js +20 -0
  174. package/core/plugin/config.tpl.json +24 -0
  175. package/core/plugin/index.js +232 -0
  176. package/core/plugin/script.tpl.js +51 -0
  177. package/core/pusher/config.tpl.json +14 -0
  178. package/core/pusher/index.js +161 -0
  179. package/core/pusher/script.tpl.js +20 -0
  180. package/core/room/bat/index.js +170 -0
  181. package/core/room/bat/room.js +524 -0
  182. package/core/room/config.tpl.json +20 -0
  183. package/core/room/index.js +249 -0
  184. package/core/room/room.js +61 -0
  185. package/core/scene/config.tpl.json +14 -0
  186. package/core/scene/index.js +466 -0
  187. package/core/scene/loop.js +1255 -0
  188. package/core/scene/map.js +28 -0
  189. package/core/scene/script.tpl.js +22 -0
  190. package/core/sender/config.tpl.json +14 -0
  191. package/core/sender/index.js +79 -0
  192. package/core/sender/script.tpl.js +20 -0
  193. package/core/service/config.tpl.json +14 -0
  194. package/core/service/index.js +100 -0
  195. package/core/service/script.tpl.js +25 -0
  196. package/core/store/config.tpl.json +26 -0
  197. package/core/store/index.js +1755 -0
  198. package/core/store/script.tpl.js +22 -0
  199. package/core/store/sql.js +1464 -0
  200. package/core/system/config.tpl.json +18 -0
  201. package/core/system/index.js +312 -0
  202. package/core/system/script.tpl.js +77 -0
  203. package/core/view/config.tpl.json +14 -0
  204. package/core/view/index.js +91 -0
  205. package/core/view/script.tpl.js +20 -0
  206. package/core/zone/bat/index.js +725 -0
  207. package/core/zone/config.tpl.json +54 -0
  208. package/core/zone/index.js +614 -0
  209. package/core/zone/script.tpl.js +10 -0
  210. package/core/zone/zone_bat.js +136 -0
  211. package/core//345/237/272/347/261/273/346/250/241/345/235/227/346/270/205/345/215/225.md +24 -0
  212. package/index.js +17 -333
  213. package/os.js +57 -0
  214. package/package.json +58 -58
  215. package/server.js +598 -0
  216. package/README.en.md +0 -36
  217. package/conf.json +0 -3
  218. package/core/base/mqtt/index.js +0 -1110
  219. package/core/base/mqtt/lib.js +0 -40
  220. package/core/base/web/index.js +0 -245
  221. package/core/com/api/com.json +0 -4
  222. package/core/com/api/drive.js +0 -668
  223. package/core/com/api/index.js +0 -108
  224. package/core/com/api/oauth.js +0 -158
  225. package/core/com/api/script.js +0 -32
  226. package/core/com/app/README.md +0 -3
  227. package/core/com/app/com.json +0 -4
  228. package/core/com/app/config.tpl.json +0 -16
  229. package/core/com/app/drive.js +0 -309
  230. package/core/com/app/index.js +0 -211
  231. package/core/com/app/script.js +0 -155
  232. package/core/com/cmd/com.json +0 -4
  233. package/core/com/cmd/config.tpl.json +0 -66
  234. package/core/com/cmd/drive.js +0 -513
  235. package/core/com/cmd/index.js +0 -354
  236. package/core/com/cmd/old/5w2h.js +0 -54
  237. package/core/com/cmd/old/drive.js +0 -423
  238. package/core/com/cmd/script.js +0 -11
  239. package/core/com/component/README.md +0 -3
  240. package/core/com/component/com.json +0 -4
  241. package/core/com/component/component.html +0 -16
  242. package/core/com/component/drive.js +0 -197
  243. package/core/com/component/index.js +0 -312
  244. package/core/com/component/script.js +0 -18
  245. package/core/com/db/com.json +0 -4
  246. package/core/com/db/drive.js +0 -1160
  247. package/core/com/db/index.js +0 -176
  248. package/core/com/event/com.json +0 -4
  249. package/core/com/event/drive.js +0 -133
  250. package/core/com/event/index.js +0 -345
  251. package/core/com/event/script.js +0 -26
  252. package/core/com/eventer/com.js +0 -477
  253. package/core/com/eventer/com.json +0 -4
  254. package/core/com/middleware/com.js +0 -154
  255. package/core/com/middleware/com.json +0 -4
  256. package/core/com/middleware/config.tpl.json +0 -8
  257. package/core/com/middleware/script.js +0 -9
  258. package/core/com/mqtt/com.json +0 -4
  259. package/core/com/mqtt/drive.js +0 -600
  260. package/core/com/mqtt/index.js +0 -572
  261. package/core/com/mqtt/mm_mqtt.js +0 -330
  262. package/core/com/mqtt/script.js +0 -604
  263. package/core/com/msg/com.js +0 -296
  264. package/core/com/msg/com.json +0 -4
  265. package/core/com/nav/com.json +0 -4
  266. package/core/com/nav/config.tpl.json +0 -75
  267. package/core/com/nav/drive.js +0 -549
  268. package/core/com/nav/index.js +0 -182
  269. package/core/com/nav/tpl/admin_pc/page_form.vue +0 -180
  270. package/core/com/nav/tpl/admin_pc/page_view.vue +0 -124
  271. package/core/com/nav/tpl/dev_pc/page_default.vue +0 -247
  272. package/core/com/nav/tpl/dev_pc/page_type.vue +0 -313
  273. package/core/com/nav/tpl/home_pc/page_default.vue +0 -234
  274. package/core/com/nav/tpl/home_pc/page_form.vue +0 -137
  275. package/core/com/nav/tpl/home_pc/page_list.vue +0 -234
  276. package/core/com/nav/tpl/home_pc/page_nav.vue +0 -221
  277. package/core/com/nav/tpl/home_pc/page_type.vue +0 -234
  278. package/core/com/nav/tpl/home_pc/page_view.vue +0 -125
  279. package/core/com/nav/tpl/home_phone/page_channel.vue +0 -234
  280. package/core/com/nav/tpl/home_phone/page_default.vue +0 -234
  281. package/core/com/nav/tpl/home_phone/page_form.vue +0 -137
  282. package/core/com/nav/tpl/home_phone/page_nav.vue +0 -237
  283. package/core/com/nav/tpl/home_phone/page_type.vue +0 -234
  284. package/core/com/nav/tpl/home_phone/page_view.vue +0 -125
  285. package/core/com/nav/viewmodel.js +0 -296
  286. package/core/com/param/drive.js +0 -366
  287. package/core/com/param/index.js +0 -80
  288. package/core/com/param/script.js +0 -12
  289. package/core/com/param/test.js +0 -98
  290. package/core/com/plugin/README.md +0 -3
  291. package/core/com/plugin/com.json +0 -4
  292. package/core/com/plugin/config.tpl.json +0 -26
  293. package/core/com/plugin/drive.js +0 -536
  294. package/core/com/plugin/index.js +0 -259
  295. package/core/com/plugin/script.js +0 -213
  296. package/core/com/rpc/com.json +0 -4
  297. package/core/com/rpc/drive.js +0 -160
  298. package/core/com/rpc/index.js +0 -87
  299. package/core/com/rpc/rpc.js +0 -118
  300. package/core/com/socket/com.json +0 -4
  301. package/core/com/socket/config.tpl.json +0 -14
  302. package/core/com/socket/drive.js +0 -403
  303. package/core/com/socket/index.js +0 -62
  304. package/core/com/socket/script.js +0 -42
  305. package/core/com/sql/drive.js +0 -1087
  306. package/core/com/sql/index.js +0 -83
  307. package/core/com/sql/script.js +0 -48
  308. package/core/com/static/com.json +0 -4
  309. package/core/com/static/drive.js +0 -220
  310. package/core/com/static/index.js +0 -149
  311. package/core/com/static/script.js +0 -28
  312. package/core/com/task/com.json +0 -4
  313. package/core/com/task/drive.js +0 -403
  314. package/core/com/task/index.js +0 -110
  315. package/core/com/task/script.js +0 -37
  316. package/core/com/timer/com.js +0 -217
  317. package/core/com/timer/com.json +0 -4
  318. package/core/com/tpl/com.js +0 -19
  319. package/core/com/tpl/com.json +0 -4
  320. package/lib/actions.js +0 -50
  321. package/lib/base.js +0 -361
  322. package/lib/com.js +0 -29
  323. package/lib/ref.js +0 -121
  324. package/middleware/cors/index.js +0 -119
  325. package/middleware/cors/middleware.json +0 -20
  326. package/middleware/csrf/index.js +0 -202
  327. package/middleware/csrf/middleware.json +0 -24
  328. package/middleware/ip_firewall/index.js +0 -476
  329. package/middleware/ip_firewall/middleware.json +0 -109
  330. package/middleware/mqtt_base/index.js +0 -10
  331. package/middleware/mqtt_base/middleware.json +0 -11
  332. package/middleware/security_audit/index.js +0 -543
  333. package/middleware/security_audit/middleware.json +0 -48
  334. package/middleware/waf/index.js +0 -343
  335. package/middleware/waf/middleware.json +0 -10
  336. package/middleware/waf_ddos/index.js +0 -520
  337. package/middleware/waf_ddos/middleware.json +0 -38
  338. package/middleware/waf_xss/index.js +0 -269
  339. package/middleware/waf_xss/middleware.json +0 -18
  340. package/middleware/web_after/index.js +0 -33
  341. package/middleware/web_after/middleware.json +0 -10
  342. package/middleware/web_base/index.js +0 -90
  343. package/middleware/web_base/middleware.json +0 -10
  344. package/middleware/web_before/index.js +0 -27
  345. package/middleware/web_before/middleware.json +0 -10
  346. package/middleware/web_check/index.js +0 -28
  347. package/middleware/web_check/middleware.json +0 -10
  348. package/middleware/web_main/index.js +0 -28
  349. package/middleware/web_main/middleware.json +0 -10
  350. package/middleware/web_proxy/index.js +0 -37
  351. package/middleware/web_proxy/middleware.json +0 -10
  352. package/middleware/web_render/index.js +0 -87
  353. package/middleware/web_render/middleware.json +0 -10
  354. package/middleware/web_socket/index.js +0 -34
  355. package/middleware/web_socket/middleware.json +0 -10
  356. package/middleware/web_static/index.js +0 -115
  357. package/middleware/web_static/middleware.json +0 -10
  358. /package/{core/com → com}/api/README.md +0 -0
  359. /package/{core/com → com}/db/README.md +0 -0
  360. /package/{core/com → com}/mqtt/README.md +0 -0
  361. /package/{core/com → com}/nav/README.md +0 -0
  362. /package/{core/com → com}/nav/tpl/admin_pc/page_channel.vue +0 -0
  363. /package/{core/com → com}/nav/tpl/admin_pc/page_default.vue +0 -0
  364. /package/{core/com → com}/nav/tpl/admin_pc/page_lang.vue +0 -0
  365. /package/{core/com → com}/nav/tpl/admin_pc/page_nav.vue +0 -0
  366. /package/{core/com → com}/nav/tpl/admin_pc/page_table.vue +0 -0
  367. /package/{core/com → com}/nav/tpl/admin_pc/page_type.vue +0 -0
  368. /package/{core/com → com}/nav/tpl/dev_pc/page_channel.vue +0 -0
  369. /package/{core/com → com}/nav/tpl/dev_pc/page_config.vue +0 -0
  370. /package/{core/com → com}/nav/tpl/dev_pc/page_form.vue +0 -0
  371. /package/{core/com → com}/nav/tpl/dev_pc/page_nav.vue +0 -0
  372. /package/{core/com → com}/nav/tpl/dev_pc/page_table.vue +0 -0
  373. /package/{core/com → com}/nav/tpl/home_pc/page_channel.vue +0 -0
  374. /package/{core/com → com}/nav/tpl/home_phone/page_list.vue +0 -0
  375. /package/{core/com → com}/param/README.md +0 -0
  376. /package/{core/com/cmd → com/pendant}/README.md +0 -0
  377. /package/{core/com → com}/socket/README.md +0 -0
  378. /package/{core/com → com}/sql/README.md +0 -0
  379. /package/{core/com → com}/static/README.md +0 -0
  380. /package/{core/com → com}/task/README.md +0 -0
@@ -0,0 +1,899 @@
1
+ const {
2
+ Drive,
3
+ Manager
4
+ } = require('mm_machine');
5
+ const {
6
+ RoomAdmin
7
+ } = require('../room/index.js');
8
+ const {
9
+ Matcher
10
+ } = require('./matcher.js');
11
+
12
+ /**
13
+ * 游戏频道 - 平行世界管理器
14
+ * 负责管理频道的创建、销毁、玩家隔离和频道间通信
15
+ */
16
+ class Channel extends Drive {
17
+ static config = {
18
+ 'name': 'default',
19
+ 'title': '默认频道',
20
+ 'min_level': 0,
21
+ 'max_level': 1000,
22
+ 'max_players': 5000,
23
+ 'type': 'normal',
24
+ 'load_threshold': 0.8,
25
+ 'main': '',
26
+ 'match': {
27
+ 'wait_time': 120000,
28
+ 'lv_range_init': 5,
29
+ 'lv_range_max': 20,
30
+ 'lv_expand_int': 10000,
31
+ 'interval': 1000
32
+ }
33
+ };
34
+
35
+ /**
36
+ * 构造函数
37
+ * @param {object} config 配置参数
38
+ */
39
+ constructor(config) {
40
+ super({ ...Channel.config, ...config });
41
+
42
+ // 游戏世界集合
43
+ this.worlds = new Map();
44
+ }
45
+ }
46
+
47
+ /**
48
+ * 预置
49
+ */
50
+ Channel.prototype._preset = function () {
51
+ this.channel_id = 0;
52
+ this.status = 1;
53
+ this.stats = {
54
+ player: 0,
55
+ room: 0,
56
+ world: 0,
57
+ message: 0,
58
+ last_update: Date.now()
59
+ };
60
+
61
+ this._monitorTimer = null;
62
+
63
+ this.roomAdmin = null;
64
+ this.matcher = null;
65
+
66
+ // 主世界ID
67
+ this._main_world_id = '';
68
+ };
69
+
70
+ /**
71
+ * 获取模板目录
72
+ * @returns {string} 模板目录
73
+ */
74
+ Channel.prototype.getTplDir = function () {
75
+ return __dirname;
76
+ };
77
+
78
+ /**
79
+ * 初始化核心
80
+ * @param {object} zone 分区对象
81
+ * @param {object} eventer 事件管理器
82
+ * @param {object} logger 日志管理器
83
+ */
84
+ Channel.prototype._initCore = async function (zone, eventer, logger) {
85
+ if (!zone) {
86
+ throw new TypeError('分区对象不能为空');
87
+ }
88
+ else {
89
+ this.getZone = function () {
90
+ return zone;
91
+ };
92
+ }
93
+
94
+ if (logger) {
95
+ this.setLogger(logger);
96
+ }
97
+ if (eventer) {
98
+ this.getEventer = function () {
99
+ return eventer;
100
+ };
101
+ }
102
+
103
+ await this._initManager();
104
+ await this._loadSources();
105
+ await this._initSources();
106
+
107
+ await this._loadWorlds();
108
+
109
+ await this._initRoomAdmin();
110
+
111
+ await this._loadRooms();
112
+
113
+ await this._initMatcher();
114
+ };
115
+
116
+ /**
117
+ * 加载世界
118
+ * @returns {Promise<void>}
119
+ */
120
+ Channel.prototype._loadWorlds = async function () {
121
+ // 通过事件方式加载已创建的世界数据,避免直接操作数据库
122
+ var worlds = await this.emitWait('world_load', {
123
+ zone_name: this.getZone().config.name,
124
+ channel_id: this.channel_id
125
+ });
126
+ if (worlds && worlds.length > 0) {
127
+ // 遍历世界列表,创建世界对象
128
+ for (var i = 0; i < worlds.length; i++) {
129
+ var info = worlds[i];
130
+ await this.createWorld(info, info.world_id);
131
+ }
132
+ this.log('info', `加载世界成功,共 ${worlds.length} 个`);
133
+ }
134
+
135
+ // 加载所有游戏世界
136
+ var promises = [];
137
+ for (var o of this.worlds.values()) {
138
+ promises.push(o.do('load'));
139
+ }
140
+ await Promise.all(promises);
141
+ };
142
+
143
+ /**
144
+ * 初始化房间管理器
145
+ */
146
+ Channel.prototype._initRoomAdmin = async function () {
147
+ this.roomAdmin = new RoomAdmin();
148
+ await this.roomAdmin.do('init', this);
149
+ };
150
+
151
+ /**
152
+ * 初始化匹配器
153
+ */
154
+ Channel.prototype._initMatcher = async function () {
155
+ this.matcher = new Matcher(this.config.match, this);
156
+ await this.matcher.do('init', this);
157
+ };
158
+
159
+ /**
160
+ * 初始化管理器
161
+ */
162
+ Channel.prototype._initManager = async function () {
163
+ // var dir = this._getDir().dirname().dirname();
164
+ // var game = new Manager({
165
+ // name: 'game',
166
+ // title: '游戏',
167
+ // filename: 'game.json',
168
+ // tpl_dir: `../game/`.fullname(__dirname),
169
+ // base_dir: '',
170
+ // // base_dir: `../../common/${name}/`.fullname(__dirname),
171
+ // dir: `./game`.fullname(dir)
172
+ // }, this, this.game, Game);
173
+ // await game.do('init');
174
+ // this.manager.game = game;
175
+ };
176
+
177
+ /**
178
+ * 获取游戏管理器目录
179
+ * @returns {string} 游戏管理器目录
180
+ */
181
+ Channel.prototype._getDir = function () {
182
+ return this.getZone()._getDir();
183
+ };
184
+
185
+ /**
186
+ * 加载资源
187
+ */
188
+ Channel.prototype._loadSources = async function () {
189
+ await this.manager.game.runAll('load');
190
+ };
191
+
192
+ /**
193
+ * 设置主世界ID
194
+ * @param {string} world_id 主世界ID
195
+ */
196
+ Channel.prototype.setMainWorld = function (world_id) {
197
+ this._main_world_id = world_id;
198
+ };
199
+
200
+ /**
201
+ * 初始化资源
202
+ */
203
+ Channel.prototype._initSources = async function () {
204
+ await this.manager.game.runAll('init', this, this.getEventer(), this.getLogger());
205
+ };
206
+
207
+ /**
208
+ * 加载游戏房间
209
+ * @returns {Promise<void>}
210
+ */
211
+ Channel.prototype._loadRooms = async function () {
212
+ // 通过事件方式加载已创建的房间数据,避免直接操作数据库
213
+ var rooms = await this.emitWait('room_load', {
214
+ zone_name: this.getZone().config.name,
215
+ channel_id: this.channel_id
216
+ });
217
+ if (rooms && rooms.length > 0) {
218
+ // 遍历房间列表,创建房间对象
219
+ for (var i = 0; i < rooms.length; i++) {
220
+ var info = rooms[i];
221
+ var room = await this.roomAdmin.create(info, info.owner);
222
+ // 恢复房间原有ID
223
+ if (info.room_id) {
224
+ this.roomAdmin._rooms.delete(room.room_id);
225
+ room.room_id = info.room_id;
226
+ this.roomAdmin._rooms.set(room.room_id, room);
227
+ }
228
+ // 恢复房间状态
229
+ if (info.state) {
230
+ room.state = info.state;
231
+ }
232
+ }
233
+ this.log('info', `加载房间成功,共 ${rooms.length} 个`);
234
+ }
235
+
236
+ // 加载所有游戏房间
237
+ var promises = [];
238
+ for (var o of this.rooms.values()) {
239
+ promises.push(o.do('load'));
240
+ }
241
+ await Promise.all(promises);
242
+ };
243
+
244
+ /**
245
+ * 启动核心
246
+ */
247
+ Channel.prototype._startCore = async function () {
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;