Play osu!standard inside Minecraft — a Fabric mod for 1.20.1 See the README below for details.
README
On GitHubosu! in Minecraft
在 Minecraft 里直接游玩 osu!standard 谱面的 Fabric Mod。
Minecraft → Esc → 暂停菜单 → osu! → 选歌 → 游玩 → Esc → 回到 Minecraft
打开 osu! 界面时 Minecraft 世界会被冻结(单人存档下集成服务器同样暂停), osu! 拥有自己的场景栈、光标、输入与时钟,退出后 Minecraft 恢复原状。
1. 它能做什么
| 功能 | 状态 |
|---|---|
暂停菜单中的 osu! 按钮(另有快捷键 O) | ✅ |
解析官方 .osu 格式(v3 – v14 及 lazer v128+) | ✅ |
.osz 拖入自动解包导入 | ✅ |
| 选歌界面:搜索、上下浏览、音频试听 | ✅ |
| Hit circle / Slider(含 tick、repeat、legacy tail)/ Spinner | ✅ |
| 判定窗口、连击、分数(ScoreV1)、准确率、评级 | ✅ |
| Slider 路径:Linear / Bezier / Catmull / Perfect curve | ✅ |
绿线变速(SV)、NaN 关闭 slider tick | ✅ |
| 叠加(stacking)、combo 颜色、AR/CS/OD/HP 全部按官方公式 | ✅ |
| 判定动画、approach circle、follow circle、hit error bar | ✅ |
暂停、重开(R)、跳过前奏(Space)、结算界面 | ✅ |
音频:.ogg / .wav / .mp3 | ✅ |
| 程序化生成的皮肤与打击音(无需任何外部素材) | ✅ |
自定义打击音:谱面自带 / 全局皮肤文件夹(.wav .ogg .mp3) | ✅ |
| sample set(normal/soft/drum)、custom bank、逐音量、逐节点 edge sounds | ✅ |
| 游戏内设置:总/音乐/打击音三档音量、按键绑定、偏移、背景暗度等 | ✅ |
| Mod:EZ NF HT / HR SD PF DT NC HD FL / RX AP SO AT | ✅ |
| osu!direct:搜索镜像站并直接下载导入 | ✅ |
| 随 mod 附带 5 张谱面,首次启动自动解包 | ✅ |
| osu!taiko / catch / mania | ❌ 目前只支持 osu!standard |
皮肤(osu! .osk / 图片素材) | ❌ 目前是程序化生成的一套 |
| 排行榜、回放、在线功能 | ❌ 未实现 |
2. 安装
- 安装 Minecraft 1.20.1 + Fabric Loader 0.15+ + Fabric API。
- 把
osu-mc-1.0.0.jar放进.minecraft/mods/。 - 启动游戏。首次启动会把随包附带的谱面解包到
.minecraft/osu/Songs/:
| 谱面 | Mapper |
|---|---|
| kimono club - HIGHBALL DAY [AFTER I REACHED CHALLENGER] | Sakagami Tomoyo |
| Hanakami Ryu - Near Under Seven [Heaven Burns Blue] | Sakagami Tomoyo |
| stargaze shelter - Heisei (Mode: Tsukimiya Toto) [x_x] | Sakagami Tomoyo |
| Sorihiko - doyobi [Extra] | Sorihiko |
| iKz - Wo Yao Mai Mai Mai [Extra] | Sorihiko |
已经存在的文件夹不会被覆盖,删掉的也不会自己回来。
导入你自己的谱面
两种方式,任选其一:
- 拖
.osz:把.osz丢进.minecraft/osu/,进入选歌界面时会自动解包到Songs/,原文件移动到osu/imported/。 (选歌界面左下角那串路径可以点,直接打开 Songs 文件夹。) - 直接用现有的 osu! 安装:编辑
.minecraft/config/osumc.json,把songsDirectory指向你的 osu!Songs文件夹,例如:
"songsDirectory": "C:\\Users\\you\\AppData\\Local\\osu!\\Songs"
进入选歌界面按 F5 重新扫描。
osu!direct
选歌界面按 F4(或点右上角的 direct)。打字 → Enter 搜索 → 上下选 → Enter 下载, 也可以直接点两下某一行。下好会自动解包进 Songs 并重扫,不用退出游戏。
用的是公开镜像站(默认 Sayobot,国内网络下通常最快;设置里可换成 osu.direct)—— 官方 osu! API 要自己注册 OAuth 应用,对一个 mod 来说太重了。镜像站是免费的志愿服务, 所以这里按 Enter 才搜(不是边打边搜)、一次只下一个。
换掉附带的谱面
附带哪些谱面完全由资源目录决定,代码里没有任何一张的名字:
- 把
.osz丢进src/main/resources/assets/osumc/songs/; - 在同目录的
index.txt里写上文件名,一行一个(#开头是注释); - 重新构建。
想一张都不带就把 index.txt 清空——代码认得空列表。 注意 .osz 里是连歌一起打包的,随 mod 分发出去的东西要自己确认有没有这个权利。
3. 操作
| 场景 | 按键 |
|---|---|
| 打开 osu! | 暂停菜单的 osu! 按钮,或游戏中按 O |
| 选歌 | ↑ ↓ 浏览,直接打字搜索,Backspace 删除,Enter 开始,F5 重扫 |
| Mod | 选歌界面按 F2 或点右上角 mods;Backspace 清空,Esc 关闭 |
| osu!direct | 选歌界面按 F4 或点右上角 direct;打字 → Enter 搜索 → Enter 下载 |
| 打开 Songs 文件夹 | 点选歌界面左下角那串路径 |
| 设置 | 选歌界面按 F1 或点右上角 options;游玩中 Esc → Options |
| 游玩 | Z / X(可配置)或鼠标左右键点击,鼠标移动瞄准 |
| 跳过前奏 | Space |
| 重开 | R |
| 暂停 / 返回 | Esc(游玩中 → 暂停;选歌中 → 退出 osu! 回到 Minecraft) |
4. 设置
游戏内就能改:选歌界面按 F1(或点右上角的 options), 游玩中 Esc → Options 会以浮层形式打开——不会把正在玩的谱面卸掉,关掉浮层就能接着打。 拖动音量滑块时声音会实时跟着变,改完自动存盘。
按键绑定点一下方框再按目标键即可;Esc 取消绑定。
三档音量是相乘关系:实际音乐音量 = masterVolume × musicVolume, 实际打击音音量 = masterVolume × effectVolume。
Hitsound latency(8–60 ms,默认 15 ms)是打击音输出缓冲的大小。 已经交给声卡的音频是改不动的,所以缓冲多大,打击音最小延迟就是多少:越小越跟手。 但太小了机器喂不满缓冲,声音会断续 / 发抖——听到这种情况就往上调,20–30 ms 一般就稳了。 拖完滑块松手时会自动重开音频输出,不用重启游戏。
也可以直接编辑 .minecraft/config/osumc.json:
| 键 | 说明 | 默认 |
|---|---|---|
audioOffsetMs | 全局音频偏移,正值表示物件更晚出现 | 0 |
masterVolume | 总音量,乘在下面两个上面 | 0.8 |
musicVolume / effectVolume | 音乐 / 打击音音量 | 0.7 / 0.6 |
hitSoundLatencyMs | 打击音输出缓冲大小(8–60);越小越跟手,太小会断音 | 15 |
backgroundDim | 游玩时背景变暗程度 | 0.75 |
leadInMs | 第一个物件前的最短倒计时;谱面自己的 AudioLeadIn 更长时以谱面为准 | 2000 |
key1 / key2 | 敲击键的 GLFW keycode(Z = 90,X = 88) | 90 / 88 |
mouseButtonsTap | 鼠标左右键是否也算敲击 | true |
hideSystemCursor | 游玩时隐藏系统光标 | true |
sliderRenderMode | FRAMEBUFFER(重叠正确)或 SIMPLE(兼容回退) | FRAMEBUFFER |
snakingSliders | 滑条是否随淡入沿路径画出来 | true |
muteGameAudio | 打开 osu 界面时静音 Minecraft(服务器上很有用) | true |
damageAlerts | 在 osu 界面里受到伤害时弹提示 | true |
show300Judgements | 打出 300 时是否弹判定字(100/50/miss 不受影响) | false |
mods | 选中的 mod,如 "HDDT";在选歌界面按 F2 改 | "" |
cursorSize | 光标大小倍率 | 1.0 |
mirror | osu!direct 用哪个镜像:sayobot / osudirect | "sayobot" |
songsDirectory | 自定义 Songs 目录(留空用默认) | "" |
如果 slider 在你的显卡上显示异常,把 sliderRenderMode 改成 SIMPLE。 设置里那一行如果显示成 Slider rendering (unavailable),说明离屏缓冲在你的显卡上初始化失败、 已经自动退回兼容模式了(日志里会有一条 Offscreen slider rendering failed 的 warn)。
5. Mod
选歌界面按 F2(或点右上角的 mods)打开,点一下开关,Backspace 清空,Esc 关闭。 选择会存进配置,下次进来还在;结算界面和游玩 HUD 都会显示当前 mod。
冲突是选进来时就解决掉的:开着 HT 再点 DT,HT 自己就没了,不会出现不可能的组合。
| Mod | 效果 | 倍率 | |
|---|---|---|---|
| 降低难度 | EZ | CS/AR/OD/HP 全部 ×0.5,另外给 2 条命 | 0.50 |
NF | 不会失败 | 0.50 | |
HT | 0.75 倍速,音调不变 | 0.30 | |
| 提高难度 | HR | HP/OD/AR ×1.4、CS ×1.3(上限 10),谱面上下翻转 | 1.06 |
SD | miss 一次直接结束 | 1.00 | |
PF | 非 300 直接结束 | 1.00 | |
DT | 1.5 倍速,音调不变 | 1.12 | |
NC | 1.5 倍速并升调 | 1.12 | |
HD | 没有 approach circle,物件提前淡出 | 1.06 | |
FL | 只能看见光标周围,连击越高范围越小 | 1.12 | |
| 特殊 | RX | 不用点,只需要瞄 | 不计分 |
AP | 不用瞄,只需要点 | 不计分 | |
SO | 转盘自动完成 | 0.90 | |
AT | 全自动演示 | 不计分 |
数值全部来自 ppy/osu(ModHardRock.ADJUST_RATIO = 1.4、CS 单独的 1.3、ModEasy.ADJUST_RATIO = 0.5、 HD 的 0.4 / 0.3 淡入淡出系数、FL 的 125 与 100/200 连击缩放),倍率用的是 osu!stable 的那套, 因为这里的计分是 ScoreV1。HD/FL 会让 S / SS 变成银色。
DT 和 HT 不升降调,只有 NC 升调——这是 osu! 的行为(ModDoubleTime.AdjustPitch 默认 false, 只有 Nightcore 打开它)。所以 DT/HT 走 WSOLA 时间拉伸,NC 走重采样。 两者都不靠改输出采样率实现:1.5 倍的 44.1kHz 是 66150Hz,很多声卡直接拒绝。
"不能失败"现在是 NF 这个 mod,设置里那一项已经去掉了——默认会掉血会失败, 想关就在 F2 里点 NF。
6. 自定义打击音
内置的打击音是代码合成的(osu! 原版素材不可再分发),但可以直接换掉。 把音频文件丢进 .minecraft/osu/Skin/,文件名按 osu! 的约定来:
| 文件名 | 用途 |
|---|---|
normal-hitnormal | 基础敲击声 |
normal-hitwhistle | whistle 叠加音 |
normal-hitfinish | finish 叠加音 |
normal-hitclap | clap 叠加音 |
normal-slidertick | 滑条 tick |
normal-sliderslide | 按住滑条时的循环音 |
normal-sliderwhistle | 同上,滑条带 whistle 时用 |
combobreak | 断连 |
spinnerspin | 转盘 |
menuhit / menuback | 选歌界面 |
扩展名 .wav / .ogg / .mp3 都行。把 normal 换成 soft 或 drum 就是另外两套 sample set——谱面会按 timing point 逐段切换,想全覆盖就三套都放。 名字后面加数字是 custom sample bank,例如 normal-hitnormal2.wav。
优先级:谱面自己文件夹里的 > 这个皮肤文件夹 > 内置合成音。 所以谱师配好的逐图 hitsound 仍然按他的设计播放。没提供的那些自动回落到内置音, 不需要凑齐一整套。
两条值得知道的规则:
- 只放
normal-一套也够用。 谱面切到soft/drum时,如果你没提供对应文件,会先回落到你的
normal-版本,而不是直接掉回内置合成音——否则一首歌里音色会突变。 - 空音频文件 = 主动静音。 很多皮肤用零采样的
.ogg把循环滑条音或slidertick2静掉,这是有意为之,会被当作静音处理,而不是当成损坏文件去回落。sliderslide/sliderwhistle没有内置合成音,文件缺失时同样是静音—— 凭空循环一个没人要的音比安静糟糕得多。
文件夹首次创建时会自带一份 README.txt 说明同样的内容。
7. 构建
./gradlew build # 产物在 build/libs/osu-mc-1.0.0.jar
./gradlew runClient # 直接起一个带 mod 的开发客户端
./gradlew coreTest # 只跑引擎自测,不需要 Minecraft
./gradlew modCheck # 只跑 mod 规则的对照测试
./gradlew mapCheck # 解析并自动打完一个文件夹里的所有谱面
./gradlew onlineCheck # JSON 解析与镜像站响应解析
coreTest 跑的是 dev.sorihiko.osumc.core 这一层——它完全不依赖 Minecraft, 用普通 JDK 就能编译运行。也可以手动跑:
javac -d build/coreclasses $(find src/main/java/dev/sorihiko/osumc/core -name '*.java')
javac -cp build/coreclasses -d build/testclasses $(find src/test/java -name '*.java')
java -cp build/coreclasses:build/testclasses dev.sorihiko.osumc.core.CoreSelfTest
java -cp build/coreclasses:build/testclasses dev.sorihiko.osumc.core.ModCheck
java -cp build/coreclasses:build/testclasses dev.sorihiko.osumc.core.DemoCheck
java -cp build/coreclasses:build/testclasses dev.sorihiko.osumc.core.MixerLatencyCheck
java -cp build/coreclasses:build/testclasses dev.sorihiko.osumc.core.BundledMapCheck <谱面文件夹>
当前输出:
136 checks, 0 failures (引擎)
95 checks, 0 failures (mod,含 60fps 逐帧 autoplay → SS)
80 checks, 0 failures (JSON 与镜像站解析,含 4 家的响应形状)
18 checks, 0 failures (打击音延迟)
40 checks, 0 failures (5 张附带谱面:3792 个物件全部 autoplay SS)
auto-play: SS score=70899 combo=63x acc=100.00% 300/100/50/x = 39/0/0/0
8. 项目结构
src/main/java/dev/sorihiko/osumc/
├── core/ ← 零依赖引擎,纯 JDK,可单独测试
│ ├── beatmap/ ← .osu 解析、SliderPath、物件、谱面后处理
│ │ ├── OsuFileParser ← 移植自 LegacyBeatmapDecoder + ConvertHitObjectParser
│ │ ├── SliderPath ← 移植自 osu.Game.Rulesets.Objects.SliderPath
│ │ ├── SliderEventGenerator← 移植自 SliderEventGenerator(含 -36ms tail 宽容)
│ │ ├── Beatmap ← 含 OsuBeatmapProcessor 的 stacking 算法
│ │ └── BeatmapLibrary ← 目录扫描 + .osz 解包
│ ├── util/PathApproximator ← 移植自 osu-framework 的 Bezier/Catmull/圆弧逼近
│ ├── scoring/ ← OsuHitWindows、ScoreV1、准确率、评级、失败条件
│ ├── mods/ ← Mod 表、冲突解决、难度调整、HR 翻转、HD 曲线、FL 几何
│ ├── play/OsuGameplay ← 判定状态机(时钟驱动,与帧率无关)
│ ├── play/AutoPlayer ← RX / AP / AT / SO 的按键序列与光标轨迹
│ └── demo/DemoBeatmap ← 生成谱面与音频(现在只作测试夹具用)
└── client/ ← Minecraft 适配层
├── OsuMcClient ← 入口:暂停菜单按钮、快捷键、库初始化
├── BundledBeatmaps ← 解包 jar 里附带的谱面
├── OsuConfig
├── audio/ ← 解码(stb_vorbis / Java Sound / JLayer)、时钟、
│ 软件混音、WSOLA 变速(不变调)
├── render/ ← 程序化皮肤、批量精灵、slider 渲染、HUD
└── screen/ ← OsuScreen 宿主 + 选歌 / 游玩 / 结算三个场景
9. 已知限制
- 只支持 osu!standard。选歌界面会自动过滤
Mode != 0的谱面。 - 输入延迟受 Minecraft 帧率影响。GLFW 事件只在主线程轮询时派发,
所以判定时间戳的粒度约等于一帧。建议把帧率上限调高(无限制最好)。 判定本身由音频时钟驱动,不会因掉帧而漂移。
- HP 掉血是近似实现。osu!stable 的掉血曲线依赖大量历史细节,这里用了
形状一致的简化模型。分数、准确率、判定窗口、转盘转数是严格按官方公式实现的。 觉得掉血不合理就开
NF。 - 音频走 Java Sound,不走 Minecraft 的 OpenAL。这样 osu! 的时钟不会被
Minecraft 音频线程干扰,但 osu! 的音量不受 Minecraft 音量滑块控制(用配置文件调)。
- 内置打击音是合成的,不是 osu! 原版素材(那些不可再分发)。
谱面自带的 hitsound 和皮肤文件夹里的文件都会优先使用,见第 5 节。
- 不支持 storyboard、视频背景、break 期间的特效。
- 变速用的是自己写的 WSOLA(DT/HT)和线性/盒式重采样(NC)。
和 osu! 走 BASS 的 SoundTouch 是同一类算法,性格也一样:大部分音乐没问题, 非常纯的长音会有一点抖动。1.5 倍速下约占单核 1.8%。
10. 许可
本项目以 MIT 发布。core 中标注了 "ported from ppy/osu" 的文件是 ppy/osu 与 ppy/osu-framework (均为 MIT)的 Java 移植,版权归 ppy Pty Ltd,详见 NOTICE。
MP3 解码使用 JLayer(LGPL-2.1), 以未修改的形式 shade 进 jar。
osu! 是 ppy Pty Ltd 的商标。本项目与 ppy 无关,代码本身不包含任何 osu! 的 美术素材或音频素材——皮肤和打击音都是程序化生成的。
assets/osumc/songs/ 下附带的谱面是另一回事:它们包含各自的歌曲与 mapper 的作品, 版权归原作者,随本仓库一起分发只是为了开箱即玩。要公开发布这个 mod 的话, 先清空 index.txt(见第 2 节)。
From the project's repository, fetched . Images load from GitHub.
Releases
FeedNo releases yet. Follow the project to hear when the first one comes out.
Works for me
Did it work on your PC? A quick report tells other players which versions are safe to try.
Discussion
No posts yet. Ask a question, share your setup or post a clip.
Sign in to post