type RangeScanFn> = ( collection: Range, data: any ) => C[]; type InRangeFn> = ( collection: Range, data: any, item: Partial ) => boolean; interface RangeType> { scan: RangeScanFn; inRange: InRangeFn; } export interface RangeCollection> { list: I[]; range: Range; } export class Range> { collection: RangeCollection; cache: Record = {}; static rangeType: Record>> = {}; constructor(collection: RangeCollection) { this.collection = collection; } /** * 扫描 collection 中在范围内的物品 * @param type 范围类型 * @param data 范围数据 * @returns 在范围内的物品列表 */ scan(type: string, data: any): C[] { const t = Range.rangeType[type]; if (!t) { throw new Error(`Unknown range type: ${type}.`); } return t.scan(this, data) as C[]; } inRange(type: string, data: any, item: Partial) { const t = Range.rangeType[type]; if (!t) { throw new Error(`Unknown range type: ${type}.`); } return t.inRange(this, data, item); } clearCache() { this.cache = {}; } static registerRangeType( type: string, scan: RangeScanFn>, inRange: InRangeFn> ) { Range.rangeType[type] = { scan, inRange }; } } // ----- 默认的范围类型 // 方形区域 Range.registerRangeType( 'square', (col, { x, y, d }) => { const cache = (col.cache.square ??= {}); const index = `${x},${y},${d}`; if (index in cache) return cache[index]; const list = col.collection.list; const r = Math.floor(d); return (cache[index] = list.filter(v => { return ( core.has(v.x) && core.has(v.y) && Math.abs(v.x - x) <= r && Math.abs(v.y - y) <= r ); })); }, (col, { x, y, d }, item) => { const r = Math.floor(d / 2); return ( core.has(item.x) && core.has(item.y) && Math.abs(item.x - x) <= r && Math.abs(item.y - y) <= r ); } );