Merge branch 'main' into local-attack

This commit is contained in:
Aotumuri
2026-02-08 07:37:59 +09:00
committed by GitHub
19 changed files with 334 additions and 41 deletions
+26
View File
@@ -755,6 +755,32 @@ class Client {
if (decodedHash.startsWith("#refresh")) {
window.location.href = "/";
}
// Handle requeue parameter for ranked matchmaking
const searchParams = new URLSearchParams(window.location.search);
if (searchParams.has("requeue")) {
// Remove only the requeue parameter, preserving other params and hash
searchParams.delete("requeue");
const newUrl =
window.location.pathname +
(searchParams.toString() ? "?" + searchParams.toString() : "") +
window.location.hash;
history.replaceState(null, "", newUrl);
// Wait for matchmaking button to be defined, then trigger its click handler
// This goes through username validation instead of bypassing it
customElements.whenDefined("matchmaking-button").then(() => {
const matchmakingButton = document.querySelector(
"matchmaking-button button",
) as HTMLButtonElement | null;
if (matchmakingButton) {
matchmakingButton.click();
} else {
console.warn(
"Requeue requested, but matchmaking button not found in DOM.",
);
}
});
}
}
private async handleJoinLobby(event: CustomEvent<JoinLobbyEvent>) {
+1 -1
View File
@@ -320,7 +320,7 @@ export class MatchmakingButton extends LitElement {
window.showPage?.("page-account");
}
private open() {
public open() {
this.matchmakingModal?.open();
}
+61 -34
View File
@@ -16,8 +16,11 @@ export class GameLeftSidebar extends LitElement implements Layer {
private isLeaderboardShow = false;
@state()
private isTeamLeaderboardShow = false;
@state()
private isVisible = false;
@state()
private isPlayerTeamLabelVisible = false;
@state()
private playerTeam: string | null = null;
private playerColor: Colord = new Colord("#FFFFFF");
@@ -59,7 +62,7 @@ export class GameLeftSidebar extends LitElement implements Layer {
this.requestUpdate();
}
if (!this.game.inSpawnPhase()) {
if (!this.game.inSpawnPhase() && this.isPlayerTeamLabelVisible) {
this.isPlayerTeamLabelVisible = false;
this.requestUpdate();
}
@@ -91,10 +94,65 @@ export class GameLeftSidebar extends LitElement implements Layer {
this.isVisible ? "translate-x-0" : "hidden"
}`}
>
<div class="flex items-center gap-4 xl:gap-6 text-white">
<div
class="cursor-pointer p-0.5 bg-gray-700/50 hover:bg-gray-600 border rounded-md border-slate-500 transition-colors"
@click=${this.toggleLeaderboard}
role="button"
tabindex="0"
@keydown=${(e: KeyboardEvent) => {
if (e.key === "Enter" || e.key === " " || e.code === "Space") {
e.preventDefault();
this.toggleLeaderboard();
}
}}
>
<img
src=${this.isLeaderboardShow
? leaderboardSolidIcon
: leaderboardRegularIcon}
alt=${translateText("help_modal.icon_alt_player_leaderboard") ||
"Player Leaderboard Icon"}
width="20"
height="20"
/>
</div>
${this.isTeamGame
? html`
<div
class="cursor-pointer p-0.5 bg-gray-700/50 hover:bg-gray-600 border rounded-md border-slate-500 transition-colors"
@click=${this.toggleTeamLeaderboard}
role="button"
tabindex="0"
@keydown=${(e: KeyboardEvent) => {
if (
e.key === "Enter" ||
e.key === " " ||
e.code === "Space"
) {
e.preventDefault();
this.toggleTeamLeaderboard();
}
}}
>
<img
src=${this.isTeamLeaderboardShow
? teamSolidIcon
: teamRegularIcon}
alt=${translateText(
"help_modal.icon_alt_team_leaderboard",
) || "Team Leaderboard Icon"}
width="20"
height="20"
/>
</div>
`
: null}
</div>
${this.isPlayerTeamLabelVisible
? html`
<div
class="flex items-center w-full h-8 lg:h-10 text-white py-1 lg:p-2"
class="flex items-center w-full text-white"
@contextmenu=${(e: Event) => e.preventDefault()}
>
${translateText("help_modal.ui_your_team")}
@@ -108,39 +166,8 @@ export class GameLeftSidebar extends LitElement implements Layer {
`
: null}
<div
class=${`flex items-center gap-2 text-white ${
this.isLeaderboardShow || this.isTeamLeaderboardShow ? "mb-2" : ""
}`}
class=${`block lg:flex flex-wrap ${this.isLeaderboardShow && this.isTeamLeaderboardShow ? "gap-2" : ""}`}
>
<div class="cursor-pointer" @click=${this.toggleLeaderboard}>
<img
src=${this.isLeaderboardShow
? leaderboardSolidIcon
: leaderboardRegularIcon}
alt="treeIcon"
width="20"
height="20"
/>
</div>
${this.isTeamGame
? html`
<div
class="cursor-pointer"
@click=${this.toggleTeamLeaderboard}
>
<img
src=${this.isTeamLeaderboardShow
? teamSolidIcon
: teamRegularIcon}
alt="treeIcon"
width="20"
height="20"
/>
</div>
`
: null}
</div>
<div class="block lg:flex flex-wrap gap-2">
<leader-board .visible=${this.isLeaderboardShow}></leader-board>
<team-stats
class="flex-1"
+4 -2
View File
@@ -177,7 +177,7 @@ export class Leaderboard extends LitElement implements Layer {
}
return html`
<div
class="max-h-[35vh] overflow-y-auto text-white text-xs md:text-xs lg:text-sm md:max-h-[50vh] ${this
class="max-h-[35vh] overflow-y-auto text-white text-xs md:text-xs lg:text-sm md:max-h-[50vh] mt-2 ${this
.visible
? ""
: "hidden"}"
@@ -265,7 +265,9 @@ export class Leaderboard extends LitElement implements Layer {
</div>
<button
class="mt-1 px-1.5 py-0.5 md:px-2 md:py-0.5 text-xs md:text-xs lg:text-sm border border-white/20 hover:bg-white/10 text-white mx-auto block"
class="mt-1 px-1.5 pb-0.5 md:px-2 text-xs md:text-xs lg:text-sm
border rounded-md border-slate-500 transition-colors
text-white mx-auto block hover:bg-white/10"
@click=${() => {
this.showTopFive = !this.showTopFive;
this.updateLeaderboard();
+1 -1
View File
@@ -132,7 +132,7 @@ export class TeamStats extends LitElement implements Layer {
return html`
<div
class="max-h-[30vh] overflow-y-auto grid bg-slate-800/70 w-full text-white text-xs md:text-sm"
class="max-h-[30vh] overflow-y-auto grid bg-slate-800/70 w-full text-white text-xs md:text-sm mt-2"
@contextmenu=${(e: MouseEvent) => e.preventDefault()}
>
<div
+24 -1
View File
@@ -8,6 +8,7 @@ import {
} from "../../../client/Utils";
import { ColorPalette, Pattern } from "../../../core/CosmeticSchemas";
import { EventBus } from "../../../core/EventBus";
import { RankedType } from "../../../core/game/Game";
import { GameUpdateType } from "../../../core/game/GameUpdates";
import { GameView } from "../../../core/game/GameView";
import { getUserMe } from "../../Api";
@@ -37,6 +38,9 @@ export class WinModal extends LitElement implements Layer {
@state()
private isWin = false;
@state()
private isRankedGame = false;
@state()
private patternContent: TemplateResult | null = null;
@@ -75,11 +79,21 @@ export class WinModal extends LitElement implements Layer {
>
${translateText("win_modal.exit")}
</button>
${this.isRankedGame
? html`
<button
@click=${this._handleRequeue}
class="flex-1 px-3 py-3 text-base cursor-pointer bg-purple-600 text-white border-0 rounded-sm transition-all duration-200 hover:bg-purple-500 hover:-translate-y-px active:translate-y-px"
>
${translateText("win_modal.requeue")}
</button>
`
: null}
<button
@click=${this.hide}
class="flex-1 px-3 py-3 text-base cursor-pointer bg-blue-500/60 text-white border-0 rounded-sm transition-all duration-200 hover:bg-blue-500/80 hover:-translate-y-px active:translate-y-px"
>
${this.isWin
${this.game.myPlayer()?.isAlive()
? translateText("win_modal.keep")
: translateText("win_modal.spectate")}
</button>
@@ -251,6 +265,9 @@ export class WinModal extends LitElement implements Layer {
async show() {
crazyGamesSDK.gameplayStop();
await this.loadPatternContent();
// Check if this is a ranked game
this.isRankedGame =
this.game.config().gameConfig().rankedType === RankedType.OneVOne;
this.isVisible = true;
this.requestUpdate();
setTimeout(() => {
@@ -270,6 +287,12 @@ export class WinModal extends LitElement implements Layer {
window.location.href = "/";
}
private _handleRequeue() {
this.hide();
// Navigate to homepage and open matchmaking modal
window.location.href = "/?requeue";
}
init() {}
tick() {
+2
View File
@@ -118,6 +118,7 @@ export enum GameMapType {
Didier = "Didier",
DidierFrance = "Didier France",
AmazonRiver = "Amazon River",
Yenisei = "Yenisei",
}
export type GameMapName = keyof typeof GameMapType;
@@ -165,6 +166,7 @@ export const mapCategories: Record<string, GameMapType[]> = {
GameMapType.TwoLakes,
GameMapType.StraitOfHormuz,
GameMapType.AmazonRiver,
GameMapType.Yenisei,
],
fantasy: [
GameMapType.Pangaea,
+4 -1
View File
@@ -988,7 +988,10 @@ export class PlayerImpl implements Player {
}
const cost = this.mg.unitInfo(unitType).cost(this.mg, this);
if (!this.isAlive() || this.gold() < cost) {
if (
unitType !== UnitType.MIRVWarhead &&
(!this.isAlive() || this.gold() < cost)
) {
return false;
}
switch (unitType) {
+1
View File
@@ -66,6 +66,7 @@ const frequency: Partial<Record<GameMapName, number>> = {
AmazonRiver: 3,
Sierpinski: 10,
TheBox: 3,
Yenisei: 6,
};
interface MapWithMode {