@poe2-toolkit/tree-core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +451 -0
  3. package/dist/geometry/centre.d.ts +17 -0
  4. package/dist/geometry/centre.d.ts.map +1 -0
  5. package/dist/geometry/centre.js +59 -0
  6. package/dist/geometry/centre.js.map +1 -0
  7. package/dist/geometry/framing.d.ts +27 -0
  8. package/dist/geometry/framing.d.ts.map +1 -0
  9. package/dist/geometry/framing.js +101 -0
  10. package/dist/geometry/framing.js.map +1 -0
  11. package/dist/geometry/orbit.d.ts +23 -0
  12. package/dist/geometry/orbit.d.ts.map +1 -0
  13. package/dist/geometry/orbit.js +28 -0
  14. package/dist/geometry/orbit.js.map +1 -0
  15. package/dist/geometry/project.d.ts +20 -0
  16. package/dist/geometry/project.d.ts.map +1 -0
  17. package/dist/geometry/project.js +149 -0
  18. package/dist/geometry/project.js.map +1 -0
  19. package/dist/ggg/normalize.d.ts +109 -0
  20. package/dist/ggg/normalize.d.ts.map +1 -0
  21. package/dist/ggg/normalize.js +279 -0
  22. package/dist/ggg/normalize.js.map +1 -0
  23. package/dist/index.d.ts +25 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +24 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/scene/allocate.d.ts +61 -0
  28. package/dist/scene/allocate.d.ts.map +1 -0
  29. package/dist/scene/allocate.js +239 -0
  30. package/dist/scene/allocate.js.map +1 -0
  31. package/dist/scene/buildScene.d.ts +21 -0
  32. package/dist/scene/buildScene.d.ts.map +1 -0
  33. package/dist/scene/buildScene.js +212 -0
  34. package/dist/scene/buildScene.js.map +1 -0
  35. package/dist/scene/connections.d.ts +13 -0
  36. package/dist/scene/connections.d.ts.map +1 -0
  37. package/dist/scene/connections.js +75 -0
  38. package/dist/scene/connections.js.map +1 -0
  39. package/dist/scene/nodeSize.d.ts +26 -0
  40. package/dist/scene/nodeSize.d.ts.map +1 -0
  41. package/dist/scene/nodeSize.js +72 -0
  42. package/dist/scene/nodeSize.js.map +1 -0
  43. package/dist/types.d.ts +426 -0
  44. package/dist/types.d.ts.map +1 -0
  45. package/dist/types.js +16 -0
  46. package/dist/types.js.map +1 -0
  47. package/package.json +50 -0
@@ -0,0 +1,101 @@
1
+ /**
2
+ * World-space framing helpers: compute the bounding box the view should focus
3
+ * on, so callers can pan/zoom to a build's allocation or a single class's
4
+ * region instead of the whole tree.
5
+ */
6
+ /** Grow a rect to include a node's footprint (centre ± hit radius). */
7
+ function extend(rect, node) {
8
+ const reach = node.radius > 0 ? node.radius : 1;
9
+ rect.minX = Math.min(rect.minX, node.x - reach);
10
+ rect.minY = Math.min(rect.minY, node.y - reach);
11
+ rect.maxX = Math.max(rect.maxX, node.x + reach);
12
+ rect.maxY = Math.max(rect.maxY, node.y + reach);
13
+ }
14
+ function emptyRect() {
15
+ return { minX: Infinity, minY: Infinity, maxX: -Infinity, maxY: -Infinity };
16
+ }
17
+ function finalize(rect) {
18
+ if (rect.minX > rect.maxX) {
19
+ return null;
20
+ }
21
+ return { minX: rect.minX, minY: rect.minY, maxX: rect.maxX, maxY: rect.maxY };
22
+ }
23
+ /**
24
+ * Bounds of the allocated main-tree nodes (ascendancy nodes excluded — they live
25
+ * in the relocated hub panel). `null` when nothing is allocated.
26
+ */
27
+ export function allocatedBounds(scene) {
28
+ const rect = emptyRect();
29
+ for (const node of scene.nodes) {
30
+ if (node.allocated && !node.ascendancy) {
31
+ extend(rect, node);
32
+ }
33
+ }
34
+ return finalize(rect);
35
+ }
36
+ /**
37
+ * Allocated bounds grown to include the centre hub, so a view framed on a fresh
38
+ * import keeps the class portrait at the tree's centre in shot. `allocatedBounds`
39
+ * alone hugs only the outlying nodes and pushes the portrait off-screen — the
40
+ * very art the import is meant to reveal. `null` when nothing main-tree is
41
+ * allocated (callers fall back to the renderer's default hub-centred view).
42
+ */
43
+ export function allocatedBoundsWithCentre(scene) {
44
+ const bounds = allocatedBounds(scene);
45
+ if (!bounds) {
46
+ return null;
47
+ }
48
+ const { centre, ring } = scene.centre;
49
+ const reach = ring.frameRadius;
50
+ return {
51
+ minX: Math.min(bounds.minX, centre.x - reach),
52
+ minY: Math.min(bounds.minY, centre.y - reach),
53
+ maxX: Math.max(bounds.maxX, centre.x + reach),
54
+ maxY: Math.max(bounds.maxY, centre.y + reach),
55
+ };
56
+ }
57
+ /** Shortest signed distance between two angles, in (-π, π]. */
58
+ function angleDelta(a, b) {
59
+ let delta = a - b;
60
+ while (delta > Math.PI) {
61
+ delta -= 2 * Math.PI;
62
+ }
63
+ while (delta <= -Math.PI) {
64
+ delta += 2 * Math.PI;
65
+ }
66
+ return delta;
67
+ }
68
+ /**
69
+ * Bounds of the tree sector belonging to one class. The tree radiates from the
70
+ * hub and each class owns a rim direction (`ClassAnchor.startAngle`); a main
71
+ * node belongs to the class whose direction its bearing from the centre is
72
+ * closest to. `null` for an unknown class or an empty sector.
73
+ */
74
+ export function classBounds(scene, classId) {
75
+ const anchors = scene.centre.classes;
76
+ if (anchors.length === 0) {
77
+ return null;
78
+ }
79
+ const { centre } = scene.centre;
80
+ const rect = emptyRect();
81
+ for (const node of scene.nodes) {
82
+ if (node.ascendancy) {
83
+ continue;
84
+ }
85
+ const bearing = Math.atan2(node.y - centre.y, node.x - centre.x);
86
+ let nearest = anchors[0];
87
+ let nearestDelta = Math.abs(angleDelta(bearing, nearest.startAngle));
88
+ for (const anchor of anchors) {
89
+ const delta = Math.abs(angleDelta(bearing, anchor.startAngle));
90
+ if (delta < nearestDelta) {
91
+ nearest = anchor;
92
+ nearestDelta = delta;
93
+ }
94
+ }
95
+ if (nearest.classId === classId) {
96
+ extend(rect, node);
97
+ }
98
+ }
99
+ return finalize(rect);
100
+ }
101
+ //# sourceMappingURL=framing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"framing.js","sourceRoot":"","sources":["../../src/geometry/framing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Node positions.
3
+ *
4
+ * GGG's skill-tree export bakes a world `x`/`y` into every node, so the engine
5
+ * reads those directly rather than recomputing them from orbit radii + angles.
6
+ * (GGG omits the orbit-radius constants PoB used for that computation; baking the
7
+ * coordinates is GGG's substitute.)
8
+ *
9
+ * Convention (matches GGG and PoB): angle `0` points straight up and increases
10
+ * clockwise, so a node on `orbit`/`orbitIndex` sits at
11
+ *
12
+ * x = group.x + radius * sin(angle)
13
+ * y = group.y - radius * cos(angle)
14
+ *
15
+ * which is exactly what the baked coordinates already encode.
16
+ */
17
+ import type { Point, TreeData } from '../types.js';
18
+ /**
19
+ * World position of a node identified by skill id, read from its baked
20
+ * coordinates. Throws if the node is missing.
21
+ */
22
+ export declare function nodePosition(data: TreeData, skill: number): Point;
23
+ //# sourceMappingURL=orbit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orbit.d.ts","sourceRoot":"","sources":["../../src/geometry/orbit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEnD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,KAAK,CAQjE"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Node positions.
3
+ *
4
+ * GGG's skill-tree export bakes a world `x`/`y` into every node, so the engine
5
+ * reads those directly rather than recomputing them from orbit radii + angles.
6
+ * (GGG omits the orbit-radius constants PoB used for that computation; baking the
7
+ * coordinates is GGG's substitute.)
8
+ *
9
+ * Convention (matches GGG and PoB): angle `0` points straight up and increases
10
+ * clockwise, so a node on `orbit`/`orbitIndex` sits at
11
+ *
12
+ * x = group.x + radius * sin(angle)
13
+ * y = group.y - radius * cos(angle)
14
+ *
15
+ * which is exactly what the baked coordinates already encode.
16
+ */
17
+ /**
18
+ * World position of a node identified by skill id, read from its baked
19
+ * coordinates. Throws if the node is missing.
20
+ */
21
+ export function nodePosition(data, skill) {
22
+ const node = data.nodes[skill];
23
+ if (!node) {
24
+ throw new RangeError(`unknown skill id ${skill}`);
25
+ }
26
+ return { x: node.x, y: node.y };
27
+ }
28
+ //# sourceMappingURL=orbit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orbit.js","sourceRoot":"","sources":["../../src/geometry/orbit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,IAAc,EAAE,KAAa;IACxD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAE/B,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,UAAU,CAAC,oBAAoB,KAAK,EAAE,CAAC,CAAC;IACpD,CAAC;IAED,OAAO,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC;AAClC,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * World <-> screen projection and hit-testing.
3
+ *
4
+ * `project` turns a world-space {@link Scene} into a {@link ScreenScene} of
5
+ * pixel coordinates, culled to the viewport, so the renderer can blit without
6
+ * any maths of its own. `nodeAt` answers "which node is under this pixel?" by
7
+ * going the other way.
8
+ */
9
+ import type { Point, Scene, ScreenScene, Size, Viewport } from '../types.js';
10
+ /** Project a world point to screen pixels. */
11
+ export declare function projectPoint(viewport: Viewport, p: Point): Point;
12
+ /** Inverse of {@link projectPoint}: screen pixels to a world point. */
13
+ export declare function screenToWorld(viewport: Viewport, sx: number, sy: number): Point;
14
+ export declare function project(scene: Scene, viewport: Viewport, size: Size): ScreenScene;
15
+ /**
16
+ * The skill id of the node under a screen pixel, or null. Returns the closest
17
+ * node whose footprint contains the point (topmost on overlap).
18
+ */
19
+ export declare function nodeAt(scene: Scene, viewport: Viewport, sx: number, sy: number): number | null;
20
+ //# sourceMappingURL=project.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../src/geometry/project.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EACV,KAAK,EACL,KAAK,EAIL,WAAW,EACX,IAAI,EACJ,QAAQ,EACT,MAAM,aAAa,CAAC;AAErB,8CAA8C;AAC9C,wBAAgB,YAAY,CAAC,QAAQ,EAAE,QAAQ,EAAE,CAAC,EAAE,KAAK,GAAG,KAAK,CAEhE;AAED,uEAAuE;AACvE,wBAAgB,aAAa,CAAC,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,KAAK,CAE/E;AAKD,wBAAgB,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,GAAG,WAAW,CAyFjF;AAED;;;GAGG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAyB9F"}
@@ -0,0 +1,149 @@
1
+ /**
2
+ * World <-> screen projection and hit-testing.
3
+ *
4
+ * `project` turns a world-space {@link Scene} into a {@link ScreenScene} of
5
+ * pixel coordinates, culled to the viewport, so the renderer can blit without
6
+ * any maths of its own. `nodeAt` answers "which node is under this pixel?" by
7
+ * going the other way.
8
+ */
9
+ /** Project a world point to screen pixels. */
10
+ export function projectPoint(viewport, p) {
11
+ return { x: p.x * viewport.scale + viewport.tx, y: p.y * viewport.scale + viewport.ty };
12
+ }
13
+ /** Inverse of {@link projectPoint}: screen pixels to a world point. */
14
+ export function screenToWorld(viewport, sx, sy) {
15
+ return { x: (sx - viewport.tx) / viewport.scale, y: (sy - viewport.ty) / viewport.scale };
16
+ }
17
+ /** Nodes whose projected radius is below this many pixels are dropped (LOD). */
18
+ const MIN_VISIBLE_RADIUS_PX = 0.4;
19
+ export function project(scene, viewport, size) {
20
+ const { scale } = viewport;
21
+ const view = worldViewport(viewport, size);
22
+ const nodes = [];
23
+ for (const node of scene.nodes) {
24
+ // Ascendancy nodes live far out in world space; the renderer relocates the
25
+ // active disc into the hub itself, so they are not part of the main map.
26
+ if (node.ascendancy) {
27
+ continue;
28
+ }
29
+ const screenRadius = node.radius * scale;
30
+ if (screenRadius < MIN_VISIBLE_RADIUS_PX) {
31
+ continue;
32
+ }
33
+ if (!within(view, node.x, node.y, node.radius)) {
34
+ continue;
35
+ }
36
+ const p = projectPoint(viewport, node);
37
+ nodes.push({
38
+ skill: node.skill,
39
+ x: p.x,
40
+ y: p.y,
41
+ kind: node.kind,
42
+ icon: node.icon,
43
+ iconSize: node.iconSize * scale,
44
+ frameSize: node.frameSize * scale,
45
+ radius: screenRadius,
46
+ allocated: node.allocated,
47
+ ...(node.jewel ? { jewel: node.jewel } : {}),
48
+ });
49
+ }
50
+ const connections = [];
51
+ for (const conn of scene.connections) {
52
+ // Ascendancy edges are relocated into the hub by the renderer, like nodes.
53
+ if (conn.ascendancy) {
54
+ continue;
55
+ }
56
+ if (!segmentTouches(view, conn.a, conn.b)) {
57
+ continue;
58
+ }
59
+ const a = projectPoint(viewport, conn.a);
60
+ const b = projectPoint(viewport, conn.b);
61
+ if (conn.kind === 'arc' && conn.arc) {
62
+ const centre = projectPoint(viewport, { x: conn.arc.cx, y: conn.arc.cy });
63
+ connections.push({
64
+ from: conn.from,
65
+ to: conn.to,
66
+ kind: 'arc',
67
+ a,
68
+ b,
69
+ active: conn.active,
70
+ arc: {
71
+ cx: centre.x,
72
+ cy: centre.y,
73
+ radius: conn.arc.radius * scale,
74
+ startAngle: conn.arc.startAngle,
75
+ endAngle: conn.arc.endAngle,
76
+ clockwise: conn.arc.clockwise,
77
+ orbit: conn.arc.orbit,
78
+ },
79
+ });
80
+ }
81
+ else {
82
+ connections.push({ from: conn.from, to: conn.to, kind: 'line', a, b, active: conn.active });
83
+ }
84
+ }
85
+ const masteryEffects = [];
86
+ for (const effect of scene.masteryEffects) {
87
+ if (!within(view, effect.x, effect.y, effect.size / 2)) {
88
+ continue;
89
+ }
90
+ const p = projectPoint(viewport, effect);
91
+ masteryEffects.push({ skill: effect.skill, x: p.x, y: p.y, size: effect.size * scale, patternKey: effect.patternKey, active: effect.active });
92
+ }
93
+ return { scale, nodes, connections, masteryEffects };
94
+ }
95
+ /**
96
+ * The skill id of the node under a screen pixel, or null. Returns the closest
97
+ * node whose footprint contains the point (topmost on overlap).
98
+ */
99
+ export function nodeAt(scene, viewport, sx, sy) {
100
+ const world = screenToWorld(viewport, sx, sy);
101
+ let best = null;
102
+ let bestDistSq = Infinity;
103
+ for (const node of scene.nodes) {
104
+ // Ascendancy nodes aren't on the main map (the renderer relocates them and
105
+ // hit-tests them there); don't match them at their far-out world position.
106
+ // Masteries are drawn as a large background pattern, not an interactive
107
+ // disc — their huge footprint would otherwise hijack the hover.
108
+ if (node.radius <= 0 || node.ascendancy || node.kind === 'mastery') {
109
+ continue;
110
+ }
111
+ const dx = node.x - world.x;
112
+ const dy = node.y - world.y;
113
+ const distSq = dx * dx + dy * dy;
114
+ if (distSq <= node.radius * node.radius && distSq < bestDistSq) {
115
+ best = node.skill;
116
+ bestDistSq = distSq;
117
+ }
118
+ }
119
+ return best;
120
+ }
121
+ /** The world-space rectangle currently visible in the viewport. */
122
+ function worldViewport(viewport, size) {
123
+ const topLeft = screenToWorld(viewport, 0, 0);
124
+ const bottomRight = screenToWorld(viewport, size.width, size.height);
125
+ return {
126
+ minX: Math.min(topLeft.x, bottomRight.x),
127
+ minY: Math.min(topLeft.y, bottomRight.y),
128
+ maxX: Math.max(topLeft.x, bottomRight.x),
129
+ maxY: Math.max(topLeft.y, bottomRight.y),
130
+ };
131
+ }
132
+ /** Whether a world circle (centre + radius) intersects the view rect. */
133
+ function within(view, x, y, radius) {
134
+ return (x + radius >= view.minX &&
135
+ x - radius <= view.maxX &&
136
+ y + radius >= view.minY &&
137
+ y - radius <= view.maxY);
138
+ }
139
+ /** Cheap bounding-box test for whether a segment could touch the view rect. */
140
+ function segmentTouches(view, a, b) {
141
+ if (Math.max(a.x, b.x) < view.minX || Math.min(a.x, b.x) > view.maxX) {
142
+ return false;
143
+ }
144
+ if (Math.max(a.y, b.y) < view.minY || Math.min(a.y, b.y) > view.maxY) {
145
+ return false;
146
+ }
147
+ return true;
148
+ }
149
+ //# sourceMappingURL=project.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/geometry/project.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Normalise GGG's official skill-tree export (`data.json`) into the engine's
3
+ * {@link TreeData}.
4
+ *
5
+ * This is the only place that knows GGG's field names and quirks. Everything
6
+ * downstream works against the clean {@link TreeData} contract. The transform is
7
+ * deliberately tolerant: optional fields come and go across patches and missing
8
+ * data should never throw.
9
+ *
10
+ * The GGG quirks handled here:
11
+ * - node positions are **baked** (`node.x`/`node.y`); the export ships none of
12
+ * the orbit-radius constants needed to recompute them, so they are read as-is;
13
+ * - edges are split across `in` + `out` id lists, merged into one set here;
14
+ * - arc geometry lives in a separate top-level `edges` table, not on the node;
15
+ * - attribute choices live in a global `skillOverrides` table, not per node;
16
+ * - ascendancy ids are internal (`Ranger1`) and mapped to display names here;
17
+ * - centre/ring dimensions are absent — filled from stable atlas frame sizes.
18
+ */
19
+ import type { TreeData } from '../types.js';
20
+ export interface GggTreeJson {
21
+ groups: Record<string, GggGroup>;
22
+ nodes: Record<string, GggNode>;
23
+ classes: GggClass[];
24
+ /** Per-edge geometry: arcs carry `orbit` + the arc centre `orbitX`/`orbitY`. */
25
+ edges?: GggEdge[];
26
+ /** Global attribute-choice definitions, keyed by the (shared) override id. */
27
+ skillOverrides?: Record<string, GggSkillOverride>;
28
+ jewelSlots?: (string | number)[];
29
+ min_x: number;
30
+ min_y: number;
31
+ max_x: number;
32
+ max_y: number;
33
+ }
34
+ interface GggEdge {
35
+ from: string | number;
36
+ to: string | number;
37
+ /** Present when the edge is an arc; the orbit it follows. */
38
+ orbit?: number;
39
+ /** World centre of the arc, when GGG provides it. */
40
+ orbitX?: number;
41
+ orbitY?: number;
42
+ }
43
+ interface GggGroup {
44
+ x: number;
45
+ y: number;
46
+ orbits?: number[];
47
+ nodes?: (string | number)[];
48
+ }
49
+ interface GggNode {
50
+ skill?: number;
51
+ name?: string;
52
+ icon?: string;
53
+ stats?: string[];
54
+ x?: number;
55
+ y?: number;
56
+ group?: number;
57
+ orbit?: number;
58
+ orbitIndex?: number;
59
+ in?: (string | number)[];
60
+ out?: (string | number)[];
61
+ isNotable?: boolean;
62
+ isKeystone?: boolean;
63
+ isMastery?: boolean;
64
+ isJewelSocket?: boolean;
65
+ isGenericAttribute?: boolean;
66
+ isAscendancyStart?: boolean;
67
+ activeEffectImage?: string;
68
+ ascendancyId?: string;
69
+ /** Class indices (into `classes`) that start at this node. */
70
+ classStartIndex?: number[];
71
+ flavourText?: string[] | string;
72
+ recipe?: string[];
73
+ unlockConstraint?: {
74
+ ascendancy?: string;
75
+ nodes?: number[];
76
+ };
77
+ }
78
+ interface GggSkillOverride {
79
+ id?: string;
80
+ skill?: number;
81
+ name?: string;
82
+ icon?: string;
83
+ stats?: string[];
84
+ }
85
+ interface GggAscendancy {
86
+ id: string;
87
+ name?: string;
88
+ /** Hub-relative position of the disc centre (radius ~1332 toward the class). */
89
+ offsetX?: number;
90
+ offsetY?: number;
91
+ }
92
+ interface GggClass {
93
+ name: string;
94
+ base_str: number;
95
+ base_dex: number;
96
+ base_int: number;
97
+ image?: string;
98
+ ascendancies?: GggAscendancy[];
99
+ /** Per-class node display overrides: base skill id -> override skill id. */
100
+ overridePairs?: Record<string | number, number>;
101
+ }
102
+ /**
103
+ * @param raw parsed GGG `data.json`
104
+ * @param version tree/patch version (e.g. "0_5") — GGG does not store it inside
105
+ * the file, so it is supplied here
106
+ */
107
+ export declare function normalizeGggTree(raw: GggTreeJson, version: string): TreeData;
108
+ export {};
109
+ //# sourceMappingURL=normalize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../src/ggg/normalize.ts"],"names":[],"mappings":"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"}