tiaoom 0.0.1
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/LICENSE +21 -0
- package/README.md +58 -0
- package/package.json +59 -0
- package/src/client.cjs +2 -0
- package/src/client.cjs.map +1 -0
- package/src/client.d.cts +383 -0
- package/src/client.d.mts +383 -0
- package/src/client.iife.js +2 -0
- package/src/client.iife.js.map +1 -0
- package/src/client.mjs +2 -0
- package/src/client.mjs.map +1 -0
- package/src/index.cjs +499 -0
- package/src/index.cjs.map +1 -0
- package/src/index.d.cts +350 -0
- package/src/index.d.mts +350 -0
- package/src/index.mjs +464 -0
- package/src/index.mjs.map +1 -0
package/src/index.mjs
ADDED
|
@@ -0,0 +1,464 @@
|
|
|
1
|
+
import EventEmitter$1, { EventEmitter } from "events";
|
|
2
|
+
|
|
3
|
+
//#region lib/models/player.ts
|
|
4
|
+
let PlayerStatus = /* @__PURE__ */ function(PlayerStatus$1) {
|
|
5
|
+
PlayerStatus$1["ready"] = "ready";
|
|
6
|
+
PlayerStatus$1["unready"] = "unready";
|
|
7
|
+
PlayerStatus$1["online"] = "online";
|
|
8
|
+
PlayerStatus$1["playing"] = "playing";
|
|
9
|
+
return PlayerStatus$1;
|
|
10
|
+
}({});
|
|
11
|
+
var Player = class extends EventEmitter$1 {
|
|
12
|
+
on(event, listener) {
|
|
13
|
+
return super.on(event, listener);
|
|
14
|
+
}
|
|
15
|
+
emit(event, ...args) {
|
|
16
|
+
return super.emit(event, ...args);
|
|
17
|
+
}
|
|
18
|
+
constructor({ id = (/* @__PURE__ */ new Date()).getTime().toString(), name = "", attributes, sender }) {
|
|
19
|
+
super();
|
|
20
|
+
this.id = "";
|
|
21
|
+
this.name = "";
|
|
22
|
+
this.status = PlayerStatus.online;
|
|
23
|
+
this.id = id;
|
|
24
|
+
this.name = name;
|
|
25
|
+
this.attributes = attributes;
|
|
26
|
+
this.sender = sender;
|
|
27
|
+
this.on("status", (status) => {
|
|
28
|
+
this.status = status;
|
|
29
|
+
});
|
|
30
|
+
[
|
|
31
|
+
"command",
|
|
32
|
+
"message",
|
|
33
|
+
"join",
|
|
34
|
+
"leave",
|
|
35
|
+
"status"
|
|
36
|
+
].forEach((event) => {
|
|
37
|
+
this.on(event, (...data) => {
|
|
38
|
+
this.sender?.(event, ...data);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
toJSON() {
|
|
43
|
+
return {
|
|
44
|
+
id: this.id,
|
|
45
|
+
name: this.name,
|
|
46
|
+
attributes: this.attributes,
|
|
47
|
+
status: this.status
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
toString() {
|
|
51
|
+
return JSON.stringify(this.toJSON());
|
|
52
|
+
}
|
|
53
|
+
setSender(sender) {
|
|
54
|
+
this.sender = sender;
|
|
55
|
+
return this;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
//#endregion
|
|
60
|
+
//#region lib/models/room.ts
|
|
61
|
+
let PlayerRole = /* @__PURE__ */ function(PlayerRole$1) {
|
|
62
|
+
PlayerRole$1["player"] = "player";
|
|
63
|
+
PlayerRole$1["watcher"] = "watcher";
|
|
64
|
+
return PlayerRole$1;
|
|
65
|
+
}({});
|
|
66
|
+
let RoomStatus = /* @__PURE__ */ function(RoomStatus$1) {
|
|
67
|
+
RoomStatus$1["waiting"] = "waiting";
|
|
68
|
+
RoomStatus$1["ready"] = "ready";
|
|
69
|
+
RoomStatus$1["playing"] = "playing";
|
|
70
|
+
return RoomStatus$1;
|
|
71
|
+
}({});
|
|
72
|
+
var RoomPlayer = class extends Player {
|
|
73
|
+
constructor(player, role = PlayerRole.player) {
|
|
74
|
+
super(player);
|
|
75
|
+
this.isReady = false;
|
|
76
|
+
this.role = PlayerRole.player;
|
|
77
|
+
this.isCreator = false;
|
|
78
|
+
this.role = role;
|
|
79
|
+
if (player instanceof Player && player.sender) super.setSender(player.sender);
|
|
80
|
+
}
|
|
81
|
+
toJSON() {
|
|
82
|
+
return {
|
|
83
|
+
...super.toJSON(),
|
|
84
|
+
role: this.role,
|
|
85
|
+
isReady: this.isReady,
|
|
86
|
+
isCreator: this.isCreator
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
var Room = class extends EventEmitter$1 {
|
|
91
|
+
on(event, listener) {
|
|
92
|
+
return super.on(event, listener);
|
|
93
|
+
}
|
|
94
|
+
emit(event, ...args) {
|
|
95
|
+
return super.emit(event, ...args);
|
|
96
|
+
}
|
|
97
|
+
get validPlayers() {
|
|
98
|
+
return this.players.filter((player) => player.role === PlayerRole.player);
|
|
99
|
+
}
|
|
100
|
+
get watchers() {
|
|
101
|
+
return this.players.filter((player) => player.role === PlayerRole.watcher);
|
|
102
|
+
}
|
|
103
|
+
get isReady() {
|
|
104
|
+
return this.players.length >= this.minSize && this.players.every((target) => target.isReady || target.role === PlayerRole.watcher);
|
|
105
|
+
}
|
|
106
|
+
get status() {
|
|
107
|
+
if (!this.isReady) return RoomStatus.waiting;
|
|
108
|
+
if (this.players.findIndex((target) => target.status === PlayerStatus.playing) != -1) return RoomStatus.playing;
|
|
109
|
+
return RoomStatus.ready;
|
|
110
|
+
}
|
|
111
|
+
get isPlaying() {
|
|
112
|
+
return this.status === RoomStatus.playing;
|
|
113
|
+
}
|
|
114
|
+
get isFull() {
|
|
115
|
+
return this.validPlayers.length == this.size;
|
|
116
|
+
}
|
|
117
|
+
toJSON() {
|
|
118
|
+
return {
|
|
119
|
+
id: this.id,
|
|
120
|
+
name: this.name,
|
|
121
|
+
size: this.size || 10,
|
|
122
|
+
minSize: this.minSize,
|
|
123
|
+
status: this.status,
|
|
124
|
+
players: this.players.map((player) => player.toJSON()),
|
|
125
|
+
attrs: this.attrs
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
toString() {
|
|
129
|
+
return JSON.stringify(this.toJSON());
|
|
130
|
+
}
|
|
131
|
+
constructor({ id = (/* @__PURE__ */ new Date()).getTime().toString(), name = "", size = 10, minSize = 2, attrs }) {
|
|
132
|
+
super();
|
|
133
|
+
this.size = 10;
|
|
134
|
+
this.name = "";
|
|
135
|
+
this.minSize = 2;
|
|
136
|
+
this.players = [];
|
|
137
|
+
this.id = id;
|
|
138
|
+
this.name = name;
|
|
139
|
+
this.size = size;
|
|
140
|
+
this.minSize = minSize;
|
|
141
|
+
this.attrs = attrs;
|
|
142
|
+
[
|
|
143
|
+
"message",
|
|
144
|
+
"command",
|
|
145
|
+
"start",
|
|
146
|
+
"end",
|
|
147
|
+
"close",
|
|
148
|
+
"error",
|
|
149
|
+
"all-ready",
|
|
150
|
+
"player-unready",
|
|
151
|
+
"player-ready",
|
|
152
|
+
"join",
|
|
153
|
+
"leave"
|
|
154
|
+
].forEach((event) => {
|
|
155
|
+
this.on(event, (...data) => {
|
|
156
|
+
this.sender?.(event, ...data);
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
addPlayer(player, isCreator = false) {
|
|
161
|
+
if (this.players.some((p) => p.id == player.id)) return;
|
|
162
|
+
let roomPlayer = this.searchPlayer(player);
|
|
163
|
+
if (!roomPlayer) {
|
|
164
|
+
roomPlayer = new RoomPlayer(player, this.isFull || this.isPlaying ? PlayerRole.watcher : PlayerRole.player);
|
|
165
|
+
roomPlayer.isCreator = isCreator;
|
|
166
|
+
roomPlayer.roomId = this.id;
|
|
167
|
+
this.players.push(roomPlayer);
|
|
168
|
+
this.emit("join", {
|
|
169
|
+
roomId: this.id,
|
|
170
|
+
...roomPlayer
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
return roomPlayer;
|
|
174
|
+
}
|
|
175
|
+
kickPlayer(player) {
|
|
176
|
+
const playerId = typeof player === "string" ? player : player.id;
|
|
177
|
+
const index = this.players.findIndex((p) => p.id == playerId);
|
|
178
|
+
const roomPlayer = this.players[index];
|
|
179
|
+
if (index > -1) {
|
|
180
|
+
this.emit("leave", {
|
|
181
|
+
roomId: this.id,
|
|
182
|
+
...roomPlayer
|
|
183
|
+
});
|
|
184
|
+
this.players.splice(index, 1);
|
|
185
|
+
if (roomPlayer.isCreator && this.players.length > 0) {
|
|
186
|
+
this.players[0].isCreator = true;
|
|
187
|
+
this.emit("update", this);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return roomPlayer;
|
|
191
|
+
}
|
|
192
|
+
searchPlayer(player) {
|
|
193
|
+
const playerId = typeof player === "string" ? player : player.id;
|
|
194
|
+
return this.players.find((player$1) => player$1.id == playerId);
|
|
195
|
+
}
|
|
196
|
+
start() {
|
|
197
|
+
if (!this.isReady) throw new Error("room is not ready.");
|
|
198
|
+
if (this.status === RoomStatus.playing) throw new Error("room is already started.");
|
|
199
|
+
this.players.forEach((player) => {
|
|
200
|
+
if (player.role != PlayerRole.player) return;
|
|
201
|
+
player.emit("status", PlayerStatus.playing);
|
|
202
|
+
});
|
|
203
|
+
this.emit("update", this);
|
|
204
|
+
return this.emit("start", this);
|
|
205
|
+
}
|
|
206
|
+
end() {
|
|
207
|
+
this.players.forEach((player) => {
|
|
208
|
+
if (player.role != PlayerRole.player) return;
|
|
209
|
+
player.emit("status", PlayerStatus.unready);
|
|
210
|
+
});
|
|
211
|
+
this.emit("update", this);
|
|
212
|
+
return this.emit("end", this);
|
|
213
|
+
}
|
|
214
|
+
setSender(sender) {
|
|
215
|
+
this.sender = sender;
|
|
216
|
+
return this;
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
//#endregion
|
|
221
|
+
//#region lib/models/message.ts
|
|
222
|
+
let MessageTypes = /* @__PURE__ */ function(MessageTypes$1) {
|
|
223
|
+
MessageTypes$1["RoomList"] = "room.list";
|
|
224
|
+
MessageTypes$1["RoomCreate"] = "room.create";
|
|
225
|
+
MessageTypes$1["RoomReady"] = "room.ready";
|
|
226
|
+
MessageTypes$1["RoomStart"] = "room.start";
|
|
227
|
+
MessageTypes$1["RoomEnd"] = "room.end";
|
|
228
|
+
MessageTypes$1["RoomClose"] = "room.close";
|
|
229
|
+
MessageTypes$1["RoomAllReady"] = "room.allready";
|
|
230
|
+
MessageTypes$1["RoomCommand"] = "room.command";
|
|
231
|
+
MessageTypes$1["RoomMessage"] = "room.message";
|
|
232
|
+
MessageTypes$1["PlayerOffline"] = "player.offline";
|
|
233
|
+
MessageTypes$1["PlayerList"] = "player.list";
|
|
234
|
+
MessageTypes$1["PlayerLogin"] = "player.login";
|
|
235
|
+
MessageTypes$1["PlayerLogout"] = "player.logout";
|
|
236
|
+
MessageTypes$1["PlayerJoin"] = "player.join";
|
|
237
|
+
MessageTypes$1["PlayerLeave"] = "player.leave";
|
|
238
|
+
MessageTypes$1["PlayerReady"] = "player.ready";
|
|
239
|
+
MessageTypes$1["PlayerUnready"] = "player.unready";
|
|
240
|
+
MessageTypes$1["PlayerCommand"] = "player.command";
|
|
241
|
+
return MessageTypes$1;
|
|
242
|
+
}({});
|
|
243
|
+
|
|
244
|
+
//#endregion
|
|
245
|
+
//#region lib/index.ts
|
|
246
|
+
var Tiaoom = class extends EventEmitter {
|
|
247
|
+
constructor({ socket }) {
|
|
248
|
+
super();
|
|
249
|
+
this.rooms = [];
|
|
250
|
+
this.players = [];
|
|
251
|
+
this.messageInstance = socket;
|
|
252
|
+
}
|
|
253
|
+
on(event, listener) {
|
|
254
|
+
super.on(event, listener);
|
|
255
|
+
return this;
|
|
256
|
+
}
|
|
257
|
+
emit(event, ...args) {
|
|
258
|
+
return super.emit(event, ...args);
|
|
259
|
+
}
|
|
260
|
+
run() {
|
|
261
|
+
this.messageInstance?.on("message", (message, cb) => {
|
|
262
|
+
try {
|
|
263
|
+
switch (message.type) {
|
|
264
|
+
case "room.list": return cb?.(null, this.rooms);
|
|
265
|
+
case "player.list": return cb?.(null, this.players);
|
|
266
|
+
case "room.create": return this.createRoom(message.sender, message.data);
|
|
267
|
+
case "player.join": return this.joinPlayer(message.sender, message.data);
|
|
268
|
+
case "player.leave": return this.leavePlayer(message.sender, message.data);
|
|
269
|
+
case "room.get": return cb?.(null, this.searchRoom(message.data));
|
|
270
|
+
case "room.start": return this.startRoom(message.sender, message.data);
|
|
271
|
+
case "room.close": return this.closeRoom(message.sender, message.data);
|
|
272
|
+
case "player.login": return this.loginPlayer(message.data);
|
|
273
|
+
case "player.logout": return this.removePlayer(message.data);
|
|
274
|
+
case "player.ready": return this.readyPlayer(message.sender, message.data);
|
|
275
|
+
case "player.unready": return this.unReadyPlayer(message.sender, message.data);
|
|
276
|
+
case "room.player-command": return this.searchRoom(message.data)?.emit("player-command", {
|
|
277
|
+
...message.data,
|
|
278
|
+
sender: message.sender
|
|
279
|
+
});
|
|
280
|
+
case "room.message": return this.searchRoom(message.data)?.emit("message", message.data);
|
|
281
|
+
case "global.command": return this.emit("command", {
|
|
282
|
+
...message.data,
|
|
283
|
+
sender: message.sender
|
|
284
|
+
});
|
|
285
|
+
default: throw new Error("unknown message type.");
|
|
286
|
+
}
|
|
287
|
+
} catch (error) {
|
|
288
|
+
cb?.(error);
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
this.on("player", (player, online) => {
|
|
292
|
+
this.messageInstance?.send({
|
|
293
|
+
type: online ? "player.login" : "player.logout",
|
|
294
|
+
data: player
|
|
295
|
+
});
|
|
296
|
+
});
|
|
297
|
+
this.on("players", (players) => {
|
|
298
|
+
this.messageInstance?.send({
|
|
299
|
+
type: "player.list",
|
|
300
|
+
data: players
|
|
301
|
+
});
|
|
302
|
+
});
|
|
303
|
+
this.on("room", (room) => {
|
|
304
|
+
this.messageInstance?.send({
|
|
305
|
+
type: "room.create",
|
|
306
|
+
data: room
|
|
307
|
+
});
|
|
308
|
+
});
|
|
309
|
+
this.on("room-player", (room) => {
|
|
310
|
+
this.messageInstance?.send({
|
|
311
|
+
type: "room.update",
|
|
312
|
+
data: room
|
|
313
|
+
});
|
|
314
|
+
});
|
|
315
|
+
this.on("rooms", (rooms) => {
|
|
316
|
+
this.messageInstance?.send({
|
|
317
|
+
type: "room.list",
|
|
318
|
+
data: rooms
|
|
319
|
+
});
|
|
320
|
+
});
|
|
321
|
+
this.on("command", (data) => {
|
|
322
|
+
this.messageInstance?.send({
|
|
323
|
+
type: "global.command",
|
|
324
|
+
data
|
|
325
|
+
});
|
|
326
|
+
});
|
|
327
|
+
return this;
|
|
328
|
+
}
|
|
329
|
+
searchPlayer(player) {
|
|
330
|
+
const playerId = typeof player === "string" ? player : player.id;
|
|
331
|
+
return this.players.find((target) => target.id === playerId);
|
|
332
|
+
}
|
|
333
|
+
searchRoom(room) {
|
|
334
|
+
const roomId = typeof room === "string" ? room : room.id;
|
|
335
|
+
return this.rooms.find((target) => target.id === roomId);
|
|
336
|
+
}
|
|
337
|
+
createRoom(sender, options) {
|
|
338
|
+
if (!options.name) throw new Error("missing room id or name.");
|
|
339
|
+
if (this.searchRoom(options)) throw new Error("room already exists.");
|
|
340
|
+
if (this.rooms.some((r) => r.players.some((p) => p.id === sender.id))) throw new Error("you are already in a room.");
|
|
341
|
+
const room = new Room(options);
|
|
342
|
+
room.setSender((type, message) => {
|
|
343
|
+
this.messageInstance?.send({
|
|
344
|
+
type: `room.${type}`,
|
|
345
|
+
data: message,
|
|
346
|
+
sender: room
|
|
347
|
+
});
|
|
348
|
+
});
|
|
349
|
+
this.emit("room", room);
|
|
350
|
+
this.rooms.push(room);
|
|
351
|
+
this.joinPlayer(sender, {
|
|
352
|
+
roomId: room.id,
|
|
353
|
+
...sender
|
|
354
|
+
}, true);
|
|
355
|
+
return room;
|
|
356
|
+
}
|
|
357
|
+
startRoom(sender, room) {
|
|
358
|
+
const roomInstance = this.searchRoom(room);
|
|
359
|
+
if (!roomInstance) throw new Error("room not found.");
|
|
360
|
+
roomInstance.start();
|
|
361
|
+
return this.emit("room-player", roomInstance);
|
|
362
|
+
}
|
|
363
|
+
closeRoom(sender, room) {
|
|
364
|
+
const roomIndex = this.rooms.findIndex((r) => r.id === room.id);
|
|
365
|
+
const roomInstance = this.rooms[roomIndex];
|
|
366
|
+
if (!roomInstance) throw new Error("room not found.");
|
|
367
|
+
if (roomInstance.players.length && !roomInstance.players.some((p) => p.id === sender.id && p.isCreator)) throw new Error("only room creator can close the room.");
|
|
368
|
+
room = this.rooms.splice(roomIndex, 1)[0];
|
|
369
|
+
this.emit("rooms", this.rooms);
|
|
370
|
+
roomInstance.emit("close");
|
|
371
|
+
return room;
|
|
372
|
+
}
|
|
373
|
+
loginPlayer(player, cb) {
|
|
374
|
+
let playerInstance = this.searchPlayer(player);
|
|
375
|
+
if (!playerInstance) {
|
|
376
|
+
playerInstance = new Player(player);
|
|
377
|
+
playerInstance.setSender((type, message) => {
|
|
378
|
+
this.messageInstance?.send({
|
|
379
|
+
type: `player.${type}`,
|
|
380
|
+
data: message,
|
|
381
|
+
sender: playerInstance
|
|
382
|
+
});
|
|
383
|
+
});
|
|
384
|
+
this.players.push(playerInstance);
|
|
385
|
+
this.emit("player", playerInstance, true);
|
|
386
|
+
}
|
|
387
|
+
playerInstance.emit("status", PlayerStatus.online);
|
|
388
|
+
cb?.({ player: playerInstance });
|
|
389
|
+
return playerInstance;
|
|
390
|
+
}
|
|
391
|
+
joinPlayer(sender, player, isCreator = false) {
|
|
392
|
+
let playerInstance = this.searchPlayer(sender);
|
|
393
|
+
if (!playerInstance) playerInstance = this.loginPlayer(sender);
|
|
394
|
+
if (!player.roomId) throw new Error("missing room id.");
|
|
395
|
+
const room = this.rooms.find((room$1) => room$1.id === player.roomId);
|
|
396
|
+
if (!room) throw new Error("room not found.");
|
|
397
|
+
const roomPlayer = room.addPlayer(playerInstance, isCreator);
|
|
398
|
+
if (!roomPlayer) throw new Error("room is full.");
|
|
399
|
+
this.emit("room-player", room);
|
|
400
|
+
return roomPlayer;
|
|
401
|
+
}
|
|
402
|
+
leavePlayer(sender, player) {
|
|
403
|
+
if (!player.roomId) throw new Error("missing room id.");
|
|
404
|
+
const room = this.rooms.find((room$1) => room$1.id === player.roomId);
|
|
405
|
+
if (!room) throw new Error("room not found.");
|
|
406
|
+
const playerInstance = room.searchPlayer(sender);
|
|
407
|
+
if (!playerInstance) throw new Error("player not in room.");
|
|
408
|
+
const roomPlayer = room.kickPlayer(playerInstance);
|
|
409
|
+
if (roomPlayer) this.emit("room-player", room);
|
|
410
|
+
return roomPlayer;
|
|
411
|
+
}
|
|
412
|
+
readyPlayer(sender, player) {
|
|
413
|
+
const playerInstance = this.searchPlayer(sender);
|
|
414
|
+
if (!playerInstance) throw new Error("player not found.");
|
|
415
|
+
if (!player.roomId) throw new Error("missing room id.");
|
|
416
|
+
const room = this.rooms.find((room$1) => room$1.id === player.roomId);
|
|
417
|
+
if (!room) throw new Error("room not found.");
|
|
418
|
+
const roomPlayer = room.searchPlayer(playerInstance);
|
|
419
|
+
if (!roomPlayer) throw new Error("player not in room.");
|
|
420
|
+
roomPlayer.isReady = true;
|
|
421
|
+
if (room.isReady) room.emit("all-ready", room.players);
|
|
422
|
+
playerInstance.emit("status", PlayerStatus.ready);
|
|
423
|
+
room.emit("player-ready", {
|
|
424
|
+
...player,
|
|
425
|
+
...roomPlayer
|
|
426
|
+
});
|
|
427
|
+
return this;
|
|
428
|
+
}
|
|
429
|
+
unReadyPlayer(sender, player) {
|
|
430
|
+
const playerInstance = this.searchPlayer(sender);
|
|
431
|
+
if (!playerInstance) throw new Error("player not found.");
|
|
432
|
+
if (!player.roomId) throw new Error("missing room id.");
|
|
433
|
+
const room = this.rooms.find((room$1) => room$1.id === player.roomId);
|
|
434
|
+
if (!room) throw new Error("room not found.");
|
|
435
|
+
const roomPlayer = room.searchPlayer(playerInstance);
|
|
436
|
+
if (!roomPlayer) throw new Error("player not in room.");
|
|
437
|
+
roomPlayer.isReady = false;
|
|
438
|
+
playerInstance.emit("status", PlayerStatus.unready);
|
|
439
|
+
room.emit("player-unready", roomPlayer);
|
|
440
|
+
return this;
|
|
441
|
+
}
|
|
442
|
+
removePlayer(sender) {
|
|
443
|
+
const playerIndex = this.players.findIndex((p) => p.id === sender.id);
|
|
444
|
+
const player = this.players[playerIndex];
|
|
445
|
+
if (playerIndex > -1) {
|
|
446
|
+
this.players.splice(playerIndex, 1)[0];
|
|
447
|
+
this.emit("player", player, false);
|
|
448
|
+
if (this.rooms.some((r) => r.searchPlayer(player))) setTimeout(() => {
|
|
449
|
+
if (this.players.some((p) => p.id === sender.id)) return;
|
|
450
|
+
this.rooms.filter((r) => r.searchPlayer(player)).forEach((r) => {
|
|
451
|
+
this.leavePlayer(sender, {
|
|
452
|
+
...sender,
|
|
453
|
+
roomId: r.id
|
|
454
|
+
});
|
|
455
|
+
});
|
|
456
|
+
}, 300 * 1e3);
|
|
457
|
+
}
|
|
458
|
+
return player;
|
|
459
|
+
}
|
|
460
|
+
};
|
|
461
|
+
|
|
462
|
+
//#endregion
|
|
463
|
+
export { MessageTypes, Player, PlayerRole, PlayerStatus, Room, RoomPlayer, RoomStatus, Tiaoom };
|
|
464
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["EventEmitter","EventEmitter","player","room"],"sources":["../lib/models/player.ts","../lib/models/room.ts","../lib/models/message.ts","../lib/index.ts"],"sourcesContent":["import { PlayerEvents } from \"@lib/events/player\";\nimport EventEmitter from \"events\";\n\nexport interface PlayerOptions {\n id: string;\n name: string;\n attributes?: any;\n sender?: (type: string, ...message: any) => void;\n}\n\nexport enum PlayerStatus {\n ready = 'ready',\n unready = 'unready',\n online = 'online',\n playing = 'playing',\n}\n\nexport interface IPlayer extends PlayerOptions {\n status: PlayerStatus;\n}\n\nexport class Player extends EventEmitter implements IPlayer {\n on<K extends keyof PlayerEvents>(event: K, listener: PlayerEvents[K]): this {\n return super.on(event, listener);\n }\n\n emit<K extends keyof PlayerEvents>(event: K, ...args: Parameters<PlayerEvents[K]>): boolean {\n return super.emit(event, ...args);\n }\n \n id: string = \"\";\n name: string = \"\";\n attributes?: any;\n status: PlayerStatus = PlayerStatus.online;\n sender?: (type: string, ...message: any) => void;\n\n constructor({ id = new Date().getTime().toString(), name = '', attributes, sender }: PlayerOptions) {\n super();\n this.id = id;\n this.name = name;\n this.attributes = attributes;\n this.sender = sender;\n\n this.on('status', (status: PlayerStatus) => {\n this.status = status;\n });\n \n const events: Array<keyof PlayerEvents> = ['command', 'message', 'join', 'leave', 'status'];\n events.forEach((event) => {\n this.on(event, (...data: any) => {\n this.sender?.(event, ...data);\n });\n }); \n }\n\n toJSON() {\n return {\n id: this.id,\n name: this.name,\n attributes: this.attributes,\n status: this.status,\n };\n }\n\n toString() {\n return JSON.stringify(this.toJSON());\n }\n\n setSender(sender: (type: string, ...message: any) => void) {\n this.sender = sender;\n return this;\n }\n}","import { IPlayer, Player, PlayerOptions, PlayerStatus } from \"./player\";\nimport EventEmitter from \"events\";\nimport { RoomEvents } from \"@lib/events\";\n\nexport interface IRoomOptions {\n /**\n * 房间号\n */\n id?: string, \n /**\n * 房间名称\n */\n name?: string,\n /**\n * 房间容量\n */\n size?: number, \n /**\n * 最小容量\n */\n minSize?: number,\n /**\n * 其他属性\n */\n attrs?: Record<string, any>,\n}\n\nexport enum PlayerRole {\n player = 'player',\n watcher = 'watcher',\n}\n\nexport enum RoomStatus {\n waiting = 'waiting',\n ready = 'ready',\n playing = 'playing',\n}\n\nexport interface IRoom extends IRoomOptions {\n players: RoomPlayer[];\n}\n\nexport interface IRoomPlayerOptions extends PlayerOptions {\n roomId?: string;\n}\nexport interface IRoomPlayer extends IRoomPlayerOptions, IPlayer {\n isReady: boolean;\n role: PlayerRole;\n isCreator: boolean;\n}\n\nexport class RoomPlayer extends Player implements IRoomPlayer {\n isReady: boolean = false;\n role: PlayerRole = PlayerRole.player;\n isCreator: boolean = false;\n roomId?: string;\n\n constructor(player: IPlayer | Player, role: PlayerRole = PlayerRole.player) {\n super(player);\n this.role = role;\n if (player instanceof Player && player.sender) super.setSender(player.sender);\n }\n\n toJSON() {\n return {\n ...super.toJSON(),\n role: this.role,\n isReady: this.isReady,\n isCreator: this.isCreator,\n };\n }\n}\n\nexport class Room extends EventEmitter implements IRoom {\n on<K extends keyof RoomEvents>(event: K, listener: RoomEvents[K]): this {\n return super.on(event, listener);\n }\n\n emit<K extends keyof RoomEvents>(event: K, ...args: Parameters<RoomEvents[K]>): boolean {\n return super.emit(event, ...args);\n }\n\n id: string; // room id\n size: number = 10; // room size\n name: string = ''; // room name\n minSize: number = 2; // room min size\n attrs?: Record<string, any>; // other attributes\n players: RoomPlayer[] = []; // player list\n\n get validPlayers() {\n return this.players.filter((player) => player.role === PlayerRole.player);\n }\n\n get watchers() {\n return this.players.filter((player) => player.role === PlayerRole.watcher);\n }\n\n private sender?: (type: string, ...message: any) => void;\n\n get isReady(): boolean {\n return this.players.length >= this.minSize\n && this.players.every((target) => target.isReady || target.role === PlayerRole.watcher); // is all player ready\n }\n\n get status(): RoomStatus {\n if (!this.isReady) return RoomStatus.waiting;\n if (this.players.findIndex((target) => target.status === PlayerStatus.playing) != -1) return RoomStatus.playing;\n return RoomStatus.ready;\n }\n\n get isPlaying(): boolean {\n return this.status === RoomStatus.playing;\n }\n\n // is room full\n get isFull(): boolean {\n return this.validPlayers.length == this.size;\n }\n\n toJSON() {\n return {\n id: this.id,\n name: this.name,\n size: this.size || 10,\n minSize: this.minSize,\n status: this.status,\n players: this.players.map((player) => player.toJSON()),\n attrs: this.attrs,\n }\n }\n\n toString() {\n return JSON.stringify(this.toJSON());\n }\n\n constructor({\n id = new Date().getTime().toString(), name = '', size = 10, minSize = 2, attrs\n }: IRoomOptions) {\n super();\n this.id = id;\n this.name = name;\n this.size = size;\n this.minSize = minSize;\n this.attrs = attrs;\n \n const events: Array<keyof RoomEvents> = ['message', 'command', 'start', 'end', 'close', 'error', 'all-ready', 'player-unready', 'player-ready', 'join', 'leave'];\n events.forEach((event) => {\n this.on(event, (...data: any) => {\n this.sender?.(event, ...data);\n });\n });\n }\n\n addPlayer(player: Player, isCreator: boolean = false) {\n if (this.players.some((p) => p.id == player.id)) return;\n let roomPlayer = this.searchPlayer(player);\n if (!roomPlayer) {\n roomPlayer = new RoomPlayer(player, this.isFull || this.isPlaying ? PlayerRole.watcher : PlayerRole.player);\n roomPlayer.isCreator = isCreator;\n roomPlayer.roomId = this.id;\n this.players.push(roomPlayer);\n this.emit(\"join\", { roomId: this.id, ...roomPlayer });\n }\n return roomPlayer;\n }\n\n kickPlayer(playerId: string): RoomPlayer;\n kickPlayer(player: IPlayer): RoomPlayer;\n\n kickPlayer(player: IPlayer | string) {\n const playerId = typeof player === \"string\" ? player : player.id;\n const index = this.players.findIndex((p) => p.id == playerId);\n const roomPlayer = this.players[index];\n if (index > -1) {\n this.emit(\"leave\", { roomId: this.id, ...roomPlayer});\n this.players.splice(index, 1);\n if (roomPlayer.isCreator && this.players.length > 0) {\n this.players[0].isCreator = true;\n this.emit(\"update\", this);\n }\n }\n return roomPlayer;\n }\n\n searchPlayer(playerId: string): RoomPlayer | undefined;\n searchPlayer(playerId: IPlayer): RoomPlayer | undefined;\n\n searchPlayer(player: string | IPlayer) {\n const playerId = typeof player === \"string\" ? player : player.id;\n return this.players.find((player) => player.id == playerId);\n }\n\n start() {\n if (!this.isReady) {\n throw new Error('room is not ready.');\n }\n if (this.status === RoomStatus.playing) {\n throw new Error('room is already started.');\n }\n this.players.forEach((player) => {\n if (player.role != PlayerRole.player) return;\n player.emit('status', PlayerStatus.playing);\n });\n this.emit(\"update\", this);\n return this.emit(\"start\", this);\n }\n\n end() {\n this.players.forEach((player) => {\n if (player.role != PlayerRole.player) return;\n player.emit('status', PlayerStatus.unready);\n });\n this.emit(\"update\", this);\n return this.emit(\"end\", this);\n }\n\n setSender(sender: (type: string, ...message: any) => void) {\n this.sender = sender;\n return this;\n }\n}\n","import EventEmitter from \"events\";\nimport { IPlayer, PlayerOptions } from \"./player\";\nimport { IRoom, IRoomPlayer, IRoomOptions } from \"./room\";\nimport { MessageEvents } from \"@lib/events/message\";\n\nexport enum MessageTypes {\n RoomList = \"room.list\",\n RoomCreate = \"room.create\",\n RoomReady = \"room.ready\",\n RoomStart = \"room.start\",\n RoomEnd = \"room.end\",\n RoomClose = \"room.close\",\n RoomAllReady = \"room.allready\",\n RoomCommand = \"room.command\",\n RoomMessage = \"room.message\",\n PlayerOffline = \"player.offline\",\n PlayerList = \"player.list\",\n PlayerLogin = \"player.login\",\n PlayerLogout = \"player.logout\",\n PlayerJoin = \"player.join\",\n PlayerLeave = \"player.leave\",\n PlayerReady = \"player.ready\",\n PlayerUnready = \"player.unready\",\n PlayerCommand = \"player.command\",\n}\n\nexport interface MessagePackage {\n type: MessageTypes | string;\n data?: PlayerOptions | IRoomOptions | IPlayer | IRoom | IRoomPlayer | any;\n sender?: IPlayer | IRoom | IRoomPlayer;\n}\n\nexport interface Message extends EventEmitter {\n on<K extends keyof MessageEvents>(event: K, listener: MessageEvents[K]): this;\n emit<K extends keyof MessageEvents>(event: K, ...args: Parameters<MessageEvents[K]>): boolean;\n close(): void;\n send(message: MessagePackage): void;\n}\n","import { EventEmitter } from \"events\";\nimport { TiaoomEvents } from \"./events\";\nimport { Message } from \"./models/message\";\nimport { IRoom, IRoomPlayer, Room, IRoomOptions, IRoomPlayerOptions } from \"./models/room\";\nimport { IPlayer, Player, PlayerOptions, PlayerStatus } from \"./models/player\";\n\nexport interface ITiaoomOptions {\n socket: Message;\n}\n\nexport class Tiaoom extends EventEmitter {\n rooms: Room[] = []; // room list\n players: Player[] = []; // player list\n messageInstance?: Message;\n\n constructor({ socket }: ITiaoomOptions) {\n super();\n this.messageInstance = socket;\n }\n\n on<K extends keyof TiaoomEvents>(event: K, listener: TiaoomEvents[K]): this {\n super.on(event, listener);\n return this\n }\n\n emit<K extends keyof TiaoomEvents>(event: K, ...args: Parameters<TiaoomEvents[K]>): boolean {\n return super.emit(event, ...args);\n }\n\n run() {\n this.messageInstance?.on(\"message\", (message: any, cb?: (err: Error | null, data?: any) => any) => {\n try {\n switch (message.type) {\n case \"room.list\":\n return cb?.(null, this.rooms);\n case \"player.list\":\n return cb?.(null, this.players);\n case \"room.create\":\n return this.createRoom(message.sender, message.data);\n case \"player.join\":\n return this.joinPlayer(message.sender, message.data);\n case \"player.leave\":\n return this.leavePlayer(message.sender, message.data);\n case \"room.get\":\n return cb?.(null, this.searchRoom(message.data));\n case \"room.start\":\n return this.startRoom(message.sender, message.data);\n case \"room.close\":\n return this.closeRoom(message.sender, message.data);\n case \"player.login\":\n return this.loginPlayer(message.data);\n case \"player.logout\":\n return this.removePlayer(message.data);\n case \"player.ready\":\n return this.readyPlayer(message.sender, message.data);\n case \"player.unready\":\n return this.unReadyPlayer(message.sender, message.data);\n case \"room.player-command\":\n return this.searchRoom(message.data)?.emit(\"player-command\", { ...message.data , sender: message.sender });\n case \"room.message\":\n return this.searchRoom(message.data)?.emit(\"message\", message.data);\n case \"global.command\":\n return this.emit(\"command\", { ...message.data , sender: message.sender });\n default:\n throw new Error('unknown message type.');\n }\n } catch (error) {\n cb?.(error as Error);\n }\n });\n\n this.on('player', (player, online) => {\n this.messageInstance?.send({ type: online ? 'player.login' : 'player.logout', data: player });\n });\n\n this.on('players', (players) => {\n this.messageInstance?.send({ type: 'player.list', data: players });\n });\n\n this.on('room', (room) => {\n this.messageInstance?.send({ type: 'room.create', data: room });\n });\n\n this.on('room-player', (room) => {\n this.messageInstance?.send({ type: 'room.update', data: room });\n });\n\n this.on('rooms', (rooms) => {\n this.messageInstance?.send({ type: 'room.list', data: rooms });\n });\n\n this.on('command', (data) => {\n this.messageInstance?.send({ type: 'global.command', data });\n });\n\n return this;\n }\n\n searchPlayer(player: string): Player | undefined;\n searchPlayer(player: PlayerOptions | IRoomPlayerOptions): Player | undefined;\n\n searchPlayer(player: PlayerOptions | IRoomPlayerOptions | string) {\n const playerId = typeof player === \"string\" ? player : player.id;\n return this.players.find((target) => target.id === playerId);\n }\n\n searchRoom(room: string): Room | undefined;\n searchRoom(room: Partial<IRoomOptions>): Room | undefined;\n\n searchRoom(room: Partial<IRoomOptions> | string) {\n const roomId = typeof room === \"string\" ? room : room.id;\n return this.rooms.find((target) => target.id === roomId);\n }\n\n createRoom(sender: IPlayer, options: IRoomOptions) {\n if (!options.name) {\n throw new Error('missing room id or name.');\n }\n const roomInstance = this.searchRoom(options);\n if (roomInstance) {\n throw new Error('room already exists.');\n }\n\n if (this.rooms.some(r => r.players.some(p => p.id === sender.id))) {\n throw new Error('you are already in a room.');\n }\n\n const room = new Room(options);\n room.setSender((type, message) => {\n this.messageInstance?.send({ type: `room.${type}`, data: message, sender: room });\n });\n \n this.emit(\"room\", room);\n this.rooms.push(room);\n\n this.joinPlayer(sender, { roomId: room.id, ...sender }, true);\n return room;\n }\n\n startRoom(sender: IPlayer, room: IRoom) {\n const roomInstance = this.searchRoom(room);\n if (!roomInstance) {\n throw new Error('room not found.');\n }\n roomInstance.start();\n\n return this.emit(\"room-player\", roomInstance);\n }\n\n closeRoom(sender: IPlayer, room: IRoom) {\n const roomIndex = this.rooms.findIndex((r) => r.id === room.id);\n const roomInstance = this.rooms[roomIndex];\n if (!roomInstance) {\n throw new Error('room not found.');\n }\n\n if (roomInstance.players.length && !roomInstance.players.some(p => p.id === sender.id && p.isCreator)) {\n throw new Error('only room creator can close the room.');\n }\n\n room = this.rooms.splice(roomIndex, 1)[0];\n\n this.emit(\"rooms\", this.rooms);\n roomInstance.emit('close');\n return room;\n }\n\n loginPlayer (player: PlayerOptions, cb?: (data: { player: Player }) => void): Player {\n let playerInstance = this.searchPlayer(player);\n if (!playerInstance) {\n playerInstance = new Player(player);\n playerInstance.setSender((type, message) => {\n this.messageInstance?.send({ type: `player.${type}`, data: message, sender: playerInstance });\n });\n this.players.push(playerInstance);\n this.emit(\"player\", playerInstance, true);\n }\n \n playerInstance.emit(\"status\", PlayerStatus.online);\n cb?.({ player: playerInstance });\n return playerInstance;\n }\n\n joinPlayer(sender: IPlayer, player: IRoomPlayerOptions, isCreator: boolean = false) {\n let playerInstance = this.searchPlayer(sender);\n if (!playerInstance) {\n playerInstance = this.loginPlayer(sender);\n }\n\n if (!player.roomId) {\n throw new Error('missing room id.');\n }\n\n const room = this.rooms.find((room) => room.id === player.roomId);\n if (!room) {\n throw new Error('room not found.');\n }\n\n const roomPlayer = room.addPlayer(playerInstance, isCreator);\n if (!roomPlayer) {\n throw new Error('room is full.');\n }\n\n this.emit(\"room-player\", room);\n\n return roomPlayer;\n }\n\n leavePlayer(sender: IPlayer, player: IRoomPlayerOptions) {\n if (!player.roomId) {\n throw new Error('missing room id.');\n }\n\n const room = this.rooms.find((room) => room.id === player.roomId);\n if (!room) {\n throw new Error('room not found.');\n }\n\n const playerInstance = room.searchPlayer(sender);\n if (!playerInstance) {\n throw new Error('player not in room.');\n }\n\n const roomPlayer = room.kickPlayer(playerInstance);\n\n if (roomPlayer) this.emit(\"room-player\", room);\n\n return roomPlayer;\n }\n\n readyPlayer(sender: IPlayer, player: IRoomPlayer) {\n const playerInstance = this.searchPlayer(sender);\n if (!playerInstance) {\n throw new Error('player not found.');\n }\n\n if (!player.roomId) {\n throw new Error('missing room id.');\n }\n\n const room = this.rooms.find((room) => room.id === player.roomId);\n if (!room) {\n throw new Error('room not found.');\n }\n\n const roomPlayer = room.searchPlayer(playerInstance);\n \n if (!roomPlayer) {\n throw new Error('player not in room.');\n }\n\n roomPlayer.isReady = true;\n\n if (room.isReady) {\n room.emit(\"all-ready\", room.players);\n }\n\n playerInstance.emit(\"status\", PlayerStatus.ready);\n\n room.emit(\"player-ready\", { ...player, ...roomPlayer });\n\n return this;\n }\n \n unReadyPlayer(sender: IPlayer, player: IRoomPlayer) {\n const playerInstance = this.searchPlayer(sender);\n if (!playerInstance) {\n throw new Error('player not found.');\n }\n\n if (!player.roomId) {\n throw new Error('missing room id.');\n }\n\n const room = this.rooms.find((room) => room.id === player.roomId);\n if (!room) {\n throw new Error('room not found.');\n }\n\n const roomPlayer = room.searchPlayer(playerInstance);\n \n if (!roomPlayer) {\n throw new Error('player not in room.');\n }\n\n roomPlayer.isReady = false;\n playerInstance.emit(\"status\", PlayerStatus.unready);\n room.emit(\"player-unready\", roomPlayer);\n\n return this;\n }\n\n removePlayer(sender: IPlayer) {\n const playerIndex = this.players.findIndex((p) => p.id === sender.id);\n const player = this.players[playerIndex];\n if (playerIndex > -1) {\n this.players.splice(playerIndex, 1)[0];\n this.emit(\"player\", player, false);\n if (this.rooms.some(r => r.searchPlayer(player))) {\n setTimeout(() => {\n if (this.players.some(p => p.id === sender.id)) return; // player is online\n this.rooms.filter(r => r.searchPlayer(player)).forEach(r => {\n this.leavePlayer(sender, { ...sender, roomId: r.id });\n });\n }, 5 * 60 * 1000); // 5 minutes later\n }\n }\n return player;\n }\n}\n\nexport * from \"./models/message\";\nexport * from \"./models/room\";\nexport * from \"./models/player\";\nexport * from \"./events\";"],"mappings":";;;AAUA,IAAY,wDAAL;AACL;AACA;AACA;AACA;;;AAOF,IAAa,SAAb,cAA4BA,eAAgC;CAC1D,GAAiC,OAAU,UAAiC;AAC1E,SAAO,MAAM,GAAG,OAAO,SAAS;;CAGlC,KAAmC,OAAU,GAAG,MAA4C;AAC1F,SAAO,MAAM,KAAK,OAAO,GAAG,KAAK;;CASnC,YAAY,EAAE,sBAAK,IAAI,MAAM,EAAC,SAAS,CAAC,UAAU,EAAE,OAAO,IAAI,YAAY,UAAyB;AAClG,SAAO;YAPI;cACE;gBAEQ,aAAa;AAKlC,OAAK,KAAK;AACV,OAAK,OAAO;AACZ,OAAK,aAAa;AAClB,OAAK,SAAS;AAEd,OAAK,GAAG,WAAW,WAAyB;AAC1C,QAAK,SAAS;IACd;AAGF,EAD0C;GAAC;GAAW;GAAW;GAAQ;GAAS;GAAS,CACpF,SAAS,UAAU;AACxB,QAAK,GAAG,QAAQ,GAAG,SAAc;AAC/B,SAAK,SAAS,OAAO,GAAG,KAAK;KAC7B;IACF;;CAGJ,SAAS;AACP,SAAO;GACL,IAAI,KAAK;GACT,MAAM,KAAK;GACX,YAAY,KAAK;GACjB,QAAQ,KAAK;GACd;;CAGH,WAAW;AACT,SAAO,KAAK,UAAU,KAAK,QAAQ,CAAC;;CAGtC,UAAU,QAAiD;AACzD,OAAK,SAAS;AACd,SAAO;;;;;;AC3CX,IAAY,oDAAL;AACL;AACA;;;AAGF,IAAY,oDAAL;AACL;AACA;AACA;;;AAgBF,IAAa,aAAb,cAAgC,OAA8B;CAM5D,YAAY,QAA0B,OAAmB,WAAW,QAAQ;AAC1E,QAAM,OAAO;iBANI;cACA,WAAW;mBACT;AAKnB,OAAK,OAAO;AACZ,MAAI,kBAAkB,UAAU,OAAO,OAAQ,OAAM,UAAU,OAAO,OAAO;;CAG/E,SAAS;AACP,SAAO;GACL,GAAG,MAAM,QAAQ;GACjB,MAAM,KAAK;GACX,SAAS,KAAK;GACd,WAAW,KAAK;GACjB;;;AAIL,IAAa,OAAb,cAA0BC,eAA8B;CACtD,GAA+B,OAAU,UAA+B;AACtE,SAAO,MAAM,GAAG,OAAO,SAAS;;CAGlC,KAAiC,OAAU,GAAG,MAA0C;AACtF,SAAO,MAAM,KAAK,OAAO,GAAG,KAAK;;CAUnC,IAAI,eAAe;AACjB,SAAO,KAAK,QAAQ,QAAQ,WAAW,OAAO,SAAS,WAAW,OAAO;;CAG3E,IAAI,WAAW;AACb,SAAO,KAAK,QAAQ,QAAQ,WAAW,OAAO,SAAS,WAAW,QAAQ;;CAK5E,IAAI,UAAmB;AACrB,SAAO,KAAK,QAAQ,UAAU,KAAK,WAC9B,KAAK,QAAQ,OAAO,WAAW,OAAO,WAAW,OAAO,SAAS,WAAW,QAAQ;;CAG3F,IAAI,SAAqB;AACvB,MAAI,CAAC,KAAK,QAAS,QAAO,WAAW;AACrC,MAAI,KAAK,QAAQ,WAAW,WAAW,OAAO,WAAW,aAAa,QAAQ,IAAI,GAAI,QAAO,WAAW;AACxG,SAAO,WAAW;;CAGpB,IAAI,YAAqB;AACvB,SAAO,KAAK,WAAW,WAAW;;CAIpC,IAAI,SAAkB;AACpB,SAAO,KAAK,aAAa,UAAU,KAAK;;CAG1C,SAAS;AACP,SAAO;GACL,IAAI,KAAK;GACT,MAAM,KAAK;GACX,MAAM,KAAK,QAAQ;GACnB,SAAS,KAAK;GACd,QAAQ,KAAK;GACb,SAAS,KAAK,QAAQ,KAAK,WAAW,OAAO,QAAQ,CAAC;GACtD,OAAO,KAAK;GACb;;CAGH,WAAW;AACT,SAAO,KAAK,UAAU,KAAK,QAAQ,CAAC;;CAGtC,YAAY,EACV,sBAAK,IAAI,MAAM,EAAC,SAAS,CAAC,UAAU,EAAE,OAAO,IAAI,OAAO,IAAI,UAAU,GAAG,SAC1D;AACf,SAAO;cAvDM;cACA;iBACG;iBAEM,EAAE;AAoDxB,OAAK,KAAK;AACV,OAAK,OAAO;AACZ,OAAK,OAAO;AACZ,OAAK,UAAU;AACf,OAAK,QAAQ;AAGb,EADwC;GAAC;GAAW;GAAW;GAAS;GAAO;GAAS;GAAS;GAAa;GAAkB;GAAgB;GAAQ;GAAQ,CACzJ,SAAS,UAAU;AACxB,QAAK,GAAG,QAAQ,GAAG,SAAc;AAC/B,SAAK,SAAS,OAAO,GAAG,KAAK;KAC7B;IACF;;CAGJ,UAAU,QAAgB,YAAqB,OAAO;AACpD,MAAI,KAAK,QAAQ,MAAM,MAAM,EAAE,MAAM,OAAO,GAAG,CAAE;EACjD,IAAI,aAAa,KAAK,aAAa,OAAO;AAC1C,MAAI,CAAC,YAAY;AACf,gBAAa,IAAI,WAAW,QAAQ,KAAK,UAAU,KAAK,YAAY,WAAW,UAAU,WAAW,OAAO;AAC3G,cAAW,YAAY;AACvB,cAAW,SAAS,KAAK;AACzB,QAAK,QAAQ,KAAK,WAAW;AAC7B,QAAK,KAAK,QAAQ;IAAE,QAAQ,KAAK;IAAI,GAAG;IAAY,CAAC;;AAEvD,SAAO;;CAMT,WAAW,QAA0B;EACnC,MAAM,WAAW,OAAO,WAAW,WAAW,SAAS,OAAO;EAC9D,MAAM,QAAQ,KAAK,QAAQ,WAAW,MAAM,EAAE,MAAM,SAAS;EAC7D,MAAM,aAAa,KAAK,QAAQ;AAChC,MAAI,QAAQ,IAAI;AACd,QAAK,KAAK,SAAU;IAAE,QAAQ,KAAK;IAAI,GAAG;IAAW,CAAC;AACtD,QAAK,QAAQ,OAAO,OAAO,EAAE;AAC7B,OAAI,WAAW,aAAa,KAAK,QAAQ,SAAS,GAAG;AACnD,SAAK,QAAQ,GAAG,YAAY;AAC5B,SAAK,KAAK,UAAU,KAAK;;;AAG7B,SAAO;;CAMT,aAAa,QAA0B;EACrC,MAAM,WAAW,OAAO,WAAW,WAAW,SAAS,OAAO;AAC9D,SAAO,KAAK,QAAQ,MAAM,aAAWC,SAAO,MAAM,SAAS;;CAG7D,QAAQ;AACN,MAAI,CAAC,KAAK,QACR,OAAM,IAAI,MAAM,qBAAqB;AAEvC,MAAI,KAAK,WAAW,WAAW,QAC7B,OAAM,IAAI,MAAM,2BAA2B;AAE7C,OAAK,QAAQ,SAAS,WAAW;AAC/B,OAAI,OAAO,QAAQ,WAAW,OAAQ;AACtC,UAAO,KAAK,UAAU,aAAa,QAAQ;IAC3C;AACF,OAAK,KAAK,UAAU,KAAK;AACzB,SAAO,KAAK,KAAK,SAAS,KAAK;;CAGjC,MAAM;AACJ,OAAK,QAAQ,SAAS,WAAW;AAC/B,OAAI,OAAO,QAAQ,WAAW,OAAQ;AACtC,UAAO,KAAK,UAAU,aAAa,QAAQ;IAC3C;AACF,OAAK,KAAK,UAAU,KAAK;AACzB,SAAO,KAAK,KAAK,OAAO,KAAK;;CAG/B,UAAU,QAAiD;AACzD,OAAK,SAAS;AACd,SAAO;;;;;;ACrNX,IAAY,wDAAL;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;ACbF,IAAa,SAAb,cAA4B,aAAa;CAKvC,YAAY,EAAE,UAA0B;AACtC,SAAO;eALO,EAAE;iBACE,EAAE;AAKpB,OAAK,kBAAkB;;CAGzB,GAAiC,OAAU,UAAiC;AAC1E,QAAM,GAAG,OAAO,SAAS;AACzB,SAAO;;CAGT,KAAmC,OAAU,GAAG,MAA4C;AAC1F,SAAO,MAAM,KAAK,OAAO,GAAG,KAAK;;CAGnC,MAAM;AACJ,OAAK,iBAAiB,GAAG,YAAY,SAAc,OAAgD;AACjG,OAAI;AACF,YAAQ,QAAQ,MAAhB;KACE,KAAK,YACH,QAAO,KAAK,MAAM,KAAK,MAAM;KAC/B,KAAK,cACH,QAAO,KAAK,MAAM,KAAK,QAAQ;KACjC,KAAK,cACH,QAAO,KAAK,WAAW,QAAQ,QAAQ,QAAQ,KAAK;KACtD,KAAK,cACH,QAAO,KAAK,WAAW,QAAQ,QAAQ,QAAQ,KAAK;KACtD,KAAK,eACH,QAAO,KAAK,YAAY,QAAQ,QAAQ,QAAQ,KAAK;KACvD,KAAK,WACH,QAAO,KAAK,MAAM,KAAK,WAAW,QAAQ,KAAK,CAAC;KAClD,KAAK,aACH,QAAO,KAAK,UAAU,QAAQ,QAAQ,QAAQ,KAAK;KACrD,KAAK,aACH,QAAO,KAAK,UAAU,QAAQ,QAAQ,QAAQ,KAAK;KACrD,KAAK,eACH,QAAO,KAAK,YAAY,QAAQ,KAAK;KACvC,KAAK,gBACH,QAAO,KAAK,aAAa,QAAQ,KAAK;KACxC,KAAK,eACH,QAAO,KAAK,YAAY,QAAQ,QAAQ,QAAQ,KAAK;KACvD,KAAK,iBACH,QAAO,KAAK,cAAc,QAAQ,QAAQ,QAAQ,KAAK;KACzD,KAAK,sBACH,QAAO,KAAK,WAAW,QAAQ,KAAK,EAAE,KAAK,kBAAkB;MAAE,GAAG,QAAQ;MAAO,QAAQ,QAAQ;MAAQ,CAAC;KAC5G,KAAK,eACH,QAAO,KAAK,WAAW,QAAQ,KAAK,EAAE,KAAK,WAAW,QAAQ,KAAK;KACrE,KAAK,iBACH,QAAO,KAAK,KAAK,WAAW;MAAE,GAAG,QAAQ;MAAO,QAAQ,QAAQ;MAAQ,CAAC;KAC3E,QACE,OAAM,IAAI,MAAM,wBAAwB;;YAErC,OAAO;AACd,SAAK,MAAe;;IAEtB;AAEF,OAAK,GAAG,WAAW,QAAQ,WAAW;AACpC,QAAK,iBAAiB,KAAK;IAAE,MAAM,SAAS,iBAAiB;IAAiB,MAAM;IAAQ,CAAC;IAC7F;AAEF,OAAK,GAAG,YAAY,YAAY;AAC9B,QAAK,iBAAiB,KAAK;IAAE,MAAM;IAAe,MAAM;IAAS,CAAC;IAClE;AAEF,OAAK,GAAG,SAAS,SAAS;AACxB,QAAK,iBAAiB,KAAK;IAAE,MAAM;IAAe,MAAM;IAAM,CAAC;IAC/D;AAEF,OAAK,GAAG,gBAAgB,SAAS;AAC/B,QAAK,iBAAiB,KAAK;IAAE,MAAM;IAAe,MAAM;IAAM,CAAC;IAC/D;AAEF,OAAK,GAAG,UAAU,UAAU;AAC1B,QAAK,iBAAiB,KAAK;IAAE,MAAM;IAAa,MAAM;IAAO,CAAC;IAC9D;AAEF,OAAK,GAAG,YAAY,SAAS;AAC3B,QAAK,iBAAiB,KAAK;IAAE,MAAM;IAAkB;IAAM,CAAC;IAC5D;AAEF,SAAO;;CAMT,aAAa,QAAqD;EAChE,MAAM,WAAW,OAAO,WAAW,WAAW,SAAS,OAAO;AAC9D,SAAO,KAAK,QAAQ,MAAM,WAAW,OAAO,OAAO,SAAS;;CAM9D,WAAW,MAAsC;EAC/C,MAAM,SAAS,OAAO,SAAS,WAAW,OAAO,KAAK;AACtD,SAAO,KAAK,MAAM,MAAM,WAAW,OAAO,OAAO,OAAO;;CAG1D,WAAW,QAAiB,SAAuB;AACjD,MAAI,CAAC,QAAQ,KACX,OAAM,IAAI,MAAM,2BAA2B;AAG7C,MADqB,KAAK,WAAW,QAAQ,CAE3C,OAAM,IAAI,MAAM,uBAAuB;AAGzC,MAAI,KAAK,MAAM,MAAK,MAAK,EAAE,QAAQ,MAAK,MAAK,EAAE,OAAO,OAAO,GAAG,CAAC,CAC/D,OAAM,IAAI,MAAM,6BAA6B;EAG/C,MAAM,OAAO,IAAI,KAAK,QAAQ;AAC9B,OAAK,WAAW,MAAM,YAAY;AAChC,QAAK,iBAAiB,KAAK;IAAE,MAAM,QAAQ;IAAQ,MAAM;IAAS,QAAQ;IAAM,CAAC;IACjF;AAEF,OAAK,KAAK,QAAQ,KAAK;AACvB,OAAK,MAAM,KAAK,KAAK;AAErB,OAAK,WAAW,QAAQ;GAAE,QAAQ,KAAK;GAAI,GAAG;GAAQ,EAAE,KAAK;AAC7D,SAAO;;CAGT,UAAU,QAAiB,MAAa;EACtC,MAAM,eAAe,KAAK,WAAW,KAAK;AAC1C,MAAI,CAAC,aACH,OAAM,IAAI,MAAM,kBAAkB;AAEpC,eAAa,OAAO;AAEpB,SAAO,KAAK,KAAK,eAAe,aAAa;;CAG/C,UAAU,QAAiB,MAAa;EACtC,MAAM,YAAY,KAAK,MAAM,WAAW,MAAM,EAAE,OAAO,KAAK,GAAG;EAC/D,MAAM,eAAe,KAAK,MAAM;AAChC,MAAI,CAAC,aACH,OAAM,IAAI,MAAM,kBAAkB;AAGpC,MAAI,aAAa,QAAQ,UAAU,CAAC,aAAa,QAAQ,MAAK,MAAK,EAAE,OAAO,OAAO,MAAM,EAAE,UAAU,CACnG,OAAM,IAAI,MAAM,wCAAwC;AAG1D,SAAO,KAAK,MAAM,OAAO,WAAW,EAAE,CAAC;AAEvC,OAAK,KAAK,SAAS,KAAK,MAAM;AAC9B,eAAa,KAAK,QAAQ;AAC1B,SAAO;;CAGT,YAAa,QAAuB,IAAiD;EACnF,IAAI,iBAAiB,KAAK,aAAa,OAAO;AAC9C,MAAI,CAAC,gBAAgB;AACnB,oBAAiB,IAAI,OAAO,OAAO;AACnC,kBAAe,WAAW,MAAM,YAAY;AAC1C,SAAK,iBAAiB,KAAK;KAAE,MAAM,UAAU;KAAQ,MAAM;KAAS,QAAQ;KAAgB,CAAC;KAC7F;AACF,QAAK,QAAQ,KAAK,eAAe;AACjC,QAAK,KAAK,UAAU,gBAAgB,KAAK;;AAG3C,iBAAe,KAAK,UAAU,aAAa,OAAO;AAClD,OAAK,EAAE,QAAQ,gBAAgB,CAAC;AAChC,SAAO;;CAGT,WAAW,QAAiB,QAA4B,YAAqB,OAAO;EAClF,IAAI,iBAAiB,KAAK,aAAa,OAAO;AAC9C,MAAI,CAAC,eACH,kBAAiB,KAAK,YAAY,OAAO;AAG3C,MAAI,CAAC,OAAO,OACV,OAAM,IAAI,MAAM,mBAAmB;EAGrC,MAAM,OAAO,KAAK,MAAM,MAAM,WAASC,OAAK,OAAO,OAAO,OAAO;AACjE,MAAI,CAAC,KACH,OAAM,IAAI,MAAM,kBAAkB;EAGpC,MAAM,aAAa,KAAK,UAAU,gBAAgB,UAAU;AAC5D,MAAI,CAAC,WACH,OAAM,IAAI,MAAM,gBAAgB;AAGlC,OAAK,KAAK,eAAe,KAAK;AAE9B,SAAO;;CAGT,YAAY,QAAiB,QAA4B;AACvD,MAAI,CAAC,OAAO,OACV,OAAM,IAAI,MAAM,mBAAmB;EAGrC,MAAM,OAAO,KAAK,MAAM,MAAM,WAASA,OAAK,OAAO,OAAO,OAAO;AACjE,MAAI,CAAC,KACH,OAAM,IAAI,MAAM,kBAAkB;EAGpC,MAAM,iBAAiB,KAAK,aAAa,OAAO;AAChD,MAAI,CAAC,eACH,OAAM,IAAI,MAAM,sBAAsB;EAGxC,MAAM,aAAa,KAAK,WAAW,eAAe;AAElD,MAAI,WAAY,MAAK,KAAK,eAAe,KAAK;AAE9C,SAAO;;CAGT,YAAY,QAAiB,QAAqB;EAChD,MAAM,iBAAiB,KAAK,aAAa,OAAO;AAChD,MAAI,CAAC,eACH,OAAM,IAAI,MAAM,oBAAoB;AAGtC,MAAI,CAAC,OAAO,OACV,OAAM,IAAI,MAAM,mBAAmB;EAGrC,MAAM,OAAO,KAAK,MAAM,MAAM,WAASA,OAAK,OAAO,OAAO,OAAO;AACjE,MAAI,CAAC,KACH,OAAM,IAAI,MAAM,kBAAkB;EAGpC,MAAM,aAAa,KAAK,aAAa,eAAe;AAEpD,MAAI,CAAC,WACH,OAAM,IAAI,MAAM,sBAAsB;AAGxC,aAAW,UAAU;AAErB,MAAI,KAAK,QACP,MAAK,KAAK,aAAa,KAAK,QAAQ;AAGtC,iBAAe,KAAK,UAAU,aAAa,MAAM;AAEjD,OAAK,KAAK,gBAAgB;GAAE,GAAG;GAAQ,GAAG;GAAY,CAAC;AAEvD,SAAO;;CAGT,cAAc,QAAiB,QAAqB;EAClD,MAAM,iBAAiB,KAAK,aAAa,OAAO;AAChD,MAAI,CAAC,eACH,OAAM,IAAI,MAAM,oBAAoB;AAGtC,MAAI,CAAC,OAAO,OACV,OAAM,IAAI,MAAM,mBAAmB;EAGrC,MAAM,OAAO,KAAK,MAAM,MAAM,WAASA,OAAK,OAAO,OAAO,OAAO;AACjE,MAAI,CAAC,KACH,OAAM,IAAI,MAAM,kBAAkB;EAGpC,MAAM,aAAa,KAAK,aAAa,eAAe;AAEpD,MAAI,CAAC,WACH,OAAM,IAAI,MAAM,sBAAsB;AAGxC,aAAW,UAAU;AACrB,iBAAe,KAAK,UAAU,aAAa,QAAQ;AACnD,OAAK,KAAK,kBAAkB,WAAW;AAEvC,SAAO;;CAGT,aAAa,QAAiB;EAC5B,MAAM,cAAc,KAAK,QAAQ,WAAW,MAAM,EAAE,OAAO,OAAO,GAAG;EACrE,MAAM,SAAS,KAAK,QAAQ;AAC5B,MAAI,cAAc,IAAI;AACpB,QAAK,QAAQ,OAAO,aAAa,EAAE,CAAC;AACpC,QAAK,KAAK,UAAU,QAAQ,MAAM;AAClC,OAAI,KAAK,MAAM,MAAK,MAAK,EAAE,aAAa,OAAO,CAAC,CAC9C,kBAAiB;AACf,QAAI,KAAK,QAAQ,MAAK,MAAK,EAAE,OAAO,OAAO,GAAG,CAAE;AAChD,SAAK,MAAM,QAAO,MAAK,EAAE,aAAa,OAAO,CAAC,CAAC,SAAQ,MAAK;AAC1D,UAAK,YAAY,QAAQ;MAAE,GAAG;MAAQ,QAAQ,EAAE;MAAI,CAAC;MACrD;MACD,MAAS,IAAK;;AAGrB,SAAO"}
|