mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 07:50:45 +00:00
improve front page
This commit is contained in:
@@ -22,11 +22,11 @@
|
||||
* delete players when territories too small DONE 8/16/2024
|
||||
* double attack add troops DONE 8/16/2024
|
||||
* Have some time for spawning before game starts DONE 8/16/2024
|
||||
* fix desync DONE 8/16/2024
|
||||
* fix server memory leak DONE 8/16/2024
|
||||
* only send delta turns on connect/reconnect DONE 8/17/2024
|
||||
* Create separate game config dev vs prod
|
||||
* improve front page, only one game at a time every 30s
|
||||
* fix desync
|
||||
* fix server memory leak
|
||||
* Create separate game config dev vs prod DONE 8/17/2024
|
||||
* improve front page, only one game at a time every 30s DONE 8/17/2024
|
||||
* BUG: boats not going to destination, coast not being recognized
|
||||
* BUG: boats freeze game on path calculation
|
||||
* better algorithm for name render placement
|
||||
|
||||
+4
-3
@@ -5,8 +5,9 @@
|
||||
"build-dev": "webpack --config webpack.config.js --mode development",
|
||||
"build-prod": "webpack --config webpack.config.js --mode production",
|
||||
"start:client": "webpack serve --open --node-env development",
|
||||
"start:server": "node --loader ts-node/esm --experimental-specifier-resolution=node src/server/Server.ts",
|
||||
"dev": "concurrently \"npm run start:client\" \"npm run start:server\"",
|
||||
"start:server": "GAME_ENV=prod node --loader ts-node/esm --experimental-specifier-resolution=node src/server/Server.ts",
|
||||
"start:server-dev": "GAME_ENV=dev node --loader ts-node/esm --experimental-specifier-resolution=node src/server/Server.ts",
|
||||
"dev": "GAME_ENV=dev concurrently \"npm run start:client\" \"npm run start:server-dev\"",
|
||||
"test": "jest"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -53,4 +54,4 @@
|
||||
"zod": "^3.23.8"
|
||||
},
|
||||
"type": "module"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 388 KiB |
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 64 KiB |
Executable
+14
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 27 KiB |
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 1.3 MiB |
+48
-16
@@ -7,6 +7,8 @@ import {GameID, Lobby, ServerMessage, ServerMessageSchema} from "../core/Schemas
|
||||
import {loadTerrainMap} from "../core/TerrainMapLoader";
|
||||
import {ClientGame, createClientGame} from "./ClientGame";
|
||||
import {v4 as uuidv4} from 'uuid';
|
||||
import backgroundImage from '../../resources/images/World.png';
|
||||
|
||||
|
||||
// import WebSocket from 'ws';
|
||||
|
||||
@@ -52,17 +54,27 @@ class Client {
|
||||
|
||||
lobbies.forEach(lobby => {
|
||||
const button = document.createElement('button');
|
||||
button.textContent = `Join Lobby ${lobby.id} (${Math.floor((lobby.startTime - Date.now()) / 1000)}s)`;
|
||||
button.className = 'lobby-button';
|
||||
|
||||
const nameElement = document.createElement('div');
|
||||
nameElement.className = 'lobby-name';
|
||||
nameElement.textContent = `Lobby ${lobby.id}`;
|
||||
|
||||
const timerElement = document.createElement('div');
|
||||
timerElement.className = 'lobby-timer';
|
||||
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';
|
||||
|
||||
button.appendChild(nameElement);
|
||||
button.appendChild(timerElement);
|
||||
button.appendChild(playerCountElement);
|
||||
|
||||
button.onclick = () => this.joinLobby(lobby);
|
||||
this.lobbiesContainer.appendChild(button);
|
||||
});
|
||||
|
||||
// // Join first lobby
|
||||
// if (!this.hasJoined && lobbies.length > 0) {
|
||||
// this.hasJoined = true
|
||||
// console.log(`joining lobby ${lobbies[0].id}`)
|
||||
// this.joinLobby(lobbies[0].id)
|
||||
// }
|
||||
}
|
||||
|
||||
async fetchLobbies(): Promise<Lobby[]> {
|
||||
@@ -81,16 +93,33 @@ class Client {
|
||||
}
|
||||
|
||||
private async joinLobby(lobby: Lobby) {
|
||||
clearInterval(this.lobbiesInterval)
|
||||
this.lobbiesContainer.innerHTML = `Joining: ${lobby.id}`; // Clear existing lobbies
|
||||
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);
|
||||
}
|
||||
|
||||
this.terrainMap.then((map) => {
|
||||
if (this.game != null) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
// TODO make id more random, if two player join same millisecond get same id.
|
||||
this.game = createClientGame(getUsername(), new PseudoRandom(Date.now()).nextID(), lobby.id, getConfig(), map)
|
||||
this.game.join()
|
||||
})
|
||||
this.game = createClientGame(getUsername(), new PseudoRandom(Date.now()).nextID(), lobby.id, getConfig(), map);
|
||||
this.game.join();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,4 +135,7 @@ function getUsername(): string {
|
||||
// Initialize the client when the DOM is loaded
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
new Client().initialize();
|
||||
});
|
||||
});
|
||||
|
||||
document.body.style.backgroundImage = `url(${backgroundImage})`;
|
||||
|
||||
|
||||
@@ -154,9 +154,9 @@ export class ClientGame {
|
||||
}
|
||||
|
||||
private inputEvent(event: MouseDownEvent) {
|
||||
if (this.turns.length < this.config.turnsUntilGameStart()) {
|
||||
return
|
||||
}
|
||||
// if (this.turns.length < this.config.turnsUntilGameStart()) {
|
||||
// return
|
||||
// }
|
||||
if (!this.isActive) {
|
||||
return
|
||||
}
|
||||
|
||||
+82
-27
@@ -8,71 +8,126 @@
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
max-width: 800px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
min-height: 100vh;
|
||||
background-color: #404040;
|
||||
/* Dark grey background */
|
||||
background-image: url('/resources/images/watercolor_worldmap.jpg');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-attachment: fixed;
|
||||
background-blend-mode: overlay;
|
||||
}
|
||||
|
||||
.content {
|
||||
max-width: 1020px;
|
||||
/* Allows for two 500px buttons side by side with some margin */
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background-color: #f0f0f0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
color: #333;
|
||||
color: #ffffff;
|
||||
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
|
||||
font-size: 2.5em;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
#username-container {
|
||||
margin-bottom: 20px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
#username {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
font-size: 16px;
|
||||
padding: 15px;
|
||||
font-size: 18px;
|
||||
border: 2px solid #007bff;
|
||||
border-radius: 5px;
|
||||
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: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
||||
gap: 15px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.lobby-button {
|
||||
height: 100px;
|
||||
font-size: 18px;
|
||||
width: 500px;
|
||||
height: 500px;
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
border: 2px solid #007bff;
|
||||
background-color: #ffffff;
|
||||
color: #007bff;
|
||||
border: 3px solid #007bff;
|
||||
background-color: rgba(0, 123, 255, 0.2);
|
||||
color: #ffffff;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: background-color 0.3s, color 0.3s;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
|
||||
transition: all 0.3s ease;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.lobby-button:hover {
|
||||
background-color: #007bff;
|
||||
color: #ffffff;
|
||||
background-color: rgba(0, 123, 255, 0.4);
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 6px 15px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.lobby-name {
|
||||
font-size: 36px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.lobby-timer {
|
||||
font-size: 28px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.player-count {
|
||||
font-size: 14px;
|
||||
margin-top: 5px;
|
||||
font-size: 24px;
|
||||
color: #aaddff;
|
||||
}
|
||||
|
||||
.joining-message {
|
||||
font-size: 48px;
|
||||
color: white;
|
||||
text-align: center;
|
||||
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>OpenFront (ALPHA)</h1>
|
||||
<div id="username-container">
|
||||
<input type="text" id="username" placeholder="Enter your username">
|
||||
</div>
|
||||
<div id="lobbies-container">
|
||||
<!-- Lobby buttons will be inserted here by your existing JavaScript -->
|
||||
<div class="content">
|
||||
<h1>OpenFront (ALPHA)</h1>
|
||||
<div id="username-container">
|
||||
<input type="text" id="username" placeholder="Enter your username">
|
||||
</div>
|
||||
<div id="lobbies-container">
|
||||
<!-- Lobby buttons will be inserted here by your existing JavaScript -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Your existing script file -->
|
||||
|
||||
@@ -4,12 +4,13 @@ import {devConfig} from "./DevConfig";
|
||||
import {defaultConfig} from "./DefaultConfig";
|
||||
|
||||
export function getConfig(): Config {
|
||||
if (process.env.GAME_ENV == 'prod') {
|
||||
console.log('Using prod config')
|
||||
return defaultConfig
|
||||
} else {
|
||||
// TODO: 'prod' not found in prod env
|
||||
if (process.env.GAME_ENV == 'dev') {
|
||||
console.log('Using dev config')
|
||||
return devConfig
|
||||
} else {
|
||||
console.log('Using prod config')
|
||||
return defaultConfig
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Vendored
+14
-1
@@ -1,4 +1,17 @@
|
||||
declare module '*.png' {
|
||||
const content: string;
|
||||
export default content;
|
||||
}
|
||||
}
|
||||
declare module '*.jpg' {
|
||||
const value: string;
|
||||
export default value;
|
||||
}
|
||||
|
||||
declare module '*.jpeg' {
|
||||
const value: string;
|
||||
export default value;
|
||||
}
|
||||
declare module '*.svg' {
|
||||
const value: string;
|
||||
export default value;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import {ClientID} from "../core/Schemas";
|
||||
import {Client} from "./Client";
|
||||
|
||||
export class Lobby {
|
||||
|
||||
public clients: Map<ClientID, Client> = new Map()
|
||||
private startGameTs: number
|
||||
|
||||
|
||||
constructor(public readonly id: string, durationMs: number) {
|
||||
this.startGameTs = Date.now() + durationMs
|
||||
}
|
||||
|
||||
public addClient(client: Client) {
|
||||
this.clients.set(client.id, client)
|
||||
}
|
||||
|
||||
public isExpired(now: number): boolean {
|
||||
return now > this.startGameTs
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,10 @@ export default (env, argv) => {
|
||||
generator: {
|
||||
filename: 'images/[hash][ext][query]'
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.svg$/,
|
||||
type: 'asset/inline',
|
||||
}
|
||||
],
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user