mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 11:10:42 +00:00
store name, anon has random suffix, color a hash of name
This commit is contained in:
@@ -103,16 +103,17 @@
|
||||
* Update landing page image DONE 9/9/2024
|
||||
* BUG: fix tile per turn pacing issues DONE 9/9/2024
|
||||
* Improve expansion directions (more uniform) 9/9/2024
|
||||
* store username DONE 9/11/2024
|
||||
* give anon unique number after Anon name DONE 9/11/2024
|
||||
* make color a hash of name DONE 9/11/2024
|
||||
* Make boats more intuitive (larger area to click off coast)
|
||||
* FakeHumans retaliate when attacked
|
||||
|
||||
|
||||
--- v3 Release
|
||||
|
||||
* store username
|
||||
|
||||
* store cookies
|
||||
* Make boats more intuitive (larger area to click off coast)
|
||||
* give anon unique number after Anon name
|
||||
* make color a hash of name
|
||||
* FakeHumans retaliate when attacked
|
||||
* BUG: when clicking on enemy sometimes boat goes all the way around
|
||||
* names dissappear too much (maybe screen size)
|
||||
* names dissapear on bottom of screen
|
||||
|
||||
+45
-7
@@ -11,8 +11,12 @@ import './styles.css';
|
||||
import {simpleHash} from "../core/Util";
|
||||
import {PseudoRandom} from "../core/PseudoRandom";
|
||||
|
||||
const usernameKey: string = 'username';
|
||||
|
||||
|
||||
class Client {
|
||||
|
||||
|
||||
private terrainMap: Promise<TerrainMap>
|
||||
private game: ClientGame
|
||||
private lobbiesInterval: NodeJS.Timeout | null = null;
|
||||
@@ -26,6 +30,13 @@ class Client {
|
||||
}
|
||||
|
||||
initialize(): void {
|
||||
const storedUsername = localStorage.getItem(usernameKey)
|
||||
if (storedUsername) {
|
||||
const usernameInput = document.getElementById('username') as HTMLInputElement | null;
|
||||
if (usernameInput) {
|
||||
usernameInput.value = storedUsername
|
||||
}
|
||||
}
|
||||
this.config = getConfig()
|
||||
setFavicon()
|
||||
this.terrainMap = loadTerrainMap()
|
||||
@@ -125,7 +136,7 @@ class Client {
|
||||
]);
|
||||
console.log(`got ip ${clientIP}`)
|
||||
this.game = createClientGame(
|
||||
getUsername(),
|
||||
refreshUsername(),
|
||||
uuidv4(),
|
||||
uuidv4(),
|
||||
clientIP,
|
||||
@@ -164,20 +175,32 @@ class Client {
|
||||
}
|
||||
}
|
||||
|
||||
function getUsername(): string {
|
||||
function refreshUsername(): string {
|
||||
const usernameInput = document.getElementById('username') as HTMLInputElement | null;
|
||||
if (usernameInput) {
|
||||
const trimmedValue = usernameInput.value.trim();
|
||||
return trimmedValue || 'Anon'; // Return 'Anon' if the trimmed value is empty
|
||||
if (usernameInput == null) {
|
||||
console.warn('username element not found')
|
||||
return "Anon"
|
||||
}
|
||||
if (usernameInput && usernameInput.value.trim()) {
|
||||
const trimmedValue = usernameInput.value.trim();
|
||||
localStorage.setItem(usernameKey, trimmedValue)
|
||||
return trimmedValue
|
||||
} else {
|
||||
const storedUsername = localStorage.getItem(usernameKey);
|
||||
if (storedUsername) {
|
||||
return storedUsername
|
||||
}
|
||||
const newUsername = "Anon" + uuidToThreeDigits()
|
||||
localStorage.setItem(usernameKey, newUsername)
|
||||
return newUsername
|
||||
}
|
||||
return 'Anon'; // Return 'Anon' if the input element is not found
|
||||
}
|
||||
|
||||
function setupUsernameCallback(callback: (username: string) => void): void {
|
||||
const usernameInput = document.getElementById('username') as HTMLInputElement | null;
|
||||
if (usernameInput) {
|
||||
usernameInput.addEventListener('input', () => {
|
||||
const username = getUsername();
|
||||
const username = refreshUsername();
|
||||
callback(username);
|
||||
});
|
||||
} else {
|
||||
@@ -229,4 +252,19 @@ function setFavicon(): void {
|
||||
link.rel = 'shortcut icon';
|
||||
link.href = favicon;
|
||||
document.head.appendChild(link);
|
||||
}
|
||||
|
||||
function uuidToThreeDigits(): string {
|
||||
const uuid = uuidv4()
|
||||
// Remove hyphens and convert to lowercase
|
||||
const cleanUuid = uuid.replace(/-/g, '').toLowerCase();
|
||||
|
||||
// Convert hex string to decimal
|
||||
const decimal = BigInt(`0x${cleanUuid}`);
|
||||
|
||||
// Get last 3 digits
|
||||
const threeDigits = decimal % 1000n;
|
||||
|
||||
// Pad with leading zeros if necessary
|
||||
return threeDigits.toString().padStart(3, '0');
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import {and, bfs, dist, manhattanDist} from "../core/Util";
|
||||
import {TerrainRenderer} from "./graphics/TerrainRenderer";
|
||||
|
||||
|
||||
|
||||
export function createClientGame(name: string, clientID: ClientID, playerID: PlayerID, ip: string | null, gameID: GameID, config: Config, terrainMap: TerrainMap): ClientGame {
|
||||
let eventBus = new EventBus()
|
||||
let game = createGame(terrainMap, eventBus, config)
|
||||
@@ -32,7 +33,6 @@ export function createClientGame(name: string, clientID: ClientID, playerID: Pla
|
||||
}
|
||||
|
||||
export class ClientGame {
|
||||
|
||||
private myPlayer: Player
|
||||
private turns: Turn[] = []
|
||||
private socket: WebSocket
|
||||
@@ -119,6 +119,8 @@ export class ClientGame {
|
||||
public start() {
|
||||
console.log('version 3')
|
||||
|
||||
|
||||
|
||||
this.isActive = true
|
||||
// TODO: make each class do this, or maybe have client intercept all requests?
|
||||
//this.eventBus.on(TickEvent, (e) => this.tick(e))
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {PriorityQueue} from "@datastructures-js/priority-queue";
|
||||
import {Boat, BoatEvent, Cell, Game, Tile, TileEvent} from "../../core/Game";
|
||||
import {Boat, BoatEvent, Cell, Game, Player, Tile, TileEvent} from "../../core/Game";
|
||||
import {PseudoRandom} from "../../core/PseudoRandom";
|
||||
import {Colord} from "colord";
|
||||
import {bfs, dist} from "../../core/Util";
|
||||
@@ -65,12 +65,12 @@ export class TerritoryRenderer {
|
||||
bfs(event.boat.tile(), dist(event.boat.tile(), 4)).forEach(
|
||||
t => {
|
||||
if (trail.has(t)) {
|
||||
this.paintCell(t.cell(), this.theme.territoryColor(event.boat.owner().id()), 150)
|
||||
this.paintCell(t.cell(), this.theme.territoryColor(event.boat.owner().info()), 150)
|
||||
}
|
||||
}
|
||||
)
|
||||
bfs(event.boat.tile(), dist(event.boat.tile(), 2)).forEach(t => this.paintCell(t.cell(), this.theme.borderColor(event.boat.owner().id()), 255))
|
||||
bfs(event.boat.tile(), dist(event.boat.tile(), 1)).forEach(t => this.paintCell(t.cell(), this.theme.territoryColor(event.boat.owner().id()), 180))
|
||||
bfs(event.boat.tile(), dist(event.boat.tile(), 2)).forEach(t => this.paintCell(t.cell(), this.theme.borderColor(event.boat.owner().info()), 255))
|
||||
bfs(event.boat.tile(), dist(event.boat.tile(), 1)).forEach(t => this.paintCell(t.cell(), this.theme.territoryColor(event.boat.owner().info()), 180))
|
||||
} else {
|
||||
trail.forEach(t => this.paintTerritory(t))
|
||||
this.boatToTrail.delete(event.boat)
|
||||
@@ -96,16 +96,17 @@ export class TerritoryRenderer {
|
||||
this.clearCell(tile.cell())
|
||||
return
|
||||
}
|
||||
const owner = tile.owner() as Player
|
||||
if (tile.isBorder()) {
|
||||
this.paintCell(
|
||||
tile.cell(),
|
||||
this.theme.borderColor(tile.owner().id()),
|
||||
this.theme.borderColor(owner.info()),
|
||||
255
|
||||
)
|
||||
} else {
|
||||
this.paintCell(
|
||||
tile.cell(),
|
||||
this.theme.territoryColor(tile.owner().id()),
|
||||
this.theme.territoryColor(owner.info()),
|
||||
110
|
||||
)
|
||||
}
|
||||
|
||||
@@ -58,14 +58,15 @@ h3 {
|
||||
}
|
||||
|
||||
#username {
|
||||
width: 100%;
|
||||
width: 60%;
|
||||
padding: 15px;
|
||||
font-size: 30px;
|
||||
font-size: 40px;
|
||||
text-align: center;
|
||||
border: 2px solid #007bff;
|
||||
border-radius: 5px;
|
||||
background-color: rgba(255, 255, 255, 0.8);
|
||||
margin: 30px auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
#lobbies-container {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import {info} from "console"
|
||||
import {Config} from "./configuration/Config"
|
||||
import {GameEvent} from "./EventBus"
|
||||
import {ClientID, GameID} from "./Schemas"
|
||||
|
||||
@@ -50,8 +50,8 @@ export interface Config {
|
||||
|
||||
export interface Theme {
|
||||
playerInfoColor(id: PlayerID): Colord;
|
||||
territoryColor(id: PlayerID): Colord;
|
||||
borderColor(id: PlayerID): Colord;
|
||||
territoryColor(playerInfo: PlayerInfo): Colord;
|
||||
borderColor(playerInfo: PlayerInfo): Colord;
|
||||
terrainColor(tile: Tile): Colord;
|
||||
backgroundColor(): Colord;
|
||||
font(): string;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {Colord, colord, random} from "colord";
|
||||
import {PlayerID, TerrainType, Tile} from "../Game";
|
||||
import {PlayerID, PlayerInfo, TerrainType, Tile} from "../Game";
|
||||
import {Theme} from "./Config";
|
||||
import {time} from "console";
|
||||
import {PseudoRandom} from "../PseudoRandom";
|
||||
@@ -119,12 +119,12 @@ export const pastelTheme = new class implements Theme {
|
||||
return colord({r: 50, g: 50, b: 50})
|
||||
}
|
||||
|
||||
territoryColor(id: PlayerID): Colord {
|
||||
return this.territoryColors[simpleHash(id) % this.territoryColors.length]
|
||||
territoryColor(playerInfo: PlayerInfo): Colord {
|
||||
return this.territoryColors[simpleHash(playerInfo.name) % this.territoryColors.length]
|
||||
}
|
||||
|
||||
borderColor(id: PlayerID): Colord {
|
||||
const tc = this.territoryColor(id).rgba;
|
||||
borderColor(playerInfo: PlayerInfo): Colord {
|
||||
const tc = this.territoryColor(playerInfo).rgba;
|
||||
return colord({
|
||||
r: Math.max(tc.r - 40, 0),
|
||||
g: Math.max(tc.g - 40, 0),
|
||||
|
||||
Reference in New Issue
Block a user