Room.tsx
3.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import React, { useCallback, useContext, useEffect, useState } from 'react';
import { useHistory, useLocation } from 'react-router';
import { Main } from '../components/common/Main';
import { MessageResponse, MessageType, RawMessage } from '../components/common/types';
import { Canvas } from '../components/room/Canvas';
import { Chat } from '../components/room/Chat';
import { GameBoard } from '../components/room/GameBoard';
import { Ready } from '../components/room/Ready';
import { RoomInfo } from '../components/room/RoomInfo';
import { RoomData, UpdateRoomUser } from '../components/room/types';
import { UserInfo } from '../components/room/UserInfo';
import { UserStatus } from '../components/room/UserStatus';
import SocketContext from '../contexts/SocketContext';
interface RoomLocation {
state: { roomData: RoomData }
}
export const Room: React.FC = () => {
const history = useHistory();
const socket = useContext(SocketContext);
const location: RoomLocation = useLocation();
const [ roomData, setRoomData ] = useState<RoomData>({
// 기본값
uuid: '0',
name: 'loading...',
maxUsers: 9,
users: []
});
const [ isInGame, setIsInGame ] = useState(false);
const handleInGame = useCallback((rawMessage: RawMessage) => {
if (rawMessage.type === MessageType.GAME_START) {
setIsInGame(true);
} else if (rawMessage.type === MessageType.GAME_FINISH_GAME) {
setIsInGame(false);
}
}, []);
const handleUpdateRoomUser = useCallback((rawMessage: RawMessage) => {
if (rawMessage.type == MessageType.ROOM_USER_UPDATE) {
const data = rawMessage.message as UpdateRoomUser;
if (data.state == 'removed') {
const newUsers = roomData.users;
const index = newUsers.findIndex(x => x.username === data.user.username);
if (index < 0) {
console.log('존재하지 않는 유저를 제거 시도');
} else {
newUsers.splice(index, 1);
}
setRoomData({
...roomData,
users: newUsers
});
} else if (data.state === 'updated') {
const newUsers = roomData.users;
const index = newUsers.findIndex(x => x.username === data.user.username);
if (index < 0) {
console.log('존재하지 않는 유저를 업데이트 시도');
} else {
newUsers[index] = data.user;
}
setRoomData({
...roomData,
users: newUsers
})
} else {
setRoomData({
...roomData,
users: [data.user, ...roomData.users]
});
}
}
}, [roomData]);
useEffect(() => {
socket.on('msg', handleUpdateRoomUser);
return () => {
socket.off('msg', handleUpdateRoomUser);
}
}, [roomData]);
useEffect(() => {
// 비정상적인 루트로 방을 들어오면 로그인 화면으로 푸시
if (location.state === undefined) {
history.push('/');
return;
}
setRoomData(location.state.roomData);
socket.on('msg', handleInGame);
return () => {
socket.off('msg', handleInGame);
const rawMessage: RawMessage = {
type: MessageType.ROOM_LEAVE,
message: ''
}
socket.emit('msg', rawMessage, (response : MessageResponse<undefined>) => {});
}
}, [])
return (
<Main>
<RoomInfo roomData={roomData}/>
<div className='w-full flex'>
{/* 게임보드를 계속 살려둬서 리스너를 항상 열어놓도록 하자 */}
<GameBoard isInGame={isInGame} />
{
isInGame ? (
<Chat w='w-4/12' h='h-132' />
) : (
<div className='w-full flex flex-col justify-center items-center'>
<UserInfo users={roomData.users}/>
<Ready users={roomData.users} />
<Chat w='w-7/12' h='h-96' />
</div>
)
}
</div>
</Main>
);
}