├── .gitignore
├── LICENSE
├── README.md
├── build.gradle.kts
├── buildSrc
├── build.gradle.kts
└── src
│ └── main
│ └── kotlin
│ └── build-extensions.kt
├── fabric
├── build.gradle.kts
├── gradle.properties
└── src
│ └── main
│ ├── java
│ └── mod
│ │ └── crend
│ │ └── autohud
│ │ ├── compat
│ │ ├── DehydrationCompat.java
│ │ ├── EnvironmentZCompat.java
│ │ ├── MicroDurabilityCompat.java
│ │ ├── OneBarCompat.java
│ │ └── mixin
│ │ │ ├── appleskin
│ │ │ └── HUDOverlayHandlerMixin.java
│ │ │ ├── armor_hud
│ │ │ └── ArmorHudMixin.java
│ │ │ ├── armorchroma
│ │ │ └── GuiArmorMixin.java
│ │ │ ├── dehydration
│ │ │ ├── DehydrationMixin.java
│ │ │ └── ThirstManagerMixin.java
│ │ │ ├── detailab
│ │ │ ├── ArmorBarRendererMixin.java
│ │ │ └── InGameDrawerMixin.java
│ │ │ ├── environmentz
│ │ │ └── TemperatureHudRenderingMixin.java
│ │ │ ├── farmersdelight
│ │ │ ├── ComfortHealthOverlayMixin.java
│ │ │ ├── HUDOverlaysMixin.java
│ │ │ └── NourishmentHungerOverlayMixin.java
│ │ │ ├── onebar
│ │ │ └── OneBarElementsMixin.java
│ │ │ └── statuseffectbars
│ │ │ └── StatusEffectBarRendererMixin.java
│ │ └── fabric
│ │ ├── AutoHudFabric.java
│ │ ├── mixin
│ │ └── gui
│ │ │ ├── ChatHudMixin.java
│ │ │ ├── InGameHudMixin.java
│ │ │ └── StatusEffectTimerMixin.java
│ │ └── screen
│ │ └── ModMenuIntegration.java
│ └── resources
│ ├── autohud-fabric-compat.mixins.json
│ ├── autohud-fabric.mixins.json
│ └── fabric.mod.json
├── forge
├── build.gradle.kts
├── gradle.properties
└── src
│ └── main
│ ├── java
│ └── mod
│ │ └── crend
│ │ └── autohud
│ │ └── forge
│ │ ├── AutoHudForge.java
│ │ ├── AutoHudGui.java
│ │ ├── AutoHudModEvents.java
│ │ ├── compat
│ │ ├── ColdSweatCompat.java
│ │ ├── QuarkCompat.java
│ │ └── legendarysurvivaloverhaul
│ │ │ ├── LSOCompat.java
│ │ │ ├── LSOComponentRenderer.java
│ │ │ ├── LSOComponents.java
│ │ │ └── TemperatureState.java
│ │ └── mixin
│ │ └── gui
│ │ ├── ChatHudMixin.java
│ │ ├── ForgeGuiMixin.java
│ │ ├── InGameHudMixin.java
│ │ └── StatusEffectTimerMixin.java
│ └── resources
│ ├── META-INF
│ └── mods.toml
│ ├── autohud-forge-compat.mixins.json
│ ├── autohud-forge.mixins.json
│ └── pack.mcmeta
├── gradle.properties
├── icon_large.png
├── neoforge
├── build.gradle.kts
├── gradle.properties
└── src
│ └── main
│ ├── java
│ └── mod
│ │ └── crend
│ │ └── autohud
│ │ └── neoforge
│ │ ├── AutoHudGui.java
│ │ ├── AutoHudModEvents.java
│ │ ├── AutoHudNeoForge.java
│ │ ├── compat
│ │ └── ColdSweatCompat.java
│ │ └── mixin
│ │ └── gui
│ │ ├── InGameHudMixin.java
│ │ └── StatusEffectTimerMixin.java
│ └── resources
│ ├── META-INF
│ ├── mods.toml
│ └── neoforge.mods.toml
│ ├── autohud-neoforge.mixins.json
│ └── pack.mcmeta
├── screenshot1.png
├── screenshot2.png
├── settings.gradle.kts
├── src
└── main
│ ├── java
│ └── mod
│ │ └── crend
│ │ └── autohud
│ │ ├── AutoHud.java
│ │ ├── AutoHudCompatMixinPlugin.java
│ │ ├── ModKeyBindings.java
│ │ ├── api
│ │ └── AutoHudApi.java
│ │ ├── compat
│ │ ├── HotbarSlotCyclingCompat.java
│ │ └── RaisedCompat.java
│ │ ├── component
│ │ ├── Component.java
│ │ ├── Components.java
│ │ ├── EventHandler.java
│ │ ├── Hud.java
│ │ ├── ScoreboardHelper.java
│ │ ├── State.java
│ │ └── state
│ │ │ ├── BooleanComponentState.java
│ │ │ ├── ComponentState.java
│ │ │ ├── EnhancedPolicyComponentState.java
│ │ │ ├── ItemStackComponentState.java
│ │ │ ├── PolicyComponentState.java
│ │ │ ├── ScoreboardComponentState.java
│ │ │ └── ValueComponentState.java
│ │ ├── config
│ │ ├── Config.java
│ │ ├── ConfigHandler.java
│ │ ├── EventPolicy.java
│ │ ├── RevealPolicy.java
│ │ ├── RevealType.java
│ │ └── ScrollDirection.java
│ │ ├── mixin
│ │ ├── ClientPlayNetworkHandlerMixin.java
│ │ ├── ScoreboardMixin.java
│ │ └── TeamMixinAccessor.java
│ │ └── render
│ │ ├── AutoHudRenderLayer.java
│ │ ├── AutoHudRenderer.java
│ │ ├── ChatMessageIndicator.java
│ │ └── ComponentRenderer.java
│ └── resources
│ ├── architectury.common.json
│ ├── assets
│ └── autohud
│ │ └── lang
│ │ ├── en_us.json
│ │ ├── it_it.json
│ │ ├── ru_ru.json
│ │ ├── zh_cn.json
│ │ └── zh_tw.json
│ ├── autohud-common-compat.mixins.json
│ ├── autohud-common.mixins.json
│ ├── autohud.accesswidener
│ └── autohud.png
├── stonecutter.gradle.kts
└── versions
├── 1.20.1
└── gradle.properties
├── 1.20.4
└── gradle.properties
├── 1.20.6
└── gradle.properties
├── 1.21.1
└── gradle.properties
└── 1.21.3
└── gradle.properties
/.gitignore:
--------------------------------------------------------------------------------
1 | # gradle
2 |
3 | gradle
4 | gradlew
5 | .gradle/
6 | build/
7 | out/
8 | classes/
9 | .kotlin
10 |
11 | # eclipse
12 |
13 | *.launch
14 |
15 | # idea
16 |
17 | .idea/
18 | *.iml
19 | *.ipr
20 | *.iws
21 |
22 | # vscode
23 |
24 | .settings/
25 | .vscode/
26 | bin/
27 | .classpath
28 | .project
29 |
30 | # macos
31 |
32 | *.DS_Store
33 |
34 | # fabric
35 |
36 | run/
37 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Auto HUD
2 |
3 | Auto HUD is a Minecraft mod for the Fabric launcher which hides parts of the user
4 | interface (HUD) that are currently not interesting.
5 |
6 | It is inspired by similar mods ("immersive hud") for other games.
7 | I personally really like the clean view of no visible HUD, but get frustrated by the
8 | limitations of using F1 mode.
9 |
10 | This is an opinionated rewrite of [Head-down Display](https://github.com/jadc/headdowndisplay/) that never got updated.
11 |
12 | ## Features
13 | * Toggle the whole HUD with a key binding.
14 | * Have parts of the HUD that haven't changed hide away.
15 | * Hide persistent, unchanging status effects, such as water breathing from the turtle helmet.
16 | * Show remaining time of status effects.
17 | * Highly configurable.
18 |
19 | ### Visual differences to F1 mode
20 | * Player hand / equipped items remain visible
21 | * Player names remain visible
22 | * The vignette remains active
23 | * Incoming chat messages still pop up
24 | * Crosshair remains visible (see my other mod Dynamic Crosshair for that)
25 | * Configurable what elements are hidden
26 |
27 | ## Screenshots
28 | All HUD elements are hidden except for the currently active status effect:
29 | 
30 |
31 | Possible look with shaders installed:
32 | 
33 |
34 | ## Installation
35 | This mod has been written for Fabric for Minecraft 1.18.2.
36 |
37 | Get packaged versions from [Modrinth](https://modrinth.com/mod/autohud) or [Curseforge](https://www.curseforge.com/minecraft/mc-mods/auto-hud)!
38 |
39 | * requires [Fabric API](https://modrinth.com/mod/fabric-api)
40 | * requires [ClothConfig](https://modrinth.com/mod/cloth-config)
41 | * not required: [Mod Menu](https://modrinth.com/mod/modmenu) for ingame configuration screen
42 |
43 | ## Mod Compatibility
44 | This mod includes a modified version of magicus' [Status Effect Timers](https://modrinth.com/mod/statuseffecttimer),
45 | because I could not figure out how to dynamically insert my modifications into it.
46 | Since this mod allows for status effect icons to be hidden individually,
47 | the non-modified version will draw the timers in the wrong place.
48 |
49 | Known to be compatible:
50 | * [Dynamic Crosshair](https://modrinth.com/mod/dynamiccrosshair) augments this mod by allowing to hide/change the crosshair based on context.
51 | * [Raised](https://modrinth.com/mod/raised) works perfectly.
52 | * [HUDTweaks](https://modrinth.com/mod/hudtweaks) mostly works.
53 | Vertical status effects bar does not work with the timer overlay.
54 | Animation direction and offset may have to be tweaked in AutoHud's settings manually.
55 | * [AppleSkin](https://modrinth.com/mod/appleskin) appears to work fine.
56 | * [DetailArmorBar](https://modrinth.com/mod/detail-armor-bar) is supported.
57 | * [BerdinskiyBears Armor Hud](https://www.curseforge.com/minecraft/mc-mods/berdinskiybears-armor-hud) is supported in "hotbar" configuration
58 | * [Dehydration](https://www.curseforge.com/minecraft/mc-mods/dehydration) is supported (hydration bar follows hunger bar settings).
59 | * [OneBar](https://modrinth.com/mod/onebar) is supported.
60 | * [Inventory Profiles Next](https://modrinth.com/mod/inventory-profiles-next)' lock symbol is supported (but not in "fade" setting).
61 | * [Micro Durability](https://modrinth.com/mod/microdurability) is supported (but does not get dynamically shown)
62 |
63 | Known to be incompatible:
64 | * OptiFabric crashes due to mixin conflicts.
65 | * Any other mod that draws status effect timers should have that functionality disabled.
66 | * HUD elements created by other mods will most likely not be moved.
67 | * Bedrockify overwrites the status effect modifications. To get them working, disable the `screenSafeArea` mixin.
68 | * "Fade" mode is more likely to cause issues with any mods that alter the GUI.
69 |
--------------------------------------------------------------------------------
/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("dev.architectury.loom")
3 | id("architectury-plugin")
4 | }
5 |
6 | val minecraft = stonecutter.current.version
7 |
8 | version = "${mod.version}+$minecraft"
9 | group = "${mod.group}.common"
10 | base {
11 | archivesName.set("${mod.id}-common")
12 | }
13 |
14 | architectury.common(stonecutter.tree.branches.mapNotNull {
15 | if (stonecutter.current.project !in it) null
16 | else it.prop("loom.platform")
17 | })
18 |
19 | repositories {
20 | }
21 |
22 | dependencies {
23 | minecraft("com.mojang:minecraft:$minecraft")
24 | mappings("net.fabricmc:yarn:$minecraft+build.${mod.dep("yarn_build")}:v2")
25 | modImplementation("net.fabricmc:fabric-loader:${mod.dep("fabric_loader")}")
26 |
27 | modImplementation(name="libbamboo", group="mod.crend", version="${mod.dep("libbamboo")}-fabric")
28 | modImplementation("dev.isxander:yet-another-config-lib:${mod.dep("yacl")}-fabric")
29 |
30 | mapOf(
31 | "appleskin" to "squeek.appleskin:appleskin-fabric:${mod.dep("appleskin_artifact")}-{}",
32 | "armorchroma" to "maven.modrinth:armor-chroma-for-fabric:{}",
33 | "detailab" to "maven.modrinth:detail-armor-bar:{}",
34 | "dehydration" to "maven.modrinth:dehydration:{}",
35 | "environmentz" to "maven.modrinth:environmentz:{}",
36 | "farmers_delight_refabricated" to "maven.modrinth:farmers-delight-refabricated:{}",
37 | "hotbarslotcycling" to "fuzs.hotbarslotcycling:hotbarslotcycling-fabric:{}",
38 | "onebar" to "maven.modrinth:onebar:{}",
39 | "raised" to "maven.modrinth:raised:Fabric-${mod.dep("raised_artifact")}-{}",
40 | "statuseffectbars" to "maven.modrinth:status-effect-bars:{}"
41 | ).map { (modName, url) ->
42 | mod.dep(modName) to url.replace("{}", mod.dep(modName))
43 | }.filterNot { (version, _) ->
44 | version.startsWith("[")
45 | }.forEach { (_, url) ->
46 | modCompileOnly(url)
47 | }
48 | }
49 |
50 | loom {
51 | accessWidenerPath = rootProject.file("src/main/resources/autohud.accesswidener")
52 |
53 | decompilers {
54 | get("vineflower").apply { // Adds names to lambdas - useful for mixins
55 | options.put("mark-corresponding-synthetics", "1")
56 | }
57 | }
58 | }
59 |
60 | java {
61 | withSourcesJar()
62 | val java = if (stonecutter.eval(minecraft, ">=1.20.5"))
63 | JavaVersion.VERSION_21 else JavaVersion.VERSION_17
64 | targetCompatibility = java
65 | sourceCompatibility = java
66 | }
67 |
68 | tasks.build {
69 | group = "versioned"
70 | description = "Must run through 'chiseledBuild'"
71 | }
--------------------------------------------------------------------------------
/buildSrc/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | `kotlin-dsl`
3 | kotlin("jvm") version "2.0.20"
4 | }
5 |
6 | repositories {
7 | mavenCentral()
8 | }
--------------------------------------------------------------------------------
/buildSrc/src/main/kotlin/build-extensions.kt:
--------------------------------------------------------------------------------
1 | import org.gradle.api.Project
2 | import org.gradle.api.artifacts.dsl.RepositoryHandler
3 | import org.gradle.kotlin.dsl.maven
4 | import org.gradle.language.jvm.tasks.ProcessResources
5 |
6 | val Project.mod: ModData get() = ModData(this)
7 | fun Project.prop(key: String): String? = findProperty(key)?.toString()
8 | fun String.upperCaseFirst() = replaceFirstChar { if (it.isLowerCase()) it.uppercaseChar() else it }
9 |
10 | fun RepositoryHandler.strictMaven(url: String, alias: String, vararg groups: String) = exclusiveContent {
11 | forRepository { maven(url) { name = alias } }
12 | filter { groups.forEach(::includeGroup) }
13 | }
14 |
15 | fun ProcessResources.properties(files: Iterable, vararg properties: Pair) {
16 | for ((name, value) in properties) inputs.property(name, value)
17 | filesMatching(files) {
18 | expand(properties.toMap())
19 | }
20 | }
21 |
22 | @JvmInline
23 | value class ModData(private val project: Project) {
24 | val id: String get() = requireNotNull(project.prop("mod.id")) { "Missing 'mod.id'" }
25 | val name: String get() = requireNotNull(project.prop("mod.name")) { "Missing 'mod.name'" }
26 | val version: String get() = requireNotNull(project.prop("mod.version")) { "Missing 'mod.version'" }
27 | val group: String get() = requireNotNull(project.prop("mod.group")) { "Missing 'mod.group'" }
28 |
29 | fun prop(key: String) = requireNotNull(project.prop("mod.$key")) { "Missing 'mod.$key'" }
30 | fun dep(key: String) = requireNotNull(project.prop("deps.$key")) { "Missing 'deps.$key'" }
31 | fun dep(platformName: String, key: String) = requireNotNull(project.prop("deps.${key}_${platformName}") ?: project.prop("deps.$key")) { "Missing 'deps.$key'" }
32 | }
--------------------------------------------------------------------------------
/fabric/build.gradle.kts:
--------------------------------------------------------------------------------
1 | @file:Suppress("UnstableApiUsage")
2 |
3 |
4 | plugins {
5 | id("dev.architectury.loom")
6 | id("architectury-plugin")
7 | id("com.github.johnrengelman.shadow")
8 | id("maven-publish")
9 | id("me.modmuss50.mod-publish-plugin")
10 | }
11 |
12 | val loader = prop("loom.platform")!!
13 | val minecraft: String = stonecutter.current.version
14 | val common: Project = requireNotNull(stonecutter.node.sibling("")) {
15 | "No common project for $project"
16 | }
17 |
18 | version = "${mod.version}+$minecraft"
19 | group = "${mod.group}.$loader"
20 | base {
21 | archivesName.set(mod.id)
22 | }
23 | architectury {
24 | platformSetupLoomIde()
25 | fabric()
26 | }
27 |
28 | val commonBundle: Configuration by configurations.creating {
29 | isCanBeConsumed = false
30 | isCanBeResolved = true
31 | }
32 |
33 | val shadowBundle: Configuration by configurations.creating {
34 | isCanBeConsumed = false
35 | isCanBeResolved = true
36 | }
37 |
38 | configurations {
39 | compileClasspath.get().extendsFrom(commonBundle)
40 | runtimeClasspath.get().extendsFrom(commonBundle)
41 | get("developmentFabric").extendsFrom(commonBundle)
42 | }
43 |
44 | repositories {
45 | }
46 |
47 | dependencies {
48 | minecraft("com.mojang:minecraft:$minecraft")
49 | mappings("net.fabricmc:yarn:$minecraft+build.${common.mod.dep("yarn_build")}:v2")
50 | modImplementation("net.fabricmc:fabric-loader:${mod.dep("fabric_loader")}")
51 |
52 | listOf(
53 | "fabric-key-binding-api-v1",
54 | "fabric-lifecycle-events-v1",
55 | "fabric-rendering-v1"
56 | ).forEach {
57 | modImplementation(fabricApi.module(it, common.mod.dep("fabric_api")))
58 | }
59 | modRuntimeOnly("net.fabricmc.fabric-api:fabric-api:${common.mod.dep("fabric_api")}")
60 |
61 | modImplementation(name="libbamboo", group="mod.crend", version="${common.mod.dep("libbamboo")}-fabric")
62 | include(name="libbamboo", group="mod.crend", version="${common.mod.dep("libbamboo")}-fabric")
63 |
64 | modImplementation("com.terraformersmc:modmenu:${common.mod.dep("modmenu")}")
65 | modRuntimeOnly("dev.isxander:yet-another-config-lib:${common.mod.dep("yacl")}-fabric")
66 |
67 | mapOf(
68 | "appleskin" to "squeek.appleskin:appleskin-fabric:${common.mod.dep("appleskin_artifact")}-{}",
69 | "armorchroma" to "maven.modrinth:armor-chroma-for-fabric:{}",
70 | "detailab" to "maven.modrinth:detail-armor-bar:{}",
71 | "dehydration" to "maven.modrinth:dehydration:{}",
72 | "environmentz" to "maven.modrinth:environmentz:{}",
73 | "farmers_delight_refabricated" to "maven.modrinth:farmers-delight-refabricated:{}",
74 | "hotbarslotcycling" to "fuzs.hotbarslotcycling:hotbarslotcycling-fabric:{}",
75 | "onebar" to "maven.modrinth:onebar:{}",
76 | "raised" to "maven.modrinth:raised:Fabric-${common.mod.dep("raised_artifact")}-{}",
77 | "statuseffectbars" to "maven.modrinth:status-effect-bars:{}"
78 | ).map { (modName, url) ->
79 | common.mod.dep(modName) to url.replace("{}", common.mod.dep("fabric", modName))
80 | }.filterNot { (version, _) ->
81 | version.startsWith("[")
82 | }.forEach { (_, url) ->
83 | modCompileOnly(url)
84 | }
85 |
86 | commonBundle(project(common.path, "namedElements")) { isTransitive = false }
87 | shadowBundle(project(common.path, "transformProductionFabric")) { isTransitive = false }
88 | }
89 |
90 | loom {
91 | decompilers {
92 | get("vineflower").apply { // Adds names to lambdas - useful for mixins
93 | options.put("mark-corresponding-synthetics", "1")
94 | }
95 | }
96 |
97 | runConfigs.all {
98 | isIdeConfigGenerated = true
99 | runDir = "../../../run"
100 | vmArgs("-Dmixin.debug.export=true")
101 | }
102 | }
103 |
104 | java {
105 | withSourcesJar()
106 | val java = if (stonecutter.eval(minecraft, ">=1.20.5"))
107 | JavaVersion.VERSION_21 else JavaVersion.VERSION_17
108 | targetCompatibility = java
109 | sourceCompatibility = java
110 | }
111 |
112 | tasks.shadowJar {
113 | configurations = listOf(shadowBundle)
114 | archiveClassifier = "dev-shadow"
115 | }
116 |
117 | tasks.remapJar {
118 | injectAccessWidener = true
119 | input = tasks.shadowJar.get().archiveFile
120 | archiveClassifier = loader
121 | dependsOn(tasks.shadowJar)
122 | }
123 |
124 | tasks.jar {
125 | archiveClassifier = "dev"
126 | }
127 |
128 | tasks.processResources {
129 | properties(listOf("fabric.mod.json"),
130 | "id" to mod.id,
131 | "name" to mod.name,
132 | "version" to mod.version,
133 | "minecraft" to common.mod.prop("mc_dep_fabric")
134 | )
135 | }
136 |
137 | tasks.build {
138 | group = "versioned"
139 | description = "Must run through 'chiseledBuild'"
140 | }
141 |
142 | tasks.register("buildAndCollect") {
143 | group = "versioned"
144 | description = "Must run through 'chiseledBuild'"
145 | from(tasks.remapJar.get().archiveFile, tasks.remapSourcesJar.get().archiveFile)
146 | into(rootProject.layout.buildDirectory.file("libs/${mod.version}/$loader"))
147 | dependsOn("build")
148 | }
149 |
150 | publishing {
151 | publications {
152 | create("maven") {
153 | groupId = mod.prop("group")
154 | artifactId = mod.prop("id")
155 | version = "${mod.version}+${minecraft}-${loader}"
156 |
157 | artifact(tasks.remapJar.get().archiveFile)
158 | artifact(tasks.remapSourcesJar.get().archiveFile) {
159 | classifier = "sources"
160 | }
161 | }
162 | }
163 | }
164 |
165 | publishMods {
166 | displayName = "[Fabric ${common.mod.prop("mc_title")}] ${mod.name} ${mod.version}"
167 |
168 | val modrinthToken = providers.gradleProperty("MODRINTH_TOKEN").orNull
169 | val curseforgeToken = providers.gradleProperty("CURSEFORGE_TOKEN").orNull
170 | dryRun = modrinthToken == null || curseforgeToken == null
171 |
172 | file = tasks.remapJar.get().archiveFile
173 | version = "${mod.version}+$minecraft-$loader"
174 | changelog = mod.prop("changelog")
175 | type = STABLE
176 | modLoaders.add(loader)
177 |
178 | val supportedVersions = common.mod.prop("mc_targets").split(" ")
179 |
180 | modrinth {
181 | projectId = property("publish.modrinth").toString()
182 | accessToken = modrinthToken
183 | minecraftVersions.addAll(supportedVersions)
184 |
185 | requires("fabric-api")
186 | optional("yacl")
187 | optional("modmenu")
188 | }
189 | curseforge {
190 | projectId = property("publish.curseforge").toString()
191 | projectSlug = property("publish.curseforge_slug").toString()
192 | accessToken = curseforgeToken
193 | minecraftVersions.addAll(supportedVersions)
194 | clientRequired = true
195 | serverRequired = false
196 |
197 | requires("fabric-api")
198 | optional("yacl")
199 | optional("modmenu")
200 | }
201 | }
202 |
--------------------------------------------------------------------------------
/fabric/gradle.properties:
--------------------------------------------------------------------------------
1 | loom.platform=fabric
--------------------------------------------------------------------------------
/fabric/src/main/java/mod/crend/autohud/compat/DehydrationCompat.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.compat;
2 |
3 | //? if dehydration {
4 |
5 | import mod.crend.autohud.AutoHud;
6 | import mod.crend.autohud.api.AutoHudApi;
7 | import mod.crend.autohud.component.Component;
8 | import mod.crend.autohud.component.Components;
9 | import mod.crend.autohud.component.state.PolicyComponentState;
10 | import mod.crend.autohud.render.ComponentRenderer;
11 | import net.dehydration.access.ThirstManagerAccess;
12 | import net.dehydration.init.EffectInit;
13 | import net.dehydration.misc.ThirstTooltipData;
14 | import net.dehydration.thirst.ThirstManager;
15 | import net.minecraft.client.network.ClientPlayerEntity;
16 |
17 | public class DehydrationCompat implements AutoHudApi {
18 | public static final String DEHYDRATION_MOD_ID = "dehydration";
19 |
20 | @Override
21 | public String modId() {
22 | return DEHYDRATION_MOD_ID;
23 | }
24 |
25 | // We bind this to the hunger config, as that is the most closely related one.
26 | public static Component Thirst = Component.builder(DEHYDRATION_MOD_ID, "thirst")
27 | .config(AutoHud.config.hunger())
28 | .stackComponents(Components.Air)
29 | .inMainHud()
30 | .state(player -> {
31 | ThirstManager thirstManager = ((ThirstManagerAccess) player).getThirstManager();
32 | if (thirstManager.hasThirst()) {
33 | return new PolicyComponentState(DehydrationCompat.Thirst, thirstManager::getThirstLevel, 20);
34 | }
35 | return null;
36 | })
37 | .build();
38 | public static ComponentRenderer THIRST_WRAPPER = ComponentRenderer.builder(Thirst)
39 | .move()
40 | .fade()
41 | .withCustomFramebuffer(false)
42 | .build();
43 | static {
44 | // Fake this API being inserted via entry point
45 | AutoHud.addApi(new DehydrationCompat());
46 | }
47 |
48 | @Override
49 | public void init() {
50 | Components.Hunger.addStackComponent(Thirst);
51 | }
52 |
53 | @Override
54 | public void tickState(ClientPlayerEntity player) {
55 | if (player.hasStatusEffect(EffectInit.THIRST)) {
56 | Thirst.reveal();
57 | } else if (((ThirstManagerAccess) player).getThirstManager().isNotFull()) {
58 | if (!player.getMainHandStack().isEmpty() && player.getMainHandStack().getTooltipData().isPresent() && player.getMainHandStack().getTooltipData().get() instanceof ThirstTooltipData) {
59 | Thirst.reveal();
60 | } else if (!player.getOffHandStack().isEmpty() && player.getOffHandStack().getTooltipData().isPresent() && player.getOffHandStack().getTooltipData().get() instanceof ThirstTooltipData) {
61 | Thirst.reveal();
62 | }
63 | }
64 | }
65 | }
66 | //?} else {
67 | /*public class DehydrationCompat { }
68 | *///?}
69 |
--------------------------------------------------------------------------------
/fabric/src/main/java/mod/crend/autohud/compat/EnvironmentZCompat.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.compat;
2 |
3 | //? if environmentz {
4 | import mod.crend.autohud.AutoHud;
5 | import mod.crend.autohud.api.AutoHudApi;
6 | import mod.crend.autohud.component.Component;
7 | import mod.crend.autohud.component.state.ValueComponentState;
8 | import mod.crend.autohud.config.ConfigHandler;
9 | import mod.crend.autohud.render.ComponentRenderer;
10 | import net.environmentz.access.TemperatureManagerAccess;
11 | import net.environmentz.temperature.TemperatureManager;
12 | import net.environmentz.temperature.Temperatures;
13 | import net.minecraft.client.MinecraftClient;
14 | import net.minecraft.client.network.ClientPlayerEntity;
15 |
16 | import java.util.function.Supplier;
17 |
18 | public class EnvironmentZCompat implements AutoHudApi {
19 | public static final String ENVIRONMENTZ_MOD_ID = "environmentz";
20 | @Override
21 | public String modId() {
22 | return ENVIRONMENTZ_MOD_ID;
23 | }
24 |
25 | public static Component Temperature = Component.builder(ENVIRONMENTZ_MOD_ID, "temperature")
26 | .config(ConfigHandler.DummyPolicyComponent)
27 | .inMainHud()
28 | .state(player -> new EnvironmentZState(EnvironmentZCompat.Temperature, EnvironmentZCompat::temperatureState))
29 | .build();
30 | public static Component Thermometer = Component.builder(ENVIRONMENTZ_MOD_ID, "thermometer")
31 | .config(ConfigHandler.DummyPolicyComponent)
32 | .inMainHud()
33 | .state(player -> new EnvironmentZState(EnvironmentZCompat.Thermometer, EnvironmentZCompat::thermometerState))
34 | .build();
35 | public static ComponentRenderer TEMPERATURE_WRAPPER = ComponentRenderer.of(Temperature);
36 | public static ComponentRenderer THERMOMETER_WRAPPER = ComponentRenderer.of(Thermometer);
37 |
38 | static {
39 | // Fake this API being inserted via entry point
40 | AutoHud.addApi(new EnvironmentZCompat());
41 | }
42 |
43 | static int temperatureState() {
44 | TemperatureManager temperatureManager = ((TemperatureManagerAccess) MinecraftClient.getInstance().player).getTemperatureManager();
45 | int playerTemperature = temperatureManager.getPlayerTemperature();
46 | if (playerTemperature < Temperatures.getBodyTemperatures(2)) {
47 | // cold
48 | if (playerTemperature < Temperatures.getBodyTemperatures(1)) {
49 | // very cold
50 | return -2;
51 | }
52 | return -1;
53 | } else if (playerTemperature > Temperatures.getBodyTemperatures(4)) {
54 | // hot
55 | if (playerTemperature > Temperatures.getBodyTemperatures(5)) {
56 | // very hot
57 | return 2;
58 | }
59 | return 1;
60 | }
61 | return 0;
62 | }
63 |
64 | static int thermometerState() {
65 | TemperatureManager temperatureManager = ((TemperatureManagerAccess) MinecraftClient.getInstance().player).getTemperatureManager();
66 | int thermometerTemperature = temperatureManager.getThermometerTemperature();
67 | if (thermometerTemperature <= Temperatures.getThermometerTemperatures(0)) {
68 | return -2; // very cold
69 | } else if (thermometerTemperature <= Temperatures.getThermometerTemperatures(1)) {
70 | return -1; // cold
71 | } else if (thermometerTemperature <= Temperatures.getThermometerTemperatures(2)) {
72 | return 0; // medium
73 | } else if (thermometerTemperature <= Temperatures.getThermometerTemperatures(3)) {
74 | return 1; // hot
75 | } else {
76 | return 2; // very hot
77 | }
78 | }
79 |
80 | static class EnvironmentZState extends ValueComponentState {
81 | public EnvironmentZState(Component component, Supplier newValueSupplier) {
82 | super(component, newValueSupplier, true);
83 | }
84 |
85 | @Override
86 | protected boolean doReveal(Integer newValue) {
87 | return newValue < -1 || newValue > 1 || super.doReveal(newValue);
88 | }
89 | }
90 |
91 |
92 | @Override
93 | public void tickState(ClientPlayerEntity player) {
94 | TemperatureManager temperatureManager = ((TemperatureManagerAccess) player).getTemperatureManager();
95 |
96 | if (temperatureManager.getThermometerCalm() > 0) {
97 | Thermometer.reveal();
98 | }
99 | }
100 | }
101 | //?} else {
102 | /*public class EnvironmentZCompat {
103 | }
104 | *///?}
105 |
--------------------------------------------------------------------------------
/fabric/src/main/java/mod/crend/autohud/compat/MicroDurabilityCompat.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.compat;
2 |
3 | import mod.crend.autohud.AutoHud;
4 | import mod.crend.autohud.api.AutoHudApi;
5 | import mod.crend.autohud.component.Component;
6 | import mod.crend.autohud.component.Components;
7 | import mod.crend.autohud.component.state.ComponentState;
8 | import net.minecraft.client.network.ClientPlayerEntity;
9 |
10 | public class MicroDurabilityCompat implements AutoHudApi {
11 | public static final String MICRODURABILITY_MOD_ID = "microdurability";
12 |
13 | @Override
14 | public String modId() {
15 | return MICRODURABILITY_MOD_ID;
16 | }
17 |
18 | // We bind this to the hotbar config, as that is the most closely related one.
19 | public static Component MicroDurabilityComponent = Component.builder(MICRODURABILITY_MOD_ID, "microdurability")
20 | .config(AutoHud.config.hotbar())
21 | .inMainHud()
22 | .state(player -> new ComponentState(MicroDurabilityCompat.MicroDurabilityComponent))
23 | .build();
24 |
25 | static {
26 | // Fake this API being inserted via entry point
27 | AutoHud.addApi(new MicroDurabilityCompat());
28 | }
29 |
30 | @Override
31 | public void init() {
32 | Components.ExperienceBar.addStackComponent(MicroDurabilityComponent);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/fabric/src/main/java/mod/crend/autohud/compat/OneBarCompat.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.compat;
2 |
3 | //? if onebar {
4 | import mod.crend.autohud.AutoHud;
5 | import mod.crend.autohud.api.AutoHudApi;
6 | import mod.crend.autohud.component.Component;
7 | import mod.crend.autohud.component.Components;
8 | import mod.crend.autohud.component.state.ComponentState;
9 | import mod.crend.autohud.render.ComponentRenderer;
10 | import net.minecraft.client.network.ClientPlayerEntity;
11 |
12 | public class OneBarCompat implements AutoHudApi {
13 | public static final String ONEBAR_MOD_ID = "onebar";
14 | @Override
15 | public String modId() {
16 | return ONEBAR_MOD_ID;
17 | }
18 |
19 | public static Component OneBarComponent = Component.builder(ONEBAR_MOD_ID, "onebar")
20 | .config(AutoHud.config.health())
21 | .inMainHud()
22 | .state(player -> new ComponentState(OneBarCompat.OneBarComponent))
23 | .build();
24 | public static final ComponentRenderer ONE_BAR_WRAPPER = ComponentRenderer.of(OneBarComponent);
25 |
26 | static {
27 | // Fake this API being inserted via entry point
28 | AutoHud.addApi(new OneBarCompat());
29 | }
30 |
31 | @Override
32 | public void init() {
33 | // Disable vanilla elements that are handled by OneBar
34 | AutoHud.targetExperienceBar = false;
35 | AutoHud.targetStatusBars = false;
36 |
37 | Components.ExperienceBar.addStackComponent(OneBarComponent);
38 | }
39 |
40 | @Override
41 | public void initState(ClientPlayerEntity player) {
42 | OneBarComponent.hideNow();
43 | }
44 |
45 | @Override
46 | public void tickState(ClientPlayerEntity player) {
47 | OneBarComponent.synchronizeFromHidden(
48 | Components.Health,
49 | Components.Hunger,
50 | Components.Air,
51 | Components.Armor
52 | );
53 | }
54 | }
55 | //?} else {
56 | /*public class OneBarCompat { }
57 | *///?}
58 |
--------------------------------------------------------------------------------
/fabric/src/main/java/mod/crend/autohud/compat/mixin/appleskin/HUDOverlayHandlerMixin.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.compat.mixin.appleskin;
2 |
3 | import mod.crend.autohud.AutoHud;
4 | import mod.crend.autohud.component.Components;
5 | import mod.crend.autohud.render.AutoHudRenderer;
6 | import mod.crend.autohud.render.ComponentRenderer;
7 | import net.minecraft.client.gui.DrawContext;
8 | //? if >=1.20.5
9 | /*import net.minecraft.entity.player.PlayerEntity;*/
10 | import org.spongepowered.asm.mixin.Mixin;
11 | import org.spongepowered.asm.mixin.injection.At;
12 | import org.spongepowered.asm.mixin.injection.Inject;
13 | import org.spongepowered.asm.mixin.injection.ModifyVariable;
14 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
15 | import squeek.appleskin.client.HUDOverlayHandler;
16 |
17 | @Mixin(value = HUDOverlayHandler.class, remap = false)
18 | public class HUDOverlayHandlerMixin {
19 |
20 | @Inject(
21 | //? if <1.20.5 {
22 | method = "onPreRender",
23 | //?} else
24 | /*method = "onPreRenderFood",*/
25 | at = @At("TAIL")
26 | )
27 | void autoHud$injectTransparency(
28 | DrawContext context,
29 | //? if >=1.20.5
30 | /*PlayerEntity player, int top, int right,*/
31 | CallbackInfo ci
32 | ) {
33 | ComponentRenderer.HUNGER.beginFade(context);
34 | }
35 |
36 | //? if <1.21.2 {
37 | @ModifyVariable(method = "enableAlpha", at=@At("HEAD"), argsOnly = true)
38 | float autoHud$modifyAlpha(float alpha) {
39 | return AutoHudRenderer.inRender ? AutoHudRenderer.alpha * alpha : alpha;
40 | }
41 | //?}
42 | }
43 |
--------------------------------------------------------------------------------
/fabric/src/main/java/mod/crend/autohud/compat/mixin/armor_hud/ArmorHudMixin.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.compat.mixin.armor_hud;
2 |
3 | import mod.crend.autohud.render.ComponentRenderer;
4 | import net.minecraft.client.gui.DrawContext;
5 | import net.minecraft.client.gui.hud.InGameHud;
6 | import org.spongepowered.asm.mixin.Dynamic;
7 | import org.spongepowered.asm.mixin.Mixin;
8 | import org.spongepowered.asm.mixin.injection.At;
9 | import org.spongepowered.asm.mixin.injection.Inject;
10 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
11 |
12 | @Mixin(value = InGameHud.class, priority = 1200, remap = false)
13 | public class ArmorHudMixin {
14 | @Dynamic("added by BerdinskiyBears Armor Hud")
15 | @Inject(method="drawSlots1", at=@At("HEAD"))
16 | private void autoHud$preDrawSlots1(DrawContext context, int y, int x, int w, int l, CallbackInfo ci) {
17 | ComponentRenderer.HOTBAR.beginRender(context);
18 | }
19 | @Dynamic("added by BerdinskiyBears Armor Hud")
20 | @Inject(method="drawSlots1", at=@At("TAIL"))
21 | private void autoHud$postDrawSlots1(DrawContext context, int y, int x, int w, int l, CallbackInfo ci) {
22 | ComponentRenderer.HOTBAR.endRender(context);
23 | }
24 |
25 | @Dynamic("added by BerdinskiyBears Armor Hud")
26 | @Inject(method="drawSlots2", at=@At("HEAD"))
27 | private void autoHud$preDrawSlots2(DrawContext context, int y, int x, int w, int l, CallbackInfo ci) {
28 | ComponentRenderer.HOTBAR.beginRender(context);
29 | }
30 | @Dynamic("added by BerdinskiyBears Armor Hud")
31 | @Inject(method="drawSlots2", at=@At("TAIL"))
32 | private void autoHud$postDrawSlots2(DrawContext context, int y, int x, int w, int l, CallbackInfo ci) {
33 | ComponentRenderer.HOTBAR.endRender(context);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/fabric/src/main/java/mod/crend/autohud/compat/mixin/armorchroma/GuiArmorMixin.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.compat.mixin.armorchroma;
2 |
3 | //? if armorchroma && armorchroma: <=1.2.6 {
4 | import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;
5 | import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
6 | import mod.crend.autohud.render.ComponentRenderer;
7 | import net.minecraft.client.gui.DrawContext;
8 | import nukeduck.armorchroma.GuiArmor;
9 | import org.spongepowered.asm.mixin.Mixin;
10 |
11 | @Mixin(value = GuiArmor.class, remap = false)
12 | public class GuiArmorMixin {
13 |
14 | @WrapMethod(method = "draw")
15 | void autoHud$wrapArmor(DrawContext context, int left, int top, Operation original) {
16 | ComponentRenderer.ARMOR_FADE.wrap(context, () -> original.call(context, left, top));
17 | }
18 |
19 | }
20 | //?} else {
21 | /*import mod.crend.libbamboo.VersionUtils;
22 | import org.spongepowered.asm.mixin.Mixin;
23 |
24 | @Mixin(VersionUtils.class)
25 | public class GuiArmorMixin {
26 | }
27 | *///?}
28 |
--------------------------------------------------------------------------------
/fabric/src/main/java/mod/crend/autohud/compat/mixin/dehydration/DehydrationMixin.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.compat.mixin.dehydration;
2 |
3 | //? if dehydration {
4 | import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;
5 | import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
6 | import mod.crend.autohud.compat.DehydrationCompat;
7 | import net.dehydration.thirst.ThirstHudRender;
8 | import net.minecraft.client.MinecraftClient;
9 | import net.minecraft.client.gui.DrawContext;
10 | import net.minecraft.entity.player.PlayerEntity;
11 | import org.spongepowered.asm.mixin.Mixin;
12 |
13 | @Mixin(value = ThirstHudRender.class, remap = false)
14 | public class DehydrationMixin {
15 | @WrapMethod(
16 | method = "renderThirstHud"
17 | )
18 | private static void autoHud$test(
19 | DrawContext context, MinecraftClient client, PlayerEntity playerEntity, int scaledWidth, int scaledHeight, int ticks,
20 | //? if dehydration: <=1.3.6
21 | int vehicleHeartCount, float flashAlpha, float otherFlashAlpha,
22 | Operation original
23 | ) {
24 |
25 | DehydrationCompat.THIRST_WRAPPER.wrap(context, () ->
26 | original.call(
27 | context, client, playerEntity, scaledWidth, scaledHeight, ticks
28 | //? if dehydration: <=1.3.6
29 | , vehicleHeartCount, flashAlpha, otherFlashAlpha
30 | )
31 | );
32 |
33 | }
34 | }
35 | //?} else {
36 |
37 | /*import mod.crend.libbamboo.VersionUtils;
38 | import org.spongepowered.asm.mixin.Mixin;
39 |
40 | @Mixin(value = VersionUtils.class, remap = false)
41 | public class DehydrationMixin {
42 | }
43 | *///?}
44 |
--------------------------------------------------------------------------------
/fabric/src/main/java/mod/crend/autohud/compat/mixin/dehydration/ThirstManagerMixin.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.compat.mixin.dehydration;
2 |
3 | //? if dehydration {
4 | import mod.crend.autohud.compat.DehydrationCompat;
5 | import net.dehydration.thirst.ThirstManager;
6 | import net.minecraft.entity.player.PlayerEntity;
7 | import org.spongepowered.asm.mixin.Mixin;
8 | import org.spongepowered.asm.mixin.injection.At;
9 | import org.spongepowered.asm.mixin.injection.Inject;
10 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
11 |
12 | @Mixin(value = ThirstManager.class, remap = false)
13 | public class ThirstManagerMixin {
14 | @Inject(method="setThirstLevel", at=@At("TAIL"))
15 | private void autoHud$setThirstLevel(int thirstLevel, CallbackInfo ci) {
16 | DehydrationCompat.Thirst.updateState();
17 | }
18 |
19 | @Inject(method = "update", at=@At("TAIL"))
20 | private void autoHud$update(PlayerEntity player, CallbackInfo ci) {
21 | DehydrationCompat.Thirst.updateState();
22 | }
23 | }
24 | //?} else {
25 |
26 | /*import mod.crend.libbamboo.VersionUtils;
27 | import org.spongepowered.asm.mixin.Mixin;
28 | @Mixin(VersionUtils.class)
29 | public class ThirstManagerMixin {
30 | }
31 | *///?}
32 |
--------------------------------------------------------------------------------
/fabric/src/main/java/mod/crend/autohud/compat/mixin/detailab/ArmorBarRendererMixin.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.compat.mixin.detailab;
2 |
3 | //? if detailab {
4 | import com.redlimerl.detailab.render.ArmorBarRenderer;
5 | import mod.crend.autohud.render.ComponentRenderer;
6 | import net.minecraft.client.gui.DrawContext;
7 | import net.minecraft.entity.player.PlayerEntity;
8 | import org.spongepowered.asm.mixin.Mixin;
9 | import org.spongepowered.asm.mixin.injection.At;
10 | import org.spongepowered.asm.mixin.injection.Inject;
11 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
12 |
13 | @Mixin(value = ArmorBarRenderer.class, remap = false)
14 | public class ArmorBarRendererMixin {
15 | @Inject(method = "render", at = @At("HEAD"))
16 | void autoHud$preRender(DrawContext context, PlayerEntity player, CallbackInfo ci) {
17 | ComponentRenderer.ARMOR_FADE.beginRender(context);
18 | }
19 | @Inject(method = "render", at = @At("TAIL"))
20 | void autoHud$postRender(DrawContext context, PlayerEntity player, CallbackInfo ci) {
21 | ComponentRenderer.ARMOR_FADE.endRender(context);
22 | }
23 | }
24 | //?} else {
25 | /*import mod.crend.libbamboo.VersionUtils;
26 | import org.spongepowered.asm.mixin.Mixin;
27 |
28 | @Mixin(VersionUtils.class)
29 | public class ArmorBarRendererMixin {
30 | }
31 | *///?}
32 |
--------------------------------------------------------------------------------
/fabric/src/main/java/mod/crend/autohud/compat/mixin/detailab/InGameDrawerMixin.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.compat.mixin.detailab;
2 |
3 | import com.redlimerl.detailab.render.InGameDrawer;
4 | import mod.crend.autohud.render.AutoHudRenderer;
5 | import org.spongepowered.asm.mixin.Mixin;
6 | import org.spongepowered.asm.mixin.injection.At;
7 | import org.spongepowered.asm.mixin.injection.ModifyArg;
8 |
9 | @Mixin(value = InGameDrawer.class, remap = false)
10 | public class InGameDrawerMixin {
11 | @ModifyArg(
12 | //? if <1.21 {
13 | method = "drawTexture(Lnet/minecraft/client/gui/DrawContext;IIFFIIIILjava/awt/Color;Z)V",
14 | //?} else
15 | /*method = "Lcom/redlimerl/detailab/render/InGameDrawer;drawTexture(Lnet/minecraft/util/Identifier;Lnet/minecraft/client/gui/DrawContext;IIFFIIIILjava/awt/Color;Z)V",*/
16 | at = @At(
17 | value = "INVOKE",
18 | target = "Lcom/mojang/blaze3d/systems/RenderSystem;setShaderColor(FFFF)V"
19 | ),
20 | index = 3
21 | )
22 | private static float autoHud$injectAlpha(float alpha) {
23 | return (AutoHudRenderer.inRender ? AutoHudRenderer.alpha * alpha : alpha);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/fabric/src/main/java/mod/crend/autohud/compat/mixin/environmentz/TemperatureHudRenderingMixin.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.compat.mixin.environmentz;
2 |
3 | //? if environmentz {
4 | import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;
5 | import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
6 | import mod.crend.autohud.compat.EnvironmentZCompat;
7 | import mod.crend.autohud.render.AutoHudRenderer;
8 | import net.environmentz.temperature.TemperatureHudRendering;
9 | import net.minecraft.client.MinecraftClient;
10 | import net.minecraft.client.gui.DrawContext;
11 | import net.minecraft.entity.player.PlayerEntity;
12 | import org.spongepowered.asm.mixin.Mixin;
13 | import org.spongepowered.asm.mixin.injection.At;
14 | import org.spongepowered.asm.mixin.injection.Inject;
15 | import org.spongepowered.asm.mixin.injection.ModifyArg;
16 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
17 |
18 | @Mixin(value = TemperatureHudRendering.class, remap = false)
19 | public class TemperatureHudRenderingMixin {
20 | @WrapMethod(method = "renderPlayerTemperatureIcon")
21 | private static void autoHud$wrapTemperatureIcon(DrawContext context, MinecraftClient client, PlayerEntity playerEntity, boolean heat, int xValue, int yValue, int extra, int intensity, int scaledWidth, int scaledHeight, Operation original) {
22 | EnvironmentZCompat.TEMPERATURE_WRAPPER.wrap(context, () ->
23 | original.call(context, client, playerEntity, heat, xValue, yValue, extra, intensity, scaledWidth, scaledHeight)
24 | );
25 | }
26 |
27 | @WrapMethod(method = "renderThermometerIcon")
28 | private static void autoHud$wrapThermometerIcon(DrawContext context, MinecraftClient client, PlayerEntity playerEntity, int xValue, int yValue, int scaledWidth, int scaledHeight, Operation original) {
29 | EnvironmentZCompat.THERMOMETER_WRAPPER.wrap(context, () ->
30 | original.call(context, client, playerEntity, xValue, yValue, scaledWidth, scaledHeight)
31 | );
32 | }
33 |
34 | @ModifyArg(
35 | method = {"renderPlayerTemperatureIcon", "renderThermometerIcon"},
36 | at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/systems/RenderSystem;setShaderColor(FFFF)V"),
37 | index = 3
38 | )
39 | private static float autoHud$transparentPlayerTemperatureIcon(float alpha) {
40 | return (AutoHudRenderer.inRender ? AutoHudRenderer.alpha * alpha : alpha);
41 | }
42 |
43 | }
44 | //?} else {
45 | /*import mod.crend.libbamboo.VersionUtils;
46 | import org.spongepowered.asm.mixin.Mixin;
47 |
48 | @Mixin(value = VersionUtils.class, remap = false)
49 | public class TemperatureHudRenderingMixin {
50 | }
51 | *///?}
--------------------------------------------------------------------------------
/fabric/src/main/java/mod/crend/autohud/compat/mixin/farmersdelight/ComfortHealthOverlayMixin.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.compat.mixin.farmersdelight;
2 |
3 | //? if farmers_delight_refabricated && 1.20.1 {
4 | import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;
5 | import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
6 | import mod.crend.autohud.render.ComponentRenderer;
7 | import net.minecraft.client.MinecraftClient;
8 | import net.minecraft.client.gui.DrawContext;
9 | import net.minecraft.entity.player.PlayerEntity;
10 | import org.spongepowered.asm.mixin.Mixin;
11 | import vectorwing.farmersdelight.client.gui.ComfortHealthOverlay;
12 |
13 | @Mixin(value = ComfortHealthOverlay.class, remap = false)
14 | public class ComfortHealthOverlayMixin {
15 | @WrapMethod(
16 | method = "drawComfortOverlay"
17 | )
18 | private static void autoHud$wrap(PlayerEntity player, MinecraftClient minecraft, DrawContext context, int left, int top, Operation original) {
19 | ComponentRenderer.HEALTH.wrap(context, () -> original.call(player, minecraft, context, left, top));
20 | }
21 | }
22 | //?} else {
23 | /*import mod.crend.libbamboo.VersionUtils;
24 | import org.spongepowered.asm.mixin.Mixin;
25 |
26 | @Mixin(value = VersionUtils.class, remap = false)
27 | public class ComfortHealthOverlayMixin {
28 | }
29 | *///?}
30 |
--------------------------------------------------------------------------------
/fabric/src/main/java/mod/crend/autohud/compat/mixin/farmersdelight/HUDOverlaysMixin.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.compat.mixin.farmersdelight;
2 |
3 | //? if farmers_delight_refabricated && >=1.21 {
4 | /*import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;
5 | import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
6 | import mod.crend.autohud.render.ComponentRenderer;
7 | import net.minecraft.client.MinecraftClient;
8 | import net.minecraft.client.gui.DrawContext;
9 | import net.minecraft.entity.player.HungerManager;
10 | import net.minecraft.entity.player.PlayerEntity;
11 | import org.spongepowered.asm.mixin.Mixin;
12 | import vectorwing.farmersdelight.client.gui.HUDOverlays;
13 |
14 | @Mixin(value = HUDOverlays.class, remap = false)
15 | public class HUDOverlaysMixin {
16 | @WrapMethod(
17 | method = "drawComfortOverlay"
18 | )
19 | private static void autoHud$wrapComfortOverlay(PlayerEntity player, MinecraftClient minecraft, DrawContext context, int left, int top, Operation original) {
20 | ComponentRenderer.HEALTH.wrap(context, () -> original.call(player, minecraft, context, left, top));
21 | }
22 |
23 | @WrapMethod(
24 | method = "drawNourishmentOverlay"
25 | )
26 | private static void autoHud$wrapNourishmentOverlay(HungerManager foodData, MinecraftClient minecraft, DrawContext context, int right, int top, boolean naturalHealing, Operation original) {
27 | ComponentRenderer.HEALTH.wrap(context, () -> original.call(foodData, minecraft, context, right, top, naturalHealing));
28 | }
29 | }
30 | *///?} else {
31 | import mod.crend.libbamboo.VersionUtils;
32 | import org.spongepowered.asm.mixin.Mixin;
33 |
34 | @Mixin(value = VersionUtils.class, remap = false)
35 | public class HUDOverlaysMixin {
36 | }
37 | //?}
38 |
--------------------------------------------------------------------------------
/fabric/src/main/java/mod/crend/autohud/compat/mixin/farmersdelight/NourishmentHungerOverlayMixin.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.compat.mixin.farmersdelight;
2 |
3 | //? if farmers_delight_refabricated && 1.20.1 {
4 | import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;
5 | import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
6 | import mod.crend.autohud.render.ComponentRenderer;
7 | import net.minecraft.client.MinecraftClient;
8 | import net.minecraft.client.gui.DrawContext;
9 | import net.minecraft.entity.player.HungerManager;
10 | import org.spongepowered.asm.mixin.Mixin;
11 | import vectorwing.farmersdelight.client.gui.NourishmentHungerOverlay;
12 |
13 | @Mixin(value = NourishmentHungerOverlay.class, remap = false)
14 | public class NourishmentHungerOverlayMixin {
15 | @WrapMethod(
16 | method = "drawNourishmentOverlay"
17 | )
18 | private static void autoHud$wrap(HungerManager stats, MinecraftClient mc, DrawContext context, int left, int top, boolean naturalHealing, Operation original) {
19 | ComponentRenderer.HUNGER.wrap(context, () -> original.call(stats, mc, context, left, top, naturalHealing));
20 | }
21 | }
22 | //?} else {
23 | /*import mod.crend.libbamboo.VersionUtils;
24 | import org.spongepowered.asm.mixin.Mixin;
25 |
26 | @Mixin(value = VersionUtils.class, remap = false)
27 | public class NourishmentHungerOverlayMixin {
28 | }
29 | *///?}
30 |
--------------------------------------------------------------------------------
/fabric/src/main/java/mod/crend/autohud/compat/mixin/onebar/OneBarElementsMixin.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.compat.mixin.onebar;
2 |
3 | //? if onebar {
4 | import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;
5 | import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
6 | import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
7 | import io.github.madis0.OneBarElements;
8 | import mod.crend.autohud.compat.OneBarCompat;
9 | import mod.crend.autohud.render.AutoHudRenderer;
10 | import mod.crend.autohud.render.ComponentRenderer;
11 | import net.minecraft.client.gui.DrawContext;
12 | import org.spongepowered.asm.mixin.Final;
13 | import org.spongepowered.asm.mixin.Mixin;
14 | import org.spongepowered.asm.mixin.Shadow;
15 | import org.spongepowered.asm.mixin.injection.At;
16 | import org.spongepowered.asm.mixin.injection.ModifyArg;
17 | import org.spongepowered.asm.mixin.injection.ModifyVariable;
18 |
19 | @Mixin(value = OneBarElements.class, remap = false)
20 | public abstract class OneBarElementsMixin {
21 | @Shadow
22 | @Final
23 | private DrawContext drawContext;
24 |
25 | @WrapMethod(method = "renderOneBar")
26 | private void autoHud$wrapOneBar(Operation original) {
27 | /*
28 | // In 1.20.1, mixin order makes it so we have to reset the context.
29 | // Presumably, something is getting canceled before we can clean up.
30 | //? if onebar: <4.1.0
31 | AutoHudRenderer.postInject(drawContext);
32 | */
33 | OneBarCompat.ONE_BAR_WRAPPER.wrap(drawContext, () -> original.call());
34 | }
35 |
36 | @WrapOperation(method = "renderOneBar", at = @At(value = "INVOKE", target = "Lio/github/madis0/OneBarElements;xpBar()V"))
37 | private void autoHud$wrapXpBar(OneBarElements instance, Operation original) {
38 | OneBarCompat.ONE_BAR_WRAPPER.endRender(drawContext);
39 | ComponentRenderer.EXPERIENCE_BAR.wrap(drawContext, () -> original.call(instance));
40 | OneBarCompat.ONE_BAR_WRAPPER.beginRender(drawContext);
41 | }
42 |
43 | @ModifyVariable(method = "renderBar", at = @At("HEAD"), ordinal = 4, argsOnly = true)
44 | private int autoHud$alpha(int color) {
45 | return AutoHudRenderer.modifyArgb(color);
46 | }
47 |
48 | @ModifyArg(
49 | method = "barText",
50 | at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawText(Lnet/minecraft/client/font/TextRenderer;Ljava/lang/String;IIIZ)I"),
51 | index = 4
52 | )
53 | private int autoHud$barTextAlpha(int color) {
54 | return AutoHudRenderer.modifyArgb(color);
55 | }
56 | @ModifyArg(
57 | method = "xpBar",
58 | at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawTextWithShadow(Lnet/minecraft/client/font/TextRenderer;Ljava/lang/String;III)I"),
59 | index = 4
60 | )
61 | private int autoHud$xpBarTextAlpha(int color) {
62 | return AutoHudRenderer.modifyArgb(color);
63 | }
64 | @ModifyArg(
65 | method = "xpBar",
66 | at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawCenteredTextWithShadow(Lnet/minecraft/client/font/TextRenderer;Ljava/lang/String;III)V"),
67 | index = 4
68 | )
69 | private int autoHud$xpBarTextCenteredAlpha(int color) {
70 | return AutoHudRenderer.modifyArgb(color);
71 | }
72 | }
73 | //?} else {
74 | /*import mod.crend.libbamboo.VersionUtils;
75 | import org.spongepowered.asm.mixin.Mixin;
76 |
77 | @Mixin(value = VersionUtils.class, remap = false)
78 | public class OneBarElementsMixin {
79 | }
80 | *///?}
81 |
--------------------------------------------------------------------------------
/fabric/src/main/java/mod/crend/autohud/compat/mixin/statuseffectbars/StatusEffectBarRendererMixin.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.compat.mixin.statuseffectbars;
2 |
3 | //? if statuseffectbars {
4 | import io.github.a5b84.statuseffectbars.StatusEffectBarRenderer;
5 | import mod.crend.autohud.component.Component;
6 | import mod.crend.autohud.render.AutoHudRenderer;
7 | import net.minecraft.client.gui.DrawContext;
8 | import net.minecraft.client.render.RenderTickCounter;
9 | import net.minecraft.entity.effect.StatusEffectInstance;
10 | import org.spongepowered.asm.mixin.Mixin;
11 | import org.spongepowered.asm.mixin.injection.At;
12 | import org.spongepowered.asm.mixin.injection.ModifyVariable;
13 |
14 | @Mixin(value = StatusEffectBarRenderer.class, remap = false)
15 | public class StatusEffectBarRendererMixin {
16 | @ModifyVariable(
17 | method = "render",
18 | at = @At("HEAD"),
19 | ordinal = 1,
20 | argsOnly = true)
21 | private static int autoHud$renderWithOffset(
22 | int y,
23 | DrawContext context,
24 | //? if >=1.21 {
25 | /*RenderTickCounter renderTickCounter,
26 | *///?} else if >=1.20.5
27 | /*float tickDelta,*/
28 | StatusEffectInstance effect
29 | ) {
30 | if (AutoHudRenderer.inRender) {
31 | return y + (int) Component.get(effect.getEffectType()).getOffsetY(AutoHudRenderer.tickDelta);
32 | }
33 | return y;
34 | }
35 | }
36 | //?} else {
37 | /*import mod.crend.libbamboo.VersionUtils;
38 | import org.spongepowered.asm.mixin.Mixin;
39 |
40 | @Mixin(value = VersionUtils.class, remap = false)
41 | public class StatusEffectBarRendererMixin {
42 | }
43 | *///?}
44 |
--------------------------------------------------------------------------------
/fabric/src/main/java/mod/crend/autohud/fabric/AutoHudFabric.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.fabric;
2 |
3 | import mod.crend.autohud.AutoHud;
4 | import mod.crend.autohud.ModKeyBindings;
5 | import mod.crend.autohud.api.AutoHudApi;
6 | import mod.crend.autohud.compat.HotbarSlotCyclingCompat;
7 | import mod.crend.autohud.compat.RaisedCompat;
8 | import mod.crend.autohud.render.AutoHudRenderer;
9 | import net.fabricmc.api.ClientModInitializer;
10 | import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
11 | import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
12 | import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback;
13 | import net.fabricmc.loader.api.FabricLoader;
14 |
15 | public class AutoHudFabric implements ClientModInitializer {
16 |
17 | @Override
18 | public void onInitializeClient() {
19 | AutoHud.loadConfig();
20 | AutoHud.init();
21 |
22 | ModKeyBindings.ALL.forEach(KeyBindingHelper::registerKeyBinding);
23 | ClientTickEvents.END_CLIENT_TICK.register(ModKeyBindings::clientTick);
24 |
25 | HudRenderCallback.EVENT.register(AutoHudRenderer::renderChatMessageIndicator);
26 |
27 | FabricLoader.getInstance().getEntrypointContainers(AutoHud.MOD_ID, AutoHudApi.class).forEach(entrypoint -> {
28 | AutoHud.addApi(entrypoint.getEntrypoint());
29 | });
30 |
31 | if (FabricLoader.getInstance().isModLoaded("raised")) {
32 | ClientTickEvents.END_CLIENT_TICK.register(RaisedCompat::tick);
33 | }
34 |
35 | if (FabricLoader.getInstance().isModLoaded("hotbarslotcycling")) {
36 | AutoHud.addApi(new HotbarSlotCyclingCompat());
37 | }
38 |
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/fabric/src/main/java/mod/crend/autohud/fabric/mixin/gui/ChatHudMixin.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.fabric.mixin.gui;
2 |
3 | import mod.crend.autohud.component.Components;
4 | import net.minecraft.client.gui.hud.ChatHud;
5 | import net.minecraft.client.gui.hud.MessageIndicator;
6 | import net.minecraft.network.message.MessageSignatureData;
7 | import net.minecraft.text.Text;
8 | import org.spongepowered.asm.mixin.Mixin;
9 | import org.spongepowered.asm.mixin.injection.At;
10 | import org.spongepowered.asm.mixin.injection.Inject;
11 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
12 |
13 | @Mixin(ChatHud.class)
14 | public class ChatHudMixin {
15 |
16 | @Inject(method = "addMessage(Lnet/minecraft/text/Text;Lnet/minecraft/network/message/MessageSignatureData;Lnet/minecraft/client/gui/hud/MessageIndicator;)V", at = @At("TAIL"))
17 | private void autoHud$showChatMessageIndicator(Text message, MessageSignatureData signature, MessageIndicator indicator, CallbackInfo ci) {
18 | if (Components.Chat.config.active() && Components.ChatIndicator.config.active() && Components.Chat.isHidden()) {
19 | Components.ChatIndicator.reveal();
20 | }
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/fabric/src/main/java/mod/crend/autohud/fabric/mixin/gui/StatusEffectTimerMixin.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.fabric.mixin.gui;
2 |
3 | import com.llamalad7.mixinextras.sugar.Local;
4 | import mod.crend.autohud.AutoHud;
5 | import mod.crend.autohud.render.ComponentRenderer;
6 | import mod.crend.libbamboo.PlatformUtils;
7 | import net.fabricmc.api.EnvType;
8 | import net.fabricmc.api.Environment;
9 | import net.minecraft.client.MinecraftClient;
10 | import net.minecraft.client.gui.DrawContext;
11 | import net.minecraft.client.gui.hud.InGameHud;
12 | import net.minecraft.client.render.RenderTickCounter;
13 | import net.minecraft.client.resource.language.I18n;
14 | import net.minecraft.entity.effect.StatusEffectInstance;
15 | import net.minecraft.util.math.MathHelper;
16 | import org.spongepowered.asm.mixin.Final;
17 | import org.spongepowered.asm.mixin.Mixin;
18 | import org.spongepowered.asm.mixin.Shadow;
19 | import org.spongepowered.asm.mixin.Unique;
20 | import org.spongepowered.asm.mixin.injection.At;
21 | import org.spongepowered.asm.mixin.injection.Inject;
22 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
23 |
24 | import java.util.List;
25 |
26 | /*
27 | * This file is originally part of the StatusEffectTimer mod:
28 | * https://github.com/magicus/statuseffecttimer
29 | *
30 | * It is included here in order to be modified properly.
31 | * Changes:
32 | * - Skip timers for hidden effects by redirecting StatusEffectInstance.shouldShowIcon()
33 | * - Insert matrix push/pop for moving each timer text with its icon
34 | */
35 |
36 | // Set priority to 500, to load before default at 1000. This is to better cooperate with HUDTweaks.
37 | @Environment(EnvType.CLIENT)
38 | @Mixin(value = InGameHud.class, priority = 500)
39 | public abstract class StatusEffectTimerMixin {
40 | @Shadow @Final
41 | private MinecraftClient client;
42 |
43 | @Inject(method = "renderStatusEffectOverlay",
44 | at = @At(value = "INVOKE", target = "Ljava/util/List;add(Ljava/lang/Object;)Z", shift = At.Shift.AFTER))
45 | private void appendOverlayDrawing(
46 | DrawContext context,
47 | //? if >1.20.6 {
48 | /*RenderTickCounter tickDelta,
49 | *///?} else if >1.20.5
50 | /*float tickDelta,*/
51 | CallbackInfo c,
52 | @Local List list,
53 | @Local StatusEffectInstance statusEffectInstance,
54 | @Local(ordinal = 2) int i2,
55 | @Local(ordinal = 3) int i3,
56 | @Local(ordinal = 4) int i4,
57 | @Local(ordinal = 5) int i5
58 | ) {
59 | list.add(() -> {
60 | if (AutoHud.config.statusEffectTimer()) {
61 | int x = switch (PlatformUtils.getCurrentPlatform()) {
62 | case FABRIC -> i4;
63 | case FORGE -> i5;
64 | case NEOFORGE -> i2;
65 | };
66 | int y = switch (PlatformUtils.getCurrentPlatform()) {
67 | case FABRIC -> i5;
68 | case FORGE -> i3;
69 | case NEOFORGE -> i3;
70 | };
71 | ComponentRenderer.getForStatusEffect(statusEffectInstance).wrap(context, () -> drawStatusEffectOverlay(context, statusEffectInstance, x, y));
72 | }
73 | });
74 | }
75 |
76 | @Unique
77 | private void drawStatusEffectOverlay(DrawContext context, StatusEffectInstance statusEffectInstance, int x, int y) {
78 | String duration = getDurationAsString(statusEffectInstance);
79 | int durationLength = client.textRenderer.getWidth(duration);
80 | context.drawTextWithShadow(client.textRenderer, duration, x + 13 - (durationLength / 2), y + 14, 0x99FFFFFF);
81 |
82 | int amplifier = statusEffectInstance.getAmplifier();
83 | if (amplifier > 0) {
84 | // Convert to roman numerals if possible
85 | String amplifierString = (amplifier < 10) ? I18n.translate("enchantment.level." + (amplifier + 1)) : "**";
86 | int amplifierLength = client.textRenderer.getWidth(amplifierString);
87 | context.drawTextWithShadow(client.textRenderer, amplifierString, x + 22 - amplifierLength, y + 3, 0x99FFFFFF);
88 | }
89 | }
90 |
91 | @Unique
92 | private String getDurationAsString(StatusEffectInstance statusEffectInstance) {
93 | if (statusEffectInstance.isInfinite()) {
94 | return I18n.translate("effect.duration.infinite");
95 | }
96 |
97 | int ticks = MathHelper.floor((float) statusEffectInstance.getDuration());
98 | int seconds = ticks / 20;
99 |
100 | if (seconds >= 3600) {
101 | return seconds / 3600 + "h";
102 | } else if (seconds >= 60) {
103 | return seconds / 60 + "m";
104 | } else {
105 | return String.valueOf(seconds);
106 | }
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/fabric/src/main/java/mod/crend/autohud/fabric/screen/ModMenuIntegration.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.fabric.screen;
2 |
3 | import com.terraformersmc.modmenu.api.ModMenuApi;
4 | import mod.crend.autohud.config.ConfigHandler;
5 | import net.fabricmc.api.EnvType;
6 | import net.fabricmc.api.Environment;
7 |
8 | @Environment(EnvType.CLIENT)
9 | public class ModMenuIntegration implements ModMenuApi {
10 | @Override
11 | public com.terraformersmc.modmenu.api.ConfigScreenFactory> getModConfigScreenFactory() {
12 | return ConfigHandler.CONFIG_STORE::makeScreen;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/fabric/src/main/resources/autohud-fabric-compat.mixins.json:
--------------------------------------------------------------------------------
1 | {
2 | "required": true,
3 | "minVersion": "0.8",
4 | "package": "mod.crend.autohud.compat.mixin",
5 | "compatibilityLevel": "JAVA_17",
6 | "client": [
7 | "appleskin.HUDOverlayHandlerMixin",
8 | "armor_hud.ArmorHudMixin",
9 | "armorchroma.GuiArmorMixin",
10 | "dehydration.DehydrationMixin",
11 | "dehydration.ThirstManagerMixin",
12 | "detailab.ArmorBarRendererMixin",
13 | "detailab.InGameDrawerMixin",
14 | "environmentz.TemperatureHudRenderingMixin",
15 | "farmersdelight.ComfortHealthOverlayMixin",
16 | "farmersdelight.HUDOverlaysMixin",
17 | "farmersdelight.NourishmentHungerOverlayMixin",
18 | "onebar.OneBarElementsMixin",
19 | "statuseffectbars.StatusEffectBarRendererMixin"
20 | ],
21 | "injectors": {
22 | "defaultRequire": 0
23 | },
24 | "plugin": "mod.crend.autohud.AutoHudCompatMixinPlugin"
25 | }
26 |
--------------------------------------------------------------------------------
/fabric/src/main/resources/autohud-fabric.mixins.json:
--------------------------------------------------------------------------------
1 | {
2 | "required": true,
3 | "minVersion": "0.8",
4 | "package": "mod.crend.autohud.fabric.mixin",
5 | "compatibilityLevel": "JAVA_17",
6 | "client": [
7 | "gui.ChatHudMixin",
8 | "gui.InGameHudMixin",
9 | "gui.StatusEffectTimerMixin"
10 | ],
11 | "injectors": {
12 | "defaultRequire": 1
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/fabric/src/main/resources/fabric.mod.json:
--------------------------------------------------------------------------------
1 | {
2 | "schemaVersion": 1,
3 | "id": "${id}",
4 | "version": "${version}",
5 | "name": "${name}",
6 | "description": "Dynamic HUD that hides interface elements while they are not needed.",
7 | "authors": [
8 | "Crendgrim"
9 | ],
10 | "contributors": [
11 | "JuggleStruggle"
12 | ],
13 | "contact": {
14 | "sources": "https://github.com/Crendgrim/AutoHUD",
15 | "issues": "https://github.com/Crendgrim/AutoHUD/issues"
16 | },
17 |
18 | "license": "LGPL-3.0",
19 | "icon": "autohud.png",
20 | "environment": "client",
21 | "entrypoints": {
22 | "client": [
23 | "mod.crend.autohud.fabric.AutoHudFabric"
24 | ],
25 | "modmenu": [
26 | "mod.crend.autohud.fabric.screen.ModMenuIntegration"
27 | ]
28 | },
29 | "mixins": [
30 | "autohud-common.mixins.json",
31 | "autohud-common-compat.mixins.json",
32 | "autohud-fabric.mixins.json",
33 | "autohud-fabric-compat.mixins.json"
34 | ],
35 | "depends": {
36 | "fabricloader": ">=0.15",
37 | "minecraft": "${minecraft}"
38 | }
39 | }
--------------------------------------------------------------------------------
/forge/build.gradle.kts:
--------------------------------------------------------------------------------
1 | @file:Suppress("UnstableApiUsage")
2 |
3 | plugins {
4 | id("dev.architectury.loom")
5 | id("architectury-plugin")
6 | id("com.github.johnrengelman.shadow")
7 | id("maven-publish")
8 | id("me.modmuss50.mod-publish-plugin")
9 | }
10 |
11 | val loader = prop("loom.platform")!!
12 | val minecraft: String = stonecutter.current.version
13 | val common: Project = requireNotNull(stonecutter.node.sibling("")) {
14 | "No common project for $project"
15 | }
16 |
17 | version = "${mod.version}+$minecraft"
18 | group = "${mod.group}.$loader"
19 | base {
20 | archivesName.set(mod.id)
21 | }
22 | architectury {
23 | platformSetupLoomIde()
24 | forge()
25 | }
26 |
27 | val commonBundle: Configuration by configurations.creating {
28 | isCanBeConsumed = false
29 | isCanBeResolved = true
30 | }
31 |
32 | val shadowBundle: Configuration by configurations.creating {
33 | isCanBeConsumed = false
34 | isCanBeResolved = true
35 | }
36 |
37 | configurations {
38 | compileClasspath.get().extendsFrom(commonBundle)
39 | runtimeClasspath.get().extendsFrom(commonBundle)
40 | get("developmentForge").extendsFrom(commonBundle)
41 | }
42 |
43 | repositories {
44 | maven("https://maven.minecraftforge.net")
45 | }
46 |
47 | dependencies {
48 | minecraft("com.mojang:minecraft:$minecraft")
49 | mappings("net.fabricmc:yarn:$minecraft+build.${common.mod.dep("yarn_build")}:v2")
50 | "forge"("net.minecraftforge:forge:$minecraft-${common.mod.dep("forge_loader")}")
51 | "io.github.llamalad7:mixinextras-common:${mod.dep("mixin_extras")}".let {
52 | annotationProcessor(it)
53 | implementation(it)
54 | }
55 | "io.github.llamalad7:mixinextras-forge:${mod.dep("mixin_extras")}".let {
56 | implementation(it)
57 | include(it)
58 | }
59 |
60 | mapOf(
61 | "coldsweat" to "maven.modrinth:cold-sweat:${common.mod.dep("coldsweat_artifact")}",
62 | "hotbarslotcycling" to "fuzs.hotbarslotcycling:hotbarslotcycling-forge:{}",
63 | "legendary_survival_overhaul" to "curse.maven:legendary-survival-overhaul-840254:{}",
64 | "quark" to "maven.modrinth:quark:{}",
65 | "raised" to "maven.modrinth:raised:Forge-${common.mod.dep("raised_artifact")}-{}",
66 | ).map { (modName, url) ->
67 | common.mod.dep("forge", modName) to url.replace("{}", common.mod.dep("forge", modName))
68 | }.filterNot { (version, _) ->
69 | version.startsWith("[")
70 | }.forEach { (_, url) ->
71 | modCompileOnly(url)
72 | }
73 |
74 | modImplementation(name="libbamboo", group="mod.crend", version="${common.mod.dep("libbamboo")}-forge")
75 | include(name="libbamboo", group="mod.crend", version="${common.mod.dep("libbamboo")}-forge")
76 |
77 | commonBundle(project(common.path, "namedElements")) { isTransitive = false }
78 | shadowBundle(project(common.path, "transformProductionForge")) { isTransitive = false }
79 | }
80 |
81 | loom {
82 | decompilers {
83 | get("vineflower").apply { // Adds names to lambdas - useful for mixins
84 | options.put("mark-corresponding-synthetics", "1")
85 | }
86 | }
87 |
88 | forge.convertAccessWideners = true
89 | forge.mixinConfigs(
90 | "autohud-common.mixins.json",
91 | "autohud-common-compat.mixins.json",
92 | "autohud-forge.mixins.json",
93 | "autohud-forge-compat.mixins.json",
94 | )
95 |
96 | runConfigs.all {
97 | isIdeConfigGenerated = true
98 | runDir = "../../../run"
99 | vmArgs("-Dmixin.debug.export=true")
100 | }
101 | }
102 |
103 | java {
104 | withSourcesJar()
105 | val java = if (stonecutter.eval(minecraft, ">=1.20.5"))
106 | JavaVersion.VERSION_21 else JavaVersion.VERSION_17
107 | targetCompatibility = java
108 | sourceCompatibility = java
109 | }
110 |
111 | tasks.jar {
112 | archiveClassifier = "dev"
113 | }
114 |
115 | tasks.remapJar {
116 | injectAccessWidener = true
117 | input = tasks.shadowJar.get().archiveFile
118 | archiveClassifier = loader
119 | dependsOn(tasks.shadowJar)
120 | }
121 |
122 | tasks.shadowJar {
123 | configurations = listOf(shadowBundle)
124 | archiveClassifier = "dev-shadow"
125 | exclude("fabric.mod.json", "architectury.common.json")
126 | }
127 |
128 | tasks.processResources {
129 | properties(listOf("META-INF/mods.toml", "pack.mcmeta"),
130 | "id" to mod.id,
131 | "name" to mod.name,
132 | "version" to mod.version,
133 | "minecraft" to common.mod.prop("mc_dep_forgelike")
134 | )
135 | }
136 |
137 | tasks.build {
138 | group = "versioned"
139 | description = "Must run through 'chiseledBuild'"
140 | }
141 |
142 | tasks.register("buildAndCollect") {
143 | group = "versioned"
144 | description = "Must run through 'chiseledBuild'"
145 | from(tasks.remapJar.get().archiveFile, tasks.remapSourcesJar.get().archiveFile)
146 | into(rootProject.layout.buildDirectory.file("libs/${mod.version}/$loader"))
147 | dependsOn("build")
148 | }
149 |
150 | publishing {
151 | publications {
152 | create("maven") {
153 | groupId = mod.prop("group")
154 | artifactId = mod.prop("id")
155 | version = "${mod.version}+${minecraft}-${loader}"
156 |
157 | artifact(tasks.remapJar.get().archiveFile)
158 | artifact(tasks.remapSourcesJar.get().archiveFile) {
159 | classifier = "sources"
160 | }
161 | }
162 | }
163 | }
164 |
165 | publishMods {
166 | displayName = "[Forge ${common.mod.prop("mc_title")}] ${mod.name} ${mod.version}"
167 |
168 | val modrinthToken = providers.gradleProperty("MODRINTH_TOKEN").orNull
169 | val curseforgeToken = providers.gradleProperty("CURSEFORGE_TOKEN").orNull
170 | dryRun = modrinthToken == null || curseforgeToken == null
171 |
172 | file = tasks.remapJar.get().archiveFile
173 | version = "${mod.version}+$minecraft-$loader"
174 | changelog = mod.prop("changelog")
175 | type = STABLE
176 | modLoaders.add(loader)
177 |
178 | val supportedVersions = common.mod.prop("mc_targets").split(" ")
179 |
180 | modrinth {
181 | projectId = property("publish.modrinth").toString()
182 | accessToken = modrinthToken
183 | minecraftVersions.addAll(supportedVersions)
184 |
185 | optional("yacl")
186 | }
187 | curseforge {
188 | projectId = property("publish.curseforge").toString()
189 | projectSlug = property("publish.curseforge_slug").toString()
190 | accessToken = curseforgeToken
191 | minecraftVersions.addAll(supportedVersions)
192 | clientRequired = true
193 | serverRequired = false
194 |
195 | optional("yacl")
196 | }
197 | }
198 |
--------------------------------------------------------------------------------
/forge/gradle.properties:
--------------------------------------------------------------------------------
1 | loom.platform=forge
--------------------------------------------------------------------------------
/forge/src/main/java/mod/crend/autohud/forge/AutoHudForge.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.forge;
2 |
3 | import mod.crend.autohud.AutoHud;
4 | import mod.crend.autohud.ModKeyBindings;
5 | //? if raised
6 | import mod.crend.autohud.compat.RaisedCompat;
7 | import mod.crend.autohud.config.ConfigHandler;
8 | import mod.crend.libbamboo.forge.ConfigScreen;
9 | import net.minecraft.client.MinecraftClient;
10 | import net.minecraftforge.event.TickEvent;
11 | import net.minecraftforge.fml.ModLoadingContext;
12 | import net.minecraftforge.fml.common.Mod;
13 | //? if >=1.21.1
14 | /*import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;*/
15 |
16 | @Mod(AutoHud.MOD_ID)
17 | public class AutoHudForge {
18 | static boolean raisedCompat = false;
19 |
20 | public AutoHudForge(/*? if >=1.21.1 {*//*FMLJavaModLoadingContext context*//*?}*/) {
21 | AutoHud.loadConfig();
22 | ConfigScreen.register(
23 | //? if <1.21.1 {
24 | ModLoadingContext.get(),
25 | //?} else
26 | /*context,*/
27 | ConfigHandler.CONFIG_STORE
28 | );
29 | }
30 |
31 | // Do not use @SubscribeEvent here because the mod "placebo" forces the game bus to run early for some reason.
32 | // This causes the key bindings to get ticked before the config is loaded...
33 | static void onClientTick(TickEvent.ClientTickEvent event) {
34 | if (event.phase == TickEvent.Phase.END) {
35 | ModKeyBindings.clientTick(MinecraftClient.getInstance());
36 |
37 | //? if raised {
38 | if (raisedCompat) {
39 | RaisedCompat.tick();
40 | }
41 | //?}
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/forge/src/main/java/mod/crend/autohud/forge/AutoHudGui.java:
--------------------------------------------------------------------------------
1 | //? if <1.20.5 {
2 | package mod.crend.autohud.forge;
3 |
4 | import mod.crend.autohud.render.ComponentRenderer;
5 | import net.minecraft.client.MinecraftClient;
6 | import net.minecraft.util.Identifier;
7 | import net.minecraftforge.client.event.RenderGuiOverlayEvent;
8 | import net.minecraftforge.client.gui.overlay.ForgeGui;
9 | import net.minecraftforge.eventbus.api.EventPriority;
10 | import net.minecraftforge.eventbus.api.SubscribeEvent;
11 |
12 | import java.util.HashMap;
13 | import java.util.Map;
14 | import java.util.Optional;
15 |
16 | import static net.minecraftforge.client.gui.overlay.VanillaGuiOverlay.*;
17 |
18 | public class AutoHudGui extends ForgeGui {
19 |
20 | public static final Map COMPONENT_RENDERERS = new HashMap<>();
21 | static {
22 | COMPONENT_RENDERERS.put(PLAYER_HEALTH.id(), ComponentRenderer.HEALTH);
23 | COMPONENT_RENDERERS.put(ARMOR_LEVEL.id(), ComponentRenderer.ARMOR);
24 | COMPONENT_RENDERERS.put(FOOD_LEVEL.id(), ComponentRenderer.HUNGER);
25 | COMPONENT_RENDERERS.put(AIR_LEVEL.id(), ComponentRenderer.AIR);
26 | COMPONENT_RENDERERS.put(MOUNT_HEALTH.id(), ComponentRenderer.MOUNT_HEALTH);
27 | COMPONENT_RENDERERS.put(JUMP_BAR.id(), ComponentRenderer.MOUNT_JUMP_BAR);
28 | COMPONENT_RENDERERS.put(EXPERIENCE_BAR.id(), ComponentRenderer.EXPERIENCE_BAR_FORGE);
29 | //RENDER_WRAPPERS.put(EXPERIENCE_LEVEL.id(), ComponentRenderer.EXPERIENCE_LEVEL);
30 |
31 | COMPONENT_RENDERERS.put(SCOREBOARD.id(), ComponentRenderer.SCOREBOARD);
32 | COMPONENT_RENDERERS.put(HOTBAR.id(), ComponentRenderer.HOTBAR);
33 | COMPONENT_RENDERERS.put(ITEM_NAME.id(), ComponentRenderer.TOOLTIP);
34 | COMPONENT_RENDERERS.put(CHAT_PANEL.id(), ComponentRenderer.CHAT);
35 | COMPONENT_RENDERERS.put(TITLE_TEXT.id(), ComponentRenderer.ACTION_BAR);
36 | COMPONENT_RENDERERS.put(BOSS_EVENT_PROGRESS.id(), ComponentRenderer.BOSS_BAR);
37 | }
38 |
39 | public AutoHudGui() {
40 | super(MinecraftClient.getInstance());
41 | }
42 |
43 | @SubscribeEvent(priority = EventPriority.HIGHEST, receiveCanceled = true)
44 | public void preHudComponent(RenderGuiOverlayEvent.Pre event) {
45 | Optional.ofNullable(COMPONENT_RENDERERS.get(event.getOverlay().id())).ifPresent(
46 | wrapper -> {
47 | if (wrapper.isActive() && !wrapper.doRender()) {
48 | event.setCanceled(true);
49 | }
50 | // Forge only: need to begin render for canceled events
51 | wrapper.beginRender(event.getGuiGraphics());
52 | }
53 | );
54 | }
55 | @SubscribeEvent(priority = EventPriority.LOWEST, receiveCanceled = true)
56 | public void cancelHudComponent(RenderGuiOverlayEvent.Pre event) {
57 | if (event.isCanceled()) {
58 | Optional.ofNullable(COMPONENT_RENDERERS.get(event.getOverlay().id())).ifPresent(
59 | wrapper -> wrapper.endRender(event.getGuiGraphics())
60 | );
61 | }
62 | }
63 | @SubscribeEvent(priority = EventPriority.LOWEST, receiveCanceled = true)
64 | public void postHudComponent(RenderGuiOverlayEvent.Post event) {
65 | Optional.ofNullable(COMPONENT_RENDERERS.get(event.getOverlay().id())).ifPresent(
66 | wrapper -> wrapper.endRender(event.getGuiGraphics())
67 | );
68 | }
69 | }
70 | //?}
71 |
--------------------------------------------------------------------------------
/forge/src/main/java/mod/crend/autohud/forge/AutoHudModEvents.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.forge;
2 |
3 | import mod.crend.autohud.AutoHud;
4 | import mod.crend.autohud.ModKeyBindings;
5 | import mod.crend.autohud.api.AutoHudApi;
6 | //? if hotbarslotcycling
7 | /*import mod.crend.autohud.compat.HotbarSlotCyclingCompat;*/
8 | //? if coldsweat
9 | import mod.crend.autohud.forge.compat.ColdSweatCompat;
10 | //? if quark
11 | import mod.crend.autohud.forge.compat.QuarkCompat;
12 | //? if legendary_survival_overhaul
13 | import mod.crend.autohud.forge.compat.legendarysurvivaloverhaul.LSOCompat;
14 | import net.minecraftforge.api.distmarker.Dist;
15 | //? if <1.20.5 {
16 | import net.minecraftforge.client.event.RegisterGuiOverlaysEvent;
17 | import mod.crend.autohud.render.AutoHudRenderer;
18 | //?}
19 | import net.minecraftforge.client.event.CustomizeGuiOverlayEvent;
20 | import net.minecraftforge.client.event.RegisterKeyMappingsEvent;
21 | import net.minecraftforge.common.MinecraftForge;
22 | import net.minecraftforge.eventbus.api.SubscribeEvent;
23 | import net.minecraftforge.fml.InterModComms;
24 | import net.minecraftforge.fml.ModList;
25 | import net.minecraftforge.fml.common.Mod;
26 | import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
27 | import net.minecraftforge.fml.event.lifecycle.InterModProcessEvent;
28 |
29 | @Mod.EventBusSubscriber(modid = AutoHud.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT)
30 | public class AutoHudModEvents {
31 | public static final String REGISTER_API = "register_api";
32 | public static final String NEW_CHAT_MESSAGE_INDICATOR = "new_chat_message_indicator";
33 |
34 | @SubscribeEvent
35 | static void onClientSetup(FMLClientSetupEvent event) {
36 | AutoHud.init();
37 | //? if <1.20.5
38 | MinecraftForge.EVENT_BUS.register(new AutoHudGui());
39 | ModList modList = ModList.get();
40 | //? if hotbarslotcycling {
41 | /*if (modList.isLoaded("hotbarslotcycling")) {
42 | AutoHud.addApi(new HotbarSlotCyclingCompat());
43 | }
44 | *///?}
45 | //? if raised {
46 | if (modList.isLoaded("raised")) {
47 | AutoHudForge.raisedCompat = true;
48 | }
49 | //?}
50 | //? if legendary_survival_overhaul {
51 | if (modList.isLoaded("legendarysurvivaloverhaul")) {
52 | AutoHud.addApi(new LSOCompat());
53 | }
54 | //?}
55 | //? if quark {
56 | if (modList.isLoaded("quark")) {
57 | AutoHud.addApi(new QuarkCompat());
58 | }
59 | //?}
60 | //? if coldsweat {
61 | if (modList.isLoaded("cold_sweat")) {
62 | AutoHud.addApi(new ColdSweatCompat());
63 | }
64 | //?}
65 | // Delay initialising the client tick event, see that method.
66 | MinecraftForge.EVENT_BUS.addListener(AutoHudForge::onClientTick);
67 | }
68 |
69 | @SubscribeEvent
70 | static void onInterModProcess(InterModProcessEvent event) {
71 | InterModComms.getMessages(AutoHud.MOD_ID, REGISTER_API::equals)
72 | .map(msg -> (AutoHudApi) msg.messageSupplier().get())
73 | .forEach(AutoHud::addApi);
74 | }
75 |
76 | @SubscribeEvent
77 | static void onKeyMappingsRegister(RegisterKeyMappingsEvent event) {
78 | ModKeyBindings.ALL.forEach(event::register);
79 | }
80 |
81 | //? if <1.20.5 {
82 | @SubscribeEvent
83 | static void onRegisterOverlaysEvent(RegisterGuiOverlaysEvent event) {
84 | event.registerAboveAll(NEW_CHAT_MESSAGE_INDICATOR, (forgeGui, context, f, i, j) -> AutoHudRenderer.renderChatMessageIndicator(context, f));
85 | }
86 | //?}
87 |
88 | }
89 |
--------------------------------------------------------------------------------
/forge/src/main/java/mod/crend/autohud/forge/compat/ColdSweatCompat.java:
--------------------------------------------------------------------------------
1 | //? if coldsweat {
2 | package mod.crend.autohud.forge.compat;
3 |
4 | import com.momosoftworks.coldsweat.ColdSweat;
5 | import com.momosoftworks.coldsweat.api.util.Temperature;
6 | import com.momosoftworks.coldsweat.client.gui.Overlays;
7 | import com.momosoftworks.coldsweat.common.capability.handler.EntityTempManager;
8 | import com.momosoftworks.coldsweat.common.capability.temperature.PlayerTempCap;
9 | import com.momosoftworks.coldsweat.config.ConfigSettings;
10 | import mod.crend.autohud.api.AutoHudApi;
11 | import mod.crend.autohud.component.Component;
12 | import mod.crend.autohud.component.state.ValueComponentState;
13 | import mod.crend.autohud.config.ConfigHandler;
14 | //? if <1.20.5
15 | import mod.crend.autohud.forge.AutoHudGui;
16 | import mod.crend.autohud.render.ComponentRenderer;
17 | import net.minecraft.client.network.ClientPlayerEntity;
18 |
19 | public class ColdSweatCompat implements AutoHudApi {
20 | @Override
21 | public String modId() {
22 | return ColdSweat.MOD_ID;
23 | }
24 |
25 | public static Component BODY_TEMP_GAUGE = Component.builder(ColdSweat.MOD_ID, "body_temp")
26 | .inMainHud()
27 | .config(ConfigHandler.DummyBooleanComponent)
28 | .state(player -> new ValueComponentState<>(ColdSweatCompat.BODY_TEMP_GAUGE, () -> Overlays.BODY_TEMP, true))
29 | .build();
30 | public static Component WORLD_TEMP_GAUGE = Component.builder(ColdSweat.MOD_ID, "world_temp")
31 | .inMainHud()
32 | .config(ConfigHandler.DummyBooleanComponent)
33 | .state(player -> new TemperatureState(ColdSweatCompat.WORLD_TEMP_GAUGE))
34 | .build();
35 | public static Component VAGUE_TEMP_GAUGE = Component.builder(ColdSweat.MOD_ID, "vague_temp")
36 | .inMainHud()
37 | .config(ConfigHandler.DummyBooleanComponent)
38 | .state(player -> new TemperatureState(ColdSweatCompat.VAGUE_TEMP_GAUGE))
39 | .build();
40 |
41 | static class TemperatureState extends ValueComponentState {
42 | static double PLAYER_MAX_TEMP;
43 | static double PLAYER_MIN_TEMP;
44 |
45 | public TemperatureState(Component component) {
46 | super(component, () -> {
47 | double temp = Temperature.convert(Overlays.WORLD_TEMP, ConfigSettings.CELSIUS.get() ? Temperature.Units.C : Temperature.Units.F, Temperature.Units.MC, true);
48 | return Overlays.getGaugeSeverity(temp, PLAYER_MIN_TEMP, PLAYER_MAX_TEMP);
49 | }, true);
50 | }
51 |
52 | @Override
53 | protected boolean doReveal(Integer newValue) {
54 | return super.doReveal(newValue) || newValue < -2 || newValue > 2;
55 | }
56 | }
57 |
58 | @Override
59 | public void tickState(ClientPlayerEntity player) {
60 | EntityTempManager.getTemperatureCap(player).ifPresent((icap) -> {
61 | if (icap instanceof PlayerTempCap cap) {
62 | TemperatureState.PLAYER_MAX_TEMP = cap.getTrait(Temperature.Trait.BURNING_POINT);
63 | TemperatureState.PLAYER_MIN_TEMP = cap.getTrait(Temperature.Trait.FREEZING_POINT);
64 | }
65 | });
66 | }
67 |
68 | public static ComponentRenderer BODY_TEMP_RENDERER = ComponentRenderer.of(BODY_TEMP_GAUGE);
69 | public static ComponentRenderer WORLD_TEMP_RENDERER = ComponentRenderer.of(WORLD_TEMP_GAUGE);
70 | public static ComponentRenderer VAGUE_TEMP_RENDERER = ComponentRenderer.of(VAGUE_TEMP_GAUGE);
71 |
72 | @Override
73 | public void init() {
74 | //? if <1.20.5 {
75 | AutoHudGui.COMPONENT_RENDERERS.put(BODY_TEMP_GAUGE.identifier, BODY_TEMP_RENDERER);
76 | AutoHudGui.COMPONENT_RENDERERS.put(WORLD_TEMP_GAUGE.identifier, WORLD_TEMP_RENDERER);
77 | AutoHudGui.COMPONENT_RENDERERS.put(VAGUE_TEMP_GAUGE.identifier, VAGUE_TEMP_RENDERER);
78 | //?}
79 | }
80 | }
81 | //?}
82 |
--------------------------------------------------------------------------------
/forge/src/main/java/mod/crend/autohud/forge/compat/QuarkCompat.java:
--------------------------------------------------------------------------------
1 | //? if quark {
2 | package mod.crend.autohud.forge.compat;
3 |
4 | import mod.crend.autohud.api.AutoHudApi;
5 | import mod.crend.autohud.component.Components;
6 | import net.minecraft.client.network.ClientPlayerEntity;
7 | import org.violetmoon.quark.base.Quark;
8 | import org.violetmoon.quark.content.management.module.HotbarChangerModule;
9 |
10 | public class QuarkCompat implements AutoHudApi {
11 | @Override
12 | public String modId() {
13 | return Quark.MOD_ID;
14 | }
15 |
16 | @Override
17 | public void tickState(ClientPlayerEntity player) {
18 | if (HotbarChangerModule.hotbarChangeOpen) {
19 | Components.Hotbar.reveal();
20 | }
21 | }
22 | }
23 | //?}
24 |
--------------------------------------------------------------------------------
/forge/src/main/java/mod/crend/autohud/forge/compat/legendarysurvivaloverhaul/LSOCompat.java:
--------------------------------------------------------------------------------
1 | //? if legendary_survival_overhaul {
2 | package mod.crend.autohud.forge.compat.legendarysurvivaloverhaul;
3 |
4 | import mod.crend.autohud.api.AutoHudApi;
5 | import mod.crend.autohud.component.Components;
6 | import mod.crend.autohud.forge.AutoHudGui;
7 | import sfiomn.legendarysurvivaloverhaul.LegendarySurvivalOverhaul;
8 |
9 | public class LSOCompat implements AutoHudApi {
10 |
11 | @Override
12 | public String modId() {
13 | return LegendarySurvivalOverhaul.MOD_ID;
14 | }
15 |
16 | @Override
17 | public void init() {
18 | Components.Hunger.addStackComponent(LSOComponents.THIRST);
19 | Components.ExperienceBar.addStackComponent(LSOComponents.TEMPERATURE);
20 | AutoHudGui.COMPONENT_RENDERERS.put(LSOComponents.FOOD_BAR_COLD_EFFECT.identifier, LSOComponentRenderer.FOOD_BAR_COLD_EFFECT);
21 | AutoHudGui.COMPONENT_RENDERERS.put(LSOComponents.THIRST.identifier, LSOComponentRenderer.THIRST);
22 | AutoHudGui.COMPONENT_RENDERERS.put(LSOComponents.TEMPERATURE.identifier, LSOComponentRenderer.TEMPERATURE);
23 | }
24 | }
25 | //?}
26 |
--------------------------------------------------------------------------------
/forge/src/main/java/mod/crend/autohud/forge/compat/legendarysurvivaloverhaul/LSOComponentRenderer.java:
--------------------------------------------------------------------------------
1 | //? if legendary_survival_overhaul {
2 | package mod.crend.autohud.forge.compat.legendarysurvivaloverhaul;
3 |
4 | import mod.crend.autohud.render.ComponentRenderer;
5 |
6 | public class LSOComponentRenderer {
7 | public static ComponentRenderer FOOD_BAR_COLD_EFFECT = ComponentRenderer.of(LSOComponents.FOOD_BAR_COLD_EFFECT);
8 | public static ComponentRenderer THIRST = ComponentRenderer.of(LSOComponents.THIRST);
9 | public static ComponentRenderer TEMPERATURE = ComponentRenderer.of(LSOComponents.TEMPERATURE);
10 | }
11 | //?}
12 |
--------------------------------------------------------------------------------
/forge/src/main/java/mod/crend/autohud/forge/compat/legendarysurvivaloverhaul/LSOComponents.java:
--------------------------------------------------------------------------------
1 | //? if legendary_survival_overhaul {
2 | package mod.crend.autohud.forge.compat.legendarysurvivaloverhaul;
3 |
4 | import mod.crend.autohud.AutoHud;
5 | import mod.crend.autohud.component.Component;
6 | import mod.crend.autohud.component.Components;
7 | import mod.crend.autohud.component.state.BooleanComponentState;
8 | import mod.crend.autohud.component.state.PolicyComponentState;
9 | import sfiomn.legendarysurvivaloverhaul.LegendarySurvivalOverhaul;
10 | import sfiomn.legendarysurvivaloverhaul.common.capabilities.thirst.ThirstCapability;
11 | import sfiomn.legendarysurvivaloverhaul.registry.MobEffectRegistry;
12 | import sfiomn.legendarysurvivaloverhaul.util.CapabilityUtil;
13 |
14 | public class LSOComponents {
15 | public static Component FOOD_BAR_COLD_EFFECT = Component.builder(LegendarySurvivalOverhaul.MOD_ID, "cold_hunger")
16 | .isTargeted(Components.TARGET_STATUS_BARS)
17 | .config(AutoHud.config.hunger())
18 | .inMainHud()
19 | .state(player -> new BooleanComponentState(LSOComponents.FOOD_BAR_COLD_EFFECT, () -> player.hasStatusEffect(MobEffectRegistry.COLD_HUNGER.get()), true))
20 | .build();
21 |
22 | static ThirstCapability THIRST_CAP;
23 | public static Component THIRST = Component.builder(LegendarySurvivalOverhaul.MOD_ID, "thirst")
24 | .isTargeted(Components.TARGET_STATUS_BARS)
25 | .config(AutoHud.config.hunger())
26 | .inMainHud()
27 | .state(player -> new PolicyComponentState(LSOComponents.THIRST, () -> {
28 | if (THIRST_CAP == null || player.age % 20 == 0) {
29 | THIRST_CAP = CapabilityUtil.getThirstCapability(player);
30 | }
31 | return THIRST_CAP.getHydrationLevel();
32 | }, () -> 20, true))
33 | .build();
34 |
35 | public static Component TEMPERATURE = Component.builder(LegendarySurvivalOverhaul.MOD_ID, "temperature")
36 | .inMainHud()
37 | .state(TemperatureState::new)
38 | .build();
39 |
40 | }
41 | //?}
42 |
--------------------------------------------------------------------------------
/forge/src/main/java/mod/crend/autohud/forge/compat/legendarysurvivaloverhaul/TemperatureState.java:
--------------------------------------------------------------------------------
1 | //? if legendary_survival_overhaul {
2 | package mod.crend.autohud.forge.compat.legendarysurvivaloverhaul;
3 |
4 | import mod.crend.autohud.component.state.ComponentState;
5 | import net.minecraft.client.network.ClientPlayerEntity;
6 | import sfiomn.legendarysurvivaloverhaul.api.temperature.TemperatureEnum;
7 | import sfiomn.legendarysurvivaloverhaul.common.capabilities.temperature.TemperatureCapability;
8 | import sfiomn.legendarysurvivaloverhaul.common.capabilities.wetness.WetnessCapability;
9 | import sfiomn.legendarysurvivaloverhaul.util.CapabilityUtil;
10 |
11 | import java.util.Objects;
12 |
13 | public class TemperatureState extends ComponentState {
14 | ClientPlayerEntity player;
15 | TemperatureCapability TEMPERATURE_CAP;
16 | WetnessCapability WETNESS_CAP;
17 | TemperatureEnum oldTemperature;
18 | int oldWetness;
19 |
20 | public TemperatureState(ClientPlayerEntity player) {
21 | super(LSOComponents.TEMPERATURE, true);
22 | this.player = player;
23 | this.TEMPERATURE_CAP = CapabilityUtil.getTempCapability(player);
24 | this.WETNESS_CAP = CapabilityUtil.getWetnessCapability(player);
25 | }
26 |
27 | @Override
28 | public void update() {
29 | TemperatureEnum newTemperature = TEMPERATURE_CAP.getTemperatureEnum();
30 | int newWetness = WETNESS_CAP.getWetness();
31 | if (doReveal(newTemperature, newWetness)) {
32 | component.revealCombined();
33 | }
34 | oldTemperature = newTemperature;
35 | oldWetness = newWetness;
36 | }
37 |
38 | protected boolean doReveal(TemperatureEnum newTemperature, int newWetness) {
39 | return !component.config.active()
40 | || (!Objects.equals(newTemperature, oldTemperature) || oldWetness != newWetness)
41 | || newWetness > 0
42 | || forceReveal()
43 | ;
44 | }
45 | private boolean forceReveal() {
46 | return switch (TEMPERATURE_CAP.getTemperatureEnum()) {
47 | case FROSTBITE, HEAT_STROKE -> true;
48 | case COLD, NORMAL, HOT -> false;
49 | };
50 | }
51 | }
52 | //?}
--------------------------------------------------------------------------------
/forge/src/main/java/mod/crend/autohud/forge/mixin/gui/ChatHudMixin.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.forge.mixin.gui;
2 |
3 | import mod.crend.autohud.component.Components;
4 | import mod.crend.autohud.render.ComponentRenderer;
5 | import net.minecraft.client.gui.DrawContext;
6 | import net.minecraft.client.gui.hud.ChatHud;
7 | import net.minecraft.client.gui.hud.MessageIndicator;
8 | import net.minecraft.network.message.MessageSignatureData;
9 | import net.minecraft.text.Text;
10 | import org.spongepowered.asm.mixin.Mixin;
11 | import org.spongepowered.asm.mixin.injection.At;
12 | import org.spongepowered.asm.mixin.injection.Inject;
13 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
14 |
15 | @Mixin(ChatHud.class)
16 | public class ChatHudMixin {
17 |
18 | @Inject(method = "addMessage(Lnet/minecraft/text/Text;Lnet/minecraft/network/message/MessageSignatureData;Lnet/minecraft/client/gui/hud/MessageIndicator;)V", at = @At("TAIL"))
19 | private void autoHud$showChatMessageIndicator(Text message, MessageSignatureData signature, MessageIndicator indicator, CallbackInfo ci) {
20 | if (Components.Chat.config.active() && Components.ChatIndicator.config.active() && Components.Chat.isHidden()) {
21 | Components.ChatIndicator.reveal();
22 | }
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/forge/src/main/java/mod/crend/autohud/forge/mixin/gui/ForgeGuiMixin.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.forge.mixin.gui;
2 |
3 | //? if <1.20.5 {
4 | import mod.crend.autohud.AutoHud;
5 | import mod.crend.autohud.component.Components;
6 | import mod.crend.autohud.render.AutoHudRenderer;
7 | import mod.crend.autohud.render.ComponentRenderer;
8 | import net.minecraft.client.gui.DrawContext;
9 | import net.minecraftforge.client.gui.overlay.ForgeGui;
10 | import org.spongepowered.asm.mixin.Mixin;
11 | import org.spongepowered.asm.mixin.injection.At;
12 | import org.spongepowered.asm.mixin.injection.Inject;
13 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
14 |
15 | @Mixin(ForgeGui.class)
16 | public class ForgeGuiMixin {
17 |
18 | @Inject(method = "render", at = @At("HEAD"))
19 | private void autoHud$preRender(DrawContext context, float tickDelta, CallbackInfo ci) {
20 | AutoHudRenderer.inRender = true;
21 | AutoHudRenderer.tickDelta = tickDelta;
22 | }
23 | @Inject(method = "render", at = @At("RETURN"))
24 | private void autoHud$postRender(DrawContext context, float tickDelta, CallbackInfo ci) {
25 | AutoHudRenderer.inRender = false;
26 | }
27 |
28 | @Inject(method = "renderHealth", at = @At("HEAD"))
29 | private void autoHud$preHealth(int width, int height, DrawContext context, CallbackInfo ci) {
30 | if (AutoHud.targetStatusBars) {
31 | ComponentRenderer.HEALTH.beginFade(context);
32 | }
33 | }
34 |
35 | @Inject(method = "renderArmor", at = @At("HEAD"))
36 | private void autoHud$preArmor(DrawContext context, int width, int height, CallbackInfo ci) {
37 | if (AutoHud.targetStatusBars) {
38 | ComponentRenderer.ARMOR.beginFade(context);
39 | }
40 | }
41 |
42 | @Inject(method = "renderFood", at = @At("HEAD"))
43 | private void autoHud$preFood(int width, int height, DrawContext context, CallbackInfo ci) {
44 | if (AutoHud.targetStatusBars) {
45 | ComponentRenderer.HUNGER.beginFade(context);
46 | }
47 | }
48 |
49 | @Inject(method = "renderAir", at = @At("HEAD"))
50 | private void autoHud$preAir(int width, int height, DrawContext context, CallbackInfo ci) {
51 | if (AutoHud.targetStatusBars) {
52 | ComponentRenderer.AIR.beginFade(context);
53 | }
54 | }
55 |
56 | @Inject(method = "renderHealthMount", at = @At("HEAD"))
57 | private void autoHud$preRenderHealthMount(int width, int height, DrawContext context, CallbackInfo ci) {
58 | if (AutoHud.targetStatusBars) {
59 | ComponentRenderer.MOUNT_HEALTH.beginFade(context);
60 | }
61 | }
62 | }
63 | //?} else {
64 |
65 | /*import mod.crend.libbamboo.VersionUtils;
66 | import org.spongepowered.asm.mixin.Mixin;
67 |
68 | @Mixin(VersionUtils.class)
69 | public class ForgeGuiMixin {
70 | }
71 | *///?}
--------------------------------------------------------------------------------
/forge/src/main/java/mod/crend/autohud/forge/mixin/gui/StatusEffectTimerMixin.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.forge.mixin.gui;
2 |
3 | import com.llamalad7.mixinextras.sugar.Local;
4 | import mod.crend.autohud.AutoHud;
5 | import mod.crend.autohud.render.ComponentRenderer;
6 | import mod.crend.libbamboo.PlatformUtils;
7 | import net.minecraft.client.MinecraftClient;
8 | import net.minecraft.client.gui.DrawContext;
9 | import net.minecraft.client.gui.hud.InGameHud;
10 | import net.minecraft.client.render.RenderTickCounter;
11 | import net.minecraft.client.resource.language.I18n;
12 | import net.minecraft.entity.effect.StatusEffectInstance;
13 | import net.minecraft.util.math.MathHelper;
14 | import org.spongepowered.asm.mixin.Final;
15 | import org.spongepowered.asm.mixin.Mixin;
16 | import org.spongepowered.asm.mixin.Shadow;
17 | import org.spongepowered.asm.mixin.Unique;
18 | import org.spongepowered.asm.mixin.injection.At;
19 | import org.spongepowered.asm.mixin.injection.Inject;
20 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
21 |
22 | import java.util.List;
23 |
24 | /*
25 | * This file is originally part of the StatusEffectTimer mod:
26 | * https://github.com/magicus/statuseffecttimer
27 | *
28 | * It is included here in order to be modified properly.
29 | * Changes:
30 | * - Skip timers for hidden effects by redirecting StatusEffectInstance.shouldShowIcon()
31 | * - Insert matrix push/pop for moving each timer text with its icon
32 | */
33 |
34 | // Set priority to 500, to load before default at 1000. This is to better cooperate with HUDTweaks.
35 | @Mixin(value = InGameHud.class, priority = 500)
36 | public abstract class StatusEffectTimerMixin {
37 | @Shadow @Final
38 | protected MinecraftClient client;
39 |
40 | @Inject(method = "renderStatusEffectOverlay",
41 | at = @At(value = "INVOKE", target = "Ljava/util/List;add(Ljava/lang/Object;)Z", shift = At.Shift.AFTER))
42 | private void appendOverlayDrawing(
43 | DrawContext context,
44 | //? if >1.20.6 {
45 | /*RenderTickCounter tickDelta,
46 | *///?} else if >1.20.5
47 | /*float tickDelta,*/
48 | CallbackInfo c,
49 | @Local List list,
50 | @Local StatusEffectInstance statusEffectInstance,
51 | @Local(ordinal = 2) int i2,
52 | @Local(ordinal = 3) int i3,
53 | @Local(ordinal = 4) int i4,
54 | @Local(ordinal = 5) int i5
55 | ) {
56 | list.add(() -> {
57 | if (AutoHud.config.statusEffectTimer()) {
58 | int x = switch (PlatformUtils.getCurrentPlatform()) {
59 | case FABRIC -> i4;
60 | case FORGE -> i5;
61 | case NEOFORGE -> i2;
62 | };
63 | int y = switch (PlatformUtils.getCurrentPlatform()) {
64 | case FABRIC -> i5;
65 | case FORGE -> i3;
66 | case NEOFORGE -> i3;
67 | };
68 | ComponentRenderer.getForStatusEffect(statusEffectInstance).wrap(context, () -> drawStatusEffectOverlay(context, statusEffectInstance, x, y));
69 | }
70 | });
71 | }
72 |
73 | @Unique
74 | private void drawStatusEffectOverlay(DrawContext context, StatusEffectInstance statusEffectInstance, int x, int y) {
75 | String duration = getDurationAsString(statusEffectInstance);
76 | int durationLength = client.textRenderer.getWidth(duration);
77 | context.drawTextWithShadow(client.textRenderer, duration, x + 13 - (durationLength / 2), y + 14, 0x99FFFFFF);
78 |
79 | int amplifier = statusEffectInstance.getAmplifier();
80 | if (amplifier > 0) {
81 | // Convert to roman numerals if possible
82 | String amplifierString = (amplifier < 10) ? I18n.translate("enchantment.level." + (amplifier + 1)) : "**";
83 | int amplifierLength = client.textRenderer.getWidth(amplifierString);
84 | context.drawTextWithShadow(client.textRenderer, amplifierString, x + 22 - amplifierLength, y + 3, 0x99FFFFFF);
85 | }
86 | }
87 |
88 | @Unique
89 | private String getDurationAsString(StatusEffectInstance statusEffectInstance) {
90 | if (statusEffectInstance.isInfinite()) {
91 | return I18n.translate("effect.duration.infinite");
92 | }
93 |
94 | int ticks = MathHelper.floor((float) statusEffectInstance.getDuration());
95 | int seconds = ticks / 20;
96 |
97 | if (seconds >= 3600) {
98 | return seconds / 3600 + "h";
99 | } else if (seconds >= 60) {
100 | return seconds / 60 + "m";
101 | } else {
102 | return String.valueOf(seconds);
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/forge/src/main/resources/META-INF/mods.toml:
--------------------------------------------------------------------------------
1 | modLoader = "javafml"
2 | loaderVersion = "*"
3 | issueTrackerURL = "https://github.com/Crendgrim/AutoHUD/issues"
4 | license = "LGPL-3.0"
5 |
6 | [[mods]]
7 | modId = "${id}"
8 | version = "${version}"
9 | displayName = "${name}"
10 | authors = "Crendgrim"
11 | description = '''
12 | Dynamic HUD that hides interface elements while they are not needed.
13 | '''
14 | logoFile = "autohud.png"
15 | logoBlur = false
16 | displayTest = "IGNORE_ALL_VERSION"
17 |
--------------------------------------------------------------------------------
/forge/src/main/resources/autohud-forge-compat.mixins.json:
--------------------------------------------------------------------------------
1 | {
2 | "required": true,
3 | "minVersion": "0.8",
4 | "package": "mod.crend.autohud.compat.mixin",
5 | "compatibilityLevel": "JAVA_17",
6 | "client": [
7 | ],
8 | "injectors": {
9 | "defaultRequire": 0
10 | },
11 | "plugin": "mod.crend.autohud.AutoHudCompatMixinPlugin"
12 | }
13 |
--------------------------------------------------------------------------------
/forge/src/main/resources/autohud-forge.mixins.json:
--------------------------------------------------------------------------------
1 | {
2 | "required": true,
3 | "minVersion": "0.8",
4 | "package": "mod.crend.autohud.forge.mixin",
5 | "compatibilityLevel": "JAVA_17",
6 | "client": [
7 | "gui.ChatHudMixin",
8 | "gui.ForgeGuiMixin",
9 | "gui.InGameHudMixin",
10 | "gui.StatusEffectTimerMixin"
11 | ],
12 | "injectors": {
13 | "defaultRequire": 1
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/forge/src/main/resources/pack.mcmeta:
--------------------------------------------------------------------------------
1 | {
2 | "pack": {
3 | "description": "AutoHUD",
4 | "pack_format": 9
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Done to increase the memory available to gradle.
2 | org.gradle.jvmargs=-Xmx6G
3 | org.gradle.parallel=false
4 | org.gradle.caching=true
5 | org.gradle.caching.debug=false
6 | #org.gradle.configureondemand=true
7 |
8 | # Mod properties
9 | mod.version=8.1
10 | mod.changelog=Fix various bugs
11 | mod.group=mod.crend
12 | mod.id=autohud
13 | mod.name=Auto HUD
14 |
15 | # Used for the mod metadata
16 | mod.mc_dep_fabric=[VERSIONED]
17 | mod.mc_dep_forgelike=[VERSIONED]
18 | # Used for the release title. I.e. '1.20.x'
19 | mod.mc_title=[VERSIONED]
20 | # Space separated versions for publishing. I.e. '1.20, 1.20.1'
21 | mod.mc_targets=[VERSIONED]
22 |
23 | # Mod setup
24 | deps.mixin_extras=0.4.1
25 | deps.fabric_loader=0.16.8
26 | deps.forge_loader=[VERSIONED]
27 | deps.neoforge_loader=[VERSIONED]
28 | deps.neoforge_patch=[VERSIONED]
29 |
30 | # Mod dependencies
31 | deps.yarn_build=[VERSIONED]
32 | deps.fabric_api=[VERSIONED]
33 | deps.libbamboo=[VERSIONED]
34 | deps.yacl=[VERSIONED]
35 | deps.modmenu=[VERSIONED]
36 |
37 | deps.appleskin=[VERSIONED]
38 | deps.appleskin_artifact=[VERSIONED]
39 | deps.armorchroma=[VERSIONED]
40 | deps.coldsweat=[VERSIONED]
41 | deps.coldsweat_artifact=[VERSIONED]
42 | deps.dehydration=[VERSIONED]
43 | deps.detailab=[VERSIONED]
44 | deps.environmentz=[VERSIONED]
45 | deps.farmers_delight_refabricated=[VERSIONED]
46 | deps.hotbarslotcycling=[VERSIONED]
47 | deps.legendary_survival_overhaul=[VERSIONED]
48 | deps.microdurability=[VERSIONED]
49 | deps.onebar=[VERSIONED]
50 | deps.quark=[VERSIONED]
51 | deps.raised=[VERSIONED]
52 | deps.raised_artifact=[VERSIONED]
53 | deps.statuseffectbars=[VERSIONED]
54 |
55 | # Publishing
56 | publish.modrinth = temczoTQ
57 | publish.curseforge = 623806
58 | publish.curseforge_slug = autohud
59 |
--------------------------------------------------------------------------------
/icon_large.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Crendgrim/AutoHUD/e6fd1ea95c3f74646c5c73d447d89f79eeef7c95/icon_large.png
--------------------------------------------------------------------------------
/neoforge/build.gradle.kts:
--------------------------------------------------------------------------------
1 | @file:Suppress("UnstableApiUsage")
2 |
3 | plugins {
4 | id("dev.architectury.loom")
5 | id("architectury-plugin")
6 | id("com.github.johnrengelman.shadow")
7 | id("maven-publish")
8 | id("me.modmuss50.mod-publish-plugin")
9 | }
10 |
11 | val loader = prop("loom.platform")!!
12 | val minecraft: String = stonecutter.current.version
13 | val common: Project = requireNotNull(stonecutter.node.sibling("")) {
14 | "No common project for $project"
15 | }
16 |
17 | version = "${mod.version}+$minecraft"
18 | group = "${mod.group}.$loader"
19 | base {
20 | archivesName.set(mod.id)
21 | }
22 | architectury {
23 | platformSetupLoomIde()
24 | neoForge()
25 | }
26 |
27 | val commonBundle: Configuration by configurations.creating {
28 | isCanBeConsumed = false
29 | isCanBeResolved = true
30 | }
31 |
32 | val shadowBundle: Configuration by configurations.creating {
33 | isCanBeConsumed = false
34 | isCanBeResolved = true
35 | }
36 |
37 | configurations {
38 | compileClasspath.get().extendsFrom(commonBundle)
39 | runtimeClasspath.get().extendsFrom(commonBundle)
40 | get("developmentNeoForge").extendsFrom(commonBundle)
41 | }
42 |
43 | repositories {
44 | maven("https://maven.neoforged.net/releases/")
45 | }
46 |
47 | dependencies {
48 | minecraft("com.mojang:minecraft:$minecraft")
49 | mappings(loom.layered {
50 | mappings("net.fabricmc:yarn:$minecraft+build.${common.mod.dep("yarn_build")}:v2")
51 | common.mod.dep("neoforge_patch").takeUnless { it.startsWith('[') }?.let {
52 | mappings("dev.architectury:yarn-mappings-patch-neoforge:$it")
53 | }
54 | })
55 | "neoForge"("net.neoforged:neoforge:${common.mod.dep("neoforge_loader")}")
56 |
57 | mapOf(
58 | "coldsweat" to "maven.modrinth:cold-sweat:${common.mod.dep("coldsweat_artifact")}",
59 | "hotbarslotcycling" to "fuzs.hotbarslotcycling:hotbarslotcycling-neoforge:{}",
60 | "raised" to "maven.modrinth:raised:NeoForge-${common.mod.dep("raised_artifact")}-{}",
61 | ).map { (modName, url) ->
62 | common.mod.dep("neoforge", modName) to url.replace("{}", common.mod.dep("neoforge", modName))
63 | }.filterNot { (version, _) ->
64 | version.startsWith("[")
65 | }.forEach { (_, url) ->
66 | modCompileOnly(url)
67 | }
68 |
69 | modImplementation(name="libbamboo", group="mod.crend", version="${common.mod.dep("libbamboo")}-neoforge")
70 | include(name="libbamboo", group="mod.crend", version="${common.mod.dep("libbamboo")}-neoforge")
71 |
72 | commonBundle(project(common.path, "namedElements")) { isTransitive = false }
73 | shadowBundle(project(common.path, "transformProductionNeoForge")) { isTransitive = false }
74 | }
75 |
76 | loom {
77 | decompilers {
78 | get("vineflower").apply { // Adds names to lambdas - useful for mixins
79 | options.put("mark-corresponding-synthetics", "1")
80 | }
81 | }
82 |
83 | runConfigs.all {
84 | isIdeConfigGenerated = true
85 | runDir = "../../../run"
86 | vmArgs("-Dmixin.debug.export=true")
87 | }
88 | }
89 |
90 | java {
91 | withSourcesJar()
92 | val java = if (stonecutter.eval(minecraft, ">=1.20.5"))
93 | JavaVersion.VERSION_21 else JavaVersion.VERSION_17
94 | targetCompatibility = java
95 | sourceCompatibility = java
96 | }
97 |
98 | tasks.jar {
99 | archiveClassifier = "dev"
100 | }
101 |
102 | tasks.remapJar {
103 | injectAccessWidener = true
104 | input = tasks.shadowJar.get().archiveFile
105 | archiveClassifier = loader
106 | dependsOn(tasks.shadowJar)
107 | }
108 |
109 | tasks.shadowJar {
110 | configurations = listOf(shadowBundle)
111 | archiveClassifier = "dev-shadow"
112 | exclude(
113 | "fabric.mod.json",
114 | "architectury.common.json",
115 | if (stonecutter.eval(minecraft, "<=1.20.4")) "META-INF/neoforge.mods.toml" else "META-INF/mods.toml"
116 | )
117 | }
118 |
119 | tasks.processResources {
120 | properties(
121 | listOf(
122 | if (stonecutter.eval(minecraft, "<=1.20.4")) "META-INF/mods.toml" else "META-INF/neoforge.mods.toml",
123 | "pack.mcmeta"
124 | ),
125 | "id" to mod.id,
126 | "name" to mod.name,
127 | "version" to mod.version,
128 | "minecraft" to common.mod.prop("mc_dep_forgelike")
129 | )
130 | }
131 |
132 | tasks.build {
133 | group = "versioned"
134 | description = "Must run through 'chiseledBuild'"
135 | }
136 |
137 | tasks.register("buildAndCollect") {
138 | group = "versioned"
139 | description = "Must run through 'chiseledBuild'"
140 | from(tasks.remapJar.get().archiveFile, tasks.remapSourcesJar.get().archiveFile)
141 | into(rootProject.layout.buildDirectory.file("libs/${mod.version}/$loader"))
142 | dependsOn("build")
143 | }
144 |
145 | publishing {
146 | publications {
147 | create("maven") {
148 | groupId = mod.prop("group")
149 | artifactId = mod.prop("id")
150 | version = "${mod.version}+${minecraft}-${loader}"
151 |
152 | artifact(tasks.remapJar.get().archiveFile)
153 | artifact(tasks.remapSourcesJar.get().archiveFile) {
154 | classifier = "sources"
155 | }
156 | }
157 | }
158 | }
159 |
160 | publishMods {
161 | displayName = "[NeoForge ${common.mod.prop("mc_title")}] ${mod.name} ${mod.version}"
162 |
163 | val modrinthToken = providers.gradleProperty("MODRINTH_TOKEN").orNull
164 | val curseforgeToken = providers.gradleProperty("CURSEFORGE_TOKEN").orNull
165 | dryRun = modrinthToken == null || curseforgeToken == null
166 |
167 | file = tasks.remapJar.get().archiveFile
168 | version = "${mod.version}+$minecraft-$loader"
169 | changelog = mod.prop("changelog")
170 | type = STABLE
171 | modLoaders.add(loader)
172 |
173 | val supportedVersions = common.mod.prop("mc_targets").split(" ")
174 |
175 | modrinth {
176 | projectId = property("publish.modrinth").toString()
177 | accessToken = modrinthToken
178 | minecraftVersions.addAll(supportedVersions)
179 |
180 | optional("yacl")
181 | }
182 | curseforge {
183 | projectId = property("publish.curseforge").toString()
184 | projectSlug = property("publish.curseforge_slug").toString()
185 | accessToken = curseforgeToken
186 | minecraftVersions.addAll(supportedVersions)
187 | clientRequired = true
188 | serverRequired = false
189 |
190 | optional("yacl")
191 | }
192 | }
193 |
--------------------------------------------------------------------------------
/neoforge/gradle.properties:
--------------------------------------------------------------------------------
1 | loom.platform=neoforge
--------------------------------------------------------------------------------
/neoforge/src/main/java/mod/crend/autohud/neoforge/AutoHudGui.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.neoforge;
2 |
3 | import mod.crend.autohud.component.Components;
4 | import mod.crend.autohud.render.ComponentRenderer;
5 | import net.minecraft.util.Identifier;
6 | import net.neoforged.bus.api.EventPriority;
7 | import net.neoforged.bus.api.SubscribeEvent;
8 | import net.neoforged.neoforge.client.event.CustomizeGuiOverlayEvent;
9 |
10 | import java.util.HashMap;
11 | import java.util.Map;
12 | import java.util.Optional;
13 |
14 | //? if <1.20.5 {
15 | import static net.neoforged.neoforge.client.gui.overlay.VanillaGuiOverlay.*;
16 | import net.neoforged.neoforge.client.event.RenderGuiOverlayEvent;
17 | //?} else {
18 | /*import static net.neoforged.neoforge.client.gui.VanillaGuiLayers.*;
19 | import net.neoforged.neoforge.client.event.RenderGuiLayerEvent;
20 | *///?}
21 |
22 | public class AutoHudGui {
23 |
24 | public static Map COMPONENT_RENDERERS = new HashMap<>();
25 | static {
26 | COMPONENT_RENDERERS.put(PLAYER_HEALTH/*? if <1.20.5 {*/.id()/*?}*/, ComponentRenderer.HEALTH);
27 | COMPONENT_RENDERERS.put(ARMOR_LEVEL/*? if <1.20.5 {*/.id()/*?}*/, ComponentRenderer.ARMOR);
28 | COMPONENT_RENDERERS.put(FOOD_LEVEL/*? if <1.20.5 {*/.id()/*?}*/, ComponentRenderer.HUNGER);
29 | COMPONENT_RENDERERS.put(AIR_LEVEL/*? if <1.20.5 {*/.id()/*?}*/, ComponentRenderer.AIR);
30 | COMPONENT_RENDERERS.put(/*? if <1.20.5 {*/MOUNT_HEALTH.id()/*?} else {*//*VEHICLE_HEALTH*//*?}*/, ComponentRenderer.MOUNT_HEALTH);
31 | COMPONENT_RENDERERS.put(/*? if <1.20.5 {*/JUMP_BAR.id()/*?} else {*//*JUMP_METER*//*?}*/, ComponentRenderer.MOUNT_JUMP_BAR);
32 | COMPONENT_RENDERERS.put(EXPERIENCE_BAR/*? if <1.20.5 {*/.id()/*?}*/, ComponentRenderer.EXPERIENCE_BAR);
33 | //? if >=1.20.5
34 | /*COMPONENT_RENDERERS.put(EXPERIENCE_LEVEL, ComponentRenderer.EXPERIENCE_LEVEL);*/
35 |
36 | COMPONENT_RENDERERS.put(/*? if <1.20.5 {*/SCOREBOARD.id()/*?} else {*//*SCOREBOARD_SIDEBAR*//*?}*/, ComponentRenderer.SCOREBOARD);
37 | COMPONENT_RENDERERS.put(HOTBAR/*? if <1.20.5 {*/.id()/*?}*/, ComponentRenderer.HOTBAR);
38 | COMPONENT_RENDERERS.put(/*? if <1.20.5 {*/ITEM_NAME.id()/*?} else {*//*SELECTED_ITEM_NAME*//*?}*/, ComponentRenderer.TOOLTIP);
39 | COMPONENT_RENDERERS.put(/*? if <1.20.5 {*/CHAT_PANEL.id()/*?} else {*//*CHAT*//*?}*/, ComponentRenderer.CHAT);
40 | COMPONENT_RENDERERS.put(/*? if <1.20.5 {*/TITLE_TEXT.id()/*?} else {*//*TITLE*//*?}*/, ComponentRenderer.ACTION_BAR);
41 | COMPONENT_RENDERERS.put(/*? if <1.20.5 {*/BOSS_EVENT_PROGRESS.id()/*?} else {*//*BOSS_OVERLAY*//*?}*/, ComponentRenderer.BOSS_BAR);
42 | }
43 |
44 | /*
45 | * NOTE: NeoForge before 1.21 handles events differently to Forge.
46 | * In Forge and modern NeoForge, canceling the event here would still call the handler below, so we would have to
47 | * still do the preRender step (and then immediately undo it in the other event).
48 | * In older NeoForge, this does not happen, and the second handler does not get invoked. So we can skip the matrix
49 | * translation right away.
50 | * We still keep the second event subscriber to hopefully catch any situation where another mod cancels one
51 | * of the handled overlay events.
52 | */
53 | @SubscribeEvent(priority = EventPriority.HIGHEST, receiveCanceled = true)
54 | public void preHudComponent(/*? if <1.20.5 {*/RenderGuiOverlayEvent/*?} else {*//*RenderGuiLayerEvent*//*?}*/.Pre event) {
55 | Optional.ofNullable(COMPONENT_RENDERERS.get(
56 | //? if <1.20.5 {
57 | event.getOverlay().id()
58 | //?} else
59 | /*event.getName()*/
60 | )).ifPresent(
61 | wrapper -> {
62 | if (wrapper.isActive() && !wrapper.doRender()) {
63 | event.setCanceled(true);
64 | }
65 | //? if <1.21
66 | else
67 | {
68 | wrapper.beginRender(event.getGuiGraphics());
69 | }
70 | }
71 | );
72 | }
73 | @SubscribeEvent(priority = EventPriority.LOWEST, receiveCanceled = true)
74 | public void cancelHudComponent(/*? if <1.20.5 {*/RenderGuiOverlayEvent/*?} else {*//*RenderGuiLayerEvent*//*?}*/.Pre event) {
75 | if (event.isCanceled()) {
76 | Optional.ofNullable(COMPONENT_RENDERERS.get(
77 | //? if <1.20.5 {
78 | event.getOverlay().id()
79 | //?} else
80 | /*event.getName()*/
81 | )).ifPresent(
82 | wrapper -> wrapper.endRender(event.getGuiGraphics())
83 | );
84 | }
85 | }
86 | @SubscribeEvent(priority = EventPriority.LOWEST, receiveCanceled = true)
87 | public void postHudComponent(/*? if <1.20.5 {*/RenderGuiOverlayEvent/*?} else {*//*RenderGuiLayerEvent*//*?}*/.Post event) {
88 | Optional.ofNullable(COMPONENT_RENDERERS.get(
89 | //? if <1.20.5 {
90 | event.getOverlay().id()
91 | //?} else
92 | /*event.getName()*/
93 | )).ifPresent(
94 | wrapper -> wrapper.endRender(event.getGuiGraphics())
95 | );
96 | }
97 |
98 | @SubscribeEvent
99 | public void preChat(CustomizeGuiOverlayEvent.Chat event) {
100 | if (Components.Chat.config.active()) {
101 | ComponentRenderer.CHAT.beginFade(event.getGuiGraphics());
102 | }
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/neoforge/src/main/java/mod/crend/autohud/neoforge/AutoHudModEvents.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.neoforge;
2 |
3 | import mod.crend.autohud.AutoHud;
4 | import mod.crend.autohud.ModKeyBindings;
5 | import mod.crend.autohud.api.AutoHudApi;
6 | import mod.crend.autohud.config.ConfigHandler;
7 | import mod.crend.autohud.compat.HotbarSlotCyclingCompat;
8 | import mod.crend.autohud.neoforge.compat.ColdSweatCompat;
9 | import mod.crend.autohud.render.AutoHudRenderer;
10 | import mod.crend.libbamboo.VersionUtils;
11 | import mod.crend.libbamboo.neoforge.ConfigScreen;
12 | import net.minecraft.util.Identifier;
13 | import net.neoforged.api.distmarker.Dist;
14 | import net.neoforged.bus.api.SubscribeEvent;
15 | import net.neoforged.fml.InterModComms;
16 | import net.neoforged.fml.ModList;
17 | import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent;
18 | import net.neoforged.fml.event.lifecycle.InterModProcessEvent;
19 | import net.neoforged.neoforge.client.event.RegisterKeyMappingsEvent;
20 | import net.neoforged.neoforge.common.NeoForge;
21 | //? if <1.20.5 {
22 | import net.neoforged.fml.common.Mod;
23 | import net.neoforged.neoforge.client.event.RegisterGuiOverlaysEvent;
24 | //?} else {
25 | /*import net.neoforged.fml.common.EventBusSubscriber;
26 | import net.neoforged.neoforge.client.event.RegisterGuiLayersEvent;
27 | *///?}
28 |
29 | //? if <1.20.5 {
30 | @Mod.EventBusSubscriber(modid = AutoHud.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT)
31 | //?} else
32 | /*@EventBusSubscriber(modid = AutoHud.MOD_ID, bus = EventBusSubscriber.Bus.MOD, value = Dist.CLIENT)*/
33 | public class AutoHudModEvents {
34 | public static final String REGISTER_API = "register_api";
35 | public static final Identifier NEW_CHAT_MESSAGE_INDICATOR = VersionUtils.getIdentifier(AutoHud.MOD_ID, "new_chat_message_indicator");
36 |
37 | @SubscribeEvent
38 | static void onClientSetup(FMLClientSetupEvent event) {
39 | AutoHud.init();
40 | ConfigScreen.register(ConfigHandler.CONFIG_STORE);
41 | NeoForge.EVENT_BUS.register(new AutoHudGui());
42 | if (ModList.get().isLoaded("hotbarslotcycling")) {
43 | AutoHud.addApi(new HotbarSlotCyclingCompat());
44 | }
45 | if (ModList.get().isLoaded("raised")) {
46 | AutoHudNeoForge.raisedCompat = true;
47 | }
48 | if (ModList.get().isLoaded("coldsweat")) {
49 | AutoHud.addApi(new ColdSweatCompat());
50 | }
51 | // Delay initialising the client tick event, see that method.
52 | NeoForge.EVENT_BUS.addListener(AutoHudNeoForge::onClientTick);
53 | }
54 |
55 | @SubscribeEvent
56 | static void onInterModProcess(InterModProcessEvent event) {
57 | InterModComms.getMessages(AutoHud.MOD_ID, REGISTER_API::equals)
58 | .map(msg -> (AutoHudApi) msg.messageSupplier().get())
59 | .forEach(AutoHud::addApi);
60 | }
61 |
62 | @SubscribeEvent
63 | static void onKeyMappingsRegister(RegisterKeyMappingsEvent event) {
64 | ModKeyBindings.ALL.forEach(event::register);
65 | }
66 |
67 | @SubscribeEvent
68 | static void onRegisterOverlaysEvent(/*? if <1.20.5 {*/RegisterGuiOverlaysEvent/*?} else {*//*RegisterGuiLayersEvent*//*?}*/ event) {
69 | event.registerAboveAll(NEW_CHAT_MESSAGE_INDICATOR,
70 | //? if <1.20.5 {
71 | (neoforgeGui, context, f, i, j) -> AutoHudRenderer.renderChatMessageIndicator(context, f)
72 | //?} else
73 | /*AutoHudRenderer::renderChatMessageIndicator*/
74 | );
75 | }
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/neoforge/src/main/java/mod/crend/autohud/neoforge/AutoHudNeoForge.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.neoforge;
2 |
3 | import mod.crend.autohud.AutoHud;
4 | import mod.crend.autohud.ModKeyBindings;
5 | import mod.crend.autohud.compat.RaisedCompat;
6 | import mod.crend.autohud.component.Components;
7 | import mod.crend.autohud.render.AutoHudRenderer;
8 | import net.minecraft.client.MinecraftClient;
9 | import net.neoforged.api.distmarker.Dist;
10 | import net.neoforged.bus.api.SubscribeEvent;
11 | import net.neoforged.fml.common.Mod;
12 | import net.neoforged.neoforge.client.event.ClientChatReceivedEvent;
13 | import net.neoforged.neoforge.client.event.RenderGuiEvent;
14 | //? if <1.20.5 {
15 | import net.neoforged.neoforge.event.TickEvent;
16 | //?} else {
17 | /*import net.neoforged.fml.common.EventBusSubscriber;
18 | import net.neoforged.neoforge.client.event.ClientTickEvent;
19 | *///?}
20 |
21 | @Mod(AutoHud.MOD_ID)
22 | //? if <1.20.5 {
23 | @Mod.EventBusSubscriber(value = Dist.CLIENT)
24 | //?} else
25 | /*@EventBusSubscriber(value = Dist.CLIENT)*/
26 | public class AutoHudNeoForge {
27 | static boolean raisedCompat = false;
28 |
29 | public AutoHudNeoForge() {
30 | AutoHud.loadConfig();
31 | }
32 |
33 | // Do not use @SubscribeEvent here because the mod "placebo" forces the game bus to run early for some reason.
34 | // This causes the key bindings to get ticked before the config is loaded...
35 | static void onClientTick(
36 | //? if <1.20.5 {
37 | TickEvent.ClientTickEvent event
38 | //?} else
39 | /*ClientTickEvent.Post event*/
40 | ) {
41 | //? if <1.20.5
42 | if (event.phase == TickEvent.Phase.START) return;
43 |
44 | ModKeyBindings.clientTick(MinecraftClient.getInstance());
45 |
46 | if (raisedCompat) {
47 | RaisedCompat.tick();
48 | }
49 | }
50 |
51 | @SubscribeEvent
52 | static void onPreRenderGuiEvent(RenderGuiEvent.Pre event) {
53 | AutoHudRenderer.startRender(event.getGuiGraphics(), event.getPartialTick());
54 | }
55 | @SubscribeEvent
56 | static void onPostRenderGuiEvent(RenderGuiEvent.Post event) {
57 | AutoHudRenderer.endRender();
58 | }
59 |
60 | @SubscribeEvent
61 | static void onChatMessageReceived(ClientChatReceivedEvent event) {
62 | if (Components.Chat.config.active() && Components.ChatIndicator.config.active() && Components.Chat.isHidden()) {
63 | Components.ChatIndicator.reveal();
64 | }
65 | }
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/neoforge/src/main/java/mod/crend/autohud/neoforge/compat/ColdSweatCompat.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.neoforge.compat;
2 |
3 | //? if coldsweat {
4 | /*import com.momosoftworks.coldsweat.ColdSweat;
5 | import com.momosoftworks.coldsweat.api.util.Temperature;
6 | import com.momosoftworks.coldsweat.client.gui.Overlays;
7 | import com.momosoftworks.coldsweat.common.capability.handler.EntityTempManager;
8 | import com.momosoftworks.coldsweat.common.capability.temperature.PlayerTempCap;
9 | import com.momosoftworks.coldsweat.config.ConfigSettings;
10 | import mod.crend.autohud.component.Component;
11 | import mod.crend.autohud.component.state.ValueComponentState;
12 | import mod.crend.autohud.config.ConfigHandler;
13 | import mod.crend.autohud.neoforge.AutoHudGui;
14 | import mod.crend.autohud.render.ComponentRenderer;
15 | import net.minecraft.client.network.ClientPlayerEntity;
16 | *///?}
17 | import mod.crend.autohud.api.AutoHudApi;
18 |
19 | public class ColdSweatCompat implements AutoHudApi {
20 | @Override
21 | public String modId() {
22 | return "cold_sweat";
23 | }
24 |
25 | //? if coldsweat {
26 | /*public static Component BODY_TEMP_GAUGE = Component.builder(ColdSweat.MOD_ID, "body_temp")
27 | .inMainHud()
28 | .config(ConfigHandler.DummyBooleanComponent)
29 | .state(player -> new ValueComponentState<>(ColdSweatCompat.BODY_TEMP_GAUGE, () -> Overlays.BODY_TEMP, true))
30 | .build();
31 | public static Component WORLD_TEMP_GAUGE = Component.builder(ColdSweat.MOD_ID, "world_temp")
32 | .inMainHud()
33 | .config(ConfigHandler.DummyBooleanComponent)
34 | .state(player -> new TemperatureState(ColdSweatCompat.WORLD_TEMP_GAUGE))
35 | .build();
36 | public static Component VAGUE_TEMP_GAUGE = Component.builder(ColdSweat.MOD_ID, "vague_temp")
37 | .inMainHud()
38 | .config(ConfigHandler.DummyBooleanComponent)
39 | .state(player -> new TemperatureState(ColdSweatCompat.VAGUE_TEMP_GAUGE))
40 | .build();
41 |
42 | static class TemperatureState extends ValueComponentState {
43 | static double PLAYER_MAX_TEMP;
44 | static double PLAYER_MIN_TEMP;
45 |
46 | public TemperatureState(Component component) {
47 | super(component, () -> {
48 | double temp = Temperature.convert(Overlays.WORLD_TEMP, ConfigSettings.CELSIUS.get() ? Temperature.Units.C : Temperature.Units.F, Temperature.Units.MC, true);
49 | return Overlays.getGaugeSeverity(temp, PLAYER_MIN_TEMP, PLAYER_MAX_TEMP);
50 | }, true);
51 | }
52 |
53 | @Override
54 | protected boolean doReveal(Integer newValue) {
55 | return super.doReveal(newValue) || newValue < -2 || newValue > 2;
56 | }
57 | }
58 |
59 | @Override
60 | public void tickState(ClientPlayerEntity player) {
61 | EntityTempManager.getTemperatureCap(player).ifPresent((icap) -> {
62 | if (icap instanceof PlayerTempCap cap) {
63 | TemperatureState.PLAYER_MAX_TEMP = cap.getTrait(Temperature.Trait.BURNING_POINT);
64 | TemperatureState.PLAYER_MIN_TEMP = cap.getTrait(Temperature.Trait.FREEZING_POINT);
65 | }
66 | });
67 | }
68 |
69 | public static ComponentRenderer BODY_TEMP_RENDERER = ComponentRenderer.of(BODY_TEMP_GAUGE);
70 | public static ComponentRenderer WORLD_TEMP_RENDERER = ComponentRenderer.of(WORLD_TEMP_GAUGE);
71 | public static ComponentRenderer VAGUE_TEMP_RENDERER = ComponentRenderer.of(VAGUE_TEMP_GAUGE);
72 |
73 | @Override
74 | public void init() {
75 | AutoHudGui.COMPONENT_RENDERERS.put(BODY_TEMP_GAUGE.identifier, BODY_TEMP_RENDERER);
76 | AutoHudGui.COMPONENT_RENDERERS.put(WORLD_TEMP_GAUGE.identifier, WORLD_TEMP_RENDERER);
77 | AutoHudGui.COMPONENT_RENDERERS.put(VAGUE_TEMP_GAUGE.identifier, VAGUE_TEMP_RENDERER);
78 | }
79 | *///?}
80 | }
81 |
--------------------------------------------------------------------------------
/neoforge/src/main/java/mod/crend/autohud/neoforge/mixin/gui/InGameHudMixin.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.neoforge.mixin.gui;
2 |
3 | import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
4 | import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
5 | import com.llamalad7.mixinextras.sugar.Local;
6 | import mod.crend.autohud.AutoHud;
7 | import mod.crend.autohud.component.Component;
8 | import mod.crend.autohud.component.Hud;
9 | import mod.crend.autohud.render.AutoHudRenderer;
10 | import mod.crend.autohud.render.ComponentRenderer;
11 | import net.minecraft.client.gui.DrawContext;
12 | import net.minecraft.client.gui.hud.InGameHud;
13 | //? if >=1.21
14 | /*import net.minecraft.client.render.RenderLayer;*/
15 | import net.minecraft.client.render.RenderTickCounter;
16 | import net.minecraft.client.texture.Sprite;
17 | import net.minecraft.entity.effect.StatusEffectInstance;
18 | import net.minecraft.entity.player.PlayerEntity;
19 | import net.minecraft.item.ItemStack;
20 | import net.minecraft.util.Identifier;
21 | import net.neoforged.neoforge.client.extensions.common.IClientMobEffectExtensions;
22 | import org.spongepowered.asm.mixin.Mixin;
23 | import org.spongepowered.asm.mixin.injection.*;
24 |
25 | import java.util.concurrent.atomic.AtomicBoolean;
26 | import java.util.function.Function;
27 |
28 | @Mixin(value = InGameHud.class, priority = 800)
29 | public class InGameHudMixin {
30 |
31 | // Hotbar items
32 | @WrapOperation(
33 | //? if <1.20.5 {
34 | method = "renderHotbar",
35 | //?} else
36 | /*method = "renderHotbarVanilla",*/
37 | at = @At(
38 | value = "INVOKE",
39 | //? if <1.21 {
40 | target = "Lnet/minecraft/client/gui/hud/InGameHud;renderHotbarItem(Lnet/minecraft/client/gui/DrawContext;IIFLnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/item/ItemStack;I)V"
41 | //?} else
42 | /*target = "Lnet/minecraft/client/gui/hud/InGameHud;renderHotbarItem(Lnet/minecraft/client/gui/DrawContext;IILnet/minecraft/client/render/RenderTickCounter;Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/item/ItemStack;I)V"*/
43 | )
44 | )
45 | private void autoHud$transparentHotbarItems(
46 | InGameHud instance,
47 | DrawContext context,
48 | int x, int y,
49 | //? if <1.21 {
50 | float tickCounter,
51 | //?} else
52 | /*RenderTickCounter tickCounter,*/
53 | PlayerEntity player,
54 | ItemStack stack,
55 | int seed,
56 | Operation original
57 | ) {
58 | ComponentRenderer.HOTBAR_ITEMS.wrap(context, () -> original.call(instance, context, x, y, tickCounter, player, stack, seed));
59 | }
60 |
61 |
62 | // Crosshair
63 | @WrapOperation(method = "renderCrosshair",
64 | slice = @Slice(
65 | //? if <1.21.2
66 | from = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/systems/RenderSystem;blendFuncSeparate(Lcom/mojang/blaze3d/platform/GlStateManager$SrcFactor;Lcom/mojang/blaze3d/platform/GlStateManager$DstFactor;Lcom/mojang/blaze3d/platform/GlStateManager$SrcFactor;Lcom/mojang/blaze3d/platform/GlStateManager$DstFactor;)V"),
67 | to = @At(value = "INVOKE", target = "Lnet/minecraft/client/option/GameOptions;getAttackIndicator()Lnet/minecraft/client/option/SimpleOption;")
68 | ),
69 | at = @At(
70 | value = "INVOKE",
71 | //? if <1.21.2 {
72 | target = "Lnet/minecraft/client/gui/DrawContext;drawGuiTexture(Lnet/minecraft/util/Identifier;IIII)V"
73 | //?} else
74 | /*target = "Lnet/minecraft/client/gui/DrawContext;drawGuiTexture(Ljava/util/function/Function;Lnet/minecraft/util/Identifier;IIII)V"*/
75 | )
76 | )
77 | private void autoHud$renderCrosshair(
78 | DrawContext context,
79 | //? if >=1.21.2
80 | /*Function renderLayer,*/
81 | Identifier texture,
82 | int x, int y,
83 | int width, int height,
84 | Operation original
85 | ) {
86 | ComponentRenderer.CROSSHAIR.wrap(context, () -> original.call(
87 | context,
88 | //? if >=1.21.2
89 | /*renderLayer,*/
90 | texture,
91 | x, y,
92 | width, height
93 | ));
94 | }
95 |
96 |
97 | // Status Effects
98 | @WrapOperation(
99 | method = "renderStatusEffectOverlay",
100 | at = @At(
101 | value = "INVOKE",
102 | //? if <1.21.2 {
103 | target = "Lnet/minecraft/client/gui/DrawContext;drawGuiTexture(Lnet/minecraft/util/Identifier;IIII)V"
104 | //?} else
105 | /*target = "Lnet/minecraft/client/gui/DrawContext;drawGuiTexture(Ljava/util/function/Function;Lnet/minecraft/util/Identifier;IIII)V"*/
106 | )
107 | )
108 | private void autoHud$statusEffectBackground(
109 | DrawContext context,
110 | //? if >=1.21.2
111 | /*Function renderLayer,*/
112 | Identifier texture,
113 | int x, int y,
114 | int width, int height,
115 | Operation original,
116 | @Local StatusEffectInstance statusEffectInstance
117 | ) {
118 | ComponentRenderer.getForStatusEffect(statusEffectInstance).wrap(context, () -> original.call(
119 | context,
120 | //? if >=1.21.2
121 | /*renderLayer,*/
122 | texture,
123 | x, y,
124 | width, height
125 | ));
126 | }
127 |
128 | @WrapOperation(method = "renderStatusEffectOverlay", at = @At(value = "INVOKE", target = "Lnet/neoforged/neoforge/client/extensions/common/IClientMobEffectExtensions;renderGuiIcon(Lnet/minecraft/entity/effect/StatusEffectInstance;Lnet/minecraft/client/gui/hud/InGameHud;Lnet/minecraft/client/gui/DrawContext;IIFF)Z"))
129 | private boolean autoHud$postEffect(IClientMobEffectExtensions instance, StatusEffectInstance statusEffectInstance, InGameHud gui, DrawContext context, int x, int y, float z, float alpha, Operation original) {
130 | AtomicBoolean result = new AtomicBoolean(false);
131 | ComponentRenderer.getForStatusEffect(statusEffectInstance).wrap(context, () ->
132 | result.set(original.call(instance, statusEffectInstance, gui, context, x, y, z, alpha))
133 | );
134 | return result.get();
135 | }
136 |
137 | @WrapOperation(
138 | //? if <1.20.5 {
139 | method = {"m_279741_", "method_18620"},
140 | //?} else if <1.21.2 {
141 | //method = "lambda$renderEffects$10",
142 | //?} else
143 | /*method = "lambda$renderEffects$11",*/
144 | at = @At(
145 | value = "INVOKE",
146 | //? if <1.21.2 {
147 | target = "Lnet/minecraft/client/gui/DrawContext;drawSprite(IIIIILnet/minecraft/client/texture/Sprite;)V"
148 | //?} else
149 | /*target = "Lnet/minecraft/client/gui/DrawContext;drawSpriteStretched(Ljava/util/function/Function;Lnet/minecraft/client/texture/Sprite;IIIII)V"*/
150 | ),
151 | require = 0
152 | )
153 | private static void autoHud$preSprite(
154 | DrawContext context,
155 | //? if >=1.21.2 {
156 | /*Function renderLayer,
157 | Sprite sprite,
158 | *///?}
159 | int x, int y, int z,
160 | int width, int height,
161 | //? if <1.21.2
162 | Sprite sprite,
163 | Operation original
164 | ) {
165 | ComponentRenderer.getForStatusEffect(sprite).wrap(context,
166 | //? if <1.21.2 {
167 | () -> original.call(context, x, y, z, width, height, sprite)
168 | //?} else
169 | /*() -> original.call(context, renderLayer, sprite, x, y, z, width, height)*/
170 | );
171 | }
172 |
173 | @WrapOperation(method = "renderStatusEffectOverlay", at = @At(value = "INVOKE", target="Lnet/minecraft/entity/effect/StatusEffectInstance;shouldShowIcon()Z"))
174 | private boolean autoHud$shouldShowIconProxy(StatusEffectInstance instance, Operation original) {
175 | return (original.call(instance) || AutoHud.config.showHiddenStatusEffects()) && Hud.shouldShowIcon(instance);
176 | }
177 |
178 | }
179 |
--------------------------------------------------------------------------------
/neoforge/src/main/java/mod/crend/autohud/neoforge/mixin/gui/StatusEffectTimerMixin.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.neoforge.mixin.gui;
2 |
3 | import com.llamalad7.mixinextras.sugar.Local;
4 | import mod.crend.autohud.AutoHud;
5 | import mod.crend.autohud.render.ComponentRenderer;
6 | import mod.crend.libbamboo.PlatformUtils;
7 | import net.minecraft.client.MinecraftClient;
8 | import net.minecraft.client.gui.DrawContext;
9 | import net.minecraft.client.gui.hud.InGameHud;
10 | import net.minecraft.client.render.RenderTickCounter;
11 | import net.minecraft.client.resource.language.I18n;
12 | import net.minecraft.entity.effect.StatusEffectInstance;
13 | import net.minecraft.util.math.MathHelper;
14 | import org.spongepowered.asm.mixin.Final;
15 | import org.spongepowered.asm.mixin.Mixin;
16 | import org.spongepowered.asm.mixin.Shadow;
17 | import org.spongepowered.asm.mixin.Unique;
18 | import org.spongepowered.asm.mixin.injection.At;
19 | import org.spongepowered.asm.mixin.injection.Inject;
20 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
21 |
22 | import java.util.List;
23 |
24 | /*
25 | * This file is originally part of the StatusEffectTimer mod:
26 | * https://github.com/magicus/statuseffecttimer
27 | *
28 | * It is included here in order to be modified properly.
29 | * Changes:
30 | * - Skip timers for hidden effects by redirecting StatusEffectInstance.shouldShowIcon()
31 | * - Insert matrix push/pop for moving each timer text with its icon
32 | */
33 |
34 | // Set priority to 500, to load before default at 1000. This is to better cooperate with HUDTweaks.
35 | @Mixin(value = InGameHud.class, priority = 500)
36 | public abstract class StatusEffectTimerMixin {
37 | @Shadow @Final
38 | private MinecraftClient client;
39 |
40 | @Inject(method = "renderStatusEffectOverlay",
41 | at = @At(value = "INVOKE", target = "Ljava/util/List;add(Ljava/lang/Object;)Z", shift = At.Shift.AFTER))
42 | private void appendOverlayDrawing(
43 | DrawContext context,
44 | //? if >1.20.6 {
45 | /*RenderTickCounter tickDelta,
46 | *///?} else if >1.20.5
47 | /*float tickDelta,*/
48 | CallbackInfo c,
49 | @Local List list,
50 | @Local StatusEffectInstance statusEffectInstance,
51 | @Local(ordinal = 2) int i2,
52 | @Local(ordinal = 3) int i3,
53 | @Local(ordinal = 4) int i4,
54 | @Local(ordinal = 5) int i5
55 | ) {
56 | list.add(() -> {
57 | if (AutoHud.config.statusEffectTimer()) {
58 | int x = switch (PlatformUtils.getCurrentPlatform()) {
59 | case FABRIC -> i4;
60 | case FORGE -> i5;
61 | case NEOFORGE -> i2;
62 | };
63 | int y = switch (PlatformUtils.getCurrentPlatform()) {
64 | case FABRIC -> i5;
65 | case FORGE -> i3;
66 | case NEOFORGE -> i3;
67 | };
68 | ComponentRenderer.getForStatusEffect(statusEffectInstance).wrap(context, () -> drawStatusEffectOverlay(context, statusEffectInstance, x, y));
69 | }
70 | });
71 | }
72 |
73 | @Unique
74 | private void drawStatusEffectOverlay(DrawContext context, StatusEffectInstance statusEffectInstance, int x, int y) {
75 | String duration = getDurationAsString(statusEffectInstance);
76 | int durationLength = client.textRenderer.getWidth(duration);
77 | context.drawTextWithShadow(client.textRenderer, duration, x + 13 - (durationLength / 2), y + 14, 0x99FFFFFF);
78 |
79 | int amplifier = statusEffectInstance.getAmplifier();
80 | if (amplifier > 0) {
81 | // Convert to roman numerals if possible
82 | String amplifierString = (amplifier < 10) ? I18n.translate("enchantment.level." + (amplifier + 1)) : "**";
83 | int amplifierLength = client.textRenderer.getWidth(amplifierString);
84 | context.drawTextWithShadow(client.textRenderer, amplifierString, x + 22 - amplifierLength, y + 3, 0x99FFFFFF);
85 | }
86 | }
87 |
88 | @Unique
89 | private String getDurationAsString(StatusEffectInstance statusEffectInstance) {
90 | if (statusEffectInstance.isInfinite()) {
91 | return I18n.translate("effect.duration.infinite");
92 | }
93 |
94 | int ticks = MathHelper.floor((float) statusEffectInstance.getDuration());
95 | int seconds = ticks / 20;
96 |
97 | if (seconds >= 3600) {
98 | return seconds / 3600 + "h";
99 | } else if (seconds >= 60) {
100 | return seconds / 60 + "m";
101 | } else {
102 | return String.valueOf(seconds);
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/neoforge/src/main/resources/META-INF/mods.toml:
--------------------------------------------------------------------------------
1 | modLoader = "javafml"
2 | loaderVersion = "*"
3 | issueTrackerURL = "https://github.com/Crendgrim/AutoHUD/issues"
4 | license = "LGPL-3.0"
5 |
6 | [[mods]]
7 | modId = "${id}"
8 | version = "${version}"
9 | displayName = "${name}"
10 | authors = "Crendgrim"
11 | description = '''
12 | Dynamic HUD that hides interface elements while they are not needed.
13 | '''
14 | logoFile = "autohud.png"
15 | logoBlur = false
16 | displayTest = "IGNORE_ALL_VERSION"
17 |
18 | [[mixins]]
19 | config = "autohud-common.mixins.json"
20 |
21 | [[mixins]]
22 | config = "autohud-common-compat.mixins.json"
23 |
24 | [[mixins]]
25 | config = "autohud-neoforge.mixins.json"
--------------------------------------------------------------------------------
/neoforge/src/main/resources/META-INF/neoforge.mods.toml:
--------------------------------------------------------------------------------
1 | modLoader = "javafml"
2 | loaderVersion = "*"
3 | issueTrackerURL = "https://github.com/Crendgrim/AutoHUD/issues"
4 | license = "LGPL-3.0"
5 |
6 | [[mods]]
7 | modId = "${id}"
8 | version = "${version}"
9 | displayName = "${name}"
10 | authors = "Crendgrim"
11 | description = '''
12 | Dynamic HUD that hides interface elements while they are not needed.
13 | '''
14 | logoFile = "autohud.png"
15 | logoBlur = false
16 | displayTest = "IGNORE_ALL_VERSION"
17 |
18 | [[mixins]]
19 | config = "autohud-common.mixins.json"
20 |
21 | [[mixins]]
22 | config = "autohud-common-compat.mixins.json"
23 |
24 | [[mixins]]
25 | config = "autohud-neoforge.mixins.json"
--------------------------------------------------------------------------------
/neoforge/src/main/resources/autohud-neoforge.mixins.json:
--------------------------------------------------------------------------------
1 | {
2 | "required": true,
3 | "minVersion": "0.8",
4 | "package": "mod.crend.autohud.neoforge.mixin",
5 | "compatibilityLevel": "JAVA_17",
6 | "client": [
7 | "gui.InGameHudMixin",
8 | "gui.StatusEffectTimerMixin"
9 | ],
10 | "injectors": {
11 | "defaultRequire": 1
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/neoforge/src/main/resources/pack.mcmeta:
--------------------------------------------------------------------------------
1 | {
2 | "pack": {
3 | "description": "AutoHUD",
4 | "pack_format": 9
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/screenshot1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Crendgrim/AutoHUD/e6fd1ea95c3f74646c5c73d447d89f79eeef7c95/screenshot1.png
--------------------------------------------------------------------------------
/screenshot2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Crendgrim/AutoHUD/e6fd1ea95c3f74646c5c73d447d89f79eeef7c95/screenshot2.png
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | mavenCentral()
4 | gradlePluginPortal()
5 | maven("https://maven.fabricmc.net/")
6 | maven("https://maven.architectury.dev")
7 | maven("https://maven.minecraftforge.net")
8 | maven("https://maven.neoforged.net/releases/")
9 | maven("https://maven.kikugie.dev/snapshots")
10 | }
11 | }
12 |
13 | plugins {
14 | id("dev.kikugie.stonecutter") version "0.5-beta.5"
15 | }
16 |
17 | var fabricVersions = linkedSetOf( "1.20.1", "1.20.4", "1.20.6", "1.21.1", "1.21.3")
18 | var forgeVersions = linkedSetOf( "1.20.1", "1.20.4", "1.20.6", "1.21.1", "1.21.3")
19 | var neoforgeVersions = linkedSetOf( "1.20.4", "1.20.6", "1.21.1", "1.21.3")
20 |
21 | stonecutter {
22 | centralScript = "build.gradle.kts"
23 | kotlinController = true
24 | create(rootProject) {
25 | // Root `src/` functions as the 'common' project
26 | versions(fabricVersions + forgeVersions + neoforgeVersions)
27 | branch("fabric") { versions(fabricVersions) }
28 | branch("forge") { versions(forgeVersions) }
29 | branch("neoforge") { versions(neoforgeVersions) }
30 | }
31 | }
32 |
33 | rootProject.name = "Auto HUD"
--------------------------------------------------------------------------------
/src/main/java/mod/crend/autohud/AutoHud.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud;
2 |
3 | import mod.crend.autohud.api.AutoHudApi;
4 | import mod.crend.autohud.component.EventHandler;
5 | import mod.crend.autohud.component.Hud;
6 | import mod.crend.autohud.config.ConfigHandler;
7 | import mod.crend.libbamboo.PlatformUtils;
8 | import mod.crend.libbamboo.event.GameEvent;
9 |
10 | import java.util.ArrayList;
11 | import java.util.List;
12 |
13 | public class AutoHud {
14 |
15 | public static final String MOD_ID = "autohud";
16 |
17 | public static ConfigHandler config;
18 | public static final List apis = new ArrayList<>();
19 |
20 | // These are global toggles that are usually always true.
21 | // Whole sections may be disabled using these flags to enhance mod compatibility.
22 | public static boolean targetHotbar = true;
23 | public static boolean targetExperienceBar = true;
24 | public static boolean targetStatusBars = true;
25 | public static boolean targetScoreboard = true;
26 | public static boolean targetStatusEffects = true;
27 | public static boolean targetCrosshair = true;
28 | public static boolean targetChat = true;
29 |
30 | public static void loadConfig() {
31 | config = new ConfigHandler();
32 | }
33 | public static void init() {
34 | if (config.dynamicOnLoad()) {
35 | Hud.enableDynamic();
36 | }
37 | GameEvent.WORLD_LOAD.register(Hud::registerState);
38 | GameEvent.WORLD_TICK.register(Hud::tickState);
39 | GameEvent.WORLD_UNLOAD.register(Hud::unregisterState);
40 | GameEvent.PLAYER_RESPAWN.register(Hud::registerState);
41 | EventHandler.registerEvents();
42 | }
43 |
44 | public static void addApi(AutoHudApi api) {
45 | if (PlatformUtils.isModLoaded(api.modId())) {
46 | apis.add(api);
47 | api.init();
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/mod/crend/autohud/AutoHudCompatMixinPlugin.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud;
2 |
3 | import mod.crend.libbamboo.PlatformUtils;
4 | import org.objectweb.asm.tree.ClassNode;
5 | import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
6 | import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
7 |
8 | import java.util.List;
9 | import java.util.Set;
10 |
11 | public class AutoHudCompatMixinPlugin implements IMixinConfigPlugin {
12 |
13 | @Override
14 | public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
15 | String[] split = mixinClassName.split("\\.compat\\.mixin\\.");
16 | if (split.length == 2) {
17 | String modid = split[1].split("\\.")[0];
18 | // Special handling for mods with - in their mod id
19 | if (modid.equals("statuseffectbars")) {
20 | modid = "status-effect-bars";
21 | }
22 | return PlatformUtils.isModPresent(modid);
23 | }
24 | return true;
25 | }
26 |
27 | @Override
28 | public void onLoad(String mixinPackage) {
29 | }
30 |
31 | @Override
32 | public String getRefMapperConfig() {
33 | return null;
34 | }
35 |
36 | @Override
37 | public void acceptTargets(Set myTargets, Set otherTargets) {
38 |
39 | }
40 |
41 | @Override
42 | public List getMixins() {
43 | return null;
44 | }
45 |
46 | @Override
47 | public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
48 |
49 | }
50 |
51 | @Override
52 | public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
53 |
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/main/java/mod/crend/autohud/ModKeyBindings.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud;
2 |
3 | import mod.crend.autohud.component.Hud;
4 | import net.minecraft.client.MinecraftClient;
5 | import net.minecraft.client.option.KeyBinding;
6 | import net.minecraft.client.util.InputUtil;
7 | import org.lwjgl.glfw.GLFW;
8 |
9 | import java.util.List;
10 |
11 | public class ModKeyBindings {
12 | public static final String CATEGORY = "key.category.autohud";
13 |
14 | public static final KeyBinding TOGGLE_HUD = new KeyBinding(
15 | "key.autohud.toggle-hud",
16 | InputUtil.Type.KEYSYM,
17 | GLFW.GLFW_KEY_G,
18 | CATEGORY
19 | );
20 |
21 | public static KeyBinding PEEK_HUD = new KeyBinding(
22 | "key.autohud.peek-hud",
23 | InputUtil.Type.KEYSYM,
24 | GLFW.GLFW_KEY_R,
25 | CATEGORY
26 | );
27 |
28 | public static final List ALL = List.of(
29 | TOGGLE_HUD,
30 | PEEK_HUD
31 | );
32 |
33 | public static void clientTick(MinecraftClient client) {
34 | while (TOGGLE_HUD.wasPressed()) {
35 | Hud.toggleHud();
36 | }
37 | Hud.peekHud(PEEK_HUD.isPressed());
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/mod/crend/autohud/api/AutoHudApi.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.api;
2 |
3 | import net.minecraft.client.network.ClientPlayerEntity;
4 |
5 | public interface AutoHudApi {
6 | /**
7 | * We want to load the compatibility module only if the targeted mod is present.
8 | * @return the targeted mod's ID, as defined in its fabric.mod.json
9 | */
10 | String modId();
11 |
12 | /**
13 | * Implement this method for a one-time initialisation on game start.
14 | */
15 | default void init() { }
16 |
17 | /**
18 | * Implement this method to initialize a component
19 | * @param player currently active player
20 | */
21 | default void initState(ClientPlayerEntity player) { }
22 |
23 | /**
24 | * Implement this method to add special component handling on ticks
25 | * @param player currently active player
26 | */
27 | default void tickState(ClientPlayerEntity player) { }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/mod/crend/autohud/compat/HotbarSlotCyclingCompat.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.compat;
2 |
3 | import mod.crend.autohud.api.AutoHudApi;
4 |
5 | //? if hotbarslotcycling {
6 | /*import fuzs.hotbarslotcycling.api.v1.client.CyclingSlotsRenderer;
7 | import fuzs.hotbarslotcycling.api.v1.client.HotbarCyclingProvider;
8 | import mod.crend.autohud.AutoHud;
9 | import mod.crend.autohud.api.AutoHudApi;
10 | import mod.crend.autohud.component.Component;
11 | import mod.crend.autohud.component.Components;
12 | import mod.crend.autohud.component.state.ItemStackComponentState;
13 | import mod.crend.autohud.render.AutoHudRenderer;
14 | import mod.crend.autohud.render.AutoHudRenderLayer;
15 | import mod.crend.autohud.render.ComponentRenderer;
16 | import net.minecraft.client.font.TextRenderer;
17 | import net.minecraft.client.gui.DrawContext;
18 | import net.minecraft.client.network.ClientPlayerEntity;
19 | import net.minecraft.entity.player.PlayerEntity;
20 | import net.minecraft.item.ItemStack;
21 | *///?}
22 |
23 | public class HotbarSlotCyclingCompat implements AutoHudApi {
24 | @Override
25 | public String modId() {
26 | return "hotbarslotcycling";
27 | }
28 |
29 | //? if hotbarslotcycling {
30 |
31 | /*public static Component HOTBAR_SLOT_CYCLING_COMPONENT = Component.builder("hotbarslotcycling")
32 | .isTargeted(() -> AutoHud.targetHotbar)
33 | .config(AutoHud.config.hotbar())
34 | .inMainHud()
35 | .state(player -> new ItemStackComponentState(
36 | HotbarSlotCyclingCompat.HOTBAR_SLOT_CYCLING_COMPONENT,
37 | () -> HotbarCyclingProvider.GLOBAL_PROVIDER[0].apply(player).getForwardStack(),
38 | true
39 | ))
40 | .build();
41 | public static ComponentRenderer COMPONENT_WRAPPER = ComponentRenderer.of(HOTBAR_SLOT_CYCLING_COMPONENT);
42 | public static ComponentRenderer BACKGROUND_WRAPPER = ComponentRenderer.builder(HOTBAR_SLOT_CYCLING_COMPONENT)
43 | .fade()
44 | .isActive(() -> HOTBAR_SLOT_CYCLING_COMPONENT.isActive() && AutoHud.config.animationFade())
45 | .doRender(AutoHudRenderer::shouldRenderHotbarItems)
46 | .withCustomFramebuffer(true)
47 | .beginRender(COMPONENT_WRAPPER::endFade)
48 | .build();
49 | public static ComponentRenderer ITEM_WRAPPER = ComponentRenderer.builder(HOTBAR_SLOT_CYCLING_COMPONENT)
50 | .fade()
51 | .isActive(() -> HOTBAR_SLOT_CYCLING_COMPONENT.isActive() && AutoHud.config.animationFade())
52 | .doRender(() -> (
53 | // Render items when they're not fully hidden (in other words, visible in some way)
54 | !HOTBAR_SLOT_CYCLING_COMPONENT.fullyHidden()
55 | // If we are in fade mode, only render items if they're not fully transparent.
56 | || (AutoHud.config.animationFade() && AutoHud.config.getHotbarItemsMaximumFade() > 0.0f)
57 | // If we are neither in fade nor move mode, skip rendering if it's hidden.
58 | // If we are in move mode, the items may still be visible in the "hidden" state!
59 | || (!AutoHud.config.animationFade() && AutoHud.config.animationMove())
60 | ))
61 | .withCustomFramebuffer(true)
62 | .beginRender(COMPONENT_WRAPPER::endFade)
63 | .build();
64 |
65 | @Override
66 | public void init() {
67 | CyclingSlotsRenderer.setSlotsRenderer(new WrappedCyclingSlotsRenderer(CyclingSlotsRenderer.getSlotsRenderer()));
68 | }
69 |
70 | @Override
71 | public void initState(ClientPlayerEntity player) {
72 | HOTBAR_SLOT_CYCLING_COMPONENT.reveal();
73 | }
74 |
75 | @Override
76 | public void tickState(ClientPlayerEntity player) {
77 | // With bad timing, we can sometimes be one tick off from the hotbar.
78 | // That will make the slot cycler start moving just a bit earlier, which looks bad.
79 | if (HOTBAR_SLOT_CYCLING_COMPONENT.fullyRevealed()) {
80 | HOTBAR_SLOT_CYCLING_COMPONENT.synchronizeFrom(Components.Hotbar);
81 | }
82 | }
83 |
84 | static class WrappedCyclingSlotsRenderer implements CyclingSlotsRenderer {
85 |
86 | CyclingSlotsRenderer parent;
87 |
88 | public WrappedCyclingSlotsRenderer(CyclingSlotsRenderer parent) {
89 | this.parent = parent;
90 | }
91 |
92 | @Override
93 | public void renderSlots(DrawContext context, int screenWidth, int screenHeight, float partialTick, TextRenderer font, PlayerEntity player, ItemStack backwardStack, ItemStack selectedStack, ItemStack forwardStack) {
94 | COMPONENT_WRAPPER.wrap(context, () -> parent.renderSlots(context, screenWidth, screenHeight, partialTick, font, player, backwardStack, selectedStack, forwardStack));
95 | }
96 |
97 | @Override
98 | public boolean testValidStacks(ItemStack backwardStack, ItemStack selectedStack, ItemStack forwardStack) {
99 | boolean original = parent.testValidStacks(backwardStack, selectedStack, forwardStack);
100 | if (!AutoHud.targetHotbar) return original;
101 | if (!original) {
102 | HOTBAR_SLOT_CYCLING_COMPONENT.forceHide();
103 | }
104 | return !HOTBAR_SLOT_CYCLING_COMPONENT.fullyHidden() || (AutoHud.config.animationFade() && AutoHud.config.getHotbarItemsMaximumFade() > 0.0f);
105 | }
106 |
107 | @Override
108 | public void renderSlotBackgrounds(DrawContext context, int posX, int posY, boolean renderForwardStack, boolean renderBackwardStack, boolean renderToRight) {
109 | BACKGROUND_WRAPPER.wrap(context, () -> parent.renderSlotBackgrounds(context, posX, posY, renderForwardStack, renderBackwardStack, renderToRight));
110 | }
111 |
112 | @Override
113 | public void renderSlotItems(DrawContext context, int posX, int posY, float partialTick, TextRenderer font, PlayerEntity player, ItemStack selectedStack, ItemStack forwardStack, ItemStack backwardStack, boolean renderToRight) {
114 | ITEM_WRAPPER.wrap(context, () -> parent.renderSlotItems(context, posX, posY, partialTick, font, player, selectedStack, forwardStack, backwardStack, renderToRight));
115 | }
116 |
117 | @Override
118 | public void renderItemInSlot(DrawContext context, int posX, int posY, float partialTick, TextRenderer font, PlayerEntity player, ItemStack stack) {
119 | parent.renderItemInSlot(context, posX, posY, partialTick, font, player, stack);
120 | }
121 | }
122 | *///?}
123 | }
124 |
--------------------------------------------------------------------------------
/src/main/java/mod/crend/autohud/compat/RaisedCompat.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.compat;
2 |
3 | //? if raised {
4 | import dev.yurisuika.raised.api.RaisedApi;
5 | import dev.yurisuika.raised.util.properties.Element;
6 | //?}
7 | import mod.crend.autohud.render.AutoHudRenderer;
8 | import net.minecraft.client.MinecraftClient;
9 |
10 | public class RaisedCompat {
11 | public static void tick() {
12 | //? if raised
13 | AutoHudRenderer.globalOffsetY = RaisedApi.getY(Element.HOTBAR);
14 | }
15 | public static void tick(MinecraftClient client) {
16 | tick();
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/mod/crend/autohud/component/Components.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.component;
2 |
3 | import mod.crend.autohud.AutoHud;
4 | import mod.crend.autohud.component.state.BooleanComponentState;
5 | import mod.crend.autohud.component.state.ComponentState;
6 | import mod.crend.autohud.component.state.EnhancedPolicyComponentState;
7 | import mod.crend.autohud.component.state.ItemStackComponentState;
8 | import mod.crend.autohud.component.state.PolicyComponentState;
9 | import mod.crend.autohud.component.state.ScoreboardComponentState;
10 | import mod.crend.autohud.component.state.ValueComponentState;
11 | //? if <1.21.2 {
12 | import net.minecraft.item.Equipment;
13 | //?} else {
14 | /*import net.minecraft.component.DataComponentTypes;
15 | import net.minecraft.component.type.EquippableComponent;
16 | import net.minecraft.item.ItemStack;
17 | *///?}
18 |
19 | import java.util.function.Supplier;
20 |
21 | public class Components {
22 | public static final Supplier TARGET_CHAT = () -> AutoHud.targetChat;
23 | public static final Supplier TARGET_CROSSHAIR = () -> AutoHud.targetCrosshair;
24 | public static final Supplier TARGET_EXPERIENCE_BAR = () -> AutoHud.targetExperienceBar;
25 | public static final Supplier TARGET_HOTBAR = () -> AutoHud.targetHotbar;
26 | public static final Supplier TARGET_SCOREBOARD = () -> AutoHud.targetScoreboard;
27 | public static final Supplier TARGET_STATUS_BARS = () -> AutoHud.targetStatusBars;
28 |
29 | public static Component Armor = Component.builder("armor")
30 | .isTargeted(TARGET_STATUS_BARS)
31 | .config(AutoHud.config.armor())
32 | .inMainHud()
33 | .state(player -> new EnhancedPolicyComponentState(Components.Armor,
34 | player::getArmor,
35 | 20,
36 | () ->
37 | //? if <1.21.2 {
38 | player.getMainHandStack().getItem() instanceof Equipment equipment
39 | && equipment.getSlotType().isArmorSlot()
40 | && player.canEquip(player.getMainHandStack())
41 | //?} else {
42 | /*{
43 | ItemStack mainHandStack = player.getMainHandStack();
44 | EquippableComponent equipment = mainHandStack.get(DataComponentTypes.EQUIPPABLE);
45 | return equipment != null
46 | && equipment.slot().isArmorSlot()
47 | && player.canEquip(mainHandStack, equipment.slot());
48 | }
49 | *///?}
50 | , true
51 | ))
52 | .build();
53 |
54 | public static Component Health = Component.builder("health")
55 | .isTargeted(TARGET_STATUS_BARS)
56 | .config(AutoHud.config.health())
57 | .stackComponents(Armor)
58 | .inMainHud()
59 | .state(player -> new EnhancedPolicyComponentState(Components.Health,
60 | () -> Math.round(player.getHealth()),
61 | () -> Math.round(player.getMaxHealth()),
62 | State::canHeal
63 | ))
64 | .build();
65 |
66 | public static Component Air = Component.builder("air")
67 | .isTargeted(TARGET_STATUS_BARS)
68 | .config(AutoHud.config.air())
69 | .inMainHud()
70 | .state(player -> new PolicyComponentState(Components.Air, player::getAir, player::getMaxAir))
71 | .build();
72 |
73 | public static Component Hunger = Component.builder("hunger")
74 | .isTargeted(TARGET_STATUS_BARS)
75 | .config(AutoHud.config.hunger())
76 | .stackComponents(Air)
77 | .inMainHud()
78 | .state(player -> new EnhancedPolicyComponentState(Components.Hunger,
79 | () -> player.getHungerManager().getFoodLevel(),
80 | 20,
81 | () -> AutoHud.config.revealHungerWhenHoldingFoodItem()
82 | && player.getHungerManager().getFoodLevel() < 20
83 | && State.isFood(player.getMainHandStack())
84 | ))
85 | .build();
86 |
87 |
88 | public static Component MountHealth = Component.builder("mount_health")
89 | .isTargeted(TARGET_STATUS_BARS)
90 | .config(AutoHud.config.mountHealth())
91 | .stackComponents(Air)
92 | .inMainHud()
93 | .build();
94 |
95 | public static Component MountJumpBar = Component.builder("mount_jump_bar")
96 | .isTargeted(TARGET_STATUS_BARS)
97 | .config(AutoHud.config.mountJumpBar())
98 | .inMainHud()
99 | .state(player -> new ComponentState(Components.MountJumpBar))
100 | .build();
101 |
102 |
103 | public static Component ExperienceLevel = Component.builder("experience_level")
104 | .isTargeted(TARGET_EXPERIENCE_BAR)
105 | .config(AutoHud.config.experience())
106 | .inMainHud()
107 | .state(player -> new ValueComponentState<>(Components.ExperienceLevel, () -> player.experienceLevel, true))
108 | .build();
109 |
110 | public static Component ExperienceBar = Component.builder("experience_bar")
111 | .isTargeted(TARGET_EXPERIENCE_BAR)
112 | .config(AutoHud.config.experienceBar())
113 | .stackComponents(Health, Hunger, MountHealth, ExperienceLevel)
114 | .inMainHud()
115 | .state(player -> new ValueComponentState<>(Components.ExperienceBar, () -> player.totalExperience, true))
116 | .build();
117 |
118 |
119 | public static Component Hotbar = Component.builder("hotbar")
120 | .isTargeted(TARGET_HOTBAR)
121 | .config(AutoHud.config.hotbar())
122 | .stackComponents(ExperienceBar)
123 | .inMainHud()
124 | .state(player -> new ItemStackComponentState(Components.Hotbar, player::getMainHandStack, true))
125 | .build();
126 |
127 | public static Component Tooltip = Component.builder("tooltip")
128 | .isTargeted(TARGET_HOTBAR)
129 | .config(AutoHud.config.tooltip())
130 | .inMainHud()
131 | .state(player -> new ItemStackComponentState(Components.Tooltip, player::getMainHandStack, true))
132 | .build();
133 |
134 |
135 | public static Component Scoreboard = Component.builder("scoreboard")
136 | .isTargeted(TARGET_SCOREBOARD)
137 | .config(AutoHud.config.scoreboard())
138 | .state(player -> new ScoreboardComponentState(Components.Scoreboard))
139 | .build();
140 |
141 |
142 | public static Component Crosshair = Component.builder("crosshair")
143 | .isTargeted(TARGET_CROSSHAIR)
144 | .config(AutoHud.config.crosshair())
145 | .state(player -> new BooleanComponentState(Components.Crosshair, State::shouldShowCrosshair))
146 | .build();
147 |
148 |
149 | public static Component Chat = Component.builder("chat")
150 | .isTargeted(TARGET_CHAT)
151 | .config(AutoHud.config.chat())
152 | .state(player -> new ComponentState(Components.Chat))
153 | .build();
154 |
155 | public static Component ChatIndicator = Component.builder("chat_indicator")
156 | .isTargeted(TARGET_CHAT)
157 | .config(AutoHud.config.chatIndicator())
158 | .state(player -> new ComponentState(Components.ChatIndicator))
159 | .build();
160 |
161 |
162 | public static Component ActionBar = Component.builder("action_bar")
163 | .config(AutoHud.config.actionBar())
164 | .state(player -> new ComponentState(Components.ActionBar))
165 | .build();
166 |
167 | public static Component BossBar = Component.builder("boss_bar")
168 | .config(AutoHud.config.bossBar())
169 | .state(player -> new ComponentState(Components.BossBar))
170 | .build();
171 | }
172 |
--------------------------------------------------------------------------------
/src/main/java/mod/crend/autohud/component/EventHandler.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.component;
2 |
3 | import mod.crend.autohud.AutoHud;
4 | import mod.crend.autohud.component.state.PolicyComponentState;
5 | import mod.crend.autohud.config.EventPolicy;
6 | import mod.crend.libbamboo.event.*;
7 | import net.minecraft.block.Blocks;
8 | import net.minecraft.registry.tag.BlockTags;
9 | import net.minecraft.util.hit.HitResult;
10 |
11 | public class EventHandler {
12 | public static void registerEvents() {
13 | ScreenEvent.CHAT.register(() -> {
14 | Components.Chat.revealNow();
15 | Components.ChatIndicator.hide();
16 | });
17 | ScreenEvent.OPEN.register(screen -> {
18 | if (AutoHud.config.onScreenOpen() == EventPolicy.Hide) Component.forceHideAll();
19 | });
20 | ScreenEvent.TICK.register(screen -> {
21 | if (AutoHud.config.onScreenOpen() == EventPolicy.Reveal) Component.revealAll();
22 | });
23 | ScreenEvent.CLOSE.register(() -> {
24 | switch (AutoHud.config.onScreenOpen()) {
25 | case Hide -> Component.updateAll();
26 | case Reveal -> Component.hideAll();
27 | }
28 | });
29 | ScreenEvent.PAUSE_TICK.register(() -> {
30 | switch (AutoHud.config.onPauseScreen()) {
31 | case Reveal -> Component.revealAll();
32 | case Hide -> Component.forceHideAll();
33 | }
34 | });
35 | ScreenEvent.UNPAUSE.register(() -> {
36 | switch (AutoHud.config.onPauseScreen()) {
37 | case Hide -> Component.updateAll();
38 | case Reveal -> Component.hideAll();
39 | }
40 | });
41 |
42 | MoveEvent.MOVING.register((player, position) -> {
43 | switch (AutoHud.config.onMoving()) {
44 | case Reveal -> Component.revealAll();
45 | case Hide -> Component.forceHideAll();
46 | default -> {
47 | }
48 | }
49 | });
50 | MoveEvent.STANDING_STILL.register((player, position) -> {
51 | switch (AutoHud.config.onStandingStill()) {
52 | case Reveal -> Component.revealAll();
53 | case Hide -> Component.forceHideAll();
54 | default -> {
55 | if (AutoHud.config.onMoving() == EventPolicy.Hide) Component.updateAll();
56 | }
57 | }
58 | });
59 | SneakEvent.TICK.register(player -> {
60 | switch (AutoHud.config.onSneaking()) {
61 | case Reveal -> Component.revealAll();
62 | case Hide -> Component.forceHideAll();
63 | }
64 | });
65 | SneakEvent.STOP.register(player -> {
66 | switch (AutoHud.config.onSneaking()) {
67 | case Reveal -> Component.hideAll();
68 | case Hide -> Component.updateAll();
69 | }
70 | });
71 | FlyEvent.TICK.register(player -> {
72 | switch (AutoHud.config.onFlying()) {
73 | case Reveal -> Component.revealAll();
74 | case Hide -> Component.forceHideAll();
75 | }
76 | });
77 | FlyEvent.STOP.register(player -> {
78 | switch (AutoHud.config.onFlying()) {
79 | case Reveal -> Component.hideAll();
80 | case Hide -> Component.updateAll();
81 | }
82 | });
83 |
84 | StatusEvent.HEALTH.register((value, old, max) -> Components.Health.updateState());
85 | StatusEvent.FOOD.register((value, old, max) -> Components.Hunger.updateState());
86 | StatusEvent.AIR.register((value, old, max) -> Components.Air.updateState());
87 | StatusEvent.EXPERIENCE.register((progress, total, level) -> {
88 | Components.ExperienceLevel.updateState();
89 | Components.ExperienceBar.updateState();
90 | });
91 | HotbarEvent.MAIN_HAND_CHANGE.register(stack -> {
92 | Components.Health.updateStateNextTick();
93 | Components.Hunger.updateStateNextTick();
94 | Components.Armor.updateStateNextTick();
95 | });
96 | HotbarEvent.SELECTED_SLOT_CHANGE.register(() -> {
97 | if (AutoHud.config.isHotbarOnSlotChange()) {
98 | Components.Hotbar.revealCombined();
99 |
100 | if (AutoHud.config.revealExperienceTextWithHotbar()) {
101 | Components.ExperienceLevel.synchronizeFrom(Components.Hotbar);
102 | }
103 | }
104 | });
105 |
106 | MountEvent.START.register((player, vehicle) -> {
107 | Components.MountHealth.state = new PolicyComponentState(Components.MountHealth, () -> (int) vehicle.getHealth(), () -> (int) vehicle.getMaxHealth());
108 | Components.MountHealth.revealCombined();
109 | });
110 | MountEvent.MOUNT_HEALTH_CHANGE.register((value, old, max) -> Components.MountHealth.updateState());
111 | MountEvent.MOUNT_JUMP.register(vehicle -> {
112 | if (AutoHud.config.mountJumpBar().onChange()) Components.MountJumpBar.revealNow();
113 | });
114 | MountEvent.STOP.register(player -> Components.MountHealth.state = null);
115 |
116 | InteractionEvent.USING_ITEM_TICK.register(player -> {
117 | if (AutoHud.config.onUsingItem()) {
118 | Component.revealAll(1);
119 | }
120 | });
121 | InteractionEvent.MINING_TICK.register(player -> {
122 | if (AutoHud.config.onMining()) {
123 | Component.revealAll(1);
124 | }
125 | });
126 | InteractionEvent.ATTACK.register((player, hitResult) -> {
127 | if (AutoHud.config.onSwinging()
128 | || (AutoHud.config.onAttacking() && hitResult.getType() == HitResult.Type.ENTITY)
129 | ) {
130 | Component.revealAll();
131 | }
132 | });
133 |
134 | TargetEvent.TARGETED_BLOCK_TICK.register(((blockPos, blockState) -> {
135 | if (AutoHud.config.revealExperienceTextOnTargetingEnchantingBlock()) {
136 | if (blockState.getBlock() == Blocks.ENCHANTING_TABLE || blockState.isIn(BlockTags.ANVIL)) {
137 | Components.ExperienceLevel.reveal();
138 | }
139 | }
140 | }));
141 |
142 | }
143 | }
144 |
--------------------------------------------------------------------------------
/src/main/java/mod/crend/autohud/component/Hud.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.component;
2 |
3 | import mod.crend.autohud.render.ComponentRenderer;
4 | import net.minecraft.client.network.ClientPlayerEntity;
5 | import net.minecraft.entity.effect.StatusEffectInstance;
6 |
7 | public class Hud {
8 | private static boolean dynamic = false;
9 | private static boolean wasPeeking = false;
10 |
11 | private static State state = null;
12 |
13 | public static boolean actDynamic() {
14 | return dynamic || wasPeeking;
15 | }
16 |
17 | public static void disableDynamic() {
18 | dynamic = false;
19 | Component.revealAll();
20 | Components.ChatIndicator.hide();
21 | }
22 |
23 | public static void enableDynamic() {
24 | dynamic = true;
25 | Component.hideAll();
26 | }
27 |
28 | public static void toggleHud() {
29 | if (dynamic) disableDynamic();
30 | else enableDynamic();
31 | }
32 | public static void peekHud(boolean doPeek) {
33 | if (dynamic == doPeek) {
34 | Component.revealAll();
35 | Components.ChatIndicator.hide();
36 | } else if (doPeek != wasPeeking) {
37 | Component.hideAll();
38 | }
39 |
40 | wasPeeking = doPeek;
41 | }
42 |
43 | public static void registerState(ClientPlayerEntity player) {
44 | state = new State(player);
45 | wasPeeking = false;
46 | }
47 | public static void tickState(ClientPlayerEntity player) {
48 | state.tick(player);
49 | }
50 | public static void unregisterState() {
51 | state = null;
52 | }
53 |
54 | public static boolean shouldShowIcon(StatusEffectInstance instance) {
55 | ComponentRenderer renderer = ComponentRenderer.getForStatusEffect(instance);
56 | return (!renderer.isActive() || renderer.doRender());
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/src/main/java/mod/crend/autohud/component/ScoreboardHelper.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.component;
2 |
3 | import mod.crend.autohud.AutoHud;
4 | import mod.crend.autohud.component.state.ScoreboardComponentState;
5 | //? if >=1.20.3
6 | /*import net.minecraft.scoreboard.ScoreHolder;*/
7 | import net.minecraft.scoreboard.ScoreboardObjective;
8 | //? if <1.20.3 {
9 | import net.minecraft.scoreboard.ScoreboardPlayerScore;
10 | //?} else {
11 | /*import net.minecraft.scoreboard.ScoreboardScore;
12 | *///?}
13 | import net.minecraft.scoreboard.Team;
14 |
15 | public class ScoreboardHelper {
16 | public static void onObjectiveUpdate(ScoreboardObjective objective) {
17 | if (canUpdate() && AutoHud.config.shouldRevealScoreboardOnTitleChange()) {
18 | getScoreboardComponent().updateObjectiveDisplayName(objective);
19 | }
20 | }
21 |
22 | //? if <1.20.3 {
23 | public static void onPlayerScoreUpdate(ScoreboardPlayerScore score) {
24 | //?} else {
25 | /*public static void onPlayerScoreUpdate(ScoreHolder scoreHolder, ScoreboardObjective objective, ScoreboardScore score) {
26 | *///?}
27 | if (canUpdate() && AutoHud.config.shouldRevealScoreboardOnScoreChange()) {
28 | //? if <1.20.3 {
29 | getScoreboardComponent().onPlayerScoreUpdate(score);
30 | //?} else {
31 | /*getScoreboardComponent().onPlayerScoreUpdate(scoreHolder, objective, score);
32 | *///?}
33 | }
34 | }
35 |
36 | public static void onPlayerScoreRemove(String playerName) {
37 | if (canUpdate() && AutoHud.config.shouldRevealScoreboardOnScoreChange()) {
38 | getScoreboardComponent().onPlayerScoreRemove(playerName);
39 | }
40 | }
41 |
42 | public static void onPlayerScoreRemove(String playerName, ScoreboardObjective objective) {
43 | if (canUpdate() && AutoHud.config.shouldRevealScoreboardOnScoreChange()) {
44 | getScoreboardComponent().onPlayerScoreRemove(playerName, objective);
45 | }
46 | }
47 |
48 | public static void onTeamRemoved(Team team) {
49 | if (canUpdate() && AutoHud.config.shouldRevealScoreboardOnTeamChange()) {
50 | getScoreboardComponent().onTeamRemoved(team);
51 | }
52 | }
53 |
54 | public static void onTeamUpdated(Team team) {
55 | if (canUpdate() && AutoHud.config.shouldRevealScoreboardOnTeamChange()) {
56 | getScoreboardComponent().onTeamUpdated(team);
57 | }
58 | }
59 |
60 | public static void onPlayerAddedToTeam(String playerName, Team team) {
61 | if (canUpdate() && AutoHud.config.shouldRevealScoreboardOnTeamChange()) {
62 | getScoreboardComponent().onPlayerAddedToTeam(playerName, team);
63 | }
64 | }
65 |
66 | public static void onPlayerRemovedFromTeam(String playerName, Team team) {
67 | if (canUpdate() && AutoHud.config.shouldRevealScoreboardOnTeamChange()) {
68 | getScoreboardComponent().onPlayerRemovedFromTeam(playerName, team);
69 | }
70 | }
71 |
72 | // The next two methods are used to cut down on unnecessary duplicate code
73 | private static boolean canUpdate() {
74 | return Components.Scoreboard.config.active() && Components.Scoreboard.state != null;
75 | }
76 |
77 | private static ScoreboardComponentState getScoreboardComponent() {
78 | return (ScoreboardComponentState) Components.Scoreboard.state;
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/main/java/mod/crend/autohud/component/state/BooleanComponentState.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.component.state;
2 |
3 | import mod.crend.autohud.component.Component;
4 |
5 | import java.util.function.Supplier;
6 |
7 | public class BooleanComponentState extends ComponentState {
8 | Supplier display;
9 |
10 | public BooleanComponentState(Component component, Supplier display, boolean updateEveryTick) {
11 | super(component, updateEveryTick);
12 | this.display = display;
13 | }
14 | public BooleanComponentState(Component component, Supplier display) {
15 | this(component, display, true);
16 | }
17 |
18 | @Override
19 | public void update() {
20 | if (!component.config.active() || (component.config.onChange() && display.get())) {
21 | component.revealCombined();
22 | } else {
23 | component.hide();
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/mod/crend/autohud/component/state/ComponentState.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.component.state;
2 |
3 |
4 | import mod.crend.autohud.component.Component;
5 | import mod.crend.autohud.component.Hud;
6 |
7 | public class ComponentState {
8 | protected Component component;
9 |
10 | protected boolean updateEveryTick = false;
11 | protected boolean updateNextTick = true;
12 |
13 | public ComponentState(Component component, boolean updateEveryTick) {
14 | this.component = component;
15 | this.updateEveryTick = updateEveryTick;
16 | }
17 | public ComponentState(Component component) {
18 | this(component, false);
19 | }
20 |
21 | public void tick() {
22 | if (updateNextTick || (updateEveryTick && Hud.actDynamic())) {
23 | update();
24 | updateNextTick = false;
25 | }
26 | }
27 |
28 | public void update() {
29 | if (!component.config.active()) {
30 | component.revealCombined();
31 | }
32 | }
33 |
34 | public void updateNextTick() {
35 | updateNextTick = true;
36 | }
37 |
38 | public boolean scheduledUpdate() {
39 | return updateNextTick;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/mod/crend/autohud/component/state/EnhancedPolicyComponentState.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.component.state;
2 |
3 | import mod.crend.autohud.component.Component;
4 |
5 | import java.util.function.Supplier;
6 |
7 | public class EnhancedPolicyComponentState extends PolicyComponentState {
8 | protected Supplier test;
9 |
10 | public EnhancedPolicyComponentState(Component component, Supplier newValueSupplier, Supplier maxValueSupplier, Supplier test, boolean updateEveryTick) {
11 | super(component, newValueSupplier, maxValueSupplier, updateEveryTick);
12 | this.test = test;
13 | }
14 |
15 | public EnhancedPolicyComponentState(Component component, Supplier newValueSupplier, Supplier maxValueSupplier, Supplier test) {
16 | super(component, newValueSupplier, maxValueSupplier);
17 | this.test = test;
18 | }
19 |
20 | public EnhancedPolicyComponentState(Component component, Supplier newValueSupplier, Integer maxValueSupplier, Supplier test, boolean updateEveryTick) {
21 | super(component, newValueSupplier, maxValueSupplier, updateEveryTick);
22 | this.test = test;
23 | }
24 |
25 | public EnhancedPolicyComponentState(Component component, Supplier newValueSupplier, Integer maxValueSupplier, Supplier test) {
26 | super(component, newValueSupplier, maxValueSupplier);
27 | this.test = test;
28 | }
29 |
30 | @Override
31 | protected boolean doReveal(Integer newValue) {
32 | return test.get() || super.doReveal(newValue);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/mod/crend/autohud/component/state/ItemStackComponentState.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.component.state;
2 |
3 | import mod.crend.autohud.component.Component;
4 | import net.minecraft.item.ItemStack;
5 |
6 | import java.util.function.Supplier;
7 |
8 | public class ItemStackComponentState extends ValueComponentState {
9 | public ItemStackComponentState(Component component, Supplier newValueSupplier, boolean updateEveryTick) {
10 | super(component, () -> newValueSupplier.get().copy(), updateEveryTick);
11 | }
12 | public ItemStackComponentState(Component component, Supplier newValueSupplier) {
13 | super(component, newValueSupplier, false);
14 | }
15 |
16 | @Override
17 | protected boolean doReveal(ItemStack newValue) {
18 | return !component.config.active() || (component.config.onChange() && !ItemStack.areEqual(oldValue, newValue));
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/mod/crend/autohud/component/state/PolicyComponentState.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.component.state;
2 |
3 | import mod.crend.autohud.component.Component;
4 | import mod.crend.autohud.component.Hud;
5 | import mod.crend.autohud.config.ConfigHandler;
6 |
7 | import java.util.function.Supplier;
8 |
9 | public class PolicyComponentState extends ValueComponentState {
10 | protected Supplier maxValueSupplier;
11 |
12 | public PolicyComponentState(Component component, Supplier newValueSupplier, Supplier maxValueSupplier, boolean updateEveryTick) {
13 | super(component, newValueSupplier, updateEveryTick);
14 | this.maxValueSupplier = maxValueSupplier;
15 | }
16 | public PolicyComponentState(Component component, Supplier newValueSupplier, Supplier maxValueSupplier) {
17 | this(component, newValueSupplier, maxValueSupplier, false);
18 | }
19 | public PolicyComponentState(Component component, Supplier newValueSupplier, Integer maxValueSupplier, boolean updateEveryTick) {
20 | this(component, newValueSupplier, () -> maxValueSupplier, updateEveryTick);
21 | }
22 | public PolicyComponentState(Component component, Supplier newValueSupplier, Integer maxValueSupplier) {
23 | this(component, newValueSupplier, maxValueSupplier, false);
24 | }
25 |
26 | @Override
27 | protected boolean doReveal(Integer newValue) {
28 | return switch (((ConfigHandler.PolicyComponent) component.config).policy()) {
29 | case NotFull -> (newValue < maxValueSupplier.get());
30 | case Low -> (newValue <= maxValueSupplier.get() / 3);
31 | case Increasing -> (newValue > oldValue);
32 | case Decreasing -> (newValue < oldValue);
33 | case Changing -> (!newValue.equals(oldValue));
34 | case Disabled -> !Hud.actDynamic();
35 | case Always -> true;
36 | };
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/mod/crend/autohud/component/state/ValueComponentState.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.component.state;
2 |
3 | import mod.crend.autohud.component.Component;
4 |
5 | import java.util.Objects;
6 | import java.util.function.Supplier;
7 |
8 | public class ValueComponentState extends ComponentState {
9 | protected T oldValue;
10 | protected Supplier newValueSupplier;
11 |
12 | public ValueComponentState(Component component, Supplier newValueSupplier, boolean updateEveryTick) {
13 | super(component, updateEveryTick);
14 | this.newValueSupplier = newValueSupplier;
15 | this.oldValue = newValueSupplier.get();
16 | }
17 | public ValueComponentState(Component component, Supplier newValueSupplier) {
18 | this(component, newValueSupplier, false);
19 | }
20 |
21 | @Override
22 | public void update() {
23 | T newValue = newValueSupplier.get();
24 | if (doReveal(newValue)) {
25 | this.onUpdateReveal(newValue);
26 | component.revealCombined();
27 | }
28 | oldValue = newValue;
29 | }
30 |
31 | protected boolean doReveal(T newValue) {
32 | return !component.config.active() || (component.config.onChange() && !Objects.equals(newValue, oldValue));
33 | }
34 |
35 | protected void onUpdateReveal(T newValue) {}
36 | }
37 |
38 |
--------------------------------------------------------------------------------
/src/main/java/mod/crend/autohud/config/EventPolicy.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.config;
2 |
3 | import mod.crend.libbamboo.type.NameableEnum;
4 | import net.minecraft.text.Text;
5 |
6 | public enum EventPolicy implements NameableEnum {
7 | Reveal,
8 | Hide,
9 | Nothing;
10 |
11 | @Override
12 | public Text getDisplayName() {
13 | return switch (this) {
14 | case Reveal -> Text.translatable("autohud.eventPolicy.Reveal");
15 | case Hide -> Text.translatable("autohud.eventPolicy.Hide");
16 | case Nothing -> Text.translatable("autohud.eventPolicy.Nothing");
17 | };
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/mod/crend/autohud/config/RevealPolicy.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.config;
2 |
3 | import mod.crend.libbamboo.type.NameableEnum;
4 | import net.minecraft.text.Text;
5 |
6 | public enum RevealPolicy implements NameableEnum {
7 | Always,
8 | Disabled,
9 | Changing,
10 | Increasing,
11 | Decreasing,
12 | NotFull,
13 | Low;
14 |
15 | @Override
16 | public Text getDisplayName() {
17 | return switch (this) {
18 | case Always -> Text.translatable("autohud.revealPolicy.Always");
19 | case Disabled -> Text.translatable("autohud.revealPolicy.Disabled");
20 | case Changing -> Text.translatable("autohud.revealPolicy.Changing");
21 | case Increasing -> Text.translatable("autohud.revealPolicy.Increasing");
22 | case Decreasing -> Text.translatable("autohud.revealPolicy.Decreasing");
23 | case NotFull -> Text.translatable("autohud.revealPolicy.NotFull");
24 | case Low -> Text.translatable("autohud.revealPolicy.Low");
25 | };
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/mod/crend/autohud/config/RevealType.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.config;
2 |
3 | import mod.crend.libbamboo.type.NameableEnum;
4 | import net.minecraft.text.Text;
5 |
6 | public enum RevealType implements NameableEnum {
7 | Individual,
8 | Stacked,
9 | Grouped,
10 | HideCombined,
11 | Combined;
12 |
13 | @Override
14 | public Text getDisplayName() {
15 | return switch (this) {
16 | case Individual -> Text.translatable("autohud.revealType.Individual");
17 | case Stacked -> Text.translatable("autohud.revealType.Stacked");
18 | case Grouped -> Text.translatable("autohud.revealType.Grouped");
19 | case HideCombined -> Text.translatable("autohud.revealType.HideCombined");
20 | case Combined -> Text.translatable("autohud.revealType.Combined");
21 | };
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/mod/crend/autohud/config/ScrollDirection.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.config;
2 |
3 | import mod.crend.libbamboo.type.NameableEnum;
4 | import net.minecraft.text.Text;
5 |
6 | public enum ScrollDirection implements NameableEnum {
7 | Up,
8 | Down,
9 | Left,
10 | Right;
11 |
12 | @Override
13 | public Text getDisplayName() {
14 | return switch (this) {
15 | case Up -> Text.translatable("autohud.scrollDirection.Up");
16 | case Down -> Text.translatable("autohud.scrollDirection.Down");
17 | case Left -> Text.translatable("autohud.scrollDirection.Left");
18 | case Right -> Text.translatable("autohud.scrollDirection.Right");
19 | };
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/mod/crend/autohud/mixin/ClientPlayNetworkHandlerMixin.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.mixin;
2 |
3 | import mod.crend.autohud.component.ScoreboardHelper;
4 | import net.minecraft.client.MinecraftClient;
5 | import net.minecraft.client.network.ClientPlayNetworkHandler;
6 | import net.minecraft.network.packet.s2c.play.TeamS2CPacket;
7 | import org.spongepowered.asm.mixin.Mixin;
8 | import org.spongepowered.asm.mixin.injection.At;
9 | import org.spongepowered.asm.mixin.injection.Inject;
10 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
11 |
12 | @Mixin(ClientPlayNetworkHandler.class)
13 | public class ClientPlayNetworkHandlerMixin {
14 | @Inject(method="onTeam", at=@At(value="INVOKE", target = "java/util/Optional.ifPresent(Ljava/util/function/Consumer;)V", shift=At.Shift.AFTER))
15 | private void autoHud$onTeamUpdate(TeamS2CPacket packet, CallbackInfo ci) {
16 | if (MinecraftClient.getInstance().world == null) {
17 | return;
18 | }
19 |
20 | // JuggleStruggle: The reason why both getTeamOperation cannot be REMOVE is because we already perform team removal checks.
21 | // As for team being present, it... just means that it is required to know that it has been updated.
22 | if (packet.getTeamOperation() == TeamS2CPacket.Operation.REMOVE) {
23 | // JuggleStruggle: We need to be sure that we are only calling the rest of the method if, and only if, there's
24 | // no player listing going on as that takes precedence over team addition/removal to avoid multiple calls when
25 | // not needed. Seems to me that "add" from team operation will never get called since it uses player list operation as well.
26 | if (packet.getPlayerListOperation() == null) {
27 | ScoreboardHelper.onTeamRemoved(MinecraftClient.getInstance().world.getScoreboard().getTeam(packet.getTeamName()));
28 | }
29 | } else {
30 | if (packet.getTeam().isPresent()) {
31 | ScoreboardHelper.onTeamUpdated(MinecraftClient.getInstance().world.getScoreboard().getTeam(packet.getTeamName()));
32 | }
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/mod/crend/autohud/mixin/ScoreboardMixin.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.mixin;
2 |
3 | import mod.crend.autohud.component.ScoreboardHelper;
4 | import net.minecraft.scoreboard.*;
5 | import org.spongepowered.asm.mixin.Mixin;
6 | import org.spongepowered.asm.mixin.injection.At;
7 | import org.spongepowered.asm.mixin.injection.Inject;
8 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
9 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
10 |
11 | @Mixin(Scoreboard.class)
12 | public class ScoreboardMixin {
13 | @Inject(method="updateExistingObjective", at=@At("HEAD"))
14 | public void autoHud$onObjectiveUpdate(ScoreboardObjective objective, CallbackInfo ci) {
15 | ScoreboardHelper.onObjectiveUpdate(objective);
16 | }
17 |
18 | //? if <1.20.3 {
19 | @Inject(method="updateScore", at=@At("HEAD"))
20 | public void autoHud$onPlayerScoreUpdate(ScoreboardPlayerScore score, CallbackInfo ci) {
21 | ScoreboardHelper.onPlayerScoreUpdate(score);
22 | }
23 |
24 | @Inject(method="updatePlayerScore(Ljava/lang/String;)V", at=@At("HEAD"))
25 | public void autoHud$onPlayerScoreReset(String playerName, CallbackInfo ci) {
26 | ScoreboardHelper.onPlayerScoreRemove(playerName);
27 | }
28 |
29 | @Inject(method="updatePlayerScore(Ljava/lang/String;Lnet/minecraft/scoreboard/ScoreboardObjective;)V", at=@At("HEAD"))
30 | public void autoHud$onPlayerScoreReset(String playerName, ScoreboardObjective objective, CallbackInfo ci) {
31 | ScoreboardHelper.onPlayerScoreRemove(playerName, objective);
32 | }
33 |
34 | @Inject(method="addPlayerToTeam", at=@At("RETURN"))
35 | public void autoHud$onPlayerAddedToTeam(String playerName, Team teamAddedTo, CallbackInfoReturnable ci) {
36 | ScoreboardHelper.onPlayerAddedToTeam(playerName, teamAddedTo);
37 | }
38 | @Inject(method="removePlayerFromTeam", at=@At("TAIL"))
39 | public void autoHud$onPlayerRemovedFromTeam(String playerName, Team teamRemovedFrom, CallbackInfo ci) {
40 | ScoreboardHelper.onPlayerRemovedFromTeam(playerName, teamRemovedFrom);
41 | }
42 |
43 | //?} else {
44 |
45 | /*@Inject(method="updateScore", at=@At("HEAD"))
46 | public void autoHud$onPlayerScoreUpdate(ScoreHolder scoreHolder, ScoreboardObjective objective, ScoreboardScore score, CallbackInfo ci) {
47 | ScoreboardHelper.onPlayerScoreUpdate(scoreHolder, objective, score);
48 | }
49 |
50 | @Inject(method="onScoreRemoved", at=@At("HEAD"))
51 | public void autoHud$onPlayerScoreRemoved(ScoreHolder scoreHolder, ScoreboardObjective objective, CallbackInfo ci) {
52 | ScoreboardHelper.onPlayerScoreRemove(scoreHolder.getNameForScoreboard(), objective);
53 | }
54 |
55 | @Inject(method="onScoreHolderRemoved", at=@At("HEAD"))
56 | public void autoHud$onPlayerRemoved(ScoreHolder scoreHolder, CallbackInfo ci) {
57 | ScoreboardHelper.onPlayerScoreRemove(scoreHolder.getNameForScoreboard());
58 | }
59 |
60 | @Inject(method="resetScore", at=@At("HEAD"))
61 | public void autoHud$onPlayerScoreReset(ScoreHolder scoreHolder, ScoreboardObjective objective, CallbackInfo ci) {
62 | ScoreboardHelper.onPlayerScoreRemove(scoreHolder.getNameForScoreboard(), objective);
63 | }
64 |
65 | @Inject(method="addScoreHolderToTeam", at=@At("RETURN"))
66 | public void autoHud$onPlayerAddedToTeam(String playerName, Team teamAddedTo, CallbackInfoReturnable ci) {
67 | ScoreboardHelper.onPlayerAddedToTeam(playerName, teamAddedTo);
68 | }
69 | @Inject(method="removeScoreHolderFromTeam", at=@At("TAIL"))
70 | public void autoHud$onPlayerRemovedFromTeam(String playerName, Team teamRemovedFrom, CallbackInfo ci) {
71 | ScoreboardHelper.onPlayerRemovedFromTeam(playerName, teamRemovedFrom);
72 | }
73 | *///?}
74 | }
75 |
--------------------------------------------------------------------------------
/src/main/java/mod/crend/autohud/mixin/TeamMixinAccessor.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.mixin;
2 |
3 | import mod.crend.autohud.component.state.ScoreboardComponentState;
4 | import net.minecraft.scoreboard.Team;
5 | import net.minecraft.text.Text;
6 | import net.minecraft.util.Formatting;
7 | import org.spongepowered.asm.mixin.Mixin;
8 | import org.spongepowered.asm.mixin.gen.Accessor;
9 |
10 | /**
11 | * The only reason why this mixin was created was to avoid calling the scoreboard
12 | * instance since that is always null when attempting to create a cache team, which
13 | * is primarily used in {@link ScoreboardComponentState}.
14 | */
15 | @Mixin(Team.class)
16 | public interface TeamMixinAccessor {
17 | @Accessor("displayName")
18 | void autohud$setDisplayName(Text displayName);
19 | @Accessor("color")
20 | void autohud$setColor(Formatting color);
21 |
22 | /**
23 | * Please do not use this method directly unless you're absolutely sure that the
24 | * text being passed in the {@code prefix} parameter isn't {@code null}.
25 | *
26 | * @param prefix sets the prefix for the team
27 | */
28 | @Accessor("prefix")
29 | void autohud$setPrefix(Text prefix);
30 |
31 | /**
32 | * Please do not use this method directly unless you're absolutely sure that the
33 | * text being passed in the {@code suffix} parameter isn't {@code null}.
34 | *
35 | * @param suffix sets the suffix for the team
36 | */
37 | @Accessor("suffix")
38 | void autohud$setSuffix(Text suffix);
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/mod/crend/autohud/render/AutoHudRenderLayer.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.render;
2 |
3 | import com.mojang.blaze3d.systems.RenderSystem;
4 | import mod.crend.autohud.AutoHud;
5 | import mod.crend.autohud.component.Component;
6 | import net.minecraft.client.gui.DrawContext;
7 |
8 | public interface AutoHudRenderLayer {
9 | AutoHudRenderLayer DO_MOVE = new DoMove();
10 | AutoHudRenderLayer DO_FADE = new DoFade();
11 | AutoHudRenderLayer DO_REVERSE_TRANSLATION = new DoReverseTranslation();
12 | AutoHudRenderLayer DO_GLOBAL_TRANSLATION = new DoGlobalTranslation();
13 |
14 | AutoHudRenderLayer MOVE_MODE = new MoveMode();
15 | AutoHudRenderLayer FADE_MODE = new FadeMode();
16 | AutoHudRenderLayer FADE_MODE_WITH_REVERSE_TRANSLATION = new FadeModeWithReverseTranslation();
17 |
18 | default boolean shouldApply() { return true; }
19 |
20 | void doPreRender(Component component, DrawContext context, float minAlpha);
21 | default void preRender(Component component, DrawContext context, float minAlpha) {
22 | if (shouldApply()) doPreRender(component, context, minAlpha);
23 | }
24 | default void preRender(Component component, DrawContext context) {
25 | preRender(component, context, (float) component.config.maximumFade());
26 | }
27 |
28 | void doPostRender(Component component, DrawContext context);
29 | default void postRender(Component component, DrawContext context) {
30 | if (shouldApply()) doPostRender(component, context);
31 | }
32 |
33 | default void wrap(Component component, DrawContext context, Runnable original) {
34 | wrap(component, context, (float) component.config.maximumFade(), original);
35 | }
36 | default void wrap(Component component, DrawContext context, float minAlpha, Runnable original) {
37 | preRender(component, context, minAlpha);
38 | original.run();
39 | postRender(component, context);
40 | }
41 |
42 | class DoMove implements AutoHudRenderLayer {
43 | @Override
44 | public boolean shouldApply() {
45 | return (AutoHud.config.animationMove() || !AutoHud.config.animationFade());
46 | }
47 |
48 | @Override
49 | public void doPreRender(Component component, DrawContext context, float ignored) {
50 | AutoHudRenderer.active.add(component);
51 | context.getMatrices().push();
52 | if (component.isHidden()) {
53 | context.getMatrices().translate(component.getOffsetX(AutoHudRenderer.tickDelta), component.getOffsetY(AutoHudRenderer.tickDelta), 0);
54 | }
55 | }
56 |
57 | @Override
58 | public void doPostRender(Component component, DrawContext context) {
59 | AutoHudRenderer.active.remove(component);
60 | context.getMatrices().pop();
61 | }
62 | }
63 |
64 | class DoFade implements AutoHudRenderLayer {
65 | @Override
66 | public boolean shouldApply() {
67 | return AutoHud.config.animationFade();
68 | }
69 |
70 | @Override
71 | public void doPreRender(Component component, DrawContext context, float minAlpha) {
72 | AutoHudRenderer.alpha = Math.max(component.getAlpha(AutoHudRenderer.tickDelta), minAlpha);
73 | RenderSystem.enableBlend();
74 | float[] color = RenderSystem.getShaderColor();
75 | RenderSystem.setShaderColor(color[0], color[1], color[2], color[3] * AutoHudRenderer.alpha);
76 | }
77 |
78 | @Override
79 | public void doPostRender(Component component, DrawContext context) {
80 | //? if >=1.21.2
81 | /*context.draw();*/
82 | AutoHudRenderer.alpha = 1.0f;
83 | RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, AutoHudRenderer.alpha);
84 | }
85 | }
86 |
87 | class DoReverseTranslation implements AutoHudRenderLayer {
88 | @Override
89 | public boolean shouldApply() {
90 | return AutoHud.config.animationMove();
91 | }
92 |
93 | @Override
94 | public void doPreRender(Component component, DrawContext context, float minAlpha) {
95 | context.getMatrices().push();
96 | if (component.isHidden()) {
97 | context.getMatrices().translate(-component.getOffsetX(AutoHudRenderer.tickDelta), -component.getOffsetY(AutoHudRenderer.tickDelta), 0);
98 | }
99 | }
100 |
101 | @Override
102 | public void doPostRender(Component component, DrawContext context) {
103 | context.getMatrices().pop();
104 | }
105 | }
106 |
107 | class DoGlobalTranslation implements AutoHudRenderLayer {
108 | @Override
109 | public boolean shouldApply() {
110 | return (AutoHudRenderer.globalOffsetX != 0 || AutoHudRenderer.globalOffsetY != 0);
111 | }
112 |
113 | @Override
114 | public void doPreRender(Component component, DrawContext context, float minAlpha) {
115 | context.getMatrices().push();
116 | context.getMatrices().translate(AutoHudRenderer.globalOffsetX, AutoHudRenderer.globalOffsetY, 0);
117 | }
118 |
119 | @Override
120 | public void doPostRender(Component component, DrawContext context) {
121 | context.getMatrices().pop();
122 | }
123 | }
124 |
125 |
126 | class MoveMode implements AutoHudRenderLayer {
127 | @Override
128 | public void doPreRender(Component component, DrawContext context, float minAlpha) {
129 | DO_FADE.preRender(component, context, minAlpha);
130 | DO_MOVE.preRender(component, context, minAlpha);
131 | }
132 |
133 | @Override
134 | public void doPostRender(Component component, DrawContext context) {
135 | DO_MOVE.postRender(component, context);
136 | DO_FADE.postRender(component, context);
137 | }
138 | }
139 |
140 | class FadeMode implements AutoHudRenderLayer {
141 | @Override
142 | public void doPreRender(Component component, DrawContext context, float minAlpha) {
143 | DO_FADE.preRender(component, context, minAlpha);
144 | }
145 |
146 | @Override
147 | public void doPostRender(Component component, DrawContext context) {
148 | DO_FADE.postRender(component, context);
149 | }
150 | }
151 |
152 | class FadeModeWithReverseTranslation implements AutoHudRenderLayer {
153 | @Override
154 | public void doPreRender(Component component, DrawContext context, float minAlpha) {
155 | DO_FADE.preRender(component, context, minAlpha);
156 | DO_REVERSE_TRANSLATION.preRender(component, context, minAlpha);
157 | DO_GLOBAL_TRANSLATION.preRender(component, context, minAlpha);
158 | }
159 |
160 | @Override
161 | public void doPostRender(Component component, DrawContext context) {
162 | DO_GLOBAL_TRANSLATION.postRender(component, context);
163 | DO_REVERSE_TRANSLATION.postRender(component, context);
164 | DO_FADE.postRender(component, context);
165 | }
166 | }
167 | }
168 |
--------------------------------------------------------------------------------
/src/main/java/mod/crend/autohud/render/AutoHudRenderer.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.render;
2 |
3 | import com.mojang.blaze3d.systems.RenderSystem;
4 | import mod.crend.autohud.AutoHud;
5 | import mod.crend.autohud.component.Component;
6 | import mod.crend.autohud.component.Components;
7 | import net.minecraft.client.gui.DrawContext;
8 | //? if >1.20.1
9 | /*import net.minecraft.client.render.RenderTickCounter;*/
10 |
11 | import java.util.ArrayList;
12 | import java.util.List;
13 |
14 | public class AutoHudRenderer {
15 | public static boolean inRender;
16 | public static float tickDelta = 0.0f;
17 | public static float alpha = 1.0f;
18 | public static float globalOffsetX = 0;
19 | public static float globalOffsetY = 0;
20 |
21 |
22 | public static boolean shouldRenderHotbarItems() {
23 | // Render items when we're not doing anything with the hotbar
24 | return !AutoHud.targetHotbar
25 | // Render items when they're not fully hidden (in other words, visible in some way)
26 | || !Components.Hotbar.fullyHidden()
27 | // If we are in fade mode, only render items if they're not fully transparent.
28 | || (AutoHud.config.animationFade() && AutoHud.config.getHotbarItemsMaximumFade() > 0.0f)
29 | // If we are neither in fade nor move mode, skip rendering if it's hidden.
30 | // If we are in move mode, the items may still be visible in the "hidden" state!
31 | || (!AutoHud.config.animationFade() && AutoHud.config.animationMove());
32 | }
33 |
34 | /**
35 | * Modifies the given color to set its alpha value
36 | */
37 | public static int modifyArgb(int argb) {
38 | int oldAlpha = argb >> 24;
39 | if ((oldAlpha & 0xFC) == 0) {
40 | oldAlpha = 0xFF;
41 | }
42 | return Math.round(alpha * oldAlpha) << 24 | (argb & 0xFFFFFF);
43 | }
44 | public static int getArgb() {
45 | return Math.round(alpha * 0xFF) << 24;
46 | }
47 |
48 | public static void injectTransparency() {
49 | if (inRender) {
50 | RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, alpha);
51 | }
52 | }
53 |
54 | public static List active = new ArrayList<>();
55 |
56 | public static void startRender(DrawContext context, /*? if <1.21 {*/float/*?} else {*//*RenderTickCounter*//*?}*/ renderTickCounter) {
57 | inRender = true;
58 | tickDelta = renderTickCounter/*? if >=1.21 {*//*.getTickDelta(true)*//*?}*/;
59 | active.clear();
60 | }
61 |
62 | public static void renderChatMessageIndicator(DrawContext context, /*? if <1.21 {*/float/*?} else {*//*RenderTickCounter*//*?}*/ ignored) {
63 | ComponentRenderer.CHAT_MESSAGE_INDICATOR.wrap(context, ChatMessageIndicator::render);
64 | }
65 |
66 | public static void endRender() {
67 | for (Component component : active) {
68 | System.err.println("Not cleaned up: " + component.identifier);
69 | }
70 | inRender = false;
71 | RenderSystem.setShaderColor(1f, 1f, 1f, 1f);
72 | RenderSystem.defaultBlendFunc();
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/main/java/mod/crend/autohud/render/ChatMessageIndicator.java:
--------------------------------------------------------------------------------
1 | package mod.crend.autohud.render;
2 |
3 | import net.minecraft.client.MinecraftClient;
4 | import net.minecraft.client.gui.DrawContext;
5 | import net.minecraft.client.toast.TutorialToast;
6 |
7 | public class ChatMessageIndicator {
8 | public static void render(DrawContext context) {
9 | int x = 10;
10 | int y = MinecraftClient.getInstance().getWindow().getScaledHeight() - 30;
11 | TutorialToast.Type.SOCIAL_INTERACTIONS.drawIcon(context, x, y);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/resources/architectury.common.json:
--------------------------------------------------------------------------------
1 | {
2 | "accessWidener": "autohud.accesswidener"
3 | }
--------------------------------------------------------------------------------
/src/main/resources/assets/autohud/lang/zh_cn.json:
--------------------------------------------------------------------------------
1 | {
2 | "autohud.title": "Auto HUD",
3 | "autohud.category.general": "自动 HUD",
4 | "autohud.category.components": "组件",
5 | "autohud.category.advanced": "Advanced",
6 |
7 | "autohud.option.dynamicOnLoad": "在游戏加载时启用动态 HUD",
8 | "autohud.option.ticksRevealed": "显示时间 (ticks)",
9 | "autohud.option.animationMove": "动画类型:移动",
10 | "autohud.option.animationFade": "动画类型:渐变",
11 | "autohud.option.animationSpeed": "动画速度",
12 | "autohud.group.animationSpeeds": "Special animation speeds (set to 0 to use above value)",
13 | "autohud.option.animationSpeeds.moveIn": "Moving in",
14 | "autohud.option.animationSpeeds.moveOut": "Moving out",
15 | "autohud.option.animationSpeeds.fadeIn": "Fading in",
16 | "autohud.option.animationSpeeds.fadeOut": "Fading out",
17 | "autohud.option.revealType": "以如下方式处理组件",
18 | "autohud.option.revealType.description": "独立:独立移动所有部件\n叠加:只有在不被其他可见组件阻挡的情况下才会隐藏组件\n分组:将所有逻辑上分组的组件(快捷栏区)移到一起\n隐藏合并:将显示的组件一起隐藏\n合并:将所有组件一起移动",
19 |
20 | "autohud.group.statusBars": "Status Bars",
21 | "autohud.group.health": "Health",
22 | "autohud.group.armor": "Armor",
23 | "autohud.group.hunger": "Hunger",
24 | "autohud.group.air": "Air",
25 | "autohud.group.experience": "Experience",
26 | "autohud.group.mountJumpBar": "Mount Jump Bar",
27 | "autohud.group.mountHealth": "Mount Health",
28 | "autohud.option.health.policy": "在如下条件下显示生命值",
29 | "autohud.option.hunger.policy": "在如下条件下显示饥饿值",
30 | "autohud.option.revealHungerWhenHoldingFoodItem": "Reveal hunger bar when holding a food item in your hand and the player is not at full hunger.",
31 | "autohud.option.air.policy": "在如下条件下显示氧气值",
32 | "autohud.option.armor.policy": "在如下条件下显示盔甲",
33 | "autohud.option.experienceBar.active": "隐藏经验栏",
34 | "autohud.option.experienceBar.onChange": "在经验改变时显示",
35 | "autohud.option.mountJumpBar.active": "不蓄力时隐藏坐骑跳跃栏",
36 | "autohud.option.mountJumpBar.onChange": "蓄力时显示坐骑跳跃栏",
37 | "autohud.option.mountHealth.policy": "在如下条件下显示坐骑健康状况",
38 | "autohud.group.hotbar": "快捷栏",
39 | "autohud.option.hotbar.hotbar.active": "隐藏",
40 | "autohud.option.hotbar.hotbar.onChange": "在活动栏的内容变化时显示",
41 | "autohud.option.hotbar.onSlotChange": "在切换选择存储槽时显示",
42 | "autohud.option.hotbar.onLowDurability": "在低耐久时显示",
43 | "autohud.option.hotbar.durabilityPercentage": "低于显示的百分比",
44 | "autohud.option.hotbar.durabilityTotal": "低于显示的耐久",
45 | "autohud.option.hotbar.maximumFadeHotbarItems": "Fade-out limit for hotbar items",
46 | "autohud.option.hotbar.hideTooltip": "Always hide the selected item tooltip",
47 | "autohud.group.statusEffects": "Status effects",
48 | "autohud.option.statusEffects.active": "隐藏状态效果",
49 | "autohud.option.statusEffects.onChange": "显示当前的状态效果",
50 | "autohud.option.hidePersistentStatusEffects": "隐藏持续的状态效果",
51 | "autohud.option.hidePersistentStatusEffects.description": "对于不变的状态效果总是隐藏状态效果符号,例如戴着海龟壳时。",
52 | "autohud.option.showHiddenStatusEffects": "Show hidden",
53 | "autohud.option.showHiddenStatusEffects.description": "By default, status effects without particles only show in the inventory screen. Toggle this on to also show them in the top right.",
54 | "autohud.option.statusEffectTimer": "在其图标上显示状态效果的剩余时间",
55 | "autohud.option.statusEffectTimer.description": "Show remaining time of status effects on their icon",
56 | "autohud.group.scoreboard": "计分板",
57 | "autohud.option.scoreboard.scoreboard.active": "隐藏",
58 | "autohud.option.scoreboard.scoreboard.onChange": "在标题改变时显示",
59 | "autohud.option.scoreboard.onScoreChange": "在分数改变时显示",
60 | "autohud.option.scoreboard.onTeamChange": "在队伍改变时显示",
61 | "autohud.option.scoreboard.onTeamChange.description": "如果队伍是玩家分数的一部分,则更新它;否则,任何队伍都可以更新,但仍然没有提供实际的可见性。",
62 | "autohud.option.defaultValues.speedMultiplier": "默认的速度倍率",
63 | "autohud.option.defaultValues.distance": "默认距离",
64 | "autohud.option.defaultValues.maximumFade": "默认的淡出限制",
65 | "autohud.option.advanced.label": "Here you can manually adjust values for each component. This might be necessary if some other mod moves components around.\nSet numeric values to -1 to inherit from default.",
66 | "autohud.option.advanced.direction": "方向",
67 | "autohud.option.advanced.speedMultiplier": "速度倍数",
68 | "autohud.option.advanced.distance": "距离",
69 | "autohud.option.advanced.maximumFade": "淡出限制",
70 |
71 | "autohud.scrollDirection.Up": "上",
72 | "autohud.scrollDirection.Down": "下",
73 | "autohud.scrollDirection.Left": "左",
74 | "autohud.scrollDirection.Right": "右",
75 | "autohud.revealType.Individual": "独立",
76 | "autohud.revealType.Stacked": "叠加",
77 | "autohud.revealType.Grouped": "分组",
78 | "autohud.revealType.HideCombined": "隐藏合并",
79 | "autohud.revealType.Combined": "合并",
80 | "autohud.revealPolicy.Always": "总是",
81 | "autohud.revealPolicy.Disabled": "关闭",
82 | "autohud.revealPolicy.Changing": "变化",
83 | "autohud.revealPolicy.Increasing": "增加",
84 | "autohud.revealPolicy.Decreasing": "减少",
85 | "autohud.revealPolicy.NotFull": "未满",
86 | "autohud.revealPolicy.Low": "低",
87 |
88 | "key.category.autohud": "自动 HUD",
89 | "key.autohud.toggle-hud": "切换动态 HUD",
90 | "key.autohud.peek-hud": "按住时切换 HUD",
91 |
92 | "modmenu.summaryTranslation.autohud": "动态地隐藏界面元素",
93 | "modmenu.descriptionTranslation.autohud": "动态 HUD,在不需要时隐藏界面元素。",
94 | "autohud.requireYaclForConfigScreen": "To configure AutoHUD through ModMenu, please install YetAnotherConfigLib!"
95 | }
96 |
--------------------------------------------------------------------------------
/src/main/resources/autohud-common-compat.mixins.json:
--------------------------------------------------------------------------------
1 | {
2 | "required": true,
3 | "minVersion": "0.8",
4 | "package": "mod.crend.autohud.compat.mixin",
5 | "compatibilityLevel": "JAVA_17",
6 | "client": [
7 | ],
8 | "injectors": {
9 | "defaultRequire": 0
10 | },
11 | "plugin": "mod.crend.autohud.AutoHudCompatMixinPlugin"
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/resources/autohud-common.mixins.json:
--------------------------------------------------------------------------------
1 | {
2 | "required": true,
3 | "minVersion": "0.8",
4 | "package": "mod.crend.autohud.mixin",
5 | "compatibilityLevel": "JAVA_17",
6 | "client": [
7 | "ClientPlayNetworkHandlerMixin",
8 | "ScoreboardMixin",
9 | "TeamMixinAccessor"
10 | ],
11 | "injectors": {
12 | "defaultRequire": 1
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/resources/autohud.accesswidener:
--------------------------------------------------------------------------------
1 | accessWidener v2 named
--------------------------------------------------------------------------------
/src/main/resources/autohud.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Crendgrim/AutoHUD/e6fd1ea95c3f74646c5c73d447d89f79eeef7c95/src/main/resources/autohud.png
--------------------------------------------------------------------------------
/stonecutter.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("dev.kikugie.stonecutter")
3 | id("dev.architectury.loom") version "1.7-SNAPSHOT" apply false
4 | id("architectury-plugin") version "3.4-SNAPSHOT" apply false
5 | id("com.github.johnrengelman.shadow") version "8.1.1" apply false
6 | id("me.modmuss50.mod-publish-plugin") version "0.8.1" apply false
7 | }
8 | stonecutter active "1.20.1" /* [SC] DO NOT EDIT */
9 | stonecutter.automaticPlatformConstants = true
10 |
11 | // Builds every version into `build/libs/{mod.version}/{loader}`
12 | stonecutter registerChiseled tasks.register("chiseledBuild", stonecutter.chiseled) {
13 | group = "project"
14 | ofTask("buildAndCollect")
15 | }
16 |
17 | // Builds loader-specific versions into `build/libs/{mod.version}/{loader}`
18 | for (it in stonecutter.tree.branches) {
19 | if (it.id.isEmpty()) continue
20 | val loader = it.id.upperCaseFirst()
21 | stonecutter registerChiseled tasks.register("chiseledBuild$loader", stonecutter.chiseled) {
22 | group = "project"
23 | versions { branch, _ -> branch == it.id }
24 | ofTask("buildAndCollect")
25 | }
26 | }
27 |
28 | stonecutter registerChiseled tasks.register("chiseledPublishToMavenLocal", stonecutter.chiseled) {
29 | group = "project"
30 | ofTask("publishToMavenLocal")
31 | }
32 |
33 | stonecutter registerChiseled tasks.register("chiseledPublish", stonecutter.chiseled) {
34 | group = "project"
35 | ofTask("publishMods")
36 | }
37 |
38 | // Runs active versions for each loader
39 | for (it in stonecutter.tree.nodes) {
40 | if (it.metadata != stonecutter.current || it.branch.id.isEmpty()) continue
41 | val types = listOf("Client", "Server")
42 | val loader = it.branch.id.upperCaseFirst()
43 | for (type in types) it.tasks.register("runActive$type$loader") {
44 | group = "project"
45 | dependsOn("run$type")
46 | }
47 | }
48 |
49 | allprojects {
50 | repositories {
51 | mavenLocal()
52 | maven("https://maven.isxander.dev/releases")
53 | maven("https://maven.terraformersmc.com/")
54 | maven {
55 | name = "Fuzs Mod Resources"
56 | setUrl("https://raw.githubusercontent.com/Fuzss/modresources/main/maven/")
57 | }
58 |
59 | // AppleSkin
60 | maven("https://maven.ryanliptak.com/")
61 |
62 | exclusiveContent {
63 | forRepository {
64 | maven {
65 | name = "Modrinth"
66 | setUrl("https://api.modrinth.com/maven")
67 | }
68 | }
69 | filter {
70 | includeGroup("maven.modrinth")
71 | }
72 | }
73 |
74 | exclusiveContent {
75 | forRepository {
76 | maven {
77 | setUrl("https://cursemaven.com")
78 | }
79 | }
80 | filter {
81 | includeGroup("curse.maven")
82 | }
83 | }
84 |
85 | }
86 | }
87 |
88 | stonecutter parameters {
89 | listOf(
90 | "appleskin",
91 | "armorchroma",
92 | "coldsweat",
93 | "dehydration",
94 | "detailab",
95 | "environmentz",
96 | "farmers_delight_refabricated",
97 | "hotbarslotcycling",
98 | "legendary_survival_overhaul",
99 | "onebar",
100 | "quark",
101 | "raised",
102 | "statuseffectbars"
103 | ).map { modName ->
104 | modName to
105 | if (node == null)
106 | // :neoforge:1.20.1 is not defined, so we would not be able to switch back to 1.20.1 without
107 | // defining any constants used in the neoforge source set. Just set them all to unsupported.
108 | "[UNSUPPORTED]"
109 | else if (node!!.sibling("") == null || node!!.prop("loom.platform") == null)
110 | node!!.mod.dep(modName)
111 | else
112 | // For e.g. :fabric:1.20.1, use the property of :1.20.1
113 | node!!.sibling("")!!.mod.dep(node!!.prop("loom.platform")!!, modName)
114 | }.forEach { (mod, version) ->
115 | val modIsPresent = !version.startsWith("[");
116 | const(mod, modIsPresent)
117 | dependency(mod, if (modIsPresent) version else "0")
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/versions/1.20.1/gradle.properties:
--------------------------------------------------------------------------------
1 | mod.mc_dep_fabric=>=1.20 <=1.20.1
2 | mod.mc_dep_forgelike=[1.20, 1.20.1]
3 | mod.mc_title=1.20.1
4 | mod.mc_targets=1.20 1.20.1
5 |
6 | deps.forge_loader=47.3.0
7 | deps.neoforge_loader=[UNSUPPORTED]
8 |
9 | deps.yarn_build=10
10 |
11 | deps.fabric_api=0.92.2+1.20.1
12 | deps.libbamboo=2.4+1.20.1
13 | deps.yacl=3.6.1+1.20.1
14 | deps.modmenu=7.2.2
15 |
16 | deps.appleskin=2.5.1
17 | deps.appleskin_artifact=mc1.20
18 | deps.armorchroma=1.2.6
19 | deps.coldsweat=2.3.8
20 | deps.coldsweat_artifact=AjaHvVAp
21 | deps.dehydration=1.3.6+1.20.1
22 | deps.detailab=2.6.3+1.20.1-fabric
23 | deps.farmers_delight_refabricated=1.20.1-2.2.0
24 | deps.environmentz=2.0.8+1.20.1
25 | deps.hotbarslotcycling=[UNSUPPORTED]
26 | deps.legendary_survival_overhaul=5825918
27 | deps.onebar=4.0.0
28 | deps.quark=1.20.1-4.0-460
29 | deps.raised=4.0.1
30 | deps.raised_artifact=1.20.1
31 | deps.statuseffectbars=1.0.3
--------------------------------------------------------------------------------
/versions/1.20.4/gradle.properties:
--------------------------------------------------------------------------------
1 | mod.mc_dep_fabric=>=1.20.3 <=1.20.4
2 | mod.mc_dep_forgelike=[1.20.3, 1.20.4]
3 | mod.mc_title=1.20.4
4 | mod.mc_targets=1.20.3 1.20.4
5 |
6 | deps.forge_loader=49.1.0
7 | deps.neoforge_loader=20.4.237
8 | deps.neoforge_patch=[UNSUPPORTED]
9 |
10 | deps.yarn_build=3
11 |
12 | deps.fabric_api=0.97.2+1.20.4
13 | deps.libbamboo=2.4+1.20.4
14 | deps.yacl=3.6.1+1.20.4
15 | deps.modmenu=9.0.0
16 |
17 | deps.appleskin=2.5.1
18 | deps.appleskin_artifact=mc1.20.3
19 | deps.armorchroma=1.2.6
20 | deps.coldsweat=[UNSUPPORTED]
21 | deps.coldsweat_artifact=AjaHvVAp
22 | deps.dehydration=[UNSUPPORTED]
23 | deps.detailab=2.6.3+1.20.4-fabric
24 | deps.farmers_delight_refabricated=[UNSUPPORTED]
25 | deps.environmentz=[UNSUPPORTED]
26 | deps.hotbarslotcycling=[UNSUPPORTED]
27 | deps.legendary_survival_overhaul=[UNSUPPORTED]
28 | deps.onebar=4.1.0
29 | deps.quark=[UNSUPPORTED]
30 | deps.raised=4.0.1
31 | deps.raised_artifact=1.20.4
32 | deps.statuseffectbars=1.0.4
33 |
--------------------------------------------------------------------------------
/versions/1.20.6/gradle.properties:
--------------------------------------------------------------------------------
1 | mod.mc_dep_fabric=>=1.20.5 <=1.20.6
2 | mod.mc_dep_forgelike=[1.20.5, 1.20.6]
3 | mod.mc_title=1.20.6
4 | mod.mc_targets=1.20.5 1.20.6
5 |
6 | deps.forge_loader=50.1.0
7 | deps.neoforge_loader=20.6.121
8 | deps.neoforge_patch=1.20.6+build.4
9 |
10 | deps.yarn_build=3
11 |
12 | deps.fabric_api=0.100.8+1.20.6
13 | deps.libbamboo=2.4+1.20.6
14 | deps.yacl=3.6.1+1.20.6
15 | deps.modmenu=10.0.0
16 |
17 | deps.appleskin=3.0.5
18 | deps.appleskin_artifact=mc1.20.5
19 | deps.armorchroma=1.2.7
20 | deps.coldsweat=[UNSUPPORTED]
21 | deps.coldsweat_artifact=[UNSUPPORTED]
22 | deps.dehydration=[UNSUPPORTED]
23 | deps.detailab=14.1-beta.2+1.20.6
24 | deps.environmentz=[UNSUPPORTED]
25 | deps.farmers_delight_refabricated=[UNSUPPORTED]
26 | deps.hotbarslotcycling=[UNSUPPORTED]
27 | deps.legendary_survival_overhaul=[UNSUPPORTED]
28 | deps.onebar=4.1.1
29 | deps.quark=[UNSUPPORTED]
30 | deps.raised=4.0.1
31 | deps.raised_artifact=1.20.6
32 | deps.statuseffectbars=1.0.5
33 |
--------------------------------------------------------------------------------
/versions/1.21.1/gradle.properties:
--------------------------------------------------------------------------------
1 | mod.mc_dep_fabric=>=1.21 <=1.21.1
2 | mod.mc_dep_forgelike=[1.21, 1.21.1]
3 | mod.mc_title=1.21.1
4 | mod.mc_targets=1.21 1.21.1
5 |
6 | deps.forge_loader=52.0.28
7 | deps.neoforge_loader=21.1.66
8 | deps.neoforge_patch=1.21+build.4
9 |
10 | deps.yarn_build=3
11 |
12 | deps.fabric_api=0.106.0+1.21.1
13 | deps.libbamboo=2.4+1.21.1
14 | deps.yacl=3.6.1+1.21
15 | deps.modmenu=11.0.3
16 |
17 | deps.appleskin=3.0.5
18 | deps.appleskin_artifact=mc1.21
19 | deps.armorchroma=1.2.8
20 | deps.coldsweat=2.3.8
21 | deps.coldsweat_artifact=2.3.8
22 | deps.dehydration=1.3.7+1.21.1
23 | deps.detailab=2.6.3+1.21.1-fabric
24 | deps.environmentz=2.0.9+1.21.1
25 | deps.farmers_delight_refabricated=1.21.1-2.2.2
26 | deps.hotbarslotcycling=21.1.1
27 | deps.hotbarslotcycling_forge=[UNSUPPORTED]
28 | deps.legendary_survival_overhaul=[UNSUPPORTED]
29 | deps.onebar=4.1.2
30 | deps.quark=[UNSUPPORTED]
31 | deps.raised=4.0.1
32 | deps.raised_artifact=1.21.1
33 | deps.statuseffectbars=1.0.6
34 |
--------------------------------------------------------------------------------
/versions/1.21.3/gradle.properties:
--------------------------------------------------------------------------------
1 | mod.mc_dep_fabric=>=1.21.2
2 | mod.mc_dep_forgelike=[1.21.2,]
3 | mod.mc_title=1.21.3
4 | mod.mc_targets=1.21.3
5 |
6 | deps.forge_loader=53.0.25
7 | deps.neoforge_loader=21.3.7-beta
8 | deps.neoforge_patch=1.21+build.4
9 |
10 | deps.yarn_build=2
11 |
12 | deps.fabric_api=0.107.0+1.21.3
13 | deps.libbamboo=2.4+1.21.3
14 | deps.yacl=3.6.1+1.21.2
15 | deps.modmenu=12.0.0-beta.1
16 |
17 | deps.appleskin=3.0.6
18 | deps.appleskin_artifact=mc1.21.3
19 | deps.armorchroma=[UNSUPPORTED]
20 | deps.coldsweat=[UNSUPPORTED]
21 | deps.coldsweat_artifact=[UNSUPPORTED]
22 | deps.dehydration=[UNSUPPORTED]
23 | deps.detailab=2.6.3+1.21.3-fabric
24 | deps.environmentz=[UNSUPPORTED]
25 | deps.farmers_delight_refabricated=[UNSUPPORTED]
26 | deps.hotbarslotcycling=[UNSUPPORTED]
27 | deps.legendary_survival_overhaul=[UNSUPPORTED]
28 | deps.onebar=4.2.0
29 | deps.quark=[UNSUPPORTED]
30 | deps.raised=4.0.1
31 | deps.raised_artifact=1.21.3
32 | deps.statuseffectbars=1.0.7
33 |
--------------------------------------------------------------------------------