Added paging to the HUD so abilities don't have to be exclusive

This commit is contained in:
Sollace 2020-10-09 14:37:49 +02:00
parent 4d8c41fa8b
commit cef123e162
5 changed files with 133 additions and 19 deletions

View file

@ -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<AbilitySlot, Stat> 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<Ability<?>> getAbility() {
public Optional<Ability<?>> 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;

View file

@ -31,7 +31,7 @@ public class EarthPonyGrowAbility implements Ability<Pos> {
@Override
public boolean canUse(Race race) {
return race == Race.EARTH;
return race.canUseEarth();
}
@Override

View file

@ -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<KeyBinding, AbilitySlot> keys = new HashMap<>();
private final Map<AbilitySlot, KeyBinding> 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<KeyBinding> 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
}
}

View file

@ -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) {

View file

@ -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);