lpc-forge 1.0.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 (75) hide show
  1. package/CREDITS.csv +22985 -0
  2. package/LICENSE +674 -0
  3. package/README.md +281 -0
  4. package/assets/music/.gitkeep +0 -0
  5. package/dist/character/batch.d.ts +17 -0
  6. package/dist/character/batch.js +48 -0
  7. package/dist/character/batch.js.map +1 -0
  8. package/dist/character/composer.d.ts +3 -0
  9. package/dist/character/composer.js +164 -0
  10. package/dist/character/composer.js.map +1 -0
  11. package/dist/character/definitions.d.ts +16 -0
  12. package/dist/character/definitions.js +116 -0
  13. package/dist/character/definitions.js.map +1 -0
  14. package/dist/character/presets.d.ts +6 -0
  15. package/dist/character/presets.js +246 -0
  16. package/dist/character/presets.js.map +1 -0
  17. package/dist/character/slicer.d.ts +8 -0
  18. package/dist/character/slicer.js +66 -0
  19. package/dist/character/slicer.js.map +1 -0
  20. package/dist/character/types.d.ts +48 -0
  21. package/dist/character/types.js +32 -0
  22. package/dist/character/types.js.map +1 -0
  23. package/dist/cli.d.ts +2 -0
  24. package/dist/cli.js +938 -0
  25. package/dist/export/frames.d.ts +5 -0
  26. package/dist/export/frames.js +15 -0
  27. package/dist/export/frames.js.map +1 -0
  28. package/dist/export/godot.d.ts +17 -0
  29. package/dist/export/godot.js +464 -0
  30. package/dist/export/godot.js.map +1 -0
  31. package/dist/export/types.d.ts +11 -0
  32. package/dist/export/types.js +2 -0
  33. package/dist/export/types.js.map +1 -0
  34. package/dist/license.d.ts +49 -0
  35. package/dist/license.js +271 -0
  36. package/dist/map/cellular.d.ts +3 -0
  37. package/dist/map/cellular.js +191 -0
  38. package/dist/map/cellular.js.map +1 -0
  39. package/dist/map/dungeon.d.ts +3 -0
  40. package/dist/map/dungeon.js +238 -0
  41. package/dist/map/dungeon.js.map +1 -0
  42. package/dist/map/multifloor.d.ts +20 -0
  43. package/dist/map/multifloor.js +57 -0
  44. package/dist/map/multifloor.js.map +1 -0
  45. package/dist/map/overworld.d.ts +3 -0
  46. package/dist/map/overworld.js +205 -0
  47. package/dist/map/overworld.js.map +1 -0
  48. package/dist/map/town.d.ts +7 -0
  49. package/dist/map/town.js +181 -0
  50. package/dist/map/town.js.map +1 -0
  51. package/dist/map/types.d.ts +65 -0
  52. package/dist/map/types.js +16 -0
  53. package/dist/map/types.js.map +1 -0
  54. package/dist/map/wfc.d.ts +18 -0
  55. package/dist/map/wfc.js +192 -0
  56. package/dist/map/wfc.js.map +1 -0
  57. package/dist/tileset/atlas.d.ts +15 -0
  58. package/dist/tileset/atlas.js +55 -0
  59. package/dist/tileset/atlas.js.map +1 -0
  60. package/dist/tileset/registry.d.ts +12 -0
  61. package/dist/tileset/registry.js +71 -0
  62. package/dist/tileset/registry.js.map +1 -0
  63. package/dist/tileset/terrain.d.ts +3 -0
  64. package/dist/tileset/terrain.js +110 -0
  65. package/dist/tileset/terrain.js.map +1 -0
  66. package/dist/utils/credits.d.ts +11 -0
  67. package/dist/utils/credits.js +74 -0
  68. package/dist/utils/credits.js.map +1 -0
  69. package/dist/utils/image.d.ts +17 -0
  70. package/dist/utils/image.js +94 -0
  71. package/dist/utils/image.js.map +1 -0
  72. package/dist/utils/rng.d.ts +18 -0
  73. package/dist/utils/rng.js +48 -0
  74. package/dist/utils/rng.js.map +1 -0
  75. package/package.json +77 -0
@@ -0,0 +1,71 @@
1
+ import { mkdir, writeFile, readFile, access } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ import { TileType } from '../map/types.js';
4
+ import { createColorTile } from '../utils/image.js';
5
+ const DEFAULT_TILE_SIZE = 32;
6
+ /** Tile color definitions for procedural generation */
7
+ const TILE_COLORS = {
8
+ floor: { r: 180, g: 150, b: 110, border: { r: 160, g: 130, b: 90 } },
9
+ wall: { r: 80, g: 80, b: 90, border: { r: 60, g: 60, b: 70 } },
10
+ wall_top: { r: 100, g: 100, b: 110, border: { r: 70, g: 70, b: 80 } },
11
+ door: { r: 140, g: 100, b: 60, border: { r: 100, g: 70, b: 40 } },
12
+ corridor: { r: 160, g: 135, b: 100, border: { r: 140, g: 115, b: 80 } },
13
+ water: { r: 60, g: 120, b: 190, border: { r: 40, g: 100, b: 170 } },
14
+ grass: { r: 80, g: 160, b: 60, border: { r: 60, g: 140, b: 40 } },
15
+ tree: { r: 30, g: 100, b: 30, border: { r: 20, g: 80, b: 20 } },
16
+ path: { r: 190, g: 170, b: 130, border: { r: 170, g: 150, b: 110 } },
17
+ sand: { r: 220, g: 200, b: 140, border: { r: 200, g: 180, b: 120 } },
18
+ stone: { r: 140, g: 140, b: 150, border: { r: 120, g: 120, b: 130 } },
19
+ bridge: { r: 150, g: 110, b: 70, border: { r: 130, g: 90, b: 50 } },
20
+ void: { r: 0, g: 0, b: 0 },
21
+ };
22
+ /** Generate default placeholder tiles programmatically */
23
+ export async function generateDefaultTileset(outputDir) {
24
+ await mkdir(outputDir, { recursive: true });
25
+ const manifest = {
26
+ name: 'default',
27
+ tileSize: DEFAULT_TILE_SIZE,
28
+ tiles: {},
29
+ };
30
+ for (const [name, color] of Object.entries(TILE_COLORS)) {
31
+ const fileName = `${name}.png`;
32
+ const filePath = join(outputDir, fileName);
33
+ const buffer = await createColorTile(DEFAULT_TILE_SIZE, color.r, color.g, color.b, name === 'void' ? 0 : 255, color.border);
34
+ await writeFile(filePath, buffer);
35
+ manifest.tiles[name.toUpperCase()] = fileName;
36
+ }
37
+ await writeFile(join(outputDir, 'tileset.json'), JSON.stringify(manifest, null, 2));
38
+ return manifest;
39
+ }
40
+ /** Load a tileset manifest from a directory */
41
+ export async function loadTileset(tilesetDir) {
42
+ const manifestPath = join(tilesetDir, 'tileset.json');
43
+ try {
44
+ await access(manifestPath);
45
+ }
46
+ catch {
47
+ // Generate default tileset if it doesn't exist
48
+ return generateDefaultTileset(tilesetDir);
49
+ }
50
+ const content = await readFile(manifestPath, 'utf-8');
51
+ return JSON.parse(content);
52
+ }
53
+ /** Map TileType enum to tile name */
54
+ export function tileTypeToName(t) {
55
+ const mapping = {
56
+ [TileType.VOID]: 'VOID',
57
+ [TileType.FLOOR]: 'FLOOR',
58
+ [TileType.WALL]: 'WALL',
59
+ [TileType.DOOR]: 'DOOR',
60
+ [TileType.CORRIDOR]: 'CORRIDOR',
61
+ [TileType.WATER]: 'WATER',
62
+ [TileType.GRASS]: 'GRASS',
63
+ [TileType.TREE]: 'TREE',
64
+ [TileType.PATH]: 'PATH',
65
+ [TileType.SAND]: 'SAND',
66
+ [TileType.STONE]: 'STONE',
67
+ [TileType.BRIDGE]: 'BRIDGE',
68
+ };
69
+ return mapping[t] ?? 'VOID';
70
+ }
71
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/tileset/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { GeneratedMap } from '../map/types.js';
2
+ /** Render a GeneratedMap into a visual PNG */
3
+ export declare function renderMap(map: GeneratedMap, tilesetDir: string, outputPath: string): Promise<void>;
@@ -0,0 +1,110 @@
1
+ import sharp from 'sharp';
2
+ import { readFile, writeFile, mkdir } from 'node:fs/promises';
3
+ import { join } from 'node:path';
4
+ import { loadTileset, tileTypeToName } from './registry.js';
5
+ /** Render a GeneratedMap into a visual PNG */
6
+ export async function renderMap(map, tilesetDir, outputPath) {
7
+ const manifest = await loadTileset(tilesetDir);
8
+ const tileSize = manifest.tileSize;
9
+ const canvasWidth = map.width * tileSize;
10
+ const canvasHeight = map.height * tileSize;
11
+ // Pre-load all tile images
12
+ const tileBuffers = {};
13
+ for (const [name, fileName] of Object.entries(manifest.tiles)) {
14
+ try {
15
+ const buf = await readFile(join(tilesetDir, fileName));
16
+ tileBuffers[name] = buf;
17
+ }
18
+ catch {
19
+ // Skip missing tiles
20
+ }
21
+ }
22
+ // Build composites for each tile
23
+ const composites = [];
24
+ for (let y = 0; y < map.height; y++) {
25
+ for (let x = 0; x < map.width; x++) {
26
+ const tileType = map.tiles[y][x];
27
+ const tileName = tileTypeToName(tileType);
28
+ const buf = tileBuffers[tileName];
29
+ if (buf) {
30
+ composites.push({
31
+ input: buf,
32
+ top: y * tileSize,
33
+ left: x * tileSize,
34
+ });
35
+ }
36
+ }
37
+ }
38
+ // Sharp has a practical limit on composites, batch if needed
39
+ await mkdir(join(outputPath, '..'), { recursive: true });
40
+ // If map is large, render in row strips
41
+ if (composites.length > 5000) {
42
+ await renderInStrips(map, tileBuffers, tileSize, canvasWidth, canvasHeight, outputPath);
43
+ return;
44
+ }
45
+ const result = await sharp({
46
+ create: {
47
+ width: canvasWidth,
48
+ height: canvasHeight,
49
+ channels: 4,
50
+ background: { r: 0, g: 0, b: 0, alpha: 0 },
51
+ },
52
+ })
53
+ .png()
54
+ .composite(composites)
55
+ .toBuffer();
56
+ await writeFile(outputPath, result);
57
+ }
58
+ async function renderInStrips(map, tileBuffers, tileSize, canvasWidth, canvasHeight, outputPath) {
59
+ const stripHeight = 10; // rows per strip
60
+ const strips = [];
61
+ for (let startRow = 0; startRow < map.height; startRow += stripHeight) {
62
+ const endRow = Math.min(startRow + stripHeight, map.height);
63
+ const stripPixelH = (endRow - startRow) * tileSize;
64
+ const composites = [];
65
+ for (let y = startRow; y < endRow; y++) {
66
+ for (let x = 0; x < map.width; x++) {
67
+ const tileName = tileTypeToName(map.tiles[y][x]);
68
+ const buf = tileBuffers[tileName];
69
+ if (buf) {
70
+ composites.push({
71
+ input: buf,
72
+ top: (y - startRow) * tileSize,
73
+ left: x * tileSize,
74
+ });
75
+ }
76
+ }
77
+ }
78
+ const stripBuf = await sharp({
79
+ create: {
80
+ width: canvasWidth,
81
+ height: stripPixelH,
82
+ channels: 4,
83
+ background: { r: 0, g: 0, b: 0, alpha: 0 },
84
+ },
85
+ })
86
+ .png()
87
+ .composite(composites)
88
+ .toBuffer();
89
+ strips.push(stripBuf);
90
+ }
91
+ // Stitch strips vertically
92
+ const stitchComposites = strips.map((buf, i) => ({
93
+ input: buf,
94
+ top: i * stripHeight * tileSize,
95
+ left: 0,
96
+ }));
97
+ const final = await sharp({
98
+ create: {
99
+ width: canvasWidth,
100
+ height: canvasHeight,
101
+ channels: 4,
102
+ background: { r: 0, g: 0, b: 0, alpha: 0 },
103
+ },
104
+ })
105
+ .png()
106
+ .composite(stitchComposites)
107
+ .toBuffer();
108
+ await writeFile(outputPath, final);
109
+ }
110
+ //# sourceMappingURL=terrain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terrain.js","sourceRoot":"","sources":["../../src/tileset/terrain.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export interface CreditEntry {
2
+ file: string;
3
+ authors: string[];
4
+ licenses: string[];
5
+ urls: string[];
6
+ notes?: string;
7
+ }
8
+ /** Parse CREDITS.csv and return structured credit entries */
9
+ export declare function parseCredits(repoRoot: string): Promise<CreditEntry[]>;
10
+ /** Generate a credits text file for used layers */
11
+ export declare function generateCreditsText(credits: CreditEntry[], usedPaths: string[]): string;
@@ -0,0 +1,74 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ /** Parse CREDITS.csv and return structured credit entries */
4
+ export async function parseCredits(repoRoot) {
5
+ const csvPath = join(repoRoot, 'CREDITS.csv');
6
+ const content = await readFile(csvPath, 'utf-8');
7
+ const lines = content.split('\n');
8
+ if (lines.length < 2)
9
+ return [];
10
+ const entries = [];
11
+ // Skip header row
12
+ for (let i = 1; i < lines.length; i++) {
13
+ const line = lines[i].trim();
14
+ if (!line)
15
+ continue;
16
+ const cols = parseCSVLine(line);
17
+ if (cols.length < 4)
18
+ continue;
19
+ entries.push({
20
+ file: cols[0],
21
+ authors: cols[1] ? cols[1].split(',').map((a) => a.trim()) : [],
22
+ licenses: cols[2] ? cols[2].split(',').map((l) => l.trim()) : [],
23
+ urls: cols[3] ? cols[3].split(',').map((u) => u.trim()) : [],
24
+ notes: cols[4] || undefined,
25
+ });
26
+ }
27
+ return entries;
28
+ }
29
+ function parseCSVLine(line) {
30
+ const result = [];
31
+ let current = '';
32
+ let inQuotes = false;
33
+ for (let i = 0; i < line.length; i++) {
34
+ const ch = line[i];
35
+ if (ch === '"') {
36
+ if (inQuotes && line[i + 1] === '"') {
37
+ current += '"';
38
+ i++;
39
+ }
40
+ else {
41
+ inQuotes = !inQuotes;
42
+ }
43
+ }
44
+ else if (ch === ',' && !inQuotes) {
45
+ result.push(current.trim());
46
+ current = '';
47
+ }
48
+ else {
49
+ current += ch;
50
+ }
51
+ }
52
+ result.push(current.trim());
53
+ return result;
54
+ }
55
+ /** Generate a credits text file for used layers */
56
+ export function generateCreditsText(credits, usedPaths) {
57
+ const relevant = credits.filter((c) => usedPaths.some((p) => p.includes(c.file) || c.file.includes(p)));
58
+ if (relevant.length === 0) {
59
+ return 'Credits: Based on Liberated Pixel Cup (LPC) assets. See CREDITS.csv for full attribution.\n';
60
+ }
61
+ const lines = ['=== Asset Credits ===', ''];
62
+ for (const entry of relevant) {
63
+ lines.push(`File: ${entry.file}`);
64
+ lines.push(`Authors: ${entry.authors.join(', ')}`);
65
+ lines.push(`Licenses: ${entry.licenses.join(', ')}`);
66
+ if (entry.urls.length > 0) {
67
+ lines.push(`URLs: ${entry.urls.join(', ')}`);
68
+ }
69
+ lines.push('');
70
+ }
71
+ lines.push('Full credits available in CREDITS.csv');
72
+ return lines.join('\n');
73
+ }
74
+ //# sourceMappingURL=credits.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credits.js","sourceRoot":"","sources":["../../src/utils/credits.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /** Create a transparent RGBA canvas of the given size */
2
+ export declare function createCanvas(width: number, height: number): Promise<Buffer>;
3
+ /** Composite multiple image buffers onto a base, all at full size */
4
+ export declare function compositeLayers(width: number, height: number, layers: Buffer[]): Promise<Buffer>;
5
+ /** Stitch multiple images vertically into one tall image */
6
+ export declare function stitchVertical(images: {
7
+ buffer: Buffer;
8
+ yOffset: number;
9
+ }[], totalWidth: number, totalHeight: number): Promise<Buffer>;
10
+ /** Extract a rectangular region from an image buffer */
11
+ export declare function extractRegion(buffer: Buffer, left: number, top: number, width: number, height: number): Promise<Buffer>;
12
+ /** Create a solid-color tile with optional border */
13
+ export declare function createColorTile(size: number, r: number, g: number, b: number, alpha?: number, borderColor?: {
14
+ r: number;
15
+ g: number;
16
+ b: number;
17
+ }): Promise<Buffer>;
@@ -0,0 +1,94 @@
1
+ import sharp from 'sharp';
2
+ /** Create a transparent RGBA canvas of the given size */
3
+ export async function createCanvas(width, height) {
4
+ return sharp({
5
+ create: {
6
+ width,
7
+ height,
8
+ channels: 4,
9
+ background: { r: 0, g: 0, b: 0, alpha: 0 },
10
+ },
11
+ })
12
+ .png()
13
+ .toBuffer();
14
+ }
15
+ /** Composite multiple image buffers onto a base, all at full size */
16
+ export async function compositeLayers(width, height, layers) {
17
+ if (layers.length === 0) {
18
+ return createCanvas(width, height);
19
+ }
20
+ const composites = layers.map((input) => ({
21
+ input,
22
+ top: 0,
23
+ left: 0,
24
+ blend: 'over',
25
+ }));
26
+ return sharp({
27
+ create: {
28
+ width,
29
+ height,
30
+ channels: 4,
31
+ background: { r: 0, g: 0, b: 0, alpha: 0 },
32
+ },
33
+ })
34
+ .png()
35
+ .composite(composites)
36
+ .toBuffer();
37
+ }
38
+ /** Stitch multiple images vertically into one tall image */
39
+ export async function stitchVertical(images, totalWidth, totalHeight) {
40
+ const composites = images.map(({ buffer, yOffset }) => ({
41
+ input: buffer,
42
+ top: yOffset,
43
+ left: 0,
44
+ blend: 'over',
45
+ }));
46
+ return sharp({
47
+ create: {
48
+ width: totalWidth,
49
+ height: totalHeight,
50
+ channels: 4,
51
+ background: { r: 0, g: 0, b: 0, alpha: 0 },
52
+ },
53
+ })
54
+ .png()
55
+ .composite(composites)
56
+ .toBuffer();
57
+ }
58
+ /** Extract a rectangular region from an image buffer */
59
+ export async function extractRegion(buffer, left, top, width, height) {
60
+ return sharp(buffer).extract({ left, top, width, height }).png().toBuffer();
61
+ }
62
+ /** Create a solid-color tile with optional border */
63
+ export async function createColorTile(size, r, g, b, alpha = 255, borderColor) {
64
+ // Create the fill
65
+ const base = await sharp({
66
+ create: {
67
+ width: size,
68
+ height: size,
69
+ channels: 4,
70
+ background: { r, g, b, alpha },
71
+ },
72
+ })
73
+ .png()
74
+ .toBuffer();
75
+ if (!borderColor)
76
+ return base;
77
+ // Overlay a 1px border by creating border lines
78
+ const hLine = await sharp({
79
+ create: { width: size, height: 1, channels: 4, background: { ...borderColor, alpha: 255 } },
80
+ }).png().toBuffer();
81
+ const vLine = await sharp({
82
+ create: { width: 1, height: size, channels: 4, background: { ...borderColor, alpha: 255 } },
83
+ }).png().toBuffer();
84
+ return sharp(base)
85
+ .composite([
86
+ { input: hLine, top: 0, left: 0 },
87
+ { input: hLine, top: size - 1, left: 0 },
88
+ { input: vLine, top: 0, left: 0 },
89
+ { input: vLine, top: 0, left: size - 1 },
90
+ ])
91
+ .png()
92
+ .toBuffer();
93
+ }
94
+ //# sourceMappingURL=image.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image.js","sourceRoot":"","sources":["../../src/utils/image.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Seeded pseudo-random number generator using mulberry32.
3
+ */
4
+ export declare class SeededRNG {
5
+ private state;
6
+ constructor(seed: string | number);
7
+ private hashString;
8
+ /** Returns a float in [0, 1) */
9
+ random(): number;
10
+ /** Returns an integer in [min, max] (inclusive) */
11
+ randomInt(min: number, max: number): number;
12
+ /** Returns a float in [min, max) */
13
+ randomFloat(min: number, max: number): number;
14
+ /** Fisher-Yates shuffle (in-place) */
15
+ shuffle<T>(array: T[]): T[];
16
+ /** Pick a random element from an array */
17
+ pick<T>(array: readonly T[]): T;
18
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Seeded pseudo-random number generator using mulberry32.
3
+ */
4
+ export class SeededRNG {
5
+ state;
6
+ constructor(seed) {
7
+ this.state = typeof seed === 'string' ? this.hashString(seed) : seed;
8
+ if (this.state === 0)
9
+ this.state = 1;
10
+ }
11
+ hashString(s) {
12
+ let hash = 0;
13
+ for (let i = 0; i < s.length; i++) {
14
+ const ch = s.charCodeAt(i);
15
+ hash = ((hash << 5) - hash + ch) | 0;
16
+ }
17
+ return Math.abs(hash) || 1;
18
+ }
19
+ /** Returns a float in [0, 1) */
20
+ random() {
21
+ this.state |= 0;
22
+ this.state = (this.state + 0x6d2b79f5) | 0;
23
+ let t = Math.imul(this.state ^ (this.state >>> 15), 1 | this.state);
24
+ t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
25
+ return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
26
+ }
27
+ /** Returns an integer in [min, max] (inclusive) */
28
+ randomInt(min, max) {
29
+ return Math.floor(this.random() * (max - min + 1)) + min;
30
+ }
31
+ /** Returns a float in [min, max) */
32
+ randomFloat(min, max) {
33
+ return this.random() * (max - min) + min;
34
+ }
35
+ /** Fisher-Yates shuffle (in-place) */
36
+ shuffle(array) {
37
+ for (let i = array.length - 1; i > 0; i--) {
38
+ const j = this.randomInt(0, i);
39
+ [array[i], array[j]] = [array[j], array[i]];
40
+ }
41
+ return array;
42
+ }
43
+ /** Pick a random element from an array */
44
+ pick(array) {
45
+ return array[this.randomInt(0, array.length - 1)];
46
+ }
47
+ }
48
+ //# sourceMappingURL=rng.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rng.js","sourceRoot":"","sources":["../../src/utils/rng.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,OAAO,SAAS;IACZ,KAAK,CAAS;IAEtB,YAAY,IAAqB;QAC/B,IAAI,CAAC,KAAK,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACrE,IAAI,IAAI,CAAC,KAAK,KAAK,CAAC;YAAE,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;IACvC,CAAC;IAEO,UAAU,CAAC,CAAS;QAC1B,IAAI,IAAI,GAAG,CAAC,CAAC;QACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAClC,MAAM,EAAE,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YAC3B,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;QACvC,CAAC;QACD,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IAED,gCAAgC;IAChC,MAAM;QACJ,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC;QAChB,IAAI,CAAC,KAAK,GAAG,CAAC,IAAI,CAAC,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;QAC3C,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,IAAI,CAAC,KAAK,KAAK,EAAE,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;QACpE,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAC/C,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,UAAU,CAAC;IAC/C,CAAC;IAED,mDAAmD;IACnD,SAAS,CAAC,GAAW,EAAE,GAAW;QAChC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;IAC3D,CAAC;IAED,oCAAoC;IACpC,WAAW,CAAC,GAAW,EAAE,GAAW;QAClC,OAAO,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC;IAC3C,CAAC;IAED,sCAAsC;IACtC,OAAO,CAAI,KAAU;QACnB,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC1C,MAAM,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAC/B,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9C,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,0CAA0C;IAC1C,IAAI,CAAI,KAAmB;QACzB,OAAO,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;IACpD,CAAC;CACF"}
package/package.json ADDED
@@ -0,0 +1,77 @@
1
+ {
2
+ "name": "lpc-forge",
3
+ "version": "1.0.0",
4
+ "description": "Complete 2D RPG asset pipeline — character compositor, procedural map generator, and Godot 4.6 exporter. Built on Liberated Pixel Cup sprites.",
5
+ "type": "module",
6
+ "bin": {
7
+ "lpc-forge": "./dist/cli.js"
8
+ },
9
+ "files": [
10
+ "dist/cli.js",
11
+ "dist/cli.d.ts",
12
+ "dist/character/**",
13
+ "dist/map/**",
14
+ "dist/export/**",
15
+ "dist/tileset/**",
16
+ "dist/utils/**",
17
+ "dist/license.js",
18
+ "dist/license.d.ts",
19
+ "assets/**",
20
+ "README.md",
21
+ "LICENSE",
22
+ "CREDITS.csv",
23
+ "package.json"
24
+ ],
25
+ "scripts": {
26
+ "build": "tsc",
27
+ "dev": "tsx src/cli.ts",
28
+ "test": "vitest run",
29
+ "lint": "eslint src/"
30
+ },
31
+ "keywords": [
32
+ "lpc",
33
+ "liberated-pixel-cup",
34
+ "spritesheet",
35
+ "character-generator",
36
+ "godot",
37
+ "godot-4",
38
+ "gamedev",
39
+ "pixel-art",
40
+ "rpg",
41
+ "2d",
42
+ "procedural-generation",
43
+ "dungeon-generator",
44
+ "tilemap",
45
+ "indie-game",
46
+ "game-assets",
47
+ "sprite-compositor"
48
+ ],
49
+ "author": "LaunchDay Studio <info@launchdaystudio.com> (https://blueth.online)",
50
+ "license": "GPL-3.0-or-later",
51
+ "repository": {
52
+ "type": "git",
53
+ "url": "https://github.com/LaunchDay-Studio-Inc/lpc-forge.git"
54
+ },
55
+ "bugs": {
56
+ "url": "https://github.com/LaunchDay-Studio-Inc/lpc-forge/issues"
57
+ },
58
+ "homepage": "https://blueth.online",
59
+ "engines": {
60
+ "node": ">=22"
61
+ },
62
+ "dependencies": {
63
+ "chalk": "^5.4.0",
64
+ "commander": "^13.0.0",
65
+ "glob": "^11.0.0",
66
+ "jsfxr": "^1.4.0",
67
+ "ora": "^8.2.0",
68
+ "sharp": "^0.34.0"
69
+ },
70
+ "devDependencies": {
71
+ "@types/node": "^22.0.0",
72
+ "eslint": "^9.0.0",
73
+ "tsx": "^4.19.0",
74
+ "typescript": "^5.8.0",
75
+ "vitest": "^3.0.0"
76
+ }
77
+ }