import { Coordinates, Location, MaterialItem, XYCoordinates } from '@gamepark/rules-api'; import { LocationDescription } from '../components'; import { ItemContext, Locator, MaterialContext } from './Locator'; /** * This Locator places items in a disorganised pile. */ export declare class PileLocator

extends Locator { constructor(clone?: Partial); /** * Random position and rotation drawn for each item of each pile, so that an item does not jump around * every time the pile is re-rendered. Both are memoized per pile, on the key returned by {@link getItemKey}. */ private positions; private rotations; /** * Items dragged out of a pile, per item type and index, waiting for the move to apply. See {@link syncDroppedItems}. */ private droppedItems; /** * Key an item is memoized on inside its pile. * * The display index is kept apart from the item index rather than summed with it: `index + displayIndex` * gave the same key to the 2nd unit of item 3 and to the 1st unit of item 4, which then piled up on the * exact same spot. * * The key must depend on nothing but the displayed item, never on the state it is read from: animations ask * for the position an item will have in a state where the move is already applied (see * {@link ItemAnimations.getPreMoveSiblingAnimation}), and a key that differs there would draw a brand new * position, ie send the item flying to a random spot for the whole animation. * * @param context Context of the item * @returns the key the item's position and rotation are memoized on */ protected getItemKey(context: ItemContext): string; /** * By default, a maximum of 20 items are displayed */ limit?: number | undefined; /** * Maximum dispersion radius of the items. */ radius: number | XYCoordinates; /** * Function to override to provide a {@link radius} that depends on the context * @param _location Location to position * @param _context Context of the game * @returns the maximum dispersion radius of the items. */ getRadius(_location: Location, _context: MaterialContext): number | XYCoordinates; /** * Maximum angle of rotation of the items. Defaults to 180, bidirectional so items can have any rotation. */ maxAngle: number; /** * Function to override to provide a {@link maxAngle} that depends on the context * @param _location Location to position * @param _context Context of the game * @returns the maximum angle of rotation of the items */ getMaxAngle(_location: Location, _context: MaterialContext): number; /** * When true, the z-index is derived from the item's Y offset instead of the item index. * Items with a higher Y appear on top, simulating depth perspective. */ zFromY: boolean; minimumDistance: number; /** * Identifier of the pile. By default, distinct location areas (different player, id or parent) forms distinct piles. * @param item Item to position * @param _context Context of the item * @returns a unique identifier for the pile of items this location goes to */ getPileId(item: MaterialItem, _context: ItemContext): string; getPositionDependencies(location: Location, context: MaterialContext): unknown; getItemCoordinates(item: MaterialItem, context: ItemContext): Partial; generateItemPosition(item: MaterialItem, context: ItemContext): { x: number; y: number; }; /** * Free the spot the player dragged from, instead of the spot of the last item drawn in the pile. * * A stack of N identical units is a single item of quantity N, displayed as N slots keyed on their display * index: rules-api only ever knows the quantity, so when one unit leaves, the slot that disappears is the * last one. Every other slot keeps its memoized position, so the item that vanishes from the table is the * one that happened to be drawn last, not the one that was just dragged away. * * The display index that was dragged is only known before the move applies - rules-api drops it from * `game.droppedItems` as soon as it does - so it is recorded while it passes by, then consumed on the render * where the quantity has decreased: the slots that are gone hand their position over to the slots that were * dropped, which leaves the pile with exactly the spots the player dragged from freed. * * @param item Item being positioned * @param context Context of the item * @param pileId Identifier of the pile the item is in, see {@link getPileId} */ protected syncDroppedItems(item: MaterialItem, context: ItemContext, pileId: string): void; private freeDroppedSpots; /** * Drop the memoized position and rotation of every item that is no longer in the pile. * * Entries are only ever added, never replaced, so without this sweep the maps grow for the whole session, * and {@link itemIsTooCloseToAnotherOne} keeps steering newcomers away from the spots of items that left * the pile long ago - until the 100 attempts run out and the item lands anywhere. * * Run right before a new entry is drawn, which is the only moment the maps grow, and only on the state * being displayed: the future states animations simulate already have the moving item out of the pile, so * sweeping on one of those would drop the entry of an item still standing on the table, which would then * be redrawn somewhere else the instant the animation ends. * * @param pileId Identifier of the pile to sweep, see {@link getPileId} * @param context Context of the item the new entry is drawn for */ protected cleanUpPile(pileId: string, context: ItemContext): void; /** * Keys of every item currently in a pile, ie the entries {@link cleanUpPile} must keep. * * Membership is decided by {@link getPileId} alone, the same way {@link getItemCoordinates} decides which * pile an item goes to: a locator that merges several location areas into one pile keeps working, and the * worst a surprising override can do is leave an extra entry in the maps, never wipe a live one. * * @param pileId Identifier of the pile * @param context Context of the game * @returns the keys of the items in that pile */ protected getPileItemKeys(pileId: string, context: ItemContext): Set; itemIsTooCloseToAnotherOne(pilePositions: Map, itemKey: string): boolean; getItemRotateZ(item: MaterialItem, context: ItemContext): number; protected generateLocationDescriptionFromDraggedItem(location: Location, context: ItemContext): LocationDescription; }