diff --git a/legacy-fabric-keybindings-api-v1/1.6.4/src/main/java/net/legacyfabric/fabric/impl/client/keybinding/ControlsScreenExtensions.java b/legacy-fabric-keybindings-api-v1/1.6.4/src/main/java/net/legacyfabric/fabric/impl/client/keybinding/ControlsScreenExtensions.java new file mode 100644 index 000000000..6011207ee --- /dev/null +++ b/legacy-fabric-keybindings-api-v1/1.6.4/src/main/java/net/legacyfabric/fabric/impl/client/keybinding/ControlsScreenExtensions.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2020 - 2024 Legacy Fabric + * Copyright (c) 2016 - 2022 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.legacyfabric.fabric.impl.client.keybinding; + +public interface ControlsScreenExtensions { + void fabric_nextPage(); + + void fabric_previousPage(); + + int fabric_currentPage(); + + boolean fabric_isButtonVisible(FabricControlsScreenComponents.Type type); + + boolean fabric_isButtonEnabled(FabricControlsScreenComponents.Type type); +} diff --git a/legacy-fabric-keybindings-api-v1/1.6.4/src/main/java/net/legacyfabric/fabric/impl/client/keybinding/FabricControlsScreenComponents.java b/legacy-fabric-keybindings-api-v1/1.6.4/src/main/java/net/legacyfabric/fabric/impl/client/keybinding/FabricControlsScreenComponents.java new file mode 100644 index 000000000..8dd9c7543 --- /dev/null +++ b/legacy-fabric-keybindings-api-v1/1.6.4/src/main/java/net/legacyfabric/fabric/impl/client/keybinding/FabricControlsScreenComponents.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2020 - 2024 Legacy Fabric + * Copyright (c) 2016 - 2022 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.legacyfabric.fabric.impl.client.keybinding; + +import java.util.function.Consumer; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.options.ControlsOptionsScreen; +import net.minecraft.client.gui.widget.ButtonWidget; + +import net.legacyfabric.fabric.api.util.Identifier; + +public class FabricControlsScreenComponents { + private static final Identifier BUTTON_TEX = new Identifier("legacy-fabric", "textures/gui/creative_buttons.png"); + public static final int AMOUNT_PER_PAGE = 14; + + public static class ControlsButtonWidget extends ButtonWidget { + ControlsScreenExtensions extensions; + ControlsOptionsScreen gui; + Type type; + + public ControlsButtonWidget(int x, int y, Type type, ControlsScreenExtensions extensions) { + super(1000 + type.ordinal(), x, y, 20, 20, type.text); + this.extensions = extensions; + this.type = type; + this.gui = (ControlsOptionsScreen) extensions; + } + + public void click() { + if (this.active) { + this.type.clickConsumer.accept(this.extensions); + } + } + + @Override + public boolean isMouseOver(MinecraftClient client, int mouseX, int mouseY) { + return super.isMouseOver(client, mouseX, mouseY); + } + + @Override + public void mouseDragged(MinecraftClient client, int mouseX, int mouseY) { + this.hovered = mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.width && mouseY < this.y + this.height; + this.visible = extensions.fabric_isButtonVisible(type); + this.active = extensions.fabric_isButtonEnabled(type); + } + } + + public enum Type { + NEXT(">", ControlsScreenExtensions::fabric_nextPage), + PREVIOUS("<", ControlsScreenExtensions::fabric_previousPage); + + final String text; + final Consumer clickConsumer; + + Type(String text, Consumer clickConsumer) { + this.text = text; + this.clickConsumer = clickConsumer; + } + } +} diff --git a/legacy-fabric-keybindings-api-v1/1.6.4/src/main/java/net/legacyfabric/fabric/mixin/client/keybinding/ControlsOptionsScreenMixin.java b/legacy-fabric-keybindings-api-v1/1.6.4/src/main/java/net/legacyfabric/fabric/mixin/client/keybinding/ControlsOptionsScreenMixin.java new file mode 100644 index 000000000..1049e44f6 --- /dev/null +++ b/legacy-fabric-keybindings-api-v1/1.6.4/src/main/java/net/legacyfabric/fabric/mixin/client/keybinding/ControlsOptionsScreenMixin.java @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2020 - 2024 Legacy Fabric + * Copyright (c) 2016 - 2022 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.legacyfabric.fabric.mixin.client.keybinding; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyArg; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.options.ControlsOptionsScreen; +import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.gui.widget.OptionButtonWidget; +import net.minecraft.client.option.GameOptions; + +import net.legacyfabric.fabric.impl.client.keybinding.ControlsScreenExtensions; +import net.legacyfabric.fabric.impl.client.keybinding.FabricControlsScreenComponents; + +@Mixin(ControlsOptionsScreen.class) +public class ControlsOptionsScreenMixin extends Screen implements ControlsScreenExtensions { + @Shadow + private GameOptions options; + + private static int fabric_currentPage = 0; + + private int fabric_getPageOffset(int page) { + switch (page) { + case 0: + return 0; + case 1: + return FabricControlsScreenComponents.AMOUNT_PER_PAGE; + default: + return FabricControlsScreenComponents.AMOUNT_PER_PAGE + ((page - 1) * FabricControlsScreenComponents.AMOUNT_PER_PAGE); + } + } + + private int fabric_getOffsetPage(int offset) { + if (offset < FabricControlsScreenComponents.AMOUNT_PER_PAGE) { + return 0; + } else { + return 1 + ((offset - FabricControlsScreenComponents.AMOUNT_PER_PAGE) / FabricControlsScreenComponents.AMOUNT_PER_PAGE); + } + } + + @Override + public boolean fabric_isButtonVisible(FabricControlsScreenComponents.Type type) { + return this.options.allKeys.length > FabricControlsScreenComponents.AMOUNT_PER_PAGE; + } + + @Override + public void fabric_nextPage() { + if (fabric_getPageOffset(fabric_currentPage + 1) >= this.options.allKeys.length) { + return; + } + + fabric_currentPage++; + fabric_updateSelection(); + } + + @Override + public void fabric_previousPage() { + if (fabric_currentPage == 0) { + return; + } + + fabric_currentPage--; + fabric_updateSelection(); + } + + @Override + public int fabric_currentPage() { + return fabric_currentPage; + } + + @Override + public boolean fabric_isButtonEnabled(FabricControlsScreenComponents.Type type) { + if (type == FabricControlsScreenComponents.Type.NEXT) { + return !(fabric_getPageOffset(fabric_currentPage + 1) >= this.options.allKeys.length); + } + + if (type == FabricControlsScreenComponents.Type.PREVIOUS) { + return fabric_currentPage != 0; + } + + return false; + } + + @Inject(at = @At("HEAD"), method = "buttonClicked", cancellable = true) + private void interceptClick(ButtonWidget button, CallbackInfo ci) { + if (button instanceof FabricControlsScreenComponents.ControlsButtonWidget) { + ((FabricControlsScreenComponents.ControlsButtonWidget) button).click(); + ci.cancel(); + } + } + + private boolean fabric_isControlVisible(int id) { + return fabric_currentPage == fabric_getOffsetPage(id); + } + + private void fabric_updateSelection() { + for (Object widget : this.buttons) { + if (widget instanceof OptionButtonWidget) { + ((OptionButtonWidget) widget).visible = fabric_isControlVisible(((ButtonWidget) widget).id); + } + } + } + + @ModifyArg(method = "init", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/widget/OptionButtonWidget;(IIIIILjava/lang/String;)V"), index = 2) + private int modifyControlY(int y) { + int temp = y - (this.height / 6); + int heightOffset = temp / 24; + return this.height / 6 + 24 * (heightOffset % 7); + } + + @Inject(method = "init", at = @At("RETURN")) + private void init(CallbackInfo info) { + fabric_updateSelection(); + + buttons.add(new FabricControlsScreenComponents.ControlsButtonWidget(this.width / 2 + 100, this.height / 6 + 168, FabricControlsScreenComponents.Type.NEXT, this)); + buttons.add(new FabricControlsScreenComponents.ControlsButtonWidget(this.width / 2 - 120, this.height / 6 + 168, FabricControlsScreenComponents.Type.PREVIOUS, this)); + } + + @WrapOperation(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/options/ControlsOptionsScreen;drawWithShadow(Lnet/minecraft/client/font/TextRenderer;Ljava/lang/String;III)V")) + private void modifyLabelPos(ControlsOptionsScreen instance, TextRenderer textRenderer, String text, int x, int y, int color, Operation original, @Local(index = 5) int id) { + if (fabric_isControlVisible(id)) { + int temp = y - (this.height / 6); + int heightOffset = temp / 24; + y = this.height / 6 + 24 * (heightOffset % 7) + 7; + original.call(instance, textRenderer, text, x, y, color); + } + } +} diff --git a/legacy-fabric-keybindings-api-v1/1.6.4/src/main/resources/fabric.mod.json b/legacy-fabric-keybindings-api-v1/1.6.4/src/main/resources/fabric.mod.json index 17813b87b..efa1cc138 100644 --- a/legacy-fabric-keybindings-api-v1/1.6.4/src/main/resources/fabric.mod.json +++ b/legacy-fabric-keybindings-api-v1/1.6.4/src/main/resources/fabric.mod.json @@ -18,7 +18,9 @@ "depends": { "minecraft": "${minecraft_version}" }, - "mixins": [], + "mixins": [ + "legacy-fabric-keybinding-api-v1.mixins.json" + ], "description": "Hooks that help adding keybindings", "custom": { "modmenu": { diff --git a/legacy-fabric-keybindings-api-v1/1.6.4/src/main/resources/legacy-fabric-keybinding-api-v1.mixins.json b/legacy-fabric-keybindings-api-v1/1.6.4/src/main/resources/legacy-fabric-keybinding-api-v1.mixins.json new file mode 100644 index 000000000..b8771d39c --- /dev/null +++ b/legacy-fabric-keybindings-api-v1/1.6.4/src/main/resources/legacy-fabric-keybinding-api-v1.mixins.json @@ -0,0 +1,11 @@ +{ + "required": true, + "package": "net.legacyfabric.fabric.mixin.client.keybinding", + "compatibilityLevel": "JAVA_8", + "client": [ + "ControlsOptionsScreenMixin" + ], + "injectors": { + "defaultRequire": 1 + } +}