mirror of
https://github.com/danbulant/slightlyComplicatedTicTacToe
synced 2026-07-08 04:30:38 +00:00
working room creation and list
This commit is contained in:
parent
7246ddea7b
commit
2206e2774f
17 changed files with 1787 additions and 26 deletions
|
|
@ -24,5 +24,9 @@
|
||||||
"typescript": "^4.7.4",
|
"typescript": "^4.7.4",
|
||||||
"vite": "^3.0.0"
|
"vite": "^3.0.0"
|
||||||
},
|
},
|
||||||
"type": "module"
|
"type": "module",
|
||||||
|
"dependencies": {
|
||||||
|
"howler": "^2.2.3",
|
||||||
|
"phaser": "^3.55.2"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,24 @@
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
||||||
<meta name="viewport" content="width=device-width" />
|
<meta name="viewport" content="width=device-width" />
|
||||||
|
<style>
|
||||||
|
body, html {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
height: 100vh;
|
||||||
|
width: 100vw;
|
||||||
|
overflow: hidden;
|
||||||
|
font-family: "Square", "Squareo", monospace;
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Square';
|
||||||
|
src: url("/assets/Square.ttf") format("truetype");
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Squareo';
|
||||||
|
src: url("/assets/Squareo.ttf") format("truetype");
|
||||||
|
}
|
||||||
|
</style>
|
||||||
%sveltekit.head%
|
%sveltekit.head%
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
|
||||||
|
|
@ -126,7 +126,7 @@ class ConnectedClient extends EventTarget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class WebsocketConnection extends EventTarget {
|
export class WebsocketConnection extends EventTarget {
|
||||||
ws: WebSocket;
|
ws: WebSocket;
|
||||||
fast: Map<string, ConnectedClient> = new Map();
|
fast: Map<string, ConnectedClient> = new Map();
|
||||||
roomName: string | null = null;
|
roomName: string | null = null;
|
||||||
|
|
@ -140,9 +140,20 @@ class WebsocketConnection extends EventTarget {
|
||||||
}
|
}
|
||||||
|
|
||||||
connect() {
|
connect() {
|
||||||
this.ws = new WebSocket("ws://" + location.hostname + ":8080");
|
this.ws = new WebSocket("ws://" + location.hostname + ":8080/?name=" + encodeURIComponent(this.name));
|
||||||
this.ws.addEventListener("open", () => {
|
this.ws.addEventListener("open", (e) => {
|
||||||
console.log("WS ready");
|
console.log("WS ready");
|
||||||
|
this.refreshList();
|
||||||
|
});
|
||||||
|
this.ws.addEventListener("close", (e) => {
|
||||||
|
console.log("WS closed");
|
||||||
|
lastError.set(e.reason || "Connection closed");
|
||||||
|
connection.set(null);
|
||||||
|
});
|
||||||
|
this.ws.addEventListener("error", (e) => {
|
||||||
|
console.error("WS error");
|
||||||
|
lastError.set("Connection error");
|
||||||
|
connection.set(null);
|
||||||
});
|
});
|
||||||
this.ws.addEventListener("message", (e) => {
|
this.ws.addEventListener("message", (e) => {
|
||||||
const msg = JSON.parse(e.data);
|
const msg = JSON.parse(e.data);
|
||||||
|
|
@ -193,32 +204,54 @@ class WebsocketConnection extends EventTarget {
|
||||||
}
|
}
|
||||||
this.fast.set(client, fast);
|
this.fast.set(client, fast);
|
||||||
}
|
}
|
||||||
|
// missing break on purpose
|
||||||
|
}
|
||||||
|
case "create": {
|
||||||
|
this.roomName = msg.name;
|
||||||
|
this.roomId = msg.id;
|
||||||
|
room.set({
|
||||||
|
name: msg.name,
|
||||||
|
id: msg.id
|
||||||
|
});
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case "leave": {
|
case "leave": {
|
||||||
const fast = this.fast.get(msg.name);
|
const fast = this.fast.get(msg.name);
|
||||||
if (!fast) return;
|
if (!fast) return;
|
||||||
fast.conn.close();
|
fast.conn.close();
|
||||||
this.fast.delete(msg.name);
|
this.fast.delete(msg.name);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case "left": {
|
case "left": {
|
||||||
console.log("Left room successfully");
|
console.log("Left room successfully");
|
||||||
this.roomName = null;
|
this.roomName = null;
|
||||||
this.roomId = null;
|
this.roomId = null;
|
||||||
|
room.set(null);
|
||||||
this.fast.forEach(connection => connection.conn.close());
|
this.fast.forEach(connection => connection.conn.close());
|
||||||
this.fast = new Map();
|
this.fast = new Map();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case "list": {
|
case "list": {
|
||||||
list.set(msg.rooms);
|
list.set(msg.rooms);
|
||||||
|
listLoading.set(false);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case "error": {
|
case "error": {
|
||||||
console.error(msg.e);
|
console.error(msg.e);
|
||||||
|
lastError.set(msg.e);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createGame(name: string) {
|
||||||
|
this.ws.send(JSON.stringify({ t: "create", name: name }));
|
||||||
|
}
|
||||||
|
|
||||||
refreshList() {
|
refreshList() {
|
||||||
this.ws.send(JSON.stringify({ t: "list" }));
|
this.ws.send(JSON.stringify({ t: "list" }));
|
||||||
|
listLoading.set(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
send(data: any) {
|
send(data: any) {
|
||||||
|
|
@ -227,4 +260,7 @@ class WebsocketConnection extends EventTarget {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const connection: Writable<WebsocketConnection|null> = writable(null);
|
export const connection: Writable<WebsocketConnection|null> = writable(null);
|
||||||
export const list: Writable<{ id: string, name: string, count: number }[]|null> = writable(null);
|
export const list: Writable<{ id: string, name: string, count: number }[]|null> = writable(null);
|
||||||
|
export const listLoading = writable(true);
|
||||||
|
export const lastError: Writable<string> = writable("");
|
||||||
|
export const room: Writable<{ name: string, id: string }|null> = writable(null);
|
||||||
0
client/src/lib/view/game/game.svelte
Normal file
0
client/src/lib/view/game/game.svelte
Normal file
49
client/src/lib/view/game/init.ts
Normal file
49
client/src/lib/view/game/init.ts
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
import { CANVAS, Game, Scale, WEBGL } from "phaser";
|
||||||
|
import { GameScene } from "./scene";
|
||||||
|
|
||||||
|
var ratio = window.devicePixelRatio || 1;
|
||||||
|
export function resize() {
|
||||||
|
if(!game || !htmlcanvas) return;
|
||||||
|
try {
|
||||||
|
game.scale.resize(htmlcanvas.parentElement!.clientWidth * ratio, htmlcanvas.parentElement!.clientHeight * ratio);
|
||||||
|
} catch(e) {
|
||||||
|
// @ts-ignore
|
||||||
|
console.error(e, new ErrorEvent(e.type, { colno: e.colno, error: e, lineno: e.lineno, message: e.message, filename: e.filename }));
|
||||||
|
window.dispatchEvent(new ErrorEvent("error", e as any));
|
||||||
|
}
|
||||||
|
// console.log("size", htmlcanvas.parentElement!.clientWidth * ratio, htmlcanvas.parentElement!.clientHeight * ratio);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @type {HTMLCanvasElement} */
|
||||||
|
var htmlcanvas: HTMLCanvasElement;
|
||||||
|
/** @type {Game} */
|
||||||
|
var game: Game;
|
||||||
|
/** @type {GameScene} */
|
||||||
|
var gs: GameScene;
|
||||||
|
export function setCanvas(canvas: HTMLCanvasElement) {
|
||||||
|
htmlcanvas = canvas;
|
||||||
|
var ctx = canvas.getContext("webgl2") || canvas.getContext("webgl");
|
||||||
|
gs = new GameScene();
|
||||||
|
game = new Game({
|
||||||
|
canvas: canvas,
|
||||||
|
url: window.location.host,
|
||||||
|
hideBanner: true,
|
||||||
|
type: ctx ? WEBGL : CANVAS,
|
||||||
|
// @ts-ignore
|
||||||
|
context: ctx || canvas.getContext("2d"),
|
||||||
|
customEnvironment: false,
|
||||||
|
width: window.innerWidth * ratio,
|
||||||
|
height: window.innerHeight * ratio,
|
||||||
|
scale: {
|
||||||
|
mode: Scale.RESIZE
|
||||||
|
},
|
||||||
|
physics: {
|
||||||
|
default: "arcade",
|
||||||
|
},
|
||||||
|
title: "Multidie",
|
||||||
|
version: "0",
|
||||||
|
scene: [gs],
|
||||||
|
backgroundColor: "#01021B",
|
||||||
|
banner: false
|
||||||
|
});
|
||||||
|
}
|
||||||
28
client/src/lib/view/game/scene.ts
Normal file
28
client/src/lib/view/game/scene.ts
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
import Phaser, { Animations } from "phaser";
|
||||||
|
|
||||||
|
var fpsBuffer: number[] = [];
|
||||||
|
|
||||||
|
export class GameScene extends Phaser.Scene {
|
||||||
|
constructor() {
|
||||||
|
super({
|
||||||
|
key: "GameScene",
|
||||||
|
active: true,
|
||||||
|
physics: {
|
||||||
|
default: "arcade"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
unload() {}
|
||||||
|
preload() {}
|
||||||
|
|
||||||
|
create() {}
|
||||||
|
|
||||||
|
update(time: number, delta: number) {
|
||||||
|
fpsBuffer.push(delta);
|
||||||
|
if (fpsBuffer.length > 10) {
|
||||||
|
fpsBuffer.shift();
|
||||||
|
}
|
||||||
|
const fps = fpsBuffer.reduce((a, b) => a + b, 0) / fpsBuffer.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
151
client/src/lib/view/menu/list.svelte
Normal file
151
client/src/lib/view/menu/list.svelte
Normal file
|
|
@ -0,0 +1,151 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import { connection, lastError, list, listLoading } from "$lib/Websocket";
|
||||||
|
import { onMount } from "svelte";
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
let i = setInterval(() => {
|
||||||
|
$connection?.refreshList();
|
||||||
|
}, 2000);
|
||||||
|
|
||||||
|
return () => clearInterval(i);
|
||||||
|
});
|
||||||
|
|
||||||
|
let creatingGame = false;
|
||||||
|
let newGameName = "";
|
||||||
|
let error = "";
|
||||||
|
|
||||||
|
$: {
|
||||||
|
if (newGameName.length > 64) {
|
||||||
|
error = "Name is too long";
|
||||||
|
} else {
|
||||||
|
error = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$: {
|
||||||
|
if($lastError === "room_name_used") {
|
||||||
|
error = $lastError;
|
||||||
|
$lastError = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function submit() {
|
||||||
|
if (newGameName.length < 2) return error = "Name is too short";
|
||||||
|
if (newGameName.length > 64) return error = "Name is too long";
|
||||||
|
error = "Creating game...";
|
||||||
|
$connection!.createGame(newGameName);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if creatingGame}
|
||||||
|
<dialog open>
|
||||||
|
<input on:submit={submit} type="text" name="name" placeholder="GAME NAME" bind:value={newGameName}>
|
||||||
|
<div class="error">
|
||||||
|
{error}
|
||||||
|
</div>
|
||||||
|
<div class="controls">
|
||||||
|
<button on:click={() => creatingGame = false}>CANCEL</button>
|
||||||
|
<button on:click={submit}>SUBMIT</button>
|
||||||
|
</div>
|
||||||
|
</dialog>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<main>
|
||||||
|
<div class="flex">
|
||||||
|
<h1>Games - {$connection?.name}</h1>
|
||||||
|
<button on:click={() => creatingGame = true}>CREATE</button>
|
||||||
|
</div>
|
||||||
|
<div class="status">
|
||||||
|
{#if $listLoading} Loading... {/if}
|
||||||
|
</div>
|
||||||
|
<ul>
|
||||||
|
{#if $list}
|
||||||
|
{#each $list as $game}
|
||||||
|
<li class="flex">
|
||||||
|
<span>
|
||||||
|
{$game.name}
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
{$game.count}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
{/each}
|
||||||
|
{/if}
|
||||||
|
</ul>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
dialog {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
backdrop-filter: blur(20px) saturate(150%);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
gap: 0.25em;
|
||||||
|
}
|
||||||
|
dialog input {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
background-color: #85E65C;
|
||||||
|
color: #bd5ce6;
|
||||||
|
border: 10px solid #bd5ce6;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
background-color: #85E65C;
|
||||||
|
color: #bd5ce6;
|
||||||
|
}
|
||||||
|
main {
|
||||||
|
max-width: 700px;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
.flex {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
.status {
|
||||||
|
height: 1.5em;
|
||||||
|
}
|
||||||
|
ul {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
height: 2em;
|
||||||
|
line-height: 2em;
|
||||||
|
padding: 0.5em;
|
||||||
|
border: 1px solid #bd5ce6;
|
||||||
|
border-radius: 0;
|
||||||
|
margin: 0;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
width: 10em;
|
||||||
|
height: 3em;
|
||||||
|
border: 1px solid #bd5ce6;
|
||||||
|
border-radius: 0;
|
||||||
|
padding: 0.5em;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
border: 10px solid #bd5ce6;
|
||||||
|
background-color: #85E65C;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
button:active {
|
||||||
|
background-color: #bd5ce6;
|
||||||
|
color: #85E65C;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
76
client/src/lib/view/menu/nameChoose.svelte
Normal file
76
client/src/lib/view/menu/nameChoose.svelte
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
<script>
|
||||||
|
import { connection, lastError, WebsocketConnection } from "$lib/Websocket";
|
||||||
|
|
||||||
|
var name = "";
|
||||||
|
var error = "";
|
||||||
|
|
||||||
|
$: {
|
||||||
|
if(name.length > 64) {
|
||||||
|
error = "Name is too long";
|
||||||
|
} else {
|
||||||
|
error = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function submit() {
|
||||||
|
if (name.length < 2) return error = "Name is too short";
|
||||||
|
if (name.length > 64) return error = "Name is too long";
|
||||||
|
$connection = new WebsocketConnection(name);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<main>
|
||||||
|
<input on:submit={submit} type="text" name="name" placeholder="PLAYER NAME" bind:value={name}>
|
||||||
|
<div class="error">
|
||||||
|
{error || $lastError}
|
||||||
|
</div>
|
||||||
|
<button on:click={submit}>SUBMIT</button>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
main {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
background-color: #85E65C;
|
||||||
|
color: #bd5ce6;
|
||||||
|
}
|
||||||
|
.error {
|
||||||
|
height: 1.5em;
|
||||||
|
}
|
||||||
|
input {
|
||||||
|
width: 20em;
|
||||||
|
height: 2em;
|
||||||
|
border: 10px solid #bd5ce6;
|
||||||
|
border-radius: 0;
|
||||||
|
padding: 0.5em;
|
||||||
|
font-size: 1.5em;
|
||||||
|
background-color: #85E65C;
|
||||||
|
color: #bd5ce6;
|
||||||
|
font-family: inherit;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
width: 10em;
|
||||||
|
height: 3em;
|
||||||
|
border: 10px solid #bd5ce6;
|
||||||
|
background-color: #85E65C;
|
||||||
|
color: #bd5ce6;
|
||||||
|
border-radius: 0;
|
||||||
|
padding: 0.5em;
|
||||||
|
font-size: 1.5em;
|
||||||
|
font-family: inherit;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
button:active {
|
||||||
|
background-color: #bd5ce6;
|
||||||
|
color: #85E65C;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -1,2 +1,14 @@
|
||||||
<h1>Welcome to SvelteKit</h1>
|
<script>
|
||||||
<p>Visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to read the documentation</p>
|
import Game from "$lib/view/game/game.svelte";
|
||||||
|
import List from "$lib/view/menu/list.svelte";
|
||||||
|
import NameChoose from "$lib/view/menu/nameChoose.svelte";
|
||||||
|
import { connection, room } from "$lib/Websocket";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if !$connection}
|
||||||
|
<NameChoose />
|
||||||
|
{:else if !$room}
|
||||||
|
<List />
|
||||||
|
{:else}
|
||||||
|
<Game />
|
||||||
|
{/if}
|
||||||
|
|
@ -8,6 +8,11 @@
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"strict": true
|
"strict": true,
|
||||||
|
|
||||||
|
"paths": {
|
||||||
|
"$lib": ["src/lib"],
|
||||||
|
"$lib/*": ["src/lib/*"]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1381
pnpm-lock.yaml
1381
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
|
|
@ -33,23 +33,19 @@ const clients = new Map();
|
||||||
require("uWebSockets.js")
|
require("uWebSockets.js")
|
||||||
.App({})
|
.App({})
|
||||||
.ws("/", {
|
.ws("/", {
|
||||||
idleTimeout: 30,
|
idleTimeout: 32,
|
||||||
maxPayloadLength: 16 * 1024 * 1024,
|
maxPayloadLength: 16 * 1024 * 1024,
|
||||||
upgrade: (res, req, context) => {
|
upgrade: (res, req, context) => {
|
||||||
console.log(
|
console.log(
|
||||||
`An Http connection wants to become WebSocket, URL: ${req.getUrl()}!`
|
`An Http connection wants to become WebSocket, URL: ${req.getUrl()}!`
|
||||||
);
|
);
|
||||||
|
let name = req.getQuery("name").trim().toLocaleLowerCase();
|
||||||
const url = req.getUrl();
|
|
||||||
const parsed = new URL(url);
|
|
||||||
let name = parsed.searchParams.get("name");
|
|
||||||
if (!name || typeof name !== "string" || name.length < 2 || name.length > 64 || !name.trim()) return res.end("invalid_name");
|
if (!name || typeof name !== "string" || name.length < 2 || name.length > 64 || !name.trim()) return res.end("invalid_name");
|
||||||
name = name.trim();
|
name = name.trim();
|
||||||
if (clients.forEach(client => client.name === name)) return res.end("name_used");
|
if ([...clients.values()].find(client => client.name === name)) return res.end("name_used");
|
||||||
/* This immediately calls open handler, you must not use res after this call */
|
/* This immediately calls open handler, you must not use res after this call */
|
||||||
res.upgrade(
|
res.upgrade(
|
||||||
{
|
{
|
||||||
url,
|
|
||||||
name
|
name
|
||||||
},
|
},
|
||||||
/* Spell these correctly */
|
/* Spell these correctly */
|
||||||
|
|
@ -62,13 +58,13 @@ require("uWebSockets.js")
|
||||||
open: (ws) => {
|
open: (ws) => {
|
||||||
console.log(
|
console.log(
|
||||||
"CON",
|
"CON",
|
||||||
ws.url,
|
|
||||||
ws.name,
|
ws.name,
|
||||||
decoder.decode(ws.getRemoteAddressAsText())
|
decoder.decode(ws.getRemoteAddressAsText())
|
||||||
);
|
);
|
||||||
clients.set(ws, {
|
clients.set(ws, {
|
||||||
connection: ws,
|
connection: ws,
|
||||||
name: ws.name,
|
name: ws.name,
|
||||||
|
ipa: decoder.decode(ws.getRemoteAddressAsText()),
|
||||||
room: null
|
room: null
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
@ -83,9 +79,10 @@ require("uWebSockets.js")
|
||||||
}
|
}
|
||||||
case "create": {
|
case "create": {
|
||||||
const client = clients.get(ws);
|
const client = clients.get(ws);
|
||||||
if(client.room) return ws.send(JSON.stringify({t: "error", m: "already_in_room"}));
|
if(client.room) return ws.send(JSON.stringify({t: "error", e: "already_in_room"}));
|
||||||
const name = data.name.trim();
|
const name = data.name.trim().toLocaleLowerCase();
|
||||||
if (!name || typeof name !== "string" || name.length < 2 || name.length > 64 || !name.trim()) return res.send(JSON.stringify({t: "error", m: "invalid_room_name"}));
|
if (!name || typeof name !== "string" || name.length < 2 || name.length > 64 || !name.trim()) return res.send(JSON.stringify({t: "error", e: "invalid_room_name"}));
|
||||||
|
if ([...rooms.values()].find(room => room.name === name)) return ws.send(JSON.stringify({t: "error", e: "room_name_used"}));
|
||||||
const room = {
|
const room = {
|
||||||
name: name,
|
name: name,
|
||||||
host: ws,
|
host: ws,
|
||||||
|
|
@ -99,8 +96,8 @@ require("uWebSockets.js")
|
||||||
case "leave": {
|
case "leave": {
|
||||||
const client = clients.get(ws);
|
const client = clients.get(ws);
|
||||||
const room = client.room;
|
const room = client.room;
|
||||||
if (!room) return ws.send(JSON.stringify({ t: "error", m: "room_not_found" }));
|
if (!room) return ws.send(JSON.stringify({ t: "error", e: "room_not_found" }));
|
||||||
if (!room.clients.includes(client)) return ws.send(JSON.stringify({ t: "error", m: "not_in_room" }));
|
if (!room.clients.includes(client)) return ws.send(JSON.stringify({ t: "error", e: "not_in_room" }));
|
||||||
room.clients.splice(room.clients.indexOf(client), 1);
|
room.clients.splice(room.clients.indexOf(client), 1);
|
||||||
if (room.clients.length === 0) {
|
if (room.clients.length === 0) {
|
||||||
rooms.delete(room.id);
|
rooms.delete(room.id);
|
||||||
|
|
@ -116,13 +113,15 @@ require("uWebSockets.js")
|
||||||
case "join": {
|
case "join": {
|
||||||
const client = clients.get(ws);
|
const client = clients.get(ws);
|
||||||
if (!client) return ws.end();
|
if (!client) return ws.end();
|
||||||
const room = client.room;
|
const room = rooms.get(msg.room);
|
||||||
if (!room) return ws.send(JSON.stringify({ t: "error", e: "room_not_found" }));
|
if (!room) return ws.send(JSON.stringify({ t: "error", e: "room_not_found" }));
|
||||||
|
if(client.room) return ws.send(JSON.stringify({ t: "error", e: "already_in_other_room" }));
|
||||||
if (room.clients.includes(client)) return ws.send(JSON.stringify({ t: "error", e: "already_in_room" }));
|
if (room.clients.includes(client)) return ws.send(JSON.stringify({ t: "error", e: "already_in_room" }));
|
||||||
|
if(room.clients.length > 5) return ws.send(JSON.stringify({ t: "error", e: "room_full" }));
|
||||||
room.clients.push(ws);
|
room.clients.push(ws);
|
||||||
ws.room = room;
|
ws.room = room;
|
||||||
room.clients.slice(0, -2).forEach(client => client.connection.send(JSON.stringify({ t: "join", id: room.id, client: client.name })));
|
room.clients.slice(0, -2).forEach(client => client.connection.send(JSON.stringify({ t: "join", id: room.id, client: client.name })));
|
||||||
ws.send(JSON.stringify({ t: "joined", id: room.id, client: client.name, clients: room.clients.map(t => t.name) }));
|
ws.send(JSON.stringify({ t: "joined", id: room.id, name: room.name, client: client.name, clients: room.clients.map(t => t.name) }));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "cand":
|
case "cand":
|
||||||
|
|
@ -138,7 +137,7 @@ require("uWebSockets.js")
|
||||||
targetClient.connection.send(JSON.stringify({ t: msg.t, id: room.id, source: client.name, d: msg.d }));
|
targetClient.connection.send(JSON.stringify({ t: msg.t, id: room.id, source: client.name, d: msg.d }));
|
||||||
}
|
}
|
||||||
case "list": {
|
case "list": {
|
||||||
ws.send(JSON.stringify({ t: "list", rooms: [...rooms.values()].map(t => ({ id: t.id, name: t.name, count: t.clients.length }))}));
|
ws.send(JSON.stringify({ t: "list", rooms: [...rooms.values()].filter(t => t.clients.length < 5).map(t => ({ id: t.id, name: t.name, count: t.clients.length }))}));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -147,9 +146,11 @@ require("uWebSockets.js")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
close: (ws, code, message) => {
|
close: (ws, code, message) => {
|
||||||
console.log("DIS", decoder.decode(ws.getRemoteAddressAsText()));
|
console.log("DIS1", ws);
|
||||||
if (clients.get(ws)) {
|
if (clients.get(ws)) {
|
||||||
let room = rooms.get(clients.get(ws));
|
const client = clients.get(ws);
|
||||||
|
console.log("DIS", client.name, client.ipa);
|
||||||
|
let room = client.room;
|
||||||
if (room) {
|
if (room) {
|
||||||
room.clients.splice(room.clients.indexOf(ws), 1);
|
room.clients.splice(room.clients.indexOf(ws), 1);
|
||||||
if (room.clients.length === 0) {
|
if (room.clients.length === 0) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue