mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 09:50:43 +00:00
can leave lobby
This commit is contained in:
@@ -54,3 +54,4 @@
|
||||
* BUG: fix hotreload (priority queue breaks it)
|
||||
* PERF: use hierarchical a* search for boats
|
||||
* Add terrain elevation to map
|
||||
* boats can go around the world
|
||||
+32
-44
@@ -24,6 +24,7 @@ class Client {
|
||||
|
||||
private lobbiesContainer: HTMLElement | null;
|
||||
private lobbiesInterval: NodeJS.Timeout | null = null;
|
||||
private isLobbyHighlighted: boolean = false;
|
||||
|
||||
private random = new PseudoRandom(1234)
|
||||
|
||||
@@ -52,34 +53,31 @@ class Client {
|
||||
}
|
||||
|
||||
private updateLobbiesDisplay(lobbies: Lobby[]): void {
|
||||
if (!this.lobbiesContainer) return;
|
||||
if (lobbies.length === 0) {
|
||||
document.getElementById('lobby-button').style.display = 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
this.lobbiesContainer.innerHTML = ''; // Clear existing lobbies
|
||||
const lobby = lobbies[0];
|
||||
const lobbyButton = document.getElementById('lobby-button');
|
||||
const nameElement = document.getElementById('lobby-name');
|
||||
const timerElement = document.getElementById('lobby-timer');
|
||||
const playerCountElement = document.getElementById('player-count');
|
||||
|
||||
lobbies.forEach(lobby => {
|
||||
const button = document.createElement('button');
|
||||
button.className = 'lobby-button';
|
||||
if (lobbyButton) {
|
||||
lobbyButton.style.display = 'flex';
|
||||
lobbyButton.onclick = () => this.joinLobby(lobby);
|
||||
|
||||
const nameElement = document.createElement('div');
|
||||
nameElement.className = 'lobby-name';
|
||||
nameElement.textContent = `Lobby ${lobby.id}`;
|
||||
// Preserve the highlighted state
|
||||
lobbyButton.classList.toggle('highlighted', this.isLobbyHighlighted);
|
||||
}
|
||||
|
||||
const timerElement = document.createElement('div');
|
||||
timerElement.className = 'lobby-timer';
|
||||
if (nameElement) nameElement.textContent = `Lobby ${lobby.id}`;
|
||||
if (timerElement) {
|
||||
const timeRemaining = Math.max(0, Math.floor((lobby.startTime - Date.now()) / 1000));
|
||||
timerElement.textContent = `Starts in: ${timeRemaining}s`;
|
||||
|
||||
const playerCountElement = document.createElement('div');
|
||||
playerCountElement.className = 'player-count';
|
||||
playerCountElement.textContent = `Players: ${lobby.numClients}`
|
||||
|
||||
button.appendChild(nameElement);
|
||||
button.appendChild(timerElement);
|
||||
button.appendChild(playerCountElement);
|
||||
|
||||
button.onclick = () => this.joinLobby(lobby);
|
||||
this.lobbiesContainer.appendChild(button);
|
||||
});
|
||||
}
|
||||
if (playerCountElement) playerCountElement.textContent = `Players: ${lobby.numClients}`;
|
||||
}
|
||||
|
||||
async fetchLobbies(): Promise<Lobby[]> {
|
||||
@@ -97,25 +95,16 @@ class Client {
|
||||
}
|
||||
}
|
||||
|
||||
private async joinLobby(lobby: Lobby) {
|
||||
clearInterval(this.lobbiesInterval);
|
||||
|
||||
if (this.lobbiesContainer) {
|
||||
// Clear existing content
|
||||
this.lobbiesContainer.innerHTML = '';
|
||||
|
||||
// Ensure the container takes up the full height of the viewport
|
||||
this.lobbiesContainer.style.display = 'flex';
|
||||
this.lobbiesContainer.style.justifyContent = 'center';
|
||||
this.lobbiesContainer.style.alignItems = 'center';
|
||||
this.lobbiesContainer.style.minHeight = '100vh';
|
||||
|
||||
// Create and add the joining message
|
||||
const joiningMessage = document.createElement('div');
|
||||
joiningMessage.textContent = `Joining: ${lobby.id}`;
|
||||
joiningMessage.className = 'joining-message';
|
||||
|
||||
this.lobbiesContainer.appendChild(joiningMessage);
|
||||
private joinLobby(lobby: Lobby) {
|
||||
const lobbyButton = document.getElementById('lobby-button');
|
||||
if (lobbyButton) {
|
||||
this.isLobbyHighlighted = !this.isLobbyHighlighted;
|
||||
lobbyButton.classList.toggle('highlighted', this.isLobbyHighlighted);
|
||||
}
|
||||
if (!this.isLobbyHighlighted) {
|
||||
this.game.stop()
|
||||
this.game = null
|
||||
return
|
||||
}
|
||||
|
||||
if (this.game != null) {
|
||||
@@ -123,11 +112,10 @@ class Client {
|
||||
}
|
||||
this.game = createClientGame(getUsername(), new PseudoRandom(Date.now()).nextID(), lobby.id, getConfig(), this.terrainMap);
|
||||
this.game.join();
|
||||
const g = this.game
|
||||
const g = this.game;
|
||||
window.addEventListener('beforeunload', function (event) {
|
||||
// Your function logic here
|
||||
console.log('Browser is closing');
|
||||
g.stop()
|
||||
g.stop();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,6 +97,9 @@ export class ClientGame {
|
||||
};
|
||||
this.socket.onclose = (event: CloseEvent) => {
|
||||
console.log(`WebSocket closed. Code: ${event.code}, Reason: ${event.reason}`);
|
||||
if (!this.isActive) {
|
||||
return
|
||||
}
|
||||
if (event.code != 1000) {
|
||||
this.join()
|
||||
}
|
||||
@@ -126,6 +129,7 @@ export class ClientGame {
|
||||
clearInterval(this.intervalID)
|
||||
this.isActive = false
|
||||
if (this.socket.readyState === WebSocket.OPEN) {
|
||||
console.log('on stop: leaving game')
|
||||
const msg = ClientLeaveMessageSchema.parse({
|
||||
type: "leave",
|
||||
clientID: this.id,
|
||||
|
||||
+17
-30
@@ -5,7 +5,7 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>OpenFront (ALPHA)</title>
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
<link rel="stylesheet" type="text/css" href="styles.css">
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
@@ -13,7 +13,6 @@
|
||||
padding: 0;
|
||||
min-height: 100vh;
|
||||
background-color: #15151500;
|
||||
/* Dark grey background */
|
||||
background-image: url('/resources/images/watercolor_worldmap.jpg');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
@@ -23,17 +22,16 @@
|
||||
|
||||
.content {
|
||||
max-width: 1020px;
|
||||
/* Allows for two 500px buttons side by side with some margin */
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-family: Arial, serif;
|
||||
text-align: center;
|
||||
color: #ffffff;
|
||||
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
|
||||
font-size: 2.5em;
|
||||
color: #2e2e2e;
|
||||
font-size: 8em;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
@@ -50,25 +48,12 @@
|
||||
background-color: rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
|
||||
.lobby-button:hover {
|
||||
background-color: rgba(0, 123, 255, 0.4);
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 6px 15px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.player-count {
|
||||
font-size: 24px;
|
||||
margin-top: 20px;
|
||||
color: #aaddff;
|
||||
}
|
||||
|
||||
#lobbies-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
|
||||
.lobby-button {
|
||||
width: 500px;
|
||||
height: 500px;
|
||||
@@ -96,6 +81,13 @@
|
||||
box-shadow: 0 6px 15px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.lobby-button.highlighted {
|
||||
background-color: rgba(0, 123, 255, 0.6);
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 6px 20px rgba(0, 123, 255, 0.6);
|
||||
border-color: #ffffff;
|
||||
}
|
||||
|
||||
.lobby-name {
|
||||
font-size: 36px;
|
||||
margin-bottom: 20px;
|
||||
@@ -117,15 +109,6 @@
|
||||
text-align: center;
|
||||
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-family: Overpass, serif;
|
||||
text-align: center;
|
||||
color: #3d3c3c;
|
||||
/* text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5); */
|
||||
font-size: 8em;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
@@ -136,7 +119,11 @@
|
||||
<input type="text" id="username" placeholder="Enter your username">
|
||||
</div>
|
||||
<div id="lobbies-container">
|
||||
<!-- Lobby buttons will be inserted here by your existing JavaScript -->
|
||||
<button id="lobby-button" class="lobby-button">
|
||||
<div id="lobby-name" class="lobby-name"></div>
|
||||
<div id="lobby-timer" class="lobby-timer"></div>
|
||||
<div id="player-count" class="player-count"></div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -71,11 +71,11 @@ export class DefaultPlayerConfig implements PlayerConfig {
|
||||
}
|
||||
|
||||
troopAdditionRate(player: Player): number {
|
||||
const max = Math.sqrt(player.numTilesOwned()) * 1000 + 1000
|
||||
const max = Math.sqrt(player.numTilesOwned()) * 1000 + 10000
|
||||
|
||||
let toAdd = 10 + (player.troops() + Math.sqrt(player.troops() * player.numTilesOwned())) / 250
|
||||
|
||||
return Math.min(player.troops() + toAdd, max)
|
||||
return Math.min(Math.min(player.troops() + toAdd, max), 1_000_0000)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,10 +4,10 @@ import {DefaultConfig, DefaultPlayerConfig, defaultPlayerConfig} from "./Default
|
||||
|
||||
export const devConfig = new class extends DefaultConfig {
|
||||
gameCreationRate(): number {
|
||||
return 2 * 1000
|
||||
return 21 * 1000
|
||||
}
|
||||
lobbyLifetime(): number {
|
||||
return 5 * 1000
|
||||
return 20 * 1000
|
||||
}
|
||||
turnIntervalMs(): number {
|
||||
return 100
|
||||
@@ -16,7 +16,7 @@ export const devConfig = new class extends DefaultConfig {
|
||||
return devPlayerConfig
|
||||
}
|
||||
numBots(): number {
|
||||
return 500
|
||||
return 250
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,6 @@ export const devPlayerConfig = new class extends DefaultPlayerConfig {
|
||||
if (playerInfo.isBot) {
|
||||
return 5000
|
||||
}
|
||||
return 5000
|
||||
return 10000
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,7 @@ export class GameServer {
|
||||
}
|
||||
}
|
||||
if (clientMsg.type == "leave") {
|
||||
// TODO: get rid of leave message, just use on close?
|
||||
const toRemove = this.clients.filter(c => c.id)
|
||||
if (toRemove.length == 0) {
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user