mirror of
https://github.com/TheWhiteDog9487/WhoProvideThisKeybind.git
synced 2026-09-16 15:04:19 +08:00
⭐ init: 完成
This commit is contained in:
@@ -0,0 +1,9 @@
|
|||||||
|
#
|
||||||
|
# https://help.github.com/articles/dealing-with-line-endings/
|
||||||
|
#
|
||||||
|
# Linux start script should use lf
|
||||||
|
/gradlew text eol=lf
|
||||||
|
|
||||||
|
# These are Windows script files and should use crlf
|
||||||
|
*.bat text eol=crlf
|
||||||
|
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# Automatically build the project and run any configured tests for every push
|
||||||
|
# and submitted pull request. This can help catch issues that only occur on
|
||||||
|
# certain platforms or Java versions, and provides a first line of defence
|
||||||
|
# against bad commits.
|
||||||
|
|
||||||
|
name: build
|
||||||
|
on: [pull_request, push]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: checkout repository
|
||||||
|
uses: actions/checkout@v6
|
||||||
|
- name: validate gradle wrapper
|
||||||
|
uses: gradle/actions/wrapper-validation@v6
|
||||||
|
- name: setup jdk
|
||||||
|
uses: actions/setup-java@v5
|
||||||
|
with:
|
||||||
|
java-version: '25'
|
||||||
|
distribution: 'microsoft'
|
||||||
|
- name: make gradle wrapper executable
|
||||||
|
run: chmod +x ./gradlew
|
||||||
|
- name: build
|
||||||
|
run: ./gradlew build
|
||||||
|
- name: capture build artifacts
|
||||||
|
uses: actions/upload-artifact@v7
|
||||||
|
with:
|
||||||
|
name: Artifacts
|
||||||
|
path: build/libs/
|
||||||
+40
@@ -0,0 +1,40 @@
|
|||||||
|
# gradle
|
||||||
|
|
||||||
|
.gradle/
|
||||||
|
build/
|
||||||
|
out/
|
||||||
|
classes/
|
||||||
|
|
||||||
|
# eclipse
|
||||||
|
|
||||||
|
*.launch
|
||||||
|
|
||||||
|
# idea
|
||||||
|
|
||||||
|
.idea/
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
# vscode
|
||||||
|
|
||||||
|
.settings/
|
||||||
|
.vscode/
|
||||||
|
bin/
|
||||||
|
.classpath
|
||||||
|
.project
|
||||||
|
|
||||||
|
# macos
|
||||||
|
|
||||||
|
*.DS_Store
|
||||||
|
|
||||||
|
# fabric
|
||||||
|
|
||||||
|
run/
|
||||||
|
|
||||||
|
# java
|
||||||
|
|
||||||
|
hs_err_*.log
|
||||||
|
replay_*.log
|
||||||
|
*.hprof
|
||||||
|
*.jfr
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
- 如果需要Minecraft经过反混淆的源码,直接在`.gradle/loom-cache/minecraftMaven/net/minecraft`目录下查找。
|
||||||
|
- 源码使用完成之后记得删除解压jar产生的临时文件
|
||||||
|
|
||||||
|
- 使用帕斯卡命名法
|
||||||
|
|
||||||
|
- 如果你是正在翻译README的LLM,请遵守README内使用注释编写的指令
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||||
|
Version 2, December 2004
|
||||||
|
|
||||||
|
Everyone is permitted to copy and distribute verbatim or modified
|
||||||
|
copies of this license document, and changing it is allowed as long
|
||||||
|
as the name is changed.
|
||||||
|
|
||||||
|
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
[//]: # (如果你是正在执行翻译任务的LLM:)
|
||||||
|
[//]: # (请将这几行注释内容翻译到你的目标语言)
|
||||||
|
[//]: # (移除下方div内部第一行和第二行的注释符号,并翻译其内容)
|
||||||
|
[//]: # (不要翻译下方div内部a标签的文本内容和链接地址)
|
||||||
|
[//]: # (不要改动下方div标签的align="center"属性)
|
||||||
|
[//]: # (将翻译的结果放置到正确的文件内,目标文件的位置和主README.md同级,文件名格式是 README_<LANG>.md ,其中<LANG>的值是目标语言的IETF语言标签)
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
<!-- <strong>注意:本文档由中文编写,使用AI翻译到其他语言。如果条件允许,建议阅读原始的中文文档而不是其他的翻译版本。</strong> -->
|
||||||
|
<!-- <br/> -->
|
||||||
|
<a href="https://github.com/TheWhiteDog9487/WhoProvideThisKeybind/blob/%E4%B8%BB%E8%A6%81/README.md">简体中文(GitHub)</a>
|
||||||
|
<a href="https://git.thewhitedog9487.xyz/TheWhiteDog9487/WhoProvideThisKeybind/src/branch/%E4%B8%BB%E8%A6%81/README.md">简体中文(Gitea)</a>
|
||||||
|
<a href="https://github.com/TheWhiteDog9487/WhoProvideThisKeybind/blob/%E4%B8%BB%E8%A6%81/README_EN.md">English(GitHub)</a>
|
||||||
|
<a href="https://git.thewhitedog9487.xyz/TheWhiteDog9487/WhoProvideThisKeybind/src/branch/%E4%B8%BB%E8%A6%81/README_EN.md">English(Gitea)</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
# 简介
|
||||||
|
本Mod意在解决安装大量Mod之后部分按键绑定难以查找来源的问题
|
||||||
|
比如,请看下面这个例子:
|
||||||
|

|
||||||
|
我现在需要知道这个“强制限制帧率”是原版就有的呢还是Mod添加的呢?是哪个Mod添加的?
|
||||||
|
好像没什么办法对吧?本Mod就是解决这个问题的
|
||||||
|
|
||||||
|
# 功能
|
||||||
|
在更改绑定按键的按钮上显示悬浮文字,显示该按键由哪个Mod提供
|
||||||
|

|
||||||
|
|
||||||
|
默认配置下为了不对用户造成干扰,因此不显示对普通玩家没有意义的信息
|
||||||
|
如果你需要的话,可以在配置页面里启用其他功能
|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
# 重要提示
|
||||||
|
**本Mod无法保证结果100%准确!**
|
||||||
|
像是CarryOn,AxolotlClient等少部分Mod注册绑定时不会提供自身信息或者提供的信息不准确,导致本Mod无法判断具体来源或者出现错判
|
||||||
|
如果出现这种情况,请向对应Mod的开发者提交反馈,让其更正按键绑定ID到正确的格式
|
||||||
|
|
||||||
|
# 兼容性
|
||||||
|
如果您使用的Mod替换或者大幅修改了原版Minecraft的按键绑定配置界面,那么就有可能出现兼容性问题
|
||||||
|
如有遇到,请在[Github仓库](https://github.com/TheWhiteDog9487/WhoProvideThisKeybind/issues)开启一个issue,我会视具体情况尽力协助
|
||||||
|
|
||||||
|
# 配置文件
|
||||||
|
- 如果你开启了版本隔离,它应当位于`.minecraft\versions\<版本名>\config\WhoProvideThisKeybind.json5`
|
||||||
|
- 如果没有版本隔离,它应该在`.minecraft\config\WhoProvideThisKeybind.json5`
|
||||||
|
|
||||||
|
这就是一个普通的json文本文件,只不过json5支持诸如注释等更多特性而已。
|
||||||
|
所有的属性都有注释,包括功能、取值范围、类型、默认值等。
|
||||||
|
使用普通的文本编辑器打开即可进行修改。
|
||||||
|
你可以直接在游戏运行时编辑配置文件,保存之后会自动应用到游戏内。
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
<div align="center">
|
||||||
|
<strong>Note: This document was originally written in Chinese and translated to other languages using AI. If possible, it is recommended to read the original Chinese document instead of other translations.</strong>
|
||||||
|
<br/>
|
||||||
|
<a href="https://github.com/TheWhiteDog9487/WhoProvideThisKeybind/blob/%E4%B8%BB%E8%A6%81/README.md">简体中文(GitHub)</a>
|
||||||
|
<a href="https://git.thewhitedog9487.xyz/TheWhiteDog9487/WhoProvideThisKeybind/src/branch/%E4%B8%BB%E8%A6%81/README.md">简体中文(Gitea)</a>
|
||||||
|
<a href="https://github.com/TheWhiteDog9487/WhoProvideThisKeybind/blob/%E4%B8%BB%E8%A6%81/README_EN.md">English(GitHub)</a>
|
||||||
|
<a href="https://git.thewhitedog9487.xyz/TheWhiteDog9487/WhoProvideThisKeybind/src/branch/%E4%B8%BB%E8%A6%81/README_EN.md">English(Gitea)</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
# Introduction
|
||||||
|
This mod is designed to solve the problem of not knowing where some keybinds came from after installing many mods.
|
||||||
|
For example, take a look at this case:
|
||||||
|

|
||||||
|
I need to know whether this “Force Limit Framerate” is part of the vanilla game or added by a mod, and if it was added by a mod, which one added it.
|
||||||
|
It seems there is no obvious way to know, right? This mod is built to solve exactly that problem.
|
||||||
|
|
||||||
|
# Features
|
||||||
|
Display hover text on the keybind modification button to show which mod provides that keybind.
|
||||||
|

|
||||||
|
|
||||||
|
By default, to avoid disturbing users, information that is not useful to ordinary players is not shown.
|
||||||
|
If you need it, you can enable additional features in the config screen.
|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
# Important Notes
|
||||||
|
**This mod cannot guarantee 100% accuracy!**
|
||||||
|
Some mods, such as CarryOn, AxolotlClient, and a few others, do not provide their own information when registering keybinds or provide inaccurate information, which means this mod may be unable to determine the actual source or may make incorrect judgments.
|
||||||
|
If this happens, please submit feedback to the corresponding mod developer and ask them to correct the keybind ID format to the proper standard.
|
||||||
|
|
||||||
|
# Compatibility
|
||||||
|
If the mod you use replaces or heavily modifies the vanilla Minecraft keybind configuration interface, compatibility issues may occur.
|
||||||
|
If you encounter this, please open an issue in the [GitHub repository](https://github.com/TheWhiteDog9487/WhoProvideThisKeybind/issues), and I will do my best to help based on the specific situation.
|
||||||
|
|
||||||
|
# Configuration File
|
||||||
|
- If version isolation is enabled, it should be located at `.minecraft\versions\<version name>\config\WhoProvideThisKeybind.json5`
|
||||||
|
- If version isolation is not enabled, it should be located at `.minecraft\config\WhoProvideThisKeybind.json5`
|
||||||
|
|
||||||
|
This is just a normal JSON text file, except that JSON5 supports more features such as comments.
|
||||||
|
All properties are documented, including features, value ranges, types, default values, and more.
|
||||||
|
You can open it with a plain text editor and edit it directly.
|
||||||
|
You can edit the configuration file while the game is running, and the changes will be applied to the game automatically after saving.
|
||||||
@@ -0,0 +1,125 @@
|
|||||||
|
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||||
|
import java.nio.file.Paths
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id("net.fabricmc.fabric-loom")
|
||||||
|
`maven-publish`
|
||||||
|
id("org.jetbrains.kotlin.jvm") version "2.4.10" }
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
// Add repositories to retrieve artifacts from in here.
|
||||||
|
// You should only use this when depending on other mods because
|
||||||
|
// Loom adds the essential maven repositories to download Minecraft and libraries from automatically.
|
||||||
|
// See https://docs.gradle.org/current/userguide/declaring_repositories.html
|
||||||
|
// for more information about repositories.
|
||||||
|
exclusiveContent {
|
||||||
|
forRepository {
|
||||||
|
maven {
|
||||||
|
name = "Modrinth"
|
||||||
|
url = uri("https://api.modrinth.com/maven") } }
|
||||||
|
filter {
|
||||||
|
includeGroup("maven.modrinth") } }
|
||||||
|
maven {
|
||||||
|
name = "Terraformers"
|
||||||
|
url = uri("https://maven.terraformersmc.com/") }
|
||||||
|
maven {
|
||||||
|
name = "Xander Maven"
|
||||||
|
url = uri("https://maven.isxander.dev/releases") } }
|
||||||
|
|
||||||
|
loom {
|
||||||
|
splitEnvironmentSourceSets()
|
||||||
|
accessWidenerPath.set(file("src/main/resources/whoprovidethiskeybind.classtweaker"))
|
||||||
|
|
||||||
|
mods {
|
||||||
|
register("WhoProvideThisKeybind") {
|
||||||
|
sourceSet(sourceSets.main.get())
|
||||||
|
sourceSet(sourceSets.getByName("client")) } } }
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
// To change the versions see the gradle.properties file
|
||||||
|
minecraft("com.mojang:minecraft:${providers.gradleProperty("minecraft_version").get()}")
|
||||||
|
implementation("net.fabricmc:fabric-loader:${providers.gradleProperty("loader_version").get()}")
|
||||||
|
|
||||||
|
// Fabric API. This is technically optional, but you probably want it anyway.
|
||||||
|
implementation("net.fabricmc.fabric-api:fabric-api:${providers.gradleProperty("fabric_api_version").get()}")
|
||||||
|
implementation("net.fabricmc:fabric-language-kotlin:${providers.gradleProperty("fabric_kotlin_version").get()}")
|
||||||
|
|
||||||
|
implementation("com.terraformersmc:modmenu:${providers.gradleProperty("modmenu_version").get()}")
|
||||||
|
implementation("dev.isxander:yet-another-config-lib:${providers.gradleProperty("yacl_version").get()}")
|
||||||
|
|
||||||
|
// 测试用途 ↓
|
||||||
|
// https://modrinth.com/mod/searchables/versions?l=fabric
|
||||||
|
implementation("maven.modrinth:fuuu3xnx:bvFby61J")
|
||||||
|
// https://modrinth.com/mod/controlling/versions?l=fabric
|
||||||
|
implementation("maven.modrinth:xv94TkTM:rAp2jljs")
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.processResources {
|
||||||
|
val version = version
|
||||||
|
inputs.property("version", version)
|
||||||
|
|
||||||
|
filesMatching("fabric.mod.json") {
|
||||||
|
expand("version" to version) } }
|
||||||
|
|
||||||
|
tasks.withType<JavaCompile>().configureEach {
|
||||||
|
options.release = 25 }
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
compilerOptions {
|
||||||
|
jvmTarget = JvmTarget.JVM_25 } }
|
||||||
|
|
||||||
|
java {
|
||||||
|
// 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()
|
||||||
|
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_25
|
||||||
|
targetCompatibility = JavaVersion.VERSION_25 }
|
||||||
|
|
||||||
|
tasks.jar {
|
||||||
|
val projectName = project.name
|
||||||
|
inputs.property("projectName", projectName)
|
||||||
|
|
||||||
|
from("LICENSE") {
|
||||||
|
rename { "${it}_$projectName" } }
|
||||||
|
|
||||||
|
archiveFileName = "${providers.gradleProperty("OutputFileBasename").get()}-${project.version} mc${providers.gradleProperty("minecraft_version").get()}.jar" }
|
||||||
|
|
||||||
|
tasks.named<Jar>("sourcesJar") {
|
||||||
|
archiveFileName = "${providers.gradleProperty("OutputFileBasename").get()}-${project.version} mc${providers.gradleProperty("minecraft_version").get()}-sources.jar"}
|
||||||
|
|
||||||
|
// configure the maven publication
|
||||||
|
publishing {
|
||||||
|
publications {
|
||||||
|
register<MavenPublication>("mavenJava") {
|
||||||
|
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.
|
||||||
|
} }
|
||||||
|
|
||||||
|
afterEvaluate {
|
||||||
|
val MixinJarPath = configurations.loaderLibraries.get().resolvedConfiguration
|
||||||
|
.resolvedArtifacts
|
||||||
|
.find { it.moduleVersion.id.group == "net.fabricmc" && it.moduleVersion.id.name == "sponge-mixin" }!!
|
||||||
|
.file
|
||||||
|
val IsSupportDceVM = Paths.get(System.getProperty("java.home"))
|
||||||
|
.resolve("bin")
|
||||||
|
.resolve("java")
|
||||||
|
.toFile()
|
||||||
|
.let {
|
||||||
|
val ReturnCode = ProcessBuilder(it.absolutePath, "-XX:+AllowEnhancedClassRedefinition", "-version")
|
||||||
|
.start()
|
||||||
|
.waitFor()
|
||||||
|
return@let ReturnCode == 0 }
|
||||||
|
loom.runs.named("client") {
|
||||||
|
jvmArguments.add("-javaagent:${MixinJarPath.absolutePath}")
|
||||||
|
if (IsSupportDceVM == true) jvmArguments.add("-XX:+AllowEnhancedClassRedefinition") }
|
||||||
|
loom.runs.named("server") {
|
||||||
|
jvmArguments.add("-javaagent:${MixinJarPath.absolutePath}")
|
||||||
|
if (IsSupportDceVM == true) jvmArguments.add("-XX:+AllowEnhancedClassRedefinition") } }
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
# Done to increase the memory available to gradle.
|
||||||
|
org.gradle.jvmargs=-Xmx2G
|
||||||
|
org.gradle.parallel=true
|
||||||
|
org.gradle.caching=true
|
||||||
|
|
||||||
|
# IntelliJ IDEA is not yet fully compatible with configuration cache, see: https://github.com/FabricMC/fabric-loom/issues/1349
|
||||||
|
org.gradle.configuration-cache=false
|
||||||
|
|
||||||
|
# Fabric Properties
|
||||||
|
# check these on https://fabricmc.net/develop
|
||||||
|
minecraft_version=26.2
|
||||||
|
loader_version=0.19.5
|
||||||
|
loom_version=1.17-SNAPSHOT
|
||||||
|
fabric_kotlin_version=1.13.13+kotlin.2.4.10
|
||||||
|
|
||||||
|
# Mod Properties
|
||||||
|
version=1.0.0
|
||||||
|
group=xyz.thewhitedog9487
|
||||||
|
|
||||||
|
OutputFileBasename=WhoProvideThisKeybind
|
||||||
|
|
||||||
|
# Dependencies
|
||||||
|
fabric_api_version=0.159.0+26.2
|
||||||
|
|
||||||
|
# https://modrinth.com/mod/modmenu/versions
|
||||||
|
modmenu_version=20.0.1
|
||||||
|
# https://modrinth.com/mod/yacl/versions
|
||||||
|
yacl_version=3.9.6+26.2-fabric
|
||||||
Vendored
BIN
Binary file not shown.
+9
@@ -0,0 +1,9 @@
|
|||||||
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-9.7.0-all.zip
|
||||||
|
networkTimeout=10000
|
||||||
|
retries=0
|
||||||
|
retryBackOffMs=500
|
||||||
|
validateDistributionUrl=true
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
||||||
@@ -0,0 +1,248 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright © 2015 the original authors.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
#
|
||||||
|
# Gradle start up script for POSIX generated by Gradle.
|
||||||
|
#
|
||||||
|
# Important for running:
|
||||||
|
#
|
||||||
|
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||||
|
# noncompliant, but you have some other compliant shell such as ksh or
|
||||||
|
# bash, then to run this script, type that shell name before the whole
|
||||||
|
# command line, like:
|
||||||
|
#
|
||||||
|
# ksh Gradle
|
||||||
|
#
|
||||||
|
# Busybox and similar reduced shells will NOT work, because this script
|
||||||
|
# requires all of these POSIX shell features:
|
||||||
|
# * functions;
|
||||||
|
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||||
|
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||||
|
# * compound commands having a testable exit status, especially «case»;
|
||||||
|
# * various built-in commands including «command», «set», and «ulimit».
|
||||||
|
#
|
||||||
|
# Important for patching:
|
||||||
|
#
|
||||||
|
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||||
|
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||||
|
#
|
||||||
|
# The "traditional" practice of packing multiple parameters into a
|
||||||
|
# space-separated string is a well documented source of bugs and security
|
||||||
|
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||||
|
# options in "$@", and eventually passing that to Java.
|
||||||
|
#
|
||||||
|
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||||
|
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||||
|
# see the in-line comments for details.
|
||||||
|
#
|
||||||
|
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||||
|
# Darwin, MinGW, and NonStop.
|
||||||
|
#
|
||||||
|
# (3) This script is generated from the Groovy template
|
||||||
|
# https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||||
|
# within the Gradle project.
|
||||||
|
#
|
||||||
|
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||||
|
#
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
# Attempt to set APP_HOME
|
||||||
|
|
||||||
|
# Resolve links: $0 may be a link
|
||||||
|
app_path=$0
|
||||||
|
|
||||||
|
# Need this for daisy-chained symlinks.
|
||||||
|
while
|
||||||
|
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||||
|
[ -h "$app_path" ]
|
||||||
|
do
|
||||||
|
ls=$( ls -ld "$app_path" )
|
||||||
|
link=${ls#*' -> '}
|
||||||
|
case $link in #(
|
||||||
|
/*) app_path=$link ;; #(
|
||||||
|
*) app_path=$APP_HOME$link ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# This is normally unused
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
APP_BASE_NAME=${0##*/}
|
||||||
|
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||||
|
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||||
|
|
||||||
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
|
MAX_FD=maximum
|
||||||
|
|
||||||
|
warn () {
|
||||||
|
echo "$*"
|
||||||
|
} >&2
|
||||||
|
|
||||||
|
die () {
|
||||||
|
echo
|
||||||
|
echo "$*"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
} >&2
|
||||||
|
|
||||||
|
# OS specific support (must be 'true' or 'false').
|
||||||
|
cygwin=false
|
||||||
|
msys=false
|
||||||
|
darwin=false
|
||||||
|
nonstop=false
|
||||||
|
case "$( uname )" in #(
|
||||||
|
CYGWIN* ) cygwin=true ;; #(
|
||||||
|
Darwin* ) darwin=true ;; #(
|
||||||
|
MSYS* | MINGW* ) msys=true ;; #(
|
||||||
|
NONSTOP* ) nonstop=true ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Determine the Java command to use to start the JVM.
|
||||||
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
|
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||||
|
else
|
||||||
|
JAVACMD=$JAVA_HOME/bin/java
|
||||||
|
fi
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD=java
|
||||||
|
if ! command -v java >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Increase the maximum file descriptors if we can.
|
||||||
|
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||||
|
case $MAX_FD in #(
|
||||||
|
max*)
|
||||||
|
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||||
|
# shellcheck disable=SC2039,SC3045
|
||||||
|
MAX_FD=$( ulimit -H -n ) ||
|
||||||
|
warn "Could not query maximum file descriptor limit"
|
||||||
|
esac
|
||||||
|
case $MAX_FD in #(
|
||||||
|
'' | soft) :;; #(
|
||||||
|
*)
|
||||||
|
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||||
|
# shellcheck disable=SC2039,SC3045
|
||||||
|
ulimit -n "$MAX_FD" ||
|
||||||
|
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Collect all arguments for the java command, stacking in reverse order:
|
||||||
|
# * args from the command line
|
||||||
|
# * the main class name
|
||||||
|
# * -classpath
|
||||||
|
# * -D...appname settings
|
||||||
|
# * --module-path (only if needed)
|
||||||
|
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||||
|
|
||||||
|
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||||
|
if "$cygwin" || "$msys" ; then
|
||||||
|
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||||
|
|
||||||
|
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||||
|
|
||||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
for arg do
|
||||||
|
if
|
||||||
|
case $arg in #(
|
||||||
|
-*) false ;; # don't mess with options #(
|
||||||
|
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||||
|
[ -e "$t" ] ;; #(
|
||||||
|
*) false ;;
|
||||||
|
esac
|
||||||
|
then
|
||||||
|
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||||
|
fi
|
||||||
|
# Roll the args list around exactly as many times as the number of
|
||||||
|
# args, so each arg winds up back in the position where it started, but
|
||||||
|
# possibly modified.
|
||||||
|
#
|
||||||
|
# NB: a `for` loop captures its iteration list before it begins, so
|
||||||
|
# changing the positional parameters here affects neither the number of
|
||||||
|
# iterations, nor the values presented in `arg`.
|
||||||
|
shift # remove old arg
|
||||||
|
set -- "$@" "$arg" # push replacement arg
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
|
# Collect all arguments for the java command:
|
||||||
|
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||||
|
# and any embedded shellness will be escaped.
|
||||||
|
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||||
|
# treated as '${Hostname}' itself on the command line.
|
||||||
|
|
||||||
|
set -- \
|
||||||
|
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||||
|
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
||||||
|
"$@"
|
||||||
|
|
||||||
|
# Stop when "xargs" is not available.
|
||||||
|
if ! command -v xargs >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "xargs is not available"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Use "xargs" to parse quoted args.
|
||||||
|
#
|
||||||
|
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||||
|
#
|
||||||
|
# In Bash we could simply go:
|
||||||
|
#
|
||||||
|
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||||
|
# set -- "${ARGS[@]}" "$@"
|
||||||
|
#
|
||||||
|
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||||
|
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||||
|
# character that might be a shell metacharacter, then use eval to reverse
|
||||||
|
# that process (while maintaining the separation between arguments), and wrap
|
||||||
|
# the whole thing up as a single "set" statement.
|
||||||
|
#
|
||||||
|
# This will of course break if any of these variables contains a newline or
|
||||||
|
# an unmatched quote.
|
||||||
|
#
|
||||||
|
|
||||||
|
eval "set -- $(
|
||||||
|
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||||
|
xargs -n1 |
|
||||||
|
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||||
|
tr '\n' ' '
|
||||||
|
)" '"$@"'
|
||||||
|
|
||||||
|
exec "$JAVACMD" "$@"
|
||||||
Vendored
+82
@@ -0,0 +1,82 @@
|
|||||||
|
@rem
|
||||||
|
@rem Copyright 2015 the original author or authors.
|
||||||
|
@rem
|
||||||
|
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
@rem you may not use this file except in compliance with the License.
|
||||||
|
@rem You may obtain a copy of the License at
|
||||||
|
@rem
|
||||||
|
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
@rem
|
||||||
|
@rem Unless required by applicable law or agreed to in writing, software
|
||||||
|
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@rem See the License for the specific language governing permissions and
|
||||||
|
@rem limitations under the License.
|
||||||
|
@rem
|
||||||
|
@rem SPDX-License-Identifier: Apache-2.0
|
||||||
|
@rem
|
||||||
|
|
||||||
|
@if "%DEBUG%"=="" @echo off
|
||||||
|
@rem ##########################################################################
|
||||||
|
@rem
|
||||||
|
@rem Gradle startup script for Windows
|
||||||
|
@rem
|
||||||
|
@rem ##########################################################################
|
||||||
|
|
||||||
|
@rem Set local scope for the variables, and ensure extensions are enabled
|
||||||
|
setlocal EnableExtensions
|
||||||
|
|
||||||
|
set DIRNAME=%~dp0
|
||||||
|
if "%DIRNAME%"=="" set DIRNAME=.
|
||||||
|
@rem This is normally unused
|
||||||
|
set APP_BASE_NAME=%~n0
|
||||||
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||||
|
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||||
|
|
||||||
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||||
|
|
||||||
|
@rem Find java.exe
|
||||||
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
|
set JAVA_EXE=java.exe
|
||||||
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
|
if %ERRORLEVEL% equ 0 goto execute
|
||||||
|
|
||||||
|
echo. 1>&2
|
||||||
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||||
|
echo. 1>&2
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
|
"%COMSPEC%" /c exit 1
|
||||||
|
|
||||||
|
:findJavaFromJavaHome
|
||||||
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
|
echo. 1>&2
|
||||||
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||||
|
echo. 1>&2
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
|
"%COMSPEC%" /c exit 1
|
||||||
|
|
||||||
|
:execute
|
||||||
|
@rem Setup the command line
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@rem Execute Gradle
|
||||||
|
@rem endlocal doesn't take effect until after the line is parsed and variables are expanded
|
||||||
|
@rem which allows us to clear the local environment before executing the java command
|
||||||
|
endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel
|
||||||
|
|
||||||
|
:exitWithErrorLevel
|
||||||
|
@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts
|
||||||
|
"%COMSPEC%" /c exit %ERRORLEVEL%
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
pluginManagement {
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
name = "Fabric"
|
||||||
|
url = uri("https://maven.fabricmc.net/") }
|
||||||
|
mavenCentral()
|
||||||
|
gradlePluginPortal() }
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id("net.fabricmc.fabric-loom") version providers.gradleProperty("loom_version") } }
|
||||||
|
|
||||||
|
// Should match your modid
|
||||||
|
rootProject.name = "whoprovidethiskeybind"
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package xyz.thewhitedog9487.client.mixin.Compatibility.Controlling;
|
||||||
|
|
||||||
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
|
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
|
||||||
|
|
||||||
|
public class MixinPlugin implements IMixinConfigPlugin {
|
||||||
|
@Override
|
||||||
|
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
|
||||||
|
return FabricLoader.getInstance().isModLoaded(("controlling")); } }
|
||||||
+30
@@ -0,0 +1,30 @@
|
|||||||
|
package xyz.thewhitedog9487.client.mixin.Compatibility.Controlling;
|
||||||
|
|
||||||
|
import net.minecraft.client.KeyMapping;
|
||||||
|
import net.minecraft.client.gui.components.Button;
|
||||||
|
import org.spongepowered.asm.mixin.Final;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Pseudo;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
import xyz.thewhitedog9487.client.MiscellaneousKt;
|
||||||
|
import xyz.thewhitedog9487.client.SettingsKt;
|
||||||
|
import xyz.thewhitedog9487.client.WhoProvideThisKeybindModClient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <a href="https://modrinth.com/mod/controlling">Controlling</a>把原版的UI直接给换了,因此需要注入到修改之后的UI中
|
||||||
|
*
|
||||||
|
* @see xyz.thewhitedog9487.client.mixin.Compatibility.Controlling.MixinPlugin
|
||||||
|
*/
|
||||||
|
@Pseudo
|
||||||
|
@Mixin(targets = "com.blamejared.controlling.client.NewKeyBindsList$KeyEntry")
|
||||||
|
public abstract class NewKeyBindsListMixin {
|
||||||
|
@Shadow @Final private KeyMapping key;
|
||||||
|
@Shadow @Final private Button btnChangeKeyBinding;
|
||||||
|
@Inject(method = "refreshEntry", at = @At("TAIL"))
|
||||||
|
private void SetNewTooltipInControllingUI(final CallbackInfo ci) {
|
||||||
|
if (SettingsKt.getSettingsInstance().getShowDebugInfo()) {
|
||||||
|
WhoProvideThisKeybindModClient.INSTANCE.getClientLogger().debug("SetNewTooltipInControllingUI函数被调用,Key:{}", key.getName()); }
|
||||||
|
MiscellaneousKt.SetNewTooltip(btnChangeKeyBinding, key); } }
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package xyz.thewhitedog9487.client.mixin;
|
||||||
|
|
||||||
|
import xyz.thewhitedog9487.client.MiscellaneousKt;
|
||||||
|
import xyz.thewhitedog9487.client.SettingsKt;
|
||||||
|
import xyz.thewhitedog9487.client.WhoProvideThisKeybindModClient;
|
||||||
|
import xyz.thewhitedog9487.client.ModInfo;
|
||||||
|
import net.minecraft.client.KeyMapping;
|
||||||
|
import net.minecraft.client.gui.components.Button;
|
||||||
|
import net.minecraft.client.gui.components.Tooltip;
|
||||||
|
import net.minecraft.client.gui.screens.options.controls.KeyBindsList;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
|
import org.spongepowered.asm.mixin.Final;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 针对原版的实现
|
||||||
|
*/
|
||||||
|
@Mixin(KeyBindsList.KeyEntry.class)
|
||||||
|
public abstract class KeyBindsListKeyEntryMixin {
|
||||||
|
@Shadow @Final private KeyMapping key;
|
||||||
|
@Shadow @Final private Button changeButton;
|
||||||
|
|
||||||
|
@Inject(method = "refreshEntry", at = @At("RETURN"))
|
||||||
|
private void SetTooltip(CallbackInfo ci) {
|
||||||
|
if (SettingsKt.getSettingsInstance().getShowDebugInfo()) {
|
||||||
|
WhoProvideThisKeybindModClient.INSTANCE.getClientLogger().debug("SetTooltip函数被调用,Key:{}", key.getName()); }
|
||||||
|
MiscellaneousKt.SetNewTooltip(changeButton, key); } }
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package xyz.thewhitedog9487.client.Event
|
||||||
|
|
||||||
|
import com.google.gson.GsonBuilder
|
||||||
|
import dev.isxander.yacl3.config.v2.api.ConfigClassHandler
|
||||||
|
import dev.isxander.yacl3.config.v2.api.serializer.GsonConfigSerializerBuilder
|
||||||
|
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents
|
||||||
|
import net.minecraft.resources.Identifier
|
||||||
|
import xyz.thewhitedog9487.client.ConfigFilePath
|
||||||
|
import xyz.thewhitedog9487.client.CurrentConfigurationVersionCode
|
||||||
|
import xyz.thewhitedog9487.client.RegisterConfigFileReloadWatcher
|
||||||
|
import xyz.thewhitedog9487.client.Settings
|
||||||
|
import xyz.thewhitedog9487.client.SettingsHandler
|
||||||
|
import xyz.thewhitedog9487.client.SettingsInstance
|
||||||
|
import xyz.thewhitedog9487.client.WhoProvideThisKeybindModClient
|
||||||
|
|
||||||
|
fun RegisterClientLifecycleEvents() {
|
||||||
|
ClientLifecycleEvents.CLIENT_STARTED.register { ClientInstance ->
|
||||||
|
try {
|
||||||
|
SettingsHandler = ConfigClassHandler
|
||||||
|
.createBuilder(Settings::class.java)
|
||||||
|
.id(Identifier.fromNamespaceAndPath(WhoProvideThisKeybindModClient.ModID, "settings_confighandler"))
|
||||||
|
.serializer {
|
||||||
|
GsonConfigSerializerBuilder.create(it)
|
||||||
|
.setPath(ConfigFilePath)
|
||||||
|
.setJson5(true)
|
||||||
|
.appendGsonBuilder(GsonBuilder::setPrettyPrinting)
|
||||||
|
.build() }
|
||||||
|
.build()
|
||||||
|
|
||||||
|
WhoProvideThisKeybindModClient.ClientLogger.info("正在从${ConfigFilePath}加载设置...")
|
||||||
|
SettingsHandler!!.load()
|
||||||
|
SettingsInstance = SettingsHandler!!.instance()
|
||||||
|
if (SettingsInstance.ConfigurationVersionCode != CurrentConfigurationVersionCode) {
|
||||||
|
// 必要时手动处理升降级,现在不必要,就这么办了
|
||||||
|
SettingsInstance.ConfigurationVersionCode = CurrentConfigurationVersionCode
|
||||||
|
SettingsHandler!!.save() }
|
||||||
|
RegisterConfigFileReloadWatcher() }
|
||||||
|
catch (_: NoClassDefFoundError) {
|
||||||
|
SettingsInstance = Settings()
|
||||||
|
WhoProvideThisKeybindModClient.ClientLogger.warn("当前没有安装YetAnotherConfigLib,因此无法在调整和保持Mod配置") } }
|
||||||
|
ClientLifecycleEvents.CLIENT_STOPPING.register { ClientInstance ->
|
||||||
|
if (SettingsHandler == null) return@register
|
||||||
|
WhoProvideThisKeybindModClient.ClientLogger.info("正在保存设置到$ConfigFilePath...")
|
||||||
|
SettingsHandler!!.save() } }
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package xyz.thewhitedog9487.client
|
||||||
|
|
||||||
|
import net.fabricmc.loader.api.FabricLoader
|
||||||
|
import net.fabricmc.loader.api.ModContainer
|
||||||
|
import net.fabricmc.loader.api.metadata.ModMetadata
|
||||||
|
import net.minecraft.client.KeyMapping
|
||||||
|
import net.minecraft.client.gui.components.Button
|
||||||
|
import net.minecraft.client.gui.components.Tooltip
|
||||||
|
import net.minecraft.network.chat.Component
|
||||||
|
|
||||||
|
val VanillaMinecraftContainer: ModContainer = FabricLoader
|
||||||
|
.getInstance()
|
||||||
|
.getModContainer("minecraft")
|
||||||
|
.get()
|
||||||
|
|
||||||
|
val KeyMapping.Provider: ModInfo get() {
|
||||||
|
val KeyBindTranslationKey = name
|
||||||
|
val CandidateModIds = KeyBindTranslationKey.split(".")
|
||||||
|
if (CandidateModIds.size == 1){
|
||||||
|
WhoProvideThisKeybindModClient.ClientLogger.warn("这是个什么东西,按键绑定ID只有一个部分,ID: $KeyBindTranslationKey")
|
||||||
|
return ModInfo(null) }
|
||||||
|
for (CandidateModId in CandidateModIds) {
|
||||||
|
val ModContainer = FabricLoader.getInstance().getModContainer(CandidateModId)
|
||||||
|
if (ModContainer.isPresent) {
|
||||||
|
return ModContainer.map(::ModInfo).get() } }
|
||||||
|
return ModInfo(VanillaMinecraftContainer) }
|
||||||
|
|
||||||
|
data class ModInfo(val ModContainerInstance: ModContainer?) {
|
||||||
|
val ID: String = ModContainerInstance?.metadata?.id ?: Component.translatable("special_provider_UNKNOWN").string
|
||||||
|
val MetaData: ModMetadata? = ModContainerInstance?.metadata
|
||||||
|
val DisplayName: String = MetaData?.name ?: Component.translatable("special_provider_UNKNOWN").string
|
||||||
|
val HumanFriendlyName: Component = Component.translatableWithFallback("modmenu.nameTranslation." + (MetaData?.id ?: "unknown"), DisplayName) }
|
||||||
|
|
||||||
|
fun Button.SetNewTooltip(Key: KeyMapping) {
|
||||||
|
if (SettingsInstance.ModEnabled == false) return
|
||||||
|
|
||||||
|
val Mod = Key.Provider
|
||||||
|
val NewTooltip = tooltip
|
||||||
|
.get()
|
||||||
|
?.message
|
||||||
|
?.copy()
|
||||||
|
?.append(Component.literal("\n"))
|
||||||
|
?.append(Component.literal("\n"))
|
||||||
|
?: Component.empty()
|
||||||
|
|
||||||
|
// 第一行:Mod的人类可读名称
|
||||||
|
NewTooltip.append(Component.translatable("tooltip.provided_by",
|
||||||
|
Mod.HumanFriendlyName))
|
||||||
|
// 第二行:Mod的ID
|
||||||
|
if (SettingsInstance.ShowModID) {
|
||||||
|
NewTooltip.append(Component.literal("\n"))
|
||||||
|
.append(Component.translatable("tooltip.provider_mod_id",
|
||||||
|
Component.literal(Mod.ID))); }
|
||||||
|
// 第三行:按键自身的ID
|
||||||
|
if (SettingsInstance.ShowKeybindID) {
|
||||||
|
NewTooltip.append(Component.literal("\n"))
|
||||||
|
.append(Component.translatable("tooltip.key_id",
|
||||||
|
Component.literal(Key.name))) }
|
||||||
|
|
||||||
|
setTooltip(Tooltip.create(NewTooltip)) }
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package xyz.thewhitedog9487.client
|
||||||
|
|
||||||
|
import com.terraformersmc.modmenu.api.ConfigScreenFactory
|
||||||
|
import com.terraformersmc.modmenu.api.ModMenuApi
|
||||||
|
import dev.isxander.yacl3.api.ConfigCategory
|
||||||
|
import dev.isxander.yacl3.api.Option
|
||||||
|
import dev.isxander.yacl3.api.OptionDescription
|
||||||
|
import dev.isxander.yacl3.api.YetAnotherConfigLib
|
||||||
|
import dev.isxander.yacl3.api.controller.BooleanControllerBuilder
|
||||||
|
import net.minecraft.network.chat.Component
|
||||||
|
|
||||||
|
class ModMenuEntryPoint: ModMenuApi {
|
||||||
|
override fun getModConfigScreenFactory() = ConfigScreenFactory { ParentScreen ->
|
||||||
|
YetAnotherConfigLib.createBuilder()
|
||||||
|
.title(Component.translatable("title.config"))
|
||||||
|
.category {
|
||||||
|
ConfigCategory.createBuilder()
|
||||||
|
.name(Component.translatable("config.category.general"))
|
||||||
|
.option {
|
||||||
|
Option.createBuilder<Boolean>()
|
||||||
|
.name(Component.translatable("option.ModEnabled"))
|
||||||
|
.description { OptionDescription.of(Component.translatable("option.ModEnabled.description") ) }
|
||||||
|
.binding( true, { SettingsInstance.ModEnabled }, { SettingsInstance.ModEnabled = it } )
|
||||||
|
.controller(BooleanControllerBuilder::create )
|
||||||
|
.build() }
|
||||||
|
.option {
|
||||||
|
Option.createBuilder<Boolean>()
|
||||||
|
.name(Component.translatable("option.ShowModID"))
|
||||||
|
.description { OptionDescription.of(Component.translatable("option.ShowModID.description") ) }
|
||||||
|
.binding( false, { SettingsInstance.ShowModID }, { SettingsInstance.ShowModID = it } )
|
||||||
|
.controller(BooleanControllerBuilder::create )
|
||||||
|
.build() }
|
||||||
|
.option {
|
||||||
|
Option.createBuilder<Boolean>()
|
||||||
|
.name(Component.translatable("option.ShowKeybindID"))
|
||||||
|
.description { OptionDescription.of(Component.translatable("option.ShowKeybindID.description") ) }
|
||||||
|
.binding( false, { SettingsInstance.ShowKeybindID }, { SettingsInstance.ShowKeybindID = it } )
|
||||||
|
.controller(BooleanControllerBuilder::create )
|
||||||
|
.build() }
|
||||||
|
.option {
|
||||||
|
Option.createBuilder<Boolean>()
|
||||||
|
.name(Component.translatable("option.ShowDebugInfo"))
|
||||||
|
.description { OptionDescription.of(Component.translatable("option.ShowDebugInfo.description") ) }
|
||||||
|
.binding( false, { SettingsInstance.ShowDebugInfo }, { SettingsInstance.ShowDebugInfo = it } )
|
||||||
|
.controller(BooleanControllerBuilder::create )
|
||||||
|
.build() }
|
||||||
|
.build() }
|
||||||
|
.build()
|
||||||
|
.generateScreen(ParentScreen) } }
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
package xyz.thewhitedog9487.client
|
||||||
|
|
||||||
|
import dev.isxander.yacl3.config.v2.api.ConfigClassHandler
|
||||||
|
import dev.isxander.yacl3.config.v2.api.SerialEntry
|
||||||
|
import kotlinx.io.IOException
|
||||||
|
import net.fabricmc.loader.api.FabricLoader
|
||||||
|
import java.nio.file.FileSystems
|
||||||
|
import java.nio.file.Path
|
||||||
|
import java.nio.file.StandardWatchEventKinds
|
||||||
|
import java.nio.file.StandardWatchEventKinds.*
|
||||||
|
|
||||||
|
const val CurrentConfigurationVersionCode: Long = 0
|
||||||
|
class Settings {
|
||||||
|
@SerialEntry(comment =
|
||||||
|
"""
|
||||||
|
配置文件版本号
|
||||||
|
用于在配置文件结构发生变化且需要手动干预时进行兼容性处理
|
||||||
|
非必要情况下你不应该手动修改这个数据,否则可能导致本Mod的配置文件出现损坏或其他问题
|
||||||
|
类型:整数
|
||||||
|
取值范围:0 ~ Long.MAX_VALUE
|
||||||
|
当前值:0
|
||||||
|
""")
|
||||||
|
var ConfigurationVersionCode = CurrentConfigurationVersionCode
|
||||||
|
|
||||||
|
@SerialEntry(comment =
|
||||||
|
"""
|
||||||
|
是否启用本模组的功能
|
||||||
|
类型:布尔值
|
||||||
|
取值范围:true false
|
||||||
|
默认值:true
|
||||||
|
""")
|
||||||
|
var ModEnabled = true
|
||||||
|
|
||||||
|
@SerialEntry(comment =
|
||||||
|
"""
|
||||||
|
是否在悬停信息中显示键位提供者的ID
|
||||||
|
类型:布尔值
|
||||||
|
取值范围:true false
|
||||||
|
默认值:false
|
||||||
|
""")
|
||||||
|
var ShowModID = false
|
||||||
|
|
||||||
|
@SerialEntry(comment =
|
||||||
|
"""
|
||||||
|
是否在悬停信息中显示键位本身的ID
|
||||||
|
类型:布尔值
|
||||||
|
取值范围:true false
|
||||||
|
默认值:false
|
||||||
|
""")
|
||||||
|
var ShowKeybindID = false
|
||||||
|
|
||||||
|
@SerialEntry(comment =
|
||||||
|
"""
|
||||||
|
是否显示调试信息
|
||||||
|
这些信息用于出现和本Mod相关的问题时进行排查,一般情况下不需要开启
|
||||||
|
类型:布尔值
|
||||||
|
取值范围:true false
|
||||||
|
默认值:false
|
||||||
|
""")
|
||||||
|
var ShowDebugInfo = false }
|
||||||
|
|
||||||
|
var SettingsHandler: ConfigClassHandler<Settings>? = null
|
||||||
|
|
||||||
|
val ConfigFilePath = FabricLoader
|
||||||
|
.getInstance()
|
||||||
|
.configDir
|
||||||
|
.resolve(WhoProvideThisKeybindModClient.FriendlyModID + ".json5")
|
||||||
|
.toAbsolutePath()
|
||||||
|
|
||||||
|
@Volatile var SettingsInstance = Settings()
|
||||||
|
|
||||||
|
// region 配置文件变更监听器
|
||||||
|
fun RegisterConfigFileReloadWatcher() {
|
||||||
|
// 由GPT 5.4 Mini生成
|
||||||
|
Thread.startVirtualThread {
|
||||||
|
WhoProvideThisKeybindModClient.ClientLogger.info("正在为${ConfigFilePath}注册配置文件变更监听器...")
|
||||||
|
val ConfigDirectory = ConfigFilePath.parent
|
||||||
|
try {
|
||||||
|
val WatchService = FileSystems.getDefault().newWatchService()
|
||||||
|
ConfigDirectory.register(WatchService, ENTRY_CREATE, ENTRY_MODIFY, ENTRY_DELETE)
|
||||||
|
while (!Thread.currentThread().isInterrupted) {
|
||||||
|
val WatchKey = WatchService.take()
|
||||||
|
var ShouldReload = false
|
||||||
|
|
||||||
|
for (EventInstance in WatchKey.pollEvents()) {
|
||||||
|
val EventKind = EventInstance.kind()
|
||||||
|
if (EventKind == StandardWatchEventKinds.OVERFLOW) {
|
||||||
|
continue }
|
||||||
|
val ChangedPath = EventInstance.context() as Path?
|
||||||
|
if (ChangedPath != null && ChangedPath == ConfigFilePath.fileName) {
|
||||||
|
ShouldReload = true } }
|
||||||
|
if (ShouldReload) {
|
||||||
|
SettingsHandler!!.load()
|
||||||
|
SettingsInstance = SettingsHandler!!.instance()
|
||||||
|
WhoProvideThisKeybindModClient.ClientLogger.info("检测到配置文件变更,已重新加载设置。") }
|
||||||
|
if (!WatchKey.reset()) {
|
||||||
|
break } }
|
||||||
|
} catch (e: InterruptedException) {
|
||||||
|
Thread.currentThread().interrupt()
|
||||||
|
} catch (e: IOException) {
|
||||||
|
throw RuntimeException(e) } } }
|
||||||
|
// endregion
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package xyz.thewhitedog9487.client
|
||||||
|
|
||||||
|
import net.fabricmc.api.ClientModInitializer
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
import xyz.thewhitedog9487.client.Event.RegisterClientLifecycleEvents
|
||||||
|
|
||||||
|
object WhoProvideThisKeybindModClient : ClientModInitializer {
|
||||||
|
const val ModID: String = "whoprovidethiskeybind"
|
||||||
|
const val FriendlyModID = "WhoProvideThisKeybind"
|
||||||
|
val ClientLogger = LoggerFactory.getLogger(FriendlyModID)
|
||||||
|
|
||||||
|
override fun onInitializeClient() {
|
||||||
|
RegisterClientLifecycleEvents() } }
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"required": false,
|
||||||
|
"package": "xyz.thewhitedog9487.client.mixin.Compatibility.Controlling",
|
||||||
|
"compatibilityLevel": "JAVA_25",
|
||||||
|
"plugin": "xyz.thewhitedog9487.client.mixin.Compatibility.Controlling.MixinPlugin",
|
||||||
|
"client": [
|
||||||
|
"NewKeyBindsListMixin" ],
|
||||||
|
"injectors": {
|
||||||
|
"defaultRequire": 0 }
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"required": true,
|
||||||
|
"package": "xyz.thewhitedog9487.client.mixin",
|
||||||
|
"compatibilityLevel": "JAVA_25",
|
||||||
|
"client": [
|
||||||
|
"KeyBindsListKeyEntryMixin"
|
||||||
|
],
|
||||||
|
"injectors": {
|
||||||
|
"defaultRequire": 1
|
||||||
|
},
|
||||||
|
"overwrites": {
|
||||||
|
"requireAnnotations": true
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 453 B |
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"modmenu.nameTranslation.whoprovidethiskeybind": "Who Provides This Keybind?",
|
||||||
|
"modmenu.descriptionTranslation.whoprovidethiskeybind": "Adds hover information on keybind change buttons in the keybinding settings screen to show which mod provides the keybind\nTip: If you need to use the config menu, install the YetAnotherConfigLib mod",
|
||||||
|
"link.bilibili": "Bilibili Homepage",
|
||||||
|
"link.blog": "TheWhiteDog9487's Blog",
|
||||||
|
"title.config": "Who Provides This Keybind?",
|
||||||
|
"config.category.general": "General",
|
||||||
|
"option.ModEnabled": "Enable Mod Functionality",
|
||||||
|
"option.ModEnabled.description": "Changes take effect immediately after modification and save without restarting the game",
|
||||||
|
"option.ShowModID": "Show Mod ID",
|
||||||
|
"option.ShowModID.description": "Display the Mod ID of the provider in the tooltip",
|
||||||
|
"option.ShowKeybindID": "Show Keybind ID",
|
||||||
|
"option.ShowKeybindID.description": "Display the keybind's own ID in the tooltip",
|
||||||
|
"option.ShowDebugInfo": "Show Debug Info",
|
||||||
|
"option.ShowDebugInfo.description": "This information is used to troubleshoot issues related to this mod; it generally does not need to be enabled",
|
||||||
|
"tooltip.provided_by": "Provided by: %s",
|
||||||
|
"tooltip.provider_mod_id": "Provider Mod ID: %s",
|
||||||
|
"tooltip.key_id": "Keybind ID: %s",
|
||||||
|
"special_provider_UNKNOWN": "Unknown"
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"modmenu.nameTranslation.whoprovidethiskeybind": "谁在提供这个键位?",
|
||||||
|
"modmenu.descriptionTranslation.whoprovidethiskeybind": "在按键绑定设置界面的键位更改按钮上添加鼠标悬停信息,显示该按键绑定是由哪个Mod提供的\n提示:如果需要使用配置菜单,请安装YetAnotherConfigLib模组",
|
||||||
|
"link.bilibili": "哔哩哔哩主页",
|
||||||
|
"link.blog": "TheWhiteDog9487的博客",
|
||||||
|
"title.config": "谁在提供这个键位?",
|
||||||
|
"config.category.general": "通用",
|
||||||
|
"option.ModEnabled": "是否启用模组功能",
|
||||||
|
"option.ModEnabled.description": "无需重启游戏,修改并保存后立刻生效",
|
||||||
|
"option.ShowModID": "是否显示Mod ID",
|
||||||
|
"option.ShowModID.description": "在提示信息中显示提供该按键的Mod的ID",
|
||||||
|
"option.ShowKeybindID": "是否显示键位ID",
|
||||||
|
"option.ShowKeybindID.description": "在提示信息中显示该按键本身的ID",
|
||||||
|
"option.ShowDebugInfo": "是否显示调试信息",
|
||||||
|
"option.ShowDebugInfo.description": "这些信息用于出现和本Mod相关的问题时进行排查,一般情况下不需要开启",
|
||||||
|
"tooltip.provided_by": "提供者:%s",
|
||||||
|
"tooltip.provider_mod_id": "提供者ID:%s",
|
||||||
|
"tooltip.key_id": "键位ID:%s",
|
||||||
|
"special_provider_UNKNOWN": "未知"
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"id": "whoprovidethiskeybind",
|
||||||
|
"version": "${version}",
|
||||||
|
"name": "Who Provide This Keybind?",
|
||||||
|
"description": "Shows which mod provides each key binding via a tooltip on the keybinds screen.",
|
||||||
|
"authors": [
|
||||||
|
"TheWhiteDog9487" ],
|
||||||
|
"contact": {
|
||||||
|
"homepage": "https://modrinth.com/project/who-provide-this-keybind",
|
||||||
|
"sources": "https://github.com/TheWhiteDog9487/WhoProvideThisKeybind",
|
||||||
|
"issues": "https://github.com/TheWhiteDog9487/WhoProvideThisKeybind/issues" },
|
||||||
|
"license": "WTFPL",
|
||||||
|
"icon": "assets/whoprovidethiskeybind/icon.png",
|
||||||
|
"environment": "client",
|
||||||
|
"entrypoints": {
|
||||||
|
"client": [ {
|
||||||
|
"value": "xyz.thewhitedog9487.client.WhoProvideThisKeybindModClient",
|
||||||
|
"adapter": "kotlin" } ],
|
||||||
|
"modmenu": [ "xyz.thewhitedog9487.client.ModMenuEntryPoint" ] },
|
||||||
|
"mixins": [ {
|
||||||
|
"config": "whoprovidethiskeybind.client.mixins.json",
|
||||||
|
"environment": "client" }, {
|
||||||
|
"config": "CompatibilityMixinConfig/controlling.mixins.json",
|
||||||
|
"environment": "client" } ],
|
||||||
|
"depends": {
|
||||||
|
"fabricloader": ">=0.19.5",
|
||||||
|
"minecraft": "~26.2",
|
||||||
|
"java": ">=25",
|
||||||
|
"fabric-api": ">=0.159.0",
|
||||||
|
"fabric-language-kotlin": ">=1.13.13+kotlin.2.4.10" },
|
||||||
|
"suggests": {
|
||||||
|
"modmenu": "*",
|
||||||
|
"yet_another_config_lib_v3": "*" },
|
||||||
|
"accessWidener": "whoprovidethiskeybind.classtweaker" ,
|
||||||
|
"custom": {
|
||||||
|
"modmenu": {
|
||||||
|
"links": {
|
||||||
|
"link.bilibili": "https://space.bilibili.com/401746666",
|
||||||
|
"link.blog": "https://www.thewhitedog9487.xyz"},
|
||||||
|
"update_checker": true } } }
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
classTweaker v1 official
|
||||||
|
|
||||||
|
accessible field net/minecraft/client/gui/components/AbstractWidget tooltip Lnet/minecraft/client/gui/components/WidgetTooltipHolder;
|
||||||
|
accessible field net/minecraft/client/gui/components/Tooltip message Lnet/minecraft/network/chat/Component;
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 702 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 652 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 752 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 638 KiB |
Reference in New Issue
Block a user