Showing
10 changed files
with
80 additions
and
132 deletions
1 | import express from "express"; | 1 | import express from "express"; |
2 | import socketIo, { Server as IoServer } from "socket.io"; | 2 | import socketIo, { Server as IoServer } from "socket.io"; |
3 | import { createServer } from "http"; | 3 | import { createServer } from "http"; |
4 | -import { SocketHandler } from "./SocketHandler"; | ||
5 | import { RoomManager } from "./room/RoomManager"; | 4 | import { RoomManager } from "./room/RoomManager"; |
5 | +import { Connection } from "./connection/Connection"; | ||
6 | +import { SocketIoWrapper } from "./connection/SocketWrapper"; | ||
6 | 7 | ||
7 | export class Server { | 8 | export class Server { |
8 | public readonly port: number; | 9 | public readonly port: number; |
... | @@ -15,7 +16,6 @@ export class Server { | ... | @@ -15,7 +16,6 @@ export class Server { |
15 | const server = createServer(app); | 16 | const server = createServer(app); |
16 | this.io = new socketIo.Server(server); | 17 | this.io = new socketIo.Server(server); |
17 | 18 | ||
18 | - const handler = new SocketHandler(); | ||
19 | const roomManager = new RoomManager(); | 19 | const roomManager = new RoomManager(); |
20 | 20 | ||
21 | roomManager.create("테스트 방 #1", 8); | 21 | roomManager.create("테스트 방 #1", 8); |
... | @@ -23,7 +23,7 @@ export class Server { | ... | @@ -23,7 +23,7 @@ export class Server { |
23 | roomManager.create("테스트 방 #3", 2); | 23 | roomManager.create("테스트 방 #3", 2); |
24 | 24 | ||
25 | this.io.on("connection", (socket) => { | 25 | this.io.on("connection", (socket) => { |
26 | - handler.connected(socket); | 26 | + new Connection(new SocketIoWrapper(socket), roomManager); |
27 | }); | 27 | }); |
28 | 28 | ||
29 | server.listen(port, () => console.log(`Listening on ${port}`)); | 29 | server.listen(port, () => console.log(`Listening on ${port}`)); | ... | ... |
server/SocketHandler.ts
deleted
100644 → 0
1 | -import { Socket } from "socket.io"; | ||
2 | -import { ConnectionMapper } from "./connection/ConnectionMapper"; | ||
3 | - | ||
4 | -export class SocketHandler { | ||
5 | - private connectionMapper: ConnectionMapper; | ||
6 | - | ||
7 | - constructor() { | ||
8 | - this.connectionMapper = new ConnectionMapper(); | ||
9 | - } | ||
10 | - | ||
11 | - public connected(socket: Socket) { | ||
12 | - const connection = this.connectionMapper.get(socket); | ||
13 | - } | ||
14 | -} |
1 | import { Socket } from "socket.io"; | 1 | import { Socket } from "socket.io"; |
2 | -import { ServerOutboundMessage, ServerOutboundMessageKey } from "../../common"; | 2 | +import { |
3 | -import { MessageHandlerChain } from "../message/MessageHandlerChain"; | 3 | + RawMessage, |
4 | + ServerInboundMessage, | ||
5 | + ServerInboundMessageKey, | ||
6 | + ServerOutboundMessage, | ||
7 | + ServerOutboundMessageKey, | ||
8 | + ServerResponse, | ||
9 | +} from "../../common"; | ||
4 | import { Room } from "../room/Room"; | 10 | import { Room } from "../room/Room"; |
11 | +import { RoomManager } from "../room/RoomManager"; | ||
5 | import { User } from "../user/User"; | 12 | import { User } from "../user/User"; |
13 | +import { SocketWrapper } from "./SocketWrapper"; | ||
6 | 14 | ||
7 | export class Connection { | 15 | export class Connection { |
8 | - public readonly socket: Socket; | 16 | + public readonly socket: SocketWrapper; |
17 | + public readonly roomManager: RoomManager; | ||
9 | 18 | ||
10 | public user?: User; | 19 | public user?: User; |
11 | 20 | ||
12 | - private messageHandlerChain: MessageHandlerChain; | 21 | + constructor(socket: SocketWrapper, roomManager: RoomManager) { |
13 | - | ||
14 | - constructor(socket: Socket) { | ||
15 | this.socket = socket; | 22 | this.socket = socket; |
16 | - this.messageHandlerChain = new MessageHandlerChain(this); | 23 | + this.roomManager = roomManager; |
24 | + socket.setHandler((raw) => this.handleRaw(raw)); | ||
17 | } | 25 | } |
18 | 26 | ||
19 | public send<T extends ServerOutboundMessageKey>( | 27 | public send<T extends ServerOutboundMessageKey>( |
20 | type: T, | 28 | type: T, |
21 | message: ServerOutboundMessage<T> | 29 | message: ServerOutboundMessage<T> |
22 | ) { | 30 | ) { |
23 | - this.socket.emit("msg", { | 31 | + this.socket.send({ |
24 | type: type as string, | 32 | type: type as string, |
25 | message: message, | 33 | message: message, |
26 | }); | 34 | }); |
27 | } | 35 | } |
36 | + | ||
37 | + public handleRaw(raw: RawMessage): ServerResponse<any> { | ||
38 | + const type = raw.type as ServerInboundMessageKey; | ||
39 | + const message = raw.message; | ||
40 | + | ||
41 | + // 유저 정보가 없으므로 로그인은 따로 핸들링 | ||
42 | + if (type === "login") { | ||
43 | + return this.handleLogin(message); | ||
44 | + } | ||
45 | + | ||
46 | + // Game > Room > User 순으로 전달 | ||
47 | + if (this.user?.room) { | ||
48 | + const response = this.user.room.handler.handle(type, this.user, message); | ||
49 | + if (response) return response; | ||
50 | + } | ||
51 | + if (this.user) { | ||
52 | + const response = this.user.handler.handle(type, this.user, message); | ||
53 | + if (response) return response; | ||
54 | + } | ||
55 | + return { ok: false }; | ||
56 | + } | ||
57 | + | ||
58 | + private handleLogin( | ||
59 | + message: ServerInboundMessage<"login"> | ||
60 | + ): ServerResponse<"login"> { | ||
61 | + this.user = new User(message.username, this); | ||
62 | + console.log(`User ${message.username} has logged in!`); | ||
63 | + | ||
64 | + return { ok: true }; | ||
65 | + } | ||
28 | } | 66 | } | ... | ... |
1 | -import { Socket } from "socket.io"; | ||
2 | -import { Connection } from "./Connection"; | ||
3 | - | ||
4 | -export class ConnectionMapper { | ||
5 | - private map: Map<Socket, Connection>; | ||
6 | - | ||
7 | - constructor() { | ||
8 | - this.map = new Map<Socket, Connection>(); | ||
9 | - } | ||
10 | - | ||
11 | - public get(socket: Socket): Connection { | ||
12 | - var value = this.map.get(socket); | ||
13 | - if (value) { | ||
14 | - return value; | ||
15 | - } | ||
16 | - | ||
17 | - value = new Connection(socket); | ||
18 | - // FIXME: Register connection to the map | ||
19 | - return value; | ||
20 | - } | ||
21 | - | ||
22 | - public close(socket: Socket): void { | ||
23 | - this.map.delete(socket); | ||
24 | - } | ||
25 | -} |
server/connection/SocketWrapper.ts
0 → 100644
1 | +import { Socket } from "socket.io"; | ||
2 | +import { RawMessage, ServerResponse } from "../../common"; | ||
3 | + | ||
4 | +export interface SocketWrapper { | ||
5 | + setHandler: (listener: (raw: RawMessage) => ServerResponse<any>) => void; | ||
6 | + send: (raw: RawMessage) => void; | ||
7 | +} | ||
8 | + | ||
9 | +export class SocketIoWrapper implements SocketWrapper { | ||
10 | + private socketIo: Socket; | ||
11 | + | ||
12 | + constructor(socketIo: Socket) { | ||
13 | + this.socketIo = socketIo; | ||
14 | + } | ||
15 | + | ||
16 | + public setHandler(listener: (raw: RawMessage) => ServerResponse<any>): void { | ||
17 | + this.socketIo.on("msg", (raw: RawMessage, callback: Function) => { | ||
18 | + callback(listener(raw)); | ||
19 | + }); | ||
20 | + } | ||
21 | + | ||
22 | + public send(raw: RawMessage) { | ||
23 | + this.socketIo.emit("msg", raw); | ||
24 | + } | ||
25 | +} |
1 | -import { Connection } from "../connection/Connection"; | ||
2 | import { | 1 | import { |
3 | ServerInboundMessage, | 2 | ServerInboundMessage, |
4 | ServerInboundMessageKey, | 3 | ServerInboundMessageKey, |
... | @@ -23,13 +22,10 @@ export class MessageHandler { | ... | @@ -23,13 +22,10 @@ export class MessageHandler { |
23 | public handle( | 22 | public handle( |
24 | type: ServerInboundMessageKey, | 23 | type: ServerInboundMessageKey, |
25 | user: User, | 24 | user: User, |
26 | - message: any, | 25 | + message: any |
27 | - callback: Function | 26 | + ): ServerResponse<any> | undefined { |
28 | - ): boolean { | ||
29 | const handler = this.handlers[type]; | 27 | const handler = this.handlers[type]; |
30 | - if (!handler) return false; | 28 | + if (!handler) return undefined; |
31 | - const response = handler(user, message); | 29 | + return handler(user, message); |
32 | - callback(response); | ||
33 | - return true; | ||
34 | } | 30 | } |
35 | } | 31 | } | ... | ... |
1 | -import { Connection } from "../connection/Connection"; | ||
2 | -import { | ||
3 | - RawMessage, | ||
4 | - ServerInboundMessage, | ||
5 | - ServerInboundMessageKey, | ||
6 | - ServerResponse, | ||
7 | -} from "../../common/index"; | ||
8 | -import { User } from "../user/User"; | ||
9 | - | ||
10 | -export class MessageHandlerChain { | ||
11 | - connection: Connection; | ||
12 | - | ||
13 | - constructor(connection: Connection) { | ||
14 | - this.connection = connection; | ||
15 | - | ||
16 | - this.connection.socket.on("msg", (raw: RawMessage, callback: Function) => { | ||
17 | - this.handleRaw(connection, raw, callback); | ||
18 | - }); | ||
19 | - } | ||
20 | - | ||
21 | - private handleRaw( | ||
22 | - connection: Connection, | ||
23 | - raw: RawMessage, | ||
24 | - callback: Function | ||
25 | - ) { | ||
26 | - const type = raw.type as ServerInboundMessageKey; | ||
27 | - const message = raw.message; | ||
28 | - | ||
29 | - // 유저 정보가 없으므로 로그인은 따로 핸들링 | ||
30 | - if (type === "login") { | ||
31 | - this.handleLogin(connection, message, callback); | ||
32 | - return; | ||
33 | - } | ||
34 | - | ||
35 | - // Game > Room > User 순으로 전달 | ||
36 | - if ( | ||
37 | - connection?.user?.room && | ||
38 | - connection.user.room.handler.handle( | ||
39 | - type, | ||
40 | - connection.user, | ||
41 | - message, | ||
42 | - callback | ||
43 | - ) | ||
44 | - ) | ||
45 | - return; | ||
46 | - | ||
47 | - if ( | ||
48 | - connection?.user && | ||
49 | - connection.user.handler.handle(type, connection.user, message, callback) | ||
50 | - ) | ||
51 | - return; | ||
52 | - } | ||
53 | - | ||
54 | - private handleLogin( | ||
55 | - connection: Connection, | ||
56 | - message: ServerInboundMessage<"login">, | ||
57 | - callback: Function | ||
58 | - ) { | ||
59 | - connection.user = new User(message.username, connection); | ||
60 | - console.log(`User ${message.username} has logged in!`); | ||
61 | - | ||
62 | - callback({ ok: true }); | ||
63 | - } | ||
64 | -} |
1 | import { Connection } from "../connection/Connection"; | 1 | import { Connection } from "../connection/Connection"; |
2 | import { v4 as uuidv4 } from "uuid"; | 2 | import { v4 as uuidv4 } from "uuid"; |
3 | import { User } from "../user/User"; | 3 | import { User } from "../user/User"; |
4 | -import { MessageHandlerChain } from "../message/MessageHandlerChain"; | ||
5 | import { MessageHandler } from "../message/MessageHandler"; | 4 | import { MessageHandler } from "../message/MessageHandler"; |
6 | import { | 5 | import { |
7 | ServerInboundMessage, | 6 | ServerInboundMessage, | ... | ... |
... | @@ -2,19 +2,12 @@ import { RoomDescription } from "../../common/dataType"; | ... | @@ -2,19 +2,12 @@ import { RoomDescription } from "../../common/dataType"; |
2 | import { Room } from "./Room"; | 2 | import { Room } from "./Room"; |
3 | 3 | ||
4 | export class RoomManager { | 4 | export class RoomManager { |
5 | - private static _instance: RoomManager; | ||
6 | - | ||
7 | private rooms: Map<string, Room>; | 5 | private rooms: Map<string, Room>; |
8 | 6 | ||
9 | constructor() { | 7 | constructor() { |
10 | - RoomManager._instance = this; | ||
11 | this.rooms = new Map<string, Room>(); | 8 | this.rooms = new Map<string, Room>(); |
12 | } | 9 | } |
13 | 10 | ||
14 | - public static instance(): RoomManager { | ||
15 | - return RoomManager._instance; | ||
16 | - } | ||
17 | - | ||
18 | public create(name: string, maxConnections: number): Room { | 11 | public create(name: string, maxConnections: number): Room { |
19 | const room = new Room(name, maxConnections); | 12 | const room = new Room(name, maxConnections); |
20 | this.rooms.set(room.uuid, room); | 13 | this.rooms.set(room.uuid, room); | ... | ... |
... | @@ -18,10 +18,10 @@ export class User { | ... | @@ -18,10 +18,10 @@ export class User { |
18 | this.connection = connection; | 18 | this.connection = connection; |
19 | this.handler = new MessageHandler({ | 19 | this.handler = new MessageHandler({ |
20 | roomList: (user, message) => { | 20 | roomList: (user, message) => { |
21 | - return { ok: true, result: RoomManager.instance().list() }; | 21 | + return { ok: true, result: connection.roomManager.list() }; |
22 | }, | 22 | }, |
23 | joinRoom: (user, message) => { | 23 | joinRoom: (user, message) => { |
24 | - const room = RoomManager.instance().get(message.uuid); | 24 | + const room = connection.roomManager.get(message.uuid); |
25 | if (user.room || !room) { | 25 | if (user.room || !room) { |
26 | return { ok: false }; | 26 | return { ok: false }; |
27 | } | 27 | } | ... | ... |
-
Please register or login to post a comment