single player start

This commit is contained in:
evanpelle
2024-10-12 13:50:11 -07:00
parent cecbe8c313
commit 117027779f
8 changed files with 122 additions and 31 deletions
+1
View File
@@ -67,6 +67,7 @@ class Client {
]);
console.log(`got ip ${clientIP}`)
this.game = createClientGame(
false,
(): string => {return this.usernameInput.getCurrentUsername()},
uuidv4(),
uuidv4(),
+12 -2
View File
@@ -13,19 +13,29 @@ import {WinCheckExecution} from "../core/execution/WinCheckExecution";
import {SendAttackIntentEvent, SendSpawnIntentEvent, Transport} from "./Transport";
import {createCanvas} from "./graphics/Utils";
import {DisplayMessageEvent, MessageType} from "./graphics/layers/EventsDisplay";
import {LocalSocket, LocalSocketFactory, SocketFactory, WebsocketFactory as WebSocketFactory} from "../core/GameSocket";
import {LocalServer} from "../core/LocalServer";
export function createClientGame(playerName: () => string, clientID: ClientID, playerID: PlayerID, ip: string | null, gameID: GameID, config: Config, terrainMap: TerrainMap): ClientGame {
export function createClientGame(isLocal: boolean, playerName: () => 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)
const canvas = createCanvas()
let gameRenderer = createRenderer(canvas, game, eventBus, clientID)
let wsFactory: SocketFactory = null
if (isLocal) {
wsFactory = new LocalSocketFactory(new LocalServer(config))
} else {
const wsHost = process.env.WEBSOCKET_URL || window.location.host;
const wsProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
wsFactory = new WebSocketFactory(`${wsProtocol}//${wsHost}`)
}
const transport = new Transport(null, eventBus, gameID, clientID, playerID, playerName)
const transport = new Transport(wsFactory, eventBus, gameID, clientID, playerID, playerName)
return new ClientGame(
+4 -4
View File
@@ -1,6 +1,7 @@
import {EventBus, GameEvent} from "../core/EventBus"
import {AllianceRequest, AllPlayers, Cell, Player, PlayerID, PlayerType} from "../core/game/Game"
import {ClientID, ClientIntentMessageSchema, ClientJoinMessageSchema, ClientLeaveMessageSchema, GameID, Intent, ServerMessage, ServerMessageSchema} from "../core/Schemas"
import {SocketFactory} from "../core/GameSocket"
export class SendAllianceRequestIntentEvent implements GameEvent {
@@ -68,9 +69,10 @@ export class SendDonateIntentEvent implements GameEvent {
export class Transport {
public onconnect: () => {}
private socket: WebSocket
constructor(
public socket: WebSocket,
private socketFactory: SocketFactory,
private eventBus: EventBus,
private gameID: GameID,
private clientID: ClientID,
@@ -89,9 +91,7 @@ export class Transport {
}
connect(onconnect: () => void, onmessage: (message: ServerMessage) => void, isActive: () => boolean) {
const wsHost = process.env.WEBSOCKET_URL || window.location.host;
const wsProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
this.socket = new WebSocket(`${wsProtocol}//${wsHost}`)
this.socket = this.socketFactory.createSocket()
this.socket.onopen = () => {
console.log('Connected to game server!');
onconnect()
+80
View File
@@ -0,0 +1,80 @@
import {LocalServer} from "./LocalServer";
export interface SocketFactory {
createSocket(): WebSocket;
}
export interface Socket {
onopen: ((event: Event) => void) | null;
onmessage: ((event: MessageEvent) => void) | null;
onerror: ((event: Event) => void) | null;
onclose: ((event: CloseEvent) => void) | null;
readyState: number;
connect(url: string): void;
send(data: string): void;
close(code?: number, reason?: string): void;
}
export const WebSocketReadyState = {
CONNECTING: 0,
OPEN: 1,
CLOSING: 2,
CLOSED: 3
};
export class WebsocketFactory implements SocketFactory {
constructor(private url: string) { }
createSocket(): WebSocket {
return new WebSocket(this.url)
}
}
export class LocalSocketFactory implements SocketFactory {
constructor(private localServer: LocalServer) { }
createSocket(): WebSocket {
return new LocalSocket(this.localServer)
}
}
export class LocalSocket implements WebSocket {
constructor(private server: LocalServer) {
server.localSocket = this
}
binaryType: BinaryType;
bufferedAmount: number;
extensions: string;
onclose: (this: WebSocket, ev: CloseEvent) => any;
onerror: (this: WebSocket, ev: Event) => any;
onmessage: (this: WebSocket, ev: MessageEvent) => any;
onopen: (this: WebSocket, ev: Event) => any;
protocol: string;
readyState: number;
url: string;
close(code?: number, reason?: string): void {
// this.server.onclose(new GameCloseEvent())
}
send(data: string | ArrayBufferLike | Blob | ArrayBufferView): void {
this.server.onMessage(data as string)
}
CONNECTING: 0;
OPEN: 1;
CLOSING: 2;
CLOSED: 3;
addEventListener(type: unknown, listener: unknown, options?: unknown): void {
throw new Error("Method not implemented.");
}
removeEventListener(type: unknown, listener: unknown, options?: unknown): void {
throw new Error("Method not implemented.");
}
dispatchEvent(event: Event): boolean {
throw new Error("Method not implemented.");
}
}
+21
View File
@@ -0,0 +1,21 @@
import {Config} from "./configuration/Config";
import {LocalSocket} from "./GameSocket";
import {ClientMessage, ClientMessageSchema} from "./Schemas";
export class LocalServer {
public localSocket: LocalSocket
constructor(private config: Config) {
}
onConnect() {
}
onMessage(message: string) {
const clientMsg: ClientMessage = ClientMessageSchema.parse(JSON.parse(message))
if (clientMsg.type == "intent") {
}
}
}
+2 -2
View File
@@ -1,10 +1,10 @@
import {GamePhase, GameServer} from "./GameServer";
import {Config} from "../core/configuration/Config";
import {PseudoRandom} from "../core/PseudoRandom";
import WebSocket from 'ws';
import {ClientID, GameID} from "../core/Schemas";
import {Client} from "./Client";
import {v4 as uuidv4} from 'uuid';
import {Client} from "./Client";
import {GamePhase, GameServer} from "./GameServer";
-21
View File
@@ -1,21 +0,0 @@
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
}
}
+2 -2
View File
@@ -4,11 +4,11 @@ import {WebSocketServer} from 'ws';
import path from 'path';
import {fileURLToPath} from 'url';
import {GameManager} from './GameManager';
import {Client} from './Client';
import {ClientMessage, ClientMessageSchema} from '../core/Schemas';
import {GamePhase} from './GameServer';
import {getConfig} from '../core/configuration/Config';
import {LogSeverity, slog} from './StructuredLog';
import {Client} from './Client';
import {GamePhase} from './GameServer';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);