🎬 A flexible Spigot plugin for playing Bad Apple in Minecraft using blocks or TextDisplay entities. 🍎✨
💬 Plugin usage / 🐛 Bug reports / 👨💻 Development discussion — Join our QQ Group: 259248174 🎉 (This group is gone)
💬 Plugin usage / 🐛 Bug reports / 👨💻 Development discussion — Join our QQ Group: 1085190201 🎉
💡 Mention me in the group for faster replies ~ ✨
The bundled video frame archive is preprocessed and loaded from the plugin JAR at runtime.
| Feature | Command | Description |
|---|---|---|
| 🧱 Block Mode | /play_bad_apple block |
Renders the video on a wall using black and white concrete blocks |
| 📝 Text Mode | /play_bad_apple text |
Renders the video using TextDisplay entities for a denser pixel screen |
| ⏹️ Stop Playback | /stop_bad_apple <text|block> |
Stops playback, clears cooldown, and optionally cleans blocks or entities |
| 🔄 Reload Config | /reload_bad_apple_config |
Reloads config.yml and refreshes the in-memory video frame cache |
The plugin ships with
assets/bin_96x54_10fps.zipinside the JAR and preloads all frames into memory before playback. Both command triggers and physical triggers can be controlled independently from the config.
In-game client screenshot
Animated in-game preview
Current repository defaults are aligned to the production
0.2.4-rc1style resource layout and config structure.
| 🎯 Server Type | |
| 🧱 Server API | |
| 📝 Language | |
| 🏗 Build | |
| 🔄 CI |
| 🧱 Plugin Jar | |
| 🎵 Music Pack Zip |
Place the generated .jar file into the server plugins/ directory and restart the server.
If you want audio playback, also download the resource pack release: bad-apple-music-resource-pack.
Default config:
# 🎬🍎 Bad Apple Plugin Configuration 🧱📝
# 🎥 全局画面设置 📺
video_settings:
# 🔄 是否在读取bin文件时进行水平翻转(镜像)
# true: 画面左右翻转,false: 保持原始画面
horizontal_flip: true
# 🧱 视频播放墙体配置 (block模式) 🧊
video_wall:
# 📍 墙体左下角方块的坐标
position:
x: -20
y: 0
z: -70
# 🧭 墙体朝向 (NORTH, SOUTH, EAST, WEST)
direction: NORTH
# 📝 视频播放文本展示配置 (text模式) 🖥️
video_text:
# 📍 文本展示左下角的坐标
position:
x: 44.5
y: -51.13
z: -18.913
# 🧭 墙体朝向 (NORTH, SOUTH, EAST, WEST)
direction: SOUTH
# 🔄 是否启用双面显示(背靠背实体)
enableBothSide: false
# ▶️ 播放设置 ⏱️
playback:
# ✅ 是否启用视频播放功能
enabled: true
# ⏳ 播放冷却时间(秒)
cooldown: 235 # ⏰ 3分55秒
# 🔊 是否启用音频播放控制
enableAudio: false
# 🆔 资源包中的声音 ID,例如 niacl:music_disc.bad_apple
audioSoundId: niacl:music_disc.bad_apple
# 🧹 清理设置 🗑️
cleanup:
# 🧊 Block 模式清理配置
block:
# ✅ 播放完毕后是否清除方块(3分55秒后)
clear_on_complete: true
# 🛑 手动停止播放后是否清除方块(stop命令或黑色压力板)
clear_on_stop: true
# 🖥️ Text 模式清理配置
text:
# ✅ 播放完毕后是否清除文本展示实体(3分55秒后)
clear_on_complete: true
# 🛑 手动停止播放后是否清除文本展示实体(stop命令或黑色按钮)
clear_on_stop: true
# 🔘 按钮控制:使用两个按钮控制播放/停止(text 模式)
controls:
# 🔇 声音延迟(tick)。例如10 tick ≈ 0.5秒
sound_delay_ticks: 1
# 🎮 触发方式配置 ⚡
triggers:
# 🧊 Block 模式触发配置
block:
# ⌨️ 允许通过指令触发 block 模式的开始
command_start_enabled: true
# ⌨️ 允许通过指令触发 block 模式的停止
command_stop_enabled: true
# 🟫 允许通过压力板触发 block 模式的开始
pressure_plate_start_enabled: true
# 🧱 用于触发 block 模式开始的压力板材质 ID
pressure_plate_start_material: PALE_OAK_PRESSURE_PLATE
# 🟫 允许通过压力板触发 block 模式的停止
pressure_plate_stop_enabled: true
# 🧱 用于触发 block 模式停止的压力板材质 ID
pressure_plate_stop_material: POLISHED_BLACKSTONE_PRESSURE_PLATE
# 🖥️ Text 模式触发配置
text:
# ⌨️ 允许通过指令触发 text 模式的开始
command_start_enabled: true
# ⌨️ 允许通过指令触发 text 模式的停止
command_stop_enabled: true
# 🔴 允许通过按钮触发 text 模式的开始
button_start_enabled: true
# 🧱 用于触发 text 模式开始的按钮材质 ID
button_start_material: PALE_OAK_BUTTON
# 🔴 允许通过按钮触发 text 模式的停止
button_stop_enabled: true
# 🧱 用于触发 text 模式停止的按钮材质 ID
button_stop_material: POLISHED_BLACKSTONE_BUTTONConfig notes:
video_settings.horizontal_flip: mirrors the loaded frame archive while decodingvideo_wall.position: lower-left block coordinate for block playbackvideo_text.position: lower-left anchor position for text playbackplayback.cooldown: shared cooldown for replaying the videoplayback.audioSoundId: sound identifier from the client resource pack, including namespace such asniacl:music_disc.bad_applecleanup.*: control whether blocks or entities are removed after playback or manual stoptriggers.*: enable or disable command, pressure plate, and button triggers independentlytriggers.block.pressure_plate_*_material/triggers.text.button_*_material: set the trigger block material names, for examplePALE_OAK_BUTTON
Reloading config:
- After editing
plugins/spigot-plugin-bad-apple/config.yml, run/reload_bad_apple_config - The command reloads config values and rebuilds the frame cache, so preprocessing-affecting options such as
horizontal_flipalso take effect - Reload is blocked while playback is active to avoid switching runtime state mid-play
./gradlew buildThe output JAR is generated under build/libs/.
Push to main or master and use commit keywords to control CI:
| Keyword | Behavior |
|---|---|
build action |
Build the plugin and upload the artifact |
build release |
Build the plugin and publish a GitHub Release |
Example:
git commit -m "feat: sync bundled video archive and config; build action"
git commit -m "build release. chore: publish bad apple plugin release"Pull requests to main or master also run the build job, but do not publish releases.

