mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-25 19:24:36 +00:00
stop fetching public lobbies when game starts
This commit is contained in:
+125
-105
@@ -1,10 +1,10 @@
|
||||
import { GameRunner, joinLobby } from "./GameRunner";
|
||||
import backgroundImage from '../../resources/images/TerrainMapFrontPage.png';
|
||||
import favicon from '../../resources/images/Favicon.svg';
|
||||
import backgroundImage from "../../resources/images/TerrainMapFrontPage.png";
|
||||
import favicon from "../../resources/images/Favicon.svg";
|
||||
|
||||
import './PublicLobby';
|
||||
import './UsernameInput';
|
||||
import './styles.css';
|
||||
import "./PublicLobby";
|
||||
import "./UsernameInput";
|
||||
import "./styles.css";
|
||||
import { UsernameInput } from "./UsernameInput";
|
||||
import { SinglePlayerModal } from "./SinglePlayerModal";
|
||||
import { HostLobbyModal as HostPrivateLobbyModal } from "./HostLobbyModal";
|
||||
@@ -12,132 +12,152 @@ import { JoinPrivateLobbyModal } from "./JoinPrivateLobbyModal";
|
||||
import { generateID } from "../core/Util";
|
||||
import { generateCryptoRandomUUID } from "./Utils";
|
||||
import { consolex } from "../core/Consolex";
|
||||
import { PublicLobby } from "./PublicLobby";
|
||||
|
||||
class Client {
|
||||
private gameStop: () => void
|
||||
private gameStop: () => void;
|
||||
|
||||
private usernameInput: UsernameInput | null = null;
|
||||
private usernameInput: UsernameInput | null = null;
|
||||
|
||||
private joinModal: JoinPrivateLobbyModal
|
||||
constructor() {
|
||||
private joinModal: JoinPrivateLobbyModal;
|
||||
private publicLobby: PublicLobby;
|
||||
constructor() {}
|
||||
|
||||
initialize(): void {
|
||||
this.usernameInput = document.querySelector(
|
||||
"username-input"
|
||||
) as UsernameInput;
|
||||
if (!this.usernameInput) {
|
||||
consolex.warn("Username input element not found");
|
||||
}
|
||||
window.addEventListener("beforeunload", (event) => {
|
||||
consolex.log("Browser is closing");
|
||||
if (this.gameStop != null) {
|
||||
this.gameStop();
|
||||
}
|
||||
});
|
||||
|
||||
initialize(): void {
|
||||
this.usernameInput = document.querySelector('username-input') as UsernameInput;
|
||||
if (!this.usernameInput) {
|
||||
consolex.warn('Username input element not found');
|
||||
setFavicon();
|
||||
document.addEventListener("join-lobby", this.handleJoinLobby.bind(this));
|
||||
document.addEventListener("leave-lobby", this.handleLeaveLobby.bind(this));
|
||||
document.addEventListener(
|
||||
"single-player",
|
||||
this.handleSinglePlayer.bind(this)
|
||||
);
|
||||
|
||||
const spModal = document.querySelector(
|
||||
"single-player-modal"
|
||||
) as SinglePlayerModal;
|
||||
spModal instanceof SinglePlayerModal;
|
||||
document.getElementById("single-player").addEventListener("click", () => {
|
||||
if (this.usernameInput.isValid()) {
|
||||
spModal.open();
|
||||
}
|
||||
});
|
||||
|
||||
this.publicLobby = document.querySelector("public-lobby") as PublicLobby;
|
||||
|
||||
const hostModal = document.querySelector(
|
||||
"host-lobby-modal"
|
||||
) as HostPrivateLobbyModal;
|
||||
hostModal instanceof HostPrivateLobbyModal;
|
||||
document
|
||||
.getElementById("host-lobby-button")
|
||||
.addEventListener("click", () => {
|
||||
if (this.usernameInput.isValid()) {
|
||||
hostModal.open();
|
||||
}
|
||||
window.addEventListener('beforeunload', (event) => {
|
||||
consolex.log('Browser is closing');
|
||||
if (this.gameStop != null) {
|
||||
this.gameStop()
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
setFavicon()
|
||||
document.addEventListener('join-lobby', this.handleJoinLobby.bind(this));
|
||||
document.addEventListener('leave-lobby', this.handleLeaveLobby.bind(this));
|
||||
document.addEventListener('single-player', this.handleSinglePlayer.bind(this));
|
||||
|
||||
|
||||
const spModal = document.querySelector('single-player-modal') as SinglePlayerModal;
|
||||
spModal instanceof SinglePlayerModal
|
||||
document.getElementById('single-player').addEventListener('click', () => {
|
||||
if (this.usernameInput.isValid()) {
|
||||
spModal.open();
|
||||
}
|
||||
})
|
||||
|
||||
const hostModal = document.querySelector('host-lobby-modal') as HostPrivateLobbyModal;
|
||||
hostModal instanceof HostPrivateLobbyModal
|
||||
document.getElementById('host-lobby-button').addEventListener('click', () => {
|
||||
if (this.usernameInput.isValid()) {
|
||||
hostModal.open();
|
||||
}
|
||||
})
|
||||
|
||||
this.joinModal = document.querySelector('join-private-lobby-modal') as JoinPrivateLobbyModal;
|
||||
this.joinModal instanceof JoinPrivateLobbyModal
|
||||
document.getElementById('join-private-lobby-button').addEventListener('click', () => {
|
||||
if (this.usernameInput.isValid()) {
|
||||
this.joinModal.open();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private async handleJoinLobby(event: CustomEvent) {
|
||||
const lobby = event.detail.lobby
|
||||
consolex.log(`joining lobby ${lobby.id}`)
|
||||
if (this.gameStop != null) {
|
||||
consolex.log('joining lobby, stopping existing game')
|
||||
this.gameStop()
|
||||
this.joinModal = document.querySelector(
|
||||
"join-private-lobby-modal"
|
||||
) as JoinPrivateLobbyModal;
|
||||
this.joinModal instanceof JoinPrivateLobbyModal;
|
||||
document
|
||||
.getElementById("join-private-lobby-button")
|
||||
.addEventListener("click", () => {
|
||||
if (this.usernameInput.isValid()) {
|
||||
this.joinModal.open();
|
||||
}
|
||||
this.gameStop = joinLobby(
|
||||
{
|
||||
gameType: event.detail.gameType,
|
||||
playerName: (): string => this.usernameInput.getCurrentUsername(),
|
||||
gameID: lobby.id,
|
||||
persistentID: getPersistentIDFromCookie(),
|
||||
playerID: generateID(),
|
||||
clientID: generateID(),
|
||||
map: event.detail.map,
|
||||
difficulty: event.detail.difficulty,
|
||||
},
|
||||
() => this.joinModal.close()
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async handleLeaveLobby(event: CustomEvent) {
|
||||
if (this.gameStop == null) {
|
||||
return
|
||||
}
|
||||
consolex.log('leaving lobby, cancelling game')
|
||||
this.gameStop()
|
||||
this.gameStop = null
|
||||
private async handleJoinLobby(event: CustomEvent) {
|
||||
const lobby = event.detail.lobby;
|
||||
consolex.log(`joining lobby ${lobby.id}`);
|
||||
if (this.gameStop != null) {
|
||||
consolex.log("joining lobby, stopping existing game");
|
||||
this.gameStop();
|
||||
}
|
||||
this.gameStop = joinLobby(
|
||||
{
|
||||
gameType: event.detail.gameType,
|
||||
playerName: (): string => this.usernameInput.getCurrentUsername(),
|
||||
gameID: lobby.id,
|
||||
persistentID: getPersistentIDFromCookie(),
|
||||
playerID: generateID(),
|
||||
clientID: generateID(),
|
||||
map: event.detail.map,
|
||||
difficulty: event.detail.difficulty,
|
||||
},
|
||||
() => {
|
||||
this.joinModal.close();
|
||||
this.publicLobby.stop();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private async handleSinglePlayer(event: CustomEvent) {
|
||||
alert('coming soon')
|
||||
private async handleLeaveLobby(event: CustomEvent) {
|
||||
if (this.gameStop == null) {
|
||||
return;
|
||||
}
|
||||
consolex.log("leaving lobby, cancelling game");
|
||||
this.gameStop();
|
||||
this.gameStop = null;
|
||||
}
|
||||
|
||||
private async handleSinglePlayer(event: CustomEvent) {
|
||||
alert("coming soon");
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the client when the DOM is loaded
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
new Client().initialize();
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
new Client().initialize();
|
||||
});
|
||||
|
||||
document.body.style.backgroundImage = `url(${backgroundImage})`;
|
||||
|
||||
function setFavicon(): void {
|
||||
const link = document.createElement('link');
|
||||
link.type = 'image/x-icon';
|
||||
link.rel = 'shortcut icon';
|
||||
link.href = favicon;
|
||||
document.head.appendChild(link);
|
||||
const link = document.createElement("link");
|
||||
link.type = "image/x-icon";
|
||||
link.rel = "shortcut icon";
|
||||
link.href = favicon;
|
||||
document.head.appendChild(link);
|
||||
}
|
||||
|
||||
// WARNING: DO NOT EXPOSE THIS ID
|
||||
export function getPersistentIDFromCookie(): string {
|
||||
const COOKIE_NAME = 'player_persistent_id'
|
||||
const COOKIE_NAME = "player_persistent_id";
|
||||
|
||||
// Try to get existing cookie
|
||||
const cookies = document.cookie.split(';')
|
||||
for (let cookie of cookies) {
|
||||
const [cookieName, cookieValue] = cookie.split('=').map(c => c.trim())
|
||||
if (cookieName === COOKIE_NAME) {
|
||||
return cookieValue
|
||||
}
|
||||
// Try to get existing cookie
|
||||
const cookies = document.cookie.split(";");
|
||||
for (let cookie of cookies) {
|
||||
const [cookieName, cookieValue] = cookie.split("=").map((c) => c.trim());
|
||||
if (cookieName === COOKIE_NAME) {
|
||||
return cookieValue;
|
||||
}
|
||||
}
|
||||
|
||||
// If no cookie exists, create new ID and set cookie
|
||||
const newID = generateCryptoRandomUUID()
|
||||
document.cookie = [
|
||||
`${COOKIE_NAME}=${newID}`,
|
||||
`max-age=${5 * 365 * 24 * 60 * 60}`, // 5 years
|
||||
'path=/',
|
||||
'SameSite=Strict',
|
||||
'Secure'
|
||||
].join(';')
|
||||
// If no cookie exists, create new ID and set cookie
|
||||
const newID = generateCryptoRandomUUID();
|
||||
document.cookie = [
|
||||
`${COOKIE_NAME}=${newID}`,
|
||||
`max-age=${5 * 365 * 24 * 60 * 60}`, // 5 years
|
||||
"path=/",
|
||||
"SameSite=Strict",
|
||||
"Secure",
|
||||
].join(";");
|
||||
|
||||
return newID
|
||||
}
|
||||
return newID;
|
||||
}
|
||||
|
||||
+100
-83
@@ -1,18 +1,18 @@
|
||||
import { LitElement, html, css } from 'lit';
|
||||
import { customElement, state } from 'lit/decorators.js';
|
||||
import { LitElement, html, css } from "lit";
|
||||
import { customElement, state } from "lit/decorators.js";
|
||||
import { Lobby } from "../core/Schemas";
|
||||
import { Difficulty, GameMap, GameType } from '../core/game/Game';
|
||||
import { consolex } from '../core/Consolex';
|
||||
import { Difficulty, GameMap, GameType } from "../core/game/Game";
|
||||
import { consolex } from "../core/Consolex";
|
||||
|
||||
@customElement('public-lobby')
|
||||
@customElement("public-lobby")
|
||||
export class PublicLobby extends LitElement {
|
||||
@state() private lobbies: Lobby[] = [];
|
||||
@state() private isLobbyHighlighted: boolean = false;
|
||||
private lobbiesInterval: number | null = null;
|
||||
@state() private lobbies: Lobby[] = [];
|
||||
@state() private isLobbyHighlighted: boolean = false;
|
||||
private lobbiesInterval: number | null = null;
|
||||
|
||||
private currLobby: Lobby = null
|
||||
private currLobby: Lobby = null;
|
||||
|
||||
static styles = css`
|
||||
static styles = css`
|
||||
/* Add your styles here, based on your existing CSS */
|
||||
.lobby-button {
|
||||
display: flex;
|
||||
@@ -22,7 +22,7 @@ export class PublicLobby extends LitElement {
|
||||
width: 100%;
|
||||
max-width: 20rem;
|
||||
margin: 0 auto;
|
||||
padding: .5rem 1rem;
|
||||
padding: 0.5rem 1rem;
|
||||
background-color: #2563eb;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
@@ -42,90 +42,107 @@ export class PublicLobby extends LitElement {
|
||||
background-color: #15803d;
|
||||
}
|
||||
|
||||
.lobby-name { font-size: 1.2rem; }
|
||||
.lobby-timer { font-size: 1rem; }
|
||||
.player-count { font-size: 1rem; }
|
||||
.lobby-name {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
.lobby-timer {
|
||||
font-size: 1rem;
|
||||
}
|
||||
.player-count {
|
||||
font-size: 1rem;
|
||||
}
|
||||
`;
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
this.fetchAndUpdateLobbies(); // Fetch immediately on start
|
||||
this.lobbiesInterval = window.setInterval(() => this.fetchAndUpdateLobbies(), 1000);
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
this.fetchAndUpdateLobbies(); // Fetch immediately on start
|
||||
this.lobbiesInterval = window.setInterval(
|
||||
() => this.fetchAndUpdateLobbies(),
|
||||
1000
|
||||
);
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
super.disconnectedCallback();
|
||||
this.stop();
|
||||
}
|
||||
|
||||
public stop() {
|
||||
if (this.lobbiesInterval !== null) {
|
||||
clearInterval(this.lobbiesInterval);
|
||||
this.lobbiesInterval = null;
|
||||
}
|
||||
}
|
||||
|
||||
private async fetchAndUpdateLobbies(): Promise<void> {
|
||||
try {
|
||||
const lobbies = await this.fetchLobbies();
|
||||
this.lobbies = lobbies;
|
||||
} catch (error) {
|
||||
consolex.error("Error fetching and updating lobbies:", error);
|
||||
}
|
||||
}
|
||||
|
||||
async fetchLobbies(): Promise<Lobby[]> {
|
||||
const url = "/lobbies";
|
||||
try {
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
const data = await response.json();
|
||||
return data.lobbies;
|
||||
} catch (error) {
|
||||
consolex.error("Error fetching lobbies:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.lobbies.length === 0) {
|
||||
return html``;
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
super.disconnectedCallback();
|
||||
if (this.lobbiesInterval !== null) {
|
||||
clearInterval(this.lobbiesInterval);
|
||||
this.lobbiesInterval = null;
|
||||
}
|
||||
}
|
||||
const lobby = this.lobbies[0];
|
||||
const timeRemaining = Math.max(0, Math.floor(lobby.msUntilStart / 1000));
|
||||
|
||||
private async fetchAndUpdateLobbies(): Promise<void> {
|
||||
try {
|
||||
const lobbies = await this.fetchLobbies();
|
||||
this.lobbies = lobbies;
|
||||
} catch (error) {
|
||||
consolex.error('Error fetching and updating lobbies:', error);
|
||||
}
|
||||
}
|
||||
|
||||
async fetchLobbies(): Promise<Lobby[]> {
|
||||
const url = '/lobbies';
|
||||
try {
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
const data = await response.json();
|
||||
return data.lobbies;
|
||||
} catch (error) {
|
||||
consolex.error('Error fetching lobbies:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.lobbies.length === 0) {
|
||||
return html``;
|
||||
}
|
||||
|
||||
const lobby = this.lobbies[0];
|
||||
const timeRemaining = Math.max(0, Math.floor(lobby.msUntilStart / 1000));
|
||||
|
||||
return html`
|
||||
return html`
|
||||
<button
|
||||
@click=${() => this.lobbyClicked(lobby)}
|
||||
class="lobby-button ${this.isLobbyHighlighted ? 'highlighted' : ''}"
|
||||
class="lobby-button ${this.isLobbyHighlighted ? "highlighted" : ""}"
|
||||
>
|
||||
<div class="lobby-name">Game ${lobby.id}</div>
|
||||
<div class="lobby-timer">Starts in: ${timeRemaining}s</div>
|
||||
<div class="player-count">Players: ${lobby.numClients}</div>
|
||||
</button>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
private lobbyClicked(lobby: Lobby) {
|
||||
this.isLobbyHighlighted = !this.isLobbyHighlighted;
|
||||
if (this.currLobby == null) {
|
||||
this.currLobby = lobby
|
||||
this.dispatchEvent(new CustomEvent('join-lobby', {
|
||||
detail: {
|
||||
lobby: lobby,
|
||||
gameType: GameType.Public,
|
||||
map: GameMap.World,
|
||||
difficulty: Difficulty.Medium,
|
||||
},
|
||||
bubbles: true,
|
||||
composed: true
|
||||
}));
|
||||
} else {
|
||||
this.dispatchEvent(new CustomEvent('leave-lobby', {
|
||||
detail: { lobby: this.currLobby },
|
||||
bubbles: true,
|
||||
composed: true
|
||||
}));
|
||||
this.currLobby = null
|
||||
}
|
||||
private lobbyClicked(lobby: Lobby) {
|
||||
this.isLobbyHighlighted = !this.isLobbyHighlighted;
|
||||
if (this.currLobby == null) {
|
||||
this.currLobby = lobby;
|
||||
this.dispatchEvent(
|
||||
new CustomEvent("join-lobby", {
|
||||
detail: {
|
||||
lobby: lobby,
|
||||
gameType: GameType.Public,
|
||||
map: GameMap.World,
|
||||
difficulty: Difficulty.Medium,
|
||||
},
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
})
|
||||
);
|
||||
} else {
|
||||
this.dispatchEvent(
|
||||
new CustomEvent("leave-lobby", {
|
||||
detail: { lobby: this.currLobby },
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
})
|
||||
);
|
||||
this.currLobby = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user