Send quick-time actions to the server so they can work properly

This commit is contained in:
Sollace 2021-12-31 16:17:41 +02:00
parent de1b597ab7
commit c84fda37c4
4 changed files with 41 additions and 18 deletions

View file

@ -28,7 +28,7 @@ public interface Ability<T extends Hit> {
int getCooldownTime(Pony player); int getCooldownTime(Pony player);
/** /**
* Called on the client when an ability is about to be triggered. * Called when an ability is about to be triggered. This event occurs on both the client and server so check {@code Pony#isClient} if you need to know which one you're on.
* <p> * <p>
* Use this method to respond to quick-time events, like short taps or double-taps. * Use this method to respond to quick-time events, like short taps or double-taps.
* <p> * <p>

View file

@ -40,12 +40,20 @@ public class AbilityDispatcher implements Tickable, NbtSerialisable {
Stat stat = getStat(slot); Stat stat = getStat(slot);
if (stat.canSwitchStates()) { if (stat.canSwitchStates()) {
if (pressType == ActivationType.NONE || stat.getAbility(page).filter(ability -> ability.onQuickAction(player, pressType)).isEmpty()) { if (pressType == ActivationType.NONE || stat.getAbility(page).filter(ability -> !triggerQuickAction(ability, pressType)).isEmpty()) {
stat.setActiveAbility(null); stat.setActiveAbility(null);
} }
} }
} }
private boolean triggerQuickAction(Ability<?> ability, ActivationType pressType) {
if (ability.onQuickAction(player, pressType)) {
Channel.CLIENT_PLAYER_ABILITY.send(new MsgPlayerAbility<>(ability, null, pressType));
return true;
}
return false;
}
public Optional<Ability<?>> activate(AbilitySlot slot, long page) { public Optional<Ability<?>> activate(AbilitySlot slot, long page) {
Stat stat = getStat(slot); Stat stat = getStat(slot);
if (stat.canSwitchStates()) { if (stat.canSwitchStates()) {
@ -199,7 +207,7 @@ public class AbilityDispatcher implements Tickable, NbtSerialisable {
T data = ability.tryActivate(player); T data = ability.tryActivate(player);
if (data != null) { if (data != null) {
Channel.CLIENT_PLAYER_ABILITY.send(new MsgPlayerAbility<>(ability, data)); Channel.CLIENT_PLAYER_ABILITY.send(new MsgPlayerAbility<>(ability, data, ActivationType.NONE));
} else { } else {
player.getEntity().playSound(SoundEvents.BLOCK_NOTE_BLOCK_DIDGERIDOO, 1, 1); player.getEntity().playSound(SoundEvents.BLOCK_NOTE_BLOCK_DIDGERIDOO, 1, 1);
setCooldown(0); setCooldown(0);

View file

@ -1,5 +1,7 @@
package com.minelittlepony.unicopia.ability; package com.minelittlepony.unicopia.ability;
import net.minecraft.util.math.MathHelper;
public enum ActivationType { public enum ActivationType {
NONE, NONE,
TAP, TAP,
@ -15,4 +17,8 @@ public enum ActivationType {
public int getTapCount() { public int getTapCount() {
return ordinal(); return ordinal();
} }
}
public static ActivationType of(int id) {
return VALUES[MathHelper.clamp(id, 0, VALUES.length)];
}
}

View file

@ -1,12 +1,16 @@
package com.minelittlepony.unicopia.network; package com.minelittlepony.unicopia.network;
import java.util.Optional;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.ability.Abilities;
import com.minelittlepony.unicopia.ability.Ability; import com.minelittlepony.unicopia.ability.Ability;
import com.minelittlepony.unicopia.ability.ActivationType;
import com.minelittlepony.unicopia.ability.data.Hit; import com.minelittlepony.unicopia.ability.data.Hit;
import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.util.network.Packet; import com.minelittlepony.unicopia.util.network.Packet;
import com.minelittlepony.unicopia.ability.Abilities;
import net.minecraft.util.Identifier;
import net.minecraft.network.PacketByteBuf; import net.minecraft.network.PacketByteBuf;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
@ -14,26 +18,28 @@ import net.minecraft.server.network.ServerPlayerEntity;
* Sent to the server when a player activates an ability. * Sent to the server when a player activates an ability.
*/ */
public class MsgPlayerAbility<T extends Hit> implements Packet<ServerPlayerEntity> { public class MsgPlayerAbility<T extends Hit> implements Packet<ServerPlayerEntity> {
private final Ability<T> power; private final Ability<T> power;
private final Optional<T> data;
private final T data; private final ActivationType type;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
MsgPlayerAbility(PacketByteBuf buffer) { MsgPlayerAbility(PacketByteBuf buffer) {
power = (Ability<T>) Abilities.REGISTRY.get(new Identifier(buffer.readString(32767))); power = (Ability<T>) Abilities.REGISTRY.get(buffer.readIdentifier());
data = power.getSerializer().fromBuffer(buffer); data = buffer.readOptional(power.getSerializer()::fromBuffer);
type = ActivationType.of(buffer.readInt());
} }
public MsgPlayerAbility(Ability<T> power, T data) { public MsgPlayerAbility(Ability<T> power, @Nullable T data, ActivationType type) {
this.power = power; this.power = power;
this.data = data; this.data = Optional.ofNullable(data);
this.type = type;
} }
@Override @Override
public void toBuffer(PacketByteBuf buffer) { public void toBuffer(PacketByteBuf buffer) {
buffer.writeString(Abilities.REGISTRY.getId(power).toString()); buffer.writeIdentifier(Abilities.REGISTRY.getId(power));
data.toBuffer(buffer); buffer.writeOptional(data, (buf, t) -> t.toBuffer(buf));
buffer.writeInt(type.ordinal());
} }
@Override @Override
@ -43,10 +49,13 @@ public class MsgPlayerAbility<T extends Hit> implements Packet<ServerPlayerEntit
return; return;
} }
if (!power.canApply(player, data)) { if (type != ActivationType.NONE) {
Channel.CANCEL_PLAYER_ABILITY.send(sender, new MsgCancelPlayerAbility()); power.onQuickAction(player, type);
} else { } else {
power.apply(player, data); data.filter(data -> power.canApply(player, data)).ifPresentOrElse(
data -> power.apply(player, data),
() -> Channel.CANCEL_PLAYER_ABILITY.send(sender, new MsgCancelPlayerAbility())
);
} }
} }
} }