All Mods Resource Packs Data Packs Shaders Modpacks Plugins
Touhou Maid: Affection

Touhou Maid: Affection

by Unknown • Downloads: 0 • Followers: 0
Description
Gallery
Changelog
Versions

Kiss your maid!

Touhou Maid: Affection

Bring affectionate interactions, bond progression, and lasting companionship to Touhou Little Maid.

中文

MC 1.20.1 Forge Java 17 Touhou Little Maid MIT


Overview

Touhou Maid: Affection is an affection and bond companion expansion for Touhou Little Maid (TLM).

Express your love through affectionate interactions, raise favorability by kissing, and unlock an exclusive Bond System as your relationship deepens. Bond abilities include relaxing Lap Pillows, personalized Morning Kisses, Emergency Rescues in fatal situations, and thoughtful Random Gifts. The mod also integrates with TLM's native AI chat and TTS speech system, alongside full datapack support for custom dialogue and voice lines.

Core Mechanics

Kiss Interaction

  • Keybind Actions: Aim your crosshair at your maid and press the kiss key. When carrying your maid using a saddle, use the dedicated carried kiss key to interact directly.
  • Visual & Audio Feedback: Each kiss brings heart particles, playful sound effects, and a brief close-up camera zoom.
  • Favorability Progression: Kissing steadily increases maid favorability. Higher favorability levels grant shorter kiss cooldowns.
  • Maid's Prayer: Rapid consecutive kisses reward both player and maid with the "Maid's Prayer" regeneration buff.

Bond System

When a maid reaches Favorability Level 3 (Max), the Bond Tab unlocks at the top of her inventory GUI. Players can spend P-Points (PowerPoint items in inventory) to unlock unique bond abilities:

Bond Ability Description
Lap Pillow Rest together sitting or lying down. Supports adjustable offsets, camera lock, and YSM custom animations.
Morning Kiss Scheduled morning greeting upon waking. The maid approaches with a morning kiss, custom lines, and voice playback.
Emergency Rescue When you suffer fatal damage, bonded maids rush in to shield you and restore emergency health with unique rescue lines.
Random Gift Bonded maids gather and present thoughtful gifts over time, with progress tracked directly in the GUI.

AI Morning Kiss & Bilingual Voice System

Morning Kiss can leverage Touhou Little Maid's configured AI chat and TTS providers to pre-generate morning greetings in the background.

  • Bilingual Combinations: Display text and spoken voice languages are completely decoupled, supporting combinations like English text with Japanese voice.
  • Auto Matching: Defaults to auto, where text matches your Minecraft language and voice inherits the maid's TLM AI voice settings.
  • Unified Management: Directly uses your existing TLM AI providers and API keys without redundant setup.

How to Use

Keybindings

Configure the following keys under Options → Controls → Key Binds:

  • Targeted Kiss: Kiss the maid in your crosshair.
  • Carried Maid Kiss: Kiss while carrying a maid with a saddle.
  • Lap Pillow: Trigger the lap pillow rest pose.
  • Lock View Angle: Lock the camera angle during a lap pillow session.

In-Game Settings Panel

Click the gear beside Bond Abilities, inside the panel header, to open settings:

  • Status: Monitoring is grouped by Random Gift and AI Morning Kiss. Select a maid in the gift section; AI switches, languages, and cache statistics form subsections.
  • Features: Toggle bond abilities, adjust AI cache policy, and choose the gift pool, preparation interval, and queue limit.
  • Voice: Switch display/voice languages, edit the Morning Kiss prompt template live, or jump directly to TLM's AI provider settings.
  • Volume: Adjust volume sliders in real-time for kiss sounds, morning kiss voices, rescue lines, and voice previews.

If an upgraded save produces a narrow selection of gifts, turn off Features → Gift preparation → Tag-only pool to select the broad pool. Existing configurations retain their saved choice. The Status tab displays server snapshots; use Refresh to update them. Delivery also depends on distance and cooldown after a gift is prepared. Hover and scroll over the contents row to inspect longer item lists.

Admin Commands

All data and settings follow server-authoritative validation. Operators (Permission Level 2) can manage features via /tma:

/tma morning_kiss status                       # View morning kiss status and AI cache stats
/tma morning_kiss clear_ai_cache [all|maid...]  # Clear generated dialogue and voice cache
/tma rescue on|off|toggle                      # Enable or disable emergency rescue server-wide
/tma bond prune [days]                         # Clean up bond data for maids inactive over N days (default: 90)

Custom Datapack Voices

Expand dialogue pools and .ogg voice lines via Datapacks:

Important Notes

  • Server Authority: Favorability growth, cooldowns, line-of-sight checks, and ability activation are fully validated by the server. Singleplayer and multiplayer servers share identical behavior.
  • Volume Attenuation: In-game volume sliders control client-side attenuation (0.0 for mute, 1.0 for full volume). Increase master/system volume for higher output.
  • Permissions: On dedicated servers, global toggles, language rules, and prompt templates are operator-only. Non-op players view the settings panel in read-only mode.
  • Data Persistence: Maid bond data is safely preserved across maid deaths, chunk unloads, or dimensional transfers. Use /tma bond prune to purge abandoned data.

Miscellaneous & Compatibility

Mod Integrations

  • Touhou Little Maid (TLM): Required core dependency (built against 1.5.3-forge+mc1.20.1).
  • MaidFileManager: Seamlessly carries bond levels, unlocked abilities, and voice settings across .maid file migrations.
  • Epic Fight: Compatible with [史诗战斗:车万女仆] bridge & Epic Fight - Avalon; bond tab automatically avoids GUI tab collisions.
  • Yes Steve Model (YSM): Supports custom animation sync during lap pillows.
  • Tweakerge / Tweakeroo: Fully compatible with Free Camera mode without causing player pose conflicts.

Installation

  1. Install Minecraft 1.20.1 and Forge 47.4.x.
  2. Install Touhou Little Maid for Forge 1.20.1 (1.5.0+).
  3. Place touhou-maid-affection-1.7.5.2.jar into your .minecraft/mods directory.
  4. Launch the game.

Developer & Architecture Docs

License

This project is open-source under the MIT License.

All Versions

+ Add Version
Name Game version Platforms Published Downloads Actions
1.20.1
Forge
1d ago 1
1.21.1
Neoforge
1d ago 1
1.20.1
Forge
1d ago 1
1.21.1
Neoforge
1d ago 1
1.20.1
Forge
1d ago 1
1.21.1
Neoforge
1d ago 1
1.21.1
Neoforge
1d ago 1
1.20.1
Forge
1d ago 1
1.21.1
Neoforge
1d ago 1
1.20.1
Forge
1d ago 1
1.21.1
Neoforge
1d ago 1
1.20.1
Forge
1d ago 1
1.21.1
Neoforge
1d ago 1
1.20.1
Forge
1d ago 1
1.21.1
Neoforge
1d ago 1
1.20.1
Forge
1d ago 1
1.21.1
Neoforge
1d ago 1
1.21.1
Neoforge
1d ago 1
1.20.1
Forge
1d ago 1
1.21.1
Neoforge
1d ago 1
1.20.1
Forge
1d ago 1
1.21.1
Neoforge
1d ago 1
1.20.1
Forge
1d ago 1
1.21.1
Neoforge
1d ago 1
1.21.1
Neoforge
1d ago 1
1.21.1
Neoforge
1d ago 1
1.21.1
Neoforge
1d ago 1
1.21.x
Neoforge
1d ago 1
1.21.x
Neoforge
1d ago 1
## [1.7.5.2] - 2026-10-01

### Fixed
  • 随机礼物的新配置默认恢复广泛物品池。旧配置的 curatedPoolOnly 选择保留,可在「设置 → 功能 → 礼物准备」中关闭「仅标签物品池」,恢复原版与模组物品抽样。黑名单继续优先生效。
  • 模组物品每批备礼重新抽样,避免世界种子固定后长期只从同一小批物品中选择。
  • 礼物详情读取保持只读;查询膝枕等待条件时也保持玩家存档不变。

### Added
  • 全局设置「状态」tab 顶部新增女仆下拉框与固定礼物详情区:查看选中女仆的积攒份数、已准备物品、下一份准备时间、上次送礼记录和等待条件。刷新保留女仆选择,多个网络分页中的女仆均可选择;物品列表较长时可在悬浮提示内滚动。设置页保持原有四个 tab。
  • 「功能」tab 新增礼物池模式、模组物品开关、准备间隔与队列上限,沿用管理员权限校验。
  • 礼物在备好时确定并保存物品,送出时按队列取用。旧存档积攒份数保留,降低队列上限保留已积攒礼物,已准备物品支持随 .maid 导出导入;上次送礼记录保留在原存档。
  • 新增整合包作者教程 [PACK_AUTHORING.md](PACK_AUTHORING.md),说明如何通过数据包定制现有内容,并提供可直接参考的示例与排障指引。

### Changed
  • 设置入口移到「羁绊能力」标题右侧,以边框内的齿轮图标显示;渲染、提示和点击范围保持一致,避开 TLM 顶部页签。
  • 状态页按「随机礼物」「AI 早安吻」两个同级功能分区;女仆选择、开关、语种、缓存与具体数据采用下级缩进和留白。
  • 羁绊面板与二级页的较长文字按可用空间适配缩放,按钮文字限制在按钮宽度内,减少溢出与重叠。

### Notes
  • 界面继续使用 Minecraft 默认字体,保留原有面板背景与整体风格。
  • 准星亲吻与抱起亲吻继续使用自定义按键,Shift+右键仍保留 TLM 原生交互。
[1.7.5.2] v1.7.5.2 by Unknown on Oct 18, 2026
Download
## [1.7.5.2] - 2026-10-01

### Fixed
  • 随机礼物的新配置默认恢复广泛物品池。旧配置的 curatedPoolOnly 选择保留,可在「设置 → 功能 → 礼物准备」中关闭「仅标签物品池」,恢复原版与模组物品抽样。黑名单继续优先生效。
  • 模组物品每批备礼重新抽样,避免世界种子固定后长期只从同一小批物品中选择。
  • 礼物详情读取保持只读;查询膝枕等待条件时也保持玩家存档不变。

### Added
  • 全局设置「状态」tab 顶部新增女仆下拉框与固定礼物详情区:查看选中女仆的积攒份数、已准备物品、下一份准备时间、上次送礼记录和等待条件。刷新保留女仆选择,多个网络分页中的女仆均可选择;物品列表较长时可在悬浮提示内滚动。设置页保持原有四个 tab。
  • 「功能」tab 新增礼物池模式、模组物品开关、准备间隔与队列上限,沿用管理员权限校验。
  • 礼物在备好时确定并保存物品,送出时按队列取用。旧存档积攒份数保留,降低队列上限保留已积攒礼物,已准备物品支持随 .maid 导出导入;上次送礼记录保留在原存档。
  • 新增整合包作者教程 PACK_AUTHORING.md,说明礼物标签数据包、服务端配置、台词与语音资源包的制作方式、覆盖规则及当前定制边界。

### Changed
  • 改善较窄界面中的文字适配缩放及按钮宽度约束,保留原有羁绊面板、二级页和设置背景。
  • 设置入口移到「羁绊能力」标题右侧,使用边框内的 12px 齿轮图标,渲染、提示和点击共用同一矩形,避开 TLM 顶部页签。
  • 状态页按「随机礼物」「AI 早安吻」两个同级功能分区;女仆选择、开关、语种、缓存与具体数据采用下级缩进和留白。
  • 界面继续使用 Minecraft 默认字体,不内封或替换字体。


### Notes
  • 准星亲吻与抱起亲吻继续使用自定义按键。本轮保持 Shift+右键的 TLM 原生交互。
## [1.7.5.1] - 2026-09-25

### Fixed
  • 修复与 Tweakeroo / Tweakerge 自由视角(“灵魂出窍”)在膝枕平躺态下同时使用时的客户端崩溃(issue #7,LocalPlayer.canAutoJump 对 null input 的 NPE):Tweakeroo 的自由摄像机是一个复制了本地玩家 UUID、但 input 为 null 的假 LocalPlayer。膝枕平躺桥接此前以 **UUID 相等** 判定目标玩家,因而也命中了这个摄像机实体,强行让它 onGround() 返回 true;当玩家开启原版“自动跳跃”时,canAutoJump() 越过“在地面”判定继续走到 hasEnoughImpulseToStartSprinting() → this.input.getMoveVector(),对 null input 解引用即崩溃。改为 **实例相等**(player == Minecraft.getInstance().player),平躺桥接只作用于真正的本地玩家;Tweakeroo 摄像机、Replay Mod 摄像机等共享 UUID 的副本实体不再被误伤。
  • 修复与史诗战斗(Epic Fight)等同样往女仆界面顶部加页签的模组同装时,羁绊页签与对方页签重叠、点击无响应(issue #8):附属页签的注册监听器执行顺序不确定,两个模组会各自把页签放到“内建页签之后的第一个槽位”而落到同一坐标。现在在界面 init 完成后(此时所有模组的页签都已是实际控件)复查一次,**仅当** 羁绊页签确实与顶部同排的其他控件重叠时,才把它移到该排第一个空槽(25px 网格);单附属的常见布局保持不变。
[1.7.5.1] v1.7.5.1 by Unknown on Oct 18, 2026
Download
## [1.7.5.1] - 2026-09-25

### Fixed
  • 修复与 Tweakeroo / Tweakerge 自由视角(“灵魂出窍”)在膝枕平躺态下同时使用时的客户端崩溃(issue #7,LocalPlayer.canAutoJump 对 null input 的 NPE):Tweakeroo 的自由摄像机是一个复制了本地玩家 UUID、但 input 为 null 的假 LocalPlayer。膝枕平躺桥接此前以 **UUID 相等** 判定目标玩家,因而也命中了这个摄像机实体,强行让它 onGround() 返回 true;当玩家开启原版“自动跳跃”时,canAutoJump() 越过“在地面”判定继续走到 hasEnoughImpulseToStartSprinting() → this.input.getMoveVector(),对 null input 解引用即崩溃。改为 **实例相等**(player == Minecraft.getInstance().player),平躺桥接只作用于真正的本地玩家;Tweakeroo 摄像机、Replay Mod 摄像机等共享 UUID 的副本实体不再被误伤。
  • 修复与史诗战斗(Epic Fight)等同样往女仆界面顶部加页签的模组同装时,羁绊页签与对方页签重叠、点击无响应(issue #8):附属页签的注册监听器执行顺序不确定,两个模组会各自把页签放到“内建页签之后的第一个槽位”而落到同一坐标。现在在界面 init 完成后(此时所有模组的页签都已是实际控件)复查一次,**仅当** 羁绊页签确实与顶部同排的其他控件重叠时,才把它移到该排第一个空槽(25px 网格);单附属的常见布局保持不变。
Release v1.7.5.0-forge1.20.1. See CHANGELOG.md in the repository.
[1.7.5.0] v1.7.5.0 by Unknown on Oct 18, 2026
Download
## [1.7.5.0] - 2026-09-25

### Added
  • 设置面板「功能」tab 末尾新增「缓存策略」区(bond.settings.section.cache_policy):每池目标条数 / 扫描间隔 两个整数(复用紧凑数值控件 BondNumberField)与 消费即用 胶囊开关,全部走既有服务端权威通道(OP2 + [TMA Settings] 审计 + 状态回推 + pending 状态点,不新造视觉)。为此新增 4 个白名单键——morning_kiss.immediate_fallback_enabled(映射 ModConfig.BOND_MORNING_KISS_AI_DIALOGUE_IMMEDIATE_FALLBACK_ENABLED)、morning_kiss.cache_target_per_pool、morning_kiss.cache_scan_interval_ticks、morning_kiss.cache_consume_on_use(映射 ModConfig.BOND_MORNING_KISS_AI_DIALOGUE_CACHE_CONSUME_ON_USE),白名单从 **10 项扩到 14 项**(9 开关 + 2 语种 + 1 文本 + 2 整数)。TmaSettingsKeys 新增取值类型 Type.INT:只接受纯数字,逐键按 ModConfig defineInRange 的上下界校验(每池目标条数 1..8、扫描间隔 20..72000 tick),非数字/越界一律拒绝,并沿用既有的整包拒绝语义。morning_kiss.cache_consume_on_use 已从「功能」tab 的通用布尔列表里排除(TOGGLE_KEYS 过滤),「消费即用」在整个面板里**只出现一次**(就在缓存策略区内)。
  • 新增紧凑数值输入控件 BondNumberField(单行原版 EditBox,关闭原版边框、复用面板字段式配色;只允许数字、失焦提交、提交前按范围夹取、右侧显示单位如 1200t)。范围跨度 20..72000 用滑块精度不可用,因此不做滑块。
  • 新增中英 lang 键:bond.settings.section.cache_policy、bond.settings.key.morning_kiss.cache_target_per_pool / bond.settings.sub.morning_kiss.cache_target_per_pool、bond.settings.key.morning_kiss.cache_scan_interval_ticks / bond.settings.sub.morning_kiss.cache_scan_interval_ticks、bond.settings.status.pool.general(通用 / Any)、bond.settings.key.morning_kiss.immediate_fallback_enabled 与 bond.settings.sub.morning_kiss.immediate_fallback_enabled、bond.settings.key.morning_kiss.cache_consume_on_use 与 bond.settings.sub.morning_kiss.cache_consume_on_use、bond.settings.number.tip,以及状态页恢复只读后重新引用的 bond.settings.status.language.auto.display / bond.settings.status.language.auto.voice。
  • 新增游戏内「全局设置」面板「语音」tab 的「台词提示词」多行编辑框:直接编辑早安吻 AI 台词模板(占位符 {maid} 女仆名 / {player} 玩家名 / {pool} 时段 / {time} 允许时段),带占位符图例与「恢复默认」按钮。这是服务端权威的新设置类型 TEXT(逻辑键 morning_kiss.text_prompt,上限 1024 字符,保存空值写回内置默认模板),沿用现有 OP2 + 审计日志的写入路径。字数计数画在编辑框**内部右下角**(次要文字色),占位符图例独占编辑框下方一整行、占满内容区整宽(完整显示、不再截断),「恢复默认」按钮移到编辑框上方标签行右对齐,「恢复默认」改用面板通用的文字按钮渲染(与「打开」「清空」同一个 drawTextButton 模板,无权限时置灰)。编辑框本身支持**框内滚动**:新增子类 BondPromptBox 把滚动步长(scrollRate() = 9px)与滚动上限(9 × (总行数 − 可见行数))都吸附到文本行网格,编辑框高度取 9 × 行数 + 4(49px = 5 行 + 内边距),因此文字永远按整行显示、不会从行中间被切断;鼠标在框内滚轮只滚框内文本、不再带动面板,光标移出可视区时由原版光标监听自动滚动保持可见。
  • 新增设置面板「状态」tab:移植 /tma morning_kiss status 与 /tma morning_kiss cache 的信息,**全部只读**——开关(早安吻 / AI 台词 / AI 语音 / 立即兜底)、语种(文本语种 / 配音语种,未配置显示 auto(跟随游戏语言) / auto(跟随女仆 AI 设置))、缓存策略(每池目标 / 扫描间隔 / 消费即用)都用纯文本行渲染(没有胶囊开关 / 下拉框 / 数值框 / pending 状态点),缓存统计(条目语音/纯文本、女仆数 / 在途 / 版本号)与按女仆列表(名字 + 各时段池条目数 + 总条目/目标 + 行内「清空」)同样只读。配套新增只读状态通道 TmaAiStatusRequestPayload / TmaAiStatusPayload 与清缓存操作包 TmaAiCacheClearPayload:状态只回该玩家名下的女仆,清缓存需 OP2 + 审计日志并复用 /tma morning_kiss clear_ai_cache 完全相同的服务方法。
  • 新增设置面板「语音」tab 的「打开车万女仆的 AI 设置」按钮:跳转 TLM 原生 AIChatSettingsHubScreen(parent 传本面板,关闭后回到这里),是全局唯一的 AI 入口;TMA 不自建站点表单。
  • 新增游戏内「全局设置」面板:在羁绊页顶部右侧(原 TMA AI Hub 按钮的槽位)新增「设置」入口,面板与当前女仆无关,分四个 tab——状态(只读)、功能开关(早安吻 / 女仆主动早安吻 / AI 台词 / AI 语音 / 立即兜底 / 残血救护 / 随机礼物 / 少女祈祷 Buff,末尾是「缓存策略」区:每池目标条数 / 扫描间隔 / 消费即用)、语音(文本语种 / 配音语种下拉框 + 台词提示词 + AI 站点入口)、音量(亲吻音效 / 早安吻语音 / 残血救护 / 语音试听,0.0–1.0 步进 0.05)。无需再手改 toml。
  • 新增服务端权威设置同步通道:TmaSettingsRequestPayload(C2S,空列表表示只读状态)与 TmaSettingsStatePayload(S2C,回推全部白名单键的当前值与 canEdit)。面板里的开关与语种由服务端校验、应用并回推,单人存档与多人服务器行为一致。
  • 新增自绘滑块组件 BondSlider,供设置面板的音量项使用。

### Fixed
  • 修复设置面板下拉弹层被下层控件文字穿透(「恢复默认」浮在展开的列表之上):根因是 GuiGraphics 把填充与文字分入不同 render type 缓冲、同帧按创建顺序刷出(填充先、文字后),于是先画的文字会盖住后画的填充。修法:画弹层前 graphics.flush() 先把此前的填充+文字落地、弹层底色改为不透明,并在弹层矩形**确实覆盖**某控件时跳过绘制该控件(BondDropdown#overlayCovers 判定,未覆盖时控件照常显示)。
  • 修复「状态」tab「按女仆」行的池计数渲染成原始 key bond.settings.status.pool.general:lang 文件缺 GENERAL 池的键,现已补齐中英两语言;并新增回归测试 TmaSettingsLangKeysTest,逐一遍历 DialoguePool 的全部取值断言中英 lang 都存在 bond.settings.status.pool.<小写枚举名>,同时断言每个可编辑键的 bond.settings.key.* / bond.settings.sub.* 与状态页相关键存在(缺键时直接测试失败,而不是等到界面上露出原始 key)。
  • 修复「状态」tab 行内文本压到「清空」按钮下面的问题:只读值行与女仆行一律在「控件左边界 − 间距」处用 clip(...) 截断并补省略号(女仆行拆成名字列 + 右对齐的计数列),长值(24 (18 / 6)、3 / 1 / 42、早 9 · 晚 9 · 通用 0 · 18/12)不再与控件重叠。
  • 修复「语音」tab 占位符图例被截断(原可用宽度仅 218px,中英文案分别需 309px / 348px):图例改为独占一整行、使用内容区整宽 270px,文案缩短为 {maid} 女仆 · {player} 玩家 · {pool} 时段 · {time} 允许时段(260px)与 {maid} maid · {player} player · {pool} pool · {time} range(261px),中英双语都完整显示;「恢复默认」按钮移到上方标签行右对齐。
  • 修复设置面板语种下拉框最后一项被裁剪的问题:展开的弹层不再受面板内容区 scissor 约束,改为夹在屏幕范围内——向下会溢出屏幕底部时翻到表头之上渲染,命中测试/高亮/点击与实际渲染位置保持一致,所有候选条目可达。
  • .maid 迁移不再携带运行态/调度键:导出(BondData.exportMaidData)剔除 BondKeys.RUNTIME_KEYS——礼物计时(RandomGiftLastWallClock / RandomGiftLastDelivery / RandomGiftLastIntervalMinutes)、早安吻窗口标记(MorningKissScheduledWindow / MorningKissScheduledAttemptTick / MorningKissLastAutoAttemptGameTime / MorningKissLastSuccessWindow / MorningKissLastFailedWindow)与本地记账 LastSeen——导入时再防御性剔一遍。此前这些会话/世界相关的绝对时间会随 .maid 迁到新女仆/新存档,导致刚导入就被判定「今天已亲过」或礼物计时错乱。待发礼物队列 RandomGiftQueue 是耐久状态,仍然随迁;extras 对外形状与整体替换语义不变。
  • 空字符串不再落盘/导出:所有「getter 缺省值本就是空串」的字符串 setter(声音包、YSM 档案、救护动作、膝枕动作、早安吻计划/窗口标记、玩家粒度早安吻选择、早安吻与救护语音选择里的空字段)改为空串时移除键而非写入空值,避免无意义键堆积进存档与 .maid。

### Changed
  • 设置面板改为**单张整页底图 + 控件叠加**:外框、表头分隔线、侧栏分隔线、footer 分隔线与左下角写实玫瑰全部烘进 textures/gui/settings_panel.png(1020×690 RGBA,已烘入 0.90 不透明度),面板背景改为一次 blit(按面板 340×230 逻辑尺寸在 GUI scale 3 下 1:1,不缩放、不额外着色),代码不再自绘面板底色 / 边框 / 分隔线;屏幕压暗层、tab 高亮、所有控件与配色 token、footer 按钮保持不变。为对齐底图,BondGuiTokens.MODAL_TITLE_HEIGHT 24→20(表头分隔线落在面板高的 20/230)、NAV_WIDTH 46→50(侧栏分隔线落在面板宽的 50/340),因此内容可视高 168→172px、内容区宽 274→270px(占位符图例 260px / 261px 仍不截断),各 tab 的 maxScroll 随可视高自动收敛。
  • 「状态」tab「按女仆」列表对同名女仆去歧义:名字列新增纯逻辑助手 bond/settings/TmaMaidLabels,输入该玩家的女仆 (uuid, 名字) 列表输出显示标签——名字唯一时原样显示(不加噪声),同名出现 ≥2 次时这些行追加 # + UUID 前 4 位十六进制(小写),如 精灵酒狐 #a1b2;名字为空/空白回退为可本地化的占位名(新增 lang 键 bond.settings.status.maid.unknown,zh 未知女仆 / en Unknown maid,由 TmaSettingsScreen 传入 Component.translatable(...).getString()),并追加短 ID,如 未知女仆 #a1b2。名字列仍按原有 clip(...) 规则截断到可用宽度,不挤占行内「清空」按钮。配套单测 TmaMaidLabelsTest,TmaSettingsLangKeysTest 一并守护该新键。
  • 设置面板间距放宽(用户反馈「配置页间距太挤」):SECTION_HEADER_HEIGHT 12→15、ROW_GAP 3→6、LANGUAGE_ROW_HEIGHT 17→20、PROMPT_BOX_HEIGHT 36→49(= 9 × 5 行 + 内边距)、PROMPT_ROW_HEIGHT 12→14、STATUS_KV_HEIGHT 12→13、STATUS_ROW_GAP 2→6。上一轮的「语音 tab 打开即免滚动」要求随之作废:功能(294px)/ 语音(208px)/ 状态三个 tab 超出内容可视高 172px(230 模态高 − 20 标题 − 8 内容上留白 − 30 footer)时一律走面板内部滚动。占位符图例仍独占一整行、占满内容区整宽 270px(340 − 2 − 50 − 8 − 2 − 8,横向槽位不受间距常量影响),中英文案按原版字宽表复算为 260px / 261px,均 ≤ 270px、不截断。
  • 设置面板 tab 顺序改为「状态 / 功能 / 语音 / 音量」:「状态」提到第一位并作为打开面板的默认选中项(activeTab 默认 0、tabLabel、导航命中测试与文档同步),状态 tab 请求 AI 状态改在 init() 里发起;「缓存策略」三个控件从状态页搬到「功能」tab 末尾,状态页对应的三行改回只读纯文本。
  • 设置面板尺寸 300×188 → 340×230,侧栏 tab 从 3 个(功能 / 语音 / 音量)扩到 4 个(新增「状态」);内容超出可视区走内部滚动。配色 token、服务端权威语义与既有状态机不变。
  • 羁绊页「设置」按钮从左上空位移到面板右上角(原 TMA AI Hub 按钮的槽位):尺寸 50×12,位置 x = panelX + panelWidth - 50 - 2、y = panelY - 12 - 3(即原 AI 按钮的 Y),文案仍是「设置」、居中绘制;命中测试与 tooltip 同步更新,左上空位不再有按钮。
  • 音量上限从 4.0 收至 1.0:四项音量配置(cooldown.kissSoundVolume、morningKissBehavior.voiceVolume、emergencyRescueBehavior.volume、voicePreview.volume)与设置面板滑块现在**只做衰减**——0.0 静音、1.0 保持原有响度,不再放大。需要更大音量请使用 Minecraft 或系统音量。旧配置里大于 1.0 的值会被配置系统在加载时纠正为 1.0(Forge defineInRange 行为)。
  • 音量四项(cooldown.kissSoundVolume、morningKissBehavior.voiceVolume、emergencyRescueBehavior.volume、voicePreview.volume)是纯客户端配置,面板里拖动即写入本机配置并立即生效,不走网络。
  • 语音试听冷却从 5 秒降到 0.5 秒(100 → 10 tick);被限流时给客户端一行 action bar 提示「试听过快,请稍候」,不再静默丢弃;非数据包(本地)试听请求不再占用限流额度。
  • 早安吻 AI 台词缓存改为按语种读取:pollRandom / peekRandom 与预热满度判定(countMatching、addIfBelowTarget)都按当前解析出的显示/配音语种过滤,改了显示或配音语种后会自动按新语种重新预热,旧语种条目保留但不再被选中,也不再阻塞重新预热(仍可手动 clear_ai_cache)。目标语种为空(auto)时不过滤,保持旧行为。
  • /tma morning_kiss status 的语种行改为两行说人话:文本语种:<值>(未配置显示 auto)、配音语种:<值>(未配置显示 auto),删掉 AI 覆盖与生效优先级两行。
  • 早安吻语种语义统一为两个:**文本语种**(displayLanguage,内置数据包台词 + AI 生成台词用哪种语言显示;auto = 跟随游戏语言,内置台词按客户端语言渲染、未标记数据包台词通配、AI 台词沿用女仆的 TLM 聊天语言)与**配音语种**(voiceLanguage,数据包语音 + AI 合成语音用哪种语言;auto = 跟随女仆的 TLM AI 语言设置,数据包语音不按语言过滤、AI 合成沿用女仆的 TLM TTS 语言)。具体 locale(zh_cn / ja_jp…)固定该语言。旧关键字 tlm / inherit / default 继续接受,等价于 auto,但面板与状态页一律显示归一化后的 auto。
  • 全局羁绊 UI 配色统一为「暖木底 + 玫瑰(交互面 / 装饰)+ 金(仅高亮文字)」:BondGuiTokens 换用新调色板(保留原常量名,新增开关 / 字段 / 滑块 / 导航等语义色常量),所有调用点自动跟随。设置面板同步按设计稿收口:300×188 模态框、46px 侧栏三 tab、胶囊开关、78×20 字段式下拉、88×13 滑块(数值金色居中)、分区作用域标签、行内请求状态点与「完成 / 重载」footer。不影响功能与其它二级页布局尺寸(仍为 172×150)。
  • 设置面板从「女仆 GUI 内嵌二级页」改为**独立 Screen**(TmaSettingsScreen,删除 SettingsSecondaryPage):在羁绊页「设置」按钮处用 Minecraft#setScreen 打开,自带全屏压暗背景,关闭(footer「完成」/ESC/点击压暗区)返回来源的女仆 GUI。面板尺寸/配色/控件与交互 token 不变,服务端权威语义、payload、状态机与音量直写零变更;除设置页外的其它二级页与 BondSecondaryPage 接口不受影响。
  • 设置面板语种从 4 项砍到 2 项:白名单变为 **7 开关 + 2 语种 = 9 项**,面板只保留「文本语种」(display_language)与「配音语种」(voice_language),两者统管内置数据包与 AI 两条链路。
  • 羁绊数据改为**按女仆嵌套存储**:女仆粒度数据从「根上扁平键 <base>_<女仆UUID>」改为 touhou_maid_affection.bond.maids.<女仆UUID>.<base> 子树,玩家粒度键(早安吻选择)仍在根上;键名常量集中到 BondKeys。首次读取旧存档时自动执行**一次性迁移**(根上新增 SchemaVersion,先写后删、幂等、无法解析的键原样保留),旧存档无损升级,无需手动操作。反查(按能力找女仆、按模型 ID 找女仆、按救护 provider 找女仆、批量重置能力)改为遍历女仆子树,不再全键扫描。
  • 新增 /tma bond prune [days](默认 90 天,权限等级 2):清理执行者羁绊数据中 LastSeen 早于阈值的女仆子树(缺失 LastSeen 的历史数据视为过旧;days <= 0 只统计不删除),并回显删除/保留数量。LastSeen 在同步女仆档案时刷新;**不**在女仆死亡 / 卸载 / 换主人时自动删除数据(TLM 灵魂玩偶、椅子等会临时移除实体,自动删会丢数据),只能靠该命令显式清理。
  • .maid 迁移(MaidFileManager SPI)的附加数据对外格式**不变**:仍是「base 名 → 值」的 compound(即女仆子树本身),旧导出文件仍可导入,导入后刷新 LastSeen。
  • 删除若干零调用者死代码:BondData/BondManager.getUnlockedMaidModelIdsForAbility、BondData/BondManager.findMaidProfileByRescueProviderId、MorningKissGeneratedDialogueService.hasCachedLine(两个重载)、MorningKissGeneratedDialogueCache.isEmpty,以及已被 BondKeys 取代的 compat/maidfm/MaidDataKeyCodec。

### Removed
  • 删除独立玫瑰贴图 textures/gui/rose_vine.png 及其绘制代码:TmaSettingsScreen#renderVine、ROSE_VINE 资源常量、NAV_VINE_WIDTH / NAV_VINE_HEIGHT / NAV_VINE_TEXTURE_WIDTH / NAV_VINE_TEXTURE_HEIGHT 尺寸常量与相关 javadoc 一并移除(全仓 grep -ri rose_vine 零命中),玫瑰改由整页底图承载。
  • 删除 AI 专用语种覆盖层:ModConfig 的 morningKissBehavior.aiDialogueLanguage / aiDialogueVoiceLanguage 两项(含 toml 键 aiDialogueLanguage / aiDialogueVoiceLanguage)与解析链里的优先级逻辑(MorningKissLanguageSettings#liveChatLanguage 的「AI 显式 > 全局显式 > 旧语义」判定、resolveGeneratedTextLanguage / resolveGeneratedVoiceTextLanguage 的 AI 专用入参与配音继承显示语种的规则)。若此前用 AI 覆盖让 AI 台词/配音与内置台词/语音用了不同语言,现在统一由**文本语种**与**配音语种**控制——把原来的值填到这两项即可(例:原来 aiDialogueLanguage=zh_cn + aiDialogueVoiceLanguage=ja_jp,现在填 displayLanguage=zh_cn + voiceLanguage=ja_jp)。旧 toml 里残留的这两个键不再被定义,配置系统直接忽略,无需手动清理。
  • 删除 TMA 自研的 AI 站点适配层:com.github.touhoumaidaffection.ai.mimo 整包(TmaMimoAdapterExtension provider 注册、MimoLLMSite / MimoTTSSite 站点类型与 serializer、MimoTTSFormLayout 站点表单、MimoLLMClient / MimoTTSClient / MimoHttp / MimoProtocol / MimoCodecHelper 协议实现、BoundedHttpClient / BoundedHttpResponse 有界响应工具)及其单元测试(MimoProtocolTest 7 例、BoundedHttpResponseTest 3 例)。
  • 删除 ModConfig 的 tmaMimoAdapter 配置段:enabled / apiKey / chatUrl / ttsUrl / maxCompletionTokens / ttsVoicePrompt / ttsAudioFormat 七项。旧 toml 里残留的 [tmaMimoAdapter] 键不再被定义,配置系统会直接忽略,**无需手动清理,也没有迁移代码**。
  • 删除中英文文案中的 MiMo 站点名与入口文案(各 6 个键)。
  • 羁绊页顶部不再有任何 AI 入口:原右上角「TMA AI Hub」按钮整条删除(含字段、渲染、命中测试、tooltip、BondPrimaryPageHost#openMimoAdapterSettings / isMimoAdapterAvailable 及其实现与 TLM AI hub 跳转)。AI 相关配置今后由 TMA 自己的设置面板承担。
  • 早安吻的 LLM/TTS 本就完全走 maid.getAiChatManager() 里 TLM 自己的站点,删除适配层不影响任何功能;TMA 也不再提供全局音色提示词(音色由 TLM 站点配置决定,GPT-SoVITS 站点另有其原生 prompt 字段)。
  • 旧站点条目处理:TLM 读取 config/touhou_little_maid/sites/{llm,tts}.json 时,api_type 找不到对应 serializer 的条目只记一条 error 日志并跳过(**不抛异常、不崩溃**),随后 TLM 保存站点时把该条目从文件里清掉。**实测**:删掉适配层后启动服务器,日志出现 Unknown LLM site type: tma_mimo_chat 与 Unknown TTS site type: tma_mimo_tts,服务器正常完成启动,且 tma_mimo_chat / tma_mimo_tts 两个条目已从两个 json 中消失——玩家无需手动删旧站点条目。

### Notes
  • MaidFileManager **1.4.0 已正式发布**(GitHub Releases,fabric/forge/neoforge 四产物):官方 SPI 与我们所 vendored 的版本**逐字节一致**,集成无需改动;官方把 .maid 格式版本从 5 升到 6,但迁移只作用于女仆实体 NBT,extras(我们的羁绊数据)不受影响,旧 v5 导出文件仍可导入。两实例已把自建 1.4.0 换成官方产物。
  • 权限:开关、语种与缓存策略属于服务端权威设置,**只有 OP(权限等级 2)可以修改**;普通玩家能看、不能改,界面底部会显示「只读」提示,按钮 tooltip 提示需要管理员权限。每次成功修改都会在服务端日志打印 [TMA Settings] player=... key=... old=... new=...;越权或非法请求打印 WARN。
  • 非法请求(未知 key、非法布尔、非法语种、超长值)整包拒绝,不会部分生效。
  • 语种下拉框只提供 auto 与常见 locale,当前值若不在列表里会动态补上;旧关键字 tlm / inherit / default 仍是合法值(服务端原样存储、语义等价 auto),但面板与状态页显示归一化后的 auto,不再作为候选条目出现。

## [1.7.4.0] - 2026-09-24

### Added
  • 新增 morningKissBehavior.displayLanguage(默认 auto)与 morningKissBehavior.voiceLanguage(默认 auto),把原先只存在于 AI 链路的「显示语种 / 配音语种」解耦提升为全局可配,并让数据包链路同样支持按语种选择台词与语音。
  • 数据包 data/touhou_maid_affection/morning_kiss/profile.json 纯增量扩展:dialogue.<pool> 元素接受 {"text": "...", "language": "zh_cn"},voice_files 元素接受 {"file": "x.ogg", "language": "ja_jp", "text": "可选字幕", "text_language": "zh_cn"};旧的纯字符串写法保留并视为「未标记」通配,向后兼容。
  • voice_files[].text / text_language 支持语音与字幕配对:选中该语音时直接显示配对字幕,不再随机抽台词;text_language 与目标显示语种不一致时退回随机台词。

### Changed
  • 语言解析优先级统一为「AI 专用显式 locale > 全局显式 locale > 旧语义(tlm / inherit / auto)」;tlm/inherit/auto 语义与翻译、缓存机制保持不变。旧配置项名字与默认值不变。
  • 数据包台词与语音选择新增语种优先级:匹配目标语种的条目 → 未标记条目 → 全部条目。dialogue_mode=append 时内置台词按「语言 = 客户端语言」参与同一筛选。
  • auto(默认值)下行为与 1.7.3.0 完全一致:不启用任何语种筛选。

### Notes
  • 内置台词仍是 i18n key,由客户端按自身语言渲染,服务端无法指定渲染语种;TLM 音包没有语言元数据,天然单语种,不参与筛选。

## [1.7.3.0] - 2026-07-24

### Added
  • 新增 cooldown.kissSoundVolume 配置项,可在 0.0 到 4.0 之间调整普通亲吻与早安吻复用亲吻音效的音量;0.0 可静音,1.0 保持旧版默认响度。
  • 新增 morningKissBehavior.voiceVolume、emergencyRescueBehavior.volume 与 voicePreview.volume 配置项,分别控制早安吻语音、残血救护语音/兜底音效和羁绊页语音试听音量。
  • 新增 morningKissBehavior.aiDialogueVoiceLanguage,可将 AI 早安吻的显示文本与配音文本设为不同语言;例如 aiDialogueLanguage=zh_cn、aiDialogueVoiceLanguage=ja_jp 会显示中文台词,并先翻译为日文后请求 TTS。
  • 新增 randomGiftBehavior.curatedPoolOnly,默认只从 touhou_maid_affection:bond_random_gift_pool 物品标签抽取礼物;可通过 bond_random_gift_blacklist 继续追加黑名单。
  • 新增可选的残血救护最大生命百分比阈值配置;启用后按最大生命的 20% 触发,在原版 20 点生命下仍等于旧版 4 点阈值。为兼容旧服自定义配置,该模式默认关闭。
  • 接入 MaidFileManager(女仆档案管理器)迁移 SPI:导出 .maid 时携带该女仆的羁绊数据(羁绊等级、能力解锁、语音池与播放模式、膝枕姿态、随机礼物队列与计时、早安吻计划/窗口、救援动作与提供者 id 等),导入到新存档/新版本时按新 UUID 自动还原;未安装管理器时静默不生效。

### Changed
  • 休闲膝枕按键默认改为未绑定,仍可在 Minecraft 控制设置中自行绑定,避免默认占用常见的 B 键。
  • 羁绊页中的休闲膝枕触发提示与能力描述改为显示当前实际绑定按键,不再固定显示 B。
  • 随机礼物默认不再遍历几乎全部物品注册表;显式标签池成为默认来源,旧的广泛抽样模式仍可通过配置恢复。
  • 羁绊解锁提示现在显示背包中的 P 点物品数量,并明确其不是神社庭灯存储的 P 点数值;点击不可用按钮时会显示失败原因。
  • 早安吻调度、对话来源与语音池策略拆分为独立模块;客户端内存语音统一复用格式检测、异步解码和实体跟随实现,减少不同播放入口之间的行为漂移。

### Fixed
  • 拒绝膝枕姿态中的 NaN/无限坐标,避免无效网络数据污染玩家存档和实体姿态。
  • 对持久化 AI 早安吻语音执行 2 MiB 单文件上限并隔离可变字节数组,避免异常 TTS 或手工缓存文件造成内存放大与缓存篡改。
  • 拒绝膝枕角度锁中的非有限旋转值,并在启动与持续执行期间复核女仆当前所有权。
  • 数据包语音改为有界流式读取,并在构造资源位置前过滤非法大小写、空格和路径字符,避免资源重载期间的过量分配或中断。
  • 限制客户端可控语音配置和动作标识的持久化长度,并为数据包语音试听增加每玩家 100 tick 冷却和请求字段上限,避免玩家 NBT 超限和小请求放大为连续大响应。
  • 旧版广泛随机礼物模式仅默认排除屏障、命令方块、结构方块、调试棒等破坏沉浸感的技术/管理物品;基岩与刷怪蛋仍可正常出现。显式礼物池标签可覆盖默认排除规则。
  • MiMo Chat 与 TTS 响应改为有界流式接收:聊天响应上限 1 MiB、TTS JSON 响应上限 4 MiB、解码后音频上限 2 MiB;远端错误正文只保留 512 字符摘要,避免异常响应造成内存和日志放大。

### Removed
  • 移除潜行空手右击女仆的亲吻入口及其 cooldown.rightClickKissEnabled 配置,避免永久占用 TLM 坐下/站起交互;亲吻改用准星目标或公主抱专用按键。
feat: custom kiss sound effects 7 random kiss sounds replace vanilla placeholder
<h1 align="center">💋 Maid Affection — 女仆亲亲</h1>

<p align="center">
<b>Kiss your Touhou Little Maid. Because she deserves it.</b><br/>
<i>亲亲你的女仆吧,她值得。</i>
</p>

<p align="center">
<img src="https://img.shields.io/badge/Minecraft-1.21.1-green?style=flat-square" alt="MC 1.21.1"/>
<img src="https://img.shields.io/badge/NeoForge-21.1.x-orange?style=flat-square" alt="NeoForge"/>
<img src="https://img.shields.io/badge/Requires-Touhou_Little_Maid_1.5.0+-blue?style=flat-square" alt="TLM"/>
<img src="https://img.shields.io/badge/License-MIT-yellow?style=flat-square" alt="MIT"/>
</p>


## ✨ 功能特性

| 特性 | 描述 |
| ------------------------ | -------------------------------------------- |
| 💋**亲吻互动** | 潜行 + 空手右击你的女仆,触发亲吻 |
| 💕**爱心粒子** | 亲吻时在两人之间生成浪漫的爱心粒子效果 |
| 🔊**亲吻音效** | 播放清脆的亲吻音效 |
| 📈**好感度提升** | 每次亲吻为女仆增加**+3 好感度**(30 秒冷却) |
| 👀**女仆凝视** | 亲吻时女仆会转头看向你 |
| ⏱️**防刷屏** | 2 秒交互冷却,防止粒子刷屏 |
| 📦**CarryOn 兼容** | 自动检测 CarryOn 模组,智能避免操作冲突 |
| 🧲**副手吸引** | 副手持有诱惑物品(默认蛋糕)也能吸引女仆过来 |

## 🎮 触发条件

### 默认(无 CarryOn)

``
潜行(Shift)+ 空手 + 右击你的女仆
`

### 安装了 CarryOn 时

由于 CarryOn 使用「潜行 + 双手空 + 右击」来搬起实体,本模组会自动调整触发方式以避免冲突:

`
潜行(Shift)+ 主手为空 + 副手持有任意物品 + 右击你的女仆
`

> 💡 **提示**:副手放一个火把、花或任何物品即可。双手全空时将由 CarryOn 接管(搬起女仆)。

## 🧲 副手吸引女仆

原版 TouhouLittleMaid 中,只有**主手**持蛋糕才能吸引女仆。本模组通过 Mixin 扩展了这一行为:

`
副手持有诱惑物品(默认蛋糕)→ 女仆也会被吸引过来
`

> 🎀 **搭配 CarryOn 使用的最佳姿势**:副手放蛋糕吸引女仆过来,然后潜行右击亲吻——一气呵成!

## 📥 安装

1. 安装 **Minecraft 1.21.1** + **NeoForge 21.1.x**
2. 安装 **[Touhou Little Maid](https://modrinth.com/mod/touhou-little-maid)** 1.5.0+
3. 将
maid-affection-x.x.x.jar 放入 .minecraft/mods/ 文件夹
4. 启动游戏!

## 🛠️ 从源码构建

`bash
git clone https://github.com/yabo083/maid-affection.git
cd maid-affection
./gradlew build
`

构建产物在
build/libs/maid-affection-x.x.x.jar。

## 📋 技术细节

  • Mod ID**: maid_affection
  • API**: 使用 TouhouLittleMaid 提供的 InteractMaidEvent 事件 API
  • 网络**: 自定义 KissMaidPayload 包(Server → Client)用于同步粒子效果
  • 兼容性**: 通过 ModList.isLoaded() 软检测 CarryOn,零硬依赖
  • 好感度**: 使用 TLM 内置的 FavorabilityManager + 自定义 Type("Kiss", 3, 600)`

## 📄 License

[MIT License](LICENSE) — 自由使用、修改和分发。


<p align="center">
<i>Made with ❤️ for the Touhou Little Maid community</i>
</p>
Touhou Maid: Affection Icon
Download Touhou Maid: Affection
Select game version
Select platform