A little more cleanup to the magic system

This commit is contained in:
Sollace 2021-03-06 11:58:44 +02:00
parent d27de0f690
commit 6d3d8051fe
16 changed files with 73 additions and 55 deletions

View file

@ -111,14 +111,10 @@ public class UnicornCastingAbility implements Ability<Hit> {
TypedActionResult<SpellType<?>> newSpell = getNewSpell(player);
if (newSpell.getResult() != ActionResult.FAIL) {
@Nullable
SpellType<?> spell = newSpell.getValue();
if (!player.getSpellSlot().isPresent() && spell == null) {
spell = SpellType.SHIELD;
}
player.subtractEnergyCost(spell == null ? 2 : 4);
player.setSpell(spell == null ? null : spell.create());
player.subtractEnergyCost(spell.isEmpty() ? 2 : 4);
spell.apply(player);
}
}
}
@ -139,12 +135,12 @@ public class UnicornCastingAbility implements Ability<Hit> {
}
private TypedActionResult<SpellType<?>> getNewSpell(Pony player) {
final SpellType<?> current = player.getSpellSlot().get(true).map(Spell::getType).orElse(null);
final SpellType<?> current = player.getSpellSlot().get(true).map(Spell::getType).orElse(SpellType.empty());
return Streams.stream(player.getMaster().getItemsHand())
.filter(GemstoneItem::isEnchanted)
.map(stack -> GemstoneItem.consumeSpell(stack, player.getMaster(), current, SpellType::mayAttach))
.findFirst()
.orElse(TypedActionResult.<SpellType<?>>pass(null));
.orElse(TypedActionResult.<SpellType<?>>pass(current == SpellType.EMPTY_KEY ? SpellType.SHIELD : SpellType.EMPTY_KEY));
}
@Override

View file

@ -5,8 +5,6 @@ import java.util.UUID;
import com.minelittlepony.unicopia.ability.magic.spell.SpellType;
import com.minelittlepony.unicopia.util.NbtSerialisable;
import net.minecraft.entity.projectile.ProjectileEntity;
/**
* Interface for a magic spells
*/
@ -38,25 +36,17 @@ public interface Spell extends NbtSerialisable, Affine {
boolean isDirty();
/**
* Marks this effect as dirty.
* Applies this spell to the supplied caster.
*/
void setDirty(boolean dirty);
boolean apply(Caster<?> caster);
/**
* Called when first attached to a gem.
* Marks this effect as dirty.
*/
default void onPlaced(Caster<?> caster) {
}
void setDirty();
/**
* Called when a gem is destroyed.
*/
default void onDestroyed(Caster<?> caster) {
setDead();
}
default boolean handleProjectileImpact(ProjectileEntity projectile) {
return false;
}
void onDestroyed(Caster<?> caster);
}

View file

@ -41,7 +41,7 @@ public abstract class AbstractPlacedSpell extends AbstractSpell implements Attac
if (dimension == null) {
dimension = source.getWorld().getRegistryKey().getValue();
setDirty(true);
setDirty();
} else if (!source.getWorld().getRegistryKey().getValue().equals(dimension)) {
return false;
}
@ -55,7 +55,7 @@ public abstract class AbstractPlacedSpell extends AbstractSpell implements Attac
entity.world.spawnEntity(entity);
castEntity.set(entity);
setDirty(true);
setDirty();
}
}

View file

@ -3,6 +3,7 @@ package com.minelittlepony.unicopia.ability.magic.spell;
import java.util.UUID;
import com.minelittlepony.unicopia.Affinity;
import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.Spell;
import net.minecraft.nbt.CompoundTag;
@ -34,6 +35,7 @@ public abstract class AbstractSpell implements Spell {
@Override
public void setDead() {
isDead = true;
setDirty();
}
@Override
@ -47,8 +49,8 @@ public abstract class AbstractSpell implements Spell {
}
@Override
public void setDirty(boolean dirty) {
isDirty = dirty;
public void setDirty() {
isDirty = true;
}
@Override
@ -56,6 +58,17 @@ public abstract class AbstractSpell implements Spell {
return getType().getAffinity();
}
@Override
public boolean apply(Caster<?> caster) {
caster.setSpell(this);
return true;
}
@Override
public void onDestroyed(Caster<?> caster) {
setDead();
}
@Override
public void toNBT(CompoundTag compound) {
compound.putBoolean("dead", isDead);
@ -64,7 +77,7 @@ public abstract class AbstractSpell implements Spell {
@Override
public void fromNBT(CompoundTag compound) {
setDirty(false);
isDirty = false;
if (compound.contains("uuid")) {
uuid = compound.getUuid("uuid");
}

View file

@ -16,6 +16,8 @@ import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.entity.player.PlayerDimensions;
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
import com.minelittlepony.unicopia.particle.UParticles;
import com.minelittlepony.unicopia.projectile.ProjectileImpactListener;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityDimensions;
import net.minecraft.entity.LivingEntity;
@ -25,7 +27,7 @@ import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.projectile.ProjectileEntity;
import net.minecraft.nbt.CompoundTag;
public class DisguiseSpell extends AbstractSpell implements Attached, Suppressable, FlightType.Provider, PlayerDimensions.Provider {
public class DisguiseSpell extends AbstractSpell implements Attached, Suppressable, FlightType.Provider, PlayerDimensions.Provider, ProjectileImpactListener {
private final Disguise disguise = new Disguise();
@ -49,7 +51,7 @@ public class DisguiseSpell extends AbstractSpell implements Attached, Suppressab
@Override
public void onSuppressed(Caster<?> otherSource) {
suppressionCounter = 100;
setDirty(true);
setDirty();
}
@Override
@ -67,12 +69,12 @@ public class DisguiseSpell extends AbstractSpell implements Attached, Suppressab
}
disguise.setAppearance(entity);
setDirty(true);
setDirty();
return this;
}
@Override
public boolean handleProjectileImpact(ProjectileEntity projectile) {
public boolean onProjectileImpact(ProjectileEntity projectile) {
return disguise.getAppearance() == projectile;
}

View file

@ -22,11 +22,6 @@ public class RevealingSpell extends AbstractSpell implements Attached, Thrown {
super(type);
}
@Override
public void onPlaced(Caster<?> source) {
source.getLevel().set(1);
}
@Override
public boolean onThrownTick(MagicProjectileEntity projectile) {
return onBodyTick(projectile);

View file

@ -90,7 +90,7 @@ public class ShieldSpell extends AbstractSpell implements Attached, Thrown {
cost /= 2.725D;
if (!source.subtractEnergyCost(cost)) {
onDestroyed(source);
setDead();
}
}

View file

@ -86,14 +86,14 @@ public class SiphoningSpell extends AbstractPlacedSpell {
if (ticksUpset > 0 || maxHealthGain <= 0) {
if (source.getWorld().random.nextInt(3000) == 0) {
onDestroyed(source);
setDead();
} else {
e.damage(damage, e.getHealth() / 4);
}
if (maxHealthGain <= 0) {
ticksUpset = 100;
}
setDirty(true);
setDirty();
} else {
e.heal((float)Math.min(0.5F * (1 + source.getLevel().get()), maxHealthGain * 0.6));
ParticleUtils.spawnParticle(new FollowingParticleEffect(UParticles.HEALTH_DRAIN, e, 0.2F), e.world, e.getPos(), Vec3d.ZERO);

View file

@ -10,6 +10,7 @@ import javax.annotation.Nullable;
import com.minelittlepony.unicopia.Affinity;
import com.minelittlepony.unicopia.ability.magic.Affine;
import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.Spell;
import net.minecraft.nbt.CompoundTag;
@ -117,11 +118,24 @@ public final class SpellType<T extends Spell> implements Affine, SpellPredicate<
return null;
}
public boolean apply(Caster<?> caster) {
if (isEmpty()) {
caster.setSpell(null);
return false;
}
return create().apply(caster);
}
@Override
public boolean test(@Nullable Spell spell) {
return spell != null && spell.getType() == this;
}
public boolean isEmpty() {
return this == EMPTY_KEY;
}
public static <T extends Spell> SpellType<T> register(Identifier id, Affinity affinity, int color, boolean obtainable, Factory<T> factory) {
SpellType<T> type = new SpellType<>(id, affinity, color, obtainable, factory);
byAffinity(affinity).add(type);
@ -133,6 +147,11 @@ public final class SpellType<T extends Spell> implements Affine, SpellPredicate<
return register(new Identifier("unicopia", name), affinity, color, obtainable, factory);
}
@SuppressWarnings("unchecked")
public static <T extends Spell> SpellType<T> empty() {
return (SpellType<T>)EMPTY_KEY;
}
@SuppressWarnings("unchecked")
public static <T extends Spell> SpellType<T> getKey(Identifier id) {
return (SpellType<T>)(EMPTY_ID.equals(id) ? EMPTY_KEY : REGISTRY.getOrDefault(id, EMPTY_KEY));

View file

@ -2,6 +2,7 @@ package com.minelittlepony.unicopia.command;
import java.util.function.Function;
import com.minelittlepony.unicopia.ability.magic.Spell;
import com.minelittlepony.unicopia.ability.magic.spell.SpellType;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.mojang.brigadier.CommandDispatcher;
@ -79,9 +80,7 @@ public class DisguiseCommand {
static int reveal(ServerCommandSource source, PlayerEntity player) {
Pony iplayer = Pony.of(player);
iplayer.getSpellSlot().get(SpellType.DISGUISE, true).ifPresent(disguise -> {
disguise.onDestroyed(iplayer);
});
iplayer.getSpellSlot().get(SpellType.DISGUISE, true).ifPresent(Spell::setDead);
if (player.getEntityWorld().getGameRules().getBoolean(GameRules.SEND_COMMAND_FEEDBACK)) {
player.sendMessage(new TranslatableText("commands.disguise.removed"), false);

View file

@ -5,6 +5,7 @@ import java.util.Optional;
import javax.annotation.Nullable;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.projectile.ProjectileImpactListener;
import com.minelittlepony.unicopia.util.NbtSerialisable;
import net.minecraft.entity.Entity;
@ -12,7 +13,7 @@ import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.projectile.ProjectileEntity;
import net.minecraft.util.Tickable;
public interface Equine<T extends Entity> extends NbtSerialisable, Tickable {
public interface Equine<T extends Entity> extends NbtSerialisable, Tickable, ProjectileImpactListener {
Race getSpecies();
Physics getPhysics();
@ -44,6 +45,7 @@ public interface Equine<T extends Entity> extends NbtSerialisable, Tickable {
/**
* Event triggered when this entity is hit by a projectile.
*/
@Override
default boolean onProjectileImpact(ProjectileEntity projectile) {
return false;
}

View file

@ -11,6 +11,7 @@ import com.minelittlepony.unicopia.ability.magic.spell.SpellPredicate;
import com.minelittlepony.unicopia.ability.magic.spell.SpellType;
import com.minelittlepony.unicopia.item.UItems;
import com.minelittlepony.unicopia.network.EffectSync;
import com.minelittlepony.unicopia.projectile.ProjectileImpactListener;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.damage.DamageSource;
@ -139,7 +140,9 @@ public abstract class Living<T extends LivingEntity> implements Equine<T>, Caste
@Override
public boolean onProjectileImpact(ProjectileEntity projectile) {
return getSpellSlot().get(true)
.filter(effect -> !effect.isDead() && effect.handleProjectileImpact(projectile))
.filter(effect -> !effect.isDead()
&& effect instanceof ProjectileImpactListener
&& ((ProjectileImpactListener)effect).onProjectileImpact(projectile))
.isPresent();
}

View file

@ -66,7 +66,7 @@ public class SheepBehaviour extends EntityBehaviour<SheepEntity> {
}
} while (dropAmount-- > 0);
}
spell.setDirty(true);
spell.setDirty();
}
}
}

View file

@ -89,6 +89,7 @@ public class EffectSync implements SpellContainer {
private void updateReference(@Nullable Spell effect) {
if (spell.isPresent() && spell.get() != effect) {
spell.get().setDead();
spell.get().onDestroyed(owner);
}
spell = Optional.ofNullable(effect);
}

View file

@ -121,15 +121,6 @@ public class MagicProjectileEntity extends ThrownItemEntity implements Magical,
return effectDelegate;
}
@Override
public void setSpell(Spell effect) {
Caster.super.setSpell(effect);
if (effect != null) {
effect.onPlaced(this);
}
}
public void setThrowDamage(float damage) {
getDataTracker().set(DAMAGE, Math.max(0, damage));
}

View file

@ -0,0 +1,7 @@
package com.minelittlepony.unicopia.projectile;
import net.minecraft.entity.projectile.ProjectileEntity;
public interface ProjectileImpactListener {
boolean onProjectileImpact(ProjectileEntity projectile);
}