Rewrite how abilities are registered and function/remove the json serializing in packets

This commit is contained in:
Sollace 2020-04-25 15:37:17 +02:00
parent 54a4309825
commit b0838e2caf
26 changed files with 269 additions and 386 deletions

View file

@ -1,9 +0,0 @@
package com.minelittlepony.unicopia;
public interface KeyBind {
String getKeyCategory();
String getKeyName();
int getKeyCode();
}

View file

@ -7,7 +7,6 @@ import net.minecraft.resource.ResourceType;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.minelittlepony.unicopia.ability.Abilities;
import com.minelittlepony.unicopia.advancement.BOHDeathCriterion;
import com.minelittlepony.unicopia.block.UBlocks;
import com.minelittlepony.unicopia.command.Commands;
@ -47,7 +46,6 @@ public class Unicopia implements ModInitializer {
UContainers.bootstrap();
UStructures.bootstrap();
URecipes.bootstrap();
Abilities.getInstance().init();
CriterionsRegistry.register(BOHDeathCriterion.INSTANCE);
ResourceManagerHelper.get(ResourceType.SERVER_DATA).registerReloadListener(Pages.instance());

View file

@ -1,65 +1,36 @@
package com.minelittlepony.unicopia.ability;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.lwjgl.glfw.GLFW;
import com.minelittlepony.unicopia.Race;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.MutableRegistry;
import net.minecraft.util.registry.SimpleRegistry;
public final class Abilities {
public interface Abilities {
MutableRegistry<Integer> KEYS_CODES = new SimpleRegistry<>();
MutableRegistry<Ability<?>> REGISTRY = new SimpleRegistry<>();
private static final Abilities INSTANCE = new Abilities();
// unicorn
Ability<?> TELEPORT = register(new UnicornTeleportAbility(), "teleport", GLFW.GLFW_KEY_O);
Ability<?> CAST = register(new UnicornCastingAbility(), "cast", GLFW.GLFW_KEY_P);
public static Abilities getInstance() {
return INSTANCE;
}
// earth
Ability<?> GROW = register(new EarthPonyGrowAbility(), "grow", GLFW.GLFW_KEY_N);
Ability<?> STOMP = register(new EarthPonyStompAbility(), "stomp", GLFW.GLFW_KEY_M);
private final Map<Integer, List<Ability<? extends Ability.IData>>> keyToPowerMap = new HashMap<>();
// pegasus
Ability<?> CARRY = register(new PegasusCarryAbility(), "carry", GLFW.GLFW_KEY_K);
Ability<?> CLOUD = register(new PegasusCloudInteractionAbility(), "cloud", GLFW.GLFW_KEY_J);
private final Map<String, Ability<? extends Ability.IData>> powerNamesMap = new HashMap<>();
// changeling
Ability<?> FEED = register(new ChangelingFeedAbility(), "feed", GLFW.GLFW_KEY_O);
Ability<?> TRAP = register(new ChangelingTrapAbility(), "trap", GLFW.GLFW_KEY_L);
private Abilities() {
}
Ability<?> DISGUISE = register(new ChangelingDisguiseAbility(), "disguise", GLFW.GLFW_KEY_P);
public void init() {
register(new UnicornTeleportAbility());
register(new UnicornCastingAbility());
register(new EarthPonyGrowAbility());
register(new ChangelingFeedAbility());
register(new PegasusCarryAbility());
register(new PegasusCloudInteractionAbility());
register(new ChangelingTrapAbility());
register(new EarthPonyStompAbility());
register(new ChangelingDisguiseAbility());
}
public boolean hasRegisteredPower(int keyCode) {
return keyToPowerMap.containsKey(keyCode);
}
public Optional<Ability<? extends Ability.IData>> getCapablePowerFromKey(int keyCode, Race race) {
return getKeyCodePool(keyCode).stream()
.filter(power -> power.canUse(race))
.findFirst();
}
public Optional<Ability<? extends Ability.IData>> getPowerFromName(String name) {
return Optional.ofNullable(powerNamesMap.get(name));
}
private List<Ability<? extends Ability.IData>> getKeyCodePool(int keyCode) {
return keyToPowerMap.computeIfAbsent(keyCode, ArrayList::new);
}
public void register(Ability<? extends Ability.IData> power) {
getKeyCodePool(power.getKeyCode()).add(power);
powerNamesMap.put(power.getKeyName(), power);
}
public Collection<Ability<? extends Ability.IData>> getValues() {
return powerNamesMap.values();
static <T extends Ability<?>> T register(T power, String name, int keyCode) {
Identifier id = new Identifier("unicopia", name);
KEYS_CODES.add(id, keyCode);
return REGISTRY.add(id, power);
}
}

View file

@ -2,21 +2,13 @@ package com.minelittlepony.unicopia.ability;
import javax.annotation.Nullable;
import com.google.gson.annotations.Expose;
import com.minelittlepony.unicopia.KeyBind;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.ability.data.Hit;
import com.minelittlepony.unicopia.entity.player.Pony;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
public interface Ability<T extends Ability.IData> extends KeyBind {
@Override
default String getKeyCategory() {
return "unicopia.category.name";
}
public interface Ability<T extends Hit> {
/**
* Returns the number of ticks the player must hold the ability key to trigger this ability.
*/
@ -53,7 +45,7 @@ public interface Ability<T extends Ability.IData> extends KeyBind {
@Nullable
T tryActivate(Pony player);
Class<T> getPackageType();
Hit.Serializer<T> getSerializer();
/**
* Called to actually apply the ability.
@ -75,48 +67,4 @@ public interface Ability<T extends Ability.IData> extends KeyBind {
* @param player The current player
*/
void postApply(Pony player);
public interface IData {
}
class Pos implements Ability.IData {
@Expose
public int x;
@Expose
public int y;
@Expose
public int z;
public Pos(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
public Pos(BlockPos pos) {
x = pos.getX();
y = pos.getY();
z = pos.getZ();
}
public BlockPos pos() {
return new BlockPos(x, y, z);
}
}
class Hit implements Ability.IData {
}
class Numeric implements IData {
@Expose
public int type;
public Numeric(int t) {
type = t;
}
}
}

View file

@ -1,18 +1,20 @@
package com.minelittlepony.unicopia.entity.player;
package com.minelittlepony.unicopia.ability;
import java.util.Optional;
import javax.annotation.Nullable;
import com.minelittlepony.unicopia.ability.AbilityReceiver;
import com.minelittlepony.unicopia.ability.Ability;
import com.minelittlepony.unicopia.ability.Abilities;
import com.minelittlepony.unicopia.ability.data.Hit;
import com.minelittlepony.unicopia.entity.Updatable;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.network.MsgPlayerAbility;
import com.minelittlepony.unicopia.network.Channel;
import com.minelittlepony.unicopia.util.NbtSerialisable;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.util.Identifier;
class AbilityDelegate implements AbilityReceiver, Updatable, NbtSerialisable {
public class AbilityDispatcher implements Updatable, NbtSerialisable {
private final Pony player;
@ -31,10 +33,9 @@ class AbilityDelegate implements AbilityReceiver, Updatable, NbtSerialisable {
*/
private boolean triggered;
@Nullable
private Ability<?> activeAbility = null;
private Optional<Ability<?>> activeAbility = Optional.empty();
public AbilityDelegate(Pony player) {
public AbilityDispatcher(Pony player) {
this.player = player;
}
@ -42,53 +43,47 @@ class AbilityDelegate implements AbilityReceiver, Updatable, NbtSerialisable {
* Returns true if the currrent ability can we swapped out.
*/
boolean canSwitchStates() {
return activeAbility == null || (warmup != 0) || (triggered && cooldown == 0);
return !activeAbility.isPresent() || (warmup != 0) || (triggered && cooldown == 0);
}
@Override
public void tryUseAbility(Ability<?> power) {
if (canSwitchStates()) {
setAbility(power);
}
}
@Override
public void tryClearAbility() {
if (canSwitchStates()) {
setAbility(null);
}
}
protected synchronized void setAbility(@Nullable Ability<?> power) {
if (activeAbility != power) {
protected synchronized void setAbility(Ability<?> power) {
if (activeAbility.orElse(null) != power) {
triggered = false;
activeAbility = power;
warmup = power == null ? 0 : power.getWarmupTime(player);
activeAbility = Optional.ofNullable(power);
warmup = activeAbility.map(p -> p.getWarmupTime(player)).orElse(0);
cooldown = 0;
}
}
@Nullable
protected synchronized Ability<?> getUsableAbility() {
if (!(activeAbility == null || (triggered && warmup == 0 && cooldown == 0)) && activeAbility.canUse(player.getSpecies())) {
return activeAbility;
}
return null;
protected synchronized Optional<Ability<?>> getUsableAbility() {
return activeAbility.filter(ability -> {
return (triggered && warmup == 0 && cooldown == 0) && ability.canUse(player.getSpecies());
});
}
@Override
public int getRemainingCooldown() {
return cooldown;
}
@Override
public void onUpdate() {
Ability<?> ability = getUsableAbility();
if (ability == null) {
return;
getUsableAbility().ifPresent(this::activate);
}
private <T extends Hit> void activate(Ability<T> ability) {
if (warmup > 0) {
warmup--;
ability.preApply(player);
@ -110,10 +105,10 @@ class AbilityDelegate implements AbilityReceiver, Updatable, NbtSerialisable {
cooldown = ability.getCooldownTime(player);
if (player.isClientPlayer()) {
Ability.IData data = ability.tryActivate(player);
T data = ability.tryActivate(player);
if (data != null) {
Channel.PLAYER_ABILITY.send(new MsgPlayerAbility(ability, data));
Channel.PLAYER_ABILITY.send(new MsgPlayerAbility<>(ability, data));
} else {
cooldown = 0;
}
@ -130,26 +125,16 @@ class AbilityDelegate implements AbilityReceiver, Updatable, NbtSerialisable {
compound.putBoolean("triggered", triggered);
compound.putInt("warmup", warmup);
compound.putInt("cooldown", cooldown);
Ability<?> ability = getUsableAbility();
if (ability != null) {
compound.putString("activeAbility", ability.getKeyName());
}
getUsableAbility().ifPresent(ability -> {
compound.putString("activeAbility", Abilities.REGISTRY.getId(ability).toString());
});
}
@Override
public void fromNBT(CompoundTag compound) {
activeAbility = null;
triggered = compound.getBoolean("triggered");
warmup = compound.getInt("warmup");
cooldown = compound.getInt("cooldown");
if (compound.contains("activeAbility")) {
Abilities.getInstance()
.getPowerFromName(compound.getString("activeAbility"))
.ifPresent(p -> activeAbility = p);
}
activeAbility = Abilities.REGISTRY.getOrEmpty(new Identifier(compound.getString("activeAbility")));
}
}

View file

@ -1,12 +0,0 @@
package com.minelittlepony.unicopia.ability;
import com.minelittlepony.unicopia.ability.Ability;
public interface AbilityReceiver {
void tryUseAbility(Ability<?> power);
void tryClearAbility();
int getRemainingCooldown();
}

View file

@ -3,9 +3,8 @@ package com.minelittlepony.unicopia.ability;
import javax.annotation.Nullable;
import org.lwjgl.glfw.GLFW;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.ability.data.Hit;
import com.minelittlepony.unicopia.entity.InAnimate;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.magic.spell.DisguiseSpell;
@ -29,20 +28,10 @@ import net.minecraft.util.math.BlockPos;
*/
public class ChangelingDisguiseAbility extends ChangelingFeedAbility {
@Override
public String getKeyName() {
return "unicopia.power.disguise";
}
@Override
public int getKeyCode() {
return GLFW.GLFW_KEY_P;
}
@Nullable
@Override
public Hit tryActivate(Pony player) {
return new Hit();
return Hit.INSTANCE;
}
@Override

View file

@ -5,9 +5,8 @@ import java.util.stream.Collectors;
import javax.annotation.Nullable;
import org.lwjgl.glfw.GLFW;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.ability.data.Hit;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.particles.ParticleUtils;
import com.minelittlepony.unicopia.particles.UParticles;
@ -30,17 +29,7 @@ import net.minecraft.particle.ParticleTypes;
/**
* Changeling ability to restore health from mobs
*/
public class ChangelingFeedAbility implements Ability<Ability.Hit> {
@Override
public String getKeyName() {
return "unicopia.power.feed";
}
@Override
public int getKeyCode() {
return GLFW.GLFW_KEY_O;
}
public class ChangelingFeedAbility implements Ability<Hit> {
@Override
public int getWarmupTime(Pony player) {
@ -62,7 +51,7 @@ public class ChangelingFeedAbility implements Ability<Ability.Hit> {
public Hit tryActivate(Pony player) {
if (canFeed(player)) {
if (!getTargets(player).isEmpty()) {
return new Hit();
return Hit.INSTANCE;
}
}
@ -84,8 +73,8 @@ public class ChangelingFeedAbility implements Ability<Ability.Hit> {
}
@Override
public Class<Hit> getPackageType() {
return Hit.class;
public Hit.Serializer<Hit> getSerializer() {
return Hit.SERIALIZER;
}
protected List<LivingEntity> getTargets(Pony player) {

View file

@ -2,23 +2,12 @@ package com.minelittlepony.unicopia.ability;
import javax.annotation.Nullable;
import org.lwjgl.glfw.GLFW;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.ability.data.Hit;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.magic.spell.ChangelingTrapSpell;
public class ChangelingTrapAbility implements Ability<Ability.Hit> {
@Override
public String getKeyName() {
return "engulf";
}
@Override
public int getKeyCode() {
return GLFW.GLFW_KEY_L;
}
public class ChangelingTrapAbility implements Ability<Hit> {
@Override
public int getWarmupTime(Pony player) {
@ -38,12 +27,12 @@ public class ChangelingTrapAbility implements Ability<Ability.Hit> {
@Nullable
@Override
public Hit tryActivate(Pony player) {
return new Hit();
return Hit.INSTANCE;
}
@Override
public Class<Hit> getPackageType() {
return Hit.class;
public Hit.Serializer<Hit> getSerializer() {
return Hit.SERIALIZER;
}
@Override

View file

@ -1,8 +1,8 @@
package com.minelittlepony.unicopia.ability;
import org.lwjgl.glfw.GLFW;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.ability.data.Hit;
import com.minelittlepony.unicopia.ability.data.Pos;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.particles.MagicParticleEffect;
import com.minelittlepony.unicopia.util.VecHelper;
@ -20,17 +20,7 @@ import net.minecraft.world.World;
/**
* Earth Pony ability to grow crops
*/
public class EarthPonyGrowAbility implements Ability<Ability.Pos> {
@Override
public String getKeyName() {
return "unicopia.power.grow";
}
@Override
public int getKeyCode() {
return GLFW.GLFW_KEY_N;
}
public class EarthPonyGrowAbility implements Ability<Pos> {
@Override
public int getWarmupTime(Pony player) {
@ -59,8 +49,8 @@ public class EarthPonyGrowAbility implements Ability<Ability.Pos> {
}
@Override
public Class<Pos> getPackageType() {
return Pos.class;
public Hit.Serializer<Pos> getSerializer() {
return Pos.SERIALIZER;
}
@Override

View file

@ -2,13 +2,12 @@ package com.minelittlepony.unicopia.ability;
import java.util.ArrayList;
import java.util.List;
import org.lwjgl.glfw.GLFW;
import com.google.common.collect.Lists;
import com.google.gson.annotations.Expose;
import com.minelittlepony.unicopia.AwaitTickQueue;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.TreeType;
import com.minelittlepony.unicopia.ability.data.Hit;
import com.minelittlepony.unicopia.ability.data.Multi;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.util.MagicalDamageSource;
import com.minelittlepony.unicopia.util.PosHelper;
@ -41,7 +40,7 @@ import net.minecraft.world.World;
/**
* Earth Pony stomping ability
*/
public class EarthPonyStompAbility implements Ability<EarthPonyStompAbility.Data> {
public class EarthPonyStompAbility implements Ability<Multi> {
private final double rad = 4;
@ -50,16 +49,6 @@ public class EarthPonyStompAbility implements Ability<EarthPonyStompAbility.Data
rad, rad, rad
);
@Override
public String getKeyName() {
return "unicopia.power.earth";
}
@Override
public int getKeyCode() {
return GLFW.GLFW_KEY_M;
}
@Override
public int getWarmupTime(Pony player) {
return 3;
@ -76,7 +65,7 @@ public class EarthPonyStompAbility implements Ability<EarthPonyStompAbility.Data
}
@Override
public EarthPonyStompAbility.Data tryActivate(Pony player) {
public Multi tryActivate(Pony player) {
HitResult mop = VecHelper.getObjectMouseOver(player.getOwner(), 6, 1);
if (mop instanceof BlockHitResult && mop.getType() == HitResult.Type.BLOCK) {
@ -86,21 +75,21 @@ public class EarthPonyStompAbility implements Ability<EarthPonyStompAbility.Data
if (state.getBlock() instanceof LogBlock) {
pos = getBaseOfTree(player.getWorld(), state, pos);
if (measureTree(player.getWorld(), state, pos) > 0) {
return new Data(pos.getX(), pos.getY(), pos.getZ(), 1);
return new Multi(pos.getX(), pos.getY(), pos.getZ(), 1);
}
}
}
if (!player.getOwner().onGround && !player.getOwner().abilities.flying) {
player.getOwner().addVelocity(0, -6, 0);
return new Data(0, 0, 0, 0);
return new Multi(0, 0, 0, 0);
}
return null;
}
@Override
public Class<EarthPonyStompAbility.Data> getPackageType() {
return EarthPonyStompAbility.Data.class;
public Hit.Serializer<Multi> getSerializer() {
return Multi.SERIALIZER;
}
public static BlockPos getSolidBlockBelow(BlockPos pos, World w) {
@ -116,7 +105,7 @@ public class EarthPonyStompAbility implements Ability<EarthPonyStompAbility.Data
}
@Override
public void apply(Pony iplayer, Data data) {
public void apply(Pony iplayer, Multi data) {
PlayerEntity player = iplayer.getOwner();
@ -452,14 +441,4 @@ public class EarthPonyStompAbility implements Ability<EarthPonyStompAbility.Data
private boolean variantEquals(BlockState one, BlockState two) {
return TreeType.get(one).equals(TreeType.get(two));
}
protected static class Data extends Ability.Pos {
@Expose
public int hitType;
public Data(int x, int y, int z, int hit) {
super(x, y, z);
hitType = hit;
}
}
}

View file

@ -1,8 +1,7 @@
package com.minelittlepony.unicopia.ability;
import org.lwjgl.glfw.GLFW;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.ability.data.Hit;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.util.VecHelper;
@ -16,17 +15,7 @@ import net.minecraft.world.World;
/**
* Pegasi ability to pick up and carry other players
*/
public class PegasusCarryAbility implements Ability<Ability.Hit> {
@Override
public String getKeyName() {
return "unicopia.power.carry";
}
@Override
public int getKeyCode() {
return GLFW.GLFW_KEY_K;
}
public class PegasusCarryAbility implements Ability<Hit> {
@Override
public int getWarmupTime(Pony player) {
@ -45,7 +34,7 @@ public class PegasusCarryAbility implements Ability<Ability.Hit> {
@Override
public Hit tryActivate(Pony player) {
return new Hit();
return Hit.INSTANCE;
}
protected LivingEntity findRider(PlayerEntity player, World w) {
@ -61,8 +50,8 @@ public class PegasusCarryAbility implements Ability<Ability.Hit> {
}
@Override
public Class<Hit> getPackageType() {
return Hit.class;
public Hit.Serializer<Hit> getSerializer() {
return Hit.SERIALIZER;
}
@Override

View file

@ -2,9 +2,9 @@ package com.minelittlepony.unicopia.ability;
import java.util.Optional;
import org.lwjgl.glfw.GLFW;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.ability.data.Hit;
import com.minelittlepony.unicopia.ability.data.Numeric;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.particles.MagicParticleEffect;
import com.minelittlepony.unicopia.particles.UParticles;
@ -12,17 +12,7 @@ import com.minelittlepony.unicopia.util.VecHelper;
import net.minecraft.entity.Entity;
public class PegasusCloudInteractionAbility implements Ability<Ability.Numeric> {
@Override
public String getKeyName() {
return "unicopia.power.cloud";
}
@Override
public int getKeyCode() {
return GLFW.GLFW_KEY_J;
}
public class PegasusCloudInteractionAbility implements Ability<Numeric> {
@Override
public int getWarmupTime(Pony player) {
@ -50,8 +40,8 @@ public class PegasusCloudInteractionAbility implements Ability<Ability.Numeric>
}
@Override
public Class<Numeric> getPackageType() {
return Numeric.class;
public Hit.Serializer<Numeric> getSerializer() {
return Numeric.SERIALIZER;
}
@Override

View file

@ -1,8 +1,7 @@
package com.minelittlepony.unicopia.ability;
import org.lwjgl.glfw.GLFW;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.ability.data.Hit;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.magic.spell.ShieldSpell;
import com.minelittlepony.unicopia.particles.MagicParticleEffect;
@ -11,17 +10,7 @@ import com.minelittlepony.unicopia.particles.MagicParticleEffect;
* A magic casting ability for unicorns.
* (only shields for now)
*/
public class UnicornCastingAbility implements Ability<Ability.Hit> {
@Override
public String getKeyName() {
return "unicopia.power.magic";
}
@Override
public int getKeyCode() {
return GLFW.GLFW_KEY_P;
}
public class UnicornCastingAbility implements Ability<Hit> {
@Override
public int getWarmupTime(Pony player) {
@ -40,12 +29,12 @@ public class UnicornCastingAbility implements Ability<Ability.Hit> {
@Override
public Hit tryActivate(Pony player) {
return new Hit();
return Hit.INSTANCE;
}
@Override
public Class<Hit> getPackageType() {
return Hit.class;
public Hit.Serializer<Hit> getSerializer() {
return Hit.SERIALIZER;
}
@Override

View file

@ -1,8 +1,8 @@
package com.minelittlepony.unicopia.ability;
import org.lwjgl.glfw.GLFW;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.ability.data.Hit;
import com.minelittlepony.unicopia.ability.data.Pos;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.particles.MagicParticleEffect;
import com.minelittlepony.unicopia.util.VecHelper;
@ -27,18 +27,7 @@ import net.minecraft.world.World;
/**
* Unicorn teleport ability
*/
public class UnicornTeleportAbility implements Ability<Ability.Pos> {
@Override
public String getKeyName() {
return "unicopia.power.teleport";
}
@Override
public int getKeyCode() {
return GLFW.GLFW_KEY_O;
}
public class UnicornTeleportAbility implements Ability<Pos> {
@Override
public int getWarmupTime(Pony player) {
return 20;
@ -107,11 +96,9 @@ public class UnicornTeleportAbility implements Ability<Ability.Pos> {
return new Pos(pos.getX(), pos.getY(), pos.getZ());
}
@Override
public Class<Pos> getPackageType() {
return Pos.class;
public Hit.Serializer<Pos> getSerializer() {
return Pos.SERIALIZER;
}
@Override

View file

@ -0,0 +1,21 @@
package com.minelittlepony.unicopia.ability.data;
import net.minecraft.util.PacketByteBuf;
public class Hit {
public static final Hit INSTANCE = new Hit();
public static final Serializer<Hit> SERIALIZER = buf -> INSTANCE;
protected Hit() {
}
public void toBuffer(PacketByteBuf buf) {
}
public interface Serializer<T extends Hit> {
T fromBuffer(PacketByteBuf buf);
}
}

View file

@ -0,0 +1,25 @@
package com.minelittlepony.unicopia.ability.data;
import net.minecraft.util.PacketByteBuf;
public class Multi extends Pos {
public static final Serializer<Multi> SERIALIZER = Multi::new;
public int hitType;
Multi(PacketByteBuf buf) {
super(buf);
hitType = buf.readInt();
}
@Override
public void toBuffer(PacketByteBuf buf) {
super.toBuffer(buf);
buf.writeInt(hitType);
}
public Multi(int x, int y, int z, int hit) {
super(x, y, z);
hitType = hit;
}
}

View file

@ -0,0 +1,25 @@
package com.minelittlepony.unicopia.ability.data;
import com.google.gson.annotations.Expose;
import net.minecraft.util.PacketByteBuf;
public class Numeric extends Hit {
public static final Serializer<Numeric> SERIALIZER = Numeric::new;
@Expose
public int type;
Numeric(PacketByteBuf buf) {
type = buf.readInt();
}
@Override
public void toBuffer(PacketByteBuf buf) {
buf.writeInt(type);
}
public Numeric(int t) {
type = t;
}
}

View file

@ -0,0 +1,42 @@
package com.minelittlepony.unicopia.ability.data;
import net.minecraft.util.PacketByteBuf;
import net.minecraft.util.math.BlockPos;
public class Pos extends Hit {
public static final Serializer<Pos> SERIALIZER = Pos::new;
public int x;
public int y;
public int z;
Pos(PacketByteBuf buf) {
x = buf.readInt();
y = buf.readInt();
z = buf.readInt();
}
@Override
public void toBuffer(PacketByteBuf buf) {
buf.writeInt(x);
buf.writeInt(y);
buf.writeInt(z);
}
public Pos(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
public Pos(BlockPos pos) {
x = pos.getX();
y = pos.getY();
z = pos.getZ();
}
public BlockPos pos() {
return new BlockPos(x, y, z);
}
}

View file

@ -1,10 +1,16 @@
package com.minelittlepony.unicopia.client;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.minelittlepony.unicopia.KeyBind;
import com.minelittlepony.unicopia.ability.Abilities;
import com.minelittlepony.unicopia.ability.Ability;
import com.minelittlepony.unicopia.ability.data.Hit;
import com.minelittlepony.unicopia.entity.player.Pony;
import net.fabricmc.fabric.api.client.keybinding.FabricKeyBinding;
@ -15,23 +21,31 @@ import net.minecraft.client.util.InputUtil;
import net.minecraft.util.Identifier;
class KeyBindingsHandler {
private final MinecraftClient client = MinecraftClient.getInstance();
private final String KEY_CATEGORY = "unicopia.category.name";
private final Map<KeyBinding, List<Ability<? extends Hit>>> keyPools = new HashMap<>();
private final Set<KeyBinding> bindings = new HashSet<>();
private final Set<KeyBinding> removed = new HashSet<>();
private final Set<KeyBinding> pressed = new HashSet<>();
public void addKeybind(KeyBind p) {
KeyBindingRegistry.INSTANCE.addCategory(p.getKeyCategory());
private Collection<Ability<?>> getKeyCodePool(KeyBinding keyCode) {
return keyPools.computeIfAbsent(keyCode, i -> new ArrayList<>());
}
FabricKeyBinding b = FabricKeyBinding.Builder.create(new Identifier("unicopia", p.getKeyName()), InputUtil.Type.KEYSYM, p.getKeyCode(), p.getKeyCategory()).build();
public void addKeybind(Ability<?> p) {
KeyBindingRegistry.INSTANCE.addCategory(KEY_CATEGORY);
Identifier id = Abilities.REGISTRY.getId(p);
int code = Abilities.KEYS_CODES.get(id);
FabricKeyBinding b = FabricKeyBinding.Builder.create(id, InputUtil.Type.KEYSYM, code, KEY_CATEGORY).build();
KeyBindingRegistry.INSTANCE.register(b);
getKeyCodePool(b).add(p);
bindings.add(b);
}
public void onKeyInput() {
public void tick(MinecraftClient client) {
if (client.currentScreen != null
|| client.player == null) {
return;
@ -42,22 +56,15 @@ class KeyBindingsHandler {
if (i.isPressed()) {
if (pressed.add(i)) {
if (!Abilities.getInstance().hasRegisteredPower(i.getDefaultKeyCode().getKeyCode())) {
removed.add(i);
System.out.println("Error: Keybinding(" + i.getLocalizedName() + ") does not have a registered pony power. Keybinding will be removed from event.");
} else {
Abilities.getInstance()
.getCapablePowerFromKey(i.getDefaultKeyCode().getKeyCode(), iplayer.getSpecies())
getKeyCodePool(i)
.stream()
.filter(power -> power.canUse(iplayer.getSpecies()))
.findFirst()
.ifPresent(iplayer.getAbilities()::tryUseAbility);
}
}
} else if (pressed.remove(i)) {
iplayer.getAbilities().tryClearAbility();
}
}
bindings.removeAll(removed);
pressed.removeAll(removed);
removed.clear();
}
}

View file

@ -45,7 +45,7 @@ public class UnicopiaClient implements ClientModInitializer {
URenderers.bootstrap();
ClientTickCallback.EVENT.register(this::tick);
ClientReadyCallback.EVENT.register(client -> Abilities.getInstance().getValues().forEach(keyboard::addKeybind));
ClientReadyCallback.EVENT.register(client -> Abilities.REGISTRY.stream().forEach(keyboard::addKeybind));
DefaultTexturesRegistry.getDefaultTextures().add(new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX, SpellbookResultSlot.EMPTY_GEM_SLOT));
@ -74,7 +74,7 @@ public class UnicopiaClient implements ClientModInitializer {
}
}
keyboard.onKeyInput();
keyboard.tick(client);
}
private static int getLeavesColor(BlockState state, @Nullable BlockRenderView world, @Nullable BlockPos pos, int tint) {

View file

@ -4,7 +4,7 @@ import javax.annotation.Nullable;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.UTags;
import com.minelittlepony.unicopia.ability.AbilityReceiver;
import com.minelittlepony.unicopia.ability.AbilityDispatcher;
import com.minelittlepony.unicopia.enchanting.PageOwner;
import com.minelittlepony.unicopia.entity.FlightControl;
import com.minelittlepony.unicopia.entity.Trap;
@ -54,7 +54,7 @@ public class PlayerImpl implements Pony {
private final PlayerPageStats pageStates = new PlayerPageStats();
private final AbilityDelegate powers = new AbilityDelegate(this);
private final AbilityDispatcher powers = new AbilityDispatcher(this);
private final GravityDelegate gravity = new GravityDelegate(this);
@ -183,7 +183,7 @@ public class PlayerImpl implements Pony {
}
@Override
public AbilityReceiver getAbilities() {
public AbilityDispatcher getAbilities() {
return powers;
}

View file

@ -3,7 +3,7 @@ package com.minelittlepony.unicopia.entity.player;
import javax.annotation.Nullable;
import com.minelittlepony.unicopia.InteractionManager;
import com.minelittlepony.unicopia.ability.AbilityReceiver;
import com.minelittlepony.unicopia.ability.AbilityDispatcher;
import com.minelittlepony.unicopia.enchanting.PageOwner;
import com.minelittlepony.unicopia.entity.FlightControl;
import com.minelittlepony.unicopia.entity.Ponylike;
@ -30,7 +30,7 @@ public interface Pony extends Caster<PlayerEntity>, RaceContainer<PlayerEntity>,
/**
* Gets the player's magical abilities delegate responsible for all spell casting and persisting/updating.
*/
AbilityReceiver getAbilities();
AbilityDispatcher getAbilities();
/**
* Gets the gravity delegate responsible for updating flight states

View file

@ -12,7 +12,7 @@ import net.minecraft.util.PacketByteBuf;
public interface Channel {
SPacketType<MsgPlayerAbility> PLAYER_ABILITY = clientToServer(new Identifier("unicopia", "player_ability"), MsgPlayerAbility::new);
SPacketType<MsgPlayerAbility<?>> PLAYER_ABILITY = clientToServer(new Identifier("unicopia", "player_ability"), MsgPlayerAbility::new);
SPacketType<MsgRequestCapabilities> REQUEST_CAPABILITIES = clientToServer(new Identifier("unicopia", "request_capabilities"), MsgRequestCapabilities::new);
CPacketType<MsgPlayerCapabilities> PLAYER_CAPABILITIES = serverToClient(new Identifier("unicopia", "player_capabilities"), MsgPlayerCapabilities::new);

View file

@ -1,53 +1,44 @@
package com.minelittlepony.unicopia.network;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.minelittlepony.unicopia.ability.Ability;
import com.minelittlepony.unicopia.ability.data.Hit;
import com.minelittlepony.unicopia.ability.Abilities;
import com.minelittlepony.unicopia.entity.player.Pony;
import net.fabricmc.fabric.api.network.PacketContext;
import net.minecraft.util.Identifier;
import net.minecraft.util.PacketByteBuf;
public class MsgPlayerAbility implements Channel.Packet {
public class MsgPlayerAbility<T extends Hit> implements Channel.Packet {
private static final Gson gson = new GsonBuilder()
.excludeFieldsWithoutExposeAnnotation()
.create();
private final Ability<T> power;
private final String powerIdentifier;
private final T data;
private final String abilityJson;
MsgPlayerAbility(Ability<?> power, Ability.IData data) {
powerIdentifier = power.getKeyName();
abilityJson = gson.toJson(data, power.getPackageType());
@SuppressWarnings("unchecked")
MsgPlayerAbility(PacketByteBuf buffer) {
power = (Ability<T>) Abilities.REGISTRY.get(new Identifier(buffer.readString()));
data = power.getSerializer().fromBuffer(buffer);
}
public MsgPlayerAbility(PacketByteBuf buffer) {
powerIdentifier = buffer.readString();
abilityJson = buffer.readString();
public MsgPlayerAbility(Ability<T> power, T data) {
this.power = power;
this.data = data;
}
private <T extends Ability.IData> void apply(Ability<T> power, PacketContext context) {
@Override
public void toBuffer(PacketByteBuf buffer) {
buffer.writeString(Abilities.REGISTRY.getId(power).toString());
data.toBuffer(buffer);
}
@Override
public void handle(PacketContext context) {
Pony player = Pony.of(context.getPlayer());
if (player == null) {
return;
}
T data = gson.fromJson(abilityJson, power.getPackageType());
power.apply(player, data);
}
@Override
public void toBuffer(PacketByteBuf buffer) {
buffer.writeString(powerIdentifier);
buffer.writeString(abilityJson);
}
@Override
public void handle(PacketContext context) {
Abilities.getInstance().getPowerFromName(powerIdentifier).ifPresent(power -> apply(power, context));
}
}