grinders-farm 0.3.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 (77) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +135 -0
  3. package/SKILL.md +142 -0
  4. package/dist/scripts/generate-tiles.d.ts +2 -0
  5. package/dist/scripts/generate-tiles.d.ts.map +1 -0
  6. package/dist/scripts/generate-tiles.js +138 -0
  7. package/dist/scripts/generate-tiles.js.map +1 -0
  8. package/dist/src/adapters/auto-worker.d.ts +2 -0
  9. package/dist/src/adapters/auto-worker.d.ts.map +1 -0
  10. package/dist/src/adapters/auto-worker.js +79 -0
  11. package/dist/src/adapters/auto-worker.js.map +1 -0
  12. package/dist/src/adapters/daemon.d.ts +6 -0
  13. package/dist/src/adapters/daemon.d.ts.map +1 -0
  14. package/dist/src/adapters/daemon.js +6 -0
  15. package/dist/src/adapters/daemon.js.map +1 -0
  16. package/dist/src/adapters/image-server.d.ts +2 -0
  17. package/dist/src/adapters/image-server.d.ts.map +1 -0
  18. package/dist/src/adapters/image-server.js +90 -0
  19. package/dist/src/adapters/image-server.js.map +1 -0
  20. package/dist/src/adapters/oneshot.d.ts +2 -0
  21. package/dist/src/adapters/oneshot.d.ts.map +1 -0
  22. package/dist/src/adapters/oneshot.js +36 -0
  23. package/dist/src/adapters/oneshot.js.map +1 -0
  24. package/dist/src/adapters/terminal.d.ts +2 -0
  25. package/dist/src/adapters/terminal.d.ts.map +1 -0
  26. package/dist/src/adapters/terminal.js +70 -0
  27. package/dist/src/adapters/terminal.js.map +1 -0
  28. package/dist/src/game/crops.d.ts +8 -0
  29. package/dist/src/game/crops.d.ts.map +1 -0
  30. package/dist/src/game/crops.js +71 -0
  31. package/dist/src/game/crops.js.map +1 -0
  32. package/dist/src/game/engine.d.ts +15 -0
  33. package/dist/src/game/engine.d.ts.map +1 -0
  34. package/dist/src/game/engine.js +236 -0
  35. package/dist/src/game/engine.js.map +1 -0
  36. package/dist/src/game/farm.d.ts +12 -0
  37. package/dist/src/game/farm.d.ts.map +1 -0
  38. package/dist/src/game/farm.js +387 -0
  39. package/dist/src/game/farm.js.map +1 -0
  40. package/dist/src/game/types.d.ts +70 -0
  41. package/dist/src/game/types.d.ts.map +1 -0
  42. package/dist/src/game/types.js +23 -0
  43. package/dist/src/game/types.js.map +1 -0
  44. package/dist/src/index.d.ts +9 -0
  45. package/dist/src/index.d.ts.map +1 -0
  46. package/dist/src/index.js +8 -0
  47. package/dist/src/index.js.map +1 -0
  48. package/dist/src/local-auto.d.ts +13 -0
  49. package/dist/src/local-auto.d.ts.map +1 -0
  50. package/dist/src/local-auto.js +239 -0
  51. package/dist/src/local-auto.js.map +1 -0
  52. package/dist/src/notify/openclaw-delivery.d.ts +36 -0
  53. package/dist/src/notify/openclaw-delivery.d.ts.map +1 -0
  54. package/dist/src/notify/openclaw-delivery.js +104 -0
  55. package/dist/src/notify/openclaw-delivery.js.map +1 -0
  56. package/dist/src/notify/openclaw-push.d.ts +49 -0
  57. package/dist/src/notify/openclaw-push.d.ts.map +1 -0
  58. package/dist/src/notify/openclaw-push.js +451 -0
  59. package/dist/src/notify/openclaw-push.js.map +1 -0
  60. package/dist/src/render/ansi-renderer.d.ts +6 -0
  61. package/dist/src/render/ansi-renderer.d.ts.map +1 -0
  62. package/dist/src/render/ansi-renderer.js +41 -0
  63. package/dist/src/render/ansi-renderer.js.map +1 -0
  64. package/dist/src/render/image-renderer.d.ts +3 -0
  65. package/dist/src/render/image-renderer.d.ts.map +1 -0
  66. package/dist/src/render/image-renderer.js +174 -0
  67. package/dist/src/render/image-renderer.js.map +1 -0
  68. package/dist/src/render/text-renderer.d.ts +3 -0
  69. package/dist/src/render/text-renderer.d.ts.map +1 -0
  70. package/dist/src/render/text-renderer.js +73 -0
  71. package/dist/src/render/text-renderer.js.map +1 -0
  72. package/dist/src/storage/local-storage.d.ts +15 -0
  73. package/dist/src/storage/local-storage.d.ts.map +1 -0
  74. package/dist/src/storage/local-storage.js +115 -0
  75. package/dist/src/storage/local-storage.js.map +1 -0
  76. package/package.json +44 -0
  77. package/src/notify/notify.json.example +3 -0
@@ -0,0 +1,90 @@
1
+ import { createServer } from "node:http";
2
+ import * as fs from "node:fs";
3
+ import * as os from "node:os";
4
+ import * as path from "node:path";
5
+ const DATA_DIR = path.join(os.homedir(), ".grinders-farm");
6
+ const IMAGE_FILE = path.join(DATA_DIR, "farm.png");
7
+ const PID_FILE = path.join(DATA_DIR, "image-server.pid");
8
+ const INFO_FILE = path.join(DATA_DIR, "image-server.json");
9
+ const requestedPort = Number.parseInt(process.argv[2] ?? "", 10);
10
+ const port = Number.isFinite(requestedPort) && requestedPort > 0 ? requestedPort : 18931;
11
+ const host = "127.0.0.1";
12
+ function cleanupFiles() {
13
+ try {
14
+ if (fs.existsSync(PID_FILE))
15
+ fs.unlinkSync(PID_FILE);
16
+ }
17
+ catch {
18
+ /* ignore */
19
+ }
20
+ }
21
+ function writeRuntimeFiles() {
22
+ fs.mkdirSync(DATA_DIR, { recursive: true });
23
+ fs.writeFileSync(PID_FILE, String(process.pid), "utf8");
24
+ fs.writeFileSync(INFO_FILE, JSON.stringify({
25
+ host,
26
+ port,
27
+ baseUrl: `http://${host}:${port}`,
28
+ imageUrl: `http://${host}:${port}/farm.png`,
29
+ updatedAt: new Date().toISOString(),
30
+ }, null, 2), "utf8");
31
+ }
32
+ const server = createServer((req, res) => {
33
+ const method = req.method ?? "GET";
34
+ if (method !== "GET" && method !== "HEAD") {
35
+ res.statusCode = 405;
36
+ res.end("Method Not Allowed");
37
+ return;
38
+ }
39
+ const urlPath = req.url ?? "/";
40
+ if (urlPath === "/" || urlPath === "/healthz") {
41
+ res.statusCode = 200;
42
+ res.setHeader("content-type", "application/json; charset=utf-8");
43
+ res.end(JSON.stringify({ ok: true, image: "/farm.png" }));
44
+ return;
45
+ }
46
+ if (urlPath !== "/farm.png") {
47
+ res.statusCode = 404;
48
+ res.end("Not Found");
49
+ return;
50
+ }
51
+ if (!fs.existsSync(IMAGE_FILE)) {
52
+ res.statusCode = 404;
53
+ res.end("farm.png not found");
54
+ return;
55
+ }
56
+ try {
57
+ const stat = fs.statSync(IMAGE_FILE);
58
+ res.statusCode = 200;
59
+ res.setHeader("content-type", "image/png");
60
+ res.setHeader("cache-control", "no-cache, no-store, must-revalidate");
61
+ res.setHeader("pragma", "no-cache");
62
+ res.setHeader("expires", "0");
63
+ res.setHeader("content-length", String(stat.size));
64
+ if (method === "HEAD") {
65
+ res.end();
66
+ return;
67
+ }
68
+ fs.createReadStream(IMAGE_FILE).pipe(res);
69
+ }
70
+ catch {
71
+ res.statusCode = 500;
72
+ res.end("failed to read image");
73
+ }
74
+ });
75
+ server.on("error", (err) => {
76
+ cleanupFiles();
77
+ const message = err instanceof Error ? err.message : String(err);
78
+ process.stderr.write(`[grinders-farm:image-server] ${message}\n`);
79
+ process.exit(1);
80
+ });
81
+ server.listen(port, host, () => {
82
+ writeRuntimeFiles();
83
+ });
84
+ const stop = () => {
85
+ cleanupFiles();
86
+ server.close(() => process.exit(0));
87
+ };
88
+ process.on("SIGTERM", stop);
89
+ process.on("SIGINT", stop);
90
+ //# sourceMappingURL=image-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-server.js","sourceRoot":"","sources":["../../../src/adapters/image-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,gBAAgB,CAAC,CAAC;AAC3D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;AACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAAC;AACzD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,mBAAmB,CAAC,CAAC;AAE3D,MAAM,aAAa,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;AACjE,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,aAAa,GAAG,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC;AACzF,MAAM,IAAI,GAAG,WAAW,CAAC;AAEzB,SAAS,YAAY;IACnB,IAAI,CAAC;QACH,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;YAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC;QACP,YAAY;IACd,CAAC;AACH,CAAC;AAED,SAAS,iBAAiB;IACxB,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC;IACxD,EAAE,CAAC,aAAa,CACd,SAAS,EACT,IAAI,CAAC,SAAS,CACZ;QACE,IAAI;QACJ,IAAI;QACJ,OAAO,EAAE,UAAU,IAAI,IAAI,IAAI,EAAE;QACjC,QAAQ,EAAE,UAAU,IAAI,IAAI,IAAI,WAAW;QAC3C,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACpC,EACD,IAAI,EACJ,CAAC,CACF,EACD,MAAM,CACP,CAAC;AACJ,CAAC;AAED,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;IACvC,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,IAAI,KAAK,CAAC;IACnC,IAAI,MAAM,KAAK,KAAK,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QAC1C,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;QACrB,GAAG,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;QAC9B,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC;IAC/B,IAAI,OAAO,KAAK,GAAG,IAAI,OAAO,KAAK,UAAU,EAAE,CAAC;QAC9C,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;QACrB,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,iCAAiC,CAAC,CAAC;QACjE,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC;QAC1D,OAAO;IACT,CAAC;IAED,IAAI,OAAO,KAAK,WAAW,EAAE,CAAC;QAC5B,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;QACrB,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAED,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;QACrB,GAAG,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;QAC9B,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;QACrC,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;QACrB,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;QAC3C,GAAG,CAAC,SAAS,CAAC,eAAe,EAAE,qCAAqC,CAAC,CAAC;QACtE,GAAG,CAAC,SAAS,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QACpC,GAAG,CAAC,SAAS,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QAC9B,GAAG,CAAC,SAAS,CAAC,gBAAgB,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACnD,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;YACtB,GAAG,CAAC,GAAG,EAAE,CAAC;YACV,OAAO;QACT,CAAC;QACD,EAAE,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;QACrB,GAAG,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;IAClC,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;IACzB,YAAY,EAAE,CAAC;IACf,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACjE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gCAAgC,OAAO,IAAI,CAAC,CAAC;IAClE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE;IAC7B,iBAAiB,EAAE,CAAC;AACtB,CAAC,CAAC,CAAC;AAEH,MAAM,IAAI,GAAG,GAAG,EAAE;IAChB,YAAY,EAAE,CAAC;IACf,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AACtC,CAAC,CAAC;AAEF,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAC5B,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=oneshot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oneshot.d.ts","sourceRoot":"","sources":["../../../src/adapters/oneshot.ts"],"names":[],"mappings":""}
@@ -0,0 +1,36 @@
1
+ import { GameEngine } from "../game/engine.js";
2
+ import { LocalStorage } from "../storage/local-storage.js";
3
+ import * as fs from "node:fs";
4
+ import * as os from "node:os";
5
+ import * as path from "node:path";
6
+ const storage = new LocalStorage();
7
+ const engine = new GameEngine(storage);
8
+ const IMAGE_SERVER_INFO_FILE = path.join(os.homedir(), ".grinders-farm", "image-server.json");
9
+ function resolveFarmImageUrl(imagePath) {
10
+ try {
11
+ if (fs.existsSync(IMAGE_SERVER_INFO_FILE)) {
12
+ const raw = JSON.parse(fs.readFileSync(IMAGE_SERVER_INFO_FILE, "utf8"));
13
+ if (typeof raw.baseUrl === "string" && raw.baseUrl.trim()) {
14
+ const baseUrl = raw.baseUrl.trim().replace(/\/+$/, "");
15
+ return `${baseUrl}/${encodeURIComponent(path.basename(imagePath))}`;
16
+ }
17
+ }
18
+ }
19
+ catch {
20
+ // fall through to file:// fallback
21
+ }
22
+ return `file://${imagePath}`;
23
+ }
24
+ const command = process.argv.slice(2).join(" ");
25
+ if (!command) {
26
+ console.log('Usage: npx tsx src/adapters/oneshot.ts <command>');
27
+ console.log('Example: npx tsx src/adapters/oneshot.ts plant carrot A1');
28
+ process.exit(1);
29
+ }
30
+ const result = await engine.executeCommand(command);
31
+ console.log(result.message);
32
+ if (result.imagePath) {
33
+ console.log(`\n🖼 查看高清像素图: ${resolveFarmImageUrl(result.imagePath)}`);
34
+ }
35
+ process.exit(result.success ? 0 : 1);
36
+ //# sourceMappingURL=oneshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oneshot.js","sourceRoot":"","sources":["../../../src/adapters/oneshot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,MAAM,OAAO,GAAG,IAAI,YAAY,EAAE,CAAC;AACnC,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,OAAO,CAAC,CAAC;AACvC,MAAM,sBAAsB,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,gBAAgB,EAAE,mBAAmB,CAAC,CAAC;AAE9F,SAAS,mBAAmB,CAAC,SAAiB;IAC5C,IAAI,CAAC;QACH,IAAI,EAAE,CAAC,UAAU,CAAC,sBAAsB,CAAC,EAAE,CAAC;YAC1C,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,sBAAsB,EAAE,MAAM,CAAC,CAA0B,CAAC;YACjG,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;gBAC1D,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;gBACvD,OAAO,GAAG,OAAO,IAAI,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC;YACtE,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,mCAAmC;IACrC,CAAC;IACD,OAAO,UAAU,SAAS,EAAE,CAAC;AAC/B,CAAC;AAED,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAChD,IAAI,CAAC,OAAO,EAAE,CAAC;IACb,OAAO,CAAC,GAAG,CAAC,kDAAkD,CAAC,CAAC;IAChE,OAAO,CAAC,GAAG,CAAC,0DAA0D,CAAC,CAAC;IACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;AACpD,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AAE5B,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;IACrB,OAAO,CAAC,GAAG,CAAC,iBAAiB,mBAAmB,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;AACxE,CAAC;AAED,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=terminal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../../../src/adapters/terminal.ts"],"names":[],"mappings":""}
@@ -0,0 +1,70 @@
1
+ import * as readline from "node:readline";
2
+ import { GameEngine } from "../game/engine.js";
3
+ import { LocalStorage } from "../storage/local-storage.js";
4
+ import { renderAnsiFromImage } from "../render/ansi-renderer.js";
5
+ const WELCOME = `
6
+ ╔═══════════════════════════════════╗
7
+ ║ 🌿 CLAW FARM 🌿 ║
8
+ ║ 像素农场种植模拟游戏 ║
9
+ ╚═══════════════════════════════════╝
10
+
11
+ 输入 "help" 查看命令列表
12
+ 输入 "farm" 查看你的农场
13
+ `;
14
+ async function main() {
15
+ const storage = new LocalStorage();
16
+ const engine = new GameEngine(storage);
17
+ console.log(WELCOME);
18
+ const initial = await engine.executeCommand("farm");
19
+ console.log(initial.message);
20
+ if (initial.imagePath) {
21
+ try {
22
+ console.log();
23
+ console.log(await renderAnsiFromImage(initial.imagePath));
24
+ }
25
+ catch {
26
+ console.log(`\n🖼 农场图片已保存: ${initial.imagePath}`);
27
+ }
28
+ }
29
+ console.log();
30
+ const rl = readline.createInterface({
31
+ input: process.stdin,
32
+ output: process.stdout,
33
+ prompt: "🌱 > ",
34
+ });
35
+ rl.prompt();
36
+ rl.on("line", async (line) => {
37
+ const input = line.trim();
38
+ if (!input) {
39
+ rl.prompt();
40
+ return;
41
+ }
42
+ if (input === "quit" || input === "exit") {
43
+ console.log("再见,农场主!👋");
44
+ rl.close();
45
+ return;
46
+ }
47
+ const result = await engine.executeCommand(input);
48
+ console.log();
49
+ console.log(result.message);
50
+ if (result.imagePath) {
51
+ try {
52
+ console.log();
53
+ console.log(await renderAnsiFromImage(result.imagePath));
54
+ }
55
+ catch {
56
+ console.log(`\n🖼 农场图片已更新: ${result.imagePath}`);
57
+ }
58
+ }
59
+ console.log();
60
+ rl.prompt();
61
+ });
62
+ rl.on("close", () => {
63
+ process.exit(0);
64
+ });
65
+ }
66
+ main().catch((err) => {
67
+ console.error("Fatal error:", err);
68
+ process.exit(1);
69
+ });
70
+ //# sourceMappingURL=terminal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal.js","sourceRoot":"","sources":["../../../src/adapters/terminal.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { CropDef, GrowthStage, PlantedCrop } from "./types.js";
2
+ export declare const CROP_DEFS: Record<string, CropDef>;
3
+ export declare function getAllCropIds(): string[];
4
+ export declare function getCropDef(cropId: string): CropDef | undefined;
5
+ export declare function getStage(crop: PlantedCrop): GrowthStage;
6
+ export declare function advanceCropGrowth(crop: PlantedCrop): PlantedCrop;
7
+ export declare function createPlantedCrop(cropId: string): PlantedCrop;
8
+ //# sourceMappingURL=crops.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crops.d.ts","sourceRoot":"","sources":["../../../src/game/crops.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AA4B/D,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAa7C,CAAC;AAEF,wBAAgB,aAAa,IAAI,MAAM,EAAE,CAExC;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAE9D;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,WAAW,GAAG,WAAW,CAYvD;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,WAAW,GAAG,WAAW,CAQhE;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,CAQ7D"}
@@ -0,0 +1,71 @@
1
+ import { GrowthStage } from "./types.js";
2
+ const MIN_GAME_GROWTH_DAYS = 5;
3
+ const REAL_MATURITY_BASELINE_DAYS = 70;
4
+ function scaleGrowthDays(realMaturityDays) {
5
+ return Math.max(2, Math.round((realMaturityDays / REAL_MATURITY_BASELINE_DAYS) * MIN_GAME_GROWTH_DAYS));
6
+ }
7
+ function makeCropDef(id, name, emoji, realMaturityDays, seedPrice, sellPrice) {
8
+ return {
9
+ id,
10
+ name,
11
+ emoji,
12
+ realMaturityDays,
13
+ growthDays: scaleGrowthDays(realMaturityDays),
14
+ seedPrice,
15
+ sellPrice,
16
+ };
17
+ }
18
+ export const CROP_DEFS = {
19
+ carrot: {
20
+ ...makeCropDef("carrot", "胡萝卜", "🥕", 70, 5, 11),
21
+ },
22
+ potato: {
23
+ ...makeCropDef("potato", "土豆", "🥔", 95, 8, 22),
24
+ },
25
+ tomato: {
26
+ ...makeCropDef("tomato", "番茄", "🍅", 80, 9, 24),
27
+ },
28
+ pumpkin: {
29
+ ...makeCropDef("pumpkin", "南瓜", "🎃", 110, 12, 34),
30
+ },
31
+ };
32
+ export function getAllCropIds() {
33
+ return Object.keys(CROP_DEFS);
34
+ }
35
+ export function getCropDef(cropId) {
36
+ return CROP_DEFS[cropId];
37
+ }
38
+ export function getStage(crop) {
39
+ const def = getCropDef(crop.cropId);
40
+ if (!def)
41
+ return GrowthStage.Seed;
42
+ const requiredWaterDays = Math.max(1, crop.requiredWaterDays ?? def.growthDays);
43
+ if (crop.wateredDays >= requiredWaterDays)
44
+ return GrowthStage.Ready;
45
+ if (crop.wateredDays <= 0)
46
+ return GrowthStage.Seed;
47
+ const progress = crop.wateredDays / requiredWaterDays;
48
+ if (progress < 1 / 3)
49
+ return GrowthStage.Sprout;
50
+ if (progress < 2 / 3)
51
+ return GrowthStage.Growing1;
52
+ return GrowthStage.Growing2;
53
+ }
54
+ export function advanceCropGrowth(crop) {
55
+ const before = getStage(crop);
56
+ if (before === GrowthStage.Ready) {
57
+ return { ...crop, watered: false };
58
+ }
59
+ const newWatered = crop.watered ? crop.wateredDays + 1 : crop.wateredDays;
60
+ return { ...crop, wateredDays: newWatered, watered: false };
61
+ }
62
+ export function createPlantedCrop(cropId) {
63
+ const def = getCropDef(cropId);
64
+ return {
65
+ cropId,
66
+ wateredDays: 0,
67
+ watered: false,
68
+ requiredWaterDays: def?.growthDays ?? 4,
69
+ };
70
+ }
71
+ //# sourceMappingURL=crops.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crops.js","sourceRoot":"","sources":["../../../src/game/crops.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import { FarmState, CommandResult } from "./types.js";
2
+ import { LocalStorage } from "../storage/local-storage.js";
3
+ export declare class GameEngine {
4
+ private state;
5
+ private storage;
6
+ constructor(storage: LocalStorage);
7
+ getState(): FarmState;
8
+ private save;
9
+ private reload;
10
+ private isMutatingCommand;
11
+ advanceDay(): Promise<CommandResult>;
12
+ executeCommand(input: string): Promise<CommandResult>;
13
+ private executeWithCurrentState;
14
+ }
15
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../src/game/engine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AActD,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAqB3D,qBAAa,UAAU;IACrB,OAAO,CAAC,KAAK,CAAY;IACzB,OAAO,CAAC,OAAO,CAAe;gBAElB,OAAO,EAAE,YAAY;IAKjC,QAAQ,IAAI,SAAS;IAIrB,OAAO,CAAC,IAAI;IAIZ,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,iBAAiB;IAInB,UAAU,IAAI,OAAO,CAAC,aAAa,CAAC;IAoBpC,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;YAoB7C,uBAAuB;CA+FtC"}
@@ -0,0 +1,236 @@
1
+ import { createNewFarm, plant, water, harvest, sellAll, nextDay, getShopText, getInventoryText, ensureFarmState, } from "./farm.js";
2
+ import { renderFarmText } from "../render/text-renderer.js";
3
+ import { renderFarmImage } from "../render/image-renderer.js";
4
+ import { startLocalAuto, stopLocalAuto } from "../local-auto.js";
5
+ const DEFAULT_START_INTERVAL_SEC = 20;
6
+ const KNOWN_COMMANDS = new Set([
7
+ "farm",
8
+ "status",
9
+ "plant",
10
+ "water",
11
+ "harvest",
12
+ "shop",
13
+ "sell",
14
+ "inventory",
15
+ "inv",
16
+ "start",
17
+ "stop",
18
+ "help",
19
+ "reset",
20
+ ]);
21
+ export class GameEngine {
22
+ state;
23
+ storage;
24
+ constructor(storage) {
25
+ this.storage = storage;
26
+ this.state = ensureFarmState(storage.load() ?? createNewFarm());
27
+ }
28
+ getState() {
29
+ return this.state;
30
+ }
31
+ save() {
32
+ this.storage.save(this.state);
33
+ }
34
+ reload() {
35
+ this.state = ensureFarmState(this.storage.load() ?? createNewFarm());
36
+ }
37
+ isMutatingCommand(cmd) {
38
+ return cmd === "plant" || cmd === "water" || cmd === "harvest" || cmd === "sell" || cmd === "reset";
39
+ }
40
+ async advanceDay() {
41
+ return this.storage.withStateLock(async () => {
42
+ this.reload();
43
+ const result = nextDay(this.state);
44
+ this.save();
45
+ if (result.success) {
46
+ const farmView = renderFarmText(this.state);
47
+ result.message += "\n\n" + farmView;
48
+ try {
49
+ result.imagePath = await renderFarmImage(this.state);
50
+ }
51
+ catch {
52
+ // image rendering unavailable, text-only fallback
53
+ }
54
+ }
55
+ return result;
56
+ });
57
+ }
58
+ async executeCommand(input) {
59
+ const normalizedInput = normalizeFarmInput(input);
60
+ const parts = normalizedInput.trim().toLowerCase().split(/\s+/);
61
+ const cmd = parts[0];
62
+ if (!cmd) {
63
+ return { success: false, message: '输入 "help" 查看帮助' };
64
+ }
65
+ if (this.isMutatingCommand(cmd)) {
66
+ return this.storage.withStateLock(async () => {
67
+ this.reload();
68
+ return this.executeWithCurrentState(cmd, parts);
69
+ });
70
+ }
71
+ this.reload();
72
+ return this.executeWithCurrentState(cmd, parts);
73
+ }
74
+ async executeWithCurrentState(cmd, parts) {
75
+ let result;
76
+ switch (cmd) {
77
+ case "farm":
78
+ case "status": {
79
+ const text = renderFarmText(this.state);
80
+ let imagePath;
81
+ try {
82
+ imagePath = await renderFarmImage(this.state);
83
+ }
84
+ catch {
85
+ // image rendering unavailable, text-only fallback
86
+ }
87
+ return { success: true, message: text, imagePath };
88
+ }
89
+ case "plant": {
90
+ const cropId = parts[1];
91
+ const label = parts[2];
92
+ if (!cropId || !label) {
93
+ return { success: false, message: '用法: plant <作物> <位置>\n例如: plant carrot A1' };
94
+ }
95
+ result = plant(this.state, cropId, label.toUpperCase());
96
+ break;
97
+ }
98
+ case "water": {
99
+ const label = parts[1]?.toUpperCase();
100
+ result = water(this.state, label);
101
+ break;
102
+ }
103
+ case "harvest": {
104
+ const label = parts[1]?.toUpperCase();
105
+ result = harvest(this.state, label);
106
+ break;
107
+ }
108
+ case "shop":
109
+ return { success: true, message: getShopText(this.state) };
110
+ case "sell":
111
+ result = sellAll(this.state);
112
+ break;
113
+ case "inventory":
114
+ case "inv":
115
+ return { success: true, message: getInventoryText(this.state) };
116
+ case "start":
117
+ if (parts.length > 1) {
118
+ return { success: false, message: '用法: start(固定每 20 秒推进一天)' };
119
+ }
120
+ return startLocalAuto(DEFAULT_START_INTERVAL_SEC);
121
+ case "stop":
122
+ if (parts.length > 1) {
123
+ return { success: false, message: '用法: stop' };
124
+ }
125
+ return stopLocalAuto();
126
+ case "help":
127
+ return { success: true, message: getHelpText() };
128
+ case "reset": {
129
+ this.state = createNewFarm();
130
+ this.save();
131
+ const resetView = renderFarmText(this.state);
132
+ let resetImagePath;
133
+ try {
134
+ resetImagePath = await renderFarmImage(this.state);
135
+ }
136
+ catch {
137
+ // image rendering unavailable
138
+ }
139
+ return { success: true, message: "农场已重置!全新开始 🌱\n\n" + resetView, imagePath: resetImagePath };
140
+ }
141
+ default:
142
+ return { success: false, message: `未知命令 "${cmd}"。输入 "help" 查看帮助` };
143
+ }
144
+ this.save();
145
+ if (result.success) {
146
+ const farmView = renderFarmText(this.state);
147
+ result.message += "\n\n" + farmView;
148
+ try {
149
+ result.imagePath = await renderFarmImage(this.state);
150
+ }
151
+ catch {
152
+ // image rendering unavailable, text-only fallback
153
+ }
154
+ }
155
+ return result;
156
+ }
157
+ }
158
+ function normalizeFarmInput(input) {
159
+ const raw = input.trim();
160
+ if (!raw)
161
+ return raw;
162
+ const parts = raw.toLowerCase().split(/\s+/);
163
+ if (KNOWN_COMMANDS.has(parts[0]))
164
+ return raw;
165
+ const cropMap = [
166
+ { id: "carrot", aliases: ["carrot", "胡萝卜"] },
167
+ { id: "potato", aliases: ["potato", "土豆", "马铃薯"] },
168
+ { id: "tomato", aliases: ["tomato", "番茄", "西红柿"] },
169
+ { id: "pumpkin", aliases: ["pumpkin", "南瓜"] },
170
+ ];
171
+ const posMatch = raw.match(/([A-Da-d])\s*([1-5])/);
172
+ const pos = posMatch ? `${posMatch[1].toUpperCase()}${posMatch[2]}` : "";
173
+ const text = raw.toLowerCase();
174
+ const has = (...tokens) => tokens.some((t) => text.includes(t));
175
+ const findCropId = () => {
176
+ for (const c of cropMap) {
177
+ if (c.aliases.some((a) => text.includes(a.toLowerCase())))
178
+ return c.id;
179
+ }
180
+ return null;
181
+ };
182
+ if (has("自动", "auto")) {
183
+ if (has("停", "关闭", "关掉", "stop"))
184
+ return "stop";
185
+ if (has("开", "启动", "start"))
186
+ return "start";
187
+ }
188
+ if (has("种", "种植", "播种", "plant")) {
189
+ const cropId = findCropId();
190
+ if (cropId && pos)
191
+ return `plant ${cropId} ${pos}`;
192
+ if (cropId)
193
+ return "farm";
194
+ }
195
+ if (has("浇水", "water"))
196
+ return pos ? `water ${pos}` : "water";
197
+ if (has("收获", "harvest"))
198
+ return pos ? `harvest ${pos}` : "harvest";
199
+ if (has("商店", "shop", "买种子", "买什么"))
200
+ return "shop";
201
+ if (has("出售", "卖掉", "卖出", "sell"))
202
+ return "sell";
203
+ if (has("仓库", "背包", "库存", "inventory", "inv"))
204
+ return "inventory";
205
+ if (has("重置", "reset", "重新开始"))
206
+ return "reset";
207
+ if (has("开始", "启动", "start"))
208
+ return "start";
209
+ if (has("停止", "关闭", "关掉", "stop"))
210
+ return "stop";
211
+ if (has("帮助", "help"))
212
+ return "help";
213
+ if (has("农场", "farm", "地块", "作物", "庄稼"))
214
+ return "farm";
215
+ return raw;
216
+ }
217
+ function getHelpText() {
218
+ return [
219
+ "🌿 Grinder's Farm — 命令帮助",
220
+ "",
221
+ " farm / status 查看农场全景",
222
+ " plant <作物> <位置> 种植作物 (如: plant carrot A1)",
223
+ " water [位置] 浇水(不指定则浇全部)",
224
+ " harvest [位置] 收获(不指定则收全部成熟作物)",
225
+ " shop 查看种子商店",
226
+ " sell 出售仓库中所有农产品",
227
+ " inventory / inv 查看仓库",
228
+ " start 启动自动推进(固定20秒/天,自动推送到已绑定频道)",
229
+ " stop 停止自动推进",
230
+ " reset 重新开始",
231
+ " help 显示此帮助",
232
+ "",
233
+ "位置格式: 行字母 + 列数字,如 A1, B3, D5",
234
+ ].join("\n");
235
+ }
236
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../../../src/game/engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import { FarmState, CommandResult } from "./types.js";
2
+ export declare function ensureFarmState(state: FarmState): FarmState;
3
+ export declare function getCurrentSellPrice(state: FarmState, cropId: string): number;
4
+ export declare function createNewFarm(rows?: number, cols?: number): FarmState;
5
+ export declare function plant(state: FarmState, cropId: string, label: string): CommandResult;
6
+ export declare function water(state: FarmState, label?: string): CommandResult;
7
+ export declare function harvest(state: FarmState, label?: string): CommandResult;
8
+ export declare function sellAll(state: FarmState): CommandResult;
9
+ export declare function nextDay(state: FarmState): CommandResult;
10
+ export declare function getShopText(state?: FarmState): string;
11
+ export declare function getInventoryText(state: FarmState): string;
12
+ //# sourceMappingURL=farm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"farm.d.ts","sourceRoot":"","sources":["../../../src/game/farm.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EAGT,aAAa,EAKd,MAAM,YAAY,CAAC;AA4BpB,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,CA4B3D;AASD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAI5E;AA6CD,wBAAgB,aAAa,CAAC,IAAI,SAAe,EAAE,IAAI,SAAe,GAAG,SAAS,CAqBjF;AAgBD,wBAAgB,KAAK,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,aAAa,CAuCpF;AAED,wBAAgB,KAAK,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,aAAa,CA8BrE;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,aAAa,CAiDvE;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,SAAS,GAAG,aAAa,CAsDvD;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,SAAS,GAAG,aAAa,CA6CvD;AAED,wBAAgB,WAAW,CAAC,KAAK,CAAC,EAAE,SAAS,GAAG,MAAM,CAiBrD;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAWzD"}