import { MaterialItem } from '@gamepark/rules-api'; /** * rules-api never removes an item from the game state: deleting an item only drops its quantity to 0, and * `MaterialMutator.getItemCreationIndex` hands that free slot to the next created item. A brand new item * therefore shows up under an identity (item type + index) that already belonged to a deleted one, and * inherits whatever the front-end memoized on that identity: * - the random position and rotation a {@link PileLocator} drew for its predecessor; * - the React node behind the `type_index_displayIndex` key, and with it the `transform 0.2s` transition of * {@link DraggableMaterial}, which makes the newcomer glide across the table from wherever the dead item * stood instead of simply appearing at its own place. * * That glide is the teleportation seen right after a delete animation, on decks and piles especially, where * deleted items concentrate. * * This tracker keeps the indexes freed by a deletion in a blacklist, and bumps a generation counter the * first time such a slot is filled again. Consumers append that generation to whatever they key on the item * index, so a newcomer never inherits its predecessor's state. */ declare class RecycledIndexes { private blacklists; private generations; private displayedItems; /** * Scan the items of one type in the state being displayed, to blacklist the slots freed by a deletion and * to bump the generation of the slots that were filled again since the last scan. * * {@link DynamicItemsDisplay} is the single writer: it calls this once per render with the real game * state, before anything reads a generation. Everything else (locators, animations, help dialogs) only * reads, so a generation cannot change in the middle of a render. * * @param type The item type * @param items The items of that type in the displayed game state */ refresh(type: number, items: MaterialItem[]): void; /** * Generation of an item slot: 0 until the slot is recycled, then incremented on every reuse. * * A slot still blacklisted while the caller has an item to place on it means the caller is not looking at * the state we scanned, but at the simulated future state an animation builds to know where an item is * going. It gets the generation the slot will have once the move is applied, so the animation targets the * very position the item will settle on instead of landing on the dead item's one and jumping afterwards. * * @param type The item type * @param index The index of the item in the game state * @returns the number of times this slot was recycled */ get(type: number, index: number): number; /** * Whether an items array is the very one being displayed, and not one of the deep copies animations build * to simulate the state a move leads to. Anything that mutates memoized state from a locator must check * this first: a simulated state has the moving item already gone from where it still stands on the table. * * @param type The item type * @param items The items of that type in the state the caller is looking at * @returns true if that array is the one last scanned by {@link refresh} */ isDisplayedState(type: number, items?: MaterialItem[]): boolean; private getBlacklist; private getGenerations; } /** * Tracks the item indexes freed by a deletion and reused by rules-api for a new item. See {@link RecycledIndexes}. */ export declare const recycledIndexes: RecycledIndexes; export {};