Управление несогласованным состоянием атрибута модели при повторном подключении WebSocket (каналы Django)Python

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Управление несогласованным состоянием атрибута модели при повторном подключении WebSocket (каналы Django)

Сообщение Anonymous »

Я работаю над онлайн-игрой «Морской бой» с помощью React Django_channels, и у меня возникли проблемы с поддержанием согласованности данных атрибута «фаза лобби» в моей модели Django. Этот атрибут должен работать для перехода лобби из состояния «ожидание другого». игрок должен присоединиться к пользовательскому интерфейсу к фазе «настройки», чтобы пользователи могли изменять положение своих кораблей, и, наконец, появится фаза «игры», на которой начнется настоящий матч.
Из-за чего Я видел из своих журналов Consumer.py, что я почти уверен, что ошибка находится где-то здесь, в методе async def Connect(self):.

Код: Выделить всё

import json, jwt, uuid, random
from channels.generic.websocket import AsyncWebsocketConsumer
from django.conf import settings
from asgiref.sync import sync_to_async
from .models import GameRoom

class BattleshipConsumer(AsyncWebsocketConsumer):
async def connect(self):
self.room_group_name = self.scope['url_route']['kwargs']['room_id']
token = self.scope['url_route']['kwargs']['token']

try:
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=['HS256'])
self.username = payload['username']
self.guest_id = payload['guest_id']

await self.channel_layer.group_add(
self.room_group_name,
self.channel_name
)
await self.accept()

# Fetch the current state of the room
self.room = await sync_to_async(GameRoom.objects.get)(room_name=self.room_group_name)
initial_lobby_phase = self.room.lobby_phase

# Log current state before making changes
print(f"Initial room state for {self.username}: {initial_lobby_phase}")

# Check if player1 or player2 is None and assign self.guest_id accordingly
if self.room.player1 is None and self.room.player2 != self.guest_id:
self.room.player1 = self.guest_id
print(f'{self.username} has been added as player1')
await sync_to_async(self.room.save)()
elif self.room.player2 is None and self.room.player1 != self.guest_id:
self.room.player2 = self.guest_id
self.room.lobby_phase = 'setup'

# Save the updated room and fetch it again to ensure consistency
await sync_to_async(self.room.save)()
print(f'{self.username} has been added as player2')
self.room = await sync_to_async(GameRoom.objects.get)(room_name=self.room_group_name)
#this works correctly, the lobby phase sent here is 'setup',as expected
print("broadcasting phase change to setup")
await self.channel_layer.group_send(
self.room_group_name,
{
'type': 'phase_change',
'phase': self.room.lobby_phase
}
)

# Fetch the latest state from the database after making changes
self.room = await sync_to_async(GameRoom.objects.get)(room_name=self.room_group_name)
lobby_phase = self.room.lobby_phase

# Log updated state after changes
print(f"Current room state for {self.username}: {lobby_phase}")

chat_history = await sync_to_async(self.room.get_chat_history)()
shots_fired_history = await sync_to_async(self.room.get_shots_fired_history)(self.guest_id)
shots_received_history = await sync_to_async(self.room.get_shots_received_history)(self.guest_id)

await self.send(text_data=json.dumps({
'type': 'restore_game_history',
'lobby_phase': lobby_phase,
'chat_history': chat_history,
'shots_fired': shots_fired_history,
'shots_received': shots_received_history
}))

msg = f'{self.username} has joined the room'
message_id = str(uuid.uuid4())
await sync_to_async(self.room.add_chat_message)('Server', msg, message_id)
await self.channel_layer.group_send(
self.room_group_name,
{
'type': 'chat_message',
'message': msg,
'username': 'Server',
'message_id':  message_id
}
)

except jwt.ExpiredSignatureError:
await self.close(code=4001)
except jwt.InvalidTokenError:
await self.close(code=4002)
Теперь, поскольку я меняю «lobby_phase» при добавлении player2 и сразу после этого беру значение для трансляции непосредственно из экземпляра моей модели, я ожидаю, что player1 при обновлении будет иметь обновленное значениеlobby_phase, чего не происходит, остается значение по умолчанию «ожидание». Вместо этого обновление p2 получает правильное значение, и это несоответствие сводит меня с ума.

журналы для справки

[img]https:/ /i.sstatic.net/cWzf6ufg.png[/img]

p1, он же Кеке, подключается, напечатайте «lobby_phase» и будет добавлено как player1, снова напечатайте «lobby_phase».

p2 он же Баба подключается, печатает «lobby_phase», добавляется как p2, меняет значение «lobby_phase», транслирует «phase_change», принимая значение непосредственно из базы данных, печатает «lobby_phase» (и это правильно).

клиент 2 обновляется и на обоих печатается имеет правильное значение фазы лобби, в то время как клиент1 обновляется и снова «ждет».
Я предполагаю, что проблема связана с асинхронными функциями, вызываемыми в моей базе данных, но это все равно не поможет какой-либо смысл для клиентов иметь разные значения, так что я, честно говоря, понятия не имею.
По крайней мере, я уверен, что проблема должна быть в бэкэнде и что интерфейс меняет пользовательский интерфейс в зависимости от полученной фазы. ..

Подробнее здесь: https://stackoverflow.com/questions/787 ... ango-chann
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Python»