mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-07-15 08:22:50 +00:00
format codebase with prettier
This commit is contained in:
+261
-196
@@ -1,240 +1,305 @@
|
||||
import { Executor } from "../core/execution/ExecutionManager";
|
||||
import { Cell, Game, PlayerID, GameMapType, Difficulty, GameType } from "../core/game/Game";
|
||||
import {
|
||||
Cell,
|
||||
Game,
|
||||
PlayerID,
|
||||
GameMapType,
|
||||
Difficulty,
|
||||
GameType,
|
||||
} from "../core/game/Game";
|
||||
import { EventBus } from "../core/EventBus";
|
||||
import { createRenderer, GameRenderer } from "./graphics/GameRenderer";
|
||||
import { InputHandler, MouseUpEvent, ZoomEvent, DragEvent, MouseDownEvent } from "./InputHandler"
|
||||
import { ClientID, ClientIntentMessageSchema, ClientJoinMessageSchema, ClientMessageSchema, GameConfig, GameID, Intent, ServerMessage, ServerMessageSchema, ServerSyncMessage, Turn } from "../core/Schemas";
|
||||
import { loadTerrainFromFile, loadTerrainMap } from "../core/game/TerrainMapLoader";
|
||||
import { SendAttackIntentEvent, SendSpawnIntentEvent, Transport } from "./Transport";
|
||||
import {
|
||||
InputHandler,
|
||||
MouseUpEvent,
|
||||
ZoomEvent,
|
||||
DragEvent,
|
||||
MouseDownEvent,
|
||||
} from "./InputHandler";
|
||||
import {
|
||||
ClientID,
|
||||
ClientIntentMessageSchema,
|
||||
ClientJoinMessageSchema,
|
||||
ClientMessageSchema,
|
||||
GameConfig,
|
||||
GameID,
|
||||
Intent,
|
||||
ServerMessage,
|
||||
ServerMessageSchema,
|
||||
ServerSyncMessage,
|
||||
Turn,
|
||||
} from "../core/Schemas";
|
||||
import {
|
||||
loadTerrainFromFile,
|
||||
loadTerrainMap,
|
||||
} from "../core/game/TerrainMapLoader";
|
||||
import {
|
||||
SendAttackIntentEvent,
|
||||
SendSpawnIntentEvent,
|
||||
Transport,
|
||||
} from "./Transport";
|
||||
import { createCanvas } from "./Utils";
|
||||
import { MessageType } from '../core/game/Game';
|
||||
import { MessageType } from "../core/game/Game";
|
||||
import { DisplayMessageUpdate, ErrorUpdate } from "../core/game/GameUpdates";
|
||||
import { WorkerClient } from "../core/worker/WorkerClient";
|
||||
import { consolex, initRemoteSender } from "../core/Consolex";
|
||||
import { getConfig, getServerConfig } from "../core/configuration/Config";
|
||||
import { GameView, PlayerView } from "../core/game/GameView";
|
||||
import { GameUpdateViewData } from '../core/game/GameUpdates';
|
||||
import { GameUpdateViewData } from "../core/game/GameUpdates";
|
||||
|
||||
export interface LobbyConfig {
|
||||
playerName: () => string
|
||||
clientID: ClientID,
|
||||
playerID: PlayerID,
|
||||
persistentID: string,
|
||||
gameType: GameType
|
||||
gameID: GameID,
|
||||
map: GameMapType | null
|
||||
difficulty: Difficulty | null
|
||||
playerName: () => string;
|
||||
clientID: ClientID;
|
||||
playerID: PlayerID;
|
||||
persistentID: string;
|
||||
gameType: GameType;
|
||||
gameID: GameID;
|
||||
map: GameMapType | null;
|
||||
difficulty: Difficulty | null;
|
||||
}
|
||||
|
||||
export function joinLobby(lobbyConfig: LobbyConfig, onjoin: () => void): () => void {
|
||||
const eventBus = new EventBus()
|
||||
initRemoteSender(eventBus)
|
||||
export function joinLobby(
|
||||
lobbyConfig: LobbyConfig,
|
||||
onjoin: () => void,
|
||||
): () => void {
|
||||
const eventBus = new EventBus();
|
||||
initRemoteSender(eventBus);
|
||||
|
||||
consolex.log(`joinging lobby: gameID: ${lobbyConfig.gameID}, clientID: ${lobbyConfig.clientID}, persistentID: ${lobbyConfig.persistentID}`)
|
||||
consolex.log(
|
||||
`joinging lobby: gameID: ${lobbyConfig.gameID}, clientID: ${lobbyConfig.clientID}, persistentID: ${lobbyConfig.persistentID}`,
|
||||
);
|
||||
|
||||
const serverConfig = getServerConfig()
|
||||
const serverConfig = getServerConfig();
|
||||
|
||||
let gameConfig: GameConfig = null
|
||||
if (lobbyConfig.gameType == GameType.Singleplayer) {
|
||||
gameConfig = {
|
||||
gameType: GameType.Singleplayer,
|
||||
gameMap: lobbyConfig.map,
|
||||
difficulty: lobbyConfig.difficulty,
|
||||
}
|
||||
}
|
||||
|
||||
const transport = new Transport(
|
||||
lobbyConfig,
|
||||
gameConfig,
|
||||
eventBus,
|
||||
serverConfig,
|
||||
)
|
||||
|
||||
const onconnect = () => {
|
||||
consolex.log(`Joined game lobby ${lobbyConfig.gameID}`);
|
||||
transport.joinGame(0)
|
||||
let gameConfig: GameConfig = null;
|
||||
if (lobbyConfig.gameType == GameType.Singleplayer) {
|
||||
gameConfig = {
|
||||
gameType: GameType.Singleplayer,
|
||||
gameMap: lobbyConfig.map,
|
||||
difficulty: lobbyConfig.difficulty,
|
||||
};
|
||||
const onmessage = (message: ServerMessage) => {
|
||||
if (message.type == "start") {
|
||||
consolex.log('lobby: game started')
|
||||
onjoin()
|
||||
createClientGame(lobbyConfig, message.config, eventBus, transport).then(r => r.start())
|
||||
};
|
||||
}
|
||||
transport.connect(onconnect, onmessage)
|
||||
return () => {
|
||||
consolex.log('leaving game')
|
||||
transport.leaveGame()
|
||||
}
|
||||
|
||||
const transport = new Transport(
|
||||
lobbyConfig,
|
||||
gameConfig,
|
||||
eventBus,
|
||||
serverConfig,
|
||||
);
|
||||
|
||||
const onconnect = () => {
|
||||
consolex.log(`Joined game lobby ${lobbyConfig.gameID}`);
|
||||
transport.joinGame(0);
|
||||
};
|
||||
const onmessage = (message: ServerMessage) => {
|
||||
if (message.type == "start") {
|
||||
consolex.log("lobby: game started");
|
||||
onjoin();
|
||||
createClientGame(lobbyConfig, message.config, eventBus, transport).then(
|
||||
(r) => r.start(),
|
||||
);
|
||||
}
|
||||
};
|
||||
transport.connect(onconnect, onmessage);
|
||||
return () => {
|
||||
consolex.log("leaving game");
|
||||
transport.leaveGame();
|
||||
};
|
||||
}
|
||||
|
||||
export async function createClientGame(
|
||||
lobbyConfig: LobbyConfig,
|
||||
gameConfig: GameConfig,
|
||||
eventBus: EventBus,
|
||||
transport: Transport,
|
||||
): Promise<ClientGameRunner> {
|
||||
const config = getConfig(gameConfig);
|
||||
|
||||
export async function createClientGame(lobbyConfig: LobbyConfig, gameConfig: GameConfig, eventBus: EventBus, transport: Transport): Promise<ClientGameRunner> {
|
||||
const config = getConfig(gameConfig)
|
||||
const gameMap = await loadTerrainMap(gameConfig.gameMap);
|
||||
const worker = new WorkerClient(lobbyConfig.gameID, gameConfig);
|
||||
await worker.initialize();
|
||||
const gameView = new GameView(
|
||||
worker,
|
||||
config,
|
||||
gameMap.gameMap,
|
||||
lobbyConfig.clientID,
|
||||
);
|
||||
|
||||
const gameMap = await loadTerrainMap(gameConfig.gameMap);
|
||||
const worker = new WorkerClient(lobbyConfig.gameID, gameConfig)
|
||||
await worker.initialize()
|
||||
const gameView = new GameView(worker, config, gameMap.gameMap, lobbyConfig.clientID)
|
||||
consolex.log("going to init path finder");
|
||||
consolex.log("inited path finder");
|
||||
const canvas = createCanvas();
|
||||
let gameRenderer = createRenderer(
|
||||
canvas,
|
||||
gameView,
|
||||
eventBus,
|
||||
lobbyConfig.clientID,
|
||||
);
|
||||
|
||||
consolex.log(
|
||||
`creating private game got difficulty: ${gameConfig.difficulty}`,
|
||||
);
|
||||
|
||||
consolex.log('going to init path finder')
|
||||
consolex.log('inited path finder')
|
||||
const canvas = createCanvas()
|
||||
let gameRenderer = createRenderer(canvas, gameView, eventBus, lobbyConfig.clientID)
|
||||
|
||||
|
||||
consolex.log(`creating private game got difficulty: ${gameConfig.difficulty}`)
|
||||
|
||||
return new ClientGameRunner(
|
||||
lobbyConfig.clientID,
|
||||
eventBus,
|
||||
gameRenderer,
|
||||
new InputHandler(canvas, eventBus),
|
||||
transport,
|
||||
worker,
|
||||
gameView
|
||||
)
|
||||
return new ClientGameRunner(
|
||||
lobbyConfig.clientID,
|
||||
eventBus,
|
||||
gameRenderer,
|
||||
new InputHandler(canvas, eventBus),
|
||||
transport,
|
||||
worker,
|
||||
gameView,
|
||||
);
|
||||
}
|
||||
|
||||
export class ClientGameRunner {
|
||||
private myPlayer: PlayerView
|
||||
private isActive = false
|
||||
private myPlayer: PlayerView;
|
||||
private isActive = false;
|
||||
|
||||
private turnsSeen = 0
|
||||
private hasJoined = false
|
||||
private turnsSeen = 0;
|
||||
private hasJoined = false;
|
||||
|
||||
constructor(
|
||||
private clientID: ClientID,
|
||||
private eventBus: EventBus,
|
||||
private renderer: GameRenderer,
|
||||
private input: InputHandler,
|
||||
private transport: Transport,
|
||||
private worker: WorkerClient,
|
||||
private gameView: GameView
|
||||
) { }
|
||||
constructor(
|
||||
private clientID: ClientID,
|
||||
private eventBus: EventBus,
|
||||
private renderer: GameRenderer,
|
||||
private input: InputHandler,
|
||||
private transport: Transport,
|
||||
private worker: WorkerClient,
|
||||
private gameView: GameView,
|
||||
) {}
|
||||
|
||||
public start() {
|
||||
consolex.log('starting client game')
|
||||
this.isActive = true
|
||||
this.eventBus.on(MouseUpEvent, (e) => this.inputEvent(e))
|
||||
public start() {
|
||||
consolex.log("starting client game");
|
||||
this.isActive = true;
|
||||
this.eventBus.on(MouseUpEvent, (e) => this.inputEvent(e));
|
||||
|
||||
this.renderer.initialize()
|
||||
this.input.initialize()
|
||||
this.worker.start((gu: GameUpdateViewData | ErrorUpdate) => {
|
||||
if ('errMsg' in gu) {
|
||||
showErrorModal(gu.errMsg, gu.stack, this.clientID)
|
||||
return
|
||||
}
|
||||
this.gameView.update(gu)
|
||||
this.renderer.tick()
|
||||
})
|
||||
const worker = this.worker
|
||||
const keepWorkerAlive = () => {
|
||||
worker.sendHeartbeat
|
||||
requestAnimationFrame(keepWorkerAlive)
|
||||
this.renderer.initialize();
|
||||
this.input.initialize();
|
||||
this.worker.start((gu: GameUpdateViewData | ErrorUpdate) => {
|
||||
if ("errMsg" in gu) {
|
||||
showErrorModal(gu.errMsg, gu.stack, this.clientID);
|
||||
return;
|
||||
}
|
||||
this.gameView.update(gu);
|
||||
this.renderer.tick();
|
||||
});
|
||||
const worker = this.worker;
|
||||
const keepWorkerAlive = () => {
|
||||
worker.sendHeartbeat;
|
||||
requestAnimationFrame(keepWorkerAlive);
|
||||
};
|
||||
requestAnimationFrame(keepWorkerAlive);
|
||||
|
||||
const onconnect = () => {
|
||||
consolex.log("Connected to game server!");
|
||||
this.transport.joinGame(this.turnsSeen);
|
||||
};
|
||||
const onmessage = (message: ServerMessage) => {
|
||||
if (message.type == "start") {
|
||||
this.hasJoined = true;
|
||||
consolex.log("starting game!");
|
||||
for (const turn of message.turns) {
|
||||
if (turn.turnNumber < this.turnsSeen) {
|
||||
continue;
|
||||
}
|
||||
this.worker.sendTurn(turn);
|
||||
this.turnsSeen++;
|
||||
}
|
||||
requestAnimationFrame(keepWorkerAlive)
|
||||
}
|
||||
if (message.type == "turn") {
|
||||
if (!this.hasJoined) {
|
||||
this.transport.joinGame(0);
|
||||
return;
|
||||
}
|
||||
if (this.turnsSeen != message.turn.turnNumber) {
|
||||
consolex.error(
|
||||
`got wrong turn have turns ${this.turnsSeen}, received turn ${message.turn.turnNumber}`,
|
||||
);
|
||||
} else {
|
||||
this.worker.sendTurn(message.turn);
|
||||
this.turnsSeen++;
|
||||
}
|
||||
}
|
||||
};
|
||||
this.transport.connect(onconnect, onmessage);
|
||||
}
|
||||
|
||||
const onconnect = () => {
|
||||
consolex.log('Connected to game server!');
|
||||
this.transport.joinGame(this.turnsSeen)
|
||||
};
|
||||
const onmessage = (message: ServerMessage) => {
|
||||
if (message.type == "start") {
|
||||
this.hasJoined = true
|
||||
consolex.log("starting game!")
|
||||
for (const turn of message.turns) {
|
||||
if (turn.turnNumber < this.turnsSeen) {
|
||||
continue
|
||||
}
|
||||
this.worker.sendTurn(turn)
|
||||
this.turnsSeen++
|
||||
}
|
||||
}
|
||||
if (message.type == "turn") {
|
||||
if (!this.hasJoined) {
|
||||
this.transport.joinGame(0)
|
||||
return
|
||||
}
|
||||
if (this.turnsSeen != message.turn.turnNumber) {
|
||||
consolex.error(`got wrong turn have turns ${this.turnsSeen}, received turn ${message.turn.turnNumber}`)
|
||||
} else {
|
||||
this.worker.sendTurn(message.turn)
|
||||
this.turnsSeen++
|
||||
}
|
||||
}
|
||||
};
|
||||
this.transport.connect(onconnect, onmessage)
|
||||
public stop() {
|
||||
this.worker.cleanup();
|
||||
this.isActive = false;
|
||||
this.transport.leaveGame();
|
||||
}
|
||||
|
||||
private inputEvent(event: MouseUpEvent) {
|
||||
if (!this.isActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
public stop() {
|
||||
this.worker.cleanup()
|
||||
this.isActive = false
|
||||
this.transport.leaveGame()
|
||||
const cell = this.renderer.transformHandler.screenToWorldCoordinates(
|
||||
event.x,
|
||||
event.y,
|
||||
);
|
||||
if (!this.gameView.isValidCoord(cell.x, cell.y)) {
|
||||
return;
|
||||
}
|
||||
|
||||
private inputEvent(event: MouseUpEvent) {
|
||||
if (!this.isActive) {
|
||||
return
|
||||
}
|
||||
const cell = this.renderer.transformHandler.screenToWorldCoordinates(event.x, event.y)
|
||||
if (!this.gameView.isValidCoord(cell.x, cell.y)) {
|
||||
return
|
||||
}
|
||||
consolex.log(`clicked cell ${cell}`)
|
||||
const tile = this.gameView.ref(cell.x, cell.y)
|
||||
if (this.gameView.isLand(tile) && !this.gameView.hasOwner(tile) && this.gameView.inSpawnPhase()) {
|
||||
this.eventBus.emit(new SendSpawnIntentEvent(cell))
|
||||
return
|
||||
}
|
||||
if (this.gameView.inSpawnPhase()) {
|
||||
return
|
||||
}
|
||||
if (this.myPlayer == null) {
|
||||
this.myPlayer = this.gameView.playerByClientID(this.clientID)
|
||||
if (this.myPlayer == null) {
|
||||
return
|
||||
}
|
||||
}
|
||||
this.myPlayer.actions(tile).then(actions => {
|
||||
console.log(`got actions: ${JSON.stringify(actions)}`)
|
||||
if (actions.canAttack) {
|
||||
this.eventBus.emit(
|
||||
new SendAttackIntentEvent(
|
||||
this.gameView.owner(tile).id(),
|
||||
this.myPlayer.troops() * this.renderer.uiState.attackRatio
|
||||
)
|
||||
)
|
||||
}
|
||||
})
|
||||
consolex.log(`clicked cell ${cell}`);
|
||||
const tile = this.gameView.ref(cell.x, cell.y);
|
||||
if (
|
||||
this.gameView.isLand(tile) &&
|
||||
!this.gameView.hasOwner(tile) &&
|
||||
this.gameView.inSpawnPhase()
|
||||
) {
|
||||
this.eventBus.emit(new SendSpawnIntentEvent(cell));
|
||||
return;
|
||||
}
|
||||
if (this.gameView.inSpawnPhase()) {
|
||||
return;
|
||||
}
|
||||
if (this.myPlayer == null) {
|
||||
this.myPlayer = this.gameView.playerByClientID(this.clientID);
|
||||
if (this.myPlayer == null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.myPlayer.actions(tile).then((actions) => {
|
||||
console.log(`got actions: ${JSON.stringify(actions)}`);
|
||||
if (actions.canAttack) {
|
||||
this.eventBus.emit(
|
||||
new SendAttackIntentEvent(
|
||||
this.gameView.owner(tile).id(),
|
||||
this.myPlayer.troops() * this.renderer.uiState.attackRatio,
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function showErrorModal(errMsg: string, stack: string, clientID: ClientID) {
|
||||
const errorText = `Error: ${errMsg}\nStack: ${stack}`;
|
||||
consolex.error(errorText);
|
||||
const errorText = `Error: ${errMsg}\nStack: ${stack}`;
|
||||
consolex.error(errorText);
|
||||
|
||||
const modal = document.createElement('div');
|
||||
const content = `Game crashed! client id: ${clientID}\nPlease paste the following in your bug report in Discord:\n${errorText}`;
|
||||
const modal = document.createElement("div");
|
||||
const content = `Game crashed! client id: ${clientID}\nPlease paste the following in your bug report in Discord:\n${errorText}`;
|
||||
|
||||
// Create elements
|
||||
const pre = document.createElement('pre');
|
||||
pre.textContent = content;
|
||||
// Create elements
|
||||
const pre = document.createElement("pre");
|
||||
pre.textContent = content;
|
||||
|
||||
const button = document.createElement('button');
|
||||
button.textContent = 'Copy to clipboard';
|
||||
button.style.cssText = 'padding: 8px 16px; margin-top: 10px; background: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer;';
|
||||
button.addEventListener('click', () => {
|
||||
navigator.clipboard.writeText(content)
|
||||
.then(() => button.textContent = 'Copied!')
|
||||
.catch(() => button.textContent = 'Failed to copy');
|
||||
});
|
||||
const button = document.createElement("button");
|
||||
button.textContent = "Copy to clipboard";
|
||||
button.style.cssText =
|
||||
"padding: 8px 16px; margin-top: 10px; background: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer;";
|
||||
button.addEventListener("click", () => {
|
||||
navigator.clipboard
|
||||
.writeText(content)
|
||||
.then(() => (button.textContent = "Copied!"))
|
||||
.catch(() => (button.textContent = "Failed to copy"));
|
||||
});
|
||||
|
||||
// Add to modal
|
||||
modal.style.cssText = 'position:fixed; padding:20px; background:white; border:1px solid black; top:50%; left:50%; transform:translate(-50%,-50%); z-index:9999;';
|
||||
modal.appendChild(pre);
|
||||
modal.appendChild(button);
|
||||
// Add to modal
|
||||
modal.style.cssText =
|
||||
"position:fixed; padding:20px; background:white; border:1px solid black; top:50%; left:50%; transform:translate(-50%,-50%); z-index:9999;";
|
||||
modal.appendChild(pre);
|
||||
modal.appendChild(button);
|
||||
|
||||
document.body.appendChild(modal);
|
||||
}
|
||||
document.body.appendChild(modal);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user