Compare commits
13 Commits
1.14.514.0
...
master
Author | SHA1 | Date | |
---|---|---|---|
81908d4548 | |||
2b390f8908 | |||
645bec3987 | |||
![]() |
3eabe96e6f | ||
![]() |
7bed25b441 | ||
![]() |
2334a12f19 | ||
![]() |
2b922647ab | ||
![]() |
ad971a375b | ||
![]() |
f60886c6d9 | ||
![]() |
d3d4a5b29f | ||
![]() |
75ffb8b54b | ||
![]() |
ad44ffec5b | ||
![]() |
b928cb9956 |
75
README.md
75
README.md
@ -1,12 +1,75 @@
|
|||||||
# 源README
|
# 源README
|
||||||
Download the mod at [Modrinth](https://modrinth.com/mod/disc-jockey) or [CurseForge](https://www.curseforge.com/minecraft/mc-mods/disc-jockey)
|
Download the mod at [Modrinth](https://modrinth.com/mod/disc-jockey) or [CurseForge](https://www.curseforge.com/minecraft/mc-mods/disc-jockey)
|
||||||
# 该版本附加
|
# 该版本附加
|
||||||
## 关于此项目
|
___
|
||||||
此 Mod 是基于 [Disc-Jockey](https://github.com/SemmieDev/Disc-Jockey)(由 [SemmieDev](https://github.com/SemmieDev/) 开发)的修改版本,适配了 Minecraft 1.21.4。
|
# Disc Jockey Revive
|
||||||
原始代码版权归原作者所有,修改部分版权归 BRanulf 所有。
|
|
||||||
|
|
||||||
同时,该二改版本我本人并没有上传至任何其他网站(包括 Modrinth 、CurseForge 、Github 等),请勿用于商业用途。
|
一个 Minecraft Fabric 模组,旨在为音符盒音乐爱好者提供强大的播放和即兴演奏功能。
|
||||||
|
|
||||||
[唯一下载地址](https://git.branulf.top/Branulf/DIsc_Jockey_revive/releases)
|
<!-- ## 模组特性
|
||||||
|
|
||||||
~~这边建议去给原作者点个Star~~
|
### 🎵 歌曲播放
|
||||||
|
- **播放 `.nbs` 歌曲文件**:支持标准的 Note Block Studio (`.nbs`) 歌曲文件(暂不支持带变速的)。
|
||||||
|
- **文件夹管理**:支持歌曲文件夹,方便组织和浏览您的音乐库。
|
||||||
|
- **多种播放模式**:
|
||||||
|
- **单曲循环**:重复播放当前歌曲。
|
||||||
|
- **列表循环**:按顺序循环播放当前文件夹或列表中的歌曲。
|
||||||
|
- **随机播放**:随机播放当前文件夹或列表中的歌曲。
|
||||||
|
- **播完停止**:歌曲播放完毕后自动停止。
|
||||||
|
- **播放进度条**:在 HUD 上显示歌曲播放进度和时间。
|
||||||
|
- **实时调速**:在播放界面通过滑块实时调整歌曲播放速度(0.25x - 4.0x)。
|
||||||
|
- **播放失败处理**:当附近音符盒配置不正确时,可选择停止播放或自动播放下一首。
|
||||||
|
- **音符盒材料清单**:显示播放当前歌曲所需的所有音符盒材料及数量。
|
||||||
|
- **自动调音**:模组会自动识别并调音附近的音符盒以匹配歌曲音高。
|
||||||
|
- **全向音符盒音效 (客户端)**:
|
||||||
|
- **常规模式**:在播放歌曲或预览时,使音符盒音效全向传播,提供更沉浸的听觉体验。
|
||||||
|
- **强制模式**:强制所有音符盒音效(包括手动触发的)始终全向传播。
|
||||||
|
|
||||||
|
### 🎹 即兴演奏 (Live DJ)
|
||||||
|
- **独立界面**:通过专用快捷键打开一个独立界面,用于即兴演奏。
|
||||||
|
- **键盘弹奏**:利用键盘按键直接弹奏音符盒,就像在 FL Studio 中一样。
|
||||||
|
- **自定义键位映射**:
|
||||||
|
- 独立的键位映射配置界面,允许您为每个键盘按键设置特定的音符(乐器和音高)。
|
||||||
|
- 默认提供类似于 FL Studio 的键盘布局预设。
|
||||||
|
- **即兴演奏调音**:在即兴演奏界面中,可以一键对周围的音符盒进行调音,以确保弹奏的音符准确无误。
|
||||||
|
- **独立于歌曲播放**:即兴演奏功能与歌曲播放功能完全独立,互不干扰。
|
||||||
|
|
||||||
|
### ⚙️ 配置与调试
|
||||||
|
- **Mod Menu 集成**:通过 Mod Menu 轻松访问模组配置。
|
||||||
|
- **快捷键**:
|
||||||
|
- 打开歌曲选择界面 (默认 `J`)。
|
||||||
|
- 打开即兴演奏界面 (默认 `UNKNOW(未指定)`)。
|
||||||
|
- **调试模式**:可配置的调试模式,开启后会在日志中输出详细的调试信息,方便排查问题。
|
||||||
|
|
||||||
|
## 如何使用
|
||||||
|
|
||||||
|
1. **安装**:将 `Disc Jockey Revive` 模组文件和 Fabric API 放入您的 Minecraft `mods` 文件夹。
|
||||||
|
2. **添加歌曲**:
|
||||||
|
* 在游戏中打开歌曲选择界面 (默认 `J` 键)。
|
||||||
|
* 点击“打开文件夹”按钮,将 `.nbs` 歌曲文件放入弹出的 `disc_jockey/songs` 文件夹中。
|
||||||
|
* 您也可以直接将 `.nbs` 文件拖放到歌曲选择界面中。
|
||||||
|
* 点击“重新加载”按钮以加载新添加的歌曲。
|
||||||
|
3. **播放歌曲**:
|
||||||
|
* 在歌曲选择界面中选择一首歌曲。
|
||||||
|
* 点击“播放”按钮。模组将自动寻找并调音附近的音符盒。
|
||||||
|
* 确保您处于生存模式或创造模式,并且附近有足够的音符盒。
|
||||||
|
* 您可以通过滑块调整播放速度,并通过播放模式按钮切换循环方式。
|
||||||
|
4. **即兴演奏**:
|
||||||
|
* 在游戏中打开即兴演奏界面 (默认 `UNKNOW` 键)。
|
||||||
|
* 点击“开始调音”按钮,模组将自动调音附近的音符盒。
|
||||||
|
* 调音完成后,您可以使用键盘按键直接弹奏音符盒。
|
||||||
|
* 点击“编辑键位映射”按钮可以自定义每个按键对应的音符。 -->
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
* **服务器兼容性**:此模组通过发送玩家交互数据包来控制音符盒。在某些服务器上,这可能被反作弊插件误判为作弊行为。**强烈建议在使用前联系服务器管理员。**
|
||||||
|
* **音符盒数量**:为了获得最佳播放效果,请确保您周围有足够数量且种类齐全的音符盒。
|
||||||
|
* **非官方版本**:此版本为非官方修订版,仅供学习和参考。请支持原版模组作者。
|
||||||
|
|
||||||
|
## 贡献与支持
|
||||||
|
|
||||||
|
如果您有任何问题、建议或发现 Bug,请联系[BRanulf](https://space.bilibili.com/479966868)(仅限于改二改版本,原版本请前往[原作者GitHub](https://github.com/SemmieDev/Disc-Jockey))。
|
||||||
|
|
||||||
|
不回复是正常现象,因为我也只是随便做做,并没有打算正经地维护,真要搞的化我估计会去GitHub创建分支,而不是只在自己仓库中修改。
|
||||||
|
|
||||||
|
---
|
||||||
|
116
build.gradle
116
build.gradle
@ -1,89 +1,51 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'fabric-loom' version '1.9.2'
|
id 'fabric-loom' version '1.10.5' apply false
|
||||||
id 'maven-publish'
|
// id 'maven-publish' apply false
|
||||||
|
|
||||||
|
id 'com.replaymod.preprocess' version '9d21b334a7'
|
||||||
|
|
||||||
|
id 'com.github.johnrengelman.shadow' version '8.1.1' apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
version = project.mod_version
|
version = project.mod_version
|
||||||
group = project.maven_group
|
group = project.maven_group
|
||||||
|
|
||||||
repositories {
|
preprocess {
|
||||||
maven { url "https://maven.shedaniel.me/" }
|
strictExtraMappings.set(false)
|
||||||
maven {url "https://maven.terraformersmc.com/"}
|
|
||||||
|
def mc12104 = createNode("1.21.4", 1_21_04, "")
|
||||||
|
def mc12105 = createNode("1.21.5", 1_21_05, "")
|
||||||
|
def mc12106 = createNode("1.21.6", 1_21_06, "")
|
||||||
|
def mc12107 = createNode("1.21.7", 1_21_07, "")
|
||||||
|
def mc12108 = createNode("1.21.8", 1_21_08, "")
|
||||||
|
|
||||||
|
mc12108.link(mc12107, file("versions/mapping_12108_12107.txt"))
|
||||||
|
mc12107.link(mc12106, file("versions/mapping_12107_12106.txt"))
|
||||||
|
mc12106.link(mc12105, file("versions/mapping_12106_12105.txt"))
|
||||||
|
mc12105.link(mc12104, file("versions/mapping_12105_12104.txt"))
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
tasks.register('buildAndGather') {
|
||||||
// To change the versions see the gradle.properties file
|
subprojects {
|
||||||
// implementation files("libs/modmenu-13.0.3.jar")
|
dependsOn project.tasks.named('build').get()
|
||||||
// implementation files("libs/modmenu-13.0.3.pom")
|
|
||||||
minecraft "com.mojang:minecraft:${project.minecraft_version}"
|
|
||||||
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
|
|
||||||
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
|
|
||||||
|
|
||||||
// Fabric API. This is technically optional, but you probably want it anyway.
|
|
||||||
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
|
|
||||||
|
|
||||||
include modApi("me.shedaniel.cloth:cloth-config-fabric:17.0.142") {
|
|
||||||
exclude(group: "net.fabricmc.fabric-api")
|
|
||||||
}
|
}
|
||||||
modImplementation "me.shedaniel.cloth:cloth-config-fabric:17.0.142"
|
doFirst {
|
||||||
|
println 'Gathering builds'
|
||||||
// modCompileOnly("com.terraformersmc:modmenu:13.0.3")、
|
def buildLibs = {
|
||||||
modCompileOnly files("libs/modmenu-13.0.3.jar")
|
p -> p.buildDir.toPath().resolve('libs')
|
||||||
modImplementation files("libs/LibGui-12.0.1+1.21.2.jar")
|
}
|
||||||
}
|
delete fileTree(buildLibs(rootProject)) {
|
||||||
|
include '*'
|
||||||
processResources {
|
}
|
||||||
inputs.property "version", project.version
|
subprojects {
|
||||||
filteringCharset "UTF-8"
|
copy {
|
||||||
|
from(buildLibs(project)) {
|
||||||
filesMatching("fabric.mod.json") {
|
include '*.jar'
|
||||||
expand "version": project.version
|
exclude '*-dev.jar', '*-sources.jar', '*-shadow.jar'
|
||||||
}
|
}
|
||||||
}
|
into buildLibs(rootProject)
|
||||||
|
duplicatesStrategy DuplicatesStrategy.INCLUDE
|
||||||
def targetJavaVersion = 21
|
}
|
||||||
tasks.withType(JavaCompile).configureEach {
|
|
||||||
// ensure that the encoding is set to UTF-8, no matter what the system default is
|
|
||||||
// this fixes some edge cases with special characters not displaying correctly
|
|
||||||
// see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html
|
|
||||||
// If Javadoc is generated, this must be specified in that task too.
|
|
||||||
it.options.encoding = "UTF-8"
|
|
||||||
if (targetJavaVersion >= 10 || JavaVersion.current().isJava10Compatible()) {
|
|
||||||
it.options.release = targetJavaVersion
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
java {
|
|
||||||
def javaVersion = JavaVersion.toVersion(targetJavaVersion)
|
|
||||||
if (JavaVersion.current() < javaVersion) {
|
|
||||||
toolchain.languageVersion = JavaLanguageVersion.of(targetJavaVersion)
|
|
||||||
}
|
|
||||||
archivesBaseName = project.archives_base_name
|
|
||||||
// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
|
|
||||||
// if it is present.
|
|
||||||
// If you remove this line, sources will not be generated.
|
|
||||||
withSourcesJar()
|
|
||||||
}
|
|
||||||
|
|
||||||
jar {
|
|
||||||
from("LICENSE") {
|
|
||||||
rename { "${it}_${project.archivesBaseName}" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// configure the maven publication
|
|
||||||
publishing {
|
|
||||||
publications {
|
|
||||||
mavenJava(MavenPublication) {
|
|
||||||
from components.java
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
|
|
||||||
repositories {
|
|
||||||
// Add repositories to publish to here.
|
|
||||||
// Notice: This block does NOT have the same function as the block in the top level.
|
|
||||||
// The repositories here will be used for publishing your artifact, not for
|
|
||||||
// retrieving dependencies.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
174
common.gradle
Normal file
174
common.gradle
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
apply plugin: 'maven-publish'
|
||||||
|
apply plugin: 'com.github.johnrengelman.shadow'
|
||||||
|
apply plugin: 'fabric-loom'
|
||||||
|
apply plugin: 'com.replaymod.preprocess'
|
||||||
|
|
||||||
|
int mcVersion = project.mcVersion
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
url 'https://maven.fabricmc.net/' // loom
|
||||||
|
}
|
||||||
|
maven {
|
||||||
|
url 'https://masa.dy.fi/maven' // masa(随便加的)
|
||||||
|
}
|
||||||
|
maven {
|
||||||
|
url 'https://maven.fallenbreath.me/releases' // preprocessor
|
||||||
|
}
|
||||||
|
maven {
|
||||||
|
url 'https://jitpack.io' // preprocessor
|
||||||
|
}
|
||||||
|
maven {
|
||||||
|
url 'https://www.cursemaven.com' // curseforge(随便加的)
|
||||||
|
}
|
||||||
|
maven {
|
||||||
|
url "https://maven.shedaniel.me/" // cloth config
|
||||||
|
}
|
||||||
|
maven {
|
||||||
|
url "https://maven.terraformersmc.com/" // modmenu
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
minecraft "com.mojang:minecraft:${project.minecraft_version}" // 从子项目
|
||||||
|
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" // 从子项目
|
||||||
|
modImplementation "net.fabricmc:fabric-loader:${rootProject.loader_version}" // 从根项目
|
||||||
|
|
||||||
|
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_api_version}"
|
||||||
|
|
||||||
|
include modApi("me.shedaniel.cloth:cloth-config-fabric:${project.cloth_config_version}") {
|
||||||
|
exclude(group: "net.fabricmc.fabric-api")
|
||||||
|
}
|
||||||
|
modImplementation "me.shedaniel.cloth:cloth-config-fabric:${project.cloth_config_version}"
|
||||||
|
|
||||||
|
// modCompileOnly files("${rootProject.projectDir}/libs/modmenu-13.0.3.jar")
|
||||||
|
modImplementation("com.terraformersmc:modmenu:${project.modmenu_version}")
|
||||||
|
// modImplementation files("${rootProject.projectDir}/libs/LibGui-12.0.1+1.21.2.jar")
|
||||||
|
}
|
||||||
|
|
||||||
|
String MIXIN_CONFIG_PATH = 'disc_jockey.mixins.json' // mixin
|
||||||
|
|
||||||
|
JavaVersion JAVA_COMPATIBILITY // java自动
|
||||||
|
if (mcVersion >= 12100) {
|
||||||
|
JAVA_COMPATIBILITY = JavaVersion.VERSION_21
|
||||||
|
} else if (mcVersion >= 11800) {
|
||||||
|
JAVA_COMPATIBILITY = JavaVersion.VERSION_17
|
||||||
|
} else if (mcVersion >= 11700) {
|
||||||
|
JAVA_COMPATIBILITY = JavaVersion.VERSION_16
|
||||||
|
} else {
|
||||||
|
JAVA_COMPATIBILITY = JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
|
JavaVersion MIXIN_COMPATIBILITY_LEVEL = JAVA_COMPATIBILITY
|
||||||
|
|
||||||
|
loom {
|
||||||
|
def commonVmArgs = ['-Dmixin.debug.export=true']
|
||||||
|
runConfigs.configureEach {
|
||||||
|
runDir '../../run'
|
||||||
|
vmArgs commonVmArgs
|
||||||
|
ideConfigGenerated true
|
||||||
|
}
|
||||||
|
|
||||||
|
runs {
|
||||||
|
def auditVmArgs = [*commonVmArgs, '-Ddisc_jockey_revive.mixin_audit=true']
|
||||||
|
serverMixinAudit {
|
||||||
|
server()
|
||||||
|
vmArgs auditVmArgs
|
||||||
|
ideConfigGenerated false
|
||||||
|
}
|
||||||
|
clientMixinAudit {
|
||||||
|
client()
|
||||||
|
vmArgs auditVmArgs
|
||||||
|
ideConfigGenerated false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打包胖子
|
||||||
|
shadowJar {
|
||||||
|
configurations = [project.configurations.shadow]
|
||||||
|
exclude("META-INF")
|
||||||
|
archiveClassifier.set('shadow')
|
||||||
|
}
|
||||||
|
|
||||||
|
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
||||||
|
|
||||||
|
tasks.withType(ShadowJar).configureEach {
|
||||||
|
enableRelocation true
|
||||||
|
relocationPrefix 'semmiedev.disc_jockey_revive.libs'
|
||||||
|
}
|
||||||
|
|
||||||
|
remapJar {
|
||||||
|
dependsOn(shadowJar)
|
||||||
|
mustRunAfter(shadowJar)
|
||||||
|
inputFile = shadowJar.archiveFile
|
||||||
|
}
|
||||||
|
|
||||||
|
String modVersionSuffix = ''
|
||||||
|
if (System.getenv("BUILD_RELEASE") != "true") {
|
||||||
|
String buildNumber = System.getenv("BUILD_ID")
|
||||||
|
modVersionSuffix += buildNumber != null ? ('+build.' + buildNumber) : '' // 文件名前
|
||||||
|
}
|
||||||
|
String fullModVersion = rootProject.mod_version + modVersionSuffix
|
||||||
|
|
||||||
|
String fullProjectVersion
|
||||||
|
|
||||||
|
group = rootProject.maven_group
|
||||||
|
if (System.getenv("JITPACK") == "true") {
|
||||||
|
base.archivesName = rootProject.archives_base_name + '-' + project.minecraft_version
|
||||||
|
fullProjectVersion = 'v' + rootProject.mod_version + modVersionSuffix
|
||||||
|
} else {
|
||||||
|
base.archivesName = rootProject.archives_base_name
|
||||||
|
fullProjectVersion = 'v' + rootProject.mod_version + '-' + project.minecraft_version + modVersionSuffix
|
||||||
|
}
|
||||||
|
version = fullProjectVersion
|
||||||
|
|
||||||
|
processResources {
|
||||||
|
inputs.property "id", rootProject.mod_id // 从根项目
|
||||||
|
inputs.property "name", rootProject.mod_name // 从根项目
|
||||||
|
inputs.property "version", fullModVersion
|
||||||
|
|
||||||
|
filesMatching("fabric.mod.json") {
|
||||||
|
def valueMap = [
|
||||||
|
"id" : rootProject.mod_id,
|
||||||
|
"name" : rootProject.mod_name,
|
||||||
|
"version" : fullModVersion,
|
||||||
|
"minecraft_version": project.minecraft_dependency, // 从子项目
|
||||||
|
"loader_version" : rootProject.loader_version // 从根项目
|
||||||
|
]
|
||||||
|
expand valueMap
|
||||||
|
}
|
||||||
|
|
||||||
|
filesMatching(MIXIN_CONFIG_PATH) {
|
||||||
|
filter { s -> s.replace('{{COMPATIBILITY_LEVEL}}', "JAVA_${MIXIN_COMPATIBILITY_LEVEL.ordinal() + 1}") }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType(JavaCompile).configureEach {
|
||||||
|
options.encoding = "UTF-8"
|
||||||
|
options.compilerArgs << "-Xlint:deprecation" << "-Xlint:unchecked"
|
||||||
|
if (JAVA_COMPATIBILITY <= JavaVersion.VERSION_1_8) {
|
||||||
|
options.compilerArgs << '-Xlint:-options'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
java {
|
||||||
|
sourceCompatibility = JAVA_COMPATIBILITY
|
||||||
|
targetCompatibility = JAVA_COMPATIBILITY
|
||||||
|
withSourcesJar()
|
||||||
|
}
|
||||||
|
|
||||||
|
jar {
|
||||||
|
from(rootProject.file('LICENSE')) {
|
||||||
|
rename { "${it}_${rootProject.archives_base_name}" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//publishing {
|
||||||
|
// publications {
|
||||||
|
// mavenJava(MavenPublication) {
|
||||||
|
// from components.java
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// repositories {
|
||||||
|
// }
|
||||||
|
//}
|
@ -1,12 +1,14 @@
|
|||||||
# Done to increase the memory available to gradle.
|
# Done to increase the memory available to gradle.
|
||||||
org.gradle.jvmargs=-Xmx1G
|
org.gradle.jvmargs=-Xmx2G
|
||||||
# Fabric Properties
|
# Fabric Properties
|
||||||
# check these on https://modmuss50.me/fabric.html
|
# check these on https://modmuss50.me/fabric.html
|
||||||
minecraft_version=1.21.4
|
minecraft_version=1.21.4
|
||||||
yarn_mappings=1.21.4+build.8
|
yarn_mappings=1.21.4+build.8
|
||||||
loader_version=0.16.10
|
loader_version=0.16.10
|
||||||
|
mod_name=Disc Jockey Revive
|
||||||
|
mod_id=disc_jockey_revive
|
||||||
# Mod Properties
|
# Mod Properties
|
||||||
mod_version=1.14.514.037
|
mod_version=1.14.514.050
|
||||||
maven_group=semmiedev
|
maven_group=semmiedev
|
||||||
archives_base_name=disc_jockey_revive
|
archives_base_name=disc_jockey_revive
|
||||||
# Dependencies
|
# Dependencies
|
||||||
|
@ -1,78 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
|
||||||
<!-- This module was also published with a richer model, Gradle metadata, -->
|
|
||||||
<!-- which should be used instead. Do not delete the following line which -->
|
|
||||||
<!-- is to indicate to Gradle or any Gradle module metadata file consumer -->
|
|
||||||
<!-- that they should prefer consuming it instead. -->
|
|
||||||
<!-- do_not_remove: published-with-gradle-metadata -->
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<groupId>io.github.cottonmc</groupId>
|
|
||||||
<artifactId>LibGui</artifactId>
|
|
||||||
<version>12.0.1+1.21.2</version>
|
|
||||||
<name>LibGui</name>
|
|
||||||
<description>Minecraft GUI Library</description>
|
|
||||||
<url>https://github.com/CottonMC/LibGui</url>
|
|
||||||
<licenses>
|
|
||||||
<license>
|
|
||||||
<name>MIT</name>
|
|
||||||
<url>https://github.com/CottonMC/LibGui/blob/HEAD/LICENSE</url>
|
|
||||||
</license>
|
|
||||||
</licenses>
|
|
||||||
<developers>
|
|
||||||
<developer>
|
|
||||||
<name>CottonMC</name>
|
|
||||||
<url>https://github.com/CottonMC</url>
|
|
||||||
</developer>
|
|
||||||
</developers>
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.github.juuxel</groupId>
|
|
||||||
<artifactId>libninepatch</artifactId>
|
|
||||||
<version>1.2.0</version>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>net.fabricmc.fabric-api</groupId>
|
|
||||||
<artifactId>fabric-api-base</artifactId>
|
|
||||||
<version>0.4.48+c47b9d4373</version>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>net.fabricmc.fabric-api</groupId>
|
|
||||||
<artifactId>fabric-networking-api-v1</artifactId>
|
|
||||||
<version>4.3.3+56ec7ac673</version>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>net.fabricmc</groupId>
|
|
||||||
<artifactId>fabric-loader</artifactId>
|
|
||||||
<version>0.16.7</version>
|
|
||||||
<scope>runtime</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>net.fabricmc.fabric-api</groupId>
|
|
||||||
<artifactId>fabric-lifecycle-events-v1</artifactId>
|
|
||||||
<version>2.3.22+c47b9d4373</version>
|
|
||||||
<scope>runtime</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>net.fabricmc.fabric-api</groupId>
|
|
||||||
<artifactId>fabric-rendering-v1</artifactId>
|
|
||||||
<version>8.0.5+c47b9d4373</version>
|
|
||||||
<scope>runtime</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>net.fabricmc.fabric-api</groupId>
|
|
||||||
<artifactId>fabric-resource-loader-v0</artifactId>
|
|
||||||
<version>3.0.5+c47b9d4373</version>
|
|
||||||
<scope>runtime</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.github.cottonmc</groupId>
|
|
||||||
<artifactId>Jankson-Fabric</artifactId>
|
|
||||||
<version>9.0.0+j1.2.3</version>
|
|
||||||
<scope>runtime</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
</project>
|
|
@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<groupId>com.terraformersmc</groupId>
|
|
||||||
<artifactId>modmenu</artifactId>
|
|
||||||
<version>13.0.3</version>
|
|
||||||
</project>
|
|
@ -1,9 +1,35 @@
|
|||||||
|
import groovy.json.JsonSlurper
|
||||||
|
|
||||||
pluginManagement {
|
pluginManagement {
|
||||||
repositories {
|
repositories {
|
||||||
maven {
|
maven {
|
||||||
name = 'Fabric'
|
name = 'Fabric'
|
||||||
url = 'https://maven.fabricmc.net/'
|
url = 'https://maven.fabricmc.net/'
|
||||||
}
|
}
|
||||||
|
maven {
|
||||||
|
name = 'Jitpack'
|
||||||
|
url = 'https://jitpack.io' // preprocessor
|
||||||
|
}
|
||||||
|
mavenCentral()
|
||||||
gradlePluginPortal()
|
gradlePluginPortal()
|
||||||
}
|
}
|
||||||
|
resolutionStrategy {
|
||||||
|
eachPlugin {
|
||||||
|
switch (requested.id.id) {
|
||||||
|
case "com.replaymod.preprocess": {
|
||||||
|
useModule("com.github.Fallen-Breath:preprocessor:${requested.version}")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def settings = new JsonSlurper().parseText(file('settings.json').text)
|
||||||
|
for (String version : settings.versions) {
|
||||||
|
include(":$version")
|
||||||
|
|
||||||
|
def proj = project(":$version")
|
||||||
|
proj.projectDir = file("versions/$version")
|
||||||
|
proj.buildFileName = "../../common.gradle"
|
||||||
}
|
}
|
||||||
|
9
settings.json
Normal file
9
settings.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"versions": [
|
||||||
|
"1.21.4",
|
||||||
|
"1.21.5",
|
||||||
|
"1.21.6",
|
||||||
|
"1.21.7",
|
||||||
|
"1.21.8"
|
||||||
|
]
|
||||||
|
}
|
@ -1,25 +1,42 @@
|
|||||||
package semmiedev.disc_jockey_revive;
|
package semmiedev.disc_jockey_revive;
|
||||||
|
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.util.Formatting;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
// 这玩意一般不用,我自己用的,但是不想删
|
// 这玩意一般不用,我自己用的,但是不想删
|
||||||
public class DebugLogger {
|
public class DebugLogger {
|
||||||
|
|
||||||
public static void log(String message) {
|
public static void log(String message) {
|
||||||
if (Main.config != null && Main.config.debugModeEnabled) {
|
if (Main.config != null && Main.config.debugModeEnabled) {
|
||||||
Main.LOGGER.info("[DiscJockeyRevive-调试] " + message);
|
Main.LOGGER.info("[DiscJockeyRevive-调试] " + message);
|
||||||
|
sendMessage(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void log(String format, Object... arguments) {
|
public static void log(String format, Object... arguments) {
|
||||||
if (Main.config != null && Main.config.debugModeEnabled) {
|
if (Main.config != null && Main.config.debugModeEnabled) {
|
||||||
Main.LOGGER.info("[DiscJockeyRevive-调试] " + format, arguments);
|
Main.LOGGER.info("[DiscJockeyRevive-调试] " + format, arguments);
|
||||||
|
sendMessage(format + ": " + Arrays.toString(arguments));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void log(String message, Throwable t) {
|
public static void log(String message, Throwable t) {
|
||||||
if (Main.config != null && Main.config.debugModeEnabled) {
|
if (Main.config != null && Main.config.debugModeEnabled) {
|
||||||
Main.LOGGER.error("[DiscJockeyRevive-调试] " + message, t);
|
Main.LOGGER.error("[DiscJockeyRevive-调试] " + message, t);
|
||||||
|
sendMessage(message + ": " + t.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void sendMessage(String message) {
|
||||||
|
MinecraftClient client = MinecraftClient.getInstance();
|
||||||
|
if (client != null && client.inGameHud != null && client.inGameHud.getChatHud() != null) {
|
||||||
|
MinecraftClient.getInstance().inGameHud.getChatHud().addMessage(Text.of("[DiscJockeyRevive-调试]"+message.formatted(Formatting.GRAY)));
|
||||||
|
} else {
|
||||||
|
// Main.LOGGER.error("[DiscJockeyRevive-调试] 聊天窗口未初始化,{}",message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,6 +48,7 @@ public class KeyMappingManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void loadMappings() {
|
public void loadMappings() {
|
||||||
|
DebugLogger.log("KeyMappingManager: 加载键位预设");
|
||||||
if (!MAPPINGS_FILE.exists()) {
|
if (!MAPPINGS_FILE.exists()) {
|
||||||
Main.LOGGER.info("未找到键映射文件,正在创建默认的类似于 FL Studio 的映射。");
|
Main.LOGGER.info("未找到键映射文件,正在创建默认的类似于 FL Studio 的映射。");
|
||||||
mappings.clear();
|
mappings.clear();
|
||||||
@ -91,6 +92,8 @@ public class KeyMappingManager {
|
|||||||
mappings.put(InputUtil.fromKeyCode(InputUtil.GLFW_KEY_LEFT_BRACKET, 0), new Note(dirt, (byte) 23));
|
mappings.put(InputUtil.fromKeyCode(InputUtil.GLFW_KEY_LEFT_BRACKET, 0), new Note(dirt, (byte) 23));
|
||||||
mappings.put(InputUtil.fromKeyCode(InputUtil.GLFW_KEY_EQUAL, 0), new Note(dirt, (byte) 24));
|
mappings.put(InputUtil.fromKeyCode(InputUtil.GLFW_KEY_EQUAL, 0), new Note(dirt, (byte) 24));
|
||||||
|
|
||||||
|
DebugLogger.log("KeyMappingManager: 默认预设创建完成");
|
||||||
|
|
||||||
|
|
||||||
saveMappings();
|
saveMappings();
|
||||||
return;
|
return;
|
||||||
@ -118,6 +121,7 @@ public class KeyMappingManager {
|
|||||||
|
|
||||||
public void saveMappings() {
|
public void saveMappings() {
|
||||||
MAPPINGS_FILE.getParentFile().mkdirs();
|
MAPPINGS_FILE.getParentFile().mkdirs();
|
||||||
|
DebugLogger.log("KeyMappingManager: 开始保存按键映射");
|
||||||
try (FileWriter writer = new FileWriter(MAPPINGS_FILE)) {
|
try (FileWriter writer = new FileWriter(MAPPINGS_FILE)) {
|
||||||
HashMap<String, NoteData> dataToSave = new HashMap<>();
|
HashMap<String, NoteData> dataToSave = new HashMap<>();
|
||||||
for (Map.Entry<InputUtil.Key, Note> entry : mappings.entrySet()) {
|
for (Map.Entry<InputUtil.Key, Note> entry : mappings.entrySet()) {
|
||||||
@ -136,10 +140,12 @@ public class KeyMappingManager {
|
|||||||
|
|
||||||
public void setMapping(InputUtil.Key key, Note note) {
|
public void setMapping(InputUtil.Key key, Note note) {
|
||||||
mappings.put(key, note);
|
mappings.put(key, note);
|
||||||
|
DebugLogger.log("KeyMappingManager: 已设置按键映射:"+key.getTranslationKey()+" 为 "+getNoteDisplayName(note));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeMapping(InputUtil.Key key) {
|
public void removeMapping(InputUtil.Key key) {
|
||||||
mappings.remove(key);
|
mappings.remove(key);
|
||||||
|
DebugLogger.log("KeyMappingManager: 已移除键位预设:"+key.getTranslationKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<InputUtil.Key, Note> getMappings() {
|
public Map<InputUtil.Key, Note> getMappings() {
|
||||||
@ -149,7 +155,7 @@ public class KeyMappingManager {
|
|||||||
public static String getNoteDisplayName(Note note) {
|
public static String getNoteDisplayName(Note note) {
|
||||||
if (note == null) return "未设置";
|
if (note == null) return "未设置";
|
||||||
|
|
||||||
String instrumentTranslationKey = "block.minecraft.note_block.instrument." + note.instrument().asString();
|
String instrumentTranslationKey = " " + note.instrument().asString();
|
||||||
String instrumentName = Text.translatable(instrumentTranslationKey).getString();
|
String instrumentName = Text.translatable(instrumentTranslationKey).getString();
|
||||||
|
|
||||||
int pitch = note.note();
|
int pitch = note.note();
|
||||||
|
@ -51,6 +51,7 @@ public class LiveDjPlayer implements ClientTickEvents.StartWorldTick {
|
|||||||
|
|
||||||
// 调音
|
// 调音
|
||||||
public synchronized void startTuning() {
|
public synchronized void startTuning() {
|
||||||
|
DebugLogger.log("LiveDjPlayer: 开始调音。");
|
||||||
if (tuned && noteBlocks != null) {
|
if (tuned && noteBlocks != null) {
|
||||||
MinecraftClient.getInstance().inGameHud.getChatHud().addMessage(Text.translatable(Main.MOD_ID+".player.retuning").formatted(Formatting.YELLOW));
|
MinecraftClient.getInstance().inGameHud.getChatHud().addMessage(Text.translatable(Main.MOD_ID+".player.retuning").formatted(Formatting.YELLOW));
|
||||||
} else {
|
} else {
|
||||||
@ -75,6 +76,7 @@ public class LiveDjPlayer implements ClientTickEvents.StartWorldTick {
|
|||||||
// 停止调音
|
// 停止调音
|
||||||
public synchronized void stopTuning() {
|
public synchronized void stopTuning() {
|
||||||
tuningRequested = false;
|
tuningRequested = false;
|
||||||
|
DebugLogger.log("LiveDjPlayer: 停止调音");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 是否正在调音
|
// 是否正在调音
|
||||||
@ -93,6 +95,7 @@ public class LiveDjPlayer implements ClientTickEvents.StartWorldTick {
|
|||||||
|
|
||||||
// 播放
|
// 播放
|
||||||
public boolean playNoteBlock(Note note) {
|
public boolean playNoteBlock(Note note) {
|
||||||
|
DebugLogger.log("LiveDjPlayer: 触发播放");
|
||||||
MinecraftClient client = MinecraftClient.getInstance();
|
MinecraftClient client = MinecraftClient.getInstance();
|
||||||
ClientWorld world = client.world;
|
ClientWorld world = client.world;
|
||||||
ClientPlayerEntity player = client.player;
|
ClientPlayerEntity player = client.player;
|
||||||
@ -120,6 +123,7 @@ public class LiveDjPlayer implements ClientTickEvents.StartWorldTick {
|
|||||||
|
|
||||||
// 获取可交互的
|
// 获取可交互的
|
||||||
private boolean sendNotePacket(BlockPos blockPos) {
|
private boolean sendNotePacket(BlockPos blockPos) {
|
||||||
|
DebugLogger.log("LiveDjPlayer: 发送播放数据包。");
|
||||||
MinecraftClient client = MinecraftClient.getInstance();
|
MinecraftClient client = MinecraftClient.getInstance();
|
||||||
ClientPlayerEntity player = client.player;
|
ClientPlayerEntity player = client.player;
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
@ -451,6 +455,7 @@ public class LiveDjPlayer implements ClientTickEvents.StartWorldTick {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private HashMap<Byte, BlockPos> getNotesMapForInstrument(NoteBlockInstrument instrument) {
|
private HashMap<Byte, BlockPos> getNotesMapForInstrument(NoteBlockInstrument instrument) {
|
||||||
|
DebugLogger.log("LiveDjPlayer: 尝试获取音符。");
|
||||||
if (noteBlocks == null) {
|
if (noteBlocks == null) {
|
||||||
noteBlocks = new HashMap<>();
|
noteBlocks = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
@ -14,9 +14,13 @@ import net.minecraft.client.MinecraftClient;
|
|||||||
import net.minecraft.client.option.KeyBinding;
|
import net.minecraft.client.option.KeyBinding;
|
||||||
import net.minecraft.client.util.InputUtil;
|
import net.minecraft.client.util.InputUtil;
|
||||||
import net.minecraft.client.world.ClientWorld;
|
import net.minecraft.client.world.ClientWorld;
|
||||||
|
import net.minecraft.registry.Registries;
|
||||||
|
import net.minecraft.registry.Registry;
|
||||||
|
import net.minecraft.sound.SoundEvent;
|
||||||
import net.minecraft.text.MutableText;
|
import net.minecraft.text.MutableText;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.util.Formatting;
|
import net.minecraft.util.Formatting;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
@ -31,7 +35,7 @@ import java.util.ArrayList;
|
|||||||
public class Main implements ClientModInitializer {
|
public class Main implements ClientModInitializer {
|
||||||
public static final String MOD_ID = "disc_jockey_revive";
|
public static final String MOD_ID = "disc_jockey_revive";
|
||||||
public static final MutableText NAME = Text.literal("Disc Jockey");
|
public static final MutableText NAME = Text.literal("Disc Jockey");
|
||||||
public static final Logger LOGGER = LogManager.getLogger("Disc Jockey");
|
public static final Logger LOGGER = LogManager.getLogger("Disc Jockey Revive");
|
||||||
public static final ArrayList<ClientTickEvents.StartWorldTick> TICK_LISTENERS = new ArrayList<>();
|
public static final ArrayList<ClientTickEvents.StartWorldTick> TICK_LISTENERS = new ArrayList<>();
|
||||||
public static final Previewer PREVIEWER = new Previewer();
|
public static final Previewer PREVIEWER = new Previewer();
|
||||||
public static final SongPlayer SONG_PLAYER = new SongPlayer();
|
public static final SongPlayer SONG_PLAYER = new SongPlayer();
|
||||||
@ -45,6 +49,7 @@ public class Main implements ClientModInitializer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInitializeClient() {
|
public void onInitializeClient() {
|
||||||
|
DebugLogger.log("Main: 正在进行初始化。");
|
||||||
configHolder = AutoConfig.register(ModConfig.class, JanksonConfigSerializer::new);
|
configHolder = AutoConfig.register(ModConfig.class, JanksonConfigSerializer::new);
|
||||||
config = configHolder.getConfig();
|
config = configHolder.getConfig();
|
||||||
|
|
||||||
@ -68,10 +73,12 @@ public class Main implements ClientModInitializer {
|
|||||||
PREVIEWER.stop();
|
PREVIEWER.stop();
|
||||||
SONG_PLAYER.stop();
|
SONG_PLAYER.stop();
|
||||||
LIVE_DJ_PLAYER.stopTuning();
|
LIVE_DJ_PLAYER.stopTuning();
|
||||||
|
DebugLogger.log("Main: 退出世界,停止。");
|
||||||
}
|
}
|
||||||
prevWorld = client.world;
|
prevWorld = client.world;
|
||||||
|
|
||||||
if (openScreenKeyBind.wasPressed()) {
|
if (openScreenKeyBind.wasPressed()) {
|
||||||
|
DebugLogger.log("Main: 打开主界面:"+openScreenKeyBind);
|
||||||
if (SongLoader.loadingSongs) {
|
if (SongLoader.loadingSongs) {
|
||||||
client.inGameHud.getChatHud().addMessage(Text.translatable(Main.MOD_ID+".still_loading").formatted(Formatting.RED));
|
client.inGameHud.getChatHud().addMessage(Text.translatable(Main.MOD_ID+".still_loading").formatted(Formatting.RED));
|
||||||
SongLoader.showToast = true;
|
SongLoader.showToast = true;
|
||||||
@ -80,12 +87,15 @@ public class Main implements ClientModInitializer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (openLiveDjScreenKeyBind.wasPressed()) {
|
if (openLiveDjScreenKeyBind.wasPressed()) {
|
||||||
if (SongLoader.loadingSongs) {
|
DebugLogger.log("Main: 打开DJ界面:"+openLiveDjScreenKeyBind);
|
||||||
client.inGameHud.getChatHud().addMessage(Text.translatable(Main.MOD_ID+".still_loading").formatted(Formatting.RED));
|
// if (SongLoader.loadingSongs) {
|
||||||
SongLoader.showToast = true;
|
// client.inGameHud.getChatHud().addMessage(Text.translatable(Main.MOD_ID+".still_loading").formatted(Formatting.RED));
|
||||||
} else {
|
// SongLoader.showToast = true;
|
||||||
client.setScreen(new LiveDjScreen());
|
// } else {
|
||||||
}
|
// client.setScreen(new LiveDjScreen());
|
||||||
|
// }
|
||||||
|
// 好像这个界面并不需要什么歌曲加载
|
||||||
|
client.setScreen(new LiveDjScreen());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -102,8 +112,11 @@ public class Main implements ClientModInitializer {
|
|||||||
PREVIEWER.stop();
|
PREVIEWER.stop();
|
||||||
SONG_PLAYER.stop();
|
SONG_PLAYER.stop();
|
||||||
LIVE_DJ_PLAYER.stopTuning();
|
LIVE_DJ_PLAYER.stopTuning();
|
||||||
|
DebugLogger.log("Main: 断开连接,停止。");
|
||||||
});
|
});
|
||||||
|
|
||||||
HudRenderCallback.EVENT.register(new PlaybackProgressOverlay());
|
HudRenderCallback.EVENT.register(new PlaybackProgressOverlay());
|
||||||
|
|
||||||
|
DebugLogger.log("Main: 出屎化完成。");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,9 @@ public class ModConfig implements ConfigData {
|
|||||||
@ConfigEntry.Gui.Tooltip(count = 2) public boolean disableAsyncPlayback;
|
@ConfigEntry.Gui.Tooltip(count = 2) public boolean disableAsyncPlayback;
|
||||||
@ConfigEntry.Gui.Tooltip(count = 2) public boolean omnidirectionalNoteBlockSounds = true;
|
@ConfigEntry.Gui.Tooltip(count = 2) public boolean omnidirectionalNoteBlockSounds = true;
|
||||||
|
|
||||||
|
@ConfigEntry.Gui.Tooltip(count = 1)
|
||||||
|
public boolean forceOmnidirectionalNoteBlockSounds = false;
|
||||||
|
|
||||||
@ConfigEntry.Gui.Excluded
|
@ConfigEntry.Gui.Excluded
|
||||||
public String currentFolderPath = "";
|
public String currentFolderPath = "";
|
||||||
|
|
||||||
@ -37,6 +40,11 @@ public class ModConfig implements ConfigData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum PlaybackFailureAction {
|
||||||
|
STOP,
|
||||||
|
NEXT_SONG
|
||||||
|
}
|
||||||
|
|
||||||
@ConfigEntry.Gui.EnumHandler(option = ConfigEntry.Gui.EnumHandler.EnumDisplayOption.BUTTON)
|
@ConfigEntry.Gui.EnumHandler(option = ConfigEntry.Gui.EnumHandler.EnumDisplayOption.BUTTON)
|
||||||
@ConfigEntry.Gui.Tooltip(count = 4)
|
@ConfigEntry.Gui.Tooltip(count = 4)
|
||||||
public ExpectedServerVersion expectedServerVersion = ExpectedServerVersion.All;
|
public ExpectedServerVersion expectedServerVersion = ExpectedServerVersion.All;
|
||||||
@ -50,6 +58,14 @@ public class ModConfig implements ConfigData {
|
|||||||
@ConfigEntry.Gui.Tooltip(count = 1)
|
@ConfigEntry.Gui.Tooltip(count = 1)
|
||||||
public boolean showHudProgressBar = true;
|
public boolean showHudProgressBar = true;
|
||||||
|
|
||||||
|
@ConfigEntry.Gui.Tooltip(count = 1)
|
||||||
|
@ConfigEntry.Gui.EnumHandler(option = ConfigEntry.Gui.EnumHandler.EnumDisplayOption.BUTTON)
|
||||||
|
public PlaybackFailureAction playbackFailureAction = PlaybackFailureAction.STOP;
|
||||||
|
|
||||||
|
|
||||||
@ConfigEntry.Gui.Tooltip(count = 1)
|
@ConfigEntry.Gui.Tooltip(count = 1)
|
||||||
public boolean debugModeEnabled = false;
|
public boolean debugModeEnabled = false;
|
||||||
|
|
||||||
|
@ConfigEntry.Gui.Tooltip(count = 1)
|
||||||
|
public boolean debugModeChatMessages = false;
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,14 @@ public record Note(NoteBlockInstrument instrument, byte note) {
|
|||||||
NoteBlockInstrument.BANJO,
|
NoteBlockInstrument.BANJO,
|
||||||
NoteBlockInstrument.PLING,
|
NoteBlockInstrument.PLING,
|
||||||
|
|
||||||
|
NoteBlockInstrument.ZOMBIE,
|
||||||
|
NoteBlockInstrument.SKELETON,
|
||||||
|
NoteBlockInstrument.CREEPER,
|
||||||
|
NoteBlockInstrument.DRAGON,
|
||||||
|
NoteBlockInstrument.WITHER_SKELETON,
|
||||||
|
NoteBlockInstrument.PIGLIN,
|
||||||
|
NoteBlockInstrument.CUSTOM_HEAD
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static {
|
static {
|
||||||
@ -50,5 +58,13 @@ public record Note(NoteBlockInstrument instrument, byte note) {
|
|||||||
INSTRUMENT_BLOCKS.put(NoteBlockInstrument.BIT, Blocks.EMERALD_BLOCK);
|
INSTRUMENT_BLOCKS.put(NoteBlockInstrument.BIT, Blocks.EMERALD_BLOCK);
|
||||||
INSTRUMENT_BLOCKS.put(NoteBlockInstrument.BANJO, Blocks.HAY_BLOCK);
|
INSTRUMENT_BLOCKS.put(NoteBlockInstrument.BANJO, Blocks.HAY_BLOCK);
|
||||||
INSTRUMENT_BLOCKS.put(NoteBlockInstrument.PLING, Blocks.GLOWSTONE);
|
INSTRUMENT_BLOCKS.put(NoteBlockInstrument.PLING, Blocks.GLOWSTONE);
|
||||||
|
|
||||||
|
INSTRUMENT_BLOCKS.put(NoteBlockInstrument.ZOMBIE, Blocks.ZOMBIE_HEAD);
|
||||||
|
INSTRUMENT_BLOCKS.put(NoteBlockInstrument.SKELETON, Blocks.SKELETON_SKULL);
|
||||||
|
INSTRUMENT_BLOCKS.put(NoteBlockInstrument.CREEPER, Blocks.CREEPER_HEAD);
|
||||||
|
INSTRUMENT_BLOCKS.put(NoteBlockInstrument.DRAGON, Blocks.DRAGON_HEAD);
|
||||||
|
INSTRUMENT_BLOCKS.put(NoteBlockInstrument.WITHER_SKELETON, Blocks.WITHER_SKELETON_SKULL);
|
||||||
|
INSTRUMENT_BLOCKS.put(NoteBlockInstrument.PIGLIN, Blocks.PIGLIN_HEAD);
|
||||||
|
INSTRUMENT_BLOCKS.put(NoteBlockInstrument.CUSTOM_HEAD, Blocks.PLAYER_HEAD);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,12 +11,13 @@ public class Previewer implements ClientTickEvents.StartWorldTick {
|
|||||||
|
|
||||||
private int i;
|
private int i;
|
||||||
private float tick;
|
private float tick;
|
||||||
private Song song;
|
public Song song;
|
||||||
|
|
||||||
public void start(Song song) {
|
public void start(Song song) {
|
||||||
this.song = song;
|
this.song = song;
|
||||||
Main.TICK_LISTENERS.add(this);
|
Main.TICK_LISTENERS.add(this);
|
||||||
running = true;
|
running = true;
|
||||||
|
DebugLogger.log("Previewer: 开始播放。");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stop() {
|
public void stop() {
|
||||||
@ -24,6 +25,30 @@ public class Previewer implements ClientTickEvents.StartWorldTick {
|
|||||||
running = false;
|
running = false;
|
||||||
i = 0;
|
i = 0;
|
||||||
tick = 0;
|
tick = 0;
|
||||||
|
DebugLogger.log("Previewer: 停止播放。");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前播放进度 (0.0 - 1.0)
|
||||||
|
public synchronized float getProgress() {
|
||||||
|
if (song == null || !running) return 0;
|
||||||
|
return Math.min(1.0f, (float) (tick / song.length));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取格式化时间字符串
|
||||||
|
public synchronized String getFormattedTime() {
|
||||||
|
if (song == null) return "00:00 / 00:00";
|
||||||
|
|
||||||
|
double totalSeconds = song.getLengthInSeconds();
|
||||||
|
double currentSeconds = song.ticksToMilliseconds(tick) / 1000.0;
|
||||||
|
|
||||||
|
return formatTime((int) currentSeconds) + " / " + formatTime((int) totalSeconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化时间为 mm:ss
|
||||||
|
private String formatTime(int seconds) {
|
||||||
|
int min = seconds / 60;
|
||||||
|
int sec = seconds % 60;
|
||||||
|
return String.format("%02d:%02d", min, sec);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -3,6 +3,7 @@ package semmiedev.disc_jockey_revive;
|
|||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.toast.SystemToast;
|
import net.minecraft.client.toast.SystemToast;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.util.Formatting;
|
||||||
import semmiedev.disc_jockey_revive.gui.SongListWidget;
|
import semmiedev.disc_jockey_revive.gui.SongListWidget;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -34,6 +35,7 @@ public class SongLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void loadSongs() {
|
public static void loadSongs() {
|
||||||
|
DebugLogger.log("SongLoader: 加载歌曲");
|
||||||
if (loadingSongs) return;
|
if (loadingSongs) return;
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
loadingSongs = true;
|
loadingSongs = true;
|
||||||
@ -48,13 +50,17 @@ public class SongLoader {
|
|||||||
for (Song song : SONGS) SONG_SUGGESTIONS.add(song.displayName);
|
for (Song song : SONGS) SONG_SUGGESTIONS.add(song.displayName);
|
||||||
Main.config.favorites.removeIf(favorite -> SongLoader.SONGS.stream().map(song -> song.fileName).noneMatch(favorite::equals));
|
Main.config.favorites.removeIf(favorite -> SongLoader.SONGS.stream().map(song -> song.fileName).noneMatch(favorite::equals));
|
||||||
|
|
||||||
if (showToast && MinecraftClient.getInstance().textRenderer != null) SystemToast.add(MinecraftClient.getInstance().getToastManager(), SystemToast.Type.PACK_LOAD_FAILURE, Main.NAME, Text.translatable(Main.MOD_ID+".loading_done"));
|
if (showToast && MinecraftClient.getInstance().textRenderer != null) {
|
||||||
|
SystemToast.add(MinecraftClient.getInstance().getToastManager(), SystemToast.Type.PACK_LOAD_FAILURE, Main.NAME, Text.translatable(Main.MOD_ID+".loading_done"));
|
||||||
|
MinecraftClient.getInstance().inGameHud.getChatHud().addMessage(Text.translatable(Main.MOD_ID+".loading_done").formatted(Formatting.AQUA));
|
||||||
|
}
|
||||||
showToast = true;
|
showToast = true;
|
||||||
loadingSongs = false;
|
loadingSongs = false;
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void loadFolder(File folder, SongFolder parentFolder) {
|
private static void loadFolder(File folder, SongFolder parentFolder) {
|
||||||
|
DebugLogger.log("SongLoader: 加载文件夹");
|
||||||
if (!folder.isDirectory()) return;
|
if (!folder.isDirectory()) return;
|
||||||
|
|
||||||
SongFolder songFolder = new SongFolder(folder.getName(), folder.getPath());
|
SongFolder songFolder = new SongFolder(folder.getName(), folder.getPath());
|
||||||
@ -86,6 +92,7 @@ public class SongLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Song loadSong(File file) throws IOException {
|
public static Song loadSong(File file) throws IOException {
|
||||||
|
DebugLogger.log("SongLoader: 加载歌曲:"+file.getName());
|
||||||
if (file.isFile()) {
|
if (file.isFile()) {
|
||||||
BinaryReader reader = new BinaryReader(Files.newInputStream(file.toPath()));
|
BinaryReader reader = new BinaryReader(Files.newInputStream(file.toPath()));
|
||||||
Song song = new Song();
|
Song song = new Song();
|
||||||
|
@ -78,6 +78,7 @@ public class SongPlayer implements ClientTickEvents.StartWorldTick {
|
|||||||
|
|
||||||
this.playbackThread = new Thread(() -> {
|
this.playbackThread = new Thread(() -> {
|
||||||
Thread ownThread = this.playbackThread;
|
Thread ownThread = this.playbackThread;
|
||||||
|
DebugLogger.log("SongPlayer: 开始播放线程。");
|
||||||
while(ownThread == this.playbackThread) {
|
while(ownThread == this.playbackThread) {
|
||||||
try {
|
try {
|
||||||
// Accuracy doesn't really matter at this precision imo
|
// Accuracy doesn't really matter at this precision imo
|
||||||
@ -102,11 +103,17 @@ public class SongPlayer implements ClientTickEvents.StartWorldTick {
|
|||||||
private boolean isRandomPlaying = false;
|
private boolean isRandomPlaying = false;
|
||||||
private int randomIndex = -1;
|
private int randomIndex = -1;
|
||||||
|
|
||||||
|
public synchronized void setSpeed(float speed) {
|
||||||
|
this.speed = MathHelper.clamp(speed, 0.25f, 4.0f);
|
||||||
|
}
|
||||||
|
|
||||||
public synchronized void stopPlaybackThread() {
|
public synchronized void stopPlaybackThread() {
|
||||||
this.playbackThread = null; // Should stop on its own then
|
this.playbackThread = null; // Should stop on its own then
|
||||||
|
DebugLogger.log("SongPlayer: 停止播放线程。");
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void start(Song song) {
|
public synchronized void start(Song song) {
|
||||||
|
DebugLogger.log("SongPlayer: 开始播放。");
|
||||||
if (!Main.config.hideWarning && !warned) {
|
if (!Main.config.hideWarning && !warned) {
|
||||||
MinecraftClient.getInstance().inGameHud.getChatHud().addMessage(Text.translatable("disc_jockey_revive.warning").formatted(Formatting.BOLD, Formatting.RED));
|
MinecraftClient.getInstance().inGameHud.getChatHud().addMessage(Text.translatable("disc_jockey_revive.warning").formatted(Formatting.BOLD, Formatting.RED));
|
||||||
warned = true;
|
warned = true;
|
||||||
@ -140,7 +147,25 @@ public class SongPlayer implements ClientTickEvents.StartWorldTick {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private synchronized void handlePlaybackFailure() {
|
||||||
|
DebugLogger.log("处理播放失败,配置选项: {}", Main.config.playbackFailureAction.name());
|
||||||
|
|
||||||
|
switch (Main.config.playbackFailureAction) {
|
||||||
|
case NEXT_SONG: // 播放下一首
|
||||||
|
stop();
|
||||||
|
MinecraftClient.getInstance().inGameHud.getChatHud().addMessage(Text.translatable(Main.MOD_ID+".playback_failure.next_message").formatted(Formatting.GRAY));
|
||||||
|
playNextSong();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STOP: // 停止播放(原本)
|
||||||
|
default:
|
||||||
|
stop();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public synchronized void stop() {
|
public synchronized void stop() {
|
||||||
|
DebugLogger.log("SongPlayer: 停止播放。");
|
||||||
//MinecraftClient.getInstance().send(() -> Main.TICK_LISTENERS.remove(this));
|
//MinecraftClient.getInstance().send(() -> Main.TICK_LISTENERS.remove(this));
|
||||||
stopPlaybackThread();
|
stopPlaybackThread();
|
||||||
running = false;
|
running = false;
|
||||||
@ -260,6 +285,7 @@ public class SongPlayer implements ClientTickEvents.StartWorldTick {
|
|||||||
public synchronized void setPlayMode(PlayMode mode) {
|
public synchronized void setPlayMode(PlayMode mode) {
|
||||||
this.playMode = mode;
|
this.playMode = mode;
|
||||||
this.loopSong = mode == PlayMode.SINGLE_LOOP;
|
this.loopSong = mode == PlayMode.SINGLE_LOOP;
|
||||||
|
DebugLogger.log("SongPlayer: 设置播放模式:"+ mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取当前播放进度 (0.0 - 1.0)
|
// 获取当前播放进度 (0.0 - 1.0)
|
||||||
@ -294,6 +320,7 @@ public class SongPlayer implements ClientTickEvents.StartWorldTick {
|
|||||||
|
|
||||||
int prevIndex = (currentIndex - 1 + SongLoader.currentFolder.songs.size()) % SongLoader.currentFolder.songs.size();
|
int prevIndex = (currentIndex - 1 + SongLoader.currentFolder.songs.size()) % SongLoader.currentFolder.songs.size();
|
||||||
start(SongLoader.currentFolder.songs.get(prevIndex));
|
start(SongLoader.currentFolder.songs.get(prevIndex));
|
||||||
|
DebugLogger.log("SongPlayer: 切上一首。");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 播放下一首
|
// 播放下一首
|
||||||
@ -309,6 +336,7 @@ public class SongPlayer implements ClientTickEvents.StartWorldTick {
|
|||||||
|
|
||||||
int nextIndex = (currentIndex + 1) % SongLoader.currentFolder.songs.size();
|
int nextIndex = (currentIndex + 1) % SongLoader.currentFolder.songs.size();
|
||||||
start(SongLoader.currentFolder.songs.get(nextIndex));
|
start(SongLoader.currentFolder.songs.get(nextIndex));
|
||||||
|
DebugLogger.log("SongPlayer: 切下一首。");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -426,6 +454,7 @@ public class SongPlayer implements ClientTickEvents.StartWorldTick {
|
|||||||
if (!missingNotes.isEmpty()) {
|
if (!missingNotes.isEmpty()) {
|
||||||
ChatHud chatHud = MinecraftClient.getInstance().inGameHud.getChatHud();
|
ChatHud chatHud = MinecraftClient.getInstance().inGameHud.getChatHud();
|
||||||
chatHud.addMessage(Text.translatable(Main.MOD_ID+".player.invalid_note_blocks").formatted(Formatting.RED));
|
chatHud.addMessage(Text.translatable(Main.MOD_ID+".player.invalid_note_blocks").formatted(Formatting.RED));
|
||||||
|
DebugLogger.log("播放失败:缺少音符盒");
|
||||||
|
|
||||||
HashMap<Block, Integer> missing = new HashMap<>();
|
HashMap<Block, Integer> missing = new HashMap<>();
|
||||||
for (Note note : missingNotes) {
|
for (Note note : missingNotes) {
|
||||||
@ -440,6 +469,8 @@ public class SongPlayer implements ClientTickEvents.StartWorldTick {
|
|||||||
missingInstrumentBlocks = missing;
|
missingInstrumentBlocks = missing;
|
||||||
missing.forEach((block, integer) -> chatHud.addMessage(Text.literal(block.getName().getString()+" × "+integer).formatted(Formatting.RED)));
|
missing.forEach((block, integer) -> chatHud.addMessage(Text.literal(block.getName().getString()+" × "+integer).formatted(Formatting.RED)));
|
||||||
stop();
|
stop();
|
||||||
|
handlePlaybackFailure();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
} else if (!tuned) {
|
} else if (!tuned) {
|
||||||
//tuned = true;
|
//tuned = true;
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
package semmiedev.disc_jockey_revive.gui;
|
||||||
|
|
||||||
|
import net.minecraft.client.gui.widget.SliderWidget;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
|
||||||
|
// 唉
|
||||||
|
public abstract class CustomSliderWidget extends SliderWidget {
|
||||||
|
public CustomSliderWidget(int x, int y, int width, int height, Text text, double value) {
|
||||||
|
super(x, y, width, height, text, value);
|
||||||
|
updateMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateMessagePublic() {
|
||||||
|
updateMessage();
|
||||||
|
}
|
||||||
|
}
|
@ -89,9 +89,9 @@ public class KeyMappingListWidget extends EntryListWidget<KeyMappingListWidget.K
|
|||||||
MinecraftClient client = MinecraftClient.getInstance();
|
MinecraftClient client = MinecraftClient.getInstance();
|
||||||
int textY = y + (entryHeight - client.textRenderer.fontHeight) / 2;
|
int textY = y + (entryHeight - client.textRenderer.fontHeight) / 2;
|
||||||
Text keyText = Text.translatable(key.getTranslationKey());
|
Text keyText = Text.translatable(key.getTranslationKey());
|
||||||
context.drawTextWithShadow(client.textRenderer, keyText, x + 5, textY, 0xFFFFFF);
|
context.drawTextWithShadow(client.textRenderer, keyText, x + 5, textY, 0xFFFFFFFF);
|
||||||
String noteDisplayName = KeyMappingManager.getNoteDisplayName(note);
|
String noteDisplayName = KeyMappingManager.getNoteDisplayName(note);
|
||||||
context.drawTextWithShadow(client.textRenderer, noteDisplayName, x + 100, textY, 0xAAAAAA);
|
context.drawTextWithShadow(client.textRenderer, noteDisplayName, x + 100, textY, 0xFFAAAAAA);
|
||||||
int buttonWidth = 50;
|
int buttonWidth = 50;
|
||||||
int buttonHeight = 18;
|
int buttonHeight = 18;
|
||||||
int buttonY = y + (entryHeight - buttonHeight) / 2;
|
int buttonY = y + (entryHeight - buttonHeight) / 2;
|
||||||
|
@ -5,10 +5,10 @@ import net.minecraft.client.gui.DrawContext;
|
|||||||
|
|
||||||
public class ProgressBarRenderer {
|
public class ProgressBarRenderer {
|
||||||
private static final int BACKGROUND_COLOR = 0x80808080;
|
private static final int BACKGROUND_COLOR = 0x80808080;
|
||||||
private static final int PROGRESS_COLOR = 0x8000FF00; // 绿色
|
// private static final int PROGRESS_COLOR = 0x8000FF00;
|
||||||
private static final int TEXT_COLOR = 0xFFFFFF;
|
private static final int TEXT_COLOR = 0xEEFFFFFF;
|
||||||
|
|
||||||
public void renderProgressBar(DrawContext context, int x, int y, int width, int height, float progress, String timeText) {
|
public void renderProgressBar(DrawContext context, int x, int y, int width, int height, float progress, String timeText, int PROGRESS_COLOR) {
|
||||||
context.fill(x, y, x + width, y + height, BACKGROUND_COLOR);
|
context.fill(x, y, x + width, y + height, BACKGROUND_COLOR);
|
||||||
|
|
||||||
int progressWidth = (int) (width * progress);
|
int progressWidth = (int) (width * progress);
|
||||||
@ -17,7 +17,7 @@ public class ProgressBarRenderer {
|
|||||||
|
|
||||||
MinecraftClient client = MinecraftClient.getInstance();
|
MinecraftClient client = MinecraftClient.getInstance();
|
||||||
int textX = x + (width - client.textRenderer.getWidth(timeText)) / 2;
|
int textX = x + (width - client.textRenderer.getWidth(timeText)) / 2;
|
||||||
int textY = y - client.textRenderer.fontHeight - 2;
|
int textY = y - client.textRenderer.fontHeight - 0;
|
||||||
context.drawTextWithShadow(client.textRenderer, timeText, textX, textY, TEXT_COLOR);
|
context.drawTextWithShadow(client.textRenderer, timeText, textX, textY, TEXT_COLOR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,7 @@ public class SongListWidget extends EntryListWidget<SongListWidget.Entry> {
|
|||||||
client.textRenderer,
|
client.textRenderer,
|
||||||
emoji,
|
emoji,
|
||||||
x + 4, y + 6,
|
x + 4, y + 6,
|
||||||
favorite ? 0xFFD700 : 0x808080
|
favorite ? 0xFFFFD700 : 0xFF808080
|
||||||
);
|
);
|
||||||
|
|
||||||
// 歌曲名称靠左显示,从收藏图标右侧开始
|
// 歌曲名称靠左显示,从收藏图标右侧开始
|
||||||
@ -81,7 +81,7 @@ public class SongListWidget extends EntryListWidget<SongListWidget.Entry> {
|
|||||||
client.textRenderer,
|
client.textRenderer,
|
||||||
displayText,
|
displayText,
|
||||||
textX, y + 6,
|
textX, y + 6,
|
||||||
selected ? 0xFFFFFF : 0x808080
|
selected ? 0xFFFFFFFF : 0xFF808080
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,7 +159,7 @@ public class SongListWidget extends EntryListWidget<SongListWidget.Entry> {
|
|||||||
client.textRenderer,
|
client.textRenderer,
|
||||||
displayText,
|
displayText,
|
||||||
x + 6, y + 6,
|
x + 6, y + 6,
|
||||||
selected ? 0xFFFFFF : 0x808080
|
selected ? 0xFFFFFFFF : 0xFF808080
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ public class PlaybackProgressOverlay implements HudRenderCallback {
|
|||||||
int screenHeight = context.getScaledWindowHeight();
|
int screenHeight = context.getScaledWindowHeight();
|
||||||
|
|
||||||
int barX = screenWidth / 2 - PROGRESS_BAR_WIDTH / 2;
|
int barX = screenWidth / 2 - PROGRESS_BAR_WIDTH / 2;
|
||||||
int barY = screenHeight - 55;
|
int barY = screenHeight - 55; // 差不多比护甲值高一点
|
||||||
|
|
||||||
progressBarRenderer.renderProgressBar(
|
progressBarRenderer.renderProgressBar(
|
||||||
context,
|
context,
|
||||||
@ -38,7 +38,27 @@ public class PlaybackProgressOverlay implements HudRenderCallback {
|
|||||||
PROGRESS_BAR_WIDTH,
|
PROGRESS_BAR_WIDTH,
|
||||||
5,
|
5,
|
||||||
Main.SONG_PLAYER.getProgress(),
|
Main.SONG_PLAYER.getProgress(),
|
||||||
Main.SONG_PLAYER.getFormattedTime()
|
Main.SONG_PLAYER.getFormattedTime(),
|
||||||
|
0x8000FF00
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Main.PREVIEWER.running && Main.PREVIEWER.song != null && isInGame) {
|
||||||
|
int screenWidth = context.getScaledWindowWidth();
|
||||||
|
int screenHeight = context.getScaledWindowHeight();
|
||||||
|
|
||||||
|
int barX = screenWidth / 2 - PROGRESS_BAR_WIDTH / 2;
|
||||||
|
int barY = screenHeight - 42; // 差不多比生命值高一点
|
||||||
|
|
||||||
|
progressBarRenderer.renderProgressBar(
|
||||||
|
context,
|
||||||
|
barX,
|
||||||
|
barY,
|
||||||
|
PROGRESS_BAR_WIDTH,
|
||||||
|
5,
|
||||||
|
Main.PREVIEWER.getProgress(),
|
||||||
|
Main.PREVIEWER.getFormattedTime(),
|
||||||
|
0x80FF0000
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
package semmiedev.disc_jockey_revive.gui.screen;
|
package semmiedev.disc_jockey_revive.gui.screen;
|
||||||
|
|
||||||
|
import me.shedaniel.autoconfig.AutoConfig;
|
||||||
import net.minecraft.client.gui.DrawContext;
|
import net.minecraft.client.gui.DrawContext;
|
||||||
import net.minecraft.client.gui.screen.ConfirmScreen;
|
import net.minecraft.client.gui.screen.ConfirmScreen;
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
import net.minecraft.client.gui.widget.ButtonWidget;
|
import net.minecraft.client.gui.widget.ButtonWidget;
|
||||||
|
import net.minecraft.client.gui.widget.SliderWidget;
|
||||||
import net.minecraft.client.gui.widget.TextFieldWidget;
|
import net.minecraft.client.gui.widget.TextFieldWidget;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.text.MutableText;
|
import net.minecraft.text.MutableText;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.util.Formatting;
|
import net.minecraft.util.Formatting;
|
||||||
import semmiedev.disc_jockey_revive.Main;
|
import semmiedev.disc_jockey_revive.*;
|
||||||
import semmiedev.disc_jockey_revive.Note;
|
import semmiedev.disc_jockey_revive.gui.CustomSliderWidget;
|
||||||
import semmiedev.disc_jockey_revive.Song;
|
|
||||||
import semmiedev.disc_jockey_revive.SongLoader;
|
|
||||||
import semmiedev.disc_jockey_revive.gui.ProgressBarRenderer;
|
import semmiedev.disc_jockey_revive.gui.ProgressBarRenderer;
|
||||||
import semmiedev.disc_jockey_revive.gui.SongListWidget;
|
import semmiedev.disc_jockey_revive.gui.SongListWidget;
|
||||||
import semmiedev.disc_jockey_revive.gui.hud.BlocksOverlay;
|
import semmiedev.disc_jockey_revive.gui.hud.BlocksOverlay;
|
||||||
@ -31,21 +31,21 @@ import semmiedev.disc_jockey_revive.SongPlayer.PlayMode;
|
|||||||
import static net.minecraft.client.toast.TutorialToast.PROGRESS_BAR_WIDTH;
|
import static net.minecraft.client.toast.TutorialToast.PROGRESS_BAR_WIDTH;
|
||||||
|
|
||||||
public class DiscJockeyScreen extends Screen {
|
public class DiscJockeyScreen extends Screen {
|
||||||
private static final MutableText
|
public static final MutableText
|
||||||
SELECT_SONG = Text.translatable(Main.MOD_ID+".screen.select_song"),
|
SELECT_SONG = Text.translatable(Main.MOD_ID+".screen.select_song"),
|
||||||
PLAY = Text.translatable(Main.MOD_ID+".screen.play"),
|
PLAY = Text.translatable(Main.MOD_ID+".screen.play"),
|
||||||
PLAY_STOP = Text.translatable(Main.MOD_ID+".screen.play.stop"),
|
PLAY_STOP = Text.translatable(Main.MOD_ID+".screen.play.stop").formatted(Formatting.YELLOW),
|
||||||
PREVIEW = Text.translatable(Main.MOD_ID+".screen.preview"),
|
PREVIEW = Text.translatable(Main.MOD_ID+".screen.preview"),
|
||||||
PREVIEW_STOP = Text.translatable(Main.MOD_ID+".screen.preview.stop"),
|
PREVIEW_STOP = Text.translatable(Main.MOD_ID+".screen.preview.stop").formatted(Formatting.YELLOW),
|
||||||
DROP_HINT = Text.translatable(Main.MOD_ID+".screen.drop_hint").formatted(Formatting.GRAY)
|
DROP_HINT = Text.translatable(Main.MOD_ID+".screen.drop_hint").formatted(Formatting.GRAY)
|
||||||
;
|
;
|
||||||
|
|
||||||
private SongListWidget songListWidget;
|
public SongListWidget songListWidget;
|
||||||
private ButtonWidget playButton, previewButton;
|
public ButtonWidget playButton, previewButton;
|
||||||
public boolean shouldFilter;
|
public boolean shouldFilter;
|
||||||
private String query = "";
|
public String query = "";
|
||||||
|
|
||||||
private static final MutableText
|
public static final MutableText
|
||||||
FOLDER_UP = Text.literal("↑"),
|
FOLDER_UP = Text.literal("↑"),
|
||||||
CURRENT_FOLDER = Text.translatable(Main.MOD_ID+".screen.current_folder"),
|
CURRENT_FOLDER = Text.translatable(Main.MOD_ID+".screen.current_folder"),
|
||||||
PLAY_MODE = Text.translatable(Main.MOD_ID+".screen.play_mode"),
|
PLAY_MODE = Text.translatable(Main.MOD_ID+".screen.play_mode"),
|
||||||
@ -54,16 +54,20 @@ public class DiscJockeyScreen extends Screen {
|
|||||||
MODE_RANDOM = Text.translatable(Main.MOD_ID+".screen.mode_random"),
|
MODE_RANDOM = Text.translatable(Main.MOD_ID+".screen.mode_random"),
|
||||||
MODE_STOP = Text.translatable(Main.MOD_ID+".screen.mode_stop");
|
MODE_STOP = Text.translatable(Main.MOD_ID+".screen.mode_stop");
|
||||||
|
|
||||||
private static final MutableText
|
public static final MutableText
|
||||||
OPEN_FOLDER = Text.translatable(Main.MOD_ID+".screen.open_folder"),
|
OPEN_FOLDER = Text.translatable(Main.MOD_ID+".screen.open_folder"),
|
||||||
RELOAD = Text.translatable(Main.MOD_ID+".screen.reload"),
|
RELOAD = Text.translatable(Main.MOD_ID+".screen.reload"),
|
||||||
LIVE_DJ = Text.translatable(Main.MOD_ID+".screen.live_dj").formatted(Formatting.GOLD);
|
LIVE_DJ = Text.translatable(Main.MOD_ID+".screen.live_dj").formatted(Formatting.GOLD);
|
||||||
|
|
||||||
private ButtonWidget folderUpButton, playModeButton;
|
public ButtonWidget folderUpButton, playModeButton;
|
||||||
public SongFolder currentFolder;
|
public SongFolder currentFolder;
|
||||||
private PlayMode currentPlayMode = PlayMode.STOP_AFTER;
|
public PlayMode currentPlayMode = PlayMode.STOP_AFTER;
|
||||||
|
|
||||||
private ProgressBarRenderer progressBarRenderer;
|
public ProgressBarRenderer progressBarRenderer;
|
||||||
|
|
||||||
|
public CustomSliderWidget speedSlider;
|
||||||
|
|
||||||
|
public ButtonWidget configButton;
|
||||||
|
|
||||||
public DiscJockeyScreen() {
|
public DiscJockeyScreen() {
|
||||||
super(Main.NAME);
|
super(Main.NAME);
|
||||||
@ -72,6 +76,7 @@ public class DiscJockeyScreen extends Screen {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void init() {
|
protected void init() {
|
||||||
|
DebugLogger.log("DiscJockeyScreen: 开始初始化界面");
|
||||||
shouldFilter = true;
|
shouldFilter = true;
|
||||||
songListWidget = new SongListWidget(client, width, height - 100, 32, 20, this);
|
songListWidget = new SongListWidget(client, width, height - 100, 32, 20, this);
|
||||||
boolean isLargeScreen = width > 900;
|
boolean isLargeScreen = width > 900;
|
||||||
@ -99,6 +104,7 @@ public class DiscJockeyScreen extends Screen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 返回
|
||||||
folderUpButton = ButtonWidget.builder(FOLDER_UP, button -> {
|
folderUpButton = ButtonWidget.builder(FOLDER_UP, button -> {
|
||||||
if (currentFolder != null) {
|
if (currentFolder != null) {
|
||||||
currentFolder = null;
|
currentFolder = null;
|
||||||
@ -108,6 +114,7 @@ public class DiscJockeyScreen extends Screen {
|
|||||||
}).dimensions(10, 10, 20, 20).build();
|
}).dimensions(10, 10, 20, 20).build();
|
||||||
addDrawableChild(folderUpButton);
|
addDrawableChild(folderUpButton);
|
||||||
|
|
||||||
|
// 播放模式
|
||||||
playModeButton = ButtonWidget.builder(getPlayModeText(), button -> {
|
playModeButton = ButtonWidget.builder(getPlayModeText(), button -> {
|
||||||
switch (currentPlayMode) {
|
switch (currentPlayMode) {
|
||||||
case SINGLE_LOOP -> currentPlayMode = PlayMode.LIST_LOOP;
|
case SINGLE_LOOP -> currentPlayMode = PlayMode.LIST_LOOP;
|
||||||
@ -120,6 +127,40 @@ public class DiscJockeyScreen extends Screen {
|
|||||||
}).dimensions(width - 120, 10, 100, 20).build();
|
}).dimensions(width - 120, 10, 100, 20).build();
|
||||||
addDrawableChild(playModeButton);
|
addDrawableChild(playModeButton);
|
||||||
|
|
||||||
|
// 我展示速度
|
||||||
|
int sliderWidth = 120;
|
||||||
|
int sliderX = width - 120 - sliderWidth - 10;
|
||||||
|
int sliderY = 10;
|
||||||
|
speedSlider = new CustomSliderWidget(sliderX, sliderY, sliderWidth, 20,
|
||||||
|
Text.translatable(Main.MOD_ID + ".screen.speed"),
|
||||||
|
(Main.SONG_PLAYER.speed - 0.25f) / (4.0f - 0.25f)
|
||||||
|
) {
|
||||||
|
@Override
|
||||||
|
protected void updateMessage() {
|
||||||
|
float currentSpeed = (float) (0.25f + this.value * (4.0f - 0.25f));
|
||||||
|
this.setMessage(Text.translatable(Main.MOD_ID + ".screen.speed_value",
|
||||||
|
String.format("%.2f", currentSpeed)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void applyValue() {
|
||||||
|
float newSpeed = (float) (0.25f + this.value * (4.0f - 0.25f));
|
||||||
|
Main.SONG_PLAYER.speed = newSpeed;
|
||||||
|
DebugLogger.log("播放速度设置为: {:.2f}x", newSpeed);
|
||||||
|
}
|
||||||
|
}; if (isLargeScreen) addDrawableChild(speedSlider);
|
||||||
|
|
||||||
|
// 配置按钮
|
||||||
|
int configButtonSize = 20;
|
||||||
|
int configButtonX = width - 120 - sliderWidth - configButtonSize - 10 - 10;
|
||||||
|
int configButtonY = 10;
|
||||||
|
if (!isLargeScreen) configButtonX = width - 120 - configButtonSize - 10;
|
||||||
|
configButton = ButtonWidget.builder(Text.literal("⚙"), button -> {
|
||||||
|
Screen configScreen = AutoConfig.getConfigScreen(ModConfig.class, this).get();
|
||||||
|
client.setScreen(configScreen);
|
||||||
|
}).dimensions(configButtonX, configButtonY, configButtonSize, configButtonSize).build();
|
||||||
|
addDrawableChild(configButton);
|
||||||
|
|
||||||
int buttonY;
|
int buttonY;
|
||||||
if (isLargeScreen){
|
if (isLargeScreen){
|
||||||
buttonY = height - 30;
|
buttonY = height - 30;
|
||||||
@ -129,7 +170,7 @@ public class DiscJockeyScreen extends Screen {
|
|||||||
int centerX = width / 2;
|
int centerX = width / 2;
|
||||||
|
|
||||||
// 上一首
|
// 上一首
|
||||||
addDrawableChild(ButtonWidget.builder(Text.literal("◀◀◀"), button -> {
|
addDrawableChild(ButtonWidget.builder(Text.literal("|◀◀"), button -> {
|
||||||
Main.SONG_PLAYER.playPreviousSong();
|
Main.SONG_PLAYER.playPreviousSong();
|
||||||
}).dimensions(centerX - 100, buttonY, 40, 20).build());
|
}).dimensions(centerX - 100, buttonY, 40, 20).build());
|
||||||
|
|
||||||
@ -148,7 +189,7 @@ public class DiscJockeyScreen extends Screen {
|
|||||||
addDrawableChild(playButton);
|
addDrawableChild(playButton);
|
||||||
|
|
||||||
// 下一首
|
// 下一首
|
||||||
addDrawableChild(ButtonWidget.builder(Text.literal("▶▶▶"), button -> {
|
addDrawableChild(ButtonWidget.builder(Text.literal("▶▶|"), button -> {
|
||||||
Main.SONG_PLAYER.playNextSong();
|
Main.SONG_PLAYER.playNextSong();
|
||||||
}).dimensions(centerX + 60, buttonY, 40, 20).build());
|
}).dimensions(centerX + 60, buttonY, 40, 20).build());
|
||||||
|
|
||||||
@ -274,20 +315,21 @@ public class DiscJockeyScreen extends Screen {
|
|||||||
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
|
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
|
||||||
super.render(context, mouseX, mouseY, delta);
|
super.render(context, mouseX, mouseY, delta);
|
||||||
|
|
||||||
context.drawCenteredTextWithShadow(textRenderer, DROP_HINT, width / 2, 5, 0xFFFFFF);
|
context.drawCenteredTextWithShadow(textRenderer, DROP_HINT, width / 2, 5, 0xFFFFFFFF);
|
||||||
context.drawCenteredTextWithShadow(textRenderer, SELECT_SONG, width / 2, 20, 0xFFFFFF);
|
context.drawCenteredTextWithShadow(textRenderer, SELECT_SONG, width / 2, 20, 0xFFFFFFFF);
|
||||||
|
|
||||||
// 显示当前文件夹和播放模式
|
// 显示当前文件夹和播放模式
|
||||||
String folderName = currentFolder == null ? "/" : currentFolder.name;
|
String folderName = currentFolder == null ? "/" : currentFolder.name;
|
||||||
context.drawTextWithShadow(textRenderer, CURRENT_FOLDER.getString() + ": " + folderName, 35, 15, 0xFFFFFF);
|
context.drawTextWithShadow(textRenderer, CURRENT_FOLDER.getString() + ": " + folderName, 35, 15, 0xFFFFFFFF);
|
||||||
context.drawTextWithShadow(textRenderer, PLAY_MODE.getString() + ":", width - 220, 15, 0xFFFFFF);
|
// context.drawTextWithShadow(textRenderer, PLAY_MODE.getString() + ":", width - 220, 15, 0xFFFFFF);
|
||||||
|
|
||||||
int screenWidth = context.getScaledWindowWidth();
|
int screenWidth = context.getScaledWindowWidth();
|
||||||
|
|
||||||
// 进度条
|
// 播放进度条
|
||||||
|
// TODO 关于可拖动什么的以后再加,这里放个TODO防止以后忘了
|
||||||
if (Main.SONG_PLAYER.running && Main.SONG_PLAYER.song != null) {
|
if (Main.SONG_PLAYER.running && Main.SONG_PLAYER.song != null) {
|
||||||
int progressBarX = 10;
|
int progressBarX = 10;
|
||||||
int progressBarY = height - 50; // 按钮上方
|
int progressBarY = height - 52; // 按钮上方
|
||||||
int barWidth = screenWidth - 20;
|
int barWidth = screenWidth - 20;
|
||||||
|
|
||||||
progressBarRenderer.renderProgressBar(
|
progressBarRenderer.renderProgressBar(
|
||||||
@ -297,9 +339,35 @@ public class DiscJockeyScreen extends Screen {
|
|||||||
barWidth,
|
barWidth,
|
||||||
5,
|
5,
|
||||||
Main.SONG_PLAYER.getProgress(),
|
Main.SONG_PLAYER.getProgress(),
|
||||||
Main.SONG_PLAYER.getFormattedTime()
|
Main.SONG_PLAYER.getFormattedTime(),
|
||||||
|
0x8000FF00
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 预览进度条
|
||||||
|
if (Main.PREVIEWER.running && Main.PREVIEWER.song != null) {
|
||||||
|
int progressBarX = 10;
|
||||||
|
int progressBarY = height - 37; // 比上一个低一点
|
||||||
|
int barWidth = screenWidth - 20;
|
||||||
|
|
||||||
|
progressBarRenderer.renderProgressBar(
|
||||||
|
context,
|
||||||
|
progressBarX,
|
||||||
|
progressBarY,
|
||||||
|
barWidth,
|
||||||
|
5,
|
||||||
|
Main.PREVIEWER.getProgress(),
|
||||||
|
Main.PREVIEWER.getFormattedTime(),
|
||||||
|
0x80FF0000
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (configButton != null && configButton.isMouseOver(mouseX, mouseY)) {
|
||||||
|
context.drawTooltip(textRenderer, Text.translatable(Main.MOD_ID + ".screen.open_config"), mouseX, mouseY);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// DebugLogger.log("DiscJockeyScreen: 初始化界面完成");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -6,6 +6,7 @@ import net.minecraft.client.gui.widget.ButtonWidget;
|
|||||||
import net.minecraft.client.util.InputUtil;
|
import net.minecraft.client.util.InputUtil;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
import semmiedev.disc_jockey_revive.DebugLogger;
|
||||||
import semmiedev.disc_jockey_revive.Main;
|
import semmiedev.disc_jockey_revive.Main;
|
||||||
import semmiedev.disc_jockey_revive.Note;
|
import semmiedev.disc_jockey_revive.Note;
|
||||||
import semmiedev.disc_jockey_revive.gui.KeyMappingListWidget;
|
import semmiedev.disc_jockey_revive.gui.KeyMappingListWidget;
|
||||||
@ -34,6 +35,8 @@ public class EditKeyMappingsScreen extends Screen {
|
|||||||
protected void init() {
|
protected void init() {
|
||||||
super.init();
|
super.init();
|
||||||
|
|
||||||
|
DebugLogger.log("EditKeyMappingsScreen: 开始初始化界面");
|
||||||
|
|
||||||
int listTop = 40;
|
int listTop = 40;
|
||||||
int listBottom = this.height - 50;
|
int listBottom = this.height - 50;
|
||||||
int listHeight = listBottom - listTop;
|
int listHeight = listBottom - listTop;
|
||||||
@ -56,6 +59,8 @@ public class EditKeyMappingsScreen extends Screen {
|
|||||||
this.client.setScreen(this.parent);
|
this.client.setScreen(this.parent);
|
||||||
}).dimensions(buttonX, buttonY, buttonWidth, buttonHeight).build();
|
}).dimensions(buttonX, buttonY, buttonWidth, buttonHeight).build();
|
||||||
addDrawableChild(doneButton);
|
addDrawableChild(doneButton);
|
||||||
|
|
||||||
|
DebugLogger.log("EditKeyMappingsScreen: 界面初始化完成");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void refreshMappingList() {
|
private void refreshMappingList() {
|
||||||
@ -90,6 +95,7 @@ public class EditKeyMappingsScreen extends Screen {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
|
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
|
||||||
|
DebugLogger.log("EditKeyMappingsScreen: 按下按键:"+keyCode);
|
||||||
if (waitingForKeyPress) {
|
if (waitingForKeyPress) {
|
||||||
if (keyCode == GLFW.GLFW_KEY_ESCAPE) {
|
if (keyCode == GLFW.GLFW_KEY_ESCAPE) {
|
||||||
|
|
||||||
@ -129,11 +135,11 @@ public class EditKeyMappingsScreen extends Screen {
|
|||||||
@Override
|
@Override
|
||||||
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
|
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
|
||||||
super.render(context, mouseX, mouseY, delta);
|
super.render(context, mouseX, mouseY, delta);
|
||||||
context.drawCenteredTextWithShadow(textRenderer, TITLE, this.width / 2, 10, 0xFFFFFF);
|
context.drawCenteredTextWithShadow(textRenderer, TITLE, this.width / 2, 10, 0xFFFFFFFF);
|
||||||
if (waitingForKeyPress) {
|
if (waitingForKeyPress) {
|
||||||
|
|
||||||
context.fill(0, 0, this.width, this.height, 0x80000000);
|
context.fill(0, 0, this.width, this.height, 0x80000000);
|
||||||
context.drawCenteredTextWithShadow(textRenderer, PRESS_KEY_INSTRUCTION, this.width / 2, this.height / 2 - 10, 0xFFFFFF);
|
context.drawCenteredTextWithShadow(textRenderer, PRESS_KEY_INSTRUCTION, this.width / 2, this.height / 2 - 10, 0xFFFFFFFF);
|
||||||
}
|
}
|
||||||
mappingListWidget.render(context, mouseX, mouseY, delta);
|
mappingListWidget.render(context, mouseX, mouseY, delta);
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,8 @@ public class LiveDjScreen extends Screen {
|
|||||||
protected void init() {
|
protected void init() {
|
||||||
super.init();
|
super.init();
|
||||||
|
|
||||||
|
DebugLogger.log("LiveDjScreen: 开始初始化界面");
|
||||||
|
|
||||||
int centerX = this.width / 2;
|
int centerX = this.width / 2;
|
||||||
int buttonWidth = 150;
|
int buttonWidth = 150;
|
||||||
int buttonHeight = 20;
|
int buttonHeight = 20;
|
||||||
@ -50,13 +52,14 @@ public class LiveDjScreen extends Screen {
|
|||||||
Main.LIVE_DJ_PLAYER.startTuning();
|
Main.LIVE_DJ_PLAYER.startTuning();
|
||||||
}).dimensions(centerX + margin, buttonY, buttonWidth, buttonHeight).build();
|
}).dimensions(centerX + margin, buttonY, buttonWidth, buttonHeight).build();
|
||||||
addDrawableChild(startTuningButton);
|
addDrawableChild(startTuningButton);
|
||||||
|
DebugLogger.log("LiveDjScreen: 界面初始化完成");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
|
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
|
||||||
super.render(context, mouseX, mouseY, delta);
|
super.render(context, mouseX, mouseY, delta);
|
||||||
context.drawCenteredTextWithShadow(textRenderer, TITLE, this.width / 2, 10, 0xFFFFFF);
|
context.drawCenteredTextWithShadow(textRenderer, TITLE, this.width / 2, 10, 0xFFFFFFFF);
|
||||||
context.drawCenteredTextWithShadow(textRenderer, INSTRUCTIONS, this.width / 2, 30, 0xFFFFFF);
|
context.drawCenteredTextWithShadow(textRenderer, INSTRUCTIONS, this.width / 2, 30, 0xFFFFFFFF);
|
||||||
|
|
||||||
Text tuningStatusText;
|
Text tuningStatusText;
|
||||||
if (Main.LIVE_DJ_PLAYER.getNoteBlocks() == null) {
|
if (Main.LIVE_DJ_PLAYER.getNoteBlocks() == null) {
|
||||||
@ -109,7 +112,7 @@ public class LiveDjScreen extends Screen {
|
|||||||
startTuningButton.active = false;
|
startTuningButton.active = false;
|
||||||
startTuningButton.visible = false;
|
startTuningButton.visible = false;
|
||||||
}
|
}
|
||||||
context.drawCenteredTextWithShadow(textRenderer, tuningStatusText, this.width / 2, 50, 0xFFFFFF);
|
context.drawCenteredTextWithShadow(textRenderer, tuningStatusText, this.width / 2, 50, 0xFFFFFFFF);
|
||||||
|
|
||||||
|
|
||||||
if (!Main.LIVE_DJ_PLAYER.missingInstrumentBlocks.isEmpty()) {
|
if (!Main.LIVE_DJ_PLAYER.missingInstrumentBlocks.isEmpty()) {
|
||||||
@ -125,6 +128,7 @@ public class LiveDjScreen extends Screen {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
|
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
|
||||||
|
DebugLogger.log("LiveDjScreen: 按下按键"+keyCode);
|
||||||
InputUtil.Key key = InputUtil.fromKeyCode(keyCode, scanCode);
|
InputUtil.Key key = InputUtil.fromKeyCode(keyCode, scanCode);
|
||||||
if (keyCode == GLFW.GLFW_KEY_ESCAPE) {
|
if (keyCode == GLFW.GLFW_KEY_ESCAPE) {
|
||||||
this.close();
|
this.close();
|
||||||
|
@ -15,6 +15,7 @@ import net.minecraft.util.Identifier;
|
|||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
import semmiedev.disc_jockey_revive.DebugLogger;
|
||||||
import semmiedev.disc_jockey_revive.Main;
|
import semmiedev.disc_jockey_revive.Main;
|
||||||
import semmiedev.disc_jockey_revive.Note;
|
import semmiedev.disc_jockey_revive.Note;
|
||||||
import semmiedev.disc_jockey_revive.KeyMappingManager;
|
import semmiedev.disc_jockey_revive.KeyMappingManager;
|
||||||
@ -46,12 +47,14 @@ public class SelectNoteScreen extends Screen {
|
|||||||
protected void init() {
|
protected void init() {
|
||||||
super.init();
|
super.init();
|
||||||
|
|
||||||
|
DebugLogger.log("SelectNoteScreen: 开始初始化界面");
|
||||||
|
|
||||||
int centerX = this.width / 2;
|
int centerX = this.width / 2;
|
||||||
int startY = this.height / 2 - 50;
|
int startY = this.height / 2 - 50;
|
||||||
int widgetWidth = 200;
|
int widgetWidth = 200;
|
||||||
int widgetHeight = 20;
|
int widgetHeight = 20;
|
||||||
int margin = 5;
|
int margin = 5;
|
||||||
CyclingButtonWidget<NoteBlockInstrument> instrumentButton = CyclingButtonWidget.builder((NoteBlockInstrument instrument) -> Text.translatable("block.minecraft.note_block.instrument." + instrument.asString()))
|
CyclingButtonWidget<NoteBlockInstrument> instrumentButton = CyclingButtonWidget.builder((NoteBlockInstrument instrument) -> Text.translatable("" + instrument.asString()))
|
||||||
.values(NoteBlockInstrument.values())
|
.values(NoteBlockInstrument.values())
|
||||||
.initially(selectedInstrument)
|
.initially(selectedInstrument)
|
||||||
|
|
||||||
@ -82,6 +85,8 @@ public class SelectNoteScreen extends Screen {
|
|||||||
this.client.setScreen(this.parent);
|
this.client.setScreen(this.parent);
|
||||||
parent.stopWaitingForKeyPress();
|
parent.stopWaitingForKeyPress();
|
||||||
}).dimensions(cancelButtonX, buttonY, buttonWidth, widgetHeight).build());
|
}).dimensions(cancelButtonX, buttonY, buttonWidth, widgetHeight).build());
|
||||||
|
|
||||||
|
DebugLogger.log("SelectNoteScreen: 界面初始化完成");
|
||||||
}
|
}
|
||||||
private class CustomPitchSlider extends SliderWidget {
|
private class CustomPitchSlider extends SliderWidget {
|
||||||
public CustomPitchSlider(int x, int y, int width, int height, Text text, double value) {
|
public CustomPitchSlider(int x, int y, int width, int height, Text text, double value) {
|
||||||
@ -142,7 +147,7 @@ public class SelectNoteScreen extends Screen {
|
|||||||
|
|
||||||
super.render(context, mouseX, mouseY, delta);
|
super.render(context, mouseX, mouseY, delta);
|
||||||
|
|
||||||
context.drawCenteredTextWithShadow(textRenderer, TITLE, this.width / 2, 10, 0xFFFFFF);
|
context.drawCenteredTextWithShadow(textRenderer, TITLE, this.width / 2, 10, 0xFFFFFFFF);
|
||||||
|
|
||||||
context.drawCenteredTextWithShadow(textRenderer, Text.translatable(Main.MOD_ID + ".screen.select_note.mapping_key", Text.translatable(keyToMap.getTranslationKey())), this.width / 2, 30, 0xFFFFFF);
|
context.drawCenteredTextWithShadow(textRenderer, Text.translatable(Main.MOD_ID + ".screen.select_note.mapping_key", Text.translatable(keyToMap.getTranslationKey())), this.width / 2, 30, 0xFFFFFF);
|
||||||
}
|
}
|
||||||
@ -154,6 +159,7 @@ public class SelectNoteScreen extends Screen {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
|
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
|
||||||
|
DebugLogger.log("SelectNoteScreen: 按下按键"+keyCode);
|
||||||
|
|
||||||
if (keyCode == GLFW.GLFW_KEY_ESCAPE) {
|
if (keyCode == GLFW.GLFW_KEY_ESCAPE) {
|
||||||
this.client.setScreen(this.parent);
|
this.client.setScreen(this.parent);
|
||||||
|
@ -32,25 +32,41 @@ public class ClientWorldMixin {
|
|||||||
boolean useDistance, long seed,
|
boolean useDistance, long seed,
|
||||||
CallbackInfo ci
|
CallbackInfo ci
|
||||||
) {
|
) {
|
||||||
if (
|
boolean isNoteBlockSound = event.id().getPath().startsWith("block.note_block");
|
||||||
((Main.config.omnidirectionalNoteBlockSounds && Main.SONG_PLAYER.running) || Main.PREVIEWER.running) &&
|
|
||||||
event.id().getPath().startsWith("block.note_block")
|
if (Main.config.forceOmnidirectionalNoteBlockSounds && isNoteBlockSound) {
|
||||||
) {
|
|
||||||
ci.cancel();
|
ci.cancel();
|
||||||
client.getSoundManager().play(
|
playOmnidirectionalSound(event, category, volume, pitch, seed);
|
||||||
new PositionedSoundInstance(
|
return;
|
||||||
event.id(),
|
}
|
||||||
category,
|
|
||||||
volume,
|
if (Main.config.omnidirectionalNoteBlockSounds &&
|
||||||
pitch,
|
(Main.SONG_PLAYER.running || Main.PREVIEWER.running) &&
|
||||||
Random.create(seed),
|
isNoteBlockSound) {
|
||||||
false,
|
ci.cancel();
|
||||||
0,
|
playOmnidirectionalSound(event, category, volume, pitch, seed);
|
||||||
SoundInstance.AttenuationType.NONE,
|
|
||||||
0, 0, 0,
|
|
||||||
true
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void playOmnidirectionalSound(
|
||||||
|
SoundEvent event,
|
||||||
|
SoundCategory category,
|
||||||
|
float volume, float pitch,
|
||||||
|
long seed
|
||||||
|
) {
|
||||||
|
client.getSoundManager().play(
|
||||||
|
new PositionedSoundInstance(
|
||||||
|
event.id(),
|
||||||
|
category,
|
||||||
|
volume,
|
||||||
|
pitch,
|
||||||
|
Random.create(seed),
|
||||||
|
false,
|
||||||
|
0,
|
||||||
|
SoundInstance.AttenuationType.NONE,
|
||||||
|
0, 0, 0,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -93,5 +93,23 @@
|
|||||||
"disc_jockey_revive.player.invalid_state_tuning": "Cannot tune: Invalid game state or mode.",
|
"disc_jockey_revive.player.invalid_state_tuning": "Cannot tune: Invalid game state or mode.",
|
||||||
"disc_jockey_revive.player.tuned": "Tuning completed。",
|
"disc_jockey_revive.player.tuned": "Tuning completed。",
|
||||||
"text.autoconfig.disc_jockey_revive.option.debugModeEnabled": "Enable Debug Mode",
|
"text.autoconfig.disc_jockey_revive.option.debugModeEnabled": "Enable Debug Mode",
|
||||||
"text.autoconfig.disc_jockey_revive.option.debugModeEnabled.@Tooltip": "Enables verbose logging for debugging purposes. \nKeep off unless troubleshooting. \nOf course, many debug-related parts have already been removed."
|
"text.autoconfig.disc_jockey_revive.option.debugModeEnabled.@Tooltip": "Enable detailed logging for debugging.\nKeep it off unless troubleshooting.\nOf course, many debug parts have been removed.\nEnabling this may cause the log file to be too large.\nHonestly, it's not really helpful for you.",
|
||||||
|
"disc_jockey_revive.screen.speed": "Speed",
|
||||||
|
"disc_jockey_revive.screen.speed_value": "Speed: %.2fx",
|
||||||
|
|
||||||
|
"text.autoconfig.disc_jockey_revive.option.playbackFailureAction": "On Playback Failure",
|
||||||
|
"text.autoconfig.disc_jockey_revive.option.playbackFailureAction.@Tooltip": "Action when playback fails due to missing note blocks\nOptions: Stop (default) or Play Next Song",
|
||||||
|
|
||||||
|
"disc_jockey_revive.playback_failure.stop": "Stop playback",
|
||||||
|
"disc_jockey_revive.playback_failure.next": "Play next song",
|
||||||
|
"disc_jockey_revive.playback_failure.next_message": "Playback failure handling: Play next song.",
|
||||||
|
|
||||||
|
"command.failure_action.set": "Playback failure action set to: %s",
|
||||||
|
|
||||||
|
"text.autoconfig.disc_jockey_revive.option.forceOmnidirectionalNoteBlockSounds": "Force Omnidirectional Note Blocks",
|
||||||
|
"text.autoconfig.disc_jockey_revive.option.forceOmnidirectionalNoteBlockSounds.@Tooltip": "Forces all note block sounds to be omnidirectional at all times.\nOverrides the regular omnidirectional setting.",
|
||||||
|
"disc_jockey_revive.screen.open_config": "Open Mod Settings",
|
||||||
|
|
||||||
|
"text.autoconfig.disc_jockey_revive.option.debugModeChatMessages": "Debug mode chat messages",
|
||||||
|
"text.autoconfig.disc_jockey_revive.option.debugModeChatMessages.@Tooltip": "Enable detailed logging output to chat\nPlease enable debug mode first"
|
||||||
}
|
}
|
||||||
|
@ -54,10 +54,10 @@
|
|||||||
"text.autoconfig.disc_jockey_revive.option.delayPlaybackStartBySecs.@Tooltip": "调音完成后延迟指定秒数再开始播放(如 0.5 表示延迟半秒)。",
|
"text.autoconfig.disc_jockey_revive.option.delayPlaybackStartBySecs.@Tooltip": "调音完成后延迟指定秒数再开始播放(如 0.5 表示延迟半秒)。",
|
||||||
"disc_jockey_revive.screen.current_folder": "当前文件夹",
|
"disc_jockey_revive.screen.current_folder": "当前文件夹",
|
||||||
"disc_jockey_revive.screen.play_mode": "播放模式",
|
"disc_jockey_revive.screen.play_mode": "播放模式",
|
||||||
"disc_jockey_revive.screen.mode_single": "单曲循环",
|
"disc_jockey_revive.screen.mode_single": "🔂单曲循环",
|
||||||
"disc_jockey_revive.screen.mode_list": "列表循环",
|
"disc_jockey_revive.screen.mode_list": "🔁列表循环",
|
||||||
"disc_jockey_revive.screen.mode_random": "随机播放",
|
"disc_jockey_revive.screen.mode_random": "🔀随机播放",
|
||||||
"disc_jockey_revive.screen.mode_stop": "播完停止",
|
"disc_jockey_revive.screen.mode_stop": "⏹播完停止",
|
||||||
"disc_jockey_revive.screen.open_folder": "打开文件夹",
|
"disc_jockey_revive.screen.open_folder": "打开文件夹",
|
||||||
"disc_jockey_revive.screen.open_folder_failed": "无法打开文件夹",
|
"disc_jockey_revive.screen.open_folder_failed": "无法打开文件夹",
|
||||||
"disc_jockey_revive.screen.reload": "重新加载",
|
"disc_jockey_revive.screen.reload": "重新加载",
|
||||||
@ -93,5 +93,23 @@
|
|||||||
"disc_jockey_revive.player.invalid_state_tuning": "无法调音:游戏状态或模式无效。",
|
"disc_jockey_revive.player.invalid_state_tuning": "无法调音:游戏状态或模式无效。",
|
||||||
"disc_jockey_revive.player.tuned": "调音完成。",
|
"disc_jockey_revive.player.tuned": "调音完成。",
|
||||||
"text.autoconfig.disc_jockey_revive.option.debugModeEnabled": "启用调试模式",
|
"text.autoconfig.disc_jockey_revive.option.debugModeEnabled": "启用调试模式",
|
||||||
"text.autoconfig.disc_jockey_revive.option.debugModeEnabled.@Tooltip": "启用详细日志输出以进行调试。\n除非排查问题,否则请保持关闭。\n当然,很多调试用的部分已经移除。"
|
"text.autoconfig.disc_jockey_revive.option.debugModeEnabled.@Tooltip": "启用详细日志输出以进行调试。\n除非排查问题,否则请保持关闭。\n当然,很多调试用的部分已经移除。\n开启这个可能会导致日志文件占用过大\n老实说,其实这对你并没有什么帮助",
|
||||||
|
"disc_jockey_revive.screen.speed": "速度",
|
||||||
|
"disc_jockey_revive.screen.speed_value": "速度: %.2fx",
|
||||||
|
|
||||||
|
"text.autoconfig.disc_jockey_revive.option.playbackFailureAction": "播放失败处理",
|
||||||
|
"text.autoconfig.disc_jockey_revive.option.playbackFailureAction.@Tooltip": "当因缺少音符盒导致播放失败时的处理方式\n选项: 停止播放(默认) 或 播放下一首",
|
||||||
|
|
||||||
|
"disc_jockey_revive.playback_failure.stop": "停止播放",
|
||||||
|
"disc_jockey_revive.playback_failure.next": "播放下一首",
|
||||||
|
"disc_jockey_revive.playback_failure.next_message": "播放失败处理:播放下一首",
|
||||||
|
|
||||||
|
"command.failure_action.set": "播放失败处理方式已设置为: %s",
|
||||||
|
|
||||||
|
"text.autoconfig.disc_jockey_revive.option.forceOmnidirectionalNoteBlockSounds": "强制全向音符盒音效",
|
||||||
|
"text.autoconfig.disc_jockey_revive.option.forceOmnidirectionalNoteBlockSounds.@Tooltip": "强制所有音符盒音效始终保持全向传播\n会覆盖常规的全向音符盒设置",
|
||||||
|
"disc_jockey_revive.screen.open_config": "打开模组设置",
|
||||||
|
|
||||||
|
"text.autoconfig.disc_jockey_revive.option.debugModeChatMessages": "调试模式聊天框消息",
|
||||||
|
"text.autoconfig.disc_jockey_revive.option.debugModeChatMessages.@Tooltip": "启用将详细日志输出到聊天框\n请先启用调试模式"
|
||||||
}
|
}
|
||||||
|
BIN
src/main/resources/assets/disc_jockey/sounds/hello_test.ogg
Normal file
BIN
src/main/resources/assets/disc_jockey/sounds/hello_test.ogg
Normal file
Binary file not shown.
@ -2,7 +2,7 @@
|
|||||||
"required": true,
|
"required": true,
|
||||||
"minVersion": "0.8",
|
"minVersion": "0.8",
|
||||||
"package": "semmiedev.disc_jockey_revive.mixin",
|
"package": "semmiedev.disc_jockey_revive.mixin",
|
||||||
"compatibilityLevel": "JAVA_21",
|
"compatibilityLevel": "{{COMPATIBILITY_LEVEL}}",
|
||||||
"mixins": [
|
"mixins": [
|
||||||
"ClientWorldMixin"
|
"ClientWorldMixin"
|
||||||
],
|
],
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"schemaVersion": 1,
|
"schemaVersion": 1,
|
||||||
"id": "disc_jockey_revive",
|
"id": "disc_jockey_revive",
|
||||||
"version": "${version}",
|
"version": "${version}",
|
||||||
"name": "Disc Jockey Revive",
|
"name": "${name}",
|
||||||
"description": "在游戏中播放音符盒(打碟机)",
|
"description": "在游戏中播放音符盒(打碟机)",
|
||||||
"authors": [
|
"authors": [
|
||||||
"SemmieDev",
|
"SemmieDev",
|
||||||
@ -10,7 +10,7 @@
|
|||||||
"BRanulf(仅限该版本,请支持上面两个原作者)"
|
"BRanulf(仅限该版本,请支持上面两个原作者)"
|
||||||
],
|
],
|
||||||
"contact": {
|
"contact": {
|
||||||
"homepage": "https://git.branulf.top/Branulf/DIsc_Jockey_revive",
|
"homepage": "https://git.branulf.top/Branulf",
|
||||||
"sources": "https://git.branulf.top/Branulf/DIsc_Jockey_revive"
|
"sources": "https://git.branulf.top/Branulf/DIsc_Jockey_revive"
|
||||||
},
|
},
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@ -28,8 +28,9 @@
|
|||||||
"disc_jockey.mixins.json"
|
"disc_jockey.mixins.json"
|
||||||
],
|
],
|
||||||
"depends": {
|
"depends": {
|
||||||
|
"fabricloader": ">=${loader_version}",
|
||||||
"fabric": "*",
|
"fabric": "*",
|
||||||
"minecraft": "~1.21.4",
|
"minecraft": "${minecraft_version}",
|
||||||
"java": ">=21",
|
"java": ">=21",
|
||||||
"cloth-config": "*"
|
"cloth-config": "*"
|
||||||
}
|
}
|
||||||
|
11
versions/1.21.4/gradle.properties
Normal file
11
versions/1.21.4/gradle.properties
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
minecraft_version=1.21.4
|
||||||
|
yarn_mappings=1.21.4+build.8
|
||||||
|
|
||||||
|
minecraft_dependency=1.21.4
|
||||||
|
|
||||||
|
game_versions=1.21.4
|
||||||
|
|
||||||
|
fabric_api_version=0.119.2+1.21.4
|
||||||
|
|
||||||
|
modmenu_version=13.0.3
|
||||||
|
cloth_config_version=17.0.144
|
11
versions/1.21.5/gradle.properties
Normal file
11
versions/1.21.5/gradle.properties
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
minecraft_version=1.21.5
|
||||||
|
yarn_mappings=1.21.5+build.1
|
||||||
|
|
||||||
|
minecraft_dependency=1.21.5
|
||||||
|
|
||||||
|
game_versions=1.21.5
|
||||||
|
|
||||||
|
fabric_api_version=0.119.5+1.21.5
|
||||||
|
|
||||||
|
modmenu_version=14.0.0-rc.2
|
||||||
|
cloth_config_version=18.0.145
|
11
versions/1.21.6/gradle.properties
Normal file
11
versions/1.21.6/gradle.properties
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
minecraft_version=1.21.6
|
||||||
|
yarn_mappings=1.21.6+build.1
|
||||||
|
|
||||||
|
minecraft_dependency=1.21.6
|
||||||
|
|
||||||
|
game_versions=1.21.6
|
||||||
|
|
||||||
|
fabric_api_version=0.127.0+1.21.6
|
||||||
|
|
||||||
|
modmenu_version=15.0.0-beta.3
|
||||||
|
cloth_config_version=19.0.147
|
11
versions/1.21.7/gradle.properties
Normal file
11
versions/1.21.7/gradle.properties
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
minecraft_version=1.21.7
|
||||||
|
yarn_mappings=1.21.7+build.7
|
||||||
|
|
||||||
|
minecraft_dependency=1.21.7
|
||||||
|
|
||||||
|
game_versions=1.21.7
|
||||||
|
|
||||||
|
fabric_api_version=0.128.1+1.21.7
|
||||||
|
|
||||||
|
modmenu_version=15.0.0-beta.3
|
||||||
|
cloth_config_version=19.0.147
|
11
versions/1.21.8/gradle.properties
Normal file
11
versions/1.21.8/gradle.properties
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
minecraft_version=1.21.8
|
||||||
|
yarn_mappings=1.21.8+build.1
|
||||||
|
|
||||||
|
minecraft_dependency=1.21.8
|
||||||
|
|
||||||
|
game_versions=1.21.8
|
||||||
|
|
||||||
|
fabric_api_version=0.129.0+1.21.8
|
||||||
|
|
||||||
|
modmenu_version=15.0.0-beta.3
|
||||||
|
cloth_config_version=19.0.147
|
1
versions/mainProject
Normal file
1
versions/mainProject
Normal file
@ -0,0 +1 @@
|
|||||||
|
1.21.4
|
0
versions/mapping_12105_12104.txt
Normal file
0
versions/mapping_12105_12104.txt
Normal file
0
versions/mapping_12106_12105.txt
Normal file
0
versions/mapping_12106_12105.txt
Normal file
0
versions/mapping_12107_12106.txt
Normal file
0
versions/mapping_12107_12106.txt
Normal file
0
versions/mapping_12108_12107.txt
Normal file
0
versions/mapping_12108_12107.txt
Normal file
Loading…
x
Reference in New Issue
Block a user