From 2048a094777b7cb2f5c23c8217757f45be6db49f Mon Sep 17 00:00:00 2001 From: isXander Date: Fri, 28 Jul 2023 23:40:33 +0100 Subject: [PATCH] Only allow handpicked bindings for radial menu (and all modded binds) with hand-picked icons for all. --- .../api/bind/ControllerBinding.java | 4 ++++ .../api/bind/ControllerBindingBuilder.java | 7 +++--- .../bindings/ControllerBindingImpl.java | 23 ++++++++++++++----- .../bindings/ControllerBindings.java | 14 +++++++++++ .../controlify/bindings/RadialAction.java | 11 --------- .../controlify/bindings/RadialIcons.java | 20 ++++++++++++---- .../controller/ControllerConfig.java | 19 ++++++++------- .../gui/screen/RadialMenuScreen.java | 23 ++++++++++--------- 8 files changed, 75 insertions(+), 46 deletions(-) delete mode 100644 src/main/java/dev/isxander/controlify/bindings/RadialAction.java diff --git a/src/main/java/dev/isxander/controlify/api/bind/ControllerBinding.java b/src/main/java/dev/isxander/controlify/api/bind/ControllerBinding.java index 1167344..ec165a3 100644 --- a/src/main/java/dev/isxander/controlify/api/bind/ControllerBinding.java +++ b/src/main/java/dev/isxander/controlify/api/bind/ControllerBinding.java @@ -3,12 +3,14 @@ package dev.isxander.controlify.api.bind; import com.google.gson.JsonObject; import dev.isxander.controlify.bindings.BindContext; import dev.isxander.controlify.bindings.IBind; +import dev.isxander.controlify.bindings.RadialIcons; import dev.isxander.yacl3.api.Option; import net.minecraft.client.KeyMapping; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.Nullable; +import java.util.Optional; import java.util.Set; import java.util.function.BooleanSupplier; @@ -70,6 +72,8 @@ public interface ControllerBinding { void tick(); + Optional radialIcon(); + record KeyMappingOverride(KeyMapping keyMapping, BooleanSupplier toggleable) { } } diff --git a/src/main/java/dev/isxander/controlify/api/bind/ControllerBindingBuilder.java b/src/main/java/dev/isxander/controlify/api/bind/ControllerBindingBuilder.java index a1f24c0..91e9152 100644 --- a/src/main/java/dev/isxander/controlify/api/bind/ControllerBindingBuilder.java +++ b/src/main/java/dev/isxander/controlify/api/bind/ControllerBindingBuilder.java @@ -1,9 +1,6 @@ package dev.isxander.controlify.api.bind; -import dev.isxander.controlify.bindings.BindContext; -import dev.isxander.controlify.bindings.ControllerBindingImpl; -import dev.isxander.controlify.bindings.GamepadBinds; -import dev.isxander.controlify.bindings.IBind; +import dev.isxander.controlify.bindings.*; import dev.isxander.controlify.controller.Controller; import dev.isxander.controlify.controller.ControllerState; import net.minecraft.client.KeyMapping; @@ -76,6 +73,8 @@ public interface ControllerBindingBuilder { ControllerBindingBuilder context(BindContext... contexts); + ControllerBindingBuilder radialCandidate(ResourceLocation icon); + /** * Specifies are vanilla override for the binding. * Will emulate presses of the vanilla keybind when the controller binding is pressed. diff --git a/src/main/java/dev/isxander/controlify/bindings/ControllerBindingImpl.java b/src/main/java/dev/isxander/controlify/bindings/ControllerBindingImpl.java index 5048a94..730dcbc 100644 --- a/src/main/java/dev/isxander/controlify/bindings/ControllerBindingImpl.java +++ b/src/main/java/dev/isxander/controlify/bindings/ControllerBindingImpl.java @@ -25,10 +25,7 @@ import net.minecraft.resources.ResourceLocation; import org.apache.commons.lang3.Validate; import org.jetbrains.annotations.ApiStatus; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.function.BooleanSupplier; public class ControllerBindingImpl implements ControllerBinding { @@ -39,13 +36,14 @@ public class ControllerBindingImpl implements Control private final ResourceLocation id; private final Component name, description, category; private final Set contexts; + private final ResourceLocation radialIcon; private final KeyMappingOverride override; private static final Map, Set>> pressedBinds = new HashMap<>(); private int fakePressState = 0; - private ControllerBindingImpl(Controller controller, IBind defaultBind, ResourceLocation id, KeyMappingOverride vanillaOverride, Component name, Component description, Component category, Set contexts) { + private ControllerBindingImpl(Controller controller, IBind defaultBind, ResourceLocation id, KeyMappingOverride vanillaOverride, Component name, Component description, Component category, Set contexts, ResourceLocation icon) { this.controller = controller; this.bind = this.defaultBind = defaultBind; this.renderer = new BindRendererImpl(bind); @@ -55,6 +53,7 @@ public class ControllerBindingImpl implements Control this.description = description; this.category = category; this.contexts = ImmutableSet.copyOf(contexts); + this.radialIcon = icon; } @Override @@ -118,6 +117,11 @@ public class ControllerBindingImpl implements Control fakePressState = 0; } + @Override + public Optional radialIcon() { + return Optional.ofNullable(this.radialIcon); + } + public IBind currentBind() { return bind; } @@ -233,6 +237,7 @@ public class ControllerBindingImpl implements Control private Component name = null, description = null, category = null; private KeyMappingOverride override = null; private final Set contexts = new HashSet<>(); + private ResourceLocation radialIcon = null; public ControllerBindingBuilderImpl(Controller controller) { this.controller = controller; @@ -290,6 +295,12 @@ public class ControllerBindingImpl implements Control return this; } + @Override + public ControllerBindingBuilder radialCandidate(ResourceLocation icon) { + this.radialIcon = icon; + return this; + } + @Override public ControllerBindingBuilder vanillaOverride(KeyMapping keyMapping, BooleanSupplier toggleable) { this.override = new KeyMappingOverride(keyMapping, toggleable); @@ -318,7 +329,7 @@ public class ControllerBindingImpl implements Control } } - return new ControllerBindingImpl<>(controller, bind, id, override, name, description, category, contexts); + return new ControllerBindingImpl<>(controller, bind, id, override, name, description, category, contexts, radialIcon); } } diff --git a/src/main/java/dev/isxander/controlify/bindings/ControllerBindings.java b/src/main/java/dev/isxander/controlify/bindings/ControllerBindings.java index 6e02b4c..0767292 100644 --- a/src/main/java/dev/isxander/controlify/bindings/ControllerBindings.java +++ b/src/main/java/dev/isxander/controlify/bindings/ControllerBindings.java @@ -20,6 +20,8 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.ToggleKeyMapping; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.item.Items; import java.util.*; import java.util.function.BooleanSupplier; @@ -140,6 +142,7 @@ public class ControllerBindings { .defaultBind(GamepadBinds.A_BUTTON) .category(MOVEMENT_CATEGORY) .context(BindContexts.INGAME) + .radialCandidate(RadialIcons.getEffect(MobEffects.JUMP)) .build()); register(SPRINT = ControllerBindingBuilder.create(controller) .identifier("controlify", "sprint") @@ -173,12 +176,14 @@ public class ControllerBindings { .defaultBind(GamepadBinds.DPAD_DOWN) .category(GAMEPLAY_CATEGORY) .context(BindContexts.INGAME, BindContexts.INVENTORY) + .radialCandidate(RadialIcons.getItem(Items.BARRIER)) .build()); register(DROP_STACK = ControllerBindingBuilder.create(controller) .identifier("controlify", "drop_stack") .defaultBind(new EmptyBind<>()) .category(GAMEPLAY_CATEGORY) .context(BindContexts.INGAME) + .radialCandidate(RadialIcons.getItem(Items.TNT)) .build()); register(NEXT_SLOT = ControllerBindingBuilder.create(controller) .identifier("controlify", "next_slot") @@ -197,30 +202,35 @@ public class ControllerBindings { .defaultBind(GamepadBinds.START) .category(GAMEPLAY_CATEGORY) .context(BindContexts.INGAME) + .radialCandidate(RadialIcons.getItem(Items.STRUCTURE_VOID)) .build()); register(INVENTORY = ControllerBindingBuilder.create(controller) .identifier("controlify", "inventory") .defaultBind(GamepadBinds.Y_BUTTON) .category(INVENTORY_CATEGORY) .context(BindContexts.INGAME) + .radialCandidate(RadialIcons.getItem(Items.CHEST)) .build()); register(CHANGE_PERSPECTIVE = ControllerBindingBuilder.create(controller) .identifier("controlify", "change_perspective") .defaultBind(GamepadBinds.BACK) .category(GAMEPLAY_CATEGORY) .context(BindContexts.INGAME) + .radialCandidate(RadialIcons.getItem(Items.PAINTING)) .build()); register(SWAP_HANDS = ControllerBindingBuilder.create(controller) .identifier("controlify", "swap_hands") .defaultBind(GamepadBinds.X_BUTTON) .category(INVENTORY_CATEGORY) .context(BindContexts.INGAME, BindContexts.INVENTORY) + .radialCandidate(RadialIcons.getItem(Items.BONE)) .build()); register(OPEN_CHAT = ControllerBindingBuilder.create(controller) .identifier("controlify", "open_chat") .defaultBind(GamepadBinds.DPAD_UP) .category(MISC_CATEGORY) .context(BindContexts.INGAME) + .radialCandidate(RadialIcons.getItem(Items.WRITABLE_BOOK)) .vanillaOverride(options.keyChat, () -> false) .build()); register(GUI_PRESS = ControllerBindingBuilder.create(controller) @@ -282,6 +292,7 @@ public class ControllerBindings { .defaultBind(GamepadBinds.DPAD_LEFT) .category(GAMEPLAY_CATEGORY) .context(BindContexts.INGAME) + .radialCandidate(RadialIcons.getItem(Items.STICK)) .vanillaOverride(options.keyPickItem, () -> false) .build()); register(TOGGLE_HUD_VISIBILITY = ControllerBindingBuilder.create(controller) @@ -289,12 +300,14 @@ public class ControllerBindings { .defaultBind(new EmptyBind<>()) .category(MISC_CATEGORY) .context(BindContexts.INGAME) + .radialCandidate(RadialIcons.getEffect(MobEffects.INVISIBILITY)) .build()); register(SHOW_PLAYER_LIST = ControllerBindingBuilder.create(controller) .identifier("controlify", "show_player_list") .defaultBind(GamepadBinds.DPAD_RIGHT) .category(MISC_CATEGORY) .context(BindContexts.INGAME) + .radialCandidate(RadialIcons.getItem(Items.PLAYER_HEAD)) .build()); register(RADIAL_MENU = ControllerBindingBuilder.create(controller) .identifier("controlify", "radial_menu") @@ -520,6 +533,7 @@ public class ControllerBindings { .name(Component.translatable(keyMapping.getName())) .description(Component.translatable("controlify.custom_binding.vanilla_description").withStyle(ChatFormatting.GRAY)) .category(Component.translatable(keyMapping.getCategory())) + .radialCandidate(RadialIcons.FABRIC_ICON) .vanillaOverride(keyMapping, toggleOverride) .build(); diff --git a/src/main/java/dev/isxander/controlify/bindings/RadialAction.java b/src/main/java/dev/isxander/controlify/bindings/RadialAction.java deleted file mode 100644 index b2484e8..0000000 --- a/src/main/java/dev/isxander/controlify/bindings/RadialAction.java +++ /dev/null @@ -1,11 +0,0 @@ -package dev.isxander.controlify.bindings; - -import dev.isxander.controlify.gui.screen.RadialMenuScreen; -import net.minecraft.resources.ResourceLocation; - -public record RadialAction(ResourceLocation binding, ResourceLocation icon) { - public static final RadialAction EMPTY = new RadialAction( - RadialMenuScreen.EMPTY_ACTION, - RadialIcons.EMPTY - ); -} diff --git a/src/main/java/dev/isxander/controlify/bindings/RadialIcons.java b/src/main/java/dev/isxander/controlify/bindings/RadialIcons.java index b5898ec..a8f65ed 100644 --- a/src/main/java/dev/isxander/controlify/bindings/RadialIcons.java +++ b/src/main/java/dev/isxander/controlify/bindings/RadialIcons.java @@ -5,15 +5,11 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.resources.MobEffectTextureManager; -import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.effect.MobEffect; -import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.effect.MobEffects; import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.item.ItemStack; import java.util.HashMap; @@ -23,11 +19,19 @@ public final class RadialIcons { private static final Minecraft minecraft = Minecraft.getInstance(); public static final ResourceLocation EMPTY = new ResourceLocation("controlify", "empty"); + public static final ResourceLocation FABRIC_ICON = new ResourceLocation("fabricloader", "icon"); private static final Map icons = Util.make(() -> { Map map = new HashMap<>(); map.put(EMPTY, (graphics, x, y) -> {}); + map.put(FABRIC_ICON, ((graphics, x, y) -> { + graphics.pose().pushPose(); + graphics.pose().translate(x, y, 0); + graphics.pose().scale(0.5f, 0.5f, 1f); + graphics.blit(FABRIC_ICON, 0, 0, 0, 0, 32, 32); + graphics.pose().popPose(); + })); addItems(map); addPotionEffects(map); @@ -38,6 +42,14 @@ public final class RadialIcons { return icons; } + public static ResourceLocation getItem(Item item) { + return prefixLocation("item", BuiltInRegistries.ITEM.getKey(item)); + } + + public static ResourceLocation getEffect(MobEffect effect) { + return prefixLocation("effect", BuiltInRegistries.MOB_EFFECT.getKey(effect)); + } + private static void addItems(Map map) { BuiltInRegistries.ITEM.entrySet().forEach(entry -> { ResourceKey key = entry.getKey(); diff --git a/src/main/java/dev/isxander/controlify/controller/ControllerConfig.java b/src/main/java/dev/isxander/controlify/controller/ControllerConfig.java index 914b0f3..6ddba16 100644 --- a/src/main/java/dev/isxander/controlify/controller/ControllerConfig.java +++ b/src/main/java/dev/isxander/controlify/controller/ControllerConfig.java @@ -2,7 +2,6 @@ package dev.isxander.controlify.controller; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; -import dev.isxander.controlify.bindings.RadialAction; import dev.isxander.controlify.gui.screen.RadialMenuScreen; import dev.isxander.controlify.rumble.RumbleSource; import net.minecraft.resources.ResourceLocation; @@ -39,15 +38,15 @@ public abstract class ControllerConfig implements Serializable { public boolean mixedInput = false; - public RadialAction[] radialActions = new RadialAction[]{ - RadialAction.EMPTY, - RadialAction.EMPTY, - RadialAction.EMPTY, - RadialAction.EMPTY, - RadialAction.EMPTY, - RadialAction.EMPTY, - RadialAction.EMPTY, - RadialAction.EMPTY, + public ResourceLocation[] radialActions = new ResourceLocation[]{ + RadialMenuScreen.EMPTY_ACTION, + RadialMenuScreen.EMPTY_ACTION, + RadialMenuScreen.EMPTY_ACTION, + RadialMenuScreen.EMPTY_ACTION, + RadialMenuScreen.EMPTY_ACTION, + RadialMenuScreen.EMPTY_ACTION, + RadialMenuScreen.EMPTY_ACTION, + RadialMenuScreen.EMPTY_ACTION, }; public abstract void setDeadzone(int axis, float deadzone); diff --git a/src/main/java/dev/isxander/controlify/gui/screen/RadialMenuScreen.java b/src/main/java/dev/isxander/controlify/gui/screen/RadialMenuScreen.java index e10d882..aafb03d 100644 --- a/src/main/java/dev/isxander/controlify/gui/screen/RadialMenuScreen.java +++ b/src/main/java/dev/isxander/controlify/gui/screen/RadialMenuScreen.java @@ -2,7 +2,6 @@ package dev.isxander.controlify.gui.screen; import dev.isxander.controlify.Controlify; import dev.isxander.controlify.api.bind.ControllerBinding; -import dev.isxander.controlify.bindings.RadialAction; import dev.isxander.controlify.bindings.RadialIcons; import dev.isxander.controlify.controller.Controller; import dev.isxander.controlify.controller.gamepad.GamepadState; @@ -36,6 +35,7 @@ import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Optional; public class RadialMenuScreen extends Screen implements ScreenControllerEventListener { @@ -188,15 +188,16 @@ public class RadialMenuScreen extends Screen implements ScreenControllerEventLis this.x = x; this.y = y; - RadialAction action = controller.config().radialActions[index]; - if (!EMPTY_ACTION.equals(action.binding())) { - this.binding = controller.bindings().get(action.binding()); + ResourceLocation binding = controller.config().radialActions[index]; + if (!EMPTY_ACTION.equals(binding)) { + this.binding = controller.bindings().get(binding); + this.icon = RadialIcons.getIcons().get(this.binding.radialIcon().orElseThrow()); this.name = MultiLineLabel.create(font, this.binding.name(), 76); } else { this.binding = null; this.name = MultiLineLabel.EMPTY; + this.icon = RadialIcons.getIcons().get(RadialIcons.EMPTY); } - this.icon = RadialIcons.getIcons().get(action.icon()); } @Override @@ -305,11 +306,12 @@ public class RadialMenuScreen extends Screen implements ScreenControllerEventLis this.width = width; this.height = height; - controller.bindings().registry().forEach((id, binding) -> { - children.add(new ActionEntry(id)); - }); + controller.bindings().registry().entrySet().stream() + .filter(entry -> entry.getValue().radialIcon().isPresent()) + .map(Map.Entry::getKey) + .forEach(id -> children.add(new ActionEntry(id))); - var selectedBind = controller.config().radialActions[radialIndex].binding(); + var selectedBind = controller.config().radialActions[radialIndex]; children.stream() .filter(action -> action.binding.equals(selectedBind)) .findAny() @@ -447,8 +449,7 @@ public class RadialMenuScreen extends Screen implements ScreenControllerEventLis public boolean overrideControllerButtons(ScreenProcessor screen, Controller controller) { if (controller == RadialMenuScreen.this.controller) { if (controller.bindings().GUI_PRESS.justPressed()) { - var icon = RadialIcons.getIcons().keySet().toArray(new ResourceLocation[0])[minecraft.level.random.nextInt(RadialIcons.getIcons().size())]; - controller.config().radialActions[radialIndex] = new RadialAction(binding, icon); + controller.config().radialActions[radialIndex] = binding; Controlify.instance().config().setDirty(); playClickSound();