diff --git a/resources/lang/en.json b/resources/lang/en.json index d9b6c0d9b..56c8941cd 100644 --- a/resources/lang/en.json +++ b/resources/lang/en.json @@ -280,6 +280,8 @@ }, "map": { "map": "Map", + "featured": "Featured", + "all": "All", "world": "World", "giantworldmap": "Giant World Map", "europe": "Europe", @@ -330,6 +332,7 @@ "amazonriver": "Amazon River" }, "map_categories": { + "featured": "Featured", "continental": "Continental", "regional": "Regional", "fantasy": "Other", diff --git a/src/client/HelpModal.ts b/src/client/HelpModal.ts index a5d150f3f..e696db76f 100644 --- a/src/client/HelpModal.ts +++ b/src/client/HelpModal.ts @@ -3,7 +3,6 @@ import { customElement, state } from "lit/decorators.js"; import { translateText } from "../client/Utils"; import { BaseModal } from "./components/BaseModal"; import "./components/Difficulties"; -import "./components/Maps"; import { modalHeader } from "./components/ui/ModalHeader"; import { TroubleshootingModal } from "./TroubleshootingModal"; diff --git a/src/client/HostLobbyModal.ts b/src/client/HostLobbyModal.ts index 5355f9f33..eff76894b 100644 --- a/src/client/HostLobbyModal.ts +++ b/src/client/HostLobbyModal.ts @@ -12,7 +12,6 @@ import { Quads, Trios, UnitType, - mapCategories, } from "../core/game/Game"; import { ClientInfo, @@ -28,7 +27,7 @@ import "./components/CopyButton"; import "./components/Difficulties"; import "./components/FluentSlider"; import "./components/LobbyPlayerView"; -import "./components/Maps"; +import "./components/map/MapPicker"; import { modalHeader } from "./components/ui/ModalHeader"; import { crazyGamesSDK } from "./CrazyGamesSDK"; import { JoinLobbyEvent } from "./Main"; @@ -38,7 +37,6 @@ import { renderToggleInputCardInput, } from "./utilities/RenderToggleInputCard"; import { renderUnitTypeOptions } from "./utilities/RenderUnitTypeOptions"; -import randomMap from "/images/RandomMap.webp?url"; @customElement("host-lobby-modal") export class HostLobbyModal extends BaseModal { @state() private selectedMap: GameMapType = GameMapType.World; @@ -209,80 +207,14 @@ export class HostLobbyModal extends BaseModal { ${translateText("map.map")} -
- - ${Object.entries(mapCategories).map( - ([categoryKey, maps]) => html` -
-

- ${translateText(`map_categories.${categoryKey}`)} -

-
- ${maps.map((mapValue) => { - const mapKey = Object.entries(GameMapType).find( - ([, v]) => v === mapValue, - )?.[0]; - return html` -
this.handleMapSelection(mapValue)} - class="cursor-pointer transition-transform duration-200 active:scale-95" - > - -
- `; - })} -
-
- `, - )} - -
-

- ${translateText("map_categories.special")} -

-
- -
-
-
+ + this.handleMapSelection(mapValue)} + .onSelectRandom=${() => this.handleSelectRandomMap()} + > diff --git a/src/client/SinglePlayerModal.ts b/src/client/SinglePlayerModal.ts index dece359e4..e423d7596 100644 --- a/src/client/SinglePlayerModal.ts +++ b/src/client/SinglePlayerModal.ts @@ -13,7 +13,6 @@ import { Quads, Trios, UnitType, - mapCategories, } from "../core/game/Game"; import { UserSettings } from "../core/game/UserSettings"; import { TeamCountConfig } from "../core/Schemas"; @@ -24,7 +23,7 @@ import "./components/baseComponents/Modal"; import { BaseModal } from "./components/BaseModal"; import "./components/Difficulties"; import "./components/FluentSlider"; -import "./components/Maps"; +import "./components/map/MapPicker"; import { modalHeader } from "./components/ui/ModalHeader"; import { fetchCosmetics } from "./Cosmetics"; import { FlagInput } from "./FlagInput"; @@ -35,7 +34,6 @@ import { renderToggleInputCardInput, } from "./utilities/RenderToggleInputCard"; import { renderUnitTypeOptions } from "./utilities/RenderUnitTypeOptions"; -import randomMap from "/images/RandomMap.webp?url"; @customElement("single-player-modal") export class SinglePlayerModal extends BaseModal { @@ -197,84 +195,15 @@ export class SinglePlayerModal extends BaseModal { -
- ${Object.entries(mapCategories).map( - ([categoryKey, maps]) => html` -
-

- ${translateText(`map_categories.${categoryKey}`)} -

-
- ${maps.map((mapValue) => { - const mapKey = Object.keys(GameMapType).find( - (key) => - GameMapType[key as keyof typeof GameMapType] === - mapValue, - ); - return html` -
this.handleMapSelection(mapValue)} - class="cursor-pointer transition-transform duration-200 active:scale-95" - > - -
- `; - })} -
-
- `, - )} - - -
-

- ${translateText("map_categories.special")} -

-
- -
-
-
+ + this.handleMapSelection(mapValue)} + .onSelectRandom=${() => this.handleSelectRandomMap()} + > diff --git a/src/client/components/Maps.ts b/src/client/components/map/MapDisplay.ts similarity index 96% rename from src/client/components/Maps.ts rename to src/client/components/map/MapDisplay.ts index e46e4691b..b7fc1364c 100644 --- a/src/client/components/Maps.ts +++ b/src/client/components/map/MapDisplay.ts @@ -1,8 +1,8 @@ import { LitElement, html } from "lit"; import { customElement, property, state } from "lit/decorators.js"; -import { Difficulty, GameMapType } from "../../core/game/Game"; -import { terrainMapFileLoader } from "../TerrainMapFileLoader"; -import { translateText } from "../Utils"; +import { Difficulty, GameMapType } from "../../../core/game/Game"; +import { terrainMapFileLoader } from "../../TerrainMapFileLoader"; +import { translateText } from "../../Utils"; @customElement("map-display") export class MapDisplay extends LitElement { diff --git a/src/client/components/map/MapPicker.ts b/src/client/components/map/MapPicker.ts new file mode 100644 index 000000000..52607622e --- /dev/null +++ b/src/client/components/map/MapPicker.ts @@ -0,0 +1,183 @@ +import { LitElement, html } from "lit"; +import { customElement, property, state } from "lit/decorators.js"; +import { + Difficulty, + GameMapType, + mapCategories, +} from "../../../core/game/Game"; +import { translateText } from "../../Utils"; +import "./MapDisplay"; +import randomMap from "/images/RandomMap.webp?url"; + +const featuredMaps: GameMapType[] = [ + GameMapType.World, + GameMapType.Europe, + GameMapType.NorthAmerica, + GameMapType.SouthAmerica, + GameMapType.Asia, + GameMapType.Africa, + GameMapType.Japan, +]; + +@customElement("map-picker") +export class MapPicker extends LitElement { + @property({ type: String }) selectedMap: GameMapType = GameMapType.World; + @property({ type: Boolean }) useRandomMap = false; + @property({ type: Boolean }) showMedals = false; + @property({ type: Boolean }) randomMapDivider = false; + @property({ attribute: false }) mapWins: Map> = + new Map(); + @property({ attribute: false }) onSelectMap?: (map: GameMapType) => void; + @property({ attribute: false }) onSelectRandom?: () => void; + @state() private showAllMaps = false; + + createRenderRoot() { + return this; + } + + private handleMapSelection(mapValue: GameMapType) { + this.onSelectMap?.(mapValue); + } + + private handleSelectRandomMap = () => { + this.onSelectRandom?.(); + }; + + private getWins(mapValue: GameMapType): Set { + return this.mapWins?.get(mapValue) ?? new Set(); + } + + private renderMapCard(mapValue: GameMapType) { + const mapKey = Object.entries(GameMapType).find( + ([_, value]) => value === mapValue, + )?.[0]; + return html` +
this.handleMapSelection(mapValue)} + class="cursor-pointer transition-transform duration-200 active:scale-95" + > + +
+ `; + } + + private renderAllMaps() { + const mapCategoryEntries = Object.entries(mapCategories); + return html`
+ ${mapCategoryEntries.map( + ([categoryKey, maps]) => html` +
+

+ ${translateText(`map_categories.${categoryKey}`)} +

+
+ ${maps.map((mapValue) => this.renderMapCard(mapValue))} +
+
+ `, + )} +
`; + } + + private renderFeaturedMaps() { + let featuredMapList = featuredMaps; + if (!featuredMapList.includes(this.selectedMap)) { + featuredMapList = [this.selectedMap, ...featuredMaps]; + } + return html`
+

+ ${translateText("map_categories.featured")} +

+
+ ${featuredMapList.map((mapValue) => this.renderMapCard(mapValue))} +
+
`; + } + + render() { + return html` +
+
+
+ + +
+
+ ${this.showAllMaps ? this.renderAllMaps() : this.renderFeaturedMaps()} +
+

+ ${translateText("map_categories.special")} +

+
+ +
+
+
+ `; + } +}