Ticker
基本信息
| 属性 | 值 |
|---|---|
| 类名 | mytown.handlers.Ticker |
| 文件 | src/main/java/mytown/handlers/Ticker.java |
| 行数 | 98 |
| 启用版本 | Minecraft 1.7.10 |
功能
服务端时钟驱动器。挂在 TickEvent.WorldTickEvent 上,承担两件按时间推进的事:
逐个 tick 居民,以及按自然日收维护费。
由 Mod 入口 registerHandlers() 双总线注册
(FML bus + Forge bus 各一次)。
字段
| 字段 | 初值 | 作用 |
|---|---|---|
ticked |
true |
阶段翻转标志(START / END 交替) |
lastCalendarDay |
-1 |
上一自然日(Calendar.DAY_OF_YEAR),-1 表示尚未初始化 |
onTickEvent(TickEvent.WorldTickEvent)
ev.side == Side.CLIENT→ 立即 return(纯服务端逻辑)。- 每 tick 遍历
MyTownUniverse.instance.residents,逐个res.tick()。 - 仅当
costTownUpkeep > 0 || costAdditionalUpkeep > 0(均为默认 0) 且ev.phase == Phase.START时,才进入收费分支。
每日维护费
检测 Calendar.getInstance().get(Calendar.DAY_OF_YEAR) 与 lastCalendarDay 不同
(即跨了一天),然后遍历所有城镇:
- 跳过
AdminTown(if (!(town instanceof AdminTown)))—— 管理员城镇永不因欠费被删。 town.bank.payUpkeep()。- 若
daysNotPaid == upkeepTownDeletionDays且upkeepTownDeletionDays > 0→ 记日志并datasource.deleteTown(town); - 否则
datasource.saveTownBank(town.bank)。
实现要点
⚠️ 按默认配置,整段维护费逻辑是死代码:
costTownUpkeep 与 costAdditionalUpkeep 默认均为 0
(见 Config),两个条件都不满足,分支永不进入。
必须由服主主动配置非零费用才生效。
⚠️ 删除条件是 == 而非 >=:
只有 daysNotPaid 恰好等于 upkeepTownDeletionDays 的那一 tick 才会删镇。
若因故跳过那一次(重启、崩溃、配置改动),
该镇会因欠费永久保留。这是个真实的边界缺陷。
⚠️ upkeepTownDeletionDays 默认 7,但删除分支额外要求该值 > 0,
所以把天数设为 0 的本意「立即删除」不会生效,反而变成永不删除。
⚠️ 用 Calendar.DAY_OF_YEAR(年内第几天,1–366)而非时间戳比较,
跨年时 365 → 1 会被判为「换了一天」,这是期望行为;
但它不区分不同年份,因此判定实际是「自然日变化」而非「经过 24 小时」。
相关条目
- Resident -
res.tick()的目标 - MyTownUniverse -
towns/residents列表 - AdminTown - 被跳过欠费检查
- Bank -
payUpkeep()/getDaysNotPaid() - Config - 费用与删除天数