diff --git a/src/main/java/com/minelittlepony/unicopia/ability/AbilityDispatcher.java b/src/main/java/com/minelittlepony/unicopia/ability/AbilityDispatcher.java index 42486e1f..37436dc2 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/AbilityDispatcher.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/AbilityDispatcher.java @@ -5,6 +5,8 @@ import java.util.EnumMap; import java.util.Map; import java.util.Optional; +import javax.annotation.Nullable; + import com.minelittlepony.unicopia.Race; import com.minelittlepony.unicopia.ability.data.Hit; import com.minelittlepony.unicopia.entity.player.Pony; @@ -22,6 +24,10 @@ public class AbilityDispatcher implements Tickable, NbtSerialisable { private final Map stats = new EnumMap<>(AbilitySlot.class); + @Nullable + private Race prevRace; + private long maxPage; + public AbilityDispatcher(Pony player) { this.player = player; } @@ -34,10 +40,10 @@ public class AbilityDispatcher implements Tickable, NbtSerialisable { } } - public void activate(AbilitySlot slot) { + public void activate(AbilitySlot slot, long page) { Stat stat = getStat(slot); if (stat.canSwitchStates()) { - stat.getAbility().ifPresent(stat::setActiveAbility); + stat.getAbility(page).ifPresent(stat::setActiveAbility); } } @@ -45,6 +51,14 @@ public class AbilityDispatcher implements Tickable, NbtSerialisable { return stats.computeIfAbsent(slot, Stat::new); } + public long getMaxPage() { + if (prevRace != player.getSpecies()) { + prevRace = player.getSpecies(); + maxPage = Math.max(0, stats.values().stream().mapToLong(Stat::getMaxPage).reduce(0, Math::max) - 1); + } + return maxPage; + } + @Override public void tick() { stats.values().forEach(Stat::tick); @@ -176,14 +190,23 @@ public class AbilityDispatcher implements Tickable, NbtSerialisable { } } - public Optional> getAbility() { + public Optional> getAbility(long page) { Race race = player.getSpecies(); return Abilities.BY_SLOT.computeIfAbsent(slot, c -> Collections.emptySet()) .stream() .filter(a -> a.canUse(race)) + .skip(page) .findFirst(); } + public long getMaxPage() { + Race race = player.getSpecies(); + return Abilities.BY_SLOT.computeIfAbsent(slot, c -> Collections.emptySet()) + .stream() + .filter(a -> a.canUse(race)) + .count(); + } + protected synchronized void setActiveAbility(Ability power) { if (activeAbility.orElse(null) != power) { triggered = false; diff --git a/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyGrowAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyGrowAbility.java index bb6024a6..2a26d732 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyGrowAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyGrowAbility.java @@ -31,7 +31,7 @@ public class EarthPonyGrowAbility implements Ability { @Override public boolean canUse(Race race) { - return race == Race.EARTH; + return race.canUseEarth(); } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/client/KeyBindingsHandler.java b/src/main/java/com/minelittlepony/unicopia/client/KeyBindingsHandler.java index ce5c2d21..04a413d8 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/KeyBindingsHandler.java +++ b/src/main/java/com/minelittlepony/unicopia/client/KeyBindingsHandler.java @@ -7,15 +7,21 @@ import java.util.Set; import org.lwjgl.glfw.GLFW; +import com.minelittlepony.unicopia.ability.AbilityDispatcher; import com.minelittlepony.unicopia.ability.AbilitySlot; +import com.minelittlepony.unicopia.client.gui.UHud; 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.options.KeyBinding; +import net.minecraft.client.sound.PositionedSoundInstance; +import net.minecraft.sound.SoundEvents; +import net.minecraft.text.LiteralText; +import net.minecraft.util.math.MathHelper; public class KeyBindingsHandler { - private final String KEY_CATEGORY = "unicopia.category.name"; + private static final String KEY_CATEGORY = "unicopia.category.name"; public static final KeyBindingsHandler INSTANCE = new KeyBindingsHandler(); @@ -24,6 +30,11 @@ public class KeyBindingsHandler { private final Map keys = new HashMap<>(); private final Map reverse = new HashMap<>(); + private final KeyBinding pageDown = register(GLFW.GLFW_KEY_PAGE_DOWN, "hud_page_dn"); + private final KeyBinding pageUp = register(GLFW.GLFW_KEY_PAGE_UP, "hud_page_up"); + + public long page = 0; + private final Set pressed = new HashSet<>(); public KeyBindingsHandler() { @@ -37,31 +48,69 @@ public class KeyBindingsHandler { } public void addKeybind(int code, AbilitySlot slot) { - KeyBinding binding = KeyBindingHelper.registerKeyBinding(new KeyBinding("key.unicopia." + slot.name().toLowerCase(), code, KEY_CATEGORY)); + KeyBinding binding = register(code, slot.name().toLowerCase()); reverse.put(slot, binding); keys.put(binding, slot); } + static KeyBinding register(int code, String name) { + return KeyBindingHelper.registerKeyBinding(new KeyBinding("key.unicopia." + name, code, KEY_CATEGORY)); + } + public void tick(MinecraftClient client) { if (client.currentScreen != null || client.player == null) { return; } Pony iplayer = Pony.of(client.player); + AbilityDispatcher abilities = iplayer.getAbilities(); + long maxPage = abilities.getMaxPage(); - for (KeyBinding i : keys.keySet()) { - AbilitySlot slot = keys.get(i); - if (slot == AbilitySlot.PRIMARY && client.options.keySneak.isPressed()) { - slot = AbilitySlot.PASSIVE; - } + page = MathHelper.clamp(page, 0, maxPage); - if (i.isPressed()) { - if (pressed.add(i)) { - iplayer.getAbilities().activate(slot); + if (page > 0 && checkPressed(pageDown) == PressedState.PRESSED) { + changePage(client, maxPage, -1); + } else if (page < maxPage && checkPressed(pageUp) == PressedState.PRESSED) { + changePage(client, maxPage, 1); + } else { + for (KeyBinding i : keys.keySet()) { + AbilitySlot slot = keys.get(i); + if (slot == AbilitySlot.PRIMARY && client.options.keySneak.isPressed()) { + slot = AbilitySlot.PASSIVE; + } + + PressedState state = checkPressed(i); + if (state != PressedState.UNCHANGED) { + if (state == PressedState.PRESSED) { + abilities.activate(slot, page); + } else { + abilities.clear(slot); + } } - } else if (pressed.remove(i)) { - iplayer.getAbilities().clear(slot); } } } + + private void changePage(MinecraftClient client, long max, int sigma) { + page += sigma; + client.getSoundManager().play(PositionedSoundInstance.master(SoundEvents.UI_BUTTON_CLICK, 1.75F + (0.25F * sigma))); + UHud.instance.setMessage(new LiteralText(page + " of " + max)); + } + + private PressedState checkPressed(KeyBinding binding) { + if (binding.isPressed()) { + return pressed.add(binding) ? PressedState.PRESSED : PressedState.UNCHANGED; + } else if (pressed.remove(binding)) { + return PressedState.UNPRESSED; + } + + + return PressedState.UNCHANGED; + } + + enum PressedState { + UNCHANGED, + PRESSED, + UNPRESSED + } } diff --git a/src/main/java/com/minelittlepony/unicopia/client/UnicopiaClient.java b/src/main/java/com/minelittlepony/unicopia/client/UnicopiaClient.java index cd558fad..57ed6052 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/UnicopiaClient.java +++ b/src/main/java/com/minelittlepony/unicopia/client/UnicopiaClient.java @@ -8,6 +8,7 @@ import com.minelittlepony.common.event.ScreenInitCallback.ButtonList; import com.minelittlepony.unicopia.InteractionManager; import com.minelittlepony.unicopia.Race; import com.minelittlepony.unicopia.Unicopia; +import com.minelittlepony.unicopia.client.gui.UHud; import com.minelittlepony.unicopia.entity.player.PlayerCamera; import com.minelittlepony.unicopia.entity.player.Pony; @@ -62,6 +63,7 @@ public class UnicopiaClient implements ClientModInitializer { private void onTick(MinecraftClient client) { KeyBindingsHandler.INSTANCE.tick(client); + UHud.instance.tick(); } private void onScreenInit(Screen screen, ButtonList buttons) { diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/UHud.java b/src/main/java/com/minelittlepony/unicopia/client/gui/UHud.java index 3fa67233..0300bfa9 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/UHud.java +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/UHud.java @@ -3,8 +3,11 @@ package com.minelittlepony.unicopia.client.gui; import java.util.ArrayList; import java.util.List; +import javax.annotation.Nullable; + import com.minelittlepony.unicopia.ability.AbilityDispatcher; import com.minelittlepony.unicopia.ability.AbilitySlot; +import com.minelittlepony.unicopia.client.KeyBindingsHandler; import com.minelittlepony.unicopia.entity.player.Pony; import com.mojang.blaze3d.systems.RenderSystem; @@ -13,6 +16,7 @@ import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawableHelper; import net.minecraft.client.gui.hud.InGameHud; import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.Text; import net.minecraft.util.Identifier; import net.minecraft.util.Util; @@ -32,6 +36,10 @@ public class UHud extends DrawableHelper { slots.add(new Slot(this, AbilitySlot.TERTIARY, AbilitySlot.TERTIARY, 36, 19, 3, 22, 17, 19).background(80, 105)); }); + @Nullable + private Text message; + private int messageTime; + public void render(InGameHud hud, MatrixStack matrices, float tickDelta) { if (client.player == null || client.player.isSpectator()) { @@ -46,13 +54,17 @@ public class UHud extends DrawableHelper { matrices.push(); matrices.translate(104 + (scaledWidth - 50) / 2, 20 + scaledHeight - 70, 0); + AbilityDispatcher abilities = Pony.of(client.player).getAbilities(); + + if (message != null && messageTime > 0) { + renderMessage(matrices, tickDelta); + } + RenderSystem.enableAlphaTest(); RenderSystem.enableBlend(); client.getTextureManager().bindTexture(HUD_TEXTURE); - AbilityDispatcher abilities = Pony.of(client.player).getAbilities(); - boolean swap = client.options.keySneak.isPressed(); slots.forEach(slot -> slot.renderBackground(matrices, abilities, swap, tickDelta)); @@ -64,8 +76,36 @@ public class UHud extends DrawableHelper { matrices.pop(); } + private void renderMessage(MatrixStack matrices, float tickDelta) { + + float time = messageTime - tickDelta; + int progress = Math.min(255, (int)(time * 255F / 20F)); + + if (progress > 8) { + + int color = 0xFFFFFF; + + int alpha = progress << 24 & -16777216; + + color |= alpha; + + drawCenteredText(matrices, client.textRenderer, message, 25, -15, color); + } + } + + public void setMessage(Text message) { + this.message = message; + this.messageTime = 60; + } + + public void tick() { + if (messageTime > 0) { + messageTime--; + } + } + void renderAbilityIcon(MatrixStack matrices, AbilityDispatcher.Stat stat, int x, int y, int u, int v, int frameWidth, int frameHeight) { - stat.getAbility().ifPresent(ability -> { + stat.getAbility(KeyBindingsHandler.INSTANCE.page).ifPresent(ability -> { client.getTextureManager().bindTexture(ability.getIcon(Pony.of(client.player))); drawTexture(matrices, x, y, 0, 0, frameWidth, frameHeight, u, v); client.getTextureManager().bindTexture(HUD_TEXTURE);