diff --git a/agot-bg-game-server/package.json b/agot-bg-game-server/package.json index 64817a9f9..5a3122d03 100644 --- a/agot-bg-game-server/package.json +++ b/agot-bg-game-server/package.json @@ -29,7 +29,7 @@ "classnames": "^2.3.1", "css-loader": "^6.7.3", "dotenv": "^14.2.0", - "emoji-picker-react": "^4.0.6", + "emoji-picker-react": "^4.10.0", "eslint": "^8.7.0", "eslint-plugin-react": "^7.28.0", "express": "^4.17.2", diff --git a/agot-bg-game-server/src/client/GameClient.ts b/agot-bg-game-server/src/client/GameClient.ts index 550138c80..a0fbc5d28 100644 --- a/agot-bg-game-server/src/client/GameClient.ts +++ b/agot-bg-game-server/src/client/GameClient.ts @@ -42,9 +42,29 @@ export default class GameClient { chatClient: ChatClient = new ChatClient(this); sfxManager: SfxManager = new SfxManager(this); + get currentVolumeSettings(): { notifications: number, music: number, sfx: number} { + if (!this.authenticatedUser) { + throw new Error("Authenticated user required"); + } + return { + notifications: this.authenticatedUser.settings.notificationsVolume, + music: this.authenticatedUser.settings.musicVolume, + sfx: this.authenticatedUser.settings.sfxVolume + }; + } + + private set currentVolumeSettings(value: { notifications: number, music: number, sfx: number}) { + if (!this.authenticatedUser) { + throw new Error("Authenticated user required"); + } + this.authenticatedUser.settings.notificationsVolume = value.notifications ?? 1; + this.authenticatedUser.settings.musicVolume = value.music ?? 1; + this.authenticatedUser.settings.sfxVolume = value.sfx ?? 1; + } + get muted(): boolean { if (!this.authenticatedUser) { - throw new Error("Game client must have an authenticated user"); + throw new Error("Authenticated user required"); } return this.authenticatedUser.settings.muted; @@ -52,40 +72,33 @@ export default class GameClient { set muted(value: boolean) { if (!this.authenticatedUser) { - throw new Error("Game client must have an authenticated user"); + throw new Error("Authenticated user required"); } this.authenticatedUser.settings.muted = value; if (value == true) { - const oldVolumes = { - notificationsVolume: this.authenticatedUser.settings.notificationsVolume, - musicVolume: this.authenticatedUser.settings.musicVolume, - sfxVolume: this.authenticatedUser.settings.sfxVolume - }; - localStorage.setItem('oldVolumes', JSON.stringify(oldVolumes)); + sessionStorage.setItem('oldVolumes', JSON.stringify(this.currentVolumeSettings)); - this.authenticatedUser.settings.notificationsVolume = 0; - this.authenticatedUser.settings.musicVolume = 0; - this.authenticatedUser.settings.sfxVolume = 0; + this.currentVolumeSettings = {notifications: 0, music: 0, sfx: 0}; this.sfxManager.muteAll(); } else { - const oldVolumesFromStorage = JSON.parse(localStorage.getItem('oldVolumes') || '{}'); - this.authenticatedUser.settings.notificationsVolume = oldVolumesFromStorage.notificationsVolume ?? 1; - this.authenticatedUser.settings.musicVolume = oldVolumesFromStorage.musicVolume ?? 1; - this.authenticatedUser.settings.sfxVolume = oldVolumesFromStorage.sfxVolume ?? 1; + const oldVolumesFromStorage = JSON.parse(sessionStorage.getItem('oldVolumes') || '{}'); + this.currentVolumeSettings = oldVolumesFromStorage; - localStorage.removeItem('oldVolumes'); + localStorage.removeItem('oldVolumes'); // Todo: Remove this some day + sessionStorage.removeItem('oldVolumes'); this.sfxManager.unmuteAll(); } + localStorage.setItem('volumeSettings', JSON.stringify(this.currentVolumeSettings)); this.authenticatedUser.syncSettings(); } get notificationsVolume(): number { if (!this.authenticatedUser) { - throw new Error("Game client must have an authenticated user"); + throw new Error("Authenticated user required"); } return this.authenticatedUser.settings.notificationsVolume; @@ -93,18 +106,18 @@ export default class GameClient { set notificationsVolume(value: number) { if (!this.authenticatedUser) { - throw new Error("Game client must have an authenticated user"); + throw new Error("Authenticated user required"); } this.authenticatedUser.settings.notificationsVolume = value; - this.setCurrentMutedState(value); + this.setCurrentMutedStateAndSaveVolumeSettingsToLocalStorage(); this.authenticatedUser.syncSettings(); } get musicVolume(): number { if (!this.authenticatedUser) { - throw new Error("Game client must have an authenticated user"); + throw new Error("Authenticated user required"); } return this.authenticatedUser.settings.musicVolume; @@ -112,18 +125,18 @@ export default class GameClient { set musicVolume(value: number) { if (!this.authenticatedUser) { - throw new Error("Game client must have an authenticated user"); + throw new Error("Authenticated user required"); } this.authenticatedUser.settings.musicVolume = value; - this.setCurrentMutedState(value); + this.setCurrentMutedStateAndSaveVolumeSettingsToLocalStorage(); this.authenticatedUser.syncSettings(); } get sfxVolume(): number { if (!this.authenticatedUser) { - throw new Error("Game client must have an authenticated user"); + throw new Error("Authenticated user required"); } return this.authenticatedUser.settings.sfxVolume; @@ -131,18 +144,18 @@ export default class GameClient { set sfxVolume(value: number) { if (!this.authenticatedUser) { - throw new Error("Game client must have an authenticated user"); + throw new Error("Authenticated user required"); } this.authenticatedUser.settings.sfxVolume = value; - this.setCurrentMutedState(value); + this.setCurrentMutedStateAndSaveVolumeSettingsToLocalStorage(); this.authenticatedUser.syncSettings(); } get authenticatedPlayer(): Player | null { if (!this.authenticatedUser) { - throw new Error("Game client must have an authenticated user"); + throw new Error("Authenticated user required"); } if (!this.entireGame || !(this.entireGame.childGameState instanceof IngameGameState)) { @@ -156,16 +169,18 @@ export default class GameClient { } } - private setCurrentMutedState(value: number): void { + private setCurrentMutedStateAndSaveVolumeSettingsToLocalStorage(): void { if (!this.authenticatedUser) { return; } - if (value > 0) { - this.authenticatedUser.settings.muted = false; - } else if (this.musicVolume == 0 && this.notificationsVolume == 0 && this.sfxVolume == 0) { + if (this.musicVolume == 0 && this.notificationsVolume == 0 && this.sfxVolume == 0) { this.authenticatedUser.settings.muted = true; + } else { + this.authenticatedUser.settings.muted = false; } + + localStorage.setItem('volumeSettings', JSON.stringify(this.currentVolumeSettings)); } constructor(authData: AuthData) { @@ -307,6 +322,7 @@ export default class GameClient { this.connectionState = ConnectionState.SYNCED; this.isReconnecting = false; + this.loadVolumeSettingsFromLocalStorage(); } else if (message.type == "new-private-chat-room") { if (this.entireGame == null) { return; @@ -377,4 +393,15 @@ export default class GameClient { this.authenticatedUser = null; this.isReconnecting = false; } + + private loadVolumeSettingsFromLocalStorage(): void { + const item = localStorage.getItem('volumeSettings'); + if (!item) { + return; + } + + const volumeSettings = JSON.parse(item); + this.currentVolumeSettings = volumeSettings; + this.setCurrentMutedStateAndSaveVolumeSettingsToLocalStorage(); + } } diff --git a/agot-bg-game-server/src/client/MapComponent.tsx b/agot-bg-game-server/src/client/MapComponent.tsx index 24dd40e90..8880e1ba3 100644 --- a/agot-bg-game-server/src/client/MapComponent.tsx +++ b/agot-bg-game-server/src/client/MapComponent.tsx @@ -525,10 +525,10 @@ export default class MapComponent extends Component { let order: Order | null = null; let orderPresent = false; - if (this.ingame.childGameState instanceof PlanningGameState && this.ingame.childGameState.childGameState instanceof PlaceOrdersGameState) { - const placeOrders = this.ingame.childGameState.childGameState; - orderPresent = placeOrders.placedOrders.has(region); - order = orderPresent ? placeOrders.placedOrders.get(region) : null; + if (this.ingame.childGameState instanceof PlanningGameState) { + const planning = this.ingame.childGameState; + orderPresent = planning.placedOrders.has(region); + order = orderPresent ? planning.placedOrders.get(region) : null; } else { orderPresent = this.ingame.ordersOnBoard.has(region); order = orderPresent ? this.ingame.ordersOnBoard.get(region) : null; diff --git a/agot-bg-game-server/src/client/chat-client/ChatComponent.tsx b/agot-bg-game-server/src/client/chat-client/ChatComponent.tsx index ee2c0f145..c71ff9cd7 100644 --- a/agot-bg-game-server/src/client/chat-client/ChatComponent.tsx +++ b/agot-bg-game-server/src/client/chat-client/ChatComponent.tsx @@ -174,7 +174,7 @@ export default class ChatComponent extends Component { theme={Theme.DARK} autoFocusSearch={!isMobile} emojiStyle={isMobile ? EmojiStyle.NATIVE : EmojiStyle.APPLE} - suggestedEmojisMode={SuggestionMode.FREQUENT} + suggestedEmojisMode={SuggestionMode.RECENT} lazyLoadEmojis={true} onEmojiClick={(emoji) => { const input = document.getElementById(`chat-client-input-${this.channel.id}`) as HTMLInputElement; diff --git a/agot-bg-game-server/src/client/game-state-panel/PlaceOrdersComponent.tsx b/agot-bg-game-server/src/client/game-state-panel/PlaceOrdersComponent.tsx index 982660edc..6477d1ef3 100644 --- a/agot-bg-game-server/src/client/game-state-panel/PlaceOrdersComponent.tsx +++ b/agot-bg-game-server/src/client/game-state-panel/PlaceOrdersComponent.tsx @@ -50,10 +50,6 @@ export default class PlaceOrdersComponent extends Component - {!this.forVassals ? ( - <>Players must now place orders in every area where they have at least one unit. - ) : ( - <>Players must now place orders for their vassals. - )} + Players must now place orders in every area where they have at least one unit. {this.placeOrders.parentGameState.planningRestrictions.map(pr => this.restrictionToWesterosCardTypeMap.tryGet(pr, null)) .map(prWc => prWc != null ? @@ -76,7 +68,7 @@ export default class PlaceOrdersComponent extends Component : <>) } - {this.props.gameClient.authenticatedPlayer && this.showButtons() && ( + {this.props.gameClient.authenticatedPlayer && ( + + + )} + + + Waiting for {this.house.name}... + + + + + + ); + } + + componentDidMount(): void { + this.props.mapControls.modifyRegionsOnMap.push(this.modifyRegionsOnMapCallback = () => this.modifyRegionsOnMap()); + this.props.mapControls.modifyOrdersOnMap.push(this.modifyOrdersOnMapCallback = () => this.modifyOrdersOnMap()); + } + + componentWillUnmount(): void { + _.pull(this.props.mapControls.modifyRegionsOnMap, this.modifyRegionsOnMapCallback); + _.pull(this.props.mapControls.modifyOrdersOnMap, this.modifyOrdersOnMapCallback); + } + + modifyRegionsOnMap(): [Region, PartialRecursive][] { + if (this.doesControlCurrentHouse) { + const possibleRegions = _.flatMap(this.housesToPlaceOrdersFor.map(h => this.singlePlaceOrders.placeOrdersGameState.getPossibleRegionsForOrders(h))); + + return possibleRegions.map(r => [ + r, + { + // Highlight areas with no order + highlight: { active: !this.singlePlaceOrders.placedOrders.has(r) }, + wrap: (child: ReactElement) => ( + + +
{r.name}
+ + +
+ +
+
+ +
+ + { + this.singlePlaceOrders.assignOrder(r, o); + document.body.click(); + }} /> + + + } + > + {child} +
+ ) + } + ] as [Region, PartialRecursive]); + } + + return []; + } + + modifyOrdersOnMap(): [Region, PartialRecursive][] { + if (this.doesControlCurrentHouse) { + return _.flatMap( + this.housesToPlaceOrdersFor.map(h => this.singlePlaceOrders.placeOrdersGameState.getPossibleRegionsForOrders(h).map(r => [ + r, + { + highlight: { active: true }, + onClick: () => this.onOrderClick(r) + } + ] as [Region, PartialRecursive])) + ); + } + + return []; + } + + onOrderClick(region: Region): void { + if (!this.doesControlCurrentHouse) { + return; + } + + this.singlePlaceOrders.assignOrder(region, null); + } + + onSubmitClick(): void { + if (!this.doesControlCurrentHouse || !this.props.gameClient.authenticatedPlayer) { + return; + } + + const readyState = this.singlePlaceOrders.placeOrdersGameState.canSubmit(this.props.gameClient.authenticatedPlayer); + + if (readyState.reason == "not-all-regions-filled") { + if (!window.confirm("You may place up to two order tokens. Are you sure you want to continue with fewer?")) { + return; + } + } + + this.singlePlaceOrders.submit(); + } +} diff --git a/agot-bg-game-server/src/common/ingame-game-state/IngameGameState.ts b/agot-bg-game-server/src/common/ingame-game-state/IngameGameState.ts index a43c416d0..9bd6b30dd 100644 --- a/agot-bg-game-server/src/common/ingame-game-state/IngameGameState.ts +++ b/agot-bg-game-server/src/common/ingame-game-state/IngameGameState.ts @@ -32,7 +32,7 @@ import CombatGameState from "./action-game-state/resolve-march-order-game-state/ import DeclareSupportGameState from "./action-game-state/resolve-march-order-game-state/combat-game-state/declare-support-game-state/DeclareSupportGameState"; import shuffle from "../../utils/shuffle"; import shuffleInPlace from "../../utils/shuffleInPlace"; -import popRandom from "../../utils/popRandom"; +import popRandom, { pickRandom } from "../../utils/popRandom"; import LoanCard from "./game-data-structure/loan-card/LoanCard"; import PayDebtsGameState, { SerializedPayDebtsGameState } from "./pay-debts-game-state/PayDebtsGameState"; import { objectiveCards } from "./game-data-structure/static-data-structure/objectiveCards"; @@ -46,6 +46,7 @@ import houseCardAbilities from "./game-data-structure/house-card/houseCardAbilit import SnrError from "../../utils/snrError"; import { TakeOverPort, findOrphanedShipsAndDestroyThem, isTakeControlOfEnemyPortRequired } from "./port-helper/PortHelper"; import { dragon } from "./game-data-structure/unitTypes"; +import groupBy from "../../utils/groupBy"; export const NOTE_MAX_LENGTH = 5000; @@ -955,13 +956,18 @@ export default class IngameGameState extends GameState< // Find new random commander let newCommander: House | null = null; - for (const house of shuffle(this.game.getTurnOrder()).filter(h => !this.isVassalHouse(h))) { - if (!forbiddenCommanders.includes(house)) { - newCommander = house; - break; - } + + const possibleCommanders = this.game.houses.values.filter(h => !this.isVassalHouse(h) && !forbiddenCommanders.includes(h)); + const commandersByVassalCount = groupBy(possibleCommanders, h => this.getVassalsControlledByPlayer(this.getControllerOfHouse(h)).length); + + const commanders = _.sortBy(commandersByVassalCount.entries, ([count, _commanders]) => count).shift(); + + if (!commanders) { + throw new SnrError(this.entireGame, "Unable to determine new commander"); } + newCommander = pickRandom(commanders[1]); + if (!newCommander) { throw new SnrError(this.entireGame, "Unable to determine new commander"); } @@ -1074,6 +1080,9 @@ export default class IngameGameState extends GameState< } }); + // Remove orphaned orders + this.actionState?.findOrphanedOrdersAndRemoveThem(); + // Destroy orphaned ships in ports findOrphanedShipsAndDestroyThem(this, this.actionState); diff --git a/agot-bg-game-server/src/common/ingame-game-state/action-game-state/resolve-march-order-game-state/ResolveMarchOrderGameState.ts b/agot-bg-game-server/src/common/ingame-game-state/action-game-state/resolve-march-order-game-state/ResolveMarchOrderGameState.ts index db23be33f..eb60914ea 100644 --- a/agot-bg-game-server/src/common/ingame-game-state/action-game-state/resolve-march-order-game-state/ResolveMarchOrderGameState.ts +++ b/agot-bg-game-server/src/common/ingame-game-state/action-game-state/resolve-march-order-game-state/ResolveMarchOrderGameState.ts @@ -62,9 +62,6 @@ export default class ResolveMarchOrderGameState extends GameState< onResolveSingleMarchOrderGameStateFinish(house: House): void { // Last march is completely handled - // Remove orphaned orders (e.g. caused by Mace Tyrell or Ilyn Payne or due to failed retreat) - this.actionGameState.findOrphanedOrdersAndRemoveThem(); - // Reset all card abilities (e.g. due to DWD Queen of Thorns) const manipulatedHouseCards = this.game.getAllHouseCardsInGame().values .filter(hc => hc.disabled || hc.originalCombatStrength !== undefined); diff --git a/agot-bg-game-server/src/common/ingame-game-state/planning-game-state/PlanningGameState.ts b/agot-bg-game-server/src/common/ingame-game-state/planning-game-state/PlanningGameState.ts index 07d5d1cd6..ae789a9ab 100644 --- a/agot-bg-game-server/src/common/ingame-game-state/planning-game-state/PlanningGameState.ts +++ b/agot-bg-game-server/src/common/ingame-game-state/planning-game-state/PlanningGameState.ts @@ -16,8 +16,15 @@ import planningRestrictions from "../game-data-structure/westeros-card/planning- import MusteringGameState, { SerializedMusteringGameState } from "../westeros-game-state/mustering-game-state/MusteringGameState"; import WesterosCard from "../game-data-structure/westeros-card/WesterosCard"; import getById from "../../../utils/getById"; - -export default class PlanningGameState extends GameState { +import PlaceOrdersForVassalsGameState, { SerializedPlaceOrdersForVassalsGameState } from "./place-orders-for-vassals-game-state/PlaceOrdersForVassalsGameState"; +import { observable } from "mobx"; +import orders from "../game-data-structure/orders"; + +export default class PlanningGameState extends GameState { + // Server-side, the value of the map should never be null. + // Client-side, the client can receive a null value if it is the order of an other player, + // it thus represents a face-down order (this player can't see it). + @observable placedOrders: BetterMap = new BetterMap(); planningRestrictions: PlanningRestriction[]; revealeadWesterosCards: WesterosCard[]; @@ -64,12 +71,12 @@ export default class PlanningGameState extends GameState): void { - if (!forVassals) { - this.setChildGameState(new PlaceOrdersGameState(this)).firstStart(orders, true); - } else { - this.ingame.proceedToActionGameState(orders, this.planningRestrictions); - } + onPlaceOrderFinish(): void { + this.setChildGameState(new PlaceOrdersForVassalsGameState(this)).firstStart(); + } + + onPlaceOrderForVassalsFinish(): void { + this.ingame.proceedToActionGameState(this.placedOrders as BetterMap, this.planningRestrictions); } onMusteringGameStateEnd(): void { @@ -77,8 +84,24 @@ export default class PlanningGameState extends GameState r.id, (o, r) => { + // Hide orders that doesn't belong to the player + // If admin, send all orders. + const controller = r.getController(); + if (admin || (player && controller != null && (controller == player.house || (this.ingame.isVassalHouse(controller) && this.ingame.isVassalControlledByPlayer(controller, player))))) { + return o ? o.id : null; + } + return null; + }); + + if (this.entireGame.gameSettings.fogOfWar && !admin && player != null) { + const visibleRegionIds = this.ingame.getVisibleRegionsForPlayer(player).map(r => r.id); + placedOrders = placedOrders.filter(([rid, _oid]) => visibleRegionIds.includes(rid)); + } + return { type: "planning", + placedOrders: placedOrders, planningRestrictions: this.planningRestrictions.map(pr => pr.id), revealedWesterosCardIds: this.revealeadWesterosCards.map(wc => wc.id), childGameState: this.childGameState.serializeToClient(admin, player) @@ -90,6 +113,14 @@ export default class PlanningGameState extends GameState planningRestrictions.get(prid)); planningGameState.revealeadWesterosCards = data.revealedWesterosCardIds.map((cid, i) => getById(ingameGameState.game.westerosDecks[i], cid)); + planningGameState.placedOrders = new BetterMap( + data.placedOrders.map( + ([regionId, orderId]) => [ + ingameGameState.world.regions.get(regionId), + orderId ? orders.get(orderId) : null + ] + ) + ); planningGameState.childGameState = planningGameState.deserializeChildGameState(data.childGameState); return planningGameState; @@ -99,6 +130,8 @@ export default class PlanningGameState extends GameState { + @observable house: House; + @observable commanders: House[] = []; + + get ingame(): IngameGameState { + return this.parentGameState.parentGameState; + } + + get planningGameState(): PlanningGameState { + return this.parentGameState; + } + + get world(): World { + return this.ingame.game.world; + } + + get placedOrders(): BetterMap { + return this.planningGameState.placedOrders; + } + + firstStart(): void { + this.commanders = this.ingame.game.getTurnOrder().filter(h => !this.ingame.isVassalHouse(h) + && this.ingame.getVassalsControlledByPlayer(this.ingame.getControllerOfHouse(h)).length > 0); + + if (this.ingame.getVassalHouses().length > 0) { + // Only if vassals are in game we want to add this log + this.ingame.log({ + type: "planning-phase-began", + forVassals: true + }); + } + + this.proceedNextResolve(); + } + + submitOrders(player: Player, resolvedAutomatically = false): void { + if (!this.canSubmit(player).status) { + return; + } + + this.ingame.log({ + type: "player-action", + house: player.house.id, + action: PlayerActionType.ORDERS_PLACED, + forHouses: this.ingame.getVassalsControlledByPlayer(player).map(h => h.id) + }, resolvedAutomatically); + + this.proceedNextResolve(); + } + + private proceedNextResolve(): void { + const next = this.commanders.shift(); + + if (next) { + this.setChildGameState(new ResolveSinglePlaceOrdersForVassalsGameState(this)).firstStart(next); + this.entireGame.broadcastToClients({ + type: "next-house", + house: next.id + }); + return; + } + + this.planningGameState.onPlaceOrderForVassalsFinish(); + } + + serializeToClient(admin: boolean, player: Player | null): SerializedPlaceOrdersForVassalsGameState { + return { + type: "place-orders-for-vassals", + commanders: this.commanders.map(h => h.id), + childGameState: this.childGameState.serializeToClient(admin, player) + }; + } + + /* + * Common + */ + + canSubmit(player: Player): {status: boolean; reason: string} { + // Here we can bypass canSubmit for debugging + // return {status: true, reason: "bypassed"}; + + // Iterate over all the houses the player should put orders for to find + // an error in one of the houses. + const possibleError = this.getHousesToPutOrdersForPlayer(player).reduce((state, house) => { + const orderList = this.getOrdersList(house); + if (this.getPlacedOrdersOfHouse(house).some(([_r, o]) => !orderList.includes(o))){ + return {status: false, reason: "invalid-orders-placed"}; + } + + const possibleRegions = this.getPossibleRegionsForOrders(house); + + const regionsWithOrders = possibleRegions.filter(r => this.placedOrders.has(r)); + + if (possibleRegions.length > MAX_VASSAL_ORDERS) { + if(regionsWithOrders.length == MAX_VASSAL_ORDERS) { + return state; + } else if (regionsWithOrders.length > MAX_VASSAL_ORDERS) { + return {status: false, reason: "too-much-orders-placed"}; + } + } + + if (possibleRegions.every(r => this.placedOrders.has(r))) { + return state; + } else { + return {status: true, reason: "not-all-regions-filled"}; + } + }, null); + + return possibleError ? possibleError as {status: boolean; reason: string} : {status: true, reason: ""}; + } + + onPlayerMessage(player: Player, message: ClientMessage): void { + this.childGameState.onPlayerMessage(player, message); + } + + onServerMessage(message: ServerMessage): void { + this.childGameState.onServerMessage(message); + } + + /** + * Queries + */ + + getHousesToPutOrdersForPlayer(player: Player): House[] { + return this.ingame.getVassalsControlledByPlayer(player); + } + + getOrdersList(house: House): Order[] { + return this.ingame.game.getOrdersListForHouse(house); + } + + getAvailableOrders(house: House): Order[] { + return this.ingame.game.getAvailableOrders(this.placedOrders, house); + } + + isOrderAvailable(house: House, order: Order): boolean { + return this.getAvailableOrders(house).includes(order); + } + + getPlacedOrdersOfHouse(house: House): [Region, Order][] { + const possibleRegions = this.world.regions.values.filter(r => r.units.size > 0 && r.getController() == house); + + return possibleRegions.filter(r => this.placedOrders.tryGet(r, null) != null).map(r => [r, this.placedOrders.get(r) as Order]); + } + + getPossibleRegionsForOrders(house: House): Region[] { + const possibleRegions = this.world.regions.values.filter(r => r.units.size > 0 && r.getController() == house); + + if (!this.ingame.isVassalHouse(house)) { + return []; + } + + const regionsWithOrders = possibleRegions.filter(r => this.placedOrders.has(r)); + + if (regionsWithOrders.length == MAX_VASSAL_ORDERS) { + return regionsWithOrders; + } + + return possibleRegions; + } + + static deserializeFromServer(planning: PlanningGameState, data: SerializedPlaceOrdersForVassalsGameState): PlaceOrdersForVassalsGameState { + const placeOrder = new PlaceOrdersForVassalsGameState(planning); + + placeOrder.commanders = data.commanders.map(hid => planning.ingame.game.houses.get(hid)); + placeOrder.childGameState = ResolveSinglePlaceOrdersForVassalsGameState.deserializeFromServer(placeOrder, data.childGameState); + + return placeOrder; + } +} + +export interface SerializedPlaceOrdersForVassalsGameState { + type: "place-orders-for-vassals"; + commanders: string[]; + childGameState: SerializedSinglePlaceOrdersForVassalsGameState; +} diff --git a/agot-bg-game-server/src/common/ingame-game-state/planning-game-state/place-orders-for-vassals-game-state/resolve-single-place-orders-for-vassals-game-state/ResolveSinglePlaceOrdersForVassalsGameState.ts b/agot-bg-game-server/src/common/ingame-game-state/planning-game-state/place-orders-for-vassals-game-state/resolve-single-place-orders-for-vassals-game-state/ResolveSinglePlaceOrdersForVassalsGameState.ts new file mode 100644 index 000000000..674dde5ad --- /dev/null +++ b/agot-bg-game-server/src/common/ingame-game-state/planning-game-state/place-orders-for-vassals-game-state/resolve-single-place-orders-for-vassals-game-state/ResolveSinglePlaceOrdersForVassalsGameState.ts @@ -0,0 +1,191 @@ +import GameState from "../../../../GameState"; +import IngameGameState from "../../../IngameGameState"; +import {ClientMessage} from "../../../../../messages/ClientMessage"; +import Player from "../../../Player"; +import Order from "../../../game-data-structure/Order"; +import Region from "../../../game-data-structure/Region"; +import World from "../../../game-data-structure/World"; +import orders from "../../../game-data-structure/orders"; +import User from "../../../../../server/User"; +import {ServerMessage} from "../../../../../messages/ServerMessage"; +import {observable} from "mobx"; +import BetterMap from "../../../../../utils/BetterMap"; +import Game from "../../../game-data-structure/Game"; +import House from "../../../game-data-structure/House"; +import PlanningGameState from "../../PlanningGameState"; +import _ from "lodash"; +import PlaceOrdersGameState from "../../place-orders-game-state/PlaceOrdersGameState"; +import PlaceOrdersForVassalsGameState from "../PlaceOrdersForVassalsGameState"; + +export default class ResolveSinglePlaceOrdersForVassalsGameState extends GameState { + @observable house: House; + + get ingame(): IngameGameState { + return this.parentGameState.parentGameState.parentGameState; + } + + get planningGameState(): PlanningGameState { + return this.parentGameState.parentGameState; + } + + get placeOrdersGameState(): PlaceOrdersForVassalsGameState { + return this.parentGameState; + } + + get placedOrders(): BetterMap { + return this.planningGameState.placedOrders; + } + + get game(): Game { + return this.ingame.game; + } + + get world(): World { + return this.game.world; + } + + firstStart(house: House): void { + this.house = house; + const player = this.ingame.getControllerOfHouse(house); + const availableRegionsForOrders = this.ingame.getVassalsControlledByPlayer(player).reduce((count, h) => count + this.placeOrdersGameState.getPossibleRegionsForOrders(h).length, 0); + if (availableRegionsForOrders == 0) { + this.placeOrdersGameState.submitOrders(player, true); + } + } + + onPlayerMessage(player: Player, message: ClientMessage): void { + if (message.type == "place-order") { + if (this.ingame.getControllerOfHouse(this.house) != player) { + return; + } + + const order = message.orderId ? orders.get(message.orderId) : null; + const region = this.world.regions.get(message.regionId); + + // Retrieve the house for which this order has been placed for. + const house = _.find(this.placeOrdersGameState.getHousesToPutOrdersForPlayer(player), h => this.placeOrdersGameState.getPossibleRegionsForOrders(h).includes(region)); + + if (house == null) { + return; + } + + if (order && !this.placeOrdersGameState.isOrderAvailable(house, order)) { + return; + } + + if (order && this.game.isOrderRestricted(region, order, this.planningGameState.planningRestrictions, true)) { + const availableOrders = this.placeOrdersGameState.getAvailableOrders(house).filter(o => o != order); + if (availableOrders.some(o => !this.game.isOrderRestricted(region, o, this.planningGameState.planningRestrictions, true))) { + // Player has to use their legal orders first + return; + } + } + + if (order) { + this.placedOrders.set(region, order); + player.user.send({ + type: "order-placed", + order: order.id, + region: region.id + }); + + this.ingame.sendMessageToUsersWhoCanSeeRegion({ + type: "order-placed", + region: region.id, + order: null + }, region, player.user); + } else if (this.placedOrders.has(region)) { + this.placedOrders.delete(region); + this.ingame.sendMessageToUsersWhoCanSeeRegion({ + type: "remove-placed-order", + regionId: region.id + }, region); + } + } else if (message.type == "ready") { + if (this.ingame.getControllerOfHouse(this.house) != player) { + return; + } + + this.placeOrdersGameState.submitOrders(player); + } + } + + getWaitedUsers(): User[] { + return [this.ingame.getControllerOfHouse(this.house).user]; + } + + serializeToClient(_admin: boolean, _player: Player | null): SerializedSinglePlaceOrdersForVassalsGameState { + return { + type: "single-place-orders-for-vassals", + house: this.house.id + }; + } + + /** + * Client + */ + assignOrder(region: Region, order: Order | null): void { + this.entireGame.sendMessageToServer({ + type: "place-order", + regionId: region.id, + orderId: order ? order.id : null + }); + } + + submit(): void { + this.entireGame.sendMessageToServer({ + type: "ready" + }); + } + + onServerMessage(message: ServerMessage): void { + if (message.type == "order-placed") { + const region = this.world.regions.get(message.region); + const order = message.order ? orders.get(message.order) : null; + + this.placedOrders.set(region, order); + } else if (message.type == "remove-placed-order") { + const region = this.world.regions.get(message.regionId); + + if (this.placedOrders.has(region)) { + this.placedOrders.delete(region); + } + } else if (message.type == "next-house") { + this.house = this.game.houses.get(message.house); + } + } + + /* + Action after vassal replacement + */ + + actionAfterVassalReplacement(newVassal: House): void { + // Remove already placed orders of house: + const placedOrders = this.placeOrdersGameState.getPlacedOrdersOfHouse(newVassal); + placedOrders.forEach(([r, _o]) => { + this.placedOrders.delete(r); + }); + + // A new vassal may want players to change their orders. + // So we restart planning phase to force players to commit their orders again + + // Reset waitedFor data, to properly call ingame.setWaitedForPlayers() by the game-state-change + this.ingame.resetAllWaitedForData(); + + // game-state-change will notify all waited users, no need to do it explicitly + this.planningGameState.setChildGameState(new PlaceOrdersGameState(this.planningGameState)).firstStart(); + } + + static deserializeFromServer(placeOrdersForVassals: PlaceOrdersForVassalsGameState, data: SerializedSinglePlaceOrdersForVassalsGameState): ResolveSinglePlaceOrdersForVassalsGameState { + const singlePlaceOrder = new ResolveSinglePlaceOrdersForVassalsGameState(placeOrdersForVassals); + + singlePlaceOrder.house = placeOrdersForVassals.ingame.game.houses.get(data.house); + + return singlePlaceOrder; + } +} + +export interface SerializedSinglePlaceOrdersForVassalsGameState { + type: "single-place-orders-for-vassals"; + house: string; +} diff --git a/agot-bg-game-server/src/common/ingame-game-state/planning-game-state/place-orders-game-state/PlaceOrdersGameState.ts b/agot-bg-game-server/src/common/ingame-game-state/planning-game-state/place-orders-game-state/PlaceOrdersGameState.ts index 2c41d8dcb..5507babd3 100644 --- a/agot-bg-game-server/src/common/ingame-game-state/planning-game-state/place-orders-game-state/PlaceOrdersGameState.ts +++ b/agot-bg-game-server/src/common/ingame-game-state/planning-game-state/place-orders-game-state/PlaceOrdersGameState.ts @@ -17,21 +17,9 @@ import PlanningGameState from "../PlanningGameState"; import { PlayerActionType } from "../../game-data-structure/GameLog"; import _ from "lodash"; -const MAX_VASSAL_ORDERS = 2; - export default class PlaceOrdersGameState extends GameState { - // Server-side, the value of the map should never be null. - // Client-side, the client can receive a null value if it is the order of an other player, - // it thus represents a face-down order (this player can't see it). - @observable placedOrders: BetterMap = new BetterMap(); @observable readyHouses: House[] = []; - /** - * Indicates whether this PlaceOrdersGameState phase is for vassals or for non-vassals. - * PlanningGameState will first go through a phase for non-vassals and then a phase for vassals. - */ - @observable forVassals: boolean; - get ingame(): IngameGameState { return this.parentGameState.parentGameState; } @@ -53,31 +41,22 @@ export default class PlaceOrdersGameState extends GameState { } get participatingHouses(): House[] { - return this.forVassals ? this.ingame.getVassalHouses() : this.game.nonVassalHouses; + return this.game.nonVassalHouses; } - firstStart(orders = new BetterMap(), forVassals = false): void { - this.placedOrders = orders; - this.forVassals = forVassals; - - if (!this.forVassals || this.ingame.getVassalHouses().length > 0) { - this.ingame.log({ - type: "planning-phase-began", - forVassals: this.forVassals - }); - } + get placedOrders(): BetterMap { + return this.planningGameState.placedOrders; + } - if (this.forVassals && this.ingame.getVassalHouses().length == 0) { - // No vassals, we can end this state - this.planningGameState.onPlaceOrderFinish(this.forVassals, this.placedOrders as BetterMap); - return; - } + firstStart(): void { + this.ingame.log({ + type: "planning-phase-began", + forVassals: false + }); // Automatically set ready for houses which can't place orders this.ingame.players.forEach(p => { - const availableRegionsForOrders = this.forVassals - ? this.ingame.getVassalsControlledByPlayer(p).reduce((count, h) => count + this.getPossibleRegionsForOrders(h).length, 0) - : this.getPossibleRegionsForOrders(p.house).length; + const availableRegionsForOrders = this.getPossibleRegionsForOrders(p.house).length; if (availableRegionsForOrders == 0) { this.setReady(p, true); @@ -90,24 +69,17 @@ export default class PlaceOrdersGameState extends GameState { return; } - if (this.forVassals) { - this.readyHouses.push(...this.ingame.getVassalsControlledByPlayer(player)); - } else { - this.readyHouses.push(player.house); - } + this.readyHouses.push(player.house); // This is for debug to allow bypassing canReady and a player sending "ready" more than once // It doesn't hurt on the live system either... this.readyHouses = _.uniq(this.readyHouses); - if (!this.forVassals || this.ingame.getVassalsControlledByPlayer(player).length > 0) { - this.ingame.log({ - type: "player-action", - house: player.house.id, - action: PlayerActionType.ORDERS_PLACED, - forHouses: this.forVassals ? this.ingame.getVassalsControlledByPlayer(player).map(h => h.id) : undefined - }, resolvedAutomatically); - } + this.ingame.log({ + type: "player-action", + house: player.house.id, + action: PlayerActionType.ORDERS_PLACED, + }, resolvedAutomatically); this.entireGame.broadcastToClients({ type: "player-ready", @@ -120,7 +92,7 @@ export default class PlaceOrdersGameState extends GameState { private checkAndProceedEndOfPlaceOrdersGameState(): boolean { if (this.readyHouses.length == this.participatingHouses.length) { - this.planningGameState.onPlaceOrderFinish(this.forVassals, this.placedOrders as BetterMap); + this.planningGameState.onPlaceOrderFinish(); return true; } @@ -128,8 +100,7 @@ export default class PlaceOrdersGameState extends GameState { } canUnready(player: Player): {status: boolean; reason: string} { - if ((this.forVassals && this.ingame.getVassalsControlledByPlayer(player).some(h => !this.isReady(h))) - || (!this.forVassals && !this.isReady(player.house))) { + if (!this.isReady(player.house)) { return {status: false, reason: "not-ready"}; } @@ -141,9 +112,7 @@ export default class PlaceOrdersGameState extends GameState { return; } - this.readyHouses = this.forVassals - ? _.without(this.readyHouses, ...this.ingame.getVassalsControlledByPlayer(player)) - : _.without(this.readyHouses, player.house); + this.readyHouses = _.without(this.readyHouses, player.house); this.entireGame.broadcastToClients({ type: "player-unready", @@ -218,48 +187,17 @@ export default class PlaceOrdersGameState extends GameState { getPossibleRegionsForOrders(house: House): Region[] { const possibleRegions = this.game.world.regions.values.filter(r => r.units.size > 0 && r.getController() == house); - if (!this.forVassals) { - if (!this.ingame.isVassalHouse(house)) { - return possibleRegions; - } else { - return []; - } - } - if (!this.ingame.isVassalHouse(house)) { + return possibleRegions; + } else { return []; } - - const regionsWithOrders = possibleRegions.filter(r => this.placedOrders.has(r)); - - if (regionsWithOrders.length == MAX_VASSAL_ORDERS) { - return regionsWithOrders; - } - - return possibleRegions; } - serializeToClient(admin: boolean, player: Player | null): SerializedPlaceOrdersGameState { - let placedOrders = this.placedOrders.mapOver(r => r.id, (o, r) => { - // Hide orders that doesn't belong to the player - // If admin, send all orders. - const controller = r.getController(); - if (admin || (player && controller != null && (controller == player.house || (this.ingame.isVassalHouse(controller) && this.ingame.isVassalControlledByPlayer(controller, player))))) { - return o ? o.id : null; - } - return null; - }); - - if (this.entireGame.gameSettings.fogOfWar && !admin && player != null) { - const visibleRegionIds = this.ingame.getVisibleRegionsForPlayer(player).map(r => r.id); - placedOrders = placedOrders.filter(([rid, _oid]) => visibleRegionIds.includes(rid)); - } - + serializeToClient(_admin: boolean, _player: Player | null): SerializedPlaceOrdersGameState { return { type: "place-orders", - placedOrders: placedOrders, - readyHouses: this.readyHouses.map(h => h.id), - forVassals: this.forVassals + readyHouses: this.readyHouses.map(h => h.id) }; } @@ -272,8 +210,7 @@ export default class PlaceOrdersGameState extends GameState { // return {status: true, reason: "bypassed"}; // Return false if player is already ready - if ((!this.forVassals && this.isReady(player.house)) - || (this.forVassals && this.ingame.getVassalsControlledByPlayer(player).every(h => this.isReady(h)))) + if (this.isReady(player.house)) { return {status: false, reason: "already-ready"}; } @@ -288,24 +225,6 @@ export default class PlaceOrdersGameState extends GameState { const possibleRegions = this.getPossibleRegionsForOrders(house); - if (this.forVassals) { - const regionsWithOrders = possibleRegions.filter(r => this.placedOrders.has(r)); - - if (possibleRegions.length > MAX_VASSAL_ORDERS) { - if(regionsWithOrders.length == MAX_VASSAL_ORDERS) { - return state; - } else if (regionsWithOrders.length > MAX_VASSAL_ORDERS) { - return {status: false, reason: "too-much-orders-placed"}; - } - } - - if (possibleRegions.every(r => this.placedOrders.has(r))) { - return state; - } else { - return {status: false, reason: "not-all-regions-filled"}; - } - } - if (possibleRegions.every(r => this.placedOrders.has(r)) || this.getAvailableOrders(house).length == 0) { // All possible regions have orders @@ -355,18 +274,10 @@ export default class PlaceOrdersGameState extends GameState { } } else if (message.type == "player-ready") { const player = this.ingame.players.get(this.entireGame.users.get(message.userId)); - - if (this.forVassals) { - this.readyHouses.push(...this.ingame.getVassalsControlledByPlayer(player)); - } else { - this.readyHouses.push(player.house); - } + this.readyHouses.push(player.house); } else if (message.type == "player-unready") { const player = this.ingame.players.get(this.entireGame.users.get(message.userId)); - - this.readyHouses = this.forVassals - ? _.without(this.readyHouses, ...this.ingame.getVassalsControlledByPlayer(player)) - : _.without(this.readyHouses, player.house); + this.readyHouses = _.without(this.readyHouses, player.house); } } @@ -374,17 +285,8 @@ export default class PlaceOrdersGameState extends GameState { * Queries */ - /** - * For a given player, returns all the houses for which `player` must place - * orders for. Depending on `this.forVassals`, this may be simply the house of the - * player, or the list of vassals commanded by the player. - */ getHousesToPutOrdersForPlayer(player: Player): House[] { - if (!this.forVassals) { - return [player.house]; - } else { - return this.ingame.getVassalsControlledByPlayer(player); - } + return [player.house]; } getNotReadyPlayers(): Player[] { @@ -425,22 +327,13 @@ export default class PlaceOrdersGameState extends GameState { this.ingame.resetAllWaitedForData(); // game-state-change will notify all waited users, no need to do it explicitly - this.parentGameState.setChildGameState(new PlaceOrdersGameState(this.parentGameState)).firstStart(this.placedOrders as BetterMap); + this.parentGameState.setChildGameState(new PlaceOrdersGameState(this.parentGameState)).firstStart(); } static deserializeFromServer(planning: PlanningGameState, data: SerializedPlaceOrdersGameState): PlaceOrdersGameState { const placeOrder = new PlaceOrdersGameState(planning); - placeOrder.placedOrders = new BetterMap( - data.placedOrders.map( - ([regionId, orderId]) => [ - planning.world.regions.get(regionId), - orderId ? orders.get(orderId) : null - ] - ) - ); placeOrder.readyHouses = data.readyHouses.map(hid => planning.ingame.game.houses.get(hid)); - placeOrder.forVassals = data.forVassals; return placeOrder; } @@ -448,7 +341,5 @@ export default class PlaceOrdersGameState extends GameState { export interface SerializedPlaceOrdersGameState { type: "place-orders"; - placedOrders: [string, number | null][]; readyHouses: string[]; - forVassals: boolean; } diff --git a/agot-bg-game-server/src/common/ingame-game-state/vote-system/VoteType.ts b/agot-bg-game-server/src/common/ingame-game-state/vote-system/VoteType.ts index a154a2a27..800d2ba3f 100644 --- a/agot-bg-game-server/src/common/ingame-game-state/vote-system/VoteType.ts +++ b/agot-bg-game-server/src/common/ingame-game-state/vote-system/VoteType.ts @@ -598,17 +598,12 @@ export class ReplaceVassalByPlayer extends VoteType { const placeOrders = vote.ingame.leafState instanceof PlaceOrdersGameState ? vote.ingame.leafState : null; if (placeOrders) { const planning = placeOrders.parentGameState; - const placedPlayerOrders = placeOrders.placedOrders.entries.filter(([r, o]) => { - const ctrl = r.getController(); - // Server-side the order is never null but it doesn't hurt to check before we cast to - return o != null && ctrl && !vote.ingame.isVassalHouse(ctrl) && ctrl != this.forHouse; - }) as [Region, Order][]; // Reset waitedFor data, to properly call ingame.setWaitedForPlayers() by the game-state-change vote.ingame.resetAllWaitedForData(); // game-state-change will notify all waited users, no need to do it explicitly - planning.setChildGameState(new PlaceOrdersGameState(planning)).firstStart(new BetterMap(placedPlayerOrders)); + planning.setChildGameState(new PlaceOrdersGameState(planning)).firstStart(); } else if (vote.ingame.leafState.getWaitedUsers().includes(newPlayer.user)) { // If we are waiting for the newPlayer, notify them about their turn newPlayer.setWaitedFor(); diff --git a/agot-bg-game-server/src/messages/ServerMessage.ts b/agot-bg-game-server/src/messages/ServerMessage.ts index 94b65b6d3..cffa8a887 100644 --- a/agot-bg-game-server/src/messages/ServerMessage.ts +++ b/agot-bg-game-server/src/messages/ServerMessage.ts @@ -17,7 +17,7 @@ import { SerializedRegion } from "../common/ingame-game-state/game-data-structur export type ServerMessage = NewUser | HouseChosen | AuthenticationResponse | OrderPlaced | PlayerReady | PlayerUnready | HouseCardChosen | SupportDeclared | SupportRefused | NewTurn | RemovePlacedOrder - | MoveUnits | CombatChangeArmy + | MoveUnits | CombatChangeArmy | NextHouse | UnitsWounded | ChangeCombatHouseCard | BeginSeeTopWildlingCard | RavenOrderReplaced | RevealTopWildlingCard | HideTopWildlingCard | ProceedWesterosCard | ChangeGarrison | BiddingBegin | BidDone | BiddingNextTrack | GameStateChange | SupplyAdjusted @@ -574,4 +574,9 @@ interface UpdatePublicVisibleRegionsForSpectators { ordersToMakeVisible?: [string, number][]; clear?: boolean; applyChangesNow?: boolean; -} \ No newline at end of file +} + +interface NextHouse { + type: "next-house"; + house: string; +} diff --git a/agot-bg-game-server/src/server/serializedGameMigrations.ts b/agot-bg-game-server/src/server/serializedGameMigrations.ts index e1d35c6bb..28ceba1d9 100644 --- a/agot-bg-game-server/src/server/serializedGameMigrations.ts +++ b/agot-bg-game-server/src/server/serializedGameMigrations.ts @@ -2367,6 +2367,23 @@ const serializedGameMigrations: {version: string; migrate: (serializeGamed: any) return result; } } + }, + { + version: "120", + migrate: (serializedGame: any) => { + if (serializedGame.childGameState.type == "ingame" && serializedGame.childGameState.childGameState.type == "planning") { + const planning = serializedGame.childGameState.childGameState; + + if (planning.childGameState.type == "place-orders") { + planning.placedOrders = planning.childGameState.placedOrders; + + if (planning.childGameState.forVassals) { + planning.childGameState.readyHouses = []; + } + } + } + return serializedGame; + } } ]; diff --git a/agot-bg-game-server/yarn.lock b/agot-bg-game-server/yarn.lock index 4221261de..6b34c348b 100644 --- a/agot-bg-game-server/yarn.lock +++ b/agot-bg-game-server/yarn.lock @@ -335,14 +335,6 @@ "@babel/plugin-transform-react-jsx-development" "^7.14.5" "@babel/plugin-transform-react-pure-annotations" "^7.14.5" -"@babel/runtime-corejs3@^7.10.2": - version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.19.1.tgz#f0cbbe7edda7c4109cd253bb1dee99aba4594ad9" - integrity sha512-j2vJGnkopRzH+ykJ8h68wrHnEUmtK//E723jjixiAl/PPf6FhqY/vYRcMVlNydRKQjQsTsYEjpx+DZMIvnGk/g== - dependencies: - core-js-pure "^3.25.1" - regenerator-runtime "^0.13.4" - "@babel/runtime-corejs3@^7.15.4": version "7.16.8" resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.16.8.tgz#ea533d96eda6fdc76b1812248e9fbd0c11d4a1a7" @@ -351,13 +343,6 @@ core-js-pure "^3.20.2" regenerator-runtime "^0.13.4" -"@babel/runtime@^7.10.2", "@babel/runtime@^7.18.9": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.19.0.tgz#22b11c037b094d27a8a2504ea4dcff00f50e2259" - integrity sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA== - dependencies: - regenerator-runtime "^0.13.4" - "@babel/runtime@^7.13.10", "@babel/runtime@^7.13.8", "@babel/runtime@^7.14.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.16.7.tgz#03ff99f64106588c9c403c6ecb8c3bafbbdff1fa" @@ -1963,14 +1948,6 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== -aria-query@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-4.2.2.tgz#0d2ca6c9aceb56b8977e9fed6aed7e15bbd2f83b" - integrity sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA== - dependencies: - "@babel/runtime" "^7.10.2" - "@babel/runtime-corejs3" "^7.10.2" - array-find-index@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" @@ -1997,17 +1974,6 @@ array-includes@^3.1.3, array-includes@^3.1.4: get-intrinsic "^1.1.1" is-string "^1.0.7" -array-includes@^3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.5.tgz#2c320010db8d31031fd2a5f6b3bbd4b1aad31bdb" - integrity sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.19.5" - get-intrinsic "^1.1.1" - is-string "^1.0.7" - array-union@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" @@ -2022,16 +1988,6 @@ array.prototype.flatmap@^1.2.5: define-properties "^1.1.3" es-abstract "^1.19.0" -array.prototype.flatmap@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.0.tgz#a7e8ed4225f4788a70cd910abcf0791e76a5534f" - integrity sha512-PZC9/8TKAIxcWKdyeb77EzULHPrIX/tIZebLJUQOMR1OwYosT8yggdfWScfTBCDj5utONvOuPQQumYsU2ULbkg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.2" - es-shim-unscopables "^1.0.0" - arrify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" @@ -2054,11 +2010,6 @@ assert-plus@1.0.0, assert-plus@^1.0.0: resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= -ast-types-flow@^0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" - integrity sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag== - async-foreach@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542" @@ -2079,16 +2030,6 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== -axe-core@^4.4.3: - version "4.4.3" - resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.4.3.tgz#11c74d23d5013c0fa5d183796729bc3482bd2f6f" - integrity sha512-32+ub6kkdhhWick/UjvEwRchgoetXqTK14INLqbGm5U2TzBkBNF3nQtLYm8ovxSkQWArjEQvftCKryjZaATu3w== - -axobject-query@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be" - integrity sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA== - babel-jest@^27.4.6: version "27.4.6" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-27.4.6.tgz#4d024e69e241cdf4f396e453a07100f44f7ce314" @@ -2681,7 +2622,7 @@ clone@^1.0.2: resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= -clsx@^1.1.1, clsx@^1.2.1: +clsx@^1.1.1: version "1.2.1" resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== @@ -2885,11 +2826,6 @@ core-js-pure@^3.20.2: resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.20.3.tgz#6cc4f36da06c61d95254efc54024fe4797fd5d02" integrity sha512-Q2H6tQ5MtPtcC7f3HxJ48i4Q7T9ybPKgvWyuH7JXIoNa2pm0KuBnycsET/qw1SLLZYfbsbrZQNMeIOClb+6WIA== -core-js-pure@^3.25.1: - version "3.25.3" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.25.3.tgz#66ac5bfa5754b47fdfd14f3841c5ed21c46db608" - integrity sha512-T/7qvgv70MEvRkZ8p6BasLZmOVYKzOaWNBEHAU8FmveCJkl4nko2quqPQOmy6AJIp5MBanhz9no3A94NoRb0XA== - core-js@3.18.3: version "3.18.3" resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.18.3.tgz#86a0bba2d8ec3df860fefcc07a8d119779f01509" @@ -3065,11 +3001,6 @@ cwebp-bin@^7.0.1: bin-build "^3.0.0" bin-wrapper "^4.0.1" -damerau-levenshtein@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" - integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA== - dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" @@ -3234,14 +3165,6 @@ define-properties@^1.1.3: dependencies: object-keys "^1.0.12" -define-properties@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" - integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== - dependencies: - has-property-descriptors "^1.0.0" - object-keys "^1.1.1" - delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -3502,26 +3425,18 @@ emittery@^0.8.1: resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.8.1.tgz#bb23cc86d03b30aa75a7f734819dee2e1ba70860" integrity sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg== -emoji-picker-react@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/emoji-picker-react/-/emoji-picker-react-4.0.6.tgz#23c8fedffcafc5fdafc301a51d32f8610c21e46e" - integrity sha512-j/ZAisWDiV79s2kIWB4PM4zDKvPNXSJCMEyFOsFSRyNOfsF6nWv1FnAJsXX34TdyWw8rzlrcUwCpidpfBtYzWA== +emoji-picker-react@^4.10.0: + version "4.10.0" + resolved "https://registry.yarnpkg.com/emoji-picker-react/-/emoji-picker-react-4.10.0.tgz#c6ad68ae7f2b36dff61cffde07cfec237195950d" + integrity sha512-EfvOsGbyweMNcJ1F99XUv+XPdfkpa2NRAYkhwdIeYS6DWeISu3kHWX+iwvFLUVAc533aWbsGpETbxwbhzsiMnw== dependencies: - clsx "^1.2.1" - eslint-plugin-jsx-a11y "^6.6.1" - eslint-plugin-react "^7.31.8" - eslint-plugin-react-hooks "^4.6.0" + flairup "0.0.39" emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== -emoji-regex@^9.2.2: - version "9.2.2" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" - integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== - emojis-list@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" @@ -3638,48 +3553,11 @@ es-abstract@^1.18.0-next.2, es-abstract@^1.18.2, es-abstract@^1.19.0, es-abstrac string.prototype.trimstart "^1.0.4" unbox-primitive "^1.0.1" -es-abstract@^1.19.2, es-abstract@^1.19.5: - version "1.20.3" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.3.tgz#90b143ff7aedc8b3d189bcfac7f1e3e3f81e9da1" - integrity sha512-AyrnaKVpMzljIdwjzrj+LxGmj8ik2LckwXacHqrJJ/jxz6dDDBcZ7I7nlHM0FvEW8MfbWJwOd+yT2XzYW49Frw== - dependencies: - call-bind "^1.0.2" - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - function.prototype.name "^1.1.5" - get-intrinsic "^1.1.3" - get-symbol-description "^1.0.0" - has "^1.0.3" - has-property-descriptors "^1.0.0" - has-symbols "^1.0.3" - internal-slot "^1.0.3" - is-callable "^1.2.6" - is-negative-zero "^2.0.2" - is-regex "^1.1.4" - is-shared-array-buffer "^1.0.2" - is-string "^1.0.7" - is-weakref "^1.0.2" - object-inspect "^1.12.2" - object-keys "^1.1.1" - object.assign "^4.1.4" - regexp.prototype.flags "^1.4.3" - safe-regex-test "^1.0.0" - string.prototype.trimend "^1.0.5" - string.prototype.trimstart "^1.0.5" - unbox-primitive "^1.0.2" - es-module-lexer@^0.9.0: version "0.9.3" resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== -es-shim-unscopables@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241" - integrity sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w== - dependencies: - has "^1.0.3" - es-to-primitive@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" @@ -3726,30 +3604,6 @@ escodegen@^2.0.0: optionalDependencies: source-map "~0.6.1" -eslint-plugin-jsx-a11y@^6.6.1: - version "6.6.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.6.1.tgz#93736fc91b83fdc38cc8d115deedfc3091aef1ff" - integrity sha512-sXgFVNHiWffBq23uiS/JaP6eVR622DqwB4yTzKvGZGcPq6/yZ3WmOZfuBks/vHWo9GaFOqC2ZK4i6+C35knx7Q== - dependencies: - "@babel/runtime" "^7.18.9" - aria-query "^4.2.2" - array-includes "^3.1.5" - ast-types-flow "^0.0.7" - axe-core "^4.4.3" - axobject-query "^2.2.0" - damerau-levenshtein "^1.0.8" - emoji-regex "^9.2.2" - has "^1.0.3" - jsx-ast-utils "^3.3.2" - language-tags "^1.0.5" - minimatch "^3.1.2" - semver "^6.3.0" - -eslint-plugin-react-hooks@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz#4c3e697ad95b77e93f8646aaa1630c1ba607edd3" - integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g== - eslint-plugin-react@^7.28.0: version "7.28.0" resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.28.0.tgz#8f3ff450677571a659ce76efc6d80b6a525adbdf" @@ -3770,26 +3624,6 @@ eslint-plugin-react@^7.28.0: semver "^6.3.0" string.prototype.matchall "^4.0.6" -eslint-plugin-react@^7.31.8: - version "7.31.8" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.31.8.tgz#3a4f80c10be1bcbc8197be9e8b641b2a3ef219bf" - integrity sha512-5lBTZmgQmARLLSYiwI71tiGVTLUuqXantZM6vlSY39OaDSV0M7+32K5DnLkmFrwTe+Ksz0ffuLUC91RUviVZfw== - dependencies: - array-includes "^3.1.5" - array.prototype.flatmap "^1.3.0" - doctrine "^2.1.0" - estraverse "^5.3.0" - jsx-ast-utils "^2.4.1 || ^3.0.0" - minimatch "^3.1.2" - object.entries "^1.1.5" - object.fromentries "^2.0.5" - object.hasown "^1.1.1" - object.values "^1.1.5" - prop-types "^15.8.1" - resolve "^2.0.0-next.3" - semver "^6.3.0" - string.prototype.matchall "^4.0.7" - eslint-scope@5.1.1, eslint-scope@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" @@ -4339,6 +4173,11 @@ find-versions@^3.0.0: dependencies: semver-regex "^2.0.0" +flairup@0.0.39: + version "0.0.39" + resolved "https://registry.yarnpkg.com/flairup/-/flairup-0.0.39.tgz#edc3a0f27548f0a0a0cb3569f4971ae4c0b73d46" + integrity sha512-UVPkzZmZeBWBx1+Ovo++kYKk9Wi32Jxt+c7HsxnEY80ExwFV54w+NyquFziqMLS0BnGVE43yGD4OvIwaAm/WiQ== + flat-cache@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" @@ -4439,26 +4278,11 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== -function.prototype.name@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" - integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.0" - functions-have-names "^1.2.2" - functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= -functions-have-names@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" - integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== - gauge@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/gauge/-/gauge-3.0.2.tgz#03bf4441c044383908bcfa0656ad91803259b395" @@ -4515,15 +4339,6 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: has "^1.0.3" has-symbols "^1.0.1" -get-intrinsic@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385" - integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A== - dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.3" - get-package-type@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" @@ -4776,11 +4591,6 @@ has-bigints@^1.0.1: resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== -has-bigints@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" - integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== - has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -4791,13 +4601,6 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-property-descriptors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" - integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== - dependencies: - get-intrinsic "^1.1.1" - has-symbol-support-x@^1.4.1: version "1.4.2" resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz#1409f98bc00247da45da67cee0a36f282ff26455" @@ -4808,11 +4611,6 @@ has-symbols@^1.0.1, has-symbols@^1.0.2: resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== -has-symbols@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== - has-to-string-tag-x@^1.2.0: version "1.4.1" resolved "https://registry.yarnpkg.com/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz#a045ab383d7b4b2012a00148ab0aa5f290044d4d" @@ -5333,11 +5131,6 @@ is-callable@^1.1.4, is-callable@^1.2.3, is-callable@^1.2.4: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== -is-callable@^1.2.6: - version "1.2.7" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" - integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== - is-cidr@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/is-cidr/-/is-cidr-4.0.2.tgz#94c7585e4c6c77ceabf920f8cde51b8c0fda8814" @@ -5427,7 +5220,7 @@ is-natural-number@^4.0.1: resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8" integrity sha1-q5124dtM7VHjXeDHLr7PCfc0zeg= -is-negative-zero@^2.0.1, is-negative-zero@^2.0.2: +is-negative-zero@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== @@ -5494,13 +5287,6 @@ is-shared-array-buffer@^1.0.1: resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz#97b0c85fbdacb59c9c446fe653b82cf2b5b7cfe6" integrity sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA== -is-shared-array-buffer@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" - integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== - dependencies: - call-bind "^1.0.2" - is-stream@^1.0.0, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" @@ -5542,7 +5328,7 @@ is-utf8@^0.2.0: resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= -is-weakref@^1.0.1, is-weakref@^1.0.2: +is-weakref@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== @@ -6230,14 +6016,6 @@ jsprim@^1.2.2: array-includes "^3.1.3" object.assign "^4.1.2" -jsx-ast-utils@^3.3.2: - version "3.3.3" - resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz#76b3e6e6cece5c69d49a5792c3d01bd1a0cdc7ea" - integrity sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw== - dependencies: - array-includes "^3.1.5" - object.assign "^4.1.3" - junk@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/junk/-/junk-3.1.0.tgz#31499098d902b7e98c5d9b9c80f43457a88abfa1" @@ -6275,18 +6053,6 @@ klona@^2.0.4: resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.5.tgz#d166574d90076395d9963aa7a928fabb8d76afbc" integrity sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ== -language-subtag-registry@~0.3.2: - version "0.3.22" - resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz#2e1500861b2e457eba7e7ae86877cbd08fa1fd1d" - integrity sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w== - -language-tags@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/language-tags/-/language-tags-1.0.5.tgz#d321dbc4da30ba8bf3024e040fa5c14661f9193a" - integrity sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ== - dependencies: - language-subtag-registry "~0.3.2" - leven@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" @@ -6782,13 +6548,6 @@ minimatch@^3.0.4, minimatch@~3.0.2: dependencies: brace-expansion "^1.1.7" -minimatch@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - minimist-options@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" @@ -7313,11 +7072,6 @@ object-inspect@^1.11.0, object-inspect@^1.9.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.0.tgz#6e2c120e868fd1fd18cb4f18c31741d0d6e776f0" integrity sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g== -object-inspect@^1.12.2: - version "1.12.2" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" - integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== - object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" @@ -7333,16 +7087,6 @@ object.assign@^4.1.2: has-symbols "^1.0.1" object-keys "^1.1.1" -object.assign@^4.1.3, object.assign@^4.1.4: - version "4.1.4" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" - integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - has-symbols "^1.0.3" - object-keys "^1.1.1" - object.entries@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.5.tgz#e1acdd17c4de2cd96d5a08487cfb9db84d881861" @@ -7378,14 +7122,6 @@ object.hasown@^1.1.0: define-properties "^1.1.3" es-abstract "^1.19.1" -object.hasown@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.1.tgz#ad1eecc60d03f49460600430d97f23882cf592a3" - integrity sha512-LYLe4tivNQzq4JdaWW6WO3HMZZJWzkkH8fnI6EebWl0VZth2wL2Lovm74ep2/gZzlaTdV62JZHEqHQ2yVn8Q/A== - dependencies: - define-properties "^1.1.4" - es-abstract "^1.19.5" - object.values@^1.1.0: version "1.1.4" resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.4.tgz#0d273762833e816b693a637d30073e7051535b30" @@ -8397,15 +8133,6 @@ regexp.prototype.flags@^1.3.1: call-bind "^1.0.2" define-properties "^1.1.3" -regexp.prototype.flags@^1.4.1, regexp.prototype.flags@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" - integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - functions-have-names "^1.2.2" - regexpp@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" @@ -8606,15 +8333,6 @@ safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -safe-regex-test@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" - integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.3" - is-regex "^1.1.4" - safe-stable-stringify@^2.2.0: version "2.3.1" resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.3.1.tgz#ab67cbe1fe7d40603ca641c5e765cb942d04fc73" @@ -9150,20 +8868,6 @@ string.prototype.matchall@^4.0.6: regexp.prototype.flags "^1.3.1" side-channel "^1.0.4" -string.prototype.matchall@^4.0.7: - version "4.0.7" - resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz#8e6ecb0d8a1fb1fda470d81acecb2dba057a481d" - integrity sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.1" - get-intrinsic "^1.1.1" - has-symbols "^1.0.3" - internal-slot "^1.0.3" - regexp.prototype.flags "^1.4.1" - side-channel "^1.0.4" - string.prototype.trimend@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80" @@ -9172,15 +8876,6 @@ string.prototype.trimend@^1.0.4: call-bind "^1.0.2" define-properties "^1.1.3" -string.prototype.trimend@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz#914a65baaab25fbdd4ee291ca7dde57e869cb8d0" - integrity sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.19.5" - string.prototype.trimstart@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed" @@ -9189,15 +8884,6 @@ string.prototype.trimstart@^1.0.4: call-bind "^1.0.2" define-properties "^1.1.3" -string.prototype.trimstart@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz#5466d93ba58cfa2134839f81d7f42437e8c01fef" - integrity sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.19.5" - string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" @@ -9735,16 +9421,6 @@ unbox-primitive@^1.0.1: has-symbols "^1.0.2" which-boxed-primitive "^1.0.2" -unbox-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" - integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== - dependencies: - call-bind "^1.0.2" - has-bigints "^1.0.2" - has-symbols "^1.0.3" - which-boxed-primitive "^1.0.2" - unbzip2-stream@^1.0.9: version "1.4.3" resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz#b0da04c4371311df771cdc215e87f2130991ace7"