import { Direction, DirectionToVector, MazeMap, MazeTile, } from "./MazeMap"; class GameState { public userID: string; public mapID: string; public tileID: string; constructor(userID: string, mapID: string, tileID: string) { this.userID = userID; this.mapID = mapID; this.tileID = tileID; } } export class GameServer { // By keeping mapList private, we can ensure, // that the server contains only valid maps. private mapList: MazeMap[]; private states: GameState[]; constructor() { this.mapList = []; this.states = []; } public addMap(newMap: MazeMap): boolean { const validationResult = newMap.validate(); if(validationResult.length > 0){ let message = "Cannot add invalid map:"; for (const e of validationResult) { message += "\n\t" + e; } throw new Error(message); } if(-1 === this.mapList.findIndex(m => m.id === newMap.id)) { this.mapList.push(newMap); return true; } else { return false; } } public startGame(userID: string, mapID: string): MazeTile { this.userIdGuard(userID); const map = this.mapList.find(m => m.id === mapID); if(map == null){ throw new Error(`Map "${mapID}" does not exist.`); } const start = map.getStartTile(); let state = this.states.find(s => s.userID === userID); if(state == null) { state = new GameState(userID, map.id, start.id); this.states.push(state); } else { state.mapID = map.id; state.tileID = start.id; } return start; } public navigate(userID: string, direction:Direction): MazeTile { this.userIdGuard(userID); const state = this.states.find(s => s.userID === userID); if(state == null){ return null; } const vec = DirectionToVector(direction); const map = this.mapList.find(m => m.id === state.mapID); let i:number; let j:number; let tile:MazeTile; for (i = 0; i < map.layout.length && tile == null; i++) { const row = map.layout[i]; for (j = 0; j < row.length; j++) { if(row[j].id === state.tileID) { tile = row[j]; break; } } } if(!tile.hasDirection(direction)){ throw new Error("Invalid direction."); } const nextTile = map.layout[i+vec[0]][j+vec[1]]; state.tileID = nextTile.id; return nextTile; } public currentPosition(userID: string): MazeTile { this.userIdGuard(userID); const state = this.states.find(s => s.userID === userID); if(state == null){ return null; } const map = this.mapList.find(m => m.id === state.mapID); const tile = map.getTile(state.tileID); return tile; } /** * Makes sure, that a userID is acceptable. * If not throw the appropriate error. * @param userID supplied userID */ private userIdGuard(userID: string): void { if(userID === undefined || userID === null){ throw new Error("UserID must be supplied!"); } if(userID === "" || /^\s+$/.test(userID)){ throw new Error("UserID must not be empty."); } } }