add hotbar borders

This commit is contained in:
2026-01-10 14:24:08 +01:00
parent f5fa0d2498
commit 5c90d046a3
9 changed files with 761 additions and 0 deletions

View File

@@ -0,0 +1,62 @@
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.fabricmc.fabric.api.client.rendering.v1;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
/**
* Callback for when hud layers are registered.
*
* <p>To register a layer, register a listener to this event and register your layers in the listener.
* For common use cases, see {@link LayeredDrawerWrapper}.
*
* <p>For example, the following code registers a layer after {@link IdentifiedLayer#MISC_OVERLAYS}:
* {@snippet :
* // @link region substring=HudLayerRegistrationCallback target=HudLayerRegistrationCallback
* // @link region substring=EVENT target="HudLayerRegistrationCallback#EVENT"
* // @link region substring=layeredDrawer target="LayeredDrawerWrapper"
* // @link region substring=attachLayerAfter target="LayeredDrawerWrapper#attachLayerAfter"
* // @link region substring=IdentifiedLayer target=IdentifiedLayer
* // @link region substring=MISC_OVERLAYS target="IdentifiedLayer#MISC_OVERLAYS"
* // @link region substring=Identifier target="net.minecraft.util.Identifier"
* // @link region substring=of target="net.minecraft.util.Identifier#of"
* // @link region substring=context target="net.minecraft.client.gui.DrawContext"
* // @link region substring=tickCounter target="net.minecraft.client.render.RenderTickCounter"
* HudLayerRegistrationCallback.EVENT.register(layeredDrawer -> layeredDrawer.attachLayerAfter(IdentifiedLayer.MISC_OVERLAYS, Identifier.of("example", "example_layer_after_misc_overlays"), (context, tickCounter) -> {
* // Your rendering code here
* }));
* // @end @end @end @end @end @end @end @end @end @end
* }
*
* @see LayeredDrawerWrapper
*/
public interface HudLayerRegistrationCallback {
Event<HudLayerRegistrationCallback> EVENT = EventFactory.createArrayBacked(HudLayerRegistrationCallback.class, callbacks -> layeredDrawer -> {
for (HudLayerRegistrationCallback callback : callbacks) {
callback.register(layeredDrawer);
}
});
/**
* Called when registering hud layers.
*
* @param layeredDrawer the layered drawer to register layers to
* @see LayeredDrawerWrapper
*/
void register(LayeredDrawerWrapper layeredDrawer);
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.fabricmc.fabric.api.client.rendering.v1;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
import net.minecraft.class_332;
import net.minecraft.class_9779;
/**
* @deprecated Use {@link HudLayerRegistrationCallback} instead. For common use cases, see {@link LayeredDrawerWrapper}.
*/
@Deprecated
public interface HudRenderCallback {
Event<HudRenderCallback> EVENT = EventFactory.createArrayBacked(HudRenderCallback.class, (listeners) -> (context, tickCounter) -> {
for (HudRenderCallback event : listeners) {
event.onHudRender(context, tickCounter);
}
});
/**
* Called after rendering the whole hud, which is displayed in game, in a world.
*
* @param drawContext the {@link class_332} instance
* @param tickCounter the {@link class_9779} instance
*/
void onHudRender(class_332 drawContext, class_9779 tickCounter);
}

View File

@@ -0,0 +1,113 @@
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.fabricmc.fabric.api.client.rendering.v1;
import net.fabricmc.fabric.impl.client.rendering.WrappedLayer;
import net.minecraft.class_2960;
import net.minecraft.class_9080;
/**
* A hud layer that has an identifier attached for use in {@link LayeredDrawerWrapper}.
*
* <p>The identifiers in this interface are the vanilla hud layers in the order they are drawn in.
* The first layer is drawn first, which means it is at the bottom.
* All vanilla layers except {@link #SLEEP} are in sub drawers and have a render condition attached ({@link net.minecraft.class_315#field_1842}).
* Operations relative to any layer will generally inherit that layer's render condition.
* There is currently no mechanism to change the render condition of a layer.
*
* <p>For common use cases and more details on how this API deals with render condition, see {@link LayeredDrawerWrapper}.
*/
public interface IdentifiedLayer extends class_9080.class_9081 {
/**
* The identifier for the vanilla miscellaneous overlays (such as vignette, spyglass, and powder snow) layer.
*/
class_2960 MISC_OVERLAYS = class_2960.method_60656("misc_overlays");
/**
* The identifier for the vanilla crosshair layer.
*/
class_2960 CROSSHAIR = class_2960.method_60656("crosshair");
/**
* The identifier for the vanilla hotbar, spectator hud, experience bar, and status bars layer.
*/
class_2960 HOTBAR_AND_BARS = class_2960.method_60656("hotbar_and_bars");
/**
* The identifier for the vanilla experience level layer.
*/
class_2960 EXPERIENCE_LEVEL = class_2960.method_60656("experience_level");
/**
* The identifier for the vanilla status effects layer.
*/
class_2960 STATUS_EFFECTS = class_2960.method_60656("status_effects");
/**
* The identifier for the vanilla boss bar layer.
*/
class_2960 BOSS_BAR = class_2960.method_60656("boss_bar");
/**
* The identifier for the vanilla sleep overlay layer.
*/
class_2960 SLEEP = class_2960.method_60656("sleep");
/**
* The identifier for the vanilla demo timer layer.
*/
class_2960 DEMO_TIMER = class_2960.method_60656("demo_timer");
/**
* The identifier for the vanilla debug hud layer.
*/
class_2960 DEBUG = class_2960.method_60656("debug");
/**
* The identifier for the vanilla scoreboard layer.
*/
class_2960 SCOREBOARD = class_2960.method_60656("scoreboard");
/**
* The identifier for the vanilla overlay message layer.
*/
class_2960 OVERLAY_MESSAGE = class_2960.method_60656("overlay_message");
/**
* The identifier for the vanilla title and subtitle layer.
*
* <p>Note that this is not the sound subtitles.
*/
class_2960 TITLE_AND_SUBTITLE = class_2960.method_60656("title_and_subtitle");
/**
* The identifier for the vanilla chat layer.
*/
class_2960 CHAT = class_2960.method_60656("chat");
/**
* The identifier for the vanilla player list layer.
*/
class_2960 PLAYER_LIST = class_2960.method_60656("player_list");
/**
* The identifier for the vanilla sound subtitles layer.
*/
class_2960 SUBTITLES = class_2960.method_60656("subtitles");
/**
* @return the identifier of the layer
*/
class_2960 id();
/**
* Wraps a hud layer in an identified layer.
*
* @param id the identifier to give the layer
* @param layer the layer to wrap
* @return the identified layer
*/
static IdentifiedLayer of(class_2960 id, class_9080.class_9081 layer) {
return new WrappedLayer(id, layer);
}
}

View File

@@ -0,0 +1,151 @@
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.fabricmc.fabric.api.client.rendering.v1;
import java.util.function.Function;
import net.minecraft.class_2960;
import net.minecraft.class_9080;
import org.jetbrains.annotations.Contract;
/**
* A layered drawer that has an identifier attached to each layer and methods to add layers in specific positions.
*
* <p>Operations relative to a layer will generally inherit that layer's render condition.
* The render condition for all vanilla layers except {@link IdentifiedLayer#SLEEP} is {@link net.minecraft.class_315#field_1842}.
* Only {@link #addLayer(IdentifiedLayer)} will not inherit any render condition.
* There is currently no mechanism to change the render condition of a layer.
* For vanilla layers, see {@link IdentifiedLayer}.
*
* <p>Common places to add layers (as of 1.21.4):
* <table>
* <tr>
* <th>Injection Point</th>
* <th>Use Case</th>
* </tr>
* <tr>
* <td>Before {@link IdentifiedLayer#MISC_OVERLAYS MISC_OVERLAYS}</td>
* <td>Render before everything</td>
* </tr>
* <tr>
* <td>After {@link IdentifiedLayer#MISC_OVERLAYS MISC_OVERLAYS}</td>
* <td>Render after misc overlays (vignette, spyglass, and powder snow) and before the crosshair</td>
* </tr>
* <tr>
* <td>After {@link IdentifiedLayer#EXPERIENCE_LEVEL EXPERIENCE_LEVEL}</td>
* <td>Render after most main hud elements like hotbar, spectator hud, status bars, experience bar, status effects overlays, and boss bar and before the sleep overlay</td>
* </tr>
* <tr>
* <td>Before {@link IdentifiedLayer#DEMO_TIMER DEMO_TIMER}</td>
* <td>Render after sleep overlay and before the demo timer, debug HUD, scoreboard, overlay message (action bar), and title and subtitle</td>
* </tr>
* <tr>
* <td>Before {@link IdentifiedLayer#CHAT CHAT}</td>
* <td>Render after the debug HUD, scoreboard, overlay message (action bar), and title and subtitle and before {@link net.minecraft.class_338 ChatHud}, player list, and sound subtitles</td>
* </tr>
* <tr>
* <td>After {@link IdentifiedLayer#SUBTITLES SUBTITLES}</td>
* <td>Render after everything</td>
* </tr>
* </table>
*
* @see HudLayerRegistrationCallback
*/
public interface LayeredDrawerWrapper {
/**
* Adds a layer to the end of the layered drawer.
*
* @param layer the layer to add
* @return this layered drawer
*/
@Contract("_ -> this")
LayeredDrawerWrapper addLayer(IdentifiedLayer layer);
/**
* Attaches a layer before the layer with the specified identifier.
*
* <p>The render condition of the layer being attached to, if any, also applies to the new layer.
*
* @param beforeThis the identifier of the layer to add the new layer before
* @param layer the layer to add
* @return this layered drawer
*/
@Contract("_, _ -> this")
LayeredDrawerWrapper attachLayerBefore(class_2960 beforeThis, IdentifiedLayer layer);
/**
* Attaches a layer before the layer with the specified identifier.
*
* <p>The render condition of the layer being attached to, if any, also applies to the new layer.
*
* @param beforeThis the identifier of the layer to add the new layer before
* @param identifier the identifier of the new layer
* @param layer the layer to add
* @return this layered drawer
*/
@Contract("_, _, _ -> this")
default LayeredDrawerWrapper attachLayerBefore(class_2960 beforeThis, class_2960 identifier, class_9080.class_9081 layer) {
return attachLayerBefore(beforeThis, IdentifiedLayer.of(identifier, layer));
}
/**
* Attaches a layer after the layer with the specified identifier.
*
* <p>The render condition of the layer being attached to, if any, also applies to the new layer.
*
* @param afterThis the identifier of the layer to add the new layer after
* @param layer the layer to add
* @return this layered drawer
*/
@Contract("_, _ -> this")
LayeredDrawerWrapper attachLayerAfter(class_2960 afterThis, IdentifiedLayer layer);
/**
* Attaches a layer after the layer with the specified identifier.
*
* <p>The render condition of the layer being attached to, if any, also applies to the new layer.
*
* @param afterThis the identifier of the layer to add the new layer after
* @param identifier the identifier of the new layer
* @param layer the layer to add
* @return this layered drawer
*/
@Contract("_, _, _ -> this")
default LayeredDrawerWrapper attachLayerAfter(class_2960 afterThis, class_2960 identifier, class_9080.class_9081 layer) {
return attachLayerAfter(afterThis, IdentifiedLayer.of(identifier, layer));
}
/**
* Removes a layer with the specified identifier.
*
* @param identifier the identifier of the layer to remove
* @return this layered drawer
*/
@Contract("_ -> this")
LayeredDrawerWrapper removeLayer(class_2960 identifier);
/**
* Replaces a layer with the specified identifier.
*
* <p>The render condition of the layer being replaced, if any, also applies to the new layer.
*
* @param identifier the identifier of the layer to replace
* @param replacer a function that takes the old layer and returns the new layer
* @return this layered drawer
*/
@Contract("_, _ -> this")
LayeredDrawerWrapper replaceLayer(class_2960 identifier, Function<IdentifiedLayer, IdentifiedLayer> replacer);
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.fabricmc.fabric.api.client.rendering.v1.hud;
import net.minecraft.class_332;
import net.minecraft.class_9779;
/**
* Represents a mod added {@link net.minecraft.class_329} element that can be rendered on the screen.
*
*
* <p>HUD elements should be registered using {@link HudElementRegistry}
*/
public interface HudElement {
/**
* Renders the HUD element.
*
* @param context the {@link class_332} used for rendering
* @param tickCounter the {@link class_9779} providing timing information
*/
void render(class_332 context, class_9779 tickCounter);
}

View File

@@ -0,0 +1,153 @@
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.fabricmc.fabric.api.client.rendering.v1.hud;
import java.util.Objects;
import java.util.function.Function;
import net.fabricmc.fabric.impl.client.rendering.hud.HudElementRegistryImpl;
import net.minecraft.class_2960;
/**
* A registry of identified hud layers with methods to add layers in specific positions.
*
* <p>Operations relative to a vanilla element will inherit that element's render condition.
*
* <p>The render condition for all vanilla layers except {@link VanillaHudElements#SLEEP} is
* {@link net.minecraft.class_315#field_1842}.
*
* <p>Only {@link #addFirst(class_2960, HudElement)} and {@link #addLast(class_2960, HudElement)} will not inherit any
* render condition.
*
* <p>There is currently no mechanism to change the render condition of a vanilla element.
*
* <p>For vanilla layers, see {@link VanillaHudElements}.
*
* <p>Common places to add layers (as of 1.21.6):
* <table>
* <tr>
* <th>Injection Point</th>
* <th>Use Case</th>
* </tr>
* <tr>
* <td>Before {@link VanillaHudElements#MISC_OVERLAYS MISC_OVERLAYS}</td>
* <td>Render before everything</td>
* </tr>
* <tr>
* <td>After {@link VanillaHudElements#MISC_OVERLAYS MISC_OVERLAYS}</td>
* <td>Render after misc overlays (vignette, spyglass, and powder snow) and before the crosshair</td>
* </tr>
* <tr>
* <td>After {@link VanillaHudElements#BOSS_BAR BOSS_BAR}</td>
* <td>Render after most main hud layers like hotbar, spectator hud, status bars, experience bar, status effects overlays, and boss bar and before the sleep overlay</td>
* </tr>
* <tr>
* <td>Before {@link VanillaHudElements#DEMO_TIMER DEMO_TIMER}</td>
* <td>Render after sleep overlay and before the demo timer, debug HUD, scoreboard, overlay message (action bar), and title and subtitle</td>
* </tr>
* <tr>
* <td>Before {@link VanillaHudElements#CHAT CHAT}</td>
* <td>Render after the debug HUD, scoreboard, overlay message (action bar), and title and subtitle and before {@link net.minecraft.class_338 ChatHud}, player list, and sound subtitles</td>
* </tr>
* <tr>
* <td>After {@link VanillaHudElements#SUBTITLES SUBTITLES}</td>
* <td>Render after everything</td>
* </tr>
* </table>
*/
public interface HudElementRegistry {
/**
* Adds an element to the front.
*
* @param element the element to add
*/
static void addFirst(class_2960 id, HudElement element) {
Objects.requireNonNull(id, "identifier");
Objects.requireNonNull(element, "hudElement");
HudElementRegistryImpl.addFirst(id, element);
}
/**
* Adds an element to the end.
*
* @param element the element to add
*/
static void addLast(class_2960 id, HudElement element) {
Objects.requireNonNull(id, "identifier");
Objects.requireNonNull(element, "hudElement");
HudElementRegistryImpl.addLast(id, element);
}
/**
* Attaches an element before the element with the specified identifier.
*
* <p>The render condition of the vanilla element being attached to, if any, also applies to the new element.
*
* @param beforeThis the identifier of the element to add the new element before
* @param identifier the identifier of the new element
* @param element the element to add
*/
static void attachElementBefore(class_2960 beforeThis, class_2960 identifier, HudElement element) {
Objects.requireNonNull(beforeThis, "beforeThis");
Objects.requireNonNull(identifier, "identifier");
Objects.requireNonNull(element, "hudElement");
HudElementRegistryImpl.attachElementBefore(beforeThis, identifier, element);
}
/**
* Attaches an element after the element with the specified identifier.
*
* <p>The render condition of the vanilla element being attached to, if any, also applies to the new element.
*
* @param afterThis the identifier of the element to add the new element after
* @param identifier the identifier of the new element
* @param element the element to add
*/
static void attachElementAfter(class_2960 afterThis, class_2960 identifier, HudElement element) {
Objects.requireNonNull(afterThis, "afterThis");
Objects.requireNonNull(identifier, "identifier");
Objects.requireNonNull(element, "hudElement");
HudElementRegistryImpl.attachElementAfter(afterThis, identifier, element);
}
/**
* Removes an element with the specified identifier.
*
* @param identifier the identifier of the element to remove
*/
static void removeElement(class_2960 identifier) {
Objects.requireNonNull(identifier, "identifier");
HudElementRegistryImpl.removeElement(identifier);
}
/**
* Replaces an element with the specified identifier, the element retains its original identifier.
*
* <p>The render condition of the vanilla element being replaced, if any, also applies to the new element.
*
* <p>If the replaced element is a status bar (like {@link VanillaHudElements#HEALTH_BAR HEALTH_BAR},
* {@link VanillaHudElements#ARMOR_BAR ARMOR_BAR} or {@link VanillaHudElements#FOOD_BAR FOOD_BAR}), it may be
* necessary to register a new {@link StatusBarHeightProvider} in {@link HudStatusBarHeightRegistry}.
*
* @param identifier the identifier of the element to replace
* @param replacer a function that takes the old element and returns the new element
*/
static void replaceElement(class_2960 identifier, Function<HudElement, HudElement> replacer) {
Objects.requireNonNull(identifier, "identifier");
Objects.requireNonNull(replacer, "replacer");
HudElementRegistryImpl.replaceElement(identifier, replacer);
}
}

View File

@@ -0,0 +1,134 @@
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.fabricmc.fabric.api.client.rendering.v1.hud;
import net.minecraft.class_2960;
/**
* A hud element that has an identifier attached for use in {@link HudElementRegistry}.
*
* <p>The identifiers in this interface are the vanilla hud layers in the order they are drawn in.
* The first element is drawn first, which means it is at the bottom.
* All vanilla layers except {@link #SLEEP} are in sub drawers and have a render condition attached ({@link net.minecraft.class_315#field_1842}).
* Operations relative to any element will generally inherit that element's render condition.
* There is currently no mechanism to change the render condition of an element.
*
* <p>For common use cases and more details on how this API deals with render condition, see {@link HudElementRegistry}.
*/
public final class VanillaHudElements {
/**
* The identifier for the vanilla miscellaneous overlays (such as vignette, spyglass, and powder snow) element.
*/
public static final class_2960 MISC_OVERLAYS = class_2960.method_60656("misc_overlays");
/**
* The identifier for the vanilla crosshair element.
*/
public static final class_2960 CROSSHAIR = class_2960.method_60656("crosshair");
/**
* The identifier for the vanilla spectator menu.
*/
public static final class_2960 SPECTATOR_MENU = class_2960.method_60656("spectator_menu");
/**
* The identifier for the vanilla hotbar.
*/
public static final class_2960 HOTBAR = class_2960.method_60656("hotbar");
/**
* The identifier for the player armor level bar.
*/
public static final class_2960 ARMOR_BAR = class_2960.method_60656("armor_bar");
/**
* The identifier for the player health bar.
*/
public static final class_2960 HEALTH_BAR = class_2960.method_60656("health_bar");
/**
* The identifier for the player hunger level bar.
*/
public static final class_2960 FOOD_BAR = class_2960.method_60656("food_bar");
/**
* The identifier for the player air level bar.
*/
public static final class_2960 AIR_BAR = class_2960.method_60656("air_bar");
/**
* The identifier for the vanilla mount health.
*/
public static final class_2960 MOUNT_HEALTH = class_2960.method_60656("mount_health");
/**
* The identifier for the info bar, either empty, experience bar, locator, or jump bar.
*/
public static final class_2960 INFO_BAR = class_2960.method_60656("info_bar");
/**
* The identifier for experience level tooltip.
*/
public static final class_2960 EXPERIENCE_LEVEL = class_2960.method_60656("experience_level");
/**
* The identifier for held item tooltip.
*/
public static final class_2960 HELD_ITEM_TOOLTIP = class_2960.method_60656("held_item_tooltip");
/**
* The identifier for the vanilla spectator tooltip.
*/
public static final class_2960 SPECTATOR_TOOLTIP = class_2960.method_60656("spectator_tooltip");
/**
* The identifier for the vanilla status effects element.
*/
public static final class_2960 STATUS_EFFECTS = class_2960.method_60656("status_effects");
/**
* The identifier for the vanilla boss bar element.
*/
public static final class_2960 BOSS_BAR = class_2960.method_60656("boss_bar");
/**
* The identifier for the vanilla sleep overlay element.
*/
public static final class_2960 SLEEP = class_2960.method_60656("sleep");
/**
* The identifier for the vanilla demo timer element.
*/
public static final class_2960 DEMO_TIMER = class_2960.method_60656("demo_timer");
/**
* The identifier for the vanilla debug hud element.
*/
public static final class_2960 DEBUG = class_2960.method_60656("debug");
/**
* The identifier for the vanilla scoreboard element.
*/
public static final class_2960 SCOREBOARD = class_2960.method_60656("scoreboard");
/**
* The identifier for the vanilla overlay message element.
*/
public static final class_2960 OVERLAY_MESSAGE = class_2960.method_60656("overlay_message");
/**
* The identifier for the vanilla title and subtitle element.
*
* <p>Note that this is not the sound subtitles.
*/
public static final class_2960 TITLE_AND_SUBTITLE = class_2960.method_60656("title_and_subtitle");
/**
* The identifier for the vanilla chat element.
*/
public static final class_2960 CHAT = class_2960.method_60656("chat");
/**
* The identifier for the vanilla player list element.
*/
public static final class_2960 PLAYER_LIST = class_2960.method_60656("player_list");
/**
* The identifier for the vanilla sound subtitles element.
*/
public static final class_2960 SUBTITLES = class_2960.method_60656("subtitles");
private VanillaHudElements() {
}
}

View File

@@ -58,6 +58,46 @@ public final class BorderRenderer {
}
}
public static void renderHud(GuiGraphics graphics) {
IconsEnhancedConfig config = ConfigManager.get();
if (!config.borders.enabled) {
return;
}
Minecraft client = Minecraft.getInstance();
if (client.player == null || client.level == null || client.options.hideGui) {
return;
}
if (client.screen != null) {
return;
}
int thickness = clamp(config.borders.thickness, 1, 3);
boolean redrawItems = config.tooltips.enabled && config.tooltips.showIcons;
Font font = redrawItems ? client.font : null;
int width = client.getWindow().getGuiScaledWidth();
int height = client.getWindow().getGuiScaledHeight();
int left = (width / 2) - 91;
int top = height - 22;
for (int i = 0; i < 9; i++) {
ItemStack stack = client.player.getInventory().getItem(i);
if (stack.isEmpty()) {
continue;
}
int slotX = left + (i * 20) + 3;
int slotY = top + 3;
int color = COLOR_LOGIC.resolve(stack);
if ((color >>> 24) == 0) {
continue;
}
drawBorder(graphics, slotX, slotY, thickness, color);
if (redrawItems) {
graphics.renderItem(stack, slotX, slotY);
graphics.renderItemDecorations(font, stack, slotX, slotY);
}
}
}
private static void drawBorder(GuiGraphics graphics, int x, int y, int thickness, int color) {
int left = x;
int top = y;

View File

@@ -1,9 +1,22 @@
package dev.dekin.iconsenhanced.client;
import dev.dekin.iconsenhanced.IconsEnhanced;
import dev.dekin.iconsenhanced.common.ConfigManager;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
//? if >=1.20.5 {
import net.fabricmc.fabric.api.client.rendering.v1.hud.HudElementRegistry;
import net.fabricmc.fabric.api.client.rendering.v1.hud.VanillaHudElements;
//?} else {
/*import net.fabricmc.fabric.api.client.rendering.v1.HudLayerRegistrationCallback;
import net.fabricmc.fabric.api.client.rendering.v1.IdentifiedLayer;
*///?}
import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents;
//? if >=1.21.11 {
import net.minecraft.resources.Identifier;
//?} else {
/*import net.minecraft.resources.ResourceLocation;
*///?}
public final class ClientInit implements ClientModInitializer {
@Override
@@ -12,6 +25,7 @@ public final class ClientInit implements ClientModInitializer {
BorderRenderer.applyConfig();
TooltipAugmenter.register();
ClientTickEvents.END_CLIENT_TICK.register(client -> TooltipAugmenter.registerLate());
registerHudBorders();
ScreenEvents.AFTER_INIT.register((client, screen, scaledWidth, scaledHeight) -> {
ScreenEvents.beforeRender(screen).register((current, graphics, mouseX, mouseY, delta) -> {
@@ -24,4 +38,20 @@ public final class ClientInit implements ClientModInitializer {
});
});
}
private static void registerHudBorders() {
//? if >=1.21.11 {
Identifier id = Identifier.fromNamespaceAndPath(IconsEnhanced.MOD_ID, "hotbar_borders");
//?} else if >=1.21 {
/*ResourceLocation id = ResourceLocation.fromNamespaceAndPath(IconsEnhanced.MOD_ID, "hotbar_borders");
*///?} else {
/*ResourceLocation id = new ResourceLocation(IconsEnhanced.MOD_ID, "hotbar_borders");
*///?}
//? if >=1.20.5 {
HudElementRegistry.attachElementAfter(VanillaHudElements.HOTBAR, id, (graphics, tickCounter) -> BorderRenderer.renderHud(graphics));
//?} else {
/*HudLayerRegistrationCallback.EVENT.register(layeredDrawer ->
layeredDrawer.attachLayerAfter(IdentifiedLayer.HOTBAR_AND_BARS, id, (graphics, tickCounter) -> BorderRenderer.renderHud(graphics)));
*///?}
}
}