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)

  1. ev.side == Side.CLIENT → 立即 return(纯服务端逻辑)。
  2. 每 tick 遍历 MyTownUniverse.instance.residents,逐个 res.tick()。
  3. 仅当 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 小时」。

相关条目