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

View file

@ -1,65 +1,36 @@
package com.minelittlepony.unicopia.ability; package com.minelittlepony.unicopia.ability;
import java.util.ArrayList; import org.lwjgl.glfw.GLFW;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
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() { // earth
return INSTANCE; 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() { static <T extends Ability<?>> T register(T power, String name, int keyCode) {
register(new UnicornTeleportAbility()); Identifier id = new Identifier("unicopia", name);
register(new UnicornCastingAbility()); KEYS_CODES.add(id, keyCode);
register(new EarthPonyGrowAbility()); return REGISTRY.add(id, power);
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();
} }
} }

View file

@ -2,21 +2,13 @@ package com.minelittlepony.unicopia.ability;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import com.google.gson.annotations.Expose;
import com.minelittlepony.unicopia.KeyBind;
import com.minelittlepony.unicopia.Race; import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.ability.data.Hit;
import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.entity.player.Pony;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
public interface Ability<T extends Ability.IData> extends KeyBind { public interface Ability<T extends Hit> {
@Override
default String getKeyCategory() {
return "unicopia.category.name";
}
/** /**
* Returns the number of ticks the player must hold the ability key to trigger this ability. * 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 @Nullable
T tryActivate(Pony player); T tryActivate(Pony player);
Class<T> getPackageType(); Hit.Serializer<T> getSerializer();
/** /**
* Called to actually apply the ability. * Called to actually apply the ability.
@ -75,48 +67,4 @@ public interface Ability<T extends Ability.IData> extends KeyBind {
* @param player The current player * @param player The current player
*/ */
void postApply(Pony 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 javax.annotation.Nullable;
import com.minelittlepony.unicopia.ability.AbilityReceiver; import com.minelittlepony.unicopia.ability.data.Hit;
import com.minelittlepony.unicopia.ability.Ability;
import com.minelittlepony.unicopia.ability.Abilities;
import com.minelittlepony.unicopia.entity.Updatable; import com.minelittlepony.unicopia.entity.Updatable;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.network.MsgPlayerAbility; import com.minelittlepony.unicopia.network.MsgPlayerAbility;
import com.minelittlepony.unicopia.network.Channel; import com.minelittlepony.unicopia.network.Channel;
import com.minelittlepony.unicopia.util.NbtSerialisable; import com.minelittlepony.unicopia.util.NbtSerialisable;
import net.minecraft.nbt.CompoundTag; 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; private final Pony player;
@ -31,10 +33,9 @@ class AbilityDelegate implements AbilityReceiver, Updatable, NbtSerialisable {
*/ */
private boolean triggered; private boolean triggered;
@Nullable private Optional<Ability<?>> activeAbility = Optional.empty();
private Ability<?> activeAbility = null;
public AbilityDelegate(Pony player) { public AbilityDispatcher(Pony player) {
this.player = player; this.player = player;
} }
@ -42,53 +43,47 @@ class AbilityDelegate implements AbilityReceiver, Updatable, NbtSerialisable {
* Returns true if the currrent ability can we swapped out. * Returns true if the currrent ability can we swapped out.
*/ */
boolean canSwitchStates() { boolean canSwitchStates() {
return activeAbility == null || (warmup != 0) || (triggered && cooldown == 0); return !activeAbility.isPresent() || (warmup != 0) || (triggered && cooldown == 0);
} }
@Override
public void tryUseAbility(Ability<?> power) { public void tryUseAbility(Ability<?> power) {
if (canSwitchStates()) { if (canSwitchStates()) {
setAbility(power); setAbility(power);
} }
} }
@Override
public void tryClearAbility() { public void tryClearAbility() {
if (canSwitchStates()) { if (canSwitchStates()) {
setAbility(null); setAbility(null);
} }
} }
protected synchronized void setAbility(@Nullable Ability<?> power) { protected synchronized void setAbility(Ability<?> power) {
if (activeAbility != power) { if (activeAbility.orElse(null) != power) {
triggered = false; triggered = false;
activeAbility = power; activeAbility = Optional.ofNullable(power);
warmup = power == null ? 0 : power.getWarmupTime(player); warmup = activeAbility.map(p -> p.getWarmupTime(player)).orElse(0);
cooldown = 0; cooldown = 0;
} }
} }
@Nullable @Nullable
protected synchronized Ability<?> getUsableAbility() { protected synchronized Optional<Ability<?>> getUsableAbility() {
if (!(activeAbility == null || (triggered && warmup == 0 && cooldown == 0)) && activeAbility.canUse(player.getSpecies())) { return activeAbility.filter(ability -> {
return activeAbility; return (triggered && warmup == 0 && cooldown == 0) && ability.canUse(player.getSpecies());
} });
return null;
} }
@Override
public int getRemainingCooldown() { public int getRemainingCooldown() {
return cooldown; return cooldown;
} }
@Override @Override
public void onUpdate() { public void onUpdate() {
Ability<?> ability = getUsableAbility(); getUsableAbility().ifPresent(this::activate);
if (ability == null) {
return;
} }
private <T extends Hit> void activate(Ability<T> ability) {
if (warmup > 0) { if (warmup > 0) {
warmup--; warmup--;
ability.preApply(player); ability.preApply(player);
@ -110,10 +105,10 @@ class AbilityDelegate implements AbilityReceiver, Updatable, NbtSerialisable {
cooldown = ability.getCooldownTime(player); cooldown = ability.getCooldownTime(player);
if (player.isClientPlayer()) { if (player.isClientPlayer()) {
Ability.IData data = ability.tryActivate(player); T data = ability.tryActivate(player);
if (data != null) { if (data != null) {
Channel.PLAYER_ABILITY.send(new MsgPlayerAbility(ability, data)); Channel.PLAYER_ABILITY.send(new MsgPlayerAbility<>(ability, data));
} else { } else {
cooldown = 0; cooldown = 0;
} }
@ -130,26 +125,16 @@ class AbilityDelegate implements AbilityReceiver, Updatable, NbtSerialisable {
compound.putBoolean("triggered", triggered); compound.putBoolean("triggered", triggered);
compound.putInt("warmup", warmup); compound.putInt("warmup", warmup);
compound.putInt("cooldown", cooldown); compound.putInt("cooldown", cooldown);
getUsableAbility().ifPresent(ability -> {
Ability<?> ability = getUsableAbility(); compound.putString("activeAbility", Abilities.REGISTRY.getId(ability).toString());
});
if (ability != null) {
compound.putString("activeAbility", ability.getKeyName());
}
} }
@Override @Override
public void fromNBT(CompoundTag compound) { public void fromNBT(CompoundTag compound) {
activeAbility = null;
triggered = compound.getBoolean("triggered"); triggered = compound.getBoolean("triggered");
warmup = compound.getInt("warmup"); warmup = compound.getInt("warmup");
cooldown = compound.getInt("cooldown"); cooldown = compound.getInt("cooldown");
activeAbility = Abilities.REGISTRY.getOrEmpty(new Identifier(compound.getString("activeAbility")));
if (compound.contains("activeAbility")) {
Abilities.getInstance()
.getPowerFromName(compound.getString("activeAbility"))
.ifPresent(p -> activeAbility = p);
}
} }
} }

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

View file

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

View file

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

View file

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

View file

@ -2,13 +2,12 @@ package com.minelittlepony.unicopia.ability;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.lwjgl.glfw.GLFW;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.gson.annotations.Expose;
import com.minelittlepony.unicopia.AwaitTickQueue; import com.minelittlepony.unicopia.AwaitTickQueue;
import com.minelittlepony.unicopia.Race; import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.TreeType; 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.entity.player.Pony;
import com.minelittlepony.unicopia.util.MagicalDamageSource; import com.minelittlepony.unicopia.util.MagicalDamageSource;
import com.minelittlepony.unicopia.util.PosHelper; import com.minelittlepony.unicopia.util.PosHelper;
@ -41,7 +40,7 @@ import net.minecraft.world.World;
/** /**
* Earth Pony stomping ability * Earth Pony stomping ability
*/ */
public class EarthPonyStompAbility implements Ability<EarthPonyStompAbility.Data> { public class EarthPonyStompAbility implements Ability<Multi> {
private final double rad = 4; private final double rad = 4;
@ -50,16 +49,6 @@ public class EarthPonyStompAbility implements Ability<EarthPonyStompAbility.Data
rad, rad, rad rad, rad, rad
); );
@Override
public String getKeyName() {
return "unicopia.power.earth";
}
@Override
public int getKeyCode() {
return GLFW.GLFW_KEY_M;
}
@Override @Override
public int getWarmupTime(Pony player) { public int getWarmupTime(Pony player) {
return 3; return 3;
@ -76,7 +65,7 @@ public class EarthPonyStompAbility implements Ability<EarthPonyStompAbility.Data
} }
@Override @Override
public EarthPonyStompAbility.Data tryActivate(Pony player) { public Multi tryActivate(Pony player) {
HitResult mop = VecHelper.getObjectMouseOver(player.getOwner(), 6, 1); HitResult mop = VecHelper.getObjectMouseOver(player.getOwner(), 6, 1);
if (mop instanceof BlockHitResult && mop.getType() == HitResult.Type.BLOCK) { 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) { if (state.getBlock() instanceof LogBlock) {
pos = getBaseOfTree(player.getWorld(), state, pos); pos = getBaseOfTree(player.getWorld(), state, pos);
if (measureTree(player.getWorld(), state, pos) > 0) { 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) { if (!player.getOwner().onGround && !player.getOwner().abilities.flying) {
player.getOwner().addVelocity(0, -6, 0); player.getOwner().addVelocity(0, -6, 0);
return new Data(0, 0, 0, 0); return new Multi(0, 0, 0, 0);
} }
return null; return null;
} }
@Override @Override
public Class<EarthPonyStompAbility.Data> getPackageType() { public Hit.Serializer<Multi> getSerializer() {
return EarthPonyStompAbility.Data.class; return Multi.SERIALIZER;
} }
public static BlockPos getSolidBlockBelow(BlockPos pos, World w) { public static BlockPos getSolidBlockBelow(BlockPos pos, World w) {
@ -116,7 +105,7 @@ public class EarthPonyStompAbility implements Ability<EarthPonyStompAbility.Data
} }
@Override @Override
public void apply(Pony iplayer, Data data) { public void apply(Pony iplayer, Multi data) {
PlayerEntity player = iplayer.getOwner(); PlayerEntity player = iplayer.getOwner();
@ -452,14 +441,4 @@ public class EarthPonyStompAbility implements Ability<EarthPonyStompAbility.Data
private boolean variantEquals(BlockState one, BlockState two) { private boolean variantEquals(BlockState one, BlockState two) {
return TreeType.get(one).equals(TreeType.get(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; package com.minelittlepony.unicopia.ability;
import org.lwjgl.glfw.GLFW;
import com.minelittlepony.unicopia.Race; import com.minelittlepony.unicopia.Race;
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.VecHelper; import com.minelittlepony.unicopia.util.VecHelper;
@ -16,17 +15,7 @@ import net.minecraft.world.World;
/** /**
* Pegasi ability to pick up and carry other players * Pegasi ability to pick up and carry other players
*/ */
public class PegasusCarryAbility implements Ability<Ability.Hit> { public class PegasusCarryAbility implements Ability<Hit> {
@Override
public String getKeyName() {
return "unicopia.power.carry";
}
@Override
public int getKeyCode() {
return GLFW.GLFW_KEY_K;
}
@Override @Override
public int getWarmupTime(Pony player) { public int getWarmupTime(Pony player) {
@ -45,7 +34,7 @@ public class PegasusCarryAbility implements Ability<Ability.Hit> {
@Override @Override
public Hit tryActivate(Pony player) { public Hit tryActivate(Pony player) {
return new Hit(); return Hit.INSTANCE;
} }
protected LivingEntity findRider(PlayerEntity player, World w) { protected LivingEntity findRider(PlayerEntity player, World w) {
@ -61,8 +50,8 @@ public class PegasusCarryAbility implements Ability<Ability.Hit> {
} }
@Override @Override
public Class<Hit> getPackageType() { public Hit.Serializer<Hit> getSerializer() {
return Hit.class; return Hit.SERIALIZER;
} }
@Override @Override

View file

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

View file

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

View file

@ -1,8 +1,8 @@
package com.minelittlepony.unicopia.ability; package com.minelittlepony.unicopia.ability;
import org.lwjgl.glfw.GLFW;
import com.minelittlepony.unicopia.Race; 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.entity.player.Pony;
import com.minelittlepony.unicopia.particles.MagicParticleEffect; import com.minelittlepony.unicopia.particles.MagicParticleEffect;
import com.minelittlepony.unicopia.util.VecHelper; import com.minelittlepony.unicopia.util.VecHelper;
@ -27,18 +27,7 @@ import net.minecraft.world.World;
/** /**
* Unicorn teleport ability * Unicorn teleport ability
*/ */
public class UnicornTeleportAbility implements Ability<Ability.Pos> { public class UnicornTeleportAbility implements Ability<Pos> {
@Override
public String getKeyName() {
return "unicopia.power.teleport";
}
@Override
public int getKeyCode() {
return GLFW.GLFW_KEY_O;
}
@Override @Override
public int getWarmupTime(Pony player) { public int getWarmupTime(Pony player) {
return 20; return 20;
@ -107,11 +96,9 @@ public class UnicornTeleportAbility implements Ability<Ability.Pos> {
return new Pos(pos.getX(), pos.getY(), pos.getZ()); return new Pos(pos.getX(), pos.getY(), pos.getZ());
} }
@Override @Override
public Class<Pos> getPackageType() { public Hit.Serializer<Pos> getSerializer() {
return Pos.class; return Pos.SERIALIZER;
} }
@Override @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; package com.minelittlepony.unicopia.client;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import com.minelittlepony.unicopia.KeyBind;
import com.minelittlepony.unicopia.ability.Abilities; 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 com.minelittlepony.unicopia.entity.player.Pony;
import net.fabricmc.fabric.api.client.keybinding.FabricKeyBinding; import net.fabricmc.fabric.api.client.keybinding.FabricKeyBinding;
@ -15,23 +21,31 @@ import net.minecraft.client.util.InputUtil;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
class KeyBindingsHandler { 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> bindings = new HashSet<>();
private final Set<KeyBinding> removed = new HashSet<>();
private final Set<KeyBinding> pressed = new HashSet<>(); private final Set<KeyBinding> pressed = new HashSet<>();
public void addKeybind(KeyBind p) { private Collection<Ability<?>> getKeyCodePool(KeyBinding keyCode) {
KeyBindingRegistry.INSTANCE.addCategory(p.getKeyCategory()); 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); KeyBindingRegistry.INSTANCE.register(b);
getKeyCodePool(b).add(p);
bindings.add(b); bindings.add(b);
} }
public void onKeyInput() { public void tick(MinecraftClient client) {
if (client.currentScreen != null if (client.currentScreen != null
|| client.player == null) { || client.player == null) {
return; return;
@ -42,22 +56,15 @@ class KeyBindingsHandler {
if (i.isPressed()) { if (i.isPressed()) {
if (pressed.add(i)) { if (pressed.add(i)) {
if (!Abilities.getInstance().hasRegisteredPower(i.getDefaultKeyCode().getKeyCode())) { getKeyCodePool(i)
removed.add(i); .stream()
System.out.println("Error: Keybinding(" + i.getLocalizedName() + ") does not have a registered pony power. Keybinding will be removed from event."); .filter(power -> power.canUse(iplayer.getSpecies()))
} else { .findFirst()
Abilities.getInstance()
.getCapablePowerFromKey(i.getDefaultKeyCode().getKeyCode(), iplayer.getSpecies())
.ifPresent(iplayer.getAbilities()::tryUseAbility); .ifPresent(iplayer.getAbilities()::tryUseAbility);
} }
}
} else if (pressed.remove(i)) { } else if (pressed.remove(i)) {
iplayer.getAbilities().tryClearAbility(); iplayer.getAbilities().tryClearAbility();
} }
} }
bindings.removeAll(removed);
pressed.removeAll(removed);
removed.clear();
} }
} }

View file

@ -45,7 +45,7 @@ public class UnicopiaClient implements ClientModInitializer {
URenderers.bootstrap(); URenderers.bootstrap();
ClientTickCallback.EVENT.register(this::tick); 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)); 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) { 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.Race;
import com.minelittlepony.unicopia.UTags; 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.enchanting.PageOwner;
import com.minelittlepony.unicopia.entity.FlightControl; import com.minelittlepony.unicopia.entity.FlightControl;
import com.minelittlepony.unicopia.entity.Trap; import com.minelittlepony.unicopia.entity.Trap;
@ -54,7 +54,7 @@ public class PlayerImpl implements Pony {
private final PlayerPageStats pageStates = new PlayerPageStats(); 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); private final GravityDelegate gravity = new GravityDelegate(this);
@ -183,7 +183,7 @@ public class PlayerImpl implements Pony {
} }
@Override @Override
public AbilityReceiver getAbilities() { public AbilityDispatcher getAbilities() {
return powers; return powers;
} }

View file

@ -3,7 +3,7 @@ package com.minelittlepony.unicopia.entity.player;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import com.minelittlepony.unicopia.InteractionManager; 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.enchanting.PageOwner;
import com.minelittlepony.unicopia.entity.FlightControl; import com.minelittlepony.unicopia.entity.FlightControl;
import com.minelittlepony.unicopia.entity.Ponylike; 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. * 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 * Gets the gravity delegate responsible for updating flight states

View file

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

View file

@ -1,53 +1,44 @@
package com.minelittlepony.unicopia.network; 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.Ability;
import com.minelittlepony.unicopia.ability.data.Hit;
import com.minelittlepony.unicopia.ability.Abilities; import com.minelittlepony.unicopia.ability.Abilities;
import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.entity.player.Pony;
import net.fabricmc.fabric.api.network.PacketContext; import net.fabricmc.fabric.api.network.PacketContext;
import net.minecraft.util.Identifier;
import net.minecraft.util.PacketByteBuf; 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() private final Ability<T> power;
.excludeFieldsWithoutExposeAnnotation()
.create();
private final String powerIdentifier; private final T data;
private final String abilityJson; @SuppressWarnings("unchecked")
MsgPlayerAbility(PacketByteBuf buffer) {
MsgPlayerAbility(Ability<?> power, Ability.IData data) { power = (Ability<T>) Abilities.REGISTRY.get(new Identifier(buffer.readString()));
powerIdentifier = power.getKeyName(); data = power.getSerializer().fromBuffer(buffer);
abilityJson = gson.toJson(data, power.getPackageType());
} }
public MsgPlayerAbility(PacketByteBuf buffer) { public MsgPlayerAbility(Ability<T> power, T data) {
powerIdentifier = buffer.readString(); this.power = power;
abilityJson = buffer.readString(); 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()); Pony player = Pony.of(context.getPlayer());
if (player == null) { if (player == null) {
return; return;
} }
T data = gson.fromJson(abilityJson, power.getPackageType());
power.apply(player, data); 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));
}
} }