Added sticky keys option. Fixes #322

This commit is contained in:
Sollace 2024-04-08 22:13:08 +01:00
parent 4cb06bcc92
commit a8f0796ad7
No known key found for this signature in database
GPG key ID: E52FACE7B5C773DB
9 changed files with 117 additions and 62 deletions

View file

@ -34,6 +34,9 @@ public class Config extends com.minelittlepony.common.util.settings.Config {
.addComment("If true Mine Little Pony will not be considered when determining the race to use")
.addComment("The result will always be what is set by this config file.");
public final Setting<Boolean> toggleAbilityKeys = value("client", "toggleAbilityKeys", false)
.addComment("If true the ability keybinds will function as toggle keys rather than hold keys");
public final Setting<Integer> hudPage = value("client", "hudActivePage", 0)
.addComment("The page of abilities currently visible in the HUD. You can change this in-game using the PG_UP and PG_DWN keys (configurable)");

View file

@ -73,7 +73,7 @@ public record Race (
.abilities(Abilities.HUG, Abilities.STOMP, Abilities.KICK, Abilities.GROW)
);
public static final Race UNICORN = register("unicorn", new Builder().foraging().magic()
.abilities(Abilities.TELEPORT, Abilities.GROUP_TELEPORT, Abilities.SHOOT, Abilities.DISPELL)
.abilities(Abilities.TELEPORT, Abilities.CAST, Abilities.GROUP_TELEPORT, Abilities.SHOOT, Abilities.DISPELL)
);
public static final Race PEGASUS = register("pegasus", new Builder().foraging().flight(FlightType.AVIAN).weatherMagic().cloudMagic()
.abilities(Abilities.TOGGLE_FLIGHT, Abilities.RAINBOOM, Abilities.CAPTURE_CLOUD, Abilities.CARRY)
@ -83,7 +83,7 @@ public record Race (
);
public static final Race ALICORN = register("alicorn", new Builder().foraging().availability(Availability.COMMANDS).flight(FlightType.AVIAN).earth().magic().weatherMagic().cloudMagic()
.abilities(
Abilities.TELEPORT, Abilities.GROUP_TELEPORT, Abilities.SHOOT, Abilities.DISPELL,
Abilities.TELEPORT, Abilities.GROUP_TELEPORT, Abilities.CAST, Abilities.SHOOT, Abilities.DISPELL,
Abilities.TOGGLE_FLIGHT, Abilities.RAINBOOM, Abilities.CAPTURE_CLOUD, Abilities.CARRY,
Abilities.HUG, Abilities.STOMP, Abilities.KICK, Abilities.GROW,
Abilities.TIME

View file

@ -18,7 +18,9 @@ import com.minelittlepony.unicopia.entity.player.Pony;
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.option.KeyBinding;
import net.minecraft.client.option.StickyKeyBinding;
import net.minecraft.client.sound.PositionedSoundInstance;
import net.minecraft.client.util.InputUtil;
import net.minecraft.text.Text;
import net.minecraft.util.math.MathHelper;
@ -35,6 +37,10 @@ public class KeyBindingsHandler {
private final Binding pageDown = register(GLFW.GLFW_KEY_PAGE_DOWN, "hud_page_dn");
private final Binding pageUp = register(GLFW.GLFW_KEY_PAGE_UP, "hud_page_up");
private final Binding singleTapModifier = register(InputUtil.UNKNOWN_KEY.getCode(), "ability_modifier_tap");
private final Binding doubleTapModifier = register(InputUtil.UNKNOWN_KEY.getCode(), "ability_modifier_double_tap");
private final Binding tripleTapModifier = register(InputUtil.UNKNOWN_KEY.getCode(), "ability_modifier_triple_tap");
private final Set<KeyBinding> pressed = new HashSet<>();
public KeyBindingsHandler() {
@ -47,8 +53,12 @@ public class KeyBindingsHandler {
return reverse.get(slot);
}
public boolean isToggleMode() {
return Unicopia.getConfig().toggleAbilityKeys.get();
}
public void addKeybind(int code, AbilitySlot slot) {
Binding binding = register(code, slot.name().toLowerCase());
Binding binding = new Binding(KeyBindingHelper.registerKeyBinding(new StickyKeyBinding("key.unicopia." + slot.name().toLowerCase(), code, KEY_CATEGORY, this::isToggleMode)));
reverse.put(slot, binding);
keys.put(binding, slot);
}
@ -104,6 +114,7 @@ public class KeyBindingsHandler {
int page = Unicopia.getConfig().hudPage.get();
page += sigma;
Unicopia.getConfig().hudPage.set(page);
Unicopia.getConfig().save();
client.getSoundManager().play(PositionedSoundInstance.master(USounds.Vanilla.UI_BUTTON_CLICK, 1.75F + (0.25F * sigma)));
UHud.INSTANCE.setMessage(Text.translatable("gui.unicopia.page_num", page + 1, max + 1));
}
@ -141,6 +152,27 @@ public class KeyBindingsHandler {
}
public ActivationType getType() {
if (binding.isPressed() && binding instanceof StickyKeyBinding) {
if (singleTapModifier.binding.isPressed()) {
KeyBinding.untoggleStickyKeys();
return ActivationType.TAP;
}
if (doubleTapModifier.binding.isPressed()) {
KeyBinding.untoggleStickyKeys();
return ActivationType.DOUBLE_TAP;
}
if (tripleTapModifier.binding.isPressed()) {
KeyBinding.untoggleStickyKeys();
return ActivationType.TRIPLE_TAP;
}
if (isToggleMode()) {
return ActivationType.NONE;
}
}
long now = System.currentTimeMillis();
if (type != ActivationType.NONE && now > nextPhaseTime - 70) {
ActivationType t = type;

View file

@ -68,6 +68,10 @@ public class SettingsScreen extends GameGui {
})
.getStyle().setText("unicopia.options.ignore_mine_lp");
content.addButton(new Toggle(LEFT, row += 20, config.toggleAbilityKeys.get()))
.onChange(config.toggleAbilityKeys)
.getStyle().setText("unicopia.options.toggle_ability_keys");
mineLpStatus = content.addButton(new Label(LEFT, row += 10)).getStyle().setText(getMineLPStatus());
RegistryIndexer<Race> races = RegistryIndexer.of(Race.REGISTRY);

View file

@ -1,5 +1,6 @@
package com.minelittlepony.unicopia.client.gui;
import com.minelittlepony.unicopia.Unicopia;
import com.minelittlepony.unicopia.ability.AbilityDispatcher;
import com.minelittlepony.unicopia.ability.AbilitySlot;
import com.minelittlepony.unicopia.client.KeyBindingsHandler;
@ -82,6 +83,12 @@ class Slot {
bSwap &= abilities.isFilled(bSlot);
}
AbilityDispatcher.Stat stat = abilities.getStat(bSwap ? bSlot : aSlot);
if (stat.getAbility(Unicopia.getConfig().hudPage.get()).isEmpty()) {
return;
}
RenderSystem.setShaderColor(1, 1, 1, 1);
RenderSystem.enableBlend();
MatrixStack matrices = context.getMatrices();
@ -91,7 +98,7 @@ class Slot {
// background
context.drawTexture(UHud.HUD_TEXTURE, 0, 0, backgroundU, backgroundV, size, size, 128, 128);
AbilityDispatcher.Stat stat = abilities.getStat(bSwap ? bSlot : aSlot);
int iconPosition = ((size - iconSize + slotPadding + 1) / 2);
int sz = iconSize - slotPadding;
@ -122,6 +129,11 @@ class Slot {
}
void renderLabel(DrawContext context, AbilityDispatcher abilities, float tickDelta) {
if (abilities.getStat(aSlot).getAbility(Unicopia.getConfig().hudPage.get()).isEmpty()) {
return;
}
Text label = KeyBindingsHandler.INSTANCE.getBinding(aSlot).getLabel();
MatrixStack matrices = context.getMatrices();

View file

@ -48,8 +48,8 @@ public class UHud {
private final List<Slot> slots = List.of(
new ManaRingSlot(this, AbilitySlot.PRIMARY, AbilitySlot.PASSIVE, 0, 0),
new Slot(this, AbilitySlot.SECONDARY, AbilitySlot.SECONDARY, 26, -5),
new Slot(this, AbilitySlot.TERTIARY, AbilitySlot.TERTIARY, 36, 19)
new Slot(this, AbilitySlot.SECONDARY, AbilitySlot.SECONDARY, 30, -8),
new Slot(this, AbilitySlot.TERTIARY, AbilitySlot.TERTIARY, 40, 18)
);
@Nullable
@ -68,10 +68,6 @@ public class UHud {
private SpellType<?> focusedType = SpellType.empty();
public void render(InGameHud hud, DrawContext context, float tickDelta) {
// TODO: Check this when backporting!
// InGameHud#renderHotbar line 460
// context.getMatrices().translate(0.0f, 0.0f, -90.0f);
final int hotbarZ = -90;
if (client.player == null) {
@ -96,7 +92,6 @@ public class UHud {
font = client.textRenderer;
xDirection = client.player.getMainArm() == Arm.LEFT ? -1 : 1;
matrices.push();
matrices.translate(scaledWidth / 2, scaledHeight / 2, 0);
@ -109,7 +104,7 @@ public class UHud {
matrices.pop();
matrices.push();
int hudX = ((scaledWidth - 50) / 2) + (104 * xDirection);
int hudX = ((scaledWidth - 50) / 2) + (109 * xDirection);
int hudY = scaledHeight - 50;
int hudZ = hotbarZ;
@ -139,33 +134,33 @@ public class UHud {
slots.forEach(slot -> slot.renderBackground(context, abilities, swap, tickDelta));
boolean canCast = Abilities.CAST.canUse(pony.getCompositeRace()) || Abilities.KIRIN_CAST.canUse(pony.getCompositeRace());
Ability<?> ability = pony.getAbilities().getStat(AbilitySlot.PRIMARY)
.getAbility(Unicopia.getConfig().hudPage.get())
.orElse(null);
boolean canCast = ability == Abilities.CAST || ability == Abilities.KIRIN_CAST || ability == Abilities.SHOOT;
if (canCast) {
Ability<?> ability = pony.getAbilities().getStat(AbilitySlot.PRIMARY)
.getAbility(Unicopia.getConfig().hudPage.get())
.orElse(null);
if (ability == Abilities.CAST || ability == Abilities.SHOOT) {
matrices.push();
matrices.translate(PRIMARY_SLOT_SIZE / 2F, PRIMARY_SLOT_SIZE / 2F, 0);
boolean first = !pony.asEntity().isSneaking();
TypedActionResult<CustomisedSpellType<?>> inHand = pony.getCharms().getSpellInHand(false);
boolean replacing = inHand.getResult().isAccepted() && pony.getAbilities().getStat(AbilitySlot.PRIMARY).getActiveAbility().isEmpty();
if (first != prevPointed || replacing != prevReplacing || inHand.getValue().type() != focusedType) {
focusedType = inHand.getValue().type();
prevPointed = first;
prevReplacing = replacing;
setMessage(ability.getName(pony));
}
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(first ? 37 : 63));
matrices.translate(-23, 0, 0);
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(-26));
matrices.scale(0.8F, 0.8F, 1);
int u = replacing ? 16 : 3;
context.drawTexture(HUD_TEXTURE, 0, 0, u, 120, 13, 7, 128, 128);
matrices.pop();
matrices.push();
matrices.translate(PRIMARY_SLOT_SIZE / 2F, PRIMARY_SLOT_SIZE / 2F, 0);
boolean first = !pony.asEntity().isSneaking();
TypedActionResult<CustomisedSpellType<?>> inHand = pony.getCharms().getSpellInHand(false);
boolean replacing = inHand.getResult().isAccepted() && pony.getAbilities().getStat(AbilitySlot.PRIMARY).getActiveAbility().isEmpty();
if (first != prevPointed || replacing != prevReplacing || inHand.getValue().type() != focusedType) {
focusedType = inHand.getValue().type();
prevPointed = first;
prevReplacing = replacing;
setMessage(ability.getName(pony));
}
int baseAngle = xDirection < 0 ? 100 : 0;
int secondAngleDif = xDirection * 30;
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(baseAngle + 37 + (first ? 0 : secondAngleDif)));
matrices.translate(-23, 0, 0);
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(-26));
matrices.scale(0.8F, 0.8F, 1);
int u = replacing ? 16 : 3;
context.drawTexture(HUD_TEXTURE, 0, 0, u, 120, 13, 7, 128, 128);
matrices.pop();
}
slots.forEach(slot -> slot.renderLabel(context, abilities, tickDelta));
@ -173,8 +168,13 @@ public class UHud {
matrices.pop();
if (canCast) {
matrices.push();
if (xDirection < 0) {
hudX += PRIMARY_SLOT_SIZE / 2F - 8;
}
SpellIconRenderer.renderSpell(context, pony.getCharms().getEquippedSpell(Hand.MAIN_HAND), hudX + 10 - xDirection * 13, hudY + 2, EQUIPPED_GEMSTONE_SCALE);
SpellIconRenderer.renderSpell(context, pony.getCharms().getEquippedSpell(Hand.OFF_HAND), hudX + 8 - xDirection * 2, hudY - 6, EQUIPPED_GEMSTONE_SCALE);
matrices.pop();
}
RenderSystem.disableBlend();

View file

@ -11,7 +11,6 @@ import java.util.stream.Collectors;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.UTags;
import com.minelittlepony.unicopia.Unicopia;
import com.minelittlepony.unicopia.item.ButterflyItem;
import com.minelittlepony.unicopia.util.NbtSerialisable;
@ -74,7 +73,7 @@ public class ButterflyEntity extends AmbientEntity {
}
public static boolean canSpawn(EntityType<? extends ButterflyEntity> type, WorldAccess world, SpawnReason spawnReason, BlockPos pos, Random random) {
return world.getBlockState(pos.down()).isIn(UTags.Blocks.BUTTERFLIES_SPAWNABLE_ON);
return true;//world.getBlockState(pos.down()).isIn(UTags.Blocks.BUTTERFLIES_SPAWNABLE_ON);
}
@Override

View file

@ -26,7 +26,8 @@ import net.minecraft.world.Heightmap.Type;
public interface UEntities {
EntityType<ButterflyEntity> BUTTERFLY = register("butterfly", FabricEntityTypeBuilder.createMob().spawnGroup(SpawnGroup.AMBIENT).entityFactory(ButterflyEntity::new)
.spawnRestriction(Location.NO_RESTRICTIONS, Type.WORLD_SURFACE_WG, ButterflyEntity::canSpawn)
.spawnRestriction(Location.NO_RESTRICTIONS, Type.MOTION_BLOCKING_NO_LEAVES, ButterflyEntity::canSpawn)
.spawnableFarFromPlayer()
.dimensions(EntityDimensions.fixed(0.25F, 0.25F)));
EntityType<MagicProjectileEntity> THROWN_ITEM = register("thrown_item", FabricEntityTypeBuilder.<MagicProjectileEntity>create(SpawnGroup.MISC, MagicProjectileEntity::new)
.trackRangeBlocks(100)
@ -83,7 +84,7 @@ public interface UEntities {
.trackRangeChunks(8)
.dimensions(EntityDimensions.fixed(3, 2)));
EntityType<SpecterEntity> SPECTER = register("specter", FabricEntityTypeBuilder.createMob().spawnGroup(SpawnGroup.MONSTER).entityFactory(SpecterEntity::new)
.spawnRestriction(Location.ON_GROUND, Type.WORLD_SURFACE, HostileEntity::canSpawnInDark)
.spawnRestriction(Location.ON_GROUND, Type.MOTION_BLOCKING_NO_LEAVES, HostileEntity::canSpawnIgnoreLightLevel)
.fireImmune()
.spawnableFarFromPlayer()
.dimensions(EntityDimensions.fixed(1, 2)));

View file

@ -1329,6 +1329,9 @@
"key.unicopia.secondary": "Secondary Ability",
"key.unicopia.tertiary": "Tertiary Ability",
"key.unicopia.passive": "Passive Ability",
"key.unicopia.ability_modifier_tap": "VR Ability Modifier (1-TAP)",
"key.unicopia.ability_modifier_double_tap": "VR Ability Modifier (2-TAP)",
"key.unicopia.ability_modifier_triple_tap": "VR Ability Modifier (3-TAP)",
"key.unicopia.hud_page_dn": "Hud Previous Page",
"key.unicopia.hud_page_up": "Hud Next Page",
@ -1408,6 +1411,7 @@
"commands.gravity.set.multiple": "Updated %s entities",
"unicopia.options.title": "Unicopia Options",
"unicopia.options.toggle_ability_keys": "Sticky Ability Keys",
"unicopia.options.ignore_mine_lp": "Ignore Mine Little Pony",
"unicopia.options.ignore_mine_lp.missing": "* Mine Little Pony is not installed",
"unicopia.options.ignore_mine_lp.detected": "* Your detected race is %s",
@ -1427,28 +1431,28 @@
"command.unicopia.config.list": "[Config] Property (%s) contains (%s) entries: ",
"command.unicopia.config.clear": "[Config] Cleared all values from property %s",
"unicopia.race.unset": "Unset",
"unicopia.race.unset.alt": "Unset",
"unicopia.race.human": "Human",
"unicopia.race.human.alt": "Humans",
"unicopia.race.earth": "Earth Pony",
"unicopia.race.earth.alt": "Earth Ponies",
"unicopia.race.unicorn": "Unicorn",
"unicopia.race.unicorn.alt": "Unicorns",
"unicopia.race.pegasus": "Pegasus",
"unicopia.race.pegasus.alt": "Pegasi",
"unicopia.race.alicorn": "Alicorn",
"unicopia.race.alicorn.alt": "Alicorns",
"unicopia.race.changeling": "Changeling",
"unicopia.race.changeling.alt": "Changelings",
"unicopia.race.bat": "Bat Pony",
"unicopia.race.bat.alt": "Bat Ponies",
"unicopia.race.kirin": "Kirin",
"unicopia.race.kirin.alt": "Kirins",
"unicopia.race.hippogriff": "Hippogriff",
"unicopia.race.hippogriff.alt": "Hippogriffs",
"unicopia.race.seapony": "Sea Pony",
"unicopia.race.seapony.alt": "Sea Ponies",
"race.unicopia.unset": "Unset",
"race.unicopia.unset.alt": "Unset",
"race.unicopia.human": "Human",
"race.unicopia.human.alt": "Humans",
"race.unicopia.earth": "Earth Pony",
"race.unicopia.earth.alt": "Earth Ponies",
"race.unicopia.unicorn": "Unicorn",
"race.unicopia.unicorn.alt": "Unicorns",
"race.unicopia.pegasus": "Pegasus",
"race.unicopia.pegasus.alt": "Pegasi",
"race.unicopia.alicorn": "Alicorn",
"race.unicopia.alicorn.alt": "Alicorns",
"race.unicopia.changeling": "Changeling",
"race.unicopia.changeling.alt": "Changelings",
"race.unicopia.bat": "Bat Pony",
"race.unicopia.bat.alt": "Bat Ponies",
"race.unicopia.kirin": "Kirin",
"race.unicopia.kirin.alt": "Kirins",
"race.unicopia.hippogriff": "Hippogriff",
"race.unicopia.hippogriff.alt": "Hippogriffs",
"race.unicopia.seapony": "Sea Pony",
"race.unicopia.seapony.alt": "Sea Ponies",
"death.attack.unicopia.generic.and_also": "%1$s and %2$s",
"death.attack.unicopia.generic.whilst_flying": "%1$s whilst flying",