mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 19:01:00 +00:00
Merge pull request #15 from NewHappyRabbit/main
Added checkboxes to disable Bots and NPCs for single player and private lobbies
This commit is contained in:
+2
-1
@@ -5,4 +5,5 @@ TODO.txt
|
||||
resources/images/.DS_Store
|
||||
resources/.DS_Store
|
||||
.env
|
||||
.prettierrc
|
||||
.prettierrc
|
||||
.prettierignore
|
||||
Generated
+20
@@ -65,6 +65,7 @@
|
||||
"binary-base64-loader": "^1.0.0",
|
||||
"chai": "^5.1.1",
|
||||
"concurrently": "^8.2.2",
|
||||
"cross-env": "^7.0.3",
|
||||
"css-loader": "^7.1.2",
|
||||
"file-loader": "^6.2.0",
|
||||
"html-inline-script-webpack-plugin": "^3.2.1",
|
||||
@@ -6612,6 +6613,25 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/cross-env": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz",
|
||||
"integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cross-spawn": "^7.0.1"
|
||||
},
|
||||
"bin": {
|
||||
"cross-env": "src/bin/cross-env.js",
|
||||
"cross-env-shell": "src/bin/cross-env-shell.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.14",
|
||||
"npm": ">=6",
|
||||
"yarn": ">=1"
|
||||
}
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
||||
|
||||
+101
-100
@@ -1,102 +1,103 @@
|
||||
{
|
||||
"name": "openfront-client",
|
||||
"scripts": {
|
||||
"build-map": "node --loader ts-node/esm --experimental-specifier-resolution=node src/scripts/TerrainMapGenerator.ts",
|
||||
"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",
|
||||
"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\"",
|
||||
"tunnel": "npm run build-prod && npm run start:server",
|
||||
"test": "jest"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.25.2",
|
||||
"@babel/preset-env": "^7.25.3",
|
||||
"@babel/preset-typescript": "^7.24.7",
|
||||
"@types/chai": "^4.3.17",
|
||||
"@types/d3": "^7.4.3",
|
||||
"@types/jest": "^29.5.12",
|
||||
"@types/jquery": "^3.5.31",
|
||||
"@types/mocha": "^10.0.7",
|
||||
"@types/node": "^22.10.2",
|
||||
"@types/sinon": "^17.0.3",
|
||||
"@types/uuid": "^10.0.0",
|
||||
"@types/ws": "^8.5.11",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"babel-jest": "^29.7.0",
|
||||
"binary-base64-loader": "^1.0.0",
|
||||
"chai": "^5.1.1",
|
||||
"concurrently": "^8.2.2",
|
||||
"css-loader": "^7.1.2",
|
||||
"file-loader": "^6.2.0",
|
||||
"html-inline-script-webpack-plugin": "^3.2.1",
|
||||
"html-loader": "^5.1.0",
|
||||
"html-webpack-plugin": "^5.6.0",
|
||||
"jest": "^29.7.0",
|
||||
"mocha": "^10.7.0",
|
||||
"mrmime": "^2.0.0",
|
||||
"postcss": "^8.5.1",
|
||||
"postcss-loader": "^8.1.1",
|
||||
"raw-loader": "^4.0.2",
|
||||
"sinon": "^18.0.0",
|
||||
"sinon-chai": "^4.0.0",
|
||||
"style-loader": "^4.0.0",
|
||||
"tailwindcss": "^3.4.17",
|
||||
"ts-jest": "^29.2.4",
|
||||
"ts-loader": "^9.5.1",
|
||||
"ts-mocha": "^10.0.0",
|
||||
"ts-node": "^10.9.2",
|
||||
"tsconfig-paths": "^4.2.0",
|
||||
"tsx": "^4.17.0",
|
||||
"typescript": "^5.7.2",
|
||||
"webpack": "^5.91.0",
|
||||
"webpack-cli": "^5.1.4",
|
||||
"webpack-dev-server": "^5.0.4",
|
||||
"worker-loader": "^3.0.8"
|
||||
},
|
||||
"dependencies": {
|
||||
"@datastructures-js/priority-queue": "^6.3.1",
|
||||
"@google-cloud/bigquery": "^7.9.1",
|
||||
"@google-cloud/secret-manager": "^5.6.0",
|
||||
"@google-cloud/storage": "^7.14.0",
|
||||
"@types/dompurify": "^3.0.5",
|
||||
"@types/express": "^4.17.21",
|
||||
"@types/google-protobuf": "^3.15.12",
|
||||
"@types/hammerjs": "^2.0.45",
|
||||
"@types/jimp": "^0.2.28",
|
||||
"@types/msgpack5": "^3.4.6",
|
||||
"@types/raphael": "^2.3.9",
|
||||
"@types/twemoji": "^13.1.1",
|
||||
"binary-loader": "^0.0.1",
|
||||
"colord": "^2.9.3",
|
||||
"crypto": "^1.0.1",
|
||||
"d3": "^7.9.0",
|
||||
"discord.js": "^14.16.3",
|
||||
"dompurify": "^3.1.7",
|
||||
"dotenv": "^16.4.7",
|
||||
"express": "^4.21.1",
|
||||
"google-auth-library": "^9.14.0",
|
||||
"googleapis": "^143.0.0",
|
||||
"hammerjs": "^2.0.8",
|
||||
"ip-anonymize": "^0.1.0",
|
||||
"jimp": "^0.22.12",
|
||||
"lit": "^3.2.1",
|
||||
"msgpack5": "^6.0.2",
|
||||
"nanoid": "^5.0.9",
|
||||
"node-addon-api": "^8.1.0",
|
||||
"node-gyp": "^10.2.0",
|
||||
"obscenity": "^0.4.3",
|
||||
"priority-queue-typescript": "^1.0.1",
|
||||
"protobufjs": "^7.3.2",
|
||||
"pureimage": "^0.4.13",
|
||||
"raphael": "^2.3.0",
|
||||
"twemoji": "^14.0.2",
|
||||
"uuid": "^10.0.0",
|
||||
"wheelnav": "^1.7.1",
|
||||
"ws": "^8.18.0",
|
||||
"zod": "^3.23.8"
|
||||
},
|
||||
"type": "module"
|
||||
"name": "openfront-client",
|
||||
"scripts": {
|
||||
"build-map": "node --loader ts-node/esm --experimental-specifier-resolution=node src/scripts/TerrainMapGenerator.ts",
|
||||
"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",
|
||||
"start:server-dev": "cross-env GAME_ENV=dev node --loader ts-node/esm --experimental-specifier-resolution=node src/server/Server.ts",
|
||||
"dev": "cross-env GAME_ENV=dev concurrently \"npm run start:client\" \"npm run start:server-dev\"",
|
||||
"tunnel": "npm run build-prod && npm run start:server",
|
||||
"test": "jest"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.25.2",
|
||||
"@babel/preset-env": "^7.25.3",
|
||||
"@babel/preset-typescript": "^7.24.7",
|
||||
"@types/chai": "^4.3.17",
|
||||
"@types/d3": "^7.4.3",
|
||||
"@types/jest": "^29.5.12",
|
||||
"@types/jquery": "^3.5.31",
|
||||
"@types/mocha": "^10.0.7",
|
||||
"@types/node": "^22.10.2",
|
||||
"@types/sinon": "^17.0.3",
|
||||
"@types/uuid": "^10.0.0",
|
||||
"@types/ws": "^8.5.11",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"babel-jest": "^29.7.0",
|
||||
"binary-base64-loader": "^1.0.0",
|
||||
"chai": "^5.1.1",
|
||||
"concurrently": "^8.2.2",
|
||||
"cross-env": "^7.0.3",
|
||||
"css-loader": "^7.1.2",
|
||||
"file-loader": "^6.2.0",
|
||||
"html-inline-script-webpack-plugin": "^3.2.1",
|
||||
"html-loader": "^5.1.0",
|
||||
"html-webpack-plugin": "^5.6.0",
|
||||
"jest": "^29.7.0",
|
||||
"mocha": "^10.7.0",
|
||||
"mrmime": "^2.0.0",
|
||||
"postcss": "^8.5.1",
|
||||
"postcss-loader": "^8.1.1",
|
||||
"raw-loader": "^4.0.2",
|
||||
"sinon": "^18.0.0",
|
||||
"sinon-chai": "^4.0.0",
|
||||
"style-loader": "^4.0.0",
|
||||
"tailwindcss": "^3.4.17",
|
||||
"ts-jest": "^29.2.4",
|
||||
"ts-loader": "^9.5.1",
|
||||
"ts-mocha": "^10.0.0",
|
||||
"ts-node": "^10.9.2",
|
||||
"tsconfig-paths": "^4.2.0",
|
||||
"tsx": "^4.17.0",
|
||||
"typescript": "^5.7.2",
|
||||
"webpack": "^5.91.0",
|
||||
"webpack-cli": "^5.1.4",
|
||||
"webpack-dev-server": "^5.0.4",
|
||||
"worker-loader": "^3.0.8"
|
||||
},
|
||||
"dependencies": {
|
||||
"@datastructures-js/priority-queue": "^6.3.1",
|
||||
"@google-cloud/bigquery": "^7.9.1",
|
||||
"@google-cloud/secret-manager": "^5.6.0",
|
||||
"@google-cloud/storage": "^7.14.0",
|
||||
"@types/dompurify": "^3.0.5",
|
||||
"@types/express": "^4.17.21",
|
||||
"@types/google-protobuf": "^3.15.12",
|
||||
"@types/hammerjs": "^2.0.45",
|
||||
"@types/jimp": "^0.2.28",
|
||||
"@types/msgpack5": "^3.4.6",
|
||||
"@types/raphael": "^2.3.9",
|
||||
"@types/twemoji": "^13.1.1",
|
||||
"binary-loader": "^0.0.1",
|
||||
"colord": "^2.9.3",
|
||||
"crypto": "^1.0.1",
|
||||
"d3": "^7.9.0",
|
||||
"discord.js": "^14.16.3",
|
||||
"dompurify": "^3.1.7",
|
||||
"dotenv": "^16.4.7",
|
||||
"express": "^4.21.1",
|
||||
"google-auth-library": "^9.14.0",
|
||||
"googleapis": "^143.0.0",
|
||||
"hammerjs": "^2.0.8",
|
||||
"ip-anonymize": "^0.1.0",
|
||||
"jimp": "^0.22.12",
|
||||
"lit": "^3.2.1",
|
||||
"msgpack5": "^6.0.2",
|
||||
"nanoid": "^5.0.9",
|
||||
"node-addon-api": "^8.1.0",
|
||||
"node-gyp": "^10.2.0",
|
||||
"obscenity": "^0.4.3",
|
||||
"priority-queue-typescript": "^1.0.1",
|
||||
"protobufjs": "^7.3.2",
|
||||
"pureimage": "^0.4.13",
|
||||
"raphael": "^2.3.0",
|
||||
"twemoji": "^14.0.2",
|
||||
"uuid": "^10.0.0",
|
||||
"wheelnav": "^1.7.1",
|
||||
"ws": "^8.18.0",
|
||||
"zod": "^3.23.8"
|
||||
},
|
||||
"type": "module"
|
||||
}
|
||||
|
||||
@@ -56,6 +56,8 @@ export interface LobbyConfig {
|
||||
gameID: GameID;
|
||||
map: GameMapType | null;
|
||||
difficulty: Difficulty | null;
|
||||
disableBots: boolean | null;
|
||||
disableNPCs: boolean | null;
|
||||
}
|
||||
|
||||
export function joinLobby(
|
||||
@@ -77,6 +79,8 @@ export function joinLobby(
|
||||
gameType: GameType.Singleplayer,
|
||||
gameMap: lobbyConfig.map,
|
||||
difficulty: lobbyConfig.difficulty,
|
||||
disableBots: lobbyConfig.disableBots,
|
||||
disableNPCs: lobbyConfig.disableNPCs,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@ export class HostLobbyModal extends LitElement {
|
||||
@state() private isModalOpen = false;
|
||||
@state() private selectedMap: GameMapType = GameMapType.World;
|
||||
@state() private selectedDiffculty: Difficulty = Difficulty.Medium;
|
||||
@state() private disableNPCs = false;
|
||||
@state() private disableBots = false;
|
||||
@state() private lobbyId = "";
|
||||
@state() private copySuccess = false;
|
||||
@state() private players: string[] = [];
|
||||
@@ -165,6 +167,22 @@ export class HostLobbyModal extends LitElement {
|
||||
)}
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<input
|
||||
type="checkbox"
|
||||
id="disable-bots"
|
||||
@change=${this.handleDisableBotsChange}
|
||||
/>
|
||||
<label for="disable-bots">Disable Bots</label>
|
||||
</div>
|
||||
<div>
|
||||
<input
|
||||
type="checkbox"
|
||||
id="disable-npcs"
|
||||
@change=${this.handleDisableNPCsChange}
|
||||
/>
|
||||
<label for="disable-npcs">Disable NPCs</label>
|
||||
</div>
|
||||
<button @click=${this.startGame}>Start Game</button>
|
||||
<div>
|
||||
<p>Players: ${this.players.join(", ")}</p>
|
||||
@@ -191,6 +209,8 @@ export class HostLobbyModal extends LitElement {
|
||||
},
|
||||
map: this.selectedMap,
|
||||
difficulty: this.selectedDiffculty,
|
||||
disableBots: this.disableBots,
|
||||
disableNPCs: this.disableNPCs,
|
||||
},
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
@@ -226,6 +246,18 @@ export class HostLobbyModal extends LitElement {
|
||||
this.putGameConfig();
|
||||
}
|
||||
|
||||
private async handleDisableBotsChange(e: Event) {
|
||||
this.disableBots = Boolean((e.target as HTMLInputElement).checked);
|
||||
consolex.log(`updating disable bots to ${this.disableBots}`);
|
||||
this.putGameConfig();
|
||||
}
|
||||
|
||||
private async handleDisableNPCsChange(e: Event) {
|
||||
this.disableNPCs = Boolean((e.target as HTMLInputElement).checked);
|
||||
consolex.log(`updating disable npcs to ${this.disableNPCs}`);
|
||||
this.putGameConfig();
|
||||
}
|
||||
|
||||
private async putGameConfig() {
|
||||
const response = await fetch(`/private_lobby/${this.lobbyId}`, {
|
||||
method: "PUT",
|
||||
@@ -235,6 +267,8 @@ export class HostLobbyModal extends LitElement {
|
||||
body: JSON.stringify({
|
||||
gameMap: this.selectedMap,
|
||||
difficulty: this.selectedDiffculty,
|
||||
disableBots: this.disableBots,
|
||||
disableNPCs: this.disableNPCs,
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -95,6 +95,8 @@ class Client {
|
||||
clientID: generateID(),
|
||||
map: event.detail.map,
|
||||
difficulty: event.detail.difficulty,
|
||||
disableBots: event.detail.disableBots,
|
||||
disableNPCs: event.detail.disableNPCs,
|
||||
},
|
||||
() => this.joinModal.close()
|
||||
);
|
||||
|
||||
@@ -9,6 +9,8 @@ export class SinglePlayerModal extends LitElement {
|
||||
@state() private isModalOpen = false;
|
||||
@state() private selectedMap: GameMapType = GameMapType.World;
|
||||
@state() private selectedDifficulty: Difficulty = Difficulty.Medium;
|
||||
@state() private disableNPCs = false;
|
||||
@state() private disableBots = false;
|
||||
|
||||
static styles = css`
|
||||
.modal-overlay {
|
||||
@@ -115,6 +117,22 @@ export class SinglePlayerModal extends LitElement {
|
||||
)}
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<input
|
||||
type="checkbox"
|
||||
id="disable-bots"
|
||||
@change=${this.handleDisableBotsChange}
|
||||
/>
|
||||
<label for="disable-bots">Disable Bots</label>
|
||||
</div>
|
||||
<div>
|
||||
<input
|
||||
type="checkbox"
|
||||
id="disable-npcs"
|
||||
@change=${this.handleDisableNPCsChange}
|
||||
/>
|
||||
<label for="disable-npcs">Disable NPCs</label>
|
||||
</div>
|
||||
|
||||
<button @click=${this.startGame}>Start Game</button>
|
||||
</div>
|
||||
@@ -140,6 +158,12 @@ export class SinglePlayerModal extends LitElement {
|
||||
(e.target as HTMLSelectElement).value,
|
||||
) as Difficulty;
|
||||
}
|
||||
private handleDisableBotsChange(e: Event) {
|
||||
this.disableBots = Boolean((e.target as HTMLInputElement).checked);
|
||||
}
|
||||
private handleDisableNPCsChange(e: Event) {
|
||||
this.disableNPCs = Boolean((e.target as HTMLInputElement).checked);
|
||||
}
|
||||
private startGame() {
|
||||
consolex.log(
|
||||
`Starting single player game with map: ${GameMapType[this.selectedMap]}`,
|
||||
@@ -153,6 +177,8 @@ export class SinglePlayerModal extends LitElement {
|
||||
},
|
||||
map: this.selectedMap,
|
||||
difficulty: this.selectedDifficulty,
|
||||
disableBots: this.disableBots,
|
||||
disableNPCs: this.disableNPCs,
|
||||
},
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
|
||||
@@ -58,9 +58,11 @@ export class GameRunner {
|
||||
) {}
|
||||
|
||||
init() {
|
||||
this.game.addExecution(
|
||||
...this.execManager.spawnBots(this.game.config().numBots())
|
||||
);
|
||||
if (this.game.config().spawnBots()) {
|
||||
this.game.addExecution(
|
||||
...this.execManager.spawnBots(this.game.config().numBots())
|
||||
);
|
||||
}
|
||||
if (this.game.config().spawnNPCs()) {
|
||||
this.game.addExecution(...this.execManager.fakeHumanExecutions());
|
||||
}
|
||||
|
||||
@@ -92,6 +92,8 @@ const GameConfigSchema = z.object({
|
||||
gameMap: z.nativeEnum(GameMapType),
|
||||
difficulty: z.nativeEnum(Difficulty),
|
||||
gameType: z.nativeEnum(GameType),
|
||||
disableBots: z.boolean(),
|
||||
disableNPCs: z.boolean(),
|
||||
});
|
||||
|
||||
const SafeString = z
|
||||
|
||||
@@ -70,6 +70,7 @@ export interface Config {
|
||||
percentageTilesOwnedToWin(): number;
|
||||
numBots(): number;
|
||||
spawnNPCs(): boolean;
|
||||
spawnBots(): boolean;
|
||||
numSpawnPhaseTurns(): number;
|
||||
|
||||
startManpower(playerInfo: PlayerInfo): number;
|
||||
|
||||
@@ -76,7 +76,10 @@ export class DefaultConfig implements Config {
|
||||
return 5;
|
||||
}
|
||||
spawnNPCs(): boolean {
|
||||
return true;
|
||||
return !this._gameConfig.disableNPCs;
|
||||
}
|
||||
spawnBots(): boolean {
|
||||
return !this._gameConfig.disableBots;
|
||||
}
|
||||
tradeShipGold(dist: number): Gold {
|
||||
return 10000 + 100 * Math.pow(dist, 1.1);
|
||||
|
||||
@@ -49,6 +49,8 @@ export class GameManager {
|
||||
gameMap: GameMapType.World,
|
||||
gameType: GameType.Private,
|
||||
difficulty: Difficulty.Medium,
|
||||
disableBots: false,
|
||||
disableNPCs: false,
|
||||
})
|
||||
);
|
||||
return id;
|
||||
@@ -87,6 +89,8 @@ export class GameManager {
|
||||
gameMap: this.random.randElement(Object.values(GameMapType)),
|
||||
gameType: GameType.Public,
|
||||
difficulty: Difficulty.Medium,
|
||||
disableBots: false,
|
||||
disableNPCs: false,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -57,6 +57,12 @@ export class GameServer {
|
||||
if (gameConfig.difficulty != null) {
|
||||
this.gameConfig.difficulty = gameConfig.difficulty;
|
||||
}
|
||||
if (gameConfig.disableBots != null) {
|
||||
this.gameConfig.disableBots = gameConfig.disableBots;
|
||||
}
|
||||
if (gameConfig.disableNPCs != null) {
|
||||
this.gameConfig.disableNPCs = gameConfig.disableNPCs;
|
||||
}
|
||||
}
|
||||
|
||||
public addClient(client: Client, lastTurn: number) {
|
||||
|
||||
@@ -94,6 +94,8 @@ app.put("/private_lobby/:id", (req, res) => {
|
||||
gm.updateGameConfig(lobbyID, {
|
||||
gameMap: req.body.gameMap,
|
||||
difficulty: req.body.difficulty,
|
||||
disableBots: req.body.disableBots,
|
||||
disableNPCs: req.body.disableNPCs,
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user