[插件] 开心农场(KXFarm)→ FlintHub 插件 开发规划方案

👑Lv.11 元老 🌞 骨干会员
2026-11-01 16:36:49

版本:v1.0(2026-11-01) 目标源码:D:\phpstudy_pro\WWW\KXFarm(Java Swing 单机版,310 文件 / 10.8 MB) 依据规范:docs/插件开发规范.md(v1.8,核心 V1.3.2) 插件标识:目录 plugins/kx_farm/,命名空间 Plugin\KxFarm,显示名「开心农场」


一、现状盘点(KXFarm)

1.1 技术形态

项结论
技术栈Java SE + Swing 桌面 GUI(.classpath/.project 为 Eclipse 工程)
入口src/main/APP.java → view/user/LoginJFrame(自带注册/登录窗口)
数据本地文件存档:`user/{userID}/user.txt
多人无网络层;「好友农场」FriendFarm 直接读同机其他用户目录,属本地伪多人
状态推进javax.swing.Timer + System.currentTimeMillis() 客户端计时
主窗口view/farm/JtFarm.java(491 行,金币/经验/等级刷新与交互总控)

结论:GUI、登录注册、存档、计时全部不可复用,可复用部分为数值规则 + 美术资源。

1.2 核心数据模型(源码字段)

  • UserBean:userID / userName / nick / passWord / pic / money(double) / exp / level / notice / userSign
  • LandData:landID / cronid(作物ID) / startTime(epoch ms) / nowStage / stealCount
  • CropBean(image/crops/cropN/crop.txt):cropId / name / pic / unitTime / stageCount / buyLevel / sellMoney / seedMoney

1.3 作物数值表(原版,共 15 种)

阶段时长规则:第 k 阶段耗时 k * unitTime 秒;总成熟时间 = unitTime * n(n+1)/2 秒。 收获产量:随机 10–30;偷摘产量:随机 1–3(每块地全站仅一次)。

ID作物阶段数单阶段基数(秒)原版总时长买价卖价解锁等级
1草莓510150s10201
2玉米512180s15301
3白萝卜415150s18351
4胡萝卜416160s19371
5地瓜518270s20402
6茄子519285s22422
7西红柿520300s24442
8绿豆522330s26463
9辣椒524360s28483
10南瓜526390s30504
11苹果628588s33554
12西瓜530450s35575
13香蕉632672s37605
14桃子534510s38626
15菠萝636756s39646

1.4 原版玩法规则(需在 Web 版保留)

  • 播种消耗背包种子,经验 +5;收获经验 +1;铲地经验 +3;出售经验 +1(按次)。
  • 升级公式:升级所需经验 = level * (level + 1) * 100(原版 ((level+1)*level/2)*200),只升 1 级。
  • 收获进「仓库」,出售按 产量 × sellMoney 计入金币。
  • 偷摘:仅可偷成熟且未被偷过的地块,偷后该地块 stealCount > 0,其他访客不能再偷。
  • 默认 6 块地(存档 land.txt 为 6 行:地号,作物ID,开始时间)。

1.5 美术资源盘点

目录文件数体积可用性
image/background4 PNG 1024×7683.17 MB✅ 选 1 张作农场场景底图(需压成 JPEG/WebP)
image/background背景图片4 PNG3.17 MB❌ 与上者完全重复,丢弃
image/crops(15 组)121 PNG + 15 txt1.48 MB✅ 核心素材:每阶段一张 201×103 整块地贴图 + seed.png(48×48) + cron_start/cron_end
image/soil土地图片5 PNG 201×1030.16 MB✅ 空地/翻地状态
image/guiRes35(32 PNG/2 GIF/1 JPG)1.96 MB⚠️ 选留(招牌 paizi、角色、tilled、成功动效),其余裁掉
image/face20 GIF0.03 MB❌ 站点已有头像,不用
image/topbutton (18)(19).png2 PNG0.02 MB❌ 桌面顶栏按钮,不用
bin/、user/、.settings/—~3 MB❌ 编译产物与桌面存档,不入包

关键约束:插件商店单包上限默认 5120 KB(规范 §11.35),当前可用图片约 6.8 MB → 必须做资源压缩,目标整包 < 4 MB。


二、改造总体思路

  1. 只移植「规则 + 美术」,不移植 UI:Java Swing 窗口、登录注册、本地存档、Timer 全部丢弃。
  2. 单机 → 在线多人:
    • 账号体系接入 FlintHub 登录(Auth),不再自带注册/登录;
    • 存档从 user/*.txt 迁到插件独立 SQLite;
    • 计时改为服务端时间判定(planted_at + 阶段时长),客户端只负责倒计时展示 → 天然防改时间作弊;
    • 「好友农场」升级为「访问任意站点用户农场 + 偷摘」,并记录偷摘日志。
  3. 两套经济不混用:金币/经验/等级存插件库,不直接写站内积分;后台可选开启「升级奖励站内积分」(调用 Points::award)。
  4. 渲染方案:每块地是一张 201×103 的整块贴图,Web 端用 CSS Grid + background-image 即可,不需要 Canvas 引擎;空地/生长/成熟直接换图,成熟期加 CSS 浮动动效。
  5. 按插件规范落地:plugins/kx_farm/ 标准目录、三语语言包、后台固定结构、CSRF/原子更新/事务、9 项打包门禁。

三、功能范围

3.1 MVP(首个可上线版本)

  • 前台 /farm:农场网格(初始 6 块、可扩至 12)、作物状态倒计时、快捷操作(播种/收获/铲地/浇水)、金币/经验/等级条、背包与仓库抽屉、商店弹层。
  • 作物时长按 unitTime × 60(后台可调倍率)、买种子、卖作物、自动进仓库、收获随机产量、经验与升级(金币体系独立于站内积分)。
  • 访问他人农场 /farm/visit/{uid} + 偷摘(每块地全站一次,可后台关闭)。
  • 排行榜 /farm/rank(按等级/经验或金币,Top 20)。
  • 后台 /admin/kx-farm:概览、玩家列表(金币/经验/封禁/补发/重置)、作物数值编辑、全局设置(时间倍率/土地上限/偷菜开关/每日限额)、操作日志。
  • 入口:顶部导航 nav_plugin_links + 首页右栏 home_sidebar_bottom + 个人主页 profile_user_card_after 三个入口。

3.2 P1(迭代)

  • 每日任务(播种/收获/出售/偷菜各 N 次 → 金币奖励)。
  • 道具:化肥(缩短当前阶段 50%)、浇水(缩短 10%,一次性)。
  • 成就与徽章、收获/升级飘字、访问动态(谁偷了我的菜)。
  • 金币 ↔ 站内积分兑换(后台开关 + 汇率)。

3.3 明确不做

  • 桌面版登录/注册/改密码/换头像窗口(交由站点账号体系)。
  • 桌面本地存档导入(如需老存档迁移,仅后台提供 CLI 一次性导入,默认不做)。
  • 桌面摇奖/商店外的 GUI 装饰功能。

四、数据库设计(插件独立 SQLite:plugins/kx_farm/data/kx_farm.sqlite)

kf_users (
  user_id   INTEGER PRIMARY KEY,           -- 站点 users.id
  coins     INTEGER NOT NULL DEFAULT 200,  -- 金币(新用户初始 200)
  exp       INTEGER NOT NULL DEFAULT 0,
  level     INTEGER NOT NULL DEFAULT 1,
  lands     INTEGER NOT NULL DEFAULT 6,    -- 已解锁地块数(≤12)
  created_at TEXT NOT NULL,
  updated_at TEXT NOT NULL
)

kf_lands (
  id          INTEGER PRIMARY KEY AUTOINCREMENT,
  user_id     INTEGER NOT NULL,
  slot        INTEGER NOT NULL,            -- 0..11
  crop_id     INTEGER NOT NULL DEFAULT 0,  -- 0 = 空地
  planted_at  INTEGER NOT NULL DEFAULT 0,  -- unix 秒
  watered     INTEGER NOT NULL DEFAULT 0,  -- 已浇水(一次性)
  fertilized  INTEGER NOT NULL DEFAULT 0,  -- 施肥次数
  steal_count INTEGER NOT NULL DEFAULT 0,  -- 0=未被偷;1=已偷
  steal_by    INTEGER NOT NULL DEFAULT 0,
  cleared_at  INTEGER NOT NULL DEFAULT 0,  -- 成熟后未铲地的标记
  UNIQUE(user_id, slot)
)

kf_bag   (user_id INTEGER, crop_id INTEGER, qty INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(user_id, crop_id))
kf_store (user_id INTEGER, crop_id INTEGER, qty INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(user_id, crop_id))

kf_crops (
  crop_id INTEGER PRIMARY KEY, name_key TEXT NOT NULL, stage_count INTEGER NOT NULL,
  unit_time INTEGER NOT NULL, seed_price INTEGER NOT NULL, sell_price INTEGER NOT NULL,
  buy_level INTEGER NOT NULL, enabled INTEGER NOT NULL DEFAULT 1, sort INTEGER NOT NULL DEFAULT 0
)

kf_config (key TEXT PRIMARY KEY, value TEXT NOT NULL)   -- 时间倍率/土地上限/开关/限额
kf_daily  (user_id INTEGER, day TEXT, sell_qty INT, steal_cnt INT, harvest_cnt INT, planted_cnt INT,
           PRIMARY KEY(user_id, day))
kf_logs   (id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INT, action TEXT, detail TEXT, created_at TEXT)

索引:kf_lands(user_id)、kf_store(user_id)、kf_bag(user_id)、kf_logs(user_id, created_at)、kf_daily(user_id, day)。

并发/防作弊要点

  • 播种:先原子扣种子 UPDATE kf_bag SET qty=qty-1 WHERE user_id=:u AND crop_id=:c AND qty>0(rowCount()==0 → 拒绝),再 UPDATE kf_lands ... WHERE crop_id=0 抢占地块;任一失败整体回滚。
  • 收获:UPDATE kf_lands SET crop_id=0, cleared_at=:t WHERE user_id=:u AND slot=:s AND crop_id=:c AND planted_at=:p(CAS),rowCount()!=1 视为重复收获 → 拒绝;产量在事务内随机并写入仓库。
  • 偷摘:UPDATE kf_lands SET steal_count=steal_count+1, steal_by=:thief WHERE user_id=:owner AND slot=:s AND steal_count=0 AND crop_id=:c AND planted_at<=成熟阈值,rowCount()==1 才算成功。
  • 成熟判断全部服务端计算:elapsed = time() - planted_at,与客户端无关。
  • 每用户每类操作每日上限(kf_daily,可后台关)。
  • Plugin::db() 已带 ERRMODE_EXCEPTION + busy_timeout=5000,插件不覆盖任何 PDO 属性(红线 7)。

五、路由与接口清单

5.1 前台页面(route_register)

方法路径说明
GET/farm我的农场(需登录,未登录 requireLogin())
GET/farm/visit/{uid}访问他人农场(公开可看,偷菜需登录)
GET/farm/rank排行榜(等级/金币 Top 20)

5.2 前台接口(全部 JSON,/api/kx_farm/*)

方法路径参数说明
GET/api/kx_farm/state—一次返回:用户数值、地块(含服务端计算的阶段/剩余秒)、商店、背包、仓库、今日限额
GET/api/kx_farm/visituid他人地块只返回阶段与是否可偷,不暴露精确时间
POST/api/kx_farm/plantslot, crop_id播种(扣种子 + 经验 +5)
POST/api/kx_farm/harvestslot收获(随机 10–30,进仓库,经验 +1)
POST/api/kx_farm/shovelslot铲地(仅成熟/枯萎,经验 +3)
POST/api/kx_farm/buycrop_id, qty买种子(金币扣减原子校验余额)
POST/api/kx_farm/sellcrop_id, qty卖作物(仓库扣减 + 金币增加,经验 +1)
POST/api/kx_farm/stealuid, slot偷摘(1–3,写日志)
POST/api/kx_farm/expand—扩地(等级 + 金币门槛)

统一约定:所有 POST 先 ajaxUser()(登录)→ Csrf::verifyOrDie() → 业务;失败一律 {ok:false,msg};写操作返回最新数值,前端不自行改余额,以服务端回包为准。

5.3 后台(admin_route_register,实际前缀 /admin)

方法路径说明
GET/admin/kx-farm管理首页(Tab:概览 / 玩家 / 作物 / 设置 / 日志)
POST/admin/kx-farm/save保存全局设置(写 kf_config)
POST/admin/kx-farm/crop-save编辑作物数值(价格/时长/解锁等级/上下架)
POST/admin/kx-farm/player玩家操作:补发金币、重置农场、封禁农场
GET/admin/kx-farm/logs日志分页查询

全局设置存插件库 kf_config,不写站内全局 Settings → permissions 仅需 ["route:admin"]。


六、视图与前端实现

6.1 页面骨架

views/farm/index.php    我的农场(.kf-wrap 内层容器,1080px)
views/farm/visit.php    他人农场
views/farm/rank.php     排行榜
views/farm/_topbar.php  金币/经验/等级/今日额度(三页复用)
views/admin.php         后台固定结构(admin-container + admin/_sidebar + main.admin-content + admin-header)
  • 前台沿用核心样式变量 --mn-*,不自造配色;按钮统一 mn-btn / mn-btn-primary,输入用 mn-input;
  • 路由地址一律 $this->url() / Url::to();静态资源才 BASE_PATH;JS 不拼 URL(全部由 data-* 注入);
  • 零内联:无 <script> 逻辑块、无 on*、无 style=。

6.2 农场网格渲染

  • 布局:grid-template-columns: repeat(3, minmax(0, 1fr)),每格 aspect-ratio: 201/103;
  • 每格 background-image 指向当前阶段贴图(assets/img/crops/{crop}/{stage}.webp),成熟加 .is-mature 浮动动画;
  • 场景底图 1024×768 作为外层背景,整体在 1080px 容器内等比缩放,860px 断点切 2 列;
  • 倒计时:页面拿到 planted_at、unit_time、stage_count 后由 JS 本地推进显示,仅展示,所有判定以接口返回的 stage/remaining 为准;
  • 定时刷新:页面可见时每 30s 拉一次 /api/kx_farm/state(不可见时暂停,visibilitychange)。

6.3 交互弹层

商店 / 背包 / 仓库统一用页面内 DOM 弹层(非原生 alert),复用一个 .kf-modal;操作结果统一 toast,禁止 alert()。

6.4 语言包(三语,键集合与键序必须完全一致——门禁 #1)

  • 前缀 plugin.kx_farm.*:导航、标题、按钮、提示、错误码、后台表单、作物名(15 个 crop_1..15)、日志动作名;
  • 作物名走语言包(不写死中文),数值进 kf_crops(后台可调)。

七、资源改造计划

步骤内容目标
1复制 15 组作物贴图(201×103 ×121 张)+ cron_start/cron_end + seed.png保留原画风
2统一转 WebP q85(保透明),命名 assets/img/crops/{cropId}/{stage}.webp、seed.webp1.48 MB → ≈0.6 MB
3背景:4 选 1(推荐 background/1.png),转 JPEG q80(或 WebP q80),可选提供 2 套皮肤0.7–0.9 MB → ≈0.15–0.25 MB
4soil 5 张转 WebP,用作空地/未解锁0.16 → 0.06 MB
5guiRes 只留 paizi.png / tilled.png / success.gif / congrats.gif → WebP/压缩 GIF1.96 → ≈0.3 MB
6丢弃重复 background背景图片、face、topbutton、bin、user、.settings−4 MB 以上
7图片统一懒加载 + loading=lazy(弹层内素材),首屏只加载场景底图 + 6 格首屏 ≤ 400 KB

合计目标:插件包 < 4 MB(留足商店 5120 KB 余量),并在 改动说明.md 注明素材来源。


八、规范落地清单(逐项对照)

  1. 目录:plugin.json / Plugin.php / FrontController.php / AdminController.php / hook/ / views/ / assets/ / lang/ / data/。
  2. plugin.json:name=开心农场、version=1.0.0、min_core=1.3.2、category=entertainment、icon=seedling(已核实存在于 TemplateCompiler::$map)、admin_url=/admin/kx-farm、permissions=["route:admin"]、hooks 见下。
  3. 钩子:init_after(幂等建表 + 种子数据)、route_register、admin_route_register、nav_plugin_links(双触发守卫 + 16px 图标)、home_sidebar_bottom(侧栏入口卡片)、profile_user_card_after("去 TA 的农场"按钮)。
  4. 独立库:Plugin::db() + ensureSchema();DDL 幂等;事务只包本库写,发积分等跨库动作放事务外。
  5. 安全:ajaxUser() → Csrf::verifyOrDie() 顺序;原子 UPDATE + rowCount();IN 查询强转占位符;输出 e();禁 unserialize/eval/DOCUMENT_ROOT;上传(若 P1 加自定义头像)走 Upload::file()。
  6. i18n:三语 100+ 键,键序一致;lang/ 自动合并,无需钩子。
  7. 后台:固定侧栏结构、表格/分页/提示按核心后台写法(alert-error 而非 alert-danger、form-input 仅限 .admin-content 作用域)。
  8. 打包:php cli/release_build.php --type=plugin --name=kx_farm --version=1.0.0 --dry-run,9 项门禁通过后正式出包并重建 release/plugins/index.json。

九、实施阶段与验收

M0 骨架与资源(先行)

  • 建插件目录、plugin.json、三语空壳、SQLite 建表、种子 15 作物;
  • 资源流水线:裁剪/转码/命名/体积统计。
  • 验收:php -l 全绿;包体积 < 4MB;kf_crops 15 条与上表逐条一致。

M1 数据层 + 核心循环(无 UI)

  • Plugin.php:state() / plant() / harvest() / shovel() / buy() / sell() 纯业务方法(可被控制器与 CLI 复用);
  • 服务端阶段计算、经验/升级、原子更新与事务。
  • 验收:脚本/接口模拟「买→种→等→收→卖」闭环;重复收获/重复播种被拒;余额不会为负。

M2 前台主页面

  • /farm 页面 + state 接口 + 网格渲染 + 弹层(商店/背包/仓库)+ 顶部数值条。
  • 验收:登录可见 6 块地;操作后数值/贴图即时正确;刷新后状态一致;移动端 2 列不溢出。

M3 社交玩法

  • /farm/visit/{uid}、偷摘、排行榜、profile_user_card_after 入口、侧栏卡片。
  • 验收:A 偷 B 的菜只能成功一次;B 地块显示"已被偷";日志可查;未登录访问只读。

M4 后台

  • 概览/玩家/作物/设置/日志 5 个 Tab,CSRF 全覆盖,分页与筛选。
  • 验收:改作物价格后前台立即生效;封禁玩家后其接口返回 403;重置农场清空地块但保留账号数值。

M5 合规、性能、打包

  • i18n 三语比对、零内联扫描、URL 双模式(伪静态开/关)回归、并发脚本(10 并发重复收获)、9 项门禁、正式出包。
  • 验收:门禁全 PASS(签名 WARN 可接受);/farm 首屏 < 500ms(本地);商店包可安装并激活。

十、风险与对策

风险影响对策
图片 6.8MB 超商店 5MB无法上架M0 阶段先做转码与裁剪,整包 < 4MB;必要时降背景分辨率到 1280×720
原版数值通胀(1 次收获 10–30 个)金币贬值、排行榜失真保留原味同时加「每日出售/偷摘上限」,后台可调;首版不上积分兑换
客户端改时间作弊数值失衡阶段/成熟/偷菜判定 100% 服务端;客户端只做展示
SQLite 并发写高并发下锁等待单事务短小、只写必要列、busy_timeout=5000、避免在事务内做非 DB 操作
桌面版存档迁移老玩家数据丢失首版不迁移;如需,后台提供一次性 CLI 导入(Properties → SQLite),默认关闭
素材版权/来源上架审核风险在 改动说明.md 与后台说明中标明素材来源于用户提供的 KXFarm 工程
路由 /farm 冲突404/覆盖已检索核心 app/ 无 /farm 路由;实现前再对 plugins/*/hook/route_register.php 做一次全量冲突扫描

十一、交付文件清单

plugins/kx_farm/
├── plugin.json
├── Plugin.php                 # db/ensureSchema/种子/业务方法(state,plant,harvest,...)
├── FrontController.php        # /farm、/farm/visit、/farm/rank、/api/kx_farm/*
├── AdminController.php        # /admin/kx-farm 及 POST 动作
├── hook/
│   ├── init_after.php
│   ├── route_register.php
│   ├── admin_route_register.php
│   ├── nav_plugin_links.php
│   ├── home_sidebar_bottom.php
│   └── profile_user_card_after.php
├── views/
│   ├── farm/index.php
│   ├── farm/visit.php
│   ├── farm/rank.php
│   ├── farm/_topbar.php
│   └── admin.php
├── assets/
│   ├── style.css
│   ├── game.js
│   └── img/ (crops/ soil/ bg/ gui/,压缩后 < 3.5MB)
├── lang/ (zh.php / en.php / zh_tw.php)
└── data/  (运行期自动创建 sqlite + .htaccess + web.config)

十二、已确认决策(2026-11-01 用户拍板)

#决策项结论落地影响
1经济体系独立金币(金币/经验/等级存插件库)不读写站内积分;Points::award 仅用于 P1 可选的「升级奖励」
2时间倍率×60(1 游戏秒 = 1 现实分钟)草莓 150s→2.5h,菠萝 756s→12.6h;后台 time_scale 可调
3偷菜保留每块地全站仅 1 次、偷 1–3 个,需登录且等级 ≥3,后台可关
4土地6 块起、可扩到 12kf_users.lands 默认 6;扩地需等级 + 金币门槛
5资源取舍默认按 体积优先(整包 < 4MB)背景单套 1024×768 转 JPEG/WebP,crops/soil 转 WebP

以上结论已同步到第三 / 四 / 五 / 七章的默认参数,开发时直接按此实现,无需再确认。

轻量级、高性能、零 MySQL 依赖的PHP社区系统。
| 浏览 12 次 | 回复 1 次

全部回复 (1)

🌳Lv.4 中级 🌛 见习会员
2026-11-01 17:29:12
JtFarm 491 行总控、Timer 客户端计时、存档直接读同机目录,这套确实只能当文档看,能迁移的是作物数值表与美术资源。迁移时最大的坑是计时:原版用 currentTimeMillis 单调推进,换成服务端权威时间后,成熟与偷摘判定必须改成「上次结算时间 → 当前时间」的区间补算,否则离线期间的阶段会一次性炸开。另外 n(n+1)/2 这套阶段公式最好固化成配置,别散在代码里。
#1 楼

请 登录