Skip to main content
Glama
sc2.ts3.51 kB
import { ScpgReadStream } from './scpg.js'; import type { MapEntity, TerrainType } from '../data/types.js'; export type { MapEntity }; interface HierarchyNode { '##name'?: string; name?: string; '#hierarchy'?: HierarchyNode[]; components?: Record<string, unknown>; } interface SC2Data { '#hierarchy'?: HierarchyNode[]; [key: string]: unknown; } export class Sc2ReadStream extends ScpgReadStream { header() { return { name: this.ascii(4), version: this.uint32(), nodeCount: this.uint32(), }; } versionTags() { return this.ka(); } descriptor() { const size = this.uint32(); const fileType = this.uint32(); this.seek(size - 4); return { size, fileType }; } sc2(): SC2Data { this.header(); this.versionTags(); this.descriptor(); return this.ka() as SC2Data; } } function classifyEntity(name: string): TerrainType { const lower = name.toLowerCase(); if (lower.includes('bush') || lower.includes('shrub')) return 'bush'; if (lower.includes('tree') || lower.includes('palm') || lower.includes('pine') || lower.includes('_k1') || lower.includes('_k2')) return 'tree'; if (lower.includes('bld_') || lower.includes('house') || lower.includes('izba') || lower.includes('barn') || lower.includes('church') || lower.includes('mill') || lower.includes('factory')) return 'building'; if (lower.includes('rock') || lower.includes('stone') || lower.includes('boulder') || lower.includes('stn_')) return 'rock'; if (lower.includes('wall') || lower.includes('fence') || lower.includes('fag_')) return 'wall'; if (lower.includes('bridge') || lower.includes('env_') && lower.includes('bridge')) return 'bridge'; if (lower.includes('water') || lower.includes('river') || lower.includes('lake')) return 'water'; if (lower.includes('road') || lower.includes('street')) return 'road'; if (lower.includes('hill') || lower.includes('mountain')) return 'elevation'; if (lower.includes('flag') || lower.includes('capture') || lower.includes('cap_')) return 'capture_point'; if (lower.includes('spawn')) return 'spawn'; if (lower.includes('dec_') || lower.includes('debris') || lower.includes('crate')) return 'decoration'; return 'other'; } function extractPosition(components: Record<string, unknown>): [number, number, number] | null { for (const comp of Object.values(components)) { if (typeof comp !== 'object' || comp === null) continue; const c = comp as Record<string, unknown>; if (c['comp.typename'] === 'TransformComponent') { const pos = c['tc.worldTranslation'] as number[] | undefined; if (pos && pos.length >= 3) { return [pos[0], pos[1], pos[2]]; } } } return null; } function traverseHierarchy(nodes: HierarchyNode[], entities: MapEntity[]) { for (const node of nodes) { if (node.name && node.components) { const position = extractPosition(node.components as Record<string, unknown>); if (position) { const type = classifyEntity(node.name); if (type !== 'other') { entities.push({ name: node.name, position, type, }); } } } if (node['#hierarchy']) { traverseHierarchy(node['#hierarchy'], entities); } } } export function extractMapEntities(data: SC2Data): MapEntity[] { const entities: MapEntity[] = []; if (data['#hierarchy']) { traverseHierarchy(data['#hierarchy'], entities); } return entities; }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Revenant30102000/wotblitz-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server