Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions resources/lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,8 @@
"left_click_label": "Left Click to Open Menu",
"left_click_desc": "When ON, left-click opens menu and sword button attacks. When OFF, left-click attacks directly.",
"left_click_menu": "Left Click Menu",
"team_stop_trade_all_label": "Stop Trading with All (Team Games Only)",
"team_stop_trade_all_desc": "If enabled, team games automatically use \"Stop Trading with All\" at game start.",
"attack_ratio_label": "⚔️ Attack Ratio",
"attack_ratio_desc": "What percentage of your troops to send in an attack (1–100%)",
"territory_patterns_label": "🏳️ Territory Skins",
Expand Down
49 changes: 48 additions & 1 deletion src/client/ClientGameRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@ import {
import { createPartialGameRecord, findClosestBy, replacer } from "../core/Util";
import { ServerConfig } from "../core/configuration/Config";
import { getGameLogicConfig } from "../core/configuration/ConfigLoader";
import { BuildableUnit, Structures, UnitType } from "../core/game/Game";
import {
BuildableUnit,
GameMode,
Structures,
UnitType,
} from "../core/game/Game";
import { TileRef } from "../core/game/GameMap";
import { GameMapLoader } from "../core/game/GameMapLoader";
import {
Expand Down Expand Up @@ -42,6 +47,7 @@ import { terrainMapFileLoader } from "./TerrainMapFileLoader";
import {
SendAttackIntentEvent,
SendBoatAttackIntentEvent,
SendEmbargoAllIntentEvent,
SendHashEvent,
SendSpawnIntentEvent,
SendUpgradeStructureIntentEvent,
Expand Down Expand Up @@ -268,6 +274,7 @@ async function createClientGame(
transport,
worker,
gameView,
userSettings,
);
}

Expand All @@ -284,6 +291,9 @@ export class ClientGameRunner {

private lastTickReceiveTime: number = 0;
private currentTickDelay: number | undefined = undefined;
private startTradeEmbargoAtTick: number | null = null;
private startTradeEmbargoApplied = false;
private startTradeModeInitialized = false;

constructor(
private lobby: LobbyConfig,
Expand All @@ -294,6 +304,7 @@ export class ClientGameRunner {
private transport: Transport,
private worker: WorkerClient,
private gameView: GameView,
private userSettings: UserSettings,
) {
this.lastMessageTime = Date.now();
}
Expand Down Expand Up @@ -392,6 +403,15 @@ export class ClientGameRunner {
this.eventBus.emit(new SendHashEvent(hu.tick, hu.hash));
});
this.gameView.update(gu);
if (
this.startTradeEmbargoAtTick !== null &&
!this.startTradeEmbargoApplied &&
this.gameView.ticks() >= this.startTradeEmbargoAtTick
) {
this.eventBus.emit(new SendEmbargoAllIntentEvent("start"));
this.startTradeEmbargoApplied = true;
this.startTradeEmbargoAtTick = null;
}
this.renderer.tick();

// Emit tick metrics event for performance overlay
Expand All @@ -415,6 +435,30 @@ export class ClientGameRunner {
this.lastMessageTime = Date.now();
if (message.type === "start") {
console.log("starting game! in client game runner");
if (!this.startTradeModeInitialized) {
this.startTradeModeInitialized = true;
const isTeamGame =
this.gameView.config().gameConfig().gameMode === GameMode.Team;
if (
isTeamGame &&
!this.gameView.config().isReplay() &&
this.userSettings.stopTradingAllAtStartForTeamGames()
) {
// gameView.ticks() is still 0 here (worker has not applied start turns yet).
// Using it would re-schedule the embargo on every reconnect from tick 0 and
// could re-emit "start" after the cooldown already passed. Anchor to server
// progress: game tick after this batch equals last turnNumber + 1 (see
// GameServer.endTurn).
const cooldownTicks = this.gameView.config().embargoAllCooldown();
const gameTickAfterBatch =
message.turns.length > 0
? message.turns[message.turns.length - 1].turnNumber + 1
: this.turnsSeen;
if (gameTickAfterBatch < cooldownTicks) {
this.startTradeEmbargoAtTick = cooldownTicks;
}
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

if (this.gameView.config().isRandomSpawn()) {
const goToPlayer = () => {
Expand Down Expand Up @@ -538,6 +582,9 @@ export class ClientGameRunner {
clearTimeout(this.goToPlayerTimeout);
this.goToPlayerTimeout = null;
}
this.startTradeEmbargoAtTick = null;
this.startTradeEmbargoApplied = false;
this.startTradeModeInitialized = false;
}

private inputEvent(event: MouseUpEvent) {
Expand Down
16 changes: 16 additions & 0 deletions src/client/UserSettingModal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,14 @@ export class UserSettingModal extends BaseModal {
this.requestUpdate();
}

private toggleStopTradeAllForTeamGames(e: CustomEvent<{ checked: boolean }>) {
const enabled = e.detail?.checked;
if (typeof enabled !== "boolean") return;

this.userSettings.setStopTradingAllAtStartForTeamGames(enabled);
this.requestUpdate();
}

private sliderAttackRatio(e: CustomEvent<{ value: number }>) {
const value = e.detail?.value;
if (typeof value === "number") {
Expand Down Expand Up @@ -867,6 +875,14 @@ export class UserSettingModal extends BaseModal {
@change=${this.toggleLeftClickOpensMenu}
></setting-toggle>

<setting-toggle
label="${translateText("user_setting.team_stop_trade_all_label")}"
description="${translateText("user_setting.team_stop_trade_all_desc")}"
id="team-stop-trade-all-toggle"
.checked=${this.userSettings.stopTradingAllAtStartForTeamGames()}
@change=${this.toggleStopTradeAllForTeamGames}
></setting-toggle>

<!-- 🙈 Anonymous Names -->
<setting-toggle
label="${translateText("user_setting.anonymous_names_label")}"
Expand Down
8 changes: 8 additions & 0 deletions src/core/game/UserSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,4 +265,12 @@ export class UserSettings {
setSoundEffectsVolume(volume: number): void {
this.setFloat("settings.soundEffectsVolume", volume);
}

stopTradingAllAtStartForTeamGames(): boolean {
return this.get("settings.stopTradingAllAtStartForTeamGames", false);
}

setStopTradingAllAtStartForTeamGames(enabled: boolean): void {
this.set("settings.stopTradingAllAtStartForTeamGames", enabled);
}
}
Loading