core: recreation of matchmaking, add: matchmaking support multiple modes
This commit is contained in:
parent
278e2cbe54
commit
6c39a13aca
@ -14,7 +14,7 @@ class Channel {
|
|||||||
|
|
||||||
// reload = function to use when we receive a message
|
// reload = function to use when we receive a message
|
||||||
async connect(reload) {
|
async connect(reload) {
|
||||||
let url = `ws://${window.location.host}/ws/chat/${this.channel_id}/`;
|
let url = `wss://${window.location.host}/ws/chat/${this.channel_id}/`;
|
||||||
|
|
||||||
this.chatSocket = new WebSocket(url);
|
this.chatSocket = new WebSocket(url);
|
||||||
this.chatSocket.onmessage = (event) =>{
|
this.chatSocket.onmessage = (event) =>{
|
||||||
|
@ -11,18 +11,21 @@ class MatchMaking
|
|||||||
* @type {Client}
|
* @type {Client}
|
||||||
*/
|
*/
|
||||||
this.client = client
|
this.client = client
|
||||||
|
this.searching = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
async start(func)
|
async start(func, mode)
|
||||||
{
|
{
|
||||||
if (!await this.client.isAuthentificate())
|
if (!await this.client.isAuthentificate())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
let url = `wss://${window.location.host}/ws/matchmaking/`;
|
let url = `wss://${window.location.host}/ws/matchmaking/${mode}`;
|
||||||
|
|
||||||
this._chatSocket = new WebSocket(url);
|
this._socket = new WebSocket(url);
|
||||||
|
|
||||||
this._chatSocket.onmessage = function (event) {
|
this.searching = true;
|
||||||
|
|
||||||
|
this._socket.onmessage = function (event) {
|
||||||
const data = JSON.parse(event.data);
|
const data = JSON.parse(event.data);
|
||||||
func(data.game_id)
|
func(data.game_id)
|
||||||
};
|
};
|
||||||
@ -30,7 +33,8 @@ class MatchMaking
|
|||||||
|
|
||||||
async stop()
|
async stop()
|
||||||
{
|
{
|
||||||
this._chatSocket.close()
|
this.searching = false;
|
||||||
|
this._socket.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,18 +7,42 @@ function game_found(game_id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default class extends AbstractView {
|
export default class extends AbstractView {
|
||||||
constructor(params) {
|
constructor(params)
|
||||||
super(params, "Dashboard");
|
{
|
||||||
|
super(params, "Matchmaking");
|
||||||
|
}
|
||||||
|
|
||||||
|
async press_button()
|
||||||
|
{
|
||||||
|
if (client.matchmaking.searching)
|
||||||
|
{
|
||||||
|
client.matchmaking.stop();
|
||||||
|
document.getElementById("button").value = "Find a game"
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await this.matchmaking();
|
||||||
|
document.getElementById("button").value = "Stop matchmaking"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async matchmaking()
|
||||||
|
{
|
||||||
|
let nb_players = document.getElementById("nb_players-input").value
|
||||||
|
|
||||||
|
client.matchmaking.start(game_found, nb_players);
|
||||||
}
|
}
|
||||||
|
|
||||||
async postInit()
|
async postInit()
|
||||||
{
|
{
|
||||||
await client.matchmaking.start(game_found)
|
document.getElementById("button").onclick = this.matchmaking
|
||||||
}
|
}
|
||||||
|
|
||||||
async getHtml() {
|
async getHtml() {
|
||||||
return `
|
return `
|
||||||
<h1>finding<h1>
|
<h1>Select mode<h1>
|
||||||
|
<input type="number" value="2" id="nb_players-input">
|
||||||
|
<input type="button" value="Find a game" id="button">
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ class GameModel(models.Model):
|
|||||||
|
|
||||||
finished = models.BooleanField(default=False)
|
finished = models.BooleanField(default=False)
|
||||||
started = models.BooleanField(default=False)
|
started = models.BooleanField(default=False)
|
||||||
winner_id = models.IntegerField(null=True, blank=True)
|
winner_id = models.IntegerField(default=-1)
|
||||||
|
|
||||||
def create(self, users_id: [int]):
|
def create(self, users_id: [int]):
|
||||||
self.save()
|
self.save()
|
||||||
|
@ -6,8 +6,7 @@ from games.models import GameModel
|
|||||||
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
queue_id: [int] = []
|
from .models import Waiter, WaitingRoom, WaitingRoomManager, normal
|
||||||
queue_ws: [WebsocketConsumer] = []
|
|
||||||
|
|
||||||
class MatchMaking(WebsocketConsumer):
|
class MatchMaking(WebsocketConsumer):
|
||||||
|
|
||||||
@ -24,25 +23,20 @@ class MatchMaking(WebsocketConsumer):
|
|||||||
|
|
||||||
self.channel_layer.group_add(self.group_name, self.channel_name)
|
self.channel_layer.group_add(self.group_name, self.channel_name)
|
||||||
|
|
||||||
self.accept()
|
self.mode = int(self.scope['url_route']['kwargs']['mode'])
|
||||||
|
self.group_name = self.mode
|
||||||
|
|
||||||
global queue_id, queue_ws
|
waiting_room: WaitingRoom = normal.get(self.mode)
|
||||||
queue_id.append(user.pk)
|
waiting_room.append(Waiter(user.pk, self))
|
||||||
queue_ws.append(self)
|
|
||||||
|
|
||||||
if len(set(queue_id)) == 2:
|
|
||||||
game_id: int = GameModel().create(set(queue_id))
|
|
||||||
event = {"game_id": game_id}
|
|
||||||
for ws in queue_ws:
|
|
||||||
ws.send(text_data=json.dumps({'game_id': game_id}))
|
|
||||||
queue_id.clear()
|
|
||||||
queue_ws.clear()
|
|
||||||
|
|
||||||
|
print(len(waiting_room), "/", self.mode, [len(waiting_room),self.mode])
|
||||||
|
if (len(waiting_room) == self.mode):
|
||||||
|
game_id: int = GameModel().create(waiting_room.get_users_id())
|
||||||
|
waiting_room.broadcast({"detail": "Game found !", "game_id": game_id})
|
||||||
|
waiting_room.clear()
|
||||||
|
|
||||||
def disconnect(self, close_code):
|
def disconnect(self, close_code):
|
||||||
user: User = self.scope["user"]
|
waiting_room: WaitingRoom = normal.get(self.mode)
|
||||||
global queue_id, queue_ws
|
waiter: Waiter = waiting_room.get_waiter_by_socket(self)
|
||||||
if (user.pk in queue_id):
|
if (waiter is not None):
|
||||||
queue_ws.pop(queue_id.index(user.pk))
|
waiting_room.remove(self.scope["user"].pk)
|
||||||
queue_id.remove(user.pk)
|
|
||||||
self.channel_layer.group_discard(self.group_name, self.channel_name)
|
|
@ -1,11 +1,92 @@
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
|
from channels.generic.websocket import WebsocketConsumer
|
||||||
|
import json
|
||||||
|
|
||||||
# Create your models here.
|
# Create your models here.
|
||||||
in_matchmaking = {
|
class Waiter:
|
||||||
"tournaments": {
|
|
||||||
|
|
||||||
},
|
def __init__(self, user_id: int, socket: WebsocketConsumer):
|
||||||
"normal": {
|
self.user_id: int = user_id
|
||||||
|
self.socket: WebsocketConsumer = socket
|
||||||
|
|
||||||
}
|
def send(self, data: dict):
|
||||||
}
|
self.socket.send(text_data=json.dumps(data))
|
||||||
|
|
||||||
|
def accept(self):
|
||||||
|
self.socket.accept()
|
||||||
|
|
||||||
|
def disconnect(self):
|
||||||
|
self.socket.disconnect()
|
||||||
|
|
||||||
|
def __eq__(self, obj):
|
||||||
|
return self.user_id == obj.user_id
|
||||||
|
|
||||||
|
class WaitingRoom:
|
||||||
|
|
||||||
|
def __init__(self, waiting_room_manager, mode: int):
|
||||||
|
self._waiter_list: [Waiter] = []
|
||||||
|
self._mode: int = mode
|
||||||
|
self._waiting_room_manager = waiting_room_manager
|
||||||
|
|
||||||
|
def broadcast(self, data: dict):
|
||||||
|
for waiter in self._waiter_list:
|
||||||
|
waiter: Waiter
|
||||||
|
waiter.send(data)
|
||||||
|
|
||||||
|
def clear(self):
|
||||||
|
self._waiter_list.clear()
|
||||||
|
|
||||||
|
def get_waiter_by_socket(self, socket: WebsocketConsumer):
|
||||||
|
for waiter in self._waiter_list:
|
||||||
|
waiter: Waiter
|
||||||
|
if (waiter.socket is socket):
|
||||||
|
return waiter
|
||||||
|
return None
|
||||||
|
|
||||||
|
def append(self, waiter: Waiter):
|
||||||
|
|
||||||
|
self.remove(waiter)
|
||||||
|
waiter.accept()
|
||||||
|
self._waiter_list.append(waiter)
|
||||||
|
|
||||||
|
def remove(self, users_id):
|
||||||
|
for waiter in self._waiter_list:
|
||||||
|
waiter: Waiter = waiter
|
||||||
|
if (waiter == users_id):
|
||||||
|
waiter.disconnect()
|
||||||
|
if (self.empty()):
|
||||||
|
self._waiting_room_manager.remove(self)
|
||||||
|
return
|
||||||
|
|
||||||
|
def empty(self):
|
||||||
|
for _ in self._waiter_list:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def get_users_id(self):
|
||||||
|
return [waiter.user_id for waiter in self._waiter_list]
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self._waiter_list)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class WaitingRoomManager:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self._waiting_rooms: [WaitingRoom] = []
|
||||||
|
|
||||||
|
def get(self, mode: int):
|
||||||
|
for waiting_room in self._waiting_rooms:
|
||||||
|
waiting_room: WaitingRoom = waiting_room
|
||||||
|
if (waiting_room._mode == mode):
|
||||||
|
return waiting_room
|
||||||
|
tmp: WaitingRoom = WaitingRoom(self, mode)
|
||||||
|
self._waiting_rooms.append(tmp)
|
||||||
|
return tmp
|
||||||
|
|
||||||
|
def remove(self, waiting_room: WaitingRoom):
|
||||||
|
self._waiting_rooms.remove(waiting_room)
|
||||||
|
|
||||||
|
normal: WaitingRoomManager = WaitingRoomManager()
|
@ -2,5 +2,5 @@ from django.urls import re_path
|
|||||||
from . import consumers
|
from . import consumers
|
||||||
|
|
||||||
websocket_urlpatterns = [
|
websocket_urlpatterns = [
|
||||||
re_path(r'ws/matchmaking/', consumers.MatchMaking.as_asgi())
|
re_path(r'ws/matchmaking/(?P<mode>\d+)$', consumers.MatchMaking.as_asgi())
|
||||||
]
|
]
|
||||||
|
@ -7,7 +7,6 @@ from django.http import HttpRequest
|
|||||||
from django.contrib.auth import login
|
from django.contrib.auth import login
|
||||||
from django.db.models import QuerySet
|
from django.db.models import QuerySet
|
||||||
|
|
||||||
from matchmaking.models import in_matchmaking
|
|
||||||
from .models import TournamentModel
|
from .models import TournamentModel
|
||||||
from .serializers import TournamentSerializer
|
from .serializers import TournamentSerializer
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user