Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 54 additions & 25 deletions backend/game/matchingConsumers.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ async def initialize(self, user1, user2):
self.left_ball = Ball(0, SCREEN_HEIGHT, SCREEN_WIDTH, self.left_bar)
self.right_ball = Ball(1, SCREEN_HEIGHT, SCREEN_WIDTH, self.right_bar)
self.score = [0, 0]
print("user1:", user1, "user2:", user2)
# print("user1:", user1, "user2:", user2)
user1_nickname, user2_nickname = await get_user_nicknames(user1, user2)
print("user1_nickname:", user1_nickname, "user2_nickname:", user2_nickname)
# print("user1_nickname:", user1_nickname, "user2_nickname:", user2_nickname)
self.player = [user1_nickname, user2_nickname]
self.penalty_time = [0, 0]
print("initializing game state finished successfully!")
Expand All @@ -75,8 +75,12 @@ async def connect(self):
self.authenticated = False
self.start_time = timezone.now()

if self.room_group_name not in MatchingGameConsumer.game_states:
return

await self.accept()


async def receive(self, text_data):
text_data_json = json.loads(text_data)
action = text_data_json["action"]
Expand All @@ -85,10 +89,9 @@ async def receive(self, text_data):
token = text_data_json.get("token")
if not token or not self.authenticate(token):
print("authentication failed")
await self.close(code=4001)
# await self.close(code=4001)
return
self.authenticated = True
self.my_uid = 0

# Join room group after successful authentication
await self.channel_layer.group_add(self.room_group_name, self.channel_name)
Expand All @@ -108,8 +111,6 @@ async def receive(self, text_data):
MatchingGameConsumer.game_tasks[self.room_group_name] = (
asyncio.create_task(self.game_loop())
)
elif not self.authenticated:
await self.close(code=4001)
else:
bar = text_data_json.get("bar")
state = MatchingGameConsumer.game_states[self.room_group_name]
Expand Down Expand Up @@ -158,22 +159,40 @@ def authenticate(self, token):
return False

async def disconnect(self, close_code):
# Leave room group
# 인증된 소켓만 처리
if self.authenticated:
await self.channel_layer.group_discard(
self.room_group_name, self.channel_name
)
# Decrease the client count for this room
print("disconnected: ", self.user_index)
await self.channel_layer.group_discard(self.room_group_name, self.channel_name)

# 현재 방의 접속자 수를 1 줄임
if self.room_group_name in MatchingGameConsumer.client_counts:
MatchingGameConsumer.client_counts[self.room_group_name] -= 1
if MatchingGameConsumer.client_counts[self.room_group_name] <= 0:
MatchingGameConsumer.game_tasks[self.room_group_name].cancel()
del MatchingGameConsumer.game_tasks[self.room_group_name]
del MatchingGameConsumer.game_states[self.room_group_name]
del MatchingGameConsumer.client_counts[self.room_group_name]

# 만약 이제 방에 1명만 남았다면 -> 남은 사람이 승자
if MatchingGameConsumer.client_counts[self.room_group_name] == 1:
# 누가 남았는지 판별 (내가 0이라면 1이 승자, 내가 1이라면 0이 승자)
winner_index = 1 - self.user_index
state = MatchingGameConsumer.game_states[self.room_group_name]

# send_game_result를 통해 DB에 게임결과 저장 및
# 나머지(승자)에게 게임 종료 메시지 전송
await self.send_game_result(winner_index)
await asyncio.sleep(0.1)
await self.close()

# 아무도 안 남았다면 방을 완전히 정리
elif MatchingGameConsumer.client_counts[self.room_group_name] <= 0:
if self.room_group_name in MatchingGameConsumer.game_tasks:
MatchingGameConsumer.game_tasks[self.room_group_name].cancel()
del MatchingGameConsumer.game_tasks[self.room_group_name]
if self.room_group_name in MatchingGameConsumer.game_states:
del MatchingGameConsumer.game_states[self.room_group_name]
if self.room_group_name in MatchingGameConsumer.client_counts:
del MatchingGameConsumer.client_counts[self.room_group_name]
else:
MatchingGameConsumer.client_counts[self.room_group_name] = 0


async def send_initialize_game(self):
state = MatchingGameConsumer.game_states[self.room_group_name]
await self.send(
Expand Down Expand Up @@ -248,6 +267,7 @@ async def game_loop(self):
async def send_game_result(self, winner):
state = MatchingGameConsumer.game_states[self.room_group_name]

print("Game result for", self.room_group_name, ":", state.score, "Winner:", winner)
await self.save_game_result(state, winner)
await self.channel_layer.group_send(
self.room_group_name,
Expand All @@ -270,6 +290,10 @@ def save_game_result(self, state, winner):
user2_obj = None

score1, score2 = state.score
if winner == 0:
score1 = MAX_SCORE
else:
score2 = MAX_SCORE

game = Game.objects.create(
game_type="PvP",
Expand Down Expand Up @@ -300,16 +324,21 @@ async def game_result_message(self, event):
score = event["score"]
winner = event["winner"]

# Send the game result to the WebSocket
await self.send(
text_data=json.dumps(
{
"type": "game_result",
"score": score,
"winner": winner,
}
if not self.scope["client"]:
return
try:
await self.send(
text_data=json.dumps(
{
"type": "game_result",
"score": score,
"winner": winner,
}
)
)
)
except Exception as e:
print("Failed to send game_result_message:", e, "for", self.user_index)


async def send_game_state(self):
state = MatchingGameConsumer.game_states[self.room_group_name]
Expand Down
35 changes: 21 additions & 14 deletions backend/game/onlineConsumers.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
from django.conf import settings
from channels.exceptions import DenyConnection
from .matchingConsumers import MatchingGameConsumer, MatchingGameState
import random
import uuid


class OnlineConsumer(AsyncWebsocketConsumer):
Expand All @@ -26,7 +28,7 @@ async def start_game(cls):
user1 = cls.matching_queue.pop(0)
user2 = cls.matching_queue.pop(0)

room_name = f"{user1.uid}_{user2.uid}"
room_name = f"{user1.uid}_{user2.uid}_{str(uuid.uuid4())[:8]}"

game_state = MatchingGameState()
await game_state.initialize(user1.uid, user2.uid) # 비동기 초기화
Expand Down Expand Up @@ -94,23 +96,28 @@ def authenticate(self, token):
return False

async def enter_matching(self):
# Add user to matching queue
if self not in OnlineConsumer.matching_queue:
OnlineConsumer.matching_queue.append(self)
print(
"Matching queue: ", [user.uid for user in OnlineConsumer.matching_queue]
)
for user in list(OnlineConsumer.matching_queue):
if user.uid == self.uid:
OnlineConsumer.matching_queue.remove(user)
print(f"Replaced existing user {self.uid} in the matching queue.")
break
OnlineConsumer.matching_queue.append(self)
print(
"Matching queue: ", [user.uid for user in OnlineConsumer.matching_queue]
)

async def leave_matching(self):
# Remove user from matching queue
if self in OnlineConsumer.matching_queue:
OnlineConsumer.matching_queue.remove(self)
print(f"User {self.uid} removed from matching queue")
print(
"Matching queue: ", [user.uid for user in OnlineConsumer.matching_queue]
)
for user in list(OnlineConsumer.matching_queue):
if user.uid == self.uid:
OnlineConsumer.matching_queue.remove(user)
print(f"User {self.uid} removed from matching queue")
break
print(
"Matching queue: ", [user.uid for user in OnlineConsumer.matching_queue]
)

async def disconnect(self, close_code):
await self.leave_matching()
try:
if self.uid in OnlineConsumer.online_user_list:
OnlineConsumer.online_user_list.remove(self.uid)
Expand Down
3 changes: 3 additions & 0 deletions backend/login/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,17 @@ def login(request):
def callback(request):
code = request.data.get("code")
if not code:
print("No code in request")
return Response(status=401)

access_token = get_acccess_token(code)
if not access_token:
print("Failed to get access token!!!")
return Response(status=401)

user_data = get_user_info(access_token)
if not user_data:
print("Failed to get user info")
return Response(status=401)

user, created = get_or_save_user(user_data)
Expand Down
37 changes: 3 additions & 34 deletions frontend/src/app.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { initializeRouter, createRoutes, changeUrl } from "./core/router.js";
import { getCookie } from "./core/jwt.js";
import { createRoutes } from "./core/router.js";
import { showLoading } from "./core/showLoading.js";

class App {
app;
Expand All @@ -12,37 +12,6 @@ class App {

export const root = new App();
export const routes = createRoutes(root);

export let socketList = [];

const closeAllSockets = () => {
socketList.forEach(socket => {
if (socket.readyState === WebSocket.OPEN || socket.readyState === WebSocket.CONNECTING) {
socket.close();
}
});
socketList = [];
};

const online = () => {
const onlineSocket = new WebSocket(
'wss://'
+ "localhost:443"
+ '/ws/online/'
);
socketList.push(onlineSocket);

console.log(onlineSocket);
onlineSocket.onopen = () => {
const token = getCookie("jwt");
onlineSocket.send(JSON.stringify({ 'action': 'authenticate', 'token': token }));
};
onlineSocket.onclose = () => {
console.log("online socket closed");
closeAllSockets();
changeUrl("/error", false);
};
}

initializeRouter(routes);
online();
showLoading(routes, socketList);
Loading
Loading